X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;ds=sidebyside;f=gdb%2Fsparc-stub.c;h=ce2aadd67b765ac3f5f6a11c5410a0c697e66aea;hb=a960f24961375851112ce6c45c8f7ae9a505bf6c;hp=47b98109d73a43733946ce424609c558940aebbe;hpb=4ddd278ffa3e6fb6aa2e956aa0c2a25b58bf56b7;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/sparc-stub.c b/gdb/sparc-stub.c index 47b98109d7..ce2aadd67b 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. @@ -60,9 +62,6 @@ * * ? 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 * @@ -84,22 +83,21 @@ #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(); @@ -123,27 +121,27 @@ enum regnames {G0, G1, G2, G3, G4, G5, G6, G7, /*************************** ASSEMBLY CODE MACROS *************************/ /* */ -#define BREAKPOINT() asm(" ta 1"); - -extern unsigned long rdtbr(); +extern void trap_low(); asm(" - .text - .align 4 + .reserve trapstack, 1000 * 4, \"bss\", 8 + + .data + .align 4 -! Read the TBR. +in_trap_handler: + .word 0 - .globl _rdtbr -_rdtbr: - retl - mov %tbr, %o0 + .text + .align 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: + .globl _trap_low +_trap_low: mov %psr, %l0 mov %wim, %l3 @@ -156,9 +154,28 @@ trap_low: 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 + 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 +good_wim: save %g0, %g0, %g0 ! Slip into next window mov %g1, %wim ! Install the new wim @@ -176,29 +193,39 @@ trap_low: mov %l4, %g1 ! Restore %g1 window_fine: - sub %fp, (16+1+6+1+72)*4, %sp ! Make room for input & locals + sethi %hi(in_trap_handler), %l4 + ld [%lo(in_trap_handler) + %l4], %l5 + tst %l5 + bg recursive_trap + inc %l5 + + 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 - std %g0, [%fp + (-72 + 0) * 4] ! registers[Gx] - std %g2, [%fp + (-72 + 2) * 4] - std %g4, [%fp + (-72 + 4) * 4] - std %g6, [%fp + (-72 + 6) * 4] + 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 %i0, [%fp + (-72 + 8) * 4] ! registers[Ox] - std %i2, [%fp + (-72 + 10) * 4] - std %i4, [%fp + (-72 + 12) * 4] - std %i6, [%fp + (-72 + 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 %tbr, %l5 - st %l4, [%fp + (-72 + 64) * 4] ! Y - st %l0, [%fp + (-72 + 65) * 4] ! PSR - st %l3, [%fp + (-72 + 66) * 4] ! WIM - st %l5, [%fp + (-72 + 67) * 4] ! TBR - st %l1, [%fp + (-72 + 68) * 4] ! PC - st %l2, [%fp + (-72 + 69) * 4] ! NPC + 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 @@ -206,28 +233,35 @@ window_fine: mov %l4, %psr ! Turn on traps, disable interrupts call _handle_exception - add %fp, -72 * 4, %o0 ! Pass address of registers - - restore ! Ensure that previous window is valid - save %g0, %g0, %g0 ! by causing a window_underflow trap + add %sp, 24 * 4, %o0 ! Pass address of registers ! Reload all of the registers that aren't on the stack - ld [%fp + (-72 + 1) * 4], %g1 ! registers[Gx] - ldd [%fp + (-72 + 2) * 4], %g2 - ldd [%fp + (-72 + 4) * 4], %g4 - ldd [%fp + (-72 + 6) * 4], %g6 + 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 + + 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 [%fp + (-72 + 8) * 4], %o0 ! registers[Ox] - ldd [%fp + (-72 + 10) * 4], %o2 - ldd [%fp + (-72 + 12) * 4], %o4 - ldd [%fp + (-72 + 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 - ldd [%fp + (-72 + 64) * 4], %l0 ! Y & PSR - ldd [%fp + (-72 + 68) * 4], %l2 ! PC & NPC mov %l0, %y mov %l1, %psr ! Make sure that traps are disabled ! for rett + + 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 "); @@ -247,67 +281,73 @@ 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 () { + 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()); + ch = getDebugChar (); + xmitcsum = hex (ch) << 4; + ch = getDebugChar (); + xmitcsum += hex (ch); + if (checksum != xmitcsum) - putDebugChar('-'); /* failed checksum */ + { + 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. */ @@ -329,8 +369,7 @@ putpacket(buffer) while (ch = buffer[count]) { - if (! putDebugChar(ch)) - return; + putDebugChar(ch); checksum += ch; count += 1; } @@ -343,9 +382,6 @@ putpacket(buffer) while (getDebugChar() != '+'); } -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; @@ -434,74 +470,46 @@ static struct hard_trap_info {0, 0} /* Must be last */ }; -/* Each entry in the trap vector occupies four words. */ +/* Set up exception handlers for tracing and breakpoints */ -struct trap_entry +void +set_debug_traps() { - unsigned long ti[4]; -}; + struct hard_trap_info *ht; -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 + 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 - - .text "); -/* Set up exception handlers for tracing and breakpoints */ - -void -set_debug_traps() -{ - struct trap_entry *tb; /* Trap vector base address */ - struct hard_trap_info *ht; - - tb = (struct trap_entry *)(rdtbr() & ~0xfff); - - for (ht = hard_trap_info; ht->tt && ht->signo; ht++) - tb[ht->tt] = fltr_proto; - - /* 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 */ - + extern void fltr_set_mem_err(); mem_err = 0; - tb = (struct trap_entry *)(rdtbr() & ~0xfff); - if (enable) - tb[9] = fltr_set_mem_err; + exceptionHandler(9, fltr_set_mem_err); else - tb[9] = fltr_proto; + exceptionHandler(9, trap_low); } /* Convert the SPARC hardware trap type code to a unix signal number. */ @@ -553,6 +561,8 @@ hexToInt(char **ptr, int *intValue) * otherwise. */ +extern void breakinst(); + static void handle_exception (registers) unsigned long *registers; @@ -584,6 +594,12 @@ handle_exception (registers) restore "); + if (registers[PC] == (unsigned long)breakinst) + { + registers[PC] = registers[NPC]; + registers[NPC] += 4; + } + sp = (unsigned long *)registers[SP]; tt = (registers[TBR] >> 4) & 0xff; @@ -634,8 +650,8 @@ handle_exception (registers) { remcomOutBuffer[0] = 0; - getpacket(remcomInBuffer); - switch (remcomInBuffer[0]) + ptr = getpacket(); + switch (*ptr++) { case '?': remcomOutBuffer[0] = 'S'; @@ -644,16 +660,14 @@ handle_exception (registers) remcomOutBuffer[3] = 0; break; - case 'd': - /* toggle debug flag */ + case 'd': /* toggle debug flag */ break; case 'g': /* return the value of the CPU registers */ { ptr = remcomOutBuffer; ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */ - ptr = mem2hex(sp + 0, ptr, 8 * 4, 0); /* L regs */ - ptr = mem2hex(sp + 8, ptr, 8 * 4, 0); /* I regs */ + ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */ memset(ptr, '0', 32 * 8); /* Floating point */ mem2hex((char *)®isters[Y], ptr + 32 * 4 * 2, @@ -664,12 +678,28 @@ handle_exception (registers) case 'G': /* set the value of the CPU registers - return OK */ { - ptr = &remcomInBuffer[1]; + unsigned long *newsp, psr; + + psr = registers[PSR]; + hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */ - hex2mem(ptr + 16 * 4 * 2, sp + 0, 8 * 4, 0); /* L regs */ - hex2mem(ptr + 24 * 4 * 2, sp + 8, 8 * 4, 0); /* I 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; @@ -677,8 +707,6 @@ handle_exception (registers) case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ /* Try to read %x,%x. */ - ptr = &remcomInBuffer[1]; - if (hexToInt(&ptr, &addr) && *ptr++ == ',' && hexToInt(&ptr, &length)) @@ -695,8 +723,6 @@ handle_exception (registers) case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ /* Try to read '%x,%x:'. */ - ptr = &remcomInBuffer[1]; - if (hexToInt(&ptr, &addr) && *ptr++ == ',' && hexToInt(&ptr, &length) @@ -712,10 +738,8 @@ handle_exception (registers) 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; @@ -734,42 +758,14 @@ handle_exception (registers) case 'k' : /* do nothing */ break; #if 0 -Disabled until we can unscrew this properly - - case 'b': /* bBB... Set baud rate to BB... */ - { - int baudrate; - extern void set_timer_3(); - - ptr = &remcomInBuffer[1]; - if (!hexToInt(&ptr, &baudrate)) - { - strcpy(remcomOutBuffer,"B01"); - break; - } - - /* 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; - } - - putpacket("OK"); /* Ack before changing speed */ - set_timer_3(baudrate); /* Set it */ - } -x1: break; + case 't': /* Test feature */ + asm (" std %f30,[%sp]"); + break; #endif + case 'r': /* Reset */ + asm ("call 0 + nop "); + break; } /* switch */ /* reply to the request */ @@ -785,6 +781,11 @@ x1: break; void breakpoint() { - if (initialized) - BREAKPOINT(); + if (!initialized) + return; + + asm(" .globl _breakinst + + _breakinst: ta 1 + "); }