2004-07-23 Andrew Cagney <cagney@gnu.org>
[external/binutils.git] / gdb / hppa-linux-nat.c
1 /* Functions specific to running GDB native on HPPA running GNU/Linux.
2
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"
26 #include "inferior.h"
27
28 #include <sys/procfs.h>
29 #include <sys/ptrace.h>
30 #include <linux/version.h>
31
32 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,43)
33 #include <asm/offset.h>
34 #else
35 #include <asm/offsets.h>
36 #endif
37
38 #include "hppa-tdep.h"
39
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
48 static 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
154 CORE_ADDR
155 register_addr (int regno, CORE_ADDR blockend)
156 {
157   CORE_ADDR addr;
158
159   if ((unsigned) regno >= NUM_REGS)
160     error ("Invalid register number %d.", regno);
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  */
183 #define GR_REGNUM(_n)   (HPPA_R0_REGNUM+_n)
184 #define TR_REGNUM(_n)   (HPPA_TR0_REGNUM+_n)
185 static 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
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,
198
199     HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM,
200     HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM,
201
202     HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM,
203     HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM,
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
208     HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM,
209     HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM,
210   };
211
212
213
214 /* Fetch one register.  */
215
216 static void
217 fetch_register (int regno)
218 {
219   int tid;
220   int val;
221
222   if (CANNOT_FETCH_REGISTER (regno))
223     {
224       regcache_raw_supply (current_regcache, regno, NULL);
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)
236     error ("Couldn't read register %s (#%d): %s.", REGISTER_NAME (regno),
237            regno, safe_strerror (errno));
238
239   regcache_raw_supply (current_regcache, regno, &val);
240 }
241
242 /* Store one register. */
243
244 static void
245 store_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)
262     error ("Couldn't write register %s (#%d): %s.", REGISTER_NAME (regno),
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
270 void
271 fetch_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
288 void
289 store_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
305 void
306 supply_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];
314       regcache_raw_supply (current_regcache, regno, regp);
315     }
316 }
317
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
322 void
323 fill_gregset (gdb_gregset_t *gregsetp, int regno)
324 {
325   int i;
326
327   for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++)
328     {
329       int mregno = greg_map[i];
330
331       if (regno == -1 || regno == mregno)
332         {
333           regcache_raw_collect(current_regcache, mregno, &(*gregsetp)[i]);
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
342 void
343 supply_fpregset (gdb_fpregset_t *fpregsetp)
344 {
345   int regi;
346   char *from;
347
348   for (regi = 0; regi <= 31; regi++)
349     {
350       from = (char *) &((*fpregsetp)[regi]);
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);
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
362 void
363 fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
364 {
365   int i;
366
367   for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 32 * 2; i++)
368    {
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;
374       regcache_raw_collect (current_regcache, i, to);
375    }
376 }