@X @~
~L3 COUK1247
80
~V7 56 2 -5
~V9 -1
~P
~D10
~H                  MUSS
~
~
~D10
~H            AP5013
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL~
~
~
                                                             ISSUE 11~
~V9 -1
~P
~V9 1
~YAP5013
~S1~M~OAP5 IMPLEMENTATION DESCRIPTION~
~S1~M~OSection 1 Version 3~
~S1~OSection 1.3 MC68000 Processor Appendix (Gemstone)~
~S1~O1. General Description~
~BThis module is concerned with mapping the CPU features of the MUSS
ideal machine onto the Gemstone 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.MILLI.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.STACK.SEG~
   V.VAL.ACCESS~
   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)~
   UPDATE.IDLE.TIME ()~
   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~
   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, V.MILLI.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.~
~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 %800000.
~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
~BThe vector addresses for peripheral interrupts are the
defaults provided by the line module software.
~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:~
~3
~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~
~0
~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~
~
   FP - Frame Pointer~
   PC - Program Counter~
   SF - Stack Front~
   XNB - Non-local Name Base~
~0
~
~ONOTES~
~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~
~
   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 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~
~
   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~
~
~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~
~0
~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.6 Memory mapping
~BThe memory management hardware supports a block of segment descriptors
for up to 32 processes. Each block defines the attributes of 64 segments,
including pointers into a block of page descriptor registers. The segment
descriptors for processes 30 and 31 are defined to map the common store accessib
le
to all processes as segments 128 to 255. The other blocks of segment
descriptors are mapped on to the MUSS activities (as defined by SYS01), such
that the hardware process number is equivalent to (31 - SYS01.CURRENT.ACTIVITY).
~BIn addition to the hardware process numbers assigned for common segments,
three additional process numbers are reserved for system use.
The segment descriptors for process 27 map the real store, and a block
of page descriptors are initialised by CONSYS code to provide this
mapping. This is the process number active when running at MC68000
supervisor level (ie. at MUSS interrupt level and when servicing
hardware interrupts).
~BThe segment descriptors for processes 28 and 29 are equivalent
to those for process 30, ie. the first 64 common segments, but these
contain access permission fields suitable for running at user level and
command level respectively. Thus, when entering a process running at user
level, the segment descriptors for process 28 are copied into those
for process 30; when entering a process running at command level,
the segment descriptors for process 29 are copied into those for
process 30. The context switch between user and command level
involves reloading the registers for process 30 as appropriate.
~BWhen the segment descriptors point to a page table in the page descriptor
registers, the layout of the segment descriptors is defined by the Gemstone
processor description. When segments are not mapped in this way,
the bottom three bytes of a segment descriptor are loaded
with the system segment number, the access permission and limit.
The access permission is modified by inverting the defined and privileged
bits so that it is compatible with the actual form required
for a segment descriptor.
~BTwo additional tables are used by the appendix code in managing
the hardware descriptor tables: a mapped activity table (MAT),
indexed by activity number, associates an activity with an SPN so
that reloading of the segment descriptors can be inhibited if they
are already loaded for a process. Secondly, a mapped system segment
table (MSST) defines whether the page table corresponding to a
system segment is loaded into the hardware page descriptor registers.

~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.~
~
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.~
~
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.~
~Y
~V9 -1
~P
~V9 -1
~D15
~HFLOWCHARTS
~
~
~H               AP5013
~V9 -1
~F
@TITLE AP501(3,11)
@COL 1S-2R-3R-4R-5R-6F
@FLOW 1-2-3-4-5-6
@BOX 1.0
MC68000 GEMSTONE PROCESSOR APPENDIX
@BOX 4.0
PROCEDURES IN MODULE
    1 SET HW INT
    2 CLEAR HW INT
    3 INT TREE POST PROC
    4 FAULT INTERRUPT
    5 SYSTEM ERROR INTERRUPT
    6 ENTER INT LEVEL INTERRUPT
    7 ENTER AP INT
    8 INT MC CONTROL POST PROC
    9 CLOCK INT POST PROC
   10 TICKER INTERRUPT
   11 RESET STATUS POST PROC
   12 CALL LINK PRE PROC
   13 EXIT LINK POST PROC
   14 MS BIT
   15 BIT
   16 SET BIT
   17 CLEAR BIT
   18 TEST BIT
   19 VALIDATE
   20 CMD ENTRY EXIT INTERRUPT
   21 INIT REGS POST PROC
   22 APP OUTWARD CALL
   23 ALLOW INTERRUPTS PRE PROC
   24 INHIBIT INTERRUPTS PRE PROC
   25 SF PRE PROC
   26 BUS ERROR INTERRUPT
   27 APP LINK PRE PROC
   28 APP LINK POST PROC
   29 RESET MMU
   30 RAW INTERRUPT ROUTINES
   31 CORE DATA PRE PROC
   32 CORE DATA POST PROC
   33 CLEAR PAGE POST PROC
@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.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.APP.LINK,
   V.CORE.PAGE, V.CORE.DATA, V.CLEAR.PAGE,
   EMPTY.ACTIVITY, PROC.ACTIVITY, SET.HW.INT, CLEAR.HW.INT,
   MS.BIT, BIT, SET.BIT, CLEAR.BIT, TEST.BIT,
   VALIDATE, APP.OUTWARD.CALL, UPDATE.IDLE.TIME,
   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);
@BOX 2.1
TYPE APP.STATS.TYPE IS
   INTEGER CMDS.CALLED, USER.TIME, CMD.TIME, INT.TIME, DUMMY;
@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;
#AP501/4
4 => VV.MC.NO;
1 => VV.INT.MC.CONTROL => AT.INT.LEVEL;
0 => V.TICKER.CONTROL;
V.TICKER.STATUS;
SYS14.SEG.SIZE - RESERVED.STACK.BOTTOM => USER.STACK.BASE;
MAKE (APP.STATS.TYPE, 0, SYS21.GET.STATS (0)) => APP.STATS;
BYTE (^MSST) => MSST.ADDR;
BYTE (^SYS14.SST.PT [0]) => V.SST.PT.PTR;
NO.OF.LOCKED.PTS => PT.DESCRIPTOR.PTR;
FOR I < 32 DO
   -1 => MAT [I];
OD
FOR I < SYS14.NO.OF.SYS.SEGS DO
   0 => MSST [I];
OD
END
@BOX 6.1
*END
@END
@TITLE AP501/1(3,11)
@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.PTS;
IMPORT LITERAL ADDR REAL.STORE.ADDRESS;
@BOX 3.1
PSPEC POLL.DEVICES ();
PSPEC GEM.DISC.INT (INTEGER);
PSPEC GEM.PROCESS.SPECIAL.I.CH (INTEGER);
PSPEC GEM.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.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(3,11)

@COL 1S
@BOX 1.0
DATA DECLARATIONS
@BOX 1.1
*GLOBAL 5;
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.VM.INTS, VV.INIT.REGS,
   VV.STACK.SEG, VV.BYTE, VV.CORE.PAGE, VV.CORE.DATA, VV.CLEAR.PAGE;
LOGICAL32 VV.TIME, VV.MILLI.TIME, VV.PRB.RA;
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, SEG.PTR, INDEX;
ADDR [LOGICAL64] CLEAR.PTR;
ADDR USER.STACK.BASE;
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;
LOGICAL8 [32] MAT;
LOGICAL16 [SYS14.NO.OF.SYS.SEGS] MSST;
:: 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 %840C22;
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;
*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;
*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.CURRENT.SEGS %840C4E;
VSTORE V.SST.PT.PTR %840C2A;
VSTORE PT.DESCRIPTOR.PTR %840C2E;
VSTORE MSST.ADDR %840C32;
VSTORE V.FIXED.ADDRS2 %840C36;
VSTORE V.CLEAR.PAGE VV.CLEAR.PAGE > CLEAR.PAGE.POST.PROC;
*VTYPE LOGICAL8;
VSTORE V.TICKER.CONTROL %406022;
VSTORE V.TICKER.STATUS %406020;
VSTORE L.LIGHT %408000;
VSTORE R.LIGHT %408001;
*VTYPE LOGICAL16;
VSTORE V.STATE.REGISTER %506000;
VSTORE SEG.DESCRIPTOR [%100000] %400000;
VSTORE PAGE.DESCRIPTOR [4096] %402000;
:: 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
DATAVEC LIGHTS (LOGICAL16)
   %FF40 %FF79 %FF24 %FF30
   %FF19 %FF12 %FF03 %FF78
   %FF00 %FF18 %F940 %F979
   %F924 %F930 %F919 %F912
END
@END
@TITLE AP501/3(3,11)

@COL 1S
@BOX 1.0
PROCEDURES IN MODULE
@BOX 1.1
*CODE 2;
:: ENTER.AP.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 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 BUS.ERROR.INTERRUPT (INTEGER);
:: PSPEC APP.LINK.PRE.PROC ();
:: PSPEC APP.LINK.POST.PROC ():
:: PSPEC CLOCK.INT.POST.PROC ();
:: PSPEC CALL.LINK.PRE.PROC ();
:: PSPEC EXIT.LINK.POST.PROC ();
:: PSPEC CLEAR.PAGE.POST.PROC ();
PSPEC RESET.MMU ();
PROC PRB.RA.POST.PROC;
*#%46FC %2700;
RESET.MMU ();
*#%46FC %2000;
END
PSPEC EMPTY.ACTIVITY ();
PROC EMPTY.ACTIVITY;
   SYS12.SYSTEM.ERROR (-1);
END
PSPEC UPDATE.IDLE.TIME ();
PROC UPDATE.IDLE.TIME;
END
   #AP501.7
   #AP501.1
   #AP501.2
   #AP501.3
   #AP501.4
   #AP501.5
   #AP501.6
   #AP501.10
   #AP501.11
   #AP501.20
   #AP501.23
   #AP501.24
   #AP501.26
   #AP501.27
   #AP501.28
   #AP501.30
   #AP501.31
   #AP501.32
   #AP501.9
   #AP501.12
   #AP501.13
   #AP501.29
   #AP501.33
*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;
   #AP501.8
   #AP501.14
   #AP501.15
   #AP501.16
   #AP501.17
   #AP501.18
*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.19
   #AP501.21
   #AP501.22
   #AP501.25
@END
@TITLE AP501/4(3,11)

@COL 1S

@BOX 1.0
INITIALISATION DATA
@BOX 1.1
*VTYPE LOGICAL32;
VSTORE INT.VEC2 %200E;
VSTORE INT.VEC3 %2014;
VSTORE INT.VEC4 %201A;
VSTORE INT.VEC5 %2020;
VSTORE INT.VEC6 %2026;
VSTORE INT.VEC7 %202C;
VSTORE INT.VEC8 %2032;
VSTORE INT.VEC28 %20AA;
VSTORE INT.VEC32 %20C2;
VSTORE INT.VEC33 %20C8;
VSTORE INT.VEC34 %20CE;
VSTORE INT.VEC35 %20D4;
VSTORE INT.VEC36 %20DA;
*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;
VECTOR28 => VEC.LABEL;
VEC.LABEL.ADDR=> INT.VEC28;
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(3,11)
@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
@BOX 4.0
END
@BOX 1.1
PROC SET.HW.INT (ACTIVITY);
@BOX 2.1
ACTIVITY !> VV.HW.INTS;
@BOX 3.1
VV.HW.INTS ! VV.SW.INTS ! VV.HALT.MASK -= VV.HALT.MASK => VV.FI;
IF AT.INT.LEVEL = 0 AND VV.FI & SYS01.INT.ACTIVITIES /= 0 THEN
   1 => INT.PENDING;
FI
@BOX 4.1
END
@END
@TITLE AP501.2(3,11)
@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
@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
VV.HW.INTS ! VV.SW.INTS ! VV.HALT.MASK -= VV.HALT.MASK => VV.FI;
@BOX 4.1
END
@END
@TITLE AP501.3(3,11)
@COL 1S-3R
@FLOW 1-3
@BOX 1.0
INT TREE POST PROC
@BOX 3.0
UPDATE INTERRUPT TREE
@BOX 1.1
::INT TREE POST PROC 1 FOR V.SW.INTS
::INT TREE POST PROC 2 FOR V.HALT.MASK
@BOX 3.1
PROC INT.TREE.POST.PROC.1;
   *#%46FC %2700; ::INHIBIT INTS;
   VV.HW.INTS ! VV.SW.INTS ! VV.HALT.MASK -= VV.HALT.MASK => VV.FI;
   *#%46FC %2000; ::ALLOW INTS;
END

PROC INT.TREE.POST.PROC.2;
   *#%46FC %2700; ::INHIBIT INTS;
   VV.HW.INTS ! VV.SW.INTS ! VV.HALT.MASK -= VV.HALT.MASK => VV.FI;
   *#%46FC %2000; ::ALLOW INTS;
END
@END
@TITLE AP501.4(3,11)

@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 ! V.EXEC.MC.CONTROL /= 0
   OR SYS01.CURRENT.ACTIVITY.BIT & SYS01.PZ.ACTIVITY /= 0
@BOX 3.1
*#%4E4F;
@BOX 4.1
END
@BOX 5.1
REASON !> VV.PF.STATUS;
@BOX 6.1
1 => INT.PENDING => INT.TYPE;
@END
@TITLE AP501.5(3,11)

@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
*#%4E4F;
@BOX 4.1
END
@END
@TITLE AP501.6(3,11)
@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 V.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.7(3,11)

@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];
V.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;
*#%46FC %2000; ::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.8(3,11)

@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 SYSTEM BASED INTERRUPT PENDING
@BOX 13.0
END
@BOX 14.0
SAVE INTERRUPT LEVEL FP
@BOX 16.0
SET MEMORY MANAGEMENT SYSTEM
ACCORDING TO PRIVILEGE OF 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]
   => V.EXEC.MC.CONTROL /= 0 OR VV.VM.INTS = 0
@BOX 6.1
%9B1F - SYS01.CURRENT.ACTIVITY => V.STATE.REGISTER;
31 - SYS01.CURRENT.ACTIVITY <<- 2 + %400000 => V.CURRENT.SEGS;
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 => V.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 SEG.DESCRIPTOR [V.EXEC.MC.CONTROL + %1C <<- 1] /=
   SEG.DESCRIPTOR [%3C] THEN
   *#%4AB9 %0084 %0C22; ::TST V.EXEC.MC.CONTROL;
   *#%6608; ::BNE +8;
   *#%207C %0040 %0070; ::MOVA USER.COMMON.SEGS, A0;
   *#%6006; ::BR +6;
   *#%207C %0040 %0074; ::MOVA CMD.COMMON.SEGS, A0;
   *#%227C %0040 %0078; ::MOVA ACTUAL.COMMON.SEGS, A0;
   *#%703F; ::MOVQ 63, D0;
   *#%2290; ::MOVL (A0), (A1);
   *#%D1FC %0001 %0000; ::ADDL #10000, A0;
   *#%D3FC %0001 %0000; ::ADDL #10000, A1;
   *#%51C8 %FFF0; ::DBF D0, -16;
FI
@BOX 17.1
1 => VV.INT.MC.CONTROL;
@END
@TITLE AP501.9(3,11)

@COL 1S-3R-5F

@FLOW 1-3-5

@BOX 1.0
CLOCK INT POST PROC
@BOX 3.0
CLEAR CLOCK HW INT
@BOX 5.0
END
@BOX 1.1
PROC CLOCK.INT.POST.PROC;
@BOX 3.1
*#%46FC %2700; ::INHIBIT INTS;
SYS01.CLOCK.ACTIVITY & VV.HW.INTS -=> VV.HW.INTS
   ! VV.SW.INTS ! VV.HALT.MASK -= VV.HALT.MASK => VV.FI;
*#%46FC %2000; ::ALLOW INTS;
@BOX 5.1
END
@END

@TITLE AP501.10(3,11)

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

@FLOW 1-2NO-11-3-4-5-12-6NO-7=<0-8NO-9-10
@FLOW 2YES-12
@FLOW 6YES-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 REAL TIME CLOCK
@BOX 4.0
RESET INTERRUPT COUNT
@BOX 5.0
SET HARDWARE INTERRUPT
[AP201.1]
@BOX 6.0
AT INTERRUPT LEVEL
OR IN PROCESS 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
MONITOR TIME USED
AT EACH LEVEL
@BOX 1.1
PROC TICKER.INTERRUPT (DUMMY);
@BOX 2.1
IF 1 -> TICKER.INT.COUNT > 0
@BOX 3.1
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 ! AT.INT.LEVEL /= 0
   OR VV.PROCESS.NUMBER = 0
@BOX 7.1
IF 1000 / TICKS.PER.SECOND  -> VM.TIMER > 0
@BOX 8.1
IF V.EXEC.MC.CONTROL /= 0
@BOX 9.1
4 => INT.PENDING => INT.TYPE;
@BOX 10.1
END
@BOX 11.1
POLL.DEVICES ();
@BOX 12.1
IF VV.INT.MC.CONTROL ! AT.INT.LEVEL /= 0 THEN
   1 +> INT.TIME OF APP.STATS^;
ELSE
   IF V.EXEC.MC.CONTROL /= 0 THEN
      1 +> CMD.TIME OF APP.STATS^;
   ELSE
      1 +> USER.TIME OF APP.STATS^;
   FI
FI
@END


@TITLE AP501.11(3,11)

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

@ROW 5-7

@FLOW 1-2NO-3-4SEG AND BLOCK-5-6
@FLOW 2YES-7-6
@FLOW 4SEG-7

@BOX 1.0
RESET STATUS POST PROC
@BOX 2.0
RESET ON SSN?
@BOX 3.0
GET SSN OF REQUIRED SEGMENT
@BOX 4.0
RESET SEG?
@BOX 5.0
RESET THE SPECIFIED
PAGE TABLE ENTRY
@BOX 6.0
END
@BOX 7.0
INITIALISE ALL ACTIVITY TABLES AND
MAPPED SYSTEM SEGMENT TABLE ENTRY
@BOX 1.1
PROC RESET.STATUS.POST.PROC;
PSPEC RESET.PROC ();
*#%46FC %2700;
RESET.PROC ();
*#%46FC %2000;

PROC RESET.PROC;
INTEGER SEG, BLOCK;
ADDR PTR;
ADDR [LOGICAL32] PT;
ADDR SYS14.SEG.VARS C.SEG.VARS;
ADDR SYS14.LST.TYPE LST.PTR;
@BOX 2.1
VV.RESET.SEG => SEG;
IF VV.RESET.STATUS = 1
@BOX 3.1
IF SEG < SYS14.NO.OF.LOCAL.SEGS THEN
   MAKE (SYS14.SEG.VARS, 0, SYS13.INT.GET.PRB (14)) => C.SEG.VARS;
   ^LST [SEG] OF C.SEG.VARS^ => LST.PTR;
ELSE
   ^SYS14.CST [SEG - SYS14.FIRST.COMMON.SEG] => LST.PTR;
FI
SELECT LST.PTR^;
SSN => SEG;
@BOX 4.1
IF VV.RESET.STATUS = 2
@BOX 5.1
-1 => MAT [SYS01.CURRENT.ACTIVITY];
VV.RESET.BLK => BLOCK;
MAKE (LOGICAL32, SYS14.PAGE.SIZE ->>2, SYS14.SST.PT [SSN]
   & PAGE.FIELD * SYS02.CORE.PAGE.SIZE) => PT;
IF PT^ [BLOCK] & %81800000 = %80800000 THEN
   IF ACCESS & 2 /= 0 THEN
      %4000000 !> PT^ [BLOCK];
   FI
   IF MSST [SSN] > 0 THEN
      PT^ [BLOCK] & PAGE.FIELD ->> 1 ! %4000 => PAGE.DESCRIPTOR [MSST [SSN] + BL
OCK];
   FI
ELSE
   IF MSST [SSN] > 0 THEN
      0 => PAGE.DESCRIPTOR [MSST [SSN] + BLOCK];
   FI
FI
@BOX 6.1
END
END
@BOX 7.1
0 => MSST [SEG];
FOR PTR < 32 DO
   -1 => MAT [PTR];
OD
RESET.MMU ();
@END

@TITLE AP501.12(3,11)
@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.13(3,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
LIGHTS [SYS01.CURRENT.ACTIVITY] => R.LIGHT;
LIGHTS [SYS01.CURRENT.ACTIVITY] ->> 8 => L.LIGHT;
*#%2C79 %0084 %0C12; :: MOVEAL SAVE.LINK, A6
:: SAVE.LINK {V.EXIT.LINK} => A6
@BOX 3.1
END
@END
@TITLE AP501.14(3,11)
@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.15(3,11)
@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.16(3,11)
@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.17(3,11)
@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.18(3,11)
@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.19(3,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.20(3,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
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
AND RESET MEMORY MANAGEMENT
FOR COMMON SEGMENTS
@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
*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 OR VV.VM.INTS /= 0 THEN
   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 => V.EXEC.MC.CONTROL;
*#%4E68; :: MOVE USP, A0
*#%2D48 %FFF8; :: MOVEL A0, -8(A6)
@BOX 11.1
IF V.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 => V.EXEC.MC.CONTROL;
FI
@BOX 19.1
1 => PZ.CMD.ENTRY;
@BOX 20.1
V.EXEC.MC.CONTROL =>
   PRB.PTR16^ [DUMPED.V.EXEC.MC.CONTROL.REG.NO];
*#%4AB9 %0084 %0C22; ::TST V.EXEC.MC.CONTROL;
*#%6608; ::BNE +8;
*#%207C %0040 %0070; ::MOVA USER.COMMON.SEGS, A0;
*#%6006; ::BR +6;
*#%207C %0040 %0074; ::MOVA CMD.COMMON.SEGS, A0;
*#%227C %0040 %0078; ::MOVA ACTUAL.COMMON.SEGS, A0;
*#%703F; ::MOVQ 63, D0;
*#%2290; ::MOVL (A0), (A1);
*#%D1FC %0001 %0000; ::ADDL #10000, A0;
*#%D3FC %0001 %0000; ::ADDL #10000, A1;
*#%51C8 %FFF0; ::DBF D0, -16;
@END

@TITLE AP501.21(3,11)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
INIT REGS POST PROC
@BOX 2.0
INITIALISE 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
;
SYS11.INITIAL.TIMER => INIT.REGS.PRB.PTR16^ [DUMPED.V.VM.TIMER.REG.NO];
@BOX 3.1
END
@END


@TITLE AP501.22(3,11)
@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|>
*#%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
*#%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.23(3,11)
@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.24(3,11)
@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.25(3,11)

@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.26(3,11)
@COL 1S-2T-3T-4T-6R-9F
@COL 10R-11R-12T-13R

@ROW 6-10

@FLOW 1-2SEGMENT VALID-3NO-4IN STORE-6-9
@FLOW 2OTHER-10-11-12NO-13
@FLOW 3YES-10
@FLOW 4ABSENT-10
@FLOW 12YES-9

@BOX 1.0
BUS ERROR INTERRUPT
@BOX 2.0
EXAMINE TYPE OF INTERRUPT
@BOX 3.0
IS SEGMENT UNDEFINED?
@BOX 4.0
IS PAGE TABLE IN STORE?
@BOX 6.0
RESET THE MAPPED SYSTEM
SEGMENT TABLE
@BOX 9.0
END
@BOX 10.0
GENERATE VALUES FOR THE
IDEAL MACHINE REGISTERS
@BOX 11.0
SET VIRTUAL STORE INTERRUPT PENDING
@BOX 12.0
AT PROCESS LEVEL?
@BOX 13.0
HALT
@BOX 1.1
PROC BUS.ERROR.INTERRUPT (ERROR);
INTEGER SSN, LIM, PTR;
LOGICAL32 SEG;
ADDR [LOGICAL16] SEG.DESCRIPTOR;
@BOX 2.1
*#%23EE %0014 %0084 %0C36; ::MOVL 20(A6), V.FIXED.ADDRS2;
V.FIXED.ADDRS2 ->> 16 & %FF => V.NEQ.SEG <<- 16 => SEG;
IF ERROR & 4 = 0
@BOX 3.1
IF V.NEQ.SEG < SYS14.NO.OF.LOCAL.SEGS THEN
   MAKE (LOGICAL16, 2, V.CURRENT.SEGS + SEG) => SEG.DESCRIPTOR;
ELSE
   IF V.NEQ.SEG >= 196 THEN
      MAKE (LOGICAL16, 2, SEG + %FF80007C) => SEG.DESCRIPTOR;
   ELSE
      MAKE (LOGICAL16, %400000, SEG + %FFC00070) => SEG.DESCRIPTOR;
   FI
FI
IF SEG.DESCRIPTOR^ [0] & %FF => SSN = 0
@BOX 4.1
IF SYS14.SST.PT [SSN] & %81800000 /= %80800000
@BOX 6.1
FOR PTR < SYS14.NO.OF.SYS.SEGS DO
   0 => MSST [PTR];
OD
FOR PTR < 32 DO
   -1 => MAT [PTR];
OD
NO.OF.LOCKED.PTS => PT.DESCRIPTOR.PTR;
RESET.MMU ();
@BOX 9.1
END
@BOX 10.1
V.FIXED.ADDRS2 ->> 10 & %3F => V.NEQ.BLK;
(IF ERROR & %F = 0 THEN %20 ELSE 0) => V.NEQ.ACCESS;
*#%33EE %0012 %0084 %0C36; ::MOVW 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
@BOX 11.1
3 => INT.PENDING => INT.TYPE;
@BOX 12.1
IF AT.INT.LEVEL = 0
@BOX 13.1
*#%4E4F;
@END
@TITLE AP501.27(3,11)

@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.28(3,11)

@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.29(3,11)

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

@FLOW 1-7NO-2NO-3-4NO-5-6
@FLOW 7YES-4
@FLOW 2YES-6
@FLOW 4YES-6

@BOX 1.0
RESET MMU
@BOX 2.0
IS SEGMENT DESCRIPTOR TABLE LOADED?
@BOX 3.0
LOAD SEGMENT DESCRIPTOR TABLE
@BOX 4.0
IS COMMON SEGMENT DECRIPTOR TABLE LOADED?
@BOX 5.0
LOAD COMMON SEGMENT DESCRIPTOR TABLE
@BOX 6.0
END
@BOX 7.0
IN AN INTERRUPT ACTIVITY?
@BOX 1.1
PROC RESET.MMU;
INTEGER PTR, SYS.SEG;
ADDR SDT.ENTRY;
LOGICAL16 ACC;
ADDR SYS14.SEG.VARS C.SEG.VARS;
*VTYPE LOGICAL32;
VSTORE CSD [%400000] %400000;
*VTYPE LOGICAL;
@BOX 2.1
IF MAT [SYS01.CURRENT.ACTIVITY] = VV.PROCESS.NUMBER
@BOX 3.1
VV.PROCESS.NUMBER => MAT [SYS01.CURRENT.ACTIVITY];
MAKE (SYS14.SEG.VARS, 0, SYS13.INT.GET.PRB (14)) => C.SEG.VARS;
SELECT C.SEG.VARS^;
31 - SYS01.CURRENT.ACTIVITY <<- 1 => SDT.ENTRY;
FOR PTR < SYS14.NO.OF.LOCAL.SEGS DO
   SSN OF LST [PTR] => SYS.SEG;
   ACCESS OF LST [PTR] & %F -= 8 <<- 8 => ACC;
   IF SYS.SEG /= 0 AND MSST [SYS.SEG] /= 0 THEN
      ACC ! LIMIT OF SYS14.SST [SYS.SEG] - 1 => SEG.DESCRIPTOR [SDT.ENTRY];
      MSST [SYS.SEG] => SEG.DESCRIPTOR [SDT.ENTRY + 1];
   ELSE
      SYS.SEG => SEG.DESCRIPTOR [SDT.ENTRY];
      LIMIT OF SYS14.SST [SYS.SEG] - 1 ! ACC => SEG.DESCRIPTOR [SDT.ENTRY + 1];
   FI
   %8000 +> SDT.ENTRY;
OD
@BOX 4.1
IF MAT [0] >= 0
@BOX 5.1
0 => MAT [0];
%40038 => SDT.ENTRY;
::FIRST 8 COMMON SEGMENTS LOCKED
FOR PTR < SYS14.NO.OF.COMMON.SEGS - 8 DO
   SSN OF SYS14.CST [PTR + 8] => SYS.SEG;
   ACCESS OF SYS14.CST [PTR + 8] & %F -= 8 <<- 8 => ACC;
   IF SYS.SEG /= 0 AND MSST [SYS.SEG] /= 0 THEN
      ACC ! LIMIT OF SYS14.SST [SYS.SEG] - 1 => SEG.DESCRIPTOR [SDT.ENTRY];
      MSST [SYS.SEG] => SEG.DESCRIPTOR [SDT.ENTRY + 1];
   ELSE
      SYS.SEG => SEG.DESCRIPTOR [SDT.ENTRY];
      LIMIT OF SYS14.SST [SYS.SEG] - 1 ! ACC => SEG.DESCRIPTOR [SDT.ENTRY + 1];
   FI
   IF PTR = 55 THEN
      %3E => SDT.ENTRY;
   ELSE
      %8000 +> SDT.ENTRY;
   FI
OD
%2001C => SDT.ENTRY;
FOR PTR < 56 DO
   CSD [SDT.ENTRY] & %F7FFFFFF => CSD [SDT.ENTRY + 1] => CSD [SDT.ENTRY + 2];
   %4000 +> SDT.ENTRY;
OD
@BOX 6.1
END
@BOX 7.1
IF SYS01.CURRENT.ACTIVITY.BIT & SYS01.INT.ACTIVITIES /= 0
@END




@TITLE AP501.30(3,11)

@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
   28 TIMER 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.30.1

VECTOR3: ::ADDRESS ERROR
   *#%3F3C %00F0; ::MOVW #F0, -(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

VECTOR28: ::TIMER
   *#%3F3C %0000; ::MOVW #0, -(A7)
   *#%2F3C %0000 %001C; ::MOVL #28, -(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 [19]
   TICKER.INTERRUPT
   GEM.DISC.INT
   SYSTEM.ERROR.INTERRUPT
   SYSTEM.ERROR.INTERRUPT
   ENTER.INT.LEVEL.INTERRUPT
   CMD.ENTRY.EXIT.INTERRUPT
   FAULT.INTERRUPT [3]
   GEM.PROCESS.SPECIAL.I.CH
   GEM.PROCESS.SPECIAL.O.CH
END
@END

@TITLE AP501.30.1(3,11)

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

@FLOW 1-2-4-3SEGMENT VALID-5NO-14NO-6NO-7IN STORE-8-10-9-11
@FLOW 3OTHER-13
@FLOW 5YES-13
@FLOW 14YES-9
@FLOW 6YES-13
@FLOW 7-13

@BOX 1.0
BUS ERROR RAW INTERRUPT
@BOX 2.0
SAVE REGISTERS
@BOX 3.0
EXAMINE TYPE OF INTERRUPT
@BOX 4.0
SET POINTER TO
SEGMENT DESCRIPTOR
@BOX 5.0
IS SEGMENT UNDEFINED?
@BOX 6.0
INSUFFICIENT SPACE IN
PAGE DESCRIPTOR TABLES?
@BOX 7.0
IS PAGE TABLE IN STORE?
@BOX 8.0
LOAD MSST ENTRY
@BOX 9.0
LOAD SEGMENT DESCRIPTOR
@BOX 10.0
COPY PAGE TABLE TO
PAGE DESCRIPTORS
@BOX 11.0
RESTORE REGISTERS AND
RETURN FROM INTERRUPT
@BOX 12.0
END
@BOX 13.0
RESTORE REGISTERS AND
JUMP TO ENTRY CODE
@BOX 14.0
IS PAGE TABLE LOADED?
@BOX 1.1
::BUS ERROR RAW INTERRUPT
BEGIN
@BOX 2.1
*#%3F39 %0058 %6000; ::MOVW ERROR.STATUS, -(A7);
*#%48E7 %F0E0; ::MOVML D0-D3, A0-A2, -(A7);
@BOX 3.1
*#%4279 %0058 %6000; ::CLRW ERROR.STATUS;
*#%026F %FFFB %001C; ::ANDIW #FFFB, 28(A7);
*#%3210; ::MOVW (A0), D1;
*#%0241 %0700; ::ANDIW #0700, D1;
*#%6704; ::BEQ +4;
-> BOX13; ::
@BOX 4.1
::LOAD A0 WITH SEGMENT DESCRIPTOR ADDRESS
*#%4280; ::CLRL D0;
*#%102F %0029; ::MOVB 41(A7), D0;
*#%2200; ::MOVL D0, D1;
*#%E849; ::LSRW 4, D1;
*#%0241 %000C; ::ANDIW #C, D1;
*#%207C %0084 %0C4E; ::MOVL #840C4E, A0;
*#%D1C1; ::ADDA D1, A0;
*#%2050; ::MOVA (A0), A0;
*#%4840; ::SWAP D0;
*#%D1C0; ::ADD D0, A0;
@BOX 5.1
*#%3F7C %0004 %001C; ::MOVW #4, 28(A7);
*#%3028 %0002; ::MOVW 2(A0), D0;
*#%4281; ::CLRL D1;
*#%1228 %0001; ::MOVB 1(A0), D1;
*#%6604; ::BNE +4;
-> BOX13; ::
@BOX 6.1
::LOAD D3 WITH LIMIT OF SEGMENT
*#%4283; ::CLRL D3;
*#%1600; ::MOVB D0, D3;
*#%2403; ::MOVL D3, D2;
*#%D4B9 %0084 %0C2E; ::ADD PT.DESCRIPTOR.PTR, D2;
*#%0C42 %0FFF; ::CMPI 4095, D2;
*#%6F04; ::BLE +4;
-> BOX13; ::
@BOX 7.1
*#%2279 %0084 %0C2A; ::MOVA SST.PT.ADDR, A1;
*#%E349; ::LSLW 1, D1;
*#%2031 %1000; ::MOVL 0(A1, D1), D0;
*#%2400; ::MOVL D0, D2;
*#%0280 %8180 %0000; ::ANDIL %81800000, D0;
*#%0C80 %8080 %0000; ::CMPIL VALID & IN CORE, D0;
*#%6704; ::BEQ +4;
-> BOX13; ::
@BOX 8.1
*#%2039 %0084 %0C2E; ::MOVL PT.DESCRIPTOR.PTR, D0;
*#%3480; ::MOVW D0, (A2);
@BOX 9.1
BOX9:
*#%30A8 %0002; ::MOVW 2(A0), (A0);
*#%3140 %0002; ::MOVW D0, 2(A0);
*#%4A2F %0029; ::TSTB 41(A7);
*#%6A24; ::BPL +36;
*#%0C2F %00C0 %0029; ::CMPB 41(A7), 192;
*#%6A1C; ::BPL +28;
*#%2010; ::MOVL (A0), D0;
*#%0280 %F7FF %FFFF; ::ANDIL #F7FFFFFF, D0;
*#%2140 %0004; ::MOVL D0, 4(A0);
*#%2140 %0008; ::MOVL D0, 8(A0);
*#%4AB9 %0084 %0C22; ::TSTL V.EXEC.MC.CONTROL;
*#%6604; ::BNE +4;
*#%2150 %0008; ::MOVL (A0), 8(A0);
@BOX 10.1
::LOAD A2 WITH ADDRESS OF PAGE TABLE
*#%C4BC %0000 %07FF; ::ANDL #07FF, D2;
*#%E98A; ::LSLL 4, D2;
*#%EB8A; ::LSLL 5, D2;
*#%2442; ::MOVA D2, A2;
*#%2212; ::TOUCH THE PT;
::LOAD A1 WITH ADDRESS OF PAGE DESCRIPTORS
*#%2239 %0084 %0C2E; ::MOVL PT.DESCRIPTOR.PTR, D1;
*#%5283; ::ADDQ #1, D3;
*#%D7B9 %0084 %0C2E; ::ADD D3, PT.DESCRIPTOR.PTR;
*#%E389; ::LSLL 1, D1;
*#%227C %0040 %2000; ::MOV #402000, A1;
*#%D3C1; ::ADDL D1, A1;
::COPY PAGE TABLE TO PAGE DESCRIPTORS
*#%51CB %0004; ::DBF D3, +4;
*#%6022; ::BR +34;
*#%2212; ::MOVL (A2), D1;
*#%0281 %8180 %0000; ::ANDIL %81800000, D1;
*#%0C81 %8080 %0000; ::CMPIL VALID & INCORE, D1;
*#%660C; ::BNE +12;
*#%2212; ::MOVL (A2), D1;
*#%E241; ::LSRW 1, D1;
*#%0241 %07FF; ::ANDIW #7FF, D1;
*#%0641 %4000; ::ADDIW #4000, D1;
*#%4A9A; ::TSTL (A2)+;
*#%32C1; ::MOVW D1, (A1)+;
*#%60D8; ::BR -40;
@BOX 11.1
*#%4CDF %070F; ::MOVML (A7)+, D0 - D3, A0 - A2;
*#%548F; ::ADDQ #2, A7;
*#%4E73; ::RTE;
@BOX 12.1
END
@BOX 13.1
BOX13:
*#%4CDF %070F; ::MOVML (A7)+, D0 - D3, A0 - A2;
*#%2F3C %0000 %0002; ::MOVL 2, -(A7);
*#%4EF9 %0080 %0000; ::JMP ENTRY CODE;
@BOX 14.1
::LOAD A2 WITH MSST ADDRESS;
*#%E349; ::LSLW 1, D1;
*#%2479 %0084 %0C32; ::MOVL MSST.ADDR, A2;
*#%D4C1; ::ADD D1, A2;
*#%4A52; ::TSTW (A2);
*#%6706; ::BEQ +6;
*#%3012; ::MOVW (A2), D0;
-> BOX9; ::
@END


@TITLE AP501.31(3,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)
   => CORE.PTR;
CORE.PTR^ => VV.CORE.DATA;
@BOX 3.1
END
@END

@TITLE AP501.32(3,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)
   => CORE.PTR;
VV.CORE.DATA => CORE.PTR^;
@BOX 3.1
END
@END

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



