]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/armnbsd-nat.c
Switch the license of all .c files to GPLv3.
[thirdparty/binutils-gdb.git] / gdb / armnbsd-nat.c
CommitLineData
e7a42bc8 1/* Native-dependent code for BSD Unix running on ARM's, for GDB.
9f8e0089 2
6aba47ca 3 Copyright (C) 1988, 1989, 1991, 1992, 1994, 1996, 1999, 2002, 2004, 2007
34e8f22d 4 Free Software Foundation, Inc.
e7a42bc8
FN
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
e7a42bc8
FN
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
e7a42bc8
FN
20
21#include "defs.h"
2b73aeb1
MK
22#include "gdbcore.h"
23#include "inferior.h"
24#include "regcache.h"
25#include "target.h"
e7a42bc8 26
2b73aeb1 27#include "gdb_string.h"
e7a42bc8
FN
28#include <sys/types.h>
29#include <sys/ptrace.h>
30#include <machine/reg.h>
31#include <machine/frame.h>
2b73aeb1
MK
32
33#include "arm-tdep.h"
34#include "inf-ptrace.h"
e7a42bc8 35
47221191
RE
36extern int arm_apcs_32;
37
b34db576 38static void
d683e2b7 39arm_supply_gregset (struct regcache *regcache, struct reg *gregset)
b34db576
RE
40{
41 int regno;
42 CORE_ADDR r_pc;
43
44 /* Integer registers. */
45 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
d683e2b7 46 regcache_raw_supply (regcache, regno, (char *) &gregset->r[regno]);
b34db576 47
d683e2b7 48 regcache_raw_supply (regcache, ARM_SP_REGNUM,
23a6d369 49 (char *) &gregset->r_sp);
d683e2b7 50 regcache_raw_supply (regcache, ARM_LR_REGNUM,
23a6d369 51 (char *) &gregset->r_lr);
b34db576 52 /* This is ok: we're running native... */
bf6ae464 53 r_pc = gdbarch_addr_bits_remove (current_gdbarch, gregset->r_pc);
d683e2b7 54 regcache_raw_supply (regcache, ARM_PC_REGNUM, (char *) &r_pc);
b34db576
RE
55
56 if (arm_apcs_32)
d683e2b7 57 regcache_raw_supply (regcache, ARM_PS_REGNUM,
23a6d369 58 (char *) &gregset->r_cpsr);
b34db576 59 else
d683e2b7 60 regcache_raw_supply (regcache, ARM_PS_REGNUM,
23a6d369 61 (char *) &gregset->r_pc);
b34db576
RE
62}
63
64static void
d683e2b7 65arm_supply_fparegset (struct regcache *regcache, struct fpreg *fparegset)
b34db576
RE
66{
67 int regno;
68
69 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
d683e2b7 70 regcache_raw_supply (regcache, regno,
23a6d369 71 (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]);
b34db576 72
d683e2b7 73 regcache_raw_supply (regcache, ARM_FPS_REGNUM,
23a6d369 74 (char *) &fparegset->fpr_fpsr);
b34db576
RE
75}
76
47221191 77static void
56be3814 78fetch_register (struct regcache *regcache, int regno)
47221191
RE
79{
80 struct reg inferior_registers;
81 int ret;
82
83 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
9f8e0089 84 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
85
86 if (ret < 0)
87 {
edefbb7c 88 warning (_("unable to fetch general register"));
47221191
RE
89 return;
90 }
91
92 switch (regno)
93 {
94 case ARM_SP_REGNUM:
56be3814 95 regcache_raw_supply (regcache, ARM_SP_REGNUM,
23a6d369 96 (char *) &inferior_registers.r_sp);
47221191
RE
97 break;
98
99 case ARM_LR_REGNUM:
56be3814 100 regcache_raw_supply (regcache, ARM_LR_REGNUM,
23a6d369 101 (char *) &inferior_registers.r_lr);
47221191
RE
102 break;
103
104 case ARM_PC_REGNUM:
105 /* This is ok: we're running native... */
bf6ae464
UW
106 inferior_registers.r_pc = gdbarch_addr_bits_remove
107 (current_gdbarch, inferior_registers.r_pc);
56be3814 108 regcache_raw_supply (regcache, ARM_PC_REGNUM,
23a6d369 109 (char *) &inferior_registers.r_pc);
47221191
RE
110 break;
111
112 case ARM_PS_REGNUM:
113 if (arm_apcs_32)
56be3814 114 regcache_raw_supply (regcache, ARM_PS_REGNUM,
23a6d369 115 (char *) &inferior_registers.r_cpsr);
47221191 116 else
56be3814 117 regcache_raw_supply (regcache, ARM_PS_REGNUM,
23a6d369 118 (char *) &inferior_registers.r_pc);
47221191
RE
119 break;
120
121 default:
56be3814 122 regcache_raw_supply (regcache, regno,
23a6d369 123 (char *) &inferior_registers.r[regno]);
47221191
RE
124 break;
125 }
126}
127
128static void
56be3814 129fetch_regs (struct regcache *regcache)
e7a42bc8
FN
130{
131 struct reg inferior_registers;
47221191
RE
132 int ret;
133 int regno;
134
135 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
9f8e0089 136 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
137
138 if (ret < 0)
139 {
edefbb7c 140 warning (_("unable to fetch general registers"));
47221191
RE
141 return;
142 }
143
56be3814 144 arm_supply_gregset (regcache, &inferior_registers);
47221191
RE
145}
146
147static void
56be3814 148fetch_fp_register (struct regcache *regcache, int regno)
47221191
RE
149{
150 struct fpreg inferior_fp_registers;
151 int ret;
152
153 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 154 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
155
156 if (ret < 0)
157 {
edefbb7c 158 warning (_("unable to fetch floating-point register"));
47221191
RE
159 return;
160 }
161
162 switch (regno)
163 {
164 case ARM_FPS_REGNUM:
56be3814 165 regcache_raw_supply (regcache, ARM_FPS_REGNUM,
23a6d369 166 (char *) &inferior_fp_registers.fpr_fpsr);
47221191
RE
167 break;
168
169 default:
56be3814 170 regcache_raw_supply (regcache, regno,
23a6d369 171 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
47221191
RE
172 break;
173 }
174}
175
176static void
56be3814 177fetch_fp_regs (struct regcache *regcache)
47221191
RE
178{
179 struct fpreg inferior_fp_registers;
180 int ret;
181 int regno;
182
183 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 184 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
185
186 if (ret < 0)
187 {
edefbb7c 188 warning (_("unable to fetch general registers"));
47221191
RE
189 return;
190 }
191
56be3814 192 arm_supply_fparegset (regcache, &inferior_fp_registers);
e7a42bc8
FN
193}
194
2b73aeb1 195static void
56be3814 196armnbsd_fetch_registers (struct regcache *regcache, int regno)
47221191
RE
197{
198 if (regno >= 0)
199 {
200 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
56be3814 201 fetch_register (regcache, regno);
47221191 202 else
56be3814 203 fetch_fp_register (regcache, regno);
47221191
RE
204 }
205 else
206 {
56be3814
UW
207 fetch_regs (regcache);
208 fetch_fp_regs (regcache);
47221191
RE
209 }
210}
211
212
213static void
56be3814 214store_register (const struct regcache *regcache, int regno)
e7a42bc8
FN
215{
216 struct reg inferior_registers;
47221191
RE
217 int ret;
218
219 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
9f8e0089 220 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
221
222 if (ret < 0)
223 {
edefbb7c 224 warning (_("unable to fetch general registers"));
47221191
RE
225 return;
226 }
227
228 switch (regno)
229 {
230 case ARM_SP_REGNUM:
56be3814 231 regcache_raw_collect (regcache, ARM_SP_REGNUM,
822c9732 232 (char *) &inferior_registers.r_sp);
47221191
RE
233 break;
234
235 case ARM_LR_REGNUM:
56be3814 236 regcache_raw_collect (regcache, ARM_LR_REGNUM,
822c9732 237 (char *) &inferior_registers.r_lr);
47221191 238 break;
e7a42bc8 239
47221191
RE
240 case ARM_PC_REGNUM:
241 if (arm_apcs_32)
56be3814 242 regcache_raw_collect (regcache, ARM_PC_REGNUM,
822c9732 243 (char *) &inferior_registers.r_pc);
47221191
RE
244 else
245 {
246 unsigned pc_val;
e7a42bc8 247
56be3814 248 regcache_raw_collect (regcache, ARM_PC_REGNUM,
822c9732 249 (char *) &pc_val);
47221191 250
bf6ae464
UW
251 pc_val = gdbarch_addr_bits_remove (current_gdbarch, pc_val);
252 inferior_registers.r_pc ^= gdbarch_addr_bits_remove
253 (current_gdbarch,
254 inferior_registers.r_pc);
47221191
RE
255 inferior_registers.r_pc |= pc_val;
256 }
257 break;
258
259 case ARM_PS_REGNUM:
260 if (arm_apcs_32)
56be3814 261 regcache_raw_collect (regcache, ARM_PS_REGNUM,
822c9732 262 (char *) &inferior_registers.r_cpsr);
47221191
RE
263 else
264 {
265 unsigned psr_val;
266
56be3814 267 regcache_raw_collect (regcache, ARM_PS_REGNUM,
822c9732 268 (char *) &psr_val);
47221191 269
bf6ae464
UW
270 psr_val ^= gdbarch_addr_bits_remove (current_gdbarch, psr_val);
271 inferior_registers.r_pc = gdbarch_addr_bits_remove
272 (current_gdbarch,
273 inferior_registers.r_pc);
47221191
RE
274 inferior_registers.r_pc |= psr_val;
275 }
276 break;
277
278 default:
56be3814 279 regcache_raw_collect (regcache, regno,
822c9732 280 (char *) &inferior_registers.r[regno]);
47221191
RE
281 break;
282 }
283
284 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
9f8e0089 285 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
286
287 if (ret < 0)
edefbb7c 288 warning (_("unable to write register %d to inferior"), regno);
47221191
RE
289}
290
291static void
56be3814 292store_regs (const struct regcache *regcache)
47221191
RE
293{
294 struct reg inferior_registers;
295 int ret;
296 int regno;
297
298
299 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
56be3814 300 regcache_raw_collect (regcache, regno,
822c9732 301 (char *) &inferior_registers.r[regno]);
47221191 302
56be3814 303 regcache_raw_collect (regcache, ARM_SP_REGNUM,
822c9732 304 (char *) &inferior_registers.r_sp);
56be3814 305 regcache_raw_collect (regcache, ARM_LR_REGNUM,
822c9732 306 (char *) &inferior_registers.r_lr);
47221191
RE
307
308 if (arm_apcs_32)
309 {
56be3814 310 regcache_raw_collect (regcache, ARM_PC_REGNUM,
822c9732 311 (char *) &inferior_registers.r_pc);
56be3814 312 regcache_raw_collect (regcache, ARM_PS_REGNUM,
822c9732 313 (char *) &inferior_registers.r_cpsr);
47221191
RE
314 }
315 else
316 {
317 unsigned pc_val;
318 unsigned psr_val;
319
56be3814 320 regcache_raw_collect (regcache, ARM_PC_REGNUM,
822c9732 321 (char *) &pc_val);
56be3814 322 regcache_raw_collect (regcache, ARM_PS_REGNUM,
822c9732 323 (char *) &psr_val);
47221191 324
bf6ae464
UW
325 pc_val = gdbarch_addr_bits_remove (current_gdbarch, pc_val);
326 psr_val ^= gdbarch_addr_bits_remove (current_gdbarch, psr_val);
47221191
RE
327
328 inferior_registers.r_pc = pc_val | psr_val;
329 }
330
331 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
9f8e0089 332 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
333
334 if (ret < 0)
edefbb7c 335 warning (_("unable to store general registers"));
47221191
RE
336}
337
338static void
56be3814 339store_fp_register (const struct regcache *regcache, int regno)
47221191
RE
340{
341 struct fpreg inferior_fp_registers;
342 int ret;
343
344 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 345 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
346
347 if (ret < 0)
348 {
edefbb7c 349 warning (_("unable to fetch floating-point registers"));
47221191
RE
350 return;
351 }
352
353 switch (regno)
354 {
355 case ARM_FPS_REGNUM:
56be3814 356 regcache_raw_collect (regcache, ARM_FPS_REGNUM,
822c9732 357 (char *) &inferior_fp_registers.fpr_fpsr);
47221191
RE
358 break;
359
360 default:
56be3814 361 regcache_raw_collect (regcache, regno,
822c9732 362 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
47221191
RE
363 break;
364 }
365
366 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
9f8e0089 367 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
368
369 if (ret < 0)
edefbb7c 370 warning (_("unable to write register %d to inferior"), regno);
47221191
RE
371}
372
373static void
56be3814 374store_fp_regs (const struct regcache *regcache)
47221191
RE
375{
376 struct fpreg inferior_fp_registers;
377 int ret;
378 int regno;
379
380
381 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
56be3814 382 regcache_raw_collect (regcache, regno,
822c9732 383 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
47221191 384
56be3814 385 regcache_raw_collect (regcache, ARM_FPS_REGNUM,
822c9732 386 (char *) &inferior_fp_registers.fpr_fpsr);
47221191
RE
387
388 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
9f8e0089 389 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
390
391 if (ret < 0)
edefbb7c 392 warning (_("unable to store floating-point registers"));
47221191
RE
393}
394
2b73aeb1 395static void
56be3814 396armnbsd_store_registers (struct regcache *regcache, int regno)
47221191
RE
397{
398 if (regno >= 0)
399 {
400 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
56be3814 401 store_register (regcache, regno);
47221191 402 else
56be3814 403 store_fp_register (regcache, regno);
47221191
RE
404 }
405 else
406 {
56be3814
UW
407 store_regs (regcache);
408 store_fp_regs (regcache);
47221191 409 }
e7a42bc8
FN
410}
411
412struct md_core
413{
414 struct reg intreg;
415 struct fpreg freg;
416};
417
3e56fc4b 418static void
9eefc95f
UW
419fetch_core_registers (struct regcache *regcache,
420 char *core_reg_sect, unsigned core_reg_size,
47221191 421 int which, CORE_ADDR ignore)
e7a42bc8
FN
422{
423 struct md_core *core_reg = (struct md_core *) core_reg_sect;
3e56fc4b
RE
424 int regno;
425 CORE_ADDR r_pc;
3e56fc4b 426
9eefc95f
UW
427 arm_supply_gregset (regcache, &core_reg->intreg);
428 arm_supply_fparegset (regcache, &core_reg->freg);
b34db576 429}
3e56fc4b 430
b34db576 431static void
9eefc95f
UW
432fetch_elfcore_registers (struct regcache *regcache,
433 char *core_reg_sect, unsigned core_reg_size,
b34db576
RE
434 int which, CORE_ADDR ignore)
435{
436 struct reg gregset;
437 struct fpreg fparegset;
e7a42bc8 438
b34db576
RE
439 switch (which)
440 {
441 case 0: /* Integer registers. */
442 if (core_reg_size != sizeof (struct reg))
edefbb7c 443 warning (_("wrong size of register set in core file"));
b34db576
RE
444 else
445 {
446 /* The memcpy may be unnecessary, but we can't really be sure
447 of the alignment of the data in the core file. */
448 memcpy (&gregset, core_reg_sect, sizeof (gregset));
9eefc95f 449 arm_supply_gregset (regcache, &gregset);
b34db576
RE
450 }
451 break;
452
453 case 2:
454 if (core_reg_size != sizeof (struct fpreg))
edefbb7c 455 warning (_("wrong size of FPA register set in core file"));
b34db576
RE
456 else
457 {
458 /* The memcpy may be unnecessary, but we can't really be sure
459 of the alignment of the data in the core file. */
460 memcpy (&fparegset, core_reg_sect, sizeof (fparegset));
9eefc95f 461 arm_supply_fparegset (regcache, &fparegset);
b34db576
RE
462 }
463 break;
3e56fc4b 464
b34db576
RE
465 default:
466 /* Don't know what kind of register request this is; just ignore it. */
467 break;
468 }
e7a42bc8
FN
469}
470
3e56fc4b
RE
471static struct core_fns arm_netbsd_core_fns =
472{
473 bfd_target_unknown_flavour, /* core_flovour. */
474 default_check_format, /* check_format. */
475 default_core_sniffer, /* core_sniffer. */
476 fetch_core_registers, /* core_read_registers. */
477 NULL
478};
479
b34db576
RE
480static struct core_fns arm_netbsd_elfcore_fns =
481{
482 bfd_target_elf_flavour, /* core_flovour. */
483 default_check_format, /* check_format. */
484 default_core_sniffer, /* core_sniffer. */
485 fetch_elfcore_registers, /* core_read_registers. */
486 NULL
487};
488
3e56fc4b
RE
489void
490_initialize_arm_netbsd_nat (void)
491{
2b73aeb1
MK
492 struct target_ops *t;
493
494 t = inf_ptrace_target ();
495 t->to_fetch_registers = armnbsd_fetch_registers;
496 t->to_store_registers = armnbsd_store_registers;
497 add_target (t);
498
00e32a35
AC
499 deprecated_add_core_fns (&arm_netbsd_core_fns);
500 deprecated_add_core_fns (&arm_netbsd_elfcore_fns);
3e56fc4b 501}