2005-07-13 Eric Christopher <echristo@redhat.com>
[deliverable/binutils-gdb.git] / gdb / ppcobsd-tdep.c
CommitLineData
d195bc9f
MK
1/* Target-dependent code for OpenBSD/powerpc.
2
18b2ae85 3 Copyright 2004, 2005 Free Software Foundation, Inc.
d195bc9f
MK
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"
5a49dfd0 24#include "floatformat.h"
d195bc9f
MK
25#include "osabi.h"
26#include "regcache.h"
27#include "regset.h"
18b2ae85
MK
28#include "trad-frame.h"
29#include "tramp-frame.h"
d195bc9f 30
18b2ae85 31#include "gdb_assert.h"
d195bc9f
MK
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>. */
39struct 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
48void
49ppcobsd_supply_gregset (const struct regset *regset,
50 struct regcache *regcache, int regnum,
51 const void *gregs, size_t len)
52{
383f0f5b
JB
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
d195bc9f
MK
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
74void
75ppcobsd_collect_gregset (const struct regset *regset,
76 const struct regcache *regcache, int regnum,
77 void *gregs, size_t len)
78{
383f0f5b
JB
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
d195bc9f
MK
91 ppc_collect_gregset (regset, regcache, regnum, gregs, len);
92 ppc_collect_fpregset (regset, regcache, regnum, gregs, len);
93}
94
5d6210f0 95/* OpenBSD/powerpc register set. */
d195bc9f
MK
96
97struct 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
106static const struct regset *
107ppcobsd_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
18b2ae85
MK
117/* Signal trampolines. */
118
119static void
120ppcobsd_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
152static 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};
18b2ae85 168\f
5d6210f0 169
d195bc9f
MK
170static void
171ppcobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
172{
5a49dfd0
MK
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
a86c5ab2
MK
177 /* OpenBSD currently uses a broken GCC. */
178 set_gdbarch_return_value (gdbarch, ppc_sysv_abi_broken_return_value);
179
d195bc9f 180 /* OpenBSD uses SVR4-style shared libraries. */
d195bc9f
MK
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);
18b2ae85
MK
186
187 tramp_frame_prepend_unwinder (gdbarch, &ppcobsd_sigtramp);
d195bc9f
MK
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
195static enum gdb_osabi
196ppcobsd_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. */
206void _initialize_ppcobsd_tdep (void);
207
208void
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
5d6210f0
MK
215 gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_OPENBSD_ELF,
216 ppcobsd_init_abi);
d195bc9f
MK
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}
This page took 0.144854 seconds and 4 git commands to generate.