From d37bfe1da239541b2a77aa7d7b7ab0e220bfef91 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 28 Nov 2014 08:47:39 +0000 Subject: [PATCH] * libc/include/machine/setjmp.h [__mips__]: Remove __mips_fpr == 64 from the 64-bit _JBTYPE definition. * libc/machine/mips/setjmp.S: Re-work the o32 FP64 support to match the now one-and-only supported o32 FP64 ABI extension. Also support o32 FPXX. --- newlib/ChangeLog | 8 +++++ newlib/libc/include/machine/setjmp.h | 2 +- newlib/libc/machine/mips/setjmp.S | 46 +++++++++++++++++++++++++--- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/newlib/ChangeLog b/newlib/ChangeLog index 159f7fa02..cf69c05ad 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,11 @@ +2014-11-28 Matthew Fortune + + * libc/include/machine/setjmp.h [__mips__]: Remove __mips_fpr == 64 + from the 64-bit _JBTYPE definition. + * libc/machine/mips/setjmp.S: Re-work the o32 FP64 support to match + the now one-and-only supported o32 FP64 ABI extension. Also + support o32 FPXX. + 2014-11-26 Hale Wang * libc/machine/arm/strcmp-armv6m.S: New file. diff --git a/newlib/libc/include/machine/setjmp.h b/newlib/libc/include/machine/setjmp.h index 63fee0160..596e64bdb 100644 --- a/newlib/libc/include/machine/setjmp.h +++ b/newlib/libc/include/machine/setjmp.h @@ -111,7 +111,7 @@ _BEGIN_STD_C #endif #ifdef __mips__ -# if defined(__mips64) || (__mips_fpr == 64) +# if defined(__mips64) # define _JBTYPE long long # endif # ifdef __mips_soft_float diff --git a/newlib/libc/machine/mips/setjmp.S b/newlib/libc/machine/mips/setjmp.S index 4a9347126..9a8b31d09 100644 --- a/newlib/libc/machine/mips/setjmp.S +++ b/newlib/libc/machine/mips/setjmp.S @@ -41,6 +41,43 @@ FPR_OFFSET ($f29, 5); \ FPR_OFFSET ($f30, 6); \ FPR_OFFSET ($f31, 7); +#elif __mips_fpr == 0 || __mips_fpr == 64 + +/* This deals with the o32 FPXX and FP64 cases. Here we must use + SDC1 and LDC1 to access the FPRs. These instructions require + 8-byte aligned addresses. + Unfortunately, the MIPS jmp_buf only guarantees 4-byte alignment + and this cannot be increased without breaking compatibility with + pre-existing objects built against newlib. There are 11 GPRS + saved in the jmp_buf so a buffer that happens to be 8-byte aligned + ends up leaving the FPR slots 4-byte aligned and an (only) 4-byte + aligned buffer leads to the FPR slots being 8-byte aligned! + + To resolve this, we move the location of $31 to the last slot + in the jmp_buf when the overall buffer is 8-byte aligned. $31 + is simply loaded/stored twice to avoid adding complexity to the + GPR_LAYOUT macro above as well as FPR_LAYOUT. + + The location of the last slot is index 22 which is calculated + from there being 11 GPRs saved and then 12 FPRs saved so the + index of the last FPR is 11+11. + + The base of the jmp_buf is modified in $4 to allow the + FPR_OFFSET macros to just use the usual constant slot numbers + regardless of whether the realignment happened or not. */ + +#define FPR_LAYOUT \ + and $8, $4, 4; \ + bne $8, $0, 1f; \ + GPR_OFFSET ($31, 22); \ + addiu $4, $4, -4; \ +1: \ + FPR_OFFSET ($f20, 0); \ + FPR_OFFSET ($f22, 2); \ + FPR_OFFSET ($f24, 4); \ + FPR_OFFSET ($f26, 6); \ + FPR_OFFSET ($f28, 8); \ + FPR_OFFSET ($f30, 10); #else /* Assuming _MIPS_SIM == _ABIO32 */ #define FPR_LAYOUT \ FPR_OFFSET ($f20, 0); \ @@ -69,12 +106,11 @@ #else #define LOAD_GPR lw #define STORE_GPR sw -#if __mips_fpr == 64 -#define BYTES_PER_WORD 8 -#define LOAD_FPR l.d -#define STORE_FPR s.d -#else #define BYTES_PER_WORD 4 +#if __mips_fpr == 0 || __mips_fpr == 64 +#define LOAD_FPR ldc1 +#define STORE_FPR sdc1 +#else #define LOAD_FPR lwc1 #define STORE_FPR swc1 #endif