Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:51

0001 #define  GDB_STUB_ENABLE_THREAD_SUPPORT 1
0002 /*******************************************************************************
0003 
0004                      THIS SOFTWARE IS NOT COPYRIGHTED
0005 
0006     The following software is offered for use in the public domain.
0007     There is no warranty with regard to this software or its performance
0008     and the user must accept the software "AS IS" with all faults.
0009 
0010     THE CONTRIBUTORS DISCLAIM ANY WARRANTIES, EXPRESS OR IMPLIED, WITH
0011     REGARD TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
0012     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
0013 
0014 ********************************************************************************
0015 *
0016 *   r46kstub.c -- target debugging stub for the IDT R4600 Orion processor
0017 *
0018 *   This module is based on the stub for the Hitachi SH processor written by
0019 *   Ben Lee and Steve Chamberlain and supplied with gdb 4.16.  The latter
0020 *   in turn "is originally based on an m68k software stub written by Glenn
0021 *   Engel at HP, but has changed quite a bit."  The changes for the R4600
0022 *   were written by C. M. Heard at VVNET.  They were based in part on the
0023 *   Algorithmics R4000 version of Phil Bunce's PMON program.
0024 *
0025 *  Remote communication protocol:
0026 *
0027 *  A debug packet whose contents are <data>
0028 *  is encapsulated for transmission in the form:
0029 *
0030 *       $ <data> # CSUM1 CSUM2
0031 *
0032 *       <data> must be ASCII alphanumeric and cannot include characters
0033 *       '$' or '#'.  If <data> starts with two characters followed by
0034 *       ':', then the existing stubs interpret this as a sequence number.
0035 *
0036 *       CSUM1 and CSUM2 are ascii hex representation of an 8-bit
0037 *       checksum of <data>, the most significant nibble is sent first.
0038 *       the hex digits 0-9,a-f are used.
0039 *
0040 *  Receiver responds with:
0041 *
0042 *       +    if CSUM is correct
0043 *       -    if CSUM is incorrect
0044 *
0045 *  <data> is as follows.  All values are encoded in ascii hex digits.
0046 *
0047 *       Request         Packet
0048 *
0049 *       read registers  g
0050 *       reply           XX....X         Each byte of register data
0051 *                                       is described by two hex digits.
0052 *                                       Registers are in the internal order
0053 *                                       for GDB, and the bytes in a register
0054 *                                       are in the same order the machine uses.
0055 *                       or ENN          for an error.
0056 *
0057 *       write regs      GXX..XX         Each byte of register data
0058 *                                       is described by two hex digits.
0059 *       reply           OK              for success
0060 *                       ENN             for an error
0061 *
0062 *       write reg       Pn...=r...      Write register n... with value r....
0063 *       reply           OK              for success
0064 *                       ENN             for an error
0065 *
0066 *       read mem        mAA..AA,LLLL    AA..AA is address, LLLL is length.
0067 *       reply           XX..XX          XX..XX is mem contents
0068 *                                       Can be fewer bytes than requested
0069 *                                       if able to read only part of the data.
0070 *                       or ENN          NN is errno
0071 *
0072 *       write mem       MAA..AA,LLLL:XX..XX
0073 *                                       AA..AA is address,
0074 *                                       LLLL is number of bytes,
0075 *                                       XX..XX is data
0076 *       reply           OK              for success
0077 *                       ENN             for an error (this includes the case
0078 *                                       where only part of the data was
0079 *                                       written).
0080 *
0081 *       cont            cAA..AA         AA..AA is address to resume
0082 *                                       If AA..AA is omitted,
0083 *                                       resume at same address.
0084 *
0085 *       step            sAA..AA         AA..AA is address to resume
0086 *                                       If AA..AA is omitted,
0087 *                                       resume at same address.
0088 *
0089 *       There is no immediate reply to step or cont.
0090 *       The reply comes when the machine stops.
0091 *       It is           SAA             AA is the "signal number"
0092 *
0093 *       last signal     ?               Reply with the reason for stopping.
0094 *                                       This is the same reply as is generated
0095 *                                       for step or cont: SAA where AA is the
0096 *                                       signal number.
0097 *
0098 *       detach          D               Host is detaching.  Reply OK and
0099 *                                       end remote debugging session.
0100 *
0101 *       reserved        <other>         On other requests, the stub should
0102 *                                       ignore the request and send an empty
0103 *                                       response ($#<checksum>).  This way
0104 *                                       we can extend the protocol and GDB
0105 *                                       can tell whether the stub it is
0106 *                                       talking to uses the old or the new.
0107 *
0108 *       Responses can be run-length encoded to save space.  A '*' means that
0109 *       the next character is an ASCII encoding giving a repeat count which
0110 *       stands for that many repetitions of the character preceding the '*'.
0111 *       The encoding is n+29, yielding a printable character when n >=3
0112 *       (which is where rle starts to win).  Don't use n > 99 since gdb
0113 *       masks each character is receives with 0x7f in order to strip off
0114 *       the parity bit.
0115 *
0116 *       As an example, "0* " means the same thing as "0000".
0117 *
0118 *******************************************************************************/
0119 
0120 
0121 #include <string.h>
0122 #include <signal.h>
0123 #include "mips_opcode.h"
0124 /* #include "memlimits.h" */
0125 #include <rtems.h>
0126 #include <rtems/bspIo.h>
0127 #include "gdb_if.h"
0128 
0129 /* Change it to something meaningful when debugging */
0130 #undef ASSERT
0131 #define ASSERT(x) if(!(x)) printk("ASSERT: stub: %d\n", __LINE__)
0132 
0133 /***************/
0134 /* Exception Codes */
0135 #define EXC_INT     0       /* External interrupt */
0136 #define EXC_MOD     1       /* TLB modification exception */
0137 #define EXC_TLBL    2       /* TLB miss (Load or Ifetch) */
0138 #define EXC_TLBS    3       /* TLB miss (Store) */
0139 #define EXC_ADEL    4       /* Address error (Load or Ifetch) */
0140 #define EXC_ADES    5       /* Address error (Store) */
0141 #define EXC_IBE     6       /* Bus error (Ifetch) */
0142 #define EXC_DBE     7       /* Bus error (data load or store) */
0143 #define EXC_SYS     8       /* System call */
0144 #define EXC_BP      9       /* Break point */
0145 #define EXC_RI      10      /* Reserved instruction */
0146 #define EXC_CPU     11      /* Coprocessor unusable */
0147 #define EXC_OVF     12      /* Arithmetic overflow */
0148 #define EXC_TRAP    13      /* Trap exception */
0149 #define EXC_FPE     15      /* Floating Point Exception */
0150 
0151 /* FPU Control/Status register fields */
0152 #define CSR_FS      0x01000000  /* Set to flush denormals to zero */
0153 #define CSR_C       0x00800000  /* Condition bit (set by FP compare) */
0154 
0155 #define CSR_CMASK   (0x3f<<12)
0156 #define CSR_CE      0x00020000
0157 #define CSR_CV      0x00010000
0158 #define CSR_CZ      0x00008000
0159 #define CSR_CO      0x00004000
0160 #define CSR_CU      0x00002000
0161 #define CSR_CI      0x00001000
0162 
0163 #define CSR_EMASK   (0x1f<<7)
0164 #define CSR_EV      0x00000800
0165 #define CSR_EZ      0x00000400
0166 #define CSR_EO      0x00000200
0167 #define CSR_EU      0x00000100
0168 #define CSR_EI      0x00000080
0169 
0170 #define CSR_FMASK   (0x1f<<2)
0171 #define CSR_FV      0x00000040
0172 #define CSR_FZ      0x00000020
0173 #define CSR_FO      0x00000010
0174 #define CSR_FU      0x00000008
0175 #define CSR_FI      0x00000004
0176 
0177 #define CSR_RMODE_MASK  (0x3<<0)
0178 #define CSR_RM      0x00000003
0179 #define CSR_RP      0x00000002
0180 #define CSR_RZ      0x00000001
0181 #define CSR_RN      0x00000000
0182 
0183 /***************/
0184 
0185 /*
0186  * Saved register information.  Must be prepared by the exception
0187  * preprocessor before handle_exception is invoked.
0188  */
0189 #if (__mips == 3)
0190 typedef long long mips_register_t;
0191 #define R_SZ 8
0192 #elif (__mips == 1)
0193 typedef unsigned int mips_register_t;
0194 #define R_SZ 4
0195 #else
0196 #error "unknown MIPS ISA"
0197 #endif
0198 static mips_register_t *registers;
0199 
0200 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
0201 static char do_threads;      /* != 0 means we are supporting threads */
0202 #endif
0203 
0204 /*
0205  * The following external functions provide character input and output.
0206  */
0207 extern char getDebugChar (void);
0208 extern void putDebugChar (char);
0209 
0210 /*
0211  * Exception handler
0212  */
0213 void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame);
0214 
0215 /*
0216  * Prototype needed by this code and to keep it self contained.
0217  */
0218 void rtems_interrupt_catch( rtems_isr_entry, int, rtems_isr_entry *);
0219 
0220 /*
0221  * The following definitions are used for the gdb stub memory map
0222  */
0223 struct memseg
0224 {
0225       unsigned begin, end, opts;
0226 };
0227 
0228 static int is_readable(unsigned,unsigned);
0229 static int is_writeable(unsigned,unsigned);
0230 static int is_steppable(unsigned);
0231 
0232 /*
0233  * BUFMAX defines the maximum number of characters in the inbound & outbound
0234  * packet buffers.  At least 4+(sizeof registers)*2 bytes will be needed for
0235  * register packets.  Memory dump packets can profitably use even more.
0236  */
0237 #define BUFMAX 1500
0238 
0239 static char inBuffer[BUFMAX];
0240 static char outBuffer[BUFMAX];
0241 
0242 /* Structure to keep info on a z-breaks */
0243 #define BREAKNUM 32
0244 
0245 struct z0break
0246 {
0247   /* List support */
0248   struct z0break *next;
0249   struct z0break *prev;
0250 
0251   /* Location, preserved data */
0252 
0253   /* the address pointer, really, really must be a pointer to
0254   ** a 32 bit quantity (likely 64 on the R4k), so the full instruction is read &
0255   ** written.  Making it a char * as on the i386 will cause
0256   ** the zbreaks to mess up the breakpoint instructions
0257   */
0258   unsigned char *address;
0259   unsigned instr;
0260 };
0261 
0262 static struct z0break z0break_arr[BREAKNUM];
0263 static struct z0break *z0break_avail = NULL;
0264 static struct z0break *z0break_list  = NULL;
0265 
0266 
0267 /*
0268  * Convert an int to hex.
0269  */
0270 const char gdb_hexchars[] = "0123456789abcdef";
0271 
0272 #define highhex(x) gdb_hexchars [(x >> 4) & 0xf]
0273 #define lowhex(x) gdb_hexchars [x & 0xf]
0274 
0275 /*
0276  * Convert length bytes of data starting at addr into hex, placing the
0277  * result in buf.  Return a pointer to the last (null) char in buf.
0278  */
0279 static char *
0280 mem2hex (void *_addr, int length, char *buf)
0281 {
0282   unsigned int addr = (unsigned int) _addr;
0283 
0284   if (((addr & 0x7) == 0) && ((length & 0x7) == 0))      /* dword aligned */
0285     {
0286       long long *source = (long long *) (addr);
0287       long long *limit  = (long long *) (addr + length);
0288 
0289       while (source < limit)
0290         {
0291           int i;
0292           long long k = *source++;
0293 
0294           for (i = 15; i >= 0; i--)
0295             *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf];
0296         }
0297     }
0298   else if (((addr & 0x3) == 0) && ((length & 0x3) == 0)) /* word aligned */
0299     {
0300       int *source = (int *) (addr);
0301       int *limit  = (int *) (addr + length);
0302 
0303       while (source < limit)
0304         {
0305           int i;
0306           int k = *source++;
0307 
0308           for (i = 7; i >= 0; i--)
0309             *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf];
0310         }
0311     }
0312   else if (((addr & 0x1) == 0) && ((length & 0x1) == 0)) /* halfword aligned */
0313     {
0314       short *source = (short *) (addr);
0315       short *limit  = (short *) (addr + length);
0316 
0317       while (source < limit)
0318         {
0319           int i;
0320           short k = *source++;
0321 
0322           for (i = 3; i >= 0; i--)
0323             *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf];
0324         }
0325     }
0326   else                                                   /* byte aligned */
0327     {
0328       char *source = (char *) (addr);
0329       char *limit  = (char *) (addr + length);
0330 
0331       while (source < limit)
0332         {
0333           int i;
0334           char k = *source++;
0335 
0336           for (i = 1; i >= 0; i--)
0337             *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf];
0338         }
0339     }
0340 
0341   *buf = '\0';
0342   return (buf);
0343 }
0344 
0345 
0346 /*
0347  * Convert a hex character to an int.
0348  */
0349 static int
0350 hex (char ch)
0351 {
0352   if ((ch >= 'a') && (ch <= 'f'))
0353     return (ch - 'a' + 10);
0354   if ((ch >= '0') && (ch <= '9'))
0355     return (ch - '0');
0356   if ((ch >= 'A') && (ch <= 'F'))
0357     return (ch - 'A' + 10);
0358   return (-1);
0359 }
0360 
0361 /*
0362  * Convert a string from hex to int until a non-hex digit
0363  * is found.  Return the number of characters processed.
0364  */
0365 static int
0366 hexToInt (char **ptr, int *intValue)
0367 {
0368   int numChars = 0;
0369   int hexValue;
0370 
0371   *intValue = 0;
0372 
0373   while (**ptr)
0374     {
0375       hexValue = hex (**ptr);
0376       if (hexValue >= 0)
0377         {
0378           *intValue = (*intValue << 4) | hexValue;
0379           numChars++;
0380         }
0381       else
0382         break;
0383 
0384       (*ptr)++;
0385     }
0386 
0387   return (numChars);
0388 }
0389 
0390 /*
0391  * Convert a string from hex to long long until a non-hex
0392  * digit is found.  Return the number of characters processed.
0393  */
0394 static int
0395 hexToLongLong (char **ptr, long long *intValue)
0396 {
0397   int numChars = 0;
0398   int hexValue;
0399 
0400   *intValue = 0;
0401 
0402   while (**ptr)
0403     {
0404       hexValue = hex (**ptr);
0405       if (hexValue >= 0)
0406         {
0407           *intValue = (*intValue << 4) | hexValue;
0408           numChars++;
0409         }
0410       else
0411         break;
0412 
0413       (*ptr)++;
0414     }
0415 
0416   return (numChars);
0417 }
0418 
0419 /*
0420  * Convert the hex array buf into binary, placing the result at the
0421  * specified address.  If the conversion fails at any point (i.e.,
0422  * if fewer bytes are written than indicated by the size parameter)
0423  * then return 0;  otherwise return 1.
0424  */
0425 static int
0426 hex2mem (char *buf, void *_addr, int length)
0427 {
0428   unsigned int addr = (unsigned int) _addr;
0429   if (((addr & 0x7) == 0) && ((length & 0x7) == 0))      /* dword aligned */
0430     {
0431       long long *target = (long long *) (addr);
0432       long long *limit  = (long long *) (addr + length);
0433 
0434       while (target < limit)
0435         {
0436           int i, j;
0437           long long k = 0;
0438 
0439           for (i = 0; i < 16; i++)
0440             if ((j = hex(*buf++)) < 0)
0441               return 0;
0442             else
0443               k = (k << 4) + j;
0444           *target++ = k;
0445         }
0446     }
0447   else if (((addr & 0x3) == 0) && ((length & 0x3) == 0)) /* word aligned */
0448     {
0449       int *target = (int *) (addr);
0450       int *limit  = (int *) (addr + length);
0451 
0452       while (target < limit)
0453         {
0454           int i, j;
0455           int k = 0;
0456 
0457           for (i = 0; i < 8; i++)
0458             if ((j = hex(*buf++)) < 0)
0459               return 0;
0460             else
0461               k = (k << 4) + j;
0462           *target++ = k;
0463         }
0464     }
0465   else if (((addr & 0x1) == 0) && ((length & 0x1) == 0)) /* halfword aligned */
0466     {
0467       short *target = (short *) (addr);
0468       short *limit  = (short *) (addr + length);
0469 
0470       while (target < limit)
0471         {
0472           int i, j;
0473           short k = 0;
0474 
0475           for (i = 0; i < 4; i++)
0476             if ((j = hex(*buf++)) < 0)
0477               return 0;
0478             else
0479               k = (k << 4) + j;
0480           *target++ = k;
0481         }
0482     }
0483   else                                                   /* byte aligned */
0484     {
0485       char *target = (char *) (addr);
0486       char *limit  = (char *) (addr + length);
0487 
0488       while (target < limit)
0489         {
0490           int i, j;
0491           char k = 0;
0492 
0493           for (i = 0; i < 2; i++)
0494             if ((j = hex(*buf++)) < 0)
0495               return 0;
0496             else
0497               k = (k << 4) + j;
0498           *target++ = k;
0499         }
0500     }
0501 
0502   return 1;
0503 }
0504 
0505 /* Convert the binary stream in BUF to memory.
0506 
0507    Gdb will escape $, #, and the escape char (0x7d).
0508    COUNT is the total number of bytes to write into
0509    memory. */
0510 static unsigned char *
0511 bin2mem (
0512   char *buf,
0513   unsigned char *mem,
0514   int   count
0515 )
0516 {
0517   int i;
0518 
0519   for (i = 0; i < count; i++) {
0520       /* Check for any escaped characters. Be paranoid and
0521          only unescape chars that should be escaped. */
0522       if (*buf == 0x7d) {
0523           switch (*(buf+1)) {
0524             case 0x3:  /* # */
0525             case 0x4:  /* $ */
0526             case 0x5d: /* escape char */
0527               buf++;
0528               *buf |= 0x20;
0529               break;
0530             default:
0531               /* nothing */
0532               break;
0533             }
0534         }
0535 
0536       *mem++ = *buf++;
0537     }
0538 
0539   return mem;
0540 }
0541 
0542 
0543 /*
0544  * Scan the input stream for a sequence for the form $<data>#<checksum>.
0545  */
0546 static void
0547 getpacket (char *buffer)
0548 {
0549   unsigned char checksum;
0550   unsigned char xmitcsum;
0551   int i;
0552   int count;
0553   char ch;
0554   do
0555     {
0556       /* wait around for the start character, ignore all other characters */
0557       while ((ch = getDebugChar ()) != '$');
0558       checksum = 0;
0559       xmitcsum = -1;
0560 
0561       count = 0;
0562 
0563       /* now, read until a # or end of buffer is found */
0564       while ( (count < BUFMAX-1) && ((ch = getDebugChar ()) != '#') )
0565           checksum += (buffer[count++] = ch);
0566 
0567       /* make sure that the buffer is null-terminated */
0568       buffer[count] = '\0';
0569 
0570       if (ch == '#')
0571         {
0572           xmitcsum = hex (getDebugChar ()) << 4;
0573           xmitcsum += hex (getDebugChar ());
0574           if (checksum != xmitcsum)
0575             putDebugChar ('-'); /* failed checksum */
0576           else
0577             {
0578               putDebugChar ('+');       /* successful transfer */
0579               /* if a sequence char is present, reply the sequence ID */
0580               if (buffer[2] == ':')
0581                 {
0582                   putDebugChar (buffer[0]);
0583                   putDebugChar (buffer[1]);
0584                   /* remove sequence chars from buffer */
0585                   for (i = 3; i <= count; i++)
0586                     buffer[i - 3] = buffer[i];
0587                 }
0588             }
0589         }
0590     }
0591   while (checksum != xmitcsum);
0592 }
0593 
0594 /*
0595  * Get a positive/negative acknowledgment for a transmitted packet.
0596  */
0597 static char
0598 getAck (void)
0599 {
0600   char c;
0601 
0602   do
0603     {
0604       c = getDebugChar ();
0605     }
0606   while ((c != '+') && (c != '-'));
0607 
0608   return c;
0609 }
0610 
0611 /*
0612  * Send the packet in buffer and wait for a positive acknowledgement.
0613  */
0614 static void
0615 putpacket (char *buffer)
0616 {
0617   int checksum;
0618 
0619   /* $<packet info>#<checksum> */
0620   do
0621     {
0622       char *src = buffer;
0623       putDebugChar ('$');
0624       checksum = 0;
0625 
0626       while (*src != '\0')
0627         {
0628           int runlen = 0;
0629 
0630           /* Do run length encoding */
0631           while ((src[runlen] == src[0]) && (runlen < 99))
0632             runlen++;
0633           if (runlen > 3)
0634             {
0635               int encode;
0636               /* Got a useful amount */
0637               putDebugChar (*src);
0638               checksum += *src;
0639               putDebugChar ('*');
0640               checksum += '*';
0641               checksum += (encode = (runlen - 4) + ' ');
0642               putDebugChar (encode);
0643               src += runlen;
0644             }
0645           else
0646             {
0647               putDebugChar (*src);
0648               checksum += *src;
0649               src++;
0650              }
0651         }
0652 
0653       putDebugChar ('#');
0654       putDebugChar (highhex (checksum));
0655       putDebugChar (lowhex (checksum));
0656     }
0657   while  (getAck () != '+');
0658 }
0659 
0660 
0661 /*
0662  * Saved instruction data for single step support
0663  */
0664 static struct
0665   {
0666     unsigned *targetAddr;
0667     unsigned savedInstr;
0668   }
0669 instrBuffer;
0670 
0671 /*
0672  * If a step breakpoint was planted restore the saved instruction.
0673  */
0674 static void
0675 undoSStep (void)
0676 {
0677   if (instrBuffer.targetAddr != NULL)
0678     {
0679       *instrBuffer.targetAddr = instrBuffer.savedInstr;
0680       instrBuffer.targetAddr = NULL;
0681     }
0682   instrBuffer.savedInstr = NOP_INSTR;
0683 }
0684 
0685 /*
0686  * If a single step is requested put a temporary breakpoint at the instruction
0687  * which logically follows the next one to be executed.  If the next instruction
0688  * is a branch instruction then skip the instruction in the delay slot.  NOTE:
0689  * ERET instructions are NOT handled, as it is impossible to single-step through
0690  * the exit code in an exception handler.  In addition, no attempt is made to
0691  * do anything about BC0T and BC0F, since a condition bit for coprocessor 0
0692  * is not defined on the R4600.  Finally, BC2T and BC2F are ignored since there
0693  * is no coprocessor 2 on a 4600.
0694  */
0695 static void
0696 doSStep (void)
0697 {
0698    InstFmt inst;
0699 
0700    instrBuffer.targetAddr = (unsigned *)(registers[PC]+4);    /* set default */
0701 
0702    inst.word = *(unsigned *)registers[PC];     /* read the next instruction  */
0703 
0704    switch (inst.RType.op) {                    /* override default if branch */
0705       case OP_SPECIAL:
0706          switch (inst.RType.func) {
0707             case OP_JR:
0708             case OP_JALR:
0709                instrBuffer.targetAddr =
0710                   (unsigned *)registers[inst.RType.rs];
0711                break;
0712          };
0713          break;
0714 
0715       case OP_REGIMM:
0716          switch (inst.IType.rt) {
0717             case OP_BLTZ:
0718             case OP_BLTZL:
0719             case OP_BLTZAL:
0720             case OP_BLTZALL:
0721                if (registers[inst.IType.rs] < 0 )
0722                   instrBuffer.targetAddr =
0723                      (unsigned *)(((signed short)inst.IType.imm<<2)
0724                                   + (registers[PC]+4));
0725                else
0726                   instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
0727                break;
0728             case OP_BGEZ:
0729             case OP_BGEZL:
0730             case OP_BGEZAL:
0731             case OP_BGEZALL:
0732                if (registers[inst.IType.rs] >= 0 )
0733                   instrBuffer.targetAddr =
0734                      (unsigned *)(((signed short)inst.IType.imm<<2)
0735                                   + (registers[PC]+4));
0736                else
0737                   instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
0738                break;
0739          };
0740          break;
0741 
0742       case OP_J:
0743       case OP_JAL:
0744          instrBuffer.targetAddr =
0745             (unsigned *)((inst.JType.target<<2) + ((registers[PC]+4)&0xf0000000));
0746          break;
0747 
0748       case OP_BEQ:
0749       case OP_BEQL:
0750          if (registers[inst.IType.rs] == registers[inst.IType.rt])
0751             instrBuffer.targetAddr =
0752                (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4));
0753          else
0754             instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
0755          break;
0756       case OP_BNE:
0757       case OP_BNEL:
0758          if (registers[inst.IType.rs] != registers[inst.IType.rt])
0759             instrBuffer.targetAddr =
0760                (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4));
0761          else
0762             instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
0763          break;
0764       case OP_BLEZ:
0765       case OP_BLEZL:
0766          if (registers[inst.IType.rs] <= 0)
0767             instrBuffer.targetAddr =
0768                (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4));
0769          else
0770             instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
0771          break;
0772       case OP_BGTZ:
0773       case OP_BGTZL:
0774          if (registers[inst.IType.rs] > 0)
0775             instrBuffer.targetAddr =
0776                (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4));
0777          else
0778             instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
0779          break;
0780 
0781       case OP_COP1:
0782          if (inst.RType.rs == OP_BC)
0783             switch (inst.RType.rt) {
0784                case COPz_BCF:
0785                case COPz_BCFL:
0786                   if (registers[FCSR] & CSR_C)
0787                      instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
0788                   else
0789                      instrBuffer.targetAddr =
0790                         (unsigned *)(((signed short)inst.IType.imm<<2)
0791                                      + (registers[PC]+4));
0792                   break;
0793                case COPz_BCT:
0794                case COPz_BCTL:
0795                   if (registers[FCSR] & CSR_C)
0796                      instrBuffer.targetAddr =
0797                         (unsigned *)(((signed short)inst.IType.imm<<2)
0798                                      + (registers[PC]+4));
0799                   else
0800                      instrBuffer.targetAddr = (unsigned*)(registers[PC]+8);
0801                   break;
0802             };
0803          break;
0804    }
0805 
0806    if( is_steppable((unsigned)instrBuffer.targetAddr) && *(instrBuffer.targetAddr) != BREAK_INSTR )
0807    {
0808       instrBuffer.savedInstr = *instrBuffer.targetAddr;
0809       *instrBuffer.targetAddr = BREAK_INSTR;
0810    }
0811    else
0812    {
0813       instrBuffer.targetAddr = NULL;
0814       instrBuffer.savedInstr = NOP_INSTR;
0815    }
0816    return;
0817 }
0818 
0819 
0820 /*
0821  * Translate the R4600 exception code into a Unix-compatible signal.
0822  */
0823 static int
0824 computeSignal (void)
0825 {
0826   int exceptionCode = (registers[CAUSE] & CAUSE_EXCMASK) >> CAUSE_EXCSHIFT;
0827 
0828   switch (exceptionCode)
0829     {
0830     case EXC_INT:
0831       /* External interrupt */
0832       return SIGINT;
0833 
0834     case EXC_RI:
0835       /* Reserved instruction */
0836     case EXC_CPU:
0837       /* Coprocessor unusable */
0838       return SIGILL;
0839 
0840     case EXC_BP:
0841       /* Break point */
0842       return SIGTRAP;
0843 
0844     case EXC_OVF:
0845       /* Arithmetic overflow */
0846     case EXC_TRAP:
0847       /* Trap exception */
0848     case EXC_FPE:
0849       /* Floating Point Exception */
0850       return SIGFPE;
0851 
0852     case EXC_IBE:
0853       /* Bus error (Ifetch) */
0854     case EXC_DBE:
0855       /* Bus error (data load or store) */
0856       return SIGBUS;
0857 
0858     case EXC_MOD:
0859       /* TLB modification exception */
0860     case EXC_TLBL:
0861       /* TLB miss (Load or Ifetch) */
0862     case EXC_TLBS:
0863       /* TLB miss (Store) */
0864     case EXC_ADEL:
0865       /* Address error (Load or Ifetch) */
0866     case EXC_ADES:
0867       /* Address error (Store) */
0868       return SIGSEGV;
0869 
0870     case EXC_SYS:
0871       /* System call */
0872       return SIGSYS;
0873 
0874     default:
0875       return SIGTERM;
0876     }
0877 }
0878 
0879 /*
0880  *  This support function prepares and sends the message containing the
0881  *  basic information about this exception.
0882  */
0883 static void gdb_stub_report_exception_info(
0884   rtems_vector_number vector,
0885   CPU_Interrupt_frame *frame,
0886   int                  thread
0887 )
0888 {
0889    char *optr;
0890    int sigval;
0891 
0892    optr = outBuffer;
0893    *optr++ = 'T';
0894    sigval = computeSignal ();
0895    *optr++ = highhex (sigval);
0896    *optr++ = lowhex (sigval);
0897 
0898    *optr++ = highhex(SP); /*gdb_hexchars[SP]; */
0899    *optr++ = lowhex(SP);
0900    *optr++ = ':';
0901    optr    = mem2hstr(optr, (unsigned char *)&frame->sp, R_SZ );
0902    *optr++ = ';';
0903 
0904    *optr++ = highhex(PC); /*gdb_hexchars[PC]; */
0905    *optr++ = lowhex(PC);
0906    *optr++ = ':';
0907    optr    = mem2hstr(optr, (unsigned char *)&frame->epc, R_SZ );
0908    *optr++ = ';';
0909 
0910 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
0911    if (do_threads)
0912    {
0913       *optr++ = 't';
0914       *optr++ = 'h';
0915       *optr++ = 'r';
0916       *optr++ = 'e';
0917       *optr++ = 'a';
0918       *optr++ = 'd';
0919       *optr++ = ':';
0920       optr   = thread2vhstr(optr, thread);
0921       *optr++ = ';';
0922    }
0923 #endif
0924    *optr++ = '\0';
0925 }
0926 
0927 
0928 
0929 /*
0930  * Scratch frame used to retrieve contexts for different threads, so as
0931  * not to disrupt our current context on the stack
0932  */
0933 CPU_Interrupt_frame current_thread_registers;
0934 
0935 /*
0936  * This function handles all exceptions.  It only does two things:
0937  * it figures out why it was activated and tells gdb, and then it
0938  * reacts to gdb's requests.
0939  */
0940 
0941 extern void clear_cache(void);
0942 void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame)
0943 {
0944    int          host_has_detached = 0;
0945    int          regno, addr, length;
0946    char         *ptr;
0947    int          current_thread;  /* current generic thread */
0948    int          thread;          /* stopped thread: context exception happened in */
0949 
0950    long long    regval;
0951    void         *regptr;
0952    int          binary;
0953 
0954    registers = (mips_register_t *)frame;
0955 
0956    thread = 0;
0957 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
0958    if (do_threads) {
0959       thread = rtems_gdb_stub_get_current_thread();
0960    }
0961 #endif
0962    current_thread = thread;
0963 
0964    {
0965       /* reapply all breakpoints regardless of how we came in */
0966       struct z0break *z0, *zother;
0967 
0968       for (zother=z0break_list; zother!=NULL; zother=zother->next)
0969       {
0970          if( zother->instr == 0xffffffff )
0971          {
0972             /* grab the instruction */
0973             zother->instr = *(zother->address);
0974             /* and insert the breakpoint */
0975             *(zother->address) = BREAK_INSTR;
0976          }
0977       }
0978 
0979       /* see if we're coming from a breakpoint */
0980       if( *((unsigned *)frame->epc) == BREAK_INSTR )
0981       {
0982          /* see if its one of our zbreaks */
0983          for (z0=z0break_list; z0!=NULL; z0=z0->next)
0984          {
0985             if( (unsigned)z0->address == frame->epc)
0986                break;
0987          }
0988          if( z0 )
0989          {
0990             /* restore the original instruction */
0991             *(z0->address) = z0->instr;
0992             /* flag the breakpoint */
0993             z0->instr = 0xffffffff;
0994 
0995             /*
0996                now when we return, we'll execute the original code in
0997                the original state.  This leaves our breakpoint inactive
0998                since the break instruction isn't there, but we'll reapply
0999                it the next time we come in via step or breakpoint
1000             */
1001          }
1002          else
1003          {
1004             /* not a zbreak, see if its our trusty stepping code */
1005 
1006             /*
1007              * Restore the saved instruction at
1008              * the single-step target address.
1009              */
1010             undoSStep();
1011          }
1012       }
1013    }
1014 
1015    /* reply to host that an exception has occurred with some basic info */
1016    gdb_stub_report_exception_info(vector, frame, thread);
1017    putpacket (outBuffer);
1018 
1019    while (!(host_has_detached)) {
1020       outBuffer[0] = '\0';
1021       getpacket (inBuffer);
1022       binary = 0;
1023 
1024       switch (inBuffer[0]) {
1025          case '?':
1026             gdb_stub_report_exception_info(vector, frame, thread);
1027             break;
1028 
1029          case 'd': /* toggle debug flag */
1030             /* can print ill-formed commands in valid packets & checksum errors */
1031             break;
1032 
1033          case 'D':
1034             /* remote system is detaching - return OK and exit from debugger */
1035             strcpy (outBuffer, "OK");
1036             host_has_detached = 1;
1037             break;
1038 
1039          case 'g':               /* return the values of the CPU registers */
1040             regptr = registers;
1041 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
1042             if (do_threads && current_thread != thread )
1043                regptr = &current_thread_registers;
1044 #endif
1045             mem2hex (regptr, NUM_REGS * (sizeof registers), outBuffer);
1046             break;
1047 
1048          case 'G':       /* set the values of the CPU registers - return OK */
1049             regptr = registers;
1050 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
1051             if (do_threads && current_thread != thread )
1052                regptr = &current_thread_registers;
1053 #endif
1054             if (hex2mem (&inBuffer[1], regptr, NUM_REGS * (sizeof registers)))
1055                strcpy (outBuffer, "OK");
1056             else
1057                strcpy (outBuffer, "E00"); /* E00 = bad "set register" command */
1058             break;
1059 
1060          case 'P':
1061             /* Pn...=r...  Write register n... with value r... - return OK */
1062             ptr = &inBuffer[1];
1063             if (hexToInt(&ptr, &regno) &&
1064                 *ptr++ == '=' &&
1065                 hexToLongLong(&ptr, &regval))
1066             {
1067                registers[regno] = regval;
1068                strcpy (outBuffer, "OK");
1069             }
1070             else
1071                strcpy (outBuffer, "E00"); /* E00 = bad "set register" command */
1072             break;
1073 
1074          case 'm':
1075             /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
1076             ptr = &inBuffer[1];
1077             if (hexToInt (&ptr, &addr)
1078                 && *ptr++ == ','
1079                 && hexToInt (&ptr, &length)
1080                 && is_readable (addr, length)
1081                 && (length < (BUFMAX - 4)/2))
1082                mem2hex ((void *)addr, length, outBuffer);
1083             else
1084                strcpy (outBuffer, "E01"); /* E01 = bad 'm' command */
1085             break;
1086 
1087          case 'X':  /* XAA..AA,LLLL:<binary data>#cs */
1088             binary = 1;
1089          case 'M':
1090             /* MAA..AA,LLLL:  Write LLLL bytes at address AA..AA - return OK */
1091             ptr = &inBuffer[1];
1092             if (hexToInt (&ptr, &addr)
1093                 && *ptr++ == ','
1094                 && hexToInt (&ptr, &length)
1095                 && *ptr++ == ':'
1096                 && is_writeable (addr, length) ) {
1097                if ( binary )
1098                   hex2mem (ptr, (void *)addr, length);
1099                else
1100                   bin2mem (ptr, (void *)addr, length);
1101                strcpy (outBuffer, "OK");
1102             }
1103             else
1104                strcpy (outBuffer, "E02"); /* E02 = bad 'M' command */
1105             break;
1106 
1107          case 'c':
1108             /* cAA..AA    Continue at address AA..AA(optional) */
1109          case 's':
1110             /* sAA..AA    Step one instruction from AA..AA(optional) */
1111          {
1112             /* try to read optional parameter, pc unchanged if no parm */
1113             ptr = &inBuffer[1];
1114             if (hexToInt (&ptr, &addr))
1115                registers[PC] = addr;
1116 
1117             if (inBuffer[0] == 's')
1118                doSStep ();
1119          }
1120          goto stubexit;
1121 
1122          case 'k':  /* remove all zbreaks if any */
1123         dumpzbreaks:
1124          {
1125             {
1126                /* Unlink the entire list */
1127                struct z0break *z0, *znxt;
1128 
1129                while( (z0= z0break_list) )
1130                {
1131 
1132                   /* put back the instruction */
1133                   if( z0->instr != 0xffffffff )
1134                      *(z0->address) = z0->instr;
1135 
1136                   /* pop off the top entry */
1137                   znxt = z0->next;
1138                   if( znxt ) znxt->prev = NULL;
1139                   z0break_list = znxt;
1140 
1141                   /* and put it on the free list */
1142                   z0->prev = NULL;
1143                   z0->next = z0break_avail;
1144                   z0break_avail = z0;
1145                }
1146             }
1147 
1148             strcpy(outBuffer, "OK");
1149          }
1150          break;
1151 
1152          case 'q':   /* queries */
1153 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
1154             rtems_gdb_process_query( inBuffer, outBuffer, do_threads, thread );
1155 #endif
1156             break;
1157 
1158 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
1159          case 'T':
1160          {
1161             int testThread;
1162 
1163             if( vhstr2thread(&inBuffer[1], &testThread) == NULL )
1164             {
1165                strcpy(outBuffer, "E01");
1166                break;
1167             }
1168 
1169             if( rtems_gdb_index_to_stub_id(testThread) == NULL )
1170             {
1171                strcpy(outBuffer, "E02");
1172             }
1173             else
1174             {
1175                strcpy(outBuffer, "OK");
1176             }
1177          }
1178          break;
1179 #endif
1180 
1181          case 'H':  /* set new thread */
1182 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
1183             if (inBuffer[1] != 'g') {
1184                break;
1185             }
1186 
1187             if (!do_threads) {
1188                break;
1189             }
1190 
1191             {
1192                int tmp, ret;
1193 
1194                /* Set new generic thread */
1195                if (vhstr2thread(&inBuffer[2], &tmp) == NULL) {
1196                   strcpy(outBuffer, "E01");
1197                   break;
1198                }
1199 
1200                /* 0 means `thread' */
1201                if (tmp == 0) {
1202                   tmp = thread;
1203                }
1204 
1205                if (tmp == current_thread) {
1206                   /* No changes */
1207                   strcpy(outBuffer, "OK");
1208                   break;
1209                }
1210 
1211                /* Save current thread registers if necessary */
1212                if (current_thread != thread) {
1213                   ret = rtems_gdb_stub_set_thread_regs(
1214                      current_thread,
1215                      (unsigned int *) (void *)&current_thread_registers);
1216                   ASSERT(ret);
1217                }
1218 
1219                /* Read new registers if necessary */
1220                if (tmp != thread) {
1221                   ret = rtems_gdb_stub_get_thread_regs(
1222                      tmp, (unsigned int *) (void *)&current_thread_registers);
1223 
1224                   if (!ret) {
1225                      /* Thread does not exist */
1226                      strcpy(outBuffer, "E02");
1227                      break;
1228                   }
1229                }
1230 
1231                current_thread = tmp;
1232                strcpy(outBuffer, "OK");
1233             }
1234 #endif
1235             break;
1236 
1237          case 'Z':  /* Add breakpoint */
1238          {
1239             int ret, type, len;
1240             unsigned char *address;
1241             struct z0break *z0;
1242 
1243             ret = parse_zbreak(inBuffer, &type, &address, &len);
1244             if (!ret) {
1245                strcpy(outBuffer, "E01");
1246                break;
1247             }
1248 
1249             if (type != 0) {
1250                /* We support only software break points so far */
1251                strcpy(outBuffer, "E02");
1252                break;
1253             }
1254 
1255             if (len != R_SZ) {     /* was 1 */
1256                strcpy(outBuffer, "E03");
1257                break;
1258             }
1259 
1260             /* Let us check whether this break point already set */
1261             for (z0=z0break_list; z0!=NULL; z0=z0->next) {
1262                if (z0->address == address) {
1263                   break;
1264                }
1265             }
1266 
1267             if (z0 != NULL) {
1268                /* we already have a breakpoint for this address */
1269                strcpy(outBuffer, "E04");
1270                break;
1271             }
1272 
1273             /* Let us allocate new break point */
1274             if (z0break_avail == NULL) {
1275                strcpy(outBuffer, "E05");
1276                break;
1277             }
1278 
1279             /* Get entry */
1280             z0 = z0break_avail;
1281             z0break_avail = z0break_avail->next;
1282 
1283             /* Let us copy memory from address add stuff the break point in */
1284             /*
1285             *if (mem2hstr(z0->buf, address, 1) == NULL ||
1286               !hstr2mem(address, "cc" , 1)) {
1287 
1288                * Memory error *
1289                z0->next = z0break_avail;
1290                z0break_avail = z0;
1291                strcpy(outBuffer, "E05");
1292                break;
1293             }*/
1294 
1295             /* Fill it */
1296             z0->address = address;
1297 
1298             if( z0->address == (unsigned char *) frame->epc )
1299             {
1300                /* re-asserting the breakpoint that put us in here, so
1301                we'll add the breakpoint but leave the code in place
1302                since we'll be returning to it when the user continues */
1303                z0->instr = 0xffffffff;
1304             }
1305             else
1306             {
1307                /* grab the instruction */
1308                z0->instr = *(z0->address);
1309                /* and insert the break */
1310                *(z0->address) = BREAK_INSTR;
1311             }
1312 
1313             /* Add to the list */
1314             {
1315                struct z0break *znxt = z0break_list;
1316 
1317                z0->prev = NULL;
1318                z0->next = znxt;
1319 
1320                if( znxt ) znxt->prev = z0;
1321                z0break_list = z0;
1322             }
1323 
1324             strcpy(outBuffer, "OK");
1325          }
1326          break;
1327 
1328          case 'z': /* remove breakpoint */
1329             if (inBuffer[1] == 'z')
1330             {
1331                goto dumpzbreaks;
1332 
1333                /*
1334                 * zz packet - remove all breaks *
1335                 z0last = NULL;
1336 
1337                 for (z0=z0break_list; z0!=NULL; z0=z0->next)
1338                 {
1339                 if(!hstr2mem(z0->address, z0->buf, R_SZ))
1340                 {
1341                 ret = 0;
1342                 }
1343                 z0last = z0;
1344                 }
1345 
1346                 * Free entries if any *
1347                 if (z0last != NULL) {
1348                 z0last->next  = z0break_avail;
1349                 z0break_avail = z0break_list;
1350                 z0break_list  = NULL;
1351                 }
1352 
1353                 if (ret) {
1354                 strcpy(outBuffer, "OK");
1355                 } else {
1356                 strcpy(outBuffer, "E04");
1357                 }
1358                 break;
1359                */
1360             }
1361             else
1362             {
1363                int ret, type, len;
1364                unsigned char *address;
1365                struct z0break *z0;
1366 
1367                ret = parse_zbreak(inBuffer, &type, &address, &len);
1368                if (!ret) {
1369                   strcpy(outBuffer, "E01");
1370                   break;
1371                }
1372 
1373                if (type != 0) {
1374                   /* We support only software break points so far */
1375                   break;
1376                }
1377 
1378                if (len != R_SZ) {
1379                   strcpy(outBuffer, "E02");
1380                   break;
1381                }
1382 
1383                /* Let us check whether this break point set */
1384                for (z0=z0break_list; z0!=NULL; z0=z0->next) {
1385                   if (z0->address == address) {
1386                      break;
1387                   }
1388                }
1389 
1390                if (z0 == NULL) {
1391                   /* Unknown breakpoint */
1392                   strcpy(outBuffer, "E03");
1393                   break;
1394                }
1395 
1396                /*
1397                if (!hstr2mem(z0->address, z0->buf, R_SZ)) {
1398                   strcpy(outBuffer, "E04");
1399                   break;
1400                   }*/
1401 
1402                if( z0->instr != 0xffffffff )
1403                {
1404                   /* put the old instruction back  */
1405                   *(z0->address) = z0->instr;
1406                }
1407 
1408                /* Unlink entry */
1409                {
1410                   struct z0break *zprv = z0->prev, *znxt = z0->next;
1411 
1412                   if( zprv ) zprv->next = znxt;
1413                   if( znxt ) znxt->prev = zprv;
1414 
1415                   if( !zprv ) z0break_list = znxt;
1416 
1417                   znxt = z0break_avail;
1418 
1419                   z0break_avail = z0;
1420                   z0->prev = NULL;
1421                   z0->next = znxt;
1422                }
1423 
1424                strcpy(outBuffer, "OK");
1425             }
1426             break;
1427 
1428          default: /* do nothing */
1429             break;
1430       }
1431 
1432       /* reply to the request */
1433       putpacket (outBuffer);
1434    }
1435 
1436   stubexit:
1437 
1438    /*
1439     *  The original code did this in the assembly wrapper.  We should consider
1440     *  doing it here before we return.
1441     *
1442     *  On exit from the exception handler invalidate each line in the I-cache
1443     *  and write back each dirty line in the D-cache.  This needs to be done
1444     *  before the target program is resumed in order to ensure that software
1445     *  breakpoints and downloaded code will actually take effect.  This
1446     *  is because modifications to code in ram will affect the D-cache,
1447     *  but not necessarily the I-cache.
1448     */
1449 
1450    clear_cache();
1451 }
1452 
1453 static int numsegs;
1454 static struct memseg   memsegments[NUM_MEMSEGS];
1455 
1456 int gdbstub_add_memsegment( unsigned base, unsigned end, int opts )
1457 {
1458    if( numsegs == NUM_MEMSEGS ) return -1;
1459 
1460    memsegments[numsegs].begin = base;
1461    memsegments[numsegs].end   = end;
1462    memsegments[numsegs].opts   = opts;
1463 
1464    ++numsegs;
1465    return RTEMS_SUCCESSFUL;
1466 }
1467 
1468 static int is_readable(unsigned ptr, unsigned len)
1469 {
1470    struct memseg *ms;
1471    int i;
1472 
1473    if( (ptr & 0x3) ) return -1;
1474 
1475    for(i=0; i<numsegs; i++)
1476    {
1477       ms= &memsegments[i];
1478 
1479       if( ms->begin <= ptr && ptr+len <= ms->end && (ms->opts & MEMOPT_READABLE) )
1480          return -1;
1481    }
1482    return 0;
1483 }
1484 
1485 static int is_writeable(unsigned ptr, unsigned len)
1486 {
1487    struct memseg *ms;
1488    int i;
1489 
1490    if( (ptr & 0x3) ) return -1;
1491 
1492    for(i=0; i<numsegs; i++)
1493    {
1494       ms= &memsegments[i];
1495 
1496       if( ms->begin <= ptr && ptr+len <= ms->end && (ms->opts & MEMOPT_WRITEABLE) )
1497          return -1;
1498    }
1499    return 0;
1500 }
1501 
1502 static int is_steppable(unsigned ptr)
1503 {
1504    struct memseg *ms;
1505    int i;
1506 
1507    if( (ptr & 0x3) ) return -1;
1508 
1509    for(i=0; i<numsegs; i++)
1510    {
1511       ms= &memsegments[i];
1512 
1513       if( ms->begin <= ptr && ptr <= ms->end && (ms->opts & MEMOPT_WRITEABLE) )
1514          return -1;
1515    }
1516    return 0;
1517 }
1518 
1519 static char initialized = 0;   /* 0 means we are not initialized */
1520 
1521 void mips_gdb_stub_install(int enableThreads)
1522 {
1523    /*
1524      These are the RTEMS-defined vectors for all the MIPS exceptions
1525    */
1526    int exceptionVector[]= { MIPS_EXCEPTION_MOD, \
1527                             MIPS_EXCEPTION_TLBL, \
1528                             MIPS_EXCEPTION_TLBS, \
1529                             MIPS_EXCEPTION_ADEL, \
1530                             MIPS_EXCEPTION_ADES, \
1531                             MIPS_EXCEPTION_IBE, \
1532                             MIPS_EXCEPTION_DBE, \
1533                             MIPS_EXCEPTION_SYSCALL, \
1534                             MIPS_EXCEPTION_BREAK, \
1535                             MIPS_EXCEPTION_RI, \
1536                             MIPS_EXCEPTION_CPU, \
1537                             MIPS_EXCEPTION_OVERFLOW, \
1538                             MIPS_EXCEPTION_TRAP, \
1539                             MIPS_EXCEPTION_VCEI, \
1540                             MIPS_EXCEPTION_FPE, \
1541                             MIPS_EXCEPTION_C2E, \
1542                             MIPS_EXCEPTION_WATCH, \
1543                             MIPS_EXCEPTION_VCED, \
1544                             -1 };
1545    int  i;
1546    rtems_isr_entry old;
1547 
1548    if (initialized)
1549    {
1550       ASSERT(0);
1551       return;
1552    }
1553 
1554    memset( memsegments,0,sizeof(struct memseg)*NUM_MEMSEGS );
1555    numsegs = 0;
1556 
1557 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
1558    if( enableThreads )
1559       do_threads = 1;
1560    else
1561       do_threads = 0;
1562 #endif
1563 
1564    {
1565       struct z0break *z0;
1566 
1567       z0break_avail = NULL;
1568       z0break_list  = NULL;
1569 
1570       /* z0breaks list init, now we'll do it so it makes sense... */
1571       for (i=0; i<BREAKNUM; i++)
1572       {
1573          memset( (z0= &z0break_arr[i]), 0, sizeof(struct z0break));
1574 
1575          z0->next = z0break_avail;
1576          z0break_avail = z0;
1577       }
1578    }
1579 
1580    for(i=0; exceptionVector[i] > -1; i++)
1581    {
1582       rtems_interrupt_catch( (rtems_isr_entry) handle_exception, exceptionVector[i], &old );
1583    }
1584 
1585    initialized = 1;
1586 
1587    /* get the attention of gdb */
1588    /* mips_break(1);  disabled so user code can choose to invoke it or not */
1589 }