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