]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - opcodes/i386-dis.c
x86: fix processing of -M disassembler option
[thirdparty/binutils-gdb.git] / opcodes / i386-dis.c
index f6a0c51d2fb482af35fffa4db7adeaff59a88c17..f57409dd17a89a2326f3a1689763dfec47682641 100644 (file)
@@ -153,8 +153,6 @@ static int prefixes;
 static int rex;
 /* Bits of REX we've already used.  */
 static int rex_used;
-/* REX bits in original REX prefix ignored.  */
-static int rex_ignored;
 /* Mark parts used in the REX prefix.  When we are testing for
    empty prefix (for 8bit register REX extension), just mask it
    out.  Otherwise test for REX bit is excuse for existence of REX
@@ -778,8 +776,10 @@ enum
   MOD_0F01_REG_5,
   MOD_0F01_REG_7,
   MOD_0F12_PREFIX_0,
+  MOD_0F12_PREFIX_2,
   MOD_0F13,
   MOD_0F16_PREFIX_0,
+  MOD_0F16_PREFIX_2,
   MOD_0F17,
   MOD_0F18_REG_0,
   MOD_0F18_REG_1,
@@ -842,8 +842,10 @@ enum
   MOD_C4_32BIT,
   MOD_C5_32BIT,
   MOD_VEX_0F12_PREFIX_0,
+  MOD_VEX_0F12_PREFIX_2,
   MOD_VEX_0F13,
   MOD_VEX_0F16_PREFIX_0,
+  MOD_VEX_0F16_PREFIX_2,
   MOD_VEX_0F17,
   MOD_VEX_0F2B,
   MOD_VEX_W_0_0F41_P_0_LEN_1,
@@ -1799,11 +1801,11 @@ enum
 {
   VEX_LEN_0F12_P_0_M_0 = 0,
   VEX_LEN_0F12_P_0_M_1,
-  VEX_LEN_0F12_P_2,
+#define VEX_LEN_0F12_P_2_M_0 VEX_LEN_0F12_P_0_M_0
   VEX_LEN_0F13_M_0,
   VEX_LEN_0F16_P_0_M_0,
   VEX_LEN_0F16_P_0_M_1,
-  VEX_LEN_0F16_P_2,
+#define VEX_LEN_0F16_P_2_M_0 VEX_LEN_0F16_P_0_M_0
   VEX_LEN_0F17_M_0,
   VEX_LEN_0F41_P_0,
   VEX_LEN_0F41_P_2,
@@ -2250,7 +2252,7 @@ struct dis386 {
    'H' => print ",pt" or ",pn" branch hint
    'I' => honor following macro letter even in Intel mode (implemented only
          for some of the macro letters)
-   'J' => print 'l'
+   'J' unused.
    'K' => print 'd' or 'q' if rex prefix is present.
    'L' => print 'l' if suffix_always is true
    'M' => print 'r' if intel_mnemonic is false.
@@ -2288,8 +2290,9 @@ struct dis386 {
    "XZ" => print 'x', 'y', or 'z' if suffix_always is true or no
           register operands and no broadcast.
    "XW" => print 's', 'd' depending on the VEX.W bit (for FMA)
-   "LQ" => print 'l' ('d' in Intel mode) or 'q' for memory operand
-          or suffix_always is true
+   "LQ" => print 'l' ('d' in Intel mode) or 'q' for memory
+          operand or no operand at all in 64bit mode, or if suffix_always
+          is true.
    "LB" => print "abs" in 64bit mode and behave as 'B' otherwise
    "LS" => print "abs" in 64bit mode and behave as 'S' otherwise
    "LV" => print "abs" for 64bit operand and behave as 'S' otherwise
@@ -2533,8 +2536,8 @@ static const struct dis386 dis386[] = {
   /* c8 */
   { "enterT",          { Iw, Ib }, 0 },
   { "leaveT",          { XX }, 0 },
-  { "Jret{|f}P",       { Iw }, 0 },
-  { "Jret{|f}P",       { XX }, 0 },
+  { "{l|}ret{|f}P",    { Iw }, 0 },
+  { "{l|}ret{|f}P",    { XX }, 0 },
   { "int3",            { XX }, 0 },
   { "int",             { Ib }, 0 },
   { X86_64_TABLE (X86_64_CE) },
@@ -2604,7 +2607,7 @@ static const struct dis386 dis386_twobyte[] = {
   { Bad_Opcode },
   { "syscall",         { XX }, 0 },
   { "clts",            { XX }, 0 },
-  { "sysret%LP",               { XX }, 0 },
+  { "sysret%LQ",               { XX }, 0 },
   /* 08 */
   { "invd",            { XX }, 0 },
   { PREFIX_TABLE (PREFIX_0F09) },
@@ -3570,7 +3573,7 @@ static const struct dis386 prefix_table[][4] = {
     { NULL, { { NULL, 0 } }, PREFIX_IGNORED }
   },
 
-  /* PREFIX_0F01_REG_3_MOD_1 */
+  /* PREFIX_0F01_REG_3_RM_1 */
   {
     { "vmmcall",       { Skip_MODRM }, 0 },
     { "vmgexit",       { Skip_MODRM }, 0 },
@@ -3589,7 +3592,7 @@ static const struct dis386 prefix_table[][4] = {
     { "serialize",     { Skip_MODRM }, PREFIX_OPCODE },
     { "setssbsy",      { Skip_MODRM }, PREFIX_OPCODE },
     { Bad_Opcode },
-    { "xsuspldtrk",     { Skip_MODRM }, PREFIX_OPCODE },
+    { "xsusldtrk",     { Skip_MODRM }, PREFIX_OPCODE },
   },
 
   /* PREFIX_0F01_REG_5_MOD_3_RM_1 */
@@ -3643,7 +3646,7 @@ static const struct dis386 prefix_table[][4] = {
   {
     { MOD_TABLE (MOD_0F12_PREFIX_0) },
     { "movsldup", { XM, EXx }, PREFIX_OPCODE },
-    { "movlpd",        { XM, EXq }, PREFIX_OPCODE },
+    { MOD_TABLE (MOD_0F12_PREFIX_2) },
     { "movddup", { XM, EXq }, PREFIX_OPCODE },
   },
 
@@ -3651,7 +3654,7 @@ static const struct dis386 prefix_table[][4] = {
   {
     { MOD_TABLE (MOD_0F16_PREFIX_0) },
     { "movshdup", { XM, EXx }, PREFIX_OPCODE },
-    { "movhpd",        { XM, EXq }, PREFIX_OPCODE },
+    { MOD_TABLE (MOD_0F16_PREFIX_2) },
   },
 
   /* PREFIX_0F1A */
@@ -4648,7 +4651,7 @@ static const struct dis386 prefix_table[][4] = {
   {
     { MOD_TABLE (MOD_VEX_0F12_PREFIX_0) },
     { "vmovsldup",     { XM, EXx }, 0 },
-    { VEX_LEN_TABLE (VEX_LEN_0F12_P_2) },
+    { MOD_TABLE (MOD_VEX_0F12_PREFIX_2) },
     { "vmovddup",      { XM, EXymmq }, 0 },
   },
 
@@ -4656,7 +4659,7 @@ static const struct dis386 prefix_table[][4] = {
   {
     { MOD_TABLE (MOD_VEX_0F16_PREFIX_0) },
     { "vmovshdup",     { XM, EXx }, 0 },
-    { VEX_LEN_TABLE (VEX_LEN_0F16_P_2) },
+    { MOD_TABLE (MOD_VEX_0F16_PREFIX_2) },
   },
 
   /* PREFIX_VEX_0F2A */
@@ -6854,7 +6857,7 @@ static const struct dis386 x86_64_table[][2] = {
 
   /* X86_64_9A */
   {
-    { "Jcall{T|}", { Ap }, 0 },
+    { "{l|}call{T|}", { Ap }, 0 },
   },
 
   /* X86_64_C2 */
@@ -6910,7 +6913,7 @@ static const struct dis386 x86_64_table[][2] = {
 
   /* X86_64_EA */
   {
-    { "Jjmp{T|}", { Ap }, 0 },
+    { "{l|}jmp{T|}", { Ap }, 0 },
   },
 
   /* X86_64_0F01_REG_0 */
@@ -9279,9 +9282,9 @@ static const struct dis386 vex_table[][256] = {
 #include "i386-dis-evex.h"
 
 static const struct dis386 vex_len_table[][2] = {
-  /* VEX_LEN_0F12_P_0_M_0 */
+  /* VEX_LEN_0F12_P_0_M_0 / VEX_LEN_0F12_P_2_M_0 */
   {
-    { "vmovlps",       { XM, Vex128, EXq }, 0 },
+    { "vmovlpX",       { XM, Vex128, EXq }, 0 },
   },
 
   /* VEX_LEN_0F12_P_0_M_1 */
@@ -9289,19 +9292,14 @@ static const struct dis386 vex_len_table[][2] = {
     { "vmovhlps",      { XM, Vex128, EXq }, 0 },
   },
 
-  /* VEX_LEN_0F12_P_2 */
-  {
-    { "vmovlpd",       { XM, Vex128, EXq }, 0 },
-  },
-
   /* VEX_LEN_0F13_M_0 */
   {
     { "vmovlpX",       { EXq, XM }, PREFIX_OPCODE },
   },
 
-  /* VEX_LEN_0F16_P_0_M_0 */
+  /* VEX_LEN_0F16_P_0_M_0 / VEX_LEN_0F16_P_2_M_0 */
   {
-    { "vmovhps",       { XM, Vex128, EXq }, 0 },
+    { "vmovhpX",       { XM, Vex128, EXq }, 0 },
   },
 
   /* VEX_LEN_0F16_P_0_M_1 */
@@ -9309,11 +9307,6 @@ static const struct dis386 vex_len_table[][2] = {
     { "vmovlhps",      { XM, Vex128, EXq }, 0 },
   },
 
-  /* VEX_LEN_0F16_P_2 */
-  {
-    { "vmovhpd",       { XM, Vex128, EXq }, 0 },
-  },
-
   /* VEX_LEN_0F17_M_0 */
   {
     { "vmovhpX",       { EXq, XM }, PREFIX_OPCODE },
@@ -10187,11 +10180,11 @@ static const struct dis386 mod_table[][2] = {
   },
   {
     /* MOD_FF_REG_3 */
-    { "Jcall^", { indirEp }, 0 },
+    { "{l|}call^", { indirEp }, 0 },
   },
   {
     /* MOD_FF_REG_5 */
-    { "Jjmp^", { indirEp }, 0 },
+    { "{l|}jmp^", { indirEp }, 0 },
   },
   {
     /* MOD_0F01_REG_0 */
@@ -10225,8 +10218,12 @@ static const struct dis386 mod_table[][2] = {
   },
   {
     /* MOD_0F12_PREFIX_0 */
-    { "movlps",                { XM, EXq }, PREFIX_OPCODE },
-    { "movhlps",       { XM, EXq }, PREFIX_OPCODE },
+    { "movlpX",                { XM, EXq }, 0 },
+    { "movhlps",       { XM, EXq }, 0 },
+  },
+  {
+    /* MOD_0F12_PREFIX_2 */
+    { "movlpX",        { XM, EXq }, 0 },
   },
   {
     /* MOD_0F13 */
@@ -10234,9 +10231,13 @@ static const struct dis386 mod_table[][2] = {
   },
   {
     /* MOD_0F16_PREFIX_0 */
-    { "movhps",                { XM, EXq }, 0 },
+    { "movhpX",                { XM, EXq }, 0 },
     { "movlhps",       { XM, EXq }, 0 },
   },
+  {
+    /* MOD_0F16_PREFIX_2 */
+    { "movhpX",        { XM, EXq }, 0 },
+  },
   {
     /* MOD_0F17 */
     { "movhpX",                { EXq, XM }, PREFIX_OPCODE },
@@ -10518,6 +10519,10 @@ static const struct dis386 mod_table[][2] = {
     { VEX_LEN_TABLE (VEX_LEN_0F12_P_0_M_0) },
     { VEX_LEN_TABLE (VEX_LEN_0F12_P_0_M_1) },
   },
+  {
+    /* MOD_VEX_0F12_PREFIX_2 */
+    { VEX_LEN_TABLE (VEX_LEN_0F12_P_2_M_0) },
+  },
   {
     /* MOD_VEX_0F13 */
     { VEX_LEN_TABLE (VEX_LEN_0F13_M_0) },
@@ -10527,6 +10532,10 @@ static const struct dis386 mod_table[][2] = {
     { VEX_LEN_TABLE (VEX_LEN_0F16_P_0_M_0) },
     { VEX_LEN_TABLE (VEX_LEN_0F16_P_0_M_1) },
   },
+  {
+    /* MOD_VEX_0F16_PREFIX_2 */
+    { VEX_LEN_TABLE (VEX_LEN_0F16_P_2_M_0) },
+  },
   {
     /* MOD_VEX_0F17 */
     { VEX_LEN_TABLE (VEX_LEN_0F17_M_0) },
@@ -11047,7 +11056,6 @@ ckprefix (void)
 {
   int newrex, i, length;
   rex = 0;
-  rex_ignored = 0;
   prefixes = 0;
   used_prefixes = 0;
   rex_used = 0;
@@ -11507,8 +11515,6 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
 
     case USE_XOP_8F_TABLE:
       FETCH_DATA (info, codep + 3);
-      /* All bits in the REX prefix are ignored.  */
-      rex_ignored = rex;
       rex = ~(*codep >> 5) & 0x7;
 
       /* VEX_TABLE_INDEX is the mmmmm part of the XOP byte 1 "RCB.mmmmm".  */
@@ -11570,8 +11576,6 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
     case USE_VEX_C4_TABLE:
       /* VEX prefix.  */
       FETCH_DATA (info, codep + 3);
-      /* All bits in the REX prefix are ignored.  */
-      rex_ignored = rex;
       rex = ~(*codep >> 5) & 0x7;
       switch ((*codep & 0x1f))
        {
@@ -11637,8 +11641,6 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
     case USE_VEX_C5_TABLE:
       /* VEX prefix.  */
       FETCH_DATA (info, codep + 2);
-      /* All bits in the REX prefix are ignored.  */
-      rex_ignored = rex;
       rex = (*codep & 0x80) ? 0 : REX_R;
 
       /* For the 2-byte VEX prefix in 32-bit mode, the highest bit in
@@ -11687,8 +11689,6 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
       /* EVEX prefix.  */
       vex.evex = 1;
       FETCH_DATA (info, codep + 4);
-      /* All bits in the REX prefix are ignored.  */
-      rex_ignored = rex;
       /* The first byte after 0x62.  */
       rex = ~(*codep >> 5) & 0x7;
       vex.r = *codep & 0x10;
@@ -11851,17 +11851,17 @@ print_insn (bfd_vma pc, disassemble_info *info)
       else if (CONST_STRNEQ (p, "x86-64"))
        {
          address_mode = mode_64bit;
-         priv.orig_sizeflag = AFLAG | DFLAG;
+         priv.orig_sizeflag |= AFLAG | DFLAG;
        }
       else if (CONST_STRNEQ (p, "i386"))
        {
          address_mode = mode_32bit;
-         priv.orig_sizeflag = AFLAG | DFLAG;
+         priv.orig_sizeflag |= AFLAG | DFLAG;
        }
       else if (CONST_STRNEQ (p, "i8086"))
        {
          address_mode = mode_16bit;
-         priv.orig_sizeflag = 0;
+         priv.orig_sizeflag &= ~(AFLAG | DFLAG);
        }
       else if (CONST_STRNEQ (p, "intel"))
        {
@@ -12169,7 +12169,7 @@ print_insn (bfd_vma pc, disassemble_info *info)
     }
 
   /* Check if the REX prefix is used.  */
-  if (rex_ignored == 0 && (rex ^ rex_used) == 0 && last_rex_prefix >= 0)
+  if ((rex ^ rex_used) == 0 && !need_vex && last_rex_prefix >= 0)
     all_prefixes[last_rex_prefix] = 0;
 
   /* Check if the SEG prefix is used.  */
@@ -12185,7 +12185,8 @@ print_insn (bfd_vma pc, disassemble_info *info)
 
   /* Check if the DATA prefix is used.  */
   if ((prefixes & PREFIX_DATA) != 0
-      && (used_prefixes & PREFIX_DATA) != 0)
+      && (used_prefixes & PREFIX_DATA) != 0
+      && !need_vex)
     all_prefixes[last_data_prefix] = 0;
 
   /* Print the extra prefixes.  */
@@ -12341,9 +12342,9 @@ static const char *float_mem[] = {
   "fist{l|}",
   "fistp{l|}",
   "(bad)",
-  "fld{t||t|}",
+  "fld{t|}",
   "(bad)",
-  "fstp{t||t|}",
+  "fstp{t|}",
   /* dc */
   "fadd{l|}",
   "fmul{l|}",
@@ -12866,11 +12867,6 @@ putop (const char *in_template, int sizeflag)
                *obufp++ = 'n';
            }
          break;
-       case 'J':
-         if (intel_syntax)
-           break;
-         *obufp++ = 'l';
-         break;
        case 'K':
          USED_REX (REX_W);
          if (rex & REX_W)
@@ -13066,7 +13062,7 @@ putop (const char *in_template, int sizeflag)
                  SAVE_LAST (*p);
                  break;
                }
-             if (intel_syntax
+             if ((intel_syntax && need_modrm)
                  || (modrm.mod == 3 && !(sizeflag & SUFFIX_ALWAYS)))
                break;
              if ((rex & REX_W))
@@ -13074,8 +13070,9 @@ putop (const char *in_template, int sizeflag)
                  USED_REX (REX_W);
                  *obufp++ = 'q';
                }
-             else
-               *obufp++ = 'l';
+             else if((address_mode == mode_64bit && need_modrm)
+                     || (sizeflag & SUFFIX_ALWAYS))
+               *obufp++ = intel_syntax? 'd' : 'l';
            }
          break;
        case 'R':