aboutsummaryrefslogtreecommitdiffstats
path: root/subv.py
diff options
context:
space:
mode:
Diffstat (limited to 'subv.py')
-rw-r--r--subv.py45
1 files changed, 43 insertions, 2 deletions
diff --git a/subv.py b/subv.py
index fae4a3e..4f38988 100644
--- a/subv.py
+++ b/subv.py
@@ -2,7 +2,7 @@ import re
white = re.compile(r'[ \t\.\n]+')
hex = re.compile(r'^\-?(0x)?[0-9a-f]+$')
num = re.compile(r'^\d+$')
-slice_re = re.compile(r'^([^\[]+)(?:\[(\d+):(\d+)\])?$')
+ref_re = re.compile(r'^([^\[+-]+)(?:([+-]\d+))?(?:\[(\d+):(\d+)\])?$')
field_re = re.compile(r'^(imm|off)(\d+)$')
# parsing
@@ -91,13 +91,22 @@ def parse_reference(part):
>>> parse_reference(('lbl', 'imm32'))
{'label': 'lbl', 'mode': 'imm', 'size': 32, 'meta': ()}
+ >>> parse_reference(('lbl+0', 'imm32'))
+ {'label': 'lbl', 'mode': 'imm', 'size': 32, 'meta': (), 'offset': 0}
+
+ >>> parse_reference(('lbl+2', 'imm32'))
+ {'label': 'lbl', 'mode': 'imm', 'size': 32, 'meta': (), 'offset': 2}
+
>>> parse_reference(('x[11:0]', 'off12'))
{'label': 'x', 'mode': 'off', 'size': 12, 'meta': (), 'hi': 11, 'lo': 0}
+
+ >>> parse_reference(('x-16[11:0]', 'off12'))
+ {'label': 'x', 'mode': 'off', 'size': 12, 'meta': (), 'offset': -16, 'hi': 11, 'lo': 0}
"""
ref = part[0]
field = part[1]
- label, hi, lo = slice_re.match(ref).groups()
+ label, off, hi, lo = ref_re.match(ref).groups()
mode, size = field_re.match(field).groups()
ref = {
@@ -107,6 +116,9 @@ def parse_reference(part):
'meta': part[2:],
}
+ if off is not None:
+ ref['offset'] = int(off)
+
if hi is not None:
ref['hi'] = int(hi)
ref['lo'] = int(lo)
@@ -177,12 +189,18 @@ def is_reference(part):
True
>>> is_reference(('hello:world',))
True
+ >>> is_reference(('hello-4',))
+ True
+ >>> is_reference(('hello[11:0]',))
+ True
>>> is_reference(('$label',))
True
>>> is_reference(('$label:extra',))
True
>>> is_reference(('$label:extra', 'off20'))
True
+ >>> is_reference(('$label+3[31:12]', 'off20'))
+ True
>>> is_reference(('plain', 'off20'))
True
@@ -225,6 +243,29 @@ def untag(part, expect=None):
raise ValueError("expected {} to be labelled {}".format(part, expect))
return part[0]
+def format_reference(ref):
+ """ opposite of parse_reference..
+
+ >>> format_reference({'label': 'lbl', 'mode': 'imm', 'size': 32, 'meta': ()})
+ ('lbl', 'imm32')
+ >>> format_reference({'label': 'lbl', 'offset': 0, 'mode': 'imm', 'size': 32, 'meta': ()})
+ ('lbl+0', 'imm32')
+ >>> format_reference({'label': 'lbl', 'offset': 2, 'mode': 'imm', 'size': 32, 'meta': ()})
+ ('lbl+2', 'imm32')
+ >>> format_reference({'label': 'x', 'mode': 'off', 'size': 12, 'meta': (), 'hi': 11, 'lo': 0})
+ ('x[11:0]', 'off12')
+ >>> format_reference({'label': 'x', 'offset': -16, 'mode': 'off', 'size': 12, 'meta': (), 'hi': 11, 'lo': 0})
+ ('x-16[11:0]', 'off12')
+ >>> format_reference({'label': 'x', 'offset': -16, 'mode': 'off', 'size': 12, 'meta': ('extra', 'stuff'), 'hi': 11, 'lo': 0})
+ ('x-16[11:0]', 'off12', 'extra', 'stuff')
+ """
+ label = ref['label']
+ if 'offset' in ref:
+ label += '{:+}'.format(ref['offset'])
+ if 'hi' in ref:
+ label += '[{hi}:{lo}]'.format(**ref)
+ return (label, '{mode}{size}'.format(**ref), *ref['meta'])
+
def format_part(part):
""" opposite of parse_part.