From 5a92dd95c77cee81755f1a441ae0b71e3ae2bcdb Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 25 Jan 2016 13:20:52 +0100 Subject: [PATCH] add powerpc soft-float support Some PowerPC CPUs (e.g. Freescale MPC85xx) have a completely different instruction set for floating point operations (SPE). Executing regular PowerPC floating point instructions results in "Illegal instruction" errors. Make it possible to run these devices in soft-float mode. --- arch/powerpc/bits/fenv.h | 5 +++ arch/powerpc/reloc.h | 8 +++- configure | 4 ++ src/fenv/powerpc/fenv-sf.c | 3 ++ src/fenv/powerpc/{fenv.s => fenv.S} | 42 ++++++++++++--------- src/setjmp/powerpc/{longjmp.s => longjmp.S} | 24 +++++++----- src/setjmp/powerpc/{setjmp.s => setjmp.S} | 14 ++++--- 7 files changed, 65 insertions(+), 35 deletions(-) create mode 100644 src/fenv/powerpc/fenv-sf.c rename src/fenv/powerpc/{fenv.s => fenv.S} (68%) rename src/setjmp/powerpc/{longjmp.s => longjmp.S} (63%) rename src/setjmp/powerpc/{setjmp.s => setjmp.S} (79%) diff --git a/arch/powerpc/bits/fenv.h b/arch/powerpc/bits/fenv.h index 2f722e6b..c5a3e5c5 100644 --- a/arch/powerpc/bits/fenv.h +++ b/arch/powerpc/bits/fenv.h @@ -1,3 +1,7 @@ +#ifdef _SOFT_FLOAT +#define FE_ALL_EXCEPT 0 +#define FE_TONEAREST 0 +#else #define FE_TONEAREST 0 #define FE_TOWARDZERO 1 #define FE_UPWARD 2 @@ -24,6 +28,7 @@ #define FE_ALL_INVALID 0x01f80700 #endif +#endif typedef unsigned fexcept_t; typedef double fenv_t; diff --git a/arch/powerpc/reloc.h b/arch/powerpc/reloc.h index b8b6589f..1b4cab36 100644 --- a/arch/powerpc/reloc.h +++ b/arch/powerpc/reloc.h @@ -1,4 +1,10 @@ -#define LDSO_ARCH "powerpc" +#ifdef _SOFT_FLOAT +#define FP_SUFFIX "-sf" +#else +#define FP_SUFFIX "" +#endif + +#define LDSO_ARCH "powerpc" FP_SUFFIX #define TPOFF_K (-0x7000) diff --git a/configure b/configure index 89e0d177..9c0762c9 100755 --- a/configure +++ b/configure @@ -621,6 +621,10 @@ trycppif "_MIPSEL || __MIPSEL || __MIPSEL__" "$t" && SUBARCH=${SUBARCH}el trycppif __mips_soft_float "$t" && SUBARCH=${SUBARCH}-sf fi +if test "$ARCH" = "powerpc" ; then +trycppif _SOFT_FLOAT "$t" && SUBARCH=${SUBARCH}-sf +fi + test "$ARCH" = "microblaze" && trycppif __MICROBLAZEEL__ "$t" \ && SUBARCH=${SUBARCH}el diff --git a/src/fenv/powerpc/fenv-sf.c b/src/fenv/powerpc/fenv-sf.c new file mode 100644 index 00000000..85bef40f --- /dev/null +++ b/src/fenv/powerpc/fenv-sf.c @@ -0,0 +1,3 @@ +#ifdef _SOFT_FLOAT +#include "../fenv.c" +#endif diff --git a/src/fenv/powerpc/fenv.s b/src/fenv/powerpc/fenv.S similarity index 68% rename from src/fenv/powerpc/fenv.s rename to src/fenv/powerpc/fenv.S index e34a9990..1516eb5c 100644 --- a/src/fenv/powerpc/fenv.s +++ b/src/fenv/powerpc/fenv.S @@ -1,18 +1,21 @@ +#ifndef _SOFT_FLOAT .global feclearexcept .type feclearexcept,@function feclearexcept: andis. 3,3,0x3e00 - # if (r3 & FE_INVALID) r3 |= all_invalid_flags + /* if (r3 & FE_INVALID) r3 |= all_invalid_flags */ andis. 0,3,0x2000 stwu 1,-16(1) beq- 0,1f oris 3,3,0x01f8 ori 3,3,0x0700 1: - # note: fpscr contains various fpu status and control - # flags and we dont check if r3 may alter other flags - # than the exception related ones - # fpscr &= ~r3 + /* + * note: fpscr contains various fpu status and control + * flags and we dont check if r3 may alter other flags + * than the exception related ones + * ufpscr &= ~r3 + */ mffs 0 stfd 0,8(1) lwz 9,12(1) @@ -21,7 +24,7 @@ feclearexcept: lfd 0,8(1) mtfsf 255,0 - # return 0 + /* return 0 */ li 3,0 addi 1,1,16 blr @@ -30,13 +33,13 @@ feclearexcept: .type feraiseexcept,@function feraiseexcept: andis. 3,3,0x3e00 - # if (r3 & FE_INVALID) r3 |= software_invalid_flag + /* if (r3 & FE_INVALID) r3 |= software_invalid_flag */ andis. 0,3,0x2000 stwu 1,-16(1) beq- 0,1f ori 3,3,0x0400 1: - # fpscr |= r3 + /* fpscr |= r3 */ mffs 0 stfd 0,8(1) lwz 9,12(1) @@ -45,7 +48,7 @@ feraiseexcept: lfd 0,8(1) mtfsf 255,0 - # return 0 + /* return 0 */ li 3,0 addi 1,1,16 blr @@ -54,7 +57,7 @@ feraiseexcept: .type fetestexcept,@function fetestexcept: andis. 3,3,0x3e00 - # return r3 & fpscr + /* return r3 & fpscr */ stwu 1,-16(1) mffs 0 stfd 0,8(1) @@ -66,7 +69,7 @@ fetestexcept: .global fegetround .type fegetround,@function fegetround: - # return fpscr & 3 + /* return fpscr & 3 */ stwu 1,-16(1) mffs 0 stfd 0,8(1) @@ -78,8 +81,10 @@ fegetround: .global __fesetround .type __fesetround,@function __fesetround: - # note: invalid input is not checked, r3 < 4 must hold - # fpscr = (fpscr & -4U) | r3 + /* + * note: invalid input is not checked, r3 < 4 must hold + * fpscr = (fpscr & -4U) | r3 + */ stwu 1,-16(1) mffs 0 stfd 0,8(1) @@ -90,7 +95,7 @@ __fesetround: lfd 0,8(1) mtfsf 255,0 - # return 0 + /* return 0 */ li 3,0 addi 1,1,16 blr @@ -98,10 +103,10 @@ __fesetround: .global fegetenv .type fegetenv,@function fegetenv: - # *r3 = fpscr + /* *r3 = fpscr */ mffs 0 stfd 0,0(3) - # return 0 + /* return 0 */ li 3,0 blr @@ -115,9 +120,10 @@ fesetenv: .zero 8 2: mflr 3 mtlr 4 -1: # fpscr = *r3 +1: /* fpscr = *r3 */ lfd 0,0(3) mtfsf 255,0 - # return 0 + /* return 0 */ li 3,0 blr +#endif diff --git a/src/setjmp/powerpc/longjmp.s b/src/setjmp/powerpc/longjmp.S similarity index 63% rename from src/setjmp/powerpc/longjmp.s rename to src/setjmp/powerpc/longjmp.S index bab17511..e598bd05 100644 --- a/src/setjmp/powerpc/longjmp.s +++ b/src/setjmp/powerpc/longjmp.S @@ -4,19 +4,21 @@ .type longjmp,@function _longjmp: longjmp: -# void longjmp(jmp_buf env, int val); -# put val into return register and restore the env saved in setjmp -# if val(r4) is 0, put 1 there. - # 0) move old return address into r0 + /* + * void longjmp(jmp_buf env, int val); + * put val into return register and restore the env saved in setjmp + * if val(r4) is 0, put 1 there. + */ + /* 0) move old return address into r0 */ lwz 0, 0(3) - # 1) put it into link reg + /* 1) put it into link reg */ mtlr 0 - #2 ) restore stack ptr + /* 2 ) restore stack ptr */ lwz 1, 4(3) - #3) restore control reg + /* 3) restore control reg */ lwz 0, 8(3) mtcr 0 - #4) restore r14-r31 + /* 4) restore r14-r31 */ lwz 14, 12(3) lwz 15, 16(3) lwz 16, 20(3) @@ -35,6 +37,7 @@ longjmp: lwz 29, 72(3) lwz 30, 76(3) lwz 31, 80(3) +#ifndef _SOFT_FLOAT lfd 14,88(3) lfd 15,96(3) lfd 16,104(3) @@ -53,10 +56,11 @@ longjmp: lfd 29,208(3) lfd 30,216(3) lfd 31,224(3) - #5) put val into return reg r3 +#endif + /* 5) put val into return reg r3 */ mr 3, 4 - #6) check if return value is 0, make it 1 in that case + /* 6) check if return value is 0, make it 1 in that case */ cmpwi cr7, 4, 0 bne cr7, 1f li 3, 1 diff --git a/src/setjmp/powerpc/setjmp.s b/src/setjmp/powerpc/setjmp.S similarity index 79% rename from src/setjmp/powerpc/setjmp.s rename to src/setjmp/powerpc/setjmp.S index 122177f1..cd91a207 100644 --- a/src/setjmp/powerpc/setjmp.s +++ b/src/setjmp/powerpc/setjmp.S @@ -10,15 +10,15 @@ ___setjmp: __setjmp: _setjmp: setjmp: - # 0) store IP int 0, then into the jmpbuf pointed to by r3 (first arg) + /* 0) store IP int 0, then into the jmpbuf pointed to by r3 (first arg) */ mflr 0 stw 0, 0(3) - # 1) store reg1 (SP) + /* 1) store reg1 (SP) */ stw 1, 4(3) - # 2) store cr + /* 2) store cr */ mfcr 0 stw 0, 8(3) - # 3) store r14-31 + /* 3) store r14-31 */ stw 14, 12(3) stw 15, 16(3) stw 16, 20(3) @@ -37,6 +37,7 @@ setjmp: stw 29, 72(3) stw 30, 76(3) stw 31, 80(3) +#ifndef _SOFT_FLOAT stfd 14,88(3) stfd 15,96(3) stfd 16,104(3) @@ -55,7 +56,8 @@ setjmp: stfd 29,208(3) stfd 30,216(3) stfd 31,224(3) - # 4) set return value to 0 +#endif + /* 4) set return value to 0 */ li 3, 0 - # 5) return + /* 5) return */ blr -- 2.25.1