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