No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / gdb6 / gdb / armnbsd-nat.c
blob76561c5f5d91c884f4ff41866cdf0715fbb231a6
1 /* Native-dependent code for BSD Unix running on ARM's, for GDB.
3 Copyright (C) 1988, 1989, 1991, 1992, 1994, 1996, 1999, 2002, 2004
4 Free Software Foundation, Inc.
6 This file is part of GDB.
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.
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.
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
20 Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
23 #include "defs.h"
24 #include "gdbcore.h"
25 #include "inferior.h"
26 #include "regcache.h"
27 #include "target.h"
29 #include "gdb_string.h"
30 #include <sys/types.h>
31 #include <sys/ptrace.h>
32 #include <machine/reg.h>
33 #include <machine/frame.h>
35 /* Support for debugging kernel virtual memory images. */
36 #include <machine/pcb.h>
38 #include "arm-tdep.h"
39 #include "inf-ptrace.h"
40 #include "bsd-kvm.h"
42 #ifndef HAVE_GREGSET_T
43 typedef struct reg gregset_t;
44 #endif
46 #ifndef HAVE_FPREGSET_T
47 typedef struct fpreg fpregset_t;
48 #endif
50 #include "gregset.h"
52 extern int arm_apcs_32;
54 static int
55 armnbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
57 struct switchframe sf;
59 /* The following is true for NetBSD/arm32 in 5.0 and after:
61 The pcb contains r8-r13 (sp) at the point of context switch in
62 cpu_switchto() or call of dumpsys(). At that point we have a
63 stack frame as described by `struct switchframe', which for
64 NetBSD/arm32 has the following layout:
66 r4 ascending.
67 r5 |
68 r6 |
69 r7 \|/
70 old sp
73 we reconstruct the register state as it would look when we just
74 returned from cpu_switchto() or dumpsys(). */
76 if (!arm_apcs_32)
77 return 0;
79 /* The stack pointer shouldn't be zero. */
80 if (pcb->pcb_un.un_32.pcb32_sp == 0)
81 return 0;
83 read_memory (pcb->pcb_un.un_32.pcb32_sp, (gdb_byte *) &sf, sizeof sf);
85 regcache_raw_supply (regcache, ARM_PC_REGNUM, &sf.sf_pc);
86 regcache_raw_supply (regcache, ARM_SP_REGNUM, &pcb->pcb_un.un_32.pcb32_sp);
87 regcache_raw_supply (regcache, 12, &pcb->pcb_un.un_32.pcb32_r12);
88 regcache_raw_supply (regcache, 11, &pcb->pcb_un.un_32.pcb32_r11);
89 regcache_raw_supply (regcache, 10, &pcb->pcb_un.un_32.pcb32_r10);
90 regcache_raw_supply (regcache, 9, &pcb->pcb_un.un_32.pcb32_r9);
91 regcache_raw_supply (regcache, 8, &pcb->pcb_un.un_32.pcb32_r8);
92 regcache_raw_supply (regcache, 7, &sf.sf_r7);
93 regcache_raw_supply (regcache, 6, &sf.sf_r6);
94 regcache_raw_supply (regcache, 5, &sf.sf_r5);
95 regcache_raw_supply (regcache, 4, &sf.sf_r4);
97 return 1;
100 void
101 supply_gregset (gregset_t *gregset)
103 int regno;
104 CORE_ADDR r_pc;
106 /* Integer registers. */
107 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
108 regcache_raw_supply (current_regcache, regno, (char *) &gregset->r[regno]);
110 regcache_raw_supply (current_regcache, ARM_SP_REGNUM,
111 (char *) &gregset->r_sp);
112 regcache_raw_supply (current_regcache, ARM_LR_REGNUM,
113 (char *) &gregset->r_lr);
114 /* This is ok: we're running native... */
115 r_pc = ADDR_BITS_REMOVE (gregset->r_pc);
116 regcache_raw_supply (current_regcache, ARM_PC_REGNUM, (char *) &r_pc);
118 if (arm_apcs_32)
119 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
120 (char *) &gregset->r_cpsr);
121 else
122 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
123 (char *) &gregset->r_pc);
126 void
127 supply_fpregset (fpregset_t *fpregset)
129 int regno;
131 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
132 regcache_raw_supply (current_regcache, regno,
133 (char *) &fpregset->fpr[regno - ARM_F0_REGNUM]);
135 regcache_raw_supply (current_regcache, ARM_FPS_REGNUM,
136 (char *) &fpregset->fpr_fpsr);
139 void
140 fill_gregset (gregset_t *gregsetp, int regno)
142 if (-1 == regno)
144 int regnum;
145 for (regnum = ARM_A1_REGNUM; regnum < ARM_SP_REGNUM; regnum++)
146 regcache_raw_collect (current_regcache, regnum, (char *) &gregsetp->r[regnum]);
148 else if (regno >= ARM_A1_REGNUM && regno < ARM_SP_REGNUM)
149 regcache_raw_collect (current_regcache, regno, (char *) &gregsetp->r[regno]);
151 if (ARM_SP_REGNUM == regno || -1 == regno)
152 regcache_raw_collect (current_regcache, ARM_SP_REGNUM, (char *) &gregsetp->r_sp);
154 if (ARM_LR_REGNUM == regno || -1 == regno)
155 regcache_raw_collect (current_regcache, ARM_LR_REGNUM, (char *) &gregsetp->r_lr);
157 if (ARM_PC_REGNUM == regno || -1 == regno)
158 regcache_raw_collect (current_regcache, ARM_PC_REGNUM, (char *) &gregsetp->r_pc);
160 if (ARM_PS_REGNUM == regno || -1 == regno)
162 if (arm_apcs_32)
163 regcache_raw_collect (current_regcache, ARM_PS_REGNUM, (char *) &gregsetp->r_cpsr);
164 else
165 regcache_raw_collect (current_regcache, ARM_PS_REGNUM, (char *) &gregsetp->r_pc);
169 void
170 fill_fpregset (fpregset_t *fpregsetp, int regno)
172 if (-1 == regno)
174 int regnum;
175 for (regnum = ARM_F0_REGNUM; regnum <= ARM_F7_REGNUM; regnum++)
176 regcache_raw_collect(current_regcache, regnum, (char *) &fpregsetp->fpr[regnum - ARM_F0_REGNUM]);
178 else if (regno >= ARM_F0_REGNUM && regno <= ARM_F7_REGNUM)
179 regcache_raw_collect(current_regcache, regno, (char *) &fpregsetp->fpr[regno - ARM_F0_REGNUM]);
181 if (ARM_FPS_REGNUM == regno || -1 == regno)
182 regcache_raw_collect (current_regcache, ARM_FPS_REGNUM, (char *) &fpregsetp->fpr_fpsr);
186 static void
187 fetch_register (int regno)
189 struct reg inferior_registers;
190 int ret;
192 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
193 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
195 if (ret < 0)
197 warning (_("unable to fetch general register"));
198 return;
201 switch (regno)
203 case ARM_SP_REGNUM:
204 regcache_raw_supply (current_regcache, ARM_SP_REGNUM,
205 (char *) &inferior_registers.r_sp);
206 break;
208 case ARM_LR_REGNUM:
209 regcache_raw_supply (current_regcache, ARM_LR_REGNUM,
210 (char *) &inferior_registers.r_lr);
211 break;
213 case ARM_PC_REGNUM:
214 /* This is ok: we're running native... */
215 inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc);
216 regcache_raw_supply (current_regcache, ARM_PC_REGNUM,
217 (char *) &inferior_registers.r_pc);
218 break;
220 case ARM_PS_REGNUM:
221 if (arm_apcs_32)
222 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
223 (char *) &inferior_registers.r_cpsr);
224 else
225 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
226 (char *) &inferior_registers.r_pc);
227 break;
229 default:
230 regcache_raw_supply (current_regcache, regno,
231 (char *) &inferior_registers.r[regno]);
232 break;
236 static void
237 fetch_regs (void)
239 struct reg inferior_registers;
240 int ret;
241 int regno;
243 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
244 (PTRACE_TYPE_ARG3) &inferior_registers, TIDGET (inferior_ptid));
246 if (ret < 0)
248 warning (_("unable to fetch general registers"));
249 return;
252 supply_gregset (&inferior_registers);
255 static void
256 fetch_fp_register (int regno)
258 struct fpreg inferior_fp_registers;
259 int ret;
261 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
262 (PTRACE_TYPE_ARG3) &inferior_fp_registers, TIDGET (inferior_ptid));
264 if (ret < 0)
266 warning (_("unable to fetch floating-point register"));
267 return;
270 switch (regno)
272 case ARM_FPS_REGNUM:
273 regcache_raw_supply (current_regcache, ARM_FPS_REGNUM,
274 (char *) &inferior_fp_registers.fpr_fpsr);
275 break;
277 default:
278 regcache_raw_supply (current_regcache, regno,
279 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
280 break;
284 static void
285 fetch_fp_regs (void)
287 struct fpreg inferior_fp_registers;
288 int ret;
289 int regno;
291 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
292 (PTRACE_TYPE_ARG3) &inferior_fp_registers, TIDGET (inferior_ptid));
294 if (ret < 0)
296 warning (_("unable to fetch general registers"));
297 return;
300 supply_fpregset (&inferior_fp_registers);
303 static void
304 armnbsd_fetch_registers (int regno)
306 if (regno >= 0)
308 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
309 fetch_register (regno);
310 else
311 fetch_fp_register (regno);
313 else
315 fetch_regs ();
316 fetch_fp_regs ();
321 static void
322 store_register (int regno)
324 struct reg inferior_registers;
325 int ret;
327 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
328 (PTRACE_TYPE_ARG3) &inferior_registers, TIDGET (inferior_ptid));
330 if (ret < 0)
332 warning (_("unable to fetch general registers"));
333 return;
336 switch (regno)
338 case ARM_SP_REGNUM:
339 regcache_raw_collect (current_regcache, ARM_SP_REGNUM,
340 (char *) &inferior_registers.r_sp);
341 break;
343 case ARM_LR_REGNUM:
344 regcache_raw_collect (current_regcache, ARM_LR_REGNUM,
345 (char *) &inferior_registers.r_lr);
346 break;
348 case ARM_PC_REGNUM:
349 if (arm_apcs_32)
350 regcache_raw_collect (current_regcache, ARM_PC_REGNUM,
351 (char *) &inferior_registers.r_pc);
352 else
354 unsigned pc_val;
356 regcache_raw_collect (current_regcache, ARM_PC_REGNUM,
357 (char *) &pc_val);
359 pc_val = ADDR_BITS_REMOVE (pc_val);
360 inferior_registers.r_pc
361 ^= ADDR_BITS_REMOVE (inferior_registers.r_pc);
362 inferior_registers.r_pc |= pc_val;
364 break;
366 case ARM_PS_REGNUM:
367 if (arm_apcs_32)
368 regcache_raw_collect (current_regcache, ARM_PS_REGNUM,
369 (char *) &inferior_registers.r_cpsr);
370 else
372 unsigned psr_val;
374 regcache_raw_collect (current_regcache, ARM_PS_REGNUM,
375 (char *) &psr_val);
377 psr_val ^= ADDR_BITS_REMOVE (psr_val);
378 inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc);
379 inferior_registers.r_pc |= psr_val;
381 break;
383 default:
384 regcache_raw_collect (current_regcache, regno,
385 (char *) &inferior_registers.r[regno]);
386 break;
389 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
390 (PTRACE_TYPE_ARG3) &inferior_registers, TIDGET (inferior_ptid));
392 if (ret < 0)
393 warning (_("unable to write register %d to inferior"), regno);
396 static void
397 store_regs (void)
399 struct reg inferior_registers;
400 int ret;
401 int regno;
404 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
405 regcache_raw_collect (current_regcache, regno,
406 (char *) &inferior_registers.r[regno]);
408 regcache_raw_collect (current_regcache, ARM_SP_REGNUM,
409 (char *) &inferior_registers.r_sp);
410 regcache_raw_collect (current_regcache, ARM_LR_REGNUM,
411 (char *) &inferior_registers.r_lr);
413 if (arm_apcs_32)
415 regcache_raw_collect (current_regcache, ARM_PC_REGNUM,
416 (char *) &inferior_registers.r_pc);
417 regcache_raw_collect (current_regcache, ARM_PS_REGNUM,
418 (char *) &inferior_registers.r_cpsr);
420 else
422 unsigned pc_val;
423 unsigned psr_val;
425 regcache_raw_collect (current_regcache, ARM_PC_REGNUM,
426 (char *) &pc_val);
427 regcache_raw_collect (current_regcache, ARM_PS_REGNUM,
428 (char *) &psr_val);
430 pc_val = ADDR_BITS_REMOVE (pc_val);
431 psr_val ^= ADDR_BITS_REMOVE (psr_val);
433 inferior_registers.r_pc = pc_val | psr_val;
436 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
437 (PTRACE_TYPE_ARG3) &inferior_registers, TIDGET (inferior_ptid));
439 if (ret < 0)
440 warning (_("unable to store general registers"));
443 static void
444 store_fp_register (int regno)
446 struct fpreg inferior_fp_registers;
447 int ret;
449 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
450 (PTRACE_TYPE_ARG3) &inferior_fp_registers, TIDGET (inferior_ptid));
452 if (ret < 0)
454 warning (_("unable to fetch floating-point registers"));
455 return;
458 switch (regno)
460 case ARM_FPS_REGNUM:
461 regcache_raw_collect (current_regcache, ARM_FPS_REGNUM,
462 (char *) &inferior_fp_registers.fpr_fpsr);
463 break;
465 default:
466 regcache_raw_collect (current_regcache, regno,
467 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
468 break;
471 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
472 (PTRACE_TYPE_ARG3) &inferior_fp_registers, TIDGET (inferior_ptid));
474 if (ret < 0)
475 warning (_("unable to write register %d to inferior"), regno);
478 static void
479 store_fp_regs (void)
481 struct fpreg inferior_fp_registers;
482 int ret;
483 int regno;
486 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
487 regcache_raw_collect (current_regcache, regno,
488 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
490 regcache_raw_collect (current_regcache, ARM_FPS_REGNUM,
491 (char *) &inferior_fp_registers.fpr_fpsr);
493 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
494 (PTRACE_TYPE_ARG3) &inferior_fp_registers, TIDGET (inferior_ptid));
496 if (ret < 0)
497 warning (_("unable to store floating-point registers"));
500 static void
501 armnbsd_store_registers (int regno)
503 if (regno >= 0)
505 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
506 store_register (regno);
507 else
508 store_fp_register (regno);
510 else
512 store_regs ();
513 store_fp_regs ();
517 struct md_core
519 struct reg intreg;
520 struct fpreg freg;
523 static void
524 fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
525 int which, CORE_ADDR ignore)
527 struct md_core *core_reg = (struct md_core *) core_reg_sect;
528 int regno;
529 CORE_ADDR r_pc;
531 supply_gregset (&core_reg->intreg);
532 supply_fpregset (&core_reg->freg);
535 static void
536 fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size,
537 int which, CORE_ADDR ignore)
539 struct reg gregset;
540 struct fpreg fpregset;
542 switch (which)
544 case 0: /* Integer registers. */
545 if (core_reg_size != sizeof (struct reg))
546 warning (_("wrong size of register set in core file"));
547 else
549 /* The memcpy may be unnecessary, but we can't really be sure
550 of the alignment of the data in the core file. */
551 memcpy (&gregset, core_reg_sect, sizeof (gregset));
552 supply_gregset (&gregset);
554 break;
556 case 2:
557 if (core_reg_size != sizeof (struct fpreg))
558 warning (_("wrong size of FPA register set in core file"));
559 else
561 /* The memcpy may be unnecessary, but we can't really be sure
562 of the alignment of the data in the core file. */
563 memcpy (&fpregset, core_reg_sect, sizeof (fpregset));
564 supply_fpregset (&fpregset);
566 break;
568 default:
569 /* Don't know what kind of register request this is; just ignore it. */
570 break;
574 static struct core_fns arm_netbsd_core_fns =
576 bfd_target_unknown_flavour, /* core_flovour. */
577 default_check_format, /* check_format. */
578 default_core_sniffer, /* core_sniffer. */
579 fetch_core_registers, /* core_read_registers. */
580 NULL
583 static struct core_fns arm_netbsd_elfcore_fns =
585 bfd_target_elf_flavour, /* core_flovour. */
586 default_check_format, /* check_format. */
587 default_core_sniffer, /* core_sniffer. */
588 fetch_elfcore_registers, /* core_read_registers. */
589 NULL
592 void
593 _initialize_arm_netbsd_nat (void)
595 struct target_ops *t;
597 t = inf_ptrace_target ();
598 t->to_fetch_registers = armnbsd_fetch_registers;
599 t->to_store_registers = armnbsd_store_registers;
600 add_target (t);
602 /* Support debugging kernel virtual memory images. */
603 bsd_kvm_add_target (armnbsd_supply_pcb);
605 deprecated_add_core_fns (&arm_netbsd_core_fns);
606 deprecated_add_core_fns (&arm_netbsd_elfcore_fns);