From 93926641d90ffb09d0752de6bb831bc729d35c1e Mon Sep 17 00:00:00 2001 From: CallumDev Date: Fri, 29 Apr 2022 04:39:57 +0930 Subject: [PATCH] F64: Implement FLDCW using host rounding mode --- .../Interface/Core/OpcodeDispatcher.cpp | 2 +- .../Source/Interface/Core/OpcodeDispatcher.h | 1 + .../Core/OpcodeDispatcher/X87F64.cpp | 14 ++++++- unittests/ASM/X87_F64/FLDCW_F64.asm | 38 +++++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 unittests/ASM/X87_F64/FLDCW_F64.asm diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 7b0db3977..32072faa2 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -5994,7 +5994,7 @@ constexpr uint16_t PF_F2 = 3; {OPDReg(0xD9, 4) | 0x00, 8, &OpDispatchBuilder::X87LDENV}, - {OPDReg(0xD9, 5) | 0x00, 8, &OpDispatchBuilder::X87FLDCW}, // XXX: stubbed FLDCW + {OPDReg(0xD9, 5) | 0x00, 8, &OpDispatchBuilder::X87FLDCWF64}, {OPDReg(0xD9, 6) | 0x00, 8, &OpDispatchBuilder::X87FNSTENV}, diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index c74a8af15..2b8c8052e 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -503,6 +503,7 @@ public: template void X87BinaryOpF64(OpcodeArgs); void X87SinCosF64(OpcodeArgs); + void X87FLDCWF64(OpcodeArgs); void X87FYL2XF64(OpcodeArgs); void X87TANF64(OpcodeArgs); void X87ATANF64(OpcodeArgs); diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp index c19c9cc11..507fbce13 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp @@ -33,7 +33,6 @@ class OrderedNode; //LDENV //FNSTENV //FNINIT -//FLDCW //FSTCW //LDSW //FNSTSW @@ -41,6 +40,19 @@ class OrderedNode; //FCMOV //FST(register to register) +void OpDispatchBuilder::X87FLDCWF64(OpcodeArgs) { + OrderedNode *NewFCW = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); + //ignore the rounding precision, we're always 64-bit in F64. + //extract rounding mode + OrderedNode *roundingMode = NewFCW; + auto shift = _Constant(10); + auto mask = _Constant(3); + roundingMode = _Lshr(roundingMode, shift); + roundingMode = _And(roundingMode, mask); + _SetRoundingMode(roundingMode); + _StoreContext(2, GPRClass, NewFCW, offsetof(FEXCore::Core::CPUState, FCW)); +} + template void OpDispatchBuilder::FLDF64(OpcodeArgs) { // Update TOP diff --git a/unittests/ASM/X87_F64/FLDCW_F64.asm b/unittests/ASM/X87_F64/FLDCW_F64.asm new file mode 100644 index 000000000..2cc0a10bb --- /dev/null +++ b/unittests/ASM/X87_F64/FLDCW_F64.asm @@ -0,0 +1,38 @@ +%ifdef CONFIG +{ + "Env": { "FEX_X87REDUCEDPRECISION" : "1" }, + "RegData": { + "RAX": "0x3", + "RBX": "0x2" + } +} +%endif + +lea rbp, [rel data] +mov rdx, 0xe0000000 +mov rcx, 0xe0004000 + +; save fcw +fnstcw [rdx] +; set rounding to truncate +mov eax, 0 +mov ax, [rdx] +or ah, 0xc +mov [rdx+8], ax +fldcw [rdx+8] + +fld dword [rbp] +fistp dword [rdx+16] +mov ebx, [rdx+16] + +; restore fcw +fldcw [rdx] +fld dword [rbp] +fistp dword[rdx+16] +mov eax, [rdx+16] + +hlt + +align 8 +data: + dd 0x40266666 ; 2.6