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"
38 class arm_netbsd_nat_target final
: public inf_ptrace_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 struct gdbarch_tdep
*tdep
= 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
;
69 ret
= ptrace (PT_GETREGS
, regcache
->ptid ().pid (),
70 (PTRACE_TYPE_ARG3
) &inferior_registers
, 0);
74 warning (_("unable to fetch general register"));
77 arm_nbsd_supply_gregset (nullptr, regcache
, regno
, &inferior_registers
,
78 sizeof (inferior_registers
));
82 fetch_fp_register (struct regcache
*regcache
, int regno
)
84 struct fpreg inferior_fp_registers
;
85 int ret
= ptrace (PT_GETFPREGS
, regcache
->ptid ().pid (),
86 (PTRACE_TYPE_ARG3
) &inferior_fp_registers
, 0);
88 struct vfpreg
&vfp
= inferior_fp_registers
.fpr_vfp
;
92 warning (_("unable to fetch floating-point register"));
96 struct gdbarch_tdep
*tdep
= gdbarch_tdep (regcache
->arch ());
97 if (regno
== ARM_FPSCR_REGNUM
&& tdep
->vfp_register_count
!= 0)
98 regcache
->raw_supply (ARM_FPSCR_REGNUM
, (char *) &vfp
.vfp_fpscr
);
99 else if (regno
>= ARM_D0_REGNUM
100 && regno
<= ARM_D0_REGNUM
+ tdep
->vfp_register_count
)
102 regcache
->raw_supply (regno
,
103 (char *) &vfp
.vfp_regs
[regno
- ARM_D0_REGNUM
]);
106 warning (_("Invalid register number."));
110 fetch_fp_regs (struct regcache
*regcache
)
112 struct fpreg inferior_fp_registers
;
116 ret
= ptrace (PT_GETFPREGS
, regcache
->ptid ().pid (),
117 (PTRACE_TYPE_ARG3
) &inferior_fp_registers
, 0);
121 warning (_("unable to fetch general registers"));
125 arm_supply_vfpregset (regcache
, &inferior_fp_registers
);
129 arm_netbsd_nat_target::fetch_registers (struct regcache
*regcache
, int regno
)
133 if (regno
< ARM_F0_REGNUM
|| regno
> ARM_FPS_REGNUM
)
134 fetch_register (regcache
, regno
);
136 fetch_fp_register (regcache
, regno
);
140 fetch_register (regcache
, -1);
141 fetch_fp_regs (regcache
);
147 store_register (const struct regcache
*regcache
, int regno
)
149 struct gdbarch
*gdbarch
= regcache
->arch ();
150 struct reg inferior_registers
;
153 ret
= ptrace (PT_GETREGS
, regcache
->ptid ().pid (),
154 (PTRACE_TYPE_ARG3
) &inferior_registers
, 0);
158 warning (_("unable to fetch general registers"));
165 regcache
->raw_collect (ARM_SP_REGNUM
, (char *) &inferior_registers
.r_sp
);
169 regcache
->raw_collect (ARM_LR_REGNUM
, (char *) &inferior_registers
.r_lr
);
174 regcache
->raw_collect (ARM_PC_REGNUM
,
175 (char *) &inferior_registers
.r_pc
);
180 regcache
->raw_collect (ARM_PC_REGNUM
, (char *) &pc_val
);
182 pc_val
= gdbarch_addr_bits_remove (gdbarch
, pc_val
);
183 inferior_registers
.r_pc
^= gdbarch_addr_bits_remove
184 (gdbarch
, inferior_registers
.r_pc
);
185 inferior_registers
.r_pc
|= pc_val
;
191 regcache
->raw_collect (ARM_PS_REGNUM
,
192 (char *) &inferior_registers
.r_cpsr
);
197 regcache
->raw_collect (ARM_PS_REGNUM
, (char *) &psr_val
);
199 psr_val
^= gdbarch_addr_bits_remove (gdbarch
, psr_val
);
200 inferior_registers
.r_pc
= gdbarch_addr_bits_remove
201 (gdbarch
, inferior_registers
.r_pc
);
202 inferior_registers
.r_pc
|= psr_val
;
207 regcache
->raw_collect (regno
, (char *) &inferior_registers
.r
[regno
]);
211 ret
= ptrace (PT_SETREGS
, regcache
->ptid ().pid (),
212 (PTRACE_TYPE_ARG3
) &inferior_registers
, 0);
215 warning (_("unable to write register %d to inferior"), regno
);
219 store_regs (const struct regcache
*regcache
)
221 struct gdbarch
*gdbarch
= regcache
->arch ();
222 struct reg inferior_registers
;
227 for (regno
= ARM_A1_REGNUM
; regno
< ARM_SP_REGNUM
; regno
++)
228 regcache
->raw_collect (regno
, (char *) &inferior_registers
.r
[regno
]);
230 regcache
->raw_collect (ARM_SP_REGNUM
, (char *) &inferior_registers
.r_sp
);
231 regcache
->raw_collect (ARM_LR_REGNUM
, (char *) &inferior_registers
.r_lr
);
235 regcache
->raw_collect (ARM_PC_REGNUM
, (char *) &inferior_registers
.r_pc
);
236 regcache
->raw_collect (ARM_PS_REGNUM
,
237 (char *) &inferior_registers
.r_cpsr
);
244 regcache
->raw_collect (ARM_PC_REGNUM
, (char *) &pc_val
);
245 regcache
->raw_collect (ARM_PS_REGNUM
, (char *) &psr_val
);
247 pc_val
= gdbarch_addr_bits_remove (gdbarch
, pc_val
);
248 psr_val
^= gdbarch_addr_bits_remove (gdbarch
, psr_val
);
250 inferior_registers
.r_pc
= pc_val
| psr_val
;
253 ret
= ptrace (PT_SETREGS
, regcache
->ptid ().pid (),
254 (PTRACE_TYPE_ARG3
) &inferior_registers
, 0);
257 warning (_("unable to store general registers"));
261 store_fp_register (const struct regcache
*regcache
, int regno
)
263 struct fpreg inferior_fp_registers
;
264 int ret
= ptrace (PT_GETFPREGS
, regcache
->ptid ().pid (),
265 (PTRACE_TYPE_ARG3
) &inferior_fp_registers
, 0);
266 struct vfpreg
&vfp
= inferior_fp_registers
.fpr_vfp
;
270 warning (_("unable to fetch floating-point registers"));
274 struct gdbarch_tdep
*tdep
= gdbarch_tdep (regcache
->arch ());
275 if (regno
== ARM_FPSCR_REGNUM
&& tdep
->vfp_register_count
!= 0)
276 regcache
->raw_collect (ARM_FPSCR_REGNUM
, (char *) &vfp
.vfp_fpscr
);
277 else if (regno
>= ARM_D0_REGNUM
278 && regno
<= ARM_D0_REGNUM
+ tdep
->vfp_register_count
)
280 regcache
->raw_collect (regno
,
281 (char *) &vfp
.vfp_regs
[regno
- ARM_D0_REGNUM
]);
284 warning (_("Invalid register number."));
286 ret
= ptrace (PT_SETFPREGS
, regcache
->ptid ().pid (),
287 (PTRACE_TYPE_ARG3
) &inferior_fp_registers
, 0);
290 warning (_("unable to write register %d to inferior"), regno
);
294 store_fp_regs (const struct regcache
*regcache
)
296 struct gdbarch_tdep
*tdep
= gdbarch_tdep (regcache
->arch ());
297 if (tdep
->vfp_register_count
== 0)
301 for (int regno
= 0; regno
<= tdep
->vfp_register_count
; regno
++)
302 regcache
->raw_collect
303 (regno
+ ARM_D0_REGNUM
, (char *) &fpregs
.fpr_vfp
.vfp_regs
[regno
]);
305 regcache
->raw_collect (ARM_FPSCR_REGNUM
,
306 (char *) &fpregs
.fpr_vfp
.vfp_fpscr
);
308 int ret
= ptrace (PT_SETFPREGS
, regcache
->ptid ().pid (),
309 (PTRACE_TYPE_ARG3
) &fpregs
, 0);
312 warning (_("unable to store floating-point registers"));
316 arm_netbsd_nat_target::store_registers (struct regcache
*regcache
, int regno
)
320 if (regno
< ARM_F0_REGNUM
|| regno
> ARM_FPS_REGNUM
)
321 store_register (regcache
, regno
);
323 store_fp_register (regcache
, regno
);
327 store_regs (regcache
);
328 store_fp_regs (regcache
);
332 const struct target_desc
*
333 arm_netbsd_nat_target::read_description ()
336 size_t len
= sizeof (flag
);
338 if (sysctlbyname("machdep.fpu_present", &flag
, &len
, NULL
, 0) != 0
340 return arm_read_description (ARM_FP_TYPE_NONE
);
343 if (sysctlbyname("machdep.neon_present", &flag
, &len
, NULL
, 0) == 0 && flag
)
344 return aarch32_read_description ();
346 return arm_read_description (ARM_FP_TYPE_VFPV3
);
349 void _initialize_arm_netbsd_nat ();
351 _initialize_arm_netbsd_nat ()
353 add_inf_child_target (&the_arm_netbsd_nat_target
);