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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [newlib/] [libgloss/] [sparc/] [sparclet-stub.c] - Blame information for rev 1765

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

powered by: WebSVN 2.1.0

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