better forward referencing plus initial AWbits test swag
This commit is contained in:
parent
83003f8a01
commit
d78fb6e8ec
1 changed files with 157 additions and 34 deletions
191
pdptests.py
191
pdptests.py
|
@ -673,6 +673,23 @@ class TestMethods(unittest.TestCase):
|
|||
# (taddr, t), (uaddr, u), (k addr, k)
|
||||
# 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()
|
||||
|
||||
# Two tests - up and down.
|
||||
|
@ -838,9 +855,14 @@ class TestMethods(unittest.TestCase):
|
|||
u.trap(0)
|
||||
|
||||
# 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:
|
||||
# location 0o17776 is used to remember the table start r5...
|
||||
k.mov(0o17776, 'sp') # start system stack at 8k - 2
|
||||
k.mov(kernel_stack, 'sp')
|
||||
|
||||
# KERNEL I SPACE
|
||||
# PAR 0 to physical 0
|
||||
|
@ -877,34 +899,15 @@ class TestMethods(unittest.TestCase):
|
|||
# pattern but this is just another excuse to test more things
|
||||
# jump to the user 'setup' code, but first establish a handler
|
||||
# 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')
|
||||
|
||||
# oh my is this a hack, but, well, here it is. Need to
|
||||
# compute where the trap handler should resume. Start with
|
||||
# the current pc, pushing it onto the stack (for use on return)
|
||||
# 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('pc', '-(sp)')
|
||||
# add the offset to (forward ref) back_from_u
|
||||
k.add(k.fwdvalue('back_from_u', 'OPERAND_WORD_1'), '(sp)')
|
||||
|
||||
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.label('back_from_u')
|
||||
|
@ -967,16 +970,17 @@ class TestMethods(unittest.TestCase):
|
|||
|
||||
# the test table for the trap handler is now here:
|
||||
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
|
||||
k.mov('(r5)', 'r2')
|
||||
|
||||
# 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')
|
||||
|
||||
# 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')
|
||||
|
||||
# ok, now ready to start the user program
|
||||
|
@ -989,7 +993,7 @@ class TestMethods(unittest.TestCase):
|
|||
k.label('DOWNTEST')
|
||||
|
||||
# re-establish initial kernel stack
|
||||
k.mov(0o17776, 'sp')
|
||||
k.mov(kernel_stack, 'sp')
|
||||
|
||||
# Redo the entire test table for the down address cases
|
||||
# these were precomputed from the algorithm for setting PDRs
|
||||
|
@ -1029,7 +1033,7 @@ class TestMethods(unittest.TestCase):
|
|||
k.mov(1, '-(sp)')
|
||||
|
||||
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
|
||||
k.mov(cn.UDSD0, 'r3')
|
||||
|
@ -1066,7 +1070,7 @@ class TestMethods(unittest.TestCase):
|
|||
k.label('BONUS')
|
||||
|
||||
# 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
|
||||
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):
|
||||
if addr == kaddr:
|
||||
# need to know DOWNTEST and BONUS
|
||||
downtest = kaddr + (2 * b.getlabel('DOWNTEST'))
|
||||
bonus = kaddr + (2 * b.getlabel('BONUS'))
|
||||
downtest = kaddr + b.getlabel('DOWNTEST')
|
||||
bonus = kaddr + b.getlabel('BONUS')
|
||||
self.loadphysmem(p, b.instructions(), addr)
|
||||
|
||||
with self.subTest(phase="UP"):
|
||||
|
@ -1171,6 +1175,125 @@ class TestMethods(unittest.TestCase):
|
|||
p.run(pc=bonus)
|
||||
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):
|
||||
p = self.make_pdp()
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue