dsm$boot_interrupt_handler IDENT
*COPY     SYA$CONSTANTS
.
.  Deck SYA$CYBIL_INTERFACE_PROCEDURES follows but is not listed.
         list,1  0,0,0
*COPY   SYA$CYBIL_INTERFACE_PROCEDURES
         list,1  1,2,0
         page
*COPY   MTA$CPU_STATE_TABLE
*COPY   MTA$SMU_COMMUNICATION_BLOCK
*COPY    OSA$DUAL_STATE_CONTROL_BLOCK
*copyc mta$dft_block
*COPY OSA$KEYPOINT_CLASSES
*copyc sya$xp_and_sf_constants
.
.
.      Define offsets into the request table entry.
.
rqtbles  equ     5*8                   .Size of request table entry
rn       equ     0                     .Highest RN for the request
il       equ     1                     .Interlock ordinal
rc       equ     2                     .Request code
totalt   equ     1*8                   .Total time for the request
maxt     equ     2*8                   .Max time to process the request
rqcnt    equ     maxt+4                .Count of times request was issued
wtcnt    equ     3*8                   .count of times waited for lock
maxwt    equ     wtcnt+4               .max wait for lock
totwt    equ     4*8                   .total wait time for lock
.
.      define offsets into interlock table.
.
ilsize   equ     3*8                   .size of interlock table entry.
ilflag   equ     0                     .interlock flag
lockcp   equ     1                     .lowest four (4) bytes of base constant
                                       . register contents of locking cpu
ilwtcnt  equ     1*8                   .lock wait count
ilmaxwt  equ     ilwtcnt+4             .max wait for lock
iltotwt  equ     2*8                   .total wait for lock
.
.      Define the request codes.  These request codes should match the
.      CYBIL declarations in SYDMTRR.
.
rqunim   equ     0                     .Unimplemented request code
rqpf     equ     9                     .Code for PAGE FAULT.
rqfault  equ     20                    .Code for MCR/UCR faults.
tsksw    equ     51                    .task switch
pswarn   equ     52                    .process short warning
mon_smu  equ     53                    .monitor_smu_status
proc_io  equ     54                    .process_io_completions
ascii_kb equ     56                    .process ascii keyboard
key_pnt  equ     57                    .monitor_keypoint_recorder
per_call equ     58                    .periodic_call
proc_due equ     59                    .process_due
in_ckp   equ     60                    .initiate_checkpoint
mm_ei    equ     62                    .process_170_mtr_requests
proc_dft equ     66                    .process DFT block
         page
.
.
. XTRACE - This macro is used to keep trace information about what happens.
.    The TRACE buffer is a circular buffer containing a list of the last
.    128 items of interest. Items currently maintained are:
.       0. exchange to job mode. (timestamp)
.       1. exchange from job mode. (timestamp, MCR)
.       2. trap in monitor mode. (timestamp, MCR)
.       3. EXCHANGE to NOS for EXCHREQ trap. (timestamp)
.       4. EXCHANGE back from NOS for EXCHREQ trap. (timestamp, MCR)
.       5. Taskswitch. (timestamp, new task XP RMA)
.    An entry in the trace buffer is 1 word long and contains:
.       bit 0 - 3,  trace id. Same as item number in above list
.       bit 4-31, data dependant on id. Usually MCR or XP RMA.
.       bit 32-63, elapsed microseconds since last entry in trace buffer
.
.    calling sequence to macro....
.
.        xtrace  p0,p1,p2,p3
.           p0 - contains trace id (0 .. 4)
.           p1 - contains data to be saved
.           p2, p3 - 2 X-registers that can be used for scratch
.              WARNING - X0 cannot be used for p2.
.           p4 - scratch A register
         PROC
xtrace   pname
f:(0)    bss     0
         local   t1,t2
         lx      f:(2,2),a_cst,tracectl
         brxgt   x0,f:(2,2),t2
         cpyxa   f:(2,4),f:(2,2)
         entp    f:(2,3),0
         cpytx   f:(2,3),f:(2,3)
         lx      f:(2,2),f:(2,4),0
         sx      f:(2,3),f:(2,4),0
         subx    f:(2,3),f:(2,2)
         entp    f:(2,2),f:(2,0)
         insb    f:(2,3),f:(2,2),x0,0003(8)
         lx      f:(2,2),f:(2,4),8
         isob    f:(2,2),f:(2,2),x0,7007(8)   .WARNING - <tracesiz> dependent.
         incx    f:(2,2),1
         sx      f:(2,2),f:(2,4),8
         do      sn:(f:(2,1))/=sn:(0)
         insb    f:(2,3),f:(2,1),x0,0433(8)
54       dend
         sxi     f:(2,3),f:(2,4),f:(2,2),8
t2       bss    0
         pend
         page
.
.
. HISTO - This macro is used to build a table of values of a variable. The
.         table consists of 64 word aligned values T0 .. t63. The value
.         of T0 is the number of times the macro was executed with
.         of the input variable negative (full word). For 1 <= i <=63,
.         the value of Ti is the number of times the macro was executed
.         with 2**(i-1) <= input variable < 2**i.
.
.       histo    xpar,atab,tab,xscr1,xscr2
.            where   xpar - X register that contains the value to be tabulated
.                    atab - A register that points to tabulation table
.                    tab  - symbol assigned to tabulation table - beginning
.                          of table is at (atab)+tab
.                    xscr1- X register to use for scratch calculations.
.                    xscr2- X register to use for scratch calculations.
.
ahisto   equ     0                     .Set this variable non-zero to activate HISTO
.
         PROC
histo    pname
         do      ahisto/=0
         do      sc:(f:(2,2))=0
         USE     oss$mainframe_wired
         def     f:(2,2)
         align   0,32
         vfd,64  c'f:(2,2)'
f:(2,2)  bssz    64*8
         USE     #LASTSEC
         dend
         local   l1,l2
         brxge   f:(2,0),x0,l1
         entn    f:(2,3),1
         brxeq   x0,x0,l2
l1       cnif    f:(2,3),f:(2,0)
         isob    f:(2,3),f:(2,3),x0,0413(8)
l2       lxi     f:(2,4),f:(2,1),f:(2,3),f:(2,2)+8
         incx    f:(2,4),1
         sxi     f:(2,4),f:(2,1),f:(2,3),f:(2,2)+8
         DEND
         PEND
         page
.
.
. ERRSTOP - This macro generates a call to the error stop routine to
.           terminate 180 operation after an unrecoverable error has
.           occurred.
.
.         errstop p1
.              where p1 = label on a string that defines the error halt message
.
         PROC
errstop  pname
f:(0)    addaq   af,a_root,f:(2,0)
         cpyaa   ae,a0
         addaq   a0,a0,8
         sa      af,ae,0
         entl    x0,31
         sbyts,2 x0,ae,x0,6
         ente    x0,00ff(16)
         callseg bs_errst,a_bindin,ae
         PEND
         page
*COPY     OSA$BASIC_REGISTER_EQUATES
         page
*COPY   SYA$ISSUE_KEYPOINTS_IN_HANDLERS
         page
.
.
.  Define A and X register usage
.   Note...
.        1. X0, X1, X2, XD, XE and XF are scratch registers
.        2. AE and AF are scratch registers
.        3.AF contains a pointer to 'xpinitv' at deadstart time. Its
.          used only for system initialization
.
a_sitret areg    15                    .Return address for PRSIT routine.
a_cst    areg    8                     .Pointer to CST.
a_rqtbl  areg    7                     .Contains the pointer to REQTBL entry
a_xcb    areg    6
a_root   areg    5
a_dscb   areg    4                     .NOS170 DSCB.
.
x_mcr    xreg    3                     .Scratch reg for MCR
x_ucr    xreg    4                     .Scratch reg for UCR
x_clock  xreg    5                     .Contains PIT/FRC values.
x_envir1 equ     00d7(16)              .Environment for CALL.
.
.  Equates for call to Interrupt processor.
.
x_inmcr  xreg    7                     .NOS170 MCR.
x_infrc  xreg    6                     .Save for free running clock.
a_innosx areg    9                     .Pointer to NOS XCB.
a_inret  areg    10                    .Return address.
a_rq_ret areg    11                    .rqproc return address
a_parm   areg    12                    .call parameters
a_extret areg    13                    .return from extint.
.
.  Equates for IDLE180.
x_resume xreg     8                    .contains RESUME ALLOWED.
.
         page
.
.
.  define procedure to define and initialize cst entries.
.
.
         PROC
defcst   pname
lpidz    set     0
         while   lpidz<f:(2,0)
         local   cst1
cst1     bssz    cstsize
.  Preset some values in the CST.

.        The value of MEMPORT is set early in initialization based on processor type.

         org     cst1+memport
         vfd,8   1**(lpidz*2)
         org     cst1+lpid
         vfd,8   lpidz
         org     cst1+lpid8
         vfs,8   lpidz*8
         org     cst1+cpu_stat
         vfd,8   2
         org     cst1+tracectl
         vfd,16  0
         address r,trace+lpidz*(tracesiz+2)*8
         org     cst1+taskid
         vfd,16,8 1,1
         org     cst1+dsprior
         vfd,16  0308(16)
         org     cst1+jcbp
         vfd,4,12,32 1,mstlen,0
         org     cst1+xcbp
         vfd,4,12,32 1,mstlen,jrootsiz
         org     cst1+cptime
         vfd,64  0ffffffffffff(16)
         org     cst1+cachtim
         vfd,64  07fffffffffffffff(16)
         org     cst1+maptim
         vfd,64  07fffffffffffffff(16)
         org     cst1+idlstats+idle_cnt
         vfd,56  1                       . initialize the cpu idle count
         org     cst1+cstsize
lpidz    set     lpidz+1
         dend
         pend
         page
...................................................................
.
.   Define the bootstrap section to the Assembler. This section
.   will contain code,data,and binding entries
.
...................................................................
oss$mainframe_wired   SECTION working,read+execute+write
         USE     oss$mainframe_wired
.....................................................................
.        LIT       - Load Interface Table.
.
.        The load interface table provides the information required
.        by the NOS/VE boot to establish the full boot environment.
.
.        Define the load size of the boot.
.
         def     root
root     equ     $
         def     osv$boot_load_size_in_bytes
osv$boot_load_size_in_bytes bss 0
BOOT_LBA vfd,32  8000(16)
.
.        Define the NOS/VE BOOT version and level.  The format of this
.        is rigidly defined.  If it is changed the utility that packages
.        the BOOT for CIP tapes must also be modified.
.
         def     osv$boot_version
osv$boot_version bss 0
         vfd,6   0                     .filler
         vfd,6   1                     . os type
         vfd,6   0                     .Interface version
         vfd,6   0                     .Interface level
.
.        The version number is a decimal number that is put in hex for convenience
.        when checking version number in memory.
.
         vfd,8   007(16)               .BOOT version number
.
.        DEFINE BOOT STOP ADDRESS.
.
         def     osp$boot_halt
         align   0,8
osp$boot_halt bss    0
         brreq   X0,X0,osp$boot_halt   .STOP THE MUSIC
.
.        Date dsm$boot_interrupt_handler deck changed.
.
         def     osv$boot_assembly_date
osv$boot_assembly_date bss 0
*put '  vfd,32 '//$substr($date(iso),6,2)//$substr($date(iso),9,2)//$substr($date(iso),1,4)//'(16)'
.
.        Relative byte offset from beginning of boot of monitor exchange package.
.
.        NOTE:
.        The location of this offset can not change without changing SCI, this is
.        how SCI figures out where the exchange package of boot monitor is.  SCI
.        expects to find it at byte offset 10(16) from the beginning of the boot.
.
         def     osv$boot_mps_offset
osv$boot_mps_offset bss 0
         vfd,32  mxp
.
...................................................................
.
.        NOS/VE memory limits.  Defines the upper and lower bounds of NOS/VE
.        memory, the bounds are RMAs.  During deadstart the memory upper bound
.        is determined by the size of the memory image.
.
.        NOTE:  The memlimit variable is referenced from Cybil, definition is
.        defined by the variable 'osv$180_memory_limits'.
.
...................................................................
memlimit vfd,32  0                     .Lower bound.
         vfd,32  0                     .Upper bound during deadstart.
         vfd,32  0                     .Upper bound after system initialized.
         PAGE

.        Variables and equates specifically for boot module.
.
.        Real memory word address 71(8) (real memory address 1c8(16)) contains the
.        real memory word address of the environment interface control block (EICB).

eicbadr  equ     71(8)*8               .Real memory address of EICB pointer.
bctadr   equ     65(8)*8               .Real memory address of the Boot Control Table.
.
pgtabpva vfd,48  0100000000000(16)     .page table PVA
mstkpva  vfd,48  0100b00000000(16)     .mtr stack PVA
jstkpva  vfd,48  0100c00000000(16)     .job stack PVA
.
         align   0,8
free_rma vfd,64  0                     .RMA of available memory
sadjcbp  address r,jcb
sadmsdt  address r,mst
sadjsdt  address r,jst
sadxcbp  address r,jxcb
         defg    osv$boot_sdte
         defg    osv$boot
         defg    osv$boot_is_executing
         defg    dsv$ssr_sdte
osv$boot vfd,8   1
osv$boot_sdte vfd,64 0
dsv$ssr_sdte  vfd,64 0
osv$boot_is_executing vfd,8 1
hnsk_p   address p,dsv$cpu_pp_communication_block
         ref     dsv$cpu_pp_communication_block
         align   0,8
         page
.....................................................................
.
.   Define the initial monitor exchange package and segment table.
.   The monitor exchange package and segment table are located at
.   the beginning of the primary boot segment.
.
.....................................................................
mstackl  equ     xpsize+mstlen*8+mstksize
         align   0,32
mxp      ALIAS   MTV$MONITOR_EXCHANGE_PACKAGE
         def     mst
         defg    mxp
mxp      bssz    xpsize
         align   0,32
mst      bssz    mstlen*8
mstend   bss       0
         xpa     mxp,2,begin
         xpa     mxp,xptos,nil
         xpareg  mxp,a_tos,nil
         xpareg  mxp,a_csf,nil
         xpareg  mxp,a_psa,nil
         xpareg  mxp,a_bindin,bindsec
         xpv     mxp,10+a_xcb*8,mstlen+01000(16),16
         xpv     mxp,12+a_xcb*8,jr_mxcb,32
         xpareg  mxp,a_root,root,0
         xpareg  mxp,a_plist,nil
         xpareg  mxp,7,mxp,0
         xpareg  mxp,8,nil
         xpareg  mxp,9,nil
         xpareg  mxp,10,nil
         xpareg  mxp,11,nil
         xpareg  mxp,12,nil
         xpareg  mxp,13,nil
         xpareg  mxp,14,nil
         xpareg  mxp,15,nil
         xpv     mxp,xpstal,mst,16         .Segment table address
         xpv     mxp,xpstl,mstlen,16       .Segment table length
         xpv     mxp,xpmm,m_mtrmsk,16  .Monitor mask
         xpv     mxp,xpum,m_usrmsk,16  .User mask
         xpv     mxp,xpkm,0,16
         xpv     mxp,xppit,0ffff(16),16  .Monitor PIT
         xpv     mxp,xppit+8,0ffff(16),16
         xpv     mxp,xplrn,1,16
         xpa     mxp,xptp,bs_trap,0
         xpv     mxp,xpflgte,00000(16),16
         xpv     mxp,xpbc1,cst0u,16
         xpv     mxp,xpbc2,cst0l,16
         xpv     mxp,248,cst0,32  .Set offset and length of CST0 into XE
         xpv     mxp,252,cstsize,32
         page
.
. Note that only two Segment table entries contain an ASID. The ASID
. for the page table and the primary boot segment will be changed
. early in the execution of this module. The ASIDs found in this
. segment table must not be changed as SCI knows these two ASIDS
. and will create one PTE for each of these two segments as
. part of the process of loading the boot for deadstart.
.
mst      alias   MTV$MONITOR_SEGMENT_TABLE
         org     mst
pt_seg   vfd,64  0ca11000100000000(16)  .seg 0 page table segment

.        Segment 1 is used for a special purpose while creating the page table
.        entries for the page table.  A page table entry is added to the first
.        page of the page table for page 0 of this segment.  If the page for
.        the page table entry is not in the page table, the page frame address of
.        the segment 1 page table entry is changed to point to the page for the
.        new page table entry.  The new page table entry is then stored in the
.        page table using segment 1.  The page table entry for segment 1 is
.        deleted after all of the page table entries for the page table are
.        created.  The ASID of segment 1 is zero.

seg1     vfd,64  0ca11000000000000(16)  .seg  1, used to create page table
         vfd,64  00000000000000000(16)  .seg  2  null entry
mnosste  vfd,64  00000000000000000(16)  .seg  3  NOS
mnsfste  vfd,64  00000000000000000(16)  .seg  4  NOS stack and the SSR
         vfd,64  00000000000000000(16)  .seg  5  null entry
         vfd,64  00000000000000000(16)  .seg  6  null entry
         vfd,64  00000000000000000(16)  .seg  7  null entry
         vfd,64  00000000000000000(16)  .seg  8  null entry
         vfd,64  00000000000000000(16)  .seg  9  null entry
bootste  vfd,64  0fe11000200000000(16)  .seg  A  BOOT primary segment
msfste   vfd,64  0ca11000000000000(16)  .seg  B  Boot monitor mode stack segment
jsfste   vfd,64  0ca11000000000000(16)  .seg  C  Boot job mode stack segment
         vfd,64  00000000000000000(16)  .Pad segment table
.
         org     mstend
         page
.....................................................................
.
.   BOOT - Execution at deadstart starts here. Create page table entries for
.          page table, boot segment, boot stack, job stack, NOS,
.          and NOS (trap) stack.  Segment 1 is defined with an ASID of zero,
.          it is used to address any page during initialization of the page
.          table.  If the page where the page table entry is to be stored does
.          not have a valid page table entry, the RMA in the page table entry
.          for segment 1, page 0 is changed and that PVA is used to store the
.          page table entry.  Using this method allows the building of the
.          page table entries with the final ASID the first time.
.
.          This is what the page table looks like when execution starts here:
.               page_table [2] = page table entry for page 0 of page table.
.               page_table [4] = page table entry for page 0 of this code.
.               page_table [0] = will be used for segment 1 page table entry,
.                                initially it is zero.
.....................................................................
         def     begin
         def     rqproc
         def     run_nos
begin    bss     0
         def     osp$prepare_os_environment
osp$prepare_os_environment equ $
.
.        Purge all maps and cache.
.
         purge   x0,2                  .purge all of cache.
         purge   x0,0f(16)             .purge all maps.
.
.        Establish X-register values required to manipulate page table.
.                xd = page table length.
.                xe = page size mask.
.                xf = page offset mask, used to mask page number from SVA.
.
begin2   entl    x0,r_psm              .page size mask
         cpysx   x2,x0
         isom    xf,x0,47
         shfx    x2,x2,x0,9
         iorx    xf,x2                 .form mask for page offset
         notx    xe,xf
         incx    xe,1                  .page size in bytes

         entl    x0,r_ptl              .page table length
         cpysx   x2,x0
         incr    x2,1
         shfx    xd,x2,x0,12           .Xd:= page table length in bytes
.
.        Create page table entry for the first page of the page table using the
.        new ASID.  Expect this page table entry to be in page 0 of page table.
.
         addpxq  a9,x0,boot5           .Find ASID for page table
         brreq   x0,x0,fasid
boot5    bss     0
         shfx    x3,x3,x0,32           .X3:= SVA of page table
         la      ac,a_root,pgtabpva    .PVA of page table
         isom    x4,x0,1               .Create page table entry for segment 1
         tpage   xc,ac
         sbyts,8 x4,ac,x0,0
         cpyxx   x6,xc                 .X6:= RMA of page table
         cpyxx   x5,xe                 .X5:= length of one page
         addpxq  a9,x0,boot10
         brreq   x0,x0,cseg            .Create PTE for page 0 of page table
boot10   bss     0
         shfx    x4,x3,x0,-32          .Store new PT ASID in segment table
         entp    x8,0                  .Zero out page table entry for first
                                       . page of page table with old ASID
         sbyts,2 x4,a_root,x0,pt_seg+2
         sbyts,8 x8,ac,x0,2*8

.        Purge all maps and cache in order to start using new page table ASID.

         purge   x0,2
         purge   x0,0f(16)

.        Create page table entry for remainder of page table with new ASID.

         cpyxx   x5,xd                 .Page table length
         addpxq  a9,x0,boot15
         brreq   x0,x0,cseg            .Create page table entries for page table
boot15   bss     0
.
.        Create page table entries for the boot segment using new ASID.
.
         entp    x8,0                  .Zero out page table entry for segment 1
         addpxq  a9,x0,boot20          .Find ASID for boot segment
         sbyts,8 x8,ac,x0,0
         brreq   x0,x0,fasid
boot20   bss     0
         shfx    x3,x3,x0,32           .X3:= SVA of boot segment
         tpage   x6,a_root
         lbyts,4 x5,a_root,x0,boot_lba  .Length of boot segment
         addpxq  a9,x0,boot25
         brreq   x0,x0,cseg            .Create page table entries for boot segment
boot25   bss     0
         shfx    x4,x3,x0,-32          .Store new boot segment ASID in
                                       . segment table
         entp    x8,0
         sx      x6,a_root,free_rma    .Save RMA of available memory
         sbyts,8 x8,a_root,x0,seg1     .Zero out segment table entry for segment 1
         sbyts,2 x4,a_root,x0,bootste+2
.
.        Purge all maps and cache in order to start using new boot segment ASID.
.
         purge   x0,2
         purge   x0,0f(16)

.        On some machines the page map may not be cleared by the purge instructions
.        for the currently executing code.  Doing an inter segment branch will clear
.        the page map when P is translated from the PVA again.  It handily works out
.        that we now are beyond the minimum environment needed for startup.

         addpxq  a9,x0,boot30          .set branch address.
         brdir   a9,x0                 .clear page map.
         page
..
.        CSEG - Create page table entries for specified segment.
.               Creation of the page table is special cased.  If the page where
.               the page table entry is to be stored is not valid, the entry
.               is stored using segment 1.
.
.        ENTRY:
.                x3 = SVA of start of segment.
.                x6 = RMA of start of segment.
.                x5 = length of segment (offset of last byte address + 1).
.                xe = page size in bytes.
.                xf = page offset mask.
.                a9 = return address.
.                ac = PVA of page table
.
.        EXIT:
.                x3 = SVA of page following segment created.
.                x6 = RMA of page following segment created.
.
.        USES:
.                a - 7, b.
.                x - 1, 2, 3, 4, 6, 8, 9.
.

cseg     entp    x8,3                  .valid + continue bit
         la      ab,a_root,pgtabpva    .PVA of page table.
         shfx    x8,x8,x0,62-0
cseg5    lpage   x2,x3,x1
.
.        If there are no available slots in the page table for
.        the SVA, then LPAGE returns with X1 equal to 32,
.        ie. the number of entries searched.
.
         cpyaa   a7,ab
         ente    x4,31
         addax   a7,x2                 .Page table PVA for page table entry
         brrgt   x1,x4,cseg20          .If no available slot in page table
         cpyxx   x1,x3
         tpage   x9,a7                 .Check if page table page in memory.
         andx    x1,xf                 .form segment/page identifier
         shfx    x4,x6,x0,-9           .form page frame address
         shfr    x1,x1,x0,1            .trim sign bit from offset
         shfx    x1,x1,x0,22-9-1
         iorx    x1,x4
         iorx    x1,x8
         brrgt   x0,x9,cseg15          .If page table page not in memory
         sbyts,8 x1,ac,x2,0            .store page table entry
cseg10   bss     0
         addr    x3,xe                 .update SVA
         addr    x6,xe                 .update RMA
         brrgt   x5,x3,cseg5           .if more entries to build
         brdir   a9,x0                 .return

.        Page table page not in memory, store page table entry using segment 1.

cseg15   bss     0
         entl    x0,r_pta
         ente    x9,1001(16)           .Form PVA for segment 1
         cpysx   x4,x0                 .Page table address
         shfx    x9,x9,x0,32
         addr    x4,x2                 .RMA for page table entry
         cpyxx   x2,x4
         andx    x4,xf                 .Round to page size
         inhx    x2,xf                 .Offset from page frame address for PTE
         shfx    x4,x4,x0,-9           .Page frame address

.        Set page frame address in page table entry for segment 1.  Page frame
.        address is for the page of the page table where the PTE entry is to
.        be stored.

         sbyts,3 x4,ab,x0,5
         cpyxa   a7,x9
         purge   x9,10                 .Purge page map, page table modified
         sbyts,8 x1,a7,x2,0            .Store page table entry for PT page
         brreq   x0,x0,cseg10          .Continue

.        Page table full, hang.

cseg20   brreq   x0,x0,cseg20          .Page table full, hang

         page
..
.        FASID - Find ASID.
.                This algorithm attempts to distribute ASIDs as far apart in
.                the page table as possible.  The algorithm is described below
.                in Cybil.
.
.        ENTRY:
.                a9 = return address.
.        EXIT:
.                x3 = ASID generated by algorithm.
.
.        USES:
.                x - 0,1, 2, 3, 4, 5, 7, 8.
.
. Selecting ASIDs for each segment
.
. PROCEDURE get_asid (VAR asid: ost$asid);
.
.
.   VAR
.     i,
.     f: integer,
.     found: boolean,
.     last_asid: ^dst$reserved_asids;
.   found := TRUE;
.   page_table_length := mmv$pt_length * 8;
.   REPEAT
.     i := asid_seed;
.     asid_seed := asid_seed + 1;
. {  Page_table_length is the PTL register.
.     f := ((((page_table_length MOD 100(16)) + 1) * 1000(16) DIV 32);
.     asid := 0;
.     WHILE i <> 0 DO
.       IF (i MOD 2) <> 0 THEN
.         asid := asid + f;
.       IFEND;
.       i := i DIV 2;
.       f := f DIV 2;
.     WHILEND;
.
.     IF (asid <> nos_asid) THEN
.       search_reserved_asids (asid, found, last_asid);
.     IFEND;
.   UNTIL NOT found;
. PROCEND get_asid;
.



fasid    bss     0
         lbyts,2 x1,a_root,x0,asidseed  .ASID seed
         entl    x0,r_ptl
         cpyxx   x7,x1                 .Initial ASID seed, represents i
         incx    x1,1                  .increment asid seed by 1
         cpysx   x2,x0                 .Read PTL register
         sbyts,2 x1,a_root,x0,asidseed
         isob    x2,x2,x0,(56*64)+7    .low order 8 bits of PTL
         entp    x3,0                  .asid:=0
         incx    x2,1
         shfx    x2,x2,x0,12-5         .((PTL + 1) * 1000(16)) DIV 32, represents f

.        Generate ASID, basically this creates a mirror image of the initial
.        ASID seed.

fasid5   bss     0
         isob    x4,x7,x0,(63*64)+0
         shfx    x7,x7,x0,-1           .Initial ASID seed DIV 2
         brxeq   x4,x0,fasid10         .If even number, nothing to invert
         addx    x3,x2
fasid10  bss     0
         shfx    x2,x2,x0,-1           .ASID hash DIV 2
         brrne   x7,x0,fasid5          .If more bits to invert
         brreq   x0,x3,fasid           .If ASID of zero, will not use
         isom    x4,x0,(48*64)+15      .hardwired 170 asid of 0FFFF(16)
         entp    x6,0                  .Initialize 'asidlist' index
         brxeq   x4,x3,fasid           .If 170 ASID, find another one
.
.        Check list of previously assigned ASIDs to see if already assigned.

fasid15  bss     0
         lbyts,2 x2,a_root,x6,asidlist
         incx    x6,2
         brreq   x2,x3,fasid           .If ASID already assigned
         brrne   x2,x0,fasid15         .If more ASIDs in previously assigned
                                       . ASID list
         decx    x6,2
         sbyts,2 x3,a_root,x6,asidlist  .Save assigned ASID in list
         brdir   a9,x0               .Return

.        Define area to save list of assigned ASIDs.  Expect this list to
.        end with a zero ASID.  If more than 15 ASIDs are ever assigned this
.        list will have to be expanded.

asidlist vfd,16*16 0
asidseed vfd,16  1                   .Initial ASID seed

.        The initial part of the boot must run in less than a 2K page, this
.        is the end of that code.

pof      bss     0                   .page overflow check.
         error,pof>7ff(16)  c'VCB overflows 2K page size.'

         PAGE

.        At this point all of the page table entries are defined for the page
.        table and the boot code segment.

         align   0,2
boot30   bss     0
         sbyts,8 x8,ac,x0,4*8          .Zero out old page table entry for first
                                       . page of boot segment
.
.        Find preferred ASID for the SSR segment.  When running dual state
.        bytes 0 to 0fff(16) of the SSR segment are used for the 170
.        stack.  The SSR begins at byte offset 1000(16).
.
         addpxq  a9,x0,boot35
         brreq   x0,x0,fasid
.
.        Add segment table entries for 170 and 170 stack into monitor's segment
.        table.  Create page table entries to address EICB.
.
boot35   bss     0
         sbyts,2 x3,a_root,x0,nsfste+2  .Save ASID in 170 segment table
         la      af,a_root,sadmsdt
         la      ae,a_root,nossegt
         lbyts,8 x5,ae,x0,snnos170*8
         isom    x3,x0,((1*64)+0)
         sx      x5,af,snnosmtr*8
         iorx    x5,x3                 .set cache bypass attribute.
         sx      x5,af,sn170mcb*8      .set 170 cache bypass segment table entry.
         lbyts,8 x5,ae,x0,snsf170*8
         sx      x5,af,snsfmtr*8
         sbyts,8 x5,a_root,x0,dsv$ssr_sdte  .make NOS stack STE ( SSR ) known to
                                       .  job mode
         lbyts,2 x3,af,x0,snnosmtr*8+2
         shfx    x3,x3,x0,32           .X3:=SVA for NOS segment
         ente    x5,eicbadr            .X5:=offset to EICB
         entp    x6,0                  .NOS/page 0 begins at RMA=0
         addpxq  a9,x0,boot40
         brreq   x0,x0,cseg            .create PTEs to address EICB pointer

boot40   bss     0
         la      ae,a_root,eicb_pva
         lbyts,4 x1,ae,x0,eicbadr+4    .eicb address is in first 28 bits
         shfx    x1,x1,x0,3            .byte offset to eicb
         cpyaa   a_dscb,ae
         addax   a_dscb,x1             .a_dscb:= pva of eicb
         sa      a_dscb,a_root,eicb_pva
         addxq   x5,x1,dscbl           .LBA + 1 of EICB.
.
.        If x3r >= x5r then lba of EICB is addressable. If not create page
.        table entries to address it.
.
         brrge   x3,x5,boot45          .if EICB in same page as pointer
         addpxq  a9,x0,boot45
         brreq   x0,x0,cseg            .Create page table entries for all of EICB
.
. At this point have defined PTEs to reference EICB from the NOS segment.  Now
. create PTEs for remainder of NOS.  When running NOS/VE standalone the EICB
. and DFT buffer are addressed with the NOS segment.
.
.        X3 = SVA+1 of last NOS page defined in page table.
.        X6 = RMA+1 of last NOS page defined in page table.
.
boot45   bss     0
         lx      xa,a_dscb,d7cm+8
         isob    x2,xa,x0,2027(8)      .NOS/VE FWA/1000(8)
         shfx    x5,x2,x0,9+3          .NOS LBA+1
         brrge   x6,x5,boot50          .if all of needed NOS PTEs created
         addpxq  a9,x0,boot50
         brreq   x0,x0,cseg            .create remainder of NOS PTEs.
.
boot50   bss     0
.
.        Fetch and store pointer to the DFT block
.          r_pointer: offset, r_upper, r_lower, size
.          rma of r_pointer = r_upper*10000000(8) + r_lower*1000(8) + offset*10(8)
.
         lbyts,2 x6,a_dscb,x0,dscm+3*8+2  .Load r_upper into x6
         lbyts,2 xb,a_dscb,x0,dscm+3*8+4  .Load r_lower into xb
         shfx    x6,x6,x0,7*3          .Shift: r_upper * 10000000(8)
         shfx    xb,xb,x0,3*3          .Shift: r_lower * 1000(8)
         addx    x6,xb                 .Add r_lower to r_upper
         lbyts,2 xb,a_dscb,x0,dscm+3*8+0  .Load offset into xb
         shfx    xb,xb,x0,1*3          .Shift: offset * 10(8)
         addx    x6,xb                 .Add offset to (r_upper + r_lower)
         entp    xb,sn170mcb
         sa      a_dscb,a_root,mtvdftb  .save base ptr: ring number.
         sbyts,1 xb,a_root,x0,mtvdftb+1  .set cache bypass segment number for
                                       . DFT buffer.
         sbyts,4 x6,a_root,x0,mtvdftb+2  .store dft offset in ptr
.
.        Create PTEs for the 170 xp stack segment and the SSR.  The 170 stack
.        and the SSR are in the same segment.  The 170 stack is from offset
.        0 to 0fff(16), the SSR starts at offset 1000(16).  The last byte
.        address of the SSR is determined from NOS/VE last word address in
.        the EICB.

         lbyts,2 x6,a_dscb,x0,d8sv+8+2 .X6:=R-upper bits
         lbyts,2 xb,a_dscb,x0,d8sv+8+4 .Xb:=R-lower bits
         shfx    x6,x6,x0,6*3
         insb    x6,xb,x0,5613(8)
         shfx    x6,x6,x0,3
         ente    x1,1000(16)           .Size of 170 stack
         subx    x6,x1                 .X6 contains RMA of NOS stack
.
         la      a7,a_root,sadmsdt
         lbyts,2 x3,a7,x0,snsfmtr*8+2
         shfx    x3,x3,x0,32           .x3:=SVA for NOS stack segment
.
         lx      x7,a_dscb,d7cm+8
         isob    x9,x7,x0,5027(8)      .X9:= NVE_CM LWA+1/1000B
         shfx    x5,x9,x0,9+3          .X5:= NVE_CM LBA
         subx    x5,x6                 .x5:= byte count for NOS stack
         addpxq  a9,x0,boot55
         brreq   x0,x0,cseg            .Create 170 stack and SSR page table entries
.
boot55   bss     0

.        Create PTEs for boot's monitor stack segment.

         addpxq  a9,x0,boot60
         brreq   x0,x0,fasid
boot60   bss     0
         sbyts,2 x3,a_root,x0,msfste+2
         shfx    x3,x3,x0,32           .X3:= SVA of mtr stack
         ente    x5,2000(16)           .initial size for stack
         lx      x6,a_root,free_rma
         addpxq  a9,x0,boot65
         brreq   x0,x0,cseg            .Create PTEs for boot's monitor stack
.
boot65   bss     0
.        load mtr a0,a1 with pva to stack segment
.
         la      a_dsp,a_root,mstkpva
         la      a_csf,a_root,mstkpva
.
.        establish pva to the cpu state table, set KBP
.
         ente    x0,63(16)             .initialize KBP register
         isom    x1,x0,2020(8),x0      .NOT CORRECT FOR MULTIPROCESSOR
         cpyxs   x1,x0                 .need to do in every processor
         entl    x0,r_bc
         cpysx   x1,x0                 .get  base constant.
         cpyax   x2,a_root
         addx    x1,x2                 .form pointer to cst
         cpyxa   a_cst,x1
.
.        store pointer to cpu-state-table in mtr stack as per
.        mtm$monitor_interrupt_handler startup code
.
         addaq   a_dsp,a_dsp,mstkfram
         sa      a_cst,a_csf,10        .Save CST_P for p-list.
.
.        save contents of x6, ie: LBA of available free memory
         sx       x6,a_root,free_rma
.
.        Create page table entries for the boot's job mode stack.
.
         addpxq  a9,x0,boot70
         brreq   x0,x0,fasid

boot70   bss     0
         entc    x1,#boff(jsfste+2)
         sbyts,2 x3,a_root,x1,0
         shfx    x3,x3,x0,32           .X3 := SVA of job stack
.
         lx      x6,a_root,free_rma
         ente    x5,1000(16)           .initial size for stack
         addpxq  a9,x0,boot75
         brreq   x0,x0,cseg            .Create PTEs for boot's job mode stack
         page
.....................................................................
.
.     Define tables internal to monitor. Some of the tables are
.     referenced by other modules running in monitor.
.
.....................................................................
.
.        The following is the definition of the communication block to
.        talk to the NOS/VE console (SCI).
.
         align   0,8
asciiblk bss     0                     .ascii console communications block
         vfd,8   0                     .input buffer id
         vfd,8,8,8 0,0,0               .character buffer
         vfd,32  0                     .rma of last output entry processed
         vfd,8   0                     .console driver command
         vfd,8   0                     .hold display flag
         vfd,8   0                     .echo line size
         vfd,8   0                     .undefined
         vfd,32  0                     .rma of output list
.
dpv$scd_block_p address r,asciiblk
.
         align   0,8
dpv$scd_time  vfd,64 0
.
         align   0,8
cst0     bss     0
         defcst  maxcst
cst0l    equ     cst0&0ffff(16)        .lower 16 bits of cst address
cst0u    equ     cst0-cst0l            .upper 16 bits of cst address
.
os_type  vfd,64  0                     .Operating mode
os_terms vfd,8   0                     .170 termination status (0=running,
         vfd,48  0                     .  1=mode error, 2=fatal due)
syskcb_p vfd,48  0ffff80000000(16)     .Pointer to system keypoint control block
act_kpc  vfd,8   0                     .Active keypoint count (software only)
multpro  vfd,8   0                     .TRUE if dualstate.
jkcb_off vfd,32  0                     .Offset in JCB to job KCB pointer
         align   0,8
nosjps   vfd,64  0                     .JPS of NOS170 if Dual State active.
nosexit  vfd,64  0                     .Time of last exit from NOS170.
eicb_pva vfd,4,12,32    1,snnosmtr,0   .Contains PVA of EICB
bct_pva  vfd,4,12,32    1,snnosmtr,bctadr   .Contains PVA of Boot Control Table
nossf    vfd,4,12,32    1,snsfmtr,0    .Contains PVA of NOS stack
nosxp    address r,a170_xp             .Contains PVA of NOS XP
nossegt  address r,a170_st             .Pointer to NOS segment table ..
         vfd,32,32,32  a170_stl*8,0,8  .  ... rest of adaptable pointer to seg table.
.
mlist    vfd,16    00100(16)           .memory_link_status.
         align   0,8
ve_vrsn  vfd,32,14,6,6,6  ost$psr,0,ost$nve,if_versn,if_level  .psr lvl, OS type, i/f version and level
eiflag   vfd,64  0fffffffffffff(16)    .EXTERNAL INTERRUPT flag
eiinc    vfd,64  1000000               .Rate at which external interrupts must
                                       .be checked for.  NOTE: because of the
                                       .algorithm used, asyninc must not be
                                       .larger than this number.
extiou   vfd,64  1                     .IOU sets this word non-zero when
                                       . sending external interrupt.
asyntime vfd,64  0                     .Time to check async activities.
asyninc  vfd,64  200000                .Rate at which asyn activities are chec.
sitvalue vfd,64  50000                 .Default SIT value.
num_proc vfd,64  1                     .number of processors
mstacklx vfd,64  mstackl               .length of monitor stack.
num_cst  vfd,64  maxcst                .Number of cst tables.
no_stop  vfd,64  0
lockwait vfd,64  0                     .Total time spent waiting for dual CPU interlock.

.        Define interrupt ports for IOU external interrupts.  This is a mask with bit
.        7 being port 0, bit 6 being port 1, bit 5 being port 2, etc.  Currently all
.        non S0 machines interrupt on port 1 (value of 1) and the S0 interrupts on
.        port 2 (value of 4).  The value of this variable is set early in
.        initialization, it is set to the same value as memport.

intport  vfd,8   1                     .Interrupt port mask for IOU external
                                       . interrupts.
         defg    osv$cpus_physically_configured
osv$cpus_physically_configured vfd,8 0
mtrprior vfd,16  708(16)               .Priority of 180 if control is
                                       . given to 170 via trap in 180 monitor.
multipos vfd,8   0                     .Nonzero if multiprocessing possible without
                                       . a deadstart.
         align   0,16
a170_xp  bssz    xpsize
a170_st  bssz    a170_stl*8
osv_bl   bssz    32                    .osv$build_level
nostime  vfd,64  0                     .Total time spent in NOS.
mmtime   vfd,64  0ffffffffffff(16)     .Time to call Memory Manager.
scbtime  vfd,64  0                     .Time to check SCB status.
alltime  vfd,64  0ffffffffffff(16)     .max time for async lock set
mmretrn  vfd,64  0                     .re_ran nos in monitor mode.
cpu1nos  vfd,8   0                     .CPU 1 dedicated to NOS.
haltring vfd,8   0                     .Halt CP on MCR fault <= this number.
asylock  vfd,8   0                     .asynchronous interrupt lock.
asylocki vfd,8   0                     .asynchronous interrupt lock for STEP.
rlock1   vfd,8   0                     .Recovery lock level 1
rlock2   vfd,8   0                     .Recovery lock level 2.
rlock3   vfd,8   0                     .Recovery lock level 3.
fltinj   vfd,8   0                     .Enable fault injection utility.
mtvdftb  vfd,48  0ffff80000000(16)     .Pointer to DFT block control_word
nossegp  vfd,4,12,32 1,snnosmtr,0      .Pointer to NOS segment
mtrstp   address r,mst                 .Pointer to MTR SEG TABLE
mtrxpp   address r,mxp                 .pointer to mtr xp
endtbls  vfd,16,32,64 0ffff(16),080000000(16),0 .Pointer to mainframe wired heap.
         align     0,8
debug0   vfd,1024  0                   .Array of debug values
.
.
.         The following is a cybil record.  Immediately after deadstart
.         the NOS system time and date and the free running clock value
.         are saved in this record.  During deadstart initialization these
.         values are converted to NOS/VE base system time.
.
         align   0,8
nos_tod  vfd,64  55333357333357333357(8) .NOS time of day (60 bits of display code)
nos_date vfd,64  55433450334350343657(8) .NOS date (60 bits of display code)
cor_frc  vfd,48  0                     .Free running clock corresponding to 'nos_tod'
nosve_bt bss     0                     .NOS/VE base time
nosve_sc vfd,8   0                     .Second
nosve_mn vfd,8   0                     .Minute
nosve_hr vfd,8   0                     .Hour
nosve_da vfd,8   0                     .Day
nosve_mo vfd,8   0                     .Month
nosve_yr vfd,16  0                     .Year
nosve_cf vfd,48  0                     .Corresponding free running clock
.
.         Define symbols to reference NOS date and time in NOS's field length.
.
nostod   equ     3421(8)               .NOS time of day address mask
nosdate  equ     1221(8)               .NOS date address mask
.
.        End of base system time record.
         align   0,8
tracesiz equ     256                   .Number of trace entries per processor
                                       . (must be power of 2.
                                       . WARNING - TRACE macro must be changed
                                       . if TRACESIZ is changed.
dtrace   bss     0                     .Dummy trace buffer.
trace    bssz    8*maxcst*(2+tracesiz) .Array to keep trace information
                                       .  of what happens in monitor. See
                                       .  the XTRACE macro.
xpinitv  bss     xpsize                .Initial value for all job mode
.                                       exchange packages.
initmxp  bss     xpsize                .initial value of mtr xp.
.
.
.   Error mesasages displayed on error stop.
.
fatalucr  vfd,248   c'FATAL MTR UCR                  '
fatalmcr  vfd,248   c'FATAL MTR MCR                  '
csthalt   vfd,248   c'HALTED VIA CST REQUEST         '
stubcall  vfd,248   c'CALL TO MONITOR STUB           '
          page
.      Set up the NOS XP.
.
.  Initialize the NOS170 Exchange Package
.
.
         ref     mtp$170_trap_handler
a170xpin bss     0
         xpa     a170_xp,2,mtp$170_trap_handler
         xpareg  a170_xp,a_tos,nil
         xpareg  a170_xp,a_csf,nil
         xpareg  a170_xp,a_psa,nil
         xpv     a170_xp,a_bindin*8+10,01000(16)+snsf170,16
         xpareg  a170_xp,a_plist,nil
         xpareg  a170_xp,5,nil
         xpareg  a170_xp,6,nil
         xpareg  a170_xp,7,nil
         xpareg  a170_xp,8,nil
         xpareg  a170_xp,9,nil
         xpareg  a170_xp,10,nil
         xpareg  a170_xp,11,nil
         xpareg  a170_xp,12,nil
         xpareg  a170_xp,13,nil
         xpareg  a170_xp,14,nil
         xpareg  a170_xp,15,nil
         xpv     a170_xp,xpstl,a170_stl,16
         xpv     a170_xp,xpmm,0fbfc(16),16
         xpv     a170_xp,xpum,0ff7f(16),16
         xpv     a170_xp,xpkm,0ffff(16),16
         xpv     a170_xp,xppit,0000f(16),16
         xpv     a170_xp,xppit+8,04240(16),16
         xpv     a170_xp,xplrn,1,16
         xpv     a170_xp,xpflgte,00002(16),16
.
         org     a170_st+snnos170*8
nosste   vfd,64  09a11ffff00000000(16) .STE for NOS
         org     a170_st+snsf170*8
nsfste   vfd,64  0ca13000000000000(16) .STE for NOS stack
. The NOS stack segment will be in the NOS/VE job mode address space
. and known as the SSR segment. The STE is initially defined here
. to be cache bypass, nonexecutable, read and write uncontrolled
. with ring 1 = 1 and ring 2 = 3, the asid will be computed.
         org     a170xpin
.
. Define the SMU Communications Block (SCB)
.
         align   0,8
scb      bss     scbsize               .SCB communication area.
.
mtv$idle_message_line bss 0            .message written to line 1 of console
         vfd,8,8 0,1                   .y position on console
         vfd,8,8 0,0                   .length
         vfd,32  0                     .rma field
         bss     80                    .text of message
         bss     6                     .space for pointer

         page
         align   0,32
jxcb     bssz    xcbsize
.   * * * * * * * * warning - dont change the above constant
.                             unless MTMGR is also changed
jst      bssz    jstlen*8
sdtxtbl  bssz    jstlen*sdtxsize
endjcb   equ     $
         xpa     jxcb,2,osp$start
         xpareg  jxcb,a_tos,nil
         xpareg  jxcb,a_csf,nil
         xpareg  jxcb,a_psa,nil
         xpareg  jxcb,a_bindin,bindsec
         xpareg  jxcb,4,nil
         xpareg  jxcb,5,nil
         xpareg  jxcb,6,nil
         xpareg  jxcb,7,nil
         xpareg  jxcb,8,nil
         xpareg  jxcb,9,nil
         xpareg  jxcb,10,nil
         xpareg  jxcb,11,nil
         xpareg  jxcb,12,nil
         xpareg  jxcb,13,nil
         xpareg  jxcb,14,nil
         xpareg  jxcb,15,nil
         xpv     jxcb,xpstal,jst,16    .Segment table address
         xpv     jxcb,xpstl,jstlen-1,16  .Segment table length
         xpv     jxcb,xpflgte,00000(16),16   .Set trap-enable
         xpv     jxcb,xpmm,j_mtrmsk,16
         xpv     jxcb,xpum,j_usrmsk,16
         xpv     jxcb,xpkm,0,16
         xpv     jxcb,xppit,07fff(16),16
         xpv     jxcb,xppit+8,0ffff(16),16
         xpv     jxcb,xplrn,15,16
         xpv     jxcb,xpbc1,0,16          .task_id DIV 10000(16) for $JOBMNTR
         xpv     jxcb,xpbc2,jxcb_off,16   .task_id MOD 10000(16) for $JOBMNTR
         xpa     jxcb,xptp,pr_trap
         xpa     jxcb,xpdlp,nil
         xpa     jxcb,xptos,nil
         org     endjcb
         page
.   Define static data for pseudo job fixed segment
.
jobfix   equ     $
         entp    x1,0
         align   0,8
         defg osp$start
osp$start bss    0
         ente    x0,00d7(16)
         callseg bs_init,a_bindin,a_plist
.
         align   0,32
         defg    jobroot
         defg    sdtxtbl
         defg    jst
jcb      bss     0
jobroot  bssz    jrootsiz              .Job root
         align   0,8
xcblist  vfd,16,32  0ffff(16),080000000(16)
         bssz    32                 .* * * must be as big as a sig lock.
tasktem  vfd,16,32  0ffff(16),080000000(16)
         bssz    12
         align   0,8
         defg    sysjob,keyinp,keylock
         defg    jfheapp
sysjob   alias   JMV$EXECUTING_WITHIN_SYSTEM_JOB
keyinp   alias   JMV$KEYBOARD_BUFFER
KEYLOCK  ALIAS   JMV$KEYBOARD_BUFFER_LOCK
JFHEAPP  ALIAS   OSV$JOB_FIXED_HEAP
keyinp   bssz    56
keylock  bssz    8
jfheapp  vfd,16,32,80 0ffff(16),080000000(16),0
jobtrapp vfd,16,32 0FFFF(16),080000000(16)
         vfd,16,32 0FFFF(16),080000000(16)
logcntl  vfd,16,32 0FFFF(16),080000000(16)
sfcntl   vfd,16,32 0FFFF(16),080000000(16)
         bssz    12
sysjob   vfd,8   1
.
.
.  Define fields in the Job Root
.
         defg    jcb
jcb      alias   jmv$jcb
sdtxtbl  alias   JMV$SDTX
         defg    jst
jst      alias   jmv$sdt
         defg    jxcb
jxcb     alias   JMV$JMTR_XCB
jxcb_off equ     #BOFF(jxcb)
         defg    xcblist
xcblist  alias   JOB_XCB_LIST
         defg    tasktem
tasktem  alias   PMV$TASK_TEMPLATE
         defg    jobtrapp
jobtrapp ALIAS   JMV$JOB_TRAP_HANDLER
         defg    logcntl
logcntl  alias   LGV$LOCAL_LOG_CNTL_P
         defg    sfcntl
sfcntl   alias   SFV$LOCAL_ROUTING_CONTROL_TABLE
         ref     jbegin
jbegin   alias   osp$initialize
         page
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. TRAKTEF - This macro enables/disables the MCR mask bit 49
.           (normally unused) to indicate to THETA models 40 - 44
.           what the current state of the trap register is.  This
.           is used as a software workaround for 'stop on error'
.           hardware found only on the THETA processor models
.           listed above.  On other models this information is
.           not used, even though the flag is tracked.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
         proc
traktef  pname
f:(0)    bss     0
         local   tf1,tf2
         ente    x3,f:(2,0)            .Enable or Disable?
         ente    x2,m_mcrtef
         entl    x0,r_mm               .Get live register for mtr mask
         cpysx   x1,x0
         brxeq   x3,x0,tf1             .Branch to clear Trap enable flag
         iorx    x1,x2                 .Set the Traps_Enabled bit in the live
         brxeq   x0,x0,tf2             .  mtr mask
tf1      inhx    x1,x2                 .Clear the Traps_Enabled bit in the live
tf2      cpyxs   x1,x0                 .  mtr mask
         bss     0
         pend
.............................................................................
.
.      Set up the request table for the various requests.
.
.
.  RQTABLE -  This macro generates monitor request table entries,
.             and binding section pointers. it also increments *MTRQMAX*
.             to indicate the maximum number of requests.
.
.                RQTABLE  REC_CODE,HRN,INT_ORD,NAME
.                  req_code = request code.
.                  hrn      = highest ring number for call.
.                  int_ord  = interlock ordinal.
.                  name     = procedure name to process request.
.
         proc
rqtable  pname
         vfd,8   f:(2,1)               .Highest ring number for the call
         vfd,8   f:(2,2)               .Interlock ordinal
         vfd,8   f:(2,0)               .Request code
         vfd,40  0
         vfd,64  0
         vfd,32  0
         vfd,32  0
         vfd,32  0
         vfd,32  0
         vfd,64  0
mtrqmax  set     mtrqmax+1
         do      f:(2,2)>maxilo
maxilo   set     f:(2,2)
         dend
         use     binding
         do      sc:(f:(2,3))/=7
         ref     f:(2,3)
         dend
         address ce,f:(2,3)
         use     #lastsec
         pend
.
.   initialize maximum requests to -1.
.
mtrqmax  set     -1
maxilo   set     0
         page
.....................................................................
.
.   Define Binding Section
.
.   define fwa of binding section and reqtable pointers.
....................................................................
         use     binding
         def     bindsec
bindsec  bss     0
bs_rqtbl bss     0
         use     #lastsec
         page
...............................................................................
. NOTE: If the highest interlock ordinal value is changed
. (parameter 3 in the macro calls below), be sure to change the
. constant value MTC$MAXIMUM_IL_TABLE_INDEX in the deck
. MTT$REQUEST_INTERLOCK_TABLE to match it.
...............................................................................
         align   0,8
reqtbl   bss     0
         rqtable 0,15,1,tmp$process_unknown_req_fault
         rqtable 1,13,0,tmp$cycle
         rqtable 2,13,0,tmp$delay
         rqtable 3,3,1,tmp$process_unknown_req_fault
         rqtable 4,1,1,iop$io_processor
         rqtable 5,13,1,tmp$process_unknown_req_fault
         rqtable 6,13,1,tmp$process_unknown_req_fault
         rqtable 7,13,1,tmp$process_unknown_req_fault
         rqtable 8,2,1,tmp$process_unknown_req_fault
         rqtable 9,0,1,pr_pf
         rqtable 10,2,1,tmp$process_unknown_req_fault
         rqtable 11,2,1,osp$boot_update_page_table
         rqtable 12,13,1,tmp$process_unknown_req_fault
         rqtable 13,13,1,tmp$process_unknown_req_fault
         rqtable 14,1,1,tmp$process_unknown_req_fault
         rqtable 15,2,1,tmp$process_unknown_req_fault
         rqtable 16,1,1,tmp$process_unknown_req_fault
         rqtable 17,3,1,tmp$process_unknown_req_fault
         rqtable 18,3,1,tmp$process_unknown_req_fault
         rqtable 19,3,0,mtp$mtr_step_unstep_system
         rqtable 20,0,1,tmp$process_task_mcr_fault
         rqtable 21,15,1,tmp$mtr_process_system_error
         rqtable 22,3,0,tmp$process_unknown_req_fault
         rqtable 23,3,1,tmp$process_unknown_req_fault
         rqtable 24,3,1,tmp$process_unknown_req_fault
         rqtable 25,13,0,tmp$process_unknown_req_fault
         rqtable 26,3,0,tmp$process_unknown_req_fault
         rqtable 27,15,0,tmp$process_unknown_req_fault
         rqtable 28,2,1,tmp$process_unknown_req_fault
         rqtable 29,3,1,tmp$process_unknown_req_fault
         rqtable 30,13,1,tmp$process_unknown_req_fault
         rqtable 31,6,1,tmp$process_unknown_req_fault
         rqtable 32,3,1,tmp$process_unknown_req_fault
         rqtable 33,1,1,tmp$process_unknown_req_fault
         rqtable 34,2,1,tmp$process_unknown_req_fault
         rqtable 35,3,0,tmp$process_unknown_req_fault
         rqtable 36,3,0,tmp$process_unknown_req_fault
         rqtable 37,11,1,tmp$process_unknown_req_fault
         rqtable 38,13,1,tmp$process_unknown_req_fault
         rqtable 39,13,1,tmp$process_unknown_req_fault
         rqtable 40,13,1,tmp$process_unknown_req_fault
         rqtable 41,1,1,tmp$process_unknown_req_fault
         rqtable 42,1,1,tmp$process_unknown_req_fault
         rqtable 43,1,1,tmp$process_unknown_req_fault
         rqtable 44,1,1,iop$tape_queue_request
         rqtable 45,1,1,tmp$process_unknown_req_fault
         rqtable 46,3,1,cmp$monitor_routines
         rqtable 47,3,1,tmp$process_unknown_req_fault
         rqtable 48,13,1,tmp$process_unknown_req_fault
         rqtable 49,3,1,dsp$issue_dft_request
         rqtable 50,13,1,tmp$process_unknown_req_fault
         rqtable 51,0,0,tmp$switch_task
         rqtable 52,0,0,mtp$process_short_warning
         rqtable 53,0,0,mtp$monitor_system_status
         rqtable 54,0,1,iop$process_io_completions
         rqtable 55,3,0,dpp$display_request
         rqtable 56,0,0,dpp$process_scd_block
         rqtable 57,3,1,tmp$process_unknown_req_fault
         rqtable 58,0,1,tmp$process_unknown_req_fault
         rqtable 59,0,0,mtp$process_due
         rqtable 60,0,0,mtp$initiate_system_idle
         rqtable 61,15,1,tmp$process_unknown_req_fault
         rqtable 62,0,0,mtp$process_170_mtr_requests
         rqtable 63,0,0,mtp$error_stop
         rqtable 64,1,1,tmp$process_unknown_req_fault
         rqtable 65,3,0,dsp$access_logging_data
         rqtable 66,0,0,dsp$process_dft_entry
         rqtable 67,15,1,tmp$process_unknown_req_fault
         rqtable 68,15,1,tmp$process_unknown_req_fault
         rqtable 69,15,1,tmp$process_unknown_req_fault
         rqtable 70,15,1,tmp$process_unknown_req_fault
         rqtable 71,15,1,tmp$process_unknown_req_fault
         rqtable 72,15,1,tmp$process_unknown_req_fault
         rqtable 73,15,1,tmp$process_unknown_req_fault
         rqtable 74,15,1,tmp$process_unknown_req_fault
         rqtable 75,15,1,tmp$process_unknown_req_fault
         rqtable 76,15,1,tmp$process_unknown_req_fault
         rqtable 77,15,1,tmp$process_unknown_req_fault
         rqtable 78,15,1,tmp$process_unknown_req_fault
         rqtable 79,15,1,tmp$process_unknown_req_fault
         rqtable 80,3,1,dsp$mtr_manage_system_ds_status
         page
         use     binding
bs_pgflt address ce,osp$process_mtr_page_fault
.
pr_errst ALIAS   MTP$ERROR_STOP
pr_dft   ALIAS   DSP$PROCESS_DFT_ENTRY
         ref     pr_dft
         ref     ptllock
         ref     pr_errst
         def     bs_trap
.
bs_trap  address ce,traprtn
bs_errst address c,pr_errst
bs_root  address p,root
bs_ptlok address p,ptllock
.
.................................................................
.   Define Binding Section for job mode boot XP
.
         def     pr_trap
         ref     jpstraprtn
pr_trap  address ce,jpstraprtn
bs_init  address ce,jbegin
.
jpstraprtn ALIAS SYP$SYSTEM_CORE_TRAP_HANDLER
         use     #lastsec
         page
.
.      Define the interlock words.  Initially only one lock word
.      is used by the various request processors.
.
.
         align   0,8
il_tbl   bssz    maxilo*3*8            .Interlock word
         page
         defg    haltring
         defg    scbtime,mmtime,nostime
         defg    alltime,cpu1nos
         defg    sitvalue,fltinj
         defg    dpv$scd_block_p,mtv$idle_message_line
         defg    dpv$scd_time
         defg    extiou
         defg    mtrprior
         defg    endtbls,memlimit,cst0
         defg    xpinitv,os_type,scb,os_terms
         defg    trace,nosjps,nosxp,eicb_pva,bct_pva,nossegp,dtrace
         defg    syskcb_p,act_kpc,jkcb_off
         defg    nosve_bt,nos_tod,mlist
         defg    reqtbl
         def     il_tbl
         defg    multpro
         defg    no_stop
         defg    eiflag
         defg    lockwait
         defg    rlock1
         defg    rlock2
         defg    rlock3
         defg    debug0
         defg    intport
         defg    asyntime,asyntime
         defg    num_proc
         defg    initmxp
         defg    osv_bl
         def     int
         def     nossegt
initmxp  ALIAS   OSV$INITIAL_MONITOR_XP
fltinj   ALIAS   syv$enable_fault_injection
         defg    num_cst,multipos
         defg    mstacklx
         defg    mtvdftb
mstacklx ALIAS   osv$monitor_stack_length
num_cst  ALIAS   osv$maximum_cst_tables
num_proc ALIAS   osv$number_of_processors
multipos ALIAS   osv$multiple_processors
lockwait ALIAS   osv$monitor_interlock_wait_time
ptllock  ALIAS   TMV$PTL_LOCK
eiflag   ALIAS   osv$external_interrupt_time
intport  ALIAS   osv$external_interrupt_selector
asyntime ALIAS   OSV$TIME_TO_CHECK_ASYN
asyninc  ALIAS   OSV$RATE_TO_CHECK_ASYN
multpro  ALIAS   OSV$MULTI_PROCESSOR
debug0   ALIAS   osv$debug
mtrprior ALIAS   OSV$MONITOR_PRIORITY
reqtbl   ALIAS   MTV$REQUEST_TABLE
il_tbl   ALIAS   mtv$request_interlock_table
nosjps   ALIAS   MTV$NOS_JPS
sitvalue ALIAS   OSV$DEFAULT_SIT_VALUE
no_stop  ALIAS   mtv$no_stop
os_type  ALIAS   OSV$170_OS_TYPE
os_terms ALIAS   OSV$170_OS_TERMINATION_STATUS
nossegp  ALIAS   MTV$NOS_SEG_P
nostime  ALIAS   MTV$TOTAL_NOS_CPU_TIME
haltring ALIAS   MTV$HALT_CPU_RING_NUMBER
extiou   ALIAS   OSV$IOU_EXTERNAL_INTERRUPT
mtvdftb  ALIAS   mtv$dft_block_p
scb      ALIAS   MTV$SCB
nosxp    ALIAS   MTV$NS_XP_P
eicb_pva ALIAS   MTV$NST_P
bct_pva  ALIAS   DSV$BOOT_CONTROL_TABLE_P
nossegt  ALIAS   MTV$NOS_SEGMENT_TABLE_P
rlock1   ALIAS   MTV$RECOVERY_LOCK1
rlock2   ALIAS   MTV$RECOVERY_LOCK2
rlock3   ALIAS   MTV$RECOVERY_LOCK3
dtrace   ALIAS   MTV$DUMMY_TRACE_BUFFER
trace    ALIAS   MTV$TRACE_BUFFER
osv_bl   ALIAS   osv$build_level
ENDTBLS  ALIAS   OSV$MAINFRAME_WIRED_HEAP
memlimit ALIAS   OSV$180_MEMORY_LIMITS
MMTIME   ALIAS   MMV$TIME_TO_CALL_MEM_MGR
scbtime  ALIAS   MTV$TIME_TO_CHECK_SCB_STATUS
alltime  ALIAS   MTV$MAX_ASYNC_LOCK_TIME
cpu1nos  ALIAS   MTV$CPU1_DEDICATED_TO_NOS
CST0     ALIAS   MTV$CST0
XPINITV  ALIAS   MTV$XP_INITIAL_VALUE
syskcb_p ALIAS   SYV$SYSTEM_KCB_P
act_kpc  ALIAS   SYV$ACTIVE_KEYPOINT_COUNT
jkcb_off ALIAS   SYV$JOB_KCB_P_OFFSET
ROOT     ALIAS   MTV$ROOT
BEGIN    ALIAS   MTP$BEGIN
TRAPRTN  ALIAS   MTP$TRAP_HANDLER
BINDSEC  ALIAS   MTV$BINDING_SECTION
BS_TRAP  ALIAS   MTV$TRAP_CBP
NOSVE_BT ALIAS   OSV$BASE_SYSTEM_TIME
NOS_TOD  ALIAS   SYV$NOS_SYSTEM_TIME
MLIST    ALIAS   MTV$MLI_STATUS
         page

         align   0,2
boot75   bss     0
         sx      x6,a_root,free_rma
         la      af,a_root,jstkpva
         la      ae,a_root,sadxcbp
         sa      af,ae,8+2             .store proper PVA into initial job mode XP.dsp
         sa      af,ae,8+8+2           .store proper PVA into initial job mode XP.csf
         sa      af,ae,xptos           .store proper PVA into initial job mode XP.tosr1
.
         la      ae,a_root,sadjcbp     .init jcb pointer
         sa      ae,a_cst,jcbp
         la      a_xcb,a_root,sadxcbp  .init xcb pointer
         sa      a_xcb,a_cst,xcbp
         la      af,a_root,sadjsdt     .init job mode sta
         tpage   x1,af
         sbyts,2 x1,a_xcb,x0,xpstal    .lower 16
         shfx    x1,x1,x0,-16
         sbyts,2 x1,a_xcb,x0,xpstau    .upper 16 bits
         la      ae,a_root,sadmsdt     .copy mtr sdt to job mode
         movb,ae,x0 af,x1 0,9,8*15(16),0 0,9,8*15(16),0
         tpage   x1,a_xcb              .Save RMA of XCB in CST.
         sx      x1,a_cst,xcbrma
         entl    x0,r_jps              .Update JPS.
         cpyxs   x1,x0
.
         entl    x0,r_eid              .Get element ID
         cpysx   x1,x0
         sx      x1,a_cst,elem_id      .Save EID in CST.
.
.        IF THIS IS CYBER 2000,
.        Clear the monitor mode monitor mask bit 48 of the job mode monitor
.        mask bit 48 of the job exchange package.
.
         isob    x1,x1,x0,(40*64+7)    .High order 7 bits of model number from
                                       . element id.
         ente    x2,46(16)             .CYBER 2000 Model 46
         brreq   x1,x2,begin2_1
         incx    x2,2                  .CYBER 2000 Model 48
         brreq   x1,x2,begin2_1
         brxeq   x0,x0,begin2_2
begin2_1 lbyts,2 x1,a_xcb,x0,xpmm
         ente    x2,m_mcrdue           .Remove DUE bit (48) from MM
         inhx    x1,x2
         sbyts,2 x1,a_xcb,x0,xpmm
         entl    x0,r_mm
         cpyxs   x1,x0                 .Replace MM in register
         la      ac,a_root,mtrxpp
         lbyts,2 x1,ac,x0,xpmm
         sbyts,2 x1,ac,x0,xpmm         . and monitor XP
begin2_2 entp    x0,0                  .start cache and map purging
         sx      x0,a_cst,cachtim
         sx      x0,a_cst,maptim
         tpage   x1,a7                 .Store MPS into CST.
         sbyts,4 x1,a_cst,x0,mps
         la      ad,a_root,eicb_pva      .FWA of NOS field length.
         cpytx   x1,x0                 .Reset time task began execution.
         entl    x0,r_eid
         sx      x1,a_root,nosexit     .Set time when last exited NOS
         cpysx   xe,x0                 .element id.
         entp    x6,5                  .high order 4 bits of S0 model number.
         isob    xe,xe,x0,(40*64+3)    .high order 4 bits of model number from
                                       . element id.
         sx      x1,a_root,scb+scbnsrv

.        Set up memory and interrupt port mask based on processor.

         lbyts,1 x1,a_cst,x0,memport   .memory and interrupt port mask for non S0
         brrne   xe,x6,begin2_5        .if not an S0.
         incr    x1,3                  .If S0, change port 0 (int sel = 1) to a 4,
         entp    x2,4                  .  port 1 (int sel = 4) to an 8.
         brxeq   x1,x2,begin2_5        .If cpu 0, then 4 is the right answer,
         entp    x1,8                  .  otherwise 8 is the answer.
begin2_5 bss     0
         sbyts,1 x1,a_cst,x0,memport   .Set up port number mask for ext interrupts.
         sbyts,1 x1,a_root,x0,intport
         lx      xe,a_root,ve_vrsn     .ve os type, dscb version/level
         sx      xe,a_dscb,d8ty        .save in block

.        Set the NOS/VE memory limits.  Both upper bounds are set to the RMA of
.        the SSR.

         lx      x1,a_dscb,d7cm+8      .fetch memory limits
         isob    xe,x1,x0,(64-48)*100(8)+24-1  .NOS/VE fwa DIV 10000(8)
         shfx    xe,xe,x0,12
         sbyts,4 xe,a_root,x0,memlimit .set memory lower bound
         la      ae,a_root,nossf
         tpage   xe,ae
         sbyts,4 xe,a_root,x0,memlimit+4  .set deadstart upper bound to the SSR RMA
         sbyts,4 xe,a_root,x0,memlimit+8  .set upper bound to the SSR RMA
.
         lx      xe,a_dscb,d7ty        .determine STATE
         isob    x1,xe,x0,5605(8)
         sbyts,1 x1,a_root,x0,os_type
         brreq   x1,x0,begin3          .if not dualstate jump
.
.         Save NOS base system time and the corresponding value of the free running clock.
.
         isob    x2,xe,x0,nostod       .isolate time of day pointer
         isob    xe,xe,x0,nosdate      .isolate date pointer
         lxi     x2,ad,x2,0            .time of day (display code)
         lxi     xe,ad,xe,0            .date (display code)
         cpytx   x1,x0                 .Free running clock
         sx      x2,a_root,nos_tod
         sx      xe,a_root,nos_date
         ente    x2,cor_frc
         sbyts,6 x1,a_root,x2,0
         addaq   af,a_root,a170_xp
         entp    x2,0                  .Clear left halt of nosjps
         tpage   x2,af
         sx      x2,a_root,nosjps
         sbyts,4 x2,a_cst,x0,dualstat
         addaq   ae,a_root,a170_st     .Store upper bits of nos seg table adr.
         tpage   x2,ae
         sbyts,2 x2,af,x0,xpstal
         shfx    x2,x2,x0,-16
         sbyts,2 x2,af,x0,xpstau
         la      af,a_root,mtrstp      .Set entry for MNFR WIRED SEG in NOS ST
         cpyax   x1,a_root             .a_root is mnfr wired segment
         isob    x1,x1,x0,2413(8)      .isolate segment number
         shfx    x1,x1,x0,3            .make sdt number
         lbyts,8 x2,af,x1,0            .get sdt entry
         sbyts,8 x2,ae,x1,0            .set sdt entry in nos st
         brcr    5,1,begin4            .Force EXCH bit
         brreq   x0,x0,begin4
.
begin3   isom    x1,x0,2020(8),x0      .Set NOS XP pointer to NIL
         sbyts,6 x1,a_root,x0,nosxp
.
.        Clear the monitor mode monitor mask bit 49 of the monitor
.        exchange package and bit 49 in the monitor mask register.
.
begin4   traktef 0                     .NO-OP; trap bit already disabled
         cpyxx   x6,x2                 .  X2 = m_mcrtef
                                       .  Use reg to clear mtr mask
         addaq   af,a_root,xpinitv     .Save the job exchange package
         movb,a_xcb,x0 af,x1 0,9,255,0 0,9,255,0
         movb,a_xcb,x0 af,x1 0,9,xpsize-255,255 0,9,xpsize-255,255
         la      ae,a_root,mtrxpp      .move original xp to
         addaq   af,a_root,initmxp     .mainframe wired.
         lbyts,2 x1,ae,x0,xpmm         .Get the mtr mask in the mtr xp
         inhx    x1,x6                 .Inhibit tef bit
         sbyts,2 x1,ae,x0,xpmm         .Store mtr mask in the mtr xp
         movb,ae,x0 af,x1 0,9,255,0 0,9,255,0
         movb,ae,x0 af,x1 0,9,xpsize-255,255 0,9,xpsize-255,255
         entl    x0,r_jps              .Save current JPS in CST.
         cpysx   x0,x0
         sx      x0,a_cst,xcbrma
         brxeq   x0,x0,begin22
.
.    The following code is initialization code for all cpus EXCEPT the first.
.
begin5   bss     0
         la      a_dscb,a_root,eicb_pva  .Pointer to interface block
         isom    x1,x0,2020(8),x0
         sbyts,6 x1,a_cst,x0,xcbp      .nill xcb pointer.
         entp    x1,1
         sbyts,1  x1,a_cst,x0,caldisp  .call dispatcher.
.
.    Complete processor initialization for ALL processors.
.
begin22  lx      x1,a_root,sitvalue    .Reset SIT.
         entl    x0,r_sit
         cpyxs   x1,x0
         entp    x0,0
         sbyts,1 x0,a_cst,x0,cpu_stat  .set cpu status running
         entl    x0,r_te               .Enable traps
         cpyxs   x0,x0
         page
.
.   Dispatch next task
.
intdislp bss     0                     .Begin of interrupt-dispatch-loop.
         entl    x0,r_pit              .Save monitor clock.
         cpysx   x_clock,x0
.
.  Process asynchronous interrupts (EXT INT, Console input, Memory mgr)
.
async    entl    x0,0                  .Check if time to check async
         cpytx   x2,x0                 .  activities.
         sbyts,1 x0,a_cst,x0,asyncp
         sx      x2,a_cst,cpwell       .Update cpu alive flag.
         sx      x2,a_root,scb+scbnsrv .Update '180 alive' flag.
         lx      x1,a_root,asyntime
         brxge   x1,x2,asynce          .Jump if not time.
         addaq   ae,a_root,asylock
         lbset   x1,ae,x0              .test and set lock
         brrgt   x1,x0,asynce          .jump if another processor here
 .
         lx      x1,a_root,asyninc     .Update time to next check async.
         addx    x1,x2
         sx      x1,a_root,asyntime
         lx      x1,a_root,eiflag
         brxgt   x1,x2,async6          .jump if not time
         lx      x1,a_root,eiinc
         addx    x1,x2
         sx      x1,a_root,eiflag
         entl    x0,0
         sx      x0,a_root,extiou
         cpyaa   a_parm,a0
         addpxq  a_rq_ret,x0,async6    .set return address.
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*proc_io
         addaq   ae,a_bindin,16*proc_io
         brreq   x0,x0,rqproc
async6   lx      x1,a_root,dpv$scd_time
         brxgt   x1,x2,async8          .jump if not time
         addpxq  a_rq_ret,x0,async12   .set return address.
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*ascii_kb
         addaq   ae,a_bindin,16*ascii_kb
         brreq   x0,x0,rqproc
.
async8   la      ae,a_root,mtvdftb     .Fetch pointer to DFT block.
         lx      x1,ae,dftcw           .Get DFT control word.
         shfx    x1,x1,x0,62           .Check E8 field.
         brxge   x1,x0,async12         .jump if not set.
         addpxq  a_rq_ret,x0,async12   .set return address.
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*proc_dft
         addaq   ae,a_bindin,16*proc_dft
         brreq   x0,x0,rqproc
.
async12  lx      x1,a_root,scbtime     .Check if time to look at SCB status.
         entp    x2,0
         cpytx   x2,x2
         brxge   x1,x2,async15         .Jump if SCB check not required.
         cpyaa   a_parm,a_csf          .Save parameter list
         addpxq  a_rq_ret,x0,async14   .set return address.
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*mon_smu
         addaq   ae,a_bindin,16*mon_smu
         brreq   x0,x0,rqproc
         cpyaa   a_parm,a0             .Restore previous parameter list
async14  entp    x2,0
         cpytx   x2,x2
async15  lx      x1,a_root,mmtime      .Check if time to call Mem Mgr.
         brxge   x1,x2,async50         .Jump if Mem Mgr call not needed.
         addpxq  a_rq_ret,x0,async50   .set return address.
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*per_call
         addaq   ae,a_bindin,16*per_call
         brreq   x0,x0,rqproc
async50  addaq   ae,a_root,asylock
         entl    x0,0
         sbyts,1 x0,ae,x0,0            .clear lock
         brreq   x0,x0,async           .check for more before exiting
asynce   lx      x1,a_cst,discntl      .get dispatch control flags.
.
.  Call the task switch routine if necessary.
.
         shfx    x1,x1,x0,-32          .Check dispatch flag.
         brxeq   x1,x0,tsckpr          .Jump if task switch not needed.
         lx      x1,a_cst,discntl      .Make sure async flags are not set.
         brrne   x1,x0,tsckpr
         la      a_xcb,a_cst,xcbp
         cpyax   x1,a_xcb               .Check for NIL xcb
         entl    x0,0
         brrgt   x0,x1,tswit4
         lbyts,2 x1,a_xcb,x0,xppit     .Calculate JOB MODE time
         lbyts,2 x2,a_xcb,x0,xppit+8
         insb    x2,x1,x0,4017(8)
         ents    x2                    .sign extend
         lx      x1,a_cst,jtime
         subx    x1,x2
         sx      x1,a_cst,jtime
         isom    x1,x0,4037(8)         .Save monitor mode time in CST.
         subx    x1,x_clock
         sx      x1,a_cst,mtime
tswit4   addpxq  a_rq_ret,x0,tswit5    .set return address.
         cpyaa   a_parm,a_csf
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*tsksw
         addaq   ae,a_bindin,16*tsksw
         brreq   x0,x0,rqproc
tswit5   isom    x_clock,x0,4037(8)    .Reset monitor clock.
         entl    x0,r_sit              .Reset SIT.
         lx      x1,a_cst,cptime
         cpyxs   x1,x0
         entl    x0,0                  .Reset CST fields -
         sbyts,4 x0,a_cst,x0,discntl   .Clear task switch control flags.
         sx      x0,a_cst,mtime        .  monitor mode time
         la      a_xcb,a_cst,xcbp      .Reload pointer to current XCB.
         cpyax   x1,a_xcb              .Skip next part if XCB is NIL.
         brrgt   x0,x1,tswit8
         lbyts,2 x1,a_xcb,x0,xppit     .Reset JOB MODE time
         lbyts,2 x2,a_xcb,x0,xppit+8
         insb    x2,x1,x0,4017(8)
         ents    x2                    .sign extend
         sx      x2,a_cst,jtime
         tpage   x1,a_xcb              .Save RMA of XCB in CST.
         sx      x1,a_cst,xcbrma
         entl    x0,r_jps                 .Update JPS.
         cpyxs   x1,x0
tswit8   xtrace  5,x1,xe,xd,ae
.
.  Run NOS 170 if it has a priority greater than 180 has.
.
tsckpr   lbyts,2 xe,a_cst,x0,dsprior   .Update 180 priority in DSCB.
         lx      x1,a_cst,discntl      .Get dispatch flags.
         brxne   x1,x0,async           .Cycle loop if flags are set.
         lbyts,1 x1,a_cst,x0,lpid8     .get cpu index
         lbyts,2 x1,a_dscb,x1,np170pr  .Get 170 priority.
         shfc    x2,xe,x0,-4           .Shift off sub priority.
         shfc    x1,x1,x0,-4
         brrgt   x2,x1,async90         .Run 180 if 180pr>170pr.
         brrne   x2,x1,tsckpr3         .Run 170 if 170pr > 180 pr.
         brreq   x2,x0,idle            .Go to idle routine if 180pr = 0.
         isob    x2,x2,x0,0003(8)      .Isolate 180 subpriority.
         entl    x0,0                  .Read the free running clock to calculate
         cpytx   x0,x0                 .  the 170 subpriority.
         isob    x1,x0,x0,5603(8)
         brxgt   x2,x1,async90         .Jump if 180 has highest priority.
tsckpr3  addpxq  a_inret,x0,tsckpr5    .Set up return address and
         brxeq   x0,x0,run_nos         .  run NOS 170.
tsckpr5  entl    x0,r_te               .Enable traps.
         cpyxs   x0,x0
         lbyts,1 x2,a_cst,x0,dsprior   .Run user task if system not idle.
         brxne   x2,x0,async90
         lx      x1,a_cst,discntl       .Cycle the loop if task switch/async.
         brxne   x1,x0,async
.
.  Idle if no 180 task was found ready.
.
idle     entl    x0,r_td               .Disable traps
         cpyxs   x0,x0
         entp    xe,0                  .Set 180 priority
         addpxq  a_inret,x0,idle3      .Idle in NOS 170 if present.
         brxeq   x0,x0,run_nos
idle3    lbyts,1 x1,a_cst,x0,nextstat
         brxne   x1,x0,idle4           .branch to main idle loop
         sbyts,1 x1,a_cst,x0,cpu_stat  .store haltreq into cpu_stat
idle4    addpxq  a_extret,x0,idle3
         brcr    8,0,extrq             .branch if EXT INT is set
         lbyts,1 x1,a_cst,x0,cpu_stat
         brxne   x1,x0,idle3           .loop if haltreq set
         lx      x1,a_cst,discntl      .exit when flags are set
         brxne   x1,x0,idle10
         addpxq  a_sitret,x0,idle3
         brcr    11,0,prsit            .jump if SIT is set
         entp    x1,1
         sbyts,1 x1,a_cst,x0,caldisp
.
idle10   lx      x1,a_root,sitvalue    .Put big number in SIT to reduce
         entl    x0,r_sit              . likelyhood of unnecessary SIT.
         cpyxs   x1,x0
         entl    x0,r_te               .exit idle routine
         cpyxs   x0,x0
         brxeq   x0,x0,async
.
.  Reload PIT for current 180 task.
.
async90  entl    x0,r_pit              .Reload monitor clock (PIT).
         cpyxs   x_clock,x0
.
.   End of task switch loop.
         page
...............   beginning of critical region ............
.
.               CRITICAL REGION - between labels BCRIT1 and ECRIT1
.
.   If any changes are made in thie following code,
.   be sure to look at the code at the begining of the trap handler.
.   Under certain circumstances, P will be reset to the beginning
.   of the critical region.
.
.
BCRIT1   bss     0
exchloop bss     0
         lx      x1,a_cst,discntl      .Check for task switch or async
         brxne   x1,x0,intdislp        . activity. Branch if found.
         xtrace  0,0,x1,x0,ae
         entp    x0,0
         sbyts,2 x0,a_xcb,x0,xpmcr     .Clear user's MCR
         lbyts,2 x1,a_cst,x0,taskid
         shfx    x1,x1,x0,13
         keypoint oscmtr,x1,oskexc8x
ecrit1   exchange
...............   end of critical region ............
.
.
.   Get the MCR from the user XP.
.
         lbyts,2 x_mcr,a_xcb,x0,xpmcr  .Get MCR from user XP
         xtrace  1,x_mcr,x1,x0,ae      .Save MCR in trace buffer.
         shfx    x1,x_mcr,x0,13        .Keypoint MCR.
         keypoint oscmtr,x1,oskexc8
         histo   x_mcr,a_root,tabmcrj,xe,xf
.
.
.  Special case an MCR of EXCH ONLY. This is the most frequent interrupt.
.  In EXCH is set and other bits are set as well, the EXCH will be handled
.  later.
.
         ente    x1,m_mcrexc           .Check for only EXCH set.
         brxne   x1,x_mcr,ckhdw        .Jump if not EXCH only.
         entl    x0,r_pit              .Stop the clock.
         cpysx   x_clock,x0
         ente    xe,#boff(a170_xp)
         sbyts,2 x1,a_root,xe,xpmcr
         addpxq  a_inret,x0,ckexsp5    .Set up return address.
         lbyts,2 xe,a_cst,x0,dsprior   .Get current 180 priority.
         brxeq   x0,x0,run_nos         .Go run NOS 170.
ckexsp5  entl    x0,r_pit              .Start monitor clock.
         cpyxs   x_clock,x0
         entl    x0,r_te               .Enable traps.
         cpyxs   x0,x0
         brxeq   x0,x0,exchloop
.
.
.   Process hardware errors - (DUE, SHORT WARNING).
.
ckhdw    ente    x1,m_mcrhdw           .Check for hardware errors
         andx    x1,x_mcr
         brreq   x1,x0,ckasync
         shfc    x1,x_mcr,x0,18        .Check for short warning.
         brrge   x1,x0,ckdue           .Jump if no short warning.
         cpyaa   a_parm,a0
         addpxq  a_rq_ret,x0,ckdue     .set return address.
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*pswarn
         addaq   ae,a_bindin,16*pswarn
         brreq   x0,x0,rqproc
ckdue    shfc    x1,x_mcr,x0,16        .Check for DUE.
         brrge   x1,x0,ckasync
         purge   x0,2                  .Purge cache and map.
         purge   x0,15
         entp    x1,0                  .Set up plist
         sx      x1,a_csf,0
         sa      a_xcb,a_csf,18
         cpyaa   a_parm,a_csf
         addpxq  a_rq_ret,x0,ckdue1    .set return address.
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*proc_due
         addaq   ae,a_bindin,16*proc_due
         brreq   x0,x0,rqproc
ckdue1   ente    x_mcr,m_mcrasy        .Force async interrupts since these
.                                       may be invalid because of DUE.
.
.   Process asynchronous interrupts.
.
ckasync  ente    x1,m_mcrasy           .Check for asynchronous interrupt
         andx    x1,x_mcr
         brreq   x1,x0,ckuser          .Jump if no asynchronous interrupt
         entl    x0,r_pit              .Stop the monitor clock.
         cpysx   x_clock,x0
         shfc    x1,x_mcr,x0,27        .Check for SIT.
         brrge   x1,x0,ckextint        .Jump if no SIT.
         addpxq  a_sitret,x0,ckextint  .Set up return address.
         brxeq   x0,x0,prsit           .Go process SIT interrupt.
ckextint shfx    x1,x_mcr,x0,24        .Check for EXT INT
         addpxq  a_extret,x0,ckexch
         brrgt   x0,x1,extrq           .Jump if  EXT INT.
ckexch   ente    x1,m_mcrexs           .Clear SIT and EXTINT.
         andx    x1,x_mcr
         sbyts,2 x_mcr,a_xcb,x0,xpmcr  .Clear MCR - see trap handler.
         shfx    x1,x_mcr,x0,21        .Check for EXCH
         brrge   x1,x0,ckasyncx        .Jump if no EXCH
         ente    x1,m_mcrexc           .Set EXCH bit in NOS XP
         ente    xe,#boff(a170_xp)
         sbyts,2 x1,a_root,xe,xpmcr
         addpxq  a_inret,x0,ckexch5
         lbyts,2 xe,a_cst,x0,dsprior   .Get current 180 priority.
         brxeq   x0,x0,run_nos         .Run NOS
ckexch5  entl    x0,r_te               .Enable traps
         cpyxs   x0,x0
ckasyncx entl    x0,r_pit              .Start monitor clock.
         cpyxs   x_clock,x0
         brxeq   x_mcr,x0,exchloop
.
.   Process faults normally handled in job mode via trap handler.
.
ckuser   ente    x1,j_mcrusr           .Check for condition that will
         cpyaa   a_parm,a_csf
         addpxq  a_rq_ret,x0,exchloop
         andx    x1,x_mcr              .be processed in job mode          .
         brreq   x1,x0,ckpf            .Jump if no job mode request
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*rqfault
         addaq   ae,a_bindin,16*rqfault
         brreq   x0,x0,rqproc
.
.   Check for a Page Fault.
.
ckpf     shfx    x1,x_mcr,x0,57        .Check for a page fault.
         brxge   x1,x0,ckmcall         .Jump if no page fault.
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*rqpf
         addaq   ae,a_bindin,16*rqpf
         brreq   x0,x0,rqproc          .Process page fault
.
.   Check for a System Call request.
.
ckmcall  shfx    x1,x_mcr,x0,58        .Check for a SYSTEM CALL.
         brxge   x1,x0,ckucr           .Jump if no SYSTEM CALL.
         lbyts,1 x1,a_xcb,x0,xpxregs   .Get request code
         ente    xe,mtrqmax            .Check for max req code.
         brxge   xe,x1,ckmcall5        .Jump if ok.
         entp    x1,0
ckmcall5 addaq   af,a_xcb,xpxregs      .Set up plist to point to
         sa      af,a_csf,0            .X_regs of current task
         addaq   a_rqtbl,a_root,reqtbl .Build pointer to the request table entry
         mulxq   xe,x1,rqtbles
         addax   a_rqtbl,xe
         cpyaa   ae,a_bindin           .Calculate binding section entry
         shfx    x1,x1,x0,4
         addax   ae,x1
         lbyts,1 xe,a_rqtbl,x0,rn      .Validate the ring number
         lbyts,1 x2,a_xcb,x0,2         .Get p.rn from XCB
         shfx    x2,x2,x0,-4
         brxge   xe,x2,rqproc
         addaq   a_rqtbl,a_root,reqtbl .Reset pointer to request 0 entry
         addaq   ae,a_bindin,16*rqunim
         brxeq   x0,x0,rqproc
.
.   If control gets here, there is a chance that the MCR value was zero
.   (except for possible async/sel interrupts). Check for a UCR fault that
.   caused a monitor exchange because traps were disabled.
.
ckucr    lbyts,2 x1,a_xcb,x0,xpucr     .Check for fatal UCR faults.
         ente    x0,j_usrabt
         andx    x1,x0
         brxeq   x1,x0,exchloop        .Jump if no fatal faults.
         lbyts,2 x1,a_xcb,x0,xpflgte   .Check for traps enabled
         isob    x1,x1,x0,7601(8)
         decr    x1,2
         brreq   x1,x0,exchloop        .Jump if traps not disabled
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*rqfault
         addaq   ae,a_bindin,16*rqfault
         brreq   x0,x0,rqproc          .back to job mode
         page
.....................................................................
.
.   Trap Handling Routine for traps that occur in Monitor Mode
.
.....................................................................
         def     traprtn
         align   0,8
traprtn  bss     0
         entl    x0,r_pit              .Save PIT
         cpysx   x_clock,x0
         la      a_root,a_bindin,bs_root
         la      a_dscb,a_root,eicb_pva
         ente    x0,r_bc
         cpysx   x1,x0                 .get  base constant.
         cpyax   x2,a_root
         addx    x1,x2                 .form pointer to cst
         cpyxa   a_cst,x1
         addaq   a0,a0,mstkfram
         sa      a_cst,a_csf,10        .Sace CST_P in p-list.
.
         lbyts,2 x_mcr,a_psa,x0,sfsa_mcr .Get MCR
         lbyts,2 x_ucr,a_psa,x0,sfsa_ucr .Get UCR
         xtrace  2,x_mcr,x1,x0,ae      .Save MCR in trace buffer.
         histo   x_mcr,a_root,tabmcrt,xe,xf
.
.   DO NOT halt the processor if a DUE or SHORT WARNING occurred.
.
         ente    x1,m_mcrhlt+m_mcrhdw+m_mcrpf  .Check for fatal errors.
         andx    x1,x_mcr
         brxeq   x1,x0,trhdw6          .If no fatal MCR errors
         shfc    x1,x_mcr,x0,50        .Check short warning.
         brxge   x1,x0,trckdue
         addpxq  a_rq_ret,x0,trckdue   .set return address.
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*pswarn
         cpyaa   a_parm,a_csf
         addaq   ae,a_bindin,16*pswarn
         brreq   x0,x0,rqproc
trckdue  shfc    x1,x_mcr,x0,48        .Check DUE.
         brxge   x1,x0,trhdw5
         ente    x_mcr,m_mcrasy        .Force all async interrupts.
         purge   x0,2                  .Purge cache and map.
         purge   x0,15
         entp    x1,2                  .Set up plist
         sx      x1,a_csf,0            .Store code to indicate DUE in monitor.
         sa      a2,a_csf,18           .Store pointer to save area.
         cpyaa   a_parm,a_csf
         addpxq  a_rq_ret,x0,trhdw5    .set return address
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*proc_due
         addaq   ae,a_bindin,16*proc_due
         brreq   x0,x0,rqproc
trhdw5   ente    x1,m_mcrhlt+m_mcrpf   .Halt if any fatal
         andx    x1,x_mcr              .  conditions are set
         brxeq   x1,x0,trhdw6          .If no fatal MCR conditions
         errstop fatalmcr
trhdw6   bss     0
.        keypt   oscmtr,osktrpm,x_mcr,x_ucr,xe
.
.  If the trap occurred between the labels BCRIT1 and ECRIT1, reset the
.  trapped 'P' address to the label BCRIT1.
.
         lbyts,4 x1,a_psa,x0,4         .Get P from SFSA.
         addpxq  ae,x0,ecrit1
         cpyax   x2,ae
         brrgt   x1,x2,trresex
         addpxq  ae,x0,bcrit1
         cpyax   x2,ae
         brrgt   x2,x1,trresex
         sa      ae,a_psa,2
.
. The following field definition is used to support the PSFSA instruction which is
. required for CYBER-2000 but is not available in the ASSEMBLER language yet.
. When it is available, replace the VFD line with the following line:
.        psfsa                         .Purge the SFSA pushdown (CYBER-2000 only)
.
         vfd,16   0701(16)             .Purge SFSA pushdown (CYBER-2000 only)
trresex  bss     0
.
.  Protect against the case where 1) a SIT or EXT INT occurred in 180 job
.  mode to cause an exchange to monitor and 2) prior to processing the
.  SIT/EXT INT an EXCH occurred to cause a trap.
.
         la      a_xcb,a_cst,xcbp      .Fetch XCB pointer.
         cpyax   x1,a_xcb              .Skip this check if NIL.
         brrgt   x0,x1,trnom
         lbyts,2 x1,a_xcb,x0,xpmcr     .Fetch MCR from current XP.
         iorx    x_mcr,x1              .Merge with trapped MCR.
         ente    x2,m_mcrasy
         inhx    x1,x2
         sbyts,2 x1,a_xcb,x0,xpmcr     .Store MCR less asynch bits.
trnom    bss     0
.
.  Process asynchronous interrupts.
.
         ente    x1,m_mcrasy           .Check for asynchronous interrupts.
         andx    x1,x_mcr
         brxeq   x1,x0,trasy15         .Jump if no asynchronous interrupts.
         shfc    x1,x_mcr,x0,27        .Check for SIT.
         brrge   x1,x0,trasy5          .Jump if no SIT.
         addpxq  a_sitret,x0,trasy5    .Set up return address.
         brxeq   x0,x0,prsit           .Go process SIT interrupt.
trasy5   shfx    x1,x_mcr,x0,24        .Check for EXT INT
         addpxq  a_extret,x0,trasy8
         brrgt   x0,x1,extrq           .Jump if  EXT INT
trasy8   shfx    x1,x_mcr,x0,21        .Check for EXCH
         brrge   x1,x0,trasy15         .Jump if no EXCH
         entl    x0,5                  .Set EXCH bit in MCR.
         sbit    x0,a_root,a170_xp+xpmcr,x0
         ente    xe,#boff(mtrprior)
         lbyts,2 x1,a_root,xe,0        .Get 180 monitor priority.
         lbyts,2 xe,a_cst,x0,dsprior   .Dont change if already greater.
         brxgt   xe,x1,trasy9
         cpyxx   xe,x1
trasy9   entl    x0,r_jps              .Check if NOS170 is the current task.
         cpysx   x1,x0
         lbyts,4 x2,a_cst,x0,dualstat
         addpxq  a_inret,x0,trasy15
         brxne   x2,x1,run_nos         .Go run NOS 170.
.
.   Halt processor if fatal UCR fault occurred.
.
trasy15  ente    x1,m_usrabt           .Check for fatal UCR fault
         andx    x1,x_ucr
         brxeq   x1,x0,trkey           .Jump if no fatal error
         errstop fatalucr
.
.         Check for keypoint trap and software keypoint recording.
.
trkey    bss     0
         shfx    x1,x_ucr,x0,22
         brrge   x1,x0,trkeye          .If not keypoint trap
         lbyts,1 x1,a_root,x0,act_kpc
         brreq   x1,x0,trkeye          .If software keypoints not active
.
.         Software recording of keypoints turned on, record keypoint in
.         circular buffer.
.
.         Form keypoint.
.
         entl    x0,0c8(16)            .Read keypoint class
         cpysx   xe,x0
         entl    x0,0c7(16)            .Read keypoint code
         cpysx   xf,x0
         insb    xf,xe,x0,3403(8)      .Combine keypoint class and code
         entp    x0,0                  .Read free running clock
         cpytx   xe,x0
         insb    xf,xe,x0,0231(8)      .Add free running clock
         cpyaa   a_parm,a0
         addpxq  a_rq_ret,x0,trkeye    .set return address.
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*key_pnt
         addaq   ae,a_bindin,16*key_pnt
         brreq   x0,x0,rqproc
trkeye   bss     0
.
.   Set TRAP ENABLE DELAY and return.
.
.        keypt   oscmtr,osktrpmx,x0,x_ucr,xe
         entl    x0,r_ted              .Set trap enable delay
         cpyxs   x0,x0
         entl    x0,r_pit              .Restore PIT
         cpyxs   x_clock,x0
         return
         page
.........................................................................
.
.      This routine updates the request statistics and calls the
.      appropriate request processor.
.
.      entry condition:
.            a_rqtbl - pointer to request table entry for request.
.            ae      - pointer to binding section entry for request proc.
.           a_rq_ret - return address
.           a_parm - pointer to parameters.
.
.      This routine exits back to the main dispatch loop.
.........................................................................
.
rqproc   bss     0
         lbyts,1 x1,a_root,x0,multpro
         brxeq   x1,x0,rqpr14          .if not multi_processor
         lbyts,1 x1,a_rqtbl,x0,il
         brxeq   x1,x0,rqpr14          .if interlock not required
         addaq   af,a_root,il_tbl
         decr    x1,1
         mulxq   x1,x1,ilsize
         addax   af,x1                 .pva of interlock table
         entp    x0,0
         lbset   x1,af,x0
         brreq   x1,x0,rqpr12          .if request accepted
         lbyts,4 x1,a_rqtbl,x0,wtcnt
         incr    x1,1
         sbyts,4 x1,a_rqtbl,x0,wtcnt   .increment request reject count.
         lbyts,4 x1,af,x0,ilwtcnt
         incr    x1,1
         sbyts,4 x1,af,x0,ilwtcnt      .increment lock reject count
         ente    xe,r_pit
         cpysx   xe,xe                 .get current pit
rqpr4    entp    x0,0
         lbset   x2,af,x0
         brreq   x2,x0,rqpr6
         ente    x0,-20                .idle to reduce memory contention
rqpr5    brinc   x0,x0,rqpr5
         lbyts,1 x2,a_cst,x0,nextstat  .check for halt cpu request
         brxeq   x2,x0,rqpr4
         errstop csthalt
rqpr6    entl    x0,r_pit
         cpysx   x2,x0                 .current pit
         cpyxs   xe,x0                 .Restore PIT- don't charge user for lock wait.
         subx    xe,x2
         lx      x2,a_root,lockwait    .increment total lock wait time
         addx    x2,xe
         sx      x2,a_root,lockwait
         lx      x2,a_rqtbl,totwt
         addx    x2,xe
         sx      x2,a_rqtbl,totwt      .increment request wait time
         lx      x2,af,iltotwt
         addx    x2,xe
         sx      x2,af,iltotwt         .increment lock wait time
         lbyts,4 x2,a_rqtbl,x0,maxwt
         brxge   x2,xe,rqpr10          .if not longest request wait
         sbyts,4 xe,a_rqtbl,x0,maxwt
rqpr10   lbyts,4 x2,af,x0,ilmaxwt
         brxge   x2,xe,rqpr12          .if not longest lock wait
         sbyts,4 xe,af,x0,ilmaxwt
rqpr12   cpyax   x1,af                 .x1 = pva of interlock table
         ente    x2,r_bc
         cpysx   xe,x2                 .get base constant.
         sbyts,4 x2,af,x0,lockcp       .Store ID of locking CPU
rqpr14   bss     0                     .x1 = zero if no interlock.
         lbyts,4 xe,a_rqtbl,x0,rqcnt   .Update request count
         incr    xe,1
         sbyts,4 xe,a_rqtbl,x0,rqcnt
         entl    x0,r_pit
         cpysx   x2,x0                 .Get current PIT
         ente    x0,x_envir1           .Process the request
         callseg bs_rqtbl,ae,a_parm
         entl    x0,r_pit
         cpysx   xd,x0                 .Calculate time to process the request
         subx    x2,xd
         lx      xd,a_rqtbl,totalt     .Update total time
         addx    xd,x2
         sx      xd,a_rqtbl,totalt
         lbyts,4 xd,a_rqtbl,x0,maxt    .Update max time
         brxge   xd,x2,rqpr20
         sbyts,4 x2,a_rqtbl,x0,maxt
rqpr20   brxeq   x1,x0,rqpr30          .exit if no lock
         entl    x0,0
         cpyxa   af,x1
         sx      x0,af,ilflag          .Clear lock and ID field in interlock table
rqpr30   brdir   a_rq_ret,x0           .return
         page
.........................................................................
.
.  This routine is called whenever a SIT interrupt occurs.
.
.........................................................................
.
prsit    bss     0
         entp    xf,1                  .Set up X15 with 'TRUE'.
         entp    x0,0                  .Set up X0 with 'FALSE'.
         cpytx   x2,x0                 .Free running clock ->X2.
         sx      x2,a_root,scb+scbnsrv .Update '180 alive' flag.
         sbyts,1 xf,a_cst,x0,caldisp
.
prsit25  lx      x1,a_root,sitvalue    .Reset SIT.
         entl    x0,r_sit
         cpyxs   x1,x0
.
         brdir   a_sitret,x0
         page
.........................................................................
.
.   The purpose of this routine is to give control to NOS170.
.
.   NOTE: This routine may be entered with traps disabled or enabled.
.         Reentry of the routine from the trap handler is prevented by
.         setting the JPS register to NOS_JPS.  This routine exits with
.         disabled unless NOS is not present. In this case no change is
.         made to the TE register.
.
.     Enter with 180 priority in XE.
.
.........................................................................
.
.
run_nos  bss     0
.
         lbyts,4 x1,a_cst,x0,dualstat  .Exit if no dual state.
         brxeq   x1,x0,runexit
.
         entl    x0,r_jps
         cpyxs   x1,x0                 .Copy NOS_JPS to JPS reg
         addaq   a_innosx,a_root,a170_xp
.
         lbyts,1 x1,a_cst,x0,lpid8     .Store 180 priority.
         sbyts,2 xe,a_dscb,x1,np180pr
.
         entp    x_infrc,0             .Get current time
         cpytx   x_infrc,x_infrc
         lx      x2,a_root,nosexit     .Update time not spent in NOS
         subx    x2,x_infrc
         notx    x2,x2
         histo   x2,a_root,tabnnos,xe,xf
         lx      x1,a_dscb,npxtime
         addx    x1,x2
         sx      x1,a_dscb,npxtime
.
.  (BEGIN - EXCH loop).   Exchange to NOS170.
.
runnos6  bss     0
         entp    x_infrc,0             .Get current time
         cpytx   x_infrc,x_infrc
         la      af,a_root,hnsk_p      .Update monitor handshaking time
         sx      x_infrc,af,8

         xtrace  3,0,x1,xe,ae
         entl    x0,r_te               .Enable traps
         cpyxs   x0,x0
         keypoint oscmtr,x0,oskexc7
runnos7  exchange
         lbyts,2 x_inmcr,a_innosx,x0,xpmcr .Get MCR
         shfx    x2,x_inmcr,x0,13
         keypoint oscmtr,x2,oskexc7x
         entl    x0,r_td               .Disable traps
         cpyxs   x0,x0
         lbyts,2 x_inmcr,a_innosx,x0,xpmcr .Get MCR
         ente    x2,m_mcrexc           .Clear MCR except for EXCH
         andx    x2,x_inmcr
         sbyts,2 x2,a_innosx,x0,xpmcr
         xtrace  4,x_inmcr,xe,xd,ae    .Save NOS MCR in trace buffer
         histo   x_inmcr,a_root,tabmcr7,xe,xf
.
.   Process 'give up CPU' if only bit set in the MCR is 'system call'.
.
         ente    x2,m_mcrmcl
         brxne   x_inmcr,x2,runnos8    .Jump if not sys call ONLY.
         lbyts,1 x2,a_innosx,x0,xpvmid .Make sure request is from
         brxne   x2,x0,runnos50        .  170 state.
.
.   Process hardware errors - DUE.
.
runnos8  shfc    x2,x_inmcr,x0,16      .Check for DUE.
         brrge   x2,x0,runnos10        .Jump if no DUE.
         purge   x0,2                  .Purge cache and map.
         purge   x0,15
         entl    x0,1                  .Set up plist - DUE in 170 mode
         sx      x0,a_csf,0
         sa      a_innosx,a_csf,18
         addpxq  a_rq_ret,x0,runnos9   .set return address.
         cpyaa   a_parm,a_csf
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*proc_due
         addaq   ae,a_bindin,16*proc_due
         brreq   x0,x0,rqproc
runnos9  ente    x2,0490(16)           .Force async bit - may be lost.
         iorx    x_inmcr,x2
         lbyts,1 x2,a_innosx,x0,xpflgte .Check PROCESS-NOT-DAMAGED.
         shfr    x2,x2,x0,27
         brrge   x2,x0,runnos10        .Jump if damaged.
         ente    x2,7fff(16)           .Clear DUE in MCR.
         andx    x_inmcr,x2

.
.   Process short warning conditions.
.
runnos10 shfc    x2,x_inmcr,x0,18      .Check for SHORT WARNING.
         brrge   x2,x0,runnos11        .Jump if no SHORT WARNING.
         addpxq  a_rq_ret,x0,runnos11  .set return address.
         cpyaa   a_parm,a0
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*pswarn
         addaq   ae,a_bindin,16*pswarn
         brreq   x0,x0,rqproc
.
.   Process SIT interrupt.
.
runnos11 shfc    x2,x_inmcr,x0,27      .Check for SIT.
         addpxq  a_sitret,x0,runnos12  .Go process SIT interrupt.
         brrgt   x0,x2,prsit           .Jump if SIT present.
.
.   Process EXTERNAL INTERRUPT.
.
runnos12 shfc    x2,x_inmcr,x0,24      .Check for EXT INT.
         addpxq  a_extret,x0,runnos16
         brrgt   x0,x2,extrq           .Jump if  EXT INT.
.
.   Process SYSTEM CALL requests.
.
runnos16 shfc    x2,x_inmcr,x0,26      .Check for SYSTEM CALL.
         brrge   x2,x0,runnos20        .Jump if no SYSTEM CALL.
         lbyts,1 x2,a_innosx,x0,xpvmid .Check whether 170 or 180 request.
         brxeq   x2,x0,runnos18        .Jump if 180 request.
         shfc    x2,x_inmcr,x0,21      .Exit if EXCH not set.
         brrge   x2,x0,runnos50
         brxeq   x0,x0,runnos6
runnos18 entp    x0,0
         sx      x0,a_csf,1*8
         ente    x0,020(16)
         sx      x0,a_csf,2*8
         sa      a_csf,a_csf,3*8
         addaq   a_parm,a_csf,8
         addpxq  a_rq_ret,x0,runnos24  .set return address.
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*mm_ei
         addaq   ae,a_bindin,16*mm_ei
         brreq   x0,x0,rqproc
.
.   Check for FATAL NOS170 errors.  Stop running 170 if fatal
.   errors occured.
.
runnos20 ente    x2,0DB4C(16)          .Check for fatal 170 MCR
         andx    x2,x_inmcr
         brreq   x_inmcr,x0,runnos22   .Fatal if MCR = 0.
         brreq   x2,x0,runnos30        .Jump if no fatal 170 errors
runnos22 addaq   af,a_csf,8
         entp    x0,2
         sx      x0,af,0
         sx      x_inmcr,af,1*8
         sa      a_csf,af,2*8
         addpxq  a_rq_ret,x0,runnos24  .set return address.
         cpyaa   a_parm,af
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*mm_ei
         addaq   ae,a_bindin,16*mm_ei
         brreq   x0,x0,rqproc
runnos24 sa      a_cst,a_csf,10        .Restore CST_P in p-list.
         lbyts,1 x2,a_csf,X0,0
         brreq   x2,x0,runnos30        .if not a fatal nos error
         shfx    x1,x_inmcr,x0,-15     .Store termination status -
         incx    x1,1                  . 2=DUE, 1=other
         sbyts,1 x1,a_root,x0,os_terms
         entl    x0,0                  .Clear dual state flag.
         sbyts,4 x0,a_cst,x0,dualstat  .Stop running NOS170.
         sbyts,2 x0,a_dscb,x0,np170pr  .Clear 170 priority.
         entl    x0,1                  .Initiate 180 checkpoint
         sbyts,1 x0,a_cst,x0,caldisp   .Force call to dispatcher.
         sbyts,8 x0,a_csf,x0,0         .Set up plist
         addpxq  a_rq_ret,x0,runnos50  .set return address.
         cpyaa   a_parm,a_csf
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*in_ckp
         addaq   ae,a_bindin,16*in_ckp
         brreq   x0,x0,rqproc
.
.   Check if it is time to run 180.  If not, exchange back to 170.
.   If 180 needs the CPU and NOS170 is in job mode, it's OK to switch to 180.
.
runnos30 lx      x2,a_cst,discntl .Check if dispat should be called
         brxeq   x2,x0,runnos6
.
.   Its time to run 180 again. If NOS170 is in 170 job mode or in EI as
.  a result of a call from job mode, its ok to exit. Otherwise, set 180
.  priority to a high value and return to NOS170. It should give up control
.  quickly.
.
         shfc    x2,x_inmcr,x0,21      .Cant exit if EXCH is set in 170 XP.
         brrgt   x0,x2,runnos35        .Jump if EXCH is set.
         lbyts,1 x2,a_innosx,x0,xpvmid .Get 170 mode VMID.
         lx      xd,a_innosx,xpucr     .Get word that contains monitor flag.
         brxne   x2,x0,runnos32         .Jump if in 170 mode.
         la      af,a_innosx,2*8+8+2   .get pointer to stack frame save area
         lx      xd,af,xpucr           .Get monitor flag from save area.
runnos32 shfc    xd,xd,x0,31           .Move monitor flag to bit 0.
         brxge   xd,x0,runnos50        .Jump if ok to exit from 170.
.
runnos35 lbyts,1 x1,a_cst,x0,lpid8     .Cant exit. Raise 180 priority.
         ente    x2,708(16)
         sbyts,2 x2,a_dscb,x1,np180pr
         brxeq   x0,x0,runnos6
.
.
.   End of EXCH loop.
.
runnos50 entp    x0,0                  .Get current time
         cpytx   x1,x0
         sx      x1,a_root,nosexit
         subx    x1,x_infrc
         histo   x1,a_root,tabinos,xe,xf
         lx      x2,a_root,nostime     .Update total NOS cpu time
         addx    x1,x2
         sx      x1,a_root,nostime
         entl    x0,r_jps              .Reset JPS
         lx      x1,a_cst,xcbrma
         cpyxs   x1,x0
runexit  brdir   a_inret,x0            .Return to where called from
         page
.........................................................................
.
.        process requests from another processor
.
.        entry conditions:
.           a_extret - return address
.
.........................................................................
.
extrq    lbyts,1 x1,a_root,x0,multpro
         brxeq   x1,x0,extrq5          .jump if not multiprocessor
         entp    x2,0
         entl    x0,tsk_sw
         lx      x1,a_cst,ext_int
         shfc    x1,x1,x0,tsk_sw
         brxge   x1,x0,extrq1          .jump if no task switch
         sbit    x2,a_cst,ext_int,x0
         entl    x0,1
         sbyts,1 x0,a_cst,x0,caldisp   .set task switch flag
extrq1   entl    x0,pur_ca
         shfc    x1,x1,x0,pur_ca-tsk_sw+64
         brxge   x1,x0,extrq2          .jump if cache purge not needed
         sbit    x2,a_cst,ext_int,x0
         cpytx   x0,x2                 .free running clock
         purge   x0,2                  .purge cache
         sx      x0,a_cst,cachtim
extrq2   entl    x0,pur_map
         shfc    x1,x1,x0,pur_map-pur_ca+64
         brxge   x1,x0,extrq3          .jump if map purge not needed
         sbit    x2,a_cst,ext_int,x0
         cpytx   x0,x2                 .free running clock
         purge   x0,15                 .purge map
         sx      x0,a_cst,maptim
extrq3   shfc    x1,x1,x0,step_pr-pur_map+64
         brxge   x1,x0,extrq4          .jump if no error halt
         errstop csthalt
extrq4   lbyts,1 x1,a_cst,x0,memport   .Dont check IO completions if
         ente    xe,#boff(intport)
         lbyts,1 x2,a_root,xe,0        . IOU doesnt send them to this CPU.
         brxne   x1,x2,extrqx
         lx      x1,a_root,extiou      .Exit if no external interrupts
         brxeq   x1,x0,extrq6          . have been sent by IOU.
extrq5   entl    x0,1
         sx      x0,a_root,eiflag      .Set flag that ext interrupt.
         sx      x0,a_root,asyntime
         sbyts,1 x0,a_cst,x0,asyncp
extrq6   la      ae,a_root,dpv$scd_block_p
         addaq   ae,ae,4
         entp    x0,0
         lbset   x1,ae,x0
         brrne   x1,x0,extrqx          .If SCD block not updated
         cpyaa   a_rq_ret,a_extret     .set return address.
         addaq   a_rqtbl,a_root,reqtbl+rqtbles*ascii_kb
         addaq   ae,a_bindin,16*ascii_kb
         brreq   x0,x0,rqproc
extrqx   brdir   a_extret,x0
         page
........................................................................
.
.        MTP$IDLE_180  routine to idle 180.
.
.        This routine is called to put 180 into an idle state. Only
.        the system console is kept alive and only the monitor window
.        will respond to commands. If dual state is present, 180 will idle
.        and give control to NOS/NOS-BE. Depending on why the system idled,
.        the system may be able to be resumed via a RESUME_SYSTEM command.
.
.            mtp$idle_180 (resume_permitted: boolean)
.
........................................................................
         align     0,8
idle180  ALIAS     MTP$IDLE_180
idle180  procedur
idleres  param     val,subrange,1
.
         ploadx    x_resume,idleres             .Load RESUME_ALLOWED - A4 gets
.                                                clobbered later.
         la        a_root,a_bindin,bs_root

         la        a_dscb,a_root,eicb_pva
         addaq     a0,a0,mstkfram
         entl      x0,r_pit                     .Save PIT - dont charge current task for idle
         cpysx     x_clock,x0                   . time.
         ente      x0,r_bc
         cpysx     x1,x0                        .get  base constant.
         cpyax     x2,a_root
         addx      x1,x2                       .form pointer to cst
         cpyxa     a_cst,x1
.
         entl      x0,0c2(16)                  .Enable traps in case we got here via trap
         cpyxs     x0,x0                       . handler.
.
i180a    entp      xe,0                        .Set 180 priority to 0.
         addpxq    a_inret,x0,i180c            .Run NOS170 if it is present. (If not present
         brreq     x0,x0,run_nos               .  runnos returns immediately.)
i180c    bss       0
         entp      x0,0                        .Set lock for calling
         addaq     af,a_root,asylocki          .  mtp$monitor_system_status.
         lbset     x1,af,x0
         brrgt     x1,x0,i180f                 .Jump if already locked.
         la        ae,a_root,mtvdftb           .Fetch pointer to DFT block.
         lx        x1,ae,dftcw                 .Get DFT control word.
         shfx      x1,x1,x0,62                 .Check E8 field.
         brxge     x1,x0,i180e                 .Jump if not set.
         ente      x0,00ff(16)
         addaq     ae,a_bindin,16*proc_dft     .Set up call to dsp$process_dft_block.
         callseg   bs_rqtbl,ae,a0              .Call dsp$process_dft_block.
i180e    bss       0
         ente      x0,00ff(16)
         addaq     ae,a_bindin,16*mon_smu      .Set up call to mtp$monitor_system_status.
         callseg   bs_rqtbl,ae,a0              .Call mtp$monitor_system_status.
         entp      x0,0                        .Clear call environment.
         sbyts,1   x0,af,x0,0                  .Clear lock.
i180f    bss       0
         ente      xc,scb+scbstepr
         lbyts,1   x1,a_root,xc,0              .Loop if STEP still requested.
         brrne     x1,x0,i180a
         brxeq     x_resume,x0,i180a           .Loop if resume not permitted.
.
         entl      x0,r_pit                    .Restore PIT.
         cpyxs     x_clock,x0
         return
.
         page
....................................................................................
.  Name:
         align   0,8
.    MTP$CST_POINTER
.  Purpose:
.    this procedure returns the pointer to the CPU STATE TABLE for the
.    current processor.
.  Output:
.    CST_P: pointer to the CST.
....................................................................................
.
.  FUNCTION [XDCL] mtp$cst_pointer (cst_id: 0..1): ^cell
.
.
cstp     alias   MTP$CST_POINTER
cstp     function pointer
cst_id   param   val,subrange,1
         la      a_root,a_bindin,bs_root
         ente    x0,r_bc
         cpysx   x1,x0                 .get  base constant.
         cpyax   x2,a_root
         addx    x1,x2                 .form pointer to cst
         freturnx x1
         page
.........................................................................
.
.   This routine is called from cybil to send interrupts to other processors.
.
.      PROCEDURE [XREF] mtp$interrupt_processor (port_mask: 0..255)
.
.........................................................................
.
int      alias   MTP$INTERRUPT_PROCESSOR
int      procedur
intmask  param   val,subrange,1
         ploadx  x2,intmask
         intrupt x2,0
         return
         page

.        The following is a list of external references that should exist in monitor
.        boot.  They are needed to satisfy external references to link without errors.
.        They are not needed for normal execution, if they are ever called, it is a
.        fatal error.

         defg    OSP$PROCESS_MTR_PAGE_FAULT
         defg    MMP$ASSIGN_PAGE_TO_MONITOR
         defg    TMP$SEND_MONITOR_FAULT
         defg    DMV$ACTIVE_VOLUME_TABLE
         defg    DMP$SEARCH_ACTIVE_VOLUME_TABLE
         defg    DMP$CREATE_DEVICE_FILE
         defg    DMP$DETACH_DEVICE_FILE
         defg    NAV$NETWORK_RESPONSE_PROCESSOR
         defg    RFV$RESPONSE_PROCESSOR
         defg    DFV$PROCESS_MULTIWORD_RESPONSE
         defg    IOV$PROCESS_SUBSYSTEM_RESPONSE
         defg    SYP$INVOKE_SYSTEM_DEBUGGER
         defg    DSP$TEST_RESOURCE_REQUESTS
         defg    SYP$INVOKE_SYSCORE_COND_HANDLER
         defg    SYP$INVOKE_SYSCORE_UCR_HANDLER
         defg    SYP$SET_PROCESS_INTERVAL_TIMER
         defg    SYP$MFH_FOR_HANG_TASK
         defg    DMP$GET_UNUSED_AVT_ENTRY
         defg    DMP$RELEASE_AVT_ENTRY
         defg    PMP$GET_JOB_NAMES

         align   0,8

OSP$PROCESS_MTR_PAGE_FAULT             bss   0
MMP$ASSIGN_PAGE_TO_MONITOR             bss   0
TMP$SEND_MONITOR_FAULT                 bss   0
DMV$ACTIVE_VOLUME_TABLE                bss   0
DMP$SEARCH_ACTIVE_VOLUME_TABLE         bss   0
DMP$CREATE_DEVICE_FILE                 bss   0
DMP$DETACH_DEVICE_FILE                 bss   0
NAV$NETWORK_RESPONSE_PROCESSOR         bss   0
RFV$RESPONSE_PROCESSOR                 bss   0
DFV$PROCESS_MULTIWORD_RESPONSE         bss   0
IOV$PROCESS_SUBSYSTEM_RESPONSE         bss   0
SYP$INVOKE_SYSTEM_DEBUGGER             bss   0
DSP$TEST_RESOURCE_REQUESTS             bss   0
SYP$INVOKE_SYSCORE_COND_HANDLER        bss   0
SYP$INVOKE_SYSCORE_UCR_HANDLER         bss   0
SYP$SET_PROCESS_INTERVAL_TIMER         bss   0
SYP$MFH_FOR_HANG_TASK                  bss   0
DMP$GET_UNUSED_AVT_ENTRY               bss   0
DMP$RELEASE_AVT_ENTRY                  bss   0
PMP$GET_JOB_NAMES                      bss   0

         errstop stubcall              .Call to a stub in monitor, fatal error

         end     begin
