1 From: Felix Fietkau <nbd@openwrt.org>
2 Date: Wed, 8 Jul 2015 13:56:37 +0200
3 Subject: [PATCH] Add PowerPC soft-float support
5 Some PowerPC CPUs (e.g. Freescale MPC85xx) have a completely different
6 instruction set for floating point operations (SPE).
7 Executing regular PowerPC floating point instructions results in
8 "Illegal instruction" errors.
10 Make it possible to run these devices in soft-float mode.
12 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
14 create mode 100644 src/fenv/powerpc/fenv-sf.c
16 --- a/arch/powerpc/bits/fenv.h
17 +++ b/arch/powerpc/bits/fenv.h
20 +#define FE_ALL_EXCEPT 0
21 +#define FE_TONEAREST 0
23 #define FE_TONEAREST 0
24 #define FE_TOWARDZERO 1
28 #define FE_ALL_INVALID 0x01f80700
32 typedef unsigned fexcept_t;
33 typedef double fenv_t;
34 --- a/arch/powerpc/reloc.h
35 +++ b/arch/powerpc/reloc.h
37 -#define LDSO_ARCH "powerpc"
39 +#define FP_SUFFIX "-sf"
44 +#define LDSO_ARCH "powerpc" FP_SUFFIX
46 #define TPOFF_K (-0x7000)
50 @@ -604,6 +604,10 @@ trycppif "_MIPSEL || __MIPSEL || __MIPSE
51 trycppif __mips_soft_float "$t" && SUBARCH=${SUBARCH}-sf
54 +if test "$ARCH" = "powerpc" ; then
55 +trycppif _SOFT_FLOAT "$t" && SUBARCH=${SUBARCH}-sf
58 test "$ARCH" = "microblaze" && trycppif __MICROBLAZEEL__ "$t" \
59 && SUBARCH=${SUBARCH}el
62 +++ b/src/fenv/powerpc/fenv-sf.c
68 +++ b/src/fenv/powerpc/fenv.S
71 +.global feclearexcept
72 +.type feclearexcept,@function
75 + /* if (r3 & FE_INVALID) r3 |= all_invalid_flags */
83 + * note: fpscr contains various fpu status and control
84 + * flags and we dont check if r3 may alter other flags
85 + * than the exception related ones
101 +.global feraiseexcept
102 +.type feraiseexcept,@function
105 + /* if (r3 & FE_INVALID) r3 |= software_invalid_flag */
125 +.global fetestexcept
126 +.type fetestexcept,@function
129 + /* return r3 & fpscr */
139 +.type fegetround,@function
141 + /* return fpscr & 3 */
150 +.global __fesetround
151 +.type __fesetround,@function
154 + * note: invalid input is not checked, r3 < 4 must hold
155 + * fpscr = (fpscr & -4U) | r3
173 +.type fegetenv,@function
183 +.type fesetenv,@function
192 +1: /* fpscr = *r3 */
199 --- a/src/fenv/powerpc/fenv.s
202 -.global feclearexcept
203 -.type feclearexcept,@function
206 - # if (r3 & FE_INVALID) r3 |= all_invalid_flags
213 - # note: fpscr contains various fpu status and control
214 - # flags and we dont check if r3 may alter other flags
215 - # than the exception related ones
230 -.global feraiseexcept
231 -.type feraiseexcept,@function
234 - # if (r3 & FE_INVALID) r3 |= software_invalid_flag
254 -.global fetestexcept
255 -.type fetestexcept,@function
258 - # return r3 & fpscr
268 -.type fegetround,@function
279 -.global __fesetround
280 -.type __fesetround,@function
282 - # note: invalid input is not checked, r3 < 4 must hold
283 - # fpscr = (fpscr & -4U) | r3
300 -.type fegetenv,@function
310 -.type fesetenv,@function
326 +++ b/src/setjmp/powerpc/longjmp.S
330 + .type _longjmp,@function
331 + .type longjmp,@function
335 + * void longjmp(jmp_buf env, int val);
336 + * put val into return register and restore the env saved in setjmp
337 + * if val(r4) is 0, put 1 there.
339 + /* 0) move old return address into r0 */
341 + /* 1) put it into link reg */
343 + /* 2 ) restore stack ptr */
345 + /* 3) restore control reg */
348 + /* 4) restore r14-r31 */
387 + /* 5) put val into return reg r3 */
390 + /* 6) check if return value is 0, make it 1 in that case */
397 --- a/src/setjmp/powerpc/longjmp.s
402 - .type _longjmp,@function
403 - .type longjmp,@function
406 -# void longjmp(jmp_buf env, int val);
407 -# put val into return register and restore the env saved in setjmp
408 -# if val(r4) is 0, put 1 there.
409 - # 0) move old return address into r0
411 - # 1) put it into link reg
413 - #2 ) restore stack ptr
415 - #3) restore control reg
418 - #4) restore r14-r31
455 - #5) put val into return reg r3
458 - #6) check if return value is 0, make it 1 in that case
466 +++ b/src/setjmp/powerpc/setjmp.S
473 + .type __setjmp,@function
474 + .type _setjmp,@function
475 + .type setjmp,@function
480 + /* 0) store IP int 0, then into the jmpbuf pointed to by r3 (first arg) */
483 + /* 1) store reg1 (SP) */
488 + /* 3) store r14-31 */
527 + /* 4) set return value to 0 */
531 --- a/src/setjmp/powerpc/setjmp.s
539 - .type __setjmp,@function
540 - .type _setjmp,@function
541 - .type setjmp,@function
546 - # 0) store IP int 0, then into the jmpbuf pointed to by r3 (first arg)
549 - # 1) store reg1 (SP)
591 - # 4) set return value to 0