aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2021-07-05 10:35:01 +0000
committers-ol <s+removethis@s-ol.nu>2021-07-05 10:35:01 +0000
commit218a4f2f7286042d7462ed9329f1b5b623662308 (patch)
tree6434b21ebd554e05a069b0e99f833b9a1289e77b
parentadd validate layer (diff)
downloadsubv-218a4f2f7286042d7462ed9329f1b5b623662308.tar.gz
subv-218a4f2f7286042d7462ed9329f1b5b623662308.zip
update survey for new stage order
-rw-r--r--subv.py50
-rwxr-xr-xsurvey.py209
2 files changed, 142 insertions, 117 deletions
diff --git a/subv.py b/subv.py
index 3e768a1..8a9b1d1 100644
--- a/subv.py
+++ b/subv.py
@@ -4,8 +4,8 @@ import bits
white = re.compile(r"[ \t\.\n]+")
hex = re.compile(r"^\-?(0x)?[0-9a-f]+$")
num = re.compile(r"^\d+$")
-ref_re = re.compile(r"^([^\[+-]+)(?:([+-]\d+))?(?:\[(\d+):(\d+)\])?$")
-field_re = re.compile(r"^(imm|off)(\d+)$")
+ref_re = re.compile(r"^([^\[+-]+)(?:([+-]\d+))?$")
+field_re = re.compile(r"^(imm|off)(\d+)(hi|lo)?$")
# parsing
def parse_part(part):
@@ -95,39 +95,31 @@ def parse_reference(part):
"""parse a sliced-label 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}
-
+ {'label': 'lbl', 'mode': 'imm', 'size': 32, offset: 0}
+ >>> parse_reference(('lbl+0', 'off32'))
+ {'label': 'lbl', 'mode': 'off', 'size': 32, '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}
+ {'label': 'lbl', 'mode': 'imm', 'size': 32, 'offset': 2}
+ >>> parse_reference(('lbl+2', 'off20hi'))
+ {'label': 'lbl', 'mode': 'off', 'size': 20, 'offset': 2, 'split': 'hi'}
+ >>> parse_reference(('lbl+2', 'off12lo'))
+ {'label': 'lbl', 'mode': 'off', 'size': 12, 'offset': 2, 'split': 'lo'}
"""
ref = part[0]
field = part[1]
- label, off, hi, lo = ref_re.match(ref).groups()
- mode, size = field_re.match(field).groups()
+ label, off = ref_re.match(ref).groups()
+ mode, size, split = field_re.match(field).groups()
ref = {
"label": label,
"mode": mode,
"size": int(size),
- "meta": part[2:],
+ "offset": int(off or 0),
}
- if off is not None:
- ref["offset"] = int(off)
-
- if hi is not None:
- ref["hi"] = int(hi)
- ref["lo"] = int(lo)
+ if split is not None:
+ ref["split"] = split
return ref
@@ -292,9 +284,9 @@ def format_part(part):
"""opposite of parse_part.
>>> format_part((0,))
- '00'
+ '0'
>>> format_part((0x00,))
- '00'
+ '0'
>>> format_part((16,))
'10'
>>> format_part((0x10,))
@@ -322,10 +314,10 @@ def format(line):
>>> format({
... 'type': 'instr',
- ... 'instr': [(255, 'op'), (0, 'subop', 'add'), (1, 'rd', 'x1'), ('label[11:0]', 'imm12')],
+ ... 'instr': [(255, 'op'), (0, 'subop', 'add'), (1, 'rd', 'x1'), ('label', 'imm12')],
... 'comment': "this does things."
... })
- 'ff/op 00/subop/add 01/rd/x1 label[11:0]/imm12 # this does things.'
+ 'ff/op 0/subop/add 1/rd/x1 label/imm12 # this does things.'
"""
type = line["type"]
if type == "instr" or type == "data":
@@ -342,10 +334,10 @@ def dump(line):
>>> dump({
... 'type': 'instr',
- ... 'instr': [(255, 'op'), (0, 'subop', 'add'), (1, 'rd', 'x1'), ('label[11:0]', 'imm12')],
+ ... 'instr': [(255, 'op'), (0, 'subop', 'add'), (1, 'rd', 'x1'), ('label', 'imm12')],
... 'comment': "this does things."
... })
- "instr[(255, 'op'), (0, 'subop', 'add'), (1, 'rd', 'x1'), ('label[11:0]', 'imm12')]"
+ "instr[(255, 'op'), (0, 'subop', 'add'), (1, 'rd', 'x1'), ('label', 'imm12')]"
"""
return "{}{}".format(line["type"], line[line["type"]])
diff --git a/survey.py b/survey.py
index 37f9759..5f195f5 100755
--- a/survey.py
+++ b/survey.py
@@ -8,52 +8,52 @@ Resolves label references and substitutes them with literal values.
... == code 0x80000000
... main:
... # load 0x10010000 (UART0) into t0
-... 37/7 05/5 10010/20
+... 37/u 5/rd 10010/imm20
... # store 0x48 (H) in UART0+0
-... 13/7 06/5 0/3 00/5 048/12
-... 23/7 00/5 2/3 05/5 06/5 00/7
+... 13/i 6/rd 0/funct3 0/rs 48/imm12
+... 23/s 5/rs1 0/off12 2/funct3 6/rs2
... # store 0x65 (e) in UART0+0
-... 13/7 06/5 0/3 00/5 065/12
-... 23/7 00/5 2/3 05/5 06/5 00/7
+... 13/i 6/rd 0/funct3 0/rs 65/imm12
+... 23/s 5/rs1 0/off12 2/funct3 6/rs2
... # store 0x6c (l) in UART0+0
-... 13/7 06/5 0/3 00/5 06c/12
-... 23/7 00/5 2/3 05/5 06/5 00/7
+... 13/i 6/rd 0/funct3 0/rs 6c/imm12
+... 23/s 5/rs1 0/off12 2/funct3 6/rs2
... # store 0x6c (l) in UART0+0
-... 13/7 06/5 0/3 00/5 06c/12
-... 23/7 00/5 2/3 05/5 06/5 00/7
+... 13/i 6/rd 0/funct3 0/rs 6c/imm12
+... 23/s 5/rs1 0/off12 2/funct3 6/rs2
... # store 0x6f (o) in UART0+0
-... 13/7 06/5 0/3 00/5 06f/12
-... 23/7 00/5 2/3 05/5 06/5 00/7
+... 13/i 6/rd 0/funct3 0/rs 6f/imm12
+... 23/s 5/rs1 0/off12 2/funct3 6/rs2
... # store 0x0a (\\\\n) in UART0+0
-... 13/7 06/5 0/3 00/5 00a/12
-... 23/7 00/5 2/3 05/5 06/5 00/7
+... 13/i 6/rd 0/funct3 0/rs a/imm12
+... 23/s 5/rs1 0/off12 2/funct3 6/rs2
... # jump back up to the top
-... 6f/7 00/5 main/off21/[19:12] main/off21/[11:11] main/off21/[10:1] main/off21/[20:20]
+... 6f/j 0/rd main/off21
... '''[1:-1]))))
== code 0x80000000
# main:
# load 0x10010000 (UART0) into t0
-37/7 05/5 10010/20
+37/u 5/rd 10010/imm20
# store 0x48 (H) in UART0+0
-13/7 06/5 00/3 00/5 48/12
-23/7 00/5 02/3 05/5 06/5 00/7
+13/i 6/rd 0/funct3 0/rs 48/imm12
+23/s 5/rs1 0/off12 2/funct3 6/rs2
# store 0x65 (e) in UART0+0
-13/7 06/5 00/3 00/5 65/12
-23/7 00/5 02/3 05/5 06/5 00/7
+13/i 6/rd 0/funct3 0/rs 65/imm12
+23/s 5/rs1 0/off12 2/funct3 6/rs2
# store 0x6c (l) in UART0+0
-13/7 06/5 00/3 00/5 6c/12
-23/7 00/5 02/3 05/5 06/5 00/7
+13/i 6/rd 0/funct3 0/rs 6c/imm12
+23/s 5/rs1 0/off12 2/funct3 6/rs2
# store 0x6c (l) in UART0+0
-13/7 06/5 00/3 00/5 6c/12
-23/7 00/5 02/3 05/5 06/5 00/7
+13/i 6/rd 0/funct3 0/rs 6c/imm12
+23/s 5/rs1 0/off12 2/funct3 6/rs2
# store 0x6f (o) in UART0+0
-13/7 06/5 00/3 00/5 6f/12
-23/7 00/5 02/3 05/5 06/5 00/7
+13/i 6/rd 0/funct3 0/rs 6f/imm12
+23/s 5/rs1 0/off12 2/funct3 6/rs2
# store 0x0a (\\n) in UART0+0
-13/7 06/5 00/3 00/5 0a/12
-23/7 00/5 02/3 05/5 06/5 00/7
+13/i 6/rd 0/funct3 0/rs a/imm12
+23/s 5/rs1 0/off12 2/funct3 6/rs2
# jump back up to the top
-6f/7 00/5 ff/8 1/1 3e6/10 1/1
+6f/j 0/rd -34/off21
>>> # doctest: +REPORT_NDIFF
... print(subv.join_all(survey(StringIO('''
@@ -61,37 +61,35 @@ Resolves label references and substitutes them with literal values.
... # repeatedly print "Hi\\\\n"
... main:
... # load 0x10010000 (UART0) into t0
-... 37/7 05/5 10010/20
+... 37/u 5/rd/t0 0x10010/imm20
... # store 0x48 (H) in UART0+0
-... 13/7 06/5 0/3 00/5 048/12
-... 23/7 00/5 2/3 05/5 06/5 00/7
+... 13/i 0/subop/add 6/rd/t1 0/rs/x0 48/imm12
+... 23/s 2/subop/word 5/rs/t0 6/rs/t1 0/off12
... # store 0x69 (i) in UART0+0
-... 13/7 06/5 0/3 00/5 069/12
-... 23/7 00/5 2/3 05/5 06/5 00/7
+... 13/i 0/subop/add 6/rd/t1 0/rs/x0 69/imm12
+... 23/s 2/subop/word 5/rs/t0 6/rs/t1 0/off12
... # store 0x0a (\\\\n) in UART0+0
-... 13/7 06/5 0/3 00/5 00a/12
-... 23/7 00/5 2/3 05/5 06/5 00/7
-... # jump back up to the top
-... 17/7 07/5 main/off32/[31:12]
-... 67/7 00/5 0/3 07/5 main+4/off32/[11:0]
+... 13/i 0/subop/add 6/rd/t1 0/rs/x0 0a/imm12
+... 23/s 2/subop/word 5/rs/t0 6/rs/t1 0/off12
+... 17/u 7/rd/t2 main/off20hi
+... 67/i 0/subop 0/rd/x0 7/rs/t2 main+4/off12lo
... '''[1:-1]))))
== code 0x80000000
# repeatedly print "Hi\\n"
# main:
# load 0x10010000 (UART0) into t0
-37/7 05/5 10010/20
+37/u 5/rd/t0 10010/imm20
# store 0x48 (H) in UART0+0
-13/7 06/5 00/3 00/5 48/12
-23/7 00/5 02/3 05/5 06/5 00/7
+13/i 0/subop/add 6/rd/t1 0/rs/x0 48/imm12
+23/s 2/subop/word 5/rs/t0 6/rs/t1 0/off12
# store 0x69 (i) in UART0+0
-13/7 06/5 00/3 00/5 69/12
-23/7 00/5 02/3 05/5 06/5 00/7
+13/i 0/subop/add 6/rd/t1 0/rs/x0 69/imm12
+23/s 2/subop/word 5/rs/t0 6/rs/t1 0/off12
# store 0x0a (\\n) in UART0+0
-13/7 06/5 00/3 00/5 0a/12
-23/7 00/5 02/3 05/5 06/5 00/7
-# jump back up to the top
-17/7 07/5 00000/20
-67/7 00/5 00/3 07/5 fe4/12
+13/i 0/subop/add 6/rd/t1 0/rs/x0 a/imm12
+23/s 2/subop/word 5/rs/t0 6/rs/t1 0/off12
+17/u 7/rd/t2 0/off20
+67/i 0/subop 0/rd/x0 7/rs/t2 -1c/off12
"""
import subv
import bits
@@ -102,33 +100,78 @@ def observe(word, pc, map):
>>> observe((3, '3'), 0, {})
(3, '3')
- >>> observe(('label', 'imm32', '[31:0]'), 0, {'label': 0x1234})
- Bitfield(0x1234, 32)
- >>> observe(('label-2', 'imm32', '[31:0]'), 0, {'label': 0x1234})
- Bitfield(0x1232, 32)
- >>> observe(('label', 'imm32', '[1:0]'), 0, {'label': 0x1236})
- Bitfield(0x2, 2)
- >>> observe(('label', 'off32', '[31:0]'), 0x1000, {'label': 0x1234})
- Bitfield(0x234, 32)
- >>> observe(('label', 'off32', '[31:12]'), 0x1000, {'label': 0x10fff})
- Bitfield(0xf, 20)
- >>> observe(('label', 'off32', '[31:0]'), 0x2000, {'label': 0x1000})
- Bitfield(0xfffff000, 32)
- >>> observe(('label+4', 'off32', '[7:0]'), 0x1000, {'label': 0x1234})
- Bitfield(0x38, 8)
- >>> observe(('label+4', 'off32', '[15:8]'), 0x1000, {'label': 0x1234})
- Bitfield(0x2, 8)
-
- >>> observe(('label', 'imm32', '[32:0]'), 0, {})
+ >>> subv.format_part(observe(('label', 'imm32'), 0, {'label': 0x1234}))
+ '1234/imm32'
+ >>> subv.format_part(observe(('label-2', 'imm20',), 0, {'label': 0x1234}))
+ '1232/imm20'
+ >>> subv.format_part(observe(('label', 'off32'), 0x1000, {'label': 0x1234}))
+ '234/off32'
+ >>> subv.format_part(observe(('label+4', 'off32'), 0x1000, {'label': 0x1234}))
+ '238/off32'
+ >>> subv.format_part(observe(('label', 'off32'), 0x1234, {'label': 0x1000}))
+ '-234/off32'
+ >>> subv.format_part(observe(('label', 'off20hi'), 0x1000, {'label': 0x3234}))
+ '2/off20'
+ >>> subv.format_part(observe(('label', 'off12lo'), 0x1000, {'label': 0x3234}))
+ '234/off12'
+ >>> subv.format_part(observe(('label', 'off20hi'), 0x3234, {'label': 0x1000}))
+ '-2/off20'
+ >>> subv.format_part(observe(('label', 'off12lo'), 0x3234, {'label': 0x1000}))
+ '-234/off12'
+
+ >>> observe(('label', 'imm32'), 0, {})
Traceback (most recent call last):
...
ValueError: undefined label 'label'
+ >>> observe(('label', 'imm8'), 0, {'label': 0x1234})
+ Traceback (most recent call last):
+ ...
+ ValueError: label reference out of range (8 bit): 'label' (0x1234)
"""
if not subv.is_reference(word):
return word
- word = bits.ref(word)
- return word.as_value(pc=pc, labels=map)
+ ref = subv.parse_reference(word)
+
+ if ref["label"] not in map:
+ raise ValueError("undefined label '{}'".format(ref["label"]))
+
+ value = map[ref["label"]] + ref["offset"]
+
+ if ref["mode"] == "off":
+ value -= pc
+
+ if "split" in ref:
+ sgn = -1 if value < 0 else 1
+ value *= sgn
+
+ if ref["split"] == "hi" and ref["size"] == 20:
+ value = value >> 12
+ elif ref["split"] == "lo" and ref["size"] == 12:
+ value = value & 0xFFF
+ else:
+ raise ValueError(
+ "unknown label split mode {mode}{size}{split}".format(**ref)
+ )
+
+ value *= sgn
+
+ if value > 0:
+ if value >= (1 << ref["size"]):
+ raise ValueError(
+ "label reference out of range ({size} bit): '{label}' (0x{:x})".format(
+ value, **ref
+ )
+ )
+ else:
+ if value < -(1 << (ref["size"] - 1)):
+ raise ValueError(
+ "label reference out of range ({size} bit): '{label}' (-0x{:x})".format(
+ abs(value), **ref
+ )
+ )
+
+ return (value, "{mode}{size}".format(**ref))
@subv.with_parsed_lines
@@ -148,6 +191,9 @@ def survey(iter):
assert bitcount == 0, "label isn't byte aligned"
map[line["label"]] = addr
elif type == "instr":
+ if len(line["instr"]) == 0:
+ continue
+
if segment == "data":
for part in line["instr"]:
bitcount += int(part[1])
@@ -163,19 +209,12 @@ def survey(iter):
)
assert addr % 2 == 0, "instruction isn't 2-byte aligned"
- bitcount = 0
- for part in line["instr"]:
- if subv.is_reference(part):
- ref = bits.ref(part)
- bitcount += ref.size
- else:
- bitcount += int(part[1])
-
- assert (
- bitcount % 8 == 0
- ), "instruction size not multiple of 8 bitcount: {}".format(bitcount)
- addr += bitcount // 8
- bitcount = 0
+ op = line["instr"][0]
+ instr_size = 0
+ if op[1] in "usirjb":
+ addr += 4
+ else:
+ raise ValueError("Unknown instruction format '{}'".format(op[1]))
else:
raise ValueError("unknown segment '{}'".format(segment))
@@ -184,14 +223,8 @@ def survey(iter):
type = line["type"]
if type == "instr":
instr = []
- if type == "instr":
- # strip label from opcode
- op = line[type].pop(0)
- instr.append(op[:2])
-
for part in line[type]:
- observed = observe(part, line["addr"], map)
- instr.append(observed)
+ instr.append(observe(part, line["addr"], map))
line[type] = instr
yield subv.format(line)
elif type == "label":