diff --git a/arch/X86/X86Mapping.c b/arch/X86/X86Mapping.c index ea3dd72848..e26f4dd83e 100644 --- a/arch/X86/X86Mapping.c +++ b/arch/X86/X86Mapping.c @@ -957,6 +957,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id) case X86_INS_LOOP: case X86_INS_LOOPE: case X86_INS_LOOPNE: + // The instruction pointer register follows the mode. switch (h->mode) { default: break; @@ -969,24 +970,30 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id) insn->detail->regs_write, insn->detail->regs_write_count, X86_REG_EIP, X86_REG_IP); + break; + case CS_MODE_64: arr_replace( insn->detail->regs_read, insn->detail->regs_read_count, - X86_REG_ECX, X86_REG_CX); + X86_REG_EIP, X86_REG_RIP); arr_replace( insn->detail->regs_write, insn->detail->regs_write_count, - X86_REG_ECX, X86_REG_CX); + X86_REG_EIP, X86_REG_RIP); break; - case CS_MODE_64: + } + // The loop counter register follows the effective address + // size, which a 0x67 address-size prefix can override. + if (insn->detail->x86.addr_size == 2) { arr_replace( insn->detail->regs_read, insn->detail->regs_read_count, - X86_REG_EIP, X86_REG_RIP); + X86_REG_ECX, X86_REG_CX); arr_replace( insn->detail->regs_write, insn->detail->regs_write_count, - X86_REG_EIP, X86_REG_RIP); + X86_REG_ECX, X86_REG_CX); + } else if (insn->detail->x86.addr_size == 8) { arr_replace( insn->detail->regs_read, insn->detail->regs_read_count, @@ -995,7 +1002,6 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id) insn->detail->regs_write, insn->detail->regs_write_count, X86_REG_ECX, X86_REG_RCX); - break; } } diff --git a/tests/details/x86.yaml b/tests/details/x86.yaml index c9e44ef3c5..9d9879690a 100644 --- a/tests/details/x86.yaml +++ b/tests/details/x86.yaml @@ -6053,8 +6053,8 @@ test_cases: x86: prefix: [ X86_PREFIX_0, X86_PREFIX_0, X86_PREFIX_0, X86_PREFIX_ADDRSIZE ] opcode: [ 0xe2, 0x00, 0x00, 0x00 ] - regs_read: [ rip, rcx ] - regs_write: [ rip, rcx ] # BUG: should be ecx + regs_read: [ rip, ecx ] + regs_write: [ rip, ecx ] - asm_text: "loope 0x34" details: @@ -6081,8 +6081,8 @@ test_cases: prefix: [ X86_PREFIX_0, X86_PREFIX_0, X86_PREFIX_0, X86_PREFIX_ADDRSIZE ] opcode: [ 0xe1, 0x00, 0x00, 0x00 ] eflags: [ X86_EFLAGS_TEST_ZF ] - regs_read: [ rip, rcx, rflags ] - regs_write: [ rip, rcx ] # BUG: should be ecx + regs_read: [ rip, ecx, rflags ] + regs_write: [ rip, ecx ] - asm_text: "loopne 0x34" details: @@ -6109,8 +6109,8 @@ test_cases: prefix: [ X86_PREFIX_0, X86_PREFIX_0, X86_PREFIX_0, X86_PREFIX_ADDRSIZE ] opcode: [ 0xe0, 0x00, 0x00, 0x00 ] eflags: [ X86_EFLAGS_TEST_ZF ] - regs_read: [ rip, rcx, rflags ] - regs_write: [ rip, rcx ] # BUG: should be ecx + regs_read: [ rip, ecx, rflags ] + regs_write: [ rip, ecx ] - input: