Handle EITR records in VMS Alpha binaries with overlarge command length parameters.
[deliverable/binutils-gdb.git] / opcodes / i386-dis.c
index 5f49f919935ad61563c805337b6c79f49f37d18a..b35dbc046ee0dda4db472230a07a186ecf786e70 100644 (file)
@@ -1,5 +1,5 @@
 /* Print i386 instructions for GDB, the GNU debugger.
-   Copyright (C) 1988-2016 Free Software Foundation, Inc.
+   Copyright (C) 1988-2017 Free Software Foundation, Inc.
 
    This file is part of the GNU opcodes library.
 
@@ -33,7 +33,7 @@
    the Intel manual for details.  */
 
 #include "sysdep.h"
-#include "dis-asm.h"
+#include "disassemble.h"
 #include "opintl.h"
 #include "opcode/i386.h"
 #include "libiberty.h"
@@ -110,6 +110,7 @@ static void CMP_Fixup (int, int);
 static void BadOp (void);
 static void REP_Fixup (int, int);
 static void BND_Fixup (int, int);
+static void NOTRACK_Fixup (int, int);
 static void HLE_Fixup1 (int, int);
 static void HLE_Fixup2 (int, int);
 static void HLE_Fixup3 (int, int);
@@ -117,6 +118,7 @@ static void CMPXCHG8B_Fixup (int, int);
 static void XMM_Fixup (int, int);
 static void CRC32_Fixup (int, int);
 static void FXSAVE_Fixup (int, int);
+static void PCMPESTR_Fixup (int, int);
 static void OP_LWPCB_E (int, int);
 static void OP_LWP_E (int, int);
 static void OP_Vex_2src_1 (int, int);
@@ -472,6 +474,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define Evh3 { HLE_Fixup3, v_mode }
 
 #define BND { BND_Fixup, 0 }
+#define NOTRACK { NOTRACK_Fixup, 0 }
 
 #define cond_jump_flag { NULL, cond_jump_mode }
 #define loop_jcxz_flag { NULL, loop_jcxz_mode }
@@ -722,6 +725,7 @@ enum
   REG_0F01,
   REG_0F0D,
   REG_0F18,
+  REG_0F1E_MOD_3,
   REG_0F71,
   REG_0F72,
   REG_0F73,
@@ -775,6 +779,7 @@ enum
   MOD_0F1A_PREFIX_0,
   MOD_0F1B_PREFIX_0,
   MOD_0F1B_PREFIX_1,
+  MOD_0F1E_PREFIX_1,
   MOD_0F24,
   MOD_0F26,
   MOD_0F2B_PREFIX_0,
@@ -813,6 +818,8 @@ enum
   MOD_0FE7_PREFIX_2,
   MOD_0FF0_PREFIX_3,
   MOD_0F382A_PREFIX_2,
+  MOD_0F38F5_PREFIX_2,
+  MOD_0F38F6_PREFIX_0,
   MOD_62_32BIT,
   MOD_C4_32BIT,
   MOD_C5_32BIT,
@@ -932,6 +939,7 @@ enum
   RM_0F01_REG_3,
   RM_0F01_REG_5,
   RM_0F01_REG_7,
+  RM_0F1E_MOD_3_REG_7,
   RM_0FAE_REG_5,
   RM_0FAE_REG_6,
   RM_0FAE_REG_7
@@ -940,12 +948,16 @@ enum
 enum
 {
   PREFIX_90 = 0,
+  PREFIX_MOD_0_0F01_REG_5,
+  PREFIX_MOD_3_0F01_REG_5_RM_1,
+  PREFIX_MOD_3_0F01_REG_5_RM_2,
   PREFIX_0F10,
   PREFIX_0F11,
   PREFIX_0F12,
   PREFIX_0F16,
   PREFIX_0F1A,
   PREFIX_0F1B,
+  PREFIX_0F1E,
   PREFIX_0F2A,
   PREFIX_0F2B,
   PREFIX_0F2C,
@@ -984,6 +996,7 @@ enum
   PREFIX_0FAE_REG_3,
   PREFIX_MOD_0_0FAE_REG_4,
   PREFIX_MOD_3_0FAE_REG_4,
+  PREFIX_MOD_0_0FAE_REG_5,
   PREFIX_0FAE_REG_6,
   PREFIX_0FAE_REG_7,
   PREFIX_0FB8,
@@ -1047,6 +1060,7 @@ enum
   PREFIX_0F38DF,
   PREFIX_0F38F0,
   PREFIX_0F38F1,
+  PREFIX_0F38F5,
   PREFIX_0F38F6,
   PREFIX_0F3A08,
   PREFIX_0F3A09,
@@ -1548,6 +1562,7 @@ enum
   PREFIX_EVEX_0F384F,
   PREFIX_EVEX_0F3852,
   PREFIX_EVEX_0F3853,
+  PREFIX_EVEX_0F3855,
   PREFIX_EVEX_0F3858,
   PREFIX_EVEX_0F3859,
   PREFIX_EVEX_0F385A,
@@ -2190,8 +2205,6 @@ enum
   VEX_W_0F3A4A_P_2,
   VEX_W_0F3A4B_P_2,
   VEX_W_0F3A4C_P_2,
-  VEX_W_0F3A60_P_2,
-  VEX_W_0F3A61_P_2,
   VEX_W_0F3A62_P_2,
   VEX_W_0F3A63_P_2,
   VEX_W_0F3ADF_P_2,
@@ -2377,6 +2390,7 @@ enum
   EVEX_W_0F3839_P_1,
   EVEX_W_0F383A_P_1,
   EVEX_W_0F3840_P_2,
+  EVEX_W_0F3855_P_2,
   EVEX_W_0F3858_P_2,
   EVEX_W_0F3859_P_2,
   EVEX_W_0F385A_P_2,
@@ -2838,7 +2852,7 @@ static const struct dis386 dis386_twobyte[] = {
   { PREFIX_TABLE (PREFIX_0F1B) },
   { "nopQ",            { Ev }, 0 },
   { "nopQ",            { Ev }, 0 },
-  { "nopQ",            { Ev }, 0 },
+  { PREFIX_TABLE (PREFIX_0F1E) },
   { "nopQ",            { Ev }, 0 },
   /* 20 */
   { "movZ",            { Rm, Cm }, 0 },
@@ -3155,6 +3169,7 @@ static int last_data_prefix;
 static int last_addr_prefix;
 static int last_rex_prefix;
 static int last_seg_prefix;
+static int last_active_prefix;
 static int fwait_prefix;
 /* The active segment register prefix.  */
 static int active_seg_prefix;
@@ -3509,7 +3524,7 @@ static const struct dis386 reg_table[][8] = {
   /* REG_F6 */
   {
     { "testA", { Eb, Ib }, 0 },
-    { Bad_Opcode },
+    { "testA", { Eb, Ib }, 0 },
     { "notA",  { Ebh1 }, 0 },
     { "negA",  { Ebh1 }, 0 },
     { "mulA",  { Eb }, 0 },    /* Don't print the implicit %al register,  */
@@ -3520,7 +3535,7 @@ static const struct dis386 reg_table[][8] = {
   /* REG_F7 */
   {
     { "testQ", { Ev, Iv }, 0 },
-    { Bad_Opcode },
+    { "testQ", { Ev, Iv }, 0 },
     { "notQ",  { Evh1 }, 0 },
     { "negQ",  { Evh1 }, 0 },
     { "mulQ",  { Ev }, 0 },    /* Don't print the implicit register.  */
@@ -3537,9 +3552,9 @@ static const struct dis386 reg_table[][8] = {
   {
     { "incQ",  { Evh1 }, 0 },
     { "decQ",  { Evh1 }, 0 },
-    { "call{&|}", { indirEv, BND }, 0 },
+    { "call{&|}", { indirEv, NOTRACK, BND }, 0 },
     { MOD_TABLE (MOD_FF_REG_3) },
-    { "jmp{&|}", { indirEv, BND }, 0 },
+    { "jmp{&|}", { indirEv, NOTRACK, BND }, 0 },
     { MOD_TABLE (MOD_FF_REG_5) },
     { "pushU", { stackEv }, 0 },
     { Bad_Opcode },
@@ -3588,6 +3603,17 @@ static const struct dis386 reg_table[][8] = {
     { MOD_TABLE (MOD_0F18_REG_6) },
     { MOD_TABLE (MOD_0F18_REG_7) },
   },
+  /* REG_0F1E_MOD_3 */
+  {
+    { "nopQ",          { Ev }, 0 },
+    { "rdsspK",                { Rdq }, PREFIX_OPCODE },
+    { "nopQ",          { Ev }, 0 },
+    { "nopQ",          { Ev }, 0 },
+    { "nopQ",          { Ev }, 0 },
+    { "nopQ",          { Ev }, 0 },
+    { "nopQ",          { Ev }, 0 },
+    { RM_TABLE (RM_0F1E_MOD_3_REG_7) },
+  },
   /* REG_0F71 */
   {
     { Bad_Opcode },
@@ -3757,6 +3783,24 @@ static const struct dis386 prefix_table[][4] = {
     { NULL, { { NULL, 0 } }, PREFIX_IGNORED }
   },
 
+  /* PREFIX_MOD_0_0F01_REG_5 */
+  {
+    { Bad_Opcode },
+    { "rstorssp",      { Mq }, PREFIX_OPCODE },
+  },
+
+  /* PREFIX_MOD_3_0F01_REG_5_RM_1 */
+  {
+    { Bad_Opcode },
+    { "incsspK",       { Skip_MODRM }, PREFIX_OPCODE },
+  },
+
+  /* PREFIX_MOD_3_0F01_REG_5_RM_2 */
+  {
+    { Bad_Opcode },
+    { "savessp",       { Skip_MODRM }, PREFIX_OPCODE },
+  },
+
   /* PREFIX_0F10 */
   {
     { "movups",        { XM, EXx }, PREFIX_OPCODE },
@@ -3804,6 +3848,14 @@ static const struct dis386 prefix_table[][4] = {
     { "bndcn",  { Gbnd, Ev_bnd }, 0 },
   },
 
+  /* PREFIX_0F1E */
+  {
+    { "nopQ",  { Ev }, PREFIX_OPCODE },
+    { MOD_TABLE (MOD_0F1E_PREFIX_1) },
+    { "nopQ",  { Ev }, PREFIX_OPCODE },
+    { "nopQ",  { Ev }, PREFIX_OPCODE },
+  },
+
   /* PREFIX_0F2A */
   {
     { "cvtpi2ps", { XM, EMCq }, PREFIX_OPCODE },
@@ -4079,11 +4131,17 @@ static const struct dis386 prefix_table[][4] = {
     { "ptwrite%LQ", { Edq }, 0 },
   },
 
+  /* PREFIX_MOD_0_0FAE_REG_5 */
+  {
+    { "xrstor",                { FXSAVE }, PREFIX_OPCODE },
+    { "setssbsy",      { Mq }, PREFIX_OPCODE },
+  },
+
   /* PREFIX_0FAE_REG_6 */
   {
-    { "xsaveopt",      { FXSAVE }, 0 },
-    { Bad_Opcode },
-    { "clwb",  { Mb }, 0 },
+    { "xsaveopt",      { FXSAVE }, PREFIX_OPCODE },
+    { "clrssbsy",      { Mq }, PREFIX_OPCODE },
+    { "clwb",  { Mb }, PREFIX_OPCODE },
   },
 
   /* PREFIX_0FAE_REG_7 */
@@ -4512,9 +4570,16 @@ static const struct dis386 prefix_table[][4] = {
     { "crc32", { Gdq, { CRC32_Fixup, v_mode } }, PREFIX_OPCODE },
   },
 
-  /* PREFIX_0F38F6 */
+  /* PREFIX_0F38F5 */
   {
     { Bad_Opcode },
+    { Bad_Opcode },
+    { MOD_TABLE (MOD_0F38F5_PREFIX_2) },
+  },
+
+  /* PREFIX_0F38F6 */
+  {
+    { MOD_TABLE (MOD_0F38F6_PREFIX_0) },
     { "adoxS", { Gdq, Edq}, PREFIX_OPCODE },
     { "adcxS", { Gdq, Edq}, PREFIX_OPCODE },
     { Bad_Opcode },
@@ -4650,14 +4715,14 @@ static const struct dis386 prefix_table[][4] = {
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { "pcmpestrm", { XM, EXx, Ib }, PREFIX_OPCODE },
+    { "pcmpestrm", { XM, { PCMPESTR_Fixup, x_mode }, Ib }, PREFIX_OPCODE },
   },
 
   /* PREFIX_0F3A61 */
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { "pcmpestri", { XM, EXx, Ib }, PREFIX_OPCODE },
+    { "pcmpestri", { XM, { PCMPESTR_Fixup, x_mode }, Ib }, PREFIX_OPCODE },
   },
 
   /* PREFIX_0F3A62 */
@@ -7245,7 +7310,7 @@ static const struct dis386 three_byte_table[][256] = {
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
-    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_0F38F5) },
     { PREFIX_TABLE (PREFIX_0F38F6) },
     { Bad_Opcode },
     /* f8 */
@@ -9996,12 +10061,12 @@ static const struct dis386 vex_len_table[][2] = {
 
   /* VEX_LEN_0F3A60_P_2 */
   {
-    { VEX_W_TABLE (VEX_W_0F3A60_P_2) },
+    { "vpcmpestrm",    { XM, { PCMPESTR_Fixup, x_mode }, Ib }, 0 },
   },
 
   /* VEX_LEN_0F3A61_P_2 */
   {
-    { VEX_W_TABLE (VEX_W_0F3A61_P_2) },
+    { "vpcmpestri",    { XM, { PCMPESTR_Fixup, x_mode }, Ib }, 0 },
   },
 
   /* VEX_LEN_0F3A62_P_2 */
@@ -11343,14 +11408,6 @@ static const struct dis386 vex_w_table[][2] = {
     /* VEX_W_0F3A4C_P_2 */
     { "vpblendvb",     { XM, Vex, EXx, XMVexI4 }, 0 },
   },
-  {
-    /* VEX_W_0F3A60_P_2 */
-    { "vpcmpestrm",    { XM, EXx, Ib }, 0 },
-  },
-  {
-    /* VEX_W_0F3A61_P_2 */
-    { "vpcmpestri",    { XM, EXx, Ib }, 0 },
-  },
   {
     /* VEX_W_0F3A62_P_2 */
     { "vpcmpistrm",    { XM, EXx, Ib }, 0 },
@@ -11413,7 +11470,7 @@ static const struct dis386 mod_table[][2] = {
   },
   {
     /* MOD_0F01_REG_5 */
-    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_MOD_0_0F01_REG_5) },
     { RM_TABLE (RM_0F01_REG_5) },
   },
   {
@@ -11486,6 +11543,11 @@ static const struct dis386 mod_table[][2] = {
     { "bndmk",         { Gbnd, Ev_bnd }, 0 },
     { "nopQ",          { Ev }, 0 },
   },
+  {
+    /* MOD_0F1E_PREFIX_1 */
+    { "nopQ",          { Ev }, 0 },
+    { REG_TABLE (REG_0F1E_MOD_3) },
+  },
   {
     /* MOD_0F24 */
     { Bad_Opcode },
@@ -11594,7 +11656,7 @@ static const struct dis386 mod_table[][2] = {
   },
   {
     /* MOD_0FAE_REG_5 */
-    { "xrstor",                { FXSAVE }, 0 },
+    { PREFIX_TABLE (PREFIX_MOD_0_0FAE_REG_5) },
     { RM_TABLE (RM_0FAE_REG_5) },
   },
   {
@@ -11662,6 +11724,14 @@ static const struct dis386 mod_table[][2] = {
     /* MOD_0F382A_PREFIX_2 */
     { "movntdqa",      { XM, Mx }, 0 },
   },
+  {
+    /* MOD_0F38F5_PREFIX_2 */
+    { "wrussK",                { M, Gdq }, PREFIX_OPCODE },
+  },
+  {
+    /* MOD_0F38F6_PREFIX_0 */
+    { "wrssK",         { M, Gdq }, PREFIX_OPCODE },
+  },
   {
     /* MOD_62_32BIT */
     { "bound{S|}",     { Gv, Ma }, 0 },
@@ -12164,8 +12234,8 @@ static const struct dis386 rm_table[][8] = {
   {
     /* RM_0F01_REG_5 */
     { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_MOD_3_0F01_REG_5_RM_1) },
+    { PREFIX_TABLE (PREFIX_MOD_3_0F01_REG_5_RM_2) },
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
@@ -12180,6 +12250,17 @@ static const struct dis386 rm_table[][8] = {
     { "mwaitx",                { { OP_Mwaitx,  0 } }, 0  },
     { "clzero",                { Skip_MODRM }, 0  },
   },
+  {
+    /* RM_0F1E_MOD_3_REG_7 */
+    { "nopQ",          { Ev }, 0 },
+    { "nopQ",          { Ev }, 0 },
+    { "endbr64",       { Skip_MODRM },  PREFIX_OPCODE },
+    { "endbr32",       { Skip_MODRM },  PREFIX_OPCODE },
+    { "nopQ",          { Ev }, 0 },
+    { "nopQ",          { Ev }, 0 },
+    { "nopQ",          { Ev }, 0 },
+    { "nopQ",          { Ev }, 0 },
+  },
   {
     /* RM_0FAE_REG_5 */
     { "lfence",                { Skip_MODRM }, 0 },
@@ -12203,6 +12284,7 @@ static const struct dis386 rm_table[][8] = {
 #define XACQUIRE_PREFIX        (0xf2 | 0x200)
 #define XRELEASE_PREFIX        (0xf3 | 0x400)
 #define BND_PREFIX     (0xf2 | 0x400)
+#define NOTRACK_PREFIX (0x3e | 0x100)
 
 static int
 ckprefix (void)
@@ -12220,6 +12302,7 @@ ckprefix (void)
   last_addr_prefix = -1;
   last_rex_prefix = -1;
   last_seg_prefix = -1;
+  last_active_prefix = -1;
   fwait_prefix = -1;
   active_seg_prefix = 0;
   for (i = 0; i < (int) ARRAY_SIZE (all_prefixes); i++)
@@ -12332,7 +12415,10 @@ ckprefix (void)
          return 1;
        }
       if (*codep != FWAIT_OPCODE)
-       all_prefixes[i++] = *codep;
+       {
+         last_active_prefix = i;
+         all_prefixes[i++] = *codep;
+       }
       rex = newrex;
       codep++;
       length++;
@@ -12421,6 +12507,8 @@ prefix_name (int pref, int sizeflag)
       return "xrelease";
     case BND_PREFIX:
       return "bnd";
+    case NOTRACK_PREFIX:
+      return "notrack";
     default:
       return NULL;
     }
@@ -12670,11 +12758,15 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
        rex |= REX_W;
 
       vex.register_specifier = (~(*codep >> 3)) & 0xf;
-      if (address_mode != mode_64bit
-         && vex.register_specifier > 0x7)
+      if (address_mode != mode_64bit)
        {
-         dp = &bad_opcode;
-         return dp;
+         /* In 16/32-bit mode REX_B is silently ignored.  */
+         rex &= ~REX_B;
+         if (vex.register_specifier > 0x7)
+           {
+             dp = &bad_opcode;
+             return dp;
+           }
        }
 
       vex.length = (*codep & 0x4) ? 256 : 128;
@@ -12765,8 +12857,8 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
       vindex = *codep++;
       dp = &vex_table[vex_table_index][vindex];
       end_codep = codep;
-      /* There is no MODRM byte for VEX [82|77].  */
-      if (vindex != 0x77 && vindex != 0x82)
+      /* There is no MODRM byte for VEX0F 77.  */
+      if (vex_table_index != VEX_0F || vindex != 0x77)
        {
          FETCH_DATA (info, codep + 1);
          modrm.mod = (*codep >> 6) & 3;
@@ -12808,8 +12900,8 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
       vindex = *codep++;
       dp = &vex_table[dp->op[1].bytemode][vindex];
       end_codep = codep;
-      /* There is no MODRM byte for VEX [82|77].  */
-      if (vindex != 0x77 && vindex != 0x82)
+      /* There is no MODRM byte for VEX 77.  */
+      if (vindex != 0x77)
        {
          FETCH_DATA (info, codep + 1);
          modrm.mod = (*codep >> 6) & 3;
@@ -16707,6 +16799,34 @@ BND_Fixup (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
     all_prefixes[last_repnz_prefix] = BND_PREFIX;
 }
 
+/* For NOTRACK-prefixed instructions, 0x3E prefix should be displayed as
+   "notrack".  */
+
+static void
+NOTRACK_Fixup (int bytemode ATTRIBUTE_UNUSED,
+              int sizeflag ATTRIBUTE_UNUSED)
+{
+  if (modrm.mod == 3
+      && active_seg_prefix == PREFIX_DS
+      && (address_mode != mode_64bit || last_data_prefix < 0))
+    {
+      /* NOTRACK prefix is only valid on register indirect branch
+        instructions and it must be the last prefix before REX
+        prefix and opcode.  NB: DATA prefix is unsupported for
+        Intel64.  */
+      if (last_active_prefix >= 0)
+       {
+         int notrack_prefix = last_active_prefix;
+         if (last_rex_prefix == last_active_prefix)
+           notrack_prefix--;
+         if (all_prefixes[notrack_prefix] != NOTRACK_PREFIX_OPCODE)
+           return;
+       }
+      active_seg_prefix = 0;
+      all_prefixes[last_seg_prefix] = NOTRACK_PREFIX;
+    }
+}
+
 /* Similar to OP_E.  But the 0xf2/0xf3 prefixes should be displayed as
    "xacquire"/"xrelease" for memory operand if there is a LOCK prefix.
  */
@@ -16891,6 +17011,27 @@ FXSAVE_Fixup (int bytemode, int sizeflag)
   OP_M (bytemode, sizeflag);
 }
 
+static void
+PCMPESTR_Fixup (int bytemode, int sizeflag)
+{
+  /* Add proper suffix to "{,v}pcmpestr{i,m}".  */
+  if (!intel_syntax)
+    {
+      char *p = mnemonicendp;
+
+      USED_REX (REX_W);
+      if (rex & REX_W)
+       *p++ = 'q';
+      else if (sizeflag & SUFFIX_ALWAYS)
+       *p++ = 'l';
+
+      *p = '\0';
+      mnemonicendp = p;
+    }
+
+  OP_EX (bytemode, sizeflag);
+}
+
 /* Display the destination register operand for instructions with
    VEX. */
 
@@ -16971,7 +17112,8 @@ OP_VEX (int bytemode, int sizeflag ATTRIBUTE_UNUSED)
          names = names_mask;
          break;
        default:
-         abort ();
+         /* See PR binutils/20893 for a reproducer.  */
+         oappend ("(bad)");
          return;
        }
       break;
This page took 0.033748 seconds and 4 git commands to generate.