diff --git a/FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp b/FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp index 239c85fea..371ab33c9 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp @@ -17,7 +17,7 @@ using namespace IR; // All OPDReg versions need it #define OPDReg(op, reg) ((1 << 15) | ((op - 0xD8) << 8) | (reg << 3)) #define OPD(op, modrmop) (((op - 0xD8) << 8) | modrmop) -constexpr std::array X87F64OpTable = {{ +constexpr std::array X87F64OpTable = {{ {OPDReg(0xD8, 0) | 0x00, 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FADDF64, OpSize::i32Bit, false, OpDispatchBuilder::OpResult::RES_ST0>}, {OPDReg(0xD8, 1) | 0x00, 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FMULF64, OpSize::i32Bit, false, OpDispatchBuilder::OpResult::RES_ST0>}, @@ -251,6 +251,8 @@ constexpr std::array X87F64OpTable = {{ {OPD(0xDE, 0xC0), 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FADDF64, OpSize::f80Bit, false, OpDispatchBuilder::OpResult::RES_STI>}, {OPD(0xDE, 0xC8), 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FMULF64, OpSize::f80Bit, false, OpDispatchBuilder::OpResult::RES_STI>}, + {OPD(0xDE, 0xD0), 8, + &OpDispatchBuilder::Bind<&OpDispatchBuilder::FCOMIF64, OpSize::f80Bit, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, {OPD(0xDE, 0xD9), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FCOMIF64, OpSize::f80Bit, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, {OPD(0xDE, 0xE0), 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FSUBF64, OpSize::f80Bit, false, true, OpDispatchBuilder::OpResult::RES_STI>}, @@ -285,7 +287,7 @@ constexpr std::array X87F64OpTable = {{ &OpDispatchBuilder::Bind<&OpDispatchBuilder::FCOMIF64, OpSize::f80Bit, false, OpDispatchBuilder::FCOMIFlags::FLAGS_RFLAGS, false>}, }}; -constexpr std::array X87F80OpTable = {{ +constexpr std::array X87F80OpTable = {{ {OPDReg(0xD8, 0) | 0x00, 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FADD, OpSize::i32Bit, false, OpDispatchBuilder::OpResult::RES_ST0>}, {OPDReg(0xD8, 1) | 0x00, 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FMUL, OpSize::i32Bit, false, OpDispatchBuilder::OpResult::RES_ST0>}, @@ -508,6 +510,7 @@ constexpr std::array X87F80OpTable = {{ {OPD(0xDE, 0xC0), 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FADD, OpSize::f80Bit, false, OpDispatchBuilder::OpResult::RES_STI>}, {OPD(0xDE, 0xC8), 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FMUL, OpSize::f80Bit, false, OpDispatchBuilder::OpResult::RES_STI>}, + {OPD(0xDE, 0xD0), 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FCOMI, OpSize::f80Bit, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, {OPD(0xDE, 0xD9), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FCOMI, OpSize::f80Bit, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, {OPD(0xDE, 0xE0), 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FSUB, OpSize::f80Bit, false, true, OpDispatchBuilder::OpResult::RES_STI>}, {OPD(0xDE, 0xE8), 8, &OpDispatchBuilder::Bind<&OpDispatchBuilder::FSUB, OpSize::f80Bit, false, false, OpDispatchBuilder::OpResult::RES_STI>}, @@ -744,7 +747,7 @@ auto GenerateX87TableLambda = [](const auto DispatchTable) consteval { // / 1 {OPD(0xDE, 0xC8), 8, X86InstInfo{"FMULP", TYPE_X87, FLAGS_POP, 0}}, // / 2 - {OPD(0xDE, 0xD0), 8, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0}}, + {OPD(0xDE, 0xD0), 8, X86InstInfo{"FCOMP", TYPE_X87, FLAGS_X87_FLAGS | FLAGS_POP, 0}}, // / 3 {OPD(0xDE, 0xD8), 1, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0}}, {OPD(0xDE, 0xD9), 1, X86InstInfo{"FCOMPP", TYPE_X87, FLAGS_POP, 0}}, diff --git a/unittests/ASM/X87/DE_D0.asm b/unittests/ASM/X87/DE_D0.asm new file mode 100644 index 000000000..7ea2f5cad --- /dev/null +++ b/unittests/ASM/X87/DE_D0.asm @@ -0,0 +1,19 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0x8000000000000000", "0x3FFF"] + } +} +%endif + +; Only tests pop behaviour +; Tests undocumented fcomp implementation at 0xde, 0xd0+i +finit +fld1 +fldz +; fcomp +db 0xde, 0xd1 +fld1 + +hlt