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