From 6f8bc554bbe54d9a645f4e314e94b48bbeaa02e7 Mon Sep 17 00:00:00 2001 From: Neil Webber Date: Mon, 23 Oct 2023 08:38:16 -0500 Subject: [PATCH] eliminated ASM with --- pdptests.py | 1441 +++++++++++++++++++++++++-------------------------- 1 file changed, 716 insertions(+), 725 deletions(-) diff --git a/pdptests.py b/pdptests.py index dc2c9c3..fa43db8 100644 --- a/pdptests.py +++ b/pdptests.py @@ -31,7 +31,7 @@ import random import os import hashlib -from pdpasmhelper import PDP11InstructionAssembler as ASM +from pdpasmhelper import InstructionBlock class TestMethods(unittest.TestCase): @@ -126,58 +126,58 @@ class TestMethods(unittest.TestCase): # These instructions will be placed at 2K in memory # - with ASM() as a: - a.mov(0o20000, 'sp') # start system stack at 8k + a = InstructionBlock() + a.mov(0o20000, 'sp') # start system stack at 8k - # write the constants as described above - a.mov(0o22222, a.ptr(0o20000)) - a.mov(0o33333, a.ptr(0o20002)) - a.mov(0o44444, a.ptr(0o40000)) + # write the constants as described above + a.mov(0o22222, a.ptr(0o20000)) + a.mov(0o33333, a.ptr(0o20002)) + a.mov(0o44444, a.ptr(0o40000)) - # point both kernel seg 0 PARs to physical zero - a.clr(a.ptr(cn.KISA0)) - a.clr(a.ptr(cn.KDSA0)) + # point both kernel seg 0 PARs to physical zero + a.clr(a.ptr(cn.KISA0)) + a.clr(a.ptr(cn.KDSA0)) - # kernel seg 7 D space PAR to I/O page (at 22-bit location) - a.mov(0o017760000 >> 6, a.ptr(cn.KDSA0 + (7 * 2))) + # kernel seg 7 D space PAR to I/O page (at 22-bit location) + a.mov(0o017760000 >> 6, a.ptr(cn.KDSA0 + (7 * 2))) - # user I seg 0 to 0o20000, user D seg 0 to 0o40000 - a.mov(0o20000 >> 6, a.ptr(cn.UISA0)) - a.mov(0o40000 >> 6, a.ptr(cn.UDSA0)) + # user I seg 0 to 0o20000, user D seg 0 to 0o40000 + a.mov(0o20000 >> 6, a.ptr(cn.UISA0)) + a.mov(0o40000 >> 6, a.ptr(cn.UDSA0)) - # set the PDRs for segment zero - a.mov(0o077406, 'r3') - # 77406 = PDR<2:0> = ACF = 0o110 = read/write - # PLF<14:8> =0o0774 = full length (128*64 bytes = 8K) + # set the PDRs for segment zero + a.mov(0o077406, 'r3') + # 77406 = PDR<2:0> = ACF = 0o110 = read/write + # PLF<14:8> =0o0774 = full length (128*64 bytes = 8K) - a.mov('r3', a.ptr(cn.KISD0)) - a.mov('r3', a.ptr(cn.KDSD0)) - a.mov('r3', a.ptr(cn.UISD0)) - a.mov('r3', a.ptr(cn.UDSD0)) + a.mov('r3', a.ptr(cn.KISD0)) + a.mov('r3', a.ptr(cn.KDSD0)) + a.mov('r3', a.ptr(cn.UISD0)) + a.mov('r3', a.ptr(cn.UDSD0)) - # PDR for segment 7 - a.mov('r3', a.ptr(cn.KDSD0 + (7 * 2))) + # PDR for segment 7 + a.mov('r3', a.ptr(cn.KDSD0 + (7 * 2))) - # set previous mode to USER, keeping current mode KERNEL, pri 7 - a.mov((p.KERNEL << 14) | (p.USER << 12) | (7 << 5), - a.ptr(self.ioaddr(p, p.PS_OFFS))) + # set previous mode to USER, keeping current mode KERNEL, pri 7 + a.mov((p.KERNEL << 14) | (p.USER << 12) | (7 << 5), + a.ptr(self.ioaddr(p, p.PS_OFFS))) - # turn on 22-bit mode, unibus mapping, and I/D sep for k & u - a.mov(0o000065, a.ptr(cn.MMR3)) + # turn on 22-bit mode, unibus mapping, and I/D sep for k & u + a.mov(0o000065, a.ptr(cn.MMR3)) - # Instructions supplied by caller, to be executed before - # enabling the MMU. They are "literals" since they have - # already been assembled. - for w in premmu: - a.literal(w) + # Instructions supplied by caller, to be executed before + # enabling the MMU. They are "literals" since they have + # already been assembled. + for w in premmu: + a.literal(w) - # turn on relocation mode ... - a.inc(a.ptr(cn.MMR0)) + # turn on relocation mode ... + a.inc(a.ptr(cn.MMR0)) - # and the post-MMU instructions - for w in postmmu: - a.literal(w) - a.halt() + # and the post-MMU instructions + for w in postmmu: + a.literal(w) + a.halt() instloc = 0o4000 # 2K self.loadphysmem(p, a, instloc) @@ -190,10 +190,10 @@ class TestMethods(unittest.TestCase): for result, r1tval in ((0o33333, 2), (0o22222, 0)): # r1=r1tval, mfpi (r1) -> r0; expect r0 = result - with ASM() as a: - a.mov(r1tval, 'r1') - a.mfpi('(r1)') - a.mov('(sp)+', 'r0') + a = InstructionBlock() + a.mov(r1tval, 'r1') + a.mfpi('(r1)') + a.mov('(sp)+', 'r0') tvecs.append((result, list(a)),) for result, insts in tvecs: @@ -205,32 +205,31 @@ class TestMethods(unittest.TestCase): def test_mfpxsp(self): cn = self.usefulconstants() - with ASM() as u: - u.mov('r2', 'r6') - u.trap(0) + u = InstructionBlock() + u.mov('r2', 'r6') + u.trap(0) - with ASM() as premmu: - ts = premmu # just for brevity... - ts.mov(0o14000, ts.ptr(0o34)) # set vector 034 to 14000 - ts.clr(ts.ptr(0o36)) # PSW for trap - zero work - ts.mov(0o20000, 'r0') # mov #20000,r0 + premmu = InstructionBlock() + premmu.mov(0o14000, premmu.ptr(0o34)) # set vector 034 to 14000 + premmu.clr(premmu.ptr(0o36)) # PSW for trap - zero work + premmu.mov(0o20000, 'r0') - for uinst in u: - ts.mov(uinst, '(r0)+') - ts.mov(0o123456, 'r2') # mov #123456,r2 - ts.mov(0o140340, '-(sp)') # push user-ish PSW to K stack - ts.clr('-(sp)') # new user PC = 0 + for uinst in u: + premmu.mov(uinst, '(r0)+') + premmu.mov(0o123456, 'r2') + premmu.mov(0o140340, '-(sp)') # push user-ish PSW to K stack + premmu.clr('-(sp)') # new user PC = 0 - with ASM() as postmmu: - postmmu.literal(6) # RTT - goes to user mode, addr 0 + postmmu = InstructionBlock() + postmmu.rtt() # RTT - goes to user mode, addr 0 p, pc = self.simplemapped_pdp(premmu=premmu, postmmu=postmmu) # put the trap handler at 14000 as expected - with ASM() as th: - th.mfpd('sp') - th.mov('(sp)+', 'r3') - th.halt() + th = InstructionBlock() + th.mfpd('sp') + th.mov('(sp)+', 'r3') + th.halt() self.loadphysmem(p, th, 0o14000) p.run(pc=pc) self.assertEqual(p.r[2], p.r[3]) @@ -238,11 +237,11 @@ class TestMethods(unittest.TestCase): def test_mtpi(self): cn = self.usefulconstants() - with ASM() as ts: - ts.mov(0o1717, '-(sp)') # pushing 0o1717 - ts.mtpi(ts.ptr(0o02)) # and MTPI it to user location 2 - ts.clr(ts.ptr(cn.MMR0)) # turn MMU back off - ts.mov(ts.ptr(0o20002), 'r0') # r0 = (020002) + ts = InstructionBlock() + ts.mov(0o1717, '-(sp)') # pushing 0o1717 + ts.mtpi(ts.ptr(0o02)) # and MTPI it to user location 2 + ts.clr(ts.ptr(cn.MMR0)) # turn MMU back off + ts.mov(ts.ptr(0o20002), 'r0') # r0 = (020002) tvecs = ((0o1717, ts),) @@ -270,9 +269,9 @@ class TestMethods(unittest.TestCase): sub_loc = testloc + 4 for addsub, loc in (('add', add_loc), ('sub', sub_loc)): - with ASM() as a: - getattr(a, addsub)('r0', 'r1') - a.halt() + a = InstructionBlock() + getattr(a, addsub)('r0', 'r1') + a.halt() self.loadphysmem(p, a, loc) for r0, r1, added, a_nzvc, subbed, s_nzvc in testvecs: @@ -297,21 +296,14 @@ class TestMethods(unittest.TestCase): p = self.make_pdp() loopcount = 0o1000 - with ASM() as a: - # Program is: - # MOV loopcount,R1 - # CLR R0 - # LOOP: INC R0 - # DEC R1 - # BNE LOOP - # HALT - a.mov(loopcount, 'r1') - a.clr('r0') - a.label('LOOP') - a.inc('r0') - a.dec('r1') - a.bne('LOOP') - a.halt() + a = InstructionBlock() + a.mov(loopcount, 'r1') + a.clr('r0') + a.label('LOOP') + a.inc('r0') + a.dec('r1') + a.bne('LOOP') + a.halt() instloc = 0o4000 self.loadphysmem(p, a, instloc) @@ -325,18 +317,18 @@ class TestMethods(unittest.TestCase): p = self.make_pdp() goodval = 0o4321 # arbitrary, not zero - with ASM() as a: - a.clr('r1') # if successful r1 will become goodval - a.clr('r0') - a.beq('good') - a.halt() # stop here if BEQ fails - a.label('good') - a.literal(0o000257) # 1f: CCC .. clear all the condition codes - a.bne('good2') - a.halt() # stop here if BNE fails - a.label('good2') - a.mov(goodval, 'r1') # indicate success - a.halt() + a = InstructionBlock() + a.clr('r1') # if successful r1 will become goodval + a.clr('r0') + a.beq('good') + a.halt() # stop here if BEQ fails + a.label('good') + a.literal(0o000257) # 1f: CCC .. clear all the condition codes + a.bne('good2') + a.halt() # stop here if BNE fails + a.label('good2') + a.mov(goodval, 'r1') # indicate success + a.halt() instloc = 0o4000 self.loadphysmem(p, a, instloc) @@ -345,40 +337,40 @@ class TestMethods(unittest.TestCase): # create the instruction sequence shared by test_cc and test_ucc def _cc_unscc(self, br1, br2): - with ASM() as a: - # program is: - # CLR R0 - # MOV @#05000,R1 ; see discussion below - # MOV @#05002,R2 ; see discussion below - # CMP R1,R2 - # br1 1f ; see discussion - # HALT - # 1: DEC R0 - # CMP R2,R1 - # br2 1f ; see discussion - # HALT - # 1: DEC R0 - # HALT - # - # The test_cc and test_unscc tests will poke various test - # cases into locations 5000 and 5002, knowing the order of - # the operands in the two CMP instructions and choosing - # test cases and br1/br2 accordingly. - # - # If the program makes it to the end R0 will be 65554 (-2) + a = InstructionBlock() + # program is: + # CLR R0 + # MOV @#05000,R1 ; see discussion below + # MOV @#05002,R2 ; see discussion below + # CMP R1,R2 + # br1 1f ; see discussion + # HALT + # 1: DEC R0 + # CMP R2,R1 + # br2 1f ; see discussion + # HALT + # 1: DEC R0 + # HALT + # + # The test_cc and test_unscc tests will poke various test + # cases into locations 5000 and 5002, knowing the order of + # the operands in the two CMP instructions and choosing + # test cases and br1/br2 accordingly. + # + # If the program makes it to the end R0 will be 65554 (-2) - a.clr('r0') - a.mov(a.ptr(0o5000), 'r1') - a.mov(a.ptr(0o5002), 'r2') - a.cmp('r1', 'r2') - a.literal((br1 & 0o177400) | 1) # br1 1f - a.halt() - a.dec('r0') - a.cmp('r2', 'r1') - a.literal((br2 & 0o177400) | 1) # br2 1f - a.halt() - a.dec('r0') - a.halt() + a.clr('r0') + a.mov(a.ptr(0o5000), 'r1') + a.mov(a.ptr(0o5002), 'r2') + a.cmp('r1', 'r2') + a.literal((br1 & 0o177400) | 1) # br1 1f + a.halt() + a.dec('r0') + a.cmp('r2', 'r1') + a.literal((br2 & 0o177400) | 1) # br2 1f + a.halt() + a.dec('r0') + a.halt() return a def test_cc(self): @@ -453,12 +445,12 @@ class TestMethods(unittest.TestCase): def test_ash1(self): # this code sequence taken from Unix startup, it's not really # much of a test. - with ASM() as a: - a.mov(0o0122451, 'r2') - neg6 = -6 & 0xFFFF - a.ash(neg6, 'r2') - a.bic(0o0176000, 'r2') - a.halt() + a = InstructionBlock() + a.mov(0o0122451, 'r2') + neg6 = -6 & 0xFFFF + a.ash(neg6, 'r2') + a.bic(0o0176000, 'r2') + a.halt() p = self.make_pdp() instloc = 0o4000 @@ -542,97 +534,97 @@ class TestMethods(unittest.TestCase): p = self.make_pdp() - with ASM() as a: - # The test cases will be X / Y: - # X : 1, 255, 4096, 10017, 32767, 32768, 32769 - # and then those same values with 690000 added to them - # Y : -50 .. 50 but skipping 0 and using a large number - # - # The code is written this way so that the resulting ASM() - # is completely self-contained (does not rely on python to - # drive it). This made it easier to cross-verify w/SIMH + a = InstructionBlock() + # The test cases will be X / Y: + # X : 1, 255, 4096, 10017, 32767, 32768, 32769 + # and then those same values with 690000 added to them + # Y : -50 .. 50 but skipping 0 and using a large number + # + # The code is written this way so that the resulting block + # is completely self-contained (does not rely on python to + # drive it). This made it easier to cross-verify w/SIMH - # As described above: X test values. - # *** SHA256 NOTE: DO NOT CHANGE THESE TEST VALUES. - # THE TEST RELIES ON A PRECOMPUTED SHA256 HASH BASED - # ON RESULTS FROM THESE VALUES - xvals = (1, 255, 4096, 10017, 32767, 32768, 32769) + # As described above: X test values. + # *** SHA256 NOTE: DO NOT CHANGE THESE TEST VALUES. + # THE TEST RELIES ON A PRECOMPUTED SHA256 HASH BASED + # ON RESULTS FROM THESE VALUES + xvals = (1, 255, 4096, 10017, 32767, 32768, 32769) - xtable = 0o20000 # address for storing the above - results = 0o30000 # address for storing results list + xtable = 0o20000 # address for storing the above + results = 0o30000 # address for storing results list - # instead of div by zero, div by this randomish large number - # *** DO NOT CHANGE; see sha256 note above - largedivisor = 10017 # has to be 16 bits or less + # instead of div by zero, div by this randomish large number + # *** DO NOT CHANGE; see sha256 note above + largedivisor = 10017 # has to be 16 bits or less - # The divisor will run from -this to this. - # *** DO NOT CHANGE; see sha256 note above - divisorrange = 50 + # The divisor will run from -this to this. + # *** DO NOT CHANGE; see sha256 note above + divisorrange = 50 - a.clr(a.ptr(0o177776)) - a.mov(xtable, 'r0') - for x in xvals: - # same data but negated - xneg = ((p.MASK32 + 1) - x) & p.MASK32 + a.clr(a.ptr(0o177776)) + a.mov(xtable, 'r0') + for x in xvals: + # same data but negated + xneg = ((p.MASK32 + 1) - x) & p.MASK32 - # same data but 690000 arbitrarily added (to make it 32bit) - xplus = x + 690000 + # same data but 690000 arbitrarily added (to make it 32bit) + xplus = x + 690000 - # ...and negated - xplusneg = ((p.MASK32 + 1) - xplus) & p.MASK32 + # ...and negated + xplusneg = ((p.MASK32 + 1) - xplus) & p.MASK32 - # put all of those into the dividend table - for v in (x, xneg, xplus, xplusneg): - a.mov((v >> 16) & p.MASK16, '(r0)+') - a.mov(v & p.MASK16, '(r0)+') + # put all of those into the dividend table + for v in (x, xneg, xplus, xplusneg): + a.mov((v >> 16) & p.MASK16, '(r0)+') + a.mov(v & p.MASK16, '(r0)+') - a.clr('(r0)+') # sentinel - a.clr('(r0)') # sentinel + a.clr('(r0)+') # sentinel + a.clr('(r0)') # sentinel - # test loop. Divisor in r4. Dividend in r2/r3 - # xval pointer in r0. Results pointer in r1 - a.mov(results, 'r1') - a.mov(-divisorrange, 'r4') - a.label('outer') - a.mov(xtable, 'r0') - a.label('inner') - a.mov('(r0)+', 'r2') - a.mov('(r0)+', 'r3') - a.tst('r2') - a.bne('divide') - a.tst('r3') - a.bne('divide') + # test loop. Divisor in r4. Dividend in r2/r3 + # xval pointer in r0. Results pointer in r1 + a.mov(results, 'r1') + a.mov(-divisorrange, 'r4') + a.label('outer') + a.mov(xtable, 'r0') + a.label('inner') + a.mov('(r0)+', 'r2') + a.mov('(r0)+', 'r3') + a.tst('r2') + a.bne('divide') + a.tst('r3') + a.bne('divide') - # hit the sentinel, bump the divisor - # look for the large divisor and forge a zero to get to 1 + # hit the sentinel, bump the divisor + # look for the large divisor and forge a zero to get to 1 - a.cmp('r4', largedivisor) - a.bne('bump') - a.clr('r4') + a.cmp('r4', largedivisor) + a.bne('bump') + a.clr('r4') - a.label('bump') - a.inc('r4') - a.bne('nz') + a.label('bump') + a.inc('r4') + a.bne('nz') - a.mov(largedivisor, 'r4') - a.br('outer') + a.mov(largedivisor, 'r4') + a.br('outer') - a.label('nz') - a.cmp('r4', divisorrange) - a.ble('outer') + a.label('nz') + a.cmp('r4', divisorrange) + a.ble('outer') - a.mov(69, 'r0') # this indicates success - a.halt() - a.label('divide') + a.mov(69, 'r0') # this indicates success + a.halt() + a.label('divide') - # divide instruction hand-assembled - a.literal(0o071204) + # divide instruction hand-assembled + a.literal(0o071204) - # first save the PSW - a.mov(a.ptr(0o177776), '(r1)+') - a.mov('r2', '(r1)+') - a.mov('r3', '(r1)+') - a.br('inner') + # first save the PSW + a.mov(a.ptr(0o177776), '(r1)+') + a.mov('r2', '(r1)+') + a.mov('r3', '(r1)+') + a.br('inner') self.loadphysmem(p, a, 0o10000) p.run(pc=0o10000) @@ -757,13 +749,13 @@ class TestMethods(unittest.TestCase): p.physmem[15] = 0 # this trap handler puts the trap # into R3 - with ASM() as handler: - # the saved PC is at the top of the stack ... get it - handler.mov('(sp)', 'r0') - # get the low byte of the instruction which is the trap code - # note that the PC points after the TRAP instruction so: - handler.movb('-2(r0)', 'r3') - handler.rtt() + handler = InstructionBlock() + # the saved PC is at the top of the stack ... get it + handler.mov('(sp)', 'r0') + # get the low byte of the instruction which is the trap code + # note that the PC points after the TRAP instruction so: + handler.movb('-2(r0)', 'r3') + handler.rtt() self.loadphysmem(p, handler, 0o10000) @@ -771,10 +763,10 @@ class TestMethods(unittest.TestCase): p.r[6] = 0o20000 # 8K and working down for i in range(256): - with ASM() as a: - a.trap(i) # TRAP #i - a.mov('r3', 'r1') # MOV R3,R1 just to show RTT worked - a.halt() + a = InstructionBlock() + a.trap(i) # TRAP #i + a.mov('r3', 'r1') # MOV R3,R1 just to show RTT worked + a.halt() self.loadphysmem(p, a, 0o30000) p.run(pc=0o30000) @@ -864,67 +856,67 @@ class TestMethods(unittest.TestCase): # Nevertheless, here it is. # this code will go at taddr - with ASM() as tr: - # The trap handler for MMU faults and the trap 0 / trap 1 from - # the user code (when there is no MMU fault). It is integrated - # into one routine. - # - # The user code gets to use r0 and r1, the trap handler - # gets to use r2-r5: - # r2: expected good flag (initialized elsewhere) - # r3: determined good flag (by trap entry) - # r5: test table data pointer (initialized elsewhere) - tr.label('UTrap') + tr = InstructionBlock() + # The trap handler for MMU faults and the trap 0 / trap 1 from + # the user code (when there is no MMU fault). It is integrated + # into one routine. + # + # The user code gets to use r0 and r1, the trap handler + # gets to use r2-r5: + # r2: expected good flag (initialized elsewhere) + # r3: determined good flag (by trap entry) + # r5: test table data pointer (initialized elsewhere) + tr.label('UTrap') - # first determine if trap0 (bad) or trap1 (good) - tr.mov('(sp)', 'r3') # get user PC from trap frame - tr.mfpi('-2(r3)') # get the trap instruction - tr.mov('(sp)+', 'r3') # r3 is now the trap instruction - tr.bic(0o177400, 'r3') - tr.cmp(1, 'r3') - tr.beq('common') # skip the HALT and the MMU entry point - # this was not a "good" trap, the user code failed - tr.halt() + # first determine if trap0 (bad) or trap1 (good) + tr.mov('(sp)', 'r3') # get user PC from trap frame + tr.mfpi('-2(r3)') # get the trap instruction + tr.mov('(sp)+', 'r3') # r3 is now the trap instruction + tr.bic(0o177400, 'r3') + tr.cmp(1, 'r3') + tr.beq('common') # skip the HALT and the MMU entry point + # this was not a "good" trap, the user code failed + tr.halt() - tr.label('TrapMMU') - tr.clr('r3') # indicate MMU fault case + tr.label('TrapMMU') + tr.clr('r3') # indicate MMU fault case - # both Utrap and TrapMMU join in common here on out - # see if the access was good/bad as expected - tr.label('common') - tr.cmp('r2', 'r3') - tr.beq('bump') # jump over the HALT - tr.halt() # NOPE, something wrong! + # both Utrap and TrapMMU join in common here on out + # see if the access was good/bad as expected + tr.label('common') + tr.cmp('r2', 'r3') + tr.beq('bump') # jump over the HALT + tr.halt() # NOPE, something wrong! - # the user mode code specifically avoids '(r0)+' - # to avoid ambiguity in machine types for when the - # autoincrement happens in the face of MMU aborts. - # Bump r0 for the user code here accordingly: - tr.label('bump') - tr.add(2, 'r0') + # the user mode code specifically avoids '(r0)+' + # to avoid ambiguity in machine types for when the + # autoincrement happens in the face of MMU aborts. + # Bump r0 for the user code here accordingly: + tr.label('bump') + tr.add(2, 'r0') - # see if it is time to switch to next table entry - tr.cmp('2(r5)', 'r0') - tr.bne('rtu') # skip over the "time to switch" stanza + # see if it is time to switch to next table entry + tr.cmp('2(r5)', 'r0') + tr.bne('rtu') # skip over the "time to switch" stanza - # it is time to switch - tr.add(4, 'r5') - tr.mov('(r5)', 'r2') - tr.cmp(0o666, 'r2') - tr.bne('rtu') - tr.halt() # test done; success if r2 = 0o666 + # it is time to switch + tr.add(4, 'r5') + tr.mov('(r5)', 'r2') + tr.cmp(0o666, 'r2') + tr.bne('rtu') + tr.halt() # test done; success if r2 = 0o666 - tr.label('rtu') - # next iteration of the user code loop - tr.clr('(sp)') # put user PC back to zero - tr.rtt() + tr.label('rtu') + # next iteration of the user code loop + tr.clr('(sp)') # put user PC back to zero + tr.rtt() - # this trap handler is only used during the startup phase - # See where the kernel code invokes the user setup code - tr.label('trap_usersetup') - # the kernel put a resume address onto the stack, just go there - tr.add(4, 'sp') # get rid of user trap frame, don't care - tr.mov('(sp)+', 'pc') + # this trap handler is only used during the startup phase + # See where the kernel code invokes the user setup code + tr.label('trap_usersetup') + # the kernel put a resume address onto the stack, just go there + tr.add(4, 'sp') # get rid of user trap frame, don't care + tr.mov('(sp)+', 'pc') # user mode program: there are two parts to this # Starting at (user) location ZERO: the test program: @@ -942,42 +934,42 @@ class TestMethods(unittest.TestCase): # user-mode code executed before the test begins to put # the test pattern into memory - with ASM() as u: - # this subtract combines the access check with part1 of chksum - u.mov(0o123456, 'r1') - u.sub('(r0)', 'r1') - u.cmp('r0', 'r1') - u.beq('good') - u.trap(0o77) # trap 77 indicates miscompare + u = InstructionBlock() + # this subtract combines the access check with part1 of chksum + u.mov(0o123456, 'r1') + u.sub('(r0)', 'r1') + u.cmp('r0', 'r1') + u.beq('good') + u.trap(0o77) # trap 77 indicates miscompare - u.label('good') - u.trap(1) # indicate good status - # the kernel puts the PC back to zero after the good trap - # and also bumps r0. This is how the loop loops. - u.halt() # never get here, this is illegal + u.label('good') + u.trap(1) # indicate good status + # the kernel puts the PC back to zero after the good trap + # and also bumps r0. This is how the loop loops. + u.halt() # never get here, this is illegal - # this code is executed one time at startup (see kernel code) - u.label('setup') + # this code is executed one time at startup (see kernel code) + u.label('setup') - # Initialize the user D space pattern that will be checked - # by the user code. In python this was: - # - # checksum = 0o123456 # arbitrary - # user_phys_DSPACEbase = 0o200000 - # words = (checksum - (user_phys_DSPACEbase + o) & 0o177777 - # for o in range(0, 65536, 2)) - # self.loadphysmem(p, words, user_phys_DSPACEbase) - u.clr('r0') - u.mov(0o123456, 'r1') + # Initialize the user D space pattern that will be checked + # by the user code. In python this was: + # + # checksum = 0o123456 # arbitrary + # user_phys_DSPACEbase = 0o200000 + # words = (checksum - (user_phys_DSPACEbase + o) & 0o177777 + # for o in range(0, 65536, 2)) + # self.loadphysmem(p, words, user_phys_DSPACEbase) + u.clr('r0') + u.mov(0o123456, 'r1') - u.label('pattern') - u.mov('r1', '(r0)+') - u.sub(2, 'r1') - u.tst('r0') - u.bne('pattern') - # the kernel code looks for this in r1 as success flag - u.mov(0o3333, 'r1') - u.trap(0) + u.label('pattern') + u.mov('r1', '(r0)+') + u.sub(2, 'r1') + u.tst('r0') + u.bne('pattern') + # the kernel code looks for this in r1 as success flag + u.mov(0o3333, 'r1') + u.trap(0) # The kernel-mode code that drives the whole test @@ -986,243 +978,243 @@ class TestMethods(unittest.TestCase): # # The stack will start at kstackstart - with ASM() as k: - k.mov(kernel_stack, 'sp') + k = InstructionBlock() + k.mov(kernel_stack, 'sp') - # KERNEL I SPACE - # PAR 0 to physical 0 - # PAR 7 to physical 760000 and 22bit not turned on - # - # PDR 77406 = read/write, full length - k.clr(k.ptr(cn.KISA0)) - k.mov(0o760000 >> 6, k.ptr(cn.KISA7)) - k.mov(0o077406, k.ptr(cn.KISD0)) - k.mov(0o077406, k.ptr(cn.KISD7)) + # KERNEL I SPACE + # PAR 0 to physical 0 + # PAR 7 to physical 760000 and 22bit not turned on + # + # PDR 77406 = read/write, full length + k.clr(k.ptr(cn.KISA0)) + k.mov(0o760000 >> 6, k.ptr(cn.KISA7)) + k.mov(0o077406, k.ptr(cn.KISD0)) + k.mov(0o077406, k.ptr(cn.KISD7)) - # USER I SPACE - k.mov(uaddr >> 6, k.ptr(cn.UISA0)) - k.mov(0o077406, k.ptr(cn.UISD0)) + # USER I SPACE + k.mov(uaddr >> 6, k.ptr(cn.UISA0)) + k.mov(0o077406, k.ptr(cn.UISD0)) - # USER D SPACE... first set it up to be simply/fully - # accessible at its physical home, so that the pattern - # can be set. Then come back and limit the page lengths later. + # USER D SPACE... first set it up to be simply/fully + # accessible at its physical home, so that the pattern + # can be set. Then come back and limit the page lengths later. - k.mov(cn.UDSD0, 'r3') # will walk through D0 .. D7 - # NOTE: A0 .. A7 is 040(r3) - k.mov(uphysdata >> 6, 'r4') # phys addr base - k.mov(8, 'r0') - k.label('utmp') - k.mov('r4', '040(r3)') # set U PAR; don't bump r3 yet - k.add(0o200, 'r4') # 0o200 = 8192>>6 - k.mov(0o77406, '(r3)+') # set U PDR and bump to next - k.sob(0, 'utmp') + k.mov(cn.UDSD0, 'r3') # will walk through D0 .. D7 + # NOTE: A0 .. A7 is 040(r3) + k.mov(uphysdata >> 6, 'r4') # phys addr base + k.mov(8, 'r0') + k.label('utmp') + k.mov('r4', '040(r3)') # set U PAR; don't bump r3 yet + k.add(0o200, 'r4') # 0o200 = 8192>>6 + k.mov(0o77406, '(r3)+') # set U PDR and bump to next + k.sob(0, 'utmp') - k.bis(1, k.ptr(cn.MMR3)) # enable I/D sep just for USER - k.mov(1, k.ptr(cn.MMR0)) # turn on MMU + k.bis(1, k.ptr(cn.MMR3)) # enable I/D sep just for USER + k.mov(1, k.ptr(cn.MMR0)) # turn on MMU - # certainly could have used mtpd to set up the user mode - # 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 + tr.getlabel('trap_usersetup'), '*$34') - k.mov(0o340, '*$36') + # certainly could have used mtpd to set up the user mode + # 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 + tr.getlabel('trap_usersetup'), '*$34') + k.mov(0o340, '*$36') - k.mov('pc', '-(sp)') - # add the offset to (forward ref) back_from_u - k.add(k.getlabel('back_from_u'), '(sp)') + k.mov('pc', '-(sp)') + # add the offset to (forward ref) back_from_u + k.add(k.getlabel('back_from_u'), '(sp)') - k.mov(0o140340, '-(sp)') # push user-ish PSW to K stack - k.mov(u.getlabel('setup'), '-(sp)') # PC for setup code - k.rtt() + k.mov(0o140340, '-(sp)') # push user-ish PSW to K stack + k.mov(u.getlabel('setup'), '-(sp)') # PC for setup code + k.rtt() - k.label('back_from_u') - # user code dropped this magic value into r1 on success - k.cmp(0o3333, 'r1') - k.beq('ok') - k.halt() + k.label('back_from_u') + # user code dropped this magic value into r1 on success + k.cmp(0o3333, 'r1') + k.beq('ok') + k.halt() - k.label('ok') - # and now set the length limits on the user D space - k.mov(cn.UDSD0, 'r3') # will walk through D0 .. D7 - k.clr('r0') # r0: segno*2 = (0, 2, 4, .., 14) + k.label('ok') + # and now set the length limits on the user D space + k.mov(cn.UDSD0, 'r3') # will walk through D0 .. D7 + k.clr('r0') # r0: segno*2 = (0, 2, 4, .., 14) - k.label('PDRloop') - k.mov('r0', 'r2') # r2 = segno*2 - k.ash(3, 'r2') # r2 = segno*16 - k.swab('r2') # really (segno*16)<<8 - k.add(0o06, 'r2') # ACF r/w segment - k.mov('r2', '(r3)+') # set U PDR - k.inc('r0') # bump r0 by two - k.inc('r0') - k.cmp('r0', 16) # and loop until done all 8 segments - k.blt('PDRloop') + k.label('PDRloop') + k.mov('r0', 'r2') # r2 = segno*2 + k.ash(3, 'r2') # r2 = segno*16 + k.swab('r2') # really (segno*16)<<8 + k.add(0o06, 'r2') # ACF r/w segment + k.mov('r2', '(r3)+') # set U PDR + k.inc('r0') # bump r0 by two + k.inc('r0') + k.cmp('r0', 16) # and loop until done all 8 segments + k.blt('PDRloop') - # create the test table, just push it onto the stack (yeehah!) - k.mov(0, '-(sp)') # this is a PAD (not really needed) - k.mov(0o666, '-(sp)') # this is a sentinel - k.mov(0, '-(sp)') - k.mov(0, '-(sp)') - k.mov(0o176100, '-(sp)') - k.mov(1, '-(sp)') - k.mov(0o160000, '-(sp)') - k.mov(0, '-(sp)') - k.mov(0o154100, '-(sp)') - k.mov(1, '-(sp)') - k.mov(0o140000, '-(sp)') - k.mov(0, '-(sp)') - k.mov(0o132100, '-(sp)') - k.mov(1, '-(sp)') - k.mov(0o120000, '-(sp)') - k.mov(0, '-(sp)') - k.mov(0o110100, '-(sp)') - k.mov(1, '-(sp)') - k.mov(0o100000, '-(sp)') - k.mov(0, '-(sp)') - k.mov(0o66100, '-(sp)') - k.mov(1, '-(sp)') - k.mov(0o60000, '-(sp)') - k.mov(0, '-(sp)') - k.mov(0o44100, '-(sp)') - k.mov(1, '-(sp)') - k.mov(0o40000, '-(sp)') - k.mov(0, '-(sp)') - k.mov(0o22100, '-(sp)') - k.mov(1, '-(sp)') - k.mov(0o20000, '-(sp)') - k.mov(0, '-(sp)') - k.mov(0o100, '-(sp)') - k.mov(1, '-(sp)') + # create the test table, just push it onto the stack (yeehah!) + k.mov(0, '-(sp)') # this is a PAD (not really needed) + k.mov(0o666, '-(sp)') # this is a sentinel + k.mov(0, '-(sp)') + k.mov(0, '-(sp)') + k.mov(0o176100, '-(sp)') + k.mov(1, '-(sp)') + k.mov(0o160000, '-(sp)') + k.mov(0, '-(sp)') + k.mov(0o154100, '-(sp)') + k.mov(1, '-(sp)') + k.mov(0o140000, '-(sp)') + k.mov(0, '-(sp)') + k.mov(0o132100, '-(sp)') + k.mov(1, '-(sp)') + k.mov(0o120000, '-(sp)') + k.mov(0, '-(sp)') + k.mov(0o110100, '-(sp)') + k.mov(1, '-(sp)') + k.mov(0o100000, '-(sp)') + k.mov(0, '-(sp)') + k.mov(0o66100, '-(sp)') + k.mov(1, '-(sp)') + k.mov(0o60000, '-(sp)') + k.mov(0, '-(sp)') + k.mov(0o44100, '-(sp)') + k.mov(1, '-(sp)') + k.mov(0o40000, '-(sp)') + k.mov(0, '-(sp)') + k.mov(0o22100, '-(sp)') + k.mov(1, '-(sp)') + k.mov(0o20000, '-(sp)') + k.mov(0, '-(sp)') + k.mov(0o100, '-(sp)') + k.mov(1, '-(sp)') - # the test table for the trap handler is now here: - k.mov('sp', 'r5') - k.mov('sp', k.ptr(saved_r5)) # so it can be recovered later + # the test table for the trap handler is now here: + k.mov('sp', 'r5') + 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') + # 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'), '*$250') - k.mov(0o340, '*$252') + # poke the MMU trap handler vector (250) + k.mov(taddr + tr.getlabel('TrapMMU'), '*$250') + k.mov(0o340, '*$252') - # same for the "trap N" handler - k.mov(taddr + tr.getlabel('UTrap'), '*$34') - k.mov(0o340, '*$36') + # same for the "trap N" handler + k.mov(taddr + tr.getlabel('UTrap'), '*$34') + k.mov(0o340, '*$36') - # ok, now ready to start the user program - k.mov(0o140340, '-(sp)') # push user-ish PSW to K stack - k.clr('-(sp)') # new user PC = 0 - k.clr('r0') # user test expects r0 to start zero - k.rtt() + # ok, now ready to start the user program + k.mov(0o140340, '-(sp)') # push user-ish PSW to K stack + k.clr('-(sp)') # new user PC = 0 + k.clr('r0') # user test expects r0 to start zero + k.rtt() - # this is where the DOWN test starts. - k.label('DOWNTEST') + # this is where the DOWN test starts. + k.label('DOWNTEST') - # re-establish initial kernel stack - k.mov(kernel_stack, 'sp') + # re-establish initial kernel stack + k.mov(kernel_stack, 'sp') - # Redo the entire test table for the down address cases - # these were precomputed from the algorithm for setting PDRs - k.mov(0, '-(sp)') - k.mov(0o666, '-(sp)') - k.mov(0, '-(sp)') - k.mov(1, '-(sp)') - k.mov(0o161700, '-(sp)') - k.mov(0, '-(sp)') - k.mov(0o160000, '-(sp)') - k.mov(1, '-(sp)') - k.mov(0o143700, '-(sp)') - k.mov(0, '-(sp)') - k.mov(0o140000, '-(sp)') - k.mov(1, '-(sp)') - k.mov(0o125700, '-(sp)') - k.mov(0, '-(sp)') - k.mov(0o120000, '-(sp)') - k.mov(1, '-(sp)') - k.mov(0o107700, '-(sp)') - k.mov(0, '-(sp)') - k.mov(0o100000, '-(sp)') - k.mov(1, '-(sp)') - k.mov(0o71700, '-(sp)') - k.mov(0, '-(sp)') - k.mov(0o60000, '-(sp)') - k.mov(1, '-(sp)') - k.mov(0o53700, '-(sp)') - k.mov(0, '-(sp)') - k.mov(0o40000, '-(sp)') - k.mov(1, '-(sp)') - k.mov(0o35700, '-(sp)') - k.mov(0, '-(sp)') - k.mov(0o20000, '-(sp)') - k.mov(1, '-(sp)') - k.mov(0o17700, '-(sp)') - k.mov(1, '-(sp)') + # Redo the entire test table for the down address cases + # these were precomputed from the algorithm for setting PDRs + k.mov(0, '-(sp)') + k.mov(0o666, '-(sp)') + k.mov(0, '-(sp)') + k.mov(1, '-(sp)') + k.mov(0o161700, '-(sp)') + k.mov(0, '-(sp)') + k.mov(0o160000, '-(sp)') + k.mov(1, '-(sp)') + k.mov(0o143700, '-(sp)') + k.mov(0, '-(sp)') + k.mov(0o140000, '-(sp)') + k.mov(1, '-(sp)') + k.mov(0o125700, '-(sp)') + k.mov(0, '-(sp)') + k.mov(0o120000, '-(sp)') + k.mov(1, '-(sp)') + k.mov(0o107700, '-(sp)') + k.mov(0, '-(sp)') + k.mov(0o100000, '-(sp)') + k.mov(1, '-(sp)') + k.mov(0o71700, '-(sp)') + k.mov(0, '-(sp)') + k.mov(0o60000, '-(sp)') + k.mov(1, '-(sp)') + k.mov(0o53700, '-(sp)') + k.mov(0, '-(sp)') + k.mov(0o40000, '-(sp)') + k.mov(1, '-(sp)') + k.mov(0o35700, '-(sp)') + k.mov(0, '-(sp)') + k.mov(0o20000, '-(sp)') + k.mov(1, '-(sp)') + k.mov(0o17700, '-(sp)') + k.mov(1, '-(sp)') - k.mov('sp', 'r5') # r5 is where the table starts - k.mov('sp', k.ptr(saved_r5)) # store location for re-use + k.mov('sp', 'r5') # r5 is where the table starts + 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') - k.clr('r0') - k.label('PARloopDOWN') - # compute segno * 8 in r2 (r0 starts as segno*2) - k.mov('r0', 'r2') - k.ash(3, 'r2') - # pln = 0o177 - (segno * 16) - k.mov(0o177, 'r1') - k.sub('r2', 'r1') - k.mov('r1', 'r2') - k.swab('r2') - k.add(0o16, 'r2') # the downward growing case - k.mov('r2', '(r3)+') # set U PDR - k.inc('r0') - k.inc('r0') - k.cmp('r0', 16) - k.blt('PARloopDOWN') + # fiddle the PDRs (PARs stay the same) for the down configuration + k.mov(cn.UDSD0, 'r3') + k.clr('r0') + k.label('PARloopDOWN') + # compute segno * 8 in r2 (r0 starts as segno*2) + k.mov('r0', 'r2') + k.ash(3, 'r2') + # pln = 0o177 - (segno * 16) + k.mov(0o177, 'r1') + k.sub('r2', 'r1') + k.mov('r1', 'r2') + k.swab('r2') + k.add(0o16, 'r2') # the downward growing case + k.mov('r2', '(r3)+') # set U PDR + k.inc('r0') + k.inc('r0') + k.cmp('r0', 16) + k.blt('PARloopDOWN') - k.clr('r2') # the down test starts in 'bad' zone + k.clr('r2') # the down test starts in 'bad' zone - # ok, now ready to start the user program - k.mov(0o140340, '-(sp)') # push user-ish PSW to K stack - k.clr('-(sp)') # new user PC = 0 - k.clr('r0') # user test expects r0 to start zero - k.rtt() + # ok, now ready to start the user program + k.mov(0o140340, '-(sp)') # push user-ish PSW to K stack + k.clr('-(sp)') # new user PC = 0 + k.clr('r0') # user test expects r0 to start zero + k.rtt() - # Now for something extra frosty... relocate just segment 4 - # (arbitrarily chosen) of the user memory to a different - # physical page and run the test again to ensure it still works. - # This will make use of KERNEL A1 and A2 segments to map the - # relocation (note: I space because no sep I/D for kernel here) - k.label('BONUS') + # Now for something extra frosty... relocate just segment 4 + # (arbitrarily chosen) of the user memory to a different + # physical page and run the test again to ensure it still works. + # This will make use of KERNEL A1 and A2 segments to map the + # relocation (note: I space because no sep I/D for kernel here) + k.label('BONUS') - # recover the r5 stack table beginning - k.mov(k.ptr(saved_r5), 'r5') + # recover the r5 stack table beginning + 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 + # 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 - # the new location for this data will be physical 0o600000 - # (not a typo) which becomes 0o6000 in the PAR - k.mov(0o6000, k.ptr(cn.KISA0 + 4)) # i.e., A2 + # the new location for this data will be physical 0o600000 + # (not a typo) which becomes 0o6000 in the PAR + k.mov(0o6000, k.ptr(cn.KISA0 + 4)) # i.e., A2 - # the standard PDR access/full-length/etc bits - k.mov(0o077406, k.ptr(cn.KISD0 + 2)) - k.mov(0o077406, k.ptr(cn.KISD0 + 4)) + # the standard PDR access/full-length/etc bits + k.mov(0o077406, k.ptr(cn.KISD0 + 2)) + k.mov(0o077406, k.ptr(cn.KISD0 + 4)) - # count r0, source address r1, destination r2 - k.mov(4096, 'r0') - k.mov(8192, 'r1') - k.mov(8192*2, 'r2') - k.mov('(r1)+', '(r2)+') - k.literal(0o077002) # SOB to the copy + # count r0, source address r1, destination r2 + k.mov(4096, 'r0') + k.mov(8192, 'r1') + k.mov(8192*2, 'r2') + k.mov('(r1)+', '(r2)+') + k.literal(0o077002) # SOB to the copy - # switch the user page to the new mapping - k.mov(0o6000, k.ptr(cn.UDSA0 + 4*2)) + # switch the user page to the new mapping + k.mov(0o6000, k.ptr(cn.UDSA0 + 4*2)) - # and the standard initialization dance - k.clr('r2') # the down test starts in 'bad' zone - k.clr('r0') - k.clr('(sp)') # just knows the user loop starts at zero - k.rtt() + # and the standard initialization dance + k.clr('r2') # the down test starts in 'bad' zone + k.clr('r0') + k.clr('(sp)') # just knows the user loop starts at zero + k.rtt() return (taddr, tr), (uaddr, u), (kaddr, k) @@ -1306,108 +1298,108 @@ class TestMethods(unittest.TestCase): 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 = InstructionBlock() + # 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 + 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') + # + # 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)') + # 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 + # 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 + # 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') + # 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 + 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 + # 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)') + # 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: W only, mgmt traps not set here - # * 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) + # expected: + # * PDR0: W only, mgmt traps not set here + # * 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) - # These expected_PDRs were obtained by running the machine - # code in this test under SIMH. - expected_PDRs = [0o077506, - 0o077604, - 0o077704, - 0o077704, - 0o077404, - 0o077404, - 0o077404, - 0o077406] + # These expected_PDRs were obtained by running the machine + # code in this test under SIMH. + expected_PDRs = [0o077506, + 0o077604, + 0o077704, + 0o077704, + 0o077404, + 0o077404, + 0o077404, + 0o077406] - k.clr('r0') - k.mov('sp', 'r1') - for i, xpdr in enumerate(expected_PDRs): - k.cmp(xpdr, '(r1)+') - k.beq(f"LXX{i}") - k.mov(i | 0o100000, 'r0') - k.mov('-2(r1)', 'r3') - k.br('_done') - k.label(f"LXX{i}") + k.clr('r0') + k.mov('sp', 'r1') + for i, xpdr in enumerate(expected_PDRs): + k.cmp(xpdr, '(r1)+') + k.beq(f"LXX{i}") + k.mov(i | 0o100000, 'r0') + k.mov('-2(r1)', 'r3') + k.br('_done') + k.label(f"LXX{i}") - k.label('_done') - k.halt() + k.label('_done') + k.halt() self.loadphysmem(p, k, base_address) p.run(pc=base_address) @@ -1416,18 +1408,18 @@ class TestMethods(unittest.TestCase): def test_stacklim0(self): # verify that simply *having* an illegal SP doesn't trap p = self.make_pdp() - with ASM() as a: - a.clr('r0') # will be used to verify progress + a = InstructionBlock() + a.clr('r0') # will be used to verify progress - # none of these bad stack pointers should cause - # a YELLOW trap as they are never used as stacks... - a.clr('sp') # really it's already zero... - a.inc('r0') # show made it to here - a.mov(1, 'sp') # odd SP, very bad idea - a.inc('r0') # show made it to here - a.mov(0o100, 'sp') # still too low - a.inc('r0') # show made it to here - a.halt() + # none of these bad stack pointers should cause + # a YELLOW trap as they are never used as stacks... + a.clr('sp') # really it's already zero... + a.inc('r0') # show made it to here + a.mov(1, 'sp') # odd SP, very bad idea + a.inc('r0') # show made it to here + a.mov(0o100, 'sp') # still too low + a.inc('r0') # show made it to here + a.halt() aa = 0o4000 self.loadphysmem(p, a, aa) @@ -1445,51 +1437,51 @@ class TestMethods(unittest.TestCase): p = self.make_pdp() - with ASM() as tr: - # record... - tr.mov('r2', '(r5)+') # ...separator/entry number - tr.mov('sp', '(r5)+') # ...the sp - tr.mov('(sp)', '(r5)+') # ...the trap-saved pc - tr.mov(tr.ptr(0o177766), 'r1') # (will be used later) - tr.mov('r1', '(r5)+') # ...cpu error register - tr.mov('r2', '(r5)+') # ...separator/entry number + tr = InstructionBlock() + # record... + tr.mov('r2', '(r5)+') # ...separator/entry number + tr.mov('sp', '(r5)+') # ...the sp + tr.mov('(sp)', '(r5)+') # ...the trap-saved pc + tr.mov(tr.ptr(0o177766), 'r1') # (will be used later) + tr.mov('r1', '(r5)+') # ...cpu error register + tr.mov('r2', '(r5)+') # ...separator/entry number - # indicate successfully completed the above, bump entry number - tr.inc('r2') + # indicate successfully completed the above, bump entry number + tr.inc('r2') - # but if RED trap, stop here. - tr.bit(p.CPUERR_BITS.REDZONE, 'r1') - tr.beq('rtt') - tr.halt() - tr.label('rtt') - tr.rtt() + # but if RED trap, stop here. + tr.bit(p.CPUERR_BITS.REDZONE, 'r1') + tr.beq('rtt') + tr.halt() + tr.label('rtt') + tr.rtt() tra = 0o6000 self.loadphysmem(p, tr, tra) recordmagic = 0o66000 - with ASM() as a: - a.mov(0o400, 'sp') - a.mov(0o7000, 'r5') - a.mov(recordmagic, 'r2') + a = InstructionBlock() + a.mov(0o400, 'sp') + a.mov(0o7000, 'r5') + a.mov(recordmagic, 'r2') - # dirty up the (to be pushed to) stack to verify writes happened - a.mov(0o370, 'r0') - a.mov('r0', '(r0)+') - a.mov('r0', '(r0)+') - a.mov('r0', '(r0)+') - a.mov('r0', '(r0)+') + # dirty up the (to be pushed to) stack to verify writes happened + a.mov(0o370, 'r0') + a.mov('r0', '(r0)+') + a.mov('r0', '(r0)+') + a.mov('r0', '(r0)+') + a.mov('r0', '(r0)+') - # install the trap handler - a.mov(tra, a.ptr(0o4)) - a.mov(0o340, a.ptr(0o6)) + # install the trap handler + a.mov(tra, a.ptr(0o4)) + a.mov(0o340, a.ptr(0o6)) - loopcount = 3 if not go_red else 30 # will never get to 30 - a.mov(loopcount, 'r0') - a.label('push') - a.clr('-(sp)') - a.sob('r0', 'push') - a.halt() + loopcount = 3 if not go_red else 30 # will never get to 30 + a.mov(loopcount, 'r0') + a.label('push') + a.clr('-(sp)') + a.sob('r0', 'push') + a.halt() aa = 0o4000 self.loadphysmem(p, a, aa) @@ -1566,11 +1558,11 @@ class TestMethods(unittest.TestCase): p = self.make_pdp() maxtest = 100 - with ASM() as a: - for i in range(maxtest): - a.mov(i, 'r0') - a.clr('r0') - a.halt() + a = InstructionBlock() + for i in range(maxtest): + a.mov(i, 'r0') + a.clr('r0') + a.halt() startaddr = 0o4000 self.loadphysmem(p, a, startaddr) @@ -1586,12 +1578,11 @@ class TestMethods(unittest.TestCase): p = self.make_pdp() maxtest = 100 - with ASM() as a: - for i in range(maxtest): - a.mov(i, 'r0') - a.label(f"L{i}") - a.clr('r0') - a.halt() + a = InstructionBlock() + for i in range(maxtest): + a.mov(i, 'r0') + a.label(f"L{i}") + a.clr('r0') startaddr = 0o4000 self.loadphysmem(p, a, startaddr) @@ -1606,11 +1597,11 @@ class TestMethods(unittest.TestCase): p = self.make_pdp() maxtest = 100 - with ASM() as a: - for i in range(maxtest): - a.mov(i+1, 'r0') - a.clr('r0') - a.halt() + a = InstructionBlock() + for i in range(maxtest): + a.mov(i+1, 'r0') + a.clr('r0') + a.halt() startaddr = 0o4000 self.loadphysmem(p, a, startaddr) @@ -1670,20 +1661,20 @@ class TestMethods(unittest.TestCase): p = PDP1170(logger=fnamebase, loglevel='DEBUG') # the point of this program is just to create N log # entries (when executed) that can be verified - with ASM() as a: - a.mov('r0', 'r0') - a.mov('r0', 'r1') - a.mov('r0', 'r2') - a.mov('r0', 'r3') - a.mov('r0', 'r4') - a.mov('r0', 'r5') - a.mov('r1', 'r0') - a.mov('r1', 'r1') - a.mov('r1', 'r2') - a.mov('r1', 'r3') - a.mov('r1', 'r4') - a.mov('r1', 'r5') - a.halt() + a = InstructionBlock() + a.mov('r0', 'r0') + a.mov('r0', 'r1') + a.mov('r0', 'r2') + a.mov('r0', 'r3') + a.mov('r0', 'r4') + a.mov('r0', 'r5') + a.mov('r1', 'r0') + a.mov('r1', 'r1') + a.mov('r1', 'r2') + a.mov('r1', 'r3') + a.mov('r1', 'r4') + a.mov('r1', 'r5') + a.halt() instloc = 0o4000 self.loadphysmem(p, a, instloc) @@ -1714,10 +1705,10 @@ class TestMethods(unittest.TestCase): startaddr = 0o4000 while curguess < maxguess: - with ASM() as a: - for i in range(curguess): - a.mov(i, 'r0') - a.halt() + a = InstructionBlock() + for i in range(curguess): + a.mov(i, 'r0') + a.halt() self.loadphysmem(p, a, startaddr) bp = BKP.Lookback() p.run(pc=startaddr, breakpoint=bp) @@ -1730,11 +1721,11 @@ class TestMethods(unittest.TestCase): curguess += 1 maxtest = default_lookbacks + 1 - with ASM() as a: - for i in range(maxtest): - a.mov(i, 'r0') - a.clr('r0') - a.halt() + a = InstructionBlock() + for i in range(maxtest): + a.mov(i, 'r0') + a.clr('r0') + a.halt() for i in range(maxtest): bp = BKP.Lookback(BKP.StepsBreakpoint(steps=i+1)) @@ -1750,36 +1741,36 @@ class TestMethods(unittest.TestCase): self.assertEqual(len(bp7.states), min(i+1, 7)) def test_jmp(self): - """In many ways more of a test of ASM module labels...""" + """In many ways more of a test of InstructionBlock labels...""" p = self.make_pdp() - with ASM() as a: - a.clr('r0') - a.clr('r1') - a.clr('r2') - a.jmp('X2') + a = InstructionBlock() + a.clr('r0') + a.clr('r1') + a.clr('r2') + a.jmp('X2') - a.label('X0') - a.inc('r0') - a.add(2, 'r1') - a.add(3, 'r2') - a.jmp('X1') + a.label('X0') + a.inc('r0') + a.add(2, 'r1') + a.add(3, 'r2') + a.jmp('X1') - # never executed - a.clr('r0') - a.clr('r1') - a.clr('r2') + # never executed + a.clr('r0') + a.clr('r1') + a.clr('r2') - a.label('X1') - a.inc('r1') - a.add('r1', 'r2') - a.add('r2', 'r0') - a.halt() - - a.label('X2') - a.inc('r2') - a.jmp('X0') - a.halt() + a.label('X1') + a.inc('r1') + a.add('r1', 'r2') + a.add('r2', 'r0') + a.halt() + + a.label('X2') + a.inc('r2') + a.jmp('X0') + a.halt() print("\n") print(list(map(oct, a))) @@ -1799,8 +1790,8 @@ class TestMethods(unittest.TestCase): are called 'co-routines.' """ p = self.make_pdp() - with ASM() as a: - pass + a = InstructionBlock() + # XXX TBD XXX def test_ubmap(self): p = self.make_pdp() @@ -1849,11 +1840,11 @@ class TestMethods(unittest.TestCase): # this is the tiny kernel code used to set up and start # each iteration of the user mode timing code. It slightly # distorts the per-instruction overhead of course. C'est la vie. - with ASM() as k: - k.mov(0o20000, 'sp') # establish proper kernel stack - k.mov(0o140340, '-(sp)') # USER mode, no interrupts - k.mov(usermode_base, '-(sp)') # pc start for loop/USER code - k.rtt() # off to the races! + k = InstructionBlock() + k.mov(0o20000, 'sp') # establish proper kernel stack + k.mov(0o140340, '-(sp)') # USER mode, no interrupts + k.mov(usermode_base, '-(sp)') # pc start for loop/USER code + k.rtt() # off to the races! kloc = 0o4000 for a2, w in enumerate(k): @@ -1861,13 +1852,13 @@ class TestMethods(unittest.TestCase): # The test timing loop... 49 "inst" instructions # and an SOB for looping (so 50 overall instructions per loop) - with ASM() as a: - a.mov(loopcount, 'r4') - a.label('LOOP') - for i in range(49): - a.literal(inst) - a.sob('r4', 'LOOP') - a.halt() + a = InstructionBlock() + a.mov(loopcount, 'r4') + a.label('LOOP') + for i in range(49): + a.literal(inst) + a.sob('r4', 'LOOP') + a.halt() for a2, w in enumerate(a): p.physRW(user_physloc + (2 * a2), w)