Skip to content

cmovCC destination operand access (ReadWrite) #778

@fvrmatteo

Description

@fvrmatteo

I was testing the differences with XED for a set of instructions and I stumbled upon the fact that all the cmovCC instructions involving 32-bits general purpose registers as destination operand are reporting a ReadWrite access instead of a Write access (as reported by the 16-bits and 64-bits variants).

This can be observed in the following output:

[INFO ] ✓ CMOVO ax, bx: iform=CMOVO_GPRv_GPRv code=Cmovo_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVO eax, ebx: iform=CMOVO_GPRv_GPRv code=Cmovo_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVO rax, rbx: iform=CMOVO_GPRv_GPRv code=Cmovo_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] ✓ CMOVNO ax, bx: iform=CMOVNO_GPRv_GPRv code=Cmovno_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVNO eax, ebx: iform=CMOVNO_GPRv_GPRv code=Cmovno_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVNO rax, rbx: iform=CMOVNO_GPRv_GPRv code=Cmovno_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] ✓ CMOVB ax, bx: iform=CMOVB_GPRv_GPRv code=Cmovb_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVB eax, ebx: iform=CMOVB_GPRv_GPRv code=Cmovb_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVB rax, rbx: iform=CMOVB_GPRv_GPRv code=Cmovb_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] ✓ CMOVAE ax, bx: iform=CMOVNB_GPRv_GPRv code=Cmovae_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVAE eax, ebx: iform=CMOVNB_GPRv_GPRv code=Cmovae_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVAE rax, rbx: iform=CMOVNB_GPRv_GPRv code=Cmovae_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] ✓ CMOVE ax, bx: iform=CMOVZ_GPRv_GPRv code=Cmove_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVE eax, ebx: iform=CMOVZ_GPRv_GPRv code=Cmove_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVE rax, rbx: iform=CMOVZ_GPRv_GPRv code=Cmove_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] ✓ CMOVNE ax, bx: iform=CMOVNZ_GPRv_GPRv code=Cmovne_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVNE eax, ebx: iform=CMOVNZ_GPRv_GPRv code=Cmovne_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVNE rax, rbx: iform=CMOVNZ_GPRv_GPRv code=Cmovne_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] ✓ CMOVBE ax, bx: iform=CMOVBE_GPRv_GPRv code=Cmovbe_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVBE eax, ebx: iform=CMOVBE_GPRv_GPRv code=Cmovbe_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVBE rax, rbx: iform=CMOVBE_GPRv_GPRv code=Cmovbe_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] ✓ CMOVA ax, bx: iform=CMOVNBE_GPRv_GPRv code=Cmova_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVA eax, ebx: iform=CMOVNBE_GPRv_GPRv code=Cmova_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVA rax, rbx: iform=CMOVNBE_GPRv_GPRv code=Cmova_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] ✓ CMOVS ax, bx: iform=CMOVS_GPRv_GPRv code=Cmovs_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVS eax, ebx: iform=CMOVS_GPRv_GPRv code=Cmovs_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVS rax, rbx: iform=CMOVS_GPRv_GPRv code=Cmovs_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] ✓ CMOVNS ax, bx: iform=CMOVNS_GPRv_GPRv code=Cmovns_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVNS eax, ebx: iform=CMOVNS_GPRv_GPRv code=Cmovns_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVNS rax, rbx: iform=CMOVNS_GPRv_GPRv code=Cmovns_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] ✓ CMOVP ax, bx: iform=CMOVP_GPRv_GPRv code=Cmovp_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVP eax, ebx: iform=CMOVP_GPRv_GPRv code=Cmovp_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVP rax, rbx: iform=CMOVP_GPRv_GPRv code=Cmovp_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] ✓ CMOVNP ax, bx: iform=CMOVNP_GPRv_GPRv code=Cmovnp_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVNP eax, ebx: iform=CMOVNP_GPRv_GPRv code=Cmovnp_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVNP rax, rbx: iform=CMOVNP_GPRv_GPRv code=Cmovnp_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] ✓ CMOVL ax, bx: iform=CMOVL_GPRv_GPRv code=Cmovl_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVL eax, ebx: iform=CMOVL_GPRv_GPRv code=Cmovl_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVL rax, rbx: iform=CMOVL_GPRv_GPRv code=Cmovl_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] ✓ CMOVGE ax, bx: iform=CMOVNL_GPRv_GPRv code=Cmovge_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVGE eax, ebx: iform=CMOVNL_GPRv_GPRv code=Cmovge_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVGE rax, rbx: iform=CMOVNL_GPRv_GPRv code=Cmovge_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] ✓ CMOVLE ax, bx: iform=CMOVLE_GPRv_GPRv code=Cmovle_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVLE eax, ebx: iform=CMOVLE_GPRv_GPRv code=Cmovle_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVLE rax, rbx: iform=CMOVLE_GPRv_GPRv code=Cmovle_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] ✓ CMOVG ax, bx: iform=CMOVNLE_GPRv_GPRv code=Cmovg_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVG eax, ebx: iform=CMOVNLE_GPRv_GPRv code=Cmovg_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVG rax, rbx: iform=CMOVNLE_GPRv_GPRv code=Cmovg_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] ✓ CMOVE ax, WORD PTR [rax]: iform=CMOVZ_GPRv_MEMv code=Cmove_r16_rm16 | op0: XED=W ICED=W | op1: XED=R ICED=R
[ERROR] ✗ CMOVE eax, DWORD PTR [rax]: iform=CMOVZ_GPRv_MEMv code=Cmove_r32_rm32 | op0: XED=W ICED=RW | op1: XED=R ICED=R
[INFO ] ✓ CMOVE rax, QWORD PTR [rax]: iform=CMOVZ_GPRv_MEMv code=Cmove_r64_rm64 | op0: XED=W ICED=W | op1: XED=R ICED=R
[INFO ] CMOVcc operand access test results: 34 passed, 17 failed

I see the info_table is reporting a difference for the 32-bits variant of the instruction.

I guess this might have something to do with the fact that 32-bits destination registers are implicitly zero-extended, but I wouldn't consider the destination register as ReadWrite anyway, although I know that iced-x86 is doing other unconventional decisions by default (e.g. #613). Is this intended or is it a bug?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions