1/* Native-dependent code for BSD Unix running on ARM's, for GDB.
2
3   Copyright (C) 1988, 1989, 1991, 1992, 1994, 1996, 1999, 2002, 2004, 2007,
4   2008, 2009, 2010, 2011 Free Software Foundation, Inc.
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 3 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, see <http://www.gnu.org/licenses/>.  */
20
21#include "defs.h"
22#include "gdbcore.h"
23#include "inferior.h"
24#include "regcache.h"
25#include "target.h"
26
27#include "nbsd-nat.h"
28#include "gdb_string.h"
29#include <sys/types.h>
30#include <sys/ptrace.h>
31#include <machine/reg.h>
32#include <machine/frame.h>
33
34/* Support for debugging kernel virtual memory images.  */
35#include <machine/pcb.h>
36
37#include "arm-tdep.h"
38#include "inf-ptrace.h"
39#include "bsd-kvm.h"
40
41#ifndef HAVE_GREGSET_T
42typedef struct reg gregset_t;
43#endif
44
45#ifndef HAVE_FPREGSET_T
46typedef struct fpreg fpregset_t;
47#endif
48
49#include "gregset.h"
50
51extern int arm_apcs_32;
52
53static int
54armnbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
55{
56  struct switchframe sf;
57
58  /* The following is true for NetBSD/arm32 in 5.0 and after:
59
60     The pcb contains r8-r13 (sp) at the point of context switch in
61     cpu_switchto() or call of dumpsys(). At that point we have a
62     stack frame as described by `struct switchframe', which for
63     NetBSD/arm32 has the following layout:
64
65	r4   ascending.
66	r5        |
67	r6        |
68	r7       \|/
69	old sp
70	pc
71
72     we reconstruct the register state as it would look when we just
73     returned from cpu_switchto() or dumpsys().  */
74
75  if (!arm_apcs_32)
76    return 0;
77
78  /* The stack pointer shouldn't be zero.  */
79  if (pcb->pcb_un.un_32.pcb32_sp == 0)
80    return 0;
81
82  read_memory (pcb->pcb_un.un_32.pcb32_sp, (gdb_byte *) &sf, sizeof sf);
83
84  regcache_raw_supply (regcache, ARM_PC_REGNUM, &sf.sf_pc);
85  regcache_raw_supply (regcache, ARM_SP_REGNUM, &pcb->pcb_un.un_32.pcb32_sp);
86  regcache_raw_supply (regcache, 12, &pcb->pcb_un.un_32.pcb32_r12);
87  regcache_raw_supply (regcache, 11, &pcb->pcb_un.un_32.pcb32_r11);
88  regcache_raw_supply (regcache, 10, &pcb->pcb_un.un_32.pcb32_r10);
89  regcache_raw_supply (regcache, 9, &pcb->pcb_un.un_32.pcb32_r9);
90  regcache_raw_supply (regcache, 8, &pcb->pcb_un.un_32.pcb32_r8);
91  regcache_raw_supply (regcache, 7, &sf.sf_r7);
92  regcache_raw_supply (regcache, 6, &sf.sf_r6);
93  regcache_raw_supply (regcache, 5, &sf.sf_r5);
94  regcache_raw_supply (regcache, 4, &sf.sf_r4);
95
96  return 1;
97}
98
99static void
100arm_supply_gregset (struct regcache *regcache, struct reg *gregset)
101{
102  int regno;
103  CORE_ADDR r_pc;
104
105  /* Integer registers.  */
106  for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
107    regcache_raw_supply (regcache, regno, (char *) &gregset->r[regno]);
108
109  regcache_raw_supply (regcache, ARM_SP_REGNUM,
110		       (char *) &gregset->r_sp);
111  regcache_raw_supply (regcache, ARM_LR_REGNUM,
112		       (char *) &gregset->r_lr);
113  /* This is ok: we're running native...  */
114  r_pc = gdbarch_addr_bits_remove (get_regcache_arch (regcache), gregset->r_pc);
115  regcache_raw_supply (regcache, ARM_PC_REGNUM, (char *) &r_pc);
116
117  if (arm_apcs_32)
118    regcache_raw_supply (regcache, ARM_PS_REGNUM,
119			 (char *) &gregset->r_cpsr);
120  else
121    regcache_raw_supply (regcache, ARM_PS_REGNUM,
122			 (char *) &gregset->r_pc);
123}
124
125static void
126arm_supply_fparegset (struct regcache *regcache, struct fpreg *fparegset)
127{
128  int regno;
129
130  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
131    regcache_raw_supply (regcache, regno,
132			 (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]);
133
134  regcache_raw_supply (regcache, ARM_FPS_REGNUM,
135		       (char *) &fparegset->fpr_fpsr);
136}
137
138void
139fill_gregset (const struct regcache *regcache, gregset_t *gregsetp, int regno)
140{
141  if (-1 == regno)
142    {
143      int regnum;
144      for (regnum = ARM_A1_REGNUM; regnum < ARM_SP_REGNUM; regnum++)
145	regcache_raw_collect (regcache, regnum, (char *) &gregsetp->r[regnum]);
146    }
147  else if (regno >= ARM_A1_REGNUM && regno < ARM_SP_REGNUM)
148    regcache_raw_collect (regcache, regno, (char *) &gregsetp->r[regno]);
149
150  if (ARM_SP_REGNUM == regno || -1 == regno)
151    regcache_raw_collect (regcache, ARM_SP_REGNUM, (char *) &gregsetp->r_sp);
152
153  if (ARM_LR_REGNUM == regno || -1 == regno)
154    regcache_raw_collect (regcache, ARM_LR_REGNUM, (char *) &gregsetp->r_lr);
155
156  if (ARM_PC_REGNUM == regno || -1 == regno)
157    regcache_raw_collect (regcache, ARM_PC_REGNUM, (char *) &gregsetp->r_pc);
158
159  if (ARM_PS_REGNUM == regno || -1 == regno)
160    {
161      if (arm_apcs_32)
162	regcache_raw_collect (regcache, ARM_PS_REGNUM, (char *) &gregsetp->r_cpsr);
163      else
164	regcache_raw_collect (regcache, ARM_PS_REGNUM, (char *) &gregsetp->r_pc);
165    }
166 }
167
168void
169fill_fpregset (const struct regcache *regcache, fpregset_t *fpregsetp, int regno)
170{
171  if (-1 == regno)
172    {
173       int regnum;
174       for (regnum = ARM_F0_REGNUM; regnum <= ARM_F7_REGNUM; regnum++)
175         regcache_raw_collect(regcache, regnum, (char *) &fpregsetp->fpr[regnum - ARM_F0_REGNUM]);
176    }
177  else if (regno >= ARM_F0_REGNUM && regno <= ARM_F7_REGNUM)
178    regcache_raw_collect(regcache, regno, (char *) &fpregsetp->fpr[regno - ARM_F0_REGNUM]);
179
180  if (ARM_FPS_REGNUM == regno || -1 == regno)
181    regcache_raw_collect (regcache, ARM_FPS_REGNUM, (char *) &fpregsetp->fpr_fpsr);
182}
183
184void
185supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
186{
187  arm_supply_gregset (regcache, (struct reg *)gregsetp);
188}
189
190void
191supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
192{
193  arm_supply_fparegset (regcache, (struct fpreg *)fpregsetp);
194}
195
196static void
197fetch_register (struct regcache *regcache, int regno)
198{
199  struct reg inferior_registers;
200  int ret;
201
202  ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
203		(PTRACE_TYPE_ARG3) &inferior_registers, TIDGET (inferior_ptid));
204
205  if (ret < 0)
206    {
207      warning (_("unable to fetch general register"));
208      return;
209    }
210
211  switch (regno)
212    {
213    case ARM_SP_REGNUM:
214      regcache_raw_supply (regcache, ARM_SP_REGNUM,
215			   (char *) &inferior_registers.r_sp);
216      break;
217
218    case ARM_LR_REGNUM:
219      regcache_raw_supply (regcache, ARM_LR_REGNUM,
220			   (char *) &inferior_registers.r_lr);
221      break;
222
223    case ARM_PC_REGNUM:
224      /* This is ok: we're running native...  */
225      inferior_registers.r_pc = gdbarch_addr_bits_remove
226				  (get_regcache_arch (regcache),
227				   inferior_registers.r_pc);
228      regcache_raw_supply (regcache, ARM_PC_REGNUM,
229			   (char *) &inferior_registers.r_pc);
230      break;
231
232    case ARM_PS_REGNUM:
233      if (arm_apcs_32)
234	regcache_raw_supply (regcache, ARM_PS_REGNUM,
235			     (char *) &inferior_registers.r_cpsr);
236      else
237	regcache_raw_supply (regcache, ARM_PS_REGNUM,
238			     (char *) &inferior_registers.r_pc);
239      break;
240
241    default:
242      regcache_raw_supply (regcache, regno,
243			   (char *) &inferior_registers.r[regno]);
244      break;
245    }
246}
247
248static void
249fetch_regs (struct regcache *regcache)
250{
251  struct reg inferior_registers;
252  int ret;
253  int regno;
254
255  ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
256		(PTRACE_TYPE_ARG3) &inferior_registers, TIDGET (inferior_ptid));
257
258  if (ret < 0)
259    {
260      warning (_("unable to fetch general registers"));
261      return;
262    }
263
264  arm_supply_gregset (regcache, &inferior_registers);
265}
266
267static void
268fetch_fp_register (struct regcache *regcache, int regno)
269{
270  struct fpreg inferior_fp_registers;
271  int ret;
272
273  ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
274		(PTRACE_TYPE_ARG3) &inferior_fp_registers, TIDGET (inferior_ptid));
275
276  if (ret < 0)
277    {
278      warning (_("unable to fetch floating-point register"));
279      return;
280    }
281
282  switch (regno)
283    {
284    case ARM_FPS_REGNUM:
285      regcache_raw_supply (regcache, ARM_FPS_REGNUM,
286			   (char *) &inferior_fp_registers.fpr_fpsr);
287      break;
288
289    default:
290      regcache_raw_supply (regcache, regno,
291			   (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
292      break;
293    }
294}
295
296static void
297fetch_fp_regs (struct regcache *regcache)
298{
299  struct fpreg inferior_fp_registers;
300  int ret;
301  int regno;
302
303  ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
304		(PTRACE_TYPE_ARG3) &inferior_fp_registers, TIDGET (inferior_ptid));
305
306  if (ret < 0)
307    {
308      warning (_("unable to fetch general registers"));
309      return;
310    }
311
312  arm_supply_fparegset (regcache, &inferior_fp_registers);
313}
314
315static void
316armnbsd_fetch_registers (struct target_ops *ops,
317			 struct regcache *regcache, int regno)
318{
319  if (regno >= 0)
320    {
321      if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
322	fetch_register (regcache, regno);
323      else
324	fetch_fp_register (regcache, regno);
325    }
326  else
327    {
328      fetch_regs (regcache);
329      fetch_fp_regs (regcache);
330    }
331}
332
333
334static void
335store_register (const struct regcache *regcache, int regno)
336{
337  struct gdbarch *gdbarch = get_regcache_arch (regcache);
338  struct reg inferior_registers;
339  int ret;
340
341  ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
342		(PTRACE_TYPE_ARG3) &inferior_registers, TIDGET (inferior_ptid));
343
344  if (ret < 0)
345    {
346      warning (_("unable to fetch general registers"));
347      return;
348    }
349
350  switch (regno)
351    {
352    case ARM_SP_REGNUM:
353      regcache_raw_collect (regcache, ARM_SP_REGNUM,
354			    (char *) &inferior_registers.r_sp);
355      break;
356
357    case ARM_LR_REGNUM:
358      regcache_raw_collect (regcache, ARM_LR_REGNUM,
359			    (char *) &inferior_registers.r_lr);
360      break;
361
362    case ARM_PC_REGNUM:
363      if (arm_apcs_32)
364	regcache_raw_collect (regcache, ARM_PC_REGNUM,
365			      (char *) &inferior_registers.r_pc);
366      else
367	{
368	  unsigned pc_val;
369
370	  regcache_raw_collect (regcache, ARM_PC_REGNUM,
371				(char *) &pc_val);
372
373	  pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
374	  inferior_registers.r_pc ^= gdbarch_addr_bits_remove
375				       (gdbarch, inferior_registers.r_pc);
376	  inferior_registers.r_pc |= pc_val;
377	}
378      break;
379
380    case ARM_PS_REGNUM:
381      if (arm_apcs_32)
382	regcache_raw_collect (regcache, ARM_PS_REGNUM,
383			      (char *) &inferior_registers.r_cpsr);
384      else
385	{
386	  unsigned psr_val;
387
388	  regcache_raw_collect (regcache, ARM_PS_REGNUM,
389				(char *) &psr_val);
390
391	  psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
392	  inferior_registers.r_pc = gdbarch_addr_bits_remove
393				      (gdbarch, inferior_registers.r_pc);
394	  inferior_registers.r_pc |= psr_val;
395	}
396      break;
397
398    default:
399      regcache_raw_collect (regcache, regno,
400			    (char *) &inferior_registers.r[regno]);
401      break;
402    }
403
404  ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
405		(PTRACE_TYPE_ARG3) &inferior_registers, TIDGET (inferior_ptid));
406
407  if (ret < 0)
408    warning (_("unable to write register %d to inferior"), regno);
409}
410
411static void
412store_regs (const struct regcache *regcache)
413{
414  struct gdbarch *gdbarch = get_regcache_arch (regcache);
415  struct reg inferior_registers;
416  int ret;
417  int regno;
418
419
420  for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
421    regcache_raw_collect (regcache, regno,
422			  (char *) &inferior_registers.r[regno]);
423
424  regcache_raw_collect (regcache, ARM_SP_REGNUM,
425			(char *) &inferior_registers.r_sp);
426  regcache_raw_collect (regcache, ARM_LR_REGNUM,
427			(char *) &inferior_registers.r_lr);
428
429  if (arm_apcs_32)
430    {
431      regcache_raw_collect (regcache, ARM_PC_REGNUM,
432			    (char *) &inferior_registers.r_pc);
433      regcache_raw_collect (regcache, ARM_PS_REGNUM,
434			    (char *) &inferior_registers.r_cpsr);
435    }
436  else
437    {
438      unsigned pc_val;
439      unsigned psr_val;
440
441      regcache_raw_collect (regcache, ARM_PC_REGNUM,
442			    (char *) &pc_val);
443      regcache_raw_collect (regcache, ARM_PS_REGNUM,
444			    (char *) &psr_val);
445
446      pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
447      psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
448
449      inferior_registers.r_pc = pc_val | psr_val;
450    }
451
452  ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
453		(PTRACE_TYPE_ARG3) &inferior_registers, TIDGET (inferior_ptid));
454
455  if (ret < 0)
456    warning (_("unable to store general registers"));
457}
458
459static void
460store_fp_register (const struct regcache *regcache, int regno)
461{
462  struct fpreg inferior_fp_registers;
463  int ret;
464
465  ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
466		(PTRACE_TYPE_ARG3) &inferior_fp_registers, TIDGET (inferior_ptid));
467
468  if (ret < 0)
469    {
470      warning (_("unable to fetch floating-point registers"));
471      return;
472    }
473
474  switch (regno)
475    {
476    case ARM_FPS_REGNUM:
477      regcache_raw_collect (regcache, ARM_FPS_REGNUM,
478			    (char *) &inferior_fp_registers.fpr_fpsr);
479      break;
480
481    default:
482      regcache_raw_collect (regcache, regno,
483			    (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
484      break;
485    }
486
487  ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
488		(PTRACE_TYPE_ARG3) &inferior_fp_registers, TIDGET (inferior_ptid));
489
490  if (ret < 0)
491    warning (_("unable to write register %d to inferior"), regno);
492}
493
494static void
495store_fp_regs (const struct regcache *regcache)
496{
497  struct fpreg inferior_fp_registers;
498  int ret;
499  int regno;
500
501
502  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
503    regcache_raw_collect (regcache, regno,
504			  (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
505
506  regcache_raw_collect (regcache, ARM_FPS_REGNUM,
507			(char *) &inferior_fp_registers.fpr_fpsr);
508
509  ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
510		(PTRACE_TYPE_ARG3) &inferior_fp_registers, TIDGET (inferior_ptid));
511
512  if (ret < 0)
513    warning (_("unable to store floating-point registers"));
514}
515
516static void
517armnbsd_store_registers (struct target_ops *ops,
518			 struct regcache *regcache, int regno)
519{
520  if (regno >= 0)
521    {
522      if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
523	store_register (regcache, regno);
524      else
525	store_fp_register (regcache, regno);
526    }
527  else
528    {
529      store_regs (regcache);
530      store_fp_regs (regcache);
531    }
532}
533
534struct md_core
535{
536  struct reg intreg;
537  struct fpreg freg;
538};
539
540static void
541fetch_core_registers (struct regcache *regcache,
542		      char *core_reg_sect, unsigned core_reg_size,
543		      int which, CORE_ADDR ignore)
544{
545  struct md_core *core_reg = (struct md_core *) core_reg_sect;
546  int regno;
547  CORE_ADDR r_pc;
548
549  arm_supply_gregset (regcache, &core_reg->intreg);
550  arm_supply_fparegset (regcache, &core_reg->freg);
551}
552
553static void
554fetch_elfcore_registers (struct regcache *regcache,
555			 char *core_reg_sect, unsigned core_reg_size,
556			 int which, CORE_ADDR ignore)
557{
558  struct reg gregset;
559  struct fpreg fparegset;
560
561  switch (which)
562    {
563    case 0:	/* Integer registers.  */
564      if (core_reg_size != sizeof (struct reg))
565	warning (_("wrong size of register set in core file"));
566      else
567	{
568	  /* The memcpy may be unnecessary, but we can't really be sure
569	     of the alignment of the data in the core file.  */
570	  memcpy (&gregset, core_reg_sect, sizeof (gregset));
571	  arm_supply_gregset (regcache, &gregset);
572	}
573      break;
574
575    case 2:
576      if (core_reg_size != sizeof (struct fpreg))
577	warning (_("wrong size of FPA register set in core file"));
578      else
579	{
580	  /* The memcpy may be unnecessary, but we can't really be sure
581	     of the alignment of the data in the core file.  */
582	  memcpy (&fparegset, core_reg_sect, sizeof (fparegset));
583	  arm_supply_fparegset (regcache, &fparegset);
584	}
585      break;
586
587    default:
588      /* Don't know what kind of register request this is; just ignore it.  */
589      break;
590    }
591}
592
593static struct core_fns arm_netbsd_core_fns =
594{
595  bfd_target_unknown_flavour,		/* core_flovour.  */
596  default_check_format,			/* check_format.  */
597  default_core_sniffer,			/* core_sniffer.  */
598  fetch_core_registers,			/* core_read_registers.  */
599  NULL
600};
601
602static struct core_fns arm_netbsd_elfcore_fns =
603{
604  bfd_target_elf_flavour,		/* core_flovour.  */
605  default_check_format,			/* check_format.  */
606  default_core_sniffer,			/* core_sniffer.  */
607  fetch_elfcore_registers,		/* core_read_registers.  */
608  NULL
609};
610
611void
612_initialize_arm_netbsd_nat (void)
613{
614  struct target_ops *t;
615
616  t = inf_ptrace_target ();
617  t->to_fetch_registers = armnbsd_fetch_registers;
618  t->to_store_registers = armnbsd_store_registers;
619  t->to_pid_to_exec_file = nbsd_pid_to_exec_file;
620  add_target (t);
621
622  /* Support debugging kernel virtual memory images.  */
623  bsd_kvm_add_target (armnbsd_supply_pcb);
624
625  deprecated_add_core_fns (&arm_netbsd_core_fns);
626  deprecated_add_core_fns (&arm_netbsd_elfcore_fns);
627}
628