|
|
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.