brace fixes
This commit is contained in:
parent
870bb34454
commit
ed3d0ee53b
@ -14,9 +14,9 @@ end
|
|||||||
local function decodeNumber(n)
|
local function decodeNumber(n)
|
||||||
n = trim(n)
|
n = trim(n)
|
||||||
local sign = 1; if n:sub(1, 1)=="-" then sign = -1; n = n:sub(2, #n); end;
|
local sign = 1; if n:sub(1, 1)=="-" then sign = -1; n = n:sub(2, #n); end;
|
||||||
if n:sub(1, 1)=="$" then return sign*tonumber(n:sub(2, #n ), 16), math.ceil((#n-1)/2)
|
if n:sub(1, 1)=="$" then return sign*(tonumber(n:sub(2, #n ), 16) or error("invalid number "..n)), math.ceil((#n-1)/2)
|
||||||
elseif n:sub(1, 2)=="0x" then return sign*tonumber(n:sub(3, #n ), 16), math.ceil((#n-2)/2)
|
elseif n:sub(1, 2)=="0x" then return sign*(tonumber(n:sub(3, #n ), 16) or error("invalid number "..n)), math.ceil((#n-2)/2)
|
||||||
elseif n:sub(#n, #n)=="h" then return sign*tonumber(n:sub(1, #n-1), 16), math.ceil((#n-1)/2)
|
elseif n:sub(#n, #n)=="h" then return sign*(tonumber(n:sub(1, #n-1), 16) or error("invalid number "..n)), math.ceil((#n-1)/2)
|
||||||
else
|
else
|
||||||
local v = tonumber(n) or error("invalid number "..n)
|
local v = tonumber(n) or error("invalid number "..n)
|
||||||
if v>=-128 and v<=255 then return v, 1
|
if v>=-128 and v<=255 then return v, 1
|
||||||
@ -34,13 +34,15 @@ local function mnemFromLine(line, instrs, validWords)
|
|||||||
end
|
end
|
||||||
local function addLabel(n)
|
local function addLabel(n)
|
||||||
local len = 2
|
local len = 2
|
||||||
if instrs[line:gsub(trim(n), "imm8", 1, true)] then len = 1 end
|
local linei8 = line:gsub(trim(n), "imm8", 1, true)
|
||||||
|
if instrs[linei8] then len = 1 end
|
||||||
n = trim(n)
|
n = trim(n)
|
||||||
table.insert(imms, { label = n, len = len } )
|
table.insert(imms, { label = n, len = len } )
|
||||||
return " imm"..(len*8).." "
|
return " imm"..(len*8).." "
|
||||||
end
|
end
|
||||||
|
|
||||||
local mnem = " "..line:gsub(" ", " ").." "
|
local mnem = " "..line:gsub(" ", " ").." "
|
||||||
|
mnem = mnem:gsub("([%*%+%-])", " %1 ")
|
||||||
mnem = mnem:gsub(" %-?%$[0-9a-fA-F]+ " , function(n) return addNum (n) end)
|
mnem = mnem:gsub(" %-?%$[0-9a-fA-F]+ " , function(n) return addNum (n) end)
|
||||||
mnem = mnem:gsub(" %-?0x[0-9a-fA-F]+ " , function(n) return addNum (n) end)
|
mnem = mnem:gsub(" %-?0x[0-9a-fA-F]+ " , function(n) return addNum (n) end)
|
||||||
mnem = mnem:gsub(" %-?[0-9a-fA-F]+h " , function(n) if not validWords[trim(n)] then return addNum (n) end end)
|
mnem = mnem:gsub(" %-?[0-9a-fA-F]+h " , function(n) if not validWords[trim(n)] then return addNum (n) end end)
|
||||||
@ -70,7 +72,7 @@ local function addSpace(state, len)
|
|||||||
end
|
end
|
||||||
local function assembleInstruction(line, state, instrs, validWords)
|
local function assembleInstruction(line, state, instrs, validWords)
|
||||||
local mnem, imms = mnemFromLine(line, instrs, validWords)
|
local mnem, imms = mnemFromLine(line, instrs, validWords)
|
||||||
local opcode = instrs[mnem] or error("invalid instruction "..line.." (mnem "..mnem..")")
|
local opcode = instrs[mnem] or error("invalid instruction \""..line.."\" (mnem \""..mnem.."\")")
|
||||||
local writeimms = true
|
local writeimms = true
|
||||||
local padlen = 0
|
local padlen = 0
|
||||||
if type(opcode)=="function" then
|
if type(opcode)=="function" then
|
||||||
@ -116,6 +118,7 @@ local function assembleCode(code, instrs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for line in code:gmatch("[^\n]+") do
|
for line in code:gmatch("[^\n]+") do
|
||||||
|
line = trim(line)
|
||||||
if line:sub(1, 1)=="." then -- directive
|
if line:sub(1, 1)=="." then -- directive
|
||||||
local dir, rest = line:match("^%.([^ ]+) *(.*)$")
|
local dir, rest = line:match("^%.([^ ]+) *(.*)$")
|
||||||
assert(dir and rest, "no directive on line "..line)
|
assert(dir and rest, "no directive on line "..line)
|
||||||
@ -151,6 +154,16 @@ end
|
|||||||
local function separateCommas(l)
|
local function separateCommas(l)
|
||||||
local c = {}; for a in l:gmatch("[^,]+") do table.insert(c, trim(a)) end; return c;
|
local c = {}; for a in l:gmatch("[^,]+") do table.insert(c, trim(a)) end; return c;
|
||||||
end
|
end
|
||||||
|
local function evaluateExpression(expr)
|
||||||
|
expr = expr:gsub("[^%+%-%*%/]+", function(word)
|
||||||
|
local val = decodeNumber(word) or error("invalid number in expression: "..word)
|
||||||
|
return val
|
||||||
|
end)
|
||||||
|
assert(not expr:find("[^a-zA-Z0-9_%(%)%+%-%*%/ \t\r\n]"), "invalid char in expression: "..expr)
|
||||||
|
local exprf = loadstring("return "..expr)
|
||||||
|
local eval = exprf() or error("invalid expr: "..expr)
|
||||||
|
return eval
|
||||||
|
end
|
||||||
local function preprocessCode(code)
|
local function preprocessCode(code)
|
||||||
local funcmacros = {}
|
local funcmacros = {}
|
||||||
code = code:gsub(".define ([a-zA-Z0-9_]+)%(([^%)]+)%) ([^\n]+)", function(name, args, repl)
|
code = code:gsub(".define ([a-zA-Z0-9_]+)%(([^%)]+)%) ([^\n]+)", function(name, args, repl)
|
||||||
@ -171,15 +184,36 @@ local function preprocessCode(code)
|
|||||||
for name, replf in pairs(funcmacros) do code = code:gsub(name.." *%(([^%)]+)%)", replf) end
|
for name, replf in pairs(funcmacros) do code = code:gsub(name.." *%(([^%)]+)%)", replf) end
|
||||||
|
|
||||||
local simplemacros = {}
|
local simplemacros = {}
|
||||||
code = code:gsub("%.define ([a-zA-Z0-9_]+) ([^\n]+)", function(name, repl)
|
code = code:gsub("%.define +([a-zA-Z0-9_]+) +([^\n]+)", function(name, repl)
|
||||||
assert(not simplemacros[name], "Redefinition of macro "..name)
|
assert(not simplemacros[name], "Redefinition of macro "..name)
|
||||||
simplemacros[name] = repl
|
simplemacros[name] = repl
|
||||||
return ""
|
return ""
|
||||||
end)
|
end)
|
||||||
for name, repl in pairs(simplemacros) do code = code:gsub(name, repl, 1, true) end
|
--for name, repl in pairs(simplemacros) do code = code:gsub(name, repl, 1, true) end
|
||||||
|
for name, repl in pairs(simplemacros) do code = code:gsub(name, repl) end
|
||||||
|
|
||||||
code = code:gsub("\\", "\n")
|
code = code:gsub("\\", "\n")
|
||||||
|
|
||||||
|
local codet = {}
|
||||||
|
local exprt = {}
|
||||||
|
local parenLevel = 0
|
||||||
|
for i = 1, #code do
|
||||||
|
local c = code:sub(i, i)
|
||||||
|
if c=="(" then
|
||||||
|
parenLevel = parenLevel+1
|
||||||
|
elseif c==")" then
|
||||||
|
parenLevel = parenLevel-1
|
||||||
|
if parenLevel==0 then
|
||||||
|
table.insert(codet, evaluateExpression(table.concat(exprt)))
|
||||||
|
exprt = {}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if parenLevel==0 then table.insert(codet, c)
|
||||||
|
else table.insert(exprt, c) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
code = table.concat(codet)
|
||||||
|
|
||||||
return code
|
return code
|
||||||
end
|
end
|
||||||
local function fixCode(code)
|
local function fixCode(code)
|
||||||
@ -192,9 +226,13 @@ local function fixCode(code)
|
|||||||
code = code:gsub("\n[ \t\r\n]*", "\n")
|
code = code:gsub("\n[ \t\r\n]*", "\n")
|
||||||
code = code:gsub(" +", " ")
|
code = code:gsub(" +", " ")
|
||||||
local curScope = ""
|
local curScope = ""
|
||||||
code = code:gsub("([a-zA-Z_%.][a-zA-Z0-9_%.]*)(:?)", function(name, colon)
|
code = code:gsub("(%.?)([a-zA-Z_][a-zA-Z0-9_%.]*)(:?)", function(dot, name, colon)
|
||||||
if name:sub(1, 1)=="." and not directiveFunctions[name:sub(2, #name)] then name = curScope..name end
|
if directiveFunctions[name] then return dot..name..colon end
|
||||||
if colon==":" then curScope = name:match("^[^%.]+") end
|
if dot=="." then
|
||||||
|
assert(curScope~="", "scoped label before any unscoped label: "..name)
|
||||||
|
name = curScope.."."..name
|
||||||
|
end
|
||||||
|
if colon==":" and not name:find("^_BRACE_") then curScope = name:match("^[^%.]+") end
|
||||||
return name..colon
|
return name..colon
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -203,10 +241,12 @@ end
|
|||||||
local stringEscapes = { ["\\"] = "\\", ["n"] = "\n", ["r"] = "\r", ["t"] = "\t", ["0"] = "\0", ["\""] = "\"", ["\'"] = "\'", }
|
local stringEscapes = { ["\\"] = "\\", ["n"] = "\n", ["r"] = "\r", ["t"] = "\t", ["0"] = "\0", ["\""] = "\"", ["\'"] = "\'", }
|
||||||
local function prefixCode(code, fn) -- fix strings, add line numbers
|
local function prefixCode(code, fn) -- fix strings, add line numbers
|
||||||
local outt = {}
|
local outt = {}
|
||||||
|
local outnextnl = {}
|
||||||
local linenum = 1
|
local linenum = 1
|
||||||
local function last() return outt[#outt] end
|
local function last() return outt[#outt] end
|
||||||
local function out(c) assert(type(c)=="string"); table.insert(outt, c); end
|
local function out(c) assert(type(c)=="string"); table.insert(outt, c); end
|
||||||
local function outn(n) out("$"..string.format("%02X", n).."\n"); end
|
local function outn(n) out("$"..string.format("%02X", n).."\n"); end
|
||||||
|
local function outnext(c) assert(type(c)=="string"); table.insert(outnextnl, c); end
|
||||||
local state = "code" -- code, comment, string, stringesc
|
local state = "code" -- code, comment, string, stringesc
|
||||||
local skipnl = false
|
local skipnl = false
|
||||||
|
|
||||||
@ -219,27 +259,29 @@ local function prefixCode(code, fn) -- fix strings, add line numbers
|
|||||||
out(".ln 1"); out("\n");
|
out(".ln 1"); out("\n");
|
||||||
for i = 1, #code do
|
for i = 1, #code do
|
||||||
local c = code:sub(i, i)
|
local c = code:sub(i, i)
|
||||||
|
local cn = code:sub(i+1, i+1)
|
||||||
if state=="code" then
|
if state=="code" then
|
||||||
if c=="\r" then
|
if c=="\r" then
|
||||||
elseif c=="\n" then
|
elseif c=="\n" or c=="/" then
|
||||||
linenum = linenum+1
|
linenum = linenum+1
|
||||||
if skipnl then out("\\"); skipnl = false;
|
if skipnl then skipnl = false
|
||||||
else out("\n") out(".ln "..linenum); out("\n"); end
|
else out("\n") out(".ln "..linenum); out("\n"); end
|
||||||
lastnl = true
|
lastnl = true
|
||||||
elseif c=="\t" or c==" " then out(" ")
|
for _, v in ipairs(outnextnl) do out(v) end; outnextnl = {};
|
||||||
elseif c=="#" or c==";" or c=="/" then state = "comment"
|
elseif c=="#" or c==";" or (c=="/" and cn=="/") then state = "comment"
|
||||||
elseif c=="\"" then state = "string" lastnl = false
|
elseif c=="\t" or c==" " then if (not lastnl) then out(" ") end
|
||||||
elseif c=="\\" then skipnl = true
|
elseif c=="\"" then state = "string" lastnl = false
|
||||||
elseif c:find("^[a-zA-Z0-9_%.:%$%(%)%*,%[%]]$") then out(c) lastnl = false
|
elseif c=="\\" then skipnl = true; out("\\");
|
||||||
|
elseif c:find("^[a-zA-Z0-9_%.:%$%(%)%*,%[%]%+%-%*%/]$") then out(c); lastnl = false
|
||||||
elseif c=="{" then
|
elseif c=="{" then
|
||||||
table.insert(bracestack, bracelabel())
|
table.insert(bracestack, bracelabel())
|
||||||
|
|
||||||
if not lastnl then out(bracestack[#bracestack].."MID") out("\n") end
|
if not lastnl then out(bracestack[#bracestack].."MID") end
|
||||||
out(bracestack[#bracestack].."START:") out("\n")
|
outnext(bracestack[#bracestack].."START:"); outnext("\n")
|
||||||
elseif c=="}" then
|
elseif c=="}" then
|
||||||
if not lastnl then out(bracestack[#bracestack].."START") out("\n") end
|
if not lastnl then out(bracestack[#bracestack].."START") end
|
||||||
out(bracestack[#bracestack].."END:") out("\n")
|
if not bracehasmid[#bracestack] then outnext(bracestack[#bracestack].."MID:") outnext("\n") end
|
||||||
if not bracehasmid[#bracestack] then out(bracestack[#bracestack].."MID:") out("\n") end
|
outnext(bracestack[#bracestack].."END:")
|
||||||
bracehasmid[#bracestack] = nil
|
bracehasmid[#bracestack] = nil
|
||||||
bracestack[#bracestack] = nil
|
bracestack[#bracestack] = nil
|
||||||
elseif c=="|" then
|
elseif c=="|" then
|
||||||
@ -248,7 +290,7 @@ local function prefixCode(code, fn) -- fix strings, add line numbers
|
|||||||
bracehasmid[#bracestack] = true
|
bracehasmid[#bracestack] = true
|
||||||
else error("invalid char "..c) end
|
else error("invalid char "..c) end
|
||||||
elseif state=="comment" then
|
elseif state=="comment" then
|
||||||
if c=="\n" then state = "code" out("\n") end
|
if c=="\n" then state = "code" out("\n") lastnl = true end
|
||||||
elseif state=="string" then
|
elseif state=="string" then
|
||||||
if c=="\\" then state = "stringesc"
|
if c=="\\" then state = "stringesc"
|
||||||
elseif c=="\"" then state = "code"
|
elseif c=="\"" then state = "code"
|
||||||
@ -259,15 +301,23 @@ local function prefixCode(code, fn) -- fix strings, add line numbers
|
|||||||
end
|
end
|
||||||
assert(#bracestack==0, "unclosed brace")
|
assert(#bracestack==0, "unclosed brace")
|
||||||
local code2 = table.concat(outt)
|
local code2 = table.concat(outt)
|
||||||
|
|
||||||
|
print(code2)
|
||||||
|
|
||||||
return code2
|
return code2
|
||||||
end
|
end
|
||||||
|
local function fixFilename(fn)
|
||||||
|
fn = fn:gsub("[^a-zA-Z0-9_]", "_")
|
||||||
|
return fn
|
||||||
|
end
|
||||||
local function includeFile(fn)
|
local function includeFile(fn)
|
||||||
fn = fn:gsub("\\", "/")
|
fn = fn:gsub("\\", "/")
|
||||||
local code = readFile(fn)
|
local code = readFile(fn)
|
||||||
code = prefixCode(code, fn)
|
code = prefixCode(code, fn)
|
||||||
code = ".fn "..fn.."\n"..code
|
local fnf = fixFilename(fn)
|
||||||
|
code = ".fn "..fnf.."\n"..code
|
||||||
code = code:gsub(".include ([^\r\n]+)", function(fn2)
|
code = code:gsub(".include ([^\r\n]+)", function(fn2)
|
||||||
return "\n"..includeFile(fn2).."\n"..".fn "..fn.."\n"
|
return "\n"..includeFile(fn2).."\n"..".fn "..fnf.."\n"
|
||||||
end)
|
end)
|
||||||
return code
|
return code
|
||||||
end
|
end
|
||||||
@ -288,7 +338,8 @@ local function instrsFromArch(arch)
|
|||||||
for _, instr in ipairs(arch.instructions) do
|
for _, instr in ipairs(arch.instructions) do
|
||||||
if instr.mnem then
|
if instr.mnem then
|
||||||
local mnem = instr.mnem
|
local mnem = instr.mnem
|
||||||
mnem = mnem:gsub("%*([^ ])", "%* %1")
|
mnem = mnem:gsub("([%*%+%-])", " %1 ")
|
||||||
|
mnem = trim(mnem):gsub(" +", " ")
|
||||||
instrs[mnem] = instr.opcode
|
instrs[mnem] = instr.opcode
|
||||||
if mnem:find("%*") then instrs[mnem:gsub("%*", "%[").." ]"] = instr.opcode end
|
if mnem:find("%*") then instrs[mnem:gsub("%*", "%[").." ]"] = instr.opcode end
|
||||||
end
|
end
|
||||||
@ -314,6 +365,7 @@ local function mnemsFromArch(arch)
|
|||||||
return mnems
|
return mnems
|
||||||
end
|
end
|
||||||
local function disassembleMemory(mem, arch)
|
local function disassembleMemory(mem, arch)
|
||||||
|
print("Disassembly:")
|
||||||
local mnems = mnemsFromArch(arch)
|
local mnems = mnemsFromArch(arch)
|
||||||
local addr = 0
|
local addr = 0
|
||||||
local function nextByte() local b = mem[addr]; addr = addr+1; return b; end
|
local function nextByte() local b = mem[addr]; addr = addr+1; return b; end
|
||||||
@ -359,12 +411,14 @@ local function disassembleHex(hex, arch)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function printMemory(mem)
|
local function printMemory(mem)
|
||||||
|
print("Memory Dump:")
|
||||||
local anynonempty = false
|
local anynonempty = false
|
||||||
local lastbase = -16
|
local lastbase = -16
|
||||||
for base = 0, 0xFFF0, 16 do
|
for base = 0, 0xFFF0, 16 do
|
||||||
local line = { string.format("%04X", base), " | " }
|
local line = { string.format("%04X", base), " |" }
|
||||||
local nonempty = false
|
local nonempty = false
|
||||||
for addr = base, base+15 do
|
for addr = base, base+15 do
|
||||||
|
if addr%4==0 then table.insert(line, " ") end
|
||||||
if mem[addr] then
|
if mem[addr] then
|
||||||
nonempty = true
|
nonempty = true
|
||||||
table.insert(line, string.format("%02X", mem[addr]).." ")
|
table.insert(line, string.format("%02X", mem[addr]).." ")
|
||||||
@ -379,7 +433,7 @@ local function printMemory(mem)
|
|||||||
anynonempty = true
|
anynonempty = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not anynonempty then print("Memory empty") end
|
if not anynonempty then print("Empty") end
|
||||||
print()
|
print()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -435,4 +489,4 @@ ts.eval [[
|
|||||||
function AssembleFile(%fn, %romsize, %offset, %len) { luacall("AssembleFile", %fn, %romsize, %offset, %len); }
|
function AssembleFile(%fn, %romsize, %offset, %len) { luacall("AssembleFile", %fn, %romsize, %offset, %len); }
|
||||||
]]
|
]]
|
||||||
|
|
||||||
if arg then AssembleFile(arg[1] or "../8608programs/keyboard.asm", "16 16 8", "0", "256") end
|
if arg then AssembleFile(arg[1] or "../8608programs/redos.asm", "16 16 8", "0", "256") end
|
||||||
|
@ -186,8 +186,8 @@ instructions = {
|
|||||||
{ mnem="jpr imm8" , opcode=0x31, ncycles=2, {"loadImmed","memSaveT","instrSub1"}, {"jmpRelT"}, desc="I+=imm8" },
|
{ mnem="jpr imm8" , opcode=0x31, ncycles=2, {"loadImmed","memSaveT","instrSub1"}, {"jmpRelT"}, desc="I+=imm8" },
|
||||||
{ mnem="jnz imm8" , opcode=0x30, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NZ" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if !Zero" },
|
{ mnem="jnz imm8" , opcode=0x30, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NZ" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if !Zero" },
|
||||||
{ mnem="jpz imm8" , opcode=0x32, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0Z" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Zero" },
|
{ mnem="jpz imm8" , opcode=0x32, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0Z" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Zero" },
|
||||||
{ mnem="jlt imm8" , opcode=0x33, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NC" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Carry" },
|
{ mnem="jlt imm8" , opcode=0x33, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NC" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if !Carry" },
|
||||||
{ mnem="jge imm8" , opcode=0x34, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0C" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if !Carry" },
|
{ mnem="jge imm8" , opcode=0x34, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0C" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Carry" },
|
||||||
{ mnem="jle imm8" , opcode=0x35, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0C","instrNext0Z"}, {}, {"jmpRelT"}, {"instrNext"}, desc="I+=imm8 if !Zero&!Carry" },
|
{ mnem="jle imm8" , opcode=0x35, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0C","instrNext0Z"}, {}, {"jmpRelT"}, {"instrNext"}, desc="I+=imm8 if !Zero&!Carry" },
|
||||||
{ mnem="jgt imm8" , opcode=0x36, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0C","instrNext0Z"}, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Zero|Carry" },
|
{ mnem="jgt imm8" , opcode=0x36, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0C","instrNext0Z"}, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Zero|Carry" },
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user