1b725ae77Skettenis /* Target-dependent code for PowerPC systems running NetBSD.
2*11efff7fSkettenis 
3*11efff7fSkettenis    Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
4*11efff7fSkettenis 
5b725ae77Skettenis    Contributed by Wasabi Systems, Inc.
6b725ae77Skettenis 
7b725ae77Skettenis    This file is part of GDB.
8b725ae77Skettenis 
9b725ae77Skettenis    This program is free software; you can redistribute it and/or modify
10b725ae77Skettenis    it under the terms of the GNU General Public License as published by
11b725ae77Skettenis    the Free Software Foundation; either version 2 of the License, or
12b725ae77Skettenis    (at your option) any later version.
13b725ae77Skettenis 
14b725ae77Skettenis    This program is distributed in the hope that it will be useful,
15b725ae77Skettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
16b725ae77Skettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17b725ae77Skettenis    GNU General Public License for more details.
18b725ae77Skettenis 
19b725ae77Skettenis    You should have received a copy of the GNU General Public License
20b725ae77Skettenis    along with this program; if not, write to the Free Software
21b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
22b725ae77Skettenis    Boston, MA 02111-1307, USA.  */
23b725ae77Skettenis 
24b725ae77Skettenis #include "defs.h"
25b725ae77Skettenis #include "gdbcore.h"
26b725ae77Skettenis #include "regcache.h"
27b725ae77Skettenis #include "target.h"
28b725ae77Skettenis #include "breakpoint.h"
29b725ae77Skettenis #include "value.h"
30b725ae77Skettenis #include "osabi.h"
31b725ae77Skettenis 
32b725ae77Skettenis #include "ppc-tdep.h"
33b725ae77Skettenis #include "ppcnbsd-tdep.h"
34b725ae77Skettenis #include "nbsd-tdep.h"
35*11efff7fSkettenis #include "tramp-frame.h"
36*11efff7fSkettenis #include "trad-frame.h"
37*11efff7fSkettenis #include "gdb_assert.h"
38b725ae77Skettenis #include "solib-svr4.h"
39b725ae77Skettenis 
40b725ae77Skettenis #define REG_FIXREG_OFFSET(x)	((x) * 4)
41b725ae77Skettenis #define REG_LR_OFFSET		(32 * 4)
42b725ae77Skettenis #define REG_CR_OFFSET		(33 * 4)
43b725ae77Skettenis #define REG_XER_OFFSET		(34 * 4)
44b725ae77Skettenis #define REG_CTR_OFFSET		(35 * 4)
45b725ae77Skettenis #define REG_PC_OFFSET		(36 * 4)
46b725ae77Skettenis #define SIZEOF_STRUCT_REG	(37 * 4)
47b725ae77Skettenis 
48b725ae77Skettenis #define FPREG_FPR_OFFSET(x)	((x) * 8)
49b725ae77Skettenis #define FPREG_FPSCR_OFFSET	(32 * 8)
50b725ae77Skettenis #define SIZEOF_STRUCT_FPREG	(33 * 8)
51b725ae77Skettenis 
52b725ae77Skettenis void
ppcnbsd_supply_reg(char * regs,int regno)53b725ae77Skettenis ppcnbsd_supply_reg (char *regs, int regno)
54b725ae77Skettenis {
55b725ae77Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
56b725ae77Skettenis   int i;
57b725ae77Skettenis 
58*11efff7fSkettenis   for (i = 0; i < ppc_num_gprs; i++)
59b725ae77Skettenis     {
60*11efff7fSkettenis       if (regno == tdep->ppc_gp0_regnum + i || regno == -1)
61*11efff7fSkettenis 	regcache_raw_supply (current_regcache, tdep->ppc_gp0_regnum + i,
62*11efff7fSkettenis 			     regs + REG_FIXREG_OFFSET (i));
63b725ae77Skettenis     }
64b725ae77Skettenis 
65b725ae77Skettenis   if (regno == tdep->ppc_lr_regnum || regno == -1)
66*11efff7fSkettenis     regcache_raw_supply (current_regcache, tdep->ppc_lr_regnum,
67*11efff7fSkettenis 			 regs + REG_LR_OFFSET);
68b725ae77Skettenis 
69b725ae77Skettenis   if (regno == tdep->ppc_cr_regnum || regno == -1)
70*11efff7fSkettenis     regcache_raw_supply (current_regcache, tdep->ppc_cr_regnum,
71*11efff7fSkettenis 			 regs + REG_CR_OFFSET);
72b725ae77Skettenis 
73b725ae77Skettenis   if (regno == tdep->ppc_xer_regnum || regno == -1)
74*11efff7fSkettenis     regcache_raw_supply (current_regcache, tdep->ppc_xer_regnum,
75*11efff7fSkettenis 			 regs + REG_XER_OFFSET);
76b725ae77Skettenis 
77b725ae77Skettenis   if (regno == tdep->ppc_ctr_regnum || regno == -1)
78*11efff7fSkettenis     regcache_raw_supply (current_regcache, tdep->ppc_ctr_regnum,
79*11efff7fSkettenis 			 regs + REG_CTR_OFFSET);
80b725ae77Skettenis 
81b725ae77Skettenis   if (regno == PC_REGNUM || regno == -1)
82*11efff7fSkettenis     regcache_raw_supply (current_regcache, PC_REGNUM,
83*11efff7fSkettenis 			 regs + REG_PC_OFFSET);
84b725ae77Skettenis }
85b725ae77Skettenis 
86b725ae77Skettenis void
ppcnbsd_fill_reg(char * regs,int regno)87b725ae77Skettenis ppcnbsd_fill_reg (char *regs, int regno)
88b725ae77Skettenis {
89b725ae77Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
90b725ae77Skettenis   int i;
91b725ae77Skettenis 
92*11efff7fSkettenis   for (i = 0; i < ppc_num_gprs; i++)
93b725ae77Skettenis     {
94*11efff7fSkettenis       if (regno == tdep->ppc_gp0_regnum + i || regno == -1)
95*11efff7fSkettenis 	regcache_raw_collect (current_regcache, tdep->ppc_gp0_regnum + i,
96*11efff7fSkettenis 			      regs + REG_FIXREG_OFFSET (i));
97b725ae77Skettenis     }
98b725ae77Skettenis 
99b725ae77Skettenis   if (regno == tdep->ppc_lr_regnum || regno == -1)
100*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_lr_regnum,
101*11efff7fSkettenis 			  regs + REG_LR_OFFSET);
102b725ae77Skettenis 
103b725ae77Skettenis   if (regno == tdep->ppc_cr_regnum || regno == -1)
104*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_cr_regnum,
105*11efff7fSkettenis 			  regs + REG_CR_OFFSET);
106b725ae77Skettenis 
107b725ae77Skettenis   if (regno == tdep->ppc_xer_regnum || regno == -1)
108*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_xer_regnum,
109*11efff7fSkettenis 			  regs + REG_XER_OFFSET);
110b725ae77Skettenis 
111b725ae77Skettenis   if (regno == tdep->ppc_ctr_regnum || regno == -1)
112*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_ctr_regnum,
113*11efff7fSkettenis 			  regs + REG_CTR_OFFSET);
114b725ae77Skettenis 
115b725ae77Skettenis   if (regno == PC_REGNUM || regno == -1)
116*11efff7fSkettenis     regcache_raw_collect (current_regcache, PC_REGNUM, regs + REG_PC_OFFSET);
117b725ae77Skettenis }
118b725ae77Skettenis 
119b725ae77Skettenis void
ppcnbsd_supply_fpreg(char * fpregs,int regno)120b725ae77Skettenis ppcnbsd_supply_fpreg (char *fpregs, int regno)
121b725ae77Skettenis {
122b725ae77Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
123b725ae77Skettenis   int i;
124b725ae77Skettenis 
125*11efff7fSkettenis   /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
126*11efff7fSkettenis      point registers.  Traditionally, GDB's register set has still
127*11efff7fSkettenis      listed the floating point registers for such machines, so this
128*11efff7fSkettenis      code is harmless.  However, the new E500 port actually omits the
129*11efff7fSkettenis      floating point registers entirely from the register set --- they
130*11efff7fSkettenis      don't even have register numbers assigned to them.
131*11efff7fSkettenis 
132*11efff7fSkettenis      It's not clear to me how best to update this code, so this assert
133*11efff7fSkettenis      will alert the first person to encounter the NetBSD/E500
134*11efff7fSkettenis      combination to the problem.  */
135*11efff7fSkettenis   gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
136*11efff7fSkettenis 
137*11efff7fSkettenis   for (i = 0; i < ppc_num_fprs; i++)
138b725ae77Skettenis     {
139*11efff7fSkettenis       if (regno == tdep->ppc_fp0_regnum + i || regno == -1)
140*11efff7fSkettenis 	regcache_raw_supply (current_regcache, tdep->ppc_fp0_regnum + i,
141*11efff7fSkettenis 			     fpregs + FPREG_FPR_OFFSET (i));
142b725ae77Skettenis     }
143b725ae77Skettenis 
144b725ae77Skettenis   if (regno == tdep->ppc_fpscr_regnum || regno == -1)
145*11efff7fSkettenis     regcache_raw_supply (current_regcache, tdep->ppc_fpscr_regnum,
146*11efff7fSkettenis 			 fpregs + FPREG_FPSCR_OFFSET);
147b725ae77Skettenis }
148b725ae77Skettenis 
149b725ae77Skettenis void
ppcnbsd_fill_fpreg(char * fpregs,int regno)150b725ae77Skettenis ppcnbsd_fill_fpreg (char *fpregs, int regno)
151b725ae77Skettenis {
152b725ae77Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
153b725ae77Skettenis   int i;
154b725ae77Skettenis 
155*11efff7fSkettenis   /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
156*11efff7fSkettenis      point registers.  Traditionally, GDB's register set has still
157*11efff7fSkettenis      listed the floating point registers for such machines, so this
158*11efff7fSkettenis      code is harmless.  However, the new E500 port actually omits the
159*11efff7fSkettenis      floating point registers entirely from the register set --- they
160*11efff7fSkettenis      don't even have register numbers assigned to them.
161*11efff7fSkettenis 
162*11efff7fSkettenis      It's not clear to me how best to update this code, so this assert
163*11efff7fSkettenis      will alert the first person to encounter the NetBSD/E500
164*11efff7fSkettenis      combination to the problem.  */
165*11efff7fSkettenis   gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
166*11efff7fSkettenis 
167*11efff7fSkettenis   for (i = 0; i < ppc_num_fprs; i++)
168b725ae77Skettenis     {
169*11efff7fSkettenis       if (regno == tdep->ppc_fp0_regnum + i || regno == -1)
170*11efff7fSkettenis 	regcache_raw_collect (current_regcache, tdep->ppc_fp0_regnum + i,
171*11efff7fSkettenis 			      fpregs + FPREG_FPR_OFFSET (i));
172b725ae77Skettenis     }
173b725ae77Skettenis 
174b725ae77Skettenis   if (regno == tdep->ppc_fpscr_regnum || regno == -1)
175*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_fpscr_regnum,
176*11efff7fSkettenis 			  fpregs + FPREG_FPSCR_OFFSET);
177b725ae77Skettenis }
178b725ae77Skettenis 
179b725ae77Skettenis static void
fetch_core_registers(char * core_reg_sect,unsigned core_reg_size,int which,CORE_ADDR ignore)180b725ae77Skettenis fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
181b725ae77Skettenis                       CORE_ADDR ignore)
182b725ae77Skettenis {
183b725ae77Skettenis   char *regs, *fpregs;
184b725ae77Skettenis 
185b725ae77Skettenis   /* We get everything from one section.  */
186b725ae77Skettenis   if (which != 0)
187b725ae77Skettenis     return;
188b725ae77Skettenis 
189b725ae77Skettenis   regs = core_reg_sect;
190b725ae77Skettenis   fpregs = core_reg_sect + SIZEOF_STRUCT_REG;
191b725ae77Skettenis 
192b725ae77Skettenis   /* Integer registers.  */
193b725ae77Skettenis   ppcnbsd_supply_reg (regs, -1);
194b725ae77Skettenis 
195b725ae77Skettenis   /* Floating point registers.  */
196b725ae77Skettenis   ppcnbsd_supply_fpreg (fpregs, -1);
197b725ae77Skettenis }
198b725ae77Skettenis 
199b725ae77Skettenis static void
fetch_elfcore_registers(char * core_reg_sect,unsigned core_reg_size,int which,CORE_ADDR ignore)200b725ae77Skettenis fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size, int which,
201b725ae77Skettenis                          CORE_ADDR ignore)
202b725ae77Skettenis {
203b725ae77Skettenis   switch (which)
204b725ae77Skettenis     {
205b725ae77Skettenis     case 0:  /* Integer registers.  */
206b725ae77Skettenis       if (core_reg_size != SIZEOF_STRUCT_REG)
207b725ae77Skettenis 	warning ("Wrong size register set in core file.");
208b725ae77Skettenis       else
209b725ae77Skettenis 	ppcnbsd_supply_reg (core_reg_sect, -1);
210b725ae77Skettenis       break;
211b725ae77Skettenis 
212b725ae77Skettenis     case 2:  /* Floating point registers.  */
213b725ae77Skettenis       if (core_reg_size != SIZEOF_STRUCT_FPREG)
214b725ae77Skettenis 	warning ("Wrong size FP register set in core file.");
215b725ae77Skettenis       else
216b725ae77Skettenis 	ppcnbsd_supply_fpreg (core_reg_sect, -1);
217b725ae77Skettenis       break;
218b725ae77Skettenis 
219b725ae77Skettenis     default:
220b725ae77Skettenis       /* Don't know what kind of register request this is; just ignore it.  */
221b725ae77Skettenis       break;
222b725ae77Skettenis     }
223b725ae77Skettenis }
224b725ae77Skettenis 
225b725ae77Skettenis static struct core_fns ppcnbsd_core_fns =
226b725ae77Skettenis {
227b725ae77Skettenis   bfd_target_unknown_flavour,		/* core_flavour */
228b725ae77Skettenis   default_check_format,			/* check_format */
229b725ae77Skettenis   default_core_sniffer,			/* core_sniffer */
230b725ae77Skettenis   fetch_core_registers,			/* core_read_registers */
231b725ae77Skettenis   NULL					/* next */
232b725ae77Skettenis };
233b725ae77Skettenis 
234b725ae77Skettenis static struct core_fns ppcnbsd_elfcore_fns =
235b725ae77Skettenis {
236b725ae77Skettenis   bfd_target_elf_flavour,		/* core_flavour */
237b725ae77Skettenis   default_check_format,			/* check_format */
238b725ae77Skettenis   default_core_sniffer,			/* core_sniffer */
239b725ae77Skettenis   fetch_elfcore_registers,		/* core_read_registers */
240b725ae77Skettenis   NULL					/* next */
241b725ae77Skettenis };
242b725ae77Skettenis 
243b725ae77Skettenis /* NetBSD is confused.  It appears that 1.5 was using the correct SVr4
244b725ae77Skettenis    convention but, 1.6 switched to the below broken convention.  For
245b725ae77Skettenis    the moment use the broken convention.  Ulgh!.  */
246b725ae77Skettenis 
247b725ae77Skettenis static enum return_value_convention
ppcnbsd_return_value(struct gdbarch * gdbarch,struct type * valtype,struct regcache * regcache,void * readbuf,const void * writebuf)248b725ae77Skettenis ppcnbsd_return_value (struct gdbarch *gdbarch, struct type *valtype,
249b725ae77Skettenis 		      struct regcache *regcache, void *readbuf,
250b725ae77Skettenis 		      const void *writebuf)
251b725ae77Skettenis {
252b725ae77Skettenis   if ((TYPE_CODE (valtype) == TYPE_CODE_STRUCT
253b725ae77Skettenis        || TYPE_CODE (valtype) == TYPE_CODE_UNION)
254b725ae77Skettenis       && !((TYPE_LENGTH (valtype) == 16 || TYPE_LENGTH (valtype) == 8)
255b725ae77Skettenis 	    && TYPE_VECTOR (valtype))
256b725ae77Skettenis       && !(TYPE_LENGTH (valtype) == 1
257b725ae77Skettenis 	   || TYPE_LENGTH (valtype) == 2
258b725ae77Skettenis 	   || TYPE_LENGTH (valtype) == 4
259b725ae77Skettenis 	   || TYPE_LENGTH (valtype) == 8))
260b725ae77Skettenis     return RETURN_VALUE_STRUCT_CONVENTION;
261b725ae77Skettenis   else
262b725ae77Skettenis     return ppc_sysv_abi_broken_return_value (gdbarch, valtype, regcache,
263b725ae77Skettenis 					     readbuf, writebuf);
264b725ae77Skettenis }
265b725ae77Skettenis 
266b725ae77Skettenis static void
ppcnbsd_sigtramp_cache_init(const struct tramp_frame * self,struct frame_info * next_frame,struct trad_frame_cache * this_cache,CORE_ADDR func)267*11efff7fSkettenis ppcnbsd_sigtramp_cache_init (const struct tramp_frame *self,
268*11efff7fSkettenis 			     struct frame_info *next_frame,
269*11efff7fSkettenis 			     struct trad_frame_cache *this_cache,
270*11efff7fSkettenis 			     CORE_ADDR func)
271*11efff7fSkettenis {
272*11efff7fSkettenis   CORE_ADDR base;
273*11efff7fSkettenis   CORE_ADDR offset;
274*11efff7fSkettenis   int i;
275*11efff7fSkettenis   struct gdbarch *gdbarch = get_frame_arch (next_frame);
276*11efff7fSkettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
277*11efff7fSkettenis 
278*11efff7fSkettenis   base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
279*11efff7fSkettenis   offset = base + 0x18 + 2 * tdep->wordsize;
280*11efff7fSkettenis   for (i = 0; i < ppc_num_gprs; i++)
281*11efff7fSkettenis     {
282*11efff7fSkettenis       int regnum = i + tdep->ppc_gp0_regnum;
283*11efff7fSkettenis       trad_frame_set_reg_addr (this_cache, regnum, offset);
284*11efff7fSkettenis       offset += tdep->wordsize;
285*11efff7fSkettenis     }
286*11efff7fSkettenis   trad_frame_set_reg_addr (this_cache, tdep->ppc_lr_regnum, offset);
287*11efff7fSkettenis   offset += tdep->wordsize;
288*11efff7fSkettenis   trad_frame_set_reg_addr (this_cache, tdep->ppc_cr_regnum, offset);
289*11efff7fSkettenis   offset += tdep->wordsize;
290*11efff7fSkettenis   trad_frame_set_reg_addr (this_cache, tdep->ppc_xer_regnum, offset);
291*11efff7fSkettenis   offset += tdep->wordsize;
292*11efff7fSkettenis   trad_frame_set_reg_addr (this_cache, tdep->ppc_ctr_regnum, offset);
293*11efff7fSkettenis   offset += tdep->wordsize;
294*11efff7fSkettenis   trad_frame_set_reg_addr (this_cache, PC_REGNUM, offset); /* SRR0? */
295*11efff7fSkettenis   offset += tdep->wordsize;
296*11efff7fSkettenis 
297*11efff7fSkettenis   /* Construct the frame ID using the function start.  */
298*11efff7fSkettenis   trad_frame_set_id (this_cache, frame_id_build (base, func));
299*11efff7fSkettenis }
300*11efff7fSkettenis 
301*11efff7fSkettenis /* Given the NEXT frame, examine the instructions at and around this
302*11efff7fSkettenis    frame's resume address (aka PC) to see of they look like a signal
303*11efff7fSkettenis    trampoline.  Return the address of the trampolines first
304*11efff7fSkettenis    instruction, or zero if it isn't a signal trampoline.  */
305*11efff7fSkettenis 
306*11efff7fSkettenis static const struct tramp_frame ppcnbsd_sigtramp = {
307*11efff7fSkettenis   SIGTRAMP_FRAME,
308*11efff7fSkettenis   4, /* insn size */
309*11efff7fSkettenis   { /* insn */
310*11efff7fSkettenis     { 0x38610018, -1 }, /* addi r3,r1,24 */
311*11efff7fSkettenis     { 0x38000127, -1 }, /* li r0,295 */
312*11efff7fSkettenis     { 0x44000002, -1 }, /* sc */
313*11efff7fSkettenis     { 0x38000001, -1 }, /* li r0,1 */
314*11efff7fSkettenis     { 0x44000002, -1 }, /* sc */
315*11efff7fSkettenis     { TRAMP_SENTINEL_INSN, -1 }
316*11efff7fSkettenis   },
317*11efff7fSkettenis   ppcnbsd_sigtramp_cache_init
318*11efff7fSkettenis };
319*11efff7fSkettenis 
320*11efff7fSkettenis static void
ppcnbsd_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)321b725ae77Skettenis ppcnbsd_init_abi (struct gdbarch_info info,
322b725ae77Skettenis                   struct gdbarch *gdbarch)
323b725ae77Skettenis {
324b725ae77Skettenis   /* For NetBSD, this is an on again, off again thing.  Some systems
325b725ae77Skettenis      do use the broken struct convention, and some don't.  */
326b725ae77Skettenis   set_gdbarch_return_value (gdbarch, ppcnbsd_return_value);
327b725ae77Skettenis   set_solib_svr4_fetch_link_map_offsets (gdbarch,
328b725ae77Skettenis                                 nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
329*11efff7fSkettenis   tramp_frame_prepend_unwinder (gdbarch, &ppcnbsd_sigtramp);
330b725ae77Skettenis }
331b725ae77Skettenis 
332b725ae77Skettenis void
_initialize_ppcnbsd_tdep(void)333b725ae77Skettenis _initialize_ppcnbsd_tdep (void)
334b725ae77Skettenis {
335b725ae77Skettenis   gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_NETBSD_ELF,
336b725ae77Skettenis 			  ppcnbsd_init_abi);
337b725ae77Skettenis 
338*11efff7fSkettenis   deprecated_add_core_fns (&ppcnbsd_core_fns);
339*11efff7fSkettenis   deprecated_add_core_fns (&ppcnbsd_elfcore_fns);
340b725ae77Skettenis }
341