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
Notes: sideshowbarker 2024-07-18 07:15:38 +09:00

View file

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