1 /* Native-dependent code for BSD Unix running on ARM's, for GDB.
3 Copyright (C) 1988-2020 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-nbsd-tdep.h"
35 #include "aarch32-tdep.h"
36 #include "inf-ptrace.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 struct gdbarch_tdep
*tdep
= 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
;
70 ret
= ptrace (PT_GETREGS
, regcache
->ptid ().pid (),
71 (PTRACE_TYPE_ARG3
) &inferior_registers
, 0);
75 warning (_("unable to fetch general register"));
78 arm_nbsd_supply_gregset (nullptr, regcache
, regno
, &inferior_registers
,
79 sizeof (inferior_registers
));
83 fetch_fp_register (struct regcache
*regcache
, int regno
)
85 struct fpreg inferior_fp_registers
;
86 int ret
= ptrace (PT_GETFPREGS
, regcache
->ptid ().pid (),
87 (PTRACE_TYPE_ARG3
) &inferior_fp_registers
, 0);
89 struct vfpreg
&vfp
= inferior_fp_registers
.fpr_vfp
;
93 warning (_("unable to fetch floating-point register"));
97 struct gdbarch_tdep
*tdep
= gdbarch_tdep (regcache
->arch ());
98 if (regno
== ARM_FPSCR_REGNUM
&& tdep
->vfp_register_count
!= 0)
99 regcache
->raw_supply (ARM_FPSCR_REGNUM
, (char *) &vfp
.vfp_fpscr
);
100 else if (regno
>= ARM_D0_REGNUM
101 && regno
<= ARM_D0_REGNUM
+ tdep
->vfp_register_count
)
103 regcache
->raw_supply (regno
,
104 (char *) &vfp
.vfp_regs
[regno
- ARM_D0_REGNUM
]);
107 warning (_("Invalid register number."));
111 fetch_fp_regs (struct regcache
*regcache
)
113 struct fpreg inferior_fp_registers
;
117 ret
= ptrace (PT_GETFPREGS
, regcache
->ptid ().pid (),
118 (PTRACE_TYPE_ARG3
) &inferior_fp_registers
, 0);
122 warning (_("unable to fetch general registers"));
126 arm_supply_vfpregset (regcache
, &inferior_fp_registers
);
130 arm_netbsd_nat_target::fetch_registers (struct regcache
*regcache
, int regno
)
134 if (regno
< ARM_F0_REGNUM
|| regno
> ARM_FPS_REGNUM
)
135 fetch_register (regcache
, regno
);
137 fetch_fp_register (regcache
, regno
);
141 fetch_register (regcache
, -1);
142 fetch_fp_regs (regcache
);
148 store_register (const struct regcache
*regcache
, int regno
)
150 struct gdbarch
*gdbarch
= regcache
->arch ();
151 struct reg inferior_registers
;
154 ret
= ptrace (PT_GETREGS
, regcache
->ptid ().pid (),
155 (PTRACE_TYPE_ARG3
) &inferior_registers
, 0);
159 warning (_("unable to fetch general registers"));
166 regcache
->raw_collect (ARM_SP_REGNUM
, (char *) &inferior_registers
.r_sp
);
170 regcache
->raw_collect (ARM_LR_REGNUM
, (char *) &inferior_registers
.r_lr
);
175 regcache
->raw_collect (ARM_PC_REGNUM
,
176 (char *) &inferior_registers
.r_pc
);
181 regcache
->raw_collect (ARM_PC_REGNUM
, (char *) &pc_val
);
183 pc_val
= gdbarch_addr_bits_remove (gdbarch
, pc_val
);
184 inferior_registers
.r_pc
^= gdbarch_addr_bits_remove
185 (gdbarch
, inferior_registers
.r_pc
);
186 inferior_registers
.r_pc
|= pc_val
;
192 regcache
->raw_collect (ARM_PS_REGNUM
,
193 (char *) &inferior_registers
.r_cpsr
);
198 regcache
->raw_collect (ARM_PS_REGNUM
, (char *) &psr_val
);
200 psr_val
^= gdbarch_addr_bits_remove (gdbarch
, psr_val
);
201 inferior_registers
.r_pc
= gdbarch_addr_bits_remove
202 (gdbarch
, inferior_registers
.r_pc
);
203 inferior_registers
.r_pc
|= psr_val
;
208 regcache
->raw_collect (regno
, (char *) &inferior_registers
.r
[regno
]);
212 ret
= ptrace (PT_SETREGS
, regcache
->ptid ().pid (),
213 (PTRACE_TYPE_ARG3
) &inferior_registers
, 0);
216 warning (_("unable to write register %d to inferior"), regno
);
220 store_regs (const struct regcache
*regcache
)
222 struct gdbarch
*gdbarch
= regcache
->arch ();
223 struct reg inferior_registers
;
228 for (regno
= ARM_A1_REGNUM
; regno
< ARM_SP_REGNUM
; regno
++)
229 regcache
->raw_collect (regno
, (char *) &inferior_registers
.r
[regno
]);
231 regcache
->raw_collect (ARM_SP_REGNUM
, (char *) &inferior_registers
.r_sp
);
232 regcache
->raw_collect (ARM_LR_REGNUM
, (char *) &inferior_registers
.r_lr
);
236 regcache
->raw_collect (ARM_PC_REGNUM
, (char *) &inferior_registers
.r_pc
);
237 regcache
->raw_collect (ARM_PS_REGNUM
,
238 (char *) &inferior_registers
.r_cpsr
);
245 regcache
->raw_collect (ARM_PC_REGNUM
, (char *) &pc_val
);
246 regcache
->raw_collect (ARM_PS_REGNUM
, (char *) &psr_val
);
248 pc_val
= gdbarch_addr_bits_remove (gdbarch
, pc_val
);
249 psr_val
^= gdbarch_addr_bits_remove (gdbarch
, psr_val
);
251 inferior_registers
.r_pc
= pc_val
| psr_val
;
254 ret
= ptrace (PT_SETREGS
, regcache
->ptid ().pid (),
255 (PTRACE_TYPE_ARG3
) &inferior_registers
, 0);
258 warning (_("unable to store general registers"));
262 store_fp_register (const struct regcache
*regcache
, int regno
)
264 struct fpreg inferior_fp_registers
;
265 int ret
= ptrace (PT_GETFPREGS
, regcache
->ptid ().pid (),
266 (PTRACE_TYPE_ARG3
) &inferior_fp_registers
, 0);
267 struct vfpreg
&vfp
= inferior_fp_registers
.fpr_vfp
;
271 warning (_("unable to fetch floating-point registers"));
275 struct gdbarch_tdep
*tdep
= gdbarch_tdep (regcache
->arch ());
276 if (regno
== ARM_FPSCR_REGNUM
&& tdep
->vfp_register_count
!= 0)
277 regcache
->raw_collect (ARM_FPSCR_REGNUM
, (char *) &vfp
.vfp_fpscr
);
278 else if (regno
>= ARM_D0_REGNUM
279 && regno
<= ARM_D0_REGNUM
+ tdep
->vfp_register_count
)
281 regcache
->raw_collect (regno
,
282 (char *) &vfp
.vfp_regs
[regno
- ARM_D0_REGNUM
]);
285 warning (_("Invalid register number."));
287 ret
= ptrace (PT_SETFPREGS
, regcache
->ptid ().pid (),
288 (PTRACE_TYPE_ARG3
) &inferior_fp_registers
, 0);
291 warning (_("unable to write register %d to inferior"), regno
);
295 store_fp_regs (const struct regcache
*regcache
)
297 struct gdbarch_tdep
*tdep
= gdbarch_tdep (regcache
->arch ());
298 if (tdep
->vfp_register_count
== 0)
302 for (int regno
= 0; regno
<= tdep
->vfp_register_count
; regno
++)
303 regcache
->raw_collect
304 (regno
+ ARM_D0_REGNUM
, (char *) &fpregs
.fpr_vfp
.vfp_regs
[regno
]);
306 regcache
->raw_collect (ARM_FPSCR_REGNUM
,
307 (char *) &fpregs
.fpr_vfp
.vfp_fpscr
);
309 int ret
= ptrace (PT_SETFPREGS
, regcache
->ptid ().pid (),
310 (PTRACE_TYPE_ARG3
) &fpregs
, 0);
313 warning (_("unable to store floating-point registers"));
317 arm_netbsd_nat_target::store_registers (struct regcache
*regcache
, int regno
)
321 if (regno
< ARM_F0_REGNUM
|| regno
> ARM_FPS_REGNUM
)
322 store_register (regcache
, regno
);
324 store_fp_register (regcache
, regno
);
328 store_regs (regcache
);
329 store_fp_regs (regcache
);
333 const struct target_desc
*
334 arm_netbsd_nat_target::read_description ()
337 size_t len
= sizeof (flag
);
339 if (sysctlbyname("machdep.fpu_present", &flag
, &len
, NULL
, 0) != 0
341 return arm_read_description (ARM_FP_TYPE_NONE
);
344 if (sysctlbyname("machdep.neon_present", &flag
, &len
, NULL
, 0) == 0 && flag
)
345 return aarch32_read_description ();
347 return arm_read_description (ARM_FP_TYPE_VFPV3
);
350 void _initialize_arm_netbsd_nat ();
352 _initialize_arm_netbsd_nat ()
354 add_inf_child_target (&the_arm_netbsd_nat_target
);