2004-05-07 Randolph Chung <tausq@debian.org>
[deliverable/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
34f75cc1
RC
30#include "hppa-tdep.h"
31
50306a9d
RC
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
40static 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
146CORE_ADDR
147register_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 */
34f75cc1
RC
175#define GR_REGNUM(_n) (HPPA_R0_REGNUM+_n)
176#define TR_REGNUM(_n) (HPPA_TR0_REGNUM+_n)
50306a9d
RC
177static 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
34f75cc1
RC
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,
50306a9d 190
34f75cc1
RC
191 HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM,
192 HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM,
50306a9d 193
34f75cc1
RC
194 HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM,
195 HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM,
50306a9d
RC
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
34f75cc1
RC
200 HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM,
201 HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM,
50306a9d
RC
202 };
203
204void
205supply_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
220void
221fill_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
243void
244supply_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
262void
263fill_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}
This page took 0.036384 seconds and 4 git commands to generate.