From fd67814e06a734cd0d78274d61fc04c7af79b5fc Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 23 Apr 2018 12:06:14 +0200 Subject: bsps: Move GDB stubs to bsps This patch is a part of the BSP source reorganization. Update #3285. --- c/src/lib/libbsp/mips/shared/gdbstub/README | 151 -- c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h | 194 --- c/src/lib/libbsp/mips/shared/gdbstub/memlimits.h | 100 -- c/src/lib/libbsp/mips/shared/gdbstub/mips-stub.c | 1589 -------------------- c/src/lib/libbsp/mips/shared/gdbstub/mips_opcode.h | 336 ----- 5 files changed, 2370 deletions(-) delete mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/README delete mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h delete mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/memlimits.h delete mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/mips-stub.c delete mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/mips_opcode.h (limited to 'c/src/lib/libbsp/mips') diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/README b/c/src/lib/libbsp/mips/shared/gdbstub/README deleted file mode 100644 index e61d0f0aa5..0000000000 --- a/c/src/lib/libbsp/mips/shared/gdbstub/README +++ /dev/null @@ -1,151 +0,0 @@ -/*****************************************************/ - -Debugged this stub against the MongooseV bsp. Relies on putting break -instructions on breakpoints and step targets- normal stuff, and does not -employ hardware breakpoint support at this time. As written, a single -breakpoint in a loop will not be reasserted unless the user steps or has -a 2nd one, since breakpoints are only reset when the gdb stub is -re-entered. A useful enhancement would be to fix the break instruction -management so the stub could invisibly put a 2nd break after the 1st -"official" one so it can silently reset breakpoints. Shouldn't be too -hard, mostly a matter of working it out. - -This was tested only against an R3000 MIPS. It should work OK on a -R4000. Needs to be tested at some point. - -This stub supports threads as implemented by gdb 5 and doesn't have any -bugs I'm aware of. - -Greg Menke -3/5/2002 - -/*****************************************************/ - - -The contents of this directory are based upon the "r46kstub.tar.gz" package -released to the net by - - C. M. Heard - VVNET, Inc. phone: +1 408 247 9376 - 4040 Moorpark Ave. Suite 206 fax: +1 408 244 3651 - San Jose, CA 95117 USA e-mail: heard@vvnet.com - -This package was released in the September 1996 time frame for use -with gdb 4.16 and an IDT R4600 Orion. The stub was modified to support -R3000 class CPUs and to work within the mips-rtems exeception processing -framework. - -THe file memlimits.h could end up being target board dependent. If -this is the case, copy it to your BSP directory and modify as necessary. - ---joel -8 February 2002 - -Original README -=============== - -The r46kstub directory and its compressed archive (r46kstub.tar.gz) contain -the 9/29/96 source code snapshot for a ROM-resident gdb-4.16 debug agent -(aka stub) for the IDT R4600 Orion processor. It is based on the stub for -the Hitachi SH processor written by Ben Lee and Steve Chamberlain and -supplied with the gdb-4.16 distribution; that stub in turn was "originally -based on an m68k software stub written by Glenn Engel at HP, but has changed -quite a bit". The modifications for the R4600 were contributed by C. M. -Heard of VVNET, Inc. and were based in part on the Algorithmics R4000 version -of Phil Bunce's PMON program. - -The distribution consists of the following files: - --rw-r--r-- 1 1178 Sep 29 16:34 ChangeLog --rw-r--r-- 1 748 Jul 26 01:18 Makefile --rw-r--r-- 1 6652 Sep 29 16:34 README --rw-r--r-- 1 1829 May 21 02:02 gdb_if.h --rw-r--r-- 1 3745 Sep 29 14:03 ioaddr.h --rw-r--r-- 1 2906 Sep 29 14:39 limits.h --rw-r--r-- 1 6552 May 23 00:17 mips_opcode.h --rw-r--r-- 1 14017 May 21 02:04 r4600.h --rw-r--r-- 1 23874 Jul 21 20:31 r46kstub.c --rw-r--r-- 1 1064 Jul 3 12:35 r46kstub.ld --rw-r--r-- 1 13299 Sep 29 16:24 stubinit.S - -With the exception of mips_opcode.h, which is a slightly modified version -of a header file contributed by Ralph Campbell to 4.4 BSD and is therefore -copyrighted by the UC Regents, all of the source files have been dedicated -by their authors to the public domain. Use them as you wish, but do so -at your own risk! The authors accept _no_ responsibility for any errors. - -The debug agent contained herein is at this writing in active use at VVNET -supporting initial hardware debug and board bring-up of an OC-12 ATM probe -board. It uses polled I/O on a 16C450 UART. We had originally intended to -add support for interrupts to allow gdb to break in on a running program, -but we have found that this is not really necessary since the reset button -will accomplish the same purpose (thanks to the MIPS feature of saving the -program counter in the ErrorEPC register when a reset exception occurs). - -Be aware that this stub handles ALL interrupts and exceptions except for -reset (or NMI) in the same way -- by passing control to the debug command -loop. It of course uses the ROM exception vectors to do so. In order to -support code that actally needs to use interrupts we use use a more elaborate -stub that is linked with the downloaded program. It hooks the RAM exception -vectors and clears the BEV status bit to gain control. The ROM-based stub -is still used in this case for initial program loading. - -In order to port this stub to a different platform you will at a minimum -need to customize the macros in limits.h (which define the limits of readable, -writeable, and steppable address space) and the I/O addresses in ioaddr.h -(which define the 16C450 MMIO addresses). If you use something other than -a 16C450 UART you will probably also need to modify the portions of stubinit.S -which deal with the serial port. I've tried to be careful to respect all the -architecturally-defined hazards as described in Appendix F of Kane and -Heinrich, MIPS RISC Architecture, in order to minimize the work in porting -to 4000-series processors other than the R4600, but no guarantees are offered. -Support is presently restricted to big-endian addressing, and I've not even -considered what changes would be needed for little-endian support. - -When this stub is built with gcc-2.7.2 and binutils-2.6 you will see a few -warning messages from the single-step support routine where a cast is used -to sign-extend a pointer (the next instruction address) into a long long -(the PC image). Those warnings are expected; I've checked the generated -code and it is doing what I had intended. But you should not see any other -warnings or errors. Here is a log of the build: - -mips64orion-idt-elf-gcc -g -Wa,-ahld -Wall -membedded-data \ - -O3 -c r46kstub.c >r46kstub.L -r46kstub.c: In function `doSStep': -r46kstub.c:537: warning: cast to pointer from integer of different size -r46kstub.c:539: warning: cast to pointer from integer of different size -r46kstub.c:547: warning: cast to pointer from integer of different size -r46kstub.c:561: warning: cast to pointer from integer of different size -r46kstub.c:563: warning: cast to pointer from integer of different size -r46kstub.c:572: warning: cast to pointer from integer of different size -r46kstub.c:574: warning: cast to pointer from integer of different size -r46kstub.c:582: warning: cast to pointer from integer of different size -r46kstub.c:589: warning: cast to pointer from integer of different size -r46kstub.c:591: warning: cast to pointer from integer of different size -r46kstub.c:597: warning: cast to pointer from integer of different size -r46kstub.c:599: warning: cast to pointer from integer of different size -r46kstub.c:605: warning: cast to pointer from integer of different size -r46kstub.c:607: warning: cast to pointer from integer of different size -r46kstub.c:613: warning: cast to pointer from integer of different size -r46kstub.c:615: warning: cast to pointer from integer of different size -r46kstub.c:624: warning: cast to pointer from integer of different size -r46kstub.c:628: warning: cast to pointer from integer of different size -r46kstub.c:635: warning: cast to pointer from integer of different size -r46kstub.c:637: warning: cast to pointer from integer of different size -mips64orion-idt-elf-gcc -g -Wa,-ahld -Wall -membedded-data \ - -O3 -c stubinit.S >stubinit.L -mips64orion-idt-elf-ld -t -s -T r46kstub.ld -Map r46kstub.map -o r46kstub.out -mips64orion-idt-elf-ld: mode elf32bmip -stubinit.o -r46kstub.o -mips64orion-idt-elf-objcopy -S -R .bss -R .data -R .reginfo \ - -O srec r46kstub.out r46kstub.hex - -Limitations: stubinit.S deliberately forces the PC (which is a 64-bit -register) to contain a legitimate sign-extended 32-bit value. This was -done to cope with a bug in gdb-4.16, which does _not_ properly sign-extend -the initial PC when it loads a program. This means that you cannot use -the "set" command to load an unmapped sixty-four bit virtual address into -the PC, as you can for all other registers. - -Please send bug reports, comments, or suggestions for improvement to: diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h b/c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h deleted file mode 100644 index ba4f0eb757..0000000000 --- a/c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h +++ /dev/null @@ -1,194 +0,0 @@ -/** - * @file - * @ingroup mips_gdb - * @brief Definition of the interface between stub and gdb - */ - -/* - * gdb_if.h - definition of the interface between the stub and gdb - * - * THIS SOFTWARE IS NOT COPYRIGHTED - * - * The following software is offered for use in the public domain. - * There is no warranty with regard to this software or its performance - * and the user must accept the software "AS IS" with all faults. - * - * THE CONTRIBUTORS DISCLAIM ANY WARRANTIES, EXPRESS OR IMPLIED, WITH - * REGARD TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -/** - * @defgroup mips_gdb GDB Interface - * @ingroup mips_shared - * @brief GDB Interface - * @{ - */ - -#ifndef _GDB_IF_H -#define _GDB_IF_H - -/** @brief Max number of threads in qM response */ -#define QM_MAX_THREADS (20) - -struct rtems_gdb_stub_thread_info { - char display[256]; - char name[256]; - char more_display[256]; -}; - -/** - * @name Prototypes - * @{ - */ - -int parse_zbreak(const char *in, int *type, unsigned char **addr, int *len); - -char* mem2hstr(char *buf, const unsigned char *mem, int count); -int hstr2mem(unsigned char *mem, const char *buf, int count); -void set_mem_err(void); -unsigned char get_byte(const unsigned char *ptr); -void set_byte(unsigned char *ptr, int val); -char* thread2vhstr(char *buf, int thread); -char* thread2fhstr(char *buf, int thread); -const char* fhstr2thread(const char *buf, int *thread); -const char* vhstr2thread(const char *buf, int *thread); -char* int2fhstr(char *buf, int val); -char* int2vhstr(char *buf, int vali); -const char* fhstr2int(const char *buf, int *ival); -const char* vhstr2int(const char *buf, int *ival); -int hstr2byte(const char *buf, int *bval); -int hstr2nibble(const char *buf, int *nibble); - -Thread_Control *rtems_gdb_index_to_stub_id(int); -int rtems_gdb_stub_thread_support_ok(void); -int rtems_gdb_stub_get_current_thread(void); -int rtems_gdb_stub_get_next_thread(int); -int rtems_gdb_stub_get_offsets( - unsigned char **text_addr, - unsigned char **data_addr, - unsigned char **bss_addr -); -int rtems_gdb_stub_get_thread_regs( - int thread, - unsigned int *registers -); -int rtems_gdb_stub_set_thread_regs( - int thread, - unsigned int *registers -); -void rtems_gdb_process_query( - char *inbuffer, - char *outbuffer, - int do_threads, - int thread -); - -/** @} */ - -/** - * @name MIPS registers - * @brief Numbered in the order in which gdb expects to see them. - * @{ - */ - -#define ZERO 0 -#define AT 1 -#define V0 2 -#define V1 3 -#define A0 4 -#define A1 5 -#define A2 6 -#define A3 7 - -#define T0 8 -#define T1 9 -#define T2 10 -#define T3 11 -#define T4 12 -#define T5 13 -#define T6 14 -#define T7 15 - -#define S0 16 -#define S1 17 -#define S2 18 -#define S3 19 -#define S4 20 -#define S5 21 -#define S6 22 -#define S7 23 - -#define T8 24 -#define T9 25 -#define K0 26 -#define K1 27 -#define GP 28 -#define SP 29 -#define S8 30 -#define RA 31 - -#define SR 32 -#define LO 33 -#define HI 34 -#define BAD_VA 35 -#define CAUSE 36 -#define PC 37 - -#define F0 38 -#define F1 39 -#define F2 40 -#define F3 41 -#define F4 42 -#define F5 43 -#define F6 44 -#define F7 45 - -#define F8 46 -#define F9 47 -#define F10 48 -#define F11 49 -#define F12 50 -#define F13 51 -#define F14 52 -#define F15 53 - -#define F16 54 -#define F17 55 -#define F18 56 -#define F19 57 -#define F20 58 -#define F21 59 -#define F22 60 -#define F23 61 - -#define F24 62 -#define F25 63 -#define F26 64 -#define F27 65 -#define F28 66 -#define F29 67 -#define F30 68 -#define F31 69 - -#define FCSR 70 -#define FIRR 71 - -#define NUM_REGS 72 - -/** @} */ - -void mips_gdb_stub_install(int enableThreads) ; - -#define MEMOPT_READABLE 1 -#define MEMOPT_WRITEABLE 2 - -#ifndef NUM_MEMSEGS -#define NUM_MEMSEGS 10 -#endif - -int gdbstub_add_memsegment(unsigned,unsigned,int); - -/** @} */ - -#endif /* _GDB_IF_H */ diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/memlimits.h b/c/src/lib/libbsp/mips/shared/gdbstub/memlimits.h deleted file mode 100644 index c60ca12111..0000000000 --- a/c/src/lib/libbsp/mips/shared/gdbstub/memlimits.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file - * @ingroup mips_limits - * @brief Definition of machine and system dependent address limits. - */ - -/* - * limits.h - definition of machine & system dependent address limits - * - * THIS SOFTWARE IS NOT COPYRIGHTED - * - * The following software is offered for use in the public domain. - * There is no warranty with regard to this software or its performance - * and the user must accept the software "AS IS" with all faults. - * - * THE CONTRIBUTORS DISCLAIM ANY WARRANTIES, EXPRESS OR IMPLIED, WITH - * REGARD TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef _MEMLIMITS_H_ -#define _MEMLIMITS_H_ - -/* - * The macros in this file are specific to a given implementation. - * The general rules for their construction are as follows: - * - * 1.) is_readable(addr,length) should be true if and only if the - * region starting at the given virtual address can be read - * _without_ causing an exception or other fatal error. Note - * that the stub will use the strictest alignment satisfied - * by _both_ addr and length (e.g., if both are divisible by - * 8 then the region will be read in double-word chunks). - * - * 2.) is_writeable(addr,length) should be true if and only if the - * region starting at the given virtual address can be written - * _without_ causing an exception or other fatal error. Note - * that the stub will use the strictest alignment satisfied - * by _both_ addr and length (e.g., if both are divisible by - * 8 then the region will be written in double-word chunks). - * - * 3.) is-steppable(ptr) whould be true if and only if ptr is the - * address of a writeable region of memory which may contain - * an executable instruction. At a minimum this requires that - * ptr be word-aligned (divisible by 4) and not point to EPROM - * or memory-mapped I/O. - * - * Note: in order to satisfy constraints related to cacheability - * of certain memory subsystems it may be necessary for regions - * of kseg0 and kseg1 which map to the same physical addresses - * to have different readability and/or writeability attributes. - */ - -/** - * @defgroup mips_limits Address Limits - * @ingroup mips_shared - * @brief Address Limits - */ - - -/* -#define K0_LIMIT_FOR_READ (K0BASE+0x18000000) -#define K1_LIMIT_FOR_READ (K1BASE+K1SIZE) - -#define is_readable(addr,length) \ - (((K0BASE <= addr) && ((addr + length) <= K0_LIMIT_FOR_READ)) \ - || ((K1BASE <= addr) && ((addr + length) <= K1_LIMIT_FOR_READ))) - -#define K0_LIMIT_FOR_WRITE (K0BASE+0x08000000) -#define K1_LIMIT_FOR_WRITE (K1BASE+0x1e000000) - -#define is_writeable(addr,length) \ - (((K0BASE <= addr) && ((addr + length) <= K0_LIMIT_FOR_WRITE)) \ - || ((K1BASE <= addr) && ((addr + length) <= K1_LIMIT_FOR_WRITE))) - -#define K0_LIMIT_FOR_STEP (K0BASE+0x08000000) -#define K1_LIMIT_FOR_STEP (K1BASE+0x08000000) - -#define is_steppable(ptr) \ - ((((int)ptr & 0x3) == 0) \ - && (((K0BASE <= (int)ptr) && ((int)ptr < K0_LIMIT_FOR_STEP)) \ - || ((K1BASE <= (int)ptr) && ((int)ptr < K1_LIMIT_FOR_STEP)))) - -struct memseg -{ - unsigned begin, end, opts; -}; - -#define MEMOPT_READABLE 1 -#define MEMOPT_WRITEABLE 2 - -#define NUM_MEMSEGS 10 - -int add_memsegment(unsigned,unsigned,int); -int is_readable(unsigned,unsigned); -int is_writeable(unsigned,unsigned); -int is_steppable(unsigned); -*/ - -#endif /* _MEMLIMITS_H_ */ diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/mips-stub.c b/c/src/lib/libbsp/mips/shared/gdbstub/mips-stub.c deleted file mode 100644 index 8320eb66a9..0000000000 --- a/c/src/lib/libbsp/mips/shared/gdbstub/mips-stub.c +++ /dev/null @@ -1,1589 +0,0 @@ -#define GDB_STUB_ENABLE_THREAD_SUPPORT 1 -/******************************************************************************* - - THIS SOFTWARE IS NOT COPYRIGHTED - - The following software is offered for use in the public domain. - There is no warranty with regard to this software or its performance - and the user must accept the software "AS IS" with all faults. - - THE CONTRIBUTORS DISCLAIM ANY WARRANTIES, EXPRESS OR IMPLIED, WITH - REGARD TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - -******************************************************************************** -* -* r46kstub.c -- target debugging stub for the IDT R4600 Orion processor -* -* This module is based on the stub for the Hitachi SH processor written by -* Ben Lee and Steve Chamberlain and supplied with gdb 4.16. The latter -* in turn "is originally based on an m68k software stub written by Glenn -* Engel at HP, but has changed quite a bit." The changes for the R4600 -* were written by C. M. Heard at VVNET. They were based in part on the -* Algorithmics R4000 version of Phil Bunce's PMON program. -* -* Remote communication protocol: -* -* A debug packet whose contents are -* is encapsulated for transmission in the form: -* -* $ # CSUM1 CSUM2 -* -* must be ASCII alphanumeric and cannot include characters -* '$' or '#'. If starts with two characters followed by -* ':', then the existing stubs interpret this as a sequence number. -* -* CSUM1 and CSUM2 are ascii hex representation of an 8-bit -* checksum of , the most significant nibble is sent first. -* the hex digits 0-9,a-f are used. -* -* Receiver responds with: -* -* + if CSUM is correct -* - if CSUM is incorrect -* -* is as follows. All values are encoded in ascii hex digits. -* -* Request Packet -* -* read registers g -* reply XX....X Each byte of register data -* is described by two hex digits. -* Registers are in the internal order -* for GDB, and the bytes in a register -* are in the same order the machine uses. -* or ENN for an error. -* -* write regs GXX..XX Each byte of register data -* is described by two hex digits. -* reply OK for success -* ENN for an error -* -* write reg Pn...=r... Write register n... with value r.... -* reply OK for success -* ENN for an error -* -* read mem mAA..AA,LLLL AA..AA is address, LLLL is length. -* reply XX..XX XX..XX is mem contents -* Can be fewer bytes than requested -* if able to read only part of the data. -* or ENN NN is errno -* -* write mem MAA..AA,LLLL:XX..XX -* AA..AA is address, -* LLLL is number of bytes, -* XX..XX is data -* reply OK for success -* ENN for an error (this includes the case -* where only part of the data was -* written). -* -* cont cAA..AA AA..AA is address to resume -* If AA..AA is omitted, -* resume at same address. -* -* step sAA..AA AA..AA is address to resume -* If AA..AA is omitted, -* resume at same address. -* -* There is no immediate reply to step or cont. -* The reply comes when the machine stops. -* It is SAA AA is the "signal number" -* -* last signal ? Reply with the reason for stopping. -* This is the same reply as is generated -* for step or cont: SAA where AA is the -* signal number. -* -* detach D Host is detaching. Reply OK and -* end remote debugging session. -* -* reserved On other requests, the stub should -* ignore the request and send an empty -* response ($#). This way -* we can extend the protocol and GDB -* can tell whether the stub it is -* talking to uses the old or the new. -* -* Responses can be run-length encoded to save space. A '*' means that -* the next character is an ASCII encoding giving a repeat count which -* stands for that many repetitions of the character preceding the '*'. -* The encoding is n+29, yielding a printable character when n >=3 -* (which is where rle starts to win). Don't use n > 99 since gdb -* masks each character is receives with 0x7f in order to strip off -* the parity bit. -* -* As an example, "0* " means the same thing as "0000". -* -*******************************************************************************/ - - -#include -#include -#include "mips_opcode.h" -/* #include "memlimits.h" */ -#include -#include -#include "gdb_if.h" - -/* Change it to something meaningful when debugging */ -#undef ASSERT -#define ASSERT(x) if(!(x)) printk("ASSERT: stub: %d\n", __LINE__) - -/***************/ -/* Exception Codes */ -#define EXC_INT 0 /* External interrupt */ -#define EXC_MOD 1 /* TLB modification exception */ -#define EXC_TLBL 2 /* TLB miss (Load or Ifetch) */ -#define EXC_TLBS 3 /* TLB miss (Store) */ -#define EXC_ADEL 4 /* Address error (Load or Ifetch) */ -#define EXC_ADES 5 /* Address error (Store) */ -#define EXC_IBE 6 /* Bus error (Ifetch) */ -#define EXC_DBE 7 /* Bus error (data load or store) */ -#define EXC_SYS 8 /* System call */ -#define EXC_BP 9 /* Break point */ -#define EXC_RI 10 /* Reserved instruction */ -#define EXC_CPU 11 /* Coprocessor unusable */ -#define EXC_OVF 12 /* Arithmetic overflow */ -#define EXC_TRAP 13 /* Trap exception */ -#define EXC_FPE 15 /* Floating Point Exception */ - -/* FPU Control/Status register fields */ -#define CSR_FS 0x01000000 /* Set to flush denormals to zero */ -#define CSR_C 0x00800000 /* Condition bit (set by FP compare) */ - -#define CSR_CMASK (0x3f<<12) -#define CSR_CE 0x00020000 -#define CSR_CV 0x00010000 -#define CSR_CZ 0x00008000 -#define CSR_CO 0x00004000 -#define CSR_CU 0x00002000 -#define CSR_CI 0x00001000 - -#define CSR_EMASK (0x1f<<7) -#define CSR_EV 0x00000800 -#define CSR_EZ 0x00000400 -#define CSR_EO 0x00000200 -#define CSR_EU 0x00000100 -#define CSR_EI 0x00000080 - -#define CSR_FMASK (0x1f<<2) -#define CSR_FV 0x00000040 -#define CSR_FZ 0x00000020 -#define CSR_FO 0x00000010 -#define CSR_FU 0x00000008 -#define CSR_FI 0x00000004 - -#define CSR_RMODE_MASK (0x3<<0) -#define CSR_RM 0x00000003 -#define CSR_RP 0x00000002 -#define CSR_RZ 0x00000001 -#define CSR_RN 0x00000000 - -/***************/ - -/* - * Saved register information. Must be prepared by the exception - * preprocessor before handle_exception is invoked. - */ -#if (__mips == 3) -typedef long long mips_register_t; -#define R_SZ 8 -#elif (__mips == 1) -typedef unsigned int mips_register_t; -#define R_SZ 4 -#else -#error "unknown MIPS ISA" -#endif -static mips_register_t *registers; - -#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) -static char do_threads; /* != 0 means we are supporting threads */ -#endif - -/* - * The following external functions provide character input and output. - */ -extern char getDebugChar (void); -extern void putDebugChar (char); - -/* - * Exception handler - */ -void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame); - -/* - * Prototype needed by this code and to keep it self contained. - */ -void rtems_interrupt_catch( rtems_isr_entry, int, rtems_isr_entry *); - -/* - * The following definitions are used for the gdb stub memory map - */ -struct memseg -{ - unsigned begin, end, opts; -}; - -static int is_readable(unsigned,unsigned); -static int is_writeable(unsigned,unsigned); -static int is_steppable(unsigned); - -/* - * BUFMAX defines the maximum number of characters in the inbound & outbound - * packet buffers. At least 4+(sizeof registers)*2 bytes will be needed for - * register packets. Memory dump packets can profitably use even more. - */ -#define BUFMAX 1500 - -static char inBuffer[BUFMAX]; -static char outBuffer[BUFMAX]; - -/* Structure to keep info on a z-breaks */ -#define BREAKNUM 32 - -struct z0break -{ - /* List support */ - struct z0break *next; - struct z0break *prev; - - /* Location, preserved data */ - - /* the address pointer, really, really must be a pointer to - ** a 32 bit quantity (likely 64 on the R4k), so the full instruction is read & - ** written. Making it a char * as on the i386 will cause - ** the zbreaks to mess up the breakpoint instructions - */ - unsigned char *address; - unsigned instr; -}; - -static struct z0break z0break_arr[BREAKNUM]; -static struct z0break *z0break_avail = NULL; -static struct z0break *z0break_list = NULL; - - -/* - * Convert an int to hex. - */ -const char gdb_hexchars[] = "0123456789abcdef"; - -#define highhex(x) gdb_hexchars [(x >> 4) & 0xf] -#define lowhex(x) gdb_hexchars [x & 0xf] - -/* - * Convert length bytes of data starting at addr into hex, placing the - * result in buf. Return a pointer to the last (null) char in buf. - */ -static char * -mem2hex (void *_addr, int length, char *buf) -{ - unsigned int addr = (unsigned int) _addr; - - if (((addr & 0x7) == 0) && ((length & 0x7) == 0)) /* dword aligned */ - { - long long *source = (long long *) (addr); - long long *limit = (long long *) (addr + length); - - while (source < limit) - { - int i; - long long k = *source++; - - for (i = 15; i >= 0; i--) - *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf]; - } - } - else if (((addr & 0x3) == 0) && ((length & 0x3) == 0)) /* word aligned */ - { - int *source = (int *) (addr); - int *limit = (int *) (addr + length); - - while (source < limit) - { - int i; - int k = *source++; - - for (i = 7; i >= 0; i--) - *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf]; - } - } - else if (((addr & 0x1) == 0) && ((length & 0x1) == 0)) /* halfword aligned */ - { - short *source = (short *) (addr); - short *limit = (short *) (addr + length); - - while (source < limit) - { - int i; - short k = *source++; - - for (i = 3; i >= 0; i--) - *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf]; - } - } - else /* byte aligned */ - { - char *source = (char *) (addr); - char *limit = (char *) (addr + length); - - while (source < limit) - { - int i; - char k = *source++; - - for (i = 1; i >= 0; i--) - *buf++ = gdb_hexchars [(k >> (i*4)) & 0xf]; - } - } - - *buf = '\0'; - return (buf); -} - - -/* - * Convert a hex character to an int. - */ -static int -hex (char ch) -{ - if ((ch >= 'a') && (ch <= 'f')) - return (ch - 'a' + 10); - if ((ch >= '0') && (ch <= '9')) - return (ch - '0'); - if ((ch >= 'A') && (ch <= 'F')) - return (ch - 'A' + 10); - return (-1); -} - -/* - * Convert a string from hex to int until a non-hex digit - * is found. Return the number of characters processed. - */ -static int -hexToInt (char **ptr, int *intValue) -{ - int numChars = 0; - int hexValue; - - *intValue = 0; - - while (**ptr) - { - hexValue = hex (**ptr); - if (hexValue >= 0) - { - *intValue = (*intValue << 4) | hexValue; - numChars++; - } - else - break; - - (*ptr)++; - } - - return (numChars); -} - -/* - * Convert a string from hex to long long until a non-hex - * digit is found. Return the number of characters processed. - */ -static int -hexToLongLong (char **ptr, long long *intValue) -{ - int numChars = 0; - int hexValue; - - *intValue = 0; - - while (**ptr) - { - hexValue = hex (**ptr); - if (hexValue >= 0) - { - *intValue = (*intValue << 4) | hexValue; - numChars++; - } - else - break; - - (*ptr)++; - } - - return (numChars); -} - -/* - * Convert the hex array buf into binary, placing the result at the - * specified address. If the conversion fails at any point (i.e., - * if fewer bytes are written than indicated by the size parameter) - * then return 0; otherwise return 1. - */ -static int -hex2mem (char *buf, void *_addr, int length) -{ - unsigned int addr = (unsigned int) _addr; - if (((addr & 0x7) == 0) && ((length & 0x7) == 0)) /* dword aligned */ - { - long long *target = (long long *) (addr); - long long *limit = (long long *) (addr + length); - - while (target < limit) - { - int i, j; - long long k = 0; - - for (i = 0; i < 16; i++) - if ((j = hex(*buf++)) < 0) - return 0; - else - k = (k << 4) + j; - *target++ = k; - } - } - else if (((addr & 0x3) == 0) && ((length & 0x3) == 0)) /* word aligned */ - { - int *target = (int *) (addr); - int *limit = (int *) (addr + length); - - while (target < limit) - { - int i, j; - int k = 0; - - for (i = 0; i < 8; i++) - if ((j = hex(*buf++)) < 0) - return 0; - else - k = (k << 4) + j; - *target++ = k; - } - } - else if (((addr & 0x1) == 0) && ((length & 0x1) == 0)) /* halfword aligned */ - { - short *target = (short *) (addr); - short *limit = (short *) (addr + length); - - while (target < limit) - { - int i, j; - short k = 0; - - for (i = 0; i < 4; i++) - if ((j = hex(*buf++)) < 0) - return 0; - else - k = (k << 4) + j; - *target++ = k; - } - } - else /* byte aligned */ - { - char *target = (char *) (addr); - char *limit = (char *) (addr + length); - - while (target < limit) - { - int i, j; - char k = 0; - - for (i = 0; i < 2; i++) - if ((j = hex(*buf++)) < 0) - return 0; - else - k = (k << 4) + j; - *target++ = k; - } - } - - return 1; -} - -/* Convert the binary stream in BUF to memory. - - Gdb will escape $, #, and the escape char (0x7d). - COUNT is the total number of bytes to write into - memory. */ -static unsigned char * -bin2mem ( - char *buf, - unsigned char *mem, - int count -) -{ - int i; - - for (i = 0; i < count; i++) { - /* Check for any escaped characters. Be paranoid and - only unescape chars that should be escaped. */ - if (*buf == 0x7d) { - switch (*(buf+1)) { - case 0x3: /* # */ - case 0x4: /* $ */ - case 0x5d: /* escape char */ - buf++; - *buf |= 0x20; - break; - default: - /* nothing */ - break; - } - } - - *mem++ = *buf++; - } - - return mem; -} - - -/* - * Scan the input stream for a sequence for the form $#. - */ -static void -getpacket (char *buffer) -{ - unsigned char checksum; - unsigned char xmitcsum; - int i; - int count; - char ch; - do - { - /* wait around for the start character, ignore all other characters */ - while ((ch = getDebugChar ()) != '$'); - checksum = 0; - xmitcsum = -1; - - count = 0; - - /* now, read until a # or end of buffer is found */ - while ( (count < BUFMAX-1) && ((ch = getDebugChar ()) != '#') ) - checksum += (buffer[count++] = ch); - - /* make sure that the buffer is null-terminated */ - buffer[count] = '\0'; - - if (ch == '#') - { - xmitcsum = hex (getDebugChar ()) << 4; - xmitcsum += hex (getDebugChar ()); - if (checksum != xmitcsum) - putDebugChar ('-'); /* failed checksum */ - else - { - putDebugChar ('+'); /* successful transfer */ - /* if a sequence char is present, reply the sequence ID */ - if (buffer[2] == ':') - { - putDebugChar (buffer[0]); - putDebugChar (buffer[1]); - /* remove sequence chars from buffer */ - for (i = 3; i <= count; i++) - buffer[i - 3] = buffer[i]; - } - } - } - } - while (checksum != xmitcsum); -} - -/* - * Get a positive/negative acknowledgment for a transmitted packet. - */ -static char -getAck (void) -{ - char c; - - do - { - c = getDebugChar (); - } - while ((c != '+') && (c != '-')); - - return c; -} - -/* - * Send the packet in buffer and wait for a positive acknowledgement. - */ -static void -putpacket (char *buffer) -{ - int checksum; - - /* $# */ - do - { - char *src = buffer; - putDebugChar ('$'); - checksum = 0; - - while (*src != '\0') - { - int runlen = 0; - - /* Do run length encoding */ - while ((src[runlen] == src[0]) && (runlen < 99)) - runlen++; - if (runlen > 3) - { - int encode; - /* Got a useful amount */ - putDebugChar (*src); - checksum += *src; - putDebugChar ('*'); - checksum += '*'; - checksum += (encode = (runlen - 4) + ' '); - putDebugChar (encode); - src += runlen; - } - else - { - putDebugChar (*src); - checksum += *src; - src++; - } - } - - putDebugChar ('#'); - putDebugChar (highhex (checksum)); - putDebugChar (lowhex (checksum)); - } - while (getAck () != '+'); -} - - -/* - * Saved instruction data for single step support - */ -static struct - { - unsigned *targetAddr; - unsigned savedInstr; - } -instrBuffer; - -/* - * If a step breakpoint was planted restore the saved instruction. - */ -static void -undoSStep (void) -{ - if (instrBuffer.targetAddr != NULL) - { - *instrBuffer.targetAddr = instrBuffer.savedInstr; - instrBuffer.targetAddr = NULL; - } - instrBuffer.savedInstr = NOP_INSTR; -} - -/* - * If a single step is requested put a temporary breakpoint at the instruction - * which logically follows the next one to be executed. If the next instruction - * is a branch instruction then skip the instruction in the delay slot. NOTE: - * ERET instructions are NOT handled, as it is impossible to single-step through - * the exit code in an exception handler. In addition, no attempt is made to - * do anything about BC0T and BC0F, since a condition bit for coprocessor 0 - * is not defined on the R4600. Finally, BC2T and BC2F are ignored since there - * is no coprocessor 2 on a 4600. - */ -static void -doSStep (void) -{ - InstFmt inst; - - instrBuffer.targetAddr = (unsigned *)(registers[PC]+4); /* set default */ - - inst.word = *(unsigned *)registers[PC]; /* read the next instruction */ - - switch (inst.RType.op) { /* override default if branch */ - case OP_SPECIAL: - switch (inst.RType.func) { - case OP_JR: - case OP_JALR: - instrBuffer.targetAddr = - (unsigned *)registers[inst.RType.rs]; - break; - }; - break; - - case OP_REGIMM: - switch (inst.IType.rt) { - case OP_BLTZ: - case OP_BLTZL: - case OP_BLTZAL: - case OP_BLTZALL: - if (registers[inst.IType.rs] < 0 ) - instrBuffer.targetAddr = - (unsigned *)(((signed short)inst.IType.imm<<2) - + (registers[PC]+4)); - else - instrBuffer.targetAddr = (unsigned*)(registers[PC]+8); - break; - case OP_BGEZ: - case OP_BGEZL: - case OP_BGEZAL: - case OP_BGEZALL: - if (registers[inst.IType.rs] >= 0 ) - instrBuffer.targetAddr = - (unsigned *)(((signed short)inst.IType.imm<<2) - + (registers[PC]+4)); - else - instrBuffer.targetAddr = (unsigned*)(registers[PC]+8); - break; - }; - break; - - case OP_J: - case OP_JAL: - instrBuffer.targetAddr = - (unsigned *)((inst.JType.target<<2) + ((registers[PC]+4)&0xf0000000)); - break; - - case OP_BEQ: - case OP_BEQL: - if (registers[inst.IType.rs] == registers[inst.IType.rt]) - instrBuffer.targetAddr = - (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4)); - else - instrBuffer.targetAddr = (unsigned*)(registers[PC]+8); - break; - case OP_BNE: - case OP_BNEL: - if (registers[inst.IType.rs] != registers[inst.IType.rt]) - instrBuffer.targetAddr = - (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4)); - else - instrBuffer.targetAddr = (unsigned*)(registers[PC]+8); - break; - case OP_BLEZ: - case OP_BLEZL: - if (registers[inst.IType.rs] <= 0) - instrBuffer.targetAddr = - (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4)); - else - instrBuffer.targetAddr = (unsigned*)(registers[PC]+8); - break; - case OP_BGTZ: - case OP_BGTZL: - if (registers[inst.IType.rs] > 0) - instrBuffer.targetAddr = - (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4)); - else - instrBuffer.targetAddr = (unsigned*)(registers[PC]+8); - break; - - case OP_COP1: - if (inst.RType.rs == OP_BC) - switch (inst.RType.rt) { - case COPz_BCF: - case COPz_BCFL: - if (registers[FCSR] & CSR_C) - instrBuffer.targetAddr = (unsigned*)(registers[PC]+8); - else - instrBuffer.targetAddr = - (unsigned *)(((signed short)inst.IType.imm<<2) - + (registers[PC]+4)); - break; - case COPz_BCT: - case COPz_BCTL: - if (registers[FCSR] & CSR_C) - instrBuffer.targetAddr = - (unsigned *)(((signed short)inst.IType.imm<<2) - + (registers[PC]+4)); - else - instrBuffer.targetAddr = (unsigned*)(registers[PC]+8); - break; - }; - break; - } - - if( is_steppable((unsigned)instrBuffer.targetAddr) && *(instrBuffer.targetAddr) != BREAK_INSTR ) - { - instrBuffer.savedInstr = *instrBuffer.targetAddr; - *instrBuffer.targetAddr = BREAK_INSTR; - } - else - { - instrBuffer.targetAddr = NULL; - instrBuffer.savedInstr = NOP_INSTR; - } - return; -} - - -/* - * Translate the R4600 exception code into a Unix-compatible signal. - */ -static int -computeSignal (void) -{ - int exceptionCode = (registers[CAUSE] & CAUSE_EXCMASK) >> CAUSE_EXCSHIFT; - - switch (exceptionCode) - { - case EXC_INT: - /* External interrupt */ - return SIGINT; - - case EXC_RI: - /* Reserved instruction */ - case EXC_CPU: - /* Coprocessor unusable */ - return SIGILL; - - case EXC_BP: - /* Break point */ - return SIGTRAP; - - case EXC_OVF: - /* Arithmetic overflow */ - case EXC_TRAP: - /* Trap exception */ - case EXC_FPE: - /* Floating Point Exception */ - return SIGFPE; - - case EXC_IBE: - /* Bus error (Ifetch) */ - case EXC_DBE: - /* Bus error (data load or store) */ - return SIGBUS; - - case EXC_MOD: - /* TLB modification exception */ - case EXC_TLBL: - /* TLB miss (Load or Ifetch) */ - case EXC_TLBS: - /* TLB miss (Store) */ - case EXC_ADEL: - /* Address error (Load or Ifetch) */ - case EXC_ADES: - /* Address error (Store) */ - return SIGSEGV; - - case EXC_SYS: - /* System call */ - return SIGSYS; - - default: - return SIGTERM; - } -} - -/* - * This support function prepares and sends the message containing the - * basic information about this exception. - */ -static void gdb_stub_report_exception_info( - rtems_vector_number vector, - CPU_Interrupt_frame *frame, - int thread -) -{ - char *optr; - int sigval; - - optr = outBuffer; - *optr++ = 'T'; - sigval = computeSignal (); - *optr++ = highhex (sigval); - *optr++ = lowhex (sigval); - - *optr++ = highhex(SP); /*gdb_hexchars[SP]; */ - *optr++ = lowhex(SP); - *optr++ = ':'; - optr = mem2hstr(optr, (unsigned char *)&frame->sp, R_SZ ); - *optr++ = ';'; - - *optr++ = highhex(PC); /*gdb_hexchars[PC]; */ - *optr++ = lowhex(PC); - *optr++ = ':'; - optr = mem2hstr(optr, (unsigned char *)&frame->epc, R_SZ ); - *optr++ = ';'; - -#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) - if (do_threads) - { - *optr++ = 't'; - *optr++ = 'h'; - *optr++ = 'r'; - *optr++ = 'e'; - *optr++ = 'a'; - *optr++ = 'd'; - *optr++ = ':'; - optr = thread2vhstr(optr, thread); - *optr++ = ';'; - } -#endif - *optr++ = '\0'; -} - - - -/* - * Scratch frame used to retrieve contexts for different threads, so as - * not to disrupt our current context on the stack - */ -CPU_Interrupt_frame current_thread_registers; - -/* - * This function handles all exceptions. It only does two things: - * it figures out why it was activated and tells gdb, and then it - * reacts to gdb's requests. - */ - -extern void clear_cache(void); -void handle_exception (rtems_vector_number vector, CPU_Interrupt_frame *frame) -{ - int host_has_detached = 0; - int regno, addr, length; - char *ptr; - int current_thread; /* current generic thread */ - int thread; /* stopped thread: context exception happened in */ - - long long regval; - void *regptr; - int binary; - - registers = (mips_register_t *)frame; - - thread = 0; -#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) - if (do_threads) { - thread = rtems_gdb_stub_get_current_thread(); - } -#endif - current_thread = thread; - - { - /* reapply all breakpoints regardless of how we came in */ - struct z0break *z0, *zother; - - for (zother=z0break_list; zother!=NULL; zother=zother->next) - { - if( zother->instr == 0xffffffff ) - { - /* grab the instruction */ - zother->instr = *(zother->address); - /* and insert the breakpoint */ - *(zother->address) = BREAK_INSTR; - } - } - - /* see if we're coming from a breakpoint */ - if( *((unsigned *)frame->epc) == BREAK_INSTR ) - { - /* see if its one of our zbreaks */ - for (z0=z0break_list; z0!=NULL; z0=z0->next) - { - if( (unsigned)z0->address == frame->epc) - break; - } - if( z0 ) - { - /* restore the original instruction */ - *(z0->address) = z0->instr; - /* flag the breakpoint */ - z0->instr = 0xffffffff; - - /* - now when we return, we'll execute the original code in - the original state. This leaves our breakpoint inactive - since the break instruction isn't there, but we'll reapply - it the next time we come in via step or breakpoint - */ - } - else - { - /* not a zbreak, see if its our trusty stepping code */ - - /* - * Restore the saved instruction at - * the single-step target address. - */ - undoSStep(); - } - } - } - - /* reply to host that an exception has occurred with some basic info */ - gdb_stub_report_exception_info(vector, frame, thread); - putpacket (outBuffer); - - while (!(host_has_detached)) { - outBuffer[0] = '\0'; - getpacket (inBuffer); - binary = 0; - - switch (inBuffer[0]) { - case '?': - gdb_stub_report_exception_info(vector, frame, thread); - break; - - case 'd': /* toggle debug flag */ - /* can print ill-formed commands in valid packets & checksum errors */ - break; - - case 'D': - /* remote system is detaching - return OK and exit from debugger */ - strcpy (outBuffer, "OK"); - host_has_detached = 1; - break; - - case 'g': /* return the values of the CPU registers */ - regptr = registers; -#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) - if (do_threads && current_thread != thread ) - regptr = ¤t_thread_registers; -#endif - mem2hex (regptr, NUM_REGS * (sizeof registers), outBuffer); - break; - - case 'G': /* set the values of the CPU registers - return OK */ - regptr = registers; -#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) - if (do_threads && current_thread != thread ) - regptr = ¤t_thread_registers; -#endif - if (hex2mem (&inBuffer[1], regptr, NUM_REGS * (sizeof registers))) - strcpy (outBuffer, "OK"); - else - strcpy (outBuffer, "E00"); /* E00 = bad "set register" command */ - break; - - case 'P': - /* Pn...=r... Write register n... with value r... - return OK */ - ptr = &inBuffer[1]; - if (hexToInt(&ptr, ®no) && - *ptr++ == '=' && - hexToLongLong(&ptr, ®val)) - { - registers[regno] = regval; - strcpy (outBuffer, "OK"); - } - else - strcpy (outBuffer, "E00"); /* E00 = bad "set register" command */ - break; - - case 'm': - /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ - ptr = &inBuffer[1]; - if (hexToInt (&ptr, &addr) - && *ptr++ == ',' - && hexToInt (&ptr, &length) - && is_readable (addr, length) - && (length < (BUFMAX - 4)/2)) - mem2hex ((void *)addr, length, outBuffer); - else - strcpy (outBuffer, "E01"); /* E01 = bad 'm' command */ - break; - - case 'X': /* XAA..AA,LLLL:#cs */ - binary = 1; - case 'M': - /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA - return OK */ - ptr = &inBuffer[1]; - if (hexToInt (&ptr, &addr) - && *ptr++ == ',' - && hexToInt (&ptr, &length) - && *ptr++ == ':' - && is_writeable (addr, length) ) { - if ( binary ) - hex2mem (ptr, (void *)addr, length); - else - bin2mem (ptr, (void *)addr, length); - strcpy (outBuffer, "OK"); - } - else - strcpy (outBuffer, "E02"); /* E02 = bad 'M' command */ - break; - - case 'c': - /* cAA..AA Continue at address AA..AA(optional) */ - case 's': - /* sAA..AA Step one instruction from AA..AA(optional) */ - { - /* try to read optional parameter, pc unchanged if no parm */ - ptr = &inBuffer[1]; - if (hexToInt (&ptr, &addr)) - registers[PC] = addr; - - if (inBuffer[0] == 's') - doSStep (); - } - goto stubexit; - - case 'k': /* remove all zbreaks if any */ - dumpzbreaks: - { - { - /* Unlink the entire list */ - struct z0break *z0, *znxt; - - while( (z0= z0break_list) ) - { - - /* put back the instruction */ - if( z0->instr != 0xffffffff ) - *(z0->address) = z0->instr; - - /* pop off the top entry */ - znxt = z0->next; - if( znxt ) znxt->prev = NULL; - z0break_list = znxt; - - /* and put it on the free list */ - z0->prev = NULL; - z0->next = z0break_avail; - z0break_avail = z0; - } - } - - strcpy(outBuffer, "OK"); - } - break; - - case 'q': /* queries */ -#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) - rtems_gdb_process_query( inBuffer, outBuffer, do_threads, thread ); -#endif - break; - -#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) - case 'T': - { - int testThread; - - if( vhstr2thread(&inBuffer[1], &testThread) == NULL ) - { - strcpy(outBuffer, "E01"); - break; - } - - if( rtems_gdb_index_to_stub_id(testThread) == NULL ) - { - strcpy(outBuffer, "E02"); - } - else - { - strcpy(outBuffer, "OK"); - } - } - break; -#endif - - case 'H': /* set new thread */ -#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) - if (inBuffer[1] != 'g') { - break; - } - - if (!do_threads) { - break; - } - - { - int tmp, ret; - - /* Set new generic thread */ - if (vhstr2thread(&inBuffer[2], &tmp) == NULL) { - strcpy(outBuffer, "E01"); - break; - } - - /* 0 means `thread' */ - if (tmp == 0) { - tmp = thread; - } - - if (tmp == current_thread) { - /* No changes */ - strcpy(outBuffer, "OK"); - break; - } - - /* Save current thread registers if necessary */ - if (current_thread != thread) { - ret = rtems_gdb_stub_set_thread_regs( - current_thread, - (unsigned int *) (void *)¤t_thread_registers); - ASSERT(ret); - } - - /* Read new registers if necessary */ - if (tmp != thread) { - ret = rtems_gdb_stub_get_thread_regs( - tmp, (unsigned int *) (void *)¤t_thread_registers); - - if (!ret) { - /* Thread does not exist */ - strcpy(outBuffer, "E02"); - break; - } - } - - current_thread = tmp; - strcpy(outBuffer, "OK"); - } -#endif - break; - - case 'Z': /* Add breakpoint */ - { - int ret, type, len; - unsigned char *address; - struct z0break *z0; - - ret = parse_zbreak(inBuffer, &type, &address, &len); - if (!ret) { - strcpy(outBuffer, "E01"); - break; - } - - if (type != 0) { - /* We support only software break points so far */ - strcpy(outBuffer, "E02"); - break; - } - - if (len != R_SZ) { /* was 1 */ - strcpy(outBuffer, "E03"); - break; - } - - /* Let us check whether this break point already set */ - for (z0=z0break_list; z0!=NULL; z0=z0->next) { - if (z0->address == address) { - break; - } - } - - if (z0 != NULL) { - /* we already have a breakpoint for this address */ - strcpy(outBuffer, "E04"); - break; - } - - /* Let us allocate new break point */ - if (z0break_avail == NULL) { - strcpy(outBuffer, "E05"); - break; - } - - /* Get entry */ - z0 = z0break_avail; - z0break_avail = z0break_avail->next; - - /* Let us copy memory from address add stuff the break point in */ - /* - *if (mem2hstr(z0->buf, address, 1) == NULL || - !hstr2mem(address, "cc" , 1)) { - - * Memory error * - z0->next = z0break_avail; - z0break_avail = z0; - strcpy(outBuffer, "E05"); - break; - }*/ - - /* Fill it */ - z0->address = address; - - if( z0->address == (unsigned char *) frame->epc ) - { - /* re-asserting the breakpoint that put us in here, so - we'll add the breakpoint but leave the code in place - since we'll be returning to it when the user continues */ - z0->instr = 0xffffffff; - } - else - { - /* grab the instruction */ - z0->instr = *(z0->address); - /* and insert the break */ - *(z0->address) = BREAK_INSTR; - } - - /* Add to the list */ - { - struct z0break *znxt = z0break_list; - - z0->prev = NULL; - z0->next = znxt; - - if( znxt ) znxt->prev = z0; - z0break_list = z0; - } - - strcpy(outBuffer, "OK"); - } - break; - - case 'z': /* remove breakpoint */ - if (inBuffer[1] == 'z') - { - goto dumpzbreaks; - - /* - * zz packet - remove all breaks * - z0last = NULL; - - for (z0=z0break_list; z0!=NULL; z0=z0->next) - { - if(!hstr2mem(z0->address, z0->buf, R_SZ)) - { - ret = 0; - } - z0last = z0; - } - - * Free entries if any * - if (z0last != NULL) { - z0last->next = z0break_avail; - z0break_avail = z0break_list; - z0break_list = NULL; - } - - if (ret) { - strcpy(outBuffer, "OK"); - } else { - strcpy(outBuffer, "E04"); - } - break; - */ - } - else - { - int ret, type, len; - unsigned char *address; - struct z0break *z0; - - ret = parse_zbreak(inBuffer, &type, &address, &len); - if (!ret) { - strcpy(outBuffer, "E01"); - break; - } - - if (type != 0) { - /* We support only software break points so far */ - break; - } - - if (len != R_SZ) { - strcpy(outBuffer, "E02"); - break; - } - - /* Let us check whether this break point set */ - for (z0=z0break_list; z0!=NULL; z0=z0->next) { - if (z0->address == address) { - break; - } - } - - if (z0 == NULL) { - /* Unknown breakpoint */ - strcpy(outBuffer, "E03"); - break; - } - - /* - if (!hstr2mem(z0->address, z0->buf, R_SZ)) { - strcpy(outBuffer, "E04"); - break; - }*/ - - if( z0->instr != 0xffffffff ) - { - /* put the old instruction back */ - *(z0->address) = z0->instr; - } - - /* Unlink entry */ - { - struct z0break *zprv = z0->prev, *znxt = z0->next; - - if( zprv ) zprv->next = znxt; - if( znxt ) znxt->prev = zprv; - - if( !zprv ) z0break_list = znxt; - - znxt = z0break_avail; - - z0break_avail = z0; - z0->prev = NULL; - z0->next = znxt; - } - - strcpy(outBuffer, "OK"); - } - break; - - default: /* do nothing */ - break; - } - - /* reply to the request */ - putpacket (outBuffer); - } - - stubexit: - - /* - * The original code did this in the assembly wrapper. We should consider - * doing it here before we return. - * - * On exit from the exception handler invalidate each line in the I-cache - * and write back each dirty line in the D-cache. This needs to be done - * before the target program is resumed in order to ensure that software - * breakpoints and downloaded code will actually take effect. This - * is because modifications to code in ram will affect the D-cache, - * but not necessarily the I-cache. - */ - - clear_cache(); -} - -static int numsegs; -static struct memseg memsegments[NUM_MEMSEGS]; - -int gdbstub_add_memsegment( unsigned base, unsigned end, int opts ) -{ - if( numsegs == NUM_MEMSEGS ) return -1; - - memsegments[numsegs].begin = base; - memsegments[numsegs].end = end; - memsegments[numsegs].opts = opts; - - ++numsegs; - return RTEMS_SUCCESSFUL; -} - -static int is_readable(unsigned ptr, unsigned len) -{ - struct memseg *ms; - int i; - - if( (ptr & 0x3) ) return -1; - - for(i=0; ibegin <= ptr && ptr+len <= ms->end && (ms->opts & MEMOPT_READABLE) ) - return -1; - } - return 0; -} - -static int is_writeable(unsigned ptr, unsigned len) -{ - struct memseg *ms; - int i; - - if( (ptr & 0x3) ) return -1; - - for(i=0; ibegin <= ptr && ptr+len <= ms->end && (ms->opts & MEMOPT_WRITEABLE) ) - return -1; - } - return 0; -} - -static int is_steppable(unsigned ptr) -{ - struct memseg *ms; - int i; - - if( (ptr & 0x3) ) return -1; - - for(i=0; ibegin <= ptr && ptr <= ms->end && (ms->opts & MEMOPT_WRITEABLE) ) - return -1; - } - return 0; -} - -static char initialized = 0; /* 0 means we are not initialized */ - -void mips_gdb_stub_install(int enableThreads) -{ - /* - These are the RTEMS-defined vectors for all the MIPS exceptions - */ - int exceptionVector[]= { MIPS_EXCEPTION_MOD, \ - MIPS_EXCEPTION_TLBL, \ - MIPS_EXCEPTION_TLBS, \ - MIPS_EXCEPTION_ADEL, \ - MIPS_EXCEPTION_ADES, \ - MIPS_EXCEPTION_IBE, \ - MIPS_EXCEPTION_DBE, \ - MIPS_EXCEPTION_SYSCALL, \ - MIPS_EXCEPTION_BREAK, \ - MIPS_EXCEPTION_RI, \ - MIPS_EXCEPTION_CPU, \ - MIPS_EXCEPTION_OVERFLOW, \ - MIPS_EXCEPTION_TRAP, \ - MIPS_EXCEPTION_VCEI, \ - MIPS_EXCEPTION_FPE, \ - MIPS_EXCEPTION_C2E, \ - MIPS_EXCEPTION_WATCH, \ - MIPS_EXCEPTION_VCED, \ - -1 }; - int i; - rtems_isr_entry old; - - if (initialized) - { - ASSERT(0); - return; - } - - memset( memsegments,0,sizeof(struct memseg)*NUM_MEMSEGS ); - numsegs = 0; - -#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) - if( enableThreads ) - do_threads = 1; - else - do_threads = 0; -#endif - - { - struct z0break *z0; - - z0break_avail = NULL; - z0break_list = NULL; - - /* z0breaks list init, now we'll do it so it makes sense... */ - for (i=0; inext = z0break_avail; - z0break_avail = z0; - } - } - - for(i=0; exceptionVector[i] > -1; i++) - { - rtems_interrupt_catch( (rtems_isr_entry) handle_exception, exceptionVector[i], &old ); - } - - initialized = 1; - - /* get the attention of gdb */ - /* mips_break(1); disabled so user code can choose to invoke it or not */ -} diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/mips_opcode.h b/c/src/lib/libbsp/mips/shared/gdbstub/mips_opcode.h deleted file mode 100644 index 883b1f174b..0000000000 --- a/c/src/lib/libbsp/mips/shared/gdbstub/mips_opcode.h +++ /dev/null @@ -1,336 +0,0 @@ -/** - * @file - * @ingroup - * @brief Instruction formats and opcode values for MIPS - */ - -/* - * Copyright (c) 1992 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)mips_opcode.h 7.1 (Berkeley) 3/19/92 - * via: mips_opcode.h,v 1.1 1994/03/10 16:15:10 (algorithmics) - */ - -/* - * Define the instruction formats and opcode values for the - * MIPS instruction set. - */ - -#ifndef _MIPS_OPCODE_H -#define _MIPS_OPCODE_H - -/** - * @defgroup mips_ops MIPS Opcodes - * @ingroup mips_shared - * @brief MIPS Instruction Formats and Opcode Values - * @{ - */ - -/** - * @name Instruction formats - * @{ - */ - -typedef union { - unsigned word; - -#ifdef MIPSEL - struct { - unsigned imm: 16; - unsigned rt: 5; - unsigned rs: 5; - unsigned op: 6; - } IType; - - struct { - unsigned target: 26; - unsigned op: 6; - } JType; - - struct { - unsigned func: 6; - unsigned shamt: 5; - unsigned rd: 5; - unsigned rt: 5; - unsigned rs: 5; - unsigned op: 6; - } RType; - - struct { - unsigned func: 6; - unsigned fd: 5; - unsigned fs: 5; - unsigned ft: 5; - unsigned fmt: 4; - unsigned : 1; /* always '1' */ - unsigned op: 6; /* always '0x11' */ - } FRType; -#else - struct { - unsigned op: 6; - unsigned rs: 5; - unsigned rt: 5; - unsigned imm: 16; - } IType; - - struct { - unsigned op: 6; - unsigned target: 26; - } JType; - - struct { - unsigned op: 6; - unsigned rs: 5; - unsigned rt: 5; - unsigned rd: 5; - unsigned shamt: 5; - unsigned func: 6; - } RType; - - struct { - unsigned op: 6; /* always '0x11' */ - unsigned : 1; /* always '1' */ - unsigned fmt: 4; - unsigned func: 6; - unsigned ft: 5; - unsigned fs: 5; - unsigned fd: 5; - } FRType; -#endif -} InstFmt; - -/** @} */ - -/** - * @name 'op' field values - * @{ - */ - -#define OP_SPECIAL 000 -#define OP_REGIMM 001 -#define OP_J 002 -#define OP_JAL 003 -#define OP_BEQ 004 -#define OP_BNE 005 -#define OP_BLEZ 006 -#define OP_BGTZ 007 - -#define OP_ADDI 010 -#define OP_ADDIU 011 -#define OP_SLTI 012 -#define OP_SLTIU 013 -#define OP_ANDI 014 -#define OP_ORI 015 -#define OP_XORI 016 -#define OP_LUI 017 - -#define OP_COP0 020 -#define OP_COP1 021 -#define OP_COP2 022 -#define OP_BEQL 024 -#define OP_BNEL 025 -#define OP_BLEZL 026 -#define OP_BGTZL 027 - -#define OP_DADDI 030 -#define OP_DADDIU 031 -#define OP_LDL 032 -#define OP_LDR 033 - -#define OP_LB 040 -#define OP_LH 041 -#define OP_LWL 042 -#define OP_LW 043 -#define OP_LBU 044 -#define OP_LHU 045 -#define OP_LWR 046 -#define OP_LWU 047 - -#define OP_SB 050 -#define OP_SH 051 -#define OP_SWL 052 -#define OP_SW 053 -#define OP_SDL 054 -#define OP_SDR 055 -#define OP_SWR 056 -#define OP_CACHE 057 - -#define OP_LL 060 -#define OP_LWC1 061 -#define OP_LWC2 062 -#define OP_LLD 064 -#define OP_LDC1 065 -#define OP_LDC2 066 -#define OP_LD 067 - -#define OP_SC 070 -#define OP_SWC1 071 -#define OP_SWC2 072 -#define OP_SCD 074 -#define OP_SDC1 075 -#define OP_SDC2 076 -#define OP_SD 077 - -/** - * @name 'func' field values when 'op' == OP_SPECIAL. - * @{ - */ - -#define OP_SLL 000 -#define OP_SRL 002 -#define OP_SRA 003 -#define OP_SLLV 004 -#define OP_SRLV 006 -#define OP_SRAV 007 - -#define OP_JR 010 -#define OP_JALR 011 -#define OP_SYSCALL 014 -#define OP_BREAK 015 -#define OP_SYNC 017 - -#define OP_MFHI 020 -#define OP_MTHI 021 -#define OP_MFLO 022 -#define OP_MTLO 023 -#define OP_DSLLV 024 -#define OP_DSRLV 026 -#define OP_DSRAV 027 - -#define OP_MULT 030 -#define OP_MULTU 031 -#define OP_DIV 032 -#define OP_DIVU 033 -#define OP_DMULT 034 -#define OP_DMULTU 035 -#define OP_DDIV 036 -#define OP_DDIVU 037 - -#define OP_ADD 040 -#define OP_ADDU 041 -#define OP_SUB 042 -#define OP_SUBU 043 -#define OP_AND 044 -#define OP_OR 045 -#define OP_XOR 046 -#define OP_NOR 047 - -#define OP_SLT 052 -#define OP_SLTU 053 -#define OP_DADD 054 -#define OP_DADDU 055 -#define OP_DSUB 056 -#define OP_DSUBU 057 - -#define OP_TGE 060 -#define OP_TGEU 061 -#define OP_TLT 062 -#define OP_TLTU 063 -#define OP_TEQ 064 -#define OP_TNE 066 - -#define OP_DSLL 070 -#define OP_DSRL 072 -#define OP_DSRA 073 -#define OP_DSLL32 074 -#define OP_DSRL32 076 -#define OP_DSRA32 077 - -/** @} */ - -/** - * 'func' field values when 'op' == OP_REGIMM. - * @{ - */ - -#define OP_BLTZ 000 -#define OP_BGEZ 001 -#define OP_BLTZL 002 -#define OP_BGEZL 003 - -#define OP_TGEI 010 -#define OP_TGEIU 011 -#define OP_TLTI 012 -#define OP_TLTIU 013 -#define OP_TEQI 014 -#define OP_TNEI 016 - -#define OP_BLTZAL 020 -#define OP_BGEZAL 021 -#define OP_BLTZALL 022 -#define OP_BGEZALL 023 - -/** @} */ - -/** - * @name 'rs' field values when 'op' == OP_COPz. - * @{ - */ - -#define OP_MF 000 -#define OP_DMF 001 -#define OP_CF 002 -#define OP_MT 004 -#define OP_DMT 005 -#define OP_CT 006 -#define OP_BC 010 - -/** @} */ - -/** - * @name 'rt' field values when 'op' == OP_COPz and 'rt' == OP_BC. - * @{ - */ - -#define COPz_BCF 0x00 -#define COPz_BCT 0x01 -#define COPz_BCFL 0x02 -#define COPz_BCTL 0x03 - -/** @} */ - -/** - * @name Instructions with specal significance to debuggers. - * @{ - */ - -#define BREAK_INSTR 0x0000000d ///< @brief instruction code for break -#define NOP_INSTR 0x00000000 ///< @brief instruction code for no-op - -/** @} */ - -/** @} */ - -#endif /* _MIPS_OPCODE_H */ -- cgit v1.2.3