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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [spu-multiarch.c] - Blame information for rev 855

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

Line No. Rev Author Line
1 227 jeremybenn
/* Cell SPU GNU/Linux multi-architecture debugging support.
2
   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
3
 
4
   Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
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 "gdbcmd.h"
24
#include "gdb_string.h"
25
#include "gdb_assert.h"
26
#include "arch-utils.h"
27
#include "observer.h"
28
#include "inferior.h"
29
#include "regcache.h"
30
#include "symfile.h"
31
#include "objfiles.h"
32
#include "solib.h"
33
#include "solist.h"
34
 
35
#include "ppc-tdep.h"
36
#include "ppc-linux-tdep.h"
37
#include "spu-tdep.h"
38
 
39
/* This module's target vector.  */
40
static struct target_ops spu_ops;
41
 
42
/* Number of SPE objects loaded into the current inferior.  */
43
static int spu_nr_solib;
44
 
45
/* Stand-alone SPE executable?  */
46
#define spu_standalone_p() \
47
  (symfile_objfile && symfile_objfile->obfd \
48
   && bfd_get_arch (symfile_objfile->obfd) == bfd_arch_spu)
49
 
50
/* PPU side system calls.  */
51
#define INSTR_SC        0x44000002
52
#define NR_spu_run      0x0116
53
 
54
/* If the PPU thread is currently stopped on a spu_run system call,
55
   return to FD and ADDR the file handle and NPC parameter address
56
   used with the system call.  Return non-zero if successful.  */
57
static int
58
parse_spufs_run (ptid_t ptid, int *fd, CORE_ADDR *addr)
59
{
60
  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
61
  struct gdbarch_tdep *tdep;
62
  struct regcache *regcache;
63
  char buf[4];
64
  CORE_ADDR pc;
65
  ULONGEST regval;
66
 
67
  /* If we're not on PPU, there's nothing to detect.  */
68
  if (gdbarch_bfd_arch_info (target_gdbarch)->arch != bfd_arch_powerpc)
69
    return 0;
70
 
71
  /* Get PPU-side registers.  */
72
  regcache = get_thread_arch_regcache (ptid, target_gdbarch);
73
  tdep = gdbarch_tdep (target_gdbarch);
74
 
75
  /* Fetch instruction preceding current NIP.  */
76
  if (target_read_memory (regcache_read_pc (regcache) - 4, buf, 4) != 0)
77
    return 0;
78
  /* It should be a "sc" instruction.  */
79
  if (extract_unsigned_integer (buf, 4, byte_order) != INSTR_SC)
80
    return 0;
81
  /* System call number should be NR_spu_run.  */
82
  regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum, &regval);
83
  if (regval != NR_spu_run)
84
    return 0;
85
 
86
  /* Register 3 contains fd, register 4 the NPC param pointer.  */
87
  regcache_cooked_read_unsigned (regcache, PPC_ORIG_R3_REGNUM, &regval);
88
  *fd = (int) regval;
89
  regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 4, &regval);
90
  *addr = (CORE_ADDR) regval;
91
  return 1;
92
}
93
 
94
/* Find gdbarch for SPU context SPUFS_FD.  */
95
static struct gdbarch *
96
spu_gdbarch (int spufs_fd)
97
{
98
  struct gdbarch_info info;
99
  gdbarch_info_init (&info);
100
  info.bfd_arch_info = bfd_lookup_arch (bfd_arch_spu, bfd_mach_spu);
101
  info.byte_order = BFD_ENDIAN_BIG;
102
  info.osabi = GDB_OSABI_LINUX;
103
  info.tdep_info = (void *) &spufs_fd;
104
  return gdbarch_find_by_info (info);
105
}
106
 
107
/* Override the to_thread_architecture routine.  */
108
static struct gdbarch *
109
spu_thread_architecture (struct target_ops *ops, ptid_t ptid)
110
{
111
  int spufs_fd;
112
  CORE_ADDR spufs_addr;
113
 
114
  if (parse_spufs_run (ptid, &spufs_fd, &spufs_addr))
115
    return spu_gdbarch (spufs_fd);
116
 
117
  return target_gdbarch;
118
}
119
 
120
/* Override the to_region_ok_for_hw_watchpoint routine.  */
121
static int
122
spu_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
123
{
124
  struct target_ops *ops_beneath = find_target_beneath (&spu_ops);
125
  while (ops_beneath && !ops_beneath->to_region_ok_for_hw_watchpoint)
126
    ops_beneath = find_target_beneath (ops_beneath);
127
 
128
  /* We cannot watch SPU local store.  */
129
  if (SPUADDR_SPU (addr) != -1)
130
    return 0;
131
 
132
  if (ops_beneath)
133
    return ops_beneath->to_region_ok_for_hw_watchpoint (addr, len);
134
 
135
  return 0;
136
}
137
 
138
/* Override the to_fetch_registers routine.  */
139
static void
140
spu_fetch_registers (struct target_ops *ops,
141
                     struct regcache *regcache, int regno)
142
{
143
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
144
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
145
  struct target_ops *ops_beneath = find_target_beneath (ops);
146
  int spufs_fd;
147
  CORE_ADDR spufs_addr;
148
 
149
  /* This version applies only if we're currently in spu_run.  */
150
  if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu)
151
    {
152
      while (ops_beneath && !ops_beneath->to_fetch_registers)
153
        ops_beneath = find_target_beneath (ops_beneath);
154
 
155
      gdb_assert (ops_beneath);
156
      ops_beneath->to_fetch_registers (ops_beneath, regcache, regno);
157
      return;
158
    }
159
 
160
  /* We must be stopped on a spu_run system call.  */
161
  if (!parse_spufs_run (inferior_ptid, &spufs_fd, &spufs_addr))
162
    return;
163
 
164
  /* The ID register holds the spufs file handle.  */
165
  if (regno == -1 || regno == SPU_ID_REGNUM)
166
    {
167
      char buf[4];
168
      store_unsigned_integer (buf, 4, byte_order, spufs_fd);
169
      regcache_raw_supply (regcache, SPU_ID_REGNUM, buf);
170
    }
171
 
172
  /* The NPC register is found in PPC memory at SPUFS_ADDR.  */
173
  if (regno == -1 || regno == SPU_PC_REGNUM)
174
    {
175
      char buf[4];
176
 
177
      if (target_read (ops_beneath, TARGET_OBJECT_MEMORY, NULL,
178
                       buf, spufs_addr, sizeof buf) == sizeof buf)
179
        regcache_raw_supply (regcache, SPU_PC_REGNUM, buf);
180
    }
181
 
182
  /* The GPRs are found in the "regs" spufs file.  */
183
  if (regno == -1 || (regno >= 0 && regno < SPU_NUM_GPRS))
184
    {
185
      char buf[16 * SPU_NUM_GPRS], annex[32];
186
      int i;
187
 
188
      xsnprintf (annex, sizeof annex, "%d/regs", spufs_fd);
189
      if (target_read (ops_beneath, TARGET_OBJECT_SPU, annex,
190
                       buf, 0, sizeof buf) == sizeof buf)
191
        for (i = 0; i < SPU_NUM_GPRS; i++)
192
          regcache_raw_supply (regcache, i, buf + i*16);
193
    }
194
}
195
 
196
/* Override the to_store_registers routine.  */
197
static void
198
spu_store_registers (struct target_ops *ops,
199
                     struct regcache *regcache, int regno)
200
{
201
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
202
  struct target_ops *ops_beneath = find_target_beneath (ops);
203
  int spufs_fd;
204
  CORE_ADDR spufs_addr;
205
 
206
  /* This version applies only if we're currently in spu_run.  */
207
  if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu)
208
    {
209
      while (ops_beneath && !ops_beneath->to_fetch_registers)
210
        ops_beneath = find_target_beneath (ops_beneath);
211
 
212
      gdb_assert (ops_beneath);
213
      ops_beneath->to_store_registers (ops_beneath, regcache, regno);
214
      return;
215
    }
216
 
217
  /* We must be stopped on a spu_run system call.  */
218
  if (!parse_spufs_run (inferior_ptid, &spufs_fd, &spufs_addr))
219
    return;
220
 
221
  /* The NPC register is found in PPC memory at SPUFS_ADDR.  */
222
  if (regno == -1 || regno == SPU_PC_REGNUM)
223
    {
224
      char buf[4];
225
      regcache_raw_collect (regcache, SPU_PC_REGNUM, buf);
226
 
227
      target_write (ops_beneath, TARGET_OBJECT_MEMORY, NULL,
228
                    buf, spufs_addr, sizeof buf);
229
    }
230
 
231
  /* The GPRs are found in the "regs" spufs file.  */
232
  if (regno == -1 || (regno >= 0 && regno < SPU_NUM_GPRS))
233
    {
234
      char buf[16 * SPU_NUM_GPRS], annex[32];
235
      int i;
236
 
237
      for (i = 0; i < SPU_NUM_GPRS; i++)
238
        regcache_raw_collect (regcache, i, buf + i*16);
239
 
240
      xsnprintf (annex, sizeof annex, "%d/regs", spufs_fd);
241
      target_write (ops_beneath, TARGET_OBJECT_SPU, annex,
242
                    buf, 0, sizeof buf);
243
    }
244
}
245
 
246
/* Override the to_xfer_partial routine.  */
247
static LONGEST
248
spu_xfer_partial (struct target_ops *ops, enum target_object object,
249
                  const char *annex, gdb_byte *readbuf,
250
                  const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
251
{
252
  struct target_ops *ops_beneath = find_target_beneath (ops);
253
  while (ops_beneath && !ops_beneath->to_xfer_partial)
254
    ops_beneath = find_target_beneath (ops_beneath);
255
  gdb_assert (ops_beneath);
256
 
257
  /* Use the "mem" spufs file to access SPU local store.  */
258
  if (object == TARGET_OBJECT_MEMORY)
259
    {
260
      int fd = SPUADDR_SPU (offset);
261
      CORE_ADDR addr = SPUADDR_ADDR (offset);
262
      char mem_annex[32];
263
 
264
      if (fd >= 0 && addr < SPU_LS_SIZE)
265
        {
266
          xsnprintf (mem_annex, sizeof mem_annex, "%d/mem", fd);
267
          return ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU,
268
                                               mem_annex, readbuf, writebuf,
269
                                               addr, len);
270
        }
271
    }
272
 
273
  return ops_beneath->to_xfer_partial (ops_beneath, object, annex,
274
                                       readbuf, writebuf, offset, len);
275
}
276
 
277
/* Override the to_search_memory routine.  */
278
static int
279
spu_search_memory (struct target_ops* ops,
280
                   CORE_ADDR start_addr, ULONGEST search_space_len,
281
                   const gdb_byte *pattern, ULONGEST pattern_len,
282
                   CORE_ADDR *found_addrp)
283
{
284
  struct target_ops *ops_beneath = find_target_beneath (ops);
285
  while (ops_beneath && !ops_beneath->to_search_memory)
286
    ops_beneath = find_target_beneath (ops_beneath);
287
 
288
  /* For SPU local store, always fall back to the simple method.  Likewise
289
     if we do not have any target-specific special implementation.  */
290
  if (!ops_beneath || SPUADDR_SPU (start_addr) >= 0)
291
    return simple_search_memory (ops,
292
                                 start_addr, search_space_len,
293
                                 pattern, pattern_len, found_addrp);
294
 
295
  return ops_beneath->to_search_memory (ops_beneath,
296
                                        start_addr, search_space_len,
297
                                        pattern, pattern_len, found_addrp);
298
}
299
 
300
 
301
/* Push and pop the SPU multi-architecture support target.  */
302
 
303
static void
304
spu_multiarch_activate (void)
305
{
306
  /* If GDB was configured without SPU architecture support,
307
     we cannot install SPU multi-architecture support either.  */
308
  if (spu_gdbarch (-1) == NULL)
309
    return;
310
 
311
  push_target (&spu_ops);
312
 
313
  /* Make sure the thread architecture is re-evaluated.  */
314
  registers_changed ();
315
}
316
 
317
static void
318
spu_multiarch_deactivate (void)
319
{
320
  unpush_target (&spu_ops);
321
 
322
  /* Make sure the thread architecture is re-evaluated.  */
323
  registers_changed ();
324
}
325
 
326
static void
327
spu_multiarch_inferior_created (struct target_ops *ops, int from_tty)
328
{
329
  if (spu_standalone_p ())
330
    spu_multiarch_activate ();
331
}
332
 
333
static void
334
spu_multiarch_solib_loaded (struct so_list *so)
335
{
336
  if (!spu_standalone_p ())
337
    if (so->abfd && bfd_get_arch (so->abfd) == bfd_arch_spu)
338
      if (spu_nr_solib++ == 0)
339
        spu_multiarch_activate ();
340
}
341
 
342
static void
343
spu_multiarch_solib_unloaded (struct so_list *so)
344
{
345
  if (!spu_standalone_p ())
346
    if (so->abfd && bfd_get_arch (so->abfd) == bfd_arch_spu)
347
      if (--spu_nr_solib == 0)
348
        spu_multiarch_deactivate ();
349
}
350
 
351
static void
352
spu_mourn_inferior (struct target_ops *ops)
353
{
354
  struct target_ops *ops_beneath = find_target_beneath (ops);
355
  while (ops_beneath && !ops_beneath->to_mourn_inferior)
356
    ops_beneath = find_target_beneath (ops_beneath);
357
 
358
  gdb_assert (ops_beneath);
359
  ops_beneath->to_mourn_inferior (ops_beneath);
360
  spu_multiarch_deactivate ();
361
}
362
 
363
 
364
/* Initialize the SPU multi-architecture support target.  */
365
 
366
static void
367
init_spu_ops (void)
368
{
369
  spu_ops.to_shortname = "spu";
370
  spu_ops.to_longname = "SPU multi-architecture support.";
371
  spu_ops.to_doc = "SPU multi-architecture support.";
372
  spu_ops.to_mourn_inferior = spu_mourn_inferior;
373
  spu_ops.to_fetch_registers = spu_fetch_registers;
374
  spu_ops.to_store_registers = spu_store_registers;
375
  spu_ops.to_xfer_partial = spu_xfer_partial;
376
  spu_ops.to_search_memory = spu_search_memory;
377
  spu_ops.to_region_ok_for_hw_watchpoint = spu_region_ok_for_hw_watchpoint;
378
  spu_ops.to_thread_architecture = spu_thread_architecture;
379
  spu_ops.to_stratum = arch_stratum;
380
  spu_ops.to_magic = OPS_MAGIC;
381
}
382
 
383
void
384
_initialize_spu_multiarch (void)
385
{
386
  /* Install ourselves on the target stack.  */
387
  init_spu_ops ();
388
  add_target (&spu_ops);
389
 
390
  /* Install observers to watch for SPU objects.  */
391
  observer_attach_inferior_created (spu_multiarch_inferior_created);
392
  observer_attach_solib_loaded (spu_multiarch_solib_loaded);
393
  observer_attach_solib_unloaded (spu_multiarch_solib_unloaded);
394
}
395
 

powered by: WebSVN 2.1.0

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