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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [newlib/] [libgloss/] [mips/] [lsi33k-stub.c] - Blame information for rev 39

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

Line No. Rev Author Line
1 39 lampret
/****************************************************************************
2
 *
3
 *  Module name: remcom.c $
4
 *  Revision: 1.34 $
5
 *  Date: 91/03/09 12:29:49 $
6
 *  Contributor:     Lake Stevens Instrument Division$
7
 *
8
 *  Description:     low level support for gdb debugger. $
9
 *
10
 *  Considerations:  only works on target hardware $
11
 *
12
 *  Written by:      Glenn Engel $
13
 *  ModuleState:     Experimental $
14
 *
15
 *  NOTES:           See Below $
16
 *
17
 *  Modified for SPARC by Stu Grossman, Cygnus Support.
18
 *
19
 *  This code has been extensively tested on the Fujitsu SPARClite demo board.
20
 *
21
 *  To enable debugger support, two things need to happen.  One, a
22
 *  call to set_debug_traps() is necessary in order to allow any breakpoints
23
 *  or error conditions to be properly intercepted and reported to gdb.
24
 *  Two, a breakpoint needs to be generated to begin communication.  This
25
 *  is most easily accomplished by a call to breakpoint().  Breakpoint()
26
 *  simulates a breakpoint by executing a trap #1.
27
 *
28
 *************
29
 *
30
 *    The following gdb commands are supported:
31
 *
32
 * command          function                               Return value
33
 *
34
 *    g             return the value of the CPU registers  hex data or ENN
35
 *    G             set the value of the CPU registers     OK or ENN
36
 *
37
 *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
38
 *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
39
 *
40
 *    c             Resume at current address              SNN   ( signal NN)
41
 *    cAA..AA       Continue at address AA..AA             SNN
42
 *
43
 *    s             Step one instruction                   SNN
44
 *    sAA..AA       Step one instruction from AA..AA       SNN
45
 *
46
 *    k             kill
47
 *
48
 *    ?             What was the last sigval ?             SNN   (signal NN)
49
 *
50
 *    bBB..BB       Set baud rate to BB..BB                OK or BNN, then sets
51
 *                                                         baud rate
52
 *
53
 * All commands and responses are sent with a packet which includes a
54
 * checksum.  A packet consists of
55
 *
56
 * $<packet info>#<checksum>.
57
 *
58
 * where
59
 * <packet info> :: <characters representing the command or response>
60
 * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
61
 *
62
 * When a packet is received, it is first acknowledged with either '+' or '-'.
63
 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
64
 *
65
 * Example:
66
 *
67
 * Host:                  Reply:
68
 * $m0,10#2a               +$00010203040506070809101112131415#42
69
 *
70
 ****************************************************************************/
71
 
72
#include <string.h>
73
#include <signal.h>
74
#include "dbgmon.h"
75
#include "parser.h"
76
#include "ctype.h"
77
 
78
/************************************************************************
79
 *
80
 * external low-level support routines
81
 */
82
 
83
extern putchar();   /* write a single character      */
84
extern getchar();   /* read and return a single char */
85
 
86
/************************************************************************/
87
 
88
/* Stuff for stdio-like gets_debugger_check() */
89
 
90
#define CTRL(x)   ('x'&0x1f)
91
#define DEL       0x7f
92
#define INTR      CTRL(C)
93
#define BELL      0x7
94
#define PROMPT    "? "
95
 
96
#define BUFSIZE 512                              /* Big enough for register packets */
97
 
98
static int initialized = 0;                      /* !0 means we've been initialized */
99
 
100
static char hexchars[]="0123456789abcdef";
101
 
102
extern unsigned int _regs[];                     /* Saved registers from client    */
103
 
104
/* Convert ch from a hex digit to an int */
105
 
106
static int
107
hex(ch)
108
     unsigned char ch;
109
{
110
  if (ch >= 'a' && ch <= 'f')
111
    return ch-'a'+10;
112
  if (ch >= '0' && ch <= '9')
113
    return ch-'0';
114
  if (ch >= 'A' && ch <= 'F')
115
    return ch-'A'+10;
116
  return -1;
117
}
118
 
119
/* scan for the sequence $<data>#<checksum>     */
120
 
121
static void
122
getpacket(buffer)
123
     char *buffer;
124
{
125
  unsigned char checksum;
126
  unsigned char xmitcsum;
127
  int i;
128
  int count;
129
  unsigned char ch;
130
 
131
    /* At this point, the start character ($) has been received through
132
     * the debug monitor parser. Get the remaining characters and
133
     * process them.
134
     */
135
 
136
    checksum = 0;
137
    xmitcsum = -1;
138
    count = 0;
139
 
140
    /* read until a # or end of buffer is found */
141
 
142
    while (count < BUFSIZE)
143
    {
144
        ch = getchar();
145
        if (ch == '#')
146
            break;
147
        checksum = checksum + ch;
148
        buffer[count] = ch;
149
        count = count + 1;
150
    }
151
 
152
    if (count >= BUFSIZE)
153
        buffer[count] = 0;
154
 
155
    if (ch == '#')
156
    {
157
        xmitcsum = hex(getchar()) << 4;
158
        xmitcsum |= hex(getchar());
159
#if 0
160
    /* Humans shouldn't have to figure out checksums to type to it. */
161
        putchar ('+');
162
        return;
163
#endif
164
 
165
        if (checksum != xmitcsum)
166
        {
167
            putchar('-');                      /* failed checksum      */
168
            return;                            /* Back to monitor loop */
169
        }
170
        else
171
        {
172
            putchar('+');                      /* successful transfer */
173
 
174
            /* if a sequence char is present, reply the sequence ID */
175
 
176
            if (buffer[2] == ':')
177
            {
178
                putchar(buffer[0]);
179
                putchar(buffer[1]);
180
 
181
               /* remove sequence chars from buffer */
182
 
183
               count = strlen(buffer);
184
               for (i=3; i <= count; i++)
185
                   buffer[i-3] = buffer[i];
186
            }
187
 
188
            /* Buffer command received- go and process it. */
189
 
190
 
191
        }
192
    }
193
}
194
 
195
 
196
/* send the packet in buffer.  */
197
 
198
static void
199
putpacket(buffer)
200
     unsigned char *buffer;
201
{
202
  unsigned char checksum;
203
  int count;
204
  unsigned char ch;
205
 
206
  /*  $<packet info>#<checksum>. */
207
  do
208
    {
209
      putchar('$');
210
      checksum = 0;
211
      count = 0;
212
 
213
      while (ch = buffer[count])
214
        {
215
          if (! putchar(ch))
216
            return;
217
          checksum += ch;
218
          count += 1;
219
        }
220
 
221
      putchar('#');
222
      putchar(hexchars[checksum >> 4]);
223
      putchar(hexchars[checksum & 0xf]);
224
 
225
    }
226
  while (getchar() != '+');
227
}
228
 
229
static char remcomInBuffer[BUFSIZE];
230
static char remcomOutBuffer[BUFSIZE];
231
 
232
/* Indicate to caller of mem2hex or hex2mem that there has been an error.  */
233
 
234
static volatile int mem_err = 0;
235
 
236
/* Convert the memory pointed to by mem into hex, placing result in buf.
237
 * Return a pointer to the last char put in buf (null), in case of mem fault,
238
 * return 0.
239
 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
240
 * a 0, else treat a fault like any other fault in the stub.
241
 */
242
 
243
static unsigned char *
244
mem2hex(mem, buf, count, may_fault)
245
     unsigned char *mem;
246
     unsigned char *buf;
247
     int count;
248
     int may_fault;
249
{
250
  unsigned char ch;
251
 
252
  while (count-- > 0)
253
    {
254
      ch = *mem++;
255
      if (mem_err)
256
        return 0;
257
      *buf++ = hexchars[ch >> 4];
258
      *buf++ = hexchars[ch & 0xf];
259
    }
260
 
261
  *buf = 0;
262
 
263
  return buf;
264
}
265
 
266
/* convert the hex array pointed to by buf into binary to be placed in mem
267
 * return a pointer to the character AFTER the last byte written */
268
 
269
static char *
270
hex2mem(buf, mem, count, may_fault)
271
     unsigned char *buf;
272
     unsigned char *mem;
273
     int count;
274
     int may_fault;
275
{
276
  int i;
277
  unsigned char ch;
278
 
279
  for (i=0; i<count; i++)
280
    {
281
      ch = hex(*buf++) << 4;
282
      ch |= hex(*buf++);
283
      *mem++ = ch;
284
      if (mem_err)
285
        return 0;
286
    }
287
 
288
  return mem;
289
}
290
 
291
/* This table contains the mapping between SPARC hardware trap types, and
292
   signals, which are primarily what GDB understands.  It also indicates
293
   which hardware traps we need to commandeer when initializing the stub. */
294
 
295
static struct hard_trap_info
296
{
297
  unsigned char tt;       /* Trap type code for SPARClite */
298
  unsigned char signo;    /* Signal that we map this trap into */
299
} hard_trap_info[] = {
300
  {0x06, SIGSEGV},        /* instruction access error */
301
  {0x0a, SIGILL},         /* privileged instruction */
302
  {0x0a, SIGILL},         /* illegal instruction */
303
  {0x0b, SIGEMT},         /* cp disabled */
304
  {0x07, SIGSEGV},        /* data access exception */
305
  {0x09, SIGTRAP},        /* ta 1 - normal breakpoint instruction */
306
  {0, 0}                  /* Must be last */
307
};
308
 
309
/* Convert the SPARC hardware trap type code to a unix signal number. */
310
 
311
static int
312
computeSignal(tt)
313
     int tt;
314
{
315
  struct hard_trap_info *ht;
316
 
317
  for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
318
    if (ht->tt == tt)
319
      return ht->signo;
320
 
321
  return SIGHUP;                /* default for things we don't know about */
322
}
323
 
324
/*
325
 * While we find nice hex chars, build an int.
326
 * Return number of chars processed.
327
 */
328
 
329
static int
330
hexToInt(char **ptr, int *intValue)
331
{
332
  int numChars = 0;
333
  int hexValue;
334
 
335
  *intValue = 0;
336
 
337
  while (**ptr)
338
    {
339
      hexValue = hex(**ptr);
340
      if (hexValue < 0)
341
        break;
342
 
343
      *intValue = (*intValue << 4) | hexValue;
344
      numChars ++;
345
 
346
      (*ptr)++;
347
    }
348
 
349
  return (numChars);
350
}
351
 
352
/* This function lets GDB know that an exception has occured. */
353
 
354
static void
355
debug_handle_exception ()
356
{
357
    int           tt;            /* Trap type */
358
    int           sigval;
359
    char          *ptr;
360
 
361
    tt = (_regs[R_CAUSE] >> 2) & 0x0f;
362
 
363
    /* reply to host that an exception has occurred */
364
    sigval = computeSignal(tt);
365
    ptr = remcomOutBuffer;
366
 
367
    *ptr++ = 'T';
368
    *ptr++ = hexchars[sigval >> 4];
369
    *ptr++ = hexchars[sigval & 0xf];
370
 
371
    *ptr++ = hexchars[R_EPC >> 4];
372
    *ptr++ = hexchars[R_EPC & 0xf];
373
    *ptr++ = ':';
374
    ptr = mem2hex((char *)&_regs[R_EPC], ptr, 4, 0);
375
    *ptr++ = ';';
376
 
377
    *ptr++ = hexchars[R_FP >> 4];
378
    *ptr++ = hexchars[R_FP & 0xf];
379
    *ptr++ = ':';
380
    ptr = mem2hex((char *)&_regs[R_FP], ptr, 4, 0);
381
    *ptr++ = ';';
382
 
383
    *ptr++ = hexchars[R_SP >> 4];
384
    *ptr++ = hexchars[R_SP & 0xf];
385
    *ptr++ = ':';
386
    ptr = mem2hex((char *)&_regs[R_SP], ptr, 4, 0);
387
    *ptr++ = ';';
388
 
389
    *ptr++ = 0;
390
 
391
    putpacket(remcomOutBuffer);
392
 
393
    return;
394
}
395
 
396
 
397
void process_packet()
398
{
399
 
400
    char          *ptr;
401
    int           length;
402
    int           addr;
403
    int           sigval;
404
    int           tt;            /* Trap type */
405
 
406
    remcomOutBuffer[0] = 0;
407
    getpacket(remcomInBuffer);
408
    switch (remcomInBuffer[0])
409
    {
410
 
411
/* Return Last SIGVAL */
412
 
413
case '?':
414
        tt = (_regs[R_CAUSE] >> 2) & 0x0f;
415
        sigval = computeSignal(tt);
416
        remcomOutBuffer[0] = 'S';
417
        remcomOutBuffer[1] = hexchars[sigval >> 4];
418
        remcomOutBuffer[2] = hexchars[sigval & 0xf];
419
        remcomOutBuffer[3] = 0;
420
        break;
421
 
422
        /* toggle debug flag */
423
 
424
        case 'd':
425
            break;
426
 
427
        /* Return the values of the CPU registers */
428
 
429
        case 'g':
430
            ptr = remcomOutBuffer;
431
            ptr = mem2hex((char *)_regs, ptr, 32 * 4, 0);        /* General Purpose Registers */
432
            ptr = mem2hex((char *)&_regs[R_EPC], ptr, 9 * 4, 0); /* CP0 Registers             */
433
            break;
434
 
435
        /*  set the value of the CPU registers - return OK */
436
 
437
        case 'G':
438
            ptr = &remcomInBuffer[1];
439
            hex2mem(ptr, (char *)_regs, 32 * 4, 0);                     /* General Purpose Registers */
440
            hex2mem(ptr + 32 * 4 * 2, (char *)&_regs[R_EPC], 9 * 4, 0); /* CP0 Registers             */
441
            strcpy(remcomOutBuffer,"OK");
442
            break;
443
 
444
        /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
445
 
446
        case 'm':
447
            ptr = &remcomInBuffer[1];
448
            if (hexToInt(&ptr, &addr) && *ptr++ == ',' && hexToInt(&ptr, &length))
449
            {
450
                if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
451
                    break;
452
                strcpy (remcomOutBuffer, "E03");
453
            }
454
            else
455
                strcpy(remcomOutBuffer,"E01");
456
            break;
457
 
458
        /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
459
 
460
        case 'M':
461
            ptr = &remcomInBuffer[1];
462
            if (hexToInt(&ptr, &addr) && *ptr++ == ',' && hexToInt(&ptr, &length) && *ptr++ == ':')
463
            {
464
                if (hex2mem(ptr, (char *)addr, length, 1))
465
                    strcpy(remcomOutBuffer, "OK");
466
                else
467
                    strcpy(remcomOutBuffer, "E03");
468
            }
469
            else
470
                strcpy(remcomOutBuffer, "E02");
471
            break;
472
 
473
        /* cAA..AA    Continue at address AA..AA(optional) */
474
 
475
        case 'c':
476
 
477
        /* try to read optional parameter, pc unchanged if no parm */
478
 
479
            ptr = &remcomInBuffer[1];
480
            if (hexToInt(&ptr, &addr))
481
            {
482
                gdb_go ( addr );
483
            }
484
            else
485
            {
486
                dbg_cont();
487
            }
488
            return;
489
 
490
        /* kill the program */
491
 
492
        case 'k':
493
            break;
494
 
495
        /* Reset */
496
 
497
        case 'r':
498
            break;
499
 
500
        /* switch */
501
 
502
    }
503
 
504
    /* Reply to the request */
505
 
506
    putpacket(remcomOutBuffer);
507
}
508
 
509
 
510
/*
511
 * gets_debugger_check - This is the same as the stdio gets, but we also
512
 *                       check for a leading $ in the buffer. This so we
513
 *                       gracefully handle the GDB protocol packets.
514
 */
515
 
516
char *
517
gets_debugger_check(buf)
518
char *buf;
519
{
520
    register char c;
521
    char *bufp;
522
 
523
    bufp = buf;
524
    for (;;)
525
    {
526
        c = getchar();
527
        switch (c)
528
        {
529
 
530
            /* quote next char */
531
 
532
            case '$':
533
                if ( buf == bufp )
534
                    process_packet();
535
                break;
536
 
537
            case CTRL(V):
538
                c = getchar();
539
                if (bufp < &buf[LINESIZE-3])
540
                {
541
                    rmw_byte (bufp++,c);
542
                    showchar(c);
543
                 }
544
                 else
545
                 {
546
                    putchar(BELL);
547
                 }
548
                 break;
549
 
550
            case '\n':
551
            case '\r':
552
                putchar('\n');
553
                rmw_byte (bufp,0);
554
                return(buf);
555
 
556
            case CTRL(H):
557
            case DEL:
558
                if (bufp > buf)
559
                {
560
                    bufp--;
561
                    putchar(CTRL(H));
562
                    putchar(' ');
563
                    putchar(CTRL(H));
564
                }
565
                break;
566
 
567
            case CTRL(U):
568
                if (bufp > buf)
569
                {
570
                    printf("^U\n%s", PROMPT);
571
                    bufp = buf;
572
                }
573
                break;
574
 
575
            case '\t':
576
                c = ' ';
577
 
578
            default:
579
                /*
580
                 * Make sure there's room for this character
581
                 * plus a trailing \n and 0 byte
582
                 */
583
                if (isprint(c) && bufp < &buf[LINESIZE-3])
584
                {
585
                    rmw_byte ( bufp++, c );
586
                    putchar(c);
587
                }
588
                else
589
                {
590
                    putchar(BELL);
591
                }
592
                break;
593
        }
594
    }
595
}

powered by: WebSVN 2.1.0

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