mirror of
https://github.com/g012/l65.git
synced 2025-03-21 04:31:51 +00:00
Started 6502 code.
This commit is contained in:
parent
01a1e5e514
commit
c054cadd1e
118
6502.lua
118
6502.lua
@ -1,3 +1,51 @@
|
||||
local M = {}
|
||||
|
||||
local byte_normalize = function(v)
|
||||
if v < -128 or v > 255 then error("value out of byte range: " .. v) end
|
||||
if v < 0 then v = v + 0x100 end
|
||||
return v & 0xff
|
||||
end
|
||||
local word_normalize = function(v)
|
||||
if v < -32768 or v > 65535 then error("value out of word range: " .. v) end
|
||||
if v < 0 then v = v + 0x10000 end
|
||||
return v & 0xffff
|
||||
end
|
||||
|
||||
local byte_emit = function(v, bin)
|
||||
assert(v >=0 and v <= 0xff)
|
||||
bin[#bin+1] = v
|
||||
end
|
||||
local word_emit = function(v, bin)
|
||||
assert(v >=0 and v <= 0xffff)
|
||||
bin[#bin+1] = 0xff & (v % 0x100)
|
||||
bin[#bin+1] = 0xff & (v // 0x100)
|
||||
end
|
||||
|
||||
M.byte = function(...)
|
||||
local data = {...}
|
||||
for _,v in ipairs(data) do byte_emit(byte_normalize(v)) end
|
||||
end
|
||||
M.word = function(...)
|
||||
local data = {...}
|
||||
for _,v in ipairs(data) do word_emit(word_normalize(v)) end
|
||||
end
|
||||
|
||||
M.section = function(t)
|
||||
local s = {}
|
||||
if (type(t) == 'string') then s.name = t
|
||||
else
|
||||
assert(type(t) == 'table')
|
||||
assert(type(t.name) == 'string' and string.len(t.name) > 0)
|
||||
s = t
|
||||
end
|
||||
s.instructions = {}
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
--[===[
|
||||
|
||||
|
||||
adressing = {
|
||||
imm=0x09, zp=0x05, zpx=0x15, ab=0x0d, abx=0x1d, aby=0x19, inx=0x01, iny=0x11,
|
||||
acc=0x09,
|
||||
@ -11,72 +59,4 @@ encode = {
|
||||
--lda = { imm=0xa9, zp=0xa5, zpx=0xb5, ab=0xad, abx=0xbd, aby=0xb9, inx=0xa1, iny=0xb1 },
|
||||
}
|
||||
|
||||
|
||||
--[=[
|
||||
adressages:
|
||||
lda #10 lda(10) lda"#10"
|
||||
lda 10 lda{10} lda"10"
|
||||
lda 10,x lda{10,"x"} ldax{10} lda{x=10} lda"10,x"
|
||||
lda $1000 lda{0x1000}
|
||||
lda $1000,x lda{0x1000,"x"} ldax{0x1000}
|
||||
lda $1000,y lda{0x1000,"y"} lday{0x1000}
|
||||
lda (10,x) lda{10,"(x)"} lda_x{10} a=(10,x) a=mem[zp[10+x]] lda"(10,x)"
|
||||
lda (10),y lda{10,"(y)"} lda_y{10} a=(10),y a=mem[zp[10]+y] lda"(10),y"
|
||||
|
||||
sta 10 sta{10}
|
||||
sta 10,x sta{10,"x"}
|
||||
sta $1000 sta{0x1000}
|
||||
sta $1000,x sta{0x1000,"x"}
|
||||
sta $1000,y sta{0x1000,"y"}
|
||||
sta (10,x) sta{10,"(x)"}
|
||||
sta (10),y sta{10,"(y)"}
|
||||
]=]
|
||||
|
||||
local function setfenv(fn, env)
|
||||
local i = 1
|
||||
while true do
|
||||
local name = debug.getupvalue(fn, i)
|
||||
if name == "_ENV" then
|
||||
debug.upvaluejoin(fn, i, (function() return env end), 1)
|
||||
break
|
||||
elseif not name then break end
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
return fn
|
||||
end
|
||||
|
||||
local function getfenv(fn)
|
||||
local i = 1
|
||||
while true do
|
||||
local name, val = debug.getupvalue(fn, i)
|
||||
if name == "_ENV" then return val
|
||||
elseif not name then break end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
asm6502_env = {
|
||||
lda = function(v)
|
||||
emit(0xa9, v)
|
||||
end,
|
||||
}
|
||||
function asm(f, ...)
|
||||
setfenv(f, asm6502_env)
|
||||
f(...)
|
||||
end
|
||||
|
||||
a,x,y = 0,0,0
|
||||
do
|
||||
local regs = { a="a", x="x", y="y" }
|
||||
setmetatable(_G, {
|
||||
__index = function(t,k,v)
|
||||
if regs[k] then assert(loadstring("ld" .. k .. "(" .. v .. ")"))() end
|
||||
return t[k]
|
||||
end,
|
||||
__newindex = function(t,k,v)
|
||||
if regs[k] then assert(loadstring("st" .. k .. "(" .. v .. ")"))() end
|
||||
t[k] = v
|
||||
end,
|
||||
})
|
||||
end
|
||||
]===]
|
||||
|
4
asm.lua
4
asm.lua
@ -13,9 +13,9 @@ xyz = 1 << 2
|
||||
x:f()
|
||||
::lualabel::
|
||||
|
||||
syntax6502_off
|
||||
#pragma syntax6502 off
|
||||
lda = 5 if lda < 6 then print('yep') end
|
||||
syntax6502_on
|
||||
#pragma syntax6502 on
|
||||
|
||||
--@@data samepage byte(1, 2) crosspage byte(3, 4)
|
||||
|
||||
|
129
l65.lua
129
l65.lua
@ -2046,112 +2046,29 @@ local function Format65(ast)
|
||||
return table.concat(out.rope)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
local function splitFilename(name)
|
||||
if name:find(".") then
|
||||
local p, ext = name:match("()%.([^%.]*)$")
|
||||
if p and ext then
|
||||
if #ext == 0 then
|
||||
return name, nil
|
||||
else
|
||||
local filename = name:sub(1,p-1)
|
||||
return filename, ext
|
||||
end
|
||||
else
|
||||
return name, nil
|
||||
end
|
||||
else
|
||||
return name, nil
|
||||
end
|
||||
if #arg ~= 2 then
|
||||
print("Invalid arguments, usage:\nl65 source destination")
|
||||
return
|
||||
end
|
||||
|
||||
if #arg == 1 then
|
||||
local name, ext = splitFilename(arg[1])
|
||||
local outname = name.."_min"
|
||||
if ext then outname = outname.."."..ext end
|
||||
--
|
||||
local inf = io.open(arg[1], 'r')
|
||||
if not inf then
|
||||
print("Failed to open '"..arg[1].."' for reading")
|
||||
return
|
||||
end
|
||||
--
|
||||
local sourceText = inf:read('*all')
|
||||
inf:close()
|
||||
--
|
||||
local st, ast = ParseLua(sourceText)
|
||||
if not st then
|
||||
--we failed to parse the file, show why
|
||||
print(ast)
|
||||
return
|
||||
end
|
||||
--
|
||||
local outf = io.open(outname, 'w')
|
||||
if not outf then
|
||||
print("Failed to open '"..outname.."' for writing")
|
||||
return
|
||||
end
|
||||
--
|
||||
outf:write(Format65(ast))
|
||||
outf:close()
|
||||
--
|
||||
|
||||
elseif #arg == 2 then
|
||||
--keep the user from accidentally overwriting their non-minified file with
|
||||
if arg[1]:find("_min") then
|
||||
print("Did you mix up the argument order?\n"..
|
||||
"Current command will minify '"..arg[1].."' and OVERWRITE '"..arg[2].."' with the results")
|
||||
while true do
|
||||
io.write("Confirm (yes/cancel): ")
|
||||
local msg = io.read('*line')
|
||||
if msg == 'yes' then
|
||||
break
|
||||
elseif msg == 'cancel' then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
local inf = io.open(arg[1], 'r')
|
||||
if not inf then
|
||||
print("Failed to open '"..arg[1].."' for reading")
|
||||
return
|
||||
end
|
||||
--
|
||||
local sourceText = inf:read('*all')
|
||||
inf:close()
|
||||
--
|
||||
local st, ast = ParseLua(sourceText)
|
||||
if not st then
|
||||
--we failed to parse the file, show why
|
||||
print(ast)
|
||||
return
|
||||
end
|
||||
--
|
||||
if arg[1] == arg[2] then
|
||||
print("Are you SURE you want to overwrite the source file?")
|
||||
while true do
|
||||
io.write("Confirm (yes/cancel): ")
|
||||
local msg = io.read('*line')
|
||||
if msg == 'yes' then
|
||||
break
|
||||
elseif msg == 'cancel' then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
local outf = io.open(arg[2], 'w')
|
||||
if not outf then
|
||||
print("Failed to open '"..arg[2].."' for writing")
|
||||
return
|
||||
end
|
||||
--
|
||||
outf:write(Format65(ast))
|
||||
outf:close()
|
||||
--
|
||||
|
||||
else
|
||||
print("Invalid arguments, usage:\nl65 source [destination]")
|
||||
local inf = io.open(arg[1], 'r')
|
||||
if not inf then
|
||||
print("Failed to open '"..arg[1].."' for reading")
|
||||
return
|
||||
end
|
||||
local outf = io.open(arg[2], 'w')
|
||||
if not outf then
|
||||
print("Failed to open '"..arg[2].."' for writing")
|
||||
return
|
||||
end
|
||||
|
||||
local sourceText = inf:read('*all')
|
||||
inf:close()
|
||||
local st, ast = ParseLua(sourceText)
|
||||
if not st then
|
||||
print(ast)
|
||||
return
|
||||
end
|
||||
|
||||
outf:write(Format65(ast))
|
||||
outf:close()
|
||||
|
Loading…
x
Reference in New Issue
Block a user