1 /* Native-dependent code for BSD Unix running on ARM's, for GDB.
3 Copyright (C) 1988-2024 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. */
26 #include <sys/types.h>
27 #include <sys/ptrace.h>
28 #include <sys/sysctl.h>
29 #include <machine/reg.h>
30 #include <machine/frame.h>
33 #include "arm-netbsd-tdep.h"
34 #include "aarch32-tdep.h"
35 #include "inf-ptrace.h"
36 #include "netbsd-nat.h"
38 class arm_netbsd_nat_target final
: public nbsd_nat_target
41 /* Add our register access methods. */
42 void fetch_registers (struct regcache
*, int) override
;
43 void store_registers (struct regcache
*, int) override
;
44 const struct target_desc
*read_description () override
;
47 static arm_netbsd_nat_target the_arm_netbsd_nat_target
;
50 arm_supply_vfpregset (struct regcache
*regcache
, struct fpreg
*fpregset
)
52 arm_gdbarch_tdep
*tdep
= gdbarch_tdep
<arm_gdbarch_tdep
> (regcache
->arch ());
53 if (tdep
->vfp_register_count
== 0)
56 struct vfpreg
&vfp
= fpregset
->fpr_vfp
;
57 for (int regno
= 0; regno
<= tdep
->vfp_register_count
; regno
++)
58 regcache
->raw_supply (regno
+ ARM_D0_REGNUM
, (char *) &vfp
.vfp_regs
[regno
]);
60 regcache
->raw_supply (ARM_FPSCR_REGNUM
, (char *) &vfp
.vfp_fpscr
);
64 fetch_register (struct regcache
*regcache
, int regno
)
66 struct reg inferior_registers
;
68 int lwp
= regcache
->ptid ().lwp ();
70 ret
= ptrace (PT_GETREGS
, regcache
->ptid ().pid (),
71 (PTRACE_TYPE_ARG3
) &inferior_registers
, lwp
);
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 lwp
= regcache
->ptid ().lwp ();
88 int ret
= ptrace (PT_GETFPREGS
, regcache
->ptid ().pid (),
89 (PTRACE_TYPE_ARG3
) &inferior_fp_registers
, lwp
);
91 struct vfpreg
&vfp
= inferior_fp_registers
.fpr_vfp
;
95 warning (_("unable to fetch floating-point register"));
99 arm_gdbarch_tdep
*tdep
= gdbarch_tdep
<arm_gdbarch_tdep
> (regcache
->arch ());
100 if (regno
== ARM_FPSCR_REGNUM
&& tdep
->vfp_register_count
!= 0)
101 regcache
->raw_supply (ARM_FPSCR_REGNUM
, (char *) &vfp
.vfp_fpscr
);
102 else if (regno
>= ARM_D0_REGNUM
103 && regno
<= ARM_D0_REGNUM
+ tdep
->vfp_register_count
)
105 regcache
->raw_supply (regno
,
106 (char *) &vfp
.vfp_regs
[regno
- ARM_D0_REGNUM
]);
109 warning (_("Invalid register number."));
113 fetch_fp_regs (struct regcache
*regcache
)
115 struct fpreg inferior_fp_registers
;
116 int lwp
= regcache
->ptid ().lwp ();
120 ret
= ptrace (PT_GETFPREGS
, regcache
->ptid ().pid (),
121 (PTRACE_TYPE_ARG3
) &inferior_fp_registers
, lwp
);
125 warning (_("unable to fetch general registers"));
129 arm_supply_vfpregset (regcache
, &inferior_fp_registers
);
133 arm_netbsd_nat_target::fetch_registers (struct regcache
*regcache
, int regno
)
137 if (regno
< ARM_F0_REGNUM
|| regno
> ARM_FPS_REGNUM
)
138 fetch_register (regcache
, regno
);
140 fetch_fp_register (regcache
, regno
);
144 fetch_register (regcache
, -1);
145 fetch_fp_regs (regcache
);
151 store_register (const struct regcache
*regcache
, int regno
)
153 struct gdbarch
*gdbarch
= regcache
->arch ();
154 struct reg inferior_registers
;
155 int lwp
= regcache
->ptid ().lwp ();
158 ret
= ptrace (PT_GETREGS
, regcache
->ptid ().pid (),
159 (PTRACE_TYPE_ARG3
) &inferior_registers
, lwp
);
163 warning (_("unable to fetch general registers"));
170 regcache
->raw_collect (ARM_SP_REGNUM
, (char *) &inferior_registers
.r_sp
);
174 regcache
->raw_collect (ARM_LR_REGNUM
, (char *) &inferior_registers
.r_lr
);
179 regcache
->raw_collect (ARM_PC_REGNUM
,
180 (char *) &inferior_registers
.r_pc
);
185 regcache
->raw_collect (ARM_PC_REGNUM
, (char *) &pc_val
);
187 pc_val
= gdbarch_addr_bits_remove (gdbarch
, pc_val
);
188 inferior_registers
.r_pc
^= gdbarch_addr_bits_remove
189 (gdbarch
, inferior_registers
.r_pc
);
190 inferior_registers
.r_pc
|= pc_val
;
196 regcache
->raw_collect (ARM_PS_REGNUM
,
197 (char *) &inferior_registers
.r_cpsr
);
202 regcache
->raw_collect (ARM_PS_REGNUM
, (char *) &psr_val
);
204 psr_val
^= gdbarch_addr_bits_remove (gdbarch
, psr_val
);
205 inferior_registers
.r_pc
= gdbarch_addr_bits_remove
206 (gdbarch
, inferior_registers
.r_pc
);
207 inferior_registers
.r_pc
|= psr_val
;
212 regcache
->raw_collect (regno
, (char *) &inferior_registers
.r
[regno
]);
216 ret
= ptrace (PT_SETREGS
, regcache
->ptid ().pid (),
217 (PTRACE_TYPE_ARG3
) &inferior_registers
, lwp
);
220 warning (_("unable to write register %d to inferior"), regno
);
224 store_regs (const struct regcache
*regcache
)
226 struct gdbarch
*gdbarch
= regcache
->arch ();
227 struct reg inferior_registers
;
228 int lwp
= regcache
->ptid ().lwp ();
233 for (regno
= ARM_A1_REGNUM
; regno
< ARM_SP_REGNUM
; regno
++)
234 regcache
->raw_collect (regno
, (char *) &inferior_registers
.r
[regno
]);
236 regcache
->raw_collect (ARM_SP_REGNUM
, (char *) &inferior_registers
.r_sp
);
237 regcache
->raw_collect (ARM_LR_REGNUM
, (char *) &inferior_registers
.r_lr
);
241 regcache
->raw_collect (ARM_PC_REGNUM
, (char *) &inferior_registers
.r_pc
);
242 regcache
->raw_collect (ARM_PS_REGNUM
,
243 (char *) &inferior_registers
.r_cpsr
);
250 regcache
->raw_collect (ARM_PC_REGNUM
, (char *) &pc_val
);
251 regcache
->raw_collect (ARM_PS_REGNUM
, (char *) &psr_val
);
253 pc_val
= gdbarch_addr_bits_remove (gdbarch
, pc_val
);
254 psr_val
^= gdbarch_addr_bits_remove (gdbarch
, psr_val
);
256 inferior_registers
.r_pc
= pc_val
| psr_val
;
259 ret
= ptrace (PT_SETREGS
, regcache
->ptid ().pid (),
260 (PTRACE_TYPE_ARG3
) &inferior_registers
, lwp
);
263 warning (_("unable to store general registers"));
267 store_fp_register (const struct regcache
*regcache
, int regno
)
269 struct fpreg inferior_fp_registers
;
270 int lwp
= regcache
->ptid ().lwp ();
271 int ret
= ptrace (PT_GETFPREGS
, regcache
->ptid ().pid (),
272 (PTRACE_TYPE_ARG3
) &inferior_fp_registers
, lwp
);
273 struct vfpreg
&vfp
= inferior_fp_registers
.fpr_vfp
;
277 warning (_("unable to fetch floating-point registers"));
281 arm_gdbarch_tdep
*tdep
= gdbarch_tdep
<arm_gdbarch_tdep
> (regcache
->arch ());
282 if (regno
== ARM_FPSCR_REGNUM
&& tdep
->vfp_register_count
!= 0)
283 regcache
->raw_collect (ARM_FPSCR_REGNUM
, (char *) &vfp
.vfp_fpscr
);
284 else if (regno
>= ARM_D0_REGNUM
285 && regno
<= ARM_D0_REGNUM
+ tdep
->vfp_register_count
)
287 regcache
->raw_collect (regno
,
288 (char *) &vfp
.vfp_regs
[regno
- ARM_D0_REGNUM
]);
291 warning (_("Invalid register number."));
293 ret
= ptrace (PT_SETFPREGS
, regcache
->ptid ().pid (),
294 (PTRACE_TYPE_ARG3
) &inferior_fp_registers
, lwp
);
297 warning (_("unable to write register %d to inferior"), regno
);
301 store_fp_regs (const struct regcache
*regcache
)
303 arm_gdbarch_tdep
*tdep
= gdbarch_tdep
<arm_gdbarch_tdep
> (regcache
->arch ());
304 int lwp
= regcache
->ptid ().lwp ();
305 if (tdep
->vfp_register_count
== 0)
309 for (int regno
= 0; regno
<= tdep
->vfp_register_count
; regno
++)
310 regcache
->raw_collect
311 (regno
+ ARM_D0_REGNUM
, (char *) &fpregs
.fpr_vfp
.vfp_regs
[regno
]);
313 regcache
->raw_collect (ARM_FPSCR_REGNUM
,
314 (char *) &fpregs
.fpr_vfp
.vfp_fpscr
);
316 int ret
= ptrace (PT_SETFPREGS
, regcache
->ptid ().pid (),
317 (PTRACE_TYPE_ARG3
) &fpregs
, lwp
);
320 warning (_("unable to store floating-point registers"));
324 arm_netbsd_nat_target::store_registers (struct regcache
*regcache
, int regno
)
328 if (regno
< ARM_F0_REGNUM
|| regno
> ARM_FPS_REGNUM
)
329 store_register (regcache
, regno
);
331 store_fp_register (regcache
, regno
);
335 store_regs (regcache
);
336 store_fp_regs (regcache
);
340 const struct target_desc
*
341 arm_netbsd_nat_target::read_description ()
344 size_t len
= sizeof (flag
);
346 if (sysctlbyname("machdep.fpu_present", &flag
, &len
, NULL
, 0) != 0
348 return arm_read_description (ARM_FP_TYPE_NONE
, false);
351 if (sysctlbyname("machdep.neon_present", &flag
, &len
, NULL
, 0) == 0 && flag
)
352 return aarch32_read_description (false);
354 return arm_read_description (ARM_FP_TYPE_VFPV3
, false);
357 void _initialize_arm_netbsd_nat ();
359 _initialize_arm_netbsd_nat ()
361 add_inf_child_target (&the_arm_netbsd_nat_target
);