diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-05-28 15:22:11 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-05-28 15:22:11 +0000 |
| commit | 51091f7355a89aab6347523f3e3e53ed328b4dfc (patch) | |
| tree | c3a11ca809ba075a8e2b37c217c6ed6278905ff2 | |
| parent | tests, cleanup, verify.py (diff) | |
| download | subv-51091f7355a89aab6347523f3e3e53ed328b4dfc.tar.gz subv-51091f7355a89aab6347523f3e3e53ed328b4dfc.zip | |
survey, pack
| -rw-r--r-- | README.md | 10 | ||||
| -rw-r--r-- | format.py | 254 | ||||
| -rw-r--r-- | pack.py | 74 | ||||
| -rw-r--r-- | riscv.py | 4 | ||||
| -rw-r--r-- | subx.py | 19 | ||||
| -rw-r--r-- | survey.py | 137 | ||||
| -rw-r--r-- | test.subv | 24 | ||||
| -rw-r--r-- | verify.py | 186 |
8 files changed, 516 insertions, 192 deletions
@@ -3,7 +3,7 @@ SubV This is a wip clone of [SubX][mu] for the RISC-V RV31I base ISA. - $ ./test.py | ./elf.py > out.elf + $ <label_test.subv ./format.py | ./survey.py | ./pack.py | ./elf.py > out.elf $ ./qemu.sh out.elf Pipeline @@ -11,8 +11,12 @@ Pipeline back to front: -- `elf`: takes `hex.subx`-style input, outputs an ELF file -- `survey`: +- `elf.py`: takes hex bytes and segment headers, outputs an ELF file +- `pack.py`: packs bitfields (`3/3 1/1 f/4`) into hex bytes (`fb`) +- `survey.py`: replaces label references by their addresses +- `format.py`: checks op-arguments and chops and orders arguments into ISA formats + +and now back to front with a little example: Debugging --------- diff --git a/format.py b/format.py new file mode 100644 index 0000000..b63a854 --- /dev/null +++ b/format.py @@ -0,0 +1,254 @@ +#!/usr/bin/env python3 +from subx import clean, classify, parse_segment, parse_instr, is_lref, untag, format_instr +from riscv import u, i, bit_concat, bit_slice + +instr_map = { + 'opr': ('r', 0x33), + 'load': ('i', 0x03), + 'opi': ('i', 0x13), + 'jalr': ('i', 0x67), + 'store': ('s', 0x23), + 'branch': ('b', 0x63), + 'lui': ('u', 0x37), + 'auipc': ('u', 0x17), + 'jal': ('j', 0x6f), +} + +def pack_u(instr): + (op, rd, imm) = instr + op = u(untag(op), 7) + rd = u(untag(rd, 'rd'), 5) + if not is_lref(imm): + imm = i(untag(imm, 'imm20'), 20) + + return [op, rd, imm] + +def pack_i(instr): + (op, sub, rd, rs, imm) = instr + op = u(untag(op), 7) + sub = u(untag(sub, 'subop'), 3) + rd = u(untag(rd, 'rd'), 5) + rs = u(untag(rs, 'rs'), 5) + if not is_lref(imm): + imm = i(untag(imm, 'imm12'), 12) + + return [op, rd, sub, rs, imm] + +def pack_s(instr): + (op, sub, rs1, rs2, imm) = instr + op = u(untag(op), 7) + sub = u(untag(sub, 'subop'), 3) + rs1 = u(untag(rs1, 'rs'), 5) + rs2 = u(untag(rs2, 'rs'), 5) + if not is_lref(imm): + imm = i(untag(imm, 'off12'), 12) + imm_lo = bit_slice(imm, 4, 0) + imm_hi = bit_slice(imm, 11, 5) + else: + label = untag(imm, 'off12') + imm_lo = (label, 5, 'off12') + imm_hi = (label, 7, 'off12>>5') + return [op, imm_lo, sub, rs1, rs2, imm_hi] + +def pack_j(instr): + (op, rd, imm) = instr + op = u(untag(op), 7) + rd = u(untag(rd, 'rd'), 5) + + if not is_lref(imm): + imm = i(untag(imm, 'off21'), 21) + if imm & 0b1 == 1: + raise ArgumentError("J-type offsets have to be halfword-aligned") + imm_lo = bit_slice(imm, 10, 1) + imm_11 = bit_slice(imm, 11, 11) + imm_hi = bit_slice(imm, 19, 12) + imm_20 = bit_slice(imm, 20, 20) + else: + label = untag(imm, 'off21') + imm_lo = (label, 10, 'off21>>1') + imm_11 = (label, 1, 'off21>>11') + imm_hi = (label, 8, 'off21>>12') + imm_20 = (label, 1, 'off21>>20') + + return [op, rd, imm_hi, imm_11, imm_lo, imm_20] + +def pack_b(instr): + (op, sub, rs1, rs2, imm) = instr + op = u(untag(op), 7) + sub = u(untag(sub, 'subop'), 3) + rs1 = u(untag(rs1, 'rs'), 5) + rs2 = u(untag(rs2, 'rs'), 5) + if not is_lref(imm): + imm = i(untag(imm, 'off13'), 13) + if imm & 0b1 == 1: + raise ArgumentError("B-type offsets have to be halfword-aligned") + imm_lo = bit_slice(imm, 4, 1) + imm_md = bit_slice(imm, 10, 5) + imm_11 = bit_slice(imm, 11, 11) + imm_12 = bit_slice(imm, 12, 12) + else: + label = untag(imm, 'off13') + imm_lo = (label, 4, 'off13>>1') + imm_md = (label, 6, 'off13>>5') + imm_11 = (label, 1, 'off13>>11') + imm_12 = (label, 1, 'off13>>12') + + return [op, imm_11, imm_lo, sub, rs1, rs2, imm_md, imm_12] + +def format(iter): + for line in iter: + line = clean(line) + if line == '': + continue + + type = classify(line) + + if type == 'segment' or type == 'label': + yield line + else: + instr = parse_instr(line) + op = instr[0] + if len(op) != 2: + raise ValueError("instruction without op label") + + (op, label) = op + if label not in instr_map: + raise ValueError("unknown instruction label: {}".format(label)) + (format, expected) = instr_map[label] + if op != expected: + raise ValueError("opcode {} doesn't match label {} (expected {})" + .format(op, label, expected)) + + if format == 'u': + out = pack_u(instr) + elif format == 'i': + out = pack_i(instr) + elif format == 's': + out = pack_s(instr) + elif format == 'j': + out = pack_j(instr) + else: + raise NotImplementedError() + + yield format_instr(out) + +if __name__ == '__main__': + import sys + for line in format(sys.stdin): + print(line) + +import unittest +class TestPackers(unittest.TestCase): + def test_pack_u(self): + final = pack_u([(0x37, 'lui'), (5, 'rd', 't0'), (0x10010, 'imm20')]) + self.assertEqual( + final, + [(0x37, 7), (0x5, 5), (0x10010, 20)] + ) + self.assertEqual(bit_concat(*final)[1], 32) + + label = pack_u([(0x37, 'lui'), (5, 'rd', 't0'), ('pos', 'imm20')]) + self.assertEqual( + label, + [(0x37, 7), (0x5, 5), ('pos', 'imm20')] + ) + + def test_pack_i(self): + final = pack_i([ + (0x13, 'opi'), + (0, 'subop', 'add'), + (6, 'rd', 't1'), + (0, 'rs', 'x0'), + (0x65, 'imm12'), + ]) + self.assertEqual( + final, + [(0x13, 7), (6, 5), (0, 3), (0, 5), (0x65, 12)] + ) + self.assertEqual(bit_concat(*final)[1], 32) + + def test_pack_s(self): + final = pack_s([ + (0x23, 'store'), + (2, 'subop', 'word'), + (5, 'rs', 't0'), + (6, 'rs', 't1'), + (0, 'off12'), + ]) + self.assertEqual( + final, + [(0x23, 7), (0, 5), (2, 3), (5, 5), (6, 5), (0, 7)] + ) + self.assertEqual(bit_concat(*final)[1], 32) + + label = pack_s([ + (0x23, 'store'), + (2, 'subop', 'word'), + (5, 'rs', 't0'), + (6, 'rs', 't1'), + ('home', 'off12'), + ]) + self.assertEqual(label, [ + (0x23, 7), + ('home', 5, 'off12'), + (2, 3), + (5, 5), + (6, 5), + ('home', 7, 'off12>>5'), + ]) + +class TestE2E(unittest.TestCase): + def test_e2e(self): + from io import StringIO + from textwrap import dedent + inp = dedent('''\ + == code 0x80000000 + main: + # load 0x10010000 (UART0) into t0 + 37/lui 5/rd/t0 0x10010/imm20 + # store 0x48 (H) in UART0+0 + 13/opi 0/subop/add 6/rd/t1 0/rs/x0 48/imm12 + 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 + # store 0x65 (e) in UART0+0 + 13/opi 0/subop/add 6/rd/t1 0/rs/x0 65/imm12 + 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 + # store 0x6c (l) in UART0+0 + 13/opi 0/subop/add 6/rd/t1 0/rs/x0 6c/imm12 + 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 + # store 0x6c (l) in UART0+0 + 13/opi 0/subop/add 6/rd/t1 0/rs/x0 6c/imm12 + 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 + # store 0x6f (o) in UART0+0 + 13/opi 0/subop/add 6/rd/t1 0/rs/x0 6f/imm12 + 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 + # store 0x0a (\\n) in UART0+0 + 13/opi 0/subop/add 6/rd/t1 0/rs/x0 0a/imm12 + 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 + # jump back up to the top + 6f/jal 0/rd/x0 main/off21 + ''') + + out = dedent('''\ + == code 0x80000000 + main: + 37/7 05/5 10010/20 + 13/7 06/5 00/3 00/5 48/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 65/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 6c/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 6c/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 6f/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 0a/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 6f/7 00/5 main/8/off21>>12 main/1/off21>>11 main/10/off21>>1 main/1/off21>>20 + ''') + + got = '' + for line in format(StringIO(inp)): + got += line + '\n' + + self.assertEqual(got, out) @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +from riscv import byteify, bit_concat +from subx import clean, classify, parse_bits, format_instr + +def pack(iter): + for line in iter: + line = clean(line) + if line == '': + continue + + type = classify(line) + + if type == 'segment' or type == 'label': + yield line + else: + fields = parse_bits(line) + total = bit_concat(*fields) + + if total[1] != 32: + raise ValueError("instruction parts do not add up to 32 bit!") + + yield format_instr(byteify(total)) + +if __name__ == '__main__': + import sys + for line in pack(sys.stdin): + print(line) + +import unittest +class TestE2E(unittest.TestCase): + def test_e2e(self): + from io import StringIO + from textwrap import dedent + inp = dedent('''\ + == code 0x80000000 + 37/7 05/5 10010/20 + 13/7 06/5 00/3 00/5 48/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 65/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 6c/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 6c/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 6f/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 0a/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 6f/7 00/5 ff/8 01/1 3e6/10 1/1 + ''') + + out = dedent('''\ + == code 0x80000000 + b7 02 01 10 + 13 03 80 04 + 23 a0 62 00 + 13 03 50 06 + 23 a0 62 00 + 13 03 c0 06 + 23 a0 62 00 + 13 03 c0 06 + 23 a0 62 00 + 13 03 f0 06 + 23 a0 62 00 + 13 03 a0 00 + 23 a0 62 00 + 6f f0 df fc + ''') + + got = '' + for line in pack(StringIO(inp)): + got += line + '\n' + + self.assertEqual(got, out) @@ -160,6 +160,10 @@ class TestHelpers(unittest.TestCase): byteify((0x12345678, 32)), [(0x78,), (0x56,), (0x34,), (0x12,)] ) + self.assertEqual( + byteify((0x4801813, 32)), + [(0x13,), (0x18,), (0x80,), (0x04,)] + ) class TestFormats(unittest.TestCase): def test_format_u(self): @@ -13,16 +13,29 @@ def parse_instr(line): parts = [parse_part(part) for part in parts if part != ''] return parts +def parse_bits(line): + parts = [] + for part in white.split(line): + if part == '': + continue + + val, size = parse_part(part) + parts.append((val, int(size))) + return parts + def parse_segment(line): parts = white.split(line) return (parts[1], int(parts[2], 16)) +def parse_label(line): + return line[:-1] + def is_lref(part): return isinstance(part[0], str) -def unlabel(part, expect=None): +def untag(part, expect=None): if expect and part[1] != expect: - raise ValueError("expected {} to be labelled {}", part, expect) + raise ValueError("expected {} to be labelled {}".format(part, expect)) return part[0] def format_part(part): @@ -38,7 +51,7 @@ def format_instr(inst, comment=None): return packed def clean(line): - return line.strip().split('#')[0] + return line.strip().split('#')[0].rstrip() def classify(line): if line.startswith('=='): # segment diff --git a/survey.py b/survey.py new file mode 100644 index 0000000..51f1136 --- /dev/null +++ b/survey.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 +from subx import clean, classify, parse_segment, parse_label, parse_instr, format_instr, is_lref +from riscv import u, i, bit_concat, bit_slice +import re + +def scan(iter): + addr = None + map = {} + for line in iter: + if line['type'] == 'label': + map[line['label']] = line['addr'] + return map + +tag_re = re.compile(r'^(imm|off)(\d+)(?:>>(\d+))?$') +def observe(part, rel_addr, map): + if is_lref(part): + label, trim, tag = part + trim = int(trim) + + if label not in map: + raise ValueError("label not found: {} ({})".format(label, part)) + addr = map[label] + + mode, size, shift = tag_re.match(tag).groups() + size = int(size) + shift = int(shift) + + if mode == 'imm': + addr = u(addr, size) + else: + addr = i(addr - rel_addr, size) + + part = bit_slice(addr, trim+shift-1, shift) + + return part + +def survey(iter): + # buffer in everything first, we need two passes + queue = [] + addr = -1 + for line in iter: + # parse the line + line = clean(line) + if line == '': + continue + + type = classify(line) + if type == 'segment': + parsed = parse_segment(line) + elif type == 'label': + parsed = parse_label(line) + elif type == 'instr': + parsed = parse_instr(line) + + queue.append({ + 'type': type, + 'raw': line, + 'addr': addr, + type: parsed, + }) + + # step forward addr + if type == 'segment': + segment, addr = parsed + elif type == 'instr': + bits = 0 + for part in parsed: + bits += int(part[1]) + + if bits % 8 != 0: + raise ValueError("SubV lines should be byte aligned!") + + addr += bits // 8 + + map = scan(queue) + for line in queue: + if line['type'] == 'instr': + instr = [] + for part in line['instr']: + observed = observe(part, line['addr'], map) + instr.append(observed) + yield format_instr(instr) + elif line['type'] == 'segment': + yield line['raw'] + +if __name__ == '__main__': + import sys + for line in survey(sys.stdin): + print(line) + +import unittest +class TestE2E(unittest.TestCase): + def test_e2e(self): + from io import StringIO + from textwrap import dedent + inp = dedent('''\ + == code 0x80000000 + main: + 37/7 05/5 10010/20 + 13/7 06/5 00/3 00/5 48/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 65/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 6c/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 6c/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 6f/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 0a/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 6f/7 00/5 main/8/off21>>12 main/1/off21>>11 main/10/off21>>1 main/1/off21>>20 + ''') + + out = dedent('''\ + == code 0x80000000 + 37/7 05/5 10010/20 + 13/7 06/5 00/3 00/5 48/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 65/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 6c/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 6c/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 6f/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 13/7 06/5 00/3 00/5 0a/12 + 23/7 00/5 02/3 05/5 06/5 00/7 + 6f/7 00/5 ff/8 01/1 3e6/10 01/1 + ''') + + got = '' + for line in survey(StringIO(inp)): + got += line + '\n' + + self.assertEqual(got, out) diff --git a/test.subv b/test.subv new file mode 100644 index 0000000..f1c73fd --- /dev/null +++ b/test.subv @@ -0,0 +1,24 @@ +== code 0x80000000 +main: + # load 0x10010000 (UART0) into t0 + 37/lui 5/rd/t0 0x10010/imm20 + # store 0x48 (H) in UART0+0 + 13/opi 0/subop/add 6/rd/t1 0/rs/x0 48/imm12 + 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 + # store 0x65 (e) in UART0+0 + 13/opi 0/subop/add 6/rd/t1 0/rs/x0 65/imm12 + 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 + # store 0x6c (l) in UART0+0 + 13/opi 0/subop/add 6/rd/t1 0/rs/x0 6c/imm12 + 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 + # store 0x6c (l) in UART0+0 + 13/opi 0/subop/add 6/rd/t1 0/rs/x0 6c/imm12 + 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 + # store 0x6f (o) in UART0+0 + 13/opi 0/subop/add 6/rd/t1 0/rs/x0 6f/imm12 + 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 + # store 0x0a (\n) in UART0+0 + 13/opi 0/subop/add 6/rd/t1 0/rs/x0 0a/imm12 + 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 + # jump back up to the top + 6f/jal 0/rd/x0 main/off21 diff --git a/verify.py b/verify.py deleted file mode 100644 index 8499da5..0000000 --- a/verify.py +++ /dev/null @@ -1,186 +0,0 @@ -#!/usr/bin/env python3 -from subx import clean, classify, parse_segment, parse_instr, is_lref, unlabel, format_instr -from riscv import u, i, bit_concat - -""" -""" - -instr_map = { - 'opr': ('r', 0x33), - 'load': ('i', 0x03), - 'opi': ('i', 0x13), - 'jalr': ('i', 0x67), - 'store': ('s', 0x23), - 'branch': ('b', 0x63), - 'lui': ('u', 0x37), - 'auipc': ('u', 0x17), - 'jal': ('j', 0x6f), -} - -def pack_u(instr): - (op, rd, imm) = instr - op = u(unlabel(op), 7) - rd = u(unlabel(rd, 'rd'), 5) - if not is_lref(imm): - imm = i(unlabel(imm, 'imm20'), 20) - - return [op, rd, imm] - -def pack_i(instr): - (op, sub, rd, rs, imm) = instr - op = u(unlabel(op), 7) - sub = u(unlabel(sub, 'subop'), 3) - rd = u(unlabel(rd, 'rd'), 5) - rs = u(unlabel(rs, 'rs'), 5) - if not is_lref(imm): - imm = i(unlabel(imm, 'imm12'), 12) - - return [op, sub, rd, rs, imm] - -def pack_s(instr): - (op, sub, rs1, rs2, imm) = instr - op = u(unlabel(op), 7) - sub = u(unlabel(sub, 'subop'), 3) - rs1 = u(unlabel(rs1, 'rs'), 5) - rs2 = u(unlabel(rs2, 'rs'), 5) - if not is_lref(imm): - imm = i(unlabel(imm, 'disp12'), 12) - - return [op, sub, rs1, rs2, imm] - -def pack_j(instr): - (op, rd, imm) = instr - op = u(unlabel(op), 7) - rd = u(unlabel(rd, 'rd'), 5) - if not is_lref(imm): - imm = i(unlabel(imm, 'disp20u'), 20) - - return [op, rd, imm] - -def pack(iter): - for line in iter: - line = clean(line) - if line == '': - continue - - type = classify(line) - - if type == 'segment' or type == 'label': - yield line - else: - instr = parse_instr(line) - op = instr[0] - if len(op) != 2: - raise ValueError("instruction without op label") - - (op, label) = op - if label not in instr_map: - raise ValueError("unknown instruction label: {}".format(label)) - (format, expected) = instr_map[label] - if op != expected: - raise ValueError("opcode {} doesn't match label {} (expected {})" - .format(op, label, expected)) - - out = None - if format == 'u': - out = pack_u(instr) - elif format == 'i': - out = pack_i(instr) - elif format == 's': - out = pack_s(instr) - elif format == 'j': - out = pack_j(instr) - else: - raise NotImplementedError() - - yield format_instr(out) - -if __name__ == '__main__': - import sys - pack(sys.stdin) - -import unittest -class TestPackers(unittest.TestCase): - def test_pack_u(self): - final = pack_u([(0x37, 'lui'), (5, 'rd', 't0'), (0x10010, 'imm20')]) - self.assertEqual( - final, - [(0x37, 7), (0x5, 5), (0x10010, 20)] - ) - self.assertEqual(bit_concat(*final)[1], 32) - - label = pack_u([(0x37, 'lui'), (5, 'rd', 't0'), ('pos', 'imm20')]) - self.assertEqual( - label, - [(0x37, 7), (0x5, 5), ('pos', 'imm20')] - ) - - def test_pack_i(self): - final = pack_i([ - (0x13, 'opi'), - (0, 'subop', 'add'), - (6, 'rd', 't1'), - (0, 'rs', 'x0'), - (0x65, 'imm12'), - ]) - self.assertEqual( - final, - [(0x13, 7), (0, 3), (6, 5), (0, 5), (0x65, 12)] - ) - self.assertEqual(bit_concat(*final)[1], 32) - -from io import StringIO -from textwrap import dedent -class TestE2E(unittest.TestCase): - def test_e2e(self): - inv = dedent('''\ - == code 0x80000000 - main: - # load 0x10010000 (UART0) into t0 - 37/lui 5/rd/t0 0x10010/imm20 - # store 0x48 (H) in UART0+0 - 13/opi 0/subop/add 6/rd/t1 0/rs/x0 48/imm12 - 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/disp12 - # store 0x65 (e) in UART0+0 - 13/opi 0/subop/add 6/rd/t1 0/rs/x0 65/imm12 - 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/disp12 - # store 0x6c (l) in UART0+0 - 13/opi 0/subop/add 6/rd/t1 0/rs/x0 6c/imm12 - 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/disp12 - # store 0x6c (l) in UART0+0 - 13/opi 0/subop/add 6/rd/t1 0/rs/x0 6c/imm12 - 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/disp12 - # store 0x6f (o) in UART0+0 - 13/opi 0/subop/add 6/rd/t1 0/rs/x0 6f/imm12 - 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/disp12 - # store 0x0a (\\n) in UART0+0 - 13/opi 0/subop/add 6/rd/t1 0/rs/x0 0a/imm12 - 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/disp12 - # jump back up to the top - 6f/jal 0/rd/x0 main/disp20u - ''') - - out = dedent('''\ - == code 0x80000000 - main: - 37/7 05/5 10010/20 - 13/7 00/3 06/5 00/5 48/12 - 23/7 02/3 05/5 06/5 00/12 - 13/7 00/3 06/5 00/5 65/12 - 23/7 02/3 05/5 06/5 00/12 - 13/7 00/3 06/5 00/5 6c/12 - 23/7 02/3 05/5 06/5 00/12 - 13/7 00/3 06/5 00/5 6c/12 - 23/7 02/3 05/5 06/5 00/12 - 13/7 00/3 06/5 00/5 6f/12 - 23/7 02/3 05/5 06/5 00/12 - 13/7 00/3 06/5 00/5 0a/12 - 23/7 02/3 05/5 06/5 00/12 - 6f/7 00/5 main/disp20u - ''') - - got = '' - for line in pack(StringIO(inv)): - got += line + '\n' - - self.assertEqual(got, out) |
