summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2006-11-04 19:50:20 +0000
committerEric Andersen <andersen@codepoet.org>2006-11-04 19:50:20 +0000
commitcb12600bc59ec9211ecb5be3083e66f7c6c6d9ef (patch)
treead8ca820494baaeaada85b9d30a702d68b461936 /libc/sysdeps/linux
parent141da0f0b098b17499c6c6e02a7d2cacc1d6d3ba (diff)
mips64 patch from Atsushi Nemoto:
The mips64 N32/N64 ABI have a bit different register usage convention. Also the register size for these ABI is 8 byte. Use ld/sd for them.
Diffstat (limited to 'libc/sysdeps/linux')
-rw-r--r--libc/sysdeps/linux/mips/__longjmp.c42
-rw-r--r--libc/sysdeps/linux/mips/bits/setjmp.h10
-rw-r--r--libc/sysdeps/linux/mips/bsd-_setjmp.S7
-rw-r--r--libc/sysdeps/linux/mips/bsd-setjmp.S7
-rw-r--r--libc/sysdeps/linux/mips/setjmp.S10
-rw-r--r--libc/sysdeps/linux/mips/setjmp_aux.c36
6 files changed, 111 insertions, 1 deletions
diff --git a/libc/sysdeps/linux/mips/__longjmp.c b/libc/sysdeps/linux/mips/__longjmp.c
index ee9c455cc..9dc09f27a 100644
--- a/libc/sysdeps/linux/mips/__longjmp.c
+++ b/libc/sysdeps/linux/mips/__longjmp.c
@@ -20,6 +20,7 @@
#include <features.h>
#include <setjmp.h>
#include <stdlib.h>
+#include <sgidefs.h>
#ifndef __GNUC__
#error This file uses GNU C extensions; you must compile with GCC.
@@ -38,12 +39,23 @@ void __longjmp (__jmp_buf env, int val_arg)
/* Pull back the floating point callee-saved registers. */
#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__
+#if _MIPS_SIM == _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 /* O32 || N32 */
__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 /* O32 || N32 */
/* Get and reconstruct the floating point csr. */
__asm__ __volatile__ ("lw $2, %0" : : "m" (env[0].__fpc_csr));
@@ -51,9 +63,14 @@ void __longjmp (__jmp_buf env, int val_arg)
#endif
/* Get the GP. */
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+ __asm__ __volatile__ ("ld $gp, %0" : : "m" (env[0].__gp));
+#else /* O32 || N32 */
__asm__ __volatile__ ("lw $gp, %0" : : "m" (env[0].__gp));
+#endif /* O32 || N32 */
/* Get the callee-saved registers. */
+#if _MIPS_SIM == _MIPS_SIM_ABI32
__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]));
@@ -62,15 +79,36 @@ void __longjmp (__jmp_buf env, int val_arg)
__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]));
+#else /* N32 || N64 */
+ __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]));
+#endif /* N32 || N64 */
/* Get the PC. */
+#if _MIPS_SIM == _MIPS_SIM_ABI32
__asm__ __volatile__ ("lw $25, %0" : : "m" (env[0].__pc));
+#elif _MIPS_SIM == _MIPS_SIM_NABI32
+ __asm__ __volatile__ ("lw $31, %0" : : "m" (env[0].__pc));
+#else /* N64 */
+ __asm__ __volatile__ ("ld $31, %0" : : "m" (env[0].__pc));
+#endif /* N64 */
/* 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. */
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+ __asm__ __volatile__ ("ld $29, %0\n\t"
+ "ld $30, %1\n\t" : : "m" (env[0].__sp), "m" (env[0].__fp));
+#else /* O32 || N32 */
__asm__ __volatile__ ("lw $29, %0\n\t"
"lw $30, %1\n\t" : : "m" (env[0].__sp), "m" (env[0].__fp));
+#endif /* O32 || N32 */
/* Give setjmp 1 if given a 0, or what they gave us if non-zero. */
if (val == 0)
@@ -78,7 +116,11 @@ void __longjmp (__jmp_buf env, int val_arg)
else
__asm__ __volatile__ ("move $2, %0" : : "r" (val));
+#if _MIPS_SIM == _MIPS_SIM_ABI32
__asm__ __volatile__ ("jr $25");
+#else /* N32 || N64 */
+ __asm__ __volatile__ ("jr $31");
+#endif /* N32 || N64 */
/* Avoid `volatile function does return' warnings. */
for (;;);
diff --git a/libc/sysdeps/linux/mips/bits/setjmp.h b/libc/sysdeps/linux/mips/bits/setjmp.h
index 4eb8e9f2a..08e74fe0a 100644
--- a/libc/sysdeps/linux/mips/bits/setjmp.h
+++ b/libc/sysdeps/linux/mips/bits/setjmp.h
@@ -24,6 +24,8 @@
# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
#endif
+#include <sgidefs.h>
+
typedef struct
{
/* Program counter. */
@@ -33,7 +35,11 @@ typedef struct
void * __sp;
/* Callee-saved registers s0 through s7. */
+#if _MIPS_SIM == _MIPS_SIM_ABI32
int __regs[8];
+#else
+ long long __regs[8];
+#endif
/* The frame pointer. */
void * __fp;
@@ -45,7 +51,11 @@ typedef struct
int __fpc_csr;
/* Callee-saved floating point registers. */
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+ double __fpregs[8];
+#else /* N32 || O32 */
double __fpregs[6];
+#endif /* N32 || O32 */
} __jmp_buf[1];
#ifdef __USE_MISC
diff --git a/libc/sysdeps/linux/mips/bsd-_setjmp.S b/libc/sysdeps/linux/mips/bsd-_setjmp.S
index e03c05ced..6853dea98 100644
--- a/libc/sysdeps/linux/mips/bsd-_setjmp.S
+++ b/libc/sysdeps/linux/mips/bsd-_setjmp.S
@@ -22,6 +22,7 @@
in setjmp doesn't clobber the state restored by longjmp. */
#include <sys/regdef.h>
+#include <sys/asm.h>
#ifdef __PIC__
.option pic2
@@ -35,10 +36,16 @@
_setjmp:
#ifdef __PIC__
+#if (_MIPS_SIM == _MIPS_SIM_ABI32)
.set noreorder
.cpload t9
.set reorder
la t9, __sigsetjmp
+#else
+ .cpsetup t9, v0, _setjmp
+ PTR_LA t9, __sigsetjmp
+ .cpreturn
+#endif
#endif
move a1,zero /* Pass a second argument of zero. */
#ifdef __PIC__
diff --git a/libc/sysdeps/linux/mips/bsd-setjmp.S b/libc/sysdeps/linux/mips/bsd-setjmp.S
index 49a904d29..1f57a97e7 100644
--- a/libc/sysdeps/linux/mips/bsd-setjmp.S
+++ b/libc/sysdeps/linux/mips/bsd-setjmp.S
@@ -22,6 +22,7 @@
in setjmp doesn't clobber the state restored by longjmp. */
#include <sys/regdef.h>
+#include <sys/asm.h>
#ifdef __PIC__
.option pic2
@@ -36,9 +37,15 @@
setjmp:
.set noreorder
#ifdef __PIC__
+#if _MIPS_SIM == _MIPS_SIM_ABI32
.cpload t9
.set reorder
la t9, __sigsetjmp
+#else /* N32 */
+ .cpsetup t9, v0, setjmp
+ PTR_LA t9, __sigsetjmp
+ .cprestore
+#endif /* N32 */
#endif
li a1, 1 /* Pass a second argument of one. */
#ifdef __PIC__
diff --git a/libc/sysdeps/linux/mips/setjmp.S b/libc/sysdeps/linux/mips/setjmp.S
index 0d9a8d431..226f75524 100644
--- a/libc/sysdeps/linux/mips/setjmp.S
+++ b/libc/sysdeps/linux/mips/setjmp.S
@@ -17,6 +17,7 @@
02111-1307 USA. */
#include <sys/regdef.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
@@ -35,7 +36,11 @@
__sigsetjmp:
#ifdef __PIC__
.set noreorder
+#if _MIPS_SIM == _MIPS_SIM_ABI32
.cpload t9
+#else
+ .cpsetup t9, v0, __sigsetjmp
+#endif
.set reorder
#endif
move a2, sp
@@ -45,7 +50,10 @@ __sigsetjmp:
move a3, $fp
#endif
#ifdef __PIC__
- la t9, __sigsetjmp_aux
+ PTR_LA t9, __sigsetjmp_aux
+#if _MIPS_SIM != _MIPS_SIM_ABI32
+ .cpreturn
+#endif
jr t9
#else
j __sigsetjmp_aux
diff --git a/libc/sysdeps/linux/mips/setjmp_aux.c b/libc/sysdeps/linux/mips/setjmp_aux.c
index 166eb7eb1..7158f87a9 100644
--- a/libc/sysdeps/linux/mips/setjmp_aux.c
+++ b/libc/sysdeps/linux/mips/setjmp_aux.c
@@ -19,6 +19,8 @@
#include <features.h>
#include <setjmp.h>
+#include <sgidefs.h>
+#include <sys/asm.h>
/* This function is only called via the assembly language routine
__sigsetjmp, which arranges to pass in the stack pointer and the frame
@@ -28,20 +30,39 @@
extern int __sigjmp_save (sigjmp_buf, int);
int
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+__sigsetjmp_aux (jmp_buf env, int savemask, long sp, long fp)
+#else /* O32 || N32 */
__sigsetjmp_aux (jmp_buf env, int savemask, int sp, int fp)
+#endif /* O32 || N32 */
{
#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__
/* Store the floating point callee-saved registers... */
+#if _MIPS_SIM == _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 /* O32 || N32 */
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 /* O32 || N32 */
#endif
/* .. and the PC; */
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+ asm volatile ("sd $31, %0" : : "m" (env[0].__jmpbuf[0].__pc));
+#else
asm volatile ("sw $31, %0" : : "m" (env[0].__jmpbuf[0].__pc));
+#endif
/* .. and the stack pointer; */
env[0].__jmpbuf[0].__sp = (void *) sp;
@@ -50,9 +71,14 @@ __sigsetjmp_aux (jmp_buf env, int savemask, int sp, int fp)
env[0].__jmpbuf[0].__fp = (void *) fp;
/* .. and the GP; */
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+ asm volatile ("sd $gp, %0" : : "m" (env[0].__jmpbuf[0].__gp));
+#else
asm volatile ("sw $gp, %0" : : "m" (env[0].__jmpbuf[0].__gp));
+#endif
/* .. and the callee-saved registers; */
+#if (_MIPS_SIM == _MIPS_SIM_ABI32)
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]));
@@ -61,6 +87,16 @@ __sigsetjmp_aux (jmp_buf env, int savemask, int sp, int fp)
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]));
+#else /* N32 || N64 */
+ 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]));
+#endif /* N32 || N64 */
#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__
/* .. and finally get and reconstruct the floating point csr. */