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