home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Exec 3 / CD_Magazyn_EXEC_nr_3.iso / Recent / misc / emu / evax11.lha / evax / kernel.asm < prev    next >
Assembly Source File  |  2000-01-28  |  55KB  |  1,320 lines

  1. ;
  2. ;       MicroKernel OS for VAX.
  3. ;
  4. ;       This is used to support development and testing of VAX programs.
  5. ;       It is not a full OS but provides minimal support for basic functions
  6. ;       like writing output to the console
  7. ;
  8. ;
  9. ;       SERVICES SUPPORTED
  10. ;
  11. ;       The microkernel supports a small (but growing!) list of basic VMS
  12. ;       services.  These include some kernel-mode operations such as
  13. ;       console I/O, some user-mode operations like str*() runtime library
  14. ;       support, and some "shim" operations that are supported by the 
  15. ;       emulator in lieu of a runtime library, such as the malloc() and
  16. ;       related routines.
  17. ;
  18. ;
  19. ;       HOW TO ADD A USER-MODE ROUTINE
  20. ;
  21. ;       User mode routines don't require special manipulation of the 
  22. ;       processor or use of privileged memory, instructions, etc.  There
  23. ;       is a section below for LIB$ and DECC$ support routines.  Simply
  24. ;       write the entry point as a normal assembler routine.
  25. ;
  26. ;       If you need the runtime to be available to a native VAX/VMS image
  27. ;       that you plan to run, add an entry in the _second_ section that
  28. ;       contains .SHIM declarations.  These declarations create bindings
  29. ;       that the image activator uses to link calls to sharable images to
  30. ;       your code instead.  Routines that are written as native VAX code
  31. ;       (such as DECC$STRCPY, for example) have a shim dispatch code of
  32. ;       zero.
  33. ;
  34. ;
  35. ;       HOW TO ADD A SHIM ROUTINE
  36. ;
  37. ;       A SHIM routine is one that is not written in native VAX code at
  38. ;       all.  Instead, a stub (shim) is created by the pseudo-assembler
  39. ;       that generates an appropriate XFC instruction.  This instruction
  40. ;       causes the emulator to read the native VAX argument list and
  41. ;       dispatch to a runtime support routine written in the emulator
  42. ;       itself.  An example of this is DECC$MALLOC(), which is implemented
  43. ;       by the routine decc_malloc() located in the file librtl_memory.c
  44. ;
  45. ;       You must write the shim routine itself (see any of the librtl*.c
  46. ;       files for how to read the argument list, access string descriptors
  47. ;       easily, etc.).  Add a prototype for the runtime in shim.h, and
  48. ;       an entry in the shim dispatch table in "shim.c".  Note that there
  49. ;       is a table entry for each routine, plus a second call that at runtime
  50. ;       fills in the function pointer value.  You must code both parts.
  51. ;
  52. ;       Finally, go to the _first_ section containing .SHIM declarations
  53. ;       below and add an entry for your routine.  The second parameter
  54. ;       must be the index into the shim table that contains your routine.
  55. ;
  56. ;
  57. ;       HOW TO ADD A NEW KERNEL-mode SERVICE
  58. ;
  59. ;       Services have two parts, the user mode part and the kernel mode
  60. ;       part.  The user mode part should validate that the arguments are
  61. ;       valid for user mode (to prevent calling with Kernel addresses,
  62. ;       for example) and otherwise check the arguments for correctness.
  63. ;       Note that for some services (lib$format_dec, for example) the
  64. ;       entire service runs in user mode and requires no system service.
  65. ;
  66. ;       When it's time to run the portion(s) of the service that must
  67. ;       run in kernel mode, write the routine as a function.  You must
  68. ;       assume that the user mode part will put it's arguments in 
  69. ;       registers for the call.  By convention, R5 is used for the
  70. ;       argument or the pointer to the arguments as appropriate.
  71. ;
  72. ;       The function should return any information it needs to via
  73. ;       the argument list by address, and a return code in R0.
  74. ;
  75. ;       Place the address of the kernel handler in the EXE$TABLE
  76. ;       below.  The position in the table must match the kernel mode
  77. ;       selector that invokes it.
  78. ;
  79.  
  80. ;       Indicate that we are building the microkernel.  This enables a number
  81. ;       of pseudo directives, etc. and tells the console it can use commands
  82. ;       like RUN that depend on the microkernel.
  83.  
  84.                 .microkernel
  85.  
  86. ;       Build the P1 system service vector to support VMS images
  87.  
  88.                 .p1vector
  89.                 
  90. ;
  91. ;       We must have the system return codes defined for us
  92.  
  93.                 .if defined( "SS$_NORMAL") = 0  .include       "ssdef.asm"
  94.  
  95. ;       Note that this can only be built if we are in kernel mode.  The
  96. ;       system initializes in kernel mode at IPL 31 to prevent interrupts,
  97. ;       etc. from occuring.  We assume this state for the system to work
  98. ;       correctly.
  99.  
  100.                 .region         system
  101. exe$base:       .byte 0
  102.  
  103.  
  104. ;--------------------------------------------------------------------
  105. ;   CONSOLE TRANSMIT INTERRUPT HANDLER
  106. ;--------------------------------------------------------------------
  107.  
  108.  
  109.                 .align          8
  110. exe$tx:         movl            #1, @#exe$tx_ready
  111.                 rei
  112.  
  113.  
  114. ;--------------------------------------------------------------------
  115. ;   CONSOLE RECIEVE INTERRUPT HANDLER
  116. ;--------------------------------------------------------------------
  117.  
  118.  
  119.                 .align          8
  120.                 
  121. exe$rx:         pushl           r0
  122.                 pushl           r1
  123.                 mfpr            #VAX$PR_RXDB, -(sp)
  124.                 calls           #1, @#EXE$RX_GET
  125.                 movl            (sp)+, r1
  126.                 movl            (sp)+, r0
  127.  
  128.                 rei
  129.  
  130.  
  131. ;--------------------------------------------------------------------
  132. ;   CHMK EXCEPTION HANDLER
  133. ;--------------------------------------------------------------------
  134.  
  135.                 .align          8
  136.  
  137. ;       Turn the exception into a call.  This lets us use registers
  138. ;       much more easily.  The #2 makes the stack a two-element arg
  139. ;       list.  When done with the call, we must discard the #1 and
  140. ;       the PSL, leaving just the PC for the REI.
  141.  
  142. exe$chmk:       movl            r0, @#exe$chmk_r0
  143.                 movl            r1, @#exe$chmk_r1
  144.                 pushl           ap          ; Save the AP at time of call
  145.                 pushl           #2
  146.                 callg           sp, @#exe$dispatch
  147.                 movl            @#exe$chmk_r1, r1
  148.                 moval           b^0x0C(sp), sp
  149.                 rei
  150.  
  151. ;--------------------------------------------------------------------
  152. ;   ACCVIO EXCEPTION HANDLER
  153. ;--------------------------------------------------------------------
  154.  
  155.                 .align          8
  156.  
  157. ;       Turn the exception into a call.  Add the signal value, and
  158. ;       account for the fault addr, mode, PC, and PSL arguments.
  159.  
  160. exe$accvio:     pushl           #SS$_ACCVIO
  161.                 pushl           #5
  162.                 callg           sp, @#exe$signal
  163.                 moval           b^10(sp), sp
  164.                 moval           @#exe$halt, (sp)
  165.                 rei
  166.  
  167. ;--------------------------------------------------------------------
  168. ;   RESERVED OPCODE EXCEPTION HANDLER
  169. ;--------------------------------------------------------------------
  170.  
  171.                 .align          8
  172.  
  173. ;       Turn the exception into a call.  Add the signal value, and
  174. ;       account for the PC, and PSL arguments.
  175.  
  176. exe$resop:      pushl           #SS$_ROPRAND
  177.                 pushl           #3
  178.                 callg           sp, @#exe$signal
  179.                 moval           b^0C(sp), sp
  180.                 moval           @#exe$halt, (sp)
  181.                 rei
  182.  
  183. ;--------------------------------------------------------------------
  184. ;   PRIVILEGED INSTRUCTION EXCEPTION HANDLER
  185. ;--------------------------------------------------------------------
  186.  
  187.                 .align          8
  188.  
  189. ;       Turn the exception into a call.  Add the signal value, and
  190. ;       account for the PC, and PSL arguments.
  191.  
  192. exe$priv:       pushl           #SS$_NOPRIV
  193.                 pushl           #3
  194.                 callg           sp, @#exe$signal
  195.                 moval           b^0C(sp), sp
  196.                 moval           @#exe$halt, (sp)
  197.                 rei
  198.  
  199. ;--------------------------------------------------------------------
  200. ;   SOFTWARE INTERRUPT 2 (AST HANDLER)
  201. ;--------------------------------------------------------------------
  202.  
  203.                 .align          8
  204.  
  205. exe$deliver_ast:nop
  206.  
  207. _next:          remque          @#exe$ast_list, r0
  208.                 bvs             _done
  209.                 pushl           r0
  210.                 pushl           r1
  211.                 pushl           r0
  212.                 calls           #1, @#exe$handle_ast
  213.                 blbc            r0, _err
  214.                 movl            (sp)+, r1
  215.                 movl            (sp)+, r0
  216.                 brb             _next
  217.  
  218. ;   Handle errors in ast services if needed, and then pop R1 and R0
  219. ;   before getting out.
  220.  
  221. _err:           movl            -(sp), r1
  222.                 movl            -(sp), r0
  223.  
  224. _done:          rei
  225.  
  226. ;--------------------------------------------------------------------
  227. ;   RESERVED ADDRESSING MODE EXCEPTION HANDLER
  228. ;--------------------------------------------------------------------
  229.  
  230.                 .align          8
  231.  
  232. ;       Turn the exception into a call.  Add the signal value, and
  233. ;       account for the  PC, and PSL arguments.
  234.  
  235. exe$resaddr:    pushl           #SS$_RADRMOD
  236.                 pushl           #3
  237.                 callg           sp, @#exe$signal
  238.                 moval           b^0C(sp), sp
  239.                 moval           @#exe$halt, (sp)
  240.                 rei
  241.  
  242. ;--------------------------------------------------------------------
  243. ;   EXCEPTIONS LAND HERE AFTER FINISHING HANDLER
  244. ;--------------------------------------------------------------------
  245.  
  246.  
  247. exe$halt:       xfc             #xfc$halt_silent    ; no fault halt
  248.                 halt            ; if you push it, it blows
  249.  
  250. ;--------------------------------------------------------------------
  251. ;   INTERVAL TIMER HANDLER
  252. ;--------------------------------------------------------------------
  253.  
  254.                 .align          8
  255. exe$interval:   incl            @#exe$int_count
  256.                 mtpr            #0FF, #VAX$PR_ICCS
  257.                 rei
  258.  
  259. ;--------------------------------------------------------------------
  260. ;   GENERAL SIGNAL HANDLER
  261. ;--------------------------------------------------------------------
  262.  
  263. ;       This is called when a hardware or software exception occurs.
  264. ;       At the time of the call, a varying number of arguments are
  265. ;       on the stack.  The last two are always the PC and PSL where
  266. ;       the fault occurred.  The first is always the exception.  Any
  267. ;       in between make up the signal vector.
  268.  
  269.                 .entry          exe$signal, ^m<r2,r3, r4>
  270.  
  271.                 pushal          @#_sigmsg
  272.                 calls           #1, @#lib$put_output
  273.  
  274.                 movl            (ap), r2
  275.                 movl            #1,r4
  276.                 
  277. _sigloop:       tstl            r2
  278.                 blss            _done
  279.                 movl            #8, @#exe$sig_buff_len
  280.                 pushl           (ap)+
  281.                 pushl           r4
  282.                 incl            r4
  283.                 pushal          _sigfmt
  284.                 calls           #3,decc$printf
  285.                 
  286.                 decl            r2
  287.                 brb             _sigloop
  288.                 
  289. _done:          ret
  290.  
  291. _sigmsg:        .ascid          "The microkernel has trapped an error.  Signal vector:"
  292. _sigfmt:        .asciz          "  %ld   %08lX\n"
  293.        
  294. ;--------------------------------------------------------------------
  295. ;   CHMK SELECTOR DISPATCHER
  296. ;--------------------------------------------------------------------
  297.  
  298. ;       Here's the real dispatcher.  It validates the kernel selector
  299. ;       value, and if it's okay, generates a call to an address stored
  300. ;       in the exe$table array.  The first argument is the real AP for
  301. ;       the call, and the second argument is the dispatcher code.
  302.  
  303.                 .entry          exe$dispatch, ^m<r2,r3>
  304.                 movl            b^8(ap), r2
  305.                 movl            b^4(ap), ap
  306.                 tstl            r2
  307.                 bgeq            _10
  308.                 movl            #SS$_INVARG, r0
  309.                 brb             exe$exit
  310. _10:            cmpl            r2, @#exe$table_len
  311.                 blss            _20
  312.                 movl            #SS$_INVARG, r0
  313.                 brb             exe$exit
  314. _20:            moval           @#exe$table, r3
  315.                 movl            (r3)[r2], r0
  316.                 
  317.                 callg           ap, (r0)
  318.  
  319. exe$exit:       ret
  320.  
  321. ;--------------------------------------------------------------------
  322. ;   CHMK 0    WRITE BYTE TO CONSOLE
  323. ;--------------------------------------------------------------------
  324.  
  325.                 .set            EXE$PUT_CONSOLE 0
  326.                 .entry          exe$$put_console
  327.  
  328. ;       First, see if the device is ready or not.  This is set
  329. ;       by the ready interrupt service routine when a byte is
  330. ;       successsfully written.
  331.  
  332.  
  333. _wait:          tstl            @#exe$tx_ready
  334.                 beql            _wait
  335.  
  336. ;       Mark the device as busy, and write a byte to it.
  337.  
  338.                 clrl            @#exe$tx_ready                              
  339.                 mtpr            r5, #VAX$PR_TXDB
  340.                 
  341.                 movl            #SS$_NORMAL, r0
  342.                 ret
  343.  
  344. ;--------------------------------------------------------------------
  345. ;   CHMK 1    READ BYTE FROM CONSOLE
  346. ;--------------------------------------------------------------------
  347.  
  348.                 .set            EXE$GET_CONSOLE 2
  349.                 .entry          exe$$get_console
  350.                 
  351.                 mfpr            #VAX$PR_RXDB, r0
  352.                 ret
  353.  
  354. ;--------------------------------------------------------------------
  355. ;   CHMK 3    READ BUFFER FROM FILE
  356. ;--------------------------------------------------------------------
  357.  
  358. ;       AP points to a legitimate argument block.
  359. ;
  360. ;           4(AP)   file id  (ignored for now, assume console)
  361. ;           8(AP)   address of buffer to write
  362. ;           12(AP)  length of buffer to write
  363. ;
  364.  
  365.                 .set            EXE$GET_FILE 3
  366.                 .entry          exe$$get_file, ^m<r2>
  367.  
  368.                 moval           b^0f0(sp),sp        ; Make automatic storage
  369.                 
  370.                 movl            b^08(ap),b^0FC(fp)  ; addr part of descriptor   
  371.                 movl            b^0c(ap),b^0F8(fp)  ; len  part of descriptor
  372.                 clrl            B^0f4(fp)           ; space to write length
  373.  
  374.                 pushal          b^0f4(fp)           ; addr of length 
  375.                 pushl           #0                  ; no prompt
  376.                 pushal          b^0f8(fp)           ; addr of descriptor
  377.                 
  378.                 calls           #3, @#LIB$GET_INPUT
  379.                 
  380.                 movl            b^0f4(fp), r0       ; Get length
  381.                 movl            b^08(ap), r2        ; Get buffer addr
  382.                 clrb            (r2)[r0]            ; Null terminate it
  383.                 
  384.                 ret                                 ; And return length in R0
  385.  
  386. ;--------------------------------------------------------------------
  387. ;   CHMK 4    WRITE BUFFER TO FILE
  388. ;--------------------------------------------------------------------
  389.  
  390. ;       AP points to a legitimate argument block.
  391. ;
  392. ;           4(AP)   file id  (ignored for now, assume console)
  393. ;           8(AP)   address of buffer to write
  394. ;           12(AP)  length of buffer to write
  395. ;
  396.  
  397.                 .set            EXE$PUT_FILE 4
  398.                 .entry          exe$$put_file
  399.             
  400.                 pushl           b^08(ap)        ; addr part of descriptor   
  401.                 pushl           b^0c(AP)        ; len  part of descriptor
  402.             
  403.                 pushl           sp              ; Make addr of descriptor on stack
  404.                 calls           #1, @#lib$put_one
  405.                 ret
  406.                 
  407.  
  408. ;--------------------------------------------------------------------
  409. ;   CHMK SELECTOR FUNCTION DISPATCH TABLE
  410. ;--------------------------------------------------------------------
  411.  
  412. ;       This is the dispatch table.  There must be a entry point
  413. ;       address in each slot that is in the table.
  414.  
  415. exe$table:      .long           exe$$put_console    ; CHMK 0
  416.                 .long           exe$halt            ; CHMK 1 - Halt emulation
  417.                 .long           exe$$get_console    ; CHMK 2
  418.                 .long           decc$read           ; CHMK 3 - direct to SHIM
  419.                 .long           decc$write          ; CHMK 4 - direct to SHIM
  420.                 .long           decc$open           ; CHMK 5 - direct to SHIM
  421.                 .long           decc$close          ; CHMK 6 - direct to SHIM
  422.                 
  423.  
  424. ;       Store the length in longwords of the table
  425.  
  426. exe$table_len:  .long         ( . - exe$table ) / 4
  427.  
  428.  
  429. ;--------------------------------------------------------------------
  430. ;   AST HANDLER
  431. ;--------------------------------------------------------------------
  432.  
  433. ;       This is called by the AST interrupt handler to process an
  434. ;       item that had been queued up for AST delivery.  The single
  435. ;       parameter is the AST control block.  The first two longwords
  436. ;       are undefined (part of the AST queue block).  The remaining
  437. ;       data after the linkages are where the AST data resides.
  438.  
  439.                 .entry          exe$handle_ast
  440.  
  441.                 ret
  442.  
  443. ;--------------------------------------------------------------------
  444. ;   CONSOLE READ A BYTE
  445. ;--------------------------------------------------------------------
  446.  
  447. ;       This is called by the CONREAD interrupt handler to process a
  448. ;       single byte of data, passed as the parameter to this routine.
  449. ;       We file this away in the console read buffer.
  450.  
  451.                 .entry          exe$rx_get
  452.                 
  453.                 cmpl            #100,@#exe$rxlen
  454.                 beql            _done
  455.     
  456.                 incl            @#exe$rxlen
  457.                 
  458.                 movl            @#exe$rxptr, r0
  459.                 movb            b^4(ap),(r0)+
  460.                 movl            r0,@#exe$rxptr  
  461.                         
  462. _done:          ret
  463.                 
  464. ;--------------------------------------------------------------------
  465. ;   KERNEL INITIALIZATION
  466. ;--------------------------------------------------------------------
  467.  
  468. ;       This is called by the vax.init file after the kernel is built.
  469. ;       This completes the runtime initialization of the system.  Put
  470. ;       things here that you want to have built by the VAX as opposed
  471. ;       to the assembler.  You must GO this code, not CALL it because
  472. ;       the console CALL code will screw up the registers on the RET
  473. ;       instruction.
  474.  
  475.  
  476. exe$initialize: tstl            @#exe$init_done ; If we've already done
  477.                 bneq            exe$init_exit   ; this, just return
  478.  
  479. ;       Set the bit in the TXCS register that says to interrupt
  480. ;       us when the data is successfully written.  This will cause
  481. ;       the EXE$TX interrupt handler to be hit again, which resets 
  482. ;       our internal ready flag at exe$tx_ready.
  483.  
  484.                 mtpr            #40,#VAX$PR_TXCS
  485.  
  486. ;       Similarly, let's indicate that we accept interrupts for the
  487. ;       console input.
  488.  
  489.                 mtpr            #40,#VAX$PR_RXCS
  490.                 
  491.  
  492. ;       We want an interval timer interrupt every 500 instructions
  493. ;       or so.  Currently the ICR is based on instructions, not real
  494. ;       time (this is a must-fix for later).
  495.  
  496.                 mcoml           #^d500, r0
  497.                 mtpr            r0, #VAX$PR_NICR
  498.  
  499. ;       Now that NICR is set up, turn on interrupts, and reload the
  500. ;       ICR from the NICR.
  501.  
  502.                 mtpr            #0ff,#VAX$PR_ICCS
  503.                 
  504. ;       Mark the flag that says we're done
  505.  
  506.                 movl            #1, @#exe$init_done
  507.  
  508. ;       We've got to get out of kernel mode.  To do this at runtime,
  509. ;       we fake out a REI instruction.  Push the desired PSL and PC
  510. ;       on the stack and do an REI.  This will take us to the exit
  511. ;       point, in user mode with IPL of zero (so interrupts will
  512. ;       start happening).
  513.  
  514.                 pushl           #03000000       ; desired PSL
  515.                 pushal          @#exe$init_exit ; desired PC
  516.                 rei                             ; do it
  517.  
  518. ;       This is the exit point from the initialization routine.
  519.  
  520. exe$init_exit:  pushl           #0a
  521.                 pushl           #0d
  522.                 pushal          @#exe$init_msg
  523.                 calls           #3, @#LIB$PUT_OUTPUT
  524.                 halt
  525.  
  526. ;       Let's protect the dispatcher so that you can't even read/see it
  527. ;       unless you are in kernel mode.  This keeps prying eyes out of 
  528. ;       the system.  But, we can't do it yet because doing so would prevent
  529. ;       forward references to fix up in the assembler.  So, save where we 
  530. ;       are and use it later.
  531.  
  532.                 .set            exe$end .
  533.  
  534.  
  535. ;       Because of that, we need to be sure to start on a new boundary.
  536.  
  537.                 .align          0200
  538.                 .set            exe$ubase .
  539.  
  540. ;--------------------------------------------------------------------
  541. ;   USER MODE FRONT-END TO SYSTEM SERVICES
  542. ;--------------------------------------------------------------------
  543.  
  544. ;
  545. ;       Write a list of items, passed as parameters via standard calling
  546. ;       conventions.  Each item is passed to lib$put_output() as a single
  547. ;       item for output.
  548. ;
  549.  
  550.                 .entry          lib$put_output, ^m<r3,r4>
  551.                 movl            (ap), r3                ; Count of arguments
  552.                 tstl            r3                      ; Are there any?
  553.                 beql            _exit                   ; No, we're done
  554.                 addl3           #4, ap, r4              ; Yes, find first one
  555.  
  556. _loop:          pushl           (r4)+                   ; push the parameter
  557.                 calls           #1, @#lib$put_one       ; call output
  558.                 sobgtr          r3, _loop               ; loop if more
  559.                 
  560.                 pushl           #0a                     ; else end with LF
  561.                 calls           #1, @#lib$put_one
  562.                 
  563.                 pushl           #0d                     ; and CR
  564.                 calls           #1, @#lib$put_one
  565.                 
  566.                 movl            #1, r0                  ; now done
  567.                 ret
  568.  
  569. _exit:          movl            #1, r0
  570.                 ret
  571.  
  572. ;               LIB$PUT_ONE( struct dsc$descriptor_s * msg );
  573.  
  574.                 .entry          lib$put_one, ^m<r2,r3,r4,r5,r6>
  575.  
  576.                 movl            b^4(ap), r5          ; Get descriptor address
  577.  
  578.                 cmpl            r5, #0ff             ; see if it's one char.
  579.                 blequ           _byte                ; if so, print it
  580.  
  581.                 clrl            r6                   ; Empty counter register
  582.                 movw            (r5), r6             ; Get count word from desc
  583.                 beql            _exit                ; If zero, then no work
  584.                 movl            b^4(r5), r2          ; Else get address
  585.                 clrl            r4                   ; Clear data register
  586.  
  587. _loop:          movb            (r2)+, r5            ; Get byte, advance ptr
  588.                 chmk            #EXE$PUT_CONSOLE     ; Output single byte
  589.                 blbc            r0, _errexit         ; If bad RC, done
  590.                 sobgtr          r6, _loop            ; Decrement counter, rpt
  591.                 brb             _exit
  592.  
  593. _byte:          chmk            #EXE$PUT_CONSOLE     ; Output single byte in R5
  594.                 blbc            r0, _errexit         ; If bad RC, done
  595.  
  596. _exit:          movl            #SS$_NORMAL, r0      ; Signal success
  597. _errexit:       ret                                  ; And flee
  598.  
  599.  
  600. ;               rc = LIB$GET_INPUT( DESCRIPTOR * buff [, DESCRIPTOR * prompt [, short * len ]]);
  601.  
  602.                 .entry  lib$get_input, ^m<r2,r3,r4>
  603.                 
  604.                 movl            b^4(ap),    r2      ; Address of descriptor
  605.                 movl            b^8(ap),    r3      ; Address of prompt
  606.                 tstl            r3
  607.                 beql            _get                ; If no prompt, skip it
  608.                 pushl           r3
  609.                 calls           #1, lib$put_one     ; Else put out prompt
  610.                 
  611. _get:           cvtwl           (r2),r4             ; Get length
  612.                 pushl           r4                  ; push length of buffer
  613.                 pushl           b^4(r2)             ; push address of buffer
  614.                 calls           #2,exe$input        ; Get input from user
  615.                 movl            b^0c(ap),   r3      ; Get address of length
  616.                 tstl            r3
  617.                 beql            _done
  618.                 cvtlw           r0, (r3)            ; Write length to caller
  619.  
  620. _done:          movl            #SS$_NORMAL, r0
  621.                 ret
  622.                 
  623.  
  624. ;               len = LIB$FORMAT_DEC( long value, char * buffer, long *size );
  625.  
  626.                 .entry  lib$format_dec, ^m<r2,r3,r4,r5,r6,r7,r8, r9>
  627.  
  628. ;
  629. ;   We're going to allocate some stack space.  So move the SP down to
  630. ;   prepare room for it.
  631.  
  632.                 subl2   #4,sp
  633.  
  634.                 movl    b^0C(ap), r9            ; Get length pointer
  635.  
  636.                 movl    b^4(ap), r2             ; Get the value to format
  637.                 tstl    r2                      ; Is it zero?
  638.  
  639.                 beql    _zero                   ; If so, special case
  640.  
  641. ;
  642. ;   Allocate some "automatic storage" on the stack by marking where we
  643. ;   are (since we want the end of the buffer anyway) and move the SP
  644. ;   down in case we need it for something else.
  645. ;
  646.  
  647.                 movl    sp,r6                   ; Point to end of space
  648.                 subl2   r9, sp                  ; and move end of stack down
  649.                                                 ; by size of user's buffer
  650.  
  651.                 clrl    r7                      ; init the counter
  652.  
  653. _loop:          divl3   #^d10, r2, r3           ; Shift off digit
  654.                 mull3   r3, #^d10, r4           ; And back again
  655.                 subl3   r4, r2, r5              ; Difference is digit
  656.                 addl2   #30, r5                 ; Make ASCII
  657.  
  658.                 movb    r5, -(r6)               ; copy to buffer, decrement
  659.                 incl    r7                      ; and increment counter
  660.                 cmpl    r7, (r9)                ; too big?
  661.                 bgtr    _oflow                  ; yes, bail out
  662.  
  663.                 tstl   r4                       ; Is there more?
  664.                 beql   _exit                    ; No, done
  665.  
  666.                 movl   r3, r2                   ; Yes, set it up
  667.                 brb    _loop                    ; And loop again
  668.  
  669. _oflow:         movl   #SS$_BUFFEROVF, r0       ; Return overflow
  670.                 ret
  671.  
  672. _zero:          movl   sp, r6                   ; Get address of stack buffer
  673.                 movb   #30, (r6)                ; Write "0" to buffer
  674.                 movl   #1, r7                   ; return length of 1
  675.  
  676. _exit:          movl   b^8(ap), r8              ; Get address of buffer
  677.                 movc3  r7, (r6), (r8)           ; Copy to user's buffer
  678.                 movl   b^0c(ap),r8
  679.                 movl   r7, (r8)                 ; and return the length
  680.                 movl   #SS$_NORMAL, r0          ; signal success
  681.                 ret                             ; Go home.
  682.  
  683.  
  684. ;               len = LIB$FORMAT_HEX( long value, char * buffer, long *size );
  685.  
  686.                 .entry  lib$format_hex, ^m<r2,r3,r4,r5,r6,r7,r8, r9>
  687.  
  688. ;
  689. ;   We're going to allocate some stack space.  So move the SP down to
  690. ;   prepare room for it.
  691.  
  692.                 subl2   #4,sp
  693.                 moval   @#lib$hex_table, r8     ; get address of table
  694.                 
  695.                 movl    b^0C(ap), r9            ; Get length pointer
  696.  
  697.                 movl    b^4(ap), r2             ; Get the value to format
  698.                 tstl    r2                      ; Is it zero?
  699.  
  700.                 beql    _zero                   ; If so, special case
  701.  
  702. ;
  703. ;   Allocate some "automatic storage" on the stack by marking where we
  704. ;   are (since we want the end of the buffer anyway) and move the SP
  705. ;   down in case we need it for something else.
  706. ;
  707.  
  708.                 movl    sp,r6                   ; Point to end of space
  709.                 subl2   (r9), sp                ; and move end of stack down
  710.                                                 ; by size of user's buffer
  711.  
  712.                 clrl    r7                      ; init the counter
  713.  
  714. _loop:          divl3   #^d16, r2, r3           ; Shift off digit
  715.                 mull3   r3, #^d16, r4           ; And back again
  716.                 subl3   r4, r2, r5              ; Difference is digit
  717.                 
  718.                 movb    (r8)[r5],-(r6)          ; Look up in table to make HEX,
  719.                                                 ;   copy to buffer, decrement
  720.                                                 
  721.                 incl    r7                      ; and increment counter
  722.                 cmpl    r7, (r9)                ; too big?
  723.                 bgtr    _oflow                  ; yes, bail out
  724.  
  725.                 tstl   r4                       ; Is there more?
  726.                 beql   _exit                    ; No, done
  727.  
  728.                 movl   r3, r2                   ; Yes, set it up
  729.                 brb    _loop                    ; And loop again
  730.  
  731. _oflow:         movl   #SS$_BUFFEROVF, r0       ; Return overflow
  732.                 ret
  733.  
  734. _zero:          movl   sp, r6                   ; Get address of stack buffer
  735.                 movb   #30, (r6)                ; Write "0" to buffer
  736.                 movl   #1, r7                   ; return length of 1
  737.  
  738. _exit:          movl   b^8(ap), r8              ; Get address of buffer
  739.                 movc3  r7, (r6), (r8)           ; Copy to user's buffer
  740.                 movl   b^0c(ap),r8
  741.                 movl   r7, (r8)                 ; and return the length
  742.                 movl   #SS$_NORMAL, r0          ; signal success
  743.                 ret                             ; Go home.
  744.  
  745.  
  746. ;--------------------------------------------------------------------
  747. ;   DECC$SHR runtime support
  748. ;--------------------------------------------------------------------
  749.  
  750. ;   *** Note that the MAIN entry initialization is via JSB not CALL
  751.  
  752. decc$main:      nop             ; Currently, no work done.
  753.                 rsb
  754.  
  755.                 .entry          decc$exit
  756.                 nop
  757.                 ret
  758.  
  759.                 .entry  cma$tis_errno_get_addr, ^m<>
  760.                 moval   @#vaxc$errno, r0
  761.                 ret
  762.  
  763.                 .entry  decc$calloc, ^m<r2,r3>
  764.  
  765.                 mull3   b^4(ap),b^8(ap), r3 ; How much storage?
  766.                 pushl   r3
  767.                 calls   #1, @#decc$malloc   ; Get the storage
  768.  
  769.                 tstl    r0                  ; If no memory, done
  770.                 beql    _done
  771.                 movl    r0,r2
  772.  
  773. _zero:          clrb    (r2)+               ; Clear byte
  774.                 sobgtr  r3, _zero           ; for as many bytes as needed
  775.  
  776. _done:          ret                         ; Done
  777.  
  778.  
  779.                 .entry  decc$strcat, ^m<r2>
  780.  
  781.                 pushl   b^4(ap)             ; Find length of dst
  782.                 calls   #1, @#decc$strlen
  783.                 addl3   b^4(ap), r0, r2     ; Add to addr of dst
  784.                 pushl   b^8(ap)             ; push src
  785.                 pushl   r2                  ; and dst   
  786.                 calls   #2, @#decc$strcpy   ; and copy there
  787.                 addl2   r2,r0               ; return total length
  788.                 ret
  789.  
  790.                 .entry  decc$strcpy, ^m<r2,r3>
  791.                 movl    b^4(ap), r2
  792.                 movl    b^8(ap), r3
  793.                 clrl    r0
  794.                 
  795. _loop:          movb    (r3),(r2)
  796.                 tstb    (r2)
  797.                 beql    _done
  798.                 incl    r0
  799.                 incl    r2
  800.                 incl    r3
  801.                 brb     _loop
  802. _done:          ret
  803.  
  804.                 .entry  decc$strlen, ^m<r2>
  805.                 movl    b^4(ap), r2
  806.                 clrl    r0
  807. _loop:          tstb    (r2)
  808.                 beql    _done
  809.                 incl    r0
  810.                 incl    r2
  811.                 brb     _loop
  812. _done:          ret
  813.  
  814.  
  815. ;   Table to support inline "ctype" operations like isupper, etc.  This will be
  816. ;   used at runtime if the ctypea flag indicates the table is available.
  817.  
  818. decc$$gl___ctypea:    
  819.  
  820.                 .long    1             ; CTYPE table is available.  If set to zero,
  821.                                        ; then the storage for the table can be
  822.                                        ; reclaimed for some other purpose.
  823.  
  824. decc$$ga___ctypet:
  825.                 long     ctype_table   ; Address of the type table found here
  826.  
  827.                  ; Actual table starts here
  828.  
  829. ctype_table:    .long    ^X00000020  ;  00
  830.                 .long    ^X00000020  ;  01
  831.                 .long    ^X00000020  ;  02
  832.                 .long    ^X00000020  ;  03
  833.                 .long    ^X00000020  ;  04
  834.                 .long    ^X00000020  ;  05
  835.                 .long    ^X00000020  ;  06
  836.                 .long    ^X00000020  ;  07
  837.                 .long    ^X00000020  ;  08
  838.                 .long    ^X00000428  ;  09
  839.                 .long    ^X00000028  ;  0A
  840.                 .long    ^X00000028  ;  0B
  841.                 .long    ^X00000028  ;  0C
  842.                 .long    ^X00000028  ;  0D
  843.                 .long    ^X00000020  ;  0E
  844.                 .long    ^X00000020  ;  0F
  845.                 .long    ^X00000020  ;  10
  846.                 .long    ^X00000020  ;  11
  847.                 .long    ^X00000020  ;  12
  848.                 .long    ^X00000020  ;  13
  849.                 .long    ^X00000020  ;  14
  850.                 .long    ^X00000020  ;  15
  851.                 .long    ^X00000020  ;  16
  852.                 .long    ^X00000020  ;  17
  853.                 .long    ^X00000020  ;  18
  854.                 .long    ^X00000020  ;  19
  855.                 .long    ^X00000020  ;  1A
  856.                 .long    ^X00000020  ;  1B
  857.                 .long    ^X00000020  ;  1C
  858.                 .long    ^X00000020  ;  1D
  859.                 .long    ^X00000020  ;  1E
  860.                 .long    ^X00000020  ;  1F
  861.                 .long    ^X00000488  ;  20
  862.                 .long    ^X00000290  ;  21
  863.                 .long    ^X00000290  ;  22
  864.                 .long    ^X00000290  ;  23
  865.                 .long    ^X00000290  ;  24
  866.                 .long    ^X00000290  ;  25
  867.                 .long    ^X00000290  ;  26
  868.                 .long    ^X00000290  ;  27
  869.                 .long    ^X00000290  ;  28
  870.                 .long    ^X00000290  ;  29
  871.                 .long    ^X00000290  ;  2A
  872.                 .long    ^X00000290  ;  2B
  873.                 .long    ^X00000290  ;  2C
  874.                 .long    ^X00000290  ;  2D
  875.                 .long    ^X00000290  ;  2E
  876.                 .long    ^X00000290  ;  2F
  877.                 .long    ^X000002C4  ;  30
  878.                 .long    ^X000002C4  ;  31
  879.                 .long    ^X000002C4  ;  32
  880.                 .long    ^X000002C4  ;  33
  881.                 .long    ^X000002C4  ;  34
  882.                 .long    ^X000002C4  ;  35
  883.                 .long    ^X000002C4  ;  36
  884.                 .long    ^X000002C4  ;  37
  885.                 .long    ^X000002C4  ;  38
  886.                 .long    ^X000002C4  ;  39
  887.                 .long    ^X00000290  ;  3A
  888.                 .long    ^X00000290  ;  3B
  889.                 .long    ^X00000290  ;  3C
  890.                 .long    ^X00000290  ;  3D
  891.                 .long    ^X00000290  ;  3E
  892.                 .long    ^X00000290  ;  3F
  893.                 .long    ^X00000290  ;  40
  894.                 .long    ^X000003C1  ;  41
  895.                 .long    ^X000003C1  ;  42
  896.                 .long    ^X000003C1  ;  43
  897.                 .long    ^X000003C1  ;  44
  898.                 .long    ^X000003C1  ;  45
  899.                 .long    ^X000003C1  ;  46
  900.                 .long    ^X00000381  ;  47
  901.                 .long    ^X00000381  ;  48
  902.                 .long    ^X00000381  ;  49
  903.                 .long    ^X00000381  ;  4A
  904.                 .long    ^X00000381  ;  4B
  905.                 .long    ^X00000381  ;  4C
  906.                 .long    ^X00000381  ;  4D
  907.                 .long    ^X00000381  ;  4E
  908.                 .long    ^X00000381  ;  4F
  909.                 .long    ^X00000381  ;  50
  910.                 .long    ^X00000381  ;  51
  911.                 .long    ^X00000381  ;  52
  912.                 .long    ^X00000381  ;  53
  913.                 .long    ^X00000381  ;  54
  914.                 .long    ^X00000381  ;  55
  915.                 .long    ^X00000381  ;  56
  916.                 .long    ^X00000381  ;  57
  917.                 .long    ^X00000381  ;  58
  918.                 .long    ^X00000381  ;  59
  919.                 .long    ^X00000381  ;  5A
  920.                 .long    ^X00000290  ;  5B
  921.                 .long    ^X00000290  ;  5C
  922.                 .long    ^X00000290  ;  5D
  923.                 .long    ^X00000290  ;  5E
  924.                 .long    ^X00000290  ;  5F
  925.                 .long    ^X00000290  ;  60
  926.                 .long    ^X000003C2  ;  61
  927.                 .long    ^X000003C2  ;  62
  928.                 .long    ^X000003C2  ;  63
  929.                 .long    ^X000003C2  ;  64
  930.                 .long    ^X000003C2  ;  65
  931.                 .long    ^X000003C2  ;  66
  932.                 .long    ^X00000382  ;  67
  933.                 .long    ^X00000382  ;  68
  934.                 .long    ^X00000382  ;  69
  935.                 .long    ^X00000382  ;  6A
  936.                 .long    ^X00000382  ;  6B
  937.                 .long    ^X00000382  ;  6C
  938.                 .long    ^X00000382  ;  6D
  939.                 .long    ^X00000382  ;  6E
  940.                 .long    ^X00000382  ;  6F
  941.                 .long    ^X00000382  ;  70
  942.                 .long    ^X00000382  ;  71
  943.                 .long    ^X00000382  ;  72
  944.                 .long    ^X00000382  ;  73
  945.                 .long    ^X00000382  ;  74
  946.                 .long    ^X00000382  ;  75
  947.                 .long    ^X00000382  ;  76
  948.                 .long    ^X00000382  ;  77
  949.                 .long    ^X00000382  ;  78
  950.                 .long    ^X00000382  ;  79
  951.                 .long    ^X00000382  ;  7A
  952.                 .long    ^X00000290  ;  7B
  953.                 .long    ^X00000290  ;  7C
  954.                 .long    ^X00000290  ;  7D
  955.                 .long    ^X00000290  ;  7E
  956.                 .long    ^X00000020  ;  7F
  957.                 .long    ^X00000000  ;  80
  958.                 .long    ^X00000000  ;  81
  959.                 .long    ^X00000000  ;  82
  960.                 .long    ^X00000000  ;  83
  961.                 .long    ^X00000020  ;  84
  962.                 .long    ^X00000020  ;  85
  963.                 .long    ^X00000020  ;  86
  964.                 .long    ^X00000020  ;  87
  965.                 .long    ^X00000020  ;  88
  966.                 .long    ^X00000020  ;  89
  967.                 .long    ^X00000020  ;  8A
  968.                 .long    ^X00000020  ;  8B
  969.                 .long    ^X00000020  ;  8C
  970.                 .long    ^X00000020  ;  8D
  971.                 .long    ^X00000020  ;  8E
  972.                 .long    ^X00000020  ;  8F
  973.                 .long    ^X00000020  ;  90
  974.                 .long    ^X00000020  ;  91
  975.                 .long    ^X00000020  ;  92
  976.                 .long    ^X00000020  ;  93
  977.                 .long    ^X00000020  ;  94
  978.                 .long    ^X00000020  ;  95
  979.                 .long    ^X00000020  ;  96
  980.                 .long    ^X00000020  ;  97
  981.                 .long    ^X00000000  ;  98
  982.                 .long    ^X00000000  ;  99
  983.                 .long    ^X00000000  ;  9A
  984.                 .long    ^X00000020  ;  9B
  985.                 .long    ^X00000020  ;  9C
  986.                 .long    ^X00000020  ;  9D
  987.                 .long    ^X00000020  ;  9E
  988.                 .long    ^X00000020  ;  9F
  989.                 .long    ^X00000000  ;  A0
  990.                 .long    ^X00000290  ;  A1
  991.                 .long    ^X00000290  ;  A2
  992.                 .long    ^X00000290  ;  A3
  993.                 .long    ^X00000000  ;  A4
  994.                 .long    ^X00000290  ;  A5
  995.                 .long    ^X00000000  ;  A6
  996.                 .long    ^X00000290  ;  A7
  997.                 .long    ^X00000290  ;  A8
  998.                 .long    ^X00000290  ;  A9
  999.                 .long    ^X00000290  ;  AA
  1000.                 .long    ^X00000290  ;  AB
  1001.                 .long    ^X00000000  ;  AC
  1002.                 .long    ^X00000000  ;  AD
  1003.                 .long    ^X00000000  ;  AE
  1004.                 .long    ^X00000000  ;  AF
  1005.                 .long    ^X00000290  ;  B0
  1006.                 .long    ^X00000290  ;  B1
  1007.                 .long    ^X00000290  ;  B2
  1008.                 .long    ^X00000290  ;  B3
  1009.                 .long    ^X00000000  ;  B4
  1010.                 .long    ^X00000290  ;  B5
  1011.                 .long    ^X00000290  ;  B6
  1012.                 .long    ^X00000290  ;  B7
  1013.                 .long    ^X00000000  ;  B8
  1014.                 .long    ^X00000290  ;  B9
  1015.                 .long    ^X00000290  ;  BA
  1016.                 .long    ^X00000290  ;  BB
  1017.                 .long    ^X00000290  ;  BC
  1018.                 .long    ^X00000290  ;  BD
  1019.                 .long    ^X00000000  ;  BE
  1020.                 .long    ^X00000290  ;  BF
  1021.                 .long    ^X00000290  ;  C0
  1022.                 .long    ^X00000290  ;  C1
  1023.                 .long    ^X00000290  ;  C2
  1024.                 .long    ^X00000290  ;  C3
  1025.                 .long    ^X00000290  ;  C4
  1026.                 .long    ^X00000290  ;  C5
  1027.                 .long    ^X00000290  ;  C6
  1028.                 .long    ^X00000290  ;  C7
  1029.                 .long    ^X00000290  ;  C8
  1030.                 .long    ^X00000290  ;  C9
  1031.                 .long    ^X00000290  ;  CA
  1032.                 .long    ^X00000290  ;  CB
  1033.                 .long    ^X00000290  ;  CC
  1034.                 .long    ^X00000290  ;  CD
  1035.                 .long    ^X00000290  ;  CE
  1036.                 .long    ^X00000290  ;  CF
  1037.                 .long    ^X00000000  ;  D0
  1038.                 .long    ^X00000290  ;  D1
  1039.                 .long    ^X00000290  ;  D2
  1040.                 .long    ^X00000290  ;  D3
  1041.                 .long    ^X00000290  ;  D4
  1042.                 .long    ^X00000290  ;  D5
  1043.                 .long    ^X00000290  ;  D6
  1044.                 .long    ^X00000290  ;  D7
  1045.                 .long    ^X00000290  ;  D8
  1046.                 .long    ^X00000290  ;  D9
  1047.                 .long    ^X00000290  ;  DA
  1048.                 .long    ^X00000290  ;  DB
  1049.                 .long    ^X00000290  ;  DC
  1050.                 .long    ^X00000290  ;  DD
  1051.                 .long    ^X00000000  ;  DE
  1052.                 .long    ^X00000290  ;  DF
  1053.                 .long    ^X00000290  ;  E0
  1054.                 .long    ^X00000290  ;  E1
  1055.                 .long    ^X00000290  ;  E2
  1056.                 .long    ^X00000290  ;  E3
  1057.                 .long    ^X00000290  ;  E4
  1058.                 .long    ^X00000290  ;  E5
  1059.                 .long    ^X00000290  ;  E6
  1060.                 .long    ^X00000290  ;  E7
  1061.                 .long    ^X00000290  ;  E8
  1062.                 .long    ^X00000290  ;  E9
  1063.                 .long    ^X00000290  ;  EA
  1064.                 .long    ^X00000290  ;  EB
  1065.                 .long    ^X00000290  ;  EC
  1066.                 .long    ^X00000290  ;  ED
  1067.                 .long    ^X00000290  ;  EE
  1068.                 .long    ^X00000290  ;  EF
  1069.                 .long    ^X00000000  ;  F0
  1070.                 .long    ^X00000290  ;  F1
  1071.                 .long    ^X00000290  ;  F2
  1072.                 .long    ^X00000290  ;  F3
  1073.                 .long    ^X00000290  ;  F4
  1074.                 .long    ^X00000290  ;  F5
  1075.                 .long    ^X00000290  ;  F6
  1076.                 .long    ^X00000290  ;  F7
  1077.                 .long    ^X00000290  ;  F8
  1078.                 .long    ^X00000290  ;  F9
  1079.                 .long    ^X00000290  ;  FA
  1080.                 .long    ^X00000290  ;  FB
  1081.                 .long    ^X00000290  ;  FC
  1082.                 .long    ^X00000290  ;  FD
  1083.                 .long    ^X00000000  ;  FE
  1084.                 .long    ^X00000000  ;  FF
  1085.  
  1086.  
  1087. ;--------------------------------------------------------------------
  1088. ;   SOFTWARE SHIM DEFINITIONS FOR XFC EXITS
  1089. ;
  1090. ;   The first parameter is the local entry point name, that can be
  1091. ;   called by assembler code, etc.
  1092. ;
  1093. ;   The second parameter defines the function code in the XFC handler
  1094. ;   as defined in "shim.c"
  1095. ;
  1096. ;   The third parameter is the name of the sharable image that this
  1097. ;   routine is a shim for.  This is used by the RUN command's image
  1098. ;   activator to map runtime libraries to families of shims.
  1099. ;
  1100. ;   The fourth parameter is the offset in the sharable image of the
  1101. ;   real sharable image that supports this routine.  This is used by
  1102. ;   the image activator to bind a specific sharable image .ADDRESS
  1103. ;   or G^ references to this shim entry.
  1104. ;
  1105. ;--------------------------------------------------------------------
  1106.  
  1107.         .align    8
  1108.  
  1109. ;                       ------------        -----  --------   ------
  1110. ;                       Entry Name             ID  RTL        Offset
  1111. ;                       ------------        -----  --------   ------
  1112.                 .shim   lib$adawi,            ^d1, LIBRTL,      0778
  1113.                 .shim   str$upcase,           ^d2, LIBRTL,      0A70
  1114.                 .shim   exe$input,            ^d3, EVAX,        0004
  1115.                 .shim   decc$open,            ^d4, DECC$SHR,    04E8
  1116.                 .shim   decc$close,           ^d5, DECC$SHR,    0490
  1117.                 .shim   decc$read,            ^d6, DECC$SHR,    04F0
  1118.                 .shim   decc$write,           ^d7, DECC$SHR,    0508
  1119.                 .shim   decc$printf,          ^d8, DECC$SHR,    0380
  1120.                 .shim   decc$sprintf,         ^d9, DECC$SHR,    03E0
  1121.                 .shim   decc$strcmp,         ^d10, DECC$SHR,    06C0
  1122.                 .shim   decc$strncmp,        ^d11, DECC$SHR,    06F8
  1123.                 .shim   decc$strncpy,        ^d12, DECC$SHR,    0700
  1124.                 .shim   decc$atoi,           ^d13, DECC$SHR,    0568
  1125.                 .shim   decc$gets,           ^d14, DECC$SHR,    0370
  1126.                 .shim   decc$malloc,         ^d15, DECC$SHR,    0548
  1127.                 .shim   decc$free,           ^d16, DECC$SHR,    0538
  1128.                 .shim   decc$isalnum,        ^d17, DECC$SHR,    0018
  1129.                 .shim   decc$isalpha,        ^d18, DECC$SHR,    0020
  1130.                 .shim   decc$iscntrl,        ^d19, DECC$SHR,    0030
  1131.                 .shim   decc$isdigit,        ^d20, DECC$SHR,    0038
  1132.                 .shim   decc$isgraph,        ^d21, DECC$SHR,    0040
  1133.                 .shim   decc$islower,        ^d22, DECC$SHR,    0048
  1134.                 .shim   decc$isprint,        ^d23, DECC$SHR,    0050
  1135.                 .shim   decc$ispunct,        ^d24, DECC$SHR,    0058
  1136.                 .shim   decc$isspace,        ^d25, DECC$SHR,    0060
  1137.                 .shim   decc$isupper,        ^d26, DECC$SHR,    0068
  1138.                 .shim   decc$isxdigit,       ^d27, DECC$SHR,    0070
  1139.                 .shim   decc$isascii,        ^d28, DECC$SHR,    0028
  1140.                 .shim   lib$get_vm,          ^d29, LIBRTL,      0550
  1141.                 .shim   lib$free_vm,         ^d30, LIBRTL,      0548
  1142.                 .shim   lib$delete_vm_zone,  ^d31, LIBRTL,      0A48
  1143.                 .shim   decc$time,           ^d32, DECC$SHR,    0768
  1144.  
  1145. ;                       ------------        -----  --------   ------
  1146. ;                       Entry Name             ID  RTL        Offset
  1147. ;                       ------------        -----  --------   ------
  1148.  
  1149.  
  1150.  
  1151.  
  1152.                 .set    exe$uend    .
  1153.     
  1154. ;--------------------------------------------------------------------
  1155. ;   WRITABLE STORAGE AREA FOR KERNEL
  1156. ;--------------------------------------------------------------------
  1157.  
  1158. ;       This is the kernel writable data area.  It has different page
  1159. ;       attributes so it must be aligned on a new page boundary.
  1160.  
  1161.                 .align          0200
  1162.                 .set            exe$wbase .
  1163.                 
  1164. exe$tx_ready:   .long           1               ; Is TXCS available?
  1165. exe$rx_ready:   .long           0               ; Is RXCS available?
  1166. exe$init_done:  .long           0               ; Is kernel initialized?
  1167. exe$int_count:  .long           0               ; Interval timer count
  1168.  
  1169. exe$ast_list:   .long           exe$ast_list    ; Head of AST queue
  1170.                 .long           exe$ast_list
  1171.  
  1172. ;       Register Save Areas
  1173.  
  1174. exe$chmk_r0:    .long           0
  1175. exe$chmk_r1:    .long           0
  1176.  
  1177. ;       Region handlers
  1178.  
  1179. exe$p0_rgn:     .long           0
  1180. exe$p1_rgn:     .long           0
  1181. exe$s0_rgn:     .long           0
  1182.  
  1183. ;       Console input stuff
  1184.  
  1185. exe$rxdata:     .blkb           100
  1186. exe$rxptr:      .long           exe$rxdata
  1187. exe$rxlen:      .long           0
  1188.  
  1189. vaxc$errno:     .long           0
  1190.  
  1191. ;       Message descriptors
  1192.  
  1193. exe$init_msgb:  .ascii          "Kernel initialized..."
  1194.                 .byte           0a,0d
  1195. exe$init_msg:   .long           . - exe$init_msgb
  1196.                 .long           exe$init_msgb   
  1197.  
  1198. exe$sig_buff:   .blkb           10
  1199. exe$sig_desc:
  1200. exe$sig_buff_len:.long          8
  1201.                 .long           exe$sig_buff
  1202.                 
  1203. ;       Storage used by LIBRTL replacements
  1204.  
  1205. lib$hex_table:
  1206.  
  1207.                 .ascii "0123456789ABCDEF"
  1208.  
  1209. decc$gl_opterr: .long           0    ; These are static owned storage
  1210. decc$gl_optind: .long           0    ; that support the getopt()
  1211. decc$gl_optopt: .long           0    ; runtime routine.  They are
  1212. decc$ga_optarg: .long optarg_buff    ; usually .ADDRESS fixups in images
  1213.  
  1214. optarg_buff:    .long           0    ; actual buffer pointer goes here
  1215.  
  1216. decc$ga_stdin:  .long           0    ; The stdin handle goes here
  1217. decc$ga_stdout: .long           0    ; the stdout handle goes here
  1218. decc$ga_stderr: .long           0    ; the stderr handle goes here
  1219.  
  1220.  
  1221.                 .set            exe$wend .
  1222.  
  1223.                 .align          200
  1224.                 .set            exe$fbase .
  1225. ;
  1226. ;   I've been playing around with a forth interpreter written back in 1984
  1227. ;   for a VAX.  It might be interesting to include it in the microkernel
  1228. ;   for handling logic at the virtual VAX level.  If the interpreter source
  1229. ;   is present, assemble it as well.
  1230.  
  1231. ;                .if file_exists("forth.asm") .include       "forth.asm"
  1232.                 nop
  1233.                 .set            exe$fend .
  1234.  
  1235. ;--------------------------------------------------------------------
  1236. ;   SOFTWARE SHIM DEFINITIONS FOR NATIVE KERNEL ROUTINES
  1237. ;
  1238. ;   NOTE that this is placed after the writable storage area, because
  1239. ;   some of the shim values point to storage locations there, rather
  1240. ;   than just routine entry points in the readonly part of the kernel.
  1241. ;
  1242. ;   They have to be here, because .SHIM cannot tolerate a forward
  1243. ;   reference in the symbol name.
  1244. ;
  1245. ;   The first parameter is the local entry point name, that can be
  1246. ;   called by assembler code, etc.
  1247. ;
  1248. ;   The second parameter of 0 means the routine is implemented in the
  1249. ;   microkernel and doesn't need a native runtime XFC stub.
  1250. ;
  1251. ;   The third parameter is the name of the sharable image that this
  1252. ;   routine is a shim for.  This is used by the RUN command's image
  1253. ;   activator to map runtime libraries to families of shims.
  1254. ;
  1255. ;   The fourth parameter is the offset in the sharable image of the
  1256. ;   real sharable image that supports this routine.  This is used by
  1257. ;   the image activator to bind a specific sharable image .ADDRESS
  1258. ;   or G^ references to this shim entry.
  1259. ;
  1260. ;--------------------------------------------------------------------
  1261.  
  1262.                 .shim   lib$put_output,         0, LIBRTL,      0478
  1263.                 .shim   decc$main,              0, DECC$SHR,    0000
  1264.                 .shim   decc$exit,              0, DECC$SHR,    0528
  1265.                 .shim   decc$strlen,            0, DECC$SHR,    06E8
  1266.                 .shim   decc$strcpy,            0, DECC$SHR,    06D0
  1267.                 .shim   decc$strcat,            0, DECC$SHR,    06B0
  1268.                 .shim   cma$tis_errno_get_addr, 0, CMA$TIS_SHR, 0038
  1269.                 .shim   decc$calloc,            0, DECC$SHR,    0520
  1270.                 .shim   decc$$ga___ctypet,      0, DECC$SHR,    309C
  1271.                 .shim   decc$$gl___ctypea,      0, DECC$SHR,    3098
  1272.                 .shim   decc$gl_optopt,         0, DECC$SHR,    306C
  1273.                 .shim   decc$gl_optind,         0, DECC$SHR,    3068
  1274.                 .shim   decc$gl_opterr,         0, DECC$SHR,    3064
  1275.                 .shim   decc$ga_optarg,         0, DECC$SHR,    3070
  1276.                 .shim   decc$ga_stdin,          0, DECC$SHR,    2018
  1277.                 .shim   decc$ga_stdout,         0, DECC$SHR,    201C
  1278.                 .shim   decc$ga_stderr,         0, DECC$SHR,    2020
  1279.  
  1280. ;--------------------------------------------------------------------
  1281. ;   RESET STATE FOR CONSOLE ASSEMBLER
  1282. ;--------------------------------------------------------------------
  1283.  
  1284. ;       This section takes care of miscellanous housekeeping.
  1285. ;       Define the exception handlers in the SCB and make the 
  1286. ;       entire kernel area protected from being written on.
  1287. ;
  1288. ;    Note that for many of these, we define "console$handler"
  1289. ;       as the handler.  This equates to -1, and causes the emulator
  1290. ;       to report on the exception using non-VAX native code, and
  1291. ;       halts the emulation.  Later, this handler will also be 
  1292. ;       able to chase user-mode stack frames looking for exception
  1293. ;       handlers.
  1294.  
  1295.                 .scb            exc$chmk,      exe$chmk
  1296.                 .scb            exc$priv,      console$handler ;   exe$priv
  1297.                 .scb            exc$accvio,    console$handler ;   exe$accvio
  1298.                 .scb            exc$resop,     console$handler ;   exe$resop
  1299.                 .scb            exc$resaddr,   console$handler ;   exe$resaddr
  1300.                 .scb            exc$interval,  exe$interval
  1301.                 .scb            exc$software2, exe$deliver_ast
  1302.                 .scb            exc$conwrite,  exe$tx
  1303.                 .scb            exc$conread,   exe$rx
  1304.                 
  1305.  
  1306. ;       Set page protections on the segments of the kernel.  This MUST
  1307. ;       be done after all symbol fixups are generated, because the
  1308. ;       microassembler is forced to abide by page table protections.
  1309.  
  1310.                 .console        set page exe$ubase to exe$uend prot=pte$k_ur
  1311.                 .console        set page exe$base to exe$end prot=pte$k_ur
  1312.                 .console        set page exe$wbase to exe$wend prot=pte$k_kwur
  1313.                 .console        set page exe$fbase to exe$fend prot=pte$k_all
  1314.                 
  1315.  
  1316. ;       All done, let's set the console back so user assembly can
  1317. ;       occur normally
  1318.  
  1319.                 .region         p0
  1320.