📄 m68k-stub.c
字号:
_catchException:");DISABLE_INTERRUPTS();asm("\ moveml %d0-%d7/%a0-%a6,registers /* save registers */ \n\ movel lastFrame,%a0 /* last frame pointer */ \n\");SAVE_FP_REGS(); asm(" \n\ lea registers,%a5 /* get address of registers */ \n\ movel (%sp)+,%d2 /* pop return address */ \n\ addl #1530,%d2 /* convert return addr to */ \n\ divs #6,%d2 /* exception number */ \n\ extl %d2 \n\ \n\ moveql #3,%d3 /* assume a three word frame */ \n\ \n\ cmpiw #3,%d2 /* bus error or address error ? */ \n\ bgt normal /* if >3 then normal error */ \n\ movel (%sp)+,-(%a0) /* copy error info to frame buff*/ \n\ movel (%sp)+,-(%a0) /* these are never used */ \n\ moveql #7,%d3 /* this is a 7 word frame */ \n\ \n\normal: \n\ movew (%sp)+,%d1 /* pop status register */ \n\ movel (%sp)+,%a4 /* pop program counter */ \n\ movew %d1,66(%a5) /* save sr */ \n\ movel %a4,68(%a5) /* save pc in _regisers[] */ \n\ movel %a4,-(%a0) /* copy pc to frame buffer */ \n\ movew %d1,-(%a0) /* copy sr to frame buffer */ \n\ \n\ movel %sp,superStack /* save supervisor sp */ \n\ \n\ andiw #0x2000,%d1 /* were we in supervisor mode ? */ \n\ beq userMode \n\ movel %a7,60(%a5) /* save a7 */ \n\ bra saveDone \n\userMode: \n\ movel %usp,%a1 /* save user stack pointer */ \n\ movel %a1,60(%a5) /* save user stack pointer */ \n\saveDone: \n\ \n\ movew %d3,-(%a0) /* push frame size in words */ \n\ movel %d2,-(%a0) /* push vector number */ \n\ movel %a4,-(%a0) /* push exception pc */ \n\ \n\# \n\# save old frame link and set the new value \n\ movel _lastFrame,%a1 /* last frame pointer */ \n\ movel %a1,-(%a0) /* save pointer to prev frame */ \n\ movel %a0,lastFrame \n\ \n\ movel %d2,-(%sp) /* push exception num */ \n\ movel exceptionHook,%a0 /* get address of handler */ \n\ jbsr (%a0) /* and call it */ \n\ clrl (%sp) /* replace exception num parm with frame ptr */ \n\ jbsr _returnFromException /* jbsr, but never returns */ \n\");#endif/* * remcomHandler is a front end for handle_exception. It moves the * stack pointer into an area reserved for debugger use in case the * breakpoint happened in supervisor mode. */asm("remcomHandler:");asm(" add.l #4,%sp"); /* pop off return address */asm(" move.l (%sp)+,%d0"); /* get the exception number */asm(" move.l stackPtr,%sp"); /* move to remcom stack area */asm(" move.l %d0,-(%sp)"); /* push exception onto stack */asm(" jbsr handle_exception"); /* this never returns */asm(" rts"); /* return */} /* end of stub_dummy_asm_wrapper function */void _returnFromException( Frame *frame ){ /* if no passed in frame, use the last one */ if (! frame) { frame = lastFrame; frame->frameSize = 4; frame->format = 0; frame->fsaveHeader = -1; /* restore regs, but we dont have fsave info*/ }#if !M68K_HAS_VBR /* a 68000 cannot use the internal info pushed onto a bus error * or address error frame when doing an RTE so don't put this info * onto the stack or the stack will creep every time this happens. */ frame->frameSize=3;#endif /* throw away any frames in the list after this frame */ lastFrame = frame; frame->sr = registers[(int) PS]; frame->pc = registers[(int) PC]; if (registers[(int) PS] & 0x2000) { /* return to supervisor mode... */ return_to_super(); } else { /* return to user mode */ return_to_user(); }}int hex(ch)char ch;{ if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10); if ((ch >= '0') && (ch <= '9')) return (ch-'0'); if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10); return (-1);}/* scan for the sequence $<data>#<checksum> */void getpacket(buffer)char * buffer;{ unsigned char checksum; unsigned char xmitcsum; int i; int count; char ch; do { /* wait around for the start character, ignore all other characters */ while ((ch = getDebugChar()) != '$'); checksum = 0; xmitcsum = -1; count = 0; /* now, read until a # or end of buffer is found */ while (count < BUFMAX) { ch = getDebugChar(); if (ch == '#') break; checksum = checksum + ch; buffer[count] = ch; count = count + 1; } buffer[count] = 0; if (ch == '#') { xmitcsum = hex(getDebugChar()) << 4; xmitcsum += hex(getDebugChar()); if ((remote_debug ) && (checksum != xmitcsum)) { fprintf (stderr,"bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n", checksum,xmitcsum,buffer); } if (checksum != xmitcsum) putDebugChar('-'); /* failed checksum */ else { 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]; } } } } while (checksum != xmitcsum); }/* send the packet in buffer. The host get's one chance to read it. This routine does not wait for a positive acknowledge. *//* * Send the packet in buffer and wait for a positive acknowledgement. */static voidputpacket (char *buffer){ int checksum; /* $<packet info>#<checksum> */ do { char *src = buffer; putDebugChar ('$'); checksum = 0; while (*src != '\0') { int runlen = 0; /* Do run length encoding */ while ((src[runlen] == src[0]) && (runlen < 99)) runlen++; if (runlen > 3) { int encode; /* Got a useful amount */ putDebugChar (*src); checksum += *src; putDebugChar ('*'); checksum += '*'; checksum += (encode = (runlen - 4) + ' '); putDebugChar (encode); src += runlen; } else { putDebugChar (*src); checksum += *src; src++; } } putDebugChar ('#'); putDebugChar (highhex (checksum)); putDebugChar (lowhex (checksum)); } while (getDebugChar () != '+');}char remcomInBuffer[BUFMAX];char remcomOutBuffer[BUFMAX];static short error;void debug_error( char * format, char * parm){ if (remote_debug) fprintf (stderr,format,parm);}/* convert the memory pointed to by mem into hex, placing result in buf *//* return a pointer to the last char put in buf (null) */char* mem2hex(mem, buf, count)char* mem;char* buf;int count;{ int i; unsigned char ch; for (i=0;i<count;i++) { ch = *mem++; *buf++ = gdb_hexchars[ch >> 4]; *buf++ = gdb_hexchars[ch % 16]; } *buf = 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 */char* hex2mem(buf, mem, count)char* buf;char* mem;int count;{ int i; unsigned char ch; for (i=0;i<count;i++) { ch = hex(*buf++) << 4; ch = ch + hex(*buf++); *mem++ = ch; } return(mem);}/* Convert the binary stream in BUF to memory. Gdb will escape $, #, and the escape char (0x7d). COUNT is the total number of bytes to write into memory. */static unsigned char *bin2mem ( unsigned char *buf, unsigned char *mem, int count){ int i; for (i = 0; i < count; i++) { /* Check for any escaped characters. Be paranoid and only unescape chars that should be escaped. */ if (*buf == 0x7d) { switch (*(buf+1)) { case 0x3: /* # */ case 0x4: /* $ */ case 0x5d: /* escape char */ buf++; *buf |= 0x20; break; default: /* nothing */ break; } } *mem++ = *buf++; } return mem;}/* a bus error has occurred, perform a longjmp to return execution and allow handling of the error */void handle_buserror(){ longjmp(remcomEnv,1);}/* this function takes the 68000 exception number and attempts to translate this number into a unix compatible signal value */int computeSignal( exceptionVector )int exceptionVector;{ int sigval; switch (exceptionVector) { case 2 : sigval = 10; break; /* bus error */ case 3 : sigval = 10; break; /* address error */ case 4 : sigval = 4; break; /* illegal instruction */ case 5 : sigval = 8; break; /* zero divide */ case 6 : sigval = 8; break; /* chk instruction */ case 7 : sigval = 8; break; /* trapv instruction */ case 8 : sigval = 11; break; /* privilege violation */ case 9 : sigval = 5; break; /* trace trap */ case 10: sigval = 4; break; /* line 1010 emulator */ case 11: sigval = 4; break; /* line 1111 emulator */ /* Coprocessor protocol violation. Using a standard MMU or FPU this cannot be triggered by software. Call it a SIGBUS. */ case 13: sigval = 10; break; case 31: sigval = 2; break; /* interrupt */ case 33: sigval = 5; break; /* GDB breakpoint */ case 34: sigval = 5; break; /* coded breakpoint */ /* This is a trap #8 instruction. Apparently it is someone's software convention for some sort of SIGFPE condition. Whose? How many people are being screwed by having this code the way it is? Is there a clean solution? */ case 40: sigval = 8; break; /* floating point err */ case 48: sigval = 8; break; /* floating point err */ case 49: sigval = 8; break; /* floating point err */ case 50: sigval = 8; break; /* zero divide */ case 51: sigval = 8; break; /* underflow */ case 52: sigval = 8; break; /* operand error */ case 53: sigval = 8; break; /* overflow */ case 54: sigval = 8; break; /* NAN */ default: sigval = 7; /* "software generated"*/ } return (sigval);}/**********************************************//* WHILE WE FIND NICE HEX CHARS, BUILD AN INT *//* RETURN NUMBER OF CHARS PROCESSED *//**********************************************/int hexToInt(char **ptr, int *intValue){ int numChars = 0; int hexValue; *intValue = 0; while (**ptr) { hexValue = hex(**ptr); if (hexValue >=0) { *intValue = (*intValue <<4) | hexValue; numChars ++; } else break; (*ptr)++; } return (numChars);}/* * This support function prepares and sends the message containing the * basic information about this exception. */void gdb_stub_report_exception_info( int vector, int *regs, int thread){ char *optr; int sigval; optr = remcomOutBuffer; *optr++ = 'T'; sigval = computeSignal (vector); *optr++ = highhex (sigval); *optr++ = lowhex (sigval); *optr++ = highhex(A7); *optr++ = lowhex(A7); *optr++ = ':'; optr = mem2hstr(optr, (unsigned char *)&(regs[A7]), sizeof(regs[A7])); *optr++ = ';'; *optr++ = highhex(PC); *optr++ = lowhex(PC); *optr++ = ':'; optr = mem2hstr(optr, (unsigned char *)&(regs[PC]), sizeof(regs[PC]) ); *optr++ = ';';#if defined(GDB_STUB_ENABLE_THREAD_SUPPORT) if (do_threads) { *optr++ = 't'; *optr++ = 'h'; *optr++ = 'r'; *optr++ = 'e'; *optr++ = 'a';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -