123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594 |
- From: Felix Fietkau <[email protected]>
- Date: Wed, 8 Jul 2015 13:56:37 +0200
- 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.
- Signed-off-by: Felix Fietkau <[email protected]>
- ---
- create mode 100644 src/fenv/powerpc/fenv-sf.c
- --- 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;
- --- 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)
-
- --- a/configure
- +++ b/configure
- @@ -604,6 +604,10 @@ trycppif "_MIPSEL || __MIPSEL || __MIPSE
- 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
-
- --- /dev/null
- +++ b/src/fenv/powerpc/fenv-sf.c
- @@ -0,0 +1,3 @@
- +#ifdef _SOFT_FLOAT
- +#include "../fenv.c"
- +#endif
- --- /dev/null
- +++ b/src/fenv/powerpc/fenv.S
- @@ -0,0 +1,129 @@
- +#ifndef _SOFT_FLOAT
- +.global feclearexcept
- +.type feclearexcept,@function
- +feclearexcept:
- + andis. 3,3,0x3e00
- + /* 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
- + * ufpscr &= ~r3
- + */
- + mffs 0
- + stfd 0,8(1)
- + lwz 9,12(1)
- + andc 9,9,3
- + stw 9,12(1)
- + lfd 0,8(1)
- + mtfsf 255,0
- +
- + /* return 0 */
- + li 3,0
- + addi 1,1,16
- + blr
- +
- +.global feraiseexcept
- +.type feraiseexcept,@function
- +feraiseexcept:
- + andis. 3,3,0x3e00
- + /* 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 */
- + mffs 0
- + stfd 0,8(1)
- + lwz 9,12(1)
- + or 9,9,3
- + stw 9,12(1)
- + lfd 0,8(1)
- + mtfsf 255,0
- +
- + /* return 0 */
- + li 3,0
- + addi 1,1,16
- + blr
- +
- +.global fetestexcept
- +.type fetestexcept,@function
- +fetestexcept:
- + andis. 3,3,0x3e00
- + /* return r3 & fpscr */
- + stwu 1,-16(1)
- + mffs 0
- + stfd 0,8(1)
- + lwz 9,12(1)
- + addi 1,1,16
- + and 3,3,9
- + blr
- +
- +.global fegetround
- +.type fegetround,@function
- +fegetround:
- + /* return fpscr & 3 */
- + stwu 1,-16(1)
- + mffs 0
- + stfd 0,8(1)
- + lwz 3,12(1)
- + addi 1,1,16
- + clrlwi 3,3,30
- + blr
- +
- +.global __fesetround
- +.type __fesetround,@function
- +__fesetround:
- + /*
- + * note: invalid input is not checked, r3 < 4 must hold
- + * fpscr = (fpscr & -4U) | r3
- + */
- + stwu 1,-16(1)
- + mffs 0
- + stfd 0,8(1)
- + lwz 9,12(1)
- + clrrwi 9,9,2
- + or 9,9,3
- + stw 9,12(1)
- + lfd 0,8(1)
- + mtfsf 255,0
- +
- + /* return 0 */
- + li 3,0
- + addi 1,1,16
- + blr
- +
- +.global fegetenv
- +.type fegetenv,@function
- +fegetenv:
- + /* *r3 = fpscr */
- + mffs 0
- + stfd 0,0(3)
- + /* return 0 */
- + li 3,0
- + blr
- +
- +.global fesetenv
- +.type fesetenv,@function
- +fesetenv:
- + cmpwi 3, -1
- + bne 1f
- + mflr 4
- + bl 2f
- + .zero 8
- +2: mflr 3
- + mtlr 4
- +1: /* fpscr = *r3 */
- + lfd 0,0(3)
- + mtfsf 255,0
- + /* return 0 */
- + li 3,0
- + blr
- +#endif
- --- a/src/fenv/powerpc/fenv.s
- +++ /dev/null
- @@ -1,123 +0,0 @@
- -.global feclearexcept
- -.type feclearexcept,@function
- -feclearexcept:
- - andis. 3,3,0x3e00
- - # 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
- - mffs 0
- - stfd 0,8(1)
- - lwz 9,12(1)
- - andc 9,9,3
- - stw 9,12(1)
- - lfd 0,8(1)
- - mtfsf 255,0
- -
- - # return 0
- - li 3,0
- - addi 1,1,16
- - blr
- -
- -.global feraiseexcept
- -.type feraiseexcept,@function
- -feraiseexcept:
- - andis. 3,3,0x3e00
- - # 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
- - mffs 0
- - stfd 0,8(1)
- - lwz 9,12(1)
- - or 9,9,3
- - stw 9,12(1)
- - lfd 0,8(1)
- - mtfsf 255,0
- -
- - # return 0
- - li 3,0
- - addi 1,1,16
- - blr
- -
- -.global fetestexcept
- -.type fetestexcept,@function
- -fetestexcept:
- - andis. 3,3,0x3e00
- - # return r3 & fpscr
- - stwu 1,-16(1)
- - mffs 0
- - stfd 0,8(1)
- - lwz 9,12(1)
- - addi 1,1,16
- - and 3,3,9
- - blr
- -
- -.global fegetround
- -.type fegetround,@function
- -fegetround:
- - # return fpscr & 3
- - stwu 1,-16(1)
- - mffs 0
- - stfd 0,8(1)
- - lwz 3,12(1)
- - addi 1,1,16
- - clrlwi 3,3,30
- - blr
- -
- -.global __fesetround
- -.type __fesetround,@function
- -__fesetround:
- - # note: invalid input is not checked, r3 < 4 must hold
- - # fpscr = (fpscr & -4U) | r3
- - stwu 1,-16(1)
- - mffs 0
- - stfd 0,8(1)
- - lwz 9,12(1)
- - clrrwi 9,9,2
- - or 9,9,3
- - stw 9,12(1)
- - lfd 0,8(1)
- - mtfsf 255,0
- -
- - # return 0
- - li 3,0
- - addi 1,1,16
- - blr
- -
- -.global fegetenv
- -.type fegetenv,@function
- -fegetenv:
- - # *r3 = fpscr
- - mffs 0
- - stfd 0,0(3)
- - # return 0
- - li 3,0
- - blr
- -
- -.global fesetenv
- -.type fesetenv,@function
- -fesetenv:
- - cmpwi 3, -1
- - bne 1f
- - mflr 4
- - bl 2f
- - .zero 8
- -2: mflr 3
- - mtlr 4
- -1: # fpscr = *r3
- - lfd 0,0(3)
- - mtfsf 255,0
- - # return 0
- - li 3,0
- - blr
- --- /dev/null
- +++ b/src/setjmp/powerpc/longjmp.S
- @@ -0,0 +1,69 @@
- + .global _longjmp
- + .global longjmp
- + .type _longjmp,@function
- + .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 */
- + lwz 0, 0(3)
- + /* 1) put it into link reg */
- + mtlr 0
- + /* 2 ) restore stack ptr */
- + lwz 1, 4(3)
- + /* 3) restore control reg */
- + lwz 0, 8(3)
- + mtcr 0
- + /* 4) restore r14-r31 */
- + lwz 14, 12(3)
- + lwz 15, 16(3)
- + lwz 16, 20(3)
- + lwz 17, 24(3)
- + lwz 18, 28(3)
- + lwz 19, 32(3)
- + lwz 20, 36(3)
- + lwz 21, 40(3)
- + lwz 22, 44(3)
- + lwz 23, 48(3)
- + lwz 24, 52(3)
- + lwz 25, 56(3)
- + lwz 26, 60(3)
- + lwz 27, 64(3)
- + lwz 28, 68(3)
- + 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)
- + lfd 17,112(3)
- + lfd 18,120(3)
- + lfd 19,128(3)
- + lfd 20,136(3)
- + lfd 21,144(3)
- + lfd 22,152(3)
- + lfd 23,160(3)
- + lfd 24,168(3)
- + lfd 25,176(3)
- + lfd 26,184(3)
- + lfd 27,192(3)
- + lfd 28,200(3)
- + lfd 29,208(3)
- + lfd 30,216(3)
- + lfd 31,224(3)
- +#endif
- + /* 5) put val into return reg r3 */
- + mr 3, 4
- +
- + /* 6) check if return value is 0, make it 1 in that case */
- + cmpwi cr7, 4, 0
- + bne cr7, 1f
- + li 3, 1
- +1:
- + blr
- +
- --- a/src/setjmp/powerpc/longjmp.s
- +++ /dev/null
- @@ -1,65 +0,0 @@
- - .global _longjmp
- - .global longjmp
- - .type _longjmp,@function
- - .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
- - lwz 0, 0(3)
- - # 1) put it into link reg
- - mtlr 0
- - #2 ) restore stack ptr
- - lwz 1, 4(3)
- - #3) restore control reg
- - lwz 0, 8(3)
- - mtcr 0
- - #4) restore r14-r31
- - lwz 14, 12(3)
- - lwz 15, 16(3)
- - lwz 16, 20(3)
- - lwz 17, 24(3)
- - lwz 18, 28(3)
- - lwz 19, 32(3)
- - lwz 20, 36(3)
- - lwz 21, 40(3)
- - lwz 22, 44(3)
- - lwz 23, 48(3)
- - lwz 24, 52(3)
- - lwz 25, 56(3)
- - lwz 26, 60(3)
- - lwz 27, 64(3)
- - lwz 28, 68(3)
- - lwz 29, 72(3)
- - lwz 30, 76(3)
- - lwz 31, 80(3)
- - lfd 14,88(3)
- - lfd 15,96(3)
- - lfd 16,104(3)
- - lfd 17,112(3)
- - lfd 18,120(3)
- - lfd 19,128(3)
- - lfd 20,136(3)
- - lfd 21,144(3)
- - lfd 22,152(3)
- - lfd 23,160(3)
- - lfd 24,168(3)
- - lfd 25,176(3)
- - lfd 26,184(3)
- - lfd 27,192(3)
- - lfd 28,200(3)
- - lfd 29,208(3)
- - lfd 30,216(3)
- - lfd 31,224(3)
- - #5) put val into return reg r3
- - mr 3, 4
- -
- - #6) check if return value is 0, make it 1 in that case
- - cmpwi cr7, 4, 0
- - bne cr7, 1f
- - li 3, 1
- -1:
- - blr
- -
- --- /dev/null
- +++ b/src/setjmp/powerpc/setjmp.S
- @@ -0,0 +1,63 @@
- + .global ___setjmp
- + .hidden ___setjmp
- + .global __setjmp
- + .global _setjmp
- + .global setjmp
- + .type __setjmp,@function
- + .type _setjmp,@function
- + .type setjmp,@function
- +___setjmp:
- +__setjmp:
- +_setjmp:
- +setjmp:
- + /* 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) */
- + stw 1, 4(3)
- + /* 2) store cr */
- + mfcr 0
- + stw 0, 8(3)
- + /* 3) store r14-31 */
- + stw 14, 12(3)
- + stw 15, 16(3)
- + stw 16, 20(3)
- + stw 17, 24(3)
- + stw 18, 28(3)
- + stw 19, 32(3)
- + stw 20, 36(3)
- + stw 21, 40(3)
- + stw 22, 44(3)
- + stw 23, 48(3)
- + stw 24, 52(3)
- + stw 25, 56(3)
- + stw 26, 60(3)
- + stw 27, 64(3)
- + stw 28, 68(3)
- + 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)
- + stfd 17,112(3)
- + stfd 18,120(3)
- + stfd 19,128(3)
- + stfd 20,136(3)
- + stfd 21,144(3)
- + stfd 22,152(3)
- + stfd 23,160(3)
- + stfd 24,168(3)
- + stfd 25,176(3)
- + stfd 26,184(3)
- + stfd 27,192(3)
- + stfd 28,200(3)
- + stfd 29,208(3)
- + stfd 30,216(3)
- + stfd 31,224(3)
- +#endif
- + /* 4) set return value to 0 */
- + li 3, 0
- + /* 5) return */
- + blr
- --- a/src/setjmp/powerpc/setjmp.s
- +++ /dev/null
- @@ -1,61 +0,0 @@
- - .global ___setjmp
- - .hidden ___setjmp
- - .global __setjmp
- - .global _setjmp
- - .global setjmp
- - .type __setjmp,@function
- - .type _setjmp,@function
- - .type setjmp,@function
- -___setjmp:
- -__setjmp:
- -_setjmp:
- -setjmp:
- - # 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)
- - stw 1, 4(3)
- - # 2) store cr
- - mfcr 0
- - stw 0, 8(3)
- - # 3) store r14-31
- - stw 14, 12(3)
- - stw 15, 16(3)
- - stw 16, 20(3)
- - stw 17, 24(3)
- - stw 18, 28(3)
- - stw 19, 32(3)
- - stw 20, 36(3)
- - stw 21, 40(3)
- - stw 22, 44(3)
- - stw 23, 48(3)
- - stw 24, 52(3)
- - stw 25, 56(3)
- - stw 26, 60(3)
- - stw 27, 64(3)
- - stw 28, 68(3)
- - stw 29, 72(3)
- - stw 30, 76(3)
- - stw 31, 80(3)
- - stfd 14,88(3)
- - stfd 15,96(3)
- - stfd 16,104(3)
- - stfd 17,112(3)
- - stfd 18,120(3)
- - stfd 19,128(3)
- - stfd 20,136(3)
- - stfd 21,144(3)
- - stfd 22,152(3)
- - stfd 23,160(3)
- - stfd 24,168(3)
- - stfd 25,176(3)
- - stfd 26,184(3)
- - stfd 27,192(3)
- - stfd 28,200(3)
- - stfd 29,208(3)
- - stfd 30,216(3)
- - stfd 31,224(3)
- - # 4) set return value to 0
- - li 3, 0
- - # 5) return
- - blr
|