[PowerPC] Include nat/linux-ptrace.h in native targets
[deliverable/binutils-gdb.git] / gdb / riscv-tdep.c
index 2f619c35e75f3e35ac5f0dd4df58f961a554e02e..4b5f38a8779838250b8b353b0d5ac9a36efa9cf8 100644 (file)
@@ -54,6 +54,7 @@
 #include "opcode/riscv-opc.h"
 #include "cli/cli-decode.h"
 #include "observable.h"
+#include "prologue-value.h"
 
 /* The stack must be 16-byte aligned.  */
 #define SP_ALIGNMENT 16
@@ -71,24 +72,48 @@ static inline bool is_ ## INSN_NAME ## _insn (long insn) \
 #include "opcode/riscv-opc.h"
 #undef DECLARE_INSN
 
-/* Architectural name for core registers.  */
+/* Cached information about a frame.  */
+
+struct riscv_unwind_cache
+{
+  /* The register from which we can calculate the frame base.  This is
+     usually $sp or $fp.  */
+  int frame_base_reg;
+
+  /* The offset from the current value in register FRAME_BASE_REG to the
+     actual frame base address.  */
+  int frame_base_offset;
+
+  /* Information about previous register values.  */
+  struct trad_frame_saved_reg *regs;
+
+  /* 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;
+};
+
+/* The preferred register names for all the general purpose and floating
+   point registers.  These are what GDB will use when referencing a
+   register.  */
 
 static const char * const riscv_gdb_reg_names[RISCV_LAST_FP_REGNUM + 1] =
 {
-  "x0",  "x1",  "x2",  "x3",  "x4",  "x5",  "x6",  "x7",
-  "x8",  "x9",  "x10", "x11", "x12", "x13", "x14", "x15",
-  "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
-  "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
-  "pc",
-  "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
-  "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
-  "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
-  "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+ "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "fp", "s1",
+ "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4",
+ "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6",
+ "pc",
+ "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", "fs0", "fs1",
+ "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", "fa6", "fa7", "fs2", "fs3",
+ "fs4", "fs5", "fs6", "fs7", "fs8", "fs9", "fs10", "fs11", "ft8", "ft9",
+ "ft10", "ft11",
 };
 
-/* Maps "pretty" register names onto their GDB register number.  */
+/* Map alternative register names onto their GDB register number.  */
 
-struct register_alias
+struct riscv_register_alias
 {
   /* The register alias.  Usually more descriptive than the
      architectural name of the register.  */
@@ -100,77 +125,78 @@ struct register_alias
 
 /* Table of register aliases.  */
 
-static const struct register_alias riscv_register_aliases[] =
-{
-  { "zero", 0 },
-  { "ra", 1 },
-  { "sp", 2 },
-  { "gp", 3 },
-  { "tp", 4 },
-  { "t0", 5 },
-  { "t1", 6 },
-  { "t2", 7 },
-  { "s0", 8 },
-  { "fp", 8 },
-  { "s1", 9 },
-  { "a0", 10 },
-  { "a1", 11 },
-  { "a2", 12 },
-  { "a3", 13 },
-  { "a4", 14 },
-  { "a5", 15 },
-  { "a6", 16 },
-  { "a7", 17 },
-  { "s2", 18 },
-  { "s3", 19 },
-  { "s4", 20 },
-  { "s5", 21 },
-  { "s6", 22 },
-  { "s7", 23 },
-  { "s8", 24 },
-  { "s9", 25 },
-  { "s10", 26 },
-  { "s11", 27 },
-  { "t3", 28 },
-  { "t4", 29 },
-  { "t5", 30 },
-  { "t6", 31 },
-  /* pc is 32.  */
-  { "ft0", 33 },
-  { "ft1", 34 },
-  { "ft2", 35 },
-  { "ft3", 36 },
-  { "ft4", 37 },
-  { "ft5", 38 },
-  { "ft6", 39 },
-  { "ft7", 40 },
-  { "fs0", 41 },
-  { "fs1", 42 },
-  { "fa0", 43 },
-  { "fa1", 44 },
-  { "fa2", 45 },
-  { "fa3", 46 },
-  { "fa4", 47 },
-  { "fa5", 48 },
-  { "fa6", 49 },
-  { "fa7", 50 },
-  { "fs2", 51 },
-  { "fs3", 52 },
-  { "fs4", 53 },
-  { "fs5", 54 },
-  { "fs6", 55 },
-  { "fs7", 56 },
-  { "fs8", 57 },
-  { "fs9", 58 },
-  { "fs10", 59 },
-  { "fs11", 60 },
-  { "ft8", 61 },
-  { "ft9", 62 },
-  { "ft10", 63 },
-  { "ft11", 64 },
-#define DECLARE_CSR(name, num) { #name, (num) + 65 },
-#include "opcode/riscv-opc.h"
-#undef DECLARE_CSR
+static const struct riscv_register_alias riscv_register_aliases[] =
+{
+ /* Aliases for general purpose registers.  These are the architectural
+    names, as GDB uses the more user friendly names by default.  */
+ { "x0", (RISCV_ZERO_REGNUM + 0) },
+ { "x1", (RISCV_ZERO_REGNUM + 1) },
+ { "x2", (RISCV_ZERO_REGNUM + 2) },
+ { "x3", (RISCV_ZERO_REGNUM + 3) },
+ { "x4", (RISCV_ZERO_REGNUM + 4) },
+ { "x5", (RISCV_ZERO_REGNUM + 5) },
+ { "x6", (RISCV_ZERO_REGNUM + 6) },
+ { "x7", (RISCV_ZERO_REGNUM + 7) },
+ { "x8", (RISCV_ZERO_REGNUM + 8) },
+ { "s0", (RISCV_ZERO_REGNUM + 8) },    /* fp, s0, and x8 are all aliases.  */
+ { "x9", (RISCV_ZERO_REGNUM + 9) },
+ { "x10", (RISCV_ZERO_REGNUM + 10) },
+ { "x11", (RISCV_ZERO_REGNUM + 11) },
+ { "x12", (RISCV_ZERO_REGNUM + 12) },
+ { "x13", (RISCV_ZERO_REGNUM + 13) },
+ { "x14", (RISCV_ZERO_REGNUM + 14) },
+ { "x15", (RISCV_ZERO_REGNUM + 15) },
+ { "x16", (RISCV_ZERO_REGNUM + 16) },
+ { "x17", (RISCV_ZERO_REGNUM + 17) },
+ { "x18", (RISCV_ZERO_REGNUM + 18) },
+ { "x19", (RISCV_ZERO_REGNUM + 19) },
+ { "x20", (RISCV_ZERO_REGNUM + 20) },
+ { "x21", (RISCV_ZERO_REGNUM + 21) },
+ { "x22", (RISCV_ZERO_REGNUM + 22) },
+ { "x23", (RISCV_ZERO_REGNUM + 23) },
+ { "x24", (RISCV_ZERO_REGNUM + 24) },
+ { "x25", (RISCV_ZERO_REGNUM + 25) },
+ { "x26", (RISCV_ZERO_REGNUM + 26) },
+ { "x27", (RISCV_ZERO_REGNUM + 27) },
+ { "x28", (RISCV_ZERO_REGNUM + 28) },
+ { "x29", (RISCV_ZERO_REGNUM + 29) },
+ { "x30", (RISCV_ZERO_REGNUM + 30) },
+ { "x31", (RISCV_ZERO_REGNUM + 31) },
+
+ /* Aliases for the floating-point registers.  These are the architectural
+    names as GDB uses the more user friendly names by default.  */
+ { "f0", (RISCV_FIRST_FP_REGNUM + 0) },
+ { "f1", (RISCV_FIRST_FP_REGNUM + 1) },
+ { "f2", (RISCV_FIRST_FP_REGNUM + 2) },
+ { "f3", (RISCV_FIRST_FP_REGNUM + 3) },
+ { "f4", (RISCV_FIRST_FP_REGNUM + 4) },
+ { "f5", (RISCV_FIRST_FP_REGNUM + 5) },
+ { "f6", (RISCV_FIRST_FP_REGNUM + 6) },
+ { "f7", (RISCV_FIRST_FP_REGNUM + 7) },
+ { "f8", (RISCV_FIRST_FP_REGNUM + 8) },
+ { "f9", (RISCV_FIRST_FP_REGNUM + 9) },
+ { "f10", (RISCV_FIRST_FP_REGNUM + 10) },
+ { "f11", (RISCV_FIRST_FP_REGNUM + 11) },
+ { "f12", (RISCV_FIRST_FP_REGNUM + 12) },
+ { "f13", (RISCV_FIRST_FP_REGNUM + 13) },
+ { "f14", (RISCV_FIRST_FP_REGNUM + 14) },
+ { "f15", (RISCV_FIRST_FP_REGNUM + 15) },
+ { "f16", (RISCV_FIRST_FP_REGNUM + 16) },
+ { "f17", (RISCV_FIRST_FP_REGNUM + 17) },
+ { "f18", (RISCV_FIRST_FP_REGNUM + 18) },
+ { "f19", (RISCV_FIRST_FP_REGNUM + 19) },
+ { "f20", (RISCV_FIRST_FP_REGNUM + 20) },
+ { "f21", (RISCV_FIRST_FP_REGNUM + 21) },
+ { "f22", (RISCV_FIRST_FP_REGNUM + 22) },
+ { "f23", (RISCV_FIRST_FP_REGNUM + 23) },
+ { "f24", (RISCV_FIRST_FP_REGNUM + 24) },
+ { "f25", (RISCV_FIRST_FP_REGNUM + 25) },
+ { "f26", (RISCV_FIRST_FP_REGNUM + 26) },
+ { "f27", (RISCV_FIRST_FP_REGNUM + 27) },
+ { "f28", (RISCV_FIRST_FP_REGNUM + 28) },
+ { "f29", (RISCV_FIRST_FP_REGNUM + 29) },
+ { "f30", (RISCV_FIRST_FP_REGNUM + 30) },
+ { "f31", (RISCV_FIRST_FP_REGNUM + 31) },
 };
 
 /* Controls whether we place compressed breakpoints or not.  When in auto
@@ -186,20 +212,9 @@ show_use_compressed_breakpoints (struct ui_file *file, int from_tty,
                                 struct cmd_list_element *c,
                                 const char *value)
 {
-  const char *additional_info;
-  struct gdbarch *gdbarch = target_gdbarch ();
-
-  if (use_compressed_breakpoints == AUTO_BOOLEAN_AUTO)
-    if (riscv_has_feature (gdbarch, 'C'))
-      additional_info = _(" (currently on)");
-    else
-      additional_info = _(" (currently off)");
-  else
-    additional_info = "";
-
   fprintf_filtered (file,
                    _("Debugger's use of compressed breakpoints is set "
-                     "to %s%s.\n"), value, additional_info);
+                     "to %s.\n"), value);
 }
 
 /* The set and show lists for 'set riscv' and 'show riscv' prefixes.  */
@@ -260,39 +275,59 @@ show_riscv_debug_variable (struct ui_file *file, int from_tty,
                    c->name, value);
 }
 
+/* When this is set to non-zero debugging information about breakpoint
+   kinds will be printed.  */
+
+static unsigned int riscv_debug_breakpoints = 0;
+
 /* When this is set to non-zero debugging information about inferior calls
    will be printed.  */
 
 static unsigned int riscv_debug_infcall = 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
-   pointer READ_P is not null, then the bool pointed to is updated  to
-   indicate if the value returned was read from the target (true) or is the
-   default (false).  */
+/* 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.  There are a couple of locations
+   that the register might be found, these are all tried.  If the MISA
+   register can't be found at all then the default value of 0 is returned,
+   this is inline with the RISC-V specification.  */
 
 static uint32_t
-riscv_read_misa_reg (bool *read_p)
+riscv_read_misa_reg ()
 {
   uint32_t value = 0;
 
   if (target_has_registers)
     {
+      /* Old cores might have MISA located at a different offset.  */
+      static int misa_regs[] =
+       { RISCV_CSR_MISA_REGNUM, RISCV_CSR_LEGACY_MISA_REGNUM };
+
       struct frame_info *frame = get_current_frame ();
 
-      TRY
-       {
-         value = get_frame_register_unsigned (frame,
-                                              RISCV_CSR_MISA_REGNUM);
-       }
-      CATCH (ex, RETURN_MASK_ERROR)
+      for (int i = 0; i < ARRAY_SIZE (misa_regs); ++i)
        {
-         /* Old cores might have MISA located at a different offset.  */
-         value = get_frame_register_unsigned (frame,
-                                              RISCV_CSR_LEGACY_MISA_REGNUM);
+         bool success = false;
+
+         TRY
+           {
+             value = get_frame_register_unsigned (frame, misa_regs[i]);
+             success = true;
+           }
+         CATCH (ex, RETURN_MASK_ERROR)
+           {
+             /* Ignore errors, it is acceptable for a target to not
+                provide a MISA register, in which case the default value
+                of 0 should be used.  */
+           }
+         END_CATCH
+
+         if (success)
+           break;
        }
-      END_CATCH
     }
 
   return value;
@@ -305,21 +340,16 @@ riscv_read_misa_reg (bool *read_p)
 static bool
 riscv_has_feature (struct gdbarch *gdbarch, char feature)
 {
-  bool have_read_misa = false;
-  uint32_t misa;
-
   gdb_assert (feature >= 'A' && feature <= 'Z');
 
-  misa = riscv_read_misa_reg (&have_read_misa);
-  if (!have_read_misa || misa == 0)
+  uint32_t misa = riscv_read_misa_reg ();
+  if (misa == 0)
     misa = gdbarch_tdep (gdbarch)->core_features;
 
   return (misa & (1 << (feature - 'A'))) != 0;
 }
 
-/* Return the width in bytes  of the general purpose registers for GDBARCH.
-   Possible return values are 4, 8, or 16 for RiscV variants RV32, RV64, or
-   RV128.  */
+/* See riscv-tdep.h.  */
 
 int
 riscv_isa_xlen (struct gdbarch *gdbarch)
@@ -338,12 +368,9 @@ riscv_isa_xlen (struct gdbarch *gdbarch)
     }
 }
 
-/* Return the width in bytes of the floating point registers for GDBARCH.
-   If this architecture has no floating point registers, then return 0.
-   Possible values are 4, 8, or 16 for depending on which of single, double
-   or quad floating point support is available.  */
+/* See riscv-tdep.h.  */
 
-static int
+int
 riscv_isa_flen (struct gdbarch *gdbarch)
 {
   if (riscv_has_feature (gdbarch, 'Q'))
@@ -388,7 +415,18 @@ riscv_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
   if (use_compressed_breakpoints == AUTO_BOOLEAN_AUTO)
     {
-      if (riscv_has_feature (gdbarch, 'C'))
+      gdb_byte buf[1];
+
+      /* Read the opcode byte to determine the instruction length.  */
+      read_code (*pcptr, buf, 1);
+
+      if (riscv_debug_breakpoints)
+       fprintf_unfiltered
+         (gdb_stdlog,
+          "Using %s for breakpoint at %s (instruction length %d)\n",
+          riscv_insn_length (buf[0]) == 2 ? "C.EBREAK" : "EBREAK",
+          paddress (gdbarch, *pcptr), riscv_insn_length (buf[0]));
+      if (riscv_insn_length (buf[0]) == 2)
        return 2;
       else
        return 4;
@@ -434,25 +472,34 @@ static const char *
 riscv_register_name (struct gdbarch *gdbarch, int regnum)
 {
   /* Prefer to use the alias. */
-  if (regnum >= RISCV_ZERO_REGNUM && regnum <= RISCV_LAST_REGNUM)
+  if (regnum >= RISCV_ZERO_REGNUM && regnum <= RISCV_LAST_FP_REGNUM)
     {
-      int i;
-
-      for (i = 0; i < ARRAY_SIZE (riscv_register_aliases); ++i)
-       if (regnum == riscv_register_aliases[i].regnum)
-         return riscv_register_aliases[i].name;
+      gdb_assert (regnum < ARRAY_SIZE (riscv_gdb_reg_names));
+      return riscv_gdb_reg_names[regnum];
     }
 
-  if (regnum >= RISCV_ZERO_REGNUM && regnum <= RISCV_LAST_FP_REGNUM)
-    return riscv_gdb_reg_names[regnum];
+  /* Check that there's no gap between the set of registers handled above,
+     and the set of registers handled next.  */
+  gdb_assert ((RISCV_LAST_FP_REGNUM + 1) == RISCV_FIRST_CSR_REGNUM);
 
   if (regnum >= RISCV_FIRST_CSR_REGNUM && regnum <= RISCV_LAST_CSR_REGNUM)
     {
-      static char buf[20];
+#define DECLARE_CSR(NAME,VALUE) \
+      case RISCV_ ## VALUE ## _REGNUM: return # NAME;
 
-      xsnprintf (buf, sizeof (buf), "csr%d",
-                regnum - RISCV_FIRST_CSR_REGNUM);
-      return buf;
+      switch (regnum)
+       {
+         #include "opcode/riscv-opc.h"
+       default:
+          {
+            static char buf[20];
+
+            xsnprintf (buf, sizeof (buf), "csr%d",
+                       regnum - RISCV_FIRST_CSR_REGNUM);
+            return buf;
+          }
+       }
+#undef DECLARE_CSR
     }
 
   if (regnum == RISCV_PRIV_REGNUM)
@@ -461,6 +508,76 @@ riscv_register_name (struct gdbarch *gdbarch, int regnum)
   return NULL;
 }
 
+/* Construct a type for 64-bit FP registers.  */
+
+static struct type *
+riscv_fpreg_d_type (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (tdep->riscv_fpreg_d_type == nullptr)
+    {
+      const struct builtin_type *bt = builtin_type (gdbarch);
+
+      /* The type we're building is this: */
+#if 0
+      union __gdb_builtin_type_fpreg_d
+      {
+       float f;
+       double d;
+      };
+#endif
+
+      struct type *t;
+
+      t = arch_composite_type (gdbarch,
+                              "__gdb_builtin_type_fpreg_d", TYPE_CODE_UNION);
+      append_composite_type_field (t, "float", bt->builtin_float);
+      append_composite_type_field (t, "double", bt->builtin_double);
+      TYPE_VECTOR (t) = 1;
+      TYPE_NAME (t) = "builtin_type_fpreg_d";
+      tdep->riscv_fpreg_d_type = t;
+    }
+
+  return tdep->riscv_fpreg_d_type;
+}
+
+/* Construct a type for 128-bit FP registers.  */
+
+static struct type *
+riscv_fpreg_q_type (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (tdep->riscv_fpreg_q_type == nullptr)
+    {
+      const struct builtin_type *bt = builtin_type (gdbarch);
+
+      /* The type we're building is this: */
+#if 0
+      union __gdb_builtin_type_fpreg_d
+      {
+       float f;
+       double d;
+       long double ld;
+      };
+#endif
+
+      struct type *t;
+
+      t = arch_composite_type (gdbarch,
+                              "__gdb_builtin_type_fpreg_q", TYPE_CODE_UNION);
+      append_composite_type_field (t, "float", bt->builtin_float);
+      append_composite_type_field (t, "double", bt->builtin_double);
+      append_composite_type_field (t, "long double", bt->builtin_long_double);
+      TYPE_VECTOR (t) = 1;
+      TYPE_NAME (t) = "builtin_type_fpreg_q";
+      tdep->riscv_fpreg_q_type = t;
+    }
+
+  return tdep->riscv_fpreg_q_type;
+}
+
 /* Implement the register_type gdbarch method.  */
 
 static struct type *
@@ -503,9 +620,9 @@ riscv_register_type (struct gdbarch *gdbarch, int regnum)
        case 4:
          return builtin_type (gdbarch)->builtin_float;
        case 8:
-         return builtin_type (gdbarch)->builtin_double;
+         return riscv_fpreg_d_type (gdbarch);
        case 16:
-         return builtin_type (gdbarch)->builtin_long_double;
+         return riscv_fpreg_q_type (gdbarch);
        default:
          internal_error (__FILE__, __LINE__,
                          _("unknown isa regsize %i"), regsize);
@@ -557,7 +674,16 @@ riscv_print_one_register_info (struct gdbarch *gdbarch,
   print_raw_format = (value_entirely_available (val)
                      && !value_optimized_out (val));
 
-  if (TYPE_CODE (regtype) == TYPE_CODE_FLT)
+  if (TYPE_CODE (regtype) == TYPE_CODE_FLT
+      || (TYPE_CODE (regtype) == TYPE_CODE_UNION
+         && TYPE_NFIELDS (regtype) == 2
+         && TYPE_CODE (TYPE_FIELD_TYPE (regtype, 0)) == TYPE_CODE_FLT
+         && TYPE_CODE (TYPE_FIELD_TYPE (regtype, 1)) == TYPE_CODE_FLT)
+      || (TYPE_CODE (regtype) == TYPE_CODE_UNION
+         && TYPE_NFIELDS (regtype) == 3
+         && TYPE_CODE (TYPE_FIELD_TYPE (regtype, 0)) == TYPE_CODE_FLT
+         && TYPE_CODE (TYPE_FIELD_TYPE (regtype, 1)) == TYPE_CODE_FLT
+         && TYPE_CODE (TYPE_FIELD_TYPE (regtype, 2)) == TYPE_CODE_FLT))
     {
       struct value_print_options opts;
       const gdb_byte *valaddr = value_contents_for_printing (val);
@@ -725,6 +851,27 @@ riscv_print_one_register_info (struct gdbarch *gdbarch,
   fprintf_filtered (file, "\n");
 }
 
+/* Return true if REGNUM is a valid CSR register.  The CSR register space
+   is sparsely populated, so not every number is a named CSR.  */
+
+static bool
+riscv_is_regnum_a_named_csr (int regnum)
+{
+  gdb_assert (regnum >= RISCV_FIRST_CSR_REGNUM
+             && regnum <= RISCV_LAST_CSR_REGNUM);
+
+  switch (regnum)
+    {
+#define DECLARE_CSR(name, num) case RISCV_ ## num ## _REGNUM:
+#include "opcode/riscv-opc.h"
+#undef DECLARE_CSR
+      return true;
+
+    default:
+      return false;
+    }
+}
+
 /* Implement the register_reggroup_p gdbarch method.  Is REGNUM a member
    of REGGROUP?  */
 
@@ -732,8 +879,6 @@ static int
 riscv_register_reggroup_p (struct gdbarch  *gdbarch, int regnum,
                           struct reggroup *reggroup)
 {
-  unsigned int i;
-
   /* Used by 'info registers' and 'info registers <groupname>'.  */
 
   if (gdbarch_register_name (gdbarch, regnum) == NULL
@@ -744,12 +889,8 @@ riscv_register_reggroup_p (struct gdbarch  *gdbarch, int regnum,
     {
       if (regnum < RISCV_FIRST_CSR_REGNUM || regnum == RISCV_PRIV_REGNUM)
        return 1;
-      /* Only include CSRs that have aliases.  */
-      for (i = 0; i < ARRAY_SIZE (riscv_register_aliases); ++i)
-       {
-         if (regnum == riscv_register_aliases[i].regnum)
-           return 1;
-       }
+      if (riscv_is_regnum_a_named_csr (regnum))
+        return 1;
       return 0;
     }
   else if (reggroup == float_reggroup)
@@ -772,12 +913,8 @@ riscv_register_reggroup_p (struct gdbarch  *gdbarch, int regnum,
        return 1;
       if (regnum < RISCV_FIRST_CSR_REGNUM || regnum > RISCV_LAST_CSR_REGNUM)
        return 0;
-      /* Only include CSRs that have aliases.  */
-      for (i = 0; i < ARRAY_SIZE (riscv_register_aliases); ++i)
-       {
-         if (regnum == riscv_register_aliases[i].regnum)
-           return 1;
-       }
+      if (riscv_is_regnum_a_named_csr (regnum))
+        return 1;
       return 0;
     }
   else if (reggroup == vector_reggroup)
@@ -972,6 +1109,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)
   {
@@ -1165,14 +1327,29 @@ riscv_insn::decode (struct gdbarch *gdbarch, CORE_ADDR pc)
          m_rd = m_rs1 = decode_register_index (ival, OP_SH_RD);
          m_imm.s = EXTRACT_RVC_ADDI16SP_IMM (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;
+        {
+          m_opcode = LUI;
+          m_rd = decode_register_index (ival, OP_SH_CRS1S);
+          m_imm.s = EXTRACT_RVC_LUI_IMM (ival);
+        }
       /* 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))
-       m_opcode = OTHER;
+       decode_cs_type_insn (SD, ival, EXTRACT_RVC_LD_IMM (ival));
       else if (is_c_sw_insn (ival))
-       m_opcode = OTHER;
+       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))
@@ -1204,16 +1381,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;
 
@@ -1231,10 +1426,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)
@@ -1246,6 +1441,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
@@ -1253,6 +1453,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)
@@ -1263,49 +1467,104 @@ 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
-                   || insn.opcode () == riscv_insn::LUI
-                   || (insn.opcode () == riscv_insn::ADDI
-                       && insn.rs1 () == RISCV_GP_REGNUM)
-                   || (insn.opcode () == riscv_insn::ADD
-                       && (insn.rs1 () == RISCV_GP_REGNUM
-                           || insn.rs2 () == RISCV_GP_REGNUM))))
-              || (insn.opcode () == riscv_insn::ADDI
-                  && insn.rd () == RISCV_ZERO_REGNUM
-                  && insn.rs1 () == RISCV_ZERO_REGNUM
-                  && insn.imm_signed () == 0))
+      else if ((insn.opcode () == riscv_insn::ADDI
+                && insn.rd () == RISCV_ZERO_REGNUM
+                && insn.rs1 () == RISCV_ZERO_REGNUM
+                && insn.imm_signed () == 0))
        {
-         /* Handle: auipc gp, n
-            or:     addi gp, gp, n
-            or:     add gp, gp, reg
-            or:     add gp, reg, gp
-            or:     lui gp, n
-            or:     add x0, x0, 0   (NOP)  */
-         /* These instructions are part of the prologue, but we don't need
-            to do anything special to handle them.  */
+         /* Handle: add x0, x0, 0   (NOP)  */
        }
+      else if (insn.opcode () == riscv_insn::AUIPC)
+        {
+          gdb_assert (insn.rd () < RISCV_NUM_INTEGER_REGS);
+          regs[insn.rd ()] = pv_constant (cur_pc + insn.imm_signed ());
+        }
+      else if (insn.opcode () == riscv_insn::LUI)
+        {
+         /* Handle: lui REG, n
+             Where REG is not gp register.  */
+          gdb_assert (insn.rd () < RISCV_NUM_INTEGER_REGS);
+          regs[insn.rd ()] = pv_constant (insn.imm_signed ());
+        }
+      else if (insn.opcode () == riscv_insn::ADDI)
+        {
+          /* Handle: addi REG1, REG2, IMM  */
+          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)
+        {
+          /* Handle: addi REG1, REG2, IMM  */
+          gdb_assert (insn.rd () < RISCV_NUM_INTEGER_REGS);
+          gdb_assert (insn.rs1 () < RISCV_NUM_INTEGER_REGS);
+          gdb_assert (insn.rs2 () < RISCV_NUM_INTEGER_REGS);
+          regs[insn.rd ()] = pv_add (regs[insn.rs1 ()], regs[insn.rs2 ()]);
+        }
       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
@@ -1321,16 +1580,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.  */
@@ -2093,7 +2345,6 @@ riscv_push_dummy_call (struct gdbarch *gdbarch,
 
   struct riscv_arg_info *arg_info =
     (struct riscv_arg_info *) alloca (nargs * sizeof (struct riscv_arg_info));
-  struct riscv_arg_info *info;
 
   struct riscv_call_info call_info (gdbarch);
 
@@ -2103,12 +2354,11 @@ riscv_push_dummy_call (struct gdbarch *gdbarch,
   if (struct_return)
     ++call_info.int_regs.next_regnum;
 
-  for (i = 0, info = &arg_info[0];
-       i < nargs;
-       ++i, ++info)
+  for (i = 0; i < nargs; ++i)
     {
       struct value *arg_value;
       struct type *arg_type;
+      struct riscv_arg_info *info = &arg_info[i];
 
       arg_value = args[i];
       arg_type = check_typedef (value_type (arg_value));
@@ -2182,7 +2432,12 @@ riscv_push_dummy_call (struct gdbarch *gdbarch,
            gdb_byte tmp [sizeof (ULONGEST)];
 
            gdb_assert (info->argloc[0].c_length <= info->length);
-           memset (tmp, 0, sizeof (tmp));
+           /* FP values in FP registers must be NaN-boxed.  */
+           if (riscv_is_fp_regno_p (info->argloc[0].loc_data.regno)
+               && info->argloc[0].c_length < call_info.flen)
+             memset (tmp, -1, sizeof (tmp));
+           else
+             memset (tmp, 0, sizeof (tmp));
            memcpy (tmp, info->contents, info->argloc[0].c_length);
            regcache->cooked_write (info->argloc[0].loc_data.regno, tmp);
            second_arg_length =
@@ -2221,7 +2476,12 @@ riscv_push_dummy_call (struct gdbarch *gdbarch,
                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));
+               /* FP values in FP registers must be NaN-boxed.  */
+               if (riscv_is_fp_regno_p (info->argloc[1].loc_data.regno)
+                   && second_arg_length < call_info.flen)
+                 memset (tmp, -1, sizeof (tmp));
+               else
+                 memset (tmp, 0, sizeof (tmp));
                memcpy (tmp, second_arg_data, second_arg_length);
                regcache->cooked_write (info->argloc[1].loc_data.regno, tmp);
              }
@@ -2408,31 +2668,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;
+    }
 
-  trad_frame_set_this_base (this_trad_cache, stack_addr);
+  /* 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);
 
-  return this_trad_cache;
+  /* Build the frame id.  */
+  cache->this_id = frame_id_build (cache->frame_base, start_addr);
+
+  /* The previous $sp value is the frame base value.  */
+  trad_frame_set_value (cache->regs, gdbarch_sp_regnum (gdbarch),
+                       cache->frame_base);
+
+  return cache;
 }
 
 /* Implement the this_id callback for RiscV frame unwinder.  */
@@ -2442,10 +2734,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.  */
@@ -2455,10 +2747,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
@@ -2577,6 +2869,7 @@ riscv_gdbarch_init (struct gdbarch_info info,
   set_gdbarch_return_value (gdbarch, riscv_return_value);
   set_gdbarch_breakpoint_kind_from_pc (gdbarch, riscv_breakpoint_kind_from_pc);
   set_gdbarch_sw_breakpoint_from_kind (gdbarch, riscv_sw_breakpoint_from_kind);
+  set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
 
   /* Register architecture.  */
   set_gdbarch_num_regs (gdbarch, RISCV_LAST_REGNUM + 1);
@@ -2777,6 +3070,16 @@ _initialize_riscv_tdep (void)
                  &showdebugriscvcmdlist, "show debug riscv ", 0,
                  &showdebuglist);
 
+  add_setshow_zuinteger_cmd ("breakpoints", class_maintenance,
+                            &riscv_debug_breakpoints,  _("\
+Set riscv breakpoint debugging."), _("\
+Show riscv breakpoint debugging."), _("\
+When non-zero, print debugging information for the riscv specific parts\n\
+of the breakpoint mechanism."),
+                            NULL,
+                            show_riscv_debug_variable,
+                            &setdebugriscvcmdlist, &showdebugriscvcmdlist);
+
   add_setshow_zuinteger_cmd ("infcall", class_maintenance,
                             &riscv_debug_infcall,  _("\
 Set riscv inferior call debugging."), _("\
@@ -2787,6 +3090,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."),
@@ -2803,10 +3116,10 @@ of the inferior call mechanism."),
                                _("\
 Set debugger's use of compressed breakpoints."), _("   \
 Show debugger's use of compressed breakpoints."), _("\
-Debugging compressed code requires compressed breakpoints to be used. If\n \
-left to 'auto' then gdb will use them if $misa indicates the C extension\n \
-is supported. If that doesn't give the correct behavior, then this option\n\
-can be used."),
+Debugging compressed code requires compressed breakpoints to be used. If\n\
+left to 'auto' then gdb will use them if the existing instruction is a\n\
+compressed instruction. If that doesn't give the correct behavior, then\n\
+this option can be used."),
                                NULL,
                                show_use_compressed_breakpoints,
                                &setriscvcmdlist,
This page took 0.035214 seconds and 4 git commands to generate.