Date: Mon, 8 Mar 2021 19:07:31 GMT From: Brandon Bergren <bdragon@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: d905133e26d0 - stable/12 - [PowerPC] Fix SPE floating point environment manipulation Message-ID: <202103081907.128J7VCK063085@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/12 has been updated by bdragon: URL: https://cgit.FreeBSD.org/src/commit/?id=d905133e26d0c8852c9977a76a1091f25a031284 commit d905133e26d0c8852c9977a76a1091f25a031284 Author: Brandon Bergren <bdragon@FreeBSD.org> AuthorDate: 2019-12-12 17:12:18 +0000 Commit: Brandon Bergren <bdragon@FreeBSD.org> CommitDate: 2021-03-08 18:51:31 +0000 [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 (cherry picked from commit 4f9ed3156c3aff08629d37c8a89ed5ba525b01c9) --- lib/libc/powerpcspe/gen/fpsetmask.c | 2 +- lib/libc/powerpcspe/gen/fpsetround.c | 2 +- lib/msun/powerpc/fenv.h | 57 ++++++++++++++++++++---------------- sys/powerpc/booke/spe.c | 2 +- 4 files changed, 34 insertions(+), 29 deletions(-) diff --git a/lib/libc/powerpcspe/gen/fpsetmask.c b/lib/libc/powerpcspe/gen/fpsetmask.c index 9763b78a0919..e71b822d6e0b 100644 --- a/lib/libc/powerpcspe/gen/fpsetmask.c +++ b/lib/libc/powerpcspe/gen/fpsetmask.c @@ -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 diff --git a/lib/libc/powerpcspe/gen/fpsetround.c b/lib/libc/powerpcspe/gen/fpsetround.c index b5340a6d9ea2..2e2469cdae5e 100644 --- a/lib/libc/powerpcspe/gen/fpsetround.c +++ b/lib/libc/powerpcspe/gen/fpsetround.c @@ -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 diff --git a/lib/msun/powerpc/fenv.h b/lib/msun/powerpc/fenv.h index af9eee999b70..3e2a11c48c50 100644 --- a/lib/msun/powerpc/fenv.h +++ b/lib/msun/powerpc/fenv.h @@ -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); } diff --git a/sys/powerpc/booke/spe.c b/sys/powerpc/booke/spe.c index 7b24f3b7a759..0305145d5107 100644 --- a/sys/powerpc/booke/spe.c +++ b/sys/powerpc/booke/spe.c @@ -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])); /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202103081907.128J7VCK063085>