📄 hw_stack.c
字号:
/* On the 68k, immediately before the rts, the sp is pointing at the * return pc on the stack. The rts pops the pc off the stack. * To reset the sp correctly after fudging the stack, we'll save the * pointer to "skip's" return-pc in Skip_pc_p, and fudge_return() will * overwrite task::task's return pc with the address of fudge_sp, * a function that will reset the sp to Skip_pc_p, and then do the rts. * Ugly, but it should work. */// NOTE: The following definition of Skip_pc_p appears in fudge.c.68k,// because of an apparent bug in the Sun-3 compiler. It seems to get// confused by intermingling of definitions and asms.// int* Skip_pc_p; // global to hold fudged return pc. // Set in FUDGE_SP, used by fudge_sp a few instructions // later. Be careful not to add intervening insts.//Note: 1st arg unnecessary on Sun-2/3voidFUDGE_SP(int*, int* de_fp){ Skip_pc_p = OLD_PC_P(de_fp);}asm(" .text");asm(" .globl _fudge_sp");asm("_fudge_sp:");asm(" movl _Skip_pc_p,a7");asm(" rts");asm(" .text");asm(" .globl _set_d2");asm("_set_d2:");asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */asm(" movl a0@,d2");asm(" rts");asm(" .text");asm(" .globl _set_d3");asm("_set_d3:");asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */asm(" movl a0@,d3");asm(" rts");asm(" .text");asm(" .globl _set_d4");asm("_set_d4:");asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */asm(" movl a0@,d4");asm(" rts");asm(" .text");asm(" .globl _set_d5");asm("_set_d5:");asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */asm(" movl a0@,d5");asm(" rts");asm(" .text");asm(" .globl _set_d6");asm("_set_d6:");asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */asm(" movl a0@,d6");asm(" rts");asm(" .text");asm(" .globl _set_d7");asm("_set_d7:");asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */asm(" movl a0@,d7");asm(" rts");asm(" .text");asm(" .globl _set_a2");asm("_set_a2:");asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */asm(" movl a0@,a2");asm(" rts");asm(" .text");asm(" .globl _set_a3");asm("_set_a3:");asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */asm(" movl a0@,a3");asm(" rts");asm(" .text");asm(" .globl _set_a4");asm("_set_a4:");asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */asm(" movl a0@,a4");asm(" rts");asm(" .text");asm(" .globl _set_a5");asm("_set_a5:");asm(" movl sp@(4),a0"); /* arg is ptr to register saved in stack */asm(" movl a0@,a5");asm(" rts");#endif /* mc68000 */#ifdef i386asm(" .text");asm(" .globl SAVE_REGS");asm("SAVE_REGS:");asm(" pushl %ebp"); /* save caller's fp */asm(" movl %esp,%ebp"); /* fp = sp */asm(" pushl %edi"); /* save edi */asm(" pushl %esi"); /* save esi */asm(" pushl %ebx"); /* save ebx */asm(" movl 8(%ebp),%eax"); /* eax = arg--ptr to HW_REGS */asm(" movl -4(%ebp),%ecx"); /* ecx = caller's edi */asm(" movl %ecx,0(%eax)"); /* arg.edi = ecx */asm(" movl -8(%ebp),%ecx"); /* ecx = caller's esi */asm(" movl %ecx,4(%eax)"); /* arg.esi = ecx */asm(" movl -12(%ebp),%ecx"); /* ecx = caller's ebx */asm(" movl %ecx,8(%eax)"); /* arg.ebx = ecx */asm(" popl %ebx");asm(" popl %esi");asm(" popl %edi");asm(" leave");asm(" ret");/* save_saved_regs copies regs saved in stack frame defined by fp * to a HW_REGS structure. Uses FrameLayout() to find which regs are saved. */voidsave_saved_regs(HW_REGS *regsp, int* fp){ FrameLayout layout(fp); register int* p = FIRST_SAVED_REG_P(fp,layout.offset); register int* rp = (int*)regsp; register unsigned short mask = layout.mask; for (register short m = 1; m != 0x08; m <<=1) { if (m & mask) { *rp++ = *p--; } else { rp++; } }}/* On the i386, without a specific inst, fp (ebp) doesn't move on a call */asm(".text");asm(".globl FP");asm("FP:");asm(" movl %ebp,%eax");asm(" ret");/* On the i386, a call pushes the pc on the stack; the caller's sp is the current sp + 1 */asm(".text");asm(".globl TOP");asm("TOP:");asm(" leal 4(%esp),%eax");asm(" ret");/* On the i386, immediately before the ret, the sp is pointing at the * return pc on the stack. The ret pops the pc off the stack. * To reset the sp correctly after fudging the stack, we'll save the * pointer to "skip's" return-pc in Skip_pc_p, and fudge_return() will * overwrite task::task's return pc with the address of fudge_sp, * a function that will reset the sp to Skip_pc_p, and then do the ret. * Ugly, but it should work. */// NOTE: The following definition of Skip_pc_p appears in fudge.c.386,// because of an apparent bug in the Sun-3 compiler. It seems to get// confused by intermingling of definitions and asms.// int* Skip_pc_p; // global to hold fudged return pc. // Set in FUDGE_SP, used by fudge_sp a few instructions // later. Be careful not to add intervening insts.//Note: 1st arg unnecessary on i386voidFUDGE_SP(int*, int* de_fp){ Skip_pc_p = OLD_PC_P(de_fp);}asm(" .text");asm(" .globl fudge_sp");asm("fudge_sp:");asm(" movl Skip_pc_p,%esp");asm(" ret");asm(".text");asm(".globl set_edi");asm("set_edi:");asm(" movl 4(%esp),%eax");asm(" movl 0(%eax),%edi");asm(" ret");asm(".text");asm(".globl set_esi");asm("set_esi:");asm(" movl 4(%esp),%eax");asm(" movl 0(%eax),%esi");asm(" ret");asm(".text");asm(".globl set_ebx");asm("set_ebx:");asm(" movl 4(%esp),%eax");asm(" movl 0(%eax),%ebx");asm(" ret");#endif /* i386 */#ifdef uts/* * FP() and AP() return the frame/arg pointer of the caller. In both * cases, this is the old value of r12. * * uts allows asm only inside functions. * Ordinarily we could simply load r0 and return, but because we're * in a C function, we have to make the compiler happy. A value is * returned through a redundant auto, which is assigned a dummy value * to make the compiler shut up about "used but not set." * (Assignment is used instead of initialization, due to a cfront quirk * which will delay initialization until right before use, overwriting * the asm work with 0). * */extern "C" {int *FP(){ int *fp; fp = 0; /* * return the saved r12 */ asm(" l 0, 48(12)"); asm(" st 0, -4+$FP_len(13)"); return fp;}int *AP(){ int *ap; ap = 0; /* * return the saved r12 */ asm(" l 0, 48(12)"); asm(" st 0, -4+$AP_len(13)"); return ap;}int *TOP(){ int *sp; sp = 0; /* * return the saved r13 */ asm(" l 0, 52(12)"); asm(" st 0, -4+$TOP_len(13)"); return sp;}voidset_r2(int*){ asm(" l 2, 64(12)"); // get loc asm(" l 2, (2)"); // load r2 with contents asm(" st 2, 8(12)"); // overwrite save area};voidset_r3(int*){ asm(" l 3, 64(12)"); asm(" l 3, (3)"); asm(" st 3, 12(12)");}voidset_r4(int*){ asm(" l 4, 64(12)"); asm(" l 4, (4)"); asm(" st 4, 16(12)");}voidset_r5(int*){ asm(" l 5, 64(12)"); asm(" l 5, (5)"); asm(" st 5, 20(12)");}voidset_r6(int*){ asm(" l 6, 64(12)"); asm(" l 6, (6)"); asm(" st 6, 24(12)");}voidset_r7(int*){ asm(" l 7, 64(12)"); asm(" l 7, (7)"); asm(" st 7, 28(12)");};voidset_r8(int*){ asm(" l 8, 64(12)"); asm(" l 8, (8)"); asm(" st 8, 32(12)");}voidset_r9(int*){ asm(" l 9, 64(12)"); asm(" l 9, (9)"); asm(" st 9, 36(12)");}voidset_r10(int*){ asm(" l 10, 64(12)"); asm(" l 10, (10)"); asm(" st 10, 40(12)");}};/* * saved_saved_regs copies regs saved in stack frame defined by fp * to a HW_REGS structure. Uses FrameLayout() to find which regs are saved. */voidsave_saved_regs(HW_REGS *regsp, int* fp){ FrameLayout layout(fp); register int* p = FIRST_SAVED_REG_P(fp); register int* rp = (int*)regsp; register int r; for (r = 0; r < 16; r++, rp++, p++) { if (layout.begreg <= r && r <= layout.endreg) { *rp = *p; } }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -