Browse code

Added Uxambly porting helper program

Andrew Alderwick authored on 23/04/2021 15:47:59
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,102 @@
1
+-- Used for porting Uxambly code for use with the old assembler
2
+-- in commit 82f7103a55c21b13f898b20e5d1e174e501bc825 with the
3
+-- assembler that replaced it straight afterwards.
4
+
5
+import P, R, S, C, Ct, Cp, V from require 'lpeg'
6
+
7
+local labels, filename
8
+
9
+opcode_translate =
10
+    PEK2: 'GET'
11
+    POK2: 'PUT'
12
+    LDR: 'PEK2'
13
+    STR: 'POK2'
14
+    LDR2: 'GET2'
15
+    STR2: 'PUT2'
16
+
17
+grammar = P {
18
+    'file'
19
+    file: Ct(V'ows' * (V'atom' * V'ows') ^ 0) * Cp!
20
+    ws: C S' \n\t' ^ 1
21
+    ows: C S' \n\t' ^ 0
22
+    atom: V'opcode' + V'comment' + V'variable' + V'addr' + V'literal' + V'setter' + V'getter' + V'short' + V'labeldef' + V'relative' + V'sublabel' + V'data' + V'macro' + V'macroref' + V'rawshort'
23
+    comment: C P'(' * (1-V'ws'*P')') ^ 0 * V'ws' * P')'
24
+    variable: (P';' / -> '@') * C(V'name') * V'ws' * (P'{' / ->'[') * V'ws' * ((P'' / -> '&') * C(V'name') * V'ws' * (P'' / -> '$') * C(V'name') * V'ws') ^ 0 * (P'}' / -> ']') / (...) ->
25
+        var = select 2, ...
26
+        r, w = if var\sub(1, 1) == var\sub(1, 1)\upper!
27
+            ' DEI', ' DEO'
28
+        else
29
+            ' PEK', ' POK'
30
+        for i = 7, select('#', ...), 6
31
+            k = select i, ...
32
+            rr, ww = if '2' == select i + 3, ...
33
+                r .. '2', w .. '2'
34
+            else
35
+                r, w
36
+            labels['~' .. var .. '.' .. k] = '.' .. var .. '/' .. k .. rr
37
+            labels['=' .. var .. '.' .. k] = '.' .. var .. '/' .. k .. ww
38
+            if i == 7
39
+                labels['~' .. var] = '.' .. var .. rr
40
+                labels['=' .. var] = '.' .. var .. ww
41
+        ...
42
+    name: R('az', 'AZ', '09', '__', '--', '++', '**', '//', '??') ^ 1
43
+    addr: C(P'|') * (C(V'hex') / (i) ->
44
+        if i == '0200'
45
+            return '0100'
46
+        if i\match '^01..$'
47
+            return i\sub 3
48
+        return i
49
+    )
50
+    literal: C P'#' * V'hex'
51
+    hex: R('09', 'af', 'AF') ^ 1
52
+    setter: C(P'=' * V'label') / (s) ->
53
+        if not labels[s]
54
+            error 'label not found: %q in %s'\format s, filename
55
+        return labels[s]
56
+    getter: C(P'~' * V'label') / (s) ->
57
+        if not labels[s]
58
+            error 'label not found: %q in %s'\format s, filename
59
+        return labels[s]
60
+    label: R('az', 'AZ', '09', '__', '--', '..', '$$', ']]', '))', '@@', '""', ',,', '##', '||', '{{', '}}', '%%', ';;', '^^', '~~', '==', '//') ^ 1
61
+    short: (P',' / -> ';') * (C(V'label') / (s) -> (s\gsub '%$', '&'))
62
+    rawshort: (P'.' / -> ':') * (C(V'label') / (s) -> (s\gsub '%$', '&'))
63
+    opcode: (C(R'AZ' * R'AZ' * R'AZ' * P'2' ^ -1) / (s) -> opcode_translate[s] or s) * C P'r' ^ -1 * #V'ws'
64
+    labeldef: C P'@' * V'label'
65
+    relative: (P'^' / -> ',') * (C(V'label') / (s) -> (s\gsub '%$', '&'))
66
+    sublabel: (P'$' / -> '&') * (C(V'label') / (s) -> (s\gsub '%$', '&'))
67
+    data: C P'[' * (1-P']') ^ 0 * P']'
68
+    macro: C(P'%' * V'name' * V'ws' * P'{') * V'ws' * (V'atom' * V'ows') ^ 0 * C P'}'
69
+    macroref: C V'name'
70
+}
71
+
72
+translate = (_filename) ->
73
+    filename = _filename
74
+    labels = {}
75
+    f = assert io.open filename
76
+    contents = f\read '*a'
77
+    f\close!
78
+    t, len = grammar\match contents
79
+    if len <= #contents
80
+        print '\027[32m%s\027[0;1m%s\027[0m'\format contents\sub(len - 100, len - 1), contents\sub(len, len + 100)
81
+        error 'no match'
82
+    filename = filename\gsub 'attic', 'auto'
83
+    f = assert io.open filename, 'w'
84
+    f\write (table.concat(t)\gsub(' +\n', '\n')\gsub('  +', ' '))
85
+    f\close!
86
+    f = assert io.popen 'bin/assembler %s bin/boot.rom'\format filename
87
+    for l in f\lines!
88
+        print l
89
+        if l == 'Error: Assembly[Failed]'
90
+            os.exit 1
91
+    f\close!
92
+    os.exit 0
93
+
94
+translate 'attic/software/left.usm'
95
+os.exit 0
96
+
97
+translate 'attic/software/assembler.usm'
98
+translate 'attic/tests/opcodes.usm'
99
+translate 'attic/tests/basics.usm'
100
+
101
+-- for k, v in pairs t
102
+--     print k