source: rtems/bsps/lm32/shared/gdbstub/lm32-stub.c @ 762fa62

5
Last change on this file since 762fa62 was fd67814, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 23, 2018 at 10:06:14 AM

bsps: Move GDB stubs to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

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