; $Id: cpu_details.mac 1359 2023-01-27 20:58:50Z mueller $ ; SPDX-License-Identifier: GPL-3.0-or-later ; Copyright 2022-2023 by Walter F.J. Mueller ; ; Revision History: ; Date Rev Version Comment ; 2023-01-27 1359 1.1 use .mcall and mlib; use rt?jmp, hta??? macros ; 2023-01-11 1349 1.0 Initial version ; 2022-07-18 1259 0.1 First draft ; ; Test CPU details ; Section A: CPU registers ; Section B: stress and flow tests ; Section C: 11/70 specifics ; .include |lib/tcode_std_base.mac| .include |lib/defs_mmu.mac| ; .mcall push,pop,push2 .mcall hcmpeq,htsteq,htstne,htstge,hbiteq,hbitne .mcall vecset,vecclr .mcall rtijmp,rttjmp .mcall htabuf,htaadd,htaini,htacmp ; ; Preface: set up MMU for kernel mode (for some tests) ======================= ; mov #kipdr,r0 mov #<127.*md.plf>!md.arw,r1 ; plf=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) ; ; some useful definitions kipdr5 = kipdr+12 kipdr6 = kipdr+14 kipar6 = kipar+14 p6base = <6*20000> ; page 6 ; ; Section A: CPU registers =================================================== ; A1 PIRQ ; A1.1 PIRQ + spl ; A1.2 PIRQ and immediate interrupt ; A2 CPUERR ; A2.1 CPUERR cp.hlt ; A2.2 CPUERR cp.odd ; A2.3 CPUERR cp.nxm ; A2.4 CPUERR cp.iot ; A2.5 CPUERR cp.ysv ; A2.6 CPUERR cp.rsv ; A2.7 CPUERR cp.odd + stack error ; A2.8 CPUERR cp.nxm + stack error ; A2.9 CPUERR cp.ito + stack error ; A2.10 CPUERR mmu abort + stack error ; A3 STKLIM + stack traps and aborts ; A3.1 STKLIM write/read test ; A3.2 yellow trap + red abort boundary ; part 1: sequence of yellow traps and a final red stack abort ; part 2: check that red zone does not have yellow islands ; part 3: check red zone PSW protection ; A3.3 stack trap conditions ; part 1: test instructions that should trap ; part 2: test instructions that should not trap ; part 3: test that interrupt (from PIRQ) vector push traps ; A3.4 red stack abort conditions ; A3.5 vector push abort recovery ; A4 PSW + tbit traps ; A4.1 PSW direct write/read test ; part 1: all bits except register set (cp.ars) ; part 2: PSW(11) - register set ; part 3: PSW(cm) and stack registers ; A4.2 PSW write/read via RTI/RTT ; part 1: from cm=0,rset=0: set cm=11 and rset=1 (fine!) ; part 2: from cm=s,rset=1 mode: set cm=0 and rset=0 (fail!) ; part 3: from cm=s,rset=0 mode: set cm=u and rset=1 (fine!) ; part 4: from cm=u,rset=1 mode: set cm=0 and rset=0 (fail!) ; part 5: from cm=k,pri=0: set pri=6 (fine!) ; part 6: from cm=s,pri=0: set pri=6 (fail!) ; part 7: from cm=u,pri=0: set pri=6 (fail!) ; A4.3 RTI/RTT tbit basics ; part 1: tbit after RTI ; part 2: tbit after RTT ; A4.4 tbit trace tests ; part 0: traced TRAP that clears tbit ; part 1: simple instruction sequence ; part 2: tracing of trap instructions (EMT tested) ; part 3: tbit vs interrupt precedence (via PIRQ) ; part 4: traced WAIT and tbit ; part 5: WAIT and SPL in user mode ; part 6: tbit trap after continuation over s_idle ; part 7: no tbit trap after an abort ; part 8: traced RTI that clears tbit ; part 9: EMT that sets tbit ; part 10: PIRQ that sets tbit ; A5 MBRK ; ; Test A1: PIRQ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; This sub-section verifies operation of PIRQ register ; ; Test A1.1 -- PIRQ + spl ++++++++++++++++++++++++++++++++++++++++++++ ; This test will exercise all 7 pirq interrupt levels: ; set 1+3 -> handle 3, set 7 ; -> handle 7, set 6+4 ; -> handle 6 ; -> handle 4, set 5+2 ; -> handle 5 ; -> handle 2 ; -> handle 1 ; ; some useful definitions pi.r00=bit08 ; pir 0 bit pi.r01=bit09 ; pir 1 bit pi.r02=bit10 ; pir 2 bit pi.r03=bit11 ; pir 3 bit pi.r04=bit12 ; pir 4 bit pi.r05=bit13 ; pir 5 bit pi.r06=bit14 ; pir 6 bit pi.r07=bit15 ; pir 7 bit pi.n00=0. ; lsb for no pir pending pi.n01=1*042 ; lsb for pir 1 next pi.n02=2*042 ; lsb for pir 2 next pi.n03=3*042 ; lsb for pir 3 next pi.n04=4*042 ; lsb for pir 4 next pi.n05=5*042 ; lsb for pir 5 next pi.n06=6*042 ; lsb for pir 6 next pi.n07=7*042 ; lsb for pir 7 next ; ta0101: vecset v..pir,1000$,cp.pr7 ; set up PIRQ handler at pr7 mov #cp.pir,r3 ; ptr to PIRQ mov #cp.psw,r4 ; ptr to PSW mov #1200$,r5 ; ptr to check data clr 1300$ ; clear nesting counter ; spl 7 ; lockout interrupts bisb #bit01,1(r3) ; set PIRQ 1 hcmpeq (r3),# ; check set 1 bisb #bit03,1(r3) ; set PIRQ 3 hcmpeq (r3),# ; check set 1+3 spl 2 nop ; allow interrupts to happen spl 0 nop ; allow interrupts to happen htsteq (r3) ; PIRQ should clear now vecclr v..pir ; restore pirq vector catcher jmp 9999$ ; ; PIRQ interrupt handler ; - it starts at pr7 from the vector ; - quickly lowers the priority to what is currently processed ; - new pirq bits are set at lowered priority ; - that leads to nested interrupts (tracked by a level counter) ; 1000$: inc 1300$ ; up level counter mov (r3),r0 ; get PIRQ value hcmpeq 1300$,(r5)+ ; check nesting level hcmpeq r0,(r5)+ ; check pirq value movb r0,(r4) ; PSW=PIRQ (sets priority) bic #177761,r0 ; mask out index bits mov r0,r1 ; r0 is word index (pri*2) asr r1 ; r1 is byte index (pri*1) mov #pi.r00,r2 ash r1,r2 ; r2 = pi.r00 <<(pri) bic r2,(r3) ; clear current level in pirq bis 1100$(r0),(r3) ; trigger new pirqs nop ; allow nested interrupts to happen nop ; dec 1300$ ; down level counter rti ; ; table with new pirqs triggered at a level 1100$: .word 0 ; new pirq @ level 0 .word 0 ; new pirq @ level 1 .word 0 ; new pirq @ level 2 .word pi.r07 ; new pirq @ level 3 -> 7 .word pi.r05!pi.r02 ; new pirq @ level 4 -> 5+2 .word 0 ; new pirq @ level 5 .word 0 ; new pirq @ level 6 .word pi.r06!pi.r04 ; new pirq @ level 7 -> 6+4 ; ; table with expected values of pirq register in interrupt sequence 1200$: .word 1,pi.r01!pi.r03!pi.n03 ; set 1+3 -> handle 3, set 7 .word 2,pi.r01!pi.r07!pi.n07 ; set 1+7 -> handle 7, set 6+4 .word 2,pi.r01!pi.r04!pi.r06!pi.n06 ; set 1+4+6 -> handle 6 .word 2,pi.r01!pi.r04!pi.n04 ; set 1+4 -> handle 4, set 5+2 .word 3,pi.r01!pi.r02!pi.r05!pi.n05 ; set 1+2+5 -> handle 5 .word 1,pi.r01!pi.r02!pi.n02 ; set 1+2 -> handle 2 .word 1,pi.r01!pi.n01 ; set 1 -> handle 1 ; nesting level counter 1300$: .word 0 ; 9999$: iot ; end of test A1.1 ; ; Test A1.2 -- PIRQ and immediate interrupt ++++++++++++++++++++++++++ ; This test verifies that an interrupt is taken immediately after the ; write of the PIRQ register ; ta0102: spl 0 ; ensure execution at PR0 vecset v..pir,1000$,cp.pr7 ; set up PIRQ handler at pr7 mov #pi.r03,cp.pir ; request PIRQ 3 halt ; halt if not taken immediatly ; 1000$: clr cp.pir ; cancel all PIRQ levels mov #1100$,(sp) ; continue rti ; 1100$: vecclr v..pir ; restore pirq vector catcher ; 9999$: iot ; end of test A1.2 ; ; Test A2: CPUERR +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; This sub-section verifies operation of CPUERR register ; ; setup for all A2.* tests mov #cp.err,r0 ; ptr tp CPUERR vecset v..iit,vhugen ; set iit handler at pr0 ; ; Test A2.1 -- CPUERR cp.hlt +++++++++++++++++++++++++++++++++++++++++ ; Test cp.hlt: halt in non-kernel mode ; ta0201: mov #177777,(r0) ; clear CPUERR (any write should) htsteq (r0) ; ensure that CPUERR is zero ; mov #4000$,r2 ; mode list (user,supervisor) mov #2,r3 ; number of modes ; 1000$: clr r1 ; clear tracer mov #3000$,vhustp ; continuation address push (r2)+ ; frame: psw push #2000$ ; frame: address rti ; start user mode code halt ; 2000$: inc r1 ; proof of execution halt ; that will abort inc r1 tst @#001 ; that must abort ; 3000$: hcmpeq r1,#1 ; check tracer hcmpeq (r0),#cp.hlt ; check CPUERR mov #cp.rsv,(r0) ; clear CPUERR (any write should) htsteq (r0) ; check CPUERR ; sob r3,1000$ ; go for next mode ; br 9999$ ; 4000$: .word ; user mode .word ; supervisor mode ; 9999$: iot ; end of test A2.1 ; ; Test A2.2 -- CPUERR cp.odd +++++++++++++++++++++++++++++++++++++++++ ; Test cp.odd: odd address error abort ; ta0202: mov #1000$,vhustp ; continuation address tst @#001 ; odd address access halt 1000$: hcmpeq (r0),#cp.odd ; check CPUERR clr (r0) ; clear CPUERR (any write should) htsteq (r0) ; check CPUERR ; 9999$: iot ; end of test A2.2 ; ; Test A2.3 -- CPUERR cp.nxm +++++++++++++++++++++++++++++++++++++++++ ; Test cp.nxm: non-existent memory abort ; Use unibus map address space (248kB) below the I/O page, the w11 ; will return a non-existent memory abort even in a maximum memory ; configuration. ; ta0203: cmpb systyp,#sy.e11 ; e11 V7.3 return wrong CPUERR value beq 9999$ push kipar6 ; save kipar6 mov #177400,kipar6 mov #m3.e22,mmr3 ; 22-bit mode mov #m0.ena,mmr0 ; enable mmu ;! MMU 22 ; mov #1000$,vhustp ; continuation address tst p6base ; access non-existing memory halt 1000$: hcmpeq (r0),#cp.nxm ; check CPUERR com (r0) ; clear CPUERR (any write should) htsteq (r0) ; check CPUERR ; reset ; disable mmu ;! MMU off pop kipar6 ; restore kipar6 9999$: iot ; end of test A2.3 ; ; Test A2.4 -- CPUERR cp.ito +++++++++++++++++++++++++++++++++++++++++ ; Test cp.ito: unibus timeout abort ; Use first address in I/O page (160000), always unused in w11 ; ta0204: mov #1000$,vhustp ; continuation address tst @#160000 ; access non-existing unibus device halt 1000$: hcmpeq (r0),#cp.ito ; check CPUERR clr (r0) ; clear CPUERR (any write should) htsteq (r0) ; check CPUERR ; 9999$: iot ; end of test A2.4 ; ; Test A2.5 -- CPUERR cp.ysv +++++++++++++++++++++++++++++++++++++++++ ; Test cp.ysv: yellow stack trap ; Since stack is still usable after the trap, the vhugen handler can be used. ; ta0205: cmpb systyp,#sy.e11 ; e11 V7.3 doesnt trap, runs on hold beq 9999$ mov #1000$,vhustp ; continuation address mov #400,sp clr -(sp) ; should trap (not abort) halt ; not executed, handler continues at 1000$ 1000$: hcmpeq (r0),#cp.ysv ; check CPUERR clr (r0) ; clear CPUERR (any write should) htsteq (r0) ; check CPUERR ; mov #stack,sp 9999$: iot ; end of test A2.5 ; ; Test A2.6 -- CPUERR cp.rsv +++++++++++++++++++++++++++++++++++++++++ ; Test cp.rsv: red stack trap - simple low stack case ; ta0206: cmpb systyp,#sy.e11 ; e11 V7.3 doesnt abort, runs on hold beq 9999$ mov #1000$,v..iit ; setup direct iit handler mov #340,sp clr -(sp) ; should abort (not trap) halt 1000$: htsteq sp ; check SP=0 hcmpeq (r0),#cp.rsv ; check CPUERR clr (r0) ; clear CPUERR (any write should) htsteq (r0) ; check CPUERR mov #stack,sp ; restore stack ; 9999$: iot ; end of test A2.6 ; ; Test A2.7 -- CPUERR cp.odd + stack error +++++++++++++++++++++++++++ ; Test cp.odd: fatal stack error after odd stack ; ta0207: cmpb systyp,#sy.e11 ; e11 V7.3 pushes to odd stack, abort after halt beq 9999$ cmpb systyp,#sy.sih ; SimH uses J11 semantics bne 100$ mov #,1010$+2 ; and sets rsv for all stack errors ; 100$: mov #1000$,v..iit ; setup direct iit handler mov #stack-1,sp clr -(sp) ; odd-address abort, fatal stack error halt 1000$: htsteq sp ; check SP=0 1010$: hcmpeq (r0),#cp.odd ; check CPUERR clr (r0) ; clear CPUERR (any write should) htsteq (r0) ; check CPUERR mov #stack,sp ; restore stack ; 9999$: iot ; end of test A2.7 ; ; Test A2.8 -- CPUERR cp.nxm + stack error +++++++++++++++++++++++++++ ; Test cp.nxm: fatal stack error after non-existent memory abort ; Setup like in A2.3, put stack at p6base+4 ; ta0208: cmpb systyp,#sy.e11 ; e11 V7.3 pushes to bad stack, abort after halt beq 9999$ cmpb systyp,#sy.sih ; SimH uses J11 semantics bne 100$ mov #,1010$+2 ; and sets rsv for all stack errors ; 100$: mov #1000$,v..iit ; setup direct iit handler mov #177400,kipar6 mov #m3.e22,mmr3 ; 22-bit mode mov #m0.ena,mmr0 ; enable mmu ;! MMU 22 ; mov #p6base+4,sp ; stack in non-existing memory clr -(sp) ; non-existing memory, fatal stack error halt 1000$: htsteq sp ; check SP=0 1010$: hcmpeq (r0),#cp.nxm ; check CPUERR clr (r0) ; clear CPUERR (any write should) htsteq (r0) ; check CPUERR mov #stack,sp ; restore stack ; reset ;! MMU off mov #001400,kipar6 ; restore kipar6 ; 9999$: iot ; end of test A2.8 ; ; Test A2.9 -- CPUERR cp.ito + stack error +++++++++++++++++++++++++++ ; Test cp.ito: fatal stack error after unibus timeout ; Setup like in A2.4, put stack at 160004 ; ta0209: cmpb systyp,#sy.e11 ; e11 V7.3 pushes to bad stack, abort after halt beq 9999$ cmpb systyp,#sy.sih ; SimH uses J11 semantics bne 100$ mov #,1010$+2 ; and sets rsv for all stack errors ; 100$: mov #1000$,v..iit ; setup direct iit handler mov #160004,sp ; stack at non-existing unibus device clr -(sp) ; non-existing memory, fatal stack error halt 1000$: htsteq sp ; check SP=0 1010$: hcmpeq (r0),#cp.ito ; check CPUERR clr (r0) ; clear CPUERR (any write should) htsteq (r0) ; check CPUERR mov #stack,sp ; restore stack ; 9999$: iot ; end of test A2.9 ; ; Test A2.10 -- CPUERR mmu abort + stack error +++++++++++++++++++++++ ; Test cp.rsv: fatal stack error after mmu abort ; Set kernel I page 6 to non-resident ; ta0210: cmpb systyp,#sy.sih ; SimH uses J11 semantics bne 100$ mov #cp.rsv,1010$+2 ; and sets rsv for all stack errors ; 100$: mov #1000$,v..iit ; setup direct iit handler clr kipdr6 ; set non-resident mov #m3.e22,mmr3 ; 22-bit mode mov #m0.ena,mmr0 ; enable mmu ;! MMU 22 ; mov #p6base+4,sp ; stack in non-resident memory clr -(sp) ; MMU abort, fatal stack error halt 1000$: htsteq sp ; check SP=0 1010$: hcmpeq (r0),#0 ; check CPUERR (none set on w11) clr (r0) ; clear CPUERR (any write should) htsteq (r0) ; check CPUERR mov #stack,sp ; restore stack ; reset ;! MMU off mov kipdr5,kipdr6 ; restore kipdr6 (default kipdr are identical) ; 9999$: iot ; end of test A2.10 ; ; ----------------------------------------------- ; end of A2.* tests, restore iit handler vecclr v..iit ; restore iit catcher ; ; Test A3: STKLIM + stack traps and aborts ++++++++++++++++++++++++++++++++++ ; This sub-section verifies operation of STKLIM register, ; the yellow stack trap, and the red stack abort functionality. ; ; Test A3.1 -- STKLIM write/read test ++++++++++++++++++++++++++++++++ ; STKLIM is a 16 bit register, upper byte is retained, lower reads always 0 ; ta0301: ; ; part 1: word access ------------------------------------------------ ; mov #1000$,r0 ; ptr to value list mov #<1010$-1000$>/2,r1 ; # of values mov #377,r2 ; LSB byte mask mov #cp.slr,r3 ; ptr to STKLIM ; 100$: mov (r0)+,r4 ; get value mov r4,(r3) ; load STKLIM bic r2,r4 ; clear LSB hcmpeq r4,(r3) ; read and ckeck STKLIM sob r1,100$ ; go for next STKLIM value br 2000$ ; 1000$: .word ^b0101010101010101 .word ^b1010101010101010 .word ^b0000000011001100 ; STKLIM = 0 at end of test 1010$: ; ; part 2: byte access ------------------------------------------------ ; 2000$: movb #7,1(r3) ; write MSB hcmpeq #3400,(r3) ; check MSB written movb #70,(r3) ; write LSB hcmpeq #3400,(r3) ; check MSB unchanged clr (r3) ; STKLIM to default ; 9999$: iot ; end of test A3.1 ; ; Test A3.2 -- yellow trap + red abort boundary ++++++++++++++++++++++ ; ta0302: ; ; part 1: sequence of yellow traps and a final red stack abort ------- ; Verifies that push to STKLIM+376 to STKLIM+344 causes a yellow stack ; trap and a push to STKLIM+342 succeeds, but the yellow stack trap flow ; fails and causes a red stack trap. Done for ; 0 yellow below 000400 ; 1400 yellow below 002000 ; 157400 yellow below 156000 ; ; Note: SimH has simplified stack limit testing in vector flows. ; The stack is checked at end of flow. SimH will happily ; do yellow trap after push to +342 and write into +336. ; This part is therefore skipped for SimH ; cmpb systyp,#sy.sih ; on SimH ? bne 10$ ; if not, execute jmp 2000$ ; if yes, skip ; 10$: mov #1200$,r0 ; ptr to value list mov #<1210$-1200$>/2,r1 ; # of values vecset v..iit,1000$,cp.pr3 ; set up iit handler, pr3 as signature ; 100$: spl 6 ; use pr6 as code signature mov (r0)+,r5 ; get value mov r5,cp.slr ; load STKLIM clr 336(r5) ; clear word on red boundary mov r5,sp ; load SP add #400,sp ; to yellow boundary clr r2 ; clear yellow trap counter mov #1.,-(sp) ; push to STKLIM+376 -> trap mov #2.,-(sp) ; push to STKLIM+374 -> trap mov #3.,-(sp) ; push to STKLIM+372 -> trap mov #4.,-(sp) ; push to STKLIM+370 -> trap mov #5.,-(sp) ; push to STKLIM+366 -> trap mov #6.,-(sp) ; push to STKLIM+364 -> trap mov #7.,-(sp) ; push to STKLIM+362 -> trap mov #8.,-(sp) ; push to STKLIM+360 -> trap mov #9.,-(sp) ; push to STKLIM+356 -> trap mov #10.,-(sp) ; push to STKLIM+354 -> trap mov #11.,-(sp) ; push to STKLIM+352 -> trap mov #12.,-(sp) ; push to STKLIM+350 -> trap mov #13.,-(sp) ; push to STKLIM+346 -> trap mov #14.,-(sp) ; push to STKLIM+344 -> trap mov #15.,-(sp) ; push to STKLIM+342 -> try trap->abort 200$: halt halt ; 1000$: tst sp ; red abort seen ? beq 1010$ ; if yes, check status inc r2 ; if no, got for next push rti ; 1010$: hcmpeq #14.,r2 ; all traps taken ? hcmpeq #13.,346(r5) ; check 13th push hcmpeq #14.,344(r5) ; check 14th push hcmpeq #15.,342(r5) ; check 15th push (was done) hcmpeq #cp.pr6,340(r5) ; saved PS of attempted yellow trap htsteq 336(r5) ; red zone border clean ? hcmpeq #cp.pr6,@#2 ; saved PS of red abort hcmpeq #200$,@#0 ; saved PC of red abort dec r1 ; too far for sob beq 1020$ jmp 100$ ; go for next STKLIM value ; 1020$: clr cp.slr ; STKLIM to default mov #stack,sp ; SP to default vecclr v..iit ; v..iit to catcher spl 0 ; prio to default br 2000$ ; 1200$: .word 000000 .word 001400 .word 157400 1210$: ; ; part 2: check that red zone does not have yellow islands ----------- ; 2000$: cmpb systyp,#sy.e11 ; on e11 ? beq 3000$ ; if yes skip, e11 still buggy here ; mov #2300$,r0 ; ptr to values mov #<2310$-2300$>/2,r1 ; # of values vecset v..iit,2200$ ; set up iit handler mov #1400,cp.slr ; set yellow limit to 1776 ; 2100$: mov (r0)+,sp ; set SP to test value clr -(sp) ; expect red abort, not yellow trap halt ; 2200$: htsteq sp ; check SP=0 sob r1,2100$ ; clr cp.slr ; STKLIM to default mov #stack,sp ; SP to default vecclr v..iit ; v..iit to catcher br 3000$ ; 2300$: .word 001400 ; probe 1376 (possible yellow mirror) .word 001340 ; probe 1336 .word 001000 ; probe 0776 (possible yellow mirror) .word 000400 ; probe 0376 (possible yellow mirror) 2310$: ; ; part 3: check red zone PSW protection ------------------------------ ; push to 177776 should also cause a red stack abort ; 3000$: tstb systyp ; only done in w11 ble 9999$ ; mov #1400,cp.slr ; set STKLIM mov #1300,sp ; SP deep in red zone vecset v..iit,3100$ ; set up iit handler clr -(sp) ; expect red abort halt 3100$: htsteq sp ; check SP=0, on emergency stack vecset v..iit,3200$ ; set up iit handler clr -(sp) ; expect red abort again halt 3200$: htsteq sp ; check SP=0 because of PSW protection clr cp.slr ; STKLIM to default mov #stack,sp ; SP to default vecclr v..iit ; v..iit to catcher ; 9999$: iot ; end of test A3.2 ; ; Test A3.3 -- stack trap conditions +++++++++++++++++++++++++++++++++ ; Verifies that mode 1,2,4,6 trap for dstw flows and dstr when rmw ; Verifies that mode 3,5,7 writes do not trap ; Verifies that mode 1-7 reads do not trap ; Verifies that implict pushes (JSR,MFPI) trap ; Verifies that vector push of trap instructions (EMT,TRAP tested) traps ; Verifies that vector push of an interrupt (PIRQ tested) traps ; Notes: ; - dstw (mov,clr,..) and dstr (add,bis,...) flows write to stack -> test both ; - inspired by eqkce0 test 041 that verifies do/dont trap instruction cases ; - SimH and e11 currently do not support full 11/70 mode semantics ; ta0303: tstb systyp ; skip if not on w11 bge 100$ jmp 9999$ ; 100$: mov #1400,cp.slr ; set yellow limit to 1776 ; ; part 1: test instructions that should trap ------------------------- ; vecset v..iit,1000$ ; set up iit handler vecset v..emt,1100$ ; set up emt handler vecset v..trp,1200$ ; set up trap handler clr r2 ; clear trap counter ; ; dstw mode 1,2,4,6 mov #1000,-(sp) ; dstw mode 4: SP now 1776 (1) clr -(sp) ; dstw mode 4: SP now 1774 (2) mov (sp),(sp) ; dstw mode 1: SP now 1774 (3) clr (sp) ; dstw mode 1: SP now 1774 (4) mov (sp),(sp)+ ; dstw mode 2: SP now 1776 (5) clr 0(sp) ; dstw mode 6: SP now 1776 (6) mov (sp),0(sp) ; dstw mode 6: SP now 1776 (7) ; implied push jsr pc,1300$ ; implied push: SP now 1176 (8) mfpi r0 ; implied push: SP now 1774 (9) ; trap instrunctions emt 100 ; trap push: SP now 1174 (10) trap 200 ; trap push: SP now 1174 (11) ; dstr mode 1,2,4,6 when rmw add (sp),(sp) ; dstr mode 1: SP now 1174 (12) bis (sp),-(sp) ; dstr mode 4: SP now 1172 (13) incb (sp)+ ; dstr mode 2: SP now 1174 (14) dec 0(sp) ; dstr mode 6: SP now 1174 (15) ; br 1500$ ; 1000$: htstne sp ; no red stack aborts expected inc r2 rti ; 1100$: rti ; dummy emt handler 1200$: rti ; dummy trap handler 1300$: rts pc ; dummy routine ; 1500$: hcmpeq #15.,r2 ; all traps taken ? vecclr v..iit ; v..iit to catcher vecclr v..emt ; v..emt to catcher vecclr v..trp ; v..trp to catcher ; ; part 2: test instructions that should not trap --------------------- ; 2000$: mov #stack-2,r2 ; in yellow zone mov r2,(r2) ; load on stack (not using SP) mov r2,sp ; SP in yellow zone ; dstw mode 3,5,7 mov (sp)+,@-(sp) ; dstw mode 5: SP now 1176 mov @(sp),@(sp)+ ; dstw mode 3: SP now 1200 mov -(sp),@(sp) ; dstw mode 7: SP now 1176 ; dstr mode 3,5,7 when rmw bis (sp)+,@-(sp) ; dstw mode 5: SP now 1176 bis @(sp),@(sp)+ ; dstw mode 3: SP now 1200 bis -(sp),@(sp) ; dstw mode 7: SP now 1176 ; dstr mode 1,2,4,6 in read-only tst (sp) ; dstr mode 1: SP now 1176 cmp (sp),-(sp) ; dstr mode 4: SP now 1174 cmp (sp),(sp)+ ; dstr mode 2: SP now 1176 cmp (sp),0(sp) ; dstr mode 6: SP now 1176 ; dstr mode 3,5,7 in read-only cmp (sp),@(sp)+ ; dstr mode 3: SP now 1200 cmp (sp),@-(sp) ; dstr mode 5: SP now 1176 cmp (sp),@(sp) ; dstr mode 7: SP now 1176 ; check that EA is compared against STKLIM clr sp mov @#2000,2000(sp) ; SP=0, EA=2000 -> no trap ; ; part 3: test that interrupt (from PIRQ) vector push traps ---------- ; Triggers 3 PIRQ interrupts at PR1, PR3, and PR6. ; The PIRQ interrupt vector push will issue a ysv trap. ; That trap executes before the first instruction of the pir handler. ; The iit handler must therefore execute at PR7 to lockout interrupts. ; When the iit handler returns, the pir hander will execute. ; 3000$: vecset v..iit,3100$,cp.pr7 ; set up iit handler, lockout interrupts vecset v..pir,3200$,cp.pr7 ; set up pir handler, lockout interrupts mov #stack,sp ; SP to default (STKLIM still 1400) clr r2 ; clear trap counter mov #cp.pir,r3 ; ptr to cp.pir mov #3500$,r5 ; ptr to probe data ; spl 0 movb #bit06!bit03!bit01,1(r3) ; request PIRQ 6+3+1 nop br 3900$ ; ; iit handler 3100$: htstne sp ; no red stack aborts expected hcmpeq #177777,(r5)+ ; check state inc r2 rti ; ; pir handler 3200$: mov (r3),r0 ; get PIRQ bic #177761,r0 ; mask out index bits (is pri*2) asr r0 ; now pri*1 hcmpeq r0,(r5)+ ; check state mov #pi.r00,r1 ash r0,r1 ; pi.r00 <<(pri) bic r1,(r3) ; clear PIRQ request rti ; ; state check data 3500$: .word 177777,6. ; iit marker + pr6 pirq .word 177777,3. ; iit marker + pr3 pirq .word 177777,1. ; iit marker + pr1 pirq ; 3900$: hcmpeq #3.,r2 ; all traps taken ? vecclr v..iit ; v..iit to catcher vecclr v..pir ; v..pir to catcher ; ; final cleanup clr cp.slr ; STKLIM to default mov #stack,sp ; SP to default ; 9999$: iot ; end of test A3.3 ; ; Test A3.4 -- red stack abort conditions ++++++++++++++++++++++++++++ ; Verifies that instruction writes abort ; Verifies that implict pushes (JSR,MFPI) abort ; Verifies that vector push after trap instructions and interrupts abort ; Abort on 1st and 2nd push is tested. ; ta0304: vecset v..iit,1000$,cp.pr7 ; set up iit handler, lockout interrupts mov #1400,cp.slr ; yellow <=1776 and red <= 1736 clr @#1736 ; ensure top red word zero clr cp.err ; clear CPUERR ; ; dstw flow mov #1740,sp ; SP at red border mov #100$,r5 mov #123456,-(sp) halt ; ; dstr flow (rmw) 100$: mov #200$,r5 add (sp),-(sp) halt ; ; implicit push instructions 200$: mov #300$,r5 jsr pc,210$ halt 210$: halt ; 300$: mov #400$,r5 mfpi r0 halt ; ; vector flow abort in 2nd push, 1st push in yellow (use EMT for test) ; Note: SimH scribbles into red zone, therefore test skipped for SimH 400$: cmpb systyp,#sy.sih ; skip section on SimH beq 500$ mov sp,r0 mov #123456,(r0)+ ; write marker to 1740, r0 to avoid ysv mov r0,sp ; SP now 1402 -> abort on 2nd push mov #cp.pr3,cp.psw ; set pr3 as marker mov #420$,r5 ; leaves NZVC = 0000 emt 100 410$: halt 420$: hcmpeq #cp.pr3,@#1740 ; check that PS written ; ; vector flow abort in 1st push (use PIRQ for test) 500$: spl 0 mov #600$,r5 mov #pi.r04,cp.pir ; request PIRQ 4 halt 600$: clr cp.pir br 9000$ ; 1000$: htsteq sp ; check SP=0 htsteq @#1736 ; check stack clean hcmpeq #cp.rsv,cp.err ; check CPUERR.rsv (and no ysv) clr cp.err ; clear CPUERR mov #1740,sp ; restore SP jmp (r5) ; continue ; 9000$: clr cp.slr ; STKLIM to default vecclr v..iit ; v..iit to catcher mov #stack,sp ; SP to default spl 0 ; back to PR0 ; 9999$: iot ; end of test A3.4 ; ; Test A3.5 -- vector push abort recovery ++++++++++++++++++++++++++++ ; Verify that the frame pushed to the emergency stack after a vector push ; abort has the PS and PC values at entry into the initial vector flow and ; not the values read in the vector fetch of the failed vector flow. ; Test abort on 2nd and 1st push after a TRAP instruction. ; Skipped on SimH that has different vector flow stack limit check logic. ; See also cpu_mmu tests C2.5,C2.6, they check vector push abort by mmu. ; ta0305: cmpb systyp,#sy.sih ; skip in SimH (different stklim logic) beq 9999$ ; vecset v..iit,200$,cp.pr5!cp0z0c ; set up iit handler, PR5+0Z0C as sig vecset v..trp,110$,cp.pr6!cpn0v0 ; set up TRAP handler,PR6+N0V0 as sig mov #1400,cp.slr ; yellow <=1776 and red <= 1736 ; ; on abort 2nd push ------------------------------ mov #1742,sp ; 2nd push will fail spl 3 ; use PR3 as signature code ccc ; clear all ccs trap 100 ; will fail 100$: halt ; label after trap 110$: halt ; trap catcher ; 200$: htsteq sp ; check emergency stack done hcmpeq (sp),#100$ ; PC: return after trap hcmpeq 2(sp),#cp.pr3 ; PS: should be code signature ; ; on abort 1st push ------------------------------ mov #400$,v..iit ; set up iit handler mov #1740,sp ; 1st push will fail spl 4 ; use PR4 as signature code ccc ; clear all ccs sec ; and set C trap 200 ; will fail 300$: halt ; 400$: htsteq sp ; check emergency stack done hcmpeq (sp),#300$ ; PC: return after trap hcmpeq 2(sp),#cp.pr4!cp000c ; PS: should be code signature ; ; trap without error, checks in_vecflow reset ---- clr cp.slr ; STKLIM to default mov #600$,v..trp ; set up TRAP handler (continuation) mov #stack,sp ; 1st push will fail spl 2 ; use PR2 as signature code ccc ; clear all ccs sez ; and set z trap 300 ; will fail 500$: halt ; 600$: hcmpeq #stack-4,sp ; check stack, 1 frame hcmpeq (sp),#500$ ; PC: return after trap hcmpeq 2(sp),#cp.pr2!cp0z00 ; PS: should be code signature ; ; restore vecclr v..iit ; v..iit to catcher vecclr v..trp ; v..trp to catcher mov #stack,sp ; SP to default spl 0 ; back to PR0 ; 9999$: iot ; end of test A3.5 ; ; Test A4: PSW + tbit traps +++++++++++++++++++++++++++++++++++++++++++++++++ ; This sub-section verifies operation of PSW register and tbit traps. ; ; Test A4.1 -- PSW direct write/read test ++++++++++++++++++++++++++++ ; ta0401: ; ; part 1: all bits except register set (cp.ars) ---------------------- ; Note: In a direct PSW write the cc of the write prevail. ; This part tests dstw flow via MOV. Part 4 will test dstr flow. ; mov #cp.psw,r0 ; ptr to PSW mov #200$,r1 ; ptr to data mov #cpnzvc,r2 ; NZVC mask 100$: mov (r1)+,r3 ; next value beq 2000$ ; if 0 end of test mov r3,(r0) ; write PSW cmp (r0),(r1)+ ; check PSW beq 100$ clr (r0) ; if error force kernel halt ; and halt ; 200$: .word cp.c,cp.c ; C cc .word cp.v,cp.v ; V cc .word cp.z,cp.z ; Z cc .word cp.n,cp.n ; N cc .word cp.t,0 ; tbit (not direct writable) .word cp.pr7,cp.pr7 ; prio bits .word bit10!bit09!bit08,0 ; bit 10:8 unused .word bit12,bit12 ; pm(0) .word bit13,bit13 ; pm(1) .word bit14,bit14 ; cm(0) .word bit15,bit15 ; cm(1) .word 0 ; ; part 2: PSW(11) - register set ------------------------------------- ; 2000$: clr cp.psw ; select set 0 mov #1000,r0 ; write to set 0 mov #1001,r1 mov #1002,r2 mov #1003,r3 mov #1004,r4 mov #1005,r5 mov #cp.ars,cp.psw ; select set 1 hbitne #cp.ars,cp.psw ; check PSW write mov #1010,r0 ; write to set 1 mov #1011,r1 mov #1012,r2 mov #1013,r3 mov #1014,r4 mov #1015,r5 clr cp.psw ; select set 0 hbiteq #cp.ars,cp.psw ; check PSW write hcmpeq #1000,r0 ; check set 0 hcmpeq #1001,r1 hcmpeq #1002,r2 hcmpeq #1003,r3 hcmpeq #1004,r4 hcmpeq #1005,r5 mov #cp.ars,cp.psw ; select set 1 hcmpeq #1010,r0 ; check set 0 hcmpeq #1011,r1 hcmpeq #1012,r2 hcmpeq #1013,r3 hcmpeq #1014,r4 hcmpeq #1015,r5 clr cp.psw ; select set 0 ; ; part 3: PSW(cm) and stack registers -------------------------------- ; mov #cp.psw,r0 ; ptr to PSW clr (r0) ; cm=k mov #0006,sp mov #cp.cms,(r0) ; cm=s mov #0106,sp mov #cp.cmu,(r0) ; cm=u mov #1106,sp clr (r0) ; cm=k hcmpeq #0006,sp ; check mov #cp.cms,(r0) ; cm=s mov sp,r1 mov #cp.cmu,(r0) ; cm=u mov sp,r2 clr (r0) ; cm=k hcmpeq #0106,r1 ; check in kernel to allow halt hcmpeq #1106,r2 ; check in kernel to allow halt ; clr (r0) mov #stack,sp ; ; part 4: verify PSW manipulation via BIS and BIC ; Note: In a direct PSW write the cc of the write prevail. ; mov #cp.psw,r0 ; ptr to PSW ccc bis #cp.n!cp.c,(r0) ; set N+C hcmpeq #cpn00c,(r0) ccc bis #cp.pr7!cp.z!cp.v,(r0) ; set PRI=7,Z+V hcmpeq #cp.pr7!cp0zv0,(r0) scc bic #cp.z!cp.v,(r0) ; clr Z+V hcmpeq #cp.pr7!cpn00c,(r0) clr (r0) ; back to normal ; 9999$: iot ; end of test A4.1 ; ; Test A4.2 -- PSW write/read via RTI/RTT ++++++++++++++++++++++++++++ ; Verifies cm, rset and priority priviledge escalation protection ; ta0402: ; ; part 1: from cm=0,rset=0: set cm=11 and rset=1 (fine!) ------------- ; rtijmp #cp.cmu!cp.ars,#1200$ ; new PS cm=u and rs=1 ; 1100$: .word 0 ; saved PS ; 1200$: mov cp.psw,1100$ ; save PS (use memory, rset=1!) clr cp.psw ; back to kernel mov #stack,sp ; restore stack bic #cpnzvc,1100$ ; discard NZVC hcmpeq #cp.cmu!cp.ars,1100$ ; check expected PS ; ; part 2: from cm=s,rset=1 mode: set cm=0 and rset=0 (fail!) --------- ; rtijmp #cp.cms!cp.ars,#2200$ ; PS cm=s and rs=1 ; .word 0,0 ; temporary stack 2100$: .word 0 ; 1st saved PS 2110$: .word 0 ; 2nd saved PS ; ; now in supervisor mode, try sneak to cm=k and rs=0 2200$: mov cp.psw,2100$ ; save PS mov #2100$,sp ; set up stack rtijmp #0,#2300$ ; new PS cm=k and rs=0 ; ; lands here after rti from cm=s -> still in cm=s 2300$: mov cp.psw,2110$ ; save PS clr cp.psw ; back to kernel mov #stack,sp ; restore stack bic #cpnzvc,2100$ ; discard NZVC hcmpeq #cp.cms!cp.ars,2100$ ; check expected 1st PS bic #cpnzvc,2110$ ; discard NZVC hcmpeq #cp.cms!cp.ars,2110$ ; check expected 2nd PS (same !) ; ; part 3: from cm=s,rset=0 mode: set cm=u and rset=1 (fine!) --------- ; rtijmp #cp.cms,#3200$ ; PS cm=s and rs=0 ; .word 0,0 ; temporary stack 3100$: .word 0 ; 1st saved PS 3110$: .word 0 ; 2nd saved PS ; ; now in supervisor mode, continue to cm=u and rs=1 3200$: mov cp.psw,3100$ ; save PS mov #3100$,sp ; set up stack rtijmp #cp.cmu!cp.ars,#3300$ ; new PS cm=u and rs=1 ; ; lands here after rti from cm=s -> now cm=u 3300$: mov cp.psw,3110$ ; save PS clr cp.psw ; back to kernel mov #stack,sp ; restore stack bic #cpnzvc,3100$ ; discard NZVC hcmpeq #cp.cms,3100$ ; check expected 1st PS bic #cpnzvc,2110$ ; discard NZVC hcmpeq #cp.cmu!cp.ars,3110$ ; check expected 2nd PS (now user) ; ; part 4: from cm=u,rset=1 mode: set cm=0 and rset=0 (fail!) --------- ; rtijmp #cp.cmu!cp.ars,#4200$ ; PS cm=u and rs=1 ; .word 0,0 ; temporary stack 4100$: .word 0 ; 1st saved PS 4110$: .word 0 ; 2nd saved PS ; ; now in user mode, try sneak to cm=k and rs=0 4200$: mov cp.psw,4100$ ; save PS mov #4100$,sp ; set up stack rtijmp #0,#4300$ ; new PS cm=k and rs=0 ; ; lands here after rti from cm=u -> still in cm=u 4300$: mov cp.psw,4110$ ; save PS clr cp.psw ; back to kernel mov #stack,sp ; restore stack bic #cpnzvc,4100$ ; discard NZVC hcmpeq #cp.cmu!cp.ars,4100$ ; check expected 1st PS bic #cpnzvc,4110$ ; discard NZVC hcmpeq #cp.cmu!cp.ars,4110$ ; check expected 2nd PS (same !) ; ; part 5: from cm=k,pri=0: set pri=6 (fine!) ------------------------- ; rtijmp #cp.pr6,#5100$ ; new PS cm=k,pri=6 ; 5100$: hcmpeq #cp.pr6,cp.psw ; check PS clr cp.psw ; back to normal mov #stack,sp ; restore stack ; ; part 6: from cm=s,pri=0: set pri=6 (fail!) ------------------------- ; rtijmp #cp.cms,#6200$ ; PS cm=s ; .word 0,0 ; temporary stack 6100$: .word 0 ; saved PS ; ; now in supervisor mode, try sneak to cm=s and pri=6 6200$: mov #6100$,sp ; set up stack rtijmp #cp.cms!cp.pr6,#6300$ ; new PS cm=s and pri=6 ; ; lands here after rti from cm=s 6300$: mov cp.psw,6100$ ; save PS clr cp.psw ; back to kernel mov #stack,sp ; restore stack bic #cpnzvc,6100$ ; discard NZVC hcmpeq #cp.cms,6100$ ; check expected PS, pri stays 0 ! ; ; part 7: from cm=u,pri=0: set pri=6 (fail!) ------------------------- ; rtijmp #cp.cmu,#7200$ ; PS cm=u ; .word 0,0 ; temporary stack 7100$: .word 0 ; saved PS ; ; now in user mode, try sneak to cm=u and pri=6 7200$: mov #7100$,sp ; set up stack rtijmp #cp.cmu!cp.pr6,#7300$ ; new PS cm=u and pri=6 ; ; lands here after rti from cm=u 7300$: mov cp.psw,7100$ ; save PS clr cp.psw ; back to kernel mov #stack,sp ; restore stack bic #cpnzvc,7100$ ; discard NZVC hcmpeq #cp.cmu,7100$ ; check expected PS, pri stays 0 ! ; 9999$: iot ; end of test A4.2 ; ; Test A4.3 -- RTI/RTT tbit basics +++++++++++++++++++++++++++++++++++ ; Verifies that tbit trap comes immediately after RTI and delayed after RTT ; ta0403: ; ; part 1: tbit after RTI --------------------------------------------- ; vecset v..bpt,200$ rtijmp #cp.t,#100$ ; PS: tbit; PC 100$ 100$: nop ; should not execute halt ; ; here in local BPT handler 200$: hcmpeq #stack-4,sp ; check single frame hcmpeq #100$,(sp) ; check saved PC before nop mov #stack,sp ; restore vecclr v..bpt ; ; part 2: tbit after RTT --------------------------------------------- ; 2000$: vecset v..bpt,2200$ rttjmp #cp.t,#2100$ ; PS: tbit; PC 2100$ 2100$: nop ; should execute halt ; ; here in local BPT handler 2200$: hcmpeq #stack-4,sp ; check single frame hcmpeq #2100$+2,(sp) ; check saved PC after nop mov #stack,sp ; restore vecclr v..bpt ; 9999$: iot ; end of test A4.3 ; ; Test A4.4 -- tbit trace tests ++++++++++++++++++++++++++++++++++++++ ; ta0404: vecset v..bpt,vhtbpt,cp.pr7 ; BPT handler, PR7 (lockout PIRQ) vecset v..emt,vhtemt ; EMT handler, PR0 (no PIRQ competion) vecset v..pir,vhtpir,cp.pr7 ; PIRQ handler,PR7 (lockout PIRQ) vecset v..trp,vhttrp ; TRAP handler,PR0 (no PIRQ competion) ; ; part 0: traced TRAP that clears tbit ------------------------------ ; Checks that a traced TRAP which loads a PS with tbit=0 does not trap. ; Tested separately because the trace zone exit of subsequent tests uses TRAP. ; mov #200$,r5 mov #300$,vhtend rtijmp #cp.t,#100$ ; RTI used to see bpt before 1st inst ; 100$: trap 100 110$: ; 200$: htabuf 2. ; 300$: htaini 200$,2. ; expect 2 items htacmp #v..bpt,#100$ ; bpt before trap (none after !) htacmp #v..trp,#110$ ; final trap ; ; part 1: simple instruction sequence ------------------------------- ; Checks that trace traps are taken instructions which allow prefetch ; and that the destination PC is saved for flow control instructions. ; mov #1200$,r5 mov #1300$,vhtend rtijmp #cp.t,#1100$ ; RTI used to see bpt before 1st inst ; 1100$: inc r0 ; 1st inst, shouldnt prefetch 1110$: dec r0 ; 2nd inst, shouldnt prefetch 1120$: cmp #1,#2 ; 3rd inst 1130$: bne 1160$ ; 4th inst halt 1140$: return ; 6th inst halt 1150$: jmp 1180$ ; 8th inst halt 1160$: call 1140$ ; 5th inst 1170$: br 1150$ ; 7th inst 1180$: trap 100 ; 9th inst 1190$: ; 1200$: htabuf 10. ; 1300$: htaini 1200$,10. ; expect 10 items htacmp #v..bpt,#1100$ ; bpt before inc htacmp #v..bpt,#1110$ ; bpt after inc htacmp #v..bpt,#1120$ ; bpt after dec htacmp #v..bpt,#1130$ ; bpt after cmp htacmp #v..bpt,#1160$ ; bpt after bne (PC is bne target) htacmp #v..bpt,#1140$ ; bpt after jsr (PC is jsr target) htacmp #v..bpt,#1170$ ; bpt after rts (PC is rts target) htacmp #v..bpt,#1150$ ; bpt after br (PC is br target) htacmp #v..bpt,#1180$ ; bpt after jmp (PC is jmp target) htacmp #v..trp,#1190$ ; final trap ; ; part 2: tracing of trap instructions (EMT tested) ----------------- ; 2000$: mov #2200$,r5 mov #2300$,vhtend rttjmp #cp.t,#2100$ ; RTT used, no before BPT ; 2100$: dec r0 2110$: emt 100 2120$: nop 2130$: trap 100 2140$: ; 2200$: htabuf 5. ; 2300$: htaini 2200$,5. ; expect 5 items htacmp #v..bpt,#2110$ ; bpt after dec htacmp #v..emt,#2120$ ; emt (with return address) htacmp #v..bpt,#2120$ ; bpt after emt (taken after emt) htacmp #v..bpt,#2130$ ; bpt after nop htacmp #v..trp,#2140$ ; final trap ; ; part 3: tbit vs interrupt precedence (via PIRQ) ------------------- ; Checks that interrupt has precedence over tbit traps. ; On a 11/70 and the w11 the PIRQ handler is sprung first, and sees as return ; address the PC after the movb that triggers the PIRQ. The tbit trap is ; sprung on return of the PIRQ handler, and also sees as return address ; the PC after the movb that triggers the PIRQ. ; On a J11 and on SimH the BPT handler is sprung first, and sees as return ; address the PC after the movb that triggers the PIRQ. After the signature ; is looged, the handler lower priority to 0, at that point the PIRQ ; handler is sprung and sees as return address the PC after the clr cp.psw ; that enabled the PIRQ interrupt. ; 3000$: mov #1,vhtbp0 ; ask BPT to lower priority cmpb systyp,#sy.e11 ; skip on e11 (different service order) beq 4000$ ; 3001$: mov #3200$,r5 mov #3300$,vhtend rttjmp #cp.t,#3100$ ; 3100$: movb #bit01,cp.pir+1 ; request PIRQ 1 3110$: trap 100 3120$: ; 3200$: htabuf 3. ; 3300$: htaini 3200$,3. ; expect 3 items cmpb systyp,#sy.sih ; different checks for SimH service order beq 3310$ ; checks for w11 htacmp #v..pir,#3110$ ; pirq (with return address) htacmp #v..bpt,#3110$ ; bpt after movb htacmp #v..trp,#3120$ ; final trap br 4000$ ; checks for SimH 3310$: htacmp #v..bpt,#3110$ ; bpt after movb first htacmp #v..pir,#vhtbpe ; pirq from bpt handler htacmp #v..trp,#3120$ ; final trap ; ; part 4: traced WAIT and tbit -------------------------------------- ; Checks that traced WAIT does not produce tbit trap. ; Checks that SPL does not produce a tbit trap. ; Skipped on SimH which implements J11 semantics for SPL, WAIT, precedence. ; 4000$: cmpb systyp,#sy.sih ; skip on SimH beq 5000$ cmpb systyp,#sy.e11 ; skip on e11 (for precedence) beq 5000$ ; 4001$: mov #4200$,r5 mov #4300$,vhtend rttjmp #cp.t+cp.pr7,#4100$ ; enable tbit, block interrupts ; 4100$: movb #bit05,cp.pir+1 ; request PIRQ 5 4110$: spl 4 ; allow interrupts, not traced !! wait ; also not traced !! 4120$: trap 100 4130$: ; 4200$: htabuf 4. ; 4300$: htaini 4200$,4. ; expect 4 items htacmp #v..bpt,#4110$ ; bpt after movb htacmp #v..pir,#4120$ ; pirq (with return address) htacmp #v..bpt,#4120$ ; bpt after wait htacmp #v..trp,#4130$ ; final trap ; ; part 5: WAIT and SPL in user mode --------------------------------- ; Checks that WAIT and SPL in user mode are traced (are nop) ; 5000$: mov #5200$,r5 mov #5300$,vhtend rttjmp #cp.cmu+cp.t,#5100$ ; user mode, enable tbit ; 5100$: wait 5110$: spl 7 5120$: trap 100 5130$: ; 5200$: htabuf 3. ; 5300$: htaini 5200$,3. ; expect 3 items htacmp #v..bpt,#5110$ ; bpt after wait htacmp #v..bpt,#5120$ ; bpt after spl htacmp #v..trp,#5130$ ; final trap ; ; part 6: tbit trap after continuation over s_idle ------------------ ; Checks instructions that complete via s_idle are properly traced ; Four instructions branch at completion to s_idle ; WAIT s_op_wait (after interrupt) ; RESET s_op_reset ; MOV/CLR s_opg_gen if is_dstw_pc ; 6000$: mov #137,@#0 ; write jmp @#6130$ to location 0,2 mov #6130$,@#2 ; mov #6200$,r5 mov #6300$,vhtend rttjmp #cp.t,#6100$ ; enable tbit ; 6100$: reset 6110$: mov #6120$,pc halt 6120$: clr pc ; continue via jmp @#6130$ at 0,2 halt 6130$: trap 100 6140$: ; 6200$: htabuf 5. ; 6300$: htaini 6200$,5. ; expect 5 items htacmp #v..bpt,#6110$ ; bpt after reset htacmp #v..bpt,#6120$ ; bpt after mov htacmp #v..bpt,#0 ; bpt after clr htacmp #v..bpt,#6130$ ; bpt after jmp htacmp #v..trp,#6140$ ; final trap ; clr @#0 clr @#2 ; ; part 7: no tbit trap after an abort ------------------------------- ; Checks that an aborted instruction doesnt tbit trap. ; Uses a bus timeout as abort reason (access to 160000). ; 7000$: vecset v..iit,7300$ ; setup local vector 4 handler mov #7200$,r5 rttjmp #cp.t,#7100$ ; enable tbit ; 7100$: clr cp.err ; clear CPUERR (will trace trap) 7110$: clr @#160000 ; will fail halt ; 7200$: htabuf 1. ; 7300$: mov #stack,sp ; discard frame hcmpeq #cp.ito,cp.err ; check CPUERR htaini 7200$,1. ; expect 1 item htacmp #v..bpt,#7110$ ; bpt after 1st clr ; vecclr v..iit ; restore ; ; part 8: traced RTI that clears tbit ------------------------------- ; Checks that a traced RTI loading a PS with tbit=0 does not trap. ; Skipped on SimH which does TRAP (confirmed bug, to be fixed). ; 8000$: cmpb systyp,#sy.sih ; skip on SimH (traced RTI traps) beq 9000$ ; push2 #0,#8300$ ; frame used by RTI mov #8200$,r5 rttjmp #cp.t,#8100$ ; 8100$: nop ; will tbit trap 8110$: rti ; will not tbit trap (new PS tbit=0) ; 8200$: htabuf 1. ; 8300$: htaini 8200$,1. ; expect 1 item htacmp #v..bpt,#8110$ ; bpt after nop ; ; part 9: EMT that sets tbit ---------------------------------------- ; Checks that a vector flow loading a PS with tbit=1 does trap. ; Test case is the EMT instruction. ; Skipped on SimH which does not trap (tbd whether that is J11 behavior or bug). ; 9000$: cmpb systyp,#sy.sih ; skip on SimH (RTI traps, EMT not) beq 10000$ ; vecset v..emt,9100$,cp.t ; set emt handler with T bit mov #9200$,r5 ; emt 100 br 9300$ ; 9100$: nop ; will tbit trap 9110$: rti ; will not tbit trap (new PS tbit=0) ; 9200$: htabuf 2. ; 9300$: htaini 9200$,2. ; expect 2 items htacmp #v..bpt,#9100$ ; bpt at entry of EMT handler htacmp #v..bpt,#9110$ ; bpt after nop ; ; part 10: PIRQ that sets tbit --------------------------------------- ; Checks that a vector flow loading a PS with tbit=1 does trap. ; Test case is a PIRQ interrupt. ; Skipped on SimH which does not trap (tbd whether that is J11 behavior or bug). ; 10000$: cmpb systyp,#sy.sih ; skip on SimH (RTI traps, PIRQ not) beq 9999$ ; vecset v..pir,10100$,cp.pr7!cp.t ; set PIRQ handler, PR7 + T bit mov #10200$,r5 ; movb #bit01,cp.pir+1 ; request PIRQ 1 br 10300$ ; 10100$: clr cp.pir ; will tbit trap 10110$: rti ; will not tbit trap (new PS tbit=0) ; 10200$: htabuf 2. ; 10300$: htaini 10200$,2. ; expect 2 items htacmp #v..bpt,#10100$ ; bpt at entry of PIRQ handler htacmp #v..bpt,#10110$ ; bpt after movb ; ; restore ------------------------------------------------------------ ; vecclr v..bpt ; restore v..bpt to catcher vecclr v..emt ; restore v..emt to catcher vecclr v..pir ; restore v..pir to catcher vecclr v..trp ; restore v..trp to catcher ; 9999$: iot ; end of test A4.4 ; ; Test A5: MBRK +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Test A5.1 -- MBRK direct write/read test +++++++++++++++++++++++++++ ; MBRK is a writable and readable 8 bit register an has no specific ; function in w11. ; ta0501: mov #cp.mbr,r0 clr (r0) htsteq (r0) mov #177777,(r0) ; test word write hcmpeq #377,(r0) movb #123,(r0) ; write low byte hcmpeq #123,(r0) movb #321,1(r0) ; write high byte (no effect) hcmpeq #123,(r0) ; 9999$: iot ; end of test A5.1 ; ; Section B: Stress and flow tests =========================================== ; B1 address mode torture tests ; B1.1 src-dst update hazards with (r0)+,(r0) ; B1.2 (pc)+ as destination ; B1.3 pc as destination in clr, mov, and add ; B1.4 (pc)+ as destination case 2 ; B2 pipeline torture tests ; B2.1 self-modifying code, use (pc), -(pc) ; B2.2 self-modifying code, use (pc) case 2 ; B2.3 self-modifying code, use (pc) case 3 ; B3 specifier flow and abort tests ; B3.1 dstw flow and cc ; part 1: check cc for MOV for all modes ; part 2: check cc for CLR for all modes ; part 3: check cc for SXT for all modes ; part 4: check cc for MOV after abort for all modes ; B3.2 mtp and cc after abort ; B3.3 mfp and cc after abort ; B3.4 dstr flow and cc ; part 1: check cc for INC for all modes ; part 2: check cc for INC after abort for all modes ; B4 byte mode flow tests ; B4.1 srcr and byte access ; B4.2 dstr and byte access ; B4.3 dstw and byte access ; ; Test B1: address mode torture tests +++++++++++++++++++++++++++++++++++++++ ; This sub-section tests peculiar address node usage ; ; Test B1.1 -- src-dst update hazards with (r0)+,(r0) ++++++++++++++++ ; tb0101: mov #2,r5 100$: mov #1000$,r0 mov #1110$,r1 push 1000$+2 ; save data that will change push 1000$+6 push 1100$+0 push 1100$+4 ; mov (r0)+,(r0)+ ; mov 111 over 222 add (r0)+,(r0)+ ; add 333 to 444 mov -(r1),-(r1) ; mov 444 over 333 add -(r1),-(r1) ; add 222 to 111 ; hcmpeq 1000$+2,#000111 hcmpeq 1000$+6,#000777 hcmpeq 1100$+4,#000444 hcmpeq 1100$+0,#000333 ; pop 1100$+4 ; restore data pop 1100$+0 pop 1000$+6 pop 1000$+2 sob r5,100$ jmp 9999$ ; 1000$: .word 000111 ; data for (r0)+ part .word 000222 .word 000333 .word 000444 ; 1100$: .word 000111 ; data for -(r0) part .word 000222 .word 000333 .word 000444 1110$: ; 9999$: iot ; end of test B1.1 ; ; Test B1.2 -- (pc)+ as destination ++++++++++++++++++++++++++++++++++ ; tb0102: mov #2,r5 100$: push 1000$+4 ; save data that will change push 1100$+4 push 1200$+2 ; clr r0 1000$: mov #1,#0 ; (pc)+,(pc)+: write #1 over #0 1100$: add #1,#2 ; (pc)+,(pc)+: add #1 to #2 mov 1000$+4,1200$+2 ; -14(pc),2(pc): dst of mov -> src of add 1200$: add #0,r0 ; add #1(!) to r0 ; hcmpeq 1000$+4,#1 hcmpeq 1100$+4,#3 hcmpeq r0,#1 ; pop 1200$+2 ; restore data pop 1100$+4 pop 1000$+4 sob r5,100$ ; 9999$: iot ; end of test B1.2 ; ; Test B1.3 -- pc as destination in clr, mov, and add ++++++++++++++++ ; tb0103: mov #000137,@#0 ; setup jmp 1000$ at mem(0) mov #1000$,@#2 clr pc halt halt halt 1000$: mov #1100$,pc halt halt halt 1100$: clr r0 add #4,pc ; skip two instructions inc r0 inc r0 inc r0 ; lands here inc r0 hcmpeq r0,#2 ; clr @#0 ; remove jmp 1000$ at mem(0) clr @#2 ; 9999$: iot ; end of test B1.3 ; ; Test B1.4 -- (pc)+ as destination case 2 +++++++++++++++++++++++++++ ; 'inc #177777' seen as 're-entry protection' in several xxdp test codes ; tb0104: mov #3,r0 ; try counter clr r1 ; 1st entry counter clr r2 ; other entry counter 100$: inc #177777 ; value will be modified bne 200$ ; ne if not 1st entry inc r1 ; 1st entry br 300$ 200$: inc r2 ; other entries 300$: sob r0,100$ hcmpeq #1,r1 ; check 1st entry count hcmpeq #2,r2 ; check other entry count mov #177777,100$+2 ; restore ; 9999$: iot ; end of test B1.4 ; ; Test B2: pipeline torture tests +++++++++++++++++++++++++++++++++++++++++++ ; This sub-section tests self-modifying code ; ; Test B2.1 -- self-modifying code, use (pc), -(pc) ++++++++++++++++++ ; tb0201: mov #2,r5 100$: mov 1000$,-(sp) mov 1100$,-(sp) ; clr r0 clr r1 clr r2 mov #005201,r3 ; r3= inc r1 mov #005202,r4 ; r4= inc r2 ; inc r0 mov r3,(pc) ; will overwrite next instruction 1000$: halt ; will be overwritten with 'inc r1' inc r0 1100$: mov r4,-(pc) ; will overwrite itself and re-execute(!) inc r0 ; hcmpeq r0,#3 ; 3 inc r0 in code hcmpeq r1,#1 ; check that 'inc r1' was executed hcmpeq r2,#1 ; check that 'inc r2' was executed ; mov (sp)+,1100$ mov (sp)+,1000$ sob r5,100$ ; 9999$: iot ; end of test B2.1 ; ; Test B2.2 -- self-modifying code, use (pc) case 2 ++++++++++++++++++ ; Was insprired by KDJ11A.MAC (J11 is indeed pipelined) ; tb0202: mov #2,r5 100$: mov 1000$,-(sp) mov 1100$,-(sp) mov 1200$,-(sp) ; mov #1999$,r1 clr r2 ; mov #005202,(pc) ; will replace jmp (r1) with 'inc r2' 1000$: jmp (r1) mov #005202,(pc) ; will replace jmp (r1) with 'inc r2' 1100$: jmp (r1) mov #005202,(pc) ; will replace jmp (r1) with 'inc r2' 1200$: jmp (r1) ; hcmpeq r2,#3 ; check that 'inc r2' was executed ; mov (sp)+,1200$ mov (sp)+,1100$ mov (sp)+,1000$ sob r5,100$ jmp 9999$ ; 1999$: halt ; halt as target for 'jmp (r1)' ; 9999$: iot ; end of test B2.2 ; ; Test B2.3 -- self-modifying code, use (pc) case 3 ++++++++++++++++++ ; The 'mtpi (pc)' usage was seen in maindec-11-dekbb-c ; tb0203: push #scc ; scc instruction clr cp.psw mtpi (pc) 100$: halt ; will be overwritten hcmpeq #cpnzvc,cp.psw ; check that scc was executed clr 100$ ; restore ; 9999$: iot ; end of test B2.3 ; ; Test B3: specifier flow and abort tests +++++++++++++++++++++++++++++++++++ ; This sub-section tests flow and cc properties ; ; Test B3.1 -- dstw flow and cc ++++++++++++++++++++++++++++++++++++++ ; tb0301: mov #123,r0 ; src for MOV mov #100$,r1 ; dst for (r1),(r1)+,-(r1),0(r1) mov #200$,r2 ; dst for @(r2)+,@-(r2),@0(r2) mov #cp.psw,r3 ; ptr to PSW br 1000$ ; 100$: .word 0 ; dst target 200$: .word 100$ ; ptr to dst 300$: .word 1 ; odd address ptr ; ; part 1: check cc for MOV for all modes ; 1000$: scc mov r0,r4 ; mode 0 hcmpeq #cp000c,(r3) ; N=0,Z=0,V=0 and keep C scc mov r0,(r1) ; mode 1 hcmpeq #cp000c,(r3) ; N=0,Z=0,V=0 and keep C scc mov r0,(r1)+ ; mode 2 hcmpeq #cp000c,(r3) ; N=0,Z=0,V=0 and keep C scc mov r0,-(r1) ; mode 4 hcmpeq #cp000c,(r3) ; N=0,Z=0,V=0 and keep C scc mov r0,0(r1) ; mode 6 hcmpeq #cp000c,(r3) ; N=0,Z=0,V=0 and keep C scc mov r0,@(r2)+ ; mode 3 hcmpeq #cp000c,(r3) ; N=0,Z=0,V=0 and keep C scc mov r0,@-(r2) ; mode 5 hcmpeq #cp000c,(r3) ; N=0,Z=0,V=0 and keep C scc mov r0,@(r2) ; mode 7 hcmpeq #cp000c,(r3) ; N=0,Z=0,V=0 and keep C ; ; part 2: check cc for CLR for all modes ; 2000$: scc clr r4 ; mode 0 hcmpeq #cp0z00,(r3) ; N=0,Z=1,V=0,C=0 scc clr (r1) ; mode 1 hcmpeq #cp0z00,(r3) ; N=0,Z=1,V=0,C=0 scc clr (r1)+ ; mode 2 hcmpeq #cp0z00,(r3) ; N=0,Z=1,V=0,C=0 scc clr -(r1) ; mode 4 hcmpeq #cp0z00,(r3) ; N=0,Z=1,V=0,C=0 scc clr 0(r1) ; mode 6 hcmpeq #cp0z00,(r3) ; N=0,Z=1,V=0,C=0 scc clr @(r2)+ ; mode 3 hcmpeq #cp0z00,(r3) ; N=0,Z=1,V=0,C=0 scc clr @-(r2) ; mode 5 hcmpeq #cp0z00,(r3) ; N=0,Z=1,V=0,C=0 scc clr @(r2) ; mode 7 hcmpeq #cp0z00,(r3) ; N=0,Z=1,V=0,C=0 ; ; part 3: check cc for SXT for all modes ; 3000$: scc sxt r4 ; mode 0 hcmpeq #cpn00c,(r3) ; Z=0,V=0 and keep N,C scc sxt (r1) ; mode 1 hcmpeq #cpn00c,(r3) ; Z=0,V=0 and keep N,C scc sxt (r1)+ ; mode 2 hcmpeq #cpn00c,(r3) ; Z=0,V=0 and keep N,C scc sxt -(r1) ; mode 4 hcmpeq #cpn00c,(r3) ; Z=0,V=0 and keep N,C scc sxt 0(r1) ; mode 6 hcmpeq #cpn00c,(r3) ; Z=0,V=0 and keep N,C scc sxt @(r2)+ ; mode 3 hcmpeq #cpn00c,(r3) ; Z=0,V=0 and keep N,C scc sxt @-(r2) ; mode 5 hcmpeq #cpn00c,(r3) ; Z=0,V=0 and keep N,C scc sxt @(r2) ; mode 7 hcmpeq #cpn00c,(r3) ; Z=0,V=0 and keep N,C ; ; part 4: check cc for MOV after abort for all memory modes ; Notes: ; - w11 updates the cc state after possible address errors ; - SimH updates the cc state before possible address errors ; 4000$: cmpb systyp,#sy.sih ; skip on SimH beq 9999$ clr r5 ; abort counter vecset v..iit,4100$ ; set up iit handler mov #1,r1 ; odd dst for (r1),(r1)+,-(r1),0(r1) mov #300$,r2 ; odd dst for @(r2)+,@-(r2),@0(r2) scc ; mov r0,(r1) ; mode 1 mov r0,(r1)+ ; mode 2 mov #3,r1 ; restore r1 scc mov r0,-(r1) ; mode 4 mov r0,0(r1) ; mode 6 mov r0,@(r2)+ ; mode 3 mov r0,@-(r2) ; mode 5 mov r0,@(r2) ; mode 7 br 4200$ ; 4100$: inc r5 ; bump counter hcmpeq #cpnzvc,2(sp) ; check PS cc untouched rti ; continue (possible here!) ; 4200$: hcmpeq #7.,r5 ; check that all 7 mov got address error vecclr v..iit ; restore ; 9999$: iot ; end of test B3.1 ; ; Test B3.2 -- mtp and cc after abort ++++++++++++++++++++++++++++++++ ; Verifies that cc is unchanged if last write fails. ; MTP* uses the dsta flow, it is sufficient to test only mode 1 and ; an odd address abort. ; tb0302: cmpb systyp,#sy.sih ; skip on SimH beq 9999$ ; mov #1,r1 ; use odd address vecset v..iit,1000$ ; set up iit handler clr -(sp) ; push value scc mtpi (r1) ; will fail halt ; 1000$: hcmpeq #cpnzvc,2(sp) ; check PS cc untouched mov #stack,sp ; restore vecclr v..iit ; restore ; 9999$: iot ; end of test B3.2 ; ; Test B3.3 -- mfp and cc after abort ++++++++++++++++++++++++++++++++ ; Verifies that cc is unchanged if last write fails. ; The last write in MFP* is a stack push, the test uses an odd address abort. ; tb0303: cmpb systyp,#sy.sih ; skip on SimH beq 9999$ ; inc sp ; set up odd stack mov #100$,r1 ; set up read address (a valid one) vecset v..iit,1000$ ; set up iit handler scc mfpi (r1) ; will fail halt ; 100$: .word 123 ; 1000$: hcmpeq #cpnzvc,2(sp) ; check PS cc untouched htsteq sp ; check that fatal stack error seen mov #stack,sp ; restore vecclr v..iit ; restore ; 9999$: iot ; end of test B3.3 ; ; Test B3.4 -- dstr flow and cc ++++++++++++++++++++++++++++++++++++++ ; Verifies dstr flow and uses INC as easy to handle test case. ; tb0304: clr r0 ; src for INC mov #100$,r1 ; dst for (r1),(r1)+,-(r1),0(r1) mov #200$,r2 ; dst for @(r2)+,@-(r2),@0(r2) mov #cp.psw,r3 ; ptr to PSW br 1000$ ; 100$: .word 0 ; dst target 200$: .word 100$ ; ptr to dst 300$: .word 1 ; odd address ptr ; ; part 1: check cc for INC for all modes ; 1000$: scc inc r0 hcmpeq #cp000c,(r3) ; NZV=0 and keep C scc inc (r1) ; mode 1 hcmpeq #cp000c,(r3) ; N=0,Z=0,V=0 and keep C scc inc (r1)+ ; mode 2 hcmpeq #cp000c,(r3) ; N=0,Z=0,V=0 and keep C scc inc -(r1) ; mode 4 hcmpeq #cp000c,(r3) ; N=0,Z=0,V=0 and keep C scc inc 0(r1) ; mode 6 hcmpeq #cp000c,(r3) ; N=0,Z=0,V=0 and keep C scc inc @(r2)+ ; mode 3 hcmpeq #cp000c,(r3) ; N=0,Z=0,V=0 and keep C scc inc @-(r2) ; mode 5 hcmpeq #cp000c,(r3) ; N=0,Z=0,V=0 and keep C scc inc @(r2) ; mode 7 hcmpeq #cp000c,(r3) ; N=0,Z=0,V=0 and keep C ; hcmpeq #7.,(r1) ; check that 7 inc's done ; ; part 2: check cc for INC after abort for all memory modes ; 2000$: clr r5 vecset v..iit,2100$ ; set up iit handler mov #1,r1 ; odd dst for (r1),(r1)+,-(r1),0(r1) mov #300$,r2 ; odd dst for @(r2)+,@-(r2),@0(r2) scc ; inc (r1) ; mode 1 inc (r1)+ ; mode 2 mov #3,r1 ; restore r1 scc inc -(r1) ; mode 4 inc 0(r1) ; mode 6 inc @(r2)+ ; mode 3 inc @-(r2) ; mode 5 inc @(r2) ; mode 7 br 2200$ ; 2100$: inc r5 ; bump counter hcmpeq #cpnzvc,2(sp) ; check PS cc untouched rti ; continue (possible here!) ; 2200$: hcmpeq #7.,r5 ; check that all 7 inc got address error vecclr v..iit ; restore ; 9999$: iot ; end of test B3.4 ; ; Test B4: byte mode flow tests +++++++++++++++++++++++++++++++++++++++++++++ ; This sub-section verifies correct byte mode increment/decrement behavior. ; Done by flow for srcr, dstr and dstw. The dsta flow does not access bytes. ; Only address changes are checked with representative instructions. The ; correct byte data behavior was already tested in cpu_basics on a per ; instruction basis. ; ; Test B4.1 -- srcr and byte access ++++++++++++++++++++++++++++++++++ ; tb0401: mov #100$,r1 ; src for (r1)+,-(r1) mov #200$,r2 ; src for @(r2)+,@-(r2) ; bisb (r1)+,r5 ; mode 2 gpr -> inc 1 hcmpeq #100$+1,r1 bisb -(r1),r5 ; mode 4 gpr -> dec 1 hcmpeq #100$,r1 ; bisb @(r2)+,r5 ; mode 3 gpr -> inc 2 hcmpeq #200$+2,r2 bisb @-(r2),r5 ; mode 5 gpr -> dec 2 hcmpeq #200$,r2 ; bisb -(sp),r5 ; mode 4 sp -> dec 2 (stupid case) hcmpeq #stack-2,sp bisb (sp)+,r5 ; mode 2 sp -> inc 2 hcmpeq #stack,sp ; br 9999$ ; 100$: .word 0 ; src target 200$: .word 100$ ; ptr to src ; 9999$: iot ; end of test B4.1 ; ; Test B4.2 -- dstr and byte access ++++++++++++++++++++++++++++++++++ ; tb0402: mov #100$,r1 ; dst for (r1)+,-(r1) mov #200$,r2 ; dst for @(r2)+,@-(r2) ; bisb r5,(r1)+ ; mode 2 gpr -> inc 1 hcmpeq #100$+1,r1 bisb r5,-(r1) ; mode 4 gpr -> dec 1 hcmpeq #100$,r1 ; bisb r5,@(r2)+ ; mode 3 gpr -> inc 2 hcmpeq #200$+2,r2 bisb r5,@-(r2) ; mode 5 gpr -> dec 2 hcmpeq #200$,r2 ; bisb r5,-(sp) ; mode 4 sp -> dec 2 (stupid case) hcmpeq #stack-2,sp bisb r5,(sp)+ ; mode 2 sp -> inc 2 hcmpeq #stack,sp ; br 9999$ ; 100$: .word 0 ; dst target 200$: .word 100$ ; ptr to dst ; 9999$: iot ; end of test B4.2 ; ; Test B4.3 -- dstw and byte access ++++++++++++++++++++++++++++++++++ ; tb0403: mov #100$,r1 ; dst for (r1)+,-(r1) mov #200$,r2 ; dst for @(r2)+,@-(r2) ; movb r5,(r1)+ ; mode 2 gpr -> inc 1 hcmpeq #100$+1,r1 movb r5,-(r1) ; mode 4 gpr -> dec 1 hcmpeq #100$,r1 ; movb r5,@(r2)+ ; mode 3 gpr -> inc 2 hcmpeq #200$+2,r2 movb r5,@-(r2) ; mode 5 gpr -> dec 2 hcmpeq #200$,r2 ; clrb -(sp) ; mode 4 sp -> dec 2 hcmpeq #stack-2,sp clrb (sp)+ ; mode 2 sp -> inc 2 (stupid case) hcmpeq #stack,sp ; br 9999$ ; 100$: .word 0 ; dst target 200$: .word 100$ ; ptr to dst ; 9999$: iot ; end of test B4.3 ; ; Section C: 11/70 specifics ================================================= ; C1 Implementation differences ; C1.1 Register used as source and changed in dst flow ; C1.2 PC used as source ; C1.3 Registers accessible via 177700-1777717 ; ; Test C1: Implementation differences +++++++++++++++++++++++++++++++++++++++ ; This sub-section verifies that w11 shows 11/70 behavior in cases ; were J11 and other CPU models show different behavior ; ; Test C1.1 -- Register used as source and changed in dst flow +++++++ ; OPR R,(R)+ : incremented before {J11} or after {70} use as source ; OPR R,-(R) : decremented before {J11} or after {70} use as source ; tc0101: mov #1000$,r4 mov r4,(r4)+ hcmpeq 1000$,#1000$ ; check r4 prior inc stored mov r4,-(r4) hcmpeq 1000$,#1000$+2 ; check r4 prior dec stored br 9999$ ; 1000$: .word 0 ; 9999$: iot ; end of test C1.1 ; ; Test C1.2 -- PC used as source +++++++++++++++++++++++++++++++++++++ ; OPR PC,A(R) : store PC+2 {70} or PC+4 {J11} ; tc0102: mov #1000$,r4 100$: mov pc,0(r4) hcmpeq 1000$,#100$+2 ; check pc after fetch stored br 9999$ ; 1000$: .word 0 ; 9999$: iot ; end of test C1.2 ; ; Test C1.3 -- Registers accessible via 177700-1777717 +++++++++++++++ ; CPU access to 177700-177717 (regs) timesout {70,J11} or not {05,10} ; tc0103: vecset v..iit,vhugen ; set iit handler, pr0 kernel ; mov #1000$,vhustp ; continuation address tst @#177700 ; should fail halt ; 1000$: mov #1100$,vhustp ; continuation address tst @#177716 ; should fail halt ; 1100$: vecclr v..iit ; restore iit handler ; 9999$: iot ; end of test C1.3 ; ; END OF ALL TESTS - loop closure ============================================ ; mov tstno,r0 ; hack, for easy monitoring ... hcmpeq tstno,#39. ; all tests done ? ; jmp loop ; ; kernel handlers ============================================================ ; ; vhugen - generic handler for expected traps/abort ++++++++++++++++++++++++++ ; the continution address must be written to vhustp ; execution will reset vhustp to a catcher value ; --> vhustp must be set for each execution ; vhugen: add #4,sp ; discard vector frame mov vhustp,100$ ; set up return address mov #vhuhlt,vhustp ; reset stop address by catcher jmp @100$ ; end return to continuation address 100$: .word 0 vhustp: .word vhuhlt vhuhlt: halt ; ; vhtbpt - handler for BPT tracing +++++++++++++++++++++++++++++++++++++++++++ ; Writes signature to data area (ptr in r5). ; Signature is vector address + return PC (PC to test proper context). ; If vhtbp0 is non-zero, the handler lowers priority to PRI=0 before RTT. ; vhtbpt: htstge (r5) ; r5 at fence ? htaadd #v..bpt ; track BPT vector, track return PC tst vhtbp0 ; should PRI be lowered ? beq vhtbpe clr vhtbp0 ; and clear flag clr cp.psw ; now PRI=0, immediate effect vhtbpe: rtt ; end with RTT (!) vhtbp0: .word 0 ; ; vhtemt - handler for EMT tracing +++++++++++++++++++++++++++++++++++++++++++ ; Writes signature to data area (ptr in r5). ; Signature is vector address + return PC (PC to test proper context). ; vhtemt: htstge (r5) ; r5 at fence ? htaadd #v..emt ; track EMT vector, track return PC rti ; ; vhtpir - handler for PIRQ interrupt tracing ++++++++++++++++++++++++++++++++ ; Writes signature to data area (ptr in r5). ; Signature is vector address + return PC (PC to test proper context). ; Clears all PIRQ requests to prevent interrupt loop. ; vhtpir: htstge (r5) ; r5 at fence ? clr cp.pir ; clear all PIRQ interrupts htaadd #v..pir ; track PIRQ vector, track return PC rti ; ; vhttrp - handler for TRAP, ends tracing ++++++++++++++++++++++++++++++++++++ ; Writes signature to data area (ptr in r5). ; Returns to address stored in vhtend ; vhtend must be set for each execution ; vhttrp: htstge (r5) ; r5 at fence ? htaadd #v..trp ; track TRAP vector, track return PC mov vhtend,100$ ; remember vhtend mov #200$,vhtend ; restore blocker mov #stack,sp ; restore stack jmp @100$ ; return or block 100$: .word 200$ ; value of vhtend at entry 200$: halt ; blocker vhtend: .word 0 ; registered return address ; .end start