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