summaryrefslogtreecommitdiff
path: root/sysdeps/mips
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/mips')
-rw-r--r--sysdeps/mips/Implies3
-rw-r--r--sysdeps/mips/Makefile78
-rw-r--r--sysdeps/mips/__longjmp.c84
-rw-r--r--sysdeps/mips/abort-instr.h6
-rw-r--r--sysdeps/mips/add_n.S121
-rw-r--r--sysdeps/mips/addmul_1.S128
-rw-r--r--sysdeps/mips/backtrace.c1
-rw-r--r--sysdeps/mips/bits/atomic.h503
-rw-r--r--sysdeps/mips/bits/dlfcn.h64
-rw-r--r--sysdeps/mips/bits/endian.h15
-rw-r--r--sysdeps/mips/bits/fenv.h85
-rw-r--r--sysdeps/mips/bits/ipctypes.h31
-rw-r--r--sysdeps/mips/bits/link.h117
-rw-r--r--sysdeps/mips/bits/linkmap.h6
-rw-r--r--sysdeps/mips/bits/mathdef.h43
-rw-r--r--sysdeps/mips/bits/nan.h67
-rw-r--r--sysdeps/mips/bits/setjmp.h73
-rw-r--r--sysdeps/mips/bits/wordsize.h23
-rw-r--r--sysdeps/mips/bsd-_setjmp.S44
-rw-r--r--sysdeps/mips/bsd-setjmp.S43
-rw-r--r--sysdeps/mips/configure163
-rw-r--r--sysdeps/mips/configure.ac15
-rw-r--r--sysdeps/mips/dl-dtprocnum.h21
-rw-r--r--sysdeps/mips/dl-machine-reject-phdr.h326
-rw-r--r--sysdeps/mips/dl-machine.h936
-rw-r--r--sysdeps/mips/dl-procinfo.c63
-rw-r--r--sysdeps/mips/dl-procinfo.h67
-rw-r--r--sysdeps/mips/dl-tls.h48
-rw-r--r--sysdeps/mips/dl-trampoline.c513
-rw-r--r--sysdeps/mips/fpregdef.h23
-rw-r--r--sysdeps/mips/fpu/e_sqrt.c38
-rw-r--r--sysdeps/mips/fpu/e_sqrtf.c38
-rw-r--r--sysdeps/mips/fpu/fclrexcpt.c47
-rw-r--r--sysdeps/mips/fpu/fedisblxcpt.c40
-rw-r--r--sysdeps/mips/fpu/feenablxcpt.c40
-rw-r--r--sysdeps/mips/fpu/fegetenv.c33
-rw-r--r--sysdeps/mips/fpu/fegetexcept.c33
-rw-r--r--sysdeps/mips/fpu/fegetround.c35
-rw-r--r--sysdeps/mips/fpu/feholdexcpt.c41
-rw-r--r--sysdeps/mips/fpu/fenv_libc.h31
-rw-r--r--sysdeps/mips/fpu/fesetenv.c44
-rw-r--r--sysdeps/mips/fpu/fesetround.c46
-rw-r--r--sysdeps/mips/fpu/feupdateenv.c45
-rw-r--r--sysdeps/mips/fpu/fgetexcptflg.c39
-rw-r--r--sysdeps/mips/fpu/fraiseexcpt.c48
-rw-r--r--sysdeps/mips/fpu/fsetexcptflg.c42
-rw-r--r--sysdeps/mips/fpu/ftestexcept.c33
-rw-r--r--sysdeps/mips/fpu_control.h133
-rw-r--r--sysdeps/mips/gccframe.h21
-rw-r--r--sysdeps/mips/ieee754/ieee754.h323
-rw-r--r--sysdeps/mips/ieee754/s_fma.c5
-rw-r--r--sysdeps/mips/ieee754/s_fmaf.c5
-rw-r--r--sysdeps/mips/ieee754/s_fmal.c7
-rw-r--r--sysdeps/mips/include/sys/asm.h53
-rw-r--r--sysdeps/mips/jmpbuf-unwind.h47
-rw-r--r--sysdeps/mips/ldsodefs.h149
-rw-r--r--sysdeps/mips/libc-tls.c32
-rw-r--r--sysdeps/mips/lshift.S97
-rw-r--r--sysdeps/mips/machine-gmon.h146
-rw-r--r--sysdeps/mips/math-tests.h38
-rw-r--r--sysdeps/mips/math_private.h252
-rw-r--r--sysdeps/mips/memcpy.S827
-rw-r--r--sysdeps/mips/memset.S426
-rw-r--r--sysdeps/mips/memusage.h20
-rw-r--r--sysdeps/mips/mips32/Implies3
-rw-r--r--sysdeps/mips/mips32/Makefile3
-rw-r--r--sysdeps/mips/mips32/crti.S93
-rw-r--r--sysdeps/mips/mips32/crtn.S57
-rw-r--r--sysdeps/mips/mips32/fpu/Makefile3
-rw-r--r--sysdeps/mips/mips32/fpu/Versions5
-rw-r--r--sysdeps/mips/mips32/fpu/e_sqrt.c1
-rw-r--r--sysdeps/mips/mips32/fpu/e_sqrtf.c1
-rw-r--r--sysdeps/mips/mips32/fpu/fpucw-helpers.c34
-rw-r--r--sysdeps/mips/mips32/libm-test-ulps1676
-rw-r--r--sysdeps/mips/mips32/mips16/add_n.c1
-rw-r--r--sysdeps/mips/mips32/mips16/addmul_1.c1
-rw-r--r--sysdeps/mips/mips32/mips16/fpu/Makefile5
-rw-r--r--sysdeps/mips/mips32/mips16/lshift.c1
-rw-r--r--sysdeps/mips/mips32/mips16/mul_1.c1
-rw-r--r--sysdeps/mips/mips32/mips16/rshift.c1
-rw-r--r--sysdeps/mips/mips32/mips16/sub_n.c1
-rw-r--r--sysdeps/mips/mips32/mips16/submul_1.c1
-rw-r--r--sysdeps/mips/mips32/sfp-machine.h68
-rw-r--r--sysdeps/mips/mips64/Implies4
-rw-r--r--sysdeps/mips/mips64/Makefile3
-rw-r--r--sysdeps/mips/mips64/Versions7
-rw-r--r--sysdeps/mips/mips64/__longjmp.c97
-rw-r--r--sysdeps/mips/mips64/add_n.S125
-rw-r--r--sysdeps/mips/mips64/addmul_1.S131
-rw-r--r--sysdeps/mips/mips64/bsd-_setjmp.S47
-rw-r--r--sysdeps/mips/mips64/bsd-setjmp.S46
-rw-r--r--sysdeps/mips/mips64/e_sqrtl.c39
-rw-r--r--sysdeps/mips/mips64/gmp-mparam.h30
-rw-r--r--sysdeps/mips/mips64/libm-test-ulps2242
-rw-r--r--sysdeps/mips/mips64/lshift.S100
-rw-r--r--sysdeps/mips/mips64/mul_1.S120
-rw-r--r--sysdeps/mips/mips64/n32/Implies5
-rw-r--r--sysdeps/mips/mips64/n32/Makefile6
-rw-r--r--sysdeps/mips/mips64/n32/_itoa.h4
-rw-r--r--sysdeps/mips/mips64/n32/crti.S93
-rw-r--r--sysdeps/mips/mips64/n32/crtn.S59
-rw-r--r--sysdeps/mips/mips64/n32/fpu/e_sqrt.c1
-rw-r--r--sysdeps/mips/mips64/n32/fpu/e_sqrtf.c1
-rw-r--r--sysdeps/mips/mips64/n64/Implies5
-rw-r--r--sysdeps/mips/mips64/n64/Makefile6
-rw-r--r--sysdeps/mips/mips64/n64/crti.S93
-rw-r--r--sysdeps/mips/mips64/n64/crtn.S59
-rw-r--r--sysdeps/mips/mips64/n64/fpu/e_sqrt.c1
-rw-r--r--sysdeps/mips/mips64/n64/fpu/e_sqrtf.c1
-rw-r--r--sysdeps/mips/mips64/rshift.S97
-rw-r--r--sysdeps/mips/mips64/setjmp.S44
-rw-r--r--sysdeps/mips/mips64/setjmp_aux.c76
-rw-r--r--sysdeps/mips/mips64/sfp-machine.h96
-rw-r--r--sysdeps/mips/mips64/sub_n.S125
-rw-r--r--sysdeps/mips/mips64/submul_1.S132
-rw-r--r--sysdeps/mips/mul_1.S117
-rw-r--r--sysdeps/mips/nptl/Makefile24
-rw-r--r--sysdeps/mips/nptl/bits/pthreadtypes.h237
-rw-r--r--sysdeps/mips/nptl/bits/semaphore.h36
-rw-r--r--sysdeps/mips/nptl/nptl-sysdep.S2
-rw-r--r--sysdeps/mips/nptl/pthread_spin_lock.c23
-rw-r--r--sysdeps/mips/nptl/pthreaddef.h32
-rw-r--r--sysdeps/mips/nptl/tcb-offsets.sym11
-rw-r--r--sysdeps/mips/nptl/tls.h185
-rw-r--r--sysdeps/mips/preconfigure29
-rw-r--r--sysdeps/mips/regdef.h25
-rw-r--r--sysdeps/mips/rshift.S94
-rw-r--r--sysdeps/mips/setjmp.S46
-rw-r--r--sysdeps/mips/setjmp_aux.c63
-rw-r--r--sysdeps/mips/sgidefs.h76
-rw-r--r--sysdeps/mips/sotruss-lib.c117
-rw-r--r--sysdeps/mips/stackinfo.h33
-rw-r--r--sysdeps/mips/start.S185
-rw-r--r--sysdeps/mips/strcmp.S249
-rw-r--r--sysdeps/mips/sub_n.S121
-rw-r--r--sysdeps/mips/submul_1.S128
-rw-r--r--sysdeps/mips/sys/asm.h498
-rw-r--r--sysdeps/mips/sys/fpregdef.h118
-rw-r--r--sysdeps/mips/sys/regdef.h81
-rw-r--r--sysdeps/mips/sys/tas.h69
-rw-r--r--sysdeps/mips/sys/ucontext.h158
-rw-r--r--sysdeps/mips/tininess.h1
-rw-r--r--sysdeps/mips/tls-macros.h123
-rw-r--r--sysdeps/mips/tst-abi-fp32mod.c22
-rw-r--r--sysdeps/mips/tst-abi-fp64amod.c22
-rw-r--r--sysdeps/mips/tst-abi-fp64mod.c22
-rw-r--r--sysdeps/mips/tst-abi-fpxxmod.c22
-rw-r--r--sysdeps/mips/tst-abi-fpxxomod.c22
-rw-r--r--sysdeps/mips/tst-abi-interlink.c844
-rw-r--r--sysdeps/mips/tst-audit.h39
-rw-r--r--sysdeps/mips/tst-mode-switch-1.c123
-rw-r--r--sysdeps/mips/tst-mode-switch-2.c163
-rw-r--r--sysdeps/mips/tst-mode-switch-3.c90
153 files changed, 17065 insertions, 0 deletions
diff --git a/sysdeps/mips/Implies b/sysdeps/mips/Implies
new file mode 100644
index 0000000000..8c18cb3034
--- /dev/null
+++ b/sysdeps/mips/Implies
@@ -0,0 +1,3 @@
+# MIPS uses IEEE 754 floating point.
+ieee754/flt-32
+ieee754/dbl-64
diff --git a/sysdeps/mips/Makefile b/sysdeps/mips/Makefile
new file mode 100644
index 0000000000..463b121758
--- /dev/null
+++ b/sysdeps/mips/Makefile
@@ -0,0 +1,78 @@
+ifeq ($(subdir),misc)
+sysdep_headers += regdef.h fpregdef.h sys/regdef.h sys/fpregdef.h \
+ sys/asm.h sgidefs.h
+endif
+
+ifeq ($(subdir),setjmp)
+sysdep_routines += setjmp_aux
+endif
+
+ifeq ($(subdir),rt)
+librt-sysdep_routines += rt-sysdep
+endif
+
+ifeq ($(subdir),debug)
+CFLAGS-backtrace.c += -funwind-tables
+endif
+
+ifeq ($(subdir),csu)
+CPPFLAGS-crti.S += $(pic-ccflag)
+CPPFLAGS-crtn.S += $(pic-ccflag)
+endif
+
+ifeq ($(subdir),nptl)
+CPPFLAGS-pt-crti.S += $(pic-ccflag)
+CPPFLAGS-crtn.S += $(pic-ccflag)
+endif
+
+ASFLAGS-.os += $(pic-ccflag)
+
+ifeq ($(subdir),elf)
+ifneq ($(o32-fpabi),)
+tests += tst-abi-interlink
+
+fpabi-modules-names =
+fpabi_list =
+ifneq (,$(filter $(o32-fpabi),32 xx xxo))
+fpabi-modules-names += tst-abi-fp32mod
+CFLAGS-tst-abi-fp32mod.c += -mfp32
+endif
+ifneq (,$(filter $(o32-fpabi),xx))
+fpabi-modules-names += tst-abi-fpxxmod
+CFLAGS-tst-abi-fpxxmod.c += -mfpxx -mno-odd-spreg
+endif
+ifneq (,$(filter $(o32-fpabi),xx xxo))
+fpabi-modules-names += tst-abi-fpxxomod
+CFLAGS-tst-abi-fpxxomod.c += -mfpxx -modd-spreg
+endif
+ifneq (,$(filter $(o32-fpabi),xx 64a))
+fpabi-modules-names += tst-abi-fp64amod
+CFLAGS-tst-abi-fp64amod.c += -mfp64 -mno-odd-spreg
+endif
+ifneq (,$(filter $(o32-fpabi),xx xxo 64a 64))
+fpabi-modules-names += tst-abi-fp64mod
+CFLAGS-tst-abi-fp64mod.c += -mfp64 -modd-spreg
+endif
+modules-names += $(fpabi-modules-names)
+
+comma:=,
+empty:=
+space:=$(empty) $(empty)
+fpabi_list=$(subst $(space),$(comma),$(patsubst tst-abi-%mod,o_%,\
+ $(fpabi-modules-names)))
+CPPFLAGS-tst-abi-interlink.c += -DFPABI_LIST=$(fpabi_list)
+CPPFLAGS-tst-abi-interlink.c += -DFPABI_COUNT=$(words $(fpabi-modules-names))
+CPPFLAGS-tst-abi-interlink.c += -DFPABI_NATIVE=o_fp$(o32-fpabi)
+$(objpfx)tst-abi-interlink: $(libdl)
+$(objpfx)tst-abi-interlink.out: $(patsubst %,$(objpfx)%.so,\
+ $(fpabi-modules-names))
+endif
+
+ifeq ($(mips-mode-switch),yes)
+ifeq ($(o32-fpabi),xx)
+tests += tst-mode-switch-1 tst-mode-switch-2 tst-mode-switch-3
+$(objpfx)tst-mode-switch-1: $(shared-thread-library)
+$(objpfx)tst-mode-switch-2: $(shared-thread-library)
+endif
+endif
+endif
diff --git a/sysdeps/mips/__longjmp.c b/sysdeps/mips/__longjmp.c
new file mode 100644
index 0000000000..8acb109cdf
--- /dev/null
+++ b/sysdeps/mips/__longjmp.c
@@ -0,0 +1,84 @@
+/* Copyright (C) 1992-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Brendan Kehoe (brendan@zen.org).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <setjmp.h>
+#include <stdlib.h>
+
+#ifndef __GNUC__
+ #error This file uses GNU C extensions; you must compile with GCC.
+#endif
+
+static void __attribute__ ((nomips16))
+____longjmp (__jmp_buf env_arg, int val_arg)
+{
+ /* gcc 1.39.19 miscompiled the longjmp routine (as it did setjmp before
+ the hack around it); force it to use $a1 for the longjmp value.
+ Without this it saves $a1 in a register which gets clobbered
+ along the way. */
+ register struct __jmp_buf_internal_tag *env asm ("a0");
+ register int val asm ("a1");
+#ifdef CHECK_SP
+ register long sp asm ("$29");
+ CHECK_SP (env[0].__sp, sp, long);
+#endif
+
+#ifdef __mips_hard_float
+ /* Pull back the floating point callee-saved registers. */
+ asm volatile ("l.d $f20, %0" : : "m" (env[0].__fpregs[0]));
+ asm volatile ("l.d $f22, %0" : : "m" (env[0].__fpregs[1]));
+ asm volatile ("l.d $f24, %0" : : "m" (env[0].__fpregs[2]));
+ asm volatile ("l.d $f26, %0" : : "m" (env[0].__fpregs[3]));
+ asm volatile ("l.d $f28, %0" : : "m" (env[0].__fpregs[4]));
+ asm volatile ("l.d $f30, %0" : : "m" (env[0].__fpregs[5]));
+#endif
+
+ /* Get the GP. */
+ asm volatile ("lw $gp, %0" : : "m" (env[0].__gp));
+
+ /* Get the callee-saved registers. */
+ asm volatile ("lw $16, %0" : : "m" (env[0].__regs[0]));
+ asm volatile ("lw $17, %0" : : "m" (env[0].__regs[1]));
+ asm volatile ("lw $18, %0" : : "m" (env[0].__regs[2]));
+ asm volatile ("lw $19, %0" : : "m" (env[0].__regs[3]));
+ asm volatile ("lw $20, %0" : : "m" (env[0].__regs[4]));
+ asm volatile ("lw $21, %0" : : "m" (env[0].__regs[5]));
+ asm volatile ("lw $22, %0" : : "m" (env[0].__regs[6]));
+ asm volatile ("lw $23, %0" : : "m" (env[0].__regs[7]));
+
+ /* Get the PC. */
+ asm volatile ("lw $25, %0" : : "m" (env[0].__pc));
+
+ /* Restore the stack pointer and the FP. They have to be restored
+ last and in a single asm as gcc, depending on options used, may
+ use either of them to access env. */
+ asm volatile ("lw $29, %0\n\t"
+ "lw $30, %1\n\t" : : "m" (env[0].__sp), "m" (env[0].__fp));
+
+/* Give setjmp 1 if given a 0, or what they gave us if non-zero. */
+ if (val == 0)
+ asm volatile ("li $2, 1");
+ else
+ asm volatile ("move $2, %0" : : "r" (val));
+
+ asm volatile ("jr $25");
+
+ /* Avoid `volatile function does return' warnings. */
+ for (;;);
+}
+
+strong_alias (____longjmp, __longjmp);
diff --git a/sysdeps/mips/abort-instr.h b/sysdeps/mips/abort-instr.h
new file mode 100644
index 0000000000..7ccae5736b
--- /dev/null
+++ b/sysdeps/mips/abort-instr.h
@@ -0,0 +1,6 @@
+/* An instruction which should crash any program is a breakpoint. */
+#ifdef __mips16
+# define ABORT_INSTRUCTION asm ("break 63")
+#else
+# define ABORT_INSTRUCTION asm ("break 255")
+#endif
diff --git a/sysdeps/mips/add_n.S b/sysdeps/mips/add_n.S
new file mode 100644
index 0000000000..e9f26f2c5a
--- /dev/null
+++ b/sysdeps/mips/add_n.S
@@ -0,0 +1,121 @@
+/* MIPS2 __mpn_add_n -- Add two limb vectors of the same length > 0 and
+store sum in a third limb vector.
+
+Copyright (C) 1995-2015 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the GNU MP Library. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+/* INPUT PARAMETERS
+ res_ptr $4
+ s1_ptr $5
+ s2_ptr $6
+ size $7
+*/
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (__mpn_add_n)
+ .set noreorder
+#ifdef __PIC__
+ .cpload t9
+#endif
+ .set nomacro
+
+ lw $10,0($5)
+ lw $11,0($6)
+
+ addiu $7,$7,-1
+ and $9,$7,4-1 /* number of limbs in first loop */
+ beq $9,$0,L(L0) /* if multiple of 4 limbs, skip first loop */
+ move $2,$0
+
+ subu $7,$7,$9
+
+L(Loop0): addiu $9,$9,-1
+ lw $12,4($5)
+ addu $11,$11,$2
+ lw $13,4($6)
+ sltu $8,$11,$2
+ addu $11,$10,$11
+ sltu $2,$11,$10
+ sw $11,0($4)
+ or $2,$2,$8
+
+ addiu $5,$5,4
+ addiu $6,$6,4
+ move $10,$12
+ move $11,$13
+ bne $9,$0,L(Loop0)
+ addiu $4,$4,4
+
+L(L0): beq $7,$0,L(end)
+ nop
+
+L(Loop): addiu $7,$7,-4
+
+ lw $12,4($5)
+ addu $11,$11,$2
+ lw $13,4($6)
+ sltu $8,$11,$2
+ addu $11,$10,$11
+ sltu $2,$11,$10
+ sw $11,0($4)
+ or $2,$2,$8
+
+ lw $10,8($5)
+ addu $13,$13,$2
+ lw $11,8($6)
+ sltu $8,$13,$2
+ addu $13,$12,$13
+ sltu $2,$13,$12
+ sw $13,4($4)
+ or $2,$2,$8
+
+ lw $12,12($5)
+ addu $11,$11,$2
+ lw $13,12($6)
+ sltu $8,$11,$2
+ addu $11,$10,$11
+ sltu $2,$11,$10
+ sw $11,8($4)
+ or $2,$2,$8
+
+ lw $10,16($5)
+ addu $13,$13,$2
+ lw $11,16($6)
+ sltu $8,$13,$2
+ addu $13,$12,$13
+ sltu $2,$13,$12
+ sw $13,12($4)
+ or $2,$2,$8
+
+ addiu $5,$5,16
+ addiu $6,$6,16
+
+ bne $7,$0,L(Loop)
+ addiu $4,$4,16
+
+L(end): addu $11,$11,$2
+ sltu $8,$11,$2
+ addu $11,$10,$11
+ sltu $2,$11,$10
+ sw $11,0($4)
+ j $31
+ or $2,$2,$8
+END (__mpn_add_n)
diff --git a/sysdeps/mips/addmul_1.S b/sysdeps/mips/addmul_1.S
new file mode 100644
index 0000000000..2162685458
--- /dev/null
+++ b/sysdeps/mips/addmul_1.S
@@ -0,0 +1,128 @@
+/* MIPS __mpn_addmul_1 -- Multiply a limb vector with a single limb and
+add the product to a second limb vector.
+
+Copyright (C) 1995-2015 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the GNU MP Library. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+/* INPUT PARAMETERS
+ res_ptr $4
+ s1_ptr $5
+ size $6
+ s2_limb $7
+*/
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (__mpn_addmul_1)
+ .set noreorder
+#ifdef __PIC__
+ .cpload t9
+#endif
+ .set nomacro
+
+ /* warm up phase 0 */
+ lw $8,0($5)
+
+ /* warm up phase 1 */
+ addiu $5,$5,4
+#if __mips_isa_rev < 6
+ multu $8,$7
+#else
+ mulu $11,$8,$7
+ muhu $12,$8,$7
+#endif
+
+ addiu $6,$6,-1
+ beq $6,$0,L(LC0)
+ move $2,$0 /* zero cy2 */
+
+ addiu $6,$6,-1
+ beq $6,$0,L(LC1)
+ lw $8,0($5) /* load new s1 limb as early as possible */
+
+L(Loop): lw $10,0($4)
+#if __mips_isa_rev < 6
+ mflo $3
+ mfhi $9
+#else
+ move $3,$11
+ move $9,$12
+#endif
+ addiu $5,$5,4
+ addu $3,$3,$2 /* add old carry limb to low product limb */
+#if __mips_isa_rev < 6
+ multu $8,$7
+#else
+ mulu $11,$8,$7
+ muhu $12,$8,$7
+#endif
+ lw $8,0($5) /* load new s1 limb as early as possible */
+ addiu $6,$6,-1 /* decrement loop counter */
+ sltu $2,$3,$2 /* carry from previous addition -> $2 */
+ addu $3,$10,$3
+ sltu $10,$3,$10
+ addu $2,$2,$10
+ sw $3,0($4)
+ addiu $4,$4,4
+ bne $6,$0,L(Loop) /* should be "bnel" */
+ addu $2,$9,$2 /* add high product limb and carry from addition */
+
+ /* cool down phase 1 */
+L(LC1): lw $10,0($4)
+#if __mips_isa_rev < 6
+ mflo $3
+ mfhi $9
+#else
+ move $3,$11
+ move $9,$12
+#endif
+ addu $3,$3,$2
+ sltu $2,$3,$2
+#if __mips_isa_rev < 6
+ multu $8,$7
+#else
+ mulu $11,$8,$7
+ muhu $12,$8,$7
+#endif
+ addu $3,$10,$3
+ sltu $10,$3,$10
+ addu $2,$2,$10
+ sw $3,0($4)
+ addiu $4,$4,4
+ addu $2,$9,$2 /* add high product limb and carry from addition */
+
+ /* cool down phase 0 */
+L(LC0): lw $10,0($4)
+#if __mips_isa_rev < 6
+ mflo $3
+ mfhi $9
+#else
+ move $3,$11
+ move $9,$12
+#endif
+ addu $3,$3,$2
+ sltu $2,$3,$2
+ addu $3,$10,$3
+ sltu $10,$3,$10
+ addu $2,$2,$10
+ sw $3,0($4)
+ j $31
+ addu $2,$9,$2 /* add high product limb and carry from addition */
+ END (__mpn_addmul_1)
diff --git a/sysdeps/mips/backtrace.c b/sysdeps/mips/backtrace.c
new file mode 100644
index 0000000000..27ce597b39
--- /dev/null
+++ b/sysdeps/mips/backtrace.c
@@ -0,0 +1 @@
+#include <sysdeps/x86_64/backtrace.c>
diff --git a/sysdeps/mips/bits/atomic.h b/sysdeps/mips/bits/atomic.h
new file mode 100644
index 0000000000..a39188160b
--- /dev/null
+++ b/sysdeps/mips/bits/atomic.h
@@ -0,0 +1,503 @@
+/* Low-level functions for atomic operations. Mips version.
+ Copyright (C) 2005-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _MIPS_BITS_ATOMIC_H
+#define _MIPS_BITS_ATOMIC_H 1
+
+#include <stdint.h>
+#include <inttypes.h>
+#include <sgidefs.h>
+
+typedef int32_t atomic32_t;
+typedef uint32_t uatomic32_t;
+typedef int_fast32_t atomic_fast32_t;
+typedef uint_fast32_t uatomic_fast32_t;
+
+typedef int64_t atomic64_t;
+typedef uint64_t uatomic64_t;
+typedef int_fast64_t atomic_fast64_t;
+typedef uint_fast64_t uatomic_fast64_t;
+
+typedef intptr_t atomicptr_t;
+typedef uintptr_t uatomicptr_t;
+typedef intmax_t atomic_max_t;
+typedef uintmax_t uatomic_max_t;
+
+#if _MIPS_SIM == _ABIO32
+#define MIPS_PUSH_MIPS2 ".set mips2\n\t"
+#else
+#define MIPS_PUSH_MIPS2
+#endif
+
+#if _MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABIN32
+#define __HAVE_64B_ATOMICS 0
+#else
+#define __HAVE_64B_ATOMICS 1
+#endif
+
+/* See the comments in <sys/asm.h> about the use of the sync instruction. */
+#ifndef MIPS_SYNC
+# define MIPS_SYNC sync
+#endif
+
+/* Certain revisions of the R10000 Processor need an LL/SC Workaround
+ enabled. Revisions before 3.0 misbehave on atomic operations, and
+ Revs 2.6 and lower deadlock after several seconds due to other errata.
+
+ To quote the R10K Errata:
+ Workaround: The basic idea is to inhibit the four instructions
+ from simultaneously becoming active in R10000. Padding all
+ ll/sc sequences with nops or changing the looping branch in the
+ routines to a branch likely (which is always predicted taken
+ by R10000) will work. The nops should go after the loop, and the
+ number of them should be 28. This number could be decremented for
+ each additional instruction in the ll/sc loop such as the lock
+ modifier(s) between the ll and sc, the looping branch and its
+ delay slot. For typical short routines with one ll/sc loop, any
+ instructions after the loop could also count as a decrement. The
+ nop workaround pollutes the cache more but would be a few cycles
+ faster if all the code is in the cache and the looping branch
+ is predicted not taken. */
+
+
+#ifdef _MIPS_ARCH_R10000
+#define R10K_BEQZ_INSN "beqzl"
+#else
+#define R10K_BEQZ_INSN "beqz"
+#endif
+
+#define MIPS_SYNC_STR_2(X) #X
+#define MIPS_SYNC_STR_1(X) MIPS_SYNC_STR_2(X)
+#define MIPS_SYNC_STR MIPS_SYNC_STR_1(MIPS_SYNC)
+
+#if __GNUC_PREREQ (4, 8) || (defined __mips16 && __GNUC_PREREQ (4, 7))
+/* The __atomic_* builtins are available in GCC 4.7 and later, but MIPS
+ support for their efficient implementation was added only in GCC 4.8.
+ We still want to use them even with GCC 4.7 for MIPS16 code where we
+ have no assembly alternative available and want to avoid the __sync_*
+ builtins if at all possible. */
+
+#define USE_ATOMIC_COMPILER_BUILTINS 1
+
+/* Compare and exchange.
+ For all "bool" routines, we return FALSE if exchange succesful. */
+
+# define __arch_compare_and_exchange_bool_8_int(mem, newval, oldval, model) \
+ (abort (), 0)
+
+# define __arch_compare_and_exchange_bool_16_int(mem, newval, oldval, model) \
+ (abort (), 0)
+
+# define __arch_compare_and_exchange_bool_32_int(mem, newval, oldval, model) \
+ ({ \
+ typeof (*mem) __oldval = (oldval); \
+ !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
+ model, __ATOMIC_RELAXED); \
+ })
+
+# define __arch_compare_and_exchange_val_8_int(mem, newval, oldval, model) \
+ (abort (), (typeof(*mem)) 0)
+
+# define __arch_compare_and_exchange_val_16_int(mem, newval, oldval, model) \
+ (abort (), (typeof(*mem)) 0)
+
+# define __arch_compare_and_exchange_val_32_int(mem, newval, oldval, model) \
+ ({ \
+ typeof (*mem) __oldval = (oldval); \
+ __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
+ model, __ATOMIC_RELAXED); \
+ __oldval; \
+ })
+
+# if _MIPS_SIM == _ABIO32
+ /* We can't do an atomic 64-bit operation in O32. */
+# define __arch_compare_and_exchange_bool_64_int(mem, newval, oldval, model) \
+ (abort (), 0)
+# define __arch_compare_and_exchange_val_64_int(mem, newval, oldval, model) \
+ (abort (), (typeof(*mem)) 0)
+# else
+# define __arch_compare_and_exchange_bool_64_int(mem, newval, oldval, model) \
+ __arch_compare_and_exchange_bool_32_int (mem, newval, oldval, model)
+# define __arch_compare_and_exchange_val_64_int(mem, newval, oldval, model) \
+ __arch_compare_and_exchange_val_32_int (mem, newval, oldval, model)
+# endif
+
+/* Compare and exchange with "acquire" semantics, ie barrier after. */
+
+# define atomic_compare_and_exchange_bool_acq(mem, new, old) \
+ __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \
+ mem, new, old, __ATOMIC_ACQUIRE)
+
+# define atomic_compare_and_exchange_val_acq(mem, new, old) \
+ __atomic_val_bysize (__arch_compare_and_exchange_val, int, \
+ mem, new, old, __ATOMIC_ACQUIRE)
+
+/* Compare and exchange with "release" semantics, ie barrier before. */
+
+# define atomic_compare_and_exchange_bool_rel(mem, new, old) \
+ __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \
+ mem, new, old, __ATOMIC_RELEASE)
+
+# define atomic_compare_and_exchange_val_rel(mem, new, old) \
+ __atomic_val_bysize (__arch_compare_and_exchange_val, int, \
+ mem, new, old, __ATOMIC_RELEASE)
+
+
+/* Atomic exchange (without compare). */
+
+# define __arch_exchange_8_int(mem, newval, model) \
+ (abort (), (typeof(*mem)) 0)
+
+# define __arch_exchange_16_int(mem, newval, model) \
+ (abort (), (typeof(*mem)) 0)
+
+# define __arch_exchange_32_int(mem, newval, model) \
+ __atomic_exchange_n (mem, newval, model)
+
+# if _MIPS_SIM == _ABIO32
+/* We can't do an atomic 64-bit operation in O32. */
+# define __arch_exchange_64_int(mem, newval, model) \
+ (abort (), (typeof(*mem)) 0)
+# else
+# define __arch_exchange_64_int(mem, newval, model) \
+ __atomic_exchange_n (mem, newval, model)
+# endif
+
+# define atomic_exchange_acq(mem, value) \
+ __atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_ACQUIRE)
+
+# define atomic_exchange_rel(mem, value) \
+ __atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_RELEASE)
+
+
+/* Atomically add value and return the previous (unincremented) value. */
+
+# define __arch_exchange_and_add_8_int(mem, value, model) \
+ (abort (), (typeof(*mem)) 0)
+
+# define __arch_exchange_and_add_16_int(mem, value, model) \
+ (abort (), (typeof(*mem)) 0)
+
+# define __arch_exchange_and_add_32_int(mem, value, model) \
+ __atomic_fetch_add (mem, value, model)
+
+# if _MIPS_SIM == _ABIO32
+/* We can't do an atomic 64-bit operation in O32. */
+# define __arch_exchange_and_add_64_int(mem, value, model) \
+ (abort (), (typeof(*mem)) 0)
+# else
+# define __arch_exchange_and_add_64_int(mem, value, model) \
+ __atomic_fetch_add (mem, value, model)
+# endif
+
+# define atomic_exchange_and_add_acq(mem, value) \
+ __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \
+ __ATOMIC_ACQUIRE)
+
+# define atomic_exchange_and_add_rel(mem, value) \
+ __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \
+ __ATOMIC_RELEASE)
+
+#elif defined __mips16 /* !__GNUC_PREREQ (4, 7) */
+/* This implementation using __sync* builtins will be removed once glibc
+ requires GCC 4.7 or later to build. */
+
+# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
+ __sync_val_compare_and_swap ((mem), (oldval), (newval))
+# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
+ (!__sync_bool_compare_and_swap ((mem), (oldval), (newval)))
+
+# define atomic_exchange_acq(mem, newval) \
+ __sync_lock_test_and_set ((mem), (newval))
+
+# define atomic_exchange_and_add(mem, val) \
+ __sync_fetch_and_add ((mem), (val))
+
+# define atomic_bit_test_set(mem, bit) \
+ ({ __typeof (bit) __bit = (bit); \
+ (__sync_fetch_and_or ((mem), 1 << (__bit)) & (1 << (__bit))); })
+
+# define atomic_and(mem, mask) (void) __sync_fetch_and_and ((mem), (mask))
+# define atomic_and_val(mem, mask) __sync_fetch_and_and ((mem), (mask))
+
+# define atomic_or(mem, mask) (void) __sync_fetch_and_or ((mem), (mask))
+# define atomic_or_val(mem, mask) __sync_fetch_and_or ((mem), (mask))
+
+#else /* !__mips16 && !__GNUC_PREREQ (4, 8) */
+/* This implementation using inline assembly will be removed once glibc
+ requires GCC 4.8 or later to build. */
+
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+
+/* Compare and exchange. For all of the "xxx" routines, we expect a
+ "__prev" and a "__cmp" variable to be provided by the enclosing scope,
+ in which values are returned. */
+
+# define __arch_compare_and_exchange_xxx_8_int(mem, newval, oldval, rel, acq) \
+ (abort (), __prev = 0, __cmp = 0, (void) __cmp)
+
+# define __arch_compare_and_exchange_xxx_16_int(mem, newval, oldval, rel, acq) \
+ (abort (), __prev = 0, __cmp = 0, (void) __cmp)
+
+# define __arch_compare_and_exchange_xxx_32_int(mem, newval, oldval, rel, acq) \
+ __asm__ __volatile__ ( \
+ ".set push\n\t" \
+ MIPS_PUSH_MIPS2 \
+ rel "\n" \
+ "1:\t" \
+ "ll %0,%5\n\t" \
+ "move %1,$0\n\t" \
+ "bne %0,%3,2f\n\t" \
+ "move %1,%4\n\t" \
+ "sc %1,%2\n\t" \
+ R10K_BEQZ_INSN" %1,1b\n" \
+ acq "\n\t" \
+ ".set pop\n" \
+ "2:\n\t" \
+ : "=&r" (__prev), "=&r" (__cmp), "=m" (*mem) \
+ : "r" (oldval), "r" (newval), "m" (*mem) \
+ : "memory")
+
+# if _MIPS_SIM == _ABIO32
+/* We can't do an atomic 64-bit operation in O32. */
+# define __arch_compare_and_exchange_xxx_64_int(mem, newval, oldval, rel, acq) \
+ (abort (), __prev = 0, __cmp = 0, (void) __cmp)
+# else
+# define __arch_compare_and_exchange_xxx_64_int(mem, newval, oldval, rel, acq) \
+ __asm__ __volatile__ ("\n" \
+ ".set push\n\t" \
+ MIPS_PUSH_MIPS2 \
+ rel "\n" \
+ "1:\t" \
+ "lld %0,%5\n\t" \
+ "move %1,$0\n\t" \
+ "bne %0,%3,2f\n\t" \
+ "move %1,%4\n\t" \
+ "scd %1,%2\n\t" \
+ R10K_BEQZ_INSN" %1,1b\n" \
+ acq "\n\t" \
+ ".set pop\n" \
+ "2:\n\t" \
+ : "=&r" (__prev), "=&r" (__cmp), "=m" (*mem) \
+ : "r" (oldval), "r" (newval), "m" (*mem) \
+ : "memory")
+# endif
+
+/* For all "bool" routines, we return FALSE if exchange succesful. */
+
+# define __arch_compare_and_exchange_bool_8_int(mem, new, old, rel, acq) \
+({ typeof (*mem) __prev __attribute__ ((unused)); int __cmp; \
+ __arch_compare_and_exchange_xxx_8_int(mem, new, old, rel, acq); \
+ !__cmp; })
+
+# define __arch_compare_and_exchange_bool_16_int(mem, new, old, rel, acq) \
+({ typeof (*mem) __prev __attribute__ ((unused)); int __cmp; \
+ __arch_compare_and_exchange_xxx_16_int(mem, new, old, rel, acq); \
+ !__cmp; })
+
+# define __arch_compare_and_exchange_bool_32_int(mem, new, old, rel, acq) \
+({ typeof (*mem) __prev __attribute__ ((unused)); int __cmp; \
+ __arch_compare_and_exchange_xxx_32_int(mem, new, old, rel, acq); \
+ !__cmp; })
+
+# define __arch_compare_and_exchange_bool_64_int(mem, new, old, rel, acq) \
+({ typeof (*mem) __prev __attribute__ ((unused)); int __cmp; \
+ __arch_compare_and_exchange_xxx_64_int(mem, new, old, rel, acq); \
+ !__cmp; })
+
+/* For all "val" routines, return the old value whether exchange
+ successful or not. */
+
+# define __arch_compare_and_exchange_val_8_int(mem, new, old, rel, acq) \
+({ typeof (*mem) __prev; int __cmp; \
+ __arch_compare_and_exchange_xxx_8_int(mem, new, old, rel, acq); \
+ (typeof (*mem))__prev; })
+
+# define __arch_compare_and_exchange_val_16_int(mem, new, old, rel, acq) \
+({ typeof (*mem) __prev; int __cmp; \
+ __arch_compare_and_exchange_xxx_16_int(mem, new, old, rel, acq); \
+ (typeof (*mem))__prev; })
+
+# define __arch_compare_and_exchange_val_32_int(mem, new, old, rel, acq) \
+({ typeof (*mem) __prev; int __cmp; \
+ __arch_compare_and_exchange_xxx_32_int(mem, new, old, rel, acq); \
+ (typeof (*mem))__prev; })
+
+# define __arch_compare_and_exchange_val_64_int(mem, new, old, rel, acq) \
+({ typeof (*mem) __prev; int __cmp; \
+ __arch_compare_and_exchange_xxx_64_int(mem, new, old, rel, acq); \
+ (typeof (*mem))__prev; })
+
+/* Compare and exchange with "acquire" semantics, ie barrier after. */
+
+# define atomic_compare_and_exchange_bool_acq(mem, new, old) \
+ __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \
+ mem, new, old, "", MIPS_SYNC_STR)
+
+# define atomic_compare_and_exchange_val_acq(mem, new, old) \
+ __atomic_val_bysize (__arch_compare_and_exchange_val, int, \
+ mem, new, old, "", MIPS_SYNC_STR)
+
+/* Compare and exchange with "release" semantics, ie barrier before. */
+
+# define atomic_compare_and_exchange_bool_rel(mem, new, old) \
+ __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \
+ mem, new, old, MIPS_SYNC_STR, "")
+
+# define atomic_compare_and_exchange_val_rel(mem, new, old) \
+ __atomic_val_bysize (__arch_compare_and_exchange_val, int, \
+ mem, new, old, MIPS_SYNC_STR, "")
+
+
+
+/* Atomic exchange (without compare). */
+
+# define __arch_exchange_xxx_8_int(mem, newval, rel, acq) \
+ (abort (), (typeof(*mem)) 0)
+
+# define __arch_exchange_xxx_16_int(mem, newval, rel, acq) \
+ (abort (), (typeof(*mem)) 0)
+
+# define __arch_exchange_xxx_32_int(mem, newval, rel, acq) \
+({ typeof (*mem) __prev; int __cmp; \
+ __asm__ __volatile__ ("\n" \
+ ".set push\n\t" \
+ MIPS_PUSH_MIPS2 \
+ rel "\n" \
+ "1:\t" \
+ "ll %0,%4\n\t" \
+ "move %1,%3\n\t" \
+ "sc %1,%2\n\t" \
+ R10K_BEQZ_INSN" %1,1b\n" \
+ acq "\n\t" \
+ ".set pop\n" \
+ "2:\n\t" \
+ : "=&r" (__prev), "=&r" (__cmp), "=m" (*mem) \
+ : "r" (newval), "m" (*mem) \
+ : "memory"); \
+ __prev; })
+
+# if _MIPS_SIM == _ABIO32
+/* We can't do an atomic 64-bit operation in O32. */
+# define __arch_exchange_xxx_64_int(mem, newval, rel, acq) \
+ (abort (), (typeof(*mem)) 0)
+# else
+# define __arch_exchange_xxx_64_int(mem, newval, rel, acq) \
+({ typeof (*mem) __prev; int __cmp; \
+ __asm__ __volatile__ ("\n" \
+ ".set push\n\t" \
+ MIPS_PUSH_MIPS2 \
+ rel "\n" \
+ "1:\n" \
+ "lld %0,%4\n\t" \
+ "move %1,%3\n\t" \
+ "scd %1,%2\n\t" \
+ R10K_BEQZ_INSN" %1,1b\n" \
+ acq "\n\t" \
+ ".set pop\n" \
+ "2:\n\t" \
+ : "=&r" (__prev), "=&r" (__cmp), "=m" (*mem) \
+ : "r" (newval), "m" (*mem) \
+ : "memory"); \
+ __prev; })
+# endif
+
+# define atomic_exchange_acq(mem, value) \
+ __atomic_val_bysize (__arch_exchange_xxx, int, mem, value, "", MIPS_SYNC_STR)
+
+# define atomic_exchange_rel(mem, value) \
+ __atomic_val_bysize (__arch_exchange_xxx, int, mem, value, MIPS_SYNC_STR, "")
+
+
+/* Atomically add value and return the previous (unincremented) value. */
+
+# define __arch_exchange_and_add_8_int(mem, newval, rel, acq) \
+ (abort (), (typeof(*mem)) 0)
+
+# define __arch_exchange_and_add_16_int(mem, newval, rel, acq) \
+ (abort (), (typeof(*mem)) 0)
+
+# define __arch_exchange_and_add_32_int(mem, value, rel, acq) \
+({ typeof (*mem) __prev; int __cmp; \
+ __asm__ __volatile__ ("\n" \
+ ".set push\n\t" \
+ MIPS_PUSH_MIPS2 \
+ rel "\n" \
+ "1:\t" \
+ "ll %0,%4\n\t" \
+ "addu %1,%0,%3\n\t" \
+ "sc %1,%2\n\t" \
+ R10K_BEQZ_INSN" %1,1b\n" \
+ acq "\n\t" \
+ ".set pop\n" \
+ "2:\n\t" \
+ : "=&r" (__prev), "=&r" (__cmp), "=m" (*mem) \
+ : "r" (value), "m" (*mem) \
+ : "memory"); \
+ __prev; })
+
+# if _MIPS_SIM == _ABIO32
+/* We can't do an atomic 64-bit operation in O32. */
+# define __arch_exchange_and_add_64_int(mem, value, rel, acq) \
+ (abort (), (typeof(*mem)) 0)
+# else
+# define __arch_exchange_and_add_64_int(mem, value, rel, acq) \
+({ typeof (*mem) __prev; int __cmp; \
+ __asm__ __volatile__ ( \
+ ".set push\n\t" \
+ MIPS_PUSH_MIPS2 \
+ rel "\n" \
+ "1:\t" \
+ "lld %0,%4\n\t" \
+ "daddu %1,%0,%3\n\t" \
+ "scd %1,%2\n\t" \
+ R10K_BEQZ_INSN" %1,1b\n" \
+ acq "\n\t" \
+ ".set pop\n" \
+ "2:\n\t" \
+ : "=&r" (__prev), "=&r" (__cmp), "=m" (*mem) \
+ : "r" (value), "m" (*mem) \
+ : "memory"); \
+ __prev; })
+# endif
+
+# define atomic_exchange_and_add_acq(mem, value) \
+ __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \
+ "", MIPS_SYNC_STR)
+
+# define atomic_exchange_and_add_rel(mem, value) \
+ __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \
+ MIPS_SYNC_STR, "")
+
+#endif /* !__mips16 && !__GNUC_PREREQ (4, 8) */
+
+/* TODO: More atomic operations could be implemented efficiently; only the
+ basic requirements are done. */
+
+#ifdef __mips16
+# define atomic_full_barrier() __sync_synchronize ()
+
+#else /* !__mips16 */
+# define atomic_full_barrier() \
+ __asm__ __volatile__ (".set push\n\t" \
+ MIPS_PUSH_MIPS2 \
+ MIPS_SYNC_STR "\n\t" \
+ ".set pop" : : : "memory")
+#endif /* !__mips16 */
+
+#endif /* bits/atomic.h */
diff --git a/sysdeps/mips/bits/dlfcn.h b/sysdeps/mips/bits/dlfcn.h
new file mode 100644
index 0000000000..0c74042a90
--- /dev/null
+++ b/sysdeps/mips/bits/dlfcn.h
@@ -0,0 +1,64 @@
+/* System dependent definitions for run-time dynamic loading.
+ Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _DLFCN_H
+# error "Never use <bits/dlfcn.h> directly; include <dlfcn.h> instead."
+#endif
+
+/* The MODE argument to `dlopen' contains one of the following: */
+#define RTLD_LAZY 0x0001 /* Lazy function call binding. */
+#define RTLD_NOW 0x0002 /* Immediate function call binding. */
+#define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */
+#define RTLD_NOLOAD 0x00008 /* Do not load the object. */
+#define RTLD_DEEPBIND 0x00010 /* Use deep binding. */
+
+/* If the following bit is set in the MODE argument to `dlopen',
+ the symbols of the loaded object and its dependencies are made
+ visible as if the object were linked directly into the program. */
+#define RTLD_GLOBAL 0x0004
+
+/* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL.
+ The implementation does this by default and so we can define the
+ value to zero. */
+#define RTLD_LOCAL 0
+
+/* Do not delete object when closed. */
+#define RTLD_NODELETE 0x01000
+
+#ifdef __USE_GNU
+/* To support profiling of shared objects it is a good idea to call
+ the function found using `dlsym' using the following macro since
+ these calls do not use the PLT. But this would mean the dynamic
+ loader has no chance to find out when the function is called. The
+ macro applies the necessary magic so that profiling is possible.
+ Rewrite
+ foo = (*fctp) (arg1, arg2);
+ into
+ foo = DL_CALL_FCT (fctp, (arg1, arg2));
+*/
+# define DL_CALL_FCT(fctp, args) \
+ (_dl_mcount_wrapper_check ((void *) (fctp)), (*(fctp)) args)
+
+__BEGIN_DECLS
+
+/* This function calls the profiling functions. */
+extern void _dl_mcount_wrapper_check (void *__selfpc) __THROW;
+
+__END_DECLS
+
+#endif
diff --git a/sysdeps/mips/bits/endian.h b/sysdeps/mips/bits/endian.h
new file mode 100644
index 0000000000..126059799d
--- /dev/null
+++ b/sysdeps/mips/bits/endian.h
@@ -0,0 +1,15 @@
+/* The MIPS architecture has selectable endianness.
+ It exists in both little and big endian flavours and we
+ want to be able to share the installed header files between
+ both, so we define __BYTE_ORDER based on GCC's predefines. */
+
+#ifndef _ENDIAN_H
+# error "Never use <bits/endian.h> directly; include <endian.h> instead."
+#endif
+
+#ifdef __MIPSEB
+# define __BYTE_ORDER __BIG_ENDIAN
+#endif
+#ifdef __MIPSEL
+# define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
diff --git a/sysdeps/mips/bits/fenv.h b/sysdeps/mips/bits/fenv.h
new file mode 100644
index 0000000000..ccd70dee55
--- /dev/null
+++ b/sysdeps/mips/bits/fenv.h
@@ -0,0 +1,85 @@
+/* Copyright (C) 1998-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _FENV_H
+# error "Never use <bits/fenv.h> directly; include <fenv.h> instead."
+#endif
+
+
+/* Define bits representing the exception. We use the bit positions
+ of the appropriate bits in the FPU control word. */
+enum
+ {
+ FE_INEXACT =
+#define FE_INEXACT 0x04
+ FE_INEXACT,
+ FE_UNDERFLOW =
+#define FE_UNDERFLOW 0x08
+ FE_UNDERFLOW,
+ FE_OVERFLOW =
+#define FE_OVERFLOW 0x10
+ FE_OVERFLOW,
+ FE_DIVBYZERO =
+#define FE_DIVBYZERO 0x20
+ FE_DIVBYZERO,
+ FE_INVALID =
+#define FE_INVALID 0x40
+ FE_INVALID,
+ };
+
+#define FE_ALL_EXCEPT \
+ (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)
+
+/* The MIPS FPU supports all of the four defined rounding modes. We
+ use again the bit positions in the FPU control word as the values
+ for the appropriate macros. */
+enum
+ {
+ FE_TONEAREST =
+#define FE_TONEAREST 0x0
+ FE_TONEAREST,
+ FE_TOWARDZERO =
+#define FE_TOWARDZERO 0x1
+ FE_TOWARDZERO,
+ FE_UPWARD =
+#define FE_UPWARD 0x2
+ FE_UPWARD,
+ FE_DOWNWARD =
+#define FE_DOWNWARD 0x3
+ FE_DOWNWARD
+ };
+
+
+/* Type representing exception flags. */
+typedef unsigned short int fexcept_t;
+
+
+/* Type representing floating-point environment. This function corresponds
+ to the layout of the block written by the `fstenv'. */
+typedef struct
+ {
+ unsigned int __fp_control_register;
+ }
+fenv_t;
+
+/* If the default argument is used we use this value. */
+#define FE_DFL_ENV ((const fenv_t *) -1)
+
+#ifdef __USE_GNU
+/* Floating-point environment where none of the exception is masked. */
+# define FE_NOMASK_ENV ((const fenv_t *) -2)
+#endif
diff --git a/sysdeps/mips/bits/ipctypes.h b/sysdeps/mips/bits/ipctypes.h
new file mode 100644
index 0000000000..f6f74c9290
--- /dev/null
+++ b/sysdeps/mips/bits/ipctypes.h
@@ -0,0 +1,31 @@
+/* bits/ipctypes.h -- Define some types used by SysV IPC/MSG/SHM. MIPS version
+ Copyright (C) 2002-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/*
+ * Never include <bits/ipctypes.h> directly.
+ */
+
+#ifndef _BITS_IPCTYPES_H
+#define _BITS_IPCTYPES_H 1
+
+#include <bits/types.h>
+
+typedef __SLONG32_TYPE __ipc_pid_t;
+
+
+#endif /* bits/ipctypes.h */
diff --git a/sysdeps/mips/bits/link.h b/sysdeps/mips/bits/link.h
new file mode 100644
index 0000000000..4a3ec63e28
--- /dev/null
+++ b/sysdeps/mips/bits/link.h
@@ -0,0 +1,117 @@
+/* Copyright (C) 2005-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+#include <sgidefs.h>
+
+#if _MIPS_SIM == _ABIO32
+
+/* Registers for entry into PLT on MIPS. */
+typedef struct La_mips_32_regs
+{
+ uint32_t lr_reg[4]; /* $a0 through $a3 */
+ double lr_fpreg[2]; /* $f12 and $f14 */
+ uint32_t lr_ra;
+ uint32_t lr_sp;
+} La_mips_32_regs;
+
+/* Return values for calls from PLT on MIPS. */
+typedef struct La_mips_32_retval
+{
+ uint32_t lrv_v0;
+ uint32_t lrv_v1;
+ double lrv_f0;
+ double lrv_f2;
+} La_mips_32_retval;
+
+#else
+
+typedef struct La_mips_64_regs
+{
+ uint64_t lr_reg[8]; /* $a0 through $a7 */
+ double lr_fpreg[8]; /* $f12 throgh $f19 */
+ uint64_t lr_ra;
+ uint64_t lr_sp;
+} La_mips_64_regs;
+
+/* Return values for calls from PLT on MIPS. */
+typedef struct La_mips_64_retval
+{
+ uint64_t lrv_v0;
+ uint64_t lrv_v1;
+ double lrv_f0;
+ double lrv_f2;
+} La_mips_64_retval;
+
+#endif
+
+__BEGIN_DECLS
+
+#if _MIPS_SIM == _ABIO32
+
+extern Elf32_Addr la_mips_o32_gnu_pltenter (Elf32_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ La_mips_32_regs *__regs,
+ unsigned int *__flags,
+ const char *__symname,
+ long int *__framesizep);
+extern unsigned int la_mips_o32_gnu_pltexit (Elf32_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ const La_mips_32_regs *__inregs,
+ La_mips_32_retval *__outregs,
+ const char *__symname);
+
+#elif _MIPS_SIM == _ABIN32
+
+extern Elf32_Addr la_mips_n32_gnu_pltenter (Elf32_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ La_mips_64_regs *__regs,
+ unsigned int *__flags,
+ const char *__symname,
+ long int *__framesizep);
+extern unsigned int la_mips_n32_gnu_pltexit (Elf32_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ const La_mips_64_regs *__inregs,
+ La_mips_64_retval *__outregs,
+ const char *__symname);
+
+#else
+
+extern Elf64_Addr la_mips_n64_gnu_pltenter (Elf64_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ La_mips_64_regs *__regs,
+ unsigned int *__flags,
+ const char *__symname,
+ long int *__framesizep);
+extern unsigned int la_mips_n64_gnu_pltexit (Elf64_Sym *__sym, unsigned int __ndx,
+ uintptr_t *__refcook,
+ uintptr_t *__defcook,
+ const La_mips_64_regs *__inregs,
+ La_mips_64_retval *__outregs,
+ const char *__symname);
+
+#endif
+
+__END_DECLS
diff --git a/sysdeps/mips/bits/linkmap.h b/sysdeps/mips/bits/linkmap.h
new file mode 100644
index 0000000000..1fb9678a6d
--- /dev/null
+++ b/sysdeps/mips/bits/linkmap.h
@@ -0,0 +1,6 @@
+struct link_map_machine
+ {
+ ElfW(Addr) plt; /* Address of .plt */
+ ElfW(Word) fpabi; /* FP ABI of the object */
+ unsigned int odd_spreg; /* Does the object require odd_spreg support? */
+ };
diff --git a/sysdeps/mips/bits/mathdef.h b/sysdeps/mips/bits/mathdef.h
new file mode 100644
index 0000000000..cfc7288abb
--- /dev/null
+++ b/sysdeps/mips/bits/mathdef.h
@@ -0,0 +1,43 @@
+/* Copyright (C) 1997-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#if !defined _MATH_H && !defined _COMPLEX_H
+# error "Never use <bits/mathdef.h> directly; include <math.h> instead"
+#endif
+
+#include <sgidefs.h>
+
+#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF
+# define _MATH_H_MATHDEF 1
+
+/* MIPS has `float' and `double' operations. */
+typedef float float_t; /* `float' expressions are evaluated as
+ `float'. */
+typedef double double_t; /* `double' expressions are evaluated as
+ `double'. */
+
+/* The values returned by `ilogb' for 0 and NaN respectively. */
+# define FP_ILOGB0 (-2147483647)
+# define FP_ILOGBNAN 2147483647
+
+#endif /* ISO C99 */
+
+#if ! defined __NO_LONG_DOUBLE_MATH && _MIPS_SIM == _ABIO32
+/* Signal that we do not really have a `long double'. This disables the
+ declaration of all the `long double' function variants. */
+# define __NO_LONG_DOUBLE_MATH 1
+#endif
diff --git a/sysdeps/mips/bits/nan.h b/sysdeps/mips/bits/nan.h
new file mode 100644
index 0000000000..320af08692
--- /dev/null
+++ b/sysdeps/mips/bits/nan.h
@@ -0,0 +1,67 @@
+/* `NAN' constant for IEEE 754 machines. MIPS version.
+ Copyright (C) 1992-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _MATH_H
+# error "Never use <bits/nan.h> directly; include <math.h> instead."
+#endif
+
+
+/* IEEE Not A Number. */
+/* In legacy-NaN mode MIPS has the qNaN and sNaN patterns reversed
+ compared to most other architectures. IEEE 754-1985 left the
+ definition of this open to implementations, and for MIPS the top bit
+ of the mantissa must be SET to indicate a sNaN. In 2008-NaN mode
+ MIPS aligned to IEEE 754-2008. */
+
+#if __GNUC_PREREQ(3,3)
+
+# define NAN (__builtin_nanf (""))
+
+#elif defined __GNUC__
+
+/* No 2008-NaN mode support in any GCC version before 4.9. */
+
+# define NAN \
+ (__extension__ \
+ ((union { unsigned __l __attribute__ ((__mode__ (__SI__))); float __d; }) \
+ { __l: 0x7fbfffffUL }).__d)
+
+#else
+
+# include <endian.h>
+
+# if __BYTE_ORDER == __BIG_ENDIAN
+# ifdef __mips_nan2008
+# define __qnan_bytes { 0x7f, 0xc0, 0, 0 }
+# else
+# define __qnan_bytes { 0x7f, 0xbf, 0xff, 0xff }
+# endif
+# endif
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+# ifdef __mips_nan2008
+# define __qnan_bytes { 0, 0, 0xc0, 0x7f }
+# else
+# define __qnan_bytes { 0xff, 0xff, 0xbf, 0x7f }
+# endif
+# endif
+
+static union { unsigned char __c[4]; float __d; } __qnan_union
+ __attribute__ ((__unused__)) = { __qnan_bytes };
+# define NAN (__qnan_union.__d)
+
+#endif /* GCC. */
diff --git a/sysdeps/mips/bits/setjmp.h b/sysdeps/mips/bits/setjmp.h
new file mode 100644
index 0000000000..a78f01b398
--- /dev/null
+++ b/sysdeps/mips/bits/setjmp.h
@@ -0,0 +1,73 @@
+/* Define the machine-dependent type `jmp_buf'. MIPS version.
+ Copyright (C) 1992-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _MIPS_BITS_SETJMP_H
+#define _MIPS_BITS_SETJMP_H 1
+
+#if !defined(_SETJMP_H) && !defined(_PTHREAD_H)
+# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
+#endif
+
+#include <sgidefs.h>
+
+typedef struct __jmp_buf_internal_tag
+ {
+#if _MIPS_SIM == _ABIO32
+ /* Program counter. */
+ __ptr_t __pc;
+
+ /* Stack pointer. */
+ __ptr_t __sp;
+
+ /* Callee-saved registers s0 through s7. */
+ int __regs[8];
+
+ /* The frame pointer. */
+ __ptr_t __fp;
+
+ /* The global pointer. */
+ __ptr_t __gp;
+#else
+ /* Program counter. */
+ __extension__ long long __pc;
+
+ /* Stack pointer. */
+ __extension__ long long __sp;
+
+ /* Callee-saved registers s0 through s7. */
+ __extension__ long long __regs[8];
+
+ /* The frame pointer. */
+ __extension__ long long __fp;
+
+ /* The global pointer. */
+ __extension__ long long __gp;
+#endif
+
+ /* Unused (was floating point status register). */
+ int __glibc_reserved1;
+
+ /* Callee-saved floating point registers. */
+#if _MIPS_SIM == _ABI64
+ double __fpregs[8];
+#else
+ double __fpregs[6];
+#endif
+ } __jmp_buf[1];
+
+#endif /* _MIPS_BITS_SETJMP_H */
diff --git a/sysdeps/mips/bits/wordsize.h b/sysdeps/mips/bits/wordsize.h
new file mode 100644
index 0000000000..befbd21b9b
--- /dev/null
+++ b/sysdeps/mips/bits/wordsize.h
@@ -0,0 +1,23 @@
+/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sgidefs.h>
+
+#define __WORDSIZE _MIPS_SZPTR
+#if _MIPS_SIM == _ABI64
+# define __WORDSIZE_TIME64_COMPAT32 1
+#endif
diff --git a/sysdeps/mips/bsd-_setjmp.S b/sysdeps/mips/bsd-_setjmp.S
new file mode 100644
index 0000000000..742757650f
--- /dev/null
+++ b/sysdeps/mips/bsd-_setjmp.S
@@ -0,0 +1,44 @@
+/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. MIPS version.
+ Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 0)'.
+ We cannot do it in C because it must be a tail-call, so frame-unwinding
+ in setjmp doesn't clobber the state restored by longjmp. */
+
+#include <sysdep.h>
+
+ .set nomips16
+
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (_setjmp)
+#ifdef __PIC__
+ .set noreorder
+ .cpload t9
+ .set reorder
+ la t9, C_SYMBOL_NAME (__sigsetjmp)
+#endif
+ move a1,zero /* Pass a second argument of zero. */
+#ifdef __PIC__
+ jr t9
+#else
+ j C_SYMBOL_NAME (__sigsetjmp)
+#endif
+END (_setjmp)
+libc_hidden_def (_setjmp)
diff --git a/sysdeps/mips/bsd-setjmp.S b/sysdeps/mips/bsd-setjmp.S
new file mode 100644
index 0000000000..0654a4e144
--- /dev/null
+++ b/sysdeps/mips/bsd-setjmp.S
@@ -0,0 +1,43 @@
+/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. MIPS version.
+ Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 1)'.
+ We cannot do it in C because it must be a tail-call, so frame-unwinding
+ in setjmp doesn't clobber the state restored by longjmp. */
+
+#include <sysdep.h>
+
+ .set nomips16
+
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (setjmp)
+ .set noreorder
+#ifdef __PIC__
+ .cpload t9
+ .set reorder
+ la t9, C_SYMBOL_NAME (__sigsetjmp)
+#endif
+ li a1, 1 /* Pass a second argument of one. */
+#ifdef __PIC__
+ jr t9
+#else
+ j C_SYMBOL_NAME (__sigsetjmp)
+#endif
+END (setjmp)
diff --git a/sysdeps/mips/configure b/sysdeps/mips/configure
new file mode 100644
index 0000000000..4e13248c03
--- /dev/null
+++ b/sysdeps/mips/configure
@@ -0,0 +1,163 @@
+# This file is generated from configure.ac by Autoconf. DO NOT EDIT!
+ # Local configure fragment for sysdeps/mips.
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler is using the 2008 NaN encoding" >&5
+$as_echo_n "checking whether the compiler is using the 2008 NaN encoding... " >&6; }
+if ${libc_cv_mips_nan2008+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+dnl
+#ifdef __mips_nan2008
+yes
+#endif
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "yes" >/dev/null 2>&1; then :
+ libc_cv_mips_nan2008=yes
+else
+ libc_cv_mips_nan2008=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_mips_nan2008" >&5
+$as_echo "$libc_cv_mips_nan2008" >&6; }
+if test x$libc_cv_mips_nan2008 = xyes; then
+ $as_echo "#define HAVE_MIPS_NAN2008 1" >>confdefs.h
+
+fi
diff --git a/sysdeps/mips/configure.ac b/sysdeps/mips/configure.ac
new file mode 100644
index 0000000000..bcbdaffd9f
--- /dev/null
+++ b/sysdeps/mips/configure.ac
@@ -0,0 +1,15 @@
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/mips.
+
+dnl No MIPS GCC supports accessing static and hidden symbols in an
+dnl position independent way.
+dnl AC_DEFINE(PI_STATIC_AND_HIDDEN)
+
+AC_CACHE_CHECK([whether the compiler is using the 2008 NaN encoding],
+ libc_cv_mips_nan2008, [AC_EGREP_CPP(yes, [dnl
+#ifdef __mips_nan2008
+yes
+#endif], libc_cv_mips_nan2008=yes, libc_cv_mips_nan2008=no)])
+if test x$libc_cv_mips_nan2008 = xyes; then
+ AC_DEFINE(HAVE_MIPS_NAN2008)
+fi
diff --git a/sysdeps/mips/dl-dtprocnum.h b/sysdeps/mips/dl-dtprocnum.h
new file mode 100644
index 0000000000..8f4622a4f3
--- /dev/null
+++ b/sysdeps/mips/dl-dtprocnum.h
@@ -0,0 +1,21 @@
+/* Configuration of lookup functions. MIPS version.
+ Copyright (C) 2000-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Number of extra dynamic section entries for this architecture. By
+ default there are none. */
+#define DT_THISPROCNUM DT_MIPS_NUM
diff --git a/sysdeps/mips/dl-machine-reject-phdr.h b/sysdeps/mips/dl-machine-reject-phdr.h
new file mode 100644
index 0000000000..b09df30ff6
--- /dev/null
+++ b/sysdeps/mips/dl-machine-reject-phdr.h
@@ -0,0 +1,326 @@
+/* Machine-dependent program header inspection for the ELF loader.
+ Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _DL_MACHINE_REJECT_PHDR_H
+#define _DL_MACHINE_REJECT_PHDR_H 1
+
+#include <unistd.h>
+#include <sys/prctl.h>
+
+#if defined PR_GET_FP_MODE && defined PR_SET_FP_MODE
+# define HAVE_PRCTL_FP_MODE 1
+#else
+# define HAVE_PRCTL_FP_MODE 0
+#endif
+
+/* Reject an object with a debug message. */
+#define REJECT(str, args...) \
+ { \
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) \
+ _dl_debug_printf (str, ##args); \
+ return true; \
+ }
+
+/* Search the program headers for the ABI Flags. */
+
+static inline const ElfW(Phdr) *
+find_mips_abiflags (const ElfW(Phdr) *phdr, ElfW(Half) phnum)
+{
+ const ElfW(Phdr) *ph;
+
+ for (ph = phdr; ph < &phdr[phnum]; ++ph)
+ if (ph->p_type == PT_MIPS_ABIFLAGS)
+ return ph;
+ return NULL;
+}
+
+/* Cache the FP ABI value from the PT_MIPS_ABIFLAGS program header. */
+
+static bool
+cached_fpabi_reject_phdr_p (struct link_map *l)
+{
+ if (l->l_mach.fpabi == 0)
+ {
+ const ElfW(Phdr) *ph = find_mips_abiflags (l->l_phdr, l->l_phnum);
+
+ if (ph)
+ {
+ Elf_MIPS_ABIFlags_v0 * mips_abiflags;
+ if (ph->p_filesz < sizeof (Elf_MIPS_ABIFlags_v0))
+ REJECT (" %s: malformed PT_MIPS_ABIFLAGS found\n", l->l_name);
+
+ mips_abiflags = (Elf_MIPS_ABIFlags_v0 *) (l->l_addr + ph->p_vaddr);
+
+ if (__glibc_unlikely (mips_abiflags->flags2 != 0))
+ REJECT (" %s: unknown MIPS.abiflags flags2: %u\n", l->l_name,
+ mips_abiflags->flags2);
+
+ l->l_mach.fpabi = mips_abiflags->fp_abi;
+ l->l_mach.odd_spreg = (mips_abiflags->flags1
+ & MIPS_AFL_FLAGS1_ODDSPREG) != 0;
+ }
+ else
+ {
+ l->l_mach.fpabi = -1;
+ l->l_mach.odd_spreg = true;
+ }
+ }
+ return false;
+}
+
+/* Return a description of the specified floating-point ABI. */
+
+static const char *
+fpabi_string (int fpabi)
+{
+ switch (fpabi)
+ {
+ case Val_GNU_MIPS_ABI_FP_ANY:
+ return "Hard or soft float";
+ case Val_GNU_MIPS_ABI_FP_DOUBLE:
+ return "Hard float (double precision)";
+ case Val_GNU_MIPS_ABI_FP_SINGLE:
+ return "Hard float (single precision)";
+ case Val_GNU_MIPS_ABI_FP_SOFT:
+ return "Soft float";
+ case Val_GNU_MIPS_ABI_FP_OLD_64:
+ return "Unsupported FP64";
+ case Val_GNU_MIPS_ABI_FP_XX:
+ return "Hard float (32-bit CPU, Any FPU)";
+ case Val_GNU_MIPS_ABI_FP_64:
+ return "Hard float (32-bit CPU, 64-bit FPU)";
+ case Val_GNU_MIPS_ABI_FP_64A:
+ return "Hard float compat (32-bit CPU, 64-bit FPU)";
+ case -1:
+ return "Double precision, single precision or soft float";
+ default:
+ return "Unknown FP ABI";
+ }
+}
+
+/* A structure to describe the requirements of each FP ABI extension.
+ Each field says whether the ABI can be executed in that mode. The FR0 field
+ is actually overloaded and means 'default' FR mode for the ABI. I.e. For
+ O32 it is FR0 and for N32/N64 it is actually FR1. Since this logic is
+ focussed on the intricacies of mode management for O32 we call the field
+ FR0. */
+
+struct abi_req
+{
+ bool single;
+ bool soft;
+ bool fr0;
+ bool fr1;
+ bool fre;
+};
+
+/* FP ABI requirements for all Val_GNU_MIPS_ABI_FP_* values. */
+
+static const struct abi_req reqs[Val_GNU_MIPS_ABI_FP_MAX + 1] =
+ {{true, true, true, true, true}, /* Any */
+ {false, false, true, false, true}, /* Double-float */
+ {true, false, false, false, false}, /* Single-float */
+ {false, true, false, false, false}, /* Soft-float */
+ {false, false, false, false, false}, /* old-FP64 */
+ {false, false, true, true, true}, /* FPXX */
+ {false, false, false, true, false}, /* FP64 */
+ {false, false, false, true, true}}; /* FP64A */
+
+/* FP ABI requirements for objects without a PT_MIPS_ABIFLAGS segment. */
+
+static const struct abi_req none_req = { true, true, true, false, true };
+
+/* Return true iff ELF program headers are incompatible with the running
+ host. This verifies that floating-point ABIs are compatible and
+ re-configures the hardware mode if necessary. This code handles both the
+ DT_NEEDED libraries and the dlopen'ed libraries. It also accounts for the
+ impact of dlclose. */
+
+static bool __attribute_used__
+elf_machine_reject_phdr_p (const ElfW(Phdr) *phdr, uint_fast16_t phnum,
+ const char *buf, size_t len, struct link_map *map,
+ int fd)
+{
+ const ElfW(Phdr) *ph = find_mips_abiflags (phdr, phnum);
+ struct link_map *l;
+ Lmid_t nsid;
+ int in_abi = -1;
+ struct abi_req in_req;
+ Elf_MIPS_ABIFlags_v0 *mips_abiflags = NULL;
+ bool perfect_match = false;
+#if _MIPS_SIM == _ABIO32
+ unsigned int cur_mode = -1;
+# if HAVE_PRCTL_FP_MODE
+ bool cannot_mode_switch = false;
+
+ /* Get the current hardware mode. */
+ cur_mode = __prctl (PR_GET_FP_MODE);
+# endif
+#endif
+
+ /* Read the attributes section. */
+ if (ph != NULL)
+ {
+ ElfW(Addr) size = ph->p_filesz;
+
+ if (ph->p_offset + size <= len)
+ mips_abiflags = (Elf_MIPS_ABIFlags_v0 *) (buf + ph->p_offset);
+ else
+ {
+ mips_abiflags = alloca (size);
+ __lseek (fd, ph->p_offset, SEEK_SET);
+ if (__libc_read (fd, (void *) mips_abiflags, size) != size)
+ REJECT (" unable to read PT_MIPS_ABIFLAGS\n");
+ }
+
+ if (size < sizeof (Elf_MIPS_ABIFlags_v0))
+ REJECT (" contains malformed PT_MIPS_ABIFLAGS\n");
+
+ if (__glibc_unlikely (mips_abiflags->flags2 != 0))
+ REJECT (" unknown MIPS.abiflags flags2: %u\n", mips_abiflags->flags2);
+
+ in_abi = mips_abiflags->fp_abi;
+ }
+
+ /* ANY is compatible with anything. */
+ perfect_match |= (in_abi == Val_GNU_MIPS_ABI_FP_ANY);
+
+ /* Unknown ABIs are rejected. */
+ if (in_abi != -1 && in_abi > Val_GNU_MIPS_ABI_FP_MAX)
+ REJECT (" uses unknown FP ABI: %u\n", in_abi);
+
+ /* Obtain the initial requirements. */
+ in_req = (in_abi == -1) ? none_req : reqs[in_abi];
+
+ /* Check that the new requirement does not conflict with any currently
+ loaded object. */
+ for (nsid = 0; nsid < DL_NNS; ++nsid)
+ for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next)
+ {
+ struct abi_req existing_req;
+
+ if (cached_fpabi_reject_phdr_p (l))
+ return true;
+
+#if _MIPS_SIM == _ABIO32
+ /* A special case arises for O32 FP64 and FP64A where the kernel
+ pre-dates PT_MIPS_ABIFLAGS. These ABIs will be blindly loaded even
+ if the hardware mode is unavailable or disabled. In this
+ circumstance the prctl call to obtain the current mode will fail.
+ Detect this situation here and reject everything. This will
+ effectively prevent dynamically linked applications from failing in
+ unusual ways but there is nothing we can do to help static
+ applications. */
+ if ((l->l_mach.fpabi == Val_GNU_MIPS_ABI_FP_64A
+ || l->l_mach.fpabi == Val_GNU_MIPS_ABI_FP_64)
+ && cur_mode == -1)
+ REJECT (" found %s running in the wrong mode\n",
+ fpabi_string (l->l_mach.fpabi));
+#endif
+
+ /* Found a perfect match, success. */
+ perfect_match |= (in_abi == l->l_mach.fpabi);
+
+ /* Unknown ABIs are rejected. */
+ if (l->l_mach.fpabi != -1 && l->l_mach.fpabi > Val_GNU_MIPS_ABI_FP_MAX)
+ REJECT (" found unknown FP ABI: %u\n", l->l_mach.fpabi);
+
+ existing_req = (l->l_mach.fpabi == -1 ? none_req
+ : reqs[l->l_mach.fpabi]);
+
+ /* Merge requirements. */
+ in_req.soft &= existing_req.soft;
+ in_req.single &= existing_req.single;
+ in_req.fr0 &= existing_req.fr0;
+ in_req.fr1 &= existing_req.fr1;
+ in_req.fre &= existing_req.fre;
+
+ /* If there is at least one mode which is still usable then the new
+ object can be loaded. */
+ if (in_req.single || in_req.soft || in_req.fr1 || in_req.fr0
+ || in_req.fre)
+ {
+#if _MIPS_SIM == _ABIO32 && HAVE_PRCTL_FP_MODE
+ /* Account for loaded ABIs which prohibit mode switching. */
+ if (l->l_mach.fpabi == Val_GNU_MIPS_ABI_FP_XX)
+ cannot_mode_switch |= l->l_mach.odd_spreg;
+#endif
+ }
+ else
+ REJECT (" uses %s, already loaded %s\n",
+ fpabi_string (in_abi),
+ fpabi_string (l->l_mach.fpabi));
+ }
+
+#if _MIPS_SIM == _ABIO32
+ /* At this point we know that the newly loaded object is compatible with all
+ existing objects but the hardware mode may not be correct. */
+ if ((in_req.fr1 || in_req.fre || in_req.fr0)
+ && !perfect_match)
+ {
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
+ _dl_debug_printf (" needs %s%s mode\n", in_req.fr0 ? "FR0 or " : "",
+ (in_req.fre && !in_req.fr1) ? "FRE" : "FR1");
+
+ /* If the PR_GET_FP_MODE is not supported then only FR0 is available.
+ If the overall requirements cannot be met by FR0 then reject the
+ object. */
+ if (cur_mode == -1)
+ return !in_req.fr0;
+
+# if HAVE_PRCTL_FP_MODE
+ {
+ unsigned int fr1_mode = PR_FP_MODE_FR;
+
+ /* It is not possible to change the mode of a thread which may be
+ executing FPXX code with odd-singles. If an FPXX object with
+ odd-singles is loaded then just check the current mode is OK. This
+ can be either the FR1 mode or FR0 if the requirements are met by
+ FR0. */
+ if (cannot_mode_switch)
+ return (!(in_req.fre && cur_mode == (PR_FP_MODE_FR | PR_FP_MODE_FRE))
+ && !(in_req.fr1 && cur_mode == PR_FP_MODE_FR)
+ && !(in_req.fr0 && cur_mode == 0));
+
+ /* If the overall requirements can be satisfied by FRE but not FR1 then
+ fr1_mode must become FRE. */
+ if (in_req.fre && !in_req.fr1)
+ fr1_mode |= PR_FP_MODE_FRE;
+
+ /* Set the new mode. Use fr1_mode if the requirements cannot be met by
+ FR0. */
+ if (!in_req.fr0)
+ return __prctl (PR_SET_FP_MODE, fr1_mode) != 0;
+ else if (__prctl (PR_SET_FP_MODE, /* fr0_mode */ 0) != 0)
+ {
+ /* Setting FR0 can validly fail on an R6 core so retry with the FR1
+ mode as a fall back. */
+ if (errno != ENOTSUP)
+ return true;
+
+ return __prctl (PR_SET_FP_MODE, fr1_mode) != 0;
+ }
+ }
+# endif /* HAVE_PRCTL_FP_MODE */
+ }
+#endif /* _MIPS_SIM == _ABIO32 */
+
+ return false;
+}
+
+#endif /* dl-machine-reject-phdr.h */
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
new file mode 100644
index 0000000000..8738564241
--- /dev/null
+++ b/sysdeps/mips/dl-machine.h
@@ -0,0 +1,936 @@
+/* Machine-dependent ELF dynamic relocation inline functions. MIPS version.
+ Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Kazumoto Kojima <kkojima@info.kanagawa-u.ac.jp>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* FIXME: Profiling of shared libraries is not implemented yet. */
+#ifndef dl_machine_h
+#define dl_machine_h
+
+#define ELF_MACHINE_NAME "MIPS"
+
+#include <entry.h>
+
+#ifndef ENTRY_POINT
+#error ENTRY_POINT needs to be defined for MIPS.
+#endif
+
+#include <sgidefs.h>
+#include <sysdep.h>
+#include <sys/asm.h>
+#include <dl-tls.h>
+
+/* The offset of gp from GOT might be system-dependent. It's set by
+ ld. The same value is also */
+#define OFFSET_GP_GOT 0x7ff0
+
+#ifndef _RTLD_PROLOGUE
+# define _RTLD_PROLOGUE(entry) \
+ ".globl\t" __STRING(entry) "\n\t" \
+ ".ent\t" __STRING(entry) "\n\t" \
+ ".type\t" __STRING(entry) ", @function\n" \
+ __STRING(entry) ":\n\t"
+#endif
+
+#ifndef _RTLD_EPILOGUE
+# define _RTLD_EPILOGUE(entry) \
+ ".end\t" __STRING(entry) "\n\t" \
+ ".size\t" __STRING(entry) ", . - " __STRING(entry) "\n\t"
+#endif
+
+/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.
+ This only makes sense on MIPS when using PLTs, so choose the
+ PLT relocation (not encountered when not using PLTs). */
+#define ELF_MACHINE_JMP_SLOT R_MIPS_JUMP_SLOT
+#define elf_machine_type_class(type) \
+ ((((type) == ELF_MACHINE_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
+ | (((type) == R_MIPS_COPY) * ELF_RTYPE_CLASS_COPY))
+
+#define ELF_MACHINE_PLT_REL 1
+#define ELF_MACHINE_NO_REL 0
+#define ELF_MACHINE_NO_RELA 0
+
+/* Translate a processor specific dynamic tag to the index
+ in l_info array. */
+#define DT_MIPS(x) (DT_MIPS_##x - DT_LOPROC + DT_NUM)
+
+/* If there is a DT_MIPS_RLD_MAP_REL or DT_MIPS_RLD_MAP entry in the dynamic
+ section, fill in the debug map pointer with the run-time address of the
+ r_debug structure. */
+#define ELF_MACHINE_DEBUG_SETUP(l,r) \
+do { if ((l)->l_info[DT_MIPS (RLD_MAP_REL)]) \
+ { \
+ char *ptr = (char *)(l)->l_info[DT_MIPS (RLD_MAP_REL)]; \
+ ptr += (l)->l_info[DT_MIPS (RLD_MAP_REL)]->d_un.d_val; \
+ *(ElfW(Addr) *)ptr = (ElfW(Addr)) (r); \
+ } \
+ else if ((l)->l_info[DT_MIPS (RLD_MAP)]) \
+ *(ElfW(Addr) *)((l)->l_info[DT_MIPS (RLD_MAP)]->d_un.d_ptr) = \
+ (ElfW(Addr)) (r); \
+ } while (0)
+
+#if ((defined __mips_nan2008 && !defined HAVE_MIPS_NAN2008) \
+ || (!defined __mips_nan2008 && defined HAVE_MIPS_NAN2008))
+# error "Configuration inconsistency: __mips_nan2008 != HAVE_MIPS_NAN2008, overridden CFLAGS?"
+#endif
+#ifdef __mips_nan2008
+# define ELF_MACHINE_NAN2008 EF_MIPS_NAN2008
+#else
+# define ELF_MACHINE_NAN2008 0
+#endif
+
+/* Return nonzero iff ELF header is compatible with the running host. */
+static inline int __attribute_used__
+elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
+{
+#if _MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABIN32
+ /* Don't link o32 and n32 together. */
+ if (((ehdr->e_flags & EF_MIPS_ABI2) != 0) != (_MIPS_SIM == _ABIN32))
+ return 0;
+#endif
+
+ /* Don't link 2008-NaN and legacy-NaN objects together. */
+ if ((ehdr->e_flags & EF_MIPS_NAN2008) != ELF_MACHINE_NAN2008)
+ return 0;
+
+ /* Ensure that the old O32 FP64 ABI is never loaded, it is not supported
+ on linux. */
+ if (ehdr->e_flags & EF_MIPS_FP64)
+ return 0;
+
+ switch (ehdr->e_machine)
+ {
+ case EM_MIPS:
+ case EM_MIPS_RS3_LE:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static inline ElfW(Addr) *
+elf_mips_got_from_gpreg (ElfW(Addr) gpreg)
+{
+ /* FIXME: the offset of gp from GOT may be system-dependent. */
+ return (ElfW(Addr) *) (gpreg - OFFSET_GP_GOT);
+}
+
+/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+ first element of the GOT. This must be inlined in a function which
+ uses global data. We assume its $gp points to the primary GOT. */
+static inline ElfW(Addr)
+elf_machine_dynamic (void)
+{
+ register ElfW(Addr) gp __asm__ ("$28");
+ return *elf_mips_got_from_gpreg (gp);
+}
+
+#define STRINGXP(X) __STRING(X)
+#define STRINGXV(X) STRINGV_(X)
+#define STRINGV_(...) # __VA_ARGS__
+
+/* Return the run-time load address of the shared object. */
+static inline ElfW(Addr)
+elf_machine_load_address (void)
+{
+ ElfW(Addr) addr;
+#ifndef __mips16
+ asm (" .set noreorder\n"
+ " " STRINGXP (PTR_LA) " %0, 0f\n"
+# if __mips_isa_rev < 6
+ " bltzal $0, 0f\n"
+ " nop\n"
+ "0: " STRINGXP (PTR_SUBU) " %0, $31, %0\n"
+# else
+ "0: addiupc $31, 0\n"
+ " " STRINGXP (PTR_SUBU) " %0, $31, %0\n"
+# endif
+ " .set reorder\n"
+ : "=r" (addr)
+ : /* No inputs */
+ : "$31");
+#else
+ ElfW(Addr) tmp;
+ asm (" .set noreorder\n"
+ " move %1,$gp\n"
+ " lw %1,%%got(0f)(%1)\n"
+ "0: .fill 0\n" /* Clear the ISA bit on 0:. */
+ " la %0,0b\n"
+ " addiu %1,%%lo(0b)\n"
+ " subu %0,%1\n"
+ " .set reorder\n"
+ : "=d" (addr), "=d" (tmp)
+ : /* No inputs */);
+#endif
+ return addr;
+}
+
+/* The MSB of got[1] of a gnu object is set to identify gnu objects. */
+#if _MIPS_SIM == _ABI64
+# define ELF_MIPS_GNU_GOT1_MASK 0x8000000000000000L
+#else
+# define ELF_MIPS_GNU_GOT1_MASK 0x80000000L
+#endif
+
+/* We can't rely on elf_machine_got_rel because _dl_object_relocation_scope
+ fiddles with global data. */
+#define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) \
+do { \
+ struct link_map *map = &bootstrap_map; \
+ ElfW(Sym) *sym; \
+ ElfW(Addr) *got; \
+ int i, n; \
+ \
+ got = (ElfW(Addr) *) D_PTR (map, l_info[DT_PLTGOT]); \
+ \
+ if (__builtin_expect (map->l_addr == 0, 1)) \
+ break; \
+ \
+ /* got[0] is reserved. got[1] is also reserved for the dynamic object \
+ generated by gnu ld. Skip these reserved entries from \
+ relocation. */ \
+ i = (got[1] & ELF_MIPS_GNU_GOT1_MASK)? 2 : 1; \
+ n = map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val; \
+ \
+ /* Add the run-time displacement to all local got entries. */ \
+ while (i < n) \
+ got[i++] += map->l_addr; \
+ \
+ /* Handle global got entries. */ \
+ got += n; \
+ sym = (ElfW(Sym) *) D_PTR(map, l_info[DT_SYMTAB]) \
+ + map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val; \
+ i = (map->l_info[DT_MIPS (SYMTABNO)]->d_un.d_val \
+ - map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val); \
+ \
+ while (i--) \
+ { \
+ if (sym->st_shndx == SHN_UNDEF || sym->st_shndx == SHN_COMMON) \
+ *got = map->l_addr + sym->st_value; \
+ else if (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC \
+ && *got != sym->st_value) \
+ *got += map->l_addr; \
+ else if (ELFW(ST_TYPE) (sym->st_info) == STT_SECTION) \
+ { \
+ if (sym->st_other == 0) \
+ *got += map->l_addr; \
+ } \
+ else \
+ *got = map->l_addr + sym->st_value; \
+ \
+ got++; \
+ sym++; \
+ } \
+} while(0)
+
+
+/* Mask identifying addresses reserved for the user program,
+ where the dynamic linker should not map anything. */
+#define ELF_MACHINE_USER_ADDRESS_MASK 0x80000000UL
+
+
+/* Initial entry point code for the dynamic linker.
+ The C function `_dl_start' is the real entry point;
+ its return value is the user program's entry point.
+ Note how we have to be careful about two things:
+
+ 1) That we allocate a minimal stack of 24 bytes for
+ every function call, the MIPS ABI states that even
+ if all arguments are passed in registers the procedure
+ called can use the 16 byte area pointed to by $sp
+ when it is called to store away the arguments passed
+ to it.
+
+ 2) That under Unix the entry is named __start
+ and not just plain _start. */
+
+#ifndef __mips16
+# if __mips_isa_rev < 6
+# define LCOFF STRINGXP(.Lcof2)
+# define LOAD_31 STRINGXP(bltzal $8) "," STRINGXP(.Lcof2)
+# else
+# define LCOFF STRINGXP(.Lcof1)
+# define LOAD_31 "addiupc $31, 0"
+# endif
+# define RTLD_START asm (\
+ ".text\n\
+ " _RTLD_PROLOGUE(ENTRY_POINT) "\
+ " STRINGXV(SETUP_GPX($25)) "\n\
+ " STRINGXV(SETUP_GPX64($18,$25)) "\n\
+ # i386 ABI book says that the first entry of GOT holds\n\
+ # the address of the dynamic structure. Though MIPS ABI\n\
+ # doesn't say nothing about this, I emulate this here.\n\
+ " STRINGXP(PTR_LA) " $4, _DYNAMIC\n\
+ # Subtract OFFSET_GP_GOT\n\
+ " STRINGXP(PTR_S) " $4, -0x7ff0($28)\n\
+ move $4, $29\n\
+ " STRINGXP(PTR_SUBIU) " $29, 16\n\
+ \n\
+ " STRINGXP(PTR_LA) " $8, " LCOFF "\n\
+.Lcof1: " LOAD_31 "\n\
+.Lcof2: " STRINGXP(PTR_SUBU) " $8, $31, $8\n\
+ \n\
+ " STRINGXP(PTR_LA) " $25, _dl_start\n\
+ " STRINGXP(PTR_ADDU) " $25, $8\n\
+ jalr $25\n\
+ \n\
+ " STRINGXP(PTR_ADDIU) " $29, 16\n\
+ # Get the value of label '_dl_start_user' in t9 ($25).\n\
+ " STRINGXP(PTR_LA) " $25, _dl_start_user\n\
+ " _RTLD_EPILOGUE(ENTRY_POINT) "\
+ \n\
+ \n\
+ " _RTLD_PROLOGUE(_dl_start_user) "\
+ " STRINGXP(SETUP_GP) "\n\
+ " STRINGXV(SETUP_GP64($18,_dl_start_user)) "\n\
+ move $16, $28\n\
+ # Save the user entry point address in a saved register.\n\
+ move $17, $2\n\
+ # See if we were run as a command with the executable file\n\
+ # name as an extra leading argument.\n\
+ lw $2, _dl_skip_args\n\
+ beq $2, $0, 1f\n\
+ # Load the original argument count.\n\
+ " STRINGXP(PTR_L) " $4, 0($29)\n\
+ # Subtract _dl_skip_args from it.\n\
+ subu $4, $2\n\
+ # Adjust the stack pointer to skip _dl_skip_args words.\n\
+ sll $2, " STRINGXP (PTRLOG) "\n\
+ " STRINGXP(PTR_ADDU) " $29, $2\n\
+ # Save back the modified argument count.\n\
+ " STRINGXP(PTR_S) " $4, 0($29)\n\
+1: # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env) \n\
+ " STRINGXP(PTR_L) " $4, _rtld_local\n\
+ " STRINGXP(PTR_L) /* or lw??? fixme */ " $5, 0($29)\n\
+ " STRINGXP(PTR_LA) " $6, " STRINGXP (PTRSIZE) "($29)\n\
+ sll $7, $5, " STRINGXP (PTRLOG) "\n\
+ " STRINGXP(PTR_ADDU) " $7, $7, $6\n\
+ " STRINGXP(PTR_ADDU) " $7, $7, " STRINGXP (PTRSIZE) " \n\
+ # Make sure the stack pointer is aligned for _dl_init.\n\
+ and $2, $29, -2 * " STRINGXP(SZREG) "\n\
+ move $8, $29\n\
+ " STRINGXP(PTR_SUBIU) " $29, $2, 32\n\
+ " STRINGXP(PTR_S) " $8, (32 - " STRINGXP(SZREG) ")($29)\n\
+ " STRINGXP(SAVE_GP(16)) "\n\
+ # Call the function to run the initializers.\n\
+ jal _dl_init\n\
+ # Restore the stack pointer for _start.\n\
+ " STRINGXP(PTR_L) " $29, (32 - " STRINGXP(SZREG) ")($29)\n\
+ # Pass our finalizer function to the user in $2 as per ELF ABI.\n\
+ " STRINGXP(PTR_LA) " $2, _dl_fini\n\
+ # Jump to the user entry point.\n\
+ move $25, $17\n\
+ jr $25\n\t"\
+ _RTLD_EPILOGUE(_dl_start_user)\
+ ".previous"\
+);
+
+#else /* __mips16 */
+/* MIPS16 version. We currently only support O32 under MIPS16; the proper
+ assembly preprocessor abstractions will need to be added if other ABIs
+ are to be supported. */
+
+# define RTLD_START asm (\
+ ".text\n\
+ .set mips16\n\
+ " _RTLD_PROLOGUE (ENTRY_POINT) "\
+ # Construct GP value in $3.\n\
+ li $3, %hi(_gp_disp)\n\
+ addiu $4, $pc, %lo(_gp_disp)\n\
+ sll $3, 16\n\
+ addu $3, $4\n\
+ move $28, $3\n\
+ lw $4, %got(_DYNAMIC)($3)\n\
+ sw $4, -0x7ff0($3)\n\
+ move $4, $sp\n\
+ addiu $sp, -16\n\
+ # _dl_start() is sufficiently near to use pc-relative\n\
+ # load address.\n\
+ la $3, _dl_start\n\
+ move $25, $3\n\
+ jalr $3\n\
+ addiu $sp, 16\n\
+ " _RTLD_EPILOGUE (ENTRY_POINT) "\
+ \n\
+ \n\
+ " _RTLD_PROLOGUE (_dl_start_user) "\
+ li $16, %hi(_gp_disp)\n\
+ addiu $4, $pc, %lo(_gp_disp)\n\
+ sll $16, 16\n\
+ addu $16, $4\n\
+ move $17, $2\n\
+ move $28, $16\n\
+ lw $4, %got(_dl_skip_args)($16)\n\
+ lw $4, 0($4)\n\
+ beqz $4, 1f\n\
+ # Load the original argument count.\n\
+ lw $5, 0($sp)\n\
+ # Subtract _dl_skip_args from it.\n\
+ subu $5, $4\n\
+ # Adjust the stack pointer to skip _dl_skip_args words.\n\
+ sll $4, " STRINGXP (PTRLOG) "\n\
+ move $6, $sp\n\
+ addu $6, $4\n\
+ move $sp, $6\n\
+ # Save back the modified argument count.\n\
+ sw $5, 0($sp)\n\
+1: # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env) \n\
+ lw $4, %got(_rtld_local)($16)\n\
+ lw $4, 0($4)\n\
+ lw $5, 0($sp)\n\
+ addiu $6, $sp, " STRINGXP (PTRSIZE) "\n\
+ sll $7, $5, " STRINGXP (PTRLOG) "\n\
+ addu $7, $6\n\
+ addu $7, " STRINGXP (PTRSIZE) "\n\
+ # Make sure the stack pointer is aligned for _dl_init.\n\
+ li $2, 2 * " STRINGXP (SZREG) "\n\
+ neg $2, $2\n\
+ move $3, $sp\n\
+ and $2, $3\n\
+ sw $3, -" STRINGXP (SZREG) "($2)\n\
+ addiu $2, -32\n\
+ move $sp, $2\n\
+ sw $16, 16($sp)\n\
+ # Call the function to run the initializers.\n\
+ lw $2, %call16(_dl_init)($16)\n\
+ move $25, $2\n\
+ jalr $2\n\
+ # Restore the stack pointer for _start.\n\
+ lw $2, 32-" STRINGXP (SZREG) "($sp)\n\
+ move $sp, $2\n\
+ move $28, $16\n\
+ # Pass our finalizer function to the user in $2 as per ELF ABI.\n\
+ lw $2, %call16(_dl_fini)($16)\n\
+ # Jump to the user entry point.\n\
+ move $25, $17\n\
+ jr $17\n\t"\
+ _RTLD_EPILOGUE (_dl_start_user)\
+ ".previous"\
+);
+
+#endif /* __mips16 */
+
+/* Names of the architecture-specific auditing callback functions. */
+# if _MIPS_SIM == _ABIO32
+# define ARCH_LA_PLTENTER mips_o32_gnu_pltenter
+# define ARCH_LA_PLTEXIT mips_o32_gnu_pltexit
+# elif _MIPS_SIM == _ABIN32
+# define ARCH_LA_PLTENTER mips_n32_gnu_pltenter
+# define ARCH_LA_PLTEXIT mips_n32_gnu_pltexit
+# else
+# define ARCH_LA_PLTENTER mips_n64_gnu_pltenter
+# define ARCH_LA_PLTEXIT mips_n64_gnu_pltexit
+# endif
+
+/* We define an initialization function. This is called very early in
+ _dl_sysdep_start. */
+#define DL_PLATFORM_INIT dl_platform_init ()
+
+static inline void __attribute__ ((unused))
+dl_platform_init (void)
+{
+ if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
+ /* Avoid an empty string which would disturb us. */
+ GLRO(dl_platform) = NULL;
+}
+
+/* For a non-writable PLT, rewrite the .got.plt entry at RELOC_ADDR to
+ point at the symbol with address VALUE. For a writable PLT, rewrite
+ the corresponding PLT entry instead. */
+static inline ElfW(Addr)
+elf_machine_fixup_plt (struct link_map *map, lookup_t t,
+ const ElfW(Rel) *reloc,
+ ElfW(Addr) *reloc_addr, ElfW(Addr) value)
+{
+ return *reloc_addr = value;
+}
+
+static inline ElfW(Addr)
+elf_machine_plt_value (struct link_map *map, const ElfW(Rel) *reloc,
+ ElfW(Addr) value)
+{
+ return value;
+}
+
+/* The semantics of zero/non-zero values of undefined symbols differs
+ depending on whether the non-PIC ABI is in use. Under the non-PIC
+ ABI, a non-zero value indicates that there is an address reference
+ to the symbol and thus it must always be resolved (except when
+ resolving a jump slot relocation) to the PLT entry whose address is
+ provided as the symbol's value; a zero value indicates that this
+ canonical-address behaviour is not required. Yet under the classic
+ MIPS psABI, a zero value indicates that there is an address
+ reference to the function and the dynamic linker must resolve the
+ symbol immediately upon loading. To avoid conflict, symbols for
+ which the dynamic linker must assume the non-PIC ABI semantics are
+ marked with the STO_MIPS_PLT flag. */
+#define ELF_MACHINE_SYM_NO_MATCH(sym) \
+ ((sym)->st_shndx == SHN_UNDEF && !((sym)->st_other & STO_MIPS_PLT))
+
+#endif /* !dl_machine_h */
+
+#ifdef RESOLVE_MAP
+
+/* Perform a relocation described by R_INFO at the location pointed to
+ by RELOC_ADDR. SYM is the relocation symbol specified by R_INFO and
+ MAP is the object containing the reloc. */
+
+auto inline void
+__attribute__ ((always_inline))
+elf_machine_reloc (struct link_map *map, ElfW(Addr) r_info,
+ const ElfW(Sym) *sym, const struct r_found_version *version,
+ void *reloc_addr, ElfW(Addr) r_addend, int inplace_p)
+{
+ const unsigned long int r_type = ELFW(R_TYPE) (r_info);
+ ElfW(Addr) *addr_field = (ElfW(Addr) *) reloc_addr;
+
+#if !defined RTLD_BOOTSTRAP && !defined SHARED
+ /* This is defined in rtld.c, but nowhere in the static libc.a;
+ make the reference weak so static programs can still link. This
+ declaration cannot be done when compiling rtld.c (i.e. #ifdef
+ RTLD_BOOTSTRAP) because rtld.c contains the common defn for
+ _dl_rtld_map, which is incompatible with a weak decl in the same
+ file. */
+ weak_extern (GL(dl_rtld_map));
+#endif
+
+ switch (r_type)
+ {
+#if !defined (RTLD_BOOTSTRAP)
+# if _MIPS_SIM == _ABI64
+ case R_MIPS_TLS_DTPMOD64:
+ case R_MIPS_TLS_DTPREL64:
+ case R_MIPS_TLS_TPREL64:
+# else
+ case R_MIPS_TLS_DTPMOD32:
+ case R_MIPS_TLS_DTPREL32:
+ case R_MIPS_TLS_TPREL32:
+# endif
+ {
+ struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+
+ switch (r_type)
+ {
+ case R_MIPS_TLS_DTPMOD64:
+ case R_MIPS_TLS_DTPMOD32:
+ if (sym_map)
+ *addr_field = sym_map->l_tls_modid;
+ break;
+
+ case R_MIPS_TLS_DTPREL64:
+ case R_MIPS_TLS_DTPREL32:
+ if (sym)
+ {
+ if (inplace_p)
+ r_addend = *addr_field;
+ *addr_field = r_addend + TLS_DTPREL_VALUE (sym);
+ }
+ break;
+
+ case R_MIPS_TLS_TPREL32:
+ case R_MIPS_TLS_TPREL64:
+ if (sym)
+ {
+ CHECK_STATIC_TLS (map, sym_map);
+ if (inplace_p)
+ r_addend = *addr_field;
+ *addr_field = r_addend + TLS_TPREL_VALUE (sym_map, sym);
+ }
+ break;
+ }
+
+ break;
+ }
+#endif
+
+#if _MIPS_SIM == _ABI64
+ case (R_MIPS_64 << 8) | R_MIPS_REL32:
+#else
+ case R_MIPS_REL32:
+#endif
+ {
+ int symidx = ELFW(R_SYM) (r_info);
+ ElfW(Addr) reloc_value;
+
+ if (inplace_p)
+ /* Support relocations on mis-aligned offsets. */
+ __builtin_memcpy (&reloc_value, reloc_addr, sizeof (reloc_value));
+ else
+ reloc_value = r_addend;
+
+ if (symidx)
+ {
+ const ElfW(Word) gotsym
+ = (const ElfW(Word)) map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;
+
+ if ((ElfW(Word))symidx < gotsym)
+ {
+ /* This wouldn't work for a symbol imported from other
+ libraries for which there's no GOT entry, but MIPS
+ requires every symbol referenced in a dynamic
+ relocation to have a GOT entry in the primary GOT,
+ so we only get here for locally-defined symbols.
+ For section symbols, we should *NOT* be adding
+ sym->st_value (per the definition of the meaning of
+ S in reloc expressions in the ELF64 MIPS ABI),
+ since it should have already been added to
+ reloc_value by the linker, but older versions of
+ GNU ld didn't add it, and newer versions don't emit
+ useless relocations to section symbols any more, so
+ it is safe to keep on adding sym->st_value, even
+ though it's not ABI compliant. Some day we should
+ bite the bullet and stop doing this. */
+#ifndef RTLD_BOOTSTRAP
+ if (map != &GL(dl_rtld_map))
+#endif
+ reloc_value += sym->st_value + map->l_addr;
+ }
+ else
+ {
+#ifndef RTLD_BOOTSTRAP
+ const ElfW(Addr) *got
+ = (const ElfW(Addr) *) D_PTR (map, l_info[DT_PLTGOT]);
+ const ElfW(Word) local_gotno
+ = (const ElfW(Word))
+ map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;
+
+ reloc_value += got[symidx + local_gotno - gotsym];
+#endif
+ }
+ }
+ else
+#ifndef RTLD_BOOTSTRAP
+ if (map != &GL(dl_rtld_map))
+#endif
+ reloc_value += map->l_addr;
+
+ __builtin_memcpy (reloc_addr, &reloc_value, sizeof (reloc_value));
+ }
+ break;
+#ifndef RTLD_BOOTSTRAP
+#if _MIPS_SIM == _ABI64
+ case (R_MIPS_64 << 8) | R_MIPS_GLOB_DAT:
+#else
+ case R_MIPS_GLOB_DAT:
+#endif
+ {
+ int symidx = ELFW(R_SYM) (r_info);
+ const ElfW(Word) gotsym
+ = (const ElfW(Word)) map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;
+
+ if (__builtin_expect ((ElfW(Word)) symidx >= gotsym, 1))
+ {
+ const ElfW(Addr) *got
+ = (const ElfW(Addr) *) D_PTR (map, l_info[DT_PLTGOT]);
+ const ElfW(Word) local_gotno
+ = ((const ElfW(Word))
+ map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val);
+
+ ElfW(Addr) reloc_value = got[symidx + local_gotno - gotsym];
+ __builtin_memcpy (reloc_addr, &reloc_value, sizeof (reloc_value));
+ }
+ }
+ break;
+#endif
+ case R_MIPS_NONE: /* Alright, Wilbur. */
+ break;
+
+ case R_MIPS_JUMP_SLOT:
+ {
+ struct link_map *sym_map;
+ ElfW(Addr) value;
+
+ /* The addend for a jump slot relocation must always be zero:
+ calls via the PLT always branch to the symbol's address and
+ not to the address plus a non-zero offset. */
+ if (r_addend != 0)
+ _dl_signal_error (0, map->l_name, NULL,
+ "found jump slot relocation with non-zero addend");
+
+ sym_map = RESOLVE_MAP (&sym, version, r_type);
+ value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
+ *addr_field = value;
+
+ break;
+ }
+
+ case R_MIPS_COPY:
+ {
+ const ElfW(Sym) *const refsym = sym;
+ struct link_map *sym_map;
+ ElfW(Addr) value;
+
+ /* Calculate the address of the symbol. */
+ sym_map = RESOLVE_MAP (&sym, version, r_type);
+ value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
+
+ if (__builtin_expect (sym == NULL, 0))
+ /* This can happen in trace mode if an object could not be
+ found. */
+ break;
+ if (__builtin_expect (sym->st_size > refsym->st_size, 0)
+ || (__builtin_expect (sym->st_size < refsym->st_size, 0)
+ && GLRO(dl_verbose)))
+ {
+ const char *strtab;
+
+ strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+ _dl_error_printf ("\
+ %s: Symbol `%s' has different size in shared object, consider re-linking\n",
+ RTLD_PROGNAME, strtab + refsym->st_name);
+ }
+ memcpy (reloc_addr, (void *) value,
+ MIN (sym->st_size, refsym->st_size));
+ break;
+ }
+
+#if _MIPS_SIM == _ABI64
+ case R_MIPS_64:
+ /* For full compliance with the ELF64 ABI, one must precede the
+ _REL32/_64 pair of relocations with a _64 relocation, such
+ that the in-place addend is read as a 64-bit value. IRIX
+ didn't pick up on this requirement, so we treat the
+ _REL32/_64 relocation as a 64-bit relocation even if it's by
+ itself. For ABI compliance, we ignore such _64 dummy
+ relocations. For RELA, this may be simply removed, since
+ it's totally unnecessary. */
+ if (ELFW(R_SYM) (r_info) == 0)
+ break;
+ /* Fall through. */
+#endif
+ default:
+ _dl_reloc_bad_type (map, r_type, 0);
+ break;
+ }
+}
+
+/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
+ MAP is the object containing the reloc. */
+
+auto inline void
+__attribute__ ((always_inline))
+elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
+ const ElfW(Sym) *sym, const struct r_found_version *version,
+ void *const reloc_addr, int skip_ifunc)
+{
+ elf_machine_reloc (map, reloc->r_info, sym, version, reloc_addr, 0, 1);
+}
+
+auto inline void
+__attribute__((always_inline))
+elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
+ void *const reloc_addr)
+{
+ /* XXX Nothing to do. There is no relative relocation, right? */
+}
+
+auto inline void
+__attribute__((always_inline))
+elf_machine_lazy_rel (struct link_map *map,
+ ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
+ int skip_ifunc)
+{
+ ElfW(Addr) *const reloc_addr = (void *) (l_addr + reloc->r_offset);
+ const unsigned int r_type = ELFW(R_TYPE) (reloc->r_info);
+ /* Check for unexpected PLT reloc type. */
+ if (__builtin_expect (r_type == R_MIPS_JUMP_SLOT, 1))
+ {
+ if (__builtin_expect (map->l_mach.plt, 0) == 0)
+ {
+ /* Nothing is required here since we only support lazy
+ relocation in executables. */
+ }
+ else
+ *reloc_addr = map->l_mach.plt;
+ }
+ else
+ _dl_reloc_bad_type (map, r_type, 1);
+}
+
+auto inline void
+__attribute__ ((always_inline))
+elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
+ const ElfW(Sym) *sym, const struct r_found_version *version,
+ void *const reloc_addr, int skip_ifunc)
+{
+ elf_machine_reloc (map, reloc->r_info, sym, version, reloc_addr,
+ reloc->r_addend, 0);
+}
+
+auto inline void
+__attribute__((always_inline))
+elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
+ void *const reloc_addr)
+{
+}
+
+#ifndef RTLD_BOOTSTRAP
+/* Relocate GOT. */
+auto inline void
+__attribute__((always_inline))
+elf_machine_got_rel (struct link_map *map, int lazy)
+{
+ ElfW(Addr) *got;
+ ElfW(Sym) *sym;
+ const ElfW(Half) *vernum;
+ int i, n, symidx;
+
+#define RESOLVE_GOTSYM(sym,vernum,sym_index,reloc) \
+ ({ \
+ const ElfW(Sym) *ref = sym; \
+ const struct r_found_version *version __attribute__ ((unused)) \
+ = vernum ? &map->l_versions[vernum[sym_index] & 0x7fff] : NULL; \
+ struct link_map *sym_map; \
+ sym_map = RESOLVE_MAP (&ref, version, reloc); \
+ ref ? sym_map->l_addr + ref->st_value : 0; \
+ })
+
+ if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
+ vernum = (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
+ else
+ vernum = NULL;
+
+ got = (ElfW(Addr) *) D_PTR (map, l_info[DT_PLTGOT]);
+
+ n = map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;
+ /* The dynamic linker's local got entries have already been relocated. */
+ if (map != &GL(dl_rtld_map))
+ {
+ /* got[0] is reserved. got[1] is also reserved for the dynamic object
+ generated by gnu ld. Skip these reserved entries from relocation. */
+ i = (got[1] & ELF_MIPS_GNU_GOT1_MASK)? 2 : 1;
+
+ /* Add the run-time displacement to all local got entries if
+ needed. */
+ if (__builtin_expect (map->l_addr != 0, 0))
+ {
+ while (i < n)
+ got[i++] += map->l_addr;
+ }
+ }
+
+ /* Handle global got entries. */
+ got += n;
+ /* Keep track of the symbol index. */
+ symidx = map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;
+ sym = (ElfW(Sym) *) D_PTR (map, l_info[DT_SYMTAB]) + symidx;
+ i = (map->l_info[DT_MIPS (SYMTABNO)]->d_un.d_val
+ - map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val);
+
+ /* This loop doesn't handle Quickstart. */
+ while (i--)
+ {
+ if (sym->st_shndx == SHN_UNDEF)
+ {
+ if (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC && sym->st_value
+ && !(sym->st_other & STO_MIPS_PLT))
+ {
+ if (lazy)
+ *got = sym->st_value + map->l_addr;
+ else
+ /* This is a lazy-binding stub, so we don't need the
+ canonical address. */
+ *got = RESOLVE_GOTSYM (sym, vernum, symidx, R_MIPS_JUMP_SLOT);
+ }
+ else
+ *got = RESOLVE_GOTSYM (sym, vernum, symidx, R_MIPS_32);
+ }
+ else if (sym->st_shndx == SHN_COMMON)
+ *got = RESOLVE_GOTSYM (sym, vernum, symidx, R_MIPS_32);
+ else if (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC
+ && *got != sym->st_value)
+ {
+ if (lazy)
+ *got += map->l_addr;
+ else
+ /* This is a lazy-binding stub, so we don't need the
+ canonical address. */
+ *got = RESOLVE_GOTSYM (sym, vernum, symidx, R_MIPS_JUMP_SLOT);
+ }
+ else if (ELFW(ST_TYPE) (sym->st_info) == STT_SECTION)
+ {
+ if (sym->st_other == 0)
+ *got += map->l_addr;
+ }
+ else
+ *got = RESOLVE_GOTSYM (sym, vernum, symidx, R_MIPS_32);
+
+ ++got;
+ ++sym;
+ ++symidx;
+ }
+
+#undef RESOLVE_GOTSYM
+}
+#endif
+
+/* Set up the loaded object described by L so its stub function
+ will jump to the on-demand fixup code __dl_runtime_resolve. */
+
+auto inline int
+__attribute__((always_inline))
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
+{
+# ifndef RTLD_BOOTSTRAP
+ ElfW(Addr) *got;
+ extern void _dl_runtime_resolve (ElfW(Word));
+ extern void _dl_runtime_pltresolve (void);
+ extern int _dl_mips_gnu_objects;
+
+ if (lazy)
+ {
+ /* The GOT entries for functions have not yet been filled in.
+ Their initial contents will arrange when called to put an
+ offset into the .dynsym section in t8, the return address
+ in t7 and then jump to _GLOBAL_OFFSET_TABLE[0]. */
+ got = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]);
+
+ /* This function will get called to fix up the GOT entry indicated by
+ the register t8, and then jump to the resolved address. */
+ got[0] = (ElfW(Addr)) &_dl_runtime_resolve;
+
+ /* Store l to _GLOBAL_OFFSET_TABLE[1] for gnu object. The MSB
+ of got[1] of a gnu object is set to identify gnu objects.
+ Where we can store l for non gnu objects? XXX */
+ if ((got[1] & ELF_MIPS_GNU_GOT1_MASK) != 0)
+ got[1] = ((ElfW(Addr)) l | ELF_MIPS_GNU_GOT1_MASK);
+ else
+ _dl_mips_gnu_objects = 0;
+ }
+
+ /* Relocate global offset table. */
+ elf_machine_got_rel (l, lazy);
+
+ /* If using PLTs, fill in the first two entries of .got.plt. */
+ if (l->l_info[DT_JMPREL] && lazy)
+ {
+ ElfW(Addr) *gotplt;
+ gotplt = (ElfW(Addr) *) D_PTR (l, l_info[DT_MIPS (PLTGOT)]);
+ /* If a library is prelinked but we have to relocate anyway,
+ we have to be able to undo the prelinking of .got.plt.
+ The prelinker saved the address of .plt for us here. */
+ if (gotplt[1])
+ l->l_mach.plt = gotplt[1] + l->l_addr;
+ gotplt[0] = (ElfW(Addr)) &_dl_runtime_pltresolve;
+ gotplt[1] = (ElfW(Addr)) l;
+ }
+
+# endif
+ return lazy;
+}
+
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/mips/dl-procinfo.c b/sysdeps/mips/dl-procinfo.c
new file mode 100644
index 0000000000..706aaed6cc
--- /dev/null
+++ b/sysdeps/mips/dl-procinfo.c
@@ -0,0 +1,63 @@
+/* Data for Mips version of processor capability information.
+ Copyright (C) 2007-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Robert Millan <rmh@gnu.org>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This information must be kept in sync with the _DL_PLATFORM_COUNT
+ definitions in procinfo.h.
+
+ If anything should be added here check whether the size of each string
+ is still ok with the given array size.
+
+ All the #ifdefs in the definitions are quite irritating but
+ necessary if we want to avoid duplicating the information. There
+ are three different modes:
+
+ - PROCINFO_DECL is defined. This means we are only interested in
+ declarations.
+
+ - PROCINFO_DECL is not defined:
+
+ + if SHARED is defined the file is included in an array
+ initializer. The .element = { ... } syntax is needed.
+
+ + if SHARED is not defined a normal array initialization is
+ needed.
+ */
+
+#ifndef PROCINFO_CLASS
+#define PROCINFO_CLASS
+#endif
+
+#if !defined PROCINFO_DECL && defined SHARED
+ ._dl_mips_platforms
+#else
+PROCINFO_CLASS const char _dl_mips_platforms[4][11]
+#endif
+#ifndef PROCINFO_DECL
+= {
+ "loongson2e", "loongson2f", "octeon", "octeon2"
+ }
+#endif
+#if !defined SHARED || defined PROCINFO_DECL
+;
+#else
+,
+#endif
+
+#undef PROCINFO_DECL
+#undef PROCINFO_CLASS
diff --git a/sysdeps/mips/dl-procinfo.h b/sysdeps/mips/dl-procinfo.h
new file mode 100644
index 0000000000..ef4252639d
--- /dev/null
+++ b/sysdeps/mips/dl-procinfo.h
@@ -0,0 +1,67 @@
+/* Mips version of processor capability information handling macros.
+ Copyright (C) 2007-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Robert Millan <rmh@gnu.org>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _DL_PROCINFO_H
+#define _DL_PROCINFO_H 1
+
+#include <ldsodefs.h>
+
+
+/* Mask to filter out platforms. */
+#define _DL_HWCAP_PLATFORM (-1ULL)
+
+#define _DL_PLATFORMS_COUNT 4
+
+static inline const char *
+__attribute__ ((unused))
+_dl_platform_string (int idx)
+{
+ return GLRO(dl_mips_platforms)[idx];
+};
+
+static inline int
+__attribute__ ((unused, always_inline))
+_dl_string_platform (const char *str)
+{
+ int i;
+
+ if (str != NULL)
+ for (i = 0; i < _DL_PLATFORMS_COUNT; ++i)
+ {
+ if (strcmp (str, _dl_platform_string (i)) == 0)
+ return i;
+ }
+ return -1;
+};
+
+/* We cannot provide a general printing function. */
+#define _dl_procinfo(type, word) -1
+
+/* There are no hardware capabilities defined. */
+#define _dl_hwcap_string(idx) ""
+
+/* By default there is no important hardware capability. */
+#define HWCAP_IMPORTANT (0)
+
+/* We don't have any hardware capabilities. */
+#define _DL_HWCAP_COUNT 0
+
+#define _dl_string_hwcap(str) (-1)
+
+#endif /* dl-procinfo.h */
diff --git a/sysdeps/mips/dl-tls.h b/sysdeps/mips/dl-tls.h
new file mode 100644
index 0000000000..54dc71190c
--- /dev/null
+++ b/sysdeps/mips/dl-tls.h
@@ -0,0 +1,48 @@
+/* Thread-local storage handling in the ELF dynamic linker. MIPS version.
+ Copyright (C) 2005-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+
+/* Type used for the representation of TLS information in the GOT. */
+typedef struct
+{
+ unsigned long int ti_module;
+ unsigned long int ti_offset;
+} tls_index;
+
+/* The thread pointer points 0x7000 past the first static TLS block. */
+#define TLS_TP_OFFSET 0x7000
+
+/* Dynamic thread vector pointers point 0x8000 past the start of each
+ TLS block. */
+#define TLS_DTV_OFFSET 0x8000
+
+/* Compute the value for a GOTTPREL reloc. */
+#define TLS_TPREL_VALUE(sym_map, sym) \
+ ((sym_map)->l_tls_offset + (sym)->st_value - TLS_TP_OFFSET)
+
+/* Compute the value for a DTPREL reloc. */
+#define TLS_DTPREL_VALUE(sym) \
+ ((sym)->st_value - TLS_DTV_OFFSET)
+
+extern void *__tls_get_addr (tls_index *ti);
+
+# define GET_ADDR_OFFSET (ti->ti_offset + TLS_DTV_OFFSET)
+# define __TLS_GET_ADDR(__ti) (__tls_get_addr (__ti) - TLS_DTV_OFFSET)
+
+/* Value used for dtv entries for which the allocation is delayed. */
+#define TLS_DTV_UNALLOCATED ((void *) -1l)
diff --git a/sysdeps/mips/dl-trampoline.c b/sysdeps/mips/dl-trampoline.c
new file mode 100644
index 0000000000..25b170990c
--- /dev/null
+++ b/sysdeps/mips/dl-trampoline.c
@@ -0,0 +1,513 @@
+/* PLT trampoline. MIPS version.
+ Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Kazumoto Kojima <kkojima@info.kanagawa-u.ac.jp>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* FIXME: Profiling of shared libraries is not implemented yet. */
+
+#include <sysdep.h>
+#include <link.h>
+#include <elf.h>
+#include <ldsodefs.h>
+#include <dl-machine.h>
+#include <sysdep-cancel.h>
+
+/* Get link map for callers object containing STUB_PC. */
+static inline struct link_map *
+elf_machine_runtime_link_map (ElfW(Addr) gpreg, ElfW(Addr) stub_pc)
+{
+ extern int _dl_mips_gnu_objects;
+
+ /* got[1] is reserved to keep its link map address for the shared
+ object generated by the gnu linker. If all are such objects, we
+ can find the link map from current GPREG simply. If not so, get
+ the link map for caller's object containing STUB_PC. */
+
+ if (_dl_mips_gnu_objects)
+ {
+ ElfW(Addr) *got = elf_mips_got_from_gpreg (gpreg);
+ ElfW(Word) g1;
+
+ g1 = ((ElfW(Word) *) got)[1];
+
+ if ((g1 & ELF_MIPS_GNU_GOT1_MASK) != 0)
+ {
+ struct link_map *l =
+ (struct link_map *) (g1 & ~ELF_MIPS_GNU_GOT1_MASK);
+ ElfW(Addr) base, limit;
+ const ElfW(Phdr) *p = l->l_phdr;
+ ElfW(Half) this, nent = l->l_phnum;
+
+ /* For the common case of a stub being called from the containing
+ object, STUB_PC will point to somewhere within the object that
+ is described by the link map fetched via got[1]. Otherwise we
+ have to scan all maps. */
+ for (this = 0; this < nent; this++)
+ {
+ if (p[this].p_type == PT_LOAD)
+ {
+ base = p[this].p_vaddr + l->l_addr;
+ limit = base + p[this].p_memsz;
+ if (stub_pc >= base && stub_pc < limit)
+ return l;
+ }
+ }
+ }
+ }
+
+ struct link_map *l;
+ Lmid_t nsid;
+
+ for (nsid = 0; nsid < DL_NNS; ++nsid)
+ for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next)
+ {
+ ElfW(Addr) base, limit;
+ const ElfW(Phdr) *p = l->l_phdr;
+ ElfW(Half) this, nent = l->l_phnum;
+
+ for (this = 0; this < nent; ++this)
+ {
+ if (p[this].p_type == PT_LOAD)
+ {
+ base = p[this].p_vaddr + l->l_addr;
+ limit = base + p[this].p_memsz;
+ if (stub_pc >= base && stub_pc < limit)
+ return l;
+ }
+ }
+ }
+
+ _dl_signal_error (0, NULL, NULL, "cannot find runtime link map");
+ return NULL;
+}
+
+/* Define mips specific runtime resolver. The function __dl_runtime_resolve
+ is called from assembler function _dl_runtime_resolve which converts
+ special argument registers t7 ($15) and t8 ($24):
+ t7 address to return to the caller of the function
+ t8 index for this function symbol in .dynsym
+ to usual c arguments.
+
+ Other architectures call fixup from dl-runtime.c in
+ _dl_runtime_resolve. MIPS instead calls __dl_runtime_resolve. We
+ have to use our own version because of the way the got section is
+ treated on MIPS (we've also got ELF_MACHINE_PLT defined). */
+
+/* The flag _dl_mips_gnu_objects is set if all dynamic objects are
+ generated by the gnu linker. */
+int _dl_mips_gnu_objects = 1;
+
+/* This is called from assembly stubs below which the compiler can't see. */
+static ElfW(Addr)
+__dl_runtime_resolve (ElfW(Word), ElfW(Word), ElfW(Addr), ElfW(Addr))
+ __attribute_used__;
+
+static ElfW(Addr)
+__dl_runtime_resolve (ElfW(Word) sym_index,
+ ElfW(Word) return_address,
+ ElfW(Addr) old_gpreg,
+ ElfW(Addr) stub_pc)
+{
+ struct link_map *l = elf_machine_runtime_link_map (old_gpreg, stub_pc);
+ const ElfW(Sym) *const symtab
+ = (const ElfW(Sym) *) D_PTR (l, l_info[DT_SYMTAB]);
+ const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
+ ElfW(Addr) *got
+ = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]);
+ const ElfW(Word) local_gotno
+ = (const ElfW(Word)) l->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;
+ const ElfW(Word) gotsym
+ = (const ElfW(Word)) l->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;
+ const ElfW(Sym) *sym = &symtab[sym_index];
+ struct link_map *sym_map;
+ ElfW(Addr) value;
+
+ /* FIXME: The symbol versioning stuff is not tested yet. */
+ if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
+ {
+ switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL ? 1 : 0)
+ {
+ default:
+ {
+ const ElfW(Half) *vernum =
+ (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
+ ElfW(Half) ndx = vernum[sym_index] & 0x7fff;
+ const struct r_found_version *version = &l->l_versions[ndx];
+
+ if (version->hash != 0)
+ {
+ /* We need to keep the scope around so do some locking. This is
+ not necessary for objects which cannot be unloaded or when
+ we are not using any threads (yet). */
+ if (!RTLD_SINGLE_THREAD_P)
+ THREAD_GSCOPE_SET_FLAG ();
+
+ sym_map = _dl_lookup_symbol_x (strtab + sym->st_name, l,
+ &sym, l->l_scope, version,
+ ELF_RTYPE_CLASS_PLT, 0, 0);
+
+ /* We are done with the global scope. */
+ if (!RTLD_SINGLE_THREAD_P)
+ THREAD_GSCOPE_RESET_FLAG ();
+
+ break;
+ }
+ /* Fall through. */
+ }
+ case 0:
+ {
+ /* We need to keep the scope around so do some locking. This is
+ not necessary for objects which cannot be unloaded or when
+ we are not using any threads (yet). */
+ int flags = DL_LOOKUP_ADD_DEPENDENCY;
+ if (!RTLD_SINGLE_THREAD_P)
+ {
+ THREAD_GSCOPE_SET_FLAG ();
+ flags |= DL_LOOKUP_GSCOPE_LOCK;
+ }
+
+ sym_map = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
+ l->l_scope, 0, ELF_RTYPE_CLASS_PLT,
+ flags, 0);
+
+ /* We are done with the global scope. */
+ if (!RTLD_SINGLE_THREAD_P)
+ THREAD_GSCOPE_RESET_FLAG ();
+ }
+ }
+
+ /* Currently value contains the base load address of the object
+ that defines sym. Now add in the symbol offset. */
+ value = (sym ? sym_map->l_addr + sym->st_value : 0);
+ }
+ else
+ /* We already found the symbol. The module (and therefore its load
+ address) is also known. */
+ value = l->l_addr + sym->st_value;
+
+ /* Apply the relocation with that value. */
+ *(got + local_gotno + sym_index - gotsym) = value;
+
+ return value;
+}
+
+#if _MIPS_SIM == _ABIO32
+#define ELF_DL_FRAME_SIZE 40
+
+#define ELF_DL_SAVE_ARG_REGS "\
+ sw $15, 36($29)\n \
+ sw $4, 16($29)\n \
+ sw $5, 20($29)\n \
+ sw $6, 24($29)\n \
+ sw $7, 28($29)\n \
+"
+
+#define ELF_DL_RESTORE_ARG_REGS "\
+ lw $31, 36($29)\n \
+ lw $4, 16($29)\n \
+ lw $5, 20($29)\n \
+ lw $6, 24($29)\n \
+ lw $7, 28($29)\n \
+"
+
+/* The PLT resolver should also save and restore $2 and $3, which are used
+ as arguments to MIPS16 stub functions. */
+#define ELF_DL_PLT_FRAME_SIZE 48
+
+#define ELF_DL_PLT_SAVE_ARG_REGS \
+ ELF_DL_SAVE_ARG_REGS "\
+ sw $2, 40($29)\n \
+ sw $3, 44($29)\n \
+"
+
+#define ELF_DL_PLT_RESTORE_ARG_REGS \
+ ELF_DL_RESTORE_ARG_REGS "\
+ lw $2, 40($29)\n \
+ lw $3, 44($29)\n \
+"
+
+#define IFABIO32(X) X
+#define IFNEWABI(X)
+
+#else /* _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64 */
+
+#define ELF_DL_FRAME_SIZE 80
+
+#define ELF_DL_SAVE_ARG_REGS "\
+ sd $15, 72($29)\n \
+ sd $4, 8($29)\n \
+ sd $5, 16($29)\n \
+ sd $6, 24($29)\n \
+ sd $7, 32($29)\n \
+ sd $8, 40($29)\n \
+ sd $9, 48($29)\n \
+ sd $10, 56($29)\n \
+ sd $11, 64($29)\n \
+"
+
+#define ELF_DL_RESTORE_ARG_REGS "\
+ ld $31, 72($29)\n \
+ ld $4, 8($29)\n \
+ ld $5, 16($29)\n \
+ ld $6, 24($29)\n \
+ ld $7, 32($29)\n \
+ ld $8, 40($29)\n \
+ ld $9, 48($29)\n \
+ ld $10, 56($29)\n \
+ ld $11, 64($29)\n \
+"
+
+/* The PLT resolver should also save and restore $2 and $3, which are used
+ as arguments to MIPS16 stub functions. */
+#define ELF_DL_PLT_FRAME_SIZE 96
+
+#define ELF_DL_PLT_SAVE_ARG_REGS \
+ ELF_DL_SAVE_ARG_REGS "\
+ sd $2, 80($29)\n \
+ sd $3, 88($29)\n \
+"
+
+#define ELF_DL_PLT_RESTORE_ARG_REGS \
+ ELF_DL_RESTORE_ARG_REGS "\
+ ld $2, 80($29)\n \
+ ld $3, 88($29)\n \
+"
+
+#define IFABIO32(X)
+#define IFNEWABI(X) X
+
+#endif
+
+#ifndef __mips16
+asm ("\n\
+ .text\n\
+ .align 2\n\
+ .set nomips16\n\
+ .globl _dl_runtime_resolve\n\
+ .type _dl_runtime_resolve,@function\n\
+ .ent _dl_runtime_resolve\n\
+_dl_runtime_resolve:\n\
+ .frame $29, " STRINGXP(ELF_DL_FRAME_SIZE) ", $31\n\
+ .set noreorder\n\
+ # Save GP.\n\
+1: move $3, $28\n\
+ # Save arguments and sp value in stack.\n\
+ " STRINGXP(PTR_SUBIU) " $29, " STRINGXP(ELF_DL_FRAME_SIZE) "\n\
+ # Modify t9 ($25) so as to point .cpload instruction.\n\
+ " IFABIO32(STRINGXP(PTR_ADDIU) " $25, (2f-1b)\n") "\
+ # Compute GP.\n\
+2: " STRINGXP(SETUP_GP) "\n\
+ " STRINGXV(SETUP_GP64 (0, _dl_runtime_resolve)) "\n\
+ .set reorder\n\
+ # Save slot call pc.\n\
+ move $2, $31\n\
+ " IFABIO32(STRINGXP(CPRESTORE(32))) "\n\
+ " ELF_DL_SAVE_ARG_REGS "\
+ move $4, $24\n\
+ move $5, $15\n\
+ move $6, $3\n\
+ move $7, $2\n\
+ jal __dl_runtime_resolve\n\
+ " ELF_DL_RESTORE_ARG_REGS "\
+ " STRINGXP(RESTORE_GP64) "\n\
+ " STRINGXP(PTR_ADDIU) " $29, " STRINGXP(ELF_DL_FRAME_SIZE) "\n\
+ move $25, $2\n\
+ jr $25\n\
+ .end _dl_runtime_resolve\n\
+ .previous\n\
+");
+
+/* Assembler veneer called from the PLT header code when using PLTs.
+
+ Code in each PLT entry and the PLT header fills in the arguments to
+ this function:
+
+ - $15 (o32 t7, n32/n64 t3) - caller's return address
+ - $24 (t8) - PLT entry index
+ - $25 (t9) - address of _dl_runtime_pltresolve
+ - o32 $28 (gp), n32/n64 $14 (t2) - address of .got.plt
+
+ Different registers are used for .got.plt because the ABI was
+ originally designed for o32, where gp was available (call
+ clobbered). On n32/n64 gp is call saved.
+
+ _dl_fixup needs:
+
+ - $4 (a0) - link map address
+ - $5 (a1) - .rel.plt offset (== PLT entry index * 8) */
+
+asm ("\n\
+ .text\n\
+ .align 2\n\
+ .set nomips16\n\
+ .globl _dl_runtime_pltresolve\n\
+ .type _dl_runtime_pltresolve,@function\n\
+ .ent _dl_runtime_pltresolve\n\
+_dl_runtime_pltresolve:\n\
+ .frame $29, " STRINGXP(ELF_DL_PLT_FRAME_SIZE) ", $31\n\
+ .set noreorder\n\
+ # Save arguments and sp value in stack.\n\
+1: " STRINGXP(PTR_SUBIU) " $29, " STRINGXP(ELF_DL_PLT_FRAME_SIZE) "\n\
+ " IFABIO32(STRINGXP(PTR_L) " $13, " STRINGXP(PTRSIZE) "($28)") "\n\
+ " IFNEWABI(STRINGXP(PTR_L) " $13, " STRINGXP(PTRSIZE) "($14)") "\n\
+ # Modify t9 ($25) so as to point .cpload instruction.\n\
+ " IFABIO32(STRINGXP(PTR_ADDIU) " $25, (2f-1b)\n") "\
+ # Compute GP.\n\
+2: " STRINGXP(SETUP_GP) "\n\
+ " STRINGXV(SETUP_GP64 (0, _dl_runtime_pltresolve)) "\n\
+ .set reorder\n\
+ " IFABIO32(STRINGXP(CPRESTORE(32))) "\n\
+ " ELF_DL_PLT_SAVE_ARG_REGS "\
+ move $4, $13\n\
+ sll $5, $24, " STRINGXP(PTRLOG) " + 1\n\
+ jal _dl_fixup\n\
+ move $25, $2\n\
+ " ELF_DL_PLT_RESTORE_ARG_REGS "\
+ " STRINGXP(RESTORE_GP64) "\n\
+ " STRINGXP(PTR_ADDIU) " $29, " STRINGXP(ELF_DL_PLT_FRAME_SIZE) "\n\
+ jr $25\n\
+ .end _dl_runtime_pltresolve\n\
+ .previous\n\
+");
+
+#elif _MIPS_SIM == _ABIO32 /* __mips16 */
+/* MIPS16 version, O32 only. */
+asm ("\n\
+ .text\n\
+ .align 2\n\
+ .set mips16\n\
+ .globl _dl_runtime_resolve\n\
+ .type _dl_runtime_resolve,@function\n\
+ .ent _dl_runtime_resolve\n\
+_dl_runtime_resolve:\n\
+ .frame $29, " STRINGXP (ELF_DL_FRAME_SIZE) ", $31\n\
+ # Save arguments and sp value in stack.\n\t"
+# if _MIPS_ISA >= _MIPS_ISA_MIPS32
+ "save " STRINGXP (ELF_DL_FRAME_SIZE) ", $4-$7, $ra\n\t"
+# else
+ "addiu $sp, -" STRINGXP (ELF_DL_FRAME_SIZE) "\n\
+ sw $7, 32($sp)\n\
+ sw $6, 28($sp)\n\
+ sw $5, 24($sp)\n\
+ sw $4, 20($sp)\n\t"
+# endif
+ "# Preserve caller's $ra, for RESTORE instruction below.\n\
+ move $5, $15\n\
+ sw $5, 36($sp)\n\
+ # Compute GP into $2.\n\
+ li $2, %hi(_gp_disp)\n\
+ addiu $3, $pc, %lo(_gp_disp)\n\
+ sll $2, 16\n\
+ addu $2, $3\n\
+ lw $3, %got(__dl_runtime_resolve)($2)\n\
+ move $4, $24\n\
+ addiu $3, %lo(__dl_runtime_resolve)\n\
+ move $7, $ra\n\
+ move $6, $28\n\
+ move $25, $3\n\
+ jalr $3\n\t"
+# if _MIPS_ISA >= _MIPS_ISA_MIPS32
+ "restore " STRINGXP(ELF_DL_FRAME_SIZE) ", $4-$7, $ra\n\t"
+# else
+ "# Restore $ra, move placed further down to hide latency.\n\
+ lw $4, 36($sp)\n\
+ lw $5, 24($sp)\n\
+ lw $6, 28($sp)\n\
+ lw $7, 32($sp)\n\
+ move $ra, $4\n\
+ lw $4, 20($sp)\n\
+ addiu $sp, " STRINGXP(ELF_DL_FRAME_SIZE) "\n\t"
+# endif
+ "move $25, $2\n\
+ jr $2\n\
+ .end _dl_runtime_resolve\n\
+ .previous\n\
+");
+
+asm ("\n\
+ .text\n\
+ .align 2\n\
+ .set mips16\n\
+ .globl _dl_runtime_pltresolve\n\
+ .type _dl_runtime_pltresolve,@function\n\
+ .ent _dl_runtime_pltresolve\n\
+_dl_runtime_pltresolve:\n\
+ .frame $29, " STRINGXP(ELF_DL_PLT_FRAME_SIZE) ", $31\n\
+ # Save arguments and sp value in stack.\n\t"
+# if _MIPS_ISA >= _MIPS_ISA_MIPS32
+ "save " STRINGXP(ELF_DL_PLT_FRAME_SIZE) ", $4-$7, $ra\n\t"
+# else
+ "addiu $sp, -" STRINGXP(ELF_DL_PLT_FRAME_SIZE) "\n\
+ sw $7, 40($sp)\n\
+ sw $6, 36($sp)\n\
+ sw $5, 32($sp)\n\
+ sw $4, 28($sp)\n\t"
+# endif
+ "# Preserve MIPS16 stub function arguments.\n\
+ sw $3, 20($sp)\n\
+ sw $2, 16($sp)\n\
+ # Preserve caller's $ra, for RESTORE instruction below.\n\
+ move $3, $15\n\
+ sw $3, 44($sp)\n\
+ # Compute GP into $2.\n\
+ li $2, %hi(_gp_disp)\n\
+ addiu $3, $pc, %lo(_gp_disp)\n\
+ sll $2, 16\n\
+ addu $2, $3\n\
+ # Save GP value in slot.\n\
+ sw $2, 24($sp)\n\
+ # Load _dl_fixup address.\n\
+ lw $6, %call16(_dl_fixup)($2)\n\
+ # Load link map address.\n\
+ move $3, $28\n\
+ lw $4, " STRINGXP (PTRSIZE) "($3)\n\
+ move $5, $24\n\
+ sll $5, " STRINGXP (PTRLOG) " + 1\n\
+ # Call _dl_fixup.\n\
+ move $25, $6\n\
+ jalr $6\n\
+ move $25, $2\n\
+ # Reload GP value into $28.\n\
+ lw $3, 24($sp)\n\
+ move $28, $3\n\
+ lw $3, 16($sp)\n\
+ move $15, $3\n\
+ lw $3, 20($sp)\n\t"
+# if _MIPS_ISA >= _MIPS_ISA_MIPS32
+ "restore " STRINGXP (ELF_DL_PLT_FRAME_SIZE) ", $4-$7, $ra\n\t"
+# else
+ "# Restore $ra, move placed further down to hide latency.\n\
+ lw $4, 44($sp)\n\
+ lw $5, 32($sp)\n\
+ lw $6, 36($sp)\n\
+ lw $7, 40($sp)\n\
+ move $ra, $4\n\
+ lw $4, 28($sp)\n\
+ addiu $sp, " STRINGXP (ELF_DL_PLT_FRAME_SIZE) "\n\t"
+# endif
+ ".set noreorder\n\
+ jr $2\n\
+ move $2, $15\n\
+ .set reorder\n\
+ .end _dl_runtime_pltresolve\n\
+ .previous\n\
+");
+
+#else /* __mips16 && _MIPS_SIM != _ABIO32 */
+# error "MIPS16 support for N32/N64 not implemented"
+
+#endif /* __mips16 */
diff --git a/sysdeps/mips/fpregdef.h b/sysdeps/mips/fpregdef.h
new file mode 100644
index 0000000000..eeccd7272e
--- /dev/null
+++ b/sysdeps/mips/fpregdef.h
@@ -0,0 +1,23 @@
+/* Copyright (C) 1991-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _FPREGDEF_H
+#define _FPREGDEF_H
+
+#include <sys/fpregdef.h>
+
+#endif /* _FPREGDEF_H */
diff --git a/sysdeps/mips/fpu/e_sqrt.c b/sysdeps/mips/fpu/e_sqrt.c
new file mode 100644
index 0000000000..fa98a225b9
--- /dev/null
+++ b/sysdeps/mips/fpu/e_sqrt.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Hartvig Ekner <hartvige@mips.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+
+#include <sgidefs.h>
+
+
+#if (_MIPS_ISA >= _MIPS_ISA_MIPS2)
+
+double __attribute__ ((nomips16))
+__ieee754_sqrt (double x)
+{
+ double z;
+ __asm__ ("sqrt.d %0,%1" : "=f" (z) : "f" (x));
+ return z;
+}
+strong_alias (__ieee754_sqrt, __sqrt_finite)
+
+#else
+
+#include <sysdeps/ieee754/dbl-64/e_sqrt.c>
+
+#endif
diff --git a/sysdeps/mips/fpu/e_sqrtf.c b/sysdeps/mips/fpu/e_sqrtf.c
new file mode 100644
index 0000000000..28da63cf58
--- /dev/null
+++ b/sysdeps/mips/fpu/e_sqrtf.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Hartvig Ekner <hartvige@mips.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+
+#include <sgidefs.h>
+
+
+#if (_MIPS_ISA >= _MIPS_ISA_MIPS2)
+
+float __attribute__ ((nomips16))
+__ieee754_sqrtf (float x)
+{
+ float z;
+ __asm__ ("sqrt.s %0,%1" : "=f" (z) : "f" (x));
+ return z;
+}
+strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+
+#else
+
+#include <sysdeps/ieee754/flt-32/e_sqrtf.c>
+
+#endif
diff --git a/sysdeps/mips/fpu/fclrexcpt.c b/sysdeps/mips/fpu/fclrexcpt.c
new file mode 100644
index 0000000000..8fe865cb2f
--- /dev/null
+++ b/sysdeps/mips/fpu/fclrexcpt.c
@@ -0,0 +1,47 @@
+/* Clear given exceptions in current floating-point environment.
+ Copyright (C) 1998-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fenv_libc.h>
+#include <fpu_control.h>
+
+int
+feclearexcept (int excepts)
+{
+ int cw;
+
+ /* Mask out unsupported bits/exceptions. */
+ excepts &= FE_ALL_EXCEPT;
+
+ /* Read the complete control word. */
+ _FPU_GETCW (cw);
+
+ /* Clear exception flag bits and cause bits. If the cause bit is not
+ cleared, the next CTC instruction (just below) will re-generate the
+ exception. */
+
+ cw &= ~(excepts | (excepts << CAUSE_SHIFT));
+
+ /* Put the new data in effect. */
+ _FPU_SETCW (cw);
+
+ /* Success. */
+ return 0;
+}
+libm_hidden_def (feclearexcept)
diff --git a/sysdeps/mips/fpu/fedisblxcpt.c b/sysdeps/mips/fpu/fedisblxcpt.c
new file mode 100644
index 0000000000..a20d309040
--- /dev/null
+++ b/sysdeps/mips/fpu/fedisblxcpt.c
@@ -0,0 +1,40 @@
+/* Disable floating-point exceptions.
+ Copyright (C) 2000-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fenv_libc.h>
+#include <fpu_control.h>
+
+int
+fedisableexcept (int excepts)
+{
+ unsigned int new_exc, old_exc;
+
+ /* Get the current control word. */
+ _FPU_GETCW (new_exc);
+
+ old_exc = (new_exc & ENABLE_MASK) >> ENABLE_SHIFT;
+
+ excepts &= FE_ALL_EXCEPT;
+
+ new_exc &= ~(excepts << ENABLE_SHIFT);
+ _FPU_SETCW (new_exc);
+
+ return old_exc;
+}
diff --git a/sysdeps/mips/fpu/feenablxcpt.c b/sysdeps/mips/fpu/feenablxcpt.c
new file mode 100644
index 0000000000..7d8968dcd6
--- /dev/null
+++ b/sysdeps/mips/fpu/feenablxcpt.c
@@ -0,0 +1,40 @@
+/* Enable floating-point exceptions.
+ Copyright (C) 2000-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fenv_libc.h>
+#include <fpu_control.h>
+
+int
+feenableexcept (int excepts)
+{
+ unsigned int new_exc, old_exc;
+
+ /* Get the current control word. */
+ _FPU_GETCW (new_exc);
+
+ old_exc = (new_exc & ENABLE_MASK) >> ENABLE_SHIFT;
+
+ excepts &= FE_ALL_EXCEPT;
+
+ new_exc |= excepts << ENABLE_SHIFT;
+ _FPU_SETCW (new_exc);
+
+ return old_exc;
+}
diff --git a/sysdeps/mips/fpu/fegetenv.c b/sysdeps/mips/fpu/fegetenv.c
new file mode 100644
index 0000000000..8123d4de97
--- /dev/null
+++ b/sysdeps/mips/fpu/fegetenv.c
@@ -0,0 +1,33 @@
+/* Store current floating-point environment.
+ Copyright (C) 1998-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+__fegetenv (fenv_t *envp)
+{
+ _FPU_GETCW (*envp);
+
+ /* Success. */
+ return 0;
+}
+libm_hidden_def (__fegetenv)
+weak_alias (__fegetenv, fegetenv)
+libm_hidden_weak (fegetenv)
diff --git a/sysdeps/mips/fpu/fegetexcept.c b/sysdeps/mips/fpu/fegetexcept.c
new file mode 100644
index 0000000000..55031a0a2d
--- /dev/null
+++ b/sysdeps/mips/fpu/fegetexcept.c
@@ -0,0 +1,33 @@
+/* Get enabled floating-point exceptions.
+ Copyright (C) 2000-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fenv_libc.h>
+#include <fpu_control.h>
+
+int
+fegetexcept (void)
+{
+ unsigned int exc;
+
+ /* Get the current control word. */
+ _FPU_GETCW (exc);
+
+ return (exc & ENABLE_MASK) >> ENABLE_SHIFT;
+}
diff --git a/sysdeps/mips/fpu/fegetround.c b/sysdeps/mips/fpu/fegetround.c
new file mode 100644
index 0000000000..bfe9130f60
--- /dev/null
+++ b/sysdeps/mips/fpu/fegetround.c
@@ -0,0 +1,35 @@
+/* Return current rounding direction.
+ Copyright (C) 1998-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@arthur.rhein-neckar.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+__fegetround (void)
+{
+ int cw;
+
+ /* Get control word. */
+ _FPU_GETCW (cw);
+
+ return cw & _FPU_RC_MASK;
+}
+libm_hidden_def (__fegetround)
+weak_alias (__fegetround, fegetround)
+libm_hidden_weak (fegetround)
diff --git a/sysdeps/mips/fpu/feholdexcpt.c b/sysdeps/mips/fpu/feholdexcpt.c
new file mode 100644
index 0000000000..69e34e8a30
--- /dev/null
+++ b/sysdeps/mips/fpu/feholdexcpt.c
@@ -0,0 +1,41 @@
+/* Store current floating-point environment and clear exceptions.
+ Copyright (C) 2000-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+__feholdexcept (fenv_t *envp)
+{
+ fpu_control_t cw;
+
+ /* Save the current state. */
+ _FPU_GETCW (cw);
+ envp->__fp_control_register = cw;
+
+ /* Clear all exception enable bits and flags. */
+ cw &= ~(_FPU_MASK_V|_FPU_MASK_Z|_FPU_MASK_O|_FPU_MASK_U|_FPU_MASK_I|FE_ALL_EXCEPT);
+ _FPU_SETCW (cw);
+
+ return 0;
+}
+
+libm_hidden_def (__feholdexcept)
+weak_alias (__feholdexcept, feholdexcept)
+libm_hidden_weak (feholdexcept)
diff --git a/sysdeps/mips/fpu/fenv_libc.h b/sysdeps/mips/fpu/fenv_libc.h
new file mode 100644
index 0000000000..73584ca605
--- /dev/null
+++ b/sysdeps/mips/fpu/fenv_libc.h
@@ -0,0 +1,31 @@
+/* Copyright (C) 2000-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _FENV_LIBC_H
+#define _FENV_LIBC_H 1
+
+/* Mask for enabling exceptions and for the CAUSE bits. */
+#define ENABLE_MASK 0x00F80U
+#define CAUSE_MASK 0x1F000U
+
+/* Shift for FE_* flags to get up to the ENABLE bits and the CAUSE bits. */
+#define ENABLE_SHIFT 5
+#define CAUSE_SHIFT 10
+
+
+#endif /* _FENV_LIBC_H */
diff --git a/sysdeps/mips/fpu/fesetenv.c b/sysdeps/mips/fpu/fesetenv.c
new file mode 100644
index 0000000000..e1629aa1e9
--- /dev/null
+++ b/sysdeps/mips/fpu/fesetenv.c
@@ -0,0 +1,44 @@
+/* Install given floating-point environment.
+ Copyright (C) 1998-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+__fesetenv (const fenv_t *envp)
+{
+ fpu_control_t cw;
+
+ /* Read first current state to flush fpu pipeline. */
+ _FPU_GETCW (cw);
+
+ if (envp == FE_DFL_ENV)
+ _FPU_SETCW (_FPU_DEFAULT);
+ else if (envp == FE_NOMASK_ENV)
+ _FPU_SETCW (_FPU_IEEE);
+ else
+ _FPU_SETCW (envp->__fp_control_register);
+
+ /* Success. */
+ return 0;
+}
+
+libm_hidden_def (__fesetenv)
+weak_alias (__fesetenv, fesetenv)
+libm_hidden_weak (fesetenv)
diff --git a/sysdeps/mips/fpu/fesetround.c b/sysdeps/mips/fpu/fesetround.c
new file mode 100644
index 0000000000..61892542a3
--- /dev/null
+++ b/sysdeps/mips/fpu/fesetround.c
@@ -0,0 +1,46 @@
+/* Set current rounding direction.
+ Copyright (C) 1998-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@arthur.rhein-neckar.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+__fesetround (int round)
+{
+ fpu_control_t cw;
+
+ if ((round & ~_FPU_RC_MASK) != 0)
+ /* ROUND is no valid rounding mode. */
+ return 1;
+
+ /* Get current state. */
+ _FPU_GETCW (cw);
+
+ /* Set rounding bits. */
+ cw &= ~_FPU_RC_MASK;
+ cw |= round;
+ /* Set new state. */
+ _FPU_SETCW (cw);
+
+ return 0;
+}
+
+libm_hidden_def (__fesetround)
+weak_alias (__fesetround, fesetround)
+libm_hidden_weak (fesetround)
diff --git a/sysdeps/mips/fpu/feupdateenv.c b/sysdeps/mips/fpu/feupdateenv.c
new file mode 100644
index 0000000000..899d49441b
--- /dev/null
+++ b/sysdeps/mips/fpu/feupdateenv.c
@@ -0,0 +1,45 @@
+/* Install given floating-point environment and raise exceptions.
+ Copyright (C) 1998-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+__feupdateenv (const fenv_t *envp)
+{
+ int temp;
+
+ /* Save current exceptions. */
+ _FPU_GETCW (temp);
+ temp &= FE_ALL_EXCEPT;
+
+ /* Install new environment. */
+ __fesetenv (envp);
+
+ /* Raise the safed exception. Incidently for us the implementation
+ defined format of the values in objects of type fexcept_t is the
+ same as the ones specified using the FE_* constants. */
+ __feraiseexcept (temp);
+
+ /* Success. */
+ return 0;
+}
+libm_hidden_def (__feupdateenv)
+weak_alias (__feupdateenv, feupdateenv)
+libm_hidden_weak (feupdateenv)
diff --git a/sysdeps/mips/fpu/fgetexcptflg.c b/sysdeps/mips/fpu/fgetexcptflg.c
new file mode 100644
index 0000000000..b586807ecc
--- /dev/null
+++ b/sysdeps/mips/fpu/fgetexcptflg.c
@@ -0,0 +1,39 @@
+/* Store current representation for exceptions.
+ Copyright (C) 1998-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+ fpu_control_t temp;
+
+ /* Get the current exceptions. */
+ _FPU_GETCW (temp);
+
+ /* We only save the relevant bits here. In particular, care has to be
+ taken with the CAUSE bits, as an inadvertent restore later on could
+ generate unexpected exceptions. */
+
+ *flagp = temp & excepts & FE_ALL_EXCEPT;
+
+ /* Success. */
+ return 0;
+}
diff --git a/sysdeps/mips/fpu/fraiseexcpt.c b/sysdeps/mips/fpu/fraiseexcpt.c
new file mode 100644
index 0000000000..1b082df96e
--- /dev/null
+++ b/sysdeps/mips/fpu/fraiseexcpt.c
@@ -0,0 +1,48 @@
+/* Raise given exceptions.
+ Copyright (C) 2000-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fenv_libc.h>
+#include <fpu_control.h>
+
+int
+__feraiseexcept (int excepts)
+{
+ fpu_control_t cw;
+
+ /* Get current state. */
+ _FPU_GETCW (cw);
+
+ /* Set flag bits (which are accumulative), and *also* set the
+ cause bits. The setting of the cause bits is what actually causes
+ the hardware to generate the exception, if the corresponding enable
+ bit is set as well. */
+
+ excepts &= FE_ALL_EXCEPT;
+ cw |= excepts | (excepts << CAUSE_SHIFT);
+
+ /* Set new state. */
+ _FPU_SETCW (cw);
+
+ return 0;
+}
+
+libm_hidden_def (__feraiseexcept)
+weak_alias (__feraiseexcept, feraiseexcept)
+libm_hidden_weak (feraiseexcept)
diff --git a/sysdeps/mips/fpu/fsetexcptflg.c b/sysdeps/mips/fpu/fsetexcptflg.c
new file mode 100644
index 0000000000..09b51cd7c1
--- /dev/null
+++ b/sysdeps/mips/fpu/fsetexcptflg.c
@@ -0,0 +1,42 @@
+/* Set floating-point environment exception handling.
+ Copyright (C) 1998-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Hartvig Ekner <hartvige@mips.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+ fpu_control_t temp;
+
+ /* Get the current exceptions. */
+ _FPU_GETCW (temp);
+
+ /* Make sure the flags we want restored are legal. */
+ excepts &= FE_ALL_EXCEPT;
+
+ /* Now clear the bits called for, and copy them in from flagp. Note that
+ we ignore all non-flag bits from *flagp, so they don't matter. */
+ temp = (temp & ~excepts) | (*flagp & excepts);
+
+ _FPU_SETCW (temp);
+
+ /* Success. */
+ return 0;
+}
diff --git a/sysdeps/mips/fpu/ftestexcept.c b/sysdeps/mips/fpu/ftestexcept.c
new file mode 100644
index 0000000000..0af7ddc427
--- /dev/null
+++ b/sysdeps/mips/fpu/ftestexcept.c
@@ -0,0 +1,33 @@
+/* Test exception in current environment.
+ Copyright (C) 1998-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@arthur.rhein-neckar.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fetestexcept (int excepts)
+{
+ int cw;
+
+ /* Get current control word. */
+ _FPU_GETCW (cw);
+
+ return cw & excepts & FE_ALL_EXCEPT;
+}
+libm_hidden_def (fetestexcept)
diff --git a/sysdeps/mips/fpu_control.h b/sysdeps/mips/fpu_control.h
new file mode 100644
index 0000000000..cfb4e6a0fd
--- /dev/null
+++ b/sysdeps/mips/fpu_control.h
@@ -0,0 +1,133 @@
+/* FPU control word bits. Mips version.
+ Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Olaf Flebbe and Ralf Baechle.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _FPU_CONTROL_H
+#define _FPU_CONTROL_H
+
+/* MIPS FPU floating point control register bits.
+ *
+ * 31-25 -> floating point conditions code bits 7-1. These bits are only
+ * available in MIPS IV.
+ * 24 -> flush denormalized results to zero instead of
+ * causing unimplemented operation exception. This bit is only
+ * available for MIPS III and newer.
+ * 23 -> Condition bit
+ * 22-21 -> reserved for architecture implementers
+ * 20 -> reserved (read as 0, write with 0)
+ * 19 -> IEEE 754-2008 non-arithmetic ABS.fmt and NEG.fmt enable
+ * 18 -> IEEE 754-2008 recommended NaN encoding enable
+ * 17 -> cause bit for unimplemented operation
+ * 16 -> cause bit for invalid exception
+ * 15 -> cause bit for division by zero exception
+ * 14 -> cause bit for overflow exception
+ * 13 -> cause bit for underflow exception
+ * 12 -> cause bit for inexact exception
+ * 11 -> enable exception for invalid exception
+ * 10 -> enable exception for division by zero exception
+ * 9 -> enable exception for overflow exception
+ * 8 -> enable exception for underflow exception
+ * 7 -> enable exception for inexact exception
+ * 6 -> flag invalid exception
+ * 5 -> flag division by zero exception
+ * 4 -> flag overflow exception
+ * 3 -> flag underflow exception
+ * 2 -> flag inexact exception
+ * 1-0 -> rounding control
+ *
+ *
+ * Rounding Control:
+ * 00 - rounding to nearest (RN)
+ * 01 - rounding toward zero (RZ)
+ * 10 - rounding (up) toward plus infinity (RP)
+ * 11 - rounding (down)toward minus infinity (RM)
+ */
+
+#include <features.h>
+
+#ifdef __mips_soft_float
+
+#define _FPU_RESERVED 0xffffffff
+#define _FPU_DEFAULT 0x00000000
+typedef unsigned int fpu_control_t;
+#define _FPU_GETCW(cw) (cw) = 0
+#define _FPU_SETCW(cw) (void) (cw)
+extern fpu_control_t __fpu_control;
+
+#else /* __mips_soft_float */
+
+/* Masks for interrupts. */
+#define _FPU_MASK_V 0x0800 /* Invalid operation */
+#define _FPU_MASK_Z 0x0400 /* Division by zero */
+#define _FPU_MASK_O 0x0200 /* Overflow */
+#define _FPU_MASK_U 0x0100 /* Underflow */
+#define _FPU_MASK_I 0x0080 /* Inexact operation */
+
+/* Flush denormalized numbers to zero. */
+#define _FPU_FLUSH_TZ 0x1000000
+
+/* IEEE 754-2008 compliance control. */
+#define _FPU_ABS2008 0x80000
+#define _FPU_NAN2008 0x40000
+
+/* Rounding control. */
+#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */
+#define _FPU_RC_ZERO 0x1
+#define _FPU_RC_UP 0x2
+#define _FPU_RC_DOWN 0x3
+/* Mask for rounding control. */
+#define _FPU_RC_MASK 0x3
+
+#define _FPU_RESERVED 0xfe840000 /* Reserved bits in cw, incl NAN2008. */
+
+
+/* The fdlibm code requires strict IEEE double precision arithmetic,
+ and no interrupts for exceptions, rounding to nearest. */
+#ifdef __mips_nan2008
+# define _FPU_DEFAULT 0x00040000
+#else
+# define _FPU_DEFAULT 0x00000000
+#endif
+
+/* IEEE: same as above, but exceptions. */
+#ifdef __mips_nan2008
+# define _FPU_IEEE 0x00040F80
+#else
+# define _FPU_IEEE 0x00000F80
+#endif
+
+/* Type of the control word. */
+typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__)));
+
+/* Macros for accessing the hardware control word. */
+extern fpu_control_t __mips_fpu_getcw (void) __THROW;
+extern void __mips_fpu_setcw (fpu_control_t) __THROW;
+#ifdef __mips16
+# define _FPU_GETCW(cw) do { (cw) = __mips_fpu_getcw (); } while (0)
+# define _FPU_SETCW(cw) __mips_fpu_setcw (cw)
+#else
+# define _FPU_GETCW(cw) __asm__ volatile ("cfc1 %0,$31" : "=r" (cw))
+# define _FPU_SETCW(cw) __asm__ volatile ("ctc1 %0,$31" : : "r" (cw))
+#endif
+
+/* Default control word set at startup. */
+extern fpu_control_t __fpu_control;
+
+#endif /* __mips_soft_float */
+
+#endif /* fpu_control.h */
diff --git a/sysdeps/mips/gccframe.h b/sysdeps/mips/gccframe.h
new file mode 100644
index 0000000000..3a35d19706
--- /dev/null
+++ b/sysdeps/mips/gccframe.h
@@ -0,0 +1,21 @@
+/* Definition of object in frame unwind info. mips version.
+ Copyright (C) 2001-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define FIRST_PSEUDO_REGISTER 76
+
+#include <sysdeps/generic/gccframe.h>
diff --git a/sysdeps/mips/ieee754/ieee754.h b/sysdeps/mips/ieee754/ieee754.h
new file mode 100644
index 0000000000..bcbd621bb2
--- /dev/null
+++ b/sysdeps/mips/ieee754/ieee754.h
@@ -0,0 +1,323 @@
+/* Copyright (C) 1992-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _IEEE754_H
+
+#define _IEEE754_H 1
+#include <features.h>
+
+#include <endian.h>
+
+#include <float.h>
+
+__BEGIN_DECLS
+
+union ieee754_float
+ {
+ float f;
+
+ /* This is the IEEE 754 single-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:8;
+ unsigned int mantissa:23;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned int mantissa:23;
+ unsigned int exponent:8;
+ unsigned int negative:1;
+#endif /* Little endian. */
+ } ieee;
+
+ /* This format makes it easier to see if a NaN is a signalling NaN. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:8;
+ unsigned int quiet_nan:1;
+ unsigned int mantissa:22;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned int mantissa:22;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:8;
+ unsigned int negative:1;
+#endif /* Little endian. */
+ } ieee_nan;
+ };
+
+#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
+
+
+union ieee754_double
+ {
+ double d;
+
+ /* This is the IEEE 754 double-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:11;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:20;
+ unsigned int mantissa1:32;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int mantissa0:20;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+ unsigned int mantissa1:32;
+# else
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:20;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+# endif
+#endif /* Little endian. */
+ } ieee;
+
+ /* This format makes it easier to see if a NaN is a signalling NaN. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:11;
+ unsigned int quiet_nan:1;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:19;
+ unsigned int mantissa1:32;
+#else
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int mantissa0:19;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+ unsigned int mantissa1:32;
+# else
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:19;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+# endif
+#endif
+ } ieee_nan;
+ };
+
+#define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */
+
+#if LDBL_MANT_DIG == 113
+
+union ieee854_long_double
+ {
+ long double d;
+
+ /* This is the IEEE 854 quad-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:15;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:16;
+ unsigned int mantissa1:32;
+ unsigned int mantissa2:32;
+ unsigned int mantissa3:32;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa3:32;
+ unsigned int mantissa2:32;
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:16;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+#endif /* Little endian. */
+ } ieee;
+
+ /* This format makes it easier to see if a NaN is a signalling NaN. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:15;
+ unsigned int quiet_nan:1;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:15;
+ unsigned int mantissa1:32;
+ unsigned int mantissa2:32;
+ unsigned int mantissa3:32;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa3:32;
+ unsigned int mantissa2:32;
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:15;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+#endif /* Little endian. */
+ } ieee_nan;
+ };
+
+#define IEEE854_LONG_DOUBLE_BIAS 0x3fff /* Added to exponent. */
+
+#elif LDBL_MANT_DIG == 64
+
+union ieee854_long_double
+ {
+ long double d;
+
+ /* This is the IEEE 854 double-extended-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:15;
+ unsigned int empty:16;
+ unsigned int mantissa0:32;
+ unsigned int mantissa1:32;
+#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+ unsigned int mantissa0:32;
+ unsigned int mantissa1:32;
+# else
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:32;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+# endif
+#endif
+ } ieee;
+
+ /* This is for NaNs in the IEEE 854 double-extended-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:15;
+ unsigned int empty:16;
+ unsigned int one:1;
+ unsigned int quiet_nan:1;
+ unsigned int mantissa0:30;
+ unsigned int mantissa1:32;
+#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+ unsigned int mantissa0:30;
+ unsigned int quiet_nan:1;
+ unsigned int one:1;
+ unsigned int mantissa1:32;
+# else
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:30;
+ unsigned int quiet_nan:1;
+ unsigned int one:1;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+# endif
+#endif
+ } ieee_nan;
+ };
+
+#define IEEE854_LONG_DOUBLE_BIAS 0x3fff
+
+#elif LDBL_MANT_DIG == 53
+
+union ieee854_long_double
+ {
+ long double d;
+
+ /* This is the IEEE 754 double-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:11;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:20;
+ unsigned int mantissa1:32;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int mantissa0:20;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+ unsigned int mantissa1:32;
+# else
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:20;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+# endif
+#endif /* Little endian. */
+ } ieee;
+
+ /* This format makes it easier to see if a NaN is a signalling NaN. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:11;
+ unsigned int quiet_nan:1;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:19;
+ unsigned int mantissa1:32;
+#else
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int mantissa0:19;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+ unsigned int mantissa1:32;
+# else
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:19;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+# endif
+#endif
+ } ieee_nan;
+ };
+
+#define IEEE854_LONG_DOUBLE_BIAS 0x3ff /* Added to exponent. */
+
+#endif /* LDBL_MANT_DIG == 53 */
+
+__END_DECLS
+
+#endif /* ieee754.h */
diff --git a/sysdeps/mips/ieee754/s_fma.c b/sysdeps/mips/ieee754/s_fma.c
new file mode 100644
index 0000000000..574141416b
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fma.c
@@ -0,0 +1,5 @@
+#ifdef __mips_hard_float
+# include <sysdeps/ieee754/dbl-64/s_fma.c>
+#else
+# include <soft-fp/fmadf4.c>
+#endif
diff --git a/sysdeps/mips/ieee754/s_fmaf.c b/sysdeps/mips/ieee754/s_fmaf.c
new file mode 100644
index 0000000000..30bcdae620
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fmaf.c
@@ -0,0 +1,5 @@
+#ifdef __mips_hard_float
+# include <sysdeps/ieee754/dbl-64/s_fmaf.c>
+#else
+# include <soft-fp/fmasf4.c>
+#endif
diff --git a/sysdeps/mips/ieee754/s_fmal.c b/sysdeps/mips/ieee754/s_fmal.c
new file mode 100644
index 0000000000..6b83e914fe
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fmal.c
@@ -0,0 +1,7 @@
+#include <sgidefs.h>
+
+#if _MIPS_SIM == _ABIO32
+# error "long double fma being compiled for o32 ABI"
+#endif
+
+#include <soft-fp/fmatf4.c>
diff --git a/sysdeps/mips/include/sys/asm.h b/sysdeps/mips/include/sys/asm.h
new file mode 100644
index 0000000000..26ecf7725f
--- /dev/null
+++ b/sysdeps/mips/include/sys/asm.h
@@ -0,0 +1,53 @@
+/* Copyright (C) 2013-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _SYS_ASM_H
+
+# include_next <sys/asm.h>
+
+# undef __mips_cfi_startproc
+# define __mips_cfi_startproc cfi_startproc
+# undef __mips_cfi_endproc
+# define __mips_cfi_endproc cfi_endproc
+
+# if _MIPS_SIM == _ABIO32
+# define SETUP_GP64_REG_CFI(a)
+# define SETUP_GP64_REG(a, b)
+# define SETUP_GP64_STACK_CFI(a)
+# define SETUP_GP64_STACK(a, b)
+# define RESTORE_GP64_REG
+# define RESTORE_GP64_STACK
+# else
+# define SETUP_GP64_REG_CFI(gpsavereg) \
+ cfi_register (gp, gpsavereg)
+# define SETUP_GP64_REG(gpsavereg, proc) \
+ SETUP_GP64 (gpsavereg, proc); \
+ SETUP_GP64_REG_CFI (gpsavereg)
+# define SETUP_GP64_STACK_CFI(gpoffset) \
+ cfi_rel_offset (gp, gpoffset)
+# define SETUP_GP64_STACK(gpoffset, proc) \
+ SETUP_GP64 (gpoffset, proc); \
+ SETUP_GP64_STACK_CFI (gpoffset)
+# define RESTORE_GP64_REG \
+ RESTORE_GP64; \
+ cfi_restore (gp)
+# define RESTORE_GP64_STACK \
+ RESTORE_GP64; \
+ cfi_restore (gp)
+# endif
+
+#endif
diff --git a/sysdeps/mips/jmpbuf-unwind.h b/sysdeps/mips/jmpbuf-unwind.h
new file mode 100644
index 0000000000..fd1c6e647e
--- /dev/null
+++ b/sysdeps/mips/jmpbuf-unwind.h
@@ -0,0 +1,47 @@
+/* Copyright (C) 2003-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <setjmp.h>
+#include <stdint.h>
+#include <unwind.h>
+#include <sysdep.h>
+
+/* Test if longjmp to JMPBUF would unwind the frame
+ containing a local variable at ADDRESS. */
+#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \
+ ((void *) (address) < (void *) demangle ((jmpbuf)[0].__sp))
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
+ _JMPBUF_UNWINDS_ADJ (_jmpbuf, \
+ (void *) (_Unwind_Ptr) _Unwind_GetCFA (_context), \
+ _adj)
+
+static inline uintptr_t __attribute__ ((unused))
+_jmpbuf_sp (__jmp_buf regs)
+{
+ uintptr_t sp = (uintptr_t) regs[0].__sp;
+#ifdef PTR_DEMANGLE
+ PTR_DEMANGLE (sp);
+#endif
+ return sp;
+}
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+ ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
+
+/* We use the normal longjmp for unwinding. */
+#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val)
diff --git a/sysdeps/mips/ldsodefs.h b/sysdeps/mips/ldsodefs.h
new file mode 100644
index 0000000000..ad95de5648
--- /dev/null
+++ b/sysdeps/mips/ldsodefs.h
@@ -0,0 +1,149 @@
+/* Run-time dynamic linker data structures for loaded ELF shared objects.
+ Copyright (C) 2000-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _MIPS_LDSODEFS_H
+#define _MIPS_LDSODEFS_H 1
+
+#include <elf.h>
+
+struct La_mips_32_regs;
+struct La_mips_32_retval;
+struct La_mips_64_regs;
+struct La_mips_64_retval;
+
+#define ARCH_PLTENTER_MEMBERS \
+ Elf32_Addr (*mips_o32_gnu_pltenter) (Elf32_Sym *, unsigned int, \
+ uintptr_t *, uintptr_t *, \
+ struct La_mips_32_regs *, \
+ unsigned int *, const char *name, \
+ long int *framesizep); \
+ Elf32_Addr (*mips_n32_gnu_pltenter) (Elf32_Sym *, unsigned int, \
+ uintptr_t *, uintptr_t *, \
+ struct La_mips_64_regs *, \
+ unsigned int *, const char *name, \
+ long int *framesizep); \
+ Elf64_Addr (*mips_n64_gnu_pltenter) (Elf64_Sym *, unsigned int, \
+ uintptr_t *, uintptr_t *, \
+ struct La_mips_64_regs *, \
+ unsigned int *, const char *name, \
+ long int *framesizep);
+
+#define ARCH_PLTEXIT_MEMBERS \
+ unsigned int (*mips_o32_gnu_pltexit) (Elf32_Sym *, unsigned int, \
+ uintptr_t *, uintptr_t *, \
+ const struct La_mips_32_regs *, \
+ struct La_mips_32_retval *, \
+ const char *); \
+ unsigned int (*mips_n32_gnu_pltexit) (Elf32_Sym *, unsigned int, \
+ uintptr_t *, uintptr_t *, \
+ const struct La_mips_64_regs *, \
+ struct La_mips_64_retval *, \
+ const char *); \
+ unsigned int (*mips_n64_gnu_pltexit) (Elf64_Sym *, unsigned int, \
+ uintptr_t *, uintptr_t *, \
+ const struct La_mips_64_regs *, \
+ struct La_mips_64_retval *, \
+ const char *);
+
+/* The MIPS ABI specifies that the dynamic section has to be read-only. */
+
+#define DL_RO_DYN_SECTION 1
+
+#include_next <ldsodefs.h>
+
+/* The 64-bit MIPS ELF ABI uses an unusual reloc format. Each
+ relocation entry specifies up to three actual relocations, all at
+ the same address. The first relocation which required a symbol
+ uses the symbol in the r_sym field. The second relocation which
+ requires a symbol uses the symbol in the r_ssym field. If all
+ three relocations require a symbol, the third one uses a zero
+ value.
+
+ We define these structures in internal headers because we're not
+ sure we want to make them part of the ABI yet. Eventually, some of
+ this may move into elf/elf.h. */
+
+/* An entry in a 64 bit SHT_REL section. */
+
+typedef struct
+{
+ Elf32_Word r_sym; /* Symbol index */
+ unsigned char r_ssym; /* Special symbol for 2nd relocation */
+ unsigned char r_type3; /* 3rd relocation type */
+ unsigned char r_type2; /* 2nd relocation type */
+ unsigned char r_type1; /* 1st relocation type */
+} _Elf64_Mips_R_Info;
+
+typedef union
+{
+ Elf64_Xword r_info_number;
+ _Elf64_Mips_R_Info r_info_fields;
+} _Elf64_Mips_R_Info_union;
+
+typedef struct
+{
+ Elf64_Addr r_offset; /* Address */
+ _Elf64_Mips_R_Info_union r_info; /* Relocation type and symbol index */
+} Elf64_Mips_Rel;
+
+typedef struct
+{
+ Elf64_Addr r_offset; /* Address */
+ _Elf64_Mips_R_Info_union r_info; /* Relocation type and symbol index */
+ Elf64_Sxword r_addend; /* Addend */
+} Elf64_Mips_Rela;
+
+#define ELF64_MIPS_R_SYM(i) \
+ ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym)
+#define ELF64_MIPS_R_TYPE(i) \
+ (((_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_type1 \
+ | ((Elf32_Word)(__extension__ (_Elf64_Mips_R_Info_union)(i) \
+ ).r_info_fields.r_type2 << 8) \
+ | ((Elf32_Word)(__extension__ (_Elf64_Mips_R_Info_union)(i) \
+ ).r_info_fields.r_type3 << 16) \
+ | ((Elf32_Word)(__extension__ (_Elf64_Mips_R_Info_union)(i) \
+ ).r_info_fields.r_ssym << 24))
+#define ELF64_MIPS_R_INFO(sym, type) \
+ (__extension__ (_Elf64_Mips_R_Info_union) \
+ (__extension__ (_Elf64_Mips_R_Info) \
+ { (sym), ELF64_MIPS_R_SSYM (type), \
+ ELF64_MIPS_R_TYPE3 (type), \
+ ELF64_MIPS_R_TYPE2 (type), \
+ ELF64_MIPS_R_TYPE1 (type) \
+ }).r_info_number)
+/* These macros decompose the value returned by ELF64_MIPS_R_TYPE, and
+ compose it back into a value that it can be used as an argument to
+ ELF64_MIPS_R_INFO. */
+#define ELF64_MIPS_R_SSYM(i) (((i) >> 24) & 0xff)
+#define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff)
+#define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff)
+#define ELF64_MIPS_R_TYPE1(i) ((i) & 0xff)
+#define ELF64_MIPS_R_TYPEENC(type1, type2, type3, ssym) \
+ ((type1) \
+ | ((Elf32_Word)(type2) << 8) \
+ | ((Elf32_Word)(type3) << 16) \
+ | ((Elf32_Word)(ssym) << 24))
+
+#undef ELF64_R_SYM
+#define ELF64_R_SYM(i) ELF64_MIPS_R_SYM (i)
+#undef ELF64_R_TYPE
+#define ELF64_R_TYPE(i) ELF64_MIPS_R_TYPE (i)
+#undef ELF64_R_INFO
+#define ELF64_R_INFO(sym, type) ELF64_MIPS_R_INFO ((sym), (type))
+
+#endif
diff --git a/sysdeps/mips/libc-tls.c b/sysdeps/mips/libc-tls.c
new file mode 100644
index 0000000000..de7786dbc2
--- /dev/null
+++ b/sysdeps/mips/libc-tls.c
@@ -0,0 +1,32 @@
+/* Thread-local storage handling in the ELF dynamic linker. MIPS version.
+ Copyright (C) 2005-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <csu/libc-tls.c>
+#include <dl-tls.h>
+
+/* On MIPS, linker optimizations are not required, so __tls_get_addr
+ can be called even in statically linked binaries. In this case module
+ must be always 1 and PT_TLS segment exist in the binary, otherwise it
+ would not link. */
+
+void *
+__tls_get_addr (tls_index *ti)
+{
+ dtv_t *dtv = THREAD_DTV ();
+ return (char *) dtv[1].pointer.val + GET_ADDR_OFFSET;
+}
diff --git a/sysdeps/mips/lshift.S b/sysdeps/mips/lshift.S
new file mode 100644
index 0000000000..b20eb812b0
--- /dev/null
+++ b/sysdeps/mips/lshift.S
@@ -0,0 +1,97 @@
+/* MIPS2 __mpn_lshift --
+
+Copyright (C) 1995-2015 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the GNU MP Library. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+/* INPUT PARAMETERS
+ res_ptr $4
+ src_ptr $5
+ size $6
+ cnt $7
+*/
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (__mpn_lshift)
+ .set noreorder
+#ifdef __PIC__
+ .cpload t9
+#endif
+ .set nomacro
+
+ sll $2,$6,2
+ addu $5,$5,$2 /* make r5 point at end of src */
+ lw $10,-4($5) /* load first limb */
+ subu $13,$0,$7
+ addu $4,$4,$2 /* make r4 point at end of res */
+ addiu $6,$6,-1
+ and $9,$6,4-1 /* number of limbs in first loop */
+ beq $9,$0,L(L0) /* if multiple of 4 limbs, skip first loop */
+ srl $2,$10,$13 /* compute function result */
+
+ subu $6,$6,$9
+
+L(Loop0): lw $3,-8($5)
+ addiu $4,$4,-4
+ addiu $5,$5,-4
+ addiu $9,$9,-1
+ sll $11,$10,$7
+ srl $12,$3,$13
+ move $10,$3
+ or $8,$11,$12
+ bne $9,$0,L(Loop0)
+ sw $8,0($4)
+
+L(L0): beq $6,$0,L(Lend)
+ nop
+
+L(Loop): lw $3,-8($5)
+ addiu $4,$4,-16
+ addiu $6,$6,-4
+ sll $11,$10,$7
+ srl $12,$3,$13
+
+ lw $10,-12($5)
+ sll $14,$3,$7
+ or $8,$11,$12
+ sw $8,12($4)
+ srl $9,$10,$13
+
+ lw $3,-16($5)
+ sll $11,$10,$7
+ or $8,$14,$9
+ sw $8,8($4)
+ srl $12,$3,$13
+
+ lw $10,-20($5)
+ sll $14,$3,$7
+ or $8,$11,$12
+ sw $8,4($4)
+ srl $9,$10,$13
+
+ addiu $5,$5,-16
+ or $8,$14,$9
+ bgtz $6,L(Loop)
+ sw $8,0($4)
+
+L(Lend): sll $8,$10,$7
+ j $31
+ sw $8,-4($4)
+ END (__mpn_lshift)
diff --git a/sysdeps/mips/machine-gmon.h b/sysdeps/mips/machine-gmon.h
new file mode 100644
index 0000000000..ee2e3ea099
--- /dev/null
+++ b/sysdeps/mips/machine-gmon.h
@@ -0,0 +1,146 @@
+/* Machine-specific calling sequence for `mcount' profiling function. MIPS
+ Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sgidefs.h>
+
+#define _MCOUNT_DECL(frompc,selfpc) \
+static void __attribute_used__ __mcount (u_long frompc, u_long selfpc)
+
+/* Call __mcount with the return PC for our caller,
+ and the return PC our caller will return to. */
+
+#if _MIPS_SIM == _ABIO32
+
+#ifdef __PIC__
+# define CPLOAD ".cpload $25;"
+# define CPRESTORE ".cprestore 44\n\t"
+#else
+# define CPLOAD
+# define CPRESTORE
+#endif
+
+#define MCOUNT asm(\
+ ".globl _mcount;\n\t" \
+ ".align 2;\n\t" \
+ ".set push;\n\t" \
+ ".set nomips16;\n\t" \
+ ".type _mcount,@function;\n\t" \
+ ".ent _mcount\n\t" \
+ "_mcount:\n\t" \
+ ".frame $sp,44,$31\n\t" \
+ ".set noreorder;\n\t" \
+ ".set noat;\n\t" \
+ CPLOAD \
+ "subu $29,$29,48;\n\t" \
+ CPRESTORE \
+ "sw $4,24($29);\n\t" \
+ "sw $5,28($29);\n\t" \
+ "sw $6,32($29);\n\t" \
+ "sw $7,36($29);\n\t" \
+ "sw $2,40($29);\n\t" \
+ "sw $1,16($29);\n\t" \
+ "sw $31,20($29);\n\t" \
+ "move $5,$31;\n\t" \
+ "move $4,$1;\n\t" \
+ "jal __mcount;\n\t" \
+ "nop;\n\t" \
+ "lw $4,24($29);\n\t" \
+ "lw $5,28($29);\n\t" \
+ "lw $6,32($29);\n\t" \
+ "lw $7,36($29);\n\t" \
+ "lw $2,40($29);\n\t" \
+ "lw $31,20($29);\n\t" \
+ "lw $1,16($29);\n\t" \
+ "addu $29,$29,56;\n\t" \
+ "j $31;\n\t" \
+ "move $31,$1;\n\t" \
+ ".end _mcount;\n\t" \
+ ".set pop");
+
+#else
+
+#ifdef __PIC__
+# define CPSETUP ".cpsetup $25, 88, _mcount;"
+# define CPRETURN ".cpreturn;"
+#else
+# define CPSETUP
+# define CPRETURN
+#endif
+
+#if _MIPS_SIM == _ABIN32
+# if __mips_isa_rev < 6
+# define PTR_ADDU_STRING "add" /* no u */
+# define PTR_SUBU_STRING "sub" /* no u */
+# else
+# define PTR_ADDU_STRING "addu"
+# define PTR_SUBU_STRING "subu"
+# endif
+#elif _MIPS_SIM == _ABI64
+# define PTR_ADDU_STRING "daddu"
+# define PTR_SUBU_STRING "dsubu"
+#else
+# error "Unknown ABI"
+#endif
+
+#define MCOUNT asm(\
+ ".globl _mcount;\n\t" \
+ ".align 3;\n\t" \
+ ".set push;\n\t" \
+ ".set nomips16;\n\t" \
+ ".type _mcount,@function;\n\t" \
+ ".ent _mcount\n\t" \
+ "_mcount:\n\t" \
+ ".frame $sp,88,$31\n\t" \
+ ".set noreorder;\n\t" \
+ ".set noat;\n\t" \
+ PTR_SUBU_STRING " $29,$29,96;\n\t" \
+ CPSETUP \
+ "sd $4,24($29);\n\t" \
+ "sd $5,32($29);\n\t" \
+ "sd $6,40($29);\n\t" \
+ "sd $7,48($29);\n\t" \
+ "sd $8,56($29);\n\t" \
+ "sd $9,64($29);\n\t" \
+ "sd $10,72($29);\n\t" \
+ "sd $11,80($29);\n\t" \
+ "sd $2,16($29);\n\t" \
+ "sd $1,0($29);\n\t" \
+ "sd $31,8($29);\n\t" \
+ "move $5,$31;\n\t" \
+ "move $4,$1;\n\t" \
+ "jal __mcount;\n\t" \
+ "nop;\n\t" \
+ "ld $4,24($29);\n\t" \
+ "ld $5,32($29);\n\t" \
+ "ld $6,40($29);\n\t" \
+ "ld $7,48($29);\n\t" \
+ "ld $8,56($29);\n\t" \
+ "ld $9,64($29);\n\t" \
+ "ld $10,72($29);\n\t" \
+ "ld $11,80($29);\n\t" \
+ "ld $2,16($29);\n\t" \
+ "ld $31,8($29);\n\t" \
+ "ld $1,0($29);\n\t" \
+ CPRETURN \
+ PTR_ADDU_STRING " $29,$29,96;\n\t" \
+ "j $31;\n\t" \
+ "move $31,$1;\n\t" \
+ ".end _mcount;\n\t" \
+ ".set pop");
+
+#endif
diff --git a/sysdeps/mips/math-tests.h b/sysdeps/mips/math-tests.h
new file mode 100644
index 0000000000..d049ffff1a
--- /dev/null
+++ b/sysdeps/mips/math-tests.h
@@ -0,0 +1,38 @@
+/* Configuration for math tests. MIPS version.
+ Copyright (C) 2013-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <features.h>
+#include <sgidefs.h>
+
+/* MIPS soft float does not support exceptions and rounding modes, and
+ before GCC 4.9 long double when wider than double is implemented
+ using fp-bit which does not integrate with hardware exceptions and
+ rounding modes. */
+#ifdef __mips_soft_float
+# define ROUNDING_TESTS_float(MODE) ((MODE) == FE_TONEAREST)
+# define ROUNDING_TESTS_double(MODE) ((MODE) == FE_TONEAREST)
+# define ROUNDING_TESTS_long_double(MODE) ((MODE) == FE_TONEAREST)
+# define EXCEPTION_TESTS_float 0
+# define EXCEPTION_TESTS_double 0
+# define EXCEPTION_TESTS_long_double 0
+#elif _MIPS_SIM != _ABIO32 && !__GNUC_PREREQ (4, 9)
+# define ROUNDING_TESTS_long_double(MODE) ((MODE) == FE_TONEAREST)
+# define EXCEPTION_TESTS_long_double 0
+#endif
+
+#include_next <math-tests.h>
diff --git a/sysdeps/mips/math_private.h b/sysdeps/mips/math_private.h
new file mode 100644
index 0000000000..baa5f28fd2
--- /dev/null
+++ b/sysdeps/mips/math_private.h
@@ -0,0 +1,252 @@
+/* Internal math stuff. MIPS version.
+ Copyright (C) 2013-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _MATH_PRIVATE_H
+
+#ifdef __mips_nan2008
+/* MIPS aligned to IEEE 754-2008. */
+#else
+/* One of the few architectures where the meaning of the quiet/signaling bit is
+ inverse to IEEE 754-2008 (as well as common practice for IEEE 754-1985). */
+# define HIGH_ORDER_BIT_IS_SET_FOR_SNAN
+#endif
+
+/* Inline functions to speed up the math library implementation. The
+ default versions of these routines are in generic/math_private.h
+ and call fesetround, feholdexcept, etc. These routines use inlined
+ code instead. */
+
+#ifdef __mips_hard_float
+
+# include <fenv.h>
+# include <fenv_libc.h>
+# include <fpu_control.h>
+
+# define _FPU_MASK_ALL (_FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O \
+ |_FPU_MASK_U | _FPU_MASK_I | FE_ALL_EXCEPT)
+
+static __always_inline void
+libc_feholdexcept_mips (fenv_t *envp)
+{
+ fpu_control_t cw;
+
+ /* Save the current state. */
+ _FPU_GETCW (cw);
+ envp->__fp_control_register = cw;
+
+ /* Clear all exception enable bits and flags. */
+ cw &= ~(_FPU_MASK_ALL);
+ _FPU_SETCW (cw);
+}
+# define libc_feholdexcept libc_feholdexcept_mips
+# define libc_feholdexceptf libc_feholdexcept_mips
+# define libc_feholdexceptl libc_feholdexcept_mips
+
+static __always_inline void
+libc_fesetround_mips (int round)
+{
+ fpu_control_t cw;
+
+ /* Get current state. */
+ _FPU_GETCW (cw);
+
+ /* Set rounding bits. */
+ cw &= ~_FPU_RC_MASK;
+ cw |= round;
+
+ /* Set new state. */
+ _FPU_SETCW (cw);
+}
+# define libc_fesetround libc_fesetround_mips
+# define libc_fesetroundf libc_fesetround_mips
+# define libc_fesetroundl libc_fesetround_mips
+
+static __always_inline void
+libc_feholdexcept_setround_mips (fenv_t *envp, int round)
+{
+ fpu_control_t cw;
+
+ /* Save the current state. */
+ _FPU_GETCW (cw);
+ envp->__fp_control_register = cw;
+
+ /* Clear all exception enable bits and flags. */
+ cw &= ~(_FPU_MASK_ALL);
+
+ /* Set rounding bits. */
+ cw &= ~_FPU_RC_MASK;
+ cw |= round;
+
+ /* Set new state. */
+ _FPU_SETCW (cw);
+}
+# define libc_feholdexcept_setround libc_feholdexcept_setround_mips
+# define libc_feholdexcept_setroundf libc_feholdexcept_setround_mips
+# define libc_feholdexcept_setroundl libc_feholdexcept_setround_mips
+
+# define libc_feholdsetround libc_feholdexcept_setround_mips
+# define libc_feholdsetroundf libc_feholdexcept_setround_mips
+# define libc_feholdsetroundl libc_feholdexcept_setround_mips
+
+static __always_inline void
+libc_fesetenv_mips (fenv_t *envp)
+{
+ fpu_control_t cw;
+
+ /* Read current state to flush fpu pipeline. */
+ _FPU_GETCW (cw);
+
+ _FPU_SETCW (envp->__fp_control_register);
+}
+# define libc_fesetenv libc_fesetenv_mips
+# define libc_fesetenvf libc_fesetenv_mips
+# define libc_fesetenvl libc_fesetenv_mips
+
+static __always_inline int
+libc_feupdateenv_test_mips (fenv_t *envp, int excepts)
+{
+ /* int ret = fetestexcept (excepts); feupdateenv (envp); return ret; */
+ int cw, temp;
+
+ /* Get current control word. */
+ _FPU_GETCW (cw);
+
+ /* Set flag bits (which are accumulative), and *also* set the
+ cause bits. The setting of the cause bits is what actually causes
+ the hardware to generate the exception, if the corresponding enable
+ bit is set as well. */
+ temp = cw & FE_ALL_EXCEPT;
+ temp |= envp->__fp_control_register | (temp << CAUSE_SHIFT);
+
+ /* Set new state. */
+ _FPU_SETCW (temp);
+
+ return cw & excepts & FE_ALL_EXCEPT;
+}
+# define libc_feupdateenv_test libc_feupdateenv_test_mips
+# define libc_feupdateenv_testf libc_feupdateenv_test_mips
+# define libc_feupdateenv_testl libc_feupdateenv_test_mips
+
+static __always_inline void
+libc_feupdateenv_mips (fenv_t *envp)
+{
+ libc_feupdateenv_test_mips (envp, 0);
+}
+# define libc_feupdateenv libc_feupdateenv_mips
+# define libc_feupdateenvf libc_feupdateenv_mips
+# define libc_feupdateenvl libc_feupdateenv_mips
+
+# define libc_feresetround libc_feupdateenv_mips
+# define libc_feresetroundf libc_feupdateenv_mips
+# define libc_feresetroundl libc_feupdateenv_mips
+
+static __always_inline int
+libc_fetestexcept_mips (int excepts)
+{
+ int cw;
+
+ /* Get current control word. */
+ _FPU_GETCW (cw);
+
+ return cw & excepts & FE_ALL_EXCEPT;
+}
+# define libc_fetestexcept libc_fetestexcept_mips
+# define libc_fetestexceptf libc_fetestexcept_mips
+# define libc_fetestexceptl libc_fetestexcept_mips
+
+/* Enable support for rounding mode context. */
+# define HAVE_RM_CTX 1
+
+static __always_inline void
+libc_feholdexcept_setround_mips_ctx (struct rm_ctx *ctx, int round)
+{
+ fpu_control_t old, new;
+
+ /* Save the current state. */
+ _FPU_GETCW (old);
+ ctx->env.__fp_control_register = old;
+
+ /* Clear all exception enable bits and flags. */
+ new = old & ~(_FPU_MASK_ALL);
+
+ /* Set rounding bits. */
+ new = (new & ~_FPU_RC_MASK) | round;
+
+ if (__glibc_unlikely (new != old))
+ {
+ _FPU_SETCW (new);
+ ctx->updated_status = true;
+ }
+ else
+ ctx->updated_status = false;
+}
+# define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_mips_ctx
+# define libc_feholdexcept_setroundf_ctx libc_feholdexcept_setround_mips_ctx
+# define libc_feholdexcept_setroundl_ctx libc_feholdexcept_setround_mips_ctx
+
+static __always_inline void
+libc_fesetenv_mips_ctx (struct rm_ctx *ctx)
+{
+ libc_fesetenv_mips (&ctx->env);
+}
+# define libc_fesetenv_ctx libc_fesetenv_mips_ctx
+# define libc_fesetenvf_ctx libc_fesetenv_mips_ctx
+# define libc_fesetenvl_ctx libc_fesetenv_mips_ctx
+
+static __always_inline void
+libc_feupdateenv_mips_ctx (struct rm_ctx *ctx)
+{
+ if (__glibc_unlikely (ctx->updated_status))
+ libc_feupdateenv_test_mips (&ctx->env, 0);
+}
+# define libc_feupdateenv_ctx libc_feupdateenv_mips_ctx
+# define libc_feupdateenvf_ctx libc_feupdateenv_mips_ctx
+# define libc_feupdateenvl_ctx libc_feupdateenv_mips_ctx
+# define libc_feresetround_ctx libc_feupdateenv_mips_ctx
+# define libc_feresetroundf_ctx libc_feupdateenv_mips_ctx
+# define libc_feresetroundl_ctx libc_feupdateenv_mips_ctx
+
+static __always_inline void
+libc_feholdsetround_mips_ctx (struct rm_ctx *ctx, int round)
+{
+ fpu_control_t old, new;
+
+ /* Save the current state. */
+ _FPU_GETCW (old);
+ ctx->env.__fp_control_register = old;
+
+ /* Set rounding bits. */
+ new = (old & ~_FPU_RC_MASK) | round;
+
+ if (__glibc_unlikely (new != old))
+ {
+ _FPU_SETCW (new);
+ ctx->updated_status = true;
+ }
+ else
+ ctx->updated_status = false;
+}
+# define libc_feholdsetround_ctx libc_feholdsetround_mips_ctx
+# define libc_feholdsetroundf_ctx libc_feholdsetround_mips_ctx
+# define libc_feholdsetroundl_ctx libc_feholdsetround_mips_ctx
+
+#endif
+
+#include_next <math_private.h>
+
+#endif
diff --git a/sysdeps/mips/memcpy.S b/sysdeps/mips/memcpy.S
new file mode 100644
index 0000000000..c85935b811
--- /dev/null
+++ b/sysdeps/mips/memcpy.S
@@ -0,0 +1,827 @@
+/* Copyright (C) 2012-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef ANDROID_CHANGES
+# include "machine/asm.h"
+# include "machine/regdef.h"
+# define USE_MEMMOVE_FOR_OVERLAP
+# define PREFETCH_LOAD_HINT PREFETCH_HINT_LOAD_STREAMED
+# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
+#elif _LIBC
+# include <sysdep.h>
+# include <regdef.h>
+# include <sys/asm.h>
+# define PREFETCH_LOAD_HINT PREFETCH_HINT_LOAD_STREAMED
+# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
+#elif defined _COMPILING_NEWLIB
+# include "machine/asm.h"
+# include "machine/regdef.h"
+# define PREFETCH_LOAD_HINT PREFETCH_HINT_LOAD_STREAMED
+# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
+#else
+# include <regdef.h>
+# include <sys/asm.h>
+#endif
+
+#if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \
+ (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
+# ifndef DISABLE_PREFETCH
+# define USE_PREFETCH
+# endif
+#endif
+
+#if defined(_MIPS_SIM) && ((_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32))
+# ifndef DISABLE_DOUBLE
+# define USE_DOUBLE
+# endif
+#endif
+
+/* Some asm.h files do not have the L macro definition. */
+#ifndef L
+# if _MIPS_SIM == _ABIO32
+# define L(label) $L ## label
+# else
+# define L(label) .L ## label
+# endif
+#endif
+
+/* Some asm.h files do not have the PTR_ADDIU macro definition. */
+#ifndef PTR_ADDIU
+# ifdef USE_DOUBLE
+# define PTR_ADDIU daddiu
+# else
+# define PTR_ADDIU addiu
+# endif
+#endif
+
+/* Some asm.h files do not have the PTR_SRA macro definition. */
+#ifndef PTR_SRA
+# ifdef USE_DOUBLE
+# define PTR_SRA dsra
+# else
+# define PTR_SRA sra
+# endif
+#endif
+
+/* New R6 instructions that may not be in asm.h. */
+#ifndef PTR_LSA
+# if _MIPS_SIM == _ABI64
+# define PTR_LSA dlsa
+# else
+# define PTR_LSA lsa
+# endif
+#endif
+
+/*
+ * Using PREFETCH_HINT_LOAD_STREAMED instead of PREFETCH_LOAD on load
+ * prefetches appears to offer a slight preformance advantage.
+ *
+ * Using PREFETCH_HINT_PREPAREFORSTORE instead of PREFETCH_STORE
+ * or PREFETCH_STORE_STREAMED offers a large performance advantage
+ * but PREPAREFORSTORE has some special restrictions to consider.
+ *
+ * Prefetch with the 'prepare for store' hint does not copy a memory
+ * location into the cache, it just allocates a cache line and zeros
+ * it out. This means that if you do not write to the entire cache
+ * line before writing it out to memory some data will get zero'ed out
+ * when the cache line is written back to memory and data will be lost.
+ *
+ * Also if you are using this memcpy to copy overlapping buffers it may
+ * not behave correctly when using the 'prepare for store' hint. If you
+ * use the 'prepare for store' prefetch on a memory area that is in the
+ * memcpy source (as well as the memcpy destination), then you will get
+ * some data zero'ed out before you have a chance to read it and data will
+ * be lost.
+ *
+ * If you are going to use this memcpy routine with the 'prepare for store'
+ * prefetch you may want to set USE_MEMMOVE_FOR_OVERLAP in order to avoid
+ * the problem of running memcpy on overlapping buffers.
+ *
+ * There are ifdef'ed sections of this memcpy to make sure that it does not
+ * do prefetches on cache lines that are not going to be completely written.
+ * This code is only needed and only used when PREFETCH_STORE_HINT is set to
+ * PREFETCH_HINT_PREPAREFORSTORE. This code assumes that cache lines are
+ * 32 bytes and if the cache line is larger it will not work correctly.
+ */
+
+#ifdef USE_PREFETCH
+# define PREFETCH_HINT_LOAD 0
+# define PREFETCH_HINT_STORE 1
+# define PREFETCH_HINT_LOAD_STREAMED 4
+# define PREFETCH_HINT_STORE_STREAMED 5
+# define PREFETCH_HINT_LOAD_RETAINED 6
+# define PREFETCH_HINT_STORE_RETAINED 7
+# define PREFETCH_HINT_WRITEBACK_INVAL 25
+# define PREFETCH_HINT_PREPAREFORSTORE 30
+
+/*
+ * If we have not picked out what hints to use at this point use the
+ * standard load and store prefetch hints.
+ */
+# ifndef PREFETCH_STORE_HINT
+# define PREFETCH_STORE_HINT PREFETCH_HINT_STORE
+# endif
+# ifndef PREFETCH_LOAD_HINT
+# define PREFETCH_LOAD_HINT PREFETCH_HINT_LOAD
+# endif
+
+/*
+ * We double everything when USE_DOUBLE is true so we do 2 prefetches to
+ * get 64 bytes in that case. The assumption is that each individual
+ * prefetch brings in 32 bytes.
+ */
+
+# ifdef USE_DOUBLE
+# define PREFETCH_CHUNK 64
+# define PREFETCH_FOR_LOAD(chunk, reg) \
+ pref PREFETCH_LOAD_HINT, (chunk)*64(reg); \
+ pref PREFETCH_LOAD_HINT, ((chunk)*64)+32(reg)
+# define PREFETCH_FOR_STORE(chunk, reg) \
+ pref PREFETCH_STORE_HINT, (chunk)*64(reg); \
+ pref PREFETCH_STORE_HINT, ((chunk)*64)+32(reg)
+# else
+# define PREFETCH_CHUNK 32
+# define PREFETCH_FOR_LOAD(chunk, reg) \
+ pref PREFETCH_LOAD_HINT, (chunk)*32(reg)
+# define PREFETCH_FOR_STORE(chunk, reg) \
+ pref PREFETCH_STORE_HINT, (chunk)*32(reg)
+# endif
+/* MAX_PREFETCH_SIZE is the maximum size of a prefetch, it must not be less
+ * than PREFETCH_CHUNK, the assumed size of each prefetch. If the real size
+ * of a prefetch is greater than MAX_PREFETCH_SIZE and the PREPAREFORSTORE
+ * hint is used, the code will not work correctly. If PREPAREFORSTORE is not
+ * used then MAX_PREFETCH_SIZE does not matter. */
+# define MAX_PREFETCH_SIZE 128
+/* PREFETCH_LIMIT is set based on the fact that we never use an offset greater
+ * than 5 on a STORE prefetch and that a single prefetch can never be larger
+ * than MAX_PREFETCH_SIZE. We add the extra 32 when USE_DOUBLE is set because
+ * we actually do two prefetches in that case, one 32 bytes after the other. */
+# ifdef USE_DOUBLE
+# define PREFETCH_LIMIT (5 * PREFETCH_CHUNK) + 32 + MAX_PREFETCH_SIZE
+# else
+# define PREFETCH_LIMIT (5 * PREFETCH_CHUNK) + MAX_PREFETCH_SIZE
+# endif
+# if (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE) \
+ && ((PREFETCH_CHUNK * 4) < MAX_PREFETCH_SIZE)
+/* We cannot handle this because the initial prefetches may fetch bytes that
+ * are before the buffer being copied. We start copies with an offset
+ * of 4 so avoid this situation when using PREPAREFORSTORE. */
+#error "PREFETCH_CHUNK is too large and/or MAX_PREFETCH_SIZE is too small."
+# endif
+#else /* USE_PREFETCH not defined */
+# define PREFETCH_FOR_LOAD(offset, reg)
+# define PREFETCH_FOR_STORE(offset, reg)
+#endif
+
+#if __mips_isa_rev > 5
+# if (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+# undef PREFETCH_STORE_HINT
+# define PREFETCH_STORE_HINT PREFETCH_HINT_STORE_STREAMED
+# endif
+# define R6_CODE
+#endif
+
+/* Allow the routine to be named something else if desired. */
+#ifndef MEMCPY_NAME
+# define MEMCPY_NAME memcpy
+#endif
+
+/* We use these 32/64 bit registers as temporaries to do the copying. */
+#define REG0 t0
+#define REG1 t1
+#define REG2 t2
+#define REG3 t3
+#if defined(_MIPS_SIM) && ((_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABIO64))
+# define REG4 t4
+# define REG5 t5
+# define REG6 t6
+# define REG7 t7
+#else
+# define REG4 ta0
+# define REG5 ta1
+# define REG6 ta2
+# define REG7 ta3
+#endif
+
+/* We load/store 64 bits at a time when USE_DOUBLE is true.
+ * The C_ prefix stands for CHUNK and is used to avoid macro name
+ * conflicts with system header files. */
+
+#ifdef USE_DOUBLE
+# define C_ST sd
+# define C_LD ld
+# ifdef __MIPSEB
+# define C_LDHI ldl /* high part is left in big-endian */
+# define C_STHI sdl /* high part is left in big-endian */
+# define C_LDLO ldr /* low part is right in big-endian */
+# define C_STLO sdr /* low part is right in big-endian */
+# else
+# define C_LDHI ldr /* high part is right in little-endian */
+# define C_STHI sdr /* high part is right in little-endian */
+# define C_LDLO ldl /* low part is left in little-endian */
+# define C_STLO sdl /* low part is left in little-endian */
+# endif
+# define C_ALIGN dalign /* r6 align instruction */
+#else
+# define C_ST sw
+# define C_LD lw
+# ifdef __MIPSEB
+# define C_LDHI lwl /* high part is left in big-endian */
+# define C_STHI swl /* high part is left in big-endian */
+# define C_LDLO lwr /* low part is right in big-endian */
+# define C_STLO swr /* low part is right in big-endian */
+# else
+# define C_LDHI lwr /* high part is right in little-endian */
+# define C_STHI swr /* high part is right in little-endian */
+# define C_LDLO lwl /* low part is left in little-endian */
+# define C_STLO swl /* low part is left in little-endian */
+# endif
+# define C_ALIGN align /* r6 align instruction */
+#endif
+
+/* Bookkeeping values for 32 vs. 64 bit mode. */
+#ifdef USE_DOUBLE
+# define NSIZE 8
+# define NSIZEMASK 0x3f
+# define NSIZEDMASK 0x7f
+#else
+# define NSIZE 4
+# define NSIZEMASK 0x1f
+# define NSIZEDMASK 0x3f
+#endif
+#define UNIT(unit) ((unit)*NSIZE)
+#define UNITM1(unit) (((unit)*NSIZE)-1)
+
+#ifdef ANDROID_CHANGES
+LEAF(MEMCPY_NAME, 0)
+#else
+LEAF(MEMCPY_NAME)
+#endif
+ .set nomips16
+ .set noreorder
+/*
+ * Below we handle the case where memcpy is called with overlapping src and dst.
+ * Although memcpy is not required to handle this case, some parts of Android
+ * like Skia rely on such usage. We call memmove to handle such cases.
+ */
+#ifdef USE_MEMMOVE_FOR_OVERLAP
+ PTR_SUBU t0,a0,a1
+ PTR_SRA t2,t0,31
+ xor t1,t0,t2
+ PTR_SUBU t0,t1,t2
+ sltu t2,t0,a2
+ beq t2,zero,L(memcpy)
+ la t9,memmove
+ jr t9
+ nop
+L(memcpy):
+#endif
+/*
+ * If the size is less than 2*NSIZE (8 or 16), go to L(lastb). Regardless of
+ * size, copy dst pointer to v0 for the return value.
+ */
+ slti t2,a2,(2 * NSIZE)
+ bne t2,zero,L(lastb)
+#if defined(RETURN_FIRST_PREFETCH) || defined(RETURN_LAST_PREFETCH)
+ move v0,zero
+#else
+ move v0,a0
+#endif
+
+#ifndef R6_CODE
+
+/*
+ * If src and dst have different alignments, go to L(unaligned), if they
+ * have the same alignment (but are not actually aligned) do a partial
+ * load/store to make them aligned. If they are both already aligned
+ * we can start copying at L(aligned).
+ */
+ xor t8,a1,a0
+ andi t8,t8,(NSIZE-1) /* t8 is a0/a1 word-displacement */
+ bne t8,zero,L(unaligned)
+ PTR_SUBU a3, zero, a0
+
+ andi a3,a3,(NSIZE-1) /* copy a3 bytes to align a0/a1 */
+ beq a3,zero,L(aligned) /* if a3=0, it is already aligned */
+ PTR_SUBU a2,a2,a3 /* a2 is the remining bytes count */
+
+ C_LDHI t8,0(a1)
+ PTR_ADDU a1,a1,a3
+ C_STHI t8,0(a0)
+ PTR_ADDU a0,a0,a3
+
+#else /* R6_CODE */
+
+/*
+ * Align the destination and hope that the source gets aligned too. If it
+ * doesn't we jump to L(r6_unaligned*) to do unaligned copies using the r6
+ * align instruction.
+ */
+ andi t8,a0,7
+ lapc t9,L(atable)
+ PTR_LSA t9,t8,t9,2
+ jrc t9
+L(atable):
+ bc L(lb0)
+ bc L(lb7)
+ bc L(lb6)
+ bc L(lb5)
+ bc L(lb4)
+ bc L(lb3)
+ bc L(lb2)
+ bc L(lb1)
+L(lb7):
+ lb a3, 6(a1)
+ sb a3, 6(a0)
+L(lb6):
+ lb a3, 5(a1)
+ sb a3, 5(a0)
+L(lb5):
+ lb a3, 4(a1)
+ sb a3, 4(a0)
+L(lb4):
+ lb a3, 3(a1)
+ sb a3, 3(a0)
+L(lb3):
+ lb a3, 2(a1)
+ sb a3, 2(a0)
+L(lb2):
+ lb a3, 1(a1)
+ sb a3, 1(a0)
+L(lb1):
+ lb a3, 0(a1)
+ sb a3, 0(a0)
+
+ li t9,8
+ subu t8,t9,t8
+ PTR_SUBU a2,a2,t8
+ PTR_ADDU a0,a0,t8
+ PTR_ADDU a1,a1,t8
+L(lb0):
+
+ andi t8,a1,(NSIZE-1)
+ lapc t9,L(jtable)
+ PTR_LSA t9,t8,t9,2
+ jrc t9
+L(jtable):
+ bc L(aligned)
+ bc L(r6_unaligned1)
+ bc L(r6_unaligned2)
+ bc L(r6_unaligned3)
+# ifdef USE_DOUBLE
+ bc L(r6_unaligned4)
+ bc L(r6_unaligned5)
+ bc L(r6_unaligned6)
+ bc L(r6_unaligned7)
+# endif
+#endif /* R6_CODE */
+
+L(aligned):
+
+/*
+ * Now dst/src are both aligned to (word or double word) aligned addresses
+ * Set a2 to count how many bytes we have to copy after all the 64/128 byte
+ * chunks are copied and a3 to the dst pointer after all the 64/128 byte
+ * chunks have been copied. We will loop, incrementing a0 and a1 until a0
+ * equals a3.
+ */
+
+ andi t8,a2,NSIZEDMASK /* any whole 64-byte/128-byte chunks? */
+ beq a2,t8,L(chkw) /* if a2==t8, no 64-byte/128-byte chunks */
+ PTR_SUBU a3,a2,t8 /* subtract from a2 the reminder */
+ PTR_ADDU a3,a0,a3 /* Now a3 is the final dst after loop */
+
+/* When in the loop we may prefetch with the 'prepare to store' hint,
+ * in this case the a0+x should not be past the "t0-32" address. This
+ * means: for x=128 the last "safe" a0 address is "t0-160". Alternatively,
+ * for x=64 the last "safe" a0 address is "t0-96" In the current version we
+ * will use "prefetch hint,128(a0)", so "t0-160" is the limit.
+ */
+#if defined(USE_PREFETCH) && (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+ PTR_ADDU t0,a0,a2 /* t0 is the "past the end" address */
+ PTR_SUBU t9,t0,PREFETCH_LIMIT /* t9 is the "last safe pref" address */
+#endif
+ PREFETCH_FOR_LOAD (0, a1)
+ PREFETCH_FOR_LOAD (1, a1)
+ PREFETCH_FOR_LOAD (2, a1)
+ PREFETCH_FOR_LOAD (3, a1)
+#if defined(USE_PREFETCH) && (PREFETCH_STORE_HINT != PREFETCH_HINT_PREPAREFORSTORE)
+ PREFETCH_FOR_STORE (1, a0)
+ PREFETCH_FOR_STORE (2, a0)
+ PREFETCH_FOR_STORE (3, a0)
+#endif
+#if defined(RETURN_FIRST_PREFETCH) && defined(USE_PREFETCH)
+# if PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE
+ sltu v1,t9,a0
+ bgtz v1,L(skip_set)
+ nop
+ PTR_ADDIU v0,a0,(PREFETCH_CHUNK*4)
+L(skip_set):
+# else
+ PTR_ADDIU v0,a0,(PREFETCH_CHUNK*1)
+# endif
+#endif
+#if defined(RETURN_LAST_PREFETCH) && defined(USE_PREFETCH) \
+ && (PREFETCH_STORE_HINT != PREFETCH_HINT_PREPAREFORSTORE)
+ PTR_ADDIU v0,a0,(PREFETCH_CHUNK*3)
+# ifdef USE_DOUBLE
+ PTR_ADDIU v0,v0,32
+# endif
+#endif
+L(loop16w):
+ C_LD t0,UNIT(0)(a1)
+#if defined(USE_PREFETCH) && (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+ sltu v1,t9,a0 /* If a0 > t9 don't use next prefetch */
+ bgtz v1,L(skip_pref)
+#endif
+ C_LD t1,UNIT(1)(a1)
+#ifdef R6_CODE
+ PREFETCH_FOR_STORE (2, a0)
+#else
+ PREFETCH_FOR_STORE (4, a0)
+ PREFETCH_FOR_STORE (5, a0)
+#endif
+#if defined(RETURN_LAST_PREFETCH) && defined(USE_PREFETCH)
+ PTR_ADDIU v0,a0,(PREFETCH_CHUNK*5)
+# ifdef USE_DOUBLE
+ PTR_ADDIU v0,v0,32
+# endif
+#endif
+L(skip_pref):
+ C_LD REG2,UNIT(2)(a1)
+ C_LD REG3,UNIT(3)(a1)
+ C_LD REG4,UNIT(4)(a1)
+ C_LD REG5,UNIT(5)(a1)
+ C_LD REG6,UNIT(6)(a1)
+ C_LD REG7,UNIT(7)(a1)
+#ifdef R6_CODE
+ PREFETCH_FOR_LOAD (3, a1)
+#else
+ PREFETCH_FOR_LOAD (4, a1)
+#endif
+ C_ST t0,UNIT(0)(a0)
+ C_ST t1,UNIT(1)(a0)
+ C_ST REG2,UNIT(2)(a0)
+ C_ST REG3,UNIT(3)(a0)
+ C_ST REG4,UNIT(4)(a0)
+ C_ST REG5,UNIT(5)(a0)
+ C_ST REG6,UNIT(6)(a0)
+ C_ST REG7,UNIT(7)(a0)
+
+ C_LD t0,UNIT(8)(a1)
+ C_LD t1,UNIT(9)(a1)
+ C_LD REG2,UNIT(10)(a1)
+ C_LD REG3,UNIT(11)(a1)
+ C_LD REG4,UNIT(12)(a1)
+ C_LD REG5,UNIT(13)(a1)
+ C_LD REG6,UNIT(14)(a1)
+ C_LD REG7,UNIT(15)(a1)
+#ifndef R6_CODE
+ PREFETCH_FOR_LOAD (5, a1)
+#endif
+ C_ST t0,UNIT(8)(a0)
+ C_ST t1,UNIT(9)(a0)
+ C_ST REG2,UNIT(10)(a0)
+ C_ST REG3,UNIT(11)(a0)
+ C_ST REG4,UNIT(12)(a0)
+ C_ST REG5,UNIT(13)(a0)
+ C_ST REG6,UNIT(14)(a0)
+ C_ST REG7,UNIT(15)(a0)
+ PTR_ADDIU a0,a0,UNIT(16) /* adding 64/128 to dest */
+ bne a0,a3,L(loop16w)
+ PTR_ADDIU a1,a1,UNIT(16) /* adding 64/128 to src */
+ move a2,t8
+
+/* Here we have src and dest word-aligned but less than 64-bytes or
+ * 128 bytes to go. Check for a 32(64) byte chunk and copy if if there
+ * is one. Otherwise jump down to L(chk1w) to handle the tail end of
+ * the copy.
+ */
+
+L(chkw):
+ PREFETCH_FOR_LOAD (0, a1)
+ andi t8,a2,NSIZEMASK /* Is there a 32-byte/64-byte chunk. */
+ /* The t8 is the reminder count past 32-bytes */
+ beq a2,t8,L(chk1w) /* When a2=t8, no 32-byte chunk */
+ nop
+ C_LD t0,UNIT(0)(a1)
+ C_LD t1,UNIT(1)(a1)
+ C_LD REG2,UNIT(2)(a1)
+ C_LD REG3,UNIT(3)(a1)
+ C_LD REG4,UNIT(4)(a1)
+ C_LD REG5,UNIT(5)(a1)
+ C_LD REG6,UNIT(6)(a1)
+ C_LD REG7,UNIT(7)(a1)
+ PTR_ADDIU a1,a1,UNIT(8)
+ C_ST t0,UNIT(0)(a0)
+ C_ST t1,UNIT(1)(a0)
+ C_ST REG2,UNIT(2)(a0)
+ C_ST REG3,UNIT(3)(a0)
+ C_ST REG4,UNIT(4)(a0)
+ C_ST REG5,UNIT(5)(a0)
+ C_ST REG6,UNIT(6)(a0)
+ C_ST REG7,UNIT(7)(a0)
+ PTR_ADDIU a0,a0,UNIT(8)
+
+/*
+ * Here we have less than 32(64) bytes to copy. Set up for a loop to
+ * copy one word (or double word) at a time. Set a2 to count how many
+ * bytes we have to copy after all the word (or double word) chunks are
+ * copied and a3 to the dst pointer after all the (d)word chunks have
+ * been copied. We will loop, incrementing a0 and a1 until a0 equals a3.
+ */
+L(chk1w):
+ andi a2,t8,(NSIZE-1) /* a2 is the reminder past one (d)word chunks */
+ beq a2,t8,L(lastb)
+ PTR_SUBU a3,t8,a2 /* a3 is count of bytes in one (d)word chunks */
+ PTR_ADDU a3,a0,a3 /* a3 is the dst address after loop */
+
+/* copying in words (4-byte or 8-byte chunks) */
+L(wordCopy_loop):
+ C_LD REG3,UNIT(0)(a1)
+ PTR_ADDIU a0,a0,UNIT(1)
+ PTR_ADDIU a1,a1,UNIT(1)
+ bne a0,a3,L(wordCopy_loop)
+ C_ST REG3,UNIT(-1)(a0)
+
+/* Copy the last 8 (or 16) bytes */
+L(lastb):
+ blez a2,L(leave)
+ PTR_ADDU a3,a0,a2 /* a3 is the last dst address */
+L(lastbloop):
+ lb v1,0(a1)
+ PTR_ADDIU a0,a0,1
+ PTR_ADDIU a1,a1,1
+ bne a0,a3,L(lastbloop)
+ sb v1,-1(a0)
+L(leave):
+ j ra
+ nop
+
+#ifndef R6_CODE
+/*
+ * UNALIGNED case, got here with a3 = "negu a0"
+ * This code is nearly identical to the aligned code above
+ * but only the destination (not the source) gets aligned
+ * so we need to do partial loads of the source followed
+ * by normal stores to the destination (once we have aligned
+ * the destination).
+ */
+
+L(unaligned):
+ andi a3,a3,(NSIZE-1) /* copy a3 bytes to align a0/a1 */
+ beqz a3,L(ua_chk16w) /* if a3=0, it is already aligned */
+ PTR_SUBU a2,a2,a3 /* a2 is the remining bytes count */
+
+ C_LDHI v1,UNIT(0)(a1)
+ C_LDLO v1,UNITM1(1)(a1)
+ PTR_ADDU a1,a1,a3
+ C_STHI v1,UNIT(0)(a0)
+ PTR_ADDU a0,a0,a3
+
+/*
+ * Now the destination (but not the source) is aligned
+ * Set a2 to count how many bytes we have to copy after all the 64/128 byte
+ * chunks are copied and a3 to the dst pointer after all the 64/128 byte
+ * chunks have been copied. We will loop, incrementing a0 and a1 until a0
+ * equals a3.
+ */
+
+L(ua_chk16w):
+ andi t8,a2,NSIZEDMASK /* any whole 64-byte/128-byte chunks? */
+ beq a2,t8,L(ua_chkw) /* if a2==t8, no 64-byte/128-byte chunks */
+ PTR_SUBU a3,a2,t8 /* subtract from a2 the reminder */
+ PTR_ADDU a3,a0,a3 /* Now a3 is the final dst after loop */
+
+# if defined(USE_PREFETCH) && (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+ PTR_ADDU t0,a0,a2 /* t0 is the "past the end" address */
+ PTR_SUBU t9,t0,PREFETCH_LIMIT /* t9 is the "last safe pref" address */
+# endif
+ PREFETCH_FOR_LOAD (0, a1)
+ PREFETCH_FOR_LOAD (1, a1)
+ PREFETCH_FOR_LOAD (2, a1)
+# if defined(USE_PREFETCH) && (PREFETCH_STORE_HINT != PREFETCH_HINT_PREPAREFORSTORE)
+ PREFETCH_FOR_STORE (1, a0)
+ PREFETCH_FOR_STORE (2, a0)
+ PREFETCH_FOR_STORE (3, a0)
+# endif
+# if defined(RETURN_FIRST_PREFETCH) && defined(USE_PREFETCH)
+# if (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+ sltu v1,t9,a0
+ bgtz v1,L(ua_skip_set)
+ nop
+ PTR_ADDIU v0,a0,(PREFETCH_CHUNK*4)
+L(ua_skip_set):
+# else
+ PTR_ADDIU v0,a0,(PREFETCH_CHUNK*1)
+# endif
+# endif
+L(ua_loop16w):
+ PREFETCH_FOR_LOAD (3, a1)
+ C_LDHI t0,UNIT(0)(a1)
+ C_LDHI t1,UNIT(1)(a1)
+ C_LDHI REG2,UNIT(2)(a1)
+# if defined(USE_PREFETCH) && (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+ sltu v1,t9,a0
+ bgtz v1,L(ua_skip_pref)
+# endif
+ C_LDHI REG3,UNIT(3)(a1)
+ PREFETCH_FOR_STORE (4, a0)
+ PREFETCH_FOR_STORE (5, a0)
+L(ua_skip_pref):
+ C_LDHI REG4,UNIT(4)(a1)
+ C_LDHI REG5,UNIT(5)(a1)
+ C_LDHI REG6,UNIT(6)(a1)
+ C_LDHI REG7,UNIT(7)(a1)
+ C_LDLO t0,UNITM1(1)(a1)
+ C_LDLO t1,UNITM1(2)(a1)
+ C_LDLO REG2,UNITM1(3)(a1)
+ C_LDLO REG3,UNITM1(4)(a1)
+ C_LDLO REG4,UNITM1(5)(a1)
+ C_LDLO REG5,UNITM1(6)(a1)
+ C_LDLO REG6,UNITM1(7)(a1)
+ C_LDLO REG7,UNITM1(8)(a1)
+ PREFETCH_FOR_LOAD (4, a1)
+ C_ST t0,UNIT(0)(a0)
+ C_ST t1,UNIT(1)(a0)
+ C_ST REG2,UNIT(2)(a0)
+ C_ST REG3,UNIT(3)(a0)
+ C_ST REG4,UNIT(4)(a0)
+ C_ST REG5,UNIT(5)(a0)
+ C_ST REG6,UNIT(6)(a0)
+ C_ST REG7,UNIT(7)(a0)
+ C_LDHI t0,UNIT(8)(a1)
+ C_LDHI t1,UNIT(9)(a1)
+ C_LDHI REG2,UNIT(10)(a1)
+ C_LDHI REG3,UNIT(11)(a1)
+ C_LDHI REG4,UNIT(12)(a1)
+ C_LDHI REG5,UNIT(13)(a1)
+ C_LDHI REG6,UNIT(14)(a1)
+ C_LDHI REG7,UNIT(15)(a1)
+ C_LDLO t0,UNITM1(9)(a1)
+ C_LDLO t1,UNITM1(10)(a1)
+ C_LDLO REG2,UNITM1(11)(a1)
+ C_LDLO REG3,UNITM1(12)(a1)
+ C_LDLO REG4,UNITM1(13)(a1)
+ C_LDLO REG5,UNITM1(14)(a1)
+ C_LDLO REG6,UNITM1(15)(a1)
+ C_LDLO REG7,UNITM1(16)(a1)
+ PREFETCH_FOR_LOAD (5, a1)
+ C_ST t0,UNIT(8)(a0)
+ C_ST t1,UNIT(9)(a0)
+ C_ST REG2,UNIT(10)(a0)
+ C_ST REG3,UNIT(11)(a0)
+ C_ST REG4,UNIT(12)(a0)
+ C_ST REG5,UNIT(13)(a0)
+ C_ST REG6,UNIT(14)(a0)
+ C_ST REG7,UNIT(15)(a0)
+ PTR_ADDIU a0,a0,UNIT(16) /* adding 64/128 to dest */
+ bne a0,a3,L(ua_loop16w)
+ PTR_ADDIU a1,a1,UNIT(16) /* adding 64/128 to src */
+ move a2,t8
+
+/* Here we have src and dest word-aligned but less than 64-bytes or
+ * 128 bytes to go. Check for a 32(64) byte chunk and copy if if there
+ * is one. Otherwise jump down to L(ua_chk1w) to handle the tail end of
+ * the copy. */
+
+L(ua_chkw):
+ PREFETCH_FOR_LOAD (0, a1)
+ andi t8,a2,NSIZEMASK /* Is there a 32-byte/64-byte chunk. */
+ /* t8 is the reminder count past 32-bytes */
+ beq a2,t8,L(ua_chk1w) /* When a2=t8, no 32-byte chunk */
+ nop
+ C_LDHI t0,UNIT(0)(a1)
+ C_LDHI t1,UNIT(1)(a1)
+ C_LDHI REG2,UNIT(2)(a1)
+ C_LDHI REG3,UNIT(3)(a1)
+ C_LDHI REG4,UNIT(4)(a1)
+ C_LDHI REG5,UNIT(5)(a1)
+ C_LDHI REG6,UNIT(6)(a1)
+ C_LDHI REG7,UNIT(7)(a1)
+ C_LDLO t0,UNITM1(1)(a1)
+ C_LDLO t1,UNITM1(2)(a1)
+ C_LDLO REG2,UNITM1(3)(a1)
+ C_LDLO REG3,UNITM1(4)(a1)
+ C_LDLO REG4,UNITM1(5)(a1)
+ C_LDLO REG5,UNITM1(6)(a1)
+ C_LDLO REG6,UNITM1(7)(a1)
+ C_LDLO REG7,UNITM1(8)(a1)
+ PTR_ADDIU a1,a1,UNIT(8)
+ C_ST t0,UNIT(0)(a0)
+ C_ST t1,UNIT(1)(a0)
+ C_ST REG2,UNIT(2)(a0)
+ C_ST REG3,UNIT(3)(a0)
+ C_ST REG4,UNIT(4)(a0)
+ C_ST REG5,UNIT(5)(a0)
+ C_ST REG6,UNIT(6)(a0)
+ C_ST REG7,UNIT(7)(a0)
+ PTR_ADDIU a0,a0,UNIT(8)
+/*
+ * Here we have less than 32(64) bytes to copy. Set up for a loop to
+ * copy one word (or double word) at a time.
+ */
+L(ua_chk1w):
+ andi a2,t8,(NSIZE-1) /* a2 is the reminder past one (d)word chunks */
+ beq a2,t8,L(ua_smallCopy)
+ PTR_SUBU a3,t8,a2 /* a3 is count of bytes in one (d)word chunks */
+ PTR_ADDU a3,a0,a3 /* a3 is the dst address after loop */
+
+/* copying in words (4-byte or 8-byte chunks) */
+L(ua_wordCopy_loop):
+ C_LDHI v1,UNIT(0)(a1)
+ C_LDLO v1,UNITM1(1)(a1)
+ PTR_ADDIU a0,a0,UNIT(1)
+ PTR_ADDIU a1,a1,UNIT(1)
+ bne a0,a3,L(ua_wordCopy_loop)
+ C_ST v1,UNIT(-1)(a0)
+
+/* Copy the last 8 (or 16) bytes */
+L(ua_smallCopy):
+ beqz a2,L(leave)
+ PTR_ADDU a3,a0,a2 /* a3 is the last dst address */
+L(ua_smallCopy_loop):
+ lb v1,0(a1)
+ PTR_ADDIU a0,a0,1
+ PTR_ADDIU a1,a1,1
+ bne a0,a3,L(ua_smallCopy_loop)
+ sb v1,-1(a0)
+
+ j ra
+ nop
+
+#else /* R6_CODE */
+
+# ifdef __MIPSEB
+# define SWAP_REGS(X,Y) X, Y
+# define ALIGN_OFFSET(N) (N)
+# else
+# define SWAP_REGS(X,Y) Y, X
+# define ALIGN_OFFSET(N) (NSIZE-N)
+# endif
+# define R6_UNALIGNED_WORD_COPY(BYTEOFFSET) \
+ andi REG7, a2, (NSIZE-1);/* REG7 is # of bytes to by bytes. */ \
+ beq REG7, a2, L(lastb); /* Check for bytes to copy by word */ \
+ PTR_SUBU a3, a2, REG7; /* a3 is number of bytes to be copied in */ \
+ /* (d)word chunks. */ \
+ move a2, REG7; /* a2 is # of bytes to copy byte by byte */ \
+ /* after word loop is finished. */ \
+ PTR_ADDU REG6, a0, a3; /* REG6 is the dst address after loop. */ \
+ PTR_SUBU REG2, a1, t8; /* REG2 is the aligned src address. */ \
+ PTR_ADDU a1, a1, a3; /* a1 is addr of source after word loop. */ \
+ C_LD t0, UNIT(0)(REG2); /* Load first part of source. */ \
+L(r6_ua_wordcopy##BYTEOFFSET): \
+ C_LD t1, UNIT(1)(REG2); /* Load second part of source. */ \
+ C_ALIGN REG3, SWAP_REGS(t1,t0), ALIGN_OFFSET(BYTEOFFSET); \
+ PTR_ADDIU a0, a0, UNIT(1); /* Increment destination pointer. */ \
+ PTR_ADDIU REG2, REG2, UNIT(1); /* Increment aligned source pointer.*/ \
+ move t0, t1; /* Move second part of source to first. */ \
+ bne a0, REG6,L(r6_ua_wordcopy##BYTEOFFSET); \
+ C_ST REG3, UNIT(-1)(a0); \
+ j L(lastb); \
+ nop
+
+ /* We are generating R6 code, the destination is 4 byte aligned and
+ the source is not 4 byte aligned. t8 is 1, 2, or 3 depending on the
+ alignment of the source. */
+
+L(r6_unaligned1):
+ R6_UNALIGNED_WORD_COPY(1)
+L(r6_unaligned2):
+ R6_UNALIGNED_WORD_COPY(2)
+L(r6_unaligned3):
+ R6_UNALIGNED_WORD_COPY(3)
+# ifdef USE_DOUBLE
+L(r6_unaligned4):
+ R6_UNALIGNED_WORD_COPY(4)
+L(r6_unaligned5):
+ R6_UNALIGNED_WORD_COPY(5)
+L(r6_unaligned6):
+ R6_UNALIGNED_WORD_COPY(6)
+L(r6_unaligned7):
+ R6_UNALIGNED_WORD_COPY(7)
+# endif
+#endif /* R6_CODE */
+
+ .set at
+ .set reorder
+END(MEMCPY_NAME)
+#ifndef ANDROID_CHANGES
+# ifdef _LIBC
+libc_hidden_builtin_def (MEMCPY_NAME)
+# endif
+#endif
diff --git a/sysdeps/mips/memset.S b/sysdeps/mips/memset.S
new file mode 100644
index 0000000000..864ab07c38
--- /dev/null
+++ b/sysdeps/mips/memset.S
@@ -0,0 +1,426 @@
+/* Copyright (C) 2013-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef ANDROID_CHANGES
+# include "machine/asm.h"
+# include "machine/regdef.h"
+# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
+#elif _LIBC
+# include <sysdep.h>
+# include <regdef.h>
+# include <sys/asm.h>
+# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
+#elif defined _COMPILING_NEWLIB
+# include "machine/asm.h"
+# include "machine/regdef.h"
+# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
+#else
+# include <regdef.h>
+# include <sys/asm.h>
+#endif
+
+/* Check to see if the MIPS architecture we are compiling for supports
+ prefetching. */
+
+#if (__mips == 4) || (__mips == 5) || (__mips == 32) || (__mips == 64)
+# ifndef DISABLE_PREFETCH
+# define USE_PREFETCH
+# endif
+#endif
+
+#if defined(_MIPS_SIM) && ((_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32))
+# ifndef DISABLE_DOUBLE
+# define USE_DOUBLE
+# endif
+#endif
+
+#ifndef USE_DOUBLE
+# ifndef DISABLE_DOUBLE_ALIGN
+# define DOUBLE_ALIGN
+# endif
+#endif
+
+
+/* Some asm.h files do not have the L macro definition. */
+#ifndef L
+# if _MIPS_SIM == _ABIO32
+# define L(label) $L ## label
+# else
+# define L(label) .L ## label
+# endif
+#endif
+
+/* Some asm.h files do not have the PTR_ADDIU macro definition. */
+#ifndef PTR_ADDIU
+# ifdef USE_DOUBLE
+# define PTR_ADDIU daddiu
+# else
+# define PTR_ADDIU addiu
+# endif
+#endif
+
+/* New R6 instructions that may not be in asm.h. */
+#ifndef PTR_LSA
+# if _MIPS_SIM == _ABI64
+# define PTR_LSA dlsa
+# else
+# define PTR_LSA lsa
+# endif
+#endif
+
+/* Using PREFETCH_HINT_PREPAREFORSTORE instead of PREFETCH_STORE
+ or PREFETCH_STORE_STREAMED offers a large performance advantage
+ but PREPAREFORSTORE has some special restrictions to consider.
+
+ Prefetch with the 'prepare for store' hint does not copy a memory
+ location into the cache, it just allocates a cache line and zeros
+ it out. This means that if you do not write to the entire cache
+ line before writing it out to memory some data will get zero'ed out
+ when the cache line is written back to memory and data will be lost.
+
+ There are ifdef'ed sections of this memcpy to make sure that it does not
+ do prefetches on cache lines that are not going to be completely written.
+ This code is only needed and only used when PREFETCH_STORE_HINT is set to
+ PREFETCH_HINT_PREPAREFORSTORE. This code assumes that cache lines are
+ less than MAX_PREFETCH_SIZE bytes and if the cache line is larger it will
+ not work correctly. */
+
+#ifdef USE_PREFETCH
+# define PREFETCH_HINT_STORE 1
+# define PREFETCH_HINT_STORE_STREAMED 5
+# define PREFETCH_HINT_STORE_RETAINED 7
+# define PREFETCH_HINT_PREPAREFORSTORE 30
+
+/* If we have not picked out what hints to use at this point use the
+ standard load and store prefetch hints. */
+# ifndef PREFETCH_STORE_HINT
+# define PREFETCH_STORE_HINT PREFETCH_HINT_STORE
+# endif
+
+/* We double everything when USE_DOUBLE is true so we do 2 prefetches to
+ get 64 bytes in that case. The assumption is that each individual
+ prefetch brings in 32 bytes. */
+# ifdef USE_DOUBLE
+# define PREFETCH_CHUNK 64
+# define PREFETCH_FOR_STORE(chunk, reg) \
+ pref PREFETCH_STORE_HINT, (chunk)*64(reg); \
+ pref PREFETCH_STORE_HINT, ((chunk)*64)+32(reg)
+# else
+# define PREFETCH_CHUNK 32
+# define PREFETCH_FOR_STORE(chunk, reg) \
+ pref PREFETCH_STORE_HINT, (chunk)*32(reg)
+# endif
+
+/* MAX_PREFETCH_SIZE is the maximum size of a prefetch, it must not be less
+ than PREFETCH_CHUNK, the assumed size of each prefetch. If the real size
+ of a prefetch is greater than MAX_PREFETCH_SIZE and the PREPAREFORSTORE
+ hint is used, the code will not work correctly. If PREPAREFORSTORE is not
+ used than MAX_PREFETCH_SIZE does not matter. */
+# define MAX_PREFETCH_SIZE 128
+/* PREFETCH_LIMIT is set based on the fact that we never use an offset greater
+ than 5 on a STORE prefetch and that a single prefetch can never be larger
+ than MAX_PREFETCH_SIZE. We add the extra 32 when USE_DOUBLE is set because
+ we actually do two prefetches in that case, one 32 bytes after the other. */
+# ifdef USE_DOUBLE
+# define PREFETCH_LIMIT (5 * PREFETCH_CHUNK) + 32 + MAX_PREFETCH_SIZE
+# else
+# define PREFETCH_LIMIT (5 * PREFETCH_CHUNK) + MAX_PREFETCH_SIZE
+# endif
+
+# if (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE) \
+ && ((PREFETCH_CHUNK * 4) < MAX_PREFETCH_SIZE)
+/* We cannot handle this because the initial prefetches may fetch bytes that
+ are before the buffer being copied. We start copies with an offset
+ of 4 so avoid this situation when using PREPAREFORSTORE. */
+# error "PREFETCH_CHUNK is too large and/or MAX_PREFETCH_SIZE is too small."
+# endif
+#else /* USE_PREFETCH not defined */
+# define PREFETCH_FOR_STORE(offset, reg)
+#endif
+
+#if __mips_isa_rev > 5
+# if (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+# undef PREFETCH_STORE_HINT
+# define PREFETCH_STORE_HINT PREFETCH_HINT_STORE_STREAMED
+# endif
+# define R6_CODE
+#endif
+
+/* Allow the routine to be named something else if desired. */
+#ifndef MEMSET_NAME
+# define MEMSET_NAME memset
+#endif
+
+/* We load/store 64 bits at a time when USE_DOUBLE is true.
+ The C_ prefix stands for CHUNK and is used to avoid macro name
+ conflicts with system header files. */
+
+#ifdef USE_DOUBLE
+# define C_ST sd
+# ifdef __MIPSEB
+# define C_STHI sdl /* high part is left in big-endian */
+# else
+# define C_STHI sdr /* high part is right in little-endian */
+# endif
+#else
+# define C_ST sw
+# ifdef __MIPSEB
+# define C_STHI swl /* high part is left in big-endian */
+# else
+# define C_STHI swr /* high part is right in little-endian */
+# endif
+#endif
+
+/* Bookkeeping values for 32 vs. 64 bit mode. */
+#ifdef USE_DOUBLE
+# define NSIZE 8
+# define NSIZEMASK 0x3f
+# define NSIZEDMASK 0x7f
+#else
+# define NSIZE 4
+# define NSIZEMASK 0x1f
+# define NSIZEDMASK 0x3f
+#endif
+#define UNIT(unit) ((unit)*NSIZE)
+#define UNITM1(unit) (((unit)*NSIZE)-1)
+
+#ifdef ANDROID_CHANGES
+LEAF(MEMSET_NAME,0)
+#else
+LEAF(MEMSET_NAME)
+#endif
+
+ .set nomips16
+ .set noreorder
+/* If the size is less than 2*NSIZE (8 or 16), go to L(lastb). Regardless of
+ size, copy dst pointer to v0 for the return value. */
+ slti t2,a2,(2 * NSIZE)
+ bne t2,zero,L(lastb)
+ move v0,a0
+
+/* If memset value is not zero, we copy it to all the bytes in a 32 or 64
+ bit word. */
+ beq a1,zero,L(set0) /* If memset value is zero no smear */
+ PTR_SUBU a3,zero,a0
+ nop
+
+ /* smear byte into 32 or 64 bit word */
+#if ((__mips == 64) || (__mips == 32)) && (__mips_isa_rev >= 2)
+# ifdef USE_DOUBLE
+ dins a1, a1, 8, 8 /* Replicate fill byte into half-word. */
+ dins a1, a1, 16, 16 /* Replicate fill byte into word. */
+ dins a1, a1, 32, 32 /* Replicate fill byte into dbl word. */
+# else
+ ins a1, a1, 8, 8 /* Replicate fill byte into half-word. */
+ ins a1, a1, 16, 16 /* Replicate fill byte into word. */
+# endif
+#else
+# ifdef USE_DOUBLE
+ and a1,0xff
+ dsll t2,a1,8
+ or a1,t2
+ dsll t2,a1,16
+ or a1,t2
+ dsll t2,a1,32
+ or a1,t2
+# else
+ and a1,0xff
+ sll t2,a1,8
+ or a1,t2
+ sll t2,a1,16
+ or a1,t2
+# endif
+#endif
+
+/* If the destination address is not aligned do a partial store to get it
+ aligned. If it is already aligned just jump to L(aligned). */
+L(set0):
+#ifndef R6_CODE
+ andi t2,a3,(NSIZE-1) /* word-unaligned address? */
+ beq t2,zero,L(aligned) /* t2 is the unalignment count */
+ PTR_SUBU a2,a2,t2
+ C_STHI a1,0(a0)
+ PTR_ADDU a0,a0,t2
+#else /* R6_CODE */
+ andi t2,a0,(NSIZE-1)
+ lapc t9,L(atable)
+ PTR_LSA t9,t2,t9,2
+ jrc t9
+L(atable):
+ bc L(aligned)
+# ifdef USE_DOUBLE
+ bc L(lb7)
+ bc L(lb6)
+ bc L(lb5)
+ bc L(lb4)
+# endif
+ bc L(lb3)
+ bc L(lb2)
+ bc L(lb1)
+L(lb7):
+ sb a1,6(a0)
+L(lb6):
+ sb a1,5(a0)
+L(lb5):
+ sb a1,4(a0)
+L(lb4):
+ sb a1,3(a0)
+L(lb3):
+ sb a1,2(a0)
+L(lb2):
+ sb a1,1(a0)
+L(lb1):
+ sb a1,0(a0)
+
+ li t9,NSIZE
+ subu t2,t9,t2
+ PTR_SUBU a2,a2,t2
+ PTR_ADDU a0,a0,t2
+#endif /* R6_CODE */
+
+L(aligned):
+/* If USE_DOUBLE is not set we may still want to align the data on a 16
+ byte boundry instead of an 8 byte boundry to maximize the opportunity
+ of proAptiv chips to do memory bonding (combining two sequential 4
+ byte stores into one 8 byte store). We know there are at least 4 bytes
+ left to store or we would have jumped to L(lastb) earlier in the code. */
+#ifdef DOUBLE_ALIGN
+ andi t2,a3,4
+ beq t2,zero,L(double_aligned)
+ PTR_SUBU a2,a2,t2
+ sw a1,0(a0)
+ PTR_ADDU a0,a0,t2
+L(double_aligned):
+#endif
+
+/* Now the destination is aligned to (word or double word) aligned address
+ Set a2 to count how many bytes we have to copy after all the 64/128 byte
+ chunks are copied and a3 to the dest pointer after all the 64/128 byte
+ chunks have been copied. We will loop, incrementing a0 until it equals
+ a3. */
+ andi t8,a2,NSIZEDMASK /* any whole 64-byte/128-byte chunks? */
+ beq a2,t8,L(chkw) /* if a2==t8, no 64-byte/128-byte chunks */
+ PTR_SUBU a3,a2,t8 /* subtract from a2 the reminder */
+ PTR_ADDU a3,a0,a3 /* Now a3 is the final dst after loop */
+
+/* When in the loop we may prefetch with the 'prepare to store' hint,
+ in this case the a0+x should not be past the "t0-32" address. This
+ means: for x=128 the last "safe" a0 address is "t0-160". Alternatively,
+ for x=64 the last "safe" a0 address is "t0-96" In the current version we
+ will use "prefetch hint,128(a0)", so "t0-160" is the limit. */
+#if defined(USE_PREFETCH) \
+ && (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+ PTR_ADDU t0,a0,a2 /* t0 is the "past the end" address */
+ PTR_SUBU t9,t0,PREFETCH_LIMIT /* t9 is the "last safe pref" address */
+#endif
+#if defined(USE_PREFETCH) \
+ && (PREFETCH_STORE_HINT != PREFETCH_HINT_PREPAREFORSTORE)
+ PREFETCH_FOR_STORE (1, a0)
+ PREFETCH_FOR_STORE (2, a0)
+ PREFETCH_FOR_STORE (3, a0)
+#endif
+
+L(loop16w):
+#if defined(USE_PREFETCH) \
+ && (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+ sltu v1,t9,a0 /* If a0 > t9 don't use next prefetch */
+ bgtz v1,L(skip_pref)
+ nop
+#endif
+#ifdef R6_CODE
+ PREFETCH_FOR_STORE (2, a0)
+#else
+ PREFETCH_FOR_STORE (4, a0)
+ PREFETCH_FOR_STORE (5, a0)
+#endif
+L(skip_pref):
+ C_ST a1,UNIT(0)(a0)
+ C_ST a1,UNIT(1)(a0)
+ C_ST a1,UNIT(2)(a0)
+ C_ST a1,UNIT(3)(a0)
+ C_ST a1,UNIT(4)(a0)
+ C_ST a1,UNIT(5)(a0)
+ C_ST a1,UNIT(6)(a0)
+ C_ST a1,UNIT(7)(a0)
+ C_ST a1,UNIT(8)(a0)
+ C_ST a1,UNIT(9)(a0)
+ C_ST a1,UNIT(10)(a0)
+ C_ST a1,UNIT(11)(a0)
+ C_ST a1,UNIT(12)(a0)
+ C_ST a1,UNIT(13)(a0)
+ C_ST a1,UNIT(14)(a0)
+ C_ST a1,UNIT(15)(a0)
+ PTR_ADDIU a0,a0,UNIT(16) /* adding 64/128 to dest */
+ bne a0,a3,L(loop16w)
+ nop
+ move a2,t8
+
+/* Here we have dest word-aligned but less than 64-bytes or 128 bytes to go.
+ Check for a 32(64) byte chunk and copy if if there is one. Otherwise
+ jump down to L(chk1w) to handle the tail end of the copy. */
+L(chkw):
+ andi t8,a2,NSIZEMASK /* is there a 32-byte/64-byte chunk. */
+ /* the t8 is the reminder count past 32-bytes */
+ beq a2,t8,L(chk1w)/* when a2==t8, no 32-byte chunk */
+ nop
+ C_ST a1,UNIT(0)(a0)
+ C_ST a1,UNIT(1)(a0)
+ C_ST a1,UNIT(2)(a0)
+ C_ST a1,UNIT(3)(a0)
+ C_ST a1,UNIT(4)(a0)
+ C_ST a1,UNIT(5)(a0)
+ C_ST a1,UNIT(6)(a0)
+ C_ST a1,UNIT(7)(a0)
+ PTR_ADDIU a0,a0,UNIT(8)
+
+/* Here we have less than 32(64) bytes to set. Set up for a loop to
+ copy one word (or double word) at a time. Set a2 to count how many
+ bytes we have to copy after all the word (or double word) chunks are
+ copied and a3 to the dest pointer after all the (d)word chunks have
+ been copied. We will loop, incrementing a0 until a0 equals a3. */
+L(chk1w):
+ andi a2,t8,(NSIZE-1) /* a2 is the reminder past one (d)word chunks */
+ beq a2,t8,L(lastb)
+ PTR_SUBU a3,t8,a2 /* a3 is count of bytes in one (d)word chunks */
+ PTR_ADDU a3,a0,a3 /* a3 is the dst address after loop */
+
+/* copying in words (4-byte or 8 byte chunks) */
+L(wordCopy_loop):
+ PTR_ADDIU a0,a0,UNIT(1)
+ bne a0,a3,L(wordCopy_loop)
+ C_ST a1,UNIT(-1)(a0)
+
+/* Copy the last 8 (or 16) bytes */
+L(lastb):
+ blez a2,L(leave)
+ PTR_ADDU a3,a0,a2 /* a3 is the last dst address */
+L(lastbloop):
+ PTR_ADDIU a0,a0,1
+ bne a0,a3,L(lastbloop)
+ sb a1,-1(a0)
+L(leave):
+ j ra
+ nop
+
+ .set at
+ .set reorder
+END(MEMSET_NAME)
+#ifndef ANDROID_CHANGES
+# ifdef _LIBC
+libc_hidden_builtin_def (MEMSET_NAME)
+# endif
+#endif
diff --git a/sysdeps/mips/memusage.h b/sysdeps/mips/memusage.h
new file mode 100644
index 0000000000..bf7912e532
--- /dev/null
+++ b/sysdeps/mips/memusage.h
@@ -0,0 +1,20 @@
+/* Copyright (C) 2000-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define GETSP() ({ register uintptr_t stack_ptr asm ("$29"); stack_ptr; })
+
+#include <sysdeps/generic/memusage.h>
diff --git a/sysdeps/mips/mips32/Implies b/sysdeps/mips/mips32/Implies
new file mode 100644
index 0000000000..6473f2517c
--- /dev/null
+++ b/sysdeps/mips/mips32/Implies
@@ -0,0 +1,3 @@
+mips/ieee754
+mips
+wordsize-32
diff --git a/sysdeps/mips/mips32/Makefile b/sysdeps/mips/mips32/Makefile
new file mode 100644
index 0000000000..dec0b024c3
--- /dev/null
+++ b/sysdeps/mips/mips32/Makefile
@@ -0,0 +1,3 @@
+ifeq ($(filter -mabi=32,$(CC)),)
+CC += -mabi=32
+endif
diff --git a/sysdeps/mips/mips32/crti.S b/sysdeps/mips/mips32/crti.S
new file mode 100644
index 0000000000..4125f41c2a
--- /dev/null
+++ b/sysdeps/mips/mips32/crti.S
@@ -0,0 +1,93 @@
+/* Special .init and .fini section support for MIPS (o32).
+ Copyright (C) 1995-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file with other
+ programs, and to distribute those programs without any restriction
+ coming from the use of this file. (The GNU Lesser General Public
+ License restrictions do apply in other respects; for example, they
+ cover modification of the file, and distribution when not linked
+ into another program.)
+
+ Note that people who make modified versions of this file are not
+ obligated to grant this special exception for their modified
+ versions; it is their choice whether to do so. The GNU Lesser
+ General Public License gives permission to release a modified
+ version without this exception; this exception also makes it
+ possible to release a modified version which carries forward this
+ exception.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* crti.S puts a function prologue at the beginning of the .init and
+ .fini sections and defines global symbols for those addresses, so
+ they can be called as functions. The symbols _init and _fini are
+ magic and cause the linker to emit DT_INIT and DT_FINI. */
+
+#include <libc-symbols.h>
+
+#ifndef PREINIT_FUNCTION
+# define PREINIT_FUNCTION __gmon_start__
+#endif
+
+#ifndef PREINIT_FUNCTION_WEAK
+# define PREINIT_FUNCTION_WEAK 1
+#endif
+
+#if PREINIT_FUNCTION_WEAK
+ weak_extern (PREINIT_FUNCTION)
+#else
+ .hidden PREINIT_FUNCTION
+#endif
+
+ .set nomips16
+
+ .section .init,"ax",@progbits
+ .p2align 2
+ .globl _init
+ .type _init, @function
+_init:
+ .set noreorder
+ .cpload $25
+ .set reorder
+ addiu $sp,$sp,-32
+ .cprestore 16
+ sw $31,28($sp)
+#if PREINIT_FUNCTION_WEAK
+ lw $2,%got(PREINIT_FUNCTION)($28)
+ beq $2,$0,.Lno_weak_fn
+ lw $25,%call16(PREINIT_FUNCTION)($28)
+ .reloc 1f,R_MIPS_JALR,PREINIT_FUNCTION
+1: jalr $25
+.Lno_weak_fn:
+#else
+ lw $25,%got(PREINIT_FUNCTION)($28)
+ .reloc 1f,R_MIPS_JALR,PREINIT_FUNCTION
+1: jalr $25
+#endif
+
+ .section .fini,"ax",@progbits
+ .p2align 2
+ .globl _fini
+ .type _fini, @function
+_fini:
+ .set noreorder
+ .cpload $25
+ .set reorder
+ addiu $sp,$sp,-32
+ .cprestore 16
+ sw $31,28($sp)
diff --git a/sysdeps/mips/mips32/crtn.S b/sysdeps/mips/mips32/crtn.S
new file mode 100644
index 0000000000..d4d29fa58f
--- /dev/null
+++ b/sysdeps/mips/mips32/crtn.S
@@ -0,0 +1,57 @@
+/* Special .init and .fini section support for MIPS (o32).
+ Copyright (C) 1995-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file with other
+ programs, and to distribute those programs without any restriction
+ coming from the use of this file. (The GNU Lesser General Public
+ License restrictions do apply in other respects; for example, they
+ cover modification of the file, and distribution when not linked
+ into another program.)
+
+ Note that people who make modified versions of this file are not
+ obligated to grant this special exception for their modified
+ versions; it is their choice whether to do so. The GNU Lesser
+ General Public License gives permission to release a modified
+ version without this exception; this exception also makes it
+ possible to release a modified version which carries forward this
+ exception.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* crtn.S puts function epilogues in the .init and .fini sections
+ corresponding to the prologues in crti.S. */
+
+ .set nomips16
+
+ .section .init,"ax",@progbits
+ lw $31,28($sp)
+ .set noreorder
+ .set nomacro
+ j $31
+ addiu $sp,$sp,32
+ .set macro
+ .set reorder
+
+ .section .fini,"ax",@progbits
+ lw $31,28($sp)
+ .set noreorder
+ .set nomacro
+ j $31
+ addiu $sp,$sp,32
+ .set macro
+ .set reorder
diff --git a/sysdeps/mips/mips32/fpu/Makefile b/sysdeps/mips/mips32/fpu/Makefile
new file mode 100644
index 0000000000..951c408423
--- /dev/null
+++ b/sysdeps/mips/mips32/fpu/Makefile
@@ -0,0 +1,3 @@
+ifeq ($(subdir),math)
+aux += fpucw-helpers
+endif
diff --git a/sysdeps/mips/mips32/fpu/Versions b/sysdeps/mips/mips32/fpu/Versions
new file mode 100644
index 0000000000..91bbf564b3
--- /dev/null
+++ b/sysdeps/mips/mips32/fpu/Versions
@@ -0,0 +1,5 @@
+libc {
+ GLIBC_2.18 {
+ __mips_fpu_getcw; __mips_fpu_setcw;
+ }
+}
diff --git a/sysdeps/mips/mips32/fpu/e_sqrt.c b/sysdeps/mips/mips32/fpu/e_sqrt.c
new file mode 100644
index 0000000000..81f4e77697
--- /dev/null
+++ b/sysdeps/mips/mips32/fpu/e_sqrt.c
@@ -0,0 +1 @@
+#include <sysdeps/mips/fpu/e_sqrt.c>
diff --git a/sysdeps/mips/mips32/fpu/e_sqrtf.c b/sysdeps/mips/mips32/fpu/e_sqrtf.c
new file mode 100644
index 0000000000..fb0700d45c
--- /dev/null
+++ b/sysdeps/mips/mips32/fpu/e_sqrtf.c
@@ -0,0 +1 @@
+#include <sysdeps/mips/fpu/e_sqrtf.c>
diff --git a/sysdeps/mips/mips32/fpu/fpucw-helpers.c b/sysdeps/mips/mips32/fpu/fpucw-helpers.c
new file mode 100644
index 0000000000..40391a3ec5
--- /dev/null
+++ b/sysdeps/mips/mips32/fpu/fpucw-helpers.c
@@ -0,0 +1,34 @@
+/* FPU control word handling, MIPS version, needed by MIPS16 callers.
+ Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fpu_control.h>
+
+fpu_control_t
+__mips_fpu_getcw (void)
+{
+ fpu_control_t cw;
+
+ _FPU_GETCW (cw);
+ return cw;
+}
+
+void
+__mips_fpu_setcw (fpu_control_t cw)
+{
+ _FPU_SETCW (cw);
+}
diff --git a/sysdeps/mips/mips32/libm-test-ulps b/sysdeps/mips/mips32/libm-test-ulps
new file mode 100644
index 0000000000..e38d37fe47
--- /dev/null
+++ b/sysdeps/mips/mips32/libm-test-ulps
@@ -0,0 +1,1676 @@
+# Begin of automatic generation
+
+# Maximal error of functions:
+Function: "acos":
+float: 1
+ifloat: 1
+
+Function: "acos_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "acos_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "acos_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "acosh":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "acosh_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "acosh_towardzero":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: "acosh_upward":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: "asin":
+float: 1
+ifloat: 1
+
+Function: "asin_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "asin_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "asin_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "asinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "asinh_downward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+
+Function: "asinh_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "asinh_upward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+
+Function: "atan":
+float: 1
+ifloat: 1
+
+Function: "atan2":
+float: 1
+ifloat: 1
+
+Function: "atan2_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "atan2_towardzero":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "atan2_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "atan_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "atan_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "atan_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "atanh":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "atanh_downward":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+Function: "atanh_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "atanh_upward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+
+Function: "cabs":
+double: 1
+idouble: 1
+
+Function: "cabs_downward":
+double: 1
+idouble: 1
+
+Function: "cabs_towardzero":
+double: 1
+idouble: 1
+
+Function: "cabs_upward":
+double: 1
+idouble: 1
+
+Function: Real part of "cacos":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Imaginary part of "cacos":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Real part of "cacos_downward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Imaginary part of "cacos_downward":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+
+Function: Real part of "cacos_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Imaginary part of "cacos_towardzero":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+
+Function: Real part of "cacos_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Imaginary part of "cacos_upward":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+
+Function: Real part of "cacosh":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Imaginary part of "cacosh":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Real part of "cacosh_downward":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+
+Function: Imaginary part of "cacosh_downward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Real part of "cacosh_towardzero":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+
+Function: Imaginary part of "cacosh_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Real part of "cacosh_upward":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+
+Function: Imaginary part of "cacosh_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "carg":
+float: 1
+ifloat: 1
+
+Function: "carg_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "carg_towardzero":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "carg_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Real part of "casin":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "casin":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Real part of "casin_downward":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+
+Function: Imaginary part of "casin_downward":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+
+Function: Real part of "casin_towardzero":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+
+Function: Imaginary part of "casin_towardzero":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+
+Function: Real part of "casin_upward":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: Imaginary part of "casin_upward":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+
+Function: Real part of "casinh":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Imaginary part of "casinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "casinh_downward":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+
+Function: Imaginary part of "casinh_downward":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+
+Function: Real part of "casinh_towardzero":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+
+Function: Imaginary part of "casinh_towardzero":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+
+Function: Real part of "casinh_upward":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+
+Function: Imaginary part of "casinh_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Real part of "catan":
+float: 1
+ifloat: 1
+
+Function: Imaginary part of "catan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "catan_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "catan_downward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Real part of "catan_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "catan_towardzero":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: Real part of "catan_upward":
+float: 1
+ifloat: 1
+
+Function: Imaginary part of "catan_upward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+
+Function: Real part of "catanh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "catanh":
+float: 1
+ifloat: 1
+
+Function: Real part of "catanh_downward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Imaginary part of "catanh_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Real part of "catanh_towardzero":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: Imaginary part of "catanh_towardzero":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Real part of "catanh_upward":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+
+Function: Imaginary part of "catanh_upward":
+float: 1
+ifloat: 1
+
+Function: "cbrt":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+
+Function: "cbrt_downward":
+double: 4
+float: 1
+idouble: 4
+ifloat: 1
+
+Function: "cbrt_towardzero":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+
+Function: "cbrt_upward":
+double: 4
+float: 1
+idouble: 4
+ifloat: 1
+
+Function: Real part of "ccos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "ccos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "ccos_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "ccos_downward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+
+Function: Real part of "ccos_towardzero":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Imaginary part of "ccos_towardzero":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+
+Function: Real part of "ccos_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Imaginary part of "ccos_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Real part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "ccosh_downward":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+
+Function: Imaginary part of "ccosh_downward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+
+Function: Real part of "ccosh_towardzero":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+
+Function: Imaginary part of "ccosh_towardzero":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+
+Function: Real part of "ccosh_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Imaginary part of "ccosh_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Real part of "cexp":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: Imaginary part of "cexp":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Real part of "cexp_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Imaginary part of "cexp_downward":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+
+Function: Real part of "cexp_towardzero":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Imaginary part of "cexp_towardzero":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+
+Function: Real part of "cexp_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Imaginary part of "cexp_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Real part of "clog":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+Function: Imaginary part of "clog":
+float: 1
+ifloat: 1
+
+Function: Real part of "clog10":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+
+Function: Imaginary part of "clog10":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Real part of "clog10_downward":
+double: 6
+float: 6
+idouble: 6
+ifloat: 6
+
+Function: Imaginary part of "clog10_downward":
+double: 2
+float: 4
+idouble: 2
+ifloat: 4
+
+Function: Real part of "clog10_towardzero":
+double: 5
+float: 4
+idouble: 5
+ifloat: 4
+
+Function: Imaginary part of "clog10_towardzero":
+double: 2
+float: 4
+idouble: 2
+ifloat: 4
+
+Function: Real part of "clog10_upward":
+double: 8
+float: 5
+idouble: 8
+ifloat: 5
+
+Function: Imaginary part of "clog10_upward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+
+Function: Real part of "clog_downward":
+double: 7
+float: 5
+idouble: 7
+ifloat: 5
+
+Function: Imaginary part of "clog_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Real part of "clog_towardzero":
+double: 7
+float: 5
+idouble: 7
+ifloat: 5
+
+Function: Imaginary part of "clog_towardzero":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Real part of "clog_upward":
+double: 8
+float: 5
+idouble: 8
+ifloat: 5
+
+Function: Imaginary part of "clog_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "cos":
+float: 1
+ifloat: 1
+
+Function: "cos_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "cos_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "cos_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "cosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "cosh_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "cosh_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "cosh_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Real part of "cpow":
+double: 2
+float: 4
+idouble: 2
+ifloat: 4
+
+Function: Imaginary part of "cpow":
+float: 2
+ifloat: 2
+
+Function: Real part of "cpow_downward":
+double: 4
+float: 8
+idouble: 4
+ifloat: 8
+
+Function: Imaginary part of "cpow_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Real part of "cpow_towardzero":
+double: 4
+float: 8
+idouble: 4
+ifloat: 8
+
+Function: Imaginary part of "cpow_towardzero":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Real part of "cpow_upward":
+double: 4
+float: 1
+idouble: 4
+ifloat: 1
+
+Function: Imaginary part of "cpow_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Real part of "csin":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "csin_downward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+
+Function: Imaginary part of "csin_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "csin_towardzero":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+
+Function: Imaginary part of "csin_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "csin_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Imaginary part of "csin_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Real part of "csinh":
+float: 1
+ifloat: 1
+
+Function: Imaginary part of "csinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "csinh_downward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Imaginary part of "csinh_downward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+
+Function: Real part of "csinh_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Imaginary part of "csinh_towardzero":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+
+Function: Real part of "csinh_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: Imaginary part of "csinh_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Real part of "csqrt":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Imaginary part of "csqrt":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Real part of "csqrt_downward":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+
+Function: Imaginary part of "csqrt_downward":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+
+Function: Real part of "csqrt_towardzero":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+
+Function: Imaginary part of "csqrt_towardzero":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+
+Function: Real part of "csqrt_upward":
+double: 5
+float: 4
+idouble: 5
+ifloat: 4
+
+Function: Imaginary part of "csqrt_upward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+
+Function: Real part of "ctan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "ctan":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: Real part of "ctan_downward":
+double: 6
+float: 5
+idouble: 6
+ifloat: 5
+
+Function: Imaginary part of "ctan_downward":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: Real part of "ctan_towardzero":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+
+Function: Imaginary part of "ctan_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Real part of "ctan_upward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+
+Function: Imaginary part of "ctan_upward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+
+Function: Real part of "ctanh":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: Imaginary part of "ctanh":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Real part of "ctanh_downward":
+double: 4
+float: 1
+idouble: 4
+ifloat: 1
+
+Function: Imaginary part of "ctanh_downward":
+double: 6
+float: 5
+idouble: 6
+ifloat: 5
+
+Function: Real part of "ctanh_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Imaginary part of "ctanh_towardzero":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+
+Function: Real part of "ctanh_upward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+
+Function: Imaginary part of "ctanh_upward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+
+Function: "erf":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "erf_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "erf_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "erf_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "erfc":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "erfc_downward":
+double: 4
+float: 6
+idouble: 4
+ifloat: 6
+
+Function: "erfc_towardzero":
+double: 3
+float: 4
+idouble: 3
+ifloat: 4
+
+Function: "erfc_upward":
+double: 4
+float: 6
+idouble: 4
+ifloat: 6
+
+Function: "exp10":
+double: 2
+idouble: 2
+
+Function: "exp10_downward":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: "exp10_towardzero":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: "exp10_upward":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: "exp2":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "exp2_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "exp2_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "exp2_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "exp_downward":
+double: 1
+idouble: 1
+
+Function: "exp_towardzero":
+double: 1
+idouble: 1
+
+Function: "exp_upward":
+double: 1
+idouble: 1
+
+Function: "expm1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "expm1_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "expm1_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "expm1_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "gamma":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "gamma_downward":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+
+Function: "gamma_towardzero":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+
+Function: "gamma_upward":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+
+Function: "hypot":
+double: 1
+idouble: 1
+
+Function: "hypot_downward":
+double: 1
+idouble: 1
+
+Function: "hypot_towardzero":
+double: 1
+idouble: 1
+
+Function: "hypot_upward":
+double: 1
+idouble: 1
+
+Function: "j0":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "j0_downward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+
+Function: "j0_towardzero":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+Function: "j0_upward":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+Function: "j1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "j1_downward":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+Function: "j1_towardzero":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+Function: "j1_upward":
+double: 3
+float: 5
+idouble: 3
+ifloat: 5
+
+Function: "jn":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+
+Function: "jn_downward":
+double: 5
+float: 5
+idouble: 5
+ifloat: 5
+
+Function: "jn_towardzero":
+double: 5
+float: 5
+idouble: 5
+ifloat: 5
+
+Function: "jn_upward":
+double: 5
+float: 5
+idouble: 5
+ifloat: 5
+
+Function: "lgamma":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "lgamma_downward":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+
+Function: "lgamma_towardzero":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+
+Function: "lgamma_upward":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+
+Function: "log":
+float: 1
+ifloat: 1
+
+Function: "log10":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "log10_downward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+
+Function: "log10_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "log10_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "log1p":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "log1p_downward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "log1p_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "log1p_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "log2":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: "log2_downward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+
+Function: "log2_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "log2_upward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+
+Function: "log_downward":
+float: 2
+ifloat: 2
+
+Function: "log_towardzero":
+float: 2
+ifloat: 2
+
+Function: "log_upward":
+float: 2
+ifloat: 2
+
+Function: "pow":
+float: 3
+ifloat: 3
+
+Function: "pow10":
+double: 2
+idouble: 2
+
+Function: "pow10_downward":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: "pow10_towardzero":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: "pow10_upward":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: "pow_downward":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+
+Function: "pow_towardzero":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+
+Function: "pow_upward":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+
+Function: "sin":
+float: 1
+ifloat: 1
+
+Function: "sin_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "sin_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "sin_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "sincos":
+float: 1
+ifloat: 1
+
+Function: "sincos_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "sincos_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "sincos_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "sinh":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "sinh_downward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+
+Function: "sinh_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "sinh_upward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+
+Function: "tan":
+float: 1
+ifloat: 1
+
+Function: "tan_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "tan_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "tan_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "tanh":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "tanh_downward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+
+Function: "tanh_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "tanh_upward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+
+Function: "tgamma":
+double: 3
+float: 5
+idouble: 3
+ifloat: 5
+
+Function: "tgamma_downward":
+double: 3
+float: 4
+idouble: 3
+ifloat: 4
+
+Function: "tgamma_towardzero":
+double: 3
+float: 5
+idouble: 3
+ifloat: 5
+
+Function: "tgamma_upward":
+double: 3
+float: 5
+idouble: 3
+ifloat: 5
+
+Function: "y0":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: "y0_downward":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+Function: "y0_towardzero":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+
+Function: "y0_upward":
+double: 3
+float: 4
+idouble: 3
+ifloat: 4
+
+Function: "y1":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+Function: "y1_downward":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+Function: "y1_towardzero":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+Function: "y1_upward":
+double: 7
+float: 2
+idouble: 7
+ifloat: 2
+
+Function: "yn":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+Function: "yn_downward":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+Function: "yn_towardzero":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+
+Function: "yn_upward":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+
+# end of automatic generation
diff --git a/sysdeps/mips/mips32/mips16/add_n.c b/sysdeps/mips/mips32/mips16/add_n.c
new file mode 100644
index 0000000000..fbb4120418
--- /dev/null
+++ b/sysdeps/mips/mips32/mips16/add_n.c
@@ -0,0 +1 @@
+#include <stdlib/add_n.c>
diff --git a/sysdeps/mips/mips32/mips16/addmul_1.c b/sysdeps/mips/mips32/mips16/addmul_1.c
new file mode 100644
index 0000000000..c0e4a0bd7e
--- /dev/null
+++ b/sysdeps/mips/mips32/mips16/addmul_1.c
@@ -0,0 +1 @@
+#include <stdlib/addmul_1.c>
diff --git a/sysdeps/mips/mips32/mips16/fpu/Makefile b/sysdeps/mips/mips32/mips16/fpu/Makefile
new file mode 100644
index 0000000000..b58c4eeb0c
--- /dev/null
+++ b/sysdeps/mips/mips32/mips16/fpu/Makefile
@@ -0,0 +1,5 @@
+# Building hard-float libm as MIPS16 actually produces larger code size,
+# so avoid doing so.
+ifeq ($(subdir),math)
+sysdep-CFLAGS += -mno-mips16
+endif
diff --git a/sysdeps/mips/mips32/mips16/lshift.c b/sysdeps/mips/mips32/mips16/lshift.c
new file mode 100644
index 0000000000..2f945d2c59
--- /dev/null
+++ b/sysdeps/mips/mips32/mips16/lshift.c
@@ -0,0 +1 @@
+#include <stdlib/lshift.c>
diff --git a/sysdeps/mips/mips32/mips16/mul_1.c b/sysdeps/mips/mips32/mips16/mul_1.c
new file mode 100644
index 0000000000..8e758d6039
--- /dev/null
+++ b/sysdeps/mips/mips32/mips16/mul_1.c
@@ -0,0 +1 @@
+#include <stdlib/mul_1.c>
diff --git a/sysdeps/mips/mips32/mips16/rshift.c b/sysdeps/mips/mips32/mips16/rshift.c
new file mode 100644
index 0000000000..4e350a0dcb
--- /dev/null
+++ b/sysdeps/mips/mips32/mips16/rshift.c
@@ -0,0 +1 @@
+#include <stdlib/rshift.c>
diff --git a/sysdeps/mips/mips32/mips16/sub_n.c b/sysdeps/mips/mips32/mips16/sub_n.c
new file mode 100644
index 0000000000..d8b54925b1
--- /dev/null
+++ b/sysdeps/mips/mips32/mips16/sub_n.c
@@ -0,0 +1 @@
+#include <stdlib/sub_n.c>
diff --git a/sysdeps/mips/mips32/mips16/submul_1.c b/sysdeps/mips/mips32/mips16/submul_1.c
new file mode 100644
index 0000000000..44cadf5cc0
--- /dev/null
+++ b/sysdeps/mips/mips32/mips16/submul_1.c
@@ -0,0 +1 @@
+#include <stdlib/submul_1.c>
diff --git a/sysdeps/mips/mips32/sfp-machine.h b/sysdeps/mips/mips32/sfp-machine.h
new file mode 100644
index 0000000000..4e23aa8b26
--- /dev/null
+++ b/sysdeps/mips/mips32/sfp-machine.h
@@ -0,0 +1,68 @@
+#define _FP_W_TYPE_SIZE 32
+#define _FP_W_TYPE unsigned long
+#define _FP_WS_TYPE signed long
+#define _FP_I_TYPE long
+
+#define _FP_MUL_MEAT_S(R,X,Y) \
+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y) \
+ _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y) \
+ _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_MUL_MEAT_DW_S(R,X,Y) \
+ _FP_MUL_MEAT_DW_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_DW_D(R,X,Y) \
+ _FP_MUL_MEAT_DW_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_DW_Q(R,X,Y) \
+ _FP_MUL_MEAT_DW_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+
+#ifdef __mips_nan2008
+# define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
+# define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1
+# define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#else
+# define _FP_NANFRAC_S (_FP_QNANBIT_S - 1)
+# define _FP_NANFRAC_D (_FP_QNANBIT_D - 1), -1
+# define _FP_NANFRAC_Q (_FP_QNANBIT_Q - 1), -1, -1, -1
+#endif
+#define _FP_NANSIGN_S 0
+#define _FP_NANSIGN_D 0
+#define _FP_NANSIGN_Q 0
+
+#define _FP_KEEPNANFRACP 1
+#ifdef __mips_nan2008
+# define _FP_QNANNEGATEDP 0
+#else
+# define _FP_QNANNEGATEDP 1
+#endif
+
+/* From my experiments it seems X is chosen unless one of the
+ NaNs is sNaN, in which case the result is NANSIGN/NANFRAC. */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
+ do { \
+ if ((_FP_FRAC_HIGH_RAW_##fs(X) | \
+ _FP_FRAC_HIGH_RAW_##fs(Y)) & _FP_QNANBIT_##fs) \
+ { \
+ R##_s = _FP_NANSIGN_##fs; \
+ _FP_FRAC_SET_##wc(R,_FP_NANFRAC_##fs); \
+ } \
+ else \
+ { \
+ R##_s = X##_s; \
+ _FP_FRAC_COPY_##wc(R,X); \
+ } \
+ R##_c = FP_CLS_NAN; \
+ } while (0)
+
+#define FP_EX_INVALID (1 << 4)
+#define FP_EX_DIVZERO (1 << 3)
+#define FP_EX_OVERFLOW (1 << 2)
+#define FP_EX_UNDERFLOW (1 << 1)
+#define FP_EX_INEXACT (1 << 0)
+
+#define _FP_TININESS_AFTER_ROUNDING 1
diff --git a/sysdeps/mips/mips64/Implies b/sysdeps/mips/mips64/Implies
new file mode 100644
index 0000000000..826ff1541f
--- /dev/null
+++ b/sysdeps/mips/mips64/Implies
@@ -0,0 +1,4 @@
+# MIPS uses IEEE 754 floating point.
+mips/ieee754
+ieee754/flt-32
+ieee754/dbl-64
diff --git a/sysdeps/mips/mips64/Makefile b/sysdeps/mips/mips64/Makefile
new file mode 100644
index 0000000000..ada13e8b70
--- /dev/null
+++ b/sysdeps/mips/mips64/Makefile
@@ -0,0 +1,3 @@
+ifeq ($(subdir),math)
+CPPFLAGS += -I../soft-fp
+endif
diff --git a/sysdeps/mips/mips64/Versions b/sysdeps/mips/mips64/Versions
new file mode 100644
index 0000000000..253a65f04e
--- /dev/null
+++ b/sysdeps/mips/mips64/Versions
@@ -0,0 +1,7 @@
+libm {
+ GLIBC_2.1 {
+ # A generic bug got this omitted from other configurations' version
+ # sets, but we always had it.
+ exp2l;
+ }
+}
diff --git a/sysdeps/mips/mips64/__longjmp.c b/sysdeps/mips/mips64/__longjmp.c
new file mode 100644
index 0000000000..15d761b599
--- /dev/null
+++ b/sysdeps/mips/mips64/__longjmp.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 1992-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Brendan Kehoe (brendan@zen.org).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <setjmp.h>
+#include <sgidefs.h>
+#include <stdlib.h>
+
+#ifndef __GNUC__
+ #error This file uses GNU C extensions; you must compile with GCC.
+#endif
+
+void
+__longjmp (env_arg, val_arg)
+ __jmp_buf env_arg;
+ int val_arg;
+{
+ /* gcc 1.39.19 miscompiled the longjmp routine (as it did setjmp before
+ the hack around it); force it to use $a1 for the longjmp value.
+ Without this it saves $a1 in a register which gets clobbered
+ along the way. */
+ register struct __jmp_buf_internal_tag *env asm ("a0");
+ register int val asm ("a1");
+#ifdef CHECK_SP
+ register long long sp asm ("$29");
+ CHECK_SP (env[0].__sp, sp, long long);
+#endif
+
+#ifdef __mips_hard_float
+ /* Pull back the floating point callee-saved registers. */
+#if _MIPS_SIM == _ABI64
+ asm volatile ("l.d $f24, %0" : : "m" (env[0].__fpregs[0]));
+ asm volatile ("l.d $f25, %0" : : "m" (env[0].__fpregs[1]));
+ asm volatile ("l.d $f26, %0" : : "m" (env[0].__fpregs[2]));
+ asm volatile ("l.d $f27, %0" : : "m" (env[0].__fpregs[3]));
+ asm volatile ("l.d $f28, %0" : : "m" (env[0].__fpregs[4]));
+ asm volatile ("l.d $f29, %0" : : "m" (env[0].__fpregs[5]));
+ asm volatile ("l.d $f30, %0" : : "m" (env[0].__fpregs[6]));
+ asm volatile ("l.d $f31, %0" : : "m" (env[0].__fpregs[7]));
+#else
+ asm volatile ("l.d $f20, %0" : : "m" (env[0].__fpregs[0]));
+ asm volatile ("l.d $f22, %0" : : "m" (env[0].__fpregs[1]));
+ asm volatile ("l.d $f24, %0" : : "m" (env[0].__fpregs[2]));
+ asm volatile ("l.d $f26, %0" : : "m" (env[0].__fpregs[3]));
+ asm volatile ("l.d $f28, %0" : : "m" (env[0].__fpregs[4]));
+ asm volatile ("l.d $f30, %0" : : "m" (env[0].__fpregs[5]));
+#endif
+#endif
+
+ /* Get the GP. */
+ asm volatile ("ld $gp, %0" : : "m" (env[0].__gp));
+
+ /* Get the callee-saved registers. */
+ asm volatile ("ld $16, %0" : : "m" (env[0].__regs[0]));
+ asm volatile ("ld $17, %0" : : "m" (env[0].__regs[1]));
+ asm volatile ("ld $18, %0" : : "m" (env[0].__regs[2]));
+ asm volatile ("ld $19, %0" : : "m" (env[0].__regs[3]));
+ asm volatile ("ld $20, %0" : : "m" (env[0].__regs[4]));
+ asm volatile ("ld $21, %0" : : "m" (env[0].__regs[5]));
+ asm volatile ("ld $22, %0" : : "m" (env[0].__regs[6]));
+ asm volatile ("ld $23, %0" : : "m" (env[0].__regs[7]));
+
+ /* Get the PC. */
+ asm volatile ("ld $31, %0" : : "m" (env[0].__pc));
+
+
+ /* Restore the stack pointer and the FP. They have to be restored
+ last and in a single asm as gcc, depending on options used, may
+ use either of them to access env. */
+ asm volatile ("ld $29, %0\n\t"
+ "ld $30, %1\n\t" : : "m" (env[0].__sp), "m" (env[0].__fp));
+
+/* Give setjmp 1 if given a 0, or what they gave us if non-zero. */
+ if (val == 0)
+ asm volatile ("dli $2, 1");
+ else
+ asm volatile ("move $2, %0" : : "r" (val));
+
+ asm volatile ("j $31");
+
+ /* Avoid `volatile function does return' warnings. */
+ for (;;);
+}
diff --git a/sysdeps/mips/mips64/add_n.S b/sysdeps/mips/mips64/add_n.S
new file mode 100644
index 0000000000..68f2fcc512
--- /dev/null
+++ b/sysdeps/mips/mips64/add_n.S
@@ -0,0 +1,125 @@
+/* MIPS3 __mpn_add_n -- Add two limb vectors of the same length > 0 and
+ * store sum in a third limb vector.
+ *
+ * Copyright (C) 1995-2015 Free Software Foundation, Inc.
+ *
+ * This file is part of the GNU MP Library.
+ *
+ * The GNU MP Library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * The GNU MP Library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the GNU MP Library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+/*
+ * INPUT PARAMETERS
+ * res_ptr $4
+ * s1_ptr $5
+ * s2_ptr $6
+ * size $7
+ */
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (__mpn_add_n)
+#ifdef __PIC__
+ SETUP_GP /* ??? unused */
+#endif
+ .set noreorder
+ .set nomacro
+
+ ld $10,0($5)
+ ld $11,0($6)
+
+ daddiu $7,$7,-1
+ and $9,$7,4-1 # number of limbs in first loop
+ beq $9,$0,L(L0) # if multiple of 4 limbs, skip first loop
+ move $2,$0
+
+ dsubu $7,$7,$9
+
+L(Loop0): daddiu $9,$9,-1
+ ld $12,8($5)
+ daddu $11,$11,$2
+ ld $13,8($6)
+ sltu $8,$11,$2
+ daddu $11,$10,$11
+ sltu $2,$11,$10
+ sd $11,0($4)
+ or $2,$2,$8
+
+ daddiu $5,$5,8
+ daddiu $6,$6,8
+ move $10,$12
+ move $11,$13
+ bne $9,$0,L(Loop0)
+ daddiu $4,$4,8
+
+L(L0): beq $7,$0,L(Lend)
+ nop
+
+L(Loop): daddiu $7,$7,-4
+
+ ld $12,8($5)
+ daddu $11,$11,$2
+ ld $13,8($6)
+ sltu $8,$11,$2
+ daddu $11,$10,$11
+ sltu $2,$11,$10
+ sd $11,0($4)
+ or $2,$2,$8
+
+ ld $10,16($5)
+ daddu $13,$13,$2
+ ld $11,16($6)
+ sltu $8,$13,$2
+ daddu $13,$12,$13
+ sltu $2,$13,$12
+ sd $13,8($4)
+ or $2,$2,$8
+
+ ld $12,24($5)
+ daddu $11,$11,$2
+ ld $13,24($6)
+ sltu $8,$11,$2
+ daddu $11,$10,$11
+ sltu $2,$11,$10
+ sd $11,16($4)
+ or $2,$2,$8
+
+ ld $10,32($5)
+ daddu $13,$13,$2
+ ld $11,32($6)
+ sltu $8,$13,$2
+ daddu $13,$12,$13
+ sltu $2,$13,$12
+ sd $13,24($4)
+ or $2,$2,$8
+
+ daddiu $5,$5,32
+ daddiu $6,$6,32
+
+ bne $7,$0,L(Loop)
+ daddiu $4,$4,32
+
+L(Lend): daddu $11,$11,$2
+ sltu $8,$11,$2
+ daddu $11,$10,$11
+ sltu $2,$11,$10
+ sd $11,0($4)
+ j $31
+ or $2,$2,$8
+
+END (__mpn_add_n)
diff --git a/sysdeps/mips/mips64/addmul_1.S b/sysdeps/mips/mips64/addmul_1.S
new file mode 100644
index 0000000000..167489aff1
--- /dev/null
+++ b/sysdeps/mips/mips64/addmul_1.S
@@ -0,0 +1,131 @@
+/* MIPS3 __mpn_addmul_1 -- Multiply a limb vector with a single limb and
+ * add the product to a second limb vector.
+ *
+ * Copyright (C) 1992-2015 Free Software Foundation, Inc.
+ *
+ * This file is part of the GNU MP Library.
+ *
+ * The GNU MP Library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * The GNU MP Library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the GNU MP Library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+/* INPUT PARAMETERS
+ * res_ptr $4
+ * s1_ptr $5
+ * size $6
+ * s2_limb $7
+ */
+
+#ifdef PIC
+ .option pic2
+#endif
+ENTRY (__mpn_addmul_1)
+#ifdef PIC
+ SETUP_GP /* ??? unused */
+#endif
+ .set noreorder
+ .set nomacro
+
+ # warm up phase 0
+ ld $8,0($5)
+
+ # warm up phase 1
+ daddiu $5,$5,8
+#if __mips_isa_rev < 6
+ dmultu $8,$7
+#else
+ dmulu $11,$8,$7
+ dmuhu $12,$8,$7
+#endif
+
+ daddiu $6,$6,-1
+ beq $6,$0,L(LC0)
+ move $2,$0 # zero cy2
+
+ daddiu $6,$6,-1
+ beq $6,$0,L(LC1)
+ ld $8,0($5) # load new s1 limb as early as possible
+
+L(Loop): ld $10,0($4)
+#if __mips_isa_rev < 6
+ mflo $3
+ mfhi $9
+#else
+ move $3,$11
+ move $9,$12
+#endif
+ daddiu $5,$5,8
+ daddu $3,$3,$2 # add old carry limb to low product limb
+#if __mips_isa_rev < 6
+ dmultu $8,$7
+#else
+ dmulu $11,$8,$7
+ dmuhu $12,$8,$7
+#endif
+ ld $8,0($5) # load new s1 limb as early as possible
+ daddiu $6,$6,-1 # decrement loop counter
+ sltu $2,$3,$2 # carry from previous addition -> $2
+ daddu $3,$10,$3
+ sltu $10,$3,$10
+ daddu $2,$2,$10
+ sd $3,0($4)
+ daddiu $4,$4,8
+ bne $6,$0,L(Loop)
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 1
+L(LC1): ld $10,0($4)
+#if __mips_isa_rev < 6
+ mflo $3
+ mfhi $9
+#else
+ move $3,$11
+ move $9,$12
+#endif
+ daddu $3,$3,$2
+ sltu $2,$3,$2
+#if __mips_isa_rev < 6
+ dmultu $8,$7
+#else
+ dmulu $11,$8,$7
+ dmuhu $12,$8,$7
+#endif
+ daddu $3,$10,$3
+ sltu $10,$3,$10
+ daddu $2,$2,$10
+ sd $3,0($4)
+ daddiu $4,$4,8
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 0
+L(LC0): ld $10,0($4)
+#if __mips_isa_rev < 6
+ mflo $3
+ mfhi $9
+#else
+ move $3,$11
+ move $9,$12
+#endif
+ daddu $3,$3,$2
+ sltu $2,$3,$2
+ daddu $3,$10,$3
+ sltu $10,$3,$10
+ daddu $2,$2,$10
+ sd $3,0($4)
+ j $31
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+END (__mpn_addmul_1)
diff --git a/sysdeps/mips/mips64/bsd-_setjmp.S b/sysdeps/mips/mips64/bsd-_setjmp.S
new file mode 100644
index 0000000000..363dc40147
--- /dev/null
+++ b/sysdeps/mips/mips64/bsd-_setjmp.S
@@ -0,0 +1,47 @@
+/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. MIPS64 version.
+ Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 0)'.
+ We cannot do it in C because it must be a tail-call, so frame-unwinding
+ in setjmp doesn't clobber the state restored by longjmp. */
+
+#include <sgidefs.h>
+#include <sysdep.h>
+#include <sys/asm.h>
+
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (_setjmp)
+#ifdef __PIC__
+ SETUP_GP
+#endif
+ SETUP_GP64_REG (v0, C_SYMBOL_NAME (_setjmp))
+ PTR_LA t9, C_SYMBOL_NAME (__sigsetjmp)
+#if _MIPS_SIM == _ABIO32
+ nop
+#endif
+ RESTORE_GP64_REG
+ move a1, zero /* Pass a second argument of zero. */
+#ifdef __PIC__
+ jr t9
+#else
+ j C_SYMBOL_NAME (__sigsetjmp)
+#endif
+END (_setjmp)
+libc_hidden_def (_setjmp)
diff --git a/sysdeps/mips/mips64/bsd-setjmp.S b/sysdeps/mips/mips64/bsd-setjmp.S
new file mode 100644
index 0000000000..1545334e89
--- /dev/null
+++ b/sysdeps/mips/mips64/bsd-setjmp.S
@@ -0,0 +1,46 @@
+/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. MIPS64 version.
+ Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 1)'.
+ We cannot do it in C because it must be a tail-call, so frame-unwinding
+ in setjmp doesn't clobber the state restored by longjmp. */
+
+#include <sgidefs.h>
+#include <sysdep.h>
+#include <sys/asm.h>
+
+#ifdef PIC
+ .option pic2
+#endif
+ENTRY (setjmp)
+#ifdef __PIC__
+ SETUP_GP
+#endif
+ SETUP_GP64_REG (v0, C_SYMBOL_NAME (setjmp))
+ PTR_LA t9, C_SYMBOL_NAME (__sigsetjmp)
+#if _MIPS_SIM == _ABIO32
+ nop
+#endif
+ RESTORE_GP64_REG
+ dli a1, 1 /* Pass a second argument of one. */
+#ifdef __PIC__
+ jr t9
+#else
+ j C_SYMBOL_NAME (__sigsetjmp)
+#endif
+END (setjmp)
diff --git a/sysdeps/mips/mips64/e_sqrtl.c b/sysdeps/mips/mips64/e_sqrtl.c
new file mode 100644
index 0000000000..55b564cd75
--- /dev/null
+++ b/sysdeps/mips/mips64/e_sqrtl.c
@@ -0,0 +1,39 @@
+/* long double square root in software floating-point emulation.
+ Copyright (C) 1997-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <soft-fp.h>
+#include <quad.h>
+
+long double
+__ieee754_sqrtl (const long double a)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A); FP_DECL_Q(C);
+ long double c;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_Q(A, a);
+ FP_SQRT_Q(C, A);
+ FP_PACK_Q(c, C);
+ FP_HANDLE_EXCEPTIONS;
+ return c;
+}
+strong_alias (__ieee754_sqrtl, __sqrtl_finite)
diff --git a/sysdeps/mips/mips64/gmp-mparam.h b/sysdeps/mips/mips64/gmp-mparam.h
new file mode 100644
index 0000000000..58a0d514aa
--- /dev/null
+++ b/sysdeps/mips/mips64/gmp-mparam.h
@@ -0,0 +1,30 @@
+/* gmp-mparam.h -- Compiler/machine parameter header file.
+
+Copyright (C) 1991-2015 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the GNU MP Library. If not, see <http://www.gnu.org/licenses/>. */
+
+#if defined __GMP_H__ && ! defined _LONG_LONG_LIMB
+#error "Included too late for _LONG_LONG_LIMB to take effect"
+#endif
+
+#define _LONG_LONG_LIMB
+#define BITS_PER_MP_LIMB 64
+#define BYTES_PER_MP_LIMB 8
+#define BITS_PER_LONGINT __WORDSIZE
+#define BITS_PER_INT 32
+#define BITS_PER_SHORTINT 16
+#define BITS_PER_CHAR 8
diff --git a/sysdeps/mips/mips64/libm-test-ulps b/sysdeps/mips/mips64/libm-test-ulps
new file mode 100644
index 0000000000..1334eaad69
--- /dev/null
+++ b/sysdeps/mips/mips64/libm-test-ulps
@@ -0,0 +1,2242 @@
+# Begin of automatic generation
+
+# Maximal error of functions:
+Function: "acos":
+float: 1
+ifloat: 1
+
+Function: "acos_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "acos_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "acos_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "acosh":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "acosh_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: "acosh_towardzero":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "acosh_upward":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: "asin":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "asin_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "asin_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "asin_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "asinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "asinh_downward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+ildouble: 3
+ldouble: 3
+
+Function: "asinh_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "asinh_upward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+ildouble: 3
+ldouble: 3
+
+Function: "atan":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "atan2":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "atan2_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "atan2_towardzero":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "atan2_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "atan_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "atan_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "atan_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "atanh":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "atanh_downward":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: "atanh_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "atanh_upward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 3
+ldouble: 3
+
+Function: "cabs":
+double: 1
+idouble: 1
+
+Function: "cabs_downward":
+double: 1
+idouble: 1
+
+Function: "cabs_towardzero":
+double: 1
+idouble: 1
+
+Function: "cabs_upward":
+double: 1
+idouble: 1
+
+Function: Real part of "cacos":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "cacos":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "cacos_downward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "cacos_downward":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+ildouble: 5
+ldouble: 5
+
+Function: Real part of "cacos_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "cacos_towardzero":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+ildouble: 5
+ldouble: 5
+
+Function: Real part of "cacos_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "cacos_upward":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+ildouble: 5
+ldouble: 5
+
+Function: Real part of "cacosh":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "cacosh":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "cacosh_downward":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "cacosh_downward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "cacosh_towardzero":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "cacosh_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "cacosh_upward":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "cacosh_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: "carg":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "carg_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "carg_towardzero":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "carg_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "casin":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "casin":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "casin_downward":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "casin_downward":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+ildouble: 5
+ldouble: 5
+
+Function: Real part of "casin_towardzero":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "casin_towardzero":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+ildouble: 5
+ldouble: 5
+
+Function: Real part of "casin_upward":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "casin_upward":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+ildouble: 5
+ldouble: 5
+
+Function: Real part of "casinh":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "casinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "casinh_downward":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "casinh_downward":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "casinh_towardzero":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "casinh_towardzero":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "casinh_upward":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "casinh_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "catan":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "catan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "catan_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "catan_downward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "catan_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "catan_towardzero":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "catan_upward":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "catan_upward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "catanh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "catanh":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "catanh_downward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "catanh_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "catanh_towardzero":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "catanh_towardzero":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "catanh_upward":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "catanh_upward":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cbrt":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cbrt_downward":
+double: 4
+float: 1
+idouble: 4
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cbrt_towardzero":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cbrt_upward":
+double: 4
+float: 1
+idouble: 4
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ccos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccos_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "ccos_downward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "ccos_towardzero":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "ccos_towardzero":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "ccos_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "ccos_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccosh_downward":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "ccosh_downward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "ccosh_towardzero":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "ccosh_towardzero":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "ccosh_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "ccosh_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "cexp":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "cexp":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cexp_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "cexp_downward":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "cexp_towardzero":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "cexp_towardzero":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "cexp_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "cexp_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "clog":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "clog":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "clog10":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "clog10":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "clog10_downward":
+double: 6
+float: 6
+idouble: 6
+ifloat: 6
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "clog10_downward":
+double: 2
+float: 4
+idouble: 2
+ifloat: 4
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "clog10_towardzero":
+double: 5
+float: 4
+idouble: 5
+ifloat: 4
+ildouble: 6
+ldouble: 6
+
+Function: Imaginary part of "clog10_towardzero":
+double: 2
+float: 4
+idouble: 2
+ifloat: 4
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "clog10_upward":
+double: 8
+float: 5
+idouble: 8
+ifloat: 5
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "clog10_upward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "clog_downward":
+double: 7
+float: 5
+idouble: 7
+ifloat: 5
+ildouble: 6
+ldouble: 6
+
+Function: Imaginary part of "clog_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "clog_towardzero":
+double: 7
+float: 5
+idouble: 7
+ifloat: 5
+ildouble: 6
+ldouble: 6
+
+Function: Imaginary part of "clog_towardzero":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "clog_upward":
+double: 8
+float: 5
+idouble: 8
+ifloat: 5
+ildouble: 6
+ldouble: 6
+
+Function: Imaginary part of "clog_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "cos":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cos_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: "cos_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cos_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "cosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cosh_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 2
+
+Function: "cosh_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 2
+
+Function: "cosh_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 3
+
+Function: Real part of "cpow":
+double: 2
+float: 4
+idouble: 2
+ifloat: 4
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "cpow":
+float: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cpow_downward":
+double: 4
+float: 8
+idouble: 4
+ifloat: 8
+ildouble: 6
+ldouble: 6
+
+Function: Imaginary part of "cpow_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "cpow_towardzero":
+double: 4
+float: 8
+idouble: 4
+ifloat: 8
+ildouble: 6
+ldouble: 6
+
+Function: Imaginary part of "cpow_towardzero":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "cpow_upward":
+double: 4
+float: 1
+idouble: 4
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "cpow_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "csin":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csin":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "csin_downward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "csin_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "csin_towardzero":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "csin_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "csin_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "csin_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "csinh":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "csinh_downward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "csinh_downward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "csinh_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "csinh_towardzero":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "csinh_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "csinh_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "csqrt":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csqrt":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "csqrt_downward":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "csqrt_downward":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "csqrt_towardzero":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "csqrt_towardzero":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "csqrt_upward":
+double: 5
+float: 4
+idouble: 5
+ifloat: 4
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "csqrt_upward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "ctan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "ctan":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "ctan_downward":
+double: 6
+float: 5
+idouble: 6
+ifloat: 5
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "ctan_downward":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 5
+ldouble: 5
+
+Function: Real part of "ctan_towardzero":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "ctan_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 5
+ldouble: 5
+
+Function: Real part of "ctan_upward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "ctan_upward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 5
+ldouble: 5
+
+Function: Real part of "ctanh":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "ctanh":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "ctanh_downward":
+double: 4
+float: 1
+idouble: 4
+ifloat: 1
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "ctanh_downward":
+double: 6
+float: 5
+idouble: 6
+ifloat: 5
+ildouble: 4
+ldouble: 4
+
+Function: Real part of "ctanh_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "ctanh_towardzero":
+double: 5
+float: 3
+idouble: 5
+ifloat: 3
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "ctanh_upward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "ctanh_upward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 5
+ldouble: 5
+
+Function: "erf":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "erf_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: "erf_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "erf_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: "erfc":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "erfc_downward":
+double: 4
+float: 6
+idouble: 4
+ifloat: 6
+ildouble: 3
+ldouble: 3
+
+Function: "erfc_towardzero":
+double: 3
+float: 4
+idouble: 3
+ifloat: 4
+ildouble: 3
+ldouble: 3
+
+Function: "erfc_upward":
+double: 4
+float: 6
+idouble: 4
+ifloat: 6
+ildouble: 3
+ldouble: 3
+
+Function: "exp10":
+double: 2
+idouble: 2
+ildouble: 1
+ldouble: 1
+
+Function: "exp10_downward":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: "exp10_towardzero":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: "exp10_upward":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: "exp2":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "exp2_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "exp2_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "exp2_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "exp_downward":
+double: 1
+idouble: 1
+
+Function: "exp_towardzero":
+double: 1
+idouble: 1
+
+Function: "exp_upward":
+double: 1
+idouble: 1
+
+Function: "expm1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "expm1_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: "expm1_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: "expm1_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: "gamma":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "gamma_downward":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: "gamma_towardzero":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: "gamma_upward":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+ildouble: 3
+ldouble: 3
+
+Function: "hypot":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: "hypot_downward":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: "hypot_towardzero":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: "hypot_upward":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: "j0":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "j0_downward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 4
+ldouble: 4
+
+Function: "j0_towardzero":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "j0_upward":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 5
+ldouble: 5
+
+Function: "j1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 4
+ldouble: 4
+
+Function: "j1_downward":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 4
+ldouble: 4
+
+Function: "j1_towardzero":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 4
+ldouble: 4
+
+Function: "j1_upward":
+double: 3
+float: 5
+idouble: 3
+ifloat: 5
+ildouble: 3
+ldouble: 3
+
+Function: "jn":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+ildouble: 7
+ldouble: 7
+
+Function: "jn_downward":
+double: 5
+float: 5
+idouble: 5
+ifloat: 5
+ildouble: 8
+ldouble: 8
+
+Function: "jn_towardzero":
+double: 5
+float: 5
+idouble: 5
+ifloat: 5
+ildouble: 8
+ldouble: 8
+
+Function: "jn_upward":
+double: 5
+float: 5
+idouble: 5
+ifloat: 5
+ildouble: 7
+ldouble: 7
+
+Function: "lgamma":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "lgamma_downward":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: "lgamma_towardzero":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: "lgamma_upward":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+ildouble: 3
+ldouble: 3
+
+Function: "log":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "log10":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log10_downward":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 1
+ldouble: 1
+
+Function: "log10_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log10_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log1p":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "log1p_downward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log1p_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log1p_upward":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log2":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "log2_downward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+ildouble: 1
+ldouble: 1
+
+Function: "log2_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log2_upward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+ildouble: 1
+ldouble: 1
+
+Function: "log_downward":
+float: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log_towardzero":
+float: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log_upward":
+float: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "pow":
+float: 3
+ifloat: 3
+ildouble: 1
+ldouble: 1
+
+Function: "pow10":
+double: 2
+idouble: 2
+ildouble: 1
+ldouble: 1
+
+Function: "pow10_downward":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: "pow10_towardzero":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: "pow10_upward":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: "pow_downward":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+ildouble: 1
+ldouble: 1
+
+Function: "pow_towardzero":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+ildouble: 1
+ldouble: 1
+
+Function: "pow_upward":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+ildouble: 2
+ldouble: 2
+
+Function: "sin":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "sin_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: "sin_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: "sin_upward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "sincos":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "sincos_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: "sincos_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: "sincos_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: "sinh":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "sinh_downward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: "sinh_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "sinh_upward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: "tan":
+float: 1
+ifloat: 1
+
+Function: "tan_downward":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "tan_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "tan_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "tanh":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "tanh_downward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: "tanh_towardzero":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "tanh_upward":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+ildouble: 3
+ldouble: 3
+
+Function: "tgamma":
+double: 3
+float: 5
+idouble: 3
+ifloat: 5
+ildouble: 4
+ldouble: 4
+
+Function: "tgamma_downward":
+double: 3
+float: 4
+idouble: 3
+ifloat: 4
+ildouble: 5
+ldouble: 5
+
+Function: "tgamma_towardzero":
+double: 3
+float: 5
+idouble: 3
+ifloat: 5
+ildouble: 5
+ldouble: 5
+
+Function: "tgamma_upward":
+double: 3
+float: 5
+idouble: 3
+ifloat: 5
+ildouble: 4
+ldouble: 4
+
+Function: "y0":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: "y0_downward":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 4
+ldouble: 4
+
+Function: "y0_towardzero":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+ildouble: 3
+ldouble: 3
+
+Function: "y0_upward":
+double: 3
+float: 4
+idouble: 3
+ifloat: 4
+ildouble: 3
+ldouble: 3
+
+Function: "y1":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "y1_downward":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 4
+ldouble: 4
+
+Function: "y1_towardzero":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "y1_upward":
+double: 7
+float: 2
+idouble: 7
+ifloat: 2
+ildouble: 5
+ldouble: 5
+
+Function: "yn":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 5
+ldouble: 5
+
+Function: "yn_downward":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 5
+ldouble: 5
+
+Function: "yn_towardzero":
+double: 3
+float: 3
+idouble: 3
+ifloat: 3
+ildouble: 5
+ldouble: 5
+
+Function: "yn_upward":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+ildouble: 5
+ldouble: 5
+
+# end of automatic generation
diff --git a/sysdeps/mips/mips64/lshift.S b/sysdeps/mips/mips64/lshift.S
new file mode 100644
index 0000000000..b5085041a3
--- /dev/null
+++ b/sysdeps/mips/mips64/lshift.S
@@ -0,0 +1,100 @@
+/* MIPS3 __mpn_lshift --
+ *
+ * Copyright (C) 1995-2015 Free Software Foundation, Inc.
+ *
+ * This file is part of the GNU MP Library.
+ *
+ * The GNU MP Library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * The GNU MP Library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the GNU MP Library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+/* INPUT PARAMETERS
+ * res_ptr $4
+ * src_ptr $5
+ * size $6
+ * cnt $7
+ */
+
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (__mpn_lshift)
+#ifdef __PIC__
+ SETUP_GP /* ??? unused */
+#endif
+ .set noreorder
+ .set nomacro
+
+ dsll $2,$6,3
+ daddu $5,$5,$2 # make r5 point at end of src
+ ld $10,-8($5) # load first limb
+ dsubu $13,$0,$7
+ daddu $4,$4,$2 # make r4 point at end of res
+ daddiu $6,$6,-1
+ and $9,$6,4-1 # number of limbs in first loop
+ beq $9,$0,L(L0) # if multiple of 4 limbs, skip first loop
+ dsrl $2,$10,$13 # compute function result
+
+ dsubu $6,$6,$9
+
+L(Loop0): ld $3,-16($5)
+ daddiu $4,$4,-8
+ daddiu $5,$5,-8
+ daddiu $9,$9,-1
+ dsll $11,$10,$7
+ dsrl $12,$3,$13
+ move $10,$3
+ or $8,$11,$12
+ bne $9,$0,L(Loop0)
+ sd $8,0($4)
+
+L(L0): beq $6,$0,L(Lend)
+ nop
+
+L(Loop): ld $3,-16($5)
+ daddiu $4,$4,-32
+ daddiu $6,$6,-4
+ dsll $11,$10,$7
+ dsrl $12,$3,$13
+
+ ld $10,-24($5)
+ dsll $14,$3,$7
+ or $8,$11,$12
+ sd $8,24($4)
+ dsrl $9,$10,$13
+
+ ld $3,-32($5)
+ dsll $11,$10,$7
+ or $8,$14,$9
+ sd $8,16($4)
+ dsrl $12,$3,$13
+
+ ld $10,-40($5)
+ dsll $14,$3,$7
+ or $8,$11,$12
+ sd $8,8($4)
+ dsrl $9,$10,$13
+
+ daddiu $5,$5,-32
+ or $8,$14,$9
+ bgtz $6,L(Loop)
+ sd $8,0($4)
+
+L(Lend): dsll $8,$10,$7
+ j $31
+ sd $8,-8($4)
+END (__mpn_lshift)
diff --git a/sysdeps/mips/mips64/mul_1.S b/sysdeps/mips/mips64/mul_1.S
new file mode 100644
index 0000000000..6fa41e9d00
--- /dev/null
+++ b/sysdeps/mips/mips64/mul_1.S
@@ -0,0 +1,120 @@
+/* MIPS3 __mpn_mul_1 -- Multiply a limb vector with a single limb and
+ * store the product in a second limb vector.
+ *
+ * Copyright (C) 1992-2015 Free Software Foundation, Inc.
+ *
+ * This file is part of the GNU MP Library.
+ *
+ * The GNU MP Library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * The GNU MP Library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the GNU MP Library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+/* INPUT PARAMETERS
+ * res_ptr $4
+ * s1_ptr $5
+ * size $6
+ * s2_limb $7
+ */
+
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (__mpn_mul_1)
+#ifdef __PIC__
+ SETUP_GP /* ??? unused */
+#endif
+ .set noreorder
+ .set nomacro
+
+ # warm up phase 0
+ ld $8,0($5)
+
+ # warm up phase 1
+ daddiu $5,$5,8
+#if __mips_isa_rev < 6
+ dmultu $8,$7
+#else
+ dmulu $11,$8,$7
+ dmuhu $12,$8,$7
+#endif
+
+ daddiu $6,$6,-1
+ beq $6,$0,L(LC0)
+ move $2,$0 # zero cy2
+
+ daddiu $6,$6,-1
+ beq $6,$0,L(LC1)
+ ld $8,0($5) # load new s1 limb as early as possible
+
+#if __mips_isa_rev < 6
+L(Loop): mflo $10
+ mfhi $9
+#else
+L(Loop): move $10,$11
+ move $9,$12
+#endif
+ daddiu $5,$5,8
+ daddu $10,$10,$2 # add old carry limb to low product limb
+#if __mips_isa_rev < 6
+ dmultu $8,$7
+#else
+ dmulu $11,$8,$7
+ dmuhu $12,$8,$7
+#endif
+ ld $8,0($5) # load new s1 limb as early as possible
+ daddiu $6,$6,-1 # decrement loop counter
+ sltu $2,$10,$2 # carry from previous addition -> $2
+ sd $10,0($4)
+ daddiu $4,$4,8
+ bne $6,$0,L(Loop)
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 1
+#if __mips_isa_rev < 6
+L(LC1): mflo $10
+ mfhi $9
+#else
+L(LC1): move $10,$11
+ move $9,$12
+#endif
+ daddu $10,$10,$2
+ sltu $2,$10,$2
+#if __mips_isa_rev < 6
+ dmultu $8,$7
+#else
+ dmulu $11,$8,$7
+ dmuhu $12,$8,$7
+#endif
+ sd $10,0($4)
+ daddiu $4,$4,8
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 0
+#if __mips_isa_rev < 6
+L(LC0): mflo $10
+ mfhi $9
+#else
+L(LC0): move $10,$11
+ move $9,$12
+#endif
+ daddu $10,$10,$2
+ sltu $2,$10,$2
+ sd $10,0($4)
+ j $31
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+END (__mpn_mul_1)
diff --git a/sysdeps/mips/mips64/n32/Implies b/sysdeps/mips/mips64/n32/Implies
new file mode 100644
index 0000000000..e5d8a0e22f
--- /dev/null
+++ b/sysdeps/mips/mips64/n32/Implies
@@ -0,0 +1,5 @@
+mips/ieee754
+ieee754/ldbl-128
+mips/mips64
+mips
+wordsize-32
diff --git a/sysdeps/mips/mips64/n32/Makefile b/sysdeps/mips/mips64/n32/Makefile
new file mode 100644
index 0000000000..a84d2a51bd
--- /dev/null
+++ b/sysdeps/mips/mips64/n32/Makefile
@@ -0,0 +1,6 @@
+# `long double' is a distinct type we support.
+long-double-fcts = yes
+
+ifeq ($(filter -mabi=n32,$(CC)),)
+CC += -mabi=n32
+endif
diff --git a/sysdeps/mips/mips64/n32/_itoa.h b/sysdeps/mips/mips64/n32/_itoa.h
new file mode 100644
index 0000000000..363cdfe9ac
--- /dev/null
+++ b/sysdeps/mips/mips64/n32/_itoa.h
@@ -0,0 +1,4 @@
+/* MIPS n32 uses 64-bit _itoa_word and _itoa is mapped to _itoa_word. */
+#define _ITOA_NEEDED 0
+#define _ITOA_WORD_TYPE unsigned long long int
+#include_next <_itoa.h>
diff --git a/sysdeps/mips/mips64/n32/crti.S b/sysdeps/mips/mips64/n32/crti.S
new file mode 100644
index 0000000000..548c5227f1
--- /dev/null
+++ b/sysdeps/mips/mips64/n32/crti.S
@@ -0,0 +1,93 @@
+/* Special .init and .fini section support for MIPS (n32).
+ Copyright (C) 1995-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file with other
+ programs, and to distribute those programs without any restriction
+ coming from the use of this file. (The GNU Lesser General Public
+ License restrictions do apply in other respects; for example, they
+ cover modification of the file, and distribution when not linked
+ into another program.)
+
+ Note that people who make modified versions of this file are not
+ obligated to grant this special exception for their modified
+ versions; it is their choice whether to do so. The GNU Lesser
+ General Public License gives permission to release a modified
+ version without this exception; this exception also makes it
+ possible to release a modified version which carries forward this
+ exception.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* crti.S puts a function prologue at the beginning of the .init and
+ .fini sections and defines global symbols for those addresses, so
+ they can be called as functions. The symbols _init and _fini are
+ magic and cause the linker to emit DT_INIT and DT_FINI. */
+
+#include <libc-symbols.h>
+
+#ifndef PREINIT_FUNCTION
+# define PREINIT_FUNCTION __gmon_start__
+#endif
+
+#ifndef PREINIT_FUNCTION_WEAK
+# define PREINIT_FUNCTION_WEAK 1
+#endif
+
+#if PREINIT_FUNCTION_WEAK
+ weak_extern (PREINIT_FUNCTION)
+#else
+ .hidden PREINIT_FUNCTION
+#endif
+
+ .set nomips16
+
+ .section .init,"ax",@progbits
+ .p2align 2
+ .globl _init
+ .type _init, @function
+_init:
+ addiu $sp,$sp,-16
+ sd $28,0($sp)
+ lui $28,%hi(%neg(%gp_rel(_init)))
+ addu $28,$28,$25
+ sd $31,8($sp)
+ addiu $28,$28,%lo(%neg(%gp_rel(_init)))
+#if PREINIT_FUNCTION_WEAK
+ lw $2,%got_disp(PREINIT_FUNCTION)($28)
+ beq $2,$0,.Lno_weak_fn
+ lw $25,%call16(PREINIT_FUNCTION)($28)
+ .reloc 1f,R_MIPS_JALR,PREINIT_FUNCTION
+1: jalr $25
+.Lno_weak_fn:
+#else
+ lw $25,%got_disp(PREINIT_FUNCTION)($28)
+ .reloc 1f,R_MIPS_JALR,PREINIT_FUNCTION
+1: jalr $25
+#endif
+
+ .section .fini,"ax",@progbits
+ .p2align 2
+ .globl _fini
+ .type _fini, @function
+_fini:
+ addiu $sp,$sp,-16
+ sd $28,0($sp)
+ lui $28,%hi(%neg(%gp_rel(_fini)))
+ addu $28,$28,$25
+ sd $31,8($sp)
+ addiu $28,$28,%lo(%neg(%gp_rel(_fini)))
diff --git a/sysdeps/mips/mips64/n32/crtn.S b/sysdeps/mips/mips64/n32/crtn.S
new file mode 100644
index 0000000000..e19c9776e3
--- /dev/null
+++ b/sysdeps/mips/mips64/n32/crtn.S
@@ -0,0 +1,59 @@
+/* Special .init and .fini section support for MIPS (n32).
+ Copyright (C) 1995-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file with other
+ programs, and to distribute those programs without any restriction
+ coming from the use of this file. (The GNU Lesser General Public
+ License restrictions do apply in other respects; for example, they
+ cover modification of the file, and distribution when not linked
+ into another program.)
+
+ Note that people who make modified versions of this file are not
+ obligated to grant this special exception for their modified
+ versions; it is their choice whether to do so. The GNU Lesser
+ General Public License gives permission to release a modified
+ version without this exception; this exception also makes it
+ possible to release a modified version which carries forward this
+ exception.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* crtn.S puts function epilogues in the .init and .fini sections
+ corresponding to the prologues in crti.S. */
+
+ .set nomips16
+
+ .section .init,"ax",@progbits
+ ld $31,8($sp)
+ ld $28,0($sp)
+ .set noreorder
+ .set nomacro
+ j $31
+ addiu $sp,$sp,16
+ .set macro
+ .set reorder
+
+ .section .fini,"ax",@progbits
+ ld $31,8($sp)
+ ld $28,0($sp)
+ .set noreorder
+ .set nomacro
+ j $31
+ addiu $sp,$sp,16
+ .set macro
+ .set reorder
diff --git a/sysdeps/mips/mips64/n32/fpu/e_sqrt.c b/sysdeps/mips/mips64/n32/fpu/e_sqrt.c
new file mode 100644
index 0000000000..81f4e77697
--- /dev/null
+++ b/sysdeps/mips/mips64/n32/fpu/e_sqrt.c
@@ -0,0 +1 @@
+#include <sysdeps/mips/fpu/e_sqrt.c>
diff --git a/sysdeps/mips/mips64/n32/fpu/e_sqrtf.c b/sysdeps/mips/mips64/n32/fpu/e_sqrtf.c
new file mode 100644
index 0000000000..fb0700d45c
--- /dev/null
+++ b/sysdeps/mips/mips64/n32/fpu/e_sqrtf.c
@@ -0,0 +1 @@
+#include <sysdeps/mips/fpu/e_sqrtf.c>
diff --git a/sysdeps/mips/mips64/n64/Implies b/sysdeps/mips/mips64/n64/Implies
new file mode 100644
index 0000000000..25ad0cf458
--- /dev/null
+++ b/sysdeps/mips/mips64/n64/Implies
@@ -0,0 +1,5 @@
+mips/ieee754
+ieee754/ldbl-128
+mips/mips64
+mips
+wordsize-64
diff --git a/sysdeps/mips/mips64/n64/Makefile b/sysdeps/mips/mips64/n64/Makefile
new file mode 100644
index 0000000000..a823f32b53
--- /dev/null
+++ b/sysdeps/mips/mips64/n64/Makefile
@@ -0,0 +1,6 @@
+# `long double' is a distinct type we support.
+long-double-fcts = yes
+
+ifeq ($(filter -mabi=64,$(CC)),)
+CC += -mabi=64
+endif
diff --git a/sysdeps/mips/mips64/n64/crti.S b/sysdeps/mips/mips64/n64/crti.S
new file mode 100644
index 0000000000..55ab3fdfb3
--- /dev/null
+++ b/sysdeps/mips/mips64/n64/crti.S
@@ -0,0 +1,93 @@
+/* Special .init and .fini section support for MIPS (n64).
+ Copyright (C) 1995-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file with other
+ programs, and to distribute those programs without any restriction
+ coming from the use of this file. (The GNU Lesser General Public
+ License restrictions do apply in other respects; for example, they
+ cover modification of the file, and distribution when not linked
+ into another program.)
+
+ Note that people who make modified versions of this file are not
+ obligated to grant this special exception for their modified
+ versions; it is their choice whether to do so. The GNU Lesser
+ General Public License gives permission to release a modified
+ version without this exception; this exception also makes it
+ possible to release a modified version which carries forward this
+ exception.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* crti.S puts a function prologue at the beginning of the .init and
+ .fini sections and defines global symbols for those addresses, so
+ they can be called as functions. The symbols _init and _fini are
+ magic and cause the linker to emit DT_INIT and DT_FINI. */
+
+#include <libc-symbols.h>
+
+#ifndef PREINIT_FUNCTION
+# define PREINIT_FUNCTION __gmon_start__
+#endif
+
+#ifndef PREINIT_FUNCTION_WEAK
+# define PREINIT_FUNCTION_WEAK 1
+#endif
+
+#if PREINIT_FUNCTION_WEAK
+ weak_extern (PREINIT_FUNCTION)
+#else
+ .hidden PREINIT_FUNCTION
+#endif
+
+ .set nomips16
+
+ .section .init,"ax",@progbits
+ .p2align 2
+ .globl _init
+ .type _init, @function
+_init:
+ daddiu $sp,$sp,-16
+ sd $28,0($sp)
+ lui $28,%hi(%neg(%gp_rel(_init)))
+ daddu $28,$28,$25
+ sd $31,8($sp)
+ daddiu $28,$28,%lo(%neg(%gp_rel(_init)))
+#if PREINIT_FUNCTION_WEAK
+ ld $2,%got_disp(PREINIT_FUNCTION)($28)
+ beq $2,$0,.Lno_weak_fn
+ ld $25,%call16(PREINIT_FUNCTION)($28)
+ .reloc 1f,R_MIPS_JALR,PREINIT_FUNCTION
+1: jalr $25
+.Lno_weak_fn:
+#else
+ ld $25,%got_disp(PREINIT_FUNCTION)($28)
+ .reloc 1f,R_MIPS_JALR,PREINIT_FUNCTION
+1: jalr $25
+#endif
+
+ .section .fini,"ax",@progbits
+ .p2align 2
+ .globl _fini
+ .type _fini, @function
+_fini:
+ daddiu $sp,$sp,-16
+ sd $28,0($sp)
+ lui $28,%hi(%neg(%gp_rel(_fini)))
+ daddu $28,$28,$25
+ sd $31,8($sp)
+ daddiu $28,$28,%lo(%neg(%gp_rel(_fini)))
diff --git a/sysdeps/mips/mips64/n64/crtn.S b/sysdeps/mips/mips64/n64/crtn.S
new file mode 100644
index 0000000000..a18f9cdbd6
--- /dev/null
+++ b/sysdeps/mips/mips64/n64/crtn.S
@@ -0,0 +1,59 @@
+/* Special .init and .fini section support for MIPS (n64).
+ Copyright (C) 1995-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file with other
+ programs, and to distribute those programs without any restriction
+ coming from the use of this file. (The GNU Lesser General Public
+ License restrictions do apply in other respects; for example, they
+ cover modification of the file, and distribution when not linked
+ into another program.)
+
+ Note that people who make modified versions of this file are not
+ obligated to grant this special exception for their modified
+ versions; it is their choice whether to do so. The GNU Lesser
+ General Public License gives permission to release a modified
+ version without this exception; this exception also makes it
+ possible to release a modified version which carries forward this
+ exception.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* crtn.S puts function epilogues in the .init and .fini sections
+ corresponding to the prologues in crti.S. */
+
+ .set nomips16
+
+ .section .init,"ax",@progbits
+ ld $31,8($sp)
+ ld $28,0($sp)
+ .set noreorder
+ .set nomacro
+ j $31
+ daddiu $sp,$sp,16
+ .set macro
+ .set reorder
+
+ .section .fini,"ax",@progbits
+ ld $31,8($sp)
+ ld $28,0($sp)
+ .set noreorder
+ .set nomacro
+ j $31
+ daddiu $sp,$sp,16
+ .set macro
+ .set reorder
diff --git a/sysdeps/mips/mips64/n64/fpu/e_sqrt.c b/sysdeps/mips/mips64/n64/fpu/e_sqrt.c
new file mode 100644
index 0000000000..81f4e77697
--- /dev/null
+++ b/sysdeps/mips/mips64/n64/fpu/e_sqrt.c
@@ -0,0 +1 @@
+#include <sysdeps/mips/fpu/e_sqrt.c>
diff --git a/sysdeps/mips/mips64/n64/fpu/e_sqrtf.c b/sysdeps/mips/mips64/n64/fpu/e_sqrtf.c
new file mode 100644
index 0000000000..fb0700d45c
--- /dev/null
+++ b/sysdeps/mips/mips64/n64/fpu/e_sqrtf.c
@@ -0,0 +1 @@
+#include <sysdeps/mips/fpu/e_sqrtf.c>
diff --git a/sysdeps/mips/mips64/rshift.S b/sysdeps/mips/mips64/rshift.S
new file mode 100644
index 0000000000..5f8e7f9376
--- /dev/null
+++ b/sysdeps/mips/mips64/rshift.S
@@ -0,0 +1,97 @@
+/* MIPS3 __mpn_rshift --
+ *
+ * Copyright (C) 1995-2015 Free Software Foundation, Inc.
+ *
+ * This file is part of the GNU MP Library.
+ *
+ * The GNU MP Library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * The GNU MP Library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the GNU MP Library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+/* INPUT PARAMETERS
+ * res_ptr $4
+ * src_ptr $5
+ * size $6
+ * cnt $7
+ */
+
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (__mpn_rshift)
+#ifdef __PIC__
+ SETUP_GP /* ??? unused */
+#endif
+ .set noreorder
+ .set nomacro
+
+ ld $10,0($5) # load first limb
+ dsubu $13,$0,$7
+ daddiu $6,$6,-1
+ and $9,$6,4-1 # number of limbs in first loop
+ beq $9,$0,L(L0) # if multiple of 4 limbs, skip first loop
+ dsll $2,$10,$13 # compute function result
+
+ dsubu $6,$6,$9
+
+L(Loop0): ld $3,8($5)
+ daddiu $4,$4,8
+ daddiu $5,$5,8
+ daddiu $9,$9,-1
+ dsrl $11,$10,$7
+ dsll $12,$3,$13
+ move $10,$3
+ or $8,$11,$12
+ bne $9,$0,L(Loop0)
+ sd $8,-8($4)
+
+L(L0): beq $6,$0,L(Lend)
+ nop
+
+L(Loop): ld $3,8($5)
+ daddiu $4,$4,32
+ daddiu $6,$6,-4
+ dsrl $11,$10,$7
+ dsll $12,$3,$13
+
+ ld $10,16($5)
+ dsrl $14,$3,$7
+ or $8,$11,$12
+ sd $8,-32($4)
+ dsll $9,$10,$13
+
+ ld $3,24($5)
+ dsrl $11,$10,$7
+ or $8,$14,$9
+ sd $8,-24($4)
+ dsll $12,$3,$13
+
+ ld $10,32($5)
+ dsrl $14,$3,$7
+ or $8,$11,$12
+ sd $8,-16($4)
+ dsll $9,$10,$13
+
+ daddiu $5,$5,32
+ or $8,$14,$9
+ bgtz $6,L(Loop)
+ sd $8,-8($4)
+
+L(Lend): dsrl $8,$10,$7
+ j $31
+ sd $8,0($4)
+END (__mpn_rshift)
diff --git a/sysdeps/mips/mips64/setjmp.S b/sysdeps/mips/mips64/setjmp.S
new file mode 100644
index 0000000000..e78ce25214
--- /dev/null
+++ b/sysdeps/mips/mips64/setjmp.S
@@ -0,0 +1,44 @@
+/* Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sgidefs.h>
+#include <sysdep.h>
+#include <sys/asm.h>
+
+/* The function __sigsetjmp_aux saves all the registers, but it can't
+ reliably access the stack or frame pointers, so we pass them in as
+ extra arguments. */
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (__sigsetjmp)
+#ifdef __PIC__
+ SETUP_GP
+#endif
+ SETUP_GP64_REG (v0, C_SYMBOL_NAME (__sigsetjmp))
+ move a2, sp
+ move a3, fp
+ PTR_LA t9, __sigsetjmp_aux
+#if _MIPS_SIM == _ABIO32
+ nop
+#endif
+ RESTORE_GP64_REG
+#if _MIPS_SIM != _ABIO32
+ move a4, gp
+#endif
+ jr t9
+END (__sigsetjmp)
diff --git a/sysdeps/mips/mips64/setjmp_aux.c b/sysdeps/mips/mips64/setjmp_aux.c
new file mode 100644
index 0000000000..6eeab2b744
--- /dev/null
+++ b/sysdeps/mips/mips64/setjmp_aux.c
@@ -0,0 +1,76 @@
+/* Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Brendan Kehoe (brendan@zen.org).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <setjmp.h>
+#include <sgidefs.h>
+
+/* This function is only called via the assembly language routine
+ __sigsetjmp, which arranges to pass in the stack pointer and the frame
+ pointer. We do things this way because it's difficult to reliably
+ access them in C. */
+
+int
+__sigsetjmp_aux (jmp_buf env, int savemask, long long sp, long long fp,
+ long long gp)
+{
+#ifdef __mips_hard_float
+ /* Store the floating point callee-saved registers... */
+#if _MIPS_SIM == _ABI64
+ asm volatile ("s.d $f24, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[0]));
+ asm volatile ("s.d $f25, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[1]));
+ asm volatile ("s.d $f26, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[2]));
+ asm volatile ("s.d $f27, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[3]));
+ asm volatile ("s.d $f28, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[4]));
+ asm volatile ("s.d $f29, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[5]));
+ asm volatile ("s.d $f30, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[6]));
+ asm volatile ("s.d $f31, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[7]));
+#else
+ asm volatile ("s.d $f20, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[0]));
+ asm volatile ("s.d $f22, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[1]));
+ asm volatile ("s.d $f24, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[2]));
+ asm volatile ("s.d $f26, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[3]));
+ asm volatile ("s.d $f28, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[4]));
+ asm volatile ("s.d $f30, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[5]));
+#endif
+#endif
+
+ /* .. and the PC; */
+ asm volatile ("sd $31, %0" : : "m" (env[0].__jmpbuf[0].__pc));
+
+ /* .. and the stack pointer; */
+ env[0].__jmpbuf[0].__sp = sp;
+
+ /* .. and the FP; it'll be in s8. */
+ env[0].__jmpbuf[0].__fp = fp;
+
+ /* .. and the GP; */
+ env[0].__jmpbuf[0].__gp = gp;
+
+ /* .. and the callee-saved registers; */
+ asm volatile ("sd $16, %0" : : "m" (env[0].__jmpbuf[0].__regs[0]));
+ asm volatile ("sd $17, %0" : : "m" (env[0].__jmpbuf[0].__regs[1]));
+ asm volatile ("sd $18, %0" : : "m" (env[0].__jmpbuf[0].__regs[2]));
+ asm volatile ("sd $19, %0" : : "m" (env[0].__jmpbuf[0].__regs[3]));
+ asm volatile ("sd $20, %0" : : "m" (env[0].__jmpbuf[0].__regs[4]));
+ asm volatile ("sd $21, %0" : : "m" (env[0].__jmpbuf[0].__regs[5]));
+ asm volatile ("sd $22, %0" : : "m" (env[0].__jmpbuf[0].__regs[6]));
+ asm volatile ("sd $23, %0" : : "m" (env[0].__jmpbuf[0].__regs[7]));
+
+ /* Save the signal mask if requested. */
+ return __sigjmp_save (env, savemask);
+}
diff --git a/sysdeps/mips/mips64/sfp-machine.h b/sysdeps/mips/mips64/sfp-machine.h
new file mode 100644
index 0000000000..708afc783e
--- /dev/null
+++ b/sysdeps/mips/mips64/sfp-machine.h
@@ -0,0 +1,96 @@
+#include <fenv.h>
+#include <fpu_control.h>
+
+#define _FP_W_TYPE_SIZE 64
+#define _FP_W_TYPE unsigned long long
+#define _FP_WS_TYPE signed long long
+#define _FP_I_TYPE long long
+
+#define _FP_MUL_MEAT_S(R,X,Y) \
+ _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S,R,X,Y)
+#define _FP_MUL_MEAT_D(R,X,Y) \
+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y) \
+ _FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_MUL_MEAT_DW_S(R,X,Y) \
+ _FP_MUL_MEAT_DW_1_imm(_FP_WFRACBITS_S,R,X,Y)
+#define _FP_MUL_MEAT_DW_D(R,X,Y) \
+ _FP_MUL_MEAT_DW_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_DW_Q(R,X,Y) \
+ _FP_MUL_MEAT_DW_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y)
+
+#ifdef __mips_nan2008
+# define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
+# define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1)
+# define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1
+#else
+# define _FP_NANFRAC_S (_FP_QNANBIT_S - 1)
+# define _FP_NANFRAC_D (_FP_QNANBIT_D - 1)
+# define _FP_NANFRAC_Q (_FP_QNANBIT_Q - 1), -1
+#endif
+#define _FP_NANSIGN_S 0
+#define _FP_NANSIGN_D 0
+#define _FP_NANSIGN_Q 0
+
+#define _FP_KEEPNANFRACP 1
+#ifdef __mips_nan2008
+# define _FP_QNANNEGATEDP 0
+#else
+# define _FP_QNANNEGATEDP 1
+#endif
+
+/* From my experiments it seems X is chosen unless one of the
+ NaNs is sNaN, in which case the result is NANSIGN/NANFRAC. */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
+ do { \
+ if ((_FP_FRAC_HIGH_RAW_##fs(X) | \
+ _FP_FRAC_HIGH_RAW_##fs(Y)) & _FP_QNANBIT_##fs) \
+ { \
+ R##_s = _FP_NANSIGN_##fs; \
+ _FP_FRAC_SET_##wc(R,_FP_NANFRAC_##fs); \
+ } \
+ else \
+ { \
+ R##_s = X##_s; \
+ _FP_FRAC_COPY_##wc(R,X); \
+ } \
+ R##_c = FP_CLS_NAN; \
+ } while (0)
+
+#define _FP_DECL_EX fpu_control_t _fcw
+
+#define FP_ROUNDMODE (_fcw & 0x3)
+
+#define FP_RND_NEAREST FE_TONEAREST
+#define FP_RND_ZERO FE_TOWARDZERO
+#define FP_RND_PINF FE_UPWARD
+#define FP_RND_MINF FE_DOWNWARD
+
+#define FP_EX_INVALID FE_INVALID
+#define FP_EX_OVERFLOW FE_OVERFLOW
+#define FP_EX_UNDERFLOW FE_UNDERFLOW
+#define FP_EX_DIVZERO FE_DIVBYZERO
+#define FP_EX_INEXACT FE_INEXACT
+
+#define _FP_TININESS_AFTER_ROUNDING 1
+
+#ifdef __mips_hard_float
+#define FP_INIT_ROUNDMODE \
+do { \
+ _FPU_GETCW (_fcw); \
+} while (0)
+
+#define FP_HANDLE_EXCEPTIONS \
+do { \
+ if (__builtin_expect (_fex, 0)) \
+ _FPU_SETCW (_fcw | _fex | (_fex << 10)); \
+} while (0)
+#define FP_TRAPPING_EXCEPTIONS ((_fcw >> 5) & 0x7c)
+#else
+#define FP_INIT_ROUNDMODE _fcw = FP_RND_NEAREST
+#endif
diff --git a/sysdeps/mips/mips64/sub_n.S b/sysdeps/mips/mips64/sub_n.S
new file mode 100644
index 0000000000..69fcac76a0
--- /dev/null
+++ b/sysdeps/mips/mips64/sub_n.S
@@ -0,0 +1,125 @@
+/* MIPS3 __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
+ * store difference in a third limb vector.
+ *
+ * Copyright (C) 1995-2015 Free Software Foundation, Inc.
+ *
+ * This file is part of the GNU MP Library.
+ *
+ * The GNU MP Library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * The GNU MP Library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the GNU MP Library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+/* INPUT PARAMETERS
+ * res_ptr $4
+ * s1_ptr $5
+ * s2_ptr $6
+ * size $7
+ */
+
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (__mpn_sub_n)
+#ifdef __PIC__
+ SETUP_GP /* ??? unused */
+#endif
+ .set noreorder
+ .set nomacro
+
+ ld $10,0($5)
+ ld $11,0($6)
+
+ daddiu $7,$7,-1
+ and $9,$7,4-1 # number of limbs in first loop
+ beq $9,$0,L(L0) # if multiple of 4 limbs, skip first loop
+ move $2,$0
+
+ dsubu $7,$7,$9
+
+L(Loop0): daddiu $9,$9,-1
+ ld $12,8($5)
+ daddu $11,$11,$2
+ ld $13,8($6)
+ sltu $8,$11,$2
+ dsubu $11,$10,$11
+ sltu $2,$10,$11
+ sd $11,0($4)
+ or $2,$2,$8
+
+ daddiu $5,$5,8
+ daddiu $6,$6,8
+ move $10,$12
+ move $11,$13
+ bne $9,$0,L(Loop0)
+ daddiu $4,$4,8
+
+L(L0): beq $7,$0,L(Lend)
+ nop
+
+L(Loop): daddiu $7,$7,-4
+
+ ld $12,8($5)
+ daddu $11,$11,$2
+ ld $13,8($6)
+ sltu $8,$11,$2
+ dsubu $11,$10,$11
+ sltu $2,$10,$11
+ sd $11,0($4)
+ or $2,$2,$8
+
+ ld $10,16($5)
+ daddu $13,$13,$2
+ ld $11,16($6)
+ sltu $8,$13,$2
+ dsubu $13,$12,$13
+ sltu $2,$12,$13
+ sd $13,8($4)
+ or $2,$2,$8
+
+ ld $12,24($5)
+ daddu $11,$11,$2
+ ld $13,24($6)
+ sltu $8,$11,$2
+ dsubu $11,$10,$11
+ sltu $2,$10,$11
+ sd $11,16($4)
+ or $2,$2,$8
+
+ ld $10,32($5)
+ daddu $13,$13,$2
+ ld $11,32($6)
+ sltu $8,$13,$2
+ dsubu $13,$12,$13
+ sltu $2,$12,$13
+ sd $13,24($4)
+ or $2,$2,$8
+
+ daddiu $5,$5,32
+ daddiu $6,$6,32
+
+ bne $7,$0,L(Loop)
+ daddiu $4,$4,32
+
+L(Lend): daddu $11,$11,$2
+ sltu $8,$11,$2
+ dsubu $11,$10,$11
+ sltu $2,$10,$11
+ sd $11,0($4)
+ j $31
+ or $2,$2,$8
+
+END (__mpn_sub_n)
diff --git a/sysdeps/mips/mips64/submul_1.S b/sysdeps/mips/mips64/submul_1.S
new file mode 100644
index 0000000000..0522ca600e
--- /dev/null
+++ b/sysdeps/mips/mips64/submul_1.S
@@ -0,0 +1,132 @@
+/* MIPS3 __mpn_submul_1 -- Multiply a limb vector with a single limb and
+ * subtract the product from a second limb vector.
+ *
+ * Copyright (C) 1992-2015 Free Software Foundation, Inc.
+ *
+ * This file is part of the GNU MP Library.
+ *
+ * The GNU MP Library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * The GNU MP Library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the GNU MP Library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+/* INPUT PARAMETERS
+ * res_ptr $4
+ * s1_ptr $5
+ * size $6
+ * s2_limb $7
+ */
+
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (__mpn_submul_1)
+#ifdef __PIC__
+ SETUP_GP /* ??? unused */
+#endif
+ .set noreorder
+ .set nomacro
+
+ # warm up phase 0
+ ld $8,0($5)
+
+ # warm up phase 1
+ daddiu $5,$5,8
+#if __mips_isa_rev < 6
+ dmultu $8,$7
+#else
+ dmulu $11,$8,$7
+ dmuhu $12,$8,$7
+#endif
+
+ daddiu $6,$6,-1
+ beq $6,$0,L(LC0)
+ move $2,$0 # zero cy2
+
+ daddiu $6,$6,-1
+ beq $6,$0,L(LC1)
+ ld $8,0($5) # load new s1 limb as early as possible
+
+L(Loop): ld $10,0($4)
+#if __mips_isa_rev < 6
+ mflo $3
+ mfhi $9
+#else
+ move $3,$11
+ move $9,$12
+#endif
+ daddiu $5,$5,8
+ daddu $3,$3,$2 # add old carry limb to low product limb
+#if __mips_isa_rev < 6
+ dmultu $8,$7
+#else
+ dmulu $11,$8,$7
+ dmuhu $12,$8,$7
+#endif
+ ld $8,0($5) # load new s1 limb as early as possible
+ daddiu $6,$6,-1 # decrement loop counter
+ sltu $2,$3,$2 # carry from previous addition -> $2
+ dsubu $3,$10,$3
+ sgtu $10,$3,$10
+ daddu $2,$2,$10
+ sd $3,0($4)
+ daddiu $4,$4,8
+ bne $6,$0,L(Loop)
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 1
+L(LC1): ld $10,0($4)
+#if __mips_isa_rev < 6
+ mflo $3
+ mfhi $9
+#else
+ move $3,$11
+ move $9,$12
+#endif
+ daddu $3,$3,$2
+ sltu $2,$3,$2
+#if __mips_isa_rev < 6
+ dmultu $8,$7
+#else
+ dmulu $11,$8,$7
+ dmuhu $12,$8,$7
+#endif
+ dsubu $3,$10,$3
+ sgtu $10,$3,$10
+ daddu $2,$2,$10
+ sd $3,0($4)
+ daddiu $4,$4,8
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+ # cool down phase 0
+L(LC0): ld $10,0($4)
+#if __mips_isa_rev < 6
+ mflo $3
+ mfhi $9
+#else
+ move $3,$11
+ move $9,$12
+#endif
+ daddu $3,$3,$2
+ sltu $2,$3,$2
+ dsubu $3,$10,$3
+ sgtu $10,$3,$10
+ daddu $2,$2,$10
+ sd $3,0($4)
+ j $31
+ daddu $2,$9,$2 # add high product limb and carry from addition
+
+END (__mpn_submul_1)
diff --git a/sysdeps/mips/mul_1.S b/sysdeps/mips/mul_1.S
new file mode 100644
index 0000000000..2defcabbf4
--- /dev/null
+++ b/sysdeps/mips/mul_1.S
@@ -0,0 +1,117 @@
+/* MIPS __mpn_mul_1 -- Multiply a limb vector with a single limb and
+store the product in a second limb vector.
+
+Copyright (C) 1995-2015 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the GNU MP Library. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+/* INPUT PARAMETERS
+ res_ptr $4
+ s1_ptr $5
+ size $6
+ s2_limb $7
+*/
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (__mpn_mul_1)
+ .set noreorder
+#ifdef __PIC__
+ .cpload t9
+#endif
+ .set nomacro
+
+ /* warm up phase 0 */
+ lw $8,0($5)
+
+ /* warm up phase 1 */
+ addiu $5,$5,4
+#if __mips_isa_rev < 6
+ multu $8,$7
+#else
+ mulu $11,$8,$7
+ muhu $12,$8,$7
+#endif
+
+ addiu $6,$6,-1
+ beq $6,$0,L(LC0)
+ move $2,$0 /* zero cy2 */
+
+ addiu $6,$6,-1
+ beq $6,$0,L(LC1)
+ lw $8,0($5) /* load new s1 limb as early as possible */
+
+
+#if __mips_isa_rev < 6
+L(Loop): mflo $10
+ mfhi $9
+#else
+L(Loop): move $10,$11
+ move $9,$12
+#endif
+ addiu $5,$5,4
+ addu $10,$10,$2 /* add old carry limb to low product limb */
+#if __mips_isa_rev < 6
+ multu $8,$7
+#else
+ mulu $11,$8,$7
+ muhu $12,$8,$7
+#endif
+ lw $8,0($5) /* load new s1 limb as early as possible */
+ addiu $6,$6,-1 /* decrement loop counter */
+ sltu $2,$10,$2 /* carry from previous addition -> $2 */
+ sw $10,0($4)
+ addiu $4,$4,4
+ bne $6,$0,L(Loop) /* should be "bnel" */
+ addu $2,$9,$2 /* add high product limb and carry from addition */
+
+ /* cool down phase 1 */
+#if __mips_isa_rev < 6
+L(LC1): mflo $10
+ mfhi $9
+#else
+L(LC1): move $10,$11
+ move $9,$12
+#endif
+ addu $10,$10,$2
+ sltu $2,$10,$2
+#if __mips_isa_rev < 6
+ multu $8,$7
+#else
+ mulu $11,$8,$7
+ muhu $12,$8,$7
+#endif
+ sw $10,0($4)
+ addiu $4,$4,4
+ addu $2,$9,$2 /* add high product limb and carry from addition */
+
+ /* cool down phase 0 */
+#if __mips_isa_rev < 6
+L(LC0): mflo $10
+ mfhi $9
+#else
+L(LC0): move $10,$11
+ move $9,$12
+#endif
+ addu $10,$10,$2
+ sltu $2,$10,$2
+ sw $10,0($4)
+ j $31
+ addu $2,$9,$2 /* add high product limb and carry from addition */
+ END (__mpn_mul_1)
diff --git a/sysdeps/mips/nptl/Makefile b/sysdeps/mips/nptl/Makefile
new file mode 100644
index 0000000000..46baad538e
--- /dev/null
+++ b/sysdeps/mips/nptl/Makefile
@@ -0,0 +1,24 @@
+# Copyright (C) 2005-2015 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+#
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library. If not, see
+# <http://www.gnu.org/licenses/>.
+
+ifeq ($(subdir),csu)
+gen-as-const-headers += tcb-offsets.sym
+endif
+
+ifeq ($(subdir),nptl)
+libpthread-sysdep_routines += nptl-sysdep
+endif
diff --git a/sysdeps/mips/nptl/bits/pthreadtypes.h b/sysdeps/mips/nptl/bits/pthreadtypes.h
new file mode 100644
index 0000000000..8cf45478b4
--- /dev/null
+++ b/sysdeps/mips/nptl/bits/pthreadtypes.h
@@ -0,0 +1,237 @@
+/* Machine-specific pthread type layouts. MIPS version.
+ Copyright (C) 2005-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _BITS_PTHREADTYPES_H
+#define _BITS_PTHREADTYPES_H 1
+
+#include <endian.h>
+
+#if _MIPS_SIM == _ABI64
+# define __SIZEOF_PTHREAD_ATTR_T 56
+# define __SIZEOF_PTHREAD_MUTEX_T 40
+# define __SIZEOF_PTHREAD_MUTEXATTR_T 4
+# define __SIZEOF_PTHREAD_COND_T 48
+# define __SIZEOF_PTHREAD_CONDATTR_T 4
+# define __SIZEOF_PTHREAD_RWLOCK_T 56
+# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
+# define __SIZEOF_PTHREAD_BARRIER_T 32
+# define __SIZEOF_PTHREAD_BARRIERATTR_T 4
+#else
+# define __SIZEOF_PTHREAD_ATTR_T 36
+# define __SIZEOF_PTHREAD_MUTEX_T 24
+# define __SIZEOF_PTHREAD_MUTEXATTR_T 4
+# define __SIZEOF_PTHREAD_COND_T 48
+# define __SIZEOF_PTHREAD_CONDATTR_T 4
+# define __SIZEOF_PTHREAD_RWLOCK_T 32
+# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
+# define __SIZEOF_PTHREAD_BARRIER_T 20
+# define __SIZEOF_PTHREAD_BARRIERATTR_T 4
+#endif
+
+
+/* Thread identifiers. The structure of the attribute type is
+ deliberately not exposed. */
+typedef unsigned long int pthread_t;
+
+
+union pthread_attr_t
+{
+ char __size[__SIZEOF_PTHREAD_ATTR_T];
+ long int __align;
+};
+#ifndef __have_pthread_attr_t
+typedef union pthread_attr_t pthread_attr_t;
+# define __have_pthread_attr_t 1
+#endif
+
+
+#if _MIPS_SIM == _ABI64
+typedef struct __pthread_internal_list
+{
+ struct __pthread_internal_list *__prev;
+ struct __pthread_internal_list *__next;
+} __pthread_list_t;
+#else
+typedef struct __pthread_internal_slist
+{
+ struct __pthread_internal_slist *__next;
+} __pthread_slist_t;
+#endif
+
+
+/* Data structures for mutex handling. The structure of the attribute
+ type is deliberately not exposed. */
+typedef union
+{
+ struct __pthread_mutex_s
+ {
+ int __lock;
+ unsigned int __count;
+ int __owner;
+#if _MIPS_SIM == _ABI64
+ unsigned int __nusers;
+#endif
+ /* KIND must stay at this position in the structure to maintain
+ binary compatibility. */
+ int __kind;
+#if _MIPS_SIM == _ABI64
+ int __spins;
+ __pthread_list_t __list;
+# define __PTHREAD_MUTEX_HAVE_PREV 1
+#else
+ unsigned int __nusers;
+ __extension__ union
+ {
+ int __spins;
+ __pthread_slist_t __list;
+ };
+#endif
+ } __data;
+ char __size[__SIZEOF_PTHREAD_MUTEX_T];
+ long int __align;
+} pthread_mutex_t;
+
+/* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER. */
+#define __PTHREAD_SPINS 0
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
+ int __align;
+} pthread_mutexattr_t;
+
+
+/* Data structure for conditional variable handling. The structure of
+ the attribute type is deliberately not exposed. */
+typedef union
+{
+ struct
+ {
+ int __lock;
+ unsigned int __futex;
+ __extension__ unsigned long long int __total_seq;
+ __extension__ unsigned long long int __wakeup_seq;
+ __extension__ unsigned long long int __woken_seq;
+ void *__mutex;
+ unsigned int __nwaiters;
+ unsigned int __broadcast_seq;
+ } __data;
+ char __size[__SIZEOF_PTHREAD_COND_T];
+ __extension__ long long int __align;
+} pthread_cond_t;
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_CONDATTR_T];
+ int __align;
+} pthread_condattr_t;
+
+
+/* Keys for thread-specific data */
+typedef unsigned int pthread_key_t;
+
+
+/* Once-only execution */
+typedef int pthread_once_t;
+
+
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K
+/* Data structure for read-write lock variable handling. The
+ structure of the attribute type is deliberately not exposed. */
+typedef union
+{
+# if _MIPS_SIM == _ABI64
+ struct
+ {
+ int __lock;
+ unsigned int __nr_readers;
+ unsigned int __readers_wakeup;
+ unsigned int __writer_wakeup;
+ unsigned int __nr_readers_queued;
+ unsigned int __nr_writers_queued;
+ int __writer;
+ int __shared;
+ unsigned long int __pad1;
+ unsigned long int __pad2;
+ /* FLAGS must stay at this position in the structure to maintain
+ binary compatibility. */
+ unsigned int __flags;
+ } __data;
+# else
+ struct
+ {
+ int __lock;
+ unsigned int __nr_readers;
+ unsigned int __readers_wakeup;
+ unsigned int __writer_wakeup;
+ unsigned int __nr_readers_queued;
+ unsigned int __nr_writers_queued;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char __pad1;
+ unsigned char __pad2;
+ unsigned char __shared;
+ /* FLAGS must stay at this position in the structure to maintain
+ binary compatibility. */
+ unsigned char __flags;
+#else
+ /* FLAGS must stay at this position in the structure to maintain
+ binary compatibility. */
+ unsigned char __flags;
+ unsigned char __shared;
+ unsigned char __pad1;
+ unsigned char __pad2;
+#endif
+ int __writer;
+ } __data;
+# endif
+ char __size[__SIZEOF_PTHREAD_RWLOCK_T];
+ long int __align;
+} pthread_rwlock_t;
+
+#define __PTHREAD_RWLOCK_ELISION_EXTRA 0
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T];
+ long int __align;
+} pthread_rwlockattr_t;
+#endif
+
+
+#ifdef __USE_XOPEN2K
+/* POSIX spinlock data type. */
+typedef volatile int pthread_spinlock_t;
+
+
+/* POSIX barriers data type. The structure of the type is
+ deliberately not exposed. */
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_BARRIER_T];
+ long int __align;
+} pthread_barrier_t;
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_BARRIERATTR_T];
+ int __align;
+} pthread_barrierattr_t;
+#endif
+
+
+#endif /* bits/pthreadtypes.h */
diff --git a/sysdeps/mips/nptl/bits/semaphore.h b/sysdeps/mips/nptl/bits/semaphore.h
new file mode 100644
index 0000000000..03b2e509bc
--- /dev/null
+++ b/sysdeps/mips/nptl/bits/semaphore.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _SEMAPHORE_H
+# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead."
+#endif
+
+#if _MIPS_SIM == _ABI64
+# define __SIZEOF_SEM_T 32
+#else
+# define __SIZEOF_SEM_T 16
+#endif
+
+/* Value returned if `sem_open' failed. */
+#define SEM_FAILED ((sem_t *) 0)
+
+
+typedef union
+{
+ char __size[__SIZEOF_SEM_T];
+ long int __align;
+} sem_t;
diff --git a/sysdeps/mips/nptl/nptl-sysdep.S b/sysdeps/mips/nptl/nptl-sysdep.S
new file mode 100644
index 0000000000..3f5c2a364a
--- /dev/null
+++ b/sysdeps/mips/nptl/nptl-sysdep.S
@@ -0,0 +1,2 @@
+/* Pull in __syscall_error. */
+#include <sysdep.S>
diff --git a/sysdeps/mips/nptl/pthread_spin_lock.c b/sysdeps/mips/nptl/pthread_spin_lock.c
new file mode 100644
index 0000000000..b211909131
--- /dev/null
+++ b/sysdeps/mips/nptl/pthread_spin_lock.c
@@ -0,0 +1,23 @@
+/* Copyright (C) 2012-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define SPIN_LOCK_READS_BETWEEN_CMPXCHG 1000
+
+/* We can't use the normal "#include <nptl/pthread_spin_lock.c>" because
+ it will resolve to this very file. Using "sysdeps/.." as reference to the
+ top level directory does the job. */
+#include <sysdeps/../nptl/pthread_spin_lock.c>
diff --git a/sysdeps/mips/nptl/pthreaddef.h b/sysdeps/mips/nptl/pthreaddef.h
new file mode 100644
index 0000000000..1933dfefcb
--- /dev/null
+++ b/sysdeps/mips/nptl/pthreaddef.h
@@ -0,0 +1,32 @@
+/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Default stack size. */
+#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024)
+
+/* Required stack pointer alignment at beginning. */
+#define STACK_ALIGN 16
+
+/* Minimal stack size after allocating thread descriptor and guard size. */
+#define MINIMAL_REST_STACK 2048
+
+/* Alignment requirement for TCB. */
+#define TCB_ALIGNMENT 16
+
+
+/* Location of current stack frame. */
+#define CURRENT_STACK_FRAME __builtin_frame_address (0)
diff --git a/sysdeps/mips/nptl/tcb-offsets.sym b/sysdeps/mips/nptl/tcb-offsets.sym
new file mode 100644
index 0000000000..e0e71dc430
--- /dev/null
+++ b/sysdeps/mips/nptl/tcb-offsets.sym
@@ -0,0 +1,11 @@
+#include <sysdep.h>
+#include <tls.h>
+
+--
+
+-- Abuse tls.h macros to derive offsets relative to the thread register.
+#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
+
+MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
+PID_OFFSET thread_offsetof (pid)
+TID_OFFSET thread_offsetof (tid)
diff --git a/sysdeps/mips/nptl/tls.h b/sysdeps/mips/nptl/tls.h
new file mode 100644
index 0000000000..ef1145779d
--- /dev/null
+++ b/sysdeps/mips/nptl/tls.h
@@ -0,0 +1,185 @@
+/* Definition for thread-local data handling. NPTL/MIPS version.
+ Copyright (C) 2005-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _TLS_H
+#define _TLS_H 1
+
+#include <dl-sysdep.h>
+
+#ifndef __ASSEMBLER__
+# include <stdbool.h>
+# include <stddef.h>
+# include <stdint.h>
+
+/* Type for the dtv. */
+typedef union dtv
+{
+ size_t counter;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
+} dtv_t;
+
+#ifdef __mips16
+/* MIPS16 uses GCC builtin to access the TP. */
+# define READ_THREAD_POINTER() (__builtin_thread_pointer ())
+#else
+/* Note: rd must be $v1 to be ABI-conformant. */
+# define READ_THREAD_POINTER() \
+ ({ void *__result; \
+ asm volatile (".set\tpush\n\t.set\tmips32r2\n\t" \
+ "rdhwr\t%0, $29\n\t.set\tpop" : "=v" (__result)); \
+ __result; })
+#endif
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+
+# define READ_THREAD_POINTER(rd) \
+ .set push; \
+ .set mips32r2; \
+ rdhwr rd, $29; \
+ .set pop
+#endif /* __ASSEMBLER__ */
+
+
+#ifndef __ASSEMBLER__
+
+/* Get system call information. */
+# include <sysdep.h>
+
+/* The TP points to the start of the thread blocks. */
+# define TLS_DTV_AT_TP 1
+# define TLS_TCB_AT_TP 0
+
+/* Get the thread descriptor definition. */
+# include <nptl/descr.h>
+
+typedef struct
+{
+ dtv_t *dtv;
+ void *private;
+} tcbhead_t;
+
+/* This is the size of the initial TCB. Because our TCB is before the thread
+ pointer, we don't need this. */
+# define TLS_INIT_TCB_SIZE 0
+
+/* Alignment requirements for the initial TCB. */
+# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
+
+/* This is the size of the TCB. Because our TCB is before the thread
+ pointer, we don't need this. */
+# define TLS_TCB_SIZE 0
+
+/* Alignment requirements for the TCB. */
+# define TLS_TCB_ALIGN __alignof__ (struct pthread)
+
+/* This is the size we need before TCB - actually, it includes the TCB. */
+# define TLS_PRE_TCB_SIZE \
+ (sizeof (struct pthread) \
+ + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
+
+/* The thread pointer (in hardware register $29) points to the end of
+ the TCB + 0x7000, as for PowerPC. The pthread_descr structure is
+ immediately in front of the TCB. */
+# define TLS_TCB_OFFSET 0x7000
+
+/* Install the dtv pointer. The pointer passed is to the element with
+ index -1 which contain the length. */
+# define INSTALL_DTV(tcbp, dtvp) \
+ (((tcbhead_t *) (tcbp))[-1].dtv = (dtvp) + 1)
+
+/* Install new dtv for current thread. */
+# define INSTALL_NEW_DTV(dtv) \
+ (THREAD_DTV() = (dtv))
+
+/* Return dtv of given thread descriptor. */
+# define GET_DTV(tcbp) \
+ (((tcbhead_t *) (tcbp))[-1].dtv)
+
+/* Code to initially initialize the thread pointer. This might need
+ special attention since 'errno' is not yet available and if the
+ operation can cause a failure 'errno' must not be touched. */
+# define TLS_INIT_TP(tcbp) \
+ ({ INTERNAL_SYSCALL_DECL (err); \
+ long result_var; \
+ result_var = INTERNAL_SYSCALL (set_thread_area, err, 1, \
+ (char *) (tcbp) + TLS_TCB_OFFSET); \
+ INTERNAL_SYSCALL_ERROR_P (result_var, err) \
+ ? "unknown error" : NULL; })
+
+/* Value passed to 'clone' for initialization of the thread register. */
+# define TLS_DEFINE_INIT_TP(tp, pd) \
+ void *tp = (void *) (pd) + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE
+
+/* Return the address of the dtv for the current thread. */
+# define THREAD_DTV() \
+ (((tcbhead_t *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET))[-1].dtv)
+
+/* Return the thread descriptor for the current thread. */
+# define THREAD_SELF \
+ ((struct pthread *) (READ_THREAD_POINTER () \
+ - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE))
+
+/* Magic for libthread_db to know how to do THREAD_SELF. */
+# define DB_THREAD_SELF \
+ CONST_THREAD_AREA (32, TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)
+
+/* Access to data in the thread descriptor is easy. */
+# define THREAD_GETMEM(descr, member) \
+ descr->member
+# define THREAD_GETMEM_NC(descr, member, idx) \
+ descr->member[idx]
+# define THREAD_SETMEM(descr, member, value) \
+ descr->member = (value)
+# define THREAD_SETMEM_NC(descr, member, idx, value) \
+ descr->member[idx] = (value)
+
+/* l_tls_offset == 0 is perfectly valid on MIPS, so we have to use some
+ different value to mean unset l_tls_offset. */
+# define NO_TLS_OFFSET -1
+
+/* Get and set the global scope generation counter in struct pthread. */
+#define THREAD_GSCOPE_FLAG_UNUSED 0
+#define THREAD_GSCOPE_FLAG_USED 1
+#define THREAD_GSCOPE_FLAG_WAIT 2
+#define THREAD_GSCOPE_RESET_FLAG() \
+ do \
+ { int __res \
+ = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \
+ THREAD_GSCOPE_FLAG_UNUSED); \
+ if (__res == THREAD_GSCOPE_FLAG_WAIT) \
+ lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \
+ } \
+ while (0)
+#define THREAD_GSCOPE_SET_FLAG() \
+ do \
+ { \
+ THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \
+ atomic_write_barrier (); \
+ } \
+ while (0)
+#define THREAD_GSCOPE_WAIT() \
+ GL(dl_wait_lookup_done) ()
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* tls.h */
diff --git a/sysdeps/mips/preconfigure b/sysdeps/mips/preconfigure
new file mode 100644
index 0000000000..c118592b27
--- /dev/null
+++ b/sysdeps/mips/preconfigure
@@ -0,0 +1,29 @@
+case "$machine" in
+mips*)
+ abiflag=`$CC $CFLAGS $CPPFLAGS -E -dM -xc /dev/null | sed -n 's/^#define _MIPS_SIM \(.*\)/\1/p'`
+ mips16flag=`$CC $CFLAGS $CPPFLAGS -E -dM -xc /dev/null | sed -n 's/^#define __mips16 \(.*\)/\1/p'`
+
+ base_machine=mips
+ if test "$abiflag" = "_ABIO32" ; then
+ if test "$mips16flag" = "1" ; then
+ machine=mips/mips32/mips16
+ else
+ machine=mips/mips32
+ fi
+ elif test "$abiflag" = "_ABIN32" ; then
+ machine=mips/mips64/n32
+ elif test "$abiflag" = "_ABI64" ; then
+ machine=mips/mips64/n64
+ else
+ as_fn_error $? "Unable to determine ABI." "$LINENO" 5
+ fi
+ # $config_machine is not really needed here but the slash after
+ # $machine is needed by the case statement in
+ # sysdeps/unix/sysv/linux/mips/configure.ac.
+ machine=$machine/$config_machine
+
+ if test "$abiflag" != "_ABIO32" -a "$mips16flag" = "1"; then
+ as_fn_error $? "MIPS16 is only supported with the o32 ABI." "$LINENO" 5
+ fi
+ ;;
+esac
diff --git a/sysdeps/mips/regdef.h b/sysdeps/mips/regdef.h
new file mode 100644
index 0000000000..d4f284f2f9
--- /dev/null
+++ b/sysdeps/mips/regdef.h
@@ -0,0 +1,25 @@
+/* Copyright (C) 1994-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ralf Baechle <ralf@gnu.org>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _REGDEF_H
+#define _REGDEF_H
+
+#include <sys/regdef.h>
+#include <sys/fpregdef.h>
+
+#endif /* _REGDEF_H */
diff --git a/sysdeps/mips/rshift.S b/sysdeps/mips/rshift.S
new file mode 100644
index 0000000000..df53e449cc
--- /dev/null
+++ b/sysdeps/mips/rshift.S
@@ -0,0 +1,94 @@
+/* MIPS2 __mpn_rshift --
+
+Copyright (C) 1995-2015 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the GNU MP Library. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+/* INPUT PARAMETERS
+ res_ptr $4
+ src_ptr $5
+ size $6
+ cnt $7
+*/
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (__mpn_rshift)
+ .set noreorder
+#ifdef __PIC__
+ .cpload t9
+#endif
+ .set nomacro
+
+ lw $10,0($5) /* load first limb */
+ subu $13,$0,$7
+ addiu $6,$6,-1
+ and $9,$6,4-1 /* number of limbs in first loop */
+ beq $9,$0,L(L0) /* if multiple of 4 limbs, skip first loop*/
+ sll $2,$10,$13 /* compute function result */
+
+ subu $6,$6,$9
+
+L(Loop0): lw $3,4($5)
+ addiu $4,$4,4
+ addiu $5,$5,4
+ addiu $9,$9,-1
+ srl $11,$10,$7
+ sll $12,$3,$13
+ move $10,$3
+ or $8,$11,$12
+ bne $9,$0,L(Loop0)
+ sw $8,-4($4)
+
+L(L0): beq $6,$0,L(Lend)
+ nop
+
+L(Loop): lw $3,4($5)
+ addiu $4,$4,16
+ addiu $6,$6,-4
+ srl $11,$10,$7
+ sll $12,$3,$13
+
+ lw $10,8($5)
+ srl $14,$3,$7
+ or $8,$11,$12
+ sw $8,-16($4)
+ sll $9,$10,$13
+
+ lw $3,12($5)
+ srl $11,$10,$7
+ or $8,$14,$9
+ sw $8,-12($4)
+ sll $12,$3,$13
+
+ lw $10,16($5)
+ srl $14,$3,$7
+ or $8,$11,$12
+ sw $8,-8($4)
+ sll $9,$10,$13
+
+ addiu $5,$5,16
+ or $8,$14,$9
+ bgtz $6,L(Loop)
+ sw $8,-4($4)
+
+L(Lend): srl $8,$10,$7
+ j $31
+ sw $8,0($4)
+ END (__mpn_rshift)
diff --git a/sysdeps/mips/setjmp.S b/sysdeps/mips/setjmp.S
new file mode 100644
index 0000000000..26306b1ef5
--- /dev/null
+++ b/sysdeps/mips/setjmp.S
@@ -0,0 +1,46 @@
+/* Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+ .set nomips16
+
+/* The function __sigsetjmp_aux saves all the registers, but it can't
+ reliably access the stack or frame pointers, so we pass them in as
+ extra arguments. */
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (__sigsetjmp)
+#ifdef __PIC__
+ .set noreorder
+ .cpload t9
+ .set reorder
+#endif
+ move a2, sp
+#ifdef fp
+ move a3, fp
+#else
+ move a3, $fp
+#endif
+#ifdef __PIC__
+ la t9, __sigsetjmp_aux
+ jr t9
+#else
+ j __sigsetjmp_aux
+#endif
+END (__sigsetjmp)
diff --git a/sysdeps/mips/setjmp_aux.c b/sysdeps/mips/setjmp_aux.c
new file mode 100644
index 0000000000..b18d7e3e89
--- /dev/null
+++ b/sysdeps/mips/setjmp_aux.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Brendan Kehoe (brendan@zen.org).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <setjmp.h>
+
+/* This function is only called via the assembly language routine
+ __sigsetjmp, which arranges to pass in the stack pointer and the frame
+ pointer. We do things this way because it's difficult to reliably
+ access them in C. */
+
+int __attribute__ ((nomips16))
+__sigsetjmp_aux (jmp_buf env, int savemask, int sp, int fp)
+{
+#ifdef __mips_hard_float
+ /* Store the floating point callee-saved registers... */
+ asm volatile ("s.d $f20, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[0]));
+ asm volatile ("s.d $f22, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[1]));
+ asm volatile ("s.d $f24, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[2]));
+ asm volatile ("s.d $f26, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[3]));
+ asm volatile ("s.d $f28, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[4]));
+ asm volatile ("s.d $f30, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[5]));
+#endif
+
+ /* .. and the PC; */
+ asm volatile ("sw $31, %0" : : "m" (env[0].__jmpbuf[0].__pc));
+
+ /* .. and the stack pointer; */
+ env[0].__jmpbuf[0].__sp = (void *) sp;
+
+ /* .. and the FP; it'll be in s8. */
+ env[0].__jmpbuf[0].__fp = (void *) fp;
+
+ /* .. and the GP; */
+ asm volatile ("sw $gp, %0" : : "m" (env[0].__jmpbuf[0].__gp));
+
+ /* .. and the callee-saved registers; */
+ asm volatile ("sw $16, %0" : : "m" (env[0].__jmpbuf[0].__regs[0]));
+ asm volatile ("sw $17, %0" : : "m" (env[0].__jmpbuf[0].__regs[1]));
+ asm volatile ("sw $18, %0" : : "m" (env[0].__jmpbuf[0].__regs[2]));
+ asm volatile ("sw $19, %0" : : "m" (env[0].__jmpbuf[0].__regs[3]));
+ asm volatile ("sw $20, %0" : : "m" (env[0].__jmpbuf[0].__regs[4]));
+ asm volatile ("sw $21, %0" : : "m" (env[0].__jmpbuf[0].__regs[5]));
+ asm volatile ("sw $22, %0" : : "m" (env[0].__jmpbuf[0].__regs[6]));
+ asm volatile ("sw $23, %0" : : "m" (env[0].__jmpbuf[0].__regs[7]));
+
+ /* Save the signal mask if requested. */
+ return __sigjmp_save (env, savemask);
+}
diff --git a/sysdeps/mips/sgidefs.h b/sysdeps/mips/sgidefs.h
new file mode 100644
index 0000000000..9fb3b37d48
--- /dev/null
+++ b/sysdeps/mips/sgidefs.h
@@ -0,0 +1,76 @@
+/* Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ralf Baechle <ralf@gnu.org>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _SGIDEFS_H
+#define _SGIDEFS_H 1
+
+/*
+ * A crude hack to stop <asm/sgidefs.h>
+ */
+#undef __ASM_SGIDEFS_H
+#define __ASM_SGIDEFS_H
+
+/*
+ * And remove any damage it might have already done
+ */
+#undef _MIPS_ISA_MIPS1
+#undef _MIPS_ISA_MIPS2
+#undef _MIPS_ISA_MIPS3
+#undef _MIPS_ISA_MIPS4
+#undef _MIPS_ISA_MIPS5
+#undef _MIPS_ISA_MIPS32
+#undef _MIPS_ISA_MIPS64
+
+#undef _MIPS_SIM_ABI32
+#undef _MIPS_SIM_NABI32
+#undef _MIPS_SIM_ABI64
+
+/*
+ * Definitions for the ISA level
+ */
+#define _MIPS_ISA_MIPS1 1
+#define _MIPS_ISA_MIPS2 2
+#define _MIPS_ISA_MIPS3 3
+#define _MIPS_ISA_MIPS4 4
+#define _MIPS_ISA_MIPS5 5
+#define _MIPS_ISA_MIPS32 6
+#define _MIPS_ISA_MIPS64 7
+
+/*
+ * Subprogram calling convention
+ */
+#ifndef _ABIO32
+# define _ABIO32 1
+#endif
+#define _MIPS_SIM_ABI32 _ABIO32
+
+#ifndef _ABIN32
+# define _ABIN32 2
+#endif
+#define _MIPS_SIM_NABI32 _ABIN32
+
+#ifndef _ABI64
+# define _ABI64 3
+#endif
+#define _MIPS_SIM_ABI64 _ABI64
+
+#ifndef _ABIO64
+# define _ABIO64 4
+#endif
+
+#endif /* sgidefs.h */
diff --git a/sysdeps/mips/sotruss-lib.c b/sysdeps/mips/sotruss-lib.c
new file mode 100644
index 0000000000..469d138665
--- /dev/null
+++ b/sysdeps/mips/sotruss-lib.c
@@ -0,0 +1,117 @@
+/* Override generic sotruss-lib.c to define actual functions for MIPS.
+ Copyright (C) 2012-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define HAVE_ARCH_PLTENTER
+#define HAVE_ARCH_PLTEXIT
+
+#include <elf/sotruss-lib.c>
+
+#if _MIPS_SIM == _ABIO32
+
+ElfW(Addr)
+la_mips_o32_gnu_pltenter (ElfW(Sym) *sym __attribute__ ((unused)),
+ unsigned int ndx __attribute__ ((unused)),
+ uintptr_t *refcook, uintptr_t *defcook,
+ La_mips_32_regs *regs, unsigned int *flags,
+ const char *symname, long int *framesizep)
+{
+ print_enter (refcook, defcook, symname,
+ regs->lr_reg[0], regs->lr_reg[1], regs->lr_reg[2],
+ *flags);
+
+ /* No need to copy anything, we will not need the parameters in any case. */
+ *framesizep = 0;
+
+ return sym->st_value;
+}
+
+unsigned int
+la_mips_o32_gnu_pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook,
+ const struct La_mips_32_regs *inregs,
+ struct La_mips_32_retval *outregs,
+ const char *symname)
+{
+ print_exit (refcook, defcook, symname, outregs->lrv_v0);
+
+ return 0;
+}
+
+#elif _MIPS_SIM == _ABIN32
+
+ElfW(Addr)
+la_mips_n32_gnu_pltenter (ElfW(Sym) *sym __attribute__ ((unused)),
+ unsigned int ndx __attribute__ ((unused)),
+ uintptr_t *refcook, uintptr_t *defcook,
+ La_mips_64_regs *regs, unsigned int *flags,
+ const char *symname, long int *framesizep)
+{
+ print_enter (refcook, defcook, symname,
+ regs->lr_reg[0], regs->lr_reg[1], regs->lr_reg[2],
+ *flags);
+
+ /* No need to copy anything, we will not need the parameters in any case. */
+ *framesizep = 0;
+
+ return sym->st_value;
+}
+
+unsigned int
+la_mips_n32_gnu_pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook,
+ const struct La_mips_64_regs *inregs,
+ struct La_mips_64_retval *outregs,
+ const char *symname)
+{
+ print_exit (refcook, defcook, symname, outregs->lrv_v0);
+
+ return 0;
+}
+
+#else
+
+ElfW(Addr)
+la_mips_n64_gnu_pltenter (ElfW(Sym) *sym __attribute__ ((unused)),
+ unsigned int ndx __attribute__ ((unused)),
+ uintptr_t *refcook, uintptr_t *defcook,
+ La_mips_64_regs *regs, unsigned int *flags,
+ const char *symname, long int *framesizep)
+{
+ print_enter (refcook, defcook, symname,
+ regs->lr_reg[0], regs->lr_reg[1], regs->lr_reg[2],
+ *flags);
+
+ /* No need to copy anything, we will not need the parameters in any case. */
+ *framesizep = 0;
+
+ return sym->st_value;
+}
+
+unsigned int
+la_mips_n64_gnu_pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook,
+ const struct La_mips_64_regs *inregs,
+ struct La_mips_64_retval *outregs,
+ const char *symname)
+{
+ print_exit (refcook, defcook, symname, outregs->lrv_v0);
+
+ return 0;
+}
+
+#endif
diff --git a/sysdeps/mips/stackinfo.h b/sysdeps/mips/stackinfo.h
new file mode 100644
index 0000000000..b27229d3b4
--- /dev/null
+++ b/sysdeps/mips/stackinfo.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2000-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This file contains a bit of information about the stack allocation
+ of the processor. */
+
+#ifndef _STACKINFO_H
+#define _STACKINFO_H 1
+
+#include <elf.h>
+
+/* On MIPS the stack grows down. */
+#define _STACK_GROWS_DOWN 1
+
+/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK is
+ * present, but it is presumed absent. */
+#define DEFAULT_STACK_PERMS (PF_R|PF_W|PF_X)
+
+#endif /* stackinfo.h */
diff --git a/sysdeps/mips/start.S b/sysdeps/mips/start.S
new file mode 100644
index 0000000000..5c9c83780b
--- /dev/null
+++ b/sysdeps/mips/start.S
@@ -0,0 +1,185 @@
+/* Startup code compliant to the ELF Mips ABI.
+ Copyright (C) 1995-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file with other
+ programs, and to distribute those programs without any restriction
+ coming from the use of this file. (The GNU Lesser General Public
+ License restrictions do apply in other respects; for example, they
+ cover modification of the file, and distribution when not linked
+ into another program.)
+
+ Note that people who make modified versions of this file are not
+ obligated to grant this special exception for their modified
+ versions; it is their choice whether to do so. The GNU Lesser
+ General Public License gives permission to release a modified
+ version without this exception; this exception also makes it
+ possible to release a modified version which carries forward this
+ exception.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define __ASSEMBLY__ 1
+#include <entry.h>
+#include <sgidefs.h>
+#include <sys/asm.h>
+
+#ifndef ENTRY_POINT
+#error ENTRY_POINT needs to be defined for start.S on MIPS/ELF.
+#endif
+
+/* This is the canonical entry point, usually the first thing in the text
+ segment. The SVR4/Mips ABI (pages 3-31, 3-32) says that when the entry
+ point runs, most registers' values are unspecified, except for:
+
+ v0 ($2) Contains a function pointer to be registered with `atexit'.
+ This is how the dynamic linker arranges to have DT_FINI
+ functions called for shared libraries that have been loaded
+ before this code runs.
+
+ sp ($29) The stack contains the arguments and environment:
+ 0(%esp) argc
+ 4(%esp) argv[0]
+ ...
+ (4*argc)(%esp) NULL
+ (4*(argc+1))(%esp) envp[0]
+ ...
+ NULL
+ ra ($31) The return address register is set to zero so that programs
+ that search backword through stack frames recognize the last
+ stack frame.
+*/
+
+
+/* We need to call:
+ __libc_start_main (int (*main) (int, char **, char **), int argc,
+ char **argv, void (*init) (void), void (*fini) (void),
+ void (*rtld_fini) (void), void *stack_end)
+*/
+
+ .text
+ .globl ENTRY_POINT
+ .type ENTRY_POINT,@function
+#ifndef __mips16
+ENTRY_POINT:
+# ifdef __PIC__
+ SETUP_GPX($0)
+ SETUP_GPX64($25,$0)
+# else
+ PTR_LA $28, _gp /* Setup GP correctly if we're non-PIC. */
+ move $31, $0
+# endif
+
+ PTR_LA $4, main /* main */
+ PTR_L $5, 0($29) /* argc */
+ PTR_ADDIU $6, $29, PTRSIZE /* argv */
+
+ /* Allocate space on the stack for seven arguments (o32 only)
+ and make sure the stack is aligned to double words (8 bytes)
+ on o32 and quad words (16 bytes) on n32 and n64. */
+
+ and $29, -2 * SZREG
+# if _MIPS_SIM == _ABIO32
+ PTR_SUBIU $29, 32
+# endif
+ PTR_LA $7, __libc_csu_init /* init */
+ PTR_LA $8, __libc_csu_fini
+# if _MIPS_SIM == _ABIO32
+ PTR_S $8, 16($29) /* fini */
+ PTR_S $2, 20($29) /* rtld_fini */
+ PTR_S $29, 24($29) /* stack_end */
+# else
+ move $9, $2 /* rtld_fini */
+ move $10, $29 /* stack_end */
+# endif
+ PTR_LA $25, __libc_start_main
+ jalr $25
+hlt: b hlt /* Crash if somehow it does return. */
+
+#elif _MIPS_SIM == _ABIO32 /* __mips16 */
+ /* MIPS16 entry point. */
+ .set mips16
+ENTRY_POINT:
+# ifdef __PIC__
+ li $3, %hi(_gp_disp)
+ addiu $4, $pc, %lo(_gp_disp)
+ sll $3, 16
+ addu $3, $4
+ move $gp, $3
+# else
+ li $3, %hi(_gp)
+ sll $3, 16
+ addiu $3, %lo(_gp)
+ move $gp, $3
+# endif
+ /* Tie end of stack frames. */
+ li $4, 0
+ move $31, $4
+ /* Create new SP value in $7, including alignment. */
+ li $4, 2 * SZREG
+ neg $4, $4
+ move $7, $sp
+ and $7, $4
+ addiu $7, -32
+ /* Load arguments with original SP. */
+ lw $5, 0($sp)
+ addiu $6, $sp, PTRSIZE
+ /* Update SP. */
+ move $sp, $7
+ /* Lay out last arguments, and call __libc_start_main(). */
+# ifdef __PIC__
+ sw $7, 24($sp) /* stack_end */
+ lw $4, %got(__libc_csu_fini)($3)
+ lw $7, %got(__libc_csu_init)($3) /* init */
+ sw $4, 16($sp) /* fini */
+ lw $4, %got(main)($3) /* main */
+ lw $3, %call16(__libc_start_main)($3)
+ sw $2, 20($sp) /* rtld_fini */
+ move $25, $3
+ jalr $3
+# else
+ lw $4, 1f
+ sw $7, 24($sp) /* stack_end */
+ lw $7, 2f /* init */
+ sw $4, 16($sp) /* fini */
+ lw $4, 3f /* main */
+ sw $2, 20($sp) /* rtld_fini */
+ /* Load and call __libc_start_main(). */
+ lw $3, 4f
+ jalr $3
+# endif
+hlt: b hlt /* Crash if somehow it does return. */
+# ifndef __PIC__
+ .align 2
+1: .word __libc_csu_fini
+2: .word __libc_csu_init
+3: .word main
+4: .word __libc_start_main
+# endif
+
+#else /* __mips16 && _MIPS_SIM != _ABIO32 */
+# error "MIPS16 support for N32/N64 not implemented"
+
+#endif /* __mips16 */
+
+/* Define a symbol for the first piece of initialized data. */
+ .data
+ .globl __data_start
+__data_start:
+ .long 0
+ .weak data_start
+ data_start = __data_start
diff --git a/sysdeps/mips/strcmp.S b/sysdeps/mips/strcmp.S
new file mode 100644
index 0000000000..7ba79e7a02
--- /dev/null
+++ b/sysdeps/mips/strcmp.S
@@ -0,0 +1,249 @@
+/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef ANDROID_CHANGES
+# include "machine/asm.h"
+# include "machine/regdef.h"
+#elif _LIBC
+# include <sysdep.h>
+# include <regdef.h>
+# include <sys/asm.h>
+#elif defined _COMPILING_NEWLIB
+# include "machine/asm.h"
+# include "machine/regdef.h"
+#else
+# include <regdef.h>
+# include <sys/asm.h>
+#endif
+
+/* Technically strcmp should not read past the end of the strings being
+ compared. We will read a full word that may contain excess bits beyond
+ the NULL string terminator but unless ENABLE_READAHEAD is set, we will not
+ read the next word after the end of string. Setting ENABLE_READAHEAD will
+ improve performance but is technically illegal based on the definition of
+ strcmp. */
+#ifdef ENABLE_READAHEAD
+# define DELAY_READ
+#else
+# define DELAY_READ nop
+#endif
+
+/* Testing on a little endian machine showed using CLZ was a
+ performance loss, so we are not turning it on by default. */
+#if defined(ENABLE_CLZ) && (__mips_isa_rev > 1)
+# define USE_CLZ
+#endif
+
+/* Some asm.h files do not have the L macro definition. */
+#ifndef L
+# if _MIPS_SIM == _ABIO32
+# define L(label) $L ## label
+# else
+# define L(label) .L ## label
+# endif
+#endif
+
+/* Some asm.h files do not have the PTR_ADDIU macro definition. */
+#ifndef PTR_ADDIU
+# ifdef USE_DOUBLE
+# define PTR_ADDIU daddiu
+# else
+# define PTR_ADDIU addiu
+# endif
+#endif
+
+/* Allow the routine to be named something else if desired. */
+#ifndef STRCMP_NAME
+# define STRCMP_NAME strcmp
+#endif
+
+#ifdef ANDROID_CHANGES
+LEAF(STRCMP_NAME, 0)
+#else
+LEAF(STRCMP_NAME)
+#endif
+ .set nomips16
+ .set noreorder
+
+ or t0, a0, a1
+ andi t0,0x3
+ bne t0, zero, L(byteloop)
+
+/* Both strings are 4 byte aligned at this point. */
+
+ lui t8, 0x0101
+ ori t8, t8, 0x0101
+ lui t9, 0x7f7f
+ ori t9, 0x7f7f
+
+#define STRCMP32(OFFSET) \
+ lw v0, OFFSET(a0); \
+ lw v1, OFFSET(a1); \
+ subu t0, v0, t8; \
+ bne v0, v1, L(worddiff); \
+ nor t1, v0, t9; \
+ and t0, t0, t1; \
+ bne t0, zero, L(returnzero)
+
+L(wordloop):
+ STRCMP32(0)
+ DELAY_READ
+ STRCMP32(4)
+ DELAY_READ
+ STRCMP32(8)
+ DELAY_READ
+ STRCMP32(12)
+ DELAY_READ
+ STRCMP32(16)
+ DELAY_READ
+ STRCMP32(20)
+ DELAY_READ
+ STRCMP32(24)
+ DELAY_READ
+ STRCMP32(28)
+ PTR_ADDIU a0, a0, 32
+ b L(wordloop)
+ PTR_ADDIU a1, a1, 32
+
+L(returnzero):
+ j ra
+ move v0, zero
+
+L(worddiff):
+#ifdef USE_CLZ
+ subu t0, v0, t8
+ nor t1, v0, t9
+ and t1, t0, t1
+ xor t0, v0, v1
+ or t0, t0, t1
+# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ wsbh t0, t0
+ rotr t0, t0, 16
+# endif
+ clz t1, t0
+ and t1, 0xf8
+# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ neg t1
+ addu t1, 24
+# endif
+ rotrv v0, v0, t1
+ rotrv v1, v1, t1
+ and v0, v0, 0xff
+ and v1, v1, 0xff
+ j ra
+ subu v0, v0, v1
+#else /* USE_CLZ */
+# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ andi t0, v0, 0xff
+ beq t0, zero, L(wexit01)
+ andi t1, v1, 0xff
+ bne t0, t1, L(wexit01)
+
+ srl t8, v0, 8
+ srl t9, v1, 8
+ andi t8, t8, 0xff
+ beq t8, zero, L(wexit89)
+ andi t9, t9, 0xff
+ bne t8, t9, L(wexit89)
+
+ srl t0, v0, 16
+ srl t1, v1, 16
+ andi t0, t0, 0xff
+ beq t0, zero, L(wexit01)
+ andi t1, t1, 0xff
+ bne t0, t1, L(wexit01)
+
+ srl t8, v0, 24
+ srl t9, v1, 24
+# else /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
+ srl t0, v0, 24
+ beq t0, zero, L(wexit01)
+ srl t1, v1, 24
+ bne t0, t1, L(wexit01)
+
+ srl t8, v0, 16
+ srl t9, v1, 16
+ andi t8, t8, 0xff
+ beq t8, zero, L(wexit89)
+ andi t9, t9, 0xff
+ bne t8, t9, L(wexit89)
+
+ srl t0, v0, 8
+ srl t1, v1, 8
+ andi t0, t0, 0xff
+ beq t0, zero, L(wexit01)
+ andi t1, t1, 0xff
+ bne t0, t1, L(wexit01)
+
+ andi t8, v0, 0xff
+ andi t9, v1, 0xff
+# endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
+
+L(wexit89):
+ j ra
+ subu v0, t8, t9
+L(wexit01):
+ j ra
+ subu v0, t0, t1
+#endif /* USE_CLZ */
+
+/* It might seem better to do the 'beq' instruction between the two 'lbu'
+ instructions so that the nop is not needed but testing showed that this
+ code is actually faster (based on glibc strcmp test). */
+#define BYTECMP01(OFFSET) \
+ lbu v0, OFFSET(a0); \
+ lbu v1, OFFSET(a1); \
+ beq v0, zero, L(bexit01); \
+ nop; \
+ bne v0, v1, L(bexit01)
+
+#define BYTECMP89(OFFSET) \
+ lbu t8, OFFSET(a0); \
+ lbu t9, OFFSET(a1); \
+ beq t8, zero, L(bexit89); \
+ nop; \
+ bne t8, t9, L(bexit89)
+
+L(byteloop):
+ BYTECMP01(0)
+ BYTECMP89(1)
+ BYTECMP01(2)
+ BYTECMP89(3)
+ BYTECMP01(4)
+ BYTECMP89(5)
+ BYTECMP01(6)
+ BYTECMP89(7)
+ PTR_ADDIU a0, a0, 8
+ b L(byteloop)
+ PTR_ADDIU a1, a1, 8
+
+L(bexit01):
+ j ra
+ subu v0, v0, v1
+L(bexit89):
+ j ra
+ subu v0, t8, t9
+
+ .set at
+ .set reorder
+
+END(STRCMP_NAME)
+#ifndef ANDROID_CHANGES
+# ifdef _LIBC
+libc_hidden_builtin_def (STRCMP_NAME)
+# endif
+#endif
diff --git a/sysdeps/mips/sub_n.S b/sysdeps/mips/sub_n.S
new file mode 100644
index 0000000000..ffc142c8f9
--- /dev/null
+++ b/sysdeps/mips/sub_n.S
@@ -0,0 +1,121 @@
+/* MIPS2 __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
+store difference in a third limb vector.
+
+Copyright (C) 1995-2015 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the GNU MP Library. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+/* INPUT PARAMETERS
+ res_ptr $4
+ s1_ptr $5
+ s2_ptr $6
+ size $7
+*/
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (__mpn_sub_n)
+ .set noreorder
+#ifdef __PIC__
+ .cpload t9
+#endif
+ .set nomacro
+
+ lw $10,0($5)
+ lw $11,0($6)
+
+ addiu $7,$7,-1
+ and $9,$7,4-1 /* number of limbs in first loop */
+ beq $9,$0,L(L0) /* if multiple of 4 limbs, skip first loop */
+ move $2,$0
+
+ subu $7,$7,$9
+
+L(Loop0): addiu $9,$9,-1
+ lw $12,4($5)
+ addu $11,$11,$2
+ lw $13,4($6)
+ sltu $8,$11,$2
+ subu $11,$10,$11
+ sltu $2,$10,$11
+ sw $11,0($4)
+ or $2,$2,$8
+
+ addiu $5,$5,4
+ addiu $6,$6,4
+ move $10,$12
+ move $11,$13
+ bne $9,$0,L(Loop0)
+ addiu $4,$4,4
+
+L(L0): beq $7,$0,L(Lend)
+ nop
+
+L(Loop): addiu $7,$7,-4
+
+ lw $12,4($5)
+ addu $11,$11,$2
+ lw $13,4($6)
+ sltu $8,$11,$2
+ subu $11,$10,$11
+ sltu $2,$10,$11
+ sw $11,0($4)
+ or $2,$2,$8
+
+ lw $10,8($5)
+ addu $13,$13,$2
+ lw $11,8($6)
+ sltu $8,$13,$2
+ subu $13,$12,$13
+ sltu $2,$12,$13
+ sw $13,4($4)
+ or $2,$2,$8
+
+ lw $12,12($5)
+ addu $11,$11,$2
+ lw $13,12($6)
+ sltu $8,$11,$2
+ subu $11,$10,$11
+ sltu $2,$10,$11
+ sw $11,8($4)
+ or $2,$2,$8
+
+ lw $10,16($5)
+ addu $13,$13,$2
+ lw $11,16($6)
+ sltu $8,$13,$2
+ subu $13,$12,$13
+ sltu $2,$12,$13
+ sw $13,12($4)
+ or $2,$2,$8
+
+ addiu $5,$5,16
+ addiu $6,$6,16
+
+ bne $7,$0,L(Loop)
+ addiu $4,$4,16
+
+L(Lend): addu $11,$11,$2
+ sltu $8,$11,$2
+ subu $11,$10,$11
+ sltu $2,$10,$11
+ sw $11,0($4)
+ j $31
+ or $2,$2,$8
+ END (__mpn_sub_n)
diff --git a/sysdeps/mips/submul_1.S b/sysdeps/mips/submul_1.S
new file mode 100644
index 0000000000..abed351733
--- /dev/null
+++ b/sysdeps/mips/submul_1.S
@@ -0,0 +1,128 @@
+/* MIPS __mpn_submul_1 -- Multiply a limb vector with a single limb and
+subtract the product from a second limb vector.
+
+Copyright (C) 1995-2015 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the GNU MP Library. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+/* INPUT PARAMETERS
+ res_ptr $4
+ s1_ptr $5
+ size $6
+ s2_limb $7
+*/
+#ifdef __PIC__
+ .option pic2
+#endif
+ENTRY (__mpn_submul_1)
+ .set noreorder
+#ifdef __PIC__
+ .cpload t9
+#endif
+ .set nomacro
+
+ /* warm up phase 0 */
+ lw $8,0($5)
+
+ /* warm up phase 1 */
+ addiu $5,$5,4
+#if __mips_isa_rev < 6
+ multu $8,$7
+#else
+ mulu $11,$8,$7
+ muhu $12,$8,$7
+#endif
+
+ addiu $6,$6,-1
+ beq $6,$0,L(LC0)
+ move $2,$0 /* zero cy2 */
+
+ addiu $6,$6,-1
+ beq $6,$0,L(LC1)
+ lw $8,0($5) /* load new s1 limb as early as possible */
+
+L(Loop): lw $10,0($4)
+#if __mips_isa_rev < 6
+ mflo $3
+ mfhi $9
+#else
+ move $3,$11
+ move $9,$12
+#endif
+ addiu $5,$5,4
+ addu $3,$3,$2 /* add old carry limb to low product limb */
+#if __mips_isa_rev < 6
+ multu $8,$7
+#else
+ mulu $11,$8,$7
+ muhu $12,$8,$7
+#endif
+ lw $8,0($5) /* load new s1 limb as early as possible */
+ addiu $6,$6,-1 /* decrement loop counter */
+ sltu $2,$3,$2 /* carry from previous addition -> $2 */
+ subu $3,$10,$3
+ sgtu $10,$3,$10
+ addu $2,$2,$10
+ sw $3,0($4)
+ addiu $4,$4,4
+ bne $6,$0,L(Loop) /* should be "bnel" */
+ addu $2,$9,$2 /* add high product limb and carry from addition */
+
+ /* cool down phase 1 */
+L(LC1): lw $10,0($4)
+#if __mips_isa_rev < 6
+ mflo $3
+ mfhi $9
+#else
+ move $3,$11
+ move $9,$12
+#endif
+ addu $3,$3,$2
+ sltu $2,$3,$2
+#if __mips_isa_rev < 6
+ multu $8,$7
+#else
+ mulu $11,$8,$7
+ muhu $12,$8,$7
+#endif
+ subu $3,$10,$3
+ sgtu $10,$3,$10
+ addu $2,$2,$10
+ sw $3,0($4)
+ addiu $4,$4,4
+ addu $2,$9,$2 /* add high product limb and carry from addition */
+
+ /* cool down phase 0 */
+L(LC0): lw $10,0($4)
+#if __mips_isa_rev < 6
+ mflo $3
+ mfhi $9
+#else
+ move $3,$11
+ move $9,$12
+#endif
+ addu $3,$3,$2
+ sltu $2,$3,$2
+ subu $3,$10,$3
+ sgtu $10,$3,$10
+ addu $2,$2,$10
+ sw $3,0($4)
+ j $31
+ addu $2,$9,$2 /* add high product limb and carry from addition */
+ END (__mpn_submul_1)
diff --git a/sysdeps/mips/sys/asm.h b/sysdeps/mips/sys/asm.h
new file mode 100644
index 0000000000..0ff88027db
--- /dev/null
+++ b/sysdeps/mips/sys/asm.h
@@ -0,0 +1,498 @@
+/* Copyright (C) 1997-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ralf Baechle <ralf@gnu.org>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _SYS_ASM_H
+#define _SYS_ASM_H
+
+#include <sgidefs.h>
+
+#ifndef CAT
+# define __CAT(str1,str2) str1##str2
+# define CAT(str1,str2) __CAT(str1,str2)
+#endif
+
+/* Redefined as nonempty in the internal header. */
+#define __mips_cfi_startproc /* Empty. */
+#define __mips_cfi_endproc /* Empty. */
+
+/*
+ * Macros to handle different pointer/register sizes for 32/64-bit code
+ *
+ * 64 bit address space isn't used yet, so we may use the R3000 32 bit
+ * defines for now.
+ */
+#if _MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABIN32
+# define PTR .word
+# define PTRSIZE 4
+# define PTRLOG 2
+#elif _MIPS_SIM == _ABI64
+# define PTR .dword
+# define PTRSIZE 8
+# define PTRLOG 3
+#endif
+
+/*
+ * PIC specific declarations
+ */
+#if _MIPS_SIM == _ABIO32
+# ifdef __PIC__
+# define CPRESTORE(register) \
+ .cprestore register
+# define CPLOAD(register) \
+ .cpload register
+# else
+# define CPRESTORE(register)
+# define CPLOAD(register)
+# endif
+
+# define CPADD(register) \
+ .cpadd register
+
+/*
+ * Set gp when at 1st instruction
+ */
+# define SETUP_GP \
+ .set noreorder; \
+ .cpload $25; \
+ .set reorder
+/* Set gp when not at 1st instruction */
+# define SETUP_GPX(r) \
+ .set noreorder; \
+ move r, $31; /* Save old ra. */ \
+ bal 10f; /* Find addr of cpload. */ \
+ nop; \
+10: \
+ .cpload $31; \
+ move $31, r; \
+ .set reorder
+# define SETUP_GPX_L(r, l) \
+ .set noreorder; \
+ move r, $31; /* Save old ra. */ \
+ bal l; /* Find addr of cpload. */ \
+ nop; \
+l: \
+ .cpload $31; \
+ move $31, r; \
+ .set reorder
+# define SAVE_GP(x) \
+ .cprestore x /* Save gp trigger t9/jalr conversion. */
+# define SETUP_GP64(a, b)
+# define SETUP_GPX64(a, b)
+# define SETUP_GPX64_L(cp_reg, ra_save, l)
+# define RESTORE_GP64
+# define USE_ALT_CP(a)
+#else /* _MIPS_SIM == _ABI64 || _MIPS_SIM == _ABIN32 */
+/*
+ * For callee-saved gp calling convention:
+ */
+# define SETUP_GP
+# define SETUP_GPX(r)
+# define SETUP_GPX_L(r, l)
+# define SAVE_GP(x)
+
+# define SETUP_GP64(gpoffset, proc) \
+ .cpsetup $25, gpoffset, proc
+# define SETUP_GPX64(cp_reg, ra_save) \
+ move ra_save, $31; /* Save old ra. */ \
+ .set noreorder; \
+ bal 10f; /* Find addr of .cpsetup. */ \
+ nop; \
+10: \
+ .set reorder; \
+ .cpsetup $31, cp_reg, 10b; \
+ move $31, ra_save
+# define SETUP_GPX64_L(cp_reg, ra_save, l) \
+ move ra_save, $31; /* Save old ra. */ \
+ .set noreorder; \
+ bal l; /* Find addr of .cpsetup. */ \
+ nop; \
+l: \
+ .set reorder; \
+ .cpsetup $31, cp_reg, l; \
+ move $31, ra_save
+# define RESTORE_GP64 \
+ .cpreturn
+/* Use alternate register for context pointer. */
+# define USE_ALT_CP(reg) \
+ .cplocal reg
+#endif /* _MIPS_SIM != _ABIO32 */
+
+/*
+ * Stack Frame Definitions
+ */
+#if _MIPS_SIM == _ABIO32
+# define NARGSAVE 4 /* Space for 4 argument registers must be allocated. */
+#endif
+#if _MIPS_SIM == _ABI64 || _MIPS_SIM == _ABIN32
+# define NARGSAVE 0 /* No caller responsibilities. */
+#endif
+
+
+/*
+ * LEAF - declare leaf routine
+ */
+#define LEAF(symbol) \
+ .globl symbol; \
+ .align 2; \
+ .type symbol,@function; \
+ .ent symbol,0; \
+symbol: .frame sp,0,ra; \
+ __mips_cfi_startproc
+
+/*
+ * NESTED - declare nested routine entry point
+ */
+#define NESTED(symbol, framesize, rpc) \
+ .globl symbol; \
+ .align 2; \
+ .type symbol,@function; \
+ .ent symbol,0; \
+symbol: .frame sp, framesize, rpc; \
+ __mips_cfi_startproc
+
+/*
+ * END - mark end of function
+ */
+#ifndef END
+# define END(function) \
+ __mips_cfi_endproc; \
+ .end function; \
+ .size function,.-function
+#endif
+
+/*
+ * EXPORT - export definition of symbol
+ */
+#define EXPORT(symbol) \
+ .globl symbol; \
+symbol: __mips_cfi_startproc
+
+/*
+ * ABS - export absolute symbol
+ */
+#define ABS(symbol,value) \
+ .globl symbol; \
+symbol = value
+
+#define PANIC(msg) \
+ .set push; \
+ .set reorder; \
+ la a0,8f; \
+ jal panic; \
+9: b 9b; \
+ .set pop; \
+ TEXT(msg)
+
+/*
+ * Print formated string
+ */
+#define PRINT(string) \
+ .set push; \
+ .set reorder; \
+ la a0,8f; \
+ jal printk; \
+ .set pop; \
+ TEXT(string)
+
+#define TEXT(msg) \
+ .data; \
+8: .asciiz msg; \
+ .previous;
+
+/*
+ * Build text tables
+ */
+#define TTABLE(string) \
+ .text; \
+ .word 1f; \
+ .previous; \
+ .data; \
+1: .asciz string; \
+ .previous
+
+/*
+ * MIPS IV pref instruction.
+ * Use with .set noreorder only!
+ *
+ * MIPS IV implementations are free to treat this as a nop. The R5000
+ * is one of them. So we should have an option not to use this instruction.
+ */
+#if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \
+ (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
+# define PREF(hint,addr) \
+ pref hint,addr
+# define PREFX(hint,addr) \
+ prefx hint,addr
+#else
+# define PREF(hint,addr)
+# define PREFX(hint,addr)
+#endif
+
+/*
+ * MIPS ISA IV/V movn/movz instructions and equivalents for older CPUs.
+ */
+#if _MIPS_ISA == _MIPS_ISA_MIPS1
+# define MOVN(rd,rs,rt) \
+ .set push; \
+ .set reorder; \
+ beqz rt,9f; \
+ move rd,rs; \
+ .set pop; \
+9:
+# define MOVZ(rd,rs,rt) \
+ .set push; \
+ .set reorder; \
+ bnez rt,9f; \
+ move rd,rt; \
+ .set pop; \
+9:
+#endif /* _MIPS_ISA == _MIPS_ISA_MIPS1 */
+#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3)
+# define MOVN(rd,rs,rt) \
+ .set push; \
+ .set noreorder; \
+ bnezl rt,9f; \
+ move rd,rs; \
+ .set pop; \
+9:
+# define MOVZ(rd,rs,rt) \
+ .set push; \
+ .set noreorder; \
+ beqzl rt,9f; \
+ movz rd,rs; \
+ .set pop; \
+9:
+#endif /* (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) */
+#if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \
+ (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
+# define MOVN(rd,rs,rt) \
+ movn rd,rs,rt
+# define MOVZ(rd,rs,rt) \
+ movz rd,rs,rt
+#endif /* (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) */
+
+/*
+ * Stack alignment
+ */
+#if _MIPS_SIM == _ABI64 || _MIPS_SIM == _ABIN32
+# define ALSZ 15
+# define ALMASK ~15
+#else
+# define ALSZ 7
+# define ALMASK ~7
+#endif
+
+/*
+ * Size of a register
+ */
+#if _MIPS_SIM == _ABI64 || _MIPS_SIM == _ABIN32
+# define SZREG 8
+#else
+# define SZREG 4
+#endif
+
+/*
+ * Use the following macros in assemblercode to load/store registers,
+ * pointers etc.
+ */
+#if (SZREG == 4)
+# define REG_S sw
+# define REG_L lw
+#else
+# define REG_S sd
+# define REG_L ld
+#endif
+
+/*
+ * How to add/sub/load/store/shift C int variables.
+ */
+#if (_MIPS_SZINT == 32)
+# define INT_ADD add
+# define INT_ADDI addi
+# define INT_ADDU addu
+# define INT_ADDIU addiu
+# define INT_SUB sub
+# define INT_SUBI subi
+# define INT_SUBU subu
+# define INT_SUBIU subu
+# define INT_L lw
+# define INT_S sw
+#endif
+
+#if (_MIPS_SZINT == 64)
+# define INT_ADD dadd
+# define INT_ADDI daddi
+# define INT_ADDU daddu
+# define INT_ADDIU daddiu
+# define INT_SUB dsub
+# define INT_SUBI dsubi
+# define INT_SUBU dsubu
+# define INT_SUBIU dsubu
+# define INT_L ld
+# define INT_S sd
+#endif
+
+/*
+ * How to add/sub/load/store/shift C long variables.
+ */
+#if (_MIPS_SZLONG == 32)
+# define LONG_ADD add
+# define LONG_ADDI addi
+# define LONG_ADDU addu
+# define LONG_ADDIU addiu
+# define LONG_SUB sub
+# define LONG_SUBI subi
+# define LONG_SUBU subu
+# define LONG_SUBIU subu
+# define LONG_L lw
+# define LONG_S sw
+# define LONG_SLL sll
+# define LONG_SLLV sllv
+# define LONG_SRL srl
+# define LONG_SRLV srlv
+# define LONG_SRA sra
+# define LONG_SRAV srav
+#endif
+
+#if (_MIPS_SZLONG == 64)
+# define LONG_ADD dadd
+# define LONG_ADDI daddi
+# define LONG_ADDU daddu
+# define LONG_ADDIU daddiu
+# define LONG_SUB dsub
+# define LONG_SUBI dsubi
+# define LONG_SUBU dsubu
+# define LONG_SUBIU dsubu
+# define LONG_L ld
+# define LONG_S sd
+# define LONG_SLL dsll
+# define LONG_SLLV dsllv
+# define LONG_SRL dsrl
+# define LONG_SRLV dsrlv
+# define LONG_SRA dsra
+# define LONG_SRAV dsrav
+#endif
+
+/*
+ * How to add/sub/load/store/shift pointers.
+ */
+#if (_MIPS_SIM == _ABIO32 && _MIPS_SZPTR == 32)
+# define PTR_ADD add
+# define PTR_ADDI addi
+# define PTR_ADDU addu
+# define PTR_ADDIU addiu
+# define PTR_SUB sub
+# define PTR_SUBI subi
+# define PTR_SUBU subu
+# define PTR_SUBIU subu
+# define PTR_L lw
+# define PTR_LA la
+# define PTR_S sw
+# define PTR_SLL sll
+# define PTR_SLLV sllv
+# define PTR_SRL srl
+# define PTR_SRLV srlv
+# define PTR_SRA sra
+# define PTR_SRAV srav
+
+# define PTR_SCALESHIFT 2
+#endif
+
+#if _MIPS_SIM == _ABIN32
+# define PTR_ADD add
+# define PTR_ADDI addi
+# define PTR_SUB sub
+# define PTR_SUBI subi
+#if !defined __mips_isa_rev || __mips_isa_rev < 6
+# define PTR_ADDU add /* no u */
+# define PTR_ADDIU addi /* no u */
+# define PTR_SUBU sub /* no u */
+# define PTR_SUBIU sub /* no u */
+#else
+# define PTR_ADDU addu
+# define PTR_ADDIU addiu
+# define PTR_SUBU subu
+# define PTR_SUBIU subu
+#endif
+# define PTR_L lw
+# define PTR_LA la
+# define PTR_S sw
+# define PTR_SLL sll
+# define PTR_SLLV sllv
+# define PTR_SRL srl
+# define PTR_SRLV srlv
+# define PTR_SRA sra
+# define PTR_SRAV srav
+
+# define PTR_SCALESHIFT 2
+#endif
+
+#if (_MIPS_SIM == _ABIO32 && _MIPS_SZPTR == 64 /* o64??? */) \
+ || _MIPS_SIM == _ABI64
+# define PTR_ADD dadd
+# define PTR_ADDI daddi
+# define PTR_ADDU daddu
+# define PTR_ADDIU daddiu
+# define PTR_SUB dsub
+# define PTR_SUBI dsubi
+# define PTR_SUBU dsubu
+# define PTR_SUBIU dsubu
+# define PTR_L ld
+# define PTR_LA dla
+# define PTR_S sd
+# define PTR_SLL dsll
+# define PTR_SLLV dsllv
+# define PTR_SRL dsrl
+# define PTR_SRLV dsrlv
+# define PTR_SRA dsra
+# define PTR_SRAV dsrav
+
+# define PTR_SCALESHIFT 3
+#endif
+
+/*
+ * Some cp0 registers were extended to 64bit for MIPS III.
+ */
+#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \
+ (_MIPS_ISA == _MIPS_ISA_MIPS32)
+# define MFC0 mfc0
+# define MTC0 mtc0
+#endif
+#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
+ (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
+# define MFC0 dmfc0
+# define MTC0 dmtc0
+#endif
+
+/* The MIPS architectures do not have a uniform memory model. Particular
+ platforms may provide additional guarantees - for instance, the R4000
+ LL and SC instructions implicitly perform a SYNC, and the 4K promises
+ strong ordering.
+
+ However, in the absence of those guarantees, we must assume weak ordering
+ and SYNC explicitly where necessary.
+
+ Some obsolete MIPS processors may not support the SYNC instruction. This
+ applies to "true" MIPS I processors; most of the processors which compile
+ using MIPS I implement parts of MIPS II. */
+
+#ifndef MIPS_SYNC
+# define MIPS_SYNC sync
+#endif
+
+#endif /* sys/asm.h */
diff --git a/sysdeps/mips/sys/fpregdef.h b/sysdeps/mips/sys/fpregdef.h
new file mode 100644
index 0000000000..6c4fc885d4
--- /dev/null
+++ b/sysdeps/mips/sys/fpregdef.h
@@ -0,0 +1,118 @@
+/* Copyright (C) 1991-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _SYS_FPREGDEF_H
+#define _SYS_FPREGDEF_H
+
+#include <sgidefs.h>
+
+/* Commonalities first, individualities next... */
+
+#define fv0 $f0 /* return value */
+#define fv1 $f2
+
+#if _MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABIN32
+#define fs0 $f20 /* callee saved */
+#define fs1 $f22
+#define fs2 $f24
+#define fs3 $f26
+#define fs4 $f28
+#define fs5 $f30
+#endif /* _MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABIN32 */
+
+#if _MIPS_SIM == _ABI64 || _MIPS_SIM == _ABIN32
+#define fa0 $f12 /* argument registers */
+#define fa1 $f13
+#define fa2 $f14
+#define fa3 $f15
+#define fa4 $f16
+#define fa5 $f17
+#define fa6 $f18
+#define fa7 $f19
+
+#define ft0 $f4 /* caller saved */
+#define ft1 $f5
+#define ft2 $f6
+#define ft3 $f7
+#define ft4 $f8
+#define ft5 $f9
+#define ft6 $f10
+#define ft7 $f11
+#endif /* _MIPS_SIM == _ABI64 || _MIPS_SIM == _ABIN32 */
+
+#if _MIPS_SIM == _ABIO32
+#define fv0f $f1 /* return value, high part */
+#define fv1f $f3
+
+#define fa0 $f12 /* argument registers */
+#define fa0f $f13
+#define fa1 $f14
+#define fa1f $f15
+
+#define ft0 $f4 /* caller saved */
+#define ft0f $f5
+#define ft1 $f6
+#define ft1f $f7
+#define ft2 $f8
+#define ft2f $f9
+#define ft3 $f10
+#define ft3f $f11
+#define ft4 $f16
+#define ft4f $f17
+#define ft5 $f18
+#define ft5f $f19
+
+#define fs0f $f21 /* callee saved, high part */
+#define fs1f $f23
+#define fs2f $f25
+#define fs3f $f27
+#define fs4f $f29
+#define fs5f $f31
+#endif /* _MIPS_SIM == _ABIO32 */
+
+#if _MIPS_SIM == _ABI64
+#define ft8 $f20 /* caller saved */
+#define ft9 $f21
+#define ft10 $f22
+#define ft11 $f23
+#define ft12 $f1
+#define ft13 $f3
+
+#define fs0 $f24 /* callee saved */
+#define fs1 $f25
+#define fs2 $f26
+#define fs3 $f27
+#define fs4 $f28
+#define fs5 $f29
+#define fs6 $f30
+#define fs7 $f31
+#endif /* _MIPS_SIM == _ABI64 */
+
+#if _MIPS_SIM == _ABIN32
+#define ft8 $f21 /* caller saved */
+#define ft9 $f23
+#define ft10 $f25
+#define ft11 $f27
+#define ft12 $f29
+#define ft13 $f31
+#define ft14 $f1
+#define ft15 $f3
+#endif /* _MIPS_SIM == _ABIN32 */
+
+#define fcr31 $31 /* FPU status register */
+
+#endif /* sys/fpregdef.h */
diff --git a/sysdeps/mips/sys/regdef.h b/sysdeps/mips/sys/regdef.h
new file mode 100644
index 0000000000..950fbe68a4
--- /dev/null
+++ b/sysdeps/mips/sys/regdef.h
@@ -0,0 +1,81 @@
+/* Copyright (C) 1997-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ralf Baechle <ralf@gnu.org>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _SYS_REGDEF_H
+#define _SYS_REGDEF_H
+
+#include <sgidefs.h>
+
+/*
+ * Symbolic register names for 32 bit ABI
+ */
+#define zero $0 /* wired zero */
+#define AT $1 /* assembler temp - uppercase because of ".set at" */
+#define v0 $2 /* return value */
+#define v1 $3
+#define a0 $4 /* argument registers */
+#define a1 $5
+#define a2 $6
+#define a3 $7
+#if _MIPS_SIM != _ABIO32
+#define a4 $8
+#define a5 $9
+#define a6 $10
+#define a7 $11
+#define t0 $12
+#define t1 $13
+#define t2 $14
+#define t3 $15
+#define ta0 a4
+#define ta1 a5
+#define ta2 a6
+#define ta3 a7
+#else /* if _MIPS_SIM == _ABIO32 */
+#define t0 $8 /* caller saved */
+#define t1 $9
+#define t2 $10
+#define t3 $11
+#define t4 $12
+#define t5 $13
+#define t6 $14
+#define t7 $15
+#define ta0 t4
+#define ta1 t5
+#define ta2 t6
+#define ta3 t7
+#endif /* _MIPS_SIM == _ABIO32 */
+#define s0 $16 /* callee saved */
+#define s1 $17
+#define s2 $18
+#define s3 $19
+#define s4 $20
+#define s5 $21
+#define s6 $22
+#define s7 $23
+#define t8 $24 /* caller saved */
+#define t9 $25
+#define jp $25 /* PIC jump register */
+#define k0 $26 /* kernel scratch */
+#define k1 $27
+#define gp $28 /* global pointer */
+#define sp $29 /* stack pointer */
+#define fp $30 /* frame pointer */
+#define s8 $30 /* same like fp! */
+#define ra $31 /* return address */
+
+#endif /* _SYS_REGDEF_H */
diff --git a/sysdeps/mips/sys/tas.h b/sysdeps/mips/sys/tas.h
new file mode 100644
index 0000000000..e14b5f04c1
--- /dev/null
+++ b/sysdeps/mips/sys/tas.h
@@ -0,0 +1,69 @@
+/* Copyright (C) 2000-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Maciej W. Rozycki <macro@ds2.pg.gda.pl>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _SYS_TAS_H
+#define _SYS_TAS_H 1
+
+#include <features.h>
+#include <sgidefs.h>
+
+__BEGIN_DECLS
+
+extern int _test_and_set (int *__p, int __v)
+ __THROW __attribute__ ((__nomips16__));
+
+#ifdef __USE_EXTERN_INLINES
+
+# ifndef _EXTERN_INLINE
+# define _EXTERN_INLINE __extern_inline
+# endif
+
+_EXTERN_INLINE int __attribute__ ((__nomips16__))
+__NTH (_test_and_set (int *__p, int __v))
+{
+ int __r, __t;
+
+ __asm__ __volatile__
+ ("/* Inline test and set */\n"
+ ".set push\n\t"
+#if _MIPS_SIM == _ABIO32
+ ".set mips2\n\t"
+#endif
+ "sync\n\t"
+ "1:\n\t"
+ "ll %0,%3\n\t"
+ "move %1,%4\n\t"
+ "beq %0,%4,2f\n\t"
+ "sc %1,%2\n\t"
+ "beqz %1,1b\n"
+ "sync\n\t"
+ ".set pop\n\t"
+ "2:\n\t"
+ "/* End test and set */"
+ : "=&r" (__r), "=&r" (__t), "=m" (*__p)
+ : "m" (*__p), "r" (__v)
+ : "memory");
+
+ return __r;
+}
+
+#endif /* __USE_EXTERN_INLINES */
+
+__END_DECLS
+
+#endif /* sys/tas.h */
diff --git a/sysdeps/mips/sys/ucontext.h b/sysdeps/mips/sys/ucontext.h
new file mode 100644
index 0000000000..bf324794d3
--- /dev/null
+++ b/sysdeps/mips/sys/ucontext.h
@@ -0,0 +1,158 @@
+/* Copyright (C) 1998-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* System V/mips ABI compliant context switching support. */
+
+#ifndef _SYS_UCONTEXT_H
+#define _SYS_UCONTEXT_H 1
+
+#include <features.h>
+#include <sgidefs.h>
+#include <signal.h>
+
+/* Type for general register. */
+#if _MIPS_SIM == _ABIO32
+typedef __uint32_t greg_t;
+#else
+typedef __uint64_t greg_t;
+#endif
+
+/* Number of general registers. */
+#define NGREG 36
+
+/* Container for all general registers. */
+typedef greg_t gregset_t[NGREG];
+
+/* Number of each register is the `gregset_t' array. */
+enum
+{
+ CTX_R0 = 0,
+#define CTX_R0 CTX_R0
+ CTX_AT = 1,
+#define CTX_AT CTX_AT
+ CTX_V0 = 2,
+#define CTX_V0 CTX_V0
+ CTX_V1 = 3,
+#define CTX_V1 CTX_V1
+ CTX_A0 = 4,
+#define CTX_A0 CTX_A0
+ CTX_A1 = 5,
+#define CTX_A1 CTX_A1
+ CTX_A2 = 6,
+#define CTX_A2 CTX_A2
+ CTX_A3 = 7,
+#define CTX_A3 CTX_A3
+ CTX_T0 = 8,
+#define CTX_T0 CTX_T0
+ CTX_T1 = 9,
+#define CTX_T1 CTX_T1
+ CTX_T2 = 10,
+#define CTX_T2 CTX_T2
+ CTX_T3 = 11,
+#define CTX_T3 CTX_T3
+ CTX_T4 = 12,
+#define CTX_T4 CTX_T4
+ CTX_T5 = 13,
+#define CTX_T5 CTX_T5
+ CTX_T6 = 14,
+#define CTX_T6 CTX_T6
+ CTX_T7 = 15,
+#define CTX_T7 CTX_T7
+ CTX_S0 = 16,
+#define CTX_S0 CTX_S0
+ CTX_S1 = 17,
+#define CTX_S1 CTX_S1
+ CTX_S2 = 18,
+#define CTX_S2 CTX_S2
+ CTX_S3 = 19,
+#define CTX_S3 CTX_S3
+ CTX_S4 = 20,
+#define CTX_S4 CTX_S4
+ CTX_S5 = 21,
+#define CTX_S5 CTX_S5
+ CTX_S6 = 22,
+#define CTX_S6 CTX_S6
+ CTX_S7 = 23,
+#define CTX_S7 CTX_S7
+ CTX_T8 = 24,
+#define CTX_T8 CTX_T8
+ CTX_T9 = 25,
+#define CTX_T9 CTX_T9
+ CTX_K0 = 26,
+#define CTX_K0 CTX_K0
+ CTX_K1 = 27,
+#define CTX_K1 CTX_K1
+ CTX_GP = 28,
+#define CTX_GP CTX_GP
+ CTX_SP = 29,
+#define CTX_SP CTX_SP
+ CTX_S8 = 30,
+#define CTX_S8 CTX_S8
+ CTX_RA = 31,
+#define CTX_RA CTX_RA
+ CTX_MDLO = 32,
+#define CTX_MDLO CTX_MDLO
+ CTX_MDHI = 33,
+#define CTX_MDHI CTX_MDHI
+ CTX_CAUSE = 34,
+#define CTX_CAUSE CTX_CAUSE
+ CTX_EPC = 35,
+#define CTX_EPC CTX_EPC
+};
+
+/* Structure to describe FPU registers. */
+typedef struct fpregset
+{
+ union
+ {
+#if _MIPS_SIM == _ABIO32
+ double fp_dregs[16];
+ float fp_fregs[32];
+ unsigned int fp_regs[32];
+#else
+ double fp_dregs[32];
+ /* float fp_fregs[32]; */
+ __uint64_t fp_regs[32];
+#endif
+ } fp_r;
+ unsigned int fp_csr;
+ unsigned int fp_pad;
+} fpregset_t;
+
+/* Context to describe whole processor state. */
+typedef struct
+{
+ gregset_t gpregs;
+ fpregset_t fpregs;
+} mcontext_t;
+
+/* Userlevel context. */
+typedef struct ucontext
+{
+#if _MIPS_SIM == _ABIO32
+ unsigned long int uc_flags;
+#else
+ __uint64_t uc_flags;
+#endif
+ struct ucontext *uc_link;
+ __sigset_t uc_sigmask;
+ stack_t uc_stack;
+ mcontext_t uc_mcontext;
+ int uc_filler[48];
+} ucontext_t;
+
+#endif /* sys/ucontext.h */
diff --git a/sysdeps/mips/tininess.h b/sysdeps/mips/tininess.h
new file mode 100644
index 0000000000..1db37790f8
--- /dev/null
+++ b/sysdeps/mips/tininess.h
@@ -0,0 +1 @@
+#define TININESS_AFTER_ROUNDING 1
diff --git a/sysdeps/mips/tls-macros.h b/sysdeps/mips/tls-macros.h
new file mode 100644
index 0000000000..3e87e42ea1
--- /dev/null
+++ b/sysdeps/mips/tls-macros.h
@@ -0,0 +1,123 @@
+/* Macros to support TLS testing in times of missing compiler support. */
+
+#include <sys/cdefs.h>
+#include <sys/asm.h>
+
+#define __STRING2(X) __STRING(X)
+#define ADDU __STRING2(PTR_ADDU)
+#define ADDIU __STRING2(PTR_ADDIU)
+#define LW __STRING2(PTR_L)
+
+/* Load the GOT pointer, which may not be in $28 in a non-PIC
+ (abicalls pic0) function. */
+#ifndef __PIC__
+# if _MIPS_SIM != _ABI64
+# ifndef __mips16
+# define LOAD_GP "move %[tmp], $28\n\tla $28, __gnu_local_gp\n\t"
+# else
+# define LOAD_GP \
+ "li %[tmp], %%hi(__gnu_local_gp)\n\t" \
+ "sll %[tmp], 16\n\t" \
+ "addiu %[tmp], %%lo(__gnu_local_gp)\n\t"
+# endif
+# else
+# define LOAD_GP "move %[tmp], $28\n\tdla $28, __gnu_local_gp\n\t"
+# endif
+# define UNLOAD_GP "\n\tmove $28, %[tmp]"
+#else
+/* MIPS16 (re)creates the GP value using PC-relative instructions. */
+# ifdef __mips16
+# define LOAD_GP \
+ "li %[tmp], %%hi(_gp_disp)\n\t" \
+ "addiu %0, $pc, %%lo(_gp_disp)\n\t" \
+ "sll %[tmp], 16\n\t" \
+ "addu %[tmp], %0\n\t"
+# else
+# define LOAD_GP
+# endif
+# define UNLOAD_GP
+#endif
+
+#ifndef __mips16
+# define TLS_GD(x) \
+ ({ void *__result, *__tmp; \
+ extern void *__tls_get_addr (void *); \
+ asm (LOAD_GP ADDIU " %0, $28, %%tlsgd(" #x ")" \
+ UNLOAD_GP \
+ : "=r" (__result), [tmp] "=&r" (__tmp)); \
+ (int *)__tls_get_addr (__result); })
+# define TLS_LD(x) \
+ ({ void *__result, *__tmp; \
+ extern void *__tls_get_addr (void *); \
+ asm (LOAD_GP ADDIU " %0, $28, %%tlsldm(" #x ")" \
+ UNLOAD_GP \
+ : "=r" (__result), [tmp] "=&r" (__tmp)); \
+ __result = __tls_get_addr (__result); \
+ asm ("lui $3,%%dtprel_hi(" #x ")\n\t" \
+ "addiu $3,$3,%%dtprel_lo(" #x ")\n\t" \
+ ADDU " %0,%0,$3" \
+ : "+r" (__result) : : "$3"); \
+ __result; })
+# define TLS_IE(x) \
+ ({ void *__result, *__tmp; \
+ asm (".set push\n\t.set mips32r2\n\t" \
+ "rdhwr\t%0,$29\n\t.set pop" \
+ : "=v" (__result)); \
+ asm (LOAD_GP LW " $3,%%gottprel(" #x ")($28)\n\t" \
+ ADDU " %0,%0,$3" \
+ UNLOAD_GP \
+ : "+r" (__result), [tmp] "=&r" (__tmp) \
+ : : "$3"); \
+ __result; })
+# define TLS_LE(x) \
+ ({ void *__result; \
+ asm (".set push\n\t.set mips32r2\n\t" \
+ "rdhwr\t%0,$29\n\t.set pop" \
+ : "=v" (__result)); \
+ asm ("lui $3,%%tprel_hi(" #x ")\n\t" \
+ "addiu $3,$3,%%tprel_lo(" #x ")\n\t" \
+ ADDU " %0,%0,$3" \
+ : "+r" (__result) : : "$3"); \
+ __result; })
+
+#else /* __mips16 */
+/* MIPS16 version. */
+# define TLS_GD(x) \
+ ({ void *__result, *__tmp; \
+ extern void *__tls_get_addr (void *); \
+ asm (LOAD_GP ADDIU " %1, %%tlsgd(" #x ")" \
+ "\n\tmove %0, %1" \
+ : "=d" (__result), [tmp] "=&d" (__tmp)); \
+ (int *) __tls_get_addr (__result); })
+# define TLS_LD(x) \
+ ({ void *__result, *__tmp; \
+ extern void *__tls_get_addr (void *); \
+ asm (LOAD_GP ADDIU " %1, %%tlsldm(" #x ")" \
+ "\n\tmove %0, %1" \
+ : "=d" (__result), [tmp] "=&d" (__tmp)); \
+ __result = __tls_get_addr (__result); \
+ asm ("li $3,%%dtprel_hi(" #x ")\n\t" \
+ "sll $3,16\n\t" \
+ "addiu $3,%%dtprel_lo(" #x ")\n\t" \
+ ADDU " %0,%0,$3" \
+ : "+d" (__result) : : "$3"); \
+ __result; })
+# define TLS_IE(x) \
+ ({ void *__result, *__tmp, *__tp; \
+ __tp = __builtin_thread_pointer (); \
+ asm (LOAD_GP LW " $3,%%gottprel(" #x ")(%1)\n\t" \
+ ADDU " %0,%[tp],$3" \
+ : "=&d" (__result), [tmp] "=&d" (__tmp) \
+ : [tp] "d" (__tp) : "$3"); \
+ __result; })
+# define TLS_LE(x) \
+ ({ void *__result, *__tp; \
+ __tp = __builtin_thread_pointer (); \
+ asm ("li $3,%%tprel_hi(" #x ")\n\t" \
+ "sll $3,16\n\t" \
+ "addiu $3,%%tprel_lo(" #x ")\n\t" \
+ ADDU " %0,%[tp],$3" \
+ : "=d" (__result) : [tp] "d" (__tp) : "$3"); \
+ __result; })
+
+#endif /* __mips16 */
diff --git a/sysdeps/mips/tst-abi-fp32mod.c b/sysdeps/mips/tst-abi-fp32mod.c
new file mode 100644
index 0000000000..a43aca3b0a
--- /dev/null
+++ b/sysdeps/mips/tst-abi-fp32mod.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+int
+fp32 (void)
+{
+ return 1;
+}
diff --git a/sysdeps/mips/tst-abi-fp64amod.c b/sysdeps/mips/tst-abi-fp64amod.c
new file mode 100644
index 0000000000..a062568633
--- /dev/null
+++ b/sysdeps/mips/tst-abi-fp64amod.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+int
+fp64a (void)
+{
+ return 7;
+}
diff --git a/sysdeps/mips/tst-abi-fp64mod.c b/sysdeps/mips/tst-abi-fp64mod.c
new file mode 100644
index 0000000000..03c33460b6
--- /dev/null
+++ b/sysdeps/mips/tst-abi-fp64mod.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+int
+fp64 (void)
+{
+ return 6;
+}
diff --git a/sysdeps/mips/tst-abi-fpxxmod.c b/sysdeps/mips/tst-abi-fpxxmod.c
new file mode 100644
index 0000000000..ed61201de2
--- /dev/null
+++ b/sysdeps/mips/tst-abi-fpxxmod.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+int
+fpxx (void)
+{
+ return 5;
+}
diff --git a/sysdeps/mips/tst-abi-fpxxomod.c b/sysdeps/mips/tst-abi-fpxxomod.c
new file mode 100644
index 0000000000..47946b75f6
--- /dev/null
+++ b/sysdeps/mips/tst-abi-fpxxomod.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+int
+fpxxo (void)
+{
+ return 5 + 100;
+}
diff --git a/sysdeps/mips/tst-abi-interlink.c b/sysdeps/mips/tst-abi-interlink.c
new file mode 100644
index 0000000000..a42a811b62
--- /dev/null
+++ b/sysdeps/mips/tst-abi-interlink.c
@@ -0,0 +1,844 @@
+/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/prctl.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#if defined PR_GET_FP_MODE && defined PR_SET_FP_MODE
+# define HAVE_PRCTL_FP_MODE 1
+# define FR1_MODE (PR_FP_MODE_FR)
+# define FRE_MODE (PR_FP_MODE_FR | PR_FP_MODE_FRE)
+#else
+# define HAVE_PRCTL_FP_MODE 0
+# define FR1_MODE 0x1
+# define FRE_MODE 0x2
+#endif
+
+#define STR_VAL(VAL) #VAL
+#define N_STR(VAL) STR_VAL(VAL)
+
+#define START_STATE(NAME) \
+case s_ ## NAME: \
+ { \
+ switch (obj) \
+ {
+
+#define END_STATE \
+ default: \
+ return false; \
+ } \
+ break; \
+ }
+
+#define NEXT(OBJ, NEXT_STATE) \
+case o_ ## OBJ: \
+ current_fp_state = s_ ## NEXT_STATE; \
+ break;
+
+#define NEXT_REQ_FR1(OBJ, NEXT_STATE) \
+case o_ ## OBJ: \
+ { \
+ if (has_fr1) \
+ current_fp_state = s_ ## NEXT_STATE; \
+ else \
+ return false; \
+ } \
+ break;
+
+#define NEXT_REQ_FR0(OBJ, NEXT_STATE) \
+case o_ ## OBJ: \
+ { \
+ if (!is_r6 \
+ || (is_r6 && has_fr1 && has_fre)) \
+ current_fp_state = s_ ## NEXT_STATE; \
+ else \
+ return false; \
+ } \
+ break;
+
+#define NEXT_REQ_FRE(OBJ, NEXT_STATE) \
+case o_ ## OBJ: \
+ { \
+ if (has_fr1 && has_fre) \
+ current_fp_state = s_ ## NEXT_STATE; \
+ else \
+ return false; \
+ } \
+ break;
+
+#define NEXT_NO_MODE_CHANGE(OBJ, NEXT_STATE) \
+case o_ ## OBJ: \
+ { \
+ if (current_mode_valid_p (s_ ## NEXT_STATE)) \
+ { \
+ current_fp_state = s_ ## NEXT_STATE; \
+ cant_change_mode = true; \
+ } \
+ else \
+ return false; \
+ } \
+ break;
+
+static const char * const shared_lib_names[] =
+ {
+ "tst-abi-fpanymod.so", "tst-abi-fpsoftmod.so", "tst-abi-fpsinglemod.so",
+ "tst-abi-fp32mod.so", "tst-abi-fp64mod.so", "tst-abi-fp64amod.so",
+ "tst-abi-fpxxmod.so", "tst-abi-fpxxomod.so"
+ };
+
+struct fp_mode_req
+{
+ int mode1;
+ int mode2;
+ int mode3;
+};
+
+enum fp_obj
+{
+ o_any,
+ o_soft,
+ o_single,
+ o_fp32,
+ o_fp64,
+ o_fp64a,
+ o_fpxx,
+ o_fpxxo,
+ o_max
+};
+
+enum fp_state
+{
+ s_any,
+ s_soft,
+ s_single,
+ s_fp32,
+ s_fpxx,
+ s_fpxxo,
+ s_fp64a,
+ s_fp64,
+ s_fpxxo_fpxx,
+ s_fp32_fpxx,
+ s_fp32_fpxxo,
+ s_fp32_fpxxo_fpxx,
+ s_fp32_fp64a_fpxx,
+ s_fp32_fp64a_fpxxo,
+ s_fp32_fp64a_fpxxo_fpxx,
+ s_fp64a_fp32,
+ s_fp64a_fpxx,
+ s_fp64a_fpxxo,
+ s_fp64a_fp64,
+ s_fp64a_fp64_fpxx,
+ s_fp64a_fp64_fpxxo,
+ s_fp64a_fpxx_fpxxo,
+ s_fp64a_fp64_fpxxo_fpxx,
+ s_fp64_fpxx,
+ s_fp64_fpxxo,
+ s_fp64_fpxx_fpxxo
+};
+
+
+static int current_fp_mode;
+static bool cant_change_mode = false;
+static bool has_fr1 = false;
+static bool has_fre = false;
+static bool is_r6 = false;
+static unsigned int fp_obj_count[o_max];
+void * shared_lib_ptrs[o_max];
+static enum fp_state current_fp_state = s_any;
+static enum fp_obj test_objects[FPABI_COUNT] = { FPABI_LIST };
+
+/* This function will return the valid FP modes for the specified state. */
+
+static struct fp_mode_req
+compute_fp_modes (enum fp_state state)
+{
+ struct fp_mode_req requirements;
+
+ requirements.mode1 = -1;
+ requirements.mode2 = -1;
+ requirements.mode3 = -1;
+
+ switch (state)
+ {
+ case s_single:
+ {
+ if (is_r6)
+ requirements.mode1 = FR1_MODE;
+ else
+ {
+ requirements.mode1 = 0;
+ requirements.mode2 = FR1_MODE;
+ }
+ break;
+ }
+ case s_fp32:
+ case s_fp32_fpxx:
+ case s_fp32_fpxxo:
+ case s_fp32_fpxxo_fpxx:
+ {
+ if (is_r6)
+ requirements.mode1 = FRE_MODE;
+ else
+ {
+ requirements.mode1 = 0;
+ requirements.mode2 = FRE_MODE;
+ }
+ break;
+ }
+ case s_fpxx:
+ case s_fpxxo:
+ case s_fpxxo_fpxx:
+ case s_any:
+ case s_soft:
+ {
+ if (is_r6)
+ {
+ requirements.mode1 = FR1_MODE;
+ requirements.mode2 = FRE_MODE;
+ }
+ else
+ {
+ requirements.mode1 = 0;
+ requirements.mode2 = FR1_MODE;
+ requirements.mode3 = FRE_MODE;
+ }
+ break;
+ }
+ case s_fp64a:
+ case s_fp64a_fpxx:
+ case s_fp64a_fpxxo:
+ case s_fp64a_fpxx_fpxxo:
+ {
+ requirements.mode1 = FR1_MODE;
+ requirements.mode2 = FRE_MODE;
+ break;
+ }
+ case s_fp64:
+ case s_fp64_fpxx:
+ case s_fp64_fpxxo:
+ case s_fp64_fpxx_fpxxo:
+ case s_fp64a_fp64:
+ case s_fp64a_fp64_fpxx:
+ case s_fp64a_fp64_fpxxo:
+ case s_fp64a_fp64_fpxxo_fpxx:
+ {
+ requirements.mode1 = FR1_MODE;
+ break;
+ }
+ case s_fp64a_fp32:
+ case s_fp32_fp64a_fpxx:
+ case s_fp32_fp64a_fpxxo:
+ case s_fp32_fp64a_fpxxo_fpxx:
+ {
+ requirements.mode1 = FRE_MODE;
+ break;
+ }
+ }
+ return requirements;
+}
+
+/* Check the current mode is suitable for the specified state. */
+
+static bool
+current_mode_valid_p (enum fp_state s)
+{
+ struct fp_mode_req req = compute_fp_modes (s);
+ return (req.mode1 == current_fp_mode
+ || req.mode2 == current_fp_mode
+ || req.mode3 == current_fp_mode);
+}
+
+/* Run the state machine by adding a new object. */
+
+static bool
+set_next_fp_state (enum fp_obj obj)
+{
+ cant_change_mode = false;
+ switch (current_fp_state)
+ {
+
+ START_STATE(soft)
+ NEXT(soft,soft)
+ NEXT(any,soft)
+ END_STATE
+
+ START_STATE(single)
+ NEXT(single,single)
+ NEXT(any,single)
+ END_STATE
+
+ START_STATE(any)
+ NEXT_REQ_FR0(fp32, fp32)
+ NEXT(fpxx, fpxx)
+ NEXT(fpxxo, fpxxo)
+ NEXT_REQ_FR1(fp64a, fp64a)
+ NEXT_REQ_FR1(fp64, fp64)
+ NEXT(any,any)
+ NEXT(soft,soft)
+ NEXT(single,single)
+ END_STATE
+
+ START_STATE(fp32)
+ NEXT_REQ_FR0(fp32,fp32)
+ NEXT(fpxx, fp32_fpxx)
+ NEXT(fpxxo, fp32_fpxxo)
+ NEXT_REQ_FRE(fp64a, fp64a_fp32)
+ NEXT(any,fp32)
+ END_STATE
+
+ START_STATE(fpxx)
+ NEXT_REQ_FR0(fp32, fp32_fpxx)
+ NEXT_REQ_FR1(fp64, fp64_fpxx)
+ NEXT_REQ_FR1(fp64a, fp64a_fpxx)
+ NEXT(fpxxo, fpxxo_fpxx)
+ NEXT(fpxx,fpxx)
+ NEXT(any,fpxx)
+ END_STATE
+
+ START_STATE(fpxxo)
+ NEXT_NO_MODE_CHANGE(fp32, fp32_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp64, fp64_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp64a, fp64a_fpxxo)
+ NEXT_NO_MODE_CHANGE(fpxx, fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fpxxo,fpxxo)
+ NEXT_NO_MODE_CHANGE(any,fpxxo)
+ END_STATE
+
+ START_STATE(fp64a)
+ NEXT_REQ_FRE(fp32, fp64a_fp32)
+ NEXT_REQ_FR1(fp64, fp64a_fp64)
+ NEXT(fpxxo, fp64a_fpxxo)
+ NEXT(fpxx, fp64a_fpxx)
+ NEXT_REQ_FR1(fp64a, fp64a)
+ NEXT(any, fp64a)
+ END_STATE
+
+ START_STATE(fp64)
+ NEXT_REQ_FR1(fp64a, fp64a_fp64)
+ NEXT(fpxxo, fp64_fpxxo)
+ NEXT(fpxx, fp64_fpxx)
+ NEXT_REQ_FR1(fp64, fp64)
+ NEXT(any, fp64)
+ END_STATE
+
+ START_STATE(fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fp32, fp32_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fp64, fp64_fpxx_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp64a, fp64a_fpxx_fpxxo)
+ NEXT_NO_MODE_CHANGE(fpxx, fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fpxxo, fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(any, fpxxo_fpxx)
+ END_STATE
+
+ START_STATE(fp32_fpxx)
+ NEXT_REQ_FR0(fp32, fp32_fpxx)
+ NEXT(fpxx, fp32_fpxx)
+ NEXT(fpxxo, fp32_fpxxo_fpxx)
+ NEXT_REQ_FRE(fp64a, fp32_fp64a_fpxx)
+ NEXT(any, fp32_fpxx)
+ END_STATE
+
+ START_STATE(fp32_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp32, fp32_fpxxo)
+ NEXT_NO_MODE_CHANGE(fpxxo, fp32_fpxxo)
+ NEXT_NO_MODE_CHANGE(fpxx, fp32_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fp64a, fp32_fp64a_fpxxo)
+ NEXT_NO_MODE_CHANGE(any, fp32_fpxxo)
+ END_STATE
+
+ START_STATE(fp32_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fp32, fp32_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fpxxo, fp32_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fpxx, fp32_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fp64a, fp32_fp64a_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(any, fp32_fpxxo_fpxx)
+ END_STATE
+
+ START_STATE(fp64a_fp32)
+ NEXT_REQ_FRE(fp32, fp64a_fp32)
+ NEXT_REQ_FRE(fp64a, fp64a_fp32)
+ NEXT(fpxxo, fp32_fp64a_fpxxo)
+ NEXT(fpxx, fp32_fp64a_fpxx)
+ NEXT(any, fp64a_fp32)
+ END_STATE
+
+ START_STATE(fp64a_fpxx)
+ NEXT_REQ_FRE(fp32, fp32_fp64a_fpxx)
+ NEXT_REQ_FR1(fp64a, fp64a_fpxx)
+ NEXT(fpxx, fp64a_fpxx)
+ NEXT(fpxxo, fp64a_fpxx_fpxxo)
+ NEXT_REQ_FR1(fp64, fp64a_fp64_fpxx)
+ NEXT(any, fp64a_fpxx)
+ END_STATE
+
+ START_STATE(fp64a_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp32, fp32_fp64a_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp64a, fp64a_fpxxo)
+ NEXT_NO_MODE_CHANGE(fpxx, fp64a_fpxx_fpxxo)
+ NEXT_NO_MODE_CHANGE(fpxxo, fp64a_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp64, fp64a_fp64_fpxxo)
+ NEXT_NO_MODE_CHANGE(any, fp64a_fpxxo)
+ END_STATE
+
+ START_STATE(fp64a_fpxx_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp32, fp32_fp64a_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fp64a, fp64a_fpxx_fpxxo)
+ NEXT_NO_MODE_CHANGE(fpxx, fp64a_fpxx_fpxxo)
+ NEXT_NO_MODE_CHANGE(fpxxo, fp64a_fpxx_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp64, fp64a_fp64_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(any, fp64a_fpxx_fpxxo)
+ END_STATE
+
+ START_STATE(fp64_fpxx)
+ NEXT_REQ_FR1(fp64a, fp64a_fp64_fpxx)
+ NEXT(fpxxo, fp64_fpxx_fpxxo)
+ NEXT(fpxx, fp64_fpxx)
+ NEXT_REQ_FR1(fp64, fp64_fpxx)
+ NEXT(any, fp64_fpxx)
+ END_STATE
+
+ START_STATE(fp64_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp64a, fp64a_fp64_fpxxo)
+ NEXT_NO_MODE_CHANGE(fpxxo, fp64_fpxxo)
+ NEXT_NO_MODE_CHANGE(fpxx, fp64_fpxx_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp64, fp64_fpxxo)
+ NEXT_NO_MODE_CHANGE(any, fp64_fpxxo)
+ END_STATE
+
+ START_STATE(fp64_fpxx_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp64a, fp64a_fp64_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fpxxo, fp64_fpxx_fpxxo)
+ NEXT_NO_MODE_CHANGE(fpxx, fp64_fpxx_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp64, fp64_fpxx_fpxxo)
+ NEXT_NO_MODE_CHANGE(any, fp64_fpxx_fpxxo)
+ END_STATE
+
+ START_STATE(fp64a_fp64)
+ NEXT_REQ_FR1(fp64a, fp64a_fp64)
+ NEXT(fpxxo, fp64a_fp64_fpxxo)
+ NEXT(fpxx, fp64a_fp64_fpxx)
+ NEXT_REQ_FR1(fp64, fp64a_fp64)
+ NEXT(any, fp64a_fp64)
+ END_STATE
+
+ START_STATE(fp64a_fp64_fpxx)
+ NEXT_REQ_FR1(fp64a, fp64a_fp64_fpxx)
+ NEXT(fpxxo, fp64a_fp64_fpxxo_fpxx)
+ NEXT(fpxx, fp64a_fp64_fpxx)
+ NEXT_REQ_FR1(fp64, fp64a_fp64_fpxx)
+ NEXT(any, fp64a_fp64_fpxx)
+ END_STATE
+
+ START_STATE(fp64a_fp64_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp64a, fp64a_fp64_fpxxo)
+ NEXT_NO_MODE_CHANGE(fpxx, fp64a_fp64_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fpxxo, fp64a_fp64_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp64, fp64a_fp64_fpxxo)
+ NEXT_NO_MODE_CHANGE(any, fp64a_fp64_fpxxo)
+ END_STATE
+
+ START_STATE(fp64a_fp64_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fp64a, fp64a_fp64_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fpxx, fp64a_fp64_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fpxxo, fp64a_fp64_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fp64, fp64a_fp64_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(any, fp64a_fp64_fpxxo_fpxx)
+ END_STATE
+
+ START_STATE(fp32_fp64a_fpxx)
+ NEXT_REQ_FRE(fp32, fp32_fp64a_fpxx)
+ NEXT_REQ_FRE(fp64a, fp32_fp64a_fpxx)
+ NEXT(fpxxo, fp32_fp64a_fpxxo_fpxx)
+ NEXT(fpxx, fp32_fp64a_fpxx)
+ NEXT(any, fp32_fp64a_fpxx)
+ END_STATE
+
+ START_STATE(fp32_fp64a_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp32, fp32_fp64a_fpxxo)
+ NEXT_NO_MODE_CHANGE(fp64a, fp32_fp64a_fpxxo)
+ NEXT_NO_MODE_CHANGE(fpxx, fp32_fp64a_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fpxxo, fp32_fp64a_fpxxo)
+ NEXT_NO_MODE_CHANGE(any, fp32_fp64a_fpxxo)
+ END_STATE
+
+ START_STATE(fp32_fp64a_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fp32, fp32_fp64a_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fp64a, fp32_fp64a_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fpxx, fp32_fp64a_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(fpxxo, fp32_fp64a_fpxxo_fpxx)
+ NEXT_NO_MODE_CHANGE(any, fp32_fp64a_fpxxo_fpxx)
+ END_STATE
+ }
+
+ if (obj != o_max)
+ fp_obj_count[obj]++;
+
+ return true;
+}
+
+/* Run the state machine by removing an object. */
+
+static bool
+remove_object (enum fp_obj obj)
+{
+ if (obj == o_max)
+ return false;
+
+ fp_obj_count[obj]--;
+
+ /* We can't change fp state until all the objects
+ of a particular type have been unloaded. */
+ if (fp_obj_count[obj] != 0)
+ return false;
+
+ switch (current_fp_state)
+ {
+ START_STATE(soft)
+ NEXT(soft,any)
+ END_STATE
+
+ START_STATE(single)
+ NEXT(single,any)
+ END_STATE
+
+ START_STATE(any)
+ NEXT(any,any)
+ END_STATE
+
+ START_STATE(fp32)
+ NEXT (fp32,any)
+ END_STATE
+
+ START_STATE(fpxx)
+ NEXT (fpxx,any)
+ END_STATE
+
+ START_STATE(fpxxo)
+ NEXT (fpxxo,any)
+ END_STATE
+
+ START_STATE(fp64a)
+ NEXT(fp64a, any)
+ END_STATE
+
+ START_STATE(fp64)
+ NEXT(fp64, any)
+ END_STATE
+
+ START_STATE(fpxxo_fpxx)
+ NEXT(fpxx, fpxxo)
+ NEXT(fpxxo, fpxx)
+ END_STATE
+
+ START_STATE(fp32_fpxx)
+ NEXT(fp32, fpxx)
+ NEXT(fpxx, fp32)
+ END_STATE
+
+ START_STATE(fp32_fpxxo)
+ NEXT(fp32, fpxxo)
+ NEXT(fpxxo, fp32)
+ END_STATE
+
+ START_STATE(fp32_fpxxo_fpxx)
+ NEXT(fp32, fpxxo_fpxx)
+ NEXT(fpxxo, fp32_fpxx)
+ NEXT(fpxx, fp32_fpxxo)
+ END_STATE
+
+ START_STATE(fp64a_fp32)
+ NEXT(fp32, fp64a)
+ NEXT(fp64a, fp32)
+ END_STATE
+
+ START_STATE(fp64a_fpxx)
+ NEXT(fp64a, fpxx)
+ NEXT(fpxx, fp64a)
+ END_STATE
+
+ START_STATE(fp64a_fpxxo)
+ NEXT(fp64a, fpxxo)
+ NEXT(fpxxo, fp64a)
+ END_STATE
+
+ START_STATE(fp64a_fpxx_fpxxo)
+ NEXT(fp64a, fpxxo_fpxx)
+ NEXT(fpxx, fp64a_fpxxo)
+ NEXT(fpxxo, fp64a_fpxx)
+ END_STATE
+
+ START_STATE(fp64_fpxx)
+ NEXT(fpxx, fp64)
+ NEXT(fp64, fpxx)
+ END_STATE
+
+ START_STATE(fp64_fpxxo)
+ NEXT(fpxxo, fp64)
+ NEXT(fp64, fpxxo)
+ END_STATE
+
+ START_STATE(fp64_fpxx_fpxxo)
+ NEXT(fp64, fpxxo_fpxx)
+ NEXT(fpxxo, fp64_fpxx)
+ NEXT(fpxx, fp64_fpxxo)
+ END_STATE
+
+ START_STATE(fp64a_fp64)
+ NEXT(fp64a, fp64)
+ NEXT(fp64, fp64a)
+ END_STATE
+
+ START_STATE(fp64a_fp64_fpxx)
+ NEXT(fp64a, fp64_fpxx)
+ NEXT(fpxx, fp64a_fp64)
+ NEXT(fp64, fp64a_fpxx)
+ END_STATE
+
+ START_STATE(fp64a_fp64_fpxxo)
+ NEXT(fp64a, fp64_fpxxo)
+ NEXT(fpxxo, fp64a_fp64)
+ NEXT(fp64, fp64a_fpxxo)
+ END_STATE
+
+ START_STATE(fp64a_fp64_fpxxo_fpxx)
+ NEXT(fp64a, fp64_fpxx_fpxxo)
+ NEXT(fpxx, fp64a_fp64_fpxxo)
+ NEXT(fpxxo, fp64a_fp64_fpxx)
+ NEXT(fp64, fp64a_fpxx_fpxxo)
+ END_STATE
+
+ START_STATE(fp32_fp64a_fpxx)
+ NEXT(fp32, fp64a_fpxx)
+ NEXT(fp64a, fp32_fpxx)
+ NEXT(fpxx, fp64a_fp32)
+ END_STATE
+
+ START_STATE(fp32_fp64a_fpxxo)
+ NEXT(fp32, fp64a_fpxxo)
+ NEXT(fp64a, fp32_fpxxo)
+ NEXT(fpxxo, fp64a_fp32)
+ END_STATE
+
+ START_STATE(fp32_fp64a_fpxxo_fpxx)
+ NEXT(fp32, fp64a_fpxx_fpxxo)
+ NEXT(fp64a, fp32_fpxxo_fpxx)
+ NEXT(fpxx, fp32_fp64a_fpxxo)
+ NEXT(fpxxo, fp32_fp64a_fpxx)
+ END_STATE
+ }
+
+ return true;
+}
+
+static int
+mode_transition_valid_p (void)
+{
+ int prev_fp_mode;
+
+ /* Get the current fp mode. */
+ prev_fp_mode = current_fp_mode;
+#if HAVE_PRCTL_FP_MODE
+ current_fp_mode = prctl (PR_GET_FP_MODE);
+
+ /* If the prctl call fails assume the core only has FR0 mode support. */
+ if (current_fp_mode == -1)
+ current_fp_mode = 0;
+#endif
+
+ if (!current_mode_valid_p (current_fp_state))
+ return 0;
+
+ /* Check if mode changes are not allowed but a mode change happened. */
+ if (cant_change_mode
+ && current_fp_mode != prev_fp_mode)
+ return 0;
+
+ return 1;
+}
+
+/* Load OBJ and check that it was/was not loaded correctly. */
+bool
+load_object (enum fp_obj obj)
+{
+ bool should_load = set_next_fp_state (obj);
+
+ shared_lib_ptrs[obj] = dlopen (shared_lib_names[obj], RTLD_LAZY);
+
+ /* If we expected an error and the load was successful then fail. */
+ if (!should_load && (shared_lib_ptrs[obj] != 0))
+ return false;
+
+ if (should_load && (shared_lib_ptrs[obj] == 0))
+ return false;
+
+ if (!mode_transition_valid_p ())
+ return false;
+
+ return true;
+}
+
+/* Remove an object and check the state remains valid. */
+bool
+unload_object (enum fp_obj obj)
+{
+ if (!shared_lib_ptrs[obj])
+ return true;
+
+ remove_object (obj);
+
+ if (dlclose (shared_lib_ptrs[obj]) != 0)
+ return false;
+
+ shared_lib_ptrs[obj] = 0;
+
+ if (!mode_transition_valid_p ())
+ return false;
+
+ return true;
+}
+
+/* Load every permuation of OBJECTS. */
+static bool
+test_permutations (enum fp_obj objects[], int count)
+{
+ int i;
+
+ for (i = 0 ; i < count ; i++)
+ {
+ if (!load_object (objects[i]))
+ return false;
+
+ if (count > 1)
+ {
+ enum fp_obj new_objects[count - 1];
+ int j;
+ int k = 0;
+
+ for (j = 0 ; j < count ; j++)
+ {
+ if (j != i)
+ new_objects[k++] = objects[j];
+ }
+
+ if (!test_permutations (new_objects, count - 1))
+ return false;
+ }
+
+ if (!unload_object (objects[i]))
+ return false;
+ }
+ return true;
+}
+
+int
+do_test (void)
+{
+#if HAVE_PRCTL_FP_MODE
+ /* Determine available hardware support and current mode. */
+ current_fp_mode = prctl (PR_GET_FP_MODE);
+
+ /* If the prctl call fails assume the core only has FR0 mode support. */
+ if (current_fp_mode == -1)
+ current_fp_mode = 0;
+ else
+ {
+ if (prctl (PR_SET_FP_MODE, 0) != 0)
+ {
+ if (errno == ENOTSUP)
+ is_r6 = true;
+ else
+ {
+ printf ("unexpected error from PR_SET_FP_MODE, 0: %m\n");
+ return 1;
+ }
+ }
+
+ if (prctl (PR_SET_FP_MODE, PR_FP_MODE_FR) != 0)
+ {
+ if (errno != ENOTSUP)
+ {
+ printf ("unexpected error from PR_SET_FP_MODE, "
+ "PR_FP_MODE_FR: %m\n");
+ return 1;
+ }
+ }
+ else
+ has_fr1 = true;
+
+ if (prctl (PR_SET_FP_MODE, PR_FP_MODE_FR | PR_FP_MODE_FRE) != 0)
+ {
+ if (errno != ENOTSUP)
+ {
+ printf ("unexpected error from PR_SET_FP_MODE, "
+ "PR_FP_MODE_FR | PR_FP_MODE_FRE: %m\n");
+ return 1;
+ }
+ }
+ else
+ has_fre = true;
+
+ if (prctl (PR_SET_FP_MODE, current_fp_mode) != 0)
+ {
+ printf ("unable to restore initial FP mode: %m\n");
+ return 1;
+ }
+ }
+
+ if ((is_r6 && !(current_fp_mode & PR_FP_MODE_FR))
+ || (!has_fr1 && (current_fp_mode & PR_FP_MODE_FR))
+ || (!has_fre && (current_fp_mode & PR_FP_MODE_FRE)))
+ {
+ puts ("Inconsistency detected between initial FP mode "
+ "and supported FP modes\n");
+ return 1;
+ }
+#else
+ current_fp_mode = 0;
+#endif
+
+ /* Set up the initial state from executable and LDSO. Assumptions:
+ 1) All system libraries have the same ABI as ld.so.
+ 2) Due to the fact that ld.so is tested by invoking it directly
+ rather than via an interpreter, there is no point in varying
+ the ABI of the test program. Instead the ABI only varies for
+ the shared libraries which get loaded. */
+ if (!set_next_fp_state (FPABI_NATIVE))
+ {
+ puts ("Unable to enter initial ABI state\n");
+ return 1;
+ }
+
+ /* Compare the computed state with the hardware state. */
+ if (!mode_transition_valid_p ())
+ return 1;
+
+ /* Run all possible test permutations. */
+ if (!test_permutations (test_objects, FPABI_COUNT))
+ {
+ puts ("Mode checks failed\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../../test-skeleton.c"
diff --git a/sysdeps/mips/tst-audit.h b/sysdeps/mips/tst-audit.h
new file mode 100644
index 0000000000..32ad4d1204
--- /dev/null
+++ b/sysdeps/mips/tst-audit.h
@@ -0,0 +1,39 @@
+/* Definitions for testing PLT entry/exit auditing. ARM version.
+
+ Copyright (C) 2005-2015 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sgidefs.h>
+
+#if _MIPS_SIM == _ABIO32
+#define pltenter la_mips_o32_gnu_pltenter
+#define pltexit la_mips_o32_gnu_pltexit
+#define La_regs La_mips_32_regs
+#define La_retval La_mips_32_retval
+#else
+#if _MIPS_SIM == _ABIN32
+#define pltenter la_mips_n32_gnu_pltenter
+#define pltexit la_mips_n32_gnu_pltexit
+#else
+#define pltenter la_mips_n64_gnu_pltenter
+#define pltexit la_mips_n64_gnu_pltexit
+#endif
+#define La_regs La_mips_64_regs
+#define La_retval La_mips_64_retval
+#endif
+#define int_retval lrv_v0
diff --git a/sysdeps/mips/tst-mode-switch-1.c b/sysdeps/mips/tst-mode-switch-1.c
new file mode 100644
index 0000000000..71ea2d1b00
--- /dev/null
+++ b/sysdeps/mips/tst-mode-switch-1.c
@@ -0,0 +1,123 @@
+/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/prctl.h>
+
+#if __mips_fpr != 0 || _MIPS_SPFPSET != 16
+# error This test requires -mfpxx -mno-odd-spreg
+#endif
+
+/* This test verifies that mode changes do not clobber register state
+ in other threads. */
+
+static volatile int finished;
+static int mode[6] =
+ {
+ 0,
+ PR_FP_MODE_FR,
+ PR_FP_MODE_FR | PR_FP_MODE_FRE,
+ PR_FP_MODE_FR,
+ 0,
+ PR_FP_MODE_FR | PR_FP_MODE_FRE
+ };
+
+static void *
+thread_function (void * arg __attribute__ ((unused)))
+{
+ volatile int i = 0;
+ volatile float f = 0.0;
+ volatile double d = 0.0;
+
+ while (!finished)
+ {
+ if ((float) i != f || (double) i != d)
+ {
+ printf ("unexpected value: i(%d) f(%f) d(%f)\n", i, f, d);
+ exit (1);
+ }
+
+ if (i == 100)
+ {
+ i = 0;
+ f = 0.0;
+ d = 0.0;
+ }
+
+ i++;
+ f++;
+ d++;
+ }
+ return NULL;
+}
+
+int
+main (void)
+{
+ int count = sysconf (_SC_NPROCESSORS_ONLN);
+ if (count <= 0)
+ count = 1;
+ count *= 4;
+
+ pthread_t th[count];
+ int i;
+ int result = 0;
+
+ for (i = 0; i < count; ++i)
+ if (pthread_create (&th[i], NULL, thread_function, 0) != 0)
+ {
+ printf ("creation of thread %d failed\n", i);
+ exit (1);
+ }
+
+ for (i = 0 ; i < 1000000 ; i++)
+ {
+ if (prctl (PR_SET_FP_MODE, mode[i % 6]) != 0
+ && errno != ENOTSUP)
+ {
+ printf ("prctl PR_SET_FP_MODE failed: %m\n");
+ exit (1);
+ }
+ }
+
+ finished = 1;
+
+ for (i = 0; i < count; ++i)
+ {
+ void *v;
+ if (pthread_join (th[i], &v) != 0)
+ {
+ printf ("join of thread %d failed\n", i);
+ result = 1;
+ }
+ else if (v != NULL)
+ {
+ printf ("join %d successful, but child failed\n", i);
+ result = 1;
+ }
+ else
+ printf ("join %d successful\n", i);
+ }
+
+ return result;
+}
diff --git a/sysdeps/mips/tst-mode-switch-2.c b/sysdeps/mips/tst-mode-switch-2.c
new file mode 100644
index 0000000000..3f731e13a1
--- /dev/null
+++ b/sysdeps/mips/tst-mode-switch-2.c
@@ -0,0 +1,163 @@
+/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <pthread.h>
+#include <sys/prctl.h>
+
+#if __mips_fpr != 0 || _MIPS_SPFPSET != 16
+# error This test requires -mfpxx -mno-odd-spreg
+#endif
+
+/* This test verifies that all threads in a process see a mode
+ change when any thread causes a mode change. */
+
+static int mode[6] =
+ {
+ 0,
+ PR_FP_MODE_FR,
+ PR_FP_MODE_FR | PR_FP_MODE_FRE,
+ PR_FP_MODE_FR,
+ 0,
+ PR_FP_MODE_FR | PR_FP_MODE_FRE
+ };
+static volatile int current_mode;
+static volatile int finished;
+static pthread_barrier_t barr_ready;
+static pthread_barrier_t barr_cont;
+
+static void *
+thread_function (void * arg __attribute__ ((unused)))
+{
+ while (!finished)
+ {
+ int res = pthread_barrier_wait (&barr_ready);
+
+ if (res != 0 && res != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("barrier wait failed: %m\n");
+ exit (1);
+ }
+
+ int mode = prctl (PR_GET_FP_MODE);
+
+ if (mode != current_mode)
+ {
+ printf ("unexpected mode: %d != %d\n", mode, current_mode);
+ exit (1);
+ }
+
+ res = pthread_barrier_wait (&barr_cont);
+
+ if (res != 0 && res != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("barrier wait failed: %m\n");
+ exit (1);
+ }
+ }
+ return NULL;
+}
+
+int
+main (void)
+{
+ int count = sysconf (_SC_NPROCESSORS_ONLN);
+ if (count <= 0)
+ count = 1;
+ count *= 4;
+
+ pthread_t th[count];
+ int i;
+ int result = 0;
+
+ if (pthread_barrier_init (&barr_ready, NULL, count + 1) != 0)
+ {
+ printf ("failed to initialize barrier: %m\n");
+ exit (1);
+ }
+
+ if (pthread_barrier_init (&barr_cont, NULL, count + 1) != 0)
+ {
+ printf ("failed to initialize barrier: %m\n");
+ exit (1);
+ }
+
+ for (i = 0; i < count; ++i)
+ if (pthread_create (&th[i], NULL, thread_function, 0) != 0)
+ {
+ printf ("creation of thread %d failed\n", i);
+ exit (1);
+ }
+
+ for (i = 0 ; i < 7 ; i++)
+ {
+ if (prctl (PR_SET_FP_MODE, mode[i % 6]) != 0)
+ {
+ if (errno != ENOTSUP)
+ {
+ printf ("prctl PR_SET_FP_MODE failed: %m");
+ exit (1);
+ }
+ }
+ else
+ current_mode = mode[i % 6];
+
+
+ int res = pthread_barrier_wait (&barr_ready);
+
+ if (res != 0 && res != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("barrier wait failed: %m\n");
+ exit (1);
+ }
+
+ if (i == 6)
+ finished = 1;
+
+ res = pthread_barrier_wait (&barr_cont);
+
+ if (res != 0 && res != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("barrier wait failed: %m\n");
+ exit (1);
+ }
+ }
+
+ for (i = 0; i < count; ++i)
+ {
+ void *v;
+ if (pthread_join (th[i], &v) != 0)
+ {
+ printf ("join of thread %d failed\n", i);
+ result = 1;
+ }
+ else if (v != NULL)
+ {
+ printf ("join %d successful, but child failed\n", i);
+ result = 1;
+ }
+ else
+ printf ("join %d successful\n", i);
+ }
+
+ return result;
+}
diff --git a/sysdeps/mips/tst-mode-switch-3.c b/sysdeps/mips/tst-mode-switch-3.c
new file mode 100644
index 0000000000..9bc08f7327
--- /dev/null
+++ b/sysdeps/mips/tst-mode-switch-3.c
@@ -0,0 +1,90 @@
+/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <sys/prctl.h>
+
+#if __mips_fpr != 0 || _MIPS_SPFPSET != 16
+# error This test requires -mfpxx -mno-odd-spreg
+#endif
+
+/* This test verifies that mode changes between a setjmp and longjmp do
+ not corrupt the state of callee-saved registers. */
+
+static int mode[6] =
+ {
+ 0,
+ PR_FP_MODE_FR,
+ PR_FP_MODE_FR | PR_FP_MODE_FRE,
+ PR_FP_MODE_FR,
+ 0,
+ PR_FP_MODE_FR | PR_FP_MODE_FRE
+ };
+static jmp_buf env;
+float check1 = 2.0;
+double check2 = 3.0;
+
+int
+main (void)
+{
+ int i;
+ int result = 0;
+
+ for (i = 0 ; i < 7 ; i++)
+ {
+ int retval;
+ register float test1 __asm ("$f20");
+ register double test2 __asm ("$f22");
+
+ /* Hide what we are doing to $f20 and $f22 from the compiler. */
+ __asm __volatile ("l.s %0,%2\n"
+ "l.d %1,%3\n"
+ : "=f" (test1), "=f" (test2)
+ : "m" (check1), "m" (check2));
+
+ retval = setjmp (env);
+
+ /* Make sure the compiler knows we want to access the variables
+ via the named registers again. */
+ __asm __volatile ("" : : "f" (test1), "f" (test2));
+
+ if (test1 != check1 || test2 != check2)
+ {
+ printf ("Corrupt register detected: $20 %f = %f, $22 %f = %f\n",
+ test1, check1, test2, check2);
+ result = 1;
+ }
+
+ if (retval == 0)
+ {
+ if (prctl (PR_SET_FP_MODE, mode[i % 6]) != 0
+ && errno != ENOTSUP)
+ {
+ printf ("prctl PR_SET_FP_MODE failed: %m");
+ exit (1);
+ }
+ longjmp (env, 0);
+ }
+ }
+
+ return result;
+}