-/* Caching code. Typically used by remote back ends for
- caching remote memory.
-
- Copyright 1992-1993, 1995, 1998-1999 Free Software Foundation, Inc.
+/* Caching code.
+ Copyright 1992-1993, 1995, 1998-1999, 2000 Free Software Foundation, Inc.
This file is part of GDB.
#include "gdbcmd.h"
#include "gdb_string.h"
#include "gdbcore.h"
+#include "target.h"
/*
The data cache could lead to incorrect results because it doesn't know
struct dcache_struct
{
- /* Function to actually read the target memory. */
- memxferfunc read_memory;
-
- /* Function to actually write the target memory */
- memxferfunc write_memory;
-
/* free list */
struct dcache_block *free_head;
struct dcache_block *free_tail;
int cache_has_stuff;
};
-static int dcache_poke_byte (DCACHE * dcache, CORE_ADDR addr, char *ptr);
+static int dcache_poke_byte (DCACHE *dcache, CORE_ADDR addr, char *ptr);
-static int dcache_peek_byte (DCACHE * dcache, CORE_ADDR addr, char *ptr);
+static int dcache_peek_byte (DCACHE *dcache, CORE_ADDR addr, char *ptr);
-static struct dcache_block *dcache_hit (DCACHE * dcache, CORE_ADDR addr);
+static struct dcache_block *dcache_hit (DCACHE *dcache, CORE_ADDR addr);
-static int dcache_write_line (DCACHE * dcache, struct dcache_block *db);
+static int dcache_write_line (DCACHE *dcache, struct dcache_block *db);
-static struct dcache_block *dcache_alloc (DCACHE * dcache, CORE_ADDR addr);
+static int dcache_read_line (DCACHE *dcache, struct dcache_block *db);
-static int dcache_writeback (DCACHE * dcache);
+static struct dcache_block *dcache_alloc (DCACHE *dcache, CORE_ADDR addr);
+
+static int dcache_writeback (DCACHE *dcache);
static void dcache_info (char *exp, int tty);
/* Free all the data cache blocks, thus discarding all cached data. */
void
-dcache_invd (DCACHE *dcache)
+dcache_invalidate (DCACHE *dcache)
{
int i;
dcache->valid_head = 0;
{
int s;
int e;
- s = 0;
+
if (db->anydirty)
{
for (s = 0; s < LINE_SIZE; s++)
int done = 0;
while (done < len)
{
- int t = dcache->write_memory (db->addr + s + done,
- db->data + s + done,
- len - done);
- if (t == 0)
+ int t = do_xfer_memory (db->addr + s + done,
+ db->data + s + done,
+ len - done, 1);
+ if (t <= 0)
return 0;
done += t;
}
return 1;
}
+/* Read cache line */
+static int
+dcache_read_line (DCACHE *dcache, struct dcache_block *db)
+{
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int res;
+
+ /* 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)
+ {
+ res = do_xfer_memory (memaddr, myaddr, len, 0);
+ if (res <= 0)
+ return 0;
+
+ memaddr += res;
+ myaddr += res;
+ len -= res;
+ }
+
+ memset (db->state, ENTRY_OK, sizeof (db->data));
+ db->anydirty = 0;
+
+ return 1;
+}
/* Get a free cache block, put or keep it on the valid list,
and return its address. */
{
/* Nothing left on free list, so grab one from the valid list */
db = dcache->valid_head;
- dcache->valid_head = db->p;
- dcache_write_line (dcache, db);
+ if (!dcache_write_line (dcache, db))
+ return NULL;
+
+ dcache->valid_head = db->p;
}
db->addr = MASK(addr);
return db;
}
-/* Using the data cache DCACHE return the contents of the byte at
- address ADDR in the remote machine.
-
- Returns 0 on error. */
-
-static int
-dcache_peek_byte (DCACHE *dcache, CORE_ADDR addr, char *ptr)
-{
- register struct dcache_block *db = dcache_hit (dcache, addr);
- int ok = 1;
- int done = 0;
- if (db == 0
- || db->state[XFORM (addr)] == ENTRY_BAD)
- {
- if (db)
- {
- dcache_write_line (dcache, db);
- }
- else
- db = dcache_alloc (dcache, addr);
-
- immediate_quit++;
- while (done < LINE_SIZE)
- {
- int try =
- (*dcache->read_memory)
- (db->addr + done,
- db->data + done,
- LINE_SIZE - done);
- if (try == 0)
- return 0;
- done += try;
- }
- immediate_quit--;
-
- memset (db->state, ENTRY_OK, sizeof (db->data));
- db->anydirty = 0;
- }
- *ptr = db->data[XFORM (addr)];
- return ok;
-}
-
/* Writeback any dirty lines to the remote. */
static int
dcache_writeback (DCACHE *dcache)
}
+/* Using the data cache DCACHE return the contents of the byte at
+ address ADDR in the remote machine.
+
+ Returns 0 on error. */
+
+static int
+dcache_peek_byte (DCACHE *dcache, CORE_ADDR addr, char *ptr)
+{
+ register struct dcache_block *db = dcache_hit (dcache, addr);
+
+ if (!db)
+ {
+ db = dcache_alloc (dcache, addr);
+ if (!db)
+ return 0;
+ }
+
+ if (db->state[XFORM (addr)] == ENTRY_BAD)
+ {
+ if (!dcache_read_line(dcache, db))
+ return 0;
+ }
+
+ *ptr = db->data[XFORM (addr)];
+ return 1;
+}
+
+
/* Write the byte at PTR into ADDR in the data cache.
Return zero on write error.
*/
if (!db)
{
db = dcache_alloc (dcache, addr);
+ if (!db)
+ return 0;
}
db->data[XFORM (addr)] = *ptr;
/* Initialize the data cache. */
DCACHE *
-dcache_init (memxferfunc reading, memxferfunc writing)
+dcache_init (void)
{
int csize = sizeof (struct dcache_block) * DCACHE_SIZE;
DCACHE *dcache;
dcache = (DCACHE *) xmalloc (sizeof (*dcache));
- dcache->read_memory = reading;
- dcache->write_memory = writing;
dcache->the_cache = (struct dcache_block *) xmalloc (csize);
memset (dcache->the_cache, 0, csize);
- dcache_invd (dcache);
+ dcache_invalidate (dcache);
last_cache = dcache;
return dcache;
if (dcache_enabled_p)
{
- int (*xfunc) (DCACHE * dcache, CORE_ADDR addr, char *ptr);
+ int (*xfunc) (DCACHE *dcache, CORE_ADDR addr, char *ptr);
xfunc = should_write ? dcache_poke_byte : dcache_peek_byte;
for (i = 0; i < len; i++)
if (!xfunc (dcache, memaddr + i, myaddr + i))
return 0;
}
+
+ if (should_write)
+ dcache_writeback (dcache);
+
dcache->cache_has_stuff = 1;
- dcache_writeback (dcache);
}
else
{
- memxferfunc xfunc;
- xfunc = should_write ? dcache->write_memory : dcache->read_memory;
-
if (dcache->cache_has_stuff)
- dcache_invd (dcache);
+ dcache_invalidate (dcache);
- len = xfunc (memaddr, myaddr, len);
+ len = do_xfer_memory(memaddr, myaddr, len, should_write);
}
return len;
}
printf_filtered ("\n");
for (j = 0; j < LINE_SIZE; j++)
- printf_filtered (" %2x", p->state[j]);
+ printf_filtered ("%2x", p->state[j]);
printf_filtered ("\n");
}
}