better forward referencing plus initial AWbits test swag

This commit is contained in:
Neil Webber 2023-09-19 11:58:38 -05:00
parent 83003f8a01
commit d78fb6e8ec

View file

@ -673,6 +673,23 @@ class TestMethods(unittest.TestCase):
# (taddr, t), (uaddr, u), (k addr, k) # (taddr, t), (uaddr, u), (k addr, k)
# where the t/u/k elements are the instruction blocks. # where the t/u/k elements are the instruction blocks.
# the kernel stack will start at 8K and work its way down.
# This is fixed/required in the code. The taddr and kaddr must also
# be in that first 8K and MUST leave space for the kernel stack.
# The kernel stack is arbitrarily given at least 256 bytes
# (in reality it doesn't come close to using that)
APR0_end = 0o20000
if APR0_end - max(taddr, kaddr) < 256:
raise ValueError("not enough room for kernel stack")
kernel_stack = APR0_end
# there are some variable locations needed in the code, they
# are allocated from the "stack", like this:
kernel_stack -= 2
saved_r5 = kernel_stack
cn = self.usefulconstants() cn = self.usefulconstants()
# Two tests - up and down. # Two tests - up and down.
@ -838,9 +855,14 @@ class TestMethods(unittest.TestCase):
u.trap(0) u.trap(0)
# The kernel-mode code that drives the whole test # The kernel-mode code that drives the whole test
# this is certainly one way to allocate data variables,
# given the limitations of the non-assembler ASM() methodology...
#
# The stack will start at kstackstart
with ASM() as k: with ASM() as k:
# location 0o17776 is used to remember the table start r5... k.mov(kernel_stack, 'sp')
k.mov(0o17776, 'sp') # start system stack at 8k - 2
# KERNEL I SPACE # KERNEL I SPACE
# PAR 0 to physical 0 # PAR 0 to physical 0
@ -877,34 +899,15 @@ class TestMethods(unittest.TestCase):
# pattern but this is just another excuse to test more things # pattern but this is just another excuse to test more things
# jump to the user 'setup' code, but first establish a handler # jump to the user 'setup' code, but first establish a handler
# for the trap it will execute when done. # for the trap it will execute when done.
k.mov(taddr + (2 * tr.getlabel('trap_usersetup')), '*$34') k.mov(taddr + tr.getlabel('trap_usersetup'), '*$34')
k.mov(0o340, '*$36') k.mov(0o340, '*$36')
# oh my is this a hack, but, well, here it is. Need to k.mov('pc', '-(sp)')
# compute where the trap handler should resume. Start with # add the offset to (forward ref) back_from_u
# the current pc, pushing it onto the stack (for use on return) k.add(k.fwdvalue('back_from_u', 'OPERAND_WORD_1'), '(sp)')
# and then ... need to add the right number of words to jump
# around everything up to and including the rtt.
# XXX NEED BETTER FORWARD LABEL SUPPORT IN asmhelper
# Since it's not a "real" assembler, but just a "helper"
# this is the best that can be done right now:
k.mov('pc', '-(sp)') # ok, the easy part
# will be called when k.label('back_from_u') runs below
def _patcher(fref):
block = fref.block
fwdoffs = block.getlabel(fref.name) - fref.loc
block._instblock[fref.loc + 1] = 2*fwdoffs
# register that callback
_ = k.getlabel('back_from_u', callback=_patcher)
# the instruction that _patcher will patch
k.add(0, '(sp)') # that 0 will be patched
k.mov(0o140340, '-(sp)') # push user-ish PSW to K stack k.mov(0o140340, '-(sp)') # push user-ish PSW to K stack
k.mov(u.getlabel('setup') * 2, '-(sp)') # PC for setup code k.mov(u.getlabel('setup'), '-(sp)') # PC for setup code
k.rtt() k.rtt()
k.label('back_from_u') k.label('back_from_u')
@ -967,16 +970,17 @@ class TestMethods(unittest.TestCase):
# the test table for the trap handler is now here: # the test table for the trap handler is now here:
k.mov('sp', 'r5') k.mov('sp', 'r5')
k.mov('sp', '*$17776') # it is also stored here for re-use k.mov('sp', k.ptr(saved_r5)) # so it can be recovered later
# test starts in the region at the start of the table # test starts in the region at the start of the table
k.mov('(r5)', 'r2') k.mov('(r5)', 'r2')
# poke the MMU trap handler vector (250) # poke the MMU trap handler vector (250)
k.mov(taddr + (tr.getlabel('TrapMMU') * 2), '*$250') k.mov(taddr + tr.getlabel('TrapMMU'), '*$250')
k.mov(0o340, '*$252') k.mov(0o340, '*$252')
# same for the "trap N" handler # same for the "trap N" handler
k.mov(taddr + (tr.getlabel('UTrap') * 2), '*$34') k.mov(taddr + tr.getlabel('UTrap'), '*$34')
k.mov(0o340, '*$36') k.mov(0o340, '*$36')
# ok, now ready to start the user program # ok, now ready to start the user program
@ -989,7 +993,7 @@ class TestMethods(unittest.TestCase):
k.label('DOWNTEST') k.label('DOWNTEST')
# re-establish initial kernel stack # re-establish initial kernel stack
k.mov(0o17776, 'sp') k.mov(kernel_stack, 'sp')
# Redo the entire test table for the down address cases # Redo the entire test table for the down address cases
# these were precomputed from the algorithm for setting PDRs # these were precomputed from the algorithm for setting PDRs
@ -1029,7 +1033,7 @@ class TestMethods(unittest.TestCase):
k.mov(1, '-(sp)') k.mov(1, '-(sp)')
k.mov('sp', 'r5') # r5 is where the table starts k.mov('sp', 'r5') # r5 is where the table starts
k.mov('sp', '*$17776') # it is also stored here for re-use k.mov('sp', k.ptr(saved_r5)) # store location for re-use
# fiddle the PDRs (PARs stay the same) for the down configuration # fiddle the PDRs (PARs stay the same) for the down configuration
k.mov(cn.UDSD0, 'r3') k.mov(cn.UDSD0, 'r3')
@ -1066,7 +1070,7 @@ class TestMethods(unittest.TestCase):
k.label('BONUS') k.label('BONUS')
# recover the r5 stack table beginning # recover the r5 stack table beginning
k.mov('*$17776', 'r5') k.mov(k.ptr(saved_r5), 'r5')
# copy UDSA4 into KISA1 - mapping old segment into kernel space # copy UDSA4 into KISA1 - mapping old segment into kernel space
k.mov(k.ptr(cn.UDSA0 + 4*2), k.ptr(cn.KISA0 + 2)) # i.e., A1 k.mov(k.ptr(cn.UDSA0 + 4*2), k.ptr(cn.KISA0 + 2)) # i.e., A1
@ -1148,8 +1152,8 @@ class TestMethods(unittest.TestCase):
for addr, b in self._make_updown(taddr, uaddr, kaddr): for addr, b in self._make_updown(taddr, uaddr, kaddr):
if addr == kaddr: if addr == kaddr:
# need to know DOWNTEST and BONUS # need to know DOWNTEST and BONUS
downtest = kaddr + (2 * b.getlabel('DOWNTEST')) downtest = kaddr + b.getlabel('DOWNTEST')
bonus = kaddr + (2 * b.getlabel('BONUS')) bonus = kaddr + b.getlabel('BONUS')
self.loadphysmem(p, b.instructions(), addr) self.loadphysmem(p, b.instructions(), addr)
with self.subTest(phase="UP"): with self.subTest(phase="UP"):
@ -1171,6 +1175,125 @@ class TestMethods(unittest.TestCase):
p.run(pc=bonus) p.run(pc=bonus)
self.assertEqual(p.r[2], 0o666) self.assertEqual(p.r[2], 0o666)
def xxxtest_mmu_AWbits(self):
cn = self.usefulconstants()
p = self.make_pdp()
base_address = 0o10000
with ASM() as k:
# this is silly but easy, just put the trap handler here and
# jump over it
k.br('L1')
k.label('traphandler')
k.rtt()
k.label('L1')
k.mov(base_address, 'sp') # system stack just below this code
#
# No I/D separation turned on, so everything is mapped via I SPACE
# PAR 0 to physical 0
# PAR 1 to physical 8K
# PAR 2 to physical 16K
# ... etc ... 1:1 virtual:physical mapping up to ...
# PAR 7 to phys 760000 and 22bit not turned on (i.e., I/O page)
#
k.clr('r2') # r2 will step by 0o200 for 8K PAR incrs
k.mov(cn.KISA0, 'r0') # r0 will chug through the PARs
k.mov(7, 'r1') # count of PARs to set
k.label('parloop')
k.mov('r2', '(r0)+')
k.add(0o200, 'r2')
k.sob('r1', 'parloop')
# set the PAR7 to I/O page
k.mov(0o7600, '(r0)')
# now the PDRs
k.mov(cn.KISD0, 'r4')
k.mov(0o77406, '(r4)+') # read/write, full length for PDR0
k.mov(0o77404, 'r2') # r/w, full length, trap on any r/w
k.mov(6, 'r1') # setting PDR1 .. PDR6
k.label('pdrloop')
k.mov('r2', '(r4)+')
k.sob('r1', 'pdrloop')
k.mov(0o77406, '(r4)+') # r/w, full length for PDR7 / IO page
# NOTE: at this point '-(r4)' will be PDR7 ... that is used below
# set up the trap handler
k.mov(base_address + k.getlabel('traphandler'), '*$250')
k.mov(0o340, '*$252')
k.mov(1, k.ptr(cn.MMR0)) # turn on MMU
# this test code just "knows" the code is in APR0 (8K and below)
# and makes three accesses:
# a READ at 12K (APR1)
# a WRITE at 20K (APR2)
# a READ-then-WRITE at 28K (APR3)
#
# then it dumps the 8 kernel PDRS onto the stack in reverse
# (so that at the end (sp) -> PDR0
#
k.mov(0o20000, 'r0') # 8K will will be the base for:
k.mov('010000(r0)', 'r1') # read from 12K
k.mov(1234, '030000(r0)') # write to 20K
k.inc('050000(r0)') # read-then-write to 28K
# push (the dumb way) PDRs onto the stack for examination
k.mov('-(r4)', '-(sp)')
k.mov('-(r4)', '-(sp)')
k.mov('-(r4)', '-(sp)')
k.mov('-(r4)', '-(sp)')
k.mov('-(r4)', '-(sp)')
k.mov('-(r4)', '-(sp)')
k.mov('-(r4)', '-(sp)')
k.mov('-(r4)', '-(sp)')
# expected:
# * PDR0 (not really part of the test)
# * PDR1 to be only A bit
# * PDR2 to be A and W
# * PDR3 to be A and W
# * PDR4-6 to be neither
# * PDR7 (not really part of the test but will be neither)
# Any that are not expected are recorded as bits in r0
# So R0 should be zero at the halt if the test succeeded
k.clr('r0')
k.bit(0o100, '2(r4)')
k.beq(4)
k.bis(1, 'r0')
k.bit(0o200, '2(r4)')
k.bne(4)
k.bis(1, 'r0')
k.bit(0o100, '4(r4)')
k.bne(4)
k.bis(2, 'r0')
k.bit(0o200, '4(r4)')
k.bne(4)
k.bis(2, 'r0')
k.bit(0o100, '6(r4)')
k.bne(4)
k.bis(4, 'r0')
k.bit(0o200, '6(r4)')
k.bne(4)
k.bis(4, 'r0')
k.halt()
self.loadphysmem(p, k.instructions(), base_address)
p.run(pc=base_address)
self.assertEqual(p.r[0], 0)
def test_ubmap(self): def test_ubmap(self):
p = self.make_pdp() p = self.make_pdp()