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