3 /* Native-dependent code for BSD Unix running on ARM's, for GDB.
4 Copyright 1988, 1989, 1991, 1992, 1994, 1996, 1999, 2002
5 Free Software Foundation, Inc.
7 This file is part of GDB.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
26 #ifndef FETCH_INFERIOR_REGISTERS
27 #ifndef CROSS_DEBUGGER
28 #error Not FETCH_INFERIOR_REGISTERS
30 #endif /* !FETCH_INFERIOR_REGISTERS */
34 #include <sys/types.h>
35 #ifndef CROSS_DEBUGGER
36 #include <sys/ptrace.h>
37 #include <machine/reg.h>
38 #include <machine/frame.h>
44 extern int arm_apcs_32;
55 typedef struct fp_extended_precision {
56 u_int32_t fp_exponent;
57 u_int32_t fp_mantissa_hi;
58 u_int32_t fp_mantissa_lo;
59 } fp_extended_precision_t;
61 typedef struct fp_extended_precision fp_reg_t;
64 unsigned int fpr_fpsr;
70 supply_gregset (struct reg *gregset)
75 /* Integer registers. */
76 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
77 supply_register (regno, (char *) &gregset->r[regno]);
79 supply_register (ARM_SP_REGNUM, (char *) &gregset->r_sp);
80 supply_register (ARM_LR_REGNUM, (char *) &gregset->r_lr);
81 supply_register (ARM_PC_REGNUM, (char *) &gregset->r_pc);
84 supply_register (ARM_PS_REGNUM, (char *) &gregset->r_cpsr);
86 supply_register (ARM_PS_REGNUM, (char *) &gregset->r_pc);
89 /* Fill register REGNO (if it is a general-purpose register) in
90 *GREGSETPS with the value in GDB's register array. If REGNO is -1,
91 do this for all registers. */
94 fill_gregset (struct reg *gregset, int regno)
98 for (i = ARM_A1_REGNUM; i < ARM_SP_REGNUM; i++)
99 if ((regno == -1 || regno == i))
100 regcache_collect (i, &gregset->r[i]);
101 if (regno == -1 || regno == ARM_SP_REGNUM)
102 regcache_collect (ARM_SP_REGNUM, &gregset->r_sp);
103 if (regno == -1 || regno == ARM_LR_REGNUM)
104 regcache_collect (ARM_LR_REGNUM, &gregset->r_lr);
105 if (regno == -1 || regno == ARM_PC_REGNUM)
106 regcache_collect (ARM_PC_REGNUM, &gregset->r_pc);
107 if (regno == -1 || regno == ARM_PS_REGNUM)
108 regcache_collect (ARM_PS_REGNUM, &gregset->r_cpsr);
112 supply_fpregset (struct fpreg *fparegset)
116 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
118 (regno, (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]);
120 supply_register (ARM_FPS_REGNUM, (char *) &fparegset->fpr_fpsr);
124 fill_fpregset (struct fpreg *fparegset, int regno)
128 for (i = ARM_F0_REGNUM; i <= ARM_F7_REGNUM; i++)
129 if (regno == -1 || regno == i)
130 regcache_raw_supply(current_regcache, i,
131 &fparegset->fpr[i - ARM_F0_REGNUM]);
132 if (regno == -1 || regno == ARM_FPS_REGNUM)
133 regcache_raw_supply(current_regcache, ARM_FPS_REGNUM,
134 &fparegset->fpr_fpsr);
138 fetch_register (int regno)
140 struct reg inferior_registers;
141 #ifndef CROSS_DEBUGGER
144 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
145 (PTRACE_ARG3_TYPE) &inferior_registers, 0);
149 warning ("unable to fetch general register");
157 supply_register (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
161 supply_register (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
165 /* This is ok: we're running native... */
166 inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc);
167 supply_register (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc);
172 supply_register (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr);
174 supply_register (ARM_PS_REGNUM, (char *) &inferior_registers.r_pc);
178 supply_register (regno, (char *) &inferior_registers.r[regno]);
186 struct reg inferior_registers;
187 #ifndef CROSS_DEBUGGER
192 #ifndef CROSS_DEBUGGER
193 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
194 (PTRACE_ARG3_TYPE) &inferior_registers, 0);
198 warning ("unable to fetch general registers");
203 supply_gregset (&inferior_registers);
207 fetch_fp_register (int regno)
209 struct fpreg inferior_fp_registers;
210 #ifndef CROSS_DEBUGGER
213 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
214 (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
218 warning ("unable to fetch floating-point register");
226 supply_register (ARM_FPS_REGNUM,
227 (char *) &inferior_fp_registers.fpr_fpsr);
232 (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
240 struct fpreg inferior_fp_registers;
241 #ifndef CROSS_DEBUGGER
246 #ifndef CROSS_DEBUGGER
247 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
248 (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
252 warning ("unable to fetch general registers");
257 supply_fpregset (&inferior_fp_registers);
261 fetch_inferior_registers (int regno)
265 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
266 fetch_register (regno);
268 fetch_fp_register (regno);
279 store_register (int regno)
281 struct reg inferior_registers;
282 #ifndef CROSS_DEBUGGER
285 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
286 (PTRACE_ARG3_TYPE) &inferior_registers, 0);
290 warning ("unable to fetch general registers");
298 regcache_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
302 regcache_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
307 regcache_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc);
312 regcache_collect (ARM_PC_REGNUM, (char *) &pc_val);
314 pc_val = ADDR_BITS_REMOVE (pc_val);
315 inferior_registers.r_pc
316 ^= ADDR_BITS_REMOVE (inferior_registers.r_pc);
317 inferior_registers.r_pc |= pc_val;
323 regcache_collect (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr);
328 regcache_collect (ARM_PS_REGNUM, (char *) &psr_val);
330 psr_val ^= ADDR_BITS_REMOVE (psr_val);
331 inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc);
332 inferior_registers.r_pc |= psr_val;
337 regcache_collect (regno, (char *) &inferior_registers.r[regno]);
341 #ifndef CROSS_DEBUGGER
342 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
343 (PTRACE_ARG3_TYPE) &inferior_registers, 0);
346 warning ("unable to write register %d to inferior", regno);
353 struct reg inferior_registers;
358 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
359 regcache_collect (regno, (char *) &inferior_registers.r[regno]);
361 regcache_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
362 regcache_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
366 regcache_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc);
367 regcache_collect (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr);
374 regcache_collect (ARM_PC_REGNUM, (char *) &pc_val);
375 regcache_collect (ARM_PS_REGNUM, (char *) &psr_val);
377 pc_val = ADDR_BITS_REMOVE (pc_val);
378 psr_val ^= ADDR_BITS_REMOVE (psr_val);
380 inferior_registers.r_pc = pc_val | psr_val;
383 #ifndef CROSS_DEBUGGER
384 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
385 (PTRACE_ARG3_TYPE) &inferior_registers, 0);
388 warning ("unable to store general registers");
393 store_fp_register (int regno)
395 struct fpreg inferior_fp_registers;
396 #ifndef CROSS_DEBUGGER
399 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
400 (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
404 warning ("unable to fetch floating-point registers");
412 regcache_collect (ARM_FPS_REGNUM,
413 (char *) &inferior_fp_registers.fpr_fpsr);
418 (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
422 #ifndef CROSS_DEBUGGER
423 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
424 (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
427 warning ("unable to write register %d to inferior", regno);
434 struct fpreg inferior_fp_registers;
439 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
441 (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
443 regcache_collect (ARM_FPS_REGNUM, (char *) &inferior_fp_registers.fpr_fpsr);
445 #ifndef CROSS_DEBUGGER
446 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
447 (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
450 warning ("unable to store floating-point registers");
455 store_inferior_registers (int regno)
459 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
460 store_register (regno);
462 store_fp_register (regno);
479 fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
480 int which, CORE_ADDR ignore)
482 struct md_core *core_reg = (struct md_core *) core_reg_sect;
486 supply_gregset (&core_reg->intreg);
487 supply_fpregset (&core_reg->freg);
491 fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size,
492 int which, CORE_ADDR ignore)
495 struct fpreg fparegset;
499 case 0: /* Integer registers. */
500 if (core_reg_size != sizeof (struct reg))
501 warning ("wrong size of register set in core file");
504 /* The memcpy may be unnecessary, but we can't really be sure
505 of the alignment of the data in the core file. */
506 memcpy (&gregset, core_reg_sect, sizeof (gregset));
507 supply_gregset (&gregset);
512 if (core_reg_size != sizeof (struct fpreg))
513 warning ("wrong size of FPA register set in core file");
516 /* The memcpy may be unnecessary, but we can't really be sure
517 of the alignment of the data in the core file. */
518 memcpy (&fparegset, core_reg_sect, sizeof (fparegset));
519 supply_fpregset (&fparegset);
524 /* Don't know what kind of register request this is; just ignore it. */
529 static struct core_fns arm_freebsd_core_fns =
531 bfd_target_unknown_flavour, /* core_flovour. */
532 default_check_format, /* check_format. */
533 default_core_sniffer, /* core_sniffer. */
534 fetch_core_registers, /* core_read_registers. */
538 static struct core_fns arm_freebsd_elfcore_fns =
540 bfd_target_elf_flavour, /* core_flovour. */
541 default_check_format, /* check_format. */
542 default_core_sniffer, /* core_sniffer. */
543 fetch_elfcore_registers, /* core_read_registers. */
548 _initialize_arm_fbsdnat (void)
550 add_core_fns (&arm_freebsd_core_fns);
551 add_core_fns (&arm_freebsd_elfcore_fns);