summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
Diffstat (limited to 'Userland')
-rw-r--r--Userland/DevTools/UserspaceEmulator/SoftFPU.cpp38
1 files changed, 20 insertions, 18 deletions
diff --git a/Userland/DevTools/UserspaceEmulator/SoftFPU.cpp b/Userland/DevTools/UserspaceEmulator/SoftFPU.cpp
index 1cc48b66fd..7c8cd5ccf8 100644
--- a/Userland/DevTools/UserspaceEmulator/SoftFPU.cpp
+++ b/Userland/DevTools/UserspaceEmulator/SoftFPU.cpp
@@ -1054,32 +1054,34 @@ void SoftFPU::F2XM1(const X86::Instruction&)
}
void SoftFPU::FYL2X(const X86::Instruction&)
{
- // FIXME: raise precision and under/overflow
- // FIXME: detect denormal operands
- // FIXME: QNaN
- auto f0 = fpu_get(0);
- auto f1 = fpu_get(1);
-
- if (f0 < 0. || isnan(f0) || isnan(f1)
- || (isinf(f0) && f1 == 0.) || (f0 == 1. && isinf(f1)))
+ // FIXME: Set C1 on when result was rounded up, cleared otherwise
+ // FIXME: Raise #IA #D #U #O #P
+ auto x = fpu_get(0);
+ auto y = fpu_get(1);
+ if (x < 0. && !isinf(x)) {
fpu_set_exception(FPU_Exception::InvalidOperation);
- if (f0 == 0.)
+ // FIXME: Spec does not say what to do here....
+ // 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::ZeroDivide);
-
- fpu_set(1, f1 * log2l(f0));
+ fpu_set(1, INFINITY * (signbit(y) ? 1 : -1));
+ } else {
+ fpu_set(1, y * log2l(x));
+ }
fpu_pop();
}
void SoftFPU::FYL2XP1(const X86::Instruction&)
{
- // FIXME: raise #O #U #P #D
- // FIXME: QNaN
- auto f0 = fpu_get(0);
- auto f1 = fpu_get(1);
- if (isnan(f0) || isnan(f1)
- || (isinf(f1) && f0 == 0))
+ // FIXME: Raise #IA #O #U #P #D
+ auto x = fpu_get(0);
+ auto y = fpu_get(1);
+ if (x == 0 && isinf(y))
fpu_set_exception(FPU_Exception::InvalidOperation);
- fpu_set(1, (f1 * log2l(f0 + 1.0l)));
+ fpu_set(1, (y * log2l(x + 1.0l)));
fpu_pop();
}