From bb72f7f111abe0e01081506caa11afdf37b95857 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 12 Nov 2007 22:55:27 -0800 Subject: [PATCH] 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. --- disasm.c | 35 ++++++++++++++++++++++++++++++----- insns.dat | 9 +++++---- test/nop.asm | 14 ++++++++++++++ 3 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 test/nop.asm diff --git a/disasm.c b/disasm.c index b86c7f7..3554ca8 100644 --- a/disasm.c +++ b/disasm.c @@ -382,6 +382,7 @@ static int matches(const struct itemplate *t, uint8_t *data, } ins->condition = -1; ins->rex = prefix->rex; + memset(ins->prefixes, 0, sizeof ins->prefixes); if (t->flags & (segsize == 64 ? IF_NOLONG : IF_LONG)) return false; @@ -712,11 +713,13 @@ static int matches(const struct itemplate *t, uint8_t *data, case 0323: ins->rex |= REX_W; /* 64-bit only instruction */ osize = 64; + o_used = true; break; case 0324: if (!(ins->rex & (REX_P|REX_W)) || osize != 64) return false; + o_used = true; break; case 0330: @@ -779,7 +782,7 @@ static int matches(const struct itemplate *t, uint8_t *data, case 0367: if (!prefix->asp) return false; - o_used = true; + a_used = true; break; default: @@ -809,10 +812,26 @@ static int matches(const struct itemplate *t, uint8_t *data, return false; ins->prefixes[PPS_LREP] = drep; } - if (!o_used && osize == ((segsize == 16) ? 32 : 16)) { - if (ins->prefixes[PPS_OSIZE]) - return false; - ins->prefixes[PPS_OSIZE] = osize == 16 ? P_O16 : P_O32; + 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]) + return false; + ins->prefixes[PPS_OSIZE] = pfx; + } } if (!a_used && asize != segsize) { if (ins->prefixes[PPS_ASIZE]) @@ -1006,12 +1025,18 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, case P_A32: slen += snprintf(output + slen, outbufsize - slen, "a32 "); break; + case P_A64: + slen += snprintf(output + slen, outbufsize - slen, "a64 "); + break; case P_O16: slen += snprintf(output + slen, outbufsize - slen, "o16 "); break; case P_O32: slen += snprintf(output + slen, outbufsize - slen, "o32 "); break; + case P_O64: + slen += snprintf(output + slen, outbufsize - slen, "o64 "); + break; default: break; } diff --git a/insns.dat b/insns.dat index f54d6cc..fa04d12 100644 --- a/insns.dat +++ b/insns.dat @@ -848,7 +848,7 @@ PADDUSW mmxreg,mmxrm \2\x0F\xDD\110 PENT,MMX,SM PADDW mmxreg,mmxrm \2\x0F\xFD\110 PENT,MMX,SM PAND mmxreg,mmxrm \2\x0F\xDB\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 PAVGUSB mmxreg,mmxrm \2\x0F\x0F\110\01\xBF PENT,3DNOW,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 XCHG reg_ax,reg16 \320\11\x90 8086 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 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_rax,reg_rax \323\1\x90 X64 XCHG reg8,mem \1\x86\110 8086,SM XCHG reg8,reg8 \1\x86\110 8086 XCHG reg16,mem \320\1\x87\110 8086,SM diff --git a/test/nop.asm b/test/nop.asm new file mode 100644 index 0000000..3dabaa0 --- /dev/null +++ b/test/nop.asm @@ -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 -- 2.7.4