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