e7cd23693b6736506aba9e00b90212f1d3a25d84
[deliverable/binutils-gdb.git] / gdb / arm-nbsd-nat.c
1 /* Native-dependent code for BSD Unix running on ARM's, for GDB.
2
3 Copyright (C) 1988-2020 Free Software Foundation, Inc.
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
9 the Free Software Foundation; either version 3 of the License, or
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
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 /* We define this to get types like register_t. */
21 #define _KERNTYPES
22 #include "defs.h"
23 #include "gdbcore.h"
24 #include "inferior.h"
25 #include "regcache.h"
26 #include "target.h"
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>
32
33 #include "arm-tdep.h"
34 #include "arm-nbsd-tdep.h"
35 #include "aarch32-tdep.h"
36 #include "inf-ptrace.h"
37 #include "nbsd-nat.h"
38
39 class arm_netbsd_nat_target final : public nbsd_nat_target
40 {
41 public:
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;
46 };
47
48 static arm_netbsd_nat_target the_arm_netbsd_nat_target;
49
50 static void
51 arm_supply_vfpregset (struct regcache *regcache, struct fpreg *fpregset)
52 {
53 struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
54 if (tdep->vfp_register_count == 0)
55 return;
56
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]);
60
61 regcache->raw_supply (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr);
62 }
63
64 static void
65 fetch_register (struct regcache *regcache, int regno)
66 {
67 struct reg inferior_registers;
68 int ret;
69
70 ret = ptrace (PT_GETREGS, regcache->ptid ().pid (),
71 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
72
73 if (ret < 0)
74 {
75 warning (_("unable to fetch general register"));
76 return;
77 }
78 arm_nbsd_supply_gregset (nullptr, regcache, regno, &inferior_registers,
79 sizeof (inferior_registers));
80 }
81
82 static void
83 fetch_fp_register (struct regcache *regcache, int regno)
84 {
85 struct fpreg inferior_fp_registers;
86 int ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
87 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
88
89 struct vfpreg &vfp = inferior_fp_registers.fpr_vfp;
90
91 if (ret < 0)
92 {
93 warning (_("unable to fetch floating-point register"));
94 return;
95 }
96
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)
102 {
103 regcache->raw_supply (regno,
104 (char *) &vfp.vfp_regs[regno - ARM_D0_REGNUM]);
105 }
106 else
107 warning (_("Invalid register number."));
108 }
109
110 static void
111 fetch_fp_regs (struct regcache *regcache)
112 {
113 struct fpreg inferior_fp_registers;
114 int ret;
115 int regno;
116
117 ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
118 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
119
120 if (ret < 0)
121 {
122 warning (_("unable to fetch general registers"));
123 return;
124 }
125
126 arm_supply_vfpregset (regcache, &inferior_fp_registers);
127 }
128
129 void
130 arm_netbsd_nat_target::fetch_registers (struct regcache *regcache, int regno)
131 {
132 if (regno >= 0)
133 {
134 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
135 fetch_register (regcache, regno);
136 else
137 fetch_fp_register (regcache, regno);
138 }
139 else
140 {
141 fetch_register (regcache, -1);
142 fetch_fp_regs (regcache);
143 }
144 }
145
146
147 static void
148 store_register (const struct regcache *regcache, int regno)
149 {
150 struct gdbarch *gdbarch = regcache->arch ();
151 struct reg inferior_registers;
152 int ret;
153
154 ret = ptrace (PT_GETREGS, regcache->ptid ().pid (),
155 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
156
157 if (ret < 0)
158 {
159 warning (_("unable to fetch general registers"));
160 return;
161 }
162
163 switch (regno)
164 {
165 case ARM_SP_REGNUM:
166 regcache->raw_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
167 break;
168
169 case ARM_LR_REGNUM:
170 regcache->raw_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
171 break;
172
173 case ARM_PC_REGNUM:
174 if (arm_apcs_32)
175 regcache->raw_collect (ARM_PC_REGNUM,
176 (char *) &inferior_registers.r_pc);
177 else
178 {
179 unsigned pc_val;
180
181 regcache->raw_collect (ARM_PC_REGNUM, (char *) &pc_val);
182
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;
187 }
188 break;
189
190 case ARM_PS_REGNUM:
191 if (arm_apcs_32)
192 regcache->raw_collect (ARM_PS_REGNUM,
193 (char *) &inferior_registers.r_cpsr);
194 else
195 {
196 unsigned psr_val;
197
198 regcache->raw_collect (ARM_PS_REGNUM, (char *) &psr_val);
199
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;
204 }
205 break;
206
207 default:
208 regcache->raw_collect (regno, (char *) &inferior_registers.r[regno]);
209 break;
210 }
211
212 ret = ptrace (PT_SETREGS, regcache->ptid ().pid (),
213 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
214
215 if (ret < 0)
216 warning (_("unable to write register %d to inferior"), regno);
217 }
218
219 static void
220 store_regs (const struct regcache *regcache)
221 {
222 struct gdbarch *gdbarch = regcache->arch ();
223 struct reg inferior_registers;
224 int ret;
225 int regno;
226
227
228 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
229 regcache->raw_collect (regno, (char *) &inferior_registers.r[regno]);
230
231 regcache->raw_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
232 regcache->raw_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
233
234 if (arm_apcs_32)
235 {
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);
239 }
240 else
241 {
242 unsigned pc_val;
243 unsigned psr_val;
244
245 regcache->raw_collect (ARM_PC_REGNUM, (char *) &pc_val);
246 regcache->raw_collect (ARM_PS_REGNUM, (char *) &psr_val);
247
248 pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
249 psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
250
251 inferior_registers.r_pc = pc_val | psr_val;
252 }
253
254 ret = ptrace (PT_SETREGS, regcache->ptid ().pid (),
255 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
256
257 if (ret < 0)
258 warning (_("unable to store general registers"));
259 }
260
261 static void
262 store_fp_register (const struct regcache *regcache, int regno)
263 {
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;
268
269 if (ret < 0)
270 {
271 warning (_("unable to fetch floating-point registers"));
272 return;
273 }
274
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)
280 {
281 regcache->raw_collect (regno,
282 (char *) &vfp.vfp_regs[regno - ARM_D0_REGNUM]);
283 }
284 else
285 warning (_("Invalid register number."));
286
287 ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (),
288 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
289
290 if (ret < 0)
291 warning (_("unable to write register %d to inferior"), regno);
292 }
293
294 static void
295 store_fp_regs (const struct regcache *regcache)
296 {
297 struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
298 if (tdep->vfp_register_count == 0)
299 return;
300
301 struct fpreg fpregs;
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]);
305
306 regcache->raw_collect (ARM_FPSCR_REGNUM,
307 (char *) &fpregs.fpr_vfp.vfp_fpscr);
308
309 int ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (),
310 (PTRACE_TYPE_ARG3) &fpregs, 0);
311
312 if (ret < 0)
313 warning (_("unable to store floating-point registers"));
314 }
315
316 void
317 arm_netbsd_nat_target::store_registers (struct regcache *regcache, int regno)
318 {
319 if (regno >= 0)
320 {
321 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
322 store_register (regcache, regno);
323 else
324 store_fp_register (regcache, regno);
325 }
326 else
327 {
328 store_regs (regcache);
329 store_fp_regs (regcache);
330 }
331 }
332
333 const struct target_desc *
334 arm_netbsd_nat_target::read_description ()
335 {
336 int flag;
337 size_t len = sizeof (flag);
338
339 if (sysctlbyname("machdep.fpu_present", &flag, &len, NULL, 0) != 0
340 || !flag)
341 return arm_read_description (ARM_FP_TYPE_NONE);
342
343 len = sizeof(flag);
344 if (sysctlbyname("machdep.neon_present", &flag, &len, NULL, 0) == 0 && flag)
345 return aarch32_read_description ();
346
347 return arm_read_description (ARM_FP_TYPE_VFPV3);
348 }
349
350 void _initialize_arm_netbsd_nat ();
351 void
352 _initialize_arm_netbsd_nat ()
353 {
354 add_inf_child_target (&the_arm_netbsd_nat_target);
355 }
This page took 0.039572 seconds and 3 git commands to generate.