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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [sparcl-stub.c] - Blame information for rev 105

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

Line No. Rev Author Line
1 104 markom
/****************************************************************************
2
 
3
                THIS SOFTWARE IS NOT COPYRIGHTED
4
 
5
   HP offers the following for use in the public domain.  HP makes no
6
   warranty with regard to the software or it's performance and the
7
   user accepts the software "AS IS" with all faults.
8
 
9
   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
10
   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
11
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12
 
13
****************************************************************************/
14
 
15
/****************************************************************************
16
 *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
17
 *
18
 *  Module name: remcom.c $
19
 *  Revision: 1.34 $
20
 *  Date: 91/03/09 12:29:49 $
21
 *  Contributor:     Lake Stevens Instrument Division$
22
 *
23
 *  Description:     low level support for gdb debugger. $
24
 *
25
 *  Considerations:  only works on target hardware $
26
 *
27
 *  Written by:      Glenn Engel $
28
 *  ModuleState:     Experimental $
29
 *
30
 *  NOTES:           See Below $
31
 *
32
 *  Modified for SPARC by Stu Grossman, Cygnus Support.
33
 *  Based on sparc-stub.c, it's modified for SPARClite Debug Unit hardware
34
 *  breakpoint support to create sparclite-stub.c, by Kung Hsu, Cygnus Support.
35
 *
36
 *  This code has been extensively tested on the Fujitsu SPARClite demo board.
37
 *
38
 *  To enable debugger support, two things need to happen.  One, a
39
 *  call to set_debug_traps() is necessary in order to allow any breakpoints
40
 *  or error conditions to be properly intercepted and reported to gdb.
41
 *  Two, a breakpoint needs to be generated to begin communication.  This
42
 *  is most easily accomplished by a call to breakpoint().  Breakpoint()
43
 *  simulates a breakpoint by executing a trap #1.
44
 *
45
 *************
46
 *
47
 *    The following gdb commands are supported:
48
 *
49
 * command          function                               Return value
50
 *
51
 *    g             return the value of the CPU registers  hex data or ENN
52
 *    G             set the value of the CPU registers     OK or ENN
53
 *    P             set the value of a single CPU register OK or ENN
54
 *
55
 *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
56
 *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
57
 *
58
 *    c             Resume at current address              SNN   ( signal NN)
59
 *    cAA..AA       Continue at address AA..AA             SNN
60
 *
61
 *    s             Step one instruction                   SNN
62
 *    sAA..AA       Step one instruction from AA..AA       SNN
63
 *
64
 *    k             kill
65
 *
66
 *    ?             What was the last sigval ?             SNN   (signal NN)
67
 *
68
 * All commands and responses are sent with a packet which includes a
69
 * checksum.  A packet consists of
70
 *
71
 * $<packet info>#<checksum>.
72
 *
73
 * where
74
 * <packet info> :: <characters representing the command or response>
75
 * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
76
 *
77
 * When a packet is received, it is first acknowledged with either '+' or '-'.
78
 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
79
 *
80
 * Example:
81
 *
82
 * Host:                  Reply:
83
 * $m0,10#2a               +$00010203040506070809101112131415#42
84
 *
85
 ****************************************************************************/
86
 
87
#include <string.h>
88
#include <signal.h>
89
#include <sparclite.h>
90
 
91
/************************************************************************
92
 *
93
 * external low-level support routines
94
 */
95
 
96
extern void putDebugChar (int c); /* write a single character      */
97
extern int getDebugChar (void); /* read and return a single char */
98
 
99
/************************************************************************/
100
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
101
/* at least NUMREGBYTES*2 are needed for register packets */
102
#define BUFMAX 2048
103
 
104
static int initialized = 0;      /* !0 means we've been initialized */
105
 
106
extern void breakinst ();
107
static void set_mem_fault_trap (int enable);
108
static void get_in_break_mode (void);
109
 
110
static const char hexchars[]="0123456789abcdef";
111
 
112
#define NUMREGS 80 
113
 
114
/* Number of bytes of registers.  */
115
#define NUMREGBYTES (NUMREGS * 4)
116
enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
117
                 O0, O1, O2, O3, O4, O5, SP, O7,
118
                 L0, L1, L2, L3, L4, L5, L6, L7,
119
                 I0, I1, I2, I3, I4, I5, FP, I7,
120
 
121
                 F0, F1, F2, F3, F4, F5, F6, F7,
122
                 F8, F9, F10, F11, F12, F13, F14, F15,
123
                 F16, F17, F18, F19, F20, F21, F22, F23,
124
                 F24, F25, F26, F27, F28, F29, F30, F31,
125
                 Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR,
126
                 DIA1, DIA2, DDA1, DDA2, DDV1, DDV2, DCR, DSR };
127
 
128
/***************************  ASSEMBLY CODE MACROS *************************/
129
/*                                                                         */
130
 
131
extern void trap_low();
132
 
133
/* Create private copies of common functions used by the stub.  This prevents
134
   nasty interactions between app code and the stub (for instance if user steps
135
   into strlen, etc..) */
136
 
137
static char *
138
strcpy (char *dst, const char *src)
139
{
140
  char *retval = dst;
141
 
142
  while ((*dst++ = *src++) != '\000');
143
 
144
  return retval;
145
}
146
 
147
static void *
148
memcpy (void *vdst, const void *vsrc, int n)
149
{
150
  char *dst = vdst;
151
  const char *src = vsrc;
152
  char *retval = dst;
153
 
154
  while (n-- > 0)
155
    *dst++ = *src++;
156
 
157
  return retval;
158
}
159
 
160
asm("
161
        .reserve trapstack, 1000 * 4, \"bss\", 8
162
 
163
        .data
164
        .align  4
165
 
166
in_trap_handler:
167
        .word   0
168
 
169
        .text
170
        .align 4
171
 
172
! This function is called when any SPARC trap (except window overflow or
173
! underflow) occurs.  It makes sure that the invalid register window is still
174
! available before jumping into C code.  It will also restore the world if you
175
! return from handle_exception.
176
!
177
! On entry, trap_low expects l1 and l2 to contain pc and npc respectivly.
178
! Register usage throughout the routine is as follows:
179
!
180
!       l0 - psr
181
!       l1 - pc
182
!       l2 - npc
183
!       l3 - wim
184
!       l4 - scratch and y reg
185
!       l5 - scratch and tbr
186
!       l6 - unused
187
!       l7 - unused
188
 
189
        .globl _trap_low
190
_trap_low:
191
        mov     %psr, %l0
192
        mov     %wim, %l3
193
 
194
        srl     %l3, %l0, %l4           ! wim >> cwp
195
        cmp     %l4, 1
196
        bne     window_fine             ! Branch if not in the invalid window
197
        nop
198
 
199
! Handle window overflow
200
 
201
        mov     %g1, %l4                ! Save g1, we use it to hold the wim
202
        srl     %l3, 1, %g1             ! Rotate wim right
203
        tst     %g1
204
        bg      good_wim                ! Branch if new wim is non-zero
205
        nop
206
 
207
! At this point, we need to bring a 1 into the high order bit of the wim.
208
! Since we don't want to make any assumptions about the number of register
209
! windows, we figure it out dynamically so as to setup the wim correctly.
210
 
211
        not     %g1                     ! Fill g1 with ones
212
        mov     %g1, %wim               ! Fill the wim with ones
213
        nop
214
        nop
215
        nop
216
        mov     %wim, %g1               ! Read back the wim
217
        inc     %g1                     ! Now g1 has 1 just to left of wim
218
        srl     %g1, 1, %g1             ! Now put 1 at top of wim
219
        mov     %g0, %wim               ! Clear wim so that subsequent save
220
        nop                             !  won't trap
221
        nop
222
        nop
223
 
224
good_wim:
225
        save    %g0, %g0, %g0           ! Slip into next window
226
        mov     %g1, %wim               ! Install the new wim
227
 
228
        std     %l0, [%sp + 0 * 4]      ! save L & I registers
229
        std     %l2, [%sp + 2 * 4]
230
        std     %l4, [%sp + 4 * 4]
231
        std     %l6, [%sp + 6 * 4]
232
 
233
        std     %i0, [%sp + 8 * 4]
234
        std     %i2, [%sp + 10 * 4]
235
        std     %i4, [%sp + 12 * 4]
236
        std     %i6, [%sp + 14 * 4]
237
 
238
        restore                         ! Go back to trap window.
239
        mov     %l4, %g1                ! Restore %g1
240
 
241
window_fine:
242
        sethi   %hi(in_trap_handler), %l4
243
        ld      [%lo(in_trap_handler) + %l4], %l5
244
        tst     %l5
245
        bg      recursive_trap
246
        inc     %l5
247
 
248
        set     trapstack+1000*4, %sp   ! Switch to trap stack
249
 
250
recursive_trap:
251
        st      %l5, [%lo(in_trap_handler) + %l4]
252
        sub     %sp,(16+1+6+1+80)*4,%sp ! Make room for input & locals
253
                                        ! + hidden arg + arg spill
254
                                        ! + doubleword alignment
255
                                        ! + registers[72] local var
256
 
257
        std     %g0, [%sp + (24 + 0) * 4] ! registers[Gx]
258
        std     %g2, [%sp + (24 + 2) * 4]
259
        std     %g4, [%sp + (24 + 4) * 4]
260
        std     %g6, [%sp + (24 + 6) * 4]
261
 
262
        std     %i0, [%sp + (24 + 8) * 4] ! registers[Ox]
263
        std     %i2, [%sp + (24 + 10) * 4]
264
        std     %i4, [%sp + (24 + 12) * 4]
265
        std     %i6, [%sp + (24 + 14) * 4]
266
 
267
        mov     %y, %l4
268
        mov     %tbr, %l5
269
        st      %l4, [%sp + (24 + 64) * 4] ! Y
270
        st      %l0, [%sp + (24 + 65) * 4] ! PSR
271
        st      %l3, [%sp + (24 + 66) * 4] ! WIM
272
        st      %l5, [%sp + (24 + 67) * 4] ! TBR
273
        st      %l1, [%sp + (24 + 68) * 4] ! PC
274
        st      %l2, [%sp + (24 + 69) * 4] ! NPC
275
 
276
        or      %l0, 0xf20, %l4
277
        mov     %l4, %psr               ! Turn on traps, disable interrupts
278
 
279
        set     0x1000, %l1
280
        btst    %l1, %l0                ! FP enabled?
281
        be      no_fpstore
282
        nop
283
 
284
! Must save fsr first, to flush the FQ.  This may cause a deferred fp trap, so
285
! traps must be enabled to allow the trap handler to clean things up.
286
 
287
        st      %fsr, [%sp + (24 + 70) * 4]
288
 
289
        std     %f0, [%sp + (24 + 32) * 4]
290
        std     %f2, [%sp + (24 + 34) * 4]
291
        std     %f4, [%sp + (24 + 36) * 4]
292
        std     %f6, [%sp + (24 + 38) * 4]
293
        std     %f8, [%sp + (24 + 40) * 4]
294
        std     %f10, [%sp + (24 + 42) * 4]
295
        std     %f12, [%sp + (24 + 44) * 4]
296
        std     %f14, [%sp + (24 + 46) * 4]
297
        std     %f16, [%sp + (24 + 48) * 4]
298
        std     %f18, [%sp + (24 + 50) * 4]
299
        std     %f20, [%sp + (24 + 52) * 4]
300
        std     %f22, [%sp + (24 + 54) * 4]
301
        std     %f24, [%sp + (24 + 56) * 4]
302
        std     %f26, [%sp + (24 + 58) * 4]
303
        std     %f28, [%sp + (24 + 60) * 4]
304
        std     %f30, [%sp + (24 + 62) * 4]
305
no_fpstore:
306
 
307
        call    _handle_exception
308
        add     %sp, 24 * 4, %o0        ! Pass address of registers
309
 
310
! Reload all of the registers that aren't on the stack
311
 
312
        ld      [%sp + (24 + 1) * 4], %g1 ! registers[Gx]
313
        ldd     [%sp + (24 + 2) * 4], %g2
314
        ldd     [%sp + (24 + 4) * 4], %g4
315
        ldd     [%sp + (24 + 6) * 4], %g6
316
 
317
        ldd     [%sp + (24 + 8) * 4], %i0 ! registers[Ox]
318
        ldd     [%sp + (24 + 10) * 4], %i2
319
        ldd     [%sp + (24 + 12) * 4], %i4
320
        ldd     [%sp + (24 + 14) * 4], %i6
321
 
322
 
323
        ldd     [%sp + (24 + 64) * 4], %l0 ! Y & PSR
324
        ldd     [%sp + (24 + 68) * 4], %l2 ! PC & NPC
325
 
326
        set     0x1000, %l5
327
        btst    %l5, %l1                ! FP enabled?
328
        be      no_fpreload
329
        nop
330
 
331
        ldd     [%sp + (24 + 32) * 4], %f0
332
        ldd     [%sp + (24 + 34) * 4], %f2
333
        ldd     [%sp + (24 + 36) * 4], %f4
334
        ldd     [%sp + (24 + 38) * 4], %f6
335
        ldd     [%sp + (24 + 40) * 4], %f8
336
        ldd     [%sp + (24 + 42) * 4], %f10
337
        ldd     [%sp + (24 + 44) * 4], %f12
338
        ldd     [%sp + (24 + 46) * 4], %f14
339
        ldd     [%sp + (24 + 48) * 4], %f16
340
        ldd     [%sp + (24 + 50) * 4], %f18
341
        ldd     [%sp + (24 + 52) * 4], %f20
342
        ldd     [%sp + (24 + 54) * 4], %f22
343
        ldd     [%sp + (24 + 56) * 4], %f24
344
        ldd     [%sp + (24 + 58) * 4], %f26
345
        ldd     [%sp + (24 + 60) * 4], %f28
346
        ldd     [%sp + (24 + 62) * 4], %f30
347
 
348
        ld      [%sp + (24 + 70) * 4], %fsr
349
no_fpreload:
350
 
351
        restore                         ! Ensure that previous window is valid
352
        save    %g0, %g0, %g0           !  by causing a window_underflow trap
353
 
354
        mov     %l0, %y
355
        mov     %l1, %psr               ! Make sure that traps are disabled
356
                                        ! for rett
357
        sethi   %hi(in_trap_handler), %l4
358
        ld      [%lo(in_trap_handler) + %l4], %l5
359
        dec     %l5
360
        st      %l5, [%lo(in_trap_handler) + %l4]
361
 
362
        jmpl    %l2, %g0                ! Restore old PC
363
        rett    %l3                     ! Restore old nPC
364
");
365
 
366
/* Convert ch from a hex digit to an int */
367
 
368
static int
369
hex(ch)
370
     unsigned char ch;
371
{
372
  if (ch >= 'a' && ch <= 'f')
373
    return ch-'a'+10;
374
  if (ch >= '0' && ch <= '9')
375
    return ch-'0';
376
  if (ch >= 'A' && ch <= 'F')
377
    return ch-'A'+10;
378
  return -1;
379
}
380
 
381
static char remcomInBuffer[BUFMAX];
382
static char remcomOutBuffer[BUFMAX];
383
 
384
/* scan for the sequence $<data>#<checksum>     */
385
 
386
unsigned char *
387
getpacket ()
388
{
389
  unsigned char *buffer = &remcomInBuffer[0];
390
  unsigned char checksum;
391
  unsigned char xmitcsum;
392
  int count;
393
  char ch;
394
 
395
  while (1)
396
    {
397
      /* wait around for the start character, ignore all other characters */
398
      while ((ch = getDebugChar ()) != '$')
399
        ;
400
 
401
retry:
402
      checksum = 0;
403
      xmitcsum = -1;
404
      count = 0;
405
 
406
      /* now, read until a # or end of buffer is found */
407
      while (count < BUFMAX)
408
        {
409
          ch = getDebugChar ();
410
          if (ch == '$')
411
            goto retry;
412
          if (ch == '#')
413
            break;
414
          checksum = checksum + ch;
415
          buffer[count] = ch;
416
          count = count + 1;
417
        }
418
      buffer[count] = 0;
419
 
420
      if (ch == '#')
421
        {
422
          ch = getDebugChar ();
423
          xmitcsum = hex (ch) << 4;
424
          ch = getDebugChar ();
425
          xmitcsum += hex (ch);
426
 
427
          if (checksum != xmitcsum)
428
            {
429
              putDebugChar ('-');       /* failed checksum */
430
            }
431
          else
432
            {
433
              putDebugChar ('+');       /* successful transfer */
434
 
435
              /* if a sequence char is present, reply the sequence ID */
436
              if (buffer[2] == ':')
437
                {
438
                  putDebugChar (buffer[0]);
439
                  putDebugChar (buffer[1]);
440
 
441
                  return &buffer[3];
442
                }
443
 
444
              return &buffer[0];
445
            }
446
        }
447
    }
448
}
449
 
450
/* send the packet in buffer.  */
451
 
452
static void
453
putpacket(buffer)
454
     unsigned char *buffer;
455
{
456
  unsigned char checksum;
457
  int count;
458
  unsigned char ch;
459
 
460
  /*  $<packet info>#<checksum>. */
461
  do
462
    {
463
      putDebugChar('$');
464
      checksum = 0;
465
      count = 0;
466
 
467
      while (ch = buffer[count])
468
        {
469
          putDebugChar (ch);
470
          checksum += ch;
471
          count += 1;
472
        }
473
 
474
      putDebugChar('#');
475
      putDebugChar(hexchars[checksum >> 4]);
476
      putDebugChar(hexchars[checksum & 0xf]);
477
 
478
    }
479
  while (getDebugChar() != '+');
480
}
481
 
482
/* Indicate to caller of mem2hex or hex2mem that there has been an
483
   error.  */
484
static volatile int mem_err = 0;
485
 
486
/* Convert the memory pointed to by mem into hex, placing result in buf.
487
 * Return a pointer to the last char put in buf (null), in case of mem fault,
488
 * return 0.
489
 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
490
 * a 0, else treat a fault like any other fault in the stub.
491
 */
492
 
493
static unsigned char *
494
mem2hex(mem, buf, count, may_fault)
495
     unsigned char *mem;
496
     unsigned char *buf;
497
     int count;
498
     int may_fault;
499
{
500
  unsigned char ch;
501
 
502
  set_mem_fault_trap(may_fault);
503
 
504
  while (count-- > 0)
505
    {
506
      ch = *mem++;
507
      if (mem_err)
508
        return 0;
509
      *buf++ = hexchars[ch >> 4];
510
      *buf++ = hexchars[ch & 0xf];
511
    }
512
 
513
  *buf = 0;
514
 
515
  set_mem_fault_trap(0);
516
 
517
  return buf;
518
}
519
 
520
/* convert the hex array pointed to by buf into binary to be placed in mem
521
 * return a pointer to the character AFTER the last byte written */
522
 
523
static char *
524
hex2mem(buf, mem, count, may_fault)
525
     unsigned char *buf;
526
     unsigned char *mem;
527
     int count;
528
     int may_fault;
529
{
530
  int i;
531
  unsigned char ch;
532
 
533
  set_mem_fault_trap(may_fault);
534
 
535
  for (i=0; i<count; i++)
536
    {
537
      ch = hex(*buf++) << 4;
538
      ch |= hex(*buf++);
539
      *mem++ = ch;
540
      if (mem_err)
541
        return 0;
542
    }
543
 
544
  set_mem_fault_trap(0);
545
 
546
  return mem;
547
}
548
 
549
/* This table contains the mapping between SPARC hardware trap types, and
550
   signals, which are primarily what GDB understands.  It also indicates
551
   which hardware traps we need to commandeer when initializing the stub. */
552
 
553
static struct hard_trap_info
554
{
555
  unsigned char tt;             /* Trap type code for SPARClite */
556
  unsigned char signo;          /* Signal that we map this trap into */
557
} hard_trap_info[] = {
558
  {0x01, SIGSEGV},              /* instruction access error */
559
  {0x02, SIGILL},               /* privileged instruction */
560
  {0x03, SIGILL},               /* illegal instruction */
561
  {0x04, SIGEMT},               /* fp disabled */
562
  {0x07, SIGBUS},               /* mem address not aligned */
563
  {0x09, SIGSEGV},              /* data access exception */
564
  {0x0a, SIGEMT},               /* tag overflow */
565
  {0x20, SIGBUS},               /* r register access error */
566
  {0x21, SIGBUS},               /* instruction access error */
567
  {0x24, SIGEMT},               /* cp disabled */
568
  {0x29, SIGBUS},               /* data access error */
569
  {0x2a, SIGFPE},               /* divide by zero */
570
  {0x2b, SIGBUS},               /* data store error */
571
  {0x80+1, SIGTRAP},            /* ta 1 - normal breakpoint instruction */
572
  {0xff, SIGTRAP},              /* hardware breakpoint */
573
  {0, 0}                  /* Must be last */
574
};
575
 
576
/* Set up exception handlers for tracing and breakpoints */
577
 
578
void
579
set_debug_traps()
580
{
581
  struct hard_trap_info *ht;
582
 
583
/* Only setup fp traps if the FP is disabled.  */
584
 
585
  for (ht = hard_trap_info;
586
       ht->tt != 0 && ht->signo != 0;
587
       ht++)
588
    if (ht->tt != 4 || ! (read_psr () & 0x1000))
589
      exceptionHandler(ht->tt, trap_low);
590
 
591
  initialized = 1;
592
}
593
 
594
asm ("
595
! Trap handler for memory errors.  This just sets mem_err to be non-zero.  It
596
! assumes that %l1 is non-zero.  This should be safe, as it is doubtful that
597
! 0 would ever contain code that could mem fault.  This routine will skip
598
! past the faulting instruction after setting mem_err.
599
 
600
        .text
601
        .align 4
602
 
603
_fltr_set_mem_err:
604
        sethi %hi(_mem_err), %l0
605
        st %l1, [%l0 + %lo(_mem_err)]
606
        jmpl %l2, %g0
607
        rett %l2+4
608
");
609
 
610
static void
611
set_mem_fault_trap(enable)
612
     int enable;
613
{
614
  extern void fltr_set_mem_err();
615
  mem_err = 0;
616
 
617
  if (enable)
618
    exceptionHandler(9, fltr_set_mem_err);
619
  else
620
    exceptionHandler(9, trap_low);
621
}
622
 
623
asm ("
624
        .text
625
        .align 4
626
 
627
_dummy_hw_breakpoint:
628
        jmpl %l2, %g0
629
        rett %l2+4
630
        nop
631
        nop
632
");
633
 
634
static void
635
get_in_break_mode()
636
{
637
  extern void dummy_hw_breakpoint();
638
 
639
  exceptionHandler (255, dummy_hw_breakpoint);
640
 
641
  asm ("ta 255");
642
 
643
  exceptionHandler (255, trap_low);
644
}
645
 
646
/* Convert the SPARC hardware trap type code to a unix signal number. */
647
 
648
static int
649
computeSignal(tt)
650
     int tt;
651
{
652
  struct hard_trap_info *ht;
653
 
654
  for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
655
    if (ht->tt == tt)
656
      return ht->signo;
657
 
658
  return SIGHUP;                /* default for things we don't know about */
659
}
660
 
661
/*
662
 * While we find nice hex chars, build an int.
663
 * Return number of chars processed.
664
 */
665
 
666
static int
667
hexToInt(char **ptr, int *intValue)
668
{
669
  int numChars = 0;
670
  int hexValue;
671
 
672
  *intValue = 0;
673
 
674
  while (**ptr)
675
    {
676
      hexValue = hex(**ptr);
677
      if (hexValue < 0)
678
        break;
679
 
680
      *intValue = (*intValue << 4) | hexValue;
681
      numChars ++;
682
 
683
      (*ptr)++;
684
    }
685
 
686
  return (numChars);
687
}
688
 
689
/*
690
 * This function does all command procesing for interfacing to gdb.  It
691
 * returns 1 if you should skip the instruction at the trap address, 0
692
 * otherwise.
693
 */
694
 
695
static void
696
handle_exception (registers)
697
     unsigned long *registers;
698
{
699
  int tt;                       /* Trap type */
700
  int sigval;
701
  int addr;
702
  int length;
703
  char *ptr;
704
  unsigned long *sp;
705
  unsigned long dsr;
706
 
707
/* First, we must force all of the windows to be spilled out */
708
 
709
  asm(" save %sp, -64, %sp
710
        save %sp, -64, %sp
711
        save %sp, -64, %sp
712
        save %sp, -64, %sp
713
        save %sp, -64, %sp
714
        save %sp, -64, %sp
715
        save %sp, -64, %sp
716
        save %sp, -64, %sp
717
        restore
718
        restore
719
        restore
720
        restore
721
        restore
722
        restore
723
        restore
724
        restore
725
");
726
 
727
  get_in_break_mode ();         /* Enable DSU register writes */
728
 
729
  registers[DIA1] = read_asi (1, 0xff00);
730
  registers[DIA2] = read_asi (1, 0xff04);
731
  registers[DDA1] = read_asi (1, 0xff08);
732
  registers[DDA2] = read_asi (1, 0xff0c);
733
  registers[DDV1] = read_asi (1, 0xff10);
734
  registers[DDV2] = read_asi (1, 0xff14);
735
  registers[DCR] = read_asi (1, 0xff18);
736
  registers[DSR] = read_asi (1, 0xff1c);
737
 
738
  if (registers[PC] == (unsigned long)breakinst)
739
    {
740
      registers[PC] = registers[NPC];
741
      registers[NPC] += 4;
742
    }
743
  sp = (unsigned long *)registers[SP];
744
 
745
  dsr = (unsigned long)registers[DSR];
746
  if (dsr & 0x3c)
747
    tt = 255;
748
  else
749
    tt = (registers[TBR] >> 4) & 0xff;
750
 
751
  /* reply to host that an exception has occurred */
752
  sigval = computeSignal(tt);
753
  ptr = remcomOutBuffer;
754
 
755
  *ptr++ = 'T';
756
  *ptr++ = hexchars[sigval >> 4];
757
  *ptr++ = hexchars[sigval & 0xf];
758
 
759
  *ptr++ = hexchars[PC >> 4];
760
  *ptr++ = hexchars[PC & 0xf];
761
  *ptr++ = ':';
762
  ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
763
  *ptr++ = ';';
764
 
765
  *ptr++ = hexchars[FP >> 4];
766
  *ptr++ = hexchars[FP & 0xf];
767
  *ptr++ = ':';
768
  ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
769
  *ptr++ = ';';
770
 
771
  *ptr++ = hexchars[SP >> 4];
772
  *ptr++ = hexchars[SP & 0xf];
773
  *ptr++ = ':';
774
  ptr = mem2hex((char *)&sp, ptr, 4, 0);
775
  *ptr++ = ';';
776
 
777
  *ptr++ = hexchars[NPC >> 4];
778
  *ptr++ = hexchars[NPC & 0xf];
779
  *ptr++ = ':';
780
  ptr = mem2hex((char *)&registers[NPC], ptr, 4, 0);
781
  *ptr++ = ';';
782
 
783
  *ptr++ = hexchars[O7 >> 4];
784
  *ptr++ = hexchars[O7 & 0xf];
785
  *ptr++ = ':';
786
  ptr = mem2hex((char *)&registers[O7], ptr, 4, 0);
787
  *ptr++ = ';';
788
 
789
  *ptr++ = 0;
790
 
791
  putpacket(remcomOutBuffer);
792
 
793
  while (1)
794
    {
795
      remcomOutBuffer[0] = 0;
796
 
797
      ptr = getpacket();
798
      switch (*ptr++)
799
        {
800
        case '?':
801
          remcomOutBuffer[0] = 'S';
802
          remcomOutBuffer[1] = hexchars[sigval >> 4];
803
          remcomOutBuffer[2] = hexchars[sigval & 0xf];
804
          remcomOutBuffer[3] = 0;
805
          break;
806
 
807
        case 'd':
808
                                /* toggle debug flag */
809
          break;
810
 
811
        case 'g':               /* return the value of the CPU registers */
812
          memcpy (&registers[L0], sp, 16 * 4); /* Copy L & I regs from stack */
813
          mem2hex ((char *)registers, remcomOutBuffer, NUMREGBYTES, 0);
814
          break;
815
 
816
        case 'G':               /* Set the value of all registers */
817
        case 'P':               /* Set the value of one register */
818
          {
819
            unsigned long *newsp, psr;
820
 
821
            psr = registers[PSR];
822
 
823
            if (ptr[-1] == 'P')
824
              {
825
                int regno;
826
 
827
                if (hexToInt (&ptr, &regno)
828
                    && *ptr++ == '=')
829
                  if (regno >= L0 && regno <= I7)
830
                    hex2mem (ptr, sp + regno - L0, 4, 0);
831
                  else
832
                    hex2mem (ptr, (char *)&registers[regno], 4, 0);
833
                else
834
                  {
835
                    strcpy (remcomOutBuffer, "E01");
836
                    break;
837
                  }
838
              }
839
            else
840
              {
841
                hex2mem (ptr, (char *)registers, NUMREGBYTES, 0);
842
                memcpy (sp, &registers[L0], 16 * 4); /* Copy L & I regs to stack */
843
              }
844
 
845
            /* See if the stack pointer has moved.  If so, then copy the saved
846
               locals and ins to the new location.  This keeps the window
847
               overflow and underflow routines happy.  */
848
 
849
            newsp = (unsigned long *)registers[SP];
850
            if (sp != newsp)
851
              sp = memcpy(newsp, sp, 16 * 4);
852
 
853
            /* Don't allow CWP to be modified. */
854
 
855
            if (psr != registers[PSR])
856
              registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
857
 
858
            strcpy(remcomOutBuffer,"OK");
859
          }
860
          break;
861
 
862
        case 'm':         /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
863
          /* Try to read %x,%x.  */
864
 
865
          if (hexToInt(&ptr, &addr)
866
              && *ptr++ == ','
867
              && hexToInt(&ptr, &length))
868
            {
869
              if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
870
                break;
871
 
872
              strcpy (remcomOutBuffer, "E03");
873
            }
874
          else
875
            strcpy(remcomOutBuffer,"E01");
876
          break;
877
 
878
        case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
879
          /* Try to read '%x,%x:'.  */
880
 
881
          if (hexToInt(&ptr, &addr)
882
              && *ptr++ == ','
883
              && hexToInt(&ptr, &length)
884
              && *ptr++ == ':')
885
            {
886
              if (hex2mem(ptr, (char *)addr, length, 1))
887
                strcpy(remcomOutBuffer, "OK");
888
              else
889
                strcpy(remcomOutBuffer, "E03");
890
            }
891
          else
892
            strcpy(remcomOutBuffer, "E02");
893
          break;
894
 
895
        case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
896
          /* try to read optional parameter, pc unchanged if no parm */
897
          if (hexToInt(&ptr, &addr))
898
            {
899
              registers[PC] = addr;
900
              registers[NPC] = addr + 4;
901
            }
902
 
903
/* Need to flush the instruction cache here, as we may have deposited a
904
   breakpoint, and the icache probably has no way of knowing that a data ref to
905
   some location may have changed something that is in the instruction cache.
906
 */
907
 
908
          flush_i_cache ();
909
 
910
          if (!(registers[DSR] & 0x1) /* DSU enabled? */
911
              && !(registers[DCR] & 0x200)) /* Are we in break state? */
912
            {                   /* Yes, set the DSU regs */
913
              write_asi (1, 0xff00, registers[DIA1]);
914
              write_asi (1, 0xff04, registers[DIA2]);
915
              write_asi (1, 0xff08, registers[DDA1]);
916
              write_asi (1, 0xff0c, registers[DDA2]);
917
              write_asi (1, 0xff10, registers[DDV1]);
918
              write_asi (1, 0xff14, registers[DDV2]);
919
              write_asi (1, 0xff1c, registers[DSR]);
920
              write_asi (1, 0xff18, registers[DCR] | 0x200); /* Clear break */
921
            }
922
 
923
          return;
924
 
925
          /* kill the program */
926
        case 'k' :              /* do nothing */
927
          break;
928
#if 0
929
        case 't':               /* Test feature */
930
          asm (" std %f30,[%sp]");
931
          break;
932
#endif
933
        case 'r':               /* Reset */
934
          asm ("call 0
935
                nop ");
936
          break;
937
        }                       /* switch */
938
 
939
      /* reply to the request */
940
      putpacket(remcomOutBuffer);
941
    }
942
}
943
 
944
/* This function will generate a breakpoint exception.  It is used at the
945
   beginning of a program to sync up with a debugger and can be used
946
   otherwise as a quick means to stop program execution and "break" into
947
   the debugger. */
948
 
949
void
950
breakpoint()
951
{
952
  if (!initialized)
953
    return;
954
 
955
  asm(" .globl _breakinst
956
 
957
        _breakinst: ta 1
958
      ");
959
}

powered by: WebSVN 2.1.0

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