1 /* none on ARM target support. 2 3 Copyright (C) 2020-2023 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "defs.h" 21 #include "arm-tdep.h" 22 #include "arch-utils.h" 23 #include "regcache.h" 24 #include "elf-bfd.h" 25 #include "regset.h" 26 #include "user-regs.h" 27 28 #ifdef HAVE_ELF 29 #include "elf-none-tdep.h" 30 #endif 31 32 /* Core file and register set support. */ 33 #define ARM_NONE_SIZEOF_GREGSET (18 * ARM_INT_REGISTER_SIZE) 34 35 /* Support VFP register format. */ 36 #define ARM_NONE_SIZEOF_VFP (32 * 8 + 4) 37 38 /* The index to access CPSR in user_regs as defined in GLIBC. */ 39 #define ARM_NONE_CPSR_GREGNUM 16 40 41 /* Supply register REGNUM from buffer GREGS_BUF (length LEN bytes) into 42 REGCACHE. If REGNUM is -1 then supply all registers. The set of 43 registers that this function will supply is limited to the general 44 purpose registers. 45 46 The layout of the registers here is based on the ARM GNU/Linux 47 layout. */ 48 49 static void 50 arm_none_supply_gregset (const struct regset *regset, 51 struct regcache *regcache, 52 int regnum, const void *gregs_buf, size_t len) 53 { 54 struct gdbarch *gdbarch = regcache->arch (); 55 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 56 const gdb_byte *gregs = (const gdb_byte *) gregs_buf; 57 58 for (int regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++) 59 if (regnum == -1 || regnum == regno) 60 regcache->raw_supply (regno, gregs + ARM_INT_REGISTER_SIZE * regno); 61 62 if (regnum == ARM_PS_REGNUM || regnum == -1) 63 { 64 if (arm_apcs_32) 65 regcache->raw_supply (ARM_PS_REGNUM, 66 gregs + ARM_INT_REGISTER_SIZE 67 * ARM_NONE_CPSR_GREGNUM); 68 else 69 regcache->raw_supply (ARM_PS_REGNUM, 70 gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM); 71 } 72 73 if (regnum == ARM_PC_REGNUM || regnum == -1) 74 { 75 gdb_byte pc_buf[ARM_INT_REGISTER_SIZE]; 76 77 CORE_ADDR reg_pc 78 = extract_unsigned_integer (gregs + ARM_INT_REGISTER_SIZE 79 * ARM_PC_REGNUM, 80 ARM_INT_REGISTER_SIZE, byte_order); 81 reg_pc = gdbarch_addr_bits_remove (gdbarch, reg_pc); 82 store_unsigned_integer (pc_buf, ARM_INT_REGISTER_SIZE, byte_order, 83 reg_pc); 84 regcache->raw_supply (ARM_PC_REGNUM, pc_buf); 85 } 86 } 87 88 /* Collect register REGNUM from REGCACHE and place it into buffer GREGS_BUF 89 (length LEN bytes). If REGNUM is -1 then collect all registers. The 90 set of registers that this function will collect is limited to the 91 general purpose registers. 92 93 The layout of the registers here is based on the ARM GNU/Linux 94 layout. */ 95 96 static void 97 arm_none_collect_gregset (const struct regset *regset, 98 const struct regcache *regcache, 99 int regnum, void *gregs_buf, size_t len) 100 { 101 gdb_byte *gregs = (gdb_byte *) gregs_buf; 102 103 for (int regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++) 104 if (regnum == -1 || regnum == regno) 105 regcache->raw_collect (regno, 106 gregs + ARM_INT_REGISTER_SIZE * regno); 107 108 if (regnum == ARM_PS_REGNUM || regnum == -1) 109 { 110 if (arm_apcs_32) 111 regcache->raw_collect (ARM_PS_REGNUM, 112 gregs + ARM_INT_REGISTER_SIZE 113 * ARM_NONE_CPSR_GREGNUM); 114 else 115 regcache->raw_collect (ARM_PS_REGNUM, 116 gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM); 117 } 118 119 if (regnum == ARM_PC_REGNUM || regnum == -1) 120 regcache->raw_collect (ARM_PC_REGNUM, 121 gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM); 122 } 123 124 /* Supply VFP registers from REGS_BUF into REGCACHE. */ 125 126 static void 127 arm_none_supply_vfp (const struct regset *regset, 128 struct regcache *regcache, 129 int regnum, const void *regs_buf, size_t len) 130 { 131 const gdb_byte *regs = (const gdb_byte *) regs_buf; 132 133 if (regnum == ARM_FPSCR_REGNUM || regnum == -1) 134 regcache->raw_supply (ARM_FPSCR_REGNUM, regs + 32 * 8); 135 136 for (int regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++) 137 if (regnum == -1 || regnum == regno) 138 regcache->raw_supply (regno, regs + (regno - ARM_D0_REGNUM) * 8); 139 } 140 141 /* Collect VFP registers from REGCACHE into REGS_BUF. */ 142 143 static void 144 arm_none_collect_vfp (const struct regset *regset, 145 const struct regcache *regcache, 146 int regnum, void *regs_buf, size_t len) 147 { 148 gdb_byte *regs = (gdb_byte *) regs_buf; 149 150 if (regnum == ARM_FPSCR_REGNUM || regnum == -1) 151 regcache->raw_collect (ARM_FPSCR_REGNUM, regs + 32 * 8); 152 153 for (int regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++) 154 if (regnum == -1 || regnum == regno) 155 regcache->raw_collect (regno, regs + (regno - ARM_D0_REGNUM) * 8); 156 } 157 158 /* The general purpose register set. */ 159 160 static const struct regset arm_none_gregset = 161 { 162 nullptr, arm_none_supply_gregset, arm_none_collect_gregset 163 }; 164 165 /* The VFP register set. */ 166 167 static const struct regset arm_none_vfpregset = 168 { 169 nullptr, arm_none_supply_vfp, arm_none_collect_vfp 170 }; 171 172 /* Iterate over core file register note sections. */ 173 174 static void 175 arm_none_iterate_over_regset_sections (struct gdbarch *gdbarch, 176 iterate_over_regset_sections_cb *cb, 177 void *cb_data, 178 const struct regcache *regcache) 179 { 180 arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch); 181 182 cb (".reg", ARM_NONE_SIZEOF_GREGSET, ARM_NONE_SIZEOF_GREGSET, 183 &arm_none_gregset, nullptr, cb_data); 184 185 if (tdep->vfp_register_count > 0) 186 cb (".reg-arm-vfp", ARM_NONE_SIZEOF_VFP, ARM_NONE_SIZEOF_VFP, 187 &arm_none_vfpregset, "VFP floating-point", cb_data); 188 } 189 190 /* Initialize ARM bare-metal ABI info. */ 191 192 static void 193 arm_none_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 194 { 195 #ifdef HAVE_ELF 196 elf_none_init_abi (gdbarch); 197 #endif 198 199 /* Iterate over registers for reading and writing bare metal ARM core 200 files. */ 201 set_gdbarch_iterate_over_regset_sections 202 (gdbarch, arm_none_iterate_over_regset_sections); 203 } 204 205 /* Initialize ARM bare-metal target support. */ 206 207 void _initialize_arm_none_tdep (); 208 void 209 _initialize_arm_none_tdep () 210 { 211 gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_NONE, 212 arm_none_init_abi); 213 } 214