2004-05-07 Michael Snyder <msnyder@redhat.com>
[deliverable/binutils-gdb.git] / gdb / hppa-linux-nat.c
CommitLineData
50306a9d
RC
1/* Functions specific to running gdb native on HPPA running Linux.
2 Copyright 2004 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21#include "defs.h"
22#include "gdbcore.h"
23#include "regcache.h"
24#include "gdb_string.h"
959464ff 25#include "inferior.h"
50306a9d
RC
26
27#include <sys/procfs.h>
959464ff 28#include <sys/ptrace.h>
50306a9d
RC
29#include <string.h>
30#include <asm/offsets.h>
31
34f75cc1
RC
32#include "hppa-tdep.h"
33
50306a9d
RC
34/* Prototypes for supply_gregset etc. */
35#include "gregset.h"
36
37/* These must match the order of the register names.
38
39 Some sort of lookup table is needed because the offsets associated
40 with the registers are all over the board. */
41
42static const int u_offsets[] =
43 {
44 /* general registers */
45 -1,
46 PT_GR1,
47 PT_GR2,
48 PT_GR3,
49 PT_GR4,
50 PT_GR5,
51 PT_GR6,
52 PT_GR7,
53 PT_GR8,
54 PT_GR9,
55 PT_GR10,
56 PT_GR11,
57 PT_GR12,
58 PT_GR13,
59 PT_GR14,
60 PT_GR15,
61 PT_GR16,
62 PT_GR17,
63 PT_GR18,
64 PT_GR19,
65 PT_GR20,
66 PT_GR21,
67 PT_GR22,
68 PT_GR23,
69 PT_GR24,
70 PT_GR25,
71 PT_GR26,
72 PT_GR27,
73 PT_GR28,
74 PT_GR29,
75 PT_GR30,
76 PT_GR31,
77
78 PT_SAR,
79 PT_IAOQ0,
80 PT_IASQ0,
81 PT_IAOQ1,
82 PT_IASQ1,
83 -1, /* eiem */
84 PT_IIR,
85 PT_ISR,
86 PT_IOR,
87 PT_PSW,
88 -1, /* goto */
89
90 PT_SR4,
91 PT_SR0,
92 PT_SR1,
93 PT_SR2,
94 PT_SR3,
95 PT_SR5,
96 PT_SR6,
97 PT_SR7,
98
99 -1, /* cr0 */
100 -1, /* pid0 */
101 -1, /* pid1 */
102 -1, /* ccr */
103 -1, /* pid2 */
104 -1, /* pid3 */
105 -1, /* cr24 */
106 -1, /* cr25 */
107 -1, /* cr26 */
108 PT_CR27,
109 -1, /* cr28 */
110 -1, /* cr29 */
111 -1, /* cr30 */
112
113 /* Floating point regs. */
114 PT_FR0, PT_FR0 + 4,
115 PT_FR1, PT_FR1 + 4,
116 PT_FR2, PT_FR2 + 4,
117 PT_FR3, PT_FR3 + 4,
118 PT_FR4, PT_FR4 + 4,
119 PT_FR5, PT_FR5 + 4,
120 PT_FR6, PT_FR6 + 4,
121 PT_FR7, PT_FR7 + 4,
122 PT_FR8, PT_FR8 + 4,
123 PT_FR9, PT_FR9 + 4,
124 PT_FR10, PT_FR10 + 4,
125 PT_FR11, PT_FR11 + 4,
126 PT_FR12, PT_FR12 + 4,
127 PT_FR13, PT_FR13 + 4,
128 PT_FR14, PT_FR14 + 4,
129 PT_FR15, PT_FR15 + 4,
130 PT_FR16, PT_FR16 + 4,
131 PT_FR17, PT_FR17 + 4,
132 PT_FR18, PT_FR18 + 4,
133 PT_FR19, PT_FR19 + 4,
134 PT_FR20, PT_FR20 + 4,
135 PT_FR21, PT_FR21 + 4,
136 PT_FR22, PT_FR22 + 4,
137 PT_FR23, PT_FR23 + 4,
138 PT_FR24, PT_FR24 + 4,
139 PT_FR25, PT_FR25 + 4,
140 PT_FR26, PT_FR26 + 4,
141 PT_FR27, PT_FR27 + 4,
142 PT_FR28, PT_FR28 + 4,
143 PT_FR29, PT_FR29 + 4,
144 PT_FR30, PT_FR30 + 4,
145 PT_FR31, PT_FR31 + 4,
146 };
147
148CORE_ADDR
149register_addr (int regno, CORE_ADDR blockend)
150{
151 CORE_ADDR addr;
152
153 if ((unsigned) regno >= NUM_REGS)
154 error ("Invalid register number %d.", regno);
155
156 if (u_offsets[regno] == -1)
157 addr = 0;
158 else
159 {
160 addr = (CORE_ADDR) u_offsets[regno];
161 }
162
163 return addr;
164}
165
166/*
167 * Registers saved in a coredump:
168 * gr0..gr31
169 * sr0..sr7
170 * iaoq0..iaoq1
171 * iasq0..iasq1
172 * sar, iir, isr, ior, ipsw
173 * cr0, cr24..cr31
174 * cr8,9,12,13
175 * cr10, cr15
176 */
34f75cc1
RC
177#define GR_REGNUM(_n) (HPPA_R0_REGNUM+_n)
178#define TR_REGNUM(_n) (HPPA_TR0_REGNUM+_n)
50306a9d
RC
179static const int greg_map[] =
180 {
181 GR_REGNUM(0), GR_REGNUM(1), GR_REGNUM(2), GR_REGNUM(3),
182 GR_REGNUM(4), GR_REGNUM(5), GR_REGNUM(6), GR_REGNUM(7),
183 GR_REGNUM(8), GR_REGNUM(9), GR_REGNUM(10), GR_REGNUM(11),
184 GR_REGNUM(12), GR_REGNUM(13), GR_REGNUM(14), GR_REGNUM(15),
185 GR_REGNUM(16), GR_REGNUM(17), GR_REGNUM(18), GR_REGNUM(19),
186 GR_REGNUM(20), GR_REGNUM(21), GR_REGNUM(22), GR_REGNUM(23),
187 GR_REGNUM(24), GR_REGNUM(25), GR_REGNUM(26), GR_REGNUM(27),
188 GR_REGNUM(28), GR_REGNUM(29), GR_REGNUM(30), GR_REGNUM(31),
189
34f75cc1
RC
190 HPPA_SR4_REGNUM+1, HPPA_SR4_REGNUM+2, HPPA_SR4_REGNUM+3, HPPA_SR4_REGNUM+4,
191 HPPA_SR4_REGNUM, HPPA_SR4_REGNUM+5, HPPA_SR4_REGNUM+6, HPPA_SR4_REGNUM+7,
50306a9d 192
34f75cc1
RC
193 HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM,
194 HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM,
50306a9d 195
34f75cc1
RC
196 HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM,
197 HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM,
50306a9d
RC
198
199 TR_REGNUM(0), TR_REGNUM(1), TR_REGNUM(2), TR_REGNUM(3),
200 TR_REGNUM(4), TR_REGNUM(5), TR_REGNUM(6), TR_REGNUM(7),
201
34f75cc1
RC
202 HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM,
203 HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM,
50306a9d
RC
204 };
205
959464ff
RC
206
207
208/* Fetch one register. */
209
210static void
211fetch_register (int regno)
212{
213 int tid;
214 int val;
215
216 if (CANNOT_FETCH_REGISTER (regno))
217 {
218 supply_register (regno, NULL);
219 return;
220 }
221
222 /* GNU/Linux LWP ID's are process ID's. */
223 tid = TIDGET (inferior_ptid);
224 if (tid == 0)
225 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
226
227 errno = 0;
228 val = ptrace (PTRACE_PEEKUSER, tid, register_addr (regno, 0), 0);
229 if (errno != 0)
230 error ("Couldn't read register %s (#%d): %s.", REGISTER_NAME (regno),
231 regno, safe_strerror (errno));
232
233 regcache_raw_supply (current_regcache, regno, &val);
234}
235
236/* Store one register. */
237
238static void
239store_register (int regno)
240{
241 int tid;
242 int val;
243
244 if (CANNOT_STORE_REGISTER (regno))
245 return;
246
247 /* GNU/Linux LWP ID's are process ID's. */
248 tid = TIDGET (inferior_ptid);
249 if (tid == 0)
250 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
251
252 errno = 0;
253 regcache_raw_collect (current_regcache, regno, &val);
254 ptrace (PTRACE_POKEUSER, tid, register_addr (regno, 0), val);
255 if (errno != 0)
256 error ("Couldn't write register %s (#%d): %s.", REGISTER_NAME (regno),
257 regno, safe_strerror (errno));
258}
259
260/* Fetch registers from the child process. Fetch all registers if
261 regno == -1, otherwise fetch all general registers or all floating
262 point registers depending upon the value of regno. */
263
264void
265fetch_inferior_registers (int regno)
266{
267 if (-1 == regno)
268 {
269 for (regno = 0; regno < NUM_REGS; regno++)
270 fetch_register (regno);
271 }
272 else
273 {
274 fetch_register (regno);
275 }
276}
277
278/* Store registers back into the inferior. Store all registers if
279 regno == -1, otherwise store all general registers or all floating
280 point registers depending upon the value of regno. */
281
282void
283store_inferior_registers (int regno)
284{
285 if (-1 == regno)
286 {
287 for (regno = 0; regno < NUM_REGS; regno++)
288 store_register (regno);
289 }
290 else
291 {
292 store_register (regno);
293 }
294}
295
296/* Fill GDB's register array with the general-purpose register values
297 in *gregsetp. */
298
50306a9d
RC
299void
300supply_gregset (gdb_gregset_t *gregsetp)
301{
302 int i;
303 greg_t *regp = (elf_greg_t *) gregsetp;
304
305 for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
306 {
307 int regno = greg_map[i];
959464ff 308 supply_register (regno, regp);
50306a9d
RC
309 }
310}
311
959464ff
RC
312/* Fill register regno (if it is a general-purpose register) in
313 *gregsetp with the appropriate value from GDB's register array.
314 If regno is -1, do this for all registers. */
315
50306a9d
RC
316void
317fill_gregset (gdb_gregset_t *gregsetp, int regno)
318{
319 int i;
50306a9d 320
959464ff 321 for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++)
50306a9d 322 {
959464ff 323 int mregno = greg_map[i];
50306a9d 324
959464ff 325 if (regno == -1 || regno == mregno)
50306a9d 326 {
959464ff 327 regcache_collect(mregno, &(*gregsetp)[i]);
50306a9d
RC
328 }
329 }
330}
331
332/* Given a pointer to a floating point register set in /proc format
333 (fpregset_t *), unpack the register contents and supply them as gdb's
334 idea of the current floating point register values. */
335
336void
337supply_fpregset (gdb_fpregset_t *fpregsetp)
338{
339 register int regi;
340 char *from;
341
342 for (regi = 0; regi <= 31; regi++)
343 {
344 from = (char *) &((*fpregsetp)[regi]);
345 supply_register (2*regi + HPPA_FP0_REGNUM, from);
346 supply_register (2*regi + HPPA_FP0_REGNUM + 1, from + 4);
347 }
348}
349
350/* Given a pointer to a floating point register set in /proc format
351 (fpregset_t *), update the register specified by REGNO from gdb's idea
352 of the current floating point register set. If REGNO is -1, update
353 them all. */
354
355void
356fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
357{
358 int i;
359
959464ff 360 for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 32 * 2; i++)
50306a9d 361 {
959464ff
RC
362 /* Gross. fpregset_t is double, registers[x] has single
363 precision reg. */
364 char *to = (char *) &((*fpregsetp)[(i - HPPA_FP0_REGNUM) / 2]);
365 if ((i - HPPA_FP0_REGNUM) & 1)
366 to += 4;
367 regcache_collect (i, to);
50306a9d
RC
368 }
369}
This page took 0.042106 seconds and 4 git commands to generate.