Back to home page

LXR

 
 

    


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

0001 /*
0002  * Low-level support for LM32 remote debuging with GDB.
0003  * Contributed by Jon Beniston <jon@beniston.com>
0004  * Modified for RTEMS with thread support by Michael Walle <michael@walle.cc>
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  * notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  * notice, this list of conditions and the following disclaimer in the
0013  * documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
0016  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
0019  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0020  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0021  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0022  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0023  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0024  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0025  * SUCH DAMAGE.
0026  */
0027 
0028 
0029 #include <bsp.h>
0030 #include <string.h>
0031 #include <signal.h>
0032 #include <rtems.h>
0033 #include <rtems/score/cpu.h>
0034 #include "gdb_if.h"
0035 
0036 /* Enable support for run-length encoding */
0037 #undef GDB_RLE_ENABLED
0038 /* Enable support for restart packets */
0039 #undef GDB_RESTART_ENABLED
0040 
0041 #define GDB_STUB_ENABLE_THREAD_SUPPORT
0042 
0043 /*
0044  * The following external functions provide character input and output.
0045  */
0046 extern char gdb_get_debug_char(void);
0047 extern void gdb_put_debug_char(char);
0048 extern void gdb_console_init(void);
0049 extern void gdb_ack_irq(void);
0050 extern void *_deba;
0051 
0052 /* Function prototypes */
0053 static void allow_nested_exception(void);
0054 static void disallow_nested_exception(void);
0055 static char *mem2hex(unsigned char *mem, char *buf, int count);
0056 static unsigned char *hex2mem(char *buf, unsigned char *mem, int count);
0057 static unsigned char *bin2mem(char *buf, unsigned char *mem, int count);
0058 static int compute_signal(int eid);
0059 static void flush_cache(void);
0060 static int hex2int(char **ptr, int *int_value);
0061 static char *getpacket(void);
0062 static void putpacket(char *buffer);
0063 
0064 unsigned int registers[NUM_REGS];
0065 
0066 /* BUFMAX defines the maximum number of characters in inbound/outbound buffers */
0067 #define BUFMAX 1500
0068 
0069 /* I/O packet buffers */
0070 static char remcomInBuffer[BUFMAX];
0071 static char remcomOutBuffer[BUFMAX];
0072 
0073 /*
0074  * Set by debugger to indicate that when handling memory faults (bus errors), the
0075  * handler should set the mem_err flag and skip over the faulting instruction
0076  */
0077 static volatile int may_fault;
0078 
0079 /*
0080  * Set by bus error exception handler, this indicates to caller of mem2hex,
0081  * hex2mem or bin2mem that there has been an error.
0082  */
0083 static volatile int mem_err;
0084 
0085 /* Indicates if we're single stepping */
0086 static unsigned char stepping;
0087 static char branch_step;
0088 
0089 /* Saved instructions */
0090 static unsigned int *seq_ptr;
0091 static unsigned int seq_insn;
0092 static unsigned int *branch_ptr;
0093 static unsigned int branch_insn;
0094 
0095 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
0096 static char do_threads;
0097 int current_thread_registers[NUM_REGS];
0098 #endif
0099 
0100 /* this mapping is used to copy the registers from a debug interrupt frame
0101  * see gdb_handle_break() */
0102 static unsigned char reg_map[] = {
0103   0, LM32_INT_REG_R1, LM32_INT_REG_R2, LM32_INT_REG_R3, LM32_INT_REG_R4,
0104   LM32_INT_REG_R5, LM32_INT_REG_R6, LM32_INT_REG_R7, LM32_INT_REG_R8,
0105   LM32_INT_REG_R9, LM32_INT_REG_R10, LM32_INT_REG_R11, LM32_INT_REG_R12,
0106   LM32_INT_REG_R13, LM32_INT_REG_R14, LM32_INT_REG_R15, LM32_INT_REG_R16,
0107   LM32_INT_REG_R17, LM32_INT_REG_R18, LM32_INT_REG_R19, LM32_INT_REG_R20,
0108   LM32_INT_REG_R21, LM32_INT_REG_R22, LM32_INT_REG_R23, LM32_INT_REG_R24,
0109   LM32_INT_REG_R25, LM32_INT_REG_GP, LM32_INT_REG_FP, LM32_INT_REG_SP,
0110   LM32_INT_REG_RA, LM32_INT_REG_EA, LM32_INT_REG_BA, LM32_INT_REG_PC,
0111   LM32_INT_REG_EID, LM32_INT_REG_EBA, LM32_INT_REG_DEBA, LM32_INT_REG_IE
0112 };
0113 
0114 /*
0115  * Conversion helper functions
0116  */
0117 
0118 /* For integer to ASCII conversion */
0119 #define highhex(x) gdb_hexchars [(x >> 4) & 0xf]
0120 #define lowhex(x) gdb_hexchars [x & 0xf]
0121 const char gdb_hexchars[]="0123456789abcdef";
0122 
0123 /* Convert ch from a hex digit to an int */
0124 static int hex(
0125   unsigned char ch
0126 )
0127 {
0128   if (ch >= 'a' && ch <= 'f')
0129     return ch-'a'+10;
0130   if (ch >= '0' && ch <= '9')
0131     return ch-'0';
0132   if (ch >= 'A' && ch <= 'F')
0133     return ch-'A'+10;
0134   return -1;
0135 }
0136 
0137 /*
0138  * Convert the memory pointed to by mem into hex, placing result in buf.
0139  * Return a pointer to the last char put in buf ('\0'), in case of mem fault,
0140  * return NULL.
0141  */
0142 static char *mem2hex(
0143   unsigned char *mem,
0144   char *buf, int count
0145 )
0146 {
0147   unsigned char ch;
0148 
0149   while (count-- > 0)
0150   {
0151     ch = *mem++;
0152     if (mem_err)
0153       return NULL;
0154     *buf++ = highhex(ch);
0155     *buf++ = lowhex(ch);
0156   }
0157 
0158   *buf = '\0';
0159   return buf;
0160 }
0161 
0162 /*
0163  * Convert the hex array pointed to by buf into binary to be placed in mem.
0164  * Return a pointer to the character AFTER the last byte written.
0165  */
0166 static unsigned char *hex2mem(
0167   char *buf,
0168   unsigned char *mem,
0169   int count
0170 )
0171 {
0172   int i;
0173   unsigned char ch;
0174 
0175   for (i = 0; i < count; i++)
0176   {
0177     /* Convert hex data to 8-bit value */
0178     ch = hex(*buf++) << 4;
0179     ch |= hex(*buf++);
0180     /* Attempt to write data to memory */
0181     *mem++ = ch;
0182     /* Return NULL if write caused an exception */
0183     if (mem_err)
0184       return NULL;
0185   }
0186   return mem;
0187 }
0188 
0189 /*
0190  * Copy the binary data pointed to by buf to mem and return a pointer to the
0191  * character AFTER the last byte written $, # and 0x7d are escaped with 0x7d.
0192  */
0193 static unsigned char *bin2mem(
0194   char *buf,
0195   unsigned char *mem,
0196   int count
0197 )
0198 {
0199   int i;
0200   unsigned char c;
0201 
0202   for (i = 0; i < count; i++)
0203   {
0204     /* Convert binary data to unsigned byte */
0205     c = *buf++;
0206     if (c == 0x7d)
0207       c = *buf++ ^ 0x20;
0208     /* Attempt to write value to memory */
0209     *mem++ = c;
0210     /* Return NULL if write caused an exception */
0211     if (mem_err)
0212       return NULL;
0213   }
0214 
0215   return mem;
0216 }
0217 
0218 /*
0219  * While we find nice hex chars, build an int.
0220  * Return number of chars processed.
0221  */
0222 static int hex2int(
0223   char **ptr,
0224   int *int_value
0225 )
0226 {
0227   int num_chars = 0;
0228   int hex_value;
0229 
0230   *int_value = 0;
0231 
0232   while(**ptr)
0233   {
0234     hex_value = hex(**ptr);
0235     if (hex_value < 0)
0236       break;
0237 
0238     *int_value = (*int_value << 4) | hex_value;
0239     num_chars ++;
0240 
0241     (*ptr)++;
0242   }
0243 
0244   return (num_chars);
0245 }
0246 
0247 /* Convert the exception identifier to a signal number. */
0248 static int compute_signal(
0249   int eid
0250 )
0251 {
0252   switch (eid)
0253   {
0254     case LM32_EXCEPTION_RESET:
0255       return 0;
0256     case LM32_EXCEPTION_INTERRUPT:
0257       return SIGINT;
0258     case LM32_EXCEPTION_DATA_BREAKPOINT:
0259     case LM32_EXCEPTION_INST_BREAKPOINT:
0260       return SIGTRAP;
0261     case LM32_EXCEPTION_INST_BUS_ERROR:
0262     case LM32_EXCEPTION_DATA_BUS_ERROR:
0263       return SIGSEGV;
0264     case LM32_EXCEPTION_DIVIDE_BY_ZERO:
0265       return SIGFPE;
0266   }
0267 
0268   return SIGHUP;  /* default for things we don't know about */
0269 }
0270 
0271 /* Scan for the sequence $<data>#<checksum> */
0272 static char *getpacket(void)
0273 {
0274   char *buffer = &remcomInBuffer[0];
0275   unsigned char checksum;
0276   unsigned char xmitcsum;
0277   int count;
0278   char ch;
0279 
0280   while (1)
0281   {
0282     /* wait around for the start character, ignore all other characters */
0283     while ((ch = gdb_get_debug_char()) != '$');
0284 
0285 retry:
0286     checksum = 0;
0287     xmitcsum = -1;
0288     count = 0;
0289 
0290     /* now, read until a # or end of buffer is found */
0291     while (count < BUFMAX)
0292     {
0293       ch = gdb_get_debug_char();
0294       if (ch == '$')
0295         goto retry;
0296       if (ch == '#')
0297         break;
0298       checksum = checksum + ch;
0299       buffer[count] = ch;
0300       count = count + 1;
0301     }
0302     buffer[count] = 0;
0303 
0304     if (ch == '#')
0305     {
0306       ch = gdb_get_debug_char();
0307       xmitcsum = hex(ch) << 4;
0308       ch = gdb_get_debug_char();
0309       xmitcsum += hex(ch);
0310 
0311       if (checksum != xmitcsum)
0312       {
0313         /* failed checksum */
0314         gdb_put_debug_char('-');
0315       }
0316       else
0317       {
0318         /* successful transfer */
0319         gdb_put_debug_char('+');
0320 
0321         /* if a sequence char is present, reply the sequence ID */
0322         if (buffer[2] == ':')
0323         {
0324           gdb_put_debug_char(buffer[0]);
0325           gdb_put_debug_char(buffer[1]);
0326 
0327           return &buffer[3];
0328         }
0329 
0330         return &buffer[0];
0331       }
0332     }
0333   }
0334 }
0335 
0336 /* Send the packet in buffer.  */
0337 static void putpacket(
0338   char *buffer
0339 )
0340 {
0341   unsigned char checksum;
0342   int count;
0343   unsigned char ch;
0344 
0345 #ifdef GDB_RLE_ENABLED
0346   int run_length;
0347   int run_idx;
0348   char run_length_char;
0349 #endif
0350 
0351   /*  $<packet info>#<checksum>. */
0352   do {
0353     gdb_put_debug_char('$');
0354     checksum = 0;
0355     count = 0;
0356 
0357 #ifdef GDB_RLE_ENABLED
0358     while (ch = buffer[count])
0359     {
0360       /* Transmit character */
0361       gdb_put_debug_char(ch);
0362       checksum += ch;
0363       count += 1;
0364 
0365       /*
0366        * Determine how many consecutive characters there are that are the same
0367        * as the character we just transmitted
0368        */
0369       run_length = 0;
0370       run_idx = count;
0371       while ((buffer[run_idx++] == ch) && (run_length < 97))
0372         run_length++;
0373       /* Encode run length as an ASCII character */
0374       run_length_char = (char)(run_length + 29);
0375       if (   (run_length >= 3)
0376           && (run_length_char != '$')
0377           && (run_length_char != '#')
0378           && (run_length_char != '+')
0379           && (run_length_char != '-')
0380          )
0381       {
0382         /* Transmit run-length */
0383         gdb_put_debug_char('*');
0384         checksum += '*';
0385         gdb_put_debug_char(run_length_char);
0386         checksum += run_length_char;
0387         count += run_length;
0388       }
0389     }
0390 #else
0391     while ((ch = buffer[count]))
0392     {
0393       gdb_put_debug_char(ch);
0394       checksum += ch;
0395       count += 1;
0396     }
0397 #endif
0398 
0399     gdb_put_debug_char('#');
0400     gdb_put_debug_char(highhex(checksum));
0401     gdb_put_debug_char(lowhex(checksum));
0402   } while (gdb_get_debug_char() != '+');
0403 }
0404 
0405 static void allow_nested_exception(void)
0406 {
0407   mem_err = 0;
0408   may_fault = 1;
0409 }
0410 
0411 static void disallow_nested_exception(void)
0412 {
0413   mem_err = 0;
0414   may_fault = 0;
0415 }
0416 
0417 /* Flush the instruction cache */
0418 static void flush_cache(void)
0419 {
0420   /*
0421    * Executing this does no harm on CPUs without a cache. We flush data cache as
0422    * well as instruction cache in case the debugger has accessed memory
0423    * directly.
0424    */
0425   __asm__ __volatile__ ("wcsr ICC, r0\n"
0426                         "nop\n"
0427                         "nop\n"
0428                         "nop\n"
0429                         "wcsr DCC, r0\n"
0430                         "nop\n"
0431                         "nop\n"
0432                         "nop"
0433                        );
0434 }
0435 
0436 /* Set a h/w breakpoint at the given address */
0437 static int set_hw_breakpoint(
0438   int address,
0439   int length
0440 )
0441 {
0442   int bp;
0443 
0444   /* Find a free break point register and then set it */
0445   __asm__ ("rcsr  %0, BP0" : "=r" (bp));
0446   if ((bp & 0x01) == 0)
0447   {
0448     __asm__ ("wcsr  BP0, %0" : : "r" (address | 1));
0449     return 1;
0450   }
0451   __asm__ ("rcsr  %0, BP1" : "=r" (bp));
0452   if ((bp & 0x01) == 0)
0453   {
0454     __asm__ ("wcsr  BP1, %0" : : "r" (address | 1));
0455     return 1;
0456   }
0457   __asm__ ("rcsr  %0, BP2" : "=r" (bp));
0458   if ((bp & 0x01) == 0)
0459   {
0460     __asm__ ("wcsr  BP2, %0" : : "r" (address | 1));
0461     return 1;
0462   }
0463   __asm__ ("rcsr  %0, BP3" : "=r" (bp));
0464   if ((bp & 0x01) == 0)
0465   {
0466     __asm__ ("wcsr  BP3, %0" : : "r" (address | 1));
0467     return 1;
0468   }
0469 
0470   /* No free breakpoint registers */
0471   return -1;
0472 }
0473 
0474 /* Remove a h/w breakpoint which should be set at the given address */
0475 static int disable_hw_breakpoint(
0476   int address,
0477   int length
0478 )
0479 {
0480   int bp;
0481 
0482   /* Try to find matching breakpoint register */
0483   __asm__ ("rcsr  %0, BP0" : "=r" (bp));
0484   if ((bp & 0xfffffffc) == (address & 0xfffffffc))
0485   {
0486     __asm__ ("wcsr  BP0, %0" : : "r" (0));
0487     return 1;
0488   }
0489   __asm__ ("rcsr  %0, BP1" : "=r" (bp));
0490   if ((bp & 0xfffffffc) == (address & 0xfffffffc))
0491   {
0492     __asm__ ("wcsr  BP1, %0" : : "r" (0));
0493     return 1;
0494   }
0495   __asm__ ("rcsr  %0, BP2" : "=r" (bp));
0496   if ((bp & 0xfffffffc) == (address & 0xfffffffc))
0497   {
0498     __asm__ ("wcsr  BP2, %0" : : "r" (0));
0499     return 1;
0500   }
0501   __asm__ ("rcsr  %0, BP3" : "=r" (bp));
0502   if ((bp & 0xfffffffc) == (address & 0xfffffffc))
0503   {
0504     __asm__ ("wcsr  BP3, %0" : : "r" (0));
0505     return 1;
0506   }
0507 
0508   /* Breakpoint not found */
0509   return -1;
0510 }
0511 
0512 /*
0513  *  This support function prepares and sends the message containing the
0514  *  basic information about this exception.
0515  */
0516 static void gdb_stub_report_exception_info(
0517   int thread
0518 )
0519 {
0520   char *ptr;
0521   int sigval;
0522 
0523   /* Convert exception ID to a signal number */
0524   sigval = compute_signal(registers[LM32_REG_EID]);
0525 
0526   /* Set pointer to start of output buffer */
0527   ptr = remcomOutBuffer;
0528 
0529   *ptr++ = 'T';
0530   *ptr++ = highhex(sigval);
0531   *ptr++ = lowhex(sigval);
0532 
0533   *ptr++ = highhex(LM32_REG_PC);
0534   *ptr++ = lowhex(LM32_REG_PC);
0535   *ptr++ = ':';
0536   ptr    = mem2hex((unsigned char *)&(registers[LM32_REG_PC]), ptr, 4);
0537   *ptr++ = ';';
0538 
0539   *ptr++ = highhex(LM32_REG_SP);
0540   *ptr++ = lowhex(LM32_REG_SP);
0541   *ptr++ = ':';
0542   ptr    = mem2hex((unsigned char *)&(registers[LM32_REG_SP]), ptr, 4);
0543   *ptr++ = ';';
0544 
0545 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
0546   if (do_threads)
0547   {
0548     *ptr++ = 't';
0549     *ptr++ = 'h';
0550     *ptr++ = 'r';
0551     *ptr++ = 'e';
0552     *ptr++ = 'a';
0553     *ptr++ = 'd';
0554     *ptr++ = ':';
0555     ptr   = thread2vhstr(ptr, thread);
0556     *ptr++ = ';';
0557   }
0558 #endif
0559 
0560   *ptr++ = '\0';
0561 }
0562 
0563 /*
0564  * This function does all command procesing for interfacing to gdb. The error
0565  * codes we return are errno numbers.
0566  */
0567 void handle_exception(void)
0568 {
0569   int addr;
0570   int length;
0571   char *ptr;
0572   int err;
0573   int reg;
0574   unsigned insn;
0575   unsigned opcode;
0576   unsigned branch_target = 0;
0577   int current_thread;
0578   int thread;
0579   void *regptr;
0580   int host_has_detached = 0;
0581   int binary;
0582 
0583   thread = 0;
0584 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
0585   if (do_threads)
0586     thread = rtems_gdb_stub_get_current_thread();
0587 #endif
0588   current_thread = thread;
0589 
0590   /*
0591    * Check for bus error caused by this code (rather than the program being
0592    * debugged)
0593    */
0594   if (may_fault && (registers[LM32_REG_EID] == LM32_EXCEPTION_DATA_BUS_ERROR))
0595   {
0596     /* Indicate that a fault occured */
0597     mem_err = 1;
0598     /* Skip over faulting instruction */
0599     registers[LM32_REG_PC] += 4;
0600     /* Resume execution */
0601     return;
0602   }
0603 
0604   if (stepping)
0605   {
0606     /* Remove breakpoints */
0607     *seq_ptr = seq_insn;
0608     if (branch_step)
0609       *branch_ptr = branch_insn;
0610     stepping = 0;
0611   }
0612 
0613   /* Reply to host that an exception has occured with some basic info */
0614   gdb_stub_report_exception_info(thread);
0615   putpacket(remcomOutBuffer);
0616 
0617   while (!host_has_detached)
0618   {
0619     remcomOutBuffer[0] = '\0';
0620     ptr = getpacket();
0621     binary = 0;
0622 
0623     switch (*ptr++)
0624     {
0625       /* Return last signal */
0626       case '?':
0627         gdb_stub_report_exception_info(thread);
0628         break;
0629 
0630       /* Detach - exit from debugger */
0631       case 'D':
0632         strcpy(remcomOutBuffer, "OK");
0633         host_has_detached = 1;
0634         break;
0635 
0636       /* Return the value of the CPU registers */
0637       case 'g':
0638         regptr = registers;
0639 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
0640         if (do_threads && current_thread != thread )
0641           regptr = &current_thread_registers;
0642 #endif
0643         ptr = mem2hex((unsigned char*)regptr, remcomOutBuffer, NUM_REGS * 4);
0644         break;
0645 
0646       /* Set the value of the CPU registers */
0647       case 'G':
0648         regptr = registers;
0649 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
0650         if (do_threads && current_thread != thread )
0651           regptr = &current_thread_registers;
0652 #endif
0653         hex2mem(ptr, (unsigned char*)regptr, NUM_REGS * 4);
0654         strcpy(remcomOutBuffer, "OK");
0655         break;
0656 
0657       /* Return the value of the specified register */
0658       case 'p':
0659         if (hex2int(&ptr, &reg))
0660         {
0661           ptr = remcomOutBuffer;
0662           ptr = mem2hex((unsigned char *)&registers[reg], ptr, 4);
0663         } else
0664           strcpy(remcomOutBuffer, "E22");
0665         break;
0666 
0667       /* Set the specified register to the given value */
0668       case 'P':
0669         if (hex2int(&ptr, &reg)
0670             && *ptr++ == '=')
0671         {
0672           hex2mem(ptr, (unsigned char *)&registers[reg], 4);
0673           strcpy(remcomOutBuffer, "OK");
0674         }
0675         else
0676           strcpy(remcomOutBuffer, "E22");
0677         break;
0678 
0679       /* Read memory */
0680       case 'm':
0681         /* Try to read %x,%x.  */
0682         if (hex2int(&ptr, &addr)
0683             && *ptr++ == ','
0684             && hex2int(&ptr, &length)
0685             && length < (sizeof(remcomOutBuffer)/2))
0686         {
0687           allow_nested_exception();
0688           if (NULL == mem2hex((unsigned char *)addr, remcomOutBuffer, length))
0689             strcpy(remcomOutBuffer, "E14");
0690           disallow_nested_exception();
0691         }
0692         else
0693           strcpy(remcomOutBuffer,"E22");
0694         break;
0695 
0696       /* Write memory */
0697       case 'X':
0698         binary = 1;
0699       case 'M':
0700         /* Try to read '%x,%x:'.  */
0701         if (hex2int(&ptr, &addr)
0702             && *ptr++ == ','
0703             && hex2int(&ptr, &length)
0704             && *ptr++ == ':')
0705         {
0706           allow_nested_exception();
0707           if (binary)
0708             err = (int)bin2mem(ptr, (unsigned char *)addr, length);
0709           else
0710             err = (int)hex2mem(ptr, (unsigned char *)addr, length);
0711           if (err)
0712             strcpy(remcomOutBuffer, "OK");
0713           else
0714             strcpy(remcomOutBuffer, "E14");
0715           disallow_nested_exception();
0716         }
0717         else
0718           strcpy(remcomOutBuffer, "E22");
0719         break;
0720 
0721       /* Continue */
0722       case 'c':
0723         /* try to read optional parameter, pc unchanged if no parm */
0724         if (hex2int(&ptr, &addr))
0725           registers[LM32_REG_PC] = addr;
0726         flush_cache();
0727         return;
0728 
0729       /* Step */
0730       case 's':
0731         /* try to read optional parameter, pc unchanged if no parm */
0732         if (hex2int(&ptr, &addr))
0733           registers[LM32_REG_PC] = addr;
0734         stepping = 1;
0735         /* Is instruction a branch? */
0736         insn = *(unsigned int*)registers[LM32_REG_PC];
0737         opcode = insn & 0xfc000000;
0738         if (   (opcode == 0xe0000000)
0739             || (opcode == 0xf8000000)
0740            )
0741         {
0742           branch_step = 1;
0743           branch_target = registers[LM32_REG_PC]
0744               + (((signed)insn << 6) >> 4);
0745         }
0746         else if (   (opcode == 0x44000000)
0747                  || (opcode == 0x48000000)
0748                  || (opcode == 0x4c000000)
0749                  || (opcode == 0x50000000)
0750                  || (opcode == 0x54000000)
0751                  || (opcode == 0x5c000000)
0752                 )
0753         {
0754           branch_step = 1;
0755           branch_target = registers[LM32_REG_PC] +
0756               + (((signed)insn << 16) >> 14);
0757         }
0758         else if (   (opcode == 0xd8000000)
0759                  || (opcode == 0xc0000000)
0760                 )
0761         {
0762           branch_step = 1;
0763           branch_target = registers[(insn >> 21) & 0x1f];
0764         }
0765         else
0766           branch_step = 0;
0767 
0768         /* Set breakpoint after instruction we're stepping */
0769         seq_ptr = (unsigned int *)registers[LM32_REG_PC];
0770         seq_ptr++;
0771         seq_insn = *seq_ptr;
0772         *seq_ptr = LM32_BREAK;
0773 
0774         /* Make sure one insn doesn't get replaced twice */
0775         if (seq_ptr == (unsigned int*)branch_target)
0776           branch_step = 0;
0777 
0778         if (branch_step)
0779         {
0780           /* Set breakpoint on branch target */
0781           branch_ptr = (unsigned int*)branch_target;
0782           branch_insn = *branch_ptr;
0783           *branch_ptr = LM32_BREAK;
0784         }
0785         flush_cache();
0786         return;
0787 
0788       case 'Z':
0789         switch (*ptr++)
0790         {
0791           /* Insert h/w breakpoint */
0792           case '1':
0793             if (*ptr++ == ','
0794                 && hex2int(&ptr, &addr)
0795                 && *ptr++ == ','
0796                 && hex2int(&ptr, &length))
0797             {
0798               err = set_hw_breakpoint(addr, length);
0799               if (err > 0)
0800                 strcpy(remcomOutBuffer, "OK");
0801               else if (err < 0)
0802                 strcpy(remcomOutBuffer, "E28");
0803             }
0804             else
0805               strcpy(remcomOutBuffer, "E22");
0806             break;
0807         }
0808         break;
0809 
0810       case 'z':
0811         switch (*ptr++)
0812         {
0813           /* Remove h/w breakpoint */
0814           case '1':
0815             if (*ptr++ == ','
0816                 && hex2int(&ptr, &addr)
0817                 && *ptr++ == ','
0818                 && hex2int(&ptr, &length))
0819             {
0820               err = disable_hw_breakpoint(addr, length);
0821               if (err > 0)
0822                 strcpy(remcomOutBuffer, "OK");
0823               else if (err < 0)
0824                 strcpy(remcomOutBuffer, "E28");
0825             }
0826             else
0827               strcpy(remcomOutBuffer, "E22");
0828             break;
0829         }
0830         break;
0831 
0832       /* Query */
0833       case 'q':
0834 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
0835         rtems_gdb_process_query(
0836             remcomInBuffer,
0837             remcomOutBuffer,
0838             do_threads,
0839             thread );
0840 #endif
0841         break;
0842 
0843 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
0844       /* Thread alive */
0845       case 'T':
0846       {
0847         int testThread;
0848 
0849         if (vhstr2thread(&remcomInBuffer[1], &testThread) == NULL)
0850         {
0851           strcpy(remcomOutBuffer, "E01");
0852           break;
0853         }
0854 
0855         if (rtems_gdb_index_to_stub_id(testThread) == NULL)
0856           strcpy(remcomOutBuffer, "E02");
0857         else
0858           strcpy(remcomOutBuffer, "OK");
0859       }
0860       break;
0861 #endif
0862 
0863       /* Set thread */
0864       case 'H':
0865 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
0866         if (remcomInBuffer[1] != 'g')
0867           break;
0868 
0869         if (!do_threads)
0870           break;
0871 
0872         {
0873           int tmp, ret;
0874 
0875           /* Set new generic thread */
0876           if (vhstr2thread(&remcomInBuffer[2], &tmp) == NULL)
0877           {
0878             strcpy(remcomOutBuffer, "E01");
0879             break;
0880           }
0881 
0882           /* 0 means `thread' */
0883           if (tmp == 0)
0884             tmp = thread;
0885 
0886           if (tmp == current_thread)
0887           {
0888             /* No changes */
0889             strcpy(remcomOutBuffer, "OK");
0890             break;
0891           }
0892 
0893           /* Save current thread registers if necessary */
0894           if (current_thread != thread)
0895           {
0896             ret = rtems_gdb_stub_set_thread_regs(
0897                 current_thread, (unsigned int *) &current_thread_registers);
0898           }
0899 
0900           /* Read new registers if necessary */
0901           if (tmp != thread)
0902           {
0903             ret = rtems_gdb_stub_get_thread_regs(
0904                 tmp, (unsigned int *) &current_thread_registers);
0905 
0906             if (!ret)
0907             {
0908               /* Thread does not exist */
0909               strcpy(remcomOutBuffer, "E02");
0910               break;
0911             }
0912           }
0913 
0914           current_thread = tmp;
0915           strcpy(remcomOutBuffer, "OK");
0916         }
0917 #endif
0918       break;
0919 
0920 #ifdef GDB_RESTART_ENABLED
0921       /* Reset */
0922       case 'r':
0923       case 'R':
0924         /* We reset by branching to the reset exception handler. */
0925         registers[LM32_REG_PC] = 0;
0926         return;
0927 #endif
0928       }
0929 
0930     /* reply to the request */
0931     putpacket(remcomOutBuffer);
0932   }
0933 }
0934 
0935 void gdb_handle_break(rtems_vector_number vector, CPU_Interrupt_frame *frame)
0936 {
0937   int i;
0938   unsigned int *int_regs = (unsigned int*)frame;
0939 
0940   /* copy extended frame to registers */
0941   registers[LM32_REG_R0]   = 0;
0942   for (i = 1; i < NUM_REGS; i++)
0943   {
0944     registers[i] = int_regs[reg_map[i]];
0945   }
0946 
0947   /* now call the real handler */
0948   handle_exception();
0949   gdb_ack_irq();
0950 
0951   /* copy registers back to extended frame */
0952   for (i = 1; i < NUM_REGS; i++)
0953   {
0954     int_regs[reg_map[i]] = registers[i];
0955   }
0956 }
0957 
0958 void lm32_gdb_stub_install(int enable_threads)
0959 {
0960   unsigned int dc;
0961 
0962   /* set DEBA and remap all exception */
0963   __asm__("wcsr DEBA, %0" : : "r" (&_deba));
0964   __asm__("rcsr %0, DC" : "=r" (dc));
0965   dc |= 0x2;
0966   __asm__("wcsr DC, %0" : : "r" (dc));
0967 
0968 #if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
0969   if( enable_threads )
0970     do_threads = 1;
0971   else
0972     do_threads = 0;
0973 #endif
0974 
0975   gdb_console_init();
0976 }
0977