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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [sparcl-stub.c] - Blame information for rev 1767

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

Line No. Rev Author Line
1 578 markom
/****************************************************************************
2
 
3
                THIS SOFTWARE IS NOT COPYRIGHTED
4
 
5
   HP offers the following for use in the public domain.  HP makes no
6
   warranty with regard to the software or it's performance and the
7
   user accepts the software "AS IS" with all faults.
8
 
9
   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
10
   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
11
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12
 
13
****************************************************************************/
14
 
15
/****************************************************************************
16
 *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
17
 *
18
 *  Module name: remcom.c $
19
 *  Revision: 1.34 $
20
 *  Date: 91/03/09 12:29:49 $
21
 *  Contributor:     Lake Stevens Instrument Division$
22
 *
23
 *  Description:     low level support for gdb debugger. $
24
 *
25
 *  Considerations:  only works on target hardware $
26
 *
27
 *  Written by:      Glenn Engel $
28
 *  ModuleState:     Experimental $
29
 *
30
 *  NOTES:           See Below $
31
 *
32
 *  Modified for 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 (unsigned char ch)
370
{
371
  if (ch >= 'a' && ch <= 'f')
372
    return ch-'a'+10;
373
  if (ch >= '0' && ch <= '9')
374
    return ch-'0';
375
  if (ch >= 'A' && ch <= 'F')
376
    return ch-'A'+10;
377
  return -1;
378
}
379
 
380
static char remcomInBuffer[BUFMAX];
381
static char remcomOutBuffer[BUFMAX];
382
 
383
/* scan for the sequence $<data>#<checksum>     */
384
 
385
unsigned char *
386
getpacket (void)
387
{
388
  unsigned char *buffer = &remcomInBuffer[0];
389
  unsigned char checksum;
390
  unsigned char xmitcsum;
391
  int count;
392
  char ch;
393
 
394
  while (1)
395
    {
396
      /* wait around for the start character, ignore all other characters */
397
      while ((ch = getDebugChar ()) != '$')
398
        ;
399
 
400
retry:
401
      checksum = 0;
402
      xmitcsum = -1;
403
      count = 0;
404
 
405
      /* now, read until a # or end of buffer is found */
406
      while (count < BUFMAX)
407
        {
408
          ch = getDebugChar ();
409
          if (ch == '$')
410
            goto retry;
411
          if (ch == '#')
412
            break;
413
          checksum = checksum + ch;
414
          buffer[count] = ch;
415
          count = count + 1;
416
        }
417
      buffer[count] = 0;
418
 
419
      if (ch == '#')
420
        {
421
          ch = getDebugChar ();
422
          xmitcsum = hex (ch) << 4;
423
          ch = getDebugChar ();
424
          xmitcsum += hex (ch);
425
 
426
          if (checksum != xmitcsum)
427
            {
428
              putDebugChar ('-');       /* failed checksum */
429
            }
430
          else
431
            {
432
              putDebugChar ('+');       /* successful transfer */
433
 
434
              /* if a sequence char is present, reply the sequence ID */
435
              if (buffer[2] == ':')
436
                {
437
                  putDebugChar (buffer[0]);
438
                  putDebugChar (buffer[1]);
439
 
440
                  return &buffer[3];
441
                }
442
 
443
              return &buffer[0];
444
            }
445
        }
446
    }
447
}
448
 
449
/* send the packet in buffer.  */
450
 
451
static void
452
putpacket (unsigned char *buffer)
453
{
454
  unsigned char checksum;
455
  int count;
456
  unsigned char ch;
457
 
458
  /*  $<packet info>#<checksum>. */
459
  do
460
    {
461
      putDebugChar('$');
462
      checksum = 0;
463
      count = 0;
464
 
465
      while (ch = buffer[count])
466
        {
467
          putDebugChar (ch);
468
          checksum += ch;
469
          count += 1;
470
        }
471
 
472
      putDebugChar('#');
473
      putDebugChar(hexchars[checksum >> 4]);
474
      putDebugChar(hexchars[checksum & 0xf]);
475
 
476
    }
477
  while (getDebugChar() != '+');
478
}
479
 
480
/* Indicate to caller of mem2hex or hex2mem that there has been an
481
   error.  */
482
static volatile int mem_err = 0;
483
 
484
/* Convert the memory pointed to by mem into hex, placing result in buf.
485
 * Return a pointer to the last char put in buf (null), in case of mem fault,
486
 * return 0.
487
 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
488
 * a 0, else treat a fault like any other fault in the stub.
489
 */
490
 
491
static unsigned char *
492
mem2hex (unsigned char *mem, unsigned char *buf, int count, int may_fault)
493
{
494
  unsigned char ch;
495
 
496
  set_mem_fault_trap(may_fault);
497
 
498
  while (count-- > 0)
499
    {
500
      ch = *mem++;
501
      if (mem_err)
502
        return 0;
503
      *buf++ = hexchars[ch >> 4];
504
      *buf++ = hexchars[ch & 0xf];
505
    }
506
 
507
  *buf = 0;
508
 
509
  set_mem_fault_trap(0);
510
 
511
  return buf;
512
}
513
 
514
/* convert the hex array pointed to by buf into binary to be placed in mem
515
 * return a pointer to the character AFTER the last byte written */
516
 
517
static char *
518
hex2mem (unsigned char *buf, unsigned char *mem, int count, int may_fault)
519
{
520
  int i;
521
  unsigned char ch;
522
 
523
  set_mem_fault_trap(may_fault);
524
 
525
  for (i=0; i<count; i++)
526
    {
527
      ch = hex(*buf++) << 4;
528
      ch |= hex(*buf++);
529
      *mem++ = ch;
530
      if (mem_err)
531
        return 0;
532
    }
533
 
534
  set_mem_fault_trap(0);
535
 
536
  return mem;
537
}
538
 
539
/* This table contains the mapping between SPARC hardware trap types, and
540
   signals, which are primarily what GDB understands.  It also indicates
541
   which hardware traps we need to commandeer when initializing the stub. */
542
 
543
static struct hard_trap_info
544
{
545
  unsigned char tt;             /* Trap type code for SPARClite */
546
  unsigned char signo;          /* Signal that we map this trap into */
547
} hard_trap_info[] = {
548
  {0x01, SIGSEGV},              /* instruction access error */
549
  {0x02, SIGILL},               /* privileged instruction */
550
  {0x03, SIGILL},               /* illegal instruction */
551
  {0x04, SIGEMT},               /* fp disabled */
552
  {0x07, SIGBUS},               /* mem address not aligned */
553
  {0x09, SIGSEGV},              /* data access exception */
554
  {0x0a, SIGEMT},               /* tag overflow */
555
  {0x20, SIGBUS},               /* r register access error */
556
  {0x21, SIGBUS},               /* instruction access error */
557
  {0x24, SIGEMT},               /* cp disabled */
558
  {0x29, SIGBUS},               /* data access error */
559
  {0x2a, SIGFPE},               /* divide by zero */
560
  {0x2b, SIGBUS},               /* data store error */
561
  {0x80+1, SIGTRAP},            /* ta 1 - normal breakpoint instruction */
562
  {0xff, SIGTRAP},              /* hardware breakpoint */
563
  {0, 0}                  /* Must be last */
564
};
565
 
566
/* Set up exception handlers for tracing and breakpoints */
567
 
568
void
569
set_debug_traps (void)
570
{
571
  struct hard_trap_info *ht;
572
 
573
/* Only setup fp traps if the FP is disabled.  */
574
 
575
  for (ht = hard_trap_info;
576
       ht->tt != 0 && ht->signo != 0;
577
       ht++)
578
    if (ht->tt != 4 || ! (read_psr () & 0x1000))
579
      exceptionHandler(ht->tt, trap_low);
580
 
581
  initialized = 1;
582
}
583
 
584
asm ("
585
! Trap handler for memory errors.  This just sets mem_err to be non-zero.  It
586
! assumes that %l1 is non-zero.  This should be safe, as it is doubtful that
587
! 0 would ever contain code that could mem fault.  This routine will skip
588
! past the faulting instruction after setting mem_err.
589
 
590
        .text
591
        .align 4
592
 
593
_fltr_set_mem_err:
594
        sethi %hi(_mem_err), %l0
595
        st %l1, [%l0 + %lo(_mem_err)]
596
        jmpl %l2, %g0
597
        rett %l2+4
598
");
599
 
600
static void
601
set_mem_fault_trap (int enable)
602
{
603
  extern void fltr_set_mem_err();
604
  mem_err = 0;
605
 
606
  if (enable)
607
    exceptionHandler(9, fltr_set_mem_err);
608
  else
609
    exceptionHandler(9, trap_low);
610
}
611
 
612
asm ("
613
        .text
614
        .align 4
615
 
616
_dummy_hw_breakpoint:
617
        jmpl %l2, %g0
618
        rett %l2+4
619
        nop
620
        nop
621
");
622
 
623
static void
624
get_in_break_mode (void)
625
{
626
  extern void dummy_hw_breakpoint();
627
 
628
  exceptionHandler (255, dummy_hw_breakpoint);
629
 
630
  asm ("ta 255");
631
 
632
  exceptionHandler (255, trap_low);
633
}
634
 
635
/* Convert the SPARC hardware trap type code to a unix signal number. */
636
 
637
static int
638
computeSignal (int tt)
639
{
640
  struct hard_trap_info *ht;
641
 
642
  for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
643
    if (ht->tt == tt)
644
      return ht->signo;
645
 
646
  return SIGHUP;                /* default for things we don't know about */
647
}
648
 
649
/*
650
 * While we find nice hex chars, build an int.
651
 * Return number of chars processed.
652
 */
653
 
654
static int
655
hexToInt(char **ptr, int *intValue)
656
{
657
  int numChars = 0;
658
  int hexValue;
659
 
660
  *intValue = 0;
661
 
662
  while (**ptr)
663
    {
664
      hexValue = hex(**ptr);
665
      if (hexValue < 0)
666
        break;
667
 
668
      *intValue = (*intValue << 4) | hexValue;
669
      numChars ++;
670
 
671
      (*ptr)++;
672
    }
673
 
674
  return (numChars);
675
}
676
 
677
/*
678
 * This function does all command procesing for interfacing to gdb.  It
679
 * returns 1 if you should skip the instruction at the trap address, 0
680
 * otherwise.
681
 */
682
 
683
static void
684
handle_exception (unsigned long *registers)
685
{
686
  int tt;                       /* Trap type */
687
  int sigval;
688
  int addr;
689
  int length;
690
  char *ptr;
691
  unsigned long *sp;
692
  unsigned long dsr;
693
 
694
/* First, we must force all of the windows to be spilled out */
695
 
696
  asm(" save %sp, -64, %sp
697
        save %sp, -64, %sp
698
        save %sp, -64, %sp
699
        save %sp, -64, %sp
700
        save %sp, -64, %sp
701
        save %sp, -64, %sp
702
        save %sp, -64, %sp
703
        save %sp, -64, %sp
704
        restore
705
        restore
706
        restore
707
        restore
708
        restore
709
        restore
710
        restore
711
        restore
712
");
713
 
714
  get_in_break_mode ();         /* Enable DSU register writes */
715
 
716
  registers[DIA1] = read_asi (1, 0xff00);
717
  registers[DIA2] = read_asi (1, 0xff04);
718
  registers[DDA1] = read_asi (1, 0xff08);
719
  registers[DDA2] = read_asi (1, 0xff0c);
720
  registers[DDV1] = read_asi (1, 0xff10);
721
  registers[DDV2] = read_asi (1, 0xff14);
722
  registers[DCR] = read_asi (1, 0xff18);
723
  registers[DSR] = read_asi (1, 0xff1c);
724
 
725
  if (registers[PC] == (unsigned long)breakinst)
726
    {
727
      registers[PC] = registers[NPC];
728
      registers[NPC] += 4;
729
    }
730
  sp = (unsigned long *)registers[SP];
731
 
732
  dsr = (unsigned long)registers[DSR];
733
  if (dsr & 0x3c)
734
    tt = 255;
735
  else
736
    tt = (registers[TBR] >> 4) & 0xff;
737
 
738
  /* reply to host that an exception has occurred */
739
  sigval = computeSignal(tt);
740
  ptr = remcomOutBuffer;
741
 
742
  *ptr++ = 'T';
743
  *ptr++ = hexchars[sigval >> 4];
744
  *ptr++ = hexchars[sigval & 0xf];
745
 
746
  *ptr++ = hexchars[PC >> 4];
747
  *ptr++ = hexchars[PC & 0xf];
748
  *ptr++ = ':';
749
  ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
750
  *ptr++ = ';';
751
 
752
  *ptr++ = hexchars[FP >> 4];
753
  *ptr++ = hexchars[FP & 0xf];
754
  *ptr++ = ':';
755
  ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
756
  *ptr++ = ';';
757
 
758
  *ptr++ = hexchars[SP >> 4];
759
  *ptr++ = hexchars[SP & 0xf];
760
  *ptr++ = ':';
761
  ptr = mem2hex((char *)&sp, ptr, 4, 0);
762
  *ptr++ = ';';
763
 
764
  *ptr++ = hexchars[NPC >> 4];
765
  *ptr++ = hexchars[NPC & 0xf];
766
  *ptr++ = ':';
767
  ptr = mem2hex((char *)&registers[NPC], ptr, 4, 0);
768
  *ptr++ = ';';
769
 
770
  *ptr++ = hexchars[O7 >> 4];
771
  *ptr++ = hexchars[O7 & 0xf];
772
  *ptr++ = ':';
773
  ptr = mem2hex((char *)&registers[O7], ptr, 4, 0);
774
  *ptr++ = ';';
775
 
776
  *ptr++ = 0;
777
 
778
  putpacket(remcomOutBuffer);
779
 
780
  while (1)
781
    {
782
      remcomOutBuffer[0] = 0;
783
 
784
      ptr = getpacket();
785
      switch (*ptr++)
786
        {
787
        case '?':
788
          remcomOutBuffer[0] = 'S';
789
          remcomOutBuffer[1] = hexchars[sigval >> 4];
790
          remcomOutBuffer[2] = hexchars[sigval & 0xf];
791
          remcomOutBuffer[3] = 0;
792
          break;
793
 
794
        case 'd':
795
                                /* toggle debug flag */
796
          break;
797
 
798
        case 'g':               /* return the value of the CPU registers */
799
          memcpy (&registers[L0], sp, 16 * 4); /* Copy L & I regs from stack */
800
          mem2hex ((char *)registers, remcomOutBuffer, NUMREGBYTES, 0);
801
          break;
802
 
803
        case 'G':               /* Set the value of all registers */
804
        case 'P':               /* Set the value of one register */
805
          {
806
            unsigned long *newsp, psr;
807
 
808
            psr = registers[PSR];
809
 
810
            if (ptr[-1] == 'P')
811
              {
812
                int regno;
813
 
814
                if (hexToInt (&ptr, &regno)
815
                    && *ptr++ == '=')
816
                  if (regno >= L0 && regno <= I7)
817
                    hex2mem (ptr, sp + regno - L0, 4, 0);
818
                  else
819
                    hex2mem (ptr, (char *)&registers[regno], 4, 0);
820
                else
821
                  {
822
                    strcpy (remcomOutBuffer, "E01");
823
                    break;
824
                  }
825
              }
826
            else
827
              {
828
                hex2mem (ptr, (char *)registers, NUMREGBYTES, 0);
829
                memcpy (sp, &registers[L0], 16 * 4); /* Copy L & I regs to stack */
830
              }
831
 
832
            /* See if the stack pointer has moved.  If so, then copy the saved
833
               locals and ins to the new location.  This keeps the window
834
               overflow and underflow routines happy.  */
835
 
836
            newsp = (unsigned long *)registers[SP];
837
            if (sp != newsp)
838
              sp = memcpy(newsp, sp, 16 * 4);
839
 
840
            /* Don't allow CWP to be modified. */
841
 
842
            if (psr != registers[PSR])
843
              registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
844
 
845
            strcpy(remcomOutBuffer,"OK");
846
          }
847
          break;
848
 
849
        case 'm':         /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
850
          /* Try to read %x,%x.  */
851
 
852
          if (hexToInt(&ptr, &addr)
853
              && *ptr++ == ','
854
              && hexToInt(&ptr, &length))
855
            {
856
              if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
857
                break;
858
 
859
              strcpy (remcomOutBuffer, "E03");
860
            }
861
          else
862
            strcpy(remcomOutBuffer,"E01");
863
          break;
864
 
865
        case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
866
          /* Try to read '%x,%x:'.  */
867
 
868
          if (hexToInt(&ptr, &addr)
869
              && *ptr++ == ','
870
              && hexToInt(&ptr, &length)
871
              && *ptr++ == ':')
872
            {
873
              if (hex2mem(ptr, (char *)addr, length, 1))
874
                strcpy(remcomOutBuffer, "OK");
875
              else
876
                strcpy(remcomOutBuffer, "E03");
877
            }
878
          else
879
            strcpy(remcomOutBuffer, "E02");
880
          break;
881
 
882
        case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
883
          /* try to read optional parameter, pc unchanged if no parm */
884
          if (hexToInt(&ptr, &addr))
885
            {
886
              registers[PC] = addr;
887
              registers[NPC] = addr + 4;
888
            }
889
 
890
/* Need to flush the instruction cache here, as we may have deposited a
891
   breakpoint, and the icache probably has no way of knowing that a data ref to
892
   some location may have changed something that is in the instruction cache.
893
 */
894
 
895
          flush_i_cache ();
896
 
897
          if (!(registers[DSR] & 0x1) /* DSU enabled? */
898
              && !(registers[DCR] & 0x200)) /* Are we in break state? */
899
            {                   /* Yes, set the DSU regs */
900
              write_asi (1, 0xff00, registers[DIA1]);
901
              write_asi (1, 0xff04, registers[DIA2]);
902
              write_asi (1, 0xff08, registers[DDA1]);
903
              write_asi (1, 0xff0c, registers[DDA2]);
904
              write_asi (1, 0xff10, registers[DDV1]);
905
              write_asi (1, 0xff14, registers[DDV2]);
906
              write_asi (1, 0xff1c, registers[DSR]);
907
              write_asi (1, 0xff18, registers[DCR] | 0x200); /* Clear break */
908
            }
909
 
910
          return;
911
 
912
          /* kill the program */
913
        case 'k' :              /* do nothing */
914
          break;
915
#if 0
916
        case 't':               /* Test feature */
917
          asm (" std %f30,[%sp]");
918
          break;
919
#endif
920
        case 'r':               /* Reset */
921
          asm ("call 0
922
                nop ");
923
          break;
924
        }                       /* switch */
925
 
926
      /* reply to the request */
927
      putpacket(remcomOutBuffer);
928
    }
929
}
930
 
931
/* This function will generate a breakpoint exception.  It is used at the
932
   beginning of a program to sync up with a debugger and can be used
933
   otherwise as a quick means to stop program execution and "break" into
934
   the debugger. */
935
 
936
void
937
breakpoint (void)
938
{
939
  if (!initialized)
940
    return;
941
 
942
  asm(" .globl _breakinst
943
 
944
        _breakinst: ta 1
945
      ");
946
}

powered by: WebSVN 2.1.0

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