summaryrefslogtreecommitdiffstats
path: root/c/src/lib
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2002-02-08 20:03:26 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2002-02-08 20:03:26 +0000
commitfb639847713fed3ed2c94e41e7f21d09cebe4af2 (patch)
tree1698f481ff266b22ee0e49b18026ca15d24f15b2 /c/src/lib
parent2002-02-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de> (diff)
downloadrtems-fb639847713fed3ed2c94e41e7f21d09cebe4af2.tar.bz2
2002-02-08 Joel Sherrill <joel@OARcorp.com>
* Merged r46kstub.c into RTEMS distribution without modification. I got the code from Franz Fischer <Franz.Fischer@franz-fischer.de> who had used this with an old version of RTEMS with the mips64orion port of RTEMS. After adding this to the repository, I will tailor this to work with the RTEMS exception processing model and trim no longer needed parts. * ChangeLog, gdb_if.h, ioaddr.h, limits.h, Makefile, mips_opcode.h, r4600.h, r46kstub.c, r46kstub.ld, README, stubinit.S:
Diffstat (limited to 'c/src/lib')
-rw-r--r--c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog43
-rw-r--r--c/src/lib/libbsp/mips/shared/gdbstub/Makefile38
-rw-r--r--c/src/lib/libbsp/mips/shared/gdbstub/README115
-rw-r--r--c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h105
-rw-r--r--c/src/lib/libbsp/mips/shared/gdbstub/ioaddr.h113
-rw-r--r--c/src/lib/libbsp/mips/shared/gdbstub/limits.h70
-rw-r--r--c/src/lib/libbsp/mips/shared/gdbstub/mips_opcode.h295
-rw-r--r--c/src/lib/libbsp/mips/shared/gdbstub/r4600.h372
-rw-r--r--c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c844
-rw-r--r--c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.ld53
-rw-r--r--c/src/lib/libbsp/mips/shared/gdbstub/stubinit.S616
11 files changed, 2664 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog b/c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog
new file mode 100644
index 0000000000..10f6c048d7
--- /dev/null
+++ b/c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog
@@ -0,0 +1,43 @@
+2002-02-08 Joel Sherrill <joel@OARcorp.com>
+
+ * Merged r46kstub.c into RTEMS distribution without modification.
+ I got the code from Franz Fischer <Franz.Fischer@franz-fischer.de>
+ who had used this with an old version of RTEMS with the mips64orion
+ port of RTEMS. After adding this to the repository, I will tailor
+ this to work with the RTEMS exception processing model and trim
+ no longer needed parts.
+ * ChangeLog, gdb_if.h, ioaddr.h, limits.h, Makefile, mips_opcode.h,
+ r4600.h, r46kstub.c, r46kstub.ld, README, stubinit.S:
+
+Sun Sep 29 16:34:53 1996 C. M. Heard <heard@vvnet.com>
+
+ * Updated snapshot posted.
+
+ * stubinit.S (_reset_exception, _general_exception): Reorder
+ instructions or insert nops as necessary to ensure that the
+ target register of mfc0, mfc1, and cfc1 instructions is not
+ used as a source register in the load delay slot of those
+ instructions and to ensure that the instruction following
+ mtc0 is always something other than mfc0. Insert .eject
+ directives and reformat some of the comments to make the
+ assembler listing more readable.
+
+ * ioaddr.h: add comments pointing out implementation-
+ specific address definitions.
+
+ * limits.h: add comments describing what the implementation-
+ specific macros in this file are supposed to do.
+
+Tue Aug 06 14:43:04 1995 C. M. Heard <heard@vvnet.com>
+
+ * Updated snapshot posted.
+
+ * stubinit.S (_general_exception): Use virtual adresses from
+ kseg0 (cached, unmapped space) instead of kseg1 (uncached,
+ unmapped space) in cache instructions.
+ (_reset_exception): Likewise, and use the right
+ mask to clean the K0 field in the config register.
+
+Fri Jul 26 14:41:49 1995 C. M. Heard <heard@vvnet.com>
+
+ * Initial snapshot posted.
diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/Makefile b/c/src/lib/libbsp/mips/shared/gdbstub/Makefile
new file mode 100644
index 0000000000..9057011b4e
--- /dev/null
+++ b/c/src/lib/libbsp/mips/shared/gdbstub/Makefile
@@ -0,0 +1,38 @@
+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
new file mode 100644
index 0000000000..3550a2ad29
--- /dev/null
+++ b/c/src/lib/libbsp/mips/shared/gdbstub/README
@@ -0,0 +1,115 @@
+/* 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 */
+
+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:
+
+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
new file mode 100644
index 0000000000..cc7d0b72fe
--- /dev/null
+++ b/c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+#ifndef _GDB_IF_H
+#define _GDB_IF_H
+
+/*
+ * R4600 registers, 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
+
+#endif /* _GDB_IF_H */
diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/ioaddr.h b/c/src/lib/libbsp/mips/shared/gdbstub/ioaddr.h
new file mode 100644
index 0000000000..7533abf5de
--- /dev/null
+++ b/c/src/lib/libbsp/mips/shared/gdbstub/ioaddr.h
@@ -0,0 +1,113 @@
+/*
+ * 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
new file mode 100644
index 0000000000..05f82123e8
--- /dev/null
+++ b/c/src/lib/libbsp/mips/shared/gdbstub/limits.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_opcode.h b/c/src/lib/libbsp/mips/shared/gdbstub/mips_opcode.h
new file mode 100644
index 0000000000..59c1a06798
--- /dev/null
+++ b/c/src/lib/libbsp/mips/shared/gdbstub/mips_opcode.h
@@ -0,0 +1,295 @@
+/*-
+ * 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
+
+/*
+ * Define the 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;
+
+/*
+ * Values for the 'op' field.
+ */
+#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
+
+/*
+ * Values for the 'func' field 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
+
+/*
+ * Values for the 'func' field 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
+
+/*
+ * Values for the 'rs' field 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
+
+/*
+ * Values for the 'rt' field when 'op' == OP_COPz and 'rt' == OP_BC.
+ */
+#define COPz_BCF 0x00
+#define COPz_BCT 0x01
+#define COPz_BCFL 0x02
+#define COPz_BCTL 0x03
+
+/*
+ * Instructions with specal significance to debuggers.
+ */
+#define BREAK_INSTR 0x0000000d /* instruction code for break */
+#define NOP_INSTR 0x00000000 /* instruction code for no-op */
+
+#endif /* _MIPS_OPCODE_H */
diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/r4600.h b/c/src/lib/libbsp/mips/shared/gdbstub/r4600.h
new file mode 100644
index 0000000000..14c1353a2d
--- /dev/null
+++ b/c/src/lib/libbsp/mips/shared/gdbstub/r4600.h
@@ -0,0 +1,372 @@
+/*
+ * 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
new file mode 100644
index 0000000000..801317c405
--- /dev/null
+++ b/c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c
@@ -0,0 +1,844 @@
+/*******************************************************************************
+
+ 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 <data>
+* is encapsulated for transmission in the form:
+*
+* $ <data> # CSUM1 CSUM2
+*
+* <data> must be ASCII alphanumeric and cannot include characters
+* '$' or '#'. If <data> 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 <data>, 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
+*
+* <data> 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 <other> On other requests, the stub should
+* ignore the request and send an empty
+* response ($#<checksum>). 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 <string.h>
+#include <signal.h>
+#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 $<data>#<checksum>.
+ */
+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;
+
+ /* $<packet info>#<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, &regno) &&
+ *ptr++ == '=' &&
+ hexToLongLong(&ptr, &regval))
+ {
+ 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
new file mode 100644
index 0000000000..675a7ee613
--- /dev/null
+++ b/c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.ld
@@ -0,0 +1,53 @@
+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
new file mode 100644
index 0000000000..7c36ac1c26
--- /dev/null
+++ b/c/src/lib/libbsp/mips/shared/gdbstub/stubinit.S
@@ -0,0 +1,616 @@
+/*
+ * 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<<EH_VPN2_SHIFT) /* incr VPN2 */
+ tlbwi
+ bnel k1,zero,1b
+ addiu k1,k1,-1 /* decr INDEX */
+
+ dmtc0 zero,C0_ENTRYHI /* Clear EntryHi to select ASID = 0 */
+ nop /* wait for update to take effect */
+
+ .eject
+/*
+ * Invalidate each line in both of the caches, then
+ * set kseg0 config to cached/writeback/non-coherent.
+ */
+ mtc0 zero,C0_TAGLO /* clear TAGLO and TAGHI - used below */
+ mtc0 zero,C0_TAGHI /* to set cache line state to invalid */
+ nop
+
+ mfc0 k0,C0_CONFIG /* read config info */
+ li k1,(1<<12) /* base size is 4K */
+ and k0,CFG_ICMASK /* isolate I-cache shift count param */
+ srl k0,CFG_ICSHIFT /* which determines the actual size */
+ sll k1,k0 /* shift left to get actual size */
+
+ mfc0 k0,C0_CONFIG /* read config info */
+ nop /* wait for CP0 read to take effect */
+ and k0,CFG_IBMASK /* isolate line size config bit */
+ bne k0,zero,2f /* jump if line size is 32 bytes */
+ lui k0,((K0BASE>>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