* remote-mips.c: New file; implements MIPS remote debugging

protocol.
	* config/idt.mt: New file; uses remote-mips.c
	* configure.in (mips-idt-ecoff): New target; uses idt.mt.

	* mips-tdep.c (mips_fpu): New variable; controls use of MIPS
	floating point coprocessor.
	(mips_push_dummy_frame): If not mips_fpu, don't save floating
	point registers.
	(mips_pop_frame): If not mips_fpu, don't restore floating point
	registers.
	(_initialize_mips_tdep): New function; let the user reset mips_fpu
	variable.
	* tm-mips.h (EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE): If not
	mips_fpu, don't use fp0 as floating point return register.
	(FIX_CALL_DUMMY): If not mips_fpu, don't save floating point
	registers.

Also added remote-mips.c to .Sanitize file.
This commit is contained in:
Ian Lance Taylor 1993-02-22 23:43:03 +00:00
parent 20f10b59ff
commit c2a0f1cb8e
8 changed files with 260 additions and 55 deletions

View File

@ -206,6 +206,7 @@ remote-adapt.c
remote-eb.c
remote-es1800.c
remote-hms.c
remote-mips.c
remote-mm.c
remote-nindy.c
remote-sim.c

View File

@ -1,3 +1,23 @@
Mon Feb 22 15:21:54 1993 Ian Lance Taylor (ian@cygnus.com)
* remote-mips.c: New file; implements MIPS remote debugging
protocol.
* config/idt.mt: New file; uses remote-mips.c
* configure.in (mips-idt-ecoff): New target; uses idt.mt.
* mips-tdep.c (mips_fpu): New variable; controls use of MIPS
floating point coprocessor.
(mips_push_dummy_frame): If not mips_fpu, don't save floating
point registers.
(mips_pop_frame): If not mips_fpu, don't restore floating point
registers.
(_initialize_mips_tdep): New function; let the user reset mips_fpu
variable.
* tm-mips.h (EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE): If not
mips_fpu, don't use fp0 as floating point return register.
(FIX_CALL_DUMMY): If not mips_fpu, don't save floating point
registers.
Mon Feb 22 07:54:03 1993 Mike Werner (mtw@poseidon.cygnus.com)
* gdb/testsuite: made modifications to testcases, etc., to allow

View File

@ -66,6 +66,7 @@ i386v.mt
i386v32.mh
i386v4.mh
i386v4.mt
idt.mt
irix3.mh
irix3.mt
irix4.mh

3
gdb/config/idt.mt Normal file
View File

@ -0,0 +1,3 @@
# Target: Big-endian IDT board.
TDEPFILES= mips-pinsn.o mips-tdep.o exec.o remote-mips.o
TM_FILE= tm-bigmips.h

View File

@ -171,6 +171,7 @@ m88k-*-*) gdb_target=m88k ;;
mips-big-*) gdb_target=bigmips ;;
mips-dec-*) gdb_target=decstation ;;
mips-idt-ecoff) gdb_target=idt ;;
mips-little-*) gdb_target=littlemips ;;
mips-sgi-*) gdb_target=irix3 ;;
mips-sony-*) gdb_target=bigmips ;;

View File

@ -1,5 +1,5 @@
/* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
Copyright 1988, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
Copyright 1988, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
@ -55,6 +55,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <sys/stat.h>
/* Some MIPS boards don't support floating point, so we permit the
user to turn it off. */
int mips_fpu = 1;
#define PROC_LOW_ADDR(proc) ((proc)->pdr.adr) /* least address */
#define PROC_HIGH_ADDR(proc) ((proc)->pdr.iline) /* upper address bound */
#define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset)
@ -316,16 +320,13 @@ init_extra_frame_info(fci)
/* r0 bit means kernel trap */
int kernel_trap = PROC_REG_MASK(proc_desc) & 1;
if (fci->frame == 0)
{
/* Fixup frame-pointer - only needed for top frame */
/* This may not be quite right, if proc has a real frame register */
if (fci->pc == PROC_LOW_ADDR(proc_desc))
fci->frame = read_register (SP_REGNUM);
else
fci->frame = READ_FRAME_REG(fci, PROC_FRAME_REG(proc_desc))
+ PROC_FRAME_OFFSET(proc_desc);
}
/* Fixup frame-pointer - only needed for top frame */
/* This may not be quite right, if proc has a real frame register */
if (fci->pc == PROC_LOW_ADDR(proc_desc))
fci->frame = read_register (SP_REGNUM);
else
fci->frame = READ_FRAME_REG(fci, PROC_FRAME_REG(proc_desc))
+ PROC_FRAME_OFFSET(proc_desc);
if (proc_desc == &temp_proc_desc)
*fci->saved_regs = temp_saved_regs;
@ -381,11 +382,14 @@ init_extra_frame_info(fci)
arguments without difficulty. */
FRAME
setup_arbitrary_frame (stack, pc)
FRAME_ADDR stack;
CORE_ADDR pc;
setup_arbitrary_frame (argc, argv)
int argc;
FRAME_ADDR *argv;
{
return create_new_frame (stack, pc);
if (argc != 2)
error ("MIPS frame specifications require two arguments: sp and pc");
return create_new_frame (argv[0], argv[1]);
}
@ -470,12 +474,12 @@ mips_push_dummy_frame()
* Saved D18 (i.e. F19, F18)
* ...
* Saved D0 (i.e. F1, F0)
* CALL_DUMMY (subroutine stub; see m-mips.h)
* CALL_DUMMY (subroutine stub; see tm-mips.h)
* Parameter build area (not yet implemented)
* (low memory)
*/
PROC_REG_MASK(proc_desc) = GEN_REG_SAVE_MASK;
PROC_FREG_MASK(proc_desc) = FLOAT_REG_SAVE_MASK;
PROC_FREG_MASK(proc_desc) = mips_fpu ? FLOAT_REG_SAVE_MASK : 0;
PROC_REG_OFFSET(proc_desc) = /* offset of (Saved R31) from FP */
-sizeof(long) - 4 * SPECIAL_REG_SAVE_COUNT;
PROC_FREG_OFFSET(proc_desc) = /* offset of (Saved D18) from FP */
@ -507,9 +511,11 @@ mips_push_dummy_frame()
write_memory (sp - 8, (char *)&buffer, sizeof(REGISTER_TYPE));
buffer = read_register (LO_REGNUM);
write_memory (sp - 12, (char *)&buffer, sizeof(REGISTER_TYPE));
buffer = read_register (FCRCS_REGNUM);
buffer = read_register (mips_fpu ? FCRCS_REGNUM : ZERO_REGNUM);
write_memory (sp - 16, (char *)&buffer, sizeof(REGISTER_TYPE));
sp -= 4 * (GEN_REG_SAVE_COUNT+FLOAT_REG_SAVE_COUNT+SPECIAL_REG_SAVE_COUNT);
sp -= 4 * (GEN_REG_SAVE_COUNT
+ (mips_fpu ? FLOAT_REG_SAVE_COUNT : 0)
+ SPECIAL_REG_SAVE_COUNT);
write_register (SP_REGNUM, sp);
PROC_LOW_ADDR(proc_desc) = sp - CALL_DUMMY_SIZE + CALL_DUMMY_START_OFFSET;
PROC_HIGH_ADDR(proc_desc) = sp;
@ -568,7 +574,8 @@ mips_pop_frame()
write_register (HI_REGNUM, read_memory_integer(new_sp - 8, 4));
write_register (LO_REGNUM, read_memory_integer(new_sp - 12, 4));
write_register (FCRCS_REGNUM, read_memory_integer(new_sp - 16, 4));
if (mips_fpu)
write_register (FCRCS_REGNUM, read_memory_integer(new_sp - 16, 4));
}
}
@ -686,7 +693,11 @@ isa_NAN(p, len)
}
else if (len == 8)
{
#if TARGET_BYTE_ORDER == BIG_ENDIAN
exponent = *p;
#else
exponent = *(p+1);
#endif
exponent = exponent << 1 >> (32 - DOUBLE_EXP_BITS - 1);
return ((exponent == -1) || (! exponent && *p * *(p+1)));
}
@ -739,3 +750,17 @@ mips_skip_prologue(pc)
return pc;
}
/* Let the user turn off floating point. */
void
_initialize_mips_tdep ()
{
add_show_from_set
(add_set_cmd ("mips_fpu", class_support, var_boolean,
(char *) &mips_fpu,
"Set use of floating point coprocessor.\n\
Turn off to avoid using floating point instructions when calling functions\n\
or dealing with return values.", &setlist),
&showlist);
}

View File

@ -48,7 +48,7 @@ static int mips_cksum PARAMS ((const unsigned char *hdr,
int len));
static void
mips_send_packet PARAMS ((const char *s));
mips_send_packet PARAMS ((const char *s, int get_ack));
static int
mips_receive_packet PARAMS ((char *buff));
@ -57,6 +57,9 @@ static int
mips_request PARAMS ((char cmd, unsigned int addr, unsigned int data,
int *perr));
static void
mips_initialize PARAMS ((void));
static void
mips_open PARAMS ((char *name, int from_tty));
@ -246,6 +249,9 @@ extern struct target_ops mips_ops;
/* Set to 1 if the target is open. */
static int mips_is_open;
/* Set to 1 while the connection is being initialized. */
static int mips_initializing;
/* The next sequence number to send. */
static int mips_send_seq;
@ -263,7 +269,7 @@ static int mips_send_retries = 10;
static int mips_syn_garbage = 1050;
/* The time to wait for a packet, in seconds. */
static int mips_receive_wait = 30;
static int mips_receive_wait = 5;
/* Set if we have sent a packet to the board but have not yet received
a reply. */
@ -273,13 +279,25 @@ static int mips_need_reply = 0;
static int mips_debug = 0;
/* Read a character from the remote, aborting on error. Returns -2 on
timeout (since that's what serial_readchar returns). */
timeout (since that's what serial_readchar returns). FIXME: If we
see the string "<IDT>" from the board, then we are debugging on the
main console port, and we have somehow dropped out of remote
debugging mode. In this case, we automatically go back in to
remote debugging mode. This is a hack, put in because I can't find
any way for a program running on the remote board to terminate
without also ending remote debugging mode. I assume users won't
have any trouble with this; for one thing, the IDT documentation
generally assumes that the remote debugging port is not the console
port. This is, however, very convenient for DejaGnu when you only
have one connected serial port. */
static int
mips_readchar (timeout)
int timeout;
{
int ch;
static int state = 0;
static char nextstate[5] = { '<', 'I', 'D', 'T', '>' };
ch = serial_readchar (timeout);
if (ch == EOF)
@ -293,6 +311,34 @@ mips_readchar (timeout)
else
printf_filtered ("Timed out in read\n");
}
/* If we have seen <IDT> and we either time out, or we see a @
(which was echoed from a packet we sent), reset the board as
described above. The first character in a packet after the SYN
(which is not echoed) is always an @ unless the packet is more
than 64 characters long, which ours never are. */
if ((ch == -2 || ch == '@')
&& state == 5
&& ! mips_initializing)
{
if (mips_debug > 0)
printf_filtered ("Reinitializing MIPS debugging mode\n");
serial_write ("\rdb tty0\r", sizeof "\rdb tty0\r" - 1);
sleep (1);
mips_need_reply = 0;
mips_initialize ();
state = 0;
error ("Remote board reset");
}
if (ch == nextstate[state])
++state;
else
state = 0;
return ch;
}
@ -327,7 +373,11 @@ mips_receive_header (hdr, pgarbage, ch, timeout)
what the program is outputting, if the debugging is
being done on the console port. FIXME: Perhaps this
should be filtered? */
putchar (ch);
if (! mips_initializing || mips_debug > 0)
{
putchar (ch);
fflush (stdout);
}
++*pgarbage;
if (*pgarbage > mips_syn_garbage)
@ -416,8 +466,9 @@ mips_cksum (hdr, data, len)
/* Send a packet containing the given ASCII string. */
static void
mips_send_packet (s)
mips_send_packet (s, get_ack)
const char *s;
int get_ack;
{
unsigned int len;
unsigned char *packet;
@ -446,6 +497,9 @@ mips_send_packet (s)
the sequence number we expect in the acknowledgement. */
mips_send_seq = (mips_send_seq + 1) % SEQ_MODULOS;
if (! get_ack)
return;
/* We can only have one outstanding data packet, so we just wait for
the acknowledgement here. Keep retransmitting the packet until
we get one, or until we've tried too many times. */
@ -728,7 +782,7 @@ mips_request (cmd, addr, data, perr)
if (mips_need_reply)
fatal ("mips_request: Trying to send command before reply");
sprintf (buff, "0x0 %c 0x%x 0x%x", cmd, addr, data);
mips_send_packet (buff);
mips_send_packet (buff, 1);
mips_need_reply = 1;
}
@ -766,6 +820,64 @@ mips_request (cmd, addr, data, perr)
return rresponse;
}
/* Initialize a new connection to the MIPS board, and make sure we are
really connected. */
static void
mips_initialize ()
{
char cr;
int hold_wait;
int tries;
char buff[DATA_MAXLEN + 1];
int err;
if (mips_initializing)
return;
mips_initializing = 1;
mips_send_seq = 0;
mips_receive_seq = 0;
/* The board seems to want to send us a packet. I don't know what
it means. The packet seems to be triggered by a carriage return
character, although perhaps any character would do. */
cr = '\r';
serial_write (&cr, 1);
hold_wait = mips_receive_wait;
mips_receive_wait = 3;
tries = 0;
while (catch_errors (mips_receive_packet, buff, (char *) NULL) == 0)
{
char cc;
if (tries > 0)
error ("Could not connect to target");
++tries;
/* We did not receive the packet we expected; try resetting the
board and trying again. */
printf_filtered ("Failed to initialize; trying to reset board\n");
cc = '\003';
serial_write (&cc, 1);
sleep (2);
serial_write ("\rdb tty0\r", sizeof "\rdb tty0\r" - 1);
sleep (1);
cr = '\r';
serial_write (&cr, 1);
}
mips_receive_wait = hold_wait;
mips_initializing = 0;
/* If this doesn't call error, we have connected; we don't care if
the request itself succeeds or fails. */
mips_request ('r', (unsigned int) 0, (unsigned int) 0, &err);
}
/* Open a connection to the remote board. */
static void
@ -773,10 +885,6 @@ mips_open (name, from_tty)
char *name;
int from_tty;
{
int err;
char cr;
char buff[DATA_MAXLEN + 1];
if (name == 0)
error (
"To open a MIPS remote debugging connection, you need to specify what serial\n\
@ -785,28 +893,20 @@ device is attached to the target board (e.g., /dev/ttya).");
target_preopen (from_tty);
if (mips_is_open)
mips_close (0);
unpush_target (&mips_ops);
if (serial_open (name) == 0)
perror_with_name (name);
mips_is_open = 1;
/* The board seems to want to send us a packet. I don't know what
it means. */
cr = '\r';
serial_write (&cr, 1);
mips_receive_packet (buff);
/* If this doesn't call error, we have connected; we don't care if
the request itself succeeds or fails. */
mips_request ('r', (unsigned int) 0, (unsigned int) 0, &err);
mips_initialize ();
if (from_tty)
printf ("Remote MIPS debugging using %s\n", name);
push_target (&mips_ops); /* Switch to using remote target now */
start_remote (); /* Initialize gdb process mechanisms */
/* FIXME: Should we call start_remote here? */
}
/* Close a connection to the remote board. */
@ -817,11 +917,14 @@ mips_close (quitting)
{
if (mips_is_open)
{
/* Get the board out of remote debugging mode. */
mips_request ('x', (unsigned int) 0, (unsigned int) 0,
(int *) NULL);
serial_close ();
int err;
mips_is_open = 0;
/* Get the board out of remote debugging mode. */
mips_request ('x', (unsigned int) 0, (unsigned int) 0, &err);
serial_close ();
}
}
@ -852,7 +955,7 @@ mips_resume (step, siggnal)
siggnal);
mips_request (step ? 's' : 'c',
(unsigned int) read_register (PC_REGNUM),
(unsigned int) 1,
(unsigned int) 0,
(int *) NULL);
}
@ -1099,6 +1202,28 @@ mips_files_info (ignore)
printf ("Debugging a MIPS board over a serial line.\n");
}
/* Kill the process running on the board. This will actually only
work if we are doing remote debugging over the console input. I
think that if IDT/sim had the remote debug interrupt enabled on the
right port, we could interrupt the process with a break signal. */
static void
mips_kill ()
{
#if 0
if (mips_is_open)
{
char cc;
/* Send a ^C. */
cc = '\003';
serial_write (&cc, 1);
sleep (1);
target_mourn_inferior ();
}
#endif
}
/* Load an executable onto the board. */
static void
@ -1109,6 +1234,7 @@ mips_load (args, from_tty)
bfd *abfd;
asection *s;
int err;
CORE_ADDR text;
abfd = bfd_openr (args, 0);
if (abfd == (bfd *) NULL)
@ -1117,6 +1243,7 @@ mips_load (args, from_tty)
if (bfd_check_format (abfd, bfd_object) == 0)
error ("%s: Not an object file", args);
text = UINT_MAX;
for (s = abfd->sections; s != (asection *) NULL; s = s->next)
{
if ((s->flags & SEC_LOAD) != 0)
@ -1140,6 +1267,10 @@ mips_load (args, from_tty)
mips_xfer_memory (vma, buffer, size, 1, &mips_ops);
do_cleanups (old_chain);
if ((bfd_get_section_flags (abfd, s) & SEC_CODE) != 0
&& vma < text)
text = vma;
}
}
}
@ -1152,7 +1283,13 @@ mips_load (args, from_tty)
bfd_close (abfd);
/* FIXME: Should we call symbol_file_add here? */
/* FIXME: Should we call symbol_file_add here? The local variable
text exists just for this call. Making the call seems to confuse
gdb if more than one file is loaded in. Perhaps passing MAINLINE
as 1 would fix this, but it's not clear that that is correct
either since it is possible to load several files onto the board.
symbol_file_add (args, from_tty, text, 0, 0, 0); */
}
/* Start running on the target board. */
@ -1165,7 +1302,6 @@ mips_create_inferior (execfile, args, env)
{
CORE_ADDR entry_pt;
/* FIXME: Actually, we probably could pass arguments. */
if (args && *args)
error ("Can't pass arguments to remote MIPS board.");
@ -1176,6 +1312,8 @@ mips_create_inferior (execfile, args, env)
init_wait_for_inferior ();
/* FIXME: Should we set inferior_pid here? */
proceed (entry_pt, -1, 0);
}
@ -1213,7 +1351,7 @@ Specify the serial device it is connected to (e.g., /dev/ttya).", /* to_doc */
NULL, /* to_terminal_ours_for_output */
NULL, /* to_terminal_ours */
NULL, /* to_terminal_info */
NULL, /* to_kill */
mips_kill, /* to_kill */
mips_load, /* to_load */
NULL, /* to_lookup_symbol */
mips_create_inferior, /* to_create_inferior */

View File

@ -34,6 +34,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Floating point is IEEE compliant */
#define IEEE_FLOAT
/* Some MIPS boards are provided both with and without a floating
point coprocessor; we provide a user settable variable to tell gdb
whether there is one or not. */
extern int mips_fpu;
/* Define this if the C compiler puts an underscore at the front
of external names before giving them to the linker. */
@ -205,13 +210,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
into VALBUF. XXX floats */
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
bcopy (REGBUF+REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 2), VALBUF, TYPE_LENGTH (TYPE))
bcopy (REGBUF + REGISTER_BYTE ((TYPE_CODE (TYPE) == TYPE_CODE_FLT && mips_fpu) ? FP0_REGNUM : 2), VALBUF, TYPE_LENGTH (TYPE))
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
write_register_bytes (REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 2), VALBUF, TYPE_LENGTH (TYPE))
write_register_bytes (REGISTER_BYTE ((TYPE_CODE (TYPE) == TYPE_CODE_FLT && mips_fpu) ? FP0_REGNUM : 2), VALBUF, TYPE_LENGTH (TYPE))
/* Extract from an array REGBUF containing the (raw) register state
the address in which a function should return its structure value,
@ -294,11 +299,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
0, /* nop # ... to stop raw backtrace*/\
0x27bd0000, /* addu sp,?0 # Pseudo prologue */\
/* Start here: */\
MK_OP(061,SP_REGNUM,12,0), /* lwc1 $f12,0(sp) # Reload first 4 args*/\
MK_OP(061,SP_REGNUM,12,0), /* lwc1 $f12,0(sp) # Reload FP regs*/\
MK_OP(061,SP_REGNUM,13,4), /* lwc1 $f13,4(sp) */\
MK_OP(061,SP_REGNUM,14,8), /* lwc1 $f14,8(sp) */\
MK_OP(061,SP_REGNUM,15,12), /* lwc1 $f15,12(sp) */\
MK_OP(043,SP_REGNUM,4,0), /* lw $r4,0(sp) # Re-load FP regs*/\
MK_OP(043,SP_REGNUM,4,0), /* lw $r4,0(sp) # Reload first 4 args*/\
MK_OP(043,SP_REGNUM,5,4), /* lw $r5,4(sp) */\
MK_OP(043,SP_REGNUM,6,8), /* lw $r6,8(sp) */\
MK_OP(043,SP_REGNUM,7,12), /* lw $r7,12(sp) */\
@ -315,8 +320,19 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
into a call sequence of the above form stored at DUMMYNAME. */
#define FIX_CALL_DUMMY(dummyname, start_sp, fun, nargs, args, rettype, gcc_p)\
(((int*)dummyname)[11] |= (((unsigned long)(fun)) >> 16), \
((int*)dummyname)[12] |= (unsigned short)(fun))
do \
{ \
((int*)(dummyname))[11] |= ((unsigned long)(fun)) >> 16; \
((int*)(dummyname))[12] |= (unsigned short)(fun); \
if (! mips_fpu) \
{ \
((int *) (dummyname))[3] = 0; \
((int *) (dummyname))[4] = 0; \
((int *) (dummyname))[5] = 0; \
((int *) (dummyname))[6] = 0; \
} \
} \
while (0)
/* There's a mess in stack frame creation. See comments in blockframe.c
near reference to INIT_FRAME_PC_FIRST. */