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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [gdb/] [spu-multiarch.c] - Blame information for rev 861

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

Line No. Rev Author Line
1 330 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], lslr_annex[32];
263
      gdb_byte buf[32];
264
      ULONGEST lslr;
265
      LONGEST ret;
266
 
267
      if (fd >= 0)
268
        {
269
          xsnprintf (mem_annex, sizeof mem_annex, "%d/mem", fd);
270
          ret = ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU,
271
                                              mem_annex, readbuf, writebuf,
272
                                              addr, len);
273
          if (ret > 0)
274
            return ret;
275
 
276
          /* SPU local store access wraps the address around at the
277
             local store limit.  We emulate this here.  To avoid needing
278
             an extra access to retrieve the LSLR, we only do that after
279
             trying the original address first, and getting end-of-file.  */
280
          xsnprintf (lslr_annex, sizeof lslr_annex, "%d/lslr", fd);
281
          memset (buf, 0, sizeof buf);
282
          if (ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU,
283
                                            lslr_annex, buf, NULL,
284
                                            0, sizeof buf) <= 0)
285
            return ret;
286
 
287
          lslr = strtoulst (buf, NULL, 16);
288
          return ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU,
289
                                               mem_annex, readbuf, writebuf,
290
                                               addr & lslr, len);
291
        }
292
    }
293
 
294
  return ops_beneath->to_xfer_partial (ops_beneath, object, annex,
295
                                       readbuf, writebuf, offset, len);
296
}
297
 
298
/* Override the to_search_memory routine.  */
299
static int
300
spu_search_memory (struct target_ops* ops,
301
                   CORE_ADDR start_addr, ULONGEST search_space_len,
302
                   const gdb_byte *pattern, ULONGEST pattern_len,
303
                   CORE_ADDR *found_addrp)
304
{
305
  struct target_ops *ops_beneath = find_target_beneath (ops);
306
  while (ops_beneath && !ops_beneath->to_search_memory)
307
    ops_beneath = find_target_beneath (ops_beneath);
308
 
309
  /* For SPU local store, always fall back to the simple method.  Likewise
310
     if we do not have any target-specific special implementation.  */
311
  if (!ops_beneath || SPUADDR_SPU (start_addr) >= 0)
312
    return simple_search_memory (ops,
313
                                 start_addr, search_space_len,
314
                                 pattern, pattern_len, found_addrp);
315
 
316
  return ops_beneath->to_search_memory (ops_beneath,
317
                                        start_addr, search_space_len,
318
                                        pattern, pattern_len, found_addrp);
319
}
320
 
321
 
322
/* Push and pop the SPU multi-architecture support target.  */
323
 
324
static void
325
spu_multiarch_activate (void)
326
{
327
  /* If GDB was configured without SPU architecture support,
328
     we cannot install SPU multi-architecture support either.  */
329
  if (spu_gdbarch (-1) == NULL)
330
    return;
331
 
332
  push_target (&spu_ops);
333
 
334
  /* Make sure the thread architecture is re-evaluated.  */
335
  registers_changed ();
336
}
337
 
338
static void
339
spu_multiarch_deactivate (void)
340
{
341
  unpush_target (&spu_ops);
342
 
343
  /* Make sure the thread architecture is re-evaluated.  */
344
  registers_changed ();
345
}
346
 
347
static void
348
spu_multiarch_inferior_created (struct target_ops *ops, int from_tty)
349
{
350
  if (spu_standalone_p ())
351
    spu_multiarch_activate ();
352
}
353
 
354
static void
355
spu_multiarch_solib_loaded (struct so_list *so)
356
{
357
  if (!spu_standalone_p ())
358
    if (so->abfd && bfd_get_arch (so->abfd) == bfd_arch_spu)
359
      if (spu_nr_solib++ == 0)
360
        spu_multiarch_activate ();
361
}
362
 
363
static void
364
spu_multiarch_solib_unloaded (struct so_list *so)
365
{
366
  if (!spu_standalone_p ())
367
    if (so->abfd && bfd_get_arch (so->abfd) == bfd_arch_spu)
368
      if (--spu_nr_solib == 0)
369
        spu_multiarch_deactivate ();
370
}
371
 
372
static void
373
spu_mourn_inferior (struct target_ops *ops)
374
{
375
  struct target_ops *ops_beneath = find_target_beneath (ops);
376
  while (ops_beneath && !ops_beneath->to_mourn_inferior)
377
    ops_beneath = find_target_beneath (ops_beneath);
378
 
379
  gdb_assert (ops_beneath);
380
  ops_beneath->to_mourn_inferior (ops_beneath);
381
  spu_multiarch_deactivate ();
382
}
383
 
384
 
385
/* Initialize the SPU multi-architecture support target.  */
386
 
387
static void
388
init_spu_ops (void)
389
{
390
  spu_ops.to_shortname = "spu";
391
  spu_ops.to_longname = "SPU multi-architecture support.";
392
  spu_ops.to_doc = "SPU multi-architecture support.";
393
  spu_ops.to_mourn_inferior = spu_mourn_inferior;
394
  spu_ops.to_fetch_registers = spu_fetch_registers;
395
  spu_ops.to_store_registers = spu_store_registers;
396
  spu_ops.to_xfer_partial = spu_xfer_partial;
397
  spu_ops.to_search_memory = spu_search_memory;
398
  spu_ops.to_region_ok_for_hw_watchpoint = spu_region_ok_for_hw_watchpoint;
399
  spu_ops.to_thread_architecture = spu_thread_architecture;
400
  spu_ops.to_stratum = arch_stratum;
401
  spu_ops.to_magic = OPS_MAGIC;
402
}
403
 
404
void
405
_initialize_spu_multiarch (void)
406
{
407
  /* Install ourselves on the target stack.  */
408
  init_spu_ops ();
409
  add_target (&spu_ops);
410
 
411
  /* Install observers to watch for SPU objects.  */
412
  observer_attach_inferior_created (spu_multiarch_inferior_created);
413
  observer_attach_solib_loaded (spu_multiarch_solib_loaded);
414
  observer_attach_solib_unloaded (spu_multiarch_solib_unloaded);
415
}
416
 

powered by: WebSVN 2.1.0

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