diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 169b64bee..dc584a396 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -5517,7 +5517,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, @@ -5776,7 +5776,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 081e2807b..4025f5f22 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -733,6 +733,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 cfa819695..69c2874d3 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp @@ -760,6 +760,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/D8_F0_2.asm b/unittests/32Bit_ASM/X87/D8_F0_2.asm new file mode 100644 index 000000000..af32cd1ce --- /dev/null +++ b/unittests/32Bit_ASM/X87/D8_F0_2.asm @@ -0,0 +1,18 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0" + }, + "Mode": "32BIT" +} +%endif + +; Tests that a division by zero does not set the IE flag +finit +fldz +fld1 +fdiv st0, st1 + +fnstsw ax +and eax, 1 +hlt diff --git a/unittests/32Bit_ASM/X87/DB_E2.asm b/unittests/32Bit_ASM/X87/DB_E2.asm new file mode 100644 index 000000000..ae1810110 --- /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 +fldz +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/D8_F0_2.asm b/unittests/ASM/X87/D8_F0_2.asm new file mode 100644 index 000000000..5c10fbbee --- /dev/null +++ b/unittests/ASM/X87/D8_F0_2.asm @@ -0,0 +1,17 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0" + } +} +%endif + +; Tests that a division by zero does not set the IE flag +finit +fldz +fld1 +fdiv st0, st1 + +fnstsw ax +and rax, 1 +hlt diff --git a/unittests/ASM/X87/DB_E2.asm b/unittests/ASM/X87/DB_E2.asm new file mode 100644 index 000000000..0975410fe --- /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 +fldz +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/D8_F0_2_F64.asm b/unittests/ASM/X87_F64/D8_F0_2_F64.asm new file mode 100644 index 000000000..318ebe82a --- /dev/null +++ b/unittests/ASM/X87_F64/D8_F0_2_F64.asm @@ -0,0 +1,18 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0" + }, + "Env": { "FEX_X87REDUCEDPRECISION" : "1" } +} +%endif + +; Tests that a division by zero does not set the IE flag +finit +fldz +fld1 +fdiv st0, st1 + +fnstsw ax +and rax, 1 +hlt diff --git a/unittests/InstructionCountCI/FlagM/x87.json b/unittests/InstructionCountCI/FlagM/x87.json index fd77709fb..a3072c535 100644 --- a/unittests/InstructionCountCI/FlagM/x87.json +++ b/unittests/InstructionCountCI/FlagM/x87.json @@ -4939,11 +4939,13 @@ ] }, "fnclex": { - "ExpectedInstructionCount": 0, + "ExpectedInstructionCount": 1, "Comment": [ "0xdb 11b 0xe2 /4" ], - "ExpectedArm64ASM": [] + "ExpectedArm64ASM": [ + "strb wzr, [x28, #1008]" + ] }, "fninit": { "ExpectedInstructionCount": 8, diff --git a/unittests/InstructionCountCI/FlagM/x87_f64.json b/unittests/InstructionCountCI/FlagM/x87_f64.json index f85b31d4e..254e7e756 100644 --- a/unittests/InstructionCountCI/FlagM/x87_f64.json +++ b/unittests/InstructionCountCI/FlagM/x87_f64.json @@ -4268,11 +4268,13 @@ ] }, "fnclex": { - "ExpectedInstructionCount": 0, + "ExpectedInstructionCount": 1, "Comment": [ "0xdb 11b 0xe2 /4" ], - "ExpectedArm64ASM": [] + "ExpectedArm64ASM": [ + "strb wzr, [x28, #1008]" + ] }, "fninit": { "ExpectedInstructionCount": 16, diff --git a/unittests/InstructionCountCI/x87.json b/unittests/InstructionCountCI/x87.json index aefa402e2..c2ffeb82a 100644 --- a/unittests/InstructionCountCI/x87.json +++ b/unittests/InstructionCountCI/x87.json @@ -4938,11 +4938,13 @@ ] }, "fnclex": { - "ExpectedInstructionCount": 0, + "ExpectedInstructionCount": 1, "Comment": [ "0xdb 11b 0xe2 /4" ], - "ExpectedArm64ASM": [] + "ExpectedArm64ASM": [ + "strb wzr, [x28, #1008]" + ] }, "fninit": { "ExpectedInstructionCount": 8, diff --git a/unittests/InstructionCountCI/x87_f64.json b/unittests/InstructionCountCI/x87_f64.json index 899a99f6f..49d60bd28 100644 --- a/unittests/InstructionCountCI/x87_f64.json +++ b/unittests/InstructionCountCI/x87_f64.json @@ -4289,11 +4289,13 @@ ] }, "fnclex": { - "ExpectedInstructionCount": 0, + "ExpectedInstructionCount": 1, "Comment": [ "0xdb 11b 0xe2 /4" ], - "ExpectedArm64ASM": [] + "ExpectedArm64ASM": [ + "strb wzr, [x28, #1008]" + ] }, "fninit": { "ExpectedInstructionCount": 16,