Un-special-case "xchg rax,rax"; disassemble o64
Un-special-case "xchg rax,rax"; allow it to be encoded as 48 90 for orthogonality's sake. It's a no-op, to be sure, but so are many other instructions. "xchg eax,eax" is still special-cased in 64-bit mode since it is not a no-op; unadorned opcode 90 is now simply "nop" and nothing else. Make the disassembler detect unused REX.W and display them as an "o64" prefix.
This commit is contained in:
parent
fb0c90cdbe
commit
bb72f7f111
3 changed files with 49 additions and 9 deletions
31
disasm.c
31
disasm.c
|
@ -382,6 +382,7 @@ static int matches(const struct itemplate *t, uint8_t *data,
|
||||||
}
|
}
|
||||||
ins->condition = -1;
|
ins->condition = -1;
|
||||||
ins->rex = prefix->rex;
|
ins->rex = prefix->rex;
|
||||||
|
memset(ins->prefixes, 0, sizeof ins->prefixes);
|
||||||
|
|
||||||
if (t->flags & (segsize == 64 ? IF_NOLONG : IF_LONG))
|
if (t->flags & (segsize == 64 ? IF_NOLONG : IF_LONG))
|
||||||
return false;
|
return false;
|
||||||
|
@ -712,11 +713,13 @@ static int matches(const struct itemplate *t, uint8_t *data,
|
||||||
case 0323:
|
case 0323:
|
||||||
ins->rex |= REX_W; /* 64-bit only instruction */
|
ins->rex |= REX_W; /* 64-bit only instruction */
|
||||||
osize = 64;
|
osize = 64;
|
||||||
|
o_used = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0324:
|
case 0324:
|
||||||
if (!(ins->rex & (REX_P|REX_W)) || osize != 64)
|
if (!(ins->rex & (REX_P|REX_W)) || osize != 64)
|
||||||
return false;
|
return false;
|
||||||
|
o_used = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0330:
|
case 0330:
|
||||||
|
@ -779,7 +782,7 @@ static int matches(const struct itemplate *t, uint8_t *data,
|
||||||
case 0367:
|
case 0367:
|
||||||
if (!prefix->asp)
|
if (!prefix->asp)
|
||||||
return false;
|
return false;
|
||||||
o_used = true;
|
a_used = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -809,10 +812,26 @@ static int matches(const struct itemplate *t, uint8_t *data,
|
||||||
return false;
|
return false;
|
||||||
ins->prefixes[PPS_LREP] = drep;
|
ins->prefixes[PPS_LREP] = drep;
|
||||||
}
|
}
|
||||||
if (!o_used && osize == ((segsize == 16) ? 32 : 16)) {
|
if (!o_used) {
|
||||||
|
if (osize != ((segsize == 16) ? 16 : 32)) {
|
||||||
|
enum prefixes pfx = 0;
|
||||||
|
|
||||||
|
switch (osize) {
|
||||||
|
case 16:
|
||||||
|
pfx = P_O16;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
pfx = P_O32;
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
pfx = P_O64;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (ins->prefixes[PPS_OSIZE])
|
if (ins->prefixes[PPS_OSIZE])
|
||||||
return false;
|
return false;
|
||||||
ins->prefixes[PPS_OSIZE] = osize == 16 ? P_O16 : P_O32;
|
ins->prefixes[PPS_OSIZE] = pfx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!a_used && asize != segsize) {
|
if (!a_used && asize != segsize) {
|
||||||
if (ins->prefixes[PPS_ASIZE])
|
if (ins->prefixes[PPS_ASIZE])
|
||||||
|
@ -1006,12 +1025,18 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
|
||||||
case P_A32:
|
case P_A32:
|
||||||
slen += snprintf(output + slen, outbufsize - slen, "a32 ");
|
slen += snprintf(output + slen, outbufsize - slen, "a32 ");
|
||||||
break;
|
break;
|
||||||
|
case P_A64:
|
||||||
|
slen += snprintf(output + slen, outbufsize - slen, "a64 ");
|
||||||
|
break;
|
||||||
case P_O16:
|
case P_O16:
|
||||||
slen += snprintf(output + slen, outbufsize - slen, "o16 ");
|
slen += snprintf(output + slen, outbufsize - slen, "o16 ");
|
||||||
break;
|
break;
|
||||||
case P_O32:
|
case P_O32:
|
||||||
slen += snprintf(output + slen, outbufsize - slen, "o32 ");
|
slen += snprintf(output + slen, outbufsize - slen, "o32 ");
|
||||||
break;
|
break;
|
||||||
|
case P_O64:
|
||||||
|
slen += snprintf(output + slen, outbufsize - slen, "o64 ");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -848,7 +848,7 @@ PADDUSW mmxreg,mmxrm \2\x0F\xDD\110 PENT,MMX,SM
|
||||||
PADDW mmxreg,mmxrm \2\x0F\xFD\110 PENT,MMX,SM
|
PADDW mmxreg,mmxrm \2\x0F\xFD\110 PENT,MMX,SM
|
||||||
PAND mmxreg,mmxrm \2\x0F\xDB\110 PENT,MMX,SM
|
PAND mmxreg,mmxrm \2\x0F\xDB\110 PENT,MMX,SM
|
||||||
PANDN mmxreg,mmxrm \2\x0F\xDF\110 PENT,MMX,SM
|
PANDN mmxreg,mmxrm \2\x0F\xDF\110 PENT,MMX,SM
|
||||||
PAUSE void \333\1\x90 8086
|
PAUSE void \314\333\1\x90 8086
|
||||||
PAVEB mmxreg,mmxrm \2\x0F\x50\110 PENT,MMX,SM,CYRIX
|
PAVEB mmxreg,mmxrm \2\x0F\x50\110 PENT,MMX,SM,CYRIX
|
||||||
PAVGUSB mmxreg,mmxrm \2\x0F\x0F\110\01\xBF PENT,3DNOW,SM
|
PAVGUSB mmxreg,mmxrm \2\x0F\x0F\110\01\xBF PENT,3DNOW,SM
|
||||||
PCMPEQB mmxreg,mmxrm \2\x0F\x74\110 PENT,MMX,SM
|
PCMPEQB mmxreg,mmxrm \2\x0F\x74\110 PENT,MMX,SM
|
||||||
|
@ -1271,12 +1271,13 @@ XBTS reg32,mem \321\2\x0F\xA6\110 386,SD,UNDOC,ND
|
||||||
XBTS reg32,reg32 \321\2\x0F\xA6\110 386,UNDOC,ND
|
XBTS reg32,reg32 \321\2\x0F\xA6\110 386,UNDOC,ND
|
||||||
XCHG reg_ax,reg16 \320\11\x90 8086
|
XCHG reg_ax,reg16 \320\11\x90 8086
|
||||||
XCHG reg_eax,reg32na \321\11\x90 386
|
XCHG reg_eax,reg32na \321\11\x90 386
|
||||||
XCHG reg_rax,reg64na \324\11\x90 X64
|
XCHG reg_rax,reg64 \324\11\x90 X64
|
||||||
XCHG reg16,reg_ax \320\10\x90 8086
|
XCHG reg16,reg_ax \320\10\x90 8086
|
||||||
XCHG reg32na,reg_eax \321\10\x90 386
|
XCHG reg32na,reg_eax \321\10\x90 386
|
||||||
XCHG reg64na,reg_rax \324\10\x90 X64
|
XCHG reg64,reg_rax \324\10\x90 X64
|
||||||
|
; This must be NOLONG since opcode 90 is NOP, and in 64-bit mode
|
||||||
|
; "xchg eax,eax" is *not* a NOP.
|
||||||
XCHG reg_eax,reg_eax \321\1\x90 386,NOLONG
|
XCHG reg_eax,reg_eax \321\1\x90 386,NOLONG
|
||||||
XCHG reg_rax,reg_rax \323\1\x90 X64
|
|
||||||
XCHG reg8,mem \1\x86\110 8086,SM
|
XCHG reg8,mem \1\x86\110 8086,SM
|
||||||
XCHG reg8,reg8 \1\x86\110 8086
|
XCHG reg8,reg8 \1\x86\110 8086
|
||||||
XCHG reg16,mem \320\1\x87\110 8086,SM
|
XCHG reg16,mem \320\1\x87\110 8086,SM
|
||||||
|
|
14
test/nop.asm
Normal file
14
test/nop.asm
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
bits 64
|
||||||
|
|
||||||
|
nop
|
||||||
|
o64 nop
|
||||||
|
pause
|
||||||
|
o64 pause
|
||||||
|
|
||||||
|
xchg ax,ax
|
||||||
|
xchg eax,eax
|
||||||
|
xchg rax,rax
|
||||||
|
|
||||||
|
rep xchg ax,ax
|
||||||
|
rep xchg eax,eax
|
||||||
|
rep xchg rax,rax
|
Loading…
Reference in a new issue