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