/* Override the to_store_registers routine.  */
static void
spu_store_registers (struct target_ops *ops,
		     struct regcache *regcache, int regno)
{
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  struct target_ops *ops_beneath = find_target_beneath (ops);
  int spufs_fd;
  CORE_ADDR spufs_addr;

  /* This version applies only if we're currently in spu_run.  */
  if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu)
    {
      while (ops_beneath && !ops_beneath->to_fetch_registers)
	ops_beneath = find_target_beneath (ops_beneath);

      gdb_assert (ops_beneath);
      ops_beneath->to_store_registers (ops_beneath, regcache, regno);
      return;
    }

  /* We must be stopped on a spu_run system call.  */
  if (!parse_spufs_run (inferior_ptid, &spufs_fd, &spufs_addr))
    return;

  /* The NPC register is found in PPC memory at SPUFS_ADDR.  */
  if (regno == -1 || regno == SPU_PC_REGNUM)
    {
      gdb_byte buf[4];
      regcache_raw_collect (regcache, SPU_PC_REGNUM, buf);

      target_write (ops_beneath, TARGET_OBJECT_MEMORY, NULL,
		    buf, spufs_addr, sizeof buf);
    }

  /* The GPRs are found in the "regs" spufs file.  */
  if (regno == -1 || (regno >= 0 && regno < SPU_NUM_GPRS))
    {
      gdb_byte buf[16 * SPU_NUM_GPRS];
      char annex[32];
      int i;

      for (i = 0; i < SPU_NUM_GPRS; i++)
	regcache_raw_collect (regcache, i, buf + i*16);

      xsnprintf (annex, sizeof annex, "%d/regs", spufs_fd);
      target_write (ops_beneath, TARGET_OBJECT_SPU, annex,
		    buf, 0, sizeof buf);
    }
}
Example #2
0
int
dcache_xfer_memory (struct target_ops *ops, DCACHE *dcache,
		    CORE_ADDR memaddr, gdb_byte *myaddr,
		    int len, int should_write)
{
  int i;
  int res;
  int (*xfunc) (DCACHE *dcache, CORE_ADDR addr, gdb_byte *ptr);

  xfunc = should_write ? dcache_poke_byte : dcache_peek_byte;

  /* If this is a different inferior from what we've recorded,
     flush the cache.  */

  if (! ptid_equal (inferior_ptid, dcache->ptid))
    {
      dcache_invalidate (dcache);
      dcache->ptid = inferior_ptid;
    }

  /* Do write-through first, so that if it fails, we don't write to
     the cache at all.  */

  if (should_write)
    {
      res = target_write (ops, TARGET_OBJECT_RAW_MEMORY,
			  NULL, myaddr, memaddr, len);
      if (res <= 0)
	return res;
      /* Update LEN to what was actually written.  */
      len = res;
    }
      
  for (i = 0; i < len; i++)
    {
      if (!xfunc (dcache, memaddr + i, myaddr + i))
	{
	  /* That failed.  Discard its cache line so we don't have a
	     partially read line.  */
	  dcache_invalidate_line (dcache, memaddr + i);
	  /* If we're writing, we still wrote LEN bytes.  */
	  if (should_write)
	    return len;
	  else
	    return i;
	}
    }
    
  return len;
}
Example #3
0
static int
dcache_write_line (DCACHE *dcache, struct dcache_block *db)
{
  CORE_ADDR memaddr;
  gdb_byte *myaddr;
  int len;
  int res;
  int reg_len;
  struct mem_region *region;

  if (!db->anydirty)
    return 1;

  len = LINE_SIZE;
  memaddr = db->addr;
  myaddr  = db->data;

  while (len > 0)
    {
      int s;
      int e;
      int dirty_len;
      
      region = lookup_mem_region(memaddr);
      if (memaddr + len < region->hi)
	reg_len = len;
      else
	reg_len = region->hi - memaddr;

      if (!region->attrib.cache || region->attrib.mode == MEM_RO)
	{
	  memaddr += reg_len;
	  myaddr  += reg_len;
	  len     -= reg_len;
	  continue;
	}

      while (reg_len > 0)
	{
	  s = XFORM(memaddr);
	  while (reg_len > 0) {
	    if (db->state[s] == ENTRY_DIRTY)
	      break;
	    s++;
	    reg_len--;

	    memaddr++;
	    myaddr++;
	    len--;
	  }

	  e = s;
	  while (reg_len > 0) {
	    if (db->state[e] != ENTRY_DIRTY)
	      break;
	    e++;
	    reg_len--;
	  }

	  dirty_len = e - s;
	  res = target_write (&current_target, TARGET_OBJECT_RAW_MEMORY,
			      NULL, myaddr, memaddr, dirty_len);
	  if (res < dirty_len)
	    return 0;

	  memset (&db->state[XFORM(memaddr)], ENTRY_VALID, res);
	  memaddr += res;
	  myaddr += res;
	  len -= res;
	}
    }

  db->anydirty = 0;
  return 1;
}