2004-01-12 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / sparcnbsd-tdep.c
CommitLineData
386c036b
MK
1/* Target-dependent code for NetBSD/sparc.
2
3 Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
9ce5c36a
JT
4 Contributed by Wasabi Systems, Inc.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
22
23#include "defs.h"
386c036b
MK
24#include "floatformat.h"
25#include "frame.h"
26#include "frame-unwind.h"
9ce5c36a 27#include "gdbcore.h"
9ce5c36a 28#include "osabi.h"
386c036b 29#include "regcache.h"
4e7b0cd3 30#include "regset.h"
386c036b
MK
31#include "solib-svr4.h"
32#include "symtab.h"
33#include "trad-frame.h"
9ce5c36a 34
386c036b 35#include "gdb_assert.h"
f6ad61e3
MK
36#include "gdb_string.h"
37
c139e7d9 38#include "sparc-tdep.h"
9ce5c36a
JT
39#include "nbsd-tdep.h"
40
386c036b 41const struct sparc_gregset sparc32nbsd_gregset =
9ce5c36a 42{
386c036b
MK
43 0 * 4, /* %psr */
44 1 * 4, /* %pc */
45 2 * 4, /* %npc */
46 3 * 4, /* %y */
47 -1, /* %wim */
48 -1, /* %tbr */
49 5 * 4, /* %g1 */
50 -1 /* %l0 */
51};
9ce5c36a 52
386c036b
MK
53/* Unlike other NetBSD implementations, the SPARC port historically
54 used .reg and .reg2 (see bfd/netbsd-core.c), and as such, we can
55 share one routine for a.out and ELF core files. */
9ce5c36a 56
9ce5c36a 57static void
4e7b0cd3
MK
58sparc32nbsd_supply_gregset (const struct regset *regset,
59 struct regcache *regcache,
60 int regnum, const void *gregs, size_t len)
9ce5c36a 61{
4e7b0cd3 62 sparc32_supply_gregset (regset->descr, regcache, regnum, gregs);
9ce5c36a
JT
63}
64
4e7b0cd3
MK
65static void
66sparc32nbsd_supply_fpregset (const struct regset *regset,
67 struct regcache *regcache,
68 int regnum, const void *fpregs, size_t len)
9ce5c36a 69{
4e7b0cd3
MK
70 sparc32_supply_fpregset (regcache, regnum, fpregs);
71}
9ce5c36a 72
386c036b
MK
73\f
74/* Signal trampolines. */
75
76/* The following variables describe the location of an on-stack signal
77 trampoline. The current values correspond to the memory layout for
78 NetBSD 1.3 and up. These shouldn't be necessary for NetBSD 2.0 and
79 up, since NetBSD uses signal trampolines provided by libc now. */
9ce5c36a 80
386c036b
MK
81static const CORE_ADDR sparc32nbsd_sigtramp_start = 0xeffffef0;
82static const CORE_ADDR sparc32nbsd_sigtramp_end = 0xeffffff0;
9ce5c36a
JT
83
84static int
386c036b
MK
85sparc32nbsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
86{
87 if (pc >= sparc32nbsd_sigtramp_start && pc < sparc32nbsd_sigtramp_end)
88 return 1;
89
90 return nbsd_pc_in_sigtramp (pc, name);
91}
92
93static struct sparc_frame_cache *
94sparc32nbsd_sigcontext_frame_cache (struct frame_info *next_frame,
95 void **this_cache)
9ce5c36a 96{
386c036b
MK
97 struct sparc_frame_cache *cache;
98 CORE_ADDR addr, sigcontext_addr;
99 LONGEST psr;
100 int regnum, delta;
9ce5c36a 101
386c036b
MK
102 if (*this_cache)
103 return *this_cache;
9ce5c36a 104
386c036b
MK
105 cache = sparc_frame_cache (next_frame, this_cache);
106 gdb_assert (cache == *this_cache);
9ce5c36a 107
386c036b
MK
108 /* The registers are saved in bits and pieces scattered all over the
109 place. The code below records their location on the assumption
110 that the part of the signal trampoline that saves the state has
111 been executed. */
9ce5c36a 112
386c036b
MK
113 /* If we couldn't find the frame's function, we're probably dealing
114 with an on-stack signal trampoline. */
115 if (cache->pc == 0)
116 {
117 cache->pc = sparc32nbsd_sigtramp_start;
118
119 /* Since we couldn't find the frame's function, the cache was
120 initialized under the assumption that we're frameless. */
121 cache->frameless_p = 0;
122 addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
123 cache->base = addr;
124 }
125
126 cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
127
128 /* We find the appropriate instance of `struct sigcontext' at a
129 fixed offset in the signal frame. */
130 sigcontext_addr = cache->base + 64 + 16;
131
132 cache->saved_regs[SPARC_SP_REGNUM].addr = sigcontext_addr + 8;
133 cache->saved_regs[SPARC32_PC_REGNUM].addr = sigcontext_addr + 12;
134 cache->saved_regs[SPARC32_NPC_REGNUM].addr = sigcontext_addr + 16;
135 cache->saved_regs[SPARC32_PSR_REGNUM].addr = sigcontext_addr + 20;
136 cache->saved_regs[SPARC_G1_REGNUM].addr = sigcontext_addr + 24;
137 cache->saved_regs[SPARC_O0_REGNUM].addr = sigcontext_addr + 28;
138
139 /* The remaining `global' registers and %y are saved in the `local'
140 registers. */
141 delta = SPARC_L0_REGNUM - SPARC_G0_REGNUM;
142 for (regnum = SPARC_G2_REGNUM; regnum <= SPARC_G7_REGNUM; regnum++)
143 cache->saved_regs[regnum].realreg = regnum + delta;
144 cache->saved_regs[SPARC32_Y_REGNUM].realreg = SPARC_L1_REGNUM;
145
146 /* The remaining `out' registers can be found in the current frame's
147 `in' registers. */
148 delta = SPARC_I0_REGNUM - SPARC_O0_REGNUM;
149 for (regnum = SPARC_O1_REGNUM; regnum <= SPARC_O5_REGNUM; regnum++)
150 cache->saved_regs[regnum].realreg = regnum + delta;
151 cache->saved_regs[SPARC_O7_REGNUM].realreg = SPARC_I7_REGNUM;
152
153 /* The `local' and `in' registers have been saved in the register
154 save area. */
155 addr = cache->saved_regs[SPARC_SP_REGNUM].addr;
156 addr = get_frame_memory_unsigned (next_frame, addr, 4);
157 for (regnum = SPARC_L0_REGNUM;
158 regnum <= SPARC_I7_REGNUM; regnum++, addr += 4)
159 cache->saved_regs[regnum].addr = addr;
160
161 /* The floating-point registers are only saved if the EF bit in %prs
162 has been set. */
163
164#define PSR_EF 0x00001000
165
166 addr = cache->saved_regs[SPARC32_PSR_REGNUM].addr;
167 psr = get_frame_memory_unsigned (next_frame, addr, 4);
168 if (psr & PSR_EF)
169 {
170 CORE_ADDR sp;
171
172 sp = frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM);
173 cache->saved_regs[SPARC32_FSR_REGNUM].addr = sp + 96;
174 for (regnum = SPARC_F0_REGNUM, addr = sp + 96 + 8;
175 regnum <= SPARC_F31_REGNUM; regnum++, addr += 4)
176 cache->saved_regs[regnum].addr = addr;
177 }
178
179 return cache;
9ce5c36a
JT
180}
181
386c036b
MK
182static void
183sparc32nbsd_sigcontext_frame_this_id (struct frame_info *next_frame,
184 void **this_cache,
185 struct frame_id *this_id)
186{
187 struct sparc_frame_cache *cache =
188 sparc32nbsd_sigcontext_frame_cache (next_frame, this_cache);
189
190 (*this_id) = frame_id_build (cache->base, cache->pc);
191}
192
193static void
194sparc32nbsd_sigcontext_frame_prev_register (struct frame_info *next_frame,
195 void **this_cache,
196 int regnum, int *optimizedp,
197 enum lval_type *lvalp,
198 CORE_ADDR *addrp,
199 int *realnump, void *valuep)
9ce5c36a 200{
386c036b
MK
201 struct sparc_frame_cache *cache =
202 sparc32nbsd_sigcontext_frame_cache (next_frame, this_cache);
9ce5c36a 203
386c036b
MK
204 trad_frame_prev_register (next_frame, cache->saved_regs, regnum,
205 optimizedp, lvalp, addrp, realnump, valuep);
206}
9ce5c36a 207
386c036b
MK
208static const struct frame_unwind sparc32nbsd_sigcontext_frame_unwind =
209{
210 SIGTRAMP_FRAME,
211 sparc32nbsd_sigcontext_frame_this_id,
212 sparc32nbsd_sigcontext_frame_prev_register
213};
9ce5c36a 214
386c036b
MK
215static const struct frame_unwind *
216sparc32nbsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
217{
218 CORE_ADDR pc = frame_pc_unwind (next_frame);
219 char *name;
9ce5c36a 220
386c036b
MK
221 find_pc_partial_function (pc, &name, NULL, NULL);
222 if (sparc32nbsd_pc_in_sigtramp (pc, name))
223 {
224 if (name == NULL || strncmp (name, "__sigtramp_sigcontext", 21))
225 return &sparc32nbsd_sigcontext_frame_unwind;
226 }
227
228 return NULL;
9ce5c36a 229}
386c036b
MK
230\f
231
232/* Return non-zero if we are in a shared library trampoline code stub. */
9ce5c36a
JT
233
234static int
235sparcnbsd_aout_in_solib_call_trampoline (CORE_ADDR pc, char *name)
236{
386c036b 237 return (name && !strcmp (name, "_DYNAMIC"));
9ce5c36a
JT
238}
239
240static void
386c036b 241sparc32nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
9ce5c36a 242{
4e7b0cd3
MK
243 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
244
386c036b
MK
245 /* NetBSD doesn't support the 128-bit `long double' from the psABI. */
246 set_gdbarch_long_double_bit (gdbarch, 64);
247 set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
248
4e7b0cd3
MK
249 tdep->gregset = XMALLOC (struct regset);
250 tdep->gregset->descr = &sparc32nbsd_gregset;
251 tdep->gregset->supply_regset = sparc32nbsd_supply_gregset;
252
253 tdep->fpregset = XMALLOC (struct regset);
254 tdep->fpregset->supply_regset = sparc32nbsd_supply_fpregset;
255
386c036b
MK
256 set_gdbarch_pc_in_sigtramp (gdbarch, sparc32nbsd_pc_in_sigtramp);
257 frame_unwind_append_sniffer (gdbarch, sparc32nbsd_sigtramp_frame_sniffer);
9ce5c36a
JT
258}
259
260static void
386c036b 261sparc32nbsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
9ce5c36a 262{
386c036b 263 sparc32nbsd_init_abi (info, gdbarch);
9ce5c36a 264
386c036b
MK
265 set_gdbarch_in_solib_call_trampoline
266 (gdbarch, sparcnbsd_aout_in_solib_call_trampoline);
9ce5c36a
JT
267}
268
269static void
386c036b 270sparc32nbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
9ce5c36a 271{
386c036b 272 sparc32nbsd_init_abi (info, gdbarch);
9ce5c36a 273
386c036b
MK
274 set_solib_svr4_fetch_link_map_offsets
275 (gdbarch, nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
9ce5c36a
JT
276}
277
278static enum gdb_osabi
279sparcnbsd_aout_osabi_sniffer (bfd *abfd)
280{
281 if (strcmp (bfd_get_target (abfd), "a.out-sparc-netbsd") == 0)
282 return GDB_OSABI_NETBSD_AOUT;
283
284 return GDB_OSABI_UNKNOWN;
285}
286
386c036b
MK
287\f
288/* Provide a prototype to silence -Wmissing-prototypes. */
289void _initialize_sparcnbsd_tdep (void);
290
9ce5c36a
JT
291void
292_initialize_sparnbsd_tdep (void)
293{
294 gdbarch_register_osabi_sniffer (bfd_arch_sparc, bfd_target_aout_flavour,
295 sparcnbsd_aout_osabi_sniffer);
296
05816f70 297 gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD_AOUT,
386c036b 298 sparc32nbsd_aout_init_abi);
05816f70 299 gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD_ELF,
386c036b 300 sparc32nbsd_elf_init_abi);
9ce5c36a 301}
This page took 0.404568 seconds and 4 git commands to generate.