Annotation of researchv10no/cmd/spitbol/cint/vaxinter.s, revision 1.1

1.1     ! root        1: #
        !             2: #      VAXINTER.S
        !             3: #
        !             4: #      This file contains the assembly language routines that interface
        !             5: #      the Macro SPITBOL compiler written in VAX assembly language to its
        !             6: #      operating system interface functions written in C.
        !             7: #
        !             8: #      Contents:
        !             9: #
        !            10: #      o Overview
        !            11: #      o Global variables accessed by OSINT functions
        !            12: #      o Interface routines between compiler and OSINT functions
        !            13: #      o C callable function get_sp
        !            14: #      o C callable function startup
        !            15: #      o Compiler callable function sbchk
        !            16: #
        !            17: #-----------
        !            18: #
        !            19: #      Overview
        !            20: #
        !            21: #      The Macro SPITBOL compiler relies on a set of operating system
        !            22: #      interface functions to provide all interaction with the host
        !            23: #      operating system.  These functions are referred to as OSINT
        !            24: #      functions.  A typical call to one of these OSINT functions takes
        !            25: #      the following form in the VAX version of the compiler:
        !            26: #
        !            27: #              ...code to put arguments in registers...
        !            28: #              jsb     sysxx           ; call osint function
        !            29: #              .long   exit_1          ; address of exit point 1
        !            30: #              .long   exit_2          ; address of exit point 2
        !            31: #              ...     ...             ; ...
        !            32: #              .long   exit_n          ; address of exit point n
        !            33: #              ...instruction following call...
        !            34: #
        !            35: #      The OSINT function 'sysxx' can then return in one of n+1 ways:
        !            36: #      to one of the n exit points or to the instruction following the
        !            37: #      last exit.  This is not really very complicated - the jsb places
        !            38: #      the return address on the stack, so all the interface function has
        !            39: #      to do is add the appropriate offset to the return address and then
        !            40: #      pick up the exit address and jump to it OR do a normal return via
        !            41: #      an rsb instruction.
        !            42: #
        !            43: #      Unfortunately, a C function cannot handle this scheme.  So, an
        !            44: #      intermediary set of routines have been established to allow the
        !            45: #      interfacing of C functions.  The mechanism is as follows:
        !            46: #
        !            47: #      (1) The compiler calls OSINT functions as described above.
        !            48: #
        !            49: #      (2) A set of assembly language interface routines is established,
        !            50: #          one per OSINT function, named accordingly.  Each interface
        !            51: #          routine ...
        !            52: #
        !            53: #          (a) saves all compiler registers in global variables
        !            54: #              accessible by C functions
        !            55: #          (b) calls the OSINT function written in C
        !            56: #          (c) restores all compiler registers from the global variables
        !            57: #          (d) inspects the OSINT function's return value to determine
        !            58: #              which of the n+1 returns should be taken and does so
        !            59: #
        !            60: #      (3) A set of C language OSINT functions is established, one per
        !            61: #          OSINT function, named differently than the interface routines.
        !            62: #          Each OSINT function can access compiler registers via global
        !            63: #          variables.  NO arguments are passed via the call.
        !            64: #
        !            65: #          When an OSINT function returns, it must return a value indicating
        !            66: #          which of the n+1 exits should be taken.  These return values are
        !            67: #          defined in header file 'inter.h'.
        !            68: #
        !            69: #      Note:  in the actual implementation below, the saving and restoring
        !            70: #      of registers is actually done in one common routine accessed by all
        !            71: #      interface routines.
        !            72: #
        !            73: #      Other notes:
        !            74: #
        !            75: #      The Un*x VAX cC ompilers transform "internal" global names to
        !            76: #      "external" global names by adding a leading underscore at the front
        !            77: #      of the internal name.  Thus, the function name 'osopen' becomes
        !            78: #      '_osopen'.
        !            79: #
        !            80: #      Acknowledgement:
        !            81: #
        !            82: #      This interfacing scheme is based on an idea put forth by Andy Koenig.
        !            83: #
        !            84: #-----------
        !            85: #
        !            86: #      Global Variables
        !            87: #
        !            88: #      The compiler uses 8 registers as described below.
        !            89: #
        !            90:        .data
        !            91:        .globl  _reg_ra
        !            92:        .globl  _reg_cp
        !            93:        .globl  _reg_ia
        !            94:        .globl  _reg_wa
        !            95:        .globl  _reg_wb
        !            96:        .globl  _reg_wc
        !            97:        .globl  _reg_xr
        !            98:        .globl  _reg_xl
        !            99:        .align  2
        !           100: _reg_ra:       .space  4       # Register RA (R2)
        !           101: _reg_cp:       .space  4       # Register CP (R3)
        !           102: _reg_ia:       .space  4       # Register IA (R5)
        !           103: _reg_wa:       .space  4       # Register WA (R6)
        !           104: _reg_wb:       .space  4       # Register WB (R7)
        !           105: _reg_wc:       .space  4       # Register WC (R8)
        !           106: _reg_xr:       .space  4       # Register XR (R9)
        !           107: _reg_xl:       .space  4       # Register XL (R10)
        !           108: #
        !           109:        .globl  _rsboff
        !           110: _rsboff:       .space  4       # Normal rsb return offset
        !           111: #
        !           112: #      The following pointers address those cells in the compiler
        !           113: #      that point into the stack when a load module might be written,
        !           114: #      and which must therefore be relocated.
        !           115:        .globl  _strellst
        !           116: _strellst:
        !           117:        .long   flptr
        !           118:        .long   stbas
        !           119:        .long   gtcef
        !           120:        .long   0               # end of list marker
        !           121: #
        !           122: #      Setup a number of internal addresses in the compiler that cannot
        !           123: #      be directly accessed from within C because of naming difficulties.
        !           124: #
        !           125:        .globl  _ic_type
        !           126: _ic_type:      .long   b$icl
        !           127:        .globl  _sc_type
        !           128: _sc_type:      .long   b$scl
        !           129:        .globl  _xn_type
        !           130: _xn_type:      .long   b$xnt
        !           131:        .globl  _xr_type
        !           132: _xr_type:      .long   b$xrt
        !           133: #
        !           134:        .globl  _id1
        !           135: _id1:  .long   0,id1l
        !           136:        .ascii  "(2.0)"
        !           137: id1e:
        !           138:        .set    id1l,id1e-_id1-8
        !           139:        .align  2
        !           140: #
        !           141:        .globl  _id2
        !           142: _id2:  .long   0,id2l
        !           143:        .ascii  "VAX/UNIX Version"
        !           144: id2e:
        !           145:        .set    id2l,id2e-_id2-8
        !           146:        .align  2
        !           147: #
        !           148:        .globl  _tscblk
        !           149:        .globl  _ticblk
        !           150: _ticblk: .space 8
        !           151: _tscblk: .space 108
        !           152: #
        !           153: #-----------
        !           154: #
        !           155: #      Interface routines
        !           156: #
        !           157: #      Each interface routine takes the following form:
        !           158: #
        !           159: #              sysxx:  jsb     ccaller         # call common interface
        !           160: #                      .long   _sysxx          # address of C OSINT function
        !           161: #                      .long   n               # offset to instruction after
        !           162: #                                              #   last procedure exit
        !           163: #
        !           164: #      We take advantage of the "internal" to "external" transformation
        !           165: #      of names by the C compiler.  Specifically, the assembly language
        !           166: #      interface routine names match those directly called by the compiler:
        !           167: #      'sysxx'.  The corresponding C OSINT functions are also called 'sysxx',
        !           168: #      but the C compiler nicely transforms these names into '_sysxx'.
        !           169: #      
        !           170:        .text
        !           171:        .globl  sysax
        !           172: sysax: jsb     ccaller
        !           173:        .long   _sysax
        !           174:        .long   0
        !           175: #
        !           176:        .globl  sysbx
        !           177: sysbx: jsb     ccaller
        !           178:        .long   _sysbx
        !           179:        .long   0
        !           180: #
        !           181:        .globl  sysdc
        !           182: sysdc: jsb     ccaller
        !           183:        .long   _sysdc
        !           184:        .long   0
        !           185: #
        !           186:        .globl  sysdm
        !           187: sysdm: jsb     ccaller
        !           188:        .long   _sysdm
        !           189:        .long   0
        !           190: #
        !           191:        .globl  sysdt
        !           192: sysdt: jsb     ccaller
        !           193:        .long   _sysdt
        !           194:        .long   0
        !           195: #
        !           196:        .globl  sysef
        !           197: sysef: jsb     ccaller
        !           198:        .long   _sysef
        !           199:        .long   12
        !           200: #
        !           201: #      .globl  sysej
        !           202: #sysej:        jsb     ccaller
        !           203: #      .long   _sysej
        !           204: #      .long   0
        !           205: #
        !           206:        .globl  sysem
        !           207: sysem: jsb     ccaller
        !           208:        .long   _sysem
        !           209:        .long   0
        !           210: #
        !           211:        .globl  sysen
        !           212: sysen: jsb     ccaller
        !           213:        .long   _sysen
        !           214:        .long   12
        !           215: #
        !           216:        .globl  sysep
        !           217: sysep: jsb     ccaller
        !           218:        .long   _sysep
        !           219:        .long   0
        !           220: #
        !           221:        .globl  sysex
        !           222: sysex: jsb     ccaller
        !           223:        .long   _sysex
        !           224:        .long   4
        !           225: #
        !           226: #      .globl  sysfc
        !           227: #sysfc:        jsb     ccaller
        !           228: #      .long   _sysfc
        !           229: #      .long   4
        !           230: #
        !           231:        .globl  syshs
        !           232: syshs: jsb     ccaller
        !           233:        .long   _syshs
        !           234:        .long   24
        !           235: #
        !           236:        .globl  sysid
        !           237: sysid: jsb     ccaller
        !           238:        .long   _sysid
        !           239:        .long   0
        !           240: #
        !           241: #      .globl  sysil
        !           242: #sysil:        jsb     ccaller
        !           243: #      .long   _sysil
        !           244: #      .long   0
        !           245: #
        !           246: #      .globl  sysin
        !           247: #sysin:        jsb     ccaller
        !           248: #      .long   _sysin
        !           249: #      .long   12
        !           250: #
        !           251: #      .globl  sysio
        !           252: #sysio:        jsb     ccaller
        !           253: #      .long   _sysio
        !           254: #
        !           255:        .globl  sysld
        !           256: sysld: jsb     ccaller
        !           257:        .long   _sysld
        !           258:        .long   8
        !           259: #
        !           260:        .globl  sysmm
        !           261: sysmm: jsb     ccaller
        !           262:        .long   _sysmm
        !           263:        .long   0
        !           264: #
        !           265:        .globl  sysmx
        !           266: sysmx: jsb     ccaller
        !           267:        .long   _sysmx
        !           268:        .long   0
        !           269: #
        !           270:        .globl  sysou
        !           271: sysou: jsb     ccaller
        !           272:        .long   _sysou
        !           273:        .long   8
        !           274: #
        !           275: #      .globl  syspi
        !           276: #syspi:        jsb     ccaller
        !           277: #      .long   _syspi
        !           278: #      .long   0
        !           279: #
        !           280:        .globl  syspp
        !           281: syspp: jsb     ccaller
        !           282:        .long   _syspp
        !           283:        .long   0
        !           284: #
        !           285: #      .globl  syspr
        !           286: #syspr:        jsb     ccaller
        !           287: #      .long   _syspr
        !           288: #      .long   4
        !           289: #
        !           290: #      .globl  sysrd
        !           291: #sysrd:        jsb     ccaller
        !           292: #      .long   _sysrd
        !           293: #      .long   4
        !           294: #
        !           295: #      .globl  sysri
        !           296: #sysri:        jsb     ccaller
        !           297: #      .long   _sysri
        !           298: #      .long   4
        !           299: #
        !           300:        .globl  sysrw
        !           301: sysrw: jsb     ccaller
        !           302:        .long   _sysrw
        !           303:        .long   12
        !           304: #
        !           305: #      .globl  sysst
        !           306: #sysst:        jsb     ccaller
        !           307: #      .long   _sysst
        !           308: #      .long   20
        !           309: #
        !           310: #      .globl  systm
        !           311: #systm:        jsb     ccaller
        !           312: #      .long   _systm
        !           313: #      .long   0
        !           314: #
        !           315:        .globl  systt
        !           316: systt: jsb     ccaller
        !           317:        .long   _systt
        !           318:        .long   0
        !           319: #
        !           320:        .globl  sysul
        !           321: sysul: jsb     ccaller
        !           322:        .long   _sysul
        !           323:        .long   0
        !           324: #
        !           325: #      .globl  sysxi
        !           326: #sysxi:        jsb     ccaller
        !           327: #      .long   _sysxi
        !           328: #      .long   8
        !           329: #
        !           330: #-----------
        !           331: #
        !           332: #      CCALLER is called by the OS interface routines to call the
        !           333: #      real C OS interface function.
        !           334: #
        !           335: #      General calling sequence is:
        !           336: #
        !           337: #              jsb     ccaller
        !           338: #              .long   address_of_C_function
        !           339: #              .long   4*number_of_exit_points
        !           340: #
        !           341: #      Control IS NEVER returned to a interface routine.  Instead, control
        !           342: #      is returned to the compiler (THE caller of the interface routine).
        !           343: #
        !           344: #      The C function that is called MUST ALWAYS return an integer
        !           345: #      indicating the proecedure exit to take or that a normal return
        !           346: #      is to be performed.
        !           347: #
        !           348: #              C function      Interpretation
        !           349: #              return value
        !           350: #              ------------    -------------------------------------------
        !           351: #                   <0         Do normal return to instruction past
        !           352: #                              last procedure exit (distance passed
        !           353: #                              in by dummy routine and saved in _rsboff)
        !           354: #                    0         Take procedure exit 1
        !           355: #                    4         Take procedure exit 2
        !           356: #                    8         Take procedure exit 3
        !           357: #                   ...        ...
        !           358: #      
        !           359: ccaller:
        !           360: #
        !           361: #      (1) Save registers in global variables
        !           362: #
        !           363:        movl    r2,_reg_ra      # save RA (R2)
        !           364:        movl    r3,_reg_cp      # save CP (R3)
        !           365:        movl    r5,_reg_ia      # save IA (R5)
        !           366:        movl    r6,_reg_wa      # save WA (R6)
        !           367:        movl    r7,_reg_wb      # save WB (R7)
        !           368:        movl    r8,_reg_wc      # save WC (R8)
        !           369:        movl    r9,_reg_xr      # save XR (R9)
        !           370:        movl    r10,_reg_xl     # save XL (R10)
        !           371: #
        !           372: #      (2) Fetch address of C function, fetch offset to 1st instruction
        !           373: #          past last procedure exit, and call C function.
        !           374: #
        !           375:        movl    (sp)+,r0        # point to arg list
        !           376:        movl    (r0)+,r1        # point to C function entry point
        !           377:        movl    (r0),_rsboff    # get adjustment for normal exit
        !           378:        calls   $0,(r1)         # call C interface function
        !           379: #
        !           380: #      (3) Restore registers after C function returns.
        !           381: #
        !           382:        movl    _reg_ra,r2      # restore RA (R2)
        !           383:        movl    _reg_cp,r3      # restore CP (R3)
        !           384:        movl    _reg_ia,r5      # restore IA (R5)
        !           385:        movl    _reg_wa,r6      # restore WA (R6)
        !           386:        movl    _reg_wb,r7      # restore WB (R7)
        !           387:        movl    _reg_wc,r8      # restore WC (R8)
        !           388:        movl    _reg_xr,r9      # restore XR (R9)
        !           389:        movl    _reg_xl,r10     # restore XL (R10)
        !           390: #
        !           391: #      (4) Based on returned value from C function either do a normal
        !           392: #          return or take a procedure exit.
        !           393: #
        !           394:        tstl    r0              # if normal return ...
        !           395:        bgeq    erexit
        !           396:        addl2   _rsboff,(sp)    #   point to instruction following exits
        !           397:        rsb                     #   return
        !           398: #                              # else (take procedure exit n)
        !           399: erexit:        addl3   r0,(sp)+,r11    #   point to address of exit
        !           400:        jmp     *(r11)+         #   take procedure exit
        !           401: #
        !           402: #-----------
        !           403: #
        !           404: #      _get_sp - get C caller's SP
        !           405: #
        !           406: #      _get_sp() returns the current value of the stack pointer from
        !           407: #      the point of reference of a C function.
        !           408: #
        !           409: #      From C this procedure is called by
        !           410: #
        !           411: #              our_sp = get_sp();
        !           412: #
        !           413: #      The generated code will look like
        !           414: #
        !           415: #              calls   #0,_get_sp
        !           416: #              movl    r0,our_sp
        !           417: #
        !           418: #      On entry to _get_sp, the stack looks like
        !           419: #
        !           420: #              +---------------+  (<-- SP before 'calls' executed)
        !           421: #              |  arg cnt (0)  |
        !           422: #              |---------------|  <-- AP
        !           423: #              |    old PC     |
        !           424: #              |---------------|
        !           425: #              |    old FP     |
        !           426: #              |---------------|
        !           427: #              |    old AP     |
        !           428: #              |---------------|
        !           429: #              |   mask/PSW    |
        !           430: #              |---------------|
        !           431: #              |      0        |
        !           432: #              +---------------+  <-- SP  <-- FP
        !           433: #
        !           434: #      On exit, all these words will be removed from the stack.  Therefore,
        !           435: #      the current value of the SP from the caller's perspective is AP+4.
        !           436: #
        !           437:        .text
        !           438:        .globl  _get_sp
        !           439: _get_sp:
        !           440:        .word   0               # no registers to save
        !           441:        addl3   $4,ap,r0        # compute caller's SP
        !           442:        ret                     # done
        !           443: #
        !           444: #-----------
        !           445: #
        !           446: #      _startup - startup compiler
        !           447: #
        !           448: #      An OSINT C function calls _startup to transfer control
        !           449: #      to the compiler.
        !           450: #
        !           451:        .text
        !           452:        .globl  _startup
        !           453: _startup:
        !           454:        .word   0
        !           455:        movl    _reg_ra,r2      # initialize RA (R2)
        !           456:        movl    _reg_cp,r3      # initialize CP (R3)
        !           457:        movl    _reg_ia,r5      # initialize IA (R5)
        !           458:        movl    _reg_wa,r6      # initialize WA (R6)
        !           459:        movl    _reg_wb,r7      # initialize WB (R7)
        !           460:        movl    _reg_wc,r8      # initialize WC (R8)
        !           461:        movl    _reg_xr,r9      # initialize XR (R9)
        !           462:        movl    _reg_xl,r10     # initialize XL (R10)
        !           463: #
        !           464:        movl    sp,_initsp      # save initial sp
        !           465:        subl3   _stacksiz,sp,_lowsp
        !           466:                                # set lowest legal sp for sbchk
        !           467: #
        !           468:        movl    _dfltcase,kvcas # set case flag IN compiler
        !           469: #
        !           470:        jmp     sec04           # transfer control to compiler
        !           471: #
        !           472: #-----------
        !           473: #
        !           474: #      sbchk - check for stack overflow
        !           475: #
        !           476:        .text
        !           477:        .globl  sbchk
        !           478: sbchk: cmpl    sp,_lowsp       # if sp is ok then
        !           479:        blssu   sb100
        !           480:        rsb                     #    return
        !           481: sb100: tstl    (sp)+           # else pop stack
        !           482:        jmp     sec05           #    and go to stack overflow section

unix.superglobalmegacorp.com

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