198944Sobrien/* Native-dependent code for BSD Unix running on ARM's, for GDB.
298944Sobrien   Copyright 1988, 1989, 1991, 1992, 1994, 1996, 1999, 2002
398944Sobrien   Free Software Foundation, Inc.
498944Sobrien
598944Sobrien   This file is part of GDB.
698944Sobrien
798944Sobrien   This program is free software; you can redistribute it and/or modify
898944Sobrien   it under the terms of the GNU General Public License as published by
998944Sobrien   the Free Software Foundation; either version 2 of the License, or
1098944Sobrien   (at your option) any later version.
1198944Sobrien
1298944Sobrien   This program is distributed in the hope that it will be useful,
1398944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1498944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1598944Sobrien   GNU General Public License for more details.
1698944Sobrien
1798944Sobrien   You should have received a copy of the GNU General Public License
1898944Sobrien   along with this program; if not, write to the Free Software
1998944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
2098944Sobrien   Boston, MA 02111-1307, USA.  */
2198944Sobrien
2298944Sobrien#include "defs.h"
2398944Sobrien
2498944Sobrien#ifndef FETCH_INFERIOR_REGISTERS
2598944Sobrien#error Not FETCH_INFERIOR_REGISTERS
2698944Sobrien#endif /* !FETCH_INFERIOR_REGISTERS */
2798944Sobrien
2898944Sobrien#include "arm-tdep.h"
2998944Sobrien
3098944Sobrien#include <sys/types.h>
3198944Sobrien#include <sys/ptrace.h>
3298944Sobrien#include <machine/reg.h>
3398944Sobrien#include <machine/frame.h>
3498944Sobrien#include "inferior.h"
3598944Sobrien#include "regcache.h"
3698944Sobrien#include "gdbcore.h"
3798944Sobrien
3898944Sobrienextern int arm_apcs_32;
3998944Sobrien
4098944Sobrienstatic void
4198944Sobriensupply_gregset (struct reg *gregset)
4298944Sobrien{
4398944Sobrien  int regno;
4498944Sobrien  CORE_ADDR r_pc;
4598944Sobrien
4698944Sobrien  /* Integer registers.  */
4798944Sobrien  for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
4898944Sobrien    supply_register (regno, (char *) &gregset->r[regno]);
4998944Sobrien
5098944Sobrien  supply_register (ARM_SP_REGNUM, (char *) &gregset->r_sp);
5198944Sobrien  supply_register (ARM_LR_REGNUM, (char *) &gregset->r_lr);
5298944Sobrien  /* This is ok: we're running native...  */
5398944Sobrien  r_pc = ADDR_BITS_REMOVE (gregset->r_pc);
5498944Sobrien  supply_register (ARM_PC_REGNUM, (char *) &r_pc);
5598944Sobrien
5698944Sobrien  if (arm_apcs_32)
5798944Sobrien    supply_register (ARM_PS_REGNUM, (char *) &gregset->r_cpsr);
5898944Sobrien  else
5998944Sobrien    supply_register (ARM_PS_REGNUM, (char *) &gregset->r_pc);
6098944Sobrien}
6198944Sobrien
6298944Sobrienstatic void
6398944Sobriensupply_fparegset (struct fpreg *fparegset)
6498944Sobrien{
6598944Sobrien  int regno;
6698944Sobrien
6798944Sobrien  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
6898944Sobrien    supply_register
6998944Sobrien      (regno, (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]);
7098944Sobrien
7198944Sobrien  supply_register (ARM_FPS_REGNUM, (char *) &fparegset->fpr_fpsr);
7298944Sobrien}
7398944Sobrien
7498944Sobrienstatic void
7598944Sobrienfetch_register (int regno)
7698944Sobrien{
7798944Sobrien  struct reg inferior_registers;
7898944Sobrien  int ret;
7998944Sobrien
8098944Sobrien  ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
8198944Sobrien		(PTRACE_ARG3_TYPE) &inferior_registers, 0);
8298944Sobrien
8398944Sobrien  if (ret < 0)
8498944Sobrien    {
8598944Sobrien      warning ("unable to fetch general register");
8698944Sobrien      return;
8798944Sobrien    }
8898944Sobrien
8998944Sobrien  switch (regno)
9098944Sobrien    {
9198944Sobrien    case ARM_SP_REGNUM:
9298944Sobrien      supply_register (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
9398944Sobrien      break;
9498944Sobrien
9598944Sobrien    case ARM_LR_REGNUM:
9698944Sobrien      supply_register (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
9798944Sobrien      break;
9898944Sobrien
9998944Sobrien    case ARM_PC_REGNUM:
10098944Sobrien      /* This is ok: we're running native... */
10198944Sobrien      inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc);
10298944Sobrien      supply_register (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc);
10398944Sobrien      break;
10498944Sobrien
10598944Sobrien    case ARM_PS_REGNUM:
10698944Sobrien      if (arm_apcs_32)
10798944Sobrien	supply_register (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr);
10898944Sobrien      else
10998944Sobrien	supply_register (ARM_PS_REGNUM, (char *) &inferior_registers.r_pc);
11098944Sobrien      break;
11198944Sobrien
11298944Sobrien    default:
11398944Sobrien      supply_register (regno, (char *) &inferior_registers.r[regno]);
11498944Sobrien      break;
11598944Sobrien    }
11698944Sobrien}
11798944Sobrien
11898944Sobrienstatic void
11998944Sobrienfetch_regs (void)
12098944Sobrien{
12198944Sobrien  struct reg inferior_registers;
12298944Sobrien  int ret;
12398944Sobrien  int regno;
12498944Sobrien
12598944Sobrien  ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
12698944Sobrien		(PTRACE_ARG3_TYPE) &inferior_registers, 0);
12798944Sobrien
12898944Sobrien  if (ret < 0)
12998944Sobrien    {
13098944Sobrien      warning ("unable to fetch general registers");
13198944Sobrien      return;
13298944Sobrien    }
13398944Sobrien
13498944Sobrien  supply_gregset (&inferior_registers);
13598944Sobrien}
13698944Sobrien
13798944Sobrienstatic void
13898944Sobrienfetch_fp_register (int regno)
13998944Sobrien{
14098944Sobrien  struct fpreg inferior_fp_registers;
14198944Sobrien  int ret;
14298944Sobrien
14398944Sobrien  ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
14498944Sobrien		(PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
14598944Sobrien
14698944Sobrien  if (ret < 0)
14798944Sobrien    {
14898944Sobrien      warning ("unable to fetch floating-point register");
14998944Sobrien      return;
15098944Sobrien    }
15198944Sobrien
15298944Sobrien  switch (regno)
15398944Sobrien    {
15498944Sobrien    case ARM_FPS_REGNUM:
15598944Sobrien      supply_register (ARM_FPS_REGNUM,
15698944Sobrien		       (char *) &inferior_fp_registers.fpr_fpsr);
15798944Sobrien      break;
15898944Sobrien
15998944Sobrien    default:
16098944Sobrien      supply_register
16198944Sobrien	(regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
16298944Sobrien      break;
16398944Sobrien    }
16498944Sobrien}
16598944Sobrien
16698944Sobrienstatic void
16798944Sobrienfetch_fp_regs (void)
16898944Sobrien{
16998944Sobrien  struct fpreg inferior_fp_registers;
17098944Sobrien  int ret;
17198944Sobrien  int regno;
17298944Sobrien
17398944Sobrien  ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
17498944Sobrien		(PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
17598944Sobrien
17698944Sobrien  if (ret < 0)
17798944Sobrien    {
17898944Sobrien      warning ("unable to fetch general registers");
17998944Sobrien      return;
18098944Sobrien    }
18198944Sobrien
18298944Sobrien  supply_fparegset (&inferior_fp_registers);
18398944Sobrien}
18498944Sobrien
18598944Sobrienvoid
18698944Sobrienfetch_inferior_registers (int regno)
18798944Sobrien{
18898944Sobrien  if (regno >= 0)
18998944Sobrien    {
19098944Sobrien      if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
19198944Sobrien	fetch_register (regno);
19298944Sobrien      else
19398944Sobrien	fetch_fp_register (regno);
19498944Sobrien    }
19598944Sobrien  else
19698944Sobrien    {
19798944Sobrien      fetch_regs ();
19898944Sobrien      fetch_fp_regs ();
19998944Sobrien    }
20098944Sobrien}
20198944Sobrien
20298944Sobrien
20398944Sobrienstatic void
20498944Sobrienstore_register (int regno)
20598944Sobrien{
20698944Sobrien  struct reg inferior_registers;
20798944Sobrien  int ret;
20898944Sobrien
20998944Sobrien  ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
21098944Sobrien		(PTRACE_ARG3_TYPE) &inferior_registers, 0);
21198944Sobrien
21298944Sobrien  if (ret < 0)
21398944Sobrien    {
21498944Sobrien      warning ("unable to fetch general registers");
21598944Sobrien      return;
21698944Sobrien    }
21798944Sobrien
21898944Sobrien  switch (regno)
21998944Sobrien    {
22098944Sobrien    case ARM_SP_REGNUM:
22198944Sobrien      regcache_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
22298944Sobrien      break;
22398944Sobrien
22498944Sobrien    case ARM_LR_REGNUM:
22598944Sobrien      regcache_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
22698944Sobrien      break;
22798944Sobrien
22898944Sobrien    case ARM_PC_REGNUM:
22998944Sobrien      if (arm_apcs_32)
23098944Sobrien	regcache_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc);
23198944Sobrien      else
23298944Sobrien	{
23398944Sobrien	  unsigned pc_val;
23498944Sobrien
23598944Sobrien	  regcache_collect (ARM_PC_REGNUM, (char *) &pc_val);
23698944Sobrien
23798944Sobrien	  pc_val = ADDR_BITS_REMOVE (pc_val);
23898944Sobrien	  inferior_registers.r_pc
23998944Sobrien	    ^= ADDR_BITS_REMOVE (inferior_registers.r_pc);
24098944Sobrien	  inferior_registers.r_pc |= pc_val;
24198944Sobrien	}
24298944Sobrien      break;
24398944Sobrien
24498944Sobrien    case ARM_PS_REGNUM:
24598944Sobrien      if (arm_apcs_32)
24698944Sobrien	regcache_collect (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr);
24798944Sobrien      else
24898944Sobrien	{
24998944Sobrien	  unsigned psr_val;
25098944Sobrien
25198944Sobrien	  regcache_collect (ARM_PS_REGNUM, (char *) &psr_val);
25298944Sobrien
25398944Sobrien	  psr_val ^= ADDR_BITS_REMOVE (psr_val);
25498944Sobrien	  inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc);
25598944Sobrien	  inferior_registers.r_pc |= psr_val;
25698944Sobrien	}
25798944Sobrien      break;
25898944Sobrien
25998944Sobrien    default:
26098944Sobrien      regcache_collect (regno, (char *) &inferior_registers.r[regno]);
26198944Sobrien      break;
26298944Sobrien    }
26398944Sobrien
26498944Sobrien  ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
26598944Sobrien		(PTRACE_ARG3_TYPE) &inferior_registers, 0);
26698944Sobrien
26798944Sobrien  if (ret < 0)
26898944Sobrien    warning ("unable to write register %d to inferior", regno);
26998944Sobrien}
27098944Sobrien
27198944Sobrienstatic void
27298944Sobrienstore_regs (void)
27398944Sobrien{
27498944Sobrien  struct reg inferior_registers;
27598944Sobrien  int ret;
27698944Sobrien  int regno;
27798944Sobrien
27898944Sobrien
27998944Sobrien  for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
28098944Sobrien    regcache_collect (regno, (char *) &inferior_registers.r[regno]);
28198944Sobrien
28298944Sobrien  regcache_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
28398944Sobrien  regcache_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
28498944Sobrien
28598944Sobrien  if (arm_apcs_32)
28698944Sobrien    {
28798944Sobrien      regcache_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc);
28898944Sobrien      regcache_collect (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr);
28998944Sobrien    }
29098944Sobrien  else
29198944Sobrien    {
29298944Sobrien      unsigned pc_val;
29398944Sobrien      unsigned psr_val;
29498944Sobrien
29598944Sobrien      regcache_collect (ARM_PC_REGNUM, (char *) &pc_val);
29698944Sobrien      regcache_collect (ARM_PS_REGNUM, (char *) &psr_val);
29798944Sobrien
29898944Sobrien      pc_val = ADDR_BITS_REMOVE (pc_val);
29998944Sobrien      psr_val ^= ADDR_BITS_REMOVE (psr_val);
30098944Sobrien
30198944Sobrien      inferior_registers.r_pc = pc_val | psr_val;
30298944Sobrien    }
30398944Sobrien
30498944Sobrien  ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
30598944Sobrien		(PTRACE_ARG3_TYPE) &inferior_registers, 0);
30698944Sobrien
30798944Sobrien  if (ret < 0)
30898944Sobrien    warning ("unable to store general registers");
30998944Sobrien}
31098944Sobrien
31198944Sobrienstatic void
31298944Sobrienstore_fp_register (int regno)
31398944Sobrien{
31498944Sobrien  struct fpreg inferior_fp_registers;
31598944Sobrien  int ret;
31698944Sobrien
31798944Sobrien  ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
31898944Sobrien		(PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
31998944Sobrien
32098944Sobrien  if (ret < 0)
32198944Sobrien    {
32298944Sobrien      warning ("unable to fetch floating-point registers");
32398944Sobrien      return;
32498944Sobrien    }
32598944Sobrien
32698944Sobrien  switch (regno)
32798944Sobrien    {
32898944Sobrien    case ARM_FPS_REGNUM:
32998944Sobrien      regcache_collect (ARM_FPS_REGNUM,
33098944Sobrien			(char *) &inferior_fp_registers.fpr_fpsr);
33198944Sobrien      break;
33298944Sobrien
33398944Sobrien    default:
33498944Sobrien      regcache_collect
33598944Sobrien	(regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
33698944Sobrien      break;
33798944Sobrien    }
33898944Sobrien
33998944Sobrien  ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
34098944Sobrien		(PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
34198944Sobrien
34298944Sobrien  if (ret < 0)
34398944Sobrien    warning ("unable to write register %d to inferior", regno);
34498944Sobrien}
34598944Sobrien
34698944Sobrienstatic void
34798944Sobrienstore_fp_regs (void)
34898944Sobrien{
34998944Sobrien  struct fpreg inferior_fp_registers;
35098944Sobrien  int ret;
35198944Sobrien  int regno;
35298944Sobrien
35398944Sobrien
35498944Sobrien  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
35598944Sobrien    regcache_collect
35698944Sobrien      (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
35798944Sobrien
35898944Sobrien  regcache_collect (ARM_FPS_REGNUM, (char *) &inferior_fp_registers.fpr_fpsr);
35998944Sobrien
36098944Sobrien  ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
36198944Sobrien		(PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
36298944Sobrien
36398944Sobrien  if (ret < 0)
36498944Sobrien    warning ("unable to store floating-point registers");
36598944Sobrien}
36698944Sobrien
36798944Sobrienvoid
36898944Sobrienstore_inferior_registers (int regno)
36998944Sobrien{
37098944Sobrien  if (regno >= 0)
37198944Sobrien    {
37298944Sobrien      if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
37398944Sobrien	store_register (regno);
37498944Sobrien      else
37598944Sobrien	store_fp_register (regno);
37698944Sobrien    }
37798944Sobrien  else
37898944Sobrien    {
37998944Sobrien      store_regs ();
38098944Sobrien      store_fp_regs ();
38198944Sobrien    }
38298944Sobrien}
38398944Sobrien
38498944Sobrienstruct md_core
38598944Sobrien{
38698944Sobrien  struct reg intreg;
38798944Sobrien  struct fpreg freg;
38898944Sobrien};
38998944Sobrien
39098944Sobrienstatic void
39198944Sobrienfetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
39298944Sobrien		      int which, CORE_ADDR ignore)
39398944Sobrien{
39498944Sobrien  struct md_core *core_reg = (struct md_core *) core_reg_sect;
39598944Sobrien  int regno;
39698944Sobrien  CORE_ADDR r_pc;
39798944Sobrien
39898944Sobrien  supply_gregset (&core_reg->intreg);
39998944Sobrien  supply_fparegset (&core_reg->freg);
40098944Sobrien}
40198944Sobrien
40298944Sobrienstatic void
40398944Sobrienfetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size,
40498944Sobrien			 int which, CORE_ADDR ignore)
40598944Sobrien{
40698944Sobrien  struct reg gregset;
40798944Sobrien  struct fpreg fparegset;
40898944Sobrien
40998944Sobrien  switch (which)
41098944Sobrien    {
41198944Sobrien    case 0:	/* Integer registers.  */
41298944Sobrien      if (core_reg_size != sizeof (struct reg))
41398944Sobrien	warning ("wrong size of register set in core file");
41498944Sobrien      else
41598944Sobrien	{
41698944Sobrien	  /* The memcpy may be unnecessary, but we can't really be sure
41798944Sobrien	     of the alignment of the data in the core file.  */
41898944Sobrien	  memcpy (&gregset, core_reg_sect, sizeof (gregset));
41998944Sobrien	  supply_gregset (&gregset);
42098944Sobrien	}
42198944Sobrien      break;
42298944Sobrien
42398944Sobrien    case 2:
42498944Sobrien      if (core_reg_size != sizeof (struct fpreg))
42598944Sobrien	warning ("wrong size of FPA register set in core file");
42698944Sobrien      else
42798944Sobrien	{
42898944Sobrien	  /* The memcpy may be unnecessary, but we can't really be sure
42998944Sobrien	     of the alignment of the data in the core file.  */
43098944Sobrien	  memcpy (&fparegset, core_reg_sect, sizeof (fparegset));
43198944Sobrien	  supply_fparegset (&fparegset);
43298944Sobrien	}
43398944Sobrien      break;
43498944Sobrien
43598944Sobrien    default:
43698944Sobrien      /* Don't know what kind of register request this is; just ignore it.  */
43798944Sobrien      break;
43898944Sobrien    }
43998944Sobrien}
44098944Sobrien
44198944Sobrienstatic struct core_fns arm_netbsd_core_fns =
44298944Sobrien{
44398944Sobrien  bfd_target_unknown_flavour,		/* core_flovour.  */
44498944Sobrien  default_check_format,			/* check_format.  */
44598944Sobrien  default_core_sniffer,			/* core_sniffer.  */
44698944Sobrien  fetch_core_registers,			/* core_read_registers.  */
44798944Sobrien  NULL
44898944Sobrien};
44998944Sobrien
45098944Sobrienstatic struct core_fns arm_netbsd_elfcore_fns =
45198944Sobrien{
45298944Sobrien  bfd_target_elf_flavour,		/* core_flovour.  */
45398944Sobrien  default_check_format,			/* check_format.  */
45498944Sobrien  default_core_sniffer,			/* core_sniffer.  */
45598944Sobrien  fetch_elfcore_registers,		/* core_read_registers.  */
45698944Sobrien  NULL
45798944Sobrien};
45898944Sobrien
45998944Sobrienvoid
46098944Sobrien_initialize_arm_netbsd_nat (void)
46198944Sobrien{
46298944Sobrien  add_core_fns (&arm_netbsd_core_fns);
46398944Sobrien  add_core_fns (&arm_netbsd_elfcore_fns);
46498944Sobrien}
465