2004-04-24 Randolph Chung <tausq@debian.org>
[external/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
26 #include <sys/procfs.h>
27 #include <string.h>
28 #include <asm/offsets.h>
29
30 /* Prototypes for supply_gregset etc. */
31 #include "gregset.h"
32
33 /* These must match the order of the register names.
34
35    Some sort of lookup table is needed because the offsets associated
36    with the registers are all over the board.  */
37
38 static const int u_offsets[] =
39   {
40     /* general registers */
41     -1,
42     PT_GR1,
43     PT_GR2,
44     PT_GR3,
45     PT_GR4,
46     PT_GR5,
47     PT_GR6,
48     PT_GR7,
49     PT_GR8,
50     PT_GR9,
51     PT_GR10,
52     PT_GR11,
53     PT_GR12,
54     PT_GR13,
55     PT_GR14,
56     PT_GR15,
57     PT_GR16,
58     PT_GR17,
59     PT_GR18,
60     PT_GR19,
61     PT_GR20,
62     PT_GR21,
63     PT_GR22,
64     PT_GR23,
65     PT_GR24,
66     PT_GR25,
67     PT_GR26,
68     PT_GR27,
69     PT_GR28,
70     PT_GR29,
71     PT_GR30,
72     PT_GR31,
73
74     PT_SAR,
75     PT_IAOQ0,
76     PT_IASQ0,
77     PT_IAOQ1,
78     PT_IASQ1,
79     -1, /* eiem */
80     PT_IIR,
81     PT_ISR,
82     PT_IOR,
83     PT_PSW,
84     -1, /* goto */
85
86     PT_SR4,
87     PT_SR0,
88     PT_SR1,
89     PT_SR2,
90     PT_SR3,
91     PT_SR5,
92     PT_SR6,
93     PT_SR7,
94
95     -1, /* cr0 */
96     -1, /* pid0 */
97     -1, /* pid1 */
98     -1, /* ccr */
99     -1, /* pid2 */
100     -1, /* pid3 */
101     -1, /* cr24 */
102     -1, /* cr25 */
103     -1, /* cr26 */
104     PT_CR27,
105     -1, /* cr28 */
106     -1, /* cr29 */
107     -1, /* cr30 */
108
109     /* Floating point regs.  */
110     PT_FR0,  PT_FR0 + 4,
111     PT_FR1,  PT_FR1 + 4,
112     PT_FR2,  PT_FR2 + 4,
113     PT_FR3,  PT_FR3 + 4,
114     PT_FR4,  PT_FR4 + 4,
115     PT_FR5,  PT_FR5 + 4,
116     PT_FR6,  PT_FR6 + 4,
117     PT_FR7,  PT_FR7 + 4,
118     PT_FR8,  PT_FR8 + 4,
119     PT_FR9,  PT_FR9 + 4,
120     PT_FR10, PT_FR10 + 4,
121     PT_FR11, PT_FR11 + 4,
122     PT_FR12, PT_FR12 + 4,
123     PT_FR13, PT_FR13 + 4,
124     PT_FR14, PT_FR14 + 4,
125     PT_FR15, PT_FR15 + 4,
126     PT_FR16, PT_FR16 + 4,
127     PT_FR17, PT_FR17 + 4,
128     PT_FR18, PT_FR18 + 4,
129     PT_FR19, PT_FR19 + 4,
130     PT_FR20, PT_FR20 + 4,
131     PT_FR21, PT_FR21 + 4,
132     PT_FR22, PT_FR22 + 4,
133     PT_FR23, PT_FR23 + 4,
134     PT_FR24, PT_FR24 + 4,
135     PT_FR25, PT_FR25 + 4,
136     PT_FR26, PT_FR26 + 4,
137     PT_FR27, PT_FR27 + 4,
138     PT_FR28, PT_FR28 + 4,
139     PT_FR29, PT_FR29 + 4,
140     PT_FR30, PT_FR30 + 4,
141     PT_FR31, PT_FR31 + 4,
142   };
143
144 CORE_ADDR
145 register_addr (int regno, CORE_ADDR blockend)
146 {
147   CORE_ADDR addr;
148
149   if ((unsigned) regno >= NUM_REGS)
150     error ("Invalid register number %d.", regno);
151
152   if (u_offsets[regno] == -1)
153     addr = 0;
154   else
155     {
156       addr = (CORE_ADDR) u_offsets[regno];
157     }
158
159   return addr;
160 }
161
162 /*
163  * Registers saved in a coredump:
164  * gr0..gr31
165  * sr0..sr7
166  * iaoq0..iaoq1
167  * iasq0..iasq1
168  * sar, iir, isr, ior, ipsw
169  * cr0, cr24..cr31
170  * cr8,9,12,13
171  * cr10, cr15
172  */
173 #define GR_REGNUM(_n)   (R0_REGNUM+_n)
174 #define TR_REGNUM(_n)   (TR0_REGNUM+_n)
175 static const int greg_map[] =
176   {
177     GR_REGNUM(0), GR_REGNUM(1), GR_REGNUM(2), GR_REGNUM(3),
178     GR_REGNUM(4), GR_REGNUM(5), GR_REGNUM(6), GR_REGNUM(7),
179     GR_REGNUM(8), GR_REGNUM(9), GR_REGNUM(10), GR_REGNUM(11),
180     GR_REGNUM(12), GR_REGNUM(13), GR_REGNUM(14), GR_REGNUM(15),
181     GR_REGNUM(16), GR_REGNUM(17), GR_REGNUM(18), GR_REGNUM(19),
182     GR_REGNUM(20), GR_REGNUM(21), GR_REGNUM(22), GR_REGNUM(23),
183     GR_REGNUM(24), GR_REGNUM(25), GR_REGNUM(26), GR_REGNUM(27),
184     GR_REGNUM(28), GR_REGNUM(29), GR_REGNUM(30), GR_REGNUM(31),
185
186     SR4_REGNUM+1, SR4_REGNUM+2, SR4_REGNUM+3, SR4_REGNUM+4,
187     SR4_REGNUM, SR4_REGNUM+5, SR4_REGNUM+6, SR4_REGNUM+7,
188
189     PCOQ_HEAD_REGNUM, PCOQ_TAIL_REGNUM,
190     PCSQ_HEAD_REGNUM, PCSQ_TAIL_REGNUM,
191
192     SAR_REGNUM, IIR_REGNUM, ISR_REGNUM, IOR_REGNUM,
193     IPSW_REGNUM, RCR_REGNUM,
194
195     TR_REGNUM(0), TR_REGNUM(1), TR_REGNUM(2), TR_REGNUM(3),
196     TR_REGNUM(4), TR_REGNUM(5), TR_REGNUM(6), TR_REGNUM(7),
197
198     PID0_REGNUM, PID1_REGNUM, PID2_REGNUM, PID3_REGNUM,
199     CCR_REGNUM, EIEM_REGNUM,
200   };
201
202 void
203 supply_gregset (gdb_gregset_t *gregsetp)
204 {
205   int i;
206   greg_t *regp = (elf_greg_t *) gregsetp;
207
208   for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
209     {
210       int regno = greg_map[i];
211       int size = register_size (current_gdbarch, regno);
212       /* When running a 64 bit kernel, a greg_t may be larger than the
213          actual register, so just pick off the LS bits of big-endian word.  */
214       supply_register (regno, ((char *) (regp + 1)) - size);
215     }
216 }
217
218 void
219 fill_gregset (gdb_gregset_t *gregsetp, int regno)
220 {
221   int i;
222   greg_t *regp = (greg_t *) gregsetp;
223
224   memset (gregsetp, 0, sizeof (*gregsetp));
225   for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
226     {
227       int regi = greg_map[i];
228
229       if (regno == -1 || regi == regno)
230         {
231           int rawsize = register_size (current_gdbarch, regi);
232           regcache_collect (regi, ((char *) (regp + 1)) - rawsize);
233         }
234     }
235 }
236
237 /*  Given a pointer to a floating point register set in /proc format
238    (fpregset_t *), unpack the register contents and supply them as gdb's
239    idea of the current floating point register values. */
240
241 void
242 supply_fpregset (gdb_fpregset_t *fpregsetp)
243 {
244   register int regi;
245   char *from;
246
247   for (regi = 0; regi <= 31; regi++)
248     {
249       from = (char *) &((*fpregsetp)[regi]);
250       supply_register (2*regi + HPPA_FP0_REGNUM, from);
251       supply_register (2*regi + HPPA_FP0_REGNUM + 1, from + 4);
252     }
253 }
254
255 /*  Given a pointer to a floating point register set in /proc format
256    (fpregset_t *), update the register specified by REGNO from gdb's idea
257    of the current floating point register set.  If REGNO is -1, update
258    them all. */
259
260 void
261 fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
262 {
263   int i;
264
265   for (i = 0; i < NUM_REGS; i++)
266    {
267     if (regno == -1 || regno == i)
268       {
269         /* Gross.  fpregset_t is double, registers[x] has single
270            precision reg.  */
271         char *to = (char *) &((*fpregsetp)[(i - HPPA_FP0_REGNUM) / 2]);
272         if ((i - HPPA_FP0_REGNUM) & 1)
273           to += 4;
274         regcache_collect (i, to);
275       }
276    }
277 }