break dcache code out of remote.c
This commit is contained in:
parent
46cf424778
commit
d538b510a0
5 changed files with 183 additions and 219 deletions
|
@ -1,5 +1,18 @@
|
||||||
Tue Aug 31 15:01:27 1993 K. Richard Pixley (rich@sendai.cygnus.com)
|
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].
|
Break dcache code out of remote-bug.c into dcache.[hc].
|
||||||
* Makefile.in (dcache_h): new macro.
|
* Makefile.in (dcache_h): new macro.
|
||||||
(HFILES): added $(dcache_h).
|
(HFILES): added $(dcache_h).
|
||||||
|
|
|
@ -189,7 +189,7 @@ SER_HARDWIRE=ser-unix.o
|
||||||
|
|
||||||
# The `remote' debugging target is supported for most architectures,
|
# The `remote' debugging target is supported for most architectures,
|
||||||
# but not all (e.g. 960)
|
# 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.
|
# Host and target-dependent makefile fragments come in here.
|
||||||
####
|
####
|
||||||
|
|
53
gdb/dcache.c
53
gdb/dcache.c
|
@ -21,10 +21,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "dcache.h"
|
#include "dcache.h"
|
||||||
|
#include "gdbcmd.h"
|
||||||
|
|
||||||
extern int insque();
|
extern int insque();
|
||||||
extern int remque();
|
extern int remque();
|
||||||
|
|
||||||
|
int remote_dcache = 0;
|
||||||
|
|
||||||
/* The data cache records all the data read from the remote machine
|
/* The data cache records all the data read from the remote machine
|
||||||
since the last time it stopped.
|
since the last time it stopped.
|
||||||
|
|
||||||
|
@ -41,17 +44,21 @@ dcache_flush (dcache)
|
||||||
{
|
{
|
||||||
register struct dcache_block *db;
|
register struct dcache_block *db;
|
||||||
|
|
||||||
|
if (remote_dcache > 0)
|
||||||
while ((db = dcache->dcache_valid.next) != &dcache->dcache_valid)
|
while ((db = dcache->dcache_valid.next) != &dcache->dcache_valid)
|
||||||
{
|
{
|
||||||
remque (db);
|
remque (db);
|
||||||
insque (db, &dcache->dcache_free);
|
insque (db, &dcache->dcache_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If addr is present in the dcache, return the address of the block
|
* If addr is present in the dcache, return the address of the block
|
||||||
* containing it.
|
* containing it.
|
||||||
*/
|
*/
|
||||||
|
static
|
||||||
struct dcache_block *
|
struct dcache_block *
|
||||||
dcache_hit (dcache, addr)
|
dcache_hit (dcache, addr)
|
||||||
DCACHE *dcache;
|
DCACHE *dcache;
|
||||||
|
@ -59,7 +66,8 @@ dcache_hit (dcache, addr)
|
||||||
{
|
{
|
||||||
register struct dcache_block *db;
|
register struct dcache_block *db;
|
||||||
|
|
||||||
if (addr & 3)
|
if (addr & 3
|
||||||
|
|| remote_dcache == 0)
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
/* Search all cache blocks for one that is at this address. */
|
/* Search all cache blocks for one that is at this address. */
|
||||||
|
@ -70,16 +78,19 @@ dcache_hit (dcache, addr)
|
||||||
return db;
|
return db;
|
||||||
db = db->next;
|
db = db->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the int data at address ADDR in dcache block DC. */
|
/* Return the int data at address ADDR in dcache block DC. */
|
||||||
|
static
|
||||||
int
|
int
|
||||||
dcache_value (db, addr)
|
dcache_value (db, addr)
|
||||||
struct dcache_block *db;
|
struct dcache_block *db;
|
||||||
unsigned int addr;
|
unsigned int addr;
|
||||||
{
|
{
|
||||||
if (addr & 3)
|
if (addr & 3
|
||||||
|
|| remote_dcache == 0)
|
||||||
abort ();
|
abort ();
|
||||||
return (db->data[XFORM (addr)]);
|
return (db->data[XFORM (addr)]);
|
||||||
}
|
}
|
||||||
|
@ -91,12 +102,16 @@ dcache_value (db, addr)
|
||||||
prevents errors from creeping in if a memory retrieval is
|
prevents errors from creeping in if a memory retrieval is
|
||||||
interrupted (which used to put garbage blocks in the valid
|
interrupted (which used to put garbage blocks in the valid
|
||||||
list...). */
|
list...). */
|
||||||
|
static
|
||||||
struct dcache_block *
|
struct dcache_block *
|
||||||
dcache_alloc (dcache)
|
dcache_alloc (dcache)
|
||||||
DCACHE *dcache;
|
DCACHE *dcache;
|
||||||
{
|
{
|
||||||
register struct dcache_block *db;
|
register struct dcache_block *db;
|
||||||
|
|
||||||
|
if (remote_dcache == 0)
|
||||||
|
abort();
|
||||||
|
|
||||||
if ((db = dcache->dcache_free.next) == &dcache->dcache_free)
|
if ((db = dcache->dcache_free.next) == &dcache->dcache_free)
|
||||||
{
|
{
|
||||||
/* If we can't get one from the free list, take last valid and put
|
/* 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 (db);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the contents of the word at address ADDR in the remote machine,
|
/* Using the data cache DCACHE return the contents of the word at
|
||||||
using the data cache. */
|
address ADDR in the remote machine. */
|
||||||
int
|
int
|
||||||
dcache_fetch (dcache, addr)
|
dcache_fetch (dcache, addr)
|
||||||
DCACHE *dcache;
|
DCACHE *dcache;
|
||||||
|
@ -120,6 +135,14 @@ dcache_fetch (dcache, addr)
|
||||||
{
|
{
|
||||||
register struct dcache_block *db;
|
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);
|
db = dcache_hit (dcache, addr);
|
||||||
if (db == 0)
|
if (db == 0)
|
||||||
{
|
{
|
||||||
|
@ -143,6 +166,12 @@ dcache_poke (dcache, addr, data)
|
||||||
{
|
{
|
||||||
register struct dcache_block *db;
|
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. */
|
/* First make sure the word is IN the cache. DB is its cache block. */
|
||||||
db = dcache_hit (dcache, addr);
|
db = dcache_hit (dcache, addr);
|
||||||
if (db == 0)
|
if (db == 0)
|
||||||
|
@ -188,3 +217,19 @@ dcache_init (reading, writing)
|
||||||
return(dcache);
|
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
|
#ifndef DCACHE_H
|
||||||
#define 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)
|
#define LINE_SIZE_POWER (4)
|
||||||
/* eg 1<<3 == 8 */
|
/* eg 1<<3 == 8 */
|
||||||
#define LINE_SIZE (1 << LINE_SIZE_POWER)
|
#define LINE_SIZE (1 << LINE_SIZE_POWER)
|
||||||
|
@ -57,8 +67,14 @@ typedef struct {
|
||||||
|
|
||||||
} DCACHE;
|
} 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));
|
int dcache_fetch PARAMS((DCACHE *dcache, CORE_ADDR addr));
|
||||||
|
|
||||||
|
/* Flush DCACHE. */
|
||||||
void dcache_flush PARAMS((DCACHE *dcache));
|
void dcache_flush PARAMS((DCACHE *dcache));
|
||||||
|
|
||||||
|
/* Initialize DCACHE. */
|
||||||
DCACHE *dcache_init PARAMS((memxferfunc reading, memxferfunc writing));
|
DCACHE *dcache_init PARAMS((memxferfunc reading, memxferfunc writing));
|
||||||
|
|
||||||
/* Write the word at ADDR both in the data cache and in the remote machine. */
|
/* 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.
|
read mem mAA..AA,LLLL AA..AA is address, LLLL is length.
|
||||||
reply XX..XX XX..XX is mem contents
|
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
|
or ENN NN is errno
|
||||||
|
|
||||||
write mem MAA..AA,LLLL:XX..XX
|
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,
|
LLLL is number of bytes,
|
||||||
XX..XX is data
|
XX..XX is data
|
||||||
reply OK for success
|
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
|
cont cAA..AA AA..AA is address to resume
|
||||||
If AA..AA is omitted,
|
If AA..AA is omitted,
|
||||||
|
@ -87,7 +91,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
n... = register number
|
n... = register number
|
||||||
r... = register contents
|
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"
|
#include "defs.h"
|
||||||
|
@ -102,6 +115,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
#include "gdbcmd.h"
|
#include "gdbcmd.h"
|
||||||
|
|
||||||
|
#include "dcache.h"
|
||||||
|
|
||||||
#if !defined(DONT_USE_REMOTE)
|
#if !defined(DONT_USE_REMOTE)
|
||||||
#ifdef USG
|
#ifdef USG
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -112,11 +127,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
/* Prototypes for local functions */
|
/* Prototypes for local functions */
|
||||||
|
|
||||||
static void
|
static int
|
||||||
remote_write_bytes PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
|
remote_write_bytes PARAMS ((CORE_ADDR memaddr, unsigned char *myaddr, int len));
|
||||||
|
|
||||||
static void
|
static int
|
||||||
remote_read_bytes PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
|
remote_read_bytes PARAMS ((CORE_ADDR memaddr, unsigned char *myaddr, int len));
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remote_files_info PARAMS ((struct target_ops *ignore));
|
remote_files_info PARAMS ((struct target_ops *ignore));
|
||||||
|
@ -132,7 +147,7 @@ static void
|
||||||
remote_fetch_registers PARAMS ((int regno));
|
remote_fetch_registers PARAMS ((int regno));
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remote_resume PARAMS ((int step, int siggnal));
|
remote_resume PARAMS ((int pid, int step, int siggnal));
|
||||||
|
|
||||||
static int
|
static int
|
||||||
remote_start_remote PARAMS ((char *dummy));
|
remote_start_remote PARAMS ((char *dummy));
|
||||||
|
@ -178,7 +193,6 @@ remote_interrupt_twice PARAMS ((int signo));
|
||||||
|
|
||||||
extern struct target_ops remote_ops; /* Forward decl */
|
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.
|
/* This was 5 seconds, which is a long time to sit and wait.
|
||||||
Unless this is going though some terminal server or multiplexer or
|
Unless this is going though some terminal server or multiplexer or
|
||||||
other form of hairy serial connection, I would think 2 seconds would
|
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.
|
/* Open a connection to a remote debugger.
|
||||||
NAME is the filename used for communication. */
|
NAME is the filename used for communication. */
|
||||||
|
|
||||||
|
static DCACHE *remote_dcache;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remote_open (name, from_tty)
|
remote_open (name, from_tty)
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -251,9 +267,7 @@ device is attached to the remote system (e.g. /dev/ttya).");
|
||||||
|
|
||||||
unpush_target (&remote_ops);
|
unpush_target (&remote_ops);
|
||||||
|
|
||||||
#if 0
|
remote_dcache = dcache_init (remote_read_bytes, remote_write_bytes);
|
||||||
dcache_init ();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
remote_desc = SERIAL_OPEN (name);
|
remote_desc = SERIAL_OPEN (name);
|
||||||
if (!remote_desc)
|
if (!remote_desc)
|
||||||
|
@ -339,8 +353,8 @@ tohex (nib)
|
||||||
/* Tell the remote machine to resume. */
|
/* Tell the remote machine to resume. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remote_resume (step, siggnal)
|
remote_resume (pid, step, siggnal)
|
||||||
int step, siggnal;
|
int pid, step, siggnal;
|
||||||
{
|
{
|
||||||
char buf[PBUFSIZ];
|
char buf[PBUFSIZ];
|
||||||
|
|
||||||
|
@ -358,9 +372,7 @@ remote_resume (step, siggnal)
|
||||||
target_terminal_inferior ();
|
target_terminal_inferior ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
dcache_flush (remote_dcache);
|
||||||
dcache_flush ();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
strcpy (buf, step ? "s": "c");
|
strcpy (buf, step ? "s": "c");
|
||||||
|
|
||||||
|
@ -377,7 +389,7 @@ remote_interrupt (signo)
|
||||||
/* If this doesn't work, try more severe steps. */
|
/* If this doesn't work, try more severe steps. */
|
||||||
signal (signo, remote_interrupt_twice);
|
signal (signo, remote_interrupt_twice);
|
||||||
|
|
||||||
if (kiodebug)
|
if (remote_debug)
|
||||||
printf ("remote_interrupt called\n");
|
printf ("remote_interrupt called\n");
|
||||||
|
|
||||||
SERIAL_WRITE (remote_desc, "\003", 1); /* Send a ^C */
|
SERIAL_WRITE (remote_desc, "\003", 1); /* Send a ^C */
|
||||||
|
@ -551,7 +563,6 @@ remote_store_registers (regno)
|
||||||
remote_send (buf);
|
remote_send (buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Read a word from remote address ADDR and return it.
|
/* Read a word from remote address ADDR and return it.
|
||||||
This goes through the data cache. */
|
This goes through the data cache. */
|
||||||
|
|
||||||
|
@ -559,6 +570,7 @@ int
|
||||||
remote_fetch_word (addr)
|
remote_fetch_word (addr)
|
||||||
CORE_ADDR addr;
|
CORE_ADDR addr;
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
if (icache)
|
if (icache)
|
||||||
{
|
{
|
||||||
extern CORE_ADDR text_start, text_end;
|
extern CORE_ADDR text_start, text_end;
|
||||||
|
@ -570,7 +582,8 @@ remote_fetch_word (addr)
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dcache_fetch (addr);
|
#endif
|
||||||
|
return dcache_fetch (remote_dcache, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write a word WORD into remote address ADDR.
|
/* Write a word WORD into remote address ADDR.
|
||||||
|
@ -581,20 +594,22 @@ remote_store_word (addr, word)
|
||||||
CORE_ADDR addr;
|
CORE_ADDR addr;
|
||||||
int word;
|
int word;
|
||||||
{
|
{
|
||||||
dcache_poke (addr, word);
|
dcache_poke (remote_dcache, addr, word);
|
||||||
}
|
}
|
||||||
#endif /* 0 */
|
|
||||||
|
|
||||||
/* Write memory data directly to the remote machine.
|
/* Write memory data directly to the remote machine.
|
||||||
This does not inform the data cache; the data cache uses this.
|
This does not inform the data cache; the data cache uses this.
|
||||||
MEMADDR is the address in the remote memory space.
|
MEMADDR is the address in the remote memory space.
|
||||||
MYADDR is the address of the buffer in our 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)
|
remote_write_bytes (memaddr, myaddr, len)
|
||||||
CORE_ADDR memaddr;
|
CORE_ADDR memaddr;
|
||||||
char *myaddr;
|
unsigned char *myaddr;
|
||||||
int len;
|
int len;
|
||||||
{
|
{
|
||||||
char buf[PBUFSIZ];
|
char buf[PBUFSIZ];
|
||||||
|
@ -617,19 +632,33 @@ remote_write_bytes (memaddr, myaddr, len)
|
||||||
}
|
}
|
||||||
*p = '\0';
|
*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.
|
/* Read memory data directly from the remote machine.
|
||||||
This does not use the data cache; the data cache uses this.
|
This does not use the data cache; the data cache uses this.
|
||||||
MEMADDR is the address in the remote memory space.
|
MEMADDR is the address in the remote memory space.
|
||||||
MYADDR is the address of the buffer in our 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)
|
remote_read_bytes (memaddr, myaddr, len)
|
||||||
CORE_ADDR memaddr;
|
CORE_ADDR memaddr;
|
||||||
char *myaddr;
|
unsigned char *myaddr;
|
||||||
int len;
|
int len;
|
||||||
{
|
{
|
||||||
char buf[PBUFSIZ];
|
char buf[PBUFSIZ];
|
||||||
|
@ -640,7 +669,18 @@ remote_read_bytes (memaddr, myaddr, len)
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
sprintf (buf, "m%x,%x", memaddr, len);
|
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,
|
/* Reply describes memory byte by byte,
|
||||||
each byte encoded as two hex characters. */
|
each byte encoded as two hex characters. */
|
||||||
|
@ -649,10 +689,13 @@ remote_read_bytes (memaddr, myaddr, len)
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
if (p[0] == 0 || p[1] == 0)
|
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]);
|
myaddr[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
|
||||||
p += 2;
|
p += 2;
|
||||||
}
|
}
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read or write LEN bytes from inferior memory at MEMADDR, transferring
|
/* 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;
|
int should_write;
|
||||||
struct target_ops *target; /* ignored */
|
struct target_ops *target; /* ignored */
|
||||||
{
|
{
|
||||||
int origlen = len;
|
|
||||||
int xfersize;
|
int xfersize;
|
||||||
|
int bytes_xferred;
|
||||||
|
int total_xferred = 0;
|
||||||
|
|
||||||
while (len > 0)
|
while (len > 0)
|
||||||
{
|
{
|
||||||
if (len > MAXBUFBYTES)
|
if (len > MAXBUFBYTES)
|
||||||
|
@ -678,14 +723,20 @@ remote_xfer_memory(memaddr, myaddr, len, should_write, target)
|
||||||
xfersize = len;
|
xfersize = len;
|
||||||
|
|
||||||
if (should_write)
|
if (should_write)
|
||||||
remote_write_bytes(memaddr, myaddr, xfersize);
|
bytes_xferred = remote_write_bytes (memaddr, myaddr, xfersize);
|
||||||
else
|
else
|
||||||
remote_read_bytes (memaddr, myaddr, xfersize);
|
bytes_xferred = remote_read_bytes (memaddr, myaddr, xfersize);
|
||||||
memaddr += xfersize;
|
|
||||||
myaddr += xfersize;
|
/* If we get an error, we are done xferring. */
|
||||||
len -= xfersize;
|
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
|
static void
|
||||||
|
@ -765,7 +816,7 @@ putpkt (buf)
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (kiodebug)
|
if (remote_debug)
|
||||||
{
|
{
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
printf ("Sending packet: %s...", buf2); fflush(stdout);
|
printf ("Sending packet: %s...", buf2); fflush(stdout);
|
||||||
|
@ -781,7 +832,7 @@ putpkt (buf)
|
||||||
switch (ch)
|
switch (ch)
|
||||||
{
|
{
|
||||||
case '+':
|
case '+':
|
||||||
if (kiodebug)
|
if (remote_debug)
|
||||||
printf("Ack\n");
|
printf("Ack\n");
|
||||||
return;
|
return;
|
||||||
case SERIAL_TIMEOUT:
|
case SERIAL_TIMEOUT:
|
||||||
|
@ -791,7 +842,7 @@ putpkt (buf)
|
||||||
case SERIAL_EOF:
|
case SERIAL_EOF:
|
||||||
error ("putpkt: EOF while trying to read ACK");
|
error ("putpkt: EOF while trying to read ACK");
|
||||||
default:
|
default:
|
||||||
if (kiodebug)
|
if (remote_debug)
|
||||||
printf ("%02X %c ", ch&0xFF, ch);
|
printf ("%02X %c ", ch&0xFF, ch);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -832,7 +883,7 @@ getpkt (buf, forever)
|
||||||
if (forever)
|
if (forever)
|
||||||
continue;
|
continue;
|
||||||
if (++retries >= MAX_RETRIES)
|
if (++retries >= MAX_RETRIES)
|
||||||
if (kiodebug) puts_filtered ("Timed out.\n");
|
if (remote_debug) puts_filtered ("Timed out.\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -850,13 +901,13 @@ getpkt (buf, forever)
|
||||||
c = readchar ();
|
c = readchar ();
|
||||||
if (c == SERIAL_TIMEOUT)
|
if (c == SERIAL_TIMEOUT)
|
||||||
{
|
{
|
||||||
if (kiodebug)
|
if (remote_debug)
|
||||||
puts_filtered ("Timeout in mid-packet, retrying\n");
|
puts_filtered ("Timeout in mid-packet, retrying\n");
|
||||||
goto whole; /* Start a new packet, count retries */
|
goto whole; /* Start a new packet, count retries */
|
||||||
}
|
}
|
||||||
if (c == '$')
|
if (c == '$')
|
||||||
{
|
{
|
||||||
if (kiodebug)
|
if (remote_debug)
|
||||||
puts_filtered ("Saw new packet start in middle of old one\n");
|
puts_filtered ("Saw new packet start in middle of old one\n");
|
||||||
goto whole; /* Start a new packet, count retries */
|
goto whole; /* Start a new packet, count retries */
|
||||||
}
|
}
|
||||||
|
@ -901,163 +952,10 @@ out:
|
||||||
|
|
||||||
SERIAL_WRITE (remote_desc, "+", 1);
|
SERIAL_WRITE (remote_desc, "+", 1);
|
||||||
|
|
||||||
if (kiodebug)
|
if (remote_debug)
|
||||||
fprintf (stderr,"Packet received: %s\n", buf);
|
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
|
static void
|
||||||
remote_kill ()
|
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
|
by the caller to be long enough to save sizeof BREAKPOINT bytes (this
|
||||||
is accomplished via BREAKPOINT_MAX). */
|
is accomplished via BREAKPOINT_MAX). */
|
||||||
|
|
||||||
int
|
static int
|
||||||
remote_insert_breakpoint (addr, contents_cache)
|
remote_insert_breakpoint (addr, contents_cache)
|
||||||
CORE_ADDR addr;
|
CORE_ADDR addr;
|
||||||
char *contents_cache;
|
char *contents_cache;
|
||||||
|
@ -1114,7 +1012,7 @@ remote_insert_breakpoint (addr, contents_cache)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
remote_remove_breakpoint (addr, contents_cache)
|
remote_remove_breakpoint (addr, contents_cache)
|
||||||
CORE_ADDR addr;
|
CORE_ADDR addr;
|
||||||
char *contents_cache;
|
char *contents_cache;
|
||||||
|
@ -1172,13 +1070,5 @@ void
|
||||||
_initialize_remote ()
|
_initialize_remote ()
|
||||||
{
|
{
|
||||||
add_target (&remote_ops);
|
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
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue