|
|
1.1 ! root 1: #include "../h/config.h" ! 2: /* ! 3: * invoke is used to invoke something. Among the candidates are: ! 4: * Call a built-in function ! 5: * Call an Icon procedure ! 6: * Create a record ! 7: * Perform mutual evaluation ! 8: * ! 9: * Note that all calls rise from a source code construct like ! 10: * expr0(expr1,...,exprn) ! 11: */ ! 12: Global(_interp) /* interpreter loop */ ! 13: Global(_cvstr) /* convert to string */ ! 14: #ifdef XPX ! 15: Global(_strprc) /* convert string to procedure block address */ ! 16: #endif XPX ! 17: Global(_ctrace) /* call trace routine */ ! 18: Global(_cvint) /* convert to integer */ ! 19: Global(_cvpos) /* convert to position */ ! 20: Global(_deref) /* dereference a variable */ ! 21: Global(_fail) /* failure processing */ ! 22: Global(_runerr) /* issue a runtime error */ ! 23: ! 24: Global(_boundary) /* Icon/C boundary address */ ! 25: Global(_line) /* current line number */ ! 26: Global(_file) /* current file name */ ! 27: Global(_k_level) /* value of &level */ ! 28: Global(_k_trace) /* value of &trace */ ! 29: ! 30: Global(_invoke) ! 31: ! 32: #ifdef VAX ! 33: .text ! 34: _invoke: ! 35: Mask 0x0e02 # Save r1, r9, r10, and r11. The return pc ! 36: # is stashed where r1 is saved. ! 37: #define INVREGS 4 /* number of registers saved */ ! 38: ! 39: movl fp,_boundary # Set Icon/C boundary ! 40: movl 4(ap),r8 # r8 holds number of arguments ! 41: movaq 8(ap)[r8],r11 # r11 points to expr0 ! 42: pushl r11 # Push address of expr0 for deref ! 43: calls $1,_deref # deref(&expr0) ! 44: movl (r11),r0 # r11 now points to a descriptor for ! 45: # expr0. The type word of the descriptor ! 46: # is put in r0 for examination ! 47: cmpl $D_PROC,r0 # See if expr0 is a procedure ! 48: jeql doinvk # if procedure, branch ! 49: /* ! 50: * See if mutual evaluation is to be performed. ! 51: */ ! 52: # If not a procedure, maybe an integer ! 53: pushl $longint # Set up for cvint, longint is buffer to ! 54: pushl r11 # receive result ! 55: calls $2,_cvint # cvint(&expr0,&longint) ! 56: cmpl $T_INTEGER,r0 # Type comes back in r0, if not integer, ! 57: jneq trystr # branch. Otherwise, longint holds ! 58: # integer value of expr0. ! 59: ! 60: pushl 4(ap) # Got an integer, ! 61: movl longint,-(sp) # convert it to a canonical position ! 62: calls $2,_cvpos # cvpos(longint), position ! 63: # comes back in r0 ! 64: cmpl r0,4(ap) # See if position is less than or equal ! 65: # to the number of arguments. ! 66: bleq f1 # if so, branch ! 67: calls $0,_fail # otherwise, fail ! 68: /* ! 69: * Do mutual evaluation by returning expr[expr0] ! 70: */ ! 71: f1: ashl $3,r0,r0 # Each expri is 8 bytes, so r0 is turned ! 72: # into a byte offset by multiplying it by 3. ! 73: subl3 r0,r11,r1 # Point r1 at desired expri ! 74: movq (r1),(r11) # r11 points at expr0, which is to replaced ! 75: # by result of mutual evaluation (the result of invoke), ! 76: # so move result of descriptor into expr0's ! 77: # place. ! 78: ! 79: clrl _boundary # mutual evaluation is done, clear the boundary and return ! 80: ret ! 81: ! 82: trystr: ! 83: #ifdef XPX ! 84: /* ! 85: * If expr0 is a string and the name of an operation, expr0 is turned ! 86: * into a procedure and execution proceeds as if expr0 had been ! 87: * a procedure all along. ! 88: */ ! 89: pushl $strbuf # Try to convert expr0 to a string ! 90: pushl r11 ! 91: calls $2,_cvstr # cvstr(&expr0,&strbuf), r0 is ! 92: tstl r0 # non-zero if expr0 is a string, and ! 93: # strbuf will contain the string. ! 94: beql f4 # If expr0 couldn't not be converted ! 95: # to a string, branch. ! 96: ! 97: pushl r8 # Otherwise, see if the string names ! 98: pushl r11 # a procedure or a function ! 99: calls $2,_strprc # strprc(&expr0,r8), note that r8 contains ! 100: # the number of expri (number of arguments) ! 101: tstl r0 # If non-zero rc, r11 now points to a ! 102: bneq doinvk # descriptor that references the procedure ! 103: # to be invoked. ! 104: #endif XPX ! 105: f4: pushl r11 # if not procedure or integer, then error ! 106: pushl $106 ! 107: calls $2,_runerr # runerr(106,&expr0) ! 108: ! 109: /* ! 110: * If the procedure being invoked has a fixed number of arguments, ! 111: * the arguments supplied are adjusted to conform in number to ! 112: * the number expected. ! 113: */ ! 114: doinvk: movl 4(r11),r9 # r11 is a procedure descriptor, r9 ! 115: # gets the address of the procedure block. ! 116: movl 12(r9),r10 # The fourth word of the procedure block ! 117: # is the number of arguments the procedure ! 118: # wants. ! 119: jlss builtin # If < 0, the number of arguments is variable; ! 120: # branch to builtin. ! 121: ! 122: subl2 r10,r8 # r8 = # args expected - # args given ! 123: beql doderef # If # given is the # expected, no ! 124: # adjustment is required. ! 125: # Otherwise, nargs and nwords must ! 126: # be adjusted. ! 127: movl r10,4(ap) # Change nargs on stack ! 128: movb r10,(ap) # Set nwords to nargs ! 129: addb2 (ap),(ap) # Double nwords because each argument ! 130: # is two words long. ! 131: addb2 $1,(ap) # Add 1 to nwords to allow for the ! 132: # nargs word. ! 133: /* ! 134: * The arguments now need to be adjusted to conform with the ! 135: * number expected. ! 136: */ ! 137: ashl $3,r8,r8 # Convert r8 to byte count ! 138: addl2 r8,sp # Move the stack pointer up or down ! 139: # as required ! 140: # ! 141: # Now the portion of the stack from ! 142: # nargs to the condition handler (inclusive) ! 143: # must be moved up or down. This ! 144: # region is ! 145: # 5 (handler, psw, ap, fp, pc) ! 146: # + ! 147: # INVREGS (11 registers saved) ! 148: # + ! 149: # 2 (nwords, nargs) words long ! 150: movc3 $(INVREGS+7)*4,(fp),(sp) # do the move, note that the ! 151: # the VAX microcode is smart enough to ! 152: # allow the regions to overlap. ! 153: movl sp,fp # Point fp at new top of stack ! 154: movl fp,_boundary # The boundary follows the fp ! 155: addl2 r8,ap # Also adjust argument pointer ! 156: tstl r8 # If r8 is positive, there were too ! 157: # many arguments, and the stack move ! 158: # overwrote excess ones. If r8 is ! 159: bgeq doderef # negative, the stack moved down ! 160: # leaving a "hole" where additional ! 161: # arguments are to be. Branch ! 162: # if r8 is positive. ! 163: # ! 164: # ! 165: mnegl r8,r8 # Otherwise, make r8 positive and ! 166: # insert null bytes to form null ! 167: # descriptors for the missing ! 168: # arguments. ! 169: movc5 $0,(r0),$0,r8,(INVREGS+7)*4(sp) # Do it. Note that ! 170: # this is a VAX idiom to move a bunch ! 171: # of null bytes to a location, r0 ! 172: # is not used at all. ! 173: /* ! 174: * Arguments to Icon procedures must be dereferenced ! 175: */ ! 176: doderef: ! 177: tstl 16(r9) # r9 still points at the procedure ! 178: # block of the procedure being invoked ! 179: # and the fifth word of the block is ! 180: # the number of dynamic locals. If ! 181: jlss builtin # it's less than 0, the procedure is ! 182: # a builtin. ! 183: tstl r10 # r10 is the number of arguments, if ! 184: jeql cktrace # it's 0 (no arguments) no dereferencing ! 185: # is needed. ! 186: ! 187: moval -8(r11),r6 # Point r6 at expr1 for later use ! 188: movl r10,r5 # Make copy of r10 for a counter ! 189: nxtarg: ! 190: pushaq -(r11) # r11 points at expr0 initially, it ! 191: # is decremented by 8, and the resulting ! 192: # value is pushed on the stack. This ! 193: # value is the address of the descriptor ! 194: # for a particular expri and the expri ! 195: calls $1,_deref # is dereferenced ! 196: sobgeq r5,nxtarg # Loop around, dereferencing each expri ! 197: /* ! 198: * If tracing is on, indicated by _k_trace (&trace) being non-zero, ! 199: * ctrace is called to produce the appropriate trace message. ! 200: */ ! 201: cktrace: ! 202: tstl _k_trace # If not tracing, ! 203: beql tracedone # then branch ! 204: # Otherwise, must set up for the ! 205: # call to ctrace. ! 206: pushl r6 # Push &expr1 ! 207: pushl r10 # Push nargs ! 208: pushl r9 # Push r9, procedure block address ! 209: calls $3,_ctrace # ctrace(&procedure-block,nargs,&expr1) ! 210: /* ! 211: * A procedure frame was partially built by the call to invoke, ! 212: * it is completed by adding _line, _file, and &null for each ! 213: * local variable. ! 214: */ ! 215: tracedone: ! 216: pushl _line # Put _line ! 217: pushl _file # and _file on the stack ! 218: ! 219: ashl $3,16(r9),r0 # r0 = #locals * 3 ! 220: subl2 r0,sp # Make space on stack for locals ! 221: movc5 $0,(r0),$0,r0,(sp) # Move the required number of null ! 222: # bytes onto the stack ! 223: /* ! 224: * Enter the procedure or function. ! 225: */ ! 226: clrl _boundary # Clear the boundary since an Icon ! 227: # procedure is to be invoked. ! 228: incl _k_level # Increment &level to indicate one more ! 229: # level of depth. ! 230: movl 8(r9),ipc # Get the procedure entry point which ! 231: # is the third word of the procedure block ! 232: # and load the interpreter pc with it. ! 233: clrq gfp # clear gfp and efp (r10 and r11) ! 234: jmp _interp # Jump back to the interpreter, note ! 235: # that at this point, the procedure ! 236: # is "in execution". ! 237: /* ! 238: * Handle invocation of a builtin procedure. Because of the extra ! 239: * "help" the VAX provides, this is inordinately complicated. ! 240: */ ! 241: builtin: ! 242: movl 16(fp),20(fp) # Save real return address where r1 ! 243: # "should be". ! 244: movab bprtn,16(fp) # Use a fake return address so that ! 245: # control comes to "bprtn:" below when ! 246: # the built-in procedure returns. ! 247: movl fp,_boundary # Going into C code, so the boundary ! 248: # must be set. ! 249: jmp *8(r9) # Jump into the procedure. ! 250: ! 251: bprtn: # When the procedure returns, it comes ! 252: # right here. ! 253: clrl _boundary # Clear Icon/C boundary since we're going ! 254: # back to Icon. (Builtin's are C fcns.) ! 255: jmp (r1) # Jump back to caller of invoke. Recall ! 256: # that the pc was stashed where r1 should ! 257: # have been saved. ! 258: ! 259: .data ! 260: longint: .long 0 ! 261: strbuf: .space MAXSTRING ! 262: #endif VAX ! 263: ! 264: #ifdef PORT ! 265: DummyFcn(_invoke) ! 266: #endif PORT ! 267: ! 268: #ifdef PDP11 ! 269: / invoke - call a procedure or function or create a record or ! 270: / perform mutual goal-directed evaluation. ! 271: / Supplies missing arguments, deletes extras for Icon ! 272: / procedures. ! 273: ! 274: / Register usage: ! 275: / r0-r2: utility registers ! 276: / r3: pointer to procedure block ! 277: / r4: pointer to icon arguments on the stack ! 278: / r5: current procedure frame pointer ! 279: ! 280: .text ! 281: _invoke: ! 282: mov r5,-(sp) / create new procedure frame ! 283: mov sp,r5 ! 284: mov r5,_boundary / set Icon/C boundary ! 285: mov r4,-(sp) / save registers ! 286: mov r3,-(sp) ! 287: mov r2,-(sp) ! 288: ! 289: / Find descriptor for procedure or function and dereference it. ! 290: ! 291: mov 4(r5),r4 / get # arguments supplied ! 292: asl r4 / compute address ! 293: asl r4 / of procedure name ! 294: add $6,r4 / in r4 ! 295: add r5,r4 ! 296: mov r4,-(sp) / dereference it ! 297: jsr pc,_deref ! 298: tst (sp)+ ! 299: mov (r4),r0 / get type field of descriptor ! 300: cmp $D_PROC,r0 / check for procedure type ! 301: beq 3f ! 302: mov $longint,-(sp) / see if its an integer for MGDE ! 303: mov r4,-(sp) ! 304: jsr pc,_cvint ! 305: cmp (sp)+,(sp)+ ! 306: cmp $T_INTEGER,r0 ! 307: bne 2f ! 308: mov 4(r5),-(sp) / push number of expressions ! 309: mov $longint,r0 / convert integer to position ! 310: mov 2(r0),-(sp) ! 311: mov (r0),-(sp) ! 312: jsr pc,_cvpos / r0 <- position ! 313: cmp (sp)+,(sp)+ ! 314: tst (sp)+ ! 315: cmp r0,4(r5) / see if in range ! 316: ble 1f ! 317: jsr pc,_fail / if not then fail ! 318: 1: asl r0 / convert position to offset from arg0 ! 319: asl r0 ! 320: mov r4,r1 ! 321: sub r0,r1 ! 322: mov (r1)+,(r4)+ / copy result to arg0 ! 323: mov (r1),(r4) ! 324: tst -(r4) / restore r4 ! 325: mov r4,sp / set sp to end of returned result ! 326: mov r5,r0 ! 327: mov (r5),r1 ! 328: mov -(r0),r4 / restore registers ! 329: mov -(r0),r3 ! 330: mov -(r0),r2 ! 331: clr _boundary ! 332: mov (r5)+,r0 / r0 <- return pc. ! 333: mov (r5)+,r0 ! 334: mov r1,r5 ! 335: jmp (r0) / return to code ! 336: 2: ! 337: #ifdef XPX ! 338: /* ! 339: * If the invokee is a string and the name of an operation, ! 340: * we invoke the corresponding procedure. ! 341: */ ! 342: mov $strbuf,-(sp) ! 343: mov r4,-(sp) ! 344: jsr pc,_cvstr / see if string for string invocation ! 345: cmp (sp)+,(sp)+ ! 346: tst r0 ! 347: beq 4f / if ok, we see if the string is the ! 348: / name of something ! 349: mov 4(r5),-(sp) / push number of arguments ! 350: mov r4,-(sp) / address of string descriptor ! 351: jsr pc,_strprc ! 352: cmp (sp)+,(sp)+ ! 353: tst r0 ! 354: bne 3f / if non-zero rc, r4 now points to a ! 355: / descriptor that references the ! 356: / procedure we want ! 357: #endif XPX ! 358: 4: mov r4,-(sp) / if not procedure or integer, error ! 359: mov $106.,-(sp) ! 360: jsr pc,_runerr ! 361: ! 362: / Check number of arguments supplied vs. number expected. ! 363: ! 364: 3: ! 365: mov 2(r4),r3 / get pointer field of descriptor ! 366: mov 6(r3),r0 / get # arguments expected ! 367: blt builtin / if < 0, # arguments is variable ! 368: mov r0,nargs / save # expected for later dereferencing ! 369: sub 4(r5),r0 / subtract # supplied from # expected ! 370: beq 1f / if zero difference, no adjustment ! 371: mov nargs,4(r5) / change nargs on stack ! 372: neg r0 / negate the difference ! 373: blt 2f / if too few supplied, branch ! 374: ! 375: / Too many arguments supplied: delete extras, compressing the stack. ! 376: ! 377: mov r5,r1 / compute adjustment addresses ! 378: add $6,r1 / r1 <- source ! 379: asl r0 / r0 <- dest ! 380: asl r0 ! 381: add r0,r5 / adjust r5 ! 382: add r0,_boundary / and boundary ! 383: add r1,r0 ! 384: 3: / move top 6 words up ! 385: mov -(r1),-(r0) ! 386: cmp r1,sp ! 387: bgt 3b ! 388: ! 389: mov r0,sp / adjust stack pointer ! 390: br 1f ! 391: ! 392: / Too few arguments supplied: push null values, expanding the stack. ! 393: ! 394: 2: ! 395: mov 4(r5),nargs / save # supplied for later dereferencing ! 396: asl r0 / compute new top of stack ! 397: asl r0 ! 398: add r0,r5 / adjust r5 ! 399: add r0,_boundary / and boundary ! 400: add sp,r0 ! 401: mov r0,r2 / save new stack pointer ! 402: mov $6,r1 ! 403: 3: / move top 6 words down ! 404: mov (sp)+,(r0)+ ! 405: sob r1,3b ! 406: 3: / supply &null for omitted arguments ! 407: clr (r0)+ ! 408: clr (r0)+ ! 409: cmp r0,sp ! 410: blt 3b ! 411: ! 412: mov r2,sp / restore new top of stack pointer ! 413: ! 414: / Dereference arguments to Icon procedures. ! 415: ! 416: 1: ! 417: tst 8.(r3) / test # dynamic locals ! 418: blt builtin / if < 0, then builtin function ! 419: mov nargs,r2 / dereference the arguments ! 420: beq 1f ! 421: 2: ! 422: cmp -(r4),-(r4) / point r4 to next argument ! 423: mov r4,-(sp) / dereference it ! 424: jsr pc,_deref ! 425: tst (sp)+ ! 426: sob r2,2b ! 427: ! 428: / Print trace message if &trace is set. ! 429: ! 430: 1: ! 431: tst _k_trace ! 432: beq 1f ! 433: mov nargs,r0 / calc address of arg1 via: ! 434: dec r0 / sp + 12. + (nargs-1)*4 ! 435: asl r0 ! 436: asl r0 ! 437: add $12.,r0 ! 438: add sp,r0 ! 439: mov r0,-(sp) / push &arg1 ! 440: mov nargs,-(sp) / push nargs ! 441: mov r3,-(sp) / push proc address ! 442: jsr pc,_ctrace / ctrace(proc_address,nargs,&arg1) ! 443: cmp (sp)+,(sp)+ ! 444: tst (sp)+ / zap ctrace args ! 445: ! 446: / Save line number and file name ! 447: ! 448: 1: ! 449: mov _line,-(sp) ! 450: mov _file,-(sp) ! 451: ! 452: / Push null values onto stack for each dynamic local ! 453: ! 454: mov 8.(r3),r0 / get # dynamic locals ! 455: beq 1f ! 456: 2: ! 457: clr -(sp) / push null value on stack for each ! 458: clr -(sp) / dynamic local ! 459: sob r0,2b ! 460: ! 461: / Enter the procedure or function. ! 462: ! 463: 1: ! 464: clr _boundary / clear boundary when going to Icon procedure ! 465: inc _k_level / increment &level ! 466: mov 4(r3),r2 / r2 <- procedure entry point ! 467: clr r3 / clear generator frame pointer ! 468: clr r4 / and expression frame pointer ! 469: jmp _interp / jump back to interpreter ! 470: builtin: / special-case builtin functions ! 471: jsr pc,*4(r3) / jump to procedure entry point ! 472: ! 473: .bss ! 474: nargs: .=.+2 ! 475: longint: .=.+4 ! 476: strbuf: .=.+MAXSTRING ! 477: #endif PDP11
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.