From 6977ae6b798c1f6f6ec0ff8f461f129dd63438dc Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sun, 8 Jan 2023 11:02:52 -0800 Subject: [PATCH 1/4] X87_F64: Fixes FICOM This was not correctly converting both 32-bit and 16-bit integers over to 64-bit double. --- .../Interface/Core/OpcodeDispatcher/X87F64.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp index 9f10eb9cf..7f5fa97aa 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp @@ -39,7 +39,7 @@ class OrderedNode; //FST(register to register) // State loading duplicated from X87.cpp, setting host rounding mode -// See issue +// See issue void OpDispatchBuilder::FNINITF64(OpcodeArgs) { // Init FCW to 0x037F auto NewFCW = _Constant(16, 0x037F); @@ -76,7 +76,7 @@ void OpDispatchBuilder::X87LDENVF64(OpcodeArgs) { roundingMode = _And(roundingMode, roundMask); _SetRoundingMode(roundingMode); _F80LoadFCW(NewFCW); - + _StoreContext(2, GPRClass, NewFCW, offsetof(FEXCore::Core::CPUState, FCW)); OrderedNode *MemLocation = _Add(Mem, _Constant(Size * 1)); @@ -184,7 +184,7 @@ void OpDispatchBuilder::FBLDF64(OpcodeArgs) { void OpDispatchBuilder::FBSTPF64(OpcodeArgs) { auto orig_top = GetX87Top(); auto data = _LoadContextIndexed(orig_top, 8, MMBaseOffset(), 16, FPRClass); - + OrderedNode *converted = _F80CVTTo(data, 8); converted = _F80BCDStore(converted); @@ -256,7 +256,7 @@ void OpDispatchBuilder::FSTF64(OpcodeArgs) { //Convert to 80-bit float auto result = _F80CVTTo(data, 8); StoreResult_WithOpSize(FPRClass, Op, Op->Dest, result, 10, 1); - } + } if ((Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) != 0) { // if we are popping then we must first mark this location as empty @@ -688,7 +688,10 @@ void OpDispatchBuilder::FCOMIF64(OpcodeArgs) { // Memory arg if constexpr (Integer) { arg = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); - b = _Float_FromGPR_S(8, 8, arg); + if(width == 16) { + arg = _Sext(16, arg); + } + b = _Float_FromGPR_S(8, width == 64 ? 8 : 4, arg); } else if constexpr (width == 32) { arg = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1); b = _Float_FToF(8, 4, arg); @@ -712,7 +715,7 @@ void OpDispatchBuilder::FCOMIF64(OpcodeArgs) { OrderedNode *HostFlag_CF = _GetHostFlag(Res, FCMP_FLAG_LT); OrderedNode *HostFlag_ZF = _GetHostFlag(Res, FCMP_FLAG_EQ); OrderedNode *HostFlag_Unordered = _GetHostFlag(Res, FCMP_FLAG_UNORDERED); - + HostFlag_CF = _Or(HostFlag_CF, HostFlag_Unordered); HostFlag_ZF = _Or(HostFlag_ZF, HostFlag_Unordered); From f156615a3a26a755b952feadd4a35280225bfbe1 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sun, 8 Jan 2023 11:04:28 -0800 Subject: [PATCH 2/4] unittests: Adds unittests to ensure FICOM works Both x80 and x64 variants. --- unittests/ASM/X87/DA_02.asm | 84 ++++++++++++++++++++++++++++ unittests/ASM/X87/DE_02.asm | 84 ++++++++++++++++++++++++++++ unittests/ASM/X87_F64/DA_02_F64.asm | 85 +++++++++++++++++++++++++++++ unittests/ASM/X87_F64/DE_02_F64.asm | 85 +++++++++++++++++++++++++++++ 4 files changed, 338 insertions(+) create mode 100644 unittests/ASM/X87/DA_02.asm create mode 100644 unittests/ASM/X87/DE_02.asm create mode 100644 unittests/ASM/X87_F64/DA_02_F64.asm create mode 100644 unittests/ASM/X87_F64/DE_02_F64.asm diff --git a/unittests/ASM/X87/DA_02.asm b/unittests/ASM/X87/DA_02.asm new file mode 100644 index 000000000..9d5672f04 --- /dev/null +++ b/unittests/ASM/X87/DA_02.asm @@ -0,0 +1,84 @@ +%ifdef CONFIG +{ + "RegData": { + "RSI": ["0x18"] + } +} +%endif + +mov rdx, 0xe0000000 +mov rsi, 0 + +; Matching positive-positive +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov eax, 1 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +ficomp dword [rdx + 8 * 1] + +; Get the status word +mov rax, 0 +fstsw ax +; Extract C3 to see if it was equal +shr ax, 14 +and ax, 1 +or rsi, rax +shl rsi, 1 + +; Matching negative-negative +mov rax, 0xbff0000000000000 ; -1.0 +mov [rdx + 8 * 0], rax +mov eax, -1 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +ficomp dword [rdx + 8 * 1] + +; Get the status word +mov rax, 0 +fstsw ax +; Extract C3 to see if it was equal +shr ax, 14 +and ax, 1 +or rsi, rax +shl rsi, 1 + +; Nonmatching negative-positive +mov rax, 0xbff0000000000000 ; -1.0 +mov [rdx + 8 * 0], rax +mov eax, 1 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +ficomp dword [rdx + 8 * 1] + +; Get the status word +mov rax, 0 +fstsw ax +; Extract C3 to see if it was equal +shr ax, 14 +and ax, 1 +or rsi, rax +shl rsi, 1 + +; Nonmatching positive-negative +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov eax, -1 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +ficomp dword [rdx + 8 * 1] + +; Get the status word +mov rax, 0 +fstsw ax +; Extract C3 to see if it was equal +shr ax, 14 +and ax, 1 +or rsi, rax +shl rsi, 1 + +hlt diff --git a/unittests/ASM/X87/DE_02.asm b/unittests/ASM/X87/DE_02.asm new file mode 100644 index 000000000..fdc0d0e1b --- /dev/null +++ b/unittests/ASM/X87/DE_02.asm @@ -0,0 +1,84 @@ +%ifdef CONFIG +{ + "RegData": { + "RSI": ["0x18"] + } +} +%endif + +mov rdx, 0xe0000000 +mov rsi, 0 + +; Matching positive-positive +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov ax, 1 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +ficomp word [rdx + 8 * 1] + +; Get the status word +mov rax, 0 +fstsw ax +; Extract C3 to see if it was equal +shr ax, 14 +and ax, 1 +or rsi, rax +shl rsi, 1 + +; Matching negative-negative +mov rax, 0xbff0000000000000 ; -1.0 +mov [rdx + 8 * 0], rax +mov ax, -1 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +ficomp word [rdx + 8 * 1] + +; Get the status word +mov rax, 0 +fstsw ax +; Extract C3 to see if it was equal +shr ax, 14 +and ax, 1 +or rsi, rax +shl rsi, 1 + +; Nonmatching negative-positive +mov rax, 0xbff0000000000000 ; -1.0 +mov [rdx + 8 * 0], rax +mov ax, 1 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +ficomp word [rdx + 8 * 1] + +; Get the status word +mov rax, 0 +fstsw ax +; Extract C3 to see if it was equal +shr ax, 14 +and ax, 1 +or rsi, rax +shl rsi, 1 + +; Nonmatching positive-negative +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov ax, -1 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +ficomp word [rdx + 8 * 1] + +; Get the status word +mov rax, 0 +fstsw ax +; Extract C3 to see if it was equal +shr ax, 14 +and ax, 1 +or rsi, rax +shl rsi, 1 + +hlt diff --git a/unittests/ASM/X87_F64/DA_02_F64.asm b/unittests/ASM/X87_F64/DA_02_F64.asm new file mode 100644 index 000000000..713446284 --- /dev/null +++ b/unittests/ASM/X87_F64/DA_02_F64.asm @@ -0,0 +1,85 @@ +%ifdef CONFIG +{ + "RegData": { + "RSI": ["0x18"] + }, + "Env": { "FEX_X87REDUCEDPRECISION" : "1" } +} +%endif + +mov rdx, 0xe0000000 +mov rsi, 0 + +; Matching positive-positive +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov eax, 1 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +ficomp dword [rdx + 8 * 1] + +; Get the status word +mov rax, 0 +fstsw ax +; Extract C3 to see if it was equal +shr ax, 14 +and ax, 1 +or rsi, rax +shl rsi, 1 + +; Matching negative-negative +mov rax, 0xbff0000000000000 ; -1.0 +mov [rdx + 8 * 0], rax +mov eax, -1 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +ficomp dword [rdx + 8 * 1] + +; Get the status word +mov rax, 0 +fstsw ax +; Extract C3 to see if it was equal +shr ax, 14 +and ax, 1 +or rsi, rax +shl rsi, 1 + +; Nonmatching negative-positive +mov rax, 0xbff0000000000000 ; -1.0 +mov [rdx + 8 * 0], rax +mov eax, 1 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +ficomp dword [rdx + 8 * 1] + +; Get the status word +mov rax, 0 +fstsw ax +; Extract C3 to see if it was equal +shr ax, 14 +and ax, 1 +or rsi, rax +shl rsi, 1 + +; Nonmatching positive-negative +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov eax, -1 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +ficomp dword [rdx + 8 * 1] + +; Get the status word +mov rax, 0 +fstsw ax +; Extract C3 to see if it was equal +shr ax, 14 +and ax, 1 +or rsi, rax +shl rsi, 1 + +hlt diff --git a/unittests/ASM/X87_F64/DE_02_F64.asm b/unittests/ASM/X87_F64/DE_02_F64.asm new file mode 100644 index 000000000..1fcbcca39 --- /dev/null +++ b/unittests/ASM/X87_F64/DE_02_F64.asm @@ -0,0 +1,85 @@ +%ifdef CONFIG +{ + "RegData": { + "RSI": ["0x18"] + }, + "Env": { "FEX_X87REDUCEDPRECISION" : "1" } +} +%endif + +mov rdx, 0xe0000000 +mov rsi, 0 + +; Matching positive-positive +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov ax, 1 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +ficomp word [rdx + 8 * 1] + +; Get the status word +mov rax, 0 +fstsw ax +; Extract C3 to see if it was equal +shr ax, 14 +and ax, 1 +or rsi, rax +shl rsi, 1 + +; Matching negative-negative +mov rax, 0xbff0000000000000 ; -1.0 +mov [rdx + 8 * 0], rax +mov ax, -1 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +ficomp word [rdx + 8 * 1] + +; Get the status word +mov rax, 0 +fstsw ax +; Extract C3 to see if it was equal +shr ax, 14 +and ax, 1 +or rsi, rax +shl rsi, 1 + +; Nonmatching negative-positive +mov rax, 0xbff0000000000000 ; -1.0 +mov [rdx + 8 * 0], rax +mov ax, 1 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +ficomp word [rdx + 8 * 1] + +; Get the status word +mov rax, 0 +fstsw ax +; Extract C3 to see if it was equal +shr ax, 14 +and ax, 1 +or rsi, rax +shl rsi, 1 + +; Nonmatching positive-negative +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov ax, -1 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +ficomp word [rdx + 8 * 1] + +; Get the status word +mov rax, 0 +fstsw ax +; Extract C3 to see if it was equal +shr ax, 14 +and ax, 1 +or rsi, rax +shl rsi, 1 + +hlt From c3c68afc3c38d9bc33db28bff7f430734cd877ab Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sun, 8 Jan 2023 13:23:40 -0800 Subject: [PATCH 3/4] Arm64: Fixes incorrect sign extension We were accidentally zero extending. --- External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp b/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp index 291b5d7f6..dd0ff6cd2 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp @@ -163,7 +163,7 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { const auto Src1 = GetReg(IROp->Args[0].ID()); if (Info.ABI == FABI_F80_I16) { - uxth(ARMEmitter::Size::i32Bit, ARMEmitter::Reg::r0, Src1); + sxth(ARMEmitter::Size::i32Bit, ARMEmitter::Reg::r0, Src1); } else { mov(ARMEmitter::Size::i32Bit, ARMEmitter::Reg::r0, Src1); @@ -310,7 +310,7 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { FillStaticRegs(); const auto Dst = GetReg(Node); - uxth(ARMEmitter::Size::i64Bit, Dst, ARMEmitter::Reg::r0); + sxth(ARMEmitter::Size::i64Bit, Dst, ARMEmitter::Reg::r0); } break; case FABI_I32_F80:{ From 676cf59198a62578c8b3f283462128e010e62b6a Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sun, 8 Jan 2023 13:28:17 -0800 Subject: [PATCH 4/4] Jit64: Fixes incorrect sign extension We were accidentally zero extending. --- .../FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp b/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp index d2d223238..d103c2b06 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp @@ -147,7 +147,12 @@ void X86JITCore::Op_Unhandled(IR::IROp_Header *IROp, IR::NodeID Node) { case FABI_F80_I32: { PushRegs(); - mov(edi, GetSrc(IROp->Args[0].ID())); + if (Info.ABI == FABI_F80_I16) { + movsx(rdi, GetSrc(IROp->Args[0].ID()).cvt16()); + } + else { + mov(edi, GetSrc(IROp->Args[0].ID())); + } call(qword [STATE + offsetof(FEXCore::Core::CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex])]); PopRegs(); @@ -223,7 +228,7 @@ void X86JITCore::Op_Unhandled(IR::IROp_Header *IROp, IR::NodeID Node) { PopRegs(); - movzx(GetDst(Node), ax); + movsx(GetDst(Node), ax); } break; case FABI_I32_F80:{