diff --git a/decode.c b/decode.c index 0129fb4..ad880de 100644 --- a/decode.c +++ b/decode.c @@ -608,6 +608,21 @@ fd_decode(const uint8_t* buffer, size_t len_sz, int mode_int, uintptr_t address, } } + if (instr->type == FDI_XCHG_NOP) + { + // Only 4890, 90, and 6690 are true NOPs. + if (instr->operands[0].reg == 0 && instr->operands[1].reg == 0) + { + instr->operands[0].type = FD_OT_NONE; + instr->operands[1].type = FD_OT_NONE; + instr->type = FDI_NOP; + } + else + { + instr->type = FDI_XCHG; + } + } + if ((prefixes & PREFIX_LOCK) && !desc->lock) return FD_ERR_UD; if ((prefixes & PREFIX_LOCK) && instr->operands[0].type != FD_OT_MEM) diff --git a/instrs.txt b/instrs.txt index 64d9445..5c6926d 100644 --- a/instrs.txt +++ b/instrs.txt @@ -143,7 +143,9 @@ 8d RM GP GP - - LEA MUSTMEM 8e RM SREG GP - - MOV_G2S 8f/0 M GP - - - POP DEF64 -90 NP - - - - NOP +# Against frequent belief, only, XCHG (r/e)AX, (r)AX with 90 is NOP. +# As a lacking REX.B cannot be specified here, this is hardcoded. +90 OA GP GP - - XCHG_NOP 91 OA GP GP - - XCHG 92 OA GP GP - - XCHG 93 OA GP GP - - XCHG diff --git a/tests/prefixes.txt b/tests/prefixes.txt index 71fda57..dc6eb5d 100644 --- a/tests/prefixes.txt +++ b/tests/prefixes.txt @@ -11,3 +11,6 @@ decode f2660f10c1 [SSE_MOVSD reg8:r0 reg8:r1] decode f3660f10c1 [SSE_MOVSS reg4:r0 reg4:r1] decode f3f2660f10c1 [SSE_MOVSD reg8:r0 reg8:r1] decode f266f3660f10c1 [SSE_MOVSS reg4:r0 reg4:r1] +decode64 4890 [NOP] +decode64 4990 [XCHG reg8:r8 reg8:r0] +decode64 6690 [NOP]