mirror of
https://github.com/g012/l65.git
synced 2025-02-19 05:30:31 +00:00
Added related sections constraint.
This commit is contained in:
parent
40bd38aa7c
commit
4d6749f1a3
31
.travis.yml
31
.travis.yml
@ -1,10 +1,21 @@
|
||||
language: c
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
script:
|
||||
- cmake . -DCMAKE_BUILD_TYPE=Release
|
||||
- make
|
||||
language: c
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
script:
|
||||
- cmake . -DCMAKE_BUILD_TYPE=Release
|
||||
- make
|
||||
- ./l65 samples/vcs0.l65
|
||||
- ./l65 samples/vcs1.l65
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: MhH11SvqA5SCbxBbIPpT4lupbkZitK+4N5nKj0HZMBejVnY78bpePJ20pdIDGZQ+bUkZP8NEfLxrIsIheRuvS7nFOXehqAFmZhC3qA7LNrgColC2jISLrzipuG9fS1M8cYdGk11imYEZIx1RrpLAdGrMSR1dx+c44Fwzs271r2t2gchgcFlUvJiAUl9Fy5bEsX95jCJF4N8ozss3oBs7coFfuGBeC9AcFahekDsRrJh8oUA1VmP+pHukgronhDz9gqVAKNSrIR7/gZjOLVXU9e/rdmFUbO6WeYBlgDF85Jqzw0KI+O9pORfcRcxb+tXqLcECQJX0s4fyS/AdObr5lMov6NCT1Z6krkxrlko6ahHc5ZgZIkEcC9RNnmGfj+1ZPspCphiQfgUd7Z4KDLK6bqIGBFQlfPQHtz8BDW8tLTxLC3heSMzu5FI8i9lBxQKQa6+mifE1kmmj2v60TndocJ4YWb3diSBYWrQYFCI1pwcE5JerffP4mF9OL42oXsQbi9dqtnc3aqEPR5C4BUSoQtzknrm4UFjPCl8dPX2mpkXaRemcpn3Xi/ANx5VOdy5EfIQ10jkg/TkdRHr+YqrfW4fHEn5lKhhNrf1l2jDg30BPJ/3D7lW5wOuaHezDUzVUdXPVO0cxj2ap6nj88WHx66+ySAPZK0/wF2XVnTkEHM0=
|
||||
file: l65
|
||||
skip_cleanup: true
|
||||
on:
|
||||
repo: g012/l65
|
||||
tags: true
|
||||
|
167
6502.lua
167
6502.lua
@ -3,6 +3,7 @@ local M = {}
|
||||
local symbols={} M.symbols=symbols
|
||||
local locations={} M.locations=locations
|
||||
local sections={} M.sections=sections
|
||||
local relations={} M.relations=relations
|
||||
local stats={} M.stats=stats setmetatable(stats, stats)
|
||||
|
||||
M.strip = true -- set to false to disable dead stripping of relocatable sections
|
||||
@ -75,12 +76,53 @@ M.link = function()
|
||||
for i=chunk_ix,chunk_ix+#new_chunks-1 do ins(chunks, i, new_chunks[i-chunk_ix+1]) end
|
||||
end
|
||||
|
||||
local chunk_from_address = function(section, address)
|
||||
local chunks,rorg = section.location.chunks,section.location.rorg
|
||||
for i,chunk in ipairs(chunks) do
|
||||
if address >= chunk.start and address+section.size <= chunk.start+chunk.size then
|
||||
return chunk,i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local check_section_position = function(section, address, chunk)
|
||||
local chunk = chunk_from_address(section, address)
|
||||
if not chunk then return end
|
||||
local rorg = section.location.rorg
|
||||
if section.align then
|
||||
local raddress = rorg(address)
|
||||
if section.offset then raddress = raddress - section.offset end
|
||||
if raddress % section.align ~= 0 then return end
|
||||
end
|
||||
for _,constraint in ipairs(section.constraints) do
|
||||
local cstart, cfinish = address+constraint.start, address+constraint.finish
|
||||
if rorg(cstart) // 0x100 == rorg(cfinish) // 0x100 then
|
||||
if constraint.type == 'crosspage' then return end
|
||||
else
|
||||
if constraint.type == 'samepage' then return end
|
||||
end
|
||||
end
|
||||
local address_end = address+section.size
|
||||
local waste = math.min(address - chunk.start, chunk.size - (address_end - chunk.start))
|
||||
local raddress,raddress_end = rorg(address),rorg(address_end)
|
||||
local align,cross=0x100,0
|
||||
repeat
|
||||
local cross_count = (raddress_end+align-1)//align - (raddress+align-1)//align
|
||||
if raddress&(align-1) == 0 then cross_count=cross_count+1 end
|
||||
cross = cross + align * align * cross_count
|
||||
align = align>>1
|
||||
until align==1
|
||||
local lsb=0
|
||||
for i=0,15 do if raddress&(1<<i) == 0 then lsb=lsb+1 else break end end
|
||||
return waste, cross, lsb
|
||||
end
|
||||
|
||||
local position_section = function(section, constrain)
|
||||
local location = section.location
|
||||
local chunks,rorg = location.chunks,location.rorg
|
||||
table.sort(chunks, function(a,b) return a.size==b.size and a.id<b.id or a.size<b.size end)
|
||||
for chunk_ix,chunk in ipairs(chunks) do if chunk.size >= section.size then
|
||||
local waste,position,position_end = math.maxinteger
|
||||
local waste,cross,lsb,position = math.maxinteger,math.maxinteger,math.maxinteger
|
||||
local usage_lowest = function(start, finish)
|
||||
local inc=1
|
||||
if section.align then
|
||||
@ -91,40 +133,24 @@ M.link = function()
|
||||
inc = section.align
|
||||
end
|
||||
for address=start,finish,inc do
|
||||
for _,constraint in ipairs(section.constraints) do
|
||||
local cstart, cfinish = address+constraint.start, address+constraint.finish
|
||||
if rorg(cstart) // 0x100 == rorg(cfinish) // 0x100 then
|
||||
if constraint.type == 'crosspage' then goto constraints_not_met end
|
||||
else
|
||||
if constraint.type == 'samepage' then goto constraints_not_met end
|
||||
local nwaste, ncross, nlsb = check_section_position(section, address, chunk)
|
||||
if nwaste then
|
||||
if constrain then
|
||||
nwaste, ncross, nlsb = constrain(address, nwaste, ncross, nlsb)
|
||||
if not nwaste then goto skip end
|
||||
end
|
||||
if nwaste > waste then goto skip end
|
||||
if nwaste == waste then
|
||||
-- if waste is the same, keep the one that uses the least amount of aligned addresses
|
||||
if ncross > cross then goto skip end
|
||||
if ncross == cross then
|
||||
-- if cross count is same, take the one with the most set LSB count (eg. select 11 over 10)
|
||||
if nlsb > lsb then goto skip end
|
||||
end
|
||||
end
|
||||
position,waste,cross,lsb = address,nwaste,ncross,nlsb
|
||||
::skip::
|
||||
end
|
||||
local address_end = address+section.size
|
||||
local w = math.min(address - chunk.start, chunk.size - (address_end - chunk.start))
|
||||
if w > waste then goto constraints_not_met end
|
||||
if w==waste then
|
||||
local rposition,rposition_end = rorg(position),rorg(position_end)
|
||||
local raddress,raddress_end = rorg(address),rorg(address_end)
|
||||
-- if waste is the same, keep the one that uses the least amount of aligned addresses
|
||||
local align=0x100
|
||||
repeat
|
||||
local cross_count_cur = (rposition_end+align-1)//align - (rposition+align-1)//align
|
||||
if rposition&(align-1) == 0 then cross_count_cur=cross_count_cur+1 end
|
||||
local cross_count_new = (raddress_end+align-1)//align - (raddress+align-1)//align
|
||||
if raddress&(align-1) == 0 then cross_count_new=cross_count_new+1 end
|
||||
if cross_count_new < cross_count_cur then goto select_pos end
|
||||
align = align>>1
|
||||
until align==1
|
||||
-- if cross count is same, take the one with the most set LSB count (eg. select 11 over 10)
|
||||
local lsb_cur,lsb_new=0,0
|
||||
for i=0,15 do if rposition&(1<<i) == 0 then lsb_cur=lsb_cur+1 else break end end
|
||||
for i=0,15 do if raddress&(1<<i) == 0 then lsb_new=lsb_new+1 else break end end
|
||||
if lsb_cur <= lsb_new then goto constraints_not_met end
|
||||
end
|
||||
::select_pos::
|
||||
if constrain and not constrain(address) then goto constraints_not_met end
|
||||
waste=w position=address position_end=address_end
|
||||
::constraints_not_met::
|
||||
end
|
||||
end
|
||||
local finish = math.min(chunk.start + 0xff, chunk.start + chunk.size - section.size)
|
||||
@ -144,10 +170,10 @@ M.link = function()
|
||||
end end
|
||||
end
|
||||
|
||||
local sibling_sections = {}
|
||||
stats.used = 0
|
||||
stats.unused = 0
|
||||
stats.cycles = 0
|
||||
local related_sections = {}
|
||||
for _,location in ipairs(locations) do
|
||||
local sections,rorg = location.sections,location.rorg
|
||||
|
||||
@ -166,8 +192,8 @@ M.link = function()
|
||||
if M.strip and not section.refcount and not section.strong then
|
||||
sections[ix]=nil
|
||||
table.insert(symbols_to_remove, section.label)
|
||||
elseif section.siblings then
|
||||
table.insert(sibling_sections, section)
|
||||
elseif section.related then
|
||||
table.insert(related_sections, section)
|
||||
else
|
||||
table.insert(position_independent_sections, section)
|
||||
end
|
||||
@ -197,24 +223,43 @@ M.link = function()
|
||||
::chunk_located::
|
||||
end end
|
||||
end
|
||||
--[[
|
||||
for _,section in ipairs(sibling_sections) do
|
||||
local sections = section.siblings
|
||||
table.insert(sections, section)
|
||||
-- biggest of all siblings first
|
||||
table.sort(sections, function(a,b) return a.size==b.size and a.id<b.id or a.size>b.size end)
|
||||
end
|
||||
table.sort(sibling_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)
|
||||
for _,section in ipairs(sibling_sections) do
|
||||
local siblings = section.siblings
|
||||
local relate = section.relate or function(sibling, siblings)
|
||||
|
||||
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)
|
||||
for _,section in ipairs(related_sections) do
|
||||
local related,ins = {},table.insert
|
||||
local function collect(section, offset)
|
||||
local relatives = relations[section]
|
||||
if relatives then
|
||||
for relative,relative_offset in pairs(relatives) do
|
||||
if not related[relative] then
|
||||
relative_offset = relative_offset + offset
|
||||
related[relative] = relative_offset
|
||||
collect(relative, relative_offset)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for _,sibling in siblings do
|
||||
if not relate(sibling, siblings) then goto not_suitable end
|
||||
collect(section, 0)
|
||||
local position = position_section(section, function(address, waste, cross, lsb)
|
||||
local waste, cross, lsb = 0, 0, 0
|
||||
for section,offset in pairs(related) do
|
||||
local nwaste, ncross, nlsb = check_section_position(section, address+offset)
|
||||
if not nwaste then return end
|
||||
waste, cross, lsb = waste+nwaste, cross+ncross, lsb+nlsb
|
||||
end
|
||||
return waste, cross, lsb
|
||||
end)
|
||||
if not position then
|
||||
error("unable to find space for section " .. section.label)
|
||||
end
|
||||
for section,offset in pairs(related) do
|
||||
section.org = position + offset
|
||||
local chunk,chunk_ix = chunk_from_address(section, section.org)
|
||||
chunk_reserve(section, chunk_ix)
|
||||
symbols[section.label] = section.location.rorg(section.org)
|
||||
end
|
||||
::not_suitable::
|
||||
end
|
||||
]]
|
||||
|
||||
for _,location in ipairs(locations) do
|
||||
local position_independent_sections = location.position_independent_sections
|
||||
table.sort(position_independent_sections, function(a,b) return a.size==b.size and a.label>b.label or a.size>b.size end)
|
||||
@ -373,7 +418,7 @@ M.location = function(start, finish)
|
||||
location.rorg = function(x) return x+offset end
|
||||
end
|
||||
end
|
||||
location.sections = {} -- TODO remove
|
||||
location.sections = {}
|
||||
if not location.rorg then location.rorg = function(x) return x end end
|
||||
local size = (location.finish or math.huge) - location.start + 1
|
||||
location.chunks={ { id=id(), start=location.start, size=size } }
|
||||
@ -398,7 +443,7 @@ M.section = function(t)
|
||||
section=t name=t[1] or 'S'..id() section[1]=nil
|
||||
if section.offset and not section.align then error("section " .. name .. " has offset, but no align") end
|
||||
end
|
||||
table.insert(M.location_current.sections, section) -- TODO remove
|
||||
table.insert(M.location_current.sections, section)
|
||||
table.insert(M.sections, section)
|
||||
section.location = M.location_current
|
||||
M.section_current = section
|
||||
@ -434,6 +479,22 @@ M.section = function(t)
|
||||
return section
|
||||
end
|
||||
|
||||
-- relate(section1, section2 [, [offset1,] offset2])
|
||||
-- Add a position relationship between 'section1' and 'section2', with 'offset1'
|
||||
-- bytes from selected position for 'section2', and 'offset2' bytes from selec-
|
||||
-- -ted positon for 'section1'.
|
||||
-- If offset1 is omitted, -offset2 is used.
|
||||
M.relate = function(section1, section2, offset, offset2)
|
||||
local rel1 = relations[section1] or {}
|
||||
rel1[section2] = offset2 or offset
|
||||
relations[section1] = rel1
|
||||
local rel2 = relations[section2] or {}
|
||||
rel2[section1] = offset2 and offset
|
||||
relations[section2] = rel2
|
||||
section1.related = true
|
||||
section2.related = true
|
||||
end
|
||||
|
||||
M.label = function(name)
|
||||
local label,offset
|
||||
local section,rorg = M.section_current,M.location_current.rorg
|
||||
|
@ -9,7 +9,16 @@ location(0xf000, 0xffff)
|
||||
section{'vectors', org=0xfffc} dc.w start,start
|
||||
|
||||
local kernel = function()
|
||||
ldx#0xd0 @_loop sta WSYNC stx COLUBK dex bne _loop
|
||||
-- add a dummy instruction to collect cycle count and binary size
|
||||
local kernel_cycles,kernel_size
|
||||
table.insert(section_current.instructions, { bin=function() kernel_cycles=cycles kernel_size=size end })
|
||||
|
||||
samepage
|
||||
ldx#0xd0 @_loop sta WSYNC stx COLUBK dex bne _loop
|
||||
end
|
||||
|
||||
-- and get the delta (cycles are counted without taking any branch)
|
||||
table.insert(section_current.instructions, { bin=function() print('kernel cycles: ', cycles-kernel_cycles, 'kernel size: ', size-kernel_size) end })
|
||||
end
|
||||
|
||||
local wait = function() local l=label() lda INTIM bne l end
|
||||
|
Loading…
x
Reference in New Issue
Block a user