source: rtems/c/src/lib/libbsp/mips/shared/gdbstub/mips-stub.c @ 6953e68e

4.104.114.84.95
Last change on this file since 6953e68e was 6953e68e, checked in by Joel Sherrill <joel.sherrill@…>, on Feb 8, 2002 at 11:27:26 PM

2002-02-08 Joel Sherrill <joel@…>

  • mips-stub.c (handle_exception): Prototype changed to be an RTEMS entry point. Added comments about possible need to flush cache. (mips_gdb_stub_install): New routine.
  • Property mode set to 100644
File size: 25.9 KB
Line 
1/*******************************************************************************
2
3                     THIS SOFTWARE IS NOT COPYRIGHTED
4
5    The following software is offered for use in the public domain.
6    There is no warranty with regard to this software or its performance
7    and the user must accept the software "AS IS" with all faults.
8
9    THE CONTRIBUTORS DISCLAIM ANY WARRANTIES, EXPRESS OR IMPLIED, WITH
10    REGARD TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
11    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12
13    $Id$
14
15********************************************************************************
16*
17*   r46kstub.c -- target debugging stub for the IDT R4600 Orion processor
18*
19*   This module is based on the stub for the Hitachi SH processor written by
20*   Ben Lee and Steve Chamberlain and supplied with gdb 4.16.  The latter
21*   in turn "is originally based on an m68k software stub written by Glenn
22*   Engel at HP, but has changed quite a bit."  The changes for the R4600
23*   were written by C. M. Heard at VVNET.  They were based in part on the
24*   Algorithmics R4000 version of Phil Bunce's PMON program.
25*
26*  Remote communication protocol:
27*
28*  A debug packet whose contents are <data>
29*  is encapsulated for transmission in the form:
30*
31*       $ <data> # CSUM1 CSUM2
32*
33*       <data> must be ASCII alphanumeric and cannot include characters
34*       '$' or '#'.  If <data> starts with two characters followed by
35*       ':', then the existing stubs interpret this as a sequence number.
36*
37*       CSUM1 and CSUM2 are ascii hex representation of an 8-bit
38*       checksum of <data>, the most significant nibble is sent first.
39*       the hex digits 0-9,a-f are used.
40*
41*  Receiver responds with:
42*
43*       +    if CSUM is correct
44*       -    if CSUM is incorrect
45*
46*  <data> is as follows.  All values are encoded in ascii hex digits.
47*
48*       Request         Packet
49*
50*       read registers  g
51*       reply           XX....X         Each byte of register data
52*                                       is described by two hex digits.
53*                                       Registers are in the internal order
54*                                       for GDB, and the bytes in a register
55*                                       are in the same order the machine uses.
56*                       or ENN          for an error.
57*
58*       write regs      GXX..XX         Each byte of register data
59*                                       is described by two hex digits.
60*       reply           OK              for success
61*                       ENN             for an error
62*
63*       write reg       Pn...=r...      Write register n... with value r....
64*       reply           OK              for success
65*                       ENN             for an error
66*
67*       read mem        mAA..AA,LLLL    AA..AA is address, LLLL is length.
68*       reply           XX..XX          XX..XX is mem contents
69*                                       Can be fewer bytes than requested
70*                                       if able to read only part of the data.
71*                       or ENN          NN is errno
72*
73*       write mem       MAA..AA,LLLL:XX..XX
74*                                       AA..AA is address,
75*                                       LLLL is number of bytes,
76*                                       XX..XX is data
77*       reply           OK              for success
78*                       ENN             for an error (this includes the case
79*                                       where only part of the data was
80*                                       written).
81*
82*       cont            cAA..AA         AA..AA is address to resume
83*                                       If AA..AA is omitted,
84*                                       resume at same address.
85*
86*       step            sAA..AA         AA..AA is address to resume
87*                                       If AA..AA is omitted,
88*                                       resume at same address.
89*
90*       There is no immediate reply to step or cont.
91*       The reply comes when the machine stops.
92*       It is           SAA             AA is the "signal number"
93*
94*       last signal     ?               Reply with the reason for stopping.
95*                                       This is the same reply as is generated
96*                                       for step or cont: SAA where AA is the
97*                                       signal number.
98*
99*       detach          D               Host is detaching.  Reply OK and
100*                                       end remote debugging session.
101*
102*       reserved        <other>         On other requests, the stub should
103*                                       ignore the request and send an empty
104*                                       response ($#<checksum>).  This way
105*                                       we can extend the protocol and GDB
106*                                       can tell whether the stub it is
107*                                       talking to uses the old or the new.
108*
109*       Responses can be run-length encoded to save space.  A '*' means that
110*       the next character is an ASCII encoding giving a repeat count which
111*       stands for that many repetitions of the character preceding the '*'.
112*       The encoding is n+29, yielding a printable character when n >=3
113*       (which is where rle starts to win).  Don't use n > 99 since gdb
114*       masks each character is receives with 0x7f in order to strip off
115*       the parity bit.
116*
117*       As an example, "0* " means the same thing as "0000".
118*
119*******************************************************************************/
120
121
122#include <string.h>
123#include <signal.h>
124#include "mips_opcode.h"
125#include "memlimits.h"
126#include <rtems.h>
127#include "gdb_if.h"
128
129/***************/
130/* Exception Codes */
131#define EXC_INT         0               /* External interrupt */
132#define EXC_MOD         1               /* TLB modification exception */
133#define EXC_TLBL        2               /* TLB miss (Load or Ifetch) */
134#define EXC_TLBS        3               /* TLB miss (Store) */
135#define EXC_ADEL        4               /* Address error (Load or Ifetch) */
136#define EXC_ADES        5               /* Address error (Store) */
137#define EXC_IBE         6               /* Bus error (Ifetch) */
138#define EXC_DBE         7               /* Bus error (data load or store) */
139#define EXC_SYS         8               /* System call */
140#define EXC_BP          9               /* Break point */
141#define EXC_RI          10              /* Reserved instruction */
142#define EXC_CPU         11              /* Coprocessor unusable */
143#define EXC_OVF         12              /* Arithmetic overflow */
144#define EXC_TRAP        13              /* Trap exception */
145#define EXC_FPE         15              /* Floating Point Exception */
146
147/* FPU Control/Status register fields */
148#define CSR_FS          0x01000000      /* Set to flush denormals to zero */
149#define CSR_C           0x00800000      /* Condition bit (set by FP compare) */
150
151#define CSR_CMASK       (0x3f<<12)
152#define CSR_CE          0x00020000
153#define CSR_CV          0x00010000
154#define CSR_CZ          0x00008000
155#define CSR_CO          0x00004000
156#define CSR_CU          0x00002000
157#define CSR_CI          0x00001000
158
159#define CSR_EMASK       (0x1f<<7)
160#define CSR_EV          0x00000800
161#define CSR_EZ          0x00000400
162#define CSR_EO          0x00000200
163#define CSR_EU          0x00000100
164#define CSR_EI          0x00000080
165
166#define CSR_FMASK       (0x1f<<2)
167#define CSR_FV          0x00000040
168#define CSR_FZ          0x00000020
169#define CSR_FO          0x00000010
170#define CSR_FU          0x00000008
171#define CSR_FI          0x00000004
172
173#define CSR_RMODE_MASK  (0x3<<0)
174#define CSR_RM          0x00000003
175#define CSR_RP          0x00000002
176#define CSR_RZ          0x00000001
177#define CSR_RN          0x00000000
178
179/***************/
180
181/*
182 * Saved register information.  Must be prepared by the exception
183 * preprocessor before handle_exception is invoked.
184 */
185#if (__mips == 3)
186typedef long long mips_register_t;
187#elif (__mips == 1)
188typedef unsigned int mips_register_t;
189#else
190#error "unknown MIPS ISA"
191#endif
192static mips_register_t *registers;
193
194
195/*
196 * The following external functions provide character input and output.
197 */
198extern char getDebugChar (void);
199
200extern void putDebugChar (char);
201
202
203/*
204 * BUFMAX defines the maximum number of characters in the inbound & outbound
205 * packet buffers.  At least 4+(sizeof registers)*2 bytes will be needed for
206 * register packets.  Memory dump packets can profitably use even more.
207 */
208#define BUFMAX 1500
209
210static char inBuffer[BUFMAX];
211static char outBuffer[BUFMAX];
212
213
214/*
215 * Convert an int to hex.
216 */
217static const char hexchars[] = "0123456789abcdef";
218
219#define highhex(x) hexchars [(x >> 4) & 0xf]
220#define lowhex(x) hexchars [x & 0xf]
221
222
223/*
224 * Convert length bytes of data starting at addr into hex, placing the
225 * result in buf.  Return a pointer to the last (null) char in buf.
226 */
227static char *
228mem2hex (int addr, int length, char *buf)
229{
230  if (((addr & 0x7) == 0) && ((length & 0x7) == 0))      /* dword aligned */
231    {
232      long long *source = (long long *) (addr);
233      long long *limit  = (long long *) (addr + length);
234
235      while (source < limit)
236        {
237          int i;
238          long long k = *source++;
239
240          for (i = 15; i >= 0; i--)
241            *buf++ = hexchars [(k >> (i*4)) & 0xf];
242        }
243    }
244  else if (((addr & 0x3) == 0) && ((length & 0x3) == 0)) /* word aligned */
245    {
246      int *source = (int *) (addr);
247      int *limit  = (int *) (addr + length);
248
249      while (source < limit)
250        {
251          int i;
252          int k = *source++;
253
254          for (i = 7; i >= 0; i--)
255            *buf++ = hexchars [(k >> (i*4)) & 0xf];
256        }
257    }
258  else if (((addr & 0x1) == 0) && ((length & 0x1) == 0)) /* halfword aligned */
259    {
260      short *source = (short *) (addr);
261      short *limit  = (short *) (addr + length);
262
263      while (source < limit)
264        {
265          int i;
266          short k = *source++;
267
268          for (i = 3; i >= 0; i--)
269            *buf++ = hexchars [(k >> (i*4)) & 0xf];
270        }
271    }
272  else                                                   /* byte aligned */
273    {
274      char *source = (char *) (addr);
275      char *limit  = (char *) (addr + length);
276
277      while (source < limit)
278        {
279          int i;
280          char k = *source++;
281
282          for (i = 1; i >= 0; i--)
283            *buf++ = hexchars [(k >> (i*4)) & 0xf];
284        }
285    }
286
287  *buf = '\0';
288  return (buf);
289}
290
291
292/*
293 * Convert a hex character to an int.
294 */
295static int
296hex (char ch)
297{
298  if ((ch >= 'a') && (ch <= 'f'))
299    return (ch - 'a' + 10);
300  if ((ch >= '0') && (ch <= '9'))
301    return (ch - '0');
302  if ((ch >= 'A') && (ch <= 'F'))
303    return (ch - 'A' + 10);
304  return (-1);
305}
306
307
308/*
309 * Convert a string from hex to int until a non-hex digit
310 * is found.  Return the number of characters processed.
311 */
312static int
313hexToInt (char **ptr, int *intValue)
314{
315  int numChars = 0;
316  int hexValue;
317
318  *intValue = 0;
319
320  while (**ptr)
321    {
322      hexValue = hex (**ptr);
323      if (hexValue >= 0)
324        {
325          *intValue = (*intValue << 4) | hexValue;
326          numChars++;
327        }
328      else
329        break;
330
331      (*ptr)++;
332    }
333
334  return (numChars);
335}
336
337
338/*
339 * Convert a string from hex to long long until a non-hex
340 * digit is found.  Return the number of characters processed.
341 */
342static int
343hexToLongLong (char **ptr, long long *intValue)
344{
345  int numChars = 0;
346  int hexValue;
347
348  *intValue = 0;
349
350  while (**ptr)
351    {
352      hexValue = hex (**ptr);
353      if (hexValue >= 0)
354        {
355          *intValue = (*intValue << 4) | hexValue;
356          numChars++;
357        }
358      else
359        break;
360
361      (*ptr)++;
362    }
363
364  return (numChars);
365}
366
367
368/*
369 * Convert the hex array buf into binary, placing the result at the
370 * specified address.  If the conversion fails at any point (i.e.,
371 * if fewer bytes are written than indicated by the size parameter)
372 * then return 0;  otherwise return 1.
373 */
374static int
375hex2mem (char *buf, int addr, int length)
376{
377  if (((addr & 0x7) == 0) && ((length & 0x7) == 0))      /* dword aligned */
378    {
379      long long *target = (long long *) (addr);
380      long long *limit  = (long long *) (addr + length);
381
382      while (target < limit)
383        {
384          int i, j;
385          long long k = 0;
386
387          for (i = 0; i < 16; i++)
388            if ((j = hex(*buf++)) < 0)
389              return 0;
390            else
391              k = (k << 4) + j;
392          *target++ = k;
393        }
394    }
395  else if (((addr & 0x3) == 0) && ((length & 0x3) == 0)) /* word aligned */
396    {
397      int *target = (int *) (addr);
398      int *limit  = (int *) (addr + length);
399
400      while (target < limit)
401        {
402          int i, j;
403          int k = 0;
404
405          for (i = 0; i < 8; i++)
406            if ((j = hex(*buf++)) < 0)
407              return 0;
408            else
409              k = (k << 4) + j;
410          *target++ = k;
411        }
412    }
413  else if (((addr & 0x1) == 0) && ((length & 0x1) == 0)) /* halfword aligned */
414    {
415      short *target = (short *) (addr);
416      short *limit  = (short *) (addr + length);
417
418      while (target < limit)
419        {
420          int i, j;
421          short k = 0;
422
423          for (i = 0; i < 4; i++)
424            if ((j = hex(*buf++)) < 0)
425              return 0;
426            else
427              k = (k << 4) + j;
428          *target++ = k;
429        }
430    }
431  else                                                   /* byte aligned */
432    {
433      char *target = (char *) (addr);
434      char *limit  = (char *) (addr + length);
435
436      while (target < limit)
437        {
438          int i, j;
439          char k = 0;
440
441          for (i = 0; i < 2; i++)
442            if ((j = hex(*buf++)) < 0)
443              return 0;
444            else
445              k = (k << 4) + j;
446          *target++ = k;
447        }
448    }
449
450  return 1;
451}
452
453
454/*
455 * Scan the input stream for a sequence for the form $<data>#<checksum>.
456 */
457static void
458getpacket (char *buffer)
459{
460  unsigned char checksum;
461  unsigned char xmitcsum;
462  int i;
463  int count;
464  char ch;
465  do
466    {
467      /* wait around for the start character, ignore all other characters */
468      while ((ch = getDebugChar ()) != '$');
469      checksum = 0;
470      xmitcsum = -1;
471
472      count = 0;
473
474      /* now, read until a # or end of buffer is found */
475      while ( (count < BUFMAX-1) && ((ch = getDebugChar ()) != '#') )
476          checksum += (buffer[count++] = ch);
477
478      /* make sure that the buffer is null-terminated */
479      buffer[count] = '\0';
480
481      if (ch == '#')
482        {
483          xmitcsum = hex (getDebugChar ()) << 4;
484          xmitcsum += hex (getDebugChar ());
485          if (checksum != xmitcsum)
486            putDebugChar ('-'); /* failed checksum */
487          else
488            {
489              putDebugChar ('+');       /* successful transfer */
490              /* if a sequence char is present, reply the sequence ID */
491              if (buffer[2] == ':')
492                {
493                  putDebugChar (buffer[0]);
494                  putDebugChar (buffer[1]);
495                  /* remove sequence chars from buffer */
496                  for (i = 3; i <= count; i++)
497                    buffer[i - 3] = buffer[i];
498                }
499            }
500        }
501    }
502  while (checksum != xmitcsum);
503}
504
505
506/*
507 * Send the packet in buffer and wait for a positive acknowledgement.
508 */
509static void
510putpacket (char *buffer)
511{
512  int checksum;
513
514  /* $<packet info>#<checksum> */
515  do
516    {
517      char *src = buffer;
518      putDebugChar ('$');
519      checksum = 0;
520
521      while (*src != '\0')
522        {
523          int runlen = 0;
524
525          /* Do run length encoding */
526          while ((src[runlen] == src[0]) && (runlen < 99))
527            runlen++;
528          if (runlen > 3)
529            {
530              int encode;
531              /* Got a useful amount */
532              putDebugChar (*src);
533              checksum += *src;
534              putDebugChar ('*');
535              checksum += '*';
536              checksum += (encode = (runlen - 4) + ' ');
537              putDebugChar (encode);
538              src += runlen;
539            }
540          else
541            {
542              putDebugChar (*src);
543              checksum += *src;
544              src++;
545             }
546        }
547
548      putDebugChar ('#');
549      putDebugChar (highhex (checksum));
550      putDebugChar (lowhex (checksum));
551    }
552  while  (getDebugChar () != '+');
553}
554
555
556/*
557 * Saved instruction data for single step support
558 */
559static struct
560  {
561    unsigned *targetAddr;
562    unsigned savedInstr;
563  }
564instrBuffer;
565
566
567/*
568 * If a step breakpoint was planted restore the saved instruction.
569 */
570static void
571undoSStep (void)
572{
573  if (instrBuffer.targetAddr != NULL)
574    {
575      *instrBuffer.targetAddr = instrBuffer.savedInstr;
576      instrBuffer.targetAddr = NULL;
577    }
578  instrBuffer.savedInstr = NOP_INSTR;
579}
580
581
582/*
583 * If a single step is requested put a temporary breakpoint at the instruction
584 * which logically follows the next one to be executed.  If the next instruction
585 * is a branch instruction then skip the instruction in the delay slot.  NOTE:
586 * ERET instructions are NOT handled, as it is impossible to single-step through
587 * the exit code in an exception handler.  In addition, no attempt is made to
588 * do anything about BC0T and BC0F, since a condition bit for coprocessor 0
589 * is not defined on the R4600.  Finally, BC2T and BC2F are ignored since there
590 * is no coprocessor 2 on a 4600.
591 */
592static void
593doSStep (void)
594{
595  InstFmt inst;
596
597  instrBuffer.targetAddr = (unsigned *)(registers[PC]+4);    /* set default */
598
599  inst.word = *(unsigned *)registers[PC];     /* read the next instruction  */
600
601  switch (inst.RType.op) {                    /* override default if branch */
602    case OP_SPECIAL:
603      switch (inst.RType.func) {
604        case OP_JR:
605        case OP_JALR:
606          instrBuffer.targetAddr =
607            (unsigned *)registers[inst.RType.rs];
608          break;
609      };
610      break;
611
612    case OP_REGIMM:
613      switch (inst.IType.rt) {
614        case OP_BLTZ:
615        case OP_BLTZL:
616        case OP_BLTZAL:
617        case OP_BLTZALL:
618          if (registers[inst.IType.rs] < 0 )
619            instrBuffer.targetAddr =
620              (unsigned *)(((signed short)inst.IType.imm<<2)
621                                        + (registers[PC]+4));
622          else
623            instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
624          break;
625        case OP_BGEZ:
626        case OP_BGEZL:
627        case OP_BGEZAL:
628        case OP_BGEZALL:
629          if (registers[inst.IType.rs] >= 0 )
630            instrBuffer.targetAddr =
631              (unsigned *)(((signed short)inst.IType.imm<<2)
632                                        + (registers[PC]+4));
633          else
634            instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
635          break;
636      };
637      break;
638
639    case OP_J:
640    case OP_JAL:
641      instrBuffer.targetAddr =
642        (unsigned *)((inst.JType.target<<2) + ((registers[PC]+4)&0xf0000000));
643      break;
644
645    case OP_BEQ:
646    case OP_BEQL:
647      if (registers[inst.IType.rs] == registers[inst.IType.rt])
648        instrBuffer.targetAddr =
649          (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4));
650      else
651        instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
652      break;
653    case OP_BNE:
654    case OP_BNEL:
655      if (registers[inst.IType.rs] != registers[inst.IType.rt])
656        instrBuffer.targetAddr =
657          (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4));
658      else
659        instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
660      break;
661    case OP_BLEZ:
662    case OP_BLEZL:
663      if (registers[inst.IType.rs] <= 0)
664        instrBuffer.targetAddr =
665          (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4));
666      else
667        instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
668      break;
669    case OP_BGTZ:
670    case OP_BGTZL:
671      if (registers[inst.IType.rs] > 0)
672        instrBuffer.targetAddr =
673          (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4));
674      else
675        instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
676      break;
677
678    case OP_COP1:
679      if (inst.RType.rs == OP_BC)
680          switch (inst.RType.rt) {
681            case COPz_BCF:
682            case COPz_BCFL:
683              if (registers[FCSR] & CSR_C)
684                instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
685              else
686                instrBuffer.targetAddr =
687                  (unsigned *)(((signed short)inst.IType.imm<<2)
688                                            + (registers[PC]+4));
689              break;
690            case COPz_BCT:
691            case COPz_BCTL:
692              if (registers[FCSR] & CSR_C)
693                instrBuffer.targetAddr =
694                  (unsigned *)(((signed short)inst.IType.imm<<2)
695                                            + (registers[PC]+4));
696              else
697                instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
698              break;
699          };
700      break;
701  }
702
703  if is_steppable (instrBuffer.targetAddr)
704    {
705      instrBuffer.savedInstr = *instrBuffer.targetAddr;
706      *instrBuffer.targetAddr = BREAK_INSTR;
707    }
708  else
709    {
710      instrBuffer.targetAddr = NULL;
711      instrBuffer.savedInstr = NOP_INSTR;
712    }
713  return;
714}
715
716
717/*
718 * Translate the R4600 exception code into a Unix-compatible signal.
719 */
720static int
721computeSignal (void)
722{
723  int exceptionCode = (registers[CAUSE] & CAUSE_EXCMASK) >> CAUSE_EXCSHIFT;
724
725  switch (exceptionCode)
726    {
727    case EXC_INT:
728      /* External interrupt */
729      return SIGINT;
730
731    case EXC_RI:
732      /* Reserved instruction */
733    case EXC_CPU:
734      /* Coprocessor unusable */
735      return SIGILL;
736
737    case EXC_BP:
738      /* Break point */
739      return SIGTRAP;
740
741    case EXC_OVF:
742      /* Arithmetic overflow */
743    case EXC_TRAP:
744      /* Trap exception */
745    case EXC_FPE:
746      /* Floating Point Exception */
747      return SIGFPE;
748
749    case EXC_IBE:
750      /* Bus error (Ifetch) */
751    case EXC_DBE:
752      /* Bus error (data load or store) */
753      return SIGBUS;
754
755    case EXC_MOD:
756      /* TLB modification exception */
757    case EXC_TLBL:
758      /* TLB miss (Load or Ifetch) */
759    case EXC_TLBS:
760      /* TLB miss (Store) */
761    case EXC_ADEL:
762      /* Address error (Load or Ifetch) */
763    case EXC_ADES:
764      /* Address error (Store) */
765      return SIGSEGV;
766
767    case EXC_SYS:
768      /* System call */
769      return SIGSYS;
770
771    default:
772      return SIGTERM;
773    }
774}
775
776
777/*
778 * This function handles all exceptions.  It only does two things:
779 * it figures out why it was activated and tells gdb, and then it
780 * reacts to gdb's requests.
781 */
782void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
783{
784  int host_has_detached = 0;
785  int sigval;
786  int regno, addr, length;
787  long long regval;
788  char *ptr;
789
790  registers = (mips_register_t *)frame;
791
792  /* reply to host that an exception has occurred */
793  sigval = computeSignal ();
794  outBuffer[0] = 'S';
795  outBuffer[1] = highhex (sigval);
796  outBuffer[2] = lowhex (sigval);
797  outBuffer[3] = '\0';
798
799  putpacket (outBuffer);
800
801  /*
802   * Restore the saved instruction at
803   * the single-step target address.
804   */
805  undoSStep ();
806
807  while (!(host_has_detached))
808    {
809      outBuffer[0] = '\0';
810      getpacket (inBuffer);
811
812      switch (inBuffer[0])
813        {
814        case '?':
815          outBuffer[0] = 'S';
816          outBuffer[1] = highhex (sigval);
817          outBuffer[2] = lowhex (sigval);
818          outBuffer[3] = '\0';
819          break;
820
821        case 'd':
822          /* toggle debug flag */
823          break;
824
825        case 'g':
826          /* return the values of the CPU registers */
827          mem2hex ((int) registers, sizeof registers, outBuffer);
828          break;
829
830        case 'G':
831          /* set the values of the CPU registers - return OK */
832          if (hex2mem (&inBuffer[1], (int) registers, sizeof registers))
833              strcpy (outBuffer, "OK");
834          else
835              strcpy (outBuffer, "E00"); /* E00 = bad "set register" command */
836          break;
837
838        case 'P':
839          /* Pn...=r...  Write register n... with value r... - return OK */
840          ptr = &inBuffer[1];
841          if (hexToInt(&ptr, &regno) &&
842              *ptr++ == '=' &&
843              hexToLongLong(&ptr, &regval))
844            {
845              registers[regno] = regval;
846              strcpy (outBuffer, "OK");
847            }
848          else
849              strcpy (outBuffer, "E00"); /* E00 = bad "set register" command */
850          break;
851
852        case 'm':
853          /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
854          ptr = &inBuffer[1];
855          if (hexToInt (&ptr, &addr)
856              && *ptr++ == ','
857              && hexToInt (&ptr, &length)
858              && is_readable (addr, length)
859              && (length < (BUFMAX - 4)/2))
860            mem2hex (addr, length, outBuffer);
861          else
862            strcpy (outBuffer, "E01"); /* E01 = bad 'm' command */
863          break;
864
865        case 'M':
866          /* MAA..AA,LLLL:  Write LLLL bytes at address AA..AA - return OK */
867          ptr = &inBuffer[1];
868          if (hexToInt (&ptr, &addr)
869              && *ptr++ == ','
870              && hexToInt (&ptr, &length)
871              && *ptr++ == ':'
872              && is_writeable (addr, length)
873              && hex2mem (ptr, addr, length))
874            strcpy (outBuffer, "OK");
875          else
876            strcpy (outBuffer, "E02"); /* E02 = bad 'M' command */
877          break;
878
879        case 'c':
880          /* cAA..AA    Continue at address AA..AA(optional) */
881        case 's':
882          /* sAA..AA    Step one instruction from AA..AA(optional) */
883          {
884            /* try to read optional parameter, pc unchanged if no parm */
885            ptr = &inBuffer[1];
886            if (hexToInt (&ptr, &addr))
887              registers[PC] = addr;
888
889            if (inBuffer[0] == 's')
890              doSStep ();
891          }
892          return;
893
894        case 'D':
895          /* remote system is detaching - return OK and exit from debugger */
896          strcpy (outBuffer, "OK");
897          host_has_detached = 1;
898          break;
899
900        default:
901          /* do nothing */
902          break;
903        }                       /* switch */
904
905      /* reply to the request */
906      putpacket (outBuffer);
907    }
908
909   /*
910    *  The original code did this in the assembly wrapper.  We should consider
911    *  doing it here before we return.
912    *
913    *  On exit from the exception handler invalidate each line in the I-cache
914    *  and write back each dirty line in the D-cache.  This needs to be done
915    *  before the target program is resumed in order to ensure that software
916    *  breakpoints and downloaded code will actually take effect.
917    */
918
919  return;
920}
921
922void mips_gdb_stub_install(void) 
923{
924  rtems_isr_entry old;
925
926  rtems_interrupt_catch( (rtems_isr_entry) handle_exception, MIPS_EXCEPTION_SYSCALL, &old );
927  /* rtems_interrupt_catch( handle_exception, MIPS_EXCEPTION_BREAK, &old ); */
928
929  /* get the attention of gdb */
930  mips_break();
931}
Note: See TracBrowser for help on using the repository browser.