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

Subversion Repositories or1k_old

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

powered by: WebSVN 2.1.0

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