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

Subversion Repositories openrisc_me

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

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

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

powered by: WebSVN 2.1.0

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