#include <stdio.h>
#include <string.h>
#include <setjmp.h>
typedef void (*ExceptionHook)(int);
typedef void (*Function)();
extern void putDebugChar();
extern int getDebugChar();
extern Function exceptionHandler();
extern ExceptionHook exceptionHook;
static void
initializeRemcomErrorFrame ();
#define BUFMAX 400
static char initialized;
int remote_debug;
static const char hexchars[]="0123456789abcdef";
#define NUMREGBYTES 180
enum regnames {D0,D1,D2,D3,D4,D5,D6,D7,
A0,A1,A2,A3,A4,A5,A6,A7,
PS,PC,
FP0,FP1,FP2,FP3,FP4,FP5,FP6,FP7,
FPCONTROL,FPSTATUS,FPIADDR
};
typedef struct FrameStruct
{
struct FrameStruct *previous;
int exceptionPC;
int exceptionVector;
short frameSize;
short sr;
int pc;
short format;
int fsaveHeader;
int morejunk[0];
} Frame;
#define FRAMESIZE 500
int gdbFrameStack[FRAMESIZE];
static Frame *lastFrame;
int registers[NUMREGBYTES/4];
int superStack;
#define STACKSIZE 10000
int remcomStack[STACKSIZE/sizeof(int)];
static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
static ExceptionHook oldExceptionHook;
#ifdef mc68020
const short exceptionSize[] = { 4,4,6,4,4,4,4,4,29,10,16,46,12,4,4,4 };
#endif
#ifdef mc68332
static const short exceptionSize[] = { 4,4,6,4,4,4,4,4,4,4,4,4,16,4,4,4 };
#endif
jmp_buf remcomEnv;
#ifdef __HAVE_68881__
#define SAVE_FP_REGS() asm(" fsave a0@-"); \
asm(" fmovemx fp0-fp7,_registers+72"); \
asm(" fmoveml fpcr/fpsr/fpi,_registers+168");
#define RESTORE_FP_REGS() \
asm(" \n\
fmoveml _registers+168,fpcr/fpsr/fpi \n\
fmovemx _registers+72,fp0-fp7 \n\
cmpl #-1,a0@ | skip frestore flag set ? \n\
beq skip_frestore \n\
frestore a0@+ \n\
skip_frestore: \n\
");
#else
#define SAVE_FP_REGS()
#define RESTORE_FP_REGS()
#endif
void return_to_super();
void return_to_user();
asm("
.text
.globl _return_to_super
_return_to_super:
movel _registers+60,sp /* get new stack pointer */
movel _lastFrame,a0 /* get last frame info */
bra return_to_any
.globl _return_to_user
_return_to_user:
movel _registers+60,a0 /* get usp */
movel a0,usp /* set usp */
movel _superStack,sp /* get original stack pointer */
return_to_any:
movel _lastFrame,a0 /* get last frame info */
movel a0@+,_lastFrame /* link in previous frame */
addql #8,a0 /* skip over pc, vector#*/
movew a0@+,d0 /* get # of words in cpu frame */
addw d0,a0 /* point to end of data */
addw d0,a0 /* point to end of data */
movel a0,a1
#
# copy the stack frame
subql #1,d0
copyUserLoop:
movew a1@-,sp@-
dbf d0,copyUserLoop
");
RESTORE_FP_REGS()
asm(" moveml _registers,d0-d7/a0-a6");
asm(" rte");
#define DISABLE_INTERRUPTS() asm(" oriw #0x0700,sr");
#define BREAKPOINT() asm(" trap #1");
asm("
.text
.globl __debug_level7
__debug_level7:
movew d0,sp@-");
#if defined (mc68020) || defined (mc68332)
asm(" movew sp@(2),d0");
#else
asm(" movew sp@(6),d0");
#endif
asm(" andiw #0x700,d0
cmpiw #0x700,d0
beq _already7
movew sp@+,d0
bra __catchException
_already7:
movew sp@+,d0");
#if !defined (mc68020) && !defined (mc68332)
asm(" lea sp@(4),sp");
#endif
asm(" rte");
extern void _catchException ();
#if defined (mc68020) || defined (mc68332)
asm("
.text
.globl __catchException
__catchException:");
DISABLE_INTERRUPTS();
asm("
moveml d0-d7/a0-a6,_registers /* save registers */
movel _lastFrame,a0 /* last frame pointer */
");
SAVE_FP_REGS();
asm("
lea _registers,a5 /* get address of registers */
movew sp@,d1 /* get status register */
movew d1,a5@(66) /* save sr */
movel sp@(2),a4 /* save pc in a4 for later use */
movel a4,a5@(68) /* save pc in _regisers[] */
#
# figure out how many bytes in the stack frame
movew sp@(6),d0 /* get '020 exception format */
movew d0,d2 /* make a copy of format word */
andiw #0xf000,d0 /* mask off format type */
rolw #5,d0 /* rotate into the low byte *2 */
lea _exceptionSize,a1
addw d0,a1 /* index into the table */
movew a1@,d0 /* get number of words in frame */
movew d0,d3 /* save it */
subw d0,a0 /* adjust save pointer */
subw d0,a0 /* adjust save pointer(bytes) */
movel a0,a1 /* copy save pointer */
subql #1,d0 /* predecrement loop counter */
#
# copy the frame
saveFrameLoop:
movew sp@+,a1@+
dbf d0,saveFrameLoop
#
# now that the stack has been clenaed,
# save the a7 in use at time of exception
movel sp,_superStack /* save supervisor sp */
andiw #0x2000,d1 /* were we in supervisor mode ? */
beq userMode
movel a7,a5@(60) /* save a7 */
bra a7saveDone
userMode:
movel usp,a1
movel a1,a5@(60) /* save user stack pointer */
a7saveDone:
#
# save size of frame
movew d3,a0@-
#
# compute exception number
andl #0xfff,d2 /* mask off vector offset */
lsrw #2,d2 /* divide by 4 to get vect num */
movel d2,a0@- /* save it */
#
# save pc causing exception
movel a4,a0@-
#
# save old frame link and set the new value
movel _lastFrame,a1 /* last frame pointer */
movel a1,a0@- /* save pointer to prev frame */
movel a0,_lastFrame
movel d2,sp@- /* push exception num */
movel _exceptionHook,a0 /* get address of handler */
jbsr a0@ /* and call it */
clrl sp@ /* replace exception num parm with frame ptr */
jbsr __returnFromException /* jbsr, but never returns */
");
#else
asm("
.text
.globl __catchException
__catchException:");
DISABLE_INTERRUPTS();
asm("
moveml d0-d7/a0-a6,_registers /* save registers */
movel _lastFrame,a0 /* last frame pointer */
");
SAVE_FP_REGS();
asm("
lea _registers,a5 /* get address of registers */
movel sp@+,d2 /* pop return address */
addl #1530,d2 /* convert return addr to */
divs #6,d2 /* exception number */
extl d2
moveql #3,d3 /* assume a three word frame */
cmpiw #3,d2 /* bus error or address error ? */
bgt normal /* if >3 then normal error */
movel sp@+,a0@- /* copy error info to frame buff*/
movel sp@+,a0@- /* these are never used */
moveql #7,d3 /* this is a 7 word frame */
normal:
movew sp@+,d1 /* pop status register */
movel sp@+,a4 /* pop program counter */
movew d1,a5@(66) /* save sr */
movel a4,a5@(68) /* save pc in _regisers[] */
movel a4,a0@- /* copy pc to frame buffer */
movew d1,a0@- /* copy sr to frame buffer */
movel sp,_superStack /* save supervisor sp */
andiw #0x2000,d1 /* were we in supervisor mode ? */
beq userMode
movel a7,a5@(60) /* save a7 */
bra saveDone
userMode:
movel usp,a1 /* save user stack pointer */
movel a1,a5@(60) /* save user stack pointer */
saveDone:
movew d3,a0@- /* push frame size in words */
movel d2,a0@- /* push vector number */
movel a4,a0@- /* push exception pc */
#
# save old frame link and set the new value
movel _lastFrame,a1 /* last frame pointer */
movel a1,a0@- /* save pointer to prev frame */
movel a0,_lastFrame
movel d2,sp@- /* push exception num */
movel _exceptionHook,a0 /* get address of handler */
jbsr a0@ /* and call it */
clrl sp@ /* replace exception num parm with frame ptr */
jbsr __returnFromException /* jbsr, but never returns */
");
#endif
asm("_remcomHandler:");
asm(" addl #4,sp");
asm(" movel sp@+,d0");
asm(" movel _stackPtr,sp");
asm(" movel d0,sp@-");
asm(" jbsr _handle_exception");
asm(" rts");
void _returnFromException( Frame *frame )
{
if (! frame)
{
frame = lastFrame;
frame->frameSize = 4;
frame->format = 0;
frame->fsaveHeader = -1;
}
#if !defined (mc68020) && !defined (mc68332)
frame->frameSize=3;
#endif
lastFrame = frame;
frame->sr = registers[(int) PS];
frame->pc = registers[(int) PC];
if (registers[(int) PS] & 0x2000)
{
return_to_super();
}
else
{
return_to_user();
}
}
int hex(ch)
char ch;
{
if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
if ((ch >= '0') && (ch <= '9')) return (ch-'0');
if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
return (-1);
}
static char remcomInBuffer[BUFMAX];
static char remcomOutBuffer[BUFMAX];
unsigned char *
getpacket (void)
{
unsigned char *buffer = &remcomInBuffer[0];
unsigned char checksum;
unsigned char xmitcsum;
int count;
char ch;
while (1)
{
while ((ch = getDebugChar ()) != '$')
;
retry:
checksum = 0;
xmitcsum = -1;
count = 0;
while (count < BUFMAX)
{
ch = getDebugChar ();
if (ch == '$')
goto retry;
if (ch == '#')
break;
checksum = checksum + ch;
buffer[count] = ch;
count = count + 1;
}
buffer[count] = 0;
if (ch == '#')
{
ch = getDebugChar ();
xmitcsum = hex (ch) << 4;
ch = getDebugChar ();
xmitcsum += hex (ch);
if (checksum != xmitcsum)
{
if (remote_debug)
{
fprintf (stderr,
"bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
checksum, xmitcsum, buffer);
}
putDebugChar ('-');
}
else
{
putDebugChar ('+');
if (buffer[2] == ':')
{
putDebugChar (buffer[0]);
putDebugChar (buffer[1]);
return &buffer[3];
}
return &buffer[0];
}
}
}
}
void putpacket(buffer)
char * buffer;
{
unsigned char checksum;
int count;
char ch;
do {
putDebugChar('$');
checksum = 0;
count = 0;
while (ch=buffer[count]) {
putDebugChar(ch);
checksum += ch;
count += 1;
}
putDebugChar('#');
putDebugChar(hexchars[checksum >> 4]);
putDebugChar(hexchars[checksum % 16]);
} while (getDebugChar() != '+');
}
void debug_error(format, parm)
char * format;
char * parm;
{
if (remote_debug) fprintf (stderr,format,parm);
}
char* mem2hex(mem, buf, count)
char* mem;
char* buf;
int count;
{
int i;
unsigned char ch;
for (i=0;i<count;i++) {
ch = *mem++;
*buf++ = hexchars[ch >> 4];
*buf++ = hexchars[ch % 16];
}
*buf = 0;
return(buf);
}
char* hex2mem(buf, mem, count)
char* buf;
char* mem;
int count;
{
int i;
unsigned char ch;
for (i=0;i<count;i++) {
ch = hex(*buf++) << 4;
ch = ch + hex(*buf++);
*mem++ = ch;
}
return(mem);
}
void handle_buserror()
{
longjmp(remcomEnv,1);
}
int computeSignal( exceptionVector )
int exceptionVector;
{
int sigval;
switch (exceptionVector) {
case 2 : sigval = 10; break;
case 3 : sigval = 10; break;
case 4 : sigval = 4; break;
case 5 : sigval = 8; break;
case 6 : sigval = 8; break;
case 7 : sigval = 8; break;
case 8 : sigval = 11; break;
case 9 : sigval = 5; break;
case 10: sigval = 4; break;
case 11: sigval = 4; break;
case 13: sigval = 10; break;
case 31: sigval = 2; break;
case 33: sigval = 5; break;
case 40: sigval = 8; break;
case 48: sigval = 8; break;
case 49: sigval = 8; break;
case 50: sigval = 8; break;
case 51: sigval = 8; break;
case 52: sigval = 8; break;
case 53: sigval = 8; break;
case 54: sigval = 8; break;
default:
sigval = 7;
}
return (sigval);
}
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);
}
void handle_exception(int exceptionVector)
{
int sigval, stepping;
int addr, length;
char * ptr;
int newPC;
Frame *frame;
if (remote_debug) printf("vector=%d, sr=0x%x, pc=0x%x\n",
exceptionVector,
registers[ PS ],
registers[ PC ]);
sigval = computeSignal( exceptionVector );
remcomOutBuffer[0] = 'S';
remcomOutBuffer[1] = hexchars[sigval >> 4];
remcomOutBuffer[2] = hexchars[sigval % 16];
remcomOutBuffer[3] = 0;
putpacket(remcomOutBuffer);
stepping = 0;
while (1==1) {
remcomOutBuffer[0] = 0;
ptr = getpacket();
switch (*ptr++) {
case '?' : remcomOutBuffer[0] = 'S';
remcomOutBuffer[1] = hexchars[sigval >> 4];
remcomOutBuffer[2] = hexchars[sigval % 16];
remcomOutBuffer[3] = 0;
break;
case 'd' : remote_debug = !(remote_debug);
break;
case 'g' :
mem2hex((char*) registers, remcomOutBuffer, NUMREGBYTES);
break;
case 'G' :
hex2mem(ptr, (char*) registers, NUMREGBYTES);
strcpy(remcomOutBuffer,"OK");
break;
case 'm' :
if (setjmp(remcomEnv) == 0)
{
exceptionHandler(2,handle_buserror);
if (hexToInt(&ptr,&addr))
if (*(ptr++) == ',')
if (hexToInt(&ptr,&length))
{
ptr = 0;
mem2hex((char*) addr, remcomOutBuffer, length);
}
if (ptr)
{
strcpy(remcomOutBuffer,"E01");
}
} else {
exceptionHandler(2,_catchException);
strcpy(remcomOutBuffer,"E03");
debug_error("bus error");
}
exceptionHandler(2,_catchException);
break;
case 'M' :
if (setjmp(remcomEnv) == 0) {
exceptionHandler(2,handle_buserror);
if (hexToInt(&ptr,&addr))
if (*(ptr++) == ',')
if (hexToInt(&ptr,&length))
if (*(ptr++) == ':')
{
hex2mem(ptr, (char*) addr, length);
ptr = 0;
strcpy(remcomOutBuffer,"OK");
}
if (ptr)
{
strcpy(remcomOutBuffer,"E02");
}
} else {
exceptionHandler(2,_catchException);
strcpy(remcomOutBuffer,"E03");
debug_error("bus error");
}
exceptionHandler(2,_catchException);
break;
case 's' :
stepping = 1;
case 'c' :
if (hexToInt(&ptr,&addr))
registers[ PC ] = addr;
newPC = registers[ PC];
registers[ PS ] &= 0x7fff;
if (stepping) registers[ PS ] |= 0x8000;
if (remote_debug) printf("new pc = 0x%x\n",newPC);
frame = lastFrame;
while (frame)
{
if (remote_debug)
printf("frame at 0x%x has pc=0x%x, except#=%d\n",
frame,frame->exceptionPC,
frame->exceptionVector);
if (frame->exceptionPC == newPC) break;
if ((frame->exceptionVector == 33) &&
(frame->exceptionPC == (newPC+2))) break;
if (frame == frame->previous)
{
frame = 0;
break;
}
frame = frame->previous;
}
if (frame)
{
if ((frame->exceptionVector != 9) &&
(frame->exceptionVector != 31) &&
(frame->exceptionVector != 33))
{
if (oldExceptionHook)
(*oldExceptionHook) (frame->exceptionVector);
newPC = registers[ PC ];
if (newPC != frame->exceptionPC)
{
if (remote_debug)
printf("frame at 0x%x has pc=0x%x, except#=%d\n",
frame,frame->exceptionPC,
frame->exceptionVector);
frame = (Frame *) 0;
_returnFromException( frame );
}
}
}
if (frame == 0)
{
frame = lastFrame -1 ;
if ((unsigned int) (frame-2) < (unsigned int) &gdbFrameStack)
{
initializeRemcomErrorFrame();
frame = lastFrame;
}
frame->previous = lastFrame;
lastFrame = frame;
frame = 0;
}
_returnFromException( frame );
break;
case 'k' :
break;
}
putpacket(remcomOutBuffer);
}
}
void
initializeRemcomErrorFrame (void)
{
lastFrame = ((Frame *) &gdbFrameStack[FRAMESIZE-1]) - 1;
lastFrame->previous = lastFrame;
}
void set_debug_traps()
{
extern void _debug_level7();
extern void remcomHandler();
int exception;
initializeRemcomErrorFrame();
stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
for (exception = 2; exception <= 23; exception++)
exceptionHandler(exception,_catchException);
exceptionHandler(31,_debug_level7);
exceptionHandler(33,_catchException);
exceptionHandler(40,_catchException);
for (exception = 48; exception <= 54; exception++)
exceptionHandler(exception,_catchException);
if (oldExceptionHook != remcomHandler)
{
oldExceptionHook = exceptionHook;
exceptionHook = remcomHandler;
}
initialized = 1;
}
void breakpoint()
{
if (initialized) BREAKPOINT();
}