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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/****************************************************************************
2
 
3
                THIS SOFTWARE IS NOT COPYRIGHTED
4
 
5
   HP offers the following for use in the public domain.  HP makes no
6
   warranty with regard to the software or it's performance and the
7
   user accepts the software "AS IS" with all faults.
8
 
9
   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
10
   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
11
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12
 
13
****************************************************************************/
14
 
15
/****************************************************************************
16
 *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
17
 *
18
 *  Module name: remcom.c $
19
 *  Revision: 1.34 $
20
 *  Date: 91/03/09 12:29:49 $
21
 *  Contributor:     Lake Stevens Instrument Division$
22
 *
23
 *  Description:     low level support for gdb debugger. $
24
 *
25
 *  Considerations:  only works on target hardware $
26
 *
27
 *  Written by:      Glenn Engel $
28
 *  ModuleState:     Experimental $
29
 *
30
 *  NOTES:           See Below $
31
 *
32
 *  Modified for SPARC by Stu Grossman, Cygnus Support.
33
 *
34
 *  This code has been extensively tested on the Fujitsu SPARClite demo board.
35
 *
36
 *  To enable debugger support, two things need to happen.  One, a
37
 *  call to set_debug_traps() is necessary in order to allow any breakpoints
38
 *  or error conditions to be properly intercepted and reported to gdb.
39
 *  Two, a breakpoint needs to be generated to begin communication.  This
40
 *  is most easily accomplished by a call to breakpoint().  Breakpoint()
41
 *  simulates a breakpoint by executing a trap #1.
42
 *
43
 *************
44
 *
45
 *    The following gdb commands are supported:
46
 *
47
 * command          function                               Return value
48
 *
49
 *    g             return the value of the CPU registers  hex data or ENN
50
 *    G             set the value of the CPU registers     OK or ENN
51
 *
52
 *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
53
 *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
54
 *
55
 *    c             Resume at current address              SNN   ( signal NN)
56
 *    cAA..AA       Continue at address AA..AA             SNN
57
 *
58
 *    s             Step one instruction                   SNN
59
 *    sAA..AA       Step one instruction from AA..AA       SNN
60
 *
61
 *    k             kill
62
 *
63
 *    ?             What was the last sigval ?             SNN   (signal NN)
64
 *
65
 * All commands and responses are sent with a packet which includes a
66
 * checksum.  A packet consists of
67
 *
68
 * $<packet info>#<checksum>.
69
 *
70
 * where
71
 * <packet info> :: <characters representing the command or response>
72
 * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
73
 *
74
 * When a packet is received, it is first acknowledged with either '+' or '-'.
75
 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
76
 *
77
 * Example:
78
 *
79
 * Host:                  Reply:
80
 * $m0,10#2a               +$00010203040506070809101112131415#42
81
 *
82
 ****************************************************************************/
83
 
84
#include <string.h>
85
#include <signal.h>
86
 
87
/************************************************************************
88
 *
89
 * external low-level support routines
90
 */
91
 
92
extern void putDebugChar();     /* write a single character      */
93
extern int getDebugChar();      /* read and return a single char */
94
 
95
/************************************************************************/
96
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
97
/* at least NUMREGBYTES*2 are needed for register packets */
98
#define BUFMAX 2048
99
 
100
static int initialized = 0;      /* !0 means we've been initialized */
101
 
102
static void set_mem_fault_trap();
103
 
104
static const char hexchars[]="0123456789abcdef";
105
 
106
#define NUMREGS 72
107
 
108
/* Number of bytes of registers.  */
109
#define NUMREGBYTES (NUMREGS * 4)
110
enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
111
                 O0, O1, O2, O3, O4, O5, SP, O7,
112
                 L0, L1, L2, L3, L4, L5, L6, L7,
113
                 I0, I1, I2, I3, I4, I5, FP, I7,
114
 
115
                 F0, F1, F2, F3, F4, F5, F6, F7,
116
                 F8, F9, F10, F11, F12, F13, F14, F15,
117
                 F16, F17, F18, F19, F20, F21, F22, F23,
118
                 F24, F25, F26, F27, F28, F29, F30, F31,
119
                 Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
120
 
121
/***************************  ASSEMBLY CODE MACROS *************************/
122
/*                                                                         */
123
 
124
extern void trap_low();
125
 
126
asm("
127
        .reserve trapstack, 1000 * 4, \"bss\", 8
128
 
129
        .data
130
        .align  4
131
 
132
in_trap_handler:
133
        .word   0
134
 
135
        .text
136
        .align 4
137
 
138
! This function is called when any SPARC trap (except window overflow or
139
! underflow) occurs.  It makes sure that the invalid register window is still
140
! available before jumping into C code.  It will also restore the world if you
141
! return from handle_exception.
142
 
143
        .globl _trap_low
144
_trap_low:
145
        mov     %psr, %l0
146
        mov     %wim, %l3
147
 
148
        srl     %l3, %l0, %l4           ! wim >> cwp
149
        cmp     %l4, 1
150
        bne     window_fine             ! Branch if not in the invalid window
151
        nop
152
 
153
! Handle window overflow
154
 
155
        mov     %g1, %l4                ! Save g1, we use it to hold the wim
156
        srl     %l3, 1, %g1             ! Rotate wim right
157
        tst     %g1
158
        bg      good_wim                ! Branch if new wim is non-zero
159
        nop
160
 
161
! At this point, we need to bring a 1 into the high order bit of the wim.
162
! Since we don't want to make any assumptions about the number of register
163
! windows, we figure it out dynamically so as to setup the wim correctly.
164
 
165
        not     %g1                     ! Fill g1 with ones
166
        mov     %g1, %wim               ! Fill the wim with ones
167
        nop
168
        nop
169
        nop
170
        mov     %wim, %g1               ! Read back the wim
171
        inc     %g1                     ! Now g1 has 1 just to left of wim
172
        srl     %g1, 1, %g1             ! Now put 1 at top of wim
173
        mov     %g0, %wim               ! Clear wim so that subsequent save
174
        nop                             !  won't trap
175
        nop
176
        nop
177
 
178
good_wim:
179
        save    %g0, %g0, %g0           ! Slip into next window
180
        mov     %g1, %wim               ! Install the new wim
181
 
182
        std     %l0, [%sp + 0 * 4]      ! save L & I registers
183
        std     %l2, [%sp + 2 * 4]
184
        std     %l4, [%sp + 4 * 4]
185
        std     %l6, [%sp + 6 * 4]
186
 
187
        std     %i0, [%sp + 8 * 4]
188
        std     %i2, [%sp + 10 * 4]
189
        std     %i4, [%sp + 12 * 4]
190
        std     %i6, [%sp + 14 * 4]
191
 
192
        restore                         ! Go back to trap window.
193
        mov     %l4, %g1                ! Restore %g1
194
 
195
window_fine:
196
        sethi   %hi(in_trap_handler), %l4
197
        ld      [%lo(in_trap_handler) + %l4], %l5
198
        tst     %l5
199
        bg      recursive_trap
200
        inc     %l5
201
 
202
        set     trapstack+1000*4, %sp   ! Switch to trap stack
203
 
204
recursive_trap:
205
        st      %l5, [%lo(in_trap_handler) + %l4]
206
        sub     %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals
207
                                        ! + hidden arg + arg spill
208
                                        ! + doubleword alignment
209
                                        ! + registers[72] local var
210
 
211
        std     %g0, [%sp + (24 + 0) * 4] ! registers[Gx]
212
        std     %g2, [%sp + (24 + 2) * 4]
213
        std     %g4, [%sp + (24 + 4) * 4]
214
        std     %g6, [%sp + (24 + 6) * 4]
215
 
216
        std     %i0, [%sp + (24 + 8) * 4] ! registers[Ox]
217
        std     %i2, [%sp + (24 + 10) * 4]
218
        std     %i4, [%sp + (24 + 12) * 4]
219
        std     %i6, [%sp + (24 + 14) * 4]
220
                                        ! F0->F31 not implemented
221
        mov     %y, %l4
222
        mov     %tbr, %l5
223
        st      %l4, [%sp + (24 + 64) * 4] ! Y
224
        st      %l0, [%sp + (24 + 65) * 4] ! PSR
225
        st      %l3, [%sp + (24 + 66) * 4] ! WIM
226
        st      %l5, [%sp + (24 + 67) * 4] ! TBR
227
        st      %l1, [%sp + (24 + 68) * 4] ! PC
228
        st      %l2, [%sp + (24 + 69) * 4] ! NPC
229
 
230
                                        ! CPSR and FPSR not impl
231
 
232
        or      %l0, 0xf20, %l4
233
        mov     %l4, %psr               ! Turn on traps, disable interrupts
234
 
235
        call    _handle_exception
236
        add     %sp, 24 * 4, %o0        ! Pass address of registers
237
 
238
! Reload all of the registers that aren't on the stack
239
 
240
        ld      [%sp + (24 + 1) * 4], %g1 ! registers[Gx]
241
        ldd     [%sp + (24 + 2) * 4], %g2
242
        ldd     [%sp + (24 + 4) * 4], %g4
243
        ldd     [%sp + (24 + 6) * 4], %g6
244
 
245
        ldd     [%sp + (24 + 8) * 4], %i0 ! registers[Ox]
246
        ldd     [%sp + (24 + 10) * 4], %i2
247
        ldd     [%sp + (24 + 12) * 4], %i4
248
        ldd     [%sp + (24 + 14) * 4], %i6
249
 
250
        ldd     [%sp + (24 + 64) * 4], %l0 ! Y & PSR
251
        ldd     [%sp + (24 + 68) * 4], %l2 ! PC & NPC
252
 
253
        restore                         ! Ensure that previous window is valid
254
        save    %g0, %g0, %g0           !  by causing a window_underflow trap
255
 
256
        mov     %l0, %y
257
        mov     %l1, %psr               ! Make sure that traps are disabled
258
                                        ! for rett
259
 
260
        sethi   %hi(in_trap_handler), %l4
261
        ld      [%lo(in_trap_handler) + %l4], %l5
262
        dec     %l5
263
        st      %l5, [%lo(in_trap_handler) + %l4]
264
 
265
        jmpl    %l2, %g0                ! Restore old PC
266
        rett    %l3                     ! Restore old nPC
267
");
268
 
269
/* Convert ch from a hex digit to an int */
270
 
271
static int
272
hex (unsigned char ch)
273
{
274
  if (ch >= 'a' && ch <= 'f')
275
    return ch-'a'+10;
276
  if (ch >= '0' && ch <= '9')
277
    return ch-'0';
278
  if (ch >= 'A' && ch <= 'F')
279
    return ch-'A'+10;
280
  return -1;
281
}
282
 
283
static char remcomInBuffer[BUFMAX];
284
static char remcomOutBuffer[BUFMAX];
285
 
286
/* scan for the sequence $<data>#<checksum>     */
287
 
288
unsigned char *
289
getpacket (void)
290
{
291
  unsigned char *buffer = &remcomInBuffer[0];
292
  unsigned char checksum;
293
  unsigned char xmitcsum;
294
  int count;
295
  char ch;
296
 
297
  while (1)
298
    {
299
      /* wait around for the start character, ignore all other characters */
300
      while ((ch = getDebugChar ()) != '$')
301
        ;
302
 
303
retry:
304
      checksum = 0;
305
      xmitcsum = -1;
306
      count = 0;
307
 
308
      /* now, read until a # or end of buffer is found */
309
      while (count < BUFMAX)
310
        {
311
          ch = getDebugChar ();
312
          if (ch == '$')
313
            goto retry;
314
          if (ch == '#')
315
            break;
316
          checksum = checksum + ch;
317
          buffer[count] = ch;
318
          count = count + 1;
319
        }
320
      buffer[count] = 0;
321
 
322
      if (ch == '#')
323
        {
324
          ch = getDebugChar ();
325
          xmitcsum = hex (ch) << 4;
326
          ch = getDebugChar ();
327
          xmitcsum += hex (ch);
328
 
329
          if (checksum != xmitcsum)
330
            {
331
              putDebugChar ('-');       /* failed checksum */
332
            }
333
          else
334
            {
335
              putDebugChar ('+');       /* successful transfer */
336
 
337
              /* if a sequence char is present, reply the sequence ID */
338
              if (buffer[2] == ':')
339
                {
340
                  putDebugChar (buffer[0]);
341
                  putDebugChar (buffer[1]);
342
 
343
                  return &buffer[3];
344
                }
345
 
346
              return &buffer[0];
347
            }
348
        }
349
    }
350
}
351
 
352
/* send the packet in buffer.  */
353
 
354
static void
355
putpacket (unsigned char *buffer)
356
{
357
  unsigned char checksum;
358
  int count;
359
  unsigned char ch;
360
 
361
  /*  $<packet info>#<checksum>. */
362
  do
363
    {
364
      putDebugChar('$');
365
      checksum = 0;
366
      count = 0;
367
 
368
      while (ch = buffer[count])
369
        {
370
          putDebugChar(ch);
371
          checksum += ch;
372
          count += 1;
373
        }
374
 
375
      putDebugChar('#');
376
      putDebugChar(hexchars[checksum >> 4]);
377
      putDebugChar(hexchars[checksum & 0xf]);
378
 
379
    }
380
  while (getDebugChar() != '+');
381
}
382
 
383
/* Indicate to caller of mem2hex or hex2mem that there has been an
384
   error.  */
385
static volatile int mem_err = 0;
386
 
387
/* Convert the memory pointed to by mem into hex, placing result in buf.
388
 * Return a pointer to the last char put in buf (null), in case of mem fault,
389
 * return 0.
390
 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
391
 * a 0, else treat a fault like any other fault in the stub.
392
 */
393
 
394
static unsigned char *
395
mem2hex (unsigned char *mem, unsigned char *buf, int count, int may_fault)
396
{
397
  unsigned char ch;
398
 
399
  set_mem_fault_trap(may_fault);
400
 
401
  while (count-- > 0)
402
    {
403
      ch = *mem++;
404
      if (mem_err)
405
        return 0;
406
      *buf++ = hexchars[ch >> 4];
407
      *buf++ = hexchars[ch & 0xf];
408
    }
409
 
410
  *buf = 0;
411
 
412
  set_mem_fault_trap(0);
413
 
414
  return buf;
415
}
416
 
417
/* convert the hex array pointed to by buf into binary to be placed in mem
418
 * return a pointer to the character AFTER the last byte written */
419
 
420
static char *
421
hex2mem (unsigned char *buf, unsigned char *mem, int count, int may_fault)
422
{
423
  int i;
424
  unsigned char ch;
425
 
426
  set_mem_fault_trap(may_fault);
427
 
428
  for (i=0; i<count; i++)
429
    {
430
      ch = hex(*buf++) << 4;
431
      ch |= hex(*buf++);
432
      *mem++ = ch;
433
      if (mem_err)
434
        return 0;
435
    }
436
 
437
  set_mem_fault_trap(0);
438
 
439
  return mem;
440
}
441
 
442
/* This table contains the mapping between SPARC hardware trap types, and
443
   signals, which are primarily what GDB understands.  It also indicates
444
   which hardware traps we need to commandeer when initializing the stub. */
445
 
446
static struct hard_trap_info
447
{
448
  unsigned char tt;             /* Trap type code for SPARClite */
449
  unsigned char signo;          /* Signal that we map this trap into */
450
} hard_trap_info[] = {
451
  {1, SIGSEGV},                 /* instruction access error */
452
  {2, SIGILL},                  /* privileged instruction */
453
  {3, SIGILL},                  /* illegal instruction */
454
  {4, SIGEMT},                  /* fp disabled */
455
  {36, SIGEMT},                 /* cp disabled */
456
  {7, SIGBUS},                  /* mem address not aligned */
457
  {9, SIGSEGV},                 /* data access exception */
458
  {10, SIGEMT},                 /* tag overflow */
459
  {128+1, SIGTRAP},             /* ta 1 - normal breakpoint instruction */
460
  {0, 0}                  /* Must be last */
461
};
462
 
463
/* Set up exception handlers for tracing and breakpoints */
464
 
465
void
466
set_debug_traps (void)
467
{
468
  struct hard_trap_info *ht;
469
 
470
  for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
471
    exceptionHandler(ht->tt, trap_low);
472
 
473
  initialized = 1;
474
}
475
 
476
asm ("
477
! Trap handler for memory errors.  This just sets mem_err to be non-zero.  It
478
! assumes that %l1 is non-zero.  This should be safe, as it is doubtful that
479
! 0 would ever contain code that could mem fault.  This routine will skip
480
! past the faulting instruction after setting mem_err.
481
 
482
        .text
483
        .align 4
484
 
485
_fltr_set_mem_err:
486
        sethi %hi(_mem_err), %l0
487
        st %l1, [%l0 + %lo(_mem_err)]
488
        jmpl %l2, %g0
489
        rett %l2+4
490
");
491
 
492
static void
493
set_mem_fault_trap (int enable)
494
{
495
  extern void fltr_set_mem_err();
496
  mem_err = 0;
497
 
498
  if (enable)
499
    exceptionHandler(9, fltr_set_mem_err);
500
  else
501
    exceptionHandler(9, trap_low);
502
}
503
 
504
/* Convert the SPARC hardware trap type code to a unix signal number. */
505
 
506
static int
507
computeSignal (int tt)
508
{
509
  struct hard_trap_info *ht;
510
 
511
  for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
512
    if (ht->tt == tt)
513
      return ht->signo;
514
 
515
  return SIGHUP;                /* default for things we don't know about */
516
}
517
 
518
/*
519
 * While we find nice hex chars, build an int.
520
 * Return number of chars processed.
521
 */
522
 
523
static int
524
hexToInt(char **ptr, int *intValue)
525
{
526
  int numChars = 0;
527
  int hexValue;
528
 
529
  *intValue = 0;
530
 
531
  while (**ptr)
532
    {
533
      hexValue = hex(**ptr);
534
      if (hexValue < 0)
535
        break;
536
 
537
      *intValue = (*intValue << 4) | hexValue;
538
      numChars ++;
539
 
540
      (*ptr)++;
541
    }
542
 
543
  return (numChars);
544
}
545
 
546
/*
547
 * This function does all command procesing for interfacing to gdb.  It
548
 * returns 1 if you should skip the instruction at the trap address, 0
549
 * otherwise.
550
 */
551
 
552
extern void breakinst();
553
 
554
static void
555
handle_exception (unsigned long *registers)
556
{
557
  int tt;                       /* Trap type */
558
  int sigval;
559
  int addr;
560
  int length;
561
  char *ptr;
562
  unsigned long *sp;
563
 
564
/* First, we must force all of the windows to be spilled out */
565
 
566
  asm(" save %sp, -64, %sp
567
        save %sp, -64, %sp
568
        save %sp, -64, %sp
569
        save %sp, -64, %sp
570
        save %sp, -64, %sp
571
        save %sp, -64, %sp
572
        save %sp, -64, %sp
573
        save %sp, -64, %sp
574
        restore
575
        restore
576
        restore
577
        restore
578
        restore
579
        restore
580
        restore
581
        restore
582
");
583
 
584
  if (registers[PC] == (unsigned long)breakinst)
585
    {
586
      registers[PC] = registers[NPC];
587
      registers[NPC] += 4;
588
    }
589
 
590
  sp = (unsigned long *)registers[SP];
591
 
592
  tt = (registers[TBR] >> 4) & 0xff;
593
 
594
  /* reply to host that an exception has occurred */
595
  sigval = computeSignal(tt);
596
  ptr = remcomOutBuffer;
597
 
598
  *ptr++ = 'T';
599
  *ptr++ = hexchars[sigval >> 4];
600
  *ptr++ = hexchars[sigval & 0xf];
601
 
602
  *ptr++ = hexchars[PC >> 4];
603
  *ptr++ = hexchars[PC & 0xf];
604
  *ptr++ = ':';
605
  ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
606
  *ptr++ = ';';
607
 
608
  *ptr++ = hexchars[FP >> 4];
609
  *ptr++ = hexchars[FP & 0xf];
610
  *ptr++ = ':';
611
  ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
612
  *ptr++ = ';';
613
 
614
  *ptr++ = hexchars[SP >> 4];
615
  *ptr++ = hexchars[SP & 0xf];
616
  *ptr++ = ':';
617
  ptr = mem2hex((char *)&sp, ptr, 4, 0);
618
  *ptr++ = ';';
619
 
620
  *ptr++ = hexchars[NPC >> 4];
621
  *ptr++ = hexchars[NPC & 0xf];
622
  *ptr++ = ':';
623
  ptr = mem2hex((char *)&registers[NPC], ptr, 4, 0);
624
  *ptr++ = ';';
625
 
626
  *ptr++ = hexchars[O7 >> 4];
627
  *ptr++ = hexchars[O7 & 0xf];
628
  *ptr++ = ':';
629
  ptr = mem2hex((char *)&registers[O7], ptr, 4, 0);
630
  *ptr++ = ';';
631
 
632
  *ptr++ = 0;
633
 
634
  putpacket(remcomOutBuffer);
635
 
636
  while (1)
637
    {
638
      remcomOutBuffer[0] = 0;
639
 
640
      ptr = getpacket();
641
      switch (*ptr++)
642
        {
643
        case '?':
644
          remcomOutBuffer[0] = 'S';
645
          remcomOutBuffer[1] = hexchars[sigval >> 4];
646
          remcomOutBuffer[2] = hexchars[sigval & 0xf];
647
          remcomOutBuffer[3] = 0;
648
          break;
649
 
650
        case 'd':               /* toggle debug flag */
651
          break;
652
 
653
        case 'g':               /* return the value of the CPU registers */
654
          {
655
            ptr = remcomOutBuffer;
656
            ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
657
            ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */
658
            memset(ptr, '0', 32 * 8); /* Floating point */
659
            mem2hex((char *)&registers[Y],
660
                    ptr + 32 * 4 * 2,
661
                    8 * 4,
662
                    0);          /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
663
          }
664
          break;
665
 
666
        case 'G':          /* set the value of the CPU registers - return OK */
667
          {
668
            unsigned long *newsp, psr;
669
 
670
            psr = registers[PSR];
671
 
672
            hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
673
            hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */
674
            hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y],
675
                    8 * 4, 0);   /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
676
 
677
            /* See if the stack pointer has moved.  If so, then copy the saved
678
               locals and ins to the new location.  This keeps the window
679
               overflow and underflow routines happy.  */
680
 
681
            newsp = (unsigned long *)registers[SP];
682
            if (sp != newsp)
683
              sp = memcpy(newsp, sp, 16 * 4);
684
 
685
            /* Don't allow CWP to be modified. */
686
 
687
            if (psr != registers[PSR])
688
              registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
689
 
690
            strcpy(remcomOutBuffer,"OK");
691
          }
692
          break;
693
 
694
        case 'm':         /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
695
          /* Try to read %x,%x.  */
696
 
697
          if (hexToInt(&ptr, &addr)
698
              && *ptr++ == ','
699
              && hexToInt(&ptr, &length))
700
            {
701
              if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
702
                break;
703
 
704
              strcpy (remcomOutBuffer, "E03");
705
            }
706
          else
707
            strcpy(remcomOutBuffer,"E01");
708
          break;
709
 
710
        case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
711
          /* Try to read '%x,%x:'.  */
712
 
713
          if (hexToInt(&ptr, &addr)
714
              && *ptr++ == ','
715
              && hexToInt(&ptr, &length)
716
              && *ptr++ == ':')
717
            {
718
              if (hex2mem(ptr, (char *)addr, length, 1))
719
                strcpy(remcomOutBuffer, "OK");
720
              else
721
                strcpy(remcomOutBuffer, "E03");
722
            }
723
          else
724
            strcpy(remcomOutBuffer, "E02");
725
          break;
726
 
727
        case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
728
          /* try to read optional parameter, pc unchanged if no parm */
729
 
730
          if (hexToInt(&ptr, &addr))
731
            {
732
              registers[PC] = addr;
733
              registers[NPC] = addr + 4;
734
            }
735
 
736
/* Need to flush the instruction cache here, as we may have deposited a
737
   breakpoint, and the icache probably has no way of knowing that a data ref to
738
   some location may have changed something that is in the instruction cache.
739
 */
740
 
741
          flush_i_cache();
742
          return;
743
 
744
          /* kill the program */
745
        case 'k' :              /* do nothing */
746
          break;
747
#if 0
748
        case 't':               /* Test feature */
749
          asm (" std %f30,[%sp]");
750
          break;
751
#endif
752
        case 'r':               /* Reset */
753
          asm ("call 0
754
                nop ");
755
          break;
756
        }                       /* switch */
757
 
758
      /* reply to the request */
759
      putpacket(remcomOutBuffer);
760
    }
761
}
762
 
763
/* This function will generate a breakpoint exception.  It is used at the
764
   beginning of a program to sync up with a debugger and can be used
765
   otherwise as a quick means to stop program execution and "break" into
766
   the debugger. */
767
 
768
void
769
breakpoint (void)
770
{
771
  if (!initialized)
772
    return;
773
 
774
  asm(" .globl _breakinst
775
 
776
        _breakinst: ta 1
777
      ");
778
}

powered by: WebSVN 2.1.0

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