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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [newlib-1.17.0/] [libgloss/] [sparc/] [sparcl-stub.c] - Blame information for rev 822

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

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

powered by: WebSVN 2.1.0

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