1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 12:17:44 +00:00

AK: Handle partial remainders

On x86, the `fprem` and `fmprem1` instructions may produce a 'partial
remainder', for which we should check by reading a FPU flag. If we don't
check for it, we may end up using values that are outside the expected
range of values.
This commit is contained in:
Daniel Bertalan 2021-08-06 18:27:11 +02:00 committed by Andreas Kling
parent 653d22e21f
commit 5d32f543ec

View file

@ -65,23 +65,29 @@ template<FloatingPoint T>
constexpr T fmod(T x, T y) constexpr T fmod(T x, T y)
{ {
CONSTEXPR_STATE(fmod, x, y); CONSTEXPR_STATE(fmod, x, y);
T res; u16 fpu_status;
do {
asm( asm(
"fprem" "fprem\n"
: "=t"(res) "fnstsw %%ax\n"
: "0"(x), "u"(y)); : "+t"(x), "=a"(fpu_status)
return res; : "u"(y));
} while (fpu_status & 0x400);
return x;
} }
template<FloatingPoint T> template<FloatingPoint T>
constexpr T remainder(T x, T y) constexpr T remainder(T x, T y)
{ {
CONSTEXPR_STATE(remainder, x, y); CONSTEXPR_STATE(remainder, x, y);
T res; u16 fpu_status;
do {
asm( asm(
"fprem1" "fprem1\n"
: "=t"(res) "fnstsw %%ax\n"
: "0"(x), "u"(y)); : "+t"(x), "=a"(fpu_status)
return res; : "u"(y));
} while (fpu_status & 0x400);
return x;
} }
} }