1: #include "../h/config.h" 2: 3: /* 4: * esusp - suspends a value from an expression. A generator frame 5: * hiding the current expression frame is created. The surrounding 6: * expression frame is duplicated and the value being suspended 7: * is copied to the top of the stack. The generator frame that 8: * is created uses efail as a return point, thus if an alternative 9: * is needed, efail will return to itself via the generator frame 10: * and then resume execution at the failure label specified in 11: * the expression marker. 12: * 13: * The value being suspended appears as an argument. 14: */ 15: 16: Global(_efail) /* signal failure in an expression */ 17: Global(_boundary) /* Icon/C boundary address */ 18: Global(_line) /* current line number */ 19: Global(_file) /* current file name */ 20: Global(_k_level) /* value of &level */ 21: 22: Global(_esusp) 23: 24: #ifdef VAX 25: _esusp: 26: /* 27: * Construct the generator frame. 28: */ 29: Mask STDSV # Partially create new generator frame 30: movl fp,_boundary # Set the boundary 31: pushl fp # Push boundary as part of generator frame 32: movl sp,gfp # The generator frame pointer points at 33: # the word containing the boundary. 34: pushl _k_level # Save &level, 35: pushl _line # line number, 36: pushl _file # and file name in generator frame, 37: # completing the frame. 38: /* 39: * Determine region to be copied. 40: */ 41: addl3 $4,efp,r0 # Point r0 at first word above the 42: # expression frame marker. This 43: # word is the lower end of the region 44: # that will be copied. 45: 46: # If the saved gfp is non-zero, the 47: # generator frame marker serves as the 48: # upper bound of the expression frame. 49: # If it is zero, the expression frame 50: # marker pointed at by the saved 51: # efp is the upper bound of the frame 52: # to be copied. 53: # Note that the marker itself is not 54: # copied, the region only extends to 55: # the marker and not through it. 56: movl -4(efp),r2 # Get gfp from expression marker. 57: jneq f1 # If it is zero, 58: subl3 $8,(efp),r2 # use saved efp - 8. 59: jmp f2 60: f1: # gfp is not zero, 61: subl2 $12,r2 # use gfp - 12. 62: /* 63: * Copy surrounding expression frame. 64: */ 65: # r0 points to the lowest word to be copied 66: # and r2 points to high end of the region. 67: # The word that r2 points at is part of 68: # a generator or expression frame marker 69: # is not copied. 70: f2: subl2 r0,r2 # Calculate length in bytes of region and 71: # put it in r2. 72: subl2 r2,sp # Move stack pointer down to accommodate 73: # copied region. 74: movc3 r2,(r0),(sp) # Copy the region by moving r2 bytes from 75: # the address pointed at by r2 to the 76: # address pointed at by the stack pointer. 77: 78: movq 8(ap),-(sp) # Copy the value being suspended to 79: # the top of the stack. 80: /* 81: * Fix things up for return. 82: */ 83: movl 16(fp),r1 # Get the saved pc (the return point for 84: # esusp) out of the frame and save it in r1. 85: movl $_efail,16(fp) # Replace saved pc with efail so that when 86: # a return using the generator frame is 87: # performed, it will go to efail. 88: movl 8(fp),ap # Restore ap 89: movl 12(fp),fp # and fp. 90: clrl _boundary # Clear the boundary since control is 91: # going back into Icon code. 92: movl (efp),efp # Point efp at bounding expression frame 93: # marker. 94: jmp (r1) # Return by branching back to desired 95: # return point. The suspended value is 96: # on the top of the stack, gfp points 97: # at the newly constructed generator 98: # frame. 99: #endif VAX 100: 101: #ifdef PORT 102: DummyFcn(_esusp) 103: #endif PORT 104: 105: #ifdef PDP11 106: / esusp - Suspend from an expression. 107: / Duplicates the most recent generator frame outside the 108: / current expression frame. Esusp does not return directly. 109: / The expression is reactivated when an alternative is needed; 110: / the return actually comes from efail. 111: 112: / Register usage: 113: / r0: pointer to top of stack region to be copied, 114: / which is just above the procedure descriptor (arg0) of the 115: / suspending procedure 116: / r2: old generator frame pointer, indexed down to r0 during copy 117: / r3: new generator frame pointer 118: / r4: suspending expression frame pointer 119: / r5: current procedure frame pointer 120: _esusp: 121: mov r5,-(sp) / create new procedure frame 122: mov sp,r5 123: mov r4,-(sp) / save registers 124: mov r3,-(sp) 125: mov r2,-(sp) 126: mov r5,-(sp) / create Icon/C boundary 127: mov r5,_boundary 128: 129: / Calculate addresses of new generator frame. 130: 131: mov sp,r3 / r3 <- pointer to new generator frame 132: mov _k_level,-(sp) / save &level 133: mov _line,-(sp) / save current line number 134: mov _file,-(sp) / and file name 135: mov r4,r0 / r0 <- pointer to top of region to be copied 136: tst (r0)+ / (= r4 + 2) 137: mov -2(r4),r2 / r2 <- generator frame pointer from caller 138: bne 1f / use saved gfp - 6 if non-zero, 139: mov (r4),r2 / else use saved efp - 4 140: cmp -(r2),-(r2) 141: br 2f 142: 1: 143: sub $6,r2 144: br 2f 145: 146: / Copy surrounding expression frame. 147: 148: 1: 149: mov -(r2),-(sp) 150: 2: 151: cmp r2,r0 / stop at end of frame 152: bhi 1b 153: 154: / Copy value of suspending expression. 155: 156: mov 8.(r5),-(sp) / push return value 157: mov 6(r5),-(sp) 158: 159: / Return to code; reactivation will go directly to efail. 160: 161: mov 2(r5),r1 / r1 <- return pc 162: mov $_efail,2(r5) / fix reactivation pc to propagate failure 163: mov -6(r5),r2 164: mov (r5),r5 / restore old registers, 165: mov (r4),r4 / and exit suspending expression frame 166: clr _boundary / returning to Icon code 167: jmp (r1) / this really suspends 168: #endif PDP11