Annotation of 43BSD/contrib/icon/lib/invoke.s, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.