mirror of
https://github.com/PDP-10/its.git
synced 2026-01-27 12:42:10 +00:00
425 lines
12 KiB
Plaintext
Executable File
425 lines
12 KiB
Plaintext
Executable File
; -*- Fundamental -*-
|
||
|
||
.TOC "ITS PAGE REFILL CODE"
|
||
|
||
.IF/ITS
|
||
|
||
CLEANUP DONE "END STATE, SKIP IRPT, J/PFTRAP"
|
||
CLEANUP AND TRAP "[AR]_WORK[SV.VMA], SKIP/TRAP CYCLE, J/CLTRP"
|
||
|
||
;ITS page table entry:
|
||
; (when shifted left once the valid bit, cache bit, write bit and page
|
||
; number will be in the right place for loading the hardware.)
|
||
PTE VALID/=<91> ;2.8 (internal to the microcode)
|
||
PTE AGE/=<94> ;2.5
|
||
ALL=1 ; (actually a field of length 1)
|
||
PTE WRITE/=<94> ;2.5 (internal to the microcode)
|
||
PTE CACHE/=<95> ;2.4
|
||
PTE PAGE/=<98:107> ;2.1 - 1.1
|
||
|
||
;Hardware page table control bits:
|
||
PT VALID/=<90> ;2.9
|
||
PT WRITE/=<93> ;2.6
|
||
PT CACHE/=<94> ;2.5
|
||
PT PAGE/=<97:107> ;2.2 - 1.1
|
||
EVEN=3776
|
||
ALL=3777
|
||
|
||
; VMA flags: Page fail word flags:
|
||
;4.9 User mode User mode
|
||
;FORCE USER
|
||
;4.8 Exec mode Nonexistent IO register
|
||
NONEXISTENT IO REGISTER/=<91> ;J/IOW5
|
||
;4.7 Instruction fetch Nonexistent memory
|
||
NONEXISTENT MEMORY/=<92> ;J/PFD
|
||
;4.6 Read Uncorrectable memory error
|
||
UNCORRECTABLE MEMORY ERROR/=<93> ;J/PFD, J/BADDATA
|
||
;4.5 Write test
|
||
;WRITE TEST
|
||
;4.4 Write Memory write
|
||
;WRITE CYCLE
|
||
;4.3 2.9 from page table entry
|
||
;4.2 Don't cache 2.8 from page table entry
|
||
PAGE ACCESS/=<96:97>
|
||
;4.1 Physical Physical
|
||
;PHYSICAL
|
||
;3.4 - 1.1 Address Address
|
||
ADDRESS HIGH/=<104:107>
|
||
MEMORY=3 ;20 bits of physical memory address.
|
||
IO=17 ;22 bits of IO address.
|
||
ALL=17
|
||
|
||
; (These VMA flags only from DP:)
|
||
;3.8 IO cycle IO cycle
|
||
;IO CYCLE
|
||
;3.7 WRU cycle
|
||
;3.6 Vector cycle
|
||
;3.5 Byte cycle IO byte cycle
|
||
;IO BYTE
|
||
|
||
; (These VMA flags only from #:)
|
||
;3.9 - 3.7 XCTR control
|
||
;3.6 Hack for AREAD: DROM supplies 4.6 - 4.4 and 3.4
|
||
;3.5 Ignore 4.9 - 3.7 from # and use 4.9 - 3.5 from DP instead.
|
||
;3.4 Load the VMA
|
||
;3.3 Extended address: Use 3.4 - 3.1
|
||
;3.2 Wait: Start a cycle.
|
||
;3.1 Hack for BWRITE: DROM supplies 3.2
|
||
|
||
.DCODE
|
||
257: IOT, AC, J/UUO257 ;Used to be MAP
|
||
.UCODE
|
||
|
||
1553:
|
||
UUO257: UUO
|
||
|
||
;The hardware comes here with a page fail or pending interrupt:
|
||
3777:
|
||
PAGE-FAIL:
|
||
WORK[SV.AR]_[AR]
|
||
;;INTERRUPT-TRAP macro (which nobody uses) does the above and comes
|
||
;;here:
|
||
ITRAP: WORK[SV.ARX]_[ARX] ;J/MVSKP
|
||
WORK[SV.BRX]_[BRX]
|
||
[BRX]_VMA ;BRX: FLAGS,,VMA
|
||
WORK[SV.VMA]_[BRX],
|
||
SKIP IRPT ;See if interrupt (saves a dispatch)
|
||
=0000
|
||
PFD: DBM/PF DISP, DBUS/DBM, ;Puts page fail condition on
|
||
AD/D, DEST/PASS, 4T, ;DP 18-21.
|
||
DISP/DP LEFT, J/PFD ;Dispatch on it.
|
||
=0001 WORK[SV.BR]_[BR], ;(1) Interrupt
|
||
J/PF-INT
|
||
=0011 [BRX]_IO DATA, ;(3) Parity
|
||
AD PARITY OK/0, ;Don't look at parity.
|
||
J/BADDATA
|
||
=0101 [BRX]_[100000] XWD 0, ;(5) NXM
|
||
J/HARD
|
||
=0111 [BRX]_[140000] XWD 0, ;(7) NXM & Parity
|
||
J/HARD
|
||
=1000 WORK[SV.BR]_[BR], ;(10) Read-only page
|
||
J/PFMAP
|
||
=1001 WORK[SV.BR]_[BR], ;[123] (11) 1 ms timer and movsrj
|
||
J/PF-INT
|
||
=1010 WORK[SV.BR]_[BR], ;(12) Nonexistent page
|
||
J/PFMAP
|
||
=1011 WORK[SV.BR]_[BR], ;(13) Exec/User mismatch
|
||
J/PFMAP
|
||
=
|
||
|
||
;Here is how a hard memory error is handled:
|
||
BADDATA:
|
||
WORK[BADW0]_[BRX] ;Save bad word.
|
||
[BRX]_[040000] XWD 0
|
||
;;I/O failures come here from J/IOW5 with 200000 in BRX:
|
||
HARD: WORK[SV.BR]_[BR] ;Finally save BR
|
||
=0 [BR]_VMA, ;VMA for page fail word.
|
||
CALL [ABORT] ;Clear page fault condition.
|
||
[BR]_[BR].AND.#, ;Save interesting flags:
|
||
FORCE USER/1, PHYSICAL/1,
|
||
IO CYCLE/1, IO BYTE/1,
|
||
ADDRESS HIGH/ALL, HOLD RIGHT
|
||
= [BRX]_[BRX].OR.[BR] ;BRX: Page fail word
|
||
PAGE FAIL TRAP
|
||
|
||
;Here is what happens when the initial dispatch on the page fail condition
|
||
;tells us an interrupt is pending:
|
||
PF-INT: SKIP IRPT ;Timer trap?
|
||
=00 [AR]_WORK[TIME1], ;Yes: Get low word.
|
||
SPEC/CLRCLK, ; Clear clock flag.
|
||
CALL [TOCK] ; Do the update. TOCK returns 2.
|
||
CLEANUP AND TRAP ;No: External interrupt. Jump away
|
||
ABORT MEM CYCLE ;Clear 1ms flags.
|
||
=
|
||
.IF/PCST ;Take a PC sample every millisecond
|
||
[AR]_WORK[SV.VMA] ;Recover VMA and flags
|
||
[ARX]_WORK[PCST], SKIP DP0 ;Skip if PC sampling is enabled
|
||
=0 [ARX]_WORK[SV.ARX], J/PAGE-CONTINUE1 ;Disabled or table full
|
||
[BR]_PC WITH FLAGS
|
||
TL [AR], FETCH/1 ;Skip if PC points at current instruction
|
||
=0 [BR]_[BR]-1, HOLD LEFT ;No, back up the PC that gets stored
|
||
WORK[PCST]_[ARX]+[XWD1] ;Increment the AOBJN pointer
|
||
[ARX] LEFT_0 ;Clear high bits of physical address damn it
|
||
VMA_[ARX], VMA PHYSICAL WRITE ;Store PC into sample table
|
||
MEM WRITE, MEM_[BR], J/PAGE-CONTINUE
|
||
.IFNOT/PCST
|
||
[AR]_WORK[SV.VMA], ;Restore VMA and continue where
|
||
J/PAGE-CONTINUE ; we left off.
|
||
.ENDIF/PCST
|
||
|
||
;Here we handle a soft page failure. BRX contains VMA FLAGS,,VMA.
|
||
PFMAP: ABORT MEM CYCLE ;Clear page fail condition.
|
||
TL [BRX], WRITE TEST/1 ;Write test?
|
||
=0 [BRX]_[BRX].OR.#, ;Yes: Turn into simple write.
|
||
WRITE CYCLE/1, HOLD RIGHT
|
||
[BRX]_[BRX].AND.#, ;Save interesting flags:
|
||
FORCE USER/1, WRITE CYCLE/1, PHYSICAL/1,
|
||
ADDRESS HIGH/MEMORY, HOLD RIGHT
|
||
= [AR]_[BRX], ;Copy virtual address and
|
||
SC_9. ;prepare to shift 11 places.
|
||
=0
|
||
PFMAP1: [AR]_[AR]*.5, ;Right adjust page #
|
||
STEP SC, J/PFMAP1
|
||
[AR]_[AR].AND.# CLR LH, ;AR: index off DBR
|
||
#/77
|
||
= READ [BRX], SKIP DP0 ;User ref?
|
||
=0 READ [BRX], SKIP DP18, ;Exec high ref?
|
||
J/EXEC-DBR
|
||
READ [BRX], SKIP DP18, ;User high ref?
|
||
J/USER-DBR
|
||
=
|
||
|
||
=0
|
||
USER-DBR:
|
||
[AR]_[AR]+WORK[DBR1], ;User low
|
||
J/GOTDBR
|
||
[AR]_[AR]+WORK[DBR2], ;User high
|
||
J/GOTDBR
|
||
=
|
||
|
||
=0
|
||
EXEC-DBR:
|
||
[AR]_[AR]+WORK[DBR4], ;Exec low
|
||
J/GOTDBR
|
||
[AR]_[AR]+WORK[DBR3], ;Exec high
|
||
J/GOTDBR
|
||
=
|
||
|
||
;BRX: Original VMA FLAGS,,VMA modified as for a page fail word.
|
||
;AR: Address of page table word.
|
||
GOTDBR: VMA_[AR], START READ, VMA PHYSICAL
|
||
MEM READ, [BR]_MEM
|
||
TR [BRX], #/2000 ;Odd?
|
||
=0 [ARX]_[BR], ;Yes: entry is in right half, just copy it
|
||
J/PTWRH ; into ARX.
|
||
[ARX]_[BR] SWAP, ;No: entry is in left half, so copy in ARX
|
||
J/PTWLH ; is swapped first.
|
||
=
|
||
|
||
PTWRH: [BR]_[BR].AND.NOT.#, ;BR gets the word to write back with the
|
||
PTE AGE/ALL, ; age bits cleared in the right half.
|
||
HOLD LEFT,
|
||
SKIP DP18, J/PTWTST ;Test 2.9 of entry.
|
||
|
||
PTWLH: [BR]_[BR].AND.NOT.#, ;BR gets the word to write back with the
|
||
PTE AGE/ALL, ; age bits cleared in the left half.
|
||
HOLD RIGHT,
|
||
SKIP DP0, J/PTWTST ;Test 2.9 of entry.
|
||
|
||
=0
|
||
PTWTST: TR [ARX], #/200000, J/PTWTS0 ;0X: Test 2.8
|
||
TR [ARX], #/200000, J/PTWTS1 ;1X: Test 2.8
|
||
=
|
||
|
||
=0
|
||
PTWTS0: [BRX]_[BRX].OR.#, ;01: Read only
|
||
PAGE ACCESS/1, ;Indicate that in page fail word.
|
||
HOLD RIGHT,
|
||
J/READ-ONLY
|
||
PAGE FAIL TRAP ;00: Not accessible.
|
||
=
|
||
|
||
=0
|
||
PTWTS1: [ARX]_[ARX].OR.#, ;11: Read/Write
|
||
PTE WRITE/1, ;Set Writable bit in page table.
|
||
HOLD LEFT,
|
||
J/PAGE-REFILL
|
||
[BRX]_[BRX].OR.#, ;10: Read/Write/First
|
||
PAGE ACCESS/2, ;Indicate that in page fail word.
|
||
HOLD RIGHT,
|
||
J/READ-ONLY
|
||
=
|
||
|
||
READ-ONLY:
|
||
TL [BRX], ;Were we perhaps trying to write?
|
||
WRITE CYCLE/1
|
||
=0 PAGE FAIL TRAP ;That would be a problem wouldn't it!
|
||
[ARX]_[ARX].AND.NOT.#, ;Clear writable bit in page table.
|
||
PTE WRITE/1,
|
||
HOLD LEFT,
|
||
J/PAGE-REFILL
|
||
=
|
||
|
||
;BRX: Original VMA FLAGS,,VMA modified as for a page fail word.
|
||
;AR: Address of page table word.
|
||
;ARX: Half formed page table entry in right half.
|
||
;BR: Original page table word with the age bit set.
|
||
PAGE-REFILL:
|
||
VMA_[AR], ;Prepare to put the word back.
|
||
START WRITE,
|
||
VMA PHYSICAL
|
||
MEM WRITE, ;Write it back.
|
||
MEM_[BR]
|
||
[AR]_WORK[SV.VMA] ;AR: For PAGE-CONTINUE to use.
|
||
[BR]_[AR].AND.NOT.#, ;Clear bits which start a cycle.
|
||
READ CYCLE/1, WRITE CYCLE/1,
|
||
WRITE TEST/1, HOLD RIGHT
|
||
[BR]_[AR].AND.NOT.#, ;Make DEC page number even.
|
||
#/1000, HOLD LEFT
|
||
VMA_[BR], 3T, DP FUNC/1 ;Restore VMA and set User according to
|
||
;what it was.
|
||
[ARX]_([ARX].OR.#)*2, ;Set Valid bit and shift into position.
|
||
3T, PTE VALID/1,
|
||
LOAD PAGE TABLE ;Load page table on next instruction.
|
||
[ARX]_[ARX].AND.# CLR LH, ;Mask out all but the correct
|
||
PT VALID/1, PT WRITE/1, ; bits. Make the DEC physical
|
||
PT CACHE/1, PT PAGE/EVEN ; page number even.
|
||
[BR]_[BR].OR.#, ;Make DEC page number in VMA odd.
|
||
#/1000, HOLD LEFT
|
||
VMA_[BR], 3T, DP FUNC/1 ;Restore VMA again for the odd page.
|
||
[ARX]_[ARX].OR.#, ;Then the odd physical page.
|
||
#/1, HOLD LEFT,
|
||
LOAD PAGE TABLE ;Load page table on next instruction.
|
||
READ [ARX],
|
||
J/PAGE-CONTINUE
|
||
|
||
;Return to interrupted microinstruction after a successful page table
|
||
;reload or a timer trap. AR should contain the right VMA to restart the
|
||
;memory cycle.
|
||
PAGE-CONTINUE:
|
||
[ARX]_WORK[SV.ARX] ;Restore saved stuff
|
||
PAGE-CONTINUE1:
|
||
[BR]_WORK[SV.BR]
|
||
[BRX]_WORK[SV.BRX]
|
||
VMA_[AR], ;MAKE MEM REQUEST
|
||
DP FUNC/1, 3T, ;FROM DATA PATH
|
||
WAIT/1 ;WAIT FOR PREVIOUS CYCLE TO
|
||
; COMPLETE. (NEED THIS TO
|
||
; START ANOTHER CYCLE)
|
||
[AR]_WORK[SV.AR],
|
||
RETURN [0]
|
||
|
||
;;; Here we have hair to back us out of an instruction in case we have to
|
||
;;; deliver a page fault or an interrupt. Think of it as micro PCLSRing.
|
||
;;; Anybody who comes to this page to deliver a page fault better have set
|
||
;;; up BRX to contain the right page fail word first. Cleanup handlers
|
||
;;; better not smash it either.
|
||
|
||
;PAGE FAIL TRAP macro does:
|
||
; TL [FLG], FLG.PI/1, ;PI cycle?
|
||
; J/PFT
|
||
=0
|
||
PFT: HALT [IOPF] ;Yes: IO Page Failure
|
||
CLEANUP AND TRAP ;No: deliver hard page fault.
|
||
=
|
||
|
||
;CLEANUP AND TRAP macro does:
|
||
; [AR]_WORK[SV.VMA],
|
||
; SKIP/TRAP CYCLE, ;See if trap cycle.
|
||
; J/CLTRP
|
||
=0
|
||
CLTRP: TL [AR], FETCH/1, ;Is this an instruction fetch?
|
||
J/CLTRP1
|
||
[AR]_WORK[TRAPPC] ;This is a trap cycle.
|
||
= READ [AR], LOAD FLAGS, ;Restore PC flags.
|
||
J/CLDISP
|
||
|
||
=0
|
||
.IF/1PROC ;Fault/interrupt while in instruction fetch
|
||
CLTRP1: TL [FLG], FLG.2PROC/1, J/CLTRP2
|
||
.IFNOT/1PROC
|
||
CLTRP1: CLEANUP DONE ;Instruction fetch: Everything is clean.
|
||
.ENDIF/1PROC
|
||
;;Many things jump here to backup the PC and cleanup.
|
||
FIXPC: [PC]_[PC]-1, HOLD LEFT
|
||
= ;;Many things jump here to cleanup.
|
||
CLDISP: READ [FLG], DBUS/DP, DISP/DP, 3T, J/CLEANUP
|
||
;;CLEANUP DISP macro (which nobody uses) does the above.
|
||
|
||
.IF/1PROC
|
||
=0
|
||
CLTRP2: TAKE 1-PROCEED TRAP ;Take one-proceed trap instead of this one
|
||
CLEANUP DONE
|
||
.ENDIF/1PROC
|
||
|
||
=0000
|
||
CLEANUP: ;;Dispatch table to cleanup after a page fault or interrupt.
|
||
CLEANED: ;;J/BLT-CLEANUP ;(0) Normal case: No more cleanup needed.
|
||
CLEANUP DONE ;Go deliver page fault or interrupt.
|
||
=0001 [AR]_WORK[SV.ARX], ;(1) BLT
|
||
J/BLT-CLEANUP
|
||
;(2) Unused.
|
||
=0011 STATE_[EDIT-SRC], ;(3) SRC IN STRING MOVE
|
||
J/STRPF
|
||
=0100 STATE_[EDIT-DST], ;(4) DST IN STRING MOVE
|
||
J/STRPF
|
||
=0101 STATE_[SRC], ;(5) SRC+DST IN STRING MOVE
|
||
J/BACKD
|
||
=0110 STATE_[EDIT-DST], ;(6) FILL IN MOVSRJ
|
||
J/STRPF4
|
||
=0111 STATE_[EDIT-SRC], ;(7) DEC TO BIN
|
||
J/PFDBIN
|
||
=1000 STATE_[EDIT-SRC], ;(10) SRC+DST IN COMP
|
||
J/CMSDST
|
||
=1001 END STATE, J/BACKS ;(11) EDIT SRC FAIL
|
||
=1010 END STATE, J/BACKD ;(12) EDIT DST FAIL
|
||
=1011 STATE_[EDIT-SRC], ;(13) SRC+DST IN EDIT
|
||
J/BACKD
|
||
=
|
||
|
||
;CLEANUP DONE macro does:
|
||
; END STATE, SKIP IRPT, J/PFTRAP
|
||
=0
|
||
PFTRAP: TR [PI], ;Here to deliver page fault after cleanup.
|
||
PI.IP1/1, PI.IP2/1, ; This hack figures out what 3 locations to
|
||
PI.IP3/1, PI.IP4/1, ; use to deliver the page fault.
|
||
J/PFTDSP
|
||
TAKE INTERRUPT ;Here to deliver interrupt after cleanup.
|
||
; J/PI after setting FLG.PI
|
||
=
|
||
|
||
=0
|
||
PFTDSP: TR [PI], PI.IP1/1, PI.IP2/1, J/PFTDS1
|
||
TR [PI], PI.IP5/1, PI.IP6/1, J/PFTDS0
|
||
=0
|
||
PFTDS1: TR [PI], PI.IP1/1, J/PFTD11
|
||
TR [PI], PI.IP3/1, J/PFTD10
|
||
=0
|
||
PFTDS0: TR [PI], PI.IP5/1, J/PFTD01
|
||
TR [PI], PI.IP7/1, J/PFTD00
|
||
=0
|
||
PFTD11: [AR]_0 XWD [443], J/PFTRAP1
|
||
[AR]_0 XWD [446], J/PFTRAP1
|
||
=0
|
||
PFTD10: [AR]_0 XWD [451], J/PFTRAP1
|
||
[AR]_0 XWD [454], J/PFTRAP1
|
||
=0
|
||
PFTD01: [AR]_0 XWD [457], J/PFTRAP1
|
||
[AR]_0 XWD [462], J/PFTRAP1
|
||
=0
|
||
PFTD00: [AR]_0 XWD [465], J/PFTRAP1
|
||
[AR]_0 XWD [440], J/PFTRAP1
|
||
=
|
||
|
||
PFTRAP1:
|
||
[AR]_[AR]+[EBR], ; Where to store PFW
|
||
VMA PHYSICAL WRITE
|
||
MEM WRITE, ; Store PFW
|
||
MEM_[BRX]
|
||
.IF/1PROC
|
||
=0** NEXT [AR] PHYSICAL WRITE, ; Where to store old PC
|
||
CALL [STORE-INT-PC]
|
||
.IFNOT/1PROC
|
||
NEXT [AR] PHYSICAL WRITE ; Where to store old PC
|
||
[BR]_PC WITH FLAGS ; Get old PC
|
||
MEM WRITE, ; Store old PC
|
||
MEM_[BR]
|
||
.ENDIF/1PROC
|
||
[AR]_[AR]+1, ; Where to get new PC
|
||
VMA PHYSICAL READ,
|
||
J/GOEXEC
|
||
|
||
.IF/1PROC
|
||
STORE-INT-PC:
|
||
[BR]_PC WITH FLAGS ; Get old PC
|
||
TL [FLG], FLG.1PROC/1 ; Was the instruction being one-proceeded?
|
||
=0 [BR]_[BR].OR.#, OIPBIT/1, ;It was, turn pc flag back on
|
||
HOLD RIGHT, J/STORE-INT-PC-2
|
||
STORE-INT-PC-1:
|
||
MEM WRITE, MEM_[BR], RETURN [4]
|
||
STORE-INT-PC-2:
|
||
[FLG]_[FLG].AND.NOT.#, FLG.1PROC/1, ;Clear 1-proceed flags
|
||
FLG.2PROC/1, HOLD RIGHT, J/STORE-INT-PC-1
|
||
.ENDIF/1PROC
|
||
.ENDIF/ITS
|