[PowerPC] Fix SPE floating point environment manipulation
Fix multiple problems in the powerpcspe floating point code. * Endianness handling of the SPEFSCR in fenv.h was completely broken. * Ensure SPEFSCR synchronization requirements are being met. The __r.__d -> __r transformations were written by jhibbits. Reviewed by: jhibbits Differential Revision: https://reviews.freebsd.org/D22526
This commit is contained in:
parent
0343972379
commit
4f9ed3156c
@ -47,7 +47,7 @@ fpsetmask(fp_except_t mask)
|
||||
__asm__ __volatile("mfspr %0, %1" : "=r"(fpscr) : "K"(SPR_SPEFSCR));
|
||||
old = (fp_rnd_t)((fpscr >> 2) & 0x1f);
|
||||
fpscr = (fpscr & 0xffffff83) | (mask << 2);
|
||||
__asm__ __volatile("mtspr %1,%0" :: "r"(fpscr), "K"(SPR_SPEFSCR));
|
||||
__asm__ __volatile("mtspr %1,%0;isync" :: "r"(fpscr), "K"(SPR_SPEFSCR));
|
||||
return (old);
|
||||
}
|
||||
#endif
|
||||
|
@ -47,7 +47,7 @@ fpsetround(fp_rnd_t rnd_dir)
|
||||
__asm__ __volatile("mfspr %0, %1" : "=r"(fpscr) : "K"(SPR_SPEFSCR) );
|
||||
old = (fp_rnd_t)(fpscr & 0x3);
|
||||
fpscr = (fpscr & 0xfffffffc) | rnd_dir;
|
||||
__asm__ __volatile("mtspr %1, %0" :: "r"(fpscr), "K"(SPR_SPEFSCR));
|
||||
__asm__ __volatile("mtspr %1, %0;isync" :: "r"(fpscr), "K"(SPR_SPEFSCR));
|
||||
return (old);
|
||||
}
|
||||
#endif
|
||||
|
@ -32,6 +32,7 @@
|
||||
#define _FENV_H_
|
||||
|
||||
#include <sys/_types.h>
|
||||
#include <machine/endian.h>
|
||||
|
||||
#ifndef __fenv_static
|
||||
#define __fenv_static static
|
||||
@ -90,11 +91,15 @@ extern const fenv_t __fe_dfl_env;
|
||||
|
||||
#ifndef _SOFT_FLOAT
|
||||
#ifdef __SPE__
|
||||
#define __mffs(__env) __asm __volatile("mfspr %0, 512" : "=r" (*(__env)))
|
||||
#define __mtfsf(__env) __asm __volatile("mtspr 512,%0" : : "r" (__env))
|
||||
#define __mffs(__env) \
|
||||
__asm __volatile("mfspr %0, 512" : "=r" ((__env)->__bits.__reg))
|
||||
#define __mtfsf(__env) \
|
||||
__asm __volatile("mtspr 512,%0;isync" :: "r" ((__env).__bits.__reg))
|
||||
#else
|
||||
#define __mffs(__env) __asm __volatile("mffs %0" : "=f" (*(__env)))
|
||||
#define __mtfsf(__env) __asm __volatile("mtfsf 255,%0" : : "f" (__env))
|
||||
#define __mffs(__env) \
|
||||
__asm __volatile("mffs %0" : "=f" ((__env)->__d))
|
||||
#define __mtfsf(__env) \
|
||||
__asm __volatile("mtfsf 255,%0" :: "f" ((__env).__d))
|
||||
#endif
|
||||
#else
|
||||
#define __mffs(__env)
|
||||
@ -121,9 +126,9 @@ feclearexcept(int __excepts)
|
||||
|
||||
if (__excepts & FE_INVALID)
|
||||
__excepts |= FE_ALL_INVALID;
|
||||
__mffs(&__r.__d);
|
||||
__mffs(&__r);
|
||||
__r.__bits.__reg &= ~__excepts;
|
||||
__mtfsf(__r.__d);
|
||||
__mtfsf(__r);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -132,7 +137,7 @@ fegetexceptflag(fexcept_t *__flagp, int __excepts)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
__mffs(&__r);
|
||||
*__flagp = __r.__bits.__reg & __excepts;
|
||||
return (0);
|
||||
}
|
||||
@ -144,10 +149,10 @@ fesetexceptflag(const fexcept_t *__flagp, int __excepts)
|
||||
|
||||
if (__excepts & FE_INVALID)
|
||||
__excepts |= FE_ALL_EXCEPT;
|
||||
__mffs(&__r.__d);
|
||||
__mffs(&__r);
|
||||
__r.__bits.__reg &= ~__excepts;
|
||||
__r.__bits.__reg |= *__flagp & __excepts;
|
||||
__mtfsf(__r.__d);
|
||||
__mtfsf(__r);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -158,9 +163,9 @@ feraiseexcept(int __excepts)
|
||||
|
||||
if (__excepts & FE_INVALID)
|
||||
__excepts |= FE_VXSOFT;
|
||||
__mffs(&__r.__d);
|
||||
__mffs(&__r);
|
||||
__r.__bits.__reg |= __excepts;
|
||||
__mtfsf(__r.__d);
|
||||
__mtfsf(__r);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -169,7 +174,7 @@ fetestexcept(int __excepts)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
__mffs(&__r);
|
||||
return (__r.__bits.__reg & __excepts);
|
||||
}
|
||||
|
||||
@ -178,7 +183,7 @@ fegetround(void)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
__mffs(&__r);
|
||||
return (__r.__bits.__reg & _ROUND_MASK);
|
||||
}
|
||||
|
||||
@ -189,10 +194,10 @@ fesetround(int __round)
|
||||
|
||||
if (__round & ~_ROUND_MASK)
|
||||
return (-1);
|
||||
__mffs(&__r.__d);
|
||||
__mffs(&__r);
|
||||
__r.__bits.__reg &= ~_ROUND_MASK;
|
||||
__r.__bits.__reg |= __round;
|
||||
__mtfsf(__r.__d);
|
||||
__mtfsf(__r);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -201,7 +206,7 @@ fegetenv(fenv_t *__envp)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
__mffs(&__r);
|
||||
*__envp = __r.__bits.__reg;
|
||||
return (0);
|
||||
}
|
||||
@ -211,10 +216,10 @@ feholdexcept(fenv_t *__envp)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
__mffs(&__r);
|
||||
*__envp = __r.__d;
|
||||
__r.__bits.__reg &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
|
||||
__mtfsf(__r.__d);
|
||||
__mtfsf(__r);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -224,7 +229,7 @@ fesetenv(const fenv_t *__envp)
|
||||
union __fpscr __r;
|
||||
|
||||
__r.__bits.__reg = *__envp;
|
||||
__mtfsf(__r.__d);
|
||||
__mtfsf(__r);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -233,10 +238,10 @@ feupdateenv(const fenv_t *__envp)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
__mffs(&__r);
|
||||
__r.__bits.__reg &= FE_ALL_EXCEPT;
|
||||
__r.__bits.__reg |= *__envp;
|
||||
__mtfsf(__r.__d);
|
||||
__mtfsf(__r);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -250,10 +255,10 @@ feenableexcept(int __mask)
|
||||
union __fpscr __r;
|
||||
fenv_t __oldmask;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
__mffs(&__r);
|
||||
__oldmask = __r.__bits.__reg;
|
||||
__r.__bits.__reg |= (__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT;
|
||||
__mtfsf(__r.__d);
|
||||
__mtfsf(__r);
|
||||
return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
|
||||
}
|
||||
|
||||
@ -263,10 +268,10 @@ fedisableexcept(int __mask)
|
||||
union __fpscr __r;
|
||||
fenv_t __oldmask;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
__mffs(&__r);
|
||||
__oldmask = __r.__bits.__reg;
|
||||
__r.__bits.__reg &= ~((__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT);
|
||||
__mtfsf(__r.__d);
|
||||
__mtfsf(__r);
|
||||
return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
|
||||
}
|
||||
|
||||
@ -275,7 +280,7 @@ fegetexcept(void)
|
||||
{
|
||||
union __fpscr __r;
|
||||
|
||||
__mffs(&__r.__d);
|
||||
__mffs(&__r);
|
||||
return ((__r.__bits.__reg & _ENABLE_MASK) << _FPUSW_SHIFT);
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ enable_vec(struct thread *td)
|
||||
|
||||
/* Restore SPEFSCR and ACC. Use %r0 as the scratch for ACC. */
|
||||
mtspr(SPR_SPEFSCR, pcb->pcb_vec.vscr);
|
||||
__asm __volatile("evldd 0, 0(%0); evmra 0,0\n"
|
||||
__asm __volatile("isync;evldd 0, 0(%0); evmra 0,0\n"
|
||||
:: "b"(&pcb->pcb_vec.spare[0]));
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user