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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [newlib/] [libgloss/] [hp74x/] [pa_stub.c] - Blame information for rev 1771

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

Line No. Rev Author Line
1 39 lampret
/* -*-C-*-
2
*******************************************************************************
3
*
4
* File:         pa_stub.c
5
* RCS:          $Header: /home/marcus/revision_ctrl_test/oc_cvs/cvs/or1k/newlib/libgloss/hp74x/pa_stub.c,v 1.1.1.1 2000-06-10 01:29:59 lampret Exp $
6
* Description:  main routines for PA RISC monitor stub
7
* Author:       Robert Quist
8
* Created:      Mon Nov  1 10:00:36 1993
9
* Modified:     Fri Nov 12 15:14:23 1993 (Robert Quist) quist@hpfcrdq
10
* Language:     C
11
* Package:      N/A
12
* Status:       Experimental (Do Not Distribute)
13
*
14
*******************************************************************************
15
*/
16
 
17
/****************************************************************************
18
 
19
                THIS SOFTWARE IS NOT COPYRIGHTED
20
 
21
   HP offers the following for use in the public domain.  HP makes no
22
   warranty with regard to the software or it's performance and the
23
   user accepts the software "AS IS" with all faults.
24
 
25
   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
26
   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
27
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
28
 
29
****************************************************************************/
30
 
31
/****************************************************************************
32
 *
33
 *  Description:     low level support for gdb debugger. $
34
 *
35
 *  Considerations:  only works on target hardware $
36
 *
37
 *  NOTES:           See Below $
38
 *
39
 *    To enable debugger support, two things need to happen.
40
 *
41
 *  One, a call to set_debug_traps() is necessary in order to allow
42
 *  any breakpoints or error conditions to be properly intercepted and
43
 *  reported to gdb.
44
 *
45
 *  Two, a breakpoint needs to be generated to begin communication.
46
 *  This is most easily accomplished by a call to breakpoint().
47
 *  breakpoint() simulates a breakpoint
48
 
49
 
50
 *************
51
 *
52
 *    The following gdb commands are supported:
53
 *
54
 * command          function                               Return value
55
 *
56
 *    g             return the value of the CPU registers  hex data or ENN
57
 *    G             set the value of the CPU registers     OK or ENN
58
 *
59
 *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
60
 *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
61
 *
62
 *    c             Resume at current address              SNN   ( signal NN)
63
 *    cAA..AA       Continue at address AA..AA             SNN
64
 *
65
 *    s             Step one instruction                   SNN
66
 *    sAA..AA       Step one instruction from AA..AA       SNN
67
 *
68
 *    k             kill
69
 *
70
 *    ?             What was the last sigval ?             SNN   (signal NN)
71
 *
72
 *    bBB..BB       Set baud rate to BB..BB                OK or BNN, then sets
73
 *                                                         baud rate
74
 *
75
 
76
 ************
77
 * All commands and responses are sent with a packet which includes a
78
 * checksum.  A packet consists of :
79
 *
80
 * $<packet info>#<checksum>.
81
 *
82
 * where
83
 * <packet info> :: <characters representing the command or response>
84
 * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
85
 *
86
 * When a packet is received, it is first acknowledged with either '+' or '-'.
87
 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
88
 *
89
 * Example:
90
 *
91
 * Host:                  Reply:
92
 * $m0,10#2a               +$00010203040506070809101112131415#42
93
 *
94
 ****************************************************************************/
95
#include <signal.h>
96
#include "hppa-defs.h"
97
 
98
/************************************************************************
99
 *
100
 * external low-level support
101
 */
102
#define OPT_PDC_CACHE        5
103
#define OPT_PDC_ADD_VALID   12
104
#define PGZ_MEM_PDC     0x0388  /* location of PDC_ENTRY in memory    */
105
#define CALL_PDC        (*(int (*)())((int *)(*((int *)PGZ_MEM_PDC))))
106
 
107
extern putDebugChar();   /* write a single character      */
108
extern getDebugChar();   /* read and return a single char */
109
extern FICE();           /* flush i cache entry */
110
extern INLINE_BREAK();   /* break for user call */
111
 
112
#define RADDR_ALIGN(s,r) (s = ((unsigned int *) ((((int) r ) + 7 ) & 0xFFFFFFF8)))
113
 
114
/************************************************************************/
115
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
116
/* at least NUMREGBYTES*2 are needed for register packets */
117
 
118
#define BUFMAX 2048
119
 
120
#define NUMGPRS   32
121
#define NUMSRS     8
122
#define NUMCRS    32
123
#define NUMSPCLS   3
124
#define NUMFPRS   32
125
 
126
#define NUMGPRBYTES     4
127
#define NUMSRBYTES      4
128
#define NUMCRBYTES      4
129
#define NUMSPCLBYTES    4
130
#define NUMFPRBYTES     8
131
 
132
/* Number of bytes of registers.  */
133
#define NUMREGBYTES \
134
        (  (NUMGPRS * NUMGPRBYTES) \
135
         + (NUMSRS * NUMSRBYTES)   \
136
         + (NUMCRS * NUMCRBYTES)   \
137
         + (NUMSPCLS * NUMSPCLBYTES) \
138
         + (NUMFPRS * NUMFPRBYTES) \
139
        )
140
 
141
 
142
enum regnames   {GR0,  GR1,  GR2,  GR3,  GR4,  GR5,  GR6,  GR7,
143
                 GR8,  GR9,  GR10, GR11, GR12, GR13, GR14, GR15,
144
                 GR16, GR17, GR18, GR19, GR20, GR21, GR22, GR23,
145
                 GR24, GR25, GR26, GR27, GR28, GR29, GR30, GR31,
146
 
147
                 SR0,  SR1,  SR2,  SR3,  SR4,  SR5,  SR6,  SR7,
148
 
149
                 CR0,  CR1,  CR2,  CR3,  CR4,  CR5,  CR6,  CR7,
150
                 CR8,  CR9,  CR10, CR11, CR12, CR13, CR14, CR15,
151
                 CR16, CR17H,CR18H,CR19, CR20, CR21, CR22, CR23,
152
                 CR24, CR25, CR26, CR27, CR28, CR29, CR30, CR31,
153
 
154
                 CR17T,CR18T,CPUD0 };
155
 
156
enum fregnames  {FPR0,  FPR1,  FPR2,  FPR3,  FPR4,  FPR5,  FPR6,  FPR7,
157
                 FPR8,  FPR9,  FPR10, FPR11, FPR12, FPR13, FPR14, FPR15,
158
                 FPR16, FPR17, FPR18, FPR19, FPR20, FPR21, FPR22, FPR23,
159
                 FPR24, FPR25, FPR26, FPR27, FPR28, FPR29, FPR30, FPR31 };
160
 
161
#define PC  CR18H
162
#define NPC CR18T
163
#define SP  GR30
164
 
165
struct registers {
166
       int intregs[NUMGPRS + NUMSRS + NUMCRS + NUMSPCLS];
167
       int fpregs [NUMFPRS * 2];
168
                 };
169
/* Global Variables */
170
 
171
static int initialized = 0;      /* !0 means we've been initialized */
172
static unsigned char hexchars[]="0123456789abcdef";
173
static unsigned char remcomInBuffer[BUFMAX];
174
static unsigned char remcomOutBuffer[BUFMAX];
175
static unsigned int  i_cache_params[6];
176
 
177
/* This table contains the mapping between PA hardware exception
178
   types, and signals, which are primarily what GDB understands.  It also
179
   indicates which hardware traps we need to commandeer when initializing
180
   the stub.
181
 
182
   The only two currently used are Recovery counter (single stepping)
183
   and Break trap ( break points ).
184
*/
185
 
186
static struct hard_trap_info
187
{
188
  unsigned char tt;             /* Trap number for PA-RISC */
189
  unsigned char signo;          /* Signal that we map this trap into */
190
} hard_trap_info[] = {
191
/* 1  High priority machine check */
192
/* 2  Power failure interrupt*/
193
/* 3  Recovery counter -- init */
194
/* 4  External interrupt */
195
/* 5  Low priority machine check */
196
  {6, SIGSEGV},                 /* Instruction TLB miss/page fault */
197
  {7, SIGSEGV},                 /* Memory protection */
198
  {8, SIGILL},                  /* Illegal instruction */
199
  {9, SIGTRAP},                 /* Break instruction -- init */
200
  {10,SIGILL},                  /* Privileged instruction */
201
  {11,SIGILL},                  /* Privileged register */
202
  {12,SIGUSR1},                 /* Overflow */
203
  {13,SIGUSR2},                 /* Conditional */
204
  {14,SIGEMT},                  /* Assist Exception */
205
  {15,SIGSEGV},                 /* Data TLB miss/page fault */
206
  {16,SIGSEGV},                 /* Non-access Instruction TLB miss */
207
  {17,SIGSEGV},                 /* Non-access Data TLB miss/page fault */
208
  {18,SIGSEGV},                 /* Data memory protection/ unaligned data reference */
209
  {19,SIGTRAP},                 /* Data memory break */
210
  {20,SIGSEGV},                 /* TLB dirty bit */
211
  {21,SIGSEGV},                 /* Page reference */
212
  {22,SIGEMT},                  /* Assist emulation */
213
  {23,SIGILL},                  /* Higher-privilege */
214
  {24,SIGILL},                  /* Lower-privilege */
215
  {25,SIGTRAP},                 /* Taken branch */
216
  {0, 0}                  /* Must be last */
217
};
218
 
219
/* Functions */
220
/*========================================================================== */
221
 
222
/* Convert ch from a hex digit to an int */
223
 
224
static int
225
hex(ch)
226
     unsigned char ch;
227
{
228
  if (ch >= 'a' && ch <= 'f')
229
    return ch-'a'+10;
230
  if (ch >= '0' && ch <= '9')
231
    return ch-'0';
232
  if (ch >= 'A' && ch <= 'F')
233
    return ch-'A'+10;
234
  return -1;
235
}
236
 
237
/* scan for the sequence $<data>#<checksum>     */
238
 
239
static void
240
getpacket(buffer)
241
     char *buffer;
242
{
243
  unsigned char checksum;
244
  unsigned char xmitcsum;
245
  int i;
246
  int count;
247
  unsigned char ch;
248
 
249
  do
250
    {
251
      /* wait around for the start character, ignore all other characters */
252
      strobe();
253
      while ((ch = getDebugChar()) != '$') ;
254
 
255
      checksum = 0;
256
      xmitcsum = -1;
257
 
258
      count = 0;
259
 
260
      /* now, read until a # or end of buffer is found */
261
      while (count < BUFMAX)
262
        {
263
          ch = getDebugChar();
264
          if (ch == '#')
265
            break;
266
          checksum = checksum + ch;
267
          buffer[count] = ch;
268
          count = count + 1;
269
        }
270
 
271
      if (count >= BUFMAX)
272
        continue;
273
 
274
      buffer[count] = 0;
275
 
276
      if (ch == '#')
277
        {
278
          xmitcsum = hex(getDebugChar()) << 4;
279
          xmitcsum |= hex(getDebugChar());
280
 
281
#if TESTING
282
          /* Humans shouldn't have to figure out checksums to type to it. */
283
          putDebugChar ('+');
284
          return;
285
#endif
286
          if (checksum != xmitcsum)
287
            putDebugChar('-');  /* failed checksum */
288
          else
289
            {
290
              putDebugChar('+'); /* successful transfer */
291
              /* if a sequence char is present, reply the sequence ID */
292
              if (buffer[2] == ':')
293
                {
294
                  putDebugChar(buffer[0]);
295
                  putDebugChar(buffer[1]);
296
                  /* remove sequence chars from buffer */
297
                  count = strlen(buffer);
298
                  for (i=3; i <= count; i++)
299
                    buffer[i-3] = buffer[i];
300
                }
301
            }
302
        }
303
    }
304
  while (checksum != xmitcsum);
305
}
306
 
307
/* send the packet in buffer.  */
308
 
309
static void
310
putpacket(buffer)
311
     unsigned char *buffer;
312
{
313
  unsigned char checksum;
314
  int count;
315
  unsigned char ch;
316
 
317
  /*  $<packet info>#<checksum>. */
318
 
319
  do
320
    {
321
      putDebugChar('$');
322
      checksum = 0;
323
      count = 0;
324
 
325
      while (ch = buffer[count])
326
        {
327
          if (! putDebugChar(ch))
328
            return;
329
          checksum += ch;
330
          count += 1;
331
        }
332
 
333
      putDebugChar('#');
334
      putDebugChar(hexchars[checksum >> 4]);
335
      putDebugChar(hexchars[checksum & 0xf]);
336
      } while (getDebugChar() != '+');
337
}
338
 
339
/* Convert the memory pointed to by mem into hex, placing result in buf.
340
 * Return a pointer to the last char put in buf (null), in case of mem fault,
341
 * return 0.
342
 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
343
 * a 0, else treat a fault like any other fault in the stub.
344
 */
345
 
346
static unsigned char *
347
mem2hex(mem, buf, count, may_fault)
348
     unsigned char *mem;
349
     unsigned char *buf;
350
     int count;
351
     int may_fault;
352
{
353
  unsigned char ch;
354
  int           check_addr,
355
                new_addr;
356
 
357
  check_addr = 0;
358
 
359
  while (count-- > 0)
360
    {
361
      if (may_fault)
362
      { new_addr = ((int) (mem+3)) & 0xFFFFFFF8;
363
        if (new_addr != check_addr)
364
        { check_addr = new_addr;
365
          if (pdc_call(OPT_PDC_ADD_VALID,0,check_addr)) return 0;
366
        }
367
      }
368
      ch = *mem++;
369
      *buf++ = hexchars[ch >> 4];
370
      *buf++ = hexchars[ch & 0xf];
371
    }
372
 
373
  *buf = 0;
374
 
375
  return buf;
376
}
377
 
378
/* convert the hex array pointed to by buf into binary to be placed in mem
379
 * return a pointer to the character AFTER the last byte written */
380
 
381
static unsigned char *
382
hex2mem(buf, mem, count, may_fault)
383
     unsigned char *buf;
384
     unsigned char *mem;
385
     int count;
386
     int may_fault;
387
{
388
  int          i;
389
  unsigned int ch;
390
  int          check_addr,
391
               new_addr;
392
 
393
  check_addr = 0;
394
 
395
  for (i=0; i<count; i++)
396
    {
397
      ch = hex(*buf++) << 4;
398
      ch |= hex(*buf++);
399
      if (may_fault)
400
      { new_addr = ((int)(mem+3)) & 0xFFFFFFF8;
401
        if (new_addr != check_addr)
402
        { check_addr = new_addr;
403
          if (pdc_call(OPT_PDC_ADD_VALID,0,check_addr)) return 0;
404
        }
405
      }
406
      *mem++ = ch;
407
    }
408
 
409
  return mem;
410
}
411
 
412
/* Set up exception handlers for traceing and breakpoints */
413
 
414
void
415
set_debug_traps()
416
{
417
  unsigned int  R_addr[33];
418
  unsigned int  *Raddr_ptr;
419
 
420
  setup_vectors();
421
 
422
  /* get cache params for use by flush_i_cache */
423
  RADDR_ALIGN(Raddr_ptr,R_addr);
424
 
425
  if (pdc_call(OPT_PDC_CACHE,0,Raddr_ptr,0))
426
    i_cache_params[0] = -1;
427
  else
428
    i_cache_params[0] = R_addr[0];
429
 
430
  i_cache_params[1] = Raddr_ptr[1];
431
  i_cache_params[2] = Raddr_ptr[2];
432
  i_cache_params[3] = Raddr_ptr[3];
433
  i_cache_params[4] = Raddr_ptr[4];
434
  i_cache_params[5] = Raddr_ptr[5];
435
 
436
  /* In case GDB is started before us, ack any packets (presumably
437
     "$?#xx") sitting there.  */
438
 
439
  putDebugChar ('+');
440
 
441
  initialized = 1;
442
}
443
 
444
 
445
/* Convert the PA-RISC hardware trap number to a unix signal number. */
446
 
447
static int
448
computeSignal(tt)
449
     int tt;
450
{
451
  struct hard_trap_info *ht;
452
 
453
  for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
454
    if (ht->tt == tt)
455
      return ht->signo;
456
 
457
  return SIGHUP;                /* default for things we don't know about */
458
}
459
 
460
/*
461
 * While we find nice hex chars, build an int.
462
 * Return number of chars processed.
463
 */
464
 
465
static int
466
hexToInt(ptr, intValue)
467
     unsigned char **ptr;
468
     int *intValue;
469
{
470
  int numChars = 0;
471
  int hexValue;
472
 
473
  *intValue = 0;
474
 
475
  while (**ptr)
476
    {
477
      hexValue = hex(**ptr);
478
      if (hexValue < 0)
479
        break;
480
 
481
      *intValue = (*intValue << 4) | hexValue;
482
      numChars ++;
483
 
484
      (*ptr)++;
485
    }
486
 
487
  return (numChars);
488
}
489
 
490
void
491
flush_i_cache()
492
 
493
{
494
  unsigned int addr,count,loop;
495
 
496
  if (i_cache_params[0] <= 0) return;
497
 
498
  addr = i_cache_params[2];
499
  for (count = 0; count < i_cache_params[4]; count++)
500
    { for ( loop = 0; loop < i_cache_params[5]; loop++) FICE(addr);
501
      addr = addr + i_cache_params[3];
502
    }
503
}
504
 
505
/*
506
 * This function does all command procesing for interfacing to gdb.
507
   return of 0 will execute DEBUG_GO (continue)
508
   return of 1 will execute DEBUG_SS (single step)
509
 */
510
 
511
int
512
handle_exception (registers,tt)
513
  unsigned long *registers;
514
  int  tt;                      /* Trap type */
515
{
516
  int sigval;
517
  int addr;
518
  int length;
519
  unsigned char *ptr;
520
 
521
  /* reply to host that an exception has occurred */
522
  sigval = computeSignal(tt);
523
  ptr = remcomOutBuffer;
524
 
525
  *ptr++ = 'T';
526
  *ptr++ = hexchars[sigval >> 4];
527
  *ptr++ = hexchars[sigval & 0xf];
528
 
529
/* could be lots of stuff here like PC and SP registers */
530
 
531
  *ptr++ = 0;
532
 
533
  putpacket(remcomOutBuffer);
534
 
535
  while (1)
536
    {
537
      remcomOutBuffer[0] = 0;
538
 
539
      getpacket(remcomInBuffer);
540
      switch (remcomInBuffer[0])
541
        {
542
        case '?':
543
          remcomOutBuffer[0] = 'S';
544
          remcomOutBuffer[1] = hexchars[sigval >> 4];
545
          remcomOutBuffer[2] = hexchars[sigval & 0xf];
546
          remcomOutBuffer[3] = 0;
547
          break;
548
 
549
        case 'd':
550
          /* toggle debug flag */
551
          led_putnum (16);
552
          break;
553
 
554
        case 'g':               /* return the value of the CPU registers */
555
          {
556
            ptr = remcomOutBuffer;
557
            /* GR0..GR31 SR0..SR7 CR0..CR31 specials */
558
            ptr = mem2hex((char *)registers, ptr, NUMREGBYTES, 0);
559
            /* need to add floating point registers */
560
          }
561
          break;
562
 
563
        case 'G':          /* set the value of the CPU registers - return OK */
564
          {
565
            ptr = &remcomInBuffer[1];
566
            /* GR0..GR31 SR0..SR7 CR0..CR31 specials */
567
            hex2mem(ptr, (char *)registers, NUMREGBYTES, 0);
568
            strcpy(remcomOutBuffer,"OK 1");
569
          }
570
          break;
571
 
572
        case 'm':         /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
573
          /* Try to read %x,%x.  */
574
 
575
          ptr = &remcomInBuffer[1];
576
 
577
          if (hexToInt(&ptr, &addr)
578
              && *ptr++ == ','
579
              && hexToInt(&ptr, &length))
580
            {
581
              if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
582
                break;
583
 
584
              strcpy (remcomOutBuffer, "E03");
585
            }
586
          else
587
            strcpy(remcomOutBuffer,"E01");
588
          break;
589
 
590
        case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
591
          /* Try to read '%x,%x:'.  */
592
 
593
          ptr = &remcomInBuffer[1];
594
 
595
          if (hexToInt(&ptr, &addr)
596
              && *ptr++ == ','
597
              && hexToInt(&ptr, &length)
598
              && *ptr++ == ':')
599
            {
600
              if (hex2mem(ptr, (char *)addr, length, 1))
601
                strcpy(remcomOutBuffer, "OK");
602
              else
603
                strcpy(remcomOutBuffer, "E03");
604
            }
605
          else
606
            strcpy(remcomOutBuffer, "E02");
607
          break;
608
 
609
        case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
610
          /* try to read optional parameter, pc unchanged if no parm */
611
 
612
          ptr = &remcomInBuffer[1];
613
          if (hexToInt(&ptr, &addr))
614
            {
615
              registers[PC] = addr;
616
              registers[NPC] = addr + 4;
617
            }
618
 
619
/* Need to flush the instruction cache here, as we may have deposited a
620
   breakpoint, and the icache probably has no way of knowing that a data ref to
621
   some location may have changed something that is in the instruction cache.
622
 */
623
 
624
          flush_i_cache();
625
          return 0;              /* execute GO */
626
 
627
          /* kill the program */
628
        case 'k' :              /* do nothing */
629
          break;
630
 
631
        case 's' :              /* single step */
632
          /* try to read optional parameter, pc unchanged if no parm */
633
 
634
          ptr = &remcomInBuffer[1];
635
          if (hexToInt(&ptr, &addr))
636
            {
637
              registers[PC] = addr;
638
              registers[NPC] = addr + 4;
639
            }
640
/* Need to flush the instruction cache here, as we may have deposited a
641
   breakpoint, and the icache probably has no way of knowing that a data ref to
642
   some location may have changed something that is in the instruction cache.
643
 */
644
          flush_i_cache();
645
          return 1;             /* execute Single Step */
646
          break;
647
 
648
#if TESTING1
649
        case 't':               /* Test feature */
650
          break;
651
#endif
652
        case 'r':               /* Reset */
653
          break;
654
 
655
#if TESTING2
656
Disabled until we can unscrew this properly
657
 
658
        case 'b':         /* bBB...  Set baud rate to BB... */
659
          {
660
            int baudrate;
661
            extern void set_timer_3();
662
 
663
            ptr = &remcomInBuffer[1];
664
            if (!hexToInt(&ptr, &baudrate))
665
              {
666
                strcpy(remcomOutBuffer,"B01");
667
                break;
668
              }
669
 
670
            /* Convert baud rate to uart clock divider */
671
            switch (baudrate)
672
              {
673
              case 38400:
674
                baudrate = 16;
675
                break;
676
              case 19200:
677
                baudrate = 33;
678
                break;
679
              case 9600:
680
                baudrate = 65;
681
                break;
682
              default:
683
                strcpy(remcomOutBuffer,"B02");
684
                goto x1;
685
              }
686
 
687
            putpacket("OK 2");  /* Ack before changing speed */
688
            set_timer_3(baudrate); /* Set it */
689
          }
690
x1:       break;
691
#endif
692
        }                       /* switch */
693
 
694
      /* reply to the request */
695
      putpacket(remcomOutBuffer);
696
    }
697
  print ("\r\nEscaped handle_exception\r\n");
698
}

powered by: WebSVN 2.1.0

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