From 14877b7aa78f29aac5c4dddf59e5e99a01f6de6f Mon Sep 17 00:00:00 2001 From: wfjm Date: Wed, 27 Jul 2022 08:11:37 +0200 Subject: [PATCH] tcodes: cpu_mmu.mac added; use macros - tools/asm-11/lib/halt_checks.mac: added, tcode support macros - tools/tcode/cpu_mmu.mac: added, with first sections --- tools/asm-11/lib/defs_mmu.mac | 51 +-- tools/asm-11/lib/halt_checks.mac | 42 +++ tools/asm-11/lib/tcode_std_start.mac | 4 +- tools/tcode/cpu_all.dat | 3 +- tools/tcode/cpu_mmu.mac | 500 +++++++++++++++++++++++++++ 5 files changed, 573 insertions(+), 27 deletions(-) create mode 100644 tools/asm-11/lib/halt_checks.mac create mode 100644 tools/tcode/cpu_mmu.mac diff --git a/tools/asm-11/lib/defs_mmu.mac b/tools/asm-11/lib/defs_mmu.mac index 6ede8372..555086a1 100644 --- a/tools/asm-11/lib/defs_mmu.mac +++ b/tools/asm-11/lib/defs_mmu.mac @@ -1,4 +1,4 @@ -; $Id: defs_mmu.mac 1184 2019-07-10 20:39:44Z mueller $ +; $Id: defs_mmu.mac 1261 2022-07-23 16:15:03Z mueller $ ; SPDX-License-Identifier: GPL-3.0-or-later ; Copyright 2015-2018 by Walter F.J. Mueller ; @@ -24,33 +24,34 @@ ; ; symbol definitions for ssr0 ; - m0.anr = 100000 - m0.ale = 040000 - m0.ard = 020000 - m0.trp = 010000 - m0.ent = 001000 - m0.mai = 000400 - m0.ico = 000200 - m0.dsp = 000020 - m0.ena = 000001 + m0.anr = 100000 ; abort non-resident + m0.ale = 040000 ; abort segment length + m0.ard = 020000 ; abort read-only violation + m0.trp = 010000 ; trap taken + m0.ent = 001000 ; enable traps + m0.mai = 000400 ; maintenance mode + m0.ico = 000200 ; instruction complete flag + m0.dsp = 000020 ; enable i/d space + m0.ena = 000001 ; enable mmu ; ; symbol definitions for ssr3 ; - m3.eub = 000040 - m3.e22 = 000020 - m3.dkm = 000004 - m3.dsm = 000002 - m3.dum = 000001 + m3.eub = 000040 ; enable unibus map + m3.e22 = 000020 ; enable 22bit addressing + m3.dkm = 000004 ; enable d space kernel + m3.dsm = 000002 ; enable d space supervisor + m3.dum = 000001 ; enable d space user ; ; symbol definitions for pdr regs ; - md.aia = 000200 - md.aiw = 000100 - md.dwn = 000010 - md.an7 = 000007 - md.arw = 000006 - md.atw = 000005 - md.atr = 000004 - md.an3 = 000003 - md.aro = 000002 - md.art = 000001 + md.slf = 000400 ; LSB of slf field + md.aia = 000200 ; access a, any access + md.aiw = 000100 ; access w, write access + md.dwn = 000010 ; ed field 1, down expansion + md.an7 = 000007 ; abort all; reserved + md.arw = 000006 ; allow r+w; no traps + md.atw = 000005 ; allow r+w; trap w + md.atr = 000004 ; allow r+w; trap r+w + md.an3 = 000003 ; abort all; reserved + md.aro = 000002 ; allow r; abort w; no traps + md.art = 000001 ; allow r; abort w; trap r diff --git a/tools/asm-11/lib/halt_checks.mac b/tools/asm-11/lib/halt_checks.mac new file mode 100644 index 00000000..51bc0df0 --- /dev/null +++ b/tools/asm-11/lib/halt_checks.mac @@ -0,0 +1,42 @@ +; $Id: halt_checks.mac 1262 2022-07-25 09:44:55Z mueller $ +; SPDX-License-Identifier: GPL-3.0-or-later +; Copyright 2022- by Walter F.J. Mueller +; +; Macros for checking a location and halt on error +; +; cmp on eq + .macro hcmpeq,src,dst + cmp src,dst + beq .+4 + halt + .endm +; cmpb on eq + .macro hcmbeq,src,dst + cmpb src,dst + beq .+4 + halt + .endm +; bit on ne + .macro hbitne,src,dst + bit src,dst + bne .+4 + halt + .endm +; bit on eq + .macro hbiteq,src,dst + bit src,dst + beq .+4 + halt + .endm +; tst on eq + .macro htsteq,src + tst src + beq .+4 + halt + .endm +; tstb on eq + .macro htsbeq,src + tstb src + beq .+4 + halt + .endm diff --git a/tools/asm-11/lib/tcode_std_start.mac b/tools/asm-11/lib/tcode_std_start.mac index c67cf965..a06931cd 100644 --- a/tools/asm-11/lib/tcode_std_start.mac +++ b/tools/asm-11/lib/tcode_std_start.mac @@ -1,4 +1,4 @@ -; $Id: tcode_std_start.mac 1184 2019-07-10 20:39:44Z mueller $ +; $Id: tcode_std_start.mac 1262 2022-07-25 09:44:55Z mueller $ ; SPDX-License-Identifier: GPL-3.0-or-later ; Copyright 2015- by Walter F.J. Mueller ; @@ -10,6 +10,8 @@ ; .include |lib/vec_cpucatch.mac| .include |lib/vec_devcatch.mac| +; + .include |lib/halt_checks.mac| ; . = 000200 jmp @#start diff --git a/tools/tcode/cpu_all.dat b/tools/tcode/cpu_all.dat index fe0dd6be..4d41a14a 100644 --- a/tools/tcode/cpu_all.dat +++ b/tools/tcode/cpu_all.dat @@ -1,4 +1,4 @@ -# $Id: cpu_all.dat 1260 2022-07-21 06:07:00Z mueller $ +# $Id: cpu_all.dat 1261 2022-07-23 16:15:03Z mueller $ # ## steering file for all cpu tests # @@ -6,4 +6,5 @@ cpu_basics.mac cpu_eis.mac cpu_details.mac cpu_badinst_nofpp.mac +cpu_mmu.mac cpu_selftest.mac diff --git a/tools/tcode/cpu_mmu.mac b/tools/tcode/cpu_mmu.mac new file mode 100644 index 00000000..f09e15b4 --- /dev/null +++ b/tools/tcode/cpu_mmu.mac @@ -0,0 +1,500 @@ +; $Id: cpu_mmu.mac 1262 2022-07-25 09:44:55Z mueller $ +; SPDX-License-Identifier: GPL-3.0-or-later +; Copyright 2022- by Walter F.J. Mueller +; +; Revision History: +; Date Rev Version Comment +; 2022-07-24 1262 1.0 Initial version +; +; Test CPU MMU: all aspects of the MMU +; Section A: pdr,par registers +; Section B: ssr0,ssr3 registers, mapping, instructions +; Section C: ssr1,ssr2 registers and traps +; Section D: aborts +; + .include |lib/tcode_std_base.mac| + .include |lib/defs_mmu.mac| +; some useful definitions + uipdr0 = uipdr+ 0 + uipar0 = uipar+ 0 + udpdr0 = udpdr+ 0 + udpar0 = udpar+ 0 + sipdr0 = sipdr+ 0 + sipar0 = sipar+ 0 + kipar6 = kipar+14 + kipar7 = kipar+16 +; +; Section A: pdr,par registers =============================================== +; +; Test A1: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +; +; Test A1.1 -- test that pdr/par are 16 bit write/readable +++++++++++ +; Write unique patterns to first and last pdr/par of each mode and read back +; +ta0101: mov #000401,r5 ; pattern master +;;; mov #077717,r5 ; bit mask for pdr +; +; write 000401,001002,002004,004010,... for pdr; complement for par + mov r5,r0 ; start pattern + mov #12.,r1 ; number tested regs + mov #9000$,r2 +1000$: mov (r2)+,r3 + mov r0,(r3) ; write pdr + add r5,r0 + dec r0 + mov r0,40(r3) ; write par + add r5,r0 + sob r1,1000$ +; +; read back + mov r5,r0 ; start pattern + mov #12.,r1 ; number of modes + mov #9000$,r2 +1100$: mov (r2)+,r3 + hcmpeq (r3),r0 ; check pdr + add r5,r0 + dec r0 + hcmpeq 40(r3),r0 ; check par + add r5,r0 + sob r1,1100$ +; +; complement all pattern + mov #12.,r1 ; number of modes + mov #9000$,r2 +1200$: mov (r2)+,r3 + mov (r3),r4 ; complement pdr only writable bits + com r4 + bic #100360,r4 ; mask non-writable (incl A and W) + mov r4,(r3) + com 40(r3) ; complement par + sob r1,1200$ +; +; and read back again +; pdr only slf,ed and acf fields are checked +; par all 18 bits are write/readable + mov r5,r0 ; start pattern + com r0 ; complemented + mov #12.,r1 ; number of modes + mov #9000$,r2 +1300$: mov (r2)+,r3 + mov r0,r4 + bic #100360,r4 ; mask non-writable (incl A and W) + hcmpeq (r3),r4 ; check pdr only writable bits + sub r5,r0 + inc r0 + hcmpeq 40(r3),r0 ; check par + sub r5,r0 + sob r1,1300$ +; + jmp 9999$ +; +9000$: .word uipdr ; usr i page dsc base 0 + .word uipdr+16 + .word udpdr ; usr d page dsc base 0 + .word udpdr+16 + .word sipdr ; sup i page dsc base 0 + .word sipdr+16 + .word sdpdr ; sup d page dsc base 0 + .word sdpdr+16 + .word kipdr ; ker i page dsc base 0 + .word kipdr+16 + .word kdpdr ; ker d page dsc base 0 + .word kdpdr+16 +; +9999$: iot ; end of test A1.1 +; +; Test A1.2 -- setup MMU default configuration +++++++++++++++++++++++ +; Nothing is verified, just sets the MMU for all further tests +; kernel I: 1-to-1 and seg7 to io-page +; kernel D: unmapped but seg7 to io-page +; supervisor and user I and D: unmapped (acf=0) +; +ta0102: +; first clear all pdr/par, that disables mapping (acf=0) + mov #1000$,r0 + mov #3,r1 +100$: mov (r0)+,r2 ; ptr to pdr+par I+D set (32 regs) + mov #8.,r3 ; 8 chunks of 4 +200$: clr (r2)+ + clr (r2)+ + clr (r2)+ + clr (r2)+ + sob r3,200$ + sob r1,100$ +; setup kernel I + mov #kipdr,r0 + mov #<127.*md.slf>!md.arw,r1 ; slf=127; ed=0(up); acf=6(w/r) + mov r1,(r0)+ ; kipdr0 + mov r1,(r0)+ ; kipdr1 + mov r1,(r0)+ ; kipdr2 + mov r1,(r0)+ ; kipdr3 + mov r1,(r0)+ ; kipdr4 + mov r1,(r0)+ ; kipdr5 + mov r1,(r0)+ ; kipdr6 + mov r1,(r0)+ ; kipdr7 + mov #kipar,r0 + mov #000000,(r0)+ ; kipar0 000000 base + mov #000200,(r0)+ ; kipar1 020000 base + mov #000400,(r0)+ ; kipar2 040000 base + mov #000600,(r0)+ ; kipar3 060000 base + mov #001000,(r0)+ ; kipar4 100000 base + mov #001200,(r0)+ ; kipar5 120000 base + mov #001400,(r0)+ ; kipar6 140000 base + mov #177600,(r0)+ ; kipar7 (map I/O page) +; setup kernel D + mov #kdpdr,r0 + mov r1,16(r0) ; kdpdr7 slf=127; ed=0(up); acf=6(w/r) + mov #kdpar,r0 + mov #177600,16(r0) ; kdpar7 (map I/O page) +; + jmp 9999$ +; +1000$: .word uipdr + .word sipdr + .word kipdr +; +9999$: iot ; end of test A1.2 +; +; Section B: ssr0,ssr3 registers, mapping, instructions ====================== +; Test whether address mapping works (traps and aborts avoided) +; +; Test B1: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +; Test kernel mode +; +; Test B1.1 -- test 1-to-1 kernel mode mapping +++++++++++++++++++++++ +; simply enable MMU, shouldnt make a difference +; test that 18bit mode extends I/O page addressing +; test that RESET clears ssr0 and ssr3 +; +; This test verifies +; x xxx xxx xxx xxx xxx NZVC Instruction / Remark +; 0 000 000 000 000 101 ---- RESET (clear ssr0,ssr3) +; +tb0101: mov #123456,1000$ +; enable mmu in 18bit mode + clr ssr3 ; no d dspace, no 22bit + mov #m0.ena,ssr0 ; enable mmu + hbitne #m0.ena,ssr0 ; test bit ;! MMU 18 + hcmpeq 1000$,#123456 ; check marker +; verify I/O page mapping in 18bit mode (007600 must be OK) + mov #kipar7,r0 ; ptr to kipar7 + bic #170000,(r0) ; clear to 4 bits in kipar7 + hcmpeq (r0),#007600 ; kipar7 still seen ??? + bis #170000,(r0) ; restore kipar7 + hcmpeq (r0),#177600 +; enable mmu in 22bit mode; check that ssr3 still seen + mov #m3.e22,ssr3 + hcmpeq ssr3,#m3.e22 ; test ssr3 stll seen ??? ;! MMU 22 +; test RESET + reset ; should clear ssr0 and ssr3 + htsteq ssr0 ; check ssr0 cleared ;! MMU off + htsteq ssr3 ; check ssr3 cleared + jmp 9999$ +; +1000$: .word 0 +; +9999$: iot ; end of test B1.1 +; +; Test B1.2 -- test variable kernel mode mapping +++++++++++++++++++++ +; change seg6 mapping +; test that 18bit mode discards the 4 MSB of the par +; +tb0102: mov #kipar6,r0 ; ptr to kipar6 + mov #140000,r5 ; seg6 base + mov #140000,(r5) ; init markers + clr 2(r5) + mov #140100,100(r5) ; init markers + clr 102(r5) +; + clr ssr3 ; no d dspace, no 22bit + mov #m0.ena,ssr0 ; enable mmu ;! MMU 18 +; check in 1-to-1 mapping + hcmpeq (r5),#140000 + htsteq 2(r5) + hcmpeq 100(r5),#140100 + htsteq 102(r5) +; move seg6 mapping up by one click + inc (r0) ; move kipar6 base up + hcmpeq (r0),#001401 + hcmpeq 0(r5),#140100 + mov #010000,2(r5) ; write marker +; set MSBs in kipar6, should be discarded in 18bit mode, check markers + bis #170000,(r0) + hcmpeq (r0),#171401 + hcmpeq (r5),#140100 ; check marker + bic #170000,(r0) + hcmpeq (r0),#001401 +; move seg6 mapping down by one click + dec (r0) ; move kipar6 base up + hcmpeq (r0),#001400 + mov #020000,2(r5) ; write marker + hcmpeq 2(r5),#020000 ; check marker + hcmpeq 102(r5),#010000 ; check marker +; disable MMU + reset ; mmu off ;! MMU off +; +9999$: iot ; end of test B1.2 +; +; Test B2: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +; Test user and supervisor mode +; +; Test B2.1 -- run code in user/supervisor mode ++++++++++++++++++++++ +; code vc0 is executed in user and in supervisor mode +; the code runs in seg0 with D space disabled +; +tb0201: +; setup emt handler + mov #vhuemt,v..emt + clr v..emt+2 ; pr0 kernel +; enable mmu + clr ssr3 ; no d dspace, no 22bit + mov #m0.ena,ssr0 ; enable mmu ;! MMU 18 +; +; run code vc0 in user mode -------------------------------- +; +; set user mode pdr/par, only short segment 0 + mov #<8.*md.slf>!md.arw,uipdr0 + mov #,uipar0 +; setup data for user mode run + mov #023456,vc0v0; + mov #000123,vc0v1 + mov #077321,vc0v2 +; start code in user mode + mov #1000$,vhustp ; setup continuation address + mov #cp.cmu,-(sp) ; next psw: user mode + clr -(sp) ; will start at 0 + rti ; and launch it + halt +1000$: ; continuation point +; check psw + ccc ; clear cc -> psw reflects pm setting + hcmpeq cp.psw,#cp.pmu ; check pm +; check data + hcmpeq vc0v0,#154321 + hcmpeq vc0v2,#077444 +; reset user mode pdr/par + clr uipdr0 + clr uipar0 +; +; run code vc0 in supervisor mode -------------------------- +; +; set supervisor mode pdr/par, only short segment 0 + mov #<8.*md.slf>!md.arw,sipdr0 + mov #,sipar0 +; setup data for user mode run + mov #017171,vc0v0 + mov #000321,vc0v1 + mov #100123,vc0v2 +; start code in supervisor mode + mov #2000$,vhustp ; setup continuation address + mov #cp.cms,-(sp) ; next psw: supervisor mode + clr -(sp) ; will start at 0 + rti ; and launch it + halt +2000$: ; continuation point +; check psw + ccc ; clear cc -> psw reflects pm setting + hcmpeq cp.psw,#cp.pms ; check pm +; check data + hcmpeq vc0v0,#160606 + hcmpeq vc0v2,#100444 +; reset supervsior mode pdr/par + clr sipdr0 + clr sipar0 +; + reset ; mmu off ;! MMU off + mov #v..emt+2,v..emt ; restore emt catcher + clr v..emt+2 +; +9999$: iot ; end of test B2.1 +; +; Test B2.2 -- run code in user mode with D space enabled ++++++++++++ +; code vc1 is executed in user and in supervisor mode +; the code runs in seg0 with D space enabled +; +; This test verifies +; x xxx xxx xxx xxx xxx NZVC Instruction / Remark +; 0 000 110 101 ddd ddd NZ0- MFPI +; 0 000 110 110 ddd ddd NZ0- MTPI +; 1 000 110 101 ddd ddd NZ0- MFPD +; 1 000 110 110 ddd ddd NZ0- MTPD +; +tb0202: +; setup emt handler + mov #vhuemt,v..emt + clr v..emt+2 ; pr0 kernel +; enable mmu + mov #m3.dum,ssr3 ; user d dspace, no 22bit + mov #m0.ena,ssr0 ; enable mmu ;! MMU 18 +; +; run code vc1 in user mode -------------------------------- +; +; set user mode pdr/par, only short segment 0; I and D + mov #<8.*md.slf>!md.arw,uipdr0 + mov #,uipar0 + mov #<8.*md.slf>!md.arw,udpdr0 + mov #,udpar0 +; setup data for user mode run + mov #020305,vc1v0 + mov #000212,vc1v1 + mov #033121,vc1v2 +; start code in user mode + mov #1000$,vhustp ; setup continuation address + mov #cp.cmu,-(sp) ; next psw: user mode + clr -(sp) ; will start at 0 + rti ; and launch it + halt +1000$: ; continuation point +; check psw + ccc ; clear cc -> psw reflects pm setting + hcmpeq cp.psw,#cp.pmu ; check pm +; check data + hcmpeq vc1v0,#157472 + hcmpeq vc1v2,#033333 +; +; psw has now pm=user and cm=kernel; good setup to test MFPI and friends +; +; test MFPD +; + mov #,r5 ; initialize data pointer + mfpd (r5) ; read vc1v0 + hcmpeq (sp)+,#157472 + mfpd @# ; read vc1v2 + hcmpeq (sp)+,#033333 +; +; test MTPD and MFPD, incl cc +; + mov #2010$,r4 ; ptr to test data + mov #2011$,r3 ; ptr to test end +2000$: mov (r4)+,-(sp) + ccc ; C=0 + mtpd (r5) ; write vc1v0 + hcmpeq cp.psw,(r4)+ ; check cc + hcmpeq vc1v0,-4(r4) ; check target + scc ; C=1 + mfpd (r5) + hcmpeq cp.psw,(r4)+ ; check cc + cmp r4,r3 ; more to do ? + blo 2000$ +; +; test MFPI +; + mov #,r5 ; initialize data pointer + mfpi (r5) ; read 1st instruction word + hcmpeq (sp)+,vc1 +; +; test MTPI and MFPI, incl cc +; + mov #,r5 ; initialize data pointer + mov #3010$,r4 ; ptr to test data + mov #3011$,r3 ; ptr to test end +3000$: mov (r4)+,-(sp) + scc ; C=1 + mtpi (r5) ; write vc1ida + hcmpeq cp.psw,(r4)+ ; check cc + hcmpeq vc1ida,-4(r4) ; check target + ccc ; C=0 + mfpi (r5) + hcmpeq cp.psw,(r4)+ ; check cc + cmp r4,r3 ; more to do ? + blo 3000$ +; +; reset user mode pdr/par + clr uipdr0 + clr uipar0 + clr udpdr0 + clr udpar0 +; + reset ; mmu off ;! MMU off + mov #v..emt+2,v..emt ; restore emt catcher + clr v..emt+2 + jmp 9999$ +; +; test data for m*pd tests (C=0 for T and C=1 for F) +2010$: .word 000000,cp.pmu!cp0z00,cp.pmu!cp0z0c + .word 000001,cp.pmu!cp0000,cp.pmu!cp000c + .word 100000,cp.pmu!cpn000,cp.pmu!cpn00c +2011$: +; +; test data for m*pi tests (C=1 for T and C=0 for F) +3010$: .word 000000,cp.pmu!cp0z0c,cp.pmu!cp0z00 + .word 000001,cp.pmu!cp000c,cp.pmu!cp0000 + .word 100000,cp.pmu!cpn00c,cp.pmu!cpn000 +3011$: +; +9999$: iot ; end of test B2.2 +; +; END OF ALL TESTS - loop closure ============================================ +; + mov tstno,r0 ; hack, for easy monitoring ... + hcmpeq tstno,#6. ; all tests done ? +; + jmp loop +; +; kernel handlers ============================================================ +; +; vhuemt - emt handler, drop frame, continue in kernel mode ++++++++++++++++++ +; use to end user/supervisor mode code with an emt xxx +; the kernel continution address must be written to vhustp +; execution will reset vhustp to a catcher value +; --> vhustp must be set for each execution +; +vhuemt: tst (sp)+ ; discard on word of vector push + mov vhustp,(sp) ; setup kernel return address + mov vhuhlt,vhustp ; reset stop address by catcher + rts pc ; end return to continuation address +vhustp: .word vhuhlt +vhuhlt: halt +; +; Test codes that will be mapped in user or supervisor mode ================== +; They are located at 100000 and above and are position-independent code. +; That allows to assemble and load them together with the main code. +; +; vc0 - simple code ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +; uses jsr, has stack below 1000 (no problem in user/supervisor mode) +; does operations with vc0v0, vc0v1, vc0v2 +; these location are usually set before and checked afterwards in kernel mode +; + . = 100000 +vc0: jmp 100$ + .blkw 14. ; small stack space +100$: mov #40,sp ; initialize stack + jsr pc,1000$ + emt 100 ; will end user/supervisor code +; +1000$: com vc0v0 + jsr pc,2000$ + rts pc +2000$: add vc0v1,vc0v2 + rts pc +; +vc0v0: .word 0 +vc0v1: .word 0 +vc0v2: .word 0 +; +; vc1 - simple I/D code ++++++++++++++++++++++++++++++++++++++++++++++++++++++ +; uses jsr, has stack below 1000 (no problem in user/supervisor mode) +; does operations with vc1v0, vc1v1, vc1v2 +; these location are usually set before and checked afterwards in kernel mode +; + . = 101000 ; I space +vc1: mov #,sp ; initialize stack + mov #,r5 ; initialize data pointer + jsr pc,1000$ + emt 100 ; will end user/supervisor code +; +1000$: com (r5) ; will access vc1v0 + jsr pc,2000$ + rts pc +2000$: add 2(r5),4(r5) ; will access vc1v1 and vc1v2 + rts pc +; +vc1ida: .word 0 ; I space location, MTPI target +; + . = 102000 ; D space +vc1dat: .blkw 16. ; small stack space +vc1v0: .word 0 +vc1v1: .word 0 +vc1v2: .word 0 +; + .end start