@X @~
~L3 COUK1247
80
~V7 56 2 -5
~D10
~H                        MUSS
~
~
~HAPPENDIX 5
~D15
This volume contains the machine dependent software for the MC68000.~
~
~
~
~
~MUNIVERSITY OF MANCHESTER
~V9 -1
~P
~D10
~H                  MUSS
~
~
~D10
~H            AP5011
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL~
~
~
                                                             ISSUE 11~
~V9 -1
~P
~MAppendix 5  CONTENTS~
~S~MPART 1~
~
~
~MAP5011  -  MC68000 CPU Appendix (ATV)~
~
~NAP5012  -  MC68000 CPU Appendix (PTV)~
~
~NAP5013  -  MC68000 CPU Appendix (GEM)~
~
~NAP5021  -  MC68000 Drum Appendix (ATV)~
~
~NAP5023  -  MC68000 Drum Appendix (GEM)~
~
~NAP5024  -  MC68000 Drum Appendix (DMA-PTV)~
~
~NAP5025  -  MC68000 Drum Appendix (RTV/PTV)~
~
~NAP1031  -  Machine Independent I/O Appendix~
~
~NAP5041  -  MC68000 Communications Appendix (Z8530)~
~
~NAP5042  -  MC68000 Communications Appendix (GEM)~
~
~NAP5991  -  End of Initialisation~
~S~MPART 2~
~
~
~MAP5111  -  M/C Dependent ROM Code (RTV)~
~
~NAP5112  -  M/C Dependent ROM Code (GEM)~
~
~NAP5121  -  ROM Drum Appendix (ATV)~
~
~NAP5122  -  ROM Drum Appendix (RTV/PTV)~
~
~NAP5123  -  ROM Drum Appendix (GEM)~
~
~NAP5124  -  ROM Drum Appendix (DMA-PTV)~
~V9 -1
~P
~V9 1
~YAP5011
~S1~M~OAP5 IMPLEMENTATION DESCRIPTION~
~S1~M~OSection 1 Version 1~
~S1~OSection 1.1 MC68000 Processor Appendix~
~S1~O1. General Description~
~BThis module is concerned with mapping the CPU features of the MUSS
ideal machine onto the MC68000. In addition it provides those functions
which are common to many modules, and which do not clearly belong in any
other section of the system.~
~BThe MC68000 Processor is described in Motorola's
'Microprocessors Data Manual 1981'.
~S1~O2. Interfaces~
Other modules used~
   SYS Section  1 (Coordinator)~
   SYS Section 10 (Virtual Machine Interrupts)~
   SYS Section 11 (Virtual Machine Timer)~
   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.INTERRUPT.TYPE~
   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.DISP~
   V.NEQ.SEG~
   V.ACCESS~
   V.STACK.SEG~
   V.VAL.ACCESS~
   V.BYTE~
   V.READ.BYTE~
   V.WRITE.BYTE~
   V.APP.LINK~
Interrupt Procedures~
   FAULT.INTERRUPT (REASON)~
   SYSTEM.ERROR.INTERRUPT (ERROR)~
   ENTER.INT.LEVEL.INTERRUPT (DUMMY)~
   INTERVAL.TIMER.INTERRUPT (DUMMY)~
   CMD.ENTRY.EXIT.INTERRUPT (ENTRY.INDEX)~
   TICKER.INTERRUPT (DUMMY)~
   BUS.ERROR.INTERRUPT (ERROR.TYPE)~
Interface Procedures~
   EMPTY.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)~
Interface Variables~
   None.~
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~
   REAL.STORE.ADDRESS~
   TICKS.PER.SECOND~
Machine Functions~
   ALLOW.INTERRUPTS~
   INHIBIT.INTERRUPTS~
~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.~
~
SYS Section 10 - V.EXEC.MC.CONTROL, V.SF, V.VM.INTS.~
~
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,~
               - V.INTERRUPT.TYPE.~
~
SYS Section 14 - V.NEQ.ACCESS, V.NEQ.DISP, V.NEQ.SEG, V.NEQ.BLK,~
               - V.STACK.SEG, V.VAL.ACCESS.~
~
AP5 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.
It runs at
INTERRUPT level.~
~S13) ENTER.INT.LEVEL.INTERRUPT (DUMMY)~
~BThis procedure services the TRAP 0 trap used to enter interrupt level
from command level. It faults an attempted entry from user level. It
runs at interrupt level.~
~S14) TICKER.INTERRUPT (DUMMY)~
~BThis procedure services interrupts from the clock in the PI/T chip. It
runs at interrupt level.~
~S15) CMD.ENTRY.EXIT.INTERRUPT (ENTRY.INDEX)~
~BThis procedure services the TRAP 1 trap which is used to enter
command level from user level. This is to allow user calls to
organizational commands. The TRAP 1 instruction is planted by the
compiler.~
~S16) BUS.ERROR.INTERRUPT (ERROR.TYPE)~
~BThis procedure services the BUS error interrupt, and also the
odd address fault interrupt. It runs at interrupt level.~
~S17) 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.~
~S18) SET.HW.INT (ACTIVITY)~
~BThis procedure sets the appropriate bit in V.HW.INT and updates
the interrupt tree. It runs at interrupt level.~
~S19) CLEAR.HW.INT (ACTIVITY)~
~BThis procedure clears the appropriate bit in V.HW.INT and updates
the interrupt tree. It runs at interrupt level.~
~S110) 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.~
~S111) BIT (INDEX)~
~BThis procedure returns a bit pattern with the required bit set.
It can run at interrupt or command level.~
~S112) SET.BIT (BIT VECTOR, INDEX)~
~BThis procedure sets the indicated bit in the specified bit vector. It can
run at interrupt or command level.~
~S113) CLEAR.BIT (BIT VECTOR, INDEX)~
~BThis procedure clears the indicated bit in the specified bit vector.
It can run at interrupt or command level.~
~S114) 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.~
~S115) 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 control is returned to user level, with
PW0 set for an access fault, on exit from VALIDATE.
VALIDATE runs at command level.~
~S116) 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 Supervisor mode function sets the interrupt priority to the lowest level
(0).~
~S12) INHIBIT.INTERRUPTS~
~BThis Supervisor mode function sets the interrupt priority to the highest level
 (7).~
~S1~O2.2 MC68000 Interface~
~BDetails of the MC68000 processor and associated memory
management unit are provided in the Motorola Data 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.
~S1~O2.2.2 Interrupt Vectoring
~BIn the present hardware, all peripherals interrupt through
the appropriate 'auto-vector' and so the initialisation of devices
does ~Wnot involve supplying a vector number to the device control chips.
~S1~O3. Implementation~
~S1~O3.1 Outline of Implementation~
~BThe three levels of the MUSS ideal machine are mapped on to the
MC68000 as follows:~
~Minterrupt level -> supervisor mode~
~Ncommand level -> user mode with~
~N                 V.EXEC.MC.CONTROL non-zero~
~Nuser level -> user mode with~
~N              V.EXEC.MC.CONTROL zero~
~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 organizational 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
~Q 8
~
~M   | local vars | XNB | FP | PC | params |~
~N ~O                                           ~O~
~N   |                  |~
~N   SF                 FP~
~
~M~OFig. 1 Stack frame structure~O~
~
   FP - Frame Pointer~
   PC - Program Counter~
   SF - Stack Front~
   XNB - Non-local Name Base~
~
~0
~ONOTES~O~
~T$ 6
~
1)~IThe term XNB comes from the MUTL implementation.~
~
2)~IPre-procs and post-procs are implemented as subroutines (using
JSR and RTS only as opposed to entry and exit sequences 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 organizational 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 six 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 six bytes long and structure is as follows:~
~
~MInstruction to Jump to Procedure code (6 bytes)~
~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 TRAP 0 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 TRAP 0 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 dependant information is stored in
the Process Register Block (PRB),
which is described in SYS Section 13. PRBs are part of the paged data.~
~BThe layout of the dumped register area of the PRB is~
~
   ~O16 bit~O~
   V.EXEC.MC.CONTROL~
   V.VM.INTS~
   V.VM.TIMER~
   V.VAL.ACCESS~
   V.INT.MC.CONTROL~
   USER STATUS Register~
~
   ~O32 bit~O~
   CURRENT Program Counter~
   Registers D0 - D7, A0 - A6~
   USER STACK POINTER~
   DUMPED PROGRAM COUNTER~
   BUS ERROR STACK (26 WORDS)~
~S1~O3.1.4 User access to organizational commands~
~BOrganizational commands are command level procedures which can be called
by the user. This necessitates a change from user level to command level.
Organizational commands run on the user stack in the same way as user
procedures but with executive privileges.~
~BCalls to organizational commands are achieved in the following
manner: the parameters are stacked as usual for a procedure call;
the FINDN index of the command is is placed in register D6; a TRAP 1 instruction
 is issued
(see LIB Section 2 Version 2).~
~3
~Q 8
~
~M  | PSW | PC | FI | params | user stack |~
~N~O                                           ~O~
~N  |                                     |~
~N USP                                  USB~
~
~M~OFig. 2 User stack on issue of TRAP 1 instruction~O~
~
    FI - FINDN Index~
   PSW - Process Status Word~
   USP - User Stack Pointer~
   USB - User Stack Base~
    PC - Program Counter~
~0
~BThe TRAP 1 interrupt handling code calls CMD.ENTRY.EXIT.INTERRUPT.
~BOn entry to CMD.ENTRY.EXIT.INTERRUPT with V.EXEC.MC.CONTROL
set to zero, the stacked program counter is saved and a new
value substituted which will result in the process
on return to "user" level, obeying code to enter the command
procedure. On return from this procedure a further TRAP 1
instruction is obeyed. This results in CMD.ENTRY.EXIT.INTERRUPT
being entered a second time, but with V.EXEC.MC.CONTROL non-zero
now.
~BThis results in the saved program counter being restored
to the stack and timer overrun being checked.
~BOn either exit from CMD.ENTRY.EXIT.INTERRUPT control passes to
ENTER.AP.INT.

~S1~O3.1.5 Validation of user addresses~
~BAll organizational 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 appropriately so that the exit from VALIDATE causes an
exit from the organizational command called by the user.~
~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| DR |user stack~
 ~O                                                                   ~O~
  |    |                           |    |           |~
 USP  AFP                         VSP  VFP         XUSP~
~
~M~OFig. 1 User stack after call of APP.OUTWARD.CALL~O~
~
   AOC - APP.OUTWARD.CALL~
   VMI - VM.INTERRUPT~
   XUSP- User stack pointer before fault detected~
   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~
   DR - Dumped Registers (used by Return From Trap etc see MTL215)~
   TN - Trap Number~
   PP - PRB Pointer~
   lv - local variables~
   sf - stack frame~
~
~M  | DPC | TR | TN | user stack~
~N~O                                ~O~
~N  |               |           |~
~N USP                 OLD         UFP~
~N                     USP          FP~
~
~0
~M~OFig. 2 User stack just before exit from APP.OUTWARD.CALL~O~
~
   UFP - User Frame Pointer~
   DPC - Dumped Program Counter (from PRB)~
   FP - Frame Pointer~
~BExit from APP.OUTWARD.CALL is achieved by a TRAP 1 instruction
which results in a command exit sequence being initiated.
~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~
~S1~O3.2 Data Structures~
~BNote PRB stands for Process Register Block.
This list is not, as yet, complete.~
~T%36
~
~
APP.STATS.TYPE~IData relevant to system statistics.~
   :CMDS.CALLED~IThe number of organizational commands called.~
   :USER.TIME~IThe time spent at user level.~
   :CMD.TIME~IThe time spent at command level.~
   :INT.TIME~IThe time spent at interrupt level.~
~
PAR.SHIFT~IThis literal is used in calculating an address
to be loaded into a PAR.~
~
CMD.AST~IThis literal is used in setting the user AST entries for
command level access.~
~
USER.AST~IThis literal is used in setting the user AST entries
for user access.~
~
REG.DUMP.SIZE~IThis literal gives the size of the dumped register
area in the PRB in 16 bit units.~
~
REG.DUMP.SIZE32~IThis literal gives the size of the
dumped register area in the PRB in 32 bit units.
~
DUMPED.V.EXEC.MC.CONTROL.REG.NO~IThis literal indexes
the DUMPED.V.EXEC.MC.CONTROL register in the PRB.~
~
DUMPED.V.VM.INTS.REG.NO~IThis literal indexes the
DUMPED.V.VM.INTS register in the PRB.~
~
DUMPED.V.VM.TIMER.REG.NO~IThis literal indexes the
DUMPED.V.VM.TIMER register in the PRB.~
~
DUMPED.PC32.REG.NO~IThis literal indexes the
dumped program counter register in the PRB.
It is used to save the user's program counter
on entry to command level, and to restore this value on exit.~
~
DUMPED.V.VAL.ACCESS.REG.NO~IThis literal indexes the
DUMPED.V.VAL.ACCESS register in the PRB.~
~
DUMPED.V.INT.MC.CONTROL.REG.NO~IThis literal indexes the
DUMPED.I.INT.MC.CONTROL register in the PRB.~
~
PRB.PC32.REG.NO~IThis literal indexes the current program
counter in the PRB.~
~
PRB.SP32.REG.NO~IThis literal indexes the user stack pointer
in the PRB.~
~
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.~
~
PZ.CMD.ENTRY~IThis logical variable is used to indicate
whether Process Zero is entering or leaving command level, (only
applicable for the LIB calls that Process Zero makes).~
~
VM.TIMER~IThis integer variable records the number of ticks that a
process has accumulated in the present time slice.~
~
INIT.REGS.COUNT~IThis integer variable is used in INIT.REGS.POST.PROC.~
~
TICKER.INT.COUNT~IThis integer variable records the number of
ticks outstanding in the present second.~
~
USER.STACK.BASE~IThis addr 'literal' gives the initial value of the
stack pointer of a process.~
~
BUFFER~IThis byte pointer is used in
READ.BYTE.POST.PROC and WRITE.BYTE.POST.PROC.~
~
PRB.PTR32~IThis array pointer is used in INT.MC.CONTROL.POST.PROC
to access the 32 bit quantities in the PRB.~
~
INIT.REGS.PRB.PTR32~IThis array pointer is used in INIT.REGS.POST.PROC
to access the 32 bit quantities in the PRB.~
~
PRB.PTR16~IThis array pointer is used in INT.MC.CONTROL.POST.PROC
and END.MC68000.INT to access the 16 bit quantities in the PRB.~
~
INIT.REGS.PRB.PTR16~IThis array pointer is used in INIT.REGS.POST.PROC
to access the 16 bit quantities in the PRB.~
~
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 INT.MC.CONTROL.POST.PROC and
END.MC68000.INT when hardware interrupts are inhibited.~
~
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.~
~S1~O3.3 Special Notes~
~BV.CALL.LINK and V.EXIT.LINK map onto the same address
but there is no inconsistency as process based interrupts are inhibited
when either of these V-lines is used.~
~V9 -1
~Y
~V9 -1
~P
~D15
~HFLOWCHARTS
~
~
~H               AP5011
~V9 -1
~F
@TITLE AP501(1,11)
@COL 1S-2R-3R-4R-5R-6F
@FLOW 1-2-3-4-5-6
@BOX 1.0
MC68000 PROCESSOR APPENDIX
@BOX 4.0
PROCEDURES IN MODULE
#AP501/3
@BOX 6.0
END
@BOX 1.1
#AP501/1
MODULE (V.HW.INTS, V.SW.INTS, V.HALT.MASK, V.FI, V.INT.MC.CONTROL,
   V.INTERRUPT.TYPE, V.EXEC.MC.CONTROL, V.PF.STATUS, V.TIME, V.CLOCK,
   V.VM.INTS, V.NEQ.SEG, V.NEQ.BLK, V.NEQ.DISP, V.NEQ.ACCESS, V.VAL.ACCESS,
   V.RESET.BLK, V.RESET.SEG, V.RESET.STATUS, V.MILLI.TIME, V.CLEAR.PAGE,
   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.BYTE, V.READ.BYTE,
   V.WRITE.BYTE, V.APP.LINK, V.CORE.PAGE, V.CORE.DATA,
   EMPTY.ACTIVITY, PROC.ACTIVITY, SET.HW.INT, CLEAR.HW.INT,
   FAULT.INTERRUPT, SYSTEM.ERROR.INTERRUPT, ENTER.INT.LEVEL.INTERRUPT,
   TICKER.INTERRUPT, BUS.ERROR.INTERRUPT,
   MS.BIT, BIT, SET.BIT, CLEAR.BIT, TEST.BIT,
   VALIDATE, CMD.ENTRY.EXIT.INTERRUPT, APP.OUTWARD.CALL,
   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, UPDATE.IDLE.TIME);
@BOX 2.1
TYPE APP.STATS.TYPE IS
   INTEGER32 CMDS.CALLED, SYSTEM.TIME, USER.TIME, IDLE.TIME, LOST.TIME, BUS.ERRO
RS;
@BOX 3.1
:: DATA DECLARATIONS
#AP501/2
@BOX 4.1
:: PROCEDURE DECLARATIONS
#AP501/3
@BOX 5.1
*CODE 7;
PSPEC INIT.AP501 ();
INIT.AP501 ();
PROC INIT.AP501;
INTEGER I;
*VTYPE LABEL;
VSTORE VEC.LABEL %840C3E;
*VTYPE LOGICAL32;
VSTORE VEC.LABEL.ADDR %840C42;
*VTYPE LOGICAL8;
VSTORE V.PIT.PCDDR %2709;
VSTORE V.TCR %2721;
VSTORE V.CPRH %2727;
VSTORE V.CPRM %2729;
VSTORE V.CPRL %272B;
*VTYPE LOGICAL;
LOGICAL32 SCALE;
#AP501/4
4 => VV.MC.NO;
1 => VV.INT.MC.CONTROL => AT.INT.LEVEL;
SYS14.SEG.SIZE - RESERVED.STACK.BOTTOM => USER.STACK.BASE;
MAKE (APP.STATS.TYPE, 0, SYS21.GET.STATS (0)) => APP.STATS;
%28 => V.PIT.PCDDR;
BYTE (^SYS14.CST [0]) - %40 => V.CST.POINTER;
BYTE (^SYS14.SST.PT [0]) => V.SST.PT.PTR;
%1B => V.DESCRIPTOR.PTR;
::4000000 / TICKS.PER.SECOND ->> 5 => SCALE;
::SCALE & %FF=> V.CPRL;
::SCALE ->> 8 & %FF => V.CPRM;
::SCALE ->> 16 & %FF => V.CPRH;
%68 => V.CPRL; %18 => V.CPRM; 0 => V.CPRH;
1 => V.TICKER.STATUS;
%E1 => V.TCR;
FOR I < 32 - NO.OF.LOCKED.PARS DO
   I => V.DP => V.ASN;
%FF => V.ASM;
   %FFFC => V.LAM;
   0 => V.SR;
   V.LOAD.PAR;
OD
END
@BOX 6.1
*END
@END
@TITLE AP501/1(1,9)
@COL 1S-2R-3R-4R
@FLOW 1-2-3-4
@BOX 1.0
OTHER MODULES REFERENCED
@BOX 4.0
SYS01 COORDINATOR
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 INTEGER ILLEGAL.ORDER, NO.OF.COMMANDS,
   RESERVED.STACK.BOTTOM, RESERVED.STACK.TOP, TICKS.PER.SECOND,
   NO.OF.LOCKED.PARS;
IMPORT LITERAL ADDR REAL.STORE.ADDRESS;
@BOX 3.1
PSPEC POLL.DEVICES ();
PSPEC Q.DISC.INT (INTEGER);
PSPEC SCC.PROCESS.SPECIAL.I.CH (INTEGER);
PSPEC SCC.PROCESS.SPECIAL.O.CH (INTEGER);
@BOX 4.1
ADDR PW0;
IMPORT LITERAL LOGICAL SYS01.INT.ACTIVITIES, SYS01.CLOCK.ACTIVITY,
   SYS01.PZ.ACTIVITY;
LOGICAL SYS01.CURRENT.ACTIVITY.BIT;
INTEGER SYS01.CURRENT.ACTIVITY;
IMPORT LITERAL SYS02.CORE.PAGE.SIZE;
PSPEC SYS10.PROC.TYPE (INTEGER, INTEGER);
PSPEC SYS10.VM.INTERRUPT ();
IMPORT LITERAL SYS11.INITIAL.TIMER;
PSPEC SYS11.VM.TIMER.INTERRUPT ();
PSPEC SYS12.SYSTEM.ERROR (INTEGER);
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 INTEGER SYS14.NO.OF.LOCAL.SEGS, SYS14.NO.OF.COMMON.SEGS,
   SYS14.NO.OF.SYS.SEGS, SYS14.SEG.SIZE, SYS14.PAGE.SIZE, SYS14.SEG.SHIFT,
   SYS14.PAGE.SHIFT, SYS14.NO.OF.X.SEGS, SYS14.PT.SEG,
   SYS14.FIRST.COMMON.SEG, PAGE.FIELD;
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;
LOGICAL32 [SYS14.NO.OF.SYS.SEGS] SYS14.SST.PT;
SYS14.LST.TYPE [SYS14.NO.OF.COMMON.SEGS] SYS14.CST;
PSPEC SYS21.GET.STATS (INTEGER) / ADDR;
@END
@TITLE AP501/2(1,11)

@COL 1S
@BOX 1.0
DATA DECLARATIONS
@BOX 1.1
*GLOBAL 5;
LITERAL / INTEGER TICK.INTERVAL = 50;
LITERAL / LOGICAL8 USER.AST = %21, CMD.AST = %61;
LITERAL / INTEGER REG.DUMP.SIZE = 70, REG.DUMP.SIZE32 = 35, PAR.SHIFT = 8,
   DUMPED.V.EXEC.MC.CONTROL.REG.NO = 0, DUMPED.V.VM.INTS.REG.NO = 1,
   DUMPED.V.VM.TIMER.REG.NO = 2, DUMPED.V.VAL.ACCESS.REG.NO = 3,
   DUMPED.V.INT.MC.CONTROL.REG.NO = 4, VOR.REG.NO = 40, PRB.PC32.REG.NO = 3,
   PRB.SP32.REG.NO = 19, DUMPED.PC32.REG.NO = 33, DUMPED.SP32.REG.NO = 34;
LOGICAL VV.HW.INTS, VV.SW.INTS, VV.HALT.MASK, VV.FI, VV.INT.MC.CONTROL,
   VV.INTERRUPT.TYPE, VV.PF.STATUS, VV.CLOCK, VV.NEQ.SEG, VV.NEQ.BLK,
 VV.RESET.BLK, VV.RESET.SEG, VV.RESET.STATUS,
   VV.NEQ.DISP, VV.NEQ.ACCESS, VV.VAL.ACCESS, VV.PROCESS.NUMBER,
   VV.MC.NO, VV.EXEC.MC.CONTROL, VV.VM.INTS, VV.INIT.REGS,
   VV.STACK.SEG, VV.BYTE, VV.CORE.PAGE, VV.CORE.DATA,
   VV.CLEAR.PAGE;
LOGICAL32 VV.TIME, VV.PRB.RA, VV.READ.BYTE, VV.WRITE.BYTE,
   VV.MILLI.TIME, RAW.USER.TIME, RAW.IDLE.TIME, RAW.ELAPSED.TIME;
ADDR VV.DUMPED.CONTROL, VV.SF;
LOGICAL INT.PENDING, INT.TYPE, AT.INT.LEVEL, PZ.CMD.ENTRY;
INTEGER VM.TIMER, INIT.REGS.COUNT, TICKER.INT.COUNT, INDEX;
ADDR USER.STACK.BASE;
ADDR LOGICAL8 BUFFER;
ADDR LOGICAL CORE.PTR;
ADDR [LOGICAL] PRB.PTR16, INIT.REGS.PRB.PTR16;
ADDR [ADDR] PRB.PTR32, INIT.REGS.PRB.PTR32;
ADDR APP.STATS.TYPE APP.STATS;
ADDR [LOGICAL32] 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;
VSTORE V.INT.MC.CONTROL VV.INT.MC.CONTROL > INT.MC.CONTROL.POST.PROC;
VSTORE V.INTERRUPT.TYPE VV.INTERRUPT.TYPE;
VSTORE V.EXEC.MC.CONTROL VV.EXEC.MC.CONTROL;
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.PF.STATUS VV.PF.STATUS;
VSTORE V.VM.INTS VV.VM.INTS;
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.RESET.BLK VV.RESET.BLK;
VSTORE V.RESET.SEG VV.RESET.SEG;
VSTORE V.RESET.STATUS VV.RESET.STATUS > RESET.STATUS.POST.PROC;
VSTORE V.NEQ.DISP VV.NEQ.DISP;
VSTORE V.NEQ.ACCESS VV.NEQ.ACCESS;
VSTORE V.VAL.ACCESS VV.VAL.ACCESS;
VSTORE V.BYTE VV.BYTE;
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 LOGICAL32;
VSTORE V.TIME VV.TIME;
VSTORE V.MILLI.TIME VV.MILLI.TIME;
VSTORE V.PRB.RA VV.PRB.RA > PRB.RA.POST.PROC;
VSTORE V.READ.BYTE VV.READ.BYTE > READ.BYTE.POST.PROC;
VSTORE V.WRITE.BYTE VV.WRITE.BYTE > WRITE.BYTE.POST.PROC;
*VTYPE ADDR;
VSTORE V.CALL.LINK %840C12 < CALL.LINK.PRE.PROC;
VSTORE V.EXIT.LINK %840C12 > EXIT.LINK.POST.PROC;
VSTORE V.SF VV.SF < SF.PRE.PROC;
VSTORE V.DUMPED.CONTROL VV.DUMPED.CONTROL;
VSTORE V.APP.LINK %840C0A < APP.LINK.PRE.PROC > APP.LINK.POST.PROC;
VSTORE FIXED.ADDRESS %840C0E;
VSTORE V.CST.POINTER %840C22;
VSTORE V.LST.POINTER %840C26;
VSTORE V.SST.PT.PTR %840C2A;
VSTORE V.DESCRIPTOR.PTR %840C2E;
VSTORE V.ADDRS.SPACE.DATA %840C32;
VSTORE V.FIXED.ADDRS2 %840C36;
VSTORE V.BUS.ERRORS %840C54;
*VTYPE LOGICAL8;
VSTORE V.TICKER.STATUS %2735;
VSTORE V.AST.UD %FFFFC2;
VSTORE V.AST.UP %FFFFC4;
*VTYPE LOGICAL16;
VSTORE V.LBA %FFFFE0;
VSTORE V.LAM %FFFFE2;
VSTORE V.PBA %FFFFE4;
*VTYPE LOGICAL8;
VSTORE V.ASN %FFFFE6;
VSTORE V.SR %FFFFE7;
VSTORE V.ASM %FFFFE8;
VSTORE V.DP %FFFFE9;
VSTORE V.GSR %FFFFED;
VSTORE V.LSR %FFFFEF;
VSTORE V.SSR %FFFFF1;
VSTORE V.LOAD.PAR %FFFFFF;
*VTYPE LOGICAL;
::
:: MACHINE FUNCTIONS
::
LOGICAL VV.ALLOW.INTERRUPTS, VV.INHIBIT.INTERRUPTS;
VSTORE ALLOW.INTERRUPTS VV.ALLOW.INTERRUPTS < ALLOW.INTERRUPTS.PRE.PROC;
VSTORE INHIBIT.INTERRUPTS VV.INHIBIT.INTERRUPTS < INHIBIT.INTERRUPTS.PRE.PROC;
::
DATAVEC BIT.POSN (LOGICAL)
   %8000 %4000 %2000 %1000
   %0800 %0400 %0200 %0100
   %0080 %0040 %0020 %0010
   %0008 %0004 %0002 %0001
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 AP501/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 ENTER AP INT
    9 INT MC CONTROL POST PROC
   10 CLOCK INT POST PROC
   12 TICKER INTERRUPT
   13 RESET STATUS POST PROC
   14 CALL LINK PRE PROC
   15 EXIT LINK POST PROC
   17 MS BIT
   18 BIT
   19 SET BIT
   20 CLEAR BIT
   21 TEST BIT
   22 VALIDATE
   23 CMD ENTRY EXIT INTERRUPT
   24 INIT REGS POST PROC
   25 APP OUTWARD CALL
   26 ALLOW INTERRUPTS PRE PROC
   27 INHIBIT INTERRUPTS PRE PROC
   28 CORE DATA PRE PROC
   29 CORE DATA POST PROC
   30 SF PRE PROC
   31 READ BYTE POST PROC
   32 WRITE BYTE POST PROC
   34 BUS ERROR INTERRUPT
   37 APP LINK PRE PROC
   38 APP LINK POST PROC
   39 PRB RA POST PROC
   40 RAW INTERRUPT ROUTINES
   41 CLEAR PAGE POST PROC
@BOX 1.1
*CODE 2;
:: ENTER.AP.INT
PSPEC UPDATE.INTERRUPT.TREE ();
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 TICKER.INTERRUPT (INTEGER);
:: PSPEC RESET.STATUS.POST.PROC ();
PSPEC CMD.ENTRY.EXIT.INTERRUPT (INTEGER);
:: PSPEC ALLOW.INTERRUPTS.PRE.PROC ();
:: PSPEC INHIBIT.INTERRUPTS.PRE.PROC ();
:: PSPEC CORE.DATA.PRE.PROC ();
:: PSPEC CORE.DATA.POST.PROC ();
:: PSPEC READ.BYTE.POST.PROC ();
:: PSPEC WRITE.BYTE.POST.PROC ();
PSPEC BUS.ERROR.INTERRUPT (INTEGER);
:: PSPEC APP.LINK.PRE.PROC ();
:: PSPEC APP.LINK.POST.PROC ():
:: PSPEC CLEAR.PAGE.POST.PROC ();
   #AP501.8
   #AP501.1
   #AP501.2
   #AP501.3
   #AP501.4
   #AP501.5
   #AP501.6
   #AP501.7
   #AP501.12
   #AP501.13
   #AP501.23
   #AP501.26
   #AP501.27
   #AP501.28
   #AP501.29
   #AP501.31
   #AP501.32
   #AP501.34
   #AP501.37
   #AP501.38
   #AP501.40
   #AP501.41
PSPEC UPDATE.IDLE.TIME ();
PROC UPDATE.IDLE.TIME;
END
PSPEC EMPTY.ACTIVITY ();
PROC EMPTY.ACTIVITY;
   SYS12.SYSTEM.ERROR (-1);
END
:: PSPEC INT.TREE.POST.PROC1 ();
PROC INT.TREE.POST.PROC.1;
   INT.TREE.POST.PROC ();
END
:: PSPEC INT.TREE.POST.PROC.2;
PROC INT.TREE.POST.PROC.2;
   INT.TREE.POST.PROC ();
END
:: PSPEC CLOCK.INT.POST.PROC ();
:: PSPEC CALL.LINK.PRE.PROC ();
:: PSPEC EXIT.LINK.POST.PROC ();
:: PSPEC PRB.RA.POST.PROC ();
   #AP501.10
   #AP501.14
   #AP501.15
   #AP501.39
*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;
:: *CODE 11;
   #AP501.9
   #AP501.17
   #AP501.18
   #AP501.19
   #AP501.20
   #AP501.21
*CODE 15;
PSPEC VALIDATE (ADDR, LOGICAL) / INTEGER;
::PSPEC INIT.REGS.POST.PROC ();
PSPEC APP.OUTWARD.CALL (ADDR, INTEGER, INTEGER, ADDR SYS10.PROC.TYPE);
:: PSPEC SF.PRE.PROC ();
   #AP501.22
   #AP501.24
   #AP501.25
   #AP501.30
@END
@TITLE AP501/4(1,9)

@COL 1S

@BOX 1.0
INITIALISATION DATA
@BOX 1.1
*VTYPE LOGICAL32;
VSTORE INT.VEC2 %8000E;
VSTORE INT.VEC3 %80014;
VSTORE INT.VEC4 %8001A;
VSTORE INT.VEC5 %80020;
VSTORE INT.VEC6 %80026;
VSTORE INT.VEC7 %8002C;
VSTORE INT.VEC8 %80032;
VSTORE INT.VEC25 %80098;
VSTORE INT.VEC26 %8009E;
VSTORE INT.VEC29 %800B0;
VSTORE INT.VEC30 %800B6;
VSTORE INT.VEC32 %800C2;
VSTORE INT.VEC33 %800C8;
VSTORE INT.VEC34 %800CE;
VSTORE INT.VEC35 %800D4;
VSTORE INT.VEC36 %800DA;
*VTYPE LOGICAL;
VECTOR2 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC2;
VECTOR3 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC3;
VECTOR4 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC4;
VECTOR5 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC5;
VECTOR6 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC6;
VECTOR7 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC7;
VECTOR8 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC8;
VECTOR25 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC25;
VECTOR26 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC26;
VECTOR29 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC29;
VECTOR30 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC30;
VECTOR32 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC32;
VECTOR33 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC33;
VECTOR34 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC34;
VECTOR35 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC35;
VECTOR36 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC36;
BYTE (^INTERRUPT.PROCS) => VEC.LABEL.ADDR;
@END

@TITLE AP501.1(1,9)
@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
PROC UPDATE.INTERRUPT.TREE;
@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 AP501.2(1,9)
@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
[AP501.1]
@BOX 4.0
END
@BOX 1.1
PROC SET.HW.INT (ACTIVITY);
@BOX 2.1
ACTIVITY !> VV.HW.INTS;
@BOX 3.1
UPDATE.INTERRUPT.TREE ();
@BOX 4.1
END
@END
@TITLE AP501.3(1,9)
@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
[AP501.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
UPDATE.INTERRUPT.TREE ();
@BOX 4.1
END
@END
@TITLE AP501.4(1,9)
@COL 1S-2R-3R-4R-5F
@FLOW 1-2-3-4-5
@BOX 1.0
INT TREE POST PROC
@BOX 2.0
INHIBIT INTERRUPTS
@BOX 3.0
UPDATE INTERRUPT TREE
[AP501.1]
@BOX 4.0
ALLOW INTERRUPTS
@BOX 5.0
END
@BOX 1.1
PROC INT.TREE.POST.PROC;
@BOX 2.1
INHIBIT.INTERRUPTS;
@BOX 3.1
UPDATE.INTERRUPT.TREE ();
@BOX 4.1
ALLOW.INTERRUPTS;
@BOX 5.1
END
@END
@TITLE AP501.5(1,9)

@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 VV.INT.MC.CONTROL /= 0 OR VV.EXEC.MC.CONTROL /= 0
   OR SYS01.CURRENT.ACTIVITY.BIT & SYS01.PZ.ACTIVITY /= 0
@BOX 3.1
*#%60FE; :: BRA -2
@BOX 4.1
END
@BOX 5.1
REASON !> VV.PF.STATUS;
@BOX 6.1
1 => INT.PENDING => INT.TYPE;
@END
@TITLE AP501.6(1,9)

@COL 1S-3R-4F
@FLOW 1-3-4
@BOX 1.0
SYSTEM ERROR INTERRUPT (ERROR)
@BOX 3.0
HALT
@BOX 4.0
END
@BOX 1.1
PROC SYSTEM.ERROR.INTERRUPT (ERROR);
@BOX 3.1
*#%60FE; :: BRA -2
@BOX 4.1
END
@END
@TITLE AP501.7(1,9)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
ENTER INT LEVEL INTERRUPT (DUMMY)
@BOX 2.0
NOTE PROCESS BASED
INTERRUPT REQUIRED
@BOX 3.0
END
@BOX 1.1
PROC ENTER.INT.LEVEL.INTERRUPT (DUMMY);
@BOX 2.1
IF VV.EXEC.MC.CONTROL /= 0 THEN
   2 => INT.PENDING => INT.TYPE;
ELSE
   ILLEGAL.ORDER !> VV.PF.STATUS;
   1 => INT.PENDING => INT.TYPE;
FI
@BOX 3.1
END
@END
@TITLE AP501.8(1,9)

@COL 1S-9T-2T-3R-4R-5R
@COL 7R-8F
@ROW 3-7
@FLOW 1-9NO-2INTERRUPT-3-4-5
@FLOW 9YES-7
@FLOW 2-7
@BOX 1.0
ENTER AP INT
@BOX 2.0
IDEAL MACHINE INTERRUPT PENDING?
@BOX 3.0
UNSTACK REGISTERS
DUMP REGISTERS IN PRB
@BOX 4.0
NOTE AT INTERRUPT LEVEL
@BOX 5.0
NOTE DESIGNATED INTERRUPT AS PENDING
@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
ENTER.AP.INT: BEGIN

::TEMPORARY TO CONFORM WITH EXISTING ORGANISATION
*#%46FC %2700; ::MOVEW #%2700, SR
*#%48F9 %7FFF %0084 %3700; ::MOVEML D0-D7, A0-A6, REG STACK
*#%201F; ::MOVEL (A7)+, D0
*#%E588; ::LSL D0, 2
*#%2C79 %0084 %0C42 ::MOVE @840C42, A6
*#%DDC0 ::ADDL D0, A6
*#%2C56; :: MOVL (A6),A6
*#%4E96 ::JSR (A6)
*#%548F; ::ADDQL #2, A7
@BOX 2.1
IF INT.PENDING = 0
@BOX 3.1
MAKE (LOGICAL, REG.DUMP.SIZE, VV.PRB.RA) => PRB.PTR16;
VV.INT.MC.CONTROL => PRB.PTR16^ [DUMPED.V.INT.MC.CONTROL.REG.NO];
VV.EXEC.MC.CONTROL => PRB.PTR16^ [DUMPED.V.EXEC.MC.CONTROL.REG.NO];
VV.VM.INTS => PRB.PTR16^ [DUMPED.V.VM.INTS.REG.NO];
VM.TIMER => PRB.PTR16^ [DUMPED.V.VM.TIMER.REG.NO];
:: LOAD CONTENTS OF REGISTER STACK INTO PRB
BYTE (PRB.PTR16) + 10 => FIXED.ADDRESS;
*#%2079 %0084 %0C0E :: MOVEAL FIXED.ADDRESS, A0
*#%45F9 %0084 %3700; :: LEA REG.STACK, A2
*#%30DF; :: MOVEW (A7)+, (A0)+
*#%20DF; :: MOVEL (A7)+, (A0)+
:: STORE REGISTERS
*#%740E; :: MOVEQ #14, D2
*#%20DA; :: MOVEL (A2)+, (A0)+
*#%51CA %FFFC; :: DBF D2, -4
*#%4E6A; :: MOVE USP, A2
*#%20CA; :: MOVEL A2, (A0)+
:: STORE BUS ERROR STACK
*#%3417; :: MOVEW (A7), D2
*#%6B04; :: BMI 4
*#%7400; :: MOVEQ #0, D2
*#%6002; :: BRA 2
*#%7419; :: MOVEQ #25, D2
*#%30DF; :: MOVEW (A7)+, (A0)+
*#%51CA %FFFC; :: DBF D2, -4
@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;
ALLOW.INTERRUPTS;
*#%2C5F; :: MOVEL (A7)+, A6
:: RECOVER INTERRUPT LEVEL FP
*#%4E75; :: RTS
@BOX 7.1
:: LOAD REGISTERS FROM REGISTER STACK
*#%4CF9 %7FFF %0084 %3700;
:: MOVEML REG.STACK, D0 - D7, A0 - A6
*#%4E73; :: RTE
@BOX 8.1
END
@BOX 9.1
*#%33D7 %0084 %0C10;
:: MOVEW (A7), FIXED.ADDRESS + 2
IF FIXED.ADDRESS  & %2000 /= 0
@END
@TITLE AP501.9(1,9)

@COL 1S-2T-3R-4T-7T-9R-10T-14R-16R-6R
@COL 11R-8R-12R-17R-13F
@ROW 3-11
@ROW 6-12
@ROW 9-8
@FLOW 1-2NO-3-4NO-7NO-9-10NO-14-16-6
@FLOW 2YES-11-13
@FLOW 4YES-10
@FLOW 17-13
@FLOW 7YES-8-17
@FLOW 10YES-12-17
@BOX 1.0
INT MC CONTROL POST PROC
@BOX 2.0
ENTER INTERRUPT LEVEL?
@BOX 3.0
GET PRB
@BOX 4.0
NO VM INTERRUPT OUTSTANDING
OR NOT IN USER MODE?
@BOX 6.0
RESET PROCESS BASED
IDEAL MACHINE REGISTERS
LOAD PROCESS CONTEXT
AND RETURN TO PROCESS LEVEL
@BOX 7.0
USER STACK OUT OF RANGE?
@BOX 8.0
MARK V.PF.STATUS
NOTE PROGRAM FAULT INTERRUPT PENDING
@BOX 9.0
FORCE ENTRY TO VM INTERRUPT
AT COMMAND LEVEL
@BOX 10.0
IDEAL MACHINE INTERRUPT PENDING?
@BOX 11.0
CHANGE MODE TO SUPERVISOR
@BOX 12.0
NOTE SYTEM BASED INTERRUPT PENDING
@BOX 13.0
END
@BOX 14.0
SAVE INTERRUPT LEVEL FP
@BOX 16.0
LOAD AST FOR PROCESS
@BOX 17.0
NOTE AT INTERRUPT LEVEL
@BOX 1.1
PROC INT.MC.CONTROL.POST.PROC;
@BOX 2.1
IF VV.INT.MC.CONTROL /= 0
@BOX 3.1
MAKE (LOGICAL, REG.DUMP.SIZE, VV.PRB.RA) => PRB.PTR16;
@BOX 4.1
PRB.PTR16^ [DUMPED.V.VM.INTS.REG.NO]
   => VV.VM.INTS;
IF PRB.PTR16^ [DUMPED.V.EXEC.MC.CONTROL.REG.NO]
   => VV.EXEC.MC.CONTROL /= 0 OR VV.VM.INTS = 0
@BOX 6.1
REG.DUMP.SIZE * 2 + VV.PRB.RA => V.LST.POINTER;
VV.PROCESS.NUMBER + 1 <<- 8 ! %4040001F
              => V.ADDRS.SPACE.DATA;
0 => AT.INT.LEVEL;
PRB.PTR16^ [DUMPED.V.INT.MC.CONTROL.REG.NO] => VV.INT.MC.CONTROL;
PRB.PTR16^ [DUMPED.V.VM.TIMER.REG.NO] => VM.TIMER;
:: LOAD USER CONTEXT FROM PRB
IF PRB.PTR16^ [40] & %8000 = 0 THEN
   BYTE (PRB.PTR16) + %52 => FIXED.ADDRESS;
   *#%2C79 %0084 %0C0E; :: MOVEAL FIXED.ADDRESS, A6
   *#%3F26; :: MOVEW -(A6), -(A7)
ELSE
   BYTE (PRB.PTR16) + %84 => FIXED.ADDRESS;
   *#%2C79 %0084 %0C0E; :: MOVEAL FIXED.ADDRESS, A6
   :: RELOAD BUS ERROR STACK
   *#%740C; :: MOVEQ #12, D2
   *#%2F26; ::MOVEL -(A6), -(A7)
   *#%51CA %FFFC; :: DBF D2, -4
FI
BYTE (PRB.PTR16) + 12 => FIXED.ADDRESS;
*#%2C79 %0084 %0C0E; :: MOVEAL FIXED.ADDRESS, A6
*#%2F1E; :: MOVEL (A6)+, -(A7)
:: RELOAD STATUS ONTO STACK
*#%3F2E %FFFA; :: MOVEW -6(A6), -(A7)
*#%4CDE %3FFF; :: MOVEML (A6)+, D0 - D7, A0 - A5
*#%23DE %0084 %0C0E; :: MOVEL (A6)+, FIXED.ADDRESS
*#%2C56; :: MOVEAL (A6), A6
*#%4E66; :: MOVE A6, USP
*#%2C79 %0084 %0C0E; :: MOVEAL FIXED.ADDRESS, A6
*#%4E73; :: RTE
@BOX 7.1
MAKE (ADDR, REG.DUMP.SIZE32, VV.PRB.RA) => PRB.PTR32;
IF PRB.PTR32^ [PRB.SP32.REG.NO] < RESERVED.STACK.TOP OR
   PRB.PTR32^ [PRB.SP32.REG.NO] > USER.STACK.BASE
@BOX 8.1
USER.STACK.BASE => PRB.PTR32^ [PRB.SP32.REG.NO];
%40 !> VV.PF.STATUS;
1 => VV.INTERRUPT.TYPE;
@BOX 9.1
1 => VV.EXEC.MC.CONTROL;
PRB.PTR32^ [PRB.PC32.REG.NO] => PRB.PTR32^ [DUMPED.PC32.REG.NO];
%88033C => PRB.PTR32^ [PRB.PC32.REG.NO]; :: RESET PC
0 => PRB.PTR16^ [VOR.REG.NO];
*CODE 15;
:: CODE TO BE OBEYED TO SERVICE VM INTERRUPT
BEGIN
*#%2F3C %0000 %0000; :: MOVEL #0, -(A7)
:: LEAVES SPACE ON STACK FOR USE BY RETURN FROM TRAP [MTL21.2(5)]
*#%42E7; :: MOVE SR, -(A7)
*#%48E7 %FFFC; :: MOVEML A5 - A0, D7 - D0, -(A7)
*#%2F3C %0000 %0000; :: MOVEL #0, -(A7)
:: LEAVES SPACE ON STACK FOR USE BY APP OUTWARD CALL [AP501.25]
SYS10.VM.INTERRUPT ();
END
*CODE 11;
@BOX 10.1
INHIBIT.INTERRUPTS;
IF VV.FI & SYS01.INT.ACTIVITIES /= 0
@BOX 11.1
*#%4E40; :: TRAP 0
0 => VV.INT.MC.CONTROL;
@BOX 12.1
ALLOW.INTERRUPTS;
0 => VV.INTERRUPT.TYPE;
@BOX 13.1
END
@BOX 14.1
*#%2F0E; :: MOVEL A6, -(A7)
@BOX 16.1
(IF VV.EXEC.MC.CONTROL = 0 THEN USER.AST ELSE CMD.AST)
   + VV.PROCESS.NUMBER => V.AST.UD => V.AST.UP;
@BOX 17.1
1 => VV.INT.MC.CONTROL;
@END
@TITLE AP501.10(1,9)

@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
[AP501.3]
@BOX 4.0
ALLOW INTERRUPTS
@BOX 5.0
END
@BOX 1.1
PROC CLOCK.INT.POST.PROC;
@BOX 2.1
INHIBIT.INTERRUPTS;
@BOX 3.1
CLEAR.HW.INT (SYS01.CLOCK.ACTIVITY);
@BOX 4.1
ALLOW.INTERRUPTS;
@BOX 5.1
END
@END

@TITLE AP501.12(1,11)

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

@FLOW 1-2NO-11-3-4-5-12-6NO-7=<0-8NO-9-10
@FLOW 2YES-12
@FLOW 6YES-13-10
@FLOW 7>0-10
@FLOW 8YES-10

@BOX 1.0
TICKER INTERRUPT
@BOX 2.0
PART OF A SECOND TO GO?
@BOX 3.0
UPDATE STATISTICS
@BOX 4.0
RESET INTERRUPT COUNT
@BOX 5.0
SET HARDWARE INTERRUPT
[AP201.2]
@BOX 6.0
AT INTERRUPT LEVEL
OR IN P ZERO?
@BOX 7.0
DECREMENT VM TIMER
@BOX 8.0
AT COMMAND LEVEL?
@BOX 9.0
NOTE PROCESS BASED
INTERRUPT REQUIRED
@BOX 10.0
END
@BOX 11.0
POLL I/O DEVICES
[AP203]
@BOX 12.0
UPDATE REAL TIME CLOCK
@BOX 13.0
MONITOR IDLE TIME
@BOX 1.1
PROC TICKER.INTERRUPT (DUMMY);
@BOX 2.1
1 => V.TICKER.STATUS;
IF 1 -> TICKER.INT.COUNT > 0
@BOX 3.1
SELECT APP.STATS^;
V.BUS.ERRORS +> BUS.ERRORS;
0 => V.BUS.ERRORS;
RAW.USER.TIME / TICKS.PER.SECOND => USER.TIME;
RAW.IDLE.TIME / TICKS.PER.SECOND => IDLE.TIME;
1 +> RAW.ELAPSED.TIME - USER.TIME - IDLE.TIME => SYSTEM.TIME;
1 +> VV.TIME;
@BOX 4.1
TICKS.PER.SECOND => TICKER.INT.COUNT;
@BOX 5.1
SET.HW.INT (SYS01.CLOCK.ACTIVITY);
@BOX 6.1
IF VV.INT.MC.CONTROL /= 0
   OR AT.INT.LEVEL /= 0
   OR VV.PROCESS.NUMBER = 0
@BOX 7.1
1 +> RAW.USER.TIME;
IF TICK.INTERVAL -> VM.TIMER > 0
@BOX 8.1
IF VV.EXEC.MC.CONTROL /= 0
@BOX 9.1
4 => INT.PENDING => INT.TYPE;
@BOX 10.1
END
@BOX 11.1
POLL.DEVICES ();
@BOX 12.1
TICK.INTERVAL +> VV.MILLI.TIME;
@BOX 13.1
IF VV.FI = 0 THEN
   1 +> RAW.IDLE.TIME;
FI
@END





@TITLE AP501.13(2,10)

@COL 1S-2R-4T-5R-3F
@FLOW 1-2-4SEGMENT AND BLOCK-5-3
@FLOW 4OTHER-3
@BOX 1.0
RESET STATUS POST PROC
@BOX 2.0
RESET USER DESCRIPTORS
@BOX 3.0
END
@BOX 4.0
CHECK RESET TYPE
@BOX 5.0
SET ALTERED BIT IF REQUIRED
@BOX 1.1
PROC RESET.STATUS.POST.PROC;
PSPEC RESET.STATUS.PROC ();
RESET.STATUS.PROC ();

PROC RESET.STATUS.PROC;
INTEGER MSN, PTE.PER.PAGE;
ADDR SYS14.SEG.VARS C.SEG.VARS;
ADDR SYS14.LST.TYPE LST.PTR;
ADDR [LOGICAL32] PT;
@BOX 2.1
FOR MSN < 32 - NO.OF.LOCKED.PARS DO
    MSN => V.DP;
    0 => V.SSR;
OD
@BOX 3.1
END
END
@BOX 4.1
IF VV.RESET.STATUS /= 4
@BOX 5.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^;
MAKE (LOGICAL32, SYS14.PAGE.SIZE ->> 2, SYS14.SST.PT [SSN]
   & PAGE.FIELD * SYS02.CORE.PAGE.SIZE + REAL.STORE.ADDRESS) => PT;
IF ACCESS & 2 /= 0 AND
   %81800000 & PT^ [VV.RESET.BLK] = %80800000 THEN
   %4000000 !> PT^ [VV.RESET.BLK];
FI
@END

@TITLE AP501.14(1,9)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
CALL LINK PRE PROC
@BOX 2.0
SAVE FRAME POINTER
@BOX 3.0
END
@BOX 1.1
PROC CALL.LINK.PRE.PROC;
@BOX 2.1
*#%23CE %0084 %0C12; :: MOVEL A6, SAVE.LINK
:: A6 => SAVE.LINK {V.CALL.LINK}
@BOX 3.1
END
@END
@TITLE AP501.15(1,9)
@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
*#%2C79 %0084 %0C12; :: MOVEAL SAVE.LINK, A6
:: SAVE.LINK {V.EXIT.LINK} => A6
@BOX 3.1
END
@END
@TITLE AP501.17(1,9)
@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
0 => MS.BIT;
WHILE WORD & %8000 = 0 DO
   WORD <<- 1 => WORD;
   1 +> MS.BIT;
OD
@BOX 3.1
END
@END


@TITLE AP501.18(1,9)
@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 AP501.19(1,9)
@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 AP501.20(1,9)
@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 AP501.21(1,9)
@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 AP501.22(1,11)

@COL 1S-8T-7T-2R-3T-4T-9N-11N-5F
@COL 10N-6R
@ROW 4-10
@ROW 9-6
@FLOW 1-8NO-7-2-3DEFINED-4NO-9-11-5
@FLOW 8YES-5
@FLOW 7INVALID-10-6-5
@FLOW 3UNDEFINED-10
@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
RETURN ALLOWED ACCESS PERMISSION
IN DUMPED REGISTER
@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;
LITERAL / INTEGER DEFINED = %80;
0 => VALIDATE;
@BOX 2.1
MAKE (SYS14.SEG.VARS, 0, SYS13.GET.PRB (-1, 14))
   => C.SEG.VARS;
SELECT C.SEG.VARS^;
IF SEG < SYS14.NO.OF.LOCAL.SEGS THEN
   ^LST [SEG] => SEG.TABLE;
ELSE
   ^SYS14.CST [SEG - SYS14.FIRST.COMMON.SEG] => SEG.TABLE;
FI
SELECT SEG.TABLE^;
@BOX 3.1
IF ACCESS & DEFINED = 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 ->> SYS14.SEG.SHIFT => SEG
   <<- SYS14.SEG.SHIFT -: ADDRESS ->> SYS14.PAGE.SHIFT
      => BLK;
IF SEG >= SYS14.NO.OF.LOCAL.SEGS < SYS14.FIRST.COMMON.SEG OR
   SEG >= SYS14.FIRST.COMMON.SEG + SYS14.NO.OF.COMMON.SEGS
@BOX 8.1
IF SYS01.CURRENT.ACTIVITY.BIT & SYS01.PZ.ACTIVITY /= 0
@BOX 13.1
FOR MSN < SYS14.NO.OF.MAPPED.SEGS DO
   IF MST [MSN] = SEG, -> OUT;
OD
OUT:
IF MSN = SYS14.NO.OF.MAPPED.SEGS
@END
@TITLE AP501.23(1,11)

@COL 12R-13R-6R-9R-14R-18N-16R-4R
@COL 1S-15T-11T-10R-7T-8T-2R-3R-17N-21N-20R-5F
@COL 19R
@ROW 19-11
@ROW 10-12
@ROW 8-6
@ROW 4-17
@FLOW 1-15NO-11ENTRY-10-7NO-8NO-2-3-17-21-20-5
@FLOW 7YES-6-14-18-16-4-20
@FLOW 8YES-9-14
@FLOW 11EXIT-12-13-18
@FLOW 15YES-19-10

@BOX 1.0
CMD ENTRY / EXIT INTERRUPT (DUMMY)
@BOX 2.0
UPDATE STATISTICS
@BOX 3.0
SAVE USER PC AND
RESET PC TO OBEY CMD ENTRY SEQUENCE
ON RETURN TO USER LEVEL
@BOX 4.0
MARK MUSS INTERRUPT PENDING
IF ERROR OUTSTANDING
@BOX 5.0
END
@BOX 6.0
RESET USER STACK FRONT
AND MARK V.PF.STATUS
FOR INVALID STACK
@BOX 7.0
IS STACK OUTSIDE BOUNDS
@BOX 8.0
INVALID ENTRY INDEX?
@BOX 9.0
MARK V.PF.STATUS
FOR PROGRAM FAULT
@BOX 10.0
NOTE AT CMD LEVEL
FORCE DUMPING OF PCB REGS
SET ESP TO VALUE OF USP
@BOX 11.0
CMD LEVEL ENTRY?
@BOX 12.0
RESET USER LINK ON STACK
@BOX 13.0
CHECK IF TIMER OVERRUN
@BOX 14.0
SET FOR PROGRAM FAULT
INTERRUPT
@BOX 15.0
CMD ENTRY FROM PROCESS ZERO?
@BOX 16.0
IF NOT PROCESS ZERO
NOTE AT USER LEVEL
@BOX 19.0
NOTE PROCESS ZERO'S
ENTRY TO CMD LEVEL
@BOX 20.0
DUMP V.EXEC.MC.CONTROL IN PRB
@BOX 1.1
PROC CMD.ENTRY.EXIT.INTERRUPT (DUMMY);
INTEGER32 USER.SF;
ADDR STACKED.PC;
INTEGER ENTRY.INDEX;
ADDR SYS14.SEG.VARS C.SEG.VARS;
ADDR [ADDR] PRB.PTR32;
ADDR [LOGICAL] PRB.PTR16;
MAKE (ADDR, REG.DUMP.SIZE32, VV.PRB.RA) => PRB.PTR32;
MAKE (LOGICAL, REG.DUMP.SIZE, VV.PRB.RA) => PRB.PTR16;
@BOX 2.1
1 +> CMDS.CALLED OF APP.STATS^;
@BOX 3.1
USER.SF => PRB.PTR32^ [DUMPED.SP32.REG.NO];
*#%2D6E %000C %FFF4; :: MOVEL 12(A6), -12(A6)
STACKED.PC => PRB.PTR32^ [DUMPED.PC32.REG.NO];
*#%2D7C %0088 %032C %000C; :: MOVEL %88032C, 12(A6)
:: RESET LINK ON STACK
CMD.AST + VV.PROCESS.NUMBER => V.AST.UD
   => V.AST.UP;
*CODE 15;
BEGIN
:: CMD PROCEDURE ENTRY SEQUENCE
*#%CDFC %0006; :: MULS #6, D6
*#%2046; :: MOVEAL D6, A0
*#%D1FC %0088 %0000; :: ADDAL #%880000, A0
*#%4E90; :: JSR (A0)
*#%4E41; :: TRAP 1
:: INVOKE CMD LEVEL EXIT SEQUENCE
END
*CODE 2;
@BOX 4.1
IF INT.TYPE = 0 AND VV.VM.INTS = 0 THEN
   USER.AST + VV.PROCESS.NUMBER => V.AST.UD
      => V.AST.UP;
ELSE
   1 => INT.PENDING;
FI
@BOX 5.1
END
@BOX 6.1
USER.STACK.BASE => USER.SF;
*#%206E %FFF8; :: MOVEAL -8(A6), A0
*#%4E60; :: MOVE A0, USP
%40 !> VV.PF.STATUS;
@BOX 7.1
IF USER.SF < RESERVED.STACK.TOP
   OR USER.SF > USER.STACK.BASE
@BOX 8.1
*#%3D46 %FFF2; :: MOVEW D6, -14(A6)
IF ENTRY.INDEX > NO.OF.COMMANDS
   OR ENTRY.INDEX < 1
@BOX 9.1
%80 !> VV.PF.STATUS;
@BOX 10.1
1 => VV.EXEC.MC.CONTROL;
*#%4E68; :: MOVE USP, A0
*#%2D48 %FFF8; :: MOVEL A0, -8(A6)
@BOX 11.1
IF VV.EXEC.MC.CONTROL /= 0
@BOX 12.1
PRB.PTR32^ [DUMPED.PC32.REG.NO] => STACKED.PC;
*#%2D6E %FFF4 %000C; :: MOVEL -12(A6), 12(A6)
@BOX 13.1
(IF VM.TIMER > 0 THEN 0 ELSE 4) => INT.TYPE;
@BOX 14.1
1 => INT.TYPE;
@BOX 15.1
IF VV.PROCESS.NUMBER = 0 AND
   PZ.CMD.ENTRY = 0
@BOX 16.1
IF VV.PROCESS.NUMBER = 0 THEN
   0 => PZ.CMD.ENTRY => INT.TYPE;
ELSE
   0 => VV.EXEC.MC.CONTROL;
FI
@BOX 19.1
1 => PZ.CMD.ENTRY;
@BOX 20.1
VV.EXEC.MC.CONTROL =>
   PRB.PTR16^ [DUMPED.V.EXEC.MC.CONTROL.REG.NO];
@END

@TITLE AP501.24(1,11)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
INIT REGS POST PROC
@BOX 2.0
INITIALIZE REGISTERS IN
PRB OF NEW PROCESS
@BOX 3.0
END
@BOX 1.1
PROC INIT.REGS.POST.PROC;
@BOX 2.1
MAKE (ADDR, REG.DUMP.SIZE32, SYS13.GET.PRB (VV.INIT.REGS, 13))
   => INIT.REGS.PRB.PTR32;
-1 => INIT.REGS.COUNT;
WHILE 1 +> INIT.REGS.COUNT < REG.DUMP.SIZE32 DO
   0 => INIT.REGS.PRB.PTR32^ [INIT.REGS.COUNT];
OD
USER.STACK.BASE => INIT.REGS.PRB.PTR32^ [18]
   => INIT.REGS.PRB.PTR32^ [PRB.SP32.REG.NO]; :: INIT USER FP AND SP
VV.DUMPED.CONTROL => INIT.REGS.PRB.PTR32^ [PRB.PC32.REG.NO]; :: INIT PC
MAKE (LOGICAL, REG.DUMP.SIZE, BYTE (INIT.REGS.PRB.PTR32)) => INIT.REGS.PRB.PTR16
;
1 => INIT.REGS.PRB.PTR16^ [DUMPED.V.VM.TIMER.REG.NO];
@BOX 3.1
END
@END


@TITLE AP501.25(1,9)
@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.NO, REASON, PROCEDURE);
@BOX 2.1
*#%246E %0010; :: MOVEAL 16(A6), A2 <|TEMP|>
::|*#%246E %0018; :: MOVEAL 24(A6), A2
::| AWAITING FIX IN MUSL
*#%D4FC %0084; :: ADDAW #%84, A2
:: A2 NOW POINTS TO DUMPED.PC IN PRB
*#%204E; :: MOVEAL A6, A0
*#%5088; :: ADDQL #8, A0
:: A0 NOW POINTS TO PROCEDURE PARAMETER
*#%2C56; :: MOVEAL (A6), A6
:: UNWIND FRAME POINTER ONE FRAME
::| *#%2A58; :: MOVEAL (A0)+, A5
::| :: LOAD XNB FROM PROCEDURE PARAMETER
::| *#%2658; :: MOVEAL (A0)+, A3
::| :: LOAD STATIC LINK FROM PROCEDURE PARAMETER
::| AWAITING FIX TO MUSL
*#%2D52 %0004; :: MOVEL (A2), 4(A6)
:: DUMPED.PC => LINK IN STACK FRAME
*#%2498; :: MOVEL (A0)+, (A2)
:: ADDRESS FROM PROCEDURE PARAMETER => DUMPED.PC
*#%3D58 %0008; :: MOVEW (A0)+, 8(A6)
:: REASON => PARAMETER 2 IN STACK FRAME
*#%3D50 %000A; :: MOVEW (A0), 10(A6)
:: TRAP.NO => PARAMETER 1 IN STACK FRAME
*#%4E5E; :: UNLK A6
:: SETS UP A6, A7 CORRECTLY
:: FOR PROCEDURE ENTRY SEQUENCE
*#%4E41; :: TRAP 1
:: INITIATE COMMAND LEVEL EXIT SEQUENCE
@BOX 3.1
END
@END
@TITLE AP501.26(1,9)
@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
*#%46FC %2000; :: MOVE #%2000, SR
@BOX 3.1
END
@END
@TITLE AP501.27(1,9)
@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
*#%46FC %2700; :: MOVE #%2700, SR
@BOX 3.1
END
@END
@TITLE AP501.28(1,9)

@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 + REAL.STORE.ADDRESS)
   => CORE.PTR;
CORE.PTR^ => VV.CORE.DATA;
@BOX 3.1
END
@END

@TITLE AP501.29(1,9)

@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 + REAL.STORE.ADDRESS)
   => CORE.PTR;
VV.CORE.DATA => CORE.PTR^;
@BOX 3.1
END
@END

@TITLE AP501.30(1,9)

@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;
LOGICAL32 TEMP;
@BOX 2.1
*#%2D4F %FFF8; :: MOVEL A7, -8(A6)
16 +> TEMP;
:: TAKES ACCOUNT OF SF PROCS' STACK FRAMES
@BOX 3.1
TEMP => VV.SF;
@BOX 4.1
END
END
@END
@TITLE AP501.31(1,9)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
READ BYTE POST PROC
@BOX 2.0
MAP REAL ADDRESS AND
READ BYTE
@BOX 3.0
END
@BOX 1.1
PROC READ.BYTE.POST.PROC;
@BOX 2.1
MAKE (LOGICAL8, 0, VV.READ.BYTE + REAL.STORE.ADDRESS) => BUFFER;
BUFFER^ => VV.BYTE;
@BOX 3.1
END
@END

@TITLE AP501.32(1,9)

@COL 1S-2R-3F


@FLOW 1-2-3

@BOX 1.0
WRITE BYTE POST PROC
@BOX 2.0
MAP ADDRESS AND
COPY BYTE TO STORE
@BOX 3.0
END
@BOX 1.1
PROC WRITE.BYTE.POST.PROC;
@BOX 2.1
MAKE (LOGICAL8, 0, VV.WRITE.BYTE + REAL.STORE.ADDRESS) => BUFFER;
VV.BYTE => BUFFER^;
@BOX 3.1
END
@END
@TITLE AP501.34(1,11)

@COL 1S-2T-4R-5R-3F
@COL 6R
@FLOW 1-2NO-4-5-3
@FLOW 2YES-6-3
@ROW 4-6
@BOX 1.0
BUS ERROR INTERRUPT (ERROR TYPE)
@BOX 2.0
AT INTERRUPT LEVEL?
@BOX 4.0
SET HARDWARE REGISTERS
@BOX 5.0
SET FAULT CODE
@BOX 6.0
HALT
@BOX 3.0
END
@BOX 1.1
PROC BUS.ERROR.INTERRUPT (ERROR.TYPE);
   INTEGER32 SEG
@BOX 2.1
IF AT.INT.LEVEL /= 0
@BOX 4.1
*#%23EE %0014 %0084 %0C36; ::MOVEL 20(A6), V.FIXED.ADDRS2
0 => V.GSR; ::CLEAR FAULT
V.FIXED.ADDRS2 ->> SYS14.SEG.SHIFT => SEG <<- SYS14.SEG.SHIFT
   -= V.FIXED.ADDRS2 ->> SYS14.PAGE.SHIFT => V.NEQ.BLK;
SEG => V.NEQ.SEG;
IF ERROR.TYPE = 1 OR
   VV.EXEC.MC.CONTROL = 0 AND
   SEG >= SYS14.FIRST.COMMON.SEG AND
   ACCESS OF SYS14.CST [SEG - SYS14.FIRST.COMMON.SEG] & 8 = 0 THEN
   %20 => V.NEQ.ACCESS;
ELSE
   0 => V.NEQ.ACCESS;
FI
@BOX  5.1
*#%33EE %0012 %0084 %0C36; :: MOVEW 18(A6), V.FIXED.ADDRS2
( IF V.FIXED.ADDRS2 & %100 = 0 THEN 2 ELSE 4 ) +> V.NEQ.ACCESS;
IF V.EXEC.MC.CONTROL = 0 THEN 8 +> V.NEQ.ACCESS; FI
3 => INT.PENDING => INT.TYPE;
@BOX 6.1
*#%60FE; ::BRA -2
@BOX 3.1
END
@END
@TITLE AP501.37(1,9)

@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
*#%23EE %0004 %0084 %0C0A;
:: MOVEL 4(A6), V.APP.LINK
@BOX 3.1
*#%2C56; :: MOVEAL (A6), A6
@BOX 4.1
END
@END
@TITLE AP501.38(1,9)

@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
*#%2EB9 %0084 %0C0A;
:: MOVEL V.APP.LINK, (A7)
@BOX 3.1
END
@END
@TITLE AP501.39(1,9)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
PRB RA POST PROC
@BOX 2.0
ADD REAL STORE ADDRESS
TO PRB RA V-LINE
@BOX 3.0
END
@BOX 1.1
PROC PRB.RA.POST.PROC;
@BOX 2.1
REAL.STORE.ADDRESS +> VV.PRB.RA;
@BOX 3.1
END
@END




@TITLE AP501.40(1,10)

@COL 1S

@BOX 1.0
RAW INTERRUPT CODE FOR INTERRUPT VECTORS
   2 BUS ERROR
   3 ADDRESS ERROR
   4 ILLEGAL INSTRUCTION
   5 ZERO DIVIDE
   6 CHK INSTRUCTION
   7 TRAPV INSTRUCTION
   8 PRIVILEGE VIOLATION
   25 TIMER INTERRUPT
   26 KEYBOARD INTERRUPT
   29 DISC INTERRUPT
   30 COMMS INTERRUPT
   32 TRAP INSTRUCTION 0
   33 TRAP INSTRUCTION 1
   34 TRAP INSTRUCTION 2
   35 TRAP INSTRUCTION 3
   36 TRAP INSTRUCTION 4
@BOX 1.1
VECTOR2: ::BUS ERROR
#AP501.40.1

VECTOR3: ::ADDRESS ERROR
   *#%3F3C %0001; ::MOVW #1, -(A7)
   *#%2F3C %0000 %0003; ::MOVEL #3, -(A7)
   *#%4EF9 %0080 %0000; ::JMP ENTRY CODE

VECTOR4: ::ILLEGAL INSTRUCTION
   *#%3F3C %0002; ::MOVW #2, -(A7)
   *#%2F3C %0000 %0004; ::MOVL #4, -(A7)
   *#%4EF9 %0080 %0000; ::JMP ENTRY CODE

VECTOR5: ::ZERO DIVIDE
   *#%3F3C %0001; ::MOVW #1, -(A7)
   *#%2F3C %0000 %0005; ::MOVL #5, -(A7)
   *#%4EF9 %0080 %0000; ::JMP ENTRY CODE

VECTOR6: ::CHK INSTRUCTION
   *#%3F3C %0800; ::MOVW #800, -(A7)
   *#%2F3C %0000 %0006; ::MOVL #6, -(A7)
   *#%4EF9 %0080 %0000; ::JMP ENTRY CODE

VECTOR7: ::TRAPV INSTRUCTION
   *#%3F3C %0001; ::MOVW #1, -(A7)
   *#%2F3C %0000 %0007; ::MOVL #7, -(A7)
   *#%4EF9 %0080 %0000; ::JMP ENTRY CODE

VECTOR8: ::PRIVILEGE VIOLATION
   *#%3F3C %0002; ::MOVW #2, -(A7)
   *#%2F3C %0000 %0008; ::MOVL #8, -(A7)
   *#%4EF9 %0080 %0000; ::JMP ENTRY CODE

VECTOR25: ::TIMER
   *#%3F3C %0000; ::MOVW #0, -(A7)
   *#%2F3C %0000 %0019; ::MOVL #25, -(A7)
   *#%4EF9 %0080 %0000; ::JMP ENTRY CODE

VECTOR26: ::KEYBOARD
   *#%3F3C %0000; ::MOVW #0, -(A7)
   *#%2F3C %0000 %001A; ::MOVL #26, -(A7)
   *#%4EF9 %0080 %0000; ::JMP ENTRY CODE

VECTOR29: ::DISC INTERRUPT
   *#%3F3C %0000; ::MOVW #0, -(A7)
   *#%2F3C %0000 %001D; ::MOVL #29, -(A7)
   *#%4EF9 %0080 %0000; ::JMP ENTRY CODE

VECTOR30: ::COMMS
   *#%3F3C %0000; ::MOVW #0, -(A7)
   *#%2F3C %0000 %001E; ::MOVL #30, -(A7)
   *#%4EF9 %0080 %0000; ::JMP ENTRY CODE

VECTOR32: ::TRAP 0
   *#%3F3C %0000; ::MOVW #0, -(A7)
   *#%2F3C %0000 %0020; ::MOVL #32, -(A7)
   *#%4EF9 %0080 %0000; ::JMP ENTRY CODE

VECTOR33: ::TRAP 1
   *#%3F3C %0000; ::MOVW #0, -(A7)
   *#%2F3C %0000 %0021; ::MOVL #33, -(A7)
   *#%4EF9 %0080 %0000; ::JMP ENTRY CODE

VECTOR34: ::TRAP 2
   *#%3F3C %0100; ::MOVW #%100, -(A7)
   *#%2F3C %0000 %0022; ::MOVL #34, -(A7)
   *#%4EF9 %0080 %0000; ::JMP ENTRY CODE

VECTOR35: ::TRAP 3
   *#%3F3C %0200; ::MOVW #%200, -(A7)
   *#%2F3C %0000 %0023; ::MOVL #35, -(A7)
   *#%4EF9 %0080 %0000; ::JMP ENTRY CODE

VECTOR36: ::TRAP 4
   *#%3F3C %0002; ::MOVW #2, -(A7)
   *#%2F3C %0000 %0024; ::MOVL #36, -(A7)
   *#%4EF9 %0080 %0000; ::JMP ENTRY CODE

DATAVEC INTERRUPT.PROCS (ADDR SYSTEM.ERROR.INTERRUPT)
   SYSTEM.ERROR.INTERRUPT
   SYSTEM.ERROR.INTERRUPT
   BUS.ERROR.INTERRUPT [2]
   FAULT.INTERRUPT [5]
   SYSTEM.ERROR.INTERRUPT [16]
   TICKER.INTERRUPT
   SYSTEM.ERROR.INTERRUPT
   SYSTEM.ERROR.INTERRUPT
   SYSTEM.ERROR.INTERRUPT
   Q.DISC.INT
   SYSTEM.ERROR.INTERRUPT
   SYSTEM.ERROR.INTERRUPT
   ENTER.INT.LEVEL.INTERRUPT
   CMD.ENTRY.EXIT.INTERRUPT
   FAULT.INTERRUPT [3]
   SCC.PROCESS.SPECIAL.I.CH
   SCC.PROCESS.SPECIAL.O.CH
END
@END

@TITLE AP501.40.1(1,11)
@COL 1S-2R-16R-17R-3R-4R-5R-6R-10R-14R-15F
@FLOW 1-2-16-17-3-4-5-6-10-14-15
@BOX 1.0
RAW INTERRUPT CODE FOR BUS ERROR INTERRUPT
@BOX 2.0
SAVE REGISTERS AND FETCH FAULT ADDRESS
@BOX 3.0
JUMP IF LOCAL SEGMENT
@BOX 4.0
LOAD CST BASE AND ASSOCIATED ASN AND ASM
GOTO BOX 6
@BOX 5.0
LOAD LST BASE AND ASSOCIATED ASN AND ASM
@BOX 6.0
FIND PAGE TABLE
#AP501.40.1.2
@BOX 10.0
PAGE SIZE DEPENDANT CODE
INDEX PAGE TABLE TO FETCH
STATUS AND ADDRESS OF PAGE
@BOX 14.0
CONTINUE AT AP501.40.1.1
@BOX 15.0
END
@BOX 16.0
JUMP IF NOT ACCESS VIOLATION
@BOX 17.0
RESTORE REGISTERS
LOAD FAUL CODE
JUMP TO ENTRY CODE
@BOX 1.1
::RAW INTERRUPT CODE FOR BUS ERROR INTERRUPT
@BOX 2.1
*#%48E7 %F0C0; ::MOVEML D0-D3, A0-A1, -(A7)
*#%206F %0022; ::MOVEAL 34(A7), A0
*#%2008;       ::MOVEL A0, D0
*#%52B9 %0084 %0C4A; :: ADDQL #1, V.BUS.ERRORS
@BOX 3.1
*#%7212;       ::L0 MOVEQ #%12, D1
*#%E2A8;       ::LSRL D1, D0
*#%0C00 %0020; ::CMPIB #%0020, D0
*#%6B10;       ::BMI L1
@BOX 4.1
*#%7601;      :: MOVEQ #1, D3
*#%2279 %0084 %0C22; ::MOVEL CSTBASE, A1
*#%3239 %0084 %0C32; ::MOVEW CASNM, D1
*#%600E;       ::BRA L2
@BOX 5.1
*#%4203;      :: L1 CLRB D3
*#%2279 %0084 %0C26; ::MOVEL LSTBASE, A1
*#%3239 %0084 %0C34; ::MOVEW LASNM, D1
@BOX 6.1
::FIND PAGE TABLE
#AP501.40.1.2
@BOX 10.1
*#%0282 %0000 %FFFF; ::L3 ANDIL #%0000FFFF, D2
*#%7009; ::MOVEQ #9,D0 !CPSD!
*#%E1AA      ; ::LSLL D0, D2
*#%2008      ; ::MOVEL A0, D0
::1K PAGE *#%0280 %0003 %FC00; ::ANDIL #3FC00, D0 !PSD!
::2K PAGE *#%0280 %0003 %F800; :: ANDIL #3F800, D0
::4K PAGE *#%0280 %0003 %F000; :: ANDIL #3F000, D0
*#%EA88      ; ::LSRL #5, D0 !PSD!
::1K PAGE *#%E688; ::LSRL #3, D0 !PSD!
::2K PAGE *#%E888; :: LSRL #4, D0
::4K PAGE *#%EA88; :: LSRL #5, D0
*#%2242      ; ::MOVEL D2, A1
*#%0680 %0008 %0000; ::ADDIL %RA.RAM, D0
*#%2431 %0800; ::MOVEL (A1,D0), D2
*#%2002      ; ::MOVEL D2, D0
@BOX 14.1
#AP501.40.1.1
@BOX 15.1
::END
@BOX 16.1
*#%4A2F %0022; ::TSTB 34(A7)
*#%660C; :: BNE ERR
*#%227C %00FF %FFEF; ::MOVEL #%FFFFEF, A1
*#%0811 %0006; ::BTST 6, (A1)
*#%6714; ::BEQ L0
@BOX 17.1
*#%4CDF %030F; ::ERR MOVEML (A7)+, D0-D3, A0-A1
*#%3F3C %0001; ::MOVEW #1, -(A7)
*#%2F3C %0000 %0002; ::MOVEL #2, -(A7)
*#%4EF9 %0080 %0000; ::JMP ENTRY CODE
@END

@TITLE AP501.40.1.1(1,11)
@COL 1S-11R-12R-13R-2R-3R-4R-5R-6R-7R-8R-9F
@FLOW 1-11-12-13-2-3-4-5-6-7-8-9
@BOX 1.0
CONTINUATION CHART OF AP501.40.1
@BOX 2.0
JUMP IF DESCRIPTOR POINTER
NEGATIVE
@BOX 3.0
RESET DECRIPTOR POINTER
@BOX 4.0
SAVE DESCRIPTOR POINTER
LOAD DESCRIPTOR INTO ACCUMULATOR
@BOX 5.0
PAGE SIZE DEPENDANT CODE
LOAD LOGICAL AND PHYSICAL
ADDRESS INTO ACCUMULATOR
@BOX 6.0
PAGE SIZE DEPENDANT CODE
LOAD ASN AND ASM AND STATUS
INTO ACCUMULATOR
@BOX 7.0
CLEAR GLOBAL STATUS REGISTER
RELOAD DESCRIPTOR
@BOX 8.0
RESTORE REGISTERS
RETURN FROM EXCEPTION
@BOX 9.0
END
@BOX 11.0
JUMP IF PAGE IN CORE
@BOX 12.0
RESTORE REGISTERS
LOAD FAULT CODE
JUMP TO ENTRY CODE
@BOX 13.0
LOAD DESCRIPTOR POINTER
AND DECREMENT
@BOX 1.1
::CONTINUATION CHART
@BOX 2.1
*#%6A02      ; ::BPL L5
@BOX 3.1
*#%701A;       ::MOVEQ #%1A, D0
@BOX 4.1
*#%13C0 %0084 %0C31; ::L5 MOVEB D0, RR
*#%227C %00FF %FFE0; ::MOVEL #%FFFFE0, A1
*#%1340 %0009; ::MOVEB D0, 9(A1)
*#%1029 %0011; ::MOVEB 17(A1), D0
@BOX 5.1
*#%2008      ; ::MOVEL A0, D0
*#%E888      ; ::LSRL #4, D0
*#%E888      ; ::LSRL #4, D0
*#%3280      ; ::MOVEW D0, (A1)
*#%E34A; :: LSLW #1, D2 !CPSD! (CORE.PAGE.SHIFT - 8)
*#%0642 %800; :: ADDW %800, D2
*#%3342 %0004; ::MOVEW D2, 4(A1)
@BOX 6.1
*#%1341 %0008; ::MOVEB D1, 8(A1)
*#%1203; ::MOVEB D3, D1
*#%3341 %0006; ::MOVEW D1, 6(A1)
::1K PAGE *#%337C %FFFC %0002; :: MOVW #%FFFC, 2(A1) !PSD!
::2K PAGE *#%337C %FFF8 %0002; :: MOVW #%FFF8, 2(A1)
::4K PAGE *#%337C %FFF0 %0002; :: MOVW #%FFF0, 2(A1)
@BOX 7.1
*#%137C %0001 %000D; ::MOVEB #1, 13(A1)
*#%1029 %001F; ::MOVEB 31(A1), D0
@BOX 8.1
*#%4CDF %030F; ::MOVEML (A7)+, D0-D3, A0-A1
*#%4E73      ; ::RTE
@BOX 9.1
::END
@BOX 11.1
*#%0280 %8180 %0000; :: ANDIL %81800000, D0
*#%0C80 %8080 %0000; :: CMPIL VALID & INCORE, D0
*#%6714; :: BEQ L4
@BOX 12.1
*#%4CDF %030F; ::MOVEML (A7)+, D0-D3, A0-A1
*#%3F3C %0000; ::MOVEW #0, -(A7)
*#%2F3C %0000 %0002; ::MOVEL #2, -(A7)
*#%4EF9 %0080 %0000; ::JMP ENTRY CODE
@BOX 13.1
*#%1039 %0084 %0C31; ::L4 MOVEB RR, D0
*#%5300;       ::SUBQB #1, D0
@END

@TITLE AP501.40.1.2(1,10)
@COL 1S-6R-7R-8R-9R-2F
@FLOW 1-6-7-8-9-2
@BOX 1.0
FIND PAGE TABLE
@BOX 2.0
END
@BOX 6.0
FETCH SSN FROM SEGMENT TABLE
@BOX 7.0
INDEX SST.PT TO FETCH PAGE TABLE
STATUS AND ADDRESS
@BOX 8.0
JUMP IF PAGE TABLE IN CORE
@BOX 9.0
RESTORE REGISTERS
LOAD FAULT CODE
JUMP TO ENTRY CODE
@BOX 1.1
::FIND PAGE TABLE
BEGIN
@BOX 2.1
END
@BOX 6.1
*#%E308;       ::L2 LSLB #1,D0
*#%3031 %0000; ::MOVEW 0(A1,D0), D0
@BOX 7.1
*#%0C03 %0001; :: CMPIB #1, D3
*#%6B22;      :: BMI #34
*#%0800 %000B; :: BTST #11, D0
*#%6706;       :: BEQ #6
*#%323C %2020; :: MOVEW #%2020, D1
*#%6016; :: BRA 22
*#%0C2F %0004 %0021; :: CMPIB #4,33(A7)
*#%6A0E; :: BPL 14
*#%1639 %00FF %FFC2; :: MOVB AST.UD,D3
*#%0283 %0000 %0040; :: ANDIL %40, D3
*#%670A; :: BEQ 10
*#%7601;       :: MOVEQ #1, D3
*#%0800 %0009; :: BTST #9, D0
*#%6602;       :: BNE #2
*#%7603;       :: MOVEQ #3, D3
*#%0240 %00FF; :: ANDIW #%00FF, D0
*#%E548      ; ::LSLW #2, D0
*#%2279 %0084 %0C2A; ::MOVEL SST.PT.BASE, A1
*#%2031 %0000; ::MOVEL 0(A1,D0), D0
*#%2400      ; ::MOVEL D0, D2
@BOX 8.1
*#%0280 %8180 %0000; ::ANDIL %81800000, D0
*#%0C80 %8080 %0000; :: CMPIL VALID & INCORE, D0
*#%6604; :: BNE 4
*#%4A03; :: TST D3
*#%6614      ; ::BNE L3
@BOX 9.1
*#%4CDF %030F; ::MOVEML (A7)+, D0-D3, A0-A1
*#%3F3C %0000; ::MOVEW #0, -(A7)
*#%2F3C %0000 %0002; ::MOVEL #2, -(A7)
*#%4EF9 %0080 %0000; ::JMP ENTRY CODE
@END


@TITLE AP501.41(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 (LOGICAL32, SYS14.PAGE.SIZE ->> 2, VV.CLEAR.PAGE * SYS14.PAGE.SIZE
    + REAL.STORE.ADDRESS) => CLEAR.PTR;
FOR INDEX < SYS14.PAGE.SIZE ->> 2 DO
   0 => CLEAR.PTR^ [INDEX];
OD
@BOX 6.1
END
@END



