OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.18.0/] [libgloss/] [m32r/] [m32r-stub.c] - Blame information for rev 258

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 207 jeremybenn
/****************************************************************************
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
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
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
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 *
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
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
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
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
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
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 *
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 *
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.