Annotation of 43BSD/contrib/icon/lib/invoke.s, revision 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.