mirror of https://git.sr.ht/~rabbits/uxn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
3.8 KiB
103 lines
3.8 KiB
-- Used for porting Uxntal code for use with the old assembler |
|
-- in commit 82f7103a55c21b13f898b20e5d1e174e501bc825 with the |
|
-- assembler that replaced it straight afterwards. |
|
|
|
import P, R, S, C, Ct, Cp, V from require 'lpeg' |
|
|
|
local labels, filename |
|
|
|
opcode_translate = |
|
LDZ2: 'LDA' |
|
STZ2: 'STA' |
|
LDR: 'LDZ2' |
|
STR: 'STZ2' |
|
LDR2: 'LDA2' |
|
STR2: 'STA2' |
|
|
|
grammar = P { |
|
'file' |
|
file: Ct(V'ows' * (V'atom' * V'ows') ^ 0) * Cp! |
|
ws: C S' \n\t' ^ 1 |
|
ows: C S' \n\t' ^ 0 |
|
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' |
|
comment: C P'(' * (1-V'ws'*P')') ^ 0 * V'ws' * P')' |
|
variable: (P';' / -> '@') * C(V'name') * V'ws' * (P'{' / ->'[') * V'ws' * ((P'' / -> '&') * C(V'name') * V'ws' * (P'' / -> '$') * C(V'name') * V'ws') ^ 0 * (P'}' / -> ']') / (...) -> |
|
var = select 2, ... |
|
r, w = if var\sub(1, 1) == var\sub(1, 1)\upper! |
|
' DEI', ' DEO' |
|
else |
|
' LDZ', ' STZ' |
|
for i = 7, select('#', ...), 6 |
|
k = select i, ... |
|
rr, ww = if '2' == select i + 3, ... |
|
r .. '2', w .. '2' |
|
else |
|
r, w |
|
labels['~' .. var .. '.' .. k] = '.' .. var .. '/' .. k .. rr |
|
labels['=' .. var .. '.' .. k] = '.' .. var .. '/' .. k .. ww |
|
if i == 7 |
|
labels['~' .. var] = '.' .. var .. rr |
|
labels['=' .. var] = '.' .. var .. ww |
|
... |
|
name: R('az', 'AZ', '09', '__', '--', '++', '**', '//', '??') ^ 1 |
|
addr: C(P'|') * (C(V'hex') / (i) -> |
|
if i == '0200' |
|
return '0100' |
|
if i\match '^01..$' |
|
return i\sub 3 |
|
return i |
|
) |
|
literal: C P'#' * V'hex' |
|
hex: R('09', 'af', 'AF') ^ 1 |
|
setter: C(P'=' * V'label') / (s) -> |
|
if not labels[s] |
|
error 'label not found: %q in %s'\format s, filename |
|
return labels[s] |
|
getter: C(P'~' * V'label') / (s) -> |
|
if not labels[s] |
|
error 'label not found: %q in %s'\format s, filename |
|
return labels[s] |
|
label: R('az', 'AZ', '09', '__', '--', '..', '$$', ']]', '))', '@@', '""', ',,', '##', '||', '{{', '}}', '%%', ';;', '^^', '~~', '==', '//') ^ 1 |
|
short: (P',' / -> ';') * (C(V'label') / (s) -> (s\gsub '%$', '&')) |
|
rawshort: (P'.' / -> ':') * (C(V'label') / (s) -> (s\gsub '%$', '&')) |
|
opcode: (C(R'AZ' * R'AZ' * R'AZ' * P'2' ^ -1) / (s) -> opcode_translate[s] or s) * C P'r' ^ -1 * #V'ws' |
|
labeldef: C P'@' * V'label' |
|
relative: (P'^' / -> ',') * (C(V'label') / (s) -> (s\gsub '%$', '&')) |
|
sublabel: (P'$' / -> '&') * (C(V'label') / (s) -> (s\gsub '%$', '&')) |
|
data: C(P'[') * V'ws' * (V'data_item' * V'ws') ^ 0 * C(P']') |
|
macro: C(P'%' * V'name' * V'ws' * P'{') * V'ws' * (V'atom' * V'ows') ^ 0 * C P'}' |
|
macroref: C V'name' |
|
data_item: C(V'hex' * #V'ws') + V'data_string' |
|
data_string: C((1 - S' \n\t') ^ 1 - P']') / (s) -> '"', s |
|
} |
|
|
|
translate = (_filename) -> |
|
filename = _filename |
|
labels = {} |
|
f = assert io.open filename |
|
contents = f\read '*a' |
|
f\close! |
|
t, len = grammar\match contents |
|
if len <= #contents |
|
print '\027[32m%s\027[0;1m%s\027[0m'\format contents\sub(len - 100, len - 1), contents\sub(len, len + 100) |
|
error 'no match' |
|
filename = filename\gsub 'attic', 'auto' |
|
f = assert io.open filename, 'w' |
|
f\write table.concat(t) |
|
f\close! |
|
f = assert io.popen 'bin/assembler %s bin/boot.rom'\format filename |
|
for l in f\lines! |
|
print l |
|
if l == 'Error: Assembly[Failed]' |
|
os.exit 1 |
|
f\close! |
|
os.exit 0 |
|
|
|
translate 'attic/software/assembler.tal' |
|
os.exit 0 |
|
|
|
translate 'attic/tests/opcodes.tal' |
|
translate 'attic/tests/basics.tal' |
|
|
|
-- for k, v in pairs t |
|
-- print k
|
|
|