Remove regcache_raw_collect
[deliverable/binutils-gdb.git] / gdb / hppa-linux-nat.c
CommitLineData
9cbc6ef0
AC
1/* Functions specific to running GDB native on HPPA running GNU/Linux.
2
e2882c85 3 Copyright (C) 2004-2018 Free Software Foundation, Inc.
50306a9d
RC
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
50306a9d
RC
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
50306a9d
RC
19
20#include "defs.h"
21#include "gdbcore.h"
22#include "regcache.h"
959464ff 23#include "inferior.h"
10d6c8cd
DJ
24#include "target.h"
25#include "linux-nat.h"
00204cf7 26#include "inf-ptrace.h"
50306a9d
RC
27
28#include <sys/procfs.h>
5826e159 29#include "nat/gdb_ptrace.h"
9a727a3c
RC
30#include <linux/version.h>
31
afa35021
DJ
32#include <asm/ptrace.h>
33#include "hppa-linux-offsets.h"
50306a9d 34
34f75cc1
RC
35#include "hppa-tdep.h"
36
f6ac5f3d
PA
37class hppa_linux_nat_target final : public linux_nat_target
38{
39public:
40 /* Add our register access methods. */
41 void fetch_registers (struct regcache *, int) override;
42 void store_registers (struct regcache *, int) override;
43};
44
45static hppa_linux_nat_target the_hppa_linux_nat_target;
46
1777feb0 47/* Prototypes for supply_gregset etc. */
50306a9d
RC
48#include "gregset.h"
49
50/* These must match the order of the register names.
51
52 Some sort of lookup table is needed because the offsets associated
53 with the registers are all over the board. */
54
55static const int u_offsets[] =
56 {
57 /* general registers */
58 -1,
59 PT_GR1,
60 PT_GR2,
61 PT_GR3,
62 PT_GR4,
63 PT_GR5,
64 PT_GR6,
65 PT_GR7,
66 PT_GR8,
67 PT_GR9,
68 PT_GR10,
69 PT_GR11,
70 PT_GR12,
71 PT_GR13,
72 PT_GR14,
73 PT_GR15,
74 PT_GR16,
75 PT_GR17,
76 PT_GR18,
77 PT_GR19,
78 PT_GR20,
79 PT_GR21,
80 PT_GR22,
81 PT_GR23,
82 PT_GR24,
83 PT_GR25,
84 PT_GR26,
85 PT_GR27,
86 PT_GR28,
87 PT_GR29,
88 PT_GR30,
89 PT_GR31,
90
91 PT_SAR,
92 PT_IAOQ0,
93 PT_IASQ0,
94 PT_IAOQ1,
95 PT_IASQ1,
96 -1, /* eiem */
97 PT_IIR,
98 PT_ISR,
99 PT_IOR,
100 PT_PSW,
101 -1, /* goto */
102
103 PT_SR4,
104 PT_SR0,
105 PT_SR1,
106 PT_SR2,
107 PT_SR3,
108 PT_SR5,
109 PT_SR6,
110 PT_SR7,
111
112 -1, /* cr0 */
113 -1, /* pid0 */
114 -1, /* pid1 */
115 -1, /* ccr */
116 -1, /* pid2 */
117 -1, /* pid3 */
118 -1, /* cr24 */
119 -1, /* cr25 */
120 -1, /* cr26 */
121 PT_CR27,
122 -1, /* cr28 */
123 -1, /* cr29 */
124 -1, /* cr30 */
125
126 /* Floating point regs. */
127 PT_FR0, PT_FR0 + 4,
128 PT_FR1, PT_FR1 + 4,
129 PT_FR2, PT_FR2 + 4,
130 PT_FR3, PT_FR3 + 4,
131 PT_FR4, PT_FR4 + 4,
132 PT_FR5, PT_FR5 + 4,
133 PT_FR6, PT_FR6 + 4,
134 PT_FR7, PT_FR7 + 4,
135 PT_FR8, PT_FR8 + 4,
136 PT_FR9, PT_FR9 + 4,
137 PT_FR10, PT_FR10 + 4,
138 PT_FR11, PT_FR11 + 4,
139 PT_FR12, PT_FR12 + 4,
140 PT_FR13, PT_FR13 + 4,
141 PT_FR14, PT_FR14 + 4,
142 PT_FR15, PT_FR15 + 4,
143 PT_FR16, PT_FR16 + 4,
144 PT_FR17, PT_FR17 + 4,
145 PT_FR18, PT_FR18 + 4,
146 PT_FR19, PT_FR19 + 4,
147 PT_FR20, PT_FR20 + 4,
148 PT_FR21, PT_FR21 + 4,
149 PT_FR22, PT_FR22 + 4,
150 PT_FR23, PT_FR23 + 4,
151 PT_FR24, PT_FR24 + 4,
152 PT_FR25, PT_FR25 + 4,
153 PT_FR26, PT_FR26 + 4,
154 PT_FR27, PT_FR27 + 4,
155 PT_FR28, PT_FR28 + 4,
156 PT_FR29, PT_FR29 + 4,
157 PT_FR30, PT_FR30 + 4,
158 PT_FR31, PT_FR31 + 4,
159 };
160
de732108
UW
161static CORE_ADDR
162hppa_linux_register_addr (int regno, CORE_ADDR blockend)
50306a9d
RC
163{
164 CORE_ADDR addr;
165
e38c262f 166 if ((unsigned) regno >= ARRAY_SIZE (u_offsets))
8a3fe4f8 167 error (_("Invalid register number %d."), regno);
50306a9d
RC
168
169 if (u_offsets[regno] == -1)
170 addr = 0;
171 else
172 {
173 addr = (CORE_ADDR) u_offsets[regno];
174 }
175
176 return addr;
177}
178
179/*
180 * Registers saved in a coredump:
181 * gr0..gr31
182 * sr0..sr7
183 * iaoq0..iaoq1
184 * iasq0..iasq1
185 * sar, iir, isr, ior, ipsw
186 * cr0, cr24..cr31
187 * cr8,9,12,13
188 * cr10, cr15
189 */
34f75cc1
RC
190#define GR_REGNUM(_n) (HPPA_R0_REGNUM+_n)
191#define TR_REGNUM(_n) (HPPA_TR0_REGNUM+_n)
50306a9d
RC
192static const int greg_map[] =
193 {
194 GR_REGNUM(0), GR_REGNUM(1), GR_REGNUM(2), GR_REGNUM(3),
195 GR_REGNUM(4), GR_REGNUM(5), GR_REGNUM(6), GR_REGNUM(7),
196 GR_REGNUM(8), GR_REGNUM(9), GR_REGNUM(10), GR_REGNUM(11),
197 GR_REGNUM(12), GR_REGNUM(13), GR_REGNUM(14), GR_REGNUM(15),
198 GR_REGNUM(16), GR_REGNUM(17), GR_REGNUM(18), GR_REGNUM(19),
199 GR_REGNUM(20), GR_REGNUM(21), GR_REGNUM(22), GR_REGNUM(23),
200 GR_REGNUM(24), GR_REGNUM(25), GR_REGNUM(26), GR_REGNUM(27),
201 GR_REGNUM(28), GR_REGNUM(29), GR_REGNUM(30), GR_REGNUM(31),
202
34f75cc1
RC
203 HPPA_SR4_REGNUM+1, HPPA_SR4_REGNUM+2, HPPA_SR4_REGNUM+3, HPPA_SR4_REGNUM+4,
204 HPPA_SR4_REGNUM, HPPA_SR4_REGNUM+5, HPPA_SR4_REGNUM+6, HPPA_SR4_REGNUM+7,
50306a9d 205
34f75cc1
RC
206 HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM,
207 HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM,
50306a9d 208
34f75cc1
RC
209 HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM,
210 HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM,
50306a9d
RC
211
212 TR_REGNUM(0), TR_REGNUM(1), TR_REGNUM(2), TR_REGNUM(3),
213 TR_REGNUM(4), TR_REGNUM(5), TR_REGNUM(6), TR_REGNUM(7),
214
34f75cc1
RC
215 HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM,
216 HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM,
50306a9d
RC
217 };
218
959464ff
RC
219
220
221/* Fetch one register. */
222
223static void
56be3814 224fetch_register (struct regcache *regcache, int regno)
959464ff 225{
ac7936df 226 struct gdbarch *gdbarch = regcache->arch ();
00204cf7 227 pid_t tid;
959464ff
RC
228 int val;
229
464963c9 230 if (gdbarch_cannot_fetch_register (gdbarch, regno))
959464ff 231 {
73e1c03f 232 regcache->raw_supply (regno, NULL);
959464ff
RC
233 return;
234 }
235
222312d3 236 tid = get_ptrace_pid (regcache->ptid ());
959464ff
RC
237
238 errno = 0;
de732108 239 val = ptrace (PTRACE_PEEKUSER, tid, hppa_linux_register_addr (regno, 0), 0);
959464ff 240 if (errno != 0)
c9f4d572 241 error (_("Couldn't read register %s (#%d): %s."),
464963c9 242 gdbarch_register_name (gdbarch, regno),
959464ff
RC
243 regno, safe_strerror (errno));
244
73e1c03f 245 regcache->raw_supply (regno, &val);
959464ff
RC
246}
247
1777feb0 248/* Store one register. */
959464ff
RC
249
250static void
56be3814 251store_register (const struct regcache *regcache, int regno)
959464ff 252{
ac7936df 253 struct gdbarch *gdbarch = regcache->arch ();
00204cf7 254 pid_t tid;
959464ff
RC
255 int val;
256
464963c9 257 if (gdbarch_cannot_store_register (gdbarch, regno))
959464ff
RC
258 return;
259
222312d3 260 tid = get_ptrace_pid (regcache->ptid ());
959464ff
RC
261
262 errno = 0;
34a79281 263 regcache->raw_collect (regno, &val);
de732108 264 ptrace (PTRACE_POKEUSER, tid, hppa_linux_register_addr (regno, 0), val);
959464ff 265 if (errno != 0)
c9f4d572 266 error (_("Couldn't write register %s (#%d): %s."),
464963c9 267 gdbarch_register_name (gdbarch, regno),
959464ff
RC
268 regno, safe_strerror (errno));
269}
270
271/* Fetch registers from the child process. Fetch all registers if
272 regno == -1, otherwise fetch all general registers or all floating
273 point registers depending upon the value of regno. */
274
f6ac5f3d
PA
275void
276hppa_linux_nat_target::fetch_inferior_registers (struct regcache *regcache,
277 int regno)
959464ff
RC
278{
279 if (-1 == regno)
280 {
464963c9 281 for (regno = 0;
ac7936df 282 regno < gdbarch_num_regs (regcache->arch ());
464963c9 283 regno++)
56be3814 284 fetch_register (regcache, regno);
959464ff
RC
285 }
286 else
287 {
56be3814 288 fetch_register (regcache, regno);
959464ff
RC
289 }
290}
291
292/* Store registers back into the inferior. Store all registers if
293 regno == -1, otherwise store all general registers or all floating
294 point registers depending upon the value of regno. */
295
f6ac5f3d
PA
296void
297hppa_linux_nat_target::store_registers (struct regcache *regcache, int regno)
959464ff
RC
298{
299 if (-1 == regno)
300 {
464963c9 301 for (regno = 0;
ac7936df 302 regno < gdbarch_num_regs (regcache->arch ());
464963c9 303 regno++)
56be3814 304 store_register (regcache, regno);
959464ff
RC
305 }
306 else
307 {
56be3814 308 store_register (regcache, regno);
959464ff
RC
309 }
310}
311
312/* Fill GDB's register array with the general-purpose register values
313 in *gregsetp. */
314
50306a9d 315void
7f7fe91e 316supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
50306a9d
RC
317{
318 int i;
7f7fe91e 319 const greg_t *regp = (const elf_greg_t *) gregsetp;
50306a9d
RC
320
321 for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
322 {
323 int regno = greg_map[i];
73e1c03f 324 regcache->raw_supply (regno, regp);
50306a9d
RC
325 }
326}
327
959464ff
RC
328/* Fill register regno (if it is a general-purpose register) in
329 *gregsetp with the appropriate value from GDB's register array.
330 If regno is -1, do this for all registers. */
331
50306a9d 332void
7f7fe91e
UW
333fill_gregset (const struct regcache *regcache,
334 gdb_gregset_t *gregsetp, int regno)
50306a9d
RC
335{
336 int i;
50306a9d 337
959464ff 338 for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++)
50306a9d 339 {
959464ff 340 int mregno = greg_map[i];
50306a9d 341
959464ff 342 if (regno == -1 || regno == mregno)
34a79281 343 regcache->raw_collect (mregno, &(*gregsetp)[i]);
50306a9d
RC
344 }
345}
346
347/* Given a pointer to a floating point register set in /proc format
348 (fpregset_t *), unpack the register contents and supply them as gdb's
1777feb0 349 idea of the current floating point register values. */
50306a9d
RC
350
351void
7f7fe91e 352supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
50306a9d 353{
1b89295f 354 int regi;
7f7fe91e 355 const char *from;
50306a9d
RC
356
357 for (regi = 0; regi <= 31; regi++)
358 {
7f7fe91e 359 from = (const char *) &((*fpregsetp)[regi]);
73e1c03f
SM
360 regcache->raw_supply (2*regi + HPPA_FP0_REGNUM, from);
361 regcache->raw_supply (2*regi + HPPA_FP0_REGNUM + 1, from + 4);
50306a9d
RC
362 }
363}
364
365/* Given a pointer to a floating point register set in /proc format
366 (fpregset_t *), update the register specified by REGNO from gdb's idea
367 of the current floating point register set. If REGNO is -1, update
1777feb0 368 them all. */
50306a9d
RC
369
370void
7f7fe91e
UW
371fill_fpregset (const struct regcache *regcache,
372 gdb_fpregset_t *fpregsetp, int regno)
50306a9d
RC
373{
374 int i;
375
959464ff 376 for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 32 * 2; i++)
50306a9d 377 {
959464ff
RC
378 /* Gross. fpregset_t is double, registers[x] has single
379 precision reg. */
380 char *to = (char *) &((*fpregsetp)[(i - HPPA_FP0_REGNUM) / 2]);
381 if ((i - HPPA_FP0_REGNUM) & 1)
382 to += 4;
34a79281 383 regcache->raw_collect (i, to);
50306a9d
RC
384 }
385}
10d6c8cd 386
10d6c8cd
DJ
387void
388_initialize_hppa_linux_nat (void)
389{
10d6c8cd 390 /* Register the target. */
f6ac5f3d 391 linux_target = &the_hppa_linux_nat_target;
d9f719f1 392 add_inf_child_target (&the_hppa_linux_nat_target);
10d6c8cd 393}
This page took 1.136347 seconds and 4 git commands to generate.