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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [sparclet-stub.c] - Blame information for rev 1765

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
 
90
/************************************************************************
91
 *
92
 * external low-level support routines
93
 */
94
 
95
extern void putDebugChar();     /* write a single character      */
96
extern int getDebugChar();      /* read and return a single char */
97
 
98
/************************************************************************/
99
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
100
/* at least NUMREGBYTES*2 are needed for register packets */
101
#define BUFMAX 2048
102
 
103
static int initialized = 0;      /* !0 means we've been initialized */
104
static int remote_debug = 0;     /* turn on verbose debugging */
105
 
106
extern void breakinst();
107
void _cprint();
108
static void hw_breakpoint();
109
static void set_mem_fault_trap();
110
static void get_in_break_mode();
111
static unsigned char *mem2hex();
112
 
113
static const char hexchars[]="0123456789abcdef";
114
 
115
#define NUMREGS 121
116
 
117
static unsigned long saved_stack_pointer;
118
 
119
/* Number of bytes of registers.  */
120
#define NUMREGBYTES (NUMREGS * 4)
121
enum regnames { G0, G1, G2, G3, G4, G5, G6, G7,
122
                O0, O1, O2, O3, O4, O5, SP, O7,
123
                L0, L1, L2, L3, L4, L5, L6, L7,
124
                I0, I1, I2, I3, I4, I5, FP, I7,
125
 
126
                F0, F1, F2, F3, F4, F5, F6, F7,
127
                F8, F9, F10, F11, F12, F13, F14, F15,
128
                F16, F17, F18, F19, F20, F21, F22, F23,
129
                F24, F25, F26, F27, F28, F29, F30, F31,
130
 
131
                Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR,
132
                CCSR, CCPR, CCCRCR, CCOR, CCOBR, CCIBR, CCIR, UNUSED1,
133
 
134
                ASR1, ASR15, ASR17, ASR18, ASR19, ASR20, ASR21, ASR22,
135
                /* the following not actually implemented */
136
                AWR0,  AWR1,  AWR2,  AWR3,  AWR4,  AWR5,  AWR6,  AWR7,
137
                AWR8,  AWR9,  AWR10, AWR11, AWR12, AWR13, AWR14, AWR15,
138
                AWR16, AWR17, AWR18, AWR19, AWR20, AWR21, AWR22, AWR23,
139
                AWR24, AWR25, AWR26, AWR27, AWR28, AWR29, AWR30, AWR31,
140
                APSR
141
};
142
 
143
/***************************  ASSEMBLY CODE MACROS *************************/
144
/*                                                                         */
145
 
146
extern void trap_low();
147
 
148
asm("
149
        .reserve trapstack, 1000 * 4, \"bss\", 8
150
 
151
        .data
152
        .align  4
153
 
154
in_trap_handler:
155
        .word   0
156
 
157
        .text
158
        .align 4
159
 
160
! This function is called when any SPARC trap (except window overflow or
161
! underflow) occurs.  It makes sure that the invalid register window is still
162
! available before jumping into C code.  It will also restore the world if you
163
! return from handle_exception.
164
!
165
! On entry, trap_low expects l1 and l2 to contain pc and npc respectivly.
166
 
167
        .globl _trap_low
168
_trap_low:
169
        mov     %psr, %l0
170
        mov     %wim, %l3
171
 
172
        srl     %l3, %l0, %l4           ! wim >> cwp
173
        and     %l4, 0xff, %l4          ! Mask off windows 28, 29
174
        cmp     %l4, 1
175
        bne     window_fine             ! Branch if not in the invalid window
176
        nop
177
 
178
! Handle window overflow
179
 
180
        mov     %g1, %l4                ! Save g1, we use it to hold the wim
181
        srl     %l3, 1, %g1             ! Rotate wim right
182
        and     %g1, 0xff, %g1          ! Mask off windows 28, 29
183
        tst     %g1
184
        bg      good_wim                ! Branch if new wim is non-zero
185
        nop
186
 
187
! At this point, we need to bring a 1 into the high order bit of the wim.
188
! Since we don't want to make any assumptions about the number of register
189
! windows, we figure it out dynamically so as to setup the wim correctly.
190
 
191
        ! The normal way doesn't work on the sparclet as register windows
192
        ! 28 and 29 are special purpose windows.
193
        !not    %g1                     ! Fill g1 with ones
194
        !mov    %g1, %wim               ! Fill the wim with ones
195
        !nop
196
        !nop
197
        !nop
198
        !mov    %wim, %g1               ! Read back the wim
199
        !inc    %g1                     ! Now g1 has 1 just to left of wim
200
        !srl    %g1, 1, %g1             ! Now put 1 at top of wim
201
 
202
        mov     0x80, %g1               ! Hack for sparclet
203
 
204
        ! This doesn't work on the sparclet.
205
        !mov    %g0, %wim               ! Clear wim so that subsequent save
206
                                        !  won't trap
207
        andn    %l3, 0xff, %l5          ! Clear wim but not windows 28, 29
208
        mov     %l5, %wim
209
        nop
210
        nop
211
        nop
212
 
213
good_wim:
214
        save    %g0, %g0, %g0           ! Slip into next window
215
        mov     %g1, %wim               ! Install the new wim
216
 
217
        std     %l0, [%sp + 0 * 4]      ! save L & I registers
218
        std     %l2, [%sp + 2 * 4]
219
        std     %l4, [%sp + 4 * 4]
220
        std     %l6, [%sp + 6 * 4]
221
 
222
        std     %i0, [%sp + 8 * 4]
223
        std     %i2, [%sp + 10 * 4]
224
        std     %i4, [%sp + 12 * 4]
225
        std     %i6, [%sp + 14 * 4]
226
 
227
        restore                         ! Go back to trap window.
228
        mov     %l4, %g1                ! Restore %g1
229
 
230
window_fine:
231
        sethi   %hi(in_trap_handler), %l4
232
        ld      [%lo(in_trap_handler) + %l4], %l5
233
        tst     %l5
234
        bg      recursive_trap
235
        inc     %l5
236
 
237
        set     trapstack+1000*4, %sp   ! Switch to trap stack
238
 
239
recursive_trap:
240
        st      %l5, [%lo(in_trap_handler) + %l4]
241
        sub     %sp,(16+1+6+1+88)*4,%sp ! Make room for input & locals
242
                                        ! + hidden arg + arg spill
243
                                        ! + doubleword alignment
244
                                        ! + registers[121]
245
 
246
        std     %g0, [%sp + (24 + 0) * 4] ! registers[Gx]
247
        std     %g2, [%sp + (24 + 2) * 4]
248
        std     %g4, [%sp + (24 + 4) * 4]
249
        std     %g6, [%sp + (24 + 6) * 4]
250
 
251
        std     %i0, [%sp + (24 + 8) * 4] ! registers[Ox]
252
        std     %i2, [%sp + (24 + 10) * 4]
253
        std     %i4, [%sp + (24 + 12) * 4]
254
        std     %i6, [%sp + (24 + 14) * 4]
255
 
256
        ! FP regs (sparclet doesn't have fpu)
257
 
258
        mov     %y, %l4
259
        mov     %tbr, %l5
260
        st      %l4, [%sp + (24 + 64) * 4] ! Y
261
        st      %l0, [%sp + (24 + 65) * 4] ! PSR
262
        st      %l3, [%sp + (24 + 66) * 4] ! WIM
263
        st      %l5, [%sp + (24 + 67) * 4] ! TBR
264
        st      %l1, [%sp + (24 + 68) * 4] ! PC
265
        st      %l2, [%sp + (24 + 69) * 4] ! NPC
266
                                        ! CPSR and FPSR not impl
267
        or      %l0, 0xf20, %l4
268
        mov     %l4, %psr               ! Turn on traps, disable interrupts
269
        nop
270
        nop
271
        nop
272
 
273
! Save coprocessor state.
274
! See SK/demo/hdlc_demo/ldc_swap_context.S.
275
 
276
        mov     %psr, %l0
277
        sethi   %hi(0x2000), %l5                ! EC bit in PSR
278
        or      %l5, %l0, %l5
279
        mov     %l5, %psr                       ! enable coprocessor
280
        nop                     ! 3 nops after write to %psr (needed?)
281
        nop
282
        nop
283
        crdcxt  %ccsr, %l1                      ! capture CCSR
284
        mov     0x6, %l2
285
        cwrcxt  %l2, %ccsr      ! set CCP state machine for CCFR
286
        crdcxt  %ccfr, %l2                      ! capture CCOR
287
        cwrcxt  %l2, %ccfr                      ! tickle  CCFR
288
        crdcxt  %ccfr, %l3                      ! capture CCOBR
289
        cwrcxt  %l3, %ccfr                      ! tickle  CCFR
290
        crdcxt  %ccfr, %l4                      ! capture CCIBR
291
        cwrcxt  %l4, %ccfr                      ! tickle  CCFR
292
        crdcxt  %ccfr, %l5                      ! capture CCIR
293
        cwrcxt  %l5, %ccfr                      ! tickle  CCFR
294
        crdcxt  %ccpr, %l6                      ! capture CCPR
295
        crdcxt  %cccrcr, %l7                    ! capture CCCRCR
296
        st      %l1, [%sp + (24 + 72) * 4]      ! save CCSR
297
        st      %l2, [%sp + (24 + 75) * 4]      ! save CCOR
298
        st      %l3, [%sp + (24 + 76) * 4]      ! save CCOBR
299
        st      %l4, [%sp + (24 + 77) * 4]      ! save CCIBR
300
        st      %l5, [%sp + (24 + 78) * 4]      ! save CCIR
301
        st      %l6, [%sp + (24 + 73) * 4]      ! save CCPR
302
        st      %l7, [%sp + (24 + 74) * 4]      ! save CCCRCR
303
        mov     %l0, %psr                       ! restore original PSR
304
        nop                     ! 3 nops after write to %psr (needed?)
305
        nop
306
        nop
307
 
308
! End of saving coprocessor state.
309
! Save asr regs
310
 
311
! Part of this is silly -- we should not display ASR15 or ASR19 at all.
312
 
313
        sethi   %hi(0x01000000), %l6
314
        st      %l6, [%sp + (24 + 81) * 4]      ! ASR15 == NOP
315
        sethi   %hi(0xdeadc0de), %l6
316
        or      %l6, %lo(0xdeadc0de), %l6
317
        st      %l6, [%sp + (24 + 84) * 4]      ! ASR19 == DEADC0DE
318
 
319
        rd      %asr1, %l4
320
        st      %l4, [%sp + (24 + 80) * 4]
321
!       rd      %asr15, %l4                     ! must not read ASR15
322
!       st      %l4, [%sp + (24 + 81) * 4]      ! (illegal instr trap)
323
        rd      %asr17, %l4
324
        st      %l4, [%sp + (24 + 82) * 4]
325
        rd      %asr18, %l4
326
        st      %l4, [%sp + (24 + 83) * 4]
327
!       rd      %asr19, %l4                     ! must not read asr19
328
!       st      %l4, [%sp + (24 + 84) * 4]      ! (halts the CPU)
329
        rd      %asr20, %l4
330
        st      %l4, [%sp + (24 + 85) * 4]
331
        rd      %asr21, %l4
332
        st      %l4, [%sp + (24 + 86) * 4]
333
        rd      %asr22, %l4
334
        st      %l4, [%sp + (24 + 87) * 4]
335
 
336
! End of saving asr regs
337
 
338
        call    _handle_exception
339
        add     %sp, 24 * 4, %o0        ! Pass address of registers
340
 
341
! Reload all of the registers that aren't on the stack
342
 
343
        ld      [%sp + (24 + 1) * 4], %g1 ! registers[Gx]
344
        ldd     [%sp + (24 + 2) * 4], %g2
345
        ldd     [%sp + (24 + 4) * 4], %g4
346
        ldd     [%sp + (24 + 6) * 4], %g6
347
 
348
        ldd     [%sp + (24 + 8) * 4], %i0 ! registers[Ox]
349
        ldd     [%sp + (24 + 10) * 4], %i2
350
        ldd     [%sp + (24 + 12) * 4], %i4
351
        ldd     [%sp + (24 + 14) * 4], %i6
352
 
353
        ! FP regs (sparclet doesn't have fpu)
354
 
355
! Update the coprocessor registers.
356
! See SK/demo/hdlc_demo/ldc_swap_context.S.
357
 
358
        mov     %psr, %l0
359
        sethi   %hi(0x2000), %l5                ! EC bit in PSR
360
        or      %l5, %l0, %l5
361
        mov     %l5, %psr                       ! enable coprocessor
362
        nop                     ! 3 nops after write to %psr (needed?)
363
        nop
364
        nop
365
 
366
        mov 0x6, %l2
367
        cwrcxt  %l2, %ccsr      ! set CCP state machine for CCFR
368
 
369
        ld      [%sp + (24 + 72) * 4], %l1      ! saved CCSR
370
        ld      [%sp + (24 + 75) * 4], %l2      ! saved CCOR
371
        ld      [%sp + (24 + 76) * 4], %l3      ! saved CCOBR
372
        ld      [%sp + (24 + 77) * 4], %l4      ! saved CCIBR
373
        ld      [%sp + (24 + 78) * 4], %l5      ! saved CCIR
374
        ld      [%sp + (24 + 73) * 4], %l6      ! saved CCPR
375
        ld      [%sp + (24 + 74) * 4], %l7      ! saved CCCRCR
376
 
377
        cwrcxt  %l2, %ccfr                      ! restore CCOR
378
        cwrcxt  %l3, %ccfr                      ! restore CCOBR
379
        cwrcxt  %l4, %ccfr                      ! restore CCIBR
380
        cwrcxt  %l5, %ccfr                      ! restore CCIR
381
        cwrcxt  %l6, %ccpr                      ! restore CCPR
382
        cwrcxt  %l7, %cccrcr                    ! restore CCCRCR
383
        cwrcxt  %l1, %ccsr                      ! restore CCSR
384
 
385
        mov %l0, %psr                           ! restore PSR
386
        nop             ! 3 nops after write to %psr (needed?)
387
        nop
388
        nop
389
 
390
! End of coprocessor handling stuff.
391
! Update asr regs
392
 
393
        ld      [%sp + (24 + 80) * 4], %l4
394
        wr      %l4, %asr1
395
!       ld      [%sp + (24 + 81) * 4], %l4      ! can't write asr15
396
!       wr      %l4, %asr15
397
        ld      [%sp + (24 + 82) * 4], %l4
398
        wr      %l4, %asr17
399
        ld      [%sp + (24 + 83) * 4], %l4
400
        wr      %l4, %asr18
401
!       ld      [%sp + (24 + 84) * 4], %l4      ! can't write asr19
402
!       wr      %l4, %asr19
403
!       ld      [%sp + (24 + 85) * 4], %l4      ! can't write asr20
404
!       wr      %l4, %asr20
405
!       ld      [%sp + (24 + 86) * 4], %l4      ! can't write asr21
406
!       wr      %l4, %asr21
407
        ld      [%sp + (24 + 87) * 4], %l4
408
        wr      %l4, %asr22
409
 
410
! End of restoring asr regs
411
 
412
 
413
        ldd     [%sp + (24 + 64) * 4], %l0 ! Y & PSR
414
        ldd     [%sp + (24 + 68) * 4], %l2 ! PC & NPC
415
 
416
        restore                         ! Ensure that previous window is valid
417
        save    %g0, %g0, %g0           !  by causing a window_underflow trap
418
 
419
        mov     %l0, %y
420
        mov     %l1, %psr               ! Make sure that traps are disabled
421
                                        ! for rett
422
        nop     ! 3 nops after write to %psr (needed?)
423
        nop
424
        nop
425
 
426
        sethi   %hi(in_trap_handler), %l4
427
        ld      [%lo(in_trap_handler) + %l4], %l5
428
        dec     %l5
429
        st      %l5, [%lo(in_trap_handler) + %l4]
430
 
431
        jmpl    %l2, %g0                ! Restore old PC
432
        rett    %l3                     ! Restore old nPC
433
");
434
 
435
/* Convert ch from a hex digit to an int */
436
 
437
static int
438
hex (unsigned char ch)
439
{
440
  if (ch >= 'a' && ch <= 'f')
441
    return ch-'a'+10;
442
  if (ch >= '0' && ch <= '9')
443
    return ch-'0';
444
  if (ch >= 'A' && ch <= 'F')
445
    return ch-'A'+10;
446
  return -1;
447
}
448
 
449
static char remcomInBuffer[BUFMAX];
450
static char remcomOutBuffer[BUFMAX];
451
 
452
/* scan for the sequence $<data>#<checksum>     */
453
 
454
unsigned char *
455
getpacket (void)
456
{
457
  unsigned char *buffer = &remcomInBuffer[0];
458
  unsigned char checksum;
459
  unsigned char xmitcsum;
460
  int count;
461
  char ch;
462
 
463
  while (1)
464
    {
465
      /* wait around for the start character, ignore all other characters */
466
      while ((ch = getDebugChar ()) != '$')
467
        ;
468
 
469
retry:
470
      checksum = 0;
471
      xmitcsum = -1;
472
      count = 0;
473
 
474
      /* now, read until a # or end of buffer is found */
475
      while (count < BUFMAX)
476
        {
477
          ch = getDebugChar ();
478
          if (ch == '$')
479
            goto retry;
480
          if (ch == '#')
481
            break;
482
          checksum = checksum + ch;
483
          buffer[count] = ch;
484
          count = count + 1;
485
        }
486
      buffer[count] = 0;
487
 
488
      if (ch == '#')
489
        {
490
          ch = getDebugChar ();
491
          xmitcsum = hex (ch) << 4;
492
          ch = getDebugChar ();
493
          xmitcsum += hex (ch);
494
 
495
          if (checksum != xmitcsum)
496
            {
497
              putDebugChar ('-');       /* failed checksum */
498
            }
499
          else
500
            {
501
              putDebugChar ('+');       /* successful transfer */
502
 
503
              /* if a sequence char is present, reply the sequence ID */
504
              if (buffer[2] == ':')
505
                {
506
                  putDebugChar (buffer[0]);
507
                  putDebugChar (buffer[1]);
508
 
509
                  return &buffer[3];
510
                }
511
 
512
              return &buffer[0];
513
            }
514
        }
515
    }
516
}
517
 
518
/* send the packet in buffer.  */
519
 
520
static void
521
putpacket (unsigned char *buffer)
522
{
523
  unsigned char checksum;
524
  int count;
525
  unsigned char ch;
526
 
527
  /*  $<packet info>#<checksum>. */
528
  do
529
    {
530
      putDebugChar('$');
531
      checksum = 0;
532
      count = 0;
533
 
534
      while (ch = buffer[count])
535
        {
536
          putDebugChar(ch);
537
          checksum += ch;
538
          count += 1;
539
        }
540
 
541
      putDebugChar('#');
542
      putDebugChar(hexchars[checksum >> 4]);
543
      putDebugChar(hexchars[checksum & 0xf]);
544
 
545
    }
546
  while (getDebugChar() != '+');
547
}
548
 
549
/* Indicate to caller of mem2hex or hex2mem that there has been an
550
   error.  */
551
static volatile int mem_err = 0;
552
 
553
/* Convert the memory pointed to by mem into hex, placing result in buf.
554
 * Return a pointer to the last char put in buf (null), in case of mem fault,
555
 * return 0.
556
 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
557
 * a 0, else treat a fault like any other fault in the stub.
558
 */
559
 
560
static unsigned char *
561
mem2hex (unsigned char *mem, unsigned char *buf, int count, int may_fault)
562
{
563
  unsigned char ch;
564
 
565
  set_mem_fault_trap(may_fault);
566
 
567
  while (count-- > 0)
568
    {
569
      ch = *mem++;
570
      if (mem_err)
571
        return 0;
572
      *buf++ = hexchars[ch >> 4];
573
      *buf++ = hexchars[ch & 0xf];
574
    }
575
 
576
  *buf = 0;
577
 
578
  set_mem_fault_trap(0);
579
 
580
  return buf;
581
}
582
 
583
/* convert the hex array pointed to by buf into binary to be placed in mem
584
 * return a pointer to the character AFTER the last byte written */
585
 
586
static char *
587
hex2mem (unsigned char *buf, unsigned char *mem, int count, int may_fault)
588
{
589
  int i;
590
  unsigned char ch;
591
 
592
  set_mem_fault_trap(may_fault);
593
 
594
  for (i=0; i<count; i++)
595
    {
596
      ch = hex(*buf++) << 4;
597
      ch |= hex(*buf++);
598
      *mem++ = ch;
599
      if (mem_err)
600
        return 0;
601
    }
602
 
603
  set_mem_fault_trap(0);
604
 
605
  return mem;
606
}
607
 
608
/* This table contains the mapping between SPARC hardware trap types, and
609
   signals, which are primarily what GDB understands.  It also indicates
610
   which hardware traps we need to commandeer when initializing the stub. */
611
 
612
static struct hard_trap_info
613
{
614
  unsigned char tt;             /* Trap type code for SPARClite */
615
  unsigned char signo;          /* Signal that we map this trap into */
616
} hard_trap_info[] = {
617
  {1, SIGSEGV},                 /* instruction access exception */
618
  {0x3b, SIGSEGV},              /* instruction access error */
619
  {2, SIGILL},                  /* illegal    instruction */
620
  {3, SIGILL},                  /* privileged instruction */
621
  {4, SIGEMT},                  /* fp disabled */
622
  {0x24, SIGEMT},               /* cp disabled */
623
  {7, SIGBUS},                  /* mem address not aligned */
624
  {0x29, SIGSEGV},              /* data access exception */
625
  {10, SIGEMT},                 /* tag overflow */
626
  {128+1, SIGTRAP},             /* ta 1 - normal breakpoint instruction */
627
  {0, 0}                  /* Must be last */
628
};
629
 
630
/* Set up exception handlers for tracing and breakpoints */
631
 
632
void
633
set_debug_traps (void)
634
{
635
  struct hard_trap_info *ht;
636
 
637
  for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
638
    exceptionHandler(ht->tt, trap_low);
639
 
640
  initialized = 1;
641
}
642
 
643
asm ("
644
! Trap handler for memory errors.  This just sets mem_err to be non-zero.  It
645
! assumes that %l1 is non-zero.  This should be safe, as it is doubtful that
646
! 0 would ever contain code that could mem fault.  This routine will skip
647
! past the faulting instruction after setting mem_err.
648
 
649
        .text
650
        .align 4
651
 
652
_fltr_set_mem_err:
653
        sethi %hi(_mem_err), %l0
654
        st %l1, [%l0 + %lo(_mem_err)]
655
        jmpl %l2, %g0
656
        rett %l2+4
657
");
658
 
659
static void
660
set_mem_fault_trap (int enable)
661
{
662
  extern void fltr_set_mem_err();
663
  mem_err = 0;
664
 
665
  if (enable)
666
    exceptionHandler(0x29, fltr_set_mem_err);
667
  else
668
    exceptionHandler(0x29, trap_low);
669
}
670
 
671
asm ("
672
        .text
673
        .align 4
674
 
675
_dummy_hw_breakpoint:
676
        jmpl %l2, %g0
677
        rett %l2+4
678
        nop
679
        nop
680
");
681
 
682
static void
683
set_hw_breakpoint_trap (int enable)
684
{
685
  extern void dummy_hw_breakpoint();
686
 
687
  if (enable)
688
    exceptionHandler(255, dummy_hw_breakpoint);
689
  else
690
    exceptionHandler(255, trap_low);
691
}
692
 
693
static void
694
get_in_break_mode (void)
695
{
696
#if 0
697
  int x;
698
  mesg("get_in_break_mode, sp = ");
699
  phex(&x);
700
#endif
701
  set_hw_breakpoint_trap(1);
702
 
703
  asm("
704
        sethi   %hi(0xff10), %l4
705
        or      %l4, %lo(0xff10), %l4
706
        sta     %g0, [%l4]0x1
707
        nop
708
        nop
709
        nop
710
      ");
711
 
712
  set_hw_breakpoint_trap(0);
713
}
714
 
715
/* Convert the SPARC hardware trap type code to a unix signal number. */
716
 
717
static int
718
computeSignal (int tt)
719
{
720
  struct hard_trap_info *ht;
721
 
722
  for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
723
    if (ht->tt == tt)
724
      return ht->signo;
725
 
726
  return SIGHUP;                /* default for things we don't know about */
727
}
728
 
729
/*
730
 * While we find nice hex chars, build an int.
731
 * Return number of chars processed.
732
 */
733
 
734
static int
735
hexToInt(char **ptr, int *intValue)
736
{
737
  int numChars = 0;
738
  int hexValue;
739
 
740
  *intValue = 0;
741
 
742
  while (**ptr)
743
    {
744
      hexValue = hex(**ptr);
745
      if (hexValue < 0)
746
        break;
747
 
748
      *intValue = (*intValue << 4) | hexValue;
749
      numChars ++;
750
 
751
      (*ptr)++;
752
    }
753
 
754
  return (numChars);
755
}
756
 
757
/*
758
 * This function does all command procesing for interfacing to gdb.  It
759
 * returns 1 if you should skip the instruction at the trap address, 0
760
 * otherwise.
761
 */
762
 
763
static void
764
handle_exception (unsigned long *registers)
765
{
766
  int tt;                       /* Trap type */
767
  int sigval;
768
  int addr;
769
  int length;
770
  char *ptr;
771
  unsigned long *sp;
772
  unsigned long dsr;
773
 
774
/* First, we must force all of the windows to be spilled out */
775
 
776
  asm("
777
        ! Ugh.  sparclet has broken save
778
        !save %sp, -64, %sp
779
        save
780
        add %fp,-64,%sp
781
        !save %sp, -64, %sp
782
        save
783
        add %fp,-64,%sp
784
        !save %sp, -64, %sp
785
        save
786
        add %fp,-64,%sp
787
        !save %sp, -64, %sp
788
        save
789
        add %fp,-64,%sp
790
        !save %sp, -64, %sp
791
        save
792
        add %fp,-64,%sp
793
        !save %sp, -64, %sp
794
        save
795
        add %fp,-64,%sp
796
        !save %sp, -64, %sp
797
        save
798
        add %fp,-64,%sp
799
        !save %sp, -64, %sp
800
        save
801
        add %fp,-64,%sp
802
        restore
803
        restore
804
        restore
805
        restore
806
        restore
807
        restore
808
        restore
809
        restore
810
");
811
 
812
  if (registers[PC] == (unsigned long)breakinst)
813
    {
814
      registers[PC] = registers[NPC];
815
      registers[NPC] += 4;
816
    }
817
  sp = (unsigned long *)registers[SP];
818
 
819
  tt = (registers[TBR] >> 4) & 0xff;
820
 
821
  /* reply to host that an exception has occurred */
822
  sigval = computeSignal(tt);
823
  ptr = remcomOutBuffer;
824
 
825
  *ptr++ = 'T';
826
  *ptr++ = hexchars[sigval >> 4];
827
  *ptr++ = hexchars[sigval & 0xf];
828
 
829
  *ptr++ = hexchars[PC >> 4];
830
  *ptr++ = hexchars[PC & 0xf];
831
  *ptr++ = ':';
832
  ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
833
  *ptr++ = ';';
834
 
835
  *ptr++ = hexchars[FP >> 4];
836
  *ptr++ = hexchars[FP & 0xf];
837
  *ptr++ = ':';
838
  ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
839
  *ptr++ = ';';
840
 
841
  *ptr++ = hexchars[SP >> 4];
842
  *ptr++ = hexchars[SP & 0xf];
843
  *ptr++ = ':';
844
  ptr = mem2hex((char *)&sp, ptr, 4, 0);
845
  *ptr++ = ';';
846
 
847
  *ptr++ = hexchars[NPC >> 4];
848
  *ptr++ = hexchars[NPC & 0xf];
849
  *ptr++ = ':';
850
  ptr = mem2hex((char *)&registers[NPC], ptr, 4, 0);
851
  *ptr++ = ';';
852
 
853
  *ptr++ = hexchars[O7 >> 4];
854
  *ptr++ = hexchars[O7 & 0xf];
855
  *ptr++ = ':';
856
  ptr = mem2hex((char *)&registers[O7], ptr, 4, 0);
857
  *ptr++ = ';';
858
 
859
  *ptr++ = 0;
860
 
861
  putpacket(remcomOutBuffer);
862
 
863
  while (1)
864
    {
865
      remcomOutBuffer[0] = 0;
866
 
867
      ptr = getpacket();
868
      switch (*ptr++)
869
        {
870
        case '?':
871
          remcomOutBuffer[0] = 'S';
872
          remcomOutBuffer[1] = hexchars[sigval >> 4];
873
          remcomOutBuffer[2] = hexchars[sigval & 0xf];
874
          remcomOutBuffer[3] = 0;
875
          break;
876
 
877
        case 'd':
878
          remote_debug = !(remote_debug);       /* toggle debug flag */
879
          break;
880
 
881
        case 'g':               /* return the value of the CPU registers */
882
          {
883
            ptr = remcomOutBuffer;
884
            ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
885
            ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */
886
            memset(ptr, '0', 32 * 8); /* Floating point */
887
            ptr = mem2hex((char *)&registers[Y],
888
                    ptr + 32 * 4 * 2,
889
                    8 * 4,
890
                    0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
891
            ptr = mem2hex((char *)&registers[CCSR],
892
                    ptr,
893
                    8 * 4,
894
                    0); /* CCSR, CCPR, CCCRCR, CCOR, CCOBR, CCIBR, CCIR */
895
            ptr = mem2hex((char *)&registers[ASR1],
896
                    ptr,
897
                    8 * 4,
898
                    0); /* ASR1,ASR15,ASR17,ASR18,ASR19,ASR20,ASR21,ASR22 */
899
#if 0 /* not implemented */
900
            ptr = mem2hex((char *) &registers[AWR0],
901
                    ptr,
902
                    32 * 4,
903
                    0); /* Alternate Window Registers */
904
#endif
905
          }
906
          break;
907
 
908
        case 'G':       /* set value of all the CPU registers - return OK */
909
        case 'P':       /* set value of one CPU register      - return OK */
910
          {
911
            unsigned long *newsp, psr;
912
 
913
            psr = registers[PSR];
914
 
915
            if (ptr[-1] == 'P') /* do a single register */
916
              {
917
                int regno;
918
 
919
                if (hexToInt (&ptr, &regno)
920
                    && *ptr++ == '=')
921
                  if (regno >= L0 && regno <= I7)
922
                    hex2mem (ptr, sp + regno - L0, 4, 0);
923
                  else
924
                    hex2mem (ptr, (char *)&registers[regno], 4, 0);
925
                else
926
                  {
927
                    strcpy (remcomOutBuffer, "E01");
928
                    break;
929
                  }
930
              }
931
            else
932
              {
933
                hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
934
                hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */
935
                hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y],
936
                        8 * 4, 0); /* Y,PSR,WIM,TBR,PC,NPC,FPSR,CPSR */
937
                hex2mem(ptr + 72 * 4 * 2, (char *)&registers[CCSR],
938
                        8 * 4, 0); /* CCSR,CCPR,CCCRCR,CCOR,CCOBR,CCIBR,CCIR */
939
                hex2mem(ptr + 80 * 4 * 2, (char *)&registers[ASR1],
940
                        8 * 4, 0); /* ASR1 ... ASR22 */
941
#if 0 /* not implemented */
942
                hex2mem(ptr + 88 * 4 * 2, (char *)&registers[AWR0],
943
                        8 * 4, 0); /* Alternate Window Registers */
944
#endif
945
              }
946
            /* See if the stack pointer has moved.  If so, then copy the saved
947
               locals and ins to the new location.  This keeps the window
948
               overflow and underflow routines happy.  */
949
 
950
            newsp = (unsigned long *)registers[SP];
951
            if (sp != newsp)
952
              sp = memcpy(newsp, sp, 16 * 4);
953
 
954
            /* Don't allow CWP to be modified. */
955
 
956
            if (psr != registers[PSR])
957
              registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
958
 
959
            strcpy(remcomOutBuffer,"OK");
960
          }
961
          break;
962
 
963
        case 'm':         /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
964
          /* Try to read %x,%x.  */
965
 
966
          if (hexToInt(&ptr, &addr)
967
              && *ptr++ == ','
968
              && hexToInt(&ptr, &length))
969
            {
970
              if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
971
                break;
972
 
973
              strcpy (remcomOutBuffer, "E03");
974
            }
975
          else
976
            strcpy(remcomOutBuffer,"E01");
977
          break;
978
 
979
        case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
980
          /* Try to read '%x,%x:'.  */
981
 
982
          if (hexToInt(&ptr, &addr)
983
              && *ptr++ == ','
984
              && hexToInt(&ptr, &length)
985
              && *ptr++ == ':')
986
            {
987
              if (hex2mem(ptr, (char *)addr, length, 1))
988
                strcpy(remcomOutBuffer, "OK");
989
              else
990
                strcpy(remcomOutBuffer, "E03");
991
            }
992
          else
993
            strcpy(remcomOutBuffer, "E02");
994
          break;
995
 
996
        case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
997
          /* try to read optional parameter, pc unchanged if no parm */
998
 
999
          if (hexToInt(&ptr, &addr))
1000
            {
1001
              registers[PC] = addr;
1002
              registers[NPC] = addr + 4;
1003
            }
1004
 
1005
/* Need to flush the instruction cache here, as we may have deposited a
1006
   breakpoint, and the icache probably has no way of knowing that a data ref to
1007
   some location may have changed something that is in the instruction cache.
1008
 */
1009
 
1010
          flush_i_cache();
1011
          return;
1012
 
1013
          /* kill the program */
1014
        case 'k' :              /* do nothing */
1015
          break;
1016
#if 0
1017
        case 't':               /* Test feature */
1018
          asm (" std %f30,[%sp]");
1019
          break;
1020
#endif
1021
        case 'r':               /* Reset */
1022
          asm ("call 0
1023
                nop ");
1024
          break;
1025
        }                       /* switch */
1026
 
1027
      /* reply to the request */
1028
      putpacket(remcomOutBuffer);
1029
    }
1030
}
1031
 
1032
/* This function will generate a breakpoint exception.  It is used at the
1033
   beginning of a program to sync up with a debugger and can be used
1034
   otherwise as a quick means to stop program execution and "break" into
1035
   the debugger. */
1036
 
1037
void
1038
breakpoint (void)
1039
{
1040
  if (!initialized)
1041
    return;
1042
 
1043
  asm(" .globl _breakinst
1044
 
1045
        _breakinst: ta 1
1046
      ");
1047
}
1048
 
1049
static void
1050
hw_breakpoint (void)
1051
{
1052
  asm("
1053
      ta 127
1054
      ");
1055
}
1056
 
1057
#if 0 /* experimental and never finished, left here for reference */
1058
static void
1059
splet_temp(void)
1060
{
1061
  asm(" sub     %sp,(16+1+6+1+121)*4,%sp ! Make room for input & locals
1062
                                        ! + hidden arg + arg spill
1063
                                        ! + doubleword alignment
1064
                                        ! + registers[121]
1065
 
1066
! Leave a trail of breadcrumbs! (save register save area for debugging)
1067
        mov     %sp, %l0
1068
        add     %l0, 24*4, %l0
1069
        sethi   %hi(_debug_registers), %l1
1070
        st      %l0, [%lo(_debug_registers) + %l1]
1071
 
1072
! Save the Alternate Register Set: (not implemented yet)
1073
!    To save the Alternate Register set, we must:
1074
!    1) Save the current SP in some global location.
1075
!    2) Swap the register sets.
1076
!    3) Save the Alternate SP in the Y register
1077
!    4) Fetch the SP that we saved in step 1.
1078
!    5) Use that to save the rest of the regs (not forgetting ASP in Y)
1079
!    6) Restore the Alternate SP from Y
1080
!    7) Swap the registers back.
1081
 
1082
! 1) Copy the current stack pointer to global _SAVED_STACK_POINTER:
1083
        sethi   %hi(_saved_stack_pointer), %l0
1084
        st      %sp, [%lo(_saved_stack_pointer) + %l0]
1085
 
1086
! 2) Swap the register sets:
1087
        mov     %psr, %l1
1088
        sethi   %hi(0x10000), %l2
1089
        xor     %l1, %l2, %l1
1090
        mov     %l1, %psr
1091
        nop                     ! 3 nops after write to %psr (needed?)
1092
        nop
1093
        nop
1094
 
1095
! 3) Save Alternate L0 in Y
1096
        wr      %l0, 0, %y
1097
 
1098
! 4) Load former SP into alternate SP, using L0
1099
        sethi   %hi(_saved_stack_pointer), %l0
1100
        or      %lo(_saved_stack_pointer), %l0, %l0
1101
        swap    [%l0], %sp
1102
 
1103
! 4.5) Restore alternate L0
1104
        rd      %y, %l0
1105
 
1106
! 5) Save the Alternate Window Registers
1107
        st      %r0, [%sp + (24 + 88) * 4]      ! AWR0
1108
        st      %r1, [%sp + (24 + 89) * 4]      ! AWR1
1109
        st      %r2, [%sp + (24 + 90) * 4]      ! AWR2
1110
        st      %r3, [%sp + (24 + 91) * 4]      ! AWR3
1111
        st      %r4, [%sp + (24 + 92) * 4]      ! AWR4
1112
        st      %r5, [%sp + (24 + 93) * 4]      ! AWR5
1113
        st      %r6, [%sp + (24 + 94) * 4]      ! AWR6
1114
        st      %r7, [%sp + (24 + 95) * 4]      ! AWR7
1115
        st      %r8, [%sp + (24 + 96) * 4]      ! AWR8
1116
        st      %r9, [%sp + (24 + 97) * 4]      ! AWR9
1117
        st      %r10, [%sp + (24 + 98) * 4]     ! AWR10
1118
        st      %r11, [%sp + (24 + 99) * 4]     ! AWR11
1119
        st      %r12, [%sp + (24 + 100) * 4]    ! AWR12
1120
        st      %r13, [%sp + (24 + 101) * 4]    ! AWR13
1121
!       st      %r14, [%sp + (24 + 102) * 4]    ! AWR14 (SP)
1122
        st      %r15, [%sp + (24 + 103) * 4]    ! AWR15
1123
        st      %r16, [%sp + (24 + 104) * 4]    ! AWR16
1124
        st      %r17, [%sp + (24 + 105) * 4]    ! AWR17
1125
        st      %r18, [%sp + (24 + 106) * 4]    ! AWR18
1126
        st      %r19, [%sp + (24 + 107) * 4]    ! AWR19
1127
        st      %r20, [%sp + (24 + 108) * 4]    ! AWR20
1128
        st      %r21, [%sp + (24 + 109) * 4]    ! AWR21
1129
        st      %r22, [%sp + (24 + 110) * 4]    ! AWR22
1130
        st      %r23, [%sp + (24 + 111) * 4]    ! AWR23
1131
        st      %r24, [%sp + (24 + 112) * 4]    ! AWR24
1132
        st      %r25, [%sp + (24 + 113) * 4]    ! AWR25
1133
        st      %r26, [%sp + (24 + 114) * 4]    ! AWR26
1134
        st      %r27, [%sp + (24 + 115) * 4]    ! AWR27
1135
        st      %r28, [%sp + (24 + 116) * 4]    ! AWR28
1136
        st      %r29, [%sp + (24 + 117) * 4]    ! AWR29
1137
        st      %r30, [%sp + (24 + 118) * 4]    ! AWR30
1138
        st      %r31, [%sp + (24 + 119) * 4]    ! AWR21
1139
 
1140
! Get the Alternate PSR (I hope...)
1141
 
1142
        rd      %psr, %l2
1143
        st      %l2, [%sp + (24 + 120) * 4]     ! APSR
1144
 
1145
! Don't forget the alternate stack pointer
1146
 
1147
        rd      %y, %l3
1148
        st      %l3, [%sp + (24 + 102) * 4]     ! AWR14 (SP)
1149
 
1150
! 6) Restore the Alternate SP (saved in Y)
1151
 
1152
        rd      %y, %o6
1153
 
1154
 
1155
! 7) Swap the registers back:
1156
 
1157
        mov     %psr, %l1
1158
        sethi   %hi(0x10000), %l2
1159
        xor     %l1, %l2, %l1
1160
        mov     %l1, %psr
1161
        nop                     ! 3 nops after write to %psr (needed?)
1162
        nop
1163
        nop
1164
");
1165
}
1166
 
1167
#endif

powered by: WebSVN 2.1.0

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