diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 54bf8a0d3..c6396f809 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -5545,7 +5545,7 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {OPD(0xDB, 0xD0), 8, &OpDispatchBuilder::X87FCMOV}, {OPD(0xDB, 0xD8), 8, &OpDispatchBuilder::X87FCMOV}, // E0 = Invalid - {OPD(0xDB, 0xE2), 1, &OpDispatchBuilder::NOPOp}, // FNCLEX + {OPD(0xDB, 0xE2), 1, &OpDispatchBuilder::FNCLEX}, {OPD(0xDB, 0xE3), 1, &OpDispatchBuilder::FNINIT}, // E4 = Invalid {OPD(0xDB, 0xE8), 8, @@ -5804,7 +5804,7 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {OPD(0xDB, 0xD0), 8, &OpDispatchBuilder::X87FCMOV}, {OPD(0xDB, 0xD8), 8, &OpDispatchBuilder::X87FCMOV}, // E0 = Invalid - {OPD(0xDB, 0xE2), 1, &OpDispatchBuilder::NOPOp}, // FNCLEX + {OPD(0xDB, 0xE2), 1, &OpDispatchBuilder::FNCLEX}, {OPD(0xDB, 0xE3), 1, &OpDispatchBuilder::FNINIT}, // E4 = Invalid {OPD(0xDB, 0xE8), 8, diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 5dc4f089a..d6ddb6fd6 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -735,6 +735,7 @@ public: void FADD(OpcodeArgs, IR::OpSize Width, bool Integer, OpResult ResInST0); void FDIV(OpcodeArgs, IR::OpSize Width, bool Integer, bool Reverse, OpResult ResInST0); void FMUL(OpcodeArgs, IR::OpSize Width, bool Integer, OpResult ResInST0); + void FNCLEX(OpcodeArgs); void FNINIT(OpcodeArgs); void FSUB(OpcodeArgs, IR::OpSize Width, bool Integer, bool Reverse, OpResult ResInST0); void FTST(OpcodeArgs); diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp index be2ab5ea2..048f78f0b 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp @@ -759,6 +759,11 @@ void OpDispatchBuilder::X87FNSTSW(OpcodeArgs) { StoreResult(GPRClass, Op, StatusWord, OpSize::iInvalid); } +void OpDispatchBuilder::FNCLEX(OpcodeArgs) { + // Clear the exception flag bit + SetRFLAG(_Constant(0)); +} + void OpDispatchBuilder::FNINIT(OpcodeArgs) { auto Zero = _Constant(0); diff --git a/unittests/32Bit_ASM/X87/DB_E2.asm b/unittests/32Bit_ASM/X87/DB_E2.asm new file mode 100644 index 000000000..040fa2187 --- /dev/null +++ b/unittests/32Bit_ASM/X87/DB_E2.asm @@ -0,0 +1,26 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0", + "RBX": "1" + }, + "Mode": "32BIT" +} +%endif + +finit ; IOC is 0 +fldz +fld1 +fdiv st0, st1 ; IOC is 1 + +fnstsw ax +and eax, 1 +mov ebx, eax ; save IOC to RBX + +; Clear +fnclex + +fnstsw ax +and eax, 1 + +hlt diff --git a/unittests/ASM/X87/DB_E2.asm b/unittests/ASM/X87/DB_E2.asm new file mode 100644 index 000000000..b4481157c --- /dev/null +++ b/unittests/ASM/X87/DB_E2.asm @@ -0,0 +1,25 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0", + "RBX": "1" + } +} +%endif + +finit ; IOC is 0 +fldz +fld1 +fdiv st0, st1 ; IOC is 1 + +fnstsw ax +and rax, 1 +mov rbx, rax ; save IOC to RBX + +; Clear +fnclex + +fnstsw ax +and rax, 1 + +hlt diff --git a/unittests/ASM/X87_F64/DB_E2_F64.asm b/unittests/ASM/X87_F64/DB_E2_F64.asm new file mode 100644 index 000000000..cfe4ccee7 --- /dev/null +++ b/unittests/ASM/X87_F64/DB_E2_F64.asm @@ -0,0 +1,26 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0", + "RBX": "1" + }, + "Env": { "FEX_X87REDUCEDPRECISION" : "1" } +} +%endif + +finit ; IOC is 0 +fldz +fld1 +fdiv st0, st1 ; IOC is 1 + +fnstsw ax +and rax, 1 +mov rbx, rax ; save IOC to RBX + +; Clear +fnclex + +fnstsw ax +and rax, 1 + +hlt