diff options
| author | Rich Felker <dalias@aerifal.cx> | 2012-11-18 16:31:14 -0500 | 
|---|---|---|
| committer | Rich Felker <dalias@aerifal.cx> | 2012-11-18 16:31:14 -0500 | 
| commit | 75c450cff34b5206aca6aab14b7ad909168b8f50 (patch) | |
| tree | 10d0a696a03195f52b7b22e190cf6aeb305be20f | |
| parent | 0b52bf5c78435f3af4e0c1cbbe4177861e599847 (diff) | |
| download | musl-75c450cff34b5206aca6aab14b7ad909168b8f50.tar.gz | |
fenv support for ppc, untested
based on code sent to the mailing list by nsz, with minor changes.
| -rw-r--r-- | arch/powerpc/bits/fenv.h | 35 | ||||
| -rw-r--r-- | src/fenv/powerpc/fenv.s | 120 | 
2 files changed, 148 insertions, 7 deletions
| diff --git a/arch/powerpc/bits/fenv.h b/arch/powerpc/bits/fenv.h index edbdea2a..b0af1ffe 100644 --- a/arch/powerpc/bits/fenv.h +++ b/arch/powerpc/bits/fenv.h @@ -1,10 +1,31 @@ -#define FE_ALL_EXCEPT 0 -#define FE_TONEAREST  0 +#define FE_TONEAREST	0 +#define FE_TOWARDZERO	1 +#define FE_UPWARD	2 +#define FE_DOWNWARD	3 -typedef unsigned long fexcept_t; +#define FE_INEXACT	0x02000000 +#define FE_DIVBYZERO	0x04000000 +#define FE_UNDERFLOW	0x08000000 +#define FE_OVERFLOW	0x10000000 +#define FE_INVALID	0x20000000 -typedef struct { -	unsigned long __cw; -} fenv_t; +#define FE_ALL_EXCEPT	0x3e000000 -#define FE_DFL_ENV      ((const fenv_t *) -1) +#ifdef _GNU_SOURCE +#define FE_INVALID_SNAN		0x01000000 +#define FE_INVALID_ISI		0x00800000 +#define FE_INVALID_IDI		0x00400000 +#define FE_INVALID_ZDZ		0x00200000 +#define FE_INVALID_IMZ		0x00100000 +#define FE_INVALID_COMPARE	0x00080000 +#define FE_INVALID_SOFTWARE	0x00000400 +#define FE_INVALID_SQRT		0x00000200 +#define FE_INVALID_INTEGER_CONVERSION	0x00000100 + +#define FE_ALL_INVALID		0x01f80700 +#endif + +typedef unsigned fexcept_t; +typedef double fenv_t; + +#define FE_DFL_ENV ((fenv_t *)-1) diff --git a/src/fenv/powerpc/fenv.s b/src/fenv/powerpc/fenv.s new file mode 100644 index 00000000..9c424d8e --- /dev/null +++ b/src/fenv/powerpc/fenv.s @@ -0,0 +1,120 @@ +.global feclearexcept +.type feclearexcept,@function +feclearexcept: +	# 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: +	# 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: +	# 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 | 
