/* 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); } }
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; }
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 (¤t_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; }