+/* 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;
+}