* ppcobsd-tdep.c: Update copyright year. Include "trad-frame.h"
[platform/upstream/binutils.git] / gdb / ppcobsd-tdep.c
1 /* Target-dependent code for OpenBSD/powerpc.
2
3    Copyright 2004, 2005 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 #include "defs.h"
23 #include "arch-utils.h"
24 #include "osabi.h"
25 #include "regcache.h"
26 #include "regset.h"
27 #include "trad-frame.h"
28 #include "tramp-frame.h"
29
30 #include "gdb_assert.h"
31 #include "gdb_string.h"
32
33 #include "ppc-tdep.h"
34 #include "ppcobsd-tdep.h"
35 #include "solib-svr4.h"
36
37 /* Register offsets from <machine/reg.h>.  */
38 struct ppc_reg_offsets ppcobsd_reg_offsets;
39 \f
40
41 /* Core file support.  */
42
43 /* Supply register REGNUM in the general-purpose register set REGSET
44    from the buffer specified by GREGS and LEN to register cache
45    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
46
47 void
48 ppcobsd_supply_gregset (const struct regset *regset,
49                         struct regcache *regcache, int regnum,
50                         const void *gregs, size_t len)
51 {
52   /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
53      point registers.  Traditionally, GDB's register set has still
54      listed the floating point registers for such machines, so this
55      code is harmless.  However, the new E500 port actually omits the
56      floating point registers entirely from the register set --- they
57      don't even have register numbers assigned to them.
58
59      It's not clear to me how best to update this code, so this assert
60      will alert the first person to encounter the OpenBSD/E500
61      combination to the problem.  */
62   gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
63
64   ppc_supply_gregset (regset, regcache, regnum, gregs, len);
65   ppc_supply_fpregset (regset, regcache, regnum, gregs, len);
66 }
67
68 /* Collect register REGNUM in the general-purpose register set
69    REGSET. from register cache REGCACHE into the buffer specified by
70    GREGS and LEN.  If REGNUM is -1, do this for all registers in
71    REGSET.  */
72
73 void
74 ppcobsd_collect_gregset (const struct regset *regset,
75                          const struct regcache *regcache, int regnum,
76                          void *gregs, size_t len)
77 {
78   /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
79      point registers.  Traditionally, GDB's register set has still
80      listed the floating point registers for such machines, so this
81      code is harmless.  However, the new E500 port actually omits the
82      floating point registers entirely from the register set --- they
83      don't even have register numbers assigned to them.
84
85      It's not clear to me how best to update this code, so this assert
86      will alert the first person to encounter the OpenBSD/E500
87      combination to the problem.  */
88   gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
89
90   ppc_collect_gregset (regset, regcache, regnum, gregs, len);
91   ppc_collect_fpregset (regset, regcache, regnum, gregs, len);
92 }
93
94 /* OpenBS/powerpc register set.  */
95
96 struct regset ppcobsd_gregset =
97 {
98   &ppcobsd_reg_offsets,
99   ppcobsd_supply_gregset
100 };
101
102 /* Return the appropriate register set for the core section identified
103    by SECT_NAME and SECT_SIZE.  */
104
105 static const struct regset *
106 ppcobsd_regset_from_core_section (struct gdbarch *gdbarch,
107                                   const char *sect_name, size_t sect_size)
108 {
109   if (strcmp (sect_name, ".reg") == 0 && sect_size >= 412)
110     return &ppcobsd_gregset;
111
112   return NULL;
113 }
114 \f
115
116 /* Signal trampolines.  */
117
118 static void
119 ppcobsd_sigtramp_cache_init (const struct tramp_frame *self,
120                              struct frame_info *next_frame,
121                              struct trad_frame_cache *this_cache,
122                              CORE_ADDR func)
123 {
124   struct gdbarch *gdbarch = get_frame_arch (next_frame);
125   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
126   CORE_ADDR addr, base;
127   int i;
128
129   base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
130   addr = base + 0x18 + 2 * tdep->wordsize;
131   for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize)
132     {
133       int regnum = i + tdep->ppc_gp0_regnum;
134       trad_frame_set_reg_addr (this_cache, regnum, addr);
135     }
136   trad_frame_set_reg_addr (this_cache, tdep->ppc_lr_regnum, addr);
137   addr += tdep->wordsize;
138   trad_frame_set_reg_addr (this_cache, tdep->ppc_cr_regnum, addr);
139   addr += tdep->wordsize;
140   trad_frame_set_reg_addr (this_cache, tdep->ppc_xer_regnum, addr);
141   addr += tdep->wordsize;
142   trad_frame_set_reg_addr (this_cache, tdep->ppc_ctr_regnum, addr);
143   addr += tdep->wordsize;
144   trad_frame_set_reg_addr (this_cache, PC_REGNUM, addr); /* SRR0? */
145   addr += tdep->wordsize;
146
147   /* Construct the frame ID using the function start.  */
148   trad_frame_set_id (this_cache, frame_id_build (base, func));
149 }
150
151 static const struct tramp_frame ppcobsd_sigtramp =
152 {
153   SIGTRAMP_FRAME,
154   4,
155   {
156     { 0x3821fff0, -1 },         /* add r1,r1,-16 */
157     { 0x4e800021, -1 },         /* blrl */
158     { 0x38610018, -1 },         /* addi r3,r1,24 */
159     { 0x38000067, -1 },         /* li r0,103 */
160     { 0x44000002, -1 },         /* sc */
161     { 0x38000001, -1 },         /* li r0,1 */
162     { 0x44000002, -1 },         /* sc */
163     { TRAMP_SENTINEL_INSN, -1 }
164   },
165   ppcobsd_sigtramp_cache_init
166 };
167
168 \f
169 static void
170 ppcobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
171 {
172   /* OpenBSD uses SVR4-style shared libraries.  */
173   set_solib_svr4_fetch_link_map_offsets
174     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
175
176   set_gdbarch_regset_from_core_section
177     (gdbarch, ppcobsd_regset_from_core_section);
178
179   tramp_frame_prepend_unwinder (gdbarch, &ppcobsd_sigtramp);
180 }
181 \f
182
183 /* OpenBSD uses uses the traditional NetBSD core file format, even for
184    ports that use ELF.  */
185 #define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF
186
187 static enum gdb_osabi
188 ppcobsd_core_osabi_sniffer (bfd *abfd)
189 {
190   if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
191     return GDB_OSABI_NETBSD_CORE;
192
193   return GDB_OSABI_UNKNOWN;
194 }
195 \f
196
197 /* Provide a prototype to silence -Wmissing-prototypes.  */
198 void _initialize_ppcobsd_tdep (void);
199
200 void
201 _initialize_ppcobsd_tdep (void)
202 {
203   /* BFD doesn't set a flavour for NetBSD style a.out core files.  */
204   gdbarch_register_osabi_sniffer (bfd_arch_powerpc, bfd_target_unknown_flavour,
205                                   ppcobsd_core_osabi_sniffer);
206
207   gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_OPENBSD_ELF,
208                           ppcobsd_init_abi);
209
210   /* Avoid initializing the register offsets again if they were
211      already initailized by ppcobsd-nat.c.  */
212   if (ppcobsd_reg_offsets.pc_offset == 0)
213     {
214       /* General-purpose registers.  */
215       ppcobsd_reg_offsets.r0_offset = 0;
216       ppcobsd_reg_offsets.pc_offset = 384;
217       ppcobsd_reg_offsets.ps_offset = 388;
218       ppcobsd_reg_offsets.cr_offset = 392;
219       ppcobsd_reg_offsets.lr_offset = 396;
220       ppcobsd_reg_offsets.ctr_offset = 400;
221       ppcobsd_reg_offsets.xer_offset = 404;
222       ppcobsd_reg_offsets.mq_offset = 408;
223
224       /* Floating-point registers.  */
225       ppcobsd_reg_offsets.f0_offset = 128;
226       ppcobsd_reg_offsets.fpscr_offset = -1;
227
228       /* AltiVec registers.  */
229       ppcobsd_reg_offsets.vr0_offset = 0;
230       ppcobsd_reg_offsets.vscr_offset = 512;
231       ppcobsd_reg_offsets.vrsave_offset = 520;
232     }
233 }