]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/i386-tdep.c
gprofng: add hardware counters for AMD Zen4
[thirdparty/binutils-gdb.git] / gdb / i386-tdep.c
index d59008b3bc378d3a0808fdac41bb7773101b15be..f1f909e16169f201df468ab0ef5ca07a18e07ce2 100644 (file)
@@ -1,6 +1,6 @@
 /* Intel 386 target-dependent stuff.
 
-   Copyright (C) 1988-2020 Free Software Foundation, Inc.
+   Copyright (C) 1988-2024 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -17,7 +17,7 @@
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-#include "defs.h"
+#include "extract-store-integer.h"
 #include "opcode/i386.h"
 #include "arch-utils.h"
 #include "command.h"
@@ -28,7 +28,7 @@
 #include "frame-unwind.h"
 #include "inferior.h"
 #include "infrun.h"
-#include "gdbcmd.h"
+#include "cli/cli-cmds.h"
 #include "gdbcore.h"
 #include "gdbtypes.h"
 #include "objfiles.h"
@@ -48,6 +48,7 @@
 #include "i387-tdep.h"
 #include "gdbsupport/x86-xstate.h"
 #include "x86-tdep.h"
+#include "expop.h"
 
 #include "record.h"
 #include "record-full.h"
@@ -66,6 +67,8 @@
 #include <algorithm>
 #include <unordered_set>
 #include "producer.h"
+#include "infcall.h"
+#include "maint.h"
 
 /* Register names.  */
 
@@ -143,7 +146,7 @@ static const char * const i386_mmx_names[] =
 
 static const char * const i386_byte_names[] =
 {
-  "al", "cl", "dl", "bl", 
+  "al", "cl", "dl", "bl",
   "ah", "ch", "dh", "bh"
 };
 
@@ -166,7 +169,7 @@ const int num_lower_zmm_regs = 16;
 static int
 i386_mmx_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int mm0_regnum = tdep->mm0_regnum;
 
   if (mm0_regnum < 0)
@@ -181,7 +184,7 @@ i386_mmx_regnum_p (struct gdbarch *gdbarch, int regnum)
 int
 i386_byte_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   regnum -= tdep->al_regnum;
   return regnum >= 0 && regnum < tdep->num_byte_regs;
@@ -192,7 +195,7 @@ i386_byte_regnum_p (struct gdbarch *gdbarch, int regnum)
 int
 i386_word_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   regnum -= tdep->ax_regnum;
   return regnum >= 0 && regnum < tdep->num_word_regs;
@@ -203,7 +206,7 @@ i386_word_regnum_p (struct gdbarch *gdbarch, int regnum)
 int
 i386_dword_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int eax_regnum = tdep->eax_regnum;
 
   if (eax_regnum < 0)
@@ -218,7 +221,7 @@ i386_dword_regnum_p (struct gdbarch *gdbarch, int regnum)
 int
 i386_zmmh_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int zmm0h_regnum = tdep->zmm0h_regnum;
 
   if (zmm0h_regnum < 0)
@@ -231,7 +234,7 @@ i386_zmmh_regnum_p (struct gdbarch *gdbarch, int regnum)
 int
 i386_zmm_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int zmm0_regnum = tdep->zmm0_regnum;
 
   if (zmm0_regnum < 0)
@@ -244,7 +247,7 @@ i386_zmm_regnum_p (struct gdbarch *gdbarch, int regnum)
 int
 i386_k_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int k0_regnum = tdep->k0_regnum;
 
   if (k0_regnum < 0)
@@ -257,7 +260,7 @@ i386_k_regnum_p (struct gdbarch *gdbarch, int regnum)
 static int
 i386_ymmh_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int ymm0h_regnum = tdep->ymm0h_regnum;
 
   if (ymm0h_regnum < 0)
@@ -272,7 +275,7 @@ i386_ymmh_regnum_p (struct gdbarch *gdbarch, int regnum)
 int
 i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int ymm0_regnum = tdep->ymm0_regnum;
 
   if (ymm0_regnum < 0)
@@ -285,7 +288,7 @@ i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum)
 static int
 i386_ymmh_avx512_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int ymm16h_regnum = tdep->ymm16h_regnum;
 
   if (ymm16h_regnum < 0)
@@ -298,7 +301,7 @@ i386_ymmh_avx512_regnum_p (struct gdbarch *gdbarch, int regnum)
 int
 i386_ymm_avx512_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int ymm16_regnum = tdep->ymm16_regnum;
 
   if (ymm16_regnum < 0)
@@ -313,7 +316,7 @@ i386_ymm_avx512_regnum_p (struct gdbarch *gdbarch, int regnum)
 int
 i386_bnd_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int bnd0_regnum = tdep->bnd0_regnum;
 
   if (bnd0_regnum < 0)
@@ -328,7 +331,7 @@ i386_bnd_regnum_p (struct gdbarch *gdbarch, int regnum)
 int
 i386_xmm_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int num_xmm_regs = I387_NUM_XMM_REGS (tdep);
 
   if (num_xmm_regs == 0)
@@ -343,7 +346,7 @@ i386_xmm_regnum_p (struct gdbarch *gdbarch, int regnum)
 int
 i386_xmm_avx512_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int num_xmm_avx512_regs = I387_NUM_XMM_AVX512_REGS (tdep);
 
   if (num_xmm_avx512_regs == 0)
@@ -356,7 +359,7 @@ i386_xmm_avx512_regnum_p (struct gdbarch *gdbarch, int regnum)
 static int
 i386_mxcsr_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   if (I387_NUM_XMM_REGS (tdep) == 0)
     return 0;
@@ -369,7 +372,7 @@ i386_mxcsr_regnum_p (struct gdbarch *gdbarch, int regnum)
 int
 i386_fp_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   if (I387_ST0_REGNUM (tdep) < 0)
     return 0;
@@ -381,12 +384,12 @@ i386_fp_regnum_p (struct gdbarch *gdbarch, int regnum)
 int
 i386_fpc_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   if (I387_ST0_REGNUM (tdep) < 0)
     return 0;
 
-  return (I387_FCTRL_REGNUM (tdep) <= regnum 
+  return (I387_FCTRL_REGNUM (tdep) <= regnum
          && regnum < I387_XMM0_REGNUM (tdep));
 }
 
@@ -395,7 +398,7 @@ i386_fpc_regnum_p (struct gdbarch *gdbarch, int regnum)
 static int
 i386_bndr_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
    if (I387_BND0R_REGNUM (tdep) < 0)
      return 0;
@@ -409,7 +412,7 @@ i386_bndr_regnum_p (struct gdbarch *gdbarch, int regnum)
 static int
 i386_mpx_ctrl_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
    if (I387_BNDCFGU_REGNUM (tdep) < 0)
      return 0;
@@ -423,7 +426,7 @@ i386_mpx_ctrl_regnum_p (struct gdbarch *gdbarch, int regnum)
 bool
 i386_pkru_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int pkru_regnum = tdep->pkru_regnum;
 
   if (pkru_regnum < 0)
@@ -459,7 +462,7 @@ i386_register_name (struct gdbarch *gdbarch, int regnum)
 const char *
 i386_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   if (i386_bnd_regnum_p (gdbarch, regnum))
     return i386_bnd_names[regnum - tdep->bnd0_regnum];
   if (i386_mmx_regnum_p (gdbarch, regnum))
@@ -473,7 +476,7 @@ i386_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
   else if (i386_word_regnum_p (gdbarch, regnum))
     return i386_word_names[regnum - tdep->ax_regnum];
 
-  internal_error (__FILE__, __LINE__, _("invalid regnum"));
+  internal_error (_("invalid regnum"));
 }
 
 /* Convert a dbx register number REG to the appropriate register
@@ -482,7 +485,7 @@ i386_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
 static int
 i386_dbx_reg_to_regnum (struct gdbarch *gdbarch, int reg)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   /* This implements what GCC calls the "default" register map
      (dbx_register_map[]).  */
@@ -529,7 +532,7 @@ i386_dbx_reg_to_regnum (struct gdbarch *gdbarch, int reg)
 static int
 i386_svr4_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   /* This implements the GCC register map that tries to be compatible
      with the SVR4 C compiler for DWARF (svr4_dbx_register_map[]).  */
@@ -827,7 +830,7 @@ i386_displaced_step_copy_insn (struct gdbarch *gdbarch,
 
   displaced_debug_printf ("%s->%s: %s",
                          paddress (gdbarch, from), paddress (gdbarch, to),
-                         displaced_step_dump_bytes (buf, len).c_str ());
+                         bytes_to_string (buf, len).c_str ());
 
   /* This is a work around for a problem with g++ 4.8.  */
   return displaced_step_copy_insn_closure_up (closure.release ());
@@ -840,7 +843,7 @@ void
 i386_displaced_step_fixup (struct gdbarch *gdbarch,
                           struct displaced_step_copy_insn_closure *closure_,
                           CORE_ADDR from, CORE_ADDR to,
-                          struct regcache *regs)
+                          struct regcache *regs, bool completed_p)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
@@ -883,14 +886,14 @@ i386_displaced_step_fixup (struct gdbarch *gdbarch,
      the displaced instruction; make it relative.  Well, signal
      handler returns don't need relocation either, but we use the
      value of %eip to recognize those; see below.  */
-  if (! i386_absolute_jmp_p (insn)
-      && ! i386_absolute_call_p (insn)
-      && ! i386_ret_p (insn))
+  if (!completed_p
+      || (!i386_absolute_jmp_p (insn)
+         && !i386_absolute_call_p (insn)
+         && !i386_ret_p (insn)))
     {
-      ULONGEST orig_eip;
       int insn_len;
 
-      regcache_cooked_read_unsigned (regs, I386_EIP_REGNUM, &orig_eip);
+      CORE_ADDR pc = regcache_read_pc (regs);
 
       /* A signal trampoline system call changes the %eip, resuming
         execution of the main program after the signal handler has
@@ -907,25 +910,25 @@ i386_displaced_step_fixup (struct gdbarch *gdbarch,
         it unrelocated.  Goodness help us if there are PC-relative
         system calls.  */
       if (i386_syscall_p (insn, &insn_len)
-         && orig_eip != to + (insn - insn_start) + insn_len
+         && pc != to + (insn - insn_start) + insn_len
          /* GDB can get control back after the insn after the syscall.
             Presumably this is a kernel bug.
-            i386_displaced_step_copy_insn ensures its a nop,
+            i386_displaced_step_copy_insn ensures it's a nop,
             we add one to the length for it.  */
-         && orig_eip != to + (insn - insn_start) + insn_len + 1)
+         && pc != to + (insn - insn_start) + insn_len + 1)
        displaced_debug_printf ("syscall changed %%eip; not relocating");
       else
        {
-         ULONGEST eip = (orig_eip - insn_offset) & 0xffffffffUL;
+         ULONGEST eip = (pc - insn_offset) & 0xffffffffUL;
 
          /* If we just stepped over a breakpoint insn, we don't backup
             the pc on purpose; this is to match behaviour without
             stepping.  */
 
-         regcache_cooked_write_unsigned (regs, I386_EIP_REGNUM, eip);
+         regcache_write_pc (regs, eip);
 
          displaced_debug_printf ("relocated %%eip from %s to %s",
-                                 paddress (gdbarch, orig_eip),
+                                 paddress (gdbarch, pc),
                                  paddress (gdbarch, eip));
        }
     }
@@ -938,7 +941,7 @@ i386_displaced_step_fixup (struct gdbarch *gdbarch,
   /* If the instruction was a call, the return address now atop the
      stack is the address following the copied instruction.  We need
      to make it the address following the original instruction.  */
-  if (i386_call_p (insn))
+  if (completed_p && i386_call_p (insn))
     {
       ULONGEST esp;
       ULONGEST retaddr;
@@ -1199,7 +1202,7 @@ i386_analyze_struct_return (CORE_ADDR pc, CORE_ADDR current_pc,
       cache->pc_in_eax = 1;
       return current_pc;
     }
-  
+
   if (buf[1] == proto1[1])
     return pc + 4;
   else
@@ -1214,7 +1217,7 @@ i386_skip_probe (CORE_ADDR pc)
        pushl constant
        call _probe
        addl $4, %esp
-          
+
      followed by
 
        pushl %ebp
@@ -1274,9 +1277,9 @@ i386_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
                pushl -4(%reg)
 
      "andl $-XXX, %esp" can be either 3 bytes or 6 bytes:
-     
-       0x83 0xe4 0xf0                  andl $-16, %esp
-       0x81 0xe4 0x00 0xff 0xff 0xff   andl $-256, %esp
+
+       0x83 0xe4 0xf0                  andl $-16, %esp
+       0x81 0xe4 0x00 0xff 0xff 0xff   andl $-256, %esp
    */
 
   gdb_byte buf[14];
@@ -1325,7 +1328,7 @@ i386_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
       /* MOD must be binary 10 and R/M must be binary 100.  */
       if ((buf[2] & 0xc7) != 0x44)
        return pc;
-      
+
       /* REG has register number.  Registers in pushl and leal have to
         be the same.  */
       if (reg != ((buf[2] >> 3) & 7))
@@ -1467,10 +1470,10 @@ i386_match_insn_block (CORE_ADDR pc, struct i386_insn *insn_patterns)
    yet, and only the scratch registers %eax, %ecx and %edx can be
    touched.  */
 
-struct i386_insn i386_frame_setup_skip_insns[] =
+static i386_insn i386_frame_setup_skip_insns[] =
 {
   /* Check for `movb imm8, r' and `movl imm32, r'.
-    
+
      ??? Should we handle 16-bit operand-sizes here?  */
 
   /* `movb imm8, %al' and `movb imm8, %ah' */
@@ -1545,11 +1548,11 @@ i386_skip_noop (CORE_ADDR pc)
   if (target_read_code (pc, &op, 1))
     return pc;
 
-  while (check) 
+  while (check)
     {
       check = 0;
       /* Ignore `nop' instruction.  */
-      if (op == 0x90) 
+      if (op == 0x90)
        {
          pc += 1;
          if (target_read_code (pc, &op, 1))
@@ -1582,7 +1585,7 @@ i386_skip_noop (CORE_ADDR pc)
            }
        }
     }
-  return pc; 
+  return pc;
 }
 
 /* Check whether PC points at a code that sets up a new stack frame.
@@ -1691,7 +1694,7 @@ i386_analyze_frame_setup (struct gdbarch *gdbarch,
       if (limit <= pc)
        return limit;
 
-      /* Check for stack adjustment 
+      /* Check for stack adjustment
 
            subl $XXX, %esp
         or
@@ -1802,7 +1805,7 @@ i386_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc,
    %ebx (and sometimes a harmless bug causes it to also save but not
    restore %eax); however, the code below is willing to see the pushes
    in any order, and will handle up to 8 of them.
+
    If the setup sequence is at the end of the function, then the next
    instruction will be a branch back to the start.  */
 
@@ -1846,15 +1849,16 @@ i386_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
       struct compunit_symtab *cust = find_pc_compunit_symtab (func_addr);
 
       /* LLVM backend (Clang/Flang) always emits a line note before the
-        prologue and another one after.  We trust clang to emit usable
-        line notes.  */
+        prologue and another one after.  We trust clang and newer Intel
+        compilers to emit usable line notes.  */
       if (post_prologue_pc
          && (cust != NULL
-             && COMPUNIT_PRODUCER (cust) != NULL
-             && producer_is_llvm (COMPUNIT_PRODUCER (cust))))
+             && cust->producer () != NULL
+             && (producer_is_llvm (cust->producer ())
+             || producer_is_icc_ge_19 (cust->producer ()))))
        return std::max (start_pc, post_prologue_pc);
     }
+
   cache.locals = -1;
   pc = i386_analyze_prologue (gdbarch, start_pc, 0xffffffff, &cache);
   if (cache.locals < 0)
@@ -1939,20 +1943,20 @@ i386_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
       gdb_byte buf[4];
 
       if (target_read_code (pc + 1, buf, sizeof buf) == 0)
-       {
+       {
          /* Make sure address is computed correctly as a 32bit
             integer even if CORE_ADDR is 64 bit wide.  */
-         struct bound_minimal_symbol s;
-         CORE_ADDR call_dest;
+         struct bound_minimal_symbol s;
+         CORE_ADDR call_dest;
 
          call_dest = pc + 5 + extract_signed_integer (buf, 4, byte_order);
          call_dest = call_dest & 0xffffffffU;
-         s = lookup_minimal_symbol_by_pc (call_dest);
-         if (s.minsym != NULL
-             && s.minsym->linkage_name () != NULL
-             && strcmp (s.minsym->linkage_name (), "__main") == 0)
-           pc += 5;
-       }
+         s = lookup_minimal_symbol_by_pc (call_dest);
+         if (s.minsym != NULL
+             && s.minsym->linkage_name () != NULL
+             && strcmp (s.minsym->linkage_name (), "__main") == 0)
+           pc += 5;
+       }
     }
 
   return pc;
@@ -1961,7 +1965,7 @@ i386_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 /* This function is 64-bit safe.  */
 
 static CORE_ADDR
-i386_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+i386_unwind_pc (struct gdbarch *gdbarch, const frame_info_ptr &next_frame)
 {
   gdb_byte buf[8];
 
@@ -1973,7 +1977,7 @@ i386_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
 /* Normal frames.  */
 
 static void
-i386_frame_cache_1 (struct frame_info *this_frame,
+i386_frame_cache_1 (const frame_info_ptr &this_frame,
                    struct i386_frame_cache *cache)
 {
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
@@ -2074,7 +2078,7 @@ i386_frame_cache_1 (struct frame_info *this_frame,
 }
 
 static struct i386_frame_cache *
-i386_frame_cache (struct frame_info *this_frame, void **this_cache)
+i386_frame_cache (const frame_info_ptr &this_frame, void **this_cache)
 {
   struct i386_frame_cache *cache;
 
@@ -2098,7 +2102,7 @@ i386_frame_cache (struct frame_info *this_frame, void **this_cache)
 }
 
 static void
-i386_frame_this_id (struct frame_info *this_frame, void **this_cache,
+i386_frame_this_id (const frame_info_ptr &this_frame, void **this_cache,
                    struct frame_id *this_id)
 {
   struct i386_frame_cache *cache = i386_frame_cache (this_frame, this_cache);
@@ -2117,7 +2121,7 @@ i386_frame_this_id (struct frame_info *this_frame, void **this_cache,
 }
 
 static enum unwind_stop_reason
-i386_frame_unwind_stop_reason (struct frame_info *this_frame,
+i386_frame_unwind_stop_reason (const frame_info_ptr &this_frame,
                               void **this_cache)
 {
   struct i386_frame_cache *cache = i386_frame_cache (this_frame, this_cache);
@@ -2133,7 +2137,7 @@ i386_frame_unwind_stop_reason (struct frame_info *this_frame,
 }
 
 static struct value *
-i386_frame_prev_register (struct frame_info *this_frame, void **this_cache,
+i386_frame_prev_register (const frame_info_ptr &this_frame, void **this_cache,
                          int regnum)
 {
   struct i386_frame_cache *cache = i386_frame_cache (this_frame, this_cache);
@@ -2194,6 +2198,7 @@ i386_frame_prev_register (struct frame_info *this_frame, void **this_cache,
 
 static const struct frame_unwind i386_frame_unwind =
 {
+  "i386 prologue",
   NORMAL_FRAME,
   i386_frame_unwind_stop_reason,
   i386_frame_this_id,
@@ -2214,12 +2219,6 @@ static int
 i386_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   gdb_byte insn;
-  struct compunit_symtab *cust;
-
-  cust = find_pc_compunit_symtab (pc);
-  if (cust != NULL && COMPUNIT_EPILOGUE_UNWIND_VALID (cust))
-    return 0;
-
   if (target_read_memory (pc, &insn, 1))
     return 0;  /* Can't read memory at pc.  */
 
@@ -2229,20 +2228,59 @@ i386_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
   return 1;
 }
 
+static int
+i386_epilogue_frame_sniffer_1 (const struct frame_unwind *self,
+                              const frame_info_ptr &this_frame,
+                              void **this_prologue_cache, bool override_p)
+{
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  CORE_ADDR pc = get_frame_pc (this_frame);
+
+  if (frame_relative_level (this_frame) != 0)
+    /* We're not in the inner frame, so assume we're not in an epilogue.  */
+    return 0;
+
+  bool unwind_valid_p
+    = compunit_epilogue_unwind_valid (find_pc_compunit_symtab (pc));
+  if (override_p)
+    {
+      if (unwind_valid_p)
+       /* Don't override the symtab unwinders, skip
+          "i386 epilogue override".  */
+       return 0;
+    }
+  else
+    {
+      if (!unwind_valid_p)
+       /* "i386 epilogue override" unwinder already ran, skip
+          "i386 epilogue".  */
+       return 0;
+    }
+
+  /* Check whether we're in an epilogue.  */
+  return i386_stack_frame_destroyed_p (gdbarch, pc);
+}
+
+static int
+i386_epilogue_override_frame_sniffer (const struct frame_unwind *self,
+                                     const frame_info_ptr &this_frame,
+                                     void **this_prologue_cache)
+{
+  return i386_epilogue_frame_sniffer_1 (self, this_frame, this_prologue_cache,
+                                       true);
+}
+
 static int
 i386_epilogue_frame_sniffer (const struct frame_unwind *self,
-                            struct frame_info *this_frame,
+                            const frame_info_ptr &this_frame,
                             void **this_prologue_cache)
 {
-  if (frame_relative_level (this_frame) == 0)
-    return i386_stack_frame_destroyed_p (get_frame_arch (this_frame),
-                                        get_frame_pc (this_frame));
-  else
-    return 0;
+  return i386_epilogue_frame_sniffer_1 (self, this_frame, this_prologue_cache,
+                                       false);
 }
 
 static struct i386_frame_cache *
-i386_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache)
+i386_epilogue_frame_cache (const frame_info_ptr &this_frame, void **this_cache)
 {
   struct i386_frame_cache *cache;
   CORE_ADDR sp;
@@ -2277,7 +2315,7 @@ i386_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache)
 }
 
 static enum unwind_stop_reason
-i386_epilogue_frame_unwind_stop_reason (struct frame_info *this_frame,
+i386_epilogue_frame_unwind_stop_reason (const frame_info_ptr &this_frame,
                                        void **this_cache)
 {
   struct i386_frame_cache *cache =
@@ -2290,7 +2328,7 @@ i386_epilogue_frame_unwind_stop_reason (struct frame_info *this_frame,
 }
 
 static void
-i386_epilogue_frame_this_id (struct frame_info *this_frame,
+i386_epilogue_frame_this_id (const frame_info_ptr &this_frame,
                             void **this_cache,
                             struct frame_id *this_id)
 {
@@ -2304,7 +2342,7 @@ i386_epilogue_frame_this_id (struct frame_info *this_frame,
 }
 
 static struct value *
-i386_epilogue_frame_prev_register (struct frame_info *this_frame,
+i386_epilogue_frame_prev_register (const frame_info_ptr &this_frame,
                                   void **this_cache, int regnum)
 {
   /* Make sure we've initialized the cache.  */
@@ -2313,13 +2351,25 @@ i386_epilogue_frame_prev_register (struct frame_info *this_frame,
   return i386_frame_prev_register (this_frame, this_cache, regnum);
 }
 
+static const struct frame_unwind i386_epilogue_override_frame_unwind =
+{
+  "i386 epilogue override",
+  NORMAL_FRAME,
+  i386_epilogue_frame_unwind_stop_reason,
+  i386_epilogue_frame_this_id,
+  i386_epilogue_frame_prev_register,
+  NULL,
+  i386_epilogue_override_frame_sniffer
+};
+
 static const struct frame_unwind i386_epilogue_frame_unwind =
 {
+  "i386 epilogue",
   NORMAL_FRAME,
   i386_epilogue_frame_unwind_stop_reason,
   i386_epilogue_frame_this_id,
   i386_epilogue_frame_prev_register,
-  NULL, 
+  NULL,
   i386_epilogue_frame_sniffer
 };
 \f
@@ -2333,7 +2383,7 @@ static const struct frame_unwind i386_epilogue_frame_unwind =
 
 /* Static chain passed in register.  */
 
-struct i386_insn i386_tramp_chain_in_reg_insns[] =
+static i386_insn i386_tramp_chain_in_reg_insns[] =
 {
   /* `movl imm32, %eax' and `movl imm32, %ecx' */
   { 5, { 0xb8 }, { 0xfe } },
@@ -2346,7 +2396,7 @@ struct i386_insn i386_tramp_chain_in_reg_insns[] =
 
 /* Static chain passed on stack (when regparm=3).  */
 
-struct i386_insn i386_tramp_chain_on_stack_insns[] =
+static i386_insn i386_tramp_chain_on_stack_insns[] =
 {
   /* `push imm32' */
   { 5, { 0x68 }, { 0xff } },
@@ -2385,7 +2435,7 @@ i386_in_stack_tramp_p (CORE_ADDR pc)
 
 static int
 i386_stack_tramp_frame_sniffer (const struct frame_unwind *self,
-                               struct frame_info *this_frame,
+                               const frame_info_ptr &this_frame,
                                void **this_cache)
 {
   if (frame_relative_level (this_frame) == 0)
@@ -2396,11 +2446,12 @@ i386_stack_tramp_frame_sniffer (const struct frame_unwind *self,
 
 static const struct frame_unwind i386_stack_tramp_frame_unwind =
 {
+  "i386 stack tramp",
   NORMAL_FRAME,
   i386_epilogue_frame_unwind_stop_reason,
   i386_epilogue_frame_this_id,
   i386_epilogue_frame_prev_register,
-  NULL, 
+  NULL,
   i386_stack_tramp_frame_sniffer
 };
 \f
@@ -2424,10 +2475,10 @@ i386_gen_return_address (struct gdbarch *gdbarch,
 /* Signal trampolines.  */
 
 static struct i386_frame_cache *
-i386_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
+i386_sigtramp_frame_cache (const frame_info_ptr &this_frame, void **this_cache)
 {
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   struct i386_frame_cache *cache;
   CORE_ADDR addr;
@@ -2473,7 +2524,7 @@ i386_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
 }
 
 static enum unwind_stop_reason
-i386_sigtramp_frame_unwind_stop_reason (struct frame_info *this_frame,
+i386_sigtramp_frame_unwind_stop_reason (const frame_info_ptr &this_frame,
                                        void **this_cache)
 {
   struct i386_frame_cache *cache =
@@ -2486,7 +2537,7 @@ i386_sigtramp_frame_unwind_stop_reason (struct frame_info *this_frame,
 }
 
 static void
-i386_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache,
+i386_sigtramp_frame_this_id (const frame_info_ptr &this_frame, void **this_cache,
                             struct frame_id *this_id)
 {
   struct i386_frame_cache *cache =
@@ -2502,7 +2553,7 @@ i386_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache,
 }
 
 static struct value *
-i386_sigtramp_frame_prev_register (struct frame_info *this_frame,
+i386_sigtramp_frame_prev_register (const frame_info_ptr &this_frame,
                                   void **this_cache, int regnum)
 {
   /* Make sure we've initialized the cache.  */
@@ -2513,10 +2564,11 @@ i386_sigtramp_frame_prev_register (struct frame_info *this_frame,
 
 static int
 i386_sigtramp_frame_sniffer (const struct frame_unwind *self,
-                            struct frame_info *this_frame,
+                            const frame_info_ptr &this_frame,
                             void **this_prologue_cache)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (this_frame));
+  gdbarch *arch = get_frame_arch (this_frame);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (arch);
 
   /* We shouldn't even bother if we don't have a sigcontext_addr
      handler.  */
@@ -2543,6 +2595,7 @@ i386_sigtramp_frame_sniffer (const struct frame_unwind *self,
 
 static const struct frame_unwind i386_sigtramp_frame_unwind =
 {
+  "i386 sigtramp",
   SIGTRAMP_FRAME,
   i386_sigtramp_frame_unwind_stop_reason,
   i386_sigtramp_frame_this_id,
@@ -2553,7 +2606,7 @@ static const struct frame_unwind i386_sigtramp_frame_unwind =
 \f
 
 static CORE_ADDR
-i386_frame_base_address (struct frame_info *this_frame, void **this_cache)
+i386_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
 {
   struct i386_frame_cache *cache = i386_frame_cache (this_frame, this_cache);
 
@@ -2569,7 +2622,7 @@ static const struct frame_base i386_frame_base =
 };
 
 static struct frame_id
-i386_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
+i386_dummy_id (struct gdbarch *gdbarch, const frame_info_ptr &this_frame)
 {
   CORE_ADDR fp;
 
@@ -2596,13 +2649,14 @@ i386_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
    success.  */
 
 static int
-i386_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
+i386_get_longjmp_target (const frame_info_ptr &frame, CORE_ADDR *pc)
 {
   gdb_byte buf[4];
   CORE_ADDR sp, jb_addr;
   struct gdbarch *gdbarch = get_frame_arch (frame);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  int jb_pc_offset = gdbarch_tdep (gdbarch)->jb_pc_offset;
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
+  int jb_pc_offset = tdep->jb_pc_offset;
 
   /* If JB_PC_OFFSET is -1, we have no way to find out where the
      longjmp will land.  */
@@ -2634,17 +2688,17 @@ i386_16_byte_align_p (struct type *type)
   type = check_typedef (type);
   if ((type->code () == TYPE_CODE_DECFLOAT
        || (type->code () == TYPE_CODE_ARRAY && type->is_vector ()))
-      && TYPE_LENGTH (type) == 16)
+      && type->length () == 16)
     return 1;
   if (type->code () == TYPE_CODE_ARRAY)
-    return i386_16_byte_align_p (TYPE_TARGET_TYPE (type));
+    return i386_16_byte_align_p (type->target_type ());
   if (type->code () == TYPE_CODE_STRUCT
       || type->code () == TYPE_CODE_UNION)
     {
       int i;
       for (i = 0; i < type->num_fields (); i++)
        {
-         if (field_is_static (&type->field (i)))
+         if (type->field (i).is_static ())
            continue;
          if (i386_16_byte_align_p (type->field (i).type ()))
            return 1;
@@ -2715,15 +2769,15 @@ i386_thiscall_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
       for (i = thiscall ? 1 : 0; i < nargs; i++)
        {
-         int len = TYPE_LENGTH (value_enclosing_type (args[i]));
+         int len = args[i]->enclosing_type ()->length ();
 
          if (write_pass)
            {
-             if (i386_16_byte_align_p (value_enclosing_type (args[i])))
+             if (i386_16_byte_align_p (args[i]->enclosing_type ()))
                args_space_used = align_up (args_space_used, 16);
 
              write_memory (sp + args_space_used,
-                           value_contents_all (args[i]), len);
+                           args[i]->contents_all ().data (), len);
              /* The System V ABI says that:
 
              "An argument's size is increased, if necessary, to make it a
@@ -2735,7 +2789,7 @@ i386_thiscall_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
            }
          else
            {
-             if (i386_16_byte_align_p (value_enclosing_type (args[i])))
+             if (i386_16_byte_align_p (args[i]->enclosing_type ()))
                args_space = align_up (args_space, 16);
              args_space += align_up (len, 4);
            }
@@ -2767,7 +2821,50 @@ i386_thiscall_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
   /* The 'this' pointer needs to be in ECX.  */
   if (thiscall)
-    regcache->cooked_write (I386_ECX_REGNUM, value_contents_all (args[0]));
+    regcache->cooked_write (I386_ECX_REGNUM,
+                           args[0]->contents_all ().data ());
+
+  /* If the PLT is position-independent, the SYSTEM V ABI requires %ebx to be
+     set to the address of the GOT when doing a call to a PLT address.
+     Note that we do not try to determine whether the PLT is
+     position-independent, we just set the register regardless.  */
+  CORE_ADDR func_addr = find_function_addr (function, nullptr, nullptr);
+  if (in_plt_section (func_addr))
+    {
+      struct objfile *objf = nullptr;
+      asection *asect = nullptr;
+      obj_section *osect = nullptr;
+
+      /* Get object file containing func_addr.  */
+      obj_section *func_section = find_pc_section (func_addr);
+      if (func_section != nullptr)
+       objf = func_section->objfile;
+
+      if (objf != nullptr)
+       {
+         /* Get corresponding .got.plt or .got section.  */
+         asect = bfd_get_section_by_name (objf->obfd.get (), ".got.plt");
+         if (asect == nullptr)
+           asect = bfd_get_section_by_name (objf->obfd.get (), ".got");
+       }
+
+      if (asect != nullptr)
+       /* Translate asection to obj_section.  */
+       osect = maint_obj_section_from_bfd_section (objf->obfd.get (),
+                                                   asect, objf);
+
+      if (osect != nullptr)
+       {
+         /* Store the section address in %ebx.  */
+         store_unsigned_integer (buf, 4, byte_order, osect->addr ());
+         regcache->cooked_write (I386_EBX_REGNUM, buf);
+       }
+      else
+       {
+         /* If we would only do this for a position-independent PLT, it would
+            make sense to issue a warning here.  */
+       }
+    }
 
   /* MarkK wrote: This "+ 8" is all over the place:
      (i386_frame_this_id, i386_sigtramp_frame_this_id,
@@ -2808,11 +2905,18 @@ static void
 i386_extract_return_value (struct gdbarch *gdbarch, struct type *type,
                           struct regcache *regcache, gdb_byte *valbuf)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int len = TYPE_LENGTH (type);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
+  int len = type->length ();
   gdb_byte buf[I386_MAX_REGISTER_SIZE];
 
-  if (type->code () == TYPE_CODE_FLT)
+  /* _Float16 and _Float16 _Complex values are returned via xmm0.  */
+  if (((type->code () == TYPE_CODE_FLT) && len == 2)
+      || ((type->code () == TYPE_CODE_COMPLEX) && len == 4))
+    {
+       regcache->raw_read (I387_XMM0_REGNUM (tdep), valbuf);
+       return;
+    }
+  else if (type->code () == TYPE_CODE_FLT)
     {
       if (tdep->st0_regnum < 0)
        {
@@ -2846,8 +2950,7 @@ i386_extract_return_value (struct gdbarch *gdbarch, struct type *type,
          memcpy (valbuf + low_size, buf, len - low_size);
        }
       else
-       internal_error (__FILE__, __LINE__,
-                       _("Cannot extract return value of %d bytes long."),
+       internal_error (_("Cannot extract return value of %d bytes long."),
                        len);
     }
 }
@@ -2859,8 +2962,8 @@ static void
 i386_store_return_value (struct gdbarch *gdbarch, struct type *type,
                         struct regcache *regcache, const gdb_byte *valbuf)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int len = TYPE_LENGTH (type);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
+  int len = type->length ();
 
   if (type->code () == TYPE_CODE_FLT)
     {
@@ -2911,8 +3014,7 @@ i386_store_return_value (struct gdbarch *gdbarch, struct type *type,
                                    valbuf + low_size);
        }
       else
-       internal_error (__FILE__, __LINE__,
-                       _("Cannot store return value of %d bytes long."), len);
+       internal_error (_("Cannot store return value of %d bytes long."), len);
     }
 }
 \f
@@ -2938,9 +3040,9 @@ static const char *struct_convention = default_struct_convention;
 static int
 i386_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   enum type_code code = type->code ();
-  int len = TYPE_LENGTH (type);
+  int len = type->length ();
 
   gdb_assert (code == TYPE_CODE_STRUCT
              || code == TYPE_CODE_UNION
@@ -2948,7 +3050,8 @@ i386_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type)
 
   if (struct_convention == pcc_struct_convention
       || (struct_convention == default_struct_convention
-         && tdep->struct_return == pcc_struct_return))
+         && tdep->struct_return == pcc_struct_return)
+      || TYPE_HAS_DYNAMIC_LENGTH (type))
     return 0;
 
   /* Structures consisting of a single `float', `double' or 'long
@@ -2972,7 +3075,7 @@ i386_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type)
 static enum return_value_convention
 i386_return_value (struct gdbarch *gdbarch, struct value *function,
                   struct type *type, struct regcache *regcache,
-                  gdb_byte *readbuf, const gdb_byte *writebuf)
+                  struct value **read_value, const gdb_byte *writebuf)
 {
   enum type_code code = type->code ();
 
@@ -2981,10 +3084,10 @@ i386_return_value (struct gdbarch *gdbarch, struct value *function,
        || code == TYPE_CODE_ARRAY)
        && !i386_reg_struct_return_p (gdbarch, type))
       /* Complex double and long double uses the struct return convention.  */
-      || (code == TYPE_CODE_COMPLEX && TYPE_LENGTH (type) == 16)
-      || (code == TYPE_CODE_COMPLEX && TYPE_LENGTH (type) == 24)
+      || (code == TYPE_CODE_COMPLEX && type->length () == 16)
+      || (code == TYPE_CODE_COMPLEX && type->length () == 24)
       /* 128-bit decimal float uses the struct return convention.  */
-      || (code == TYPE_CODE_DECFLOAT && TYPE_LENGTH (type) == 16))
+      || (code == TYPE_CODE_DECFLOAT && type->length () == 16))
     {
       /* The System V ABI says that:
 
@@ -3003,12 +3106,12 @@ i386_return_value (struct gdbarch *gdbarch, struct value *function,
         a record, so the convention applied to records also applies
         to arrays.  */
 
-      if (readbuf)
+      if (read_value != nullptr)
        {
          ULONGEST addr;
 
          regcache_raw_read_unsigned (regcache, I386_EAX_REGNUM, &addr);
-         read_memory (addr, readbuf, TYPE_LENGTH (type));
+         *read_value = value_at_non_lval (type, addr);
        }
 
       return RETURN_VALUE_ABI_RETURNS_ADDRESS;
@@ -3023,13 +3126,21 @@ i386_return_value (struct gdbarch *gdbarch, struct value *function,
      here.  */
   if (code == TYPE_CODE_STRUCT && type->num_fields () == 1)
     {
-      type = check_typedef (type->field (0).type ());
-      return i386_return_value (gdbarch, function, type, regcache,
-                               readbuf, writebuf);
+      struct type *inner_type = check_typedef (type->field (0).type ());
+      enum return_value_convention result
+       = i386_return_value (gdbarch, function, inner_type, regcache,
+                            read_value, writebuf);
+      if (read_value != nullptr)
+       (*read_value)->deprecated_set_type (type);
+      return result;
     }
 
-  if (readbuf)
-    i386_extract_return_value (gdbarch, type, regcache, readbuf);
+  if (read_value != nullptr)
+    {
+      *read_value = value::allocate (type);
+      i386_extract_return_value (gdbarch, type, regcache,
+                                (*read_value)->contents_raw ().data ());
+    }
   if (writebuf)
     i386_store_return_value (gdbarch, type, regcache, writebuf);
 
@@ -3040,7 +3151,7 @@ i386_return_value (struct gdbarch *gdbarch, struct value *function,
 struct type *
 i387_ext_type (struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   if (!tdep->i387_ext_type)
     {
@@ -3058,7 +3169,7 @@ i387_ext_type (struct gdbarch *gdbarch)
 static struct type *
 i386_bnd_type (struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
 
   if (!tdep->i386_bnd_type)
@@ -3094,7 +3205,7 @@ i386_bnd_type (struct gdbarch *gdbarch)
 static struct type *
 i386_zmm_type (struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   if (!tdep->i386_zmm_type)
     {
@@ -3111,6 +3222,7 @@ i386_zmm_type (struct gdbarch *gdbarch)
        int8_t v64_int8[64];
        double v8_double[8];
        float v16_float[16];
+       float16_t v32_half[32];
        bfloat16_t v32_bfloat16[32];
       };
 #endif
@@ -3121,6 +3233,8 @@ i386_zmm_type (struct gdbarch *gdbarch)
                               "__gdb_builtin_type_vec512i", TYPE_CODE_UNION);
       append_composite_type_field (t, "v32_bfloat16",
                                   init_vector_type (bt->builtin_bfloat16, 32));
+      append_composite_type_field (t, "v32_half",
+                                  init_vector_type (bt->builtin_half, 32));
       append_composite_type_field (t, "v16_float",
                                   init_vector_type (bt->builtin_float, 16));
       append_composite_type_field (t, "v8_double",
@@ -3150,7 +3264,7 @@ i386_zmm_type (struct gdbarch *gdbarch)
 static struct type *
 i386_ymm_type (struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   if (!tdep->i386_ymm_type)
     {
@@ -3167,6 +3281,7 @@ i386_ymm_type (struct gdbarch *gdbarch)
        int8_t v32_int8[32];
        double v4_double[4];
        float v8_float[8];
+       float16_t v16_half[16];
        bfloat16_t v16_bfloat16[16];
       };
 #endif
@@ -3177,6 +3292,8 @@ i386_ymm_type (struct gdbarch *gdbarch)
                               "__gdb_builtin_type_vec256i", TYPE_CODE_UNION);
       append_composite_type_field (t, "v16_bfloat16",
                                   init_vector_type (bt->builtin_bfloat16, 16));
+      append_composite_type_field (t, "v16_half",
+                                  init_vector_type (bt->builtin_half, 16));
       append_composite_type_field (t, "v8_float",
                                   init_vector_type (bt->builtin_float, 8));
       append_composite_type_field (t, "v4_double",
@@ -3204,7 +3321,7 @@ i386_ymm_type (struct gdbarch *gdbarch)
 static struct type *
 i386_mmx_type (struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   if (!tdep->i386_mmx_type)
     {
@@ -3271,24 +3388,22 @@ i386_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
        return bt->builtin_int64;
     }
 
-  internal_error (__FILE__, __LINE__, _("invalid regnum"));
+  internal_error (_("invalid regnum"));
 }
 
 /* Map a cooked register onto a raw register or memory.  For the i386,
    the MMX registers need to be mapped onto floating point registers.  */
 
 static int
-i386_mmx_regnum_to_fp_regnum (readable_regcache *regcache, int regnum)
+i386_mmx_regnum_to_fp_regnum (const frame_info_ptr &next_frame, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
-  int mmxreg, fpreg;
-  ULONGEST fstat;
-  int tos;
-
-  mmxreg = regnum - tdep->mm0_regnum;
-  regcache->raw_read (I387_FSTAT_REGNUM (tdep), &fstat);
-  tos = (fstat >> 11) & 0x7;
-  fpreg = (mmxreg + tos) % 8;
+  gdbarch *arch = frame_unwind_arch (next_frame);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (arch);
+  ULONGEST fstat
+    = frame_unwind_register_unsigned (next_frame, I387_FSTAT_REGNUM (tdep));
+  int tos = (fstat >> 11) & 0x7;
+  int mmxreg = regnum - tdep->mm0_regnum;
+  int fpreg = (mmxreg + tos) % 8;
 
   return (I387_ST0_REGNUM (tdep) + fpreg);
 }
@@ -3297,319 +3412,200 @@ i386_mmx_regnum_to_fp_regnum (readable_regcache *regcache, int regnum)
    amd64_pseudo_register_read_value.  It does all the work but reads
    the data into an already-allocated value.  */
 
-void
-i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
-                                     readable_regcache *regcache,
-                                     int regnum,
-                                     struct value *result_value)
+value *
+i386_pseudo_register_read_value (gdbarch *gdbarch, const frame_info_ptr &next_frame,
+                                const int pseudo_reg_num)
 {
-  gdb_byte raw_buf[I386_MAX_REGISTER_SIZE];
-  enum register_status status;
-  gdb_byte *buf = value_contents_raw (result_value);
-
-  if (i386_mmx_regnum_p (gdbarch, regnum))
+  if (i386_mmx_regnum_p (gdbarch, pseudo_reg_num))
     {
-      int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
+      int fpnum = i386_mmx_regnum_to_fp_regnum (next_frame, pseudo_reg_num);
 
       /* Extract (always little endian).  */
-      status = regcache->raw_read (fpnum, raw_buf);
-      if (status != REG_VALID)
-       mark_value_bytes_unavailable (result_value, 0,
-                                     TYPE_LENGTH (value_type (result_value)));
-      else
-       memcpy (buf, raw_buf, register_size (gdbarch, regnum));
+      return pseudo_from_raw_part (next_frame, pseudo_reg_num, fpnum, 0);
     }
   else
     {
-      struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-      if (i386_bnd_regnum_p (gdbarch, regnum))
+      i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
+      if (i386_bnd_regnum_p (gdbarch, pseudo_reg_num))
        {
-         regnum -= tdep->bnd0_regnum;
+         int i = pseudo_reg_num - tdep->bnd0_regnum;
 
          /* Extract (always little endian).  Read lower 128bits.  */
-         status = regcache->raw_read (I387_BND0R_REGNUM (tdep) + regnum,
-                                      raw_buf);
-         if (status != REG_VALID)
-           mark_value_bytes_unavailable (result_value, 0, 16);
-         else
-           {
-             enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
-             LONGEST upper, lower;
-             int size = TYPE_LENGTH (builtin_type (gdbarch)->builtin_data_ptr);
+         value *bndr_value
+           = value_of_register (I387_BND0R_REGNUM (tdep) + i, next_frame);
+         int size = builtin_type (gdbarch)->builtin_data_ptr->length ();
+         value *result
+           = value::allocate_register (next_frame, pseudo_reg_num);
 
-             lower = extract_unsigned_integer (raw_buf, 8, byte_order);
-             upper = extract_unsigned_integer (raw_buf + 8, 8, byte_order);
-             upper = ~upper;
+         /* Copy the lower. */
+         bndr_value->contents_copy (result, 0, 0, size);
 
-             memcpy (buf, &lower, size);
-             memcpy (buf + size, &upper, size);
+         /* Copy the upper.  */
+         bndr_value->contents_copy (result, size, 8, size);
+
+         /* If upper bytes are available, compute ones' complement.  */
+         if (result->bytes_available (size, size))
+           {
+             bfd_endian byte_order
+               = gdbarch_byte_order (frame_unwind_arch (next_frame));
+             gdb::array_view<gdb_byte> upper_bytes
+               = result->contents_raw ().slice (size, size);
+             ULONGEST upper
+               = extract_unsigned_integer (upper_bytes, byte_order);
+             upper = ~upper;
+             store_unsigned_integer (upper_bytes, byte_order, upper);
            }
-       }
-      else if (i386_k_regnum_p (gdbarch, regnum))
-       {
-         regnum -= tdep->k0_regnum;
 
-         /* Extract (always little endian).  */
-         status = regcache->raw_read (tdep->k0_regnum + regnum, raw_buf);
-         if (status != REG_VALID)
-           mark_value_bytes_unavailable (result_value, 0, 8);
-         else
-           memcpy (buf, raw_buf, 8);
+         return result;
        }
-      else if (i386_zmm_regnum_p (gdbarch, regnum))
+      else if (i386_zmm_regnum_p (gdbarch, pseudo_reg_num))
        {
-         regnum -= tdep->zmm0_regnum;
+         /* Which register is it, relative to zmm0.  */
+         int i_0 = pseudo_reg_num - tdep->zmm0_regnum;
 
-         if (regnum < num_lower_zmm_regs)
-           {
-             /* Extract (always little endian).  Read lower 128bits.  */
-             status = regcache->raw_read (I387_XMM0_REGNUM (tdep) + regnum,
-                                          raw_buf);
-             if (status != REG_VALID)
-               mark_value_bytes_unavailable (result_value, 0, 16);
-             else
-               memcpy (buf, raw_buf, 16);
-
-             /* Extract (always little endian).  Read upper 128bits.  */
-             status = regcache->raw_read (tdep->ymm0h_regnum + regnum,
-                                          raw_buf);
-             if (status != REG_VALID)
-               mark_value_bytes_unavailable (result_value, 16, 16);
-             else
-               memcpy (buf + 16, raw_buf, 16);
-           }
+         if (i_0 < num_lower_zmm_regs)
+           return pseudo_from_concat_raw (next_frame, pseudo_reg_num,
+                                          I387_XMM0_REGNUM (tdep) + i_0,
+                                          tdep->ymm0h_regnum + i_0,
+                                          tdep->zmm0h_regnum + i_0);
          else
            {
-             /* Extract (always little endian).  Read lower 128bits.  */
-             status = regcache->raw_read (I387_XMM16_REGNUM (tdep) + regnum
-                                          - num_lower_zmm_regs,
-                                          raw_buf);
-             if (status != REG_VALID)
-               mark_value_bytes_unavailable (result_value, 0, 16);
-             else
-               memcpy (buf, raw_buf, 16);
-
-             /* Extract (always little endian).  Read upper 128bits.  */
-             status = regcache->raw_read (I387_YMM16H_REGNUM (tdep) + regnum
-                                          - num_lower_zmm_regs,
-                                          raw_buf);
-             if (status != REG_VALID)
-               mark_value_bytes_unavailable (result_value, 16, 16);
-             else
-               memcpy (buf + 16, raw_buf, 16);
-           }
+             /* Which register is it, relative to zmm16.  */
+             int i_16 = i_0 - num_lower_zmm_regs;
 
-         /* Read upper 256bits.  */
-         status = regcache->raw_read (tdep->zmm0h_regnum + regnum,
-                                      raw_buf);
-         if (status != REG_VALID)
-           mark_value_bytes_unavailable (result_value, 32, 32);
-         else
-           memcpy (buf + 32, raw_buf, 32);
+             return pseudo_from_concat_raw (next_frame, pseudo_reg_num,
+                                            I387_XMM16_REGNUM (tdep) + i_16,
+                                            I387_YMM16H_REGNUM (tdep) + i_16,
+                                            tdep->zmm0h_regnum + i_0);
+           }
        }
-      else if (i386_ymm_regnum_p (gdbarch, regnum))
+      else if (i386_ymm_regnum_p (gdbarch, pseudo_reg_num))
        {
-         regnum -= tdep->ymm0_regnum;
+         int i = pseudo_reg_num - tdep->ymm0_regnum;
 
-         /* Extract (always little endian).  Read lower 128bits.  */
-         status = regcache->raw_read (I387_XMM0_REGNUM (tdep) + regnum,
-                                      raw_buf);
-         if (status != REG_VALID)
-           mark_value_bytes_unavailable (result_value, 0, 16);
-         else
-           memcpy (buf, raw_buf, 16);
-         /* Read upper 128bits.  */
-         status = regcache->raw_read (tdep->ymm0h_regnum + regnum,
-                                      raw_buf);
-         if (status != REG_VALID)
-           mark_value_bytes_unavailable (result_value, 16, 32);
-         else
-           memcpy (buf + 16, raw_buf, 16);
+         return pseudo_from_concat_raw (next_frame, pseudo_reg_num,
+                                        I387_XMM0_REGNUM (tdep) + i,
+                                        tdep->ymm0h_regnum + i);
        }
-      else if (i386_ymm_avx512_regnum_p (gdbarch, regnum))
+      else if (i386_ymm_avx512_regnum_p (gdbarch, pseudo_reg_num))
        {
-         regnum -= tdep->ymm16_regnum;
-         /* Extract (always little endian).  Read lower 128bits.  */
-         status = regcache->raw_read (I387_XMM16_REGNUM (tdep) + regnum,
-                                      raw_buf);
-         if (status != REG_VALID)
-           mark_value_bytes_unavailable (result_value, 0, 16);
-         else
-           memcpy (buf, raw_buf, 16);
-         /* Read upper 128bits.  */
-         status = regcache->raw_read (tdep->ymm16h_regnum + regnum,
-                                      raw_buf);
-         if (status != REG_VALID)
-           mark_value_bytes_unavailable (result_value, 16, 16);
-         else
-           memcpy (buf + 16, raw_buf, 16);
+         int i = pseudo_reg_num - tdep->ymm16_regnum;
+
+         return pseudo_from_concat_raw (next_frame, pseudo_reg_num,
+                                        I387_XMM16_REGNUM (tdep) + i,
+                                        tdep->ymm16h_regnum + i);
        }
-      else if (i386_word_regnum_p (gdbarch, regnum))
+      else if (i386_word_regnum_p (gdbarch, pseudo_reg_num))
        {
-         int gpnum = regnum - tdep->ax_regnum;
+         int gpnum = pseudo_reg_num - tdep->ax_regnum;
 
          /* Extract (always little endian).  */
-         status = regcache->raw_read (gpnum, raw_buf);
-         if (status != REG_VALID)
-           mark_value_bytes_unavailable (result_value, 0,
-                                         TYPE_LENGTH (value_type (result_value)));
-         else
-           memcpy (buf, raw_buf, 2);
+         return pseudo_from_raw_part (next_frame, pseudo_reg_num, gpnum, 0);
        }
-      else if (i386_byte_regnum_p (gdbarch, regnum))
+      else if (i386_byte_regnum_p (gdbarch, pseudo_reg_num))
        {
-         int gpnum = regnum - tdep->al_regnum;
+         int gpnum = pseudo_reg_num - tdep->al_regnum;
 
          /* Extract (always little endian).  We read both lower and
             upper registers.  */
-         status = regcache->raw_read (gpnum % 4, raw_buf);
-         if (status != REG_VALID)
-           mark_value_bytes_unavailable (result_value, 0,
-                                         TYPE_LENGTH (value_type (result_value)));
-         else if (gpnum >= 4)
-           memcpy (buf, raw_buf + 1, 1);
-         else
-           memcpy (buf, raw_buf, 1);
+         return pseudo_from_raw_part (next_frame, pseudo_reg_num, gpnum % 4,
+                                      gpnum >= 4 ? 1 : 0);
        }
       else
-       internal_error (__FILE__, __LINE__, _("invalid regnum"));
+       internal_error (_("invalid regnum"));
     }
 }
 
-static struct value *
-i386_pseudo_register_read_value (struct gdbarch *gdbarch,
-                                readable_regcache *regcache,
-                                int regnum)
-{
-  struct value *result;
-
-  result = allocate_value (register_type (gdbarch, regnum));
-  VALUE_LVAL (result) = lval_register;
-  VALUE_REGNUM (result) = regnum;
-
-  i386_pseudo_register_read_into_value (gdbarch, regcache, regnum, result);
-
-  return result;
-}
-
 void
-i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
-                           int regnum, const gdb_byte *buf)
+i386_pseudo_register_write (gdbarch *gdbarch, const frame_info_ptr &next_frame,
+                           const int pseudo_reg_num,
+                           gdb::array_view<const gdb_byte> buf)
 {
-  gdb_byte raw_buf[I386_MAX_REGISTER_SIZE];
-
-  if (i386_mmx_regnum_p (gdbarch, regnum))
+  if (i386_mmx_regnum_p (gdbarch, pseudo_reg_num))
     {
-      int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
+      int fpnum = i386_mmx_regnum_to_fp_regnum (next_frame, pseudo_reg_num);
 
-      /* Read ...  */
-      regcache->raw_read (fpnum, raw_buf);
-      /* ... Modify ... (always little endian).  */
-      memcpy (raw_buf, buf, register_size (gdbarch, regnum));
-      /* ... Write.  */
-      regcache->raw_write (fpnum, raw_buf);
+      pseudo_to_raw_part (next_frame, buf, fpnum, 0);
     }
   else
     {
-      struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+      i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
-      if (i386_bnd_regnum_p (gdbarch, regnum))
+      if (i386_bnd_regnum_p (gdbarch, pseudo_reg_num))
        {
-         ULONGEST upper, lower;
-         int size = TYPE_LENGTH (builtin_type (gdbarch)->builtin_data_ptr);
-         enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
+         int size = builtin_type (gdbarch)->builtin_data_ptr->length ();
+         bfd_endian byte_order
+           = gdbarch_byte_order (current_inferior ()->arch ());
 
          /* New values from input value.  */
-         regnum -= tdep->bnd0_regnum;
-         lower = extract_unsigned_integer (buf, size, byte_order);
-         upper = extract_unsigned_integer (buf + size, size, byte_order);
-
-         /* Fetching register buffer.  */
-         regcache->raw_read (I387_BND0R_REGNUM (tdep) + regnum,
-                             raw_buf);
+         int reg_index = pseudo_reg_num - tdep->bnd0_regnum;
+         int raw_regnum = I387_BND0R_REGNUM (tdep) + reg_index;
 
-         upper = ~upper;
+         value *bndr_value = value_of_register (raw_regnum, next_frame);
+         gdb::array_view<gdb_byte> bndr_view
+           = bndr_value->contents_writeable ();
 
-         /* Set register bits.  */
-         memcpy (raw_buf, &lower, 8);
-         memcpy (raw_buf + 8, &upper, 8);
+         /* Copy lower bytes directly.  */
+         copy (buf.slice (0, size), bndr_view.slice (0, size));
 
-         regcache->raw_write (I387_BND0R_REGNUM (tdep) + regnum, raw_buf);
-       }
-      else if (i386_k_regnum_p (gdbarch, regnum))
-       {
-         regnum -= tdep->k0_regnum;
+         /* Convert and then copy upper bytes.  */
+         ULONGEST upper
+           = extract_unsigned_integer (buf.slice (size, size), byte_order);
+         upper = ~upper;
+         store_unsigned_integer (bndr_view.slice (8, size), byte_order,
+                                 upper);
 
-         regcache->raw_write (tdep->k0_regnum + regnum, buf);
+         put_frame_register (next_frame, raw_regnum, bndr_view);
        }
-      else if (i386_zmm_regnum_p (gdbarch, regnum))
+      else if (i386_zmm_regnum_p (gdbarch, pseudo_reg_num))
        {
-         regnum -= tdep->zmm0_regnum;
+         /* Which register is it, relative to zmm0.  */
+         int reg_index_0 = pseudo_reg_num - tdep->zmm0_regnum;
 
-         if (regnum < num_lower_zmm_regs)
-           {
-             /* Write lower 128bits.  */
-             regcache->raw_write (I387_XMM0_REGNUM (tdep) + regnum, buf);
-             /* Write upper 128bits.  */
-             regcache->raw_write (I387_YMM0_REGNUM (tdep) + regnum, buf + 16);
-           }
+         if (reg_index_0 < num_lower_zmm_regs)
+           pseudo_to_concat_raw (next_frame, buf,
+                                 I387_XMM0_REGNUM (tdep) + reg_index_0,
+                                 I387_YMM0_REGNUM (tdep) + reg_index_0,
+                                 tdep->zmm0h_regnum + reg_index_0);
          else
            {
-             /* Write lower 128bits.  */
-             regcache->raw_write (I387_XMM16_REGNUM (tdep) + regnum
-                                  - num_lower_zmm_regs, buf);
-             /* Write upper 128bits.  */
-             regcache->raw_write (I387_YMM16H_REGNUM (tdep) + regnum
-                                  - num_lower_zmm_regs, buf + 16);
+             /* Which register is it, relative to zmm16.  */
+             int reg_index_16 = reg_index_0 - num_lower_zmm_regs;
+
+             pseudo_to_concat_raw (next_frame, buf,
+                                   I387_XMM16_REGNUM (tdep) + reg_index_16,
+                                   I387_YMM16H_REGNUM (tdep) + reg_index_16,
+                                   tdep->zmm0h_regnum + +reg_index_0);
            }
-         /* Write upper 256bits.  */
-         regcache->raw_write (tdep->zmm0h_regnum + regnum, buf + 32);
        }
-      else if (i386_ymm_regnum_p (gdbarch, regnum))
+      else if (i386_ymm_regnum_p (gdbarch, pseudo_reg_num))
        {
-         regnum -= tdep->ymm0_regnum;
+         int i = pseudo_reg_num - tdep->ymm0_regnum;
 
-         /* ... Write lower 128bits.  */
-         regcache->raw_write (I387_XMM0_REGNUM (tdep) + regnum, buf);
-         /* ... Write upper 128bits.  */
-         regcache->raw_write (tdep->ymm0h_regnum + regnum, buf + 16);
+         pseudo_to_concat_raw (next_frame, buf, I387_XMM0_REGNUM (tdep) + i,
+                               tdep->ymm0h_regnum + i);
        }
-      else if (i386_ymm_avx512_regnum_p (gdbarch, regnum))
+      else if (i386_ymm_avx512_regnum_p (gdbarch, pseudo_reg_num))
        {
-         regnum -= tdep->ymm16_regnum;
+         int i = pseudo_reg_num - tdep->ymm16_regnum;
 
-         /* ... Write lower 128bits.  */
-         regcache->raw_write (I387_XMM16_REGNUM (tdep) + regnum, buf);
-         /* ... Write upper 128bits.  */
-         regcache->raw_write (tdep->ymm16h_regnum + regnum, buf + 16);
+         pseudo_to_concat_raw (next_frame, buf, I387_XMM16_REGNUM (tdep) + i,
+                               tdep->ymm16h_regnum + i);
        }
-      else if (i386_word_regnum_p (gdbarch, regnum))
+      else if (i386_word_regnum_p (gdbarch, pseudo_reg_num))
        {
-         int gpnum = regnum - tdep->ax_regnum;
+         int gpnum = pseudo_reg_num - tdep->ax_regnum;
 
-         /* Read ...  */
-         regcache->raw_read (gpnum, raw_buf);
-         /* ... Modify ... (always little endian).  */
-         memcpy (raw_buf, buf, 2);
-         /* ... Write.  */
-         regcache->raw_write (gpnum, raw_buf);
+         pseudo_to_raw_part (next_frame, buf, gpnum, 0);
        }
-      else if (i386_byte_regnum_p (gdbarch, regnum))
+      else if (i386_byte_regnum_p (gdbarch, pseudo_reg_num))
        {
-         int gpnum = regnum - tdep->al_regnum;
+         int gpnum = pseudo_reg_num - tdep->al_regnum;
 
-         /* Read ...  We read both lower and upper registers.  */
-         regcache->raw_read (gpnum % 4, raw_buf);
-         /* ... Modify ... (always little endian).  */
-         if (gpnum >= 4)
-           memcpy (raw_buf + 1, buf, 1);
-         else
-           memcpy (raw_buf, buf, 1);
-         /* ... Write.  */
-         regcache->raw_write (gpnum % 4, raw_buf);
+         pseudo_to_raw_part (next_frame, buf, gpnum % 4, gpnum >= 4 ? 1 : 0);
        }
       else
-       internal_error (__FILE__, __LINE__, _("invalid regnum"));
+       internal_error (_("invalid regnum"));
     }
 }
 
@@ -3619,7 +3615,7 @@ int
 i386_ax_pseudo_register_collect (struct gdbarch *gdbarch,
                                 struct agent_expr *ax, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   if (i386_mmx_regnum_p (gdbarch, regnum))
     {
@@ -3638,12 +3634,6 @@ i386_ax_pseudo_register_collect (struct gdbarch *gdbarch,
       ax_reg_mask (ax, I387_BND0R_REGNUM (tdep) + regnum);
       return 0;
     }
-  else if (i386_k_regnum_p (gdbarch, regnum))
-    {
-      regnum -= tdep->k0_regnum;
-      ax_reg_mask (ax, tdep->k0_regnum + regnum);
-      return 0;
-    }
   else if (i386_zmm_regnum_p (gdbarch, regnum))
     {
       regnum -= tdep->zmm0_regnum;
@@ -3691,7 +3681,7 @@ i386_ax_pseudo_register_collect (struct gdbarch *gdbarch,
       return 0;
     }
   else
-    internal_error (__FILE__, __LINE__, _("invalid regnum"));
+    internal_error (_("invalid regnum"));
   return 1;
 }
 \f
@@ -3732,7 +3722,7 @@ static int
 i386_convert_register_p (struct gdbarch *gdbarch,
                         int regnum, struct type *type)
 {
-  int len = TYPE_LENGTH (type);
+  int len = type->length ();
 
   /* Values may be spread across multiple registers.  Most debugging
      formats aren't expressive enough to specify the locations, so
@@ -3760,12 +3750,12 @@ i386_convert_register_p (struct gdbarch *gdbarch,
    return its contents in TO.  */
 
 static int
-i386_register_to_value (struct frame_info *frame, int regnum,
+i386_register_to_value (const frame_info_ptr &frame, int regnum,
                        struct type *type, gdb_byte *to,
                        int *optimizedp, int *unavailablep)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  int len = TYPE_LENGTH (type);
+  int len = type->length ();
 
   if (i386_fp_regnum_p (gdbarch, regnum))
     return i387_register_to_value (frame, regnum, type, to,
@@ -3780,9 +3770,11 @@ i386_register_to_value (struct frame_info *frame, int regnum,
       gdb_assert (regnum != -1);
       gdb_assert (register_size (gdbarch, regnum) == 4);
 
-      if (!get_frame_register_bytes (frame, regnum, 0,
-                                    register_size (gdbarch, regnum),
-                                    to, optimizedp, unavailablep))
+      auto to_view
+       = gdb::make_array_view (to, register_size (gdbarch, regnum));
+      frame_info_ptr next_frame = get_next_frame_sentinel_okay (frame);
+      if (!get_frame_register_bytes (next_frame, regnum, 0, to_view,
+                                    optimizedp, unavailablep))
        return 0;
 
       regnum = i386_next_regnum (regnum);
@@ -3798,10 +3790,10 @@ i386_register_to_value (struct frame_info *frame, int regnum,
    REGNUM in frame FRAME.  */
 
 static void
-i386_value_to_register (struct frame_info *frame, int regnum,
+i386_value_to_register (const frame_info_ptr &frame, int regnum,
                        struct type *type, const gdb_byte *from)
 {
-  int len = TYPE_LENGTH (type);
+  int len = type->length ();
 
   if (i386_fp_regnum_p (get_frame_arch (frame), regnum))
     {
@@ -3818,7 +3810,9 @@ i386_value_to_register (struct frame_info *frame, int regnum,
       gdb_assert (regnum != -1);
       gdb_assert (register_size (get_frame_arch (frame), regnum) == 4);
 
-      put_frame_register (frame, regnum, from);
+      auto from_view = gdb::make_array_view (from, 4);
+      put_frame_register (get_next_frame_sentinel_okay (frame), regnum,
+                         from_view);
       regnum = i386_next_regnum (regnum);
       len -= 4;
       from += 4;
@@ -3834,7 +3828,7 @@ i386_supply_gregset (const struct regset *regset, struct regcache *regcache,
                     int regnum, const void *gregs, size_t len)
 {
   struct gdbarch *gdbarch = regcache->arch ();
-  const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   const gdb_byte *regs = (const gdb_byte *) gregs;
   int i;
 
@@ -3859,7 +3853,7 @@ i386_collect_gregset (const struct regset *regset,
                      int regnum, void *gregs, size_t len)
 {
   struct gdbarch *gdbarch = regcache->arch ();
-  const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   gdb_byte *regs = (gdb_byte *) gregs;
   int i;
 
@@ -3882,7 +3876,7 @@ i386_supply_fpregset (const struct regset *regset, struct regcache *regcache,
                      int regnum, const void *fpregs, size_t len)
 {
   struct gdbarch *gdbarch = regcache->arch ();
-  const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   if (len == I387_SIZEOF_FXSAVE)
     {
@@ -3905,7 +3899,7 @@ i386_collect_fpregset (const struct regset *regset,
                       int regnum, void *fpregs, size_t len)
 {
   struct gdbarch *gdbarch = regcache->arch ();
-  const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   if (len == I387_SIZEOF_FXSAVE)
     {
@@ -3937,7 +3931,7 @@ i386_iterate_over_regset_sections (struct gdbarch *gdbarch,
                                   void *cb_data,
                                   const struct regcache *regcache)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   cb (".reg", tdep->sizeof_gregset, tdep->sizeof_gregset, &i386_gregset, NULL,
       cb_data);
@@ -3950,7 +3944,7 @@ i386_iterate_over_regset_sections (struct gdbarch *gdbarch,
 /* Stuff for WIN32 PE style DLL's but is pretty generic really.  */
 
 CORE_ADDR
-i386_pe_skip_trampoline_code (struct frame_info *frame,
+i386_pe_skip_trampoline_code (const frame_info_ptr &frame,
                              CORE_ADDR pc, char *name)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
@@ -3981,7 +3975,7 @@ i386_pe_skip_trampoline_code (struct frame_info *frame,
    routine.  */
 
 int
-i386_sigtramp_p (struct frame_info *this_frame)
+i386_sigtramp_p (const frame_info_ptr &this_frame)
 {
   CORE_ADDR pc = get_frame_pc (this_frame);
   const char *name;
@@ -4017,7 +4011,7 @@ i386_print_insn (bfd_vma pc, struct disassemble_info *info)
    routine.  */
 
 static int
-i386_svr4_sigtramp_p (struct frame_info *this_frame)
+i386_svr4_sigtramp_p (const frame_info_ptr &this_frame)
 {
   CORE_ADDR pc = get_frame_pc (this_frame);
   const char *name;
@@ -4032,7 +4026,7 @@ i386_svr4_sigtramp_p (struct frame_info *this_frame)
    address of the associated sigcontext (ucontext) structure.  */
 
 static CORE_ADDR
-i386_svr4_sigcontext_addr (struct frame_info *this_frame)
+i386_svr4_sigcontext_addr (const frame_info_ptr &this_frame)
 {
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
@@ -4067,7 +4061,7 @@ i386_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
    Return true if the operand was parsed successfully, false
    otherwise.  */
 
-static bool
+static expr::operation_up
 i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch,
                                       struct stap_parse_info *p)
 {
@@ -4079,9 +4073,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch,
       int i;
       long displacements[3];
       const char *start;
-      char *regname;
       int len;
-      struct stoken str;
       char *endp;
 
       got_minus[0] = false;
@@ -4094,7 +4086,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch,
        }
 
       if (!isdigit ((unsigned char) *s))
-       return false;
+       return {};
 
       displacements[0] = strtol (s, &endp, 10);
       s = endp;
@@ -4102,7 +4094,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch,
       if (*s != '+' && *s != '-')
        {
          /* We are not dealing with a triplet.  */
-         return false;
+         return {};
        }
 
       got_minus[1] = false;
@@ -4115,7 +4107,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch,
        }
 
       if (!isdigit ((unsigned char) *s))
-       return false;
+       return {};
 
       displacements[1] = strtol (s, &endp, 10);
       s = endp;
@@ -4123,7 +4115,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch,
       if (*s != '+' && *s != '-')
        {
          /* We are not dealing with a triplet.  */
-         return false;
+         return {};
        }
 
       got_minus[2] = false;
@@ -4136,13 +4128,13 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch,
        }
 
       if (!isdigit ((unsigned char) *s))
-       return false;
+       return {};
 
       displacements[2] = strtol (s, &endp, 10);
       s = endp;
 
       if (*s != '(' || s[1] != '%')
-       return false;
+       return {};
 
       s += 2;
       start = s;
@@ -4151,57 +4143,46 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch,
        ++s;
 
       if (*s++ != ')')
-       return false;
+       return {};
 
       len = s - start - 1;
-      regname = (char *) alloca (len + 1);
-
-      strncpy (regname, start, len);
-      regname[len] = '\0';
+      std::string regname (start, len);
 
-      if (user_reg_map_name_to_regnum (gdbarch, regname, len) == -1)
+      if (user_reg_map_name_to_regnum (gdbarch, regname.c_str (), len) == -1)
        error (_("Invalid register name `%s' on expression `%s'."),
-              regname, p->saved_arg);
+              regname.c_str (), p->saved_arg);
 
+      LONGEST value = 0;
       for (i = 0; i < 3; i++)
        {
-         write_exp_elt_opcode (&p->pstate, OP_LONG);
-         write_exp_elt_type
-           (&p->pstate, builtin_type (gdbarch)->builtin_long);
-         write_exp_elt_longcst (&p->pstate, displacements[i]);
-         write_exp_elt_opcode (&p->pstate, OP_LONG);
+         LONGEST this_val = displacements[i];
          if (got_minus[i])
-           write_exp_elt_opcode (&p->pstate, UNOP_NEG);
+           this_val = -this_val;
+         value += this_val;
        }
 
-      write_exp_elt_opcode (&p->pstate, OP_REGISTER);
-      str.ptr = regname;
-      str.length = len;
-      write_exp_string (&p->pstate, str);
-      write_exp_elt_opcode (&p->pstate, OP_REGISTER);
-
-      write_exp_elt_opcode (&p->pstate, UNOP_CAST);
-      write_exp_elt_type (&p->pstate,
-                         builtin_type (gdbarch)->builtin_data_ptr);
-      write_exp_elt_opcode (&p->pstate, UNOP_CAST);
-
-      write_exp_elt_opcode (&p->pstate, BINOP_ADD);
-      write_exp_elt_opcode (&p->pstate, BINOP_ADD);
-      write_exp_elt_opcode (&p->pstate, BINOP_ADD);
+      p->arg = s;
 
-      write_exp_elt_opcode (&p->pstate, UNOP_CAST);
-      write_exp_elt_type (&p->pstate,
-                         lookup_pointer_type (p->arg_type));
-      write_exp_elt_opcode (&p->pstate, UNOP_CAST);
+      using namespace expr;
 
-      write_exp_elt_opcode (&p->pstate, UNOP_IND);
+      struct type *long_type = builtin_type (gdbarch)->builtin_long;
+      operation_up offset
+       = make_operation<long_const_operation> (long_type, value);
 
-      p->arg = s;
+      operation_up reg
+       = make_operation<register_operation> (std::move (regname));
+      struct type *void_ptr = builtin_type (gdbarch)->builtin_data_ptr;
+      reg = make_operation<unop_cast_operation> (std::move (reg), void_ptr);
 
-      return true;
+      operation_up sum
+       = make_operation<add_operation> (std::move (reg), std::move (offset));
+      struct type *arg_ptr_type = lookup_pointer_type (p->arg_type);
+      sum = make_operation<unop_cast_operation> (std::move (sum),
+                                                arg_ptr_type);
+      return make_operation<unop_ind_operation> (std::move (sum));
     }
 
-  return false;
+  return {};
 }
 
 /* Helper function for i386_stap_parse_special_token.
@@ -4213,7 +4194,7 @@ i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch,
    Return true if the operand was parsed successfully, false
    otherwise.  */
 
-static bool
+static expr::operation_up
 i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch,
                                              struct stap_parse_info *p)
 {
@@ -4226,11 +4207,8 @@ i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch,
       bool size_minus = false;
       long size = 0;
       const char *start;
-      char *base;
       int len_base;
-      char *index;
       int len_index;
-      struct stoken base_token, index_token;
 
       if (*s == '+')
        ++s;
@@ -4241,7 +4219,7 @@ i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch,
        }
 
       if (offset_minus && !isdigit (*s))
-       return false;
+       return {};
 
       if (isdigit (*s))
        {
@@ -4252,7 +4230,7 @@ i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch,
        }
 
       if (*s != '(' || s[1] != '%')
-       return false;
+       return {};
 
       s += 2;
       start = s;
@@ -4261,16 +4239,14 @@ i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch,
        ++s;
 
       if (*s != ',' || s[1] != '%')
-       return false;
+       return {};
 
       len_base = s - start;
-      base = (char *) alloca (len_base + 1);
-      strncpy (base, start, len_base);
-      base[len_base] = '\0';
+      std::string base (start, len_base);
 
-      if (user_reg_map_name_to_regnum (gdbarch, base, len_base) == -1)
+      if (user_reg_map_name_to_regnum (gdbarch, base.c_str (), len_base) == -1)
        error (_("Invalid register name `%s' on expression `%s'."),
-              base, p->saved_arg);
+              base.c_str (), p->saved_arg);
 
       s += 2;
       start = s;
@@ -4279,16 +4255,15 @@ i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch,
        ++s;
 
       len_index = s - start;
-      index = (char *) alloca (len_index + 1);
-      strncpy (index, start, len_index);
-      index[len_index] = '\0';
+      std::string index (start, len_index);
 
-      if (user_reg_map_name_to_regnum (gdbarch, index, len_index) == -1)
+      if (user_reg_map_name_to_regnum (gdbarch, index.c_str (),
+                                      len_index) == -1)
        error (_("Invalid register name `%s' on expression `%s'."),
-              index, p->saved_arg);
+              index.c_str (), p->saved_arg);
 
       if (*s != ',' && *s != ')')
-       return false;
+       return {};
 
       if (*s == ',')
        {
@@ -4307,85 +4282,60 @@ i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch,
          s = endp;
 
          if (*s != ')')
-           return false;
+           return {};
        }
 
       ++s;
+      p->arg = s;
+
+      using namespace expr;
+
+      struct type *long_type = builtin_type (gdbarch)->builtin_long;
+      operation_up reg = make_operation<register_operation> (std::move (base));
 
-      if (offset)
+      if (offset != 0)
        {
-         write_exp_elt_opcode (&p->pstate, OP_LONG);
-         write_exp_elt_type (&p->pstate,
-                             builtin_type (gdbarch)->builtin_long);
-         write_exp_elt_longcst (&p->pstate, offset);
-         write_exp_elt_opcode (&p->pstate, OP_LONG);
          if (offset_minus)
-           write_exp_elt_opcode (&p->pstate, UNOP_NEG);
+           offset = -offset;
+         operation_up value
+           = make_operation<long_const_operation> (long_type, offset);
+         reg = make_operation<add_operation> (std::move (reg),
+                                              std::move (value));
        }
 
-      write_exp_elt_opcode (&p->pstate, OP_REGISTER);
-      base_token.ptr = base;
-      base_token.length = len_base;
-      write_exp_string (&p->pstate, base_token);
-      write_exp_elt_opcode (&p->pstate, OP_REGISTER);
+      operation_up ind_reg
+       = make_operation<register_operation> (std::move (index));
 
-      if (offset)
-       write_exp_elt_opcode (&p->pstate, BINOP_ADD);
-
-      write_exp_elt_opcode (&p->pstate, OP_REGISTER);
-      index_token.ptr = index;
-      index_token.length = len_index;
-      write_exp_string (&p->pstate, index_token);
-      write_exp_elt_opcode (&p->pstate, OP_REGISTER);
-
-      if (size)
+      if (size != 0)
        {
-         write_exp_elt_opcode (&p->pstate, OP_LONG);
-         write_exp_elt_type (&p->pstate,
-                             builtin_type (gdbarch)->builtin_long);
-         write_exp_elt_longcst (&p->pstate, size);
-         write_exp_elt_opcode (&p->pstate, OP_LONG);
          if (size_minus)
-           write_exp_elt_opcode (&p->pstate, UNOP_NEG);
-         write_exp_elt_opcode (&p->pstate, BINOP_MUL);
+           size = -size;
+         operation_up value
+           = make_operation<long_const_operation> (long_type, size);
+         ind_reg = make_operation<mul_operation> (std::move (ind_reg),
+                                                  std::move (value));
        }
 
-      write_exp_elt_opcode (&p->pstate, BINOP_ADD);
-
-      write_exp_elt_opcode (&p->pstate, UNOP_CAST);
-      write_exp_elt_type (&p->pstate,
-                         lookup_pointer_type (p->arg_type));
-      write_exp_elt_opcode (&p->pstate, UNOP_CAST);
-
-      write_exp_elt_opcode (&p->pstate, UNOP_IND);
+      operation_up sum
+       = make_operation<add_operation> (std::move (reg),
+                                        std::move (ind_reg));
 
-      p->arg = s;
-
-      return true;
+      struct type *arg_ptr_type = lookup_pointer_type (p->arg_type);
+      sum = make_operation<unop_cast_operation> (std::move (sum),
+                                                arg_ptr_type);
+      return make_operation<unop_ind_operation> (std::move (sum));
     }
 
-  return false;
+  return {};
 }
 
 /* Implementation of `gdbarch_stap_parse_special_token', as defined in
    gdbarch.h.  */
 
-int
+expr::operation_up
 i386_stap_parse_special_token (struct gdbarch *gdbarch,
                               struct stap_parse_info *p)
 {
-  /* In order to parse special tokens, we use a state-machine that go
-     through every known token and try to get a match.  */
-  enum
-    {
-      TRIPLET,
-      THREE_ARG_DISPLACEMENT,
-      DONE
-    };
-  int current_state;
-
-  current_state = TRIPLET;
-
   /* The special tokens to be parsed here are:
 
      - `register base + (register index * size) + offset', as represented
@@ -4394,26 +4344,13 @@ i386_stap_parse_special_token (struct gdbarch *gdbarch,
      - Operands of the form `-8+3+1(%rbp)', which must be interpreted as
      `*(-8 + 3 - 1 + (void *) $eax)'.  */
 
-  while (current_state != DONE)
-    {
-      switch (current_state)
-       {
-       case TRIPLET:
-         if (i386_stap_parse_special_token_triplet (gdbarch, p))
-           return 1;
-         break;
-
-       case THREE_ARG_DISPLACEMENT:
-         if (i386_stap_parse_special_token_three_arg_disp (gdbarch, p))
-           return 1;
-         break;
-       }
+  expr::operation_up result
+    = i386_stap_parse_special_token_triplet (gdbarch, p);
 
-      /* Advancing to the next state.  */
-      ++current_state;
-    }
+  if (result == nullptr)
+    result = i386_stap_parse_special_token_three_arg_disp (gdbarch, p);
 
-  return 0;
+  return result;
 }
 
 /* Implementation of 'gdbarch_stap_adjust_register', as defined in
@@ -4431,7 +4368,7 @@ i386_stap_adjust_register (struct gdbarch *gdbarch, struct stap_parse_info *p,
      specified by the "[-]N@" prefix, and it is one of the registers that
      we know has an extended variant available, then use the extended
      version of the register instead.  */
-  if (register_size (gdbarch, regnum) < TYPE_LENGTH (p->arg_type)
+  if (register_size (gdbarch, regnum) < p->arg_type->length ()
       && reg_assoc.find (regname) != reg_assoc.end ())
     return "e" + regname;
 
@@ -4499,7 +4436,7 @@ i386_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 void
 i386_svr4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   /* System V Release 4 uses ELF.  */
   i386_elf_init_abi (info, gdbarch);
@@ -4520,8 +4457,8 @@ i386_svr4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 /* i386 register groups.  In addition to the normal groups, add "mmx"
    and "sse".  */
 
-static struct reggroup *i386_sse_reggroup;
-static struct reggroup *i386_mmx_reggroup;
+static const reggroup *i386_sse_reggroup;
+static const reggroup *i386_mmx_reggroup;
 
 static void
 i386_init_reggroups (void)
@@ -4535,20 +4472,13 @@ i386_add_reggroups (struct gdbarch *gdbarch)
 {
   reggroup_add (gdbarch, i386_sse_reggroup);
   reggroup_add (gdbarch, i386_mmx_reggroup);
-  reggroup_add (gdbarch, general_reggroup);
-  reggroup_add (gdbarch, float_reggroup);
-  reggroup_add (gdbarch, all_reggroup);
-  reggroup_add (gdbarch, save_reggroup);
-  reggroup_add (gdbarch, restore_reggroup);
-  reggroup_add (gdbarch, vector_reggroup);
-  reggroup_add (gdbarch, system_reggroup);
 }
 
 int
 i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
-                         struct reggroup *group)
+                         const struct reggroup *group)
 {
-  const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int fp_regnum_p, mmx_regnum_p, xmm_regnum_p, mxcsr_regnum_p,
       ymm_regnum_p, ymmh_regnum_p, ymm_avx512_regnum_p, ymmh_avx512_regnum_p,
       bndr_regnum_p, bnd_regnum_p, zmm_regnum_p, zmmh_regnum_p,
@@ -4652,7 +4582,7 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
 /* Get the ARGIth function argument for the current function.  */
 
 static CORE_ADDR
-i386_fetch_pointer_argument (struct frame_info *frame, int argi, 
+i386_fetch_pointer_argument (const frame_info_ptr &frame, int argi,
                             struct type *type)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
@@ -4993,7 +4923,7 @@ static int i386_record_floats (struct gdbarch *gdbarch,
                               struct i386_record_s *ir,
                               uint32_t iregnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   int i;
 
   /* Oza: Because of floating point insn push/pop of fpu stack is going to
@@ -5020,10 +4950,8 @@ static int i386_record_floats (struct gdbarch *gdbarch,
   else if (I386_SAVE_FPU_ENV_REG_STACK == iregnum)
     {
       for (i = I387_ST0_REGNUM (tdep); i <= I387_FOP_REGNUM (tdep); i++)
-      {
        if (record_full_arch_list_add_reg (ir->regcache, i))
          return -1;
-      }
     }
   else if ((iregnum >= I387_ST0_REGNUM (tdep)) &&
           (iregnum <= I387_FOP_REGNUM (tdep)))
@@ -5066,7 +4994,7 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
   ULONGEST addr;
   gdb_byte buf[I386_MAX_REGISTER_SIZE];
   struct i386_record_s ir;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
   uint8_t rex_w = -1;
   uint8_t rex_r = 0;
 
@@ -5082,9 +5010,9 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
   ir.gdbarch = gdbarch;
 
   if (record_debug > 1)
-    fprintf_unfiltered (gdb_stdlog, "Process record: i386_process_record "
-                                   "addr = %s\n",
-                       paddress (gdbarch, ir.addr));
+    gdb_printf (gdb_stdlog, "Process record: i386_process_record "
+               "addr = %s\n",
+               paddress (gdbarch, ir.addr));
 
   /* prefixes */
   while (1)
@@ -5634,7 +5562,7 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
          ir.addr -= 1;
          goto no_support;
        }
-      for (regnum = X86_RECORD_REAX_REGNUM; 
+      for (regnum = X86_RECORD_REAX_REGNUM;
           regnum <= X86_RECORD_REDI_REGNUM;
           regnum++)
        I386_RECORD_FULL_ARCH_LIST_ADD_REG (regnum);
@@ -5955,7 +5883,7 @@ Do you want to stop the program?"),
          ir.addr -= 1;
          goto no_support;
        }
-      /* FALLTHROUGH */
+      [[fallthrough]];
     case 0x0fb2:    /* lss Gv */
     case 0x0fb4:    /* lfs Gv */
     case 0x0fb5:    /* lgs Gv */
@@ -6192,7 +6120,7 @@ Do you want to stop the program?"),
                                                  I386_SAVE_FPU_REGS))
                            return -1;
                        }
-                     /* Fall through */
+                     [[fallthrough]];
                    default:
                      if (record_full_arch_list_add_mem (addr64, 2))
                        return -1;
@@ -6731,7 +6659,7 @@ Do you want to stop the program?"),
          ir.addr -= 1;
          goto no_support;
        }
-      /* FALLTHROUGH */
+      [[fallthrough]];
     case 0xf5:    /* cmc */
     case 0xf8:    /* clc */
     case 0xf9:    /* stc */
@@ -6855,8 +6783,9 @@ Do you want to stop the program?"),
 
       /* XXX */
     case 0xcc:    /* int3 */
-      printf_unfiltered (_("Process record does not support instruction "
-                          "int3.\n"));
+      gdb_printf (gdb_stderr,
+                 _("Process record does not support instruction "
+                   "int3.\n"));
       ir.addr -= 1;
       goto no_support;
       break;
@@ -6872,9 +6801,10 @@ Do you want to stop the program?"),
        if (interrupt != 0x80
            || tdep->i386_intx80_record == NULL)
          {
-           printf_unfiltered (_("Process record does not support "
-                                "instruction int 0x%02x.\n"),
-                              interrupt);
+           gdb_printf (gdb_stderr,
+                       _("Process record does not support "
+                         "instruction int 0x%02x.\n"),
+                       interrupt);
            ir.addr -= 2;
            goto no_support;
          }
@@ -6886,8 +6816,9 @@ Do you want to stop the program?"),
 
       /* XXX */
     case 0xce:    /* into */
-      printf_unfiltered (_("Process record does not support "
-                          "instruction into.\n"));
+      gdb_printf (gdb_stderr,
+                 _("Process record does not support "
+                   "instruction into.\n"));
       ir.addr -= 1;
       goto no_support;
       break;
@@ -6897,8 +6828,9 @@ Do you want to stop the program?"),
       break;
 
     case 0x62:    /* bound */
-      printf_unfiltered (_("Process record does not support "
-                          "instruction bound.\n"));
+      gdb_printf (gdb_stderr,
+                 _("Process record does not support "
+                   "instruction bound.\n"));
       ir.addr -= 1;
       goto no_support;
       break;
@@ -6933,19 +6865,24 @@ Do you want to stop the program?"),
       break;
 
     case 0x0f30:    /* wrmsr */
-      printf_unfiltered (_("Process record does not support "
-                          "instruction wrmsr.\n"));
+      gdb_printf (gdb_stderr,
+                 _("Process record does not support "
+                   "instruction wrmsr.\n"));
       ir.addr -= 2;
       goto no_support;
       break;
 
     case 0x0f32:    /* rdmsr */
-      printf_unfiltered (_("Process record does not support "
-                          "instruction rdmsr.\n"));
+      gdb_printf (gdb_stderr,
+                 _("Process record does not support "
+                   "instruction rdmsr.\n"));
       ir.addr -= 2;
       goto no_support;
       break;
 
+    case 0x0f01f9:  /* rdtscp */
+      I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM);
+      [[fallthrough]];
     case 0x0f31:    /* rdtsc */
       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REDX_REGNUM);
@@ -6961,8 +6898,9 @@ Do you want to stop the program?"),
          }
        if (tdep->i386_sysenter_record == NULL)
          {
-           printf_unfiltered (_("Process record does not support "
-                                "instruction sysenter.\n"));
+           gdb_printf (gdb_stderr,
+                       _("Process record does not support "
+                         "instruction sysenter.\n"));
            ir.addr -= 2;
            goto no_support;
          }
@@ -6973,8 +6911,9 @@ Do you want to stop the program?"),
       break;
 
     case 0x0f35:    /* sysexit */
-      printf_unfiltered (_("Process record does not support "
-                          "instruction sysexit.\n"));
+      gdb_printf (gdb_stderr,
+                 _("Process record does not support "
+                   "instruction sysexit.\n"));
       ir.addr -= 2;
       goto no_support;
       break;
@@ -6984,8 +6923,9 @@ Do you want to stop the program?"),
        int ret;
        if (tdep->i386_syscall_record == NULL)
          {
-           printf_unfiltered (_("Process record does not support "
-                                "instruction syscall.\n"));
+           gdb_printf (gdb_stderr,
+                       _("Process record does not support "
+                         "instruction syscall.\n"));
            ir.addr -= 2;
            goto no_support;
          }
@@ -6996,8 +6936,9 @@ Do you want to stop the program?"),
       break;
 
     case 0x0f07:    /* sysret */
-      printf_unfiltered (_("Process record does not support "
-                          "instruction sysret.\n"));
+      gdb_printf (gdb_stderr,
+                 _("Process record does not support "
+                   "instruction sysret.\n"));
       ir.addr -= 2;
       goto no_support;
       break;
@@ -7010,8 +6951,9 @@ Do you want to stop the program?"),
       break;
 
     case 0xf4:    /* hlt */
-      printf_unfiltered (_("Process record does not support "
-                          "instruction hlt.\n"));
+      gdb_printf (gdb_stderr,
+                 _("Process record does not support "
+                   "instruction hlt.\n"));
       ir.addr -= 1;
       goto no_support;
       break;
@@ -7050,6 +6992,11 @@ Do you want to stop the program?"),
     case 0x0f01:
       if (i386_record_modrm (&ir))
        return -1;
+      if (ir.modrm == 0xf9)
+       {
+         opcode = (opcode << 8) | 0xf9;
+         goto reswitch;
+       }
       switch (ir.reg)
        {
        case 0:  /* sgdt */
@@ -7162,7 +7109,7 @@ Do you want to stop the program?"),
              else if (ir.rm == 1)
                break;
            }
-         /* Fall through.  */
+         [[fallthrough]];
        case 3:  /* lidt */
          if (ir.mod == 3)
            {
@@ -8129,10 +8076,11 @@ reswitch_prefix_add:
   return 0;
 
  no_support:
-  printf_unfiltered (_("Process record does not support instruction 0x%02x "
-                      "at address %s.\n"),
-                    (unsigned int) (opcode),
-                    paddress (gdbarch, ir.orig_addr));
+  gdb_printf (gdb_stderr,
+             _("Process record does not support instruction 0x%02x "
+               "at address %s.\n"),
+             (unsigned int) (opcode),
+             paddress (gdbarch, ir.orig_addr));
   return -1;
 }
 
@@ -8216,16 +8164,87 @@ i386_floatformat_for_type (struct gdbarch *gdbarch,
        || strcmp (name, "_Float128") == 0
        || strcmp (name, "complex _Float128") == 0
        || strcmp (name, "complex(kind=16)") == 0
+       || strcmp (name, "COMPLEX(16)") == 0
+       || strcmp (name, "complex*32") == 0
+       || strcmp (name, "COMPLEX*32") == 0
        || strcmp (name, "quad complex") == 0
        || strcmp (name, "real(kind=16)") == 0
-       || strcmp (name, "real*16") == 0)
-      return floatformats_ia64_quad;
+       || strcmp (name, "real*16") == 0
+       || strcmp (name, "REAL*16") == 0
+       || strcmp (name, "REAL(16)") == 0)
+      return floatformats_ieee_quad;
 
   return default_floatformat_for_type (gdbarch, name, len);
 }
 
+/* Compute an XCR0 mask based on a target description.  */
+
+static uint64_t
+i386_xcr0_from_tdesc (const struct target_desc *tdesc)
+{
+  if (! tdesc_has_registers (tdesc))
+    return 0;
+
+  const struct tdesc_feature *feature_core;
+
+  const struct tdesc_feature *feature_sse, *feature_avx, *feature_mpx,
+                            *feature_avx512, *feature_pkeys;
+
+  /* Get core registers.  */
+  feature_core = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.core");
+  if (feature_core == NULL)
+    return 0;
+
+  /* Get SSE registers.  */
+  feature_sse = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.sse");
+
+  /* Try AVX registers.  */
+  feature_avx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx");
+
+  /* Try MPX registers.  */
+  feature_mpx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.mpx");
+
+  /* Try AVX512 registers.  */
+  feature_avx512 = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx512");
+
+  /* Try PKEYS  */
+  feature_pkeys = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.pkeys");
+
+  /* The XCR0 bits.  */
+  uint64_t xcr0 = X86_XSTATE_X87;
+
+  if (feature_sse)
+    xcr0 |= X86_XSTATE_SSE;
+
+  if (feature_avx)
+    {
+      /* AVX register description requires SSE register description.  */
+      if (!feature_sse)
+       return 0;
+
+      xcr0 |= X86_XSTATE_AVX;
+    }
+
+  if (feature_mpx)
+    xcr0 |= X86_XSTATE_MPX_MASK;
+
+  if (feature_avx512)
+    {
+      /* AVX512 register description requires AVX register description.  */
+      if (!feature_avx)
+       return 0;
+
+      xcr0 |= X86_XSTATE_AVX512;
+    }
+
+  if (feature_pkeys)
+    xcr0 |= X86_XSTATE_PKRU;
+
+  return xcr0;
+}
+
 static int
-i386_validate_tdesc_p (struct gdbarch_tdep *tdep,
+i386_validate_tdesc_p (i386_gdbarch_tdep *tdep,
                       struct tdesc_arch_data *tdesc_data)
 {
   const struct target_desc *tdesc = tdep->tdesc;
@@ -8409,12 +8428,12 @@ i386_type_align (struct gdbarch *gdbarch, struct type *type)
     {
       if ((type->code () == TYPE_CODE_INT
           || type->code () == TYPE_CODE_FLT)
-         && TYPE_LENGTH (type) > 4)
+         && type->length () > 4)
        return 4;
 
       /* Handle x86's funny long double.  */
       if (type->code () == TYPE_CODE_FLT
-         && gdbarch_long_double_bit (gdbarch) == TYPE_LENGTH (type) * 8)
+         && gdbarch_long_double_bit (gdbarch) == type->length () * 8)
        return 4;
     }
 
@@ -8427,22 +8446,41 @@ i386_type_align (struct gdbarch *gdbarch, struct type *type)
 static struct gdbarch *
 i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
-  struct gdbarch_tdep *tdep;
-  struct gdbarch *gdbarch;
   const struct target_desc *tdesc;
   int mm0_regnum;
   int ymm0_regnum;
   int bnd0_regnum;
   int num_bnd_cooked;
 
+  x86_xsave_layout xsave_layout = target_fetch_x86_xsave_layout ();
+
+  /* If the target did not provide an XSAVE layout but the target
+     description includes registers from the XSAVE extended region,
+     use a fallback XSAVE layout.  Specifically, this fallback layout
+     is used when writing out a local core dump for a remote
+     target.  */
+  if (xsave_layout.sizeof_xsave == 0)
+    xsave_layout
+      = i387_fallback_xsave_layout (i386_xcr0_from_tdesc (info.target_desc));
+
   /* If there is already a candidate, use it.  */
-  arches = gdbarch_list_lookup_by_info (arches, &info);
-  if (arches != NULL)
-    return arches->gdbarch;
+  for (arches = gdbarch_list_lookup_by_info (arches, &info);
+       arches != NULL;
+       arches = gdbarch_list_lookup_by_info (arches->next, &info))
+    {
+      /* Check that the XSAVE layout of ARCHES matches the layout for
+        the current target.  */
+      i386_gdbarch_tdep *other_tdep
+       = gdbarch_tdep<i386_gdbarch_tdep> (arches->gdbarch);
+
+      if (other_tdep->xsave_layout == xsave_layout)
+       return arches->gdbarch;
+    }
 
   /* Allocate space for the new architecture.  Assume i386 for now.  */
-  tdep = XCNEW (struct gdbarch_tdep);
-  gdbarch = gdbarch_alloc (&info, tdep);
+  gdbarch *gdbarch
+    = gdbarch_alloc (&info, gdbarch_tdep_up (new i386_gdbarch_tdep));
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
 
   /* General-purpose registers.  */
   tdep->gregset_reg_offset = NULL;
@@ -8557,7 +8595,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_register_to_value (gdbarch,  i386_register_to_value);
   set_gdbarch_value_to_register (gdbarch, i386_value_to_register);
 
-  set_gdbarch_return_value (gdbarch, i386_return_value);
+  set_gdbarch_return_value_as_value (gdbarch, i386_return_value);
 
   set_gdbarch_skip_prologue (gdbarch, i386_skip_prologue);
 
@@ -8586,16 +8624,20 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_fetch_pointer_argument (gdbarch, i386_fetch_pointer_argument);
 
   /* Hook the function epilogue frame unwinder.  This unwinder is
-     appended to the list first, so that it supercedes the DWARF
+     appended to the list first, so that it supersedes the DWARF
      unwinder in function epilogues (where the DWARF unwinder
      currently fails).  */
-  frame_unwind_append_unwinder (gdbarch, &i386_epilogue_frame_unwind);
+  if (info.bfd_arch_info->bits_per_word == 32)
+    frame_unwind_append_unwinder (gdbarch, &i386_epilogue_override_frame_unwind);
 
   /* Hook in the DWARF CFI frame unwinder.  This unwinder is appended
      to the list before the prologue-based unwinders, so that DWARF
      CFI info will be used if it is available.  */
   dwarf2_append_unwinders (gdbarch);
 
+  if (info.bfd_arch_info->bits_per_word == 32)
+    frame_unwind_append_unwinder (gdbarch, &i386_epilogue_frame_unwind);
+
   frame_base_set_default (gdbarch, &i386_frame_base);
 
   /* Pseudo registers may be changed by amd64_init_abi.  */
@@ -8685,10 +8727,10 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   if (!i386_validate_tdesc_p (tdep, tdesc_data.get ()))
     {
-      xfree (tdep);
       gdbarch_free (gdbarch);
       return NULL;
     }
+  tdep->xsave_layout = xsave_layout;
 
   num_bnd_cooked = (tdep->bnd0r_regnum > 0 ? I387_NUM_BND_REGS : 0);
 
@@ -8769,9 +8811,12 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     tdep-> bnd0_regnum = -1;
 
   /* Hook in the legacy prologue-based unwinders last (fallback).  */
-  frame_unwind_append_unwinder (gdbarch, &i386_stack_tramp_frame_unwind);
-  frame_unwind_append_unwinder (gdbarch, &i386_sigtramp_frame_unwind);
-  frame_unwind_append_unwinder (gdbarch, &i386_frame_unwind);
+  if (info.bfd_arch_info->bits_per_word == 32)
+    {
+      frame_unwind_append_unwinder (gdbarch, &i386_stack_tramp_frame_unwind);
+      frame_unwind_append_unwinder (gdbarch, &i386_sigtramp_frame_unwind);
+      frame_unwind_append_unwinder (gdbarch, &i386_frame_unwind);
+    }
 
   /* If we have a register mapping, enable the generic core file
      support, unless it has already been enabled.  */
@@ -8817,13 +8862,12 @@ i386_target_description (uint64_t xcr0, bool segments)
 static unsigned long
 i386_mpx_bd_base (void)
 {
-  struct regcache *rcache;
-  struct gdbarch_tdep *tdep;
   ULONGEST ret;
   enum register_status regstatus;
 
-  rcache = get_current_regcache ();
-  tdep = gdbarch_tdep (rcache->arch ());
+  regcache *rcache = get_thread_regcache (inferior_thread ());
+  gdbarch *arch = rcache->arch ();
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (arch);
 
   regstatus = regcache_raw_read_unsigned (rcache, tdep->bndcfgu_regnum, &ret);
 
@@ -8836,7 +8880,8 @@ i386_mpx_bd_base (void)
 int
 i386_mpx_enabled (void)
 {
-  const struct gdbarch_tdep *tdep = gdbarch_tdep (get_current_arch ());
+  gdbarch *arch = get_current_arch ();
+  i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (arch);
   const struct target_desc *tdesc = tdep->tdesc;
 
   return (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.mpx") != NULL);
@@ -8968,14 +9013,14 @@ i386_mpx_info_bounds (const char *args, int from_tty)
   if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_i386
       || !i386_mpx_enabled ())
     {
-      printf_unfiltered (_("Intel Memory Protection Extensions not "
-                          "supported on this target.\n"));
+      gdb_printf (_("Intel Memory Protection Extensions not "
+                   "supported on this target.\n"));
       return;
     }
 
   if (args == NULL)
     {
-      printf_unfiltered (_("Address of pointer variable expected.\n"));
+      gdb_printf (_("Address of pointer variable expected.\n"));
       return;
     }
 
@@ -8988,7 +9033,7 @@ i386_mpx_info_bounds (const char *args, int from_tty)
 
   for (i = 0; i < 4; i++)
     bt_entry[i] = read_memory_typed_address (bt_entry_addr
-                                            + i * TYPE_LENGTH (data_ptr_type),
+                                            + i * data_ptr_type->length (),
                                             data_ptr_type);
 
   i386_mpx_print_bounds (bt_entry);
@@ -9035,15 +9080,15 @@ i386_mpx_set_bounds (const char *args, int from_tty)
   bt_entry_addr = i386_mpx_get_bt_entry (addr, bd_base);
   for (i = 0; i < 2; i++)
     bt_entry[i] = read_memory_typed_address (bt_entry_addr
-                                            + i * TYPE_LENGTH (data_ptr_type),
+                                            + i * data_ptr_type->length (),
                                             data_ptr_type);
   bt_entry[0] = (uint64_t) lower;
   bt_entry[1] = ~(uint64_t) upper;
 
   for (i = 0; i < 2; i++)
     write_memory_unsigned_integer (bt_entry_addr
-                                  + i * TYPE_LENGTH (data_ptr_type),
-                                  TYPE_LENGTH (data_ptr_type), byte_order,
+                                  + i * data_ptr_type->length (),
+                                  data_ptr_type->length (), byte_order,
                                   bt_entry[i]);
 }
 
@@ -9053,7 +9098,7 @@ void _initialize_i386_tdep ();
 void
 _initialize_i386_tdep ()
 {
-  register_gdbarch_init (bfd_arch_i386, i386_gdbarch_init);
+  gdbarch_register (bfd_arch_i386, i386_gdbarch_init);
 
   /* Add the variable that controls the disassembly flavor.  */
   add_setshow_enum_cmd ("disassembly-flavor", no_class, valid_flavors,
@@ -9077,33 +9122,29 @@ is \"default\"."),
                        NULL, /* FIXME: i18n: */
                        &setlist, &showlist);
 
-  /* Add "mpx" prefix for the set commands.  */
-
-  add_basic_prefix_cmd ("mpx", class_support, _("\
-Set Intel Memory Protection Extensions specific variables."),
-                       &mpx_set_cmdlist, "set mpx ",
-                       0 /* allow-unknown */, &setlist);
-
-  /* Add "mpx" prefix for the show commands.  */
+  /* Add "mpx" prefix for the set and show commands.  */
 
-  add_show_prefix_cmd ("mpx", class_support, _("\
-Show Intel Memory Protection Extensions specific variables."),
-                      &mpx_show_cmdlist, "show mpx ",
-                      0 /* allow-unknown */, &showlist);
+  add_setshow_prefix_cmd
+    ("mpx", class_support,
+     _("Set Intel Memory Protection Extensions specific variables."),
+     _("Show Intel Memory Protection Extensions specific variables."),
+     &mpx_set_cmdlist, &mpx_show_cmdlist, &setlist, &showlist);
 
   /* Add "bound" command for the show mpx commands list.  */
 
-  add_cmd ("bound", no_class, i386_mpx_info_bounds,
+  cmd_list_element *c = add_cmd ("bound", no_class, i386_mpx_info_bounds,
           "Show the memory bounds for a given array/pointer storage\
  in the bound table.",
           &mpx_show_cmdlist);
+  deprecate_cmd (c, nullptr);
 
   /* Add "bound" command for the set mpx commands list.  */
 
-  add_cmd ("bound", no_class, i386_mpx_set_bounds,
+  c = add_cmd ("bound", no_class, i386_mpx_set_bounds,
           "Set the memory bounds for a given array/pointer storage\
  in the bound table.",
           &mpx_set_cmdlist);
+  deprecate_cmd (c, nullptr);
 
   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_SVR4,
                          i386_svr4_init_abi);