📄 sparcl-stub.c
字号:
set_mem_fault_trap(0); return buf;}/* convert the hex array pointed to by buf into binary to be placed in mem * 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;{ int i; unsigned char ch; set_mem_fault_trap(may_fault); for (i=0; i<count; i++) { ch = hex(*buf++) << 4; ch |= hex(*buf++); *mem++ = ch; if (mem_err) return 0; } set_mem_fault_trap(0); return mem;}/* 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 */ {255, SIGTRAP}, /* hardware breakpoint */ {0, 0} /* Must be last */};/* Set up exception handlers for tracing and breakpoints */voidset_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" STRINGSYM(fltr_set_mem_err) ": sethi %hi(" STRINGSYM(mem_err) "), %l0 st %l1, [%l0 + %lo(" STRINGSYM(mem_err) ")] jmpl %l2, %g0 rett %l2+4");static voidset_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);}asm (" .text .align 4" STRINGSYM(dummy_hw_breakpoint) ": jmpl %l2, %g0 rett %l2+4 nop nop");static voidset_hw_breakpoint_trap(enable) int enable;{ extern void dummy_hw_breakpoint(); if (enable) exceptionHandler(255, dummy_hw_breakpoint); else exceptionHandler(255, trap_low);}static voidget_in_break_mode(){ set_hw_breakpoint_trap(1); asm(" sethi %hi(0xff10), %l4 or %l4, %lo(0xff10), %l4 sta %g0, [%l4]0x1 nop nop nop "); set_hw_breakpoint_trap(0);}/* Convert the SPARC hardware trap type code to a unix signal number. */static intcomputeSignal(tt) int tt;{ struct hard_trap_info *ht; 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 we find nice hex chars, build an int. * Return number of chars processed. */static inthexToInt(char **ptr, int *intValue){ int numChars = 0; int hexValue; *intValue = 0; while (**ptr) { hexValue = hex(**ptr); if (hexValue < 0) break; *intValue = (*intValue << 4) | hexValue; numChars ++; (*ptr)++; } return (numChars);}/* Replacement for outbyte that sends a packet to GDB containing the character to be output. */static voidoutbyte_stub (int c){ static char buf[4]; buf[0] = 'O'; buf[1] = hexchars[(c >> 4) & 0xf]; buf[2] = hexchars[c % 16]; buf[3] = 0; putpacket (buf);}/* * This function does all command procesing for interfacing to gdb. It * returns 1 if you should skip the instruction at the trap address, 0 * otherwise. */static voidhandle_exception (registers) unsigned long *registers;{ int tt; /* Trap type */ int sigval; int addr; int length; char *ptr; unsigned long *sp; unsigned long dsr;/* First, we must force all of the windows to be spilled out */ 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 restore restore restore restore"); if (registers[PC] == (unsigned long)breakinst) { registers[PC] = registers[NPC]; registers[NPC] += 4; } sp = (unsigned long *)registers[SP]; dsr = (unsigned long)registers[DSR]; if (dsr & 0x3c) { tt = 255; } else { tt = (registers[TBR] >> 4) & 0xff; } /* reply to host that an exception has occurred */ sigval = computeSignal(tt); 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); __outbyte_hook = outbyte_stub; while (1) { remcomOutBuffer[0] = 0; getpacket(remcomInBuffer); switch (remcomInBuffer[0]) { case '?': remcomOutBuffer[0] = 'S'; remcomOutBuffer[1] = hexchars[sigval >> 4]; remcomOutBuffer[2] = hexchars[sigval & 0xf]; remcomOutBuffer[3] = 0; break; 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, 16 * 4, 0); /* L & I regs */ memset(ptr, '0', 32 * 8); /* Floating point */ ptr = mem2hex((char *)®isters[Y], ptr + 32 * 4 * 2, 8 * 4, 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ mem2hex((char *)®isters[DIA1], ptr, 8 * 4, 0); /* DIA1, DIA2, DDA1, DDA2, DDV1, DDV2, DCR, DSR */ } break; case 'G': /* set the value of the CPU registers - return OK */ { 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 */ hex2mem(ptr + 72 * 4 * 2, (char *)®isters[DIA1], 8 * 4, 0); /* DIA1, DIA2, DDA1, DDA2, DDV1, DDV2, DCR, DSR */ /* 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. */ ptr = &remcomInBuffer[1]; if (hexToInt(&ptr, &addr) && *ptr++ == ',' && hexToInt(&ptr, &length)) { if (mem2hex((char *)addr, remcomOutBuffer, length, 1)) break; strcpy (remcomOutBuffer, "E03"); } else strcpy(remcomOutBuffer,"E01"); break; 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) && *ptr++ == ':') { if (hex2mem(ptr, (char *)addr, length, 1)) strcpy(remcomOutBuffer, "OK"); else strcpy(remcomOutBuffer, "E03"); } else strcpy(remcomOutBuffer, "E02"); break; case 'c': /* cAA..AA Continue at address 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; }/* 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;#if 0Disabled 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;#endif } /* switch */ /* reply to the request */ putpacket(remcomOutBuffer); }}/* 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. */voidbreakpoint(){ if (!initialized) return; asm(" .globl " STRINGSYM(breakinst) " " STRINGSYM(breakinst) ": ta 1 ");}static voidhw_breakpoint(){ asm(" ta 127 ");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -