gdb/
[deliverable/binutils-gdb.git] / gdb / sparc64fbsd-tdep.c
CommitLineData
8b39fe56
MK
1/* Target-dependent code for FreeBSD/sparc64.
2
4c38e0a4 3 Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010
0fb0cc75 4 Free Software Foundation, Inc.
8b39fe56
MK
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
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
8b39fe56
MK
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
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
8b39fe56
MK
20
21#include "defs.h"
386c036b
MK
22#include "frame.h"
23#include "frame-unwind.h"
8b39fe56
MK
24#include "gdbcore.h"
25#include "osabi.h"
26#include "regcache.h"
762c360d 27#include "regset.h"
8b39fe56 28#include "target.h"
386c036b 29#include "trad-frame.h"
8b39fe56 30
386c036b 31#include "gdb_assert.h"
8b39fe56
MK
32#include "gdb_string.h"
33
34#include "sparc64-tdep.h"
9e07977b 35#include "solib-svr4.h"
8b39fe56
MK
36
37/* From <machine/reg.h>. */
386c036b 38const struct sparc_gregset sparc64fbsd_gregset =
8b39fe56 39{
386c036b
MK
40 26 * 8, /* "tstate" */
41 25 * 8, /* %pc */
42 24 * 8, /* %npc */
43 28 * 8, /* %y */
44 16 * 8, /* %fprs */
45 -1,
46 1 * 8, /* %g1 */
47 -1, /* %l0 */
48 8 /* sizeof (%y) */
49};
8b39fe56
MK
50\f
51
52static void
762c360d
MK
53sparc64fbsd_supply_gregset (const struct regset *regset,
54 struct regcache *regcache,
55 int regnum, const void *gregs, size_t len)
8b39fe56 56{
9ea75c57 57 sparc64_supply_gregset (&sparc64fbsd_gregset, regcache, regnum, gregs);
8b39fe56
MK
58}
59
ae036357
MK
60static void
61sparc64fbsd_collect_gregset (const struct regset *regset,
62 const struct regcache *regcache,
63 int regnum, void *gregs, size_t len)
64{
65 sparc64_collect_gregset (&sparc64fbsd_gregset, regcache, regnum, gregs);
66}
67
762c360d
MK
68static void
69sparc64fbsd_supply_fpregset (const struct regset *regset,
70 struct regcache *regcache,
71 int regnum, const void *fpregs, size_t len)
8b39fe56 72{
762c360d
MK
73 sparc64_supply_fpregset (regcache, regnum, fpregs);
74}
ae036357
MK
75
76static void
77sparc64fbsd_collect_fpregset (const struct regset *regset,
78 const struct regcache *regcache,
79 int regnum, void *fpregs, size_t len)
80{
81 sparc64_collect_fpregset (regcache, regnum, fpregs);
82}
8b39fe56
MK
83\f
84
386c036b
MK
85/* Signal trampolines. */
86
87static int
88sparc64fbsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
89{
90 return (name && strcmp (name, "__sigtramp") == 0);
91}
92
93static struct sparc_frame_cache *
94afd7a6 94sparc64fbsd_sigtramp_frame_cache (struct frame_info *this_frame,
386c036b
MK
95 void **this_cache)
96{
97 struct sparc_frame_cache *cache;
98 CORE_ADDR addr, mcontext_addr, sp;
99 LONGEST fprs;
100 int regnum;
101
102 if (*this_cache)
103 return *this_cache;
104
94afd7a6 105 cache = sparc_frame_cache (this_frame, this_cache);
386c036b
MK
106 gdb_assert (cache == *this_cache);
107
94afd7a6 108 cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
386c036b
MK
109
110 /* The third argument is a pointer to an instance of `ucontext_t',
111 which has a member `uc_mcontext' that contains the saved
112 registers. */
94afd7a6 113 addr = get_frame_register_unsigned (this_frame, SPARC_O2_REGNUM);
386c036b
MK
114 mcontext_addr = addr + 64;
115
116 /* The following registers travel in the `mc_local' slots of
117 `mcontext_t'. */
118 addr = mcontext_addr + 16 * 8;
119 cache->saved_regs[SPARC64_FPRS_REGNUM].addr = addr + 0 * 8;
120 cache->saved_regs[SPARC64_FSR_REGNUM].addr = addr + 1 * 8;
121
122 /* The following registers travel in the `mc_in' slots of
123 `mcontext_t'. */
124 addr = mcontext_addr + 24 * 8;
125 cache->saved_regs[SPARC64_NPC_REGNUM].addr = addr + 0 * 8;
126 cache->saved_regs[SPARC64_PC_REGNUM].addr = addr + 1 * 8;
127 cache->saved_regs[SPARC64_STATE_REGNUM].addr = addr + 2 * 8;
128 cache->saved_regs[SPARC64_Y_REGNUM].addr = addr + 4 * 8;
129
130 /* The `global' and `out' registers travel in the `mc_global' and
131 `mc_out' slots of `mcontext_t', except for %g0. Since %g0 is
132 always zero, keep the identity encoding. */
133 for (regnum = SPARC_G1_REGNUM, addr = mcontext_addr + 8;
134 regnum <= SPARC_O7_REGNUM; regnum++, addr += 8)
135 cache->saved_regs[regnum].addr = addr;
136
137 /* The `local' and `in' registers have been saved in the register
138 save area. */
139 addr = cache->saved_regs[SPARC_SP_REGNUM].addr;
94afd7a6 140 sp = get_frame_memory_unsigned (this_frame, addr, 8);
386c036b
MK
141 for (regnum = SPARC_L0_REGNUM, addr = sp + BIAS;
142 regnum <= SPARC_I7_REGNUM; regnum++, addr += 8)
143 cache->saved_regs[regnum].addr = addr;
144
145 /* The floating-point registers are only saved if the FEF bit in
146 %fprs has been set. */
147
148#define FPRS_FEF (1 << 2)
149
150 addr = cache->saved_regs[SPARC64_FPRS_REGNUM].addr;
94afd7a6 151 fprs = get_frame_memory_unsigned (this_frame, addr, 8);
386c036b
MK
152 if (fprs & FPRS_FEF)
153 {
154 for (regnum = SPARC_F0_REGNUM, addr = mcontext_addr + 32 * 8;
155 regnum <= SPARC_F31_REGNUM; regnum++, addr += 4)
156 cache->saved_regs[regnum].addr = addr;
157
158 for (regnum = SPARC64_F32_REGNUM;
159 regnum <= SPARC64_F62_REGNUM; regnum++, addr += 8)
160 cache->saved_regs[regnum].addr = addr;
161 }
162
163 return cache;
164}
165
166static void
94afd7a6 167sparc64fbsd_sigtramp_frame_this_id (struct frame_info *this_frame,
386c036b
MK
168 void **this_cache,
169 struct frame_id *this_id)
170{
171 struct sparc_frame_cache *cache =
94afd7a6 172 sparc64fbsd_sigtramp_frame_cache (this_frame, this_cache);
386c036b
MK
173
174 (*this_id) = frame_id_build (cache->base, cache->pc);
175}
176
94afd7a6
UW
177static struct value *
178sparc64fbsd_sigtramp_frame_prev_register (struct frame_info *this_frame,
179 void **this_cache, int regnum)
386c036b
MK
180{
181 struct sparc_frame_cache *cache =
94afd7a6 182 sparc64fbsd_sigtramp_frame_cache (this_frame, this_cache);
386c036b 183
94afd7a6 184 return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
386c036b
MK
185}
186
94afd7a6
UW
187static int
188sparc64fbsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
189 struct frame_info *this_frame,
190 void **this_cache)
386c036b 191{
94afd7a6 192 CORE_ADDR pc = get_frame_pc (this_frame);
386c036b
MK
193 char *name;
194
195 find_pc_partial_function (pc, &name, NULL, NULL);
196 if (sparc64fbsd_pc_in_sigtramp (pc, name))
94afd7a6 197 return 1;
386c036b 198
94afd7a6 199 return 0;
386c036b 200}
94afd7a6
UW
201
202static const struct frame_unwind sparc64fbsd_sigtramp_frame_unwind =
203{
204 SIGTRAMP_FRAME,
205 sparc64fbsd_sigtramp_frame_this_id,
206 sparc64fbsd_sigtramp_frame_prev_register,
207 NULL,
208 sparc64fbsd_sigtramp_frame_sniffer
209};
386c036b
MK
210\f
211
8b39fe56
MK
212static void
213sparc64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
214{
762c360d
MK
215 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
216
ae036357
MK
217 tdep->gregset = regset_alloc (gdbarch, sparc64fbsd_supply_gregset,
218 sparc64fbsd_collect_gregset);
762c360d
MK
219 tdep->sizeof_gregset = 256;
220
ae036357
MK
221 tdep->fpregset = regset_alloc (gdbarch, sparc64fbsd_supply_fpregset,
222 sparc64fbsd_collect_fpregset);
762c360d
MK
223 tdep->sizeof_fpregset = 272;
224
94afd7a6 225 frame_unwind_append_unwinder (gdbarch, &sparc64fbsd_sigtramp_frame_unwind);
386c036b
MK
226
227 sparc64_init_abi (info, gdbarch);
9e07977b
MK
228
229 /* FreeBSD/sparc64 has SVR4-style shared libraries. */
230 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
231 set_solib_svr4_fetch_link_map_offsets
232 (gdbarch, svr4_lp64_fetch_link_map_offsets);
8b39fe56
MK
233}
234
235/* Provide a prototype to silence -Wmissing-prototypes. */
236void _initialize_sparc64fbsd_tdep (void);
237
238void
239_initialize_sparc64fbsd_tdep (void)
240{
241 gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
242 GDB_OSABI_FREEBSD_ELF, sparc64fbsd_init_abi);
8b39fe56 243}
This page took 0.761934 seconds and 4 git commands to generate.