|
|
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: // VAX frame fudger ! 16: ! 17: // STACK GROWS DOWN ! 18: ! 19: /* ! 20: * Fudge frame of function-defined-by-f_fp (called "f" below) ! 21: * so that that function returns to its grandparent, ! 22: * in particular, so a parent task returns to the function that ! 23: * called the derived constructor (de_ctor), skipping de_ctor; ! 24: * the child will return to the derived constructor, which is its "main." ! 25: * To do this we will overwrite the old fp, ap, and pc (those saved by ! 26: * f) with the old-old ones (those saved by f's caller), ! 27: * and we will overwrite the register save area with registers saved by ! 28: * f's caller (referred to as "skip" below). ! 29: * ! 30: * There are 2 register-save cases to deal with: ! 31: * 1. skip_n_saved <= f_n_saved ! 32: * 3. skip_n_saved > f_n_saved ! 33: * ! 34: * These are handled as follows: ! 35: * 1. copy the saved skip_regs over the corresponding f_regs, ! 36: * leaving any additional saved f_regs intact. ! 37: * f's restore instruction will be correct. ! 38: * 2. f's restore instruction will restore too few regs, must take special ! 39: * care to see that the extras are restored properly. ! 40: * -Copy saved skip_regs over any corresponding f_regs, ! 41: * -If fudge_return saved more regs than f did, then ! 42: * copy saved extra saved skip_regs over any corresponding fudge_regs, ! 43: * -If more extra skip_regs (not saved by either f or fudge_return, ! 44: * and therefore not used by either) remain, restore them explicitly. ! 45: * They will not be disturbed by the return from fudge_return or f, ! 46: */ ! 47: void ! 48: task::fudge_return(int* f_fp) ! 49: { ! 50: register int* fp = f_fp; // fp of frame-to-be-fudged ! 51: register int* skip_fp = (int*)OLD_FP(fp); // fp for f's caller (skip) ! 52: unsigned short mask = ENTRY_MASK(fp); ! 53: unsigned spa = mask >> 14; // stack pointer alignment ! 54: mask &= 0xfff; // mask of saved registers in the frame ! 55: unsigned short skip_mask = ENTRY_MASK(skip_fp); ! 56: unsigned skip_spa = skip_mask >> 14; ! 57: skip_mask &= 0xfff; ! 58: ! 59: OLD_AP(fp) = OLD_AP(skip_fp); ! 60: OLD_FP(fp) = OLD_FP(skip_fp); ! 61: OLD_PC(fp) = OLD_PC(skip_fp); ! 62: ! 63: // finally copy saved regs ! 64: // copy any saved skip regs over corresponding f regs; if there isn't ! 65: // a corresponding f reg, copy over corresponding fudge_return reg; ! 66: // if there isn't a corresponding fr_reg, restore it explicitly. ! 67: register int* to = FIRST_SAVED_REG_P(fp,0); ! 68: register int* from = FIRST_SAVED_REG_P(skip_fp,0); ! 69: register int* fr_fp = FP(); ! 70: register int* fr_to = FIRST_SAVED_REG_P(fr_fp,0); ! 71: unsigned short fr_mask = ENTRY_MASK(fr_fp); ! 72: fr_mask &= 0xfff; ! 73: for (int m = 1; m != 0x1000; m <<= 1) { ! 74: if (m & mask) { ! 75: if (m & skip_mask) { ! 76: *to++ = *from++; ! 77: if (m & fr_mask) fr_to++; ! 78: } else { // nothing to copy ! 79: to++; ! 80: if (m & fr_mask) fr_to++; ! 81: } ! 82: } else if (m & skip_mask) { ! 83: // No slot for *from in f's frame ! 84: if (m & fr_mask) { // copy to fudge_return's frame ! 85: *fr_to++ = *from++; ! 86: } else { ! 87: // Not used in f or fudge_return; ! 88: // restore explicitly ! 89: switch(m) { ! 90: case 0x0020: ! 91: set_r6(from++); ! 92: break; ! 93: case 0x0040: ! 94: set_r7(from++); ! 95: break; ! 96: case 0x0080: ! 97: set_r8(from++); ! 98: break; ! 99: case 0x0100: ! 100: set_r9(from++); ! 101: break; ! 102: case 0x0200: ! 103: set_r10(from++); ! 104: break; ! 105: case 0x0400: ! 106: set_r11(from++); ! 107: break; ! 108: default: ! 109: // Oops--don't expect other regs ! 110: // to be saved ! 111: from++; ! 112: task_error(E_REGMASK, this); ! 113: break; ! 114: } ! 115: } ! 116: } else if (m & fr_mask) fr_to++; ! 117: } ! 118: ! 119: // to and from now point at argument descriptor (if spa == 0); ! 120: // add number of words in skip's frame to arg descriptor, so sp ! 121: // will be set properly when f returns (no need for fudge_sp here). ! 122: // WARNING: spa != 0 untested. ! 123: to -= spa; ! 124: from -= skip_spa; ! 125: unsigned big_arg_list = *(unsigned char*)from + (from - to); ! 126: if (big_arg_list > 0xff) ! 127: task_error(E_FUDGE_SIZE, this); ! 128: *(unsigned char*)to = big_arg_list; ! 129: } ! 130:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.