mirror of
https://github.com/wfjm/w11.git
synced 2026-01-21 10:42:10 +00:00
- cpu_details.mac: fix systyp checks; - cpu_mmu.mac: add MMR0/3 unimplented bit tests; add B4.1 and B4.2 tests
536 lines
20 KiB
Plaintext
536 lines
20 KiB
Plaintext
; $Id: cpu_details.mac 1304 2022-10-22 10:19:34Z mueller $
|
|
; SPDX-License-Identifier: GPL-3.0-or-later
|
|
; Copyright 2022- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
|
;
|
|
; Revision History:
|
|
; Date Rev Version Comment
|
|
; 2022-07-28 1264 1.0 Initial version
|
|
; 2022-07-18 1259 0.1 First draft
|
|
;
|
|
; Test CPU details
|
|
; Section A: CPU registers
|
|
; Section B: stress tests
|
|
; Section C: 11/70 specifics
|
|
;
|
|
.include |lib/tcode_std_base.mac|
|
|
.include |lib/defs_mmu.mac|
|
|
;
|
|
; 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 ===================================================
|
|
;
|
|
; 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: mov #1000$,v..pir ; setup handler
|
|
mov #cp.pr7,v..pir+2 ; which runs 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),#<pi.r01!pi.n01> ; check set 1
|
|
bisb #bit03,1(r3) ; set PIRQ 3
|
|
hcmpeq (r3),#<pi.r01!pi.r03!pi.n03> ; check set 1+3
|
|
spl 2
|
|
nop ; allow interrupts to happen
|
|
spl 0
|
|
nop ; allow interrupts to happen
|
|
htsteq (r3) ; PIRQ should clear now
|
|
mov #v..pir+2,v..pir; restore pirq vector catcher
|
|
clr v..pir+2
|
|
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 nestec interrupts to happem
|
|
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 A2: CPUERR +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
; This sub-section verifies operation of CPUERR register
|
|
;
|
|
; setup for all A2.* tests
|
|
mov #cp.err,r0 ; ptr tp CPUERR
|
|
mov #vhugen,v..iit ; set iit handler
|
|
clr v..iit+2 ; pr0 kernel
|
|
;
|
|
; Test A2.1 -- CPUERR cp.hlt +++++++++++++++++++++++++++++++++++++++++
|
|
; Test cp.hlt: halt in non-kernel mode
|
|
;
|
|
ta0201: mov #177777,(r0) ; clear CPUERR (any write should)
|
|
hcmpeq (r0),#0 ; 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)
|
|
hcmpeq (r0),#0 ; check CPUERR
|
|
;
|
|
sob r3,1000$ ; go for next mode
|
|
;
|
|
br 9999$
|
|
;
|
|
4000$: .word <cp.cmu!cp.pmu> ; user mode
|
|
.word <cp.cms!cp.pms> ; supervisor mode
|
|
;
|
|
9999$: iot ; end of test A2.1
|
|
;
|
|
; Test A2.2 -- CPUERR cp.aer +++++++++++++++++++++++++++++++++++++++++
|
|
; Test cp.aer: address error abort
|
|
;
|
|
ta0202: mov #1000$,vhustp ; continuation address
|
|
tst @#001 ; odd address access
|
|
halt
|
|
1000$: hcmpeq (r0),#cp.aer ; check CPUERR
|
|
clr (r0) ; clear CPUERR (any write should)
|
|
hcmpeq (r0),#0 ; 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)
|
|
hcmpeq (r0),#0 ; 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)
|
|
hcmpeq (r0),#0 ; 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)
|
|
hcmpeq (r0),#0 ; 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$: mov #stack,sp ; direct iit handler
|
|
hcmpeq (r0),#cp.rsv ; check CPUERR
|
|
clr (r0) ; clear CPUERR (any write should)
|
|
hcmpeq (r0),#0 ; check CPUERR
|
|
;
|
|
9999$: iot ; end of test A2.6
|
|
;
|
|
; Test A2.7 -- CPUERR cp.rsv+cp.aer (odd address) ++++++++++++++++++++
|
|
; Test cp.aer: fatal stack error after odd stack
|
|
;
|
|
ta0207: cmpb systyp,#sy.e11 ; e11 V7.3 pushes to odd stack, abort after halt
|
|
beq 9999$
|
|
mov #1000$,v..iit ; setup direct iit handler
|
|
mov #stack-1,sp
|
|
clr -(sp) ; odd-address abort, fatal stack error
|
|
halt
|
|
1000$: mov #stack,sp ; direct iit handler
|
|
hcmpeq (r0),#<cp.rsv+cp.aer> ; check CPUERR
|
|
clr (r0) ; clear CPUERR (any write should)
|
|
hcmpeq (r0),#0 ; check CPUERR
|
|
;
|
|
9999$: iot ; end of test A2.7
|
|
;
|
|
; Test A2.8 -- CPUERR cp.rsv+cp.nxm ++++++++++++++++++++++++++++++++++
|
|
; 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$
|
|
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$: mov #stack,sp ; direct iit handler
|
|
hcmpeq (r0),#<cp.rsv+cp.nxm> ; check CPUERR
|
|
clr (r0) ; clear CPUERR (any write should)
|
|
hcmpeq (r0),#0 ; check CPUERR
|
|
;
|
|
reset ;! MMU off
|
|
mov #001400,kipar6 ; restore kipar6
|
|
;
|
|
9999$: iot ; end of test A2.8
|
|
;
|
|
; Test A2.9 -- CPUERR cp.rsv+cp.ito ++++++++++++++++++++++++++++++++++
|
|
; 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$
|
|
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$: mov #stack,sp ; direct iit handler
|
|
hcmpeq (r0),#<cp.rsv+cp.ito> ; check CPUERR
|
|
clr (r0) ; clear CPUERR (any write should)
|
|
hcmpeq (r0),#0 ; check CPUERR
|
|
;
|
|
9999$: iot ; end of test A2.9
|
|
;
|
|
; Test A2.10 -- CPUERR cp.rsv+cp.aer (mmu abort) +++++++++++++++++++++
|
|
; Test cp.rsv: fatal stack error after mmu abort
|
|
; Set kernel I page 6 to non-resident
|
|
;
|
|
ta0210: cmpb systyp,#sy.sih ; this fatal stack error fails in SimH
|
|
beq 9999$
|
|
cmpb systyp,#sy.e11 ; e11 V7.3 pushes to bad stack, does MMU 250
|
|
beq 9999$
|
|
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$: mov #stack,sp ; direct iit handler
|
|
hcmpeq (r0),#<cp.rsv+cp.aer> ; check CPUERR
|
|
clr (r0) ; clear CPUERR (any write should)
|
|
hcmpeq (r0),#0 ; check CPUERR
|
|
;
|
|
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
|
|
mov v..iit+2,v..iit ; restore iit handler
|
|
;
|
|
; Section B: Stress tests ====================================================
|
|
;
|
|
; 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 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
|
|
;
|
|
; END OF ALL TESTS - loop closure ============================================
|
|
;
|
|
mov tstno,r0 ; hack, for easy monitoring ...
|
|
hcmpeq tstno,#16. ; all tests done ?
|
|
;
|
|
jmp loop
|
|
;
|
|
; kernel handlers ============================================================
|
|
;
|
|
; vhugen - generic handler for expected traps/abort ++++++++++++++++++++++++++
|
|
; the kernel continution address must be written to vhustp
|
|
; execution will reset vhustp to a catcher value
|
|
; --> vhustp must be set for each execution
|
|
;
|
|
vhugen: tst (sp)+ ; discard one word of vector push
|
|
mov vhustp,(sp) ; set up kernel return address
|
|
mov #vhuhlt,vhustp ; reset stop address by catcher
|
|
rts pc ; end return to continuation address
|
|
vhustp: .word vhuhlt
|
|
vhuhlt: halt
|
|
;
|
|
.end start
|