fc901ace3bdfa36a6f59a89f6ddbfc55829d8e8f
[platform/upstream/binutils.git] / gdb / hppa-linux-nat.c
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"
25 #include "inferior.h"
26
27 #include <sys/procfs.h>
28 #include <sys/ptrace.h>
29 #include <linux/version.h>
30
31 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,43)
32 #include <asm/offset.h>
33 #else
34 #include <asm/offsets.h>
35 #endif
36
37 #include "hppa-tdep.h"
38
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
47 static 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
153 CORE_ADDR
154 register_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  */
182 #define GR_REGNUM(_n)   (HPPA_R0_REGNUM+_n)
183 #define TR_REGNUM(_n)   (HPPA_TR0_REGNUM+_n)
184 static 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
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,
197
198     HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM,
199     HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM,
200
201     HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM,
202     HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM,
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
207     HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM,
208     HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM,
209   };
210
211
212
213 /* Fetch one register.  */
214
215 static void
216 fetch_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
243 static void
244 store_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
269 void
270 fetch_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
287 void
288 store_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
304 void
305 supply_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];
313       supply_register (regno, regp);
314     }
315 }
316
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
321 void
322 fill_gregset (gdb_gregset_t *gregsetp, int regno)
323 {
324   int i;
325
326   for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++)
327     {
328       int mregno = greg_map[i];
329
330       if (regno == -1 || regno == mregno)
331         {
332           regcache_collect(mregno, &(*gregsetp)[i]);
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
341 void
342 supply_fpregset (gdb_fpregset_t *fpregsetp)
343 {
344   int regi;
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
360 void
361 fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
362 {
363   int i;
364
365   for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 32 * 2; i++)
366    {
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);
373    }
374 }