Add support for NetBSD threads in x86-bsd-nat.c
[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"
e7a42bc8 37
f6ac5f3d
PA
38class arm_netbsd_nat_target final : public inf_ptrace_target
39{
40public:
41 /* Add our register access methods. */
42 void fetch_registers (struct regcache *, int) override;
43 void store_registers (struct regcache *, int) override;
81b86b97 44 const struct target_desc *read_description () override;
f6ac5f3d
PA
45};
46
47static arm_netbsd_nat_target the_arm_netbsd_nat_target;
48
b34db576 49static void
81b86b97 50arm_supply_vfpregset (struct regcache *regcache, struct fpreg *fpregset)
b34db576 51{
81b86b97
CB
52 struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
53 if (tdep->vfp_register_count == 0)
54 return;
b34db576 55
81b86b97
CB
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]);
b34db576 59
81b86b97 60 regcache->raw_supply (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr);
b34db576
RE
61}
62
47221191 63static void
56be3814 64fetch_register (struct regcache *regcache, int regno)
47221191
RE
65{
66 struct reg inferior_registers;
67 int ret;
68
e99b03dc 69 ret = ptrace (PT_GETREGS, regcache->ptid ().pid (),
9f8e0089 70 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
71
72 if (ret < 0)
73 {
edefbb7c 74 warning (_("unable to fetch general register"));
47221191
RE
75 return;
76 }
8dd8e1c7
CB
77 arm_nbsd_supply_gregset (nullptr, regcache, regno, &inferior_registers,
78 sizeof (inferior_registers));
47221191
RE
79}
80
81static void
56be3814 82fetch_fp_register (struct regcache *regcache, int regno)
47221191
RE
83{
84 struct fpreg inferior_fp_registers;
81b86b97
CB
85 int ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
86 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191 87
81b86b97 88 struct vfpreg &vfp = inferior_fp_registers.fpr_vfp;
47221191
RE
89
90 if (ret < 0)
91 {
edefbb7c 92 warning (_("unable to fetch floating-point register"));
47221191
RE
93 return;
94 }
95
81b86b97
CB
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)
47221191 101 {
81b86b97
CB
102 regcache->raw_supply (regno,
103 (char *) &vfp.vfp_regs[regno - ARM_D0_REGNUM]);
47221191 104 }
81b86b97
CB
105 else
106 warning (_("Invalid register number."));
47221191
RE
107}
108
109static void
56be3814 110fetch_fp_regs (struct regcache *regcache)
47221191
RE
111{
112 struct fpreg inferior_fp_registers;
113 int ret;
114 int regno;
115
e99b03dc 116 ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
9f8e0089 117 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
118
119 if (ret < 0)
120 {
edefbb7c 121 warning (_("unable to fetch general registers"));
47221191
RE
122 return;
123 }
124
81b86b97 125 arm_supply_vfpregset (regcache, &inferior_fp_registers);
e7a42bc8
FN
126}
127
f6ac5f3d 128void
3050c6f4 129arm_netbsd_nat_target::fetch_registers (struct regcache *regcache, int regno)
47221191
RE
130{
131 if (regno >= 0)
132 {
133 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
56be3814 134 fetch_register (regcache, regno);
47221191 135 else
56be3814 136 fetch_fp_register (regcache, regno);
47221191
RE
137 }
138 else
139 {
8dd8e1c7 140 fetch_register (regcache, -1);
56be3814 141 fetch_fp_regs (regcache);
47221191
RE
142 }
143}
144
145
146static void
56be3814 147store_register (const struct regcache *regcache, int regno)
e7a42bc8 148{
ac7936df 149 struct gdbarch *gdbarch = regcache->arch ();
e7a42bc8 150 struct reg inferior_registers;
47221191
RE
151 int ret;
152
e99b03dc 153 ret = ptrace (PT_GETREGS, regcache->ptid ().pid (),
9f8e0089 154 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
155
156 if (ret < 0)
157 {
edefbb7c 158 warning (_("unable to fetch general registers"));
47221191
RE
159 return;
160 }
161
162 switch (regno)
163 {
164 case ARM_SP_REGNUM:
34a79281 165 regcache->raw_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
47221191
RE
166 break;
167
168 case ARM_LR_REGNUM:
34a79281 169 regcache->raw_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
47221191 170 break;
e7a42bc8 171
47221191
RE
172 case ARM_PC_REGNUM:
173 if (arm_apcs_32)
34a79281
SM
174 regcache->raw_collect (ARM_PC_REGNUM,
175 (char *) &inferior_registers.r_pc);
47221191
RE
176 else
177 {
178 unsigned pc_val;
e7a42bc8 179
34a79281 180 regcache->raw_collect (ARM_PC_REGNUM, (char *) &pc_val);
47221191 181
b2cb219a 182 pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
bf6ae464 183 inferior_registers.r_pc ^= gdbarch_addr_bits_remove
b2cb219a 184 (gdbarch, inferior_registers.r_pc);
47221191
RE
185 inferior_registers.r_pc |= pc_val;
186 }
187 break;
188
189 case ARM_PS_REGNUM:
190 if (arm_apcs_32)
34a79281
SM
191 regcache->raw_collect (ARM_PS_REGNUM,
192 (char *) &inferior_registers.r_cpsr);
47221191
RE
193 else
194 {
195 unsigned psr_val;
196
34a79281 197 regcache->raw_collect (ARM_PS_REGNUM, (char *) &psr_val);
47221191 198
b2cb219a 199 psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
bf6ae464 200 inferior_registers.r_pc = gdbarch_addr_bits_remove
b2cb219a 201 (gdbarch, inferior_registers.r_pc);
47221191
RE
202 inferior_registers.r_pc |= psr_val;
203 }
204 break;
205
206 default:
34a79281 207 regcache->raw_collect (regno, (char *) &inferior_registers.r[regno]);
47221191
RE
208 break;
209 }
210
e99b03dc 211 ret = ptrace (PT_SETREGS, regcache->ptid ().pid (),
9f8e0089 212 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
213
214 if (ret < 0)
edefbb7c 215 warning (_("unable to write register %d to inferior"), regno);
47221191
RE
216}
217
218static void
56be3814 219store_regs (const struct regcache *regcache)
47221191 220{
ac7936df 221 struct gdbarch *gdbarch = regcache->arch ();
47221191
RE
222 struct reg inferior_registers;
223 int ret;
224 int regno;
225
226
227 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
34a79281 228 regcache->raw_collect (regno, (char *) &inferior_registers.r[regno]);
47221191 229
34a79281
SM
230 regcache->raw_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
231 regcache->raw_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
47221191
RE
232
233 if (arm_apcs_32)
234 {
34a79281
SM
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);
47221191
RE
238 }
239 else
240 {
241 unsigned pc_val;
242 unsigned psr_val;
243
34a79281
SM
244 regcache->raw_collect (ARM_PC_REGNUM, (char *) &pc_val);
245 regcache->raw_collect (ARM_PS_REGNUM, (char *) &psr_val);
47221191 246
b2cb219a
UW
247 pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
248 psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
47221191
RE
249
250 inferior_registers.r_pc = pc_val | psr_val;
251 }
252
e99b03dc 253 ret = ptrace (PT_SETREGS, regcache->ptid ().pid (),
9f8e0089 254 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
255
256 if (ret < 0)
edefbb7c 257 warning (_("unable to store general registers"));
47221191
RE
258}
259
260static void
56be3814 261store_fp_register (const struct regcache *regcache, int regno)
47221191
RE
262{
263 struct fpreg inferior_fp_registers;
81b86b97
CB
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;
47221191
RE
267
268 if (ret < 0)
269 {
edefbb7c 270 warning (_("unable to fetch floating-point registers"));
47221191
RE
271 return;
272 }
273
81b86b97
CB
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)
47221191 279 {
81b86b97
CB
280 regcache->raw_collect (regno,
281 (char *) &vfp.vfp_regs[regno - ARM_D0_REGNUM]);
47221191 282 }
81b86b97
CB
283 else
284 warning (_("Invalid register number."));
47221191 285
e99b03dc 286 ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (),
9f8e0089 287 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
288
289 if (ret < 0)
edefbb7c 290 warning (_("unable to write register %d to inferior"), regno);
47221191
RE
291}
292
293static void
56be3814 294store_fp_regs (const struct regcache *regcache)
47221191 295{
81b86b97
CB
296 struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
297 if (tdep->vfp_register_count == 0)
298 return;
47221191 299
81b86b97
CB
300 struct fpreg fpregs;
301 for (int regno = 0; regno <= tdep->vfp_register_count; regno++)
34a79281 302 regcache->raw_collect
81b86b97 303 (regno + ARM_D0_REGNUM, (char *) &fpregs.fpr_vfp.vfp_regs[regno]);
47221191 304
81b86b97
CB
305 regcache->raw_collect (ARM_FPSCR_REGNUM,
306 (char *) &fpregs.fpr_vfp.vfp_fpscr);
47221191 307
81b86b97
CB
308 int ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (),
309 (PTRACE_TYPE_ARG3) &fpregs, 0);
47221191
RE
310
311 if (ret < 0)
edefbb7c 312 warning (_("unable to store floating-point registers"));
47221191
RE
313}
314
f6ac5f3d 315void
3050c6f4 316arm_netbsd_nat_target::store_registers (struct regcache *regcache, int regno)
47221191
RE
317{
318 if (regno >= 0)
319 {
320 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
56be3814 321 store_register (regcache, regno);
47221191 322 else
56be3814 323 store_fp_register (regcache, regno);
47221191
RE
324 }
325 else
326 {
56be3814
UW
327 store_regs (regcache);
328 store_fp_regs (regcache);
47221191 329 }
e7a42bc8
FN
330}
331
81b86b97
CB
332const struct target_desc *
333arm_netbsd_nat_target::read_description ()
334{
335 int flag;
336 size_t len = sizeof (flag);
337
338 if (sysctlbyname("machdep.fpu_present", &flag, &len, NULL, 0) != 0
339 || !flag)
340 return arm_read_description (ARM_FP_TYPE_NONE);
341
342 len = sizeof(flag);
343 if (sysctlbyname("machdep.neon_present", &flag, &len, NULL, 0) == 0 && flag)
344 return aarch32_read_description ();
345
346 return arm_read_description (ARM_FP_TYPE_VFPV3);
347}
348
6c265988 349void _initialize_arm_netbsd_nat ();
3e56fc4b 350void
6c265988 351_initialize_arm_netbsd_nat ()
3e56fc4b 352{
d9f719f1 353 add_inf_child_target (&the_arm_netbsd_nat_target);
3e56fc4b 354}
This page took 1.415452 seconds and 4 git commands to generate.