Automatic date update in version.in
[binutils-gdb.git] / gdb / arm-netbsd-nat.c
blob251159154c92be8692e73f3b4d3fd3ea96b46e97
1 /* Native-dependent code for BSD Unix running on ARM's, for GDB.
3 Copyright (C) 1988-2022 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
20 /* We define this to get types like register_t. */
21 #define _KERNTYPES
22 #include "defs.h"
23 #include "gdbcore.h"
24 #include "inferior.h"
25 #include "regcache.h"
26 #include "target.h"
27 #include <sys/types.h>
28 #include <sys/ptrace.h>
29 #include <sys/sysctl.h>
30 #include <machine/reg.h>
31 #include <machine/frame.h>
33 #include "arm-tdep.h"
34 #include "arm-netbsd-tdep.h"
35 #include "aarch32-tdep.h"
36 #include "inf-ptrace.h"
37 #include "netbsd-nat.h"
39 class arm_netbsd_nat_target final : public nbsd_nat_target
41 public:
42 /* Add our register access methods. */
43 void fetch_registers (struct regcache *, int) override;
44 void store_registers (struct regcache *, int) override;
45 const struct target_desc *read_description () override;
48 static arm_netbsd_nat_target the_arm_netbsd_nat_target;
50 static void
51 arm_supply_vfpregset (struct regcache *regcache, struct fpreg *fpregset)
53 arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (regcache->arch ());
54 if (tdep->vfp_register_count == 0)
55 return;
57 struct vfpreg &vfp = fpregset->fpr_vfp;
58 for (int regno = 0; regno <= tdep->vfp_register_count; regno++)
59 regcache->raw_supply (regno + ARM_D0_REGNUM, (char *) &vfp.vfp_regs[regno]);
61 regcache->raw_supply (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr);
64 static void
65 fetch_register (struct regcache *regcache, int regno)
67 struct reg inferior_registers;
68 int ret;
69 int lwp = regcache->ptid ().lwp ();
71 ret = ptrace (PT_GETREGS, regcache->ptid ().pid (),
72 (PTRACE_TYPE_ARG3) &inferior_registers, lwp);
74 if (ret < 0)
76 warning (_("unable to fetch general register"));
77 return;
79 arm_nbsd_supply_gregset (nullptr, regcache, regno, &inferior_registers,
80 sizeof (inferior_registers));
83 static void
84 fetch_fp_register (struct regcache *regcache, int regno)
86 struct fpreg inferior_fp_registers;
87 int lwp = regcache->ptid ().lwp ();
89 int ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
90 (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp);
92 struct vfpreg &vfp = inferior_fp_registers.fpr_vfp;
94 if (ret < 0)
96 warning (_("unable to fetch floating-point register"));
97 return;
100 arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (regcache->arch ());
101 if (regno == ARM_FPSCR_REGNUM && tdep->vfp_register_count != 0)
102 regcache->raw_supply (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr);
103 else if (regno >= ARM_D0_REGNUM
104 && regno <= ARM_D0_REGNUM + tdep->vfp_register_count)
106 regcache->raw_supply (regno,
107 (char *) &vfp.vfp_regs[regno - ARM_D0_REGNUM]);
109 else
110 warning (_("Invalid register number."));
113 static void
114 fetch_fp_regs (struct regcache *regcache)
116 struct fpreg inferior_fp_registers;
117 int lwp = regcache->ptid ().lwp ();
118 int ret;
119 int regno;
121 ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
122 (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp);
124 if (ret < 0)
126 warning (_("unable to fetch general registers"));
127 return;
130 arm_supply_vfpregset (regcache, &inferior_fp_registers);
133 void
134 arm_netbsd_nat_target::fetch_registers (struct regcache *regcache, int regno)
136 if (regno >= 0)
138 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
139 fetch_register (regcache, regno);
140 else
141 fetch_fp_register (regcache, regno);
143 else
145 fetch_register (regcache, -1);
146 fetch_fp_regs (regcache);
151 static void
152 store_register (const struct regcache *regcache, int regno)
154 struct gdbarch *gdbarch = regcache->arch ();
155 struct reg inferior_registers;
156 int lwp = regcache->ptid ().lwp ();
157 int ret;
159 ret = ptrace (PT_GETREGS, regcache->ptid ().pid (),
160 (PTRACE_TYPE_ARG3) &inferior_registers, lwp);
162 if (ret < 0)
164 warning (_("unable to fetch general registers"));
165 return;
168 switch (regno)
170 case ARM_SP_REGNUM:
171 regcache->raw_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
172 break;
174 case ARM_LR_REGNUM:
175 regcache->raw_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
176 break;
178 case ARM_PC_REGNUM:
179 if (arm_apcs_32)
180 regcache->raw_collect (ARM_PC_REGNUM,
181 (char *) &inferior_registers.r_pc);
182 else
184 unsigned pc_val;
186 regcache->raw_collect (ARM_PC_REGNUM, (char *) &pc_val);
188 pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
189 inferior_registers.r_pc ^= gdbarch_addr_bits_remove
190 (gdbarch, inferior_registers.r_pc);
191 inferior_registers.r_pc |= pc_val;
193 break;
195 case ARM_PS_REGNUM:
196 if (arm_apcs_32)
197 regcache->raw_collect (ARM_PS_REGNUM,
198 (char *) &inferior_registers.r_cpsr);
199 else
201 unsigned psr_val;
203 regcache->raw_collect (ARM_PS_REGNUM, (char *) &psr_val);
205 psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
206 inferior_registers.r_pc = gdbarch_addr_bits_remove
207 (gdbarch, inferior_registers.r_pc);
208 inferior_registers.r_pc |= psr_val;
210 break;
212 default:
213 regcache->raw_collect (regno, (char *) &inferior_registers.r[regno]);
214 break;
217 ret = ptrace (PT_SETREGS, regcache->ptid ().pid (),
218 (PTRACE_TYPE_ARG3) &inferior_registers, lwp);
220 if (ret < 0)
221 warning (_("unable to write register %d to inferior"), regno);
224 static void
225 store_regs (const struct regcache *regcache)
227 struct gdbarch *gdbarch = regcache->arch ();
228 struct reg inferior_registers;
229 int lwp = regcache->ptid ().lwp ();
230 int ret;
231 int regno;
234 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
235 regcache->raw_collect (regno, (char *) &inferior_registers.r[regno]);
237 regcache->raw_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
238 regcache->raw_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
240 if (arm_apcs_32)
242 regcache->raw_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc);
243 regcache->raw_collect (ARM_PS_REGNUM,
244 (char *) &inferior_registers.r_cpsr);
246 else
248 unsigned pc_val;
249 unsigned psr_val;
251 regcache->raw_collect (ARM_PC_REGNUM, (char *) &pc_val);
252 regcache->raw_collect (ARM_PS_REGNUM, (char *) &psr_val);
254 pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
255 psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
257 inferior_registers.r_pc = pc_val | psr_val;
260 ret = ptrace (PT_SETREGS, regcache->ptid ().pid (),
261 (PTRACE_TYPE_ARG3) &inferior_registers, lwp);
263 if (ret < 0)
264 warning (_("unable to store general registers"));
267 static void
268 store_fp_register (const struct regcache *regcache, int regno)
270 struct fpreg inferior_fp_registers;
271 int lwp = regcache->ptid ().lwp ();
272 int ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
273 (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp);
274 struct vfpreg &vfp = inferior_fp_registers.fpr_vfp;
276 if (ret < 0)
278 warning (_("unable to fetch floating-point registers"));
279 return;
282 arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (regcache->arch ());
283 if (regno == ARM_FPSCR_REGNUM && tdep->vfp_register_count != 0)
284 regcache->raw_collect (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr);
285 else if (regno >= ARM_D0_REGNUM
286 && regno <= ARM_D0_REGNUM + tdep->vfp_register_count)
288 regcache->raw_collect (regno,
289 (char *) &vfp.vfp_regs[regno - ARM_D0_REGNUM]);
291 else
292 warning (_("Invalid register number."));
294 ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (),
295 (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp);
297 if (ret < 0)
298 warning (_("unable to write register %d to inferior"), regno);
301 static void
302 store_fp_regs (const struct regcache *regcache)
304 arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (regcache->arch ());
305 int lwp = regcache->ptid ().lwp ();
306 if (tdep->vfp_register_count == 0)
307 return;
309 struct fpreg fpregs;
310 for (int regno = 0; regno <= tdep->vfp_register_count; regno++)
311 regcache->raw_collect
312 (regno + ARM_D0_REGNUM, (char *) &fpregs.fpr_vfp.vfp_regs[regno]);
314 regcache->raw_collect (ARM_FPSCR_REGNUM,
315 (char *) &fpregs.fpr_vfp.vfp_fpscr);
317 int ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (),
318 (PTRACE_TYPE_ARG3) &fpregs, lwp);
320 if (ret < 0)
321 warning (_("unable to store floating-point registers"));
324 void
325 arm_netbsd_nat_target::store_registers (struct regcache *regcache, int regno)
327 if (regno >= 0)
329 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
330 store_register (regcache, regno);
331 else
332 store_fp_register (regcache, regno);
334 else
336 store_regs (regcache);
337 store_fp_regs (regcache);
341 const struct target_desc *
342 arm_netbsd_nat_target::read_description ()
344 int flag;
345 size_t len = sizeof (flag);
347 if (sysctlbyname("machdep.fpu_present", &flag, &len, NULL, 0) != 0
348 || !flag)
349 return arm_read_description (ARM_FP_TYPE_NONE, false);
351 len = sizeof(flag);
352 if (sysctlbyname("machdep.neon_present", &flag, &len, NULL, 0) == 0 && flag)
353 return aarch32_read_description ();
355 return arm_read_description (ARM_FP_TYPE_VFPV3, false);
358 void _initialize_arm_netbsd_nat ();
359 void
360 _initialize_arm_netbsd_nat ()
362 add_inf_child_target (&the_arm_netbsd_nat_target);