@X @~
~L3 COUK1247
80
~V7 56 2 -5
~D10
~H                  MUSS
~
~
~HAPPENDIX  3
~D15
This volume contains the machine dependent software for the VAX11.
~D9
~MUNIVERSITY OF MANCHESTER
~V9 -1
~P
~D10
~MAppendix 3  CONTENTS
~
~
~MAP2022  -  Drum Appendix (RK07)
~
~NAP2023  -  Drum Appendix (RK07)~
~
~NAP2101  -  Magnetic Tape Appendix (TM11)
~
~NAP3011  -  VAX11/750 CPU Appendix
~
~NAP1031  -  I/O Appendix
~
~NAP3041  -  DZ11 Multiplexer Device Driver Appendix
~
~NAP3071  -  LP11 Lineprinter Driver Appendix
~
~NAP3081  -  Operators Console Device Driver Appendix
~
~NAP3201  -  Post Mortem Dump Procedure
~
~NAP3211  -  Bootstrap
~
~NAP3501  -  Monitor CPU Appendix (VAX)~
~
~NAP3511  -  Monitor Drum Appendix (VAX)~
~
~NAP3991  -  End of Initialisation~
~P
~D10
~H                    MUSS
~
~
~D10
~H             AP3011
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL
~
~
                                                           ISSUE 11~
~V9 -1
~P
~V9 1
~YAP3011
~S1~M~OAP3 IMPLEMENTATION DESCRIPTION~
~S1~M~OSection 1 Version 1~
~S1~OSection 1.1 Vax 11/750 Processor Appendix~
~S1~O1. General Description~
~BThis module is concerned with mapping the CPU features of the MUSS
ideal machine onto the Vax. In addition it provides those facilities
which are widely used, and which do not clearly belong to any
other section of the system.~
~BThe Vax 11/750 Processor is described in Digital's
"Vax Hardware Handbook 1980-81". The "Vax11 Architecture Handbook 1979-80" is
also of use for reference.~
~S1~O2. Interfaces~
~3
Other modules used~
   SYS Section  1 (Coordinator)~
   SYS Section 10 (Virtual Machine Interrupts)~
   SYS Section 11 (Virtual Machine Timer)~
   SYS Section 12 (Fault Conditions)~
   SYS Section 13 (Process Management)~
   SYS Section 14 (Virtual Store Management)~
   SYS Section 21 (Performance Monitoring)~
Ideal hardware registers used~
   V.CALL.LINK~
   V.EXIT.LINK~
   V.FI~
   V.HALT.MASK~
   V.HW.INTS~
   V.SW.INTS~
   V.CLOCK~
   V.TIME~
   V.MILLI.TIME~
   V.VM.TIMER~
   V.EXEC.MC.CONTROL~
   V.SF~
   V.VM.INTS~
   V.PF.STATUS~
   V.DUMPED.CONTROL~
   V.INIT.REGS~
   V.INT.MC.CONTROL~
   V.MC.NO~
   V.PRB.RA~
   V.PROCESS.NUMBER~
   V.NEQ.ACCESS~
   V.NEQ.BLK~
   V.NEQ.SEG~
   V.RESET.BLK~
   V.RESET.SEG~
   V.RESET.STATUS~
   V.STACK.SEG~
   V.VAL.ACCESS~
   V.APP.LINK~
Vax hardware registers used~
   PCBB - PROCESS CONTROL BLOCK BASE~
   IPL  - INTERRUPT PRIORITY LEVEL~
   ICCS - INTERVAL CLOCK CONTROL/STATUS REGISTER~
   NICR - NEXT INTERVAL COUNT REGISTER~
   ICR  - INTERVAL COUNTER REGISTER~
   TODR - TIME OF DAY REGISTER~
   TBIA - TRANSLATION BUFFER INVALIDATE ALL~
Interrupt Procedures~
   FAULT.INTERRUPT (REASON)~
   SYSTEM.ERROR.INTERRUPT (ERROR)~
   ENTER.INT.LEVEL.INTERRUPT (DUMMY)~
   INTERVAL.TIMER.INTERRUPT (DUMMY)~
   CMD.ENTRY.INTERRUPT (ENTRY.INDEX)~
   MEMORY.MANAGEMENT.INTERRUPT (VIRTUAL ADDRESS, FAULT REASON, DUMMY)~
   RETURN.TO.USER.INTERRUPT (DUMMY)~
Interface Procedures~
   EMPTY.ACTIVITY ()~
   PROC.ACTIVITY ()~
   SET.HW.INT (ACTIVITY)~
   CLEAR.HW.INT (ACTIVITY)~
   MS.BIT (WORD)~
   BIT (INDEX)~
   SET.BIT (BIT VECTOR, INDEX)~
   CLEAR.BIT (BIT VECTOR, INDEX)~
   TEST.BIT (BIT VECTOR, INDEX)~
   VALIDATE (ADDRESS, REQUIRED ACCESS)~
   APP.OUTWARD.CALL (PRB PTR, TRAP NO, REASON, PROCEDURE)~
   SET.LINKS ()~
Interface Variables~
   INIT.TRAP.FLAG~
Interface Types~
   APP.STATS.TYPE~
Interface Literals~
   REG.DUMP.SIZE~
   DUMPED.V.VM.INTS.REG.NO~
   DUMPED.V.VM.TIMER.REG.NO~
   DUMPED.V.VAL.ACCESS.REG.NO~
Configuration Parameters~
   ILLEGAL.ORDER~
   RESERVED.STACK.BOTTOM~
   RESERVED.STACK.TOP~
   NO.OF.COMMANDS~
   BYTES.PER.WORD~
   P0.BASE~
   P0.LIMIT~
   P1.BASE~
   P1.LIMIT~
Machine Functions~
   ALLOW.INTERRUPTS~
   INHIBIT.INTERRUPTS~
   MAP.IO.APP~
   UNMAP.IO.APP~
~0
~S1~O2.1 MUSS Interface~
~S1~O2.1.1 Hardware Interface~
~BThe ideal hardware registers are described in the following sections:~
~3
~
SYS Section  1 - V.CALL.LINK, V.EXIT.LINK, V.FI, V.HALT.MASK,~
               - V.HW.INTS, V.SW.INTS.~
~
SYS Section  8 - V.CLOCK, V.TIME, V.MILLI.TIME.~
~
SYS Section 10 - V.EXEC.MC.CONTROL, V.SF, V.VM.INTS.~
~
~
SYS Section 11 - V.VM.TIMER.~
SYS Section 12 - V.PF.STATUS.~
~
SYS Section 13 - V.DUMPED.CONTROL, V.INIT.REGS, V.INT.MC.CONTROL,~
               - V.MC.NO, V.PRB.RA, V.PROCESS.NUMBER.~
~
SYS Section 14 - V.NEQ.ACCESS, V.NEQ.BLK, V.NEQ.SEG,~
               - V.RESET.BLK, V.RESET.SEG, V.RESET.STATUS,~
               - V.STACK.SEG, V.VAL.ACCESS.~
~
AP2 Section  3 - V.BYTE, V.READ.BYTE, V.WRITE.BYTE.~
~0
~BV.APP.LINK is used to implement a co-routine type mechanism
between hardware interrupt handling code and code for handling
complex protocols.~
~BV.APP.LINK should be read within a procedure which is called from
the protocol handling code. It yields the return link of the calling
procedure and returns control to the interrupt handling code.
When this return link is written to V.APP.LINK, control is returned
to the point in the protocol handling code to which the
procedure would have returned. V.APP.LINK should be written
to within an interrupt handling procedure. Only a return link
previously obtained from V.APP.LINK should be written to it.~
~S1~O2.1.2 Software Interface~
~S11) FAULT.INTERRUPT (REASON)~
~BThis procedure services the interrupts generated by
programming faults. It runs at interrupt level.~
~S12) SYSTEM.ERROR.INTERRUPT (ERROR)~
~BThis procedure services the interrupts generated by system
errors. Errors resulting from non-existent device faults are
handled in a different way from other system errors. It runs at
INTERRUPT level.~
~S13) ENTER.INT.LEVEL.INTERRUPT (MODE)~
~BThis procedure services the CHMK trap used to enter interrupt level
from command level. It faults an attempted entry from user level. It
runs at interrupt level.~
~S14) INTERVAL.TIMER.INTERRUPT (DUMMY)~
~BThis procedure services interrupts from the INTERVAL COUNTER REGISTER. It
runs at interrupt level.~
~S15) CMD.ENTRY.INTERRUPT (ENTRY.INDEX)~
~BThis procedure services the CHME trap which is used to enter
command level from user level. This is to allow user calls to
organisational commands. The CHME instruction is planted by the
compiler.~
~S16) MEMORY.MANAGEMENT.INTERRUPT (VIRTUAL ADDRESS, FAULT REASON, DUMMY)~
~BThis procedure services the translation not valid interrupt, and also the
access control violation interrupt. It runs at interrupt level.~
~S17) RETURN.TO.USER.INTERRUPT (DUMMY)~
~BThis procedure services the Asynchronous System Trap which
results from a return to user mode when the AST-LVL privileged register
is set appropriately. The AST-LVL is set indirectly via the Process
Control Block. RETURN.TO.USER.INTERRUPT runs at interrupt level.~
~S18) EMPTY.ACTIVITY ()~
~BThis procedure is used as an entry in the ACTIVITY.LINK table
(SYS Section 1) for those entries allocated to the system which
have no corresponding activity.~
~S19) PROC.ACTIVITY ()~
~BThis procedure is used as an entry in the ACTIVITY.LINK table
for those entries allocated to user processes which have no associated
user process.~
~S110) SET.HW.INT (ACTIVITY)~
~BThis procedure sets the appropriate bit in V.HW.INT and updates
the interrupt tree. It runs at interrupt level.~
~S111) CLEAR.HW.INT (ACTIVITY)~
~BThis procedure clears the appropriate bit in V.HW.INT and updates
the interrupt tree. It runs at interrupt level.~
~S112) MS.BIT (WORD)~
~BThis procedure finds and returns the most significant bit in WORD,
which must be non-zero. It can run at interrupt or command level.~
~S113) BIT (INDEX)~
~BThis procedure returns a bit pattern with the required bit set.
It can run at interrupt or command level.~
~S114) SET.BIT (BIT VECTOR, INDEX)~
~BThis procedure sets the indicated bit in the specified bit vector. It can
run at interrupt or command level.~
~S115) CLEAR.BIT (BIT VECTOR, INDEX)~
~BThis procedure clears the indicated bit in the specified bit vector.
It can run at interrupt or command level.~
~S116) TEST.BIT (BIT VECTOR, INDEX)~
~BThis procedure returns the value of the indicated bit in the
specified bit vector. It can run at interrupt or command level.~
~S117) VALIDATE (ADDRESS, REQUIRED ACCESS)~
~BThis procedure checks that the user address supplied is valid and if this is s
o, that
the user has the required access permission. If any of these
checks fail the user's frame pointer is unwound so as to return
to user level, with fault status set, on exit from VALIDATE.
VALIDATE runs at command level.~
~S118) APP.OUTWARD.CALL (PRB PTR, TRAP NO, REASON, PROCEDURE)~
~BThis procedure manipulates the stack so that on return to user
level PROCEDURE (TRAP NO, REASON) is entered. APP.OUTWARD.CALL
runs at command level.~
~S1~O2.1.3 Machine Functions~
~S11) ALLOW.INTERRUPTS~
~BThis KERNEL mode function sets the interrupt priority to the lowest level (0).
~
~S12) INHIBIT.INTERRUPTS~
~BThis KERNEL mode function sets the interrupt priority to the highest level (31
).~
~S13) MAP.IO.APP~
~BThis function has no action. It is included for compatibility with
those AP2 device appendices which are also used in the PDP 11/34
implementation.~
~S14) UNMAP.IO.APP~
~BSee MAP.IO.APP.~
~S1~O2.2 Vax Interface~
~BDetails of the VAX11/750 processor are provided in the
VAX Hardware Handbook.
~S1~O2.2.1 Servicing of Interrupts
~BThe servicing of interrupts may be performed at one of three
levels, namely~
~
~Mraw interrupt level
~Nappendix interrupt level
~NMUSS interrupt level.
~BThe latter is the interrupt level state defined for the MUSS
ideal machine (as described in SYS000).
~BThe initial servicing of interrupts is controlled by the
interrupt vectors, which provide a jump into the corresponding
raw interrupt level code.  On entry to this code, the only
context information saved is that dumped on the stack by the
hardware.  Any other registers required by the raw interrupt level
software must be preserved and restored within the interrupt runtime.
~BThe raw interrupt level code is intended for the rapid servicing
of trivial interrupt conditions, such as the arrival of a single
character down a communications link.  To restrict the registers
used by the interrupt routine (and hence reduce the overheads of
dumping and restoring), this code is normally written in
hexadecimal.
~BIf the interrupting condition requires more significant
actions, then appendix interrupt level should be entered.
Entry to this level is achieved by stacking a parameter for the
appendix level procedure and the vector number of the interrupt,
~X%`
and then jumping into the system code at address %240C00.
~X%%
The entry sequence into the appendix level interrupt
procedure saves the full process context, and so these
procedures may be written in MUSL without needing to preserve or
restore any registers explicitly.
~BA decision to formally enter MUSS interrupt level or to return
back to the current process is made on returning from the appendix
level interrupt procedure, depending on whether an ideal machine
interrupt has resulted.
~P~S1~O3. Implementation~
~S1~O3.1 Outline of Implementation~
~BThe three levels of the MUSS ideal machine are mapped on to the
VAX as follows:~
~Minterrupt level -> kernel mode~
~Ncommand level -> executive mode~
~Nuser level -> user mode~
~BThe aspects of this implemention discussed here are as follows:~
~
~M1) MUTL implementation features~
~N2) Interrupt level entry~
~N3) Process structure~
~N4) User access to organisational commands~
~N5) Validation of user addresses~
~N6) Trapping user faults~
~N7) Memory mapping~
~S1~O3.1.1 MUTL Implementation Features~
~BThe MUTL features of relevance to this description are the
the structure of a procedure stack frame and the structure of the
system jump table.~
~3
~
   | local vars | CH | MS | AP | FP | PC | XNB | ARG | params |~
 ~O                                                                 ~O~
   |            |~
   SF           FP~
~
~M~OFig. 1 Stack frame structure~
~
   CH - Condition Handler~
   MS - Mask~
   AP - Argument Pointer~
   FP - Frame Pointer~
   PC - Program Counter~
   SF - Stack Front~
   XNB - Non-local Name Base~
   ARG - Argument Number~
~0
~
~ONOTES~
~T$ 6
~
1)~IThe term XNB comes from the MUTL implementation. All other
terms are as defined in the Architecture Handbook.~
~
2)~IThe compiler ensures that stacks are always longword aligned.~
~
3)~IPre-procs and post-procs are implemented as subroutines (using
JSB and RSB as opposed to CALLS and RET for normal procedures)
for faster running and so do not have a stack frame. This
is why local variables, whether explicitly declared or compiler generated,
are not allowed in these types of procedure.~
~BThe system jump table is essentially a list of the addresses of
all the organisational commands. Its purpose is to facilitate user
calls to these commands. The system jump table is situated
at the top of the segment containing paged system code .~
~BThe system jump table consists of four bytes which give the start
address of the code in the segment followed by a number of jump table entries.~
~BA jump table entry is eight bytes long and structure is as follows:~
~T% 15
~
%Entry Mask (2 bytes)~
%Instruction to Jump to Procedure code (6 bytes)~
~BThe entry mask specifies the registers to be stacked and the overflow
enables to be set on entry to the procedure. General Register 11 (R11)
is the only register so stacked as it is used as the XNB by MUTL.~
~BThe address supplied in the jump instruction takes account of the
entry mask planted with the procedure code.~

~S1~O3.1.2 Interrupt level entry~
~BThere are many cases where command level procedures need to call
interrupt level procedures. Since this cannot be done directly the
mechanism described below is adopted.~
~
~ONOTE~
~
INT.MC.CONTROL.POST.PROC is an unusual procedure in that while most
of its code is executed at interrupt level, a small amount is executed
at command level.~
~BThe major steps involved in calling an interrupt level procedure
from command level are as follows:~
~T$ 6
~
1)~IThe number one is written to V.INT.MC.CONTROL at process level.~
~
2)~IThis invokes V.INT.MC.CONTROL.POST.PROC and as V.INT.MC.CONTROL is
non-zero a CHMK instruction is issued.~
~
3)~IThe code that handles the resulting trap calls ENTER.INT.LEVEL.INTERRUPT
which marks a software forced interrupt as pending if the CHMK instruction
was issued at command level and a program fault interrupt otherwise.~
~
4)~IWhen the software forced interrupt is serviced the interrupt
level procedure required, with its parameters, is obtained
from the INT.ENTRY.VARS and called. (See SYSINT13.4).~
~
5)~IRescheduling may occur on return from the interrupt level procedure.
When the process is selected again it is restarted via writing
zero to V.INT.MC.CONTROL~
~
6)~IThe process is restarted with control immediately after the CHMK
instruction in INT.MC.CONTROL.POST.PROC and returning from this
procedure leaves control back at process level.~
~
~ONOTES~
~
1) Events 1, 2 and 6 occur at command level.~
~
2) Events 3, 4 and 5 occur at interrupt level.~
~S1~O3.1.3 Process structure~
~BThe process dependent information is stored in the Process
Control Block (PCB) and the Process Register Block (PRB).
~BThe PCB contains the dumped hardware registers. The dumping and
undumping of the hardware registers is achieved by the use of the
LDPCTX and SVPCTX instructions (See Hardware Handbook).
The PCBs are part of the locked data.~
~BThe PRB is described in SYS Section 13. PRBs are part of the paged data.~
~BThe process dependent data was divided between the PCB and the PRB for
the following reasons:~
~
1)~IThe PCB and the PRB between them contain more than a page of information.~
~
2)~IThe desire to restict the amount of paged process dependent data to a
page.~
~
3)~IThe relatively small size of the PRB.~
~
4)~IThe convenience of having the data which is accessed by the hardware
using real addressing as locked data.~
~S1~O3.1.4 User access to organisational commands~
~BOrganisational commands are command level procedures which can be called
by the user. This necessitates a change from user level to command level.
Organisational commands run on the user stack in the same way as user
procedures but with executive privileges.~
~BCalls to organisational commands are achieved in the following
manner: the parameters are stacked as usual for a procedure call;
the argument number is stacked; a CHME instruction is issued with
the FINDN index of the command as parameter (see LIB Section 2 Version 2).~
~BThe executive stack is a reserved portion at the bottom of
the user stack.~
~3
~
   | ARG | params | user stack |             | FI | PC | PSL |~
 ~O                                 ~O         ~O                     ~O~
   |                           |             |               |~
  USP                        USB           ESP             ESB~
~
~M~OFig. 2 User stack on issue of CHME instruction~
~
   FI - FINDN Index~
   PSL - Process Status Longword~
   USP - User Stack Pointer~
   USB - User Stack Base~
   ESP - Executive Stack Pointer~
   ESB - Executive Stack Base~
~0
~BThe CHME interrupt handling code calls CMD.ENTRY.INTERRUPT
with an argument number of one in order to make the FINDN index
a parameter to the procedure.~
~BOn return from the organisational command the USP is reset so
that the user stack is in the state it was in before the call
to the organisational command was initiated.~
~3
~Q 7
~
   | user stack |            | PC | PSL |~
 ~O                  ~O        ~O                ~O~
   |            |            |          |~
  USP          USB          ESP        ESB~
~
~M~OFig. 3 User stack on exit from CMD.ENTRY.INTERRUPT~
~0
~BOn exit from CMD.ENTRY.INTERRUPT control returns to the CHME
interrupt handling code where an REI instruction is obeyed. This uses the
PC and PSL on the executive stack to return to the user process.~
~BThis return to user mode causes an Asynchronous System Trap (AST)
to occur (the AST-LVL must be set appropriately prior to this return:
at present it is set in SET.USP) which is serviced by
RETURN.TO.USER.INTERRUPT. The return to user mode is trapped because
it is necessary to perform some housekeeping operations before
returning to user level. Primarily this involves checking for
user faults detected by the organisational command (see 3.1.6 Trapping user faul
ts).~
~S1~O3.1.5 Validation of user addresses~
~BAll organisational commands which have array pointers as parameters
have the start and end addresses of the arrays checked for valid user
access.~
~BThis is done by appropriate calls to VALIDATE. If the validation fails
the stack is unwound one frame so that the exit from VALIDATE causes an
exit from the calling procedure.~
~BFor this reason the calls to VALIDATE in SYS10.VM.INTERRUPT must always
succeed.~
~S1~O3.1.6 Trapping user faults~
~BWhen a user fault is detected by the system a call to a trap
procedure (of the form TRAP.PROC (NO, REASON)) is forced. This is done
in such a way as to give the appearance of the trap procedure having
been called directly from the user's virtual machine.~
~BThe fault status of a user process is kept in the dumped V.VM.INTS
register in the Process Register Block (PRB). The trap information
maintained in the PRB is described in SYS Section 10.~
~BUser faults are detected by the hardware (e.g illegal instruction,
divide by zero) or by software (e.g unable to open file, segment does
not exist). The handling of faults detected by hardware is different
from the handling of those detected by software in the initial stages
but the final steps are common to both.~
~BUser faults detected by hardware result in an interrupt procedure
writing to V.PF.STATUS and marking a program fault interrupt as pending.
When this is serviced the information in V.PF.STATUS is transfered to
the trap variables in the PRB (See SYS Section 12).
~BUser faults detected by system software result in information being
transfered to the trap variables in the PRB 'directly' via
SYS10.SET.VM.INTS (or SYS10.CMD.SET.VM.INTS).~
~BWhen a process is being reloaded (in INT.MC.CONTROL.POST.PROC)
a check is made to see if V.VM.INTS is non-zero and that the process will
run at user level. If this is the case control is altered to a piece of
command level code which
stacks the user's registers (to enable the trap procedure, if so
required, to reset the user's registers to the values they held when
the trap occurred) and then
calls SYS10.VM.INTERRUPT. This procedure
obtains the relevant trap information and then calls APP.OUTWARD.CALL.~
~3
~
                <    AOC  params    >             <  PS   >~
  | lv | AOC sf | TP | TR | TN | PP | lv | VMI sf | 0 | 0 | user stack~
 ~O                                                                      ~O~
  |    |                            |    |                |~
 ESP  AFP                          VSP  VFP              USP~
~
~M~OFig. 1 User stack after call of APP.OUTWARD.CALL~O~
~
   AOC - APP.OUTWARD.CALL~
   VMI - VM.INTERRUPT~
   ESP - Executive stack pointer~
   AFP - APP.OUTWARD.CALL Frame Pointer~
   VSP - VM.INTERRUPT Stack Pointer~
   VFP - VM.INTERRUPT Frame Pointer~
   USP - User Stack Pointer~
   PS - Space for TRAP.PROC Parameters~
   TP - TRAP.PROC Address~
   TR - Trap Reason~
   TN - Trap Number~
   PP - PRB Pointer~
   lv - local variables~
   sf - stack frame~
~Q 19
~
                                                               user~
  | TP | PSL | CH | MS | UAP | UFP | DPC | XNB | 2 | TR | TN | stack~
 ~O                                                                     ~O~
  |          |                                               |~
 ESP        FP                                              OLD~
            USP                                             USP~
~
~M~OFig. 2 User stack just before return from APP.OUTWARD.CALL~
~
   PSL - New Process Status Longword (set to user level)~
   UAP - User Argument Pointer~
   UFP - User Frame Pointer~
   DPC - Dumped Program Counter (from PRB)~
   XNB - Non-local Name Base~
   CH - Condition Handler~
   MS - Mask~
   FP - Frame Pointer~
~
~0
~BThus when the user process is rescheduled the trap procedure
is entered as if it was a user procedure called by the user.~
~S1~O3.1.7 Memory mapping~
~BThe hardware segment table (HST) and the hardware common segment
table (C.HST) form the main interface between the MUSS and the VAX
memory management systems.~
~BThe HST holds the local segment entries of the currently executing
process and is mapped onto the P0 region of the VAX address space.
The C.HST holds the common segment entries and is mapped onto the
P1 region. Both tables are accessed as V-store.~
~BThe HST and the C.HST form those areas of the system space page
table which map, respectively, the P0 and the P1 regions of the VAX
address space. This arrangement is required by the VAX architecture.~
~BThe system space page table consists of the real store page table,
the unibus page table, the HST, and the C.HST. Real addresses are
translated into system addresses (and vice versa) by setting (clearing)
the top bit of the real address.~
~3
~Q4
~
   | real store page table | unibus page table | C.HST | HST |~
   ~O                                                           ~O~
~
~M~OFig 1. Layout of system page table~
~S1~O3.2 Data Structures~
~3
~T%36
~
~
APP.STATS.TYPE~IData relevant to system statistics.~
   :CMDS.CALLED~IThe number of organisational commands called.~
   :SYSTEM.TIME~IThe time spent at system level.~
   :USER.TIME~IThe time spent at user level.~
   :IDLE.TIME~IThe time spent idling.~
   :LOST.TIME~IThe time spent while all the scheduled activities
are halted.~
~
REG.DUMP.SIZE~IThis literal gives the number of dumped registers
in the Process Register Block.~
~
DUMPED.V.EXEC.MC.CONTROL.REG.NO~IThis literal indexes
the DUMPED.V.EXEC.MC.CONTROL register in the Process Register Block.~
~
DUMPED.V.VM.INTS.REG.NO~IThis literal indexes the
DUMPED.V.VM.INTS register in the Process Register Block.~
~
DUMPED.V.VM.TIMER.REG.NO~IThis literal indexes the
DUMPED.V.VM.TIMER register in the Process Register Block.~
~
DUMPED.PC.REG.NO~IThis literal indexes the
DUMPED.PC register in the Process Register Block.~
~
DUMPED.V.VAL.ACCESS.REG.NO~IThis literal indexes the
DUMPED.V.VAL.ACCESS register in the Process Register Block.~
~
DUMPED.V.INT.MC.CONTROL.REG.NO~IThis literal indexes the
DUMPED.V.INT.MC.CONTROL register in the Process Register Block.~
~
DUMPED.PSL.REG.NO~IThis literal indexes the
DUMPED.PSL register in the Process Register Block.~
~
DUMPED.ICR.REG.NO~IThis literal indexes the DUMPED.ICR register in
the Process Register Block. DUMPED.ICR holds the number of microseconds
to the next V.VM.TIMER tick.~
~
INT.PENDING~IIf this logical variable is non-zero it indicates
that an ideal machine interrupt is outstanding.~
~
INT.TYPE~IThe value of this logical variable indicates
the type of ideal machine interrupt outstanding.~
~
AT.INT.LEVEL~IThis logical variable is set immediately prior
to entering interrupt level and cleared on exit from interrupt level.~
~
LAST.SECS.VALUE~IThis logical variable gives the most
recent value, in seconds, obtained from the TIME OF DAY REGISTER.~
~
PREV.PROCESS.NUMBER~IThis logical variable gives the system process number
of the process running before context was changed to service an
ideal machine interrupt.~
~
INIT.REGS.COUNT~IThis integer variable is used in INIT.REGS.POST.PROC.~
~
WORDS.PER.PAGE~IThis integer 'literal' gives the number
of 32-bit words in a Vax page.~
~
INIT.TRAP.FLAG~IThis integer variable is used in SYSTEM.ERROR.INTERRUPT
to determine if the interrupt was due to a non-existent device.~
LINK.ADDRESS~IThis array of logical 'literals' gives the
addresses of the ideal machine interrupt handler labels.~
~
BUFFER~IThis byte pointer is used in
READ.BYTE.POST.PROC and WRITE.BYTE.POST.PROC.~
~
PCB.PTR~IThis array pointer is used in INT.MC.CONTROL.POST.PROC
to access the Process Control Block.~
~
INIT.REGS.PCB.PTR~IThis array pointer is used in INIT.REGS.POST.PROC
to access the Process Control Block.~
~
PRB.PTR~IThis array pointer is used in END.VAX11.INT and
INT.MC.CONTROL.POST.PROC to access the Process Register Block.~
~
INIT.REGS.PRB.PTR~IThis array pointer is used in INIT.REGS.POST.PROC
to access the Process Register Block.~
~
APP.STATS~IThis pointer is used
to access an APP.STATS.TYPE variable.~
~
FIXED.ADDRESS~IThis V-line is at a known address to enable the
privileged registers to be written to, and read from. It is
used in the module initialisation, END.VAX11.INT and
INT.MC.CONTROL.POST.PROC when hardware interrupts are inhibited.~
~
INT.ENTRY.ADDRESS~IThis V-line is at a known address to enable access
to the stack and the stack pointer (R14). It is used in
INT.MC.CONTROL.POST.PROC when process based interrupts are inhibited.~
~
REAL.TIME~IThis V-line is at a known address to enable access
to the real-time clock (TODR). It is used in SECONDS.CLOCK,
UPDATE.IDLE.TIME, MILLI.TIME.PROC and
in the module initialisation.~
~
BIT.POSN~IThis datavector is used in BIT.~
~
BIT.POSN8~IThis datavector is used in SET.BIT and TEST.BIT.~
~
BIT.MASK8~IThis datavector is used in CLEAR.BIT.~
~
HST~IThis vector is the hardware segment table for
local segments.~
~
C.HST~IThis vector is the hardware segment table for
common segments.~
~S1~O3.3 Special Notes~
~0
~BIt is possible for an interval timer interrupt to be lost
if it occurs just after a CHMK interrupt. For this reason a small
negative number is written to the next interval count register
so that if the interrupt is lost another one will immediately occur
when the process is re-entered.~
~BV.CALL.LINK and V.EXIT.LINK map onto the same address as does REAL.TIME
but there is no inconsistency as process based interrupts are inhibited
when any of these V-lines is used.~
~BV.APP.LINK maps onto the same address as does FIXED.ADDRESS
but there is no inconsistency as hardware interrupts are inhibited
when either V-line is used.~
~Y
~V9 -1
~P
~D15
~HFLOWCHARTS
~
~
~H                AP3011
~V9 -1
~F
@TITLE AP301(1,11)
@COL 1S-2R-3R-4R-5R-6F
@FLOW 1-2-3-4-5-6
@BOX 1.0
VAX11/750 PROCESSOR APPENDIX
@BOX 4.0
PROCEDURES IN MODULE
[AP301/3]
@BOX 6.0
END
@BOX 1.1
#AP301/1
MODULE (V.HW.INTS, V.SW.INTS, V.HALT.MASK, V.FI, V.INT.MC.CONTROL,
   V.EXEC.MC.CONTROL, V.PF.STATUS, V.TIME, V.MILLI.TIME,
   V.CLOCK, V.VM.INTS, V.INTERRUPT.TYPE, V.CLEAR.PAGE,
   V.NEQ.SEG, V.NEQ.BLK, V.NEQ.ACCESS, V.VAL.ACCESS, V.CALL.LINK,
   V.EXIT.LINK, V.SF, V.PROCESS.NUMBER, V.DUMPED.CONTROL, V.INIT.REGS,
   V.PRB.RA, V.STACK.SEG, V.MC.NO, V.RESET.STATUS, V.RESET.SEG,
   V.RESET.BLK, V.BYTE, V.READ.BYTE, V.WRITE.BYTE, V.APP.LINK,
   EMPTY.ACTIVITY, SET.HW.INT, CLEAR.HW.INT, UPDATE.IDLE.TIME,
   FAULT.INTERRUPT, SYSTEM.ERROR.INTERRUPT, ENTER.INT.LEVEL.INTERRUPT,
   V.CORE.PAGE, V.CORE.DATA,
   INTERVAL.TIMER.INTERRUPT, MEMORY.MANAGEMENT.INTERRUPT,
   RETURN.TO.USER.INTERRUPT, MS.BIT, BIT, SET.BIT, CLEAR.BIT,
   TEST.BIT, CHECK.ADDRESS, VALIDATE, CMD.ENTRY.INTERRUPT,
   APP.OUTWARD.CALL, INIT.TRAP.FLAG, APP.STATS.TYPE, REG.DUMP.SIZE,
   DUMPED.V.VM.INTS.REG.NO, DUMPED.V.VM.TIMER.REG.NO, DUMPED.V.VAL.ACCESS.REG.NO
,
   ALLOW.INTERRUPTS, INHIBIT.INTERRUPTS, MAP.IO.APP, UNMAP.IO.APP, INIT.AP301);
@BOX 2.1
TYPE APP.STATS.TYPE IS
   INTEGER32 CMDS.CALLED, SYSTEM.TIME, USER.TIME, IDLE.TIME, LOST.TIME, PAGE.FAU
LTS;
@BOX 3.1
#AP301/2
@BOX 4.1
#AP301/3
@BOX 5.1
*CODE 7;
PSPEC INIT.AP301 ();
PROC INIT.AP301;
:: INITIALISE INTERRUPT VECTORS
#AP301/4
1 => VV.MC.NO;
1 => VV.INT.MC.CONTROL => AT.INT.LEVEL;
SYS14.PAGE.SIZE / BYTES.PER.WORD => WORDS.PER.PAGE;
SYS14.SEG.SIZE - RESERVED.STACK.BOTTOM => USER.STACK.BASE;
-1 => PREV.PROCESS.NUMBER;
*#%DB %1B %9F %0C %00 %03 %80; :: MFPR #TODR, @#REAL.TIME
REAL.TIME => BOOT.TIME;
REAL.TIME ->> 1 / 50 => LAST.SECS.VALUE;
83 * 15768000 <<- 1 + LAST.SECS.VALUE => VV.TIME;
:: YEAR * SECONDS IN YEAR + (TODR / 100) => VV.TIME
MAKE (APP.STATS.TYPE, 0, SYS21.GET.STATS (0)) => APP.STATS;
END
@BOX 6.1
*END
@END
@TITLE AP301/1(1,11)
@COL 1S-2R-3R-4R
@FLOW 1-2-3-4
@BOX 1.0
OTHER MODULES REFERENCED
@BOX 4.0
SYS01 COORDINATOR
SYS02 CORE MANAGER
SYS10 VIRTUAL MACHINE INTERRUPTS
SYS11 VIRTUAL MACHINE TIMER
SYS12 FAULT CONDITIONS
SYS13 PROCESS MANAGEMENT
SYS14 VIRTUAL STORE MANAGEMENT
SYS21 PERFORMANCE MONITORING
@BOX 1.1
:: EXTERNAL ENVIRONMENT
@BOX 2.1
IMPORT LITERAL ILLEGAL.ORDER, RESERVED.STACK.BOTTOM,
   RESERVED.STACK.TOP, NO.OF.COMMANDS, BYTES.PER.WORD,
   P0.BASE, P0.LIMIT, P1.BASE, P1.LIMIT;
IMPORT VSTORE LOGICAL HST [], C.HST [];
LOGICAL NEQ.VIRTUAL.ADDRESS, NEQ.FAIL.STATUS;
@BOX 3.1
PSPEC POLL.DEVICES ();
PSPEC MT.POLL ();
@BOX 4.1
ADDR PW0;
PSPEC RK07.DISC.INT (INTEGER);
PSPEC TM11.INT (INTEGER);
PSPEC GCT.INT (INTEGER);
IMPORT LITERAL SYS01.INT.ACTIVITIES, SYS01.CLOCK.ACTIVITY,
   SYS01.PZ.ACTIVITY, SYS01.NO.OF.ACTIVITIES;
LOGICAL SYS01.CURRENT.ACTIVITY.BIT;
INTEGER SYS01.CURRENT.ACTIVITY;
ADDR [SYS01.NO.OF.ACTIVITIES] INITIAL.KERNEL.STACK;
PSPEC SYS01.SET.INTERRUPT (LOGICAL, LOGICAL);
IMPORT LITERAL SYS02.CORE.PAGE.SIZE;
PSPEC SYS10.PROC.TYPE (INTEGER, INTEGER);
PSPEC SYS10.SET.VM.INT (INTEGER, LOGICAL);
PSPEC SYS10.VM.INTERRUPT ();
PSPEC SYS12.SYSTEM.ERROR (INTEGER);
IMPORT LITERAL SYS13.NO.OF.PROCS;
TYPE PCB.TYPE IS LOGICAL [24] PCB;
PCB.TYPE [SYS13.NO.OF.PROCS] PCBS;
PSPEC SYS13.INT.PROC (LOGICAL, LOGICAL);
PSPEC SYS13.ENTER.INT.LEVEL (ADDR SYS13.INT.PROC, LOGICAL, LOGICAL);
PSPEC SYS13.INT.GET.PRB (INTEGER) / ADDR;
PSPEC SYS13.GET.PRB (INTEGER, INTEGER) / ADDR;
IMPORT LITERAL SYS14.NO.OF.LOCAL.SEGS, SYS14.NO.OF.COMMON.SEGS,
   SYS14.NO.OF.SYS.SEGS, SYS14.SEG.SIZE, SYS14.FIRST.COMMON.SEG,
   SYS14.PT.SEG, SYS14.PAGE.SIZE, SYS14.PAGE.SHIFT,
   SYS14.REAL.STORE.ADDRESS, SYS14.NO.OF.X.SEGS;
TYPE SYS14.LST.TYPE IS
   LOGICAL8 ACCESS, SSN
OR
   LOGICAL16 LST.ENTRY;
TYPE SYS14.SST.TYPE IS
   INTEGER LIMIT, COUNT, PAGE.COUNT
   LOGICAL8 STATUS
OR
   INTEGER SST.LINK;
TYPE SYS14.SEG.VARS IS
   SYS14.LST.TYPE [SYS14.NO.OF.LOCAL.SEGS] LST
   SYS14.LST.TYPE [SYS14.NO.OF.X.SEGS] XST
   INTEGER SSN1, BLK1, SSN2, BLK2;
SYS14.SST.TYPE [SYS14.NO.OF.SYS.SEGS] SYS14.SST;
SYS14.LST.TYPE [SYS14.NO.OF.COMMON.SEGS] SYS14.CST;
LOGICAL [SYS14.NO.OF.SYS.SEGS] SYS14.SST.PT;
PSPEC SYS21.GET.STATS (INTEGER) / ADDR;
@END
@TITLE AP301/2(1,11)

@COL 1S
@BOX 1.0
DECLARATIONS
@BOX 1.1
*GLOBAL 5;
LITERAL / INTEGER REG.DUMP.SIZE = 8,
   DUMPED.V.EXEC.MC.CONTROL.REG.NO = 0, DUMPED.V.VM.INTS.REG.NO = 1,
   DUMPED.V.VM.TIMER.REG.NO = 2, DUMPED.PC.REG.NO = 3,
   DUMPED.V.VAL.ACCESS.REG.NO = 4, DUMPED.V.INT.MC.CONTROL.REG.NO = 5,
   DUMPED.PSL.REG.NO = 6, DUMPED.ICR.REG.NO = 7;
LOGICAL VV.HW.INTS, VV.SW.INTS, VV.HALT.MASK, VV.FI, VV.INT.MC.CONTROL,
   VV.PF.STATUS, VV.TIME, VV.MILLI.TIME, VV.CLOCK, VV.NEQ.SEG, VV.NEQ.BLK,
   VV.NEQ.ACCESS, VV.VAL.ACCESS, VV.PROCESS.NUMBER, VV.MC.NO, VV.INTERRUPT.TYPE,
   VV.EXEC.MC.CONTROL, VV.VM.INTS, VV.INIT.REGS,  VV.STACK.SEG, VV.PRB.RA,
   VV.RESET.STATUS, VV.RESET.SEG, VV.RESET.BLK, VV.CORE.PAGE, VV.CORE.DATA,
   VV.CLEAR.PAGE;
ADDR VV.DUMPED.CONTROL, VV.SF;
LOGICAL INT.PENDING, INT.TYPE, AT.INT.LEVEL, LAST.SECS.VALUE,
   PRESENT.SECS.VALUE, PREV.PROCESS.NUMBER;
INTEGER INIT.REGS.COUNT, WORDS.PER.PAGE, INIT.TRAP.FLAG,
   BOOT.TIME, USER.STACK.BASE, RAW.IDLE.TIME, RAW.LOST.TIME, RAW.ELAPSED.TIME,
   INDEX;
ADDR LOGICAL8 BUFFER;
ADDR [LOGICAL] PCB.PTR, PRB.PTR, INIT.REGS.PCB.PTR, INIT.REGS.PRB.PTR;
ADDR APP.STATS.TYPE APP.STATS;
ADDR LOGICAL CORE.PTR;
ADDR [LOGICAL64] CLEAR.PTR;
::
:: VSTORE DECLARATIONS
::
VSTORE V.HW.INTS VV.HW.INTS;
VSTORE V.SW.INTS VV.SW.INTS > INT.TREE.POST.PROC.1;
VSTORE V.HALT.MASK VV.HALT.MASK > INT.TREE.POST.PROC.2;
VSTORE V.FI VV.FI < SECONDS.CLOCK;
VSTORE V.INT.MC.CONTROL VV.INT.MC.CONTROL > INT.MC.CONTROL.POST.PROC;
VSTORE V.EXEC.MC.CONTROL VV.EXEC.MC.CONTROL;
*VTYPE ADDR;
VSTORE V.CALL.LINK %8003000C < CALL.LINK.PRE.PROC;
VSTORE V.EXIT.LINK %8003000C > EXIT.LINK.POST.PROC;
VSTORE V.SF VV.SF < SF.PRE.PROC;
VSTORE V.DUMPED.CONTROL VV.DUMPED.CONTROL;
*VTYPE LOGICAL;
VSTORE V.INTERRUPT.TYPE VV.INTERRUPT.TYPE;
VSTORE V.STACK.SEG VV.STACK.SEG;
VSTORE V.PROCESS.NUMBER VV.PROCESS.NUMBER;
VSTORE V.INIT.REGS VV.INIT.REGS > INIT.REGS.POST.PROC;
VSTORE V.MC.NO VV.MC.NO;
VSTORE V.PRB.RA VV.PRB.RA;
VSTORE V.PF.STATUS VV.PF.STATUS;
VSTORE V.VM.INTS VV.VM.INTS;
VSTORE V.RESET.STATUS VV.RESET.STATUS > RESET.STATUS.POST.PROC;
VSTORE V.RESET.SEG VV.RESET.SEG;
VSTORE V.RESET.BLK VV.RESET.BLK;
VSTORE V.TIME VV.TIME > TIME.POST.PROC;
VSTORE V.MILLI.TIME VV.MILLI.TIME < MILLI.TIME.PRE.PROC;
VSTORE V.CLOCK VV.CLOCK > CLOCK.INT.POST.PROC;
VSTORE V.NEQ.SEG VV.NEQ.SEG;
VSTORE V.NEQ.BLK VV.NEQ.BLK;
VSTORE V.NEQ.ACCESS VV.NEQ.ACCESS;
VSTORE V.VAL.ACCESS VV.VAL.ACCESS;
VSTORE V.APP.LINK %80030008 < APP.LINK.PRE.PROC > APP.LINK.POST.PROC;
VSTORE FIXED.ADDRESS %80030008;
VSTORE REAL.TIME %8003000C;
VSTORE CALL.LINK.TIME %8003007C;
VSTORE RAW.USER.TIME %80030080;
VSTORE V.CORE.PAGE VV.CORE.PAGE;
VSTORE V.CORE.DATA VV.CORE.DATA < CORE.DATA.PRE.PROC > CORE.DATA.POST.PROC;
VSTORE V.CLEAR.PAGE VV.CLEAR.PAGE > CLEAR.PAGE.POST.PROC;
*VTYPE INTEGER32;
VSTORE V.VM.TIMER %80030050;
*VTYPE LOGICAL;
::
:: MACHINE FUNCTIONS
::
LOGICAL VV.ALLOW.INTERRUPTS, VV.INHIBIT.INTERRUPTS, VV.MAP.IO.APP,
   VV.UNMAP.IO.APP;
VSTORE MAP.IO.APP VV.MAP.IO.APP;
VSTORE UNMAP.IO.APP VV.UNMAP.IO.APP;
VSTORE ALLOW.INTERRUPTS VV.ALLOW.INTERRUPTS < ALLOW.INTERRUPTS.PRE.PROC;
VSTORE INHIBIT.INTERRUPTS VV.INHIBIT.INTERRUPTS < INHIBIT.INTERRUPTS.PRE.PROC;
::
DATAVEC BIT.POSN (LOGICAL)
   %80000000 %40000000 %20000000 %10000000
   %08000000 %04000000 %02000000 %01000000
   %00800000 %00400000 %00200000 %00100000
   %00080000 %00040000 %00020000 %00010000
   %00008000 %00004000 %00002000 %00001000
   %00000800 %00000400 %00000200 %00000100
   %00000080 %00000040 %00000020 %00000010
   %00000008 %00000004 %00000002 %00000001
END
DATAVEC BIT.POSN8 (LOGICAL8)
   %80 %40 %20 %10
   %08 %04 %02 %01
END
DATAVEC BIT.MASK8 (LOGICAL8)
   %7F %BF %DF %EF
   %F7 %FB %FD %FE
END
@END
@TITLE AP301/3(1,11)

@COL 1S
@BOX 1.0
PROCEDURES IN MODULE:
    1 UPDATE INTERRUPT TREE
    2 SET HW INT
    3 CLEAR HW INT
    4 INT TREE POST PROC
    5 FAULT INTERRUPT
    6 SYSTEM ERROR INTERRUPT
    7 ENTER INT LEVEL INTERRUPT
    8 END VAX11 INT
    9 INT MC CONTROL POST PROC
   10 CLOCK INT POST PROC
   11 SECONDS CLOCK
   12 INTERVAL TIMER INTERRUPT
   13 RESET STATUS POST PROC
   14 CALL LINK PRE PROC
   15 EXIT LINK POST PROC
   16 RELOAD HST
   17 MS BIT
   18 BIT
   19 SET BIT
   20 CLEAR BIT
   21 TEST BIT
   22 VALIDATE
   23 CMD ENTRY INTERRUPT
   24 INIT REGS POST PROC
   25 APP OUTWARD CALL
   26 ALLOW INTERRUPTS PRE PROC
   27 INHIBIT INTERRUPTS PRE PROC
   28 TIME POST PROC
   29 TIME PROC
   30 SF PRE PROC
   31 CORE DATA PRE PROC
   32 CORE DATA POST PROC
   33 SET USP
   34 MEMORY MANAGEMENT INTERRUPT
   35 CHECK ADDRESS
   36 RETURN TO USER INTERRUPT
   37 APP LINK PRE PROC
   38 APP LINK POST PROC
   39 RAW INTERRUPT ROUTINES (BASIC CPU)
   40 RAW INTERRUPT ROUTINES (MISCELLANEOUS)
   41 MILLI TIME PRE PROC
   42 MILLI TIME PROC
   43 UPDATE IDLE TIME
   44 CLEAR PAGE POST PROC
@BOX 1.1
*CODE 2;
:: END.VAX11.INT
PSPEC SET.HW.INT (LOGICAL);
PSPEC CLEAR.HW.INT (LOGICAL);
:: PSPEC INT.TREE.POST.PROC ();
PSPEC FAULT.INTERRUPT (INTEGER);
PSPEC SYSTEM.ERROR.INTERRUPT (INTEGER);
PSPEC ENTER.INT.LEVEL.INTERRUPT (INTEGER);
:: PSPEC SECONDS.CLOCK ();
PSPEC INTERVAL.TIMER.INTERRUPT (INTEGER);
PSPEC RELOAD.HST ();
:: PSPEC ALLOW.INTERRUPTS.PRE.PROC ();
:: PSPEC INHIBIT.INTERRUPTS.PRE.PROC ();
PSPEC TIME.PROC (LOGICAL, LOGICAL);
:: PSPEC CORE.DATA.PRE.PROC ();
:: PSPEC CORE.DATA.POST.PROC ();
PSPEC SET.USP (LOGICAL, LOGICAL);
PSPEC MEMORY.MANAGEMENT.INTERRUPT (INTEGER);
PSPEC RETURN.TO.USER.INTERRUPT (INTEGER);
:: PSPEC APP.LINK.PRE.PROC ();
:: PSPEC APP.LINK.POST.PROC ():
PSPEC MILLI.TIME.PROC (LOGICAL, LOGICAL);
:: PSPEC MILLI.TIME.PRE.PROC();
PSPEC UPDATE.IDLE.TIME ();
:: PSPEC CLEAR.PAGE.POST.PROC ();
   #AP301.8
   #AP301.2
   #AP301.3
   #AP301.4
   #AP301.5
   #AP301.6
   #AP301.7
   #AP301.11
   #AP301.12
   #AP301.16
   #AP301.26
   #AP301.27
   #AP301.29
   #AP301.31
   #AP301.32
   #AP301.33
   #AP301.34
   #AP301.36
   #AP301.37
   #AP301.38
   #AP301.39
   #AP301.40
   #AP301.41
   #AP301.42
   #AP301.43
   #AP301.44
PSPEC EMPTY.ACTIVITY ();
PROC EMPTY.ACTIVITY;
   SYS12.SYSTEM.ERROR (-1);
END
*CODE 11;
:: PSPEC INT.MC.CONTROL.POST.PROC ();
PSPEC MS.BIT (LOGICAL) / INTEGER;
PSPEC BIT (INTEGER) / LOGICAL;
PSPEC SET.BIT (ADDR [LOGICAL8], INTEGER);
PSPEC CLEAR.BIT (ADDR [LOGICAL8], INTEGER);
PSPEC TEST.BIT (ADDR [LOGICAL8], INTEGER) / INTEGER;
   #AP301.9
   #AP301.17
   #AP301.18
   #AP301.19
   #AP301.20
   #AP301.21
*CODE 2;
*GLOBAL 5;
:: PSPEC CLOCK.INT.POST.PROC ();
:: PSPEC RESET.STATUS.POST.PROC ();
:: PSPEC CALL.LINK.PRE.PROC ();
:: PSPEC EXIT.LINK.POST.PROC ();
PSPEC CHECK.ADDRESS (LOGICAL) / LOGICAL;
   #AP301.10
   #AP301.13
   #AP301.14
   #AP301.15
   #AP301.35
*CODE 15;
PSPEC VALIDATE (ADDR, LOGICAL) / INTEGER;
PSPEC CMD.ENTRY.INTERRUPT (INTEGER);
:: PSPEC INIT.REGS.POST.PROC ();
PSPEC APP.OUTWARD.CALL (ADDR, INTEGER, INTEGER, ADDR SYS10.PROC.TYPE);
:: PSPEC TIME.POST.PROC ();
:: PSPEC SF.PRE.PROC ();
   #AP301.22
   #AP301.23
   #AP301.24
   #AP301.25
   #AP301.28
   #AP301.30
@END
@TITLE AP301/4(1,10)
@COL 1S
@BOX 1.0
INITIALISE INTERRUPT VECTORS
@BOX 1.1
INTEGER I;
*VTYPE LOGICAL32;
VSTORE INT.STORE [%FFFF] %80040000;
*VTYPE LABEL;
VSTORE VEC.LABEL %80043400;
*VTYPE LOGICAL32;
VSTORE VEC.ADDR %80043400;
#AP301/4.1
UNASSIGNED.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C00];
MACHINE.CHECK.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C01];
KERNEL.STACK.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C02];
POWER.FAIL.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C03];
RESERVED.INST.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C04];
CUST.RESERVED.INST.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C05];
RESERVED.OPND.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C06];
RESERVED.ADDRESSING.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C07];
ACCESS.VIOLATION.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C08];
TRANSLATION.FAIL.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C09];
TRACE.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C0A];
BPT.TRAP.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C0B];
COMPATABILITY.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C0C];
ARITHMETIC.TRAP.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C0D];
CHMK.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC => INT.STORE [%C10];
CHME.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC => INT.STORE [%C11];
CHMS.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC => INT.STORE [%C12];
WRITE.TIMEOUT.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C18];
AST.TRAP.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C22];
TIMER.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C30];
GENISCO.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%C9A];
RK07.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%CA2];
TAPE11.INT => VEC.LABEL;
VEC.ADDR + 3 & %FFFFFFFC + 1 => INT.STORE [%CA5];
::SIZE (INT.VECTORS) = 23
FOR I < 23 DO
   BYTE (INT.PROCS [I]) => INT.STORE [INT.VECTORS [I] + %D00];
OD
@END
@TITLE AP301/4.1(1,10)
@COL 1S
@BOX 1.0
INITIALISE INTERRUPT VECTORS
@BOX 1.1
DATAVEC INT.VECTORS (INTEGER)
   %00 ::UNASSIGNED INT
   %01 ::MACHINE CHECK
   %02 ::KERNEL STACK
   %03 ::POWER FAIL
   %04 ::RESERVED INSTRUCTION
   %05 ::CUST RESERVED INSTRUCTION
   %06 ::RESERVED OPERAND
   %07 ::RESERVED ADDRESSING
   %08 ::ACCESS VIOLATION
   %09 ::TRANSLATION FAIL
   %0A ::TRACE PENDING
   %0B ::BPT TRAP
   %0C ::COMPATABILITY
   %0D ::ARITHMETIC TRAP
   %10 ::CHMK
   %11 ::CHME
   %12 ::CHMS
   %18 ::WRITE TIMEOUT
   %22 ::AST TRAP
   %30 ::INTERVAL TIMER
   %9A ::GENISCO
   %A2 ::RK07 DISCS
   %A5 ::TM11 TAPES
END
DATAVEC INT.PROCS (ADDR SYSTEM.ERROR.INTERRUPT)
   SYSTEM.ERROR.INTERRUPT [4]
   FAULT.INTERRUPT [4]
   MEMORY.MANAGEMENT.INTERRUPT [2]
   FAULT.INTERRUPT [4]
   ENTER.INT.LEVEL.INTERRUPT
   CMD.ENTRY.INTERRUPT [2]
   SYSTEM.ERROR.INTERRUPT
   RETURN.TO.USER.INTERRUPT
   INTERVAL.TIMER.INTERRUPT
   GCT.INT
   RK07.DISC.INT
   TM11.INT
END
@END


@TITLE AP301.1(1,6)
@COL 1S-2R-3T-4R-5F
@FLOW 1-2-3NO-4-5
@FLOW 3YES-5
@BOX 1.0
UPDATE INTERRUPT TREE
@BOX 2.0
GENERATE NEW VALUE OF
FREE INDICATOR
@BOX 3.0
AT MUSS INTERRUPT LEVEL?
@BOX 4.0
NOTE SYSTEM BASED
INTERRUPT REQUIRED
@BOX 5.0
END
@BOX 1.1
UPDATE.INTERRUPT.TREE: BEGIN;
@BOX 2.1
VV.HW.INTS ! VV.SW.INTS ! VV.HALT.MASK -= VV.HALT.MASK => VV.FI;
@BOX 3.1
IF AT.INT.LEVEL /= 0
   OR VV.FI & SYS01.INT.ACTIVITIES = 0
@BOX 4.1
1 => INT.PENDING;
@BOX 5.1
END
@END
@TITLE AP301.2(1,6)
@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
SET HW INT (ACTIVITY)
@BOX 2.0
SET APPROPRIATE BIT
IN V HW INTS
@BOX 3.0
UPDATE INTERRUPT TREE
[AP301.1]
@BOX 4.0
END
@BOX 1.1
PROC SET.HW.INT (ACTIVITY);
@BOX 2.1
ACTIVITY !> VV.HW.INTS;
@BOX 3.1
#AP301.1
@BOX 4.1
END
@END
@TITLE AP301.3(1,6)
@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
CLEAR HW INT (ACTIVITY)
@BOX 2.0
CLEAR APPROPRIATE BIT
IN V HW INTS
@BOX 3.0
UPDATE INTERRUPT TREE
[AP301.1]
@BOX 4.0
END
@BOX 1.1
PROC CLEAR.HW.INT (ACTIVITY);
@BOX 2.1
ACTIVITY & VV.HW.INTS -=> VV.HW.INTS;
@BOX 3.1
#AP301.1
@BOX 4.1
END
@END
@TITLE AP301.4(1,6)
@COL 1S-2F
@FLOW 1-2
@BOX 1.0
INT TREE POST PROC
UPDATE INTERRUPT TREE
[AP301.1]
WITH INTERRUPTS INHIBITED
@BOX 2.0
END
@BOX 1.1
PROC INT.TREE.POST.PROC.1;
   :: INHIBIT INTERRUPTS
   *#%DA %1F %12; :: MTPR #%1F, #IPL
   #AP301.1
   :: ALLOW INTERRUPTS
   *#%DA %00 %12; :: MTPR #%00, #IPL
END
PROC INT.TREE.POST.PROC.2;
   :: INHIBIT INTERRUPTS
   *#%DA %1F %12; :: MTPR #%1F, #IPL
   #AP301.1
   :: ALLOW INTERRUPTS
   *#%DA %00 %12; :: MTPR #%00, #IPL
END
@BOX 2.1
@END
@TITLE AP301.5(1,6)

@COL 1S-2T-5R-6R-4F
@COL 3R
@ROW 3-5
@FLOW 1-2NO-5-6-4
@FLOW 2YES-3-4
@BOX 1.0
FAULT INTERRUPT (REASON)
@BOX 2.0
NOT AT USER LEVEL?
@BOX 3.0
HALT
(SYSTEM ERROR)
@BOX 4.0
END
@BOX 5.0
SET V PF STATUS
@BOX 6.0
NOTE PROCESS BASED
INTERRUPT REQUIRED
@BOX 1.1
PROC FAULT.INTERRUPT (REASON);
@BOX 2.1
IF SYS01.CURRENT.ACTIVITY.BIT & SYS01.PZ.ACTIVITY !
   VV.INT.MC.CONTROL ! VV.EXEC.MC.CONTROL /= 0
@BOX 3.1
*#%00 :: HALT
@BOX 4.1
END
@BOX 5.1
REASON !> VV.PF.STATUS;
@BOX 6.1
1 => INT.PENDING => INT.TYPE;
@END
@TITLE AP301.6(1,6)

@COL 1S-2T-3R-4F
@COL 5R
@ROW 3-5
@FLOW 1-2NO-3-4
@FLOW 2YES-5-4
@BOX 1.0
SYSTEM ERROR INTERRUPT (ERROR)
@BOX 2.0
INITIALIZATION TRAP?
@BOX 3.0
HALT
@BOX 4.0
END
@BOX 5.0
SET FLAG
@BOX 1.1
PROC SYSTEM.ERROR.INTERRUPT (ERROR);
@BOX 2.1
IF ERROR = %18 AND INIT.TRAP.FLAG = 1
@BOX 3.1
*#%00 :: HALT
@BOX 4.1
END
@BOX 5.1
0 => INIT.TRAP.FLAG;
@END
@TITLE AP301.7(1,11)

@COL 1S-2T-3R-4F
@COL 5R
@ROW 3-5
@FLOW 1-2YES-3-4
@FLOW 2NO-5-4
@BOX 1.0
ENTER INT LEVEL INTERRUPT (MODE)
@BOX 2.0
ENTERING FROM COMMAND LEVEL?
@BOX 3.0
PROCESS INTERRUPT
ACCORDING TO MODE
@BOX 4.0
END
@BOX 5.0
NOTE PROGRAM FAULT
INTERRUPT PENDING
@BOX 1.1
PROC ENTER.INT.LEVEL.INTERRUPT (MODE);
@BOX 2.1
IF VV.EXEC.MC.CONTROL = 0
@BOX 3.1
ALTERNATIVE MODE FROM
   2 => INT.PENDING => INT.TYPE;
   BEGIN
      *#%DB %03 %52; :: MFPR #USP, R2
      *#%DA %52 %01; :: MTPR R2, #ESP
   END
   BEGIN
      *#%DB %01 %52; :: MFPR #ESP, R2
      *#%DA %52 %03; :: MTPR R2, #USP
      *#%DA %03 %13; :: MTPR #3, #AST
      PCB [21] OF PCBS [VV.PROCESS.NUMBER] & %F8FFFFFF
         ! %03000000 => PCB [21] OF PCBS [VV.PROCESS.NUMBER];
   END
END
@BOX 4.1
END
@BOX 5.1
ILLEGAL.ORDER !> VV.PF.STATUS;
1 => INT.PENDING => INT.TYPE;
@END
@TITLE AP301.8(1,11)

@COL 1S-9T-2T-6R-3R-4R-5R
@COL 7R-8F
@ROW 3-7
@FLOW 1-9NO-2-6-7-8
@FLOW 9YES-7
@FLOW 2INTERRUPT-3-4-5
@BOX 1.0
END VAX11 INT
@BOX 2.0
IDEAL MACHINE INTERRUPT PENDING?
@BOX 3.0
UNSTACK REGISTERS
DUMP REGISTERS
IN PCB AND PRB
@BOX 4.0
NOTE AT INTERRUPT LEVEL
@BOX 5.0
RETURN TO MUSS INTERRUPT LEVEL
@BOX 6.0
START CLOCK
@BOX 7.0
UNSTACK REGISTERS AND
RETURN FROM INTERRUPT
@BOX 8.0
END
@BOX 9.0
IN KERNEL MODE WHEN
INTERRUPT OCCURRED?
@BOX 1.1
END.VAX11.INT: BEGIN
@BOX 2.1
IF INT.PENDING /= 0
@BOX 3.1
MAKE (LOGICAL, REG.DUMP.SIZE, SYS14.REAL.STORE.ADDRESS + VV.PRB.RA)
   => PRB.PTR;
V.VM.TIMER => PRB.PTR^ [DUMPED.V.VM.TIMER.REG.NO];
*#%DB %1A %9F %08 %00 %03 %80; :: MFPR #ICR, @#FIXED.ADDRESS
FIXED.ADDRESS => PRB.PTR^ [DUMPED.ICR.REG.NO];
VV.INT.MC.CONTROL => PRB.PTR^ [DUMPED.V.INT.MC.CONTROL.REG.NO];
VV.EXEC.MC.CONTROL => PRB.PTR^ [DUMPED.V.EXEC.MC.CONTROL.REG.NO];
VV.VM.INTS => PRB.PTR^ [DUMPED.V.VM.INTS.REG.NO];
:: POP REGISTERS FROM REGISTER STACK
*#%D0 %5E %9F %4C %00 %03 %80;
:: MOVL R14, @#%80030014
*#%D0 %8F %14 %00 %03 %80 %5E;
:: MOVL #%80030014, R14
*#%BA %8F %FF %3F; :: POP REGS 0-13
*#%D0 %9F %4C %00 %03 %80 %5E;
:: MOVL @#%8003004C, R14
*#%07; :: SVPCTX
@BOX 4.1
1 => VV.INT.MC.CONTROL => AT.INT.LEVEL;
0 => INT.PENDING;
@BOX 5.1
INT.TYPE => VV.INTERRUPT.TYPE;
0 => INT.TYPE;
*#%DD %00 ; :: PUSHL #0 {NEW PSL ON INT STACK}
*#%10 %05; ::BSBB #5 {"PUSH" PC ON STACK AND BRANCH TO REI}
*#%BA %8F %00 %20; :: POPR #%2000 {POP FP}
*#%04; :: RET
*#%02; :: REI
@BOX 6.1
*#%DA %8F %41 %00 %00 %00 %18;
:: START CLOCK
@BOX 7.1
:: POP REGISTERS FROM REGISTER STACK
*#%D0 %5E %9F %4C %00 %03 %80;
:: MOVL R14, @#%8003004C
*#%D0 %8F %14 %00 %03 %80 %5E;
:: MOVL #%80030014, R14
*#%BA %8F %FF %3F; :: POP REGS 0-13
*#%D0 %6E %5E; :: MOVL (R14), R14
*#%02; :: REI
@BOX 8.1
END
@BOX 9.1
*#%DA %1F %12 :: INHIBIT INTS (MTPR #%1F, #IPL);
*#%D0 %5E %9F :: SAVE STACK POINTER;
*#%4C %00 %03 %80 :: (MOVL R14, @#8003004C);
*#%D0 %8F %4C %00 :: POINT STACK POINTER AT REGISTER DUMP;
*#%03 %80 %5E :: (MOVL #%8003004C, R14);
*#%BB %8F %FF %3F :: SAVE REGISTERS (PUSHR %3FFF);
*#%D0 %9F %4C %00 :: RESET STACK POINTER;
*#%03 %80 %5E :: (MOVL @#%8003004C, R14);
*#%D0 %8E %51 :: GET PROCEDURE ADDRESS;
*#%D0 %61 %51 :: MOVL STACK, R1; MOVL (R1), R1;
*#%FB %01 %61 :: CALLS (R1);
*#%D0 %AE %04 %9F %08 %00 %03 %80;
:: MOVL 4(R14), @#FIXED.ADDRESS
IF FIXED.ADDRESS & %03000000 = 0
@END
@TITLE AP301.9(1,11)

@COL 1S-2T-3R-4T-12T-7R-5R-10T-6R
@COL 8R-9R-11R-13F
@ROW 3-8
@ROW 7-9
@ROW 6-11
@FLOW 1-2NO-3-4NO-12NO-7-5-10NO-6
@FLOW 4YES-5
@FLOW 2YES-8-13
@FLOW 10YES-11-13
@FLOW 12YES-9-13
@BOX 1.0
INT MC CONTROL POST PROC
@BOX 2.0
ENTER INTERRUPT LEVEL?
@BOX 3.0
GET PCB AND PRB
@BOX 4.0
NO VM INTERRUPT OUTSTANDING
OR NOT IN USER MODE?
@BOX 5.0
IF NECESSARY RELOAD HST
RESET KERNEL STACK
@BOX 6.0
RESET PROCESS BASED
IDEAL MACHINE REGISTERS
LOAD PROCESS CONTEXT
AND RETURN TO PROCESS LEVEL
@BOX 7.0
FORCE ENTRY TO VM INTERRUPT
AT COMMAND LEVEL
@BOX 8.0
CHANGE MODE TO KERNEL
@BOX 9.0
RESET STACK AND INDICATE PROGRAM
FAULT
@BOX 10.0
IDEAL MACHINE INTERRUPT PENDING?
@BOX 11.0
INDICATE SYSTEM BASED INTERRUPT
@BOX 12.0
STACK OVERFLOW?
@BOX 13.0
END
@BOX 1.1
PROC INT.MC.CONTROL.POST.PROC;
@BOX 2.1
IF VV.INT.MC.CONTROL /= 0
@BOX 3.1
^PCB OF PCBS [VV.PROCESS.NUMBER] => PCB.PTR;
MAKE (LOGICAL, REG.DUMP.SIZE, SYS14.REAL.STORE.ADDRESS + VV.PRB.RA)
   => PRB.PTR;
@BOX 4.1
IF PCB.PTR^ [19] & %03000000 /= %03000000
   OR PRB.PTR^ [DUMPED.V.VM.INTS.REG.NO] = 0
@BOX 5.1
IF VV.PROCESS.NUMBER /= PREV.PROCESS.NUMBER THEN
   RELOAD.HST ();
   *#%DA %00 %39; :: MTPR #0, #TBIA
   VV.PROCESS.NUMBER => PREV.PROCESS.NUMBER;
FI
@BOX 6.1
*#%BB %8F %00 %20; :: PUSHR %200 {SAVE INTERRUPT LEVEL FP}
0 => AT.INT.LEVEL;
PRB.PTR^ [DUMPED.V.INT.MC.CONTROL.REG.NO] => VV.INT.MC.CONTROL;
PRB.PTR^ [DUMPED.V.EXEC.MC.CONTROL.REG.NO] => VV.EXEC.MC.CONTROL;
PRB.PTR^ [DUMPED.V.VM.INTS.REG.NO] => VV.VM.INTS;
PRB.PTR^ [DUMPED.V.VM.TIMER.REG.NO] => V.VM.TIMER;
PRB.PTR^ [DUMPED.ICR.REG.NO] => FIXED.ADDRESS;
*#%DA %9F %08 %00 %03 %80 %19; :: MTPR @#FIXED.ADDRESS, #NICR
*#%DA %8F %51 %00 %00 %00 %18; :: MTPR #%51, #ICCS
*#%DA %8F %18 %FC %FF %FF %19; :: MTPR #-1000, #NICR
BYTE (PCB.PTR) & %7FFFFFFF - %10000 => FIXED.ADDRESS;
:: LOAD PCBB WITH REAL ADDRESS OF PCB
*#%DA %9F %08 %00 %03 %80 %10; :: MTPR @#FIXED.ADDRESS, #PCBB
*#%06; :: LDPCTX
*#%02; :: REI
@BOX 7.1
PCB.PTR^ [3] => PCB.PTR^ [1]; :: USP => ESP
1 => PRB.PTR^ [DUMPED.V.EXEC.MC.CONTROL.REG.NO];
PCB.PTR^ [18] => PRB.PTR^ [DUMPED.PC.REG.NO];
%7FFC0404 => PCB.PTR^ [18]; :: RESET PC
PCB.PTR^ [19] => PRB.PTR^ [DUMPED.PSL.REG.NO];
%01C00000 => PCB.PTR^ [19]; :: RESET PSL
*CODE 15;
:: CODE TO BE OBEYED ON ENTERING VM INTERRUPT
BEGIN
*#%BB %8F %FF %07; :: PUSH REGS 0 - 10
*#%DD %00 %DD %00; :: PUSHL #0, PUSHL #0
:: LEAVES SPACE ON STACK FOR USE BY APP OUTWARD CALL [AP301.25]
SYS10.VM.INTERRUPT ();
END
*CODE 11;
@BOX 8.1
*#%BC %00; :: CHMK
0 => VV.INT.MC.CONTROL;
@BOX 9.1
USER.STACK.BASE => PCB.PTR^ [3];
%40 !> VV.PF.STATUS;
1 => VV.INT.MC.CONTROL => VV.INTERRUPT.TYPE;
@BOX 10.1
INHIBIT.INTERRUPTS;
IF VV.FI & SYS01.INT.ACTIVITIES /= 0
@BOX 11.1
1 => VV.INT.MC.CONTROL;
0 => VV.INTERRUPT.TYPE;
ALLOW.INTERRUPTS;
@BOX 12.1
IF PCB.PTR^ [3] < RESERVED.STACK.TOP OR
   PCB.PTR^ [3] > USER.STACK.BASE
@BOX 13.1
END
@END

@TITLE AP301.10(1,6)

@COL 1S-2R-3R-4R-5F

@FLOW 1-2-3-4-5

@BOX 1.0
CLOCK INT POST PROC
@BOX 2.0
INHIBIT INTERRUPTS
@BOX 3.0
CLEAR HW INT
[AP301.3]
@BOX 4.0
ALLOW INTERRUPTS
@BOX 5.0
END
@BOX 1.1
PROC CLOCK.INT.POST.PROC;
@BOX 2.1
:: INHIBIT INTERRUPTS
*#%DA %1F %12; :: MTPR #1F, #IPR
@BOX 3.1
CLEAR.HW.INT (SYS01.CLOCK.ACTIVITY);
@BOX 4.1
:: ALLOW INTERRUPTS
*#%DA %00 %12; :: MTPR #00, #IPL
@BOX 5.1
END
@END

@TITLE AP301.11(1,11)

@COL 1S-2T-8R-7R-3R-4R-10R-5R-9R-6F
@FLOW 1-2NO-8-7-3-4-10-5-9-6
@FLOW 2YES-6

@BOX 1.0
SECONDS CLOCK
@BOX 2.0
SECOND NOT GONE?
@BOX 3.0
UPDATE REAL TIME CLOCK
@BOX 4.0
UPDATE SECONDS COUNT
@BOX 5.0
SET HARDWARE INTERRUPT
[AP301.2]
@BOX 6.0
END
@BOX 7.0
POLL I/O DEVICES
[AP203]
@BOX 8.0
INHIBIT INTERRUPTS
@BOX 9.0
ALLOW INTERRUPTS
@BOX 10.0
UPDATE TIME DISTRIBUTION
@BOX 1.1
PROC SECONDS.CLOCK;
PSPEC UPDATE.TIME.DIST ();
PROC UPDATE.TIME.DIST;
SELECT APP.STATS^;
RAW.USER.TIME ->> 3 / 125 => USER.TIME;
RAW.IDLE.TIME ->> 2 / 25 => IDLE.TIME;
RAW.LOST.TIME ->> 2 / 25 => LOST.TIME;
1 +> RAW.ELAPSED.TIME - USER.TIME - IDLE.TIME - LOST.TIME
   => SYSTEM.TIME;
END
@BOX 2.1
*#%DB %1B %9F %0C %00 %03 %80;
:: MFPR #TODR, @#REAL.TIME
IF REAL.TIME ->> 1 / 50 => PRESENT.SECS.VALUE = LAST.SECS.VALUE
@BOX 3.1
PRESENT.SECS.VALUE - LAST.SECS.VALUE +> VV.TIME;
@BOX 4.1
PRESENT.SECS.VALUE => LAST.SECS.VALUE;
@BOX 5.1
SET.HW.INT (SYS01.CLOCK.ACTIVITY);
@BOX 6.1
END
@BOX 7.1
POLL.DEVICES ();
MT.POLL ();
@BOX 8.1
*#%DA %1F %12; :: MTPR #1F, #IPL
@BOX 9.1
*#%DA %00 %12; :: MTPR #00, #IPL
@BOX 10.1
UPDATE.TIME.DIST ();
@END
@TITLE AP301.12(1,11)

@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
INTERVAL TIMER INTERRUPT (DUMMY)
@BOX 2.0
NOTE PROCESS BASED
INTERRUPT REQUIRED
@BOX 3.0
END
@BOX 1.1
PROC INTERVAL.TIMER.INTERRUPT (DUMMY);
@BOX 2.1
4 => INT.PENDING => INT.TYPE;
@BOX 3.1
END
@END
@TITLE AP301.13(1,11)

@COL 1S-2T-3R-4T-5R-10R-6R-9R-7F
@COL 8R

@ROW 3-8

@FLOW 1-2NO-3-4IN CORE-5-10-6-9-7
@FLOW 2YES-8-9
@FLOW 4-6

@BOX 1.0
RESET STATUS POST PROC
CALL RESET STATUS PROC

RESET STATUS PROC
@BOX 2.0
IS ENTIRE HST RESET REQUIRED?
@BOX 3.0
SET POINTER TO THE RELEVANT
SEGMENT TABLE
@BOX 4.0
IS VALID PAGE TABLE IN CORE?
@BOX 5.0
RESET ACCESS PERMISSION IN
PAGE TABLE IF NECESSARY
@BOX 6.0
RESET HST ENTRY
@BOX 7.0
END
END
@BOX 8.0
RELOAD HST
[AP301.16]
@BOX 9.0
CLEAR TRANSLATION BUFFERS
@BOX 10.0
INITIALISE ACCESS PERMISSION
FOR NEW PAGE TABLES
@BOX 1.1
PROC RESET.STATUS.POST.PROC;
PSPEC RESET.STATUS.PROC ();
RESET.STATUS.PROC ();

PROC RESET.STATUS.PROC;
INTEGER COUNT, PT.SEG.COUNT, OFFSET;
LOGICAL ACC;
ADDR SYS14.LST.TYPE LST.PTR;
ADDR SYS14.SEG.VARS C.SEG.VARS;
ADDR [LOGICAL] PT;
DATAVEC P.ACCESS (LOGICAL8)
   %0 %B %0 %8 %B %B %8 %8
   %0 %F %0 %4 %F %F %4 %4
END
@BOX 2.1
-1 => PREV.PROCESS.NUMBER;
IF VV.RESET.STATUS = 1
@BOX 3.1
IF VV.RESET.SEG < SYS14.NO.OF.LOCAL.SEGS THEN
   MAKE (SYS14.SEG.VARS, 0, SYS13.INT.GET.PRB (14)) => C.SEG.VARS;
   ^LST [VV.RESET.SEG] OF C.SEG.VARS^ => LST.PTR;
ELSE
   ^SYS14.CST [VV.RESET.SEG - SYS14.FIRST.COMMON.SEG] => LST.PTR;
FI
SELECT LST.PTR^;
@BOX 4.1
IF VV.RESET.SEG /= SYS14.PT.SEG OR VV.RESET.BLK /= 0 THEN
   0 => SYS14.SST.PT [0];
FI
IF %81800000 & SYS14.SST.PT [SSN] /= %80800000
@BOX 5.1
P.ACCESS [ACCESS & %F] <<- 27 => ACC;
MAKE (LOGICAL,WORDS.PER.PAGE, SYS14.SST.PT [SSN] & %1FFFFF
   * SYS02.CORE.PAGE.SIZE + SYS14.REAL.STORE.ADDRESS) => PT;
%87FFFFFF & PT^ [VV.RESET.BLK] ! ACC => PT^ [VV.RESET.BLK];
@BOX 6.1
IF VV.RESET.SEG < SYS14.NO.OF.LOCAL.SEGS THEN
   SYS14.SST.PT [SSN] => HST [VV.RESET.SEG];
ELSE
   SYS14.SST.PT [SSN] => C.HST [VV.RESET.SEG - SYS14.FIRST.COMMON.SEG * 1];
FI
@BOX 7.1
END
END
@BOX 8.1
RELOAD.HST ();
@BOX 9.1
*#%DA %00 %39; :: MTPR #0, #TBIA
@BOX 10.1
SYS14.NO.OF.SYS.SEGS / WORDS.PER.PAGE => PT.SEG.COUNT;
IF VV.RESET.SEG >= SYS14.PT.SEG < SYS14.PT.SEG + PT.SEG.COUNT THEN
   MAKE (LOGICAL,WORDS.PER.PAGE, SYS14.SST.PT [VV.RESET.SEG - SYS14.PT.SEG
      * WORDS.PER.PAGE + VV.RESET.BLK] & %1FFFFF * SYS02.CORE.PAGE.SIZE
      + SYS14.REAL.STORE.ADDRESS) => PT;
   FOR COUNT < WORDS.PER.PAGE DO
      %87FFFFFF & PT^ [COUNT] ! %20000000 => PT^ [COUNT];
   OD
FI
@END
@TITLE AP301.14(1,11)
@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
CALL LINK PRE PROC
@BOX 2.0
NOTE ENTRY TIME
@BOX 3.0
SAVE FRAME POINTER
@BOX 4.0
END
@BOX 1.1
PROC CALL.LINK.PRE.PROC;
@BOX 2.1
*#%DB %1B %9F %7C %00 %03 %80; :: MFTR #TODR, @CALL.LINK.TIME
@BOX 3.1
*#%D0 %5D %9F %0C %00 %03 %80;
:: R13 => SAVE.LINK {V.CALL.LINK}
*#%D0 %AD %10 %9F %D0 %38 %03 %80; :: MOVL 16(FP), @#%800338F0
*#%D0 %8F %C0 %38 %03 %80 %5D; :: MOVL #%800338E0 ,FP
@BOX 4.1
END
@END
@TITLE AP301.15(1,11)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
EXIT LINK POST PROC
@BOX 2.0
RESET FRAME POINTER
AND EXIT VIA LINK ON STACK
@BOX 3.0
END
@BOX 1.1
PROC EXIT.LINK.POST.PROC;
@BOX 2.1
*#%D0 %9F %0C %00 %03 %80 %5D;
:: SAVE.LINK {V.EXIT.LINK} => R13
*#%D0 %9F %D0 %38 %03 %80 %AD %10 ; :: MOVL @#%800338F0, 16(FP)
@BOX 3.1
END
@END
@TITLE AP301.16(1,6)

@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
RELOAD HST
@BOX 2.0
RELOAD HARDWARE SEGMENT TABLES
FOR LOCAL AND COMMON SEGMENTS
@BOX 3.0
END
@BOX 1.1
PROC RELOAD.HST;
INTEGER SEG.NO;
ADDR SYS14.SEG.VARS C.SEG.VARS;
@BOX 2.1
MAKE (SYS14.SEG.VARS, 0, SYS13.INT.GET.PRB (14)) => C.SEG.VARS;
0 => SYS14.SST.PT [0];
SELECT C.SEG.VARS ^;
FOR SEG.NO < SYS14.NO.OF.LOCAL.SEGS DO
   SYS14.SST.PT [SSN OF LST [SEG.NO]] => HST [SEG.NO];
OD
FOR SEG.NO < SYS14.NO.OF.COMMON.SEGS DO
   SYS14.SST.PT [SSN OF SYS14.CST [SEG.NO]] => C.HST [SEG.NO];
OD
@BOX 3.1
END
@END
@TITLE AP301.17(1,6)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
MS BIT (WORD)
@BOX 2.0
RETURN POSITION OF
MOST SIGNIFICANT BIT IN WORD
@BOX 3.0
END
@BOX 1.1
PROC MS.BIT (WORD);
@BOX 2.1
31 => MS.BIT;
IF WORD & %FFFF0000 /= 0 THEN
   16 -> MS.BIT;
   WORD ->> 16 => WORD;
FI
IF WORD > %FF THEN
   8 -> MS.BIT;
   WORD ->> 8 => WORD;
FI
IF WORD > %F THEN
   4 -> MS.BIT;
   WORD ->> 4 => WORD;
FI
IF WORD > 3 THEN
   2 -> MS.BIT;
   WORD ->> 2 => WORD;
FI
IF WORD > 1 THEN
   1 -> MS.BIT;
FI
@BOX 3.1
END
@END


@TITLE AP301.18(1,6)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
BIT (INDEX)
@BOX 2.0
RETURN BIT PATTERN WITH
REQUIRED BIT SET
@BOX 3.0
END
@BOX 1.1
PROC BIT (INDEX);
@BOX 2.1
BIT.POSN [INDEX] => BIT;
@BOX 3.1
END
@END

@TITLE AP301.19(1,6)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
SET BIT (BIT VECTOR, INDEX)
@BOX 2.0
SET BIT IN SPECIFIED
BIT VECTOR
@BOX 3.0
END
@BOX 1.1
PROC SET.BIT (VEC, INDEX);
@BOX 2.1
BIT.POSN8 [INDEX & 7] !> VEC^ [INDEX / 8];
@BOX 3.1
END
@END

@TITLE AP301.20(1,6)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
CLEAR BIT (BIT VECTOR, INDEX)
@BOX 2.0
CLEAR BIT IN SPECIFIED
BIT VECTOR
@BOX 3.0
END
@BOX 1.1
PROC CLEAR.BIT (VEC, INDEX);
@BOX 2.1
BIT.MASK8 [INDEX & 7] &> VEC^ [INDEX / 8];
@BOX 3.1
END
@END


@TITLE AP301.21(1,6)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
TEST BIT (BIT VECTOR, INDEX)
@BOX 2.0
RETURN VALUE OF SPECIFIED BIT
IN BIT VECTOR
@BOX 3.0
END
@BOX 1.1
PROC TEST.BIT (VEC, INDEX);
@BOX 2.1
BIT.POSN8 [INDEX & 7] & VEC^ [INDEX / 8] => TEST.BIT;
@BOX 3.1
END
@END


@TITLE AP301.22(1,11)
@COL 1S-8T-7T-2R-3T-4T-9N-11N-5F
@COL 12N-10N-6R
@ROW 3-12
@ROW 4-10
@ROW 9-6
@FLOW 1-8NO-7-2-3DEFINED-4NO-9-11-5
@FLOW 3UNDEFINED-12-10-6-5
@FLOW 7INVALID-12
@FLOW 8YES-5
@FLOW 4YES-10
@BOX 1.0
VALIDATE (ADDRESS, REQUIRED ACCESS)
@BOX 2.0
SET POINTERS TO
RELEVANT SEGMENT TABLE
@BOX 3.0
IS SEGMENT DEFINED?
@BOX 4.0
IS ADDRESS OUT OF RANGE
OR REQUIRED ACCESS ILLEGAL?
@BOX 5.0
END
@BOX 6.0
INDICATE VALIDATE FAIL
@BOX 7.0
IS SEGMENT NUMBER VALID?
@BOX 8.0
PROCESS ZERO?
@BOX 1.1
PROC VALIDATE (ADDRESS, REQ.ACCESS);
INTEGER SEG, BLK;
ADDR SYS14.LST.TYPE SEG.TABLE;
ADDR SYS14.SEG.VARS C.SEG.VARS;
0 => VALIDATE;
@BOX 2.1
IF SEG < SYS14.NO.OF.LOCAL.SEGS THEN
   MAKE (SYS14.SEG.VARS, 0, SYS13.GET.PRB (-1, 14)) => C.SEG.VARS;
   ^LST [SEG] OF C.SEG.VARS^ => SEG.TABLE;
ELSE
   ^SYS14.CST [SEG - SYS14.FIRST.COMMON.SEG] => SEG.TABLE;
FI
SELECT SEG.TABLE^;
@BOX 3.1
IF ACCESS & %80 = 0
@BOX 4.1
IF LIMIT OF SYS14.SST [SSN] =< BLK OR
   REQ.ACCESS -= ACCESS & REQ.ACCESS /= 0
@BOX 5.1
END
@BOX 6.1
1 => VALIDATE;
@BOX 7.1
ADDRESS ->> 16 & %7FFF => SEG;
ADDRESS ->> 9 & %7F => BLK;
IF SEG < SYS14.FIRST.COMMON.SEG >= SYS14.NO.OF.LOCAL.SEGS OR
   SEG >= SYS14.FIRST.COMMON.SEG + SYS14.NO.OF.COMMON.SEGS
@BOX 8.1
IF SYS01.CURRENT.ACTIVITY.BIT & SYS01.PZ.ACTIVITY /= 0
@END
@TITLE AP301.23(1,9)

@COL 19R-20R-21R
@COL 1S-18T-10R-7T-17N-8T-2R-3R-16N-4R-5F
@COL 6R-9R-15N

@ROW 19-10
@ROW 6-17
@ROW 9-2
@ROW 15-16

@FLOW 1-18N0-10-7NO-17-8NO-2-3-16-4-5
@FLOW 18YES-19-20-21
@FLOW 7YES-6-15-16
@FLOW 8YES-9-15

@BOX 1.0
CMD ENTRY INTERRUPT (ENTRY INDEX)
@BOX 2.0
UPDATE STATISTICS
@BOX 3.0
CALL CMD PROCEDURE
@BOX 4.0
ISSUE CHMK 2 INSTRUCTION
@BOX 5.0
END
@BOX 6.0
RESET USER STACK FRONT
ENTER INTERRUPT LEVEL
WITH CALL TO SET VM INT
FOR INVALID STACK
@BOX 7.0
IS STACK OUTSIDE BOUNDS
@BOX 8.0
INVALID ENTRY INDEX?
@BOX 9.0
ENTER INTERRUPT LEVEL
WITH CALL TO SET VM INT
FOR PROGRAM FAULT
@BOX 10.0
NOTE AT CMD LEVEL
ISSUE CHMK 1 INSTRUCTION
@BOX 18.0
PROCESS ZERO?
@BOX 19.0
SAVE PC AND PSL OF INTERRUPT
@BOX 20.0
CALL PROCEDURE
@BOX 21.0
RETURN FROM INTERRUPT
@BOX 1.1
PROC CMD.ENTRY.INTERRUPT (ENTRY.INDEX);
INTEGER USER.SF;
@BOX 2.1
1 +> CMDS.CALLED OF APP.STATS^;
@BOX 3.1
0 => PW0;
ENTRY.INDEX * 8 - 4 + %7FFC0000 => ENTRY.INDEX;
*#%FB %8E %BD %1C; :: CALLS (R14)+, @28(R13)
*#%D0 %5E %AD %FC; :: MOVL R14, -4(R13)
:: ESP => USER SF
@BOX 4.1
*#%BC %02; :: CHMK 2
@BOX 5.1
END
@BOX 6.1
USER.STACK.BASE => USER.SF;
*#%D0 %AD %FC %5E; :: MOVL -4(R13), R14
:: USER.SF => ESP
SYS13.ENTER.INT.LEVEL (^SYS10.SET.VM.INT, 0, %40);
@BOX 7.1
IF USER.SF < RESERVED.STACK.TOP
   OR USER.SF > USER.STACK.BASE
@BOX 8.1
IF ENTRY.INDEX > NO.OF.COMMANDS
   OR ENTRY.INDEX < 1
@BOX 9.1
SYS13.ENTER.INT.LEVEL (^SYS10.SET.VM.INT, 0, %80);
@BOX 10.1
1 => VV.EXEC.MC.CONTROL;
*#%BC %01; ::CHMK 1
*#%D0 %5E %AD %FC; :: MOVL R14, -4(R13)
:: ESP => USER.SF
@BOX 18.1
IF SYS01.CURRENT.ACTIVITY.BIT
   & SYS01.PZ.ACTIVITY /= 0
@BOX 19.1
*#%7D %AD %20 %9F %F8 %FF %00 %00;
:: MOVQ 32(FP), @%FFF8
@BOX 20.1
ENTRY.INDEX * 8 - 4 + %7FFC0000 => ENTRY.INDEX;
*#%D0 %AD %1C %52; :: MOVL 28(FP),R2
*#%D0 %AD %08 %5C; :: MOVL 8(FP),R12
*#%D0 %AD %14 %5B; :: MOVL 20(FP),R11
*#%D0 %5D %51; :: MOVL FP, R1
*#%D0 %AD %0C %5D; :: MOVL 12(FP), FP
*#%DE %A1 %28 %5E; :: MOVAL 40(R1),SP
*#%FB %8E %62; :: CALLS (SP)+, (R2)
@BOX 21.1
*#%7D %9F %F8 %FF %00 %00 %7E;
:: MOVQ @%FFF8, -(SP)
*#%02;::REI
@END
@TITLE AP301.24(1,11)
@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
INIT REGS POST PROC
@BOX 2.0
INITIALIZE REGISTERS IN
PCB OF NEW PROCESS
@BOX 3.0
INITIALIZE REGISTERS IN
PRB OF NEW PROCESS
@BOX 4.0
END
@BOX 1.1
PROC INIT.REGS.POST.PROC;
@BOX 2.1
^PCB OF PCBS [VV.INIT.REGS] => INIT.REGS.PCB.PTR;
-1 => INIT.REGS.COUNT;
WHILE 1 +> INIT.REGS.COUNT < 24 DO
   0 => INIT.REGS.PCB.PTR^ [INIT.REGS.COUNT];
OD
SYS14.SEG.SIZE => INIT.REGS.PCB.PTR^ [1]; :: INIT ESP
SYS14.SEG.SIZE => INIT.REGS.PCB.PTR^ [2]; :: INIT SSP
USER.STACK.BASE => INIT.REGS.PCB.PTR^ [17] => INIT.REGS.PCB.PTR^ [3];
:: INIT USER FP AND SP
VV.DUMPED.CONTROL + 2 => INIT.REGS.PCB.PTR^ [18]; :: INIT PC
%03C00000 => INIT.REGS.PCB.PTR^ [19]; :: INIT PSL
P0.BASE => INIT.REGS.PCB.PTR^ [20];
P0.LIMIT ! %04000000 => INIT.REGS.PCB.PTR^ [21]; :: INIT P1LR AND AST-LVL
P1.BASE => INIT.REGS.PCB.PTR^ [22];
P1.LIMIT => INIT.REGS.PCB.PTR^ [23];
@BOX 3.1
MAKE (LOGICAL, REG.DUMP.SIZE, SYS13.GET.PRB (VV.INIT.REGS, 13)) => INIT.REGS.PRB
.PTR;
0 - 1000 => INIT.REGS.PRB.PTR^ [DUMPED.ICR.REG.NO];
1 => INIT.REGS.PRB.PTR^ [DUMPED.V.VM.TIMER.REG.NO];
@BOX 4.1
END
@END


@TITLE AP301.25(1,6)
@COL 1S-2R-3F
@FLOW 1-2
@BOX 1.0
APP OUTWARD CALL (PRB PTR, TRAP NO, REASON, PROCEDURE)
@BOX 2.0
OBTAIN DUMPED PC FROM PRB
SET UP STACK TO
FORCE PROCEDURE CALL
PROCEDURE (TRAP NO, REASON)
ON RETURN TO USER LEVEL
@BOX 3.0
END
@BOX 1.1
PROC APP.OUTWARD.CALL (PRB.PTR, TRAP, REASON, PROCEDURE);
LOGICAL STATUS, LINK, USER.SF;
@BOX 2.1
12 +> PRB.PTR; :: NOW POINTS TO DUMPED PC
*#%C1 %5D %1C %52; :: ADDL3 R13, #28, R2
:: R2 NOW POINTS TO PROCEDURE PARAMETER
*#%D0 %AD %0C %5D; :: MOVL 12(R13), R13
:: UNWIND FRAME POINTER ONE FRAME
*#%D0 %5D %AD %F4; :: MOVL R13, -12(R13)
:: FRAME POINTER => USER SF
*#%C1 %82 %02 %AD %F8; :: ADDL3 (R2)+, #2, -8(R13)
:: USER LINK {WITH REG DUMP MASK SKIPPED} => LINK
*#%D0 %02 %AD %18; :: MOVL #2, 24(R13)
:: LOAD NO OF LONGWORDS USED FOR PARAMETERS
*#%D0 %82 %AD %1C; :: MOVL (R2)+, 28(R13)
:: LOAD PARAMETER 2 (REASON) IN CORRECT POSITION
*#%D0 %82 %AD %20; :: MOVL (R2)+, 32(R13)
:: LOAD PARAMETER 1 (TRAP NO) IN CORRECT POSITION
*#%D0 %B2 %00 %AD %10; :: MOVL @0(R2), 16(R13)
:: LOAD DUMPED PC IN CORRECT POSITION
*#%C0 %0C %62; :: ADDL2 12, (R2) {12 +> PRB.PTR}
:: NOW POINTS TO DUMPED PSL
*#%B0 %B2 %00 %AD %04; :: MOVW @0(R2), 4(R13)
:: LOAD DUMPED PSW IN CORRECT POSITION
SYS13.ENTER.INT.LEVEL (^SET.USP, USER.SF, 0);
%03C00000 => STATUS;
*#%C3 %08 %5D %5E; :: SUBL3 #8, R13, R14
*#%02; :: REI {NEW PC AND PSL ON STACK}
@BOX 3.1
END
@END
@TITLE AP301.26(1,6)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
ALLOW INTERRUPTS PRE PROC
@BOX 2.0
SET INTERRUPT LEVEL
TO LOWEST PRIORITY
@BOX 3.0
END
@BOX 1.1
PROC ALLOW.INTERRUPTS.PRE.PROC;
@BOX 2.1
*#%DA %00 %12; :: MTPR #0, #IPL
@BOX 3.1
END
@END
@TITLE AP301.27(1,6)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
INHIBIT INTERRUPTS PRE PROC
@BOX 2.0
SET INTERRUPT LEVEL
TO HIGHEST PRIORITY
@BOX 3.0
END
@BOX 1.1
PROC INHIBIT.INTERRUPTS.PRE.PROC;
@BOX 2.1
*#%DA %1F %12; :: MTPR #%1F, #IPL
@BOX 3.1
END
@END
@TITLE AP301.28(1,6)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
TIME POST PROC
@BOX 2.0
ENTER INTERRUPT LEVEL
WITH CALL TO TIME PROC
[AP301.29]
@BOX 3.0
END
@BOX 1.1
PROC TIME.POST.PROC;
@BOX 2.1
SYS13.ENTER.INT.LEVEL (^TIME.PROC, VV.TIME, 0);
@BOX 3.1
END
@END
@TITLE AP301.29(1,6)
@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
TIME PROC (TIME, DUMMY)
@BOX 2.0
CALCULATE TIME OF YEAR
IN HUNDREDTHS OF SECONDS
@BOX 3.0
LOAD TIME INTO
TIME OF DAY REGISTER
@BOX 4.0
END
@BOX 1.1
PROC TIME.PROC (TIME, DUMMY);
@BOX 2.1
TIME ->> 1 / 15768000 * 15768000 <<- 1 -> TIME
   => LAST.SECS.VALUE;
TIME * 50 <<- 1 => TIME;
@BOX 3.1
*#%DA %AD %20 %1B; :: MTPR 32(R13), #TODR
@BOX 4.1
END
@END
@TITLE AP301.30(1,6)

@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
SF PRE PROC
CALL SF PROC

SF PROC
@BOX 2.0
MOVE STACK FRONT
INTO LOCAL VARIABLE
@BOX 3.0
LOAD V.SF
FROM LOCAL VARIABLE
@BOX 4.0
END
END
@BOX 1.1
PROC SF.PRE.PROC;
PSPEC SF.PROC ();
SF.PROC ();

PROC SF.PROC;
LOGICAL TEMP;
@BOX 2.1
*#%D0 %5E %AD %FC; :: MOVL R14, -4(R13)
:: R14 => TEMP
60 +> TEMP;
:: TAKES ACCOUNT OF SF PROCS' STACK FRAMES
@BOX 3.1
TEMP => VV.SF;
@BOX 4.1
END
END
@END
@TITLE AP301.31(1,11)

@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
CORE DATA PRE PROC
@BOX 2.0
RETURN FIRST WORD OF
SPECIFIED PAGE IN CORE
@BOX 3.0
END
@BOX 1.1
PROC CORE.DATA.PRE.PROC;
@BOX 2.1
MAKE (LOGICAL, 0, VV.CORE.PAGE * SYS02.CORE.PAGE.SIZE + SYS14.REAL.STORE.ADDRESS
)
   => CORE.PTR;
CORE.PTR^ => VV.CORE.DATA;
@BOX 3.1
END
@END

@TITLE AP301.32(1,11)

@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
CORE DATA POST PROC
@BOX 2.0
WRITE TO FIRST WORD OF
SPECIFIED PAGE IN CORE
@BOX 3.0
END
@BOX 1.1
PROC CORE.DATA.POST.PROC;
@BOX 2.1
MAKE (LOGICAL, 0, VV.CORE.PAGE * SYS02.CORE.PAGE.SIZE + SYS14.REAL.STORE.ADDRESS
)
   => CORE.PTR;
VV.CORE.DATA => CORE.PTR^;
@BOX 3.1
END
@END

@TITLE AP301.33(1,6)

@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
SET USP (USER SF, DUMMY)
@BOX 2.0
UPDATE USP
@BOX 3.0
SET AST TO TRAP ON
RETURN TO USER LEVEL
@BOX 4.0
END
@BOX 1.1
PROC SET.USP (USER.SF, DUMMY);
ADDR [LOGICAL] PCB.PTR;
@BOX 2.1
^PCB OF PCBS [VV.PROCESS.NUMBER] => PCB.PTR;
USER.SF => PCB.PTR^ [3];
@BOX 3.1
PCB.PTR^ [21] & %F8FFFFFF ! %03000000 => PCB.PTR^ [21];
@BOX 4.1
END
@END
@TITLE AP301.34(1,11)

@COL 1S-4T-2R-3F
@COL 5R
@ROW 2-5
@FLOW 1-4NO-2-3
@FLOW 4YES-5-3
@BOX 1.0
MEMORY MANAGEMENT INTERRUPT (FAULT REASON)
@BOX 2.0
SET APPROPRIATE V-LINES
FOR NON-EQUIVALENCE
@BOX 3.0
END
@BOX 4.0
AT INTERRUPT LEVEL?
@BOX 5.0
HALT
@BOX 1.1
PROC MEMORY.MANAGEMENT.INTERRUPT (FAULT.REASON);
@BOX 2.1
NEQ.VIRTUAL.ADDRESS ->> 16 & %7FFF => VV.NEQ.SEG;
NEQ.VIRTUAL.ADDRESS ->> 9 & %7F => VV.NEQ.BLK;
IF FAULT.REASON = 0 AND NEQ.FAIL.STATUS & 3 = 0 THEN
   %20 => VV.NEQ.ACCESS;
ELSE
   0 => VV.NEQ.ACCESS;
FI
3 => INT.PENDING => INT.TYPE;
IF FAULT.REASON = 1 THEN
   1 +> PAGE.FAULTS OF APP.STATS^;
FI
@BOX 3.1
END
@BOX 4.1
IF AT.INT.LEVEL /= 0
@BOX 5.1
*#%00; ::HALT
@END
@TITLE AP301.35(1,6)

@COL 1S-2R-3R-4R-5R-6F
@FLOW 1-2-3-4-5-6
@BOX 1.0
CHECK ADDRESS (ADDRESS)
@BOX 2.0
SET FLAG
@BOX 3.0
WRITE TO STORE
@BOX 4.0
WAIT FOR INTERRUPT
@BOX 5.0
SET RESULT
@BOX 6.0
END
@BOX 1.1
PROC CHECK.ADDRESS (ADDRESS);
*VTYPE LOGICAL8;
VSTORE STORE8 [%7FFFFFFF] %80000000;
*VTYPE LOGICAL;
INTEGER COUNT;
@BOX 2.1
1 => INIT.TRAP.FLAG;
@BOX 3.1
0 => STORE8 [ADDRESS & %7FFFFFFF];
@BOX 4.1
0 => COUNT;
WHILE INIT.TRAP.FLAG /= 0 AND 1 +> COUNT < 10 DO OD;
@BOX 5.1
INIT.TRAP.FLAG => CHECK.ADDRESS;
0 => INIT.TRAP.FLAG;
@BOX 6.1
END
@END

@TITLE AP301.36(1,11)

@COL 1S-2R-3R-4R-5T-6R-8F
@COL 7R
@ROW 6-7
@FLOW 1-2-3-4-5NO-6-8
@FLOW 5YES-7-8
@BOX 1.0
RETURN TO USER INTERRUPT (DUMMY)
@BOX 2.0
CLEAR AST
@BOX 3.0
CLEAR V.EXEC.MC.CONTROL
@BOX 4.0
RESET ESP
@BOX 5.0
TIME SLICE OVER-RUN?
@BOX 6.0
SET SYSTEM BASED INTERRUPT
@BOX 7.0
SET TIMER INTERRUPT
@BOX 8.0
END
@BOX 1.1
PROC RETURN.TO.USER.INTERRUPT (DUMMY);
LOGICAL TEMP;
@BOX 2.1
PCB [21] OF PCBS [VV.PROCESS.NUMBER] & %F8FFFFFF
   ! %04000000 => PCB [21] OF PCBS [VV.PROCESS.NUMBER];
*#%DA %04 %13; :: MTPR #3, #AST
@BOX 3.1
0 => VV.EXEC.MC.CONTROL;
@BOX 4.1
SYS14.SEG.SIZE => TEMP;
*#%DA %AD %FC %01; :: MTPR -4(R13), #ESP
@BOX 5.1
IF V.VM.TIMER =< 0
@BOX 6.1
IF VV.VM.INTS /= 0 THEN
   1 => INT.PENDING;
FI
@BOX 7.1
4 => INT.PENDING => INT.TYPE;
@BOX 8.1
END
@END
@TITLE AP301.37(1,8)

@COL 1S-2R-3R-4F

@FLOW 1-2-3-4

@BOX 1.0
APP LINK PRE PROC
@BOX 2.0
RETURN LINK OF CALLING PROCEDURE
@BOX 3.0
RESET CALLING PROCEDURE TO SKIP
STACK FRAME ON RETURN
@BOX 4.0
END
@BOX 1.1
PROC APP.LINK.PRE.PROC;
@BOX 2.1
*#%D0 %AD %0C %52; ::MOVL 12(FP), R2
*#%D0 %A2 %10 %9F %08 %00 %03 %80;
::MOVL 16(R2), @#V.APP.LINK
@BOX 3.1
*#%D0 %A2 %0C %AD %0C; ::MOVL 12(R2), 12(R13)
@BOX 4.1
END
@END
@TITLE AP301.38(1,8)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
APP LINK POST PROC
@BOX 2.0
RESET RETURN LINK
FROM V LINE
@BOX 3.0
END
@BOX 1.1
PROC APP.LINK.POST.PROC;
@BOX 2.1
*#%D0 %9F %08 %00 %03 %80 %AD %10;
::MOVL @#V.APP.LINK, 16(FP)
@BOX 3.1
END
@END
@TITLE AP301.39(1,10)
@COL 1R
@COL 2R
@BOX 1.0
RAW INTERRUPT ROUTINES (BASIC CPU)
@BOX 2.0
RAW INTERRUPT ROUTINES (BASIC CPU)
@BOX 1.1
UNASSIGNED.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%DD %8F :: STACK PARAMETER;
   *#%00 %00 %00 %00;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%00 %34 %04 %80;
   *#%17 %9F :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

MACHINE.CHECK.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 ::STOP CLOCK;
   *#%DD %8F  :: STACK PARAMETER;
   *#%01 %00 %00 %00;
   *#%DD %8F  :: STACK PROCEDURE ADDRESS;
   *#%04 %34 %04 %80;
   *#%17 %9F  :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

KERNEL.STACK.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%DD %8F :: STACK PARAMETER;
   *#%02 %00 %00 %00;
   *#%DD %8F ::STACK PROCEDURE ADDRESS;
   *#%08 %34 %04 %80;
   *#%17 %9F ::JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

POWER.FAIL.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 ::STOP CLOCK;
   *#%DD %8F :: STACK PARAMETER;
   *#%03 %00 %00 %00;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%0C %34 %04 %80;
   *#%17 %9F ::JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

RESERVED.INST.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%DD %8F :: STACK PARAMETER;
   *#%02 %00 %00 %00;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%10 %34 %04 %80;
   *#%17 %9F :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

CUST.RESERVED.INST.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%DD %8F :: STACK PARAMETER;
   *#%00 %02 %00 %00;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%14 %34 %04 %80;
   *#%17 %9F :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

RESERVED.OPND.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%DD %8F :: STACK PARAMETER;
   *#%02 %00 %00 %00;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%18 %34 %04 %80;
   *#%17 %9F :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

RESERVED.ADDRESSING.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%DD %8F :: STACK PARAMETER;
   *#%02 %00 %00 %00;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%1C %34 %04 %80;
   *#%17 %9F :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

@BOX 2.1
ACCESS.VIOLATION.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%D0 %8E %9F ::SAVE NEQ FAIL STATUS;
   *#%58 %00 %03 %80;
   *#%D0 %8E %9F :: SAVE NEQ VIRTUAL ADDRESS;
   *#%54 %00 %03 %80;
   *#%DD %8F :: STACK PARAMETER;
   *#%00 %00 %00 %00;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%20 %34 %04 %80;
   *#%17 %9F :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

TRANSLATION.FAIL.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%D0 %8E %9F :: SAVE NEQ FAIL STATUS;
   *#%58 %00 %03 %80;
   *#%D0 %8E %9F :: SAVE NEQ VIRTUAL ADDRRESS;
   *#%54 %00 %03 %80;
   *#%DD %8F :: STACK PARAMETER;
   *#%01 %00 %00 %00;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%24 %34 %04 %80;
   *#%17 %9F :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

TRACE.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%DD %8F :: STACK PARAMETER;
   *#%02 %00 %00 %00;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%28 %34 %04 %80;
   *#%17 %9F :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

BPT.TRAP.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%DD %8F :: STACK PARAMETER;
   *#%00 %01 %00 %00;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%2C %34 %04 %80;
   *#%17 %9F :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

COMPATABILITY.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%D0 %8F :: STACK PARAMETER;
   *#%02 %00 %00 %00 %6E;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%30 %34 %04 %80;
   *#%17 %9F :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

ARITHMETIC.TRAP.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%D0 %8F :: STACK PARAMETER;
   *#%01 %00 %00 %00 %6E;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%34 %34 %04 %80;
   *#%17 %9F :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;
@END

@TITLE AP301.40(1,11)
@COL 1S
@BOX 1.0
RAW INTERRUPT ROUTINES (MISCELLANEOUS)
@BOX 1.1
CHMK.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%DD %8F  :: STACK PROCEDURE ADDRESS;
   *#%40 %34 %04 %80;
   *#%17 %9F  :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

CHME.INT:*#%01 %01 %01 %01;
   *#%D0 %9F;
   *#%44 %34 %04 %80 %51;
   *#%FB %01 %61 :: CALLS #1, @CMD.ENTRY.INTERRUPT;
   *#%02  :: REI;

CHMS.INT:*#%01 %01 %01 %01;
   *#%D0 %9F;
   *#%48 %34 %04 %80 %51;
   *#%FB %01 %61 :: CALLS #1, @CMD.ENTRY.INTERRUPT;
   *#%02  :: REI;

WRITE.TIMEOUT.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%DD %8F :: STACK PARAMETER;
   *#%18 %00 %00 %00;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%60 %34 %04 %80;
   *#%17 %9F :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

AST.TRAP.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%DD %8F :: STACK PARAMETER;
   *#%00 %00 %00 %00;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%88 %34 %04 %80;
   *#%17 %9F :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

:: TIMER.INT
   #AP301.40.1

GENISCO.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%DD %8F :: STACK PARAMETER;
   *#%00 %00 %00 %00;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%68 %36 %04 %80;
   *#%17 %9F :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

RK07.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%DD %8F :: STACK PARAMETER;
   *#%00 %00 %00 %00;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%88 %36 %04 %80;
   *#%17 %9F :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

TAPE11.INT:*#%01 %01 %01 %01;
   *#%DA %00 %18 :: STOP CLOCK;
   *#%DD %8F :: STACK PARAMETER;
   *#%00 %00 %00 %00;
   *#%DD %8F :: STACK PROCEDURE ADDRESS;
   *#%94 %36 %04 %80;
   *#%17 %9F :: JUMP TO END VAX11 INT;
   *#%00 %00 %02 %80;

@END

@TITLE AP301.40.1(1,11)
@COL 1S-2R-3T-4T-5T-6R
@COL 7F
@ROW 6-7
@FLOW 1-2-3NO-4-5USER-6
@FLOW 3YES-7
@FLOW 4POSITIVE-7
@FLOW 5YES-7
@BOX 1.0
TIMER INT
@BOX 2.0
RESET ICR
@BOX 3.0
AT KERNEL LEVEL?
@BOX 4.0
NOTE USER TIME AND
DECREMENT V.VM.TIMER
@BOX 5.0
AT SUPERVISOR LEVEL?
@BOX 6.0
ENTER MUSS INTERRUPT LEVEL
@BOX 7.0
END
@BOX 1.1
TIMER.INT:
   *#%01 %01 %01 %01;
@BOX 2.1
   *#%DA %1F %12; :: INHIBIT INTERRUPTS
   *#%DA %8F %18 %FC %FF %FF %19; :: MTPR #-1000, #NICR
   *#%DA %8F %C1 %00 %00 %00 %18; :: MTPR #%C1, #ICCS
@BOX 3.1
   *#%D0 %AE %04 %9F %08 %00 %03 %80; :: MOVL 4(R14), @#FIXED.ADDRESS
   *#%93 %03 %9F %0B %00 %03 %80; :: BITB %03,@#FIXED.ADDRESS
   *#%12 %01; :: BNEQ #1
   *#%02; :: REI (IGNORE FLIP JUMP)
@BOX 4.1
   *#%D6 %9F %80 %00 %03 %80; :: INCL @#RAW.USER.TIME
   *#%D7 %9F %50 %00 %03 %80; :: DECL @#V.VM.TIMER
   *#%15 %01; :: BLEQ #1
   *#%02; :: REI (IGNORE FLIP JUMP)
@BOX 5.1
   *#%8C %03 %9F %0B %00 %03 %80; :: XORB2 #%03, @#FIXED.ADDRESS
   *#%93 %03 %9F %0B %00 %03 %80; :: BITB %03, @#FIXED.ADDRESS
   *#%13 %01; :: BEQL #1
   *#%02; :: REI (IGNORE FLIP JUMP)
@BOX 6.1
   *#%DA %00 %18; :: STOP CLOCK;
   *#%DD %8F; :: STACK PARAMETER
   *#%00 %00 %00 %00;
   *#%DD %8F; :: STACK PROCEDURE ADDRESS
   *#%C0 %34 %04 %80;
   *#%17 %9F; :: JUMP TO END VAX11 INT
   *#%00 %00 %02 %80;
@BOX 7.1
:: END
@END
@TITLE AP301.41(1,11)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
MILLI TIME PRE PROC
@BOX 2.0
UPDATE MILLI TIME
@BOX 3.0
END
@BOX 1.1
PROC MILLI.TIME.PRE.PROC;
@BOX 2.1
SYS13.ENTER.INT.LEVEL (^MILLI.TIME.PROC, 0, 0);
@BOX 3.1
END
@END
@TITLE AP301.42(1,11)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
MILLI TIME PROC
@BOX 2.0
READ MILLI TIME
@BOX 3.0
END
@BOX 1.1
PROC MILLI.TIME.PROC (DUMMY1, DUMMY2);
@BOX 2.1
*#%DB %1B %9F %0C %00 %03 %80; :: MFTR #TODR, @#REAL.TIME
REAL.TIME - BOOT.TIME * 10 => VV.MILLI.TIME
@BOX 3.1
END
@END
@TITLE AP301.43(1,11)
@COL 1S-2R-3F
@FLOW 1-2-3

@BOX 1.0
UPDATE IDLE TIME
@BOX 2.0
UPDATE IDLE AND LOST TIMES
@BOX 3.0
END
@BOX 1.1
PROC UPDATE.IDLE.TIME;
@BOX 2.1
*#%DB %1B %9F %0C %00 %03 %80; :: MFPR #TODR, @#REAL.TIME
IF REAL.TIME -:> CALL.LINK.TIME /= 0 THEN
   IF VV.HALT.MASK & %7FFF /= 0 THEN
      CALL.LINK.TIME +> RAW.LOST.TIME;
   ELSE
      CALL.LINK.TIME +> RAW.IDLE.TIME;
   FI
FI
REAL.TIME => CALL.LINK.TIME;
@BOX 3.1
END
@END
@TITLE AP301.44(1,11)
@COL 1S-2R-6F
@FLOW 1-2-6
@BOX 1.0
CLEAR PAGE POST PROC
@BOX 2.0
WRITE ZEROES TO PAGE
@BOX 6.0
END
@BOX 1.1
PROC CLEAR.PAGE.POST.PROC;
@BOX 2.1
MAKE (LOGICAL64, %40, VV.CLEAR.PAGE * SYS14.PAGE.SIZE
    + SYS14.REAL.STORE.ADDRESS) => CLEAR.PTR;
FOR INDEX < %40 DO
   0 => CLEAR.PTR^ [INDEX];
OD
@BOX 6.1
END
@END



