* LMFL(DIRECTORY "RMS" NAME "PDP10" TYPE "LISP" VERSION 1 BYTE-SIZE 10 CREATION-DATE 23073453367 AUTHOR "rms") ;PDP-10 simulator microcode ;The simulator uses an internal accumulator for its arithmetic ;and most of its data transfers. ;This internal accumulator consists of M-1 and M-2. ;M-1 holds the left half of the 36-bit quantity and M-2 the right half. (locality a-mem) a-10-pc (0) a-10-flags (0) ;Address of Q containing the left half of memory location 0. ;The memory lives in an array. ;Each pdp-10 word occupies two consecutive Qs, ;the left half in the first and the right in the second. a-10-mem-0-addr (0) (modulo 20) ;These are the left halves of the pdp-10's simulated accumulators. a-10-ac-0-left (0) (modulo 20) ;These are the right halves. a-10-ac-0-right (0) (modulo 20) (locality i-mem) ;Store the internal accumulator into the simulated accumulator ;whose number is in M-A. store-10-ac ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated accumulator whose number is in M-A ;into the internal accumulator. load-10-ac ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Load the simulated memory location whose number is in M-A ;into the internal accumulator. load-10-mem (jump-less-than m-a (a-constant 20) load-10-ac) ;Check for ACs referenced as memory. ((vma-start-read) add m-a a-10-mem-0-addr) (check-page-read) ((m-1) read-memory-data) ((vma-start-read) m+a+1 m-a a-10-mem-0-addr) (check-page-read) (popj (m-2) read-memory-data) ;Store the internal accumulator into the simulated memory location ;whose address is in M-A. store-10-mem (jump-less-than m-a (a-constant 20) store-10-ac) ;Check for ACs referenced as memory. ((write-memory-data) m-1) ((vma-start-write) add m-a a-10-mem-0-addr) (check-page-write) ((write-memory-data) m-2) ((vma-start-write) m+a+1 m-a a-10-mem-0-addr) (check-page-write) (popj) * LMFL(DIRECTORY "RMS" NAME "PDP10" TYPE "LISP" VERSION 2 BYTE-SIZE 10 CREATION-DATE 23073453374 AUTHOR "rms") ;PDP-10 simulator microcode ;The simulator uses an internal accumulator for its arithmetic ;and most of its data transfers. ;This internal accumulator consists of M-1 and M-2. ;M-1 holds the left half of the 36-bit quantity and M-2 the right half. ;The other argument of arithmetic operations goes in ;the T register, composed of M-T and M-R. ;Instructions are executed out of the instruction register, ;which occupies M-3 and M-E. ;The AC field of the instruction is standardly placed in M-A, ;and the effective address is computed in M-E. ;The pdp-10 PC lives in M-B. (locality a-mem) a-10-flags (0) ;Address of Q containing the left half of memory location 0. ;The memory lives in an array. ;Each pdp-10 word occupies two consecutive Qs, ;the left half in the first and the right in the second. a-10-mem-0-addr (0) (modulo 20) ;These are the left halves of the pdp-10's simulated accumulators. a-10-ac-0-left (0) (modulo 20) ;These are the right halves. a-10-ac-0-right (0) (modulo 20) (locality i-mem) ;Load and store simulated accumulators (AC number in M-A) ;from the internal accumulator and the T register. ;Store the internal accumulator into the simulated accumulator ;whose number is in M-A. store-10-ac ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated accumulator whose number is in M-A ;into the internal accumulator. load-10-ac ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the T register into the simulated accumulator ;whose number is in M-A. store-10-ac-t ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Load the simulated accumulator whose number is in M-A ;into the T register. load-10-ac-t ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Load and store main memory (address in M-E) ;from the internal accumulator and the T register. ;Load the simulated memory location whose number is in M-E ;into the internal accumulator. load-10-mem (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-addr) (check-page-read) ((m-1) read-memory-data) ((vma-start-read) m+a+1 m-e a-10-mem-0-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-ac-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the internal accumulator into the simulated memory location ;whose address is in M-E. store-10-mem (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-1) ((vma-start-write) add m-e a-10-mem-0-addr) (check-page-write) ((write-memory-data) m-2) ((vma-start-write) m+a+1 m-e a-10-mem-0-addr) (check-page-write) (popj) store-10-ac-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated memory location whose number is in M-E ;into the T register. load-10-mem-t (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-addr) (check-page-read) ((m-t) read-memory-data) ((vma-start-read) m+a+1 m-e a-10-mem-0-addr) (check-page-read) (popj (m-r) read-memory-data) load-10-ac-t-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Store the T register into the simulated memory location ;whose address is in M-E. store-10-mem-t (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-t) ((vma-start-write) add m-e a-10-mem-0-addr) (check-page-write) ((write-memory-data) m-r) ((vma-start-write) m+a+1 m-e a-10-mem-0-addr) (check-page-write) (popj) store-10-ac-t-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Loop point for executing the next pdp-10 instruction. next-10-insn (jump-less-than m-b (a-constant 20) xct-10-ac) ;Check for ACs referenced as memory. ((vma-start-read) add m-b a-10-mem-0-addr) (check-page-read) ((m-3) read-memory-data) ((vma-start-read) m+a+1 m-b a-10-mem-0-addr) (check-page-read) ((m-e) read-memory-data) ;Compute the effective address in M-E ;for the instruction in the instruction register (M-3, M-E). eff-addr-comp (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-addr-comp) ((m-a) pdp10-index-field m-3) ;Fetch the next instruction from an accumulator. xct-10-ac ((oa-reg-high) dpb m-b oah-a-src a-zero) ((m-3) a-10-ac-0-left) ((oa-reg-high) dpb m-b oah-a-src a-zero) (jump-xct-next xct-10-insn) ((m-e) a-10-ac-0-right) (locality d-mem) (start-dispatch 5 0) d-10-addr-comp (xct-10-insn-1) (repeat 17 (do-10-indexing)) (do-10-indirect) (repeat 17 (do-10-indexing)) (end-dispatch) (locality i-mem) ;Perform indexing on address field in M-E ;with index register number in M-A. do-10-indexing ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-e) add m-e a-10-ac-0-right) (jump-if-bit-clear-xct-next pdp10-indirect-bit xct-10-insn) ((m-e) truncate-to-halfword m-e) ;Perform indirection, and merge the indirect pointer ;into the instruction register. Then go to begin again to execute the instruction. do-10-indirect (call load-10-mem) ((m-e) m-2) (jump-xct-next eff-addr-comp) ((m-3) mask-field pdp10-opcode m-3 a-1) ;Execute the instruction in M-3 with effective address in M-E ;The execution routine finds the accumulator in M-A. xct-10-insn (dispatch-xct-next pdp10-insn-class m-3 d-10-insn) ((m-a) pdp10-ac-field m-3) ;Dispatch on major classes of pdp-10 instructions. (locality d-mem) (start-dispatch 3 0) d-10-insn (xct-10-uuo) (xct-10-random) (xct-10-move) (xct-10-what) (xct-10-logical) (xct-10-halfword) (xct-10-test) (xct-10-uuo) (end-dispatch) (locality i-mem) ;The XCT instruction. i-10-xct (call load-10-mem) ((m-3) m-1) ((m-e) m-2) (jump eff-addr-comp) i-10-lsh (call load-10-ac-op) ((m-c) m-1) ((m-d) m- * LMFL(DIRECTORY "RMS" NAME "PDP10" TYPE "LISP" VERSION 3 BYTE-SIZE 10 CREATION-DATE 23073453374 AUTHOR "rms") ;PDP-10 simulator microcode ;The simulator uses an internal accumulator for its arithmetic ;and most of its data transfers. ;This internal accumulator consists of M-1 and M-2. ;M-1 holds the left half of the 36-bit quantity and M-2 the right half. ;The other argument of arithmetic operations goes in ;the T register, composed of M-T and M-R. ;Instructions are executed out of the instruction register, ;which occupies M-3 and M-E. ;The AC field of the instruction is standardly placed in M-A, ;and the effective address is computed in M-E. ;The simulated PC lives in M-B; actually, that contains ;one less than the Q address of the left halfword of the next instruction. ;Jump instructions and PC saving instructions convert ;between this form of quantity and a pdp-10 address. (locality a-mem) a-10-flags (0) ;Address of Q containing the left half of simulated memory location 0. ;The left halves of all PDP-10 memory words live in consecutive Qs. a-10-mem-0-left-addr (0) ;Address of Q containing the right half of simulated memory location 0. ;The right halves of all PDP-10 memory words live in consecutive Qs, ;immediately following the left halves. ;Thus, this address is always 1000000 more than that in a-10-mem-0-left-addr. a-10-mem-0-right-addr (0) ;Address of left half of memory location 20, ;used for testing the PC to see whether points at an AC. a-10-mem-20-left-addr (0) (modulo 20) ;These are the left halves of the pdp-10's simulated accumulators. a-10-ac-0-left (0) (modulo 20) ;These are the right halves. a-10-ac-0-right (0) (modulo 20) (locality i-mem) ;Load and store simulated accumulators (AC number in M-A) ;from the internal accumulator and the T register. ;Store the internal accumulator into the simulated accumulator ;whose number is in M-A. store-10-ac ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated accumulator whose number is in M-A ;into the internal accumulator. load-10-ac ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the T register into the simulated accumulator ;whose number is in M-A. store-10-ac-t ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Load the simulated accumulator whose number is in M-A ;into the T register. load-10-ac-t ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Load and store main memory (address in M-E) ;from the internal accumulator and the T register. ;Load the simulated memory location whose number is in M-E ;into the internal accumulator. load-10-mem (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-1) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-ac-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the internal accumulator into the simulated memory location ;whose address is in M-E. store-10-mem (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-1) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-2) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated memory location whose number is in M-E ;into the T register. load-10-mem-t (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-t) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-r) read-memory-data) load-10-ac-t-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Store the T register into the simulated memory location ;whose address is in M-E. store-10-mem-t (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-t) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-r) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-t-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Loop point for executing the next pdp-10 instruction. next-10-insn (jump-less-than m-b a-10-mem-20-addr xct-10-ac) ;Check for ACs referenced as memory. ((vma-start-read m-b) m+1 m-b) ;Increment pc and fetch lh of insn. (check-page-read) ((m-3) read-memory-data) ((vma-start-read) add m-b (a-constant 1000000)) (check-page-read) ((m-e) read-memory-data) ;Compute the effective address in M-E ;for the instruction in the instruction register (M-3, M-E). eff-addr-comp (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-addr-comp) ((m-a) pdp10-index-field m-3) ;Fetch the next instruction from an accumulator. xct-10-ac (call get-10-pc) ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-3) a-10-ac-0-left) ((oa-reg-high) dpb m-a oah-a-src a-zero) (jump-xct-next eff-addr-comp) ((m-e) a-10-ac-0-right) (locality d-mem) (start-dispatch 5 0) d-10-addr-comp (xct-10-insn-1) (repeat 17 (do-10-indexing)) (do-10-indirect) (repeat 17 (do-10-indexing)) (end-dispatch) (locality i-mem) ;Perform indexing on address field in M-E ;with index register number in M-A. do-10-indexing ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-e) add m-e a-10-ac-0-right) (jump-if-bit-clear-xct-next pdp10-indirect-bit xct-10-insn) ((m-e) truncate-to-halfword m-e) ;Perform indirection, and merge the indirect pointer ;into the instruction register. Then go to begin again to execute the instruction. do-10-indirect (call load-10-mem) ((m-e) m-2) (jump-xct-next eff-addr-comp) ((m-3) mask-field pdp10-opcode m-3 a-1) ;Execute the instruction in M-3 with effective address in M-E ;The execution routine finds the accumulator in M-A. xct-10-insn (dispatch-xct-next pdp10-insn-class m-3 d-10-insn) ((m-a) pdp10-ac-field m-3) ;Dispatch on major classes of pdp-10 instructions. (locality d-mem) (start-dispatch 3 0) d-10-insn (xct-10-uuo) (xct-10-random) (xct-10-move) (xct-10-what) (xct-10-logical) (xct-10-halfword) (xct-10-test) (xct-10-uuo) (end-dispatch) (locality i-mem) ;The XCT instruction. i-10-xct (call load-10-mem) ((m-3) m-1) ((m-e) m-2) (jump eff-addr-comp) i-10-lsh (call load-10-ac-t) ((m-1) dpb m-t ?? a-zero) ((m-1) dpb m-r ?? a-1) ((m-2) dpb m-t ?? a-zero) ((m-2) dpb m-r ?? a-2) (call store-10-ac-t) (jump next-10-insn) ;Jump instructions ;Set the simulated pc from a pdp-10 format pc in M-2. set-10-pc (popj-after-next (m-b) add m-2 (a-constant -1)) ((m-b) add m-b a-10-mem-0-left-addr) ;Get the pc in pdp-10 form in M-2. get-10-pc (popj-after-next (m-2) sub m-b a-10-mem-0-leftaddr) ((m-2) m+1 m-2) * LMFL(DIRECTORY "RMS" NAME "PDP10" TYPE "LISP" VERSION 4 BYTE-SIZE 10 CREATION-DATE 23073453375 AUTHOR "rms") ;PDP-10 simulator microcode ;The simulator uses an internal accumulator for its arithmetic ;and most of its data transfers. ;This internal accumulator consists of M-1 and M-2. ;M-1 holds the left half of the 36-bit quantity and M-2 the right half. ;The other argument of arithmetic operations goes in ;the T register, composed of M-T and M-R. ;Instructions are executed out of the instruction register, ;which occupies M-3 and M-E. ;The AC field of the instruction is standardly placed in M-A, ;and the effective address is computed in M-E. ;The simulated PC lives in M-B; actually, that contains ;one less than the Q address of the left halfword of the next instruction. ;Jump instructions and PC saving instructions convert ;between this form of quantity and a pdp-10 address. (locality a-mem) a-10-flags (0) ;Address of Q containing the left half of simulated memory m." u(.o 0.Í{Ui$ m$gu i mw$2 .g mm QEQmq0 ,$,.s8 6.se2 m(w$ (o ".o2$"4u(w$ 2.Í mq0m,$,m0mm$gum ees (0iÍÍ{ees$22 .g  ".ou (o(o& ui$ s(&iu i mg .g 2(,4m u$e ,$,.s8 m." u(.o 0.Í{Ui$ s(&iu i mw$2 .g mm QEQmq0 ,$,.s8 6.se2 m(w$ (o ".o2$"4u(w$ 2,Í{(,,$e( u$m8 g.mm.6(o& ui$ m$gu i mw$2.Í{Ui42, ui(2 ees$22 (2 m6 82 q000000 ,.s$ ui o ui u (o mq0m,$,m0mm$gum ees.Í mq0m,$,m0ms(&ium ees (0iÍÍ{ees$22 .g m$gu i mg .g ,$,.s8 m." u(.o 20,Í{42$e g.s u$2u(o& ui$ Q u. 2$$ 6i$ui$s q.(ou2 u o .Í mq0m,$,m20mm$gum ees (0iÍÍ(,.e4m. 20iÍÍ{Ui$2$ s$ ui$ m$gu i mw$2 .g ui$ qeqmq0g2 2(,4m u$e ""4,4m u.s2.Í mq0m "m0mm$gu (0iÍÍ(,.e4m. 20iÍÍ{Ui$2$ s$ ui$ s(&iu i mw$2.Í mq0m "m0ms(&iu (0iÍÍ(,.e4m. 20iÍÍ(m." m(u8 (m,$,iÍÍ{$u ui$ 2(,4m u$e q" gs., qeqmq0 g.s, u q" (o m2.Í2$umq0mq"ÍÉ(q.qkm gu$smo$yuÍÉ (,mci ee ,m2 ( m".o2u ou mqiiÍ ((,mci ee ,mc mq0m,$,m0mm$gum eesiÍÍ{$u ui$ q" (o qeqmq0 g.s, (o m2.Í&$umq0mq"ÍÉ(q.qkm gu$smo$yuÍÉ (,m2i 24c ,mc mq0m,$,m0mm$gu eesiÍÉ((,m2i ,kq ,m2iÍ Í{M. e oe 2u.s$ 2(,4m u$e ""4,4m u.s2 ( o4,c$s (o miÍ{gs., ui$ (ou$so m ""4,4m u.s oe ui$ U s$&(2u$s.ÍÍ{u.s$ ui$ (ou$so m ""4,4m u.s (ou. ui$ 2(,4m u$e ""4,4m u.sÍ{6i.2$ o4,c$s (2 (o m.Í2u.s$mq0m "ÍÉ((. ms$&mm.6i eqc ,m . mm me$2u m{$s.iÍÉ(( mq0m "m0mm$gui ,mqiÍÉ(q.qgm gu$smo$yuÍÉ (. ms$&mm.6i eqc ,m . mm me$2u m{$s.iÍ (( mq0m "m0ms(&iui ,m2iÍÍ{M. e ui$ 2(,4m u$e ""4,4m u.s 6i.2$ o4,c$s (2 (o mÍ{(ou. ui$ (ou$so m ""4,4m u.s.Ím. emq0m "ÍÉ((. ms$&mi(&ii eqc ,m . im m2s" m{$s.iÍÉ((,mqi mq0m "m0mm$guiÍÉ(q.qkm gu$smo$yuÍÉ (. ms$&mi(&ii eqc ,m . im m2s" m{$s.iÍ ((,m2i mq0m "m0ms(&iuiÍÍ{u.s$ ui$ U s$&(2u$s (ou. ui$ 2(,4m u$e ""4,4m u.sÍ{6i.2$ o4,c$s (2 (o m.Í2u.s$mq0m "muÍÉ((. ms$&mm.6i eqc ,m . mm me$2u m{$s.iÍÉ(( mq0m "m0mm$gui ,muiÍÉ(q.qgm gu$smo$yuÍÉ (. ms$&mm.6i eqc ,m . mm me$2u m{$s.iÍ (( mq0m "m0ms(&iui ,msiÍÍ{M. e ui$ 2(,4m u$e ""4,4m u.s 6i.2$ o4,c$s (2 (o mÍ{(ou. ui$ U s$&(2u$s.Ím. emq0m "muÍÉ((. ms$&mi(&ii eqc ,m . im m2s" m{$s.iÍÉ((,mui mq0m "m0mm$guiÍÉ(q.qkm gu$smo$yuÍÉ (. ms$&mi(&ii eqc ,m . im m2s" m{$s.iÍ ((,msi mq0m "m0ms(&iuiÍ Í{M. e oe 2u.s$ , (o ,$,.s8 ( ees$22 (o miÍ{gs., ui$ (ou$so m ""4,4m u.s oe ui$ U s$&(2u$s.ÍÍ{M. e ui$ 2(,4m u$e ,$,.s8 m." u(.o 6i.2$ o4,c$s (2 (o mÍ{(ou. ui$ (ou$so m ""4,4m u.s.Ím. emq0m,$,ÍÉ(k4,qmm$22mui o ,m$ ( m".o2u ou 20iÍÉÉÉm. emq0m "m,m$iÉ{i$"* g.s 2 s$g$s$o"$e 2 ,$,.s8.ÍÉ((w, m2u sums$ ei ee ,m$ mq0m,$,m0mm$gum eesiÍÉ("i$"*mq &$ms$ eiÍÉ((,mqi s$ em,$,.s8me u iÍÉ((w, m2u sums$ ei ee ,m$ mq0m,$,m0ms(&ium eesiÍÉ("i$"*mq &$ms$ eiÍÉ(q.qk (,m2i s$ em,$,.s8me u iÍÍm. emq0m "m,m$ÍÉ((. ms$&mi(&ii eqc ,m$ . im m2s" m{$s.iÍÉ((,mqi mq0m "m0mm$guiÍÉ(q.qkm gu$smo$yuÍÉ (. ms$&mi(&ii eqc ,m$ . im m2s" m{$s.iÍ ((,m2i mq0m "m0ms(&iuiÍÍ{u.s$ ui$ (ou$so m ""4,4m u.s (ou. ui$ 2(,4m u$e ,$,.s8 m." u(.oÍ{6i.2$ ees$22 (2 (o m.Í2u.s$mq0m,$,ÍÉ(k4,qmm$22mui o ,m$ ( m".o2u ou 20iÍÉÉÉ2u.s$mq0m "m,m$iÉ{i$"* g.s 2 s$g$s$o"$e 2 ,$,.s8.ÍÉ((6s(u$m,$,.s8me u i ,mqiÍÉ((w, m2u sum6s(u$i ee ,m$ mq0m,$,m0mm$gum eesiÍÉ("i$"*mq &$m6s(u$iÍÉ((6s(u$m,$,.s8me u i ,m2iÍÉ((w, m2u sum6s(u$i ee ,m$ mq0m,$,m0ms(&ium eesiÍÉ("i$"*mq &$m6s(u$iÍÉ(q.qkiÍÍ2u.s$mq0m "m,m$ÍÉ((. ms$&mm.6i eqc ,-e oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated memory location whose number is in M-E ;into the T register. load-10-mem-t (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-t) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-r) read-memory-data) load-10-ac-t-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Store the T register into the simulated memory location ;whose address is in M-E. store-10-mem-t (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-t) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-r) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-t-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Come here to jump to effective address and execute next instruction. jump-10-jump ((m-b) add m-e a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Loop point for executing the next pdp-10 instruction. next-10-insn (jump-less-than m-b a-10-mem-20-addr xct-10-ac) ;Check for ACs referenced as memory. ((vma-start-read m-b) m+1 m-b) ;Increment pc and fetch lh of insn. (check-page-read) ((m-3) read-memory-data) ((vma-start-read) add m-b (a-constant 1000000)) (check-page-read) ((m-e) read-memory-data) ;Compute the effective address in M-E ;for the instruction in the instruction register (M-3, M-E). eff-addr-comp (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ;Fetch the next instruction from an accumulator. xct-10-ac (call get-10-pc) ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-3) a-10-ac-0-left) ((oa-reg-high) dpb m-a oah-a-src a-zero) (jump-xct-next eff-addr-comp) ((m-e) a-10-ac-0-right) (locality d-mem) (start-dispatch 5 0) d-10-index-and-indirect (xct-10-insn-1) (repeat 17 (do-10-indexing)) (do-10-indirect) (repeat 17 (do-10-indexing)) (end-dispatch) (locality i-mem) ;Perform indexing on address field in M-E ;with index register number in M-A. do-10-indexing ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-e) add m-e a-10-ac-0-right) (jump-if-bit-clear-xct-next pdp10-indirect-bit xct-10-insn) ((m-e) truncate-to-halfword m-e) ;Perform indirection, and merge the indirect pointer ;into the instruction register. Then go to begin again to execute the instruction. do-10-indirect (call load-10-mem) ((m-e) m-2) (jump-xct-next eff-addr-comp) ((m-3) mask-field pdp10-opcode m-3 a-1) ;Execute the instruction in M-3 with effective address in M-E ;The execution routine finds the accumulator in M-A. xct-10-insn (dispatch-xct-next pdp10-insn-class m-3 d-10-insn-class) ((m-a) pdp10-ac-field m-3) ;Dispatch on major classes of pdp-10 instructions. (locality d-mem) (start-dispatch 3 0) d-10-insn-class (xct-10-uuo) (xct-10-random) (xct-10-move) (xct-10-jump) (xct-10-logical) (xct-10-halfword) (xct-10-test) (xct-10-uuo) (end-dispatch) (locality i-mem) ;The XCT instruction. i-10-xct (call load-10-mem) ((m-3) m-1) ((m-e) m-2) (jump eff-addr-comp) i-10-lsh (call load-10-ac-t) ((m-1) dpb m-t ?? a-zero) ((m-1) dpb m-r ?? a-1) ((m-2) dpb m-t ?? a-zero) ((m-2) dpb m-r ?? a-2) (call store-10-ac-t) (jump next-10-insn) ;Arithmetic Jump and Skip Instructions xct-10-jump ;Dispatch on jump vs skip, whether to increment, etc. (dispatch pdp10-jump-subclass m-3 d-10-jump-subclass) ;;;???These are in the wrong order (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-subclass (i-10-jump) (i-10-skip) (i-10-aoj) (i-10-soj) (i-10-aos) (i-10-sos) (i-10-cai) (i-10-cam) (locality i-mem) i-10-jump (call load-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aoj (call load-10-ac) (call inc-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-soj (call load-10-ac) (call dec-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-skip (call load-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aos (call load-10-mem) (call inc-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-sos (call load-10-mem) (call dec-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-cam (call load-10-mem-t) (call load-10-ac) (call sub-10) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-cai (call load-10-ac) ((m-2) sub m-2 a-e) (jump-if-bit-clear pdp10-overflow-bit m-2 i-10-cai-1) ((m-1) sub m-1 (a-constant 1)) i-10-cai-1 ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;Jump or Skip on Sign of Internal Accumulator. ;Do it with an instruction ; (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;The I-ARG should be COND-10-JUMP to jump, COND-10-SKIP to skip. ;;;??? These are in the wrong order. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-condition (next-10-insn) ;Jump never (cond-10-equal) (cond-10-less) (cond-10-grtr) (cond-10-le) (cond-10-ge) (cond-10-ne) (cond-10-always) (end-dispatch) (locality i-mem) cond-10-le (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) cond-10-equal (jump-not-equal m-1 next-10-insn) (jump-not-equal m-2 next-10-insn) (jump cond-10-always) cond-10-grtr (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-ne (jump-not-equal m-1 cond-10-always) (jump-not-equal m-2 cond-10-always) (jump next-10-insn) cond-10-less (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) (jump next-10-insn) cond-10-ge (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-always (dispatch-xct-next read-i-arg d-10-jump-action) ((m-b) add m-b (a-constant 1)) ;The last instruction does a skip. ;If we are really jumping, it makes no difference. ;If we want to skip, we can go straight to the instruction loop. (locality d-mem) (start-dispatch 1 0) d-10-jump-action (jump-10-jump) (next-10-insn) (end-dispatch) (locality i-mem) * LMFL(DIRECTORY "RMS" NAME "PDP10" TYPE "LISP" VERSION 5 BYTE-SIZE 10 CREATION-DATE 23073453401 AUTHOR "rms") ;PDP-10 simulator microcode ;The simulator uses an internal accumulator for its arithmetic ;and most of its data transfers. ;This internal accumulator consists of M-1 and M-2. ;M-1 holds the left half of the 36-bit quantity and M-2 the right half. ;The other argument of arithmetic operations goes in ;the T register, composed of M-T and M-R. ;Instructions are executed out of the instruction register, ;which occupies M-3 and M-E. ;The AC field of the instruction is standardly placed in M-A, ;and the effective address is computed in M-E. ;The simulated PC lives in M-B; actually, that contains ;one less than the Q address of the left halfword of the next instruction. ;Jump instructions and PC saving instructions convert ;between this form of quantity and a pdp-10 address. (locality a-mem) a-10-flags (0) (modulo 2) ;So halfword instructions can choose which half! ;Address of Q containing the left half of simulated memory location 0. ;The left halves of all PDP-10 memory words live in consecutive Qs. a-10-mem-0-left-addr (0) ;Address of Q containing the right half of simulated memory location 0. ;The right halves of all PDP-10 memory words live in consecutive Qs, ;immediately following the left halves. ;Thus, this address is always 1000000 more than that in a-10-mem-0-left-addr. a-10-mem-0-right-addr (0) ;Address of left half of memory location 20, ;used for testing the PC to see whether points at an AC. a-10-mem-20-left-addr (0) ;40 here so halfword instructions can choose which half! (modulo 40) ;These are the left halves of the pdp-10's simulated accumulators. a-10-ac-0-left (0) (modulo 20) ;These are the right halves. a-10-ac-0-right (0) (modulo 20) (locality i-mem) ;Set the simulated pc from a pdp-10 format pc in M-2. set-10-pc (popj-after-next (m-b) add m-2 (a-constant -1)) ((m-b) add m-b a-10-mem-0-left-addr) ;Get the pc in pdp-10 form in M-2. get-10-pc (popj-after-next (m-2) sub m-b a-10-mem-0-leftaddr) ((m-2) m+1 m-2) ;Load and store simulated accumulators (AC number in M-A) ;from the internal accumulator and the T register. ;Store the internal accumulator into the simulated accumulator ;whose number is in M-A. store-10-ac ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated accumulator whose number is in M-A ;into the internal accumulator. load-10-ac ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the T register into the simulated accumulator ;whose number is in M-A. store-10-ac-t ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Load the simulated accumulator whose number is in M-A ;into the T register. load-10-ac-t ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Load and store main memory (address in M-E) ;from the internal accumulator and the T register. ;Load the simulated memory location whose number is in M-E ;into the internal accumulator. load-10-mem (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-1) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-ac-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the internal accumulator into the simulated memory location ;whose address is in M-E. store-10-mem (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-1) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-2) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated memory location whose number is in M-E ;into the T register. load-10-mem-t (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-t) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-r) read-memory-data) load-10-ac-t-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Store the T register into the simulated memory location ;whose address is in M-E. store-10-mem-t (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-t) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-r) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-t-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Come here to jump to effective address and execute next instruction. jump-10-jump ((m-b) add m-e a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Loop point for executing the next pdp-10 instruction. next-10-insn (jump-less-than m-b a-10-mem-20-addr xct-10-ac) ;Check for ACs referenced as memory. ((vma-start-read m-b) m+1 m-b) ;Increment pc and fetch lh of insn. (check-page-read) ((m-3) read-memory-data) ((vma-start-read) add m-b (a-constant 1000000)) (check-page-read) ((m-e) read-memory-data) ;Compute the effective address in M-E ;for the instruction in the instruction register (M-3, M-E). eff-addr-comp (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ;Fetch the next instruction from an accumulator. xct-10-ac (call get-10-pc) ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-3) a-10-ac-0-left) ((oa-reg-high) dpb m-a oah-a-src a-zero) (jump-xct-next eff-addr-comp) ((m-e) a-10-ac-0-right) (locality d-mem) (start-dispatch 5 0) d-10-index-and-indirect (xct-10-insn-1) (repeat 17 (do-10-indexing)) (do-10-indirect) (repeat 17 (do-10-indexing)) (end-dispatch) (locality i-mem) ;Perform indexing on address field in M-E ;with index register number in M-A. do-10-indexing ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-e) add m-e a-10-ac-0-right) (jump-if-bit-clear-xct-next pdp10-indirect-bit xct-10-insn) ((m-e) truncate-to-halfword m-e) ;Perform indirection, and merge the indirect pointer ;into the instruction register. Then go to begin again to execute the instruction. do-10-indirect (call load-10-mem) ((m-e) m-2) (jump-xct-next eff-addr-comp) ((m-3) mask-field pdp10-opcode m-3 a-1) ;Execute the instruction in M-3 with effective address in M-E ;The execution routine finds the accumulator in M-A. xct-10-insn (dispatch-xct-next pdp10-insn-class m-3 d-10-insn-class) ((m-a) pdp10-ac-field m-3) ;Dispatch on major classes of pdp-10 instructions. (locality d-mem) (start-dispatch 3 0) d-10-insn-class (xct-10-uuo) (xct-10-random) (xct-10-move) (xct-10-jump) (xct-10-logical) (xct-10-halfword) (xct-10-test) (xct-10-uuo) (end-dispatch) (locality i-mem) ;Do the store for an instruction like ADD ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-both (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-both) (end-dispatch) (locality i-mem) store-10-both (call store-10-mem) (jump store-10-ac) ;Do the store for an instruction like MOVE ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-self) (end-dispatch) (locality i-mem) store-10-self (call store-10-mem) (popj-equal m-a) (jump store-10-ac) ;The XCT instruction. i-10-xct (call load-10-mem) ((m-3) m-1) ((m-e) m-2) (jump eff-addr-comp) i-10-lsh (call load-10-ac-t) ((m-1) dpb m-t ?? a-zero) ((m-1) dpb m-r ?? a-1) ((m-2) dpb m-t ?? a-zero) ((m-2) dpb m-r ?? a-2) (call store-10-ac-t) (jump next-10-insn) ;Arithmetic Jump and Skip Instructions xct-10-jump ;Dispatch on jump vs skip, whether to increment, etc. (dispatch pdp10-jump-subclass m-3 d-10-jump-subclass) ;;;???These are in the wrong order (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-subclass (i-10-jump) (i-10-skip) (i-10-aoj) (i-10-soj) (i-10-aos) (i-10-sos) (i-10-cai) (i-10-cam) (locality i-mem) i-10-jump (call load-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aoj (call load-10-ac) (call inc-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-soj (call load-10-ac) (call dec-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-skip (call load-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aos (call load-10-mem) (call inc-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-sos (call load-10-mem) (call dec-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-cam (call load-10-mem-t) (call load-10-ac) (call sub-10) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-cai (call load-10-ac) ((m-2) sub m-2 a-e) (jump-if-bit-clear pdp10-overflow-bit m-2 i-10-cai-1) ((m-1) sub m-1 (a-constant 1)) i-10-cai-1 ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;Jump or Skip on Sign of Internal Accumulator. ;Do it with an instruction ; (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;The I-ARG should be COND-10-JUMP to jump, COND-10-SKIP to skip. ;;;??? These are in the wrong order. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-condition (next-10-insn) ;Jump never (cond-10-equal) (cond-10-less) (cond-10-grtr) (cond-10-le) (cond-10-ge) (cond-10-ne) (cond-10-always) (end-dispatch) (locality i-mem) cond-10-le (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) cond-10-equal (jump-not-equal m-1 next-10-insn) (jump-not-equal m-2 next-10-insn) (jump cond-10-always) cond-10-grtr (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-ne (jump-not-equal m-1 cond-10-always) (jump-not-equal m-2 cond-10-always) (jump next-10-insn) cond-10-less (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) (jump next-10-insn) cond-10-ge (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-always (dispatch-xct-next read-i-arg d-10-jump-action) ((m-b) add m-b (a-constant 1)) ;The last instruction does a skip. ;If we are really jumping, it makes no difference. ;If we want to skip, we can go straight to the instruction loop. (locality d-mem) (start-dispatch 1 0) d-10-jump-action (jump-10-jump) (next-10-insn) (end-dispatch) (locality i-mem) ;Halfword Instructions ;Subroutines ;Store M-2 in half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. store-10-ac-half (dispatch-xct-next pdp10-dest-halfword-bit m-3 d-store-10-ac-half) (popj-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) (locality d-mem) (start-dispatch 1 0) d-store-10-ac-half (store-10-ac-left) (store-10-ac-right) (end-dispatch) store-10-ac-left ((a-10-ac-0-left) m-2) store-10-ac-right ((a-10-ac-0-right) m-2) ;Load M-2 from half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. load-10-ac-half (dispatch-xct-next pdp10-src-halfword-bit m-3 d-load-10-ac-half) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) (locality d-mem) (start-dispatch 1 0) d-load-10-ac-half (load-10-ac-left) (load-10-ac-right) (end-dispatch) load-10-ac-left ((m-2) a-10-ac-0-left) load-10-ac-right ((m-2) a-10-ac-0-right) ;Store M-2 in half of the simulated memory location with address in M-E. ;Which half is controlled by the instruction register. store-10-mem-half (dispatch-xct-next pdp10-dest-halfword-bit m-3 d-store-10-mem-half) ((write-memory-data) m-2) (locality d-mem) (start-dispatch 1 0) d-store-10-mem-half (store-10-mem-left) (store-10-mem-right) (end-dispatch) store-10-mem-left ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) (popj) store-10-mem-right ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) ;Load M-2 from half of the simulated memory location whose address is in M-E. ;Which half is controlled by the instruction register. load-10-mem-half (dispatch-xct-next pdp10-src-halfword-bit m-3 d-load-10-mem-half) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d-load-10-mem-half (load-10-mem-left) (load-10-mem-right) (end-dispatch) load-10-mem-left ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-mem-right ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) ;Load M-2 from half of the immediate arg. ;Which half is controlled by the instruction register. load-10-immed-half (dispatch pdp10-src-halfword-bit m-3 d-load-10-immed-half) (locality d-mem) (start-dispatch 1 0) d-load-10-immed-half (load-10-immed-left) (load-10-immed-right) (end-dispatch) load-10-immed-left (popj (m-2) a-zero) load-10-immed-right (popj (m-2) m-e) xct-10-halfword (dispatch pdp10-operation-direction m-3 d-10-load-in-out-or-both-half) (dispatch pdp10-other-halfword-action m-3 d-other-10-halfword) ;;;??? correct sense? (jump-if-bit-clear pdp10-halfword-store-left-bit m-3 xct-10-halfword-1) ((m-c) m-1) ((m-1) m-2) ((m-2) m-c) xct-10-halfword-1 (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self) (jump next-10-insn) (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-load-in-out-or-both-half (p-bit load-10-mem-half) (p-bit load-immed-arg-half) (p-bit load-10-ac-half) (p-bit load-10-mem-half) (end-dispatch) (locality i-mem) ;Clear, set or sign-extend the "other" half, ;which right now is always in M-1. ;;;??? These are in the wrong order. (locality d-mem) (start-dispatch 2 inhibit-xct-next-bit) d-other-10-halfword (xct-10-halfword-preserve-other-half) (p-bit other-10-halfword-clear) (p-bit other-10-halfword-set) (p-bit other-10-halfword-extend) (end-dispatch) (locality i-mem) other-10-halfword-extend (jump-if-bit-set pdp10-sign-bit m-2 other-10-halfword-set) other-10-halfword-clear (popj (m-1) a-zero) other-10-halfword-set (popj (m-1) (a-constant 777777)) xct-10-halfword-preserve-other-half (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self-half) (jump next-10-insn) ;Do the store for an instruction like HRL ;which only wants to store one halfword ;and can do it in the AC, in memory or in self. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self-halfword (p-bit store-10-mem-half) (p-bit store-10-mem-half) (p-bit store-10-ac-half) (p-bit store-10-self-half) (end-dispatch) (locality i-mem) store-10-self-half (call store-10-mem-half) (popj-equal m-a) (jump store-10-ac-half) * LMFL(DIRECTORY "RMS" NAME "PDP10" TYPE "LISP" VERSION 6 BYTE-SIZE 10 CREATION-DATE 23075640617 AUTHOR "RMS") ;PDP-10 simulator microcode ;The simulator uses an internal accumulator for its arithmetic ;and most of its data transfers. ;This internal accumulator consists of M-1 and M-2. ;M-1 holds the left half of the 36-bit quantity and M-2 the right half. ;The other argument of arithmetic operations goes in ;the T register, composed of M-T and M-R. ;Instructions are executed out of the instruction register, ;which occupies M-3 and M-E. ;The AC field of the instruction is standardly placed in M-A, ;and the effective address is computed in M-E. ;The simulated PC lives in M-B; actually, that contains ;one less than the Q address of the left halfword of the next instruction. ;Jump instructions and PC saving instructions convert ;between this form of quantity and a pdp-10 address. (locality a-mem) a-10-flags (0) (modulo 2) ;So halfword instructions can choose which half! ;Address of Q containing the left half of simulated memory location 0. ;The left halves of all PDP-10 memory words live in consecutive Qs. a-10-mem-0-left-addr (0) ;Address of Q containing the right half of simulated memory location 0. ;The right halves of all PDP-10 memory words live in consecutive Qs, ;immediately following the left halves. ;Thus, this address is always 1000000 more than that in a-10-mem-0-left-addr. a-10-mem-0-right-addr (0) ;Address of left half of memory location 20, ;used for testing the PC to see whether points at an AC. a-10-mem-20-left-addr (0) ;40 here so halfword instructions can choose which half! (modulo 40) ;These are the left halves of the pdp-10's simulated accumulators. a-10-ac-0-left (0) (modulo 20) ;These are the right halves. a-10-ac-0-right (0) (modulo 20) (locality i-mem) ;Set the simulated pc from a pdp-10 format pc in M-2. set-10-pc (popj-after-next (m-b) add m-2 (a-constant -1)) ((m-b) add m-b a-10-mem-0-left-addr) ;Get the pc in pdp-10 form in M-2. get-10-pc (popj-after-next (m-2) sub m-b a-10-mem-0-leftaddr) ((m-2) m+1 m-2) ;Load and store simulated accumulators (AC number in M-A) ;from the internal accumulator and the T register. ;Store the internal accumulator into the simulated accumulator ;whose number is in M-A. store-10-ac ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated accumulator whose number is in M-A ;into the internal accumulator. load-10-ac ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the T register into the simulated accumulator ;whose number is in M-A. store-10-ac-t ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Load the simulated accumulator whose number is in M-A ;into the T register. load-10-ac-t ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Load and store main memory (address in M-E) ;from the internal accumulator and the T register. ;Load the simulated memory location whose number is in M-E ;into the internal accumulator. load-10-mem (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-1) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-ac-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the internal accumulator into the simulated memory location ;whose address is in M-E. store-10-mem (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-1) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-2) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated memory location whose number is in M-E ;into the T register. load-10-mem-t (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-t) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-r) read-memory-data) load-10-ac-t-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Store the T register into the simulated memory location ;whose address is in M-E. store-10-mem-t (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-t) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-r) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-t-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Come here to jump to effective address and execute next instruction. jump-10-jump ((m-b) add m-e a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Loop point for executing the next pdp-10 instruction. next-10-insn (jump-less-than m-b a-10-mem-20-addr xct-10-ac) ;Check for ACs referenced as memory. ((vma-start-read m-b) m+1 m-b) ;Increment pc and fetch lh of insn. (check-page-read) ((m-3) read-memory-data) ((vma-start-read) add m-b (a-constant 1000000)) (check-page-read) ((m-e) read-memory-data) ;Compute the effective address in M-E ;for the instruction in the instruction register (M-3, M-E). eff-addr-comp (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ;Fetch the next instruction from an accumulator. xct-10-ac (call get-10-pc) ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-3) a-10-ac-0-left) ((oa-reg-high) dpb m-a oah-a-src a-zero) (jump-xct-next eff-addr-comp) ((m-e) a-10-ac-0-right) (locality d-mem) (start-dispatch 5 0) d-10-index-and-indirect (xct-10-insn-1) (repeat 17 (do-10-indexing)) (do-10-indirect) (repeat 17 (do-10-indexing)) (end-dispatch) (locality i-mem) ;Perform indexing on address field in M-E ;with index register number in M-A. do-10-indexing ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-e) add m-e a-10-ac-0-right) (jump-if-bit-clear-xct-next pdp10-indirect-bit xct-10-insn) ((m-e) truncate-to-halfword m-e) ;Perform indirection, and merge the indirect pointer ;into the instruction register. Then go to begin again to execute the instruction. do-10-indirect (call load-10-mem) ((m-e) m-2) (jump-xct-next eff-addr-comp) ((m-3) mask-field pdp10-opcode m-3 a-1) ;Execute the instruction in M-3 with effective address in M-E ;The execution routine finds the accumulator in M-A. xct-10-insn (dispatch-xct-next pdp10-insn-class m-3 d-10-insn-class) ((m-a) pdp10-ac-field m-3) ;Dispatch on major classes of pdp-10 instructions. (locality d-mem) (start-dispatch 3 0) d-10-insn-class (xct-10-uuo) (xct-10-random) (xct-10-move) (xct-10-jump) (xct-10-logical) (xct-10-halfword) (xct-10-test) (xct-10-uuo) (end-dispatch) (locality i-mem) ;Do the store for an instruction like ADD ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-both (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-both) (end-dispatch) (locality i-mem) store-10-both (call store-10-mem) (jump store-10-ac) ;Do the store for an instruction like MOVE ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-self) (end-dispatch) (locality i-mem) store-10-self (call store-10-mem) (popj-equal m-a) (jump store-10-ac) ;The XCT instruction. i-10-xct (call load-10-mem) ((m-3) m-1) ((m-e) m-2) (jump eff-addr-comp) i-10-lsh (call load-10-ac-t) ((m-1) dpb m-t ?? a-zero) ((m-1) dpb m-r ?? a-1) ((m-2) dpb m-t ?? a-zero) ((m-2) dpb m-r ?? a-2) (call store-10-ac-t) (jump next-10-insn) ;Arithmetic Jump and Skip Instructions xct-10-jump ;Dispatch on jump vs skip, whether to increment, etc. (dispatch pdp10-jump-subclass m-3 d-10-jump-subclass) ;PDP10-JUMP-SUBCLASS should be bits 70 of the opcode. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-subclass (i-10-cai) (i-10-cam) (i-10-jump) (i-10-skip) (i-10-aoj) (i-10-aos) (i-10-soj) (i-10-sos) (locality i-mem) i-10-cam (call load-10-mem-t) (call load-10-ac) (call sub-10-no-flags) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-cai (call load-10-ac) ((m-2) sub m-2 a-e) (jump-if-bit-clear pdp10-carry-0-bit m-2 i-10-cai-1) ((m-1) sub m-1 (a-constant 1)) i-10-cai-1 ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-jump (call load-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-skip (call load-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aoj (call load-10-ac) (call inc-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aos (call load-10-mem) (call inc-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-soj (call load-10-ac) (call dec-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-sos (call load-10-mem) (call dec-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;Jump or Skip on Sign of Internal Accumulator. ;Do it with an instruction ; (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;The I-ARG should be COND-10-JUMP to jump, COND-10-SKIP to skip. ;PDP10-JUMP-CONDITION should be bits 7 of the opcode. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-condition (next-10-insn) ;Jump never (cond-10-less) (cond-10-equal) (cond-10-le) (cond-10-always) (cond-10-ge) (cond-10-ne) (cond-10-grtr) (end-dispatch) (locality i-mem) cond-10-le (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) cond-10-equal (jump-not-equal m-1 next-10-insn) (jump-not-equal m-2 next-10-insn) (jump cond-10-always) cond-10-grtr (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-ne (jump-not-equal m-1 cond-10-always) (jump-not-equal m-2 cond-10-always) (jump next-10-insn) cond-10-less (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) (jump next-10-insn) cond-10-ge (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-always (dispatch-xct-next read-i-arg d-10-jump-action) ((m-b) add m-b (a-constant 1)) ;The last instruction does a skip. ;If we are really jumping, it makes no difference. ;If we want to skip, we can go straight to the instruction loop. (locality d-mem) (start-dispatch 1 0) d-10-jump-action (jump-10-jump) (next-10-insn) (end-dispatch) (locality i-mem) ;Halfword Instructions ;PDP10-HALFWORD-FETCH-RIGHT-BIT should be the 4 bit of the opcode. ;PDP10-HALFWORD-STORE-RIGHT-BIT should be the 40 bit of the opcode. ;Subroutines ;Store M-2 in half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. store-10-ac-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-ac-half) (popj-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) (locality d-mem) (start-dispatch 1 0) d-store-10-ac-half (store-10-ac-left) (store-10-ac-right) (end-dispatch) store-10-ac-left ((a-10-ac-0-left) m-2) store-10-ac-right ((a-10-ac-0-right) m-2) ;Load M-2 from half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. load-10-ac-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-ac-half) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) (locality d-mem) (start-dispatch 1 0) d-load-10-ac-half (load-10-ac-left) (load-10-ac-right) (end-dispatki „„mfid$90$ik$mmft„€))d$2 i$90$ik$0$mmft „„mfid$90$ik$r`oit„€))d$2 i$90$ik$0$r`oit „„2[tfrm D$2 `o iimf ff tim {`d}mitmd dmdfrp mfkit`fo `ti iddrm{{ `o D$M/„2_i`ki iimf `{ kfotrfmmmd bp tim `o{tr}kt`fo rmo`{tmr/„{tfrm$90$dmd$iimf„€)d`{pitki$ykt$omyt pdp90$iimffrd${tfrm$r`oit$b`t d$; d${tfrm$90$dmd$iimf „ ))r`tm$dmdfrp$diti d$2 „„)mfkim`tp d$dmd „){tirt$d`{pitki 9 0 „d${tfrm$90$dmd$iimf„€){tfrm$90$dmd$mmft „€){tfrm$90$dmd$r`oit „)mod$d`{pitki „„{tfrm$90$dmd$mmft„€))vdi${tirt$r`tm idd d$m i$90$dmd$0$mmft$iddr „€)kimkb$piom$r`tm „€)pfpk „„{tfrm$90$dmd$r`oit„€))vdi${tirt$r`tm idd d$m i$90$dmd$0$r`oit$iddr „€)kimkb$piom$r`tm „€)pfpk „„2Mfid D$2 frfd iimf ff tim {`d}mitmd dmdfrp mfkit`fo if{m iddrm{{ `{ `o D$M/„2_i`ki iimf `{ kfotrfmmmd bp tim `o{tr}kt`fo rmo`{tmr/„mfid$90$dmd$iimf„€)d`{pitki$ykt$omyt pdp90$iimffrd$fmtki$r`oit$b`t d$; d$mfid$90$dmd$iimf „„)mfkim`tp d$dmd „){tirt$d`{pitki 9 `oi`b`t$ykt$omyt$b`t „d$mfid$90$dmd$iimf„€)mfid$90$dmd$mmft „€)mfid$90$dmd$r`oit „)mod$d`{pitki „„mfid$90$dmd$mmft„€))vdi${tirt$rmid idd d$m i$90$dmd$0$mmft$iddr „€)kimkb$piom$rmid „€)pfpk )d$2 rmid$dmdfrp$diti „„mfid$90$dmd$r`oit„€))vdi${tirt$rmid idd d$m i$90$dmd$0$r`oit$iddr „€)kimkb$piom$rmid „€)pfpk )d$2 rmid$dmdfrp$diti „„2Mfid D$2 frfd iimf ff tim `ddmd`itm iro/„2_i`ki iimf `{ kfotrfmmmd bp tim `o{tr}kt`fo rmo`{tmr/„mfid$90$`ddmd$iimf„€)d`{pitki pdp90$iimffrd$fmtki$r`oit$b`t d$; d$mfid$90$`ddmd$iimf „„)mfkim`tp d$dmd „){tirt$d`{pitki 9 0 „d$mfid$90$`ddmd$iimf„€)mfid$90$`ddmd$mmft „€)mfid$90$`ddmd$r`oit „)mod$d`{pitki „„mfid$90$`ddmd$mmft„€)pfpk )d$2 i${mrf „„mfid$90$`ddmd$r`oit„€)pfpk )d$2 d$m „ „2PDP90$FPMRIT@FO$D@RMKT@FO {if}md bm tim mf 2 b`t{ ff tim fpkfdm/„2PDP90$FTIMR$IIMF_FRD$IKT@FO {if}md bm tim ;0 b`t{ ff tim fpkfdm/„2PDP90$IIMF_FRD$[TFRM$R@OIT$B@T {if}md bm tim 40 b`t ff tim fpkfdm/„ykt$90$iimffrd„€)d`{pitki pdp90$fpmrit`fo$d`rmkt`fo d$; d$90$mfid$`o$f}t$fr$bfti$iimf „€)d`{pitki pdp90$ftimr$iimffrd$ikt`fo d$; d$ftimr$90$iimffrd „€)k}dp$`f$b`t${mt pdp90$iimffrd${tfrm$r`oit$b`t d$; ykt$90$iimffrd$9 „€))d$k d$9 „€))d$9 d$2 „€))d$2 d$k „ykt$90$iimffrd$9„€)d`{pitki pdp90$fpmrit`fo$d`rmkt`fo d$; d$90${tfrm$`o$f}t$fr${mmf „€)k}dp omyt$90$`o{o „„)mfkim`tp d$dmd „){tirt$d`{pitki ; `oi`b`t$ykt$omyt$b`t „d$90$mfid$`o$f}t$fr$bfti$iimf„€)p$b`t mfid$90$dmd$iimf „€)p$b`t mfid$`ddmd$iro$iimf „€)p$b`t mfid$90$ik$iimf „€)p$b`t mfid$90$dmd$iimf „)mod$d`{pitki „)mfkim`tp `$dmd „„2Kmmir- {mt fr {`oo$mytmod tim "ftimr" iimf-„2i`ki r`oit of `{ imip{ `o D$9/„)mfkim`tp d$dmd „){tirt$d`{pitki 2 `oi`b`t$ykt$omyt$b`t „d$ftimr$90$iimffrd„€)ykt$90$iimffrd$prm{mrvm$ftimr$iimf „€)p$b`t ftimr$90$iimffrd$kmmir „€)p$b`t ftimr$90$iimffrd${mt „€)p$b`t ftimr$90$iimffrd$mytmod „)mod$d`{pitki „)mfkim`tp `$dmd „„ftimr$90$iimffrd$mytmod„€)k}dp$`f$b`t${mt pdp90${`oo$b`t d$2 ftimr$90$iimffrd${mt „ftimr$90$iimffrd$kmmir„€)pfpk )d$9 i${mrf „„ftimr$90$iimffrd${mt„€)pfpk )d$9 )i$kfo{tiot ?????? „„ykt$90$iimffrd$prm{mrvm$ftimr$iimf„€)d`{pitki pdp90$fpmrit`fo$d`rmkt`fo d$; d$90${tfrm$`o$f}t$fr${mmf$iimf „€)k}dp omyt$90$`o{o „„2Df tim {tfrm ffr io `o{tr}kt`fo m`bm IRM„2i`ki fomp iot{ tf {tfrm fom iimffrd„2iod kio df `t `o tim IK- `o dmdfrp fr `o {mmf/„)mfkim`tp d$dmd „){tirt$d`{pitki ; `oi`b`t$ykt$omyt$b`t „d$90${tfrm$`o$f}t$fr${mmf$iimffrd„€)p$b`t {tfrm$90$ik$iimf „€)p$b`t {tfrm$90$ik$iimf „€)p$b`t {tfrm$90$dmd$iimf „€)p$b`t {tfrm$90${mmf$iimf „)mod$d`{pitki „)mfkim`tp `$dmd „„{tfrm$90${mmf$iimf„€)kimm {tfrm$90$dmd$iimf „€)pfpk$my}im d$i „€)kump store-10-ac-half) ;Simple arithmetic subroutines. sub-10-no-flags ((m-1) sub m-1 m-t) ((m-2) sub m-2 m-r) (jump-if-bit-clear pdp10-carry-0-bit m-2 sub-10-a) ((m-1) sub m-1 (a-constant 1)) sub-10-a (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) inc-10 ((m-2) add m-2 (a-constant 1)) (jump-if-bit-set pdp10-carry-0-bit m-2 inc-10-a) ((m-1) add m-1 (a-constant 1)) inc-10-a ;;;??? Needs to compute and save carry 0, carry 1 and overflow flags. (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) dec-10 ((m-2) sub m-2 (a-constant 1)) (jump-if-bit-clear pdp10-carry-0-bit m-2 inc-10-a) ((m-1) add m-1 (a-constant 1)) dec-10-a ;;;??? Needs to compute and save carry 0, carry 1 and overflow flags. (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) ;TRNN, etc. xct-10-test ;Fetch the test mask from effective address or memory. (dispatch pdp10-test-source-bit m-3 d-10-test-source) ;Swap the test mask's halves if appropriate. (jump-if-bit-clear-xct-next pdp10-test-swapped-bit m-3 xct-10-test-1) ((m-1) m-t) ((m-t) m-r) ((m-r) m-1) xct-10-test-1 ;Fetch the AC to be tested. (call load-10-ac) ;Are any masked bits nonzero? ((m-i) and m-1 a-t) ((m-j) and m-2 a-r) (dispatch-xct-next pdp10-test-condition m-3 d-10-test-condition) ((m-i) ior m-i a-j) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d-10-test-source (p-bit xct-10-test-immed) (p-bit load-10-mem-t) (end-dispatch) (locality i-mem) xct-10-test-immed (popj-after-next (m-r) m-e) ((m-t) a-zero) (locality d-mem) (start-dispatch 2 0) d-10-test-condition (xct-10-test-2) ;Do not skip. (xct-10-test-skip-if-0) (xct-10-test-skip-always) (xct-10-test-skip-not-0) (end-dispatch) (locality i-mem) xct-10-test-skip-not-0 (jump-xct-next xct-10-test-skip-always) (popj-equal m-i a-zero) ;;;??? Will that work? xct-10-test-skip-if-0 (popj-not-equal m-i a-zero) xct-10-test-skip-always (popj (m-b) add m-b (a-constant 1)) * LMFL(DIRECTORY "RMS" NAME "PDP10" TYPE "LISP" VERSION 7 BYTE-SIZE 10 CREATION-DATE 23075640617 AUTHOR "RMS") ;PDP-10 simulator microcode ;The simulator uses an internal accumulator for its arithmetic ;and most of its data transfers. ;This internal accumulator consists of M-1 and M-2. ;M-1 holds the left half of the 36-bit quantity and M-2 the right half. ;The other argument of arithmetic operations goes in ;the T register, composed of M-T and M-R. ;Instructions are executed out of the instruction register, ;which occupies M-3 and M-E. ;The AC field of the instruction is standardly placed in M-A, ;and the effective address is computed in M-E. ;The simulated PC lives in M-B; actually, that contains ;one less than the Q address of the left halfword of the next instruction. ;Jump instructions and PC saving instructions convert ;between this form of quantity and a pdp-10 address. (locality a-mem) a-10-flags (0) (modulo 2) ;So halfword instructions can choose which half! ;Address of Q containing the left half of simulated memory location 0. ;The left halves of all PDP-10 memory words live in consecutive Qs. a-10-mem-0-left-addr (0) ;Address of Q containing the right half of simulated memory location 0. ;The right halves of all PDP-10 memory words live in consecutive Qs, ;immediately following the left halves. ;Thus, this address is always 1000000 more than that in a-10-mem-0-left-addr. a-10-mem-0-right-addr (0) ;Address of left half of memory location 20, ;used for testing the PC to see whether points at an AC. a-10-mem-20-left-addr (0) ;40 here so halfword instructions can choose which half! (modulo 40) ;These are the left halves of the pdp-10's simulated accumulators. a-10-ac-0-left (0) (modulo 20) ;These are the right halves. a-10-ac-0-right (0) (modulo 20) (locality i-mem) ;Set the simulated pc from a pdp-10 format pc in M-2. set-10-pc (popj-after-next (m-b) add m-2 (a-constant -1)) ((m-b) add m-b a-10-mem-0-left-addr) ;Get the pc in pdp-10 form in M-2. get-10-pc (popj-after-next (m-2) sub m-b a-10-mem-0-leftaddr) ((m-2) m+1 m-2) ;Load and store simulated accumulators (AC number in M-A) ;from the internal accumulator and the T register. ;Store the internal accumulator into the simulated accumulator ;whose number is in M-A. store-10-ac ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated accumulator whose number is in M-A ;into the internal accumulator. load-10-ac ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the T register into the simulated accumulator ;whose number is in M-A. store-10-ac-t ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Load the simulated accumulator whose number is in M-A ;into the T register. load-10-ac-t ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Load and store main memory (address in M-E) ;from the internal accumulator and the T register. ;Load the simulated memory location whose number is in M-E ;into the internal accumulator. load-10-mem (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-1) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-ac-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the internal accumulator into the simulated memory location ;whose address is in M-E. store-10-mem (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-1) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-2) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated memory location whose number is in M-E ;into the T register. load-10-mem-t (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-t) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-r) read-memory-data) load-10-ac-t-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Store the T register into the simulated memory location ;whose address is in M-E. store-10-mem-t (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-t) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-r) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-t-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Come here to jump to effective address and execute next instruction. jump-10-jump ((m-b) add m-e a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Loop point for executing the next pdp-10 instruction. next-10-insn (jump-less-than m-b a-10-mem-20-addr xct-10-ac) ;Check for ACs referenced as memory. ((vma-start-read m-b) m+1 m-b) ;Increment pc and fetch lh of insn. (check-page-read) ((m-3) read-memory-data) ((vma-start-read) add m-b (a-constant 1000000)) (check-page-read) ((m-e) read-memory-data) ;Compute the effective address in M-E ;for the instruction in the instruction register (M-3, M-E). eff-addr-comp (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ;Fetch the next instruction from an accumulator. xct-10-ac (call get-10-pc) ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-3) a-10-ac-0-left) ((oa-reg-high) dpb m-a oah-a-src a-zero) (jump-xct-next eff-addr-comp) ((m-e) a-10-ac-0-right) (locality d-mem) (start-dispatch 5 0) d-10-index-and-indirect (xct-10-insn-1) (repeat 17 (do-10-indexing)) (do-10-indirect) (repeat 17 (do-10-indexing)) (end-dispatch) (locality i-mem) ;Perform indexing on address field in M-E ;with index register number in M-A. do-10-indexing ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-e) add m-e a-10-ac-0-right) (jump-if-bit-clear-xct-next pdp10-indirect-bit xct-10-insn) ((m-e) truncate-to-halfword m-e) ;Perform indirection, and merge the indirect pointer ;into the instruction register. Then go to begin again to execute the instruction. do-10-indirect (call load-10-mem) ((m-e) m-2) (jump-xct-next eff-addr-comp) ((m-3) mask-field pdp10-opcode m-3 a-1) ;Execute the instruction in M-3 with effective address in M-E ;The execution routine finds the accumulator in M-A. xct-10-insn (dispatch-xct-next pdp10-insn-class m-3 d-10-insn-class) ((m-a) pdp10-ac-field m-3) ;Dispatch on major classes of pdp-10 instructions. (locality d-mem) (start-dispatch 3 0) d-10-insn-class (xct-10-uuo) (xct-10-random) (xct-10-move) (xct-10-jump) (xct-10-logical) (xct-10-halfword) (xct-10-test) (xct-10-uuo) (end-dispatch) (locality i-mem) ;Do the store for an instruction like ADD ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-both (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-both) (end-dispatch) (locality i-mem) store-10-both (call store-10-mem) (jump store-10-ac) ;Do the store for an instruction like MOVE ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-self) (end-dispatch) (locality i-mem) store-10-self (call store-10-mem) (popj-equal m-a) (jump store-10-ac) ;The XCT instruction. i-10-xct (call load-10-mem) ((m-3) m-1) ((m-e) m-2) (jump eff-addr-comp) i-10-lsh (call load-10-ac-t) ((m-1) dpb m-t ?? a-zero) ((m-1) dpb m-r ?? a-1) ((m-2) dpb m-t ?? a-zero) ((m-2) dpb m-r ?? a-2) (call store-10-ac-t) (jump next-10-insn) ;Arithmetic Jump and Skip Instructions xct-10-jump ;Dispatch on jump vs skip, whether to increment, etc. (dispatch pdp10-jump-subclass m-3 d-10-jump-subclass) ;PDP10-JUMP-SUBCLASS should be bits 70 of the opcode. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-subclass (i-10-cai) (i-10-cam) (i-10-jump) (i-10-skip) (i-10-aoj) (i-10-aos) (i-10-soj) (i-10-sos) (locality i-mem) i-10-cam (call load-10-mem-t) (call load-10-ac) (call sub-10-no-flags) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-cai (call load-10-ac) ((m-2) sub m-2 a-e) (jump-if-bit-clear pdp10-carry-0-bit m-2 i-10-cai-1) ((m-1) sub m-1 (a-constant 1)) i-10-cai-1 ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-jump (call load-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-skip (call load-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aoj (call load-10-ac) (call inc-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aos (call load-10-mem) (call inc-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-soj (call load-10-ac) (call dec-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-sos (call load-10-mem) (call dec-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;Jump or Skip on Sign of Internal Accumulator. ;Do it with an instruction ; (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;The I-ARG should be COND-10-JUMP to jump, COND-10-SKIP to skip. ;PDP10-JUMP-CONDITION should be bits 7 of the opcode. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-condition (next-10-insn) ;Jump never (cond-10-less) (cond-10-equal) (cond-10-le) (cond-10-always) (cond-10-ge) (cond-10-ne) (cond-10-grtr) (end-dispatch) (locality i-mem) cond-10-le (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) cond-10-equal (jump-not-equal m-1 next-10-insn) (jump-not-equal m-2 next-10-insn) (jump cond-10-always) cond-10-grtr (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-ne (jump-not-equal m-1 cond-10-always) (jump-not-equal m-2 cond-10-always) (jump next-10-insn) cond-10-less (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) (jump next-10-insn) cond-10-ge (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-always (dispatch-xct-next read-i-arg d-10-jump-action) ((m-b) add m-b (a-constant 1)) ;The last instruction does a skip. ;If we are really jumping, it makes no difference. ;If we want to skip, we can go straight to the instruction loop. (locality d-mem) (start-dispatch 1 0) d-10-jump-action (jump-10-jump) (next-10-insn) (end-dispatch) (locality i-mem) ;Halfword Instructions ;PDP10-HALFWORD-FETCH-RIGHT-BIT should be the 4 bit of the opcode. ;PDP10-HALFWORD-STORE-RIGHT-BIT should be the 40 bit of the opcode. ;Subroutines ;Store M-2 in half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. store-10-ac-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-ac-half) (popj-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) (locality d-mem) (start-dispatch 1 0) d-store-10-ac-half (store-10-ac-left) (store-10-ac-right) (end-dispatch) store-10-ac-left ((a-10-ac-0-left) m-2) store-10-ac-right ((a-10-ac-0-right) m-2) ;Load M-2 from half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. load-10-ac-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-ac-half) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) (locality d-mem) (start-dispatch 1 0) d-load-10-ac-half (load-10-ac-left) (load-10-ac-right) (end-dispatch) load-10-ac-left ((m-2) a-10-ac-0-left) load-10-ac-right ((m-2) a-10-ac-0-right) ;Store M-2 in half of the simulated memory location with address in M-E. ;Which half is controlled by the instruction register. store-10-mem-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-mem-half) ((write-memory-data) m-2) (locality d-mem) (start-dispatch 1 0) d-store-10-mem-half (store-10-mem-left) (store-10-mem-right) (end-dispatch) store-10-mem-left ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) (popj) store-10-mem-right ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) ;Load M-2 from half of the simulated memory location whose address is in M-E. ;Which half is controlled by the instruction register. load-10-mem-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-mem-half) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d-load-10-mem-half (load-10-mem-left) (load-10-mem-right) (end-dispatch) load-10-mem-left ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-mem-right ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) ;Load M-2 from half of the immediate arg. ;Which half is controlled by the instruction register. load-10-immed-half (dispatch pdp10-halfword-fetch-right-bit m-3 d-load-10-immed-half) (locality d-mem) (start-dispatch 1 0) d-load-10-immed-half (load-10-immed-left) (load-10-immed-right) (end-dispatch) load-10-immed-left (popj (m-2) a-zero) load-10-immed-right (popj (m-2) m-e) ;PDP10-OPERATION-DIRECTION should be the low 2 bits of the opcode. ;PDP10-OTHER-HALFWORD-ACTION should be the 30 bits of the opcode. ;PDP10-HALFWORD-STORE-RIGHT-BIT should be the 40 bit of the opcode. xct-10-halfword (dispatch pdp10-operation-direction m-3 d-10-load-in-out-or-both-half) (dispatch pdp10-other-halfword-action m-3 d-other-10-halfword) (jump-if-bit-set pdp10-halfword-store-right-bit m-3 xct-10-halfword-1) ((m-c) m-1) ((m-1) m-2) ((m-2) m-c) xct-10-halfword-1 (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self) (jump next-10-insn) (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-load-in-out-or-both-half (p-bit load-10-mem-half) (p-bit load-immed-arg-half) (p-bit load-10-ac-half) (p-bit load-10-mem-half) (end-dispatch) (locality i-mem) ;Clear, set or sign-extend the "other" half, ;which right now is always in M-1. (locality d-mem) (start-dispatch 2 inhibit-xct-next-bit) d-other-10-halfword (xct-10-halfword-preserve-other-half) (p-bit other-10-halfword-clear) (p-bit other-10-halfword-set) (p-bit other-10-halfword-extend) (end-dispatch) (locality i-mem) other-10-halfword-extend (jump-if-bit-set pdp10-sign-bit m-2 other-10-halfword-set) other-10-halfword-clear (popj (m-1) a-zero) other-10-halfword-set (popj (m-1) (a-constant 777777)) xct-10-halfword-preserve-other-half (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self-half) (jump next-10-insn) ;Do the store for an instruction like HRL ;which only wants to store one halfword ;and can do it in the AC, in memory or in self. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self-halfword (p-bit store-10-ac-half) (p-bit store-10-ac-half) (p-bit store-10-mem-half) (p-bit store-10-self-half) (end-dispatch) (locality i-mem) store-10-self-half (call store-10-mem-half) (popj-equal m-a) (jump store-10-ac-half) ;Simple arithmetic subroutines. sub-10-no-flags ((m-1) sub m-1 m-t) ((m-2) sub m-2 m-r) (jump-if-bit-clear pdp10-carry-0-bit m-2 sub-10-a) ((m-1) sub m-1 (a-constant 1)) sub-10-a (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) inc-10 ((m-2) add m-2 (a-constant 1)) (jump-if-bit-set pdp10-carry-0-bit m-2 inc-10-a) ((m-1) add m-1 (a-constant 1)) inc-10-a ;;;??? Needs to compute and save carry 0, carry 1 and overflow flags. (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) dec-10 ((m-2) sub m-2 (a-constant 1)) (jump-if-bit-clear pdp10-carry-0-bit m-2 inc-10-a) ((m-1) add m-1 (a-constant 1)) dec-10-a ;;;??? Needs to compute and save carry 0, carry 1 and overflow flags. (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) ;TRNN, etc. ;PDP10-TEST-MODIFICATION should be the 60 bits of the opcode. ;PDP10-TEST-SOURCE-BIT should be bit 10 of the opcode. ;PDP10-TEST-SWAPPED-BIT should be bit 1 of the opcode. ;PDP10-TEST-CONDITION should be bits 6 of the opcode. xct-10-test ;Fetch the test mask from effective address or memory. (dispatch pdp10-test-source-bit m-3 d-10-test-source) ;Swap the test mask's halves if appropriate. (jump-if-bit-clear-xct-next pdp10-test-swapped-bit m-3 xct-10-test-1) ((m-1) m-t) ((m-t) m-r) ((m-r) m-1) xct-10-test-1 ;Fetch the AC to be tested. (call load-10-ac) ;Are any masked bits nonzero? ((m-i) and m-1 a-t) ((m-j) and m-2 a-r) (dispatch-xct-next pdp10-test-condition m-3 d-10-test-condition) ((m-i) ior m-i a-j) ;Maybe store new contents in AC. (dispatch pdp10-test-modification m-3 d-10-test-modification) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d-10-test-source (p-bit xct-10-test-immed) (p-bit load-10-mem-t) (end-dispatch) (locality i-mem) xct-10-test-immed (popj-after-next (m-r) m-e) ((m-t) a-zero) ;Decide whether to skip, and maybe do so. ;Called with (dispatch-xct-next pdp10-test-condition m-3 d-10-test-condition) ;The thing to test is whether M-I is nonzero. (locality d-mem) (start-dispatch 2 0) d-10-test-condition (xct-10-test-2) ;Do not skip. (p-bit xct-10-test-skip-if-0) (p-bit xct-10-test-skip-always) (p-bit xct-10-test-skip-not-0) (end-dispatch) (locality i-mem) xct-10-test-skip-not-0 (jump-xct-next xct-10-test-skip-always) (popj-equal m-i a-zero) ;;;??? Will that work? xct-10-test-skip-if-0 (popj-not-equal m-i a-zero) xct-10-test-skip-always (popj (m-b) add m-b (a-constant 1)) ;Compute and store the new contents of the accumulator. ;Called by (dispatch pdp10-test-modification m-3 d-10-test-modification) (locality d-mem) (start-dispatch 2 inhibit-xct-next-bit) d-10-test-modification (next-10-insn) (xct-10-test-set-zero) (xct-10-test-complement) (xct-10-test-set-one) (end-dispatch) (locality i-mem) xct-10-test-set-zero ((m-1) andca m-1 a-t) ((m-2) andca m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) xct-10-test-complement ((m-1) xor m-1 a-t) ((m-2) xor m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) xct-10-test-set-one ((m-1) ior m-1 a-t) ((m-2) ior m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) * LMFL(DIRECTORY "RMS" NAME "PDP10" TYPE "LISP" VERSION 10 BYTE-SIZE 10 CREATION-DATE 23075640622 AUTHOR "RMS") ;PDP-10 simulator microcode ;The simulator uses an internal accumulator for its arithmetic ;and most of its data transfers. ;This internal accumulator consists of M-1 and M-2. ;M-1 holds the left half of the 36-bit quantity and M-2 the right half. ;The other argument of arithmetic operations goes in ;the T register, composed of M-T and M-R. ;Instructions are executed out of the instruction register, ;which occupies M-3 and M-E. ;The AC field of the instruction is standardly placed in M-A, ;and the effective address is computed in M-E. ;The simulated PC lives in M-B; actually, that contains ;one less than the Q address of the left halfword of the next instruction. ;Jump instructions and PC saving instructions convert ;between this form of quantity and a pdp-10 address. ;The simulated PDP10 flags, except for CARRY 0, CARRY 1 and OVERFLOW, ;are kept in A-10-FLAGS. The flags can be used to help decode ;the reason why the microcode simulator exited. ;For example, the pdl overflow flag may be set. (locality a-mem) a-10-flags (0) (modulo 2) ;So halfword instructions can choose which half! ;Address of Q containing the left half of simulated memory location 0. ;The left halves of all PDP-10 memory words live in consecutive Qs. a-10-mem-0-left-addr (0) ;Address of Q containing the right half of simulated memory location 0. ;The right halves of all PDP-10 memory words live in consecutive Qs, ;immediately following the left halves. ;Thus, this address is always 1000000 more than that in a-10-mem-0-left-addr. a-10-mem-0-right-addr (0) ;Address of left half of memory location 20, ;used for testing the PC to see whether points at an AC. a-10-mem-20-left-addr (0) ;40 here so halfword instructions can choose which half! (modulo 40) ;These are the left halves of the pdp-10's simulated accumulators. a-10-ac-0-left (0) (modulo 20) ;These are the right halves. a-10-ac-0-right (0) (modulo 20) (locality i-mem) ;Load and store simulated accumulators (AC number in M-A) ;from the internal accumulator and the T register. ;Store the internal accumulator into the simulated accumulator ;whose number is in M-A. store-10-ac ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated accumulator whose number is in M-A ;into the internal accumulator. load-10-ac ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the T register into the simulated accumulator ;whose number is in M-A. store-10-ac-t ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Load the simulated accumulator whose number is in M-A ;into the T register. load-10-ac-t ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Load and store main memory (address in M-E) ;from the internal accumulator and the T register. ;Load the simulated memory location whose number is in M-E ;into the internal accumulator. load-10-mem (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-1) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-ac-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the internal accumulator into the simulated memory location ;whose address is in M-E. store-10-mem (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-1) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-2) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated memory location whose number is in M-E ;into the T register. load-10-mem-t (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-t) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-r) read-memory-data) load-10-ac-t-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Store the T register into the simulated memory location ;whose address is in M-E. store-10-mem-t (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-t) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-r) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-t-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Entry and exit. ;Call with (%pdp10-simulator
) ;It returns two values on the stack: the new pc and the new flags. enter-10-simulator (misc-inst-entry %pdp10-simulator) ((a-10-mem-0-left-addr) c-pdl-buffer-pointer-pop) ((a-10-flags) c-pdl-buffer-pointer-pop) ((m-e) c-pdl-buffer-pointer-pop) (jump jump-10-jump) ;Jump to the PC now in M-E. exit-10-simulator (call get-10-pc-and-flags-t) ;Get flags in M-T, pc in M-R. ((c-pdl-buffer-pointer-push) m-r) (popj) ;return flags to misc insn destination (push). pdl-10-overflow ((m-1) (a-constant pdp10-pdl-overflow-flag)) ((a-10-flags) ior m-1 a-10-flags) (jump exit-10-simulator) ;Set the simulated pc from a pdp-10 format pc in M-2. set-10-pc (popj-after-next (m-b) add m-2 (a-constant -1)) ((m-b) add m-b a-10-mem-0-left-addr) ;Get the pc and flags in internal accumulator (m-1 and m-2) get-10-pc-and-flags ;;;??? ;Get the pc in pdp-10 form in M-2. get-10-pc (popj-after-next (m-2) sub m-b a-10-mem-0-leftaddr) ((m-2) m+1 m-2) ;Get the pc and flags in other accumulator (m-t and m-r) get-10-pc-and-flags ;;;??? (popj-after-next (m-r) sub m-b a-10-mem-0-leftaddr) ((m-r) m+1 m-r) ;Come here to jump to effective address and execute next instruction. jump-10-jump ((m-b) add m-e a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Loop point for executing the next pdp-10 instruction. next-10-insn (jump-less-than m-b a-10-mem-20-addr xct-10-ac) ;Check for ACs referenced as memory. ((vma-start-read m-b) m+1 m-b) ;Increment pc and fetch lh of insn. (check-page-read) ((m-3) read-memory-data) ((vma-start-read) add m-b (a-constant 1000000)) (check-page-read) ((m-e) read-memory-data) ;Compute the effective address in M-E ;for the instruction in the instruction register (M-3, M-E). eff-addr-comp (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ;Fetch the next instruction from an accumulator. xct-10-ac (call get-10-pc) ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-3) a-10-ac-0-left) ((oa-reg-high) dpb m-a oah-a-src a-zero) (jump-xct-next eff-addr-comp) ((m-e) a-10-ac-0-right) (locality d-mem) (start-dispatch 5 0) d-10-index-and-indirect (xct-10-insn-1) (repeat 17 (do-10-indexing)) (do-10-indirect) (repeat 17 (do-10-indexing)) (end-dispatch) (locality i-mem) ;Perform indexing on address field in M-E ;with index register number in M-A. do-10-indexing ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-e) add m-e a-10-ac-0-right) (jump-if-bit-clear-xct-next pdp10-indirect-bit xct-10-insn) ((m-e) truncate-to-halfword m-e) ;Perform indirection, and merge the indirect pointer ;into the instruction register. Then go to begin again to execute the instruction. do-10-indirect (call load-10-mem) ((m-e) m-2) (jump-xct-next eff-addr-comp) ((m-3) mask-field pdp10-opcode m-3 a-1) ;Execute the instruction in M-3 with effective address in M-E ;The execution routine finds the accumulator in M-A. xct-10-insn (dispatch-xct-next pdp10-insn-class m-3 d-10-insn-class) ((m-a) pdp10-ac-field m-3) ;Dispatch on major classes of pdp-10 instructions. (locality d-mem) (start-dispatch 3 0) d-10-insn-class (xct-10-uuo) (xct-10-random) (xct-10-move) (xct-10-jump) (xct-10-logical) (xct-10-halfword) (xct-10-test) (xct-10-uuo) (end-dispatch) (locality i-mem) ;Do the store for an instruction like ADD ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-both (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-both) (end-dispatch) (locality i-mem) store-10-both (call store-10-mem) (jump store-10-ac) ;Do the store for an instruction like MOVE ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-self) (end-dispatch) (locality i-mem) store-10-self (call store-10-mem) (popj-equal m-a) (jump store-10-ac) ;The XCT instruction. i-10-xct (call load-10-mem) ((m-3) m-1) ((m-e) m-2) (jump eff-addr-comp) i-10-lsh (call load-10-ac-t) ((m-1) dpb m-t ?? a-zero) ((m-1) dpb m-r ?? a-1) ((m-2) dpb m-t ?? a-zero) ((m-2) dpb m-r ?? a-2) (call store-10-ac-t) (jump next-10-insn) ;Arithmetic Jump and Skip Instructions xct-10-jump ;Dispatch on jump vs skip, whether to increment, etc. (dispatch pdp10-jump-subclass m-3 d-10-jump-subclass) ;PDP10-JUMP-SUBCLASS should be bits 70 of the opcode. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-subclass (i-10-cai) (i-10-cam) (i-10-jump) (i-10-skip) (i-10-aoj) (i-10-aos) (i-10-soj) (i-10-sos) (locality i-mem) i-10-cam (call load-10-mem-t) (call load-10-ac) (call sub-10-no-flags) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-cai (call load-10-ac) ((m-2) sub m-2 a-e) (jump-if-bit-clear pdp10-carry-0-bit m-2 i-10-cai-1) ((m-1) sub m-1 (a-constant 1)) i-10-cai-1 ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-jump (call load-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-skip (call load-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aoj (call load-10-ac) (call inc-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aos (call load-10-mem) (call inc-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-soj (call load-10-ac) (call dec-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-sos (call load-10-mem) (call dec-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;Jump or Skip on Sign of Internal Accumulator. ;Do it with an instruction ; (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;The I-ARG should be COND-10-JUMP to jump, COND-10-SKIP to skip. ;PDP10-JUMP-CONDITION should be bits 7 of the opcode. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-condition (next-10-insn) ;Jump never (cond-10-less) (cond-10-equal) (cond-10-le) (cond-10-always) (cond-10-ge) (cond-10-ne) (cond-10-grtr) (end-dispatch) (locality i-mem) cond-10-le (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) cond-10-equal (jump-not-equal m-1 next-10-insn) (jump-not-equal m-2 next-10-insn) (jump cond-10-always) cond-10-grtr (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-ne (jump-not-equal m-1 cond-10-always) (jump-not-equal m-2 cond-10-always) (jump next-10-insn) cond-10-less (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) (jump next-10-insn) cond-10-ge (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-always (dispatch-xct-next read-i-arg d-10-jump-action) ((m-b) add m-b (a-constant 1)) ;The last instruction does a skip. ;If we are really jumping, it makes no difference. ;If we want to skip, we can go straight to the instruction loop. (locality d-mem) (start-dispatch 1 0) d-10-jump-action (jump-10-jump) (next-10-insn) (end-dispatch) (locality i-mem) ;Halfword Instructions ;PDP10-HALFWORD-FETCH-RIGHT-BIT should be the 4 bit of the opcode. ;PDP10-HALFWORD-STORE-RIGHT-BIT should be the 40 bit of the opcode. ;Subroutines ;Store M-2 in half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. store-10-ac-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-ac-half) (popj-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) (locality d-mem) (start-dispatch 1 0) d-store-10-ac-half (store-10-ac-left) (store-10-ac-right) (end-dispatch) store-10-ac-left ((a-10-ac-0-left) m-2) store-10-ac-right ((a-10-ac-0-right) m-2) ;Load M-2 from half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. load-10-ac-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-ac-half) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) (locality d-mem) (start-dispatch 1 0) d-load-10-ac-half (load-10-ac-left) (load-10-ac-right) (end-dispatch) load-10-ac-left ((m-2) a-10-ac-0-left) load-10-ac-right ((m-2) a-10-ac-0-right) ;Store M-2 in half of the simulated memory location with address in M-E. ;Which half is controlled by the instruction register. store-10-mem-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-mem-half) ((write-memory-data) m-2) (locality d-mem) (start-dispatch 1 0) d-store-10-mem-half (store-10-mem-left) (store-10-mem-right) (end-dispatch) store-10-mem-left ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) (popj) store-10-mem-right ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) ;Load M-2 from half of the simulated memory location whose address is in M-E. ;Which half is controlled by the instruction register. load-10-mem-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-mem-half) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d-load-10-mem-half (load-10-mem-left) (load-10-mem-right) (end-dispatch) load-10-mem-left ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-mem-right ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) ;Load M-2 from half of the immediate arg. ;Which half is controlled by the instruction register. load-10-immed-half (dispatch pdp10-halfword-fetch-right-bit m-3 d-load-10-immed-half) (locality d-mem) (start-dispatch 1 0) d-load-10-immed-half (load-10-immed-left) (load-10-immed-right) (end-dispatch) load-10-immed-left (popj (m-2) a-zero) load-10-immed-right (popj (m-2) m-e) ;PDP10-OPERATION-DIRECTION should be the low 2 bits of the opcode. ;PDP10-OTHER-HALFWORD-ACTION should be the 30 bits of the opcode. ;PDP10-HALFWORD-STORE-RIGHT-BIT should be the 40 bit of the opcode. xct-10-halfword (dispatch pdp10-operation-direction m-3 d-10-load-in-out-or-both-half) (dispatch pdp10-other-halfword-action m-3 d-other-10-halfword) (jump-if-bit-set pdp10-halfword-store-right-bit m-3 xct-10-halfword-1) ((m-c) m-1) ((m-1) m-2) ((m-2) m-c) xct-10-halfword-1 (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self) (jump next-10-insn) (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-load-in-out-or-both-half (p-bit load-10-mem-half) (p-bit load-immed-arg-half) (p-bit load-10-ac-half) (p-bit load-10-mem-half) (end-dispatch) (locality i-mem) ;Clear, set or sign-extend the "other" half, ;which right now is always in M-1. (locality d-mem) (start-dispatch 2 inhibit-xct-next-bit) d-other-10-halfword (xct-10-halfword-preserve-other-half) (p-bit other-10-halfword-clear) (p-bit other-10-halfword-set) (p-bit other-10-halfword-extend) (end-dispatch) (locality i-mem) other-10-halfword-extend (jump-if-bit-set pdp10-sign-bit m-2 other-10-halfword-set) other-10-halfword-clear (popj (m-1) a-zero) other-10-halfword-set (popj (m-1) (a-constant 777777)) xct-10-halfword-preserve-other-half (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self-half) (jump next-10-insn) ;Do the store for an instruction like HRL ;which only wants to store one halfword ;and can do it in the AC, in memory or in self. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self-halfword (p-bit store-10-ac-half) (p-bit store-10-ac-half) (p-bit store-10-mem-half) (p-bit store-10-self-half) (end-dispatch) (locality i-mem) store-10-self-half (call store-10-mem-half) (popj-equal m-a) (jump store-10-ac-half) ;Simple arithmetic subroutines. sub-10-no-flags ((m-1) sub m-1 m-t) ((m-2) sub m-2 m-r) (jump-if-bit-clear pdp10-carry-0-bit m-2 sub-10-a) ((m-1) sub m-1 (a-constant 1)) sub-10-a (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) inc-10 ((m-2) add m-2 (a-constant 1)) (jump-if-bit-set pdp10-carry-0-bit m-2 inc-10-a) ((m-1) add m-1 (a-constant 1)) inc-10-a ;;;??? Needs to compute and save carry 0, carry 1 and overflow flags. (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) dec-10 ((m-2) sub m-2 (a-constant 1)) (jump-if-bit-clear pdp10-carry-0-bit m-2 inc-10-a) ((m-1) add m-1 (a-constant 1)) dec-10-a ;;;??? Needs to compute and save carry 0, carry 1 and overflow flags. (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) ;TRNN, etc. ;PDP10-TEST-MODIFICATION should be the 60 bits of the opcode. ;PDP10-TEST-SOURCE-BIT should be bit 10 of the opcode. ;PDP10-TEST-SWAPPED-BIT should be bit 1 of the opcode. ;PDP10-TEST-CONDITION should be bits 6 of the opcode. xct-10-test ;Fetch the test mask from effective address or memory. (dispatch pdp10-test-source-bit m-3 d-10-test-source) ;Swap the test mask's halves if appropriate. (jump-if-bit-clear-xct-next pdp10-test-swapped-bit m-3 xct-10-test-1) ((m-1) m-t) ((m-t) m-r) ((m-r) m-1) xct-10-test-1 ;Fetch the AC to be tested. (call load-10-ac) ;Are any masked bits nonzero? ((m-i) and m-1 a-t) ((m-j) and m-2 a-r) (dispatch-xct-next pdp10-test-condition m-3 d-10-test-condition) ((m-i) ior m-i a-j) ;Maybe store new contents in AC. (dispatch pdp10-test-modification m-3 d-10-test-modification) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d-10-test-source (p-bit xct-10-test-immed) (p-bit load-10-mem-t) (end-dispatch) (locality i-mem) xct-10-test-immed (popj-after-next (m-r) m-e) ((m-t) a-zero) ;Decide whether to skip, and maybe do so. ;Called with (dispatch-xct-next pdp10-test-condition m-3 d-10-test-condition) ;The thing to test is whether M-I is nonzero. (locality d-mem) (start-dispatch 2 0) d-10-test-condition (xct-10-test-2) ;Do not skip. (p-bit xct-10-test-skip-if-0) (p-bit xct-10-test-skip-always) (p-bit xct-10-test-skip-not-0) (end-dispatch) (locality i-mem) xct-10-test-skip-not-0 (jump-xct-next xct-10-test-skip-always) (popj-equal m-i a-zero) ;;;??? Will that work? xct-10-test-skip-if-0 (popj-not-equal m-i a-zero) xct-10-test-skip-always (popj (m-b) add m-b (a-constant 1)) ;Compute and store the new contents of the accumulator. ;Called by (dispatch pdp10-test-modification m-3 d-10-test-modification) (locality d-mem) (start-dispatch 2 inhibit-xct-next-bit) d-10-test-modification (next-10-insn) (xct-10-test-set-zero) (xct-10-test-complement) (xct-10-test-set-one) (end-dispatch) (locality i-mem) xct-10-test-set-zero ((m-1) andca m-1 a-t) ((m-2) andca m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) xct-10-test-complement ((m-1) xor m-1 a-t) ((m-2) xor m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) xct-10-test-set-one ((m-1) ior m-1 a-t) ((m-2) ior m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) ;Stack instructions i-10-push (call load-10-ac) (call-xct-next load-10-mem-t) ((m-1) add m-1 (a-constant 1)) ((m-2) add m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) (call-xct-next store-10-ac) ((m-2) truncate-to-halfword m-2) (call-xct-next store-10-mem-t) ((m-e) m-2) (jump-not-equal m-1 a-zero next-10-insn) (jump pdl-10-overflow) i-10-pop (call-xct-next load-10-ac) ((c-pdl-buffer-pointer-push) m-e) (call-xct-next load-10-mem-t) ((m-e) m-2) (call-xct-next store-10-mem-t) ((m-e) c-pdl-buffer-pointer-pop) ((m-1) sub m-1 (a-constant 1)) ((m-2) sub m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (call store-10-ac) (jump-not-equal m-1 (a-constant -1) next-10-insn) (jump pdl-10-overflow) i-10-popj (call load-10-ac) (call-xct-next load-10-mem-t) ((m-e) m-2) ;Set the PC. ((m-b) add m-r a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Decrement the halves of the AC. ((m-1) sub m-1 (a-constant 1)) ((m-2) sub m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (call store-10-ac) (jump-not-equal m-1 (a-constant -1) next-10-insn) (jump pdl-10-overflow) i-10-pushj (call load-10-ac) (call-xct-next get-10-pc-and-flags-t) ((m-1) add m-1 (a-constant 1)) ((m-2) add m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) (call-xct-next store-10-ac) ((m-2) truncate-to-halfword m-2) (call-xct-next store-10-mem-t) ((m-e) m-2) (jump-not-equal m-1 a-zero next-10-insn) (jump pdl-10-overflow) ;Byte instructions. * LMFL(DIRECTORY "RMS" NAME "PDP10" TYPE "LISP" VERSION 11 BYTE-SIZE 10 CREATION-DATE 23075640622 AUTHOR "RMS") ;PDP-10 simulator microcode ;The simulator uses an internal accumulator for its arithmetic ;and most of its data transfers. ;This internal accumulator consists of M-1 and M-2. ;M-1 holds the left half of the 36-bit quantity and M-2 the right half. ;The other argument of arithmetic operations goes in ;the T register, composed of M-T and M-R. ;Instructions are executed out of the instruction register, ;which occupies M-3 and M-E. ;The AC field of the instruction is standardly placed in M-A, ;and the effective address is computed in M-E. ;The simulated PC lives in M-B; actually, that contains ;one less than the Q address of the left halfword of the next instruction. ;Jump instructions and PC saving instructions convert ;between this form of quantity and a pdp-10 address. ;The simulated PDP10 flags, except for CARRY 0, CARRY 1 and OVERFLOW, ;are kept in A-10-FLAGS. The flags can be used to help decode ;the reason why the microcode simulator exited. ;For example, the pdl overflow flag may be set. (locality a-mem) a-10-flags (0) (modulo 2) ;So halfword instructions can choose which half! ;Address of Q containing the left half of simulated memory location 0. ;The left halves of all PDP-10 memory words live in consecutive Qs. a-10-mem-0-left-addr (0) ;Address of Q containing the right half of simulated memory location 0. ;The right halves of all PDP-10 memory words live in consecutive Qs, ;immediately following the left halves. ;Thus, this address is always 1000000 more than that in a-10-mem-0-left-addr. a-10-mem-0-right-addr (0) ;Address of left half of memory location 20, ;used for testing the PC to see whether points at an AC. a-10-mem-20-left-addr (0) ;40 here so halfword instructions can choose which half! (modulo 40) ;These are the left halves of the pdp-10's simulated accumulators. a-10-ac-0-left (0) (modulo 20) ;These are the right halves. a-10-ac-0-right (0) (modulo 20) (locality i-mem) ;Load and store simulated accumulators (AC number in M-A) ;from the internal accumulator and the T register. ;Store the internal accumulator into the simulated accumulator ;whose number is in M-A. store-10-ac ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated accumulator whose number is in M-A ;into the internal accumulator. load-10-ac ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the T register into the simulated accumulator ;whose number is in M-A. store-10-ac-t ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Load the simulated accumulator whose number is in M-A ;into the T register. load-10-ac-t ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Load and store main memory (address in M-E) ;from the internal accumulator and the T register. ;Load the simulated memory location whose number is in M-E ;into the internal accumulator. load-10-mem (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-1) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-ac-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the internal accumulator into the simulated memory location ;whose address is in M-E. store-10-mem (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-1) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-2) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated memory location whose number is in M-E ;into the T register. load-10-mem-t (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-t) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-r) read-memory-data) load-10-ac-t-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Store the T register into the simulated memory location ;whose address is in M-E. store-10-mem-t (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-t) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-r) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-t-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Entry and exit. ;Call with (%pdp10-simulator
) ;It returns two values on the stack: the new pc and the new flags. enter-10-simulator (misc-inst-entry %pdp10-simulator) ((a-10-mem-0-left-addr) c-pdl-buffer-pointer-pop) ((a-10-flags) c-pdl-buffer-pointer-pop) ((m-e) c-pdl-buffer-pointer-pop) (jump jump-10-jump) ;Jump to the PC now in M-E. exit-10-simulator (call get-10-pc-and-flags-t) ;Get flags in M-T, pc in M-R. ((c-pdl-buffer-pointer-push) m-r) (popj) ;return flags to misc insn destination (push). pdl-10-overflow ((m-1) (a-constant pdp10-pdl-overflow-flag)) ((a-10-flags) ior m-1 a-10-flags) (jump exit-10-simulator) ;Set the simulated pc from a pdp-10 format pc in M-2. set-10-pc (popj-after-next (m-b) add m-2 (a-constant -1)) ((m-b) add m-b a-10-mem-0-left-addr) ;Get the pc and flags in internal accumulator (m-1 and m-2) get-10-pc-and-flags ;;;??? ;Get the pc in pdp-10 form in M-2. get-10-pc (popj-after-next (m-2) sub m-b a-10-mem-0-leftaddr) ((m-2) m+1 m-2) ;Get the pc and flags in other accumulator (m-t and m-r) get-10-pc-and-flags ;;;??? (popj-after-next (m-r) sub m-b a-10-mem-0-leftaddr) ((m-r) m+1 m-r) ;Come here to jump to effective address and execute next instruction. jump-10-jump ((m-b) add m-e a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Loop point for executing the next pdp-10 instruction. next-10-insn (jump-less-than m-b a-10-mem-20-addr xct-10-ac) ;Check for ACs referenced as memory. ((vma-start-read m-b) m+1 m-b) ;Increment pc and fetch lh of insn. (check-page-read) ((m-3) read-memory-data) ((vma-start-read) add m-b (a-constant 1000000)) (check-page-read) ((m-e) read-memory-data) ;Compute the effective address in M-E ;for the instruction in the instruction register (M-3, M-E). eff-addr-comp (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ;Fetch the next instruction from an accumulator. xct-10-ac (call get-10-pc) ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-3) a-10-ac-0-left) ((oa-reg-high) dpb m-a oah-a-src a-zero) (jump-xct-next eff-addr-comp) ((m-e) a-10-ac-0-right) (locality d-mem) (start-dispatch 5 0) d-10-index-and-indirect (xct-10-insn-1) (repeat 17 (do-10-indexing)) (do-10-indirect) (repeat 17 (do-10-indexing)) (end-dispatch) (locality i-mem) ;Perform indexing on address field in M-E ;with index register number in M-A. do-10-indexing ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-e) add m-e a-10-ac-0-right) (jump-if-bit-clear-xct-next pdp10-indirect-bit xct-10-insn) ((m-e) truncate-to-halfword m-e) ;Perform indirection, and merge the indirect pointer ;into the instruction register. Then go to begin again to execute the instruction. do-10-indirect (call load-10-mem) ((m-e) m-2) (jump-xct-next eff-addr-comp) ((m-3) mask-field pdp10-opcode m-3 a-1) ;Execute the instruction in M-3 with effective address in M-E ;The execution routine finds the accumulator in M-A. xct-10-insn (dispatch-xct-next pdp10-insn-class m-3 d-10-insn-class) ((m-a) pdp10-ac-field m-3) ;Dispatch on major classes of pdp-10 instructions. (locality d-mem) (start-dispatch 3 0) d-10-insn-class (xct-10-uuo) (xct-10-random) (xct-10-move) (xct-10-jump) (xct-10-logical) (xct-10-halfword) (xct-10-test) (xct-10-uuo) (end-dispatch) (locality i-mem) ;Do the store for an instruction like ADD ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-both (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-both) (end-dispatch) (locality i-mem) store-10-both (call store-10-mem) (jump store-10-ac) ;Do the store for an instruction like MOVE ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-self) (end-dispatch) (locality i-mem) store-10-self (call store-10-mem) (popj-equal m-a) (jump store-10-ac) ;The XCT instruction. i-10-xct (call load-10-mem) ((m-3) m-1) ((m-e) m-2) (jump eff-addr-comp) i-10-lsh (call load-10-ac-t) ((m-1) dpb m-t ?? a-zero) ((m-1) dpb m-r ?? a-1) ((m-2) dpb m-t ?? a-zero) ((m-2) dpb m-r ?? a-2) (call store-10-ac-t) (jump next-10-insn) ;Arithmetic Jump and Skip Instructions xct-10-jump ;Dispatch on jump vs skip, whether to increment, etc. (dispatch pdp10-jump-subclass m-3 d-10-jump-subclass) ;PDP10-JUMP-SUBCLASS should be bits 70 of the opcode. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-subclass (i-10-cai) (i-10-cam) (i-10-jump) (i-10-skip) (i-10-aoj) (i-10-aos) (i-10-soj) (i-10-sos) (locality i-mem) i-10-cam (call load-10-mem-t) (call load-10-ac) (call sub-10-no-flags) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-cai (call load-10-ac) ((m-2) sub m-2 a-e) (jump-if-bit-clear pdp10-carry-0-bit m-2 i-10-cai-1) ((m-1) sub m-1 (a-constant 1)) i-10-cai-1 ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-jump (call load-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-skip (call load-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aoj (call load-10-ac) (call inc-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aos (call load-10-mem) (call inc-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-soj (call load-10-ac) (call dec-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-sos (call load-10-mem) (call dec-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;Jump or Skip on Sign of Internal Accumulator. ;Do it with an instruction ; (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;The I-ARG should be COND-10-JUMP to jump, COND-10-SKIP to skip. ;PDP10-JUMP-CONDITION should be bits 7 of the opcode. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-condition (next-10-insn) ;Jump never (cond-10-less) (cond-10-equal) (cond-10-le) (cond-10-always) (cond-10-ge) (cond-10-ne) (cond-10-grtr) (end-dispatch) (locality i-mem) cond-10-le (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) cond-10-equal (jump-not-equal m-1 next-10-insn) (jump-not-equal m-2 next-10-insn) (jump cond-10-always) cond-10-grtr (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-ne (jump-not-equal m-1 cond-10-always) (jump-not-equal m-2 cond-10-always) (jump next-10-insn) cond-10-less (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) (jump next-10-insn) cond-10-ge (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-always (dispatch-xct-next read-i-arg d-10-jump-action) ((m-b) add m-b (a-constant 1)) ;The last instruction does a skip. ;If we are really jumping, it makes no difference. ;If we want to skip, we can go straight to the instruction loop. (locality d-mem) (start-dispatch 1 0) d-10-jump-action (jump-10-jump) (next-10-insn) (end-dispatch) (locality i-mem) ;Halfword Instructions ;PDP10-HALFWORD-FETCH-RIGHT-BIT should be the 4 bit of the opcode. ;PDP10-HALFWORD-STORE-RIGHT-BIT should be the 40 bit of the opcode. ;Subroutines ;Store M-2 in half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. store-10-ac-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-ac-half) (popj-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) (locality d-mem) (start-dispatch 1 0) d-store-10-ac-half (store-10-ac-left) (store-10-ac-right) (end-dispatch) store-10-ac-left ((a-10-ac-0-left) m-2) store-10-ac-right ((a-10-ac-0-right) m-2) ;Load M-2 from half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. load-10-ac-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-ac-half) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) (locality d-mem) (start-dispatch 1 0) d-load-10-ac-half (load-10-ac-left) (load-10-ac-right) (end-dispatch) load-10-ac-left ((m-2) a-10-ac-0-left) load-10-ac-right ((m-2) a-10-ac-0-right) ;Store M-2 in half of the simulated memory location with address in M-E. ;Which half is controlled by the instruction register. store-10-mem-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-mem-half) ((write-memory-data) m-2) (locality d-mem) (start-dispatch 1 0) d-store-10-mem-half (store-10-mem-left) (store-10-mem-right) (end-dispatch) store-10-mem-left ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) (popj) store-10-mem-right ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) ;Load M-2 from half of the simulated memory location whose address is in M-E. ;Which half is controlled by the instruction register. load-10-mem-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-mem-half) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d-load-10-mem-half (load-10-mem-left) (load-10-mem-right) (end-dispatch) load-10-mem-left ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-mem-right ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) ;Load M-2 from half of the immediate arg. ;Which half is controlled by the instruction register. load-10-immed-half (dispatch pdp10-halfword-fetch-right-bit m-3 d-load-10-immed-half) (locality d-mem) (start-dispatch 1 0) d-load-10-immed-half (load-10-immed-left) (load-10-immed-right) (end-dispatch) load-10-immed-left (popj (m-2) a-zero) load-10-immed-right (popj (m-2) m-e) ;PDP10-OPERATION-DIRECTION should be the low 2 bits of the opcode. ;PDP10-OTHER-HALFWORD-ACTION should be the 30 bits of the opcode. ;PDP10-HALFWORD-STORE-RIGHT-BIT should be the 40 bit of the opcode. xct-10-halfword (dispatch pdp10-operation-direction m-3 d-10-load-in-out-or-both-half) (dispatch pdp10-other-halfword-action m-3 d-other-10-halfword) (jump-if-bit-set pdp10-halfword-store-right-bit m-3 xct-10-halfword-1) ((m-c) m-1) ((m-1) m-2) ((m-2) m-c) xct-10-halfword-1 (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self) (jump next-10-insn) (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-load-in-out-or-both-half (p-bit load-10-mem-half) (p-bit load-immed-arg-half) (p-bit load-10-ac-half) (p-bit load-10-mem-half) (end-dispatch) (locality i-mem) ;Clear, set or sign-extend the "other" half, ;which right now is always in M-1. (locality d-mem) (start-dispatch 2 inhibit-xct-next-bit) d-other-10-halfword (xct-10-halfword-preserve-other-half) (p-bit other-10-halfword-clear) (p-bit other-10-halfword-set) (p-bit other-10-halfword-extend) (end-dispatch) (locality i-mem) other-10-halfword-extend (jump-if-bit-set pdp10-sign-bit m-2 other-10-halfword-set) other-10-halfword-clear (popj (m-1) a-zero) other-10-halfword-set (popj (m-1) (a-constant 777777)) xct-10-halfword-preserve-other-half (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self-half) (jump next-10-insn) ;Do the store for an instruction like HRL ;which only wants to store one halfword ;and can do it in the AC, in memory or in self. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self-halfword (p-bit store-10-ac-half) (p-bit store-10-ac-half) (p-bit store-10-mem-half) (p-bit store-10-self-half) (end-dispatch) (locality i-mem) store-10-self-half (call store-10-mem-half) (popj-equal m-a) (jump store-10-ac-half) ;Simple arithmetic subroutines. sub-10-no-flags ((m-1) sub m-1 m-t) ((m-2) sub m-2 m-r) (jump-if-bit-clear pdp10-carry-0-bit m-2 sub-10-a) ((m-1) sub m-1 (a-constant 1)) sub-10-a (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) inc-10 ((m-2) add m-2 (a-constant 1)) (jump-if-bit-set pdp10-carry-0-bit m-2 inc-10-a) ((m-1) add m-1 (a-constant 1)) inc-10-a ;;;??? Needs to compute and save carry 0, carry 1 and overflow flags. (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) dec-10 ((m-2) sub m-2 (a-constant 1)) (jump-if-bit-clear pdp10-carry-0-bit m-2 inc-10-a) ((m-1) add m-1 (a-constant 1)) dec-10-a ;;;??? Needs to compute and save carry 0, carry 1 and overflow flags. (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) ;TRNN, etc. ;PDP10-TEST-MODIFICATION should be the 60 bits of the opcode. ;PDP10-TEST-SOURCE-BIT should be bit 10 of the opcode. ;PDP10-TEST-SWAPPED-BIT should be bit 1 of the opcode. ;PDP10-TEST-CONDITION should be bits 6 of the opcode. xct-10-test ;Fetch the test mask from effective address or memory. (dispatch pdp10-test-source-bit m-3 d-10-test-source) ;Swap the test mask's halves if appropriate. (jump-if-bit-clear-xct-next pdp10-test-swapped-bit m-3 xct-10-test-1) ((m-1) m-t) ((m-t) m-r) ((m-r) m-1) xct-10-test-1 ;Fetch the AC to be tested. (call load-10-ac) ;Are any masked bits nonzero? ((m-i) and m-1 a-t) ((m-j) and m-2 a-r) (dispatch-xct-next pdp10-test-condition m-3 d-10-test-condition) ((m-i) ior m-i a-j) ;Maybe store new contents in AC. (dispatch pdp10-test-modification m-3 d-10-test-modification) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d-10-test-source (p-bit xct-10-test-immed) (p-bit load-10-mem-t) (end-dispatch) (locality i-mem) xct-10-test-immed (popj-after-next (m-r) m-e) ((m-t) a-zero) ;Decide whether to skip, and maybe do so. ;Called with (dispatch-xct-next pdp10-test-condition m-3 d-10-test-condition) ;The thing to test is whether M-I is nonzero. (locality d-mem) (start-dispatch 2 0) d-10-test-condition (xct-10-test-2) ;Do not skip. (p-bit xct-10-test-skip-if-0) (p-bit xct-10-test-skip-always) (p-bit xct-10-test-skip-not-0) (end-dispatch) (locality i-mem) xct-10-test-skip-not-0 (jump-xct-next xct-10-test-skip-always) (popj-equal m-i a-zero) ;;;??? Will that work? xct-10-test-skip-if-0 (popj-not-equal m-i a-zero) xct-10-test-skip-always (popj (m-b) add m-b (a-constant 1)) ;Compute and store the new contents of the accumulator. ;Called by (dispatch pdp10-test-modification m-3 d-10-test-modification) (locality d-mem) (start-dispatch 2 inhibit-xct-next-bit) d-10-test-modification (next-10-insn) (xct-10-test-set-zero) (xct-10-test-complement) (xct-10-test-set-one) (end-dispatch) (locality i-mem) xct-10-test-set-zero ((m-1) andca m-1 a-t) ((m-2) andca m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) xct-10-test-complement ((m-1) xor m-1 a-t) ((m-2) xor m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) xct-10-test-set-one ((m-1) ior m-1 a-t) ((m-2) ior m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) ;Stack instructions i-10-push (call load-10-ac) (call-xct-next load-10-mem-t) ((m-1) add m-1 (a-constant 1)) ((m-2) add m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) (call-xct-next store-10-ac) ((m-2) truncate-to-halfword m-2) (call-xct-next store-10-mem-t) ((m-e) m-2) (jump-not-equal m-1 a-zero next-10-insn) (jump pdl-10-overflow) i-10-pop (call-xct-next load-10-ac) ((c-pdl-buffer-pointer-push) m-e) (call-xct-next load-10-mem-t) ((m-e) m-2) (call-xct-next store-10-mem-t) ((m-e) c-pdl-buffer-pointer-pop) ((m-1) sub m-1 (a-constant 1)) ((m-2) sub m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (call store-10-ac) (jump-not-equal m-1 (a-constant -1) next-10-insn) (jump pdl-10-overflow) i-10-popj (call load-10-ac) (call-xct-next load-10-mem-t) ((m-e) m-2) ;Set the PC. ((m-b) add m-r a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Decrement the halves of the AC. ((m-1) sub m-1 (a-constant 1)) ((m-2) sub m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (call store-10-ac) (jump-not-equal m-1 (a-constant -1) next-10-insn) (jump pdl-10-overflow) i-10-pushj (call load-10-ac) (call-xct-next get-10-pc-and-flags-t) ((m-1) add m-1 (a-constant 1)) ((m-2) add m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) (call-xct-next store-10-ac) ((m-2) truncate-to-halfword m-2) (call-xct-next store-10-mem-t) ((m-e) m-2) (jump-not-equal m-1 a-zero next-10-insn) (jump pdl-10-overflow) ;Byte instructions. ;PDP10-BP-POSITION and PDP10-BP-SIZE are needed. i-10-ldb (call load-10-mem) ((m-3) m-1) ((m-e) m-2) ;compute bp effective address. (call load-10-mem) * LMFL(DIRECTORY "RMS" NAME "PDP10" TYPE "LISP" VERSION 12 BYTE-SIZE 10 CREATION-DATE 23075640631 AUTHOR "RMS") ;PDP-10 simulator microcode ;The simulator uses an internal accumulator for its arithmetic ;and most of its data transfers. ;This internal accumulator consists of M-1 and M-2. ;M-1 holds the left half of the 36-bit quantity and M-2 the right half. ;The other argument of arithmetic operations goes in ;the T register, composed of M-T and M-R. ;Instructions are executed out of the instruction register, ;which occupies M-3 and M-E. ;The AC field of the instruction is standardly placed in M-A, ;and the effective address is computed in M-E. ;The simulated PC lives in M-B; actually, that contains ;one less than the Q address of the left halfword of the next instruction. ;Jump instructions and PC saving instructions convert ;between this form of quantity and a pdp-10 address. ;The simulated PDP10 flags, except for CARRY 0, CARRY 1 and OVERFLOW, ;are kept in A-10-FLAGS. The flags can be used to help decode ;the reason why the microcode simulator exited. ;For example, the pdl overflow flag may be set. (locality a-mem) a-10-flags (0) (modulo 2) ;So halfword instructions can choose which half! ;Address of Q containing the left half of simulated memory location 0. ;The left halves of all PDP-10 memory words live in consecutive Qs. a-10-mem-0-left-addr (0) ;Address of Q containing the right half of simulated memory location 0. ;The right halves of all PDP-10 memory words live in consecutive Qs, ;immediately following the left halves. ;Thus, this address is always 1000000 more than that in a-10-mem-0-left-addr. a-10-mem-0-right-addr (0) ;Address of left half of memory location 20, ;used for testing the PC to see whether points at an AC. a-10-mem-20-left-addr (0) ;40 here so halfword instructions can choose which half! (modulo 40) ;These are the left halves of the pdp-10's simulated accumulators. a-10-ac-0-left (0) (modulo 20) ;These are the right halves. a-10-ac-0-right (0) (modulo 20) (locality i-mem) ;Load and store simulated accumulators (AC number in M-A) ;from the internal accumulator and the T register. ;Store the internal accumulator into the simulated accumulator ;whose number is in M-A. store-10-ac ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated accumulator whose number is in M-A ;into the internal accumulator. load-10-ac ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the T register into the simulated accumulator ;whose number is in M-A. store-10-ac-t ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Load the simulated accumulator whose number is in M-A ;into the T register. load-10-ac-t ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Load and store main memory (address in M-E) ;from the internal accumulator and the T register. ;Load the simulated memory location whose number is in M-E ;into the internal accumulator. load-10-mem (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-1) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-ac-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the internal accumulator into the simulated memory location ;whose address is in M-E. store-10-mem (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-1) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-2) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated memory location whose number is in M-E ;into the T register. load-10-mem-t (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-t) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-r) read-memory-data) load-10-ac-t-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Store the T register into the simulated memory location ;whose address is in M-E. store-10-mem-t (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-t) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-r) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-t-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Entry and exit. ;Call with (%pdp10-simulator
) ;It returns two values on the stack: the new pc and the new flags. enter-10-simulator (misc-inst-entry %pdp10-simulator) ((a-10-mem-0-left-addr) c-pdl-buffer-pointer-pop) ((a-10-flags) c-pdl-buffer-pointer-pop) ((m-e) c-pdl-buffer-pointer-pop) (jump jump-10-jump) ;Jump to the PC now in M-E. exit-10-simulator (call get-10-pc-and-flags-t) ;Get flags in M-T, pc in M-R. ((c-pdl-buffer-pointer-push) m-r) (popj) ;return flags to misc insn destination (push). pdl-10-overflow ((m-1) (a-constant pdp10-pdl-overflow-flag)) ((a-10-flags) ior m-1 a-10-flags) (jump exit-10-simulator) ;Set the simulated pc from a pdp-10 format pc in M-2. set-10-pc (popj-after-next (m-b) add m-2 (a-constant -1)) ((m-b) add m-b a-10-mem-0-left-addr) ;Get the pc and flags in internal accumulator (m-1 and m-2) get-10-pc-and-flags ;;;??? ;Get the pc in pdp-10 form in M-2. get-10-pc (popj-after-next (m-2) sub m-b a-10-mem-0-leftaddr) ((m-2) m+1 m-2) ;Get the pc and flags in other accumulator (m-t and m-r) get-10-pc-and-flags ;;;??? (popj-after-next (m-r) sub m-b a-10-mem-0-leftaddr) ((m-r) m+1 m-r) ;Come here to jump to effective address and execute next instruction. jump-10-jump ((m-b) add m-e a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Loop point for executing the next pdp-10 instruction. next-10-insn (jump-less-than m-b a-10-mem-20-addr xct-10-ac) ;Check for ACs referenced as memory. ((vma-start-read m-b) m+1 m-b) ;Increment pc and fetch lh of insn. (check-page-read) ((m-3) read-memory-data) ((vma-start-read) add m-b (a-constant 1000000)) (check-page-read) ((m-e) read-memory-data) ;Compute the effective address in M-E ;for the instruction in the instruction register (M-3, M-E). eff-addr-comp (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ;Fetch the next instruction from an accumulator. xct-10-ac (call get-10-pc) ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-3) a-10-ac-0-left) ((oa-reg-high) dpb m-a oah-a-src a-zero) (jump-xct-next eff-addr-comp) ((m-e) a-10-ac-0-right) (locality d-mem) (start-dispatch 5 0) d-10-index-and-indirect (xct-10-insn-1) (repeat 17 (do-10-indexing)) (do-10-indirect) (repeat 17 (do-10-indexing)) (end-dispatch) (locality i-mem) ;Perform indexing on address field in M-E ;with index register number in M-A. do-10-indexing ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-e) add m-e a-10-ac-0-right) (jump-if-bit-clear-xct-next pdp10-indirect-bit xct-10-insn) ((m-e) truncate-to-halfword m-e) ;Perform indirection, and merge the indirect pointer ;into the instruction register. Then go to begin again to execute the instruction. do-10-indirect (call load-10-mem) ((m-e) m-2) (jump-xct-next eff-addr-comp) ((m-3) mask-field pdp10-opcode m-3 a-1) ;Execute the instruction in M-3 with effective address in M-E ;The execution routine finds the accumulator in M-A. xct-10-insn (dispatch-xct-next pdp10-insn-class m-3 d-10-insn-class) ((m-a) pdp10-ac-field m-3) ;Dispatch on major classes of pdp-10 instructions. (locality d-mem) (start-dispatch 3 0) d-10-insn-class (xct-10-uuo) (xct-10-random) (xct-10-move) (xct-10-jump) (xct-10-logical) (xct-10-halfword) (xct-10-test) (xct-10-uuo) (end-dispatch) (locality i-mem) ;Do the store for an instruction like ADD ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-both (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-both) (end-dispatch) (locality i-mem) store-10-both (call store-10-mem) (jump store-10-ac) ;Do the store for an instruction like MOVE ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-self) (end-dispatch) (locality i-mem) store-10-self (call store-10-mem) (popj-equal m-a) (jump store-10-ac) ;The XCT instruction. i-10-xct (call load-10-mem) ((m-3) m-1) ((m-e) m-2) (jump eff-addr-comp) i-10-lsh (call load-10-ac-t) ((m-1) dpb m-t ?? a-zero) ((m-1) dpb m-r ?? a-1) ((m-2) dpb m-t ?? a-zero) ((m-2) dpb m-r ?? a-2) (call store-10-ac-t) (jump next-10-insn) ;Arithmetic Jump and Skip Instructions xct-10-jump ;Dispatch on jump vs skip, whether to increment, etc. (dispatch pdp10-jump-subclass m-3 d-10-jump-subclass) ;PDP10-JUMP-SUBCLASS should be bitp 40 lg thg lp`ldg/(ll`clkt{ d/ogo+(ptcst/dkppct`h 0 kohkckt/x`t/ogxt/ckt+d/30/kwop/pwc`lcpp‹(k/30/`ck+‹(k/30/`co+‹(k/30/kwop+‹(k/30/phkp+‹(k/30/clk+‹(k/30/clp+‹(k/30/plk+‹(k/30/plp+(ll`clkt{ k/ogo+k/30/`co‹(`cll llcd/30/ogo/t+‹(`cll llcd/30/c`+‹(`cll pwc/30/ol/glcdp+‹(dkppct`h (k/csd `lod/30/phkp+ pdp30/kwop/`lodktklo o/0 d/30/kwop/`lodktklo+k/30/`ck‹(`cll llcd/30/c`+‹((o/3+ pwc o/3 c/g+‹(kwop/kg/ckt/`lgcs pdp30/`css{/0/ckt o/3 k/30/`ck/3+‹((o/3+ pwc o/3 (c/`loptcot 3++k/30/`ck/3‹((o/3+ tswo`ctg/tl/hclgtlsd o/3+‹((o/3+ tswo`ctg/tl/hclgtlsd o/3+‹(dkppct`h (k/csd `lod/30/phkp+ pdp30/kwop/`lodktklo o/0 d/30/kwop/`lodktklo+k/30/kwop‹(`cll llcd/30/c`+‹(dkppct`h (k/csd `lod/30/kwop+ pdp30/kwop/`lodktklo o/0 d/30/kwop/`lodktklo+k/30/phkp‹(`cll llcd/30/ogo+‹(`cll/olt/gswcl o/c c/{gsl ptlsg/30/c`+‹(dkppct`h (k/csd `lod/30/phkp+ pdp30/kwop/`lodktklo o/0 d/30/kwop/`lodktklo+k/30/clk‹(`cll llcd/30/c`+‹(`cll ko`/30+‹(`cll ptlsg/30/c`+‹(dkppct`h (k/csd `lod/30/kwop+ pdp30/kwop/`lodktklo o/0 d/30/kwop/`lodktklo+k/30/clp‹(`cll llcd/30/ogo+‹(`cll ko`/30+‹(`cll ptlsg/30/ogo+‹(`cll/olt/gswcl o/c c/{gsl ptlsg/30/c`+‹(dkppct`h (k/csd `lod/30/phkp+ pdp30/kwop/`lodktklo o/0 d/30/kwop/`lodktklo+k/30/plk‹(`cll llcd/30/c`+‹(`cll dg`/30+‹(`cll ptlsg/30/c`+‹(dkppct`h (k/csd `lod/30/kwop+ pdp30/kwop/`lodktklo o/0 d/30/kwop/`lodktklo+k/30/plp‹(`cll llcd/30/ogo+‹(`cll dg`/30+‹(`cll ptlsg/30/ogo+‹(`cll/olt/gswcl o/c c/{gsl ptlsg/30/c`+‹(dkppct`h (k/csd `lod/30/phkp+ pdp30/kwop/`lodktklo o/0 d/30/kwop/`lodktklo+ 8Kwop ls Phkp lo Pkdo lg Kotgsocl C``wowlctls/8Dl kt tkth co koptsw`tklo8‹(dkppct`h (k/csd `lod/30/phkp+ pdp30/kwop/`lodktklo o/0 d/30/kwop/`lodktklo+8Thg K/CSD phlwld cg @LOD/30/KWOP tl kwop, @LOD/30/PHKP tl phkp/8PDP30/KWOP/@LODKTKLO phlwld cg cktp 4 lg thg lp`ldg/(ll`clkt{ d/ogo+(ptcst/dkppct`h 0 kohkckt/x`t/ogxt/ckt+d/30/kwop/`lodktklo‹(ogxt/30/kopo+‹8Kwop ogwgs‹(`lod/30/lgpp+‹(`lod/30/gswcl+‹(`lod/30/lg+‹(`lod/30/cltc{p+‹(`lod/30/dg+‹(`lod/30/og+‹(`lod/30/dsts+(god/dkppct`h+(ll`clkt{ k/ogo+`lod/30/lg‹(kwop/kg/ckt/pgt pdp30/pkdo/ckt o/3 `lod/30/cltc{p+`lod/30/gswcl‹(kwop/olt/gswcl o/3 ogxt/30/kopo+‹(kwop/olt/gswcl o/3 ogxt/30/kopo+‹(kwop cond-10-always) cond-10-grtr (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-ne (jump-not-equal m-1 cond-10-always) (jump-not-equal m-2 cond-10-always) (jump next-10-insn) cond-10-less (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) (jump next-10-insn) cond-10-ge (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-always (dispatch-xct-next read-i-arg d-10-jump-action) ((m-b) add m-b (a-constant 1)) ;The last instruction does a skip. ;If we are really jumping, it makes no difference. ;If we want to skip, we can go straight to the instruction loop. (locality d-mem) (start-dispatch 1 0) d-10-jump-action (jump-10-jump) (next-10-insn) (end-dispatch) (locality i-mem) ;Halfword Instructions ;PDP10-HALFWORD-FETCH-RIGHT-BIT should be the 4 bit of the opcode. ;PDP10-HALFWORD-STORE-RIGHT-BIT should be the 40 bit of the opcode. ;Subroutines ;Store M-2 in half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. store-10-ac-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-ac-half) (popj-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) (locality d-mem) (start-dispatch 1 0) d-store-10-ac-half (store-10-ac-left) (store-10-ac-right) (end-dispatch) store-10-ac-left ((a-10-ac-0-left) m-2) store-10-ac-right ((a-10-ac-0-right) m-2) ;Load M-2 from half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. load-10-ac-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-ac-half) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) (locality d-mem) (start-dispatch 1 0) d-load-10-ac-half (load-10-ac-left) (load-10-ac-right) (end-dispatch) load-10-ac-left ((m-2) a-10-ac-0-left) load-10-ac-right ((m-2) a-10-ac-0-right) ;Store M-2 in half of the simulated memory location with address in M-E. ;Which half is controlled by the instruction register. store-10-mem-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-mem-half) ((write-memory-data) m-2) (locality d-mem) (start-dispatch 1 0) d-store-10-mem-half (store-10-mem-left) (store-10-mem-right) (end-dispatch) store-10-mem-left ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) (popj) store-10-mem-right ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) ;Load M-2 from half of the simulated memory location whose address is in M-E. ;Which half is controlled by the instruction register. load-10-mem-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-mem-half) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d-load-10-mem-half (load-10-mem-left) (load-10-mem-right) (end-dispatch) load-10-mem-left ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-mem-right ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) ;Load M-2 from half of the immediate arg. ;Which half is controlled by the instruction register. load-10-immed-half (dispatch pdp10-halfword-fetch-right-bit m-3 d-load-10-immed-half) (locality d-mem) (start-dispatch 1 0) d-load-10-immed-half (load-10-immed-left) (load-10-immed-right) (end-dispatch) load-10-immed-left (popj (m-2) a-zero) load-10-immed-right (popj (m-2) m-e) ;PDP10-OPERATION-DIRECTION should be the low 2 bits of the opcode. ;PDP10-OTHER-HALFWORD-ACTION should be the 30 bits of the opcode. ;PDP10-HALFWORD-STORE-RIGHT-BIT should be the 40 bit of the opcode. xct-10-halfword (dispatch pdp10-operation-direction m-3 d-10-load-in-out-or-both-half) (dispatch pdp10-other-halfword-action m-3 d-other-10-halfword) (jump-if-bit-set pdp10-halfword-store-right-bit m-3 xct-10-halfword-1) ((m-c) m-1) ((m-1) m-2) ((m-2) m-c) xct-10-halfword-1 (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self) (jump next-10-insn) (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-load-in-out-or-both-half (p-bit load-10-mem-half) (p-bit load-immed-arg-half) (p-bit load-10-ac-half) (p-bit load-10-mem-half) (end-dispatch) (locality i-mem) ;Clear, set or sign-extend the "other" half, ;which right now is always in M-1. (locality d-mem) (start-dispatch 2 inhibit-xct-next-bit) d-other-10-halfword (xct-10-halfword-preserve-other-half) (p$b`t ftimr$90$iimffrd$kmmir „€)p$b`t ftimr$90$iimffrd${mt „€)p$b`t ftimr$90$iimffrd$mytmod „)mod$d`{pitki „)mfkim`tp `$dmd „„ftimr$90$iimffrd$mytmod„€)k}dp$`f$b`t${mt pdp90${`oo$b`t d$2 ftimr$90$iimffrd${mt „ftimr$90$iimffrd$kmmir„€)pfpk )d$9 i${mrf „„ftimr$90$iimffrd${mt„€)pfpk )d$9 )i$kfo{tiot ?????? „„ykt$90$iimffrd$prm{mrvm$ftimr$iimf„€)d`{pitki pdp90$fpmrit`fo$d`rmkt`fo d$; d$90${tfrm$`o$f}t$fr${mmf$iimf „€)k}dp omyt$90$`o{o „„2Df tim {tfrm ffr io `o{tr}kt`fo m`bm IRM„2i`ki fomp iot{ tf {tfrm fom iimffrd„2iod kio df `t `o tim IK- `o dmdfrp fr `o {mmf/„)mfkim`tp d$dmd „){tirt$d`{pitki ; `oi`b`t$ykt$omyt$b`t „d$90${tfrm$`o$f}t$fr${mmf$iimffrd„€)p$b`t {tfrm$90$ik$iimf „€)p$b`t {tfrm$90$ik$iimf „€)p$b`t {tfrm$90$dmd$iimf „€)p$b`t {tfrm$90${mmf$iimf „)mod$d`{pitki „)mfkim`tp `$dmd „„{tfrm$90${mmf$iimf„€)kimm {tfrm$90$dmd$iimf „€)pfpk$my}im d$i „€)k}dp {tfrm$90$ik$iimf „ „2[`dpmm ir`tidmt`k {}brf}t`om{/„„{}b$90$of$fmio{„€))d$9 {}b d$9 d$t „€))d$2 {}b d$2 d$r „€)k}dp$`f$b`t$kmmir pdp90$kirrp$0$b`t d$2 {}b$90$i „€))d$9 {}b d$9 )i$kfo{tiot 9 „{}b$90$i„€)pfpk$iftmr$omyt„€ )d$9 tr}okitm$tf$iimffrd d$9 „€))d$2 tr}okitm$tf$iimffrd d$2 „„`ok$90„€))d$2 idd d$2 )i$kfo{tiot 9 „€)k}dp$`f$b`t${mt pdp90$kirrp$0$b`t d$2 `ok$90$i „€))d$9 idd d$9 )i$kfo{tiot 9 „`ok$90$i„222666 Ommd{ tf kfdp}tm iod {ivm kirrp 0- kirrp 9 iod fvmrfmf fmio{/„€)pfpk$iftmr$omyt„€ )d$9 tr}okitm$tf$iimffrd d$9 „€))d$2 tr}okitm$tf$iimffrd d$2 „„dmk$90„€))d$2 {}b d$2 )i$kfo{tiot 9 „€)k}dp$`f$b`t$kmmir pdp90$kirrp$0$b`t d$2 `ok$90$i „€))d$9 idd d$9 )i$kfo{tiot 9 „dmk$90$i„222666 Ommd{ tf kfdp}tm iod {ivm kirrp 0- kirrp 9 iod fvmrfmf fmio{/„€)pfpk$iftmr$omyt„€ )d$9 tr}okitm$tf$iimffrd d$9 „€))d$2 tr}okitm$tf$iimffrd d$2 „ „2TROO- mtk/„„2PDP90$TM[T$DFD@F@KIT@FO {if}md bm tim 60 b`t{ ff tim fpkfdm/„2PDP90$TM[T$[F]RKM$B@T {if}md bm b`t 90 ff tim fpkfdm/„2PDP90$TM[T$[_IPPMD$B@T {if}md bm b`t 9 ff tim fpkfdm/„2PDP90$TM[T$KFOD@T@FO {if}md bm b`t{ 6 ff tim fpkfdm/„„ykt$90$tm{t„2Fmtki tim tm{t di{b frfd mffmkt`vm iddrm{{ fr dmdfrp/„€)d`{pitki pdp90$tm{t${f}rkm$b`t d$; d$90$tm{t${f}rkm „2[ip tim tm{t di{b/{ iimvm{ `f ipprfpr`itm/„€)k}dp$`f$b`t$kmmir$ykt$omyt pdp90$tm{t${ippmd$b`t d$; ykt$90$tm{t$9 „ ))d$9 d$t „€))d$t d$r „€))d$r d$9 „ykt$90$tm{t$9„2Fmtki tim IK tf bm tm{tmd/„€)kimm mfid$90$ik „2Irm iop di{bmd k`tp dodpo{o?„€++d$` kdd d$; k$t „€++d$` kdd d$; k${ „€+d`ppkt`k${`t$do{t pdp;0$topt$`odd`t`od d$0 d$;0$topt$`odd`t`od „ ++d$` `o{ d$` k$` „;Dkpko pto{o dot `odtodtp `d K@$„€+d`ppkt`k pdp;0$topt$dod`o``kt`od d$0 d$;0$topt$dod`o``kt`od „„+oo`ko`tp d$dod „+ptk{t$d`ppkt`k ; `dk`k`t${`t$do{t$k`t „d$;0$topt$po{`o„€+p$k`t {`t$;0$topt$`ddod „€+p$k`t ookd$;0$dod$t „+odd$d`ppkt`k „+oo`ko`tp `$dod „„{`t$;0$topt$`ddod„€+pop`$koto{$do{t„€ +d${ d$o „€++d$t k$po{o „„;Do``do tkotko{ to pk`p/ kdd dkpko do po$„;@koood t`tk +d`ppkt`k${`t$do{t pdp;0$topt$`odd`t`od d$0 d$;0$topt$`odd`t`od „;Tko tk`dd to topt `p tkotko{ D$@ `p dodpo{o$„„+oo`ko`tp d$dod „+ptk{t$d`ppkt`k ; 0 „d$;0$topt$`odd`t`od„€+{`t$;0$topt$; €;Do dot pk`p$„€+p$k`t {`t$;0$topt$pk`p$`o$0 „€+p$k`t {`t$;0$topt$pk`p$kotkpp „€+p$k`t {`t$;0$topt$pk`p$dot$0 „+odd$d`ppkt`k „+oo`ko`tp `$dod „„{`t$;0$topt$pk`p$dot$0„€+`dp${`t$do{t {`t$;0$topt$pk`p$kotkpp „€+pop`$o{ko d$` k$po{o „;;;??? T`oo tkkt to{k?„„{`t$;0$topt$pk`p$`o$0„€+pop`$dot$o{ko d$` k$po{o „{`t$;0$topt$pk`p$kotkpp„€+pop` +d$k kdd d$k +k$`odptkdt ; „„;@odpto kdd pto{o tko dot `odtodtp oo tko k``dokto{$„;@koood kp +d`ppkt`k pdp;0$topt$dod`o``kt`od d$0 d$;0$topt$dod`o``kt`od „„+oo`ko`tp d$dod „+ptk{t$d`ppkt`k ; `dk`k`t${`t$do{t$k`t „d$;0$topt$dod`o``kt`od„€+do{t$;0$`dpd „€+{`t$;0$topt$pot$po{o „€+{`t$;0$topt$`odpoododt „€+{`t$;0$topt$pot$odo „+odd$d`ppkt`k „+oo`ko`tp `$dod „„{`t$;0$topt$pot$po{o„€++d$; kdd`k d$; k$t „€++d$; kddca m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) xct-10-test-complement ((m-1) xor m-1 a-t) ((m-2) xor m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) xct-10-test-set-one ((m-1) ior m-1 a-t) ((m-2) ior m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) ;Stack instructions i-10-push (call load-10-ac) (call-xct-next load-10-mem-t) ((m-1) add m-1 (a-constant 1)) ((m-2) add m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) (call-xct-next store-10-ac) ((m-2) truncate-to-halfword m-2) (call-xct-next store-10-mem-t) ((m-e) m-2) (jump-not-equal m-1 a-zero next-10-insn) (jump pdl-10-overflow) i-10-pop (call-xct-next load-10-ac) ((c-pdl-buffer-pointer-push) m-e) (call-xct-next load-10-mem-t) ((m-e) m-2) (call-xct-next store-10-mem-t) ((m-e) c-pdl-buffer-pointer-pop) ((m-1) sub m-1 (a-constant 1)) ((m-2) sub m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (call store-10-ac) (jump-not-equal m-1 (a-constant -1) next-10-insn) (jump pdl-10-overflow) i-10-popj (call load-10-ac) (call-xct-next load-10-mem-t) ((m-e) m-2) ;Set the PC. ((m-b) add m-r a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Decrement the halves of the AC. ((m-1) sub m-1 (a-constant 1)) ((m-2) sub m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (call store-10-ac) (jump-not-equal m-1 (a-constant -1) next-10-insn) (jump pdl-10-overflow) i-10-pushj (call load-10-ac) (call-xct-next get-10-pc-and-flags-t) ((m-1) add m-1 (a-constant 1)) ((m-2) add m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) (call-xct-next store-10-ac) ((m-2) truncate-to-halfword m-2) (call-xct-next store-10-mem-t) ((m-e) m-2) (jump-not-equal m-1 a-zero next-10-insn) (jump pdl-10-overflow) ;Byte instructions. ;PDP10-BP-POSITION and PDP10-BP-SIZE are needed. i-10-ldb (call load-10-mem) ((m-3) m-1) ((m-e) m-2) ;Compute effective address of byte pointer, ;preserving M-A over it. ((c-pdl-buffer-pointer-push) m-a) (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ((m-a) c-pdl-buffer-pointer-pop) ;Fetch the word addressed by the byte pointer. (call load-10-mem) ;Shift it right so desired byte is on the bottom. ((m-t) pdp10-bp-position m-3) (call shift-10-right) ;Depending on whether byte size is more than 18, ;we must truncate M-1, or clear M-1 and truncate M-2. ;If it's exactly 0 or 18, we must clear one or both, but not truncate. ((m-t) pdp10-bp-size m-3) (jump-greater-than m-t (a-constant 18.) i-10-ldb-1) (jump-equal-xct-next m-t (a-constant 18.) i-10-ldb-store) ((m-1) a-zero) (jump-equal-xct-next m-t a-zero i-10-ldb-store-0) ((m-t) sub m-t (a-constant 1)) ((oa-reg-low) dpb m-t oal-bytl-1 a-zero) ((m-2) byte-inst m-2 a-zero) i-10-ldb-store (jump-xct-next next-10-insn) (call store-10-ac) i-10-ldb-store-0 ((m-2) a-zero) (jump-xct-next next-10-insn) (call store-10-ac) i-10-ldb-1 ((m-t) sub m-t (a-constant 19.)) ((oa-reg-low) dpb m-t oal-bytl-1 a-zero) ((m-1) byte-inst m-1 a-zero) (jump-xct-next next-10-insn) (call store-10-ac) i-10-ibp (call load-10-mem) ((m-t) pdp10-bp-position m-1) ((m-r) pdp10-bp-size m-1) ((m-t) sub m-t a-r) (call-less-than m-t a-zero i-10-ibp-next-word) ((m-1) dpb m-t pdp10-bp-position a-1) (jump-xct-next next-10-insn) (call store-10-mem) i-10-ibp-next-word ((m-1) add m-1 (a-constant 1)) (popj-after-next (m-t) (a-constant 36.)) ((m-t) sub m-t a-r) * LMFL(DIRECTORY "RMS" NAME "PDP10" TYPE "LISP" VERSION 13 BYTE-SIZE 10 CREATION-DATE 23075640633 AUTHOR "RMS") ;PDP-10 simulator microcode ;The simulator uses an internal accumulator for its arithmetic ;and most of its data transfers. ;This internal accumulator consists of M-1 and M-2. ;M-1 holds the left half of the 36-bit quantity and M-2 the right half. ;The other argument of arithmetic operations goes in ;the T register, composed of M-T and M-R. ;Instructions are executed out of the instruction register, ;which occupies M-3 and M-E. ;The AC field of the instruction is standardly placed in M-A, ;and the effective address is computed in M-E. ;The simulated PC lives in M-B; actually, that contains ;one less than the Q address of the left halfword of the next instruction. ;Jump instructions and PC saving instructions convert ;between this form of quantity and a pdp-10 address. ;The simulated PDP10 flags, except for CARRY 0, CARRY 1 and OVERFLOW, ;are kept in A-10-FLAGS. The flags can be used to help decode ;the reason why the microcode simulator exited. ;For example, the pdl overflow flag may be set. (def-data-field pdp10-sign-bit 1 17.) (def-data-field pdp10-carry-0-bit 1 18.) (def-data-field pdp10-index-field 4 0) (def-data-field pdp10-indirect-bit 1 4) (def-data-field pdp10-index-and-indirect 5 0) ;Indirect bit and index reg number. (def-data-field pdp10-ac-field 4 5) (def-data-field pdp10-opcode 9 9) ;These bits distinguish between test insns, logical insns, halfword insns, io insns, etc. (def-data-field pdp10-insn-class 3 15.) ;Distinguish logical vs halfword vs test, etc. ;For instructions which can be direct, immediate, to memory or to self (or both), ;these are the bits which say which one it is. (def-data-field pdp10-operation-direction 2 9.) ;These bits distinguish CAI vs CAM vs JUMP vs SKIP vs AOJ vs AOS vs SOJ vs SOS. (def-data-field pdp10-jump-subclass 3 12.) ;These bits control the jump condition of a CAI, CAM, etc. (def-data-field pdp10-jump-condition 3 9.) ;This bit, if set, means source of halfword insn is the right half. (def-data-field pdp10-halfword-fetch-right-bit 1 11.) ;This bit means destination is the right half. (def-data-field pdp10-halfword-store-right-bit 1 14.) ;These bits say what to do with the other halfword. (def-data-field pdp10-other-halfword-action 2 12.) ;These bits control what operation a logical instruction does. ;They are like arg 1 of BOOLE. (def-data-field pdp10-logical-operation 4 11.) ;In a test instruction, this bit, if one, says mask comes from memory. (def-data-field pdp10-test-source-bit 1 12.) ;This bit, if one, says swap the mask (whether from memory or from 0,,E) (def-data-field pdp10-test-swapped-bit 1 9) ;These bits say when to skip. (def-data-field pdp10-test-condition 2 10.) ;These bits say what to do to the selected bits in the accumulator. (def-data-field pdp10-test-modification 2 13.) ;Components of PDP10 byte pointers. (def-data-field pdp10-bp-position 6 12.) (def-data-field pdp10-bp-size 6 6) (locality a-mem) a-10-flags (0) (assign pdp10-overflow-flag 400000) (assign pdp10-carry-0-flag 200000) (assign pdp10-carry-1-flag 100000) (assign pdp10-floating-overflow-flag 040000) (assign pdp10-fpd-flag 020000) (assign pdp10-user-mode-flag 010000) (assign pdp10-floating-underflow-flag 000100) (assign pdp10-no-divide-flag 000040) (modulo 2) ;So halfword instructions can choose which half! ;Address of Q containing the left half of simulated memory location 0. ;The left halves of all PDP-10 memory words live in consecutive Qs. a-10-mem-0-left-addr (0) ;Address of Q containing the right half of simulated memory location 0. ;The right halves of all PDP-10 memory words live in consecutive Qs, ;immediately following the left halves. ;Thus, this address is always 1000000 more than that in a-10-mem-0-left-addr. a-10-mem-0-right-addr (0) ;Address of left half of memory location 20, ;used for testing the PC to see whether points at an AC. a-10-mem-20-left-addr (0) ;40 here so halfword instructions can choose which half! (modulo 40) ;These are the left halves of the pdp-10's simulated accumulators. a-10-ac-0-left (0) (modulo 20) ;These are the right halves. a-10-ac-0-right (0) (modulo 20) (locality i-mem) ;Load and store simulated accumulators (AC number in M-A) ;from the internal accumulator and the T register. ;Store the internal accumulator into the simulated accumulator ;whose number is in M-A. store-10-ac ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated accumulator whose number is in M-A ;into the internal accumulator. load-10-ac ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the T register into the simulated accumulator ;whose number is in M-A. store-10-ac-t ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Load the simulated accumulator whose number is in M-A ;into the T register. load-10-ac-t ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Load and store main memory (address in M-E) ;from the internal accumulator and the T register. ;Load the simulated memory location whose number is in M-E ;into the internal accumulator. load-10-mem (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-1) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-ac-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the internal accumulator into the simulated memory location ;whose address is in M-E. store-10-mem (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-1) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-2) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated memory location whose number is in M-E ;into the T register. load-10-mem-t (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-t) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-r) read-memory-data) load-10-ac-t-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Store the T register into the simulated memory location ;whose address is in M-E. store-10-mem-t (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-t) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-r) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-t-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Entry and exit. ;Call with (%pdp10-simulator
) ;It returns two values on the stack: the new pc and the new flags. enter-10-simulator (misc-inst-entry %pdp10-simulator) ((a-10-mem-0-left-addr) c-pdl-buffer-pointer-pop) ((a-10-flags) c-pdl-buffer-pointer-pop) ((m-e) c-pdl-buffer-pointer-pop) (jump jump-10-jump) ;Jump to the PC now in M-E. exit-10-simulator (call get-10-pc-and-flags-t) ;Get flags in M-T, pc in M-R. ((c-pdl-buffer-pointer-push) m-r) (popj) ;return flags to misc insn destination (push). pdl-10-overflow ((m-1) (a-constant pdp10-pdl-overflow-flag)) ((a-10-flags) ior m-1 a-10-flags) (jump exit-10-simulator) ;Set the simulated pc from a pdp-10 format pc in M-2. set-10-pc (popj-after-next (m-b) add m-2 (a-constant -1)) ((m-b) add m-b a-10-mem-0-left-addr) ;Get the pc and flags in internal accumulator (m-1 and m-2) get-10-pc-and-flags ;;;??? ;Get the pc in pdp-10 form in M-2. get-10-pc (popj-after-next (m-2) sub m-b a-10-mem-0-leftaddr) ((m-2) m+1 m-2) ;Get the pc and flags in other accumulator (m-t and m-r) get-10-pc-and-flags ;;;??? (popj-after-next (m-r) sub m-b a-10-mem-0-leftaddr) ((m-r) m+1 m-r) ;Come here to jump to effective address and execute next instruction. jump-10-jump ((m-b) add m-e a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Loop point for executing the next pdp-10 instruction. next-10-insn (jump-less-than m-b a-10-mem-20-addr xct-10-ac) ;Check for ACs referenced as memory. ((vma-start-read m-b) m+1 m-b) ;Increment pc and fetch lh of insn. (check-page-read) ((m-3) read-memory-data) ((vma-start-read) add m-b (a-constant 1000000)) (check-page-read) ((m-e) read-memory-data) ;Compute the effective address in M-E ;for the instruction in the instruction register (M-3, M-E). eff-addr-comp (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ;Fetch the next instruction from an accumulator. xct-10-ac (call get-10-pc) ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-3) a-10-ac-0-left) ((oa-reg-high) dpb m-a oah-a-src a-zero) (jump-xct-next eff-addr-comp) ((m-e) a-10-ac-0-right) (locality d-mem) (start-dispatch 5 0) d-10-index-and-indirect (xct-10-insn-1) (repeat 17 (do-10-indexing)) (do-10-indirect) (repeat 17 (do-10-indexing)) (end-dispatch) (locality i-mem) ;Perform indexing on address field in M-E ;with index register number in M-A. do-10-indexing ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-e) add m-e a-10-ac-0-right) (jump-if-bit-clear-xct-next pdp10-indirect-bit xct-10-insn) ((m-e) truncate-to-halfword m-e) ;Perform indirection, and merge the indirect pointer ;into the instruction register. Then go to begin again to execute the instruction. do-10-indirect (call load-10-mem) ((m-e) m-2) (jump-xct-next eff-addr-comp) ((m-3) mask-field pdp10-opcode m-3 a-1) ;Execute the instruction in M-3 with effective address in M-E ;The execution routine finds the accumulator in M-A. xct-10-insn (dispatch-xct-next pdp10-insn-class m-3 d-10-insn-class) ((m-a) pdp10-ac-field m-3) ;Dispatch on major classes of pdp-10 instructions. (locality d-mem) (start-dispatch 3 0) d-10-insn-class (xct-10-uuo) (xct-10-random) (xct-10-move) (xct-10-jump) (xct-10-logical) (xct-10-halfword) (xct-10-test) (xct-10-uuo) (end-dispatch) (locality i-mem) ;Do the store for an instruction like ADD ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-both (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-both) (end-dispatch) (locality i-mem) store-10-both (call store-10-mem) (jump store-10-ac) ;Do the store for an instruction like MOVE ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-self) (end-dispatch) (locality i-mem) store-10-self (call store-10-mem) (popj-equal m-a) (jump store-10-ac) ;The XCT instruction. i-10-xct (call load-10-mem) ((m-3) m-1) ((m-e) m-2) (jump eff-addr-comp) i-10-lsh (call load-10-ac-t) ((m-1) dpb m-t ?? a-zero) ((m-1) dpb m-r ?? a-1) ((m-2) dpb m-t ?? a-zero) ((m-2) dpb m-r ?? a-2) (call store-10-ac-t) (jump next-10-insn) ;Arithmetic Jump and Skip Instructions xct-10-jump ;Dispatch on jump vs skip, whether to increment, etc. (dispatch pdp10-jump-subclass m-3 d-10-jump-subclass) (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-subclass (i-10-cai) (i-10-cam) (i-10-jump) (i-10-skip) (i-10-aoj) (i-10-aos) (i-10-soj) (i-10-sos) (locality i-mem) ;Depending on type of instruction, ;we get our argument from somewhere ;and then supply one of these as I-ARG when we test the condition. (assign cond-10-jump 0) (assign cond-10-skip 1) i-10-cam (call load-10-mem-t) (call load-10-ac) (call sub-10-no-flags) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-cai (call load-10-ac) ((m-2) sub m-2 a-e) (jump-if-bit-clear pdp10-carry-0-bit m-2 i-10-cai-1) ((m-1) sub m-1 (a-constant 1)) i-10-cai-1 ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-jump (call load-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-skip (call load-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aoj (call load-10-ac) (call inc-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aos (call load-10-mem) (call inc-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-soj (call load-10-ac) (call dec-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-sos (call load-10-mem) (call dec-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;Jump or Skip on Sign of Internal Accumulator. ;Do it with an instruction ; (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;The I-ARG should be COND-10-JUMP to jump, COND-10-SKIP to skip. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-condition (next-10-insn) ;Jump never (cond-10-less) (cond-10-equal) (cond-10-le) (cond-10-always) (cond-10-ge) (cond-10-ne) (cond-10-grtr) (end-dispatch) (locality i-mem) cond-10-le (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) cond-10-equal (jump-not-equal m-1 next-10-insn) (jump-not-equal m-2 next-10-insn) (jump cond-10-always) cond-10-grtr (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-ne (jump-not-equal m-1 cond-10-always) (jump-not-equal m-2 cond-10-always) (jump next-10-insn) cond-10-less (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) (jump next-10-insn) cond-10-ge (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-always (dispatch-xct-next read-i-arg d-10-jump-action) ((m-b) add m-b (a-constant 1)) ;The last instruction does a skip. ;If we are really jumping, it makes no difference. ;If we want to skip, we can go straight to the instruction loop. (locality d-mem) (start-dispatch 1 0) d-10-jump-action (jump-10-jump) (next-10-insn) (end-dispatch) (locality i-mem) ;Halfword Instructions ;Subroutines ;Store M-2 in half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. store-10-ac-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-ac-half) (popj-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) (locality d-mem) (start-dispatch 1 0) d-store-10-ac-half (store-10-ac-left) (store-10-ac-right) (end-dispatch) store-10-ac-left ((a-10-ac-0-left) m-2) store-10-ac-right ((a-10-ac-0-right) m-2) ;Load M-2 from half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. load-10-ac-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-ac-half) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) (locality d-mem) (start-dispatch 1 0) d-load-10-ac-half (load-10-ac-left) (load-10-ac-right) (end-dispatch) load-10-ac-left ((m-2) a-10-ac-0-left) load-10-ac-right ((m-2) a-10-ac-0-right) ;Store M-2 in half of the simulated memory location with address in M-E. ;Which half is controlled by the instruction register. store-10-mem-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-mem-half) ((write-memory-data) m-2) (locality d-mem) (start-dispatch 1 0) d-store-10-mem-half (store-10-mem-left) (store-10-mem-right) (end-dispatch) store-10-mem-left ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) (popj) store-10-mem-right ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) ;Load M-2 from half of the simulated memory location whose address is in M-E. ;Which half is controlled by the instruction register. load-10-mem-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-mem-half) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d-load-10-mem-half (load-10-mem-left) (load-10-mem-right) (end-dispatch) load-10-mem-left ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-mem-right ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) ;Load M-2 from half of the immediate arg. ;Which half is controlled by the instruction register. load-10-immed-half (dispatch pdp10-halfword-fetch-right-bit m-3 d-load-10-immed-half) (locality d-mem) (start-dispatch 1 0) d-load-10-immed-half (load-10-immed-left) (load-10-immed-right) (end-dispatch) load-10-immed-left (popj (m-2) a-zero) load-10-immed-right (popj (m-2) m-e) xct-10-halfword (dispatch pdp10-operation-direction m-3 d-10-load-in-out-or-both-half) (dispatch pdp10-other-halfword-action m-3 d-other-10-halfword) (jump-if-bit-set pdp10-halfword-store-right-bit m-3 xct-10-halfword-1) ((m-c) m-1) ((m-1) m-2) ((m-2) m-c) xct-10-halfword-1 (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self) (jump next-10-insn) (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-load-in-out-or-both-half (p-bit load-10-mem-half) (p-bit load-immed-arg-half) (p-bit load-10-ac-half) (p-bit load-10-mem-half) (end-dispatch) (locality i-mem) ;Clear, set or sign-extend the "other" half, ;which right now is always in M-1. (locality d-mem) (start-dispatch 2 inhibit-xct-next-bit) d-other-10-halfword (xct-10-halfword-preserve-other-half) (p-bit other-10-halfword-clear) (p-bit other-10-halfword-set) (p-bit other-10-halfword-extend) (end-dispatch) (locality i-mem) other-10-halfword-extend (jump-if-bit-set pdp10-sign-bit m-2 other-10-halfword-set) other-10-halfword-clear (popj (m-1) a-zero) other-10-halfword-set (popj (m-1) (a-constant 777777)) xct-10-halfword-preserve-other-half (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self-half) (jump next-10-insn) ;Do the store for an instruction like HRL ;which only wants to store one halfword ;and can do it in the AC, in memory or in self. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self-halfword (p-bit store-10-ac-half) (p-bit store-10-ac-half) (p-bit store-10-mem-half) (p-bit store-10-self-half) (end-dispatch) (locality i-mem) store-10-self-half (call store-10-mem-half) (popj-equal m-a) (jump store-10-ac-half) ;Simple arithmetic subroutines. sub-10-no-flags ((m-1) sub m-1 m-t) ((m-2) sub m-2 m-r) (jump-if-bit-clear pdp10-carry-0-bit m-2 sub-10-a) ((m-1) sub m-1 (a-constant 1)) sub-10-a (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) inc-10 ((m-2) add m-2 (a-constant 1)) (jump-if-bit-set pdp10-carry-0-bit m-2 inc-10-a) ((m-1) add m-1 (a-constant 1)) inc-10-a ;;;??? Needs to compute and save carry 0, carry 1 and overflow flags. (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) dec-10 ((m-2) sub m-2 (a-constant 1)) (jump-if-bit-clear pdp10-carry-0-bit m-2 inc-10-a) ((m-1) add m-1 (a-constant 1)) dec-10-a ;;;??? Needs to compute and save carry 0, carry 1 and overflow flags. (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) ;AND, etc. xct-10-logical (call load-10-ac) (dispatch pdp10-operation-direction m-3 d-10-load-in-out-or-both) ((m-c) pdp10-logical-operation m-3) ((oa-reg-low) dpb m-c oal-aluf a-zero) ((m-1) setz m-1 a-t) ((oa-reg-low) dpb m-c oal-aluf a-zero) ((m-2) setz m-2 a-r) (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self) (jump next-10-insn) ;TRNN, etc. xct-10-test ;Fetch the test mask from effective address or memory. (dispatch pdp10-test-source-bit m-3 d-10-test-source) ;Swap the test mask's halves if appropriate. (jump-if-bit-clear-xct-next pdp10-test-swapped-bit m-3 xct-10-test-1) ((m-1) m-t) ((m-t) m-r) ((m-r) m-1) xct-10-test-1 ;Fetch the AC to be tested. (call load-10-ac) ;Are any masked bits nonzero? ((m-i) and m-1 a-t) ((m-j) and m-2 a-r) (dispatch-xct-next pdp10-test-condition m-3 d-10-test-condition) ((m-i) ior m-i a-j) ;Maybe store new contents in AC. (dispatch pdp10-test-modification m-3 d-10-test-modification) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d-10-test-source (p-bit xct-10-test-immed) (p-bit load-10-mem-t) (end-dispatch) (locality i-mem) xct-10-test-immed (popj-after-next (m-r) m-e) ((m-t) a-zero) ;Decide whether to skip, and maybe do so. ;Called with (dispatch-xct-next pdp10-test-condition m-3 d-10-test-condition) ;The thing to test is whether M-I is nonzero. (locality d-mem) (start-dispatch 2 0) d-10-test-condition (xct-10-test-2) ;Do not skip. (p-bit xct-10-test-skip-if-0) (p-bit xct-10-test-skip-always) (p-bit xct-10-test-skip-not-0) (end-dispatch) (locality i-mem) xct-10-test-skip-not-0 (jump-xct-next xct-10-test-skip-always) (popj-equal m-i a-zero) ;;;??? Will that work? xct-10-test-skip-if-0 (popj-not-equal m-i a-zero) xct-10-test-skip-always (popj (m-b) add m-b (a-constant 1)) ;Compute and store the new contents of the accumulator. ;Called by (dispatch pdp10-test-modification m-3 d-10-test-modification) (locality d-mem) (start-dispatch 2 inhibit-xct-next-bit) d-10-test-modification (next-10-insn) (xct-10-test-set-zero) (xct-10-test-complement) (xct-10-test-set-one) (end-dispatch) (locality i-mem) xct-10-test-set-zero ((m-1) andca m-1 a-t) ((m-2) andca m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) xct-10-test-complement ((m-1) xor m-1 a-t) ((m-2) xor m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) xct-10-test-set-one ((m-1) ior m-1 a-t) ((m-2) ior m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) ;Stack instructions i-10-push (call load-10-ac) (call-xct-next load-10-mem-t) ((m-1) add m-1 (a-constant 1)) ((m-2) add m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) (call-xct-next store-10-ac) ((m-2) truncate-to-halfword m-2) (call-xct-next store-10-mem-t) ((m-e) m-2) (jump-not-equal m-1 a-zero next-10-insn) (jump pdl-10-overflow) i-10-pop (call-xct-next load-10-ac) ((c-pdl-buffer-pointer-push) m-e) (call-xct-next load-10-mem-t) ((m-e) m-2) (call-xct-next store-10-mem-t) ((m-e) c-pdl-buffer-pointer-pop) ((m-1) sub m-1 (a-constant 1)) ((m-2) sub m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (call store-10-ac) (jump-not-equal m-1 (a-constant -1) next-10-insn) (jump pdl-10-overflow) i-10-popj (call load-10-ac) (call-xct-next load-10-mem-t) ((m-e) m-2) ;Set the PC. ((m-b) add m-r a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Decrement the halves of the AC. ((m-1) sub m-1 (a-constant 1)) ((m-2) sub m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (call store-10-ac) (jump-not-equal m-1 (a-constant -1) next-10-insn) (jump pdl-10-overflow) i-10-pushj (call load-10-ac) (call-xct-next get-10-pc-and-flags-t) ((m-1) add m-1 (a-constant 1)) ((m-2) add m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) (call-xct-next store-10-ac) ((m-2) truncate-to-halfword m-2) (call-xct-next store-10-mem-t) ((m-e) m-2) (jump-not-equal m-1 a-zero next-10-insn) (jump pdl-10-overflow) ;Byte instructions. i-10-ibp (call inc-10-bp) (jump next-10-insn ;Increment the byte pointer in the PDP-10 memory location ;addressed by M-E. Store it back in that memory location. inc-10-bp (call load-10-mem) ((m-t) pdp10-bp-position m-1) ((m-r) pdp10-bp-size m-1) ((m-t) sub m-t a-r) (call-less-than m-t a-zero i-10-ibp-next-word) ((m-1) dpb m-t pdp10-bp-position a-1) (jump store-10-mem) i-10-ibp-next-word ((m-1) add m-1 (a-constant 1)) (popj-after-next (m-t) (a-constant 36.)) ((m-t) sub m-t a-r) i-10-ildb (call inc-10-bp) ((m-1) (a-constant pdp10-fpd-flag)) ((a-10-flags) ior m-1 a-10-flags) (jump i-10-ldb-0) i-10-ldb (call load-10-mem) i-10-ldb-0 ((m-3) m-1) ((m-e) m-2) ;Compute effective address of byte pointer, ;preserving M-A over it. ((c-pdl-buffer-pointer-push) m-a) (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ((m-a) c-pdl-buffer-pointer-pop) ;Fetch the word addressed by the byte pointer. (call load-10-mem) ((m-1) (a-constant pdp10-fpd-flag)) ((a-10-flags) andcm m-1 a-10-flags) ;Shift it right so desired byte is on the bottom. ((m-c) pdp10-bp-position m-3) (call shift-10-right) ;Depending on whether byte size is more than 18, ;we must truncate M-1, or clear M-1 and truncate M-2. ;If it's exactly 0 or 18, we must clear one or both, but not truncate. ((m-c) pdp10-bp-size m-3) (call truncate-10-byte) (jump-xct-next next-10-insn) (call store-10-ac) ;Truncate the PDP-10 quantity in the A register ;to the length specified in M-C. truncate-10-byte (jump-greater-than m-c (a-constant 18.) truncate-10-byte-1) (popj-equal-xct-next m-c (a-constant 18.)) ((m-1) a-zero) (jump-equal-xct-next m-c a-zero truncate-10-byte-0-length) ((m-c) sub m-c (a-constant 1)) (popj-after-next (oa-reg-low) dpb m-c oal-bytl-1 a-zero) ((m-2) byte-inst m-2 a-zero) truncate-10-byte-0-length (popj (m-2) a-zero) truncate-10-byte-1 ((m-c) sub m-c (a-constant 19.)) (popj-after-next (oa-reg-low) dpb m-c oal-bytl-1 a-zero) ((m-1) byte-inst m-1 a-zero) i-10-idpb (call inc-10-bp) ((m-1) (a-constant pdp10-fpd-flag)) ((a-10-flags) ior m-1 a-10-flags) (jump i-10-dpb-0) i-10-dpb (call load-10-mem) i-10-dpb-0 ((m-3) m-1) ((m-e) m-2) ;Compute effective address of byte pointer, ;preserving M-A over it. ((c-pdl-buffer-pointer-push) m-a) (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ((m-a) c-pdl-buffer-pointer-pop) ;Fetch the word addressed by the byte pointer. (call load-10-mem-t) ((m-1) (a-constant pdp10-fpd-flag)) ((a-10-flags) andcm m-1 a-10-flags) ;Now zero out the byte we want to replace. ;Load -1 into the A-register, and shift/truncate it to the byte we want. ((m-1) a-minus-one) ((m-2) a-minus-one) (call-xct-next shift-10-left) ((m-c) pdp10-bp-position m-3) (call-xct-next truncate-10-byte) ((m-c) pdp10-bp-size m-3) ;Now clear that byte in the T register. ((m-t) andca m-t a-1) ((m-r) andca m-r a-1) ;Get the byte into A register, truncate, and shift into position. (call load-10-ac) (call-xct-next shift-10-left) ((m-c) pdp10-bp-position m-3) (call-xct-next truncate-10-byte) ((m-c) pdp10-bp-size m-3) ;Merge it into T register. ((m-t) ior m-t a-1) ((m-r) ior m-r a-2) ;Store the result. (jump-xct-next next-10-insn) (call store-10-mem-t) * LMFL(DIRECTORY "RMS" NAME "PDP10" TYPE "LISP" VERSION 14 BYTE-SIZE 10 CREATION-DATE 23075640637 AUTHOR "RMS") ;PDP-10 simulator microcode ;The simulator uses an internal accumulator for its arithmetic ;and most of its data transfers. ;This internal accumulator consists of M-1 and M-2. ;M-1 holds the left half of the 36-bit quantity and M-2 the right half. ;The other argument of arithmetic operations goes in ;the T register, composed of M-T and M-R. ;Instructions are executed out of the instruction register, ;which occupies M-3 and M-E. ;The AC field of the instruction is standardly placed in M-A, ;and the effective address is computed in M-E. ;The simulated PC lives in M-B; actually, that contains ;one less than the Q address of the left halfword of the next instruction. ;Jump instructions and PC saving instructions convert ;between this form of quantity and a pdp-10 address. ;The simulated PDP10 flags are kept in A-10-FLAGS. ;However, the CARRY 0, CARRY 1 and OVERFLOW flags can also ;be considered set if ...??? ;GET-10-PC-AND-FLAGS-T merges those things into A-10-FLAGS ;before returning the flags. (def-data-field pdp10-sign-bit 1 17.) (def-data-field pdp10-carry-0-bit 1 18.) (def-data-field pdp10-index-field 4 0) (def-data-field pdp10-indirect-bit 1 4) (def-data-field pdp10-index-and-indirect 5 0) ;Indirect bit and index reg number. (def-data-field pdp10-ac-field 4 5) (def-data-field pdp10-opcode 9 9) ;These bits distinguish between test insns, logical insns, halfword insns, io insns, etc. (def-data-field pdp10-insn-class 3 15.) ;Distinguish logical vs halfword vs test, etc. ;For instructions which can be direct, immediate, to memory or to self (or both), ;these are the bits which say which one it is. (def-data-field pdp10-operation-direction 2 9.) ;These bits distinguish CAI vs CAM vs JUMP vs SKIP vs AOJ vs AOS vs SOJ vs SOS. (def-data-field pdp10-jump-subclass 3 12.) ;These bits control the jump condition of a CAI, CAM, etc. (def-data-field pdp10-jump-condition 3 9.) ;This bit, if set, means source of halfword insn is the right half. (def-data-field pdp10-halfword-fetch-right-bit 1 11.) ;This bit means destination is the right half. (def-data-field pdp10-halfword-store-right-bit 1 14.) ;These bits say what to do with the other halfword. (def-data-field pdp10-other-halfword-action 2 12.) ;These bits control what operation a logical instruction does. ;They are like arg 1 of BOOLE. (def-data-field pdp10-logical-operation 4 11.) ;In a test instruction, this bit, if one, says mask comes from memory. (def-data-field pdp10-test-source-bit 1 12.) ;This bit, if one, says swap the mask (whether from memory or from 0,,E) (def-data-field pdp10-test-swapped-bit 1 9) ;These bits say when to skip. (def-data-field pdp10-test-condition 2 10.) ;These bits say what to do to the selected bits in the accumulator. (def-data-field pdp10-test-modification 2 13.) ;This bit set in a JRST instruction makes it a JRSTF. (def-data-field pdp10-jrstf-bit 1 6) ;Components of PDP10 byte pointers. (def-data-field pdp10-bp-position 6 12.) (def-data-field pdp10-bp-size 6 6) (locality a-mem) a-10-flags (0) (assign pdp10-overflow-flag 400000) (assign pdp10-carry-0-flag 200000) (assign pdp10-carry-1-flag 100000) (assign pdp10-floating-overflow-flag 040000) (assign pdp10-fpd-flag 020000) (assign pdp10-user-mode-flag 010000) (assign pdp10-floating-underflow-flag 000100) (assign pdp10-no-divide-flag 000040) (modulo 2) ;So halfword instructions can choose which half! ;Address of Q containing the left half of simulated memory location 0. ;The left halves of all PDP-10 memory words live in consecutive Qs. a-10-mem-0-left-addr (0) ;Address of Q containing the right half of simulated memory location 0. ;The right halves of all PDP-10 memory words live in consecutive Qs, ;immediately following the left halves. ;Thus, this address is always 1000000 more than that in a-10-mem-0-left-addr. a-10-mem-0-right-addr (0) ;Address of left half of memory location 20, ;used for testing the PC to see whether points at an AC. a-10-mem-20-left-addr (0) ;40 here so halfword instructions can choose which half! (modulo 40) ;These are the left halves of the pdp-10's simulated accumulators. a-10-ac-0-left (0) (modulo 20) ;These are the right halves. a-10-ac-0-right (0) (modulo 20) (locality i-mem) ;Load and store simulated accumulators (AC number in M-A) ;from the internal accumulator and the T register. ;Store the internal accumulator into the simulated accumulator ;whose number is in M-A. store-10-ac ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated accumulator whose number is in M-A ;into the internal accumulator. load-10-ac ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the T register into the simulated accumulator ;whose number is in M-A. store-10-ac-t ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Load the simulated accumulator whose number is in M-A ;into the T register. load-10-ac-t ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Load and store main memory (address in M-E) ;from the internal accumulator and the T register. ;Load the simulated memory location whose number is in M-E ;into the internal accumulator. load-10-mem (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-1) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-ac-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the internal accumulator into the simulated memory location ;whose address is in M-E. store-10-mem (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-1) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-2) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-1) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-2) ;Load the simulated memory location whose number is in M-E ;into the T register. load-10-mem-t (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-t) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-r) read-memory-data) load-10-ac-t-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Store the T register into the simulated memory location ;whose address is in M-E. store-10-mem-t (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) m-t) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) m-r) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-t-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) m-t) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) m-r) ;Entry and exit. ;Call with (%pdp10-simulator
) ;It returns two values on the stack: the new pc and the new flags. enter-10-simulator (misc-inst-entry %pdp10-simulator) ((a-10-mem-0-left-addr) c-pdl-buffer-pointer-pop) ((a-10-flags) c-pdl-buffer-pointer-pop) ((m-e) c-pdl-buffer-pointer-pop) (jump jump-10-jump) ;Jump to the PC now in M-E. exit-10-simulator (call get-10-pc-and-flags-t) ;Get flags in M-T, pc in M-R. ((c-pdl-buffer-pointer-push) m-r) (popj) ;return flags to misc insn destination (push). pdl-10-overflow ((m-1) (a-constant pdp10-pdl-overflow-flag)) ((a-10-flags) ior m-1 a-10-flags) (jump exit-10-simulator) ;Set the simulated pc from a pdp-10 format pc in M-2. set-10-pc (popj-after-next (m-b) add m-2 (a-constant -1)) ((m-b) add m-b a-10-mem-0-left-addr) ;Get the pc and flags in internal accumulator (m-1 and m-2) get-10-pc-and-flags ;;;??? ;Get the pc in pdp-10 form in M-2. get-10-pc (popj-after-next (m-2) sub m-b a-10-mem-0-leftaddr) ((m-2) m+1 m-2) ;Get the pc and flags in other accumulator (m-t and m-r) get-10-pc-and-flags ;;;??? (popj-after-next (m-r) sub m-b a-10-mem-0-leftaddr) ((m-r) m+1 m-r) ;Come here to jump to effective address and execute next instruction. jump-10-jump ((m-b) add m-e a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Loop point for executing the next pdp-10 instruction. next-10-insn (jump-less-than m-b a-10-mem-20-addr xct-10-ac) ;Check for ACs referenced as memory. ((vma-start-read m-b) m+1 m-b) ;Increment pc and fetch lh of insn. (check-page-read) ((m-3) read-memory-data) ((vma-start-read) add m-b (a-constant 1000000)) (check-page-read) ((m-e) read-memory-data) ;Compute the effective address in M-E ;for the instruction in the instruction register (M-3, M-E). eff-addr-comp (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ;Fetch the next instruction from an accumulator. xct-10-ac (call get-10-pc) ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-3) a-10-ac-0-left) ((oa-reg-high) dpb m-a oah-a-src a-zero) (jump-xct-next eff-addr-comp) ((m-e) a-10-ac-0-right) (locality d-mem) (start-dispatch 5 0) d-10-index-and-indirect (xct-10-insn) (repeat 17 (do-10-indexing)) (do-10-indirect) (repeat 17 (do-10-indexing)) (end-dispatch) (start-dispatch 5 0) d-10-index-and-indirect-not-first-time (xct-10-insn) (repeat 17 (do-10-indexing-after-indirect)) (do-10-indirect) (repeat 17 (do-10-indexing-after-indirect)) (end-dispatch) (locality i-mem) ;Perform indexing on address field in M-E ;with index register number in M-A. do-10-indexing ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-e) add m-e a-10-ac-0-right) (jump-if-bit-clear-xct-next pdp10-indirect-bit m-3 xct-10-insn) ((m-e) truncate-to-halfword m-e) ;Perform indexing on address field in M-E after indirection ;index register number in M-A. ;The difference is where we test the indirect bit. do-10-indexing-after-indirect ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-e) add m-e a-10-ac-0-right) (jump-if-bit-clear-xct-next pdp10-indirect-bit m-1 xct-10-insn) ((m-e) truncate-to-halfword m-e) ;Perform indirection, and merge the indirect pointer ;into the instruction register. Then decide whether ;additional indirection or indexing is needed. ;We do not clobber M-3. This is for the sake of JRSTF! do-10-indirect (call load-10-mem) ((m-e) m-2) (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect-not-first-time) ((m-a) pdp10-index-field m-1) ;Execute the instruction in M-3 with effective address in M-E ;The execution routine finds the accumulator in M-A. xct-10-insn (dispatch-xct-next pdp10-insn-class m-3 d-10-insn-class) ((m-a) pdp10-ac-field m-3) ;Dispatch on major classes of pdp-10 instructions. (locality d-mem) (start-dispatch 3 0) d-10-insn-class (xct-10-uuo) (xct-10-random) (xct-10-move) (xct-10-jump) (xct-10-logical) (xct-10-halfword) (xct-10-test) (xct-10-uuo) (end-dispatch) (locality i-mem) ;Do the store for an instruction like ADD ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-both (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-both) (end-dispatch) (locality i-mem) store-10-both (call store-10-mem) (jump store-10-ac) ;Do the store for an instruction like MOVE ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-self) (end-dispatch) (locality i-mem) store-10-self (call store-10-mem) (popj-equal m-a) (jump store-10-ac) ;Arithmetic Jump and Skip Instructions xct-10-jump ;Dispatch on jump vs skip, whether to increment, etc. (dispatch pdp10-jump-subclass m-3 d-10-jump-subclass) (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-subclass (i-10-cai) (i-10-cam) (i-10-jump) (i-10-skip) (i-10-aoj) (i-10-aos) (i-10-soj) (i-10-sos) (locality i-mem) ;Depending on type of instruction, ;we get our argument from somewhere ;and then supply one of these as I-ARG when we test the condition. (assign cond-10-jump 0) (assign cond-10-skip 1) i-10-cam (call load-10-mem-t) (call load-10-ac) (call sub-10-no-flags) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-cai (call load-10-ac) ((m-2) sub m-2 a-e) (jump-if-bit-clear pdp10-carry-0-bit m-2 i-10-cai-1) ((m-1) sub m-1 (a-constant 1)) i-10-cai-1 ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-jump (call load-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-skip (call load-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aoj (call load-10-ac) (call inc-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aos (call load-10-mem) (call inc-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-soj (call load-10-ac) (call dec-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-sos (call load-10-mem) (call dec-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;Jump or Skip on Sign of Internal Accumulator. ;Do it with an instruction ; (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;The I-ARG should be COND-10-JUMP to jump, COND-10-SKIP to skip. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-condition (next-10-insn) ;Jump never (cond-10-less) (cond-10-equal) (cond-10-le) (cond-10-always) (cond-10-ge) (cond-10-ne) (cond-10-grtr) (end-dispatch) (locality i-mem) cond-10-le (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) cond-10-equal (jump-not-equal m-1 next-10-insn) (jump-not-equal m-2 next-10-insn) (jump cond-10-always) cond-10-grtr (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-ne (jump-not-equal m-1 cond-10-always) (jump-not-equal m-2 cond-10-always) (jump next-10-insn) cond-10-less (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) (jump next-10-insn) cond-10-ge (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-always (dispatch-xct-next read-i-arg d-10-jump-action) ((m-b) add m-b (a-constant 1)) ;The last instruction does a skip. ;If we are really jumping, it makes no difference. ;If we want to skip, we can go straight to the instruction loop. (locality d-mem) (start-dispatch 1 0) d-10-jump-action (jump-10-jump) (next-10-insn) (end-dispatch) (locality i-mem) ;Halfword Instructions ;Subroutines ;Store M-2 in half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. store-10-ac-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-ac-half) (popj-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) (locality d-mem) (start-dispatch 1 0) d-store-10-ac-half (store-10-ac-left) (store-10-ac-right) (end-dispatch) store-10-ac-left ((a-10-ac-0-left) m-2) store-10-ac-right ((a-10-ac-0-right) m-2) ;Load M-2 from half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. load-10-ac-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-ac-half) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) (locality d-mem) (start-dispatch 1 0) d-load-10-ac-half (load-10-ac-left) (load-10-ac-right) (end-dispatch) load-10-ac-left ((m-2) a-10-ac-0-left) load-10-ac-right ((m-2) a-10-ac-0-right) ;Store M-2 in half of the simulated memory location with address in M-E. ;Which half is controlled by the instruction register. store-10-mem-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-mem-half) ((write-memory-data) m-2) (locality d-mem) (start-dispatch 1 0) d-store-10-mem-half (store-10-mem-left) (store-10-mem-right) (end-dispatch) store-10-mem-left ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) (popj) store-10-mem-right ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) ;Load M-2 from half of the simulated memory location whose address is in M-E. ;Which half is controlled by the instruction register. load-10-mem-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-mem-half) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d-load-10-mem-half (load-10-mem-left) (load-10-mem-right) (end-dispatch) load-10-mem-left ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-mem-right ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) ;Load M-2 from half of the immediate arg. ;Which half is controlled by the instruction register. load-10-immed-half (dispatch pdp10-halfword-fetch-right-bit m-3 d-load-10-immed-half) (locality d-mem) (start-dispatch 1 0) d-load-10-immed-half (load-10-immed-left) (load-10-immed-right) (end-dispatch) load-10-immed-left (popj (m-2) a-zero) load-10-immed-right (popj (m-2) m-e) xct-10-halfword (dispatch pdp10-operation-direction m-3 d-10-load-in-out-or-both-half) (dispatch pdp10-other-halfword-action m-3 d-other-10-halfword) (jump-if-bit-set pdp10-halfword-store-right-bit m-3 xct-10-halfword-1) ((m-c) m-1) ((m-1) m-2) ((m-2) m-c) xct-10-halfword-1 (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self) (jump next-10-insn) (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-load-in-out-or-both-half (p-bit load-10-mem-half) (p-bit load-immed-arg-half) (p-bit load-10-ac-half) (p-bit load-10-mem-half) (end-dispatch) (locality i-mem) ;Clear, set or sign-extend the "other" half, ;which right now is always in M-1. (locality d-mem) (start-dispatch 2 inhibit-xct-next-bit) d-other-10-halfword (xct-10-halfword-preserve-other-half) (p-bit other-10-halfword-clear) (p-bit other-10-halfword-set) (p-bit other-10-halfword-extend) (end-dispatch) (locality i-mem) other-10-halfword-extend (jump-if-bit-set pdp10-sign-bit m-2 other-10-halfword-set) other-10-halfword-clear (popj (m-1) a-zero) other-10-halfword-set (popj (m-1) (a-constant 777777)) xct-10-halfword-preserve-other-half (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self-half) (jump next-10-insn) ;Do the store for an instruction like HRL ;which only wants to store one halfword ;and can do it in the AC, in memory or in self. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self-halfword (p-bit store-10-ac-half) (p-bit store-10-ac-half) (p-bit store-10-mem-half) (p-bit store-10-self-half) (end-dispatch) (locality i-mem) store-10-self-half (call store-10-mem-half) (popj-equal m-a) (jump store-10-ac-half) ;Simple arithmetic subroutines. sub-10-no-flags ((m-1) sub m-1 m-t) ((m-2) sub m-2 m-r) (jump-if-bit-clear pdp10-carry-0-bit m-2 sub-10-a) ((m-1) sub m-1 (a-constant 1)) sub-10-a (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) inc-10 ((m-2) add m-2 (a-constant 1)) (jump-if-bit-set pdp10-carry-0-bit d$2 `ok$90$i „€))d$9 idd d$9 )i$kfo{tiot 9 „`ok$90$i„222666 Ommd{ tf kfdp}tm iod {ivm kirrp 0- kirrp 9 iod fvmrfmf fmio{/„€)pfpk$iftmr-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) dec-10 ((m-2) sub m-2 (a-constant 1)) (jump-if-bit-clear pdp10-carry-0-bit m-2 inc-10-a) ((m-1) add m-1 (a-constant 1)) dec-10-a ;;;??? Needs to compute and save carry 0, carry 1 and overflow flags. (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) ;AND, etc. xct-10-logical (call load-10-ac) (dispatch pdp10-operation-direction m-3 d-10-load-in-out-or-both) ((m-c) pdp10-logical-operation m-3) ((oa-reg-low) dpb m-c oal-aluf a-zero) ((m-1) setz m-1 a-t) ((oa-reg-low) dpb m-c oal-aluf a-zero) ((m-2) setz m-2 a-r) (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self) (jump next-10-insn) ;TRNN, etc. xct-10-test ;Fetch the test mask from effective address or memory. (dispatch pdp10-test-source-bit m-3 d-10-test-source) ;Swap the test mask's halves if appropriate. (jump-if-bit-clear-xct-next pdp10-test-swapped-bit m-3 xct-10-test-1) ((m-1) m-t) ((m-t) m-r) ((m-r) m-1) xct-10-test-1 ;Fetch the AC to be tested. (call load-10-ac) ;Are any masked bits nonzero? ((m-i) and m-1 a-t) ((m-j) and m-2 a-r) (dispatch-xct-next pdp10-test-condition m-3 d-10-test-condition) ((m-i) ior m-i a-j) ;Maybe store new contents in AC. (dispatch pdp10-test-modification m-3 d-10-test-modification) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d= 1=uubu=bdssu™(q=byu ysu= 1=uubu=y}}ud9™(q=byu lqd= 1=}u}=u9(und=dybqqush9(lsqlyuh y=}u}9ysu= 1=uubu=y}}ud™(qqj=qfuus=nuyu™ (}=s9 }=u9™((}=u9 q={us9*Dusydu fhuuhus u b{yq, qnd }qhbu d b.*Sqllud fyuh (dybqqush=ysu=nuyu qdq 1=uubu=sndyuyn }=" d= 1=uubu=sndyuyn9*Uhu uhynw u uubu yb fhuuhus ]=Y yb nn{us.(lsqlyuh d=}u}9(buqsu=dybqqush 3 19d= 1=uubu=sndyuyn™(ysu= 1=uubu=39™*D nu b{yq.™(q=byu ysu= 1=uubu=b{yq=yf=19™(q=byu ysu= 1=uubu=b{yq=qlfqhb9™(q=byu ysu= 1=uubu=b{yq=nu=19(und=dybqqush9(lsqlyuh y=}u}9ysu= 1=uubu=b{yq=nu=1™(jd}q=ysu=nuyu ysu= 1=uubu=b{yq=qlfqhb9™(qqj=u`dql }=y q={us9***... Fyll uhqu fs{.ysu= 1=uubu=b{yq=yf=1™(qqj=nu=u`dql }=y q={us9ysu= 1=uubu=b{yq=qlfqhb™(qqj (}=b9 qdd }=b (q=snbuqnu 99*S}qduu qnd busu uhu nuf snuunub f uhu qssd}dlqus.*Sqllud bh (dybqqush qdq 1=uubu=}dyfysquyn }=" d= 1=uubu=}dyfysquyn9(lsqlyuh d=}u}9(buqsu=dybqqush 3 ynhybyu=ysu=nuyu=byu9d= 1=uubu=}dyfysquyn™(nuyu= 1=ynbn9™(ysu= 1=uubu=buu={us9™(ysu= 1=uubu=s}qlu}unu9™(ysu= 1=uubu=buu=nu9(und=dybqqush9(lsqlyuh y=}u}9ysu= 1=uubu=buu={us™((}= 9 qndsq }= q=u9™((}=39 qndsq }=3 q=s9™(jd}q=ysu=nuyu nuyu= 1=ynbn9™(sqll busu= 1=qs9ysu= 1=uubu=s}qlu}unu™((}= 9 ys }= q=u9™((}=39 ys }=3 q=s9™(jd}q=ysu=nuyu nuyu= 1=ynbn9™(sqll busu= 1=qs9ysu= 1=uubu=buu=nu™((}= 9 ys }= q=u9™((}=39 ys }=3 q=s9™(jd}q=ysu=nuyu nuyu= 1=ynbn9™(sqll busu= 1=qs9 *Buqs{ ynbusdsuynby= 1=qdbh™(sqll lqd= 1=qs9™(sqll=ysu=nuyu lqd= 1=}u}=u9 ((}= 9 qdd }= (q=snbuqnu 99™((}=39 qdd }=3 (q=snbuqnu 99™((}= 9 usdnsquu=u=hqlffsd }= 9™(sqll=ysu=nuyu busu= 1=qs9 ((}=39 usdnsquu=u=hqlffsd }=39™(sqll=ysu=nuyu busu= 1=}u}=u9 ((}=u9 }=39™(jd}q=nu=u`dql }= q={us nuyu= 1=ynbn9™(jd}q qdl= 1=wusflf9y= 1=qq™(sqll=ysu=nuyu lqd= 1=qs9 ((s=qdl=bdffus=qynuus=qdbh9 }=u9™(sqll=ysu=nuyu lqd= 1=}u}=u9 ((}=u9 }=39™(sqll=ysu=nuyu busu= 1=}u}=u9 ((}=u9 s=qdl=bdffus=qynuus=qq9™((}= 9 bdb }= (q=snbuqnu 99™((}=39 bdb }=3 (q=snbuqnu 99™((}= 9 usdnsquu=u=hqlffsd }= 9™((}=39 usdnsquu=u=hqlffsd }=39™(sqll busu= 1=qs9™(jd}q=nu=u`dql™}= (q=snbuqnu = 9 nuyu= 1=ynbn9™(jd}q qdl= 1=wusflf9y= 1=qqj™(sqll lqd= 1=qs9™(sqll=ysu=nuyu lqd= 1=}u}=u9 ((}=u9 }=39*Buu uhu QS.™((}=b9 qdd }=s q= 1=}u}=1=lufu=qdds9™((}=b9 bdb (q=snbuqnu 99*Dussu}unu uhu hqlwub f uhu QS.™((}= 9 bdb }= (q=snbuqnu 99™((}=39 bdb }=3 (q=snbuqnu 99™((}= 9 usdnsquu=u=hqlffsd }= 9™((}=39 usdnsquu=u=hqlffsd }=39™(sqll busu= 1=qs9™(jd}q=nu=u`dql™}= (q=snbuqnu = 9 nuyu= 1=ynbn9™(jd}q qdl= 1=wusflf9y= 1=qdbhj™(sall load-10-ac) (call-xct-next get-10-pc-and-flags-t) ((m-1) add m-1 (a-constant 1)) ((m-2) add m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) (call-xct-next store-10-ac) ((m-2) truncate-to-halfword m-2) (call-xct-next store-10-mem-t) ((m-e) m-2) (jump-not-equal m-1 a-zero next-10-insn) (jump pdl-10-overflow) ;Byte instructions. i-10-ibp (call inc-10-bp) (jump next-10-insn) ;Truncate the PDP-10 quantity in the A register ;to the length specified in M-C. truncate-10-byte (jump-greater-than m-c (a-constant 18.) truncate-10-byte-1) (popj-equal-xct-next m-c (a-constant 18.)) ((m-1) a-zero) (jump-equal-xct-next m-c a-zero truncate-10-byte-0-length) ((m-c) sub m-c (a-constant 1)) (popj-after-next (oa-reg-low) dpb m-c oal-bytl-1 a-zero) ((m-2) byte-inst m-2 a-zero) truncate-10-byte-0-length (popj (m-2) a-zero) truncate-10-byte-1 ((m-c) sub m-c (a-constant 19.)) (popj-after-next (oa-reg-low) dpb m-c oal-bytl-1 a-zero) ((m-1) byte-inst m-1 a-zero) ;Increment the byte pointer in the PDP-10 memory location ;addressed by M-E. Store it back in that memory location. inc-10-bp (call load-10-mem) ((m-t) pdp10-bp-position m-1) ((m-r) pdp10-bp-size m-1) ((m-t) sub m-t a-r) (call-less-than m-t a-zero inc-10-bp-next-word) ((m-1) dpb m-t pdp10-bp-position a-1) (jump store-10-mem) inc-10-bp-next-word ((m-1) add m-1 (a-constant 1)) (popj-after-next (m-t) (a-constant 36.)) ((m-t) sub m-t a-r) i-10-ildb (jump-if-bit-set pdp10-fpd-flag a-10-flags i-10-ldb) (call inc-10-bp) ((m-1) (a-constant pdp10-fpd-flag)) ((a-10-flags) ior m-1 a-10-flags) (jump i-10-ldb-0) i-10-ldb (call load-10-mem) i-10-ldb-0 ((m-3) m-1) ((m-e) m-2) ;Compute effective address of byte pointer, ;preserving M-A over it. ((c-pdl-buffer-pointer-push) m-a) (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ((m-a) c-pdl-buffer-pointer-pop) ;Fetch the word addressed by the byte pointer. (call load-10-mem) ((m-1) (a-constant pdp10-fpd-flag)) ((a-10-flags) andcm m-1 a-10-flags) ;Shift it right so desired byte is on the bottom. ((m-c) pdp10-bp-position m-3) (call shift-10-right) ;Depending on whether byte size is more than 18, ;we must truncate M-1, or clear M-1 and truncate M-2. ;If it's exactly 0 or 18, we must clear one or both, but not truncate. ((m-c) pdp10-bp-size m-3) (call truncate-10-byte) (jump-xct-next next-10-insn) (call store-10-ac) i-10-idpb (jump-if-bit-set pdp10-fpd-flag a-10-flags i-10-dpb) (call inc-10-bp) ((m-1) (a-constant pdp10-fpd-flag)) ((a-10-flags) ior m-1 a-10-flags) (jump i-10-dpb-0) i-10-dpb (call load-10-mem) i-10-dpb-0 ((m-3) m-1) ((m-e) m-2) ;Compute effective address of byte pointer, ;preserving M-A over it. ((c-pdl-buffer-pointer-push) m-a) (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ((m-a) c-pdl-buffer-pointer-pop) ;Fetch the word addressed by the byte pointer. (call load-10-mem-t) ((m-1) (a-constant pdp10-fpd-flag)) ((a-10-flags) andcm m-1 a-10-flags) ;Now zero out the byte we want to replace. ;Load -1 into the A-register, and shift/truncate it to the byte we want. ((m-1) a-minus-one) ((m-2) a-minus-one) (call-xct-next shift-10-left) ((m-c) pdp10-bp-position m-3) (call-xct-next truncate-10-byte) ((m-c) pdp10-bp-size m-3) ;Now clear that byte in the T register. ((m-t) andca m-t a-1) ((m-r) andca m-r a-1) ;Get the byte into A register, truncate, and shift into position. (call load-10-ac) (call-xct-next shift-10-left) ((m-c) pdp10-bp-position m-3) (call-xct-next truncate-10-byte) ((m-c) pdp10-bp-size m-3) ;Merge it into T register. ((m-t) ior m-t a-1) ((m-r) ior m-r a-2) ;Store the result. (jump-xct-next next-10-insn) (call store-10-mem-t) ;The XCT instruction. i-10-xct (call load-10-mem) ((m-3) m-1) ((m-e) m-2) (jump eff-addr-comp) i-10-jrst ;If not JRSTF, just jump. (jump-if-bit-clear pdp10-jrstf-bit m-3 jump-10-jump) ;We must reconstruct the flags to restore! ;The result of any indirection is still in M-1, ;but any indexing which followed it was only done for the right half (M-E). ;So we must do it now for the left half. ;Also, if there was no indirection, we must initialize M-1 to zero. (jump-if-bit-set pdp10-indirect-bit m-3 i-10-jrstf-1) ((m-1) a-zero) i-10-jrstf-1 ((m-a) pdp10-index-field m-3) ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-1) add m-1 a-10-ac-0-left) ((a-10-flags) mask-field m-1 a-zero) (jump jump-10-jump) i-10-jsr (call get-10-pc-and-flags-t) (call store-10-mem-t) (jump-xct-next jump-10-jump) ((m-e) add m-e (a-constant 1)) i-10-jsp (call get-10-pc-and-flags-t) (jump-xct-next jump-10-jump) (call store-10-ac-t) i-10-jsa (call load-10-ac) (call store-10-mem) (call-xct-next get-10-pc) ((m-1) m-e) (call store-10-ac) (jump-xct-next jump-10-jump) ((m-e) add m-e (a-constant 1)) i-10-jra ((m-t) m-e) (call load-10-ac) ((m-e) m-1) (call load-10-mem) (call store-10-ac) ((m-e) m-t) (jump jump-10-jump) ;Shift instructions. i-10-lsh (call load-10-ac) (jump-greater-than-or-equal m-e a-zero i-10-lsh-left) ((m-c) sub m-zero a-e) (call shift-10-right) ((m-c) pdp10-shift-count m-c) (call store-10-ac) (jump next-10-insn) i-10-lsh-left (call shift-10-left) ((m-c) pdp10-shift-count m-e) (call store-10-ac) (jump next-10-insn) i-10-ash (call load-10-ac) (jump-greater-than-or-equal m-e a-zero i-10-lsh-left) ((m-c) sub m-zero a-e) (call arith-shift-10-right) ((m-c) pdp10-shift-count m-c) (call store-10-ac) (jump next-10-insn) ;;;??? No point in writing the rest until I can write ;SHIFT-10-LEFT, etc. * LMFL(DIRECTORY "RMS" NAME "PDP10" TYPE "LISP" VERSION 15 BYTE-SIZE 10 CREATION-DATE 23075640645 AUTHOR "RMS") ;PDP-10 simulator microcode ;The simulator uses an internal accumulator for its arithmetic ;and most of its data transfers. ;This internal accumulator consists of M-1 and M-2. ;M-1 holds the left half of the 36-bit quantity and M-2 the right half. ;The other argument of arithmetic operations goes in ;the T register, composed of M-T and M-R. ;Instructions are executed out of the instruction register, ;which occupies M-3 and M-E. ;The AC field of the instruction is standardly placed in M-A, ;and the effective address is computed in M-E. ;The simulated PC lives in M-B; actually, that contains ;one less than the Q address of the left halfword of the next instruction. ;Jump instructions and PC saving instructions convert ;between this form of quantity and a pdp-10 address. ;The simulated PDP10 flags are kept in A-10-FLAGS. ;However, the CARRY 0, CARRY 1 and OVERFLOW flags can also ;be considered set if ...??? ;GET-10-PC-AND-FLAGS-T merges those things into A-10-FLAGS ;before returning the flags. (def-data-field pdp10-sign-bit 1 17.) (def-data-field pdp10-carry-0-bit 1 18.) (def-data-field pdp10-index-field 4 0) (def-data-field pdp10-indirect-bit 1 4) (def-data-field pdp10-index-and-indirect 5 0) ;Indirect bit and index reg number. (def-data-field pdp10-ac-field 4 5) (def-data-field pdp10-opcode 9 9) ;These bits distinguish between test insns, logical insns, halfword insns, io insns, etc. (def-data-field pdp10-insn-class 3 15.) ;Distinguish logical vs halfword vs test, etc. ;For instructions which can be direct, immediate, to memory or to self (or both), ;these are the bits which say which one it is. (def-data-field pdp10-operation-direction 2 9.) ;These bits distinguish CAI vs CAM vs JUMP vs SKIP vs AOJ vs AOS vs SOJ vs SOS. (def-data-field pdp10-jump-subclass 3 12.) ;These bits control the jump condition of a CAI, CAM, etc. (def-data-field pdp10-jump-condition 3 9.) ;This bit, if set, means source of halfword insn is the right half. (def-data-field pdp10-halfword-fetch-right-bit 1 11.) ;This bit means destination is the right half. (def-data-field pdp10-halfword-store-right-bit 1 14.) ;These bits say what to do with the other halfword. (def-data-field pdp10-other-halfword-action 2 12.) ;These bits control what operation a logical instruction does. ;They are like arg 1 of BOOLE. (def-data-field pdp10-logical-operation 4 11.) ;In a test instruction, this bit, if one, says mask comes from memory. (def-data-field pdp10-test-source-bit 1 12.) ;This bit, if one, says swap the mask (whether from memory or from 0,,E) (def-data-field pdp10-test-swapped-bit 1 9) ;These bits say when to skip. (def-data-field pdp10-test-condition 2 10.) ;These bits say what to do to the selected bits in the accumulator. (def-data-field pdp10-test-modification 2 13.) ;This bit set in a JRST instruction makes it a JRSTF. (def-data-field pdp10-jrstf-bit 1 6) ;Components of PDP10 byte pointers. (def-data-field pdp10-bp-position 6 12.) (def-data-field pdp10-bp-size 6 6) (locality a-mem) a-10-flags (0) (assign pdp10-overflow-flag 400000) (assign pdp10-carry-0-flag 200000) (assign pdp10-carry-1-flag 100000) (assign pdp10-floating-overflow-flag 040000) (assign pdp10-fpd-flag 020000) (assign pdp10-user-mode-flag 010000) (assign pdp10-floating-underflow-flag 000100) (assign pdp10-no-divide-flag 000040) (modulo 2) ;So halfword instructions can choose which half! ;Address of Q containing the left half of simulated memory location 0. ;The left halves of all PDP-10 memory words live in consecutive Qs. a-10-mem-0-left-addr (0) ;Address of Q containing the right half of simulated memory location 0. ;The right halves of all PDP-10 memory words live in consecutive Qs, ;immediately following the left halves. ;Thus, this address is always 1000000 more than that in a-10-mem-0-left-addr. a-10-mem-0-right-addr (0) ;Address of left half of memory location 20, ;used for testing the PC to see whether points at an AC. a-10-mem-20-left-addr (0) ;40 here so halfword instructions can choose which half! (modulo 40) ;These are the left halves of the pdp-10's simulated accumulators. a-10-ac-0-left (0) (modulo 20) ;These are the right halves. a-10-ac-0-right (0) (modulo 20) (locality i-mem) ;Load and store simulated accumulators (AC number in M-A) ;from the internal accumulator and the T register. ;Store routines automatically zero out the unused bits of ;the Qs being stored. ;Store the internal accumulator into the simulated accumulator ;whose number is in M-A. store-10-ac ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) truncate-to-halfword m-1) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) truncate-to-halfword m-2) ;Load the simulated accumulator whose number is in M-A ;into the internal accumulator. load-10-ac ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the T register into the simulated accumulator ;whose number is in M-A. store-10-ac-t ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) truncate-to-halfword m-t) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) truncate-to-halfword m-r) ;Load the simulated accumulator whose number is in M-A ;into the T register. load-10-ac-t ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Load and store main memory (address in M-E) ;from the internal accumulator and the T register. ;Store routines automatically zero out the unused bits of ;the Qs being stored. ;Load the simulated memory location whose number is in M-E ;into the internal accumulator. load-10-mem (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-1) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-ac-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the internal accumulator into the simulated memory location ;whose address is in M-E. store-10-mem (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) truncate-to-halfword m-1) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) truncate-to-halfword m-2) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) truncate-to-halfword m-1) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) truncate-to-halfword m-2) ;Load the simulated memory location whose number is in M-E ;into the T register. load-10-mem-t (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-t) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-r) read-memory-data) load-10-ac-t-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Store the T register into the simulated memory location ;whose address is in M-E. store-10-mem-t (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) truncate-to-halfword m-t) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) truncate-to-halfword m-r) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-t-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) truncate-to-halfword m-t) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) truncate-to-halfword m-r) ;Entry and exit. ;Call with (%pdp10-simulator data-array) ;It returns NIL, having made changes in the data-array. enter-10-simulator (misc-inst-entry %pdp10-simulator) (call gahdra) ;Pop and decode array. (call-if-bit-set (lisp-byte %%array-displaced-bit) m-b trap) (error-table argtyp non-displaced-array m-a 0) ((m-b) selective-deposit m-b (lisp-byte %%array-type-field) a-zero) (call-not-equal m-b (a-constant (eval art-q)) trap) (error-table argtyp art-q-array m-a 0) (call-not-equal m-d (a-constant 1) trap) (error-table array-number-dimensions m-d 1 m-a) ;; now we have the array in M-A (origin in M-E, length in M-S) (call-less-than m-s (a-constant data-array-length) trap) (error-table argtyp reasonable-size-array m-a 0) ;Load the PDP-10 accumulators from the data array. ((m-a) a-zero) ((vma) m-e) ((a-10-data-array-origin) m-e) enter-10-simulator-1 ((vma-start-read) add vma (a-constant 1)) (check-page-read) ((m-1) truncate-to-halfword read-memory-data) ((vma-start-read) add vma (a-constant 1)) (check-page-read) ((m-2) truncate-to-halfword read-memory-data) (call-xct-next store-10-ac) ((m-a) add m-a (a-constant 1)) (jump-less-than m-a (a-constant 20) enter-10-simulator-1) ;Fetch the PC and flags. ((vma-start-read) add vma (a-constant 1)) (check-page-read) ((m-e) truncate-to-halfword read-memory-data) ((vma-start-read) add vma (a-constant 1)) (check-page-read) ((a-10-flags) truncate-to-halfword read-memory-data) ;Fetch the address of PDP-10 memory. ((vma-start-read) add vma (a-constant 1)) (check-page-read) ((a-10-mem-0-left-addr) truncate-to-halfword read-memory-data) ((m-1) truncate-to-halfword read-memory-data) ((a-10-mem-0-right-addr) add m-1 (a-constant 1000000)) (jump jump-10-jump) ;Jump to the PC now in M-E. (assign exit-10-pdl-overflow 1) pdl-10-overflow ((m-c) (a-constant exit-10-pdl-overflow)) exit-10-simulator ;M-C has code indicating exit condition. ;Store the ACs back into the data array. ((vma) a-10-data-array-origin) ((m-a) a-zero) exit-10-simulator-1 (call load-10-ac) ((write-memory-data) dpb m-1 q-pointer (a-constant (byte-value q-data-type dtp-fix))) ((vma-start-write) add vma (a-constant 1)) (check-page-write) ((write-memory-data) dpb m-2 q-pointer (a-constant (byte-value q-data-type dtp-fix))) ((vma-start-write) add vma (a-constant 1)) (check-page-write) ((m-a) add m-a (a-constant 1)) (jump-less-than m-a (a-constant 20) exit-10-simulator-1) ;Store pc and flags via T register. (call get-10-pc-and-flags-t) ;Get flags in M-T, pc in M-R. ((write-memory-data) dpb m-t q-pointer (a-constant (byte-value q-data-type dtp-fix))) ((vma-start-write) add vma (a-constant 1)) (check-page-write) ((write-memory-data) dpb m-r q-pointer (a-constant (byte-value q-data-type dtp-fix))) ((vma-start-write) add vma (a-constant 1)) (check-page-write) ;Return the exit condition code, as a fixnum. (popj (m-t) dpb m-c q-pointer (a-constant (byte-value q-data-type dtp-fix))) ;Set the simulated pc from a pdp-10 format pc in M-2. set-10-pc (popj-after-next (m-b) add m-2 (a-constant -1)) ((m-b) add m-b a-10-mem-0-left-addr) ;Get the pc and flags in internal accumulator (m-1 and m-2) get-10-pc-and-flags ;;;??? ;Get the pc in pdp-10 form in M-2. get-10-pc (popj-after-next (m-2) sub m-b a-10-mem-0-leftaddr) ((m-2) m+1 m-2) ;Get the pc and flags in other accumulator (m-t and m-r) get-10-pc-and-flags ;;;??? (popj-after-next (m-r) sub m-b a-10-mem-0-leftaddr) ((m-r) m+1 m-r) ;Come here to jump to effective address and execute next instruction. jump-10-jump ((m-b) add m-e a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Loop point for executing the next pdp-10 instruction. next-10-insn (jump-less-than m-b a-10-mem-20-addr xct-10-ac) ;Check for ACs referenced as memory. ((vma-start-read m-b) m+1 m-b) ;Increment pc and fetch lh of insn. (check-page-read) ((m-3) read-memory-data) ((vma-start-read) add m-b (a-constant 1000000)) (check-page-read) ((m-e) read-memory-data) ;Compute the effective address in M-E ;for the instruction in the instruction register (M-3, M-E). eff-addr-comp (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ;Fetch the next instruction from an accumulator. xct-10-ac (call get-10-pc) ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-3) a-10-ac-0-left) ((oa-reg-high) dpb m-a oah-a-src a-zero) (jump-xct-next eff-addr-comp) ((m-e) a-10-ac-0-right) (locality d-mem) (start-dispatch 5 0) d-10-index-and-indirect (xct-10-insn) (repeat 17 (do-10-indexing)) (do-10-indirect) (repeat 17 (do-10-indexing)) (end-dispatch) (start-dispatch 5 0) d-10-index-and-indirect-not-first-time (xct-10-insn) (repeat 17 (do-10-indexing-after-indirect)) (do-10-indirect) (repeat 17 (do-10-indexing-after-indirect)) (end-dispatch) (locality i-mem) ;Perform indexing on address field in M-E ;with index register number in M-A. do-10-indexing ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-e) add m-e a-10-ac-0-right) (jump-if-bit-clear-xct-next pdp10-indirect-bit m-3 xct-10-insn) ((m-e) truncate-to-halfword m-e) ;Perform indexing on address field in M-E after indirection ;index register number in M-A. ;The difference is where we test the indirect bit. do-10-indexing-after-indirect ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-e) add m-e a-10-ac-0-right) (jump-if-bit-clear-xct-next pdp10-indirect-bit m-1 xct-10-insn) ((m-e) truncate-to-halfword m-e) ;Perform indirection, and merge the indirect pointer ;into the instruction register. Then decide whether ;additional indirection or indexing is needed. ;We do not clobber M-3. This is for the sake of JRSTF! do-10-indirect (call load-10-mem) ((m-e) m-2) (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect-not-first-time) ((m-a) pdp10-index-field m-1) ;Execute the instruction in M-3 with effective address in M-E ;The execution routine finds the accumulator in M-A. xct-10-insn (dispatch-xct-next pdp10-insn-class m-3 d-10-insn-class) ((m-a) pdp10-ac-field m-3) ;Dispatch on major classes of pdp-10 instructions. (locality d-mem) (start-dispatch 3 0) d-10-insn-class (xct-10-uuo) (xct-10-random) (xct-10-move) (xct-10-jump) (xct-10-logical) (xct-10-halfword) (xct-10-test) (xct-10-uuo) (end-dispatch) (locality i-mem) ;Do the store for an instruction like ADD ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-both (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-both) (end-dispatch) (locality i-mem) store-10-both (call store-10-mem) (jump store-10-ac) ;Do the store for an instruction like MOVE ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-self) (end-dispatch) (locality i-mem) store-10-self (call store-10-mem) (popj-equal m-a) (jump store-10-ac) ;Arithmetic Jump and Skip Instructions xct-10-jump ;Dispatch on jump vs skip, whether to increment, etc. (dispatch pdp10-jump-subclass m-3 d-10-jump-subclass) (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-subclass (i-10-cai) (i-10-cam) (i-10-jump) (i-10-skip) (i-10-aoj) (i-10-aos) (i-10-soj) (i-10-sos) (locality i-mem) ;Depending on type of instruction, ;we get our argument from somewhere ;and then supply one of these as I-ARG when we test the condition. (assign cond-10-jump 0) (assign cond-10-skip 1) i-10-cam (call load-10-mem-t) (call load-10-ac) (call sub-10-no-flags) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-cai (call load-10-ac) ((m-2) sub m-2 a-e) (jump-if-bit-clear pdp10-carry-0-bit m-2 i-10-cai-1) ((m-1) sub m-1 (a-constant 1)) i-10-cai-1 ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-jump (call load-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-skip (call load-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aoj (call load-10-ac) (call inc-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aos (call load-10-mem) (call inc-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-soj (call load-10-ac) (call dec-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-sos (call load-10-mem) (call dec-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;Jump or Skip on Sign of Internal Accumulator. ;Do it with an instruction ; (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;The I-ARG should be COND-10-JUMP to jump, COND-10-SKIP to skip. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-condition (next-10-insn) ;Jump never (cond-10-less) (cond-10-equal) (cond-10-le) (cond-10-always) (cond-10-ge) (cond-10-ne) (cond-10-grtr) (end-dispatch) (locality i-mem) cond-10-le (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) cond-10-equal (jump-not-equal m-1 next-10-insn) (jump-not-equal m-2 next-10-insn) (jump cond-10-always) cond-10-grtr (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-ne (jump-not-equal m-1 cond-10-always) (jump-not-equal m-2 cond-10-always) (jump next-10-insn) cond-10-less (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) (jump next-10-insn) cond-10-ge (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-always (dispatch-xct-next read-i-arg d-10-jump-action) ((m-b) add m-b (a-constant 1)) ;The last instruction does a skip. ;If we are really jumping, it makes no difference. ;If we want to skip, we can go straight to the instruction loop. (locality d-mem) (start-dispatch 1 0) d-10-jump-action (jump-10-jump) (next-10-insn) (end-dispatch) (locality i-mem) ;Halfword Instructions ;Subroutines ;Store M-2 in half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. store-10-ac-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-ac-half) (popj-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) (locality d-mem) (start-dispatch 1 0) d-store-10-ac-half (store-10-ac-left) (store-10-ac-right) (end-dispatch) store-10-ac-left ((a-10-ac-0-left) m-2) store-10-ac-right ((a-10-ac-0-right) m-2) ;Load M-2 from half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. load-10-ac-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-ac-half) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) (locality d-mem) (start-dispatch 1 0) d-load-10-ac-half (load-10-ac-left) (load-10-ac-right) (end-dispatch) load-10-ac-left ((m-2) a-10-ac-0-left) load-10-ac-right ((m-2) a-10-ac-0-right) ;Store M-2 in half of the simulated memory location with address in M-E. ;Which half is controlled by the instruction register. store-10-mem-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-mem-half) ((write-memory-data) m-2) (locality d-mem) (start-dispatch 1 0) d-store-10-mem-half (store-10-mem-left) (store-10-mem-right) (end-dispatch) store-10-mem-left ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) (popj) store-10-mem-right ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) ;Load M-2 from half of the simulated memory location whose address is in M-E. ;Which half is controlled by the instruction register. load-10-mem-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-mem-half) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d-load-10-mem-half (load-10-mem-left) (load-10-mem-right) (end-dispatch) load-10-mem-left ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-mem-right ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) ;Load M-2 from half of the immediate arg. ;Which half is controlled by the instruction register. load-10-immed-half (dispatch pdp10-halfword-fetch-right-bit m-3 d-load-10-immed-half) (locality d-mem) (start-dispatch 1 0) d-load-10-immed-half (load-10-immed-left) (load-10-immed-right) (end-dispatch) load-10-immed-left (popj (m-2) a-zero) load-10-immed-right (popj (m-2) m-e) xct-10-halfword (dispatch pdp10-operation-direction m-3 d-10-load-in-out-or-both-half) (dispatch pdp10-other-halfword-action m-3 d-other-10-halfword) (jump-if-bit-set pdp10-halfword-store-right-bit m-3 xct-10-halfword-1) ((m-c) m-1) ((m-1) m-2) ((m-2) m-c) xct-10-halfword-1 (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self) (jump next-10-insn) (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-load-in-out-or-both-half (p-bit load-10-mem-half) (p-bit load-immed-arg-half) (p-bit load-10-ac-half) (p-bit load-10-mem-half) (end-dispatch) (locality i-mem) ;Clear, set or sign-extend the "other" half, ;which right now is always in M-1. (locality d-mem) (start-dispatch 2 inhibit-xct-next-bit) d-other-10-halfword (xct-10-halfword-preserve-other-half) (p-bit other-10-halfword-clear) (p-bit other-10-halfword-set) (p-bit other-10-halfword-extend) (end-dispatch) (locality i-mem) other-10-halfword-extend (jump-if-bit-set pdp10-sign-bit m-2 other-10-halfword-set) other-10-halfword-clear (popj (m-1) a-zero) other-10-halfword-set (popj (m-1) (a-constant 777777)) xct-10-halfword-preserve-other-half (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self-half) (jump next-10-insn) ;Do the store for an instruction like HRL ;which only wants to store one halfword ;and can do it in the AC, in memory or in self. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self-halfword (p-bit store-10-ac-half) (p-bit store-10-ac-half) (p-bit store-10-mem-half) (p-bit store-10-self-half) (end-dispatch) (locality i-mem) store-10-self-half (call store-10-mem-half) (popj-equal m-a) (jump store-10-ac-half) ;Simple arithmetic subroutines. sub-10-no-flags ((m-1) sub m-1 m-t) ((m-2) sub m-2 m-r) (jump-if-bit-clear pdp10-carry-0-bit m-2 sub-10-a) ((m-1) sub m-1 (a-constant 1)) sub-10-a (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) inc-10 ((m-2) add m-2 (a-constant 1)) (jump-if-bit-set pdp10-carry-0-bit m-2 inc-10-a) ((m-1) add m-1 (a-constant 1)) inc-10-a ;;;??? Needs to compute and save carry 0, carry 1 and overflow flags. (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) dec-10 ((m-2) sub m-2 (a-constant 1)) (jump-if-bit-clear pdp10-carry-0-bit m-2 inc-10-a) ((m-1) add m-1 (a-constant 1)) dec-10-a ;;;??? Needs to compute and save carry 0, carry 1 and overflow flags. (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) ;AND, etc. xct-10-logical (call load-10-ac) (dispatch pdp10-operation-direction m-3 d-10-load-in-out-or-both) ((m-c) pdp10-logical-operation m-3) ((oa-reg-low) dpb m-c oal-aluf a-zero) ((m-1) setz m-1 a-t) ((oa-reg-low) dpb m-c oal-aluf a-zero) ((m-2) setz m-2 a-r) (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self) (jump next-10-insn) ;TRNN, etc. xct-10-test ;Fetch the test mask from effective address or memory. (dispatch pdp10-test-source-bit m-3 d-10-test-source) ;Swap the test mask's halves if appropriate. (jump-if-bit-clear-xct-next pdp10-test-swapped-bit m-3 xct-10-test-1) ((m-1) m-t) ((m-t) m-r) ((m-r) m-1) xct-10-test-1 ;Fetch the AC to be tested. (call load-10-ac) ;Are any masked bits nonzero? ((m-i) and m-1 a-t) ((m-j) and m-2 a-r) (dispatch-xct-next pdp10-test-condition m-3 d-10-test-condition) ((m-i) ior m-i a-j) ;Maybe store new contents in AC. (dispatch pdp10-test-modification m-3 d-10-test-modification) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d-10-test-source (p-bit xct-10-test-immed) (p-bit load-10-mem-t) (end-dispatch) (locality i-mem) xct-10-test-immed (popj-after-next (m-r) m-e) ((m-t) a-zero) ;Decide whether to skip, and maybe do so. ;Called with (dispatch-xct-next pdp10-test-condition m-3 d-10-test-condition) ;The thing to test is whether M-I is nonzero. (locality d-mem) (start-dispatch 2 0) d-10-test-condition (xct-10-test-2) ;Do not skip. (p-bit xct-10-test-skip-if-0) (p-bit xct-10-test-skip-always) (p-bit xct-10-test-skip-not-0) (end-dispatch) (locality i-mem) xct-10-test-skip-not-0 (jump-xct-next xct-10-test-skip-always) (popj-equal m-i a-zero) ;;;??? Will that work? xct-10-test-skip-if-0 (popj-not-equal m-i a-zero) xct-10-test-skip-always (popj (m-b) add m-b (a-constant 1)) ;Compute and store the new contents of the accumulator. ;Called by (dispatch pdp10-test-modification m-3 d-10-test-modification) (locality d-mem) (start-dispatch 2 inhibit-xct-next-bit) d-10-test-modification (next-10-insn) (xct-10-test-set-zero) (xct-10-test-complement) (xct-10-test-set-one) (end-dispatch) (locality i-mem) xct-10-test-set-zero ((m-1) andca m-1 a-t) ((m-2) andca m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) xct-10-test-complement ((m-1) xor m-1 a-t) ((m-2) xor m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) xct-10-test-set-one ((m-1) ior m-1 a-t) ((m-2) ior m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) ;Stack instructions i-10-push (call load-10-ac) (call-xct-next load-10-mem-t) ((m-1) add m-1 (a-constant 1)) ((m-2) add m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) (call-xct-next store-10-ac) ((m-2) truncate-to-halfword m-2) (call-xct-next store-10-mem-t) ((m-e) m-2) (jump-not-equal m-1 a-zero next-10-insn) (jump pdl-10-overflow) i-10-pop (call-xct-next load-10-ac) ((c-pdl-buffer-pointer-push) m-e) (call-xct-next load-10-mem-t) ((m-e) m-2) (call-xct-next store-10-mem-t) ((m-e) c-pdl-buffer-pointer-pop) ((m-1) sub m-1 (a-constant 1)) ((m-2) sub m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (call store-10-ac) (jump-not-equal m-1 (a-constant -1) next-10-insn) (jump pdl-10-overflow) i-10-popj (call load-10-ac) (call-xct-next load-10-mem-t) ((m-e) m-2) ;Set the PC. ((m-b) add m-r a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Decrement the halves of the AC. ((m-1) sub m-1 (a-constant 1)) ((m-2) sub m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (call store-10-ac) (jump-not-equal m-1 (a-constant -1) next-10-insn) (jump pdl-10-overflow) i-10-pushj (call load-10-ac) (call-xct-next get-10-pc-and-flags-t) ((m-1) add m-1 (a-constant 1)) ((m-2) add m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) (call-xct-next store-10-ac) ((m-2) truncate-to-halfword m-2) (call-xct-next store-10-mem-t) ((m-e) m-2) (jump-not-equal m-1 a-zero next-10-insn) (jump pdl-10-overflow) ;Byte instructions. i-10-ibp (call inc-10-bp) (jump next-10-insn) ;Truncate the PDP-10 quantity in the A register ;to the length specified in M-C. truncate-10-byte (jump-greater-than m-c (a-constant 18.) truncate-10-byte-1) (popj-equal-xct-next m-c (a-constant 18.)) ((m-1) a-zero) (jump-equal-xct-next m-c a-zero truncate-10-byte-0-length) ((m-c) sub m-c (a-constant 1)) (popj-after-next (oa-reg-low) dpb m-c oal-bytl-1 a-zero) ((m-2) byte-inst m-2 a-zero) truncate-10-byte-0-length (popj (m-2) a-zero) truncate-10-byte-1 ((m-c) sub m-c (a-constant 19.)) (popj-after-next (oa-reg-low) dpb m-c oal-bytl-1 a-zero) ((m-1) byte-inst m-1 a-zero) ;Increment the byte pointer in the PDP-10 memory location ;addressed by M-E. Store it back in that memory location. inc-10-bp (call load-10-mem) ((m-t) pdp10-bp-position m-1) ((m-r) pdp10-bp-size m-1) ((m-t) sub m-t a-r) (call-less-than m-t a-zero inc-10-bp-next-word) ((m-1) dpb m-t pdp10-bp-position a-1) (jump store-10-mem) inc-10-bp-next-word ((m-1) add m-1 (a-constant 1)) (popj-after-next (m-t) (a-constant 36.)) ((m-t) sub m-t a-r) i-10-ildb (jump-if-bit-set pdp10-fpd-flag a-10-flags i-10-ldb) (call inc-10-bp) ((m-1) (a-constant pdp10-fpd-flag)) ((a-10-flags) ior m-1 a-10-flags) (jump i-10-ldb-0) i-10-ldb (call load-10-mem) i-10-ldb-0 ((m-3) m-1) ((m-e) m-2) ;Compute effective address of byte pointer, ;preserving M-A over it. ((c-pdl-buffer-pointer-push) m-a) (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ((m-a) c-pdl-buffer-pointer-pop) ;Fetch the word addressed by the byte pointer. (call load-10-mem) ((m-1) (a-constant pdp10-fpd-flag)) ((a-10-flags) andcm m-1 a-10-flags) ;Shift it right so desired byte is on the bottom. ((m-c) pdp10-bp-position m-3) (call shift-10-right) ;Depending on whether byte size is more than 18, ;we must truncate M-1, or clear M-1 and truncate M-2. ;If it's exactly 0 or 18, we must clear one or both, but not truncate. ((m-c) pdp10-bp-size m-3) (call truncate-10-byte) (jump-xct-next next-10-insn) (call store-10-ac) i-10-idpb (jump-if-bit-set pdp10-fpd-flag a-10-flags i-10-dpb) (call inc-10-bp) ((m-1) (a-constant pdp10-fpd-flag)) ((a-10-flags) ior m-1 a-10-flags) (jump i-10-dpb-0) i-10-dpb (call load-10-mem) i-10-dpb-0 ((m-3) m-1) ((m-e) m-2) ;Compute effective address of byte pointer, ;preserving M-A over it. ((c-pdl-buffer-pointer-push) m-a) (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ((m-a) c-pdl-buffer-pointer-pop) ;Fetch the word addressed by the byte pointer. (call load-10-mem-t) ((m-1) (a-constant pdp10-fpd-flag)) ((a-10-flags) andcm m-1 a-10-flags) ;Now zero out the byte we want to replace. ;Load -1 into the A-register, and shift/truncate it to the byte we want. ((m-1) a-minus-one) ((m-2) a-minus-one) (call-xct-next shift-10-left) ((m-c) pdp10-bp-position m-3) (call-xct-next truncate-10-byte) ((m-c) pdp10-bp-size m-3) ;Now clear that byte in the T register. ((m-t) andca m-t a-1) ((m-r) andca m-r a-1) ;Get the byte into A register, truncate, and shift into position. (call load-10-ac) (call-xct-next shift-10-left) ((m-c) pdp10-bp-position m-3) (call-xct-next truncate-10-byte) ((m-c) pdp10-bp-size m-3) ;Merge it into T register. ((m-t) ior m-t a-1) ((m-r) ior m-r a-2) ;Store the result. (jump-xct-next next-10-insn) (call store-10-mem-t) ;The XCT instruction. i-10-xct (call load-10-mem) ((m-3) m-1) ((m-e) m-2) (jump eff-addr-comp) i-10-jrst ;If not JRSTF, just jump. (jump-if-bit-clear pdp10-jrstf-bit m-3 jump-10-jump) ;We must reconstruct the flags to restore! ;The result of any indirection is still in M-1, ;but any indexing which followed it was only done for the right half (M-E). ;So we must do it now for the left half. ;Also, if there was no indirection, we must initialize M-1 to zero. (jump-if-bit-set pdp10-indirect-bit m-3 i-10-jrstf-1) ((m-1) a-zero) i-10-jrstf-1 ((m-a) pdp10-index-field m-3) ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-1) add m-1 a-10-ac-0-left) ((a-10-flags) mask-field m-1 a-zero) (jump jump-10-jump) i-10-jsr (call get-10-pc-and-flags-t) (call store-10-mem-t) (jump-xct-next jump-10-jump) ((m-e) add m-e (a-constant 1)) i-10-jsp (call get-10-pc-and-flags-t) (jump-xct-next jump-10-jump) (call store-10-ac-t) i-10-jsa (call load-10-ac) (call store-10-mem) (call-xct-next get-10-pc) ((m-1) m-e) (call store-10-ac) (jump-xct-next jump-10-jump) ((m-e) add m-e (a-constant 1)) i-10-jra ((m-t) m-e) (call load-10-ac) ((m-e) m-1) (call load-10-mem) (call store-10-ac) ((m-e) m-t) (jump jump-10-jump) ;Shift instructions. i-10-lsh (call load-10-ac) (jump-greater-than-or-equal m-e a-zero i-10-lsh-left) ((m-c) sub m-zero a-e) (call shift-10-right) ((m-c) pdp10-shift-count m-c) (call store-10-ac) (jump next-10-insn) i-10-lsh-left (call shift-10-left) ((m-c) pdp10-shift-count m-e) (call store-10-ac) (jump next-10-insn) i-10-ash (call load-10-ac) (jump-greater-than-or-equal m-e a-zero i-10-lsh-left) ((m-c) sub m-zero a-e) (call arith-shift-10-right) ((m-c) pdp10-shift-count m-c) (call store-10-ac) (jump next-10-insn) ;;;??? No point in writing the rest until I can write ;SHIFT-10-LEFT, etc. * LMFL(DIRECTORY "RMS" NAME "PDP10" TYPE "LISP" VERSION 16 BYTE-SIZE 10 CREATION-DATE 23075640653 AUTHOR "RMS") ;PDP-10 simulator microcode ;The simulator uses an internal accumulator for its arithmetic ;and most of its data transfers. ;This internal accumulator consists of M-1 and M-2. ;M-1 holds the left half of the 36-bit quantity and M-2 the right half. ;The other argument of arithmetic operations goes in ;the T register, composed of M-T and M-R. ;Instructions are executed out of the instruction register, ;which occupies M-3 and M-E. ;The AC field of the instruction is standardly placed in M-A, ;and the effective address is computed in M-E. ;The simulated PC lives in M-B; actually, that contains ;one less than the Q address of the left halfword of the next instruction. ;Jump instructions and PC saving instructions convert ;between this form of quantity and a pdp-10 address. ;M-Q contains the count of instructions to execute before it is time to return. ;The simulated PDP10 flags are kept in A-10-FLAGS. ;However, the CARRY 0, CARRY 1 and OVERFLOW flags can also ;be considered set if ...??? ;GET-10-PC-AND-FLAGS-T merges those things into A-10-FLAGS ;before returning the flags. (def-data-field pdp10-sign-bit 1 17.) (def-data-field pdp10-carry-0-bit 1 18.) (def-data-field pdp10-index-field 4 0) (def-data-field pdp10-indirect-bit 1 4) (def-data-field pdp10-index-and-indirect 5 0) ;Indirect bit and index reg number. (def-data-field pdp10-ac-field 4 5) (def-data-field pdp10-opcode 9 9) ;These bits distinguish between test insns, logical insns, halfword insns, io insns, etc. (def-data-field pdp10-insn-class 3 15.) ;Distinguish logical vs halfword vs test, etc. ;For instructions which can be direct, immediate, to memory or to self (or both), ;these are the bits which say which one it is. (def-data-field pdp10-operation-direction 2 9.) ;These bits distinguish CAI vs CAM vs JUMP vs SKIP vs AOJ vs AOS vs SOJ vs SOS. (def-data-field pdp10-jump-subclass 3 12.) ;These bits control the jump condition of a CAI, CAM, etc. (def-data-field pdp10-jump-condition 3 9.) ;This bit, if set, means source of halfword insn is the right half. (def-data-field pdp10-halfword-fetch-right-bit 1 11.) ;This bit means destination is the right half. (def-data-field pdp10-halfword-store-right-bit 1 14.) ;These bits say what to do with the other halfword. (def-data-field pdp10-other-halfword-action 2 12.) ;These bits control what operation a logical instruction does. ;They are like arg 1 of BOOLE. (def-data-field pdp10-logical-operation 4 11.) ;In a test instruction, this bit, if one, says mask comes from memory. (def-data-field pdp10-test-source-bit 1 12.) ;This bit, if one, says swap the mask (whether from memory or from 0,,E) (def-data-field pdp10-test-swapped-bit 1 9) ;These bits say when to skip. (def-data-field pdp10-test-condition 2 10.) ;These bits say what to do to the selected bits in the accumulator. (def-data-field pdp10-test-modification 2 13.) ;This bit set in a JRST instruction makes it a JRSTF. (def-data-field pdp10-jrstf-bit 1 6) ;Components of PDP10 byte pointers. (def-data-field pdp10-bp-position 6 12.) (def-data-field pdp10-bp-size 6 6) (locality a-mem) ;Address of first data word of the array in which ;the AC contents, PC and flags were passed, ;so we can store them back when we exit. a-10-data-array-origin (0) a-10-flags (0) (assign pdp10-overflow-flag 400000) (assign pdp10-carry-0-flag 200000) (assign pdp10-carry-1-flag 100000) (assign pdp10-floating-overflow-flag 040000) (assign pdp10-fpd-flag 020000) (assign pdp10-user-mode-flag 010000) (assign pdp10-floating-underflow-flag 000100) (assign pdp10-no-divide-flag 000040) (modulo 2) ;So halfword instructions can choose which half! ;Address of Q containing the left half of simulated memory location 0. ;The left halves of all PDP-10 memory words live in consecutive Qs. a-10-mem-0-left-addr (0) ;Address of Q containing the right half of simulated memory location 0. ;The right halves of all PDP-10 memory words live in consecutive Qs, ;immediately following the left halves. ;Thus, this address is always 1000000 more than that in a-10-mem-0-left-addr. a-10-mem-0-right-addr (0) ;Address of left half of memory location 20, ;used for testing the PC to see whether points at an AC. a-10-mem-20-left-addr (0) ;40 here so halfword instructions can choose which half! (modulo 40) ;These are the left halves of the pdp-10's simulated accumulators. a-10-ac-0-left (0) (modulo 20) ;These are the right halves. a-10-ac-0-right (0) (modulo 20) (locality i-mem) ;Load and store simulated accumulators (AC number in M-A) ;from the internal accumulator and the T register. ;Store routines automatically zero out the unused bits of ;the Qs being stored. ;Store the internal accumulator into the simulated accumulator ;whose number is in M-A. store-10-ac ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) truncate-to-halfword m-1) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) truncate-to-halfword m-2) ;Load the simulated accumulator whose number is in M-A ;into the internal accumulator. load-10-ac ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the T register into the simulated accumulator ;whose number is in M-A. store-10-ac-t ((oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-left) truncate-to-halfword m-t) (popf-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) ((a-10-ac-0-right) truncate-to-halfword m-r) ;Load the simulated accumulator whose number is in M-A ;into the T register. load-10-ac-t ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Load and store main memory (address in M-E) ;from the internal accumulator and the T register. ;Store routines automatically zero out the unused bits of ;the Qs being stored. ;Load the simulated memory location whose number is in M-E ;into the internal accumulator. load-10-mem (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-1) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-ac-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-1) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-2) a-10-ac-0-right) ;Store the internal accumulator into the simulated memory location ;whose address is in M-E. store-10-mem (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) truncate-to-halfword m-1) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) truncate-to-halfword m-2) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) truncate-to-halfword m-1) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) truncate-to-halfword m-2) ;Load the simulated memory location whose number is in M-E ;into the T register. load-10-mem-t (jump-less-than m-e (a-constant 20) load-10-ac-m-e) ;Check for ACs referenced as memory. ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) ((m-t) read-memory-data) ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-r) read-memory-data) load-10-ac-t-m-e ((oa-reg-high) dpb m-e oah-a-src a-zero) ((m-t) a-10-ac-0-left) (popj-after-next (oa-reg-high) dpb m-e oah-a-src a-zero) ((m-r) a-10-ac-0-right) ;Store the T register into the simulated memory location ;whose address is in M-E. store-10-mem-t (jump-less-than m-e (a-constant 20) store-10-ac-m-e) ;Check for ACs referenced as memory. ((write-memory-data) truncate-to-halfword m-t) ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) ((write-memory-data) truncate-to-halfword m-r) ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) store-10-ac-t-m-e ((oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-left) truncate-to-halfword m-t) (popf-after-next (oa-reg-low) dpb m-e oal-a-dest a-zero) ((a-10-ac-0-right) truncate-to-halfword m-r) ;Entry and exit. ;Call with (%pdp10-simulator data-array) ;It returns NIL, having made changes in the data-array. enter-10-simulator (misc-inst-entry %pdp10-simulator) (call gahdra) ;Pop and decode array. (call-if-bit-set (lisp-byte %%array-displaced-bit) m-b trap) (error-table argtyp non-displaced-array m-a 0) ((m-b) selective-deposit m-b (lisp-byte %%array-type-field) a-zero) (call-not-equal m-b (a-constant (eval art-q)) trap) (error-table argtyp art-q-array m-a 0) (call-not-equal m-d (a-constant 1) trap) (error-table array-number-dimensions m-d 1 m-a) ;; now we have the array in M-A (origin in M-E, length in M-S) (call-less-than m-s (a-constant data-array-length) trap) (error-table argtyp reasonable-size-array m-a 0) ;Load the PDP-10 accumulators from the data array. ((m-a) a-zero) ((vma) m-e) ((a-10-data-array-origin) m-e) enter-10-simulator-1 ((vma-start-read) add vma (a-constant 1)) (check-page-read) ((m-1) truncate-to-halfword read-memory-data) ((vma-start-read) add vma (a-constant 1)) (check-page-read) ((m-2) truncate-to-halfword read-memory-data) (call-xct-next store-10-ac) ((m-a) add m-a (a-constant 1)) (jump-less-than m-a (a-constant 20) enter-10-simulator-1) ;Fetch the PC and flags and instruction count. ((vma-start-read) add vma (a-constant 1)) (check-page-read) ((c-pdl-buffer-pointer-push) truncate-to-halfword read-memory-data) ((vma-start-read) add vma (a-constant 1)) (check-page-read) ((a-10-flags) truncate-to-halfword read-memory-data) ((vma-start-read) add vma (a-constant 1)) (check-page-read) ((m-q) q-pointer read-memory-data) ;Fetch the address of PDP-10 memory. ((vma-start-read) add vma (a-constant 1)) (check-page-read) ((m-a) read-memory-data) (call gahdr) ((a-10-mem-0-left-addr) m-e) ((a-10-mem-0-right-addr) add m-e (a-constant 1000000)) ((a-10-mem-20-left-addr) add m-e (a-constant 20)) ((m-e) c-pdl-buffer-pointer-pop) (jump jump-10-jump) ;Jump to the PC now in M-E. ;Exit codes returned as value from call to %PDP10-SIMULATOR. (assign exit-10-sequence-break 0) ; With that code, the caller should loop around and start it up again. (assign exit-10-pdl-overflow 1) (assign exit-10-system-call 2) (assign exit-10-instruction-count 3) pdl-10-overflow ((m-c) (a-constant exit-10-pdl-overflow)) (jump exit-10-simulator) enough-10-insns-done ((m-c) (a-constant exit-10-instruction-count)) (jump exit-10-simulator) exit-10-simulator ;M-C has code indicating exit condition. ;Store the ACs back into the data array. ((vma) a-10-data-array-origin) ((m-a) a-zero) exit-10-simulator-1 (call load-10-ac) ((write-memory-data) dpb m-1 q-pointer (a-constant (byte-value q-data-type dtp-fix))) ((vma-start-write) add vma (a-constant 1)) (check-page-write) ((write-memory-data) dpb m-2 q-pointer (a-constant (byte-value q-data-type dtp-fix))) ((vma-start-write) add vma (a-constant 1)) (check-page-write) ((m-a) add m-a (a-constant 1)) (jump-less-than m-a (a-constant 20) exit-10-simulator-1) ;Store pc and flags via T register. (call get-10-pc-and-flags-t) ;Get flags in M-T, pc in M-R. ((write-memory-data) dpb m-t q-pointer (a-constant (byte-value q-data-type dtp-fix))) ((vma-start-write) add vma (a-constant 1)) (check-page-write) ((write-memory-data) dpb m-r q-pointer (a-constant (byte-value q-data-type dtp-fix))) ((vma-start-write) add vma (a-constant 1)) (check-page-write) ;Store remaining instruction count ((write-memory-data) dpb m-q q-pointer (a-constant (byte-value q-data-type dtp-fix))) ((vma-start-write) add vma (a-constant 1)) (check-page-write) ;Return the exit condition code, as a fixnum. (popj (m-t) dpb m-c q-pointer (a-constant (byte-value q-data-type dtp-fix))) ;Set the simulated pc from a pdp-10 format pc in M-2. set-10-pc (popj-after-next (m-b) add m-2 (a-constant -1)) ((m-b) add m-b a-10-mem-0-left-addr) ;Get the pc and flags in internal accumulator (m-1 and m-2) get-10-pc-and-flags ;;;??? ;Get the pc in pdp-10 form in M-2. get-10-pc (popj-after-next (m-2) sub m-b a-10-mem-0-leftaddr) ((m-2) m+1 m-2) ;Get the pc and flags in other accumulator (m-t and m-r) get-10-pc-and-flags ;;;??? (popj-after-next (m-r) sub m-b a-10-mem-0-leftaddr) ((m-r) m+1 m-r) ;Come here to jump to effective address and execute next instruction. jump-10-jump ((m-b) add m-e a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Loop point for executing the next pdp-10 instruction. next-10-insn (jump-less-than-or-equal-xct-next m-q (a-constant 0) enough-10-insns-done) ((m-q) sub m-q (a-constant 1)) (jump-less-than m-b a-10-mem-20-addr xct-10-ac) ;Check for ACs referenced as memory. ((vma-start-read m-b) m+1 m-b) ;Increment pc and fetch lh of insn. (check-page-read) ((m-3) read-memory-data) ((vma-start-read) add m-b (a-constant 1000000)) (check-page-read) ((m-e) read-memory-data) ;Compute the effective address in M-E ;for the instruction in the instruction register (M-3, M-E). eff-addr-comp (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ;Fetch the next instruction from an accumulator. xct-10-ac (call get-10-pc) ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-3) a-10-ac-0-left) ((oa-reg-high) dpb m-a oah-a-src a-zero) (jump-xct-next eff-addr-comp) ((m-e) a-10-ac-0-right) (locality d-mem) (start-dispatch 5 0) d-10-index-and-indirect (xct-10-insn) (repeat 17 (do-10-indexing)) (do-10-indirect) (repeat 17 (do-10-indexing)) (end-dispatch) (start-dispatch 5 0) d-10-index-and-indirect-not-first-time (xct-10-insn) (repeat 17 (do-10-indexing-after-indirect)) (do-10-indirect) (repeat 17 (do-10-indexing-after-indirect)) (end-dispatch) (locality i-mem) ;Perform indexing on address field in M-E ;with index register number in M-A. do-10-indexing ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-e) add m-e a-10-ac-0-right) (jump-if-bit-clear-xct-next pdp10-indirect-bit m-3 xct-10-insn) ((m-e) truncate-to-halfword m-e) ;Perform indexing on address field in M-E after indirection ;index register number in M-A. ;The difference is where we test the indirect bit. do-10-indexing-after-indirect ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-e) add m-e a-10-ac-0-right) (jump-if-bit-clear-xct-next pdp10-indirect-bit m-1 xct-10-insn) ((m-e) truncate-to-halfword m-e) ;Perform indirection, and merge the indirect pointer ;into the instruction register. Then decide whether ;additional indirection or indexing is needed. ;We do not clobber M-3. This is for the sake of JRSTF! do-10-indirect (call load-10-mem) ((m-e) m-2) (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect-not-first-time) ((m-a) pdp10-index-field m-1) ;Execute the instruction in M-3 with effective address in M-E ;The execution routine finds the accumulator in M-A. xct-10-insn (dispatch-xct-next pdp10-insn-class m-3 d-10-insn-class) ((m-a) pdp10-ac-field m-3) ;Dispatch on major classes of pdp-10 instructions. (locality d-mem) (start-dispatch 3 0) d-10-insn-class (xct-10-uuo) (xct-10-random) (xct-10-move) (xct-10-jump) (xct-10-logical) (xct-10-halfword) (xct-10-test) (xct-10-uuo) (end-dispatch) (locality i-mem) ;Do the store for an instruction like ADD ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-both (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-both) (end-dispatch) (locality i-mem) store-10-both (call store-10-mem) (jump store-10-ac) ;Do the store for an instruction like MOVE ;which is from memory, to memory, immediate or to both. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self (p-bit store-10-ac) (p-bit store-10-ac) (p-bit store-10-mem) (p-bit store-10-self) (end-dispatch) (locality i-mem) store-10-self (call store-10-mem) (popj-equal m-a) (jump store-10-ac) ;Arithmetic Jump and Skip Instructions xct-10-jump ;Dispatch on jump vs skip, whether to increment, etc. (dispatch pdp10-jump-subclass m-3 d-10-jump-subclass) (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-subclass (i-10-cai) (i-10-cam) (i-10-jump) (i-10-skip) (i-10-aoj) (i-10-aos) (i-10-soj) (i-10-sos) (locality i-mem) ;Depending on type of instruction, ;we get our argument from somewhere ;and then supply one of these as I-ARG when we test the condition. (assign cond-10-jump 0) (assign cond-10-skip 1) i-10-cam (call load-10-mem-t) (call load-10-ac) (call sub-10-no-flags) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-cai (call load-10-ac) ((m-2) sub m-2 a-e) (jump-if-bit-clear pdp10-carry-0-bit m-2 i-10-cai-1) ((m-1) sub m-1 (a-constant 1)) i-10-cai-1 ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-jump (call load-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-skip (call load-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aoj (call load-10-ac) (call inc-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-aos (call load-10-mem) (call inc-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) i-10-soj (call load-10-ac) (call dec-10) (call store-10-ac) (dispatch (i-arg cond-10-jump) pdp10-jump-condition m-3 d-10-jump-condition) i-10-sos (call load-10-mem) (call dec-10) (call store-10-mem) (call-not-equal m-a a-zero store-10-ac) (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;Jump or Skip on Sign of Internal Accumulator. ;Do it with an instruction ; (dispatch (i-arg cond-10-skip) pdp10-jump-condition m-3 d-10-jump-condition) ;The I-ARG should be COND-10-JUMP to jump, COND-10-SKIP to skip. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-jump-condition (next-10-insn) ;Jump never (cond-10-less) (cond-10-equal) (cond-10-le) (cond-10-always) (cond-10-ge) (cond-10-ne) (cond-10-grtr) (end-dispatch) (locality i-mem) cond-10-le (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) cond-10-equal (jump-not-equal m-1 next-10-insn) (jump-not-equal m-2 next-10-insn) (jump cond-10-always) cond-10-grtr (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-ne (jump-not-equal m-1 cond-10-always) (jump-not-equal m-2 cond-10-always) (jump next-10-insn) cond-10-less (jump-if-bit-set pdp10-sign-bit m-1 cond-10-always) (jump next-10-insn) cond-10-ge (jump-if-bit-set pdp10-sign-bit m-1 next-10-insn) cond-10-always (dispatch-xct-next read-i-arg d-10-jump-action) ((m-b) add m-b (a-constant 1)) ;The last instruction does a skip. ;If we are really jumping, it makes no difference. ;If we want to skip, we can go straight to the instruction loop. (locality d-mem) (start-dispatch 1 0) d-10-jump-action (jump-10-jump) (next-10-insn) (end-dispatch) (locality i-mem) ;Halfword Instructions ;Subroutines ;Store M-2 in half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. store-10-ac-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-ac-half) (popj-after-next (oa-reg-low) dpb m-a oal-a-dest a-zero) (locality d-mem) (start-dispatch 1 0) d-store-10-ac-half (store-10-ac-left) (store-10-ac-right) (end-dispatch) store-10-ac-left ((a-10-ac-0-left) m-2) store-10-ac-right ((a-10-ac-0-right) m-2) ;Load M-2 from half of the simulated AC whose number is in M-A. ;Which half is controlled by the instruction register. load-10-ac-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-ac-half) (popj-after-next (oa-reg-high) dpb m-a oah-a-src a-zero) (locality d-mem) (start-dispatch 1 0) d-load-10-ac-half (load-10-ac-left) (load-10-ac-right) (end-dispatch) load-10-ac-left ((m-2) a-10-ac-0-left) load-10-ac-right ((m-2) a-10-ac-0-right) ;Store M-2 in half of the simulated memory location with address in M-E. ;Which half is controlled by the instruction register. store-10-mem-half (dispatch-xct-next pdp10-halfword-store-right-bit m-3 d-store-10-mem-half) ((write-memory-data) m-2) (locality d-mem) (start-dispatch 1 0) d-store-10-mem-half (store-10-mem-left) (store-10-mem-right) (end-dispatch) store-10-mem-left ((vma-start-write) add m-e a-10-mem-0-left-addr) (check-page-write) (popj) store-10-mem-right ((vma-start-write) add m-e a-10-mem-0-right-addr) (check-page-write) (popj) ;Load M-2 from half of the simulated memory location whose address is in M-E. ;Which half is controlled by the instruction register. load-10-mem-half (dispatch-xct-next pdp10-halfword-fetch-right-bit m-3 d-load-10-mem-half) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d-load-10-mem-half (load-10-mem-left) (load-10-mem-right) (end-dispatch) load-10-mem-left ((vma-start-read) add m-e a-10-mem-0-left-addr) (check-page-read) (popj (m-2) read-memory-data) load-10-mem-right ((vma-start-read) add m-e a-10-mem-0-right-addr) (check-page-read) (popj (m-2) read-memory-data) ;Load M-2 from half of the immediate arg. ;Which half is controlled by the instruction register. load-10-immed-half (dispatch pdp10-halfword-fetch-right-bit m-3 d-load-10-immed-half) (locality d-mem) (start-dispatch 1 0) d-load-10-immed-half (load-10-immed-left) (load-10-immed-right) (end-dispatch) load-10-immed-left (popj (m-2) a-zero) load-10-immed-right (popj (m-2) m-e) xct-10-halfword (dispatch pdp10-operation-direction m-3 d-10-load-in-out-or-both-half) (dispatch pdp10-other-halfword-action m-3 d-other-10-halfword) (jump-if-bit-set pdp10-halfword-store-right-bit m-3 xct-10-halfword-1) ((m-c) m-1) ((m-1) m-2) ((m-2) m-c) xct-10-halfword-1 (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self) (jump next-10-insn) (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-load-in-out-or-both-half (p-bit load-10-mem-half) (p-bit load-immed-arg-half) (p-bit load-10-ac-half) (p-bit load-10-mem-half) (end-dispatch) (locality i-mem) ;Clear, set or sign-extend the "other" half, ;which right now is always in M-1. (locality d-mem) (start-dispatch 2 inhibit-xct-next-bit) d-other-10-halfword (xct-10-halfword-preserve-other-half) (p-bit other-10-halfword-clear) (p-bit other-10-halfword-set) (p-bit other-10-halfword-extend) (end-dispatch) (locality i-mem) other-10-halfword-extend (jump-if-bit-set pdp10-sign-bit m-2 other-10-halfword-set) other-10-halfword-clear (popj (m-1) a-zero) other-10-halfword-set (popj (m-1) (a-constant 777777)) xct-10-halfword-preserve-other-half (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self-half) (jump next-10-insn) ;Do the store for an instruction like HRL ;which only wants to store one halfword ;and can do it in the AC, in memory or in self. (locality d-mem) (start-dispatch 3 inhibit-xct-next-bit) d-10-store-in-out-or-self-halfword (p-bit store-10-ac-half) (p-bit store-10-ac-half) (p-bit store-10-mem-half) (p-bit store-10-self-half) (end-dispatch) (locality i-mem) store-10-self-half (call store-10-mem-half) (popj-equal m-a) (jump store-10-ac-half) ;Simple arithmetic subroutines. sub-10-no-flags ((m-1) sub m-1 m-t) ((m-2) sub m-2 m-r) (jump-if-bit-clear pdp10-carry-0-bit m-2 sub-10-a) ((m-1) sub m-1 (a-constant 1)) sub-10-a (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) inc-10 ((m-2) add m-2 (a-constant 1)) (jump-if-bit-set pdp10-carry-0-bit m-2 inc-10-a) ((m-1) add m-1 (a-constant 1)) inc-10-a ;;;??? Needs to compute and save carry 0, carry 1 and overflow flags. (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) dec-10 ((m-2) sub m-2 (a-constant 1)) (jump-if-bit-clear pdp10-carry-0-bit m-2 inc-10-a) ((m-1) add m-1 (a-constant 1)) dec-10-a ;;;??? Needs to compute and save carry 0, carry 1 and overflow flags. (popj-after-next (m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) ;AND, etc. xct-10-logical (call load-10-ac) (dispatch pdp10-operation-direction m-3 d-10-load-in-out-or-both) ((m-c) pdp10-logical-operation m-3) ((oa-reg-low) dpb m-c oal-aluf a-zero) ((m-1) setz m-1 a-t) ((oa-reg-low) dpb m-c oal-aluf a-zero) ((m-2) setz m-2 a-r) (dispatch pdp10-operation-direction m-3 d-10-store-in-out-or-self) (jump next-10-insn) ;TRNN, etc. xct-10-test ;Fetch the test mask from effective address or memory. (dispatch pdp10-test-source-bit m-3 d-10-test-source) ;Swap the test mask's halves if appropriate. (jump-if-bit-clear-xct-next pdp10-test-swapped-bit m-3 xct-10-test-1) ((m-1) m-t) ((m-t) m-r) ((m-r) m-1) xct-10-test-1 ;Fetch the AC to be tested. (call load-10-ac) ;Are any masked bits nonzero? ((m-i) and m-1 a-t) ((m-j) and m-2 a-r) (dispatch-xct-next pdp10-test-condition m-3 d-10-test-condition) ((m-i) ior m-i a-j) ;Maybe store new contents in AC. (dispatch pdp10-test-modification m-3 d-10-test-modification) (locality d-mem) (start-dispatch 1 inhibit-xct-next-bit) d-10-test-source (p-bit xct-10-test-immed) (p-bit load-10-mem-t) (end-dispatch) (locality i-mem) xct-10-test-immed (popj-after-next (m-r) m-e) ((m-t) a-zero) ;Decide whether to skip, and maybe do so. ;Called with (dispatch-xct-next pdp10-test-condition m-3 d-10-test-condition) ;The thing to test is whether M-I is nonzero. (locality d-mem) (start-dispatch 2 0) d-10-test-condition (xct-10-test-2) ;Do not skip. (p-bit xct-10-test-skip-if-0) (p-bit xct-10-test-skip-always) (p-bit xct-10-test-skip-not-0) (end-dispatch) (locality i-mem) xct-10-test-skip-not-0 (jump-xct-next xct-10-test-skip-always) (popj-equal m-i a-zero) ;;;??? Will that work? xct-10-test-skip-if-0 (popj-not-equal m-i a-zero) xct-10-test-skip-always (popj (m-b) add m-b (a-constant 1)) ;Compute and store the new contents of the accumulator. ;Called by (dispatch pdp10-test-modification m-3 d-10-test-modification) (locality d-mem) (start-dispatch 2 inhibit-xct-next-bit) d-10-test-modification (next-10-insn) (xct-10-test-set-zero) (xct-10-test-complement) (xct-10-test-set-one) (end-dispatch) (locality i-mem) xct-10-test-set-zero ((m-1) andca m-1 a-t) ((m-2) andca m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) xct-10-test-complement ((m-1) xor m-1 a-t) ((m-2) xor m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) xct-10-test-set-one ((m-1) ior m-1 a-t) ((m-2) ior m-2 a-r) (jump-xct-next next-10-insn) (call store-10-ac) ;Stack instructions i-10-push (call load-10-ac) (call-xct-next load-10-mem-t) ((m-1) add m-1 (a-constant 1)) ((m-2) add m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) (call-xct-next store-10-ac) ((m-2) truncate-to-halfword m-2) (call-xct-next store-10-mem-t) ((m-e) m-2) (jump-not-equal m-1 a-zero next-10-insn) (jump pdl-10-overflow) i-10-pop (call-xct-next load-10-ac) ((c-pdl-buffer-pointer-push) m-e) (call-xct-next load-10-mem-t) ((m-e) m-2) (call-xct-next store-10-mem-t) ((m-e) c-pdl-buffer-pointer-pop) ((m-1) sub m-1 (a-constant 1)) ((m-2) sub m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (call store-10-ac) (jump-not-equal m-1 (a-constant -1) next-10-insn) (jump pdl-10-overflow) i-10-popj (call load-10-ac) (call-xct-next load-10-mem-t) ((m-e) m-2) ;Set the PC. ((m-b) add m-r a-10-mem-0-left-addr) ((m-b) sub (a-constant 1)) ;Decrement the halves of the AC. ((m-1) sub m-1 (a-constant 1)) ((m-2) sub m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) ((m-2) truncate-to-halfword m-2) (call store-10-ac) (jump-not-equal m-1 (a-constant -1) next-10-insn) (jump pdl-10-overflow) i-10-pushj (call load-10-ac) (call-xct-next get-10-pc-and-flags-t) ((m-1) add m-1 (a-constant 1)) ((m-2) add m-2 (a-constant 1)) ((m-1) truncate-to-halfword m-1) (call-xct-next store-10-ac) ((m-2) truncate-to-halfword m-2) (call-xct-next store-10-mem-t) ((m-e) m-2) (jump-not-equal m-1 a-zero next-10-insn) (jump pdl-10-overflow) ;Byte instructions. i-10-ibp (call inc-10-bp) (jump next-10-insn) ;Truncate the PDP-10 quantity in the A register ;to the length specified in M-C. truncate-10-byte (jump-greater-than m-c (a-constant 18.) truncate-10-byte-1) (popj-equal-xct-next m-c (a-constant 18.)) ((m-1) a-zero) (jump-equal-xct-next m-c a-zero truncate-10-byte-0-length) ((m-c) sub m-c (a-constant 1)) (popj-after-next (oa-reg-low) dpb m-c oal-bytl-1 a-zero) ((m-2) byte-inst m-2 a-zero) truncate-10-byte-0-length (popj (m-2) a-zero) truncate-10-byte-1 ((m-c) sub m-c (a-constant 19.)) (popj-after-next (oa-reg-low) dpb m-c oal-bytl-1 a-zero) ((m-1) byte-inst m-1 a-zero) ;Increment the byte pointer in the PDP-10 memory location ;addressed by M-E. Store it back in that memory location. inc-10-bp (call load-10-mem) ((m-t) pdp10-bp-position m-1) ((m-r) pdp10-bp-size m-1) ((m-t) sub m-t a-r) (call-less-than m-t a-zero inc-10-bp-next-word) ((m-1) dpb m-t pdp10-bp-position a-1) (jump store-10-mem) inc-10-bp-next-word ((m-1) add m-1 (a-constant 1)) (popj-after-next (m-t) (a-constant 36.)) ((m-t) sub m-t a-r) i-10-ildb (jump-if-bit-set pdp10-fpd-flag a-10-flags i-10-ldb) (call inc-10-bp) ((m-1) (a-constant pdp10-fpd-flag)) ((a-10-flags) ior m-1 a-10-flags) (jump i-10-ldb-0) i-10-ldb (call load-10-mem) i-10-ldb-0 ((m-3) m-1) ((m-e) m-2) ;Compute effective address of byte pointer, ;preserving M-A over it. ((c-pdl-buffer-pointer-push) m-a) (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ((m-a) c-pdl-buffer-pointer-pop) ;Fetch the word addressed by the byte pointer. (call load-10-mem) ((m-1) (a-constant pdp10-fpd-flag)) ((a-10-flags) andcm m-1 a-10-flags) ;Shift it right so desired byte is on the bottom. ((m-c) pdp10-bp-position m-3) (call shift-10-right) ;Depending on whether byte size is more than 18, ;we must truncate M-1, or clear M-1 and truncate M-2. ;If it's exactly 0 or 18, we must clear one or both, but not truncate. ((m-c) pdp10-bp-size m-3) (call truncate-10-byte) (jump-xct-next next-10-insn) (call store-10-ac) i-10-idpb (jump-if-bit-set pdp10-fpd-flag a-10-flags i-10-dpb) (call inc-10-bp) ((m-1) (a-constant pdp10-fpd-flag)) ((a-10-flags) ior m-1 a-10-flags) (jump i-10-dpb-0) i-10-dpb (call load-10-mem) i-10-dpb-0 ((m-3) m-1) ((m-e) m-2) ;Compute effective address of byte pointer, ;preserving M-A over it. ((c-pdl-buffer-pointer-push) m-a) (dispatch-xct-next pdp10-index-and-indirect m-3 d-10-index-and-indirect) ((m-a) pdp10-index-field m-3) ((m-a) c-pdl-buffer-pointer-pop) ;Fetch the word addressed by the byte pointer. (call load-10-mem-t) ((m-1) (a-constant pdp10-fpd-flag)) ((a-10-flags) andcm m-1 a-10-flags) ;Now zero out the byte we want to replace. ;Load -1 into the A-register, and shift/truncate it to the byte we want. ((m-1) a-minus-one) ((m-2) a-minus-one) (call-xct-next shift-10-left) ((m-c) pdp10-bp-position m-3) (call-xct-next truncate-10-byte) ((m-c) pdp10-bp-size m-3) ;Now clear that byte in the T register. ((m-t) andca m-t a-1) ((m-r) andca m-r a-1) ;Get the byte into A register, truncate, and shift into position. (call load-10-ac) (call-xct-next shift-10-left) ((m-c) pdp10-bp-position m-3) (call-xct-next truncate-10-byte) ((m-c) pdp10-bp-size m-3) ;Merge it into T register. ((m-t) ior m-t a-1) ((m-r) ior m-r a-2) ;Store the result. (jump-xct-next next-10-insn) (call store-10-mem-t) ;The XCT instruction. i-10-xct (call load-10-mem) ((m-3) m-1) ((m-e) m-2) (jump eff-addr-comp) i-10-jrst ;If not JRSTF, just jump. (jump-if-bit-clear pdp10-jrstf-bit m-3 jump-10-jump) ;We must reconstruct the flags to restore! ;The result of any indirection is still in M-1, ;but any indexing which followed it was only done for the right half (M-E). ;So we must do it now for the left half. ;Also, if there was no indirection, we must initialize M-1 to zero. (jump-if-bit-set pdp10-indirect-bit m-3 i-10-jrstf-1) ((m-1) a-zero) i-10-jrstf-1 ((m-a) pdp10-index-field m-3) ((oa-reg-high) dpb m-a oah-a-src a-zero) ((m-1) add m-1 a-10-ac-0-left) ((a-10-flags) mask-field m-1 a-zero) (jump jump-10-jump) i-10-jsr (call get-10-pc-and-flags-t) (call store-10-mem-t) (jump-xct-next jump-10-jump) ((m-e) add m-e (a-constant 1)) i-10-jsp (call get-10-pc-and-flags-t) (jump-xct-next jump-10-jump) (call store-10-ac-t) i-10-jsa (call load-10-ac) (call store-10-mem) (call-xct-next get-10-pc) ((m-1) m-e) (call store-10-ac) (jump-xct-next jump-10-jump) ((m-e) add m-e (a-constant 1)) i-10-jra ((m-t) m-e) (call load-10-ac) ((m-e) m-1) (call load-10-mem) (call store-10-ac) ((m-e) m-t) (jump jump-10-jump) ;Shift instructions. i-10-lsh (call load-10-ac) (jump-greater-than-or-equal m-e a-zero i-10-lsh-left) ((m-c) sub m-zero a-e) (call shift-10-right) ((m-c) pdp10-shift-count m-c) (call store-10-ac) (jump next-10-insn) i-10-lsh-left (call shift-10-left) ((m-c) pdp10-shift-count m-e) (call store-10-ac) (jump next-10-insn) i-10-ash (call load-10-ac) (jump-greater-than-or-equal m-e a-zero i-10-lsh-left) ((m-c) sub m-zero a-e) (call arith-shift-10-right) ((m-c) pdp10-shift-count m-c) (call store-10-ac) (jump next-10-insn) ;;;??? No point in writing the rest until I can write ;SHIFT-10-LEFT, etc.