gas/testsuite/
[deliverable/binutils-gdb.git] / opcodes / i386-dis.c
index c169343c4a08a1de04076a31d7076a8a21507e2a..149bafb74e22f11024a928f51b4215c198854a60 100644 (file)
@@ -236,6 +236,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define Md { OP_M, d_mode }
 #define Mp { OP_M, f_mode }            /* 32 or 48 bit memory operand for LDS, LES etc */
 #define Mq { OP_M, q_mode }
+#define Mx { OP_M, x_mode }
 #define Gb { OP_G, b_mode }
 #define Gv { OP_G, v_mode }
 #define Gd { OP_G, d_mode }
@@ -491,8 +492,8 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define REG_FF                 (REG_FE + 1)
 #define REG_0F00               (REG_FF + 1)
 #define REG_0F01               (REG_0F00 + 1)
-#define REG_0F0E               (REG_0F01 + 1)
-#define REG_0F18               (REG_0F0E + 1)
+#define REG_0F0D               (REG_0F01 + 1)
+#define REG_0F18               (REG_0F0D + 1)
 #define REG_0F71               (REG_0F18 + 1)
 #define REG_0F72               (REG_0F71 + 1)
 #define REG_0F73               (REG_0F72 + 1)
@@ -541,7 +542,8 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define MOD_0FAE_REG_1         (MOD_0FAE_REG_0 + 1)
 #define MOD_0FAE_REG_2         (MOD_0FAE_REG_1 + 1)
 #define MOD_0FAE_REG_3         (MOD_0FAE_REG_2 + 1)
-#define MOD_0FAE_REG_5         (MOD_0FAE_REG_3 + 1)
+#define MOD_0FAE_REG_4         (MOD_0FAE_REG_3 + 1)
+#define MOD_0FAE_REG_5         (MOD_0FAE_REG_4 + 1)
 #define MOD_0FAE_REG_6         (MOD_0FAE_REG_5 + 1)
 #define MOD_0FAE_REG_7         (MOD_0FAE_REG_6 + 1)
 #define MOD_0FB2               (MOD_0FAE_REG_7 + 1)
@@ -559,7 +561,8 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 
 #define RM_0F01_REG_0          0
 #define RM_0F01_REG_1          (RM_0F01_REG_0 + 1)
-#define RM_0F01_REG_3          (RM_0F01_REG_1 + 1)
+#define RM_0F01_REG_2          (RM_0F01_REG_1 + 1)
+#define RM_0F01_REG_3          (RM_0F01_REG_2 + 1)
 #define RM_0F01_REG_7          (RM_0F01_REG_3 + 1)
 #define RM_0FAE_REG_5          (RM_0F01_REG_7 + 1)
 #define RM_0FAE_REG_6          (RM_0FAE_REG_5 + 1)
@@ -605,7 +608,8 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define PREFIX_0FB8            (PREFIX_0F7F + 1)
 #define PREFIX_0FBD            (PREFIX_0FB8 + 1)
 #define PREFIX_0FC2            (PREFIX_0FBD + 1)
-#define PREFIX_0FC7_REG_6      (PREFIX_0FC2 + 1)
+#define PREFIX_0FC3            (PREFIX_0FC2 + 1)
+#define PREFIX_0FC7_REG_6      (PREFIX_0FC3 + 1)
 #define PREFIX_0FD0            (PREFIX_0FC7_REG_6 + 1)
 #define PREFIX_0FD6            (PREFIX_0FD0 + 1)
 #define PREFIX_0FE6            (PREFIX_0FD6 + 1)
@@ -718,24 +722,25 @@ struct dis386 {
    'A' => print 'b' if no register operands or suffix_always is true
    'B' => print 'b' if suffix_always is true
    'C' => print 's' or 'l' ('w' or 'd' in Intel mode) depending on operand
-   .      size prefix
+         size prefix
    'D' => print 'w' if no register operands or 'w', 'l' or 'q', if
-   .      suffix_always is true
+         suffix_always is true
    'E' => print 'e' if 32-bit form of jcxz
    'F' => print 'w' or 'l' depending on address size prefix (loop insns)
    'G' => print 'w' or 'l' depending on operand size prefix (i/o insns)
    'H' => print ",pt" or ",pn" branch hint
    'I' => honor following macro letter even in Intel mode (implemented only
-   .      for some of the macro letters)
+         for some of the macro letters)
    'J' => print 'l'
    '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.
    'N' => print 'n' if instruction has no wait "prefix"
    'O' => print 'd' or 'o' (or 'q' in Intel mode)
    'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix,
-   .      or suffix_always is true.  print 'q' if rex prefix is present.
-   'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always
-   .      is true
+         or suffix_always is true.  print 'q' if rex prefix is present.
+   'Q' => print 'w', 'l' or 'q' for memory operand or suffix_always
+         is true
    'R' => print 'w', 'l' or 'q' ('d' for 'l' and 'e' in Intel mode)
    'S' => print 'w', 'l' or 'q' if suffix_always is true
    'T' => print 'q' in 64bit mode and behave as 'P' otherwise
@@ -746,6 +751,12 @@ struct dis386 {
    'Y' => 'q' if instruction has an REX 64bit overwrite prefix and
          suffix_always is true.
    'Z' => print 'q' in 64bit mode and behave as 'L' otherwise
+   '!' => change condition from true to false or from false to true.
+   '%' => add 1 upper case letter to the macro.
+
+   2 upper case letter macros:
+   'LQ' => print 'l' ('d' in Intel mode) or 'q' for memory operand
+          or suffix_always is true
 
    Many of the above letters print nothing in Intel mode.  See "putop"
    for the details.
@@ -1060,7 +1071,7 @@ static const struct dis386 dis386_twobyte[] = {
   { "(bad)",           { XX } },
   { "ud2a",            { XX } },
   { "(bad)",           { XX } },
-  { REG_TABLE (REG_0F0E) },
+  { REG_TABLE (REG_0F0D) },
   { "femms",           { XX } },
   { "",                        { MX, EM, OPSUF } }, /* See OP_3DNowSuffix.  */
   /* 10 */
@@ -1074,12 +1085,12 @@ static const struct dis386 dis386_twobyte[] = {
   { MOD_TABLE (MOD_0F17) },
   /* 18 */
   { REG_TABLE (REG_0F18) },
-  { "(bad)",           { XX } },
-  { "(bad)",           { XX } },
-  { "(bad)",           { XX } },
-  { "(bad)",           { XX } },
-  { "(bad)",           { XX } },
-  { "(bad)",           { XX } },
+  { "nopQ",            { Ev } },
+  { "nopQ",            { Ev } },
+  { "nopQ",            { Ev } },
+  { "nopQ",            { Ev } },
+  { "nopQ",            { Ev } },
+  { "nopQ",            { Ev } },
   { "nopQ",            { Ev } },
   /* 20 */
   { MOD_TABLE (MOD_0F20) },
@@ -1265,7 +1276,7 @@ static const struct dis386 dis386_twobyte[] = {
   { "xaddB",           { Eb, Gb } },
   { "xaddS",           { Ev, Gv } },
   { PREFIX_TABLE (PREFIX_0FC2) },
-  { "movntiS",         { Ev, Gv } },
+  { PREFIX_TABLE (PREFIX_0FC3) },
   { "pinsrw",          { MX, Edqw, Ib } },
   { "pextrw",          { Gdq, MS, Ib } },
   { "shufpX",          { XM, EXx, Ib } },
@@ -1362,7 +1373,7 @@ 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,1, /* 1f */
+  /* 10 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 1f */
   /* 20 */ 1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1, /* 2f */
   /* 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 */
@@ -1672,7 +1683,7 @@ static const struct dis386 reg_table[][8] = {
     { "lmsw",  { Ew } },
     { MOD_TABLE (MOD_0F01_REG_7) },
   },
-  /* REG_0F0E */
+  /* REG_0F0D */
   {
     { "prefetch",      { Eb } },
     { "prefetchw",     { Eb } },
@@ -1755,7 +1766,7 @@ static const struct dis386 reg_table[][8] = {
     { MOD_TABLE (MOD_0FAE_REG_1) },
     { MOD_TABLE (MOD_0FAE_REG_2) },
     { MOD_TABLE (MOD_0FAE_REG_3) },
-    { "(bad)", { XX } },
+    { MOD_TABLE (MOD_0FAE_REG_4) },
     { MOD_TABLE (MOD_0FAE_REG_5) },
     { MOD_TABLE (MOD_0FAE_REG_6) },
     { MOD_TABLE (MOD_0FAE_REG_7) },
@@ -1828,9 +1839,9 @@ static const struct dis386 prefix_table[][4] = {
   /* PREFIX_0F2A */
   {
     { "cvtpi2ps", { XM, EMCq } },
-    { "cvtsi2ssY", { XM, Ev } },
+    { "cvtsi2ss%LQ", { XM, Ev } },
     { "cvtpi2pd", { XM, EMCq } },
-    { "cvtsi2sdY", { XM, Ev } },
+    { "cvtsi2sd%LQ", { XM, Ev } },
   },
 
   /* PREFIX_0F2B */
@@ -2105,6 +2116,14 @@ static const struct dis386 prefix_table[][4] = {
     { "cmpsd", { XM, EXq, CMP } },
   },
 
+  /* PREFIX_0FC3 */
+  {
+    { "movntiS", { Ma, Gv } },
+    { "(bad)", { XX } },
+    { "(bad)", { XX } },
+    { "(bad)", { XX } },
+  },
+
   /* PREFIX_0FC7_REG_6 */
   {
     { "vmptrld",{ Mq } },
@@ -2139,7 +2158,7 @@ static const struct dis386 prefix_table[][4] = {
 
   /* PREFIX_0FE7 */
   {
-    { "movntq",        { EM, MX } },
+    { "movntq",        { Mq, MX } },
     { "(bad)", { XX } },
     { MOD_TABLE (MOD_0FE7_PREFIX_2) },
     { "(bad)", { XX } },
@@ -4532,7 +4551,7 @@ static const struct dis386 mod_table[][2] = {
   {
     /* MOD_0F01_REG_2 */
     { X86_64_TABLE (X86_64_0F01_REG_2) },
-    { "(bad)",         { XX } },
+    { RM_TABLE (RM_0F01_REG_2) },
   },
   {
     /* MOD_0F01_REG_3 */
@@ -4616,22 +4635,22 @@ static const struct dis386 mod_table[][2] = {
   },
   {
     /* MOD_0F2B_PREFIX_0 */
-    {"movntps",                { Ev, XM } },
+    {"movntps",                { Mx, XM } },
     { "(bad)",         { XX } },
   },
   {
     /* MOD_0F2B_PREFIX_1 */
-    {"movntss",                { Ed, XM } },
+    {"movntss",                { Md, XM } },
     { "(bad)",         { XX } },
   },
   {
     /* MOD_0F2B_PREFIX_2 */
-    {"movntpd",                { Ev, XM } },
+    {"movntpd",                { Mx, XM } },
     { "(bad)",         { XX } },
   },
   {
     /* MOD_0F2B_PREFIX_3 */
-    {"movntsd",                { Eq, XM } },
+    {"movntsd",                { Mq, XM } },
     { "(bad)",         { XX } },
   },
   {
@@ -4710,8 +4729,13 @@ static const struct dis386 mod_table[][2] = {
     { "(bad)",         { XX } },
   },
   {
-    /* MOD_0FAE_REG_5 */
+    /* MOD_0FAE_REG_4 */
+    { "xsave",         { M } },
     { "(bad)",         { XX } },
+  },
+  {
+    /* MOD_0FAE_REG_5 */
+    { "xrstor",                { M } },
     { RM_TABLE (RM_0FAE_REG_5) },
   },
   {
@@ -4756,7 +4780,7 @@ static const struct dis386 mod_table[][2] = {
   },
   {
     /* MOD_0FE7_PREFIX_2 */
-    { "movntdq",       { EM, XM } },
+    { "movntdq",       { Mx, XM } },
     { "(bad)",         { XX } },
   },
   {
@@ -4766,7 +4790,7 @@ static const struct dis386 mod_table[][2] = {
   },
   {
     /* MOD_0F382A_PREFIX_2 */
-    { "movntdqa",      { XM, EM } },
+    { "movntdqa",      { XM, Mx } },
     { "(bad)",         { XX } },
   },
   {
@@ -4809,6 +4833,17 @@ static const struct dis386 rm_table[][8] = {
     { "(bad)",         { XX } },
     { "(bad)",         { XX } },
   },
+  {
+    /* RM_0F01_REG_2 */
+    { "xgetbv",                { Skip_MODRM } },
+    { "xsetbv",                { Skip_MODRM } },
+    { "(bad)",         { XX } },
+    { "(bad)",         { XX } },
+    { "(bad)",         { XX } },
+    { "(bad)",         { XX } },
+    { "(bad)",         { XX } },
+    { "(bad)",         { XX } },
+  },
   {
     /* RM_0F01_REG_3 */
     { "vmrun",         { Skip_MODRM } },
@@ -5058,6 +5093,7 @@ static bfd_vma start_pc;
  */
 
 static char intel_syntax;
+static char intel_mnemonic = !SYSV386_COMPAT;
 static char open_char;
 static char close_char;
 static char separator_char;
@@ -5102,6 +5138,10 @@ with the -M switch (multiple options should be separated by commas):\n"));
   fprintf (stream, _("  i8086       Disassemble in 16bit mode\n"));
   fprintf (stream, _("  att         Display instruction in AT&T syntax\n"));
   fprintf (stream, _("  intel       Display instruction in Intel syntax\n"));
+  fprintf (stream, _("  att-mnemonic\n"
+                    "              Display instruction in AT&T mnemonic\n"));
+  fprintf (stream, _("  intel-mnemonic\n"
+                    "              Display instruction in Intel mnemonic\n"));
   fprintf (stream, _("  addr64      Assume 64bit address size\n"));
   fprintf (stream, _("  addr32      Assume 32bit address size\n"));
   fprintf (stream, _("  addr16      Assume 16bit address size\n"));
@@ -5245,10 +5285,14 @@ print_insn (bfd_vma pc, disassemble_info *info)
       else if (CONST_STRNEQ (p, "intel"))
        {
          intel_syntax = 1;
+         if (CONST_STRNEQ (p + 5, "-mnemonic"))
+           intel_mnemonic = 1;
        }
       else if (CONST_STRNEQ (p, "att"))
        {
          intel_syntax = 0;
+         if (CONST_STRNEQ (p + 3, "-mnemonic"))
+           intel_mnemonic = 0;
        }
       else if (CONST_STRNEQ (p, "addr"))
        {
@@ -5790,17 +5834,10 @@ static const struct dis386 float_reg[][8] = {
     { "fmul",  { STi, ST } },
     { "(bad)", { XX } },
     { "(bad)", { XX } },
-#if SYSV386_COMPAT
-    { "fsub",  { STi, ST } },
-    { "fsubr", { STi, ST } },
-    { "fdiv",  { STi, ST } },
-    { "fdivr", { STi, ST } },
-#else
-    { "fsubr", { STi, ST } },
-    { "fsub",  { STi, ST } },
-    { "fdivr", { STi, ST } },
-    { "fdiv",  { STi, ST } },
-#endif
+    { "fsub!M",        { STi, ST } },
+    { "fsubM", { STi, ST } },
+    { "fdiv!M",        { STi, ST } },
+    { "fdivM", { STi, ST } },
   },
   /* dd */
   {
@@ -5819,17 +5856,10 @@ static const struct dis386 float_reg[][8] = {
     { "fmulp", { STi, ST } },
     { "(bad)", { XX } },
     { FGRPde_3 },
-#if SYSV386_COMPAT
-    { "fsubp", { STi, ST } },
-    { "fsubrp",        { STi, ST } },
-    { "fdivp", { STi, ST } },
-    { "fdivrp",        { STi, ST } },
-#else
-    { "fsubrp",        { STi, ST } },
-    { "fsubp", { STi, ST } },
-    { "fdivrp",        { STi, ST } },
-    { "fdivp", { STi, ST } },
-#endif
+    { "fsub!Mp", { STi, ST } },
+    { "fsubMp",        { STi, ST } },
+    { "fdiv!Mp", { STi, ST } },
+    { "fdivMp",        { STi, ST } },
   },
   /* df */
   {
@@ -5967,6 +5997,15 @@ putop (const char *template, int sizeflag)
 {
   const char *p;
   int alt = 0;
+  int cond = 1;
+  unsigned int l = 0, len = 1;
+  char last[4];
+
+#define SAVE_LAST(c)                   \
+  if (l < len && l < sizeof (last))    \
+    last[l++] = c;                     \
+  else                                 \
+    abort ();
 
   for (p = template; *p; p++)
     {
@@ -5975,6 +6014,12 @@ putop (const char *template, int sizeflag)
        default:
          *obufp++ = *p;
          break;
+       case '%':
+         len++;
+         break;
+       case '!':
+         cond = 0;
+         break;
        case '{':
          alt = 0;
          if (intel_syntax)
@@ -6108,12 +6153,23 @@ putop (const char *template, int sizeflag)
              break;
            }
          /* Fall through.  */
+         goto case_L;
        case 'L':
+         if (l != 0 || len != 1)
+           {
+             SAVE_LAST (*p);
+             break;
+           }
+case_L:
          if (intel_syntax)
            break;
          if (sizeflag & SUFFIX_ALWAYS)
            *obufp++ = 'l';
          break;
+       case 'M':
+         if (intel_mnemonic != cond)
+           *obufp++ = 'r';
+         break;
        case 'N':
          if ((prefixes & PREFIX_FWAIT) == 0)
            *obufp++ = 'n';
@@ -6170,22 +6226,45 @@ putop (const char *template, int sizeflag)
              break;
            }
          /* Fall through.  */
+         goto case_Q;
        case 'Q':
-         if (intel_syntax && !alt)
-           break;
-         USED_REX (REX_W);
-         if (modrm.mod != 3 || (sizeflag & SUFFIX_ALWAYS))
+         if (l == 0 && len == 1)
            {
-             if (rex & REX_W)
-               *obufp++ = 'q';
-             else
+case_Q:
+             if (intel_syntax && !alt)
+               break;
+             USED_REX (REX_W);
+             if (modrm.mod != 3 || (sizeflag & SUFFIX_ALWAYS))
                {
-                 if (sizeflag & DFLAG)
-                   *obufp++ = intel_syntax ? 'd' : 'l';
+                 if (rex & REX_W)
+                   *obufp++ = 'q';
                  else
-                   *obufp++ = 'w';
+                   {
+                     if (sizeflag & DFLAG)
+                       *obufp++ = intel_syntax ? 'd' : 'l';
+                     else
+                       *obufp++ = 'w';
+                   }
+                 used_prefixes |= (prefixes & PREFIX_DATA);
                }
-             used_prefixes |= (prefixes & PREFIX_DATA);
+           }
+         else
+           {
+             if (l != 1 || len != 2 || last[0] != 'L')
+               {
+                 SAVE_LAST (*p);
+                 break;
+               }
+             if (intel_syntax
+                 || (modrm.mod == 3 && !(sizeflag & SUFFIX_ALWAYS)))
+               break;
+             if ((rex & REX_W))
+               {
+                 USED_REX (REX_W);
+                 *obufp++ = 'q';
+               }
+             else
+               *obufp++ = 'l';
            }
          break;
        case 'R':
@@ -6584,7 +6663,7 @@ OP_E_extended (int bytemode, int sizeflag, int has_drex)
       int havebase;
       int haveindex;
       int needindex;
-      int base;
+      int base, rbase;
       int index = 0;
       int scale = 0;
 
@@ -6606,7 +6685,7 @@ OP_E_extended (int bytemode, int sizeflag, int has_drex)
          haveindex = index != 4;
          codep++;
        }
-      base += add;
+      rbase = base + add;
 
       /* If we have a DREX byte, skip it now 
         (it has already been handled) */
@@ -6619,7 +6698,7 @@ OP_E_extended (int bytemode, int sizeflag, int has_drex)
       switch (modrm.mod)
        {
        case 0:
-         if ((base & 7) == 5)
+         if (base == 5)
            {
              havebase = 0;
              if (address_mode == mode_64bit && !havesib)
@@ -6649,7 +6728,7 @@ OP_E_extended (int bytemode, int sizeflag, int has_drex)
                  || (havesib && (haveindex || scale != 0)));
 
       if (!intel_syntax)
-       if (modrm.mod != 0 || (base & 7) == 5)
+       if (modrm.mod != 0 || base == 5)
          {
            if (havedisp || riprel)
              print_displacement (scratchbuf, disp);
@@ -6677,7 +6756,7 @@ OP_E_extended (int bytemode, int sizeflag, int has_drex)
          *obufp = '\0';
          if (havebase)
            oappend (address_mode == mode_64bit && (sizeflag & AFLAG)
-                    ? names64[base] : names32[base]);
+                    ? names64[rbase] : names32[rbase]);
          if (havesib)
            {
              /* ESP/RSP won't allow index.  If base isn't ESP/RSP,
@@ -6708,7 +6787,7 @@ OP_E_extended (int bytemode, int sizeflag, int has_drex)
                }
            }
          if (intel_syntax
-             && (disp || modrm.mod != 0 || (base & 7) == 5))
+             && (disp || modrm.mod != 0 || base == 5))
            {
              if (!havedisp || (bfd_signed_vma) disp >= 0)
                {
@@ -6734,7 +6813,7 @@ OP_E_extended (int bytemode, int sizeflag, int has_drex)
        }
       else if (intel_syntax)
        {
-         if (modrm.mod != 0 || (base & 7) == 5)
+         if (modrm.mod != 0 || base == 5)
            {
              if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
                              | PREFIX_ES | PREFIX_FS | PREFIX_GS))
This page took 0.033605 seconds and 4 git commands to generate.