]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/hppa-linux-nat.c
2004-04-24 Randolph Chung <tausq@debian.org>
[thirdparty/binutils-gdb.git] / gdb / hppa-linux-nat.c
CommitLineData
50306a9d
RC
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
38static 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
144CORE_ADDR
145register_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)
175static 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
202void
203supply_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
218void
219fill_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
241void
242supply_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
260void
261fill_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}