Index: c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog
===================================================================
--- c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
+++ c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
@@ -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.
Index: c/src/lib/libbsp/mips/shared/gdbstub/Makefile
===================================================================
--- c/src/lib/libbsp/mips/shared/gdbstub/Makefile	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
+++ c/src/lib/libbsp/mips/shared/gdbstub/Makefile	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
@@ -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
Index: c/src/lib/libbsp/mips/shared/gdbstub/README
===================================================================
--- c/src/lib/libbsp/mips/shared/gdbstub/README	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
+++ c/src/lib/libbsp/mips/shared/gdbstub/README	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
@@ -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
Index: c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h
===================================================================
--- c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
+++ c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
@@ -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 */
Index: c/src/lib/libbsp/mips/shared/gdbstub/ioaddr.h
===================================================================
--- c/src/lib/libbsp/mips/shared/gdbstub/ioaddr.h	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
+++ c/src/lib/libbsp/mips/shared/gdbstub/ioaddr.h	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
@@ -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 */
Index: c/src/lib/libbsp/mips/shared/gdbstub/limits.h
===================================================================
--- c/src/lib/libbsp/mips/shared/gdbstub/limits.h	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
+++ c/src/lib/libbsp/mips/shared/gdbstub/limits.h	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
@@ -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_ */
Index: c/src/lib/libbsp/mips/shared/gdbstub/mips_opcode.h
===================================================================
--- c/src/lib/libbsp/mips/shared/gdbstub/mips_opcode.h	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
+++ c/src/lib/libbsp/mips/shared/gdbstub/mips_opcode.h	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
@@ -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 */
Index: c/src/lib/libbsp/mips/shared/gdbstub/r4600.h
===================================================================
--- c/src/lib/libbsp/mips/shared/gdbstub/r4600.h	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
+++ c/src/lib/libbsp/mips/shared/gdbstub/r4600.h	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
@@ -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 */
Index: c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c
===================================================================
--- c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
+++ c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
@@ -0,0 +1,851 @@
+/*******************************************************************************
+
+                     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;
+}
Index: c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.ld
===================================================================
--- c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.ld	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
+++ c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.ld	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
@@ -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)
Index: c/src/lib/libbsp/mips/shared/gdbstub/stubinit.S
===================================================================
--- c/src/lib/libbsp/mips/shared/gdbstub/stubinit.S	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
+++ c/src/lib/libbsp/mips/shared/gdbstub/stubinit.S	(revision fb639847713fed3ed2c94e41e7f21d09cebe4af2)
@@ -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
