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