* remote.c (remote_open): Fix baud rate setting to make -b flag

work.  (remote_wait):  Change 'T' message parser to deal with new
improved format which allows stub to send an arbitrary bunch of
registers.
* sparc-stub.c:  General cleanups.  (trap_low, handle_exception):
make all this re-entrant by storing all state on the stack.  Clean
up memory error trapping.  (computeSignal, set_debug_traps):
make it all table driven.  Make a start at a baud rate setting command.
This commit is contained in:
Stu Grossman 1992-08-21 22:35:35 +00:00
parent 4772861e5b
commit 39a131782f
2 changed files with 380 additions and 472 deletions

View File

@ -1,3 +1,14 @@
Fri Aug 21 15:17:03 1992 Stu Grossman (grossman at cygnus.com)
* remote.c (remote_open): Fix baud rate setting to make -b flag
work. (remote_wait): Change 'T' message parser to deal with new
improved format which allows stub to send an arbitrary bunch of
registers.
* sparc-stub.c: General cleanups. (trap_low, handle_exception):
make all this re-entrant by storing all state on the stack. Clean
up memory error trapping. (computeSignal, set_debug_traps):
make it all table driven. Make a start at a baud rate setting command.
Wed Aug 19 10:23:27 1992 Ian Lance Taylor (ian@cygnus.com)
* m68k-pinsn.c: handle new operand type 'r', introduced for cas2.

View File

@ -60,6 +60,9 @@
*
* ? What was the last sigval ? SNN (signal NN)
*
* bBB..BB Set baud rate to BB..BB OK or BNN, then sets
* baud rate
*
* All commands and responses are sent with a packet which includes a
* checksum. A packet consists of
*
@ -79,7 +82,6 @@
*
****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <memory.h>
@ -101,9 +103,6 @@ static int initialized; /* boolean flag. != 0 means we've been initialized */
static void set_mem_fault_trap();
int remote_debug;
/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
static const char hexchars[]="0123456789abcdef";
#define NUMREGS 72
@ -121,8 +120,6 @@ enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
F24, F25, F26, F27, F28, F29, F30, F31,
Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
static unsigned long registers[NUMREGS] __attribute__ ((aligned (8)));
/*************************** ASSEMBLY CODE MACROS *************************/
/* */
@ -132,76 +129,8 @@ extern unsigned long rdtbr();
asm("
.text
!
! FUNCTION
! _chk4ovflo
!
! DESCRIPTION
! This code is branched to before each trap (except reset,
! _win_unf, and _win_ovf) handler.
! It checks to see if we've moved into the invalid window
! and performs fixup ala _win_ovf.
!
! INPUTS
! - %l1 = pc at trap time.
! - %l2 = npc at trap time.
! - %l7 = return address.
!
! INTERNAL DESCRIPTION
!
! RETURNS
! - None.
!
.align 4
_chk4ovflo:
mov %psr, %l0 ! get the psr
and %l0, 0x1F, %l3 ! get the cwp
mov 1, %l4 ! compare cwp with the wim
sll %l4, %l3, %l3 ! compare
mov %wim, %l4 ! read the wim
btst %l4, %l3
bz _retsave ! not invalid window, just return
nop
! in line version of _win_ovf
or %l0, 0xf20, %l3 ! enable traps, disable interrupts.
mov %l3, %psr
mov %g1, %l0 ! Save %g1.
srl %l4, 1, %g1 ! Next WIM = %g1 = rol(WIM, 1, NWINDOW)
sll %l4, 8-1, %l3
bset %l3, %g1
save %g0, %g0, %g0 ! Get into window to be saved.
mov %g1, %wim ! Install new wim.
nop ! must delay three instructions
nop ! before using these registers, so
nop ! put nops in just to be safe
std %l0, [%sp + 0 * 4] ! save all local registers
std %l2, [%sp + 2 * 4]
std %l4, [%sp + 4 * 4]
std %l6, [%sp + 6 * 4]
std %i0, [%sp + 8 * 4]
std %i2, [%sp + 10 * 4]
std %i4, [%sp + 12 * 4]
std %i6, [%sp + 14 * 4]
restore ! Go back to trap window.
mov %l0, %g1 ! Restore %g1.
_retsave:
! It is safe now to allocate a stack frame for this window
! because all overflow handling will have been accomplished
! in the event we trapped into the invalid window.
! ie. all of this window's %o regs (next window's %i regs)
! will have been safely stored to the stack before we overwrite %sp.
jmpl %l7+8, %g0 ! Window is valid, just return
sub %fp, (16+1+6+1)*4, %sp ! Make room for input & locals
! + hidden arg + arg spill
! + doubleword alignment
! Read the TBR.
.globl _rdtbr
@ -214,78 +143,93 @@ _rdtbr:
! available before jumping into C code. It will also restore the world if you
! return from handle_exception.
_trap_low:
set _registers, %l0
trap_low:
mov %psr, %l0
mov %wim, %l3
std %g0, [%l0 + 0 * 4] ! registers[Gx]
std %g2, [%l0 + 2 * 4]
std %g4, [%l0 + 4 * 4]
std %g6, [%l0 + 6 * 4]
srl %l3, %l0, %l4 ! wim >> cwp
cmp %l4, 1
bne window_fine ! Branch if not in the invalid window
nop
std %i0, [%l0 + 8 * 4] ! registers[Ox]
std %i2, [%l0 + 10 * 4]
std %i4, [%l0 + 12 * 4]
std %i6, [%l0 + 14 * 4]
! Handle window overflow
mov %g1, %l4 ! Save g1, we use it to hold the wim
srl %l3, 1, %g1 ! Rotate wim right
sll %l3, 8-1, %l5
or %l5, %g1, %g1
save %g0, %g0, %g0 ! Slip into next window
mov %g1, %wim ! Install the new wim
std %l0, [%sp + 0 * 4] ! save L & I registers
std %l2, [%sp + 2 * 4]
std %l4, [%sp + 4 * 4]
std %l6, [%sp + 6 * 4]
std %i0, [%sp + 8 * 4]
std %i2, [%sp + 10 * 4]
std %i4, [%sp + 12 * 4]
std %i6, [%sp + 14 * 4]
restore ! Go back to trap window.
mov %l4, %g1 ! Restore %g1
window_fine:
sub %fp, (16+1+6+1+72)*4, %sp ! Make room for input & locals
! + hidden arg + arg spill
! + doubleword alignment
! + registers[72] local var
std %g0, [%fp + (-72 + 0) * 4] ! registers[Gx]
std %g2, [%fp + (-72 + 2) * 4]
std %g4, [%fp + (-72 + 4) * 4]
std %g6, [%fp + (-72 + 6) * 4]
std %i0, [%fp + (-72 + 8) * 4] ! registers[Ox]
std %i2, [%fp + (-72 + 10) * 4]
std %i4, [%fp + (-72 + 12) * 4]
std %i6, [%fp + (-72 + 14) * 4]
! F0->F31 not implemented
mov %y, %l4
mov %psr, %l5
mov %wim, %l6
mov %tbr, %l7
std %l4, [%l0 + 64 * 4] ! Y & PSR
std %l6, [%l0 + 66 * 4] ! WIM & TBR
st %l1, [%l0 + 68 * 4] ! PC
st %l2, [%l0 + 69 * 4] ! NPC
mov %tbr, %l5
st %l4, [%fp + (-72 + 64) * 4] ! Y
st %l0, [%fp + (-72 + 65) * 4] ! PSR
st %l3, [%fp + (-72 + 66) * 4] ! WIM
st %l5, [%fp + (-72 + 67) * 4] ! TBR
st %l1, [%fp + (-72 + 68) * 4] ! PC
st %l2, [%fp + (-72 + 69) * 4] ! NPC
! CPSR and FPSR not impl
sethi %hi(_chk4ovflo), %l7 ! Must call this routine via %l7
jmpl %l7+%lo(_chk4ovflo), %l7 ! because o regs may not be available yet
nop
mov %psr, %o1
bset 0xf20, %o1
mov %o1, %psr ! Turn on traps, disable interrupts
or %l0, 0xf20, %l4
mov %l4, %psr ! Turn on traps, disable interrupts
call _handle_exception
nop
mov %o0, %l7 ! Save return value
! Reload all of the registers that aren't on the stack
set _registers, %l0 ! Need to use reg immune from save/rest
ld [%l0 + 1 * 4], %g1 ! registers[Gx]
ldd [%l0 + 2 * 4], %g2
ldd [%l0 + 4 * 4], %g4
ldd [%l0 + 6 * 4], %g6
ldd [%l0 + 8 * 4], %o0 ! registers[Ox]
ldd [%l0 + 10 * 4], %o2
ldd [%l0 + 12 * 4], %o4
ldd [%l0 + 14 * 4], %o6
add %fp, -72 * 4, %o0 ! Pass address of registers
restore ! Ensure that previous window is valid
save %g0, %g0, %g0 ! by causing a window_underflow trap
ld [%l0 + 64 * 4], %l3 ! registers[Y]
mov %l3, %y
ld [%l0 + 65 * 4], %l3 ! registers[PSR]
ld [%l0 + 68 * 4], %l1 ! registers[PC]
ld [%l0 + 69 * 4], %l2 ! registers[NPC]
! Reload all of the registers that aren't on the stack
tst %l7 ! Did handle_exception tell
bg retskip ! us to skip the next inst?
nop
ld [%fp + (-72 + 1) * 4], %g1 ! registers[Gx]
ldd [%fp + (-72 + 2) * 4], %g2
ldd [%fp + (-72 + 4) * 4], %g4
ldd [%fp + (-72 + 6) * 4], %g6
mov %l3, %psr ! Make sure that traps are disabled
ldd [%fp + (-72 + 8) * 4], %o0 ! registers[Ox]
ldd [%fp + (-72 + 10) * 4], %o2
ldd [%fp + (-72 + 12) * 4], %o4
ldd [%fp + (-72 + 14) * 4], %o6
ldd [%fp + (-72 + 64) * 4], %l0 ! Y & PSR
ldd [%fp + (-72 + 68) * 4], %l2 ! PC & NPC
mov %l0, %y
mov %l1, %psr ! Make sure that traps are disabled
! for rett
jmpl %l1, %g0 ! Restore old PC
rett %l2 ! Restore old nPC
mov %l3, %psr ! Make sure that traps are disabled
! for rett
retskip: ! Come here to skip the next instruction
jmpl %l2, %g0 ! Old nPC
rett %l2+4 ! Old nPC+4
jmpl %l2, %g0 ! Restore old PC
rett %l3 ! Restore old nPC
");
/* Convert ch from a hex digit to an int */
@ -345,13 +289,6 @@ getpacket(buffer)
{
xmitcsum = hex(getDebugChar()) << 4;
xmitcsum |= hex(getDebugChar());
#ifdef DEBUG
if (remote_debug && checksum != xmitcsum)
{
fprintf(stderr, "bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
checksum,xmitcsum,buffer);
}
#endif
#if 1
/* Humans shouldn't have to figure out checksums to type to it. */
putDebugChar ('+');
@ -411,48 +348,13 @@ putpacket(buffer)
while (getDebugChar() != '+');
}
static unsigned char remcomInBuffer[BUFMAX];
static unsigned char remcomOutBuffer[BUFMAX];
static short error;
static void
debug_error(format, parm)
char *format;
char *parm;
{
#ifdef DEBUG
if (remote_debug)
fprintf(stderr,format,parm);
#endif
}
/* Address of a routine to RTE to if we get a memory fault. */
static void (*mem_fault_routine)() = NULL;
static char remcomInBuffer[BUFMAX];
static char remcomOutBuffer[BUFMAX];
/* Indicate to caller of mem2hex or hex2mem that there has been an
error. */
static volatile int mem_err = 0;
/* These are separate functions so that they are so short and sweet
that the compiler won't save any registers (if there is a fault
to mem_fault, they won't get restored, so there better not be any
saved). */
static int
get_char (addr)
char *addr;
{
return *addr;
}
static void
set_char (addr, val)
char *addr;
int val;
{
*addr = val;
}
/* Convert the memory pointed to by mem into hex, placing result in buf.
* Return a pointer to the last char put in buf (null), in case of mem fault,
* return 0.
@ -473,7 +375,7 @@ mem2hex(mem, buf, count, may_fault)
while (count-- > 0)
{
ch = get_char(mem++);
ch = *mem++;
if (mem_err)
return 0;
*buf++ = hexchars[ch >> 4];
@ -506,7 +408,7 @@ hex2mem(buf, mem, count, may_fault)
{
ch = hex(*buf++) << 4;
ch |= hex(*buf++);
set_char(mem++, ch);
*mem++ = ch;
if (mem_err)
return 0;
}
@ -516,276 +418,26 @@ hex2mem(buf, mem, count, may_fault)
return mem;
}
/* this function takes the SPARC trap type code and attempts to
translate this number into a unix compatible signal value */
/* This table contains the mapping between SPARC hardware trap types, and
signals, which are primarily what GDB understands. It also indicates
which hardware traps we need to commandeer when initializing the stub. */
static int
computeSignal(tt)
int tt;
static struct hard_trap_info
{
int sigval;
switch (tt)
{
case 1:
sigval = SIGSEGV; break; /* instruction access error */
case 2:
sigval = SIGILL; break; /* privileged instruction */
case 3:
sigval = SIGILL; break; /* illegal instruction */
case 4:
sigval = SIGEMT; break; /* fp disabled */
case 36:
sigval = SIGEMT; break; /* cp disabled */
case 7:
sigval = SIGBUS; break; /* mem address not aligned */
case 9:
sigval = SIGSEGV; break; /* data access exception */
case 10:
sigval = SIGEMT; break; /* tag overflow */
case 128+1: /* ta 1 - normal breakpoint instruction */
case 255: /* breakpoint hardware unique to SPARClite */
sigval = SIGTRAP; break; /* breakpoint trap */
default:
sigval = SIGHUP; /* "software generated"*/
}
return (sigval);
}
/*
* While we find nice hex chars, build an int.
* Return number of chars processed.
*/
static int
hexToInt(char **ptr, int *intValue)
{
int numChars = 0;
int hexValue;
*intValue = 0;
while (**ptr)
{
hexValue = hex(**ptr);
if (hexValue >=0)
{
*intValue = (*intValue <<4) | hexValue;
numChars ++;
}
else
break;
(*ptr)++;
}
return (numChars);
}
/*
* This function does all command procesing for interfacing to gdb. It
* returns 1 if you should skip the instruction at the trap address, 0
* otherwise.
*/
static int
handle_exception ()
{
int tt; /* Trap type */
int sigval;
int addr;
int length;
char *ptr;
int newPC;
unsigned char *sp;
unsigned char *com;
/* First, we must force all of the windows to be spilled out */
asm(" save %g0, -64, %g0
save %g0, -64, %g0
save %g0, -64, %g0
save %g0, -64, %g0
save %g0, -64, %g0
save %g0, -64, %g0
save %g0, -64, %g0
save %g0, -64, %g0
restore
restore
restore
restore
restore
restore
restore
restore
");
#if 0
writez(1, "Got to handle_exception()\r\n ");
writez(1, "psr = 0x");
numout(registers[PSR], 16);
writez(1, " tbr = 0x");
numout(registers[TBR], 16);
writez(1, " oldpc = 0x");
numout(registers[PC], 16);
writez(1, " oldnpc = 0x");
numout(registers[NPC], 16);
writez(1, "\r\n");
#endif
sp = (unsigned char *)registers[SP];
tt = (registers[TBR] >> 4) & 0xff;
#ifdef DEBUG
if (remote_debug)
printf("tbr=0x%x, tt=%d, psr=0x%x, pc=0x%x, npc=0x%x\n",
registers[TBR], (registers[TBR] >> 4) & 0xff, registers[PSR], registers[PC], registers[NPC]);
#endif
/* reply to host that an exception has occurred */
sigval = computeSignal(tt);
com = remcomOutBuffer;
*com++ = 'T';
*com++ = hexchars[sigval >> 4];
*com++ = hexchars[sigval & 0xf];
*com++ = hexchars[PC >> 4];
*com++ = hexchars[PC & 0xf];
com = mem2hex((char *)&registers[PC], com, 4, 0);
*com++ = hexchars[FP >> 4];
*com++ = hexchars[FP & 0xf];
com = mem2hex(sp + (8 + 6) * 4, com, 4, 0); /* FP */
*com++ = hexchars[SP >> 4];
*com++ = hexchars[SP & 0xf];
com = mem2hex((char *)&registers[SP], com, 4, 0);
*com++ = hexchars[NPC >> 4];
*com++ = hexchars[NPC & 0xf];
com = mem2hex((char *)&registers[NPC], com, 4, 0);
*com++ = 0;
putpacket(remcomOutBuffer);
while (1)
{
error = 0;
remcomOutBuffer[0] = 0;
getpacket(remcomInBuffer);
switch (remcomInBuffer[0])
{
case '?':
remcomOutBuffer[0] = 'S';
remcomOutBuffer[1] = hexchars[sigval >> 4];
remcomOutBuffer[2] = hexchars[sigval & 0xf];
remcomOutBuffer[3] = 0;
break;
case 'd':
remote_debug = !remote_debug; /* toggle debug flag */
break;
case 'g': /* return the value of the CPU registers */
{
com = remcomOutBuffer;
com = mem2hex((char *)registers, com, 16 * 4, 0); /* G & O regs */
com = mem2hex(sp + 0 * 4, com, 8 * 4, 0); /* L regs */
com = mem2hex(sp + 8 * 4, com, 8 * 4, 0); /* I regs */
memset(com, '0', 32 * 8); /* Floating point */
mem2hex((char *)&registers[Y],
com + 32 * 4 * 2,
8 * 4,
0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
}
break;
case 'G': /* set the value of the CPU registers - return OK */
{
com = &remcomInBuffer[1];
hex2mem(com, (char *)registers, 16 * 4, 0); /* G & O regs */
hex2mem(com + 16 * 4 * 2, sp + 0 * 4, 8 * 4, 0); /* L regs */
hex2mem(com + 24 * 4 * 2, sp + 8 * 4, 8 * 4, 0); /* I regs */
hex2mem(com + 64 * 4 * 2, (char *)&registers[Y],
8 * 4, 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
strcpy(remcomOutBuffer,"OK");
}
break;
case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
/* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
ptr = &remcomInBuffer[1];
if (hexToInt(&ptr, &addr)
&& *ptr++ == ','
&& hexToInt(&ptr, &length))
{
if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
break;
strcpy (remcomOutBuffer, "E03");
debug_error ("memory fault");
}
else
{
strcpy(remcomOutBuffer,"E01");
debug_error("malformed read memory command: %s",remcomInBuffer);
}
break;
case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
/* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
ptr = &remcomInBuffer[1];
if (hexToInt(&ptr, &addr)
&& *ptr++ == ','
&& hexToInt(&ptr, &length)
&& *ptr++ == ':')
{
if (hex2mem(ptr, (char *)addr, length, 1))
strcpy(remcomOutBuffer, "OK");
else
{
strcpy(remcomOutBuffer, "E03");
debug_error("memory fault");
}
}
else
{
strcpy(remcomOutBuffer, "E02");
debug_error("malformed write memory command: %s",remcomInBuffer);
}
break;
case 'c': /* cAA..AA Continue at address AA..AA(optional) */
case 's': /* sAA..AA Step one instruction from AA..AA(optional) */
/* try to read optional parameter, pc unchanged if no parm */
ptr = &remcomInBuffer[1];
if (hexToInt(&ptr, &addr))
{
registers[PC] = addr;
registers[NPC] = addr + 4;
}
return 0;
/* kill the program */
case 'k' : /* do nothing */
break;
} /* switch */
/* reply to the request */
putpacket(remcomOutBuffer);
}
}
unsigned char tt; /* Trap type code for SPARClite */
unsigned char signo; /* Signal that we map this trap into */
} hard_trap_info[] = {
{1, SIGSEGV}, /* instruction access error */
{2, SIGILL}, /* privileged instruction */
{3, SIGILL}, /* illegal instruction */
{4, SIGEMT}, /* fp disabled */
{36, SIGEMT}, /* cp disabled */
{7, SIGBUS}, /* mem address not aligned */
{9, SIGSEGV}, /* data access exception */
{10, SIGEMT}, /* tag overflow */
{128+1, SIGTRAP}, /* ta 1 - normal breakpoint instruction */
{0, 0} /* Must be last */
};
/* Each entry in the trap vector occupies four words. */
@ -794,10 +446,6 @@ struct trap_entry
unsigned long ti[4];
};
#define NUMTRAPS 256
/* static struct trap_entry oldvec[NUMTRAPS];*/
extern struct trap_entry fltr_proto;
extern struct trap_entry fltr_set_mem_err;
asm ("
@ -805,8 +453,8 @@ asm ("
.globl _fltr_proto
.align 4
_fltr_proto: ! First level trap routine prototype
sethi %hi(_trap_low), %l0
jmpl %lo(_trap_low)+%l0, %g0
sethi %hi(trap_low), %l0
jmpl %lo(trap_low)+%l0, %g0
nop
nop
@ -824,35 +472,18 @@ _fltr_set_mem_err:
.text
");
/* this function is used to set up exception handlers for tracing and
breakpoints */
/* Set up exception handlers for tracing and breakpoints */
void
set_debug_traps()
{
int exception;
struct trap_entry *tb; /* Trap vector base address */
writez(1, "Got to set_debug_traps\r\n");
struct hard_trap_info *ht;
tb = (struct trap_entry *)(rdtbr() & ~0xfff);
writez(1, "tb = 0x");
numout(tb, 16);
writez(1, " trap ins = 0x");
numout(fltr_proto, 16);
writez(1, "\r\n");
tb[1] = fltr_proto; /* instruction access exception */
tb[2] = fltr_proto; /* privileged instruction */
tb[3] = fltr_proto; /* illegal instruction */
tb[4] = fltr_proto; /* fp disabled */
tb[36] = fltr_proto; /* cp disabled */
tb[7] = fltr_proto; /* mem address not aligned */
tb[9] = fltr_proto; /* data access exception */
tb[10] = fltr_proto; /* tag overflow */
tb[128+1] = fltr_proto; /* breakpoint instruction (ta 1) */
tb[255] = fltr_proto; /* hardware breakpoint trap */
for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
tb[ht->tt] = fltr_proto;
/* In case GDB is started before us, ack any packets (presumably
"$?#xx") sitting there. */
@ -878,6 +509,273 @@ set_mem_fault_trap(enable)
tb[9] = fltr_proto;
}
/* Convert the SPARC hardware trap type code to a unix signal number. */
static int
computeSignal(tt)
int tt;
{
struct hard_trap_info *ht;
for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
if (ht->tt == tt)
return ht->signo;
return SIGHUP; /* default for things we don't know about */
}
/*
* While we find nice hex chars, build an int.
* Return number of chars processed.
*/
static int
hexToInt(char **ptr, int *intValue)
{
int numChars = 0;
int hexValue;
*intValue = 0;
while (**ptr)
{
hexValue = hex(**ptr);
if (hexValue < 0)
break;
*intValue = (*intValue << 4) | hexValue;
numChars ++;
*ptr++;
}
return (numChars);
}
/*
* This function does all command procesing for interfacing to gdb. It
* returns 1 if you should skip the instruction at the trap address, 0
* otherwise.
*/
static void
handle_exception (registers)
unsigned long *registers;
{
int tt; /* Trap type */
int sigval;
int addr;
int length;
char *ptr;
unsigned long *sp;
/* First, we must force all of the windows to be spilled out */
asm(" save %sp, -64, %sp
save %sp, -64, %sp
save %sp, -64, %sp
save %sp, -64, %sp
save %sp, -64, %sp
save %sp, -64, %sp
save %sp, -64, %sp
save %sp, -64, %sp
restore
restore
restore
restore
restore
restore
restore
restore
");
sp = (unsigned long *)registers[SP];
tt = (registers[TBR] >> 4) & 0xff;
/* reply to host that an exception has occurred */
sigval = computeSignal(tt);
ptr = remcomOutBuffer;
*ptr++ = 'T';
*ptr++ = hexchars[sigval >> 4];
*ptr++ = hexchars[sigval & 0xf];
*ptr++ = hexchars[PC >> 4];
*ptr++ = hexchars[PC & 0xf];
*ptr++ = ':';
ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
*ptr++ = ';';
*ptr++ = hexchars[FP >> 4];
*ptr++ = hexchars[FP & 0xf];
*ptr++ = ':';
ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
*ptr++ = ';';
*ptr++ = hexchars[SP >> 4];
*ptr++ = hexchars[SP & 0xf];
*ptr++ = ':';
ptr = mem2hex((char *)&sp, ptr, 4, 0);
*ptr++ = ';';
*ptr++ = hexchars[NPC >> 4];
*ptr++ = hexchars[NPC & 0xf];
*ptr++ = ':';
ptr = mem2hex((char *)&registers[NPC], ptr, 4, 0);
*ptr++ = ';';
*ptr++ = hexchars[O7 >> 4];
*ptr++ = hexchars[O7 & 0xf];
*ptr++ = ':';
ptr = mem2hex((char *)&registers[O7], ptr, 4, 0);
*ptr++ = ';';
*ptr++ = 0;
putpacket(remcomOutBuffer);
while (1)
{
remcomOutBuffer[0] = 0;
getpacket(remcomInBuffer);
switch (remcomInBuffer[0])
{
case '?':
remcomOutBuffer[0] = 'S';
remcomOutBuffer[1] = hexchars[sigval >> 4];
remcomOutBuffer[2] = hexchars[sigval & 0xf];
remcomOutBuffer[3] = 0;
break;
case 'd':
/* toggle debug flag */
break;
case 'g': /* return the value of the CPU registers */
{
ptr = remcomOutBuffer;
ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
ptr = mem2hex(sp + 0, ptr, 8 * 4, 0); /* L regs */
ptr = mem2hex(sp + 8, ptr, 8 * 4, 0); /* I regs */
memset(ptr, '0', 32 * 8); /* Floating point */
mem2hex((char *)&registers[Y],
ptr + 32 * 4 * 2,
8 * 4,
0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
}
break;
case 'G': /* set the value of the CPU registers - return OK */
{
ptr = &remcomInBuffer[1];
hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
hex2mem(ptr + 16 * 4 * 2, sp + 0, 8 * 4, 0); /* L regs */
hex2mem(ptr + 24 * 4 * 2, sp + 8, 8 * 4, 0); /* I regs */
hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y],
8 * 4, 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
strcpy(remcomOutBuffer,"OK");
}
break;
case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
/* Try to read %x,%x. */
ptr = &remcomInBuffer[1];
if (hexToInt(&ptr, &addr)
&& *ptr++ == ','
&& hexToInt(&ptr, &length))
{
if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
break;
strcpy (remcomOutBuffer, "E03");
}
else
strcpy(remcomOutBuffer,"E01");
break;
case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
/* Try to read '%x,%x:'. */
ptr = &remcomInBuffer[1];
if (hexToInt(&ptr, &addr)
&& *ptr++ == ','
&& hexToInt(&ptr, &length)
&& *ptr++ == ':')
{
if (hex2mem(ptr, (char *)addr, length, 1))
strcpy(remcomOutBuffer, "OK");
else
strcpy(remcomOutBuffer, "E03");
}
else
strcpy(remcomOutBuffer, "E02");
break;
case 'c': /* cAA..AA Continue at address AA..AA(optional) */
case 's': /* sAA..AA Step one instruction from AA..AA(optional) */
/* try to read optional parameter, pc unchanged if no parm */
ptr = &remcomInBuffer[1];
if (hexToInt(&ptr, &addr))
{
registers[PC] = addr;
registers[NPC] = addr + 4;
}
return;
/* kill the program */
case 'k' : /* do nothing */
break;
#if 0
Disabled until we can unscrew this properly
case 'b': /* bBB... Set baud rate to BB... */
{
int baudrate;
extern void set_timer_3();
ptr = &remcomInBuffer[1];
if (!hexToInt(&ptr, &baudrate))
{
strcpy(remcomOutBuffer,"B01");
break;
}
/* Convert baud rate to uart clock divider */
switch (baudrate)
{
case 38400:
baudrate = 16;
break;
case 19200:
baudrate = 33;
break;
case 9600:
baudrate = 65;
break;
default:
strcpy(remcomOutBuffer,"B02");
goto x1;
}
putpacket("OK"); /* Ack before changing speed */
set_timer_3(baudrate); /* Set it */
}
x1: break;
#endif
} /* switch */
/* reply to the request */
putpacket(remcomOutBuffer);
}
}
/* This function will generate a breakpoint exception. It is used at the
beginning of a program to sync up with a debugger and can be used
otherwise as a quick means to stop program execution and "break" into
@ -886,7 +784,6 @@ set_mem_fault_trap(enable)
void
breakpoint()
{
writez(1, "About to do a breakpoint\r\n\n");
if (initialized)
BREAKPOINT();
}