more fwdref improvements, some more instrs

This commit is contained in:
Neil Webber 2023-11-01 09:15:57 -05:00
parent 1f196e1923
commit 7354007fe4

View file

@ -267,6 +267,16 @@ class PDP11InstructionAssembler:
def rti(self): def rti(self):
return self.literal(2) return self.literal(2)
def nop(self):
return self.literal(0o000240)
def clc(self):
"""Clear Carry"""
return self.literal(0o000241)
def wait(self):
return self.literal(1)
def mtpi(self, dst): def mtpi(self, dst):
return self._1op(0o006600, dst) return self._1op(0o006600, dst)
@ -290,10 +300,14 @@ class PDP11InstructionAssembler:
class FwdRef: class FwdRef:
"""Values determined by a not-yet-seen label() definition.""" """Values determined by a not-yet-seen label() definition."""
def __init__(self, name, block): def __init__(self, name, block, *, pcrel=False):
self.loc = len(block) self.loc = len(block)
self.name = name self.name = name
self.block = block self.block = block
if pcrel:
self.pcadj = (2 * self.loc) + 4
else:
self.pcadj = 0
block._fwdrefs[name].append(self) block._fwdrefs[name].append(self)
def __call__(self): def __call__(self):
@ -309,17 +323,14 @@ class FwdRef:
def __iter__(self): def __iter__(self):
return iter([0o27, self]) return iter([0o27, self])
def transform(self): def __repr__(self):
return self.block.getlabel(self.name) - (2 * self.loc) s = f"{self.__class__.__name__}<"
s += f"{str(self.name)}, block<len={len(self.block)}>"
s += f", loc={self.loc}>"
return s
class JumpTarget(FwdRef):
# when a label is used as a PC-relative offset in a Jump (or JSR)
# target, the PC is already advanced according to where the literal of
# forward reference occurs in the stream. This has to be adjusted for.
def transform(self): def transform(self):
return self.block._neg16( return self.block._neg16(self.block.getlabel(self.name) - self.pcadj)
self.block.getlabel(self.name) - (2 * (self.loc + 2)))
class BranchTarget(FwdRef): class BranchTarget(FwdRef):
@ -415,7 +426,12 @@ class InstructionBlock(PDP11InstructionAssembler):
raise raise
# falling through to here means it is a label or forward reference # falling through to here means it is a label or forward reference
return [0o27, self.getlabel(operand_token)] # IF it starts with '+' it means use PC-relative addr mode
# which will require some fussing around...
if operand_token[0] == '+':
return [0o67, self.getlabel(operand_token[1:], pcrel=True)]
else:
return [0o27, self.getlabel(operand_token)]
def __len__(self): def __len__(self):
"""Returns the length of the sequence in WORDS""" """Returns the length of the sequence in WORDS"""
@ -480,7 +496,7 @@ class InstructionBlock(PDP11InstructionAssembler):
return self._labels[name] return self._labels[name]
def getlabel(self, name, *, fwdfactory=FwdRef): def getlabel(self, name, *, fwdfactory=FwdRef, pcrel=False):
"""Return value (loc) of name, which may be a FwdRef object. """Return value (loc) of name, which may be a FwdRef object.
Label values are offsets relative to the start of the block. Label values are offsets relative to the start of the block.
@ -496,9 +512,13 @@ class InstructionBlock(PDP11InstructionAssembler):
forward references raise a TypeError forward references raise a TypeError
""" """
try: try:
return self._labels[name] x = self._labels[name]
except KeyError: except KeyError:
return fwdfactory(name=name, block=self) return fwdfactory(name=name, block=self, pcrel=pcrel)
else:
if pcrel:
x = self._neg16(x - (2 * (len(self) + 2)))
return x
@staticmethod @staticmethod
def _neg16(x): def _neg16(x):
@ -564,16 +584,9 @@ class InstructionBlock(PDP11InstructionAssembler):
# labels become operand mode 0o67 ... PC-relative w/offset # labels become operand mode 0o67 ... PC-relative w/offset
inst = 0o004067 | (self.register_parser(reg) << 6) inst = 0o004067 | (self.register_parser(reg) << 6)
x = self.getlabel(dst, fwdfactory=JumpTarget) offs = self.getlabel(dst, pcrel=True)
try:
offs = self._neg16(x - (2 * (len(self) + 2)))
except TypeError:
# forward reference will be patched later
offs = x
return self._seqwords([inst, offs]) return self._seqwords([inst, offs])
# override JMP to provide reference/label support (like branches)
def jmp(self, dst): def jmp(self, dst):
# anything not a label handled by the regular jmp method: # anything not a label handled by the regular jmp method:
if not self._allowable_label(dst): if not self._allowable_label(dst):
@ -581,14 +594,7 @@ class InstructionBlock(PDP11InstructionAssembler):
# labels become operand mode 0o67 ... PC-relative w/offset # labels become operand mode 0o67 ... PC-relative w/offset
inst = 0o000167 inst = 0o000167
x = self.getlabel(dst, fwdfactory=JumpTarget) return self._seqwords([inst, self.getlabel(dst, pcrel=True)])
try:
offs = self._neg16(x - (2 * (len(self) + 2)))
except TypeError:
# forward reference will be patched later
offs = x
return self._seqwords([inst, offs])
def sob(self, reg, target): def sob(self, reg, target):
# the register can be a naked integer 0 .. 5 or an 'r' string # the register can be a naked integer 0 .. 5 or an 'r' string