source: trunk/libs/newlib/src/libgloss/m32r/m32r-stub.c @ 684

Last change on this file since 684 was 444, checked in by satin@…, 7 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 46.4 KB
Line 
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 */
99extern void putDebugChar ();    /* write a single character      */
100extern int getDebugChar ();     /* read and return a single char */
101extern 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
109static char initialized;        /* boolean flag. != 0 means we've been initialized */
110
111int remote_debug;
112/*  debug >  0 prints ill-formed commands in valid packets & checksum errors */
113
114static const unsigned char hexchars[] = "0123456789abcdef";
115
116#define NUMREGS 24
117
118/* Number of bytes of registers.  */
119#define NUMREGBYTES (NUMREGS * 4)
120enum 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
126enum 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
153static int registers[NUMREGS];
154
155#define STACKSIZE 8096
156static unsigned char remcomInBuffer[BUFMAX];
157static unsigned char remcomOutBuffer[BUFMAX];
158static int remcomStack[STACKSIZE / sizeof (int)];
159static int *stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1];
160
161static unsigned int save_vectors[18];   /* previous exception vectors */
162
163/* Indicate to caller of mem2hex or hex2mem that there has been an error. */
164static 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).  */
168int 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
177extern void handle_exception (int);
178extern void set_debug_traps (void);
179extern void breakpoint (void);
180
181/* Local functions:
182 */
183
184static int computeSignal (int);
185static void putpacket (unsigned char *);
186static unsigned char *getpacket (void);
187
188static unsigned char *mem2hex (unsigned char *, unsigned char *, int, int);
189static unsigned char *hex2mem (unsigned char *, unsigned char *, int, int);
190static int hexToInt (unsigned char **, int *);
191static unsigned char *bin2mem (unsigned char *, unsigned char *, int, int);
192static void stash_registers (void);
193static void restore_registers (void);
194static int prepare_to_step (int);
195static int finish_from_step (void);
196static unsigned long crc32 (unsigned char *, int, unsigned long);
197
198static void gdb_error (char *, char *);
199static int gdb_putchar (int), gdb_puts (char *), gdb_write (char *, int);
200
201static unsigned char *strcpy (unsigned char *, const unsigned char *);
202static int strlen (const unsigned char *);
203
204/*
205 * This function does all command procesing for interfacing to gdb.
206 */
207
208void
209handle_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. */
546static unsigned long crc32_table[256] = { 0, 0 };
547
548static unsigned long
549crc32 (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
573static int
574hex (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
587unsigned char *
588getpacket (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
663static void
664putpacket (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
692static void (*volatile mem_fault_routine) () = 0;
693
694static void
695set_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
705static int
706mem_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).  */
727static int
728get_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
740static void
741set_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
758static unsigned char *
759mem2hex (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
783static unsigned char *
784hex2mem (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. */
809static unsigned char *
810bin2mem (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
851static int
852computeSignal (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/**********************************************/
922static int
923hexToInt (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
968static int
969isShortBranch (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
987static int
988isLongBranch (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
1013static int
1014isBranch (unsigned char *instr)
1015{
1016  if (INSTRUCTION_SIZE (instr) == 2)
1017    return isShortBranch (instr);
1018  else
1019    return isLongBranch (instr);
1020}
1021
1022static int
1023willBranch (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
1080static int
1081branchDestination (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
1113static void
1114branchSideEffects (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
1131static 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
1159static unsigned short trap1 = TRAP1;
1160static unsigned short noop = NOOP;
1161
1162static int
1163prepare_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
1223static int
1224finish_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
1248struct 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
1266asm ("\n\
1267stash_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
1314static void
1315cleanup_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
1340asm ("\n\
1341restore_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
1382static void
1383process_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
1395void _catchException0 ();
1396
1397asm ("\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
1405void _catchException1 ();
1406
1407asm ("\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
1425void _catchException2 ();
1426
1427asm ("\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
1435void _catchException3 ();
1436
1437asm ("\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
1445void _catchException4 ();
1446
1447asm ("\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
1455void _catchException5 ();
1456
1457asm ("\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
1465void _catchException6 ();
1466
1467asm ("\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
1475void _catchException7 ();
1476
1477asm ("\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
1485void _catchException8 ();
1486
1487asm ("\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
1495void _catchException9 ();
1496
1497asm ("\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
1505void _catchException10 ();
1506
1507asm ("\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
1515void _catchException11 ();
1516
1517asm ("\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
1525void _catchException12 ();
1526
1527asm ("\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
1535void _catchException13 ();
1536
1537asm ("\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
1545void _catchException14 ();
1546
1547asm ("\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
1555void _catchException15 ();
1556
1557asm ("\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
1565void _catchException16 ();
1566
1567asm ("\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
1575void _catchException17 ();
1576
1577asm ("\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 */
1588void
1589set_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
1629void
1630breakpoint (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
1648static int
1649gdb_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
1665static int
1666gdb_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
1692static int
1693gdb_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
1703static void
1704gdb_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
1735static unsigned char *
1736strcpy (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
1749static int
1750strlen (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
1761void
1762exit (code)
1763     int code;
1764{
1765  _exit (code);
1766}
1767
1768int
1769atexit (void *p)
1770{
1771  return 0;
1772}
1773
1774void
1775abort (void)
1776{
1777  _exit (1);
1778}
1779#endif
Note: See TracBrowser for help on using the repository browser.