1
0
mirror of https://github.com/g012/l65.git synced 2024-12-29 16:29:15 +00:00

Tested cross bank stubs generation.

This commit is contained in:
g012 2017-10-03 11:51:36 +02:00
parent 4d6749f1a3
commit 27887f42c6
5 changed files with 80 additions and 36 deletions

View File

@ -224,14 +224,14 @@ M.link = function()
end end end end
end end
table.sort(related_sections, function(a,b) return a[1].size==b[1].size and a[1].id<b[1].id or a[1].size>b[1].size end) table.sort(related_sections, function(a,b) return a.size==b.size and a.id<b.id or a.size>b.size end)
for _,section in ipairs(related_sections) do for _,section in ipairs(related_sections) do if not section.org then
local related,ins = {},table.insert local related,ins = {},table.insert
local function collect(section, offset) local function collect(section_parent, offset)
local relatives = relations[section] local relatives = relations[section_parent]
if relatives then if relatives then
for relative,relative_offset in pairs(relatives) do for relative,relative_offset in pairs(relatives) do
if not related[relative] then if not related[relative] and relative ~= section then
relative_offset = relative_offset + offset relative_offset = relative_offset + offset
related[relative] = relative_offset related[relative] = relative_offset
collect(relative, relative_offset) collect(relative, relative_offset)
@ -240,10 +240,12 @@ M.link = function()
end end
end end
collect(section, 0) collect(section, 0)
local location_start = section.location.start
local position = position_section(section, function(address, waste, cross, lsb) local position = position_section(section, function(address, waste, cross, lsb)
local waste, cross, lsb = 0, 0, 0 local waste, cross, lsb = 0, 0, 0
for section,offset in pairs(related) do for section,offset in pairs(related) do
local nwaste, ncross, nlsb = check_section_position(section, address+offset) local section_address = address + (section.location.start - location_start) + offset
local nwaste, ncross, nlsb = check_section_position(section, section_address)
if not nwaste then return end if not nwaste then return end
waste, cross, lsb = waste+nwaste, cross+ncross, lsb+nlsb waste, cross, lsb = waste+nwaste, cross+ncross, lsb+nlsb
end end
@ -253,12 +255,12 @@ M.link = function()
error("unable to find space for section " .. section.label) error("unable to find space for section " .. section.label)
end end
for section,offset in pairs(related) do for section,offset in pairs(related) do
section.org = position + offset section.org = position + (section.location.start - location_start) + offset
local chunk,chunk_ix = chunk_from_address(section, section.org) local chunk,chunk_ix = chunk_from_address(section, section.org)
chunk_reserve(section, chunk_ix) chunk_reserve(section, chunk_ix)
symbols[section.label] = section.location.rorg(section.org) symbols[section.label] = section.location.rorg(section.org)
end end
end end end
for _,location in ipairs(locations) do for _,location in ipairs(locations) do
local position_independent_sections = location.position_independent_sections local position_independent_sections = location.position_independent_sections
@ -401,7 +403,7 @@ end
M.location = function(start, finish) M.location = function(start, finish)
local location local location
if type(start) ~= 'table' then if type(start) ~= 'table' then
location = { type='location', start=start, finish=finish } location = { start=start, finish=finish }
else else
if start.type == 'location' then if start.type == 'location' then
for _,v in ipairs(locations) do if v == start then for _,v in ipairs(locations) do if v == start then
@ -418,6 +420,7 @@ M.location = function(start, finish)
location.rorg = function(x) return x+offset end location.rorg = function(x) return x+offset end
end end
end end
location.type = 'location'
location.sections = {} location.sections = {}
if not location.rorg then location.rorg = function(x) return x end end if not location.rorg then location.rorg = function(x) return x end end
local size = (location.finish or math.huge) - location.start + 1 local size = (location.finish or math.huge) - location.start + 1
@ -486,10 +489,10 @@ end
-- If offset1 is omitted, -offset2 is used. -- If offset1 is omitted, -offset2 is used.
M.relate = function(section1, section2, offset, offset2) M.relate = function(section1, section2, offset, offset2)
local rel1 = relations[section1] or {} local rel1 = relations[section1] or {}
rel1[section2] = offset2 or offset rel1[section2] = (offset2 or offset) or 0
relations[section1] = rel1 relations[section1] = rel1
local rel2 = relations[section2] or {} local rel2 = relations[section2] or {}
rel2[section1] = offset2 and offset rel2[section1] = (offset2 and offset) or -rel1[section2]
relations[section2] = rel2 relations[section2] = rel2
section1.related = true section1.related = true
section2.related = true section2.related = true
@ -508,6 +511,7 @@ M.label = function(name)
end end
if symbols[name] then error("duplicate symbol: " .. name) end if symbols[name] then error("duplicate symbol: " .. name) end
symbols[name] = label symbols[name] = label
label.label = name
label.size = function() label.size = function()
offset = section.size offset = section.size
label.size = 0 label.size = 0
@ -558,6 +562,14 @@ M.sleep = function(cycles, noillegal)
for i=1,cycles/2 do nopimp() end for i=1,cycles/2 do nopimp() end
end end
local op_resolve = function(v)
if type(v) == 'function' then v=v() end
if type(v) == 'table' and v.label then v = symbols[v.label] end
if type(v) == 'string' then v = symbols[v] end
if type(v) ~= 'number' then error("unresolved symbol: " .. tostring(v)) end
return v
end
local size_ref = function(v) local size_ref = function(v)
if type(v) == 'string' then v=symbols[v] end if type(v) == 'string' then v=symbols[v] end
if type(v) == 'table' and v.type == 'label' then v.section.refcount = 1 + (v.section.refcount or 0) end if type(v) == 'table' and v.type == 'label' then v.section.refcount = 1 + (v.section.refcount or 0) end
@ -572,7 +584,7 @@ local size_dc = function(v)
end end
local size_op = function(late, early) local size_op = function(late, early)
if type(late) == 'function' then if type(late) == 'function' then
local r,x = M.pcall(late, early or 0) local r,x = M.pcall(late, early or 0, op_resolve)
if not r or not x then return late,early end if not r or not x then return late,early end
late=x early=nil late=x early=nil
end end
@ -769,7 +781,7 @@ op = function(code, cycles, extra_on_crosspage)
end end
local op_eval = function(late, early) local op_eval = function(late, early)
local x = early or 0 local x = early or 0
return type(late) == 'function' and late(x) or x+late return type(late) == 'function' and late(x,op_resolve) or x+op_resolve(late)
end end
local op_eval_byte = function(late, early) return byte_normalize(op_eval(late, early)) end local op_eval_byte = function(late, early) return byte_normalize(op_eval(late, early)) end
local op_eval_word = function(late, early) return word_normalize(op_eval(late, early)) end local op_eval_word = function(late, early) return word_normalize(op_eval(late, early)) end
@ -845,7 +857,7 @@ for k,_ in pairs(opzab) do
local abs = opabs[k] local abs = opabs[k]
local ins = { cycles=abs.cycles } local ins = { cycles=abs.cycles }
ins.size = function() local l65dbg=l65dbg ins.size = function() local l65dbg=l65dbg
local r,x = M.pcall_za(late, early or 0) local r,x = M.pcall_za(op_eval, late, early)
if not r then return 3 end if not r then return 3 end
size_ref(x) size_ref(x)
x = word_normalize(x) x = word_normalize(x)
@ -861,9 +873,9 @@ for k,_ in pairs(opzab) do
return 3 return 3
end end
ins.bin = function() local l65dbg=l65dbg ins.bin = function() local l65dbg=l65dbg
local x = word_normalize(late(early or 0)) local x = word_normalize(op_eval(late, early))
-- since we assumed absolute on link phase, we must generate absolute in binary -- since we assumed absolute on link phase, we must generate absolute in binary
if x <= 0xff and opzpg[k] then io.stderr:write("warning: forcing abs on zpg operand for opcode " .. k) end if x <= 0xff and opzpg[k] then io.stderr:write("warning: forcing abs on zpg operand for opcode " .. k .. "\n") end
return { abs.opc, x&0xff, x>>8 } return { abs.opc, x&0xff, x>>8 }
end end
table.insert(M.section_current.instructions, ins) table.insert(M.section_current.instructions, ins)
@ -913,7 +925,7 @@ for k,_ in pairs(opzax) do
local abx = opabx[k] local abx = opabx[k]
local ins = { cycles=abx.cycles } local ins = { cycles=abx.cycles }
ins.size = function() local l65dbg=l65dbg ins.size = function() local l65dbg=l65dbg
local r,x = M.pcall_za(late, early or 0) local r,x = M.pcall_za(op_eval, late, early)
if not r then return 3 end if not r then return 3 end
size_ref(x) size_ref(x)
x = word_normalize(x) x = word_normalize(x)
@ -929,9 +941,9 @@ for k,_ in pairs(opzax) do
return 3 return 3
end end
ins.bin = function() local l65dbg=l65dbg ins.bin = function() local l65dbg=l65dbg
local x = word_normalize(late(early or 0)) local x = word_normalize(op_eval(late, early))
-- since we assumed absolute on link phase, we must generate absolute in binary -- since we assumed absolute on link phase, we must generate absolute in binary
if x <= 0xff and opzpx[k] then io.stderr:write("warning: forcing abx on zpx operand for opcode " .. k) end if x <= 0xff and opzpx[k] then io.stderr:write("warning: forcing abx on zpx operand for opcode " .. k .. "\n") end
return { abx.opc, x&0xff, x>>8 } return { abx.opc, x&0xff, x>>8 }
end end
table.insert(M.section_current.instructions, ins) table.insert(M.section_current.instructions, ins)
@ -980,7 +992,7 @@ for k,_ in pairs(opzay) do
local aby = opaby[k] local aby = opaby[k]
local ins = { cycles=aby.cycles } local ins = { cycles=aby.cycles }
ins.size = function() local l65dbg=l65dbg ins.size = function() local l65dbg=l65dbg
local r,x = M.pcall_za(late, early or 0) local r,x = M.pcall_za(op_eval, late, early)
if not r then return 3 end if not r then return 3 end
size_ref(x) size_ref(x)
x = word_normalize(x) x = word_normalize(x)
@ -996,9 +1008,9 @@ for k,_ in pairs(opzay) do
return 3 return 3
end end
ins.bin = function() local l65dbg=l65dbg ins.bin = function() local l65dbg=l65dbg
local x = word_normalize(late(early or 0)) local x = word_normalize(op_eval(late, early))
-- since we assumed absolute on link phase, we must generate absolute in binary -- since we assumed absolute on link phase, we must generate absolute in binary
if x <= 0xff and opzpy[k] then io.stderr:write("warning: forcing aby on zpy operand for opcode " .. k) end if x <= 0xff and opzpy[k] then io.stderr:write("warning: forcing aby on zpy operand for opcode " .. k .. "\n") end
return { aby.opc, x&0xff, x>>8 } return { aby.opc, x&0xff, x>>8 }
end end
table.insert(M.section_current.instructions, ins) table.insert(M.section_current.instructions, ins)

21
l65.lua
View File

@ -1270,15 +1270,18 @@ local function ParseLua(src, src_name)
end end
end end
elseif #args > 0 and ( (encapsulate and not inverse_encapsulate) or (not encapsulate and inverse_encapsulate) ) and not no_encapsulation[args[1].AstType] then elseif #args > 0 and ( (encapsulate and not inverse_encapsulate) or (not encapsulate and inverse_encapsulate) ) and not no_encapsulation[args[1].AstType] then
-- opcode arguments of type (late, early), where only late is to be encapsulated with a _o parameter to be set to early and added to late -- opcode arguments of type (late, early), where only late is to be encapsulated with _o parameter to be set to early and added to _f(late)
local inner_call_scope = CreateScope(op_var.Variable.Scope) local inner_call_scope = CreateScope(op_var.Variable.Scope)
local fvarexpr = {
AstType='VarExpr', Name='_f', Variable={ Name='_f', Scope=CreateScope(inner_call_scope) }, Tokens = { t('Ident', '_f') }
}
local inner_add = { local inner_add = {
AstType='BinopExpr', Op='+', OperatorPrecedence=10, Tokens={ t('Symbol', '+') }, AstType='BinopExpr', Op='+', OperatorPrecedence=10, Tokens={ t('Symbol', '+') },
Lhs = { Lhs = {
AstType='VarExpr', Name='_o', Variable={ IsGlobal=false, Name='_o', Scope=inner_call_scope }, Tokens={ t('Ident', '_o', {space}) } AstType='VarExpr', Name='_o', Variable={ IsGlobal=false, Name='_o', Scope=inner_call_scope }, Tokens={ t('Ident', '_o', {space}) }
}, },
Rhs = { Rhs = {
AstType='Parentheses', Inner=args[1], Tokens={ t('Symbol', '('), t('Symbol', ')') } AstType = 'CallExpr', Base = fvarexpr, Arguments = {args[1]}, Tokens = { t('Symbol', '('), t('Symbol', ')') }
} }
} }
local inner_call_body = { local inner_call_body = {
@ -1288,8 +1291,11 @@ local function ParseLua(src, src_name)
} }
local inner_call = { local inner_call = {
AstType='Function', VarArg=false, IsLocal=true, Scope=inner_call_scope, Body=inner_call_body, AstType='Function', VarArg=false, IsLocal=true, Scope=inner_call_scope, Body=inner_call_body,
Arguments={ { IsGlobal=false, Name='_o', Scope=inner_call_scope } }, Arguments={
Tokens={ t('Keyword', 'function'), t('Symbol', '('), t('Ident', '_o'), t('Symbol', ')'), t('Keyword', 'end', {space}) } { IsGlobal=false, Name='_o', Scope=inner_call_scope },
{ IsGlobal=false, Name='_f', Scope=inner_call_scope },
},
Tokens={ t('Keyword', 'function'), t('Symbol', '('), t('Ident', '_o'), t('Symbol', ','), t('Ident', '_f'), t('Symbol', ')'), t('Keyword', 'end', {space}) }
} }
args[1] = inner_call args[1] = inner_call
end end
@ -2505,12 +2511,15 @@ l65.msghandler = function(msg)
if line:find("in local 'late'") then break end if line:find("in local 'late'") then break end
table.insert(lines, line) table.insert(lines, line)
end end
print(table.concat(lines,'\n')) lines = table.concat(lines,'\n')
lines = lines:gsub("^%s*\r?\n$", '')
io.stderr:write(lines .. '\n')
end end
local trace = v.trace:match(".-\n(.*)\n.-'xpcall'") local trace = v.trace:match(".-\n(.*)\n.-'xpcall'")
trace = trace:gsub('%[string "(.-%.l65)"%]', '%1') trace = trace:gsub('%[string "(.-%.l65)"%]', '%1')
trace = trace:gsub('stack traceback:', '') trace = trace:gsub('stack traceback:', '')
print(trace) trace = trace:gsub("^%s*\r?\n$", '')
io.stderr:write(trace .. '\n')
os.exit(-2) os.exit(-2)
end end
j = j + 1 j = j + 1

View File

@ -9,7 +9,8 @@ end
init() init()
@_frame @_frame
overscan() vblank() screen(kernel) jmp _frame overscan() vblank() screen(kernel) jmp _frame
;
; -- needed if last instruction is implied
writebin(filename..'.bin') writebin(filename..'.bin')
writesym(filename..'.sym') writesym(filename..'.sym')
print(stats) print(stats)

19
samples/vcs2.l65 Normal file
View File

@ -0,0 +1,19 @@
require'vcs'
mappers.F4()
local bank_core,bank_fx = rom0,rom1
location(bank_fx)
@@kernel
ldx#0xd0 @_loop sta WSYNC stx COLUBK dex bne _loop rts
location(bank_core)
@@main
init()
@_frame
overscan() vblank() screen_begin() far(kernel) screen_end() jmp _frame
;
writebin(filename..'.bin')
writesym(filename..'.sym')
print(stats)

17
vcs.l65
View File

@ -186,16 +186,19 @@ screen = function(f) screen_begin() if f then f() end screen_end() end
-- call an asm function into another bank and generate the stubs if needed -- call an asm function into another bank and generate the stubs if needed
local far_stubs = {} far_stubs=far_stubs local far_stubs = {} far_stubs=far_stubs
local far = function(dst) local far = function(dst)
dst.section.refcount = dst.section.refcount + 1
local stub,loc_src,loc_dst = far_stubs[dst],location_current,dst.section.location local stub,loc_src,loc_dst = far_stubs[dst],location_current,dst.section.location
if not (stub and stub.stub_caller.location==loc_src and stub.stub_callee.location==loc_dst) then if not (stub and stub[loc_src]) then
local seccur = section_current local seccur = section_current
local stub_caller = section() switchrom(loc_dst.rom) skip(6) rts local stub_caller = section() switchrom(loc_dst.rom) skip(6) rts
location(loc_dst) location(loc_dst)
local stub_callee = section() jsr dst switchrom(loc_src.rom) local stub_callee = section() jsr dst switchrom(loc_src.rom)
section(seccur) section(seccur)
far_stubs[dst] = relate(stub_caller, stub_callee, 3) relate(stub_caller, stub_callee, 3)
if not stub then far_stubs[dst] = {} end
far_stubs[dst][loc_src] = stub_caller
end end
jsr stub_caller jsr far_stubs[dst][loc_src]
end end
mappers = {} mappers = {}
@ -213,7 +216,7 @@ end
local bank_stubs = function(irq, count, hotspot, entry) local bank_stubs = function(irq, count, hotspot, entry)
function switchrom(i) assert(i>=0 and i<count) bit 0x1000+hotspot+i end function switchrom(i) assert(i>=0 and i<count) bit 0x1000+hotspot+i end
far = far _ENV.far = far
local base = 0x10000 - (count << 12) local base = 0x10000 - (count << 12)
for bi=0,count-1 do for bi=0,count-1 do
local o = base+(bi<<12) local o = base+(bi<<12)
@ -298,7 +301,7 @@ local bank_stubs2 = function(irq, hotspot0, hotspot1)
elseif i==1 then bit hotspot1 elseif i==1 then bit hotspot1
else error("invalid rom index: " .. i) end else error("invalid rom index: " .. i) end
end end
far = far _ENV.far = far
local base = 0xe000 local base = 0xe000
for bi=0,1 do for bi=0,1 do
local o = base+(bi<<12) local o = base+(bi<<12)
@ -311,7 +314,7 @@ mappers.UA = function(irq) bank_stubs2(irq, 0x220, 0x240) end
mappers['0840'] = function(irq) bank_stubs2(irq, 0x800, 0x840) end mappers['0840'] = function(irq) bank_stubs2(irq, 0x800, 0x840) end
mappers.SB = function(count, irq) mappers.SB = function(count, irq)
function switchrom(i) assert(i>=0 and i<count) bit 0x800+i end function switchrom(i) assert(i>=0 and i<count) bit 0x800+i end
far = far _ENV.far = far
for bi=0,count-1 do for bi=0,count-1 do
local o = bi*0x1000 + 0x1000 local o = bi*0x1000 + 0x1000
_ENV['rom' .. bi] = location{o, o+0xfff, rorg=0xf000} _ENV['rom' .. bi] = location{o, o+0xfff, rorg=0xf000}
@ -342,7 +345,7 @@ end
mappers.X07 = function(irq) mappers.X07 = function(irq)
function switchrom(i) assert(i>=0 and i<16) bit 0x80b+(i<<4) end function switchrom(i) assert(i>=0 and i<16) bit 0x80b+(i<<4) end
far = far _ENV.far = far
-- map TIA also to 0x40-0x7F: use VSYNC for bank 14, and VSYNC2 for bank 15 -- map TIA also to 0x40-0x7F: use VSYNC for bank 14, and VSYNC2 for bank 15
vcs.VSYNC2=0x40 cpu.symbols.VSYNC2=0x40 vcs.VSYNC2=0x40 cpu.symbols.VSYNC2=0x40
for bi=0,count-1 do for bi=0,count-1 do