From 14489df432f77df0e6f4490dff6878d1138fb226 Mon Sep 17 00:00:00 2001 From: Matthew Fortune Date: Thu, 13 Nov 2014 17:00:08 +0000 Subject: [PATCH 1/3] Re-work setjmp/longjmp to match o32 FPXX and FP64 ABI definitions newlib/ * 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/libc/include/machine/setjmp.h | 2 +- newlib/libc/machine/mips/setjmp.S | 46 ++++++++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/newlib/libc/include/machine/setjmp.h b/newlib/libc/include/machine/setjmp.h index 63fee01..596e64b 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 4a93471..9a8b31d 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 -- 1.9.4