RISC-V: Don't decrement pc after break.
[deliverable/binutils-gdb.git] / gdb / riscv-tdep.c
index 3e1ad99c673df28bab02dacb6332f6d3b6d9bf34..f5d1af822c7391d2877a9ced5ab26b43c415c54b 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
@@ -58,7 +53,7 @@
 #include "common-defs.h"
 #include "opcode/riscv-opc.h"
 #include "cli/cli-decode.h"
-#include "observer.h"
+#include "observable.h"
 
 /* The stack must be 16-byte aligned.  */
 #define SP_ALIGNMENT 16
@@ -133,8 +128,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 },
@@ -340,23 +335,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;
 
@@ -374,6 +353,7 @@ riscv_isa_xlen (struct gdbarch *gdbarch)
     {
     default:
       warning (_("unknown xlen size, assuming 4 bytes"));
+      /* Fall through.  */
     case 1:
       return 4;
     case 2:
@@ -417,6 +397,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 +440,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 +458,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 +475,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 +486,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 *
@@ -815,10 +780,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)
@@ -1079,12 +1044,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)
@@ -1969,12 +1932,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 +1998,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"));
     }
 }
 
@@ -2133,7 +2092,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 +2113,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 +2136,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 +2147,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;
 
@@ -2278,10 +2235,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 +2252,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;
 
@@ -2467,7 +2424,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 +2455,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 +2512,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 +2525,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,44 +2544,13 @@ 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);
 
+  /* Hook in OS ABI-specific overrides, if they have been registered.  */
+  gdbarch_init_osabi (info, gdbarch);
+
   return gdbarch;
 }
 
@@ -2709,8 +2627,8 @@ _initialize_riscv_tdep (void)
     = 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);
+  gdb::observers::inferior_exit.attach (riscv_invalidate_inferior_data);
+  gdb::observers::inferior_appeared.attach (riscv_invalidate_inferior_data);
 
   /* Add root prefix command for all "set debug riscv" and "show debug
      riscv" commands.  */
This page took 0.037508 seconds and 4 git commands to generate.