gas/testsuite/
[deliverable/binutils-gdb.git] / opcodes / i386-dis.c
index 0014a706ad89889adc206542d6d5ba07b04be9f1..40be2261daed51676833480478bf13ce266c2ce1 100644 (file)
@@ -35,7 +35,7 @@
 #include "sysdep.h"
 #include "opintl.h"
 
-#define MAXLEN 20
+#define MAXLEN 15
 
 #include <setjmp.h>
 
@@ -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 },
@@ -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 _("<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,18 +4551,31 @@ 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, names32[0]);
+           strcpy (op1out, names[0]);
        }
       else
        {
@@ -4383,28 +4583,100 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
          strcpy (p, "monitor");
          if (!intel_syntax)
            {
-             if (!mode_64bit)
-               strcpy (op1out, names32[0]);
-             else if (!(prefixes & PREFIX_ADDR))
-               strcpy (op1out, names64[0]);
+             const char **op1_names;
+             if (!(prefixes & PREFIX_ADDR))
+               op1_names = (address_mode == mode_16bit
+                            ? names16 : names);
              else
                {
-                 strcpy (op1out, names32[0]);
+                 op1_names = (address_mode != mode_32bit
+                              ? names32 : names16);
                  used_prefixes |= PREFIX_ADDR;
                }
-             strcpy (op3out, names32[2]);
+             strcpy (op1out, op1_names[0]);
+             strcpy (op3out, names[2]);
            }
        }
       if (!intel_syntax)
        {
-         strcpy (op2out, names32[1]);
+         strcpy (op2out, names[1]);
          two_source_ops = 1;
        }
 
       codep++;
     }
   else
-    OP_E (0, sizeflag);
+    OP_M (0, sizeflag);
+}
+
+static void
+SVME_Fixup (int bytemode, int sizeflag)
+{
+  const char *alt;
+  char *p;
+
+  switch (*codep)
+    {
+    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;
+    }
 }
 
 static void
@@ -4421,7 +4693,7 @@ INVLPG_Fixup (int bytemode, int sizeflag)
       alt = "rdtscp";
       break;
     default:
-      OP_E (bytemode, sizeflag);
+      OP_M (bytemode, sizeflag);
       return;
     }
   /* Override "invlpg".  */
@@ -4485,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;
+    }
+}
This page took 0.046737 seconds and 4 git commands to generate.