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 97e586eb9..7e39345e8 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp @@ -1025,7 +1025,7 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const shr(GetDst(Node).cvt16(), cl); break; case 4: - movzx(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); + mov(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); shr(GetDst(Node), cl); break; case 8: @@ -1054,7 +1054,7 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const shl(GetDst(Node).cvt16(), cl); break; case 4: - movzx(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); + mov(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); shl(GetDst(Node), cl); break; case 8: diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 6a1642efd..466020eb5 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -1360,7 +1360,15 @@ void OpDispatchBuilder::BTOp(OpcodeArgs) { OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[SrcIndex], Op->Flags, -1); if (Op->Dest.TypeNone.Type == FEXCore::X86Tables::DecodedOperand::TYPE_GPR) { OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, -1); - Result = _Lshr(Dest, Src); + + uint32_t Size = GetSrcSize(Op); + uint32_t Mask = Size * 8 - 1; + OrderedNode *SizeMask = _Constant(Mask); + + // Get the bit selection from the src + OrderedNode *BitSelect = _And(Src, SizeMask); + + Result = _Lshr(Dest, BitSelect); } else { // Load the address to the memory location @@ -1395,7 +1403,6 @@ void OpDispatchBuilder::BTROp(OpcodeArgs) { OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[SrcIndex], Op->Flags, -1); if (Op->Dest.TypeNone.Type == FEXCore::X86Tables::DecodedOperand::TYPE_GPR) { OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, -1); - Result = _Lshr(Dest, Src); uint32_t Size = GetSrcSize(Op); uint32_t Mask = Size * 8 - 1; @@ -1404,6 +1411,8 @@ void OpDispatchBuilder::BTROp(OpcodeArgs) { // Get the bit selection from the src OrderedNode *BitSelect = _And(Src, SizeMask); + Result = _Lshr(Dest, BitSelect); + OrderedNode *BitMask = _Lshl(_Constant(1), BitSelect); BitMask = _Not(BitMask); Dest = _And(Dest, BitMask); @@ -1446,7 +1455,6 @@ void OpDispatchBuilder::BTSOp(OpcodeArgs) { OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[SrcIndex], Op->Flags, -1); if (Op->Dest.TypeNone.Type == FEXCore::X86Tables::DecodedOperand::TYPE_GPR) { OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, -1); - Result = _Lshr(Dest, Src); uint32_t Size = GetSrcSize(Op); uint32_t Mask = Size * 8 - 1; @@ -1455,6 +1463,8 @@ void OpDispatchBuilder::BTSOp(OpcodeArgs) { // Get the bit selection from the src OrderedNode *BitSelect = _And(Src, SizeMask); + Result = _Lshr(Dest, BitSelect); + OrderedNode *BitMask = _Lshl(_Constant(1), BitSelect); Dest = _Or(Dest, BitMask); StoreResult(GPRClass, Op, Dest, -1); @@ -1495,7 +1505,6 @@ void OpDispatchBuilder::BTCOp(OpcodeArgs) { OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[SrcIndex], Op->Flags, -1); if (Op->Dest.TypeNone.Type == FEXCore::X86Tables::DecodedOperand::TYPE_GPR) { OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, -1); - Result = _Lshr(Dest, Src); uint32_t Size = GetSrcSize(Op); uint32_t Mask = Size * 8 - 1; @@ -1504,6 +1513,8 @@ void OpDispatchBuilder::BTCOp(OpcodeArgs) { // Get the bit selection from the src OrderedNode *BitSelect = _And(Src, SizeMask); + Result = _Lshr(Dest, BitSelect); + OrderedNode *BitMask = _Lshl(_Constant(1), BitSelect); Dest = _Xor(Dest, BitMask); StoreResult(GPRClass, Op, Dest, -1); diff --git a/unittests/ASM/Secondary/08_66_04_2.asm b/unittests/ASM/Secondary/08_66_04_2.asm new file mode 100644 index 000000000..ece0e1f1e --- /dev/null +++ b/unittests/ASM/Secondary/08_66_04_2.asm @@ -0,0 +1,56 @@ +%ifdef CONFIG +{ + "RegData": { + "R15": "0x4" + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +%macro cfmerge 0 + +; Get CF +sbb r14, r14 +and r14, 1 + +; Merge in to results +shl r15, 1 +or r15, r14 + +%endmacro + +mov rdx, 0xe0000000 + +mov rax, 0xFFFFFFFF80000002 +mov [rdx + 8 * 0], rax +mov [rdx + 8 * 1], rax +mov [rdx + 8 * 2], rax +mov rax, 0x01 +mov [rdx + 8 * 3], eax +mov rax, 0x0 +mov [rdx + 8 * 3 + 4], eax + +xor r15, r15 ; Will contain our results + +movzx r12, word [rdx] +db 0x66 ; Prefix with 66. Shouldn't change behaviour +bt r12w, 1 +cfmerge + +mov r13, 32 +mov r12d, dword [rdx] + +db 0x66 ; Prefix with 66. Shouldn't change behaviour +bt r12d, r13d +cfmerge + +mov r12, qword [rdx] +db 0x66 ; Prefix with 66. Shouldn't change behaviour +bt r12, 64 * 3 +cfmerge + +hlt + + diff --git a/unittests/ASM/Secondary/08_F2_04_2.asm b/unittests/ASM/Secondary/08_F2_04_2.asm new file mode 100644 index 000000000..d746454d4 --- /dev/null +++ b/unittests/ASM/Secondary/08_F2_04_2.asm @@ -0,0 +1,55 @@ +%ifdef CONFIG +{ + "RegData": { + "R15": "0x4" + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +%macro cfmerge 0 + +; Get CF +sbb r14, r14 +and r14, 1 + +; Merge in to results +shl r15, 1 +or r15, r14 + +%endmacro + +mov rdx, 0xe0000000 + +mov rax, 0xFFFFFFFF80000002 +mov [rdx + 8 * 0], rax +mov [rdx + 8 * 1], rax +mov [rdx + 8 * 2], rax +mov rax, 0x01 +mov [rdx + 8 * 3], eax +mov rax, 0x0 +mov [rdx + 8 * 3 + 4], eax + +xor r15, r15 ; Will contain our results + +movzx r12, word [rdx] +db 0xF2 ; Prefix with F2. Shouldn't change behaviour +bt r12w, 1 +cfmerge + +mov r13, 32 +mov r12d, dword [rdx] +db 0xF2 ; Prefix with F2. Shouldn't change behaviour +bt r12d, r13d +cfmerge + +mov r12, qword [rdx] +db 0xF2 ; Prefix with F2. Shouldn't change behaviour +bt r12, 64 * 3 +cfmerge + +hlt + + diff --git a/unittests/ASM/Secondary/08_F3_04_2.asm b/unittests/ASM/Secondary/08_F3_04_2.asm new file mode 100644 index 000000000..bdf4ca889 --- /dev/null +++ b/unittests/ASM/Secondary/08_F3_04_2.asm @@ -0,0 +1,55 @@ +%ifdef CONFIG +{ + "RegData": { + "R15": "0x4" + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +%macro cfmerge 0 + +; Get CF +sbb r14, r14 +and r14, 1 + +; Merge in to results +shl r15, 1 +or r15, r14 + +%endmacro + +mov rdx, 0xe0000000 + +mov rax, 0xFFFFFFFF80000002 +mov [rdx + 8 * 0], rax +mov [rdx + 8 * 1], rax +mov [rdx + 8 * 2], rax +mov rax, 0x01 +mov [rdx + 8 * 3], eax +mov rax, 0x0 +mov [rdx + 8 * 3 + 4], eax + +xor r15, r15 ; Will contain our results + +movzx r12, word [rdx] +db 0xF3 ; Prefix with F3. Shouldn't change behaviour +bt r12w, 1 +cfmerge + +mov r13, 32 +mov r12d, dword [rdx] +db 0xF3 ; Prefix with F3. Shouldn't change behaviour +bt r12d, r13d +cfmerge + +mov r12, qword [rdx] +db 0xF3 ; Prefix with F3. Shouldn't change behaviour +bt r12, 64 * 3 +cfmerge + +hlt + + diff --git a/unittests/ASM/Secondary/08_XX_04_2.asm b/unittests/ASM/Secondary/08_XX_04_2.asm new file mode 100644 index 000000000..550769168 --- /dev/null +++ b/unittests/ASM/Secondary/08_XX_04_2.asm @@ -0,0 +1,52 @@ +%ifdef CONFIG +{ + "RegData": { + "R15": "0x4" + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +%macro cfmerge 0 + +; Get CF +sbb r14, r14 +and r14, 1 + +; Merge in to results +shl r15, 1 +or r15, r14 + +%endmacro + +mov rdx, 0xe0000000 + +mov rax, 0xFFFFFFFF80000002 +mov [rdx + 8 * 0], rax +mov [rdx + 8 * 1], rax +mov [rdx + 8 * 2], rax +mov rax, 0x01 +mov [rdx + 8 * 3], eax +mov rax, 0x0 +mov [rdx + 8 * 3 + 4], eax + +xor r15, r15 ; Will contain our results + +movzx r12, word [rdx] +bt r12w, 1 +cfmerge + +mov r13, 32 +mov r12d, dword [rdx] +bt r12d, r13d +cfmerge + +mov r12, qword [rdx] +bt r12, 64 * 3 +cfmerge + +hlt + + diff --git a/unittests/ASM/Secondary/08_XX_05_2.asm b/unittests/ASM/Secondary/08_XX_05_2.asm new file mode 100644 index 000000000..909d4a8c7 --- /dev/null +++ b/unittests/ASM/Secondary/08_XX_05_2.asm @@ -0,0 +1,64 @@ +%ifdef CONFIG +{ + "RegData": { + "R15": "0x35" + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +%macro cfmerge 0 + +; Get CF +sbb r14, r14 +and r14, 1 + +; Merge in to results +shl r15, 1 +or r15, r14 + +%endmacro + +mov rdx, 0xe0000000 + +mov rax, 0xFFFFFFFF80000002 +mov [rdx + 8 * 0], rax +mov [rdx + 8 * 1], rax +mov [rdx + 8 * 2], rax +mov rax, 0x01 +mov [rdx + 8 * 3], eax +mov rax, 0x0 +mov [rdx + 8 * 3 + 4], eax + +xor r15, r15 ; Will contain our results +movzx r12, word [rdx] + +; Test and set +bts r12w, 1 +cfmerge + +; Ensure it is set +bt r12w, 1 +cfmerge + +mov r13, 32 +mov r12d, dword [rdx] + +bts r12d, r13d +cfmerge + +bt r12d, r13d +cfmerge + +mov r12, qword [rdx] +bts r12, 64 * 3 +cfmerge + +bt r12, 64 * 3 +cfmerge + +hlt + + diff --git a/unittests/ASM/Secondary/08_XX_06_2.asm b/unittests/ASM/Secondary/08_XX_06_2.asm new file mode 100644 index 000000000..cc2839136 --- /dev/null +++ b/unittests/ASM/Secondary/08_XX_06_2.asm @@ -0,0 +1,65 @@ +%ifdef CONFIG +{ + "RegData": { + "R15": "0x20" + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +%macro cfmerge 0 + +; Get CF +sbb r14, r14 +and r14, 1 + +; Merge in to results +shl r15, 1 +or r15, r14 + +%endmacro + +mov rdx, 0xe0000000 + +mov rax, 0xFFFFFFFF80000002 +mov [rdx + 8 * 0], rax +mov [rdx + 8 * 1], rax +mov [rdx + 8 * 2], rax +mov rax, 0x01 +mov [rdx + 8 * 3], eax +mov rax, 0x0 +mov [rdx + 8 * 3 + 4], eax + +xor r15, r15 ; Will contain our results + +movzx r12, word [rdx] + +; Test and set +btr r12w, 1 +cfmerge + +; Ensure it is set +bt r12w, 1 +cfmerge + +mov r13, 32 +mov r12d, dword [rdx] + +btr r12d, r13d +cfmerge + +bt r12d, r13d +cfmerge + +mov r12, qword [rdx] +btr r12, 64 * 3 +cfmerge + +bt r12, 64 * 3 +cfmerge + +hlt + + diff --git a/unittests/ASM/Secondary/08_XX_07_2.asm b/unittests/ASM/Secondary/08_XX_07_2.asm new file mode 100644 index 000000000..d07ebfd3e --- /dev/null +++ b/unittests/ASM/Secondary/08_XX_07_2.asm @@ -0,0 +1,64 @@ +%ifdef CONFIG +{ + "RegData": { + "R15": "0x25" + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +%macro cfmerge 0 + +; Get CF +sbb r14, r14 +and r14, 1 + +; Merge in to results +shl r15, 1 +or r15, r14 + +%endmacro + +mov rdx, 0xe0000000 + +mov rax, 0xFFFFFFFF80000002 +mov [rdx + 8 * 0], rax +mov [rdx + 8 * 1], rax +mov [rdx + 8 * 2], rax +mov rax, 0x01 +mov [rdx + 8 * 3], eax +mov rax, 0x0 +mov [rdx + 8 * 3 + 4], eax + +xor r15, r15 ; Will contain our results + +movzx r12, word [rdx] + +; Test and set +btc r12w, 1 +cfmerge + +; Ensure it is set +bt r12w, 1 +cfmerge + +mov r13, 32 +mov r12d, dword [rdx] + +btc r12d, r13d +cfmerge + +bt r12d, r13d +cfmerge + +mov r12, qword [rdx] +btc r12, 64 * 3 +cfmerge + +bt r12, 64 * 3 +cfmerge + +hlt +