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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 104 markom
/****************************************************************************
2
 
3
                THIS SOFTWARE IS NOT COPYRIGHTED
4
 
5
   HP offers the following for use in the public domain.  HP makes no
6
   warranty with regard to the software or it's performance and the
7
   user accepts the software "AS IS" with all faults.
8
 
9
   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
10
   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
11
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12
 
13
****************************************************************************/
14
 
15
/****************************************************************************
16
 *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
17
 *
18
 *  Module name: remcom.c $
19
 *  Revision: 1.34 $
20
 *  Date: 91/03/09 12:29:49 $
21
 *  Contributor:     Lake Stevens Instrument Division$
22
 *
23
 *  Description:     low level support for gdb debugger. $
24
 *
25
 *  Considerations:  only works on target hardware $
26
 *
27
 *  Written by:      Glenn Engel $
28
 *  ModuleState:     Experimental $
29
 *
30
 *  NOTES:           See Below $
31
 *
32
 *  Modified for SPARC by Stu Grossman, Cygnus Support.
33
 *
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(ch)
273
     unsigned char ch;
274
{
275
  if (ch >= 'a' && ch <= 'f')
276
    return ch-'a'+10;
277
  if (ch >= '0' && ch <= '9')
278
    return ch-'0';
279
  if (ch >= 'A' && ch <= 'F')
280
    return ch-'A'+10;
281
  return -1;
282
}
283
 
284
static char remcomInBuffer[BUFMAX];
285
static char remcomOutBuffer[BUFMAX];
286
 
287
/* scan for the sequence $<data>#<checksum>     */
288
 
289
unsigned char *
290
getpacket ()
291
{
292
  unsigned char *buffer = &remcomInBuffer[0];
293
  unsigned char checksum;
294
  unsigned char xmitcsum;
295
  int count;
296
  char ch;
297
 
298
  while (1)
299
    {
300
      /* wait around for the start character, ignore all other characters */
301
      while ((ch = getDebugChar ()) != '$')
302
        ;
303
 
304
retry:
305
      checksum = 0;
306
      xmitcsum = -1;
307
      count = 0;
308
 
309
      /* now, read until a # or end of buffer is found */
310
      while (count < BUFMAX)
311
        {
312
          ch = getDebugChar ();
313
          if (ch == '$')
314
            goto retry;
315
          if (ch == '#')
316
            break;
317
          checksum = checksum + ch;
318
          buffer[count] = ch;
319
          count = count + 1;
320
        }
321
      buffer[count] = 0;
322
 
323
      if (ch == '#')
324
        {
325
          ch = getDebugChar ();
326
          xmitcsum = hex (ch) << 4;
327
          ch = getDebugChar ();
328
          xmitcsum += hex (ch);
329
 
330
          if (checksum != xmitcsum)
331
            {
332
              putDebugChar ('-');       /* failed checksum */
333
            }
334
          else
335
            {
336
              putDebugChar ('+');       /* successful transfer */
337
 
338
              /* if a sequence char is present, reply the sequence ID */
339
              if (buffer[2] == ':')
340
                {
341
                  putDebugChar (buffer[0]);
342
                  putDebugChar (buffer[1]);
343
 
344
                  return &buffer[3];
345
                }
346
 
347
              return &buffer[0];
348
            }
349
        }
350
    }
351
}
352
 
353
/* send the packet in buffer.  */
354
 
355
static void
356
putpacket(buffer)
357
     unsigned char *buffer;
358
{
359
  unsigned char checksum;
360
  int count;
361
  unsigned char ch;
362
 
363
  /*  $<packet info>#<checksum>. */
364
  do
365
    {
366
      putDebugChar('$');
367
      checksum = 0;
368
      count = 0;
369
 
370
      while (ch = buffer[count])
371
        {
372
          putDebugChar(ch);
373
          checksum += ch;
374
          count += 1;
375
        }
376
 
377
      putDebugChar('#');
378
      putDebugChar(hexchars[checksum >> 4]);
379
      putDebugChar(hexchars[checksum & 0xf]);
380
 
381
    }
382
  while (getDebugChar() != '+');
383
}
384
 
385
/* Indicate to caller of mem2hex or hex2mem that there has been an
386
   error.  */
387
static volatile int mem_err = 0;
388
 
389
/* Convert the memory pointed to by mem into hex, placing result in buf.
390
 * Return a pointer to the last char put in buf (null), in case of mem fault,
391
 * return 0.
392
 * If MAY_FAULT is non-zero, then we will handle memory faults by returning
393
 * a 0, else treat a fault like any other fault in the stub.
394
 */
395
 
396
static unsigned char *
397
mem2hex(mem, buf, count, may_fault)
398
     unsigned char *mem;
399
     unsigned char *buf;
400
     int count;
401
     int may_fault;
402
{
403
  unsigned char ch;
404
 
405
  set_mem_fault_trap(may_fault);
406
 
407
  while (count-- > 0)
408
    {
409
      ch = *mem++;
410
      if (mem_err)
411
        return 0;
412
      *buf++ = hexchars[ch >> 4];
413
      *buf++ = hexchars[ch & 0xf];
414
    }
415
 
416
  *buf = 0;
417
 
418
  set_mem_fault_trap(0);
419
 
420
  return buf;
421
}
422
 
423
/* convert the hex array pointed to by buf into binary to be placed in mem
424
 * return a pointer to the character AFTER the last byte written */
425
 
426
static char *
427
hex2mem(buf, mem, count, may_fault)
428
     unsigned char *buf;
429
     unsigned char *mem;
430
     int count;
431
     int may_fault;
432
{
433
  int i;
434
  unsigned char ch;
435
 
436
  set_mem_fault_trap(may_fault);
437
 
438
  for (i=0; i<count; i++)
439
    {
440
      ch = hex(*buf++) << 4;
441
      ch |= hex(*buf++);
442
      *mem++ = ch;
443
      if (mem_err)
444
        return 0;
445
    }
446
 
447
  set_mem_fault_trap(0);
448
 
449
  return mem;
450
}
451
 
452
/* This table contains the mapping between SPARC hardware trap types, and
453
   signals, which are primarily what GDB understands.  It also indicates
454
   which hardware traps we need to commandeer when initializing the stub. */
455
 
456
static struct hard_trap_info
457
{
458
  unsigned char tt;             /* Trap type code for SPARClite */
459
  unsigned char signo;          /* Signal that we map this trap into */
460
} hard_trap_info[] = {
461
  {1, SIGSEGV},                 /* instruction access error */
462
  {2, SIGILL},                  /* privileged instruction */
463
  {3, SIGILL},                  /* illegal instruction */
464
  {4, SIGEMT},                  /* fp disabled */
465
  {36, SIGEMT},                 /* cp disabled */
466
  {7, SIGBUS},                  /* mem address not aligned */
467
  {9, SIGSEGV},                 /* data access exception */
468
  {10, SIGEMT},                 /* tag overflow */
469
  {128+1, SIGTRAP},             /* ta 1 - normal breakpoint instruction */
470
  {0, 0}                  /* Must be last */
471
};
472
 
473
/* Set up exception handlers for tracing and breakpoints */
474
 
475
void
476
set_debug_traps()
477
{
478
  struct hard_trap_info *ht;
479
 
480
  for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
481
    exceptionHandler(ht->tt, trap_low);
482
 
483
  initialized = 1;
484
}
485
 
486
asm ("
487
! Trap handler for memory errors.  This just sets mem_err to be non-zero.  It
488
! assumes that %l1 is non-zero.  This should be safe, as it is doubtful that
489
! 0 would ever contain code that could mem fault.  This routine will skip
490
! past the faulting instruction after setting mem_err.
491
 
492
        .text
493
        .align 4
494
 
495
_fltr_set_mem_err:
496
        sethi %hi(_mem_err), %l0
497
        st %l1, [%l0 + %lo(_mem_err)]
498
        jmpl %l2, %g0
499
        rett %l2+4
500
");
501
 
502
static void
503
set_mem_fault_trap(enable)
504
     int enable;
505
{
506
  extern void fltr_set_mem_err();
507
  mem_err = 0;
508
 
509
  if (enable)
510
    exceptionHandler(9, fltr_set_mem_err);
511
  else
512
    exceptionHandler(9, trap_low);
513
}
514
 
515
/* Convert the SPARC hardware trap type code to a unix signal number. */
516
 
517
static int
518
computeSignal(tt)
519
     int tt;
520
{
521
  struct hard_trap_info *ht;
522
 
523
  for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
524
    if (ht->tt == tt)
525
      return ht->signo;
526
 
527
  return SIGHUP;                /* default for things we don't know about */
528
}
529
 
530
/*
531
 * While we find nice hex chars, build an int.
532
 * Return number of chars processed.
533
 */
534
 
535
static int
536
hexToInt(char **ptr, int *intValue)
537
{
538
  int numChars = 0;
539
  int hexValue;
540
 
541
  *intValue = 0;
542
 
543
  while (**ptr)
544
    {
545
      hexValue = hex(**ptr);
546
      if (hexValue < 0)
547
        break;
548
 
549
      *intValue = (*intValue << 4) | hexValue;
550
      numChars ++;
551
 
552
      (*ptr)++;
553
    }
554
 
555
  return (numChars);
556
}
557
 
558
/*
559
 * This function does all command procesing for interfacing to gdb.  It
560
 * returns 1 if you should skip the instruction at the trap address, 0
561
 * otherwise.
562
 */
563
 
564
extern void breakinst();
565
 
566
static void
567
handle_exception (registers)
568
     unsigned long *registers;
569
{
570
  int tt;                       /* Trap type */
571
  int sigval;
572
  int addr;
573
  int length;
574
  char *ptr;
575
  unsigned long *sp;
576
 
577
/* First, we must force all of the windows to be spilled out */
578
 
579
  asm(" save %sp, -64, %sp
580
        save %sp, -64, %sp
581
        save %sp, -64, %sp
582
        save %sp, -64, %sp
583
        save %sp, -64, %sp
584
        save %sp, -64, %sp
585
        save %sp, -64, %sp
586
        save %sp, -64, %sp
587
        restore
588
        restore
589
        restore
590
        restore
591
        restore
592
        restore
593
        restore
594
        restore
595
");
596
 
597
  if (registers[PC] == (unsigned long)breakinst)
598
    {
599
      registers[PC] = registers[NPC];
600
      registers[NPC] += 4;
601
    }
602
 
603
  sp = (unsigned long *)registers[SP];
604
 
605
  tt = (registers[TBR] >> 4) & 0xff;
606
 
607
  /* reply to host that an exception has occurred */
608
  sigval = computeSignal(tt);
609
  ptr = remcomOutBuffer;
610
 
611
  *ptr++ = 'T';
612
  *ptr++ = hexchars[sigval >> 4];
613
  *ptr++ = hexchars[sigval & 0xf];
614
 
615
  *ptr++ = hexchars[PC >> 4];
616
  *ptr++ = hexchars[PC & 0xf];
617
  *ptr++ = ':';
618
  ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
619
  *ptr++ = ';';
620
 
621
  *ptr++ = hexchars[FP >> 4];
622
  *ptr++ = hexchars[FP & 0xf];
623
  *ptr++ = ':';
624
  ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
625
  *ptr++ = ';';
626
 
627
  *ptr++ = hexchars[SP >> 4];
628
  *ptr++ = hexchars[SP & 0xf];
629
  *ptr++ = ':';
630
  ptr = mem2hex((char *)&sp, ptr, 4, 0);
631
  *ptr++ = ';';
632
 
633
  *ptr++ = hexchars[NPC >> 4];
634
  *ptr++ = hexchars[NPC & 0xf];
635
  *ptr++ = ':';
636
  ptr = mem2hex((char *)&registers[NPC], ptr, 4, 0);
637
  *ptr++ = ';';
638
 
639
  *ptr++ = hexchars[O7 >> 4];
640
  *ptr++ = hexchars[O7 & 0xf];
641
  *ptr++ = ':';
642
  ptr = mem2hex((char *)&registers[O7], ptr, 4, 0);
643
  *ptr++ = ';';
644
 
645
  *ptr++ = 0;
646
 
647
  putpacket(remcomOutBuffer);
648
 
649
  while (1)
650
    {
651
      remcomOutBuffer[0] = 0;
652
 
653
      ptr = getpacket();
654
      switch (*ptr++)
655
        {
656
        case '?':
657
          remcomOutBuffer[0] = 'S';
658
          remcomOutBuffer[1] = hexchars[sigval >> 4];
659
          remcomOutBuffer[2] = hexchars[sigval & 0xf];
660
          remcomOutBuffer[3] = 0;
661
          break;
662
 
663
        case 'd':               /* toggle debug flag */
664
          break;
665
 
666
        case 'g':               /* return the value of the CPU registers */
667
          {
668
            ptr = remcomOutBuffer;
669
            ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
670
            ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */
671
            memset(ptr, '0', 32 * 8); /* Floating point */
672
            mem2hex((char *)&registers[Y],
673
                    ptr + 32 * 4 * 2,
674
                    8 * 4,
675
                    0);          /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
676
          }
677
          break;
678
 
679
        case 'G':          /* set the value of the CPU registers - return OK */
680
          {
681
            unsigned long *newsp, psr;
682
 
683
            psr = registers[PSR];
684
 
685
            hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
686
            hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */
687
            hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y],
688
                    8 * 4, 0);   /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
689
 
690
            /* See if the stack pointer has moved.  If so, then copy the saved
691
               locals and ins to the new location.  This keeps the window
692
               overflow and underflow routines happy.  */
693
 
694
            newsp = (unsigned long *)registers[SP];
695
            if (sp != newsp)
696
              sp = memcpy(newsp, sp, 16 * 4);
697
 
698
            /* Don't allow CWP to be modified. */
699
 
700
            if (psr != registers[PSR])
701
              registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
702
 
703
            strcpy(remcomOutBuffer,"OK");
704
          }
705
          break;
706
 
707
        case 'm':         /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
708
          /* Try to read %x,%x.  */
709
 
710
          if (hexToInt(&ptr, &addr)
711
              && *ptr++ == ','
712
              && hexToInt(&ptr, &length))
713
            {
714
              if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
715
                break;
716
 
717
              strcpy (remcomOutBuffer, "E03");
718
            }
719
          else
720
            strcpy(remcomOutBuffer,"E01");
721
          break;
722
 
723
        case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
724
          /* Try to read '%x,%x:'.  */
725
 
726
          if (hexToInt(&ptr, &addr)
727
              && *ptr++ == ','
728
              && hexToInt(&ptr, &length)
729
              && *ptr++ == ':')
730
            {
731
              if (hex2mem(ptr, (char *)addr, length, 1))
732
                strcpy(remcomOutBuffer, "OK");
733
              else
734
                strcpy(remcomOutBuffer, "E03");
735
            }
736
          else
737
            strcpy(remcomOutBuffer, "E02");
738
          break;
739
 
740
        case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
741
          /* try to read optional parameter, pc unchanged if no parm */
742
 
743
          if (hexToInt(&ptr, &addr))
744
            {
745
              registers[PC] = addr;
746
              registers[NPC] = addr + 4;
747
            }
748
 
749
/* Need to flush the instruction cache here, as we may have deposited a
750
   breakpoint, and the icache probably has no way of knowing that a data ref to
751
   some location may have changed something that is in the instruction cache.
752
 */
753
 
754
          flush_i_cache();
755
          return;
756
 
757
          /* kill the program */
758
        case 'k' :              /* do nothing */
759
          break;
760
#if 0
761
        case 't':               /* Test feature */
762
          asm (" std %f30,[%sp]");
763
          break;
764
#endif
765
        case 'r':               /* Reset */
766
          asm ("call 0
767
                nop ");
768
          break;
769
        }                       /* switch */
770
 
771
      /* reply to the request */
772
      putpacket(remcomOutBuffer);
773
    }
774
}
775
 
776
/* This function will generate a breakpoint exception.  It is used at the
777
   beginning of a program to sync up with a debugger and can be used
778
   otherwise as a quick means to stop program execution and "break" into
779
   the debugger. */
780
 
781
void
782
breakpoint()
783
{
784
  if (!initialized)
785
    return;
786
 
787
  asm(" .globl _breakinst
788
 
789
        _breakinst: ta 1
790
      ");
791
}

powered by: WebSVN 2.1.0

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