1: #include "../h/config.h" 2: /* 3: * suspend suspends from a built-in procedure (a C function). 4: * The function calling suspend is suspending and the value to 5: * suspend is contained in arg0 of its argument list. The generator 6: * or expression frame immediately containing the frame of the 7: * suspending procedure is duplicated. 8: * 9: * suspend returns through the duplicated procedure frame and the 10: * arg0 descriptor of the suspending function is left on the 11: * top of the stack. When an alternative is needed, efail causes 12: * a return through the original procedure frame which was created 13: * by the original call to the built-in procedure. 14: */ 15: Global(_boundary) /* Icon/C boundary address */ 16: Global(_file) /* Current file name */ 17: Global(_k_level) /* Value of &level */ 18: Global(_line) /* Current line number */ 19: 20: Global(_suspend) 21: #ifdef VAX 22: _suspend: 23: /* 24: * Construct the generator frame 25: */ 26: Mask 0x0fc0 # Start new generator frame by saving 27: # registers upon entry to suspend. 28: movl _boundary,r6 # Establish new boundary value and 29: pushl r6 # save it in the new generator frame. 30: movl sp,gfp # Point gfp at boundary word in new frame 31: pushl _k_level # Push &level, 32: pushl _line # line number, 33: pushl _file # and file name to complete the frame. 34: /* 35: * Determine region to be duplicated and copy it. This is just 36: * like it's done in psusp. 37: */ 38: movl 12(fp),r7 # Low word of region to copy is the 39: # low word of procedure frame of suspending 40: # procedure. 41: movl 8(fp),r2 # Get ap of suspending procedure in r2 42: movl -8(r2),r4 # Get gfp from procedure frame of suspending 43: # procedure. 44: bneq f1 # If it is zero, 45: movl -4(r2),r4 # get saved efp and 46: subl2 $8,r4 # use efp - 8. 47: jmp f2 48: f1: # gfp is not zero, 49: subl2 $12,r4 # use gfp - 12. 50: 51: /* 52: * Copy region to be duplicated to top of stack. 53: */ 54: # r7 points at the low word of the region 55: # to be copied. r4 points at the high end 56: # of the region. (i.e. r4 is the first 57: # word not_ to copy.) 58: f2: 59: subl2 r7,r4 # r4 = r4 - r7, giving r4 number of bytes 60: # in region. 61: subl2 r4,sp # Move stack pointer down to make space 62: # for region. 63: movc3 r4,(r7),(sp) # Copy the region by moving r4 bytes starting 64: # at r7 to the top of the stack. 65: /* 66: * Return from suspending function; resumption will return from suspend. 67: */ 68: subl3 12(fp),8(fp),r0 # Calculate distance between fp and ap 69: # in suspender's frame, specifically, 70: # r0 = ap - fp 71: addl2 sp,r0 # sp points at the first word of the 72: # duplicated procedure frame on the 73: # stack. By adding it to r0, r0 points 74: # at nwords word in argument list of 75: # duplicated frame. That is, r0 is 76: # serving as a pseudo ap. 77: subl2 $8,r0 # Point r0 at location of saved gfp 78: # in duplicated frame. 79: movl gfp,(r0) # Replace saved gfp with new gfp value 80: 81: movl sp,fp # Point fp at duplicated procedure frame 82: # in preparation for return through it. 83: clrl _boundary # Clear the boundary since control is 84: # going back into Icon code. 85: ret # Return through duplicated frame. This 86: # looks like a return from the original 87: # call to the built-in function. 88: 89: #endif VAX 90: 91: #ifdef PORT 92: DummyFcn(_suspend) 93: #endif PORT 94: 95: #ifdef PDP11 96: / suspend - Suspend from a (C) function. 97: / Duplicates the most recent generator frame outside the 98: / current boundary. Suspend does not return directly. 99: / The caller is reactivated when an alternative is needed; 100: / the return actually comes from efail. 101: 102: / Register usage: 103: / r0: pointer to top of stack region to be copied, 104: / which is just above the procedure descriptor (arg0) of the 105: / suspending procedure 106: / r2: suspending procedure frame pointer 107: / r3: new generator frame pointer 108: / r4: old generator frame pointer, indexed down to r0 during copy 109: / r5: current procedure frame pointer 110: 111: _suspend: 112: mov r5,-(sp) / create new procedure frame 113: mov sp,r5 114: mov r4,-(sp) / save registers 115: mov r3,-(sp) 116: mov r2,-(sp) 117: mov _boundary,r2 / r2 <- pointer to suspending procedure frame 118: mov r2,-(sp) / save Icon/C boundary address 119: 120: / Calculate addresses of new generator frame. 121: 122: mov sp,r3 / r3 <- pointer to new generator frame 123: mov _k_level,-(sp) / save &level 124: mov _line,-(sp) / save current line number 125: mov _file,-(sp) / and file name 126: mov 4(r2),r0 / r0 <- pointer to top of region to be copied 127: asl r0 / (= r2 + 10 + 4*nargs) 128: asl r0 129: add r2,r0 130: add $10.,r0 131: mov -4(r2),r4 / r4 <- generator frame pointer from caller 132: bne 1f / use saved r3 (gfp) - 6 if non-zero, 133: mov -2(r2),r4 / else use saved r4 (efp) - 4 134: cmp -(r4),-(r4) 135: br 2f 136: 1: 137: sub $6,r4 138: br 2f 139: 140: / Copy surrounding expression frame. 141: 142: 1: 143: mov -(r4),-(sp) 144: 2: 145: cmp r4,r0 / stop at end of frame 146: bhi 1b 147: 148: / Copy return value of suspending function. 149: 150: mov -(r4),-(sp) 151: mov -(r4),-(sp) 152: 153: / Return from suspending function; reactivation will return from suspend. 154: 155: mov 2(r2),r1 / r1 <- return pc 156: mov (r2),r5 / restore old registers 157: mov -(r2),r4 158: tst -(r2) / except generator frame pointer 159: mov -(r2),r2 160: clr _boundary / returning to Icon code 161: jmp (r1) / this really suspends 162: #endif PDP11