Merge pull request #3504 from Sonicadvance1/fix_loop_a16

OpcodeDispatcher: Fixes 32-bit mode LOOP RCX register usage
This commit is contained in:
Ryan Houdek authored and GitHub committed 2024-03-25 12:18:14 -07:00
commit 76983476b9
3 files changed
+60 -2

No files matched your search

@@ -1058,13 +1058,19 @@ void OpDispatchBuilder::LoopOp(OpcodeArgs) {
BlockSetRIP = true;
uint32_t SrcSize = (Op->Flags & X86Tables::DecodeFlags::FLAG_ADDRESS_SIZE) ? 4 : 8;
auto OpSize = SrcSize == 8 ? OpSize::i64Bit : OpSize::i32Bit;
if (!CTX->Config.Is64BitMode) {
// RCX size is 32-bit or 16-bit when executing in 32-bit mode.
SrcSize >>= 1;
OpSize = OpSize::i32Bit;
}
LOGMAN_THROW_A_FMT(Op->Src[1].IsLiteral(), "Src1 needs to be literal here");
uint64_t Target = Op->PC + Op->InstSize + Op->Src[1].Data.Literal.Value;
auto OpSize = SrcSize == 8 ? OpSize::i64Bit : OpSize::i32Bit;
OrderedNode *CondReg = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags);
OrderedNode *CondReg = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], SrcSize, Op->Flags);
CondReg = _Sub(OpSize, CondReg, _Constant(SrcSize * 8, 1));
StoreResult(GPRClass, Op, Op->Src[0], CondReg, -1);
@@ -0,0 +1,27 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0x0000000000000001",
"RBX": "0x0000000000010001"
},
"Mode": "32BIT"
}
%endif
; FEX-Emu had a bug where a16 loop instructions weren't treating the input RCX register as 16-bit.
; Effectively always treating it as 32-bit.
; Little test that operates at 16-bit and 32-bit sizes to ensure it is correctly handled.
mov eax, 0
mov ebx, 0
mov ecx, 0x0001_0001
.test:
inc eax
a16 loop .test
mov ecx, 0x0001_0001
.test2:
inc ebx
a32 loop .test2
hlt
@@ -0,0 +1,25 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0x0000000000010001",
"RBX": "0x0000000000000001"
}
}
%endif
; FEX-Emu had a bug in the 32-bit implementation of LOOP where it didn't handle 16-bit RCX correctly.
; For test coverage on the 64-bit side, ensure that both 64-bit and 32-bit operation works correctly.
mov rax, 0
mov rbx, 0
mov rcx, 0x0001_0001
.test:
inc rax
a64 loop .test
mov rcx, 0x1_0000_0001
.test2:
inc rbx
a32 loop .test2
hlt