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