diff options
Diffstat (limited to 'bits.py')
| -rw-r--r-- | bits.py | 52 |
1 files changed, 51 insertions, 1 deletions
@@ -283,7 +283,7 @@ class LabelRef(WordBase): Bitfield(0xa, 8) """ if self.label not in labels: - raise ValueError("label '{}' unresolved".format(self.label)) + raise ValueError("undefined label '{}'".format(self.label)) value = labels[self.label] + self.offset @@ -404,3 +404,53 @@ def from_part(part): val = int(part[0]) size = part[1] return Bitfield(val, int(size)) + +global_slice = slice +ref_re = re.compile(r'^([^\[+-]+)(?:([+-]\d+))?$') +slice_re = re.compile(r'^\[(\d+):(\d+)]$') + +def ref(val, default_slice=None): + """ add a default slice spec to labels if missing. + + >>> ref(('label', 'imm12')) + LabelRef('label', 0, ('imm', 12), 11:0) + >>> ref(('label', 'imm12'), slice(12, 1)) + LabelRef('label', 0, ('imm', 12), 12:1) + >>> ref(('label-4', 'imm12'), slice(12, 1)) + LabelRef('label', -4, ('imm', 12), 12:1) + >>> ref(('label', 'imm12', '[14:3]'), slice(12, 1)) + LabelRef('label', 0, ('imm', 12), 14:3) + >>> ref(('label+4', 'imm12', '[14:3]'), slice(12, 1)) + LabelRef('label', 4, ('imm', 12), 14:3) + >>> ref(('label', 'imm12', '[14:3]'), slice(12, 1)) + LabelRef('label', 0, ('imm', 12), 14:3) + >>> ref(('label', 'imm12', '[31:0]'), slice(11, 0)) + Traceback (most recent call last): + ... + AssertionError: expected 12 bit slice, got label/imm12/[31:0] + """ + slice = None + if len(val) == 3: + label_offset, mode, slice = val + elif len(val) == 2: + label_offset, mode = val + else: + raise ValueError("expected label reference, got {}".format(val)) + + match = ref_re.match(label_offset) + assert match, ValueError("invalid label reference") + label, offset = match.group(1), int(match.group(2) or 0) + + if isinstance(slice, str): + match = slice_re.match(slice) + assert match, ValueError("invalid slice syntax") + a, b = match.groups() + slice = global_slice(int(a), int(b)) + + ref = LabelRef(label, offset, mode, slice or default_slice) + + if default_slice: + expected = default_slice.start - default_slice.stop + 1 + assert expected == ref.size, ValueError("expected {} bit slice, got {}".format(expected, ref)) + + return ref |
