* ppcobsd-tdep.c (ppcobsd_init_abi): Set return_value.
[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 "floatformat.h"
25 #include "osabi.h"
26 #include "regcache.h"
27 #include "regset.h"
28 #include "trad-frame.h"
29 #include "tramp-frame.h"
30
31 #include "gdb_assert.h"
32 #include "gdb_string.h"
33
34 #include "ppc-tdep.h"
35 #include "ppcobsd-tdep.h"
36 #include "solib-svr4.h"
37
38 /* Register offsets from <machine/reg.h>.  */
39 struct ppc_reg_offsets ppcobsd_reg_offsets;
40 \f
41
42 /* Core file support.  */
43
44 /* Supply register REGNUM in the general-purpose register set REGSET
45    from the buffer specified by GREGS and LEN to register cache
46    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
47
48 void
49 ppcobsd_supply_gregset (const struct regset *regset,
50                         struct regcache *regcache, int regnum,
51                         const void *gregs, size_t len)
52 {
53   /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
54      point registers.  Traditionally, GDB's register set has still
55      listed the floating point registers for such machines, so this
56      code is harmless.  However, the new E500 port actually omits the
57      floating point registers entirely from the register set --- they
58      don't even have register numbers assigned to them.
59
60      It's not clear to me how best to update this code, so this assert
61      will alert the first person to encounter the OpenBSD/E500
62      combination to the problem.  */
63   gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
64
65   ppc_supply_gregset (regset, regcache, regnum, gregs, len);
66   ppc_supply_fpregset (regset, regcache, regnum, gregs, len);
67 }
68
69 /* Collect register REGNUM in the general-purpose register set
70    REGSET. from register cache REGCACHE into the buffer specified by
71    GREGS and LEN.  If REGNUM is -1, do this for all registers in
72    REGSET.  */
73
74 void
75 ppcobsd_collect_gregset (const struct regset *regset,
76                          const struct regcache *regcache, int regnum,
77                          void *gregs, size_t len)
78 {
79   /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
80      point registers.  Traditionally, GDB's register set has still
81      listed the floating point registers for such machines, so this
82      code is harmless.  However, the new E500 port actually omits the
83      floating point registers entirely from the register set --- they
84      don't even have register numbers assigned to them.
85
86      It's not clear to me how best to update this code, so this assert
87      will alert the first person to encounter the OpenBSD/E500
88      combination to the problem.  */
89   gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
90
91   ppc_collect_gregset (regset, regcache, regnum, gregs, len);
92   ppc_collect_fpregset (regset, regcache, regnum, gregs, len);
93 }
94
95 /* OpenBSD/powerpc register set.  */
96
97 struct regset ppcobsd_gregset =
98 {
99   &ppcobsd_reg_offsets,
100   ppcobsd_supply_gregset
101 };
102
103 /* Return the appropriate register set for the core section identified
104    by SECT_NAME and SECT_SIZE.  */
105
106 static const struct regset *
107 ppcobsd_regset_from_core_section (struct gdbarch *gdbarch,
108                                   const char *sect_name, size_t sect_size)
109 {
110   if (strcmp (sect_name, ".reg") == 0 && sect_size >= 412)
111     return &ppcobsd_gregset;
112
113   return NULL;
114 }
115 \f
116
117 /* Signal trampolines.  */
118
119 static void
120 ppcobsd_sigtramp_cache_init (const struct tramp_frame *self,
121                              struct frame_info *next_frame,
122                              struct trad_frame_cache *this_cache,
123                              CORE_ADDR func)
124 {
125   struct gdbarch *gdbarch = get_frame_arch (next_frame);
126   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
127   CORE_ADDR addr, base;
128   int i;
129
130   base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
131   addr = base + 0x18 + 2 * tdep->wordsize;
132   for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize)
133     {
134       int regnum = i + tdep->ppc_gp0_regnum;
135       trad_frame_set_reg_addr (this_cache, regnum, addr);
136     }
137   trad_frame_set_reg_addr (this_cache, tdep->ppc_lr_regnum, addr);
138   addr += tdep->wordsize;
139   trad_frame_set_reg_addr (this_cache, tdep->ppc_cr_regnum, addr);
140   addr += tdep->wordsize;
141   trad_frame_set_reg_addr (this_cache, tdep->ppc_xer_regnum, addr);
142   addr += tdep->wordsize;
143   trad_frame_set_reg_addr (this_cache, tdep->ppc_ctr_regnum, addr);
144   addr += tdep->wordsize;
145   trad_frame_set_reg_addr (this_cache, PC_REGNUM, addr); /* SRR0? */
146   addr += tdep->wordsize;
147
148   /* Construct the frame ID using the function start.  */
149   trad_frame_set_id (this_cache, frame_id_build (base, func));
150 }
151
152 static const struct tramp_frame ppcobsd_sigtramp =
153 {
154   SIGTRAMP_FRAME,
155   4,
156   {
157     { 0x3821fff0, -1 },         /* add r1,r1,-16 */
158     { 0x4e800021, -1 },         /* blrl */
159     { 0x38610018, -1 },         /* addi r3,r1,24 */
160     { 0x38000067, -1 },         /* li r0,103 */
161     { 0x44000002, -1 },         /* sc */
162     { 0x38000001, -1 },         /* li r0,1 */
163     { 0x44000002, -1 },         /* sc */
164     { TRAMP_SENTINEL_INSN, -1 }
165   },
166   ppcobsd_sigtramp_cache_init
167 };
168 \f
169
170 static void
171 ppcobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
172 {
173   /* OpenBSD doesn't support the 128-bit `long double' from the psABI.  */
174   set_gdbarch_long_double_bit (gdbarch, 64);
175   set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
176
177   /* OpenBSD currently uses a broken GCC.  */
178   set_gdbarch_return_value (gdbarch, ppc_sysv_abi_broken_return_value);
179
180   /* OpenBSD uses SVR4-style shared libraries.  */
181   set_solib_svr4_fetch_link_map_offsets
182     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
183
184   set_gdbarch_regset_from_core_section
185     (gdbarch, ppcobsd_regset_from_core_section);
186
187   tramp_frame_prepend_unwinder (gdbarch, &ppcobsd_sigtramp);
188 }
189 \f
190
191 /* OpenBSD uses uses the traditional NetBSD core file format, even for
192    ports that use ELF.  */
193 #define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF
194
195 static enum gdb_osabi
196 ppcobsd_core_osabi_sniffer (bfd *abfd)
197 {
198   if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
199     return GDB_OSABI_NETBSD_CORE;
200
201   return GDB_OSABI_UNKNOWN;
202 }
203 \f
204
205 /* Provide a prototype to silence -Wmissing-prototypes.  */
206 void _initialize_ppcobsd_tdep (void);
207
208 void
209 _initialize_ppcobsd_tdep (void)
210 {
211   /* BFD doesn't set a flavour for NetBSD style a.out core files.  */
212   gdbarch_register_osabi_sniffer (bfd_arch_powerpc, bfd_target_unknown_flavour,
213                                   ppcobsd_core_osabi_sniffer);
214
215   gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_OPENBSD_ELF,
216                           ppcobsd_init_abi);
217   gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_OPENBSD_ELF,
218                           ppcobsd_init_abi);
219
220   /* Avoid initializing the register offsets again if they were
221      already initailized by ppcobsd-nat.c.  */
222   if (ppcobsd_reg_offsets.pc_offset == 0)
223     {
224       /* General-purpose registers.  */
225       ppcobsd_reg_offsets.r0_offset = 0;
226       ppcobsd_reg_offsets.pc_offset = 384;
227       ppcobsd_reg_offsets.ps_offset = 388;
228       ppcobsd_reg_offsets.cr_offset = 392;
229       ppcobsd_reg_offsets.lr_offset = 396;
230       ppcobsd_reg_offsets.ctr_offset = 400;
231       ppcobsd_reg_offsets.xer_offset = 404;
232       ppcobsd_reg_offsets.mq_offset = 408;
233
234       /* Floating-point registers.  */
235       ppcobsd_reg_offsets.f0_offset = 128;
236       ppcobsd_reg_offsets.fpscr_offset = -1;
237
238       /* AltiVec registers.  */
239       ppcobsd_reg_offsets.vr0_offset = 0;
240       ppcobsd_reg_offsets.vscr_offset = 512;
241       ppcobsd_reg_offsets.vrsave_offset = 520;
242     }
243 }