|
|
1.1 ! root 1: #include "task.h" ! 2: ! 3: // MC68000 frame fudger ! 4: ! 5: /* careful -- stack frame not self-describing */ ! 6: // STACK GROWS DOWN ! 7: #define FP(p) ( (int*)(&p+1) ) ! 8: #define AP() 0 /* unnecessary on mc68000 */ ! 9: #define OLD_AP(fp) 0 /* unnecessary on mc68000 */ ! 10: #define OLD_FP(fp) (*fp) ! 11: ! 12: struct FrameLayout { ! 13: short offset; // of top of frame from fp (size of locals + regs) ! 14: unsigned short mask; // of registers saved in frame ! 15: FrameLayout(int*); // called with frame pointer ! 16: }; ! 17: ! 18: /* ! 19: * This code figures out the layout of the frame of the user's constructor. Note ! 20: * the user's class is directly derived from class task and the call to the ! 21: * constructor is automatically generated. ! 22: */ ! 23: FrameLayout::FrameLayout(int* fp) ! 24: { ! 25: unsigned short* ret_addr = (unsigned short*)*(fp+1); ! 26: /* ! 27: * find the starting address of the function. The idea is that the instruction ! 28: * immediately before the return address must be the function call. Only works ! 29: * if the function was called by name. ! 30: */ ! 31: /* ! 32: * On the 68000, the four forms of function call generated by the compiler are ! 33: * 047271 jsr followed by the function address (long) ! 34: * 060777 bsrl followed by the function offset (long) (68020 only) ! 35: * 060400 bsr followed by the function offset (short) ! 36: * 0x61NN bsrb low order byte is the offset (not actually seen or tested) ! 37: */ ! 38: unsigned short* func_addr = ! 39: (ret_addr[-3] == 047271) ? ! 40: (unsigned short*)*(int*)(ret_addr-2) : ! 41: (ret_addr[-3] == 060777) ? ! 42: (unsigned short*) ((char*)(ret_addr-2) + *(int*)(ret_addr-2)) : ! 43: (ret_addr[-2] == 060400) ? ! 44: (unsigned short*) ((char*)(ret_addr-1) + *(short*)(ret_addr-1)) : ! 45: (*(char*)(ret_addr-1) == 0x61) ? ! 46: (unsigned short*) ((char*)ret_addr + *((char*)ret_addr-1)) : ! 47: (unsigned short*)((object*)0)->task_error(E_FUNCS); ! 48: /* ! 49: * the first instruction in the function is linkw a6,xxx ! 50: * if -O was used, xxx is the frame size in bytes, otherwise ! 51: * xxx is 0 and the next instruction is addl #yyy, sp ! 52: * where yyy is the frame size ! 53: */ ! 54: if (*func_addr == 047126) { // linkw instruction ! 55: if ((offset = (short)*++func_addr / 4) == 0) ! 56: if (*++func_addr == 0157774) // addl ! 57: offset = (short)*(func_addr += 2) / 4; ! 58: } else ((object*)0)->task_error(E_FRAMES); ! 59: /* ! 60: * The next instruction saves the registers in the frame. The possibilities are ! 61: * movem mask,@sp | save the register specified by the mask word ! 62: * movl a5,@sp | just save a5 ! 63: * movl d7,@sp | just save d7 ! 64: * The mask uses the standard 68000 layout ! 65: */ ! 66: switch (*++func_addr) { ! 67: case 027215: // movl a5,sp@ ! 68: mask = 020000; // just a5 ! 69: break; ! 70: case 044327: // movem mask,@sp ! 71: mask = *++func_addr; // mask word ! 72: break; ! 73: case 027207: // movl d7,sp@ ! 74: mask = 0200; // just d7 ! 75: break; ! 76: default: // no saved registers is also possible ! 77: mask = 0; ! 78: break; ! 79: } ! 80: } ! 81: ! 82: /* ! 83: * fix a frame so that it returns like the arg ! 84: * The idea is that task_fp points to the task::task() stack frame which ! 85: * contains all the saved registers. t_framep points to the stack frame ! 86: * that contains the return address and old fp (and perhaps some registers). ! 87: * fill the frame pointed to by t_framep with the registers from task_fp. ! 88: */ ! 89: void ! 90: task::fudge_return(int* task_fp, int offset, task* next) ! 91: { ! 92: int* fp = t_framep + offset; ! 93: task_fp += offset; // in case this is SHARED ! 94: FrameLayout this_lo(fp); ! 95: FrameLayout task_lo(task_fp); ! 96: // copy any saved registers from this to task frame ! 97: register int* task_rp = task_fp + task_lo.offset; ! 98: register int* this_rp = fp + this_lo.offset; ! 99: register int reg_count = 0; ! 100: for (register mask = 1; mask != 0x10000; mask <<= 1) { ! 101: if (mask & task_lo.mask) { ! 102: reg_count++; ! 103: if (mask & this_lo.mask) ! 104: *task_rp++ = *this_rp++; ! 105: else task_rp++; ! 106: } else if (mask & this_lo.mask) ! 107: task_error(E_FUDGE); ! 108: } ! 109: // next copy all the registers from the task frame to this (using task offset) ! 110: task_rp = task_fp + task_lo.offset + reg_count; ! 111: this_rp = fp + task_lo.offset + reg_count; ! 112: while (reg_count--) ! 113: *--this_rp = *--task_rp; ! 114: if (next) next->restore(); ! 115: } ! 116:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.