Save all fpcr/fpsr bits in the AArch64 fenv_t
The existing code masked off all bits that it didn't know about. To be future-proof, we should save and restore the entire fpcr/fpsr registers. Additionally, the existing fesetenv() was incorrectly setting the rounding mode in fpsr instead of fpcr. This patch stores fpcr in the high 32 bits of fenv_t and fpsr in the low bits instead of trying to interleave them in a single 32-bit field. Technically, this is an ABI break if you re-compile parts of your code or pass a fenv_t between DSOs that were compiled with different versions of fenv.h. However, I believe we should fix this since the existing code was broken and passing fenv_t across DSOs should rarely happen. Reviewed By: andrew Differential Revision: https://reviews.freebsd.org/D29160
This commit is contained in:
parent
b8e12d2d5c
commit
34cc08e336
@ -35,6 +35,7 @@
|
|||||||
#define __fenv_static static
|
#define __fenv_static static
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* The high 32 bits contain fpcr, low 32 contain fpsr. */
|
||||||
typedef __uint64_t fenv_t;
|
typedef __uint64_t fenv_t;
|
||||||
typedef __uint64_t fexcept_t;
|
typedef __uint64_t fexcept_t;
|
||||||
|
|
||||||
@ -156,13 +157,12 @@ fesetround(int __round)
|
|||||||
__fenv_static inline int
|
__fenv_static inline int
|
||||||
fegetenv(fenv_t *__envp)
|
fegetenv(fenv_t *__envp)
|
||||||
{
|
{
|
||||||
fenv_t __r;
|
__uint64_t fpcr;
|
||||||
|
__uint64_t fpsr;
|
||||||
|
|
||||||
__mrs_fpcr(__r);
|
__mrs_fpcr(fpcr);
|
||||||
*__envp = __r & _ENABLE_MASK;
|
__mrs_fpsr(fpsr);
|
||||||
|
*__envp = fpsr | (fpcr << 32);
|
||||||
__mrs_fpsr(__r);
|
|
||||||
*__envp |= __r & (FE_ALL_EXCEPT | (_ROUND_MASK << _ROUND_SHIFT));
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -173,12 +173,12 @@ feholdexcept(fenv_t *__envp)
|
|||||||
fenv_t __r;
|
fenv_t __r;
|
||||||
|
|
||||||
__mrs_fpcr(__r);
|
__mrs_fpcr(__r);
|
||||||
*__envp = __r & _ENABLE_MASK;
|
*__envp = __r << 32;
|
||||||
__r &= ~(_ENABLE_MASK);
|
__r &= ~(_ENABLE_MASK);
|
||||||
__msr_fpcr(__r);
|
__msr_fpcr(__r);
|
||||||
|
|
||||||
__mrs_fpsr(__r);
|
__mrs_fpsr(__r);
|
||||||
*__envp |= __r & (FE_ALL_EXCEPT | (_ROUND_MASK << _ROUND_SHIFT));
|
*__envp |= (__uint32_t)__r;
|
||||||
__r &= ~(_ENABLE_MASK);
|
__r &= ~(_ENABLE_MASK);
|
||||||
__msr_fpsr(__r);
|
__msr_fpsr(__r);
|
||||||
return (0);
|
return (0);
|
||||||
@ -188,8 +188,8 @@ __fenv_static inline int
|
|||||||
fesetenv(const fenv_t *__envp)
|
fesetenv(const fenv_t *__envp)
|
||||||
{
|
{
|
||||||
|
|
||||||
__msr_fpcr((*__envp) & _ENABLE_MASK);
|
__msr_fpcr((*__envp) >> 32);
|
||||||
__msr_fpsr((*__envp) & (FE_ALL_EXCEPT | (_ROUND_MASK << _ROUND_SHIFT)));
|
__msr_fpsr((fenv_t)(__uint32_t)*__envp);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user