diff options
author | Andreas Kling <kling@serenityos.org> | 2020-11-14 15:15:41 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-11-14 15:33:56 +0100 |
commit | 60ff27c63358ccf147c05c7cdfa6ca0d5d5a547c (patch) | |
tree | f46f7be95757757c3539f382f44d2a9394c83ffe | |
parent | d4509647d8ebbab89daedf705c25f8929cc1adb4 (diff) | |
download | serenity-60ff27c63358ccf147c05c7cdfa6ca0d5d5a547c.zip |
UserspaceEmulator: Improve FCOMI/FCOMIP/FUCOMI/FUCOMIP
These instructions now operate on the specified FPU stack entry instead
of always using ST(0) and ST(1).
FUCOMI and FUCOMIP also handle NaN values slightly better.
-rw-r--r-- | DevTools/UserspaceEmulator/SoftCPU.cpp | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/DevTools/UserspaceEmulator/SoftCPU.cpp b/DevTools/UserspaceEmulator/SoftCPU.cpp index 94de431e56..e86db38ea9 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.cpp +++ b/DevTools/UserspaceEmulator/SoftCPU.cpp @@ -1709,24 +1709,32 @@ void SoftCPU::FNINIT(const X86::Instruction&) { TODO_INSN(); } void SoftCPU::FNSETPM(const X86::Instruction&) { TODO_INSN(); } void SoftCPU::FLD_RM80(const X86::Instruction&) { TODO_INSN(); } -void SoftCPU::FUCOMI(const X86::Instruction&) +void SoftCPU::FUCOMI(const X86::Instruction& insn) { + auto i = insn.rm() & 7; // FIXME: Unordered comparison checks. // FIXME: QNaN / exception handling. // FIXME: Set C0, C2, C3 in FPU status word. - set_zf(fpu_get(0) == fpu_get(1)); - set_pf(false); - set_cf(fpu_get(0) < fpu_get(1)); - set_of(false); + if (__builtin_isnan(fpu_get(0)) || __builtin_isnan(fpu_get(i))) { + set_zf(true); + set_pf(true); + set_cf(true); + } else { + set_zf(fpu_get(0) == fpu_get(i)); + set_pf(false); + set_cf(fpu_get(0) < fpu_get(i)); + set_of(false); + } } -void SoftCPU::FCOMI(const X86::Instruction&) +void SoftCPU::FCOMI(const X86::Instruction& insn) { + auto i = insn.rm() & 7; // FIXME: QNaN / exception handling. // FIXME: Set C0, C2, C3 in FPU status word. - set_zf(fpu_get(0) == fpu_get(1)); + set_zf(fpu_get(0) == fpu_get(i)); set_pf(false); - set_cf(fpu_get(0) < fpu_get(1)); + set_cf(fpu_get(0) < fpu_get(i)); set_of(false); } |