x86: Properly decode EVEX.W in vcvt[u]si2s[sd] in 32-bit mode
[deliverable/binutils-gdb.git] / opcodes / i386-dis.c
index f2ad0fad0f80db1c7640286b82e0f88ae1138454..83c610703dc81a843cf741888cbc356f2be49809 100644 (file)
@@ -260,6 +260,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define Edb { OP_E, db_mode }
 #define Edw { OP_E, dw_mode }
 #define Edqd { OP_E, dqd_mode }
+#define Edqa { OP_E, dqa_mode }
 #define Eq { OP_E, q_mode }
 #define indirEv { OP_indirE, indir_v_mode }
 #define indirEp { OP_indirE, f_mode }
@@ -273,6 +274,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define Mo { OP_M, o_mode }
 #define Mp { OP_M, f_mode }            /* 32 or 48 bit memory operand for LDS, LES etc */
 #define Mq { OP_M, q_mode }
+#define Mv_bnd { OP_M, v_bndmk_mode }
 #define Mx { OP_M, x_mode }
 #define Mxmm { OP_M, xmm_mode }
 #define Gb { OP_G, b_mode }
@@ -561,6 +563,8 @@ enum
   cond_jump_mode,
   loop_jcxz_mode,
   v_bnd_mode,
+  /* like v_bnd_mode in 32bit, no RIP-rel in 64bit mode.  */
+  v_bndmk_mode,
   /* operand size depends on REX prefixes.  */
   dq_mode,
   /* registers like dq_mode, memory like w_mode.  */
@@ -588,6 +592,8 @@ enum
   dw_mode,
   /* registers like dq_mode, memory like d_mode.  */
   dqd_mode,
+  /* operand size depends on the W bit as well as address mode.  */
+  dqa_mode,
   /* normal vex mode */
   vex_mode,
   /* 128bit vex mode */
@@ -11646,17 +11652,17 @@ static const struct dis386 mod_table[][2] = {
   },
   {
     /* MOD_0F1A_PREFIX_0 */
-    { "bndldx",                { Gbnd, Ev_bnd }, 0 },
+    { "bndldx",                { Gbnd, Mv_bnd }, 0 },
     { "nopQ",          { Ev }, 0 },
   },
   {
     /* MOD_0F1B_PREFIX_0 */
-    { "bndstx",                { Ev_bnd, Gbnd }, 0 },
+    { "bndstx",                { Mv_bnd, Gbnd }, 0 },
     { "nopQ",          { Ev }, 0 },
   },
   {
     /* MOD_0F1B_PREFIX_1 */
-    { "bndmk",         { Gbnd, Ev_bnd }, 0 },
+    { "bndmk",         { Gbnd, Mv_bnd }, 0 },
     { "nopQ",          { Ev }, 0 },
   },
   {
@@ -11859,7 +11865,7 @@ static const struct dis386 mod_table[][2] = {
   },
   {
     /* MOD_0F38F9_PREFIX_0 */
-    { "movdiri",       { Em, Gm }, PREFIX_OPCODE },
+    { "movdiri",       { Em, Gv }, PREFIX_OPCODE },
   },
   {
     /* MOD_62_32BIT */
@@ -14802,6 +14808,7 @@ intel_operand_size (int bytemode, int sizeflag)
     case q_swap_mode:
       oappend ("QWORD PTR ");
       break;
+    case dqa_mode:
     case m_mode:
       if (address_mode == mode_64bit)
        oappend ("QWORD PTR ");
@@ -15083,6 +15090,7 @@ intel_operand_size (int bytemode, int sizeflag)
        oappend ("WORD PTR ");
       break;
     case v_bnd_mode:
+    case v_bndmk_mode:
     default:
       break;
     }
@@ -15159,6 +15167,7 @@ OP_E_register (int bytemode, int sizeflag)
     case dqb_mode:
     case dqd_mode:
     case dqw_mode:
+    case dqa_mode:
       USED_REX (REX_W);
       if (rex & REX_W)
        names = names64;
@@ -15177,10 +15186,8 @@ OP_E_register (int bytemode, int sizeflag)
       names = (address_mode == mode_64bit
               ? names64 : names32);
       if (!(prefixes & PREFIX_ADDR))
-       {
-         if (address_mode == mode_16bit)
-           names = names16;
-       }
+       names = (address_mode == mode_16bit
+                    ? names16 : names);
       else
        {
          /* Remove "addr16/addr32".  */
@@ -15295,14 +15302,17 @@ OP_E_memory (int bytemode, int sizeflag)
        case d_scalar_swap_mode:
          shift = 2;
          break;
-    case w_scalar_mode:
+       case w_scalar_mode:
        case xmm_mw_mode:
          shift = 1;
          break;
-    case b_scalar_mode:
+       case b_scalar_mode:
        case xmm_mb_mode:
          shift = 0;
          break;
+       case dqa_mode:
+         shift = address_mode == mode_64bit ? 3 : 2;
+         break;
        default:
          abort ();
        }
@@ -15339,11 +15349,13 @@ OP_E_memory (int bytemode, int sizeflag)
       int havebase;
       int haveindex;
       int needindex;
+      int needaddr32;
       int base, rbase;
       int vindex = 0;
       int scale = 0;
       int addr32flag = !((sizeflag & AFLAG)
                         || bytemode == v_bnd_mode
+                        || bytemode == v_bndmk_mode
                         || bytemode == bnd_mode
                         || bytemode == bnd_swap_mode);
       const char **indexes64 = names64;
@@ -15420,6 +15432,11 @@ OP_E_memory (int bytemode, int sizeflag)
              if (address_mode == mode_64bit && !havesib)
                riprel = 1;
              disp = get32s ();
+             if (riprel && bytemode == v_bndmk_mode)
+               {
+                 oappend ("(bad)");
+                 return;
+               }
            }
          break;
        case 1:
@@ -15435,12 +15452,27 @@ OP_E_memory (int bytemode, int sizeflag)
          break;
        }
 
-      /* In 32bit mode, we need index register to tell [offset] from
-        [eiz*1 + offset].  */
-      needindex = (havesib
-                  && !havebase
-                  && !haveindex
-                  && address_mode == mode_32bit);
+      needindex = 0;
+      needaddr32 = 0;
+      if (havesib
+         && !havebase
+         && !haveindex
+         && address_mode != mode_16bit)
+       {
+         if (address_mode == mode_64bit)
+           {
+             /* Display eiz instead of addr32.  */
+             needindex = addr32flag;
+             needaddr32 = 1;
+           }
+         else
+           {
+             /* In 32-bit mode, we need index register to tell [offset]
+                from [eiz*1 + offset].  */
+             needindex = 1;
+           }
+       }
+
       havedisp = (havebase
                  || needindex
                  || (havesib && (haveindex || scale != 0)));
@@ -15460,8 +15492,9 @@ OP_E_memory (int bytemode, int sizeflag)
              }
          }
 
-      if ((havebase || haveindex || riprel)
+      if ((havebase || haveindex || needaddr32 || riprel)
          && (bytemode != v_bnd_mode)
+         && (bytemode != v_bndmk_mode)
          && (bytemode != bnd_mode)
          && (bytemode != bnd_swap_mode))
        used_prefixes |= PREFIX_ADDR;
This page took 0.028007 seconds and 4 git commands to generate.