source: rtems/c/src/lib/libbsp/mips/shared/gdbstub/mips-stub.c @ 72bbcf1

4.104.114.84.95
Last change on this file since 72bbcf1 was 72bbcf1, checked in by Joel Sherrill <joel.sherrill@…>, on 11/01/02 at 21:53:28

2002-11-01 Joel Sherrill <joel@…>

  • mips-stub.c: Removed warnings.
  • Property mode set to 100644
File size: 43.7 KB
RevLine 
[1bbe2e1]1#define  GDB_STUB_ENABLE_THREAD_SUPPORT 1
[fb63984]2/*******************************************************************************
3
4                     THIS SOFTWARE IS NOT COPYRIGHTED
5
6    The following software is offered for use in the public domain.
7    There is no warranty with regard to this software or its performance
8    and the user must accept the software "AS IS" with all faults.
9
10    THE CONTRIBUTORS DISCLAIM ANY WARRANTIES, EXPRESS OR IMPLIED, WITH
11    REGARD TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
12    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13
[fc82e71]14    $Id$
15
[fb63984]16********************************************************************************
17*
18*   r46kstub.c -- target debugging stub for the IDT R4600 Orion processor
19*
20*   This module is based on the stub for the Hitachi SH processor written by
21*   Ben Lee and Steve Chamberlain and supplied with gdb 4.16.  The latter
22*   in turn "is originally based on an m68k software stub written by Glenn
23*   Engel at HP, but has changed quite a bit."  The changes for the R4600
24*   were written by C. M. Heard at VVNET.  They were based in part on the
25*   Algorithmics R4000 version of Phil Bunce's PMON program.
26*
27*  Remote communication protocol:
28*
29*  A debug packet whose contents are <data>
30*  is encapsulated for transmission in the form:
31*
32*       $ <data> # CSUM1 CSUM2
33*
34*       <data> must be ASCII alphanumeric and cannot include characters
35*       '$' or '#'.  If <data> starts with two characters followed by
36*       ':', then the existing stubs interpret this as a sequence number.
37*
38*       CSUM1 and CSUM2 are ascii hex representation of an 8-bit
39*       checksum of <data>, the most significant nibble is sent first.
40*       the hex digits 0-9,a-f are used.
41*
42*  Receiver responds with:
43*
44*       +    if CSUM is correct
45*       -    if CSUM is incorrect
46*
47*  <data> is as follows.  All values are encoded in ascii hex digits.
48*
49*       Request         Packet
50*
51*       read registers  g
52*       reply           XX....X         Each byte of register data
53*                                       is described by two hex digits.
54*                                       Registers are in the internal order
55*                                       for GDB, and the bytes in a register
56*                                       are in the same order the machine uses.
57*                       or ENN          for an error.
58*
59*       write regs      GXX..XX         Each byte of register data
60*                                       is described by two hex digits.
61*       reply           OK              for success
62*                       ENN             for an error
63*
64*       write reg       Pn...=r...      Write register n... with value r....
65*       reply           OK              for success
66*                       ENN             for an error
67*
68*       read mem        mAA..AA,LLLL    AA..AA is address, LLLL is length.
69*       reply           XX..XX          XX..XX is mem contents
70*                                       Can be fewer bytes than requested
71*                                       if able to read only part of the data.
72*                       or ENN          NN is errno
73*
74*       write mem       MAA..AA,LLLL:XX..XX
75*                                       AA..AA is address,
76*                                       LLLL is number of bytes,
77*                                       XX..XX is data
78*       reply           OK              for success
79*                       ENN             for an error (this includes the case
80*                                       where only part of the data was
81*                                       written).
82*
83*       cont            cAA..AA         AA..AA is address to resume
84*                                       If AA..AA is omitted,
85*                                       resume at same address.
86*
87*       step            sAA..AA         AA..AA is address to resume
88*                                       If AA..AA is omitted,
89*                                       resume at same address.
90*
91*       There is no immediate reply to step or cont.
92*       The reply comes when the machine stops.
93*       It is           SAA             AA is the "signal number"
94*
95*       last signal     ?               Reply with the reason for stopping.
96*                                       This is the same reply as is generated
97*                                       for step or cont: SAA where AA is the
98*                                       signal number.
99*
100*       detach          D               Host is detaching.  Reply OK and
101*                                       end remote debugging session.
102*
103*       reserved        <other>         On other requests, the stub should
104*                                       ignore the request and send an empty
105*                                       response ($#<checksum>).  This way
106*                                       we can extend the protocol and GDB
107*                                       can tell whether the stub it is
108*                                       talking to uses the old or the new.
109*
110*       Responses can be run-length encoded to save space.  A '*' means that
111*       the next character is an ASCII encoding giving a repeat count which
112*       stands for that many repetitions of the character preceding the '*'.
113*       The encoding is n+29, yielding a printable character when n >=3
114*       (which is where rle starts to win).  Don't use n > 99 since gdb
115*       masks each character is receives with 0x7f in order to strip off
116*       the parity bit.
117*
118*       As an example, "0* " means the same thing as "0000".
119*
120*******************************************************************************/
121
122
123#include <string.h>
124#include <signal.h>
125#include "mips_opcode.h"
[2f89140]126/* #include "memlimits.h" */
[fc82e71]127#include <rtems.h>
[fb63984]128#include "gdb_if.h"
129
[1bbe2e1]130extern int printk(const char *fmt, ...);
131
132/* Change it to something meaningful when debugging */
133#undef ASSERT
134#define ASSERT(x) if(!(x)) printk("ASSERT: stub: %d\n", __LINE__)
135
[fc82e71]136/***************/
137/* Exception Codes */
138#define EXC_INT         0               /* External interrupt */
139#define EXC_MOD         1               /* TLB modification exception */
140#define EXC_TLBL        2               /* TLB miss (Load or Ifetch) */
141#define EXC_TLBS        3               /* TLB miss (Store) */
142#define EXC_ADEL        4               /* Address error (Load or Ifetch) */
143#define EXC_ADES        5               /* Address error (Store) */
144#define EXC_IBE         6               /* Bus error (Ifetch) */
145#define EXC_DBE         7               /* Bus error (data load or store) */
146#define EXC_SYS         8               /* System call */
147#define EXC_BP          9               /* Break point */
148#define EXC_RI          10              /* Reserved instruction */
149#define EXC_CPU         11              /* Coprocessor unusable */
150#define EXC_OVF         12              /* Arithmetic overflow */
151#define EXC_TRAP        13              /* Trap exception */
152#define EXC_FPE         15              /* Floating Point Exception */
153
154/* FPU Control/Status register fields */
155#define CSR_FS          0x01000000      /* Set to flush denormals to zero */
156#define CSR_C           0x00800000      /* Condition bit (set by FP compare) */
157
158#define CSR_CMASK       (0x3f<<12)
159#define CSR_CE          0x00020000
160#define CSR_CV          0x00010000
161#define CSR_CZ          0x00008000
162#define CSR_CO          0x00004000
163#define CSR_CU          0x00002000
164#define CSR_CI          0x00001000
165
166#define CSR_EMASK       (0x1f<<7)
167#define CSR_EV          0x00000800
168#define CSR_EZ          0x00000400
169#define CSR_EO          0x00000200
170#define CSR_EU          0x00000100
171#define CSR_EI          0x00000080
172
173#define CSR_FMASK       (0x1f<<2)
174#define CSR_FV          0x00000040
175#define CSR_FZ          0x00000020
176#define CSR_FO          0x00000010
177#define CSR_FU          0x00000008
178#define CSR_FI          0x00000004
179
180#define CSR_RMODE_MASK  (0x3<<0)
181#define CSR_RM          0x00000003
182#define CSR_RP          0x00000002
183#define CSR_RZ          0x00000001
184#define CSR_RN          0x00000000
185
186/***************/
[fb63984]187
188/*
189 * Saved register information.  Must be prepared by the exception
190 * preprocessor before handle_exception is invoked.
191 */
[fc82e71]192#if (__mips == 3)
193typedef long long mips_register_t;
[1bbe2e1]194#define R_SZ 8
[fc82e71]195#elif (__mips == 1)
196typedef unsigned int mips_register_t;
[1bbe2e1]197#define R_SZ 4
[fc82e71]198#else
199#error "unknown MIPS ISA"
200#endif
201static mips_register_t *registers;
[fb63984]202
[1bbe2e1]203#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
204static char do_threads;      /* != 0 means we are supporting threads */
205#endif
[fb63984]206
207/*
208 * The following external functions provide character input and output.
209 */
210extern char getDebugChar (void);
211extern void putDebugChar (char);
212
213
[2f89140]214
215/*
216 * The following definitions are used for the gdb stub memory map
217 */
218struct memseg
219{
220      unsigned begin, end, opts;
221};
222
223static int is_readable(unsigned,unsigned);
224static int is_writeable(unsigned,unsigned);
225static int is_steppable(unsigned);
226
227
228
229
230
231
[fb63984]232/*
233 * BUFMAX defines the maximum number of characters in the inbound & outbound
234 * packet buffers.  At least 4+(sizeof registers)*2 bytes will be needed for
235 * register packets.  Memory dump packets can profitably use even more.
236 */
237#define BUFMAX 1500
238
239static char inBuffer[BUFMAX];
240static char outBuffer[BUFMAX];
241
[1bbe2e1]242/* Structure to keep info on a z-breaks */
243#define BREAKNUM 32
[2f89140]244
[1bbe2e1]245struct z0break
246{
247  /* List support */
248  struct z0break *next;
249  struct z0break *prev;
250
251  /* Location, preserved data */
[a681285]252
253  /* the address pointer, really, really must be a pointer to
254  ** a 32 bit quantity (likely 64 on the R4k), so the full instruction is read &
255  ** written.  Making it a char * as on the i386 will cause
256  ** the zbreaks to mess up the breakpoint instructions
257  */
258  unsigned *address;
[2f89140]259  unsigned instr;
[1bbe2e1]260};
261
262static struct z0break z0break_arr[BREAKNUM];
263static struct z0break *z0break_avail = NULL;
264static struct z0break *z0break_list  = NULL;
265
[fb63984]266
267/*
268 * Convert an int to hex.
269 */
[1bbe2e1]270const char gdb_hexchars[] = "0123456789abcdef";
[fb63984]271
[1bbe2e1]272#define highhex(x) gdb_hexchars [(x >> 4) & 0xf]
273#define lowhex(x) gdb_hexchars [x & 0xf]
[fb63984]274
275
276/*
277 * Convert length bytes of data starting at addr into hex, placing the
278 * result in buf.  Return a pointer to the last (null) char in buf.
279 */
280static char *
[1bbe2e1]281mem2hex (void *_addr, int length, char *buf)
[fb63984]282{
[1bbe2e1]283  unsigned int addr = (unsigned int) _addr;
284
[fb63984]285  if (((addr & 0x7) == 0) && ((length & 0x7) == 0))      /* dword aligned */
286    {
287      long long *source = (long long *) (addr);
288      long long *limit  = (long long *) (addr + length);
289
290      while (source < limit)
291        {
292          int i;
293          long long k = *source++;
294
295          for (i = 15; i >= 0; i--)
[1bbe2e1]296            *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf];
[fb63984]297        }
298    }
299  else if (((addr & 0x3) == 0) && ((length & 0x3) == 0)) /* word aligned */
300    {
301      int *source = (int *) (addr);
302      int *limit  = (int *) (addr + length);
303
304      while (source < limit)
305        {
306          int i;
307          int k = *source++;
308
309          for (i = 7; i >= 0; i--)
[1bbe2e1]310            *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf];
[fb63984]311        }
312    }
313  else if (((addr & 0x1) == 0) && ((length & 0x1) == 0)) /* halfword aligned */
314    {
315      short *source = (short *) (addr);
316      short *limit  = (short *) (addr + length);
317
318      while (source < limit)
319        {
320          int i;
321          short k = *source++;
322
323          for (i = 3; i >= 0; i--)
[1bbe2e1]324            *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf];
[fb63984]325        }
326    }
327  else                                                   /* byte aligned */
328    {
329      char *source = (char *) (addr);
330      char *limit  = (char *) (addr + length);
331
332      while (source < limit)
333        {
334          int i;
335          char k = *source++;
336
337          for (i = 1; i >= 0; i--)
[1bbe2e1]338            *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf];
[fb63984]339        }
340    }
341
342  *buf = '\0';
343  return (buf);
344}
345
346
347/*
348 * Convert a hex character to an int.
349 */
350static int
351hex (char ch)
352{
353  if ((ch >= 'a') && (ch <= 'f'))
354    return (ch - 'a' + 10);
355  if ((ch >= '0') && (ch <= '9'))
356    return (ch - '0');
357  if ((ch >= 'A') && (ch <= 'F'))
358    return (ch - 'A' + 10);
359  return (-1);
360}
361
362
363/*
364 * Convert a string from hex to int until a non-hex digit
365 * is found.  Return the number of characters processed.
366 */
367static int
368hexToInt (char **ptr, int *intValue)
369{
370  int numChars = 0;
371  int hexValue;
372
373  *intValue = 0;
374
375  while (**ptr)
376    {
377      hexValue = hex (**ptr);
378      if (hexValue >= 0)
379        {
380          *intValue = (*intValue << 4) | hexValue;
381          numChars++;
382        }
383      else
384        break;
385
386      (*ptr)++;
387    }
388
389  return (numChars);
390}
391
392
393/*
394 * Convert a string from hex to long long until a non-hex
395 * digit is found.  Return the number of characters processed.
396 */
397static int
398hexToLongLong (char **ptr, long long *intValue)
399{
400  int numChars = 0;
401  int hexValue;
402
403  *intValue = 0;
404
405  while (**ptr)
406    {
407      hexValue = hex (**ptr);
408      if (hexValue >= 0)
409        {
410          *intValue = (*intValue << 4) | hexValue;
411          numChars++;
412        }
413      else
414        break;
415
416      (*ptr)++;
417    }
418
419  return (numChars);
420}
421
422
423/*
424 * Convert the hex array buf into binary, placing the result at the
425 * specified address.  If the conversion fails at any point (i.e.,
426 * if fewer bytes are written than indicated by the size parameter)
427 * then return 0;  otherwise return 1.
428 */
429static int
[1bbe2e1]430hex2mem (char *buf, void *_addr, int length)
[fb63984]431{
[1bbe2e1]432  unsigned int addr = (unsigned int) _addr;
[fb63984]433  if (((addr & 0x7) == 0) && ((length & 0x7) == 0))      /* dword aligned */
434    {
435      long long *target = (long long *) (addr);
436      long long *limit  = (long long *) (addr + length);
437
438      while (target < limit)
439        {
440          int i, j;
441          long long k = 0;
442
443          for (i = 0; i < 16; i++)
444            if ((j = hex(*buf++)) < 0)
445              return 0;
446            else
447              k = (k << 4) + j;
448          *target++ = k;
449        }
450    }
451  else if (((addr & 0x3) == 0) && ((length & 0x3) == 0)) /* word aligned */
452    {
453      int *target = (int *) (addr);
454      int *limit  = (int *) (addr + length);
455
456      while (target < limit)
457        {
458          int i, j;
459          int k = 0;
460
461          for (i = 0; i < 8; i++)
462            if ((j = hex(*buf++)) < 0)
463              return 0;
464            else
465              k = (k << 4) + j;
466          *target++ = k;
467        }
468    }
469  else if (((addr & 0x1) == 0) && ((length & 0x1) == 0)) /* halfword aligned */
470    {
471      short *target = (short *) (addr);
472      short *limit  = (short *) (addr + length);
473
474      while (target < limit)
475        {
476          int i, j;
477          short k = 0;
478
479          for (i = 0; i < 4; i++)
480            if ((j = hex(*buf++)) < 0)
481              return 0;
482            else
483              k = (k << 4) + j;
484          *target++ = k;
485        }
486    }
487  else                                                   /* byte aligned */
488    {
489      char *target = (char *) (addr);
490      char *limit  = (char *) (addr + length);
491
492      while (target < limit)
493        {
494          int i, j;
495          char k = 0;
496
497          for (i = 0; i < 2; i++)
498            if ((j = hex(*buf++)) < 0)
499              return 0;
500            else
501              k = (k << 4) + j;
502          *target++ = k;
503        }
504    }
505
506  return 1;
507}
508
[1bbe2e1]509
510/* Convert the binary stream in BUF to memory.
511
512   Gdb will escape $, #, and the escape char (0x7d).
513   COUNT is the total number of bytes to write into
514   memory. */
515static unsigned char *
516bin2mem (
517  unsigned char *buf,
518  unsigned char *mem,
519  int   count
520)
521{
522  int i;
523
524  for (i = 0; i < count; i++) {
525      /* Check for any escaped characters. Be paranoid and
526         only unescape chars that should be escaped. */
527      if (*buf == 0x7d) {
528          switch (*(buf+1)) {
529            case 0x3:  /* # */
530            case 0x4:  /* $ */
531            case 0x5d: /* escape char */
532              buf++;
533              *buf |= 0x20;
534              break;
535            default:
536              /* nothing */
537              break;
538            }
539        }
540
541      *mem++ = *buf++;
542    }
543
544  return mem;
545}
546
547
[fb63984]548
549/*
550 * Scan the input stream for a sequence for the form $<data>#<checksum>.
551 */
552static void
553getpacket (char *buffer)
554{
555  unsigned char checksum;
556  unsigned char xmitcsum;
557  int i;
558  int count;
559  char ch;
560  do
561    {
562      /* wait around for the start character, ignore all other characters */
563      while ((ch = getDebugChar ()) != '$');
564      checksum = 0;
565      xmitcsum = -1;
566
567      count = 0;
568
569      /* now, read until a # or end of buffer is found */
570      while ( (count < BUFMAX-1) && ((ch = getDebugChar ()) != '#') )
571          checksum += (buffer[count++] = ch);
572
573      /* make sure that the buffer is null-terminated */
574      buffer[count] = '\0';
575
576      if (ch == '#')
577        {
578          xmitcsum = hex (getDebugChar ()) << 4;
579          xmitcsum += hex (getDebugChar ());
580          if (checksum != xmitcsum)
581            putDebugChar ('-'); /* failed checksum */
582          else
583            {
584              putDebugChar ('+');       /* successful transfer */
585              /* if a sequence char is present, reply the sequence ID */
586              if (buffer[2] == ':')
587                {
588                  putDebugChar (buffer[0]);
589                  putDebugChar (buffer[1]);
590                  /* remove sequence chars from buffer */
591                  for (i = 3; i <= count; i++)
592                    buffer[i - 3] = buffer[i];
593                }
594            }
595        }
596    }
597  while (checksum != xmitcsum);
598}
599
600
601/*
602 * Send the packet in buffer and wait for a positive acknowledgement.
603 */
604static void
605putpacket (char *buffer)
606{
607  int checksum;
608
609  /* $<packet info>#<checksum> */
610  do
611    {
612      char *src = buffer;
613      putDebugChar ('$');
614      checksum = 0;
615
616      while (*src != '\0')
617        {
618          int runlen = 0;
619
620          /* Do run length encoding */
621          while ((src[runlen] == src[0]) && (runlen < 99))
622            runlen++;
623          if (runlen > 3)
624            {
625              int encode;
626              /* Got a useful amount */
627              putDebugChar (*src);
628              checksum += *src;
629              putDebugChar ('*');
630              checksum += '*';
631              checksum += (encode = (runlen - 4) + ' ');
632              putDebugChar (encode);
633              src += runlen;
634            }
635          else
636            {
637              putDebugChar (*src);
638              checksum += *src;
639              src++;
640             }
641        }
642
643      putDebugChar ('#');
644      putDebugChar (highhex (checksum));
645      putDebugChar (lowhex (checksum));
646    }
647  while  (getDebugChar () != '+');
648}
649
[2f89140]650
651
652
653
654
[fb63984]655
656/*
657 * Saved instruction data for single step support
658 */
659static struct
660  {
661    unsigned *targetAddr;
662    unsigned savedInstr;
663  }
664instrBuffer;
665
666
667/*
668 * If a step breakpoint was planted restore the saved instruction.
669 */
670static void
671undoSStep (void)
672{
673  if (instrBuffer.targetAddr != NULL)
674    {
675      *instrBuffer.targetAddr = instrBuffer.savedInstr;
676      instrBuffer.targetAddr = NULL;
677    }
678  instrBuffer.savedInstr = NOP_INSTR;
679}
680
681
682/*
683 * If a single step is requested put a temporary breakpoint at the instruction
684 * which logically follows the next one to be executed.  If the next instruction
685 * is a branch instruction then skip the instruction in the delay slot.  NOTE:
686 * ERET instructions are NOT handled, as it is impossible to single-step through
687 * the exit code in an exception handler.  In addition, no attempt is made to
688 * do anything about BC0T and BC0F, since a condition bit for coprocessor 0
689 * is not defined on the R4600.  Finally, BC2T and BC2F are ignored since there
690 * is no coprocessor 2 on a 4600.
691 */
692static void
693doSStep (void)
694{
[2f89140]695   InstFmt inst;
696
697   instrBuffer.targetAddr = (unsigned *)(registers[PC]+4);    /* set default */
698
699   inst.word = *(unsigned *)registers[PC];     /* read the next instruction  */
700
701   switch (inst.RType.op) {                    /* override default if branch */
702      case OP_SPECIAL:
703         switch (inst.RType.func) {
704            case OP_JR:
705            case OP_JALR:
706               instrBuffer.targetAddr =
707                  (unsigned *)registers[inst.RType.rs];
708               break;
709         };
710         break;
711
712      case OP_REGIMM:
713         switch (inst.IType.rt) {
714            case OP_BLTZ:
715            case OP_BLTZL:
716            case OP_BLTZAL:
717            case OP_BLTZALL:
718               if (registers[inst.IType.rs] < 0 )
719                  instrBuffer.targetAddr =
720                     (unsigned *)(((signed short)inst.IType.imm<<2)
721                                  + (registers[PC]+4));
722               else
723                  instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
724               break;
725            case OP_BGEZ:
726            case OP_BGEZL:
727            case OP_BGEZAL:
728            case OP_BGEZALL:
729               if (registers[inst.IType.rs] >= 0 )
730                  instrBuffer.targetAddr =
731                     (unsigned *)(((signed short)inst.IType.imm<<2)
732                                  + (registers[PC]+4));
733               else
734                  instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
735               break;
736         };
737         break;
738
739      case OP_J:
740      case OP_JAL:
741         instrBuffer.targetAddr =
742            (unsigned *)((inst.JType.target<<2) + ((registers[PC]+4)&0xf0000000));
743         break;
744
745      case OP_BEQ:
746      case OP_BEQL:
747         if (registers[inst.IType.rs] == registers[inst.IType.rt])
[fb63984]748            instrBuffer.targetAddr =
[2f89140]749               (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4));
750         else
[fb63984]751            instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
[2f89140]752         break;
753      case OP_BNE:
754      case OP_BNEL:
755         if (registers[inst.IType.rs] != registers[inst.IType.rt])
[fb63984]756            instrBuffer.targetAddr =
[2f89140]757               (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4));
758         else
[fb63984]759            instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
[2f89140]760         break;
761      case OP_BLEZ:
762      case OP_BLEZL:
763         if (registers[inst.IType.rs] <= 0)
764            instrBuffer.targetAddr =
765               (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4));
766         else
767            instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
768         break;
769      case OP_BGTZ:
770      case OP_BGTZL:
771         if (registers[inst.IType.rs] > 0)
772            instrBuffer.targetAddr =
773               (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4));
774         else
775            instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
776         break;
777
778      case OP_COP1:
779         if (inst.RType.rs == OP_BC)
780            switch (inst.RType.rt) {
781               case COPz_BCF:
782               case COPz_BCFL:
783                  if (registers[FCSR] & CSR_C)
784                     instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
785                  else
786                     instrBuffer.targetAddr =
787                        (unsigned *)(((signed short)inst.IType.imm<<2)
788                                     + (registers[PC]+4));
789                  break;
790               case COPz_BCT:
791               case COPz_BCTL:
792                  if (registers[FCSR] & CSR_C)
793                     instrBuffer.targetAddr =
794                        (unsigned *)(((signed short)inst.IType.imm<<2)
795                                     + (registers[PC]+4));
796                  else
797                     instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
798                  break;
799            };
800         break;
801   }
[fb63984]802
[2f89140]803
804   if( is_steppable((unsigned)instrBuffer.targetAddr) && *(instrBuffer.targetAddr) != BREAK_INSTR )
805   {
[fb63984]806      instrBuffer.savedInstr = *instrBuffer.targetAddr;
807      *instrBuffer.targetAddr = BREAK_INSTR;
[2f89140]808   }
809   else
810   {
[fb63984]811      instrBuffer.targetAddr = NULL;
812      instrBuffer.savedInstr = NOP_INSTR;
[2f89140]813   }
814   return;
[fb63984]815}
816
[2f89140]817
818
819
820
[fb63984]821
822/*
823 * Translate the R4600 exception code into a Unix-compatible signal.
824 */
825static int
826computeSignal (void)
827{
828  int exceptionCode = (registers[CAUSE] & CAUSE_EXCMASK) >> CAUSE_EXCSHIFT;
829
830  switch (exceptionCode)
831    {
832    case EXC_INT:
833      /* External interrupt */
834      return SIGINT;
835
836    case EXC_RI:
837      /* Reserved instruction */
838    case EXC_CPU:
839      /* Coprocessor unusable */
840      return SIGILL;
841
842    case EXC_BP:
843      /* Break point */
844      return SIGTRAP;
845
846    case EXC_OVF:
847      /* Arithmetic overflow */
848    case EXC_TRAP:
849      /* Trap exception */
850    case EXC_FPE:
851      /* Floating Point Exception */
852      return SIGFPE;
853
854    case EXC_IBE:
855      /* Bus error (Ifetch) */
856    case EXC_DBE:
857      /* Bus error (data load or store) */
858      return SIGBUS;
859
860    case EXC_MOD:
861      /* TLB modification exception */
862    case EXC_TLBL:
863      /* TLB miss (Load or Ifetch) */
864    case EXC_TLBS:
865      /* TLB miss (Store) */
866    case EXC_ADEL:
867      /* Address error (Load or Ifetch) */
868    case EXC_ADES:
869      /* Address error (Store) */
870      return SIGSEGV;
871
872    case EXC_SYS:
873      /* System call */
874      return SIGSYS;
875
876    default:
877      return SIGTERM;
878    }
879}
880
[1bbe2e1]881/*
882 *  This support function prepares and sends the message containing the
883 *  basic information about this exception.
884 */
885
886void gdb_stub_report_exception_info(
887  rtems_vector_number vector,
888  CPU_Interrupt_frame *frame,
889  int                  thread
890)
891{
[2f89140]892   char *optr;
893   int sigval;
894
895   optr = outBuffer;
896   *optr++ = 'T';
897   sigval = computeSignal ();
898   *optr++ = highhex (sigval);
899   *optr++ = lowhex (sigval);
900
901   *optr++ = highhex(SP); /*gdb_hexchars[SP]; */
902   *optr++ = lowhex(SP);
903   *optr++ = ':';
904   optr    = mem2hstr(optr, (unsigned char *)&frame->sp, R_SZ );
905   *optr++ = ';';
[1bbe2e1]906 
[2f89140]907   *optr++ = highhex(PC); /*gdb_hexchars[PC]; */
908   *optr++ = lowhex(PC);
909   *optr++ = ':';
910   optr    = mem2hstr(optr, (unsigned char *)&frame->epc, R_SZ );
911   *optr++ = ';';
[1bbe2e1]912
913#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
[2f89140]914   if (do_threads)
915   {
916      *optr++ = 't';
917      *optr++ = 'h';
918      *optr++ = 'r';
919      *optr++ = 'e';
920      *optr++ = 'a';
921      *optr++ = 'd';
922      *optr++ = ':';
923      optr   = thread2vhstr(optr, thread);
924      *optr++ = ';';
925   }
[1bbe2e1]926#endif
[2f89140]927   *optr++ = '\0';
[1bbe2e1]928}
929
930
[fb63984]931
[2f89140]932
933/*
934 * Scratch frame used to retrieve contexts for different threads, so as
935 * not to disrupt our current context on the stack
936 */
937CPU_Interrupt_frame current_thread_registers;
938
939
940
[fb63984]941/*
942 * This function handles all exceptions.  It only does two things:
943 * it figures out why it was activated and tells gdb, and then it
944 * reacts to gdb's requests.
945 */
[1bbe2e1]946
947
[6953e68e]948void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
[fb63984]949{
[2f89140]950   int          host_has_detached = 0;
951   int          regno, addr, length;
952   char         *ptr;
953   int          current_thread;  /* current generic thread */
954   int          thread;          /* stopped thread: context exception happened in */
955
956   long long    regval;
957   void         *regptr;
958   int          binary;
959   
960
961   registers = (mips_register_t *)frame;
962
963   thread = 0;
[1bbe2e1]964#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
[2f89140]965   if (do_threads) {
966      thread = rtems_gdb_stub_get_current_thread();
967   }
[1bbe2e1]968#endif
[2f89140]969   current_thread = thread;
970
971
972   {
973      /* reapply all breakpoints regardless of how we came in */
974      struct z0break *z0, *zother;
975
976      for (zother=z0break_list; zother!=NULL; zother=zother->next)
977      {
978         if( zother->instr == 0xffffffff )
979         {
980            /* grab the instruction */
981            zother->instr = *(zother->address);
982            /* and insert the breakpoint */
983            *(zother->address) = BREAK_INSTR;
984         }
985      }
986
987
988
989      /* see if we're coming from a breakpoint */
990      if( *((unsigned *)frame->epc) == BREAK_INSTR )
991      {
992         /* see if its one of our zbreaks */
993         for (z0=z0break_list; z0!=NULL; z0=z0->next)
994         {
995            if( (unsigned)z0->address == frame->epc)
996               break;
997         }
998         if( z0 )
999         {
1000            /* restore the original instruction */
1001            *(z0->address) = z0->instr;
1002            /* flag the breakpoint */
1003            z0->instr = 0xffffffff;
1004
1005            /*
1006               now when we return, we'll execute the original code in
1007               the original state.  This leaves our breakpoint inactive
1008               since the break instruction isn't there, but we'll reapply
1009               it the next time we come in via step or breakpoint
1010            */
1011         }
1012         else
1013         {
1014            /* not a zbreak, see if its our trusty stepping code */
1015
1016            /*
1017             * Restore the saved instruction at
1018             * the single-step target address.
1019             */
1020            undoSStep();
1021         }
1022      }
1023   }
1024
[1bbe2e1]1025
[fb63984]1026
1027
1028
[2f89140]1029   /* reply to host that an exception has occurred with some basic info */
1030   gdb_stub_report_exception_info(vector, frame, thread);
1031   putpacket (outBuffer);
1032
1033
1034
1035   while (!(host_has_detached)) {
[fb63984]1036      outBuffer[0] = '\0';
1037      getpacket (inBuffer);
[1bbe2e1]1038      binary = 0;
[fb63984]1039
[1bbe2e1]1040      switch (inBuffer[0]) {
[2f89140]1041         case '?':
1042            gdb_stub_report_exception_info(vector, frame, thread);
1043            break;
1044
1045         case 'd': /* toggle debug flag */
1046            /* can print ill-formed commands in valid packets & checksum errors */
1047            break;
1048
1049         case 'D':
1050            /* remote system is detaching - return OK and exit from debugger */
1051            strcpy (outBuffer, "OK");
1052            host_has_detached = 1;
1053            break;
1054
1055         case 'g':               /* return the values of the CPU registers */
1056            regptr = registers;
[1bbe2e1]1057#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
[2f89140]1058            if (do_threads && current_thread != thread )
1059               regptr = &current_thread_registers;
[1bbe2e1]1060#endif
[2f89140]1061            mem2hex (regptr, NUM_REGS * (sizeof registers), outBuffer);
1062            break;
[1bbe2e1]1063
[fb63984]1064
[2f89140]1065         case 'G':       /* set the values of the CPU registers - return OK */
1066            regptr = registers;
[1bbe2e1]1067#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
[2f89140]1068            if (do_threads && current_thread != thread )
1069               regptr = &current_thread_registers;
[1bbe2e1]1070#endif
[2f89140]1071            if (hex2mem (&inBuffer[1], regptr, NUM_REGS * (sizeof registers)))
1072               strcpy (outBuffer, "OK");
1073            else
1074               strcpy (outBuffer, "E00"); /* E00 = bad "set register" command */
1075            break;
1076
1077
1078         case 'P':
1079            /* Pn...=r...  Write register n... with value r... - return OK */
1080            ptr = &inBuffer[1];
1081            if (hexToInt(&ptr, &regno) &&
1082                *ptr++ == '=' &&
1083                hexToLongLong(&ptr, &regval))
[fb63984]1084            {
[2f89140]1085               registers[regno] = regval;
1086               strcpy (outBuffer, "OK");
[fb63984]1087            }
[2f89140]1088            else
1089               strcpy (outBuffer, "E00"); /* E00 = bad "set register" command */
1090            break;
1091
1092
1093         case 'm':
1094            /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
1095            ptr = &inBuffer[1];
1096            if (hexToInt (&ptr, &addr)
1097                && *ptr++ == ','
1098                && hexToInt (&ptr, &length)
1099                && is_readable (addr, length)
1100                && (length < (BUFMAX - 4)/2))
1101               mem2hex ((void *)addr, length, outBuffer);
1102            else
1103               strcpy (outBuffer, "E01"); /* E01 = bad 'm' command */
1104            break;
1105
1106
1107         case 'X':  /* XAA..AA,LLLL:<binary data>#cs */
1108            binary = 1;
1109         case 'M':
1110            /* MAA..AA,LLLL:  Write LLLL bytes at address AA..AA - return OK */
1111            ptr = &inBuffer[1];
1112            if (hexToInt (&ptr, &addr)
1113                && *ptr++ == ','
1114                && hexToInt (&ptr, &length)
1115                && *ptr++ == ':'
1116                && is_writeable (addr, length) ) {
1117               if ( binary )
1118                  hex2mem (ptr, (void *)addr, length);
1119               else
1120                  bin2mem (ptr, (void *)addr, length);
1121               strcpy (outBuffer, "OK");
1122            }
1123            else
1124               strcpy (outBuffer, "E02"); /* E02 = bad 'M' command */
1125            break;
1126
1127
1128
1129         case 'c':
1130            /* cAA..AA    Continue at address AA..AA(optional) */
1131         case 's':
1132            /* sAA..AA    Step one instruction from AA..AA(optional) */
1133         {
[fb63984]1134            /* try to read optional parameter, pc unchanged if no parm */
1135            ptr = &inBuffer[1];
1136            if (hexToInt (&ptr, &addr))
[2f89140]1137               registers[PC] = addr;
[fb63984]1138
1139            if (inBuffer[0] == 's')
[2f89140]1140               doSStep ();
1141         }
1142         goto stubexit;
[fb63984]1143
[1bbe2e1]1144
1145
1146
1147
[2f89140]1148         case 'k':  /* remove all zbreaks if any */
1149        dumpzbreaks:
1150         {
1151            {
1152               /* Unlink the entire list */
1153               struct z0break *z0, *znxt;
1154
1155               while( (z0= z0break_list) )
1156               {
1157
1158                  /* put back the instruction */
1159                  if( z0->instr != 0xffffffff )
1160                     *(z0->address) = z0->instr;
1161
1162                  /* pop off the top entry */
1163                  znxt = z0->next;
1164                  if( znxt ) znxt->prev = NULL;
1165                  z0break_list = znxt;
1166
1167                  /* and put it on the free list */
1168                  z0->prev = NULL;
1169                  z0->next = z0break_avail;
1170                  z0break_avail = z0;
1171               }
[1bbe2e1]1172            }
1173
[2f89140]1174            strcpy(outBuffer, "OK");
1175         }
1176         break;
[1bbe2e1]1177
[2f89140]1178
1179
1180
1181
1182         case 'q':   /* queries */
[1bbe2e1]1183#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
[2f89140]1184            rtems_gdb_process_query( inBuffer, outBuffer, do_threads, thread );
1185#endif
1186            break;
1187
1188#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
1189         case 'T':
1190         {
1191            int testThread;
1192
1193            if( vhstr2thread(&inBuffer[1], &testThread) == NULL )
1194            {
1195               strcpy(outBuffer, "E01");
1196               break;
1197            }
1198
1199            if( rtems_gdb_index_to_stub_id(testThread) == NULL )
1200            {
1201               strcpy(outBuffer, "E02");
1202            }
1203            else
1204            {
1205               strcpy(outBuffer, "OK");
1206            }
1207         }
1208         break;
[1bbe2e1]1209#endif
1210       
[2f89140]1211         case 'H':  /* set new thread */
[1bbe2e1]1212#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
[2f89140]1213            if (inBuffer[1] != 'g') {
1214               break;
1215            }
[1bbe2e1]1216         
[2f89140]1217            if (!do_threads) {
1218               break;
1219            }
[1bbe2e1]1220         
[2f89140]1221            {
1222               int tmp, ret;
[1bbe2e1]1223           
[2f89140]1224               /* Set new generic thread */
1225               if (vhstr2thread(&inBuffer[2], &tmp) == NULL) {
1226                  strcpy(outBuffer, "E01");
1227                  break;
1228               }
[fb63984]1229
[2f89140]1230               /* 0 means `thread' */
1231               if (tmp == 0) {
1232                  tmp = thread;
1233               }
1234
1235               if (tmp == current_thread) {
1236                  /* No changes */
1237                  strcpy(outBuffer, "OK");
1238                  break;
1239               }
1240
1241               /* Save current thread registers if necessary */
1242               if (current_thread != thread) {
1243                  ret = rtems_gdb_stub_set_thread_regs(
1244                     current_thread, (unsigned int *) &current_thread_registers);
1245                  ASSERT(ret);
1246               }
1247
1248               /* Read new registers if necessary */
1249               if (tmp != thread) {
1250                  ret = rtems_gdb_stub_get_thread_regs(
1251                     tmp, (unsigned int *) &current_thread_registers);
1252
1253                  if (!ret) {
1254                     /* Thread does not exist */
1255                     strcpy(outBuffer, "E02");
1256                     break;
1257                  }
1258               }
1259           
1260               current_thread = tmp;
1261               strcpy(outBuffer, "OK");
1262            }
[1bbe2e1]1263#endif
[2f89140]1264            break;
[1bbe2e1]1265
[2f89140]1266
1267
1268
1269         case 'Z':  /* Add breakpoint */
1270         {
[1bbe2e1]1271            int ret, type, len;
[72bbcf1]1272            unsigned *address;
[1bbe2e1]1273            struct z0break *z0;
1274
[72bbcf1]1275            ret = parse_zbreak(inBuffer, &type, (unsigned char **)&address, &len);
[1bbe2e1]1276            if (!ret) {
[2f89140]1277               strcpy(outBuffer, "E01");
1278               break;
[1bbe2e1]1279            }
1280
1281            if (type != 0) {
[2f89140]1282               /* We support only software break points so far */
1283               strcpy(outBuffer, "E02");
1284               break;
[1bbe2e1]1285            }
1286
[2f89140]1287            if (len != R_SZ) {     /* was 1 */
1288               strcpy(outBuffer, "E03");
[1bbe2e1]1289               break;
1290            }
1291
1292            /* Let us check whether this break point already set */
1293            for (z0=z0break_list; z0!=NULL; z0=z0->next) {
[2f89140]1294               if (z0->address == address) {
[1bbe2e1]1295                  break;
[2f89140]1296               }
[1bbe2e1]1297            }
1298
1299            if (z0 != NULL) {
[2f89140]1300               /* we already have a breakpoint for this address */
1301               strcpy(outBuffer, "E04");
1302               break;
[1bbe2e1]1303            }
1304
1305            /* Let us allocate new break point */
1306            if (z0break_avail == NULL) {
[2f89140]1307               strcpy(outBuffer, "E05");
1308               break;
[1bbe2e1]1309            }
1310
[2f89140]1311
[1bbe2e1]1312            /* Get entry */
1313            z0 = z0break_avail;
1314            z0break_avail = z0break_avail->next;
1315
1316            /* Let us copy memory from address add stuff the break point in */
[2f89140]1317            /*
1318            *if (mem2hstr(z0->buf, address, 1) == NULL ||
1319              !hstr2mem(address, "cc" , 1)) {
1320
1321               * Memory error *
1322               z0->next = z0break_avail;
1323               z0break_avail = z0;
1324               strcpy(outBuffer, "E05");
1325               break;
1326            }*/
[1bbe2e1]1327
1328            /* Fill it */
1329            z0->address = address;
1330
[72bbcf1]1331            if( z0->address == (unsigned *) frame->epc )
[2f89140]1332            {
1333               /* re-asserting the breakpoint that put us in here, so
1334               we'll add the breakpoint but leave the code in place
1335               since we'll be returning to it when the user continues */
1336               z0->instr = 0xffffffff;
1337            }
1338            else
1339            {
1340               /* grab the instruction */
1341               z0->instr = *(z0->address);
1342               /* and insert the break */
1343               *(z0->address) = BREAK_INSTR;
1344            }
1345
[1bbe2e1]1346            /* Add to the list */
[2f89140]1347            {
1348               struct z0break *znxt = z0break_list;
[1bbe2e1]1349
[2f89140]1350               z0->prev = NULL;
1351               z0->next = znxt;
1352               
1353               if( znxt ) znxt->prev = z0;
1354               z0break_list = z0;
[1bbe2e1]1355            }
1356
1357            strcpy(outBuffer, "OK");
[2f89140]1358         }
1359         break;
[1bbe2e1]1360
1361
[2f89140]1362         case 'z': /* remove breakpoint */
1363            if (inBuffer[1] == 'z')
1364            {
1365               goto dumpzbreaks;
1366               
1367
1368               /*
1369                * zz packet - remove all breaks *
[1bbe2e1]1370                z0last = NULL;
[2f89140]1371
1372                for (z0=z0break_list; z0!=NULL; z0=z0->next)
1373                {
1374                if(!hstr2mem(z0->address, z0->buf, R_SZ))
1375                {
1376                ret = 0;
1377                }
1378                z0last = z0;
1379                }
1380
1381                * Free entries if any *
[1bbe2e1]1382                if (z0last != NULL) {
[2f89140]1383                z0last->next  = z0break_avail;
1384                z0break_avail = z0break_list;
1385                z0break_list  = NULL;
1386                }
[1bbe2e1]1387
1388                if (ret) {
[2f89140]1389                strcpy(outBuffer, "OK");
[1bbe2e1]1390                } else {
[2f89140]1391                strcpy(outBuffer, "E04");
1392                }
[1bbe2e1]1393                break;
[2f89140]1394               */
1395            }
1396            else
1397            {
1398               int ret, type, len;
[72bbcf1]1399               unsigned *address;
[2f89140]1400               struct z0break *z0;
[1bbe2e1]1401             
[72bbcf1]1402
1403               ret = parse_zbreak(inBuffer, &type, (unsigned char **)&address, &len);
[2f89140]1404               if (!ret) {
1405                  strcpy(outBuffer, "E01");
1406                  break;
1407               }
[1bbe2e1]1408
[2f89140]1409               if (type != 0) {
1410                  /* We support only software break points so far */
1411                  break;
1412               }
1413
1414               if (len != R_SZ) {
1415                  strcpy(outBuffer, "E02");
1416                  break;
1417               }
[1bbe2e1]1418           
[2f89140]1419               /* Let us check whether this break point set */
1420               for (z0=z0break_list; z0!=NULL; z0=z0->next) {
1421                  if (z0->address == address) {
1422                     break;
1423                  }
1424               }
[1bbe2e1]1425             
[2f89140]1426               if (z0 == NULL) {
1427                  /* Unknown breakpoint */
1428                  strcpy(outBuffer, "E03");
1429                  break;
1430               }
[1bbe2e1]1431           
[2f89140]1432               /*
1433               if (!hstr2mem(z0->address, z0->buf, R_SZ)) {
1434                  strcpy(outBuffer, "E04");
1435                  break;
1436                  }*/
1437
1438               if( z0->instr != 0xffffffff )
1439               {
1440                  /* put the old instruction back  */
1441                  *(z0->address) = z0->instr;
1442               }
[1bbe2e1]1443   
[2f89140]1444               /* Unlink entry */
1445               {
1446                  struct z0break *zprv = z0->prev, *znxt = z0->next;
1447
1448                  if( zprv ) zprv->next = znxt;
1449                  if( znxt ) znxt->prev = zprv;
1450
1451                  if( !zprv ) z0break_list = znxt;
[1bbe2e1]1452
[2f89140]1453                  znxt = z0break_avail;
1454
1455                  z0break_avail = z0;
1456                  z0->prev = NULL;
1457                  z0->next = znxt;
1458               }
1459   
1460               strcpy(outBuffer, "OK");
1461            }
1462            break;
1463
1464
1465         default: /* do nothing */
1466            break;
[1bbe2e1]1467      }
[fb63984]1468
1469      /* reply to the request */
1470      putpacket (outBuffer);
[2f89140]1471   }
1472
1473  stubexit:
[6953e68e]1474
1475   /*
1476    *  The original code did this in the assembly wrapper.  We should consider
1477    *  doing it here before we return.
1478    *
1479    *  On exit from the exception handler invalidate each line in the I-cache
1480    *  and write back each dirty line in the D-cache.  This needs to be done
1481    *  before the target program is resumed in order to ensure that software
[2f89140]1482    *  breakpoints and downloaded code will actually take effect.  This
1483    *  is because modifications to code in ram will affect the D-cache,
1484    *  but not necessarily the I-cache.
[6953e68e]1485    */
1486
[2f89140]1487   {
1488      extern void clear_cache();
1489      clear_cache();
1490   }
1491
1492   return;
[fb63984]1493}
[6953e68e]1494
[1bbe2e1]1495
[2f89140]1496
1497
1498
1499
1500
1501
1502
1503
1504static int numsegs;
1505static struct memseg   memsegments[NUM_MEMSEGS];
1506
1507int gdbstub_add_memsegment( unsigned base, unsigned end, int opts )
1508{
1509   if( numsegs == NUM_MEMSEGS ) return -1;
1510
1511   memsegments[numsegs].begin = base;
1512   memsegments[numsegs].end   = end;
1513   memsegments[numsegs].opts   = opts;
1514
1515   ++numsegs;
1516   return RTEMS_SUCCESSFUL;
1517}
1518
1519
1520
1521
1522static int is_readable(unsigned ptr, unsigned len)
1523{
1524   struct memseg *ms;
1525   int i;
1526
1527   if( (ptr & 0x3) ) return -1;
1528
1529   for(i=0; i<numsegs; i++)
1530   {
1531      ms= &memsegments[i];
1532
1533      if( ms->begin <= ptr && ptr+len <= ms->end && (ms->opts & MEMOPT_READABLE) )
1534         return -1;
1535   }
1536   return 0;
1537}
1538
1539
1540static int is_writeable(unsigned ptr, unsigned len)
1541{
1542   struct memseg *ms;
1543   int i;
1544
1545   if( (ptr & 0x3) ) return -1;
1546
1547   for(i=0; i<numsegs; i++)
1548   {
1549      ms= &memsegments[i];
1550
1551      if( ms->begin <= ptr && ptr+len <= ms->end && (ms->opts & MEMOPT_WRITEABLE) )
1552         return -1;
1553   }
1554   return 0;
1555}
1556
1557
1558static int is_steppable(unsigned ptr)
1559{
1560   struct memseg *ms;
1561   int i;
1562
1563   if( (ptr & 0x3) ) return -1;
1564
1565   for(i=0; i<numsegs; i++)
1566   {
1567      ms= &memsegments[i];
1568
1569      if( ms->begin <= ptr && ptr <= ms->end && (ms->opts & MEMOPT_WRITEABLE) )
1570         return -1;
1571   }
1572   return 0;
1573}
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588static char initialized = 0;   /* 0 means we are not initialized */
1589
1590void mips_gdb_stub_install(int enableThreads)
[6953e68e]1591{
[cd6bec6]1592   /*
1593     These are the RTEMS-defined vectors for all the MIPS exceptions
1594   */
1595   int exceptionVector[]= { MIPS_EXCEPTION_MOD, \
1596                            MIPS_EXCEPTION_TLBL, \
1597                            MIPS_EXCEPTION_TLBS, \
1598                            MIPS_EXCEPTION_ADEL, \
1599                            MIPS_EXCEPTION_ADES, \
1600                            MIPS_EXCEPTION_IBE, \
1601                            MIPS_EXCEPTION_DBE, \
1602                            MIPS_EXCEPTION_SYSCALL, \
1603                            MIPS_EXCEPTION_BREAK, \
1604                            MIPS_EXCEPTION_RI, \
1605                            MIPS_EXCEPTION_CPU, \
1606                            MIPS_EXCEPTION_OVERFLOW, \
1607                            MIPS_EXCEPTION_TRAP, \
1608                            MIPS_EXCEPTION_VCEI, \
1609                            MIPS_EXCEPTION_FPE, \
1610                            MIPS_EXCEPTION_C2E, \
1611                            MIPS_EXCEPTION_WATCH, \
1612                            MIPS_EXCEPTION_VCED, \
1613                            -1 };
1614   int  i;
1615   rtems_isr_entry old;
1616
[2f89140]1617   if (initialized)
1618   {
[cd6bec6]1619      ASSERT(0);
1620      return;
1621   }
1622
[2f89140]1623   memset( memsegments,0,sizeof(struct memseg)*NUM_MEMSEGS );
1624   numsegs = 0;
[cd6bec6]1625
[2f89140]1626#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
1627   if( enableThreads )
1628      do_threads = 1;
1629   else
1630      do_threads = 0;
1631#endif
1632
1633   {
1634      struct z0break *z0;
[cd6bec6]1635
[2f89140]1636      z0break_avail = NULL;
1637      z0break_list  = NULL;
1638   
1639      /* z0breaks list init, now we'll do it so it makes sense... */
1640      for (i=0; i<BREAKNUM; i++)
1641      {
1642         memset( (z0= &z0break_arr[i]), 0, sizeof(struct z0break));
1643
1644         z0->next = z0break_avail;
1645         z0break_avail = z0;
1646      }
1647   }     
[cd6bec6]1648
1649   for(i=0; exceptionVector[i] > -1; i++)
1650   {
1651      rtems_interrupt_catch( (rtems_isr_entry) handle_exception, exceptionVector[i], &old );
1652   }
1653
1654   initialized = 1;
[2f89140]1655
[cd6bec6]1656   /* get the attention of gdb */
[2f89140]1657   /* mips_break(1);  disabled so user code can choose to invoke it or not */
[cd6bec6]1658}
[6953e68e]1659
1660
[1bbe2e1]1661
Note: See TracBrowser for help on using the repository browser.