gdb/riscv: Fix an ARI warning
[deliverable/binutils-gdb.git] / gdb / riscv-tdep.c
index 3e1ad99c673df28bab02dacb6332f6d3b6d9bf34..254914c9c7e2b86f3392913aba4bfc510d042501 100644 (file)
@@ -2,11 +2,6 @@
 
    Copyright (C) 2018 Free Software Foundation, Inc.
 
-   Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
-   and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin
-   and by Todd Snyder <todd@bluespec.com>
-   and by Mike Frysinger <vapier@gentoo.org>.
-
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
 #include "common-defs.h"
 #include "opcode/riscv-opc.h"
 #include "cli/cli-decode.h"
-#include "observer.h"
+#include "observable.h"
+#include "prologue-value.h"
 
 /* The stack must be 16-byte aligned.  */
 #define SP_ALIGNMENT 16
 
 /* Forward declarations.  */
 static bool riscv_has_feature (struct gdbarch *gdbarch, char feature);
-struct riscv_inferior_data;
-struct riscv_inferior_data * riscv_inferior_data (struct inferior *const inf);
 
 /* Define a series of is_XXX_insn functions to check if the value INSN
    is an instance of instruction XXX.  */
@@ -78,21 +72,28 @@ static inline bool is_ ## INSN_NAME ## _insn (long insn) \
 #include "opcode/riscv-opc.h"
 #undef DECLARE_INSN
 
-/* Per inferior information for RiscV.  */
+/* Cached information about a frame.  */
 
-struct riscv_inferior_data
+struct riscv_unwind_cache
 {
-  /* True when MISA_VALUE is valid, otherwise false.  */
-  bool misa_read;
+  /* The register from which we can calculate the frame base.  This is
+     usually $sp or $fp.  */
+  int frame_base_reg;
 
-  /* If MISA_READ is true then MISA_VALUE holds the value of the MISA
-     register read from the target.  */
-  uint32_t misa_value;
-};
+  /* The offset from the current value in register FRAME_BASE_REG to the
+     actual frame base address.  */
+  int frame_base_offset;
 
-/* Key created when the RiscV per-inferior data is registered.  */
+  /* Information about previous register values.  */
+  struct trad_frame_saved_reg *regs;
 
-static const struct inferior_data *riscv_inferior_data_reg;
+  /* The id for this frame.  */
+  struct frame_id this_id;
+
+  /* The base (stack) address for this frame.  This is the stack pointer
+     value on entry to this frame before any adjustments are made.  */
+  CORE_ADDR frame_base;
+};
 
 /* Architectural name for core registers.  */
 
@@ -133,8 +134,8 @@ static const struct register_alias riscv_register_aliases[] =
   { "t0", 5 },
   { "t1", 6 },
   { "t2", 7 },
-  { "fp", 8 },
   { "s0", 8 },
+  { "fp", 8 },
   { "s1", 9 },
   { "a0", 10 },
   { "a1", 11 },
@@ -288,6 +289,11 @@ show_riscv_debug_variable (struct ui_file *file, int from_tty,
 
 static unsigned int riscv_debug_infcall = 0;
 
+/* When this is set to non-zero debugging information about stack unwinding
+   will be printed.  */
+
+static unsigned int riscv_debug_unwinder = 0;
+
 /* Read the MISA register from the target.  The register will only be read
    once, and the value read will be cached.  If the register can't be read
    from the target then a default value (0) will be returned.  If the
@@ -298,17 +304,16 @@ static unsigned int riscv_debug_infcall = 0;
 static uint32_t
 riscv_read_misa_reg (bool *read_p)
 {
-  struct riscv_inferior_data *inf_data
-    = riscv_inferior_data (current_inferior ());
+  uint32_t value = 0;
 
-  if (!inf_data->misa_read && target_has_registers)
+  if (target_has_registers)
     {
-      uint32_t value = 0;
       struct frame_info *frame = get_current_frame ();
 
       TRY
        {
-         value = get_frame_register_unsigned (frame, RISCV_CSR_MISA_REGNUM);
+         value = get_frame_register_unsigned (frame,
+                                              RISCV_CSR_MISA_REGNUM);
        }
       CATCH (ex, RETURN_MASK_ERROR)
        {
@@ -317,15 +322,9 @@ riscv_read_misa_reg (bool *read_p)
                                               RISCV_CSR_LEGACY_MISA_REGNUM);
        }
       END_CATCH
-
-      inf_data->misa_read = true;
-      inf_data->misa_value = value;
     }
 
-  if (read_p != nullptr)
-    *read_p = inf_data->misa_read;
-
-  return inf_data->misa_value;
+  return value;
 }
 
 /* Return true if FEATURE is available for the architecture GDBARCH.  The
@@ -340,23 +339,7 @@ riscv_has_feature (struct gdbarch *gdbarch, char feature)
 
   gdb_assert (feature >= 'A' && feature <= 'Z');
 
-  /* It would be nice to always check with the real target where possible,
-     however, for compressed instructions this is a bad idea.
-
-     The call to `set_gdbarch_decr_pc_after_break' is made just once per
-     GDBARCH and we decide at that point if we should decrement by 2 or 4
-     bytes based on whether the BFD has compressed instruction support or
-     not.
-
-     If the BFD was not compiled with compressed instruction support, but we
-     are running on a target with compressed instructions then we might
-     place a 4-byte breakpoint, then decrement the $pc by 2 bytes leading to
-     confusion.
-
-     It's safer if we just make decisions about compressed instruction
-     support based on the BFD.  */
-  if (feature != 'C')
-    misa = riscv_read_misa_reg (&have_read_misa);
+  misa = riscv_read_misa_reg (&have_read_misa);
   if (!have_read_misa || misa == 0)
     misa = gdbarch_tdep (gdbarch)->core_features;
 
@@ -367,13 +350,14 @@ riscv_has_feature (struct gdbarch *gdbarch, char feature)
    Possible return values are 4, 8, or 16 for RiscV variants RV32, RV64, or
    RV128.  */
 
-static int
+int
 riscv_isa_xlen (struct gdbarch *gdbarch)
 {
   switch (gdbarch_tdep (gdbarch)->abi.fields.base_len)
     {
     default:
       warning (_("unknown xlen size, assuming 4 bytes"));
+      /* Fall through.  */
     case 1:
       return 4;
     case 2:
@@ -417,6 +401,15 @@ riscv_has_fp_abi (struct gdbarch *gdbarch)
   return (gdbarch_tdep (gdbarch)->abi.fields.float_abi != 0);
 }
 
+/* Return true if REGNO is a floating pointer register.  */
+
+static bool
+riscv_is_fp_regno_p (int regno)
+{
+  return (regno >= RISCV_FIRST_FP_REGNUM
+         && regno <= RISCV_LAST_FP_REGNUM);
+}
+
 /* Implement the breakpoint_kind_from_pc gdbarch method.  */
 
 static int
@@ -451,7 +444,7 @@ riscv_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
     case 4:
       return ebreak;
     default:
-      gdb_assert_not_reached ("unhandled breakpoint kind");
+      gdb_assert_not_reached (_("unhandled breakpoint kind"));
     }
 }
 
@@ -469,9 +462,6 @@ value_of_riscv_user_reg (struct frame_info *frame, const void *baton)
 static const char *
 riscv_register_name (struct gdbarch *gdbarch, int regnum)
 {
-  if (tdesc_has_registers (gdbarch_target_desc (gdbarch)))
-    return tdesc_register_name (gdbarch, regnum);
-
   /* Prefer to use the alias. */
   if (regnum >= RISCV_ZERO_REGNUM && regnum <= RISCV_LAST_REGNUM)
     {
@@ -489,7 +479,8 @@ riscv_register_name (struct gdbarch *gdbarch, int regnum)
     {
       static char buf[20];
 
-      sprintf (buf, "csr%d", regnum - RISCV_FIRST_CSR_REGNUM);
+      xsnprintf (buf, sizeof (buf), "csr%d",
+                regnum - RISCV_FIRST_CSR_REGNUM);
       return buf;
     }
 
@@ -499,28 +490,6 @@ riscv_register_name (struct gdbarch *gdbarch, int regnum)
   return NULL;
 }
 
-/* Implement the pseudo_register_read gdbarch method.  */
-
-static enum register_status
-riscv_pseudo_register_read (struct gdbarch *gdbarch,
-                           readable_regcache *regcache,
-                           int regnum,
-                           gdb_byte *buf)
-{
-  return regcache->raw_read (regnum, buf);
-}
-
-/* Implement the pseudo_register_write gdbarch method.  */
-
-static void
-riscv_pseudo_register_write (struct gdbarch *gdbarch,
-                            struct regcache *regcache,
-                            int cookednum,
-                            const gdb_byte *buf)
-{
-  regcache_raw_write (regcache, cookednum, buf);
-}
-
 /* Implement the register_type gdbarch method.  */
 
 static struct type *
@@ -792,8 +761,6 @@ static int
 riscv_register_reggroup_p (struct gdbarch  *gdbarch, int regnum,
                           struct reggroup *reggroup)
 {
-  int float_p;
-  int raw_p;
   unsigned int i;
 
   /* Used by 'info registers' and 'info registers <groupname>'.  */
@@ -815,10 +782,10 @@ riscv_register_reggroup_p (struct gdbarch  *gdbarch, int regnum,
       return 0;
     }
   else if (reggroup == float_reggroup)
-    return ((regnum >= RISCV_FIRST_FP_REGNUM && regnum <= RISCV_LAST_FP_REGNUM)
-           || (regnum == RISCV_CSR_FCSR_REGNUM
-               || regnum == RISCV_CSR_FFLAGS_REGNUM
-               || regnum == RISCV_CSR_FRM_REGNUM));
+    return (riscv_is_fp_regno_p (regnum)
+           || regnum == RISCV_CSR_FCSR_REGNUM
+           || regnum == RISCV_CSR_FFLAGS_REGNUM
+           || regnum == RISCV_CSR_FRM_REGNUM);
   else if (reggroup == general_reggroup)
     return regnum < RISCV_FIRST_FP_REGNUM;
   else if (reggroup == restore_reggroup || reggroup == save_reggroup)
@@ -917,6 +884,18 @@ public:
       LUI,
       SD,
       SW,
+      /* These are needed for software breakopint support.  */
+      JAL,
+      JALR,
+      BEQ,
+      BNE,
+      BLT,
+      BGE,
+      BLTU,
+      BGEU,
+      /* These are needed for stepping over atomic sequences.  */
+      LR,
+      SC,
 
       /* Other instructions are not interesting during the prologue scan, and
         are ignored.  */
@@ -973,6 +952,12 @@ private:
     return (opcode >> offset) & 0x1F;
   }
 
+  /* Extract 5 bit register field at OFFSET from instruction OPCODE.  */
+  int decode_register_index_short (unsigned long opcode, int offset)
+  {
+    return ((opcode >> offset) & 0x7) + 8;
+  }
+
   /* Helper for DECODE, decode 32-bit R-type instruction.  */
   void decode_r_type_insn (enum opcode opcode, ULONGEST ival)
   {
@@ -1016,6 +1001,31 @@ private:
     m_imm.s = EXTRACT_STYPE_IMM (ival);
   }
 
+  /* Helper for DECODE, decode 16-bit CS-type instruction.  The immediate
+     encoding is different for each CS format instruction, so extracting
+     the immediate is left up to the caller, who should pass the extracted
+     immediate value through in IMM.  */
+  void decode_cs_type_insn (enum opcode opcode, ULONGEST ival, int imm)
+  {
+    m_opcode = opcode;
+    m_imm.s = imm;
+    m_rs1 = decode_register_index_short (ival, OP_SH_CRS1S);
+    m_rs2 = decode_register_index_short (ival, OP_SH_CRS2S);
+  }
+
+  /* Helper for DECODE, decode 16-bit CSS-type instruction.  The immediate
+     encoding is different for each CSS format instruction, so extracting
+     the immediate is left up to the caller, who should pass the extracted
+     immediate value through in IMM.  */
+  void decode_css_type_insn (enum opcode opcode, ULONGEST ival, int imm)
+  {
+    m_opcode = opcode;
+    m_imm.s = imm;
+    m_rs1 = RISCV_SP_REGNUM;
+    /* Not a compressed register number in this case.  */
+    m_rs2 = decode_register_index (ival, OP_SH_CRS2);
+  }
+
   /* Helper for DECODE, decode 32-bit U-type instruction.  */
   void decode_u_type_insn (enum opcode opcode, ULONGEST ival)
   {
@@ -1024,6 +1034,36 @@ private:
     m_imm.s = EXTRACT_UTYPE_IMM (ival);
   }
 
+  /* Helper for DECODE, decode 32-bit J-type instruction.  */
+  void decode_j_type_insn (enum opcode opcode, ULONGEST ival)
+  {
+    m_opcode = opcode;
+    m_rd = decode_register_index (ival, OP_SH_RD);
+    m_imm.s = EXTRACT_UJTYPE_IMM (ival);
+  }
+
+  /* Helper for DECODE, decode 32-bit J-type instruction.  */
+  void decode_cj_type_insn (enum opcode opcode, ULONGEST ival)
+  {
+    m_opcode = opcode;
+    m_imm.s = EXTRACT_RVC_J_IMM (ival);
+  }
+
+  void decode_b_type_insn (enum opcode opcode, ULONGEST ival)
+  {
+    m_opcode = opcode;
+    m_rs1 = decode_register_index (ival, OP_SH_RS1);
+    m_rs2 = decode_register_index (ival, OP_SH_RS2);
+    m_imm.s = EXTRACT_SBTYPE_IMM (ival);
+  }
+
+  void decode_cb_type_insn (enum opcode opcode, ULONGEST ival)
+  {
+    m_opcode = opcode;
+    m_rs1 = decode_register_index_short (ival, OP_SH_CRS1S);
+    m_imm.s = EXTRACT_RVC_B_IMM (ival);
+  }
+
   /* Fetch instruction from target memory at ADDR, return the content of
      the instruction, and update LEN with the instruction length.  */
   static ULONGEST fetch_instruction (struct gdbarch *gdbarch,
@@ -1079,12 +1119,10 @@ riscv_insn::fetch_instruction (struct gdbarch *gdbarch,
 
   /* If we need more, grab it now.  */
   instlen = riscv_insn_length (buf[0]);
+  gdb_assert (instlen <= sizeof (buf));
   *len = instlen;
-  if (instlen > sizeof (buf))
-    internal_error (__FILE__, __LINE__,
-                   _("%s: riscv_insn_length returned %i"),
-                   __func__, instlen);
-  else if (instlen > 2)
+
+  if (instlen > 2)
     {
       status = target_read_memory (addr + 2, buf + 2, instlen - 2);
       if (status)
@@ -1122,32 +1160,94 @@ riscv_insn::decode (struct gdbarch *gdbarch, CORE_ADDR pc)
        decode_s_type_insn (SD, ival);
       else if (is_sw_insn (ival))
        decode_s_type_insn (SW, ival);
+      else if (is_jal_insn (ival))
+       decode_j_type_insn (JAL, ival);
+      else if (is_jalr_insn (ival))
+       decode_i_type_insn (JALR, ival);
+      else if (is_beq_insn (ival))
+       decode_b_type_insn (BEQ, ival);
+      else if (is_bne_insn (ival))
+       decode_b_type_insn (BNE, ival);
+      else if (is_blt_insn (ival))
+       decode_b_type_insn (BLT, ival);
+      else if (is_bge_insn (ival))
+       decode_b_type_insn (BGE, ival);
+      else if (is_bltu_insn (ival))
+       decode_b_type_insn (BLTU, ival);
+      else if (is_bgeu_insn (ival))
+       decode_b_type_insn (BGEU, ival);
+      else if (is_lr_w_insn (ival))
+       decode_r_type_insn (LR, ival);
+      else if (is_lr_d_insn (ival))
+       decode_r_type_insn (LR, ival);
+      else if (is_sc_w_insn (ival))
+       decode_r_type_insn (SC, ival);
+      else if (is_sc_d_insn (ival))
+       decode_r_type_insn (SC, ival);
       else
        /* None of the other fields are valid in this case.  */
        m_opcode = OTHER;
     }
   else if (m_length == 2)
     {
-      if (is_c_add_insn (ival))
+      int xlen = riscv_isa_xlen (gdbarch);
+
+      /* C_ADD and C_JALR have the same opcode.  If RS2 is 0, then this is a
+        C_JALR.  So must try to match C_JALR first as it has more bits in
+        mask.  */
+      if (is_c_jalr_insn (ival))
+       decode_cr_type_insn (JALR, ival);
+      else if (is_c_add_insn (ival))
        decode_cr_type_insn (ADD, ival);
-      else if (is_c_addw_insn (ival))
+      /* C_ADDW is RV64 and RV128 only.  */
+      else if (xlen != 4 && is_c_addw_insn (ival))
        decode_cr_type_insn (ADDW, ival);
       else if (is_c_addi_insn (ival))
        decode_ci_type_insn (ADDI, ival);
-      else if (is_c_addiw_insn (ival))
+      /* C_ADDIW and C_JAL have the same opcode.  C_ADDIW is RV64 and RV128
+        only and C_JAL is RV32 only.  */
+      else if (xlen != 4 && is_c_addiw_insn (ival))
        decode_ci_type_insn (ADDIW, ival);
+      else if (xlen == 4 && is_c_jal_insn (ival))
+       decode_cj_type_insn (JAL, ival);
+      /* C_ADDI16SP and C_LUI have the same opcode.  If RD is 2, then this is a
+        C_ADDI16SP.  So must try to match C_ADDI16SP first as it has more bits
+        in mask.  */
       else if (is_c_addi16sp_insn (ival))
        {
          m_opcode = ADDI;
          m_rd = m_rs1 = decode_register_index (ival, OP_SH_RD);
          m_imm.s = EXTRACT_RVC_ADDI16SP_IMM (ival);
        }
-      else if (is_lui_insn (ival))
-       m_opcode = OTHER;
-      else if (is_c_sd_insn (ival))
-       m_opcode = OTHER;
-      else if (is_sw_insn (ival))
+      else if (is_c_addi4spn_insn (ival))
+       {
+         m_opcode = ADDI;
+         m_rd = decode_register_index_short (ival, OP_SH_CRS2S);
+         m_rs1 = RISCV_SP_REGNUM;
+         m_imm.s = EXTRACT_RVC_ADDI4SPN_IMM (ival);
+       }
+      else if (is_c_lui_insn (ival))
        m_opcode = OTHER;
+      /* C_SD and C_FSW have the same opcode.  C_SD is RV64 and RV128 only,
+        and C_FSW is RV32 only.  */
+      else if (xlen != 4 && is_c_sd_insn (ival))
+       decode_cs_type_insn (SD, ival, EXTRACT_RVC_LD_IMM (ival));
+      else if (is_c_sw_insn (ival))
+       decode_cs_type_insn (SW, ival, EXTRACT_RVC_LW_IMM (ival));
+      else if (is_c_swsp_insn (ival))
+       decode_css_type_insn (SW, ival, EXTRACT_RVC_SWSP_IMM (ival));
+      else if (xlen != 4 && is_c_sdsp_insn (ival))
+       decode_css_type_insn (SW, ival, EXTRACT_RVC_SDSP_IMM (ival));
+      /* C_JR and C_MV have the same opcode.  If RS2 is 0, then this is a C_JR.
+        So must try to match C_JR first as it ahs more bits in mask.  */
+      else if (is_c_jr_insn (ival))
+       decode_cr_type_insn (JALR, ival);
+      else if (is_c_j_insn (ival))
+       decode_cj_type_insn (JAL, ival);
+      else if (is_c_beqz_insn (ival))
+       decode_cb_type_insn (BEQ, ival);
+      else if (is_c_bnez_insn (ival))
+       decode_cb_type_insn (BNE, ival);
       else
        /* None of the other fields of INSN are valid in this case.  */
        m_opcode = OTHER;
@@ -1169,16 +1269,34 @@ riscv_insn::decode (struct gdbarch *gdbarch, CORE_ADDR pc)
 
 static CORE_ADDR
 riscv_scan_prologue (struct gdbarch *gdbarch,
-                    CORE_ADDR start_pc, CORE_ADDR limit_pc)
+                    CORE_ADDR start_pc, CORE_ADDR end_pc,
+                    struct riscv_unwind_cache *cache)
 {
-  CORE_ADDR cur_pc, next_pc;
-  long frame_offset = 0;
+  CORE_ADDR cur_pc, next_pc, after_prologue_pc;
   CORE_ADDR end_prologue_addr = 0;
 
-  if (limit_pc > start_pc + 200)
-    limit_pc = start_pc + 200;
-
-  for (next_pc = cur_pc = start_pc; cur_pc < limit_pc; cur_pc = next_pc)
+  /* Find an upper limit on the function prologue using the debug
+     information.  If the debug information could not be used to provide
+     that bound, then use an arbitrary large number as the upper bound.  */
+  after_prologue_pc = skip_prologue_using_sal (gdbarch, start_pc);
+  if (after_prologue_pc == 0)
+    after_prologue_pc = start_pc + 100;   /* Arbitrary large number.  */
+  if (after_prologue_pc < end_pc)
+    end_pc = after_prologue_pc;
+
+  pv_t regs[RISCV_NUM_INTEGER_REGS]; /* Number of GPR.  */
+  for (int regno = 0; regno < RISCV_NUM_INTEGER_REGS; regno++)
+    regs[regno] = pv_register (regno, 0);
+  pv_area stack (RISCV_SP_REGNUM, gdbarch_addr_bit (gdbarch));
+
+  if (riscv_debug_unwinder)
+    fprintf_unfiltered
+      (gdb_stdlog,
+       "Prologue scan for function starting at %s (limit %s)\n",
+       core_addr_to_string (start_pc),
+       core_addr_to_string (end_pc));
+
+  for (next_pc = cur_pc = start_pc; cur_pc < end_pc; cur_pc = next_pc)
     {
       struct riscv_insn insn;
 
@@ -1196,10 +1314,10 @@ riscv_scan_prologue (struct gdbarch *gdbarch,
        {
          /* Handle: addi sp, sp, -i
             or:     addiw sp, sp, -i  */
-         if (insn.imm_signed () < 0)
-           frame_offset += insn.imm_signed ();
-         else
-           break;
+          gdb_assert (insn.rd () < RISCV_NUM_INTEGER_REGS);
+          gdb_assert (insn.rs1 () < RISCV_NUM_INTEGER_REGS);
+          regs[insn.rd ()]
+            = pv_add_constant (regs[insn.rs1 ()], insn.imm_signed ());
        }
       else if ((insn.opcode () == riscv_insn::SW
                || insn.opcode () == riscv_insn::SD)
@@ -1211,6 +1329,11 @@ riscv_scan_prologue (struct gdbarch *gdbarch,
             or:     sw reg, offset(s0)
             or:     sd reg, offset(s0)  */
          /* Instruction storing a register onto the stack.  */
+          gdb_assert (insn.rs1 () < RISCV_NUM_INTEGER_REGS);
+          gdb_assert (insn.rs2 () < RISCV_NUM_INTEGER_REGS);
+          stack.store (pv_add_constant (regs[insn.rs1 ()], insn.imm_signed ()),
+                        (insn.opcode () == riscv_insn::SW ? 4 : 8),
+                        regs[insn.rs2 ()]);
        }
       else if (insn.opcode () == riscv_insn::ADDI
               && insn.rd () == RISCV_FP_REGNUM
@@ -1218,6 +1341,10 @@ riscv_scan_prologue (struct gdbarch *gdbarch,
        {
          /* Handle: addi s0, sp, size  */
          /* Instructions setting up the frame pointer.  */
+          gdb_assert (insn.rd () < RISCV_NUM_INTEGER_REGS);
+          gdb_assert (insn.rs1 () < RISCV_NUM_INTEGER_REGS);
+          regs[insn.rd ()]
+            = pv_add_constant (regs[insn.rs1 ()], insn.imm_signed ());
        }
       else if ((insn.opcode () == riscv_insn::ADD
                || insn.opcode () == riscv_insn::ADDW)
@@ -1228,6 +1355,9 @@ riscv_scan_prologue (struct gdbarch *gdbarch,
          /* Handle: add s0, sp, 0
             or:     addw s0, sp, 0  */
          /* Instructions setting up the frame pointer.  */
+          gdb_assert (insn.rd () < RISCV_NUM_INTEGER_REGS);
+          gdb_assert (insn.rs1 () < RISCV_NUM_INTEGER_REGS);
+          regs[insn.rd ()] = pv_add_constant (regs[insn.rs1 ()], 0);
        }
       else if ((insn.rd () == RISCV_GP_REGNUM
                && (insn.opcode () == riscv_insn::AUIPC
@@ -1253,24 +1383,63 @@ riscv_scan_prologue (struct gdbarch *gdbarch,
        }
       else
        {
-         if (end_prologue_addr == 0)
-           end_prologue_addr = cur_pc;
+         end_prologue_addr = cur_pc;
+         break;
        }
     }
 
   if (end_prologue_addr == 0)
     end_prologue_addr = cur_pc;
 
+  if (riscv_debug_unwinder)
+    fprintf_unfiltered (gdb_stdlog, "End of prologue at %s\n",
+                       core_addr_to_string (end_prologue_addr));
+
+  if (cache != NULL)
+    {
+      /* Figure out if it is a frame pointer or just a stack pointer.  Also
+         the offset held in the pv_t is from the original register value to
+         the current value, which for a grows down stack means a negative
+         value.  The FRAME_BASE_OFFSET is the negation of this, how to get
+         from the current value to the original value.  */
+      if (pv_is_register (regs[RISCV_FP_REGNUM], RISCV_SP_REGNUM))
+       {
+          cache->frame_base_reg = RISCV_FP_REGNUM;
+          cache->frame_base_offset = -regs[RISCV_FP_REGNUM].k;
+       }
+      else
+       {
+          cache->frame_base_reg = RISCV_SP_REGNUM;
+          cache->frame_base_offset = -regs[RISCV_SP_REGNUM].k;
+       }
+
+      /* Assign offset from old SP to all saved registers.  As we don't
+         have the previous value for the frame base register at this
+         point, we store the offset as the address in the trad_frame, and
+         then convert this to an actual address later.  */
+      for (int i = 0; i <= RISCV_NUM_INTEGER_REGS; i++)
+       {
+         CORE_ADDR offset;
+         if (stack.find_reg (gdbarch, i, &offset))
+            {
+              if (riscv_debug_unwinder)
+                fprintf_unfiltered (gdb_stdlog,
+                                    "Register $%s at stack offset %ld\n",
+                                    gdbarch_register_name (gdbarch, i),
+                                    offset);
+              trad_frame_set_addr (cache->regs, i, offset);
+            }
+       }
+    }
+
   return end_prologue_addr;
 }
 
 /* Implement the riscv_skip_prologue gdbarch method.  */
 
 static CORE_ADDR
-riscv_skip_prologue (struct gdbarch *gdbarch,
-                    CORE_ADDR       pc)
+riscv_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
-  CORE_ADDR limit_pc;
   CORE_ADDR func_addr;
 
   /* See if we can determine the end of the prologue via the symbol
@@ -1286,16 +1455,9 @@ riscv_skip_prologue (struct gdbarch *gdbarch,
     }
 
   /* Can't determine prologue from the symbol table, need to examine
-     instructions.  */
-
-  /* Find an upper limit on the function prologue using the debug
-     information.  If the debug information could not be used to provide
-     that bound, then use an arbitrary large number as the upper bound.  */
-  limit_pc = skip_prologue_using_sal (gdbarch, pc);
-  if (limit_pc == 0)
-    limit_pc = pc + 100;   /* MAGIC! */
-
-  return riscv_scan_prologue (gdbarch, pc, limit_pc);
+     instructions.  Pass -1 for the end address to indicate the prologue
+     scanner can scan as far as it needs to find the end of the prologue.  */
+  return riscv_scan_prologue (gdbarch, pc, ((CORE_ADDR) -1), NULL);
 }
 
 /* Implement the gdbarch push dummy code callback.  */
@@ -1969,12 +2131,8 @@ riscv_print_arg_location (ui_file *stream, struct gdbarch *gdbarch,
                          struct riscv_arg_info *info,
                          CORE_ADDR sp_refs, CORE_ADDR sp_args)
 {
-  const char* type_name = TYPE_NAME (info->type);
-  if (type_name == nullptr)
-    type_name = "???";
-
   fprintf_unfiltered (stream, "type: '%s', length: 0x%x, alignment: 0x%x",
-                     type_name, info->length, info->align);
+                     TYPE_SAFE_NAME (info->type), info->length, info->align);
   switch (info->argloc[0].loc_type)
     {
     case riscv_arg_info::location::in_reg:
@@ -2039,7 +2197,7 @@ riscv_print_arg_location (ui_file *stream, struct gdbarch *gdbarch,
       break;
 
     default:
-      error ("unknown argument location type");
+      gdb_assert_not_reached (_("unknown argument location type"));
     }
 }
 
@@ -2059,7 +2217,6 @@ riscv_push_dummy_call (struct gdbarch *gdbarch,
   int i;
   CORE_ADDR sp_args, sp_refs;
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   struct riscv_arg_info *arg_info =
     (struct riscv_arg_info *) alloca (nargs * sizeof (struct riscv_arg_info));
@@ -2133,7 +2290,7 @@ riscv_push_dummy_call (struct gdbarch *gdbarch,
       gdb_byte buf[sizeof (LONGEST)];
 
       store_unsigned_integer (buf, call_info.xlen, byte_order, struct_addr);
-      regcache_cooked_write (regcache, RISCV_A0_REGNUM, buf);
+      regcache->cooked_write (RISCV_A0_REGNUM, buf);
     }
 
   for (i = 0; i < nargs; ++i)
@@ -2154,9 +2311,7 @@ riscv_push_dummy_call (struct gdbarch *gdbarch,
            gdb_assert (info->argloc[0].c_length <= info->length);
            memset (tmp, 0, sizeof (tmp));
            memcpy (tmp, info->contents, info->argloc[0].c_length);
-           regcache_cooked_write (regcache,
-                                  info->argloc[0].loc_data.regno,
-                                  tmp);
+           regcache->cooked_write (info->argloc[0].loc_data.regno, tmp);
            second_arg_length =
              ((info->argloc[0].c_length < info->length)
               ? info->argloc[1].c_length : 0);
@@ -2179,7 +2334,7 @@ riscv_push_dummy_call (struct gdbarch *gdbarch,
          break;
 
        default:
-         error ("unknown argument location type");
+         gdb_assert_not_reached (_("unknown argument location type"));
        }
 
       if (second_arg_length > 0)
@@ -2190,12 +2345,12 @@ riscv_push_dummy_call (struct gdbarch *gdbarch,
              {
                gdb_byte tmp [sizeof (ULONGEST)];
 
-               gdb_assert (second_arg_length <= call_info.xlen);
+               gdb_assert ((riscv_is_fp_regno_p (info->argloc[1].loc_data.regno)
+                            && second_arg_length <= call_info.flen)
+                           || second_arg_length <= call_info.xlen);
                memset (tmp, 0, sizeof (tmp));
                memcpy (tmp, second_arg_data, second_arg_length);
-               regcache_cooked_write (regcache,
-                                      info->argloc[1].loc_data.regno,
-                                      tmp);
+               regcache->cooked_write (info->argloc[1].loc_data.regno, tmp);
              }
              break;
 
@@ -2247,10 +2402,6 @@ riscv_return_value (struct gdbarch  *gdbarch,
                    gdb_byte *readbuf,
                    const gdb_byte *writebuf)
 {
-  enum type_code rv_type = TYPE_CODE (type);
-  unsigned int rv_size = TYPE_LENGTH (type);
-  int fp, regnum, flen;
-  ULONGEST tmp;
   struct riscv_call_info call_info (gdbarch);
   struct riscv_arg_info info;
   struct type *arg_type;
@@ -2278,10 +2429,10 @@ riscv_return_value (struct gdbarch  *gdbarch,
              regnum = info.argloc[0].loc_data.regno;
 
              if (readbuf)
-               regcache_cooked_read (regcache, regnum, readbuf);
+               regcache->cooked_read (regnum, readbuf);
 
              if (writebuf)
-               regcache_cooked_write (regcache, regnum, writebuf);
+               regcache->cooked_write (regnum, writebuf);
 
              /* A return value in register can have a second part in a
                 second register.  */
@@ -2295,13 +2446,13 @@ riscv_return_value (struct gdbarch  *gdbarch,
                      if (readbuf)
                        {
                          readbuf += info.argloc[1].c_offset;
-                         regcache_cooked_read (regcache, regnum, readbuf);
+                         regcache->cooked_read (regnum, readbuf);
                        }
 
                      if (writebuf)
                        {
                          writebuf += info.argloc[1].c_offset;
-                         regcache_cooked_write (regcache, regnum, writebuf);
+                         regcache->cooked_write (regnum, writebuf);
                        }
                      break;
 
@@ -2384,31 +2535,63 @@ riscv_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
 /* Generate, or return the cached frame cache for the RiscV frame
    unwinder.  */
 
-static struct trad_frame_cache *
+static struct riscv_unwind_cache *
 riscv_frame_cache (struct frame_info *this_frame, void **this_cache)
 {
-  CORE_ADDR pc;
-  CORE_ADDR start_addr;
-  CORE_ADDR stack_addr;
-  struct trad_frame_cache *this_trad_cache;
+  CORE_ADDR pc, start_addr;
+  struct riscv_unwind_cache *cache;
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  int numregs, regno;
 
   if ((*this_cache) != NULL)
-    return (struct trad_frame_cache *) *this_cache;
-  this_trad_cache = trad_frame_cache_zalloc (this_frame);
-  (*this_cache) = this_trad_cache;
+    return (struct riscv_unwind_cache *) *this_cache;
 
-  trad_frame_set_reg_realreg (this_trad_cache, gdbarch_pc_regnum (gdbarch),
-                             RISCV_RA_REGNUM);
+  cache = FRAME_OBSTACK_ZALLOC (struct riscv_unwind_cache);
+  cache->regs = trad_frame_alloc_saved_regs (this_frame);
+  (*this_cache) = cache;
 
+  /* Scan the prologue, filling in the cache.  */
+  start_addr = get_frame_func (this_frame);
   pc = get_frame_pc (this_frame);
-  find_pc_partial_function (pc, NULL, &start_addr, NULL);
-  stack_addr = get_frame_register_signed (this_frame, RISCV_SP_REGNUM);
-  trad_frame_set_id (this_trad_cache, frame_id_build (stack_addr, start_addr));
+  riscv_scan_prologue (gdbarch, start_addr, pc, cache);
+
+  /* We can now calculate the frame base address.  */
+  cache->frame_base
+    = (get_frame_register_signed (this_frame, cache->frame_base_reg)
+       + cache->frame_base_offset);
+  if (riscv_debug_unwinder)
+    fprintf_unfiltered (gdb_stdlog, "Frame base is %s ($%s + 0x%x)\n",
+                        core_addr_to_string (cache->frame_base),
+                        gdbarch_register_name (gdbarch,
+                                               cache->frame_base_reg),
+                        cache->frame_base_offset);
+
+  /* The prologue scanner sets the address of registers stored to the stack
+     as the offset of that register from the frame base.  The prologue
+     scanner doesn't know the actual frame base value, and so is unable to
+     compute the exact address.  We do now know the frame base value, so
+     update the address of registers stored to the stack.  */
+  numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
+  for (regno = 0; regno < numregs; ++regno)
+    {
+      if (trad_frame_addr_p (cache->regs, regno))
+       cache->regs[regno].addr += cache->frame_base;
+    }
+
+  /* The previous $pc can be found wherever the $ra value can be found.
+     The previous $ra value is gone, this would have been stored be the
+     previous frame if required.  */
+  cache->regs[gdbarch_pc_regnum (gdbarch)] = cache->regs[RISCV_RA_REGNUM];
+  trad_frame_set_unknown (cache->regs, RISCV_RA_REGNUM);
+
+  /* Build the frame id.  */
+  cache->this_id = frame_id_build (cache->frame_base, start_addr);
 
-  trad_frame_set_this_base (this_trad_cache, stack_addr);
+  /* The previous $sp value is the frame base value.  */
+  trad_frame_set_value (cache->regs, gdbarch_sp_regnum (gdbarch),
+                       cache->frame_base);
 
-  return this_trad_cache;
+  return cache;
 }
 
 /* Implement the this_id callback for RiscV frame unwinder.  */
@@ -2418,10 +2601,10 @@ riscv_frame_this_id (struct frame_info *this_frame,
                     void **prologue_cache,
                     struct frame_id *this_id)
 {
-  struct trad_frame_cache *info;
+  struct riscv_unwind_cache *cache;
 
-  info = riscv_frame_cache (this_frame, prologue_cache);
-  trad_frame_get_id (info, this_id);
+  cache = riscv_frame_cache (this_frame, prologue_cache);
+  *this_id = cache->this_id;
 }
 
 /* Implement the prev_register callback for RiscV frame unwinder.  */
@@ -2431,10 +2614,10 @@ riscv_frame_prev_register (struct frame_info *this_frame,
                           void **prologue_cache,
                           int regnum)
 {
-  struct trad_frame_cache *info;
+  struct riscv_unwind_cache *cache;
 
-  info = riscv_frame_cache (this_frame, prologue_cache);
-  return trad_frame_get_register (info, this_frame, regnum);
+  cache = riscv_frame_cache (this_frame, prologue_cache);
+  return trad_frame_get_prev_register (this_frame, cache->regs, regnum);
 }
 
 /* Structure defining the RiscV normal frame unwind functions.  Since we
@@ -2467,7 +2650,6 @@ riscv_gdbarch_init (struct gdbarch_info info,
   struct gdbarch *gdbarch;
   struct gdbarch_tdep *tdep;
   struct gdbarch_tdep tmp_tdep;
-  bool has_compressed_isa = false;
   int i;
 
   /* Ideally, we'd like to get as much information from the target for
@@ -2499,10 +2681,7 @@ riscv_gdbarch_init (struct gdbarch_info info,
                        _("unknown ELF header class %d"), eclass);
 
       if (e_flags & EF_RISCV_RVC)
-       {
-         has_compressed_isa = true;
-         tmp_tdep.core_features |= (1 << ('C' - 'A'));
-       }
+       tmp_tdep.core_features |= (1 << ('C' - 'A'));
 
       if (e_flags & EF_RISCV_FLOAT_ABI_DOUBLE)
        {
@@ -2559,10 +2738,7 @@ riscv_gdbarch_init (struct gdbarch_info info,
   set_gdbarch_sw_breakpoint_from_kind (gdbarch, riscv_sw_breakpoint_from_kind);
 
   /* Register architecture.  */
-  set_gdbarch_pseudo_register_read (gdbarch, riscv_pseudo_register_read);
-  set_gdbarch_pseudo_register_write (gdbarch, riscv_pseudo_register_write);
   set_gdbarch_num_regs (gdbarch, RISCV_LAST_REGNUM + 1);
-  set_gdbarch_num_pseudo_regs (gdbarch, RISCV_LAST_REGNUM + 1);
   set_gdbarch_sp_regnum (gdbarch, RISCV_SP_REGNUM);
   set_gdbarch_pc_regnum (gdbarch, RISCV_PC_REGNUM);
   set_gdbarch_ps_regnum (gdbarch, RISCV_FP_REGNUM);
@@ -2575,7 +2751,6 @@ riscv_gdbarch_init (struct gdbarch_info info,
   set_gdbarch_register_reggroup_p (gdbarch, riscv_register_reggroup_p);
 
   /* Functions to analyze frames.  */
-  set_gdbarch_decr_pc_after_break (gdbarch, (has_compressed_isa ? 2 : 4));
   set_gdbarch_skip_prologue (gdbarch, riscv_skip_prologue);
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   set_gdbarch_frame_align (gdbarch, riscv_frame_align);
@@ -2595,108 +2770,153 @@ riscv_gdbarch_init (struct gdbarch_info info,
   dwarf2_append_unwinders (gdbarch);
   frame_unwind_append_unwinder (gdbarch, &riscv_frame_unwind);
 
-  /* Check any target description for validity.  */
-  if (tdesc_has_registers (info.target_desc))
-    {
-      const struct tdesc_feature *feature;
-      struct tdesc_arch_data *tdesc_data;
-      int valid_p;
-
-      feature = tdesc_find_feature (info.target_desc, "org.gnu.gdb.riscv.cpu");
-      if (feature == NULL)
-       goto no_tdata;
-
-      tdesc_data = tdesc_data_alloc ();
-
-      valid_p = 1;
-      for (i = RISCV_ZERO_REGNUM; i <= RISCV_LAST_FP_REGNUM; ++i)
-        valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
-                                            riscv_gdb_reg_names[i]);
-      for (i = RISCV_FIRST_CSR_REGNUM; i <= RISCV_LAST_CSR_REGNUM; ++i)
-        {
-          char buf[20];
-
-          sprintf (buf, "csr%d", i - RISCV_FIRST_CSR_REGNUM);
-          valid_p &= tdesc_numbered_register (feature, tdesc_data, i, buf);
-        }
-
-      valid_p &= tdesc_numbered_register (feature, tdesc_data, i++, "priv");
-
-      if (!valid_p)
-       tdesc_data_cleanup (tdesc_data);
-      else
-       tdesc_use_registers (gdbarch, info.target_desc, tdesc_data);
-    }
- no_tdata:
-
   for (i = 0; i < ARRAY_SIZE (riscv_register_aliases); ++i)
     user_reg_add (gdbarch, riscv_register_aliases[i].name,
                  value_of_riscv_user_reg, &riscv_register_aliases[i].regnum);
 
-  return gdbarch;
-}
-
-
-/* Allocate new riscv_inferior_data object.  */
-
-static struct riscv_inferior_data *
-riscv_new_inferior_data (void)
-{
-  struct riscv_inferior_data *inf_data
-    = new (struct riscv_inferior_data);
-  inf_data->misa_read = false;
-  return inf_data;
-}
-
-/* Free inferior data.  */
+  /* Hook in OS ABI-specific overrides, if they have been registered.  */
+  gdbarch_init_osabi (info, gdbarch);
 
-static void
-riscv_inferior_data_cleanup (struct inferior *inf, void *data)
-{
-  struct riscv_inferior_data *inf_data =
-    static_cast <struct riscv_inferior_data *> (data);
-  delete (inf_data);
+  return gdbarch;
 }
 
-/* Return riscv_inferior_data for the given INFERIOR.  If not yet created,
-   construct it.  */
+/* This decodes the current instruction and determines the address of the
+   next instruction.  */
 
-struct riscv_inferior_data *
-riscv_inferior_data (struct inferior *const inf)
+static CORE_ADDR
+riscv_next_pc (struct regcache *regcache, CORE_ADDR pc)
 {
-  struct riscv_inferior_data *inf_data;
+  struct gdbarch *gdbarch = regcache->arch ();
+  struct riscv_insn insn;
+  CORE_ADDR next_pc;
 
-  gdb_assert (inf != NULL);
+  insn.decode (gdbarch, pc);
+  next_pc = pc + insn.length ();
 
-  inf_data
-    = (struct riscv_inferior_data *) inferior_data (inf, riscv_inferior_data_reg);
-  if (inf_data == NULL)
+  if (insn.opcode () == riscv_insn::JAL)
+    next_pc = pc + insn.imm_signed ();
+  else if (insn.opcode () == riscv_insn::JALR)
+    {
+      LONGEST source;
+      regcache->cooked_read (insn.rs1 (), &source);
+      next_pc = (source + insn.imm_signed ()) & ~(CORE_ADDR) 0x1;
+    }
+  else if (insn.opcode () == riscv_insn::BEQ)
+    {
+      LONGEST src1, src2;
+      regcache->cooked_read (insn.rs1 (), &src1);
+      regcache->cooked_read (insn.rs2 (), &src2);
+      if (src1 == src2)
+       next_pc = pc + insn.imm_signed ();
+    }
+  else if (insn.opcode () == riscv_insn::BNE)
+    {
+      LONGEST src1, src2;
+      regcache->cooked_read (insn.rs1 (), &src1);
+      regcache->cooked_read (insn.rs2 (), &src2);
+      if (src1 != src2)
+       next_pc = pc + insn.imm_signed ();
+    }
+  else if (insn.opcode () == riscv_insn::BLT)
+    {
+      LONGEST src1, src2;
+      regcache->cooked_read (insn.rs1 (), &src1);
+      regcache->cooked_read (insn.rs2 (), &src2);
+      if (src1 < src2)
+       next_pc = pc + insn.imm_signed ();
+    }
+  else if (insn.opcode () == riscv_insn::BGE)
+    {
+      LONGEST src1, src2;
+      regcache->cooked_read (insn.rs1 (), &src1);
+      regcache->cooked_read (insn.rs2 (), &src2);
+      if (src1 >= src2)
+       next_pc = pc + insn.imm_signed ();
+    }
+  else if (insn.opcode () == riscv_insn::BLTU)
+    {
+      ULONGEST src1, src2;
+      regcache->cooked_read (insn.rs1 (), &src1);
+      regcache->cooked_read (insn.rs2 (), &src2);
+      if (src1 < src2)
+       next_pc = pc + insn.imm_signed ();
+    }
+  else if (insn.opcode () == riscv_insn::BGEU)
     {
-      inf_data = riscv_new_inferior_data ();
-      set_inferior_data (inf, riscv_inferior_data_reg, inf_data);
+      ULONGEST src1, src2;
+      regcache->cooked_read (insn.rs1 (), &src1);
+      regcache->cooked_read (insn.rs2 (), &src2);
+      if (src1 >= src2)
+       next_pc = pc + insn.imm_signed ();
     }
 
-  return inf_data;
+  return next_pc;
 }
 
-/* Free the inferior data when an inferior exits.  */
+/* We can't put a breakpoint in the middle of a lr/sc atomic sequence, so look
+   for the end of the sequence and put the breakpoint there.  */
 
-static void
-riscv_invalidate_inferior_data (struct inferior *inf)
+static bool
+riscv_next_pc_atomic_sequence (struct regcache *regcache, CORE_ADDR pc,
+                              CORE_ADDR *next_pc)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  struct riscv_insn insn;
+  CORE_ADDR cur_step_pc = pc;
+  CORE_ADDR last_addr = 0;
+
+  /* First instruction has to be a load reserved.  */
+  insn.decode (gdbarch, cur_step_pc);
+  if (insn.opcode () != riscv_insn::LR)
+    return false;
+  cur_step_pc = cur_step_pc + insn.length ();
+
+  /* Next instruction should be branch to exit.  */
+  insn.decode (gdbarch, cur_step_pc);
+  if (insn.opcode () != riscv_insn::BNE)
+    return false;
+  last_addr = cur_step_pc + insn.imm_signed ();
+  cur_step_pc = cur_step_pc + insn.length ();
+
+  /* Next instruction should be store conditional.  */
+  insn.decode (gdbarch, cur_step_pc);
+  if (insn.opcode () != riscv_insn::SC)
+    return false;
+  cur_step_pc = cur_step_pc + insn.length ();
+
+  /* Next instruction should be branch to start.  */
+  insn.decode (gdbarch, cur_step_pc);
+  if (insn.opcode () != riscv_insn::BNE)
+    return false;
+  if (pc != (cur_step_pc + insn.imm_signed ()))
+    return false;
+  cur_step_pc = cur_step_pc + insn.length ();
+
+  /* We should now be at the end of the sequence.  */
+  if (cur_step_pc != last_addr)
+    return false;
+
+  *next_pc = cur_step_pc;
+  return true;
+}
+
+/* This is called just before we want to resume the inferior, if we want to
+   single-step it but there is no hardware or kernel single-step support.  We
+   find the target of the coming instruction and breakpoint it.  */
+
+std::vector<CORE_ADDR>
+riscv_software_single_step (struct regcache *regcache)
 {
-  struct riscv_inferior_data *inf_data;
+  CORE_ADDR pc, next_pc;
 
-  gdb_assert (inf != NULL);
+  pc = regcache_read_pc (regcache);
 
-  /* Don't call RISCV_INFERIOR_DATA as we don't want to create the data if
-     we've not already created it by this point.  */
-  inf_data
-    = (struct riscv_inferior_data *) inferior_data (inf, riscv_inferior_data_reg);
-  if (inf_data != NULL)
-    {
-      delete (inf_data);
-      set_inferior_data (inf, riscv_inferior_data_reg, NULL);
-    }
+  if (riscv_next_pc_atomic_sequence (regcache, pc, &next_pc))
+    return {next_pc};
+
+  next_pc = riscv_next_pc (regcache, pc);
+
+  return {next_pc};
 }
 
 void
@@ -2704,14 +2924,6 @@ _initialize_riscv_tdep (void)
 {
   gdbarch_register (bfd_arch_riscv, riscv_gdbarch_init, NULL);
 
-  /* Register per-inferior data.  */
-  riscv_inferior_data_reg
-    = register_inferior_data_with_cleanup (NULL, riscv_inferior_data_cleanup);
-
-  /* Observers used to invalidate the inferior data when needed.  */
-  observer_attach_inferior_exit (riscv_invalidate_inferior_data);
-  observer_attach_inferior_appeared (riscv_invalidate_inferior_data);
-
   /* Add root prefix command for all "set debug riscv" and "show debug
      riscv" commands.  */
   add_prefix_cmd ("riscv", no_class, set_debug_riscv_command,
@@ -2734,6 +2946,16 @@ of the inferior call mechanism."),
                             show_riscv_debug_variable,
                             &setdebugriscvcmdlist, &showdebugriscvcmdlist);
 
+  add_setshow_zuinteger_cmd ("unwinder", class_maintenance,
+                            &riscv_debug_unwinder,  _("\
+Set riscv stack unwinding debugging."), _("\
+Show riscv stack unwinding debugging."), _("\
+When non-zero, print debugging information for the riscv specific parts\n\
+of the stack unwinding mechanism."),
+                            NULL,
+                            show_riscv_debug_variable,
+                            &setdebugriscvcmdlist, &showdebugriscvcmdlist);
+
   /* Add root prefix command for all "set riscv" and "show riscv" commands.  */
   add_prefix_cmd ("riscv", no_class, set_riscv_command,
                  _("RISC-V specific commands."),
This page took 0.038546 seconds and 4 git commands to generate.