ppc-netbsd-tdep.c revision 1.1 1 /* Target-dependent code for NetBSD/powerpc.
2
3 Copyright (C) 2002-2023 Free Software Foundation, Inc.
4
5 Contributed by Wasabi Systems, Inc.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22 #include "defs.h"
23 #include "gdbtypes.h"
24 #include "osabi.h"
25 #include "regcache.h"
26 #include "regset.h"
27 #include "trad-frame.h"
28 #include "tramp-frame.h"
29
30 #include "ppc-tdep.h"
31 #include "netbsd-tdep.h"
32 #include "ppc-netbsd-tdep.h"
33 #include "ppc-tdep.h"
34 #include "solib-svr4.h"
35
36 /* Register offsets from <machine/reg.h>. */
37 static ppc_reg_offsets ppcnbsd_reg_offsets;
38
39
41 /* Core file support. */
42
43 /* NetBSD/powerpc register sets. */
44
45 const struct regset ppcnbsd_gregset =
46 {
47 &ppcnbsd_reg_offsets,
48 ppc_supply_gregset
49 };
50
51 const struct regset ppcnbsd_fpregset =
52 {
53 &ppcnbsd_reg_offsets,
54 ppc_supply_fpregset
55 };
56
57 /* Iterate over core file register note sections. */
58
59 static void
60 ppcnbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
61 iterate_over_regset_sections_cb *cb,
62 void *cb_data,
63 const struct regcache *regcache)
64 {
65 cb (".reg", 148, 148, &ppcnbsd_gregset, NULL, cb_data);
66 cb (".reg2", 264, 264, &ppcnbsd_fpregset, NULL, cb_data);
67 }
68
69
71 /* NetBSD is confused. It appears that 1.5 was using the correct SVR4
72 convention but, 1.6 switched to the below broken convention. For
73 the moment use the broken convention. Ulgh! */
74
75 static enum return_value_convention
76 ppcnbsd_return_value (struct gdbarch *gdbarch, struct value *function,
77 struct type *valtype, struct regcache *regcache,
78 gdb_byte *readbuf, const gdb_byte *writebuf)
79 {
80 #if 0
81 if ((valtype->code () == TYPE_CODE_STRUCT
82 || valtype->code () == TYPE_CODE_UNION)
83 && !((valtype->length () == 16 || valtype->length () == 8)
84 && valtype->is_vector ())
85 && !(valtype->length () == 1
86 || valtype->length () == 2
87 || valtype->length () == 4
88 || valtype->length () == 8))
89 return RETURN_VALUE_STRUCT_CONVENTION;
90 else
91 #endif
92 return ppc_sysv_abi_broken_return_value (gdbarch, function, valtype,
93 regcache, readbuf, writebuf);
94 }
95
96
98 /* Signal trampolines. */
99
100 extern const struct tramp_frame ppcnbsd2_sigtramp;
101
102 static void
103 ppcnbsd_sigtramp_cache_init (const struct tramp_frame *self,
104 frame_info_ptr this_frame,
105 struct trad_frame_cache *this_cache,
106 CORE_ADDR func)
107 {
108 struct gdbarch *gdbarch = get_frame_arch (this_frame);
109 ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
110 CORE_ADDR addr, base;
111 int i;
112
113 base = get_frame_register_unsigned (this_frame,
114 gdbarch_sp_regnum (gdbarch));
115 if (self == &ppcnbsd2_sigtramp)
116 addr = base + 0x10 + 2 * tdep->wordsize;
117 else
118 addr = base + 0x18 + 2 * tdep->wordsize;
119 for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize)
120 {
121 int regnum = i + tdep->ppc_gp0_regnum;
122 trad_frame_set_reg_addr (this_cache, regnum, addr);
123 }
124 trad_frame_set_reg_addr (this_cache, tdep->ppc_lr_regnum, addr);
125 addr += tdep->wordsize;
126 trad_frame_set_reg_addr (this_cache, tdep->ppc_cr_regnum, addr);
127 addr += tdep->wordsize;
128 trad_frame_set_reg_addr (this_cache, tdep->ppc_xer_regnum, addr);
129 addr += tdep->wordsize;
130 trad_frame_set_reg_addr (this_cache, tdep->ppc_ctr_regnum, addr);
131 addr += tdep->wordsize;
132 trad_frame_set_reg_addr (this_cache, gdbarch_pc_regnum (gdbarch),
133 addr); /* SRR0? */
134 addr += tdep->wordsize;
135
136 /* Construct the frame ID using the function start. */
137 trad_frame_set_id (this_cache, frame_id_build (base, func));
138 }
139
140 static const struct tramp_frame ppcnbsd_sigtramp =
141 {
142 SIGTRAMP_FRAME,
143 4,
144 {
145 { 0x3821fff0, ULONGEST_MAX }, /* add r1,r1,-16 */
146 { 0x4e800021, ULONGEST_MAX }, /* blrl */
147 { 0x38610018, ULONGEST_MAX }, /* addi r3,r1,24 */
148 { 0x38000127, ULONGEST_MAX }, /* li r0,295 */
149 { 0x44000002, ULONGEST_MAX }, /* sc */
150 { 0x38000001, ULONGEST_MAX }, /* li r0,1 */
151 { 0x44000002, ULONGEST_MAX }, /* sc */
152 { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
153 },
154 ppcnbsd_sigtramp_cache_init
155 };
156
157 /* NetBSD 2.0 introduced a slightly different signal trampoline. */
158
159 const struct tramp_frame ppcnbsd2_sigtramp =
160 {
161 SIGTRAMP_FRAME,
162 4,
163 {
164 { 0x3821fff0, ULONGEST_MAX }, /* add r1,r1,-16 */
165 { 0x4e800021, ULONGEST_MAX }, /* blrl */
166 { 0x38610010, ULONGEST_MAX }, /* addi r3,r1,16 */
167 { 0x38000127, ULONGEST_MAX }, /* li r0,295 */
168 { 0x44000002, ULONGEST_MAX }, /* sc */
169 { 0x38000001, ULONGEST_MAX }, /* li r0,1 */
170 { 0x44000002, ULONGEST_MAX }, /* sc */
171 { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
172 },
173 ppcnbsd_sigtramp_cache_init
174 };
175
176
178 static void
179 ppcnbsd_init_abi (struct gdbarch_info info,
180 struct gdbarch *gdbarch)
181 {
182 nbsd_init_abi (info, gdbarch);
183
184 /* NetBSD doesn't support the 128-bit `long double' from the psABI. */
185 set_gdbarch_long_double_bit (gdbarch, 64);
186 set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
187
188 /* For NetBSD, this is an on again, off again thing. Some systems
189 do use the broken struct convention, and some don't. */
190 set_gdbarch_return_value (gdbarch, ppcnbsd_return_value);
191
192 /* NetBSD uses SVR4-style shared libraries. */
193 set_solib_svr4_fetch_link_map_offsets
194 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
195
196 set_gdbarch_iterate_over_regset_sections
197 (gdbarch, ppcnbsd_iterate_over_regset_sections);
198
199 tramp_frame_prepend_unwinder (gdbarch, &ppcnbsd_sigtramp);
200 tramp_frame_prepend_unwinder (gdbarch, &ppcnbsd2_sigtramp);
201 }
202
203 void _initialize_ppcnbsd_tdep ();
204 void
205 _initialize_ppcnbsd_tdep ()
206 {
207 gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_NETBSD,
208 ppcnbsd_init_abi);
209
210 /* Register NetBSD OSABI also for rs6000, which is default target
211 used before any executable image is loaded. */
212 gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_NETBSD,
213 ppcnbsd_init_abi);
214
215 /* Avoid initializing the register offsets again if they were
216 already initialized by ppc-netbsd-nat.c. */
217 if (ppcnbsd_reg_offsets.pc_offset == 0)
218 {
219 /* General-purpose registers. */
220 ppcnbsd_reg_offsets.r0_offset = 0;
221 ppcnbsd_reg_offsets.gpr_size = 4;
222 ppcnbsd_reg_offsets.xr_size = 4;
223 ppcnbsd_reg_offsets.lr_offset = 128;
224 ppcnbsd_reg_offsets.cr_offset = 132;
225 ppcnbsd_reg_offsets.xer_offset = 136;
226 ppcnbsd_reg_offsets.ctr_offset = 140;
227 ppcnbsd_reg_offsets.pc_offset = 144;
228 ppcnbsd_reg_offsets.ps_offset = -1;
229 ppcnbsd_reg_offsets.mq_offset = -1;
230
231 /* Floating-point registers. */
232 ppcnbsd_reg_offsets.f0_offset = 0;
233 ppcnbsd_reg_offsets.fpscr_offset = 256;
234 ppcnbsd_reg_offsets.fpscr_size = 4;
235
236 }
237 }
238