#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 ();
}