Annotation of researchv10no/cmd/spitbol/cint/vaxinter.s, revision 1.1.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.