/gas/ChangeLog
[deliverable/binutils-gdb.git] / opcodes / i386-dis.c
index 66fd388a4557502b646c0b488d84ac813d2ff8bd..0e9ce49e2536807cc29b30a3917713a3a8fff2ac 100644 (file)
@@ -193,16 +193,19 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define Eb OP_E, b_mode
 #define Ev OP_E, v_mode
 #define Ed OP_E, d_mode
+#define Eq OP_E, q_mode
 #define Edq OP_E, dq_mode
-#define indirEb OP_indirE, b_mode
+#define Edqw OP_E, dqw_mode
 #define indirEv OP_indirE, v_mode
+#define indirEp OP_indirE, f_mode
 #define Ew OP_E, w_mode
 #define Ma OP_E, v_mode
 #define M OP_M, 0              /* lea, lgdt, etc. */
-#define Mp OP_M, 0             /* 32 or 48 bit memory operand for LDS, LES etc */
+#define Mp OP_M, f_mode                /* 32 or 48 bit memory operand for LDS, LES etc */
 #define Gb OP_G, b_mode
 #define Gv OP_G, v_mode
 #define Gd OP_G, d_mode
+#define Gdq OP_G, dq_mode
 #define Gw OP_G, w_mode
 #define Rd OP_Rd, d_mode
 #define Rm OP_Rd, m_mode
@@ -212,6 +215,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define Iq OP_I, q_mode
 #define Iv64 OP_I64, v_mode
 #define Iw OP_I, w_mode
+#define I1 OP_I, const_1_mode
 #define Jb OP_J, b_mode
 #define Jv OP_J, v_mode
 #define Cm OP_C, m_mode
@@ -308,11 +312,15 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define w_mode 3  /* word operand */
 #define d_mode 4  /* double word operand  */
 #define q_mode 5  /* quad word operand */
-#define x_mode 6  /* 80 bit float operand */
-#define m_mode 7  /* d_mode in 32bit, q_mode in 64bit mode.  */
-#define cond_jump_mode 8
-#define loop_jcxz_mode 9
-#define dq_mode 10 /* operand size depends on REX prefixes.  */
+#define t_mode 6  /* ten-byte operand */
+#define x_mode 7  /* 16-byte XMM operand */
+#define m_mode 8  /* d_mode in 32bit, q_mode in 64bit mode.  */
+#define cond_jump_mode 9
+#define loop_jcxz_mode 10
+#define dq_mode 11 /* operand size depends on REX prefixes.  */
+#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 es_reg 100
 #define cs_reg 101
@@ -443,9 +451,14 @@ struct dis386 {
 /* Upper case letters in the instruction names here are macros.
    '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
    'E' => print 'e' if 32-bit form of jcxz
    'F' => print 'w' or 'l' depending on address size prefix (loop 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)
+   'J' => print 'l'
    'L' => print 'l' if suffix_always is true
    'N' => print 'n' if instruction has no wait "prefix"
    'O' => print 'd', or 'o'
@@ -457,8 +470,8 @@ 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
-   'X' => print 's', 'd' depending on data16 prefix (for XMM)
    '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
 
    Many of the above letters print nothing in Intel mode.  See "putop"
@@ -645,7 +658,7 @@ static const struct dis386 dis386[] = {
   /* 98 */
   { "cW{tR||tR|}",     XX, XX, XX },
   { "cR{tO||tO|}",     XX, XX, XX },
-  { "lcall{T|}",       Ap, XX, XX },
+  { "Jcall{T|}",       Ap, XX, XX },
   { "(bad)",           XX, XX, XX },   /* fwait */
   { "pushfT",          XX, XX, XX },
   { "popfT",           XX, XX, XX },
@@ -735,7 +748,7 @@ static const struct dis386 dis386[] = {
   /* e8 */
   { "callT",           Jv, XX, XX },
   { "jmpT",            Jv, XX, XX },
-  { "ljmp{T|}",                Ap, XX, XX },
+  { "Jjmp{T|}",                Ap, XX, XX },
   { "jmp",             Jb, XX, XX },
   { "inB",             AL, indirDX, XX },
   { "inS",             eAX, indirDX, XX },
@@ -853,7 +866,7 @@ static const struct dis386 dis386_twobyte[] = {
   { "cmovle",          Gv, Ev, XX },
   { "cmovg",           Gv, Ev, XX },
   /* 50 */
-  { "movmskpX",                Gd, XS, XX },
+  { "movmskpX",                Gdq, XS, XX },
   { PREGRP13 },
   { PREGRP12 },
   { PREGRP11 },
@@ -983,8 +996,8 @@ static const struct dis386 dis386_twobyte[] = {
   { "xaddS",           Ev, Gv, XX },
   { PREGRP1 },
   { "movntiS",         Ev, Gv, XX },
-  { "pinsrw",          MX, Ed, Ib },
-  { "pextrw",          Gd, MS, Ib },
+  { "pinsrw",          MX, Edqw, Ib },
+  { "pextrw",          Gdq, MS, Ib },
   { "shufpX",          XM, EX, Ib },
   { GRP9 },
   /* c8 */
@@ -1004,7 +1017,7 @@ static const struct dis386 dis386_twobyte[] = {
   { "paddq",           MX, EM, XX },
   { "pmullw",          MX, EM, XX },
   { PREGRP21 },
-  { "pmovmskb",                Gd, MS, XX },
+  { "pmovmskb",                Gdq, MS, XX },
   /* d8 */
   { "psubusb",         MX, EM, XX },
   { "psubusw",         MX, EM, XX },
@@ -1256,25 +1269,25 @@ static const struct dis386 grps[][8] = {
   },
   /* GRP2b_one */
   {
-    { "rolA",  Eb, XX, XX },
-    { "rorA",  Eb, XX, XX },
-    { "rclA",  Eb, XX, XX },
-    { "rcrA",  Eb, XX, XX },
-    { "shlA",  Eb, XX, XX },
-    { "shrA",  Eb, XX, XX },
+    { "rolA",  Eb, I1, XX },
+    { "rorA",  Eb, I1, XX },
+    { "rclA",  Eb, I1, XX },
+    { "rcrA",  Eb, I1, XX },
+    { "shlA",  Eb, I1, XX },
+    { "shrA",  Eb, I1, XX },
     { "(bad)", XX, XX, XX },
-    { "sarA",  Eb, XX, XX },
+    { "sarA",  Eb, I1, XX },
   },
   /* GRP2S_one */
   {
-    { "rolQ",  Ev, XX, XX },
-    { "rorQ",  Ev, XX, XX },
-    { "rclQ",  Ev, XX, XX },
-    { "rcrQ",  Ev, XX, XX },
-    { "shlQ",  Ev, XX, XX },
-    { "shrQ",  Ev, XX, XX },
+    { "rolQ",  Ev, I1, XX },
+    { "rorQ",  Ev, I1, XX },
+    { "rclQ",  Ev, I1, XX },
+    { "rcrQ",  Ev, I1, XX },
+    { "shlQ",  Ev, I1, XX },
+    { "shrQ",  Ev, I1, XX },
     { "(bad)", XX, XX, XX},
-    { "sarQ",  Ev, XX, XX },
+    { "sarQ",  Ev, I1, XX },
   },
   /* GRP2b_cl */
   {
@@ -1336,9 +1349,9 @@ static const struct dis386 grps[][8] = {
     { "incQ",  Ev, XX, XX },
     { "decQ",  Ev, XX, XX },
     { "callT", indirEv, XX, XX },
-    { "lcallT",        indirEv, XX, XX },
+    { "JcallT",        indirEp, XX, XX },
     { "jmpT",  indirEv, XX, XX },
-    { "ljmpT", indirEv, XX, XX },
+    { "JjmpT", indirEp, XX, XX },
     { "pushU", Ev, XX, XX },
     { "(bad)", XX, XX, XX },
   },
@@ -1355,10 +1368,10 @@ static const struct dis386 grps[][8] = {
   },
   /* GRP7 */
   {
-    { "sgdtQ",  M, XX, XX },
-    { "sidtQ", PNI_Fixup, 0, XX, XX },
-    { "lgdtQ",  M, XX, XX },
-    { "lidtQ",  M, XX, XX },
+    { "sgdtIQ",         M, XX, XX },
+    { "sidtIQ", PNI_Fixup, 0, XX, XX },
+    { "lgdt{Q|Q||}",    M, XX, XX },
+    { "lidt{Q|Q||}",    M, XX, XX },
     { "smswQ", Ev, XX, XX },
     { "(bad)", XX, XX, XX },
     { "lmsw",  Ew, XX, XX },
@@ -1378,7 +1391,7 @@ static const struct dis386 grps[][8] = {
   /* GRP9 */
   {
     { "(bad)", XX, XX, XX },
-    { "cmpxchg8b", Ev, XX, XX },
+    { "cmpxchg8b", Eq, XX, XX },
     { "(bad)", XX, XX, XX },
     { "(bad)", XX, XX, XX },
     { "(bad)", XX, XX, XX },
@@ -1654,10 +1667,10 @@ static const struct dis386 prefix_user_table[][4] = {
   },
   /* PREGRP25 */
   {
-  { "movntq", Ev, MX, XX },
-  { "(bad)", Ev, XM, XX },
-  { "movntdq", Ev, XM, XX },
-  { "(bad)", Ev, XM, XX },
+    { "movntq", EM, MX, XX },
+    { "(bad)", EM, XM, XX },
+    { "movntdq", EM, XM, XX },
+    { "(bad)", EM, XM, XX },
   },
   /* PREGRP26 */
   {
@@ -2339,9 +2352,9 @@ static const char *float_mem[] = {
   "(bad)",
   "fst{s||s|}",
   "fstp{s||s|}",
-  "fldenv",
+  "fldenvIC",
   "fldcw",
-  "fNstenv",
+  "fNstenvIC",
   "fNstcw",
   /* da */
   "fiadd{l||l|}",
@@ -2375,9 +2388,9 @@ static const char *float_mem[] = {
   "fisttp{ll||ll|}",
   "fst{l||l|}",
   "fstp{l||l|}",
-  "frstor",
+  "frstorIC",
   "(bad)",
-  "fNsave",
+  "fNsaveIC",
   "fNstsw",
   /* de */
   "fiadd",
@@ -2433,9 +2446,9 @@ static const unsigned char float_mem_mode[] = {
   d_mode,
   d_mode,
   0,
-  x_mode,
+  t_mode,
   0,
-  x_mode,
+  t_mode,
   /* dc */
   q_mode,
   q_mode,
@@ -2468,9 +2481,9 @@ static const unsigned char float_mem_mode[] = {
   w_mode,
   w_mode,
   w_mode,
-  x_mode,
+  t_mode,
   q_mode,
-  x_mode,
+  t_mode,
   q_mode
 };
 
@@ -2701,7 +2714,7 @@ static int
 putop (const char *template, int sizeflag)
 {
   const char *p;
-  int alt;
+  int alt = 0;
 
   for (p = template; *p; p++)
     {
@@ -2732,7 +2745,10 @@ putop (const char *template, int sizeflag)
                }
              alt--;
            }
-         break;
+         /* Fall through.  */
+       case 'I':
+         alt = 1;
+         continue;
        case '|':
          while (*++p != '}')
            {
@@ -2754,6 +2770,18 @@ putop (const char *template, int sizeflag)
          if (sizeflag & SUFFIX_ALWAYS)
            *obufp++ = 'b';
          break;
+       case 'C':
+         if (intel_syntax && !alt)
+           break;
+         if ((prefixes & PREFIX_DATA) || (sizeflag & SUFFIX_ALWAYS))
+           {
+             if (sizeflag & DFLAG)
+               *obufp++ = intel_syntax ? 'd' : 'l';
+             else
+               *obufp++ = intel_syntax ? 'w' : 's';
+             used_prefixes |= (prefixes & PREFIX_DATA);
+           }
+         break;
        case 'E':               /* For jcxz/jecxz */
          if (mode_64bit)
            {
@@ -2794,6 +2822,11 @@ putop (const char *template, int sizeflag)
                *obufp++ = 'n';
            }
          break;
+       case 'J':
+         if (intel_syntax)
+           break;
+         *obufp++ = 'l';
+         break;
        case 'L':
          if (intel_syntax)
            break;
@@ -2852,7 +2885,7 @@ putop (const char *template, int sizeflag)
            }
          /* Fall through.  */
        case 'Q':
-         if (intel_syntax)
+         if (intel_syntax && !alt)
            break;
          USED_REX (REX_MODE64);
          if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
@@ -2862,7 +2895,7 @@ putop (const char *template, int sizeflag)
              else
                {
                  if (sizeflag & DFLAG)
-                   *obufp++ = 'l';
+                   *obufp++ = intel_syntax ? 'd' : 'l';
                  else
                    *obufp++ = 'w';
                  used_prefixes |= (prefixes & PREFIX_DATA);
@@ -2965,6 +2998,7 @@ putop (const char *template, int sizeflag)
            used_prefixes |= (prefixes & PREFIX_DATA);
          break;
        }
+      alt = 0;
     }
   *obufp = 0;
   return 0;
@@ -3119,10 +3153,11 @@ OP_E (int bytemode, int sizeflag)
          break;
        case v_mode:
        case dq_mode:
+       case dqw_mode:
          USED_REX (REX_MODE64);
          if (rex & REX_MODE64)
            oappend (names64[rm + add]);
-         else if ((sizeflag & DFLAG) || bytemode == dq_mode)
+         else if ((sizeflag & DFLAG) || bytemode != v_mode)
            oappend (names32[rm + add]);
          else
            oappend (names16[rm + add]);
@@ -3156,8 +3191,10 @@ OP_E (int bytemode, int sizeflag)
        {
          havesib = 1;
          FETCH_DATA (the_info, codep + 1);
-         scale = (*codep >> 6) & 3;
          index = (*codep >> 3) & 7;
+         if (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);
@@ -3212,13 +3249,19 @@ OP_E (int bytemode, int sizeflag)
                  oappend ("BYTE PTR ");
                  break;
                case w_mode:
+               case dqw_mode:
                  oappend ("WORD PTR ");
                  break;
                case v_mode:
-                 if (sizeflag & DFLAG)
+               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 ");
@@ -3228,17 +3271,29 @@ OP_E (int bytemode, int sizeflag)
                  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 ("QWORD PTR ");
+                   oappend ("DWORD PTR ");
+                 break;
+               case t_mode:
+                 oappend ("TBYTE PTR ");
                  break;
                case x_mode:
-                 oappend ("XWORD PTR ");
+                 oappend ("XMMWORD PTR ");
                  break;
                default:
                  break;
                }
-            }
+           }
          *obufp++ = open_char;
          if (intel_syntax && riprel)
            oappend ("rip + ");
@@ -3253,22 +3308,13 @@ OP_E (int bytemode, int sizeflag)
            {
              if (index != 4)
                {
-                 if (intel_syntax)
+                 if (!intel_syntax || havebase)
                    {
-                     if (havebase)
-                       {
-                         *obufp++ = separator_char;
-                         *obufp = '\0';
-                       }
-                     sprintf (scratchbuf, "%s",
-                              mode_64bit && (sizeflag & AFLAG)
-                              ? names64[index] : names32[index]);
+                     *obufp++ = separator_char;
+                     *obufp = '\0';
                    }
-                 else
-                   sprintf (scratchbuf, ",%s",
-                            mode_64bit && (sizeflag & AFLAG)
-                            ? names64[index] : names32[index]);
-                 oappend (scratchbuf);
+                 oappend (mode_64bit && (sizeflag & AFLAG)
+                          ? names64[index] : names32[index]);
                }
              if (scale != 0 || (!intel_syntax && index != 4))
                {
@@ -3384,10 +3430,12 @@ OP_G (int bytemode, int sizeflag)
       oappend (names64[reg + add]);
       break;
     case v_mode:
+    case dq_mode:
+    case dqw_mode:
       USED_REX (REX_MODE64);
       if (rex & REX_MODE64)
        oappend (names64[reg + add]);
-      else if (sizeflag & DFLAG)
+      else if ((sizeflag & DFLAG) || bytemode != v_mode)
        oappend (names32[reg + add]);
       else
        oappend (names16[reg + add]);
@@ -3628,6 +3676,10 @@ OP_I (int bytemode, int sizeflag)
       mask = 0xfffff;
       op = get16 ();
       break;
+    case const_1_mode:
+      if (intel_syntax)
+        oappend ("1");
+      return;
     default:
       oappend (INTERNAL_DISASSEMBLER_ERROR);
       return;
@@ -3884,6 +3936,23 @@ ptr_reg (int code, int sizeflag)
 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 ");
+    }
+
   oappend ("%es:" + intel_syntax);
   ptr_reg (code, sizeflag);
 }
@@ -3891,6 +3960,23 @@ OP_ESreg (int code, int sizeflag)
 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 ");
+    }
+
   if ((prefixes
        & (PREFIX_CS
          | PREFIX_DS
@@ -3977,6 +4063,11 @@ OP_EM (int bytemode, int sizeflag)
 {
   if (mod != 3)
     {
+      if (intel_syntax && bytemode == v_mode)
+       {
+         bytemode = (prefixes & PREFIX_DATA) ? x_mode : q_mode;
+         used_prefixes |= (prefixes & PREFIX_DATA);
+       }
       OP_E (bytemode, sizeflag);
       return;
     }
@@ -4005,6 +4096,17 @@ OP_EX (int bytemode, int sizeflag)
   int add = 0;
   if (mod != 3)
     {
+      if (intel_syntax && bytemode == v_mode)
+       {
+         switch (prefixes & (PREFIX_DATA|PREFIX_REPZ|PREFIX_REPNZ))
+           {
+           case 0:            bytemode = x_mode; break;
+           case PREFIX_REPZ:  bytemode = d_mode; used_prefixes |= PREFIX_REPZ;  break;
+           case PREFIX_DATA:  bytemode = x_mode; used_prefixes |= PREFIX_DATA;  break;
+           case PREFIX_REPNZ: bytemode = q_mode; used_prefixes |= PREFIX_REPNZ; break;
+           default:           bytemode = 0; break;
+           }
+       }
       OP_E (bytemode, sizeflag);
       return;
     }
This page took 0.031619 seconds and 4 git commands to generate.