diff --git a/core/libs/prx/libc/src/Math.cpp b/core/libs/prx/libc/src/Math.cpp index 0d1bd3bbb4..3ee11e1da4 100644 --- a/core/libs/prx/libc/src/Math.cpp +++ b/core/libs/prx/libc/src/Math.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -792,7 +793,10 @@ SonyDconst _LSnan_nid_postfix {{1, 0, 0, 0x8000, 0x7fff, 0, 0, 0}}; int APS5_VABI fesetenv_nid_postfix(const GuestFloatingPointEnvironment* environment) { if (environment == nullptr) throw std::invalid_argument("fesetenv: null environment"); - if ((environment->mxcsr & 0xffff0000u) != 0) throw std::invalid_argument("fesetenv: unsupported MXCSR bits"); + alignas(16) std::array state; + asm volatile("fxsave %0" : "=m"(state)); + const auto supported = state[7] != 0 ? state[7] : 0xffbfu; + if ((environment->mxcsr & ~supported) != 0) throw std::invalid_argument("fesetenv: unsupported MXCSR bits"); asm volatile("fldenv %0" : : "m"(*environment) : "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)"); _mm_setcsr(environment->mxcsr); return 0; diff --git a/core/libs/tests/GuestSetEnv.cpp b/core/libs/tests/GuestSetEnv.cpp index e6fee83bc6..ed61a9717a 100644 --- a/core/libs/tests/GuestSetEnv.cpp +++ b/core/libs/tests/GuestSetEnv.cpp @@ -146,13 +146,18 @@ void BoundsAndErrors() { *__error_nid_postfix()=123; try { setEnvironment(nullptr); } catch(const std::invalid_argument&) { rejected=true; } Require(rejected && Same(Read(),original) && *__error_nid_postfix()==123,"null rejected without state or errno change"); - for(unsigned reserved:{0x10000u,0x80000000u,0xffff0000u}) { + alignas(16) std::array extended; + asm volatile("fxsave %0" : "=m"(extended)); + const auto supported=extended[7] ? extended[7] : 0xffbfu; + for(unsigned bit=0;bit<32;++bit) { + const auto reserved=1u<