2011-01-07 Michael Snyder <msnyder@vmware.com>
[deliverable/binutils-gdb.git] / gdb / armnbsd-nat.c
CommitLineData
e7a42bc8 1/* Native-dependent code for BSD Unix running on ARM's, for GDB.
9f8e0089 2
9b254dd1 3 Copyright (C) 1988, 1989, 1991, 1992, 1994, 1996, 1999, 2002, 2004, 2007,
7b6bb8da 4 2008, 2009, 2010, 2011 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... */
b2cb219a 53 r_pc = gdbarch_addr_bits_remove (get_regcache_arch (regcache), 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:
0963b4bd 105 /* This is ok: we're running native... */
bf6ae464 106 inferior_registers.r_pc = gdbarch_addr_bits_remove
b2cb219a
UW
107 (get_regcache_arch (regcache),
108 inferior_registers.r_pc);
56be3814 109 regcache_raw_supply (regcache, ARM_PC_REGNUM,
23a6d369 110 (char *) &inferior_registers.r_pc);
47221191
RE
111 break;
112
113 case ARM_PS_REGNUM:
114 if (arm_apcs_32)
56be3814 115 regcache_raw_supply (regcache, ARM_PS_REGNUM,
23a6d369 116 (char *) &inferior_registers.r_cpsr);
47221191 117 else
56be3814 118 regcache_raw_supply (regcache, ARM_PS_REGNUM,
23a6d369 119 (char *) &inferior_registers.r_pc);
47221191
RE
120 break;
121
122 default:
56be3814 123 regcache_raw_supply (regcache, regno,
23a6d369 124 (char *) &inferior_registers.r[regno]);
47221191
RE
125 break;
126 }
127}
128
129static void
56be3814 130fetch_regs (struct regcache *regcache)
e7a42bc8
FN
131{
132 struct reg inferior_registers;
47221191
RE
133 int ret;
134 int regno;
135
136 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
9f8e0089 137 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
138
139 if (ret < 0)
140 {
edefbb7c 141 warning (_("unable to fetch general registers"));
47221191
RE
142 return;
143 }
144
56be3814 145 arm_supply_gregset (regcache, &inferior_registers);
47221191
RE
146}
147
148static void
56be3814 149fetch_fp_register (struct regcache *regcache, int regno)
47221191
RE
150{
151 struct fpreg inferior_fp_registers;
152 int ret;
153
154 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 155 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
156
157 if (ret < 0)
158 {
edefbb7c 159 warning (_("unable to fetch floating-point register"));
47221191
RE
160 return;
161 }
162
163 switch (regno)
164 {
165 case ARM_FPS_REGNUM:
56be3814 166 regcache_raw_supply (regcache, ARM_FPS_REGNUM,
23a6d369 167 (char *) &inferior_fp_registers.fpr_fpsr);
47221191
RE
168 break;
169
170 default:
56be3814 171 regcache_raw_supply (regcache, regno,
23a6d369 172 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
47221191
RE
173 break;
174 }
175}
176
177static void
56be3814 178fetch_fp_regs (struct regcache *regcache)
47221191
RE
179{
180 struct fpreg inferior_fp_registers;
181 int ret;
182 int regno;
183
184 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 185 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
186
187 if (ret < 0)
188 {
edefbb7c 189 warning (_("unable to fetch general registers"));
47221191
RE
190 return;
191 }
192
56be3814 193 arm_supply_fparegset (regcache, &inferior_fp_registers);
e7a42bc8
FN
194}
195
2b73aeb1 196static void
28439f5e
PA
197armnbsd_fetch_registers (struct target_ops *ops,
198 struct regcache *regcache, int regno)
47221191
RE
199{
200 if (regno >= 0)
201 {
202 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
56be3814 203 fetch_register (regcache, regno);
47221191 204 else
56be3814 205 fetch_fp_register (regcache, regno);
47221191
RE
206 }
207 else
208 {
56be3814
UW
209 fetch_regs (regcache);
210 fetch_fp_regs (regcache);
47221191
RE
211 }
212}
213
214
215static void
56be3814 216store_register (const struct regcache *regcache, int regno)
e7a42bc8 217{
b2cb219a 218 struct gdbarch *gdbarch = get_regcache_arch (regcache);
e7a42bc8 219 struct reg inferior_registers;
47221191
RE
220 int ret;
221
222 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
9f8e0089 223 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
224
225 if (ret < 0)
226 {
edefbb7c 227 warning (_("unable to fetch general registers"));
47221191
RE
228 return;
229 }
230
231 switch (regno)
232 {
233 case ARM_SP_REGNUM:
56be3814 234 regcache_raw_collect (regcache, ARM_SP_REGNUM,
822c9732 235 (char *) &inferior_registers.r_sp);
47221191
RE
236 break;
237
238 case ARM_LR_REGNUM:
56be3814 239 regcache_raw_collect (regcache, ARM_LR_REGNUM,
822c9732 240 (char *) &inferior_registers.r_lr);
47221191 241 break;
e7a42bc8 242
47221191
RE
243 case ARM_PC_REGNUM:
244 if (arm_apcs_32)
56be3814 245 regcache_raw_collect (regcache, ARM_PC_REGNUM,
822c9732 246 (char *) &inferior_registers.r_pc);
47221191
RE
247 else
248 {
249 unsigned pc_val;
e7a42bc8 250
56be3814 251 regcache_raw_collect (regcache, ARM_PC_REGNUM,
822c9732 252 (char *) &pc_val);
47221191 253
b2cb219a 254 pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
bf6ae464 255 inferior_registers.r_pc ^= gdbarch_addr_bits_remove
b2cb219a 256 (gdbarch, inferior_registers.r_pc);
47221191
RE
257 inferior_registers.r_pc |= pc_val;
258 }
259 break;
260
261 case ARM_PS_REGNUM:
262 if (arm_apcs_32)
56be3814 263 regcache_raw_collect (regcache, ARM_PS_REGNUM,
822c9732 264 (char *) &inferior_registers.r_cpsr);
47221191
RE
265 else
266 {
267 unsigned psr_val;
268
56be3814 269 regcache_raw_collect (regcache, ARM_PS_REGNUM,
822c9732 270 (char *) &psr_val);
47221191 271
b2cb219a 272 psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
bf6ae464 273 inferior_registers.r_pc = gdbarch_addr_bits_remove
b2cb219a 274 (gdbarch, inferior_registers.r_pc);
47221191
RE
275 inferior_registers.r_pc |= psr_val;
276 }
277 break;
278
279 default:
56be3814 280 regcache_raw_collect (regcache, regno,
822c9732 281 (char *) &inferior_registers.r[regno]);
47221191
RE
282 break;
283 }
284
285 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
9f8e0089 286 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
287
288 if (ret < 0)
edefbb7c 289 warning (_("unable to write register %d to inferior"), regno);
47221191
RE
290}
291
292static void
56be3814 293store_regs (const struct regcache *regcache)
47221191 294{
b2cb219a 295 struct gdbarch *gdbarch = get_regcache_arch (regcache);
47221191
RE
296 struct reg inferior_registers;
297 int ret;
298 int regno;
299
300
301 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
56be3814 302 regcache_raw_collect (regcache, regno,
822c9732 303 (char *) &inferior_registers.r[regno]);
47221191 304
56be3814 305 regcache_raw_collect (regcache, ARM_SP_REGNUM,
822c9732 306 (char *) &inferior_registers.r_sp);
56be3814 307 regcache_raw_collect (regcache, ARM_LR_REGNUM,
822c9732 308 (char *) &inferior_registers.r_lr);
47221191
RE
309
310 if (arm_apcs_32)
311 {
56be3814 312 regcache_raw_collect (regcache, ARM_PC_REGNUM,
822c9732 313 (char *) &inferior_registers.r_pc);
56be3814 314 regcache_raw_collect (regcache, ARM_PS_REGNUM,
822c9732 315 (char *) &inferior_registers.r_cpsr);
47221191
RE
316 }
317 else
318 {
319 unsigned pc_val;
320 unsigned psr_val;
321
56be3814 322 regcache_raw_collect (regcache, ARM_PC_REGNUM,
822c9732 323 (char *) &pc_val);
56be3814 324 regcache_raw_collect (regcache, ARM_PS_REGNUM,
822c9732 325 (char *) &psr_val);
47221191 326
b2cb219a
UW
327 pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
328 psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
47221191
RE
329
330 inferior_registers.r_pc = pc_val | psr_val;
331 }
332
333 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
9f8e0089 334 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
335
336 if (ret < 0)
edefbb7c 337 warning (_("unable to store general registers"));
47221191
RE
338}
339
340static void
56be3814 341store_fp_register (const struct regcache *regcache, int regno)
47221191
RE
342{
343 struct fpreg inferior_fp_registers;
344 int ret;
345
346 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 347 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
348
349 if (ret < 0)
350 {
edefbb7c 351 warning (_("unable to fetch floating-point registers"));
47221191
RE
352 return;
353 }
354
355 switch (regno)
356 {
357 case ARM_FPS_REGNUM:
56be3814 358 regcache_raw_collect (regcache, ARM_FPS_REGNUM,
822c9732 359 (char *) &inferior_fp_registers.fpr_fpsr);
47221191
RE
360 break;
361
362 default:
56be3814 363 regcache_raw_collect (regcache, regno,
822c9732 364 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
47221191
RE
365 break;
366 }
367
368 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
9f8e0089 369 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
370
371 if (ret < 0)
edefbb7c 372 warning (_("unable to write register %d to inferior"), regno);
47221191
RE
373}
374
375static void
56be3814 376store_fp_regs (const struct regcache *regcache)
47221191
RE
377{
378 struct fpreg inferior_fp_registers;
379 int ret;
380 int regno;
381
382
383 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
56be3814 384 regcache_raw_collect (regcache, regno,
822c9732 385 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
47221191 386
56be3814 387 regcache_raw_collect (regcache, ARM_FPS_REGNUM,
822c9732 388 (char *) &inferior_fp_registers.fpr_fpsr);
47221191
RE
389
390 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
9f8e0089 391 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
392
393 if (ret < 0)
edefbb7c 394 warning (_("unable to store floating-point registers"));
47221191
RE
395}
396
2b73aeb1 397static void
28439f5e
PA
398armnbsd_store_registers (struct target_ops *ops,
399 struct regcache *regcache, int regno)
47221191
RE
400{
401 if (regno >= 0)
402 {
403 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
56be3814 404 store_register (regcache, regno);
47221191 405 else
56be3814 406 store_fp_register (regcache, regno);
47221191
RE
407 }
408 else
409 {
56be3814
UW
410 store_regs (regcache);
411 store_fp_regs (regcache);
47221191 412 }
e7a42bc8
FN
413}
414
415struct md_core
416{
417 struct reg intreg;
418 struct fpreg freg;
419};
420
3e56fc4b 421static void
9eefc95f
UW
422fetch_core_registers (struct regcache *regcache,
423 char *core_reg_sect, unsigned core_reg_size,
47221191 424 int which, CORE_ADDR ignore)
e7a42bc8
FN
425{
426 struct md_core *core_reg = (struct md_core *) core_reg_sect;
3e56fc4b
RE
427 int regno;
428 CORE_ADDR r_pc;
3e56fc4b 429
9eefc95f
UW
430 arm_supply_gregset (regcache, &core_reg->intreg);
431 arm_supply_fparegset (regcache, &core_reg->freg);
b34db576 432}
3e56fc4b 433
b34db576 434static void
9eefc95f
UW
435fetch_elfcore_registers (struct regcache *regcache,
436 char *core_reg_sect, unsigned core_reg_size,
b34db576
RE
437 int which, CORE_ADDR ignore)
438{
439 struct reg gregset;
440 struct fpreg fparegset;
e7a42bc8 441
b34db576
RE
442 switch (which)
443 {
444 case 0: /* Integer registers. */
445 if (core_reg_size != sizeof (struct reg))
edefbb7c 446 warning (_("wrong size of register set in core file"));
b34db576
RE
447 else
448 {
449 /* The memcpy may be unnecessary, but we can't really be sure
450 of the alignment of the data in the core file. */
451 memcpy (&gregset, core_reg_sect, sizeof (gregset));
9eefc95f 452 arm_supply_gregset (regcache, &gregset);
b34db576
RE
453 }
454 break;
455
456 case 2:
457 if (core_reg_size != sizeof (struct fpreg))
edefbb7c 458 warning (_("wrong size of FPA register set in core file"));
b34db576
RE
459 else
460 {
461 /* The memcpy may be unnecessary, but we can't really be sure
462 of the alignment of the data in the core file. */
463 memcpy (&fparegset, core_reg_sect, sizeof (fparegset));
9eefc95f 464 arm_supply_fparegset (regcache, &fparegset);
b34db576
RE
465 }
466 break;
3e56fc4b 467
b34db576
RE
468 default:
469 /* Don't know what kind of register request this is; just ignore it. */
470 break;
471 }
e7a42bc8
FN
472}
473
3e56fc4b
RE
474static struct core_fns arm_netbsd_core_fns =
475{
476 bfd_target_unknown_flavour, /* core_flovour. */
477 default_check_format, /* check_format. */
478 default_core_sniffer, /* core_sniffer. */
479 fetch_core_registers, /* core_read_registers. */
480 NULL
481};
482
b34db576
RE
483static struct core_fns arm_netbsd_elfcore_fns =
484{
485 bfd_target_elf_flavour, /* core_flovour. */
486 default_check_format, /* check_format. */
487 default_core_sniffer, /* core_sniffer. */
488 fetch_elfcore_registers, /* core_read_registers. */
489 NULL
490};
491
3e56fc4b
RE
492void
493_initialize_arm_netbsd_nat (void)
494{
2b73aeb1
MK
495 struct target_ops *t;
496
497 t = inf_ptrace_target ();
498 t->to_fetch_registers = armnbsd_fetch_registers;
499 t->to_store_registers = armnbsd_store_registers;
500 add_target (t);
501
00e32a35
AC
502 deprecated_add_core_fns (&arm_netbsd_core_fns);
503 deprecated_add_core_fns (&arm_netbsd_elfcore_fns);
3e56fc4b 504}
This page took 0.748097 seconds and 4 git commands to generate.