|
|
1.1 ! root 1: /*ident "%W%" */ ! 2: /************************************************************************** ! 3: Copyright (c) 1984 AT&T ! 4: All Rights Reserved ! 5: ! 6: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T ! 7: ! 8: The copyright notice above does not evidence any ! 9: actual or intended publication of such source code. ! 10: ! 11: *****************************************************************************/ ! 12: #include <task.h> ! 13: #include "hw_stack.h" ! 14: ! 15: // Sun MC68000 frame fudger ! 16: ! 17: /* careful -- stack frame not self-describing */ ! 18: // STACK GROWS DOWN ! 19: ! 20: /* ! 21: * On the 68K Suns, the four forms of function call generated ! 22: * by the compiler are: ! 23: * jsr followed by the function address (int) ! 24: * bsrl followed by the function offset (int) (68020 only) ! 25: * bsr followed by the function offset (short) ! 26: * bsrb low order byte is the offset ! 27: * (not actually seen or tested) ! 28: */ ! 29: const JSR_CALL = 047271; ! 30: const BSRL_CALL = 060777; ! 31: const BSR_CALL = 060400; ! 32: const BSRB_CALL = 0x61; // Really 0x61NN, where NN is the offset. ! 33: ! 34: /* On the 68K Suns, the function prologue may include the following ! 35: * instructions. See FrameLayout for sequencing. ! 36: */ ! 37: const LINKW = 047126; // linkw a6,xxx ! 38: const ADDL = 0157774; // addl #yyy,sp ! 39: const MOVLA5 = 027215; // movl a5,sp@ ! 40: const MOVLD7 = 027207; // movl d7,sp@ ! 41: const MOVEM = 044327; // movem mask,sp@ ! 42: // (for movem M,a6@(xx) ) ! 43: ! 44: int* Skip_pc_p; // global to hold fudged return pc. ! 45: // See comments in hw_stack.c. ! 46: ! 47: FrameLayout::FrameLayout(int* fp) ! 48: { ! 49: unsigned short* ret_addr = (unsigned short*)OLD_PC(fp); ! 50: /* ! 51: * find the starting address of the function. The idea is that the ! 52: * instruction immediately before the return address must be the function call. ! 53: * Only works if the function was called by name. ! 54: */ ! 55: unsigned short* func_addr = ! 56: (ret_addr[-3] == JSR_CALL) ? ! 57: (unsigned short*)*(int*)(ret_addr-2) : ! 58: (ret_addr[-3] == BSRL_CALL) ? ! 59: (unsigned short*) ((char*)(ret_addr-2) ! 60: + *(int*)(ret_addr-2)) : ! 61: (ret_addr[-2] == BSR_CALL) ? ! 62: (unsigned short*) ((char*)(ret_addr-1) ! 63: + *(short*)(ret_addr-1)) : ! 64: (*(char*)(ret_addr-1) == BSRB_CALL) ? ! 65: (unsigned short*) ((char*)ret_addr ! 66: + *((char*)ret_addr-1)) : ! 67: (unsigned short*)object::task_error(E_FUNCS, (object*)0); ! 68: /* ! 69: * the first instruction in the function is linkw a6,xxx ! 70: * if -O was used, xxx is the frame size in bytes (saved regs + automatics), ! 71: * otherwise xxx is 0 and the next instruction is addl #yyy, sp ! 72: * where yyy is the frame size. ! 73: */ ! 74: if (*func_addr == LINKW) { ! 75: if ((offset = (short)*++func_addr / 4) == 0) ! 76: if (*++func_addr == ADDL) ! 77: offset = (short)*(func_addr += 2) / 4; ! 78: } else object::task_error(E_FRAMES, (object*)0); ! 79: /* ! 80: * The next instruction saves the registers in the frame. Possibilities are: ! 81: * movem mask,sp@ | save the regs specified by the mask word ! 82: * movl a5,sp@ | just save a5 ! 83: * movl d7,sp@ | just save d7 ! 84: * The mask uses the standard 68000 layout ! 85: */ ! 86: switch (*++func_addr) { ! 87: case MOVLA5: // movl a5,sp@ ! 88: mask = 020000; // just a5 ! 89: break; ! 90: case MOVEM: // movem mask,sp@ ! 91: mask = *++func_addr; // mask word ! 92: break; ! 93: case MOVLD7: // movl d7,sp@ ! 94: mask = 0200; // just d7 ! 95: break; ! 96: default: // no saved registers is also possible ! 97: mask = 0; ! 98: break; ! 99: } ! 100: } ! 101: ! 102: /* ! 103: * Fudge frame of function-defined-by-f_fp (called "f" below) ! 104: * so that that function returns to its grandparent, ! 105: * in particular, so a parent task returns to the function that ! 106: * called the derived constructor (de_ctor), skipping de_ctor; ! 107: * the child will return to the derived constructor, which is its "main." ! 108: * To do this we will overwrite the old fp and pc (those saved by ! 109: * f) with the old-old ones (those saved by f's caller), ! 110: * and we will overwrite the register save area with registers saved by ! 111: * f's caller (referred to as "skip" below). ! 112: * ! 113: * There are 2 register-save cases to deal with: ! 114: * 1. skip_n_saved <= f_n_saved ! 115: * 3. skip_n_saved > f_n_saved ! 116: * ! 117: * These are handled as follows: ! 118: * 1. copy the saved skip_regs over the corresponding f_regs, ! 119: * leaving any additional saved f_regs intact. ! 120: * f's epilogue instructions will be correct. ! 121: * 2. f's epilogue instructions will restore too few regs, ! 122: * must take special care to see that the extras are restored properly. ! 123: * -Copy saved skip_regs over any corresponding f_regs, ! 124: * -If fudge_return saved more regs than f did, then ! 125: * copy saved extra saved skip_regs over any corresponding fudge_regs, ! 126: * -If more extra skip_regs (not saved by either f or fudge_return, ! 127: * and therefore not used by either) remain, restore them explicitly. ! 128: * They will not be disturbed by the return from fudge_return or f, ! 129: */ ! 130: void ! 131: task::fudge_return(int* f_fp) ! 132: { ! 133: register int* fp = f_fp; // fp of frame-to-be-fudged ! 134: FrameLayout lo(fp); // frame to be fudged ! 135: register int* skip_fp = (int*)OLD_FP(fp); // fp for f's caller (skip) ! 136: FrameLayout skip_lo(skip_fp); // frame for skip ! 137: register int* fr_fp = FP(); // fp for fudge_return ! 138: FrameLayout fr_lo(fr_fp); // frame for fudge_return ! 139: ! 140: OLD_PC(fp) = (int)&fudge_sp; // task::task will return through ! 141: // fudge_sp, which will reset the sp ! 142: // to point at the return-pc in ! 143: // skip's frame ! 144: // copy old fp ! 145: OLD_FP(fp) = OLD_FP(skip_fp); ! 146: ! 147: // now copy saved registers ! 148: // copy any saved skip regs over corresponding f regs; if there isn't ! 149: // a corresponding f reg, copy over corresponding fudge_return reg; ! 150: // if there isn't a corresponding fr_reg, restore it explicitly. ! 151: register int* to = FIRST_SAVED_REG_P(fp, lo.offset); ! 152: register int* from = FIRST_SAVED_REG_P(skip_fp, skip_lo.offset); ! 153: register int* fr_to = FIRST_SAVED_REG_P(fr_fp, fr_lo.offset); ! 154: for (register int m = 1; m != 0x10000; m <<=1) { ! 155: if (m & lo.mask) { ! 156: if (m & skip_lo.mask) { ! 157: *to++ = *from++; ! 158: if (m & fr_lo.mask) fr_to++; ! 159: } else { // nothing to copy ! 160: to++; ! 161: if (m & fr_lo.mask) fr_to++; ! 162: } ! 163: } else if (m & skip_lo.mask) { ! 164: // No slot for *from in f's frame ! 165: if (m & fr_lo.mask) { // copy to fudge_return's frame ! 166: *fr_to++ = *from++; ! 167: } else { ! 168: // Not used in f or fudge_return; ! 169: // restore explicitly ! 170: switch(m) { ! 171: case 0x0004: ! 172: set_d2(from++); ! 173: break; ! 174: case 0x0008: ! 175: set_d3(from++); ! 176: break; ! 177: case 0x0010: ! 178: set_d4(from++); ! 179: break; ! 180: case 0x0020: ! 181: set_d5(from++); ! 182: break; ! 183: case 0x0040: ! 184: set_d6(from++); ! 185: break; ! 186: case 0x0080: ! 187: set_d7(from++); ! 188: break; ! 189: case 0x0400: ! 190: set_a2(from++); ! 191: break; ! 192: case 0x0800: ! 193: set_a3(from++); ! 194: break; ! 195: case 0x1000: ! 196: set_a4(from++); ! 197: break; ! 198: case 0x2000: ! 199: set_a5(from++); ! 200: break; ! 201: default: ! 202: // Oops--don't expect other regs ! 203: // to be saved ! 204: from++; ! 205: task_error(E_REGMASK, this); ! 206: break; ! 207: } ! 208: } ! 209: } ! 210: } ! 211: } ! 212:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.