1285SN/A/* Target-dependent code for PowerPC systems running NetBSD.
2821Saefimov   Copyright 2002, 2003 Free Software Foundation, Inc.
3285SN/A   Contributed by Wasabi Systems, Inc.
4285SN/A
5285SN/A   This file is part of GDB.
6285SN/A
7285SN/A   This program is free software; you can redistribute it and/or modify
8285SN/A   it under the terms of the GNU General Public License as published by
9285SN/A   the Free Software Foundation; either version 2 of the License, or
10285SN/A   (at your option) any later version.
11285SN/A
12285SN/A   This program is distributed in the hope that it will be useful,
13285SN/A   but WITHOUT ANY WARRANTY; without even the implied warranty of
14285SN/A   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15285SN/A   GNU General Public License for more details.
16285SN/A
17285SN/A   You should have received a copy of the GNU General Public License
18285SN/A   along with this program; if not, write to the Free Software
19285SN/A   Foundation, Inc., 59 Temple Place - Suite 330,
20285SN/A   Boston, MA 02111-1307, USA.  */
21285SN/A
22285SN/A#include "defs.h"
23285SN/A#include "gdbcore.h"
24285SN/A#include "regcache.h"
25285SN/A#include "target.h"
26285SN/A#include "breakpoint.h"
27285SN/A#include "value.h"
28285SN/A#include "osabi.h"
29285SN/A
30285SN/A#include "ppc-tdep.h"
31285SN/A#include "ppcnbsd-tdep.h"
32285SN/A#include "nbsd-tdep.h"
33285SN/A
34285SN/A#include "solib-svr4.h"
35285SN/A
36285SN/A#define REG_FIXREG_OFFSET(x)	((x) * 4)
37285SN/A#define REG_LR_OFFSET		(32 * 4)
38285SN/A#define REG_CR_OFFSET		(33 * 4)
39285SN/A#define REG_XER_OFFSET		(34 * 4)
40285SN/A#define REG_CTR_OFFSET		(35 * 4)
41285SN/A#define REG_PC_OFFSET		(36 * 4)
42285SN/A#define SIZEOF_STRUCT_REG	(37 * 4)
43285SN/A
44285SN/A#define FPREG_FPR_OFFSET(x)	((x) * 8)
45285SN/A#define FPREG_FPSCR_OFFSET	(32 * 8)
46285SN/A#define SIZEOF_STRUCT_FPREG	(33 * 8)
47285SN/A
48285SN/Avoid
49285SN/Appcnbsd_supply_reg (char *regs, int regno)
50285SN/A{
51285SN/A  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
52285SN/A  int i;
53285SN/A
54285SN/A  for (i = 0; i <= 31; i++)
55285SN/A    {
56285SN/A      if (regno == i || regno == -1)
57285SN/A	supply_register (i, regs + REG_FIXREG_OFFSET (i));
58285SN/A    }
59285SN/A
60285SN/A  if (regno == tdep->ppc_lr_regnum || regno == -1)
61285SN/A    supply_register (tdep->ppc_lr_regnum, regs + REG_LR_OFFSET);
62285SN/A
63285SN/A  if (regno == tdep->ppc_cr_regnum || regno == -1)
64285SN/A    supply_register (tdep->ppc_cr_regnum, regs + REG_CR_OFFSET);
65285SN/A
66285SN/A  if (regno == tdep->ppc_xer_regnum || regno == -1)
67285SN/A    supply_register (tdep->ppc_xer_regnum, regs + REG_XER_OFFSET);
68285SN/A
69285SN/A  if (regno == tdep->ppc_ctr_regnum || regno == -1)
70285SN/A    supply_register (tdep->ppc_ctr_regnum, regs + REG_CTR_OFFSET);
71285SN/A
72285SN/A  if (regno == PC_REGNUM || regno == -1)
73285SN/A    supply_register (PC_REGNUM, regs + REG_PC_OFFSET);
74285SN/A}
75285SN/A
76285SN/Avoid
77285SN/Appcnbsd_fill_reg (char *regs, int regno)
78285SN/A{
79285SN/A  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
80285SN/A  int i;
81641Smkos
82641Smkos  for (i = 0; i <= 31; i++)
83641Smkos    {
84285SN/A      if (regno == i || regno == -1)
85285SN/A	regcache_collect (i, regs + REG_FIXREG_OFFSET (i));
86285SN/A    }
87285SN/A
88285SN/A  if (regno == tdep->ppc_lr_regnum || regno == -1)
89285SN/A    regcache_collect (tdep->ppc_lr_regnum, regs + REG_LR_OFFSET);
90285SN/A
91285SN/A  if (regno == tdep->ppc_cr_regnum || regno == -1)
92285SN/A    regcache_collect (tdep->ppc_cr_regnum, regs + REG_CR_OFFSET);
93285SN/A
94285SN/A  if (regno == tdep->ppc_xer_regnum || regno == -1)
95285SN/A    regcache_collect (tdep->ppc_xer_regnum, regs + REG_XER_OFFSET);
96285SN/A
97285SN/A  if (regno == tdep->ppc_ctr_regnum || regno == -1)
98285SN/A    regcache_collect (tdep->ppc_ctr_regnum, regs + REG_CTR_OFFSET);
99285SN/A
100285SN/A  if (regno == PC_REGNUM || regno == -1)
101641Smkos    regcache_collect (PC_REGNUM, regs + REG_PC_OFFSET);
102641Smkos}
103285SN/A
104285SN/Avoid
105285SN/Appcnbsd_supply_fpreg (char *fpregs, int regno)
106285SN/A{
107285SN/A  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
108285SN/A  int i;
109285SN/A
110285SN/A  for (i = FP0_REGNUM; i <= FP0_REGNUM + 31; i++)
111285SN/A    {
112285SN/A      if (regno == i || regno == -1)
113285SN/A	supply_register (i, fpregs + FPREG_FPR_OFFSET (i - FP0_REGNUM));
114285SN/A    }
115285SN/A
116285SN/A  if (regno == tdep->ppc_fpscr_regnum || regno == -1)
117285SN/A    supply_register (tdep->ppc_fpscr_regnum, fpregs + FPREG_FPSCR_OFFSET);
118285SN/A}
119285SN/A
120285SN/Avoid
121285SN/Appcnbsd_fill_fpreg (char *fpregs, int regno)
122285SN/A{
123285SN/A  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
124285SN/A  int i;
125285SN/A
126285SN/A  for (i = FP0_REGNUM; i <= FP0_REGNUM + 31; i++)
127285SN/A    {
128285SN/A      if (regno == i || regno == -1)
129285SN/A	regcache_collect (i, fpregs + FPREG_FPR_OFFSET (i - FP0_REGNUM));
130285SN/A    }
131285SN/A
132285SN/A  if (regno == tdep->ppc_fpscr_regnum || regno == -1)
133285SN/A    regcache_collect (tdep->ppc_fpscr_regnum, fpregs + FPREG_FPSCR_OFFSET);
134285SN/A}
135285SN/A
136285SN/Astatic void
137285SN/Afetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
138285SN/A                      CORE_ADDR ignore)
139285SN/A{
140285SN/A  char *regs, *fpregs;
141285SN/A
142285SN/A  /* We get everything from one section.  */
143285SN/A  if (which != 0)
144285SN/A    return;
145285SN/A
146285SN/A  regs = core_reg_sect;
147285SN/A  fpregs = core_reg_sect + SIZEOF_STRUCT_REG;
148285SN/A
149285SN/A  /* Integer registers.  */
150285SN/A  ppcnbsd_supply_reg (regs, -1);
151285SN/A
152285SN/A  /* Floating point registers.  */
153285SN/A  ppcnbsd_supply_fpreg (fpregs, -1);
154285SN/A}
155285SN/A
156285SN/Astatic void
157285SN/Afetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size, int which,
158285SN/A                         CORE_ADDR ignore)
159285SN/A{
160285SN/A  switch (which)
161285SN/A    {
162285SN/A    case 0:  /* Integer registers.  */
163285SN/A      if (core_reg_size != SIZEOF_STRUCT_REG)
164285SN/A	warning ("Wrong size register set in core file.");
165285SN/A      else
166285SN/A	ppcnbsd_supply_reg (core_reg_sect, -1);
167285SN/A      break;
168821Saefimov
169285SN/A    case 2:  /* Floating point registers.  */
170285SN/A      if (core_reg_size != SIZEOF_STRUCT_FPREG)
171285SN/A	warning ("Wrong size FP register set in core file.");
172285SN/A      else
173285SN/A	ppcnbsd_supply_fpreg (core_reg_sect, -1);
174285SN/A      break;
175285SN/A
176285SN/A    default:
177285SN/A      /* Don't know what kind of register request this is; just ignore it.  */
178285SN/A      break;
179285SN/A    }
180285SN/A}
181285SN/A
182285SN/Astatic struct core_fns ppcnbsd_core_fns =
183285SN/A{
184285SN/A  bfd_target_unknown_flavour,		/* core_flavour */
185285SN/A  default_check_format,			/* check_format */
186285SN/A  default_core_sniffer,			/* core_sniffer */
187285SN/A  fetch_core_registers,			/* core_read_registers */
188285SN/A  NULL					/* next */
189285SN/A};
190285SN/A
191367SN/Astatic struct core_fns ppcnbsd_elfcore_fns =
192285SN/A{
193285SN/A  bfd_target_elf_flavour,		/* core_flavour */
194285SN/A  default_check_format,			/* check_format */
195285SN/A  default_core_sniffer,			/* core_sniffer */
196285SN/A  fetch_elfcore_registers,		/* core_read_registers */
197285SN/A  NULL					/* next */
198285SN/A};
199285SN/A
200285SN/Astatic int
201285SN/Appcnbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
202285SN/A{
203285SN/A  /* FIXME: Need to add support for kernel-provided signal trampolines.  */
204285SN/A  return (nbsd_pc_in_sigtramp (pc, func_name));
205285SN/A}
206285SN/A
207285SN/A/* NetBSD is confused.  It appears that 1.5 was using the correct SVr4
208285SN/A   convention but, 1.6 switched to the below broken convention.  For
209285SN/A   the moment use the broken convention.  Ulgh!.  */
210285SN/A
211285SN/Astatic enum return_value_convention
212285SN/Appcnbsd_return_value (struct gdbarch *gdbarch, struct type *valtype,
213285SN/A		      struct regcache *regcache, void *readbuf,
214285SN/A		      const void *writebuf)
215285SN/A{
216285SN/A  if ((TYPE_CODE (valtype) == TYPE_CODE_STRUCT
217285SN/A       || TYPE_CODE (valtype) == TYPE_CODE_UNION)
218285SN/A      && !((TYPE_LENGTH (valtype) == 16 || TYPE_LENGTH (valtype) == 8)
219285SN/A	    && TYPE_VECTOR (valtype))
220285SN/A      && !(TYPE_LENGTH (valtype) == 1
221285SN/A	   || TYPE_LENGTH (valtype) == 2
222285SN/A	   || TYPE_LENGTH (valtype) == 4
223285SN/A	   || TYPE_LENGTH (valtype) == 8))
224285SN/A    return RETURN_VALUE_STRUCT_CONVENTION;
225285SN/A  else
226285SN/A    return ppc_sysv_abi_broken_return_value (gdbarch, valtype, regcache,
227285SN/A					     readbuf, writebuf);
228285SN/A}
229285SN/A
230285SN/Astatic void
231285SN/Appcnbsd_init_abi (struct gdbarch_info info,
232285SN/A                  struct gdbarch *gdbarch)
233285SN/A{
234285SN/A  set_gdbarch_pc_in_sigtramp (gdbarch, ppcnbsd_pc_in_sigtramp);
235285SN/A  /* For NetBSD, this is an on again, off again thing.  Some systems
236285SN/A     do use the broken struct convention, and some don't.  */
237285SN/A  set_gdbarch_return_value (gdbarch, ppcnbsd_return_value);
238285SN/A  set_solib_svr4_fetch_link_map_offsets (gdbarch,
239285SN/A                                nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
240285SN/A}
241285SN/A
242285SN/Avoid
243285SN/A_initialize_ppcnbsd_tdep (void)
244285SN/A{
245285SN/A  gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_NETBSD_ELF,
246285SN/A			  ppcnbsd_init_abi);
247285SN/A
248285SN/A  add_core_fns (&ppcnbsd_core_fns);
249285SN/A  add_core_fns (&ppcnbsd_elfcore_fns);
250285SN/A}
251285SN/A