From fc82e7107274789c558a8a4fbc3a4d210edec672 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Fri, 8 Feb 2002 21:26:00 +0000 Subject: 2002-02-08 Joel Sherrill * Makefile, stubinit.S, r46kstub.ld, ioaddr.h: Removed as unused with RTEMS. * r46kstub.c: Renamed to mips-stub.c. * mips-stub.c: New file -- was r46kstub.c. * memlimits.h: New file was limits.h. * limits.h: Removed. * r4600.h: Eliminated need for this file. * README: Updated. * gdb_if.h: Added CVS Id. * mips-stub.c: Attempt to deal with MIPS1 versus MIPS3. --- c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog | 13 + c/src/lib/libbsp/mips/shared/gdbstub/Makefile | 38 - c/src/lib/libbsp/mips/shared/gdbstub/README | 35 +- c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h | 4 +- c/src/lib/libbsp/mips/shared/gdbstub/ioaddr.h | 113 --- c/src/lib/libbsp/mips/shared/gdbstub/limits.h | 70 -- c/src/lib/libbsp/mips/shared/gdbstub/memlimits.h | 70 ++ c/src/lib/libbsp/mips/shared/gdbstub/mips-stub.c | 910 +++++++++++++++++++++++ c/src/lib/libbsp/mips/shared/gdbstub/r4600.h | 372 --------- c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c | 844 --------------------- c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.ld | 53 -- c/src/lib/libbsp/mips/shared/gdbstub/stubinit.S | 616 --------------- 12 files changed, 1022 insertions(+), 2116 deletions(-) delete mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/Makefile delete mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/ioaddr.h delete mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/limits.h create mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/memlimits.h create mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/mips-stub.c delete mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/r4600.h delete mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c delete mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.ld delete mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/stubinit.S (limited to 'c') diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog b/c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog index 10f6c048d7..1fd3679b3f 100644 --- a/c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog +++ b/c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog @@ -1,3 +1,16 @@ +2002-02-08 Joel Sherrill + + * Makefile, stubinit.S, r46kstub.ld, ioaddr.h: Removed as unused + with RTEMS. + * r46kstub.c: Renamed to mips-stub.c. + * mips-stub.c: New file -- was r46kstub.c. + * memlimits.h: New file was limits.h. + * limits.h: Removed. + * r4600.h: Eliminated need for this file. + * README: Updated. + * gdb_if.h: Added CVS Id. + * mips-stub.c: Attempt to deal with MIPS1 versus MIPS3. + 2002-02-08 Joel Sherrill * Merged r46kstub.c into RTEMS distribution without modification. diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/Makefile b/c/src/lib/libbsp/mips/shared/gdbstub/Makefile deleted file mode 100644 index 9057011b4e..0000000000 --- a/c/src/lib/libbsp/mips/shared/gdbstub/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -CC = mips64orion-idt-elf-gcc -CFLAGS = -g -Wa,-ahld -Wall -membedded-data -O3 -AS = mips64orion-idt-elf-as -ASFLAGS = -ahld -LD = mips64orion-idt-elf-ld -LDFLAGS = -t -s - -# Inference rules - -.SUFFIXES: $(SUFFIXES) .out .ld - -.ld.out: - $(LD) $(LDFLAGS) -T $< -Map $*.map -o $*.out -.c.o: - $(CC) $(CFLAGS) -c $< >$*.L - -.S.o: - $(CC) $(CFLAGS) -c $< >$*.L - -.s.o: - $(AS) $(ASFLAGS) -o $*.o $< >$*.L - -# Targets - -r46kstub.hex: r46kstub.out - mips64orion-idt-elf-objcopy -S -R .bss -R .data -R .reginfo \ - -O srec r46kstub.out r46kstub.hex - -clean: - rm -f *.L *.map *.o *.out *.hex - -# Dependencies - -r46kstub.out: r46kstub.ld r46kstub.o stubinit.o - -r46kstub.o: mips_opcode.h r4600.h limits.h gdb_if.h r46kstub.c - -stubinit.o: r4600.h ioaddr.h gdb_if.h stubinit.S diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/README b/c/src/lib/libbsp/mips/shared/gdbstub/README index 3550a2ad29..f1ce5db96d 100644 --- a/c/src/lib/libbsp/mips/shared/gdbstub/README +++ b/c/src/lib/libbsp/mips/shared/gdbstub/README @@ -1,7 +1,29 @@ -/* r46kstub 9/29/96 c. m. heard */ -/* 7/26/96 -- original posting */ -/* 8/06/96 -- cache initialization/flushing logic fixed */ -/* 9/29/96 -- coprocessor load delay slots respected, documentation improved */ +# +# $Id$ +# + + +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 @@ -108,8 +130,3 @@ 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: - -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 diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h b/c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h index cc7d0b72fe..14b9abf4d8 100644 --- a/c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h +++ b/c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h @@ -10,13 +10,15 @@ * 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. + * + * $Id$ */ #ifndef _GDB_IF_H #define _GDB_IF_H /* - * R4600 registers, numbered in the order in which gdb expects to see them. + * MIPS registers, numbered in the order in which gdb expects to see them. */ #define ZERO 0 #define AT 1 diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/ioaddr.h b/c/src/lib/libbsp/mips/shared/gdbstub/ioaddr.h deleted file mode 100644 index 7533abf5de..0000000000 --- a/c/src/lib/libbsp/mips/shared/gdbstub/ioaddr.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * ioaddr.h - 16C450 serial port memory-mapped I/O address definitions - * - * 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 _IOADDR_H -#define _IOADDR_H - -/* - * The following addresses are implementation-specific. - * Note that big-endian memory addressing is assumed. - */ -#define ISA_IO_BASE 0xb8000000 -#define BYTE_IO(ioaddr) ((ioaddr<<3)+7) -#define WORD_IO(ioaddr) ((ioaddr<<3)+6) - -#define ISA_IRQ9_RESET 0xb8043000 -#define ISA_IRQ5_RESET 0xb8042000 -#define ISA_IRQ4_RESET 0xb8041000 -#define ISA_IRQ3_RESET 0xb8040000 -#define ISA_IRQ_STATUS 0xb8040000 - -/* ISA IRQ Status Register fields */ -#define ISA_IRQ9_STATUS 0x08 -#define ISA_IRQ5_STATUS 0x04 -#define ISA_IRQ4_STATUS 0x02 -#define ISA_IRQ3_STATUS 0x01 - -/* - * Serial Port 1 (COM1) I/O Addresses. These definitions - * follows the standard IBM AT I/O address assignments. - * Note that IRQ4 is normally assigned to serial port 1. - */ -#define DIV_LO_COM1 BYTE_IO(0x3f8) /* Div latch lo (line ctl bit 7 = 1) */ -#define DIV_HI_COM1 BYTE_IO(0x3f9) /* Div latch hi (line ctl bit 7 = 1) */ -#define DATA_REG_COM1 BYTE_IO(0x3f8) /* TX Buf (write)/RX Buf (read) */ -#define INT_ENA_COM1 BYTE_IO(0x3f9) /* Interrupt Enable Register */ -#define INT_ID_COM1 BYTE_IO(0x3fa) /* Interrupt ID Register */ -#define LINE_CTL_COM1 BYTE_IO(0x3fb) /* Line Control Register */ -#define MODEM_CTL_COM1 BYTE_IO(0x3fc) /* Modem Control Register */ -#define LINE_STS_COM1 BYTE_IO(0x3fd) /* Line Status Register */ -#define MODEM_STS_COM1 BYTE_IO(0x3fe) /* Modem Status Register */ - -/* - * Serial Port 2 (COM1) I/O Addresses. These definitions - * follows the standard IBM AT I/O address assignments. - * Note that IRQ3 is normally assigned to serial port 2. - */ -#define DIV_LO_COM2 BYTE_IO(0x2f8) /* Div latch lo (line ctl bit 7 = 1) */ -#define DIV_HI_COM2 BYTE_IO(0x2f9) /* Div latch hi (line ctl bit 7 = 1) */ -#define DATA_REG_COM2 BYTE_IO(0x2f8) /* TX Buf (write)/RX Buf (read) */ -#define INT_ENA_COM2 BYTE_IO(0x2f9) /* Interrupt Enable Register */ -#define INT_ID_COM2 BYTE_IO(0x2fa) /* Interrupt ID Register */ -#define LINE_CTL_COM2 BYTE_IO(0x2fb) /* Line Control Register */ -#define MODEM_CTL_COM2 BYTE_IO(0x2fc) /* Modem Control Register */ -#define LINE_STS_COM2 BYTE_IO(0x2fd) /* Line Status Register */ -#define MODEM_STS_COM2 BYTE_IO(0x2fe) /* Modem Status Register */ - -/* Interrupt Enable Register fields */ -#define IENA_MODEM 0x08 -#define IENA_LINE 0x04 -#define IENA_TX 0x02 -#define IENA_RX 0x01 - -/* Interrupt Identification Register fields */ -#define INT_ID_MASK 0x06 -#define INT_PENDING 0x01 - -/* Line Control Register fields */ -#define DIV_LATCH_EN 0x80 -#define SET_BREAK 0x40 -#define STICK_PARITY 0x20 -#define EVEN_PARITY 0x10 -#define PARITY_ENA 0x08 -#define STOP_BITS 0x04 -#define WORD_LEN_MASK 0x03 - -/* Line Status Register fields */ -#define TX_SHR_EMPTY 0x40 -#define TX_BUF_EMPTY 0x20 -#define BRK_RCVD 0x10 -#define FRAMING_ERR 0x08 -#define PARITY_ERR 0x04 -#define OVRUN_ERR 0x02 -#define RX_CHAR_AVA 0x01 - -/* Modem Control Register fields */ -#define LOOPBACK 0x10 -#define OUT2 0x08 -#define OUT1 0x04 -#define RTS 0x02 -#define DTR 0x01 - -/* Modem Status Register fields */ -#define RLSD 0x80 -#define RI 0x40 -#define DSR 0x20 -#define CTS 0x10 -#define DELTA_RLSD 0x08 -#define TRAIL_EDGE_RI 0x04 -#define DELTA_DSR 0x02 -#define DELTA_CTS 0x01 - -#endif /* _IOADDR_H */ diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/limits.h b/c/src/lib/libbsp/mips/shared/gdbstub/limits.h deleted file mode 100644 index 05f82123e8..0000000000 --- a/c/src/lib/libbsp/mips/shared/gdbstub/limits.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 _LIMITS_H_ -#define _LIMITS_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. - */ - -#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)))) - -#endif /* _LIMITS_H_ */ diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/memlimits.h b/c/src/lib/libbsp/mips/shared/gdbstub/memlimits.h new file mode 100644 index 0000000000..05f82123e8 --- /dev/null +++ b/c/src/lib/libbsp/mips/shared/gdbstub/memlimits.h @@ -0,0 +1,70 @@ +/* + * 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 _LIMITS_H_ +#define _LIMITS_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. + */ + +#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)))) + +#endif /* _LIMITS_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 new file mode 100644 index 0000000000..5eb8b78355 --- /dev/null +++ b/c/src/lib/libbsp/mips/shared/gdbstub/mips-stub.c @@ -0,0 +1,910 @@ +/******************************************************************************* + + 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. + + $Id$ + +******************************************************************************** +* +* 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 "gdb_if.h" + +/***************/ +/* 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; +#elif (__mips == 1) +typedef unsigned int mips_register_t; +#else +#error "unknown MIPS ISA" +#endif +static mips_register_t *registers; + + +/* + * The following external functions provide character input and output. + */ +extern char getDebugChar (void); + +extern void putDebugChar (char); + + +/* + * 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]; + + +/* + * Convert an int to hex. + */ +static const char hexchars[] = "0123456789abcdef"; + +#define highhex(x) hexchars [(x >> 4) & 0xf] +#define lowhex(x) 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 (int addr, int length, char *buf) +{ + 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++ = 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++ = 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++ = 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++ = 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, int addr, int length) +{ + 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; +} + + +/* + * 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); +} + + +/* + * 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 (getDebugChar () != '+'); +} + + +/* + * 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 (instrBuffer.targetAddr) + { + 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 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. + */ +void +handle_exception (CPU_Interrupt_frame *frame) +{ + int host_has_detached = 0; + int sigval; + int regno, addr, length; + long long regval; + char *ptr; + + registers = (mips_register_t *)frame; + + /* reply to host that an exception has occurred */ + sigval = computeSignal (); + outBuffer[0] = 'S'; + outBuffer[1] = highhex (sigval); + outBuffer[2] = lowhex (sigval); + outBuffer[3] = '\0'; + + putpacket (outBuffer); + + /* + * Restore the saved instruction at + * the single-step target address. + */ + undoSStep (); + + while (!(host_has_detached)) + { + outBuffer[0] = '\0'; + getpacket (inBuffer); + + switch (inBuffer[0]) + { + case '?': + outBuffer[0] = 'S'; + outBuffer[1] = highhex (sigval); + outBuffer[2] = lowhex (sigval); + outBuffer[3] = '\0'; + break; + + case 'd': + /* toggle debug flag */ + break; + + case 'g': + /* return the values of the CPU registers */ + mem2hex ((int) registers, sizeof registers, outBuffer); + break; + + case 'G': + /* set the values of the CPU registers - return OK */ + if (hex2mem (&inBuffer[1], (int) registers, 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 (addr, length, outBuffer); + else + strcpy (outBuffer, "E01"); /* E01 = bad 'm' command */ + break; + + 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) + && hex2mem (ptr, 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 (); + } + return; + + case 'D': + /* remote system is detaching - return OK and exit from debugger */ + strcpy (outBuffer, "OK"); + host_has_detached = 1; + break; + + default: + /* do nothing */ + break; + } /* switch */ + + /* reply to the request */ + putpacket (outBuffer); + } + return; +} diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/r4600.h b/c/src/lib/libbsp/mips/shared/gdbstub/r4600.h deleted file mode 100644 index 14c1353a2d..0000000000 --- a/c/src/lib/libbsp/mips/shared/gdbstub/r4600.h +++ /dev/null @@ -1,372 +0,0 @@ -/* - * r4600.h - register and address space definitions for the R4600 processor - * - * 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 _R4600_H -#define _R4600_H - -/* - * R4600 general registers - */ -#define zero $0 -#define at $1 /* assembler temporary */ -#define v0 $2 /* value holders */ -#define v1 $3 -#define a0 $4 /* arguments */ -#define a1 $5 -#define a2 $6 -#define a3 $7 -#define t0 $8 /* temporaries */ -#define t1 $9 -#define t2 $10 -#define t3 $11 -#define t4 $12 -#define t5 $13 -#define t6 $14 -#define t7 $15 -#define s0 $16 /* saved registers */ -#define s1 $17 -#define s2 $18 -#define s3 $19 -#define s4 $20 -#define s5 $21 -#define s6 $22 -#define s7 $23 -#define t8 $24 /* temporaries */ -#define t9 $25 -#define k0 $26 /* kernel registers */ -#define k1 $27 -#define gp $28 /* global pointer */ -#define sp $29 /* stack pointer */ -#define s8 $30 /* saved register */ -#define fp $30 /* frame pointer (obsolete usage) */ -#define ra $31 /* return address */ - - -/* - * Kernel address space definitions (32 bit/64 bit compatibility spaces) - */ -#define K0BASE 0x80000000 -#define K0SIZE 0x20000000 -#define K1BASE 0xa0000000 -#define K1SIZE 0x20000000 - -#define PHYS_TO_K0(pa) ((pa)|K0BASE) -#define PHYS_TO_K1(pa) ((pa)|K1BASE) -#define K0_TO_PHYS(va) ((va)&(K0SIZE-1)) -#define K1_TO_PHYS(va) ((va)&(K1SIZE-1)) -#define K0_TO_K1(va) ((va)|K1SIZE) -#define K1_TO_K0(va) ((va)&~K1SIZE) - - -/* - * System Control Coprocessor (CP0) memory-management registers - */ -#define C0_INDEX $0 /* TLB Index */ -#define C0_RANDOM $1 /* TLB Random */ -#define C0_ENTRYLO0 $2 /* TLB EntryLo0 */ -#define C0_ENTRYLO1 $3 /* TLB EntryLo1 */ -#define C0_PAGEMASK $5 /* TLB PageMask */ -#define C0_WIRED $6 /* TLB Wired */ -#define C0_ENTRYHI $10 /* TLB EntryHi */ -#define C0_PRID $15 /* Processor Revision Indentifier */ -#define C0_CONFIG $16 /* Config */ -#define C0_LLADDR $17 /* LLAddr */ -#define C0_TAGLO $28 /* TagLo */ -#define C0_TAGHI $29 /* TagHi (always zero on the R4600) */ - -/* EntryHi register fields */ -#define EH_REGION_MASK 0xc000000000000000 /* 11=krnl, 01=supv, 00=user */ -#define EH_REGION_SHIFT 62 -#define EH_FILL_MASK 0x3fffff0000000000 /* (holds replica of bit 63) */ -#define EH_FILL_SHIFT 40 -#define EH_VPN2_MASK 0x000000ffffffe000 /* Virtual pageno div 2 */ -#define EH_VPN2_SHIFT 13 -#define EH_ASID_MASK 0x00000000000000ff /* Address space ID */ -#define EH_ASID_SHIFT 0 - -/* EntryLo register fields */ -#define EL_PFN_MASK 0x000000003fffffc0 /* Page Frame Number */ -#define EL_PFN_SHIFT 6 -#define EL_C_MASK 0x0000000000000038 /* Cacheability attributes */ -#define EL_C_SHIFT 3 -#define EL_D_MASK 0x0000000000000004 /* Dirty bit */ -#define EL_D_SHIFT 2 -#define EL_V_MASK 0x0000000000000002 /* Valid bit */ -#define EL_V_SHIFT 1 -#define EL_G_MASK 0x0000000000000001 /* Global bit */ -#define EL_G_SHIFT 0 - -/* PageMask register fields */ -#define PM_MASK 0x01ffe000 /* Page size mask: */ -#define PM_M_4K 0x00000000 /* 4K bytes */ -#define PM_M_16K 0x00006000 /* 16K bytes */ -#define PM_M_64K 0x0001e000 /* 64K bytes */ -#define PM_M_256K 0x0007e000 /* 256K bytes */ -#define PM_M_1M 0x001fe000 /* 1M bytes */ -#define PM_M_4M 0x007fe000 /* 4M bytes */ -#define PM_M_16M 0x01ffe000 /* 16M bytes */ - -/* Index register fields */ -#define IR_P_MASK 0x80000000 /* TLB Probe (TLBP) failure */ -#define IR_INDEX_MASK 0x0000003f /* Index of TLB entry for TLBR/TLBWI */ - -/* Random register */ -#define RR_INDEX_MASK 0x0000003f /* Index of TLB entry for TLBWR */ -#define NTLBENTRIES 48 /* Max TLB index is one less */ - -/* Wired register */ -#define WR_INDEX_MASK 0x0000003f /* Number of wired TLB entries */ - -/* PrID register fields */ -#define PRID_IMP_MASK (0xff<<8) /* Implementation number */ -#define PRID_REV_MASK (0xff<<0) /* Revision number */ - -/* Config register fields (read only except for K0 cacheability attributes) */ -#define CFG_ECMASK 0x70000000 /* System Clock Ratio: */ -#define CFG_ECBY2 0x00000000 /* processor clock divided by 2 */ -#define CFG_ECBY3 0x10000000 /* processor clock divided by 3 */ -#define CFG_ECBY4 0x20000000 /* processor clock divided by 4 */ -#define CFG_ECBY5 0x30000000 /* processor clock divided by 5 */ -#define CFG_ECBY6 0x40000000 /* processor clock divided by 6 */ -#define CFG_ECBY7 0x50000000 /* processor clock divided by 7 */ -#define CFG_ECBY8 0x60000000 /* processor clock divided by 8 */ -#define CFG_EC_RESERVED 0x70000000 /* (reserved) */ -#define CFG_EPMASK 0x0f000000 /* Writeback pattern: */ -#define CFG_EPD 0x00000000 /* DDDD (one dword every cycle) */ -#define CFG_EPDDx 0x01000000 /* DDxDDx (2 dword/3 cyc) */ -#define CFG_EPDDxx 0x02000000 /* DDxDDx (2 dword/4 cyc) */ -#define CFG_EPDxDx 0x03000000 /* DxDxDxDx (2 dword/4 cyc) */ -#define CFG_EPDDxxx 0x04000000 /* DDxxxDDxxx (2 dword/5 cyc) */ -#define CFG_EPDDxxxx 0x05000000 /* DDxxxxDDxxxx (2 dword/6 cyc) */ -#define CFG_EPDxxDxx 0x06000000 /* DxxDxxDxxDxx (2 dword/6 cyc) */ -#define CFG_EPDDxxxxx 0x07000000 /* DDxxxxxDDxxxxx (2 dword/7 cyc) */ -#define CFG_EPDDxxxxxx 0x08000000 /* DDxxxxxxDDxxxxxx (2 dword/8 cyc) */ -#define CFG_BEMASK 0x00008000 /* Big Endian */ -#define CFG_EMMASK 0x00004000 /* set to 1 => Parity mode enabled */ -#define CFG_EBMASK 0x00002000 /* set to 1 => Sub-block ordering */ -#define CFG_ICMASK 0x00000e00 /* I-cache size = 2**(12+IC) bytes */ -#define CFG_ICSHIFT 9 -#define CFG_DCMASK 0x000001c0 /* D-cache size = 2**(12+DC) bytes */ -#define CFG_DCSHIFT 6 -#define CFG_IBMASK 0x00000020 /* set to 1 => 32 byte I-cache line */ -#define CFG_DBMASK 0x00000010 /* set to 1 => 32 byte D-cache line */ -#define CFG_K0C_MASK 0x00000007 /* KSEG0 cacheability attributes: */ -#define CFG_C_WTNOALLOC 0 /* write thru, no write allocate */ -#define CFG_C_WTALLOC 1 /* write thru, write allocate */ -#define CFG_C_UNCACHED 2 /* uncached */ -#define CFG_C_WRITEBACK 3 /* writeback, non-coherent */ - - -/* Primary Cache TagLo */ -#define TAG_PTAG_MASK 0xffffff00 /* P-Cache Tag (Addr 35:12) */ -#define TAG_PTAG_SHIFT 8 -#define TAG_PSTATE_MASK 0x000000c0 /* P-Cache State */ -#define TAG_PSTATE_SHIFT 6 -#define TAG_FIFO_BIT_MASK 0x00000002 /* P-Cache FIFO bit */ -#define TAG_FIFO_BIT_SHIFT 1 -#define TAG_PARITY_MASK 0x00000001 /* P-Cache Tag Parity */ -#define TAG_PARITY_SHIFT 0 - -#define PSTATE_INVAL 0 /* Invalid */ -#define PSTATE_SHARED 1 /* Should not occur */ -#define PSTATE_CLEAN_EXCL 2 /* Should not occur */ -#define PSTATE_DIRTY_EXCL 3 /* Dirty exclusive */ - - -/* - * System Control Coprocessor (CP0) exception processing registers - */ -#define C0_CONTEXT $4 /* Context */ -#define C0_BADVADDR $8 /* Bad Virtual Address */ -#define C0_COUNT $9 /* Count */ -#define C0_COMPARE $11 /* Compare */ -#define C0_STATUS $12 /* Processor Status */ -#define C0_CAUSE $13 /* Exception Cause */ -#define C0_EPC $14 /* Exception PC */ -#define C0_XCONTEXT $20 /* XContext */ -#define C0_ECC $26 /* ECC */ -#define C0_CACHEERR $27 /* CacheErr */ -#define C0_ERROREPC $30 /* ErrorEPC */ - - -/* Status register fields */ -#define SR_CUMASK 0xf0000000 /* Coprocessor usable bits */ -#define SR_CU3 0x80000000 /* Coprocessor 3 usable */ -#define SR_CU2 0x40000000 /* coprocessor 2 usable */ -#define SR_CU1 0x20000000 /* Coprocessor 1 usable */ -#define SR_CU0 0x10000000 /* Coprocessor 0 usable */ - -#define SR_FR 0x04000000 /* Enable 32 floating-point registers */ -#define SR_RE 0x02000000 /* Reverse Endian in user mode */ - -#define SR_BEV 0x00400000 /* Bootstrap Exception Vector */ -#define SR_TS 0x00200000 /* TLB shutdown (reserved on R4600) */ -#define SR_SR 0x00100000 /* Soft Reset */ - -#define SR_CH 0x00040000 /* Cache Hit */ -#define SR_CE 0x00020000 /* ECC register modifies check bits */ -#define SR_DE 0x00010000 /* Disable cache errors */ - -#define SR_IMASK 0x0000ff00 /* Interrupt Mask */ -#define SR_IMASK8 0x00000000 /* Interrupt Mask level=8 */ -#define SR_IMASK7 0x00008000 /* Interrupt Mask level=7 */ -#define SR_IMASK6 0x0000c000 /* Interrupt Mask level=6 */ -#define SR_IMASK5 0x0000e000 /* Interrupt Mask level=5 */ -#define SR_IMASK4 0x0000f000 /* Interrupt Mask level=4 */ -#define SR_IMASK3 0x0000f800 /* Interrupt Mask level=3 */ -#define SR_IMASK2 0x0000fc00 /* Interrupt Mask level=2 */ -#define SR_IMASK1 0x0000fe00 /* Interrupt Mask level=1 */ -#define SR_IMASK0 0x0000ff00 /* Interrupt Mask level=0 */ - -#define SR_IBIT8 0x00008000 /* (Intr5) */ -#define SR_IBIT7 0x00004000 /* (Intr4) */ -#define SR_IBIT6 0x00002000 /* (Intr3) */ -#define SR_IBIT5 0x00001000 /* (Intr2) */ -#define SR_IBIT4 0x00000800 /* (Intr1) */ -#define SR_IBIT3 0x00000400 /* (Intr0) */ -#define SR_IBIT2 0x00000200 /* (Software Interrupt 1) */ -#define SR_IBIT1 0x00000100 /* (Software Interrupt 0) */ - -#define SR_KX 0x00000080 /* xtlb in kernel mode */ -#define SR_SX 0x00000040 /* mips3 & xtlb in supervisor mode */ -#define SR_UX 0x00000020 /* mips3 & xtlb in user mode */ - -#define SR_KSU_MASK 0x00000018 /* ksu mode mask */ -#define SR_KSU_USER 0x00000010 /* user mode */ -#define SR_KSU_SUPV 0x00000008 /* supervisor mode */ -#define SR_KSU_KERN 0x00000000 /* kernel mode */ - -#define SR_ERL 0x00000004 /* error level */ -#define SR_EXL 0x00000002 /* exception level */ -#define SR_IE 0x00000001 /* interrupt enable */ - -/* Cause register fields */ -#define CAUSE_BD 0x80000000 /* Branch Delay */ -#define CAUSE_CEMASK 0x30000000 /* Coprocessor Error */ -#define CAUSE_CESHIFT 28 /* Right justify CE */ -#define CAUSE_IPMASK 0x0000ff00 /* Interrupt Pending */ -#define CAUSE_IPSHIFT 8 /* Right justify IP */ -#define CAUSE_IP8 0x00008000 /* (Intr5) */ -#define CAUSE_IP7 0x00004000 /* (Intr4) */ -#define CAUSE_IP6 0x00002000 /* (Intr3) */ -#define CAUSE_IP5 0x00001000 /* (Intr2) */ -#define CAUSE_IP4 0x00000800 /* (Intr1) */ -#define CAUSE_IP3 0x00000400 /* (Intr0) */ -#define CAUSE_SW2 0x00000200 /* (Software Interrupt 1) */ -#define CAUSE_SW1 0x00000100 /* (Software Interrupt 0) */ -#define CAUSE_EXCMASK 0x0000007c /* Exception Code */ -#define CAUSE_EXCSHIFT 2 /* Right justify EXC */ - -/* 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 */ - - -/* CacheErr register */ -#define CACHEERR_TYPE 0x80000000 /* reference type: - 0=Instr, 1=Data */ -#define CACHEERR_LEVEL 0x40000000 /* cache level: - 0=Primary, 1=Secondary */ -#define CACHEERR_DATA 0x20000000 /* data field: - 0=No error, 1=Error */ -#define CACHEERR_TAG 0x10000000 /* tag field: - 0=No error, 1=Error */ -#define CACHEERR_REQ 0x08000000 /* request type: - 0=Internal, 1=External */ -#define CACHEERR_BUS 0x04000000 /* error on bus: - 0=No, 1=Yes */ -#define CACHEERR_BOTH 0x02000000 /* Data & Instruction error: - 0=No, 1=Yes */ -#define CACHEERR_REFILL 0x01000000 /* Error on Refill: - 0=No, 1=Yes */ -#define CACHEERR_SIDX_MASK 0x003ffff8 /* PADDR(21..3) */ -#define CACHEERR_SIDX_SHIFT 0 -#define CACHEERR_PIDX_MASK 0x00000007 /* VADDR(14..12) */ -#define CACHEERR_PIDX_SHIFT 12 - - -/* - * R4600 Cache operations - */ -#define Index_Invalidate_I 0x0 /* 0 0 */ -#define Index_Writeback_Inv_D 0x1 /* 0 1 */ -#define Index_Load_Tag_I 0x4 /* 1 0 */ -#define Index_Load_Tag_D 0x5 /* 1 1 */ -#define Index_Store_Tag_I 0x8 /* 2 0 */ -#define Index_Store_Tag_D 0x9 /* 2 1 */ -#define Create_Dirty_Exc_D 0xD /* 3 1 */ -#define Hit_Invalidate_I 0x10 /* 4 0 */ -#define Hit_Invalidate_D 0x11 /* 4 1 */ -#define Fill_I 0x14 /* 5 0 */ -#define Hit_Writeback_Inv_D 0x15 /* 5 1 */ -#define Hit_Writeback_I 0x18 /* 6 0 */ -#define Hit_Writeback_D 0x19 /* 6 1 */ - - -/* - * Floating Point Coprocessor (CP1) registers - */ -#define C1_IRR $0 /* Implementation/Revision register */ -#define C1_CSR $31 /* FPU Control/Status register */ - -/* Implementation/Revision reg fields */ -#define IRR_IMP_MASK (0xff<<8) /* Implementation number */ -#define IRR_REV_MASK (0xff<<0) /* Revision number */ - -/* 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 - -#endif /* _R4600_H */ diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c b/c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c deleted file mode 100644 index 801317c405..0000000000 --- a/c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c +++ /dev/null @@ -1,844 +0,0 @@ -/******************************************************************************* - - 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 "r4600.h" -#include "limits.h" -#include "gdb_if.h" - - -/* - * Saved register information. Must be prepared by the exception - * preprocessor before handle_exception is invoked. - */ -extern long long registers[NUM_REGS]; - - -/* - * The following external functions provide character input and output. - */ -extern char getDebugChar (void); - -extern void putDebugChar (char); - - -/* - * 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]; - - -/* - * Convert an int to hex. - */ -static const char hexchars[] = "0123456789abcdef"; - -#define highhex(x) hexchars [(x >> 4) & 0xf] -#define lowhex(x) 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 (int addr, int length, char *buf) -{ - 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++ = 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++ = 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++ = 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++ = 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, int addr, int length) -{ - 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; -} - - -/* - * 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); -} - - -/* - * 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 (getDebugChar () != '+'); -} - - -/* - * 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 (instrBuffer.targetAddr) - { - 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 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. - */ -void -handle_exception (void) -{ - int host_has_detached = 0; - int sigval; - int regno, addr, length; - long long regval; - char *ptr; - - /* reply to host that an exception has occurred */ - sigval = computeSignal (); - outBuffer[0] = 'S'; - outBuffer[1] = highhex (sigval); - outBuffer[2] = lowhex (sigval); - outBuffer[3] = '\0'; - - putpacket (outBuffer); - - /* - * Restore the saved instruction at - * the single-step target address. - */ - undoSStep (); - - while (!(host_has_detached)) - { - outBuffer[0] = '\0'; - getpacket (inBuffer); - - switch (inBuffer[0]) - { - case '?': - outBuffer[0] = 'S'; - outBuffer[1] = highhex (sigval); - outBuffer[2] = lowhex (sigval); - outBuffer[3] = '\0'; - break; - - case 'g': - /* return the values of the CPU registers */ - mem2hex ((int) registers, sizeof registers, outBuffer); - break; - - case 'G': - /* set the values of the CPU registers - return OK */ - if (hex2mem (&inBuffer[1], (int) registers, 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 (addr, length, outBuffer); - else - strcpy (outBuffer, "E01"); /* E01 = bad 'm' command */ - break; - - 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) - && hex2mem (ptr, 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 (); - } - return; - - case 'D': - /* remote system is detaching - return OK and exit from debugger */ - strcpy (outBuffer, "OK"); - host_has_detached = 1; - break; - - default: - /* do nothing */ - break; - } /* switch */ - - /* reply to the request */ - putpacket (outBuffer); - } - return; -} diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.ld b/c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.ld deleted file mode 100644 index 675a7ee613..0000000000 --- a/c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.ld +++ /dev/null @@ -1,53 +0,0 @@ -MEMORY -{ - NUL : ORIGIN = 0xa00f0000, LENGTH = 0 - RAM : ORIGIN = 0xa00fe000, LENGTH = 8K - ROM : ORIGIN = 0xbfc00000, LENGTH = 8K -} - -SECTIONS -{ - /* Initialized data is _not_ supported. */ - /* Assign it to an empty region in order */ - /* to force a link error if any exists. */ - .data 0xa00f0000 (NOLOAD): { - _fdata = .; - *(.data) - . = ALIGN(8); - _gp = . + 0x8000; - *(.sdata) - . = ALIGN(8); - _edata = .; - } >NUL - - /* Assign uninitialized read/write data to RAM. */ - .bss 0xa00fe000 (NOLOAD): { - _fbss = .; - stubinit.o(.bss) - *(.sbss) - *(.bss) - *(.scommon) - *(COMMON) - . = ALIGN(8); - _end = .; - } >RAM - - /* Assign code and read-only data to ROM. This */ - /* section MUST start at the reset address, */ - /* and the reset code MUST be linked first. */ - .text 0xbfc00000: { - _ftext = .; - stubinit.o(.text) - . = ALIGN(8); - r46kstub.o(.text) - . = ALIGN(8); - *(.rdata) - . = ALIGN(8); - *(.rodata) - . = ALIGN(8); - _etext = .; - } >ROM = 0 - -} - -ENTRY(_reset_exception) diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/stubinit.S b/c/src/lib/libbsp/mips/shared/gdbstub/stubinit.S deleted file mode 100644 index 7c36ac1c26..0000000000 --- a/c/src/lib/libbsp/mips/shared/gdbstub/stubinit.S +++ /dev/null @@ -1,616 +0,0 @@ -/* - * stubinit.S - low level startup code for the ROM-based R4600 gdb stub - * - * 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. - */ - - .nolist -#include "r4600.h" -#include "ioaddr.h" -#include "gdb_if.h" - .list - -#define SERIAL_SPEED 19200 /* use 19200 bps serial link */ -#define FORCE_PC_TO_32_BITS /* to work around a bug in gdb-4.16 */ -#define STACKSIZE 4096 /* allocate 4K bootstack */ - - .sdata - .globl _gp /* value to put in gp register */ - - .bss - .globl _fbss /* start of .bss area */ - .space STACKSIZE /* allocate the exception stack */ -_stack: /* stack top here (stack grows DOWN) */ - .globl registers /* register save area */ -registers: - .space NUM_REGS*8 - .globl _end /* end of .bss area */ - - .eject - .text - .globl handle_exception /* C exception handler */ - .set noreorder - .set noat - .globl _reset_exception /* entry point into the EPROM */ - /* it MUST reside at bfc00000 */ -/* - * Set the STATUS register initial state: mark CP1 usable, MIPS-3 - * floating point registers enabled, boot exception vectors selected, - * cache parity exceptions disabled, kernel TLB miss to XTLB refill - * vector, machine in kernel mode, exception level cleared, error - * level set, interrupt enable cleared, all interrupts masked. Note - * that the value written here is what will saved in the register - * image; this will put the machine in a reasonable default state - * even if the debug exception handler does nothing to the status - * register image. - */ -_reset_exception: - li k0,SR_CU1 + SR_FR + SR_BEV + SR_DE + SR_KX \ - + SR_KSU_KERN + SR_ERL - mtc0 k0,C0_STATUS - -/* - * Mark each TLB entry as "invalid" and fill the tag field with a VPN that - * cannot occur and an ASID that will not match the value left in EntryHi. - */ - li k0,K1BASE+EH_ASID_MASK /* EntryHi = unmapped VPN2, ASID 255 */ - dmtc0 zero,C0_ENTRYLO0 /* EntryLo0 = invalid */ - dmtc0 zero,C0_ENTRYLO1 /* EntryLo1 = invalid */ - mtc0 zero,C0_PAGEMASK /* PageSize = 4K */ - li k1,(NTLBENTRIES-1) /* TLB index */ -1: - dmtc0 k0,C0_ENTRYHI - mtc0 k1,C0_INDEX - addu k0,(1<>16)&0xffff)/* set lower limit to unmapped addr */ - - addu k1,k0 /* this prevents a TLB exception */ - addiu k1,-16 /* set upper limit for 16 byte line */ -1: - cache Index_Store_Tag_I,(k0) /* write TAGLO/TAGHI to the cache */ - bnel k0,k1,1b /* do that by index so that a */ - addiu k0,k0,16 /* cache hit is not required */ - b 4f - nop -2: - addu k1,k0 /* come here for 32 byte line size */ - addiu k1,-32 -3: - cache Index_Store_Tag_I,(k0) - bnel k0,k1,3b - addiu k0,k0,32 -4: - .eject - mfc0 k0,C0_CONFIG /* repeat for D-cache */ - li k1,(1<<12) - and k0,CFG_DCMASK - srl k0,CFG_DCSHIFT - sll k1,k0 - - mfc0 k0,C0_CONFIG - nop - and k0,CFG_DBMASK - bne k0,zero,6f - lui k0,((K0BASE>>16)&0xffff) - - addu k1,k0 - addiu k1,-16 -5: - cache Index_Store_Tag_D,(k0) - bnel k0,k1,5b - addiu k0,k0,16 - b 8f - nop -6: - addu k1,k0 - addiu k1,-32 -7: - cache Index_Store_Tag_D,(k0) - bnel k0,k1,7b - addiu k0,k0,32 -8: - mfc0 k0,C0_CONFIG /* read config info one last time */ - li k1,~CFG_K0C_MASK /* clear K0 config field */ - and k0,k1 /* in CONFIG image register image */ - or k0,CFG_C_WRITEBACK /* set config to cached/writeback */ - mtc0 k0,C0_CONFIG /* write back to CP0 */ - nop /* wait for update to take effect */ - - .eject -/* - * Initialize the serial port - */ - li k0,DIV_LATCH_EN + WORD_LEN_MASK - la k1,ISA_IO_BASE /* set 8/bits char, no parity, and */ - sb k0,LINE_CTL_COM1(k1) /* enable access to divisor latch */ - - li k0,(1843200/(16*SERIAL_SPEED)) - sb k0,DIV_LO_COM1(k1) /* set clock divisor low byte */ - sra k0,8 - sb k0,DIV_HI_COM1(k1) /* set clock divisor high byte */ - - li k0,WORD_LEN_MASK /* set 8/bits char, no parity, and */ - sb k0,LINE_CTL_COM1(k1) /* disable access to divisor latch */ - - lbu k0,DATA_REG_COM1(k1) /* read & discard any existing char */ - sb zero,INT_ENA_COM1(k1) /* disable all interrupt sources */ - - li k0,RTS + DTR /* turn RTS and DTR on */ - sb k0,MODEM_CTL_COM1(k1) - -/* - * Reset all pending ISA interrupts - */ - la k1,ISA_IRQ3_RESET - sd zero,(k1) - la k1,ISA_IRQ4_RESET - sd zero,(k1) - la k1,ISA_IRQ5_RESET - sd zero,(k1) - la k1,ISA_IRQ9_RESET - sd zero,(k1) - - .eject -/* - * Clear the CAUSE register to indicate the - * absence of software-initiated exceptions. - */ - mtc0 zero,C0_CAUSE - -/* - * Clear floating point errors and configure - * the FPU to flush denormals to zero. - */ - li k0,CSR_FS - ctc1 k0,C1_CSR - -/* - * Clear the .bss area - */ - la k0,_fbss - la k1,_end -1: - addiu k1,k1,-8 - bne k1,k0,1b - sd zero,(k1) - -/* - * Save the ErrorEPC register, in case of a pushbutton - * reset, and join the general exception-handling path. - */ - la k0,registers - dmfc0 k1,C0_ERROREPC - j _common_path_join - sd k1,8*PC(k0) - - .align 9 - .eject -_tlbmiss_exception: /* bfc00200: tlbmiss exception */ - j _general_exception - nop - - .align 7 -_xtlbmiss_exception: /* bfc00280: xtlbmiss exception */ - j _general_exception - nop - - .align 7 -_cache_parity_error: /* bfc00300: cache parity error */ - j _reset_exception - nop - - .align 7 - /* bfc00380: general exception */ -/* - * Clear the register save area - */ -_general_exception: - la k0,registers - addiu k1,k0,8*(NUM_REGS-1) -1: - sd zero,(k1) - bnel k1,k0,1b - addiu k1,k1,-8 - -/* - * Save the PC - */ - dmfc0 k1,C0_EPC - nop - sd k1,8*PC(k0) - - .eject -/* - * Save the SR, CAUSE, and BAD_VA registers. - */ -_common_path_join: - mfc0 k1,C0_STATUS - nop - sd k1,8*SR(k0) - mfc0 k1,C0_CAUSE - nop - sd k1,8*CAUSE(k0) - mfc0 k1,C0_BADVADDR - nop - sd k1,8*BAD_VA(k0) - -/* - * Save LO, HI, and the general registers. - * Note that zero, k0 & k1 are not saved. - */ - mflo k1 - sd k1,8*LO(k0) - mfhi k1 - sd k1,8*HI(k0) - - /* zero is hard-wired */ - sd at,8*AT(k0) - - sd v0,8*V0(k0) - sd v1,8*V1(k0) - - sd a0,8*A0(k0) - sd a1,8*A1(k0) - sd a2,8*A2(k0) - sd a3,8*A3(k0) - - sd t0,8*T0(k0) - sd t1,8*T1(k0) - sd t2,8*T2(k0) - sd t3,8*T3(k0) - sd t4,8*T4(k0) - sd t5,8*T5(k0) - sd t6,8*T6(k0) - sd t7,8*T7(k0) - - .eject - sd s0,8*S0(k0) - sd s1,8*S1(k0) - sd s2,8*S2(k0) - sd s3,8*S3(k0) - sd s4,8*S4(k0) - sd s5,8*S5(k0) - sd s6,8*S6(k0) - sd s7,8*S7(k0) - - sd t8,8*T8(k0) - sd t9,8*T9(k0) - - /* k0 is not saved */ - /* k1 is not saved */ - - sd gp,8*GP(k0) - sd sp,8*SP(k0) - sd s8,8*S8(k0) - sd ra,8*RA(k0) - -/* - * Save the floating point control registers. - */ - cfc1 k1,C1_CSR - nop - sd k1,8*FCSR(k0) - cfc1 k1,C1_IRR - nop - sd k1,8*FIRR(k0) - -/* - * Save the even-numbered floating point registers. - */ - sdc1 $0,8*F0(k0) - sdc1 $2,8*F2(k0) - sdc1 $4,8*F4(k0) - sdc1 $6,8*F6(k0) - sdc1 $8,8*F8(k0) - sdc1 $10,8*F10(k0) - sdc1 $12,8*F12(k0) - sdc1 $14,8*F14(k0) - sdc1 $16,8*F16(k0) - sdc1 $18,8*F18(k0) - sdc1 $20,8*F20(k0) - sdc1 $22,8*F22(k0) - sdc1 $24,8*F24(k0) - sdc1 $26,8*F26(k0) - sdc1 $28,8*F28(k0) - sdc1 $30,8*F30(k0) - - .eject -/* - * If they are enabled, save the odd-numbered - * floating point registers as well. - */ - mfc0 k1,C0_STATUS - li at,SR_FR - and k1,at - beq k1,zero,1f - nop - sdc1 $1,8*F1(k0) - sdc1 $3,8*F3(k0) - sdc1 $5,8*F5(k0) - sdc1 $7,8*F7(k0) - sdc1 $9,8*F9(k0) - sdc1 $11,8*F11(k0) - sdc1 $13,8*F13(k0) - sdc1 $15,8*F15(k0) - sdc1 $17,8*F17(k0) - sdc1 $19,8*F19(k0) - sdc1 $21,8*F21(k0) - sdc1 $23,8*F23(k0) - sdc1 $25,8*F25(k0) - sdc1 $27,8*F27(k0) - sdc1 $29,8*F29(k0) - sdc1 $31,8*F31(k0) -1: - -/* - * Set up the global pointer and the stack - * and invoke the exception handler. - */ - la gp,_gp - la sp,_stack - jal handle_exception - addiu fp,sp,0 - - .eject -/* - * 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. - */ - mfc0 t0,C0_CONFIG /* read config info into t0 */ - nop /* wait for CP0 read to take effect */ - - and t1,t0,CFG_ICMASK /* isolate I-cache shift */ - srl t1,t1,CFG_ICSHIFT /* count param into t1 */ - li t2,(1<<12) /* put base size in t2 */ - sllv t2,t2,t1 /* shift left to get actual size */ - - and t1,t0,CFG_IBMASK /* isolate linesize config bit */ - bne t1,zero,1f /* guess line size is 32 bytes */ - addiu t3,zero,32 /* skip next load if guessed right */ - addiu t3,zero,16 /* else set size to 16 bytes */ -1: - la t1,K0BASE /* set lower & upper address limits */ - addu t2,t2,t1 /* use kseg0 to avoid TLB exception */ - subu t2,t2,t3 -2: - cache Index_Invalidate_I,(t1) /* invalidate each I-cache line */ - bnel t1,t2,2b /* do this by index so that */ - addu t1,t1,t3 /* a hit is not required */ - - and t1,t0,CFG_DCMASK /* repeat for D-cache with writeback */ - srl t1,t1,CFG_DCSHIFT - li t2,(1<<12) - sllv t2,t2,t1 - - and t1,t0,CFG_DBMASK - bne t1,zero,3f - addiu t3,zero,32 - addiu t3,zero,16 -3: - la t1,K0BASE - addu t2,t2,t1 - subu t2,t2,t3 -4: - cache Index_Writeback_Inv_D,(t1) - bnel t1,t2,4b - addu t1,t1,t3 - - .eject -/* - * Now restore the registers. Note that they may - * have been modified while within the debugger. - * Start with even-numbered floating point registers. - */ - la k0,registers - ldc1 $0,8*F0(k0) - ldc1 $2,8*F2(k0) - ldc1 $4,8*F4(k0) - ldc1 $6,8*F6(k0) - ldc1 $8,8*F8(k0) - ldc1 $10,8*F10(k0) - ldc1 $12,8*F12(k0) - ldc1 $14,8*F14(k0) - ldc1 $16,8*F16(k0) - ldc1 $18,8*F18(k0) - ldc1 $20,8*F20(k0) - ldc1 $22,8*F22(k0) - ldc1 $24,8*F24(k0) - ldc1 $26,8*F26(k0) - ldc1 $28,8*F28(k0) - ldc1 $30,8*F30(k0) - -/* - * If they are enabled, restore the odd-numbered - * floating point registers as well. - */ - mfc0 k1,C0_STATUS - li at,SR_FR - and k1,at - beq k1,zero,1f - nop - ldc1 $1,8*F1(k0) - ldc1 $3,8*F3(k0) - ldc1 $5,8*F5(k0) - ldc1 $7,8*F7(k0) - ldc1 $9,8*F9(k0) - ldc1 $11,8*F11(k0) - ldc1 $13,8*F13(k0) - ldc1 $15,8*F15(k0) - ldc1 $17,8*F17(k0) - ldc1 $19,8*F19(k0) - ldc1 $21,8*F21(k0) - ldc1 $23,8*F23(k0) - ldc1 $25,8*F25(k0) - ldc1 $27,8*F27(k0) - ldc1 $29,8*F29(k0) - ldc1 $31,8*F31(k0) -1: - .eject -/* - * Restore the floating point control & status register. - * FIRR is not restored because it is read-only. - */ - ld k1,8*FCSR(k0) - ctc1 k1,C1_CSR - -/* - * Restore LO, HI, and the general registers. - */ - ld k1,8*LO(k0) - mtlo k1 - ld k1,8*HI(k0) - mthi k1 - - /* zero is hard-wired */ - ld at,8*AT(k0) - - ld v0,8*V0(k0) - ld v1,8*V1(k0) - - ld a0,8*A0(k0) - ld a1,8*A1(k0) - ld a2,8*A2(k0) - ld a3,8*A3(k0) - - ld t0,8*T0(k0) - ld t1,8*T1(k0) - ld t2,8*T2(k0) - ld t3,8*T3(k0) - ld t4,8*T4(k0) - ld t5,8*T5(k0) - ld t6,8*T6(k0) - ld t7,8*T7(k0) - - ld s0,8*S0(k0) - ld s1,8*S1(k0) - ld s2,8*S2(k0) - ld s3,8*S3(k0) - ld s4,8*S4(k0) - ld s5,8*S5(k0) - ld s6,8*S6(k0) - ld s7,8*S7(k0) - - ld t8,8*T8(k0) - ld t9,8*T9(k0) - - /* k0 is not restored */ - /* k1 is not restored */ - - ld gp,8*GP(k0) - ld sp,8*SP(k0) - ld s8,8*S8(k0) - ld ra,8*RA(k0) - - .eject -/* - * Restore the cause register, the status register, and the PC. Note - * that the saved PC is loaded into the ErrorEPC if ERL is set in the - * status register image and is loaded into the EPC otherwise. - */ - ld k1,8*CAUSE(k0) - mtc0 k1,C0_CAUSE - ld k1,8*SR(k0) - mtc0 k1,C0_STATUS - andi k1,k1,SR_ERL - beq k1,zero,1f - ld k1,8*PC(k0) -#if !defined(FORCE_PC_TO_32_BITS) - b 2f - dmtc0 k1,C0_ERROREPC -1: - dmtc0 k1,C0_EPC -2: -#else - addu k1,k1,zero - b 2f - dmtc0 k1,C0_ERROREPC -1: - addu k1,k1,zero - dmtc0 k1,C0_EPC -2: -#endif - -/* - * Flush the write buffer to memory. - */ - sync - -/* - * Hide the contents of k0 & k1 - * and return to the user program. - */ - move k0,zero - move k1,zero - eret - - .eject -/* - * char getDebugChar (void); - */ - .set reorder - .globl getDebugChar - .ent getDebugChar -getDebugChar: - la t0,ISA_IO_BASE /* point to ISA slot I/O */ -1: - lbu t1,LINE_STS_COM1(t0) /* read line status register */ - and t1,RX_CHAR_AVA /* isolate RX status bit */ - beqz t1,1b /* loop until char is available */ - - lbu v0,DATA_REG_COM1(t0) /* read the character */ - j ra /* and return */ - .end getDebugChar - -/* - * void putDebugChar (char); - */ - .set reorder - .globl putDebugChar - .ent putDebugChar -putDebugChar: - la t0,ISA_IO_BASE /* point to ISA slot I/O */ -1: - lbu t1,LINE_STS_COM1(t0) /* read line status register */ - and t1,TX_BUF_EMPTY /* isolate TX status bit */ - beqz t1,1b /* loop while buffer is full */ - - sb a0,DATA_REG_COM1(t0) /* write the outgoing character */ - sync /* flush the write buffer to memory */ - j ra /* and return */ - .end putDebugChar -- cgit v1.2.3