source: rtems/c/src/lib/libbsp/lm32/shared/gdbstub/lm32-stub.c @ dce1032b

4.115
Last change on this file since dce1032b was dce1032b, checked in by Joel Sherrill <joel.sherrill@…>, on 08/01/11 at 13:48:40

2011-08-01 Sebastien Bourdeauducq <sebastien.bourdeauducq@…>

PR 1869/bsps

  • startup/bspclean.c: New file.
  • include/tm27.h: Removed.
  • ChangeLog?, Makefile.am, README, preinstall.am, include/bsp.h, include/system_conf.h, make/custom/milkymist.cfg, startup/linkcmds: Complete BSP for Milkymist One supporting Milkymist SOC 1.0.x. Includes new or updated drivers for:
    • Multi-standard video input (PAL/SECAM/NTSC)
    • Two DMX512 (RS485) ports
    • MIDI IN and MIDI OUT ports
    • VGA output
    • AC'97 audio
    • NOR flash
    • 10/100 Ethernet
    • Memory card (experimental and incomplete)
    • USB host connectors (input devices only)
    • RC5 infrared receiver
    • RS232 debug port
  • Property mode set to 100644
File size: 23.6 KB
Line 
1/*
2 * Low-level support for LM32 remote debuging with GDB.
3 * Contributed by Jon Beniston <jon@beniston.com>
4 * Modified for RTEMS with thread support by Michael Walle <michael@walle.cc>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28/* $Id$ */
29
30#include <bsp.h>
31#include <string.h>
32#include <signal.h>
33#include <rtems.h>
34#include <rtems/score/cpu.h>
35#include "gdb_if.h"
36
37/* Enable support for run-length encoding */
38#undef GDB_RLE_ENABLED
39/* Enable support for restart packets */
40#undef GDB_RESTART_ENABLED
41
42#define GDB_STUB_ENABLE_THREAD_SUPPORT
43
44/*
45 * The following external functions provide character input and output.
46 */
47extern char gdb_get_debug_char(void);
48extern void gdb_put_debug_char(char);
49extern void gdb_console_init(void);
50extern void gdb_ack_irq(void);
51extern void *_deba;
52
53/* Function prototypes */
54static void allow_nested_exception(void);
55static void disallow_nested_exception(void);
56static char *mem2hex(unsigned char *mem, char *buf, int count);
57static unsigned char *hex2mem(char *buf, unsigned char *mem, int count);
58static unsigned char *bin2mem(char *buf, unsigned char *mem, int count);
59static int compute_signal(int eid);
60static void flush_cache(void);
61static int hex2int(char **ptr, int *int_value);
62static char *getpacket(void);
63static void putpacket(char *buffer);
64
65unsigned int registers[NUM_REGS];
66
67/* BUFMAX defines the maximum number of characters in inbound/outbound buffers */
68#define BUFMAX 1500
69
70/* I/O packet buffers */
71static char remcomInBuffer[BUFMAX];
72static char remcomOutBuffer[BUFMAX];
73
74/*
75 * Set by debugger to indicate that when handling memory faults (bus errors), the
76 * handler should set the mem_err flag and skip over the faulting instruction
77 */
78static volatile int may_fault;
79
80/*
81 * Set by bus error exception handler, this indicates to caller of mem2hex,
82 * hex2mem or bin2mem that there has been an error.
83 */
84static volatile int mem_err;
85
86/* Indicates if we're single stepping */
87static unsigned char stepping;
88static char branch_step;
89
90/* Saved instructions */
91static unsigned int *seq_ptr;
92static unsigned int seq_insn;
93static unsigned int *branch_ptr;
94static unsigned int branch_insn;
95
96#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
97static char do_threads;
98int current_thread_registers[NUM_REGS];
99#endif
100
101/* this mapping is used to copy the registers from a debug interrupt frame
102 * see gdb_handle_break() */
103static unsigned char reg_map[] = {
104  0, LM32_INT_REG_R1, LM32_INT_REG_R2, LM32_INT_REG_R3, LM32_INT_REG_R4,
105  LM32_INT_REG_R5, LM32_INT_REG_R6, LM32_INT_REG_R7, LM32_INT_REG_R8,
106  LM32_INT_REG_R9, LM32_INT_REG_R10, LM32_INT_REG_R11, LM32_INT_REG_R12,
107  LM32_INT_REG_R13, LM32_INT_REG_R14, LM32_INT_REG_R15, LM32_INT_REG_R16,
108  LM32_INT_REG_R17, LM32_INT_REG_R18, LM32_INT_REG_R19, LM32_INT_REG_R20,
109  LM32_INT_REG_R21, LM32_INT_REG_R22, LM32_INT_REG_R23, LM32_INT_REG_R24,
110  LM32_INT_REG_R25, LM32_INT_REG_GP, LM32_INT_REG_FP, LM32_INT_REG_SP,
111  LM32_INT_REG_RA, LM32_INT_REG_EA, LM32_INT_REG_BA, LM32_INT_REG_PC,
112  LM32_INT_REG_EID, LM32_INT_REG_EBA, LM32_INT_REG_DEBA, LM32_INT_REG_IE
113};
114
115/*
116 * Conversion helper functions
117 */
118
119/* For integer to ASCII conversion */
120#define highhex(x) gdb_hexchars [(x >> 4) & 0xf]
121#define lowhex(x) gdb_hexchars [x & 0xf]
122const char gdb_hexchars[]="0123456789abcdef";
123
124/* Convert ch from a hex digit to an int */
125static int hex(
126  unsigned char ch
127)
128{
129  if (ch >= 'a' && ch <= 'f')
130    return ch-'a'+10;
131  if (ch >= '0' && ch <= '9')
132    return ch-'0';
133  if (ch >= 'A' && ch <= 'F')
134    return ch-'A'+10;
135  return -1;
136}
137
138/*
139 * Convert the memory pointed to by mem into hex, placing result in buf.
140 * Return a pointer to the last char put in buf ('\0'), in case of mem fault,
141 * return NULL.
142 */
143static char *mem2hex(
144  unsigned char *mem,
145  char *buf, int count
146)
147{
148  unsigned char ch;
149
150  while (count-- > 0)
151  {
152    ch = *mem++;
153    if (mem_err)
154      return NULL;
155    *buf++ = highhex(ch);
156    *buf++ = lowhex(ch);
157  }
158
159  *buf = '\0';
160  return buf;
161}
162
163/*
164 * Convert the hex array pointed to by buf into binary to be placed in mem.
165 * Return a pointer to the character AFTER the last byte written.
166 */
167static unsigned char *hex2mem(
168  char *buf,
169  unsigned char *mem,
170  int count
171)
172{
173  int i;
174  unsigned char ch;
175
176  for (i = 0; i < count; i++)
177  {
178    /* Convert hex data to 8-bit value */
179    ch = hex(*buf++) << 4;
180    ch |= hex(*buf++);
181    /* Attempt to write data to memory */
182    *mem++ = ch;
183    /* Return NULL if write caused an exception */
184    if (mem_err)
185      return NULL;
186  }
187  return mem;
188}
189
190/*
191 * Copy the binary data pointed to by buf to mem and return a pointer to the
192 * character AFTER the last byte written $, # and 0x7d are escaped with 0x7d.
193 */
194static unsigned char *bin2mem(
195  char *buf,
196  unsigned char *mem,
197  int count
198)
199{
200  int i;
201  unsigned char c;
202
203  for (i = 0; i < count; i++)
204  {
205    /* Convert binary data to unsigned byte */
206    c = *buf++;
207    if (c == 0x7d)
208      c = *buf++ ^ 0x20;
209    /* Attempt to write value to memory */
210    *mem++ = c;
211    /* Return NULL if write caused an exception */
212    if (mem_err)
213      return NULL;
214  }
215
216  return mem;
217}
218
219/*
220 * While we find nice hex chars, build an int.
221 * Return number of chars processed.
222 */
223static int hex2int(
224  char **ptr,
225  int *int_value
226)
227{
228  int num_chars = 0;
229  int hex_value;
230
231  *int_value = 0;
232
233  while(**ptr)
234  {
235    hex_value = hex(**ptr);
236    if (hex_value < 0)
237      break;
238
239    *int_value = (*int_value << 4) | hex_value;
240    num_chars ++;
241
242    (*ptr)++;
243  }
244
245  return (num_chars);
246}
247
248/* Convert the exception identifier to a signal number. */
249static int compute_signal(
250  int eid
251)
252{
253  switch (eid)
254  {
255    case LM32_EXCEPTION_RESET:
256      return 0;
257    case LM32_EXCEPTION_INTERRUPT:
258      return SIGINT;
259    case LM32_EXCEPTION_DATA_BREAKPOINT:
260    case LM32_EXCEPTION_INST_BREAKPOINT:
261      return SIGTRAP;
262    case LM32_EXCEPTION_INST_BUS_ERROR:
263    case LM32_EXCEPTION_DATA_BUS_ERROR:
264      return SIGSEGV;
265    case LM32_EXCEPTION_DIVIDE_BY_ZERO:
266      return SIGFPE;
267  }
268
269  return SIGHUP;  /* default for things we don't know about */
270}
271
272/* Scan for the sequence $<data>#<checksum> */
273static char *getpacket(void)
274{
275  char *buffer = &remcomInBuffer[0];
276  unsigned char checksum;
277  unsigned char xmitcsum;
278  int count;
279  char ch;
280
281  while (1)
282  {
283    /* wait around for the start character, ignore all other characters */
284    while ((ch = gdb_get_debug_char()) != '$');
285
286retry:
287    checksum = 0;
288    xmitcsum = -1;
289    count = 0;
290
291    /* now, read until a # or end of buffer is found */
292    while (count < BUFMAX)
293    {
294      ch = gdb_get_debug_char();
295      if (ch == '$')
296        goto retry;
297      if (ch == '#')
298        break;
299      checksum = checksum + ch;
300      buffer[count] = ch;
301      count = count + 1;
302    }
303    buffer[count] = 0;
304
305    if (ch == '#')
306    {
307      ch = gdb_get_debug_char();
308      xmitcsum = hex(ch) << 4;
309      ch = gdb_get_debug_char();
310      xmitcsum += hex(ch);
311
312      if (checksum != xmitcsum)
313      {
314            /* failed checksum */
315        gdb_put_debug_char('-');
316      }
317      else
318      {
319            /* successful transfer */
320        gdb_put_debug_char('+');
321
322        /* if a sequence char is present, reply the sequence ID */
323        if (buffer[2] == ':')
324        {
325          gdb_put_debug_char(buffer[0]);
326          gdb_put_debug_char(buffer[1]);
327
328          return &buffer[3];
329        }
330
331        return &buffer[0];
332      }
333    }
334  }
335}
336
337/* Send the packet in buffer.  */
338static void putpacket(
339  char *buffer
340)
341{
342  unsigned char checksum;
343  int count;
344  unsigned char ch;
345
346#ifdef GDB_RLE_ENABLED
347  int run_length;
348  int run_idx;
349  char run_length_char;
350#endif
351
352  /*  $<packet info>#<checksum>. */
353  do {
354    gdb_put_debug_char('$');
355    checksum = 0;
356    count = 0;
357
358#ifdef GDB_RLE_ENABLED
359    while (ch = buffer[count])
360    {
361      /* Transmit character */
362      gdb_put_debug_char(ch);
363      checksum += ch;
364      count += 1;
365
366      /*
367       * Determine how many consecutive characters there are that are the same
368       * as the character we just transmitted
369       */
370      run_length = 0;
371      run_idx = count;
372      while ((buffer[run_idx++] == ch) && (run_length < 97))
373        run_length++;
374      /* Encode run length as an ASCII character */
375      run_length_char = (char)(run_length + 29);
376      if (   (run_length >= 3)
377          && (run_length_char != '$')
378          && (run_length_char != '#')
379          && (run_length_char != '+')
380          && (run_length_char != '-')
381         )
382      {
383        /* Transmit run-length */
384        gdb_put_debug_char('*');
385        checksum += '*';
386        gdb_put_debug_char(run_length_char);
387        checksum += run_length_char;
388        count += run_length;
389      }
390    }
391#else
392    while ((ch = buffer[count]))
393    {
394      gdb_put_debug_char(ch);
395      checksum += ch;
396      count += 1;
397    }
398#endif
399
400    gdb_put_debug_char('#');
401    gdb_put_debug_char(highhex(checksum));
402    gdb_put_debug_char(lowhex(checksum));
403  } while (gdb_get_debug_char() != '+');
404}
405
406static void allow_nested_exception(void)
407{
408  mem_err = 0;
409  may_fault = 1;
410}
411
412static void disallow_nested_exception(void)
413{
414  mem_err = 0;
415  may_fault = 0;
416}
417
418/* Flush the instruction cache */
419static void flush_cache(void)
420{
421  /*
422   * Executing this does no harm on CPUs without a cache. We flush data cache as
423   * well as instruction cache in case the debugger has accessed memory
424   * directly.
425   */
426  __asm__ __volatile__ ("wcsr ICC, r0\n"
427                        "nop\n"
428                        "nop\n"
429                        "nop\n"
430                        "wcsr DCC, r0\n"
431                        "nop\n"
432                        "nop\n"
433                        "nop"
434                       );
435}
436
437/* Set a h/w breakpoint at the given address */
438static int set_hw_breakpoint(
439  int address,
440  int length
441)
442{
443  int bp;
444
445  /* Find a free break point register and then set it */
446  __asm__ ("rcsr  %0, BP0" : "=r" (bp));
447  if ((bp & 0x01) == 0)
448  {
449    __asm__ ("wcsr  BP0, %0" : : "r" (address | 1));
450    return 1;
451  }
452  __asm__ ("rcsr  %0, BP1" : "=r" (bp));
453  if ((bp & 0x01) == 0)
454  {
455    __asm__ ("wcsr  BP1, %0" : : "r" (address | 1));
456    return 1;
457  }
458  __asm__ ("rcsr  %0, BP2" : "=r" (bp));
459  if ((bp & 0x01) == 0)
460  {
461    __asm__ ("wcsr  BP2, %0" : : "r" (address | 1));
462    return 1;
463  }
464  __asm__ ("rcsr  %0, BP3" : "=r" (bp));
465  if ((bp & 0x01) == 0)
466  {
467    __asm__ ("wcsr  BP3, %0" : : "r" (address | 1));
468    return 1;
469  }
470
471  /* No free breakpoint registers */
472  return -1;
473}
474
475/* Remove a h/w breakpoint which should be set at the given address */
476static int disable_hw_breakpoint(
477  int address,
478  int length
479)
480{
481  int bp;
482
483  /* Try to find matching breakpoint register */
484  __asm__ ("rcsr  %0, BP0" : "=r" (bp));
485  if ((bp & 0xfffffffc) == (address & 0xfffffffc))
486  {
487    __asm__ ("wcsr  BP0, %0" : : "r" (0));
488    return 1;
489  }
490  __asm__ ("rcsr  %0, BP1" : "=r" (bp));
491  if ((bp & 0xfffffffc) == (address & 0xfffffffc))
492  {
493    __asm__ ("wcsr  BP1, %0" : : "r" (0));
494    return 1;
495  }
496  __asm__ ("rcsr  %0, BP2" : "=r" (bp));
497  if ((bp & 0xfffffffc) == (address & 0xfffffffc))
498  {
499    __asm__ ("wcsr  BP2, %0" : : "r" (0));
500    return 1;
501  }
502  __asm__ ("rcsr  %0, BP3" : "=r" (bp));
503  if ((bp & 0xfffffffc) == (address & 0xfffffffc))
504  {
505    __asm__ ("wcsr  BP3, %0" : : "r" (0));
506    return 1;
507  }
508
509  /* Breakpoint not found */
510  return -1;
511}
512
513/*
514 *  This support function prepares and sends the message containing the
515 *  basic information about this exception.
516 */
517static void gdb_stub_report_exception_info(
518  int thread
519)
520{
521  char *ptr;
522  int sigval;
523
524  /* Convert exception ID to a signal number */
525  sigval = compute_signal(registers[LM32_REG_EID]);
526
527  /* Set pointer to start of output buffer */
528  ptr = remcomOutBuffer;
529
530  *ptr++ = 'T';
531  *ptr++ = highhex(sigval);
532  *ptr++ = lowhex(sigval);
533
534  *ptr++ = highhex(LM32_REG_PC);
535  *ptr++ = lowhex(LM32_REG_PC);
536  *ptr++ = ':';
537  ptr    = mem2hex((unsigned char *)&(registers[LM32_REG_PC]), ptr, 4);
538  *ptr++ = ';';
539
540  *ptr++ = highhex(LM32_REG_SP);
541  *ptr++ = lowhex(LM32_REG_SP);
542  *ptr++ = ':';
543  ptr    = mem2hex((unsigned char *)&(registers[LM32_REG_SP]), ptr, 4);
544  *ptr++ = ';';
545
546#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
547  if (do_threads)
548  {
549    *ptr++ = 't';
550    *ptr++ = 'h';
551    *ptr++ = 'r';
552    *ptr++ = 'e';
553    *ptr++ = 'a';
554    *ptr++ = 'd';
555    *ptr++ = ':';
556    ptr   = thread2vhstr(ptr, thread);
557    *ptr++ = ';';
558  }
559#endif
560
561  *ptr++ = '\0';
562}
563
564/*
565 * This function does all command procesing for interfacing to gdb. The error
566 * codes we return are errno numbers.
567 */
568void handle_exception(void)
569{
570  int addr;
571  int length;
572  char *ptr;
573  int err;
574  int reg;
575  unsigned insn;
576  unsigned opcode;
577  unsigned branch_target = 0;
578  int current_thread;
579  int thread;
580  void *regptr;
581  int host_has_detached = 0;
582  int binary;
583
584  thread = 0;
585#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
586  if (do_threads)
587    thread = rtems_gdb_stub_get_current_thread();
588#endif
589  current_thread = thread;
590
591  /*
592   * Check for bus error caused by this code (rather than the program being
593   * debugged)
594   */
595  if (may_fault && (registers[LM32_REG_EID] == LM32_EXCEPTION_DATA_BUS_ERROR))
596  {
597    /* Indicate that a fault occured */
598    mem_err = 1;
599    /* Skip over faulting instruction */
600    registers[LM32_REG_PC] += 4;
601    /* Resume execution */
602    return;
603  }
604
605  if (stepping)
606  {
607    /* Remove breakpoints */
608    *seq_ptr = seq_insn;
609    if (branch_step)
610      *branch_ptr = branch_insn;
611    stepping = 0;
612  }
613
614  /* Reply to host that an exception has occured with some basic info */
615  gdb_stub_report_exception_info(thread);
616  putpacket(remcomOutBuffer);
617
618  while (!host_has_detached)
619  {
620    remcomOutBuffer[0] = '\0';
621    ptr = getpacket();
622    binary = 0;
623
624    switch (*ptr++)
625    {
626      /* Return last signal */
627      case '?':
628        gdb_stub_report_exception_info(thread);
629        break;
630
631      /* Detach - exit from debugger */
632          case 'D':
633            strcpy(remcomOutBuffer, "OK");
634                host_has_detached = 1;
635                break;
636
637      /* Return the value of the CPU registers */
638      case 'g':
639        regptr = registers;
640#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
641        if (do_threads && current_thread != thread )
642          regptr = &current_thread_registers;
643#endif
644        ptr = mem2hex((unsigned char*)regptr, remcomOutBuffer, NUM_REGS * 4);
645        break;
646
647      /* Set the value of the CPU registers */
648      case 'G':
649        regptr = registers;
650#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
651        if (do_threads && current_thread != thread )
652          regptr = &current_thread_registers;
653#endif
654        hex2mem(ptr, (unsigned char*)regptr, NUM_REGS * 4);
655        strcpy(remcomOutBuffer, "OK");
656        break;
657
658      /* Return the value of the specified register */
659      case 'p':
660        if (hex2int(&ptr, &reg))
661        {
662          ptr = remcomOutBuffer;
663          ptr = mem2hex((unsigned char *)&registers[reg], ptr, 4);
664        } else
665          strcpy(remcomOutBuffer, "E22");
666        break;
667
668      /* Set the specified register to the given value */
669      case 'P':
670        if (hex2int(&ptr, &reg)
671            && *ptr++ == '=')
672        {
673          hex2mem(ptr, (unsigned char *)&registers[reg], 4);
674          strcpy(remcomOutBuffer, "OK");
675        }
676        else
677          strcpy(remcomOutBuffer, "E22");
678        break;
679
680      /* Read memory */
681      case 'm':
682        /* Try to read %x,%x.  */
683        if (hex2int(&ptr, &addr)
684            && *ptr++ == ','
685            && hex2int(&ptr, &length)
686            && length < (sizeof(remcomOutBuffer)/2))
687        {
688          allow_nested_exception();
689          if (NULL == mem2hex((unsigned char *)addr, remcomOutBuffer, length))
690            strcpy(remcomOutBuffer, "E14");
691          disallow_nested_exception();
692        }
693        else
694          strcpy(remcomOutBuffer,"E22");
695        break;
696
697      /* Write memory */
698      case 'X':
699            binary = 1;
700      case 'M':
701        /* Try to read '%x,%x:'.  */
702        if (hex2int(&ptr, &addr)
703            && *ptr++ == ','
704            && hex2int(&ptr, &length)
705            && *ptr++ == ':')
706        {
707          allow_nested_exception();
708          if (binary)
709            err = (int)bin2mem(ptr, (unsigned char *)addr, length);
710          else
711            err = (int)hex2mem(ptr, (unsigned char *)addr, length);
712          if (err)
713            strcpy(remcomOutBuffer, "OK");
714          else
715            strcpy(remcomOutBuffer, "E14");
716          disallow_nested_exception();
717        }
718        else
719          strcpy(remcomOutBuffer, "E22");
720        break;
721
722      /* Continue */
723      case 'c':
724        /* try to read optional parameter, pc unchanged if no parm */
725        if (hex2int(&ptr, &addr))
726          registers[LM32_REG_PC] = addr;
727        flush_cache();
728        return;
729
730      /* Step */
731      case 's':
732        /* try to read optional parameter, pc unchanged if no parm */
733        if (hex2int(&ptr, &addr))
734          registers[LM32_REG_PC] = addr;
735        stepping = 1;
736        /* Is instruction a branch? */
737        insn = *(unsigned int*)registers[LM32_REG_PC];
738        opcode = insn & 0xfc000000;
739        if (   (opcode == 0xe0000000)
740            || (opcode == 0xf8000000)
741           )
742        {
743          branch_step = 1;
744          branch_target = registers[LM32_REG_PC]
745              + (((signed)insn << 6) >> 4);
746        }
747        else if (   (opcode == 0x44000000)
748                 || (opcode == 0x48000000)
749                 || (opcode == 0x4c000000)
750                 || (opcode == 0x50000000)
751                 || (opcode == 0x54000000)
752                 || (opcode == 0x5c000000)
753                )
754        {
755          branch_step = 1;
756          branch_target = registers[LM32_REG_PC] +
757              + (((signed)insn << 16) >> 14);
758        }
759        else if (   (opcode == 0xd8000000)
760                 || (opcode == 0xc0000000)
761                )
762        {
763          branch_step = 1;
764          branch_target = registers[(insn >> 21) & 0x1f];
765        }
766        else
767          branch_step = 0;
768
769        /* Set breakpoint after instruction we're stepping */
770        seq_ptr = (unsigned int *)registers[LM32_REG_PC];
771        seq_ptr++;
772        seq_insn = *seq_ptr;
773        *seq_ptr = LM32_BREAK;
774
775        /* Make sure one insn doesn't get replaced twice */
776        if (seq_ptr == (unsigned int*)branch_target)
777          branch_step = 0;
778
779        if (branch_step)
780        {
781          /* Set breakpoint on branch target */
782          branch_ptr = (unsigned int*)branch_target;
783          branch_insn = *branch_ptr;
784          *branch_ptr = LM32_BREAK;
785        }
786        flush_cache();
787        return;
788
789      case 'Z':
790        switch (*ptr++)
791        {
792          /* Insert h/w breakpoint */
793          case '1':
794            if (*ptr++ == ','
795                && hex2int(&ptr, &addr)
796                && *ptr++ == ','
797                && hex2int(&ptr, &length))
798            {
799              err = set_hw_breakpoint(addr, length);
800              if (err > 0)
801                strcpy(remcomOutBuffer, "OK");
802              else if (err < 0)
803                strcpy(remcomOutBuffer, "E28");
804            }
805            else
806              strcpy(remcomOutBuffer, "E22");
807            break;
808        }
809        break;
810
811      case 'z':
812        switch (*ptr++)
813        {
814          /* Remove h/w breakpoint */
815          case '1':
816            if (*ptr++ == ','
817                && hex2int(&ptr, &addr)
818                && *ptr++ == ','
819                && hex2int(&ptr, &length))
820            {
821              err = disable_hw_breakpoint(addr, length);
822              if (err > 0)
823                strcpy(remcomOutBuffer, "OK");
824              else if (err < 0)
825                strcpy(remcomOutBuffer, "E28");
826            }
827            else
828              strcpy(remcomOutBuffer, "E22");
829            break;
830        }
831        break;
832
833      /* Query */
834      case 'q':
835#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
836        rtems_gdb_process_query(
837            remcomInBuffer,
838            remcomOutBuffer,
839            do_threads,
840            thread );
841#endif
842        break;
843
844#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
845      /* Thread alive */
846      case 'T':
847      {
848        int testThread;
849
850        if (vhstr2thread(&remcomInBuffer[1], &testThread) == NULL)
851        {
852          strcpy(remcomOutBuffer, "E01");
853          break;
854        }
855
856        if (rtems_gdb_index_to_stub_id(testThread) == NULL)
857          strcpy(remcomOutBuffer, "E02");
858        else
859          strcpy(remcomOutBuffer, "OK");
860      }
861      break;
862#endif
863
864      /* Set thread */
865      case 'H':
866#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
867        if (remcomInBuffer[1] != 'g')
868          break;
869
870        if (!do_threads)
871          break;
872
873        {
874          int tmp, ret;
875
876          /* Set new generic thread */
877          if (vhstr2thread(&remcomInBuffer[2], &tmp) == NULL)
878          {
879            strcpy(remcomOutBuffer, "E01");
880            break;
881          }
882
883          /* 0 means `thread' */
884          if (tmp == 0)
885            tmp = thread;
886
887          if (tmp == current_thread)
888          {
889            /* No changes */
890            strcpy(remcomOutBuffer, "OK");
891            break;
892          }
893
894          /* Save current thread registers if necessary */
895          if (current_thread != thread)
896          {
897            ret = rtems_gdb_stub_set_thread_regs(
898                current_thread, (unsigned int *) &current_thread_registers);
899          }
900
901          /* Read new registers if necessary */
902          if (tmp != thread)
903          {
904            ret = rtems_gdb_stub_get_thread_regs(
905                tmp, (unsigned int *) &current_thread_registers);
906
907            if (!ret)
908            {
909              /* Thread does not exist */
910              strcpy(remcomOutBuffer, "E02");
911              break;
912            }
913          }
914
915          current_thread = tmp;
916          strcpy(remcomOutBuffer, "OK");
917        }
918#endif
919      break;
920
921#ifdef GDB_RESTART_ENABLED
922      /* Reset */
923      case 'r':
924      case 'R':
925        /* We reset by branching to the reset exception handler. */
926        registers[LM32_REG_PC] = 0;
927        return;
928#endif
929      }
930
931    /* reply to the request */
932    putpacket(remcomOutBuffer);
933  }
934}
935
936void gdb_handle_break(rtems_vector_number vector, CPU_Interrupt_frame *frame)
937{
938  int i;
939  unsigned int *int_regs = (unsigned int*)frame;
940
941  /* copy extended frame to registers */
942  registers[LM32_REG_R0]   = 0;
943  for (i = 1; i < NUM_REGS; i++)
944  {
945    registers[i] = int_regs[reg_map[i]];
946  }
947
948  /* now call the real handler */
949  handle_exception();
950  gdb_ack_irq();
951
952  /* copy registers back to extended frame */
953  for (i = 1; i < NUM_REGS; i++)
954  {
955    int_regs[reg_map[i]] = registers[i];
956  }
957}
958
959void lm32_gdb_stub_install(int enable_threads)
960{
961  unsigned int dc;
962
963  /* set DEBA and remap all exception */
964  __asm__("wcsr DEBA, %0" : : "r" (&_deba));
965  __asm__("rcsr %0, DC" : "=r" (dc));
966  dc |= 0x2;
967  __asm__("wcsr DC, %0" : : "r" (dc));
968
969#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT)
970  if( enable_threads )
971    do_threads = 1;
972  else
973    do_threads = 0;
974#endif
975
976  gdb_console_init();
977}
978
Note: See TracBrowser for help on using the repository browser.