mirror of
https://github.com/g012/l65.git
synced 2024-09-29 16:55:13 +00:00
First attempt to add k65 style syntax.
This commit is contained in:
parent
378667685d
commit
7eabbe80a6
1
6502.lua
1
6502.lua
@ -277,6 +277,7 @@ M.location = function(start, finish)
|
|||||||
end
|
end
|
||||||
location.start = start[1]
|
location.start = start[1]
|
||||||
location.finish = start[2]
|
location.finish = start[2]
|
||||||
|
location.name = start.name
|
||||||
location.rorg = start.rorg
|
location.rorg = start.rorg
|
||||||
if type(location.rorg) == 'number' then
|
if type(location.rorg) == 'number' then
|
||||||
local offset = location.rorg - location.start
|
local offset = location.rorg - location.start
|
||||||
|
86
l65.lua
86
l65.lua
@ -54,6 +54,7 @@ local Keywords_6502 = {
|
|||||||
'lax', 'rla', 'rra', 'sax', 'sbx', 'sha', 'shs', 'shx',
|
'lax', 'rla', 'rra', 'sax', 'sbx', 'sha', 'shs', 'shx',
|
||||||
'shy', 'slo', 'sre',
|
'shy', 'slo', 'sre',
|
||||||
}
|
}
|
||||||
|
local Registers_6502 = { a=8, x=8, y=8 }
|
||||||
|
|
||||||
local syntax6502_on
|
local syntax6502_on
|
||||||
local function syntax6502(on)
|
local function syntax6502(on)
|
||||||
@ -64,6 +65,11 @@ local function syntax6502(on)
|
|||||||
end
|
end
|
||||||
syntax6502(true)
|
syntax6502(true)
|
||||||
|
|
||||||
|
local syntax6502k_on
|
||||||
|
local function syntax6502k(on)
|
||||||
|
syntax6502k_on = on
|
||||||
|
end
|
||||||
|
|
||||||
local opcode_arg_encapsulate_on
|
local opcode_arg_encapsulate_on
|
||||||
local function opcode_arg_encapsulate(on)
|
local function opcode_arg_encapsulate(on)
|
||||||
opcode_arg_encapsulate_on = not opcode_arg_encapsulate_on
|
opcode_arg_encapsulate_on = not opcode_arg_encapsulate_on
|
||||||
@ -257,6 +263,15 @@ local function LexLua(src)
|
|||||||
repeat get() c = peek() until not (UpperChars[c] or LowerChars[c] or Digits[c] or c == '_')
|
repeat get() c = peek() until not (UpperChars[c] or LowerChars[c] or Digits[c] or c == '_')
|
||||||
return src:sub(start, p-1)
|
return src:sub(start, p-1)
|
||||||
end
|
end
|
||||||
|
local function peek_ident(i, spaces)
|
||||||
|
if not spaces then spaces = Spaces end
|
||||||
|
local c
|
||||||
|
while true do c=peek(i) if not spaces[c] then break end i=i+1 end
|
||||||
|
if not (UpperChars[c] or LowerChars[c] or c == '_') then return end
|
||||||
|
local start = p+i
|
||||||
|
repeat i=i+1 c = peek(i) until not (UpperChars[c] or LowerChars[c] or Digits[c] or c == '_')
|
||||||
|
return src:sub(start, p+i-1),i,c
|
||||||
|
end
|
||||||
|
|
||||||
--shared stuff
|
--shared stuff
|
||||||
local function generateError(err)
|
local function generateError(err)
|
||||||
@ -454,6 +469,9 @@ local function LexLua(src)
|
|||||||
if dat == 'syntax6502' then
|
if dat == 'syntax6502' then
|
||||||
onoff(syntax6502)
|
onoff(syntax6502)
|
||||||
toEmit = {Type = 'Symbol', Data = ';'}
|
toEmit = {Type = 'Symbol', Data = ';'}
|
||||||
|
elseif dat == 'syntax6502k' then
|
||||||
|
onoff(syntax6502k)
|
||||||
|
toEmit = {Type = 'Symbol', Data = ';'}
|
||||||
elseif dat == 'encapsulate' then
|
elseif dat == 'encapsulate' then
|
||||||
onoff(function() end)
|
onoff(function() end)
|
||||||
toEmit = {Type = 'Keyword', Data = 'encapsulate_' .. opt}
|
toEmit = {Type = 'Keyword', Data = 'encapsulate_' .. opt}
|
||||||
@ -476,7 +494,35 @@ local function LexLua(src)
|
|||||||
if Keywords[dat] then
|
if Keywords[dat] then
|
||||||
toEmit = {Type = 'Keyword', Data = dat}
|
toEmit = {Type = 'Keyword', Data = dat}
|
||||||
else
|
else
|
||||||
toEmit = {Type = 'Ident', Data = dat}
|
if syntax6502k_on then
|
||||||
|
local i=0
|
||||||
|
while true do c=peek(i) if not Spaces[c] then break end i=i+1 end
|
||||||
|
if c == '=' then
|
||||||
|
local idents,ident = {dat}
|
||||||
|
repeat
|
||||||
|
i = i+1
|
||||||
|
ident,i,c = peek_ident(i)
|
||||||
|
if not ident then break end
|
||||||
|
table.insert(idents, ident)
|
||||||
|
until c ~= '='
|
||||||
|
local reg = idents[#idents]
|
||||||
|
if Registers_6502[reg] then
|
||||||
|
-- list of assignements ends with =a, =x, or =y
|
||||||
|
get_n(i)
|
||||||
|
-- TODO find a=expr, emit lda expr
|
||||||
|
local st = 'st'..reg
|
||||||
|
idents[#idents] = nil
|
||||||
|
toEmit = {}
|
||||||
|
for k,v in ipairs(idents) do
|
||||||
|
table.insert(toEmit, { Type='Keyword', Data=st })
|
||||||
|
table.insert(toEmit, { Type='Ident', Data=v })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not toEmit then
|
||||||
|
toEmit = {Type = 'Ident', Data = dat}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif Digits[c] or (peek() == '.' and Digits[peek(1)]) then
|
elseif Digits[c] or (peek() == '.' and Digits[peek(1)]) then
|
||||||
@ -594,21 +640,33 @@ local function LexLua(src)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--add the emitted symbol, after adding some common data
|
if toEmit[1] then
|
||||||
toEmit.LeadingWhite = leading -- table of leading whitespace/comments
|
toEmit[1].LeadingWhite = leading
|
||||||
--for k, tok in pairs(leading) do
|
for k,v in ipairs(toEmit) do
|
||||||
-- tokens[#tokens + 1] = tok
|
v.Line = thisLine
|
||||||
--end
|
v.Char = thisChar
|
||||||
|
v.Print = function()
|
||||||
|
return "<"..(v.Type..string.rep(' ', 7-#v.Type)).." "..(v.Data or '').." >"
|
||||||
|
end
|
||||||
|
tokens[#tokens+1] = v
|
||||||
|
end
|
||||||
|
else
|
||||||
|
--add the emitted symbol, after adding some common data
|
||||||
|
toEmit.LeadingWhite = leading -- table of leading whitespace/comments
|
||||||
|
--for k, tok in pairs(leading) do
|
||||||
|
-- tokens[#tokens + 1] = tok
|
||||||
|
--end
|
||||||
|
|
||||||
toEmit.Line = thisLine
|
toEmit.Line = thisLine
|
||||||
toEmit.Char = thisChar
|
toEmit.Char = thisChar
|
||||||
toEmit.Print = function()
|
toEmit.Print = function()
|
||||||
return "<"..(toEmit.Type..string.rep(' ', 7-#toEmit.Type)).." "..(toEmit.Data or '').." >"
|
return "<"..(toEmit.Type..string.rep(' ', 7-#toEmit.Type)).." "..(toEmit.Data or '').." >"
|
||||||
|
end
|
||||||
|
tokens[#tokens+1] = toEmit
|
||||||
|
|
||||||
|
--halt after eof has been emitted
|
||||||
|
if toEmit.Type == 'Eof' then break end
|
||||||
end
|
end
|
||||||
tokens[#tokens+1] = toEmit
|
|
||||||
|
|
||||||
--halt after eof has been emitted
|
|
||||||
if toEmit.Type == 'Eof' then break end
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
if not st then
|
if not st then
|
||||||
|
35
samples/vcs1k.l65
Normal file
35
samples/vcs1k.l65
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
require'vcs'
|
||||||
|
|
||||||
|
#pragma syntax6502k on
|
||||||
|
|
||||||
|
TIM_OVERSCAN = 50 -- TIM64T, 3200 cycles = ~ 42 scanlines
|
||||||
|
TIM_VBLANK = 61 -- TIM64T, 3904 cycles = ~ 51 scanlines
|
||||||
|
TIM_KERNEL = 17 -- T1024T, 17408 cycles = ~229 scanlines
|
||||||
|
|
||||||
|
location(0xf000, 0xffff)
|
||||||
|
|
||||||
|
section{'vectors', org=0xfffc} dc.w start,start
|
||||||
|
|
||||||
|
local kernel = function()
|
||||||
|
ldx#0xd0 @_loop sta WSYNC stx COLUBK dex bne _loop
|
||||||
|
end
|
||||||
|
|
||||||
|
local wait = function() local l=label() lda INTIM bne l end
|
||||||
|
|
||||||
|
@@start
|
||||||
|
-- clear zeropage
|
||||||
|
cld ldx#0 txa @_clear dex tsx pha bne _clear
|
||||||
|
@main
|
||||||
|
-- overscan
|
||||||
|
WSYNC=a lda#2 VBLANK=a lda#TIM_OVERSCAN sta TIM64T wait()
|
||||||
|
-- vblank
|
||||||
|
lda#0b1110 @_vsync sta WSYNC sta VSYNC lsr bne _vsync
|
||||||
|
lda#2 sta VBLANK lda#TIM_VBLANK sta TIM64T wait() sta WSYNC sta VBLANK
|
||||||
|
-- kernel
|
||||||
|
lda#TIM_KERNEL sta T1024T kernel() wait()
|
||||||
|
jmp main
|
||||||
|
|
||||||
|
local filename=string.match(arg[0], ".-([^\\/]-)%.?[^%.\\/]*$")
|
||||||
|
writebin(filename..'.bin')
|
||||||
|
writesym(filename..'.sym')
|
||||||
|
print(stats)
|
5
vcs.lua
5
vcs.lua
@ -83,3 +83,8 @@ do
|
|||||||
local symbols = cpu.symbols
|
local symbols = cpu.symbols
|
||||||
for k,v in pairs(vcs) do symbols[k] = v end
|
for k,v in pairs(vcs) do symbols[k] = v end
|
||||||
end
|
end
|
||||||
|
-- forbid globals of same key as system address constants
|
||||||
|
cpu.__newindex = function(t,k,v)
|
||||||
|
if vcs[k] then error("attempt to modify read only symbol " .. k) end
|
||||||
|
rawset(t,k,v)
|
||||||
|
end
|
||||||
|
45
vcs_test.l65
45
vcs_test.l65
@ -1,45 +0,0 @@
|
|||||||
dofile "vcs.lua"
|
|
||||||
|
|
||||||
TIM_OVERSCAN = 50 -- TIM64T, 3200 cycles = ~ 42 scanlines
|
|
||||||
TIM_VBLANK = 61 -- TIM64T, 3904 cycles = ~ 51 scanlines
|
|
||||||
TIM_KERNEL = 17 -- T1024T, 17408 cycles = ~229 scanlines
|
|
||||||
|
|
||||||
location(0xf000, 0xffff)
|
|
||||||
|
|
||||||
section waitForIntim
|
|
||||||
lda INTIM
|
|
||||||
bne waitForIntim
|
|
||||||
rts
|
|
||||||
|
|
||||||
-- alternate syntax
|
|
||||||
section waitForIntim
|
|
||||||
{ a=INTIM }!=
|
|
||||||
rts
|
|
||||||
|
|
||||||
section waitForIntim
|
|
||||||
repeat a=INTIM until N
|
|
||||||
@{ a=INTIM }~0
|
|
||||||
rts
|
|
||||||
|
|
||||||
-- interop: generate stubs at fixed addresses
|
|
||||||
-- stub(0xff10, waitForIntim[, altname])
|
|
||||||
-- and dumps all generated code/data into opaque data
|
|
||||||
|
|
||||||
function inca() asm("clc; adc #0") end
|
|
||||||
section "testMacro" {
|
|
||||||
lda #0
|
|
||||||
inca()
|
|
||||||
}
|
|
||||||
=>
|
|
||||||
section("testMacro")
|
|
||||||
label("testMacro")
|
|
||||||
lda{imm=0}
|
|
||||||
inca()
|
|
||||||
=>
|
|
||||||
clc()
|
|
||||||
adc{imm=0}
|
|
||||||
endsection()
|
|
||||||
|
|
||||||
|
|
||||||
require_ "6502-def"
|
|
||||||
|
|
57
vcs_test.lua
57
vcs_test.lua
@ -1,57 +0,0 @@
|
|||||||
dofile "vcs.lua"
|
|
||||||
|
|
||||||
TIM_OVERSCAN = 50 -- TIM64T, 3200 cycles = ~ 42 scanlines
|
|
||||||
TIM_VBLANK = 61 -- TIM64T, 3904 cycles = ~ 51 scanlines
|
|
||||||
TIM_KERNEL = 17 -- T1024T, 17408 cycles = ~229 scanlines
|
|
||||||
|
|
||||||
location(0xf000, 0xffff)
|
|
||||||
|
|
||||||
section "waitForIntim"
|
|
||||||
-- n_{ a=INTIM } ?
|
|
||||||
lda(INTIM) -- or a=INTIM
|
|
||||||
bne "waitForIntim"
|
|
||||||
rts
|
|
||||||
|
|
||||||
section "doOverscan"
|
|
||||||
sta{WSYNC} -- WSYNC=a
|
|
||||||
lda(2) sta{VBLANK} -- a=2 VBLANK=a
|
|
||||||
lda(TIM_OVERSCAN) sta{TIM64T} -- a=TIM_OVERSCAN TIM64T=a
|
|
||||||
jsr "waitForIntim"
|
|
||||||
|
|
||||||
section "doVBlank"
|
|
||||||
lda(0x0e)
|
|
||||||
label ".vsyncLoop"
|
|
||||||
sta{WSYNC}
|
|
||||||
sta{VSYNC}
|
|
||||||
lsr()
|
|
||||||
bne ".vsyncLoop"
|
|
||||||
lda(2)
|
|
||||||
sta{VBLANK}
|
|
||||||
lda(TIM_VBLANK)
|
|
||||||
sta{TIM64T}
|
|
||||||
jsr "waitForIntim"
|
|
||||||
|
|
||||||
section "doKernel"
|
|
||||||
lda(TIM_KERNEL)
|
|
||||||
sta{T1024T}
|
|
||||||
jsr "waitForIntim"
|
|
||||||
|
|
||||||
section "start"
|
|
||||||
-- clear zeropage
|
|
||||||
cld()
|
|
||||||
ldx(0)
|
|
||||||
txa()
|
|
||||||
label ".clearLoop"
|
|
||||||
dex()
|
|
||||||
tsx()
|
|
||||||
pha()
|
|
||||||
bne ".clearLoop"
|
|
||||||
-- main
|
|
||||||
label "mainLoop"
|
|
||||||
jsr "doOverscan"
|
|
||||||
jsr "doVBlank"
|
|
||||||
jsr "doKernel"
|
|
||||||
jmp "mainLoop"
|
|
||||||
|
|
||||||
section{ name="vectors", org=0xfffc }
|
|
||||||
word{ "start", "start" }
|
|
Loading…
Reference in New Issue
Block a user