From ded021ee9932c47f905e7847a91edf776ddde8b1 Mon Sep 17 00:00:00 2001 From: Redo Date: Wed, 26 Oct 2022 20:30:33 -0600 Subject: [PATCH] add dasm and braces --- assembler-8608.lua | 132 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 109 insertions(+), 23 deletions(-) diff --git a/assembler-8608.lua b/assembler-8608.lua index 3c8ce14..78ecad9 100644 --- a/assembler-8608.lua +++ b/assembler-8608.lua @@ -1,4 +1,6 @@ +local arch8608 = require("rom-8608-defs") + local function trim(s) return s:gsub("^ +", ""):gsub(" +$", "").."" end local function validWordsFromInstrs(instrs) local words = {} @@ -12,9 +14,9 @@ end local function decodeNumber(n) n = trim(n) 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), (#n-1)/2 - elseif n:sub(1, 2)=="0x" then return sign*tonumber(n:sub(3, #n ), 16), (#n-2)/2 - elseif n:sub(#n, #n)=="h" then return sign*tonumber(n:sub(1, #n-1), 16), (#n-1)/2 + if n:sub(1, 1)=="$" then return sign*tonumber(n:sub(2, #n ), 16), 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(#n, #n)=="h" then return sign*tonumber(n:sub(1, #n-1), 16), math.ceil((#n-1)/2) else local v = tonumber(n) or error("invalid number "..n) if v>=-128 and v<=255 then return v, 1 @@ -50,7 +52,7 @@ local function mnemFromLine(line, instrs, validWords) end local function addByte(state, val) assert(val>=-128 and val<=255, "invalid byte "..val) - assert(not state.memory[state.curAddr], "overwriting memory at "..state.curAddr) + assert(state.memory[state.curAddr]==nil, "overwriting memory at "..state.curAddr) state.memory[state.curAddr] = val%256 state.curAddr = state.curAddr + 1 end @@ -59,6 +61,13 @@ local function addWord(state, val) addByte(state, math.floor(val/256)) addByte(state, val%256) end +local function addSpace(state, len) + for i = 1, len do + assert(state.memory[state.curAddr]==nil, "overwriting memory at "..state.curAddr) + state.memory[state.curAddr] = false + state.curAddr = state.curAddr + 1 + end +end local function assembleInstruction(line, state, instrs, validWords) local mnem, imms = mnemFromLine(line, instrs, validWords) local opcode = instrs[mnem] or error("invalid instruction "..line.." (mnem "..mnem..")") @@ -66,7 +75,7 @@ local function assembleInstruction(line, state, instrs, validWords) local padlen = 0 if type(opcode)=="function" then padlen, writeimms = opcode(imms) - state.curAddr = state.curAddr + padlen + addSpace(state, padlen) elseif opcode>=0 then addByte(state, opcode) end @@ -175,8 +184,10 @@ local function preprocessCode(code) end local function fixCode(code) code = code:gsub(",", " ") + code = code:gsub(":([^\\/])", ":\n%1") code = code:gsub("%]", " %] ") code = code:gsub("%[", " %[ ") + code = code:gsub("%*", " %* ") code = code:gsub("\n[ \t\r\n]*", "\n") code = code:gsub(" +", " ") return code @@ -194,6 +205,8 @@ local function prefixCode(code, fn) -- fix strings, add line numbers local lastbracelabel = 0 local function bracelabel() lastbracelabel = lastbracelabel+1; return "_BRACE_"..lastbracelabel.."_"; end local bracestack = {} + local bracehasmid = {} + local lastnl = false out(".ln 1"); out("\n"); for i = 1, #code do @@ -202,18 +215,29 @@ local function prefixCode(code, fn) -- fix strings, add line numbers if c=="\r" then elseif c=="\n" then linenum = linenum+1 - if skipnl then out("\\") - else out("\n") out(".ln "..linenum) out("\n") end - skipnl = false - elseif c=="\t" or c==" " then out(" ") - elseif c=="#" or c==";" or c=="/" then state = "comment" - elseif c=="\"" then state = "string" - elseif c:find("^[a-zA-Z0-9_%.:%$%(%)%*,%[%]]$") then out(c) - elseif c=="\\" then skipnl = true + if skipnl then out("\\"); skipnl = false; + else out("\n") out(".ln "..linenum); out("\n"); end + lastnl = true + elseif c=="\t" or c==" " then out(" ") + elseif c=="#" or c==";" or c=="/" then state = "comment" + elseif c=="\"" then state = "string" lastnl = false + elseif c=="\\" then skipnl = true + elseif c:find("^[a-zA-Z0-9_%.:%$%(%)%*,%[%]]$") then out(c) lastnl = false elseif c=="{" then + table.insert(bracestack, bracelabel()) + if not lastnl then out(bracestack[#bracestack].."MID") out("\n") end + out(bracestack[#bracestack].."START:") out("\n") elseif c=="}" then - + if not lastnl then out(bracestack[#bracestack].."START") out("\n") end + out(bracestack[#bracestack].."END:") out("\n") + if not bracehasmid[#bracestack] then out(bracestack[#bracestack].."MID:") out("\n") end + bracehasmid[#bracestack] = nil + bracestack[#bracestack] = nil + elseif c=="|" then + if not lastnl then out(bracestack[#bracestack].."END") out("\n") end + out(bracestack[#bracestack].."MID:") out("\n") + bracehasmid[#bracestack] = true else error("invalid char "..c) end elseif state=="comment" then if c=="\n" then state = "code" out("\n") end @@ -225,7 +249,8 @@ local function prefixCode(code, fn) -- fix strings, add line numbers out(stringEscapes[c] or error("invalid escape "..c)); state = "string"; end end - return table.concat(outt) + local code2 = table.concat(outt) + return code2 end local function includeFile(fn) fn = fn:gsub("\\", "/") @@ -238,7 +263,7 @@ local function includeFile(fn) return code end local function instrsFromArch(arch) - local function arraySize(imms) local s = 1; for i = 1, #imms do s = s*imms[i].val end; return s; end + local function arraySize(imms) local s = 1; for i = 1, #imms do s = s*(imms[i].val or error("invalid array size")) end; return s; end local instrs = { imm8 = function() return 0, true end, imm16 = function() return 0, true end, @@ -253,22 +278,78 @@ local function instrsFromArch(arch) } for _, instr in ipairs(arch.instructions) do if instr.mnem then - instrs[instr.mnem] = instr.opcode + local mnem = instr.mnem + mnem = mnem:gsub("%*([^ ])", "%* %1") + instrs[mnem] = instr.opcode end end return instrs end -local function assembleFile(fn) +local function assembleFile(fn, arch) local code = includeFile(fn) code = preprocessCode(code) code = fixCode(code) - local arch = require("rom-8608-defs") local instrs = instrsFromArch(arch) local mem = assembleCode(code, instrs) return mem end +local function mnemsFromArch(arch) + local mnems = {} + for _, instr in ipairs(arch.instructions) do + if instr.mnem then + mnems[instr.opcode] = instr.mnem + end + end + return mnems +end +local function disassembleMemory(mem, arch) + local mnems = mnemsFromArch(arch) + local addr = 0 + local function nextByte() local b = mem[addr]; addr = addr+1; return b; end + local lastaddr = 0 + while addr<=0xFFFF do + local opcode = nextByte() + if opcode then + local line = {} + local mnem = mnems[opcode] or "???" + table.insert(line, trim(mnem:gsub("imm[0-9]+", ""))) + local tlen = 1 + for lens in mnem:gmatch("imm([0-9]+)") do local len = tonumber(lens)/8 + if len==1 then + table.insert(line, "$"..string.format("%02X", nextByte() or 0)) + elseif len==2 then + table.insert(line, "$"..string.format("%04X", (nextByte() or 0)*256 + (nextByte() or 0))) + else error("invalid imm len") end + tlen = tlen + len + end + local lineb = {} + for i = addr-tlen, addr-1 do + table.insert(lineb, string.format("%02X", mem[i] or 0)) + end + local lb = table.concat(lineb, " ") + if lastaddr~=addr-tlen then print("...") end + print(string.format("%04X", addr-tlen).." | "..(" "):rep(9-#lb)..lb.." | "..table.concat(line, " ")) + lastaddr = addr + end + end + print() +end +local function memToHex(hex) + local mem = {} + local addr = 0 + for d in hex:gmatch("[0-9a-fA-F][0-9a-fA-F]") do + mem[addr] = tonumber(d, 16) + addr = addr+1 + end + return mem +end +local function disassembleHex(hex, arch) + disassembleMemory(memToHex(hex), arch) +end + local function printMemory(mem) + local anynonempty = false local lastbase = -16 for base = 0, 0xFFF0, 16 do local line = { string.format("%04X", base), " | " } @@ -285,8 +366,11 @@ local function printMemory(mem) if base ~= lastbase+16 then print("...") end print(table.concat(line)) lastbase = base + anynonempty = true end end + if not anynonempty then print("Memory empty") end + print() end local ts = ts or { @@ -322,21 +406,23 @@ local function buildMemory(mem, romsize, offset, len) local pow = math.pow(2, z%8) local data = (addr>=offset and ((not len) or addr0 then assert(#romsize==3, "incorrect rom size") end buildMemory(mem, romsize, offset, len) + disassembleMemory(mem, arch) end ts.eval [[ function AssembleFile(%fn, %romsize, %offset, %len) { luacall("AssembleFile", %fn, %romsize, %offset, %len); } ]] -if arg then AssembleFile(arg[1] or "programs/keyboard.asm", "16 16 8", "0", "256") end +if arg then AssembleFile(arg[1] or "../8608programs/keyboard.asm", "16 16 8", "0", "256") end