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