fixed up (again, maybe right this time) pcrel stuff in getlabel

This commit is contained in:
Neil Webber 2023-11-01 10:22:27 -05:00
parent 111347faa2
commit 2f17117c02

View file

@ -300,14 +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, *, pcrel=False): def __init__(self, name, block, *, idxrel=False, idxadj=0):
self.loc = len(block) self.loc = len(block)
self.name = name self.name = name
self.block = block self.block = block
if pcrel: if idxrel:
self.pcadj = (2 * self.loc) + 4 self.adjust = (2 * self.loc) + idxadj
else: else:
self.pcadj = 0 self.adjust = 0
block._fwdrefs[name].append(self) block._fwdrefs[name].append(self)
def __call__(self): def __call__(self):
@ -330,7 +330,7 @@ class FwdRef:
return s return s
def transform(self): def transform(self):
return self.block._neg16(self.block.getlabel(self.name) - self.pcadj) return self.block._neg16(self.block.getlabel(self.name) - self.adjust)
class BranchTarget(FwdRef): class BranchTarget(FwdRef):
@ -429,7 +429,7 @@ class InstructionBlock(PDP11InstructionAssembler):
# IF it starts with '+' it means use PC-relative addr mode # IF it starts with '+' it means use PC-relative addr mode
# which will require some fussing around... # which will require some fussing around...
if operand_token[0] == '+': if operand_token[0] == '+':
return [0o67, self.getlabel(operand_token[1:], pcrel=True)] return [0o67, self.getlabel(operand_token[1:], idxrel=True, idxadj=4)]
else: else:
return [0o27, self.getlabel(operand_token)] return [0o27, self.getlabel(operand_token)]
@ -496,7 +496,7 @@ class InstructionBlock(PDP11InstructionAssembler):
return self._labels[name] return self._labels[name]
def getlabel(self, name, *, fwdfactory=FwdRef, pcrel=False): def getlabel(self, name, *, fwdfactory=FwdRef, idxrel=False, idxadj=0):
"""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.
@ -514,10 +514,11 @@ class InstructionBlock(PDP11InstructionAssembler):
try: try:
x = self._labels[name] x = self._labels[name]
except KeyError: except KeyError:
return fwdfactory(name=name, block=self, pcrel=pcrel) return fwdfactory(name=name, block=self,
idxrel=idxrel, idxadj=idxadj)
else: else:
if pcrel: if idxrel:
x = self._neg16(x - (2 * (len(self) + 2))) x = self._neg16(x - ((2 * len(self)) + idxadj))
return x return x
@staticmethod @staticmethod
@ -584,7 +585,7 @@ 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)
offs = self.getlabel(dst, pcrel=True) offs = self.getlabel(dst, idxrel=True, idxadj=4)
return self._seqwords([inst, offs]) return self._seqwords([inst, offs])
def jmp(self, dst): def jmp(self, dst):
@ -594,7 +595,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
return self._seqwords([inst, self.getlabel(dst, pcrel=True)]) return self._seqwords([inst, self.getlabel(dst, idxrel=True, idxadj=4)])
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
@ -642,6 +643,9 @@ class InstructionBlock(PDP11InstructionAssembler):
f.write(f"D PC {oct(startaddr)[2:]}\n") f.write(f"D PC {oct(startaddr)[2:]}\n")
if __name__ == "__main__": if __name__ == "__main__":
import unittest import unittest
@ -677,6 +681,7 @@ if __name__ == "__main__":
insts = list(a) insts = list(a)
self.assertEqual(list(a), [0o012700, 6, 0o005001, 0o012701, 6]) self.assertEqual(list(a), [0o012700, 6, 0o005001, 0o012701, 6])
def test_labelmath_dot(self): def test_labelmath_dot(self):
a = InstructionBlock() a = InstructionBlock()
a.mov('bozo', 'r0') a.mov('bozo', 'r0')