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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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