mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:51:15 +08:00
break dcache code out of remote.c
This commit is contained in:
parent
46cf424778
commit
d538b510a0
@ -1,5 +1,18 @@
|
||||
Tue Aug 31 15:01:27 1993 K. Richard Pixley (rich@sendai.cygnus.com)
|
||||
|
||||
Break dcache code out of remote.c.
|
||||
* dcache.h: white space changes only.
|
||||
* dcache.c: add user settable variable to set whether data caching
|
||||
is in use.
|
||||
* remote.c: include dcache.h. removed data caching code which is
|
||||
now in dcache.c. Compile in data caching again. (data caching
|
||||
is currently off by default.)
|
||||
(remote_read_bytes, remote_write_bytes): change second arg to
|
||||
unsigned char.
|
||||
(remote_dcache): new static variable.
|
||||
* Makefile.in (REMOTE_O): add dcache.o.
|
||||
* config/m88k/m88k.mt (TDEPFILES): removed dcache.o.
|
||||
|
||||
Break dcache code out of remote-bug.c into dcache.[hc].
|
||||
* Makefile.in (dcache_h): new macro.
|
||||
(HFILES): added $(dcache_h).
|
||||
|
@ -189,7 +189,7 @@ SER_HARDWIRE=ser-unix.o
|
||||
|
||||
# The `remote' debugging target is supported for most architectures,
|
||||
# but not all (e.g. 960)
|
||||
REMOTE_O=remote.o
|
||||
REMOTE_O = remote.o dcache.o
|
||||
|
||||
# Host and target-dependent makefile fragments come in here.
|
||||
####
|
||||
|
67
gdb/dcache.c
67
gdb/dcache.c
@ -21,10 +21,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "dcache.h"
|
||||
#include "gdbcmd.h"
|
||||
|
||||
extern int insque();
|
||||
extern int remque();
|
||||
|
||||
int remote_dcache = 0;
|
||||
|
||||
/* The data cache records all the data read from the remote machine
|
||||
since the last time it stopped.
|
||||
|
||||
@ -41,17 +44,21 @@ dcache_flush (dcache)
|
||||
{
|
||||
register struct dcache_block *db;
|
||||
|
||||
while ((db = dcache->dcache_valid.next) != &dcache->dcache_valid)
|
||||
{
|
||||
remque (db);
|
||||
insque (db, &dcache->dcache_free);
|
||||
}
|
||||
if (remote_dcache > 0)
|
||||
while ((db = dcache->dcache_valid.next) != &dcache->dcache_valid)
|
||||
{
|
||||
remque (db);
|
||||
insque (db, &dcache->dcache_free);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If addr is present in the dcache, return the address of the block
|
||||
* containing it.
|
||||
*/
|
||||
static
|
||||
struct dcache_block *
|
||||
dcache_hit (dcache, addr)
|
||||
DCACHE *dcache;
|
||||
@ -59,7 +66,8 @@ dcache_hit (dcache, addr)
|
||||
{
|
||||
register struct dcache_block *db;
|
||||
|
||||
if (addr & 3)
|
||||
if (addr & 3
|
||||
|| remote_dcache == 0)
|
||||
abort ();
|
||||
|
||||
/* Search all cache blocks for one that is at this address. */
|
||||
@ -70,16 +78,19 @@ dcache_hit (dcache, addr)
|
||||
return db;
|
||||
db = db->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return the int data at address ADDR in dcache block DC. */
|
||||
static
|
||||
int
|
||||
dcache_value (db, addr)
|
||||
struct dcache_block *db;
|
||||
unsigned int addr;
|
||||
{
|
||||
if (addr & 3)
|
||||
if (addr & 3
|
||||
|| remote_dcache == 0)
|
||||
abort ();
|
||||
return (db->data[XFORM (addr)]);
|
||||
}
|
||||
@ -91,12 +102,16 @@ dcache_value (db, addr)
|
||||
prevents errors from creeping in if a memory retrieval is
|
||||
interrupted (which used to put garbage blocks in the valid
|
||||
list...). */
|
||||
static
|
||||
struct dcache_block *
|
||||
dcache_alloc (dcache)
|
||||
DCACHE *dcache;
|
||||
{
|
||||
register struct dcache_block *db;
|
||||
|
||||
if (remote_dcache == 0)
|
||||
abort();
|
||||
|
||||
if ((db = dcache->dcache_free.next) == &dcache->dcache_free)
|
||||
{
|
||||
/* If we can't get one from the free list, take last valid and put
|
||||
@ -111,8 +126,8 @@ dcache_alloc (dcache)
|
||||
return (db);
|
||||
}
|
||||
|
||||
/* Return the contents of the word at address ADDR in the remote machine,
|
||||
using the data cache. */
|
||||
/* Using the data cache DCACHE return the contents of the word at
|
||||
address ADDR in the remote machine. */
|
||||
int
|
||||
dcache_fetch (dcache, addr)
|
||||
DCACHE *dcache;
|
||||
@ -120,6 +135,14 @@ dcache_fetch (dcache, addr)
|
||||
{
|
||||
register struct dcache_block *db;
|
||||
|
||||
if (remote_dcache == 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
(*dcache->read_memory) (addr, (unsigned char *) &i, 4);
|
||||
return(i);
|
||||
}
|
||||
|
||||
db = dcache_hit (dcache, addr);
|
||||
if (db == 0)
|
||||
{
|
||||
@ -143,6 +166,12 @@ dcache_poke (dcache, addr, data)
|
||||
{
|
||||
register struct dcache_block *db;
|
||||
|
||||
if (remote_dcache == 0)
|
||||
{
|
||||
(*dcache->write_memory) (addr, (unsigned char *) &data, 4);
|
||||
return;
|
||||
}
|
||||
|
||||
/* First make sure the word is IN the cache. DB is its cache block. */
|
||||
db = dcache_hit (dcache, addr);
|
||||
if (db == 0)
|
||||
@ -152,8 +181,8 @@ dcache_poke (dcache, addr, data)
|
||||
(*dcache->write_memory) (addr & ~LINE_SIZE_MASK, (unsigned char *) db->data, LINE_SIZE);
|
||||
immediate_quit--;
|
||||
db->addr = addr & ~LINE_SIZE_MASK;
|
||||
remque (db); /* Off the free list */
|
||||
insque (db, &dcache->dcache_valid); /* On the valid list */
|
||||
remque (db); /* Off the free list */
|
||||
insque (db, &dcache->dcache_valid); /* On the valid list */
|
||||
}
|
||||
|
||||
/* Modify the word in the cache. */
|
||||
@ -188,3 +217,19 @@ dcache_init (reading, writing)
|
||||
return(dcache);
|
||||
}
|
||||
|
||||
void
|
||||
_initialitize_dcache ()
|
||||
{
|
||||
add_show_from_set
|
||||
(add_set_cmd ("remotecache", class_support, var_boolean,
|
||||
(char *) &remote_dcache,
|
||||
"\
|
||||
Set cache use for remote targets.\n\
|
||||
When on, use data caching for remote targets. For many remote targets\n\
|
||||
this option can offer better throughput for reading target memory.\n\
|
||||
Unfortunately, gdb does not currently know anything about volatile\n\
|
||||
registers and thus data caching will produce incorrect results with\n\
|
||||
volatile registers are in use. By default, this option is off.",
|
||||
&setlist),
|
||||
&showlist);
|
||||
}
|
||||
|
16
gdb/dcache.h
16
gdb/dcache.h
@ -22,6 +22,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#ifndef DCACHE_H
|
||||
#define DCACHE_H
|
||||
|
||||
/* The data cache leads to incorrect results because it doesn't know about
|
||||
volatile variables, thus making it impossible to debug functions which
|
||||
use hardware registers. Therefore it is #if 0'd out. Effect on
|
||||
performance is some, for backtraces of functions with a few
|
||||
arguments each. For functions with many arguments, the stack
|
||||
frames don't fit in the cache blocks, which makes the cache less
|
||||
helpful. Disabling the cache is a big performance win for fetching
|
||||
large structures, because the cache code fetched data in 16-byte
|
||||
chunks. */
|
||||
|
||||
#define LINE_SIZE_POWER (4)
|
||||
/* eg 1<<3 == 8 */
|
||||
#define LINE_SIZE (1 << LINE_SIZE_POWER)
|
||||
@ -57,8 +67,14 @@ typedef struct {
|
||||
|
||||
} DCACHE;
|
||||
|
||||
/* Using the data cache DCACHE return the contents of the word at
|
||||
address ADDR in the remote machine. */
|
||||
int dcache_fetch PARAMS((DCACHE *dcache, CORE_ADDR addr));
|
||||
|
||||
/* Flush DCACHE. */
|
||||
void dcache_flush PARAMS((DCACHE *dcache));
|
||||
|
||||
/* Initialize DCACHE. */
|
||||
DCACHE *dcache_init PARAMS((memxferfunc reading, memxferfunc writing));
|
||||
|
||||
/* Write the word at ADDR both in the data cache and in the remote machine. */
|
||||
|
304
gdb/remote.c
304
gdb/remote.c
@ -56,6 +56,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
read mem mAA..AA,LLLL AA..AA is address, LLLL is length.
|
||||
reply XX..XX XX..XX is mem contents
|
||||
Can be fewer bytes than requested
|
||||
if able to read only part of the data.
|
||||
or ENN NN is errno
|
||||
|
||||
write mem MAA..AA,LLLL:XX..XX
|
||||
@ -63,7 +65,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
LLLL is number of bytes,
|
||||
XX..XX is data
|
||||
reply OK for success
|
||||
ENN for an error
|
||||
ENN for an error (this includes the case
|
||||
where only part of the data was
|
||||
written).
|
||||
|
||||
cont cAA..AA AA..AA is address to resume
|
||||
If AA..AA is omitted,
|
||||
@ -87,7 +91,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
n... = register number
|
||||
r... = register contents
|
||||
|
||||
kill req k
|
||||
kill request k
|
||||
|
||||
toggle debug d toggle debug flag (see 386 & 68k stubs)
|
||||
reset r reset -- see sparc stub.
|
||||
reserved <other> On other requests, the stub should
|
||||
ignore the request and send an empty
|
||||
response ($#<checksum>). This way
|
||||
we can extend the protocol and GDB
|
||||
can tell whether the stub it is
|
||||
talking to uses the old or the new.
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
@ -102,6 +115,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "terminal.h"
|
||||
#include "gdbcmd.h"
|
||||
|
||||
#include "dcache.h"
|
||||
|
||||
#if !defined(DONT_USE_REMOTE)
|
||||
#ifdef USG
|
||||
#include <sys/types.h>
|
||||
@ -112,11 +127,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* Prototypes for local functions */
|
||||
|
||||
static void
|
||||
remote_write_bytes PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
|
||||
static int
|
||||
remote_write_bytes PARAMS ((CORE_ADDR memaddr, unsigned char *myaddr, int len));
|
||||
|
||||
static void
|
||||
remote_read_bytes PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
|
||||
static int
|
||||
remote_read_bytes PARAMS ((CORE_ADDR memaddr, unsigned char *myaddr, int len));
|
||||
|
||||
static void
|
||||
remote_files_info PARAMS ((struct target_ops *ignore));
|
||||
@ -132,7 +147,7 @@ static void
|
||||
remote_fetch_registers PARAMS ((int regno));
|
||||
|
||||
static void
|
||||
remote_resume PARAMS ((int step, int siggnal));
|
||||
remote_resume PARAMS ((int pid, int step, int siggnal));
|
||||
|
||||
static int
|
||||
remote_start_remote PARAMS ((char *dummy));
|
||||
@ -178,7 +193,6 @@ remote_interrupt_twice PARAMS ((int signo));
|
||||
|
||||
extern struct target_ops remote_ops; /* Forward decl */
|
||||
|
||||
static int kiodebug = 0;
|
||||
/* This was 5 seconds, which is a long time to sit and wait.
|
||||
Unless this is going though some terminal server or multiplexer or
|
||||
other form of hairy serial connection, I would think 2 seconds would
|
||||
@ -237,6 +251,8 @@ remote_start_remote (dummy)
|
||||
/* Open a connection to a remote debugger.
|
||||
NAME is the filename used for communication. */
|
||||
|
||||
static DCACHE *remote_dcache;
|
||||
|
||||
static void
|
||||
remote_open (name, from_tty)
|
||||
char *name;
|
||||
@ -251,9 +267,7 @@ device is attached to the remote system (e.g. /dev/ttya).");
|
||||
|
||||
unpush_target (&remote_ops);
|
||||
|
||||
#if 0
|
||||
dcache_init ();
|
||||
#endif
|
||||
remote_dcache = dcache_init (remote_read_bytes, remote_write_bytes);
|
||||
|
||||
remote_desc = SERIAL_OPEN (name);
|
||||
if (!remote_desc)
|
||||
@ -339,8 +353,8 @@ tohex (nib)
|
||||
/* Tell the remote machine to resume. */
|
||||
|
||||
static void
|
||||
remote_resume (step, siggnal)
|
||||
int step, siggnal;
|
||||
remote_resume (pid, step, siggnal)
|
||||
int pid, step, siggnal;
|
||||
{
|
||||
char buf[PBUFSIZ];
|
||||
|
||||
@ -358,9 +372,7 @@ remote_resume (step, siggnal)
|
||||
target_terminal_inferior ();
|
||||
}
|
||||
|
||||
#if 0
|
||||
dcache_flush ();
|
||||
#endif
|
||||
dcache_flush (remote_dcache);
|
||||
|
||||
strcpy (buf, step ? "s": "c");
|
||||
|
||||
@ -377,7 +389,7 @@ remote_interrupt (signo)
|
||||
/* If this doesn't work, try more severe steps. */
|
||||
signal (signo, remote_interrupt_twice);
|
||||
|
||||
if (kiodebug)
|
||||
if (remote_debug)
|
||||
printf ("remote_interrupt called\n");
|
||||
|
||||
SERIAL_WRITE (remote_desc, "\003", 1); /* Send a ^C */
|
||||
@ -551,7 +563,6 @@ remote_store_registers (regno)
|
||||
remote_send (buf);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Read a word from remote address ADDR and return it.
|
||||
This goes through the data cache. */
|
||||
|
||||
@ -559,6 +570,7 @@ int
|
||||
remote_fetch_word (addr)
|
||||
CORE_ADDR addr;
|
||||
{
|
||||
#if 0
|
||||
if (icache)
|
||||
{
|
||||
extern CORE_ADDR text_start, text_end;
|
||||
@ -570,7 +582,8 @@ remote_fetch_word (addr)
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
return dcache_fetch (addr);
|
||||
#endif
|
||||
return dcache_fetch (remote_dcache, addr);
|
||||
}
|
||||
|
||||
/* Write a word WORD into remote address ADDR.
|
||||
@ -581,20 +594,22 @@ remote_store_word (addr, word)
|
||||
CORE_ADDR addr;
|
||||
int word;
|
||||
{
|
||||
dcache_poke (addr, word);
|
||||
dcache_poke (remote_dcache, addr, word);
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
|
||||
/* Write memory data directly to the remote machine.
|
||||
This does not inform the data cache; the data cache uses this.
|
||||
MEMADDR is the address in the remote memory space.
|
||||
MYADDR is the address of the buffer in our space.
|
||||
LEN is the number of bytes. */
|
||||
LEN is the number of bytes.
|
||||
|
||||
static void
|
||||
Returns number of bytes transferred, or 0 for error. */
|
||||
|
||||
static int
|
||||
remote_write_bytes (memaddr, myaddr, len)
|
||||
CORE_ADDR memaddr;
|
||||
char *myaddr;
|
||||
unsigned char *myaddr;
|
||||
int len;
|
||||
{
|
||||
char buf[PBUFSIZ];
|
||||
@ -617,19 +632,33 @@ remote_write_bytes (memaddr, myaddr, len)
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
remote_send (buf);
|
||||
putpkt (buf);
|
||||
getpkt (buf, 0);
|
||||
|
||||
if (buf[0] == 'E')
|
||||
{
|
||||
/* There is no correspondance between what the remote protocol uses
|
||||
for errors and errno codes. We would like a cleaner way of
|
||||
representing errors (big enough to include errno codes, bfd_error
|
||||
codes, and others). But for now just return EIO. */
|
||||
errno = EIO;
|
||||
return 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Read memory data directly from the remote machine.
|
||||
This does not use the data cache; the data cache uses this.
|
||||
MEMADDR is the address in the remote memory space.
|
||||
MYADDR is the address of the buffer in our space.
|
||||
LEN is the number of bytes. */
|
||||
LEN is the number of bytes.
|
||||
|
||||
static void
|
||||
Returns number of bytes transferred, or 0 for error. */
|
||||
|
||||
static int
|
||||
remote_read_bytes (memaddr, myaddr, len)
|
||||
CORE_ADDR memaddr;
|
||||
char *myaddr;
|
||||
unsigned char *myaddr;
|
||||
int len;
|
||||
{
|
||||
char buf[PBUFSIZ];
|
||||
@ -640,7 +669,18 @@ remote_read_bytes (memaddr, myaddr, len)
|
||||
abort ();
|
||||
|
||||
sprintf (buf, "m%x,%x", memaddr, len);
|
||||
remote_send (buf);
|
||||
putpkt (buf);
|
||||
getpkt (buf, 0);
|
||||
|
||||
if (buf[0] == 'E')
|
||||
{
|
||||
/* There is no correspondance between what the remote protocol uses
|
||||
for errors and errno codes. We would like a cleaner way of
|
||||
representing errors (big enough to include errno codes, bfd_error
|
||||
codes, and others). But for now just return EIO. */
|
||||
errno = EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Reply describes memory byte by byte,
|
||||
each byte encoded as two hex characters. */
|
||||
@ -649,10 +689,13 @@ remote_read_bytes (memaddr, myaddr, len)
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (p[0] == 0 || p[1] == 0)
|
||||
error ("Remote reply is too short: %s", buf);
|
||||
/* Reply is short. This means that we were able to read only part
|
||||
of what we wanted to. */
|
||||
break;
|
||||
myaddr[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
|
||||
p += 2;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Read or write LEN bytes from inferior memory at MEMADDR, transferring
|
||||
@ -668,8 +711,10 @@ remote_xfer_memory(memaddr, myaddr, len, should_write, target)
|
||||
int should_write;
|
||||
struct target_ops *target; /* ignored */
|
||||
{
|
||||
int origlen = len;
|
||||
int xfersize;
|
||||
int bytes_xferred;
|
||||
int total_xferred = 0;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
if (len > MAXBUFBYTES)
|
||||
@ -678,14 +723,20 @@ remote_xfer_memory(memaddr, myaddr, len, should_write, target)
|
||||
xfersize = len;
|
||||
|
||||
if (should_write)
|
||||
remote_write_bytes(memaddr, myaddr, xfersize);
|
||||
bytes_xferred = remote_write_bytes (memaddr, myaddr, xfersize);
|
||||
else
|
||||
remote_read_bytes (memaddr, myaddr, xfersize);
|
||||
memaddr += xfersize;
|
||||
myaddr += xfersize;
|
||||
len -= xfersize;
|
||||
bytes_xferred = remote_read_bytes (memaddr, myaddr, xfersize);
|
||||
|
||||
/* If we get an error, we are done xferring. */
|
||||
if (bytes_xferred == 0)
|
||||
break;
|
||||
|
||||
memaddr += bytes_xferred;
|
||||
myaddr += bytes_xferred;
|
||||
len -= bytes_xferred;
|
||||
total_xferred += bytes_xferred;
|
||||
}
|
||||
return origlen; /* no error possible */
|
||||
return total_xferred;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -765,7 +816,7 @@ putpkt (buf)
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (kiodebug)
|
||||
if (remote_debug)
|
||||
{
|
||||
*p = '\0';
|
||||
printf ("Sending packet: %s...", buf2); fflush(stdout);
|
||||
@ -781,7 +832,7 @@ putpkt (buf)
|
||||
switch (ch)
|
||||
{
|
||||
case '+':
|
||||
if (kiodebug)
|
||||
if (remote_debug)
|
||||
printf("Ack\n");
|
||||
return;
|
||||
case SERIAL_TIMEOUT:
|
||||
@ -791,7 +842,7 @@ putpkt (buf)
|
||||
case SERIAL_EOF:
|
||||
error ("putpkt: EOF while trying to read ACK");
|
||||
default:
|
||||
if (kiodebug)
|
||||
if (remote_debug)
|
||||
printf ("%02X %c ", ch&0xFF, ch);
|
||||
continue;
|
||||
}
|
||||
@ -832,7 +883,7 @@ getpkt (buf, forever)
|
||||
if (forever)
|
||||
continue;
|
||||
if (++retries >= MAX_RETRIES)
|
||||
if (kiodebug) puts_filtered ("Timed out.\n");
|
||||
if (remote_debug) puts_filtered ("Timed out.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -850,13 +901,13 @@ getpkt (buf, forever)
|
||||
c = readchar ();
|
||||
if (c == SERIAL_TIMEOUT)
|
||||
{
|
||||
if (kiodebug)
|
||||
if (remote_debug)
|
||||
puts_filtered ("Timeout in mid-packet, retrying\n");
|
||||
goto whole; /* Start a new packet, count retries */
|
||||
}
|
||||
if (c == '$')
|
||||
{
|
||||
if (kiodebug)
|
||||
if (remote_debug)
|
||||
puts_filtered ("Saw new packet start in middle of old one\n");
|
||||
goto whole; /* Start a new packet, count retries */
|
||||
}
|
||||
@ -901,163 +952,10 @@ getpkt (buf, forever)
|
||||
|
||||
SERIAL_WRITE (remote_desc, "+", 1);
|
||||
|
||||
if (kiodebug)
|
||||
if (remote_debug)
|
||||
fprintf (stderr,"Packet received: %s\n", buf);
|
||||
}
|
||||
|
||||
/* The data cache leads to incorrect results because it doesn't know about
|
||||
volatile variables, thus making it impossible to debug functions which
|
||||
use hardware registers. Therefore it is #if 0'd out. Effect on
|
||||
performance is some, for backtraces of functions with a few
|
||||
arguments each. For functions with many arguments, the stack
|
||||
frames don't fit in the cache blocks, which makes the cache less
|
||||
helpful. Disabling the cache is a big performance win for fetching
|
||||
large structures, because the cache code fetched data in 16-byte
|
||||
chunks. */
|
||||
#if 0
|
||||
/* The data cache records all the data read from the remote machine
|
||||
since the last time it stopped.
|
||||
|
||||
Each cache block holds 16 bytes of data
|
||||
starting at a multiple-of-16 address. */
|
||||
|
||||
#define DCACHE_SIZE 64 /* Number of cache blocks */
|
||||
|
||||
struct dcache_block {
|
||||
struct dcache_block *next, *last;
|
||||
unsigned int addr; /* Address for which data is recorded. */
|
||||
int data[4];
|
||||
};
|
||||
|
||||
struct dcache_block dcache_free, dcache_valid;
|
||||
|
||||
/* Free all the data cache blocks, thus discarding all cached data. */
|
||||
|
||||
static void
|
||||
dcache_flush ()
|
||||
{
|
||||
register struct dcache_block *db;
|
||||
|
||||
while ((db = dcache_valid.next) != &dcache_valid)
|
||||
{
|
||||
remque (db);
|
||||
insque (db, &dcache_free);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If addr is present in the dcache, return the address of the block
|
||||
* containing it.
|
||||
*/
|
||||
|
||||
struct dcache_block *
|
||||
dcache_hit (addr)
|
||||
{
|
||||
register struct dcache_block *db;
|
||||
|
||||
if (addr & 3)
|
||||
abort ();
|
||||
|
||||
/* Search all cache blocks for one that is at this address. */
|
||||
db = dcache_valid.next;
|
||||
while (db != &dcache_valid)
|
||||
{
|
||||
if ((addr & 0xfffffff0) == db->addr)
|
||||
return db;
|
||||
db = db->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return the int data at address ADDR in dcache block DC. */
|
||||
|
||||
int
|
||||
dcache_value (db, addr)
|
||||
struct dcache_block *db;
|
||||
unsigned int addr;
|
||||
{
|
||||
if (addr & 3)
|
||||
abort ();
|
||||
return (db->data[(addr>>2)&3]);
|
||||
}
|
||||
|
||||
/* Get a free cache block, put it on the valid list,
|
||||
and return its address. The caller should store into the block
|
||||
the address and data that it describes. */
|
||||
|
||||
struct dcache_block *
|
||||
dcache_alloc ()
|
||||
{
|
||||
register struct dcache_block *db;
|
||||
|
||||
if ((db = dcache_free.next) == &dcache_free)
|
||||
/* If we can't get one from the free list, take last valid */
|
||||
db = dcache_valid.last;
|
||||
|
||||
remque (db);
|
||||
insque (db, &dcache_valid);
|
||||
return (db);
|
||||
}
|
||||
|
||||
/* Return the contents of the word at address ADDR in the remote machine,
|
||||
using the data cache. */
|
||||
|
||||
int
|
||||
dcache_fetch (addr)
|
||||
CORE_ADDR addr;
|
||||
{
|
||||
register struct dcache_block *db;
|
||||
|
||||
db = dcache_hit (addr);
|
||||
if (db == 0)
|
||||
{
|
||||
db = dcache_alloc ();
|
||||
remote_read_bytes (addr & ~0xf, db->data, 16);
|
||||
db->addr = addr & ~0xf;
|
||||
}
|
||||
return (dcache_value (db, addr));
|
||||
}
|
||||
|
||||
/* Write the word at ADDR both in the data cache and in the remote machine. */
|
||||
|
||||
dcache_poke (addr, data)
|
||||
CORE_ADDR addr;
|
||||
int data;
|
||||
{
|
||||
register struct dcache_block *db;
|
||||
|
||||
/* First make sure the word is IN the cache. DB is its cache block. */
|
||||
db = dcache_hit (addr);
|
||||
if (db == 0)
|
||||
{
|
||||
db = dcache_alloc ();
|
||||
remote_read_bytes (addr & ~0xf, db->data, 16);
|
||||
db->addr = addr & ~0xf;
|
||||
}
|
||||
|
||||
/* Modify the word in the cache. */
|
||||
db->data[(addr>>2)&3] = data;
|
||||
|
||||
/* Send the changed word. */
|
||||
remote_write_bytes (addr, &data, 4);
|
||||
}
|
||||
|
||||
/* Initialize the data cache. */
|
||||
|
||||
dcache_init ()
|
||||
{
|
||||
register i;
|
||||
register struct dcache_block *db;
|
||||
|
||||
db = (struct dcache_block *) xmalloc (sizeof (struct dcache_block) *
|
||||
DCACHE_SIZE);
|
||||
dcache_free.next = dcache_free.last = &dcache_free;
|
||||
dcache_valid.next = dcache_valid.last = &dcache_valid;
|
||||
for (i=0;i<DCACHE_SIZE;i++,db++)
|
||||
insque (db, &dcache_free);
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
static void
|
||||
remote_kill ()
|
||||
{
|
||||
@ -1099,7 +997,7 @@ static unsigned char break_insn[] = BREAKPOINT;
|
||||
by the caller to be long enough to save sizeof BREAKPOINT bytes (this
|
||||
is accomplished via BREAKPOINT_MAX). */
|
||||
|
||||
int
|
||||
static int
|
||||
remote_insert_breakpoint (addr, contents_cache)
|
||||
CORE_ADDR addr;
|
||||
char *contents_cache;
|
||||
@ -1114,7 +1012,7 @@ remote_insert_breakpoint (addr, contents_cache)
|
||||
return val;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
remote_remove_breakpoint (addr, contents_cache)
|
||||
CORE_ADDR addr;
|
||||
char *contents_cache;
|
||||
@ -1172,13 +1070,5 @@ void
|
||||
_initialize_remote ()
|
||||
{
|
||||
add_target (&remote_ops);
|
||||
|
||||
add_show_from_set (
|
||||
add_set_cmd ("remotedebug", no_class, var_boolean, (char *)&kiodebug,
|
||||
"Set debugging of remote serial I/O.\n\
|
||||
When enabled, each packet sent or received with the remote target\n\
|
||||
is displayed.", &setlist),
|
||||
&showlist);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user