]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/sparc-netbsd-tdep.c
gdb, gdbserver, gdbsupport: remove includes of early headers
[thirdparty/binutils-gdb.git] / gdb / sparc-netbsd-tdep.c
CommitLineData
386c036b
MK
1/* Target-dependent code for NetBSD/sparc.
2
1d506c26 3 Copyright (C) 2002-2024 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
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
9ce5c36a
JT
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/>. */
9ce5c36a 20
386c036b
MK
21#include "frame.h"
22#include "frame-unwind.h"
9ce5c36a 23#include "gdbcore.h"
3e461478 24#include "gdbtypes.h"
9ce5c36a 25#include "osabi.h"
386c036b 26#include "regcache.h"
4e7b0cd3 27#include "regset.h"
386c036b
MK
28#include "solib-svr4.h"
29#include "symtab.h"
30#include "trad-frame.h"
0d12e84c 31#include "gdbarch.h"
9ce5c36a 32
c139e7d9 33#include "sparc-tdep.h"
1b71cfcf 34#include "netbsd-tdep.h"
9ce5c36a 35
c893be75
MK
36/* Macros to extract fields from SPARC instructions. */
37#define X_RS1(i) (((i) >> 14) & 0x1f)
38#define X_RS2(i) ((i) & 0x1f)
39#define X_I(i) (((i) >> 13) & 1)
40
b4fd25c9 41const struct sparc_gregmap sparc32nbsd_gregmap =
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
9ce5c36a 53static void
4e7b0cd3
MK
54sparc32nbsd_supply_gregset (const struct regset *regset,
55 struct regcache *regcache,
56 int regnum, const void *gregs, size_t len)
9ce5c36a 57{
b4fd25c9 58 sparc32_supply_gregset (&sparc32nbsd_gregmap, regcache, regnum, gregs);
c8e737d5
MK
59
60 /* Traditional NetBSD core files don't use multiple register sets.
61 Instead, the general-purpose and floating-point registers are
62 lumped together in a single section. */
63 if (len >= 212)
b4fd25c9 64 sparc32_supply_fpregset (&sparc32_bsd_fpregmap, regcache, regnum,
db75c717 65 (const char *) gregs + 80);
9ce5c36a
JT
66}
67
4e7b0cd3
MK
68static void
69sparc32nbsd_supply_fpregset (const struct regset *regset,
70 struct regcache *regcache,
71 int regnum, const void *fpregs, size_t len)
9ce5c36a 72{
b4fd25c9 73 sparc32_supply_fpregset (&sparc32_bsd_fpregmap, regcache, regnum, fpregs);
4e7b0cd3 74}
9ce5c36a 75
386c036b
MK
76\f
77/* Signal trampolines. */
78
79/* The following variables describe the location of an on-stack signal
80 trampoline. The current values correspond to the memory layout for
81 NetBSD 1.3 and up. These shouldn't be necessary for NetBSD 2.0 and
82 up, since NetBSD uses signal trampolines provided by libc now. */
9ce5c36a 83
386c036b
MK
84static const CORE_ADDR sparc32nbsd_sigtramp_start = 0xeffffef0;
85static const CORE_ADDR sparc32nbsd_sigtramp_end = 0xeffffff0;
9ce5c36a
JT
86
87static int
2c02bd72 88sparc32nbsd_pc_in_sigtramp (CORE_ADDR pc, const char *name)
386c036b
MK
89{
90 if (pc >= sparc32nbsd_sigtramp_start && pc < sparc32nbsd_sigtramp_end)
91 return 1;
92
93 return nbsd_pc_in_sigtramp (pc, name);
94}
95
098caef4 96trad_frame_saved_reg *
8480a37e 97sparc32nbsd_sigcontext_saved_regs (const frame_info_ptr &this_frame)
9ce5c36a 98{
e17a4113 99 struct gdbarch *gdbarch = get_frame_arch (this_frame);
098caef4 100 trad_frame_saved_reg *saved_regs;
386c036b 101 CORE_ADDR addr, sigcontext_addr;
386c036b 102 int regnum, delta;
566626fa 103 ULONGEST psr;
9ce5c36a 104
7ea566be 105 saved_regs = trad_frame_alloc_saved_regs (this_frame);
9ce5c36a 106
566626fa
MK
107 /* We find the appropriate instance of `struct sigcontext' at a
108 fixed offset in the signal frame. */
7ea566be 109 addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM);
566626fa 110 sigcontext_addr = addr + 64 + 16;
9ce5c36a 111
386c036b
MK
112 /* The registers are saved in bits and pieces scattered all over the
113 place. The code below records their location on the assumption
114 that the part of the signal trampoline that saves the state has
115 been executed. */
9ce5c36a 116
098caef4
LM
117 saved_regs[SPARC_SP_REGNUM].set_addr (sigcontext_addr + 8);
118 saved_regs[SPARC32_PC_REGNUM].set_addr (sigcontext_addr + 12);
119 saved_regs[SPARC32_NPC_REGNUM].set_addr (sigcontext_addr + 16);
120 saved_regs[SPARC32_PSR_REGNUM].set_addr (sigcontext_addr + 20);
121 saved_regs[SPARC_G1_REGNUM].set_addr (sigcontext_addr + 24);
122 saved_regs[SPARC_O0_REGNUM].set_addr (sigcontext_addr + 28);
386c036b
MK
123
124 /* The remaining `global' registers and %y are saved in the `local'
125 registers. */
126 delta = SPARC_L0_REGNUM - SPARC_G0_REGNUM;
127 for (regnum = SPARC_G2_REGNUM; regnum <= SPARC_G7_REGNUM; regnum++)
098caef4
LM
128 saved_regs[regnum].set_realreg (regnum + delta);
129 saved_regs[SPARC32_Y_REGNUM].set_realreg (SPARC_L1_REGNUM);
386c036b
MK
130
131 /* The remaining `out' registers can be found in the current frame's
132 `in' registers. */
133 delta = SPARC_I0_REGNUM - SPARC_O0_REGNUM;
134 for (regnum = SPARC_O1_REGNUM; regnum <= SPARC_O5_REGNUM; regnum++)
098caef4
LM
135 saved_regs[regnum].set_realreg (regnum + delta);
136 saved_regs[SPARC_O7_REGNUM].set_realreg (SPARC_I7_REGNUM);
386c036b
MK
137
138 /* The `local' and `in' registers have been saved in the register
139 save area. */
098caef4 140 addr = saved_regs[SPARC_SP_REGNUM].addr ();
7ea566be 141 addr = get_frame_memory_unsigned (this_frame, addr, 4);
386c036b
MK
142 for (regnum = SPARC_L0_REGNUM;
143 regnum <= SPARC_I7_REGNUM; regnum++, addr += 4)
098caef4 144 saved_regs[regnum].set_addr (addr);
386c036b 145
1c800673
MK
146 /* Handle StackGhost. */
147 {
e17a4113 148 ULONGEST wcookie = sparc_fetch_wcookie (gdbarch);
1c800673
MK
149
150 if (wcookie != 0)
151 {
152 ULONGEST i7;
153
098caef4 154 addr = saved_regs[SPARC_I7_REGNUM].addr ();
7ea566be 155 i7 = get_frame_memory_unsigned (this_frame, addr, 4);
a9a87d35 156 saved_regs[SPARC_I7_REGNUM].set_value (i7 ^ wcookie);
1c800673
MK
157 }
158 }
159
386c036b
MK
160 /* The floating-point registers are only saved if the EF bit in %prs
161 has been set. */
162
163#define PSR_EF 0x00001000
164
098caef4 165 addr = saved_regs[SPARC32_PSR_REGNUM].addr ();
7ea566be 166 psr = get_frame_memory_unsigned (this_frame, addr, 4);
386c036b
MK
167 if (psr & PSR_EF)
168 {
169 CORE_ADDR sp;
170
7ea566be 171 sp = get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM);
098caef4 172 saved_regs[SPARC32_FSR_REGNUM].set_addr (sp + 96);
386c036b
MK
173 for (regnum = SPARC_F0_REGNUM, addr = sp + 96 + 8;
174 regnum <= SPARC_F31_REGNUM; regnum++, addr += 4)
098caef4 175 saved_regs[regnum].set_addr (addr);
566626fa
MK
176 }
177
178 return saved_regs;
179}
180
181static struct sparc_frame_cache *
8480a37e 182sparc32nbsd_sigcontext_frame_cache (const frame_info_ptr &this_frame,
566626fa
MK
183 void **this_cache)
184{
185 struct sparc_frame_cache *cache;
186 CORE_ADDR addr;
187
188 if (*this_cache)
19ba03f4 189 return (struct sparc_frame_cache *) *this_cache;
566626fa 190
7ea566be 191 cache = sparc_frame_cache (this_frame, this_cache);
566626fa
MK
192 gdb_assert (cache == *this_cache);
193
194 /* If we couldn't find the frame's function, we're probably dealing
195 with an on-stack signal trampoline. */
196 if (cache->pc == 0)
197 {
198 cache->pc = sparc32nbsd_sigtramp_start;
199
200 /* Since we couldn't find the frame's function, the cache was
dda83cd7 201 initialized under the assumption that we're frameless. */
369c397b 202 sparc_record_save_insn (cache);
7ea566be 203 addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM);
566626fa 204 cache->base = addr;
386c036b
MK
205 }
206
7ea566be 207 cache->saved_regs = sparc32nbsd_sigcontext_saved_regs (this_frame);
566626fa 208
386c036b 209 return cache;
9ce5c36a
JT
210}
211
386c036b 212static void
8480a37e 213sparc32nbsd_sigcontext_frame_this_id (const frame_info_ptr &this_frame,
386c036b
MK
214 void **this_cache,
215 struct frame_id *this_id)
216{
217 struct sparc_frame_cache *cache =
7ea566be 218 sparc32nbsd_sigcontext_frame_cache (this_frame, this_cache);
386c036b
MK
219
220 (*this_id) = frame_id_build (cache->base, cache->pc);
221}
222
7ea566be 223static struct value *
8480a37e 224sparc32nbsd_sigcontext_frame_prev_register (const frame_info_ptr &this_frame,
7ea566be 225 void **this_cache, int regnum)
9ce5c36a 226{
386c036b 227 struct sparc_frame_cache *cache =
7ea566be 228 sparc32nbsd_sigcontext_frame_cache (this_frame, this_cache);
9ce5c36a 229
7ea566be 230 return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
386c036b 231}
9ce5c36a 232
7ea566be
MK
233static int
234sparc32nbsd_sigcontext_frame_sniffer (const struct frame_unwind *self,
8480a37e 235 const frame_info_ptr &this_frame,
7ea566be 236 void **this_cache)
386c036b 237{
7ea566be 238 CORE_ADDR pc = get_frame_pc (this_frame);
2c02bd72 239 const char *name;
9ce5c36a 240
386c036b
MK
241 find_pc_partial_function (pc, &name, NULL, NULL);
242 if (sparc32nbsd_pc_in_sigtramp (pc, name))
243 {
61012eef 244 if (name == NULL || !startswith (name, "__sigtramp_sigcontext"))
7ea566be 245 return 1;
386c036b
MK
246 }
247
7ea566be 248 return 0;
9ce5c36a 249}
7ea566be
MK
250
251static const struct frame_unwind sparc32nbsd_sigcontext_frame_unwind =
252{
a154d838 253 "sparc32 netbsd sigcontext",
7ea566be 254 SIGTRAMP_FRAME,
8fbca658 255 default_frame_unwind_stop_reason,
7ea566be
MK
256 sparc32nbsd_sigcontext_frame_this_id,
257 sparc32nbsd_sigcontext_frame_prev_register,
258 NULL,
259 sparc32nbsd_sigcontext_frame_sniffer
260};
386c036b 261\f
c893be75
MK
262/* Return the address of a system call's alternative return
263 address. */
264
265CORE_ADDR
8480a37e 266sparcnbsd_step_trap (const frame_info_ptr &frame, unsigned long insn)
c893be75
MK
267{
268 if ((X_I (insn) == 0 && X_RS1 (insn) == 0 && X_RS2 (insn) == 0)
269 || (X_I (insn) == 1 && X_RS1 (insn) == 0 && (insn & 0x7f) == 0))
270 {
271 /* "New" system call. */
0b1b3e42 272 ULONGEST number = get_frame_register_unsigned (frame, SPARC_G1_REGNUM);
c893be75
MK
273
274 if (number & 0x400)
0b1b3e42 275 return get_frame_register_unsigned (frame, SPARC_G2_REGNUM);
c893be75 276 if (number & 0x800)
0b1b3e42 277 return get_frame_register_unsigned (frame, SPARC_G7_REGNUM);
c893be75
MK
278 }
279
280 return 0;
281}
282\f
386c036b 283
b13feb94
AA
284static const struct regset sparc32nbsd_gregset =
285 {
286 NULL, sparc32nbsd_supply_gregset, NULL
287 };
288
289static const struct regset sparc32nbsd_fpregset =
290 {
291 NULL, sparc32nbsd_supply_fpregset, NULL
292 };
293
1736a7bd 294void
386c036b 295sparc32nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
9ce5c36a 296{
08106042 297 sparc_gdbarch_tdep *tdep = gdbarch_tdep<sparc_gdbarch_tdep> (gdbarch);
4e7b0cd3 298
79743962
KR
299 nbsd_init_abi (info, gdbarch);
300
386c036b
MK
301 /* NetBSD doesn't support the 128-bit `long double' from the psABI. */
302 set_gdbarch_long_double_bit (gdbarch, 64);
8da61cc4 303 set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
386c036b 304
b13feb94 305 tdep->gregset = &sparc32nbsd_gregset;
c8e737d5 306 tdep->sizeof_gregset = 20 * 4;
4e7b0cd3 307
b13feb94 308 tdep->fpregset = &sparc32nbsd_fpregset;
c8e737d5 309 tdep->sizeof_fpregset = 33 * 4;
4e7b0cd3 310
c893be75
MK
311 /* Make sure we can single-step "new" syscalls. */
312 tdep->step_trap = sparcnbsd_step_trap;
313
7ea566be 314 frame_unwind_append_unwinder (gdbarch, &sparc32nbsd_sigcontext_frame_unwind);
9ce5c36a 315
386c036b 316 set_solib_svr4_fetch_link_map_offsets
be24b061 317 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
9ce5c36a
JT
318}
319
6c265988 320void _initialize_sparcnbsd_tdep ();
9ce5c36a 321void
6c265988 322_initialize_sparcnbsd_tdep ()
9ce5c36a 323{
1736a7bd
PA
324 gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD,
325 sparc32nbsd_init_abi);
9ce5c36a 326}