more instructions
This commit is contained in:
parent
ea0f383121
commit
ed150822ad
1 changed files with 59 additions and 2 deletions
|
@ -148,7 +148,7 @@ class PDP11InstructionAssembler:
|
||||||
raise valerr() from None
|
raise valerr() from None
|
||||||
return [mode | (b6 & 0o07), idxval]
|
return [mode | (b6 & 0o07), idxval]
|
||||||
|
|
||||||
# no-op here, but overridden in _Sequence to track generated instructions
|
# gets overridden in InstructionBlock to track generated instructions
|
||||||
def _seqwords(self, seq):
|
def _seqwords(self, seq):
|
||||||
return seq
|
return seq
|
||||||
|
|
||||||
|
@ -184,15 +184,27 @@ class PDP11InstructionAssembler:
|
||||||
def cmp(self, src, dst):
|
def cmp(self, src, dst):
|
||||||
return self._2op(0o020000, src, dst)
|
return self._2op(0o020000, src, dst)
|
||||||
|
|
||||||
|
def bic(self, src, dst):
|
||||||
|
return self._2op(0o030000, src, dst)
|
||||||
|
|
||||||
def bic(self, src, dst):
|
def bic(self, src, dst):
|
||||||
return self._2op(0o040000, src, dst)
|
return self._2op(0o040000, src, dst)
|
||||||
|
|
||||||
|
def bis(self, src, dst):
|
||||||
|
return self._2op(0o050000, src, dst)
|
||||||
|
|
||||||
def add(self, src, dst):
|
def add(self, src, dst):
|
||||||
return self._2op(0o060000, src, dst)
|
return self._2op(0o060000, src, dst)
|
||||||
|
|
||||||
def sub(self, src, dst):
|
def sub(self, src, dst):
|
||||||
return self._2op(0o160000, src, dst)
|
return self._2op(0o160000, src, dst)
|
||||||
|
|
||||||
|
def jmp(self, dst):
|
||||||
|
return self._1op(0o000100, dst)
|
||||||
|
|
||||||
|
def br(self, offs):
|
||||||
|
return self.literal(0o000400 | (offs & 0o77))
|
||||||
|
|
||||||
def clr(self, dst):
|
def clr(self, dst):
|
||||||
return self._1op(0o005000, dst)
|
return self._1op(0o005000, dst)
|
||||||
|
|
||||||
|
@ -202,6 +214,18 @@ class PDP11InstructionAssembler:
|
||||||
def dec(self, dst):
|
def dec(self, dst):
|
||||||
return self._1op(0o005300, dst)
|
return self._1op(0o005300, dst)
|
||||||
|
|
||||||
|
def swab(self, dst):
|
||||||
|
return self._1op(0o000300, dst)
|
||||||
|
|
||||||
|
def ash(self, cnt, dst):
|
||||||
|
try:
|
||||||
|
return self.literal(0o072000 | dst << 6, cnt)
|
||||||
|
except TypeError:
|
||||||
|
dstb6, *dst_i = self.operand_parser(dst)
|
||||||
|
if dstb6 & 0o70:
|
||||||
|
raise ValueError("ash dst must be register direct")
|
||||||
|
return self.literal(0o072000 | dstb6 << 6, cnt)
|
||||||
|
|
||||||
def halt(self):
|
def halt(self):
|
||||||
return self.literal(0)
|
return self.literal(0)
|
||||||
|
|
||||||
|
@ -248,6 +272,8 @@ class PDP11InstructionAssembler:
|
||||||
# which, subject to opinion, may be notationally cleaner/clearer and also
|
# which, subject to opinion, may be notationally cleaner/clearer and also
|
||||||
# opens the possibility of if/for/etc full programming constructs as needed.
|
# opens the possibility of if/for/etc full programming constructs as needed.
|
||||||
#
|
#
|
||||||
|
# The context manager also supports bare-bones labels, helpful for branches
|
||||||
|
#
|
||||||
# A list of instructions in an InstructionBlock can be obtained at any
|
# A list of instructions in an InstructionBlock can be obtained at any
|
||||||
# time via: insts = a.instructions()
|
# time via: insts = a.instructions()
|
||||||
#
|
#
|
||||||
|
@ -294,10 +320,12 @@ class InstructionBlock(PDP11InstructionAssembler, AbstractContextManager):
|
||||||
except TypeError:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# perhaps it is a label
|
# perhaps it is a label ... by definition it has to be backwards if so
|
||||||
try:
|
try:
|
||||||
# +255 not 256 bcs the Bxx instruction itself
|
# +255 not 256 bcs the Bxx instruction itself
|
||||||
offs = self.labels[target] - len(self) + 255
|
offs = self.labels[target] - len(self) + 255
|
||||||
|
if offs < 128:
|
||||||
|
raise ValueError(f"branch target ('{target}') too far.")
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise ValueError(f"can't find branch target '{target}'")
|
raise ValueError(f"can't find branch target '{target}'")
|
||||||
|
|
||||||
|
@ -309,8 +337,37 @@ class InstructionBlock(PDP11InstructionAssembler, AbstractContextManager):
|
||||||
def bne(self, target):
|
def bne(self, target):
|
||||||
return self.literal(BRANCH_CODES['bne'] | self.bxx_offset(target))
|
return self.literal(BRANCH_CODES['bne'] | self.bxx_offset(target))
|
||||||
|
|
||||||
|
def blt(self, target):
|
||||||
|
return self.literal(BRANCH_CODES['blt'] | self.bxx_offset(target))
|
||||||
|
|
||||||
def beq(self, target):
|
def beq(self, target):
|
||||||
return self.literal(BRANCH_CODES['beq'] | self.bxx_offset(target))
|
return self.literal(BRANCH_CODES['beq'] | self.bxx_offset(target))
|
||||||
|
|
||||||
def instructions(self):
|
def instructions(self):
|
||||||
return self._instblock
|
return self._instblock
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
ASM = PDP11InstructionAssembler
|
||||||
|
|
||||||
|
class TestMethods(unittest.TestCase):
|
||||||
|
def test_bne_label_distance(self):
|
||||||
|
# this should just execute without any issue
|
||||||
|
for i in range(127):
|
||||||
|
with ASM() as a:
|
||||||
|
a.label('foo')
|
||||||
|
for _ in range(i):
|
||||||
|
a.mov('r0', 'r0')
|
||||||
|
a.bne('foo')
|
||||||
|
|
||||||
|
# but this should ValueError ... branch too far
|
||||||
|
with ASM() as a:
|
||||||
|
a.label('foo')
|
||||||
|
for _ in range(128):
|
||||||
|
a.mov('r0', 'r0')
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
a.bne('foo')
|
||||||
|
|
||||||
|
unittest.main()
|
||||||
|
|
Loading…
Add table
Reference in a new issue