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

1.1       root        1: #include "../h/config.h"
                      2: 
                      3: /* psusp - suspends a value from an Icon procedure.  The procedure
                      4:  *  calling psusp is suspending and the value to suspend appears as
                      5:  *  an argument to psusp.  The generator or expression frame
                      6:  *  immediately containing the frame of the suspending procedure is
                      7:  *  duplicated.
                      8:  *
                      9:  * psusp returns through the duplicated procedure frame and leaves the
                     10:  *  value being suspended on the top of the stack.  When an alternative
                     11:  *  is needed, efail causes a return through the original procedure frame
                     12:  *  which was created by invoke.
                     13:  */
                     14: Global(_deref)         /* Dereference a variable */
                     15: Global(_strace)                /* Trace procedure suspension */
                     16: Global(_boundary)      /* Icon/C boundary address */
                     17: Global(_current)       /* Current expression stack */
                     18: Global(_line)          /* Current line number */
                     19: Global(_file)          /* Current file name */
                     20: Global(_k_level)       /* Value of &level */
                     21: Global(_k_trace)       /* Value of &trace */
                     22: 
                     23: Global(_psusp)
                     24: #ifdef VAX
                     25: _psusp:
                     26: /*
                     27:  * Construct the generator frame.
                     28:  */
                     29:        Mask    STDSV           # Start new generator frame by saving
                     30:                                #  registers upon entry to psusp.
                     31:        movl    fp,_boundary    # Establish boundary value to be saved
                     32:                                #  in frame.  boundary is also needed 
                     33:                                #  because deref may be called.
                     34:        pushl   fp              # Save the boundary in the frame.
                     35: /*
                     36:  * Dereference the return value if it is a local variable or an
                     37:  *  argument.
                     38:  */
                     39:                                # The return value is on the stack as
                     40:                                #  an argument, put type field of return
                     41:        movl    8(ap),r1        #  value in r1 for testing.
                     42:        bitl    $F_NQUAL,r1     # If return value is a string,
                     43:        beql    cmpltfrm        #  it doesn't need dereferencing.
                     44:        bitl    $F_VAR,r1       # If return value isn't a variable,
                     45:        beql    cmpltfrm        #  it doesn't need dereferencing.
                     46:        bitl    $F_TVAR,r1      # If return value is a trapped variable,
                     47:        bneq    chktv           #  it requires some work.
                     48:        movl    12(ap),r1       # Otherwise, get the address of the
                     49:        jmp     chkloc          #  data block for more testing.
                     50:        
                     51: chktv:                         # A trapped variable is being returned,
                     52:                                #  only substring trapped variables need
                     53:                                #  dereferencing.
                     54:        bicl2   $~TYPEMASK,r1   # "and" off all but bits in type field
                     55:        cmpl    $T_TVSUBS,r1    # If the variable isn't a substring t.v.,
                     56:        bneq    cmpltfrm        #  it doesn't need dereferencing.
                     57:        movl    12(ap),r1       # Point r1 at data block for s.s.t.v.
                     58:        movl    16(r1),r1       # Then at actual address of variable
                     59: chkloc:                                #
                     60:                                # See if the variable is on the stack.
                     61:                                #  If it is, it will lie between the
                     62:                                #  sp and the base of the current
                     63:                                #  expression stack. r1 holds address
                     64:                                #  of variable.
                     65:        cmpl    r1,sp           # If address is below the sp,
                     66:        blssu   cmpltfrm        #  it's not a local or an argument
                     67:        movl    _current+4,r0   # Point r0 at data block for current
                     68:                                #  expression.
                     69:        cmpl    r1,12(r0)       # Fourth word is the base of the stack
                     70:                                #  for the current expression.  If the
                     71:                                #  variable address is above the stack
                     72:        bgtru   cmpltfrm        #  base, it's not a local or an argument.
                     73:                                # Otherwise, it is a local or an argument
                     74:                                #  and must be dereferenced.
                     75:        pushal  8(ap)           # Push address of return value
                     76:        calls   $1,_deref       #  and dereference it.
                     77: /*
                     78:  * Complete the generator frame.
                     79:  */
                     80: cmpltfrm:
                     81:        movl    sp,gfp          # Boundary value is on top of stack,
                     82:                                #  make it word 0 of generator frame
                     83:         pushl  _k_level        # Push &level,
                     84:        pushl   _line           #  line number,
                     85:        pushl   _file           #  and file name to complete the frame.
                     86: /*
                     87:  * Determine region to be duplicated and copy it.
                     88:  */
                     89:                                # Note that because the call to psusp
                     90:                                #  made a frame, the saved ap and fp
                     91:                                #  values in that frame must be used.
                     92:        movl    12(fp),r7       # Low word of region to be copied is the
                     93:                                #  low word of procedure frame of suspending
                     94:                                #  procedure.
                     95:                                
                     96:                                # If the saved gfp is non-zero, the
                     97:                                #  generator frame marker serves as the
                     98:                                #  upper bound of the expression frame.
                     99:                                # If it is zero, the expression frame
                    100:                                #  marker pointed at by the saved
                    101:                                #  efp is the upper bound of the frame
                    102:                                #  to be copied.
                    103:                                # Note that the marker itself is not
                    104:                                #  copied, the region only extends to
                    105:                                #  the marker and not through it.
                    106:                                # This code counts on efp and gfp being
                    107:                                #  saved in the frame of the suspender.
                    108:        movl    8(fp),r2        # Get ap of suspending procedure in r2
                    109:        movl    -8(r2),r4       # Get gfp from procedure frame of suspending
                    110:                                #  procedure.
                    111:        bneq    f1              # If it is zero,
                    112:        movl    -4(r2),r4       #  get saved efp and
                    113:        subl2   $8,r4           #  use efp - 8.
                    114:        jmp     f2
                    115: f1:                            # gfp is not zero,
                    116:        subl2   $12,r4          #  use gfp - 12.
                    117: /*
                    118:  * Copy region to be duplicated to top of stack.
                    119:  */
                    120:                                # r7 points at the low word of the region
                    121:                                #  to be copied.  r4 points at the high end
                    122:                                #  of the region.  (i.e. r4 is the first
                    123:                                #  word not_ to copy.)
                    124: f2:
                    125:        subl2   r7,r4           # r4 = r4 - r7, giving r4 number of bytes
                    126:                                #  in region.
                    127:        subl2   r4,sp           # Move stack pointer down to make space
                    128:                                #  for region.
                    129:        movc3   r4,(r7),(sp)    # Copy the region by moving r4 bytes starting
                    130:                                #  at r7 to the top of the stack.
                    131: /*
                    132:  * Produce trace message if tracing is on.
                    133:  */
                    134:        decl    _k_level        # Decrement &level because a procedure
                    135:                                #  is being "exited".
                    136:        tstl    _k_trace        # If &trace is 0,
                    137:        jeql    tracedone       #  no tracing.
                    138:                                # Otherwise, call strace with address
                    139:                                #  of suspending procedure block and
                    140:                                #  value being suspended.
                    141:        pushal  8(ap)           # Push pointer to value being suspended.
                    142:                                # arg0 in the suspender's argument list
                    143:                                #  is the descriptor for the suspending
                    144:                                #  procedure.
                    145:        movl    8(fp),r1        # Get suspender's ap into r1.
                    146:        ashl    $3,4(r1),r0     # &arg0 = nargs * 8
                    147:        addl2   $8,r0           #  + 8
                    148:        addl2   r1,r0           #  + ap
                    149:        pushl   4(r0)           # Push second word (the address) of
                    150:                                #  the descriptor for the procedure block
                    151:        calls   $2,_strace      # strace(&procblock,&suspending-value)
                    152: /*
                    153:  * Return from suspending function; resumption will return from suspend.
                    154:  */
                    155: tracedone:
                    156:        movl    12(fp),r1       # Get fp of suspending procedure into r1 and
                    157:        movl    -4(r1),_line    #  restore _line and
                    158:        movl    -8(r1),_file    #  _file from the frame.
                    159:                                # The duplicated frame must be fixed up.
                    160:                                #  Specifically, the saved gfp is replaced
                    161:                                #  by the new gfp, and the value being
                    162:                                #  suspended replaces arg0, the descriptor
                    163:                                #  of the suspending procedure.
                    164:        subl3   r1,8(fp),r0     # Calculate distance between fp and ap
                    165:                                #  in suspender's frame, specifically,
                    166:                                #  r0 = ap - fp
                    167:        addl2   sp,r0           # sp points at the first word of the
                    168:                                #  duplicated procedure frame on the
                    169:                                #  stack.  By adding it to r0, r0 points
                    170:                                #  at nwords word in argument list of
                    171:                                #  duplicated frame.  That is, r0 is
                    172:                                #  serving as a pseudo ap.
                    173:        subl3   $8,r0,r1        # Point r1 at location of saved gfp
                    174:                                #  in duplicated frame.
                    175:        movl    gfp,(r1)        # Replace saved gfp with new gfp value
                    176:                                # Calculate address of arg0 via
                    177:                                #  &arg0 =
                    178:        ashl    $2,(r0),r1      #   nwords * 4
                    179:        addl2   $4,r1           #   + 4 (bytes for nwords word)
                    180:        addl2   r1,r0           #   + (pseudo) ap
                    181:        movq    8(ap),(r0)      # Replace arg0 with suspending value
                    182:                                #
                    183:        movl    sp,fp           # Point fp at duplicated procedure frame
                    184:                                #  in preparation for return through it.
                    185:        clrl    _boundary       # Clear the boundary since control is
                    186:                                #  going back into Icon code.
                    187:        ret                     # Return through duplicated frame.  This
                    188:                                #  looks like the original invoke for the
                    189:                                #  suspending procedure has returned.  The
                    190:                                #  suspended value is left on the top
                    191:                                #  of the stack.
                    192: 
                    193: #endif VAX
                    194: 
                    195: #ifdef PORT
                    196: DummyFcn(_psusp)
                    197: #endif PORT
                    198: #ifdef PDP11
                    199: / psusp - suspend from an Icon procedure.
                    200: / Duplicates the most recent generator frame outside the
                    201: / calling procedure frame.  The procedure calling psusp is
                    202: / suspending, and the saved value of r3 in its frame marker
                    203: / points to the beginning of the generator frame to be
                    204: / duplicated.  Psusp does not return directly.  The caller
                    205: / is reactivated when an alternative is needed; the return
                    206: / actually comes from efail.
                    207: 
                    208: / Register usage:
                    209: /   r0:    pointer to top of stack region to be copied,
                    210: /           which is just above the procedure descriptor (arg0) of the
                    211: /           suspending procedure
                    212: /   r2:    suspending procedure frame pointer
                    213: /   r3:    new generator frame pointer
                    214: /   r4:           old generator frame pointer, indexed down to r0 during copy
                    215: /   r5:    current procedure frame pointer
                    216: 
                    217:  .globl        _deref                  / dereference a variable
                    218:  .globl        _strace                 / suspend trace routine
                    219: 
                    220:  .globl        _boundary               / Icon/C boundary address
                    221:  .globl        _current                / current expression stack
                    222:  .globl        _file                   / current file name
                    223:  .globl  _k_level              / value of &level
                    224:  .globl        _k_trace                / value of &trace
                    225:  .globl        _line                   / current line number
                    226: 
                    227:  .globl  _psusp
                    228: _psusp:
                    229:        mov     r5,-(sp)        / create new procedure frame
                    230:        mov     sp,r5
                    231:        mov     r4,-(sp)        / save registers
                    232:        mov     r3,-(sp)
                    233:        mov     r2,-(sp)
                    234:        mov     r5,-(sp)        / create Icon/C boundary
                    235:        mov     r5,_boundary
                    236: 
                    237: / Dereference return value if necessary.
                    238: 
                    239:        mov     6(r5),r1        / get type field of return value into r1
                    240:        bit     $F_NQUAL,r1     / if return value is the
                    241:        beq     1f              /   name of a local variable
                    242:        bit     $F_VAR,r1       /   or argument, then it
                    243:        beq     1f              /   needs dereferencing
                    244:        bit     $F_TVAR,r1
                    245:        bne     2f
                    246:        mov     8.(r5),r1       / get pointer field into r1
                    247:        br      3f
                    248: 2:
                    249:        bic     $!TYPEMASK,r1   / check type code for substring t.v.
                    250:        cmp     $T_TVSUBS,r1    /   if not, it doesn't need
                    251:        bne     1f              /   dereferencing
                    252:        mov     8.(r5),r1       / get pointer field from b_tvsubs
                    253:        mov     8.(r1),r1       /   block into r1
                    254: 3:
                    255:        cmp     r1,sp           / if pointer is between
                    256:        blo     1f              /   sp and sbase, it is a local
                    257:        mov     _current+2,r0   /   or an argument
                    258:        cmp     r1,6(r0)
                    259:        bhi     1f
                    260:        mov     r5,-(sp)        / dereference it
                    261:        add     $6,(sp)
                    262:        jsr     pc,_deref
                    263:        tst     (sp)+
                    264: 1:
                    265: 
                    266: / Calculate addresses of new generator frame.
                    267: 
                    268:        mov     sp,r3           / r3 <- pointer to new generator frame
                    269:        mov     _k_level,-(sp)  / save &level
                    270:        mov     _line,-(sp)     / save current line number
                    271:        mov     _file,-(sp)     /   and file name
                    272:        mov     (r5),r2         / r2 <- pointer to calling procedure frame
                    273:        mov     4(r2),r0        / r0 <- pointer to top of region to be copied
                    274:        asl     r0              /       (= r2 + 10 + 4*nargs)
                    275:        asl     r0
                    276:        add     r2,r0
                    277:        add     $10.,r0
                    278:        mov     -4(r2),r4       / r4 <- generator frame pointer from caller
                    279:        bne     1f              /   use saved r3 (gfp) - 6 if non-zero,
                    280:        mov     -2(r2),r4       /   else use saved r4 (efp) - 4
                    281:        cmp     -(r4),-(r4)
                    282:        br      2f
                    283: 1:
                    284:        sub     $6,r4
                    285:        br      2f
                    286: 
                    287: / Copy surrounding expression frame.
                    288: 
                    289: 1:
                    290:        mov     -(r4),-(sp)     / copy old generator frame
                    291: 2:
                    292:        cmp     r4,r0           / stop at end of frame
                    293:        bhi     1b
                    294: 
                    295: / Copy return value of suspending procedure.
                    296: 
                    297:        mov     8.(r5),-(sp)
                    298:        mov     6(r5),-(sp)
                    299: 
                    300: / Decrement &level; print trace message if &trace is set.
                    301: 
                    302:        dec     _k_level
                    303:        tst     _k_trace        / print trace if &trace != 0
                    304:        beq     1f
                    305:        mov     r5,-(sp)        /   push address of suspending value
                    306:        add     $6,(sp)
                    307:        mov     -(r0),-(sp)     /   push address of procedure block
                    308:        jsr     pc,_strace      /   call strace
                    309:        cmp     (sp)+,(sp)+
                    310: 
                    311: / Return from suspending procedure; reactivation will return from psusp.
                    312: 
                    313: 1:
                    314:        mov     r2,r0
                    315:        mov     2(r0),r1        / r1 <- return pc
                    316:        mov     (r0),r5         / restore old registers
                    317:        mov     -(r0),r4
                    318:        tst     -(r0)           /   except generator frame pointer
                    319:        mov     -(r0),r2
                    320:        mov     -(r0),_line
                    321:        mov     -(r0),_file
                    322:        clr     _boundary       / returning to Icon code
                    323:        jmp     (r1)            / this really suspends
                    324: #endif PDP11

unix.superglobalmegacorp.com

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