xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/hppa-netbsd-tdep.c (revision f8cf1a9151c7af1cb0bd8b09c13c66bca599c027)
1 /* Target-dependent code for NetBSD/hppa
2 
3    Copyright (C) 2008-2023 Free Software Foundation, Inc.
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
9    the Free Software Foundation; either version 3 of the License, or
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
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 #include "defs.h"
21 #include "osabi.h"
22 #include "regcache.h"
23 #include "regset.h"
24 
25 #include "trad-frame.h"
26 #include "tramp-frame.h"
27 
28 #include "hppa-tdep.h"
29 #include "hppa-bsd-tdep.h"
30 #include "netbsd-tdep.h"
31 #include "gdbarch.h"
32 
33 /* From <machine/mcontext.h>.  */
34 static int hppanbsd_mc_reg_offset[] =
35 {
36   /* r0 ... r31 */
37       -1,   1 * 4,   2 * 4,   3 * 4,
38    4 * 4,   5 * 4,   6 * 4,   7 * 4,
39    8 * 4,   9 * 4,  10 * 4,  11 * 4,
40   12 * 4,  13 * 4,  14 * 4,  15 * 4,
41   16 * 4,  17 * 4,  18 * 4,  19 * 4,
42   20 * 4,  21 * 4,  22 * 4,  23 * 4,
43   24 * 4,  25 * 4,  26 * 4,  27 * 4,
44   28 * 4,  29 * 4,  30 * 4,  31 * 4,
45 
46   32 * 4,	/* HPPA_SAR_REGNUM */
47   35 * 4,	/* HPPA_PCOQ_HEAD_REGNUM */
48   33 * 4,	/* HPPA_PCSQ_HEAD_REGNUM */
49   36 * 4,	/* HPPA_PCOQ_TAIL_REGNUM */
50   34 * 4,	/* HPPA_PCSQ_TAIL_REGNUM */
51   -1,		/* HPPA_EIEM_REGNUM */
52   -1,		/* HPPA_IIR_REGNUM */
53   -1,		/* HPPA_ISR_REGNUM */
54   -1,		/* HPPA_IOR_REGNUM */
55   0 * 4,	/* HPPA_IPSW_REGNUM */
56   -1,		/* spare? */
57   41 * 4,	/* HPPA_SR4_REGNUM */
58   37 * 4,	/* sr0 */
59   38 * 4,	/* sr1 */
60   39 * 4,	/* sr2 */
61   40 * 4,	/* sr3 */
62   -1,		/* 48 */
63   -1,		/* 49 */
64   -1,		/* 50 */
65   -1,		/* 51 */
66   -1,		/* 52 */
67   -1,		/* 53 */
68   -1,		/* 54 */
69   -1,		/* 55 */
70   -1,		/* 56 */
71   -1,		/* 57 CR24 */
72   -1,		/* 58 CR25 */
73   -1,		/* 59 CR26 */
74   43 * 4,	/* HPPA_CR27_REGNUM */
75 
76   /* more tbd */
77 };
78 
79 static void hppanbsd_sigtramp_cache_init (const struct tramp_frame *,
80 					 frame_info_ptr,
81 					 struct trad_frame_cache *,
82 					 CORE_ADDR);
83 
84 static const struct tramp_frame hppanbsd_sigtramp_si4 =
85 {
86   SIGTRAMP_FRAME,
87   4,
88   {
89     { 0xc7d7c012, ULONGEST_MAX },	/*	bb,>=,n %arg3, 30, 1f		*/
90     { 0xd6e01c1e, ULONGEST_MAX },	/*	 depwi 0,31,2,%arg3		*/
91     { 0x0ee81093, ULONGEST_MAX },	/*	ldw 4(%arg3), %r19		*/
92     { 0x0ee01097, ULONGEST_MAX },	/*	ldw 0(%arg3), %arg3		*/
93 			/* 1: 					*/
94     { 0xe8404000, ULONGEST_MAX },	/* 	blr %r0, %rp			*/
95     { 0xeae0c002, ULONGEST_MAX },	/*	bv,n %r0(%arg3)			*/
96     { 0x08000240, ULONGEST_MAX },	/*	 nop				*/
97 
98     { 0x0803025a, ULONGEST_MAX },	/*	copy %r3, %arg0			*/
99     { 0x20200801, ULONGEST_MAX },	/*	ldil -40000000, %r1		*/
100     { 0xe420e008, ULONGEST_MAX },	/*	be,l 4(%sr7, %r1), %sr0, %r31	*/
101     { 0x34160268, ULONGEST_MAX },	/*	 ldi 134, %t1 ; SYS_setcontext	*/
102 
103     { 0x081c025a, ULONGEST_MAX },	/*	copy ret0, %arg0		*/
104     { 0x20200801, ULONGEST_MAX },	/*	ldil -40000000, %r1		*/
105     { 0xe420e008, ULONGEST_MAX },	/*	be,l 4(%sr7, %r1), %sr0, %r31	*/
106     { 0x34160002, ULONGEST_MAX },	/*	 ldi 1, %t1 ; SYS_exit		*/
107     { TRAMP_SENTINEL_INSN, ULONGEST_MAX }
108   },
109   hppanbsd_sigtramp_cache_init
110 };
111 
112 
113 static void
114 hppanbsd_sigtramp_cache_init (const struct tramp_frame *self,
115 			     frame_info_ptr this_frame,
116 			     struct trad_frame_cache *this_cache,
117 			     CORE_ADDR func)
118 {
119   CORE_ADDR sp = get_frame_register_unsigned (this_frame, HPPA_SP_REGNUM);
120   CORE_ADDR base;
121   int *reg_offset;
122   int num_regs;
123   int i;
124 
125   reg_offset = hppanbsd_mc_reg_offset;
126   num_regs = ARRAY_SIZE (hppanbsd_mc_reg_offset);
127 
128   /* frame pointer */
129   base = sp - 0x280;
130   /* offsetof(struct sigframe_siginfo, sf_uc) = 128 */
131   base += 128;
132   /* offsetof(ucontext_t, uc_mcontext) == 40 */
133   base += 40;
134 
135   for (i = 0; i < num_regs; i++)
136     if (reg_offset[i] != -1)
137       trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]);
138 
139   /* Construct the frame ID using the function start.  */
140   trad_frame_set_id (this_cache, frame_id_build (sp, func));
141 }
142 
143 /* Core file support.  */
144 
145 /* Sizeof `struct reg' in <machine/reg.h>.  */
146 #define HPPANBSD_SIZEOF_GREGS	(47 * 4)
147 
148 static int hppanbsd_reg_offset[] =
149 {
150   /* r0 ... r31 */
151       -1,   1 * 4,   2 * 4,   3 * 4,
152    4 * 4,   5 * 4,   6 * 4,   7 * 4,
153    8 * 4,   9 * 4,  10 * 4,  11 * 4,
154   12 * 4,  13 * 4,  14 * 4,  15 * 4,
155   16 * 4,  17 * 4,  18 * 4,  19 * 4,
156   20 * 4,  21 * 4,  22 * 4,  23 * 4,
157   24 * 4,  25 * 4,  26 * 4,  27 * 4,
158   28 * 4,  29 * 4,  30 * 4,  31 * 4,
159 
160   32 * 4,	/* HPPA_SAR_REGNUM */
161   35 * 4,	/* HPPA_PCOQ_HEAD_REGNUM */
162   33 * 4,	/* HPPA_PCSQ_HEAD_REGNUM */
163   36 * 4,	/* HPPA_PCOQ_TAIL_REGNUM */
164   34 * 4,	/* HPPA_PCSQ_TAIL_REGNUM */
165   -1,		/* HPPA_EIEM_REGNUM */
166   -1,		/* HPPA_IIR_REGNUM */
167   -1,		/* HPPA_ISR_REGNUM */
168   -1,		/* HPPA_IOR_REGNUM */
169   0 * 4,	/* HPPA_IPSW_REGNUM */
170   -1,		/* spare? */
171   41 * 4,	/* HPPA_SR4_REGNUM */
172   37 * 4,	/* sr0 */
173   38 * 4,	/* sr1 */
174   39 * 4,	/* sr2 */
175   40 * 4,	/* sr3 */
176   -1,		/* 48 */
177   -1,		/* 49 */
178   -1,		/* 50 */
179   -1,		/* 51 */
180   -1,		/* 52 */
181   -1,		/* 53 */
182   -1,		/* 54 */
183   -1,		/* 55 */
184   -1,		/* 56 */
185   -1,		/* 57 */
186   -1,		/* 58 */
187   -1,		/* 59 */
188   46 * 4,	/* HPPA_CR27_REGNUM */
189 };
190 
191 /* Supply register REGNUM from the buffer specified by GREGS and LEN
192    in the general-purpose register set REGSET to register cache
193    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
194 
195 static void
196 hppanbsd_supply_gregset (const struct regset *regset,
197 			 struct regcache *regcache,
198 			 int regnum, const void *gregs, size_t len)
199 {
200   const gdb_byte *regs = (const gdb_byte *) gregs;
201   int i;
202 
203   gdb_assert (len >= HPPANBSD_SIZEOF_GREGS);
204 
205   for (i = 0; i < ARRAY_SIZE (hppanbsd_reg_offset); i++)
206     if (hppanbsd_reg_offset[i] != -1)
207       if (regnum == -1 || regnum == i)
208 	regcache->raw_supply (i, regs + hppanbsd_reg_offset[i]);
209 }
210 
211 /* NetBSD/hppa register set.  */
212 
213 static const struct regset hppanbsd_gregset =
214 {
215   NULL,
216   hppanbsd_supply_gregset
217 };
218 
219 /* Iterate over supported core file register note sections. */
220 
221 static void
222 hppanbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
223 				       iterate_over_regset_sections_cb *cb,
224 				       void *cb_data,
225 				       const struct regcache *regcache)
226 {
227   cb (".reg", HPPANBSD_SIZEOF_GREGS, HPPANBSD_SIZEOF_GREGS, &hppanbsd_gregset,
228       NULL, cb_data);
229 }
230 
231 static void
232 hppanbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
233 {
234   /* Obviously NetBSD is BSD-based.  */
235   hppabsd_init_abi (info, gdbarch);
236 
237   nbsd_init_abi (info, gdbarch);
238 
239   /* Core file support.  */
240   set_gdbarch_iterate_over_regset_sections
241     (gdbarch, hppanbsd_iterate_over_regset_sections);
242 
243   tramp_frame_prepend_unwinder (gdbarch, &hppanbsd_sigtramp_si4);
244 }
245 
246 void _initialize_hppanbsd_tdep ();
247 void
248 _initialize_hppanbsd_tdep ()
249 {
250   gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_NETBSD,
251 			  hppanbsd_init_abi);
252 }
253