gdb: ensure the cast in gdbarch_tdep is valid
[binutils-gdb.git] / gdb / aarch64-tdep.c
index 1c44345e573132f7bb921b9eb0b488684c9c3bc3..8670197a88892b9473fad2d89da93dcb659e9b3b 100644 (file)
@@ -1,6 +1,6 @@
 /* Common target dependent code for GDB on AArch64 systems.
 
-   Copyright (C) 2009-2020 Free Software Foundation, Inc.
+   Copyright (C) 2009-2022 Free Software Foundation, Inc.
    Contributed by ARM Ltd.
 
    This file is part of GDB.
 
 #include "opcode/aarch64.h"
 #include <algorithm>
-
-#define submask(x) ((1L << ((x) + 1)) - 1)
-#define bit(obj,st) (((obj) >> (st)) & 1)
-#define bits(obj,st,fn) (((obj) >> (st)) & submask ((fn) - (st)))
+#include <unordered_map>
 
 /* A Homogeneous Floating-Point or Short-Vector Aggregate may have at most
    four members.  */
 #define HA_MAX_NUM_FLDS                4
 
 /* All possible aarch64 target descriptors.  */
-struct target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1][2/*pauth*/];
+static std::unordered_map <aarch64_features, target_desc *> tdesc_aarch64_map;
 
 /* The standard register names, and all the valid aliases for them.  */
 static const struct
@@ -176,6 +173,12 @@ static const char *const aarch64_pauth_register_names[] =
   "pauth_cmask"
 };
 
+static const char *const aarch64_mte_register_names[] =
+{
+  /* Tag Control Register.  */
+  "tag_ctl"
+};
+
 /* AArch64 prologue cache structure.  */
 struct aarch64_prologue_cache
 {
@@ -205,14 +208,14 @@ struct aarch64_prologue_cache
   int framereg;
 
   /* Saved register offsets.  */
-  struct trad_frame_saved_reg *saved_regs;
+  trad_frame_saved_reg *saved_regs;
 };
 
 static void
 show_aarch64_debug (struct ui_file *file, int from_tty,
-                    struct cmd_list_element *c, const char *value)
+                   struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("AArch64 debugging is %s.\n"), value);
+  gdb_printf (file, _("AArch64 debugging is %s.\n"), value);
 }
 
 namespace {
@@ -246,12 +249,12 @@ class instruction_reader : public abstract_instruction_reader
    THIS_FRAME.  */
 
 static CORE_ADDR
-aarch64_frame_unmask_lr (struct gdbarch_tdep *tdep,
+aarch64_frame_unmask_lr (aarch64_gdbarch_tdep *tdep,
                         struct frame_info *this_frame, CORE_ADDR addr)
 {
   if (tdep->has_pauth ()
       && frame_unwind_register_unsigned (this_frame,
-                                        tdep->pauth_ra_state_regnum))
+                                        tdep->ra_sign_state_regnum))
     {
       int cmask_num = AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base);
       CORE_ADDR cmask = frame_unwind_register_unsigned (this_frame, cmask_num);
@@ -287,6 +290,12 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
 {
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   int i;
+
+  /* Whether the stack has been set.  This should be true when we notice a SP
+     to FP move or if we are using the SP as the base register for storing
+     data, in case the FP is ommitted.  */
+  bool seen_stack_set = false;
+
   /* Track X registers and D registers in prologue.  */
   pv_t regs[AARCH64_X_REGISTER_COUNT + AARCH64_D_REGISTER_COUNT];
 
@@ -326,6 +335,10 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
              regs[rd] = pv_add_constant (regs[rn],
                                          -inst.operands[2].imm.value);
            }
+
+         /* Did we move SP to FP?  */
+         if (rn == AARCH64_SP_REGNUM && rd == AARCH64_FP_REGNUM)
+           seen_stack_set = true;
        }
       else if (inst.opcode->iclass == pcreladdr
               && inst.operands[1].type == AARCH64_OPND_ADDR_ADRP)
@@ -358,6 +371,12 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
       else if (inst.opcode->op == OP_MOVZ)
        {
          gdb_assert (inst.operands[0].type == AARCH64_OPND_Rd);
+
+         /* If this shows up before we set the stack, keep going.  Otherwise
+            stop the analysis.  */
+         if (seen_stack_set)
+           break;
+
          regs[inst.operands[0].reg.regno] = pv_unknown ();
        }
       else if (inst.opcode->iclass == log_shift
@@ -376,12 +395,10 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
            regs[rd] = regs[rm];
          else
            {
-             if (aarch64_debug)
-               {
-                 debug_printf ("aarch64: prologue analysis gave up "
-                               "addr=%s opcode=0x%x (orr x register)\n",
-                               core_addr_to_string_nz (start), insn);
-               }
+             aarch64_debug_printf ("prologue analysis gave up "
+                                   "addr=%s opcode=0x%x (orr x register)",
+                                   core_addr_to_string_nz (start), insn);
+
              break;
            }
        }
@@ -399,6 +416,10 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
          stack.store
            (pv_add_constant (regs[rn], inst.operands[1].addr.offset.imm),
             size, regs[rt]);
+
+         /* Are we storing with SP as a base?  */
+         if (rn == AARCH64_SP_REGNUM)
+           seen_stack_set = true;
        }
       else if ((inst.opcode->iclass == ldstpair_off
                || (inst.opcode->iclass == ldstpair_indexed
@@ -442,6 +463,10 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
          if (inst.operands[2].addr.writeback)
            regs[rn] = pv_add_constant (regs[rn], imm);
 
+         /* Ignore the instruction that allocates stack space and sets
+            the SP.  */
+         if (rn == AARCH64_SP_REGNUM && !inst.operands[2].addr.writeback)
+           seen_stack_set = true;
        }
       else if ((inst.opcode->iclass == ldst_imm9 /* Signed immediate.  */
                || (inst.opcode->iclass == ldst_pos /* Unsigned immediate.  */
@@ -464,6 +489,10 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
          stack.store (pv_add_constant (regs[rn], imm), size, regs[rt]);
          if (inst.operands[1].addr.writeback)
            regs[rn] = pv_add_constant (regs[rn], imm);
+
+         /* Are we storing with SP as a base?  */
+         if (rn == AARCH64_SP_REGNUM)
+           seen_stack_set = true;
        }
       else if (inst.opcode->iclass == testbranch)
        {
@@ -472,7 +501,8 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
        }
       else if (inst.opcode->iclass == ic_system)
        {
-         struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+         aarch64_gdbarch_tdep *tdep
+           = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
          int ra_state_val = 0;
 
          if (insn == 0xd503233f /* paciasp.  */
@@ -487,28 +517,29 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
              /* Return addresses are not mangled.  */
              ra_state_val = 0;
            }
+         else if (IS_BTI (insn))
+           /* We don't need to do anything special for a BTI instruction.  */
+           continue;
          else
            {
-             if (aarch64_debug)
-               debug_printf ("aarch64: prologue analysis gave up addr=%s"
-                             " opcode=0x%x (iclass)\n",
-                             core_addr_to_string_nz (start), insn);
+             aarch64_debug_printf ("prologue analysis gave up addr=%s"
+                                   " opcode=0x%x (iclass)",
+                                   core_addr_to_string_nz (start), insn);
              break;
            }
 
          if (tdep->has_pauth () && cache != nullptr)
-           trad_frame_set_value (cache->saved_regs,
-                                 tdep->pauth_ra_state_regnum,
-                                 ra_state_val);
+           {
+             int regnum = tdep->ra_sign_state_regnum;
+             cache->saved_regs[regnum].set_value (ra_state_val);
+           }
        }
       else
        {
-         if (aarch64_debug)
-           {
-             debug_printf ("aarch64: prologue analysis gave up addr=%s"
-                           " opcode=0x%x\n",
-                           core_addr_to_string_nz (start), insn);
-           }
+         aarch64_debug_printf ("prologue analysis gave up addr=%s"
+                               " opcode=0x%x",
+                               core_addr_to_string_nz (start), insn);
+
          break;
        }
     }
@@ -540,7 +571,7 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
       CORE_ADDR offset;
 
       if (stack.find_reg (gdbarch, i, &offset))
-       cache->saved_regs[i].addr = offset;
+       cache->saved_regs[i].set_addr (offset);
     }
 
   for (i = 0; i < AARCH64_D_REGISTER_COUNT; i++)
@@ -550,7 +581,7 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
 
       if (stack.find_reg (gdbarch, i + AARCH64_X_REGISTER_COUNT,
                          &offset))
-       cache->saved_regs[i + regnum + AARCH64_D0_REGNUM].addr = offset;
+       cache->saved_regs[i + regnum + AARCH64_D0_REGNUM].set_addr (offset);
     }
 
   return start;
@@ -601,7 +632,6 @@ aarch64_analyze_prologue_test (void)
 {
   struct gdbarch_info info;
 
-  gdbarch_info_init (&info);
   info.bfd_arch_info = bfd_scan_arch ("aarch64");
 
   struct gdbarch *gdbarch = gdbarch_find_by_info (info);
@@ -610,7 +640,7 @@ aarch64_analyze_prologue_test (void)
   struct aarch64_prologue_cache cache;
   cache.saved_regs = trad_frame_alloc_saved_regs (gdbarch);
 
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
   /* Test the simple prologue in which frame pointer is used.  */
   {
@@ -630,19 +660,21 @@ aarch64_analyze_prologue_test (void)
     for (int i = 0; i < AARCH64_X_REGISTER_COUNT; i++)
       {
        if (i == AARCH64_FP_REGNUM)
-         SELF_CHECK (cache.saved_regs[i].addr == -272);
+         SELF_CHECK (cache.saved_regs[i].addr () == -272);
        else if (i == AARCH64_LR_REGNUM)
-         SELF_CHECK (cache.saved_regs[i].addr == -264);
+         SELF_CHECK (cache.saved_regs[i].addr () == -264);
        else
-         SELF_CHECK (cache.saved_regs[i].addr == -1);
+         SELF_CHECK (cache.saved_regs[i].is_realreg ()
+                     && cache.saved_regs[i].realreg () == i);
       }
 
     for (int i = 0; i < AARCH64_D_REGISTER_COUNT; i++)
       {
-       int regnum = gdbarch_num_regs (gdbarch);
+       int num_regs = gdbarch_num_regs (gdbarch);
+       int regnum = i + num_regs + AARCH64_D0_REGNUM;
 
-       SELF_CHECK (cache.saved_regs[i + regnum + AARCH64_D0_REGNUM].addr
-                   == -1);
+       SELF_CHECK (cache.saved_regs[regnum].is_realreg ()
+                   && cache.saved_regs[regnum].realreg () == regnum);
       }
   }
 
@@ -670,26 +702,139 @@ aarch64_analyze_prologue_test (void)
     for (int i = 0; i < AARCH64_X_REGISTER_COUNT; i++)
       {
        if (i == 1)
-         SELF_CHECK (cache.saved_regs[i].addr == -16);
+         SELF_CHECK (cache.saved_regs[i].addr () == -16);
        else if (i == 19)
-         SELF_CHECK (cache.saved_regs[i].addr == -48);
+         SELF_CHECK (cache.saved_regs[i].addr () == -48);
        else
-         SELF_CHECK (cache.saved_regs[i].addr == -1);
+         SELF_CHECK (cache.saved_regs[i].is_realreg ()
+                     && cache.saved_regs[i].realreg () == i);
       }
 
     for (int i = 0; i < AARCH64_D_REGISTER_COUNT; i++)
       {
-       int regnum = gdbarch_num_regs (gdbarch);
+       int num_regs = gdbarch_num_regs (gdbarch);
+       int regnum = i + num_regs + AARCH64_D0_REGNUM;
+
 
        if (i == 0)
-         SELF_CHECK (cache.saved_regs[i + regnum + AARCH64_D0_REGNUM].addr
-                     == -24);
+         SELF_CHECK (cache.saved_regs[regnum].addr () == -24);
        else
-         SELF_CHECK (cache.saved_regs[i + regnum + AARCH64_D0_REGNUM].addr
-                     == -1);
+         SELF_CHECK (cache.saved_regs[regnum].is_realreg ()
+                     && cache.saved_regs[regnum].realreg () == regnum);
       }
   }
 
+  /* Test handling of movz before setting the frame pointer.  */
+  {
+    static const uint32_t insns[] = {
+      0xa9bf7bfd, /* stp     x29, x30, [sp, #-16]! */
+      0x52800020, /* mov     w0, #0x1 */
+      0x910003fd, /* mov     x29, sp */
+      0x528000a2, /* mov     w2, #0x5 */
+      0x97fffff8, /* bl      6e4 */
+    };
+
+    instruction_reader_test reader (insns);
+
+    trad_frame_reset_saved_regs (gdbarch, cache.saved_regs);
+    CORE_ADDR end = aarch64_analyze_prologue (gdbarch, 0, 128, &cache, reader);
+
+    /* We should stop at the 4th instruction.  */
+    SELF_CHECK (end == (4 - 1) * 4);
+    SELF_CHECK (cache.framereg == AARCH64_FP_REGNUM);
+    SELF_CHECK (cache.framesize == 16);
+  }
+
+  /* Test handling of movz/stp when using the stack pointer as frame
+     pointer.  */
+  {
+    static const uint32_t insns[] = {
+      0xa9bc7bfd, /* stp     x29, x30, [sp, #-64]! */
+      0x52800020, /* mov     w0, #0x1 */
+      0x290207e0, /* stp     w0, w1, [sp, #16] */
+      0xa9018fe2, /* stp     x2, x3, [sp, #24] */
+      0x528000a2, /* mov     w2, #0x5 */
+      0x97fffff8, /* bl      6e4 */
+    };
+
+    instruction_reader_test reader (insns);
+
+    trad_frame_reset_saved_regs (gdbarch, cache.saved_regs);
+    CORE_ADDR end = aarch64_analyze_prologue (gdbarch, 0, 128, &cache, reader);
+
+    /* We should stop at the 5th instruction.  */
+    SELF_CHECK (end == (5 - 1) * 4);
+    SELF_CHECK (cache.framereg == AARCH64_SP_REGNUM);
+    SELF_CHECK (cache.framesize == 64);
+  }
+
+  /* Test handling of movz/str when using the stack pointer as frame
+     pointer  */
+  {
+    static const uint32_t insns[] = {
+      0xa9bc7bfd, /* stp     x29, x30, [sp, #-64]! */
+      0x52800020, /* mov     w0, #0x1 */
+      0xb9002be4, /* str     w4, [sp, #40] */
+      0xf9001be5, /* str     x5, [sp, #48] */
+      0x528000a2, /* mov     w2, #0x5 */
+      0x97fffff8, /* bl      6e4 */
+    };
+
+    instruction_reader_test reader (insns);
+
+    trad_frame_reset_saved_regs (gdbarch, cache.saved_regs);
+    CORE_ADDR end = aarch64_analyze_prologue (gdbarch, 0, 128, &cache, reader);
+
+    /* We should stop at the 5th instruction.  */
+    SELF_CHECK (end == (5 - 1) * 4);
+    SELF_CHECK (cache.framereg == AARCH64_SP_REGNUM);
+    SELF_CHECK (cache.framesize == 64);
+  }
+
+  /* Test handling of movz/stur when using the stack pointer as frame
+     pointer.  */
+  {
+    static const uint32_t insns[] = {
+      0xa9bc7bfd, /* stp     x29, x30, [sp, #-64]! */
+      0x52800020, /* mov     w0, #0x1 */
+      0xb80343e6, /* stur    w6, [sp, #52] */
+      0xf80383e7, /* stur    x7, [sp, #56] */
+      0x528000a2, /* mov     w2, #0x5 */
+      0x97fffff8, /* bl      6e4 */
+    };
+
+    instruction_reader_test reader (insns);
+
+    trad_frame_reset_saved_regs (gdbarch, cache.saved_regs);
+    CORE_ADDR end = aarch64_analyze_prologue (gdbarch, 0, 128, &cache, reader);
+
+    /* We should stop at the 5th instruction.  */
+    SELF_CHECK (end == (5 - 1) * 4);
+    SELF_CHECK (cache.framereg == AARCH64_SP_REGNUM);
+    SELF_CHECK (cache.framesize == 64);
+  }
+
+  /* Test handling of movz when there is no frame pointer set or no stack
+     pointer used.  */
+  {
+    static const uint32_t insns[] = {
+      0xa9bf7bfd, /* stp     x29, x30, [sp, #-16]! */
+      0x52800020, /* mov     w0, #0x1 */
+      0x528000a2, /* mov     w2, #0x5 */
+      0x97fffff8, /* bl      6e4 */
+    };
+
+    instruction_reader_test reader (insns);
+
+    trad_frame_reset_saved_regs (gdbarch, cache.saved_regs);
+    CORE_ADDR end = aarch64_analyze_prologue (gdbarch, 0, 128, &cache, reader);
+
+    /* We should stop at the 4th instruction.  */
+    SELF_CHECK (end == (4 - 1) * 4);
+    SELF_CHECK (cache.framereg == AARCH64_SP_REGNUM);
+    SELF_CHECK (cache.framesize == 16);
+  }
+
   /* Test a prologue in which there is a return address signing instruction.  */
   if (tdep->has_pauth ())
     {
@@ -713,20 +858,53 @@ aarch64_analyze_prologue_test (void)
       for (int i = 0; i < AARCH64_X_REGISTER_COUNT; i++)
        {
          if (i == 19)
-           SELF_CHECK (cache.saved_regs[i].addr == -20);
+           SELF_CHECK (cache.saved_regs[i].addr () == -20);
          else if (i == AARCH64_FP_REGNUM)
-           SELF_CHECK (cache.saved_regs[i].addr == -48);
+           SELF_CHECK (cache.saved_regs[i].addr () == -48);
          else if (i == AARCH64_LR_REGNUM)
-           SELF_CHECK (cache.saved_regs[i].addr == -40);
+           SELF_CHECK (cache.saved_regs[i].addr () == -40);
          else
-           SELF_CHECK (cache.saved_regs[i].addr == -1);
+           SELF_CHECK (cache.saved_regs[i].is_realreg ()
+                       && cache.saved_regs[i].realreg () == i);
        }
 
       if (tdep->has_pauth ())
        {
-         SELF_CHECK (trad_frame_value_p (cache.saved_regs,
-                                         tdep->pauth_ra_state_regnum));
-         SELF_CHECK (cache.saved_regs[tdep->pauth_ra_state_regnum].addr == 1);
+         int regnum = tdep->ra_sign_state_regnum;
+         SELF_CHECK (cache.saved_regs[regnum].is_value ());
+       }
+    }
+
+  /* Test a prologue with a BTI instruction.  */
+    {
+      static const uint32_t insns[] = {
+       0xd503245f, /* bti */
+       0xa9bd7bfd, /* stp      x29, x30, [sp, #-48]! */
+       0x910003fd, /* mov      x29, sp */
+       0xf801c3f3, /* str      x19, [sp, #28] */
+       0xb9401fa0, /* ldr      x19, [x29, #28] */
+      };
+      instruction_reader_test reader (insns);
+
+      trad_frame_reset_saved_regs (gdbarch, cache.saved_regs);
+      CORE_ADDR end = aarch64_analyze_prologue (gdbarch, 0, 128, &cache,
+                                               reader);
+
+      SELF_CHECK (end == 4 * 4);
+      SELF_CHECK (cache.framereg == AARCH64_FP_REGNUM);
+      SELF_CHECK (cache.framesize == 48);
+
+      for (int i = 0; i < AARCH64_X_REGISTER_COUNT; i++)
+       {
+         if (i == 19)
+           SELF_CHECK (cache.saved_regs[i].addr () == -20);
+         else if (i == AARCH64_FP_REGNUM)
+           SELF_CHECK (cache.saved_regs[i].addr () == -48);
+         else if (i == AARCH64_LR_REGNUM)
+           SELF_CHECK (cache.saved_regs[i].addr () == -40);
+         else
+           SELF_CHECK (cache.saved_regs[i].is_realreg ()
+                       && cache.saved_regs[i].realreg () == i);
        }
     }
 }
@@ -815,8 +993,8 @@ aarch64_scan_prologue (struct frame_info *this_frame,
 
       cache->framereg = AARCH64_FP_REGNUM;
       cache->framesize = 16;
-      cache->saved_regs[29].addr = 0;
-      cache->saved_regs[30].addr = 8;
+      cache->saved_regs[29].set_addr (0);
+      cache->saved_regs[30].set_addr (8);
     }
 }
 
@@ -845,8 +1023,9 @@ aarch64_make_prologue_cache_1 (struct frame_info *this_frame,
   /* Calculate actual addresses of saved registers using offsets
      determined by aarch64_analyze_prologue.  */
   for (reg = 0; reg < gdbarch_num_regs (get_frame_arch (this_frame)); reg++)
-    if (trad_frame_addr_p (cache->saved_regs, reg))
-      cache->saved_regs[reg].addr += cache->prev_sp;
+    if (cache->saved_regs[reg].is_addr ())
+      cache->saved_regs[reg].set_addr (cache->saved_regs[reg].addr ()
+                                      + cache->prev_sp);
 
   cache->func = get_frame_func (this_frame);
 
@@ -896,7 +1075,9 @@ aarch64_prologue_frame_unwind_stop_reason (struct frame_info *this_frame,
     return UNWIND_UNAVAILABLE;
 
   /* Halt the backtrace at "_start".  */
-  if (cache->prev_pc <= gdbarch_tdep (get_frame_arch (this_frame))->lowest_pc)
+  gdbarch *arch = get_frame_arch (this_frame);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (arch);
+  if (cache->prev_pc <= tdep->lowest_pc)
     return UNWIND_OUTERMOST;
 
   /* We've hit a wall, stop.  */
@@ -938,13 +1119,13 @@ aarch64_prologue_prev_register (struct frame_info *this_frame,
     {
       CORE_ADDR lr;
       struct gdbarch *gdbarch = get_frame_arch (this_frame);
-      struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+      aarch64_gdbarch_tdep *tdep
+       = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
       lr = frame_unwind_register_unsigned (this_frame, AARCH64_LR_REGNUM);
 
       if (tdep->has_pauth ()
-         && trad_frame_value_p (cache->saved_regs,
-                                tdep->pauth_ra_state_regnum))
+         && cache->saved_regs[tdep->ra_sign_state_regnum].is_value ())
        lr = aarch64_frame_unmask_lr (tdep, this_frame, lr);
 
       return frame_unwind_got_constant (this_frame, prev_regnum, lr);
@@ -954,17 +1135,17 @@ aarch64_prologue_prev_register (struct frame_info *this_frame,
      identified by the next frame's stack pointer at the time of the
      call.  The value was already reconstructed into PREV_SP.  */
   /*
-         +----------+  ^
-         | saved lr |  |
+        +----------+  ^
+        | saved lr |  |
       +->| saved fp |--+
       |  |          |
       |  |          |     <- Previous SP
       |  +----------+
       |  | saved lr |
       +--| saved fp |<- FP
-         |          |
-         |          |<- SP
-         +----------+  */
+        |          |
+        |          |<- SP
+        +----------+  */
   if (prev_regnum == AARCH64_SP_REGNUM)
     return frame_unwind_got_constant (this_frame, prev_regnum,
                                      cache->prev_sp);
@@ -974,8 +1155,9 @@ aarch64_prologue_prev_register (struct frame_info *this_frame,
 }
 
 /* AArch64 prologue unwinder.  */
-struct frame_unwind aarch64_prologue_unwind =
+static frame_unwind aarch64_prologue_unwind =
 {
+  "aarch64 prologue",
   NORMAL_FRAME,
   aarch64_prologue_frame_unwind_stop_reason,
   aarch64_prologue_this_id,
@@ -1068,8 +1250,9 @@ aarch64_stub_unwind_sniffer (const struct frame_unwind *self,
 }
 
 /* AArch64 stub unwinder.  */
-struct frame_unwind aarch64_stub_unwind =
+static frame_unwind aarch64_stub_unwind =
 {
+  "aarch64 stub",
   NORMAL_FRAME,
   aarch64_stub_frame_unwind_stop_reason,
   aarch64_stub_this_id,
@@ -1090,7 +1273,7 @@ aarch64_normal_frame_base (struct frame_info *this_frame, void **this_cache)
 }
 
 /* AArch64 default frame base information.  */
-struct frame_base aarch64_normal_base =
+static frame_base aarch64_normal_base =
 {
   &aarch64_prologue_unwind,
   aarch64_normal_frame_base,
@@ -1105,7 +1288,8 @@ static struct value *
 aarch64_dwarf2_prev_register (struct frame_info *this_frame,
                              void **this_cache, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (this_frame));
+  gdbarch *arch = get_frame_arch (this_frame);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (arch);
   CORE_ADDR lr;
 
   switch (regnum)
@@ -1131,7 +1315,7 @@ aarch64_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
                               struct dwarf2_frame_state_reg *reg,
                               struct frame_info *this_frame)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
   switch (regnum)
     {
@@ -1148,7 +1332,7 @@ aarch64_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
   /* Init pauth registers.  */
   if (tdep->has_pauth ())
     {
-      if (regnum == tdep->pauth_ra_state_regnum)
+      if (regnum == tdep->ra_sign_state_regnum)
        {
          /* Initialize RA_STATE to zero.  */
          reg->how = DWARF2_FRAME_REG_SAVED_VAL_EXP;
@@ -1171,7 +1355,7 @@ static bool
 aarch64_execute_dwarf_cfa_vendor_op (struct gdbarch *gdbarch, gdb_byte op,
                                     struct dwarf2_frame_state *fs)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
   struct dwarf2_frame_state_reg *ra_state;
 
   if (op == DW_CFA_AARCH64_negate_ra_state)
@@ -1181,10 +1365,10 @@ aarch64_execute_dwarf_cfa_vendor_op (struct gdbarch *gdbarch, gdb_byte op,
        return true;
 
       /* Allocate RA_STATE column if it's not allocated yet.  */
-      fs->regs.alloc_regs (AARCH64_DWARF_PAUTH_RA_STATE + 1);
+      fs->regs.alloc_regs (AARCH64_DWARF_RA_SIGN_STATE + 1);
 
       /* Toggle the status of RA_STATE between 0 and 1.  */
-      ra_state = &(fs->regs.reg[AARCH64_DWARF_PAUTH_RA_STATE]);
+      ra_state = &(fs->regs.reg[AARCH64_DWARF_RA_SIGN_STATE]);
       ra_state->how = DWARF2_FRAME_REG_SAVED_VAL_EXP;
 
       if (ra_state->loc.exp.start == nullptr
@@ -1254,7 +1438,7 @@ static ULONGEST
 aarch64_type_align (gdbarch *gdbarch, struct type *t)
 {
   t = check_typedef (t);
-  if (TYPE_CODE (t) == TYPE_CODE_ARRAY && TYPE_VECTOR (t))
+  if (t->code () == TYPE_CODE_ARRAY && t->is_vector ())
     {
       /* Use the natural alignment for vector types (the same for
         scalar type), but the maximum alignment is 128-bit.  */
@@ -1283,16 +1467,17 @@ aapcs_is_vfp_call_or_return_candidate_1 (struct type *type,
   if (type == nullptr)
     return -1;
 
-  switch (TYPE_CODE (type))
+  switch (type->code ())
     {
     case TYPE_CODE_FLT:
+    case TYPE_CODE_DECFLOAT:
       if (TYPE_LENGTH (type) > 16)
        return -1;
 
       if (*fundamental_type == nullptr)
        *fundamental_type = type;
       else if (TYPE_LENGTH (type) != TYPE_LENGTH (*fundamental_type)
-              || TYPE_CODE (type) != TYPE_CODE (*fundamental_type))
+              || type->code () != (*fundamental_type)->code ())
        return -1;
 
       return 1;
@@ -1306,7 +1491,7 @@ aapcs_is_vfp_call_or_return_candidate_1 (struct type *type,
        if (*fundamental_type == nullptr)
          *fundamental_type = target_type;
        else if (TYPE_LENGTH (target_type) != TYPE_LENGTH (*fundamental_type)
-                || TYPE_CODE (target_type) != TYPE_CODE (*fundamental_type))
+                || target_type->code () != (*fundamental_type)->code ())
          return -1;
 
        return 2;
@@ -1314,7 +1499,7 @@ aapcs_is_vfp_call_or_return_candidate_1 (struct type *type,
 
     case TYPE_CODE_ARRAY:
       {
-       if (TYPE_VECTOR (type))
+       if (type->is_vector ())
          {
            if (TYPE_LENGTH (type) != 8 && TYPE_LENGTH (type) != 16)
              return -1;
@@ -1322,7 +1507,7 @@ aapcs_is_vfp_call_or_return_candidate_1 (struct type *type,
            if (*fundamental_type == nullptr)
              *fundamental_type = type;
            else if (TYPE_LENGTH (type) != TYPE_LENGTH (*fundamental_type)
-                    || TYPE_CODE (type) != TYPE_CODE (*fundamental_type))
+                    || type->code () != (*fundamental_type)->code ())
              return -1;
 
            return 1;
@@ -1346,13 +1531,13 @@ aapcs_is_vfp_call_or_return_candidate_1 (struct type *type,
       {
        int count = 0;
 
-       for (int i = 0; i < TYPE_NFIELDS (type); i++)
+       for (int i = 0; i < type->num_fields (); i++)
          {
            /* Ignore any static fields.  */
-           if (field_is_static (&TYPE_FIELD (type, i)))
+           if (field_is_static (&type->field (i)))
              continue;
 
-           struct type *member = check_typedef (TYPE_FIELD_TYPE (type, i));
+           struct type *member = check_typedef (type->field (i).type ());
 
            int sub_count = aapcs_is_vfp_call_or_return_candidate_1
                              (member, fundamental_type);
@@ -1449,9 +1634,9 @@ pass_in_x (struct gdbarch *gdbarch, struct regcache *regcache,
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   int len = TYPE_LENGTH (type);
-  enum type_code typecode = TYPE_CODE (type);
+  enum type_code typecode = type->code ();
   int regnum = AARCH64_X0_REGNUM + info->ngrn;
-  const bfd_byte *buf = value_contents (arg);
+  const bfd_byte *buf = value_contents (arg).data ();
 
   info->argnum++;
 
@@ -1468,12 +1653,10 @@ pass_in_x (struct gdbarch *gdbarch, struct regcache *regcache,
          && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
        regval <<= ((X_REGISTER_SIZE - partial_len) * TARGET_CHAR_BIT);
 
-      if (aarch64_debug)
-       {
-         debug_printf ("arg %d in %s = 0x%s\n", info->argnum,
-                       gdbarch_register_name (gdbarch, regnum),
-                       phex (regval, X_REGISTER_SIZE));
-       }
+      aarch64_debug_printf ("arg %d in %s = 0x%s", info->argnum,
+                           gdbarch_register_name (gdbarch, regnum),
+                           phex (regval, X_REGISTER_SIZE));
+
       regcache_cooked_write_unsigned (regcache, regnum, regval);
       len -= partial_len;
       buf += partial_len;
@@ -1508,11 +1691,9 @@ pass_in_v (struct gdbarch *gdbarch,
       memcpy (reg, buf, len);
       regcache->cooked_write (regnum, reg);
 
-      if (aarch64_debug)
-       {
-         debug_printf ("arg %d in %s\n", info->argnum,
-                       gdbarch_register_name (gdbarch, regnum));
-       }
+      aarch64_debug_printf ("arg %d in %s", info->argnum,
+                           gdbarch_register_name (gdbarch, regnum));
+
       return 1;
     }
   info->nsrn = 8;
@@ -1525,7 +1706,7 @@ static void
 pass_on_stack (struct aarch64_call_info *info, struct type *type,
               struct value *arg)
 {
-  const bfd_byte *buf = value_contents (arg);
+  const bfd_byte *buf = value_contents (arg).data ();
   int len = TYPE_LENGTH (type);
   int align;
   stack_item_t item;
@@ -1542,11 +1723,8 @@ pass_on_stack (struct aarch64_call_info *info, struct type *type,
   if (align > 16)
     align = 16;
 
-  if (aarch64_debug)
-    {
-      debug_printf ("arg %d len=%d @ sp + %d\n", info->argnum, len,
-                   info->nsaa);
-    }
+  aarch64_debug_printf ("arg %d len=%d @ sp + %d\n", info->argnum, len,
+                       info->nsaa);
 
   item.len = len;
   item.data = buf;
@@ -1600,16 +1778,17 @@ pass_in_v_vfp_candidate (struct gdbarch *gdbarch, struct regcache *regcache,
                         struct aarch64_call_info *info, struct type *arg_type,
                         struct value *arg)
 {
-  switch (TYPE_CODE (arg_type))
+  switch (arg_type->code ())
     {
     case TYPE_CODE_FLT:
+    case TYPE_CODE_DECFLOAT:
       return pass_in_v (gdbarch, regcache, info, TYPE_LENGTH (arg_type),
-                       value_contents (arg));
+                       value_contents (arg).data ());
       break;
 
     case TYPE_CODE_COMPLEX:
       {
-       const bfd_byte *buf = value_contents (arg);
+       const bfd_byte *buf = value_contents (arg).data ();
        struct type *target_type = check_typedef (TYPE_TARGET_TYPE (arg_type));
 
        if (!pass_in_v (gdbarch, regcache, info, TYPE_LENGTH (target_type),
@@ -1621,17 +1800,17 @@ pass_in_v_vfp_candidate (struct gdbarch *gdbarch, struct regcache *regcache,
       }
 
     case TYPE_CODE_ARRAY:
-      if (TYPE_VECTOR (arg_type))
+      if (arg_type->is_vector ())
        return pass_in_v (gdbarch, regcache, info, TYPE_LENGTH (arg_type),
-                         value_contents (arg));
+                         value_contents (arg).data ());
       /* fall through.  */
 
     case TYPE_CODE_STRUCT:
     case TYPE_CODE_UNION:
-      for (int i = 0; i < TYPE_NFIELDS (arg_type); i++)
+      for (int i = 0; i < arg_type->num_fields (); i++)
        {
          /* Don't include static fields.  */
-         if (field_is_static (&TYPE_FIELD (arg_type, i)))
+         if (field_is_static (&arg_type->field (i)))
            continue;
 
          struct value *field = value_primitive_field (arg, 0, i, arg_type);
@@ -1695,13 +1874,11 @@ aarch64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   /* The struct_return pointer occupies X8.  */
   if (return_method != return_method_normal)
     {
-      if (aarch64_debug)
-       {
-         debug_printf ("struct return in %s = 0x%s\n",
-                       gdbarch_register_name (gdbarch,
-                                              AARCH64_STRUCT_RETURN_REGNUM),
-                       paddress (gdbarch, struct_addr));
-       }
+      aarch64_debug_printf ("struct return in %s = 0x%s",
+                           gdbarch_register_name
+                             (gdbarch, AARCH64_STRUCT_RETURN_REGNUM),
+                           paddress (gdbarch, struct_addr));
+
       regcache_cooked_write_unsigned (regcache, AARCH64_STRUCT_RETURN_REGNUM,
                                      struct_addr);
     }
@@ -1736,17 +1913,17 @@ aarch64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
          continue;
        }
 
-      switch (TYPE_CODE (arg_type))
+      switch (arg_type->code ())
        {
        case TYPE_CODE_INT:
        case TYPE_CODE_BOOL:
        case TYPE_CODE_CHAR:
        case TYPE_CODE_RANGE:
        case TYPE_CODE_ENUM:
-         if (len < 4)
+         if (len < 4 && !is_fixed_point_type (arg_type))
            {
              /* Promote to 32 bit integer.  */
-             if (TYPE_UNSIGNED (arg_type))
+             if (arg_type->is_unsigned ())
                arg_type = builtin_type (gdbarch)->builtin_uint32;
              else
                arg_type = builtin_type (gdbarch)->builtin_int32;
@@ -1767,7 +1944,7 @@ aarch64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              sp = align_down (sp - len, 16);
 
              /* Write the real data into the stack.  */
-             write_memory (sp, value_contents (arg), len);
+             write_memory (sp, value_contents (arg).data (), len);
 
              /* Construct the indirection.  */
              arg_type = lookup_pointer_type (arg_type);
@@ -1819,7 +1996,7 @@ aarch64_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
 static struct type *
 aarch64_vnq_type (struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
   if (tdep->vnq_type == NULL)
     {
@@ -1846,7 +2023,7 @@ aarch64_vnq_type (struct gdbarch *gdbarch)
 static struct type *
 aarch64_vnd_type (struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
   if (tdep->vnd_type == NULL)
     {
@@ -1876,7 +2053,7 @@ aarch64_vnd_type (struct gdbarch *gdbarch)
 static struct type *
 aarch64_vns_type (struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
   if (tdep->vns_type == NULL)
     {
@@ -1906,7 +2083,7 @@ aarch64_vns_type (struct gdbarch *gdbarch)
 static struct type *
 aarch64_vnh_type (struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
   if (tdep->vnh_type == NULL)
     {
@@ -1916,6 +2093,9 @@ aarch64_vnh_type (struct gdbarch *gdbarch)
       t = arch_composite_type (gdbarch, "__gdb_builtin_type_vnh",
                               TYPE_CODE_UNION);
 
+      elem = builtin_type (gdbarch)->builtin_bfloat16;
+      append_composite_type_field (t, "bf", elem);
+
       elem = builtin_type (gdbarch)->builtin_half;
       append_composite_type_field (t, "f", elem);
 
@@ -1936,7 +2116,7 @@ aarch64_vnh_type (struct gdbarch *gdbarch)
 static struct type *
 aarch64_vnb_type (struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
   if (tdep->vnb_type == NULL)
     {
@@ -1963,11 +2143,11 @@ aarch64_vnb_type (struct gdbarch *gdbarch)
 static struct type *
 aarch64_vnv_type (struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
   if (tdep->vnv_type == NULL)
     {
-      /* The other AArch64 psuedo registers (Q,D,H,S,B) refer to a single value
+      /* The other AArch64 pseudo registers (Q,D,H,S,B) refer to a single value
         slice from the non-pseudo vector registers.  However NEON V registers
         are always vector registers, and need constructing as such.  */
       const struct builtin_type *bt = builtin_type (gdbarch);
@@ -1997,6 +2177,8 @@ aarch64_vnv_type (struct gdbarch *gdbarch)
 
       sub = arch_composite_type (gdbarch, "__gdb_builtin_type_vnh",
                                 TYPE_CODE_UNION);
+      append_composite_type_field (sub, "bf",
+                                  init_vector_type (bt->builtin_bfloat16, 8));
       append_composite_type_field (sub, "f",
                                   init_vector_type (bt->builtin_half, 8));
       append_composite_type_field (sub, "u",
@@ -2032,7 +2214,7 @@ aarch64_vnv_type (struct gdbarch *gdbarch)
 static int
 aarch64_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
   if (reg >= AARCH64_DWARF_X0 && reg <= AARCH64_DWARF_X0 + 30)
     return AARCH64_X0_REGNUM + reg - AARCH64_DWARF_X0;
@@ -2040,6 +2222,9 @@ aarch64_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
   if (reg == AARCH64_DWARF_SP)
     return AARCH64_SP_REGNUM;
 
+  if (reg == AARCH64_DWARF_PC)
+    return AARCH64_PC_REGNUM;
+
   if (reg >= AARCH64_DWARF_V0 && reg <= AARCH64_DWARF_V0 + 31)
     return AARCH64_V0_REGNUM + reg - AARCH64_DWARF_V0;
 
@@ -2057,11 +2242,8 @@ aarch64_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
 
   if (tdep->has_pauth ())
     {
-      if (reg >= AARCH64_DWARF_PAUTH_DMASK && reg <= AARCH64_DWARF_PAUTH_CMASK)
-       return tdep->pauth_reg_base + reg - AARCH64_DWARF_PAUTH_DMASK;
-
-      if (reg == AARCH64_DWARF_PAUTH_RA_STATE)
-       return tdep->pauth_ra_state_regnum;
+      if (reg == AARCH64_DWARF_RA_SIGN_STATE)
+       return tdep->ra_sign_state_regnum;
     }
 
   return -1;
@@ -2108,24 +2290,22 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs,
          gdb_byte buf[register_size (gdbarch, regno)];
          gdb_assert (len <= sizeof (buf));
 
-         if (aarch64_debug)
-           {
-             debug_printf ("read HFA or HVA return value element %d from %s\n",
-                           i + 1,
-                           gdbarch_register_name (gdbarch, regno));
-           }
+         aarch64_debug_printf
+           ("read HFA or HVA return value element %d from %s",
+            i + 1, gdbarch_register_name (gdbarch, regno));
+
          regs->cooked_read (regno, buf);
 
          memcpy (valbuf, buf, len);
          valbuf += len;
        }
     }
-  else if (TYPE_CODE (type) == TYPE_CODE_INT
-          || TYPE_CODE (type) == TYPE_CODE_CHAR
-          || TYPE_CODE (type) == TYPE_CODE_BOOL
-          || TYPE_CODE (type) == TYPE_CODE_PTR
+  else if (type->code () == TYPE_CODE_INT
+          || type->code () == TYPE_CODE_CHAR
+          || type->code () == TYPE_CODE_BOOL
+          || type->code () == TYPE_CODE_PTR
           || TYPE_IS_REFERENCE (type)
-          || TYPE_CODE (type) == TYPE_CODE_ENUM)
+          || type->code () == TYPE_CODE_ENUM)
     {
       /* If the type is a plain integer, then the access is
         straight-forward.  Otherwise we have to play around a bit
@@ -2149,8 +2329,8 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs,
   else
     {
       /* For a structure or union the behaviour is as if the value had
-         been stored to word-aligned memory and then loaded into
-         registers with 64-bit load instruction(s).  */
+        been stored to word-aligned memory and then loaded into
+        registers with 64-bit load instruction(s).  */
       int len = TYPE_LENGTH (type);
       int regno = AARCH64_X0_REGNUM;
       bfd_byte buf[X_REGISTER_SIZE];
@@ -2185,10 +2365,11 @@ aarch64_return_in_memory (struct gdbarch *gdbarch, struct type *type)
       return 0;
     }
 
-  if (TYPE_LENGTH (type) > 16)
+  if (TYPE_LENGTH (type) > 16
+      || !language_pass_by_reference (type).trivially_copyable)
     {
       /* PCS B.6 Aggregates larger than 16 bytes are passed by
-         invisible reference.  */
+        invisible reference.  */
 
       return 1;
     }
@@ -2220,12 +2401,9 @@ aarch64_store_return_value (struct type *type, struct regcache *regs,
          gdb_byte tmpbuf[register_size (gdbarch, regno)];
          gdb_assert (len <= sizeof (tmpbuf));
 
-         if (aarch64_debug)
-           {
-             debug_printf ("write HFA or HVA return value element %d to %s\n",
-                           i + 1,
-                           gdbarch_register_name (gdbarch, regno));
-           }
+         aarch64_debug_printf
+           ("write HFA or HVA return value element %d to %s",
+            i + 1, gdbarch_register_name (gdbarch, regno));
 
          memcpy (tmpbuf, valbuf,
                  len > V_REGISTER_SIZE ? V_REGISTER_SIZE : len);
@@ -2233,12 +2411,12 @@ aarch64_store_return_value (struct type *type, struct regcache *regs,
          valbuf += len;
        }
     }
-  else if (TYPE_CODE (type) == TYPE_CODE_INT
-          || TYPE_CODE (type) == TYPE_CODE_CHAR
-          || TYPE_CODE (type) == TYPE_CODE_BOOL
-          || TYPE_CODE (type) == TYPE_CODE_PTR
+  else if (type->code () == TYPE_CODE_INT
+          || type->code () == TYPE_CODE_CHAR
+          || type->code () == TYPE_CODE_BOOL
+          || type->code () == TYPE_CODE_PTR
           || TYPE_IS_REFERENCE (type)
-          || TYPE_CODE (type) == TYPE_CODE_ENUM)
+          || type->code () == TYPE_CODE_ENUM)
     {
       if (TYPE_LENGTH (type) <= X_REGISTER_SIZE)
        {
@@ -2294,15 +2472,30 @@ aarch64_return_value (struct gdbarch *gdbarch, struct value *func_value,
                      gdb_byte *readbuf, const gdb_byte *writebuf)
 {
 
-  if (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
-      || TYPE_CODE (valtype) == TYPE_CODE_UNION
-      || TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
+  if (valtype->code () == TYPE_CODE_STRUCT
+      || valtype->code () == TYPE_CODE_UNION
+      || valtype->code () == TYPE_CODE_ARRAY)
     {
       if (aarch64_return_in_memory (gdbarch, valtype))
        {
-         if (aarch64_debug)
-           debug_printf ("return value in memory\n");
-         return RETURN_VALUE_STRUCT_CONVENTION;
+         /* From the AAPCS64's Result Return section:
+
+            "Otherwise, the caller shall reserve a block of memory of
+             sufficient size and alignment to hold the result.  The address
+             of the memory block shall be passed as an additional argument to
+             the function in x8.  */
+
+         aarch64_debug_printf ("return value in memory");
+
+         if (readbuf)
+           {
+             CORE_ADDR addr;
+
+             regcache->cooked_read (AARCH64_STRUCT_RETURN_REGNUM, &addr);
+             read_memory (addr, readbuf, TYPE_LENGTH (valtype));
+           }
+
+         return RETURN_VALUE_ABI_RETURNS_ADDRESS;
        }
     }
 
@@ -2312,8 +2505,7 @@ aarch64_return_value (struct gdbarch *gdbarch, struct value *func_value,
   if (readbuf)
     aarch64_extract_return_value (valtype, regcache, readbuf);
 
-  if (aarch64_debug)
-    debug_printf ("return value in registers\n");
+  aarch64_debug_printf ("return value in registers");
 
   return RETURN_VALUE_REGISTER_CONVENTION;
 }
@@ -2326,7 +2518,7 @@ aarch64_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
   CORE_ADDR jb_addr;
   gdb_byte buf[X_REGISTER_SIZE];
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
   jb_addr = get_frame_register_unsigned (frame, AARCH64_X0_REGNUM);
@@ -2357,7 +2549,7 @@ aarch64_gen_return_address (struct gdbarch *gdbarch,
 static const char *
 aarch64_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
   static const char *const q_name[] =
     {
@@ -2458,7 +2650,7 @@ aarch64_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
   /* RA_STATE is used for unwinding only.  Do not assign it a name - this
      prevents it from being read by methods such as
      mi_cmd_trace_frame_collected.  */
-  if (tdep->has_pauth () && regnum == tdep->pauth_ra_state_regnum)
+  if (tdep->has_pauth () && regnum == tdep->ra_sign_state_regnum)
     return "";
 
   internal_error (__FILE__, __LINE__,
@@ -2471,7 +2663,7 @@ aarch64_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
 static struct type *
 aarch64_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
   int p_regnum = regnum - gdbarch_num_regs (gdbarch);
 
@@ -2494,7 +2686,7 @@ aarch64_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
       && p_regnum < AARCH64_SVE_V0_REGNUM + AARCH64_V_REGS_NUM)
     return aarch64_vnv_type (gdbarch);
 
-  if (tdep->has_pauth () && regnum == tdep->pauth_ra_state_regnum)
+  if (tdep->has_pauth () && regnum == tdep->ra_sign_state_regnum)
     return builtin_type (gdbarch)->builtin_uint64;
 
   internal_error (__FILE__, __LINE__,
@@ -2506,9 +2698,9 @@ aarch64_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
 
 static int
 aarch64_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
-                                   struct reggroup *group)
+                                   const struct reggroup *group)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
   int p_regnum = regnum - gdbarch_num_regs (gdbarch);
 
@@ -2528,7 +2720,7 @@ aarch64_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
           && p_regnum < AARCH64_SVE_V0_REGNUM + AARCH64_V_REGS_NUM)
     return group == all_reggroup || group == vector_reggroup;
   /* RA_STATE is used for unwinding only.  Do not assign it to any groups.  */
-  if (tdep->has_pauth () && regnum == tdep->pauth_ra_state_regnum)
+  if (tdep->has_pauth () && regnum == tdep->ra_sign_state_regnum)
     return 0;
 
   return group == all_reggroup;
@@ -2551,7 +2743,7 @@ aarch64_pseudo_read_value_1 (struct gdbarch *gdbarch,
     mark_value_bytes_unavailable (result_value, 0,
                                  TYPE_LENGTH (value_type (result_value)));
   else
-    memcpy (value_contents_raw (result_value), reg_buf, regsize);
+    memcpy (value_contents_raw (result_value).data (), reg_buf, regsize);
 
   return result_value;
  }
@@ -2562,7 +2754,7 @@ static struct value *
 aarch64_pseudo_read_value (struct gdbarch *gdbarch, readable_regcache *regcache,
                           int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
   struct value *result_value = allocate_value (register_type (gdbarch, regnum));
 
   VALUE_LVAL (result_value) = lval_register;
@@ -2632,7 +2824,7 @@ static void
 aarch64_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
                      int regnum, const gdb_byte *buf)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
   regnum -= gdbarch_num_regs (gdbarch);
 
   if (regnum >= AARCH64_Q0_REGNUM && regnum < AARCH64_Q0_REGNUM + 32)
@@ -2764,7 +2956,8 @@ aarch64_software_single_step (struct regcache *regcache)
   return next_pcs;
 }
 
-struct aarch64_displaced_step_closure : public displaced_step_closure
+struct aarch64_displaced_step_copy_insn_closure
+  : public displaced_step_copy_insn_closure
 {
   /* It is true when condition instruction, such as B.CON, TBZ, etc,
      is being displaced stepping.  */
@@ -2790,7 +2983,7 @@ struct aarch64_displaced_step_data
   /* Registers when doing displaced stepping.  */
   struct regcache *regs;
 
-  aarch64_displaced_step_closure *dsc;
+  aarch64_displaced_step_copy_insn_closure *dsc;
 };
 
 /* Implementation of aarch64_insn_visitor method "b".  */
@@ -2974,14 +3167,21 @@ aarch64_displaced_step_others (const uint32_t insn,
   struct aarch64_displaced_step_data *dsd
     = (struct aarch64_displaced_step_data *) data;
 
-  aarch64_emit_insn (dsd->insn_buf, insn);
-  dsd->insn_count = 1;
-
-  if ((insn & 0xfffffc1f) == 0xd65f0000)
+  uint32_t masked_insn = (insn & CLEAR_Rn_MASK);
+  if (masked_insn == BLR)
     {
-      /* RET */
-      dsd->dsc->pc_adjust = 0;
+      /* Emit a BR to the same register and then update LR to the original
+        address (similar to aarch64_displaced_step_b).  */
+      aarch64_emit_insn (dsd->insn_buf, insn & 0xffdfffff);
+      regcache_cooked_write_unsigned (dsd->regs, AARCH64_LR_REGNUM,
+                                     data->insn_addr + 4);
     }
+  else
+    aarch64_emit_insn (dsd->insn_buf, insn);
+  dsd->insn_count = 1;
+
+  if (masked_insn == RET || masked_insn == BR || masked_insn == BLR)
+    dsd->dsc->pc_adjust = 0;
   else
     dsd->dsc->pc_adjust = 4;
 }
@@ -2999,7 +3199,7 @@ static const struct aarch64_insn_visitor visitor =
 
 /* Implement the "displaced_step_copy_insn" gdbarch method.  */
 
-struct displaced_step_closure *
+displaced_step_copy_insn_closure_up
 aarch64_displaced_step_copy_insn (struct gdbarch *gdbarch,
                                  CORE_ADDR from, CORE_ADDR to,
                                  struct regcache *regs)
@@ -3019,8 +3219,8 @@ aarch64_displaced_step_copy_insn (struct gdbarch *gdbarch,
       return NULL;
     }
 
-  std::unique_ptr<aarch64_displaced_step_closure> dsc
-    (new aarch64_displaced_step_closure);
+  std::unique_ptr<aarch64_displaced_step_copy_insn_closure> dsc
+    (new aarch64_displaced_step_copy_insn_closure);
   dsd.base.insn_addr = from;
   dsd.new_addr = to;
   dsd.regs = regs;
@@ -3038,12 +3238,10 @@ aarch64_displaced_step_copy_insn (struct gdbarch *gdbarch,
         relocated instruction(s) there.  */
       for (i = 0; i < dsd.insn_count; i++)
        {
-         if (debug_displaced)
-           {
-             debug_printf ("displaced: writing insn ");
-             debug_printf ("%.8x", dsd.insn_buf[i]);
-             debug_printf (" at %s\n", paddress (gdbarch, to + i * 4));
-           }
+         displaced_debug_printf ("writing insn %.8x at %s",
+                                 dsd.insn_buf[i],
+                                 paddress (gdbarch, to + i * 4));
+
          write_memory_unsigned_integer (to + i * 4, 4, byte_order_for_code,
                                         (ULONGEST) dsd.insn_buf[i]);
        }
@@ -3053,32 +3251,32 @@ aarch64_displaced_step_copy_insn (struct gdbarch *gdbarch,
       dsc = NULL;
     }
 
-  return dsc.release ();
+  /* This is a work around for a problem with g++ 4.8.  */
+  return displaced_step_copy_insn_closure_up (dsc.release ());
 }
 
 /* Implement the "displaced_step_fixup" gdbarch method.  */
 
 void
 aarch64_displaced_step_fixup (struct gdbarch *gdbarch,
-                             struct displaced_step_closure *dsc_,
+                             struct displaced_step_copy_insn_closure *dsc_,
                              CORE_ADDR from, CORE_ADDR to,
                              struct regcache *regs)
 {
-  aarch64_displaced_step_closure *dsc = (aarch64_displaced_step_closure *) dsc_;
+  aarch64_displaced_step_copy_insn_closure *dsc
+    = (aarch64_displaced_step_copy_insn_closure *) dsc_;
 
   ULONGEST pc;
 
   regcache_cooked_read_unsigned (regs, AARCH64_PC_REGNUM, &pc);
 
-  if (debug_displaced)
-    debug_printf ("Displaced: PC after stepping: %s (was %s).\n",
-                 paddress (gdbarch, pc), paddress (gdbarch, to));
+  displaced_debug_printf ("PC after stepping: %s (was %s).",
+                         paddress (gdbarch, pc), paddress (gdbarch, to));
 
   if (dsc->cond)
     {
-      if (debug_displaced)
-       debug_printf ("Displaced: [Conditional] pc_adjust before: %d\n",
-                     dsc->pc_adjust);
+      displaced_debug_printf ("[Conditional] pc_adjust before: %d",
+                             dsc->pc_adjust);
 
       if (pc - to == 8)
        {
@@ -3092,16 +3290,13 @@ aarch64_displaced_step_fixup (struct gdbarch *gdbarch,
       else
        gdb_assert_not_reached ("Unexpected PC value after displaced stepping");
 
-      if (debug_displaced)
-       debug_printf ("Displaced: [Conditional] pc_adjust after: %d\n",
-                     dsc->pc_adjust);
+      displaced_debug_printf ("[Conditional] pc_adjust after: %d",
+                             dsc->pc_adjust);
     }
 
-  if (debug_displaced)
-    debug_printf ("Displaced: %s PC by %d\n",
-                 dsc->pc_adjust? "adjusting" : "not adjusting",
-                 dsc->pc_adjust);
-
+  displaced_debug_printf ("%s PC by %d",
+                         dsc->pc_adjust ? "adjusting" : "not adjusting",
+                         dsc->pc_adjust);
 
   if (dsc->pc_adjust != 0)
     {
@@ -3111,17 +3306,13 @@ aarch64_displaced_step_fixup (struct gdbarch *gdbarch,
         took place.  */
       if ((pc - to) == 0)
        {
-         if (debug_displaced)
-           debug_printf ("Displaced: PC did not move. Discarding PC "
-                         "adjustment.\n");
+         displaced_debug_printf ("PC did not move. Discarding PC adjustment.");
          dsc->pc_adjust = 0;
        }
 
-      if (debug_displaced)
-       {
-         debug_printf ("Displaced: fixup: set PC to %s:%d\n",
-                       paddress (gdbarch, from), dsc->pc_adjust);
-       }
+      displaced_debug_printf ("fixup: set PC to %s:%d",
+                             paddress (gdbarch, from), dsc->pc_adjust);
+
       regcache_cooked_write_unsigned (regs, AARCH64_PC_REGNUM,
                                      from + dsc->pc_adjust);
     }
@@ -3129,30 +3320,33 @@ aarch64_displaced_step_fixup (struct gdbarch *gdbarch,
 
 /* Implement the "displaced_step_hw_singlestep" gdbarch method.  */
 
-int
-aarch64_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
-                                     struct displaced_step_closure *closure)
+bool
+aarch64_displaced_step_hw_singlestep (struct gdbarch *gdbarch)
 {
-  return 1;
+  return true;
 }
 
 /* Get the correct target description for the given VQ value.
    If VQ is zero then it is assumed SVE is not supported.
-   (It is not possible to set VQ to zero on an SVE system).  */
+   (It is not possible to set VQ to zero on an SVE system).
+
+   MTE_P indicates the presence of the Memory Tagging Extension feature.
+
+   TLS_P indicates the presence of the Thread Local Storage feature.  */
 
 const target_desc *
-aarch64_read_description (uint64_t vq, bool pauth_p)
+aarch64_read_description (const aarch64_features &features)
 {
-  if (vq > AARCH64_MAX_SVE_VQ)
-    error (_("VQ is %" PRIu64 ", maximum supported value is %d"), vq,
+  if (features.vq > AARCH64_MAX_SVE_VQ)
+    error (_("VQ is %" PRIu64 ", maximum supported value is %d"), features.vq,
           AARCH64_MAX_SVE_VQ);
 
-  struct target_desc *tdesc = tdesc_aarch64_list[vq][pauth_p];
+  struct target_desc *tdesc = tdesc_aarch64_map[features];
 
   if (tdesc == NULL)
     {
-      tdesc = aarch64_create_target_description (vq, pauth_p);
-      tdesc_aarch64_list[vq][pauth_p] = tdesc;
+      tdesc = aarch64_create_target_description (features);
+      tdesc_aarch64_map[features] = tdesc;
     }
 
   return tdesc;
@@ -3178,26 +3372,12 @@ aarch64_get_tdesc_vq (const struct target_desc *tdesc)
   return sve_vq_from_vl (vl);
 }
 
-/* Add all the expected register sets into GDBARCH.  */
-
-static void
-aarch64_add_reggroups (struct gdbarch *gdbarch)
-{
-  reggroup_add (gdbarch, general_reggroup);
-  reggroup_add (gdbarch, float_reggroup);
-  reggroup_add (gdbarch, system_reggroup);
-  reggroup_add (gdbarch, vector_reggroup);
-  reggroup_add (gdbarch, all_reggroup);
-  reggroup_add (gdbarch, save_reggroup);
-  reggroup_add (gdbarch, restore_reggroup);
-}
-
 /* Implement the "cannot_store_register" gdbarch method.  */
 
 static int
 aarch64_cannot_store_register (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
   if (!tdep->has_pauth ())
     return 0;
@@ -3207,6 +3387,25 @@ aarch64_cannot_store_register (struct gdbarch *gdbarch, int regnum)
          || regnum == AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base));
 }
 
+/* Implement the stack_frame_destroyed_p gdbarch method.  */
+
+static int
+aarch64_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  CORE_ADDR func_start, func_end;
+  if (!find_pc_partial_function (pc, NULL, &func_start, &func_end))
+    return 0;
+
+  enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
+  uint32_t insn = read_memory_unsigned_integer (pc, 4, byte_order_for_code);
+
+  aarch64_inst inst;
+  if (aarch64_decode_insn (insn, &inst, 1, nullptr) != 0)
+    return 0;
+
+  return streq (inst.opcode->name, "ret");
+}
+
 /* Initialize the current architecture based on INFO.  If possible,
    re-use an architecture from ARCHES, which is a list of
    architectures already created during this debugging session.
@@ -3221,7 +3420,8 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   const struct tdesc_feature *feature_pauth;
   bool valid_p = true;
   int i, num_regs = 0, num_pseudo_regs = 0;
-  int first_pauth_regnum = -1, pauth_ra_state_offset = -1;
+  int first_pauth_regnum = -1, ra_sign_state_offset = -1;
+  int first_mte_regnum = -1, tls_regnum = -1;
 
   /* Use the vector length passed via the target info.  Here -1 is used for no
      SVE, and 0 is unset.  If unset then use the vector length from the existing
@@ -3243,7 +3443,8 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        best_arch != nullptr;
        best_arch = gdbarch_list_lookup_by_info (best_arch->next, &info))
     {
-      struct gdbarch_tdep *tdep = gdbarch_tdep (best_arch->gdbarch);
+      aarch64_gdbarch_tdep *tdep
+       = gdbarch_tdep<aarch64_gdbarch_tdep> (best_arch->gdbarch);
       if (tdep && tdep->vq == vq)
        return best_arch->gdbarch;
     }
@@ -3252,23 +3453,31 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      value.  */
   const struct target_desc *tdesc = info.target_desc;
   if (!tdesc_has_registers (tdesc) || vq != aarch64_get_tdesc_vq (tdesc))
-    tdesc = aarch64_read_description (vq, false);
+    {
+      aarch64_features features;
+      features.vq = vq;
+      tdesc = aarch64_read_description (features);
+    }
   gdb_assert (tdesc);
 
   feature_core = tdesc_find_feature (tdesc,"org.gnu.gdb.aarch64.core");
   feature_fpu = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.fpu");
   feature_sve = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.sve");
   feature_pauth = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.pauth");
+  const struct tdesc_feature *feature_mte
+    = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.mte");
+  const struct tdesc_feature *feature_tls
+    = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.tls");
 
   if (feature_core == nullptr)
     return nullptr;
 
-  struct tdesc_arch_data *tdesc_data = tdesc_data_alloc ();
+  tdesc_arch_data_up tdesc_data = tdesc_data_alloc ();
 
   /* Validate the description provides the mandatory core R registers
      and allocate their numbers.  */
   for (i = 0; i < ARRAY_SIZE (aarch64_r_register_names); i++)
-    valid_p &= tdesc_numbered_register (feature_core, tdesc_data,
+    valid_p &= tdesc_numbered_register (feature_core, tdesc_data.get (),
                                        AARCH64_X0_REGNUM + i,
                                        aarch64_r_register_names[i]);
 
@@ -3283,7 +3492,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       /* Validate the description provides the mandatory V registers
         and allocate their numbers.  */
       for (i = 0; i < ARRAY_SIZE (aarch64_v_register_names); i++)
-       valid_p &= tdesc_numbered_register (feature_fpu, tdesc_data,
+       valid_p &= tdesc_numbered_register (feature_fpu, tdesc_data.get (),
                                            AARCH64_V0_REGNUM + i,
                                            aarch64_v_register_names[i]);
 
@@ -3296,7 +3505,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       /* Validate the description provides the mandatory SVE registers
         and allocate their numbers.  */
       for (i = 0; i < ARRAY_SIZE (aarch64_sve_register_names); i++)
-       valid_p &= tdesc_numbered_register (feature_sve, tdesc_data,
+       valid_p &= tdesc_numbered_register (feature_sve, tdesc_data.get (),
                                            AARCH64_SVE_Z0_REGNUM + i,
                                            aarch64_sve_register_names[i]);
 
@@ -3313,15 +3522,27 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       num_pseudo_regs += 32;   /* add the Bn scalar register pseudos */
     }
 
+  /* Add the TLS register.  */
+  if (feature_tls != nullptr)
+    {
+      tls_regnum = num_regs;
+      /* Validate the descriptor provides the mandatory TLS register
+        and allocate its number.  */
+      valid_p = tdesc_numbered_register (feature_tls, tdesc_data.get (),
+                                        tls_regnum, "tpidr");
+
+      num_regs++;
+    }
+
   /* Add the pauth registers.  */
   if (feature_pauth != NULL)
     {
       first_pauth_regnum = num_regs;
-      pauth_ra_state_offset = num_pseudo_regs;
+      ra_sign_state_offset = num_pseudo_regs;
       /* Validate the descriptor provides the mandatory PAUTH registers and
         allocate their numbers.  */
       for (i = 0; i < ARRAY_SIZE (aarch64_pauth_register_names); i++)
-       valid_p &= tdesc_numbered_register (feature_pauth, tdesc_data,
+       valid_p &= tdesc_numbered_register (feature_pauth, tdesc_data.get (),
                                            first_pauth_regnum + i,
                                            aarch64_pauth_register_names[i]);
 
@@ -3329,16 +3550,27 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       num_pseudo_regs += 1;    /* Count RA_STATE pseudo register.  */
     }
 
-  if (!valid_p)
+  /* Add the MTE registers.  */
+  if (feature_mte != NULL)
     {
-      tdesc_data_cleanup (tdesc_data);
-      return nullptr;
+      first_mte_regnum = num_regs;
+      /* Validate the descriptor provides the mandatory MTE registers and
+        allocate their numbers.  */
+      for (i = 0; i < ARRAY_SIZE (aarch64_mte_register_names); i++)
+       valid_p &= tdesc_numbered_register (feature_mte, tdesc_data.get (),
+                                           first_mte_regnum + i,
+                                           aarch64_mte_register_names[i]);
+
+      num_regs += i;
     }
 
+  if (!valid_p)
+    return nullptr;
+
   /* AArch64 code is always little-endian.  */
   info.byte_order_for_code = BFD_ENDIAN_LITTLE;
 
-  struct gdbarch_tdep *tdep = XCNEW (struct gdbarch_tdep);
+  aarch64_gdbarch_tdep *tdep = new aarch64_gdbarch_tdep;
   struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep);
 
   /* This should be low enough for everything.  */
@@ -3347,8 +3579,10 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->jb_elt_size = 8;
   tdep->vq = vq;
   tdep->pauth_reg_base = first_pauth_regnum;
-  tdep->pauth_ra_state_regnum = (feature_pauth == NULL) ? -1
-                               : pauth_ra_state_offset + num_regs;
+  tdep->ra_sign_state_regnum = (feature_pauth == NULL) ? -1
+                               : ra_sign_state_offset + num_regs;
+  tdep->mte_reg_base = first_mte_regnum;
+  tdep->tls_regnum = tls_regnum;
 
   set_gdbarch_push_dummy_call (gdbarch, aarch64_push_dummy_call);
   set_gdbarch_frame_align (gdbarch, aarch64_frame_align);
@@ -3394,9 +3628,12 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_wchar_signed (gdbarch, 0);
   set_gdbarch_float_format (gdbarch, floatformats_ieee_single);
   set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
-  set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
+  set_gdbarch_long_double_format (gdbarch, floatformats_ieee_quad);
   set_gdbarch_type_align (gdbarch, aarch64_type_align);
 
+  /* Detect whether PC is at a point where the stack has been destroyed.  */
+  set_gdbarch_stack_frame_destroyed_p (gdbarch, aarch64_stack_frame_destroyed_p);
+
   /* Internal <-> external register number maps.  */
   set_gdbarch_dwarf2_reg_to_regnum (gdbarch, aarch64_dwarf_reg_to_regnum);
 
@@ -3409,12 +3646,9 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Virtual tables.  */
   set_gdbarch_vbit_in_delta (gdbarch, 1);
 
-  /* Register architecture.  */
-  aarch64_add_reggroups (gdbarch);
-
   /* Hook in the ABI-specific overrides, if they have been registered.  */
   info.target_desc = tdesc;
-  info.tdesc_data = tdesc_data;
+  info.tdesc_data = tdesc_data.get ();
   gdbarch_init_osabi (info, gdbarch);
 
   dwarf2_frame_set_init_reg (gdbarch, aarch64_dwarf2_frame_init_reg);
@@ -3443,7 +3677,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_get_pc_address_flags (gdbarch, aarch64_get_pc_address_flags);
 
-  tdesc_use_registers (gdbarch, tdesc, tdesc_data);
+  tdesc_use_registers (gdbarch, tdesc, std::move (tdesc_data));
 
   /* Add standard register aliases.  */
   for (i = 0; i < ARRAY_SIZE (aarch64_register_aliases); i++)
@@ -3459,13 +3693,13 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 static void
 aarch64_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
   if (tdep == NULL)
     return;
 
-  fprintf_unfiltered (file, _("aarch64_dump_tdep: Lowest pc = 0x%s"),
-                     paddress (gdbarch, tdep->lowest_pc));
+  gdb_printf (file, _("aarch64_dump_tdep: Lowest pc = 0x%s"),
+             paddress (gdbarch, tdep->lowest_pc));
 }
 
 #if GDB_SELF_TEST
@@ -3502,29 +3736,29 @@ When on, AArch64 specific debugging is enabled."),
 /* AArch64 process record-replay related structures, defines etc.  */
 
 #define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
-        do  \
-          { \
-            unsigned int reg_len = LENGTH; \
-            if (reg_len) \
-              { \
-                REGS = XNEWVEC (uint32_t, reg_len); \
-                memcpy(&REGS[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
-              } \
-          } \
-        while (0)
+       do  \
+         { \
+           unsigned int reg_len = LENGTH; \
+           if (reg_len) \
+             { \
+               REGS = XNEWVEC (uint32_t, reg_len); \
+               memcpy(&REGS[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
+             } \
+         } \
+       while (0)
 
 #define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
-        do  \
-          { \
-            unsigned int mem_len = LENGTH; \
-            if (mem_len) \
-            { \
-              MEMS =  XNEWVEC (struct aarch64_mem_r, mem_len);  \
-              memcpy(&MEMS->len, &RECORD_BUF[0], \
-                     sizeof(struct aarch64_mem_r) * LENGTH); \
-            } \
-          } \
-          while (0)
+       do  \
+         { \
+           unsigned int mem_len = LENGTH; \
+           if (mem_len) \
+             { \
+               MEMS =  XNEWVEC (struct aarch64_mem_r, mem_len);  \
+               memcpy(MEMS, &RECORD_BUF[0], \
+                      sizeof(struct aarch64_mem_r) * LENGTH); \
+             } \
+         } \
+         while (0)
 
 /* AArch64 record/replay structures and enumerations.  */
 
@@ -3541,7 +3775,7 @@ enum aarch64_record_result
   AARCH64_RECORD_UNKNOWN
 };
 
-typedef struct insn_decode_record_t
+struct aarch64_insn_decode_record
 {
   struct gdbarch *gdbarch;
   struct regcache *regcache;
@@ -3551,12 +3785,12 @@ typedef struct insn_decode_record_t
   uint32_t reg_rec_count;              /* Count of register records.  */
   uint32_t *aarch64_regs;              /* Registers to be recorded.  */
   struct aarch64_mem_r *aarch64_mems;  /* Memory locations to be recorded.  */
-} insn_decode_record;
+};
 
 /* Record handler for data processing - register instructions.  */
 
 static unsigned int
-aarch64_record_data_proc_reg (insn_decode_record *aarch64_insn_r)
+aarch64_record_data_proc_reg (aarch64_insn_decode_record *aarch64_insn_r)
 {
   uint8_t reg_rd, insn_bits24_27, insn_bits21_23;
   uint32_t record_buf[4];
@@ -3632,7 +3866,7 @@ aarch64_record_data_proc_reg (insn_decode_record *aarch64_insn_r)
 /* Record handler for data processing - immediate instructions.  */
 
 static unsigned int
-aarch64_record_data_proc_imm (insn_decode_record *aarch64_insn_r)
+aarch64_record_data_proc_imm (aarch64_insn_decode_record *aarch64_insn_r)
 {
   uint8_t reg_rd, insn_bit23, insn_bits24_27, setflags;
   uint32_t record_buf[4];
@@ -3677,9 +3911,11 @@ aarch64_record_data_proc_imm (insn_decode_record *aarch64_insn_r)
 /* Record handler for branch, exception generation and system instructions.  */
 
 static unsigned int
-aarch64_record_branch_except_sys (insn_decode_record *aarch64_insn_r)
+aarch64_record_branch_except_sys (aarch64_insn_decode_record *aarch64_insn_r)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (aarch64_insn_r->gdbarch);
+
+  aarch64_gdbarch_tdep *tdep
+    = gdbarch_tdep<aarch64_gdbarch_tdep> (aarch64_insn_r->gdbarch);
   uint8_t insn_bits24_27, insn_bits28_31, insn_bits22_23;
   uint32_t record_buf[4];
 
@@ -3757,7 +3993,7 @@ aarch64_record_branch_except_sys (insn_decode_record *aarch64_insn_r)
 /* Record handler for advanced SIMD load and store instructions.  */
 
 static unsigned int
-aarch64_record_asimd_load_store (insn_decode_record *aarch64_insn_r)
+aarch64_record_asimd_load_store (aarch64_insn_decode_record *aarch64_insn_r)
 {
   CORE_ADDR address;
   uint64_t addr_offset = 0;
@@ -3782,46 +4018,46 @@ aarch64_record_asimd_load_store (insn_decode_record *aarch64_insn_r)
       uint8_t sindex, scale, selem, esize, replicate = 0;
       scale = opcode_bits >> 2;
       selem = ((opcode_bits & 0x02) |
-              bit (aarch64_insn_r->aarch64_insn, 21)) + 1;
+             bit (aarch64_insn_r->aarch64_insn, 21)) + 1;
       switch (scale)
-        {
-        case 1:
-          if (size_bits & 0x01)
-            return AARCH64_RECORD_UNKNOWN;
-          break;
-        case 2:
-          if ((size_bits >> 1) & 0x01)
-            return AARCH64_RECORD_UNKNOWN;
-          if (size_bits & 0x01)
-            {
-              if (!((opcode_bits >> 1) & 0x01))
-                scale = 3;
-              else
-                return AARCH64_RECORD_UNKNOWN;
-            }
-          break;
-        case 3:
-          if (bit (aarch64_insn_r->aarch64_insn, 22) && !(opcode_bits & 0x01))
-            {
-              scale = size_bits;
-              replicate = 1;
-              break;
-            }
-          else
-            return AARCH64_RECORD_UNKNOWN;
-        default:
-          break;
-        }
+       {
+       case 1:
+         if (size_bits & 0x01)
+           return AARCH64_RECORD_UNKNOWN;
+         break;
+       case 2:
+         if ((size_bits >> 1) & 0x01)
+           return AARCH64_RECORD_UNKNOWN;
+         if (size_bits & 0x01)
+           {
+             if (!((opcode_bits >> 1) & 0x01))
+               scale = 3;
+             else
+               return AARCH64_RECORD_UNKNOWN;
+           }
+         break;
+       case 3:
+         if (bit (aarch64_insn_r->aarch64_insn, 22) && !(opcode_bits & 0x01))
+           {
+             scale = size_bits;
+             replicate = 1;
+             break;
+           }
+         else
+           return AARCH64_RECORD_UNKNOWN;
+       default:
+         break;
+       }
       esize = 8 << scale;
       if (replicate)
-        for (sindex = 0; sindex < selem; sindex++)
-          {
-            record_buf[reg_index++] = reg_rt + AARCH64_V0_REGNUM;
-            reg_rt = (reg_rt + 1) % 32;
-          }
+       for (sindex = 0; sindex < selem; sindex++)
+         {
+           record_buf[reg_index++] = reg_rt + AARCH64_V0_REGNUM;
+           reg_rt = (reg_rt + 1) % 32;
+         }
       else
-        {
-          for (sindex = 0; sindex < selem; sindex++)
+       {
+         for (sindex = 0; sindex < selem; sindex++)
            {
              if (bit (aarch64_insn_r->aarch64_insn, 22))
                record_buf[reg_index++] = reg_rt + AARCH64_V0_REGNUM;
@@ -3833,7 +4069,7 @@ aarch64_record_asimd_load_store (insn_decode_record *aarch64_insn_r)
              addr_offset = addr_offset + (esize / 8);
              reg_rt = (reg_rt + 1) % 32;
            }
-        }
+       }
     }
   /* Load/store multiple structure.  */
   else
@@ -3843,69 +4079,69 @@ aarch64_record_asimd_load_store (insn_decode_record *aarch64_insn_r)
 
       esize = 8 << size_bits;
       if (bit (aarch64_insn_r->aarch64_insn, 30))
-        elements = 128 / esize;
+       elements = 128 / esize;
       else
-        elements = 64 / esize;
+       elements = 64 / esize;
 
       switch (opcode_bits)
-        {
-        /*LD/ST4 (4 Registers).  */
-        case 0:
-          rpt = 1;
-          selem = 4;
-          break;
-        /*LD/ST1 (4 Registers).  */
-        case 2:
-          rpt = 4;
-          selem = 1;
-          break;
-        /*LD/ST3 (3 Registers).  */
-        case 4:
-          rpt = 1;
-          selem = 3;
-          break;
-        /*LD/ST1 (3 Registers).  */
-        case 6:
-          rpt = 3;
-          selem = 1;
-          break;
-        /*LD/ST1 (1 Register).  */
-        case 7:
-          rpt = 1;
-          selem = 1;
-          break;
-        /*LD/ST2 (2 Registers).  */
-        case 8:
-          rpt = 1;
-          selem = 2;
-          break;
-        /*LD/ST1 (2 Registers).  */
-        case 10:
-          rpt = 2;
-          selem = 1;
-          break;
-        default:
-          return AARCH64_RECORD_UNSUPPORTED;
-          break;
-        }
+       {
+       /*LD/ST4 (4 Registers).  */
+       case 0:
+         rpt = 1;
+         selem = 4;
+         break;
+       /*LD/ST1 (4 Registers).  */
+       case 2:
+         rpt = 4;
+         selem = 1;
+         break;
+       /*LD/ST3 (3 Registers).  */
+       case 4:
+         rpt = 1;
+         selem = 3;
+         break;
+       /*LD/ST1 (3 Registers).  */
+       case 6:
+         rpt = 3;
+         selem = 1;
+         break;
+       /*LD/ST1 (1 Register).  */
+       case 7:
+         rpt = 1;
+         selem = 1;
+         break;
+       /*LD/ST2 (2 Registers).  */
+       case 8:
+         rpt = 1;
+         selem = 2;
+         break;
+       /*LD/ST1 (2 Registers).  */
+       case 10:
+         rpt = 2;
+         selem = 1;
+         break;
+       default:
+         return AARCH64_RECORD_UNSUPPORTED;
+         break;
+       }
       for (rindex = 0; rindex < rpt; rindex++)
-        for (eindex = 0; eindex < elements; eindex++)
-          {
-            uint8_t reg_tt, sindex;
-            reg_tt = (reg_rt + rindex) % 32;
-            for (sindex = 0; sindex < selem; sindex++)
-              {
-                if (bit (aarch64_insn_r->aarch64_insn, 22))
-                  record_buf[reg_index++] = reg_tt + AARCH64_V0_REGNUM;
-                else
-                  {
-                    record_buf_mem[mem_index++] = esize / 8;
-                    record_buf_mem[mem_index++] = address + addr_offset;
-                  }
-                addr_offset = addr_offset + (esize / 8);
-                reg_tt = (reg_tt + 1) % 32;
-              }
-          }
+       for (eindex = 0; eindex < elements; eindex++)
+         {
+           uint8_t reg_tt, sindex;
+           reg_tt = (reg_rt + rindex) % 32;
+           for (sindex = 0; sindex < selem; sindex++)
+             {
+               if (bit (aarch64_insn_r->aarch64_insn, 22))
+                 record_buf[reg_index++] = reg_tt + AARCH64_V0_REGNUM;
+               else
+                 {
+                   record_buf_mem[mem_index++] = esize / 8;
+                   record_buf_mem[mem_index++] = address + addr_offset;
+                 }
+               addr_offset = addr_offset + (esize / 8);
+               reg_tt = (reg_tt + 1) % 32;
+             }
+         }
     }
 
   if (bit (aarch64_insn_r->aarch64_insn, 23))
@@ -3914,16 +4150,16 @@ aarch64_record_asimd_load_store (insn_decode_record *aarch64_insn_r)
   aarch64_insn_r->reg_rec_count = reg_index;
   aarch64_insn_r->mem_rec_count = mem_index / 2;
   MEM_ALLOC (aarch64_insn_r->aarch64_mems, aarch64_insn_r->mem_rec_count,
-             record_buf_mem);
+            record_buf_mem);
   REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
-             record_buf);
+            record_buf);
   return AARCH64_RECORD_SUCCESS;
 }
 
 /* Record handler for load and store instructions.  */
 
 static unsigned int
-aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
+aarch64_record_load_store (aarch64_insn_decode_record *aarch64_insn_r)
 {
   uint8_t insn_bits24_27, insn_bits28_29, insn_bits10_11;
   uint8_t insn_bit23, insn_bit21;
@@ -3987,9 +4223,9 @@ aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
       if (record_debug)
        debug_printf ("Process record: load register (literal)\n");
       if (vector_flag)
-        record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
+       record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
       else
-        record_buf[0] = reg_rt;
+       record_buf[0] = reg_rt;
       aarch64_insn_r->reg_rec_count = 1;
     }
   /* All types of load/store pair instructions decoding.  */
@@ -3999,46 +4235,46 @@ aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
        debug_printf ("Process record: load/store pair\n");
 
       if (ld_flag)
-        {
-          if (vector_flag)
-            {
-              record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
-              record_buf[1] = reg_rt2 + AARCH64_V0_REGNUM;
-            }
-          else
-            {
-              record_buf[0] = reg_rt;
-              record_buf[1] = reg_rt2;
-            }
-          aarch64_insn_r->reg_rec_count = 2;
-        }
+       {
+         if (vector_flag)
+           {
+             record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
+             record_buf[1] = reg_rt2 + AARCH64_V0_REGNUM;
+           }
+         else
+           {
+             record_buf[0] = reg_rt;
+             record_buf[1] = reg_rt2;
+           }
+         aarch64_insn_r->reg_rec_count = 2;
+       }
       else
-        {
-          uint16_t imm7_off;
-          imm7_off = bits (aarch64_insn_r->aarch64_insn, 15, 21);
-          if (!vector_flag)
-            size_bits = size_bits >> 1;
-          datasize = 8 << (2 + size_bits);
-          offset = (imm7_off & 0x40) ? (~imm7_off & 0x007f) + 1 : imm7_off;
-          offset = offset << (2 + size_bits);
-          regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
-                                      &address);
-          if (!((insn_bits24_27 & 0x0b) == 0x08 && insn_bit23))
-            {
-              if (imm7_off & 0x40)
-                address = address - offset;
-              else
-                address = address + offset;
-            }
-
-          record_buf_mem[0] = datasize / 8;
-          record_buf_mem[1] = address;
-          record_buf_mem[2] = datasize / 8;
-          record_buf_mem[3] = address + (datasize / 8);
-          aarch64_insn_r->mem_rec_count = 2;
-        }
+       {
+         uint16_t imm7_off;
+         imm7_off = bits (aarch64_insn_r->aarch64_insn, 15, 21);
+         if (!vector_flag)
+           size_bits = size_bits >> 1;
+         datasize = 8 << (2 + size_bits);
+         offset = (imm7_off & 0x40) ? (~imm7_off & 0x007f) + 1 : imm7_off;
+         offset = offset << (2 + size_bits);
+         regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
+                                     &address);
+         if (!((insn_bits24_27 & 0x0b) == 0x08 && insn_bit23))
+           {
+             if (imm7_off & 0x40)
+               address = address - offset;
+             else
+               address = address + offset;
+           }
+
+         record_buf_mem[0] = datasize / 8;
+         record_buf_mem[1] = address;
+         record_buf_mem[2] = datasize / 8;
+         record_buf_mem[3] = address + (datasize / 8);
+         aarch64_insn_r->mem_rec_count = 2;
+       }
       if (bit (aarch64_insn_r->aarch64_insn, 23))
-        record_buf[aarch64_insn_r->reg_rec_count++] = reg_rn;
+       record_buf[aarch64_insn_r->reg_rec_count++] = reg_rn;
     }
   /* Load/store register (unsigned immediate) instructions.  */
   else if ((insn_bits24_27 & 0x0b) == 0x09 && insn_bits28_29 == 0x03)
@@ -4080,26 +4316,26 @@ aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
        }
 
       if (!ld_flag)
-        {
-          offset = bits (aarch64_insn_r->aarch64_insn, 10, 21);
-          datasize = 8 << size_bits;
-          regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
-                                      &address);
-          offset = offset << size_bits;
-          address = address + offset;
-
-          record_buf_mem[0] = datasize >> 3;
-          record_buf_mem[1] = address;
-          aarch64_insn_r->mem_rec_count = 1;
-        }
+       {
+         offset = bits (aarch64_insn_r->aarch64_insn, 10, 21);
+         datasize = 8 << size_bits;
+         regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
+                                     &address);
+         offset = offset << size_bits;
+         address = address + offset;
+
+         record_buf_mem[0] = datasize >> 3;
+         record_buf_mem[1] = address;
+         aarch64_insn_r->mem_rec_count = 1;
+       }
       else
-        {
-          if (vector_flag)
-            record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
-          else
-            record_buf[0] = reg_rt;
-          aarch64_insn_r->reg_rec_count = 1;
-        }
+       {
+         if (vector_flag)
+           record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
+         else
+           record_buf[0] = reg_rt;
+         aarch64_insn_r->reg_rec_count = 1;
+       }
     }
   /* Load/store register (register offset) instructions.  */
   else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x03
@@ -4109,42 +4345,42 @@ aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
        debug_printf ("Process record: load/store (register offset)\n");
       opc = bits (aarch64_insn_r->aarch64_insn, 22, 23);
       if (!(opc >> 1))
-        if (opc & 0x01)
-          ld_flag = 0x01;
-        else
-          ld_flag = 0x0;
+       if (opc & 0x01)
+         ld_flag = 0x01;
+       else
+         ld_flag = 0x0;
       else
-        if (size_bits != 0x03)
-          ld_flag = 0x01;
-        else
-          return AARCH64_RECORD_UNKNOWN;
+       if (size_bits != 0x03)
+         ld_flag = 0x01;
+       else
+         return AARCH64_RECORD_UNKNOWN;
 
       if (!ld_flag)
-        {
-          ULONGEST reg_rm_val;
-
-          regcache_raw_read_unsigned (aarch64_insn_r->regcache,
-                     bits (aarch64_insn_r->aarch64_insn, 16, 20), &reg_rm_val);
-          if (bit (aarch64_insn_r->aarch64_insn, 12))
-            offset = reg_rm_val << size_bits;
-          else
-            offset = reg_rm_val;
-          datasize = 8 << size_bits;
-          regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
-                                      &address);
-          address = address + offset;
-          record_buf_mem[0] = datasize >> 3;
-          record_buf_mem[1] = address;
-          aarch64_insn_r->mem_rec_count = 1;
-        }
+       {
+         ULONGEST reg_rm_val;
+
+         regcache_raw_read_unsigned (aarch64_insn_r->regcache,
+                    bits (aarch64_insn_r->aarch64_insn, 16, 20), &reg_rm_val);
+         if (bit (aarch64_insn_r->aarch64_insn, 12))
+           offset = reg_rm_val << size_bits;
+         else
+           offset = reg_rm_val;
+         datasize = 8 << size_bits;
+         regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
+                                     &address);
+         address = address + offset;
+         record_buf_mem[0] = datasize >> 3;
+         record_buf_mem[1] = address;
+         aarch64_insn_r->mem_rec_count = 1;
+       }
       else
-        {
-          if (vector_flag)
-            record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
-          else
-            record_buf[0] = reg_rt;
-          aarch64_insn_r->reg_rec_count = 1;
-        }
+       {
+         if (vector_flag)
+           record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
+         else
+           record_buf[0] = reg_rt;
+         aarch64_insn_r->reg_rec_count = 1;
+       }
     }
   /* Load/store register (immediate and unprivileged) instructions.  */
   else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x03
@@ -4157,61 +4393,61 @@ aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
        }
       opc = bits (aarch64_insn_r->aarch64_insn, 22, 23);
       if (!(opc >> 1))
-        if (opc & 0x01)
-          ld_flag = 0x01;
-        else
-          ld_flag = 0x0;
+       if (opc & 0x01)
+         ld_flag = 0x01;
+       else
+         ld_flag = 0x0;
       else
-        if (size_bits != 0x03)
-          ld_flag = 0x01;
-        else
-          return AARCH64_RECORD_UNKNOWN;
+       if (size_bits != 0x03)
+         ld_flag = 0x01;
+       else
+         return AARCH64_RECORD_UNKNOWN;
 
       if (!ld_flag)
-        {
-          uint16_t imm9_off;
-          imm9_off = bits (aarch64_insn_r->aarch64_insn, 12, 20);
-          offset = (imm9_off & 0x0100) ? (((~imm9_off) & 0x01ff) + 1) : imm9_off;
-          datasize = 8 << size_bits;
-          regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
-                                      &address);
-          if (insn_bits10_11 != 0x01)
-            {
-              if (imm9_off & 0x0100)
-                address = address - offset;
-              else
-                address = address + offset;
-            }
-          record_buf_mem[0] = datasize >> 3;
-          record_buf_mem[1] = address;
-          aarch64_insn_r->mem_rec_count = 1;
-        }
+       {
+         uint16_t imm9_off;
+         imm9_off = bits (aarch64_insn_r->aarch64_insn, 12, 20);
+         offset = (imm9_off & 0x0100) ? (((~imm9_off) & 0x01ff) + 1) : imm9_off;
+         datasize = 8 << size_bits;
+         regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
+                                     &address);
+         if (insn_bits10_11 != 0x01)
+           {
+             if (imm9_off & 0x0100)
+               address = address - offset;
+             else
+               address = address + offset;
+           }
+         record_buf_mem[0] = datasize >> 3;
+         record_buf_mem[1] = address;
+         aarch64_insn_r->mem_rec_count = 1;
+       }
       else
-        {
-          if (vector_flag)
-            record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
-          else
-            record_buf[0] = reg_rt;
-          aarch64_insn_r->reg_rec_count = 1;
-        }
+       {
+         if (vector_flag)
+           record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
+         else
+           record_buf[0] = reg_rt;
+         aarch64_insn_r->reg_rec_count = 1;
+       }
       if (insn_bits10_11 == 0x01 || insn_bits10_11 == 0x03)
-        record_buf[aarch64_insn_r->reg_rec_count++] = reg_rn;
+       record_buf[aarch64_insn_r->reg_rec_count++] = reg_rn;
     }
   /* Advanced SIMD load/store instructions.  */
   else
     return aarch64_record_asimd_load_store (aarch64_insn_r);
 
   MEM_ALLOC (aarch64_insn_r->aarch64_mems, aarch64_insn_r->mem_rec_count,
-             record_buf_mem);
+            record_buf_mem);
   REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
-             record_buf);
+            record_buf);
   return AARCH64_RECORD_SUCCESS;
 }
 
 /* Record handler for data processing SIMD and floating point instructions.  */
 
 static unsigned int
-aarch64_record_data_proc_simd_fp (insn_decode_record *aarch64_insn_r)
+aarch64_record_data_proc_simd_fp (aarch64_insn_decode_record *aarch64_insn_r)
 {
   uint8_t insn_bit21, opcode, rmode, reg_rd;
   uint8_t insn_bits24_27, insn_bits28_31, insn_bits10_11, insn_bits12_15;
@@ -4253,7 +4489,7 @@ aarch64_record_data_proc_simd_fp (insn_decode_record *aarch64_insn_r)
          record_buf[0] = AARCH64_CPSR_REGNUM;
        }
       /* Floating point - data processing (2-source) and
-         conditional select instructions.  */
+        conditional select instructions.  */
       else if (insn_bits10_11 == 0x02 || insn_bits10_11 == 0x03)
        {
          if (record_debug)
@@ -4310,10 +4546,10 @@ aarch64_record_data_proc_simd_fp (insn_decode_record *aarch64_insn_r)
                }
              else
                return AARCH64_RECORD_UNKNOWN;
-            }
+           }
          else
            return AARCH64_RECORD_UNKNOWN;
-        }
+       }
       else
        return AARCH64_RECORD_UNKNOWN;
     }
@@ -4347,8 +4583,15 @@ aarch64_record_data_proc_simd_fp (insn_decode_record *aarch64_insn_r)
   if (record_debug)
     debug_printf ("\n");
 
+  /* Record the V/X register.  */
+  aarch64_insn_r->reg_rec_count++;
+
+  /* Some of these instructions may set bits in the FPSR, so record it
+     too.  */
+  record_buf[1] = AARCH64_FPSR_REGNUM;
   aarch64_insn_r->reg_rec_count++;
-  gdb_assert (aarch64_insn_r->reg_rec_count == 1);
+
+  gdb_assert (aarch64_insn_r->reg_rec_count == 2);
   REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
             record_buf);
   return AARCH64_RECORD_SUCCESS;
@@ -4357,7 +4600,7 @@ aarch64_record_data_proc_simd_fp (insn_decode_record *aarch64_insn_r)
 /* Decodes insns type and invokes its record handler.  */
 
 static unsigned int
-aarch64_record_decode_insn_handler (insn_decode_record *aarch64_insn_r)
+aarch64_record_decode_insn_handler (aarch64_insn_decode_record *aarch64_insn_r)
 {
   uint32_t ins_bit25, ins_bit26, ins_bit27, ins_bit28;
 
@@ -4392,7 +4635,7 @@ aarch64_record_decode_insn_handler (insn_decode_record *aarch64_insn_r)
 /* Cleans up local record registers and memory allocations.  */
 
 static void
-deallocate_reg_mem (insn_decode_record *record)
+deallocate_reg_mem (aarch64_insn_decode_record *record)
 {
   xfree (record->aarch64_regs);
   xfree (record->aarch64_mems);
@@ -4407,15 +4650,14 @@ aarch64_process_record_test (void)
   struct gdbarch_info info;
   uint32_t ret;
 
-  gdbarch_info_init (&info);
   info.bfd_arch_info = bfd_scan_arch ("aarch64");
 
   struct gdbarch *gdbarch = gdbarch_find_by_info (info);
   SELF_CHECK (gdbarch != NULL);
 
-  insn_decode_record aarch64_record;
+  aarch64_insn_decode_record aarch64_record;
 
-  memset (&aarch64_record, 0, sizeof (insn_decode_record));
+  memset (&aarch64_record, 0, sizeof (aarch64_insn_decode_record));
   aarch64_record.regcache = NULL;
   aarch64_record.this_addr = 0;
   aarch64_record.gdbarch = gdbarch;
@@ -4445,10 +4687,10 @@ aarch64_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
   uint8_t insn_size = 4;
   uint32_t ret = 0;
   gdb_byte buf[insn_size];
-  insn_decode_record aarch64_record;
+  aarch64_insn_decode_record aarch64_record;
 
   memset (&buf[0], 0, insn_size);
-  memset (&aarch64_record, 0, sizeof (insn_decode_record));
+  memset (&aarch64_record, 0, sizeof (aarch64_insn_decode_record));
   target_read_memory (insn_addr, &buf[0], insn_size);
   aarch64_record.aarch64_insn
     = (uint32_t) extract_unsigned_integer (&buf[0],
@@ -4461,10 +4703,11 @@ aarch64_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
   ret = aarch64_record_decode_insn_handler (&aarch64_record);
   if (ret == AARCH64_RECORD_UNSUPPORTED)
     {
-      printf_unfiltered (_("Process record does not support instruction "
-                          "0x%0x at address %s.\n"),
-                        aarch64_record.aarch64_insn,
-                        paddress (gdbarch, insn_addr));
+      gdb_printf (gdb_stderr,
+                 _("Process record does not support instruction "
+                   "0x%0x at address %s.\n"),
+                 aarch64_record.aarch64_insn,
+                 paddress (gdbarch, insn_addr));
       ret = -1;
     }