|
|
1.1 root 1: #include "../h/config.h"
2:
3: /*
4: * lsusp - suspends a result from a limited expression. The limit counter
5: * for the expression is decremented. If the counter becomes zero,
6: * lsusp exits the current expression frame, replacing the limit
7: * counter with the result which was to be suspended. Otherwise,
8: * lsusp suspends from the current expression frame leaving the
9: * value being suspended on top of the stack. A generator frame
10: * hiding the current expression frame is created. The surrounding
11: * expression frame is duplicated and the value being suspended
12: * is copied to the top of the stack. The generator frame that
13: * is created uses efail as a return point, thus if an alternative
14: * is needed, efail will return to itself via the generator frame
15: * and then resume execution at the failure label specified in
16: * the expression marker.
17: *
18: * The value being suspended appears as an argument.
19: */
20: Global(_efail) /* Signal failure in an expression */
21: Global(_boundary) /* Icon/C boundary address */
22: Global(_line) /* Current line number */
23: Global(_file) /* Current file name */
24: Global(_k_level) /* Value of &level */
25:
26: Global(_lsusp)
27: #ifdef VAX
28: _lsusp:
29: Mask STDSV # Partially create generator frame
30: # upon entry.
31: decl 8(efp) # Decrement the limit counter,
32: jneq dosusp # and if this result is not the last, go
33: # to dosusp to actually suspend the value.
34: /*
35: * The limit counter has reached zero. Replace the counter with the
36: * value that was to be suspended, remove the current expression frame
37: * and return.
38: */
39: movq 8(ap),4(efp) # Replace limit counter with value
40: movl -4(efp),gfp # Restore gfp from expression frame
41: movl 16(sp),r0 # Save return pc in r0 for later use
42: movl efp,sp # Point sp at 0'th word of expression
43: movl (sp)+,efp # frame and restore efp from frame,
44: # also moving sp up to point at low
45: # word of return value.
46: movl 8(fp),ap # Restore ap
47: movl 12(fp),fp # and fp to state they were in before
48: # call to lsusp.
49: jmp (r0) # Return from lsusp
50:
51: /*
52: * From this point on, the code is EXACTLY the same as esusp, with the
53: * exception of the line denoted by "--->".
54: */
55: dosusp:
56: /*
57: * Construct the generator frame.
58: */
59: movl fp,_boundary # Set the boundary
60: pushl fp # Push boundary as part of generator frame
61: movl sp,gfp # The generator frame pointer points at
62: # the word containing the boundary.
63: pushl _k_level # Save &level,
64: pushl _line # line number,
65: pushl _file # and file name in generator frame,
66: # completing the frame.
67: /*
68: * Determine region to be copied.
69: */
70: addl3 $12,efp,r0 # Point r0 at first word above the
71: # expression frame marker. This
72: # word is the lower end of the region
73: # that will be copied.
74: # ---> In esusp, the preceding instruction is
75: # addl3 $4,efp,r0
76: # It is 12 instead of 4 here because the
77: # descriptor for the limit counter is
78: # on the stack above the expression marker
79: # and the limit counter is not to be
80: # in the duplicated region.
81: #
82: # If the saved gfp is non-zero, the
83: # generator frame marker serves as the
84: # upper bound of the expression frame.
85: # If it is zero, the expression frame
86: # marker pointed at by the saved
87: # efp is the upper bound of the frame
88: # to be copied.
89: # Note that the marker itself is not
90: # copied, the region only extends to
91: # the marker and not through it.
92: movl -4(efp),r2 # Get gfp from expression marker.
93: jneq f1 # If it is zero,
94: subl3 $8,(efp),r2 # use saved efp - 8.
95: jmp f2
96: f1: # gfp is not zero,
97: subl2 $12,r2 # use gfp - 12.
98: /*
99: * Copy surrounding expression frame.
100: */
101: # r0 points to the lowest word to be copied
102: # and r2 points to high end of the region.
103: # The word that r2 points at is part of
104: # a generator or expression frame marker
105: # is not copied.
106: f2: subl2 r0,r2 # Calculate length in bytes of region and
107: # put it in r2.
108: subl2 r2,sp # Move stack pointer down to accommodate
109: # copied region.
110: movc3 r2,(r0),(sp) # Copy the region by moving r2 bytes from
111: # the address pointed at by r2 to the
112: # address pointed at by the stack pointer.
113:
114: movq 8(ap),-(sp) # Copy the value being suspended to
115: # the top of the stack.
116: /*
117: * Fix things up for return.
118: */
119: movl 16(fp),r1 # Get the saved pc (the return point for
120: # lsusp) out of the frame and save it in r1.
121: movl $_efail,16(fp) # Replace saved pc with efail so that when
122: # a return using the generator frame is
123: # performed, it will go to efail.
124: movl 8(fp),ap # Restore ap
125: movl 12(fp),fp # and fp.
126: clrl _boundary # Clear the boundary since control is
127: # going back into Icon code.
128: movl (efp),efp # Point efp at bounding expression frame
129: # marker.
130: jmp (r1) # Return by branching back to desired
131: # return point. The suspended value is
132: # on the top of the stack, gfp points
133: # at the newly constructed generator
134: # frame.
135: #endif VAX
136:
137: #ifdef PORT
138: DummyFcn(_lsusp)
139: #endif PORT
140:
141: #ifdef PDP11
142: / lsusp - Suspend or return from a limited expression.
143: / Decrements the limit counter; if it becomes zero, lsusp
144: / exits the current expression frame. If not, lsusp
145: / suspends from the current expression frame.
146:
147: _lsusp:
148: dec 4(r4) / decrement the limit counter
149: bne 1f / branch if still > 0
150:
151: / Return from the limited expression.
152:
153: mov (sp)+,r0 / pop return pc
154: tst (sp)+ / skip nargs
155: mov (sp)+,2(r4) / copy expression value
156: mov (sp)+,4(r4)
157: mov -2(r4),r3 / exit expression frame
158: mov r4,sp
159: mov (sp)+,r4
160: jmp (r0) / return
161:
162: / Suspend from the limited expression.
163: / Duplicates the most recent generator frame outside the
164: / current expression frame. Lsusp does not return directly.
165: / The expression is reactivated when an alternative is needed;
166: / the return actually comes from efail.
167:
168: / Register usage:
169: / r0: pointer to top of stack region to be copied,
170: / which is just above the procedure descriptor (arg0) of the
171: / suspending procedure
172: / r2: old generator frame pointer, indexed down to r0 during copy
173: / r3: new generator frame pointer
174: / r4: suspending expression frame pointer
175: / r5: current procedure frame pointer
176:
177: / This code is exactly the same as esusp.s except for the line marked ***
178: / The difference is due to the extra descriptor below the expression frame
179: / marker that holds the limit counter.
180:
181: 1:
182: mov r5,-(sp) / create new procedure frame
183: mov sp,r5
184: mov r4,-(sp) / save registers
185: mov r3,-(sp)
186: mov r2,-(sp)
187: mov r5,-(sp) / create Icon/C boundary
188: mov r5,_boundary
189:
190: / Calculate addresses of new generator frame.
191:
192: mov sp,r3 / r3 <- pointer to new generator frame
193: mov _k_level,-(sp) / save &level
194: mov _line,-(sp) / save current line number
195: mov _file,-(sp) / and file name
196: mov r4,r0 / r0 <- pointer to top of region to be copied
197: add $6,r0 / (= r4 + 6) ***
198: mov -2(r4),r2 / r2 <- generator frame pointer from caller
199: bne 1f / use saved gfp - 6 if non-zero,
200: mov (r4),r2 / else use saved efp - 4
201: cmp -(r2),-(r2)
202: br 2f
203: 1:
204: sub $6,r2
205: br 2f
206:
207: / Copy surrounding expression frame.
208:
209: 1:
210: mov -(r2),-(sp)
211: 2:
212: cmp r2,r0 / stop at end of frame
213: bhi 1b
214:
215: / Copy value of suspending expression.
216:
217: mov 8.(r5),-(sp) / push return value
218: mov 6(r5),-(sp)
219:
220: / Return to code; reactivation will go directly to efail.
221:
222: mov 2(r5),r1 / r1 <- return pc
223: mov $_efail,2(r5) / fix reactivation pc to propagate failure
224: mov -6(r5),r2
225: mov (r5),r5 / restore old registers,
226: mov (r4),r4 / and exit suspending expression frame
227: clr _boundary / returning to Icon code
228: jmp (r1) / this really suspends
229: #endif PDP11
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.