1: #include "../h/config.h" 2: 3: /* 4: * efail - handles the failure of an expression. efail is used 5: * by a number of routines. Its task to resume the newest 6: * inactive generator in the current expression frame. If 7: * no such generator exists, the expression frame is exited 8: * and execution continues at the point indicated in the 9: * expression marker. If the marker has a 0 address for 10: * the point to continue at, efail is called to fail again. 11: */ 12: 13: Global(_interp) /* interpreter loop */ 14: Global(_atrace) /* trace generator reactivations */ 15: Global(_boundary) /* Icon/C boundary address */ 16: Global(_line) /* current line number */ 17: Global(_file) /* current file name */ 18: Global(_k_level) /* value of &level */ 19: Global(_k_trace) /* value of &trace */ 20: 21: Global(_efail) 22: /* 23: * Note that efail is jumped to. 24: */ 25: #ifdef VAX 26: _efail: 27: tstl gfp # gfp points to the most recent generator 28: # frame. If it's 0, there is no inactive 29: jeql nogen # generator in this expression frame and 30: # the frame is exited. 31: 32: /* 33: * There is an inactive generator in this expression frame. It 34: * must be reactivated. 35: */ 36: movl (gfp),_boundary # Restore boundary address from that 37: # stored in the generator frame. 38: movl fp,r0 # Save fp value for testing later. 39: # The fp must be restored. gfp points 40: movl gfp,fp # at the word before the former top 41: tstl (fp)+ # of stack. The fp is loaded from 42: # gfp and then incremented by 4. 43: /* 44: * Trace resumption if &trace is set and if generator is an Icon procedure. 45: */ 46: tstl _k_trace # If &trace is 0, 47: jeql tracedone # no tracing. 48: cmpl _boundary,fp # If the boundary is not the same as the 49: jneq tracedone # fp, the generator is not an Icon procedure. 50: movl 12(fp),efp # Point efp at saved fp in generator frame. 51: # If efp is the same as the fp was upon 52: cmpl efp,r0 # entry to efail, then generator is 53: jeql tracedone # control regime 54: # 55: # Otherwise, an Icon procedure is to be 56: # resumed. atrace handles the tracing, 57: # and takes the address of the procedure 58: # block as it's only argument. arg0 is 59: # is the descriptor for the block. It is 60: # located using: 61: # &arg0 = (ap + 8 + 8*nargs) 62: movl 8(fp),r4 # r4 = old ap 63: ashl $3,4(r4),r2 # r2 = nargs * 8 64: addl2 r4,r2 # ... + old ap 65: addl2 $8,r2 # ... + 8 66: pushl 4(r2) # r2 points to descriptor, push address 67: # residing in second word. 68: calls $1,_atrace # atrace(&arg0) 69: /* 70: * Resume the generator. 71: */ 72: tracedone: 73: movl -(gfp),_k_level # Restore &level 74: movl -(gfp),_line # Restore _line and 75: movl -(gfp),_file # _file from the generator frame. 76: 77: cmpl _boundary,fp # If the boundary is the same as the 78: bneq f3 # fp, the return if from Icon to C 79: clrl _boundary # and the boundary is cleared. 80: f3: 81: ret # All set, return. This return 82: # will sweep off the generator frame 83: # on the top of the stack and resume 84: # execution after point where the 85: # suspension that created this generator 86: # was performed. 87: 88: /* 89: * There are no inactive generators in the expression frame, thus 90: * the expression fails. If the failure label in the expression 91: * frame marker is not 0, execution resumes at the indicated address. 92: * Otherwise, failure in the surrounding expression is signaled by 93: * looping back to efail. 94: */ 95: nogen: 96: movl -8(efp),ipc # Point ipc at failure label from expression 97: # frame. Note that this is always a 98: # ucode address. 99: movl -4(efp),gfp # Restore old generator frame pointer from 100: # expression frame marker. 101: movl efp,sp # Move sp back to point at expression frame 102: # marker. 103: movl (sp)+,efp # Restore old expression frame pointer and 104: # move sp up to previous word. Moving 105: # the sp up effectively removes the 106: # expression marker from the stack. 107: tstl ipc # If the failure label in the expression 108: # frame is 0, this expression fails 109: jeql _efail # by branching back to efail. 110: jmp _interp # Otherwise, execution continues. (at 111: # address in ipc) 112: 113: #endif VAX 114: 115: #ifdef PORT 116: DummyFcn(_efail) 117: #endif PORT 118: 119: #ifdef PDP11 120: / efail - reactivate newest inactive generator within current 121: / expression frame. If there are none, exit the expression 122: / frame and take the failure branch (stored in the expression 123: / frame marker). 124: Global(cret) 125: _efail: 126: tst r3 / test for inactive generators, 127: beq 1f / branch if none 128: 129: / Reactivate newest inactive generator. 130: 131: mov (r3),_boundary / restore Icon/C boundary address 132: mov r5,r0 / save procedure frame pointer 133: mov r3,r5 / restore procedure frame pointer 134: add $8.,r5 135: 136: / Trace reactivation if &trace is set and if generator is an Icon procedure. 137: 138: tst _k_trace 139: beq 2f 140: cmp _boundary,r5 / if boundary == r5, then 141: bne 2f / generator is an Icon procedure 142: mov (r5),r4 / r4 <- address of procedure frame 143: cmp r4,r0 / if hidden procedure frame is same as current, 144: beq 2f / then generator is control regime 145: mov 4(r4),r2 / r2 <- nargs * 4 146: asl r2 147: asl r2 148: add r4,r2 / push address of procedure block, 149: mov 8.(r2),-(sp) / which is pointer field of arg0 150: jsr pc,_atrace 151: 152: / Restore &level, line number, and file name, and return to generator. 153: 154: 2: 155: mov -(r3),_k_level 156: mov -(r3),_line 157: mov -(r3),_file 158: jmp cret 159: 160: / Exit expression frame and signal failure again. 161: 162: 1: 163: mov -4(r4),r2 / get failure label 164: mov -2(r4),r3 / exit current expression frame 165: mov r4,sp 166: mov (sp)+,r4 167: tst r2 / is failure label zero? 168: beq _efail / yes, pass failure to outer expression 169: jmp _interp / no, resume interpreting at failure label 170: 171: #endif PDP11