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.
This commit is contained in:
Felix Fietkau 2016-01-25 13:20:52 +01:00 committed by Rich Felker
parent 9543656cc3
commit 5a92dd95c7
7 changed files with 65 additions and 35 deletions

View File

@ -1,3 +1,7 @@
#ifdef _SOFT_FLOAT
#define FE_ALL_EXCEPT 0
#define FE_TONEAREST 0
#else
#define FE_TONEAREST 0 #define FE_TONEAREST 0
#define FE_TOWARDZERO 1 #define FE_TOWARDZERO 1
#define FE_UPWARD 2 #define FE_UPWARD 2
@ -24,6 +28,7 @@
#define FE_ALL_INVALID 0x01f80700 #define FE_ALL_INVALID 0x01f80700
#endif #endif
#endif
typedef unsigned fexcept_t; typedef unsigned fexcept_t;
typedef double fenv_t; typedef double fenv_t;

View File

@ -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) #define TPOFF_K (-0x7000)

4
configure vendored
View File

@ -621,6 +621,10 @@ trycppif "_MIPSEL || __MIPSEL || __MIPSEL__" "$t" && SUBARCH=${SUBARCH}el
trycppif __mips_soft_float "$t" && SUBARCH=${SUBARCH}-sf trycppif __mips_soft_float "$t" && SUBARCH=${SUBARCH}-sf
fi fi
if test "$ARCH" = "powerpc" ; then
trycppif _SOFT_FLOAT "$t" && SUBARCH=${SUBARCH}-sf
fi
test "$ARCH" = "microblaze" && trycppif __MICROBLAZEEL__ "$t" \ test "$ARCH" = "microblaze" && trycppif __MICROBLAZEEL__ "$t" \
&& SUBARCH=${SUBARCH}el && SUBARCH=${SUBARCH}el

View File

@ -0,0 +1,3 @@
#ifdef _SOFT_FLOAT
#include "../fenv.c"
#endif

View File

@ -1,18 +1,21 @@
#ifndef _SOFT_FLOAT
.global feclearexcept .global feclearexcept
.type feclearexcept,@function .type feclearexcept,@function
feclearexcept: feclearexcept:
andis. 3,3,0x3e00 andis. 3,3,0x3e00
# if (r3 & FE_INVALID) r3 |= all_invalid_flags /* if (r3 & FE_INVALID) r3 |= all_invalid_flags */
andis. 0,3,0x2000 andis. 0,3,0x2000
stwu 1,-16(1) stwu 1,-16(1)
beq- 0,1f beq- 0,1f
oris 3,3,0x01f8 oris 3,3,0x01f8
ori 3,3,0x0700 ori 3,3,0x0700
1: 1:
# note: fpscr contains various fpu status and control /*
# flags and we dont check if r3 may alter other flags * note: fpscr contains various fpu status and control
# than the exception related ones * flags and we dont check if r3 may alter other flags
# fpscr &= ~r3 * than the exception related ones
* ufpscr &= ~r3
*/
mffs 0 mffs 0
stfd 0,8(1) stfd 0,8(1)
lwz 9,12(1) lwz 9,12(1)
@ -21,7 +24,7 @@ feclearexcept:
lfd 0,8(1) lfd 0,8(1)
mtfsf 255,0 mtfsf 255,0
# return 0 /* return 0 */
li 3,0 li 3,0
addi 1,1,16 addi 1,1,16
blr blr
@ -30,13 +33,13 @@ feclearexcept:
.type feraiseexcept,@function .type feraiseexcept,@function
feraiseexcept: feraiseexcept:
andis. 3,3,0x3e00 andis. 3,3,0x3e00
# if (r3 & FE_INVALID) r3 |= software_invalid_flag /* if (r3 & FE_INVALID) r3 |= software_invalid_flag */
andis. 0,3,0x2000 andis. 0,3,0x2000
stwu 1,-16(1) stwu 1,-16(1)
beq- 0,1f beq- 0,1f
ori 3,3,0x0400 ori 3,3,0x0400
1: 1:
# fpscr |= r3 /* fpscr |= r3 */
mffs 0 mffs 0
stfd 0,8(1) stfd 0,8(1)
lwz 9,12(1) lwz 9,12(1)
@ -45,7 +48,7 @@ feraiseexcept:
lfd 0,8(1) lfd 0,8(1)
mtfsf 255,0 mtfsf 255,0
# return 0 /* return 0 */
li 3,0 li 3,0
addi 1,1,16 addi 1,1,16
blr blr
@ -54,7 +57,7 @@ feraiseexcept:
.type fetestexcept,@function .type fetestexcept,@function
fetestexcept: fetestexcept:
andis. 3,3,0x3e00 andis. 3,3,0x3e00
# return r3 & fpscr /* return r3 & fpscr */
stwu 1,-16(1) stwu 1,-16(1)
mffs 0 mffs 0
stfd 0,8(1) stfd 0,8(1)
@ -66,7 +69,7 @@ fetestexcept:
.global fegetround .global fegetround
.type fegetround,@function .type fegetround,@function
fegetround: fegetround:
# return fpscr & 3 /* return fpscr & 3 */
stwu 1,-16(1) stwu 1,-16(1)
mffs 0 mffs 0
stfd 0,8(1) stfd 0,8(1)
@ -78,8 +81,10 @@ fegetround:
.global __fesetround .global __fesetround
.type __fesetround,@function .type __fesetround,@function
__fesetround: __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) stwu 1,-16(1)
mffs 0 mffs 0
stfd 0,8(1) stfd 0,8(1)
@ -90,7 +95,7 @@ __fesetround:
lfd 0,8(1) lfd 0,8(1)
mtfsf 255,0 mtfsf 255,0
# return 0 /* return 0 */
li 3,0 li 3,0
addi 1,1,16 addi 1,1,16
blr blr
@ -98,10 +103,10 @@ __fesetround:
.global fegetenv .global fegetenv
.type fegetenv,@function .type fegetenv,@function
fegetenv: fegetenv:
# *r3 = fpscr /* *r3 = fpscr */
mffs 0 mffs 0
stfd 0,0(3) stfd 0,0(3)
# return 0 /* return 0 */
li 3,0 li 3,0
blr blr
@ -115,9 +120,10 @@ fesetenv:
.zero 8 .zero 8
2: mflr 3 2: mflr 3
mtlr 4 mtlr 4
1: # fpscr = *r3 1: /* fpscr = *r3 */
lfd 0,0(3) lfd 0,0(3)
mtfsf 255,0 mtfsf 255,0
# return 0 /* return 0 */
li 3,0 li 3,0
blr blr
#endif

View File

@ -4,19 +4,21 @@
.type longjmp,@function .type longjmp,@function
_longjmp: _longjmp:
longjmp: longjmp:
# void longjmp(jmp_buf env, int val); /*
# put val into return register and restore the env saved in setjmp * void longjmp(jmp_buf env, int val);
# if val(r4) is 0, put 1 there. * put val into return register and restore the env saved in setjmp
# 0) move old return address into r0 * if val(r4) is 0, put 1 there.
*/
/* 0) move old return address into r0 */
lwz 0, 0(3) lwz 0, 0(3)
# 1) put it into link reg /* 1) put it into link reg */
mtlr 0 mtlr 0
#2 ) restore stack ptr /* 2 ) restore stack ptr */
lwz 1, 4(3) lwz 1, 4(3)
#3) restore control reg /* 3) restore control reg */
lwz 0, 8(3) lwz 0, 8(3)
mtcr 0 mtcr 0
#4) restore r14-r31 /* 4) restore r14-r31 */
lwz 14, 12(3) lwz 14, 12(3)
lwz 15, 16(3) lwz 15, 16(3)
lwz 16, 20(3) lwz 16, 20(3)
@ -35,6 +37,7 @@ longjmp:
lwz 29, 72(3) lwz 29, 72(3)
lwz 30, 76(3) lwz 30, 76(3)
lwz 31, 80(3) lwz 31, 80(3)
#ifndef _SOFT_FLOAT
lfd 14,88(3) lfd 14,88(3)
lfd 15,96(3) lfd 15,96(3)
lfd 16,104(3) lfd 16,104(3)
@ -53,10 +56,11 @@ longjmp:
lfd 29,208(3) lfd 29,208(3)
lfd 30,216(3) lfd 30,216(3)
lfd 31,224(3) lfd 31,224(3)
#5) put val into return reg r3 #endif
/* 5) put val into return reg r3 */
mr 3, 4 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 cmpwi cr7, 4, 0
bne cr7, 1f bne cr7, 1f
li 3, 1 li 3, 1

View File

@ -10,15 +10,15 @@ ___setjmp:
__setjmp: __setjmp:
_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 mflr 0
stw 0, 0(3) stw 0, 0(3)
# 1) store reg1 (SP) /* 1) store reg1 (SP) */
stw 1, 4(3) stw 1, 4(3)
# 2) store cr /* 2) store cr */
mfcr 0 mfcr 0
stw 0, 8(3) stw 0, 8(3)
# 3) store r14-31 /* 3) store r14-31 */
stw 14, 12(3) stw 14, 12(3)
stw 15, 16(3) stw 15, 16(3)
stw 16, 20(3) stw 16, 20(3)
@ -37,6 +37,7 @@ setjmp:
stw 29, 72(3) stw 29, 72(3)
stw 30, 76(3) stw 30, 76(3)
stw 31, 80(3) stw 31, 80(3)
#ifndef _SOFT_FLOAT
stfd 14,88(3) stfd 14,88(3)
stfd 15,96(3) stfd 15,96(3)
stfd 16,104(3) stfd 16,104(3)
@ -55,7 +56,8 @@ setjmp:
stfd 29,208(3) stfd 29,208(3)
stfd 30,216(3) stfd 30,216(3)
stfd 31,224(3) stfd 31,224(3)
# 4) set return value to 0 #endif
/* 4) set return value to 0 */
li 3, 0 li 3, 0
# 5) return /* 5) return */
blr blr