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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [m32r-stub.c] - Blame information for rev 1770

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

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

powered by: WebSVN 2.1.0

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