summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2002-02-08 21:26:00 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2002-02-08 21:26:00 +0000
commitfc82e7107274789c558a8a4fbc3a4d210edec672 (patch)
tree2e29f0b2f19080ef6db46565006ddc7de9307c1e /c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c
parent2002-02-08 Joel Sherrill <joel@OARcorp.com> (diff)
downloadrtems-fc82e7107274789c558a8a4fbc3a4d210edec672.tar.bz2
2002-02-08 Joel Sherrill <joel@OARcorp.com>
* Makefile, stubinit.S, r46kstub.ld, ioaddr.h: Removed as unused with RTEMS. * r46kstub.c: Renamed to mips-stub.c. * mips-stub.c: New file -- was r46kstub.c. * memlimits.h: New file was limits.h. * limits.h: Removed. * r4600.h: Eliminated need for this file. * README: Updated. * gdb_if.h: Added CVS Id. * mips-stub.c: Attempt to deal with MIPS1 versus MIPS3.
Diffstat (limited to 'c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c')
-rw-r--r--c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c844
1 files changed, 0 insertions, 844 deletions
diff --git a/c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c b/c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c
deleted file mode 100644
index 801317c405..0000000000
--- a/c/src/lib/libbsp/mips/shared/gdbstub/r46kstub.c
+++ /dev/null
@@ -1,844 +0,0 @@
-/*******************************************************************************
-
- THIS SOFTWARE IS NOT COPYRIGHTED
-
- The following software is offered for use in the public domain.
- There is no warranty with regard to this software or its performance
- and the user must accept the software "AS IS" with all faults.
-
- THE CONTRIBUTORS DISCLAIM ANY WARRANTIES, EXPRESS OR IMPLIED, WITH
- REGARD TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-
-********************************************************************************
-*
-* r46kstub.c -- target debugging stub for the IDT R4600 Orion processor
-*
-* This module is based on the stub for the Hitachi SH processor written by
-* Ben Lee and Steve Chamberlain and supplied with gdb 4.16. The latter
-* in turn "is originally based on an m68k software stub written by Glenn
-* Engel at HP, but has changed quite a bit." The changes for the R4600
-* were written by C. M. Heard at VVNET. They were based in part on the
-* Algorithmics R4000 version of Phil Bunce's PMON program.
-*
-* Remote communication protocol:
-*
-* A debug packet whose contents are <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;
-}