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

UserspaceEmulator: Make error checks in FYL2XP1 and FYL2X a bit closer

...to the manual

This removes the non complete NaN checks and fixes a bounds check in
FYL2X.
This commit is contained in:
Hendiadyoin1 2022-02-03 12:46:21 +01:00 committed by Andreas Kling
parent 60cb5b8dfa
commit 3f581c77d9

View file

@ -1054,32 +1054,34 @@ void SoftFPU::F2XM1(const X86::Instruction&)
} }
void SoftFPU::FYL2X(const X86::Instruction&) void SoftFPU::FYL2X(const X86::Instruction&)
{ {
// FIXME: raise precision and under/overflow // FIXME: Set C1 on when result was rounded up, cleared otherwise
// FIXME: detect denormal operands // FIXME: Raise #IA #D #U #O #P
// FIXME: QNaN auto x = fpu_get(0);
auto f0 = fpu_get(0); auto y = fpu_get(1);
auto f1 = fpu_get(1); if (x < 0. && !isinf(x)) {
fpu_set_exception(FPU_Exception::InvalidOperation);
if (f0 < 0. || isnan(f0) || isnan(f1) // FIXME: Spec does not say what to do here....
|| (isinf(f0) && f1 == 0.) || (f0 == 1. && isinf(f1))) // So lets just ask libm....
fpu_set(1, y * log2l(x));
} else if (x == 0.) {
if (y == 0)
fpu_set_exception(FPU_Exception::InvalidOperation); fpu_set_exception(FPU_Exception::InvalidOperation);
if (f0 == 0.)
fpu_set_exception(FPU_Exception::ZeroDivide); fpu_set_exception(FPU_Exception::ZeroDivide);
fpu_set(1, INFINITY * (signbit(y) ? 1 : -1));
fpu_set(1, f1 * log2l(f0)); } else {
fpu_set(1, y * log2l(x));
}
fpu_pop(); fpu_pop();
} }
void SoftFPU::FYL2XP1(const X86::Instruction&) void SoftFPU::FYL2XP1(const X86::Instruction&)
{ {
// FIXME: raise #O #U #P #D // FIXME: Raise #IA #O #U #P #D
// FIXME: QNaN auto x = fpu_get(0);
auto f0 = fpu_get(0); auto y = fpu_get(1);
auto f1 = fpu_get(1); if (x == 0 && isinf(y))
if (isnan(f0) || isnan(f1)
|| (isinf(f1) && f0 == 0))
fpu_set_exception(FPU_Exception::InvalidOperation); fpu_set_exception(FPU_Exception::InvalidOperation);
fpu_set(1, (f1 * log2l(f0 + 1.0l))); fpu_set(1, (y * log2l(x + 1.0l)));
fpu_pop(); fpu_pop();
} }