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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [sparclet-stub.c] - Blame information for rev 104

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

Line No. Rev Author Line
1 104 markom
/****************************************************************************
2
 
3
                THIS SOFTWARE IS NOT COPYRIGHTED
4
 
5
   HP offers the following for use in the public domain.  HP makes no
6
   warranty with regard to the software or it's performance and the
7
   user accepts the software "AS IS" with all faults.
8
 
9
   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
10
   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
11
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12
 
13
****************************************************************************/
14
 
15
/****************************************************************************
16
 *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
17
 *
18
 *  Module name: remcom.c $
19
 *  Revision: 1.34 $
20
 *  Date: 91/03/09 12:29:49 $
21
 *  Contributor:     Lake Stevens Instrument Division$
22
 *
23
 *  Description:     low level support for gdb debugger. $
24
 *
25
 *  Considerations:  only works on target hardware $
26
 *
27
 *  Written by:      Glenn Engel $
28
 *  ModuleState:     Experimental $
29
 *
30
 *  NOTES:           See Below $
31
 *
32
 *  Modified for SPARC by Stu Grossman, Cygnus Support.
33
 *  Based on sparc-stub.c, it's modified for SPARClite Debug Unit hardware
34
 *  breakpoint support to create sparclite-stub.c, by Kung Hsu, Cygnus Support.
35
 *
36
 *  This code has been extensively tested on the Fujitsu SPARClite demo board.
37
 *
38
 *  To enable debugger support, two things need to happen.  One, a
39
 *  call to set_debug_traps() is necessary in order to allow any breakpoints
40
 *  or error conditions to be properly intercepted and reported to gdb.
41
 *  Two, a breakpoint needs to be generated to begin communication.  This
42
 *  is most easily accomplished by a call to breakpoint().  Breakpoint()
43
 *  simulates a breakpoint by executing a trap #1.
44
 *
45
 *************
46
 *
47
 *    The following gdb commands are supported:
48
 *
49
 * command          function                               Return value
50
 *
51
 *    g             return the value of the CPU registers  hex data or ENN
52
 *    G             set the value of the CPU registers     OK or ENN
53
 *    P             set the value of a single CPU register OK or ENN
54
 *
55
 *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
56
 *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
57
 *
58
 *    c             Resume at current address              SNN   ( signal NN)
59
 *    cAA..AA       Continue at address AA..AA             SNN
60
 *
61
 *    s             Step one instruction                   SNN
62
 *    sAA..AA       Step one instruction from AA..AA       SNN
63
 *
64
 *    k             kill
65
 *
66
 *    ?             What was the last sigval ?             SNN   (signal NN)
67
 *
68
 * All commands and responses are sent with a packet which includes a
69
 * checksum.  A packet consists of
70
 *
71
 * $<packet info>#<checksum>.
72
 *
73
 * where
74
 * <packet info> :: <characters representing the command or response>
75
 * <checksum>    :: <two hex digits computed as modulo 256 sum of <packetinfo>>
76
 *
77
 * When a packet is received, it is first acknowledged with either '+' or '-'.
78
 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
79
 *
80
 * Example:
81
 *
82
 * Host:                  Reply:
83
 * $m0,10#2a               +$00010203040506070809101112131415#42
84
 *
85
 ****************************************************************************/
86
 
87
#include <string.h>
88
#include <signal.h>
89
 
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(ch)
439
     unsigned char ch;
440
{
441
  if (ch >= 'a' && ch <= 'f')
442
    return ch-'a'+10;
443
  if (ch >= '0' && ch <= '9')
444
    return ch-'0';
445
  if (ch >= 'A' && ch <= 'F')
446
    return ch-'A'+10;
447
  return -1;
448
}
449
 
450
static char remcomInBuffer[BUFMAX];
451
static char remcomOutBuffer[BUFMAX];
452
 
453
/* scan for the sequence $<data>#<checksum>     */
454
 
455
unsigned char *
456
getpacket ()
457
{
458
  unsigned char *buffer = &remcomInBuffer[0];
459
  unsigned char checksum;
460
  unsigned char xmitcsum;
461
  int count;
462
  char ch;
463
 
464
  while (1)
465
    {
466
      /* wait around for the start character, ignore all other characters */
467
      while ((ch = getDebugChar ()) != '$')
468
        ;
469
 
470
retry:
471
      checksum = 0;
472
      xmitcsum = -1;
473
      count = 0;
474
 
475
      /* now, read until a # or end of buffer is found */
476
      while (count < BUFMAX)
477
        {
478
          ch = getDebugChar ();
479
          if (ch == '$')
480
            goto retry;
481
          if (ch == '#')
482
            break;
483
          checksum = checksum + ch;
484
          buffer[count] = ch;
485
          count = count + 1;
486
        }
487
      buffer[count] = 0;
488
 
489
      if (ch == '#')
490
        {
491
          ch = getDebugChar ();
492
          xmitcsum = hex (ch) << 4;
493
          ch = getDebugChar ();
494
          xmitcsum += hex (ch);
495
 
496
          if (checksum != xmitcsum)
497
            {
498
              putDebugChar ('-');       /* failed checksum */
499
            }
500
          else
501
            {
502
              putDebugChar ('+');       /* successful transfer */
503
 
504
              /* if a sequence char is present, reply the sequence ID */
505
              if (buffer[2] == ':')
506
                {
507
                  putDebugChar (buffer[0]);
508
                  putDebugChar (buffer[1]);
509
 
510
                  return &buffer[3];
511
                }
512
 
513
              return &buffer[0];
514
            }
515
        }
516
    }
517
}
518
 
519
/* send the packet in buffer.  */
520
 
521
static void
522
putpacket(buffer)
523
     unsigned char *buffer;
524
{
525
  unsigned char checksum;
526
  int count;
527
  unsigned char ch;
528
 
529
  /*  $<packet info>#<checksum>. */
530
  do
531
    {
532
      putDebugChar('$');
533
      checksum = 0;
534
      count = 0;
535
 
536
      while (ch = buffer[count])
537
        {
538
          putDebugChar(ch);
539
          checksum += ch;
540
          count += 1;
541
        }
542
 
543
      putDebugChar('#');
544
      putDebugChar(hexchars[checksum >> 4]);
545
      putDebugChar(hexchars[checksum & 0xf]);
546
 
547
    }
548
  while (getDebugChar() != '+');
549
}
550
 
551
/* Indicate to caller of mem2hex or hex2mem that there has been an
552
   error.  */
553
static volatile int mem_err = 0;
554
 
555
/* Convert the memory pointed to by mem into hex, placing result in buf.
556
 * Return a pointer to the last char put in buf (null), in case of mem fault,
557
 * return 0.
558
 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
559
 * a 0, else treat a fault like any other fault in the stub.
560
 */
561
 
562
static unsigned char *
563
mem2hex(mem, buf, count, may_fault)
564
     unsigned char *mem;
565
     unsigned char *buf;
566
     int count;
567
     int may_fault;
568
{
569
  unsigned char ch;
570
 
571
  set_mem_fault_trap(may_fault);
572
 
573
  while (count-- > 0)
574
    {
575
      ch = *mem++;
576
      if (mem_err)
577
        return 0;
578
      *buf++ = hexchars[ch >> 4];
579
      *buf++ = hexchars[ch & 0xf];
580
    }
581
 
582
  *buf = 0;
583
 
584
  set_mem_fault_trap(0);
585
 
586
  return buf;
587
}
588
 
589
/* convert the hex array pointed to by buf into binary to be placed in mem
590
 * return a pointer to the character AFTER the last byte written */
591
 
592
static char *
593
hex2mem(buf, mem, count, may_fault)
594
     unsigned char *buf;
595
     unsigned char *mem;
596
     int count;
597
     int may_fault;
598
{
599
  int i;
600
  unsigned char ch;
601
 
602
  set_mem_fault_trap(may_fault);
603
 
604
  for (i=0; i<count; i++)
605
    {
606
      ch = hex(*buf++) << 4;
607
      ch |= hex(*buf++);
608
      *mem++ = ch;
609
      if (mem_err)
610
        return 0;
611
    }
612
 
613
  set_mem_fault_trap(0);
614
 
615
  return mem;
616
}
617
 
618
/* This table contains the mapping between SPARC hardware trap types, and
619
   signals, which are primarily what GDB understands.  It also indicates
620
   which hardware traps we need to commandeer when initializing the stub. */
621
 
622
static struct hard_trap_info
623
{
624
  unsigned char tt;             /* Trap type code for SPARClite */
625
  unsigned char signo;          /* Signal that we map this trap into */
626
} hard_trap_info[] = {
627
  {1, SIGSEGV},                 /* instruction access exception */
628
  {0x3b, SIGSEGV},              /* instruction access error */
629
  {2, SIGILL},                  /* illegal    instruction */
630
  {3, SIGILL},                  /* privileged instruction */
631
  {4, SIGEMT},                  /* fp disabled */
632
  {0x24, SIGEMT},               /* cp disabled */
633
  {7, SIGBUS},                  /* mem address not aligned */
634
  {0x29, SIGSEGV},              /* data access exception */
635
  {10, SIGEMT},                 /* tag overflow */
636
  {128+1, SIGTRAP},             /* ta 1 - normal breakpoint instruction */
637
  {0, 0}                  /* Must be last */
638
};
639
 
640
/* Set up exception handlers for tracing and breakpoints */
641
 
642
void
643
set_debug_traps()
644
{
645
  struct hard_trap_info *ht;
646
 
647
  for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
648
    exceptionHandler(ht->tt, trap_low);
649
 
650
  initialized = 1;
651
}
652
 
653
asm ("
654
! Trap handler for memory errors.  This just sets mem_err to be non-zero.  It
655
! assumes that %l1 is non-zero.  This should be safe, as it is doubtful that
656
! 0 would ever contain code that could mem fault.  This routine will skip
657
! past the faulting instruction after setting mem_err.
658
 
659
        .text
660
        .align 4
661
 
662
_fltr_set_mem_err:
663
        sethi %hi(_mem_err), %l0
664
        st %l1, [%l0 + %lo(_mem_err)]
665
        jmpl %l2, %g0
666
        rett %l2+4
667
");
668
 
669
static void
670
set_mem_fault_trap(enable)
671
     int enable;
672
{
673
  extern void fltr_set_mem_err();
674
  mem_err = 0;
675
 
676
  if (enable)
677
    exceptionHandler(0x29, fltr_set_mem_err);
678
  else
679
    exceptionHandler(0x29, trap_low);
680
}
681
 
682
asm ("
683
        .text
684
        .align 4
685
 
686
_dummy_hw_breakpoint:
687
        jmpl %l2, %g0
688
        rett %l2+4
689
        nop
690
        nop
691
");
692
 
693
static void
694
set_hw_breakpoint_trap(enable)
695
     int enable;
696
{
697
  extern void dummy_hw_breakpoint();
698
 
699
  if (enable)
700
    exceptionHandler(255, dummy_hw_breakpoint);
701
  else
702
    exceptionHandler(255, trap_low);
703
}
704
 
705
static void
706
get_in_break_mode()
707
{
708
#if 0
709
  int x;
710
  mesg("get_in_break_mode, sp = ");
711
  phex(&x);
712
#endif
713
  set_hw_breakpoint_trap(1);
714
 
715
  asm("
716
        sethi   %hi(0xff10), %l4
717
        or      %l4, %lo(0xff10), %l4
718
        sta     %g0, [%l4]0x1
719
        nop
720
        nop
721
        nop
722
      ");
723
 
724
  set_hw_breakpoint_trap(0);
725
}
726
 
727
/* Convert the SPARC hardware trap type code to a unix signal number. */
728
 
729
static int
730
computeSignal(tt)
731
     int tt;
732
{
733
  struct hard_trap_info *ht;
734
 
735
  for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
736
    if (ht->tt == tt)
737
      return ht->signo;
738
 
739
  return SIGHUP;                /* default for things we don't know about */
740
}
741
 
742
/*
743
 * While we find nice hex chars, build an int.
744
 * Return number of chars processed.
745
 */
746
 
747
static int
748
hexToInt(char **ptr, int *intValue)
749
{
750
  int numChars = 0;
751
  int hexValue;
752
 
753
  *intValue = 0;
754
 
755
  while (**ptr)
756
    {
757
      hexValue = hex(**ptr);
758
      if (hexValue < 0)
759
        break;
760
 
761
      *intValue = (*intValue << 4) | hexValue;
762
      numChars ++;
763
 
764
      (*ptr)++;
765
    }
766
 
767
  return (numChars);
768
}
769
 
770
/*
771
 * This function does all command procesing for interfacing to gdb.  It
772
 * returns 1 if you should skip the instruction at the trap address, 0
773
 * otherwise.
774
 */
775
 
776
static void
777
handle_exception (registers)
778
     unsigned long *registers;
779
{
780
  int tt;                       /* Trap type */
781
  int sigval;
782
  int addr;
783
  int length;
784
  char *ptr;
785
  unsigned long *sp;
786
  unsigned long dsr;
787
 
788
/* First, we must force all of the windows to be spilled out */
789
 
790
  asm("
791
        ! Ugh.  sparclet has broken save
792
        !save %sp, -64, %sp
793
        save
794
        add %fp,-64,%sp
795
        !save %sp, -64, %sp
796
        save
797
        add %fp,-64,%sp
798
        !save %sp, -64, %sp
799
        save
800
        add %fp,-64,%sp
801
        !save %sp, -64, %sp
802
        save
803
        add %fp,-64,%sp
804
        !save %sp, -64, %sp
805
        save
806
        add %fp,-64,%sp
807
        !save %sp, -64, %sp
808
        save
809
        add %fp,-64,%sp
810
        !save %sp, -64, %sp
811
        save
812
        add %fp,-64,%sp
813
        !save %sp, -64, %sp
814
        save
815
        add %fp,-64,%sp
816
        restore
817
        restore
818
        restore
819
        restore
820
        restore
821
        restore
822
        restore
823
        restore
824
");
825
 
826
  if (registers[PC] == (unsigned long)breakinst)
827
    {
828
      registers[PC] = registers[NPC];
829
      registers[NPC] += 4;
830
    }
831
  sp = (unsigned long *)registers[SP];
832
 
833
  tt = (registers[TBR] >> 4) & 0xff;
834
 
835
  /* reply to host that an exception has occurred */
836
  sigval = computeSignal(tt);
837
  ptr = remcomOutBuffer;
838
 
839
  *ptr++ = 'T';
840
  *ptr++ = hexchars[sigval >> 4];
841
  *ptr++ = hexchars[sigval & 0xf];
842
 
843
  *ptr++ = hexchars[PC >> 4];
844
  *ptr++ = hexchars[PC & 0xf];
845
  *ptr++ = ':';
846
  ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
847
  *ptr++ = ';';
848
 
849
  *ptr++ = hexchars[FP >> 4];
850
  *ptr++ = hexchars[FP & 0xf];
851
  *ptr++ = ':';
852
  ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
853
  *ptr++ = ';';
854
 
855
  *ptr++ = hexchars[SP >> 4];
856
  *ptr++ = hexchars[SP & 0xf];
857
  *ptr++ = ':';
858
  ptr = mem2hex((char *)&sp, ptr, 4, 0);
859
  *ptr++ = ';';
860
 
861
  *ptr++ = hexchars[NPC >> 4];
862
  *ptr++ = hexchars[NPC & 0xf];
863
  *ptr++ = ':';
864
  ptr = mem2hex((char *)&registers[NPC], ptr, 4, 0);
865
  *ptr++ = ';';
866
 
867
  *ptr++ = hexchars[O7 >> 4];
868
  *ptr++ = hexchars[O7 & 0xf];
869
  *ptr++ = ':';
870
  ptr = mem2hex((char *)&registers[O7], ptr, 4, 0);
871
  *ptr++ = ';';
872
 
873
  *ptr++ = 0;
874
 
875
  putpacket(remcomOutBuffer);
876
 
877
  while (1)
878
    {
879
      remcomOutBuffer[0] = 0;
880
 
881
      ptr = getpacket();
882
      switch (*ptr++)
883
        {
884
        case '?':
885
          remcomOutBuffer[0] = 'S';
886
          remcomOutBuffer[1] = hexchars[sigval >> 4];
887
          remcomOutBuffer[2] = hexchars[sigval & 0xf];
888
          remcomOutBuffer[3] = 0;
889
          break;
890
 
891
        case 'd':
892
          remote_debug = !(remote_debug);       /* toggle debug flag */
893
          break;
894
 
895
        case 'g':               /* return the value of the CPU registers */
896
          {
897
            ptr = remcomOutBuffer;
898
            ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
899
            ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */
900
            memset(ptr, '0', 32 * 8); /* Floating point */
901
            ptr = mem2hex((char *)&registers[Y],
902
                    ptr + 32 * 4 * 2,
903
                    8 * 4,
904
                    0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
905
            ptr = mem2hex((char *)&registers[CCSR],
906
                    ptr,
907
                    8 * 4,
908
                    0); /* CCSR, CCPR, CCCRCR, CCOR, CCOBR, CCIBR, CCIR */
909
            ptr = mem2hex((char *)&registers[ASR1],
910
                    ptr,
911
                    8 * 4,
912
                    0); /* ASR1,ASR15,ASR17,ASR18,ASR19,ASR20,ASR21,ASR22 */
913
#if 0 /* not implemented */
914
            ptr = mem2hex((char *) &registers[AWR0],
915
                    ptr,
916
                    32 * 4,
917
                    0); /* Alternate Window Registers */
918
#endif
919
          }
920
          break;
921
 
922
        case 'G':       /* set value of all the CPU registers - return OK */
923
        case 'P':       /* set value of one CPU register      - return OK */
924
          {
925
            unsigned long *newsp, psr;
926
 
927
            psr = registers[PSR];
928
 
929
            if (ptr[-1] == 'P') /* do a single register */
930
              {
931
                int regno;
932
 
933
                if (hexToInt (&ptr, &regno)
934
                    && *ptr++ == '=')
935
                  if (regno >= L0 && regno <= I7)
936
                    hex2mem (ptr, sp + regno - L0, 4, 0);
937
                  else
938
                    hex2mem (ptr, (char *)&registers[regno], 4, 0);
939
                else
940
                  {
941
                    strcpy (remcomOutBuffer, "E01");
942
                    break;
943
                  }
944
              }
945
            else
946
              {
947
                hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
948
                hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */
949
                hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y],
950
                        8 * 4, 0); /* Y,PSR,WIM,TBR,PC,NPC,FPSR,CPSR */
951
                hex2mem(ptr + 72 * 4 * 2, (char *)&registers[CCSR],
952
                        8 * 4, 0); /* CCSR,CCPR,CCCRCR,CCOR,CCOBR,CCIBR,CCIR */
953
                hex2mem(ptr + 80 * 4 * 2, (char *)&registers[ASR1],
954
                        8 * 4, 0); /* ASR1 ... ASR22 */
955
#if 0 /* not implemented */
956
                hex2mem(ptr + 88 * 4 * 2, (char *)&registers[AWR0],
957
                        8 * 4, 0); /* Alternate Window Registers */
958
#endif
959
              }
960
            /* See if the stack pointer has moved.  If so, then copy the saved
961
               locals and ins to the new location.  This keeps the window
962
               overflow and underflow routines happy.  */
963
 
964
            newsp = (unsigned long *)registers[SP];
965
            if (sp != newsp)
966
              sp = memcpy(newsp, sp, 16 * 4);
967
 
968
            /* Don't allow CWP to be modified. */
969
 
970
            if (psr != registers[PSR])
971
              registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
972
 
973
            strcpy(remcomOutBuffer,"OK");
974
          }
975
          break;
976
 
977
        case 'm':         /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
978
          /* Try to read %x,%x.  */
979
 
980
          if (hexToInt(&ptr, &addr)
981
              && *ptr++ == ','
982
              && hexToInt(&ptr, &length))
983
            {
984
              if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
985
                break;
986
 
987
              strcpy (remcomOutBuffer, "E03");
988
            }
989
          else
990
            strcpy(remcomOutBuffer,"E01");
991
          break;
992
 
993
        case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
994
          /* Try to read '%x,%x:'.  */
995
 
996
          if (hexToInt(&ptr, &addr)
997
              && *ptr++ == ','
998
              && hexToInt(&ptr, &length)
999
              && *ptr++ == ':')
1000
            {
1001
              if (hex2mem(ptr, (char *)addr, length, 1))
1002
                strcpy(remcomOutBuffer, "OK");
1003
              else
1004
                strcpy(remcomOutBuffer, "E03");
1005
            }
1006
          else
1007
            strcpy(remcomOutBuffer, "E02");
1008
          break;
1009
 
1010
        case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
1011
          /* try to read optional parameter, pc unchanged if no parm */
1012
 
1013
          if (hexToInt(&ptr, &addr))
1014
            {
1015
              registers[PC] = addr;
1016
              registers[NPC] = addr + 4;
1017
            }
1018
 
1019
/* Need to flush the instruction cache here, as we may have deposited a
1020
   breakpoint, and the icache probably has no way of knowing that a data ref to
1021
   some location may have changed something that is in the instruction cache.
1022
 */
1023
 
1024
          flush_i_cache();
1025
          return;
1026
 
1027
          /* kill the program */
1028
        case 'k' :              /* do nothing */
1029
          break;
1030
#if 0
1031
        case 't':               /* Test feature */
1032
          asm (" std %f30,[%sp]");
1033
          break;
1034
#endif
1035
        case 'r':               /* Reset */
1036
          asm ("call 0
1037
                nop ");
1038
          break;
1039
        }                       /* switch */
1040
 
1041
      /* reply to the request */
1042
      putpacket(remcomOutBuffer);
1043
    }
1044
}
1045
 
1046
/* This function will generate a breakpoint exception.  It is used at the
1047
   beginning of a program to sync up with a debugger and can be used
1048
   otherwise as a quick means to stop program execution and "break" into
1049
   the debugger. */
1050
 
1051
void
1052
breakpoint()
1053
{
1054
  if (!initialized)
1055
    return;
1056
 
1057
  asm(" .globl _breakinst
1058
 
1059
        _breakinst: ta 1
1060
      ");
1061
}
1062
 
1063
static void
1064
hw_breakpoint()
1065
{
1066
  asm("
1067
      ta 127
1068
      ");
1069
}
1070
 
1071
#if 0 /* experimental and never finished, left here for reference */
1072
static void
1073
splet_temp(void)
1074
{
1075
  asm(" sub     %sp,(16+1+6+1+121)*4,%sp ! Make room for input & locals
1076
                                        ! + hidden arg + arg spill
1077
                                        ! + doubleword alignment
1078
                                        ! + registers[121]
1079
 
1080
! Leave a trail of breadcrumbs! (save register save area for debugging)
1081
        mov     %sp, %l0
1082
        add     %l0, 24*4, %l0
1083
        sethi   %hi(_debug_registers), %l1
1084
        st      %l0, [%lo(_debug_registers) + %l1]
1085
 
1086
! Save the Alternate Register Set: (not implemented yet)
1087
!    To save the Alternate Register set, we must:
1088
!    1) Save the current SP in some global location.
1089
!    2) Swap the register sets.
1090
!    3) Save the Alternate SP in the Y register
1091
!    4) Fetch the SP that we saved in step 1.
1092
!    5) Use that to save the rest of the regs (not forgetting ASP in Y)
1093
!    6) Restore the Alternate SP from Y
1094
!    7) Swap the registers back.
1095
 
1096
! 1) Copy the current stack pointer to global _SAVED_STACK_POINTER:
1097
        sethi   %hi(_saved_stack_pointer), %l0
1098
        st      %sp, [%lo(_saved_stack_pointer) + %l0]
1099
 
1100
! 2) Swap the register sets:
1101
        mov     %psr, %l1
1102
        sethi   %hi(0x10000), %l2
1103
        xor     %l1, %l2, %l1
1104
        mov     %l1, %psr
1105
        nop                     ! 3 nops after write to %psr (needed?)
1106
        nop
1107
        nop
1108
 
1109
! 3) Save Alternate L0 in Y
1110
        wr      %l0, 0, %y
1111
 
1112
! 4) Load former SP into alternate SP, using L0
1113
        sethi   %hi(_saved_stack_pointer), %l0
1114
        or      %lo(_saved_stack_pointer), %l0, %l0
1115
        swap    [%l0], %sp
1116
 
1117
! 4.5) Restore alternate L0
1118
        rd      %y, %l0
1119
 
1120
! 5) Save the Alternate Window Registers
1121
        st      %r0, [%sp + (24 + 88) * 4]      ! AWR0
1122
        st      %r1, [%sp + (24 + 89) * 4]      ! AWR1
1123
        st      %r2, [%sp + (24 + 90) * 4]      ! AWR2
1124
        st      %r3, [%sp + (24 + 91) * 4]      ! AWR3
1125
        st      %r4, [%sp + (24 + 92) * 4]      ! AWR4
1126
        st      %r5, [%sp + (24 + 93) * 4]      ! AWR5
1127
        st      %r6, [%sp + (24 + 94) * 4]      ! AWR6
1128
        st      %r7, [%sp + (24 + 95) * 4]      ! AWR7
1129
        st      %r8, [%sp + (24 + 96) * 4]      ! AWR8
1130
        st      %r9, [%sp + (24 + 97) * 4]      ! AWR9
1131
        st      %r10, [%sp + (24 + 98) * 4]     ! AWR10
1132
        st      %r11, [%sp + (24 + 99) * 4]     ! AWR11
1133
        st      %r12, [%sp + (24 + 100) * 4]    ! AWR12
1134
        st      %r13, [%sp + (24 + 101) * 4]    ! AWR13
1135
!       st      %r14, [%sp + (24 + 102) * 4]    ! AWR14 (SP)
1136
        st      %r15, [%sp + (24 + 103) * 4]    ! AWR15
1137
        st      %r16, [%sp + (24 + 104) * 4]    ! AWR16
1138
        st      %r17, [%sp + (24 + 105) * 4]    ! AWR17
1139
        st      %r18, [%sp + (24 + 106) * 4]    ! AWR18
1140
        st      %r19, [%sp + (24 + 107) * 4]    ! AWR19
1141
        st      %r20, [%sp + (24 + 108) * 4]    ! AWR20
1142
        st      %r21, [%sp + (24 + 109) * 4]    ! AWR21
1143
        st      %r22, [%sp + (24 + 110) * 4]    ! AWR22
1144
        st      %r23, [%sp + (24 + 111) * 4]    ! AWR23
1145
        st      %r24, [%sp + (24 + 112) * 4]    ! AWR24
1146
        st      %r25, [%sp + (24 + 113) * 4]    ! AWR25
1147
        st      %r26, [%sp + (24 + 114) * 4]    ! AWR26
1148
        st      %r27, [%sp + (24 + 115) * 4]    ! AWR27
1149
        st      %r28, [%sp + (24 + 116) * 4]    ! AWR28
1150
        st      %r29, [%sp + (24 + 117) * 4]    ! AWR29
1151
        st      %r30, [%sp + (24 + 118) * 4]    ! AWR30
1152
        st      %r31, [%sp + (24 + 119) * 4]    ! AWR21
1153
 
1154
! Get the Alternate PSR (I hope...)
1155
 
1156
        rd      %psr, %l2
1157
        st      %l2, [%sp + (24 + 120) * 4]     ! APSR
1158
 
1159
! Don't forget the alternate stack pointer
1160
 
1161
        rd      %y, %l3
1162
        st      %l3, [%sp + (24 + 102) * 4]     ! AWR14 (SP)
1163
 
1164
! 6) Restore the Alternate SP (saved in Y)
1165
 
1166
        rd      %y, %o6
1167
 
1168
 
1169
! 7) Swap the registers back:
1170
 
1171
        mov     %psr, %l1
1172
        sethi   %hi(0x10000), %l2
1173
        xor     %l1, %l2, %l1
1174
        mov     %l1, %psr
1175
        nop                     ! 3 nops after write to %psr (needed?)
1176
        nop
1177
        nop
1178
");
1179
}
1180
 
1181
#endif

powered by: WebSVN 2.1.0

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