X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=opcodes%2Fi386-dis.c;h=40be2261daed51676833480478bf13ce266c2ce1;hb=1596541188b1a4080ab7bce6578c09626193dfd0;hp=a2a5a06f72612bf9fff4814ddd3e2d5811ac93bf;hpb=4cc91dba12d0461b0fd31b02bdb53c1a2ee87088;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index a2a5a06f72..40be2261da 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu) July 1988 @@ -35,7 +35,7 @@ #include "sysdep.h" #include "opintl.h" -#define MAXLEN 20 +#define MAXLEN 15 #include @@ -88,16 +88,21 @@ static void OP_EX (int, int); static void OP_MS (int, int); static void OP_XS (int, int); static void OP_M (int, int); +static void OP_VMX (int, int); static void OP_0fae (int, int); static void OP_0f07 (int, int); -static void NOP_Fixup (int, int); +static void NOP_Fixup1 (int, int); +static void NOP_Fixup2 (int, int); static void OP_3DNowSuffix (int, int); static void OP_SIMD_Suffix (int, int); static void SIMD_Fixup (int, int); static void PNI_Fixup (int, int); +static void SVME_Fixup (int, int); static void INVLPG_Fixup (int, int); static void BadOp (void); static void SEG_Fixup (int, int); +static void VMX_Fixup (int, int); +static void REP_Fixup (int, int); struct dis_private { /* Points to first byte not fetched. */ @@ -112,8 +117,14 @@ struct dis_private { when we can. */ #define FWAIT_OPCODE (0x9b) -/* Set to 1 for 64bit mode disassembly. */ -static int mode_64bit; +enum address_mode +{ + mode_16bit, + mode_32bit, + mode_64bit +}; + +enum address_mode address_mode; /* Flags for the prefixes for the current instruction. See below. */ static int prefixes; @@ -170,10 +181,13 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) struct dis_private *priv = (struct dis_private *) info->private_data; bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer); - status = (*info->read_memory_func) (start, - priv->max_fetched, - addr - priv->max_fetched, - info); + if (addr <= priv->the_buffer + MAXLEN) + status = (*info->read_memory_func) (start, + priv->max_fetched, + addr - priv->max_fetched, + info); + else + status = -1; if (status != 0) { /* If we did manage to read at least one byte, then @@ -197,8 +211,10 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define Eq OP_E, q_mode #define Edq OP_E, dq_mode #define Edqw OP_E, dqw_mode -#define indirEv OP_indirE, v_mode +#define indirEv OP_indirE, stack_v_mode #define indirEp OP_indirE, f_mode +#define stackEv OP_E, stack_v_mode +#define Em OP_E, m_mode #define Ew OP_E, w_mode #define Ma OP_E, v_mode #define M OP_M, 0 /* lea, lgdt, etc. */ @@ -207,6 +223,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define Gv OP_G, v_mode #define Gd OP_G, d_mode #define Gdq OP_G, dq_mode +#define Gm OP_G, m_mode #define Gw OP_G, w_mode #define Rd OP_Rd, d_mode #define Rm OP_Rd, m_mode @@ -261,7 +278,6 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define eSI OP_IMREG, eSI_reg #define eDI OP_IMREG, eDI_reg #define AL OP_IMREG, al_reg -#define AL OP_IMREG, al_reg #define CL OP_IMREG, cl_reg #define DL OP_IMREG, dl_reg #define BL OP_IMREG, bl_reg @@ -275,10 +291,8 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define Sw OP_SEG, w_mode #define Ap OP_DIR, 0 -#define Ob OP_OFF, b_mode -#define Ob64 OP_OFF64, b_mode -#define Ov OP_OFF, v_mode -#define Ov64 OP_OFF64, v_mode +#define Ob OP_OFF64, b_mode +#define Ov OP_OFF64, v_mode #define Xb OP_DSreg, eSI_reg #define Xv OP_DSreg, eSI_reg #define Yb OP_ESreg, eDI_reg @@ -298,9 +312,19 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define EX OP_EX, v_mode #define MS OP_MS, v_mode #define XS OP_XS, v_mode +#define VM OP_VMX, q_mode #define OPSUF OP_3DNowSuffix, 0 #define OPSIMD OP_SIMD_Suffix, 0 +/* Used handle "rep" prefix for string instructions. */ +#define Xbr REP_Fixup, eSI_reg +#define Xvr REP_Fixup, eSI_reg +#define Ybr REP_Fixup, eDI_reg +#define Yvr REP_Fixup, eDI_reg +#define indirDXr REP_Fixup, indir_dx_reg +#define ALr REP_Fixup, al_reg +#define eAXr REP_Fixup, eAX_reg + #define cond_jump_flag NULL, cond_jump_mode #define loop_jcxz_flag NULL, loop_jcxz_mode @@ -323,6 +347,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define dqw_mode 12 /* registers like dq_mode, memory like w_mode. */ #define f_mode 13 /* 4- or 6-byte pointer operand */ #define const_1_mode 14 +#define stack_v_mode 15 /* v_mode for stack-related opcodes. */ #define es_reg 100 #define cs_reg 101 @@ -373,6 +398,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define USE_GROUPS 2 #define USE_PREFIX_USER_TABLE 3 #define X86_64_SPECIAL 4 +#define IS_3BYTE_OPCODE 5 #define FLOAT NULL, NULL, FLOATCODE, NULL, 0, NULL, 0 @@ -393,11 +419,11 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define GRP7 NULL, NULL, USE_GROUPS, NULL, 14, NULL, 0 #define GRP8 NULL, NULL, USE_GROUPS, NULL, 15, NULL, 0 #define GRP9 NULL, NULL, USE_GROUPS, NULL, 16, NULL, 0 -#define GRP10 NULL, NULL, USE_GROUPS, NULL, 17, NULL, 0 -#define GRP11 NULL, NULL, USE_GROUPS, NULL, 18, NULL, 0 -#define GRP12 NULL, NULL, USE_GROUPS, NULL, 19, NULL, 0 -#define GRP13 NULL, NULL, USE_GROUPS, NULL, 20, NULL, 0 -#define GRP14 NULL, NULL, USE_GROUPS, NULL, 21, NULL, 0 +#define GRP12 NULL, NULL, USE_GROUPS, NULL, 17, NULL, 0 +#define GRP13 NULL, NULL, USE_GROUPS, NULL, 18, NULL, 0 +#define GRP14 NULL, NULL, USE_GROUPS, NULL, 19, NULL, 0 +#define GRP15 NULL, NULL, USE_GROUPS, NULL, 20, NULL, 0 +#define GRP16 NULL, NULL, USE_GROUPS, NULL, 21, NULL, 0 #define GRPAMD NULL, NULL, USE_GROUPS, NULL, 22, NULL, 0 #define GRPPADLCK1 NULL, NULL, USE_GROUPS, NULL, 23, NULL, 0 #define GRPPADLCK2 NULL, NULL, USE_GROUPS, NULL, 24, NULL, 0 @@ -438,6 +464,9 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define X86_64_0 NULL, NULL, X86_64_SPECIAL, NULL, 0, NULL, 0 +#define THREE_BYTE_0 NULL, NULL, IS_3BYTE_OPCODE, NULL, 0, NULL, 0 +#define THREE_BYTE_1 NULL, NULL, IS_3BYTE_OPCODE, NULL, 1, NULL, 0 + typedef void (*op_rtn) (int bytemode, int sizeflag); struct dis386 { @@ -472,9 +501,11 @@ struct dis386 { 'S' => print 'w', 'l' or 'q' if suffix_always is true 'T' => print 'q' in 64bit mode and behave as 'P' otherwise 'U' => print 'q' in 64bit mode and behave as 'Q' otherwise + 'V' => print 'q' in 64bit mode and behave as 'S' otherwise 'W' => print 'b' or 'w' ("w" or "de" in intel mode) 'X' => print 's', 'd' depending on data16 prefix (for XMM) 'Y' => 'q' if instruction has an REX 64bit overwrite prefix + 'Z' => print 'q' in 64bit mode and behave as 'L' otherwise Many of the above letters print nothing in Intel mode. See "putop" for the details. @@ -512,7 +543,7 @@ static const struct dis386 dis386[] = { { "adcB", AL, Ib, XX }, { "adcS", eAX, Iv, XX }, { "push{T|}", ss, XX, XX }, - { "popT|}", ss, XX, XX }, + { "pop{T|}", ss, XX, XX }, /* 18 */ { "sbbB", Eb, Gb, XX }, { "sbbS", Ev, Gv, XX }, @@ -577,23 +608,23 @@ static const struct dis386 dis386[] = { { "dec{S|}", RMeSI, XX, XX }, { "dec{S|}", RMeDI, XX, XX }, /* 50 */ - { "pushS", RMrAX, XX, XX }, - { "pushS", RMrCX, XX, XX }, - { "pushS", RMrDX, XX, XX }, - { "pushS", RMrBX, XX, XX }, - { "pushS", RMrSP, XX, XX }, - { "pushS", RMrBP, XX, XX }, - { "pushS", RMrSI, XX, XX }, - { "pushS", RMrDI, XX, XX }, + { "pushV", RMrAX, XX, XX }, + { "pushV", RMrCX, XX, XX }, + { "pushV", RMrDX, XX, XX }, + { "pushV", RMrBX, XX, XX }, + { "pushV", RMrSP, XX, XX }, + { "pushV", RMrBP, XX, XX }, + { "pushV", RMrSI, XX, XX }, + { "pushV", RMrDI, XX, XX }, /* 58 */ - { "popS", RMrAX, XX, XX }, - { "popS", RMrCX, XX, XX }, - { "popS", RMrDX, XX, XX }, - { "popS", RMrBX, XX, XX }, - { "popS", RMrSP, XX, XX }, - { "popS", RMrBP, XX, XX }, - { "popS", RMrSI, XX, XX }, - { "popS", RMrDI, XX, XX }, + { "popV", RMrAX, XX, XX }, + { "popV", RMrCX, XX, XX }, + { "popV", RMrDX, XX, XX }, + { "popV", RMrBX, XX, XX }, + { "popV", RMrSP, XX, XX }, + { "popV", RMrBP, XX, XX }, + { "popV", RMrSI, XX, XX }, + { "popV", RMrDI, XX, XX }, /* 60 */ { "pusha{P|}", XX, XX, XX }, { "popa{P|}", XX, XX, XX }, @@ -608,10 +639,10 @@ static const struct dis386 dis386[] = { { "imulS", Gv, Ev, Iv }, { "pushT", sIb, XX, XX }, { "imulS", Gv, Ev, sIb }, - { "ins{b||b|}", Yb, indirDX, XX }, - { "ins{R||R|}", Yv, indirDX, XX }, - { "outs{b||b|}", indirDX, Xb, XX }, - { "outs{R||R|}", indirDX, Xv, XX }, + { "ins{b||b|}", Ybr, indirDX, XX }, + { "ins{R||R|}", Yvr, indirDX, XX }, + { "outs{b||b|}", indirDXr, Xb, XX }, + { "outs{R||R|}", indirDXr, Xv, XX }, /* 70 */ { "joH", Jb, XX, cond_jump_flag }, { "jnoH", Jb, XX, cond_jump_flag }, @@ -647,9 +678,9 @@ static const struct dis386 dis386[] = { { "movQ", Sv, Sw, XX }, { "leaS", Gv, M, XX }, { "movQ", Sw, Sv, XX }, - { "popU", Ev, XX, XX }, + { "popU", stackEv, XX, XX }, /* 90 */ - { "nop", NOP_Fixup, 0, XX, XX }, + { "xchgS", NOP_Fixup1, eAX_reg, NOP_Fixup2, eAX_reg, XX }, { "xchgS", RMeCX, eAX, XX }, { "xchgS", RMeDX, eAX, XX }, { "xchgS", RMeBX, eAX, XX }, @@ -667,21 +698,21 @@ static const struct dis386 dis386[] = { { "sahf{|}", XX, XX, XX }, { "lahf{|}", XX, XX, XX }, /* a0 */ - { "movB", AL, Ob64, XX }, - { "movS", eAX, Ov64, XX }, - { "movB", Ob64, AL, XX }, - { "movS", Ov64, eAX, XX }, - { "movs{b||b|}", Yb, Xb, XX }, - { "movs{R||R|}", Yv, Xv, XX }, + { "movB", AL, Ob, XX }, + { "movS", eAX, Ov, XX }, + { "movB", Ob, AL, XX }, + { "movS", Ov, eAX, XX }, + { "movs{b||b|}", Ybr, Xb, XX }, + { "movs{R||R|}", Yvr, Xv, XX }, { "cmps{b||b|}", Xb, Yb, XX }, { "cmps{R||R|}", Xv, Yv, XX }, /* a8 */ { "testB", AL, Ib, XX }, { "testS", eAX, Iv, XX }, - { "stosB", Yb, AL, XX }, - { "stosS", Yv, eAX, XX }, - { "lodsB", AL, Xb, XX }, - { "lodsS", eAX, Xv, XX }, + { "stosB", Ybr, AL, XX }, + { "stosS", Yvr, eAX, XX }, + { "lodsB", ALr, Xb, XX }, + { "lodsS", eAXr, Xv, XX }, { "scasB", AL, Yb, XX }, { "scasS", eAX, Yv, XX }, /* b0 */ @@ -805,19 +836,19 @@ static const struct dis386 dis386_twobyte[] = { { PREGRP31 }, { "movhpX", EX, XM, SIMD_Fixup, 'l' }, /* 18 */ - { GRP14 }, - { "(bad)", XX, XX, XX }, + { GRP16 }, { "(bad)", XX, XX, XX }, { "(bad)", XX, XX, XX }, { "(bad)", XX, XX, XX }, { "(bad)", XX, XX, XX }, { "(bad)", XX, XX, XX }, { "(bad)", XX, XX, XX }, + { "nopQ", Ev, XX, XX }, /* 20 */ - { "movL", Rm, Cm, XX }, - { "movL", Rm, Dm, XX }, - { "movL", Cm, Rm, XX }, - { "movL", Dm, Rm, XX }, + { "movZ", Rm, Cm, XX }, + { "movZ", Rm, Dm, XX }, + { "movZ", Cm, Rm, XX }, + { "movZ", Dm, Rm, XX }, { "movL", Rd, Td, XX }, { "(bad)", XX, XX, XX }, { "movL", Td, Rd, XX }, @@ -841,9 +872,9 @@ static const struct dis386 dis386_twobyte[] = { { "(bad)", XX, XX, XX }, { "(bad)", XX, XX, XX }, /* 38 */ + { THREE_BYTE_0 }, { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, + { THREE_BYTE_1 }, { "(bad)", XX, XX, XX }, { "(bad)", XX, XX, XX }, { "(bad)", XX, XX, XX }, @@ -905,16 +936,16 @@ static const struct dis386 dis386_twobyte[] = { { PREGRP19 }, /* 70 */ { PREGRP22 }, - { GRP10 }, - { GRP11 }, { GRP12 }, + { GRP13 }, + { GRP14 }, { "pcmpeqb", MX, EM, XX }, { "pcmpeqw", MX, EM, XX }, { "pcmpeqd", MX, EM, XX }, { "emms", XX, XX, XX }, /* 78 */ - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, + { "vmread", Em, Gm, XX }, + { "vmwrite", Gm, Em, XX }, { "(bad)", XX, XX, XX }, { "(bad)", XX, XX, XX }, { PREGRP28 }, @@ -973,7 +1004,7 @@ static const struct dis386 dis386_twobyte[] = { { "btsS", Ev, Gv, XX }, { "shrdS", Ev, Gv, Ib }, { "shrdS", Ev, Gv, CL }, - { GRP13 }, + { GRP15 }, { "imulS", Gv, Ev, XX }, /* b0 */ { "cmpxchgB", Eb, Gb, XX }, @@ -1094,13 +1125,13 @@ static const unsigned char twobyte_has_modrm[256] = { /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ /* ------------------------------- */ /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0f */ - /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, /* 1f */ + /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1, /* 1f */ /* 20 */ 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 2f */ - /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ + /* 30 */ 0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 3f */ /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */ /* 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5f */ /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */ - /* 70 */ 1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1, /* 7f */ + /* 70 */ 1,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1, /* 7f */ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */ /* a0 */ 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1, /* af */ @@ -1119,7 +1150,7 @@ static const unsigned char twobyte_uses_SSE_prefix[256] = { /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ /* 10 */ 1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0, /* 1f */ /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0, /* 2f */ - /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ + /* 30 */ 0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 3f */ /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */ /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1, /* 6f */ @@ -1354,7 +1385,7 @@ static const struct dis386 grps[][8] = { { "JcallT", indirEp, XX, XX }, { "jmpT", indirEv, XX, XX }, { "JjmpT", indirEp, XX, XX }, - { "pushU", Ev, XX, XX }, + { "pushU", stackEv, XX, XX }, { "(bad)", XX, XX, XX }, }, /* GRP6 */ @@ -1370,10 +1401,10 @@ static const struct dis386 grps[][8] = { }, /* GRP7 */ { - { "sgdtIQ", M, XX, XX }, - { "sidtIQ", PNI_Fixup, 0, XX, XX }, + { "sgdt{Q|IQ||}", VMX_Fixup, 0, XX, XX }, + { "sidt{Q|IQ||}", PNI_Fixup, 0, XX, XX }, { "lgdt{Q|Q||}", M, XX, XX }, - { "lidt{Q|Q||}", M, XX, XX }, + { "lidt{Q|Q||}", SVME_Fixup, 0, XX, XX }, { "smswQ", Ev, XX, XX }, { "(bad)", XX, XX, XX }, { "lmsw", Ew, XX, XX }, @@ -1398,10 +1429,10 @@ static const struct dis386 grps[][8] = { { "(bad)", XX, XX, XX }, { "(bad)", XX, XX, XX }, { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, + { "", VM, XX, XX }, /* See OP_VMX. */ + { "vmptrst", Eq, XX, XX }, }, - /* GRP10 */ + /* GRP12 */ { { "(bad)", XX, XX, XX }, { "(bad)", XX, XX, XX }, @@ -1412,7 +1443,7 @@ static const struct dis386 grps[][8] = { { "psllw", MS, Ib, XX }, { "(bad)", XX, XX, XX }, }, - /* GRP11 */ + /* GRP13 */ { { "(bad)", XX, XX, XX }, { "(bad)", XX, XX, XX }, @@ -1423,7 +1454,7 @@ static const struct dis386 grps[][8] = { { "pslld", MS, Ib, XX }, { "(bad)", XX, XX, XX }, }, - /* GRP12 */ + /* GRP14 */ { { "(bad)", XX, XX, XX }, { "(bad)", XX, XX, XX }, @@ -1434,7 +1465,7 @@ static const struct dis386 grps[][8] = { { "psllq", MS, Ib, XX }, { "pslldq", MS, Ib, XX }, }, - /* GRP13 */ + /* GRP15 */ { { "fxsave", Ev, XX, XX }, { "fxrstor", Ev, XX, XX }, @@ -1445,7 +1476,7 @@ static const struct dis386 grps[][8] = { { "mfence", OP_0fae, 0, XX, XX }, { "clflush", OP_0fae, 0, XX, XX }, }, - /* GRP14 */ + /* GRP16 */ { { "prefetchnta", Ev, XX, XX }, { "prefetcht0", Ev, XX, XX }, @@ -1469,14 +1500,14 @@ static const struct dis386 grps[][8] = { }, /* GRPPADLCK1 */ { - { "xstorerng", OP_0f07, 0, XX, XX }, - { "xcryptecb", OP_0f07, 0, XX, XX }, - { "xcryptcbc", OP_0f07, 0, XX, XX }, - { "(bad)", OP_0f07, 0, XX, XX }, - { "xcryptcfb", OP_0f07, 0, XX, XX }, - { "xcryptofb", OP_0f07, 0, XX, XX }, - { "(bad)", OP_0f07, 0, XX, XX }, - { "(bad)", OP_0f07, 0, XX, XX }, + { "xstore-rng", OP_0f07, 0, XX, XX }, + { "xcrypt-ecb", OP_0f07, 0, XX, XX }, + { "xcrypt-cbc", OP_0f07, 0, XX, XX }, + { "xcrypt-ctr", OP_0f07, 0, XX, XX }, + { "xcrypt-cfb", OP_0f07, 0, XX, XX }, + { "xcrypt-ofb", OP_0f07, 0, XX, XX }, + { "(bad)", OP_0f07, 0, XX, XX }, + { "(bad)", OP_0f07, 0, XX, XX }, }, /* GRPPADLCK2 */ { @@ -1732,6 +1763,79 @@ static const struct dis386 x86_64_table[][2] = { }, }; +static const struct dis386 three_byte_table[][32] = { + /* THREE_BYTE_0 */ + { + { "pshufb", MX, EM, XX }, + { "phaddw", MX, EM, XX }, + { "phaddd", MX, EM, XX }, + { "phaddsw", MX, EM, XX }, + { "pmaddubsw", MX, EM, XX }, + { "phsubw", MX, EM, XX }, + { "phsubd", MX, EM, XX }, + { "phsubsw", MX, EM, XX }, + { "psignb", MX, EM, XX }, + { "psignw", MX, EM, XX }, + { "psignd", MX, EM, XX }, + { "pmulhrsw", MX, EM, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "pabsb", MX, EM, XX }, + { "pabsw", MX, EM, XX }, + { "pabsd", MX, EM, XX }, + { "(bad)", XX, XX, XX } + }, + /* THREE_BYTE_1 */ + { + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "palignr", MX, EM, Ib }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX } + }, +}; + #define INTERNAL_DISASSEMBLER_ERROR _("") static void @@ -1765,7 +1869,7 @@ ckprefix (void) case 0x4d: case 0x4e: case 0x4f: - if (mode_64bit) + if (address_mode == mode_64bit) newrex = *codep; else return; @@ -1807,7 +1911,7 @@ ckprefix (void) /* fwait is really an instruction. If there are prefixes before the fwait, they belong to the fwait, *not* to the following instruction. */ - if (prefixes) + if (prefixes || rex) { prefixes |= PREFIX_FWAIT; codep++; @@ -1821,8 +1925,8 @@ ckprefix (void) /* Rex is ignored when followed by another prefix. */ if (rex) { - oappend (prefix_name (rex, 0)); - oappend (" "); + rex_used = rex; + return; } rex = newrex; codep++; @@ -1891,10 +1995,10 @@ prefix_name (int pref, int sizeflag) case 0x66: return (sizeflag & DFLAG) ? "data16" : "data32"; case 0x67: - if (mode_64bit) + if (address_mode == mode_64bit) return (sizeflag & AFLAG) ? "addr32" : "addr64"; else - return ((sizeflag & AFLAG) && !mode_64bit) ? "addr16" : "addr32"; + return (sizeflag & AFLAG) ? "addr16" : "addr32"; case FWAIT_OPCODE: return "fwait"; default: @@ -1963,8 +2067,11 @@ print_insn (bfd_vma pc, disassemble_info *info) const char *p; struct dis_private priv; - mode_64bit = (info->mach == bfd_mach_x86_64_intel_syntax - || info->mach == bfd_mach_x86_64); + if (info->mach == bfd_mach_x86_64_intel_syntax + || info->mach == bfd_mach_x86_64) + address_mode = mode_64bit; + else + address_mode = mode_32bit; if (intel_syntax == (char) -1) intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax @@ -1984,17 +2091,17 @@ print_insn (bfd_vma pc, disassemble_info *info) { if (strncmp (p, "x86-64", 6) == 0) { - mode_64bit = 1; + address_mode = mode_64bit; priv.orig_sizeflag = AFLAG | DFLAG; } else if (strncmp (p, "i386", 4) == 0) { - mode_64bit = 0; + address_mode = mode_32bit; priv.orig_sizeflag = AFLAG | DFLAG; } else if (strncmp (p, "i8086", 5) == 0) { - mode_64bit = 0; + address_mode = mode_16bit; priv.orig_sizeflag = 0; } else if (strncmp (p, "intel", 5) == 0) @@ -2110,13 +2217,14 @@ print_insn (bfd_vma pc, disassemble_info *info) FETCH_DATA (info, codep + 1); two_source_ops = (*codep == 0x62) || (*codep == 0xc8); - if ((prefixes & PREFIX_FWAIT) - && ((*codep < 0xd8) || (*codep > 0xdf))) + if (((prefixes & PREFIX_FWAIT) + && ((*codep < 0xd8) || (*codep > 0xdf))) + || (rex && rex_used)) { const char *name; - /* fwait not followed by floating point instruction. Print the - first prefix, which is probably fwait itself. */ + /* fwait not followed by floating point instruction, or rex followed + by other prefixes. Print the first prefix. */ name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag); if (name == NULL) name = INTERNAL_DISASSEMBLER_ERROR; @@ -2162,7 +2270,7 @@ print_insn (bfd_vma pc, disassemble_info *info) sizeflag ^= AFLAG; if (dp->bytemode3 != loop_jcxz_mode || intel_syntax) { - if ((sizeflag & AFLAG) || mode_64bit) + if ((sizeflag & AFLAG) || address_mode == mode_64bit) oappend ("addr32 "); else oappend ("addr16 "); @@ -2185,7 +2293,15 @@ print_insn (bfd_vma pc, disassemble_info *info) } } - if (need_modrm) + if (dp->name == NULL && dp->bytemode1 == IS_3BYTE_OPCODE) + { + FETCH_DATA (info, codep + 2); + dp = &three_byte_table[dp->bytemode2][*codep++]; + mod = (*codep >> 6) & 3; + reg = (*codep >> 3) & 7; + rm = *codep & 7; + } + else if (need_modrm) { FETCH_DATA (info, codep + 1); mod = (*codep >> 6) & 3; @@ -2229,7 +2345,8 @@ print_insn (bfd_vma pc, disassemble_info *info) break; case X86_64_SPECIAL: - dp = &x86_64_table[dp->bytemode2][mode_64bit]; + index = address_mode == mode_64bit ? 1 : 0; + dp = &x86_64_table[dp->bytemode2][index]; break; default: @@ -2671,6 +2788,7 @@ dofloat (int sizeflag) putop (float_mem[fp_indx], sizeflag); obufp = op1out; + op_ad = 2; OP_E (float_mem_mode[fp_indx], sizeflag); return; } @@ -2692,9 +2810,12 @@ dofloat (int sizeflag) putop (dp->name, sizeflag); obufp = op1out; + op_ad = 2; if (dp->op1) (*dp->op1) (dp->bytemode1, sizeflag); + obufp = op2out; + op_ad = 1; if (dp->op2) (*dp->op2) (dp->bytemode2, sizeflag); } @@ -2703,7 +2824,7 @@ dofloat (int sizeflag) static void OP_ST (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) { - oappend ("%st"); + oappend ("%st" + intel_syntax); } static void @@ -2731,7 +2852,7 @@ putop (const char *template, int sizeflag) alt = 0; if (intel_syntax) alt += 1; - if (mode_64bit) + if (address_mode == mode_64bit) alt += 2; while (alt != 0) { @@ -2787,7 +2908,7 @@ putop (const char *template, int sizeflag) } break; case 'E': /* For jcxz/jecxz */ - if (mode_64bit) + if (address_mode == mode_64bit) { if (sizeflag & AFLAG) *obufp++ = 'r'; @@ -2805,9 +2926,9 @@ putop (const char *template, int sizeflag) if ((prefixes & PREFIX_ADDR) || (sizeflag & SUFFIX_ALWAYS)) { if (sizeflag & AFLAG) - *obufp++ = mode_64bit ? 'q' : 'l'; + *obufp++ = address_mode == mode_64bit ? 'q' : 'l'; else - *obufp++ = mode_64bit ? 'l' : 'w'; + *obufp++ = address_mode == mode_64bit ? 'l' : 'w'; used_prefixes |= (prefixes & PREFIX_ADDR); } break; @@ -2831,6 +2952,15 @@ putop (const char *template, int sizeflag) break; *obufp++ = 'l'; break; + case 'Z': + if (intel_syntax) + break; + if (address_mode == mode_64bit && (sizeflag & SUFFIX_ALWAYS)) + { + *obufp++ = 'q'; + break; + } + /* Fall through. */ case 'L': if (intel_syntax) break; @@ -2853,7 +2983,7 @@ putop (const char *template, int sizeflag) case 'T': if (intel_syntax) break; - if (mode_64bit) + if (address_mode == mode_64bit && (sizeflag & DFLAG)) { *obufp++ = 'q'; break; @@ -2875,16 +3005,17 @@ putop (const char *template, int sizeflag) *obufp++ = 'l'; else *obufp++ = 'w'; - used_prefixes |= (prefixes & PREFIX_DATA); } + used_prefixes |= (prefixes & PREFIX_DATA); } break; case 'U': if (intel_syntax) break; - if (mode_64bit) + if (address_mode == mode_64bit && (sizeflag & DFLAG)) { - *obufp++ = 'q'; + if (mod != 3 || (sizeflag & SUFFIX_ALWAYS)) + *obufp++ = 'q'; break; } /* Fall through. */ @@ -2902,8 +3033,8 @@ putop (const char *template, int sizeflag) *obufp++ = intel_syntax ? 'd' : 'l'; else *obufp++ = 'w'; - used_prefixes |= (prefixes & PREFIX_DATA); } + used_prefixes |= (prefixes & PREFIX_DATA); } break; case 'R': @@ -2938,6 +3069,16 @@ putop (const char *template, int sizeflag) if (!(rex & REX_MODE64)) used_prefixes |= (prefixes & PREFIX_DATA); break; + case 'V': + if (intel_syntax) + break; + if (address_mode == mode_64bit && (sizeflag & DFLAG)) + { + if (sizeflag & SUFFIX_ALWAYS) + *obufp++ = 'q'; + break; + } + /* Fall through. */ case 'S': if (intel_syntax) break; @@ -3061,7 +3202,7 @@ OP_indirE (int bytemode, int sizeflag) static void print_operand_value (char *buf, int hex, bfd_vma disp) { - if (mode_64bit) + if (address_mode == mode_64bit) { if (hex) { @@ -3115,6 +3256,67 @@ print_operand_value (char *buf, int hex, bfd_vma disp) } } +static void +intel_operand_size (int bytemode, int sizeflag) +{ + switch (bytemode) + { + case b_mode: + oappend ("BYTE PTR "); + break; + case w_mode: + case dqw_mode: + oappend ("WORD PTR "); + break; + case stack_v_mode: + if (address_mode == mode_64bit && (sizeflag & DFLAG)) + { + oappend ("QWORD PTR "); + used_prefixes |= (prefixes & PREFIX_DATA); + break; + } + /* FALLTHRU */ + case v_mode: + case dq_mode: + USED_REX (REX_MODE64); + if (rex & REX_MODE64) + oappend ("QWORD PTR "); + else if ((sizeflag & DFLAG) || bytemode == dq_mode) + oappend ("DWORD PTR "); + else + oappend ("WORD PTR "); + used_prefixes |= (prefixes & PREFIX_DATA); + break; + case d_mode: + oappend ("DWORD PTR "); + break; + case q_mode: + oappend ("QWORD PTR "); + break; + case m_mode: + if (address_mode == mode_64bit) + oappend ("QWORD PTR "); + else + oappend ("DWORD PTR "); + break; + case f_mode: + if (sizeflag & DFLAG) + oappend ("FWORD PTR "); + else + oappend ("DWORD PTR "); + used_prefixes |= (prefixes & PREFIX_DATA); + break; + case t_mode: + oappend ("TBYTE PTR "); + break; + case x_mode: + oappend ("XMMWORD PTR "); + break; + default: + break; + } +} + static void OP_E (int bytemode, int sizeflag) { @@ -3150,11 +3352,20 @@ OP_E (int bytemode, int sizeflag) oappend (names64[rm + add]); break; case m_mode: - if (mode_64bit) + if (address_mode == mode_64bit) oappend (names64[rm + add]); else oappend (names32[rm + add]); break; + case stack_v_mode: + if (address_mode == mode_64bit && (sizeflag & DFLAG)) + { + oappend (names64[rm + add]); + used_prefixes |= (prefixes & PREFIX_DATA); + break; + } + bytemode = v_mode; + /* FALLTHRU */ case v_mode: case dq_mode: case dqw_mode: @@ -3177,9 +3388,11 @@ OP_E (int bytemode, int sizeflag) } disp = 0; + if (intel_syntax) + intel_operand_size (bytemode, sizeflag); append_seg (); - if ((sizeflag & AFLAG) || mode_64bit) /* 32 bit address mode */ + if ((sizeflag & AFLAG) || address_mode == mode_64bit) /* 32 bit address mode */ { int havesib; int havebase; @@ -3196,18 +3409,16 @@ OP_E (int bytemode, int sizeflag) havesib = 1; FETCH_DATA (the_info, codep + 1); index = (*codep >> 3) & 7; - if (mode_64bit || index != 0x4) + if (address_mode == mode_64bit || index != 0x4) /* When INDEX == 0x4 in 32 bit mode, SCALE is ignored. */ scale = (*codep >> 6) & 3; base = *codep & 7; USED_REX (REX_EXTY); - USED_REX (REX_EXTZ); if (rex & REX_EXTY) index += 8; - if (rex & REX_EXTZ) - base += 8; codep++; } + base += add; switch (mod) { @@ -3215,7 +3426,7 @@ OP_E (int bytemode, int sizeflag) if ((base & 7) == 5) { havebase = 0; - if (mode_64bit && !havesib) + if (address_mode == mode_64bit && !havesib) riprel = 1; disp = get32s (); } @@ -3245,68 +3456,12 @@ OP_E (int bytemode, int sizeflag) if (havebase || (havesib && (index != 4 || scale != 0))) { - if (intel_syntax) - { - switch (bytemode) - { - case b_mode: - oappend ("BYTE PTR "); - break; - case w_mode: - case dqw_mode: - oappend ("WORD PTR "); - break; - case v_mode: - case dq_mode: - USED_REX (REX_MODE64); - if (rex & REX_MODE64) - oappend ("QWORD PTR "); - else if ((sizeflag & DFLAG) || bytemode == dq_mode) - oappend ("DWORD PTR "); - else - oappend ("WORD PTR "); - used_prefixes |= (prefixes & PREFIX_DATA); - break; - case d_mode: - oappend ("DWORD PTR "); - break; - case q_mode: - oappend ("QWORD PTR "); - break; - case m_mode: - if (mode_64bit) - oappend ("QWORD PTR "); - else - oappend ("DWORD PTR "); - break; - case f_mode: - if (sizeflag & DFLAG) - { - used_prefixes |= (prefixes & PREFIX_DATA); - oappend ("FWORD PTR "); - } - else - oappend ("DWORD PTR "); - break; - case t_mode: - oappend ("TBYTE PTR "); - break; - case x_mode: - oappend ("XMMWORD PTR "); - break; - default: - break; - } - } *obufp++ = open_char; if (intel_syntax && riprel) oappend ("rip + "); *obufp = '\0'; - USED_REX (REX_EXTZ); - if (!havesib && (rex & REX_EXTZ)) - base += 8; if (havebase) - oappend (mode_64bit && (sizeflag & AFLAG) + oappend (address_mode == mode_64bit && (sizeflag & AFLAG) ? names64[base] : names32[base]); if (havesib) { @@ -3317,7 +3472,7 @@ OP_E (int bytemode, int sizeflag) *obufp++ = separator_char; *obufp = '\0'; } - oappend (mode_64bit && (sizeflag & AFLAG) + oappend (address_mode == mode_64bit && (sizeflag & AFLAG) ? names64[index] : names32[index]); } if (scale != 0 || (!intel_syntax && index != 4)) @@ -3328,22 +3483,23 @@ OP_E (int bytemode, int sizeflag) oappend (scratchbuf); } } - if (intel_syntax) - if (mod != 0 || (base & 7) == 5) - { - /* Don't print zero displacements. */ - if (disp != 0) - { - if ((bfd_signed_vma) disp > 0) - { - *obufp++ = '+'; - *obufp = '\0'; - } - - print_operand_value (scratchbuf, 0, disp); - oappend (scratchbuf); - } - } + if (intel_syntax && disp) + { + if ((bfd_signed_vma) disp > 0) + { + *obufp++ = '+'; + *obufp = '\0'; + } + else if (mod != 1) + { + *obufp++ = '-'; + *obufp = '\0'; + disp = - (bfd_signed_vma) disp; + } + + print_operand_value (scratchbuf, mod != 1, disp); + oappend (scratchbuf); + } *obufp++ = close_char; *obufp = '\0'; @@ -3370,7 +3526,7 @@ OP_E (int bytemode, int sizeflag) switch (mod) { case 0: - if ((rm & 7) == 6) + if (rm == 6) { disp = get16 (); if ((disp & 0x8000) != 0) @@ -3391,20 +3547,51 @@ OP_E (int bytemode, int sizeflag) } if (!intel_syntax) - if (mod != 0 || (rm & 7) == 6) + if (mod != 0 || rm == 6) { print_operand_value (scratchbuf, 0, disp); oappend (scratchbuf); } - if (mod != 0 || (rm & 7) != 6) + if (mod != 0 || rm != 6) { *obufp++ = open_char; *obufp = '\0'; - oappend (index16[rm + add]); + oappend (index16[rm]); + if (intel_syntax && disp) + { + if ((bfd_signed_vma) disp > 0) + { + *obufp++ = '+'; + *obufp = '\0'; + } + else if (mod != 1) + { + *obufp++ = '-'; + *obufp = '\0'; + disp = - (bfd_signed_vma) disp; + } + + print_operand_value (scratchbuf, mod != 1, disp); + oappend (scratchbuf); + } + *obufp++ = close_char; *obufp = '\0'; } + else if (intel_syntax) + { + if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS + | PREFIX_ES | PREFIX_FS | PREFIX_GS)) + ; + else + { + oappend (names_seg[ds_reg - es_reg]); + oappend (":"); + } + print_operand_value (scratchbuf, 1, disp & 0xffff); + oappend (scratchbuf); + } } } @@ -3445,6 +3632,12 @@ OP_G (int bytemode, int sizeflag) oappend (names16[reg + add]); used_prefixes |= (prefixes & PREFIX_DATA); break; + case m_mode: + if (address_mode == mode_64bit) + oappend (names64[reg + add]); + else + oappend (names32[reg + add]); + break; default: oappend (INTERNAL_DISASSEMBLER_ERROR); break; @@ -3520,7 +3713,7 @@ static void set_op (bfd_vma op, int riprel) { op_index[op_ad] = op_ad; - if (mode_64bit) + if (address_mode == mode_64bit) { op_address[op_ad] = op; op_riprel[op_ad] = riprel; @@ -3568,7 +3761,7 @@ OP_REG (int code, int sizeflag) break; case rAX_reg: case rCX_reg: case rDX_reg: case rBX_reg: case rSP_reg: case rBP_reg: case rSI_reg: case rDI_reg: - if (mode_64bit) + if (address_mode == mode_64bit && (sizeflag & DFLAG)) { s = names64[code - rAX_reg + add]; break; @@ -3654,7 +3847,7 @@ OP_I (int bytemode, int sizeflag) mask = 0xff; break; case q_mode: - if (mode_64bit) + if (address_mode == mode_64bit) { op = get32s (); break; @@ -3702,7 +3895,7 @@ OP_I64 (int bytemode, int sizeflag) bfd_signed_vma op; bfd_signed_vma mask = -1; - if (!mode_64bit) + if (address_mode != mode_64bit) { OP_I (bytemode, sizeflag); return; @@ -3811,7 +4004,7 @@ OP_J (int bytemode, int sizeflag) disp -= 0x100; break; case v_mode: - if (sizeflag & DFLAG) + if ((sizeflag & DFLAG) || (rex & REX_MODE64)) disp = get32s (); else { @@ -3855,20 +4048,22 @@ OP_DIR (int dummy ATTRIBUTE_UNUSED, int sizeflag) } used_prefixes |= (prefixes & PREFIX_DATA); if (intel_syntax) - sprintf (scratchbuf, "0x%x,0x%x", seg, offset); + sprintf (scratchbuf, "0x%x:0x%x", seg, offset); else sprintf (scratchbuf, "$0x%x,$0x%x", seg, offset); oappend (scratchbuf); } static void -OP_OFF (int bytemode ATTRIBUTE_UNUSED, int sizeflag) +OP_OFF (int bytemode, int sizeflag) { bfd_vma off; + if (intel_syntax && (sizeflag & SUFFIX_ALWAYS)) + intel_operand_size (bytemode, sizeflag); append_seg (); - if ((sizeflag & AFLAG) || mode_64bit) + if ((sizeflag & AFLAG) || address_mode == mode_64bit) off = get32 (); else off = get16 (); @@ -3887,16 +4082,18 @@ OP_OFF (int bytemode ATTRIBUTE_UNUSED, int sizeflag) } static void -OP_OFF64 (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) +OP_OFF64 (int bytemode, int sizeflag) { bfd_vma off; - if (!mode_64bit) + if (address_mode != mode_64bit) { OP_OFF (bytemode, sizeflag); return; } + if (intel_syntax && (sizeflag & SUFFIX_ALWAYS)) + intel_operand_size (bytemode, sizeflag); append_seg (); off = get64 (); @@ -3921,7 +4118,7 @@ ptr_reg (int code, int sizeflag) *obufp++ = open_char; used_prefixes |= (prefixes & PREFIX_ADDR); - if (mode_64bit) + if (address_mode == mode_64bit) { if (!(sizeflag & AFLAG)) s = names32[code - eAX_reg]; @@ -3941,22 +4138,7 @@ static void OP_ESreg (int code, int sizeflag) { if (intel_syntax) - { - if (codep[-1] & 1) - { - USED_REX (REX_MODE64); - used_prefixes |= (prefixes & PREFIX_DATA); - if (rex & REX_MODE64) - oappend ("QWORD PTR "); - else if ((sizeflag & DFLAG)) - oappend ("DWORD PTR "); - else - oappend ("WORD PTR "); - } - else - oappend ("BYTE PTR "); - } - + intel_operand_size (codep[-1] & 1 ? v_mode : b_mode, sizeflag); oappend ("%es:" + intel_syntax); ptr_reg (code, sizeflag); } @@ -3965,22 +4147,10 @@ static void OP_DSreg (int code, int sizeflag) { if (intel_syntax) - { - if (codep[-1] != 0xd7 && (codep[-1] & 1)) - { - USED_REX (REX_MODE64); - used_prefixes |= (prefixes & PREFIX_DATA); - if (rex & REX_MODE64) - oappend ("QWORD PTR "); - else if ((sizeflag & DFLAG)) - oappend ("DWORD PTR "); - else - oappend ("WORD PTR "); - } - else - oappend ("BYTE PTR "); - } - + intel_operand_size (codep[-1] != 0xd7 && (codep[-1] & 1) + ? v_mode + : b_mode, + sizeflag); if ((prefixes & (PREFIX_CS | PREFIX_DS @@ -4002,7 +4172,7 @@ OP_C (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) USED_REX (REX_EXTX); add = 8; } - else if (!mode_64bit && (prefixes & PREFIX_LOCK)) + else if (address_mode != mode_64bit && (prefixes & PREFIX_LOCK)) { used_prefixes |= PREFIX_LOCK; add = 8; @@ -4191,12 +4361,29 @@ OP_0fae (int bytemode, int sizeflag) OP_E (bytemode, sizeflag); } +/* NOP is an alias of "xchg %ax,%ax" in 16bit mode, "xchg %eax,%eax" in + 32bit mode and "xchg %rax,%rax" in 64bit mode. NOP with REPZ prefix + is called PAUSE. We display "xchg %ax,%ax" instead of "data16 nop". + */ + static void -NOP_Fixup (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) +NOP_Fixup1 (int bytemode, int sizeflag) { - /* NOP with REPZ prefix is called PAUSE. */ if (prefixes == PREFIX_REPZ) strcpy (obuf, "pause"); + else if (prefixes == PREFIX_DATA + || ((rex & REX_MODE64) && rex != 0x48)) + OP_REG (bytemode, sizeflag); + else + strcpy (obuf, "nop"); +} + +static void +NOP_Fixup2 (int bytemode, int sizeflag) +{ + if (prefixes == PREFIX_DATA + || ((rex & REX_MODE64) && rex != 0x48)) + OP_IMREG (bytemode, sizeflag); } static const char *const Suffix3DNow[] = { @@ -4364,46 +4551,154 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag) if (mod == 3 && reg == 1 && rm <= 1) { /* Override "sidt". */ - char *p = obuf + strlen (obuf) - 4; + size_t olen = strlen (obuf); + char *p = obuf + olen - 4; + const char **names = (address_mode == mode_64bit + ? names64 : names32); - /* We might have a suffix. */ + /* We might have a suffix when disassembling with -Msuffix. */ if (*p == 'i') --p; + /* Remove "addr16/addr32" if we aren't in Intel mode. */ + if (!intel_syntax + && (prefixes & PREFIX_ADDR) + && olen >= (4 + 7) + && *(p - 1) == ' ' + && strncmp (p - 7, "addr", 4) == 0 + && (strncmp (p - 3, "16", 2) == 0 + || strncmp (p - 3, "32", 2) == 0)) + p -= 7; + if (rm) { /* mwait %eax,%ecx */ strcpy (p, "mwait"); + if (!intel_syntax) + strcpy (op1out, names[0]); } else { /* monitor %eax,%ecx,%edx" */ strcpy (p, "monitor"); - strcpy (op3out, names32[2]); + if (!intel_syntax) + { + const char **op1_names; + if (!(prefixes & PREFIX_ADDR)) + op1_names = (address_mode == mode_16bit + ? names16 : names); + else + { + op1_names = (address_mode != mode_32bit + ? names32 : names16); + used_prefixes |= PREFIX_ADDR; + } + strcpy (op1out, op1_names[0]); + strcpy (op3out, names[2]); + } + } + if (!intel_syntax) + { + strcpy (op2out, names[1]); + two_source_ops = 1; } - strcpy (op1out, names32[0]); - strcpy (op2out, names32[1]); - two_source_ops = 1; codep++; } else - OP_E (0, sizeflag); + OP_M (0, sizeflag); } static void -INVLPG_Fixup (int bytemode, int sizeflag) +SVME_Fixup (int bytemode, int sizeflag) { - if (*codep == 0xf8) + const char *alt; + char *p; + + switch (*codep) { - char *p = obuf + strlen (obuf); + case 0xd8: + alt = "vmrun"; + break; + case 0xd9: + alt = "vmmcall"; + break; + case 0xda: + alt = "vmload"; + break; + case 0xdb: + alt = "vmsave"; + break; + case 0xdc: + alt = "stgi"; + break; + case 0xdd: + alt = "clgi"; + break; + case 0xde: + alt = "skinit"; + break; + case 0xdf: + alt = "invlpga"; + break; + default: + OP_M (bytemode, sizeflag); + return; + } + /* Override "lidt". */ + p = obuf + strlen (obuf) - 4; + /* We might have a suffix. */ + if (*p == 'i') + --p; + strcpy (p, alt); + if (!(prefixes & PREFIX_ADDR)) + { + ++codep; + return; + } + used_prefixes |= PREFIX_ADDR; + switch (*codep++) + { + case 0xdf: + strcpy (op2out, names32[1]); + two_source_ops = 1; + /* Fall through. */ + case 0xd8: + case 0xda: + case 0xdb: + *obufp++ = open_char; + if (address_mode == mode_64bit || (sizeflag & AFLAG)) + alt = names32[0]; + else + alt = names16[0]; + strcpy (obufp, alt); + obufp += strlen (alt); + *obufp++ = close_char; + *obufp = '\0'; + break; + } +} - /* Override "invlpg". */ - strcpy (p - 6, "swapgs"); - codep++; +static void +INVLPG_Fixup (int bytemode, int sizeflag) +{ + const char *alt; + + switch (*codep) + { + case 0xf8: + alt = "swapgs"; + break; + case 0xf9: + alt = "rdtscp"; + break; + default: + OP_M (bytemode, sizeflag); + return; } - else - OP_E (bytemode, sizeflag); + /* Override "invlpg". */ + strcpy (obuf + strlen (obuf) - 6, alt); + codep++; } static void @@ -4462,3 +4757,123 @@ SEG_Fixup (int extrachar, int sizeflag) OP_E (extrachar, sizeflag); } + +static void +VMX_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag) +{ + if (mod == 3 && reg == 0 && rm >=1 && rm <= 4) + { + /* Override "sgdt". */ + char *p = obuf + strlen (obuf) - 4; + + /* We might have a suffix when disassembling with -Msuffix. */ + if (*p == 'g') + --p; + + switch (rm) + { + case 1: + strcpy (p, "vmcall"); + break; + case 2: + strcpy (p, "vmlaunch"); + break; + case 3: + strcpy (p, "vmresume"); + break; + case 4: + strcpy (p, "vmxoff"); + break; + } + + codep++; + } + else + OP_E (0, sizeflag); +} + +static void +OP_VMX (int bytemode, int sizeflag) +{ + used_prefixes |= (prefixes & (PREFIX_DATA | PREFIX_REPZ)); + if (prefixes & PREFIX_DATA) + strcpy (obuf, "vmclear"); + else if (prefixes & PREFIX_REPZ) + strcpy (obuf, "vmxon"); + else + strcpy (obuf, "vmptrld"); + OP_E (bytemode, sizeflag); +} + +static void +REP_Fixup (int bytemode, int sizeflag) +{ + /* The 0xf3 prefix should be displayed as "rep" for ins, outs, movs, + lods and stos. */ + size_t ilen = 0; + + if (prefixes & PREFIX_REPZ) + switch (*insn_codep) + { + case 0x6e: /* outsb */ + case 0x6f: /* outsw/outsl */ + case 0xa4: /* movsb */ + case 0xa5: /* movsw/movsl/movsq */ + if (!intel_syntax) + ilen = 5; + else + ilen = 4; + break; + case 0xaa: /* stosb */ + case 0xab: /* stosw/stosl/stosq */ + case 0xac: /* lodsb */ + case 0xad: /* lodsw/lodsl/lodsq */ + if (!intel_syntax && (sizeflag & SUFFIX_ALWAYS)) + ilen = 5; + else + ilen = 4; + break; + case 0x6c: /* insb */ + case 0x6d: /* insl/insw */ + if (!intel_syntax) + ilen = 4; + else + ilen = 3; + break; + default: + abort (); + break; + } + + if (ilen != 0) + { + size_t olen; + char *p; + + olen = strlen (obuf); + p = obuf + olen - ilen - 1 - 4; + /* Handle "repz [addr16|addr32]". */ + if ((prefixes & PREFIX_ADDR)) + p -= 1 + 6; + + memmove (p + 3, p + 4, olen - (p + 3 - obuf)); + } + + switch (bytemode) + { + case al_reg: + case eAX_reg: + case indir_dx_reg: + OP_IMREG (bytemode, sizeflag); + break; + case eDI_reg: + OP_ESreg (bytemode, sizeflag); + break; + case eSI_reg: + OP_DSreg (bytemode, sizeflag); + break; + default: + abort (); + break; + } +}