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