OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [gdb/] [hppa-linux-nat.c] - Blame information for rev 258

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.