*** empty log message ***
[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
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
10 the Free Software Foundation; either version 2 of the License, or
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
19 along with this program; if not, write to the Free Software
197e01b6
EZ
20 Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
e7a42bc8
FN
22
23#include "defs.h"
2b73aeb1
MK
24#include "gdbcore.h"
25#include "inferior.h"
26#include "regcache.h"
27#include "target.h"
e7a42bc8 28
2b73aeb1 29#include "gdb_string.h"
e7a42bc8
FN
30#include <sys/types.h>
31#include <sys/ptrace.h>
32#include <machine/reg.h>
33#include <machine/frame.h>
2b73aeb1
MK
34
35#include "arm-tdep.h"
36#include "inf-ptrace.h"
e7a42bc8 37
47221191
RE
38extern int arm_apcs_32;
39
b34db576 40static void
d683e2b7 41arm_supply_gregset (struct regcache *regcache, struct reg *gregset)
b34db576
RE
42{
43 int regno;
44 CORE_ADDR r_pc;
45
46 /* Integer registers. */
47 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
d683e2b7 48 regcache_raw_supply (regcache, regno, (char *) &gregset->r[regno]);
b34db576 49
d683e2b7 50 regcache_raw_supply (regcache, ARM_SP_REGNUM,
23a6d369 51 (char *) &gregset->r_sp);
d683e2b7 52 regcache_raw_supply (regcache, ARM_LR_REGNUM,
23a6d369 53 (char *) &gregset->r_lr);
b34db576 54 /* This is ok: we're running native... */
bf6ae464 55 r_pc = gdbarch_addr_bits_remove (current_gdbarch, gregset->r_pc);
d683e2b7 56 regcache_raw_supply (regcache, ARM_PC_REGNUM, (char *) &r_pc);
b34db576
RE
57
58 if (arm_apcs_32)
d683e2b7 59 regcache_raw_supply (regcache, ARM_PS_REGNUM,
23a6d369 60 (char *) &gregset->r_cpsr);
b34db576 61 else
d683e2b7 62 regcache_raw_supply (regcache, ARM_PS_REGNUM,
23a6d369 63 (char *) &gregset->r_pc);
b34db576
RE
64}
65
66static void
d683e2b7 67arm_supply_fparegset (struct regcache *regcache, struct fpreg *fparegset)
b34db576
RE
68{
69 int regno;
70
71 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
d683e2b7 72 regcache_raw_supply (regcache, regno,
23a6d369 73 (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]);
b34db576 74
d683e2b7 75 regcache_raw_supply (regcache, ARM_FPS_REGNUM,
23a6d369 76 (char *) &fparegset->fpr_fpsr);
b34db576
RE
77}
78
47221191 79static void
56be3814 80fetch_register (struct regcache *regcache, int regno)
47221191
RE
81{
82 struct reg inferior_registers;
83 int ret;
84
85 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
9f8e0089 86 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
87
88 if (ret < 0)
89 {
edefbb7c 90 warning (_("unable to fetch general register"));
47221191
RE
91 return;
92 }
93
94 switch (regno)
95 {
96 case ARM_SP_REGNUM:
56be3814 97 regcache_raw_supply (regcache, ARM_SP_REGNUM,
23a6d369 98 (char *) &inferior_registers.r_sp);
47221191
RE
99 break;
100
101 case ARM_LR_REGNUM:
56be3814 102 regcache_raw_supply (regcache, ARM_LR_REGNUM,
23a6d369 103 (char *) &inferior_registers.r_lr);
47221191
RE
104 break;
105
106 case ARM_PC_REGNUM:
107 /* This is ok: we're running native... */
bf6ae464
UW
108 inferior_registers.r_pc = gdbarch_addr_bits_remove
109 (current_gdbarch, inferior_registers.r_pc);
56be3814 110 regcache_raw_supply (regcache, ARM_PC_REGNUM,
23a6d369 111 (char *) &inferior_registers.r_pc);
47221191
RE
112 break;
113
114 case ARM_PS_REGNUM:
115 if (arm_apcs_32)
56be3814 116 regcache_raw_supply (regcache, ARM_PS_REGNUM,
23a6d369 117 (char *) &inferior_registers.r_cpsr);
47221191 118 else
56be3814 119 regcache_raw_supply (regcache, ARM_PS_REGNUM,
23a6d369 120 (char *) &inferior_registers.r_pc);
47221191
RE
121 break;
122
123 default:
56be3814 124 regcache_raw_supply (regcache, regno,
23a6d369 125 (char *) &inferior_registers.r[regno]);
47221191
RE
126 break;
127 }
128}
129
130static void
56be3814 131fetch_regs (struct regcache *regcache)
e7a42bc8
FN
132{
133 struct reg inferior_registers;
47221191
RE
134 int ret;
135 int regno;
136
137 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
9f8e0089 138 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
139
140 if (ret < 0)
141 {
edefbb7c 142 warning (_("unable to fetch general registers"));
47221191
RE
143 return;
144 }
145
56be3814 146 arm_supply_gregset (regcache, &inferior_registers);
47221191
RE
147}
148
149static void
56be3814 150fetch_fp_register (struct regcache *regcache, int regno)
47221191
RE
151{
152 struct fpreg inferior_fp_registers;
153 int ret;
154
155 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 156 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
157
158 if (ret < 0)
159 {
edefbb7c 160 warning (_("unable to fetch floating-point register"));
47221191
RE
161 return;
162 }
163
164 switch (regno)
165 {
166 case ARM_FPS_REGNUM:
56be3814 167 regcache_raw_supply (regcache, ARM_FPS_REGNUM,
23a6d369 168 (char *) &inferior_fp_registers.fpr_fpsr);
47221191
RE
169 break;
170
171 default:
56be3814 172 regcache_raw_supply (regcache, regno,
23a6d369 173 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
47221191
RE
174 break;
175 }
176}
177
178static void
56be3814 179fetch_fp_regs (struct regcache *regcache)
47221191
RE
180{
181 struct fpreg inferior_fp_registers;
182 int ret;
183 int regno;
184
185 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 186 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
187
188 if (ret < 0)
189 {
edefbb7c 190 warning (_("unable to fetch general registers"));
47221191
RE
191 return;
192 }
193
56be3814 194 arm_supply_fparegset (regcache, &inferior_fp_registers);
e7a42bc8
FN
195}
196
2b73aeb1 197static void
56be3814 198armnbsd_fetch_registers (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
FN
217{
218 struct reg inferior_registers;
47221191
RE
219 int ret;
220
221 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
9f8e0089 222 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
223
224 if (ret < 0)
225 {
edefbb7c 226 warning (_("unable to fetch general registers"));
47221191
RE
227 return;
228 }
229
230 switch (regno)
231 {
232 case ARM_SP_REGNUM:
56be3814 233 regcache_raw_collect (regcache, ARM_SP_REGNUM,
822c9732 234 (char *) &inferior_registers.r_sp);
47221191
RE
235 break;
236
237 case ARM_LR_REGNUM:
56be3814 238 regcache_raw_collect (regcache, ARM_LR_REGNUM,
822c9732 239 (char *) &inferior_registers.r_lr);
47221191 240 break;
e7a42bc8 241
47221191
RE
242 case ARM_PC_REGNUM:
243 if (arm_apcs_32)
56be3814 244 regcache_raw_collect (regcache, ARM_PC_REGNUM,
822c9732 245 (char *) &inferior_registers.r_pc);
47221191
RE
246 else
247 {
248 unsigned pc_val;
e7a42bc8 249
56be3814 250 regcache_raw_collect (regcache, ARM_PC_REGNUM,
822c9732 251 (char *) &pc_val);
47221191 252
bf6ae464
UW
253 pc_val = gdbarch_addr_bits_remove (current_gdbarch, pc_val);
254 inferior_registers.r_pc ^= gdbarch_addr_bits_remove
255 (current_gdbarch,
256 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
bf6ae464
UW
272 psr_val ^= gdbarch_addr_bits_remove (current_gdbarch, psr_val);
273 inferior_registers.r_pc = gdbarch_addr_bits_remove
274 (current_gdbarch,
275 inferior_registers.r_pc);
47221191
RE
276 inferior_registers.r_pc |= psr_val;
277 }
278 break;
279
280 default:
56be3814 281 regcache_raw_collect (regcache, regno,
822c9732 282 (char *) &inferior_registers.r[regno]);
47221191
RE
283 break;
284 }
285
286 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
9f8e0089 287 (PTRACE_TYPE_ARG3) &inferior_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_regs (const struct regcache *regcache)
47221191
RE
295{
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
bf6ae464
UW
327 pc_val = gdbarch_addr_bits_remove (current_gdbarch, pc_val);
328 psr_val ^= gdbarch_addr_bits_remove (current_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
56be3814 398armnbsd_store_registers (struct regcache *regcache, int regno)
47221191
RE
399{
400 if (regno >= 0)
401 {
402 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
56be3814 403 store_register (regcache, regno);
47221191 404 else
56be3814 405 store_fp_register (regcache, regno);
47221191
RE
406 }
407 else
408 {
56be3814
UW
409 store_regs (regcache);
410 store_fp_regs (regcache);
47221191 411 }
e7a42bc8
FN
412}
413
414struct md_core
415{
416 struct reg intreg;
417 struct fpreg freg;
418};
419
3e56fc4b 420static void
9eefc95f
UW
421fetch_core_registers (struct regcache *regcache,
422 char *core_reg_sect, unsigned core_reg_size,
47221191 423 int which, CORE_ADDR ignore)
e7a42bc8
FN
424{
425 struct md_core *core_reg = (struct md_core *) core_reg_sect;
3e56fc4b
RE
426 int regno;
427 CORE_ADDR r_pc;
3e56fc4b 428
9eefc95f
UW
429 arm_supply_gregset (regcache, &core_reg->intreg);
430 arm_supply_fparegset (regcache, &core_reg->freg);
b34db576 431}
3e56fc4b 432
b34db576 433static void
9eefc95f
UW
434fetch_elfcore_registers (struct regcache *regcache,
435 char *core_reg_sect, unsigned core_reg_size,
b34db576
RE
436 int which, CORE_ADDR ignore)
437{
438 struct reg gregset;
439 struct fpreg fparegset;
e7a42bc8 440
b34db576
RE
441 switch (which)
442 {
443 case 0: /* Integer registers. */
444 if (core_reg_size != sizeof (struct reg))
edefbb7c 445 warning (_("wrong size of register set in core file"));
b34db576
RE
446 else
447 {
448 /* The memcpy may be unnecessary, but we can't really be sure
449 of the alignment of the data in the core file. */
450 memcpy (&gregset, core_reg_sect, sizeof (gregset));
9eefc95f 451 arm_supply_gregset (regcache, &gregset);
b34db576
RE
452 }
453 break;
454
455 case 2:
456 if (core_reg_size != sizeof (struct fpreg))
edefbb7c 457 warning (_("wrong size of FPA register set in core file"));
b34db576
RE
458 else
459 {
460 /* The memcpy may be unnecessary, but we can't really be sure
461 of the alignment of the data in the core file. */
462 memcpy (&fparegset, core_reg_sect, sizeof (fparegset));
9eefc95f 463 arm_supply_fparegset (regcache, &fparegset);
b34db576
RE
464 }
465 break;
3e56fc4b 466
b34db576
RE
467 default:
468 /* Don't know what kind of register request this is; just ignore it. */
469 break;
470 }
e7a42bc8
FN
471}
472
3e56fc4b
RE
473static struct core_fns arm_netbsd_core_fns =
474{
475 bfd_target_unknown_flavour, /* core_flovour. */
476 default_check_format, /* check_format. */
477 default_core_sniffer, /* core_sniffer. */
478 fetch_core_registers, /* core_read_registers. */
479 NULL
480};
481
b34db576
RE
482static struct core_fns arm_netbsd_elfcore_fns =
483{
484 bfd_target_elf_flavour, /* core_flovour. */
485 default_check_format, /* check_format. */
486 default_core_sniffer, /* core_sniffer. */
487 fetch_elfcore_registers, /* core_read_registers. */
488 NULL
489};
490
3e56fc4b
RE
491void
492_initialize_arm_netbsd_nat (void)
493{
2b73aeb1
MK
494 struct target_ops *t;
495
496 t = inf_ptrace_target ();
497 t->to_fetch_registers = armnbsd_fetch_registers;
498 t->to_store_registers = armnbsd_store_registers;
499 add_target (t);
500
00e32a35
AC
501 deprecated_add_core_fns (&arm_netbsd_core_fns);
502 deprecated_add_core_fns (&arm_netbsd_elfcore_fns);
3e56fc4b 503}
This page took 0.370902 seconds and 4 git commands to generate.