Revert "x86: work around compiler diagnosing dangling pointer"
[binutils-gdb.git] / opcodes / i386-dis.c
index afc3743e4e8fa5c17d8751385c22d2379f106218..01e5ba81723d9e08f1839a5dfb47c631953e2417 100644 (file)
@@ -1,5 +1,5 @@
 /* Print i386 instructions for GDB, the GNU debugger.
-   Copyright (C) 1988-2022 Free Software Foundation, Inc.
+   Copyright (C) 1988-2023 Free Software Foundation, Inc.
 
    This file is part of the GNU opcodes library.
 
 #include "libiberty.h"
 #include "safe-ctype.h"
 
-#include <setjmp.h>
 typedef struct instr_info instr_info;
 
-static int print_insn (bfd_vma, instr_info *);
-static void dofloat (instr_info *, int);
-static void OP_ST (instr_info *, int, int);
-static void OP_STi (instr_info *, int, int);
+static bool dofloat (instr_info *, int);
 static int putop (instr_info *, const char *, int);
+static void oappend_with_style (instr_info *, const char *,
+                               enum disassembler_style);
 static void oappend (instr_info *, const char *);
 static void append_seg (instr_info *);
-static void OP_indirE (instr_info *, int, int);
-static void print_operand_value (instr_info *, char *, int, bfd_vma);
-static void OP_E_memory (instr_info *, int, int);
-static void print_displacement (instr_info *, char *, bfd_vma);
-static void OP_E (instr_info *, int, int);
-static void OP_G (instr_info *, int, int);
-static bfd_vma get64 (instr_info *);
-static bfd_signed_vma get32 (instr_info *);
-static bfd_signed_vma get32s (instr_info *);
-static int get16 (instr_info *);
-static void set_op (instr_info *, bfd_vma, int);
-static void OP_Skip_MODRM (instr_info *, int, int);
-static void OP_REG (instr_info *, int, int);
-static void OP_IMREG (instr_info *, int, int);
-static void OP_I (instr_info *, int, int);
-static void OP_I64 (instr_info *, int, int);
-static void OP_sI (instr_info *, int, int);
-static void OP_J (instr_info *, int, int);
-static void OP_SEG (instr_info *, int, int);
-static void OP_DIR (instr_info *, int, int);
-static void OP_OFF (instr_info *, int, int);
-static void OP_OFF64 (instr_info *, int, int);
-static void ptr_reg (instr_info *, int, int);
-static void OP_ESreg (instr_info *, int, int);
-static void OP_DSreg (instr_info *, int, int);
-static void OP_C (instr_info *, int, int);
-static void OP_D (instr_info *, int, int);
-static void OP_T (instr_info *, int, int);
-static void OP_MMX (instr_info *, int, int);
-static void OP_XMM (instr_info *, int, int);
-static void OP_EM (instr_info *, int, int);
-static void OP_EX (instr_info *, int, int);
-static void OP_EMC (instr_info *, int,int);
-static void OP_MXC (instr_info *, int,int);
-static void OP_MS (instr_info *, int, int);
-static void OP_XS (instr_info *, int, int);
-static void OP_M (instr_info *, int, int);
-static void OP_VEX (instr_info *, int, int);
-static void OP_VexR (instr_info *, int, int);
-static void OP_VexW (instr_info *, int, int);
-static void OP_Rounding (instr_info *, int, int);
-static void OP_REG_VexI4 (instr_info *, int, int);
-static void OP_VexI4 (instr_info *, int, int);
-static void PCLMUL_Fixup (instr_info *, int, int);
-static void VPCMP_Fixup (instr_info *, int, int);
-static void VPCOM_Fixup (instr_info *, int, int);
-static void OP_0f07 (instr_info *, int, int);
-static void OP_Monitor (instr_info *, int, int);
-static void OP_Mwait (instr_info *, int, int);
-static void NOP_Fixup1 (instr_info *, int, int);
-static void NOP_Fixup2 (instr_info *, int, int);
-static void OP_3DNowSuffix (instr_info *, int, int);
-static void CMP_Fixup (instr_info *, int, int);
-static void BadOp (instr_info *);
-static void REP_Fixup (instr_info *, int, int);
-static void SEP_Fixup (instr_info *, int, int);
-static void BND_Fixup (instr_info *, int, int);
-static void NOTRACK_Fixup (instr_info *, int, int);
-static void HLE_Fixup1 (instr_info *, int, int);
-static void HLE_Fixup2 (instr_info *, int, int);
-static void HLE_Fixup3 (instr_info *, int, int);
-static void CMPXCHG8B_Fixup (instr_info *, int, int);
-static void XMM_Fixup (instr_info *, int, int);
-static void FXSAVE_Fixup (instr_info *, int, int);
-
-static void MOVSXD_Fixup (instr_info *, int, int);
-static void DistinctDest_Fixup (instr_info *, int, int);
+static bool get32s (instr_info *, bfd_signed_vma *);
+static bool get16 (instr_info *, int *);
+static void set_op (instr_info *, bfd_vma, bool);
+
+static bool OP_E (instr_info *, int, int);
+static bool OP_E_memory (instr_info *, int, int);
+static bool OP_indirE (instr_info *, int, int);
+static bool OP_G (instr_info *, int, int);
+static bool OP_ST (instr_info *, int, int);
+static bool OP_STi (instr_info *, int, int);
+static bool OP_Skip_MODRM (instr_info *, int, int);
+static bool OP_REG (instr_info *, int, int);
+static bool OP_IMREG (instr_info *, int, int);
+static bool OP_I (instr_info *, int, int);
+static bool OP_I64 (instr_info *, int, int);
+static bool OP_sI (instr_info *, int, int);
+static bool OP_J (instr_info *, int, int);
+static bool OP_SEG (instr_info *, int, int);
+static bool OP_DIR (instr_info *, int, int);
+static bool OP_OFF (instr_info *, int, int);
+static bool OP_OFF64 (instr_info *, int, int);
+static bool OP_ESreg (instr_info *, int, int);
+static bool OP_DSreg (instr_info *, int, int);
+static bool OP_C (instr_info *, int, int);
+static bool OP_D (instr_info *, int, int);
+static bool OP_T (instr_info *, int, int);
+static bool OP_MMX (instr_info *, int, int);
+static bool OP_XMM (instr_info *, int, int);
+static bool OP_EM (instr_info *, int, int);
+static bool OP_EX (instr_info *, int, int);
+static bool OP_EMC (instr_info *, int,int);
+static bool OP_MXC (instr_info *, int,int);
+static bool OP_MS (instr_info *, int, int);
+static bool OP_XS (instr_info *, int, int);
+static bool OP_M (instr_info *, int, int);
+static bool OP_VEX (instr_info *, int, int);
+static bool OP_VexR (instr_info *, int, int);
+static bool OP_VexW (instr_info *, int, int);
+static bool OP_Rounding (instr_info *, int, int);
+static bool OP_REG_VexI4 (instr_info *, int, int);
+static bool OP_VexI4 (instr_info *, int, int);
+static bool OP_0f07 (instr_info *, int, int);
+static bool OP_Monitor (instr_info *, int, int);
+static bool OP_Mwait (instr_info *, int, int);
+
+static bool BadOp (instr_info *);
+
+static bool PCLMUL_Fixup (instr_info *, int, int);
+static bool VPCMP_Fixup (instr_info *, int, int);
+static bool VPCOM_Fixup (instr_info *, int, int);
+static bool NOP_Fixup (instr_info *, int, int);
+static bool OP_3DNowSuffix (instr_info *, int, int);
+static bool CMP_Fixup (instr_info *, int, int);
+static bool REP_Fixup (instr_info *, int, int);
+static bool SEP_Fixup (instr_info *, int, int);
+static bool BND_Fixup (instr_info *, int, int);
+static bool NOTRACK_Fixup (instr_info *, int, int);
+static bool HLE_Fixup1 (instr_info *, int, int);
+static bool HLE_Fixup2 (instr_info *, int, int);
+static bool HLE_Fixup3 (instr_info *, int, int);
+static bool CMPXCHG8B_Fixup (instr_info *, int, int);
+static bool XMM_Fixup (instr_info *, int, int);
+static bool FXSAVE_Fixup (instr_info *, int, int);
+static bool MOVSXD_Fixup (instr_info *, int, int);
+static bool DistinctDest_Fixup (instr_info *, int, int);
+static bool PREFETCHI_Fixup (instr_info *, int, int);
+
+static void ATTRIBUTE_PRINTF_3 i386_dis_printf (const instr_info *,
+                                               enum disassembler_style,
+                                               const char *, ...);
+static const char *prefix_name (const instr_info *, int, int);
+
+/* This character is used to encode style information within the output
+   buffers.  See oappend_insert_style for more details.  */
+#define STYLE_MARKER_CHAR '\002'
+
+/* The maximum operand buffer size.  */
+#define MAX_OPERAND_BUFFER_SIZE 128
 
 struct dis_private {
   /* Points to first byte not fetched.  */
@@ -123,7 +132,6 @@ struct dis_private {
   bfd_byte the_buffer[MAX_MNEM_SIZE];
   bfd_vma insn_start;
   int orig_sizeflag;
-  OPCODES_SIGJMP_BUF bailout;
 };
 
 enum address_mode
@@ -147,9 +155,13 @@ struct instr_info
   int prefixes;
 
   /* REX prefix the current instruction.  See below.  */
-  int rex;
+  unsigned char rex;
   /* Bits of REX we've already used.  */
-  int rex_used;
+  unsigned char rex_used;
+
+  bool need_modrm;
+  bool need_vex;
+  bool has_sib;
 
   /* Flags for ins->prefixes which we somehow handled when printing the
      current instruction.  */
@@ -159,29 +171,28 @@ struct instr_info
      current instruction.  */
   int evex_used;
 
-  char obuf[100];
+  char obuf[MAX_OPERAND_BUFFER_SIZE];
   char *obufp;
   char *mnemonicendp;
-  char scratchbuf[100];
   unsigned char *start_codep;
   unsigned char *insn_codep;
   unsigned char *codep;
   unsigned char *end_codep;
-  int last_lock_prefix;
-  int last_repz_prefix;
-  int last_repnz_prefix;
-  int last_data_prefix;
-  int last_addr_prefix;
-  int last_rex_prefix;
-  int last_seg_prefix;
-  int fwait_prefix;
+  signed char last_lock_prefix;
+  signed char last_repz_prefix;
+  signed char last_repnz_prefix;
+  signed char last_data_prefix;
+  signed char last_addr_prefix;
+  signed char last_rex_prefix;
+  signed char last_seg_prefix;
+  signed char fwait_prefix;
   /* The active segment register prefix.  */
-  int active_seg_prefix;
+  unsigned char active_seg_prefix;
 
 #define MAX_CODE_LENGTH 15
   /* We can up to 14 ins->prefixes since the maximum instruction length is
      15bytes.  */
-  int all_prefixes[MAX_CODE_LENGTH - 1];
+  unsigned char all_prefixes[MAX_CODE_LENGTH - 1];
   disassemble_info *info;
 
   struct
@@ -191,7 +202,6 @@ struct instr_info
     int rm;
   }
   modrm;
-  unsigned char need_modrm;
 
   struct
   {
@@ -206,44 +216,28 @@ struct instr_info
     int register_specifier;
     int length;
     int prefix;
-    int w;
-    int evex;
-    int r;
-    int v;
     int mask_register_specifier;
-    int zeroing;
     int ll;
-    int b;
-    int no_broadcast;
+    bool w;
+    bool evex;
+    bool r;
+    bool v;
+    bool zeroing;
+    bool b;
+    bool no_broadcast;
   }
   vex;
-  unsigned char need_vex;
-
-  const char **names64;
-  const char **names32;
-  const char **names16;
-  const char **names8;
-  const char **names8rex;
-  const char **names_seg;
-  const char *index64;
-  const char *index32;
-  const char **index16;
-  const char **names_bnd;
-  const char **names_mm;
-  const char **names_xmm;
-  const char **names_ymm;
-  const char **names_zmm;
-  const char **names_tmm;
-  const char **names_mask;
 
   /* Remember if the current op is a jump instruction.  */
   bool op_is_jump;
 
-  char op_out[MAX_OPERANDS][100];
-  int op_ad, op_index[MAX_OPERANDS];
-  int two_source_ops;
+  bool two_source_ops;
+
+  unsigned char op_ad;
+  signed char op_index[MAX_OPERANDS];
+  bool op_riprel[MAX_OPERANDS];
+  char *op_out[MAX_OPERANDS];
   bfd_vma op_address[MAX_OPERANDS];
-  bfd_vma op_riprel[MAX_OPERANDS];
   bfd_vma start_pc;
 
   /* On the 386's of 1988, the maximum length of an instruction is 15 bytes.
@@ -254,14 +248,13 @@ struct instr_info
    * The function returns the length of this instruction in bytes.
    */
   char intel_syntax;
-  char intel_mnemonic;
+  bool intel_mnemonic;
   char open_char;
   char close_char;
   char separator_char;
   char scale_char;
 
   enum x86_64_isa isa64;
-
 };
 
 /* Mark parts used in the REX prefix.  When we are testing for
@@ -281,42 +274,40 @@ struct instr_info
 
 
 #define EVEX_b_used 1
+#define EVEX_len_used 2
 
 /* Flags stored in PREFIXES.  */
 #define PREFIX_REPZ 1
 #define PREFIX_REPNZ 2
-#define PREFIX_LOCK 4
-#define PREFIX_CS 8
-#define PREFIX_SS 0x10
-#define PREFIX_DS 0x20
-#define PREFIX_ES 0x40
-#define PREFIX_FS 0x80
-#define PREFIX_GS 0x100
+#define PREFIX_CS 4
+#define PREFIX_SS 8
+#define PREFIX_DS 0x10
+#define PREFIX_ES 0x20
+#define PREFIX_FS 0x40
+#define PREFIX_GS 0x80
+#define PREFIX_LOCK 0x100
 #define PREFIX_DATA 0x200
 #define PREFIX_ADDR 0x400
 #define PREFIX_FWAIT 0x800
 
 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
-   to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
+   to ADDR (exclusive) are valid.  Returns true for success, false
    on error.  */
-#define FETCH_DATA(info, addr) \
-  ((addr) <= ((struct dis_private *) (info->private_data))->max_fetched \
-   ? 1 : fetch_data ((info), (addr)))
-
-static int
-fetch_data (struct disassemble_info *info, bfd_byte *addr)
+static bool
+fetch_code (struct disassemble_info *info, bfd_byte *until)
 {
-  int status;
-  struct dis_private *priv = (struct dis_private *) info->private_data;
+  int status = -1;
+  struct dis_private *priv = info->private_data;
   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
 
-  if (addr <= priv->the_buffer + MAX_MNEM_SIZE)
+  if (until <= priv->max_fetched)
+    return true;
+
+  if (until <= priv->the_buffer + MAX_MNEM_SIZE)
     status = (*info->read_memory_func) (start,
                                        priv->max_fetched,
-                                       addr - priv->max_fetched,
+                                       until - priv->max_fetched,
                                        info);
-  else
-    status = -1;
   if (status != 0)
     {
       /* If we did manage to read at least one byte, then
@@ -325,10 +316,50 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
         STATUS.  */
       if (priv->max_fetched == priv->the_buffer)
        (*info->memory_error_func) (status, start, info);
-      OPCODES_SIGLONGJMP (priv->bailout, 1);
+      return false;
     }
+
+  priv->max_fetched = until;
+  return true;
+}
+
+static bool
+fetch_modrm (instr_info *ins)
+{
+  if (!fetch_code (ins->info, ins->codep + 1))
+    return false;
+
+  ins->modrm.mod = (*ins->codep >> 6) & 3;
+  ins->modrm.reg = (*ins->codep >> 3) & 7;
+  ins->modrm.rm = *ins->codep & 7;
+
+  return true;
+}
+
+static int
+fetch_error (const instr_info *ins)
+{
+  /* Getting here means we tried for data but didn't get it.  That
+     means we have an incomplete instruction of some sort.  Just
+     print the first byte as a prefix or a .byte pseudo-op.  */
+  const struct dis_private *priv = ins->info->private_data;
+  const char *name = NULL;
+
+  if (ins->codep <= priv->the_buffer)
+    return -1;
+
+  if (ins->prefixes || ins->fwait_prefix >= 0 || (ins->rex & REX_OPCODE))
+    name = prefix_name (ins, priv->the_buffer[0], priv->orig_sizeflag);
+  if (name != NULL)
+    i386_dis_printf (ins, dis_style_mnemonic, "%s", name);
   else
-    priv->max_fetched = addr;
+    {
+      /* Just print the first byte as a .byte instruction.  */
+      i386_dis_printf (ins, dis_style_assembler_directive, ".byte ");
+      i386_dis_printf (ins, dis_style_immediate, "%#x",
+                      (unsigned int) priv->the_buffer[0]);
+    }
+
   return 1;
 }
 
@@ -375,11 +406,13 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define Ma { OP_M, a_mode }
 #define Mb { OP_M, b_mode }
 #define Md { OP_M, d_mode }
+#define Mdq { OP_M, dq_mode }
 #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 { OP_M, v_mode }
 #define Mv_bnd { OP_M, v_bndmk_mode }
+#define Mw { OP_M, w_mode }
 #define Mx { OP_M, x_mode }
 #define Mxmm { OP_M, xmm_mode }
 #define Gb { OP_G, b_mode }
@@ -628,8 +661,6 @@ enum
   ymm_mode,
   /* quad word, ymmword or zmmword memory operand.  */
   ymmq_mode,
-  /* 32-byte YMM or 16-byte word operand */
-  ymmxmm_mode,
   /* TMM operand */
   tmm_mode,
   /* d_mode in 32bit, q_mode in 64bit mode.  */
@@ -841,6 +872,8 @@ enum
   MOD_0F01_REG_3,
   MOD_0F01_REG_5,
   MOD_0F01_REG_7,
+  MOD_0F02,
+  MOD_0F03,
   MOD_0F12_PREFIX_0,
   MOD_0F12_PREFIX_2,
   MOD_0F13,
@@ -851,6 +884,8 @@ enum
   MOD_0F18_REG_1,
   MOD_0F18_REG_2,
   MOD_0F18_REG_3,
+  MOD_0F18_REG_6,
+  MOD_0F18_REG_7,
   MOD_0F1A_PREFIX_0,
   MOD_0F1B_PREFIX_0,
   MOD_0F1B_PREFIX_1,
@@ -942,10 +977,12 @@ enum
   MOD_VEX_0F384B_X86_64_P_3_W_0,
   MOD_VEX_0F385A,
   MOD_VEX_0F385C_X86_64_P_1_W_0,
+  MOD_VEX_0F385C_X86_64_P_3_W_0,
   MOD_VEX_0F385E_X86_64_P_0_W_0,
   MOD_VEX_0F385E_X86_64_P_1_W_0,
   MOD_VEX_0F385E_X86_64_P_2_W_0,
   MOD_VEX_0F385E_X86_64_P_3_W_0,
+  MOD_VEX_0F386C_X86_64_W_0,
   MOD_VEX_0F388C,
   MOD_VEX_0F388E,
   MOD_VEX_0F3A30_L_0,
@@ -955,13 +992,6 @@ enum
 
   MOD_XOP_09_12,
 
-  MOD_EVEX_0F12_PREFIX_0,
-  MOD_EVEX_0F12_PREFIX_2,
-  MOD_EVEX_0F13,
-  MOD_EVEX_0F16_PREFIX_0,
-  MOD_EVEX_0F16_PREFIX_2,
-  MOD_EVEX_0F17,
-  MOD_EVEX_0F2B,
   MOD_EVEX_0F381A,
   MOD_EVEX_0F381B,
   MOD_EVEX_0F3828_P_1,
@@ -998,6 +1028,7 @@ enum
 enum
 {
   PREFIX_90 = 0,
+  PREFIX_0F01_REG_0_MOD_3_RM_6,
   PREFIX_0F01_REG_1_RM_4,
   PREFIX_0F01_REG_1_RM_5,
   PREFIX_0F01_REG_1_RM_6,
@@ -1012,6 +1043,7 @@ enum
   PREFIX_0F01_REG_5_MOD_3_RM_6,
   PREFIX_0F01_REG_5_MOD_3_RM_7,
   PREFIX_0F01_REG_7_MOD_3_RM_2,
+  PREFIX_0F01_REG_7_MOD_3_RM_5,
   PREFIX_0F01_REG_7_MOD_3_RM_6,
   PREFIX_0F01_REG_7_MOD_3_RM_7,
   PREFIX_0F09,
@@ -1019,6 +1051,8 @@ enum
   PREFIX_0F11,
   PREFIX_0F12,
   PREFIX_0F16,
+  PREFIX_0F18_REG_6_MOD_0_X86_64,
+  PREFIX_0F18_REG_7_MOD_0_X86_64,
   PREFIX_0F1A,
   PREFIX_0F1B,
   PREFIX_0F1C,
@@ -1085,6 +1119,7 @@ enum
   PREFIX_0F38F8,
   PREFIX_0F38FA,
   PREFIX_0F38FB,
+  PREFIX_0F38FC,
   PREFIX_0F3A0F,
   PREFIX_VEX_0F10,
   PREFIX_VEX_0F11,
@@ -1146,27 +1181,20 @@ enum
   PREFIX_VEX_0FF0,
   PREFIX_VEX_0F3849_X86_64,
   PREFIX_VEX_0F384B_X86_64,
+  PREFIX_VEX_0F3850_W_0,
+  PREFIX_VEX_0F3851_W_0,
   PREFIX_VEX_0F385C_X86_64,
   PREFIX_VEX_0F385E_X86_64,
+  PREFIX_VEX_0F386C_X86_64_W_0_M_1_L_0,
+  PREFIX_VEX_0F3872,
+  PREFIX_VEX_0F38B0_W_0,
+  PREFIX_VEX_0F38B1_W_0,
   PREFIX_VEX_0F38F5_L_0,
   PREFIX_VEX_0F38F6_L_0,
   PREFIX_VEX_0F38F7_L_0,
   PREFIX_VEX_0F3AF0_L_0,
 
-  PREFIX_EVEX_0F10,
-  PREFIX_EVEX_0F11,
-  PREFIX_EVEX_0F12,
-  PREFIX_EVEX_0F16,
-  PREFIX_EVEX_0F2A,
-  PREFIX_EVEX_0F51,
-  PREFIX_EVEX_0F58,
-  PREFIX_EVEX_0F59,
-  PREFIX_EVEX_0F5A,
   PREFIX_EVEX_0F5B,
-  PREFIX_EVEX_0F5C,
-  PREFIX_EVEX_0F5D,
-  PREFIX_EVEX_0F5E,
-  PREFIX_EVEX_0F5F,
   PREFIX_EVEX_0F6F,
   PREFIX_EVEX_0F70,
   PREFIX_EVEX_0F78,
@@ -1285,6 +1313,8 @@ enum
   X86_64_E9,
   X86_64_EA,
   X86_64_0F01_REG_0,
+  X86_64_0F01_REG_0_MOD_3_RM_6_P_1,
+  X86_64_0F01_REG_0_MOD_3_RM_6_P_3,
   X86_64_0F01_REG_1,
   X86_64_0F01_REG_1_RM_5_PREFIX_2,
   X86_64_0F01_REG_1_RM_6_PREFIX_2,
@@ -1295,9 +1325,12 @@ enum
   X86_64_0F01_REG_5_MOD_3_RM_5_PREFIX_1,
   X86_64_0F01_REG_5_MOD_3_RM_6_PREFIX_1,
   X86_64_0F01_REG_5_MOD_3_RM_7_PREFIX_1,
+  X86_64_0F01_REG_7_MOD_3_RM_5_PREFIX_1,
   X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_1,
   X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_3,
   X86_64_0F01_REG_7_MOD_3_RM_7_PREFIX_1,
+  X86_64_0F18_REG_6_MOD_0,
+  X86_64_0F18_REG_7_MOD_0,
   X86_64_0F24,
   X86_64_0F26,
   X86_64_0FC7_REG_6_MOD_3_PREFIX_1,
@@ -1305,7 +1338,24 @@ enum
   X86_64_VEX_0F3849,
   X86_64_VEX_0F384B,
   X86_64_VEX_0F385C,
-  X86_64_VEX_0F385E
+  X86_64_VEX_0F385E,
+  X86_64_VEX_0F386C,
+  X86_64_VEX_0F38E0,
+  X86_64_VEX_0F38E1,
+  X86_64_VEX_0F38E2,
+  X86_64_VEX_0F38E3,
+  X86_64_VEX_0F38E4,
+  X86_64_VEX_0F38E5,
+  X86_64_VEX_0F38E6,
+  X86_64_VEX_0F38E7,
+  X86_64_VEX_0F38E8,
+  X86_64_VEX_0F38E9,
+  X86_64_VEX_0F38EA,
+  X86_64_VEX_0F38EB,
+  X86_64_VEX_0F38EC,
+  X86_64_VEX_0F38ED,
+  X86_64_VEX_0F38EE,
+  X86_64_VEX_0F38EF,
 };
 
 enum
@@ -1385,10 +1435,12 @@ enum
   VEX_LEN_0F384B_X86_64_P_3_W_0_M_0,
   VEX_LEN_0F385A_M_0,
   VEX_LEN_0F385C_X86_64_P_1_W_0_M_0,
+  VEX_LEN_0F385C_X86_64_P_3_W_0_M_0,
   VEX_LEN_0F385E_X86_64_P_0_W_0_M_0,
   VEX_LEN_0F385E_X86_64_P_1_W_0_M_0,
   VEX_LEN_0F385E_X86_64_P_2_W_0_M_0,
   VEX_LEN_0F385E_X86_64_P_3_W_0_M_0,
+  VEX_LEN_0F386C_X86_64_W_0_M_1,
   VEX_LEN_0F38DB,
   VEX_LEN_0F38F2,
   VEX_LEN_0F38F3,
@@ -1551,12 +1603,19 @@ enum
   VEX_W_0F3859,
   VEX_W_0F385A_M_0_L_0,
   VEX_W_0F385C_X86_64_P_1,
+  VEX_W_0F385C_X86_64_P_3,
   VEX_W_0F385E_X86_64_P_0,
   VEX_W_0F385E_X86_64_P_1,
   VEX_W_0F385E_X86_64_P_2,
   VEX_W_0F385E_X86_64_P_3,
+  VEX_W_0F386C_X86_64,
+  VEX_W_0F3872_P_1,
   VEX_W_0F3878,
   VEX_W_0F3879,
+  VEX_W_0F38B0,
+  VEX_W_0F38B1,
+  VEX_W_0F38B4,
+  VEX_W_0F38B5,
   VEX_W_0F38CF,
   VEX_W_0F3A00_L_1,
   VEX_W_0F3A01_L_1,
@@ -1621,36 +1680,7 @@ enum
   VEX_W_0FXOP_09_E2_L_0,
   VEX_W_0FXOP_09_E3_L_0,
 
-  EVEX_W_0F10_P_1,
-  EVEX_W_0F10_P_3,
-  EVEX_W_0F11_P_1,
-  EVEX_W_0F11_P_3,
-  EVEX_W_0F12_P_0_M_1,
-  EVEX_W_0F12_P_1,
-  EVEX_W_0F12_P_3,
-  EVEX_W_0F16_P_0_M_1,
-  EVEX_W_0F16_P_1,
-  EVEX_W_0F51_P_1,
-  EVEX_W_0F51_P_3,
-  EVEX_W_0F58_P_1,
-  EVEX_W_0F58_P_3,
-  EVEX_W_0F59_P_1,
-  EVEX_W_0F59_P_3,
-  EVEX_W_0F5A_P_0,
-  EVEX_W_0F5A_P_1,
-  EVEX_W_0F5A_P_2,
-  EVEX_W_0F5A_P_3,
   EVEX_W_0F5B_P_0,
-  EVEX_W_0F5B_P_1,
-  EVEX_W_0F5B_P_2,
-  EVEX_W_0F5C_P_1,
-  EVEX_W_0F5C_P_3,
-  EVEX_W_0F5D_P_1,
-  EVEX_W_0F5D_P_3,
-  EVEX_W_0F5E_P_1,
-  EVEX_W_0F5E_P_3,
-  EVEX_W_0F5F_P_1,
-  EVEX_W_0F5F_P_3,
   EVEX_W_0F62,
   EVEX_W_0F66,
   EVEX_W_0F6A,
@@ -1678,15 +1708,11 @@ enum
   EVEX_W_0F7F_P_1,
   EVEX_W_0F7F_P_2,
   EVEX_W_0F7F_P_3,
-  EVEX_W_0FC2_P_1,
-  EVEX_W_0FC2_P_3,
   EVEX_W_0FD2,
   EVEX_W_0FD3,
   EVEX_W_0FD4,
   EVEX_W_0FD6,
   EVEX_W_0FE6_P_1,
-  EVEX_W_0FE6_P_2,
-  EVEX_W_0FE6_P_3,
   EVEX_W_0FE7,
   EVEX_W_0FF2,
   EVEX_W_0FF3,
@@ -1694,7 +1720,7 @@ enum
   EVEX_W_0FFA,
   EVEX_W_0FFB,
   EVEX_W_0FFE,
-  EVEX_W_0F380D,
+
   EVEX_W_0F3810_P_1,
   EVEX_W_0F3810_P_2,
   EVEX_W_0F3811_P_1,
@@ -1702,7 +1728,6 @@ enum
   EVEX_W_0F3812_P_1,
   EVEX_W_0F3812_P_2,
   EVEX_W_0F3813_P_1,
-  EVEX_W_0F3813_P_2,
   EVEX_W_0F3814_P_1,
   EVEX_W_0F3815_P_1,
   EVEX_W_0F3819_L_n,
@@ -1731,21 +1756,15 @@ enum
   EVEX_W_0F3835_P_2,
   EVEX_W_0F3837,
   EVEX_W_0F383A_P_1,
-  EVEX_W_0F3852_P_1,
   EVEX_W_0F3859,
   EVEX_W_0F385A_M_0_L_n,
   EVEX_W_0F385B_M_0_L_2,
   EVEX_W_0F3870,
-  EVEX_W_0F3872_P_1,
   EVEX_W_0F3872_P_2,
-  EVEX_W_0F3872_P_3,
   EVEX_W_0F387A,
   EVEX_W_0F387B,
   EVEX_W_0F3883,
 
-  EVEX_W_0F3A05,
-  EVEX_W_0F3A09,
-  EVEX_W_0F3A0B,
   EVEX_W_0F3A18_L_n,
   EVEX_W_0F3A19_L_n,
   EVEX_W_0F3A1A_L_2,
@@ -1765,7 +1784,7 @@ enum
   EVEX_W_MAP5_7A_P_3,
 };
 
-typedef void (*op_rtn) (instr_info *ins, int bytemode, int sizeflag);
+typedef bool (*op_rtn) (instr_info *ins, int bytemode, int sizeflag);
 
 struct dis386 {
   const char *name;
@@ -1823,10 +1842,12 @@ 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)
-   "XD" => print 'd' if EVEX.W=1, EVEX.W=0 is not a valid encoding
+   "XD" => print 'd' if !EVEX or EVEX.W=1, EVEX.W=0 is not a valid encoding
    "XH" => print 'h' if EVEX.W=0, EVEX.W=1 is not a valid encoding (for FP16)
-   "XS" => print 's' if EVEX.W=0, EVEX.W=1 is not a valid encoding
-   "XV" => print "{vex3}" pseudo prefix
+   "XS" => print 's' if !EVEX or EVEX.W=0, EVEX.W=1 is not a valid encoding
+   "XV" => print "{vex} " pseudo prefix
+   "XE" => print "{evex} " pseudo prefix if no EVEX-specific functionality is
+          is used by an EVEX-encoded (AVX512VL) instruction.
    "LQ" => print 'l' ('d' in Intel mode) or 'q' for memory operand, cond
           being false, or no operand at all in 64bit mode, or if suffix_always
           is true.
@@ -2140,8 +2161,8 @@ static const struct dis386 dis386_twobyte[] = {
   /* 00 */
   { REG_TABLE (REG_0F00 ) },
   { REG_TABLE (REG_0F01 ) },
-  { "larS",            { Gv, Ew }, 0 },
-  { "lslS",            { Gv, Ew }, 0 },
+  { MOD_TABLE (MOD_0F02) },
+  { MOD_TABLE (MOD_0F03) },
   { Bad_Opcode },
   { "syscall",         { XX }, 0 },
   { "clts",            { XX }, 0 },
@@ -2427,7 +2448,7 @@ static const struct dis386 dis386_twobyte[] = {
   { "ud0S",            { Gv, Ev }, 0 },
 };
 
-static const unsigned char onebyte_has_modrm[256] = {
+static const bool onebyte_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,1,1,1,1,0,0,0,0, /* 00 */
@@ -2450,7 +2471,7 @@ static const unsigned char onebyte_has_modrm[256] = {
   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
 };
 
-static const unsigned char twobyte_has_modrm[256] = {
+static const bool 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 */
@@ -2485,90 +2506,48 @@ struct op
    need to update onebyte_has_modrm or twobyte_has_modrm.  */
 #define MODRM_CHECK  if (!ins->need_modrm) abort ()
 
-static const char *intel_names64[] = {
-  "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
-  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
-};
-static const char *intel_names32[] = {
-  "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
-  "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
-};
-static const char *intel_names16[] = {
-  "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
-  "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
-};
-static const char *intel_names8[] = {
-  "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
-};
-static const char *intel_names8rex[] = {
-  "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
-  "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
-};
-static const char *intel_names_seg[] = {
-  "es", "cs", "ss", "ds", "fs", "gs", "?", "?",
-};
-static const char *intel_index64 = "riz";
-static const char *intel_index32 = "eiz";
-static const char *intel_index16[] = {
+static const char intel_index16[][6] = {
   "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"
 };
 
-static const char *att_names64[] = {
+static const char att_names64[][8] = {
   "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
   "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
 };
-static const char *att_names32[] = {
+static const char att_names32[][8] = {
   "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
   "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
 };
-static const char *att_names16[] = {
+static const char att_names16[][8] = {
   "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
   "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
 };
-static const char *att_names8[] = {
+static const char att_names8[][8] = {
   "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
 };
-static const char *att_names8rex[] = {
+static const char att_names8rex[][8] = {
   "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil",
   "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
 };
-static const char *att_names_seg[] = {
+static const char att_names_seg[][4] = {
   "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%?", "%?",
 };
-static const char *att_index64 = "%riz";
-static const char *att_index32 = "%eiz";
-static const char *att_index16[] = {
+static const char att_index64[] = "%riz";
+static const char att_index32[] = "%eiz";
+static const char att_index16[][8] = {
   "%bx,%si", "%bx,%di", "%bp,%si", "%bp,%di", "%si", "%di", "%bp", "%bx"
 };
 
-static const char *intel_names_mm[] = {
-  "mm0", "mm1", "mm2", "mm3",
-  "mm4", "mm5", "mm6", "mm7"
-};
-static const char *att_names_mm[] = {
+static const char att_names_mm[][8] = {
   "%mm0", "%mm1", "%mm2", "%mm3",
   "%mm4", "%mm5", "%mm6", "%mm7"
 };
 
-static const char *intel_names_bnd[] = {
-  "bnd0", "bnd1", "bnd2", "bnd3"
-};
-
-static const char *att_names_bnd[] = {
+static const char att_names_bnd[][8] = {
   "%bnd0", "%bnd1", "%bnd2", "%bnd3"
 };
 
-static const char *intel_names_xmm[] = {
-  "xmm0", "xmm1", "xmm2", "xmm3",
-  "xmm4", "xmm5", "xmm6", "xmm7",
-  "xmm8", "xmm9", "xmm10", "xmm11",
-  "xmm12", "xmm13", "xmm14", "xmm15",
-  "xmm16", "xmm17", "xmm18", "xmm19",
-  "xmm20", "xmm21", "xmm22", "xmm23",
-  "xmm24", "xmm25", "xmm26", "xmm27",
-  "xmm28", "xmm29", "xmm30", "xmm31"
-};
-static const char *att_names_xmm[] = {
+static const char att_names_xmm[][8] = {
   "%xmm0", "%xmm1", "%xmm2", "%xmm3",
   "%xmm4", "%xmm5", "%xmm6", "%xmm7",
   "%xmm8", "%xmm9", "%xmm10", "%xmm11",
@@ -2579,17 +2558,7 @@ static const char *att_names_xmm[] = {
   "%xmm28", "%xmm29", "%xmm30", "%xmm31"
 };
 
-static const char *intel_names_ymm[] = {
-  "ymm0", "ymm1", "ymm2", "ymm3",
-  "ymm4", "ymm5", "ymm6", "ymm7",
-  "ymm8", "ymm9", "ymm10", "ymm11",
-  "ymm12", "ymm13", "ymm14", "ymm15",
-  "ymm16", "ymm17", "ymm18", "ymm19",
-  "ymm20", "ymm21", "ymm22", "ymm23",
-  "ymm24", "ymm25", "ymm26", "ymm27",
-  "ymm28", "ymm29", "ymm30", "ymm31"
-};
-static const char *att_names_ymm[] = {
+static const char att_names_ymm[][8] = {
   "%ymm0", "%ymm1", "%ymm2", "%ymm3",
   "%ymm4", "%ymm5", "%ymm6", "%ymm7",
   "%ymm8", "%ymm9", "%ymm10", "%ymm11",
@@ -2600,17 +2569,7 @@ static const char *att_names_ymm[] = {
   "%ymm28", "%ymm29", "%ymm30", "%ymm31"
 };
 
-static const char *intel_names_zmm[] = {
-  "zmm0", "zmm1", "zmm2", "zmm3",
-  "zmm4", "zmm5", "zmm6", "zmm7",
-  "zmm8", "zmm9", "zmm10", "zmm11",
-  "zmm12", "zmm13", "zmm14", "zmm15",
-  "zmm16", "zmm17", "zmm18", "zmm19",
-  "zmm20", "zmm21", "zmm22", "zmm23",
-  "zmm24", "zmm25", "zmm26", "zmm27",
-  "zmm28", "zmm29", "zmm30", "zmm31"
-};
-static const char *att_names_zmm[] = {
+static const char att_names_zmm[][8] = {
   "%zmm0", "%zmm1", "%zmm2", "%zmm3",
   "%zmm4", "%zmm5", "%zmm6", "%zmm7",
   "%zmm8", "%zmm9", "%zmm10", "%zmm11",
@@ -2621,19 +2580,12 @@ static const char *att_names_zmm[] = {
   "%zmm28", "%zmm29", "%zmm30", "%zmm31"
 };
 
-static const char *intel_names_tmm[] = {
-  "tmm0", "tmm1", "tmm2", "tmm3",
-  "tmm4", "tmm5", "tmm6", "tmm7"
-};
-static const char *att_names_tmm[] = {
+static const char att_names_tmm[][8] = {
   "%tmm0", "%tmm1", "%tmm2", "%tmm3",
   "%tmm4", "%tmm5", "%tmm6", "%tmm7"
 };
 
-static const char *intel_names_mask[] = {
-  "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7"
-};
-static const char *att_names_mask[] = {
+static const char att_names_mask[][8] = {
   "%k0", "%k1", "%k2", "%k3", "%k4", "%k5", "%k6", "%k7"
 };
 
@@ -2855,8 +2807,8 @@ static const struct dis386 reg_table[][8] = {
     { MOD_TABLE (MOD_0F18_REG_3) },
     { "nopQ",          { Ev }, 0 },
     { "nopQ",          { Ev }, 0 },
-    { "nopQ",          { Ev }, 0 },
-    { "nopQ",          { Ev }, 0 },
+    { MOD_TABLE (MOD_0F18_REG_6) },
+    { MOD_TABLE (MOD_0F18_REG_7) },
   },
   /* REG_0F1C_P_0_MOD_0 */
   {
@@ -3057,12 +3009,20 @@ static const struct dis386 reg_table[][8] = {
 static const struct dis386 prefix_table[][4] = {
   /* PREFIX_90 */
   {
-    { "xchgS", { { NOP_Fixup1, eAX_reg }, { NOP_Fixup2, eAX_reg } }, 0 },
+    { "xchgS", { { NOP_Fixup, 0 }, { NOP_Fixup, 1 } }, 0 },
     { "pause", { XX }, 0 },
-    { "xchgS", { { NOP_Fixup1, eAX_reg }, { NOP_Fixup2, eAX_reg } }, 0 },
+    { "xchgS", { { NOP_Fixup, 0 }, { NOP_Fixup, 1 } }, 0 },
     { NULL, { { NULL, 0 } }, PREFIX_IGNORED }
   },
 
+  /* PREFIX_0F01_REG_0_MOD_3_RM_6 */
+  {
+    { "wrmsrns",        { Skip_MODRM }, 0 },
+    { X86_64_TABLE (X86_64_0F01_REG_0_MOD_3_RM_6_P_1) },
+    { Bad_Opcode },
+    { X86_64_TABLE (X86_64_0F01_REG_0_MOD_3_RM_6_P_3) },
+  },
+
   /* PREFIX_0F01_REG_1_RM_4 */
   {
     { Bad_Opcode },
@@ -3161,6 +3121,12 @@ static const struct dis386 prefix_table[][4] = {
     { "mcommit",       { Skip_MODRM }, 0 },
   },
 
+  /* PREFIX_0F01_REG_7_MOD_3_RM_5 */
+  {
+    { "rdpru", { Skip_MODRM }, 0 },
+    { X86_64_TABLE (X86_64_0F01_REG_7_MOD_3_RM_5_PREFIX_1) },
+  },
+
   /* PREFIX_0F01_REG_7_MOD_3_RM_6 */
   {
     { "invlpgb",        { Skip_MODRM }, 0 },
@@ -3214,6 +3180,22 @@ static const struct dis386 prefix_table[][4] = {
     { MOD_TABLE (MOD_0F16_PREFIX_2) },
   },
 
+  /* PREFIX_0F18_REG_6_MOD_0_X86_64 */
+  {
+    { "prefetchit1",   { { PREFETCHI_Fixup, b_mode } }, 0 },
+    { "nopQ",          { Ev }, 0 },
+    { "nopQ",          { Ev }, 0 },
+    { "nopQ",          { Ev }, 0 },
+  },
+
+  /* PREFIX_0F18_REG_7_MOD_0_X86_64 */
+  {
+    { "prefetchit0",   { { PREFETCHI_Fixup, b_mode } }, 0 },
+    { "nopQ",          { Ev }, 0 },
+    { "nopQ",          { Ev }, 0 },
+    { "nopQ",          { Ev }, 0 },
+  },
+
   /* PREFIX_0F1A */
   {
     { MOD_TABLE (MOD_0F1A_PREFIX_0) },
@@ -3693,6 +3675,14 @@ static const struct dis386 prefix_table[][4] = {
     { MOD_TABLE (MOD_0F38FB_PREFIX_1) },
   },
 
+  /* PREFIX_0F38FC */
+  {
+    { "aadd",  { Mdq, Gdq }, 0 },
+    { "axor",  { Mdq, Gdq }, 0 },
+    { "aand",  { Mdq, Gdq }, 0 },
+    { "aor",   { Mdq, Gdq }, 0 },
+  },
+
   /* PREFIX_0F3A0F */
   {
     { Bad_Opcode },
@@ -3701,71 +3691,71 @@ static const struct dis386 prefix_table[][4] = {
 
   /* PREFIX_VEX_0F10 */
   {
-    { "vmovups",       { XM, EXx }, 0 },
-    { "vmovss",                { XMScalar, VexScalarR, EXd }, 0 },
-    { "vmovupd",       { XM, EXx }, 0 },
-    { "vmovsd",                { XMScalar, VexScalarR, EXq }, 0 },
+    { "%XEvmovupX",    { XM, EXEvexXNoBcst }, 0 },
+    { "%XEvmovs%XS",   { XMScalar, VexScalarR, EXd }, 0 },
+    { "%XEvmovupX",    { XM, EXEvexXNoBcst }, 0 },
+    { "%XEvmovs%XD",   { XMScalar, VexScalarR, EXq }, 0 },
   },
 
   /* PREFIX_VEX_0F11 */
   {
-    { "vmovups",       { EXxS, XM }, 0 },
-    { "vmovss",                { EXdS, VexScalarR, XMScalar }, 0 },
-    { "vmovupd",       { EXxS, XM }, 0 },
-    { "vmovsd",                { EXqS, VexScalarR, XMScalar }, 0 },
+    { "%XEvmovupX",    { EXxS, XM }, 0 },
+    { "%XEvmovs%XS",   { EXdS, VexScalarR, XMScalar }, 0 },
+    { "%XEvmovupX",    { EXxS, XM }, 0 },
+    { "%XEvmovs%XD",   { EXqS, VexScalarR, XMScalar }, 0 },
   },
 
   /* PREFIX_VEX_0F12 */
   {
     { MOD_TABLE (MOD_VEX_0F12_PREFIX_0) },
-    { "vmovsldup",     { XM, EXx }, 0 },
+    { "%XEvmov%XSldup",        { XM, EXEvexXNoBcst }, 0 },
     { MOD_TABLE (MOD_VEX_0F12_PREFIX_2) },
-    { "vmovddup",      { XM, EXymmq }, 0 },
+    { "%XEvmov%XDdup", { XM, EXymmq }, 0 },
   },
 
   /* PREFIX_VEX_0F16 */
   {
     { MOD_TABLE (MOD_VEX_0F16_PREFIX_0) },
-    { "vmovshdup",     { XM, EXx }, 0 },
+    { "%XEvmov%XShdup",        { XM, EXEvexXNoBcst }, 0 },
     { MOD_TABLE (MOD_VEX_0F16_PREFIX_2) },
   },
 
   /* PREFIX_VEX_0F2A */
   {
     { Bad_Opcode },
-    { "vcvtsi2ss{%LQ|}",       { XMScalar, VexScalar, Edq }, 0 },
+    { "%XEvcvtsi2ss{%LQ|}",    { XMScalar, VexScalar, EXxEVexR, Edq }, 0 },
     { Bad_Opcode },
-    { "vcvtsi2sd{%LQ|}",       { XMScalar, VexScalar, Edq }, 0 },
+    { "%XEvcvtsi2sd{%LQ|}",    { XMScalar, VexScalar, EXxEVexR64, Edq }, 0 },
   },
 
   /* PREFIX_VEX_0F2C */
   {
     { Bad_Opcode },
-    { "vcvttss2si",    { Gdq, EXd, EXxEVexS }, 0 },
+    { "%XEvcvttss2si", { Gdq, EXd, EXxEVexS }, 0 },
     { Bad_Opcode },
-    { "vcvttsd2si",    { Gdq, EXq, EXxEVexS }, 0 },
+    { "%XEvcvttsd2si", { Gdq, EXq, EXxEVexS }, 0 },
   },
 
   /* PREFIX_VEX_0F2D */
   {
     { Bad_Opcode },
-    { "vcvtss2si",     { Gdq, EXd, EXxEVexR }, 0 },
+    { "%XEvcvtss2si",  { Gdq, EXd, EXxEVexR }, 0 },
     { Bad_Opcode },
-    { "vcvtsd2si",     { Gdq, EXq, EXxEVexR }, 0 },
+    { "%XEvcvtsd2si",  { Gdq, EXq, EXxEVexR }, 0 },
   },
 
   /* PREFIX_VEX_0F2E */
   {
-    { "vucomisX",      { XMScalar, EXd, EXxEVexS }, PREFIX_OPCODE },
+    { "%XEvucomisX",   { XMScalar, EXd, EXxEVexS }, 0 },
     { Bad_Opcode },
-    { "vucomisX",      { XMScalar, EXq, EXxEVexS }, PREFIX_OPCODE },
+    { "%XEvucomisX",   { XMScalar, EXq, EXxEVexS }, 0 },
   },
 
   /* PREFIX_VEX_0F2F */
   {
-    { "vcomisX",       { XMScalar, EXd, EXxEVexS }, PREFIX_OPCODE },
+    { "%XEvcomisX",    { XMScalar, EXd, EXxEVexS }, 0 },
     { Bad_Opcode },
-    { "vcomisX",       { XMScalar, EXq, EXxEVexS }, PREFIX_OPCODE },
+    { "%XEvcomisX",    { XMScalar, EXq, EXxEVexS }, 0 },
   },
 
   /* PREFIX_VEX_0F41_L_1_M_1_W_0 */
@@ -3880,10 +3870,10 @@ static const struct dis386 prefix_table[][4] = {
 
   /* PREFIX_VEX_0F51 */
   {
-    { "vsqrtps",       { XM, EXx }, 0 },
-    { "vsqrtss",       { XMScalar, VexScalar, EXd }, 0 },
-    { "vsqrtpd",       { XM, EXx }, 0 },
-    { "vsqrtsd",       { XMScalar, VexScalar, EXq }, 0 },
+    { "%XEvsqrtpX",    { XM, EXx, EXxEVexR }, 0 },
+    { "%XEvsqrts%XS",  { XMScalar, VexScalar, EXd, EXxEVexR }, 0 },
+    { "%XEvsqrtpX",    { XM, EXx, EXxEVexR }, 0 },
+    { "%XEvsqrts%XD",  { XMScalar, VexScalar, EXq, EXxEVexR }, 0 },
   },
 
   /* PREFIX_VEX_0F52 */
@@ -3900,26 +3890,26 @@ static const struct dis386 prefix_table[][4] = {
 
   /* PREFIX_VEX_0F58 */
   {
-    { "vaddps",                { XM, Vex, EXx }, 0 },
-    { "vaddss",                { XMScalar, VexScalar, EXd }, 0 },
-    { "vaddpd",                { XM, Vex, EXx }, 0 },
-    { "vaddsd",                { XMScalar, VexScalar, EXq }, 0 },
+    { "%XEvaddpX",     { XM, Vex, EXx, EXxEVexR }, 0 },
+    { "%XEvadds%XS",   { XMScalar, VexScalar, EXd, EXxEVexR }, 0 },
+    { "%XEvaddpX",     { XM, Vex, EXx, EXxEVexR }, 0 },
+    { "%XEvadds%XD",   { XMScalar, VexScalar, EXq, EXxEVexR }, 0 },
   },
 
   /* PREFIX_VEX_0F59 */
   {
-    { "vmulps",                { XM, Vex, EXx }, 0 },
-    { "vmulss",                { XMScalar, VexScalar, EXd }, 0 },
-    { "vmulpd",                { XM, Vex, EXx }, 0 },
-    { "vmulsd",                { XMScalar, VexScalar, EXq }, 0 },
+    { "%XEvmulpX",     { XM, Vex, EXx, EXxEVexR }, 0 },
+    { "%XEvmuls%XS",   { XMScalar, VexScalar, EXd, EXxEVexR }, 0 },
+    { "%XEvmulpX",     { XM, Vex, EXx, EXxEVexR }, 0 },
+    { "%XEvmuls%XD",   { XMScalar, VexScalar, EXq, EXxEVexR }, 0 },
   },
 
   /* PREFIX_VEX_0F5A */
   {
-    { "vcvtps2pd",     { XM, EXxmmq }, 0 },
-    { "vcvtss2sd",     { XMScalar, VexScalar, EXd }, 0 },
-    { "vcvtpd2ps%XY",{ XMM, EXx }, 0 },
-    { "vcvtsd2ss",     { XMScalar, VexScalar, EXq }, 0 },
+    { "%XEvcvtp%XS2pd", { XM, EXEvexHalfBcstXmmq, EXxEVexS }, 0 },
+    { "%XEvcvts%XS2sd", { XMScalar, VexScalar, EXd, EXxEVexS }, 0 },
+    { "%XEvcvtp%XD2ps%XY", { XMxmmq, EXx, EXxEVexR }, 0 },
+    { "%XEvcvts%XD2ss", { XMScalar, VexScalar, EXq, EXxEVexR }, 0 },
   },
 
   /* PREFIX_VEX_0F5B */
@@ -3931,34 +3921,34 @@ static const struct dis386 prefix_table[][4] = {
 
   /* PREFIX_VEX_0F5C */
   {
-    { "vsubps",                { XM, Vex, EXx }, 0 },
-    { "vsubss",                { XMScalar, VexScalar, EXd }, 0 },
-    { "vsubpd",                { XM, Vex, EXx }, 0 },
-    { "vsubsd",                { XMScalar, VexScalar, EXq }, 0 },
+    { "%XEvsubpX",     { XM, Vex, EXx, EXxEVexR }, 0 },
+    { "%XEvsubs%XS",   { XMScalar, VexScalar, EXd, EXxEVexR }, 0 },
+    { "%XEvsubpX",     { XM, Vex, EXx, EXxEVexR }, 0 },
+    { "%XEvsubs%XD",   { XMScalar, VexScalar, EXq, EXxEVexR }, 0 },
   },
 
   /* PREFIX_VEX_0F5D */
   {
-    { "vminps",                { XM, Vex, EXx }, 0 },
-    { "vminss",                { XMScalar, VexScalar, EXd }, 0 },
-    { "vminpd",                { XM, Vex, EXx }, 0 },
-    { "vminsd",                { XMScalar, VexScalar, EXq }, 0 },
+    { "%XEvminpX",     { XM, Vex, EXx, EXxEVexS }, 0 },
+    { "%XEvmins%XS",   { XMScalar, VexScalar, EXd, EXxEVexS }, 0 },
+    { "%XEvminpX",     { XM, Vex, EXx, EXxEVexS }, 0 },
+    { "%XEvmins%XD",   { XMScalar, VexScalar, EXq, EXxEVexS }, 0 },
   },
 
   /* PREFIX_VEX_0F5E */
   {
-    { "vdivps",                { XM, Vex, EXx }, 0 },
-    { "vdivss",                { XMScalar, VexScalar, EXd }, 0 },
-    { "vdivpd",                { XM, Vex, EXx }, 0 },
-    { "vdivsd",                { XMScalar, VexScalar, EXq }, 0 },
+    { "%XEvdivpX",     { XM, Vex, EXx, EXxEVexR }, 0 },
+    { "%XEvdivs%XS",   { XMScalar, VexScalar, EXd, EXxEVexR }, 0 },
+    { "%XEvdivpX",     { XM, Vex, EXx, EXxEVexR }, 0 },
+    { "%XEvdivs%XD",   { XMScalar, VexScalar, EXq, EXxEVexR }, 0 },
   },
 
   /* PREFIX_VEX_0F5F */
   {
-    { "vmaxps",                { XM, Vex, EXx }, 0 },
-    { "vmaxss",                { XMScalar, VexScalar, EXd }, 0 },
-    { "vmaxpd",                { XM, Vex, EXx }, 0 },
-    { "vmaxsd",                { XMScalar, VexScalar, EXq }, 0 },
+    { "%XEvmaxpX",     { XM, Vex, EXx, EXxEVexS }, 0 },
+    { "%XEvmaxs%XS",   { XMScalar, VexScalar, EXd, EXxEVexS }, 0 },
+    { "%XEvmaxpX",     { XM, Vex, EXx, EXxEVexS }, 0 },
+    { "%XEvmaxs%XD",   { XMScalar, VexScalar, EXq, EXxEVexS }, 0 },
   },
 
   /* PREFIX_VEX_0F6F */
@@ -4142,11 +4132,27 @@ static const struct dis386 prefix_table[][4] = {
     { VEX_W_TABLE (VEX_W_0F384B_X86_64_P_3) },
   },
 
+  /* PREFIX_VEX_0F3850_W_0 */
+  {
+    { "vpdpbuud",      { XM, Vex, EXx }, 0 },
+    { "vpdpbsud",      { XM, Vex, EXx }, 0 },
+    { "%XVvpdpbusd",   { XM, Vex, EXx }, 0 },
+    { "vpdpbssd",      { XM, Vex, EXx }, 0 },
+  },
+
+  /* PREFIX_VEX_0F3851_W_0 */
+  {
+    { "vpdpbuuds",     { XM, Vex, EXx }, 0 },
+    { "vpdpbsuds",     { XM, Vex, EXx }, 0 },
+    { "%XVvpdpbusds",  { XM, Vex, EXx }, 0 },
+    { "vpdpbssds",     { XM, Vex, EXx }, 0 },
+  },
   /* PREFIX_VEX_0F385C_X86_64 */
   {
     { Bad_Opcode },
     { VEX_W_TABLE (VEX_W_0F385C_X86_64_P_1) },
     { Bad_Opcode },
+    { VEX_W_TABLE (VEX_W_0F385C_X86_64_P_3) },
   },
 
   /* PREFIX_VEX_0F385E_X86_64 */
@@ -4157,6 +4163,34 @@ static const struct dis386 prefix_table[][4] = {
     { VEX_W_TABLE (VEX_W_0F385E_X86_64_P_3) },
   },
 
+  /* PREFIX_VEX_0F386C_X86_64_W_0_M_1_L_0 */
+  {
+    { "tcmmrlfp16ps", { TMM, EXtmm, VexTmm }, 0 },
+    { Bad_Opcode },
+    { "tcmmimfp16ps", { TMM, EXtmm, VexTmm }, 0 },
+  },
+
+  /* PREFIX_VEX_0F3872 */
+  {
+    { Bad_Opcode },
+    { VEX_W_TABLE (VEX_W_0F3872_P_1) },
+  },
+
+  /* PREFIX_VEX_0F38B0_W_0 */
+  {
+    { "vcvtneoph2ps", { XM, Mx }, 0 },
+    { "vcvtneebf162ps", { XM, Mx }, 0 },
+    { "vcvtneeph2ps", { XM, Mx }, 0 },
+    { "vcvtneobf162ps", { XM, Mx }, 0 },
+  },
+
+  /* PREFIX_VEX_0F38B1_W_0 */
+  {
+    { Bad_Opcode },
+    { "vbcstnebf162ps", { XM, Mw }, 0 },
+    { "vbcstnesh2ps", { XM, Mw }, 0 },
+  },
   /* PREFIX_VEX_0F38F5_L_0 */
   {
     { "bzhiS",         { Gdq, Edq, VexGdq }, 0 },
@@ -4355,6 +4389,18 @@ static const struct dis386 x86_64_table[][2] = {
     { "sgdt", { M }, 0 },
   },
 
+  /* X86_64_0F01_REG_0_MOD_3_RM_6_P_1 */
+  {
+    { Bad_Opcode },
+    { "wrmsrlist",     { Skip_MODRM }, 0 },
+  },
+
+  /* X86_64_0F01_REG_0_MOD_3_RM_6_P_3 */
+  {
+    { Bad_Opcode },
+    { "rdmsrlist",     { Skip_MODRM }, 0 },
+  },
+
   /* X86_64_0F01_REG_1 */
   {
     { "sidt{Q|Q}", { M }, 0 },
@@ -4415,6 +4461,12 @@ static const struct dis386 x86_64_table[][2] = {
     { "stui",  { Skip_MODRM }, 0 },
   },
 
+  /* X86_64_0F01_REG_7_MOD_3_RM_5_PREFIX_1 */
+  {
+    { Bad_Opcode },
+    { "rmpquery", { Skip_MODRM }, 0 },
+  },
+
   /* X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_1 */
   {
     { Bad_Opcode },
@@ -4433,6 +4485,18 @@ static const struct dis386 x86_64_table[][2] = {
     { "psmash",        { Skip_MODRM }, 0 },
   },
 
+  /* X86_64_0F18_REG_6_MOD_0 */
+  {
+    { "nopQ",          { Ev }, 0 },
+    { PREFIX_TABLE (PREFIX_0F18_REG_6_MOD_0_X86_64) },
+  },
+
+  /* X86_64_0F18_REG_7_MOD_0 */
+  {
+    { "nopQ",          { Ev }, 0 },
+    { PREFIX_TABLE (PREFIX_0F18_REG_7_MOD_0_X86_64) },
+  },
+
   {
     /* X86_64_0F24 */
     { "movZ",          { Em, Td }, 0 },
@@ -4472,6 +4536,108 @@ static const struct dis386 x86_64_table[][2] = {
     { Bad_Opcode },
     { PREFIX_TABLE (PREFIX_VEX_0F385E_X86_64) },
   },
+
+  /* X86_64_VEX_0F386C */
+  {
+    { Bad_Opcode },
+    { VEX_W_TABLE (VEX_W_0F386C_X86_64) },
+  },
+
+  /* X86_64_VEX_0F38E0 */
+  {
+    { Bad_Opcode },
+    { "cmpoxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+  },
+
+  /* X86_64_VEX_0F38E1 */
+  {
+    { Bad_Opcode },
+    { "cmpnoxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+  },
+
+  /* X86_64_VEX_0F38E2 */
+  {
+    { Bad_Opcode },
+    { "cmpbxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+  },
+
+  /* X86_64_VEX_0F38E3 */
+  {
+    { Bad_Opcode },
+    { "cmpnbxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+  },
+
+  /* X86_64_VEX_0F38E4 */
+  {
+    { Bad_Opcode },
+    { "cmpzxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+  },
+
+  /* X86_64_VEX_0F38E5 */
+  {
+    { Bad_Opcode },
+    { "cmpnzxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+  },
+
+  /* X86_64_VEX_0F38E6 */
+  {
+    { Bad_Opcode },
+    { "cmpbexadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+  },
+
+  /* X86_64_VEX_0F38E7 */
+  {
+    { Bad_Opcode },
+    { "cmpnbexadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+  },
+
+  /* X86_64_VEX_0F38E8 */
+  {
+    { Bad_Opcode },
+    { "cmpsxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+  },
+
+  /* X86_64_VEX_0F38E9 */
+  {
+    { Bad_Opcode },
+    { "cmpnsxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+  },
+
+  /* X86_64_VEX_0F38EA */
+  {
+    { Bad_Opcode },
+    { "cmppxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+  },
+
+  /* X86_64_VEX_0F38EB */
+  {
+    { Bad_Opcode },
+    { "cmpnpxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+  },
+
+  /* X86_64_VEX_0F38EC */
+  {
+    { Bad_Opcode },
+    { "cmplxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+  },
+
+  /* X86_64_VEX_0F38ED */
+  {
+    { Bad_Opcode },
+    { "cmpnlxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+  },
+
+  /* X86_64_VEX_0F38EE */
+  {
+    { Bad_Opcode },
+    { "cmplexadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+  },
+
+  /* X86_64_VEX_0F38EF */
+  {
+    { Bad_Opcode },
+    { "cmpnlexadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+  },
 };
 
 static const struct dis386 three_byte_table[][256] = {
@@ -4762,7 +4928,7 @@ static const struct dis386 three_byte_table[][256] = {
     { MOD_TABLE (MOD_0F38F9) },
     { PREFIX_TABLE (PREFIX_0F38FA) },
     { PREFIX_TABLE (PREFIX_0F38FB) },
-    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_0F38FC) },
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
@@ -6352,14 +6518,14 @@ static const struct dis386 vex_table[][256] = {
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
-    { Bad_Opcode },
+    { X86_64_TABLE (X86_64_VEX_0F386C) },
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
     /* 70 */
     { Bad_Opcode },
     { Bad_Opcode },
-    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_VEX_0F3872) },
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
@@ -6429,12 +6595,12 @@ static const struct dis386 vex_table[][256] = {
     { "vfnmsub213p%XW", { XM, Vex, EXx }, PREFIX_DATA },
     { "vfnmsub213s%XW", { XMScalar, VexScalar, EXdq }, PREFIX_DATA },
     /* b0 */
+    { VEX_W_TABLE (VEX_W_0F38B0) },
+    { VEX_W_TABLE (VEX_W_0F38B1) },
     { Bad_Opcode },
     { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
+    { VEX_W_TABLE (VEX_W_0F38B4) },
+    { VEX_W_TABLE (VEX_W_0F38B5) },
     { "vfmaddsub231p%XW", { XM, Vex, EXx }, PREFIX_DATA },
     { "vfmsubadd231p%XW", { XM, Vex, EXx }, PREFIX_DATA },
     /* b8 */
@@ -6483,23 +6649,23 @@ static const struct dis386 vex_table[][256] = {
     { "vaesdec",       { XM, Vex, EXx }, PREFIX_DATA },
     { "vaesdeclast",   { XM, Vex, EXx }, PREFIX_DATA },
     /* e0 */
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
+    { X86_64_TABLE (X86_64_VEX_0F38E0) },
+    { X86_64_TABLE (X86_64_VEX_0F38E1) },
+    { X86_64_TABLE (X86_64_VEX_0F38E2) },
+    { X86_64_TABLE (X86_64_VEX_0F38E3) },
+    { X86_64_TABLE (X86_64_VEX_0F38E4) },
+    { X86_64_TABLE (X86_64_VEX_0F38E5) },
+    { X86_64_TABLE (X86_64_VEX_0F38E6) },
+    { X86_64_TABLE (X86_64_VEX_0F38E7) },
     /* e8 */
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
+    { X86_64_TABLE (X86_64_VEX_0F38E8) },
+    { X86_64_TABLE (X86_64_VEX_0F38E9) },
+    { X86_64_TABLE (X86_64_VEX_0F38EA) },
+    { X86_64_TABLE (X86_64_VEX_0F38EB) },
+    { X86_64_TABLE (X86_64_VEX_0F38EC) },
+    { X86_64_TABLE (X86_64_VEX_0F38ED) },
+    { X86_64_TABLE (X86_64_VEX_0F38EE) },
+    { X86_64_TABLE (X86_64_VEX_0F38EF) },
     /* f0 */
     { Bad_Opcode },
     { Bad_Opcode },
@@ -6817,32 +6983,32 @@ static const struct dis386 vex_table[][256] = {
 static const struct dis386 vex_len_table[][2] = {
   /* VEX_LEN_0F12_P_0_M_0 / VEX_LEN_0F12_P_2_M_0 */
   {
-    { "vmovlpX",       { XM, Vex, EXq }, 0 },
+    { "%XEvmovlpX",    { XM, Vex, EXq }, 0 },
   },
 
   /* VEX_LEN_0F12_P_0_M_1 */
   {
-    { "vmovhlps",      { XM, Vex, EXq }, 0 },
+    { "%XEvmovhlp%XS", { XM, Vex, EXq }, 0 },
   },
 
   /* VEX_LEN_0F13_M_0 */
   {
-    { "vmovlpX",       { EXq, XM }, PREFIX_OPCODE },
+    { "%XEvmovlpX",    { EXq, XM }, PREFIX_OPCODE },
   },
 
   /* VEX_LEN_0F16_P_0_M_0 / VEX_LEN_0F16_P_2_M_0 */
   {
-    { "vmovhpX",       { XM, Vex, EXq }, 0 },
+    { "%XEvmovhpX",    { XM, Vex, EXq }, 0 },
   },
 
   /* VEX_LEN_0F16_P_0_M_1 */
   {
-    { "vmovlhps",      { XM, Vex, EXq }, 0 },
+    { "%XEvmovlhp%XS", { XM, Vex, EXq }, 0 },
   },
 
   /* VEX_LEN_0F17_M_0 */
   {
-    { "vmovhpX",       { EXq, XM }, PREFIX_OPCODE },
+    { "%XEvmovhpX",    { EXq, XM }, PREFIX_OPCODE },
   },
 
   /* VEX_LEN_0F41 */
@@ -6894,7 +7060,7 @@ static const struct dis386 vex_len_table[][2] = {
 
   /* VEX_LEN_0F6E */
   {
-    { "vmovK",         { XMScalar, Edq }, PREFIX_DATA },
+    { "%XEvmovK",      { XMScalar, Edq }, PREFIX_DATA },
   },
 
   /* VEX_LEN_0F77 */
@@ -6905,12 +7071,12 @@ static const struct dis386 vex_len_table[][2] = {
 
   /* VEX_LEN_0F7E_P_1 */
   {
-    { "vmovq",         { XMScalar, EXq }, 0 },
+    { "%XEvmovq",      { XMScalar, EXq }, 0 },
   },
 
   /* VEX_LEN_0F7E_P_2 */
   {
-    { "vmovK",         { Edq, XMScalar }, 0 },
+    { "%XEvmovK",      { Edq, XMScalar }, 0 },
   },
 
   /* VEX_LEN_0F90 */
@@ -6955,17 +7121,17 @@ static const struct dis386 vex_len_table[][2] = {
 
   /* VEX_LEN_0FC4 */
   {
-    { "vpinsrw",       { XM, Vex, Edw, Ib }, PREFIX_DATA },
+    { "%XEvpinsrw",    { XM, Vex, Edw, Ib }, PREFIX_DATA },
   },
 
   /* VEX_LEN_0FC5 */
   {
-    { "vpextrw",       { Gd, XS, Ib }, PREFIX_DATA },
+    { "%XEvpextrw",    { Gd, XS, Ib }, PREFIX_DATA },
   },
 
   /* VEX_LEN_0FD6 */
   {
-    { "vmovq",         { EXqS, XMScalar }, PREFIX_DATA },
+    { "%XEvmovq",      { EXqS, XMScalar }, PREFIX_DATA },
   },
 
   /* VEX_LEN_0FF7 */
@@ -7047,6 +7213,11 @@ static const struct dis386 vex_len_table[][2] = {
     { "tdpbf16ps", { TMM, EXtmm, VexTmm }, 0 },
   },
 
+  /* VEX_LEN_0F385C_X86_64_P_3_W_0_M_0 */
+  {
+    { "tdpfp16ps", { TMM, EXtmm, VexTmm }, 0 },
+  },
+
   /* VEX_LEN_0F385E_X86_64_P_0_W_0_M_0 */
   {
     { "tdpbuud", {TMM, EXtmm, VexTmm }, 0 },
@@ -7067,6 +7238,11 @@ static const struct dis386 vex_len_table[][2] = {
     { "tdpbssd", {TMM, EXtmm, VexTmm }, 0 },
   },
 
+  /* VEX_LEN_0F386C_X86_64_W_0_M_1 */
+  {
+    { PREFIX_TABLE (PREFIX_VEX_0F386C_X86_64_W_0_M_1_L_0) },
+  },
+
   /* VEX_LEN_0F38DB */
   {
     { "vaesimc",       { XM, EXx }, PREFIX_DATA },
@@ -7117,22 +7293,22 @@ static const struct dis386 vex_len_table[][2] = {
 
   /* VEX_LEN_0F3A14 */
   {
-    { "vpextrb",       { Edb, XM, Ib }, PREFIX_DATA },
+    { "%XEvpextrb",    { Edb, XM, Ib }, PREFIX_DATA },
   },
 
   /* VEX_LEN_0F3A15 */
   {
-    { "vpextrw",       { Edw, XM, Ib }, PREFIX_DATA },
+    { "%XEvpextrw",    { Edw, XM, Ib }, PREFIX_DATA },
   },
 
   /* VEX_LEN_0F3A16  */
   {
-    { "vpextrK",       { Edq, XM, Ib }, PREFIX_DATA },
+    { "%XEvpextrK",    { Edq, XM, Ib }, PREFIX_DATA },
   },
 
   /* VEX_LEN_0F3A17 */
   {
-    { "vextractps",    { Ed, XM, Ib }, PREFIX_DATA },
+    { "%XEvextractps", { Ed, XM, Ib }, PREFIX_DATA },
   },
 
   /* VEX_LEN_0F3A18 */
@@ -7149,17 +7325,17 @@ static const struct dis386 vex_len_table[][2] = {
 
   /* VEX_LEN_0F3A20 */
   {
-    { "vpinsrb",       { XM, Vex, Edb, Ib }, PREFIX_DATA },
+    { "%XEvpinsrb",    { XM, Vex, Edb, Ib }, PREFIX_DATA },
   },
 
   /* VEX_LEN_0F3A21 */
   {
-    { "vinsertps",     { XM, Vex, EXd, Ib }, PREFIX_DATA },
+    { "%XEvinsertps",  { XM, Vex, EXd, Ib }, PREFIX_DATA },
   },
 
   /* VEX_LEN_0F3A22 */
   {
-    { "vpinsrK",       { XM, Vex, Edq, Ib }, PREFIX_DATA },
+    { "%XEvpinsrK",    { XM, Vex, Edq, Ib }, PREFIX_DATA },
   },
 
   /* VEX_LEN_0F3A30 */
@@ -7601,7 +7777,7 @@ static const struct dis386 vex_w_table[][2] = {
   },
   {
     /* VEX_W_0F380C  */
-    { "vpermilps",     { XM, Vex, EXx }, PREFIX_DATA },
+    { "%XEvpermilps",  { XM, Vex, EXx }, PREFIX_DATA },
   },
   {
     /* VEX_W_0F380D  */
@@ -7625,7 +7801,7 @@ static const struct dis386 vex_w_table[][2] = {
   },
   {
     /* VEX_W_0F3818 */
-    { "vbroadcastss",  { XM, EXd }, PREFIX_DATA },
+    { "%XEvbroadcastss",       { XM, EXd }, PREFIX_DATA },
   },
   {
     /* VEX_W_0F3819_L_1 */
@@ -7685,23 +7861,23 @@ static const struct dis386 vex_w_table[][2] = {
   },
   {
     /* VEX_W_0F3850 */
-    { "%XV vpdpbusd",  { XM, Vex, EXx }, 0 },
+    { PREFIX_TABLE (PREFIX_VEX_0F3850_W_0) },
   },
   {
     /* VEX_W_0F3851 */
-    { "%XV vpdpbusds", { XM, Vex, EXx }, 0 },
+    { PREFIX_TABLE (PREFIX_VEX_0F3851_W_0) },
   },
   {
     /* VEX_W_0F3852 */
-    { "%XV vpdpwssd",  { XM, Vex, EXx }, 0 },
+    { "%XVvpdpwssd",   { XM, Vex, EXx }, PREFIX_DATA },
   },
   {
     /* VEX_W_0F3853 */
-    { "%XV vpdpwssds", { XM, Vex, EXx }, 0 },
+    { "%XVvpdpwssds",  { XM, Vex, EXx }, PREFIX_DATA },
   },
   {
     /* VEX_W_0F3858 */
-    { "vpbroadcastd", { XM, EXd }, PREFIX_DATA },
+    { "%XEvpbroadcastd", { XM, EXd }, PREFIX_DATA },
   },
   {
     /* VEX_W_0F3859 */
@@ -7715,6 +7891,10 @@ static const struct dis386 vex_w_table[][2] = {
     /* VEX_W_0F385C_X86_64_P_1 */
     { MOD_TABLE (MOD_VEX_0F385C_X86_64_P_1_W_0) },
   },
+  {
+    /* VEX_W_0F385C_X86_64_P_3 */
+    { MOD_TABLE (MOD_VEX_0F385C_X86_64_P_3_W_0) },
+  },
   {
     /* VEX_W_0F385E_X86_64_P_0 */
     { MOD_TABLE (MOD_VEX_0F385E_X86_64_P_0_W_0) },
@@ -7731,27 +7911,53 @@ static const struct dis386 vex_w_table[][2] = {
     /* VEX_W_0F385E_X86_64_P_3 */
     { MOD_TABLE (MOD_VEX_0F385E_X86_64_P_3_W_0) },
   },
+  {
+    /* VEX_W_0F386C_X86_64 */
+    { MOD_TABLE (MOD_VEX_0F386C_X86_64_W_0) },
+  },
+  {
+    /* VEX_W_0F3872_P_1 */
+    { "%XVvcvtneps2bf16%XY", { XMM, EXx }, 0 },
+  },
   {
     /* VEX_W_0F3878 */
-    { "vpbroadcastb",  { XM, EXb }, PREFIX_DATA },
+    { "%XEvpbroadcastb",       { XM, EXb }, PREFIX_DATA },
   },
   {
     /* VEX_W_0F3879 */
-    { "vpbroadcastw",  { XM, EXw }, PREFIX_DATA },
+    { "%XEvpbroadcastw",       { XM, EXw }, PREFIX_DATA },
+  },
+  {
+    /* VEX_W_0F38B0 */
+    { PREFIX_TABLE (PREFIX_VEX_0F38B0_W_0) },
+  },
+  {
+    /* VEX_W_0F38B1 */
+    { PREFIX_TABLE (PREFIX_VEX_0F38B1_W_0) },
+  },
+  {
+    /* VEX_W_0F38B4 */
+    { Bad_Opcode },
+    { "%XVvpmadd52luq",        { XM, Vex, EXx }, PREFIX_DATA },
+  },
+  {
+    /* VEX_W_0F38B5 */
+    { Bad_Opcode },
+    { "%XVvpmadd52huq",        { XM, Vex, EXx }, PREFIX_DATA },
   },
   {
     /* VEX_W_0F38CF */
-    { "vgf2p8mulb", { XM, Vex, EXx }, PREFIX_DATA },
+    { "%XEvgf2p8mulb", { XM, Vex, EXx }, PREFIX_DATA },
   },
   {
     /* VEX_W_0F3A00_L_1 */
     { Bad_Opcode },
-    { "vpermq",                { XM, EXx, Ib }, PREFIX_DATA },
+    { "%XEvpermq",             { XM, EXx, Ib }, PREFIX_DATA },
   },
   {
     /* VEX_W_0F3A01_L_1 */
     { Bad_Opcode },
-    { "vpermpd",       { XM, EXx, Ib }, PREFIX_DATA },
+    { "%XEvpermpd",    { XM, EXx, Ib }, PREFIX_DATA },
   },
   {
     /* VEX_W_0F3A02 */
@@ -7759,7 +7965,7 @@ static const struct dis386 vex_w_table[][2] = {
   },
   {
     /* VEX_W_0F3A04 */
-    { "vpermilps",     { XM, EXx, Ib }, PREFIX_DATA },
+    { "%XEvpermilps",  { XM, EXx, Ib }, PREFIX_DATA },
   },
   {
     /* VEX_W_0F3A05 */
@@ -7779,7 +7985,7 @@ static const struct dis386 vex_w_table[][2] = {
   },
   {
     /* VEX_W_0F3A1D */
-    { "vcvtps2ph", { EXxmmq, XM, EXxEVexS, Ib }, PREFIX_DATA },
+    { "%XEvcvtps2ph", { EXxmmq, XM, EXxEVexS, Ib }, PREFIX_DATA },
   },
   {
     /* VEX_W_0F3A38_L_1 */
@@ -7808,12 +8014,12 @@ static const struct dis386 vex_w_table[][2] = {
   {
     /* VEX_W_0F3ACE */
     { Bad_Opcode },
-    { "vgf2p8affineqb", { XM, Vex, EXx, Ib }, PREFIX_DATA },
+    { "%XEvgf2p8affineqb", { XM, Vex, EXx, Ib }, PREFIX_DATA },
   },
   {
     /* VEX_W_0F3ACF */
     { Bad_Opcode },
-    { "vgf2p8affineinvqb",  { XM, Vex, EXx, Ib }, PREFIX_DATA },
+    { "%XEvgf2p8affineinvqb",  { XM, Vex, EXx, Ib }, PREFIX_DATA },
   },
   /* VEX_W_0FXOP_08_85_L_0 */
   {
@@ -8059,6 +8265,16 @@ static const struct dis386 mod_table[][2] = {
     { "invlpg",                { Mb }, 0 },
     { RM_TABLE (RM_0F01_REG_7_MOD_3) },
   },
+  {
+    /* MOD_0F02 */
+    { "larS",          { Gv, Mw }, 0 },
+    { "larS",          { Gv, Ev }, 0 },
+  },
+  {
+    /* MOD_0F03 */
+    { "lslS",          { Gv, Mw }, 0 },
+    { "lslS",          { Gv, Ev }, 0 },
+  },
   {
     /* MOD_0F12_PREFIX_0 */
     { "movlpX",                { XM, EXq }, 0 },
@@ -8105,6 +8321,16 @@ static const struct dis386 mod_table[][2] = {
     { "prefetcht2",    { Mb }, 0 },
     { "nopQ",          { Ev }, 0 },
   },
+  {
+    /* MOD_0F18_REG_6 */
+    { X86_64_TABLE (X86_64_0F18_REG_6_MOD_0) },
+    { "nopQ",          { Ev }, 0 },
+  },
+  {
+    /* MOD_0F18_REG_7 */
+    { X86_64_TABLE (X86_64_0F18_REG_7_MOD_0) },
+    { "nopQ",          { Ev }, 0 },
+  },
   {
     /* MOD_0F1A_PREFIX_0 */
     { "bndldx",                { Gbnd, Mv_bnd }, 0 },
@@ -8345,7 +8571,7 @@ static const struct dis386 mod_table[][2] = {
   },
   {
     /* MOD_VEX_0F2B */
-    { "vmovntpX",      { Mx, XM }, PREFIX_OPCODE },
+    { "%XEvmovntpX",   { Mx, XM }, PREFIX_OPCODE },
   },
   {
     /* MOD_VEX_0F41_L_1 */
@@ -8511,6 +8737,11 @@ static const struct dis386 mod_table[][2] = {
     { Bad_Opcode },
     { VEX_LEN_TABLE (VEX_LEN_0F385C_X86_64_P_1_W_0_M_0) },
   },
+  {
+    /* MOD_VEX_0F385C_X86_64_P_3_W_0 */
+    { Bad_Opcode },
+    { VEX_LEN_TABLE (VEX_LEN_0F385C_X86_64_P_3_W_0_M_0) },
+  },
   {
     /* MOD_VEX_0F385E_X86_64_P_0_W_0 */
     { Bad_Opcode },
@@ -8531,6 +8762,11 @@ static const struct dis386 mod_table[][2] = {
     { Bad_Opcode },
     { VEX_LEN_TABLE (VEX_LEN_0F385E_X86_64_P_3_W_0_M_0) },
   },
+  {
+    /* MOD_VEX_0F386C_X86_64_W_0 */
+    { Bad_Opcode },
+    { VEX_LEN_TABLE (VEX_LEN_0F386C_X86_64_W_0_M_1) },
+  },
   {
     /* MOD_VEX_0F388C */
     { "vpmaskmov%DQ",  { XM, Vex, Mx }, PREFIX_DATA },
@@ -8585,6 +8821,7 @@ static const struct dis386 rm_table[][8] = {
     { "vmresume",      { Skip_MODRM }, 0 },
     { "vmxoff",                { Skip_MODRM }, 0 },
     { "pconfig",       { Skip_MODRM }, 0 },
+    { PREFIX_TABLE (PREFIX_0F01_REG_0_MOD_3_RM_6) },
   },
   {
     /* RM_0F01_REG_1 */
@@ -8637,7 +8874,7 @@ static const struct dis386 rm_table[][8] = {
     { PREFIX_TABLE (PREFIX_0F01_REG_7_MOD_3_RM_2) },
     { "mwaitx",                { { OP_Mwait, eBX_reg } }, PREFIX_OPCODE },
     { "clzero",                { Skip_MODRM }, 0  },
-    { "rdpru",         { Skip_MODRM }, 0  },
+    { PREFIX_TABLE (PREFIX_0F01_REG_7_MOD_3_RM_5) },
     { PREFIX_TABLE (PREFIX_0F01_REG_7_MOD_3_RM_6) },
     { PREFIX_TABLE (PREFIX_0F01_REG_7_MOD_3_RM_7) },
   },
@@ -8672,40 +8909,30 @@ static const struct dis386 rm_table[][8] = {
 
 #define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
 
-/* We use the high bit to indicate different name for the same
-   prefix.  */
-#define REP_PREFIX     (0xf3 | 0x100)
-#define XACQUIRE_PREFIX        (0xf2 | 0x200)
-#define XRELEASE_PREFIX        (0xf3 | 0x400)
-#define BND_PREFIX     (0xf2 | 0x400)
-#define NOTRACK_PREFIX (0x3e | 0x100)
-
-static int
+/* The values used here must be non-zero, fit in 'unsigned char', and not be
+   in conflict with actual prefix opcodes.  */
+#define REP_PREFIX     0x01
+#define XACQUIRE_PREFIX        0x02
+#define XRELEASE_PREFIX        0x03
+#define BND_PREFIX     0x04
+#define NOTRACK_PREFIX 0x05
+
+static enum {
+  ckp_okay,
+  ckp_bogus,
+  ckp_fetch_error,
+}
 ckprefix (instr_info *ins)
 {
   int newrex, i, length;
-  ins->rex = 0;
-  ins->prefixes = 0;
-  ins->used_prefixes = 0;
-  ins->rex_used = 0;
-  ins->evex_used = 0;
-  ins->last_lock_prefix = -1;
-  ins->last_repz_prefix = -1;
-  ins->last_repnz_prefix = -1;
-  ins->last_data_prefix = -1;
-  ins->last_addr_prefix = -1;
-  ins->last_rex_prefix = -1;
-  ins->last_seg_prefix = -1;
-  ins->fwait_prefix = -1;
-  ins->active_seg_prefix = 0;
-  for (i = 0; i < (int) ARRAY_SIZE (ins->all_prefixes); i++)
-    ins->all_prefixes[i] = 0;
+
   i = 0;
   length = 0;
   /* The maximum instruction length is 15bytes.  */
   while (length < MAX_CODE_LENGTH - 1)
     {
-      FETCH_DATA (ins->info, ins->codep + 1);
+      if (!fetch_code (ins->info, ins->codep + 1))
+       return ckp_fetch_error;
       newrex = 0;
       switch (*ins->codep)
        {
@@ -8729,7 +8956,7 @@ ckprefix (instr_info *ins)
          if (ins->address_mode == mode_64bit)
            newrex = *ins->codep;
          else
-           return 1;
+           return ckp_okay;
          ins->last_rex_prefix = i;
          break;
        case 0xf3:
@@ -8797,34 +9024,30 @@ ckprefix (instr_info *ins)
              ins->codep++;
              /* This ensures that the previous REX prefixes are noticed
                 as unused prefixes, as in the return case below.  */
-             ins->rex_used = ins->rex;
-             return 1;
+             return ins->rex ? ckp_bogus : ckp_okay;
            }
          ins->prefixes = PREFIX_FWAIT;
          break;
        default:
-         return 1;
+         return ckp_okay;
        }
       /* Rex is ignored when followed by another prefix.  */
       if (ins->rex)
-       {
-         ins->rex_used = ins->rex;
-         return 1;
-       }
+       return ckp_bogus;
       if (*ins->codep != FWAIT_OPCODE)
        ins->all_prefixes[i++] = *ins->codep;
       ins->rex = newrex;
       ins->codep++;
       length++;
     }
-  return 0;
+  return ckp_bogus;
 }
 
 /* Return the name of the prefix byte PREF, or NULL if PREF is not a
    prefix byte.  */
 
 static const char *
-prefix_name (instr_info *ins, int pref, int sizeflag)
+prefix_name (const instr_info *ins, int pref, int sizeflag)
 {
   static const char *rexes [16] =
     {
@@ -8908,39 +9131,6 @@ prefix_name (instr_info *ins, int pref, int sizeflag)
     }
 }
 
-/* Here for backwards compatibility.  When gdb stops using
-   print_insn_i386_att and print_insn_i386_intel these functions can
-   disappear, and print_insn_i386 be merged into print_insn.  */
-int
-print_insn_i386_att (bfd_vma pc, disassemble_info *info)
-{
-  instr_info ins;
-  ins.info = info;
-  ins.intel_syntax = 0;
-
-  return print_insn (pc, &ins);
-}
-
-int
-print_insn_i386_intel (bfd_vma pc, disassemble_info *info)
-{
-  instr_info ins;
-  ins.info = info;
-  ins.intel_syntax = 1;
-
-  return print_insn (pc, &ins);
-}
-
-int
-print_insn_i386 (bfd_vma pc, disassemble_info *info)
-{
-  instr_info ins;
-  ins.info = info;
-  ins.intel_syntax = -1;
-
-  return print_insn (pc, &ins);
-}
-
 void
 print_i386_disassembler_options (FILE *stream)
 {
@@ -8970,6 +9160,9 @@ with the -M switch (multiple options should be separated by commas):\n"));
 /* Bad opcode.  */
 static const struct dis386 bad_opcode = { "(bad)", { XX }, 0 };
 
+/* Fetch error indicator.  */
+static const struct dis386 err_opcode = { NULL, { XX }, 0 };
+
 /* Get a pointer to struct dis386 with a valid name.  */
 
 static const struct dis386 *
@@ -9071,13 +9264,13 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins)
       break;
 
     case USE_3BYTE_TABLE:
-      FETCH_DATA (ins->info, ins->codep + 2);
+      if (!fetch_code (ins->info, ins->codep + 2))
+       return &err_opcode;
       vindex = *ins->codep++;
       dp = &three_byte_table[dp->op[1].bytemode][vindex];
       ins->end_codep = ins->codep;
-      ins->modrm.mod = (*ins->codep >> 6) & 3;
-      ins->modrm.reg = (*ins->codep >> 3) & 7;
-      ins->modrm.rm = *ins->codep & 7;
+      if (!fetch_modrm (ins))
+       return &err_opcode;
       break;
 
     case USE_VEX_LEN_TABLE:
@@ -9131,7 +9324,8 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins)
       break;
 
     case USE_XOP_8F_TABLE:
-      FETCH_DATA (ins->info, ins->codep + 3);
+      if (!fetch_code (ins->info, ins->codep + 3))
+       return &err_opcode;
       ins->rex = ~(*ins->codep >> 5) & 0x7;
 
       /* VEX_TABLE_INDEX is the mmmmm part of the XOP byte 1 "RCB.mmmmm".  */
@@ -9177,16 +9371,14 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins)
          ins->vex.prefix = REPNE_PREFIX_OPCODE;
          break;
        }
-      ins->need_vex = 1;
+      ins->need_vex = true;
       ins->codep++;
       vindex = *ins->codep++;
       dp = &xop_table[vex_table_index][vindex];
 
       ins->end_codep = ins->codep;
-      FETCH_DATA (ins->info, ins->codep + 1);
-      ins->modrm.mod = (*ins->codep >> 6) & 3;
-      ins->modrm.reg = (*ins->codep >> 3) & 7;
-      ins->modrm.rm = *ins->codep & 7;
+      if (!fetch_modrm (ins))
+       return &err_opcode;
 
       /* No XOP encoding so far allows for a non-zero embedded prefix. Avoid
         having to decode the bits for every otherwise valid encoding.  */
@@ -9196,7 +9388,8 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins)
 
     case USE_VEX_C4_TABLE:
       /* VEX prefix.  */
-      FETCH_DATA (ins->info, ins->codep + 3);
+      if (!fetch_code (ins->info, ins->codep + 3))
+       return &err_opcode;
       ins->rex = ~(*ins->codep >> 5) & 0x7;
       switch ((*ins->codep & 0x1f))
        {
@@ -9243,24 +9436,21 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins)
          ins->vex.prefix = REPNE_PREFIX_OPCODE;
          break;
        }
-      ins->need_vex = 1;
+      ins->need_vex = true;
       ins->codep++;
       vindex = *ins->codep++;
       dp = &vex_table[vex_table_index][vindex];
       ins->end_codep = ins->codep;
       /* There is no MODRM byte for VEX0F 77.  */
-      if (vex_table_index != VEX_0F || vindex != 0x77)
-       {
-         FETCH_DATA (ins->info, ins->codep + 1);
-         ins->modrm.mod = (*ins->codep >> 6) & 3;
-         ins->modrm.reg = (*ins->codep >> 3) & 7;
-         ins->modrm.rm = *ins->codep & 7;
-       }
+      if ((vex_table_index != VEX_0F || vindex != 0x77)
+         && !fetch_modrm (ins))
+       return &err_opcode;
       break;
 
     case USE_VEX_C5_TABLE:
       /* VEX prefix.  */
-      FETCH_DATA (ins->info, ins->codep + 2);
+      if (!fetch_code (ins->info, ins->codep + 2))
+       return &err_opcode;
       ins->rex = (*ins->codep & 0x80) ? 0 : REX_R;
 
       /* For the 2-byte VEX prefix in 32-bit mode, the highest bit in
@@ -9281,33 +9471,29 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins)
          ins->vex.prefix = REPNE_PREFIX_OPCODE;
          break;
        }
-      ins->need_vex = 1;
+      ins->need_vex = true;
       ins->codep++;
       vindex = *ins->codep++;
       dp = &vex_table[dp->op[1].bytemode][vindex];
       ins->end_codep = ins->codep;
       /* There is no MODRM byte for VEX 77.  */
-      if (vindex != 0x77)
-       {
-         FETCH_DATA (ins->info, ins->codep + 1);
-         ins->modrm.mod = (*ins->codep >> 6) & 3;
-         ins->modrm.reg = (*ins->codep >> 3) & 7;
-         ins->modrm.rm = *ins->codep & 7;
-       }
+      if (vindex != 0x77 && !fetch_modrm (ins))
+       return &err_opcode;
       break;
 
     case USE_VEX_W_TABLE:
       if (!ins->need_vex)
        abort ();
 
-      dp = &vex_w_table[dp->op[1].bytemode][ins->vex.w ? 1 : 0];
+      dp = &vex_w_table[dp->op[1].bytemode][ins->vex.w];
       break;
 
     case USE_EVEX_TABLE:
-      ins->two_source_ops = 0;
+      ins->two_source_ops = false;
       /* EVEX prefix.  */
-      ins->vex.evex = 1;
-      FETCH_DATA (ins->info, ins->codep + 4);
+      ins->vex.evex = true;
+      if (!fetch_code (ins->info, ins->codep + 4))
+       return &err_opcode;
       /* The first byte after 0x62.  */
       ins->rex = ~(*ins->codep >> 5) & 0x7;
       ins->vex.r = *ins->codep & 0x10;
@@ -9364,7 +9550,7 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins)
 
       /* Remember the static rounding bits.  */
       ins->vex.ll = (*ins->codep >> 5) & 3;
-      ins->vex.b = (*ins->codep & 0x10) != 0;
+      ins->vex.b = *ins->codep & 0x10;
 
       ins->vex.v = *ins->codep & 0x8;
       ins->vex.mask_register_specifier = *ins->codep & 0x7;
@@ -9374,18 +9560,16 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins)
        {
          /* In 16/32-bit mode silently ignore following bits.  */
          ins->rex &= ~REX_B;
-         ins->vex.r = 1;
+         ins->vex.r = true;
        }
 
-      ins->need_vex = 1;
+      ins->need_vex = true;
       ins->codep++;
       vindex = *ins->codep++;
       dp = &evex_table[vex_table_index][vindex];
       ins->end_codep = ins->codep;
-      FETCH_DATA (ins->info, ins->codep + 1);
-      ins->modrm.mod = (*ins->codep >> 6) & 3;
-      ins->modrm.reg = (*ins->codep >> 3) & 7;
-      ins->modrm.rm = *ins->codep & 7;
+      if (!fetch_modrm (ins))
+       return &err_opcode;
 
       /* Set vector length.  */
       if (ins->modrm.mod == 3 && ins->vex.b)
@@ -9423,7 +9607,7 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins)
     return get_valid_dis386 (dp, ins);
 }
 
-static void
+static bool
 get_sib (instr_info *ins, int sizeflag)
 {
   /* If modrm.mod == 3, operand must be register.  */
@@ -9432,78 +9616,199 @@ get_sib (instr_info *ins, int sizeflag)
       && ins->modrm.mod != 3
       && ins->modrm.rm == 4)
     {
-      FETCH_DATA (ins->info, ins->codep + 2);
+      if (!fetch_code (ins->info, ins->codep + 2))
+       return false;
       ins->sib.index = (ins->codep[1] >> 3) & 7;
       ins->sib.scale = (ins->codep[1] >> 6) & 3;
       ins->sib.base = ins->codep[1] & 7;
+      ins->has_sib = true;
     }
+  else
+    ins->has_sib = false;
+
+  return true;
+}
+
+/* Like oappend (below), but S is a string starting with '%'.  In
+   Intel syntax, the '%' is elided.  */
+
+static void
+oappend_register (instr_info *ins, const char *s)
+{
+  oappend_with_style (ins, s + ins->intel_syntax, dis_style_register);
+}
+
+/* Wrap around a call to INS->info->fprintf_styled_func, printing FMT.
+   STYLE is the default style to use in the fprintf_styled_func calls,
+   however, FMT might include embedded style markers (see oappend_style),
+   these embedded markers are not printed, but instead change the style
+   used in the next fprintf_styled_func call.  */
+
+static void ATTRIBUTE_PRINTF_3
+i386_dis_printf (const instr_info *ins, enum disassembler_style style,
+                const char *fmt, ...)
+{
+  va_list ap;
+  enum disassembler_style curr_style = style;
+  const char *start, *curr;
+  char staging_area[40];
+
+  va_start (ap, fmt);
+  /* In particular print_insn()'s processing of op_txt[] can hand rather long
+     strings here.  Bypass vsnprintf() in such cases to avoid capacity issues
+     with the staging area.  */
+  if (strcmp (fmt, "%s"))
+    {
+      int res = vsnprintf (staging_area, sizeof (staging_area), fmt, ap);
+
+      va_end (ap);
+
+      if (res < 0)
+       return;
+
+      if ((size_t) res >= sizeof (staging_area))
+       abort ();
+
+      start = curr = staging_area;
+    }
+  else
+    {
+      start = curr = va_arg (ap, const char *);
+      va_end (ap);
+    }
+
+  do
+    {
+      if (*curr == '\0'
+         || (*curr == STYLE_MARKER_CHAR
+             && ISXDIGIT (*(curr + 1))
+             && *(curr + 2) == STYLE_MARKER_CHAR))
+       {
+         /* Output content between our START position and CURR.  */
+         int len = curr - start;
+         int n = (*ins->info->fprintf_styled_func) (ins->info->stream,
+                                                    curr_style,
+                                                    "%.*s", len, start);
+         if (n < 0)
+           break;
+
+         if (*curr == '\0')
+           break;
+
+         /* Skip over the initial STYLE_MARKER_CHAR.  */
+         ++curr;
+
+         /* Update the CURR_STYLE.  As there are less than 16 styles, it
+            is possible, that if the input is corrupted in some way, that
+            we might set CURR_STYLE to an invalid value.  Don't worry
+            though, we check for this situation.  */
+         if (*curr >= '0' && *curr <= '9')
+           curr_style = (enum disassembler_style) (*curr - '0');
+         else if (*curr >= 'a' && *curr <= 'f')
+           curr_style = (enum disassembler_style) (*curr - 'a' + 10);
+         else
+           curr_style = dis_style_text;
+
+         /* Check for an invalid style having been selected.  This should
+            never happen, but it doesn't hurt to be a little paranoid.  */
+         if (curr_style > dis_style_comment_start)
+           curr_style = dis_style_text;
+
+         /* Skip the hex character, and the closing STYLE_MARKER_CHAR.  */
+         curr += 2;
+
+         /* Reset the START to after the style marker.  */
+         start = curr;
+       }
+      else
+       ++curr;
+    }
+  while (true);
 }
 
 static int
-print_insn (bfd_vma pc, instr_info *ins)
+print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax)
 {
   const struct dis386 *dp;
   int i;
+  int ret;
   char *op_txt[MAX_OPERANDS];
   int needcomma;
+  bool intel_swap_2_3;
   int sizeflag, orig_sizeflag;
   const char *p;
   struct dis_private priv;
   int prefix_length;
+  int op_count;
+  instr_info ins = {
+    .info = info,
+    .intel_syntax = intel_syntax >= 0
+                   ? intel_syntax
+                   : (info->mach & bfd_mach_i386_intel_syntax) != 0,
+    .intel_mnemonic = !SYSV386_COMPAT,
+    .op_index[0 ... MAX_OPERANDS - 1] = -1,
+    .start_pc = pc,
+    .start_codep = priv.the_buffer,
+    .codep = priv.the_buffer,
+    .obufp = ins.obuf,
+    .last_lock_prefix = -1,
+    .last_repz_prefix = -1,
+    .last_repnz_prefix = -1,
+    .last_data_prefix = -1,
+    .last_addr_prefix = -1,
+    .last_rex_prefix = -1,
+    .last_seg_prefix = -1,
+    .fwait_prefix = -1,
+  };
+  char op_out[MAX_OPERANDS][MAX_OPERAND_BUFFER_SIZE];
 
-  ins->isa64 = 0;
-  ins->intel_mnemonic = !SYSV386_COMPAT;
-  ins->op_is_jump = false;
   priv.orig_sizeflag = AFLAG | DFLAG;
-  if ((ins->info->mach & bfd_mach_i386_i386) != 0)
-    ins->address_mode = mode_32bit;
-  else if (ins->info->mach == bfd_mach_i386_i8086)
+  if ((info->mach & bfd_mach_i386_i386) != 0)
+    ins.address_mode = mode_32bit;
+  else if (info->mach == bfd_mach_i386_i8086)
     {
-      ins->address_mode = mode_16bit;
+      ins.address_mode = mode_16bit;
       priv.orig_sizeflag = 0;
     }
   else
-    ins->address_mode = mode_64bit;
-
-  if (ins->intel_syntax == (char) -1)
-    ins->intel_syntax = (ins->info->mach & bfd_mach_i386_intel_syntax) != 0;
+    ins.address_mode = mode_64bit;
 
-  for (p = ins->info->disassembler_options; p != NULL;)
+  for (p = info->disassembler_options; p != NULL;)
     {
       if (startswith (p, "amd64"))
-       ins->isa64 = amd64;
+       ins.isa64 = amd64;
       else if (startswith (p, "intel64"))
-       ins->isa64 = intel64;
+       ins.isa64 = intel64;
       else if (startswith (p, "x86-64"))
        {
-         ins->address_mode = mode_64bit;
+         ins.address_mode = mode_64bit;
          priv.orig_sizeflag |= AFLAG | DFLAG;
        }
       else if (startswith (p, "i386"))
        {
-         ins->address_mode = mode_32bit;
+         ins.address_mode = mode_32bit;
          priv.orig_sizeflag |= AFLAG | DFLAG;
        }
       else if (startswith (p, "i8086"))
        {
-         ins->address_mode = mode_16bit;
+         ins.address_mode = mode_16bit;
          priv.orig_sizeflag &= ~(AFLAG | DFLAG);
        }
       else if (startswith (p, "intel"))
        {
-         ins->intel_syntax = 1;
+         ins.intel_syntax = 1;
          if (startswith (p + 5, "-mnemonic"))
-           ins->intel_mnemonic = 1;
+           ins.intel_mnemonic = true;
        }
       else if (startswith (p, "att"))
        {
-         ins->intel_syntax = 0;
+         ins.intel_syntax = 0;
          if (startswith (p + 3, "-mnemonic"))
-           ins->intel_mnemonic = 0;
+           ins.intel_mnemonic = false;
        }
       else if (startswith (p, "addr"))
        {
-         if (ins->address_mode == mode_64bit)
+         if (ins.address_mode == mode_64bit)
            {
              if (p[4] == '3' && p[5] == '2')
                priv.orig_sizeflag &= ~AFLAG;
@@ -9533,237 +9838,180 @@ print_insn (bfd_vma pc, instr_info *ins)
        p++;
     }
 
-  if (ins->address_mode == mode_64bit && sizeof (bfd_vma) < 8)
+  if (ins.address_mode == mode_64bit && sizeof (bfd_vma) < 8)
     {
-      (*ins->info->fprintf_func) (ins->info->stream,
-                            _("64-bit address is disabled"));
+      i386_dis_printf (&ins, dis_style_text, _("64-bit address is disabled"));
       return -1;
     }
 
-  if (ins->intel_syntax)
+  if (ins.intel_syntax)
     {
-      ins->names64 = intel_names64;
-      ins->names32 = intel_names32;
-      ins->names16 = intel_names16;
-      ins->names8 = intel_names8;
-      ins->names8rex = intel_names8rex;
-      ins->names_seg = intel_names_seg;
-      ins->names_mm = intel_names_mm;
-      ins->names_bnd = intel_names_bnd;
-      ins->names_xmm = intel_names_xmm;
-      ins->names_ymm = intel_names_ymm;
-      ins->names_zmm = intel_names_zmm;
-      ins->names_tmm = intel_names_tmm;
-      ins->index64 = intel_index64;
-      ins->index32 = intel_index32;
-      ins->names_mask = intel_names_mask;
-      ins->index16 = intel_index16;
-      ins->open_char = '[';
-      ins->close_char = ']';
-      ins->separator_char = '+';
-      ins->scale_char = '*';
+      ins.open_char = '[';
+      ins.close_char = ']';
+      ins.separator_char = '+';
+      ins.scale_char = '*';
     }
   else
     {
-      ins->names64 = att_names64;
-      ins->names32 = att_names32;
-      ins->names16 = att_names16;
-      ins->names8 = att_names8;
-      ins->names8rex = att_names8rex;
-      ins->names_seg = att_names_seg;
-      ins->names_mm = att_names_mm;
-      ins->names_bnd = att_names_bnd;
-      ins->names_xmm = att_names_xmm;
-      ins->names_ymm = att_names_ymm;
-      ins->names_zmm = att_names_zmm;
-      ins->names_tmm = att_names_tmm;
-      ins->index64 = att_index64;
-      ins->index32 = att_index32;
-      ins->names_mask = att_names_mask;
-      ins->index16 = att_index16;
-      ins->open_char = '(';
-      ins->close_char =  ')';
-      ins->separator_char = ',';
-      ins->scale_char = ',';
+      ins.open_char = '(';
+      ins.close_char =  ')';
+      ins.separator_char = ',';
+      ins.scale_char = ',';
     }
 
   /* The output looks better if we put 7 bytes on a line, since that
-     puts most long word instructions on a single line.  Use 8 bytes
-     for Intel L1OM.  */
-  if ((ins->info->mach & bfd_mach_l1om) != 0)
-    ins->info->bytes_per_line = 8;
-  else
-    ins->info->bytes_per_line = 7;
+     puts most long word instructions on a single line.  */
+  info->bytes_per_line = 7;
 
-  ins->info->private_data = &priv;
+  info->private_data = &priv;
   priv.max_fetched = priv.the_buffer;
   priv.insn_start = pc;
 
-  ins->obuf[0] = 0;
   for (i = 0; i < MAX_OPERANDS; ++i)
     {
-      ins->op_out[i][0] = 0;
-      ins->op_index[i] = -1;
+      op_out[i][0] = 0;
+      ins.op_out[i] = op_out[i];
     }
 
-  ins->start_pc = pc;
-  ins->start_codep = priv.the_buffer;
-  ins->codep = priv.the_buffer;
+  sizeflag = priv.orig_sizeflag;
 
-  if (OPCODES_SIGSETJMP (priv.bailout) != 0)
+  switch (ckprefix (&ins))
     {
-      const char *name;
-
-      /* Getting here means we tried for data but didn't get it.  That
-        means we have an incomplete instruction of some sort.  Just
-        print the first byte as a prefix or a .byte pseudo-op.  */
-      if (ins->codep > priv.the_buffer)
-       {
-         name = prefix_name (ins, priv.the_buffer[0], priv.orig_sizeflag);
-         if (name != NULL)
-           (*ins->info->fprintf_func) (ins->info->stream, "%s", name);
-         else
-           {
-             /* Just print the first byte as a .byte instruction.  */
-             (*ins->info->fprintf_func) (ins->info->stream, ".byte 0x%x",
-                                    (unsigned int) priv.the_buffer[0]);
-           }
-
-         return 1;
-       }
+    case ckp_okay:
+      break;
 
-      return -1;
+    case ckp_bogus:
+      /* Too many prefixes or unused REX prefixes.  */
+      for (i = 0;
+          i < (int) ARRAY_SIZE (ins.all_prefixes) && ins.all_prefixes[i];
+          i++)
+       i386_dis_printf (&ins, dis_style_mnemonic, "%s%s",
+                        (i == 0 ? "" : " "),
+                        prefix_name (&ins, ins.all_prefixes[i], sizeflag));
+      ret = i;
+      goto out;
+
+    case ckp_fetch_error:
+      goto fetch_error_out;
     }
 
-  ins->obufp = ins->obuf;
-  sizeflag = priv.orig_sizeflag;
+  ins.insn_codep = ins.codep;
 
-  if (!ckprefix (ins) || ins->rex_used)
+  if (!fetch_code (info, ins.codep + 1))
     {
-      /* Too many ins->prefixes or unused REX ins->prefixes.  */
-      for (i = 0;
-          i < (int) ARRAY_SIZE (ins->all_prefixes) && ins->all_prefixes[i];
-          i++)
-       (*ins->info->fprintf_func) (ins->info->stream, "%s%s",
-                              i == 0 ? "" : " ",
-                              prefix_name (ins, ins->all_prefixes[i],
-                                           sizeflag));
-      return i;
+    fetch_error_out:
+      ret = fetch_error (&ins);
+      goto out;
     }
 
-  ins->insn_codep = ins->codep;
+  ins.two_source_ops = (*ins.codep == 0x62) || (*ins.codep == 0xc8);
 
-  FETCH_DATA (ins->info, ins->codep + 1);
-  ins->two_source_ops = (*ins->codep == 0x62) || (*ins->codep == 0xc8);
-
-  if (((ins->prefixes & PREFIX_FWAIT)
-       && ((*ins->codep < 0xd8) || (*ins->codep > 0xdf))))
+  if (((ins.prefixes & PREFIX_FWAIT)
+       && ((*ins.codep < 0xd8) || (*ins.codep > 0xdf))))
     {
-      /* Handle ins->prefixes before fwait.  */
-      for (i = 0; i < ins->fwait_prefix && ins->all_prefixes[i];
+      /* Handle ins.prefixes before fwait.  */
+      for (i = 0; i < ins.fwait_prefix && ins.all_prefixes[i];
           i++)
-       (*ins->info->fprintf_func) (ins->info->stream, "%s ",
-                                   prefix_name (ins, ins->all_prefixes[i],
-                                                sizeflag));
-      (*ins->info->fprintf_func) (ins->info->stream, "fwait");
-      return i + 1;
+       i386_dis_printf (&ins, dis_style_mnemonic, "%s ",
+                        prefix_name (&ins, ins.all_prefixes[i], sizeflag));
+      i386_dis_printf (&ins, dis_style_mnemonic, "fwait");
+      ret = i + 1;
+      goto out;
     }
 
-  if (*ins->codep == 0x0f)
+  if (*ins.codep == 0x0f)
     {
       unsigned char threebyte;
 
-      ins->codep++;
-      FETCH_DATA (ins->info, ins->codep + 1);
-      threebyte = *ins->codep;
+      ins.codep++;
+      if (!fetch_code (info, ins.codep + 1))
+       goto fetch_error_out;
+      threebyte = *ins.codep;
       dp = &dis386_twobyte[threebyte];
-      ins->need_modrm = twobyte_has_modrm[threebyte];
-      ins->codep++;
+      ins.need_modrm = twobyte_has_modrm[threebyte];
+      ins.codep++;
     }
   else
     {
-      dp = &dis386[*ins->codep];
-      ins->need_modrm = onebyte_has_modrm[*ins->codep];
-      ins->codep++;
+      dp = &dis386[*ins.codep];
+      ins.need_modrm = onebyte_has_modrm[*ins.codep];
+      ins.codep++;
     }
 
-  /* Save sizeflag for printing the extra ins->prefixes later before updating
+  /* Save sizeflag for printing the extra ins.prefixes later before updating
      it for mnemonic and operand processing.  The prefix names depend
      only on the address mode.  */
   orig_sizeflag = sizeflag;
-  if (ins->prefixes & PREFIX_ADDR)
+  if (ins.prefixes & PREFIX_ADDR)
     sizeflag ^= AFLAG;
-  if ((ins->prefixes & PREFIX_DATA))
+  if ((ins.prefixes & PREFIX_DATA))
     sizeflag ^= DFLAG;
 
-  ins->end_codep = ins->codep;
-  if (ins->need_modrm)
-    {
-      FETCH_DATA (ins->info, ins->codep + 1);
-      ins->modrm.mod = (*ins->codep >> 6) & 3;
-      ins->modrm.reg = (*ins->codep >> 3) & 7;
-      ins->modrm.rm = *ins->codep & 7;
-    }
-  else
-    memset (&ins->modrm, 0, sizeof (ins->modrm));
-
-  ins->need_vex = 0;
-  memset (&ins->vex, 0, sizeof (ins->vex));
+  ins.end_codep = ins.codep;
+  if (ins.need_modrm && !fetch_modrm (&ins))
+    goto fetch_error_out;
 
   if (dp->name == NULL && dp->op[0].bytemode == FLOATCODE)
     {
-      get_sib (ins, sizeflag);
-      dofloat (ins, sizeflag);
+      if (!get_sib (&ins, sizeflag)
+         || !dofloat (&ins, sizeflag))
+       goto fetch_error_out;
     }
   else
     {
-      dp = get_valid_dis386 (dp, ins);
-      if (dp != NULL && putop (ins, dp->name, sizeflag) == 0)
+      dp = get_valid_dis386 (dp, &ins);
+      if (dp == &err_opcode)
+       goto fetch_error_out;
+      if (dp != NULL && putop (&ins, dp->name, sizeflag) == 0)
        {
-         get_sib (ins, sizeflag);
+         if (!get_sib (&ins, sizeflag))
+           goto fetch_error_out;
          for (i = 0; i < MAX_OPERANDS; ++i)
            {
-             ins->obufp = ins->op_out[i];
-             ins->op_ad = MAX_OPERANDS - 1 - i;
-             if (dp->op[i].rtn)
-               (*dp->op[i].rtn) (ins, dp->op[i].bytemode, sizeflag);
+             ins.obufp = ins.op_out[i];
+             ins.op_ad = MAX_OPERANDS - 1 - i;
+             if (dp->op[i].rtn
+                 && !dp->op[i].rtn (&ins, dp->op[i].bytemode, sizeflag))
+               goto fetch_error_out;
              /* For EVEX instruction after the last operand masking
                 should be printed.  */
-             if (i == 0 && ins->vex.evex)
+             if (i == 0 && ins.vex.evex)
                {
                  /* Don't print {%k0}.  */
-                 if (ins->vex.mask_register_specifier)
+                 if (ins.vex.mask_register_specifier)
                    {
-                     oappend (ins, "{");
-                     oappend (ins,
-                            ins->names_mask[ins->vex.mask_register_specifier]);
-                     oappend (ins, "}");
+                     const char *reg_name
+                       = att_names_mask[ins.vex.mask_register_specifier];
+
+                     oappend (&ins, "{");
+                     oappend_register (&ins, reg_name);
+                     oappend (&ins, "}");
                    }
-                 if (ins->vex.zeroing)
-                   oappend (ins, "{z}");
+                 if (ins.vex.zeroing)
+                   oappend (&ins, "{z}");
 
                  /* S/G insns require a mask and don't allow
                     zeroing-masking.  */
                  if ((dp->op[0].bytemode == vex_vsib_d_w_dq_mode
                       || dp->op[0].bytemode == vex_vsib_q_w_dq_mode)
-                     && (ins->vex.mask_register_specifier == 0
-                         || ins->vex.zeroing))
-                   oappend (ins, "/(bad)");
+                     && (ins.vex.mask_register_specifier == 0
+                         || ins.vex.zeroing))
+                   oappend (&ins, "/(bad)");
                }
            }
 
          /* Check whether rounding control was enabled for an insn not
             supporting it.  */
-         if (ins->modrm.mod == 3 && ins->vex.b
-             && !(ins->evex_used & EVEX_b_used))
+         if (ins.modrm.mod == 3 && ins.vex.b
+             && !(ins.evex_used & EVEX_b_used))
            {
              for (i = 0; i < MAX_OPERANDS; ++i)
                {
-                 ins->obufp = ins->op_out[i];
-                 if (*ins->obufp)
+                 ins.obufp = ins.op_out[i];
+                 if (*ins.obufp)
                    continue;
-                 oappend (ins, names_rounding[ins->vex.ll]);
-                 oappend (ins, "bad}");
+                 oappend (&ins, names_rounding[ins.vex.ll]);
+                 oappend (&ins, "bad}");
                  break;
                }
            }
@@ -9771,15 +10019,15 @@ print_insn (bfd_vma pc, instr_info *ins)
     }
 
   /* Clear instruction information.  */
-  ins->info->insn_info_valid = 0;
-  ins->info->branch_delay_insns = 0;
-  ins->info->data_size = 0;
-  ins->info->insn_type = dis_noninsn;
-  ins->info->target = 0;
-  ins->info->target2 = 0;
+  info->insn_info_valid = 0;
+  info->branch_delay_insns = 0;
+  info->data_size = 0;
+  info->insn_type = dis_noninsn;
+  info->target = 0;
+  info->target2 = 0;
 
   /* Reset jump operation indicator.  */
-  ins->op_is_jump = false;
+  ins.op_is_jump = false;
   {
     int jump_detection = 0;
 
@@ -9800,28 +10048,30 @@ print_insn (bfd_vma pc, instr_info *ins)
     /* Determine if this is a jump or branch.  */
     if ((jump_detection & 0x3) == 0x3)
       {
-       ins->op_is_jump = true;
+       ins.op_is_jump = true;
        if (jump_detection & 0x4)
-         ins->info->insn_type = dis_condbranch;
+         info->insn_type = dis_condbranch;
        else
-         ins->info->insn_type = (dp->name && !strncmp (dp->name, "call", 4))
+         info->insn_type = (dp->name && !strncmp (dp->name, "call", 4))
            ? dis_jsr : dis_branch;
       }
   }
 
   /* If VEX.vvvv and EVEX.vvvv are unused, they must be all 1s, which
      are all 0s in inverted form.  */
-  if (ins->need_vex && ins->vex.register_specifier != 0)
+  if (ins.need_vex && ins.vex.register_specifier != 0)
     {
-      (*ins->info->fprintf_func) (ins->info->stream, "(bad)");
-      return ins->end_codep - priv.the_buffer;
+      i386_dis_printf (&ins, dis_style_text, "(bad)");
+      ret = ins.end_codep - priv.the_buffer;
+      goto out;
     }
 
   /* If EVEX.z is set, there must be an actual mask register in use.  */
-  if (ins->vex.zeroing && ins->vex.mask_register_specifier == 0)
+  if (ins.vex.zeroing && ins.vex.mask_register_specifier == 0)
     {
-      (*ins->info->fprintf_func) (ins->info->stream, "(bad)");
-      return ins->end_codep - priv.the_buffer;
+      i386_dis_printf (&ins, dis_style_text, "(bad)");
+      ret = ins.end_codep - priv.the_buffer;
+      goto out;
     }
 
   switch (dp->prefix_requirement)
@@ -9829,12 +10079,13 @@ print_insn (bfd_vma pc, instr_info *ins)
     case PREFIX_DATA:
       /* If only the data prefix is marked as mandatory, its absence renders
         the encoding invalid.  Most other PREFIX_OPCODE rules still apply.  */
-      if (ins->need_vex ? !ins->vex.prefix : !(ins->prefixes & PREFIX_DATA))
+      if (ins.need_vex ? !ins.vex.prefix : !(ins.prefixes & PREFIX_DATA))
        {
-         (*ins->info->fprintf_func) (ins->info->stream, "(bad)");
-         return ins->end_codep - priv.the_buffer;
+         i386_dis_printf (&ins, dis_style_text, "(bad)");
+         ret = ins.end_codep - priv.the_buffer;
+         goto out;
        }
-      ins->used_prefixes |= PREFIX_DATA;
+      ins.used_prefixes |= PREFIX_DATA;
       /* Fall through.  */
     case PREFIX_OPCODE:
       /* If the mandatory PREFIX_REPZ/PREFIX_REPNZ/PREFIX_DATA prefix is
@@ -9842,155 +10093,214 @@ print_insn (bfd_vma pc, instr_info *ins)
         used by putop and MMX/SSE operand and may be overridden by the
         PREFIX_REPZ/PREFIX_REPNZ fix, we check the PREFIX_DATA prefix
         separately.  */
-      if (((ins->need_vex
-           ? ins->vex.prefix == REPE_PREFIX_OPCODE
-             || ins->vex.prefix == REPNE_PREFIX_OPCODE
-           : (ins->prefixes
+      if (((ins.need_vex
+           ? ins.vex.prefix == REPE_PREFIX_OPCODE
+             || ins.vex.prefix == REPNE_PREFIX_OPCODE
+           : (ins.prefixes
               & (PREFIX_REPZ | PREFIX_REPNZ)) != 0)
-          && (ins->used_prefixes
+          && (ins.used_prefixes
               & (PREFIX_REPZ | PREFIX_REPNZ)) == 0)
-         || (((ins->need_vex
-               ? ins->vex.prefix == DATA_PREFIX_OPCODE
-               : ((ins->prefixes
+         || (((ins.need_vex
+               ? ins.vex.prefix == DATA_PREFIX_OPCODE
+               : ((ins.prefixes
                    & (PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA))
                   == PREFIX_DATA))
-              && (ins->used_prefixes & PREFIX_DATA) == 0))
-         || (ins->vex.evex && dp->prefix_requirement != PREFIX_DATA
-             && !ins->vex.w != !(ins->used_prefixes & PREFIX_DATA)))
+              && (ins.used_prefixes & PREFIX_DATA) == 0))
+         || (ins.vex.evex && dp->prefix_requirement != PREFIX_DATA
+             && !ins.vex.w != !(ins.used_prefixes & PREFIX_DATA)))
        {
-         (*ins->info->fprintf_func) (ins->info->stream, "(bad)");
-         return ins->end_codep - priv.the_buffer;
+         i386_dis_printf (&ins, dis_style_text, "(bad)");
+         ret = ins.end_codep - priv.the_buffer;
+         goto out;
        }
       break;
 
     case PREFIX_IGNORED:
       /* Zap data size and rep prefixes from used_prefixes and reinstate their
         origins in all_prefixes.  */
-      ins->used_prefixes &= ~PREFIX_OPCODE;
-      if (ins->last_data_prefix >= 0)
-       ins->all_prefixes[ins->last_data_prefix] = 0x66;
-      if (ins->last_repz_prefix >= 0)
-       ins->all_prefixes[ins->last_repz_prefix] = 0xf3;
-      if (ins->last_repnz_prefix >= 0)
-       ins->all_prefixes[ins->last_repnz_prefix] = 0xf2;
+      ins.used_prefixes &= ~PREFIX_OPCODE;
+      if (ins.last_data_prefix >= 0)
+       ins.all_prefixes[ins.last_data_prefix] = 0x66;
+      if (ins.last_repz_prefix >= 0)
+       ins.all_prefixes[ins.last_repz_prefix] = 0xf3;
+      if (ins.last_repnz_prefix >= 0)
+       ins.all_prefixes[ins.last_repnz_prefix] = 0xf2;
       break;
     }
 
   /* Check if the REX prefix is used.  */
-  if ((ins->rex ^ ins->rex_used) == 0
-      && !ins->need_vex && ins->last_rex_prefix >= 0)
-    ins->all_prefixes[ins->last_rex_prefix] = 0;
+  if ((ins.rex ^ ins.rex_used) == 0
+      && !ins.need_vex && ins.last_rex_prefix >= 0)
+    ins.all_prefixes[ins.last_rex_prefix] = 0;
 
   /* Check if the SEG prefix is used.  */
-  if ((ins->prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS | PREFIX_ES
-                  | PREFIX_FS | PREFIX_GS)) != 0
-      && (ins->used_prefixes & ins->active_seg_prefix) != 0)
-    ins->all_prefixes[ins->last_seg_prefix] = 0;
+  if ((ins.prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS | PREFIX_ES
+                      | PREFIX_FS | PREFIX_GS)) != 0
+      && (ins.used_prefixes & ins.active_seg_prefix) != 0)
+    ins.all_prefixes[ins.last_seg_prefix] = 0;
 
   /* Check if the ADDR prefix is used.  */
-  if ((ins->prefixes & PREFIX_ADDR) != 0
-      && (ins->used_prefixes & PREFIX_ADDR) != 0)
-    ins->all_prefixes[ins->last_addr_prefix] = 0;
+  if ((ins.prefixes & PREFIX_ADDR) != 0
+      && (ins.used_prefixes & PREFIX_ADDR) != 0)
+    ins.all_prefixes[ins.last_addr_prefix] = 0;
 
   /* Check if the DATA prefix is used.  */
-  if ((ins->prefixes & PREFIX_DATA) != 0
-      && (ins->used_prefixes & PREFIX_DATA) != 0
-      && !ins->need_vex)
-    ins->all_prefixes[ins->last_data_prefix] = 0;
+  if ((ins.prefixes & PREFIX_DATA) != 0
+      && (ins.used_prefixes & PREFIX_DATA) != 0
+      && !ins.need_vex)
+    ins.all_prefixes[ins.last_data_prefix] = 0;
 
-  /* Print the extra ins->prefixes.  */
+  /* Print the extra ins.prefixes.  */
   prefix_length = 0;
-  for (i = 0; i < (int) ARRAY_SIZE (ins->all_prefixes); i++)
-    if (ins->all_prefixes[i])
+  for (i = 0; i < (int) ARRAY_SIZE (ins.all_prefixes); i++)
+    if (ins.all_prefixes[i])
       {
        const char *name;
-       name = prefix_name (ins, ins->all_prefixes[i], orig_sizeflag);
+       name = prefix_name (&ins, ins.all_prefixes[i], orig_sizeflag);
        if (name == NULL)
          abort ();
        prefix_length += strlen (name) + 1;
-       (*ins->info->fprintf_func) (ins->info->stream, "%s ", name);
+       i386_dis_printf (&ins, dis_style_mnemonic, "%s ", name);
       }
 
   /* Check maximum code length.  */
-  if ((ins->codep - ins->start_codep) > MAX_CODE_LENGTH)
+  if ((ins.codep - ins.start_codep) > MAX_CODE_LENGTH)
     {
-      (*ins->info->fprintf_func) (ins->info->stream, "(bad)");
-      return MAX_CODE_LENGTH;
+      i386_dis_printf (&ins, dis_style_text, "(bad)");
+      ret = MAX_CODE_LENGTH;
+      goto out;
     }
 
-  ins->obufp = ins->mnemonicendp;
-  for (i = strlen (ins->obuf) + prefix_length; i < 6; i++)
-    oappend (ins, " ");
-  oappend (ins, " ");
-  (*ins->info->fprintf_func) (ins->info->stream, "%s", ins->obuf);
+  /* Calculate the number of operands this instruction has.  */
+  op_count = 0;
+  for (i = 0; i < MAX_OPERANDS; ++i)
+    if (*ins.op_out[i] != '\0')
+      ++op_count;
+
+  /* Calculate the number of spaces to print after the mnemonic.  */
+  ins.obufp = ins.mnemonicendp;
+  if (op_count > 0)
+    {
+      i = strlen (ins.obuf) + prefix_length;
+      if (i < 7)
+       i = 7 - i;
+      else
+       i = 1;
+    }
+  else
+    i = 0;
+
+  /* Print the instruction mnemonic along with any trailing whitespace.  */
+  i386_dis_printf (&ins, dis_style_mnemonic, "%s%*s", ins.obuf, i, "");
 
   /* The enter and bound instructions are printed with operands in the same
      order as the intel book; everything else is printed in reverse order.  */
-  if (ins->intel_syntax || ins->two_source_ops)
+  intel_swap_2_3 = false;
+  if (ins.intel_syntax || ins.two_source_ops)
     {
-      bfd_vma riprel;
-
       for (i = 0; i < MAX_OPERANDS; ++i)
-       op_txt[i] = ins->op_out[i];
+       op_txt[i] = ins.op_out[i];
 
-      if (ins->intel_syntax && dp && dp->op[2].rtn == OP_Rounding
+      if (ins.intel_syntax && dp && dp->op[2].rtn == OP_Rounding
           && dp->op[3].rtn == OP_E && dp->op[4].rtn == NULL)
        {
-         op_txt[2] = ins->op_out[3];
-         op_txt[3] = ins->op_out[2];
+         op_txt[2] = ins.op_out[3];
+         op_txt[3] = ins.op_out[2];
+         intel_swap_2_3 = true;
        }
 
       for (i = 0; i < (MAX_OPERANDS >> 1); ++i)
        {
-         ins->op_ad = ins->op_index[i];
-         ins->op_index[i] = ins->op_index[MAX_OPERANDS - 1 - i];
-         ins->op_index[MAX_OPERANDS - 1 - i] = ins->op_ad;
-         riprel = ins->op_riprel[i];
-         ins->op_riprel[i] = ins->op_riprel[MAX_OPERANDS - 1 - i];
-         ins->op_riprel[MAX_OPERANDS - 1 - i] = riprel;
+         bool riprel;
+
+         ins.op_ad = ins.op_index[i];
+         ins.op_index[i] = ins.op_index[MAX_OPERANDS - 1 - i];
+         ins.op_index[MAX_OPERANDS - 1 - i] = ins.op_ad;
+         riprel = ins.op_riprel[i];
+         ins.op_riprel[i] = ins.op_riprel[MAX_OPERANDS - 1 - i];
+         ins.op_riprel[MAX_OPERANDS - 1 - i] = riprel;
        }
     }
   else
     {
       for (i = 0; i < MAX_OPERANDS; ++i)
-       op_txt[MAX_OPERANDS - 1 - i] = ins->op_out[i];
+       op_txt[MAX_OPERANDS - 1 - i] = ins.op_out[i];
     }
 
   needcomma = 0;
   for (i = 0; i < MAX_OPERANDS; ++i)
     if (*op_txt[i])
       {
+       /* In Intel syntax embedded rounding / SAE are not separate operands.
+          Instead they're attached to the prior register operand.  Simply
+          suppress emission of the comma to achieve that effect.  */
+       switch (i & -(ins.intel_syntax && dp))
+         {
+         case 2:
+           if (dp->op[2].rtn == OP_Rounding && !intel_swap_2_3)
+             needcomma = 0;
+           break;
+         case 3:
+           if (dp->op[3].rtn == OP_Rounding || intel_swap_2_3)
+             needcomma = 0;
+           break;
+         }
        if (needcomma)
-         (*ins->info->fprintf_func) (ins->info->stream, ",");
-       if (ins->op_index[i] != -1 && !ins->op_riprel[i])
+         i386_dis_printf (&ins, dis_style_text, ",");
+       if (ins.op_index[i] != -1 && !ins.op_riprel[i])
          {
-           bfd_vma target = (bfd_vma) ins->op_address[ins->op_index[i]];
+           bfd_vma target = (bfd_vma) ins.op_address[ins.op_index[i]];
 
-           if (ins->op_is_jump)
+           if (ins.op_is_jump)
              {
-               ins->info->insn_info_valid = 1;
-               ins->info->branch_delay_insns = 0;
-               ins->info->data_size = 0;
-               ins->info->target = target;
-               ins->info->target2 = 0;
+               info->insn_info_valid = 1;
+               info->branch_delay_insns = 0;
+               info->data_size = 0;
+               info->target = target;
+               info->target2 = 0;
              }
-           (*ins->info->print_address_func) (target, ins->info);
+           (*info->print_address_func) (target, info);
          }
        else
-         (*ins->info->fprintf_func) (ins->info->stream, "%s", op_txt[i]);
+         i386_dis_printf (&ins, dis_style_text, "%s", op_txt[i]);
        needcomma = 1;
       }
 
   for (i = 0; i < MAX_OPERANDS; i++)
-    if (ins->op_index[i] != -1 && ins->op_riprel[i])
+    if (ins.op_index[i] != -1 && ins.op_riprel[i])
       {
-       (*ins->info->fprintf_func) (ins->info->stream, "        # ");
-       (*ins->info->print_address_func) ((bfd_vma)
-                       (ins->start_pc + (ins->codep - ins->start_codep)
-                        + ins->op_address[ins->op_index[i]]), ins->info);
+       i386_dis_printf (&ins, dis_style_comment_start, "        # ");
+       (*info->print_address_func)
+         ((bfd_vma)(ins.start_pc + (ins.codep - ins.start_codep)
+                    + ins.op_address[ins.op_index[i]]),
+         info);
        break;
       }
-  return ins->codep - priv.the_buffer;
+  ret = ins.codep - priv.the_buffer;
+ out:
+  info->private_data = NULL;
+  return ret;
+}
+
+/* Here for backwards compatibility.  When gdb stops using
+   print_insn_i386_att and print_insn_i386_intel these functions can
+   disappear, and print_insn_i386 be merged into print_insn.  */
+int
+print_insn_i386_att (bfd_vma pc, disassemble_info *info)
+{
+  return print_insn (pc, info, 0);
+}
+
+int
+print_insn_i386_intel (bfd_vma pc, disassemble_info *info)
+{
+  return print_insn (pc, info, 1);
+}
+
+int
+print_insn_i386 (bfd_vma pc, disassemble_info *info)
+{
+  return print_insn (pc, info, -1);
 }
 
 static const char *float_mem[] = {
@@ -10247,7 +10557,7 @@ static const struct dis386 float_reg[][8] = {
   },
 };
 
-static char *fgrps[][8] = {
+static const char *const fgrps[][8] = {
   /* Bad opcode 0 */
   {
     "(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
@@ -10309,16 +10619,17 @@ swap_operand (instr_info *ins)
   ins->mnemonicendp += 2;
 }
 
-static void
+static bool
 OP_Skip_MODRM (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
               int sizeflag ATTRIBUTE_UNUSED)
 {
   /* Skip mod/rm byte.  */
   MODRM_CHECK;
   ins->codep++;
+  return true;
 }
 
-static void
+static bool
 dofloat (instr_info *ins, int sizeflag)
 {
   const struct dis386 *dp;
@@ -10333,8 +10644,7 @@ dofloat (instr_info *ins, int sizeflag)
       putop (ins, float_mem[fp_indx], sizeflag);
       ins->obufp = ins->op_out[0];
       ins->op_ad = 2;
-      OP_E (ins, float_mem_mode[fp_indx], sizeflag);
-      return;
+      return OP_E (ins, float_mem_mode[fp_indx], sizeflag);
     }
   /* Skip mod/rm byte.  */
   MODRM_CHECK;
@@ -10347,7 +10657,7 @@ dofloat (instr_info *ins, int sizeflag)
 
       /* Instruction fnstsw is only one with strange arg.  */
       if (floatop == 0xdf && ins->codep[-1] == 0xe0)
-       strcpy (ins->op_out[0], ins->names16[0]);
+       strcpy (ins->op_out[0], att_names16[0] + ins->intel_syntax);
     }
   else
     {
@@ -10355,37 +10665,38 @@ dofloat (instr_info *ins, int sizeflag)
 
       ins->obufp = ins->op_out[0];
       ins->op_ad = 2;
-      if (dp->op[0].rtn)
-       (*dp->op[0].rtn) (ins, dp->op[0].bytemode, sizeflag);
+      if (dp->op[0].rtn
+         && !dp->op[0].rtn (ins, dp->op[0].bytemode, sizeflag))
+       return false;
 
       ins->obufp = ins->op_out[1];
       ins->op_ad = 1;
-      if (dp->op[1].rtn)
-       (*dp->op[1].rtn) (ins, dp->op[1].bytemode, sizeflag);
+      if (dp->op[1].rtn
+         && !dp->op[1].rtn (ins, dp->op[1].bytemode, sizeflag))
+       return false;
     }
+  return true;
 }
 
-/* Like oappend (below), but S is a string starting with '%'.
-   In Intel syntax, the '%' is elided.  */
-static void
-oappend_maybe_intel (instr_info *ins, const char *s)
-{
-  oappend (ins, s + ins->intel_syntax);
-}
-
-static void
+static bool
 OP_ST (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
        int sizeflag ATTRIBUTE_UNUSED)
 {
-  oappend_maybe_intel (ins, "%st");
+  oappend_register (ins, "%st");
+  return true;
 }
 
-static void
+static bool
 OP_STi (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
        int sizeflag ATTRIBUTE_UNUSED)
 {
-  sprintf (ins->scratchbuf, "%%st(%d)", ins->modrm.rm);
-  oappend_maybe_intel (ins, ins->scratchbuf);
+  char scratch[8];
+  int res = snprintf (scratch, ARRAY_SIZE (scratch), "%%st(%d)", ins->modrm.rm);
+
+  if (res < 0 || (size_t) res >= ARRAY_SIZE (scratch))
+    abort ();
+  oappend_register (ins, scratch);
+  return true;
 }
 
 /* Capital letters in template are macros.  */
@@ -10486,7 +10797,7 @@ putop (instr_info *ins, const char *in_template, int sizeflag)
              switch (last[0])
              {
              case 'X':
-               if (ins->vex.w)
+               if (!ins->vex.evex || ins->vex.w)
                  *ins->obufp++ = 'd';
                else
                  oappend (ins, "{bad}");
@@ -10517,7 +10828,41 @@ putop (instr_info *ins, const char *in_template, int sizeflag)
          else
            *ins->obufp++ = 'w';
          break;
-       case 'E':               /* For jcxz/jecxz */
+       case 'E':
+         if (l == 1)
+           {
+             switch (last[0])
+               {
+               case 'X':
+                 if (!ins->vex.evex || ins->vex.b || ins->vex.ll >= 2
+                     || !ins->vex.r
+                     || (ins->modrm.mod == 3 && (ins->rex & REX_X))
+                     || !ins->vex.v || ins->vex.mask_register_specifier)
+                   break;
+                 /* AVX512 extends a number of V*D insns to also have V*Q variants,
+                    merely distinguished by EVEX.W.  Look for a use of the
+                    respective macro.  */
+                 if (ins->vex.w)
+                   {
+                     const char *pct = strchr (p + 1, '%');
+
+                     if (pct != NULL && pct[1] == 'D' && pct[2] == 'Q')
+                       break;
+                   }
+                 *ins->obufp++ = '{';
+                 *ins->obufp++ = 'e';
+                 *ins->obufp++ = 'v';
+                 *ins->obufp++ = 'e';
+                 *ins->obufp++ = 'x';
+                 *ins->obufp++ = '}';
+                 *ins->obufp++ = ' ';
+                 break;
+               default:
+                 abort ();
+               }
+               break;
+           }
+         /* For jcxz/jecxz */
          if (ins->address_mode == mode_64bit)
            {
              if (sizeflag & AFLAG)
@@ -10581,7 +10926,7 @@ putop (instr_info *ins, const char *in_template, int sizeflag)
            }
          else if (l == 1 && last[0] == 'X')
            {
-             if (ins->vex.w == 0)
+             if (!ins->vex.w)
                *ins->obufp++ = 'h';
              else
                oappend (ins, "{bad}");
@@ -10765,7 +11110,7 @@ putop (instr_info *ins, const char *in_template, int sizeflag)
 
              goto case_S;
            case 'X':
-             if (!ins->vex.w)
+             if (!ins->vex.evex || !ins->vex.w)
                *ins->obufp++ = 's';
              else
                oappend (ins, "{bad}");
@@ -10777,22 +11122,29 @@ putop (instr_info *ins, const char *in_template, int sizeflag)
        case 'V':
          if (l == 0)
            abort ();
-         else if (l == 1
-                  && (last[0] == 'L' || last[0] == 'X'))
+         else if (l == 1)
            {
-             if (last[0] == 'X')
+             switch (last[0])
                {
+               case 'X':
+                 if (ins->vex.evex)
+                   break;
                  *ins->obufp++ = '{';
                  *ins->obufp++ = 'v';
                  *ins->obufp++ = 'e';
                  *ins->obufp++ = 'x';
                  *ins->obufp++ = '}';
-               }
-             else if (ins->rex & REX_W)
-               {
+                 *ins->obufp++ = ' ';
+                 break;
+               case 'L':
+                 if (!(ins->rex & REX_W))
+                   break;
                  *ins->obufp++ = 'a';
                  *ins->obufp++ = 'b';
                  *ins->obufp++ = 's';
+                 break;
+               default:
+                 abort ();
                }
            }
          else
@@ -10932,12 +11284,73 @@ putop (instr_info *ins, const char *in_template, int sizeflag)
   return 0;
 }
 
+/* Add a style marker to *INS->obufp that encodes STYLE.  This assumes that
+   the buffer pointed to by INS->obufp has space.  A style marker is made
+   from the STYLE_MARKER_CHAR followed by STYLE converted to a single hex
+   digit, followed by another STYLE_MARKER_CHAR.  This function assumes
+   that the number of styles is not greater than 16.  */
+
 static void
-oappend (instr_info *ins, const char *s)
+oappend_insert_style (instr_info *ins, enum disassembler_style style)
+{
+  unsigned num = (unsigned) style;
+
+  /* We currently assume that STYLE can be encoded as a single hex
+     character.  If more styles are added then this might start to fail,
+     and we'll need to expand this code.  */
+  if (num > 0xf)
+    abort ();
+
+  *ins->obufp++ = STYLE_MARKER_CHAR;
+  *ins->obufp++ = (num < 10 ? ('0' + num)
+                  : ((num < 16) ? ('a' + (num - 10)) : '0'));
+  *ins->obufp++ = STYLE_MARKER_CHAR;
+
+  /* This final null character is not strictly necessary, after inserting a
+     style marker we should always be inserting some additional content.
+     However, having the buffer null terminated doesn't cost much, and make
+     it easier to debug what's going on.  Also, if we do ever forget to add
+     any additional content after this style marker, then the buffer will
+     still be well formed.  */
+  *ins->obufp = '\0';
+}
+
+static void
+oappend_with_style (instr_info *ins, const char *s,
+                   enum disassembler_style style)
 {
+  oappend_insert_style (ins, style);
   ins->obufp = stpcpy (ins->obufp, s);
 }
 
+/* Like oappend_with_style but always with text style.  */
+
+static void
+oappend (instr_info *ins, const char *s)
+{
+  oappend_with_style (ins, s, dis_style_text);
+}
+
+/* Add a single character C to the buffer pointer to by INS->obufp, marking
+   the style for the character as STYLE.  */
+
+static void
+oappend_char_with_style (instr_info *ins, const char c,
+                        enum disassembler_style style)
+{
+  oappend_insert_style (ins, style);
+  *ins->obufp++ = c;
+  *ins->obufp = '\0';
+}
+
+/* Like oappend_char_with_style, but always uses dis_style_text.  */
+
+static void
+oappend_char (instr_info *ins, const char c)
+{
+  oappend_char_with_style (ins, c, dis_style_text);
+}
+
 static void
 append_seg (instr_info *ins)
 {
@@ -10949,106 +11362,71 @@ append_seg (instr_info *ins)
   switch (ins->active_seg_prefix)
     {
     case PREFIX_CS:
-      oappend_maybe_intel (ins, "%cs:");
+      oappend_register (ins, att_names_seg[1]);
       break;
     case PREFIX_DS:
-      oappend_maybe_intel (ins, "%ds:");
+      oappend_register (ins, att_names_seg[3]);
       break;
     case PREFIX_SS:
-      oappend_maybe_intel (ins, "%ss:");
+      oappend_register (ins, att_names_seg[2]);
       break;
     case PREFIX_ES:
-      oappend_maybe_intel (ins, "%es:");
+      oappend_register (ins, att_names_seg[0]);
       break;
     case PREFIX_FS:
-      oappend_maybe_intel (ins, "%fs:");
+      oappend_register (ins, att_names_seg[4]);
       break;
     case PREFIX_GS:
-      oappend_maybe_intel (ins, "%gs:");
+      oappend_register (ins, att_names_seg[5]);
       break;
     default:
       break;
     }
+  oappend_char (ins, ':');
 }
 
-static void
+static bool
 OP_indirE (instr_info *ins, int bytemode, int sizeflag)
 {
   if (!ins->intel_syntax)
     oappend (ins, "*");
-  OP_E (ins, bytemode, sizeflag);
+  return OP_E (ins, bytemode, sizeflag);
 }
 
 static void
-print_operand_value (instr_info *ins, char *buf, int hex, bfd_vma disp)
+print_operand_value (instr_info *ins, bfd_vma disp,
+                    enum disassembler_style style)
 {
-  if (ins->address_mode == mode_64bit)
-    {
-      if (hex)
-       {
-         char tmp[30];
-         int i;
-         buf[0] = '0';
-         buf[1] = 'x';
-         sprintf_vma (tmp, disp);
-         for (i = 0; tmp[i] == '0' && tmp[i + 1]; i++);
-         strcpy (buf + 2, tmp + i);
-       }
-      else
-       {
-         bfd_signed_vma v = disp;
-         char tmp[30];
-         int i;
-         if (v < 0)
-           {
-             *(buf++) = '-';
-             v = -disp;
-             /* Check for possible overflow on 0x8000000000000000.  */
-             if (v < 0)
-               {
-                 strcpy (buf, "9223372036854775808");
-                 return;
-               }
-           }
-         if (!v)
-           {
-             strcpy (buf, "0");
-             return;
-           }
+  char tmp[30];
 
-         i = 0;
-         tmp[29] = 0;
-         while (v)
-           {
-             tmp[28 - i] = (v % 10) + '0';
-             v /= 10;
-             i++;
-           }
-         strcpy (buf, tmp + 29 - i);
-       }
-    }
+  if (ins->address_mode == mode_64bit)
+    sprintf (tmp, "0x%" PRIx64, (uint64_t) disp);
   else
-    {
-      if (hex)
-       sprintf (buf, "0x%x", (unsigned int) disp);
-      else
-       sprintf (buf, "%d", (int) disp);
-    }
+    sprintf (tmp, "0x%x", (unsigned int) disp);
+  oappend_with_style (ins, tmp, style);
+}
+
+/* Like oappend, but called for immediate operands.  */
+
+static void
+oappend_immediate (instr_info *ins, bfd_vma imm)
+{
+  if (!ins->intel_syntax)
+    oappend_char_with_style (ins, '$', dis_style_immediate);
+  print_operand_value (ins, imm, dis_style_immediate);
 }
 
 /* Put DISP in BUF as signed hex number.  */
 
 static void
-print_displacement (instr_info *ins, char *buf, bfd_vma disp)
+print_displacement (instr_info *ins, bfd_signed_vma val)
 {
-  bfd_signed_vma val = disp;
   char tmp[30];
-  int i, j = 0;
 
   if (val < 0)
     {
-      buf[j++] = '-';
-      val = -disp;
+      oappend_char_with_style (ins, '-', dis_style_address_offset);
+      val = (bfd_vma) 0 - val;
 
       /* Check for possible overflow.  */
       if (val < 0)
@@ -11056,28 +11434,24 @@ print_displacement (instr_info *ins, char *buf, bfd_vma disp)
          switch (ins->address_mode)
            {
            case mode_64bit:
-             strcpy (buf + j, "0x8000000000000000");
+             oappend_with_style (ins, "0x8000000000000000",
+                                 dis_style_address_offset);
              break;
            case mode_32bit:
-             strcpy (buf + j, "0x80000000");
+             oappend_with_style (ins, "0x80000000",
+                                 dis_style_address_offset);
              break;
            case mode_16bit:
-             strcpy (buf + j, "0x8000");
+             oappend_with_style (ins, "0x8000",
+                                 dis_style_address_offset);
              break;
            }
          return;
        }
     }
 
-  buf[j++] = '0';
-  buf[j++] = 'x';
-
-  sprintf_vma (tmp, (bfd_vma) val);
-  for (i = 0; tmp[i] == '0'; i++)
-    continue;
-  if (tmp[i] == '\0')
-    i--;
-  strcpy (buf + j, tmp + i);
+  sprintf (tmp, "0x%" PRIx64, (int64_t) val);
+  oappend_with_style (ins, tmp, dis_style_address_offset);
 }
 
 static void
@@ -11091,17 +11465,17 @@ intel_operand_size (instr_info *ins, int bytemode, int sizeflag)
          case x_mode:
          case evex_half_bcst_xmmq_mode:
            if (ins->vex.w)
-             oappend (ins, "QWORD PTR ");
+             oappend (ins, "QWORD BCST ");
            else
-             oappend (ins, "DWORD PTR ");
+             oappend (ins, "DWORD BCST ");
            break;
          case xh_mode:
          case evex_half_bcst_xmmqh_mode:
          case evex_half_bcst_xmmqdh_mode:
-           oappend (ins, "WORD PTR ");
+           oappend (ins, "WORD BCST ");
            break;
          default:
-           ins->vex.no_broadcast = 1;
+           ins->vex.no_broadcast = true;
            break;
          }
       return;
@@ -11306,20 +11680,6 @@ intel_operand_size (instr_info *ins, int bytemode, int sizeflag)
          abort ();
        }
       break;
-    case ymmxmm_mode:
-      if (!ins->need_vex)
-       abort ();
-
-      switch (ins->vex.length)
-       {
-       case 128:
-       case 256:
-         oappend (ins, "XMMWORD PTR ");
-         break;
-       default:
-         abort ();
-       }
-      break;
     case o_mode:
       oappend (ins, "OWORD PTR ");
       break;
@@ -11359,7 +11719,7 @@ static void
 print_register (instr_info *ins, unsigned int reg, unsigned int rexmask,
                int bytemode, int sizeflag)
 {
-  const char **names;
+  const char (*names)[8];
 
   USED_REX (rexmask);
   if (ins->rex & rexmask)
@@ -11372,24 +11732,24 @@ print_register (instr_info *ins, unsigned int reg, unsigned int rexmask,
       if (reg & 4)
        USED_REX (0);
       if (ins->rex)
-       names = ins->names8rex;
+       names = att_names8rex;
       else
-       names = ins->names8;
+       names = att_names8;
       break;
     case w_mode:
-      names = ins->names16;
+      names = att_names16;
       break;
     case d_mode:
     case dw_mode:
     case db_mode:
-      names = ins->names32;
+      names = att_names32;
       break;
     case q_mode:
-      names = ins->names64;
+      names = att_names64;
       break;
     case m_mode:
     case v_bnd_mode:
-      names = ins->address_mode == mode_64bit ? ins->names64 : ins->names32;
+      names = ins->address_mode == mode_64bit ? att_names64 : att_names32;
       break;
     case bnd_mode:
     case bnd_swap_mode:
@@ -11398,12 +11758,12 @@ print_register (instr_info *ins, unsigned int reg, unsigned int rexmask,
          oappend (ins, "(bad)");
          return;
        }
-      names = ins->names_bnd;
+      names = att_names_bnd;
       break;
     case indir_v_mode:
       if (ins->address_mode == mode_64bit && ins->isa64 == intel64)
        {
-         names = ins->names64;
+         names = att_names64;
          break;
        }
       /* Fall through.  */
@@ -11411,7 +11771,7 @@ print_register (instr_info *ins, unsigned int reg, unsigned int rexmask,
       if (ins->address_mode == mode_64bit && ((sizeflag & DFLAG)
                                              || (ins->rex & REX_W)))
        {
-         names = ins->names64;
+         names = att_names64;
          break;
        }
       bytemode = v_mode;
@@ -11421,37 +11781,37 @@ print_register (instr_info *ins, unsigned int reg, unsigned int rexmask,
     case dq_mode:
       USED_REX (REX_W);
       if (ins->rex & REX_W)
-       names = ins->names64;
+       names = att_names64;
       else if (bytemode != v_mode && bytemode != v_swap_mode)
-       names = ins->names32;
+       names = att_names32;
       else
        {
          if (sizeflag & DFLAG)
-           names = ins->names32;
+           names = att_names32;
          else
-           names = ins->names16;
+           names = att_names16;
          ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
        }
       break;
     case movsxd_mode:
       if (!(sizeflag & DFLAG) && ins->isa64 == intel64)
-       names = ins->names16;
+       names = att_names16;
       else
-       names = ins->names32;
+       names = att_names32;
       ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
       break;
     case va_mode:
       names = (ins->address_mode == mode_64bit
-              ? ins->names64 : ins->names32);
+              ? att_names64 : att_names32);
       if (!(ins->prefixes & PREFIX_ADDR))
        names = (ins->address_mode == mode_16bit
-                    ? ins->names16 : names);
+                    ? att_names16 : names);
       else
        {
          /* Remove "addr16/addr32".  */
          ins->all_prefixes[ins->last_addr_prefix] = 0;
          names = (ins->address_mode != mode_32bit
-                      ? ins->names32 : ins->names16);
+                      ? att_names32 : att_names16);
          ins->used_prefixes |= PREFIX_ADDR;
        }
       break;
@@ -11462,7 +11822,7 @@ print_register (instr_info *ins, unsigned int reg, unsigned int rexmask,
          oappend (ins, "(bad)");
          return;
        }
-      names = ins->names_mask;
+      names = att_names_mask;
       break;
     case 0:
       return;
@@ -11470,13 +11830,12 @@ print_register (instr_info *ins, unsigned int reg, unsigned int rexmask,
       oappend (ins, INTERNAL_DISASSEMBLER_ERROR);
       return;
     }
-  oappend (ins, names[reg]);
+  oappend_register (ins, names[reg]);
 }
 
-static void
+static bool
 OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
 {
-  bfd_vma disp = 0;
   int add = (ins->rex & REX_B) ? 8 : 0;
   int riprel = 0;
   int shift;
@@ -11585,10 +11944,9 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
   if ((sizeflag & AFLAG) || ins->address_mode == mode_64bit)
     {
       /* 32/64 bit address mode */
+      bfd_signed_vma disp = 0;
       int havedisp;
-      int havesib;
       int havebase;
-      int haveindex;
       int needindex;
       int needaddr32;
       int base, rbase;
@@ -11600,17 +11958,13 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
                         || bytemode == bnd_mode
                         || bytemode == bnd_swap_mode);
       bool check_gather = false;
-      const char **indexes64 = ins->names64;
-      const char **indexes32 = ins->names32;
+      const char (*indexes)[8] = NULL;
 
-      havesib = 0;
       havebase = 1;
-      haveindex = 0;
       base = ins->modrm.rm;
 
       if (base == 4)
        {
-         havesib = 1;
          vindex = ins->sib.index;
          USED_REX (REX_X);
          if (ins->rex & REX_X)
@@ -11628,32 +11982,33 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
                  check_gather = ins->obufp == ins->op_out[1];
                }
 
-             haveindex = 1;
              switch (ins->vex.length)
                {
                case 128:
-                 indexes64 = indexes32 = ins->names_xmm;
+                 indexes = att_names_xmm;
                  break;
                case 256:
                  if (!ins->vex.w
                      || bytemode == vex_vsib_q_w_dq_mode)
-                   indexes64 = indexes32 = ins->names_ymm;
+                   indexes = att_names_ymm;
                  else
-                   indexes64 = indexes32 = ins->names_xmm;
+                   indexes = att_names_xmm;
                  break;
                case 512:
                  if (!ins->vex.w
                      || bytemode == vex_vsib_q_w_dq_mode)
-                   indexes64 = indexes32 = ins->names_zmm;
+                   indexes = att_names_zmm;
                  else
-                   indexes64 = indexes32 = ins->names_ymm;
+                   indexes = att_names_ymm;
                  break;
                default:
                  abort ();
                }
              break;
            default:
-             haveindex = vindex != 4;
+             if (vindex != 4)
+               indexes = ins->address_mode == mode_64bit && !addr32flag
+                         ? att_names64 : att_names32;
              break;
            }
          scale = ins->sib.scale;
@@ -11668,7 +12023,7 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
              || bytemode == vex_sibmem_mode)
            {
              oappend (ins, "(bad)");
-             return;
+             return true;
            }
        }
       rbase = base + add;
@@ -11679,18 +12034,20 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
          if (base == 5)
            {
              havebase = 0;
-             if (ins->address_mode == mode_64bit && !havesib)
+             if (ins->address_mode == mode_64bit && !ins->has_sib)
                riprel = 1;
-             disp = get32s (ins);
+             if (!get32s (ins, &disp))
+               return false;
              if (riprel && bytemode == v_bndmk_mode)
                {
                  oappend (ins, "(bad)");
-                 return;
+                 return true;
                }
            }
          break;
        case 1:
-         FETCH_DATA (ins->info, ins->codep + 1);
+         if (!fetch_code (ins->info, ins->codep + 1))
+           return false;
          disp = *ins->codep++;
          if ((disp & 0x80) != 0)
            disp -= 0x100;
@@ -11698,15 +12055,16 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
            disp <<= shift;
          break;
        case 2:
-         disp = get32s (ins);
+         if (!get32s (ins, &disp))
+           return false;
          break;
        }
 
       needindex = 0;
       needaddr32 = 0;
-      if (havesib
+      if (ins->has_sib
          && !havebase
-         && !haveindex
+         && !indexes
          && ins->address_mode != mode_16bit)
        {
          if (ins->address_mode == mode_64bit)
@@ -11730,24 +12088,26 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
 
       havedisp = (havebase
                  || needindex
-                 || (havesib && (haveindex || scale != 0)));
+                 || (ins->has_sib && (indexes || scale != 0)));
 
       if (!ins->intel_syntax)
        if (ins->modrm.mod != 0 || base == 5)
          {
            if (havedisp || riprel)
-             print_displacement (ins, ins->scratchbuf, disp);
+             print_displacement (ins, disp);
            else
-             print_operand_value (ins, ins->scratchbuf, 1, disp);
-           oappend (ins, ins->scratchbuf);
+             print_operand_value (ins, disp, dis_style_address_offset);
            if (riprel)
              {
-               set_op (ins, disp, 1);
-               oappend (ins, !addr32flag ? "(%rip)" : "(%eip)");
+               set_op (ins, disp, true);
+               oappend_char (ins, '(');
+               oappend_with_style (ins, !addr32flag ? "%rip" : "%eip",
+                                   dis_style_register);
+               oappend_char (ins, ')');
              }
          }
 
-      if ((havebase || haveindex || needindex || needaddr32 || riprel)
+      if ((havebase || indexes || needindex || needaddr32 || riprel)
          && (ins->address_mode != mode_64bit
              || ((bytemode != v_bnd_mode)
                  && (bytemode != v_bndmk_mode)
@@ -11757,73 +12117,60 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
 
       if (havedisp || (ins->intel_syntax && riprel))
        {
-         *ins->obufp++ = ins->open_char;
+         oappend_char (ins, ins->open_char);
          if (ins->intel_syntax && riprel)
            {
-             set_op (ins, disp, 1);
-             oappend (ins, !addr32flag ? "rip" : "eip");
+             set_op (ins, disp, true);
+             oappend_with_style (ins, !addr32flag ? "rip" : "eip",
+                                 dis_style_register);
            }
-         *ins->obufp = '\0';
          if (havebase)
-           oappend (ins, ins->address_mode == mode_64bit && !addr32flag
-                    ? ins->names64[rbase] : ins->names32[rbase]);
-         if (havesib)
+           oappend_register
+             (ins,
+              (ins->address_mode == mode_64bit && !addr32flag
+               ? att_names64 : att_names32)[rbase]);
+         if (ins->has_sib)
            {
              /* ESP/RSP won't allow index.  If base isn't ESP/RSP,
                 print index to tell base + index from base.  */
              if (scale != 0
                  || needindex
-                 || haveindex
+                 || indexes
                  || (havebase && base != ESP_REG_NUM))
                {
                  if (!ins->intel_syntax || havebase)
-                   {
-                     *ins->obufp++ = ins->separator_char;
-                     *ins->obufp = '\0';
-                   }
-                 if (haveindex)
+                   oappend_char (ins, ins->separator_char);
+                 if (indexes)
                    {
                      if (ins->address_mode == mode_64bit || vindex < 16)
-                       oappend (ins, ins->address_mode == mode_64bit
-                                && !addr32flag
-                                ? indexes64[vindex] : indexes32[vindex]);
+                       oappend_register (ins, indexes[vindex]);
                      else
                        oappend (ins, "(bad)");
                    }
                  else
-                   oappend (ins, ins->address_mode == mode_64bit && !addr32flag
-                            ? ins->index64 : ins->index32);
-
-                 *ins->obufp++ = ins->scale_char;
-                 *ins->obufp = '\0';
-                 sprintf (ins->scratchbuf, "%d", 1 << scale);
-                 oappend (ins, ins->scratchbuf);
+                   oappend_register (ins,
+                                     ins->address_mode == mode_64bit
+                                     && !addr32flag
+                                     ? att_index64
+                                     : att_index32);
+
+                 oappend_char (ins, ins->scale_char);
+                 oappend_char_with_style (ins, '0' + (1 << scale),
+                                          dis_style_immediate);
                }
            }
          if (ins->intel_syntax
              && (disp || ins->modrm.mod != 0 || base == 5))
            {
-             if (!havedisp || (bfd_signed_vma) disp >= 0)
-               {
-                 *ins->obufp++ = '+';
-                 *ins->obufp = '\0';
-               }
-             else if (ins->modrm.mod != 1 && disp != -disp)
-               {
-                 *ins->obufp++ = '-';
-                 *ins->obufp = '\0';
-                 disp = - (bfd_signed_vma) disp;
-               }
-
+             if (!havedisp || disp >= 0)
+                 oappend_char (ins, '+');
              if (havedisp)
-               print_displacement (ins, ins->scratchbuf, disp);
+               print_displacement (ins, disp);
              else
-               print_operand_value (ins, ins->scratchbuf, 1, disp);
-             oappend (ins, ins->scratchbuf);
+               print_operand_value (ins, disp, dis_style_address_offset);
            }
 
-         *ins->obufp++ = ins->close_char;
-         *ins->obufp = '\0';
+         oappend_char (ins, ins->close_char);
 
          if (check_gather)
            {
@@ -11844,11 +12191,10 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
            {
              if (!ins->active_seg_prefix)
                {
-                 oappend (ins, ins->names_seg[ds_reg - es_reg]);
+                 oappend_register (ins, att_names_seg[ds_reg - es_reg]);
                  oappend (ins, ":");
                }
-             print_operand_value (ins, ins->scratchbuf, 1, disp);
-             oappend (ins, ins->scratchbuf);
+             print_operand_value (ins, disp, dis_style_text);
            }
        }
     }
@@ -11860,109 +12206,97 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
           || bytemode == vex_vsib_q_w_dq_mode)
     {
       oappend (ins, "(bad)");
-      return;
+      return true;
     }
   else
     {
       /* 16 bit address mode */
+      int disp = 0;
+
       ins->used_prefixes |= ins->prefixes & PREFIX_ADDR;
       switch (ins->modrm.mod)
        {
        case 0:
          if (ins->modrm.rm == 6)
            {
-             disp = get16 (ins);
+       case 2:
+             if (!get16 (ins, &disp))
+               return false;
              if ((disp & 0x8000) != 0)
                disp -= 0x10000;
            }
          break;
        case 1:
-         FETCH_DATA (ins->info, ins->codep + 1);
+         if (!fetch_code (ins->info, ins->codep + 1))
+           return false;
          disp = *ins->codep++;
          if ((disp & 0x80) != 0)
            disp -= 0x100;
          if (ins->vex.evex && shift > 0)
            disp <<= shift;
          break;
-       case 2:
-         disp = get16 (ins);
-         if ((disp & 0x8000) != 0)
-           disp -= 0x10000;
-         break;
        }
 
       if (!ins->intel_syntax)
        if (ins->modrm.mod != 0 || ins->modrm.rm == 6)
-         {
-           print_displacement (ins, ins->scratchbuf, disp);
-           oappend (ins, ins->scratchbuf);
-         }
+         print_displacement (ins, disp);
 
       if (ins->modrm.mod != 0 || ins->modrm.rm != 6)
        {
-         *ins->obufp++ = ins->open_char;
-         *ins->obufp = '\0';
-         oappend (ins, ins->index16[ins->modrm.rm]);
+         oappend_char (ins, ins->open_char);
+         oappend (ins, ins->intel_syntax ? intel_index16[ins->modrm.rm]
+                                         : att_index16[ins->modrm.rm]);
          if (ins->intel_syntax
              && (disp || ins->modrm.mod != 0 || ins->modrm.rm == 6))
            {
-             if ((bfd_signed_vma) disp >= 0)
-               {
-                 *ins->obufp++ = '+';
-                 *ins->obufp = '\0';
-               }
-             else if (ins->modrm.mod != 1)
-               {
-                 *ins->obufp++ = '-';
-                 *ins->obufp = '\0';
-                 disp = - (bfd_signed_vma) disp;
-               }
-
-             print_displacement (ins, ins->scratchbuf, disp);
-             oappend (ins, ins->scratchbuf);
+             if (disp >= 0)
+               oappend_char (ins, '+');
+             print_displacement (ins, disp);
            }
 
-         *ins->obufp++ = ins->close_char;
-         *ins->obufp = '\0';
+         oappend_char (ins, ins->close_char);
        }
       else if (ins->intel_syntax)
        {
          if (!ins->active_seg_prefix)
            {
-             oappend (ins, ins->names_seg[ds_reg - es_reg]);
+             oappend_register (ins, att_names_seg[ds_reg - es_reg]);
              oappend (ins, ":");
            }
-         print_operand_value (ins, ins->scratchbuf, 1, disp & 0xffff);
-         oappend (ins, ins->scratchbuf);
+         print_operand_value (ins, disp & 0xffff, dis_style_text);
        }
     }
   if (ins->vex.b)
     {
       ins->evex_used |= EVEX_b_used;
-      if (!ins->vex.no_broadcast)
+
+      /* Broadcast can only ever be valid for memory sources.  */
+      if (ins->obufp == ins->op_out[0])
+       ins->vex.no_broadcast = true;
+
+      if (!ins->vex.no_broadcast
+         && (!ins->intel_syntax || !(ins->evex_used & EVEX_len_used)))
        {
          if (bytemode == xh_mode)
            {
-             if (ins->vex.w)
-               oappend (ins, "{bad}");
-             else
+             switch (ins->vex.length)
                {
-                 switch (ins->vex.length)
-                   {
-                   case 128:
-                     oappend (ins, "{1to8}");
-                     break;
-                   case 256:
-                     oappend (ins, "{1to16}");
-                     break;
-                   case 512:
-                     oappend (ins, "{1to32}");
-                     break;
-                   default:
-                     abort ();
-                   }
+               case 128:
+                 oappend (ins, "{1to8}");
+                 break;
+               case 256:
+                 oappend (ins, "{1to16}");
+                 break;
+               case 512:
+                 oappend (ins, "{1to32}");
+                 break;
+               default:
+                 abort ();
                }
            }
+         else if (bytemode == q_mode
+                  || bytemode == ymmq_mode)
+           ins->vex.no_broadcast = true;
          else if (ins->vex.w
                   || bytemode == evex_half_bcst_xmmqdh_mode
                   || bytemode == evex_half_bcst_xmmq_mode)
@@ -12001,14 +12335,16 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
                }
            }
          else
-           ins->vex.no_broadcast = 1;
+           ins->vex.no_broadcast = true;
        }
       if (ins->vex.no_broadcast)
        oappend (ins, "{bad}");
     }
+
+  return true;
 }
 
-static void
+static bool
 OP_E (instr_info *ins, int bytemode, int sizeflag)
 {
   /* Skip mod/rm byte.  */
@@ -12024,32 +12360,30 @@ OP_E (instr_info *ins, int bytemode, int sizeflag)
        swap_operand (ins);
 
       print_register (ins, ins->modrm.rm, REX_B, bytemode, sizeflag);
+      return true;
     }
-  else
-    OP_E_memory (ins, bytemode, sizeflag);
+
+  return OP_E_memory (ins, bytemode, sizeflag);
 }
 
-static void
+static bool
 OP_G (instr_info *ins, int bytemode, int sizeflag)
 {
   if (ins->vex.evex && !ins->vex.r && ins->address_mode == mode_64bit)
-    {
-      oappend (ins, "(bad)");
-      return;
-    }
-
-  print_register (ins, ins->modrm.reg, REX_R, bytemode, sizeflag);
+    oappend (ins, "(bad)");
+  else
+    print_register (ins, ins->modrm.reg, REX_R, bytemode, sizeflag);
+  return true;
 }
 
-#ifdef BFD64
-static bfd_vma
-get64 (instr_info *ins)
+static bool
+get64 (instr_info *ins, uint64_t *res)
 {
-  bfd_vma x;
   unsigned int a;
   unsigned int b;
 
-  FETCH_DATA (ins->info, ins->codep + 8);
+  if (!fetch_code (ins->info, ins->codep + 8))
+    return false;
   a = *ins->codep++ & 0xff;
   a |= (*ins->codep++ & 0xff) << 8;
   a |= (*ins->codep++ & 0xff) << 16;
@@ -12058,76 +12392,55 @@ get64 (instr_info *ins)
   b |= (*ins->codep++ & 0xff) << 8;
   b |= (*ins->codep++ & 0xff) << 16;
   b |= (*ins->codep++ & 0xffu) << 24;
-  x = a + ((bfd_vma) b << 32);
-  return x;
-}
-#else
-static bfd_vma
-get64 (instr_info *ins ATTRIBUTE_UNUSED)
-{
-  abort ();
-  return 0;
+  *res = a + ((uint64_t) b << 32);
+  return true;
 }
-#endif
 
-static bfd_signed_vma
-get32 (instr_info *ins)
+static bool
+get32 (instr_info *ins, bfd_signed_vma *res)
 {
-  bfd_signed_vma x = 0;
-
-  FETCH_DATA (ins->info, ins->codep + 4);
-  x = *ins->codep++ & (bfd_signed_vma) 0xff;
-  x |= (*ins->codep++ & (bfd_signed_vma) 0xff) << 8;
-  x |= (*ins->codep++ & (bfd_signed_vma) 0xff) << 16;
-  x |= (*ins->codep++ & (bfd_signed_vma) 0xff) << 24;
-  return x;
+  if (!fetch_code (ins->info, ins->codep + 4))
+    return false;
+  *res = *ins->codep++ & (bfd_vma) 0xff;
+  *res |= (*ins->codep++ & (bfd_vma) 0xff) << 8;
+  *res |= (*ins->codep++ & (bfd_vma) 0xff) << 16;
+  *res |= (*ins->codep++ & (bfd_vma) 0xff) << 24;
+  return true;
 }
 
-static bfd_signed_vma
-get32s (instr_info *ins)
+static bool
+get32s (instr_info *ins, bfd_signed_vma *res)
 {
-  bfd_signed_vma x = 0;
+  if (!get32 (ins, res))
+    return false;
 
-  FETCH_DATA (ins->info, ins->codep + 4);
-  x = *ins->codep++ & (bfd_signed_vma) 0xff;
-  x |= (*ins->codep++ & (bfd_signed_vma) 0xff) << 8;
-  x |= (*ins->codep++ & (bfd_signed_vma) 0xff) << 16;
-  x |= (*ins->codep++ & (bfd_signed_vma) 0xff) << 24;
+  *res = (*res ^ ((bfd_vma) 1 << 31)) - ((bfd_vma) 1 << 31);
 
-  x = (x ^ ((bfd_signed_vma) 1 << 31)) - ((bfd_signed_vma) 1 << 31);
-
-  return x;
+  return true;
 }
 
-static int
-get16 (instr_info *ins)
+static bool
+get16 (instr_info *ins, int *res)
 {
-  int x = 0;
-
-  FETCH_DATA (ins->info, ins->codep + 2);
-  x = *ins->codep++ & 0xff;
-  x |= (*ins->codep++ & 0xff) << 8;
-  return x;
+  if (!fetch_code (ins->info, ins->codep + 2))
+    return false;
+  *res = *ins->codep++ & 0xff;
+  *res |= (*ins->codep++ & 0xff) << 8;
+  return true;
 }
 
 static void
-set_op (instr_info *ins, bfd_vma op, int riprel)
+set_op (instr_info *ins, bfd_vma op, bool riprel)
 {
   ins->op_index[ins->op_ad] = ins->op_ad;
   if (ins->address_mode == mode_64bit)
-    {
-      ins->op_address[ins->op_ad] = op;
-      ins->op_riprel[ins->op_ad] = riprel;
-    }
-  else
-    {
-      /* Mask to get a 32-bit address.  */
-      ins->op_address[ins->op_ad] = op & 0xffffffff;
-      ins->op_riprel[ins->op_ad] = riprel & 0xffffffff;
-    }
+    ins->op_address[ins->op_ad] = op;
+  else /* Mask to get a 32-bit address.  */
+    ins->op_address[ins->op_ad] = op & 0xffffffff;
+  ins->op_riprel[ins->op_ad] = riprel;
 }
 
-static void
+static bool
 OP_REG (instr_info *ins, int code, int sizeflag)
 {
   const char *s;
@@ -12137,8 +12450,8 @@ OP_REG (instr_info *ins, int code, int sizeflag)
     {
     case es_reg: case ss_reg: case cs_reg:
     case ds_reg: case fs_reg: case gs_reg:
-      oappend (ins, ins->names_seg[code - es_reg]);
-      return;
+      oappend_register (ins, att_names_seg[code - es_reg]);
+      return true;
     }
 
   USED_REX (REX_B);
@@ -12151,23 +12464,23 @@ OP_REG (instr_info *ins, int code, int sizeflag)
     {
     case ax_reg: case cx_reg: case dx_reg: case bx_reg:
     case sp_reg: case bp_reg: case si_reg: case di_reg:
-      s = ins->names16[code - ax_reg + add];
+      s = att_names16[code - ax_reg + add];
       break;
     case ah_reg: case ch_reg: case dh_reg: case bh_reg:
       USED_REX (0);
       /* Fall through.  */
     case al_reg: case cl_reg: case dl_reg: case bl_reg:
       if (ins->rex)
-       s = ins->names8rex[code - al_reg + add];
+       s = att_names8rex[code - al_reg + add];
       else
-       s = ins->names8[code - al_reg];
+       s = att_names8[code - al_reg];
       break;
     case rAX_reg: case rCX_reg: case rDX_reg: case rBX_reg:
     case rSP_reg: case rBP_reg: case rSI_reg: case rDI_reg:
       if (ins->address_mode == mode_64bit
          && ((sizeflag & DFLAG) || (ins->rex & REX_W)))
        {
-         s = ins->names64[code - rAX_reg + add];
+         s = att_names64[code - rAX_reg + add];
          break;
        }
       code += eAX_reg - rAX_reg;
@@ -12176,24 +12489,25 @@ OP_REG (instr_info *ins, int code, int sizeflag)
     case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
       USED_REX (REX_W);
       if (ins->rex & REX_W)
-       s = ins->names64[code - eAX_reg + add];
+       s = att_names64[code - eAX_reg + add];
       else
        {
          if (sizeflag & DFLAG)
-           s = ins->names32[code - eAX_reg + add];
+           s = att_names32[code - eAX_reg + add];
          else
-           s = ins->names16[code - eAX_reg + add];
+           s = att_names16[code - eAX_reg + add];
          ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
        }
       break;
     default:
-      s = INTERNAL_DISASSEMBLER_ERROR;
-      break;
+      oappend (ins, INTERNAL_DISASSEMBLER_ERROR);
+      return true;
     }
-  oappend (ins, s);
+  oappend_register (ins, s);
+  return true;
 }
 
-static void
+static bool
 OP_IMREG (instr_info *ins, int code, int sizeflag)
 {
   const char *s;
@@ -12201,38 +12515,41 @@ OP_IMREG (instr_info *ins, int code, int sizeflag)
   switch (code)
     {
     case indir_dx_reg:
-      if (ins->intel_syntax)
-       s = "dx";
-      else
-       s = "(%dx)";
+      if (!ins->intel_syntax)
+       {
+         oappend (ins, "(%dx)");
+         return true;
+       }
+      s = att_names16[dx_reg - ax_reg];
       break;
     case al_reg: case cl_reg:
-      s = ins->names8[code - al_reg];
+      s = att_names8[code - al_reg];
       break;
     case eAX_reg:
       USED_REX (REX_W);
       if (ins->rex & REX_W)
        {
-         s = *ins->names64;
+         s = *att_names64;
          break;
        }
       /* Fall through.  */
     case z_mode_ax_reg:
       if ((ins->rex & REX_W) || (sizeflag & DFLAG))
-       s = *ins->names32;
+       s = *att_names32;
       else
-       s = *ins->names16;
+       s = *att_names16;
       if (!(ins->rex & REX_W))
        ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
       break;
     default:
-      s = INTERNAL_DISASSEMBLER_ERROR;
-      break;
+      oappend (ins, INTERNAL_DISASSEMBLER_ERROR);
+      return true;
     }
-  oappend (ins, s);
+  oappend_register (ins, s);
+  return true;
 }
 
-static void
+static bool
 OP_I (instr_info *ins, int bytemode, int sizeflag)
 {
   bfd_signed_vma op;
@@ -12241,72 +12558,73 @@ OP_I (instr_info *ins, int bytemode, int sizeflag)
   switch (bytemode)
     {
     case b_mode:
-      FETCH_DATA (ins->info, ins->codep + 1);
+      if (!fetch_code (ins->info, ins->codep + 1))
+       return false;
       op = *ins->codep++;
       mask = 0xff;
       break;
     case v_mode:
       USED_REX (REX_W);
       if (ins->rex & REX_W)
-       op = get32s (ins);
+       {
+         if (!get32s (ins, &op))
+           return false;
+       }
       else
        {
+         ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
          if (sizeflag & DFLAG)
            {
-             op = get32 (ins);
+    case d_mode:
+             if (!get32 (ins, &op))
+               return false;
              mask = 0xffffffff;
            }
          else
            {
-             op = get16 (ins);
+             int num;
+
+    case w_mode:
+             if (!get16 (ins, &num))
+               return false;
+             op = num;
              mask = 0xfffff;
            }
-         ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
        }
       break;
-    case d_mode:
-      mask = 0xffffffff;
-      op = get32 (ins);
-      break;
-    case w_mode:
-      mask = 0xfffff;
-      op = get16 (ins);
-      break;
     case const_1_mode:
       if (ins->intel_syntax)
        oappend (ins, "1");
-      return;
+      return true;
     default:
       oappend (ins, INTERNAL_DISASSEMBLER_ERROR);
-      return;
+      return true;
     }
 
   op &= mask;
-  ins->scratchbuf[0] = '$';
-  print_operand_value (ins, ins->scratchbuf + 1, 1, op);
-  oappend_maybe_intel (ins, ins->scratchbuf);
-  ins->scratchbuf[0] = '\0';
+  oappend_immediate (ins, op);
+  return true;
 }
 
-static void
+static bool
 OP_I64 (instr_info *ins, int bytemode, int sizeflag)
 {
+  uint64_t op;
+
   if (bytemode != v_mode || ins->address_mode != mode_64bit
       || !(ins->rex & REX_W))
-    {
-      OP_I (ins, bytemode, sizeflag);
-      return;
-    }
+    return OP_I (ins, bytemode, sizeflag);
 
   USED_REX (REX_W);
 
-  ins->scratchbuf[0] = '$';
-  print_operand_value (ins, ins->scratchbuf + 1, 1, get64 (ins));
-  oappend_maybe_intel (ins, ins->scratchbuf);
-  ins->scratchbuf[0] = '\0';
+  if (!get64 (ins, &op))
+    return false;
+
+  oappend_immediate (ins, op);
+  return true;
 }
 
-static void
+static bool
 OP_sI (instr_info *ins, int bytemode, int sizeflag)
 {
   bfd_signed_vma op;
@@ -12315,7 +12633,8 @@ OP_sI (instr_info *ins, int bytemode, int sizeflag)
     {
     case b_mode:
     case b_T_mode:
-      FETCH_DATA (ins->info, ins->codep + 1);
+      if (!fetch_code (ins->info, ins->codep + 1))
+       return false;
       op = *ins->codep++;
       if ((op & 0x80) != 0)
        op -= 0x100;
@@ -12344,22 +12663,27 @@ OP_sI (instr_info *ins, int bytemode, int sizeflag)
       break;
     case v_mode:
       /* The operand-size prefix is overridden by a REX prefix.  */
-      if ((sizeflag & DFLAG) || (ins->rex & REX_W))
-       op = get32s (ins);
-      else
-       op = get16 (ins);
+      if (!(sizeflag & DFLAG) && !(ins->rex & REX_W))
+       {
+         int val;
+
+         if (!get16 (ins, &val))
+           return false;
+         op = val;
+       }
+      else if (!get32s (ins, &op))
+       return false;
       break;
     default:
       oappend (ins, INTERNAL_DISASSEMBLER_ERROR);
-      return;
+      return true;
     }
 
-  ins->scratchbuf[0] = '$';
-  print_operand_value (ins, ins->scratchbuf + 1, 1, op);
-  oappend_maybe_intel (ins, ins->scratchbuf);
+  oappend_immediate (ins, op);
+  return true;
 }
 
-static void
+static bool
 OP_J (instr_info *ins, int bytemode, int sizeflag)
 {
   bfd_vma disp;
@@ -12369,7 +12693,8 @@ OP_J (instr_info *ins, int bytemode, int sizeflag)
   switch (bytemode)
     {
     case b_mode:
-      FETCH_DATA (ins->info, ins->codep + 1);
+      if (!fetch_code (ins->info, ins->codep + 1))
+       return false;
       disp = *ins->codep++;
       if ((disp & 0x80) != 0)
        disp -= 0x100;
@@ -12380,12 +12705,20 @@ OP_J (instr_info *ins, int bytemode, int sizeflag)
          || (ins->address_mode == mode_64bit
              && ((ins->isa64 == intel64 && bytemode != dqw_mode)
                  || (ins->rex & REX_W))))
-       disp = get32s (ins);
+       {
+         bfd_signed_vma val;
+
+         if (!get32s (ins, &val))
+           return false;
+         disp = val;
+       }
       else
        {
-         disp = get16 (ins);
-         if ((disp & 0x8000) != 0)
-           disp -= 0x10000;
+         int val;
+
+         if (!get16 (ins, &val))
+           return false;
+         disp = val & 0x8000 ? val - 0x10000 : val;
          /* In 16bit mode, address is wrapped around at 64k within
             the same segment.  Otherwise, a data16 prefix on a jump
             instruction means that the pc is masked to 16 bits after
@@ -12401,48 +12734,56 @@ OP_J (instr_info *ins, int bytemode, int sizeflag)
       break;
     default:
       oappend (ins, INTERNAL_DISASSEMBLER_ERROR);
-      return;
+      return true;
     }
   disp = ((ins->start_pc + (ins->codep - ins->start_codep) + disp) & mask)
         | segment;
-  set_op (ins, disp, 0);
-  print_operand_value (ins, ins->scratchbuf, 1, disp);
-  oappend (ins, ins->scratchbuf);
+  set_op (ins, disp, false);
+  print_operand_value (ins, disp, dis_style_text);
+  return true;
 }
 
-static void
+static bool
 OP_SEG (instr_info *ins, int bytemode, int sizeflag)
 {
   if (bytemode == w_mode)
-    oappend (ins, ins->names_seg[ins->modrm.reg]);
-  else
-    OP_E (ins, ins->modrm.mod == 3 ? bytemode : w_mode, sizeflag);
+    {
+      oappend_register (ins, att_names_seg[ins->modrm.reg]);
+      return true;
+    }
+  return OP_E (ins, ins->modrm.mod == 3 ? bytemode : w_mode, sizeflag);
 }
 
-static void
+static bool
 OP_DIR (instr_info *ins, int dummy ATTRIBUTE_UNUSED, int sizeflag)
 {
-  int seg, offset;
+  int seg, offset, res;
+  char scratch[24];
 
   if (sizeflag & DFLAG)
     {
-      offset = get32 (ins);
-      seg = get16 (ins);
-    }
-  else
-    {
-      offset = get16 (ins);
-      seg = get16 (ins);
+      bfd_signed_vma val;
+
+      if (!get32 (ins, &val))
+       return false;;
+      offset = val;
     }
+  else if (!get16 (ins, &offset))
+    return false;
+  if (!get16 (ins, &seg))
+    return false;;
   ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
-  if (ins->intel_syntax)
-    sprintf (ins->scratchbuf, "0x%x:0x%x", seg, offset);
-  else
-    sprintf (ins->scratchbuf, "$0x%x,$0x%x", seg, offset);
-  oappend (ins, ins->scratchbuf);
+
+  res = snprintf (scratch, ARRAY_SIZE (scratch),
+                 ins->intel_syntax ? "0x%x:0x%x" : "$0x%x,$0x%x",
+                 seg, offset);
+  if (res < 0 || (size_t) res >= ARRAY_SIZE (scratch))
+    abort ();
+  oappend (ins, scratch);
+  return true;
 }
 
-static void
+static bool
 OP_OFF (instr_info *ins, int bytemode, int sizeflag)
 {
   bfd_vma off;
@@ -12452,50 +12793,60 @@ OP_OFF (instr_info *ins, int bytemode, int sizeflag)
   append_seg (ins);
 
   if ((sizeflag & AFLAG) || ins->address_mode == mode_64bit)
-    off = get32 (ins);
+    {
+      bfd_signed_vma val;
+
+      if (!get32 (ins, &val))
+       return false;
+      off = val;
+    }
   else
-    off = get16 (ins);
+    {
+      int val;
+
+      if (!get16 (ins, &val))
+       return false;
+      off = val;
+    }
 
   if (ins->intel_syntax)
     {
       if (!ins->active_seg_prefix)
        {
-         oappend (ins, ins->names_seg[ds_reg - es_reg]);
+         oappend_register (ins, att_names_seg[ds_reg - es_reg]);
          oappend (ins, ":");
        }
     }
-  print_operand_value (ins, ins->scratchbuf, 1, off);
-  oappend (ins, ins->scratchbuf);
+  print_operand_value (ins, off, dis_style_address_offset);
+  return true;
 }
 
-static void
+static bool
 OP_OFF64 (instr_info *ins, int bytemode, int sizeflag)
 {
-  bfd_vma off;
+  uint64_t off;
 
   if (ins->address_mode != mode_64bit
       || (ins->prefixes & PREFIX_ADDR))
-    {
-      OP_OFF (ins, bytemode, sizeflag);
-      return;
-    }
+    return OP_OFF (ins, bytemode, sizeflag);
 
   if (ins->intel_syntax && (sizeflag & SUFFIX_ALWAYS))
     intel_operand_size (ins, bytemode, sizeflag);
   append_seg (ins);
 
-  off = get64 (ins);
+  if (!get64 (ins, &off))
+    return false;
 
   if (ins->intel_syntax)
     {
       if (!ins->active_seg_prefix)
        {
-         oappend (ins, ins->names_seg[ds_reg - es_reg]);
+         oappend_register (ins, att_names_seg[ds_reg - es_reg]);
          oappend (ins, ":");
        }
     }
-  print_operand_value (ins, ins->scratchbuf, 1, off);
-  oappend (ins, ins->scratchbuf);
+  print_operand_value (ins, off, dis_style_address_offset);
+  return true;
 }
 
 static void
@@ -12508,20 +12859,19 @@ ptr_reg (instr_info *ins, int code, int sizeflag)
   if (ins->address_mode == mode_64bit)
     {
       if (!(sizeflag & AFLAG))
-       s = ins->names32[code - eAX_reg];
+       s = att_names32[code - eAX_reg];
       else
-       s = ins->names64[code - eAX_reg];
+       s = att_names64[code - eAX_reg];
     }
   else if (sizeflag & AFLAG)
-    s = ins->names32[code - eAX_reg];
+    s = att_names32[code - eAX_reg];
   else
-    s = ins->names16[code - eAX_reg];
-  oappend (ins, s);
-  *ins->obufp++ = ins->close_char;
-  *ins->obufp = 0;
+    s = att_names16[code - eAX_reg];
+  oappend_register (ins, s);
+  oappend_char (ins, ins->close_char);
 }
 
-static void
+static bool
 OP_ESreg (instr_info *ins, int code, int sizeflag)
 {
   if (ins->intel_syntax)
@@ -12541,11 +12891,13 @@ OP_ESreg (instr_info *ins, int code, int sizeflag)
          intel_operand_size (ins, b_mode, sizeflag);
        }
     }
-  oappend_maybe_intel (ins, "%es:");
+  oappend_register (ins, att_names_seg[0]);
+  oappend_char (ins, ':');
   ptr_reg (ins, code, sizeflag);
+  return true;
 }
 
-static void
+static bool
 OP_DSreg (instr_info *ins, int code, int sizeflag)
 {
   if (ins->intel_syntax)
@@ -12570,13 +12922,16 @@ OP_DSreg (instr_info *ins, int code, int sizeflag)
     ins->active_seg_prefix = PREFIX_DS;
   append_seg (ins);
   ptr_reg (ins, code, sizeflag);
+  return true;
 }
 
-static void
+static bool
 OP_C (instr_info *ins, int dummy ATTRIBUTE_UNUSED,
       int sizeflag ATTRIBUTE_UNUSED)
 {
-  int add;
+  int add, res;
+  char scratch[8];
+
   if (ins->rex & REX_R)
     {
       USED_REX (REX_R);
@@ -12590,59 +12945,74 @@ OP_C (instr_info *ins, int dummy ATTRIBUTE_UNUSED,
     }
   else
     add = 0;
-  sprintf (ins->scratchbuf, "%%cr%d", ins->modrm.reg + add);
-  oappend_maybe_intel (ins, ins->scratchbuf);
+  res = snprintf (scratch, ARRAY_SIZE (scratch), "%%cr%d",
+                 ins->modrm.reg + add);
+  if (res < 0 || (size_t) res >= ARRAY_SIZE (scratch))
+    abort ();
+  oappend_register (ins, scratch);
+  return true;
 }
 
-static void
+static bool
 OP_D (instr_info *ins, int dummy ATTRIBUTE_UNUSED,
       int sizeflag ATTRIBUTE_UNUSED)
 {
-  int add;
+  int add, res;
+  char scratch[8];
+
   USED_REX (REX_R);
   if (ins->rex & REX_R)
     add = 8;
   else
     add = 0;
-  if (ins->intel_syntax)
-    sprintf (ins->scratchbuf, "dr%d", ins->modrm.reg + add);
-  else
-    sprintf (ins->scratchbuf, "%%db%d", ins->modrm.reg + add);
-  oappend (ins, ins->scratchbuf);
+  res = snprintf (scratch, ARRAY_SIZE (scratch),
+                 ins->intel_syntax ? "dr%d" : "%%db%d",
+                 ins->modrm.reg + add);
+  if (res < 0 || (size_t) res >= ARRAY_SIZE (scratch))
+    abort ();
+  oappend (ins, scratch);
+  return true;
 }
 
-static void
+static bool
 OP_T (instr_info *ins, int dummy ATTRIBUTE_UNUSED,
       int sizeflag ATTRIBUTE_UNUSED)
 {
-  sprintf (ins->scratchbuf, "%%tr%d", ins->modrm.reg);
-  oappend_maybe_intel (ins, ins->scratchbuf);
+  int res;
+  char scratch[8];
+
+  res = snprintf (scratch, ARRAY_SIZE (scratch), "%%tr%d", ins->modrm.reg);
+  if (res < 0 || (size_t) res >= ARRAY_SIZE (scratch))
+    abort ();
+  oappend_register (ins, scratch);
+  return true;
 }
 
-static void
+static bool
 OP_MMX (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
        int sizeflag ATTRIBUTE_UNUSED)
 {
   int reg = ins->modrm.reg;
-  const char **names;
+  const char (*names)[8];
 
   ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
   if (ins->prefixes & PREFIX_DATA)
     {
-      names = ins->names_xmm;
+      names = att_names_xmm;
       USED_REX (REX_R);
       if (ins->rex & REX_R)
        reg += 8;
     }
   else
-    names = ins->names_mm;
-  oappend (ins, names[reg]);
+    names = att_names_mm;
+  oappend_register (ins, names[reg]);
+  return true;
 }
 
 static void
 print_vector_reg (instr_info *ins, unsigned int reg, int bytemode)
 {
-  const char **names;
+  const char (*names)[8];
 
   if (bytemode == xmmq_mode
       || bytemode == evex_half_bcst_xmmqh_mode
@@ -12652,17 +13022,18 @@ print_vector_reg (instr_info *ins, unsigned int reg, int bytemode)
        {
        case 128:
        case 256:
-         names = ins->names_xmm;
+         names = att_names_xmm;
          break;
        case 512:
-         names = ins->names_ymm;
+         names = att_names_ymm;
+         ins->evex_used |= EVEX_len_used;
          break;
        default:
          abort ();
        }
     }
   else if (bytemode == ymm_mode)
-    names = ins->names_ymm;
+    names = att_names_ymm;
   else if (bytemode == tmm_mode)
     {
       if (reg >= 8)
@@ -12670,7 +13041,7 @@ print_vector_reg (instr_info *ins, unsigned int reg, int bytemode)
          oappend (ins, "(bad)");
          return;
        }
-      names = ins->names_tmm;
+      names = att_names_tmm;
     }
   else if (ins->need_vex
           && bytemode != xmm_mode
@@ -12684,35 +13055,36 @@ print_vector_reg (instr_info *ins, unsigned int reg, int bytemode)
           && bytemode != d_mode
           && bytemode != q_mode)
     {
+      ins->evex_used |= EVEX_len_used;
       switch (ins->vex.length)
        {
        case 128:
-         names = ins->names_xmm;
+         names = att_names_xmm;
          break;
        case 256:
          if (ins->vex.w
              || bytemode != vex_vsib_q_w_dq_mode)
-           names = ins->names_ymm;
+           names = att_names_ymm;
          else
-           names = ins->names_xmm;
+           names = att_names_xmm;
          break;
        case 512:
          if (ins->vex.w
              || bytemode != vex_vsib_q_w_dq_mode)
-           names = ins->names_zmm;
+           names = att_names_zmm;
          else
-           names = ins->names_ymm;
+           names = att_names_ymm;
          break;
        default:
          abort ();
        }
     }
   else
-    names = ins->names_xmm;
-  oappend (ins, names[reg]);
+    names = att_names_xmm;
+  oappend_register (ins, names[reg]);
 }
 
-static void
+static bool
 OP_XMM (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
 {
   unsigned int reg = ins->modrm.reg;
@@ -12729,16 +13101,17 @@ OP_XMM (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
   if (bytemode == tmm_mode)
     ins->modrm.reg = reg;
   else if (bytemode == scalar_mode)
-    ins->vex.no_broadcast = 1;
+    ins->vex.no_broadcast = true;
 
   print_vector_reg (ins, reg, bytemode);
+  return true;
 }
 
-static void
+static bool
 OP_EM (instr_info *ins, int bytemode, int sizeflag)
 {
   int reg;
-  const char **names;
+  const char (*names)[8];
 
   if (ins->modrm.mod != 3)
     {
@@ -12748,8 +13121,7 @@ OP_EM (instr_info *ins, int bytemode, int sizeflag)
          bytemode = (ins->prefixes & PREFIX_DATA) ? x_mode : q_mode;
          ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
        }
-      OP_E (ins, bytemode, sizeflag);
-      return;
+      return OP_E (ins, bytemode, sizeflag);
     }
 
   if ((sizeflag & SUFFIX_ALWAYS) && bytemode == v_swap_mode)
@@ -12762,14 +13134,15 @@ OP_EM (instr_info *ins, int bytemode, int sizeflag)
   reg = ins->modrm.rm;
   if (ins->prefixes & PREFIX_DATA)
     {
-      names = ins->names_xmm;
+      names = att_names_xmm;
       USED_REX (REX_B);
       if (ins->rex & REX_B)
        reg += 8;
     }
   else
-    names = ins->names_mm;
-  oappend (ins, names[reg]);
+    names = att_names_mm;
+  oappend_register (ins, names[reg]);
+  return true;
 }
 
 /* cvt* are the only instructions in sse2 which have
@@ -12777,7 +13150,7 @@ OP_EM (instr_info *ins, int bytemode, int sizeflag)
    in their opcode. 0x66 was originally used to differentiate
    between SSE and MMX instruction(operands). So we have to handle the
    cvt* separately using OP_EMC and OP_MXC */
-static void
+static bool
 OP_EMC (instr_info *ins, int bytemode, int sizeflag)
 {
   if (ins->modrm.mod != 3)
@@ -12787,26 +13160,27 @@ OP_EMC (instr_info *ins, int bytemode, int sizeflag)
          bytemode = (ins->prefixes & PREFIX_DATA) ? x_mode : q_mode;
          ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
        }
-      OP_E (ins, bytemode, sizeflag);
-      return;
+      return OP_E (ins, bytemode, sizeflag);
     }
 
   /* Skip mod/rm byte.  */
   MODRM_CHECK;
   ins->codep++;
   ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
-  oappend (ins, ins->names_mm[ins->modrm.rm]);
+  oappend_register (ins, att_names_mm[ins->modrm.rm]);
+  return true;
 }
 
-static void
+static bool
 OP_MXC (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
        int sizeflag ATTRIBUTE_UNUSED)
 {
   ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
-  oappend (ins, ins->names_mm[ins->modrm.reg]);
+  oappend_register (ins, att_names_mm[ins->modrm.reg]);
+  return true;
 }
 
-static void
+static bool
 OP_EX (instr_info *ins, int bytemode, int sizeflag)
 {
   int reg;
@@ -12819,10 +13193,7 @@ OP_EX (instr_info *ins, int bytemode, int sizeflag)
     bytemode = ins->vex.w ? q_mode : d_mode;
 
   if (ins->modrm.mod != 3)
-    {
-      OP_E_memory (ins, bytemode, sizeflag);
-      return;
-    }
+    return OP_E_memory (ins, bytemode, sizeflag);
 
   reg = ins->modrm.rm;
   USED_REX (REX_B);
@@ -12846,68 +13217,56 @@ OP_EX (instr_info *ins, int bytemode, int sizeflag)
     ins->modrm.rm = reg;
 
   print_vector_reg (ins, reg, bytemode);
+  return true;
 }
 
-static void
+static bool
 OP_MS (instr_info *ins, int bytemode, int sizeflag)
 {
   if (ins->modrm.mod == 3)
-    OP_EM (ins, bytemode, sizeflag);
-  else
-    BadOp (ins);
+    return OP_EM (ins, bytemode, sizeflag);
+  return BadOp (ins);
 }
 
-static void
+static bool
 OP_XS (instr_info *ins, int bytemode, int sizeflag)
 {
   if (ins->modrm.mod == 3)
-    OP_EX (ins, bytemode, sizeflag);
-  else
-    BadOp (ins);
+    return OP_EX (ins, bytemode, sizeflag);
+  return BadOp (ins);
 }
 
-static void
+static bool
 OP_M (instr_info *ins, int bytemode, int sizeflag)
 {
   if (ins->modrm.mod == 3)
     /* bad bound,lea,lds,les,lfs,lgs,lss,cmpxchg8b,vmptrst modrm */
-    BadOp (ins);
-  else
-    OP_E (ins, bytemode, sizeflag);
+    return BadOp (ins);
+  return OP_E (ins, bytemode, sizeflag);
 }
 
-static void
+static bool
 OP_0f07 (instr_info *ins, int bytemode, int sizeflag)
 {
   if (ins->modrm.mod != 3 || ins->modrm.rm != 0)
-    BadOp (ins);
-  else
-    OP_E (ins, bytemode, sizeflag);
+    return BadOp (ins);
+  return OP_E (ins, bytemode, sizeflag);
 }
 
 /* NOP is an alias of "xchg %ax,%ax" in 16bit mode, "xchg %eax,%eax" in
    32bit mode and "xchg %rax,%rax" in 64bit mode.  */
 
-static void
-NOP_Fixup1 (instr_info *ins, int bytemode, int sizeflag)
-{
-  if ((ins->prefixes & PREFIX_DATA) != 0
-      || (ins->rex != 0
-         && ins->rex != 0x48
-         && ins->address_mode == mode_64bit))
-    OP_REG (ins, bytemode, sizeflag);
-  else
-    strcpy (ins->obuf, "nop");
-}
-
-static void
-NOP_Fixup2 (instr_info *ins, int bytemode, int sizeflag)
+static bool
+NOP_Fixup (instr_info *ins, int opnd, int sizeflag)
 {
-  if ((ins->prefixes & PREFIX_DATA) != 0
-      || (ins->rex != 0
-         && ins->rex != 0x48
-         && ins->address_mode == mode_64bit))
-    OP_IMREG (ins, bytemode, sizeflag);
+  if ((ins->prefixes & PREFIX_DATA) == 0 && (ins->rex & REX_B) == 0)
+    {
+      ins->mnemonicendp = stpcpy (ins->obuf, "nop");
+      return true;
+    }
+  if (opnd == 0)
+    return OP_REG (ins, eAX_reg, sizeflag);
+  return OP_IMREG (ins, eAX_reg, sizeflag);
 }
 
 static const char *const Suffix3DNow[] = {
@@ -12977,20 +13336,21 @@ static const char *const Suffix3DNow[] = {
 /* FC */       NULL,           NULL,           NULL,           NULL,
 };
 
-static void
+static bool
 OP_3DNowSuffix (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
                int sizeflag ATTRIBUTE_UNUSED)
 {
   const char *mnemonic;
 
-  FETCH_DATA (ins->info, ins->codep + 1);
+  if (!fetch_code (ins->info, ins->codep + 1))
+    return false;
   /* AMD 3DNow! instructions are specified by an opcode suffix in the
      place where an 8-bit immediate would normally go.  ie. the last
      byte of the instruction.  */
   ins->obufp = ins->mnemonicendp;
   mnemonic = Suffix3DNow[*ins->codep++ & 0xff];
   if (mnemonic)
-    oappend (ins, mnemonic);
+    ins->obufp = stpcpy (ins->obufp, mnemonic);
   else
     {
       /* Since a variable sized ins->modrm/ins->sib chunk is between the start
@@ -13002,6 +13362,7 @@ OP_3DNowSuffix (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
       BadOp (ins);
     }
   ins->mnemonicendp = ins->obufp;
+  return true;
 }
 
 static const struct op simd_cmp_op[] =
@@ -13044,13 +13405,14 @@ static const struct op vex_cmp_op[] =
   { STRING_COMMA_LEN ("true_us") },
 };
 
-static void
+static bool
 CMP_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
           int sizeflag ATTRIBUTE_UNUSED)
 {
   unsigned int cmp_type;
 
-  FETCH_DATA (ins->info, ins->codep + 1);
+  if (!fetch_code (ins->info, ins->codep + 1))
+    return false;
   cmp_type = *ins->codep++ & 0xff;
   if (cmp_type < ARRAY_SIZE (simd_cmp_op))
     {
@@ -13077,69 +13439,70 @@ CMP_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
   else
     {
       /* We have a reserved extension byte.  Output it directly.  */
-      ins->scratchbuf[0] = '$';
-      print_operand_value (ins, ins->scratchbuf + 1, 1, cmp_type);
-      oappend_maybe_intel (ins, ins->scratchbuf);
-      ins->scratchbuf[0] = '\0';
+      oappend_immediate (ins, cmp_type);
     }
+  return true;
 }
 
-static void
+static bool
 OP_Mwait (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
 {
   /* mwait %eax,%ecx / mwaitx %eax,%ecx,%ebx  */
   if (!ins->intel_syntax)
     {
-      strcpy (ins->op_out[0], ins->names32[0]);
-      strcpy (ins->op_out[1], ins->names32[1]);
+      strcpy (ins->op_out[0], att_names32[0] + ins->intel_syntax);
+      strcpy (ins->op_out[1], att_names32[1] + ins->intel_syntax);
       if (bytemode == eBX_reg)
-       strcpy (ins->op_out[2], ins->names32[3]);
-      ins->two_source_ops = 1;
+       strcpy (ins->op_out[2], att_names32[3] + ins->intel_syntax);
+      ins->two_source_ops = true;
     }
   /* Skip mod/rm byte.  */
   MODRM_CHECK;
   ins->codep++;
+  return true;
 }
 
-static void
+static bool
 OP_Monitor (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
            int sizeflag ATTRIBUTE_UNUSED)
 {
   /* monitor %{e,r,}ax,%ecx,%edx"  */
   if (!ins->intel_syntax)
     {
-      const char **names = (ins->address_mode == mode_64bit
-                           ? ins->names64 : ins->names32);
+      const char (*names)[8] = (ins->address_mode == mode_64bit
+                               ? att_names64 : att_names32);
 
       if (ins->prefixes & PREFIX_ADDR)
        {
          /* Remove "addr16/addr32".  */
          ins->all_prefixes[ins->last_addr_prefix] = 0;
          names = (ins->address_mode != mode_32bit
-                  ? ins->names32 : ins->names16);
+                  ? att_names32 : att_names16);
          ins->used_prefixes |= PREFIX_ADDR;
        }
       else if (ins->address_mode == mode_16bit)
-       names = ins->names16;
-      strcpy (ins->op_out[0], names[0]);
-      strcpy (ins->op_out[1], ins->names32[1]);
-      strcpy (ins->op_out[2], ins->names32[2]);
-      ins->two_source_ops = 1;
+       names = att_names16;
+      strcpy (ins->op_out[0], names[0] + ins->intel_syntax);
+      strcpy (ins->op_out[1], att_names32[1] + ins->intel_syntax);
+      strcpy (ins->op_out[2], att_names32[2] + ins->intel_syntax);
+      ins->two_source_ops = true;
     }
   /* Skip mod/rm byte.  */
   MODRM_CHECK;
   ins->codep++;
+  return true;
 }
 
-static void
+static bool
 BadOp (instr_info *ins)
 {
   /* Throw away prefixes and 1st. opcode byte.  */
   ins->codep = ins->insn_codep + 1;
-  oappend (ins, "(bad)");
+  ins->obufp = stpcpy (ins->obufp, "(bad)");
+  return true;
 }
 
-static void
+static bool
 REP_Fixup (instr_info *ins, int bytemode, int sizeflag)
 {
   /* The 0xf3 prefix should be displayed as "rep" for ins, outs, movs,
@@ -13152,48 +13515,48 @@ REP_Fixup (instr_info *ins, int bytemode, int sizeflag)
     case al_reg:
     case eAX_reg:
     case indir_dx_reg:
-      OP_IMREG (ins, bytemode, sizeflag);
-      break;
+      return OP_IMREG (ins, bytemode, sizeflag);
     case eDI_reg:
-      OP_ESreg (ins, bytemode, sizeflag);
-      break;
+      return OP_ESreg (ins, bytemode, sizeflag);
     case eSI_reg:
-      OP_DSreg (ins, bytemode, sizeflag);
-      break;
+      return OP_DSreg (ins, bytemode, sizeflag);
     default:
       abort ();
       break;
     }
+  return true;
 }
 
-static void
+static bool
 SEP_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
           int sizeflag ATTRIBUTE_UNUSED)
 {
   if (ins->isa64 != amd64)
-    return;
+    return true;
 
   ins->obufp = ins->obuf;
   BadOp (ins);
   ins->mnemonicendp = ins->obufp;
   ++ins->codep;
+  return true;
 }
 
 /* For BND-prefixed instructions 0xF2 prefix should be displayed as
    "bnd".  */
 
-static void
+static bool
 BND_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
           int sizeflag ATTRIBUTE_UNUSED)
 {
   if (ins->prefixes & PREFIX_REPNZ)
     ins->all_prefixes[ins->last_repnz_prefix] = BND_PREFIX;
+  return true;
 }
 
 /* For NOTRACK-prefixed instructions, 0x3E prefix should be displayed as
    "notrack".  */
 
-static void
+static bool
 NOTRACK_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
               int sizeflag ATTRIBUTE_UNUSED)
 {
@@ -13207,13 +13570,14 @@ NOTRACK_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
       ins->active_seg_prefix = 0;
       ins->all_prefixes[ins->last_seg_prefix] = NOTRACK_PREFIX;
     }
+  return true;
 }
 
 /* Similar to OP_E.  But the 0xf2/0xf3 ins->prefixes should be displayed as
    "xacquire"/"xrelease" for memory operand if there is a LOCK prefix.
  */
 
-static void
+static bool
 HLE_Fixup1 (instr_info *ins, int bytemode, int sizeflag)
 {
   if (ins->modrm.mod != 3
@@ -13225,14 +13589,14 @@ HLE_Fixup1 (instr_info *ins, int bytemode, int sizeflag)
        ins->all_prefixes[ins->last_repnz_prefix] = XACQUIRE_PREFIX;
     }
 
-  OP_E (ins, bytemode, sizeflag);
+  return OP_E (ins, bytemode, sizeflag);
 }
 
 /* Similar to OP_E.  But the 0xf2/0xf3 ins->prefixes should be displayed as
    "xacquire"/"xrelease" for memory operand.  No check for LOCK prefix.
  */
 
-static void
+static bool
 HLE_Fixup2 (instr_info *ins, int bytemode, int sizeflag)
 {
   if (ins->modrm.mod != 3)
@@ -13243,13 +13607,13 @@ HLE_Fixup2 (instr_info *ins, int bytemode, int sizeflag)
        ins->all_prefixes[ins->last_repnz_prefix] = XACQUIRE_PREFIX;
     }
 
-  OP_E (ins, bytemode, sizeflag);
+  return OP_E (ins, bytemode, sizeflag);
 }
 
 /* Similar to OP_E.  But the 0xf3 prefixes should be displayed as
    "xrelease" for memory operand.  No check for LOCK prefix.   */
 
-static void
+static bool
 HLE_Fixup3 (instr_info *ins, int bytemode, int sizeflag)
 {
   if (ins->modrm.mod != 3
@@ -13257,10 +13621,10 @@ HLE_Fixup3 (instr_info *ins, int bytemode, int sizeflag)
       && (ins->prefixes & PREFIX_REPZ) != 0)
     ins->all_prefixes[ins->last_repz_prefix] = XRELEASE_PREFIX;
 
-  OP_E (ins, bytemode, sizeflag);
+  return OP_E (ins, bytemode, sizeflag);
 }
 
-static void
+static bool
 CMPXCHG8B_Fixup (instr_info *ins, int bytemode, int sizeflag)
 {
   USED_REX (REX_W);
@@ -13279,34 +13643,32 @@ CMPXCHG8B_Fixup (instr_info *ins, int bytemode, int sizeflag)
        ins->all_prefixes[ins->last_repnz_prefix] = XACQUIRE_PREFIX;
     }
 
-  OP_M (ins, bytemode, sizeflag);
+  return OP_M (ins, bytemode, sizeflag);
 }
 
-static void
+static bool
 XMM_Fixup (instr_info *ins, int reg, int sizeflag ATTRIBUTE_UNUSED)
 {
-  const char **names;
+  const char (*names)[8] = att_names_xmm;
 
   if (ins->need_vex)
     {
       switch (ins->vex.length)
        {
        case 128:
-         names = ins->names_xmm;
          break;
        case 256:
-         names = ins->names_ymm;
+         names = att_names_ymm;
          break;
        default:
          abort ();
        }
     }
-  else
-    names = ins->names_xmm;
-  oappend (ins, names[reg]);
+  oappend_register (ins, names[reg]);
+  return true;
 }
 
-static void
+static bool
 FXSAVE_Fixup (instr_info *ins, int bytemode, int sizeflag)
 {
   /* Add proper suffix to "fxsave" and "fxrstor".  */
@@ -13319,17 +13681,17 @@ FXSAVE_Fixup (instr_info *ins, int bytemode, int sizeflag)
       *p = '\0';
       ins->mnemonicendp = p;
     }
-  OP_M (ins, bytemode, sizeflag);
+  return OP_M (ins, bytemode, sizeflag);
 }
 
 /* Display the destination register operand for instructions with
    VEX. */
 
-static void
+static bool
 OP_VEX (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
 {
   int reg, modrm_reg, sib_index = -1;
-  const char **names;
+  const char (*names)[8];
 
   if (!ins->need_vex)
     abort ();
@@ -13341,7 +13703,7 @@ OP_VEX (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
       if (ins->vex.evex && !ins->vex.v)
        {
          oappend (ins, "(bad)");
-         return;
+         return true;
        }
 
       reg &= 7;
@@ -13352,8 +13714,8 @@ OP_VEX (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
   switch (bytemode)
     {
     case scalar_mode:
-      oappend (ins, ins->names_xmm[reg]);
-      return;
+      oappend_register (ins, att_names_xmm[reg]);
+      return true;
 
     case vex_vsib_d_w_dq_mode:
     case vex_vsib_q_w_dq_mode:
@@ -13363,16 +13725,16 @@ OP_VEX (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
       if (ins->vex.length == 128
          || (bytemode != vex_vsib_d_w_dq_mode
              && !ins->vex.w))
-       oappend (ins, ins->names_xmm[reg]);
+       oappend_register (ins, att_names_xmm[reg]);
       else
-       oappend (ins, ins->names_ymm[reg]);
+       oappend_register (ins, att_names_ymm[reg]);
 
       /* All 3 XMM/YMM registers must be distinct.  */
       modrm_reg = ins->modrm.reg;
       if (ins->rex & REX_R)
        modrm_reg += 8;
 
-      if (ins->modrm.rm == 4)
+      if (ins->has_sib && ins->modrm.rm == 4)
        {
          sib_index = ins->sib.index;
          if (ins->rex & REX_X)
@@ -13386,7 +13748,7 @@ OP_VEX (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
       if (sib_index == modrm_reg || sib_index == reg)
        strcat (ins->op_out[1], "/(bad)");
 
-      return;
+      return true;
 
     case tmm_mode:
       /* All 3 TMM registers must be distinct.  */
@@ -13397,7 +13759,7 @@ OP_VEX (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
          /* This must be the 3rd operand.  */
          if (ins->obufp != ins->op_out[2])
            abort ();
-         oappend (ins, ins->names_tmm[reg]);
+         oappend_register (ins, att_names_tmm[reg]);
          if (reg == ins->modrm.reg || reg == ins->modrm.rm)
            strcpy (ins->obufp, "/(bad)");
        }
@@ -13413,7 +13775,7 @@ OP_VEX (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
            strcat (ins->op_out[1], "/(bad)");
        }
 
-      return;
+      return true;
     }
 
   switch (ins->vex.length)
@@ -13422,67 +13784,71 @@ OP_VEX (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
       switch (bytemode)
        {
        case x_mode:
-         names = ins->names_xmm;
+         names = att_names_xmm;
+         ins->evex_used |= EVEX_len_used;
          break;
        case dq_mode:
          if (ins->rex & REX_W)
-           names = ins->names64;
+           names = att_names64;
          else
-           names = ins->names32;
+           names = att_names32;
          break;
        case mask_bd_mode:
        case mask_mode:
          if (reg > 0x7)
            {
              oappend (ins, "(bad)");
-             return;
+             return true;
            }
-         names = ins->names_mask;
+         names = att_names_mask;
          break;
        default:
          abort ();
-         return;
+         return true;
        }
       break;
     case 256:
       switch (bytemode)
        {
        case x_mode:
-         names = ins->names_ymm;
+         names = att_names_ymm;
+         ins->evex_used |= EVEX_len_used;
          break;
        case mask_bd_mode:
        case mask_mode:
-         if (reg > 0x7)
+         if (reg <= 0x7)
            {
-             oappend (ins, "(bad)");
-             return;
+             names = att_names_mask;
+             break;
            }
-         names = ins->names_mask;
-         break;
+         /* Fall through.  */
        default:
          /* See PR binutils/20893 for a reproducer.  */
          oappend (ins, "(bad)");
-         return;
+         return true;
        }
       break;
     case 512:
-      names = ins->names_zmm;
+      names = att_names_zmm;
+      ins->evex_used |= EVEX_len_used;
       break;
     default:
       abort ();
       break;
     }
-  oappend (ins, names[reg]);
+  oappend_register (ins, names[reg]);
+  return true;
 }
 
-static void
+static bool
 OP_VexR (instr_info *ins, int bytemode, int sizeflag)
 {
   if (ins->modrm.mod == 3)
-    OP_VEX (ins, bytemode, sizeflag);
+    return OP_VEX (ins, bytemode, sizeflag);
+  return true;
 }
 
-static void
+static bool
 OP_VexW (instr_info *ins, int bytemode, int sizeflag)
 {
   OP_VEX (ins, bytemode, sizeflag);
@@ -13490,19 +13856,22 @@ OP_VexW (instr_info *ins, int bytemode, int sizeflag)
   if (ins->vex.w)
     {
       /* Swap 2nd and 3rd operands.  */
-      strcpy (ins->scratchbuf, ins->op_out[2]);
-      strcpy (ins->op_out[2], ins->op_out[1]);
-      strcpy (ins->op_out[1], ins->scratchbuf);
+      char *tmp = ins->op_out[2];
+
+      ins->op_out[2] = ins->op_out[1];
+      ins->op_out[1] = tmp;
     }
+  return true;
 }
 
-static void
+static bool
 OP_REG_VexI4 (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
 {
   int reg;
-  const char **names = ins->names_xmm;
+  const char (*names)[8] = att_names_xmm;
 
-  FETCH_DATA (ins->info, ins->codep + 1);
+  if (!fetch_code (ins->info, ins->codep + 1))
+    return false;
   reg = *ins->codep++;
 
   if (bytemode != x_mode && bytemode != scalar_mode)
@@ -13513,29 +13882,30 @@ OP_REG_VexI4 (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
     reg &= 7;
 
   if (bytemode == x_mode && ins->vex.length == 256)
-    names = ins->names_ymm;
+    names = att_names_ymm;
 
-  oappend (ins, names[reg]);
+  oappend_register (ins, names[reg]);
 
   if (ins->vex.w)
     {
       /* Swap 3rd and 4th operands.  */
-      strcpy (ins->scratchbuf, ins->op_out[3]);
-      strcpy (ins->op_out[3], ins->op_out[2]);
-      strcpy (ins->op_out[2], ins->scratchbuf);
+      char *tmp = ins->op_out[3];
+
+      ins->op_out[3] = ins->op_out[2];
+      ins->op_out[2] = tmp;
     }
+  return true;
 }
 
-static void
+static bool
 OP_VexI4 (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
          int sizeflag ATTRIBUTE_UNUSED)
 {
-  ins->scratchbuf[0] = '$';
-  print_operand_value (ins, ins->scratchbuf + 1, 1, ins->codep[-1] & 0xf);
-  oappend_maybe_intel (ins, ins->scratchbuf);
+  oappend_immediate (ins, ins->codep[-1] & 0xf);
+  return true;
 }
 
-static void
+static bool
 VPCMP_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
             int sizeflag ATTRIBUTE_UNUSED)
 {
@@ -13544,7 +13914,8 @@ VPCMP_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
   if (!ins->vex.evex)
     abort ();
 
-  FETCH_DATA (ins->info, ins->codep + 1);
+  if (!fetch_code (ins->info, ins->codep + 1))
+    return false;
   cmp_type = *ins->codep++ & 0xff;
   /* There are aliases for immediates 0, 1, 2, 4, 5, 6.
      If it's the case, print suffix, otherwise - print the immediate.  */
@@ -13575,11 +13946,9 @@ VPCMP_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
   else
     {
       /* We have a reserved extension byte.  Output it directly.  */
-      ins->scratchbuf[0] = '$';
-      print_operand_value (ins, ins->scratchbuf + 1, 1, cmp_type);
-      oappend_maybe_intel (ins, ins->scratchbuf);
-      ins->scratchbuf[0] = '\0';
+      oappend_immediate (ins, cmp_type);
     }
+  return true;
 }
 
 static const struct op xop_cmp_op[] =
@@ -13594,13 +13963,14 @@ static const struct op xop_cmp_op[] =
   { STRING_COMMA_LEN ("true") }
 };
 
-static void
+static bool
 VPCOM_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
             int sizeflag ATTRIBUTE_UNUSED)
 {
   unsigned int cmp_type;
 
-  FETCH_DATA (ins->info, ins->codep + 1);
+  if (!fetch_code (ins->info, ins->codep + 1))
+    return false;
   cmp_type = *ins->codep++ & 0xff;
   if (cmp_type < ARRAY_SIZE (xop_cmp_op))
     {
@@ -13627,11 +13997,9 @@ VPCOM_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
   else
     {
       /* We have a reserved extension byte.  Output it directly.  */
-      ins->scratchbuf[0] = '$';
-      print_operand_value (ins, ins->scratchbuf + 1, 1, cmp_type);
-      oappend_maybe_intel (ins, ins->scratchbuf);
-      ins->scratchbuf[0] = '\0';
+      oappend_immediate (ins, cmp_type);
     }
+  return true;
 }
 
 static const struct op pclmul_op[] =
@@ -13642,13 +14010,14 @@ static const struct op pclmul_op[] =
   { STRING_COMMA_LEN ("hqh") }
 };
 
-static void
+static bool
 PCLMUL_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
              int sizeflag ATTRIBUTE_UNUSED)
 {
   unsigned int pclmul_type;
 
-  FETCH_DATA (ins->info, ins->codep + 1);
+  if (!fetch_code (ins->info, ins->codep + 1))
+    return false;
   pclmul_type = *ins->codep++ & 0xff;
   switch (pclmul_type)
     {
@@ -13675,14 +14044,12 @@ PCLMUL_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
   else
     {
       /* We have a reserved extension byte.  Output it directly.  */
-      ins->scratchbuf[0] = '$';
-      print_operand_value (ins, ins->scratchbuf + 1, 1, pclmul_type);
-      oappend_maybe_intel (ins, ins->scratchbuf);
-      ins->scratchbuf[0] = '\0';
+      oappend_immediate (ins, pclmul_type);
     }
+  return true;
 }
 
-static void
+static bool
 MOVSXD_Fixup (instr_info *ins, int bytemode, int sizeflag)
 {
   /* Add proper suffix to "movsxd".  */
@@ -13712,10 +14079,10 @@ MOVSXD_Fixup (instr_info *ins, int bytemode, int sizeflag)
 
   ins->mnemonicendp = p;
   *p = '\0';
-  OP_E (ins, bytemode, sizeflag);
+  return OP_E (ins, bytemode, sizeflag);
 }
 
-static void
+static bool
 DistinctDest_Fixup (instr_info *ins, int bytemode, int sizeflag)
 {
   unsigned int reg = ins->vex.register_specifier;
@@ -13750,22 +14117,22 @@ DistinctDest_Fixup (instr_info *ins, int bytemode, int sizeflag)
          && modrm_reg == modrm_rm))
     {
       oappend (ins, "(bad)");
+      return true;
     }
-  else
-    OP_XMM (ins, bytemode, sizeflag);
+  return OP_XMM (ins, bytemode, sizeflag);
 }
 
-static void
+static bool
 OP_Rounding (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
 {
   if (ins->modrm.mod != 3 || !ins->vex.b)
-    return;
+    return true;
 
   switch (bytemode)
     {
     case evex_rounding_64_mode:
       if (ins->address_mode != mode_64bit || !ins->vex.w)
-        return;
+        return true;
       /* Fall through.  */
     case evex_rounding_mode:
       ins->evex_used |= EVEX_b_used;
@@ -13779,4 +14146,34 @@ OP_Rounding (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
       abort ();
     }
   oappend (ins, "sae}");
+  return true;
+}
+
+static bool
+PREFETCHI_Fixup (instr_info *ins, int bytemode, int sizeflag)
+{
+  if (ins->modrm.mod != 0 || ins->modrm.rm != 5)
+    {
+      if (ins->intel_syntax)
+       {
+         ins->mnemonicendp = stpcpy (ins->obuf, "nop   ");
+       }
+      else
+       {
+         USED_REX (REX_W);
+         if (ins->rex & REX_W)
+           ins->mnemonicendp = stpcpy (ins->obuf, "nopq  ");
+         else
+           {
+             if (sizeflag & DFLAG)
+               ins->mnemonicendp = stpcpy (ins->obuf, "nopl  ");
+             else
+               ins->mnemonicendp = stpcpy (ins->obuf, "nopw  ");
+             ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
+           }
+       }
+      bytemode = v_mode;
+    }
+
+  return OP_M (ins, bytemode, sizeflag);
 }