Change regcache list to be an hash map
[deliverable/binutils-gdb.git] / gdb / ppc-nbsd-tdep.c
1 /* Target-dependent code for NetBSD/powerpc.
2
3 Copyright (C) 2002-2020 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 "nbsd-tdep.h"
32 #include "ppc-tdep.h"
33 #include "solib-svr4.h"
34
35 /* Register offsets from <machine/reg.h>. */
36 struct ppc_reg_offsets ppcnbsd_reg_offsets;
37 \f
38
39 /* Core file support. */
40
41 /* NetBSD/powerpc register sets. */
42
43 const struct regset ppcnbsd_gregset =
44 {
45 &ppcnbsd_reg_offsets,
46 ppc_supply_gregset
47 };
48
49 const struct regset ppcnbsd_fpregset =
50 {
51 &ppcnbsd_reg_offsets,
52 ppc_supply_fpregset
53 };
54
55 /* Iterate over core file register note sections. */
56
57 static void
58 ppcnbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
59 iterate_over_regset_sections_cb *cb,
60 void *cb_data,
61 const struct regcache *regcache)
62 {
63 cb (".reg", 148, 148, &ppcnbsd_gregset, NULL, cb_data);
64 cb (".reg2", 264, 264, &ppcnbsd_fpregset, NULL, cb_data);
65 }
66 \f
67
68 /* NetBSD is confused. It appears that 1.5 was using the correct SVR4
69 convention but, 1.6 switched to the below broken convention. For
70 the moment use the broken convention. Ulgh! */
71
72 static enum return_value_convention
73 ppcnbsd_return_value (struct gdbarch *gdbarch, struct value *function,
74 struct type *valtype, struct regcache *regcache,
75 gdb_byte *readbuf, const gdb_byte *writebuf)
76 {
77 #if 0
78 if ((valtype->code () == TYPE_CODE_STRUCT
79 || valtype->code () == TYPE_CODE_UNION)
80 && !((TYPE_LENGTH (valtype) == 16 || TYPE_LENGTH (valtype) == 8)
81 && TYPE_VECTOR (valtype))
82 && !(TYPE_LENGTH (valtype) == 1
83 || TYPE_LENGTH (valtype) == 2
84 || TYPE_LENGTH (valtype) == 4
85 || TYPE_LENGTH (valtype) == 8))
86 return RETURN_VALUE_STRUCT_CONVENTION;
87 else
88 #endif
89 return ppc_sysv_abi_broken_return_value (gdbarch, function, valtype,
90 regcache, readbuf, writebuf);
91 }
92 \f
93
94 /* Signal trampolines. */
95
96 extern const struct tramp_frame ppcnbsd2_sigtramp;
97
98 static void
99 ppcnbsd_sigtramp_cache_init (const struct tramp_frame *self,
100 struct frame_info *this_frame,
101 struct trad_frame_cache *this_cache,
102 CORE_ADDR func)
103 {
104 struct gdbarch *gdbarch = get_frame_arch (this_frame);
105 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
106 CORE_ADDR addr, base;
107 int i;
108
109 base = get_frame_register_unsigned (this_frame,
110 gdbarch_sp_regnum (gdbarch));
111 if (self == &ppcnbsd2_sigtramp)
112 addr = base + 0x10 + 2 * tdep->wordsize;
113 else
114 addr = base + 0x18 + 2 * tdep->wordsize;
115 for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize)
116 {
117 int regnum = i + tdep->ppc_gp0_regnum;
118 trad_frame_set_reg_addr (this_cache, regnum, addr);
119 }
120 trad_frame_set_reg_addr (this_cache, tdep->ppc_lr_regnum, addr);
121 addr += tdep->wordsize;
122 trad_frame_set_reg_addr (this_cache, tdep->ppc_cr_regnum, addr);
123 addr += tdep->wordsize;
124 trad_frame_set_reg_addr (this_cache, tdep->ppc_xer_regnum, addr);
125 addr += tdep->wordsize;
126 trad_frame_set_reg_addr (this_cache, tdep->ppc_ctr_regnum, addr);
127 addr += tdep->wordsize;
128 trad_frame_set_reg_addr (this_cache, gdbarch_pc_regnum (gdbarch),
129 addr); /* SRR0? */
130 addr += tdep->wordsize;
131
132 /* Construct the frame ID using the function start. */
133 trad_frame_set_id (this_cache, frame_id_build (base, func));
134 }
135
136 static const struct tramp_frame ppcnbsd_sigtramp =
137 {
138 SIGTRAMP_FRAME,
139 4,
140 {
141 { 0x3821fff0, ULONGEST_MAX }, /* add r1,r1,-16 */
142 { 0x4e800021, ULONGEST_MAX }, /* blrl */
143 { 0x38610018, ULONGEST_MAX }, /* addi r3,r1,24 */
144 { 0x38000127, ULONGEST_MAX }, /* li r0,295 */
145 { 0x44000002, ULONGEST_MAX }, /* sc */
146 { 0x38000001, ULONGEST_MAX }, /* li r0,1 */
147 { 0x44000002, ULONGEST_MAX }, /* sc */
148 { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
149 },
150 ppcnbsd_sigtramp_cache_init
151 };
152
153 /* NetBSD 2.0 introduced a slightly different signal trampoline. */
154
155 const struct tramp_frame ppcnbsd2_sigtramp =
156 {
157 SIGTRAMP_FRAME,
158 4,
159 {
160 { 0x3821fff0, ULONGEST_MAX }, /* add r1,r1,-16 */
161 { 0x4e800021, ULONGEST_MAX }, /* blrl */
162 { 0x38610010, ULONGEST_MAX }, /* addi r3,r1,16 */
163 { 0x38000127, ULONGEST_MAX }, /* li r0,295 */
164 { 0x44000002, ULONGEST_MAX }, /* sc */
165 { 0x38000001, ULONGEST_MAX }, /* li r0,1 */
166 { 0x44000002, ULONGEST_MAX }, /* sc */
167 { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
168 },
169 ppcnbsd_sigtramp_cache_init
170 };
171 \f
172
173 static void
174 ppcnbsd_init_abi (struct gdbarch_info info,
175 struct gdbarch *gdbarch)
176 {
177 nbsd_init_abi (info, gdbarch);
178
179 /* For NetBSD, this is an on again, off again thing. Some systems
180 do use the broken struct convention, and some don't. */
181 set_gdbarch_return_value (gdbarch, ppcnbsd_return_value);
182
183 /* NetBSD uses SVR4-style shared libraries. */
184 set_solib_svr4_fetch_link_map_offsets
185 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
186
187 set_gdbarch_iterate_over_regset_sections
188 (gdbarch, ppcnbsd_iterate_over_regset_sections);
189
190 tramp_frame_prepend_unwinder (gdbarch, &ppcnbsd_sigtramp);
191 tramp_frame_prepend_unwinder (gdbarch, &ppcnbsd2_sigtramp);
192 }
193
194 void _initialize_ppcnbsd_tdep ();
195 void
196 _initialize_ppcnbsd_tdep ()
197 {
198 gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_NETBSD,
199 ppcnbsd_init_abi);
200
201 /* Avoid initializing the register offsets again if they were
202 already initialized by ppcnbsd-nat.c. */
203 if (ppcnbsd_reg_offsets.pc_offset == 0)
204 {
205 /* General-purpose registers. */
206 ppcnbsd_reg_offsets.r0_offset = 0;
207 ppcnbsd_reg_offsets.gpr_size = 4;
208 ppcnbsd_reg_offsets.xr_size = 4;
209 ppcnbsd_reg_offsets.lr_offset = 128;
210 ppcnbsd_reg_offsets.cr_offset = 132;
211 ppcnbsd_reg_offsets.xer_offset = 136;
212 ppcnbsd_reg_offsets.ctr_offset = 140;
213 ppcnbsd_reg_offsets.pc_offset = 144;
214 ppcnbsd_reg_offsets.ps_offset = -1;
215 ppcnbsd_reg_offsets.mq_offset = -1;
216
217 /* Floating-point registers. */
218 ppcnbsd_reg_offsets.f0_offset = 0;
219 ppcnbsd_reg_offsets.fpscr_offset = 256;
220 ppcnbsd_reg_offsets.fpscr_size = 4;
221
222 }
223 }
This page took 0.033973 seconds and 4 git commands to generate.