From f5ce72dffc738d43213e566d8ae082d7428f8be9 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Mon, 15 Dec 2014 13:32:17 +0000 Subject: [PATCH] * newlib/libc/include/machine/setjmp.h: Add FPU support. * newlib/libc/machine/nds32/setjmp.S: Add FPU support. --- newlib/ChangeLog | 5 ++ newlib/libc/include/machine/setjmp.h | 13 ++++- newlib/libc/machine/nds32/setjmp.S | 82 +++++++++++++++++++++++++++- 3 files changed, 95 insertions(+), 5 deletions(-) diff --git a/newlib/ChangeLog b/newlib/ChangeLog index 802945ba9..526a66de2 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,8 @@ +2014-12-15 Nick Hung + + * newlib/libc/include/machine/setjmp.h: Add FPU support. + * newlib/libc/machine/nds32/setjmp.S: Add FPU support. + 2014-12-15 Nick Hung * configure.host: Add libm nds32 machine directory. diff --git a/newlib/libc/include/machine/setjmp.h b/newlib/libc/include/machine/setjmp.h index a9e0d7141..f7e5865ab 100644 --- a/newlib/libc/include/machine/setjmp.h +++ b/newlib/libc/include/machine/setjmp.h @@ -61,11 +61,18 @@ _BEGIN_STD_C #endif #ifdef __nds32__ -/* Only 17 words are currently needed. - Preserve one word slot if we need to expand. - Check newlib/libc/machine/nds32/setjmp.S for more information. */ +/* 17 words for GPRs, + 1 word for $fpcfg.freg and 30 words for FPUs + Reserved 2 words for aligement-adjustment. When storeing double-precision + floating-point register into memory, the address has to be + double-word-aligned. + Check libc/machine/nds32/setjmp.S for more information. */ +#if __NDS32_EXT_FPU_SP__ || __NDS32_EXT_FPU_DP__ +#define _JBLEN 50 +#else #define _JBLEN 18 #endif +#endif #if defined(__Z8001__) || defined(__Z8002__) /* 16 regs + pc */ diff --git a/newlib/libc/machine/nds32/setjmp.S b/newlib/libc/machine/nds32/setjmp.S index e5d8531bc..7197c86f3 100644 --- a/newlib/libc/machine/nds32/setjmp.S +++ b/newlib/libc/machine/nds32/setjmp.S @@ -51,7 +51,7 @@ The $r16 ~ $r19 are used to store D0/D1, keep them for backward-compatible. .global setjmp .type setjmp, @function setjmp: -#ifdef __NDS32_REDUCED_REGS__ +#if __NDS32_REDUCED_REGS__ smw.bim $r6, [$r0], $r10, #0b0000 addi $r0, $r0, #32 /* Leave room to keep jum_buf all the same. */ smw.bim $r31, [$r0], $r31, #0b1111 @@ -60,6 +60,46 @@ setjmp: smw.bim $r16, [$r0], $r19, #0b1111 #endif +#if __NDS32_EXT_FPU_SP__ || __NDS32_EXT_FPU_DP__ + + /* Extract $fpcfg.freg (b[3:2]), then save into jmp_buf. */ + fmfcfg $r2 + slli $r2, $r2, #28 + srli $r2, $r2, #30 + swi.bi $r2, [$r0], #4 + + /* Make sure $r0 is double-word-aligned. */ + addi $r0, $r0, #7 + bitci $r0, $r0, #7 + + /* Case switch according to $fpcfg.freg */ + beqz $r2, .LCFG0_save /* Branch if $fpcfg.freg = 0b00. */ + xori $r15, $r2, #0b10 + beqz $r15, .LCFG2_save /* Branch $fpcfg.freg = 0b10. */ + srli $r2, $r2, #0b01 + beqz $r2, .LCFG1_save /* Branch if $fpcfg.freg = 0b01. */ + /* Fall-through if $fpcfg.freg = 0b11. */ +.LCFG3_save: + fsdi.bi $fd31, [$r0], #8 + fsdi.bi $fd29, [$r0], #8 + fsdi.bi $fd27, [$r0], #8 + fsdi.bi $fd25, [$r0], #8 + fsdi.bi $fd23, [$r0], #8 + fsdi.bi $fd21, [$r0], #8 + fsdi.bi $fd19, [$r0], #8 + fsdi.bi $fd17, [$r0], #8 +.LCFG2_save: + fsdi.bi $fd15, [$r0], #8 + fsdi.bi $fd13, [$r0], #8 + fsdi.bi $fd11, [$r0], #8 + fsdi.bi $fd9, [$r0], #8 +.LCFG1_save: + fsdi.bi $fd7, [$r0], #8 + fsdi.bi $fd5, [$r0], #8 +.LCFG0_save: + fsdi.bi $fd3, [$r0], #8 +#endif + /* Set return value to zero. */ movi $r0, 0 ret @@ -72,7 +112,7 @@ setjmp: .global longjmp .type longjmp, @function longjmp: -#ifdef __NDS32_REDUCED_REGS__ +#if __NDS32_REDUCED_REGS__ lmw.bim $r6, [$r0], $r10, #0b0000 addi $r0, $r0, #32 lmw.bim $r31, [$r0], $r31, #0b1111 @@ -80,6 +120,44 @@ longjmp: lmw.bim $r6, [$r0], $r14, #0b0000 lmw.bim $r16, [$r0], $r19, #0b1111 #endif + +#if __NDS32_EXT_FPU_SP__ || __NDS32_EXT_FPU_DP__ + + /* Restore value of $fpcfg.freg (b[3:2]). */ + lwi.bi $r2, [$r0], #4 + + /* Make sure $r0 is double-word-aligned. */ + addi $r0, $r0, #7 + bitci $r0, $r0, #7 + + /* Case switch according to $fpcfg.freg */ + beqz $r2, .LCFG0_restore /* Branch if $fpcfg.freg = 0b00. */ + xori $r15, $r2, #0b10 + beqz $r15, .LCFG2_restore /* Branch $fpcfg.freg = 0b10. */ + srli $r2, $r2, #0b01 + beqz $r2, .LCFG1_restore /* Branch if $fpcfg.freg = 0b01. */ + /* Fall-through if $fpcfg.freg = 0b11. */ +.LCFG3_restore: + fldi.bi $fd31, [$r0], #8 + fldi.bi $fd29, [$r0], #8 + fldi.bi $fd27, [$r0], #8 + fldi.bi $fd25, [$r0], #8 + fldi.bi $fd23, [$r0], #8 + fldi.bi $fd21, [$r0], #8 + fldi.bi $fd19, [$r0], #8 + fldi.bi $fd17, [$r0], #8 +.LCFG2_restore: + fldi.bi $fd15, [$r0], #8 + fldi.bi $fd13, [$r0], #8 + fldi.bi $fd11, [$r0], #8 + fldi.bi $fd9, [$r0], #8 +.LCFG1_restore: + fldi.bi $fd7, [$r0], #8 + fldi.bi $fd5, [$r0], #8 +.LCFG0_restore: + fldi.bi $fd3, [$r0], #8 +#endif + /* Set val as return value. If the value val is 0, 1 will be returned instead. */ movi $r0, 1