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.
This commit is contained in:
Andreas Kling 2020-11-14 15:15:41 +01:00
parent d4509647d8
commit 60ff27c633
Notes: sideshowbarker 2024-07-19 02:28:16 +09:00

View File

@ -1709,24 +1709,32 @@ void SoftCPU::FNINIT(const X86::Instruction&) { TODO_INSN(); }
void SoftCPU::FNSETPM(const X86::Instruction&) { TODO_INSN(); } void SoftCPU::FNSETPM(const X86::Instruction&) { TODO_INSN(); }
void SoftCPU::FLD_RM80(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: Unordered comparison checks.
// FIXME: QNaN / exception handling. // FIXME: QNaN / exception handling.
// FIXME: Set C0, C2, C3 in FPU status word. // FIXME: Set C0, C2, C3 in FPU status word.
set_zf(fpu_get(0) == fpu_get(1)); if (__builtin_isnan(fpu_get(0)) || __builtin_isnan(fpu_get(i))) {
set_pf(false); set_zf(true);
set_cf(fpu_get(0) < fpu_get(1)); set_pf(true);
set_of(false); 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: QNaN / exception handling.
// FIXME: Set C0, C2, C3 in FPU status word. // 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_pf(false);
set_cf(fpu_get(0) < fpu_get(1)); set_cf(fpu_get(0) < fpu_get(i));
set_of(false); set_of(false);
} }