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