📄 sparclet-stub.c
字号:
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 exception */ {0x3b, SIGSEGV}, /* instruction access error */ {2, SIGILL}, /* illegal instruction */ {3, SIGILL}, /* privileged instruction */ {4, SIGEMT}, /* fp disabled */ {0x24, SIGEMT}, /* cp disabled */ {7, SIGBUS}, /* mem address not aligned */ {0x29, 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 */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_fltr_set_mem_err: sethi %hi(_mem_err), %l0 st %l1, [%l0 + %lo(_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(0x29, fltr_set_mem_err); else exceptionHandler(0x29, trap_low);}asm (" .text .align 4_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(){#if 0 int x; mesg("get_in_break_mode, sp = "); phex(&x);#endif 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);}/* * 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(" ! Ugh. sparclet has broken save !save %sp, -64, %sp save add %fp,-64,%sp !save %sp, -64, %sp save add %fp,-64,%sp !save %sp, -64, %sp save add %fp,-64,%sp !save %sp, -64, %sp save add %fp,-64,%sp !save %sp, -64, %sp save add %fp,-64,%sp !save %sp, -64, %sp save add %fp,-64,%sp !save %sp, -64, %sp save add %fp,-64,%sp !save %sp, -64, %sp save add %fp,-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]; 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); 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': remote_debug = !(remote_debug); /* 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 */ ptr = mem2hex((char *)®isters[CCSR], ptr, 8 * 4, 0); /* CCSR, CCPR, CCCRCR, CCOR, CCOBR, CCIBR, CCIR */ ptr = mem2hex((char *)®isters[ASR1], ptr, 8 * 4, 0); /* ASR1,ASR15,ASR17,ASR18,ASR19,ASR20,ASR21,ASR22 */#if 0 /* not implemented */ ptr = mem2hex((char *) ®isters[AWR0], ptr, 32 * 4, 0); /* Alternate Window Registers */#endif } break; case 'G': /* set value of all the CPU registers - return OK */ case 'P': /* set value of one CPU register - return OK */ { unsigned long *newsp, psr; psr = registers[PSR]; ptr = &remcomInBuffer[1]; if (remcomInBuffer[0] == 'P') /* do a single register */ { int regno; if (hexToInt (&ptr, ®no) && *ptr++ == '=') if (regno >= L0 && regno <= I7) hex2mem (ptr, sp + regno - L0, 4, 0); else hex2mem (ptr, (char *)®isters[regno], 4, 0); else { strcpy (remcomOutBuffer, "P01"); break; } } else { 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[CCSR], 8 * 4, 0); /* CCSR,CCPR,CCCRCR,CCOR,CCOBR,CCIBR,CCIR */ hex2mem(ptr + 80 * 4 * 2, (char *)®isters[ASR1], 8 * 4, 0); /* ASR1 ... ASR22 */#if 0 /* not implemented */ hex2mem(ptr + 88 * 4 * 2, (char *)®isters[AWR0], 8 * 4, 0); /* Alternate Window Registers */#endif } /* 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 _breakinst _breakinst: ta 1 ");}static voidhw_breakpoint(){ asm(" ta 127 ");}#if 0 /* experimental and never finished, left here for reference */static voidsplet_temp(void){ asm(" sub %sp,(16+1+6+1+121)*4,%sp ! Make room for input & locals ! + hidden arg + arg spill ! + doubleword alignment ! + registers[121]! Leave a trail of breadcrumbs! (save register save area for debugging) mov %sp, %l0 add %l0, 24*4, %l0 sethi %hi(_debug_registers), %l1 st %l0, [%lo(_debug_registers) + %l1]! Save the Alternate Register Set: (not implemented yet)! To save the Alternate Register set, we must:! 1) Save the current SP in some global location.! 2) Swap the register sets.! 3) Save the Alternate SP in the Y register! 4) Fetch the SP that we saved in step 1.! 5) Use that to save the rest of the regs (not forgetting ASP in Y)! 6) Restore the Alternate SP from Y! 7) Swap the registers back.! 1) Copy the current stack pointer to global _SAVED_STACK_POINTER: sethi %hi(_saved_stack_pointer), %l0 st %sp, [%lo(_saved_stack_pointer) + %l0]! 2) Swap the register sets: mov %psr, %l1 sethi %hi(0x10000), %l2 xor %l1, %l2, %l1 mov %l1, %psr nop ! 3 nops after write to %psr (needed?) nop nop! 3) Save Alternate L0 in Y wr %l0, 0, %y! 4) Load former SP into alternate SP, using L0 sethi %hi(_saved_stack_pointer), %l0 or %lo(_saved_stack_pointer), %l0, %l0 swap [%l0], %sp! 4.5) Restore alternate L0 rd %y, %l0! 5) Save the Alternate Window Registers st %r0, [%sp + (24 + 88) * 4] ! AWR0 st %r1, [%sp + (24 + 89) * 4] ! AWR1 st %r2, [%sp + (24 + 90) * 4] ! AWR2 st %r3, [%sp + (24 + 91) * 4] ! AWR3 st %r4, [%sp + (24 + 92) * 4] ! AWR4 st %r5, [%sp + (24 + 93) * 4] ! AWR5 st %r6, [%sp + (24 + 94) * 4] ! AWR6 st %r7, [%sp + (24 + 95) * 4] ! AWR7 st %r8, [%sp + (24 + 96) * 4] ! AWR8 st %r9, [%sp + (24 + 97) * 4] ! AWR9 st %r10, [%sp + (24 + 98) * 4] ! AWR10 st %r11, [%sp + (24 + 99) * 4] ! AWR11 st %r12, [%sp + (24 + 100) * 4] ! AWR12 st %r13, [%sp + (24 + 101) * 4] ! AWR13! st %r14, [%sp + (24 + 102) * 4] ! AWR14 (SP) st %r15, [%sp + (24 + 103) * 4] ! AWR15 st %r16, [%sp + (24 + 104) * 4] ! AWR16 st %r17, [%sp + (24 + 105) * 4] ! AWR17 st %r18, [%sp + (24 + 106) * 4] ! AWR18 st %r19, [%sp + (24 + 107) * 4] ! AWR19 st %r20, [%sp + (24 + 108) * 4] ! AWR20 st %r21, [%sp + (24 + 109) * 4] ! AWR21 st %r22, [%sp + (24 + 110) * 4] ! AWR22 st %r23, [%sp + (24 + 111) * 4] ! AWR23 st %r24, [%sp + (24 + 112) * 4] ! AWR24 st %r25, [%sp + (24 + 113) * 4] ! AWR25 st %r26, [%sp + (24 + 114) * 4] ! AWR26 st %r27, [%sp + (24 + 115) * 4] ! AWR27 st %r28, [%sp + (24 + 116) * 4] ! AWR28 st %r29, [%sp + (24 + 117) * 4] ! AWR29 st %r30, [%sp + (24 + 118) * 4] ! AWR30 st %r31, [%sp + (24 + 119) * 4] ! AWR21! Get the Alternate PSR (I hope...) rd %psr, %l2 st %l2, [%sp + (24 + 120) * 4] ! APSR! Don't forget the alternate stack pointer rd %y, %l3 st %l3, [%sp + (24 + 102) * 4] ! AWR14 (SP)! 6) Restore the Alternate SP (saved in Y) rd %y, %o6! 7) Swap the registers back: mov %psr, %l1 sethi %hi(0x10000), %l2 xor %l1, %l2, %l1 mov %l1, %psr nop ! 3 nops after write to %psr (needed?) nop nop");}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -