No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / gdb6 / gdb / alphanbsd-tdep.c
blobb983327ce884c379fd5dca0c391c139da717548c
1 /* Target-dependent code for NetBSD/Alpha.
3 Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
4 Contributed by Wasabi Systems, Inc.
6 This file is part of GDB.
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.
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.
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., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
23 #include "defs.h"
24 #include "frame.h"
25 #include "gdbcore.h"
26 #include "osabi.h"
27 #include "regcache.h"
28 #include "regset.h"
29 #include "value.h"
30 #include "osabi.h"
31 #include "trad-frame.h"
32 #include "tramp-frame.h"
34 #include "gdb_assert.h"
35 #include "gdb_string.h"
37 #include "alpha-tdep.h"
38 #include "alphabsd-tdep.h"
39 #include "nbsd-tdep.h"
40 #include "solib-svr4.h"
42 /* Core file support. */
44 /* Even though NetBSD/alpha used ELF since day one, it used the
45 traditional a.out-style core dump format before NetBSD 1.6. */
47 /* Sizeof `struct reg' in <machine/reg.h>. */
48 #define ALPHANBSD_SIZEOF_GREGS (32 * 8)
50 /* Sizeof `struct fpreg' in <machine/reg.h. */
51 #define ALPHANBSD_SIZEOF_FPREGS ((32 * 8) + 8)
53 /* Supply register REGNUM from the buffer specified by FPREGS and LEN
54 in the floating-point register set REGSET to register cache
55 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
57 static void
58 alphanbsd_supply_fpregset (const struct regset *regset,
59 struct regcache *regcache,
60 int regnum, const void *fpregs, size_t len)
62 const gdb_byte *regs = fpregs;
63 int i;
65 gdb_assert (len >= ALPHANBSD_SIZEOF_FPREGS);
67 for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; i++)
69 if (regnum == i || regnum == -1)
70 regcache_raw_supply (regcache, i, regs + (i - ALPHA_FP0_REGNUM) * 8);
73 if (regnum == ALPHA_FPCR_REGNUM || regnum == -1)
74 regcache_raw_supply (regcache, ALPHA_FPCR_REGNUM, regs + 32 * 8);
77 /* Supply register REGNUM from the buffer specified by GREGS and LEN
78 in the general-purpose register set REGSET to register cache
79 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
81 static void
82 alphanbsd_supply_gregset (const struct regset *regset,
83 struct regcache *regcache,
84 int regnum, const void *gregs, size_t len)
86 const gdb_byte *regs = gregs;
87 int i;
89 gdb_assert (len >= ALPHANBSD_SIZEOF_GREGS);
91 for (i = 0; i < ALPHA_ZERO_REGNUM; i++)
93 if (regnum == i || regnum == -1)
94 regcache_raw_supply (regcache, i, regs + i * 8);
97 if (regnum == ALPHA_PC_REGNUM || regnum == -1)
98 regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8);
101 /* Supply register REGNUM from the buffer specified by GREGS and LEN
102 in the general-purpose register set REGSET to register cache
103 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
105 static void
106 alphanbsd_aout_supply_gregset (const struct regset *regset,
107 struct regcache *regcache,
108 int regnum, const void *gregs, size_t len)
110 const gdb_byte *regs = gregs;
111 int i;
113 /* Table to map a GDB register number to a trapframe register index. */
114 static const int regmap[] =
116 0, 1, 2, 3,
117 4, 5, 6, 7,
118 8, 9, 10, 11,
119 12, 13, 14, 15,
120 30, 31, 32, 16,
121 17, 18, 19, 20,
122 21, 22, 23, 24,
123 25, 29, 26
126 gdb_assert (len >= ALPHANBSD_SIZEOF_GREGS);
128 for (i = 0; i < ARRAY_SIZE(regmap); i++)
130 if (regnum == i || regnum == -1)
131 regcache_raw_supply (regcache, i, regs + regmap[i] * 8);
134 if (regnum == ALPHA_PC_REGNUM || regnum == -1)
135 regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8);
137 if (len >= ALPHANBSD_SIZEOF_GREGS + ALPHANBSD_SIZEOF_FPREGS)
139 regs += ALPHANBSD_SIZEOF_GREGS;
140 len -= ALPHANBSD_SIZEOF_GREGS;
141 alphanbsd_supply_fpregset (regset, regcache, regnum, regs, len);
145 /* NetBSD/alpha register sets. */
147 static struct regset alphanbsd_gregset =
149 NULL,
150 alphanbsd_supply_gregset
153 static struct regset alphanbsd_fpregset =
155 NULL,
156 alphanbsd_supply_fpregset
159 static struct regset alphanbsd_aout_gregset =
161 NULL,
162 alphanbsd_aout_supply_gregset
165 /* Return the appropriate register set for the core section identified
166 by SECT_NAME and SECT_SIZE. */
168 const struct regset *
169 alphanbsd_regset_from_core_section (struct gdbarch *gdbarch,
170 const char *sect_name, size_t sect_size)
172 if (strcmp (sect_name, ".reg") == 0 && sect_size >= ALPHANBSD_SIZEOF_GREGS)
174 if (sect_size >= ALPHANBSD_SIZEOF_GREGS + ALPHANBSD_SIZEOF_FPREGS)
175 return &alphanbsd_aout_gregset;
176 else
177 return &alphanbsd_gregset;
180 if (strcmp (sect_name, ".reg2") == 0 && sect_size >= ALPHANBSD_SIZEOF_FPREGS)
181 return &alphanbsd_fpregset;
183 return NULL;
186 static void
187 alphanbsd_sigtramp_cache_init (const struct tramp_frame *,
188 struct frame_info *,
189 struct trad_frame_cache *,
190 CORE_ADDR);
192 /* Under NetBSD/alpha signal handler invocations can be identified by the
193 designated code sequence that is used to return from a signal handler.
194 In particular, the return address of a signal handler points to the
195 following code sequences. */
196 static const struct tramp_frame alphanbsd_sigtramp_sc1 =
198 SIGTRAMP_FRAME,
201 { 0xa61e0000, 0xffffffff }, /* ldq a0, 0(sp) */
202 { 0x23de0010, 0xffffffff }, /* lda sp, 16(sp) */
203 { 0x201f0127, 0xffffffff }, /* lda v0, 295 */
204 { 0x00000083, 0xffffffff }, /* call_pal callsys */
205 { TRAMP_SENTINEL_INSN, -1 }
207 alphanbsd_sigtramp_cache_init
210 /* The siginfo signal trampoline for NetBSD/alpha introduced in 2.0 */
211 static const struct tramp_frame alphanbsd_sigtramp_si2 =
213 SIGTRAMP_FRAME,
216 { 0x221e0080, -1 }, /* lda a0,128(sp) */
217 { 0x201f0134, -1 }, /* lda v0,308 */
218 { 0x00000083, -1 }, /* callsys */
219 { 0x47e00410, -1 }, /* mov v0,a0 */
220 { 0x201f0001, -1 }, /* lda v0,1 */
221 { 0x00000083, -1 }, /* callsys */
222 { TRAMP_SENTINEL_INSN, -1 }
224 alphanbsd_sigtramp_cache_init
227 /* The siginfo signal trampoline for NetBSD/alpha introduced in 4.0 */
228 static const struct tramp_frame alphanbsd_sigtramp_si4 =
230 SIGTRAMP_FRAME,
233 { 0x27ba0000, 0xffff0000 },
234 { 0x23bd0000, 0xffff0000 }, /* ldgp gp,0(ra) */
235 { 0x221e0080, -1 }, /* lda a0,128(sp) */
236 { 0x201f0134, -1 }, /* lda v0,308 */
237 { 0x00000083, -1 }, /* callsys */
238 { 0x221fffff, -1 }, /* lda a0,-1 */
239 { 0x201f0001, -1 }, /* lda v0,1 */
240 { 0x00000083, -1 }, /* callsys */
241 { TRAMP_SENTINEL_INSN, -1 }
243 alphanbsd_sigtramp_cache_init
246 static void
247 alphanbsd_sigtramp_cache_init (const struct tramp_frame *self,
248 struct frame_info *next_frame,
249 struct trad_frame_cache *this_cache,
250 CORE_ADDR func)
252 struct gdbarch *gdbarch = get_frame_arch (next_frame);
253 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
254 CORE_ADDR addr, sp;
255 int i;
257 sp = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
259 if (self == &alphanbsd_sigtramp_sc1) {
260 addr = sp;
261 } else {
262 addr = sp + 128 + 56;
265 for (i = 0; i < 32; i++, addr += ALPHA_REGISTER_SIZE)
267 trad_frame_set_reg_addr (this_cache, i, addr);
269 trad_frame_set_reg_addr (this_cache, ALPHA_PC_REGNUM, addr);
271 /* Construct the frame ID using the function start. */
272 trad_frame_set_id (this_cache, frame_id_build (sp, func));
275 static void
276 alphanbsd_init_abi (struct gdbarch_info info,
277 struct gdbarch *gdbarch)
279 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
281 /* Hook into the DWARF CFI frame unwinder. */
282 alpha_dwarf2_init_abi (info, gdbarch);
284 /* Hook into the MDEBUG frame unwinder. */
285 alpha_mdebug_init_abi (info, gdbarch);
287 /* NetBSD/alpha does not provide single step support via ptrace(2); we
288 must use software single-stepping. */
289 set_gdbarch_software_single_step (gdbarch, alpha_software_single_step);
291 /* NetBSD/alpha has SVR4-style shared libraries. */
292 set_solib_svr4_fetch_link_map_offsets
293 (gdbarch, svr4_lp64_fetch_link_map_offsets);
295 tdep->jb_pc = 2;
296 tdep->jb_elt_size = 8;
298 set_gdbarch_regset_from_core_section
299 (gdbarch, alphanbsd_regset_from_core_section);
301 tramp_frame_prepend_unwinder (gdbarch, &alphanbsd_sigtramp_sc1);
302 tramp_frame_prepend_unwinder (gdbarch, &alphanbsd_sigtramp_si2);
303 tramp_frame_prepend_unwinder (gdbarch, &alphanbsd_sigtramp_si4);
306 void
307 _initialize_alphanbsd_tdep (void)
309 gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_NETBSD_ELF,
310 alphanbsd_init_abi);
311 gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_OPENBSD_ELF,
312 alphanbsd_init_abi);