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