1999-01-31 J.T. Conklin <jtc@redbacknetworks.com>
[external/binutils.git] / gdb / m32r-stub.c
1 /****************************************************************************
2
3                 THIS SOFTWARE IS NOT COPYRIGHTED
4
5    HP offers the following for use in the public domain.  HP makes no
6    warranty with regard to the software or it's performance and the
7    user accepts the software "AS IS" with all faults.
8
9    HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
10    TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
11    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12
13 ****************************************************************************/
14
15 /****************************************************************************
16  *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
17  *
18  *  Module name: remcom.c $
19  *  Revision: 1.34 $
20  *  Date: 91/03/09 12:29:49 $
21  *  Contributor:     Lake Stevens Instrument Division$
22  *
23  *  Description:     low level support for gdb debugger. $
24  *
25  *  Considerations:  only works on target hardware $
26  *
27  *  Written by:      Glenn Engel $
28  *  ModuleState:     Experimental $
29  *
30  *  NOTES:           See Below $
31  *
32  *  Modified for M32R by Michael Snyder, Cygnus Support.
33  *
34  *  To enable debugger support, two things need to happen.  One, a
35  *  call to set_debug_traps() is necessary in order to allow any breakpoints
36  *  or error conditions to be properly intercepted and reported to gdb.
37  *  Two, a breakpoint needs to be generated to begin communication.  This
38  *  is most easily accomplished by a call to breakpoint().  Breakpoint()
39  *  simulates a breakpoint by executing a trap #1.
40  *
41  *  The external function exceptionHandler() is
42  *  used to attach a specific handler to a specific M32R vector number.
43  *  It should use the same privilege level it runs at.  It should
44  *  install it as an interrupt gate so that interrupts are masked
45  *  while the handler runs.
46  *
47  *  Because gdb will sometimes write to the stack area to execute function
48  *  calls, this program cannot rely on using the supervisor stack so it
49  *  uses it's own stack area reserved in the int array remcomStack.
50  *
51  *************
52  *
53  *    The following gdb commands are supported:
54  *
55  * command          function                               Return value
56  *
57  *    g             return the value of the CPU registers  hex data or ENN
58  *    G             set the value of the CPU registers     OK or ENN
59  *
60  *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
61  *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
62  *
63  *    c             Resume at current address              SNN   ( signal NN)
64  *    cAA..AA       Continue at address AA..AA             SNN
65  *
66  *    s             Step one instruction                   SNN
67  *    sAA..AA       Step one instruction from AA..AA       SNN
68  *
69  *    k             kill
70  *
71  *    ?             What was the last sigval ?             SNN   (signal NN)
72  *
73  * All commands and responses are sent with a packet which includes a
74  * checksum.  A packet consists of
75  *
76  * $<packet info>#<checksum>.
77  *
78  * where
79  * <packet info> :: <characters representing the command or response>
80  * <checksum>    :: <two hex digits computed as modulo 256 sum of <packetinfo>>
81  *
82  * When a packet is received, it is first acknowledged with either '+' or '-'.
83  * '+' indicates a successful transfer.  '-' indicates a failed transfer.
84  *
85  * Example:
86  *
87  * Host:                  Reply:
88  * $m0,10#2a               +$00010203040506070809101112131415#42
89  *
90  ****************************************************************************/
91
92
93 /************************************************************************
94  *
95  * external low-level support routines
96  */
97 extern void putDebugChar();     /* write a single character      */
98 extern int getDebugChar();      /* read and return a single char */
99 extern void exceptionHandler(); /* assign an exception handler   */
100
101 /*****************************************************************************
102  * BUFMAX defines the maximum number of characters in inbound/outbound buffers
103  * at least NUMREGBYTES*2 are needed for register packets 
104  */
105 #define BUFMAX 400
106
107 static char initialized;  /* boolean flag. != 0 means we've been initialized */
108
109 int     remote_debug;
110 /*  debug >  0 prints ill-formed commands in valid packets & checksum errors */
111
112 static const char hexchars[]="0123456789abcdef";
113
114 #define NUMREGS 24
115
116 /* Number of bytes of registers.  */
117 #define NUMREGBYTES (NUMREGS * 4)
118 enum regnames { R0,  R1,  R2,  R3,  R4,  R5,  R6,   R7,
119                 R8,  R9,  R10, R11, R12, R13, R14,  R15,
120                 PSW, CBR, SPI, SPU, BPC, PC,  ACCL, ACCH };
121
122 enum SYS_calls {
123         SYS_null, 
124         SYS_exit,
125         SYS_open,
126         SYS_close,
127         SYS_read,
128         SYS_write,
129         SYS_lseek,
130         SYS_unlink,
131         SYS_getpid,
132         SYS_kill,
133         SYS_fstat,
134         SYS_sbrk,
135         SYS_fork,
136         SYS_execve,
137         SYS_wait4,
138         SYS_link,
139         SYS_chdir,
140         SYS_stat,
141         SYS_utime,
142         SYS_chown,
143         SYS_chmod,
144         SYS_time,
145         SYS_pipe };
146
147 static int registers[NUMREGS];
148
149 #define STACKSIZE 8096
150 static char remcomInBuffer[BUFMAX];
151 static char remcomOutBuffer[BUFMAX];
152 static int  remcomStack[STACKSIZE/sizeof(int)];
153 static int*  stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
154
155 static unsigned int save_vectors[18];   /* previous exception vectors */
156
157 /* Indicate to caller of mem2hex or hex2mem that there has been an error. */
158 static volatile int mem_err = 0;
159
160 /* Store the vector number here (since GDB only gets the signal
161    number through the usual means, and that's not very specific).  */
162 int gdb_m32r_vector = -1;
163
164 #if 0
165 #include "syscall.h" /* for SYS_exit, SYS_write etc. */
166 #endif
167
168 /* Global entry points:
169  */
170
171 extern void handle_exception(int);
172 extern void set_debug_traps(void);
173 extern void breakpoint(void);
174
175 /* Local functions:
176  */
177
178 static int  computeSignal(int);
179 static void putpacket(char *);
180 static void getpacket(char *);
181 static char *mem2hex(char *, char *, int, int);
182 static char *hex2mem(char *, char *, int, int);
183 static int  hexToInt(char **, int *);
184 static void stash_registers(void);
185 static void restore_registers(void);
186 static int  prepare_to_step(int);
187 static int  finish_from_step(void);
188
189 static void gdb_error(char *, char *);
190 static int  gdb_putchar(int), gdb_puts(char *), gdb_write(char *, int);
191
192 static char *strcpy (char *, const char *);
193 static int   strlen (const char *);
194
195 /*
196  * This function does all command procesing for interfacing to gdb.
197  */
198
199 void 
200 handle_exception(int exceptionVector)
201 {
202   int    sigval;
203   int    addr, length, i;
204   char * ptr;
205   char   buf[16];
206
207   if (!finish_from_step())
208     return;             /* "false step": let the target continue */
209
210   gdb_m32r_vector = exceptionVector;
211
212   if (remote_debug)
213     {
214       mem2hex((char *) &exceptionVector, buf, 4, 0);
215       gdb_error("Handle exception %s, ", buf);
216       mem2hex((char *) &registers[PC], buf, 4, 0);
217       gdb_error("PC == 0x%s\n", buf);
218     }
219
220   /* reply to host that an exception has occurred */
221   sigval = computeSignal( exceptionVector );
222
223   ptr = remcomOutBuffer;
224  
225   *ptr++ = 'T';         /* notify gdb with signo, PC, FP and SP */
226   *ptr++ = hexchars[sigval >> 4];
227   *ptr++ = hexchars[sigval & 0xf];
228  
229   *ptr++ = hexchars[PC >> 4];
230   *ptr++ = hexchars[PC & 0xf];
231   *ptr++ = ':';
232   ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);     /* PC */
233   *ptr++ = ';';
234  
235   *ptr++ = hexchars[R13 >> 4];
236   *ptr++ = hexchars[R13 & 0xf];
237   *ptr++ = ':';
238   ptr = mem2hex((char *)&registers[R13], ptr, 4, 0);    /* FP */
239   *ptr++ = ';';
240  
241   *ptr++ = hexchars[R15 >> 4];
242   *ptr++ = hexchars[R15 & 0xf];
243   *ptr++ = ':';
244   ptr = mem2hex((char *)&registers[R15], ptr, 4, 0);    /* SP */
245   *ptr++ = ';';
246   *ptr++ = 0;
247  
248   if (exceptionVector == 0)     /* simulated SYS call stuff */
249     {
250       mem2hex((char *) &registers[PC], buf, 4, 0);
251       switch (registers[R0]) {
252       case SYS_exit:
253         gdb_error("Target program has exited at %s\n", buf);
254         ptr = remcomOutBuffer;
255         *ptr++ = 'W';
256         sigval = registers[R1] & 0xff;
257         *ptr++ = hexchars[sigval >> 4];
258         *ptr++ = hexchars[sigval & 0xf];
259         *ptr++ = 0;
260         break;
261       case SYS_open:
262         gdb_error("Target attempts SYS_open call at %s\n", buf);
263         break;
264       case SYS_close:
265         gdb_error("Target attempts SYS_close call at %s\n", buf);
266         break;
267       case SYS_read:
268         gdb_error("Target attempts SYS_read call at %s\n", buf);
269         break;
270       case SYS_write:
271         if (registers[R1] == 1 ||       /* write to stdout  */
272             registers[R1] == 2)         /* write to stderr  */
273           {                             /* (we can do that) */
274             registers[R0] = gdb_write((void *) registers[R2], registers[R3]);
275             return;
276           }
277         else
278           gdb_error("Target attempts SYS_write call at %s\n", buf);
279         break;
280       case SYS_lseek:
281         gdb_error("Target attempts SYS_lseek call at %s\n", buf);
282         break;
283       case SYS_unlink:
284         gdb_error("Target attempts SYS_unlink call at %s\n", buf);
285         break;
286       case SYS_getpid:
287         gdb_error("Target attempts SYS_getpid call at %s\n", buf);
288         break;
289       case SYS_kill:
290         gdb_error("Target attempts SYS_kill call at %s\n", buf);
291         break;
292       case SYS_fstat:
293         gdb_error("Target attempts SYS_fstat call at %s\n", buf);
294         break;
295       default:
296         gdb_error("Target attempts unknown SYS call at %s\n", buf);
297         break;
298       }
299     }
300
301   putpacket(remcomOutBuffer);
302
303   while (1==1) {
304     remcomOutBuffer[0] = 0;
305     getpacket(remcomInBuffer);
306     switch (remcomInBuffer[0]) {
307       default:  /* Unknown code.  Return an empty reply message. */
308         break;
309       case 'R':
310         ptr = &remcomInBuffer[1];
311         if (hexToInt (&ptr, &addr))
312           registers[PC] = addr;
313         strcpy(remcomOutBuffer, "OK");
314         break;
315       case '!':
316         strcpy(remcomOutBuffer, "OK");
317         break;
318       case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
319                 /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
320         ptr = &remcomInBuffer[1];
321         if (hexToInt(&ptr,&addr))
322           if (*(ptr++) == ',')
323             if (hexToInt(&ptr,&length))
324               if (*(ptr++) == ':')
325                 {
326                   mem_err = 0;
327                   hex2mem(ptr, (char*) addr, length, 1);
328                   if (mem_err) {
329                     strcpy (remcomOutBuffer, "E03");
330                     gdb_error ("memory fault", "");
331                   } else {
332                     strcpy(remcomOutBuffer,"OK");
333                   }
334                   ptr = 0;
335                 }
336         if (ptr)
337           {
338             strcpy(remcomOutBuffer,"E02");
339             gdb_error("malformed write memory command: %s",
340                         remcomInBuffer);
341           }
342         break;
343       case 'm': /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
344                 /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
345         ptr = &remcomInBuffer[1];
346         if (hexToInt(&ptr,&addr))
347           if (*(ptr++) == ',')
348             if (hexToInt(&ptr,&length))
349               {
350                 ptr = 0;
351                 mem_err = 0;
352                 mem2hex((char*) addr, remcomOutBuffer, length, 1);
353                 if (mem_err) {
354                   strcpy (remcomOutBuffer, "E03");
355                   gdb_error ("memory fault", "");
356                 }
357               }
358         if (ptr)
359           {
360             strcpy(remcomOutBuffer,"E01");
361             gdb_error("malformed read memory command: %s",
362                         remcomInBuffer);
363           }
364         break;
365       case '?': 
366         remcomOutBuffer[0] = 'S';
367         remcomOutBuffer[1] =  hexchars[sigval >> 4];
368         remcomOutBuffer[2] =  hexchars[sigval % 16];
369         remcomOutBuffer[3] = 0;
370         break;
371       case 'd': 
372         remote_debug = !(remote_debug);  /* toggle debug flag */
373         break;
374       case 'g': /* return the value of the CPU registers */
375         mem2hex((char*) registers, remcomOutBuffer, NUMREGBYTES, 0);
376         break;
377       case 'P': /* set the value of a single CPU register - return OK */
378         {
379           int regno;
380
381           ptr = &remcomInBuffer[1];
382           if (hexToInt (&ptr, &regno) && *ptr++ == '=')
383             if (regno >= 0 && regno < NUMREGS)
384               {
385                 int stackmode;
386
387                 hex2mem (ptr, (char *) &registers[regno], 4, 0);
388                 /*
389                  * Since we just changed a single CPU register, let's
390                  * make sure to keep the several stack pointers consistant.
391                  */
392                 stackmode = registers[PSW] & 0x80;
393                 if (regno == R15)       /* stack pointer changed */
394                   {                     /* need to change SPI or SPU */
395                     if (stackmode == 0)
396                       registers[SPI] = registers[R15];
397                     else
398                       registers[SPU] = registers[R15];
399                   }
400                 else if (regno == SPU)  /* "user" stack pointer changed */
401                   {
402                     if (stackmode != 0) /* stack in user mode: copy SP */
403                       registers[R15] = registers[SPU];
404                   }
405                 else if (regno == SPI)  /* "interrupt" stack pointer changed */
406                   {
407                     if (stackmode == 0) /* stack in interrupt mode: copy SP */
408                       registers[R15] = registers[SPI];
409                   }
410                 else if (regno == PSW)  /* stack mode may have changed! */
411                   {                     /* force SP to either SPU or SPI */
412                     if (stackmode == 0) /* stack in user mode */
413                       registers[R15] = registers[SPI];
414                     else                /* stack in interrupt mode */
415                       registers[R15] = registers[SPU];
416                   }
417                 strcpy (remcomOutBuffer, "OK");
418                 break;
419               }
420           strcpy (remcomOutBuffer, "P01");
421           break;
422         }
423       case 'G': /* set the value of the CPU registers - return OK */
424         hex2mem(&remcomInBuffer[1], (char*) registers, NUMREGBYTES, 0);
425         strcpy(remcomOutBuffer,"OK");
426         break;
427       case 's': /* sAA..AA      Step one instruction from AA..AA(optional) */
428       case 'c': /* cAA..AA      Continue from address AA..AA(optional) */
429                 /* try to read optional parameter, pc unchanged if no parm */
430         ptr = &remcomInBuffer[1];
431         if (hexToInt(&ptr,&addr))
432           registers[ PC ] = addr;
433         
434         if (remcomInBuffer[0] == 's')   /* single-stepping */
435           {
436             if (!prepare_to_step(0))    /* set up for single-step */
437               {
438                 /* prepare_to_step has already emulated the target insn:
439                    Send SIGTRAP to gdb, don't resume the target at all.  */
440                 ptr = remcomOutBuffer;
441                 *ptr++ = 'T';           /* Simulate stopping with SIGTRAP */
442                 *ptr++ = '0';
443                 *ptr++ = '5';
444
445                 *ptr++ = hexchars[PC >> 4];     /* send PC */
446                 *ptr++ = hexchars[PC & 0xf];
447                 *ptr++ = ':';
448                 ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
449                 *ptr++ = ';';
450
451                 *ptr++ = hexchars[R13 >> 4];    /* send FP */
452                 *ptr++ = hexchars[R13 & 0xf];
453                 *ptr++ = ':';
454                 ptr = mem2hex((char *)&registers[R13], ptr, 4, 0);
455                 *ptr++ = ';';
456
457                 *ptr++ = hexchars[R15 >> 4];    /* send SP */
458                 *ptr++ = hexchars[R15 & 0xf];
459                 *ptr++ = ':';
460                 ptr = mem2hex((char *)&registers[R15], ptr, 4, 0);
461                 *ptr++ = ';';
462                 *ptr++ = 0;
463
464                 break;  
465               }
466           }
467         else    /* continuing, not single-stepping */
468           {
469             /* OK, about to do a "continue".  First check to see if the 
470                target pc is on an odd boundary (second instruction in the 
471                word).  If so, we must do a single-step first, because 
472                ya can't jump or return back to an odd boundary!  */
473             if ((registers[PC] & 2) != 0)
474               prepare_to_step(1);
475           }
476         return;
477
478       case 'D': /* Detach */
479         /* I am interpreting this to mean, release the board from control 
480            by the remote stub.  To do this, I am restoring the original
481            (or at least previous) exception vectors.
482          */
483         for (i = 0; i < 18; i++)
484           exceptionHandler (i, save_vectors[i]);
485         putpacket ("OK");
486         return;         /* continue the inferior */
487
488       case 'k': /* kill the program */
489         continue;
490       } /* switch */
491
492     /* reply to the request */
493     putpacket(remcomOutBuffer);
494   }
495 }
496
497 static int 
498 hex(ch)
499      char ch;
500 {
501   if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
502   if ((ch >= '0') && (ch <= '9')) return (ch-'0');
503   if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
504   return (-1);
505 }
506
507 /* scan for the sequence $<data>#<checksum>     */
508
509 static void 
510 getpacket(buffer)
511      char * buffer;
512 {
513   unsigned char checksum;
514   unsigned char xmitcsum;
515   int  i;
516   int  count;
517   char ch;
518
519   do {
520     /* wait around for the start character, ignore all other characters */
521     while ((ch = (getDebugChar() & 0x7f)) != '$');
522     checksum = 0;
523     xmitcsum = -1;
524
525     count = 0;
526
527     /* now, read until a # or end of buffer is found */
528     while (count < BUFMAX) {
529       ch = getDebugChar() & 0x7f;
530       if (ch == '#') break;
531       checksum = checksum + ch;
532       buffer[count] = ch;
533       count = count + 1;
534       }
535     buffer[count] = 0;
536
537     if (ch == '#') {
538       xmitcsum = hex(getDebugChar() & 0x7f) << 4;
539       xmitcsum += hex(getDebugChar() & 0x7f);
540       if (checksum != xmitcsum) {
541         if (remote_debug) {
542           char buf[16];
543
544           mem2hex((char *) &checksum, buf, 4, 0);
545           gdb_error("Bad checksum: my count = %s, ", buf);
546           mem2hex((char *) &xmitcsum, buf, 4, 0);
547           gdb_error("sent count = %s\n", buf);
548           gdb_error(" -- Bad buffer: \"%s\"\n", buffer); 
549         }
550
551         putDebugChar('-');  /* failed checksum */
552       } else {
553         putDebugChar('+');  /* successful transfer */
554         /* if a sequence char is present, reply the sequence ID */
555         if (buffer[2] == ':') {
556           putDebugChar( buffer[0] );
557           putDebugChar( buffer[1] );
558           /* remove sequence chars from buffer */
559           count = strlen(buffer);
560           for (i=3; i <= count; i++) buffer[i-3] = buffer[i];
561         }
562       }
563     }
564   } while (checksum != xmitcsum);
565 }
566
567 /* send the packet in buffer.  */
568
569 static void 
570 putpacket(buffer)
571      char * buffer;
572 {
573   unsigned char checksum;
574   int  count;
575   char ch;
576
577   /*  $<packet info>#<checksum>. */
578   do {
579     putDebugChar('$');
580     checksum = 0;
581     count    = 0;
582
583     while (ch=buffer[count]) {
584       putDebugChar(ch);
585       checksum += ch;
586       count += 1;
587     }
588     putDebugChar('#');
589     putDebugChar(hexchars[checksum >> 4]);
590     putDebugChar(hexchars[checksum % 16]);
591   } while ((getDebugChar() & 0x7f) != '+');
592 }
593
594 /* Address of a routine to RTE to if we get a memory fault.  */
595
596 static void (*volatile mem_fault_routine)() = 0;
597
598 static void
599 set_mem_err ()
600 {
601   mem_err = 1;
602 }
603
604 /* Check the address for safe access ranges.  As currently defined,
605    this routine will reject the "expansion bus" address range(s).
606    To make those ranges useable, someone must implement code to detect
607    whether there's anything connected to the expansion bus. */
608
609 static int
610 mem_safe (addr)
611      char *addr;
612 {
613 #define BAD_RANGE_ONE_START     ((char *) 0x600000)
614 #define BAD_RANGE_ONE_END       ((char *) 0xa00000)
615 #define BAD_RANGE_TWO_START     ((char *) 0xff680000)
616 #define BAD_RANGE_TWO_END       ((char *) 0xff800000)
617
618   if (addr < BAD_RANGE_ONE_START)       return 1;       /* safe */
619   if (addr < BAD_RANGE_ONE_END)         return 0;       /* unsafe */
620   if (addr < BAD_RANGE_TWO_START)       return 1;       /* safe */
621   if (addr < BAD_RANGE_TWO_END)         return 0;       /* unsafe */
622 }
623
624 /* These are separate functions so that they are so short and sweet
625    that the compiler won't save any registers (if there is a fault
626    to mem_fault, they won't get restored, so there better not be any
627    saved).  */
628 static int
629 get_char (addr)
630      char *addr;
631 {
632 #if 1
633   if (mem_fault_routine && !mem_safe(addr))
634     {
635       mem_fault_routine ();
636       return 0;
637     }
638 #endif
639   return *addr;
640 }
641
642 static void
643 set_char (addr, val)
644      char *addr;
645      int val;
646 {
647 #if 1
648   if (mem_fault_routine && !mem_safe (addr))
649     {
650       mem_fault_routine ();
651       return;
652     }
653 #endif
654   *addr = val;
655 }
656
657 /* Convert the memory pointed to by mem into hex, placing result in buf.
658    Return a pointer to the last char put in buf (null).
659    If MAY_FAULT is non-zero, then we should set mem_err in response to
660    a fault; if zero treat a fault like any other fault in the stub.  */
661
662 static char *
663 mem2hex(mem, buf, count, may_fault)
664      char* mem;
665      char* buf;
666      int   count;
667      int   may_fault;
668 {
669   int i;
670   unsigned char ch;
671
672   if (may_fault)
673     mem_fault_routine = set_mem_err;
674   for (i=0;i<count;i++) {
675     ch = get_char (mem++);
676     if (may_fault && mem_err)
677       return (buf);
678     *buf++ = hexchars[ch >> 4];
679     *buf++ = hexchars[ch % 16];
680   }
681   *buf = 0;
682   if (may_fault)
683     mem_fault_routine = 0;
684   return(buf);
685 }
686
687 /* Convert the hex array pointed to by buf into binary to be placed in mem.
688    Return a pointer to the character AFTER the last byte written. */
689
690 static char* 
691 hex2mem(buf, mem, count, may_fault)
692      char* buf;
693      char* mem;
694      int   count;
695      int   may_fault;
696 {
697   int i;
698   unsigned char ch;
699
700   if (may_fault)
701     mem_fault_routine = set_mem_err;
702   for (i=0;i<count;i++) {
703     ch = hex(*buf++) << 4;
704     ch = ch + hex(*buf++);
705     set_char (mem++, ch);
706     if (may_fault && mem_err)
707       return (mem);
708   }
709   if (may_fault)
710     mem_fault_routine = 0;
711   return(mem);
712 }
713
714 /* this function takes the m32r exception vector and attempts to
715    translate this number into a unix compatible signal value */
716
717 static int 
718 computeSignal(exceptionVector)
719      int exceptionVector;
720 {
721   int sigval;
722   switch (exceptionVector) {
723     case 0  : sigval = 23; break; /* I/O trap                    */
724     case 1  : sigval = 5;  break; /* breakpoint                  */
725     case 2  : sigval = 5;  break; /* breakpoint                  */
726     case 3  : sigval = 5;  break; /* breakpoint                  */
727     case 4  : sigval = 5;  break; /* breakpoint                  */
728     case 5  : sigval = 5;  break; /* breakpoint                  */
729     case 6  : sigval = 5;  break; /* breakpoint                  */
730     case 7  : sigval = 5;  break; /* breakpoint                  */
731     case 8  : sigval = 5;  break; /* breakpoint                  */
732     case 9  : sigval = 5;  break; /* breakpoint                  */
733     case 10 : sigval = 5;  break; /* breakpoint                  */
734     case 11 : sigval = 5;  break; /* breakpoint                  */
735     case 12 : sigval = 5;  break; /* breakpoint                  */
736     case 13 : sigval = 5;  break; /* breakpoint                  */
737     case 14 : sigval = 5;  break; /* breakpoint                  */
738     case 15 : sigval = 5;  break; /* breakpoint                  */
739     case 16 : sigval = 10; break; /* BUS ERROR (alignment)       */
740     case 17 : sigval = 2;  break; /* INTerrupt                   */
741     default : sigval = 7;  break; /* "software generated"        */
742   }
743   return (sigval);
744 }
745
746 /**********************************************/
747 /* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
748 /* RETURN NUMBER OF CHARS PROCESSED           */
749 /**********************************************/
750 static int 
751 hexToInt(ptr, intValue)
752      char **ptr;
753      int *intValue;
754 {
755   int numChars = 0;
756   int hexValue;
757
758   *intValue = 0;
759   while (**ptr)
760     {
761       hexValue = hex(**ptr);
762       if (hexValue >=0)
763         {
764           *intValue = (*intValue <<4) | hexValue;
765           numChars ++;
766         }
767       else
768         break;
769       (*ptr)++;
770     }
771   return (numChars);
772 }
773
774 /*
775   Table of branch instructions:
776   
777   10B6          RTE     return from trap or exception
778   1FCr          JMP     jump
779   1ECr          JL      jump and link
780   7Fxx          BRA     branch
781   FFxxxxxx      BRA     branch (long)
782   B09rxxxx      BNEZ    branch not-equal-zero
783   Br1rxxxx      BNE     branch not-equal
784   7Dxx          BNC     branch not-condition
785   FDxxxxxx      BNC     branch not-condition (long)
786   B0Arxxxx      BLTZ    branch less-than-zero
787   B0Crxxxx      BLEZ    branch less-equal-zero
788   7Exx          BL      branch and link
789   FExxxxxx      BL      branch and link (long)
790   B0Drxxxx      BGTZ    branch greater-than-zero
791   B0Brxxxx      BGEZ    branch greater-equal-zero
792   B08rxxxx      BEQZ    branch equal-zero
793   Br0rxxxx      BEQ     branch equal
794   7Cxx          BC      branch condition
795   FCxxxxxx      BC      branch condition (long)
796   */
797
798 static int 
799 isShortBranch(instr)
800      unsigned char *instr;
801 {
802   char instr0 = instr[0] & 0x7F;                /* mask off high bit */
803
804   if (instr0 == 0x10 && instr[1] == 0xB6)       /* RTE */
805     return 1;           /* return from trap or exception */
806
807   if (instr0 == 0x1E || instr0 == 0x1F)         /* JL or JMP */
808     if ((instr[1] & 0xF0) == 0xC0)
809       return 2;                                 /* jump thru a register */
810
811   if (instr0 == 0x7C || instr0 == 0x7D ||       /* BC, BNC, BL, BRA */
812       instr0 == 0x7E || instr0 == 0x7F)
813     return 3;                                   /* eight bit PC offset */
814
815   return 0;
816 }
817
818 static int
819 isLongBranch(instr)
820      unsigned char *instr;
821 {
822   if (instr[0] == 0xFC || instr[0] == 0xFD ||   /* BRA, BNC, BL, BC */
823       instr[0] == 0xFE || instr[0] == 0xFF)     /* 24 bit relative */
824     return 4;
825   if ((instr[0] & 0xF0) == 0xB0)                /* 16 bit relative */
826     {
827       if ((instr[1] & 0xF0) == 0x00 ||          /* BNE, BEQ */
828           (instr[1] & 0xF0) == 0x10)
829         return 5;
830       if (instr[0] == 0xB0)     /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ, BEQZ */
831         if ((instr[1] & 0xF0) == 0x80 || (instr[1] & 0xF0) == 0x90 || 
832             (instr[1] & 0xF0) == 0xA0 || (instr[1] & 0xF0) == 0xB0 ||
833             (instr[1] & 0xF0) == 0xC0 || (instr[1] & 0xF0) == 0xD0)
834           return 6;
835     }
836   return 0;
837 }
838
839 /* if address is NOT on a 4-byte boundary, or high-bit of instr is zero, 
840    then it's a 2-byte instruction, else it's a 4-byte instruction.  */
841
842 #define INSTRUCTION_SIZE(addr) \
843     ((((int) addr & 2) || (((unsigned char *) addr)[0] & 0x80) == 0) ? 2 : 4)
844
845 static int
846 isBranch(instr)
847      unsigned char *instr;
848 {
849   if (INSTRUCTION_SIZE(instr) == 2)
850     return isShortBranch(instr);
851   else
852     return isLongBranch(instr);
853 }
854
855 static int
856 willBranch(instr, branchCode)
857      unsigned char *instr;
858 {
859   switch (branchCode) 
860     {
861     case 0:     return 0;       /* not a branch */
862     case 1:     return 1;       /* RTE */
863     case 2:     return 1;       /* JL or JMP    */
864     case 3:                     /* BC, BNC, BL, BRA (short) */
865     case 4:                     /* BC, BNC, BL, BRA (long) */
866       switch (instr[0] & 0x0F) 
867         {
868         case 0xC:               /* Branch if Condition Register */
869           return (registers[CBR] != 0);
870         case 0xD:               /* Branch if NOT Condition Register */
871           return (registers[CBR] == 0);
872         case 0xE:               /* Branch and Link */
873         case 0xF:               /* Branch (unconditional) */
874           return 1;
875         default:                /* oops? */
876           return 0;
877         }
878     case 5:                     /* BNE, BEQ */
879       switch (instr[1] & 0xF0) 
880         {
881         case 0x00:              /* Branch if r1 equal to r2 */
882           return (registers[instr[0] & 0x0F] == registers[instr[1] & 0x0F]);
883         case 0x10:              /* Branch if r1 NOT equal to r2 */
884           return (registers[instr[0] & 0x0F] != registers[instr[1] & 0x0F]);
885         default:                /* oops? */
886           return 0;
887         }
888     case 6:                     /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ */
889       switch (instr[1] & 0xF0) 
890         {
891         case 0x80:              /* Branch if reg equal to zero */
892           return (registers[instr[1] & 0x0F] == 0);
893         case 0x90:              /* Branch if reg NOT equal to zero */
894           return (registers[instr[1] & 0x0F] != 0);
895         case 0xA0:              /* Branch if reg less than zero */
896           return (registers[instr[1] & 0x0F] < 0);
897         case 0xB0:              /* Branch if reg greater or equal to zero */
898           return (registers[instr[1] & 0x0F] >= 0);
899         case 0xC0:              /* Branch if reg less than or equal to zero */
900           return (registers[instr[1] & 0x0F] <= 0);
901         case 0xD0:              /* Branch if reg greater than zero */
902           return (registers[instr[1] & 0x0F] > 0);
903         default:                /* oops? */
904           return 0;
905         }
906     default:                    /* oops? */
907       return 0;
908     }
909 }
910
911 static int 
912 branchDestination(instr, branchCode) 
913      unsigned char *instr;
914
915   switch (branchCode) { 
916   default: 
917   case 0:                                       /* not a branch */ 
918     return 0;
919   case 1:                                       /* RTE */ 
920     return registers[BPC] & ~3;                 /* pop BPC into PC */
921   case 2:                                       /* JL or JMP */ 
922     return registers[instr[1] & 0x0F] & ~3;     /* jump thru a register */ 
923   case 3:               /* BC, BNC, BL, BRA (short, 8-bit relative offset) */ 
924     return (((int) instr) & ~3) + ((char) instr[1] << 2);
925   case 4:               /* BC, BNC, BL, BRA (long, 24-bit relative offset) */ 
926     return ((int) instr + 
927             ((((char) instr[1] << 16) | (instr[2] << 8) | (instr[3])) << 2)); 
928   case 5:               /* BNE, BEQ (16-bit relative offset) */ 
929   case 6:               /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ (ditto) */ 
930     return ((int) instr + ((((char) instr[2] << 8) | (instr[3])) << 2)); 
931   }
932
933   /* An explanatory note: in the last three return expressions, I have
934      cast the most-significant byte of the return offset to char.
935      What this accomplishes is sign extension.  If the other
936      less-significant bytes were signed as well, they would get sign
937      extended too and, if negative, their leading bits would clobber
938      the bits of the more-significant bytes ahead of them.  There are
939      other ways I could have done this, but sign extension from
940      odd-sized integers is always a pain. */
941 }
942
943 static void
944 branchSideEffects(instr, branchCode)
945      char *instr;
946      int branchCode;
947 {
948   switch (branchCode)
949     {
950     case 1:                     /* RTE */
951       return;                   /* I <THINK> this is already handled... */
952     case 2:                     /* JL (or JMP) */
953     case 3:                     /* BL (or BC, BNC, BRA) */
954     case 4:
955       if ((instr[0] & 0x0F) == 0x0E)            /* branch/jump and link */
956         registers[R14] = (registers[PC] & ~3) + 4;
957       return;
958     default:                    /* any other branch has no side effects */
959       return;
960     }
961 }
962
963 static struct STEPPING_CONTEXT {
964   int stepping;                 /* true when we've started a single-step */
965   unsigned long  target_addr;   /* the instr we're trying to execute */
966   unsigned long  target_size;   /* the size of the target instr */
967   unsigned long  noop_addr;     /* where we've inserted a no-op, if any */
968   unsigned long  trap1_addr;    /* the trap following the target instr */
969   unsigned long  trap2_addr;    /* the trap at a branch destination, if any */
970   unsigned short noop_save;     /* instruction overwritten by our no-op */
971   unsigned short trap1_save;    /* instruction overwritten by trap1 */
972   unsigned short trap2_save;    /* instruction overwritten by trap2 */
973   unsigned short continue_p;    /* true if NOT returning to gdb after step */
974 } stepping;
975
976 /* Function: prepare_to_step
977    Called from handle_exception to prepare the user program to single-step.
978    Places a trap instruction after the target instruction, with special 
979    extra handling for branch instructions and for instructions in the 
980    second half-word of a word.  
981
982    Returns: True  if we should actually execute the instruction; 
983             False if we are going to emulate executing the instruction,
984             in which case we simply report to GDB that the instruction 
985             has already been executed.  */
986
987 #define TRAP1  0x10f1;  /* trap #1 instruction */
988 #define NOOP   0x7000;  /* noop    instruction */
989
990 static unsigned short trap1 = TRAP1;
991 static unsigned short noop  = NOOP;
992
993 static int
994 prepare_to_step(continue_p)
995      int continue_p;    /* if this isn't REALLY a single-step (see below) */
996 {
997   unsigned long pc = registers[PC];
998   int branchCode   = isBranch((char *) pc);
999   char *p;
1000
1001   /* zero out the stepping context 
1002      (paranoia -- it should already be zeroed) */
1003   for (p = (char *) &stepping;
1004        p < ((char *) &stepping) + sizeof(stepping);
1005        p++)
1006     *p = 0;
1007
1008   if (branchCode != 0)                  /* next instruction is a branch */
1009     {
1010       branchSideEffects((char *) pc, branchCode);
1011       if (willBranch((char *)pc, branchCode))
1012         registers[PC] = branchDestination((char *) pc, branchCode);
1013       else
1014         registers[PC] = pc + INSTRUCTION_SIZE(pc);
1015       return 0;                 /* branch "executed" -- just notify GDB */
1016     }
1017   else if (((int) pc & 2) != 0)         /* "second-slot" instruction */
1018     {
1019       /* insert no-op before pc */
1020       stepping.noop_addr  =  pc - 2;
1021       stepping.noop_save  = *(unsigned short *) stepping.noop_addr;
1022       *(unsigned short *) stepping.noop_addr  = noop;
1023       /* insert trap  after  pc */
1024       stepping.trap1_addr =  pc + 2;
1025       stepping.trap1_save = *(unsigned short *) stepping.trap1_addr;
1026       *(unsigned short *) stepping.trap1_addr = trap1;
1027     }
1028   else                                  /* "first-slot" instruction */
1029     {
1030       /* insert trap  after  pc */
1031       stepping.trap1_addr = pc + INSTRUCTION_SIZE(pc);  
1032       stepping.trap1_save = *(unsigned short *) stepping.trap1_addr;
1033       *(unsigned short *) stepping.trap1_addr = trap1;
1034     }
1035   /* "continue_p" means that we are actually doing a continue, and not 
1036      being requested to single-step by GDB.  Sometimes we have to do
1037      one single-step before continuing, because the PC is on a half-word
1038      boundary.  There's no way to simply resume at such an address.  */
1039   stepping.continue_p = continue_p;
1040   stepping.stepping = 1;                /* starting a single-step */
1041   return 1;
1042 }
1043
1044 /* Function: finish_from_step
1045    Called from handle_exception to finish up when the user program 
1046    returns from a single-step.  Replaces the instructions that had
1047    been overwritten by traps or no-ops, 
1048
1049    Returns: True  if we should notify GDB that the target stopped.
1050             False if we only single-stepped because we had to before we
1051             could continue (ie. we were trying to continue at a 
1052             half-word boundary).  In that case don't notify GDB:
1053             just "continue continuing".  */
1054
1055 static int
1056 finish_from_step()
1057 {
1058   if (stepping.stepping)        /* anything to do? */
1059     {
1060       int continue_p = stepping.continue_p;
1061       char *p;
1062
1063       if (stepping.noop_addr)   /* replace instr "under" our no-op */
1064         *(unsigned short *) stepping.noop_addr  = stepping.noop_save;
1065       if (stepping.trap1_addr)  /* replace instr "under" our trap  */
1066         *(unsigned short *) stepping.trap1_addr = stepping.trap1_save;
1067       if (stepping.trap2_addr)  /* ditto our other trap, if any    */
1068         *(unsigned short *) stepping.trap2_addr = stepping.trap2_save;
1069
1070       for (p = (char *) &stepping;      /* zero out the stepping context */
1071            p < ((char *) &stepping) + sizeof(stepping);
1072            p++)
1073         *p = 0;
1074
1075       return !(continue_p);
1076     }
1077   else  /* we didn't single-step, therefore this must be a legitimate stop */
1078     return 1;
1079 }
1080
1081 struct PSWreg {         /* separate out the bit flags in the PSW register */
1082   int pad1 : 16;
1083   int bsm  : 1;
1084   int bie  : 1;
1085   int pad2 : 5;
1086   int bc   : 1;
1087   int sm   : 1;
1088   int ie   : 1;
1089   int pad3 : 5;
1090   int c    : 1;
1091 } *psw;
1092
1093 /* Upon entry the value for LR to save has been pushed.
1094    We unpush that so that the value for the stack pointer saved is correct.
1095    Upon entry, all other registers are assumed to have not been modified
1096    since the interrupt/trap occured.  */
1097
1098 asm ("
1099 stash_registers:
1100         push r0
1101         push r1
1102         seth r1, #shigh(registers)
1103         add3 r1, r1, #low(registers)
1104         pop r0          ; r1
1105         st r0, @(4,r1)
1106         pop r0          ; r0
1107         st r0, @r1
1108         addi r1, #4     ; only add 4 as subsequent saves are `pre inc'
1109         st r2, @+r1
1110         st r3, @+r1
1111         st r4, @+r1
1112         st r5, @+r1
1113         st r6, @+r1
1114         st r7, @+r1
1115         st r8, @+r1
1116         st r9, @+r1
1117         st r10, @+r1
1118         st r11, @+r1
1119         st r12, @+r1
1120         st r13, @+r1    ; fp
1121         pop r0          ; lr (r14)
1122         st r0, @+r1
1123         st sp, @+r1     ; sp contains right value at this point
1124         mvfc r0, cr0
1125         st r0, @+r1     ; cr0 == PSW
1126         mvfc r0, cr1
1127         st r0, @+r1     ; cr1 == CBR
1128         mvfc r0, cr2
1129         st r0, @+r1     ; cr2 == SPI
1130         mvfc r0, cr3
1131         st r0, @+r1     ; cr3 == SPU
1132         mvfc r0, cr6
1133         st r0, @+r1     ; cr6 == BPC
1134         st r0, @+r1     ; PC  == BPC
1135         mvfaclo r0
1136         st r0, @+r1     ; ACCL
1137         mvfachi r0
1138         st r0, @+r1     ; ACCH
1139         jmp lr");
1140
1141 /* C routine to clean up what stash_registers did.
1142    It is called after calling stash_registers.
1143    This is separate from stash_registers as we want to do this in C
1144    but doing stash_registers in C isn't straightforward.  */
1145
1146 static void
1147 cleanup_stash ()
1148 {
1149   psw = (struct PSWreg *) &registers[PSW];      /* fields of PSW register */
1150   psw->sm = psw->bsm;           /* fix up pre-trap values of psw fields */
1151   psw->ie = psw->bie;
1152   psw->c  = psw->bc;
1153   registers[CBR] = psw->bc;             /* fix up pre-trap "C" register */
1154
1155 #if 0 /* FIXME: Was in previous version.  Necessary?
1156          (Remember that we use the "rte" insn to return from the
1157          trap/interrupt so the values of bsm, bie, bc are important.  */
1158   psw->bsm = psw->bie = psw->bc = 0;    /* zero post-trap values */
1159 #endif
1160
1161   /* FIXME: Copied from previous version.  This can probably be deleted
1162      since methinks stash_registers has already done this.  */
1163   registers[PC] = registers[BPC];       /* pre-trap PC */
1164
1165   /* FIXME: Copied from previous version.  Necessary?  */
1166   if (psw->sm)                  /* copy R15 into (psw->sm ? SPU : SPI) */
1167     registers[SPU] = registers[R15];
1168   else
1169     registers[SPI] = registers[R15];
1170 }
1171
1172 asm ("
1173 restore_and_return:
1174         seth r0, #shigh(registers+8)
1175         add3 r0, r0, #low(registers+8)
1176         ld r2, @r0+     ; restore r2
1177         ld r3, @r0+     ; restore r3
1178         ld r4, @r0+     ; restore r4
1179         ld r5, @r0+     ; restore r5
1180         ld r6, @r0+     ; restore r6
1181         ld r7, @r0+     ; restore r7
1182         ld r8, @r0+     ; restore r8
1183         ld r9, @r0+     ; restore r9
1184         ld r10, @r0+    ; restore r10
1185         ld r11, @r0+    ; restore r11
1186         ld r12, @r0+    ; restore r12
1187         ld r13, @r0+    ; restore r13
1188         ld r14, @r0+    ; restore r14
1189         ld r15, @r0+    ; restore r15
1190         ld r1, @r0+     ; restore cr0 == PSW
1191         mvtc r1, cr0
1192         ld r1, @r0+     ; restore cr1 == CBR (no-op, because it's read only)
1193         mvtc r1, cr1
1194         ld r1, @r0+     ; restore cr2 == SPI
1195         mvtc r1, cr2
1196         ld r1, @r0+     ; restore cr3 == SPU
1197         mvtc r1, cr3
1198         addi r0, #4     ; skip BPC
1199         ld r1, @r0+     ; restore cr6 (BPC) == PC
1200         mvtc r1, cr6
1201         ld r1, @r0+     ; restore ACCL
1202         mvtaclo r1
1203         ld r1, @r0+     ; restore ACCH
1204         mvtachi r1
1205         seth r0, #shigh(registers)
1206         add3 r0, r0, #low(registers)
1207         ld r1, @(4,r0)  ; restore r1
1208         ld r0, @r0      ; restore r0
1209         rte");
1210
1211 /* General trap handler, called after the registers have been stashed.
1212    NUM is the trap/exception number.  */
1213
1214 static void
1215 process_exception (num)
1216      int num;
1217 {
1218   cleanup_stash ();
1219   asm volatile ("
1220         seth r1, #shigh(stackPtr)
1221         add3 r1, r1, #low(stackPtr)
1222         ld r15, @r1             ; setup local stack (protect user stack)
1223         mv r0, %0
1224         bl handle_exception
1225         bl restore_and_return"
1226                 : : "r" (num) : "r0", "r1");
1227 }
1228
1229 void _catchException0 ();
1230
1231 asm ("
1232 _catchException0:
1233         push lr
1234         bl stash_registers
1235         ; Note that at this point the pushed value of `lr' has been popped
1236         ldi r0, #0
1237         bl process_exception");
1238
1239 void _catchException1 ();
1240
1241 asm ("
1242 _catchException1:
1243         push lr
1244         bl stash_registers
1245         ; Note that at this point the pushed value of `lr' has been popped
1246         bl cleanup_stash
1247         seth r1, #shigh(stackPtr)
1248         add3 r1, r1, #low(stackPtr)
1249         ld r15, @r1             ; setup local stack (protect user stack)
1250         seth r1, #shigh(registers + 21*4) ; PC
1251         add3 r1, r1, #low(registers + 21*4)
1252         ld r0, @r1
1253         addi r0, #-4            ; back up PC for breakpoint trap.
1254         st r0, @r1              ; FIXME: what about bp in right slot?
1255         ldi r0, #1
1256         bl handle_exception
1257         bl restore_and_return");
1258
1259 void _catchException2 ();
1260
1261 asm ("
1262 _catchException2:
1263         push lr
1264         bl stash_registers
1265         ; Note that at this point the pushed value of `lr' has been popped
1266         ldi r0, #2
1267         bl process_exception");
1268
1269 void _catchException3 ();
1270
1271 asm ("
1272 _catchException3:
1273         push lr
1274         bl stash_registers
1275         ; Note that at this point the pushed value of `lr' has been popped
1276         ldi r0, #3
1277         bl process_exception");
1278
1279 void _catchException4 ();
1280
1281 asm ("
1282 _catchException4:
1283         push lr
1284         bl stash_registers
1285         ; Note that at this point the pushed value of `lr' has been popped
1286         ldi r0, #4
1287         bl process_exception");
1288
1289 void _catchException5 ();
1290
1291 asm ("
1292 _catchException5:
1293         push lr
1294         bl stash_registers
1295         ; Note that at this point the pushed value of `lr' has been popped
1296         ldi r0, #5
1297         bl process_exception");
1298
1299 void _catchException6 ();
1300
1301 asm ("
1302 _catchException6:
1303         push lr
1304         bl stash_registers
1305         ; Note that at this point the pushed value of `lr' has been popped
1306         ldi r0, #6
1307         bl process_exception");
1308
1309 void _catchException7 ();
1310
1311 asm ("
1312 _catchException7:
1313         push lr
1314         bl stash_registers
1315         ; Note that at this point the pushed value of `lr' has been popped
1316         ldi r0, #7
1317         bl process_exception");
1318
1319 void _catchException8 ();
1320
1321 asm ("
1322 _catchException8:
1323         push lr
1324         bl stash_registers
1325         ; Note that at this point the pushed value of `lr' has been popped
1326         ldi r0, #8
1327         bl process_exception");
1328
1329 void _catchException9 ();
1330
1331 asm ("
1332 _catchException9:
1333         push lr
1334         bl stash_registers
1335         ; Note that at this point the pushed value of `lr' has been popped
1336         ldi r0, #9
1337         bl process_exception");
1338
1339 void _catchException10 ();
1340
1341 asm ("
1342 _catchException10:
1343         push lr
1344         bl stash_registers
1345         ; Note that at this point the pushed value of `lr' has been popped
1346         ldi r0, #10
1347         bl process_exception");
1348
1349 void _catchException11 ();
1350
1351 asm ("
1352 _catchException11:
1353         push lr
1354         bl stash_registers
1355         ; Note that at this point the pushed value of `lr' has been popped
1356         ldi r0, #11
1357         bl process_exception");
1358
1359 void _catchException12 ();
1360
1361 asm ("
1362 _catchException12:
1363         push lr
1364         bl stash_registers
1365         ; Note that at this point the pushed value of `lr' has been popped
1366         ldi r0, #12
1367         bl process_exception");
1368
1369 void _catchException13 ();
1370
1371 asm ("
1372 _catchException13:
1373         push lr
1374         bl stash_registers
1375         ; Note that at this point the pushed value of `lr' has been popped
1376         ldi r0, #13
1377         bl process_exception");
1378
1379 void _catchException14 ();
1380
1381 asm ("
1382 _catchException14:
1383         push lr
1384         bl stash_registers
1385         ; Note that at this point the pushed value of `lr' has been popped
1386         ldi r0, #14
1387         bl process_exception");
1388
1389 void _catchException15 ();
1390
1391 asm ("
1392 _catchException15:
1393         push lr
1394         bl stash_registers
1395         ; Note that at this point the pushed value of `lr' has been popped
1396         ldi r0, #15
1397         bl process_exception");
1398
1399 void _catchException16 ();
1400
1401 asm ("
1402 _catchException16:
1403         push lr
1404         bl stash_registers
1405         ; Note that at this point the pushed value of `lr' has been popped
1406         ldi r0, #16
1407         bl process_exception");
1408
1409 void _catchException17 ();
1410
1411 asm ("
1412 _catchException17:
1413         push lr
1414         bl stash_registers
1415         ; Note that at this point the pushed value of `lr' has been popped
1416         ldi r0, #17
1417         bl process_exception");
1418
1419
1420 /* this function is used to set up exception handlers for tracing and
1421    breakpoints */
1422 void 
1423 set_debug_traps()
1424 {
1425   /*  extern void remcomHandler(); */
1426   int i;
1427
1428   for (i = 0; i < 18; i++)              /* keep a copy of old vectors */
1429     if (save_vectors[i] == 0)           /* only copy them the first time */
1430       save_vectors[i] = getExceptionHandler (i);
1431
1432   stackPtr  = &remcomStack[STACKSIZE/sizeof(int) - 1];
1433
1434   exceptionHandler (0, _catchException0);
1435   exceptionHandler (1, _catchException1);
1436   exceptionHandler (2, _catchException2);
1437   exceptionHandler (3, _catchException3);
1438   exceptionHandler (4, _catchException4);
1439   exceptionHandler (5, _catchException5);
1440   exceptionHandler (6, _catchException6);
1441   exceptionHandler (7, _catchException7);
1442   exceptionHandler (8, _catchException8);
1443   exceptionHandler (9, _catchException9);
1444   exceptionHandler (10, _catchException10);
1445   exceptionHandler (11, _catchException11);
1446   exceptionHandler (12, _catchException12);
1447   exceptionHandler (13, _catchException13);
1448   exceptionHandler (14, _catchException14);
1449   exceptionHandler (15, _catchException15);
1450   exceptionHandler (16, _catchException16);
1451   /*  exceptionHandler (17, _catchException17); */
1452
1453   /* In case GDB is started before us, ack any packets (presumably
1454      "$?#xx") sitting there.  */
1455   putDebugChar ('+');
1456
1457   initialized = 1;
1458 }
1459
1460 /* This function will generate a breakpoint exception.  It is used at the
1461    beginning of a program to sync up with a debugger and can be used
1462    otherwise as a quick means to stop program execution and "break" into
1463    the debugger. */
1464
1465 #define BREAKPOINT() asm volatile ("    trap #2");
1466
1467 void 
1468 breakpoint()
1469 {
1470   if (initialized)
1471     BREAKPOINT();
1472 }
1473
1474 /* STDOUT section:
1475    Stuff pertaining to simulating stdout by sending chars to gdb to be echoed.
1476    Functions: gdb_putchar(char ch)
1477               gdb_puts(char *str)
1478               gdb_write(char *str, int len)
1479               gdb_error(char *format, char *parm)
1480               */
1481  
1482 /* Function: gdb_putchar(int)
1483    Make gdb write a char to stdout.
1484    Returns: the char */
1485  
1486 static int
1487 gdb_putchar(ch)
1488      int ch;
1489 {
1490   char buf[4];
1491  
1492   buf[0] = 'O';
1493   buf[1] = hexchars[ch >> 4];
1494   buf[2] = hexchars[ch & 0x0F];
1495   buf[3] = 0;
1496   putpacket(buf);
1497   return ch;
1498 }
1499  
1500 /* Function: gdb_write(char *, int)
1501    Make gdb write n bytes to stdout (not assumed to be null-terminated).
1502    Returns: number of bytes written */
1503  
1504 static int
1505 gdb_write(data, len)
1506      char *data;
1507      int len;
1508 {
1509   char *buf, *cpy;
1510   int i;
1511  
1512   buf = remcomOutBuffer;
1513   buf[0] = 'O';
1514   i = 0;
1515   while (i < len)
1516     {
1517       for (cpy = buf+1; 
1518            i < len && cpy < buf + sizeof(remcomOutBuffer) - 3; 
1519            i++)
1520         {
1521           *cpy++ = hexchars[data[i] >> 4];
1522           *cpy++ = hexchars[data[i] & 0x0F];
1523         }
1524       *cpy = 0;
1525       putpacket(buf);
1526     }
1527   return len;
1528 }
1529
1530 /* Function: gdb_puts(char *)
1531    Make gdb write a null-terminated string to stdout.
1532    Returns: the length of the string */
1533  
1534 static int
1535 gdb_puts(str)
1536      char *str;
1537 {
1538   return gdb_write(str, strlen(str));
1539 }
1540  
1541 /* Function: gdb_error(char *, char *)
1542    Send an error message to gdb's stdout.
1543    First string may have 1 (one) optional "%s" in it, which
1544    will cause the optional second string to be inserted.  */
1545  
1546 static void
1547 gdb_error(format, parm)
1548      char * format;
1549      char * parm;
1550 {
1551   char buf[400], *cpy;
1552   int len;
1553  
1554   if (remote_debug)
1555     {
1556       if (format && *format)
1557         len = strlen(format);
1558       else
1559         return;             /* empty input */
1560
1561       if (parm && *parm)
1562         len += strlen(parm);
1563  
1564       for (cpy = buf; *format; )
1565         {
1566           if (format[0] == '%' && format[1] == 's') /* include second string */
1567             {
1568               format += 2;          /* advance two chars instead of just one */
1569               while (parm && *parm)
1570                 *cpy++ = *parm++;
1571             }
1572           else
1573             *cpy++ = *format++;
1574         }
1575       *cpy = '\0';
1576       gdb_puts(buf);
1577     }
1578 }
1579  
1580 static char *
1581 strcpy (char *dest, const char *src)
1582 {
1583   char *ret = dest;
1584
1585   if (dest && src)
1586     {
1587       while (*src)
1588         *dest++ = *src++;
1589       *dest = 0;
1590     }
1591   return ret;
1592 }
1593
1594 static int
1595 strlen (const char *src)
1596 {
1597   int ret;
1598
1599   for (ret = 0; *src; src++)
1600     ret++;
1601
1602   return ret;
1603 }
1604
1605 #if 0
1606 void exit (code)
1607      int code;
1608 {
1609   _exit (code);
1610 }
1611
1612 int atexit (void *p)
1613 {
1614   return 0;
1615 }
1616
1617 void abort (void)
1618 {
1619   _exit (1);
1620 }
1621 #endif