/* 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; }
/* Writeback any dirty lines. */ static int dcache_writeback (DCACHE *dcache) { struct dcache_block *db; db = dcache->valid_head; while (db) { if (!dcache_write_line (dcache, db)) return 0; db = db->p; } return 1; }
static struct dcache_block * dcache_alloc (DCACHE *dcache, CORE_ADDR addr) { struct dcache_block *db; /* Take something from the free list */ db = dcache->free_head; if (db) { dcache->free_head = db->p; } else { /* Nothing left on free list, so grab one from the valid list */ db = dcache->valid_head; if (!dcache_write_line (dcache, db)) return NULL; dcache->valid_head = db->p; } db->addr = MASK(addr); db->refs = 0; db->anydirty = 0; memset (db->state, ENTRY_BAD, sizeof (db->data)); /* append this line to end of valid list */ if (!dcache->valid_head) dcache->valid_head = db; else dcache->valid_tail->p = db; dcache->valid_tail = db; db->p = 0; return db; }