X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Fsparc-stub.c;h=1e6298a179e1c853e2928f6d970ffb6a8fe46a55;hb=56e2d25ab5b69584198204090fe049e920cd57db;hp=d81b6e57ae4a19c8852258e3757480f7d5f97f3c;hpb=4ecee2f9f17ab0cd2b4e10e3b1b75eb33f1b4940;p=binutils-gdb.git diff --git a/gdb/sparc-stub.c b/gdb/sparc-stub.c index d81b6e57ae4..1e6298a179e 100644 --- a/gdb/sparc-stub.c +++ b/gdb/sparc-stub.c @@ -31,6 +31,8 @@ * * 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. @@ -79,31 +81,26 @@ * ****************************************************************************/ -#include #include #include -#include /************************************************************************ * * external low-level support routines */ -extern putDebugChar(); /* write a single character */ -extern getDebugChar(); /* read and return a single char */ +extern void putDebugChar(); /* write a single character */ +extern int getDebugChar(); /* read and return a single char */ /************************************************************************/ /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ /* 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 @@ -121,63 +118,68 @@ enum regnames {G0, G1, G2, G3, G4, G5, G6, G7, 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 + +! Handle window overflow + + mov %g1, %l4 ! Save g1, we use it to hold the wim + srl %l3, 1, %g1 ! Rotate wim right + tst %g1 + bg good_wim ! Branch if new wim is non-zero + nop + +! At this point, we need to bring a 1 into the high order bit of the wim. +! Since we don't want to make any assumptions about the number of register +! windows, we figure it out dynamically so as to setup the wim correctly. + + not %g1 ! Fill g1 with ones + mov %g1, %wim ! Fill the wim with ones + nop + nop + nop + mov %wim, %g1 ! Read back the wim + inc %g1 ! Now g1 has 1 just to left of wim + srl %g1, 1, %g1 ! Now put 1 at top of wim + mov %g0, %wim ! Clear wim so that subsequent save + nop ! won't trap + nop 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 + +good_wim: + 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] @@ -188,111 +190,86 @@ _chk4ovflo: std %i6, [%sp + 14 * 4] restore ! Go back to trap window. - mov %l0, %g1 ! Restore %g1. + mov %l4, %g1 ! Restore %g1 -_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. +window_fine: + sethi %hi(in_trap_handler), %l4 + ld [%lo(in_trap_handler) + %l4], %l5 + tst %l5 + bg recursive_trap + inc %l5 - jmpl %l7+8, %g0 ! Window is valid, just return - sub %fp, (16+1+6+1)*4, %sp ! Make room for input & locals + set trapstack+1000*4, %sp ! Switch to trap stack + +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 + 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] -! 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, [%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 */ static int -hex(ch) - unsigned char ch; +hex (unsigned char ch) { if (ch >= 'a' && ch <= 'f') return ch-'a'+10; @@ -303,86 +280,79 @@ hex(ch) return -1; } +static char remcomInBuffer[BUFMAX]; +static char remcomOutBuffer[BUFMAX]; + /* scan for the sequence $# */ -static void -getpacket(buffer) - char *buffer; +unsigned char * +getpacket (void) { + unsigned char *buffer = &remcomInBuffer[0]; unsigned char checksum; unsigned char xmitcsum; - int i; int count; - unsigned char ch; + char ch; - do + while (1) { /* wait around for the start character, ignore all other characters */ - while ((ch = getDebugChar()) != '$') ; + while ((ch = getDebugChar ()) != '$') + ; +retry: checksum = 0; xmitcsum = -1; - count = 0; /* now, read until a # or end of buffer is found */ while (count < BUFMAX) { - ch = getDebugChar(); + ch = getDebugChar (); + if (ch == '$') + goto retry; if (ch == '#') break; checksum = checksum + ch; buffer[count] = ch; count = count + 1; } - - if (count >= BUFMAX) - continue; - buffer[count] = 0; if (ch == '#') { - xmitcsum = hex(getDebugChar()) << 4; - xmitcsum |= hex(getDebugChar()); -#ifdef DEBUG - if (remote_debug && checksum != xmitcsum) + ch = getDebugChar (); + xmitcsum = hex (ch) << 4; + ch = getDebugChar (); + xmitcsum += hex (ch); + + if (checksum != xmitcsum) { - fprintf(stderr, "bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n", - checksum,xmitcsum,buffer); + putDebugChar ('-'); /* failed checksum */ } -#endif -#if 1 - /* Humans shouldn't have to figure out checksums to type to it. */ - putDebugChar ('+'); - return; -#endif - if (checksum != xmitcsum) - putDebugChar('-'); /* failed checksum */ else { - putDebugChar('+'); /* successful transfer */ + 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 */ - count = strlen(buffer); - for (i=3; i <= count; i++) - buffer[i-3] = buffer[i]; + putDebugChar (buffer[0]); + putDebugChar (buffer[1]); + + return &buffer[3]; } + + return &buffer[0]; } } } - while (checksum != xmitcsum); } /* send the packet in buffer. */ static void -putpacket(buffer) - unsigned char *buffer; +putpacket (unsigned char *buffer) { unsigned char checksum; int count; @@ -397,8 +367,7 @@ putpacket(buffer) while (ch = buffer[count]) { - if (! putDebugChar(ch)) - return; + putDebugChar(ch); checksum += ch; count += 1; } @@ -411,48 +380,10 @@ putpacket(buffer) 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; - /* 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. @@ -461,11 +392,7 @@ set_char (addr, val) */ static unsigned char * -mem2hex(mem, buf, count, may_fault) - unsigned char *mem; - unsigned char *buf; - int count; - int may_fault; +mem2hex (unsigned char *mem, unsigned char *buf, int count, int may_fault) { unsigned char ch; @@ -473,7 +400,7 @@ mem2hex(mem, buf, count, may_fault) while (count-- > 0) { - ch = get_char(mem++); + ch = *mem++; if (mem_err) return 0; *buf++ = hexchars[ch >> 4]; @@ -491,11 +418,7 @@ mem2hex(mem, buf, count, may_fault) * return a pointer to the character AFTER the last byte written */ static char * -hex2mem(buf, mem, count, may_fault) - unsigned char *buf; - unsigned char *mem; - int count; - int may_fault; +hex2mem (unsigned char *buf, unsigned char *mem, int count, int may_fault) { int i; unsigned char ch; @@ -506,7 +429,7 @@ hex2mem(buf, mem, count, may_fault) { ch = hex(*buf++) << 4; ch |= hex(*buf++); - set_char(mem++, ch); + *mem++ = ch; if (mem_err) return 0; } @@ -516,40 +439,80 @@ hex2mem(buf, mem, count, may_fault) 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 (void) +{ + struct hard_trap_info *ht; + + for (ht = hard_trap_info; ht->tt && ht->signo; ht++) + exceptionHandler(ht->tt, trap_low); + + 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 (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; +computeSignal (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 */ } /* @@ -568,14 +531,12 @@ hexToInt(char **ptr, int *intValue) while (**ptr) { hexValue = hex(**ptr); - if (hexValue >=0) - { - *intValue = (*intValue <<4) | hexValue; - numChars ++; - } - else + if (hexValue < 0) break; + *intValue = (*intValue << 4) | hexValue; + numChars ++; + (*ptr)++; } @@ -588,28 +549,28 @@ hexToInt(char **ptr, int *intValue) * otherwise. */ -static int -handle_exception () +extern void breakinst(); + +static void +handle_exception (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 @@ -620,65 +581,64 @@ handle_exception () 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); - switch (remcomInBuffer[0]) + ptr = getpacket(); + switch (*ptr++) { case '?': remcomOutBuffer[0] = 'S'; @@ -687,19 +647,17 @@ handle_exception () remcomOutBuffer[3] = 0; break; - case 'd': - remote_debug = !remote_debug; /* toggle debug flag */ + case 'd': /* 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 */ } @@ -707,20 +665,34 @@ handle_exception () 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]; + + 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 */ - - ptr = &remcomInBuffer[1]; + /* Try to read %x,%x. */ if (hexToInt(&ptr, &addr) && *ptr++ == ',' @@ -730,19 +702,13 @@ handle_exception () 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 */ - - ptr = &remcomInBuffer[1]; + /* Try to read '%x,%x:'. */ if (hexToInt(&ptr, &addr) && *ptr++ == ',' @@ -752,34 +718,41 @@ handle_exception () 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]; if (hexToInt(&ptr, &addr)) { registers[PC] = addr; 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; +#if 0 + case 't': /* Test feature */ + asm (" std %f30,[%sp]"); + break; +#endif + case 'r': /* Reset */ + asm ("call 0 + nop "); + break; } /* switch */ /* reply to the request */ @@ -787,106 +760,19 @@ handle_exception () } } -/* 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. */ - - putDebugChar ('+'); - - initialized = 1; -} - -static void -set_mem_fault_trap(enable) - int enable; -{ - struct trap_entry *tb; /* Trap vector base address */ - - mem_err = 0; - - tb = (struct trap_entry *)(rdtbr() & ~0xfff); - - if (enable) - tb[9] = fltr_set_mem_err; - else - tb[9] = fltr_proto; -} - /* This function will generate a breakpoint exception. It is used at the beginning of a program to sync up with a debugger and can be used otherwise as a quick means to stop program execution and "break" into the debugger. */ void -breakpoint() +breakpoint (void) { - writez(1, "About to do a breakpoint\r\n\n"); - if (initialized) - BREAKPOINT(); + if (!initialized) + return; + + asm(" .globl _breakinst + + _breakinst: ta 1 + "); }