gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / arm-nbsd-nat.c
CommitLineData
e7a42bc8 1/* Native-dependent code for BSD Unix running on ARM's, for GDB.
9f8e0089 2
b811d2c2 3 Copyright (C) 1988-2020 Free Software Foundation, Inc.
e7a42bc8
FN
4
5 This file is part of GDB.
6
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
e7a42bc8
FN
10 (at your option) any later version.
11
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.
16
17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
e7a42bc8 19
73685c7e
CB
20/* We define this to get types like register_t. */
21#define _KERNTYPES
e7a42bc8 22#include "defs.h"
d55e5aa6 23#include "gdbcore.h"
d55e5aa6
TT
24#include "inferior.h"
25#include "regcache.h"
26#include "target.h"
4de283e4
TT
27#include <sys/types.h>
28#include <sys/ptrace.h>
81b86b97 29#include <sys/sysctl.h>
4de283e4
TT
30#include <machine/reg.h>
31#include <machine/frame.h>
32
33#include "arm-tdep.h"
8dd8e1c7 34#include "arm-nbsd-tdep.h"
81b86b97 35#include "aarch32-tdep.h"
4de283e4 36#include "inf-ptrace.h"
6018d381 37#include "nbsd-nat.h"
e7a42bc8 38
6018d381 39class arm_netbsd_nat_target final : public nbsd_nat_target
f6ac5f3d
PA
40{
41public:
42 /* Add our register access methods. */
43 void fetch_registers (struct regcache *, int) override;
44 void store_registers (struct regcache *, int) override;
81b86b97 45 const struct target_desc *read_description () override;
f6ac5f3d
PA
46};
47
48static arm_netbsd_nat_target the_arm_netbsd_nat_target;
49
b34db576 50static void
81b86b97 51arm_supply_vfpregset (struct regcache *regcache, struct fpreg *fpregset)
b34db576 52{
81b86b97
CB
53 struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
54 if (tdep->vfp_register_count == 0)
55 return;
b34db576 56
81b86b97
CB
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]);
b34db576 60
81b86b97 61 regcache->raw_supply (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr);
b34db576
RE
62}
63
47221191 64static void
56be3814 65fetch_register (struct regcache *regcache, int regno)
47221191
RE
66{
67 struct reg inferior_registers;
68 int ret;
75c56d3d 69 int lwp = regcache->ptid ().lwp ();
47221191 70
e99b03dc 71 ret = ptrace (PT_GETREGS, regcache->ptid ().pid (),
75c56d3d 72 (PTRACE_TYPE_ARG3) &inferior_registers, lwp);
47221191
RE
73
74 if (ret < 0)
75 {
edefbb7c 76 warning (_("unable to fetch general register"));
47221191
RE
77 return;
78 }
8dd8e1c7
CB
79 arm_nbsd_supply_gregset (nullptr, regcache, regno, &inferior_registers,
80 sizeof (inferior_registers));
47221191
RE
81}
82
83static void
56be3814 84fetch_fp_register (struct regcache *regcache, int regno)
47221191
RE
85{
86 struct fpreg inferior_fp_registers;
75c56d3d
KR
87 int lwp = regcache->ptid ().lwp ();
88
81b86b97 89 int ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
75c56d3d 90 (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp);
47221191 91
81b86b97 92 struct vfpreg &vfp = inferior_fp_registers.fpr_vfp;
47221191
RE
93
94 if (ret < 0)
95 {
edefbb7c 96 warning (_("unable to fetch floating-point register"));
47221191
RE
97 return;
98 }
99
81b86b97
CB
100 struct gdbarch_tdep *tdep = 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)
47221191 105 {
81b86b97
CB
106 regcache->raw_supply (regno,
107 (char *) &vfp.vfp_regs[regno - ARM_D0_REGNUM]);
47221191 108 }
81b86b97
CB
109 else
110 warning (_("Invalid register number."));
47221191
RE
111}
112
113static void
56be3814 114fetch_fp_regs (struct regcache *regcache)
47221191
RE
115{
116 struct fpreg inferior_fp_registers;
75c56d3d 117 int lwp = regcache->ptid ().lwp ();
47221191
RE
118 int ret;
119 int regno;
120
e99b03dc 121 ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
75c56d3d 122 (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp);
47221191
RE
123
124 if (ret < 0)
125 {
edefbb7c 126 warning (_("unable to fetch general registers"));
47221191
RE
127 return;
128 }
129
81b86b97 130 arm_supply_vfpregset (regcache, &inferior_fp_registers);
e7a42bc8
FN
131}
132
f6ac5f3d 133void
3050c6f4 134arm_netbsd_nat_target::fetch_registers (struct regcache *regcache, int regno)
47221191
RE
135{
136 if (regno >= 0)
137 {
138 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
56be3814 139 fetch_register (regcache, regno);
47221191 140 else
56be3814 141 fetch_fp_register (regcache, regno);
47221191
RE
142 }
143 else
144 {
8dd8e1c7 145 fetch_register (regcache, -1);
56be3814 146 fetch_fp_regs (regcache);
47221191
RE
147 }
148}
149
150
151static void
56be3814 152store_register (const struct regcache *regcache, int regno)
e7a42bc8 153{
ac7936df 154 struct gdbarch *gdbarch = regcache->arch ();
e7a42bc8 155 struct reg inferior_registers;
75c56d3d 156 int lwp = regcache->ptid ().lwp ();
47221191
RE
157 int ret;
158
e99b03dc 159 ret = ptrace (PT_GETREGS, regcache->ptid ().pid (),
75c56d3d 160 (PTRACE_TYPE_ARG3) &inferior_registers, lwp);
47221191
RE
161
162 if (ret < 0)
163 {
edefbb7c 164 warning (_("unable to fetch general registers"));
47221191
RE
165 return;
166 }
167
168 switch (regno)
169 {
170 case ARM_SP_REGNUM:
34a79281 171 regcache->raw_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
47221191
RE
172 break;
173
174 case ARM_LR_REGNUM:
34a79281 175 regcache->raw_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
47221191 176 break;
e7a42bc8 177
47221191
RE
178 case ARM_PC_REGNUM:
179 if (arm_apcs_32)
34a79281
SM
180 regcache->raw_collect (ARM_PC_REGNUM,
181 (char *) &inferior_registers.r_pc);
47221191
RE
182 else
183 {
184 unsigned pc_val;
e7a42bc8 185
34a79281 186 regcache->raw_collect (ARM_PC_REGNUM, (char *) &pc_val);
47221191 187
b2cb219a 188 pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
bf6ae464 189 inferior_registers.r_pc ^= gdbarch_addr_bits_remove
b2cb219a 190 (gdbarch, inferior_registers.r_pc);
47221191
RE
191 inferior_registers.r_pc |= pc_val;
192 }
193 break;
194
195 case ARM_PS_REGNUM:
196 if (arm_apcs_32)
34a79281
SM
197 regcache->raw_collect (ARM_PS_REGNUM,
198 (char *) &inferior_registers.r_cpsr);
47221191
RE
199 else
200 {
201 unsigned psr_val;
202
34a79281 203 regcache->raw_collect (ARM_PS_REGNUM, (char *) &psr_val);
47221191 204
b2cb219a 205 psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
bf6ae464 206 inferior_registers.r_pc = gdbarch_addr_bits_remove
b2cb219a 207 (gdbarch, inferior_registers.r_pc);
47221191
RE
208 inferior_registers.r_pc |= psr_val;
209 }
210 break;
211
212 default:
34a79281 213 regcache->raw_collect (regno, (char *) &inferior_registers.r[regno]);
47221191
RE
214 break;
215 }
216
e99b03dc 217 ret = ptrace (PT_SETREGS, regcache->ptid ().pid (),
75c56d3d 218 (PTRACE_TYPE_ARG3) &inferior_registers, lwp);
47221191
RE
219
220 if (ret < 0)
edefbb7c 221 warning (_("unable to write register %d to inferior"), regno);
47221191
RE
222}
223
224static void
56be3814 225store_regs (const struct regcache *regcache)
47221191 226{
ac7936df 227 struct gdbarch *gdbarch = regcache->arch ();
47221191 228 struct reg inferior_registers;
75c56d3d 229 int lwp = regcache->ptid ().lwp ();
47221191
RE
230 int ret;
231 int regno;
232
233
234 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
34a79281 235 regcache->raw_collect (regno, (char *) &inferior_registers.r[regno]);
47221191 236
34a79281
SM
237 regcache->raw_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
238 regcache->raw_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
47221191
RE
239
240 if (arm_apcs_32)
241 {
34a79281
SM
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);
47221191
RE
245 }
246 else
247 {
248 unsigned pc_val;
249 unsigned psr_val;
250
34a79281
SM
251 regcache->raw_collect (ARM_PC_REGNUM, (char *) &pc_val);
252 regcache->raw_collect (ARM_PS_REGNUM, (char *) &psr_val);
47221191 253
b2cb219a
UW
254 pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
255 psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
47221191
RE
256
257 inferior_registers.r_pc = pc_val | psr_val;
258 }
259
e99b03dc 260 ret = ptrace (PT_SETREGS, regcache->ptid ().pid (),
75c56d3d 261 (PTRACE_TYPE_ARG3) &inferior_registers, lwp);
47221191
RE
262
263 if (ret < 0)
edefbb7c 264 warning (_("unable to store general registers"));
47221191
RE
265}
266
267static void
56be3814 268store_fp_register (const struct regcache *regcache, int regno)
47221191
RE
269{
270 struct fpreg inferior_fp_registers;
75c56d3d 271 int lwp = regcache->ptid ().lwp ();
81b86b97 272 int ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
75c56d3d 273 (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp);
81b86b97 274 struct vfpreg &vfp = inferior_fp_registers.fpr_vfp;
47221191
RE
275
276 if (ret < 0)
277 {
edefbb7c 278 warning (_("unable to fetch floating-point registers"));
47221191
RE
279 return;
280 }
281
81b86b97
CB
282 struct gdbarch_tdep *tdep = 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)
47221191 287 {
81b86b97
CB
288 regcache->raw_collect (regno,
289 (char *) &vfp.vfp_regs[regno - ARM_D0_REGNUM]);
47221191 290 }
81b86b97
CB
291 else
292 warning (_("Invalid register number."));
47221191 293
e99b03dc 294 ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (),
75c56d3d 295 (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp);
47221191
RE
296
297 if (ret < 0)
edefbb7c 298 warning (_("unable to write register %d to inferior"), regno);
47221191
RE
299}
300
301static void
56be3814 302store_fp_regs (const struct regcache *regcache)
47221191 303{
81b86b97 304 struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
75c56d3d 305 int lwp = regcache->ptid ().lwp ();
81b86b97
CB
306 if (tdep->vfp_register_count == 0)
307 return;
47221191 308
81b86b97
CB
309 struct fpreg fpregs;
310 for (int regno = 0; regno <= tdep->vfp_register_count; regno++)
34a79281 311 regcache->raw_collect
81b86b97 312 (regno + ARM_D0_REGNUM, (char *) &fpregs.fpr_vfp.vfp_regs[regno]);
47221191 313
81b86b97
CB
314 regcache->raw_collect (ARM_FPSCR_REGNUM,
315 (char *) &fpregs.fpr_vfp.vfp_fpscr);
47221191 316
81b86b97 317 int ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (),
75c56d3d 318 (PTRACE_TYPE_ARG3) &fpregs, lwp);
47221191
RE
319
320 if (ret < 0)
edefbb7c 321 warning (_("unable to store floating-point registers"));
47221191
RE
322}
323
f6ac5f3d 324void
3050c6f4 325arm_netbsd_nat_target::store_registers (struct regcache *regcache, int regno)
47221191
RE
326{
327 if (regno >= 0)
328 {
329 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
56be3814 330 store_register (regcache, regno);
47221191 331 else
56be3814 332 store_fp_register (regcache, regno);
47221191
RE
333 }
334 else
335 {
56be3814
UW
336 store_regs (regcache);
337 store_fp_regs (regcache);
47221191 338 }
e7a42bc8
FN
339}
340
81b86b97
CB
341const struct target_desc *
342arm_netbsd_nat_target::read_description ()
343{
344 int flag;
345 size_t len = sizeof (flag);
346
347 if (sysctlbyname("machdep.fpu_present", &flag, &len, NULL, 0) != 0
348 || !flag)
349 return arm_read_description (ARM_FP_TYPE_NONE);
350
351 len = sizeof(flag);
352 if (sysctlbyname("machdep.neon_present", &flag, &len, NULL, 0) == 0 && flag)
353 return aarch32_read_description ();
354
355 return arm_read_description (ARM_FP_TYPE_VFPV3);
356}
357
6c265988 358void _initialize_arm_netbsd_nat ();
3e56fc4b 359void
6c265988 360_initialize_arm_netbsd_nat ()
3e56fc4b 361{
d9f719f1 362 add_inf_child_target (&the_arm_netbsd_nat_target);
3e56fc4b 363}
This page took 1.167418 seconds and 4 git commands to generate.