Home | History | Annotate | Line # | Download | only in stubs
      1  1.1  christos /****************************************************************************
      2  1.1  christos 
      3  1.1  christos 		THIS SOFTWARE IS NOT COPYRIGHTED
      4  1.1  christos 
      5  1.1  christos    HP offers the following for use in the public domain.  HP makes no
      6  1.1  christos    warranty with regard to the software or it's performance and the
      7  1.1  christos    user accepts the software "AS IS" with all faults.
      8  1.1  christos 
      9  1.1  christos    HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
     10  1.1  christos    TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
     11  1.1  christos    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     12  1.1  christos 
     13  1.1  christos ****************************************************************************/
     14  1.1  christos 
     15  1.1  christos /****************************************************************************
     16  1.1  christos  *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
     17  1.1  christos  *
     18  1.1  christos  *  Module name: remcom.c $
     19  1.1  christos  *  Revision: 1.34 $
     20  1.1  christos  *  Date: 91/03/09 12:29:49 $
     21  1.1  christos  *  Contributor:     Lake Stevens Instrument Division$
     22  1.1  christos  *
     23  1.1  christos  *  Description:     low level support for gdb debugger. $
     24  1.1  christos  *
     25  1.1  christos  *  Considerations:  only works on target hardware $
     26  1.1  christos  *
     27  1.1  christos  *  Written by:      Glenn Engel $
     28  1.1  christos  *  ModuleState:     Experimental $
     29  1.1  christos  *
     30  1.1  christos  *  NOTES:           See Below $
     31  1.1  christos  *
     32  1.1  christos  *  To enable debugger support, two things need to happen.  One, a
     33  1.1  christos  *  call to set_debug_traps() is necessary in order to allow any breakpoints
     34  1.1  christos  *  or error conditions to be properly intercepted and reported to gdb.
     35  1.1  christos  *  Two, a breakpoint needs to be generated to begin communication.  This
     36  1.1  christos  *  is most easily accomplished by a call to breakpoint().  Breakpoint()
     37  1.1  christos  *  simulates a breakpoint by executing a trap #1.  The breakpoint instruction
     38  1.1  christos  *  is hardwired to trap #1 because not to do so is a compatibility problem--
     39  1.1  christos  *  there either should be a standard breakpoint instruction, or the protocol
     40  1.1  christos  *  should be extended to provide some means to communicate which breakpoint
     41  1.1  christos  *  instruction is in use (or have the stub insert the breakpoint).
     42  1.1  christos  *
     43  1.1  christos  *  Some explanation is probably necessary to explain how exceptions are
     44  1.1  christos  *  handled.  When an exception is encountered the 68000 pushes the current
     45  1.1  christos  *  program counter and status register onto the supervisor stack and then
     46  1.1  christos  *  transfers execution to a location specified in it's vector table.
     47  1.1  christos  *  The handlers for the exception vectors are hardwired to jmp to an address
     48  1.6  christos  *  given by the relation:  (exception - 256) * 6.  These are descending
     49  1.1  christos  *  addresses starting from -6, -12, -18, ...  By allowing 6 bytes for
     50  1.1  christos  *  each entry, a jsr, jmp, bsr, ... can be used to enter the exception
     51  1.1  christos  *  handler.  Using a jsr to handle an exception has an added benefit of
     52  1.1  christos  *  allowing a single handler to service several exceptions and use the
     53  1.1  christos  *  return address as the key differentiation.  The vector number can be
     54  1.1  christos  *  computed from the return address by [ exception = (addr + 1530) / 6 ].
     55  1.1  christos  *  The sole purpose of the routine _catchException is to compute the
     56  1.1  christos  *  exception number and push it on the stack in place of the return address.
     57  1.1  christos  *  The external function exceptionHandler() is
     58  1.1  christos  *  used to attach a specific handler to a specific m68k exception.
     59  1.1  christos  *  For 68020 machines, the ability to have a return address around just
     60  1.1  christos  *  so the vector can be determined is not necessary because the '020 pushes an
     61  1.1  christos  *  extra word onto the stack containing the vector offset
     62  1.1  christos  *
     63  1.1  christos  *  Because gdb will sometimes write to the stack area to execute function
     64  1.1  christos  *  calls, this program cannot rely on using the supervisor stack so it
     65  1.8  christos  *  uses its own stack area reserved in the int array remcomStack.
     66  1.1  christos  *
     67  1.1  christos  *************
     68  1.1  christos  *
     69  1.1  christos  *    The following gdb commands are supported:
     70  1.1  christos  *
     71  1.1  christos  * command          function                               Return value
     72  1.1  christos  *
     73  1.1  christos  *    g             return the value of the CPU registers  hex data or ENN
     74  1.1  christos  *    G             set the value of the CPU registers     OK or ENN
     75  1.1  christos  *
     76  1.1  christos  *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
     77  1.1  christos  *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
     78  1.1  christos  *
     79  1.1  christos  *    c             Resume at current address              SNN   ( signal NN)
     80  1.1  christos  *    cAA..AA       Continue at address AA..AA             SNN
     81  1.1  christos  *
     82  1.1  christos  *    s             Step one instruction                   SNN
     83  1.1  christos  *    sAA..AA       Step one instruction from AA..AA       SNN
     84  1.1  christos  *
     85  1.1  christos  *    k             kill
     86  1.1  christos  *
     87  1.1  christos  *    ?             What was the last sigval ?             SNN   (signal NN)
     88  1.1  christos  *
     89  1.1  christos  * All commands and responses are sent with a packet which includes a
     90  1.1  christos  * checksum.  A packet consists of
     91  1.1  christos  *
     92  1.1  christos  * $<packet info>#<checksum>.
     93  1.1  christos  *
     94  1.1  christos  * where
     95  1.1  christos  * <packet info> :: <characters representing the command or response>
     96  1.1  christos  * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
     97  1.1  christos  *
     98  1.1  christos  * When a packet is received, it is first acknowledged with either '+' or '-'.
     99  1.1  christos  * '+' indicates a successful transfer.  '-' indicates a failed transfer.
    100  1.1  christos  *
    101  1.1  christos  * Example:
    102  1.1  christos  *
    103  1.1  christos  * Host:                  Reply:
    104  1.1  christos  * $m0,10#2a               +$00010203040506070809101112131415#42
    105  1.1  christos  *
    106  1.1  christos  ****************************************************************************/
    107  1.1  christos 
    108  1.1  christos #include <stdio.h>
    109  1.1  christos #include <string.h>
    110  1.1  christos #include <setjmp.h>
    111  1.1  christos 
    112  1.1  christos /************************************************************************
    113  1.1  christos  *
    114  1.1  christos  * external low-level support routines
    115  1.1  christos  */
    116  1.1  christos typedef void (*ExceptionHook)(int);   /* pointer to function with int parm */
    117  1.1  christos typedef void (*Function)();           /* pointer to a function */
    118  1.1  christos 
    119  1.1  christos extern void putDebugChar();	/* write a single character      */
    120  1.1  christos extern int getDebugChar();	/* read and return a single char */
    121  1.1  christos 
    122  1.1  christos extern Function exceptionHandler();  /* assign an exception handler */
    123  1.1  christos extern ExceptionHook exceptionHook;  /* hook variable for errors/exceptions */
    124  1.1  christos 
    125  1.1  christos /************************/
    126  1.1  christos /* FORWARD DECLARATIONS */
    127  1.1  christos /************************/
    128  1.1  christos static void
    129  1.1  christos initializeRemcomErrorFrame ();
    130  1.1  christos 
    131  1.1  christos /************************************************************************/
    132  1.1  christos /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
    133  1.1  christos /* at least NUMREGBYTES*2 are needed for register packets */
    134  1.1  christos #define BUFMAX 400
    135  1.1  christos 
    136  1.1  christos static char initialized;  /* boolean flag. != 0 means we've been initialized */
    137  1.1  christos 
    138  1.1  christos int     remote_debug;
    139  1.1  christos /*  debug >  0 prints ill-formed commands in valid packets & checksum errors */
    140  1.1  christos 
    141  1.1  christos static const char hexchars[]="0123456789abcdef";
    142  1.1  christos 
    143  1.1  christos /* there are 180 bytes of registers on a 68020 w/68881      */
    144  1.1  christos /* many of the fpa registers are 12 byte (96 bit) registers */
    145  1.1  christos #define NUMREGBYTES 180
    146  1.1  christos enum regnames {D0,D1,D2,D3,D4,D5,D6,D7,
    147  1.7  christos 	       A0,A1,A2,A3,A4,A5,A6,A7,
    148  1.7  christos 	       PS,PC,
    149  1.7  christos 	       FP0,FP1,FP2,FP3,FP4,FP5,FP6,FP7,
    150  1.7  christos 	       FPCONTROL,FPSTATUS,FPIADDR
    151  1.7  christos 	      };
    152  1.1  christos 
    153  1.1  christos 
    154  1.1  christos /* We keep a whole frame cache here.  "Why?", I hear you cry, "doesn't
    156  1.1  christos    GDB handle that sort of thing?"  Well, yes, I believe the only
    157  1.1  christos    reason for this cache is to save and restore floating point state
    158  1.1  christos    (fsave/frestore).  A cleaner way to do this would be to make the
    159  1.1  christos  fsave data part of the registers which GDB deals with like any
    160  1.1  christos    other registers.  This should not be a performance problem if the
    161  1.1  christos    ability to read individual registers is added to the protocol.  */
    162  1.1  christos 
    163  1.1  christos typedef struct FrameStruct
    164  1.1  christos {
    165  1.1  christos     struct FrameStruct  *previous;
    166  1.1  christos     int       exceptionPC;      /* pc value when this frame created */
    167  1.1  christos     int       exceptionVector;  /* cpu vector causing exception     */
    168  1.1  christos     short     frameSize;        /* size of cpu frame in words       */
    169  1.1  christos     short     sr;               /* for 68000, this not always sr    */
    170  1.1  christos     int       pc;
    171  1.1  christos     short     format;
    172  1.1  christos     int       fsaveHeader;
    173  1.1  christos     int       morejunk[0];        /* exception frame, fp save... */
    174  1.1  christos } Frame;
    175  1.1  christos 
    176  1.1  christos #define FRAMESIZE 500
    177  1.1  christos int   gdbFrameStack[FRAMESIZE];
    178  1.1  christos static Frame *lastFrame;
    179  1.1  christos 
    180  1.1  christos /*
    181  1.1  christos  * these should not be static cuz they can be used outside this module
    182  1.1  christos  */
    183  1.1  christos int registers[NUMREGBYTES/4];
    184  1.1  christos int superStack;
    185  1.1  christos 
    186  1.1  christos #define STACKSIZE 10000
    187  1.1  christos int remcomStack[STACKSIZE/sizeof(int)];
    188  1.1  christos static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
    189  1.1  christos 
    190  1.1  christos /*
    191  1.1  christos  * In many cases, the system will want to continue exception processing
    192  1.1  christos  * when a continue command is given.
    193  1.1  christos  * oldExceptionHook is a function to invoke in this case.
    194  1.1  christos  */
    195  1.1  christos 
    196  1.1  christos static ExceptionHook oldExceptionHook;
    197  1.1  christos 
    198  1.1  christos #ifdef mc68020
    199  1.1  christos /* the size of the exception stack on the 68020 varies with the type of
    200  1.1  christos  * exception.  The following table is the number of WORDS used
    201  1.1  christos  * for each exception format.
    202  1.1  christos  */
    203  1.1  christos const short exceptionSize[] = { 4,4,6,4,4,4,4,4,29,10,16,46,12,4,4,4 };
    204  1.1  christos #endif
    205  1.1  christos 
    206  1.1  christos #ifdef mc68332
    207  1.1  christos static const short exceptionSize[] = { 4,4,6,4,4,4,4,4,4,4,4,4,16,4,4,4 };
    208  1.1  christos #endif
    209  1.1  christos 
    210  1.1  christos /************* jump buffer used for setjmp/longjmp **************************/
    211  1.1  christos jmp_buf remcomEnv;
    212  1.1  christos 
    213  1.1  christos /***************************  ASSEMBLY CODE MACROS *************************/
    214  1.1  christos /* 									   */
    215  1.1  christos 
    216  1.1  christos #ifdef __HAVE_68881__
    217  1.1  christos /* do an fsave, then remember the address to begin a restore from */
    218  1.1  christos #define SAVE_FP_REGS()    asm(" fsave   a0@-");		\
    219  1.1  christos 			  asm(" fmovemx fp0-fp7,_registers+72");        \
    220  1.1  christos 			  asm(" fmoveml fpcr/fpsr/fpi,_registers+168");
    221  1.1  christos #define RESTORE_FP_REGS()                              \
    222  1.1  christos asm("                                                \n\
    223  1.1  christos     fmoveml  _registers+168,fpcr/fpsr/fpi            \n\
    224  1.1  christos     fmovemx  _registers+72,fp0-fp7                   \n\
    225  1.1  christos     cmpl     #-1,a0@     |  skip frestore flag set ? \n\
    226  1.1  christos     beq      skip_frestore                           \n\
    227  1.1  christos     frestore a0@+                                    \n\
    228  1.1  christos skip_frestore:                                       \n\
    229  1.1  christos ");
    230  1.1  christos 
    231  1.1  christos #else
    232  1.1  christos #define SAVE_FP_REGS()
    233  1.1  christos #define RESTORE_FP_REGS()
    234  1.1  christos #endif /* __HAVE_68881__ */
    235  1.1  christos 
    236  1.1  christos void return_to_super();
    237  1.1  christos void return_to_user();
    238  1.1  christos 
    239  1.1  christos asm("
    240  1.1  christos .text
    241  1.1  christos .globl _return_to_super
    242  1.7  christos _return_to_super:
    243  1.7  christos 	movel   _registers+60,sp /* get new stack pointer */
    244  1.7  christos 	movel   _lastFrame,a0   /* get last frame info  */
    245  1.1  christos 	bra     return_to_any
    246  1.1  christos 
    247  1.1  christos .globl _return_to_user
    248  1.7  christos _return_to_user:
    249  1.7  christos 	movel   _registers+60,a0 /* get usp */
    250  1.7  christos 	movel   a0,usp           /* set usp */
    251  1.1  christos 	movel   _superStack,sp  /* get original stack pointer */
    252  1.1  christos 
    253  1.7  christos return_to_any:
    254  1.7  christos 	movel   _lastFrame,a0   /* get last frame info  */
    255  1.7  christos 	movel   a0@+,_lastFrame /* link in previous frame     */
    256  1.7  christos 	addql   #8,a0           /* skip over pc, vector#*/
    257  1.7  christos 	movew   a0@+,d0         /* get # of words in cpu frame */
    258  1.7  christos 	addw    d0,a0           /* point to end of data        */
    259  1.7  christos 	addw    d0,a0           /* point to end of data        */
    260  1.1  christos 	movel   a0,a1
    261  1.1  christos #
    262  1.7  christos # copy the stack frame
    263  1.1  christos 	subql   #1,d0
    264  1.7  christos copyUserLoop:
    265  1.7  christos 	movew   a1@-,sp@-
    266  1.1  christos 	dbf     d0,copyUserLoop
    267  1.7  christos ");
    268  1.1  christos 	RESTORE_FP_REGS()
    269  1.1  christos    asm("   moveml  _registers,d0-d7/a0-a6");
    270  1.1  christos    asm("   rte");  /* pop and go! */
    271  1.1  christos 
    272  1.1  christos #define DISABLE_INTERRUPTS()   asm("         oriw   #0x0700,sr");
    273  1.1  christos #define BREAKPOINT() asm("   trap #1");
    274  1.1  christos 
    275  1.1  christos /* this function is called immediately when a level 7 interrupt occurs */
    276  1.1  christos /* if the previous interrupt level was 7 then we're already servicing  */
    277  1.1  christos /* this interrupt and an rte is in order to return to the debugger.    */
    278  1.1  christos /* For the 68000, the offset for sr is 6 due to the jsr return address */
    279  1.1  christos asm("
    280  1.1  christos .text
    281  1.1  christos .globl __debug_level7
    282  1.1  christos __debug_level7:
    283  1.1  christos 	movew   d0,sp@-");
    284  1.1  christos #if defined (mc68020) || defined (mc68332)
    285  1.1  christos asm("	movew   sp@(2),d0");
    286  1.1  christos #else
    287  1.1  christos asm("	movew   sp@(6),d0");
    288  1.1  christos #endif
    289  1.1  christos asm("	andiw   #0x700,d0
    290  1.1  christos 	cmpiw   #0x700,d0
    291  1.7  christos 	beq     _already7
    292  1.7  christos 	movew   sp@+,d0
    293  1.1  christos 	bra     __catchException
    294  1.1  christos _already7:
    295  1.1  christos 	movew   sp@+,d0");
    296  1.1  christos #if !defined (mc68020) && !defined (mc68332)
    297  1.1  christos asm("	lea     sp@(4),sp");     /* pull off 68000 return address */
    298  1.1  christos #endif
    299  1.1  christos asm("	rte");
    300  1.1  christos 
    301  1.1  christos extern void _catchException ();
    302  1.1  christos 
    303  1.1  christos #if defined (mc68020) || defined (mc68332)
    304  1.1  christos /* This function is called when a 68020 exception occurs.  It saves
    305  1.1  christos  * all the cpu and fpcp regs in the _registers array, creates a frame on a
    306  1.1  christos  * linked list of frames which has the cpu and fpcp stack frames needed
    307  1.1  christos  * to properly restore the context of these processors, and invokes
    308  1.1  christos  * an exception handler (remcom_handler).
    309  1.1  christos  *
    310  1.1  christos  * stack on entry:                       stack on exit:
    311  1.1  christos  *   N bytes of junk                     exception # MSWord
    312  1.1  christos  *   Exception Format Word               exception # MSWord
    313  1.1  christos  *   Program counter LSWord
    314  1.1  christos  *   Program counter MSWord
    315  1.1  christos  *   Status Register
    316  1.1  christos  *
    317  1.1  christos  *
    318  1.1  christos  */
    319  1.1  christos asm("
    320  1.1  christos .text
    321  1.1  christos .globl __catchException
    322  1.1  christos __catchException:");
    323  1.1  christos DISABLE_INTERRUPTS();
    324  1.7  christos asm("
    325  1.1  christos 	moveml  d0-d7/a0-a6,_registers /* save registers        */
    326  1.1  christos 	movel	_lastFrame,a0	/* last frame pointer */
    327  1.1  christos ");
    328  1.1  christos SAVE_FP_REGS();
    329  1.1  christos asm("
    330  1.7  christos 	lea     _registers,a5   /* get address of registers     */
    331  1.7  christos 	movew   sp@,d1          /* get status register          */
    332  1.1  christos 	movew   d1,a5@(66)      /* save sr		 	*/
    333  1.7  christos 	movel   sp@(2),a4       /* save pc in a4 for later use  */
    334  1.1  christos 	movel   a4,a5@(68)      /* save pc in _regisers[]      	*/
    335  1.1  christos 
    336  1.1  christos #
    337  1.1  christos # figure out how many bytes in the stack frame
    338  1.7  christos 	movew   sp@(6),d0	/* get '020 exception format	*/
    339  1.7  christos 	movew   d0,d2           /* make a copy of format word   */
    340  1.7  christos 	andiw   #0xf000,d0      /* mask off format type         */
    341  1.7  christos 	rolw    #5,d0           /* rotate into the low byte *2  */
    342  1.7  christos 	lea     _exceptionSize,a1
    343  1.1  christos 	addw    d0,a1           /* index into the table         */
    344  1.7  christos 	movew   a1@,d0          /* get number of words in frame */
    345  1.7  christos 	movew   d0,d3           /* save it                      */
    346  1.7  christos 	subw    d0,a0		/* adjust save pointer          */
    347  1.1  christos 	subw    d0,a0		/* adjust save pointer(bytes)   */
    348  1.1  christos 	movel   a0,a1           /* copy save pointer            */
    349  1.1  christos 	subql   #1,d0           /* predecrement loop counter    */
    350  1.1  christos #
    351  1.1  christos # copy the frame
    352  1.1  christos saveFrameLoop:
    353  1.1  christos 	movew  	sp@+,a1@+
    354  1.1  christos 	dbf     d0,saveFrameLoop
    355  1.8  christos #
    356  1.1  christos # now that the stack has been cleaned,
    357  1.7  christos # save the a7 in use at time of exception
    358  1.7  christos 	movel   sp,_superStack  /* save supervisor sp           */
    359  1.7  christos 	andiw   #0x2000,d1      /* were we in supervisor mode ? */
    360  1.7  christos 	beq     userMode
    361  1.7  christos 	movel   a7,a5@(60)      /* save a7                  */
    362  1.1  christos 	bra     a7saveDone
    363  1.1  christos userMode:
    364  1.7  christos 	movel   usp,a1
    365  1.1  christos 	movel   a1,a5@(60)      /* save user stack pointer	*/
    366  1.1  christos a7saveDone:
    367  1.1  christos 
    368  1.1  christos #
    369  1.7  christos # save size of frame
    370  1.1  christos 	movew   d3,a0@-
    371  1.1  christos 
    372  1.1  christos #
    373  1.1  christos # compute exception number
    374  1.1  christos 	andl    #0xfff,d2   	/* mask off vector offset	*/
    375  1.7  christos 	lsrw    #2,d2   	/* divide by 4 to get vect num	*/
    376  1.1  christos 	movel   d2,a0@-         /* save it                      */
    377  1.1  christos #
    378  1.7  christos # save pc causing exception
    379  1.1  christos 	movel   a4,a0@-
    380  1.1  christos #
    381  1.1  christos # save old frame link and set the new value
    382  1.1  christos 	movel	_lastFrame,a1	/* last frame pointer */
    383  1.7  christos 	movel   a1,a0@-		/* save pointer to prev frame	*/
    384  1.1  christos 	movel   a0,_lastFrame
    385  1.7  christos 
    386  1.1  christos 	movel   d2,sp@-		/* push exception num           */
    387  1.7  christos 	movel   _exceptionHook,a0  /* get address of handler */
    388  1.7  christos 	jbsr    a0@             /* and call it */
    389  1.7  christos 	clrl    sp@             /* replace exception num parm with frame ptr */
    390  1.1  christos 	jbsr     __returnFromException   /* jbsr, but never returns */
    391  1.1  christos ");
    392  1.1  christos #else /* mc68000 */
    393  1.1  christos /* This function is called when an exception occurs.  It translates the
    394  1.1  christos  * return address found on the stack into an exception vector # which
    395  1.1  christos  * is then handled by either handle_exception or a system handler.
    396  1.1  christos  * _catchException provides a front end for both.
    397  1.1  christos  *
    398  1.1  christos  * stack on entry:                       stack on exit:
    399  1.1  christos  *   Program counter MSWord              exception # MSWord
    400  1.1  christos  *   Program counter LSWord              exception # MSWord
    401  1.1  christos  *   Status Register
    402  1.1  christos  *   Return Address  MSWord
    403  1.1  christos  *   Return Address  LSWord
    404  1.1  christos  */
    405  1.1  christos asm("
    406  1.1  christos .text
    407  1.1  christos .globl __catchException
    408  1.1  christos __catchException:");
    409  1.1  christos DISABLE_INTERRUPTS();
    410  1.7  christos asm("
    411  1.1  christos 	moveml d0-d7/a0-a6,_registers  /* save registers               */
    412  1.1  christos 	movel	_lastFrame,a0	/* last frame pointer */
    413  1.1  christos ");
    414  1.1  christos SAVE_FP_REGS();
    415  1.7  christos asm("
    416  1.7  christos 	lea     _registers,a5   /* get address of registers     */
    417  1.1  christos 	movel   sp@+,d2         /* pop return address           */
    418  1.1  christos 	addl 	#1530,d2        /* convert return addr to 	*/
    419  1.1  christos 	divs 	#6,d2   	/*  exception number		*/
    420  1.1  christos 	extl    d2
    421  1.7  christos 
    422  1.1  christos 	moveql  #3,d3           /* assume a three word frame     */
    423  1.7  christos 
    424  1.7  christos 	cmpiw   #3,d2           /* bus error or address error ? */
    425  1.7  christos 	bgt     normal          /* if >3 then normal error      */
    426  1.7  christos 	movel   sp@+,a0@-       /* copy error info to frame buff*/
    427  1.7  christos 	movel   sp@+,a0@-       /* these are never used         */
    428  1.1  christos 	moveql  #7,d3           /* this is a 7 word frame       */
    429  1.1  christos 
    430  1.1  christos normal:
    431  1.7  christos 	movew   sp@+,d1         /* pop status register          */
    432  1.7  christos 	movel   sp@+,a4         /* pop program counter          */
    433  1.7  christos 	movew   d1,a5@(66)      /* save sr		 	*/
    434  1.7  christos 	movel   a4,a5@(68)      /* save pc in _regisers[]      	*/
    435  1.1  christos 	movel   a4,a0@-         /* copy pc to frame buffer      */
    436  1.1  christos 	movew   d1,a0@-         /* copy sr to frame buffer      */
    437  1.7  christos 
    438  1.1  christos 	movel   sp,_superStack  /* save supervisor sp          */
    439  1.7  christos 
    440  1.7  christos 	andiw   #0x2000,d1      /* were we in supervisor mode ? */
    441  1.7  christos 	beq     userMode
    442  1.7  christos 	movel   a7,a5@(60)      /* save a7                  */
    443  1.1  christos 	bra     saveDone
    444  1.7  christos userMode:
    445  1.7  christos 	movel   usp,a1    	/* save user stack pointer 	*/
    446  1.1  christos 	movel   a1,a5@(60)      /* save user stack pointer	*/
    447  1.1  christos saveDone:
    448  1.7  christos 
    449  1.7  christos 	movew   d3,a0@-         /* push frame size in words     */
    450  1.7  christos 	movel   d2,a0@-         /* push vector number           */
    451  1.1  christos 	movel   a4,a0@-         /* push exception pc            */
    452  1.1  christos 
    453  1.1  christos #
    454  1.1  christos # save old frame link and set the new value
    455  1.1  christos 	movel	_lastFrame,a1	/* last frame pointer */
    456  1.7  christos 	movel   a1,a0@-		/* save pointer to prev frame	*/
    457  1.1  christos 	movel   a0,_lastFrame
    458  1.7  christos 
    459  1.1  christos 	movel   d2,sp@-		/* push exception num           */
    460  1.7  christos 	movel   _exceptionHook,a0  /* get address of handler */
    461  1.7  christos 	jbsr    a0@             /* and call it */
    462  1.7  christos 	clrl    sp@             /* replace exception num parm with frame ptr */
    463  1.1  christos 	jbsr     __returnFromException   /* jbsr, but never returns */
    464  1.1  christos ");
    465  1.1  christos #endif
    466  1.1  christos 
    467  1.1  christos 
    468  1.1  christos /*
    469  1.1  christos  * remcomHandler is a front end for handle_exception.  It moves the
    470  1.1  christos  * stack pointer into an area reserved for debugger use in case the
    471  1.1  christos  * breakpoint happened in supervisor mode.
    472  1.1  christos  */
    473  1.1  christos asm("_remcomHandler:");
    474  1.1  christos asm("           addl    #4,sp");        /* pop off return address     */
    475  1.1  christos asm("           movel   sp@+,d0");      /* get the exception number   */
    476  1.1  christos asm("		movel   _stackPtr,sp"); /* move to remcom stack area  */
    477  1.1  christos asm("		movel   d0,sp@-");	/* push exception onto stack  */
    478  1.1  christos asm("		jbsr    _handle_exception");    /* this never returns */
    479  1.1  christos asm("           rts");                  /* return */
    480  1.1  christos 
    481  1.1  christos void
    482  1.1  christos _returnFromException (Frame * frame)
    483  1.1  christos {
    484  1.1  christos   /* if no passed in frame, use the last one */
    485  1.1  christos   if (!frame)
    486  1.1  christos     {
    487  1.1  christos       frame = lastFrame;
    488  1.1  christos       frame->frameSize = 4;
    489  1.1  christos       frame->format = 0;
    490  1.1  christos       frame->fsaveHeader = -1;	/* restore regs, but we dont have fsave info */
    491  1.1  christos     }
    492  1.1  christos 
    493  1.1  christos #if !defined (mc68020) && !defined (mc68332)
    494  1.1  christos   /* a 68000 cannot use the internal info pushed onto a bus error
    495  1.1  christos    * or address error frame when doing an RTE so don't put this info
    496  1.1  christos    * onto the stack or the stack will creep every time this happens.
    497  1.1  christos    */
    498  1.1  christos   frame->frameSize = 3;
    499  1.1  christos #endif
    500  1.1  christos 
    501  1.1  christos   /* throw away any frames in the list after this frame */
    502  1.1  christos   lastFrame = frame;
    503  1.1  christos 
    504  1.1  christos   frame->sr = registers[(int) PS];
    505  1.1  christos   frame->pc = registers[(int) PC];
    506  1.1  christos 
    507  1.1  christos   if (registers[(int) PS] & 0x2000)
    508  1.1  christos     {
    509  1.1  christos       /* return to supervisor mode... */
    510  1.1  christos       return_to_super ();
    511  1.1  christos     }
    512  1.1  christos   else
    513  1.1  christos     {				/* return to user mode */
    514  1.1  christos       return_to_user ();
    515  1.1  christos     }
    516  1.1  christos }
    517  1.1  christos 
    518  1.1  christos int
    519  1.1  christos hex (ch)
    520  1.1  christos      char ch;
    521  1.1  christos {
    522  1.1  christos   if ((ch >= 'a') && (ch <= 'f'))
    523  1.1  christos     return (ch - 'a' + 10);
    524  1.1  christos   if ((ch >= '0') && (ch <= '9'))
    525  1.1  christos     return (ch - '0');
    526  1.1  christos   if ((ch >= 'A') && (ch <= 'F'))
    527  1.1  christos     return (ch - 'A' + 10);
    528  1.1  christos   return (-1);
    529  1.1  christos }
    530  1.1  christos 
    531  1.1  christos static char remcomInBuffer[BUFMAX];
    532  1.1  christos static char remcomOutBuffer[BUFMAX];
    533  1.1  christos 
    534  1.1  christos /* scan for the sequence $<data>#<checksum>     */
    535  1.1  christos 
    536  1.1  christos unsigned char *
    537  1.1  christos getpacket (void)
    538  1.1  christos {
    539  1.1  christos   unsigned char *buffer = &remcomInBuffer[0];
    540  1.1  christos   unsigned char checksum;
    541  1.1  christos   unsigned char xmitcsum;
    542  1.1  christos   int count;
    543  1.1  christos   char ch;
    544  1.1  christos 
    545  1.1  christos   while (1)
    546  1.1  christos     {
    547  1.1  christos       /* wait around for the start character, ignore all other characters */
    548  1.1  christos       while ((ch = getDebugChar ()) != '$')
    549  1.1  christos 	;
    550  1.1  christos 
    551  1.1  christos     retry:
    552  1.1  christos       checksum = 0;
    553  1.1  christos       xmitcsum = -1;
    554  1.1  christos       count = 0;
    555  1.1  christos 
    556  1.1  christos       /* now, read until a # or end of buffer is found */
    557  1.1  christos       while (count < BUFMAX - 1)
    558  1.1  christos 	{
    559  1.1  christos 	  ch = getDebugChar ();
    560  1.1  christos 	  if (ch == '$')
    561  1.1  christos 	    goto retry;
    562  1.1  christos 	  if (ch == '#')
    563  1.1  christos 	    break;
    564  1.1  christos 	  checksum = checksum + ch;
    565  1.1  christos 	  buffer[count] = ch;
    566  1.1  christos 	  count = count + 1;
    567  1.1  christos 	}
    568  1.1  christos       buffer[count] = 0;
    569  1.1  christos 
    570  1.1  christos       if (ch == '#')
    571  1.1  christos 	{
    572  1.1  christos 	  ch = getDebugChar ();
    573  1.1  christos 	  xmitcsum = hex (ch) << 4;
    574  1.1  christos 	  ch = getDebugChar ();
    575  1.1  christos 	  xmitcsum += hex (ch);
    576  1.1  christos 
    577  1.1  christos 	  if (checksum != xmitcsum)
    578  1.1  christos 	    {
    579  1.1  christos 	      if (remote_debug)
    580  1.1  christos 		{
    581  1.1  christos 		  fprintf (stderr,
    582  1.1  christos 			   "bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",
    583  1.1  christos 			   checksum, xmitcsum, buffer);
    584  1.1  christos 		}
    585  1.1  christos 	      putDebugChar ('-');	/* failed checksum */
    586  1.1  christos 	    }
    587  1.1  christos 	  else
    588  1.1  christos 	    {
    589  1.1  christos 	      putDebugChar ('+');	/* successful transfer */
    590  1.1  christos 
    591  1.1  christos 	      /* if a sequence char is present, reply the sequence ID */
    592  1.1  christos 	      if (buffer[2] == ':')
    593  1.1  christos 		{
    594  1.1  christos 		  putDebugChar (buffer[0]);
    595  1.1  christos 		  putDebugChar (buffer[1]);
    596  1.1  christos 
    597  1.1  christos 		  return &buffer[3];
    598  1.1  christos 		}
    599  1.1  christos 
    600  1.1  christos 	      return &buffer[0];
    601  1.1  christos 	    }
    602  1.1  christos 	}
    603  1.1  christos     }
    604  1.1  christos }
    605  1.1  christos 
    606  1.1  christos /* send the packet in buffer. */
    607  1.1  christos 
    608  1.1  christos void
    609  1.1  christos putpacket (buffer)
    610  1.1  christos      char *buffer;
    611  1.1  christos {
    612  1.1  christos   unsigned char checksum;
    613  1.1  christos   int count;
    614  1.1  christos   char ch;
    615  1.1  christos 
    616  1.1  christos   /*  $<packet info>#<checksum>. */
    617  1.1  christos   do
    618  1.1  christos     {
    619  1.1  christos       putDebugChar ('$');
    620  1.1  christos       checksum = 0;
    621  1.1  christos       count = 0;
    622  1.1  christos 
    623  1.1  christos       while (ch = buffer[count])
    624  1.1  christos 	{
    625  1.1  christos 	  putDebugChar (ch);
    626  1.1  christos 	  checksum += ch;
    627  1.1  christos 	  count += 1;
    628  1.1  christos 	}
    629  1.1  christos 
    630  1.1  christos       putDebugChar ('#');
    631  1.1  christos       putDebugChar (hexchars[checksum >> 4]);
    632  1.1  christos       putDebugChar (hexchars[checksum % 16]);
    633  1.1  christos 
    634  1.1  christos     }
    635  1.1  christos   while (getDebugChar () != '+');
    636  1.1  christos 
    637  1.1  christos }
    638  1.1  christos 
    639  1.1  christos void
    640  1.1  christos debug_error (format, parm)
    641  1.1  christos      char *format;
    642  1.1  christos      char *parm;
    643  1.1  christos {
    644  1.1  christos   if (remote_debug)
    645  1.1  christos     fprintf (stderr, format, parm);
    646  1.1  christos }
    647  1.1  christos 
    648  1.1  christos /* convert the memory pointed to by mem into hex, placing result in buf */
    649  1.1  christos /* return a pointer to the last char put in buf (null) */
    650  1.1  christos char *
    651  1.1  christos mem2hex (mem, buf, count)
    652  1.1  christos      char *mem;
    653  1.1  christos      char *buf;
    654  1.1  christos      int count;
    655  1.1  christos {
    656  1.1  christos   int i;
    657  1.1  christos   unsigned char ch;
    658  1.1  christos   for (i = 0; i < count; i++)
    659  1.1  christos     {
    660  1.1  christos       ch = *mem++;
    661  1.1  christos       *buf++ = hexchars[ch >> 4];
    662  1.1  christos       *buf++ = hexchars[ch % 16];
    663  1.1  christos     }
    664  1.1  christos   *buf = 0;
    665  1.1  christos   return (buf);
    666  1.1  christos }
    667  1.1  christos 
    668  1.1  christos /* convert the hex array pointed to by buf into binary to be placed in mem */
    669  1.1  christos /* return a pointer to the character AFTER the last byte written */
    670  1.1  christos char *
    671  1.1  christos hex2mem (buf, mem, count)
    672  1.1  christos      char *buf;
    673  1.1  christos      char *mem;
    674  1.1  christos      int count;
    675  1.1  christos {
    676  1.1  christos   int i;
    677  1.1  christos   unsigned char ch;
    678  1.1  christos   for (i = 0; i < count; i++)
    679  1.1  christos     {
    680  1.1  christos       ch = hex (*buf++) << 4;
    681  1.1  christos       ch = ch + hex (*buf++);
    682  1.1  christos       *mem++ = ch;
    683  1.1  christos     }
    684  1.1  christos   return (mem);
    685  1.1  christos }
    686  1.1  christos 
    687  1.1  christos /* a bus error has occurred, perform a longjmp
    688  1.1  christos    to return execution and allow handling of the error */
    689  1.1  christos 
    690  1.1  christos void
    691  1.1  christos handle_buserror ()
    692  1.1  christos {
    693  1.1  christos   longjmp (remcomEnv, 1);
    694  1.1  christos }
    695  1.1  christos 
    696  1.1  christos /* this function takes the 68000 exception number and attempts to
    697  1.1  christos    translate this number into a unix compatible signal value */
    698  1.1  christos int
    699  1.1  christos computeSignal (exceptionVector)
    700  1.1  christos      int exceptionVector;
    701  1.1  christos {
    702  1.1  christos   int sigval;
    703  1.1  christos   switch (exceptionVector)
    704  1.1  christos     {
    705  1.1  christos     case 2:
    706  1.1  christos       sigval = 10;
    707  1.1  christos       break;			/* bus error           */
    708  1.1  christos     case 3:
    709  1.1  christos       sigval = 10;
    710  1.1  christos       break;			/* address error       */
    711  1.1  christos     case 4:
    712  1.1  christos       sigval = 4;
    713  1.1  christos       break;			/* illegal instruction */
    714  1.1  christos     case 5:
    715  1.1  christos       sigval = 8;
    716  1.1  christos       break;			/* zero divide         */
    717  1.1  christos     case 6:
    718  1.1  christos       sigval = 8;
    719  1.1  christos       break;			/* chk instruction     */
    720  1.1  christos     case 7:
    721  1.1  christos       sigval = 8;
    722  1.1  christos       break;			/* trapv instruction   */
    723  1.1  christos     case 8:
    724  1.1  christos       sigval = 11;
    725  1.1  christos       break;			/* privilege violation */
    726  1.1  christos     case 9:
    727  1.1  christos       sigval = 5;
    728  1.1  christos       break;			/* trace trap          */
    729  1.1  christos     case 10:
    730  1.1  christos       sigval = 4;
    731  1.1  christos       break;			/* line 1010 emulator  */
    732  1.1  christos     case 11:
    733  1.1  christos       sigval = 4;
    734  1.1  christos       break;			/* line 1111 emulator  */
    735  1.1  christos 
    736  1.7  christos       /* Coprocessor protocol violation.  Using a standard MMU or FPU
    737  1.1  christos 	 this cannot be triggered by software.  Call it a SIGBUS.  */
    738  1.1  christos     case 13:
    739  1.1  christos       sigval = 10;
    740  1.1  christos       break;
    741  1.1  christos 
    742  1.1  christos     case 31:
    743  1.1  christos       sigval = 2;
    744  1.1  christos       break;			/* interrupt           */
    745  1.1  christos     case 33:
    746  1.1  christos       sigval = 5;
    747  1.1  christos       break;			/* breakpoint          */
    748  1.1  christos 
    749  1.7  christos       /* This is a trap #8 instruction.  Apparently it is someone's software
    750  1.7  christos 	 convention for some sort of SIGFPE condition.  Whose?  How many
    751  1.7  christos 	 people are being screwed by having this code the way it is?
    752  1.1  christos 	 Is there a clean solution?  */
    753  1.1  christos     case 40:
    754  1.1  christos       sigval = 8;
    755  1.1  christos       break;			/* floating point err  */
    756  1.1  christos 
    757  1.1  christos     case 48:
    758  1.1  christos       sigval = 8;
    759  1.1  christos       break;			/* floating point err  */
    760  1.1  christos     case 49:
    761  1.1  christos       sigval = 8;
    762  1.1  christos       break;			/* floating point err  */
    763  1.1  christos     case 50:
    764  1.1  christos       sigval = 8;
    765  1.1  christos       break;			/* zero divide         */
    766  1.1  christos     case 51:
    767  1.1  christos       sigval = 8;
    768  1.1  christos       break;			/* underflow           */
    769  1.1  christos     case 52:
    770  1.1  christos       sigval = 8;
    771  1.1  christos       break;			/* operand error       */
    772  1.1  christos     case 53:
    773  1.1  christos       sigval = 8;
    774  1.1  christos       break;			/* overflow            */
    775  1.1  christos     case 54:
    776  1.1  christos       sigval = 8;
    777  1.1  christos       break;			/* NAN                 */
    778  1.1  christos     default:
    779  1.1  christos       sigval = 7;		/* "software generated" */
    780  1.1  christos     }
    781  1.1  christos   return (sigval);
    782  1.1  christos }
    783  1.1  christos 
    784  1.1  christos /**********************************************/
    785  1.1  christos /* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
    786  1.1  christos /* RETURN NUMBER OF CHARS PROCESSED           */
    787  1.1  christos /**********************************************/
    788  1.1  christos int
    789  1.1  christos hexToInt (char **ptr, int *intValue)
    790  1.1  christos {
    791  1.1  christos   int numChars = 0;
    792  1.1  christos   int hexValue;
    793  1.1  christos 
    794  1.1  christos   *intValue = 0;
    795  1.1  christos 
    796  1.1  christos   while (**ptr)
    797  1.1  christos     {
    798  1.1  christos       hexValue = hex (**ptr);
    799  1.1  christos       if (hexValue >= 0)
    800  1.1  christos 	{
    801  1.1  christos 	  *intValue = (*intValue << 4) | hexValue;
    802  1.1  christos 	  numChars++;
    803  1.1  christos 	}
    804  1.1  christos       else
    805  1.1  christos 	break;
    806  1.1  christos 
    807  1.1  christos       (*ptr)++;
    808  1.1  christos     }
    809  1.1  christos 
    810  1.1  christos   return (numChars);
    811  1.1  christos }
    812  1.1  christos 
    813  1.1  christos /*
    814  1.1  christos  * This function does all command procesing for interfacing to gdb.
    815  1.1  christos  */
    816  1.1  christos void
    817  1.1  christos handle_exception (int exceptionVector)
    818  1.1  christos {
    819  1.1  christos   int sigval, stepping;
    820  1.1  christos   int addr, length;
    821  1.1  christos   char *ptr;
    822  1.1  christos   int newPC;
    823  1.1  christos   Frame *frame;
    824  1.1  christos 
    825  1.1  christos   if (remote_debug)
    826  1.1  christos     printf ("vector=%d, sr=0x%x, pc=0x%x\n",
    827  1.1  christos 	    exceptionVector, registers[PS], registers[PC]);
    828  1.1  christos 
    829  1.1  christos   /* reply to host that an exception has occurred */
    830  1.1  christos   sigval = computeSignal (exceptionVector);
    831  1.1  christos   remcomOutBuffer[0] = 'S';
    832  1.1  christos   remcomOutBuffer[1] = hexchars[sigval >> 4];
    833  1.1  christos   remcomOutBuffer[2] = hexchars[sigval % 16];
    834  1.1  christos   remcomOutBuffer[3] = 0;
    835  1.1  christos 
    836  1.1  christos   putpacket (remcomOutBuffer);
    837  1.1  christos 
    838  1.1  christos   stepping = 0;
    839  1.1  christos 
    840  1.1  christos   while (1 == 1)
    841  1.1  christos     {
    842  1.1  christos       remcomOutBuffer[0] = 0;
    843  1.1  christos       ptr = getpacket ();
    844  1.1  christos       switch (*ptr++)
    845  1.1  christos 	{
    846  1.1  christos 	case '?':
    847  1.1  christos 	  remcomOutBuffer[0] = 'S';
    848  1.1  christos 	  remcomOutBuffer[1] = hexchars[sigval >> 4];
    849  1.1  christos 	  remcomOutBuffer[2] = hexchars[sigval % 16];
    850  1.1  christos 	  remcomOutBuffer[3] = 0;
    851  1.1  christos 	  break;
    852  1.1  christos 	case 'd':
    853  1.1  christos 	  remote_debug = !(remote_debug);	/* toggle debug flag */
    854  1.1  christos 	  break;
    855  1.1  christos 	case 'g':		/* return the value of the CPU registers */
    856  1.1  christos 	  mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES);
    857  1.1  christos 	  break;
    858  1.1  christos 	case 'G':		/* set the value of the CPU registers - return OK */
    859  1.1  christos 	  hex2mem (ptr, (char *) registers, NUMREGBYTES);
    860  1.1  christos 	  strcpy (remcomOutBuffer, "OK");
    861  1.1  christos 	  break;
    862  1.1  christos 
    863  1.1  christos 	  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
    864  1.1  christos 	case 'm':
    865  1.1  christos 	  if (setjmp (remcomEnv) == 0)
    866  1.1  christos 	    {
    867  1.1  christos 	      exceptionHandler (2, handle_buserror);
    868  1.1  christos 
    869  1.1  christos 	      /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
    870  1.1  christos 	      if (hexToInt (&ptr, &addr))
    871  1.1  christos 		if (*(ptr++) == ',')
    872  1.1  christos 		  if (hexToInt (&ptr, &length))
    873  1.1  christos 		    {
    874  1.1  christos 		      ptr = 0;
    875  1.1  christos 		      mem2hex ((char *) addr, remcomOutBuffer, length);
    876  1.1  christos 		    }
    877  1.1  christos 
    878  1.1  christos 	      if (ptr)
    879  1.1  christos 		{
    880  1.1  christos 		  strcpy (remcomOutBuffer, "E01");
    881  1.1  christos 		}
    882  1.1  christos 	    }
    883  1.1  christos 	  else
    884  1.1  christos 	    {
    885  1.1  christos 	      exceptionHandler (2, _catchException);
    886  1.1  christos 	      strcpy (remcomOutBuffer, "E03");
    887  1.1  christos 	      debug_error ("bus error");
    888  1.1  christos 	    }
    889  1.1  christos 
    890  1.1  christos 	  /* restore handler for bus error */
    891  1.1  christos 	  exceptionHandler (2, _catchException);
    892  1.1  christos 	  break;
    893  1.1  christos 
    894  1.1  christos 	  /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
    895  1.1  christos 	case 'M':
    896  1.1  christos 	  if (setjmp (remcomEnv) == 0)
    897  1.1  christos 	    {
    898  1.1  christos 	      exceptionHandler (2, handle_buserror);
    899  1.1  christos 
    900  1.1  christos 	      /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
    901  1.1  christos 	      if (hexToInt (&ptr, &addr))
    902  1.1  christos 		if (*(ptr++) == ',')
    903  1.1  christos 		  if (hexToInt (&ptr, &length))
    904  1.1  christos 		    if (*(ptr++) == ':')
    905  1.1  christos 		      {
    906  1.1  christos 			hex2mem (ptr, (char *) addr, length);
    907  1.1  christos 			ptr = 0;
    908  1.1  christos 			strcpy (remcomOutBuffer, "OK");
    909  1.1  christos 		      }
    910  1.1  christos 	      if (ptr)
    911  1.1  christos 		{
    912  1.1  christos 		  strcpy (remcomOutBuffer, "E02");
    913  1.1  christos 		}
    914  1.1  christos 	    }
    915  1.1  christos 	  else
    916  1.1  christos 	    {
    917  1.1  christos 	      exceptionHandler (2, _catchException);
    918  1.1  christos 	      strcpy (remcomOutBuffer, "E03");
    919  1.1  christos 	      debug_error ("bus error");
    920  1.1  christos 	    }
    921  1.1  christos 
    922  1.1  christos 	  /* restore handler for bus error */
    923  1.1  christos 	  exceptionHandler (2, _catchException);
    924  1.1  christos 	  break;
    925  1.1  christos 
    926  1.1  christos 	  /* cAA..AA    Continue at address AA..AA(optional) */
    927  1.1  christos 	  /* sAA..AA   Step one instruction from AA..AA(optional) */
    928  1.1  christos 	case 's':
    929  1.1  christos 	  stepping = 1;
    930  1.1  christos 	case 'c':
    931  1.1  christos 	  /* try to read optional parameter, pc unchanged if no parm */
    932  1.1  christos 	  if (hexToInt (&ptr, &addr))
    933  1.1  christos 	    registers[PC] = addr;
    934  1.1  christos 
    935  1.1  christos 	  newPC = registers[PC];
    936  1.1  christos 
    937  1.1  christos 	  /* clear the trace bit */
    938  1.1  christos 	  registers[PS] &= 0x7fff;
    939  1.1  christos 
    940  1.1  christos 	  /* set the trace bit if we're stepping */
    941  1.1  christos 	  if (stepping)
    942  1.1  christos 	    registers[PS] |= 0x8000;
    943  1.1  christos 
    944  1.1  christos 	  /*
    945  1.1  christos 	   * look for newPC in the linked list of exception frames.
    946  1.1  christos 	   * if it is found, use the old frame it.  otherwise,
    947  1.1  christos 	   * fake up a dummy frame in returnFromException().
    948  1.1  christos 	   */
    949  1.1  christos 	  if (remote_debug)
    950  1.1  christos 	    printf ("new pc = 0x%x\n", newPC);
    951  1.1  christos 	  frame = lastFrame;
    952  1.1  christos 	  while (frame)
    953  1.1  christos 	    {
    954  1.1  christos 	      if (remote_debug)
    955  1.1  christos 		printf ("frame at 0x%x has pc=0x%x, except#=%d\n",
    956  1.1  christos 			frame, frame->exceptionPC, frame->exceptionVector);
    957  1.1  christos 	      if (frame->exceptionPC == newPC)
    958  1.1  christos 		break;		/* bingo! a match */
    959  1.1  christos 	      /*
    960  1.1  christos 	       * for a breakpoint instruction, the saved pc may
    961  1.1  christos 	       * be off by two due to re-executing the instruction
    962  1.1  christos 	       * replaced by the trap instruction.  Check for this.
    963  1.1  christos 	       */
    964  1.1  christos 	      if ((frame->exceptionVector == 33) &&
    965  1.1  christos 		  (frame->exceptionPC == (newPC + 2)))
    966  1.1  christos 		break;
    967  1.1  christos 	      if (frame == frame->previous)
    968  1.1  christos 		{
    969  1.1  christos 		  frame = 0;	/* no match found */
    970  1.1  christos 		  break;
    971  1.1  christos 		}
    972  1.1  christos 	      frame = frame->previous;
    973  1.1  christos 	    }
    974  1.1  christos 
    975  1.1  christos 	  /*
    976  1.1  christos 	   * If we found a match for the PC AND we are not returning
    977  1.1  christos 	   * as a result of a breakpoint (33),
    978  1.1  christos 	   * trace exception (9), nmi (31), jmp to
    979  1.1  christos 	   * the old exception handler as if this code never ran.
    980  1.1  christos 	   */
    981  1.1  christos 	  if (frame)
    982  1.1  christos 	    {
    983  1.1  christos 	      if ((frame->exceptionVector != 9) &&
    984  1.1  christos 		  (frame->exceptionVector != 31) &&
    985  1.1  christos 		  (frame->exceptionVector != 33))
    986  1.1  christos 		{
    987  1.1  christos 		  /*
    988  1.1  christos 		   * invoke the previous handler.
    989  1.1  christos 		   */
    990  1.1  christos 		  if (oldExceptionHook)
    991  1.1  christos 		    (*oldExceptionHook) (frame->exceptionVector);
    992  1.1  christos 		  newPC = registers[PC];	/* pc may have changed  */
    993  1.1  christos 		  if (newPC != frame->exceptionPC)
    994  1.1  christos 		    {
    995  1.1  christos 		      if (remote_debug)
    996  1.1  christos 			printf ("frame at 0x%x has pc=0x%x, except#=%d\n",
    997  1.1  christos 				frame, frame->exceptionPC,
    998  1.1  christos 				frame->exceptionVector);
    999  1.1  christos 		      /* re-use the last frame, we're skipping it (longjump?) */
   1000  1.1  christos 		      frame = (Frame *) 0;
   1001  1.1  christos 		      _returnFromException (frame);	/* this is a jump */
   1002  1.1  christos 		    }
   1003  1.1  christos 		}
   1004  1.1  christos 	    }
   1005  1.1  christos 
   1006  1.1  christos 	  /* if we couldn't find a frame, create one */
   1007  1.1  christos 	  if (frame == 0)
   1008  1.1  christos 	    {
   1009  1.1  christos 	      frame = lastFrame - 1;
   1010  1.1  christos 
   1011  1.7  christos 	      /* by using a bunch of print commands with breakpoints,
   1012  1.7  christos 		 it's possible for the frame stack to creep down.  If it creeps
   1013  1.7  christos 		 too far, give up and reset it to the top.  Normal use should
   1014  1.1  christos 		 not see this happen.
   1015  1.1  christos 	       */
   1016  1.1  christos 	      if ((unsigned int) (frame - 2) < (unsigned int) &gdbFrameStack)
   1017  1.1  christos 		{
   1018  1.1  christos 		  initializeRemcomErrorFrame ();
   1019  1.1  christos 		  frame = lastFrame;
   1020  1.1  christos 		}
   1021  1.1  christos 	      frame->previous = lastFrame;
   1022  1.1  christos 	      lastFrame = frame;
   1023  1.1  christos 	      frame = 0;	/* null so _return... will properly initialize it */
   1024  1.1  christos 	    }
   1025  1.1  christos 
   1026  1.1  christos 	  _returnFromException (frame);	/* this is a jump */
   1027  1.1  christos 
   1028  1.1  christos 	  break;
   1029  1.1  christos 
   1030  1.1  christos 	  /* kill the program */
   1031  1.1  christos 	case 'k':		/* do nothing */
   1032  1.1  christos 	  break;
   1033  1.1  christos 	}			/* switch */
   1034  1.1  christos 
   1035  1.1  christos       /* reply to the request */
   1036  1.1  christos       putpacket (remcomOutBuffer);
   1037  1.1  christos     }
   1038  1.1  christos }
   1039  1.1  christos 
   1040  1.1  christos 
   1041  1.1  christos void
   1042  1.1  christos initializeRemcomErrorFrame (void)
   1043  1.1  christos {
   1044  1.1  christos   lastFrame = ((Frame *) & gdbFrameStack[FRAMESIZE - 1]) - 1;
   1045  1.1  christos   lastFrame->previous = lastFrame;
   1046  1.1  christos }
   1047  1.1  christos 
   1048  1.1  christos /* this function is used to set up exception handlers for tracing and
   1049  1.1  christos    breakpoints */
   1050  1.1  christos void
   1051  1.1  christos set_debug_traps ()
   1052  1.1  christos {
   1053  1.1  christos   extern void _debug_level7 ();
   1054  1.1  christos   extern void remcomHandler ();
   1055  1.1  christos   int exception;
   1056  1.1  christos 
   1057  1.1  christos   initializeRemcomErrorFrame ();
   1058  1.1  christos   stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1];
   1059  1.1  christos 
   1060  1.1  christos   for (exception = 2; exception <= 23; exception++)
   1061  1.1  christos     exceptionHandler (exception, _catchException);
   1062  1.1  christos 
   1063  1.1  christos   /* level 7 interrupt              */
   1064  1.1  christos   exceptionHandler (31, _debug_level7);
   1065  1.1  christos 
   1066  1.1  christos   /* breakpoint exception (trap #1) */
   1067  1.1  christos   exceptionHandler (33, _catchException);
   1068  1.1  christos 
   1069  1.1  christos   /* This is a trap #8 instruction.  Apparently it is someone's software
   1070  1.1  christos      convention for some sort of SIGFPE condition.  Whose?  How many
   1071  1.1  christos      people are being screwed by having this code the way it is?
   1072  1.1  christos      Is there a clean solution?  */
   1073  1.1  christos   exceptionHandler (40, _catchException);
   1074  1.1  christos 
   1075  1.1  christos   /* 48 to 54 are floating point coprocessor errors */
   1076  1.1  christos   for (exception = 48; exception <= 54; exception++)
   1077  1.1  christos     exceptionHandler (exception, _catchException);
   1078  1.1  christos 
   1079  1.1  christos   if (oldExceptionHook != remcomHandler)
   1080  1.1  christos     {
   1081  1.1  christos       oldExceptionHook = exceptionHook;
   1082  1.1  christos       exceptionHook = remcomHandler;
   1083  1.1  christos     }
   1084  1.1  christos 
   1085  1.1  christos   initialized = 1;
   1086  1.1  christos 
   1087  1.1  christos }
   1088  1.1  christos 
   1089  1.1  christos /* This function will generate a breakpoint exception.  It is used at the
   1090  1.1  christos    beginning of a program to sync up with a debugger and can be used
   1091  1.1  christos    otherwise as a quick means to stop program execution and "break" into
   1092  1.1  christos    the debugger. */
   1093  1.1  christos 
   1094  1.1  christos void
   1095  1.1  christos breakpoint ()
   1096  1.1  christos {
   1097  1.1  christos   if (initialized)
   1098  1.1  christos     BREAKPOINT ();
   1099                }
   1100