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

Subversion Repositories openrisc_me

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

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

Line No. Rev Author Line
1 148 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 { 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 (buf, len, crc)
539
     unsigned char *buf;
540
     int len;
541
     unsigned long crc;
542
{
543
  if (! crc32_table[1])
544
    {
545
      /* Initialize the CRC table and the decoding table. */
546
      int i, j;
547
      unsigned long c;
548
 
549
      for (i = 0; i < 256; i++)
550
        {
551
          for (c = i << 24, j = 8; j > 0; --j)
552
            c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
553
          crc32_table[i] = c;
554
        }
555
    }
556
 
557
  while (len--)
558
    {
559
      crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf) & 255];
560
      buf++;
561
    }
562
  return crc;
563
}
564
 
565
static int
566
hex(ch)
567
     unsigned char ch;
568
{
569
  if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
570
  if ((ch >= '0') && (ch <= '9')) return (ch-'0');
571
  if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
572
  return (-1);
573
}
574
 
575
/* scan for the sequence $<data>#<checksum>     */
576
 
577
unsigned char *
578
getpacket ()
579
{
580
  unsigned char *buffer = &remcomInBuffer[0];
581
  unsigned char checksum;
582
  unsigned char xmitcsum;
583
  int count;
584
  char ch;
585
 
586
  while (1)
587
    {
588
      /* wait around for the start character, ignore all other characters */
589
      while ((ch = getDebugChar ()) != '$')
590
        ;
591
 
592
retry:
593
      checksum = 0;
594
      xmitcsum = -1;
595
      count = 0;
596
 
597
      /* now, read until a # or end of buffer is found */
598
      while (count < BUFMAX)
599
        {
600
          ch = getDebugChar ();
601
          if (ch == '$')
602
            goto retry;
603
          if (ch == '#')
604
            break;
605
          checksum = checksum + ch;
606
          buffer[count] = ch;
607
          count = count + 1;
608
        }
609
      buffer[count] = 0;
610
 
611
      if (ch == '#')
612
        {
613
          ch = getDebugChar ();
614
          xmitcsum = hex (ch) << 4;
615
          ch = getDebugChar ();
616
          xmitcsum += hex (ch);
617
 
618
          if (checksum != xmitcsum)
619
            {
620
              if (remote_debug)
621
                {
622
                  unsigned char buf[16];
623
 
624
                  mem2hex((unsigned char *) &checksum, buf, 4, 0);
625
                  gdb_error("Bad checksum: my count = %s, ", buf);
626
                  mem2hex((unsigned char *) &xmitcsum, buf, 4, 0);
627
                  gdb_error("sent count = %s\n", buf);
628
                  gdb_error(" -- Bad buffer: \"%s\"\n", buffer);
629
                }
630
              putDebugChar ('-');       /* failed checksum */
631
            }
632
          else
633
            {
634
              putDebugChar ('+');       /* successful transfer */
635
 
636
              /* if a sequence char is present, reply the sequence ID */
637
              if (buffer[2] == ':')
638
                {
639
                  putDebugChar (buffer[0]);
640
                  putDebugChar (buffer[1]);
641
 
642
                  return &buffer[3];
643
                }
644
 
645
              return &buffer[0];
646
            }
647
        }
648
    }
649
}
650
 
651
/* send the packet in buffer.  */
652
 
653
static void
654
putpacket(buffer)
655
     unsigned char *buffer;
656
{
657
  unsigned char checksum;
658
  int  count;
659
  char ch;
660
 
661
  /*  $<packet info>#<checksum>. */
662
  do {
663
    putDebugChar('$');
664
    checksum = 0;
665
    count    = 0;
666
 
667
    while (ch=buffer[count]) {
668
      putDebugChar(ch);
669
      checksum += ch;
670
      count += 1;
671
    }
672
    putDebugChar('#');
673
    putDebugChar(hexchars[checksum >> 4]);
674
    putDebugChar(hexchars[checksum % 16]);
675
  } while (getDebugChar() != '+');
676
}
677
 
678
/* Address of a routine to RTE to if we get a memory fault.  */
679
 
680
static void (*volatile mem_fault_routine)() = 0;
681
 
682
static void
683
set_mem_err ()
684
{
685
  mem_err = 1;
686
}
687
 
688
/* Check the address for safe access ranges.  As currently defined,
689
   this routine will reject the "expansion bus" address range(s).
690
   To make those ranges useable, someone must implement code to detect
691
   whether there's anything connected to the expansion bus. */
692
 
693
static int
694
mem_safe (addr)
695
     unsigned char *addr;
696
{
697
#define BAD_RANGE_ONE_START     ((unsigned char *) 0x600000)
698
#define BAD_RANGE_ONE_END       ((unsigned char *) 0xa00000)
699
#define BAD_RANGE_TWO_START     ((unsigned char *) 0xff680000)
700
#define BAD_RANGE_TWO_END       ((unsigned char *) 0xff800000)
701
 
702
  if (addr < BAD_RANGE_ONE_START)       return 1;       /* safe */
703
  if (addr < BAD_RANGE_ONE_END)         return 0;        /* unsafe */
704
  if (addr < BAD_RANGE_TWO_START)       return 1;       /* safe */
705
  if (addr < BAD_RANGE_TWO_END)         return 0;        /* unsafe */
706
}
707
 
708
/* These are separate functions so that they are so short and sweet
709
   that the compiler won't save any registers (if there is a fault
710
   to mem_fault, they won't get restored, so there better not be any
711
   saved).  */
712
static int
713
get_char (addr)
714
     unsigned char *addr;
715
{
716
#if 1
717
  if (mem_fault_routine && !mem_safe(addr))
718
    {
719
      mem_fault_routine ();
720
      return 0;
721
    }
722
#endif
723
  return *addr;
724
}
725
 
726
static void
727
set_char (addr, val)
728
     unsigned char *addr;
729
     unsigned char val;
730
{
731
#if 1
732
  if (mem_fault_routine && !mem_safe (addr))
733
    {
734
      mem_fault_routine ();
735
      return;
736
    }
737
#endif
738
  *addr = val;
739
}
740
 
741
/* Convert the memory pointed to by mem into hex, placing result in buf.
742
   Return a pointer to the last char put in buf (null).
743
   If MAY_FAULT is non-zero, then we should set mem_err in response to
744
   a fault; if zero treat a fault like any other fault in the stub.  */
745
 
746
static unsigned char *
747
mem2hex(mem, buf, count, may_fault)
748
     unsigned char* mem;
749
     unsigned char* buf;
750
     int   count;
751
     int   may_fault;
752
{
753
  int i;
754
  unsigned char ch;
755
 
756
  if (may_fault)
757
    mem_fault_routine = set_mem_err;
758
  for (i=0;i<count;i++) {
759
    ch = get_char (mem++);
760
    if (may_fault && mem_err)
761
      return (buf);
762
    *buf++ = hexchars[ch >> 4];
763
    *buf++ = hexchars[ch % 16];
764
  }
765
  *buf = 0;
766
  if (may_fault)
767
    mem_fault_routine = 0;
768
  return(buf);
769
}
770
 
771
/* Convert the hex array pointed to by buf into binary to be placed in mem.
772
   Return a pointer to the character AFTER the last byte written. */
773
 
774
static unsigned char*
775
hex2mem(buf, mem, count, may_fault)
776
     unsigned char* buf;
777
     unsigned char* mem;
778
     int   count;
779
     int   may_fault;
780
{
781
  int i;
782
  unsigned char ch;
783
 
784
  if (may_fault)
785
    mem_fault_routine = set_mem_err;
786
  for (i=0;i<count;i++) {
787
    ch = hex(*buf++) << 4;
788
    ch = ch + hex(*buf++);
789
    set_char (mem++, ch);
790
    if (may_fault && mem_err)
791
      return (mem);
792
  }
793
  if (may_fault)
794
    mem_fault_routine = 0;
795
  return(mem);
796
}
797
 
798
/* Convert the binary stream in BUF to memory.
799
 
800
   Gdb will escape $, #, and the escape char (0x7d).
801
   COUNT is the total number of bytes to write into
802
   memory. */
803
static unsigned char *
804
bin2mem (buf, mem, count, may_fault)
805
     unsigned char *buf;
806
     unsigned char *mem;
807
     int   count;
808
     int   may_fault;
809
{
810
  int i;
811
  unsigned char ch;
812
 
813
  if (may_fault)
814
    mem_fault_routine = set_mem_err;
815
  for (i = 0; i < count; i++)
816
    {
817
      /* Check for any escaped characters. Be paranoid and
818
         only unescape chars that should be escaped. */
819
      if (*buf == 0x7d)
820
        {
821
          switch (*(buf+1))
822
            {
823
            case 0x3:  /* # */
824
            case 0x4:  /* $ */
825
            case 0x5d: /* escape char */
826
              buf++;
827
              *buf |= 0x20;
828
              break;
829
            default:
830
              /* nothing */
831
              break;
832
            }
833
        }
834
 
835
      set_char (mem++, *buf++);
836
 
837
      if (may_fault && mem_err)
838
        return mem;
839
    }
840
 
841
  if (may_fault)
842
    mem_fault_routine = 0;
843
  return mem;
844
}
845
 
846
/* this function takes the m32r exception vector and attempts to
847
   translate this number into a unix compatible signal value */
848
 
849
static int
850
computeSignal(exceptionVector)
851
     int exceptionVector;
852
{
853
  int sigval;
854
  switch (exceptionVector) {
855
    case 0  : sigval = 23; break; /* I/O trap                    */
856
    case 1  : sigval = 5;  break; /* breakpoint                  */
857
    case 2  : sigval = 5;  break; /* breakpoint                  */
858
    case 3  : sigval = 5;  break; /* breakpoint                  */
859
    case 4  : sigval = 5;  break; /* breakpoint                  */
860
    case 5  : sigval = 5;  break; /* breakpoint                  */
861
    case 6  : sigval = 5;  break; /* breakpoint                  */
862
    case 7  : sigval = 5;  break; /* breakpoint                  */
863
    case 8  : sigval = 5;  break; /* breakpoint                  */
864
    case 9  : sigval = 5;  break; /* breakpoint                  */
865
    case 10 : sigval = 5;  break; /* breakpoint                  */
866
    case 11 : sigval = 5;  break; /* breakpoint                  */
867
    case 12 : sigval = 5;  break; /* breakpoint                  */
868
    case 13 : sigval = 5;  break; /* breakpoint                  */
869
    case 14 : sigval = 5;  break; /* breakpoint                  */
870
    case 15 : sigval = 5;  break; /* breakpoint                  */
871
    case 16 : sigval = 10; break; /* BUS ERROR (alignment)       */
872
    case 17 : sigval = 2;  break; /* INTerrupt                   */
873
    default : sigval = 7;  break; /* "software generated"        */
874
  }
875
  return (sigval);
876
}
877
 
878
/**********************************************/
879
/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
880
/* RETURN NUMBER OF CHARS PROCESSED           */
881
/**********************************************/
882
static int
883
hexToInt(ptr, intValue)
884
     unsigned char **ptr;
885
     int *intValue;
886
{
887
  int numChars = 0;
888
  int hexValue;
889
 
890
  *intValue = 0;
891
  while (**ptr)
892
    {
893
      hexValue = hex(**ptr);
894
      if (hexValue >=0)
895
        {
896
          *intValue = (*intValue <<4) | hexValue;
897
          numChars ++;
898
        }
899
      else
900
        break;
901
      (*ptr)++;
902
    }
903
  return (numChars);
904
}
905
 
906
/*
907
  Table of branch instructions:
908
 
909
  10B6          RTE     return from trap or exception
910
  1FCr          JMP     jump
911
  1ECr          JL      jump and link
912
  7Fxx          BRA     branch
913
  FFxxxxxx      BRA     branch (long)
914
  B09rxxxx      BNEZ    branch not-equal-zero
915
  Br1rxxxx      BNE     branch not-equal
916
  7Dxx          BNC     branch not-condition
917
  FDxxxxxx      BNC     branch not-condition (long)
918
  B0Arxxxx      BLTZ    branch less-than-zero
919
  B0Crxxxx      BLEZ    branch less-equal-zero
920
  7Exx          BL      branch and link
921
  FExxxxxx      BL      branch and link (long)
922
  B0Drxxxx      BGTZ    branch greater-than-zero
923
  B0Brxxxx      BGEZ    branch greater-equal-zero
924
  B08rxxxx      BEQZ    branch equal-zero
925
  Br0rxxxx      BEQ     branch equal
926
  7Cxx          BC      branch condition
927
  FCxxxxxx      BC      branch condition (long)
928
  */
929
 
930
static int
931
isShortBranch(instr)
932
     unsigned char *instr;
933
{
934
  unsigned char instr0 = instr[0] & 0x7F;                /* mask off high bit */
935
 
936
  if (instr0 == 0x10 && instr[1] == 0xB6)       /* RTE */
937
    return 1;           /* return from trap or exception */
938
 
939
  if (instr0 == 0x1E || instr0 == 0x1F)         /* JL or JMP */
940
    if ((instr[1] & 0xF0) == 0xC0)
941
      return 2;                                 /* jump thru a register */
942
 
943
  if (instr0 == 0x7C || instr0 == 0x7D ||       /* BC, BNC, BL, BRA */
944
      instr0 == 0x7E || instr0 == 0x7F)
945
    return 3;                                   /* eight bit PC offset */
946
 
947
  return 0;
948
}
949
 
950
static int
951
isLongBranch(instr)
952
     unsigned char *instr;
953
{
954
  if (instr[0] == 0xFC || instr[0] == 0xFD ||     /* BRA, BNC, BL, BC */
955
      instr[0] == 0xFE || instr[0] == 0xFF)       /* 24 bit relative */
956
    return 4;
957
  if ((instr[0] & 0xF0) == 0xB0)         /* 16 bit relative */
958
    {
959
      if ((instr[1] & 0xF0) == 0x00 ||          /* BNE, BEQ */
960
          (instr[1] & 0xF0) == 0x10)
961
        return 5;
962
      if (instr[0] == 0xB0)      /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ, BEQZ */
963
        if ((instr[1] & 0xF0) == 0x80 || (instr[1] & 0xF0) == 0x90 ||
964
            (instr[1] & 0xF0) == 0xA0 || (instr[1] & 0xF0) == 0xB0 ||
965
            (instr[1] & 0xF0) == 0xC0 || (instr[1] & 0xF0) == 0xD0)
966
          return 6;
967
    }
968
  return 0;
969
}
970
 
971
/* if address is NOT on a 4-byte boundary, or high-bit of instr is zero,
972
   then it's a 2-byte instruction, else it's a 4-byte instruction.  */
973
 
974
#define INSTRUCTION_SIZE(addr) \
975
    ((((int) addr & 2) || (((unsigned char *) addr)[0] & 0x80) == 0) ? 2 : 4)
976
 
977
static int
978
isBranch(instr)
979
     unsigned char *instr;
980
{
981
  if (INSTRUCTION_SIZE(instr) == 2)
982
    return isShortBranch(instr);
983
  else
984
    return isLongBranch(instr);
985
}
986
 
987
static int
988
willBranch(instr, branchCode)
989
     unsigned char *instr;
990
{
991
  switch (branchCode)
992
    {
993
    case 0:      return 0;        /* not a branch */
994
    case 1:     return 1;       /* RTE */
995
    case 2:     return 1;       /* JL or JMP    */
996
    case 3:                     /* BC, BNC, BL, BRA (short) */
997
    case 4:                     /* BC, BNC, BL, BRA (long) */
998
      switch (instr[0] & 0x0F)
999
        {
1000
        case 0xC:               /* Branch if Condition Register */
1001
          return (registers[CBR] != 0);
1002
        case 0xD:               /* Branch if NOT Condition Register */
1003
          return (registers[CBR] == 0);
1004
        case 0xE:               /* Branch and Link */
1005
        case 0xF:               /* Branch (unconditional) */
1006
          return 1;
1007
        default:                /* oops? */
1008
          return 0;
1009
        }
1010
    case 5:                     /* BNE, BEQ */
1011
      switch (instr[1] & 0xF0)
1012
        {
1013
        case 0x00:              /* Branch if r1 equal to r2 */
1014
          return (registers[instr[0] & 0x0F] == registers[instr[1] & 0x0F]);
1015
        case 0x10:              /* Branch if r1 NOT equal to r2 */
1016
          return (registers[instr[0] & 0x0F] != registers[instr[1] & 0x0F]);
1017
        default:                /* oops? */
1018
          return 0;
1019
        }
1020
    case 6:                     /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ */
1021
      switch (instr[1] & 0xF0)
1022
        {
1023
        case 0x80:              /* Branch if reg equal to zero */
1024
          return (registers[instr[1] & 0x0F] == 0);
1025
        case 0x90:              /* Branch if reg NOT equal to zero */
1026
          return (registers[instr[1] & 0x0F] != 0);
1027
        case 0xA0:              /* Branch if reg less than zero */
1028
          return (registers[instr[1] & 0x0F] < 0);
1029
        case 0xB0:              /* Branch if reg greater or equal to zero */
1030
          return (registers[instr[1] & 0x0F] >= 0);
1031
        case 0xC0:              /* Branch if reg less than or equal to zero */
1032
          return (registers[instr[1] & 0x0F] <= 0);
1033
        case 0xD0:              /* Branch if reg greater than zero */
1034
          return (registers[instr[1] & 0x0F] > 0);
1035
        default:                /* oops? */
1036
          return 0;
1037
        }
1038
    default:                    /* oops? */
1039
      return 0;
1040
    }
1041
}
1042
 
1043
static int
1044
branchDestination(instr, branchCode)
1045
     unsigned char *instr;
1046
{
1047
  switch (branchCode) {
1048
  default:
1049
  case 0:                                        /* not a branch */
1050
    return 0;
1051
  case 1:                                       /* RTE */
1052
    return registers[BPC] & ~3;                 /* pop BPC into PC */
1053
  case 2:                                       /* JL or JMP */
1054
    return registers[instr[1] & 0x0F] & ~3;     /* jump thru a register */
1055
  case 3:               /* BC, BNC, BL, BRA (short, 8-bit relative offset) */
1056
    return (((int) instr) & ~3) + ((char) instr[1] << 2);
1057
  case 4:               /* BC, BNC, BL, BRA (long, 24-bit relative offset) */
1058
    return ((int) instr +
1059
            ((((char) instr[1] << 16) | (instr[2] << 8) | (instr[3])) << 2));
1060
  case 5:               /* BNE, BEQ (16-bit relative offset) */
1061
  case 6:               /* BNEZ, BLTZ, BLEZ, BGTZ, BGEZ ,BEQZ (ditto) */
1062
    return ((int) instr + ((((char) instr[2] << 8) | (instr[3])) << 2));
1063
  }
1064
 
1065
  /* An explanatory note: in the last three return expressions, I have
1066
     cast the most-significant byte of the return offset to char.
1067
     What this accomplishes is sign extension.  If the other
1068
     less-significant bytes were signed as well, they would get sign
1069
     extended too and, if negative, their leading bits would clobber
1070
     the bits of the more-significant bytes ahead of them.  There are
1071
     other ways I could have done this, but sign extension from
1072
     odd-sized integers is always a pain. */
1073
}
1074
 
1075
static void
1076
branchSideEffects(instr, branchCode)
1077
     unsigned char *instr;
1078
     int branchCode;
1079
{
1080
  switch (branchCode)
1081
    {
1082
    case 1:                     /* RTE */
1083
      return;                   /* I <THINK> this is already handled... */
1084
    case 2:                     /* JL (or JMP) */
1085
    case 3:                     /* BL (or BC, BNC, BRA) */
1086
    case 4:
1087
      if ((instr[0] & 0x0F) == 0x0E)             /* branch/jump and link */
1088
        registers[R14] = (registers[PC] & ~3) + 4;
1089
      return;
1090
    default:                    /* any other branch has no side effects */
1091
      return;
1092
    }
1093
}
1094
 
1095
static struct STEPPING_CONTEXT {
1096
  int stepping;                 /* true when we've started a single-step */
1097
  unsigned long  target_addr;   /* the instr we're trying to execute */
1098
  unsigned long  target_size;   /* the size of the target instr */
1099
  unsigned long  noop_addr;     /* where we've inserted a no-op, if any */
1100
  unsigned long  trap1_addr;    /* the trap following the target instr */
1101
  unsigned long  trap2_addr;    /* the trap at a branch destination, if any */
1102
  unsigned short noop_save;     /* instruction overwritten by our no-op */
1103
  unsigned short trap1_save;    /* instruction overwritten by trap1 */
1104
  unsigned short trap2_save;    /* instruction overwritten by trap2 */
1105
  unsigned short continue_p;    /* true if NOT returning to gdb after step */
1106
} stepping;
1107
 
1108
/* Function: prepare_to_step
1109
   Called from handle_exception to prepare the user program to single-step.
1110
   Places a trap instruction after the target instruction, with special
1111
   extra handling for branch instructions and for instructions in the
1112
   second half-word of a word.
1113
 
1114
   Returns: True  if we should actually execute the instruction;
1115
            False if we are going to emulate executing the instruction,
1116
            in which case we simply report to GDB that the instruction
1117
            has already been executed.  */
1118
 
1119
#define TRAP1  0x10f1;  /* trap #1 instruction */
1120
#define NOOP   0x7000;  /* noop    instruction */
1121
 
1122
static unsigned short trap1 = TRAP1;
1123
static unsigned short noop  = NOOP;
1124
 
1125
static int
1126
prepare_to_step(continue_p)
1127
     int continue_p;    /* if this isn't REALLY a single-step (see below) */
1128
{
1129
  unsigned long pc = registers[PC];
1130
  int branchCode   = isBranch((unsigned char *) pc);
1131
  unsigned char *p;
1132
 
1133
  /* zero out the stepping context
1134
     (paranoia -- it should already be zeroed) */
1135
  for (p = (unsigned char *) &stepping;
1136
       p < ((unsigned char *) &stepping) + sizeof(stepping);
1137
       p++)
1138
    *p = 0;
1139
 
1140
  if (branchCode != 0)                   /* next instruction is a branch */
1141
    {
1142
      branchSideEffects((unsigned char *) pc, branchCode);
1143
      if (willBranch((unsigned char *)pc, branchCode))
1144
        registers[PC] = branchDestination((unsigned char *) pc, branchCode);
1145
      else
1146
        registers[PC] = pc + INSTRUCTION_SIZE(pc);
1147
      return 0;                  /* branch "executed" -- just notify GDB */
1148
    }
1149
  else if (((int) pc & 2) != 0)          /* "second-slot" instruction */
1150
    {
1151
      /* insert no-op before pc */
1152
      stepping.noop_addr  =  pc - 2;
1153
      stepping.noop_save  = *(unsigned short *) stepping.noop_addr;
1154
      *(unsigned short *) stepping.noop_addr  = noop;
1155
      /* insert trap  after  pc */
1156
      stepping.trap1_addr =  pc + 2;
1157
      stepping.trap1_save = *(unsigned short *) stepping.trap1_addr;
1158
      *(unsigned short *) stepping.trap1_addr = trap1;
1159
    }
1160
  else                                  /* "first-slot" instruction */
1161
    {
1162
      /* insert trap  after  pc */
1163
      stepping.trap1_addr = pc + INSTRUCTION_SIZE(pc);
1164
      stepping.trap1_save = *(unsigned short *) stepping.trap1_addr;
1165
      *(unsigned short *) stepping.trap1_addr = trap1;
1166
    }
1167
  /* "continue_p" means that we are actually doing a continue, and not
1168
     being requested to single-step by GDB.  Sometimes we have to do
1169
     one single-step before continuing, because the PC is on a half-word
1170
     boundary.  There's no way to simply resume at such an address.  */
1171
  stepping.continue_p = continue_p;
1172
  stepping.stepping = 1;                /* starting a single-step */
1173
  return 1;
1174
}
1175
 
1176
/* Function: finish_from_step
1177
   Called from handle_exception to finish up when the user program
1178
   returns from a single-step.  Replaces the instructions that had
1179
   been overwritten by traps or no-ops,
1180
 
1181
   Returns: True  if we should notify GDB that the target stopped.
1182
            False if we only single-stepped because we had to before we
1183
            could continue (ie. we were trying to continue at a
1184
            half-word boundary).  In that case don't notify GDB:
1185
            just "continue continuing".  */
1186
 
1187
static int
1188
finish_from_step()
1189
{
1190
  if (stepping.stepping)        /* anything to do? */
1191
    {
1192
      int continue_p = stepping.continue_p;
1193
      unsigned char *p;
1194
 
1195
      if (stepping.noop_addr)   /* replace instr "under" our no-op */
1196
        *(unsigned short *) stepping.noop_addr  = stepping.noop_save;
1197
      if (stepping.trap1_addr)  /* replace instr "under" our trap  */
1198
        *(unsigned short *) stepping.trap1_addr = stepping.trap1_save;
1199
      if (stepping.trap2_addr)  /* ditto our other trap, if any    */
1200
        *(unsigned short *) stepping.trap2_addr = stepping.trap2_save;
1201
 
1202
      for (p = (unsigned char *) &stepping;     /* zero out the stepping context */
1203
           p < ((unsigned char *) &stepping) + sizeof(stepping);
1204
           p++)
1205
        *p = 0;
1206
 
1207
      return !(continue_p);
1208
    }
1209
  else  /* we didn't single-step, therefore this must be a legitimate stop */
1210
    return 1;
1211
}
1212
 
1213
struct PSWreg {         /* separate out the bit flags in the PSW register */
1214
  int pad1 : 16;
1215
  int bsm  : 1;
1216
  int bie  : 1;
1217
  int pad2 : 5;
1218
  int bc   : 1;
1219
  int sm   : 1;
1220
  int ie   : 1;
1221
  int pad3 : 5;
1222
  int c    : 1;
1223
} *psw;
1224
 
1225
/* Upon entry the value for LR to save has been pushed.
1226
   We unpush that so that the value for the stack pointer saved is correct.
1227
   Upon entry, all other registers are assumed to have not been modified
1228
   since the interrupt/trap occured.  */
1229
 
1230
asm ("
1231
stash_registers:
1232
        push r0
1233
        push r1
1234
        seth r1, #shigh(registers)
1235
        add3 r1, r1, #low(registers)
1236
        pop r0          ; r1
1237
        st r0, @(4,r1)
1238
        pop r0          ; r0
1239
        st r0, @r1
1240
        addi r1, #4     ; only add 4 as subsequent saves are `pre inc'
1241
        st r2, @+r1
1242
        st r3, @+r1
1243
        st r4, @+r1
1244
        st r5, @+r1
1245
        st r6, @+r1
1246
        st r7, @+r1
1247
        st r8, @+r1
1248
        st r9, @+r1
1249
        st r10, @+r1
1250
        st r11, @+r1
1251
        st r12, @+r1
1252
        st r13, @+r1    ; fp
1253
        pop r0          ; lr (r14)
1254
        st r0, @+r1
1255
        st sp, @+r1     ; sp contains right value at this point
1256
        mvfc r0, cr0
1257
        st r0, @+r1     ; cr0 == PSW
1258
        mvfc r0, cr1
1259
        st r0, @+r1     ; cr1 == CBR
1260
        mvfc r0, cr2
1261
        st r0, @+r1     ; cr2 == SPI
1262
        mvfc r0, cr3
1263
        st r0, @+r1     ; cr3 == SPU
1264
        mvfc r0, cr6
1265
        st r0, @+r1     ; cr6 == BPC
1266
        st r0, @+r1     ; PC  == BPC
1267
        mvfaclo r0
1268
        st r0, @+r1     ; ACCL
1269
        mvfachi r0
1270
        st r0, @+r1     ; ACCH
1271
        jmp lr");
1272
 
1273
/* C routine to clean up what stash_registers did.
1274
   It is called after calling stash_registers.
1275
   This is separate from stash_registers as we want to do this in C
1276
   but doing stash_registers in C isn't straightforward.  */
1277
 
1278
static void
1279
cleanup_stash ()
1280
{
1281
  psw = (struct PSWreg *) &registers[PSW];      /* fields of PSW register */
1282
  psw->sm = psw->bsm;           /* fix up pre-trap values of psw fields */
1283
  psw->ie = psw->bie;
1284
  psw->c  = psw->bc;
1285
  registers[CBR] = psw->bc;             /* fix up pre-trap "C" register */
1286
 
1287
#if 0 /* FIXME: Was in previous version.  Necessary?
1288
         (Remember that we use the "rte" insn to return from the
1289
         trap/interrupt so the values of bsm, bie, bc are important.  */
1290
  psw->bsm = psw->bie = psw->bc = 0;     /* zero post-trap values */
1291
#endif
1292
 
1293
  /* FIXME: Copied from previous version.  This can probably be deleted
1294
     since methinks stash_registers has already done this.  */
1295
  registers[PC] = registers[BPC];       /* pre-trap PC */
1296
 
1297
  /* FIXME: Copied from previous version.  Necessary?  */
1298
  if (psw->sm)                  /* copy R15 into (psw->sm ? SPU : SPI) */
1299
    registers[SPU] = registers[R15];
1300
  else
1301
    registers[SPI] = registers[R15];
1302
}
1303
 
1304
asm ("
1305
restore_and_return:
1306
        seth r0, #shigh(registers+8)
1307
        add3 r0, r0, #low(registers+8)
1308
        ld r2, @r0+     ; restore r2
1309
        ld r3, @r0+     ; restore r3
1310
        ld r4, @r0+     ; restore r4
1311
        ld r5, @r0+     ; restore r5
1312
        ld r6, @r0+     ; restore r6
1313
        ld r7, @r0+     ; restore r7
1314
        ld r8, @r0+     ; restore r8
1315
        ld r9, @r0+     ; restore r9
1316
        ld r10, @r0+    ; restore r10
1317
        ld r11, @r0+    ; restore r11
1318
        ld r12, @r0+    ; restore r12
1319
        ld r13, @r0+    ; restore r13
1320
        ld r14, @r0+    ; restore r14
1321
        ld r15, @r0+    ; restore r15
1322
        ld r1, @r0+     ; restore cr0 == PSW
1323
        mvtc r1, cr0
1324
        ld r1, @r0+     ; restore cr1 == CBR (no-op, because it's read only)
1325
        mvtc r1, cr1
1326
        ld r1, @r0+     ; restore cr2 == SPI
1327
        mvtc r1, cr2
1328
        ld r1, @r0+     ; restore cr3 == SPU
1329
        mvtc r1, cr3
1330
        addi r0, #4     ; skip BPC
1331
        ld r1, @r0+     ; restore cr6 (BPC) == PC
1332
        mvtc r1, cr6
1333
        ld r1, @r0+     ; restore ACCL
1334
        mvtaclo r1
1335
        ld r1, @r0+     ; restore ACCH
1336
        mvtachi r1
1337
        seth r0, #shigh(registers)
1338
        add3 r0, r0, #low(registers)
1339
        ld r1, @(4,r0)  ; restore r1
1340
        ld r0, @r0      ; restore r0
1341
        rte");
1342
 
1343
/* General trap handler, called after the registers have been stashed.
1344
   NUM is the trap/exception number.  */
1345
 
1346
static void
1347
process_exception (num)
1348
     int num;
1349
{
1350
  cleanup_stash ();
1351
  asm volatile ("
1352
        seth r1, #shigh(stackPtr)
1353
        add3 r1, r1, #low(stackPtr)
1354
        ld r15, @r1             ; setup local stack (protect user stack)
1355
        mv r0, %0
1356
        bl handle_exception
1357
        bl restore_and_return"
1358
                : : "r" (num) : "r0", "r1");
1359
}
1360
 
1361
void _catchException0 ();
1362
 
1363
asm ("
1364
_catchException0:
1365
        push lr
1366
        bl stash_registers
1367
        ; Note that at this point the pushed value of `lr' has been popped
1368
        ldi r0, #0
1369
        bl process_exception");
1370
 
1371
void _catchException1 ();
1372
 
1373
asm ("
1374
_catchException1:
1375
        push lr
1376
        bl stash_registers
1377
        ; Note that at this point the pushed value of `lr' has been popped
1378
        bl cleanup_stash
1379
        seth r1, #shigh(stackPtr)
1380
        add3 r1, r1, #low(stackPtr)
1381
        ld r15, @r1             ; setup local stack (protect user stack)
1382
        seth r1, #shigh(registers + 21*4) ; PC
1383
        add3 r1, r1, #low(registers + 21*4)
1384
        ld r0, @r1
1385
        addi r0, #-4            ; back up PC for breakpoint trap.
1386
        st r0, @r1              ; FIXME: what about bp in right slot?
1387
        ldi r0, #1
1388
        bl handle_exception
1389
        bl restore_and_return");
1390
 
1391
void _catchException2 ();
1392
 
1393
asm ("
1394
_catchException2:
1395
        push lr
1396
        bl stash_registers
1397
        ; Note that at this point the pushed value of `lr' has been popped
1398
        ldi r0, #2
1399
        bl process_exception");
1400
 
1401
void _catchException3 ();
1402
 
1403
asm ("
1404
_catchException3:
1405
        push lr
1406
        bl stash_registers
1407
        ; Note that at this point the pushed value of `lr' has been popped
1408
        ldi r0, #3
1409
        bl process_exception");
1410
 
1411
void _catchException4 ();
1412
 
1413
asm ("
1414
_catchException4:
1415
        push lr
1416
        bl stash_registers
1417
        ; Note that at this point the pushed value of `lr' has been popped
1418
        ldi r0, #4
1419
        bl process_exception");
1420
 
1421
void _catchException5 ();
1422
 
1423
asm ("
1424
_catchException5:
1425
        push lr
1426
        bl stash_registers
1427
        ; Note that at this point the pushed value of `lr' has been popped
1428
        ldi r0, #5
1429
        bl process_exception");
1430
 
1431
void _catchException6 ();
1432
 
1433
asm ("
1434
_catchException6:
1435
        push lr
1436
        bl stash_registers
1437
        ; Note that at this point the pushed value of `lr' has been popped
1438
        ldi r0, #6
1439
        bl process_exception");
1440
 
1441
void _catchException7 ();
1442
 
1443
asm ("
1444
_catchException7:
1445
        push lr
1446
        bl stash_registers
1447
        ; Note that at this point the pushed value of `lr' has been popped
1448
        ldi r0, #7
1449
        bl process_exception");
1450
 
1451
void _catchException8 ();
1452
 
1453
asm ("
1454
_catchException8:
1455
        push lr
1456
        bl stash_registers
1457
        ; Note that at this point the pushed value of `lr' has been popped
1458
        ldi r0, #8
1459
        bl process_exception");
1460
 
1461
void _catchException9 ();
1462
 
1463
asm ("
1464
_catchException9:
1465
        push lr
1466
        bl stash_registers
1467
        ; Note that at this point the pushed value of `lr' has been popped
1468
        ldi r0, #9
1469
        bl process_exception");
1470
 
1471
void _catchException10 ();
1472
 
1473
asm ("
1474
_catchException10:
1475
        push lr
1476
        bl stash_registers
1477
        ; Note that at this point the pushed value of `lr' has been popped
1478
        ldi r0, #10
1479
        bl process_exception");
1480
 
1481
void _catchException11 ();
1482
 
1483
asm ("
1484
_catchException11:
1485
        push lr
1486
        bl stash_registers
1487
        ; Note that at this point the pushed value of `lr' has been popped
1488
        ldi r0, #11
1489
        bl process_exception");
1490
 
1491
void _catchException12 ();
1492
 
1493
asm ("
1494
_catchException12:
1495
        push lr
1496
        bl stash_registers
1497
        ; Note that at this point the pushed value of `lr' has been popped
1498
        ldi r0, #12
1499
        bl process_exception");
1500
 
1501
void _catchException13 ();
1502
 
1503
asm ("
1504
_catchException13:
1505
        push lr
1506
        bl stash_registers
1507
        ; Note that at this point the pushed value of `lr' has been popped
1508
        ldi r0, #13
1509
        bl process_exception");
1510
 
1511
void _catchException14 ();
1512
 
1513
asm ("
1514
_catchException14:
1515
        push lr
1516
        bl stash_registers
1517
        ; Note that at this point the pushed value of `lr' has been popped
1518
        ldi r0, #14
1519
        bl process_exception");
1520
 
1521
void _catchException15 ();
1522
 
1523
asm ("
1524
_catchException15:
1525
        push lr
1526
        bl stash_registers
1527
        ; Note that at this point the pushed value of `lr' has been popped
1528
        ldi r0, #15
1529
        bl process_exception");
1530
 
1531
void _catchException16 ();
1532
 
1533
asm ("
1534
_catchException16:
1535
        push lr
1536
        bl stash_registers
1537
        ; Note that at this point the pushed value of `lr' has been popped
1538
        ldi r0, #16
1539
        bl process_exception");
1540
 
1541
void _catchException17 ();
1542
 
1543
asm ("
1544
_catchException17:
1545
        push lr
1546
        bl stash_registers
1547
        ; Note that at this point the pushed value of `lr' has been popped
1548
        ldi r0, #17
1549
        bl process_exception");
1550
 
1551
 
1552
/* this function is used to set up exception handlers for tracing and
1553
   breakpoints */
1554
void
1555
set_debug_traps()
1556
{
1557
  /*  extern void remcomHandler(); */
1558
  int i;
1559
 
1560
  for (i = 0; i < 18; i++)               /* keep a copy of old vectors */
1561
    if (save_vectors[i] == 0)            /* only copy them the first time */
1562
      save_vectors[i] = getExceptionHandler (i);
1563
 
1564
  stackPtr  = &remcomStack[STACKSIZE/sizeof(int) - 1];
1565
 
1566
  exceptionHandler (0, _catchException0);
1567
  exceptionHandler (1, _catchException1);
1568
  exceptionHandler (2, _catchException2);
1569
  exceptionHandler (3, _catchException3);
1570
  exceptionHandler (4, _catchException4);
1571
  exceptionHandler (5, _catchException5);
1572
  exceptionHandler (6, _catchException6);
1573
  exceptionHandler (7, _catchException7);
1574
  exceptionHandler (8, _catchException8);
1575
  exceptionHandler (9, _catchException9);
1576
  exceptionHandler (10, _catchException10);
1577
  exceptionHandler (11, _catchException11);
1578
  exceptionHandler (12, _catchException12);
1579
  exceptionHandler (13, _catchException13);
1580
  exceptionHandler (14, _catchException14);
1581
  exceptionHandler (15, _catchException15);
1582
  exceptionHandler (16, _catchException16);
1583
  /*  exceptionHandler (17, _catchException17); */
1584
 
1585
  initialized = 1;
1586
}
1587
 
1588
/* This function will generate a breakpoint exception.  It is used at the
1589
   beginning of a program to sync up with a debugger and can be used
1590
   otherwise as a quick means to stop program execution and "break" into
1591
   the debugger. */
1592
 
1593
#define BREAKPOINT() asm volatile ("    trap #2");
1594
 
1595
void
1596
breakpoint()
1597
{
1598
  if (initialized)
1599
    BREAKPOINT();
1600
}
1601
 
1602
/* STDOUT section:
1603
   Stuff pertaining to simulating stdout by sending chars to gdb to be echoed.
1604
   Functions: gdb_putchar(char ch)
1605
              gdb_puts(char *str)
1606
              gdb_write(char *str, int len)
1607
              gdb_error(char *format, char *parm)
1608
              */
1609
 
1610
/* Function: gdb_putchar(int)
1611
   Make gdb write a char to stdout.
1612
   Returns: the char */
1613
 
1614
static int
1615
gdb_putchar(ch)
1616
     int ch;
1617
{
1618
  char buf[4];
1619
 
1620
  buf[0] = 'O';
1621
  buf[1] = hexchars[ch >> 4];
1622
  buf[2] = hexchars[ch & 0x0F];
1623
  buf[3] = 0;
1624
  putpacket(buf);
1625
  return ch;
1626
}
1627
 
1628
/* Function: gdb_write(char *, int)
1629
   Make gdb write n bytes to stdout (not assumed to be null-terminated).
1630
   Returns: number of bytes written */
1631
 
1632
static int
1633
gdb_write(data, len)
1634
     char *data;
1635
     int len;
1636
{
1637
  char *buf, *cpy;
1638
  int i;
1639
 
1640
  buf = remcomOutBuffer;
1641
  buf[0] = 'O';
1642
  i = 0;
1643
  while (i < len)
1644
    {
1645
      for (cpy = buf+1;
1646
           i < len && cpy < buf + sizeof(remcomOutBuffer) - 3;
1647
           i++)
1648
        {
1649
          *cpy++ = hexchars[data[i] >> 4];
1650
          *cpy++ = hexchars[data[i] & 0x0F];
1651
        }
1652
      *cpy = 0;
1653
      putpacket(buf);
1654
    }
1655
  return len;
1656
}
1657
 
1658
/* Function: gdb_puts(char *)
1659
   Make gdb write a null-terminated string to stdout.
1660
   Returns: the length of the string */
1661
 
1662
static int
1663
gdb_puts(str)
1664
     char *str;
1665
{
1666
  return gdb_write(str, strlen(str));
1667
}
1668
 
1669
/* Function: gdb_error(char *, char *)
1670
   Send an error message to gdb's stdout.
1671
   First string may have 1 (one) optional "%s" in it, which
1672
   will cause the optional second string to be inserted.  */
1673
 
1674
static void
1675
gdb_error(format, parm)
1676
     char * format;
1677
     char * parm;
1678
{
1679
  char buf[400], *cpy;
1680
  int len;
1681
 
1682
  if (remote_debug)
1683
    {
1684
      if (format && *format)
1685
        len = strlen(format);
1686
      else
1687
        return;             /* empty input */
1688
 
1689
      if (parm && *parm)
1690
        len += strlen(parm);
1691
 
1692
      for (cpy = buf; *format; )
1693
        {
1694
          if (format[0] == '%' && format[1] == 's') /* include second string */
1695
            {
1696
              format += 2;          /* advance two chars instead of just one */
1697
              while (parm && *parm)
1698
                *cpy++ = *parm++;
1699
            }
1700
          else
1701
            *cpy++ = *format++;
1702
        }
1703
      *cpy = '\0';
1704
      gdb_puts(buf);
1705
    }
1706
}
1707
 
1708
static unsigned char *
1709
strcpy (unsigned char *dest, const unsigned char *src)
1710
{
1711
  unsigned char *ret = dest;
1712
 
1713
  if (dest && src)
1714
    {
1715
      while (*src)
1716
        *dest++ = *src++;
1717
      *dest = 0;
1718
    }
1719
  return ret;
1720
}
1721
 
1722
static int
1723
strlen (const unsigned char *src)
1724
{
1725
  int ret;
1726
 
1727
  for (ret = 0; *src; src++)
1728
    ret++;
1729
 
1730
  return ret;
1731
}
1732
 
1733
#if 0
1734
void exit (code)
1735
     int code;
1736
{
1737
  _exit (code);
1738
}
1739
 
1740
int atexit (void *p)
1741
{
1742
  return 0;
1743
}
1744
 
1745
void abort (void)
1746
{
1747
  _exit (1);
1748
}
1749
#endif

powered by: WebSVN 2.1.0

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