/* Read cache line */ static int dcache_read_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 there are any dirty bytes in the line, it must be written before a new line can be read */ if (db->anydirty) { if (!dcache_write_line (dcache, db)) return 0; } len = LINE_SIZE; memaddr = db->addr; myaddr = db->data; while (len > 0) { 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_WO) { memaddr += reg_len; myaddr += reg_len; len -= reg_len; continue; } while (reg_len > 0) { res = do_xfer_memory (memaddr, myaddr, reg_len, 0, ®ion->attrib); if (res <= 0) return 0; memaddr += res; myaddr += res; len -= res; reg_len -= res; } } memset (db->state, ENTRY_OK, sizeof (db->data)); db->anydirty = 0; return 1; }
/* Read cache line */ static int dcache_read_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 there are any dirty bytes in the line, it must be written before a new line can be read */ if (db->anydirty) { if (!dcache_write_line (dcache, db)) return 0; } len = LINE_SIZE; memaddr = db->addr; myaddr = db->data; while (len > 0) { 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_WO) { memaddr += reg_len; myaddr += reg_len; len -= reg_len; continue; } res = target_read (¤t_target, TARGET_OBJECT_RAW_MEMORY, NULL, myaddr, memaddr, reg_len); if (res < reg_len) return 0; memaddr += res; myaddr += res; len -= res; } memset (db->state, ENTRY_VALID, sizeof (db->data)); db->anydirty = 0; return 1; }
static int dcache_read_line (DCACHE *dcache, struct dcache_block *db) { CORE_ADDR memaddr; gdb_byte *myaddr; int len; int res; int reg_len; struct mem_region *region; len = LINE_SIZE; memaddr = db->addr; myaddr = db->data; while (len > 0) { /* Don't overrun if this block is right at the end of the region. */ region = lookup_mem_region (memaddr); if (region->hi == 0 || memaddr + len < region->hi) reg_len = len; else reg_len = region->hi - memaddr; /* Skip non-readable regions. The cache attribute can be ignored, since we may be loading this for a stack access. */ if (region->attrib.mode == MEM_WO) { memaddr += reg_len; myaddr += reg_len; len -= reg_len; continue; } res = target_read (¤t_target, TARGET_OBJECT_RAW_MEMORY, NULL, myaddr, memaddr, reg_len); if (res < reg_len) return 0; memaddr += res; myaddr += res; len -= res; } return 1; }
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; while (dirty_len > 0) { res = do_xfer_memory(memaddr, myaddr, dirty_len, 1, ®ion->attrib); if (res <= 0) return 0; memset (&db->state[XFORM(memaddr)], ENTRY_OK, res); memaddr += res; myaddr += res; len -= res; dirty_len -= res; } } } db->anydirty = 0; return 1; }
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; }