*
* Modified for SPARC by Stu Grossman, Cygnus Support.
*
+ * This code has been extensively tested on the Fujitsu SPARClite demo board.
+ *
* To enable debugger support, two things need to happen. One, a
* call to set_debug_traps() is necessary in order to allow any breakpoints
* or error conditions to be properly intercepted and reported to gdb.
*
* ? What was the last sigval ? SNN (signal NN)
*
+ * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
+ * baud rate
+ *
* All commands and responses are sent with a packet which includes a
* checksum. A packet consists of
*
*
****************************************************************************/
-#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <memory.h>
/* at least NUMREGBYTES*2 are needed for register packets */
#define BUFMAX 2048
-static int initialized; /* boolean flag. != 0 means we've been initialized */
+static int initialized = 0; /* !0 means we've been initialized */
static void set_mem_fault_trap();
-int remote_debug;
-/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
-
static const char hexchars[]="0123456789abcdef";
#define NUMREGS 72
F24, F25, F26, F27, F28, F29, F30, F31,
Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
-static unsigned long registers[NUMREGS] __attribute__ ((aligned (8)));
-
/*************************** ASSEMBLY CODE MACROS *************************/
/* */
-#define BREAKPOINT() asm(" ta 1");
-
-extern unsigned long rdtbr();
+extern void trap_low();
asm("
- .text
-!
-! FUNCTION
-! _chk4ovflo
-!
-! DESCRIPTION
-! This code is branched to before each trap (except reset,
-! _win_unf, and _win_ovf) handler.
-! It checks to see if we've moved into the invalid window
-! and performs fixup ala _win_ovf.
-!
-! INPUTS
-! - %l1 = pc at trap time.
-! - %l2 = npc at trap time.
-! - %l7 = return address.
-!
-! INTERNAL DESCRIPTION
-!
-! RETURNS
-! - None.
-!
+ .reserve trapstack, 1000 * 4, \"bss\", 8
+ .data
+ .align 4
+
+in_trap_handler:
+ .word 0
+
+ .text
.align 4
-_chk4ovflo:
- mov %psr, %l0 ! get the psr
- and %l0, 0x1F, %l3 ! get the cwp
- mov 1, %l4 ! compare cwp with the wim
- sll %l4, %l3, %l3 ! compare
- mov %wim, %l4 ! read the wim
- btst %l4, %l3
- bz _retsave ! not invalid window, just return
+! This function is called when any SPARC trap (except window overflow or
+! underflow) occurs. It makes sure that the invalid register window is still
+! available before jumping into C code. It will also restore the world if you
+! return from handle_exception.
+
+ .globl _trap_low
+_trap_low:
+ mov %psr, %l0
+ mov %wim, %l3
+
+ srl %l3, %l0, %l4 ! wim >> cwp
+ cmp %l4, 1
+ bne window_fine ! Branch if not in the invalid window
nop
- ! in line version of _win_ovf
- or %l0, 0xf20, %l3 ! enable traps, disable interrupts.
- mov %l3, %psr
- mov %g1, %l0 ! Save %g1.
- srl %l4, 1, %g1 ! Next WIM = %g1 = rol(WIM, 1, NWINDOW)
- sll %l4, 8-1, %l3
- bset %l3, %g1
- save %g0, %g0, %g0 ! Get into window to be saved.
- mov %g1, %wim ! Install new wim.
- nop ! must delay three instructions
- nop ! before using these registers, so
- nop ! put nops in just to be safe
-
- std %l0, [%sp + 0 * 4] ! save all local registers
+
+! Handle window overflow
+
+ mov %g1, %l4 ! Save g1, we use it to hold the wim
+ srl %l3, 1, %g1 ! Rotate wim right
+ sll %l3, 8-1, %l5
+ or %l5, %g1, %g1
+
+ save %g0, %g0, %g0 ! Slip into next window
+ mov %g1, %wim ! Install the new wim
+
+ std %l0, [%sp + 0 * 4] ! save L & I registers
std %l2, [%sp + 2 * 4]
std %l4, [%sp + 4 * 4]
std %l6, [%sp + 6 * 4]
std %i6, [%sp + 14 * 4]
restore ! Go back to trap window.
- mov %l0, %g1 ! Restore %g1.
+ mov %l4, %g1 ! Restore %g1
+
+window_fine:
+ sethi %hi(in_trap_handler), %l4
+ ld [%lo(in_trap_handler) + %l4], %l5
+ tst %l5
+ bg recursive_trap
+ inc %l5
-_retsave:
- ! It is safe now to allocate a stack frame for this window
- ! because all overflow handling will have been accomplished
- ! in the event we trapped into the invalid window.
- ! ie. all of this window's %o regs (next window's %i regs)
- ! will have been safely stored to the stack before we overwrite %sp.
+ set trapstack+1000*4, %sp ! Switch to trap stack
- jmpl %l7+8, %g0 ! Window is valid, just return
- sub %fp, (16+1+6+1)*4, %sp ! Make room for input & locals
+recursive_trap:
+ st %l5, [%lo(in_trap_handler) + %l4]
+ sub %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals
! + hidden arg + arg spill
! + doubleword alignment
+ ! + registers[72] local var
-! Read the TBR.
-
- .globl _rdtbr
-_rdtbr:
- retl
- mov %tbr, %o0
-
-! This function is called when any SPARC trap (except window overflow or
-! underflow) occurs. It makes sure that the invalid register window is still
-! available before jumping into C code. It will also restore the world if you
-! return from handle_exception.
-
-_trap_low:
- set _registers, %l0
+ std %g0, [%sp + (24 + 0) * 4] ! registers[Gx]
+ std %g2, [%sp + (24 + 2) * 4]
+ std %g4, [%sp + (24 + 4) * 4]
+ std %g6, [%sp + (24 + 6) * 4]
- std %g0, [%l0 + 0 * 4] ! registers[Gx]
- std %g2, [%l0 + 2 * 4]
- std %g4, [%l0 + 4 * 4]
- std %g6, [%l0 + 6 * 4]
-
- std %i0, [%l0 + 8 * 4] ! registers[Ox]
- std %i2, [%l0 + 10 * 4]
- std %i4, [%l0 + 12 * 4]
- std %i6, [%l0 + 14 * 4]
+ std %i0, [%sp + (24 + 8) * 4] ! registers[Ox]
+ std %i2, [%sp + (24 + 10) * 4]
+ std %i4, [%sp + (24 + 12) * 4]
+ std %i6, [%sp + (24 + 14) * 4]
! F0->F31 not implemented
mov %y, %l4
- mov %psr, %l5
- mov %wim, %l6
- mov %tbr, %l7
- std %l4, [%l0 + 64 * 4] ! Y & PSR
- std %l6, [%l0 + 66 * 4] ! WIM & TBR
- st %l1, [%l0 + 68 * 4] ! PC
- st %l2, [%l0 + 69 * 4] ! NPC
+ mov %tbr, %l5
+ st %l4, [%sp + (24 + 64) * 4] ! Y
+ st %l0, [%sp + (24 + 65) * 4] ! PSR
+ st %l3, [%sp + (24 + 66) * 4] ! WIM
+ st %l5, [%sp + (24 + 67) * 4] ! TBR
+ st %l1, [%sp + (24 + 68) * 4] ! PC
+ st %l2, [%sp + (24 + 69) * 4] ! NPC
! CPSR and FPSR not impl
- sethi %hi(_chk4ovflo), %l7 ! Must call this routine via %l7
- jmpl %l7+%lo(_chk4ovflo), %l7 ! because o regs may not be available yet
- nop
- mov %psr, %o1
- bset 0xf20, %o1
- mov %o1, %psr ! Turn on traps, disable interrupts
+ or %l0, 0xf20, %l4
+ mov %l4, %psr ! Turn on traps, disable interrupts
call _handle_exception
- nop
- mov %o0, %l7 ! Save return value
+ add %sp, 24 * 4, %o0 ! Pass address of registers
! Reload all of the registers that aren't on the stack
- set _registers, %l0 ! Need to use reg immune from save/rest
+ ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx]
+ ldd [%sp + (24 + 2) * 4], %g2
+ ldd [%sp + (24 + 4) * 4], %g4
+ ldd [%sp + (24 + 6) * 4], %g6
- ld [%l0 + 1 * 4], %g1 ! registers[Gx]
- ldd [%l0 + 2 * 4], %g2
- ldd [%l0 + 4 * 4], %g4
- ldd [%l0 + 6 * 4], %g6
+ ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox]
+ ldd [%sp + (24 + 10) * 4], %i2
+ ldd [%sp + (24 + 12) * 4], %i4
+ ldd [%sp + (24 + 14) * 4], %i6
- ldd [%l0 + 8 * 4], %o0 ! registers[Ox]
- ldd [%l0 + 10 * 4], %o2
- ldd [%l0 + 12 * 4], %o4
- ldd [%l0 + 14 * 4], %o6
+ ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR
+ ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC
restore ! Ensure that previous window is valid
save %g0, %g0, %g0 ! by causing a window_underflow trap
- ld [%l0 + 64 * 4], %l3 ! registers[Y]
- mov %l3, %y
- ld [%l0 + 65 * 4], %l3 ! registers[PSR]
- ld [%l0 + 68 * 4], %l1 ! registers[PC]
- ld [%l0 + 69 * 4], %l2 ! registers[NPC]
-
- tst %l7 ! Did handle_exception tell
- bg retskip ! us to skip the next inst?
- nop
-
- mov %l3, %psr ! Make sure that traps are disabled
+ mov %l0, %y
+ mov %l1, %psr ! Make sure that traps are disabled
! for rett
- jmpl %l1, %g0 ! Restore old PC
- rett %l2 ! Restore old nPC
- mov %l3, %psr ! Make sure that traps are disabled
- ! for rett
-retskip: ! Come here to skip the next instruction
- jmpl %l2, %g0 ! Old nPC
- rett %l2+4 ! Old nPC+4
+ sethi %hi(in_trap_handler), %l4
+ ld [%lo(in_trap_handler) + %l4], %l5
+ dec %l5
+ st %l5, [%lo(in_trap_handler) + %l4]
+
+ jmpl %l2, %g0 ! Restore old PC
+ rett %l3 ! Restore old nPC
");
/* Convert ch from a hex digit to an int */
{
xmitcsum = hex(getDebugChar()) << 4;
xmitcsum |= hex(getDebugChar());
-#ifdef DEBUG
- if (remote_debug && checksum != xmitcsum)
- {
- fprintf(stderr, "bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
- checksum,xmitcsum,buffer);
- }
-#endif
-#if 1
+#if 0
/* Humans shouldn't have to figure out checksums to type to it. */
putDebugChar ('+');
return;
while (getDebugChar() != '+');
}
-static unsigned char remcomInBuffer[BUFMAX];
-static unsigned char remcomOutBuffer[BUFMAX];
-static short error;
-
-static void
-debug_error(format, parm)
- char *format;
- char *parm;
-{
-#ifdef DEBUG
- if (remote_debug)
- fprintf(stderr,format,parm);
-#endif
-}
-
-/* Address of a routine to RTE to if we get a memory fault. */
-static void (*mem_fault_routine)() = NULL;
+static char remcomInBuffer[BUFMAX];
+static char remcomOutBuffer[BUFMAX];
/* Indicate to caller of mem2hex or hex2mem that there has been an
error. */
-
static volatile int mem_err = 0;
-/* These are separate functions so that they are so short and sweet
- that the compiler won't save any registers (if there is a fault
- to mem_fault, they won't get restored, so there better not be any
- saved). */
-static int
-get_char (addr)
- char *addr;
-{
- return *addr;
-}
-
-static void
-set_char (addr, val)
- char *addr;
- int val;
-{
- *addr = val;
-}
-
/* Convert the memory pointed to by mem into hex, placing result in buf.
* Return a pointer to the last char put in buf (null), in case of mem fault,
* return 0.
while (count-- > 0)
{
- ch = get_char(mem++);
+ ch = *mem++;
if (mem_err)
return 0;
*buf++ = hexchars[ch >> 4];
{
ch = hex(*buf++) << 4;
ch |= hex(*buf++);
- set_char(mem++, ch);
+ *mem++ = ch;
if (mem_err)
return 0;
}
return mem;
}
-/* this function takes the SPARC trap type code and attempts to
- translate this number into a unix compatible signal value */
+/* This table contains the mapping between SPARC hardware trap types, and
+ signals, which are primarily what GDB understands. It also indicates
+ which hardware traps we need to commandeer when initializing the stub. */
+
+static struct hard_trap_info
+{
+ unsigned char tt; /* Trap type code for SPARClite */
+ unsigned char signo; /* Signal that we map this trap into */
+} hard_trap_info[] = {
+ {1, SIGSEGV}, /* instruction access error */
+ {2, SIGILL}, /* privileged instruction */
+ {3, SIGILL}, /* illegal instruction */
+ {4, SIGEMT}, /* fp disabled */
+ {36, SIGEMT}, /* cp disabled */
+ {7, SIGBUS}, /* mem address not aligned */
+ {9, SIGSEGV}, /* data access exception */
+ {10, SIGEMT}, /* tag overflow */
+ {128+1, SIGTRAP}, /* ta 1 - normal breakpoint instruction */
+ {0, 0} /* Must be last */
+};
+
+/* Set up exception handlers for tracing and breakpoints */
+
+void
+set_debug_traps()
+{
+ struct hard_trap_info *ht;
+
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ exceptionHandler(ht->tt, trap_low);
+
+ /* In case GDB is started before us, ack any packets (presumably
+ "$?#xx") sitting there. */
+
+ putDebugChar ('+');
+
+ initialized = 1;
+}
+
+asm ("
+! Trap handler for memory errors. This just sets mem_err to be non-zero. It
+! assumes that %l1 is non-zero. This should be safe, as it is doubtful that
+! 0 would ever contain code that could mem fault. This routine will skip
+! past the faulting instruction after setting mem_err.
+
+ .text
+ .align 4
+
+_fltr_set_mem_err:
+ sethi %hi(_mem_err), %l0
+ st %l1, [%l0 + %lo(_mem_err)]
+ jmpl %l2, %g0
+ rett %l2+4
+");
+
+static void
+set_mem_fault_trap(enable)
+ int enable;
+{
+ extern void fltr_set_mem_err();
+ mem_err = 0;
+
+ if (enable)
+ exceptionHandler(9, fltr_set_mem_err);
+ else
+ exceptionHandler(9, trap_low);
+}
+
+/* Convert the SPARC hardware trap type code to a unix signal number. */
static int
computeSignal(tt)
int tt;
{
- int sigval;
+ struct hard_trap_info *ht;
- switch (tt)
- {
- case 1:
- sigval = SIGSEGV; break; /* instruction access error */
- case 2:
- sigval = SIGILL; break; /* privileged instruction */
- case 3:
- sigval = SIGILL; break; /* illegal instruction */
- case 4:
- sigval = SIGEMT; break; /* fp disabled */
- case 36:
- sigval = SIGEMT; break; /* cp disabled */
- case 7:
- sigval = SIGBUS; break; /* mem address not aligned */
- case 9:
- sigval = SIGSEGV; break; /* data access exception */
- case 10:
- sigval = SIGEMT; break; /* tag overflow */
- case 128+1: /* ta 1 - normal breakpoint instruction */
- case 255: /* breakpoint hardware unique to SPARClite */
- sigval = SIGTRAP; break; /* breakpoint trap */
- default:
- sigval = SIGHUP; /* "software generated"*/
- }
- return (sigval);
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ if (ht->tt == tt)
+ return ht->signo;
+
+ return SIGHUP; /* default for things we don't know about */
}
/*
while (**ptr)
{
hexValue = hex(**ptr);
- if (hexValue >=0)
- {
- *intValue = (*intValue <<4) | hexValue;
- numChars ++;
- }
- else
+ if (hexValue < 0)
break;
+ *intValue = (*intValue << 4) | hexValue;
+ numChars ++;
+
(*ptr)++;
}
* otherwise.
*/
-static int
-handle_exception ()
+extern void breakinst();
+
+static void
+handle_exception (registers)
+ unsigned long *registers;
{
int tt; /* Trap type */
int sigval;
int addr;
int length;
char *ptr;
- int newPC;
- unsigned char *sp;
- unsigned char *com;
+ unsigned long *sp;
/* First, we must force all of the windows to be spilled out */
- asm(" save %g0, -64, %g0
- save %g0, -64, %g0
- save %g0, -64, %g0
- save %g0, -64, %g0
- save %g0, -64, %g0
- save %g0, -64, %g0
- save %g0, -64, %g0
- save %g0, -64, %g0
+ asm(" save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
+ save %sp, -64, %sp
restore
restore
restore
restore
");
-#if 0
- writez(1, "Got to handle_exception()\r\n ");
-
- writez(1, "psr = 0x");
- numout(registers[PSR], 16);
- writez(1, " tbr = 0x");
- numout(registers[TBR], 16);
- writez(1, " oldpc = 0x");
- numout(registers[PC], 16);
- writez(1, " oldnpc = 0x");
- numout(registers[NPC], 16);
- writez(1, "\r\n");
-#endif
+ if (registers[PC] == (unsigned long)breakinst)
+ {
+ registers[PC] = registers[NPC];
+ registers[NPC] += 4;
+ }
- sp = (unsigned char *)registers[SP];
+ sp = (unsigned long *)registers[SP];
tt = (registers[TBR] >> 4) & 0xff;
-#ifdef DEBUG
- if (remote_debug)
- printf("tbr=0x%x, tt=%d, psr=0x%x, pc=0x%x, npc=0x%x\n",
- registers[TBR], (registers[TBR] >> 4) & 0xff, registers[PSR], registers[PC], registers[NPC]);
-#endif
-
/* reply to host that an exception has occurred */
sigval = computeSignal(tt);
- com = remcomOutBuffer;
-
- *com++ = 'T';
- *com++ = hexchars[sigval >> 4];
- *com++ = hexchars[sigval & 0xf];
-
- *com++ = hexchars[PC >> 4];
- *com++ = hexchars[PC & 0xf];
- com = mem2hex((char *)®isters[PC], com, 4, 0);
-
- *com++ = hexchars[FP >> 4];
- *com++ = hexchars[FP & 0xf];
- com = mem2hex(sp + (8 + 6) * 4, com, 4, 0); /* FP */
-
- *com++ = hexchars[SP >> 4];
- *com++ = hexchars[SP & 0xf];
- com = mem2hex((char *)®isters[SP], com, 4, 0);
-
- *com++ = hexchars[NPC >> 4];
- *com++ = hexchars[NPC & 0xf];
- com = mem2hex((char *)®isters[NPC], com, 4, 0);
-
- *com++ = 0;
+ ptr = remcomOutBuffer;
+
+ *ptr++ = 'T';
+ *ptr++ = hexchars[sigval >> 4];
+ *ptr++ = hexchars[sigval & 0xf];
+
+ *ptr++ = hexchars[PC >> 4];
+ *ptr++ = hexchars[PC & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)®isters[PC], ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[FP >> 4];
+ *ptr++ = hexchars[FP & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[SP >> 4];
+ *ptr++ = hexchars[SP & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)&sp, ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[NPC >> 4];
+ *ptr++ = hexchars[NPC & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)®isters[NPC], ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = hexchars[O7 >> 4];
+ *ptr++ = hexchars[O7 & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)®isters[O7], ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = 0;
putpacket(remcomOutBuffer);
while (1)
{
- error = 0;
remcomOutBuffer[0] = 0;
getpacket(remcomInBuffer);
break;
case 'd':
- remote_debug = !remote_debug; /* toggle debug flag */
+ /* toggle debug flag */
break;
case 'g': /* return the value of the CPU registers */
{
- com = remcomOutBuffer;
- com = mem2hex((char *)registers, com, 16 * 4, 0); /* G & O regs */
- com = mem2hex(sp + 0 * 4, com, 8 * 4, 0); /* L regs */
- com = mem2hex(sp + 8 * 4, com, 8 * 4, 0); /* I regs */
- memset(com, '0', 32 * 8); /* Floating point */
+ ptr = remcomOutBuffer;
+ ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
+ ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */
+ memset(ptr, '0', 32 * 8); /* Floating point */
mem2hex((char *)®isters[Y],
- com + 32 * 4 * 2,
+ ptr + 32 * 4 * 2,
8 * 4,
0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
}
case 'G': /* set the value of the CPU registers - return OK */
{
- com = &remcomInBuffer[1];
- hex2mem(com, (char *)registers, 16 * 4, 0); /* G & O regs */
- hex2mem(com + 16 * 4 * 2, sp + 0 * 4, 8 * 4, 0); /* L regs */
- hex2mem(com + 24 * 4 * 2, sp + 8 * 4, 8 * 4, 0); /* I regs */
- hex2mem(com + 64 * 4 * 2, (char *)®isters[Y],
+ unsigned long *newsp, psr;
+
+ psr = registers[PSR];
+
+ ptr = &remcomInBuffer[1];
+ hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
+ hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */
+ hex2mem(ptr + 64 * 4 * 2, (char *)®isters[Y],
8 * 4, 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
+
+ /* See if the stack pointer has moved. If so, then copy the saved
+ locals and ins to the new location. This keeps the window
+ overflow and underflow routines happy. */
+
+ newsp = (unsigned long *)registers[SP];
+ if (sp != newsp)
+ sp = memcpy(newsp, sp, 16 * 4);
+
+ /* Don't allow CWP to be modified. */
+
+ if (psr != registers[PSR])
+ registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
+
strcpy(remcomOutBuffer,"OK");
}
break;
case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
- /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
+ /* Try to read %x,%x. */
ptr = &remcomInBuffer[1];
break;
strcpy (remcomOutBuffer, "E03");
- debug_error ("memory fault");
}
else
- {
- strcpy(remcomOutBuffer,"E01");
- debug_error("malformed read memory command: %s",remcomInBuffer);
- }
+ strcpy(remcomOutBuffer,"E01");
break;
case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
- /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
+ /* Try to read '%x,%x:'. */
ptr = &remcomInBuffer[1];
if (hex2mem(ptr, (char *)addr, length, 1))
strcpy(remcomOutBuffer, "OK");
else
- {
- strcpy(remcomOutBuffer, "E03");
- debug_error("memory fault");
- }
+ strcpy(remcomOutBuffer, "E03");
}
else
- {
- strcpy(remcomOutBuffer, "E02");
- debug_error("malformed write memory command: %s",remcomInBuffer);
- }
+ strcpy(remcomOutBuffer, "E02");
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 = &remcomInBuffer[1];
registers[NPC] = addr + 4;
}
- return 0;
+/* Need to flush the instruction cache here, as we may have deposited a
+ breakpoint, and the icache probably has no way of knowing that a data ref to
+ some location may have changed something that is in the instruction cache.
+ */
+
+ flush_i_cache();
+ return;
/* kill the program */
case 'k' : /* do nothing */
break;
- } /* switch */
-
- /* reply to the request */
- putpacket(remcomOutBuffer);
- }
-}
-
-/* Each entry in the trap vector occupies four words. */
-
-struct trap_entry
-{
- unsigned long ti[4];
-};
-
-#define NUMTRAPS 256
-
-/* static struct trap_entry oldvec[NUMTRAPS];*/
-
-extern struct trap_entry fltr_proto;
-extern struct trap_entry fltr_set_mem_err;
-asm ("
- .data
- .globl _fltr_proto
- .align 4
-_fltr_proto: ! First level trap routine prototype
- sethi %hi(_trap_low), %l0
- jmpl %lo(_trap_low)+%l0, %g0
- nop
- nop
-
-! Trap handler for memory errors. This just sets mem_err to be non-zero. It
-! assumes that %l1 is non-zero. This should be safe, as it is doubtful that
-! 0 would ever contain code that could mem fault. This routine will skip
-! past the faulting instruction after setting mem_err.
-
-_fltr_set_mem_err:
- sethi %hi(_mem_err), %l0
- st %l1, [%l0 + %lo(_mem_err)]
- jmpl %l2, %g0
- rett %l2+4
-
- .text
-");
-
-/* this function is used to set up exception handlers for tracing and
- breakpoints */
-
-void
-set_debug_traps()
-{
- int exception;
- struct trap_entry *tb; /* Trap vector base address */
-
- writez(1, "Got to set_debug_traps\r\n");
-
- tb = (struct trap_entry *)(rdtbr() & ~0xfff);
-
- writez(1, "tb = 0x");
- numout(tb, 16);
- writez(1, " trap ins = 0x");
- numout(fltr_proto, 16);
- writez(1, "\r\n");
-
- tb[1] = fltr_proto; /* instruction access exception */
- tb[2] = fltr_proto; /* privileged instruction */
- tb[3] = fltr_proto; /* illegal instruction */
- tb[4] = fltr_proto; /* fp disabled */
- tb[36] = fltr_proto; /* cp disabled */
- tb[7] = fltr_proto; /* mem address not aligned */
- tb[9] = fltr_proto; /* data access exception */
- tb[10] = fltr_proto; /* tag overflow */
- tb[128+1] = fltr_proto; /* breakpoint instruction (ta 1) */
- tb[255] = fltr_proto; /* hardware breakpoint trap */
-
- /* In case GDB is started before us, ack any packets (presumably
- "$?#xx") sitting there. */
+#if 0
+ case 't': /* Test feature */
+ asm (" std %f31,[%sp]");
+ break;
+#endif
+ case 'r': /* Reset */
+ asm ("call 0
+ nop ");
+ break;
- putDebugChar ('+');
+#if 0
+Disabled until we can unscrew this properly
- initialized = 1;
-}
+ case 'b': /* bBB... Set baud rate to BB... */
+ {
+ int baudrate;
+ extern void set_timer_3();
-static void
-set_mem_fault_trap(enable)
- int enable;
-{
- struct trap_entry *tb; /* Trap vector base address */
+ ptr = &remcomInBuffer[1];
+ if (!hexToInt(&ptr, &baudrate))
+ {
+ strcpy(remcomOutBuffer,"B01");
+ break;
+ }
- mem_err = 0;
+ /* Convert baud rate to uart clock divider */
+ switch (baudrate)
+ {
+ case 38400:
+ baudrate = 16;
+ break;
+ case 19200:
+ baudrate = 33;
+ break;
+ case 9600:
+ baudrate = 65;
+ break;
+ default:
+ strcpy(remcomOutBuffer,"B02");
+ goto x1;
+ }
- tb = (struct trap_entry *)(rdtbr() & ~0xfff);
+ putpacket("OK"); /* Ack before changing speed */
+ set_timer_3(baudrate); /* Set it */
+ }
+x1: break;
+#endif
+ } /* switch */
- if (enable)
- tb[9] = fltr_set_mem_err;
- else
- tb[9] = fltr_proto;
+ /* reply to the request */
+ putpacket(remcomOutBuffer);
+ }
}
/* This function will generate a breakpoint exception. It is used at the
void
breakpoint()
{
- writez(1, "About to do a breakpoint\r\n\n");
- if (initialized)
- BREAKPOINT();
+ if (!initialized)
+ return;
+
+ asm(" .globl _breakinst
+
+ _breakinst: ta 1
+ ");
}