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. */
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>
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
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
;
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)
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
);
65 fetch_register (struct regcache
*regcache
, int regno
)
67 struct reg inferior_registers
;
69 int lwp
= regcache
->ptid ().lwp ();
71 ret
= ptrace (PT_GETREGS
, regcache
->ptid ().pid (),
72 (PTRACE_TYPE_ARG3
) &inferior_registers
, lwp
);
76 warning (_("unable to fetch general register"));
79 arm_nbsd_supply_gregset (nullptr, regcache
, regno
, &inferior_registers
,
80 sizeof (inferior_registers
));
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
;
96 warning (_("unable to fetch floating-point register"));
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
]);
110 warning (_("Invalid register number."));
114 fetch_fp_regs (struct regcache
*regcache
)
116 struct fpreg inferior_fp_registers
;
117 int lwp
= regcache
->ptid ().lwp ();
121 ret
= ptrace (PT_GETFPREGS
, regcache
->ptid ().pid (),
122 (PTRACE_TYPE_ARG3
) &inferior_fp_registers
, lwp
);
126 warning (_("unable to fetch general registers"));
130 arm_supply_vfpregset (regcache
, &inferior_fp_registers
);
134 arm_netbsd_nat_target::fetch_registers (struct regcache
*regcache
, int regno
)
138 if (regno
< ARM_F0_REGNUM
|| regno
> ARM_FPS_REGNUM
)
139 fetch_register (regcache
, regno
);
141 fetch_fp_register (regcache
, regno
);
145 fetch_register (regcache
, -1);
146 fetch_fp_regs (regcache
);
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 ();
159 ret
= ptrace (PT_GETREGS
, regcache
->ptid ().pid (),
160 (PTRACE_TYPE_ARG3
) &inferior_registers
, lwp
);
164 warning (_("unable to fetch general registers"));
171 regcache
->raw_collect (ARM_SP_REGNUM
, (char *) &inferior_registers
.r_sp
);
175 regcache
->raw_collect (ARM_LR_REGNUM
, (char *) &inferior_registers
.r_lr
);
180 regcache
->raw_collect (ARM_PC_REGNUM
,
181 (char *) &inferior_registers
.r_pc
);
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
;
197 regcache
->raw_collect (ARM_PS_REGNUM
,
198 (char *) &inferior_registers
.r_cpsr
);
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
;
213 regcache
->raw_collect (regno
, (char *) &inferior_registers
.r
[regno
]);
217 ret
= ptrace (PT_SETREGS
, regcache
->ptid ().pid (),
218 (PTRACE_TYPE_ARG3
) &inferior_registers
, lwp
);
221 warning (_("unable to write register %d to inferior"), regno
);
225 store_regs (const struct regcache
*regcache
)
227 struct gdbarch
*gdbarch
= regcache
->arch ();
228 struct reg inferior_registers
;
229 int lwp
= regcache
->ptid ().lwp ();
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
);
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
);
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
);
264 warning (_("unable to store general registers"));
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
;
278 warning (_("unable to fetch floating-point registers"));
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
]);
292 warning (_("Invalid register number."));
294 ret
= ptrace (PT_SETFPREGS
, regcache
->ptid ().pid (),
295 (PTRACE_TYPE_ARG3
) &inferior_fp_registers
, lwp
);
298 warning (_("unable to write register %d to inferior"), regno
);
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)
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
);
321 warning (_("unable to store floating-point registers"));
325 arm_netbsd_nat_target::store_registers (struct regcache
*regcache
, int regno
)
329 if (regno
< ARM_F0_REGNUM
|| regno
> ARM_FPS_REGNUM
)
330 store_register (regcache
, regno
);
332 store_fp_register (regcache
, regno
);
336 store_regs (regcache
);
337 store_fp_regs (regcache
);
341 const struct target_desc
*
342 arm_netbsd_nat_target::read_description ()
345 size_t len
= sizeof (flag
);
347 if (sysctlbyname("machdep.fpu_present", &flag
, &len
, NULL
, 0) != 0
349 return arm_read_description (ARM_FP_TYPE_NONE
, false);
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 ();
360 _initialize_arm_netbsd_nat ()
362 add_inf_child_target (&the_arm_netbsd_nat_target
);