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