Home | History | Annotate | Line # | Download | only in gdb
      1 /* Copyright (C) 2020-2024 Free Software Foundation, Inc.
      2 
      3    This file is part of GDB.
      4 
      5    This program is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by
      7    the Free Software Foundation; either version 3 of the License, or
      8    (at your option) any later version.
      9 
     10    This program is distributed in the hope that it will be useful,
     11    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13    GNU General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public License
     16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     17 
     18 /* This file contain code that is specific for bare-metal RISC-V targets.  */
     19 
     20 #include "arch-utils.h"
     21 #include "regcache.h"
     22 #include "riscv-tdep.h"
     23 #include "elf-bfd.h"
     24 #include "regset.h"
     25 #include "user-regs.h"
     26 #include "target-descriptions.h"
     27 
     28 #ifdef HAVE_ELF
     29 #include "elf-none-tdep.h"
     30 #endif
     31 
     32 /* Define the general register mapping.  This follows the same format as
     33    the RISC-V linux corefile.  The linux kernel puts the PC at offset 0,
     34    gdb puts it at offset 32.  Register x0 is always 0 and can be ignored.
     35    Registers x1 to x31 are in the same place.  */
     36 
     37 static const struct regcache_map_entry riscv_gregmap[] =
     38 {
     39   { 1,  RISCV_PC_REGNUM, 0 },
     40   { 31, RISCV_RA_REGNUM, 0 }, /* x1 to x31 */
     41   { 0 }
     42 };
     43 
     44 /* Define the FP register mapping.  This follows the same format as the
     45    RISC-V linux corefile.  The kernel puts the 32 FP regs first, and then
     46    FCSR.  */
     47 
     48 static const struct regcache_map_entry riscv_fregmap[] =
     49 {
     50   { 32, RISCV_FIRST_FP_REGNUM, 0 },
     51   { 1, RISCV_CSR_FCSR_REGNUM, 4 },	/* Always stored as 4-bytes.  */
     52   { 0 }
     53 };
     54 
     55 /* Define the general register regset.  */
     56 
     57 static const struct regset riscv_gregset =
     58 {
     59   riscv_gregmap, riscv_supply_regset, regcache_collect_regset
     60 };
     61 
     62 /* Define the FP register regset.  */
     63 
     64 static const struct regset riscv_fregset =
     65 {
     66   riscv_fregmap, riscv_supply_regset, regcache_collect_regset
     67 };
     68 
     69 /* Define the CSR regset, this is not constant as the regmap field is
     70    updated dynamically based on the current target description.  */
     71 
     72 static struct regset riscv_csrset =
     73 {
     74   nullptr, regcache_supply_regset, regcache_collect_regset
     75 };
     76 
     77 /* Update the regmap field of RISCV_CSRSET based on the CSRs available in
     78    the current target description.  */
     79 
     80 static void
     81 riscv_update_csrmap (struct gdbarch *gdbarch,
     82 		     const struct tdesc_feature *feature_csr)
     83 {
     84   int i = 0;
     85 
     86   /* Release any previously defined map.  */
     87   delete[] ((struct regcache_map_entry *) riscv_csrset.regmap);
     88 
     89   /* Now create a register map for every csr found in the target
     90      description.  */
     91   struct regcache_map_entry *riscv_csrmap
     92     = new struct regcache_map_entry[feature_csr->registers.size() + 1];
     93   for (auto &csr : feature_csr->registers)
     94     {
     95       int regnum = user_reg_map_name_to_regnum (gdbarch, csr->name.c_str(),
     96 						csr->name.length());
     97       riscv_csrmap[i++] = {1, regnum, 0};
     98     }
     99 
    100   /* Mark the end of the array.  */
    101   riscv_csrmap[i] = {0};
    102   riscv_csrset.regmap = riscv_csrmap;
    103 }
    104 
    105 /* Implement the "iterate_over_regset_sections" gdbarch method.  */
    106 
    107 static void
    108 riscv_iterate_over_regset_sections (struct gdbarch *gdbarch,
    109 				    iterate_over_regset_sections_cb *cb,
    110 				    void *cb_data,
    111 				    const struct regcache *regcache)
    112 {
    113   /* Write out the GPRs.  */
    114   int sz = 32 * riscv_isa_xlen (gdbarch);
    115   cb (".reg", sz, sz, &riscv_gregset, NULL, cb_data);
    116 
    117   /* Write out the FPRs, but only if present.  */
    118   if (riscv_isa_flen (gdbarch) > 0)
    119     {
    120       sz = (32 * riscv_isa_flen (gdbarch)
    121 	    + register_size (gdbarch, RISCV_CSR_FCSR_REGNUM));
    122       cb (".reg2", sz, sz, &riscv_fregset, NULL, cb_data);
    123     }
    124 
    125   /* Read or write the CSRs.  The set of CSRs is defined by the current
    126      target description.  The user is responsible for ensuring that the
    127      same target description is in use when reading the core file as was
    128      in use when writing the core file.  */
    129   const struct target_desc *tdesc = gdbarch_target_desc (gdbarch);
    130 
    131   /* Do not dump/load any CSRs if there is no target description or the target
    132      description does not contain any CSRs.  */
    133   if (tdesc != nullptr)
    134     {
    135       const struct tdesc_feature *feature_csr
    136 	= tdesc_find_feature (tdesc, riscv_feature_name_csr);
    137       if (feature_csr != nullptr && feature_csr->registers.size () > 0)
    138 	{
    139 	  riscv_update_csrmap (gdbarch, feature_csr);
    140 	  cb (".reg-riscv-csr",
    141 	      (feature_csr->registers.size() * riscv_isa_xlen (gdbarch)),
    142 	      (feature_csr->registers.size() * riscv_isa_xlen (gdbarch)),
    143 	      &riscv_csrset, NULL, cb_data);
    144 	}
    145     }
    146 }
    147 
    148 /* Initialize RISC-V bare-metal ABI info.  */
    149 
    150 static void
    151 riscv_none_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
    152 {
    153 #ifdef HAVE_ELF
    154   elf_none_init_abi (gdbarch);
    155 #endif
    156 
    157   /* Iterate over registers for reading and writing bare metal RISC-V core
    158      files.  */
    159   set_gdbarch_iterate_over_regset_sections
    160     (gdbarch, riscv_iterate_over_regset_sections);
    161 
    162 }
    163 
    164 /* Initialize RISC-V bare-metal target support.  */
    165 
    166 void _initialize_riscv_none_tdep ();
    167 void
    168 _initialize_riscv_none_tdep ()
    169 {
    170   gdbarch_register_osabi (bfd_arch_riscv, 0, GDB_OSABI_NONE,
    171 			  riscv_none_init_abi);
    172 }
    173