MOAR branch support
This commit is contained in:
parent
e03efaffaa
commit
c6dcec323c
2 changed files with 32 additions and 18 deletions
|
@ -29,6 +29,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
from contextlib import AbstractContextManager
|
from contextlib import AbstractContextManager
|
||||||
|
from branches import BRANCH_CODES
|
||||||
|
|
||||||
|
|
||||||
class PDP11InstructionAssembler:
|
class PDP11InstructionAssembler:
|
||||||
|
@ -276,28 +277,40 @@ class InstructionBlock(PDP11InstructionAssembler, AbstractContextManager):
|
||||||
return curoffs
|
return curoffs
|
||||||
|
|
||||||
# Branch instruction support only exists within a given InstructionBlock
|
# Branch instruction support only exists within a given InstructionBlock
|
||||||
def bxx_offset(self, name1, name2=None):
|
def bxx_offset(self, target, /):
|
||||||
"""Generate offset appropriate to Bxx between name1 and name2.
|
"""Generate offset for Bxx target
|
||||||
|
|
||||||
If name2 is None, generate offset, backwards, from current to name1.
|
A target can be a string label or a number. Numbers are taken as-is.
|
||||||
|
Names are looked up in the labels and offsets generated.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# XXX TODO XXX make forward references possible and automate the
|
# XXX TODO XXX make forward references possible and automate the
|
||||||
# backpatching even if that gets one step closer
|
# backpatching even if that gets one step closer
|
||||||
# to slowly implementing an entire assembler...
|
# to slowly implementing an entire assembler...
|
||||||
if name2 is None:
|
try:
|
||||||
# +255 not 256 because account for the Bxx instruction itself
|
if (target & 0o377) != target:
|
||||||
offs = self.labels[name1] - len(self) + 255
|
raise ValueError(f"branch target ({target}) too far")
|
||||||
else:
|
return target
|
||||||
raise ValueError("two name bxx_offset not yet implemented")
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
offs8 = offs & 0o377
|
# perhaps it is a label
|
||||||
if offs8 != offs:
|
try:
|
||||||
raise ValueError(f"distance to {name1} too far.")
|
# +255 not 256 bcs the Bxx instruction itself
|
||||||
return offs8
|
offs = self.labels[target] - len(self) + 255
|
||||||
|
except KeyError:
|
||||||
|
raise ValueError(f"can't find branch target '{target}'")
|
||||||
|
|
||||||
def bne(self, name):
|
if offs >= 0 and offs < 256:
|
||||||
return self.literal(0o001000 | self.bxx_offset(name))
|
return offs
|
||||||
|
|
||||||
|
raise ValueError(f"branch target ('{target}') too far.")
|
||||||
|
|
||||||
|
def bne(self, target):
|
||||||
|
return self.literal(BRANCH_CODES['bne'] | self.bxx_offset(target))
|
||||||
|
|
||||||
|
def beq(self, target):
|
||||||
|
return self.literal(BRANCH_CODES['beq'] | self.bxx_offset(target))
|
||||||
|
|
||||||
def instructions(self):
|
def instructions(self):
|
||||||
return self._instblock
|
return self._instblock
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
|
|
||||||
from machine import PDP1170
|
from machine import PDP1170
|
||||||
|
from branches import BRANCH_CODES
|
||||||
from pdptraps import PDPTraps
|
from pdptraps import PDPTraps
|
||||||
import unittest
|
import unittest
|
||||||
import random
|
import random
|
||||||
|
@ -331,10 +332,10 @@ class TestMethods(unittest.TestCase):
|
||||||
with ASM() as a:
|
with ASM() as a:
|
||||||
a.clr('r1') # if successful r1 will become goodval
|
a.clr('r1') # if successful r1 will become goodval
|
||||||
a.clr('r0')
|
a.clr('r0')
|
||||||
a.literal(0o101401) # BEQ +1
|
a.beq(+1)
|
||||||
a.halt() # stop here if BEQ fails
|
a.halt() # stop here if BEQ fails
|
||||||
a.literal(0o000257) # 1f: CCC .. clear all the condition codes
|
a.literal(0o000257) # 1f: CCC .. clear all the condition codes
|
||||||
a.literal(0o001001) # BNE +1
|
a.bne(+1)
|
||||||
a.halt() # stop here if BNE fails
|
a.halt() # stop here if BNE fails
|
||||||
a.mov(goodval, 'r1') # indicate success
|
a.mov(goodval, 'r1') # indicate success
|
||||||
a.halt()
|
a.halt()
|
||||||
|
@ -386,7 +387,7 @@ class TestMethods(unittest.TestCase):
|
||||||
# various condition code tests
|
# various condition code tests
|
||||||
p = self.make_pdp()
|
p = self.make_pdp()
|
||||||
|
|
||||||
insts = self._cc_unscc(0o3400, 0o3000)
|
insts = self._cc_unscc(BRANCH_CODES['blt'], BRANCH_CODES['bgt'])
|
||||||
|
|
||||||
instloc = 0o4000
|
instloc = 0o4000
|
||||||
self.loadphysmem(p, insts, instloc)
|
self.loadphysmem(p, insts, instloc)
|
||||||
|
@ -423,7 +424,7 @@ class TestMethods(unittest.TestCase):
|
||||||
# more stuff like test_cc but specifically testing unsigned Bxx codes
|
# more stuff like test_cc but specifically testing unsigned Bxx codes
|
||||||
p = self.make_pdp()
|
p = self.make_pdp()
|
||||||
|
|
||||||
insts = self._cc_unscc(0o103400, 0o101000)
|
insts = self._cc_unscc(BRANCH_CODES['blo'], BRANCH_CODES['bhi'])
|
||||||
instloc = 0o4000
|
instloc = 0o4000
|
||||||
self.loadphysmem(p, insts, instloc)
|
self.loadphysmem(p, insts, instloc)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue