aboutsummaryrefslogtreecommitdiffstats
path: root/pack.py
blob: 98d7d869b5c61fb60f4144a7e8a76be38e9bb177 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/usr/bin/env python3
import subv
import bits

def byteify(word):
    (val, size) = word
    if size % 8 != 0:
        raise ValueError("Not byte aligned: {} bits".format(size))

    out = []
    for i in range(0, size, 8):
        byte = bits.slice(word,  i+7,  i)
        out.append(byte[:1])
    return out

def pack(iter):
    segment = None
    for line in iter:
        line = subv.parse(line)
        if line['type'] == 'instr':
            fields = [bits.from_part(p) for p in line['instr']]
            total = bits.concat(*fields)

            if segment == 'code' and total[1] != 32:
                raise ValueError("instruction parts do not add up to 32 bit!")

            yield subv.format_instr(byteify(total))
        else:
            if line['type'] == 'segment':
                segment = line['segment'][0]
            yield line['raw']

if __name__ == '__main__':
    import sys
    for line in pack(sys.stdin):
        print(line)

import unittest
class TestPack(unittest.TestCase):
    def test_byteify(self):
        self.assertEqual(
            byteify((0x12345678, 32)),
            [(0x78,), (0x56,), (0x34,), (0x12,)]
        )
        self.assertEqual(
            byteify((0x4801813, 32)),
            [(0x13,), (0x18,), (0x80,), (0x04,)]
        )

    def test_e2e(self):
        from io import StringIO
        from textwrap import dedent
        inp = dedent('''\
            # do some things
            == 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('''\
            # do some things
            == 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)