From fb639847713fed3ed2c94e41e7f21d09cebe4af2 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Fri, 8 Feb 2002 20:03:26 +0000 Subject: 2002-02-08 Joel Sherrill * Merged r46kstub.c into RTEMS distribution without modification. I got the code from Franz Fischer 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: --- c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog | 43 ++ c/src/lib/libbsp/mips/shared/gdbstub/Makefile | 38 + c/src/lib/libbsp/mips/shared/gdbstub/README | 115 +++ c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h | 105 +++ c/src/lib/libbsp/mips/shared/gdbstub/ioaddr.h | 113 +++ c/src/lib/libbsp/mips/shared/gdbstub/limits.h | 70 ++ c/src/lib/libbsp/mips/shared/gdbstub/mips_opcode.h | 295 +++++++ c/src/lib/libbsp/mips/shared/gdbstub/r4600.h | 372 +++++++++ c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c | 844 +++++++++++++++++++++ c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.ld | 53 ++ c/src/lib/libbsp/mips/shared/gdbstub/stubinit.S | 616 +++++++++++++++ 11 files changed, 2664 insertions(+) create mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog create mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/Makefile create mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/README create mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/gdb_if.h create mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/ioaddr.h create mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/limits.h create mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/mips_opcode.h create mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/r4600.h create mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c create mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.ld create mode 100644 c/src/lib/libbsp/mips/shared/gdbstub/stubinit.S (limited to 'c') diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog b/c/src/lib/libbsp/mips/shared/gdbstub/ChangeLog 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 + + * Merged r46kstub.c into RTEMS distribution without modification. + I got the code from Franz Fischer + 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 + + * 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 + + * 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 + + * 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 +* is encapsulated for transmission in the form: +* +* $ # CSUM1 CSUM2 +* +* must be ASCII alphanumeric and cannot include characters +* '$' or '#'. If starts with two characters followed by +* ':', then the existing stubs interpret this as a sequence number. +* +* CSUM1 and CSUM2 are ascii hex representation of an 8-bit +* checksum of , the most significant nibble is sent first. +* the hex digits 0-9,a-f are used. +* +* Receiver responds with: +* +* + if CSUM is correct +* - if CSUM is incorrect +* +* is as follows. All values are encoded in ascii hex digits. +* +* Request Packet +* +* read registers g +* reply XX....X Each byte of register data +* is described by two hex digits. +* Registers are in the internal order +* for GDB, and the bytes in a register +* are in the same order the machine uses. +* or ENN for an error. +* +* write regs GXX..XX Each byte of register data +* is described by two hex digits. +* reply OK for success +* ENN for an error +* +* write reg Pn...=r... Write register n... with value r.... +* reply OK for success +* ENN for an error +* +* read mem mAA..AA,LLLL AA..AA is address, LLLL is length. +* reply XX..XX XX..XX is mem contents +* Can be fewer bytes than requested +* if able to read only part of the data. +* or ENN NN is errno +* +* write mem MAA..AA,LLLL:XX..XX +* AA..AA is address, +* LLLL is number of bytes, +* XX..XX is data +* reply OK for success +* ENN for an error (this includes the case +* where only part of the data was +* written). +* +* cont cAA..AA AA..AA is address to resume +* If AA..AA is omitted, +* resume at same address. +* +* step sAA..AA AA..AA is address to resume +* If AA..AA is omitted, +* resume at same address. +* +* There is no immediate reply to step or cont. +* The reply comes when the machine stops. +* It is SAA AA is the "signal number" +* +* last signal ? Reply with the reason for stopping. +* This is the same reply as is generated +* for step or cont: SAA where AA is the +* signal number. +* +* detach D Host is detaching. Reply OK and +* end remote debugging session. +* +* reserved On other requests, the stub should +* ignore the request and send an empty +* response ($#). This way +* we can extend the protocol and GDB +* can tell whether the stub it is +* talking to uses the old or the new. +* +* Responses can be run-length encoded to save space. A '*' means that +* the next character is an ASCII encoding giving a repeat count which +* stands for that many repetitions of the character preceding the '*'. +* The encoding is n+29, yielding a printable character when n >=3 +* (which is where rle starts to win). Don't use n > 99 since gdb +* masks each character is receives with 0x7f in order to strip off +* the parity bit. +* +* As an example, "0* " means the same thing as "0000". +* +*******************************************************************************/ + + +#include +#include +#include "mips_opcode.h" +#include "r4600.h" +#include "limits.h" +#include "gdb_if.h" + + +/* + * Saved register information. Must be prepared by the exception + * preprocessor before handle_exception is invoked. + */ +extern long long registers[NUM_REGS]; + + +/* + * The following external functions provide character input and output. + */ +extern char getDebugChar (void); + +extern void putDebugChar (char); + + +/* + * BUFMAX defines the maximum number of characters in the inbound & outbound + * packet buffers. At least 4+(sizeof registers)*2 bytes will be needed for + * register packets. Memory dump packets can profitably use even more. + */ +#define BUFMAX 1500 + +static char inBuffer[BUFMAX]; +static char outBuffer[BUFMAX]; + + +/* + * Convert an int to hex. + */ +static const char hexchars[] = "0123456789abcdef"; + +#define highhex(x) hexchars [(x >> 4) & 0xf] +#define lowhex(x) hexchars [x & 0xf] + + +/* + * Convert length bytes of data starting at addr into hex, placing the + * result in buf. Return a pointer to the last (null) char in buf. + */ +static char * +mem2hex (int addr, int length, char *buf) +{ + if (((addr & 0x7) == 0) && ((length & 0x7) == 0)) /* dword aligned */ + { + long long *source = (long long *) (addr); + long long *limit = (long long *) (addr + length); + + while (source < limit) + { + int i; + long long k = *source++; + + for (i = 15; i >= 0; i--) + *buf++ = hexchars [(k >> (i*4)) & 0xf]; + } + } + else if (((addr & 0x3) == 0) && ((length & 0x3) == 0)) /* word aligned */ + { + int *source = (int *) (addr); + int *limit = (int *) (addr + length); + + while (source < limit) + { + int i; + int k = *source++; + + for (i = 7; i >= 0; i--) + *buf++ = hexchars [(k >> (i*4)) & 0xf]; + } + } + else if (((addr & 0x1) == 0) && ((length & 0x1) == 0)) /* halfword aligned */ + { + short *source = (short *) (addr); + short *limit = (short *) (addr + length); + + while (source < limit) + { + int i; + short k = *source++; + + for (i = 3; i >= 0; i--) + *buf++ = hexchars [(k >> (i*4)) & 0xf]; + } + } + else /* byte aligned */ + { + char *source = (char *) (addr); + char *limit = (char *) (addr + length); + + while (source < limit) + { + int i; + char k = *source++; + + for (i = 1; i >= 0; i--) + *buf++ = hexchars [(k >> (i*4)) & 0xf]; + } + } + + *buf = '\0'; + return (buf); +} + + +/* + * Convert a hex character to an int. + */ +static int +hex (char ch) +{ + if ((ch >= 'a') && (ch <= 'f')) + return (ch - 'a' + 10); + if ((ch >= '0') && (ch <= '9')) + return (ch - '0'); + if ((ch >= 'A') && (ch <= 'F')) + return (ch - 'A' + 10); + return (-1); +} + + +/* + * Convert a string from hex to int until a non-hex digit + * is found. Return the number of characters processed. + */ +static int +hexToInt (char **ptr, int *intValue) +{ + int numChars = 0; + int hexValue; + + *intValue = 0; + + while (**ptr) + { + hexValue = hex (**ptr); + if (hexValue >= 0) + { + *intValue = (*intValue << 4) | hexValue; + numChars++; + } + else + break; + + (*ptr)++; + } + + return (numChars); +} + + +/* + * Convert a string from hex to long long until a non-hex + * digit is found. Return the number of characters processed. + */ +static int +hexToLongLong (char **ptr, long long *intValue) +{ + int numChars = 0; + int hexValue; + + *intValue = 0; + + while (**ptr) + { + hexValue = hex (**ptr); + if (hexValue >= 0) + { + *intValue = (*intValue << 4) | hexValue; + numChars++; + } + else + break; + + (*ptr)++; + } + + return (numChars); +} + + +/* + * Convert the hex array buf into binary, placing the result at the + * specified address. If the conversion fails at any point (i.e., + * if fewer bytes are written than indicated by the size parameter) + * then return 0; otherwise return 1. + */ +static int +hex2mem (char *buf, int addr, int length) +{ + if (((addr & 0x7) == 0) && ((length & 0x7) == 0)) /* dword aligned */ + { + long long *target = (long long *) (addr); + long long *limit = (long long *) (addr + length); + + while (target < limit) + { + int i, j; + long long k = 0; + + for (i = 0; i < 16; i++) + if ((j = hex(*buf++)) < 0) + return 0; + else + k = (k << 4) + j; + *target++ = k; + } + } + else if (((addr & 0x3) == 0) && ((length & 0x3) == 0)) /* word aligned */ + { + int *target = (int *) (addr); + int *limit = (int *) (addr + length); + + while (target < limit) + { + int i, j; + int k = 0; + + for (i = 0; i < 8; i++) + if ((j = hex(*buf++)) < 0) + return 0; + else + k = (k << 4) + j; + *target++ = k; + } + } + else if (((addr & 0x1) == 0) && ((length & 0x1) == 0)) /* halfword aligned */ + { + short *target = (short *) (addr); + short *limit = (short *) (addr + length); + + while (target < limit) + { + int i, j; + short k = 0; + + for (i = 0; i < 4; i++) + if ((j = hex(*buf++)) < 0) + return 0; + else + k = (k << 4) + j; + *target++ = k; + } + } + else /* byte aligned */ + { + char *target = (char *) (addr); + char *limit = (char *) (addr + length); + + while (target < limit) + { + int i, j; + char k = 0; + + for (i = 0; i < 2; i++) + if ((j = hex(*buf++)) < 0) + return 0; + else + k = (k << 4) + j; + *target++ = k; + } + } + + return 1; +} + + +/* + * Scan the input stream for a sequence for the form $#. + */ +static void +getpacket (char *buffer) +{ + unsigned char checksum; + unsigned char xmitcsum; + int i; + int count; + char ch; + do + { + /* wait around for the start character, ignore all other characters */ + while ((ch = getDebugChar ()) != '$'); + checksum = 0; + xmitcsum = -1; + + count = 0; + + /* now, read until a # or end of buffer is found */ + while ( (count < BUFMAX-1) && ((ch = getDebugChar ()) != '#') ) + checksum += (buffer[count++] = ch); + + /* make sure that the buffer is null-terminated */ + buffer[count] = '\0'; + + if (ch == '#') + { + xmitcsum = hex (getDebugChar ()) << 4; + xmitcsum += hex (getDebugChar ()); + if (checksum != xmitcsum) + putDebugChar ('-'); /* failed checksum */ + else + { + putDebugChar ('+'); /* successful transfer */ + /* if a sequence char is present, reply the sequence ID */ + if (buffer[2] == ':') + { + putDebugChar (buffer[0]); + putDebugChar (buffer[1]); + /* remove sequence chars from buffer */ + for (i = 3; i <= count; i++) + buffer[i - 3] = buffer[i]; + } + } + } + } + while (checksum != xmitcsum); +} + + +/* + * Send the packet in buffer and wait for a positive acknowledgement. + */ +static void +putpacket (char *buffer) +{ + int checksum; + + /* $# */ + do + { + char *src = buffer; + putDebugChar ('$'); + checksum = 0; + + while (*src != '\0') + { + int runlen = 0; + + /* Do run length encoding */ + while ((src[runlen] == src[0]) && (runlen < 99)) + runlen++; + if (runlen > 3) + { + int encode; + /* Got a useful amount */ + putDebugChar (*src); + checksum += *src; + putDebugChar ('*'); + checksum += '*'; + checksum += (encode = (runlen - 4) + ' '); + putDebugChar (encode); + src += runlen; + } + else + { + putDebugChar (*src); + checksum += *src; + src++; + } + } + + putDebugChar ('#'); + putDebugChar (highhex (checksum)); + putDebugChar (lowhex (checksum)); + } + while (getDebugChar () != '+'); +} + + +/* + * Saved instruction data for single step support + */ +static struct + { + unsigned *targetAddr; + unsigned savedInstr; + } +instrBuffer; + + +/* + * If a step breakpoint was planted restore the saved instruction. + */ +static void +undoSStep (void) +{ + if (instrBuffer.targetAddr != NULL) + { + *instrBuffer.targetAddr = instrBuffer.savedInstr; + instrBuffer.targetAddr = NULL; + } + instrBuffer.savedInstr = NOP_INSTR; +} + + +/* + * If a single step is requested put a temporary breakpoint at the instruction + * which logically follows the next one to be executed. If the next instruction + * is a branch instruction then skip the instruction in the delay slot. NOTE: + * ERET instructions are NOT handled, as it is impossible to single-step through + * the exit code in an exception handler. In addition, no attempt is made to + * do anything about BC0T and BC0F, since a condition bit for coprocessor 0 + * is not defined on the R4600. Finally, BC2T and BC2F are ignored since there + * is no coprocessor 2 on a 4600. + */ +static void +doSStep (void) +{ + InstFmt inst; + + instrBuffer.targetAddr = (unsigned *)(registers[PC]+4); /* set default */ + + inst.word = *(unsigned *)registers[PC]; /* read the next instruction */ + + switch (inst.RType.op) { /* override default if branch */ + case OP_SPECIAL: + switch (inst.RType.func) { + case OP_JR: + case OP_JALR: + instrBuffer.targetAddr = + (unsigned *)registers[inst.RType.rs]; + break; + }; + break; + + case OP_REGIMM: + switch (inst.IType.rt) { + case OP_BLTZ: + case OP_BLTZL: + case OP_BLTZAL: + case OP_BLTZALL: + if (registers[inst.IType.rs] < 0 ) + instrBuffer.targetAddr = + (unsigned *)(((signed short)inst.IType.imm<<2) + + (registers[PC]+4)); + else + instrBuffer.targetAddr = (unsigned*)(registers[PC]+8); + break; + case OP_BGEZ: + case OP_BGEZL: + case OP_BGEZAL: + case OP_BGEZALL: + if (registers[inst.IType.rs] >= 0 ) + instrBuffer.targetAddr = + (unsigned *)(((signed short)inst.IType.imm<<2) + + (registers[PC]+4)); + else + instrBuffer.targetAddr = (unsigned*)(registers[PC]+8); + break; + }; + break; + + case OP_J: + case OP_JAL: + instrBuffer.targetAddr = + (unsigned *)((inst.JType.target<<2) + ((registers[PC]+4)&0xf0000000)); + break; + + case OP_BEQ: + case OP_BEQL: + if (registers[inst.IType.rs] == registers[inst.IType.rt]) + instrBuffer.targetAddr = + (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4)); + else + instrBuffer.targetAddr = (unsigned*)(registers[PC]+8); + break; + case OP_BNE: + case OP_BNEL: + if (registers[inst.IType.rs] != registers[inst.IType.rt]) + instrBuffer.targetAddr = + (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4)); + else + instrBuffer.targetAddr = (unsigned*)(registers[PC]+8); + break; + case OP_BLEZ: + case OP_BLEZL: + if (registers[inst.IType.rs] <= 0) + instrBuffer.targetAddr = + (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4)); + else + instrBuffer.targetAddr = (unsigned*)(registers[PC]+8); + break; + case OP_BGTZ: + case OP_BGTZL: + if (registers[inst.IType.rs] > 0) + instrBuffer.targetAddr = + (unsigned *)(((signed short)inst.IType.imm<<2) + (registers[PC]+4)); + else + instrBuffer.targetAddr = (unsigned*)(registers[PC]+8); + break; + + case OP_COP1: + if (inst.RType.rs == OP_BC) + switch (inst.RType.rt) { + case COPz_BCF: + case COPz_BCFL: + if (registers[FCSR] & CSR_C) + instrBuffer.targetAddr = (unsigned*)(registers[PC]+8); + else + instrBuffer.targetAddr = + (unsigned *)(((signed short)inst.IType.imm<<2) + + (registers[PC]+4)); + break; + case COPz_BCT: + case COPz_BCTL: + if (registers[FCSR] & CSR_C) + instrBuffer.targetAddr = + (unsigned *)(((signed short)inst.IType.imm<<2) + + (registers[PC]+4)); + else + instrBuffer.targetAddr = (unsigned*)(registers[PC]+8); + break; + }; + break; + } + + if is_steppable (instrBuffer.targetAddr) + { + instrBuffer.savedInstr = *instrBuffer.targetAddr; + *instrBuffer.targetAddr = BREAK_INSTR; + } + else + { + instrBuffer.targetAddr = NULL; + instrBuffer.savedInstr = NOP_INSTR; + } + return; +} + + +/* + * Translate the R4600 exception code into a Unix-compatible signal. + */ +static int +computeSignal (void) +{ + int exceptionCode = (registers[CAUSE] & CAUSE_EXCMASK) >> CAUSE_EXCSHIFT; + + switch (exceptionCode) + { + case EXC_INT: + /* External interrupt */ + return SIGINT; + + case EXC_RI: + /* Reserved instruction */ + case EXC_CPU: + /* Coprocessor unusable */ + return SIGILL; + + case EXC_BP: + /* Break point */ + return SIGTRAP; + + case EXC_OVF: + /* Arithmetic overflow */ + case EXC_TRAP: + /* Trap exception */ + case EXC_FPE: + /* Floating Point Exception */ + return SIGFPE; + + case EXC_IBE: + /* Bus error (Ifetch) */ + case EXC_DBE: + /* Bus error (data load or store) */ + return SIGBUS; + + case EXC_MOD: + /* TLB modification exception */ + case EXC_TLBL: + /* TLB miss (Load or Ifetch) */ + case EXC_TLBS: + /* TLB miss (Store) */ + case EXC_ADEL: + /* Address error (Load or Ifetch) */ + case EXC_ADES: + /* Address error (Store) */ + return SIGSEGV; + + case EXC_SYS: + /* System call */ + return SIGSYS; + + default: + return SIGTERM; + } +} + + +/* + * This function handles all exceptions. It only does two things: + * it figures out why it was activated and tells gdb, and then it + * reacts to gdb's requests. + */ +void +handle_exception (void) +{ + int host_has_detached = 0; + int sigval; + int regno, addr, length; + long long regval; + char *ptr; + + /* reply to host that an exception has occurred */ + sigval = computeSignal (); + outBuffer[0] = 'S'; + outBuffer[1] = highhex (sigval); + outBuffer[2] = lowhex (sigval); + outBuffer[3] = '\0'; + + putpacket (outBuffer); + + /* + * Restore the saved instruction at + * the single-step target address. + */ + undoSStep (); + + while (!(host_has_detached)) + { + outBuffer[0] = '\0'; + getpacket (inBuffer); + + switch (inBuffer[0]) + { + case '?': + outBuffer[0] = 'S'; + outBuffer[1] = highhex (sigval); + outBuffer[2] = lowhex (sigval); + outBuffer[3] = '\0'; + break; + + case 'g': + /* return the values of the CPU registers */ + mem2hex ((int) registers, sizeof registers, outBuffer); + break; + + case 'G': + /* set the values of the CPU registers - return OK */ + if (hex2mem (&inBuffer[1], (int) registers, sizeof registers)) + strcpy (outBuffer, "OK"); + else + strcpy (outBuffer, "E00"); /* E00 = bad "set register" command */ + break; + + case 'P': + /* Pn...=r... Write register n... with value r... - return OK */ + ptr = &inBuffer[1]; + if (hexToInt(&ptr, ®no) && + *ptr++ == '=' && + hexToLongLong(&ptr, ®val)) + { + registers[regno] = regval; + strcpy (outBuffer, "OK"); + } + else + strcpy (outBuffer, "E00"); /* E00 = bad "set register" command */ + break; + + case 'm': + /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ + ptr = &inBuffer[1]; + if (hexToInt (&ptr, &addr) + && *ptr++ == ',' + && hexToInt (&ptr, &length) + && is_readable (addr, length) + && (length < (BUFMAX - 4)/2)) + mem2hex (addr, length, outBuffer); + else + strcpy (outBuffer, "E01"); /* E01 = bad 'm' command */ + break; + + case 'M': + /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA - return OK */ + ptr = &inBuffer[1]; + if (hexToInt (&ptr, &addr) + && *ptr++ == ',' + && hexToInt (&ptr, &length) + && *ptr++ == ':' + && is_writeable (addr, length) + && hex2mem (ptr, addr, length)) + strcpy (outBuffer, "OK"); + else + strcpy (outBuffer, "E02"); /* E02 = bad 'M' command */ + break; + + case 'c': + /* cAA..AA Continue at address AA..AA(optional) */ + case 's': + /* sAA..AA Step one instruction from AA..AA(optional) */ + { + /* try to read optional parameter, pc unchanged if no parm */ + ptr = &inBuffer[1]; + if (hexToInt (&ptr, &addr)) + registers[PC] = addr; + + if (inBuffer[0] == 's') + doSStep (); + } + return; + + case 'D': + /* remote system is detaching - return OK and exit from debugger */ + strcpy (outBuffer, "OK"); + host_has_detached = 1; + break; + + default: + /* do nothing */ + break; + } /* switch */ + + /* reply to the request */ + putpacket (outBuffer); + } + return; +} diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.ld b/c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.ld 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<>16)&0xffff)/* set lower limit to unmapped addr */ + + addu k1,k0 /* this prevents a TLB exception */ + addiu k1,-16 /* set upper limit for 16 byte line */ +1: + cache Index_Store_Tag_I,(k0) /* write TAGLO/TAGHI to the cache */ + bnel k0,k1,1b /* do that by index so that a */ + addiu k0,k0,16 /* cache hit is not required */ + b 4f + nop +2: + addu k1,k0 /* come here for 32 byte line size */ + addiu k1,-32 +3: + cache Index_Store_Tag_I,(k0) + bnel k0,k1,3b + addiu k0,k0,32 +4: + .eject + mfc0 k0,C0_CONFIG /* repeat for D-cache */ + li k1,(1<<12) + and k0,CFG_DCMASK + srl k0,CFG_DCSHIFT + sll k1,k0 + + mfc0 k0,C0_CONFIG + nop + and k0,CFG_DBMASK + bne k0,zero,6f + lui k0,((K0BASE>>16)&0xffff) + + addu k1,k0 + addiu k1,-16 +5: + cache Index_Store_Tag_D,(k0) + bnel k0,k1,5b + addiu k0,k0,16 + b 8f + nop +6: + addu k1,k0 + addiu k1,-32 +7: + cache Index_Store_Tag_D,(k0) + bnel k0,k1,7b + addiu k0,k0,32 +8: + mfc0 k0,C0_CONFIG /* read config info one last time */ + li k1,~CFG_K0C_MASK /* clear K0 config field */ + and k0,k1 /* in CONFIG image register image */ + or k0,CFG_C_WRITEBACK /* set config to cached/writeback */ + mtc0 k0,C0_CONFIG /* write back to CP0 */ + nop /* wait for update to take effect */ + + .eject +/* + * Initialize the serial port + */ + li k0,DIV_LATCH_EN + WORD_LEN_MASK + la k1,ISA_IO_BASE /* set 8/bits char, no parity, and */ + sb k0,LINE_CTL_COM1(k1) /* enable access to divisor latch */ + + li k0,(1843200/(16*SERIAL_SPEED)) + sb k0,DIV_LO_COM1(k1) /* set clock divisor low byte */ + sra k0,8 + sb k0,DIV_HI_COM1(k1) /* set clock divisor high byte */ + + li k0,WORD_LEN_MASK /* set 8/bits char, no parity, and */ + sb k0,LINE_CTL_COM1(k1) /* disable access to divisor latch */ + + lbu k0,DATA_REG_COM1(k1) /* read & discard any existing char */ + sb zero,INT_ENA_COM1(k1) /* disable all interrupt sources */ + + li k0,RTS + DTR /* turn RTS and DTR on */ + sb k0,MODEM_CTL_COM1(k1) + +/* + * Reset all pending ISA interrupts + */ + la k1,ISA_IRQ3_RESET + sd zero,(k1) + la k1,ISA_IRQ4_RESET + sd zero,(k1) + la k1,ISA_IRQ5_RESET + sd zero,(k1) + la k1,ISA_IRQ9_RESET + sd zero,(k1) + + .eject +/* + * Clear the CAUSE register to indicate the + * absence of software-initiated exceptions. + */ + mtc0 zero,C0_CAUSE + +/* + * Clear floating point errors and configure + * the FPU to flush denormals to zero. + */ + li k0,CSR_FS + ctc1 k0,C1_CSR + +/* + * Clear the .bss area + */ + la k0,_fbss + la k1,_end +1: + addiu k1,k1,-8 + bne k1,k0,1b + sd zero,(k1) + +/* + * Save the ErrorEPC register, in case of a pushbutton + * reset, and join the general exception-handling path. + */ + la k0,registers + dmfc0 k1,C0_ERROREPC + j _common_path_join + sd k1,8*PC(k0) + + .align 9 + .eject +_tlbmiss_exception: /* bfc00200: tlbmiss exception */ + j _general_exception + nop + + .align 7 +_xtlbmiss_exception: /* bfc00280: xtlbmiss exception */ + j _general_exception + nop + + .align 7 +_cache_parity_error: /* bfc00300: cache parity error */ + j _reset_exception + nop + + .align 7 + /* bfc00380: general exception */ +/* + * Clear the register save area + */ +_general_exception: + la k0,registers + addiu k1,k0,8*(NUM_REGS-1) +1: + sd zero,(k1) + bnel k1,k0,1b + addiu k1,k1,-8 + +/* + * Save the PC + */ + dmfc0 k1,C0_EPC + nop + sd k1,8*PC(k0) + + .eject +/* + * Save the SR, CAUSE, and BAD_VA registers. + */ +_common_path_join: + mfc0 k1,C0_STATUS + nop + sd k1,8*SR(k0) + mfc0 k1,C0_CAUSE + nop + sd k1,8*CAUSE(k0) + mfc0 k1,C0_BADVADDR + nop + sd k1,8*BAD_VA(k0) + +/* + * Save LO, HI, and the general registers. + * Note that zero, k0 & k1 are not saved. + */ + mflo k1 + sd k1,8*LO(k0) + mfhi k1 + sd k1,8*HI(k0) + + /* zero is hard-wired */ + sd at,8*AT(k0) + + sd v0,8*V0(k0) + sd v1,8*V1(k0) + + sd a0,8*A0(k0) + sd a1,8*A1(k0) + sd a2,8*A2(k0) + sd a3,8*A3(k0) + + sd t0,8*T0(k0) + sd t1,8*T1(k0) + sd t2,8*T2(k0) + sd t3,8*T3(k0) + sd t4,8*T4(k0) + sd t5,8*T5(k0) + sd t6,8*T6(k0) + sd t7,8*T7(k0) + + .eject + sd s0,8*S0(k0) + sd s1,8*S1(k0) + sd s2,8*S2(k0) + sd s3,8*S3(k0) + sd s4,8*S4(k0) + sd s5,8*S5(k0) + sd s6,8*S6(k0) + sd s7,8*S7(k0) + + sd t8,8*T8(k0) + sd t9,8*T9(k0) + + /* k0 is not saved */ + /* k1 is not saved */ + + sd gp,8*GP(k0) + sd sp,8*SP(k0) + sd s8,8*S8(k0) + sd ra,8*RA(k0) + +/* + * Save the floating point control registers. + */ + cfc1 k1,C1_CSR + nop + sd k1,8*FCSR(k0) + cfc1 k1,C1_IRR + nop + sd k1,8*FIRR(k0) + +/* + * Save the even-numbered floating point registers. + */ + sdc1 $0,8*F0(k0) + sdc1 $2,8*F2(k0) + sdc1 $4,8*F4(k0) + sdc1 $6,8*F6(k0) + sdc1 $8,8*F8(k0) + sdc1 $10,8*F10(k0) + sdc1 $12,8*F12(k0) + sdc1 $14,8*F14(k0) + sdc1 $16,8*F16(k0) + sdc1 $18,8*F18(k0) + sdc1 $20,8*F20(k0) + sdc1 $22,8*F22(k0) + sdc1 $24,8*F24(k0) + sdc1 $26,8*F26(k0) + sdc1 $28,8*F28(k0) + sdc1 $30,8*F30(k0) + + .eject +/* + * If they are enabled, save the odd-numbered + * floating point registers as well. + */ + mfc0 k1,C0_STATUS + li at,SR_FR + and k1,at + beq k1,zero,1f + nop + sdc1 $1,8*F1(k0) + sdc1 $3,8*F3(k0) + sdc1 $5,8*F5(k0) + sdc1 $7,8*F7(k0) + sdc1 $9,8*F9(k0) + sdc1 $11,8*F11(k0) + sdc1 $13,8*F13(k0) + sdc1 $15,8*F15(k0) + sdc1 $17,8*F17(k0) + sdc1 $19,8*F19(k0) + sdc1 $21,8*F21(k0) + sdc1 $23,8*F23(k0) + sdc1 $25,8*F25(k0) + sdc1 $27,8*F27(k0) + sdc1 $29,8*F29(k0) + sdc1 $31,8*F31(k0) +1: + +/* + * Set up the global pointer and the stack + * and invoke the exception handler. + */ + la gp,_gp + la sp,_stack + jal handle_exception + addiu fp,sp,0 + + .eject +/* + * On exit from the exception handler invalidate each line in the I-cache + * and write back each dirty line in the D-cache. This needs to be done + * before the target program is resumed in order to ensure that software + * breakpoints and downloaded code will actually take effect. + */ + mfc0 t0,C0_CONFIG /* read config info into t0 */ + nop /* wait for CP0 read to take effect */ + + and t1,t0,CFG_ICMASK /* isolate I-cache shift */ + srl t1,t1,CFG_ICSHIFT /* count param into t1 */ + li t2,(1<<12) /* put base size in t2 */ + sllv t2,t2,t1 /* shift left to get actual size */ + + and t1,t0,CFG_IBMASK /* isolate linesize config bit */ + bne t1,zero,1f /* guess line size is 32 bytes */ + addiu t3,zero,32 /* skip next load if guessed right */ + addiu t3,zero,16 /* else set size to 16 bytes */ +1: + la t1,K0BASE /* set lower & upper address limits */ + addu t2,t2,t1 /* use kseg0 to avoid TLB exception */ + subu t2,t2,t3 +2: + cache Index_Invalidate_I,(t1) /* invalidate each I-cache line */ + bnel t1,t2,2b /* do this by index so that */ + addu t1,t1,t3 /* a hit is not required */ + + and t1,t0,CFG_DCMASK /* repeat for D-cache with writeback */ + srl t1,t1,CFG_DCSHIFT + li t2,(1<<12) + sllv t2,t2,t1 + + and t1,t0,CFG_DBMASK + bne t1,zero,3f + addiu t3,zero,32 + addiu t3,zero,16 +3: + la t1,K0BASE + addu t2,t2,t1 + subu t2,t2,t3 +4: + cache Index_Writeback_Inv_D,(t1) + bnel t1,t2,4b + addu t1,t1,t3 + + .eject +/* + * Now restore the registers. Note that they may + * have been modified while within the debugger. + * Start with even-numbered floating point registers. + */ + la k0,registers + ldc1 $0,8*F0(k0) + ldc1 $2,8*F2(k0) + ldc1 $4,8*F4(k0) + ldc1 $6,8*F6(k0) + ldc1 $8,8*F8(k0) + ldc1 $10,8*F10(k0) + ldc1 $12,8*F12(k0) + ldc1 $14,8*F14(k0) + ldc1 $16,8*F16(k0) + ldc1 $18,8*F18(k0) + ldc1 $20,8*F20(k0) + ldc1 $22,8*F22(k0) + ldc1 $24,8*F24(k0) + ldc1 $26,8*F26(k0) + ldc1 $28,8*F28(k0) + ldc1 $30,8*F30(k0) + +/* + * If they are enabled, restore the odd-numbered + * floating point registers as well. + */ + mfc0 k1,C0_STATUS + li at,SR_FR + and k1,at + beq k1,zero,1f + nop + ldc1 $1,8*F1(k0) + ldc1 $3,8*F3(k0) + ldc1 $5,8*F5(k0) + ldc1 $7,8*F7(k0) + ldc1 $9,8*F9(k0) + ldc1 $11,8*F11(k0) + ldc1 $13,8*F13(k0) + ldc1 $15,8*F15(k0) + ldc1 $17,8*F17(k0) + ldc1 $19,8*F19(k0) + ldc1 $21,8*F21(k0) + ldc1 $23,8*F23(k0) + ldc1 $25,8*F25(k0) + ldc1 $27,8*F27(k0) + ldc1 $29,8*F29(k0) + ldc1 $31,8*F31(k0) +1: + .eject +/* + * Restore the floating point control & status register. + * FIRR is not restored because it is read-only. + */ + ld k1,8*FCSR(k0) + ctc1 k1,C1_CSR + +/* + * Restore LO, HI, and the general registers. + */ + ld k1,8*LO(k0) + mtlo k1 + ld k1,8*HI(k0) + mthi k1 + + /* zero is hard-wired */ + ld at,8*AT(k0) + + ld v0,8*V0(k0) + ld v1,8*V1(k0) + + ld a0,8*A0(k0) + ld a1,8*A1(k0) + ld a2,8*A2(k0) + ld a3,8*A3(k0) + + ld t0,8*T0(k0) + ld t1,8*T1(k0) + ld t2,8*T2(k0) + ld t3,8*T3(k0) + ld t4,8*T4(k0) + ld t5,8*T5(k0) + ld t6,8*T6(k0) + ld t7,8*T7(k0) + + ld s0,8*S0(k0) + ld s1,8*S1(k0) + ld s2,8*S2(k0) + ld s3,8*S3(k0) + ld s4,8*S4(k0) + ld s5,8*S5(k0) + ld s6,8*S6(k0) + ld s7,8*S7(k0) + + ld t8,8*T8(k0) + ld t9,8*T9(k0) + + /* k0 is not restored */ + /* k1 is not restored */ + + ld gp,8*GP(k0) + ld sp,8*SP(k0) + ld s8,8*S8(k0) + ld ra,8*RA(k0) + + .eject +/* + * Restore the cause register, the status register, and the PC. Note + * that the saved PC is loaded into the ErrorEPC if ERL is set in the + * status register image and is loaded into the EPC otherwise. + */ + ld k1,8*CAUSE(k0) + mtc0 k1,C0_CAUSE + ld k1,8*SR(k0) + mtc0 k1,C0_STATUS + andi k1,k1,SR_ERL + beq k1,zero,1f + ld k1,8*PC(k0) +#if !defined(FORCE_PC_TO_32_BITS) + b 2f + dmtc0 k1,C0_ERROREPC +1: + dmtc0 k1,C0_EPC +2: +#else + addu k1,k1,zero + b 2f + dmtc0 k1,C0_ERROREPC +1: + addu k1,k1,zero + dmtc0 k1,C0_EPC +2: +#endif + +/* + * Flush the write buffer to memory. + */ + sync + +/* + * Hide the contents of k0 & k1 + * and return to the user program. + */ + move k0,zero + move k1,zero + eret + + .eject +/* + * char getDebugChar (void); + */ + .set reorder + .globl getDebugChar + .ent getDebugChar +getDebugChar: + la t0,ISA_IO_BASE /* point to ISA slot I/O */ +1: + lbu t1,LINE_STS_COM1(t0) /* read line status register */ + and t1,RX_CHAR_AVA /* isolate RX status bit */ + beqz t1,1b /* loop until char is available */ + + lbu v0,DATA_REG_COM1(t0) /* read the character */ + j ra /* and return */ + .end getDebugChar + +/* + * void putDebugChar (char); + */ + .set reorder + .globl putDebugChar + .ent putDebugChar +putDebugChar: + la t0,ISA_IO_BASE /* point to ISA slot I/O */ +1: + lbu t1,LINE_STS_COM1(t0) /* read line status register */ + and t1,TX_BUF_EMPTY /* isolate TX status bit */ + beqz t1,1b /* loop while buffer is full */ + + sb a0,DATA_REG_COM1(t0) /* write the outgoing character */ + sync /* flush the write buffer to memory */ + j ra /* and return */ + .end putDebugChar -- cgit v1.2.3