mirror of https://github.com/g012/l65.git
commit
5105f8bd8d
|
@ -9,6 +9,7 @@ script:
|
|||
- cmake . -DCMAKE_BUILD_TYPE=Release
|
||||
- make
|
||||
- cd samples; for f in *.l65; do echo $f; ../l65 $f || break; done; cd ..
|
||||
- cd samples; for f in *.l7801; do echo $f; ../l7801 $f || break; done; cd ..
|
||||
- cp l65 l65-$TRAVIS_TAG-$TRAVIS_OS_NAME
|
||||
deploy:
|
||||
provider: releases
|
||||
|
|
|
@ -80,6 +80,7 @@ set(L65_HEADERS
|
|||
|
||||
file(GLOB L65_FILES ${L65_SOURCE_DIR}/*.l65)
|
||||
set(L65_SCRIPTS
|
||||
${L65_SOURCE_DIR}/asm.lua
|
||||
${L65_SOURCE_DIR}/6502.lua
|
||||
${L65_SOURCE_DIR}/dkjson.lua
|
||||
${L65_SOURCE_DIR}/l65.lua
|
||||
|
@ -116,3 +117,42 @@ endif()
|
|||
|
||||
target_link_libraries(embed ${LINKLIBS})
|
||||
target_link_libraries(${PROJECT_NAME} ${LINKLIBS})
|
||||
|
||||
set(L7801_SOURCES
|
||||
${L65_SOURCE_DIR}/lfs.c
|
||||
${L65_SOURCE_DIR}/lpeg.c
|
||||
${L65_SOURCE_DIR}/l7801.c
|
||||
)
|
||||
set(L7801_HEADERS
|
||||
${L65_HEADERS}
|
||||
)
|
||||
|
||||
set(L7801_FILES ${L65_SOURCE_DIR}/scv.l7801)
|
||||
|
||||
set(L7801_SCRIPTS
|
||||
${L65_SOURCE_DIR}/asm.lua
|
||||
${L65_SOURCE_DIR}/uPD7801.lua
|
||||
${L65_SOURCE_DIR}/dkjson.lua
|
||||
${L65_SOURCE_DIR}/l7801.lua
|
||||
${L65_BINARY_DIR}/l65cfg.lua
|
||||
${L65_SOURCE_DIR}/re.lua
|
||||
${L7801_FILES}
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${L65_BINARY_DIR}/scripts_7801.h
|
||||
COMMAND embed -o ${L65_BINARY_DIR}/scripts_7801.h ${L7801_SCRIPTS}
|
||||
DEPENDS embed ${L7801_SCRIPTS}
|
||||
)
|
||||
add_custom_target(prereq_7801 DEPENDS ${L65_BINARY_DIR}/scripts_7801.h)
|
||||
add_executable(l7801 ${L7801_SOURCES} ${L7801_HEADERS} ${L7801_FILES})
|
||||
add_dependencies(l7801 prereq_7801)
|
||||
set_property(TARGET l7801 PROPERTY C_STANDARD 99)
|
||||
target_include_directories(l7801 PRIVATE "${L7801_SOURCE_DIR}" "${L65_BINARY_DIR}")
|
||||
target_link_libraries(l7801 ${LINKLIBS})
|
||||
|
||||
|
||||
install(TARGETS l65 l7801
|
||||
RUNTIME DESTINATION bin)
|
||||
install(DIRECTORY samples DESTINATION doc)
|
||||
install(FILES README.md DESTINATION doc)
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
version: '0.1.{build}'
|
||||
|
||||
os: Visual Studio 2013
|
||||
platform: x64
|
||||
configuration: Release
|
||||
|
||||
before_build:
|
||||
- mkdir install
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake -G "Visual Studio 12 2013 Win64" -DCMAKE_INSTALL_PREFIX=../install ..
|
||||
|
||||
build_script:
|
||||
- FOR /F "tokens=*" %%i in ('git describe') do SET COMMITNOW=%%i
|
||||
- if defined APPVEYOR_REPO_TAG_NAME (set L65_RELEASE=true) else (set L65_SNAPSHOT=true)
|
||||
- if defined L65_RELEASE set L65_VERSION=%APPVEYOR_REPO_TAG_NAME:~1%
|
||||
- if defined L65_RELEASE echo Building l65 %L65_VERSION%... (from %COMMITNOW%)
|
||||
- if defined L65_SNAPSHOT set L65_VERSION=%APPVEYOR_BUILD_VERSION%
|
||||
- if defined L65_SNAPSHOT echo Building l65 snapshot %L65_VERSION%... (from %COMMITNOW%)
|
||||
- cmake --build . --config Release
|
||||
- cmake --build . --config Release --target install
|
||||
|
||||
after_build:
|
||||
- cd ../install
|
||||
- 7z a ../l65.zip * -tzip
|
||||
|
||||
artifacts:
|
||||
- path: l65.zip
|
||||
name: l65-${L65_VERSION}.zip
|
||||
|
||||
deploy:
|
||||
- provider: GitHub
|
||||
release: l65-${L65_VERSION}
|
||||
description: 'l65 msvc12 win64 build'
|
||||
auth_token:
|
||||
secure: xRIravp3mvMiAgogn6KGuK1yrolmSJUsum/wPXwu82bh97O7YkuQ3B178ac+WHml
|
||||
artifact: /l65.*\.zip/
|
||||
draft: true
|
||||
on:
|
||||
appveyor_repo_tag: true
|
||||
push_release: true
|
|
@ -0,0 +1,826 @@
|
|||
local M = {}
|
||||
|
||||
local symbols,symbolsorg={},{} M.symbols,M.symbolsorg=symbols,symbolsorg
|
||||
local locations={} M.locations=locations
|
||||
local sections={} M.sections=sections
|
||||
local relations={} M.relations=relations
|
||||
local stats={} M.stats=stats setmetatable(stats, stats)
|
||||
|
||||
local before_link={} M.before_link=before_link
|
||||
|
||||
M.strip = true -- set to false to disable dead stripping of relocatable sections
|
||||
M.strip_empty = false -- set to true to strip empty sections: their label will then not resolve
|
||||
M.pcall = pcall -- set to empty function returning false to disable eval during compute_size()
|
||||
-- set to pcall directly if you want to keep ldazab/x/y eval during compute_size() even if
|
||||
-- disabled for other parts (required to distinguish automatically between zp/abs addressing)
|
||||
M.pcall_za = function(...) return M.pcall(...) end
|
||||
|
||||
M.__index = M
|
||||
M.__newindex = function(t,k,v)
|
||||
local kk = k
|
||||
if type(k) == 'string' and k:sub(1,1) == '_' and M.label_current then
|
||||
kk = M.label_current .. k
|
||||
end
|
||||
if symbols[kk] then error("attempt to modify symbol " .. k) end
|
||||
rawset(t,k,v)
|
||||
end
|
||||
symbols.__index = symbols
|
||||
setmetatable(M, symbols)
|
||||
|
||||
local id_ = 0
|
||||
local id = function() id_=id_+1 return id_ end M.id=id
|
||||
|
||||
M.link = function()
|
||||
if stats.unused then return end
|
||||
|
||||
for _,v in ipairs(before_link) do v() end
|
||||
|
||||
if M.strip then
|
||||
symbols.__index = function(tab,key)
|
||||
local val = rawget(symbols, key)
|
||||
if type(val) == 'table' and val.type == 'label' then
|
||||
val.section.refcount = val.section.refcount + 1
|
||||
end
|
||||
return val
|
||||
end
|
||||
end
|
||||
for _,section in ipairs(sections) do
|
||||
section:compute_size()
|
||||
end
|
||||
symbols.__index = symbols
|
||||
|
||||
local chunk_reserve = function(section, chunk_ix)
|
||||
local chunks = section.location.chunks
|
||||
local chunk = chunks[chunk_ix]
|
||||
local holes = section.holes
|
||||
local new_chunks,ins = {},table.insert
|
||||
|
||||
local chunk1 = { id=id(), start=chunk.start, size=section.org-chunk.start }
|
||||
local hole_ix = 1
|
||||
local hole1 = holes[1]
|
||||
if hole1 and hole1.start==0 then
|
||||
chunk1.size = chunk1.size + hole1.size
|
||||
hole_ix = 2
|
||||
end
|
||||
if chunk1.size > 0 then ins(new_chunks, chunk1) end
|
||||
while hole_ix <= #holes do
|
||||
local hole = holes[hole_ix]
|
||||
local chunki = { id=id(), start=section.org+hole.start, size=hole.size }
|
||||
ins(new_chunks, chunki)
|
||||
hole_ix = hole_ix + 1
|
||||
end
|
||||
local chunkl = { id=id(), start=section.org+section.size, size=chunk.start+chunk.size-(section.org+section.size) }
|
||||
local chunkn = new_chunks[#new_chunks]
|
||||
if chunkn and chunkn.start+chunkn.size==chunkl.start then
|
||||
chunkn.size = chunkn.size + chunkl.size
|
||||
elseif chunkl.size > 0 then
|
||||
ins(new_chunks, chunkl)
|
||||
end
|
||||
|
||||
table.remove(chunks, chunk_ix)
|
||||
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) if a.size==b.size then return a.id<b.id end return a.size<b.size end)
|
||||
for chunk_ix,chunk in ipairs(chunks) do if chunk.size >= section.size then
|
||||
local waste,cross,lsb,position = math.maxinteger,math.maxinteger,math.maxinteger
|
||||
local usage_lowest = function(start, finish)
|
||||
local inc=1
|
||||
if section.align then
|
||||
local rstart = rorg(start)
|
||||
local arstart = (rstart + section.align - 1) // section.align * section.align
|
||||
if section.offset then arstart = arstart + section.offset end
|
||||
start = start + arstart-rstart
|
||||
inc = section.align
|
||||
end
|
||||
for address=start,finish,inc do
|
||||
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
|
||||
end
|
||||
end
|
||||
local finish = math.min(chunk.start + 0xff, chunk.start + chunk.size - section.size)
|
||||
usage_lowest(chunk.start, finish)
|
||||
if chunk.size ~= math.huge then
|
||||
local start = math.max(chunk.start + chunk.size - section.size - 0xff, chunk.start)
|
||||
usage_lowest(start, chunk.start + chunk.size - section.size)
|
||||
end
|
||||
if position then
|
||||
section.org = position
|
||||
chunk_reserve(section, chunk_ix)
|
||||
--print(section.label, string.format("%04X\t%d", position, section.size))
|
||||
--for k,v in ipairs(location.chunks) do print(string.format(" %04X %04X %d", v.start, v.size+v.start-1, v.size)) end
|
||||
return position
|
||||
end
|
||||
end end
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
-- filter sections list
|
||||
local position_independent_sections = {}
|
||||
local symbols_to_remove = {}
|
||||
local section_count = #sections
|
||||
location.cycles=0 location.used=0
|
||||
for ix,section in ipairs(sections) do
|
||||
location.cycles = location.cycles + section.cycles
|
||||
location.used = location.used + section.size
|
||||
if section.size == 0 then
|
||||
if M.strip_empty or section.weak then
|
||||
sections[ix]=nil
|
||||
if not section.org then table.insert(symbols_to_remove, section.label) end
|
||||
else
|
||||
section.org = location.start
|
||||
end
|
||||
elseif not section.org then
|
||||
if M.strip and not section.refcount and not section.strong then
|
||||
sections[ix]=nil
|
||||
table.insert(symbols_to_remove, section.label)
|
||||
elseif section.related then
|
||||
table.insert(related_sections, section)
|
||||
else
|
||||
table.insert(position_independent_sections, section)
|
||||
end
|
||||
end
|
||||
end
|
||||
do local j=0 for i=1,section_count do
|
||||
if sections[i] ~= nil then j=j+1 sections[j],sections[i] = sections[i],sections[j] end
|
||||
end end
|
||||
for _,v in ipairs(symbols_to_remove) do symbols[v] = nil end
|
||||
location.position_independent_sections = position_independent_sections
|
||||
stats.cycles = stats.cycles + location.cycles
|
||||
stats.used = stats.used + location.used
|
||||
|
||||
-- fixed position sections
|
||||
for section_ix,section in ipairs(sections) do if section.org then
|
||||
if section.org < location.start or section.org > (location.finish or math.huge) then
|
||||
error("ORG section " .. section.label .. " starts outside container location")
|
||||
end
|
||||
for chunk_ix,chunk in ipairs(location.chunks) do
|
||||
if chunk.start <= section.org and chunk.size - (section.org - chunk.start) >= section.size then
|
||||
chunk_reserve(section, chunk_ix)
|
||||
goto chunk_located
|
||||
end
|
||||
end
|
||||
error("ORG section " .. section.label .. " overflows its location")
|
||||
::chunk_located::
|
||||
end end
|
||||
end
|
||||
|
||||
table.sort(related_sections, function(a,b) if a.size==b.size then return a.id<b.id end return a.size>b.size end)
|
||||
for _,section in ipairs(related_sections) do if not section.org then
|
||||
local related,ins = {},table.insert
|
||||
local function collect(section_parent, offset)
|
||||
local relatives = relations[section_parent]
|
||||
if relatives then
|
||||
for relative,relative_offset in pairs(relatives) do
|
||||
if not related[relative] and relative ~= section then
|
||||
relative_offset = relative_offset + offset
|
||||
related[relative] = relative_offset
|
||||
collect(relative, relative_offset)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
collect(section, 0)
|
||||
local location_start = section.location.start
|
||||
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 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
|
||||
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 + (section.location.start - location_start) + offset
|
||||
local chunk,chunk_ix = chunk_from_address(section, section.org)
|
||||
chunk_reserve(section, chunk_ix)
|
||||
end
|
||||
end end
|
||||
|
||||
for _,location in ipairs(locations) do
|
||||
local position_independent_sections = location.position_independent_sections
|
||||
table.sort(position_independent_sections, function(a,b) if a.size==b.size then return a.label>b.label end return a.size>b.size end)
|
||||
for _,section in ipairs(position_independent_sections) do
|
||||
if not position_section(section) then
|
||||
error("unable to find space for section " .. section.label)
|
||||
end
|
||||
end
|
||||
|
||||
-- unused space stats
|
||||
local unused = 0
|
||||
for _,chunk in ipairs(location.chunks) do
|
||||
if chunk.size ~= math.huge then
|
||||
unused = unused + chunk.size
|
||||
else
|
||||
location.stops_at = chunk.start-1
|
||||
end
|
||||
end
|
||||
location.unused = unused
|
||||
stats.unused = stats.unused + unused
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
M.resolve = function()
|
||||
if stats.resolved_count then return end
|
||||
M.link()
|
||||
|
||||
stats.resolved_count = 0
|
||||
repeat local count = 0
|
||||
for k,v in pairs(symbols) do if k ~= '__index' then
|
||||
local t = type(v)
|
||||
if t == 'function' then v=v() t=type(v) symbols[k]=v count=count+1 end
|
||||
if t == 'table' and type(v.resolve) == 'function' then symbols[k],symbolsorg[k]=v.resolve() count=count+1 end
|
||||
if t == 'string' and symbols[v] then symbols[k]=symbols[v] count=count+1 end
|
||||
stats.resolved_count = stats.resolved_count + count
|
||||
end end until count == 0
|
||||
|
||||
-- set local label references resolver
|
||||
local llresolver = { __index = function(tab,key)
|
||||
if type(key) ~= 'string' or key:sub(1,1) ~= '_' or not M.label_current then return nil end
|
||||
return symbols[M.label_current .. key]
|
||||
end }
|
||||
setmetatable(symbols, llresolver)
|
||||
end
|
||||
|
||||
M.genbin = function(filler)
|
||||
if #locations == 0 then return end
|
||||
if not filler then filler = 0 end -- brk opcode
|
||||
M.resolve()
|
||||
local bin = {}
|
||||
local ins,mov = table.insert,table.move
|
||||
table.sort(locations, function(a,b) return a.start < b.start end)
|
||||
local of0 = locations[1].start
|
||||
local fill
|
||||
for _,location in ipairs(locations) do
|
||||
if location.start < #bin then
|
||||
error(string.format("location [%04x,%04x] overlaps another", location.start, location.finish or location.stops_at))
|
||||
end
|
||||
if fill then for i=#bin+of0,location.start-1 do ins(bin, filler) end end
|
||||
M.size=0 M.cycles=0
|
||||
local sections = location.sections
|
||||
table.sort(sections, function(a,b) return a.org < b.org end)
|
||||
for _,section in ipairs(sections) do
|
||||
for i=#bin+of0,section.org-1 do ins(bin, filler) end
|
||||
local bin_offset = math.min(#bin, section.org-of0)+1
|
||||
for _,instruction in ipairs(section.instructions) do
|
||||
local b,o = instruction.bin
|
||||
if type(b) == 'function' then b,o = b(filler) end
|
||||
if type(b) == 'table' then mov(b,1,#b,bin_offset,bin) bin_offset=bin_offset+#b
|
||||
elseif b then bin[bin_offset]=b bin_offset=bin_offset+1 end
|
||||
if o then
|
||||
bin_offset=bin_offset+o
|
||||
for i=#bin,bin_offset-1 do ins(bin, filler) end
|
||||
end
|
||||
M.size=#bin M.cycles=M.cycles+(instruction.cycles or 0)
|
||||
end
|
||||
end
|
||||
fill = not location.nofill
|
||||
if location.finish and fill then
|
||||
for i=#bin+of0,location.finish do ins(bin, filler) end
|
||||
end
|
||||
end
|
||||
stats.bin_size = #bin
|
||||
return bin
|
||||
end
|
||||
|
||||
M.writebin = function(filename, bin)
|
||||
if not filename then filename = 'main.bin' end
|
||||
if not bin then bin = M.genbin() end
|
||||
local f = assert(io.open(filename, "wb"), "failed to open " .. filename .. " for writing")
|
||||
f:write(string.char(table.unpack(bin)))
|
||||
f:close()
|
||||
end
|
||||
|
||||
-- return a table of entry(address, label)
|
||||
M.getsym = function(entry)
|
||||
local ins = table.insert
|
||||
local s,sym_rev = {},{}
|
||||
for k,v in pairs(symbols) do if type(v) == 'number' then ins(sym_rev,k) end end
|
||||
table.sort(sym_rev, function(a,b) local x,y=symbols[a],symbols[b] if x==y then return a<b end return x<y end)
|
||||
for _,v in ipairs(sym_rev) do
|
||||
local k,vorg=symbols[v],v
|
||||
local u=v:match'.*()_' if u then -- change _ to . in local labels
|
||||
local parent=v:sub(1,u-1) if symbols[parent] then v = parent..'.'..v:sub(u+1) end
|
||||
end
|
||||
local e = entry(k,v,vorg) if e then
|
||||
if type(e) == 'table' then for _,ev in ipairs(e) do ins(s, ev) end
|
||||
else ins(s, e) end
|
||||
end
|
||||
end
|
||||
return s
|
||||
end
|
||||
M.getsym_as = {
|
||||
lua = function() -- .lua
|
||||
local fmt,rep = string.format,string.rep
|
||||
local s = M.getsym(function(a,l) return fmt("%s = 0x%04x", l, a) end)
|
||||
return table.concat(s, '\n')
|
||||
end,
|
||||
dasm = function() -- .sym
|
||||
local fmt,rep = string.format,string.rep
|
||||
local s = M.getsym(function(a,l) return fmt("%s%s %04x", l, rep(' ',24-#l), a) end)
|
||||
table.insert(s, 1, '--- Symbol List')
|
||||
s[#s+1] = '--- End of Symbol List.'
|
||||
return table.concat(s, '\n')
|
||||
end,
|
||||
}
|
||||
-- write a symbol file for debuggers, using specified format (defaults to DASM)
|
||||
M.writesym = function(filename, format)
|
||||
assert(filename)
|
||||
local s = M.getsym_as[format or 'dasm'](filename)
|
||||
if s then
|
||||
local f = assert(io.open(filename, "wb"), "failed to open " .. filename .. " for writing")
|
||||
f:write(s) f:close()
|
||||
end
|
||||
end
|
||||
|
||||
stats.__tostring = function()
|
||||
local s,ins={},table.insert
|
||||
ins(s, " Free Used Size Area")
|
||||
for _,location in ipairs(locations) do
|
||||
local name = (location.name or ''):sub(1,14)
|
||||
name = string.rep(' ', 14-#name) .. name
|
||||
local fmt = "%s %5d %5d %5d [%04X-%04X]"
|
||||
if location.finish then
|
||||
local size = location.finish-location.start+1
|
||||
ins(s, string.format(fmt, name,
|
||||
location.unused, size-location.unused, size, location.start, location.finish))
|
||||
else
|
||||
ins(s, string.format(fmt, name,
|
||||
location.unused, location.used, location.stops_at-location.start+1, location.start, location.stops_at))
|
||||
end
|
||||
end
|
||||
if #locations > 1 then
|
||||
ins(s, string.format(" --- Total --- %5d %5d %5d", stats.unused, stats.used, stats.bin_size))
|
||||
end
|
||||
return table.concat(s, '\n')
|
||||
end
|
||||
|
||||
M.location = function(start, finish)
|
||||
local location
|
||||
if type(start) ~= 'table' then
|
||||
location = { start=start, finish=finish }
|
||||
else
|
||||
if start.type == 'location' then
|
||||
for _,v in ipairs(locations) do if v == start then
|
||||
M.location_current = start
|
||||
return start
|
||||
end end
|
||||
error("unable to find reference to location [" .. (start.start or '?') .. ", " .. (start.finish or '?') .. "]")
|
||||
end
|
||||
location = start
|
||||
location.start = start[1]
|
||||
location.finish = start[2]
|
||||
if type(location.rorg) == 'number' then
|
||||
local offset = location.rorg - location.start
|
||||
location.rorg = function(x) return x+offset end
|
||||
end
|
||||
end
|
||||
location.type = 'location'
|
||||
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 } }
|
||||
locations[#locations+1] = location
|
||||
M.location_current = location
|
||||
return location
|
||||
end
|
||||
|
||||
M.section = function(t)
|
||||
local section = {}
|
||||
local name = t or 'S'..id()
|
||||
if type(name) ~= 'string' then
|
||||
assert(type(t) == 'table', "invalid arguments for section")
|
||||
if t.type == 'section' then
|
||||
for _,v in ipairs(sections) do if v == t then
|
||||
M.location_current = t.location
|
||||
M.section_current = t
|
||||
return t
|
||||
end end
|
||||
error("unable to find reference to section " .. (t.label or '?'))
|
||||
end
|
||||
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)
|
||||
table.insert(M.sections, section)
|
||||
section.location = M.location_current
|
||||
M.section_current = section
|
||||
section.type = 'section'
|
||||
section.id = id()
|
||||
section.constraints = {}
|
||||
section.instructions = {}
|
||||
assert(name:sub(1,1) ~= '_', "sections can't be named with a local label")
|
||||
section.label = M.label(name)
|
||||
section.holes = {}
|
||||
section.refcount = 0
|
||||
function section:compute_size()
|
||||
local instructions = self.instructions
|
||||
self.size=0 self.cycles=0
|
||||
for _,instruction in ipairs(instructions) do
|
||||
instruction.offset = self.size
|
||||
local ins_sz = instruction.size or 0
|
||||
if type(ins_sz) == 'function' then
|
||||
-- evaluation is needed to get the size (distinguish zpg/abs)
|
||||
-- labels and sections are not resolved at this point, so
|
||||
-- evaluation will fail if the size is not explicitly stated (.b/.w);
|
||||
-- in that case, assume max size
|
||||
ins_sz = ins_sz()
|
||||
end
|
||||
self.size = self.size + ins_sz
|
||||
self.cycles = self.cycles + (instruction.cycles or 0)
|
||||
end
|
||||
for _,constraint in ipairs(self.constraints) do
|
||||
constraint.start = instructions[constraint.from].offset
|
||||
constraint.finish = constraint.to==#instructions and self.size or instructions[constraint.to+1].offset
|
||||
end
|
||||
end
|
||||
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)
|
||||
assert(section1.type == 'section', "section1 is not a section")
|
||||
assert(section2.type == 'section', "section2 is not a section")
|
||||
local rel1 = relations[section1] or {}
|
||||
rel1[section2] = (offset2 or offset) or 0
|
||||
relations[section1] = rel1
|
||||
local rel2 = relations[section2] or {}
|
||||
rel2[section1] = (offset2 and offset) or -rel1[section2]
|
||||
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
|
||||
label = { type='label', section=section }
|
||||
if not name then name='_L'..id() end
|
||||
if name:sub(1,1) == '_' then -- local label
|
||||
name = M.label_current .. name
|
||||
else
|
||||
M.label_current = name
|
||||
label.bin = function() M.label_current = name end
|
||||
end
|
||||
if symbols[name] then error("duplicate symbol: " .. name) end
|
||||
symbols[name] = label
|
||||
label.label = name
|
||||
label.size = function()
|
||||
offset = section.size
|
||||
label.size = 0
|
||||
return 0
|
||||
end
|
||||
label.resolve = function()
|
||||
local o = section.org + offset
|
||||
return rorg(o),o
|
||||
end
|
||||
table.insert(section.instructions, label)
|
||||
return name,label
|
||||
end
|
||||
|
||||
M.samepage = function()
|
||||
local section = M.section_current
|
||||
table.insert(section.constraints, { type='samepage', from=#section.instructions+1 })
|
||||
end
|
||||
M.crosspage = function()
|
||||
local section = M.section_current
|
||||
table.insert(section.constraints, { type='crosspage', from=#section.instructions+1 })
|
||||
end
|
||||
M.endpage = function()
|
||||
local section = M.section_current
|
||||
local constraint = section.constraints[#section.constraints]
|
||||
assert(constraint and not constraint.to, "closing constraint, but no constraint is open")
|
||||
constraint.to = #section.instructions
|
||||
end
|
||||
|
||||
-- skip(bytes)
|
||||
-- Insert a hole in the section of 'bytes' bytes, which can be used by other
|
||||
-- relocatable sections.
|
||||
M.skip = function(bytes)
|
||||
local l65dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local ins,section = {},M.section_current
|
||||
ins.size = function()
|
||||
table.insert(section.holes, { start=ins.offset, size=bytes })
|
||||
return bytes
|
||||
end
|
||||
ins.bin = function(filler) return nil,bytes end
|
||||
table.insert(section.instructions, ins)
|
||||
end
|
||||
|
||||
-- sleep(cycles [, noillegal])
|
||||
-- Waste 'cycles' cycles. If 'noillegal' is true, trashes NZ flags.
|
||||
M.sleep = function(cycles, noillegal)
|
||||
assert(cycles > 1, "can't sleep for less than 2 cycles")
|
||||
if cycles & 1 ~= 0 then
|
||||
if noillegal then bitzpg(0) else nopzpg(0) end
|
||||
cycles = cycles - 3
|
||||
end
|
||||
for i=1,cycles/2 do nopimp() 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 M.op_resolve = op_resolve
|
||||
|
||||
local size_ref = function(v)
|
||||
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
|
||||
end
|
||||
M.size_ref = size_ref
|
||||
|
||||
local size_dc = function(v)
|
||||
if type(v) == 'function' then
|
||||
local r,x = M.pcall(v)
|
||||
if not r or not x then return v end
|
||||
end
|
||||
size_ref(v)
|
||||
return v
|
||||
end
|
||||
M.size_dc = size_dc
|
||||
|
||||
local size_op = function(late, early)
|
||||
if type(late) == 'function' then
|
||||
local r,x = M.pcall(late, early or 0, op_resolve)
|
||||
if not r or not x then return late,early end
|
||||
late=x early=nil
|
||||
end
|
||||
size_ref(late) size_ref(early)
|
||||
return late,early
|
||||
end
|
||||
M.size_op = size_op
|
||||
|
||||
local byte_normalize = function(v)
|
||||
if v < -0x80 or v > 0xFF then error("value out of byte range: " .. v) end
|
||||
if v < 0 then v = v + 0x100 end
|
||||
return v & 0xff
|
||||
end
|
||||
M.byte_normalize = byte_normalize
|
||||
|
||||
local word_normalize = function(v)
|
||||
if v < -0x8000 or v > 0xFFFF then error("value out of word range: " .. v) end
|
||||
if v < 0 then v = v + 0x10000 end
|
||||
return v & 0xffff
|
||||
end
|
||||
M.word_normalize = word_normalize
|
||||
|
||||
local long_normalize = function(v)
|
||||
if v < -0x80000000 or v > 0xFFFFFFFF then error("value out of word range: " .. v) end
|
||||
if v < 0 then v = v + 0x100000000 end
|
||||
return v & 0xffffffff
|
||||
end
|
||||
M.long_normalize = long_normalize
|
||||
|
||||
-- charset([s] [, f])
|
||||
-- Set a new charset to be used for next string data in byte().
|
||||
-- Without argument, revert to Lua charset.
|
||||
-- s: string of all letters of charset
|
||||
-- f: letter index offset or function to transform the letter index
|
||||
M.charset = function(s, f)
|
||||
local st = type(s)
|
||||
if st == 'nil' then M.cs = nil return s end
|
||||
if st == 'table' then M.cs = s return s end
|
||||
if not f then f = function(v) return v end
|
||||
elseif type(f) == 'number' then f = function(v) return v + f end end
|
||||
local t,i={},0
|
||||
for c in s:gmatch'.' do local v=i t[c]=function() return f(v) end i=i+1 end
|
||||
M.cs=t
|
||||
return t
|
||||
end
|
||||
|
||||
M.byte_impl = function(args, nrm)
|
||||
local l65dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local data,cs = {},M.cs
|
||||
for k,v in ipairs(args) do
|
||||
local t = type(v)
|
||||
if t == 'number' or t == 'function' then data[#data+1] = v
|
||||
elseif t == 'table' then table.move(v,1,#v,#data+1,data)
|
||||
elseif t == 'string' then
|
||||
if cs then
|
||||
for c in v:gmatch'.' do
|
||||
local i=cs[c]
|
||||
if not i then error("character " .. c .. " is not part of current charset") end
|
||||
data[#data+1]=i
|
||||
end
|
||||
else
|
||||
local s = {v:byte(1,#v)}
|
||||
table.move(s, 1, #s, #data+1, data)
|
||||
end
|
||||
else error("unsupported type for byte() argument: " .. t .. ", value: " .. v)
|
||||
end
|
||||
end
|
||||
local size = function()
|
||||
for i,v in ipairs(data) do data[i] = size_dc(v) end
|
||||
return #data
|
||||
end
|
||||
local bin = function() local l65dbg=l65dbg
|
||||
local b={}
|
||||
for k,v in ipairs(data) do
|
||||
if type(v) == 'function' then v = v() end
|
||||
local vt = type(v)
|
||||
if vt == 'table' and v.label then v = symbols[v.label]
|
||||
elseif vt == 'string' then v = symbols[v] end
|
||||
if type(v) ~= 'number' then error("unresolved symbol for dc.b, index " .. k) end
|
||||
b[#b+1] = nrm(v)
|
||||
end
|
||||
return b
|
||||
end
|
||||
table.insert(M.section_current.instructions, { data=data, size=size, bin=bin })
|
||||
end
|
||||
-- byte(...)
|
||||
-- Declare bytes to go into the binary stream.
|
||||
-- Each argument can be either:
|
||||
-- * a number resolving to a valid range byte
|
||||
-- * a string, converted to bytes using the charset previously defined,
|
||||
-- or Lua's charset if none was defined
|
||||
-- * a table, with each entry resolving to a valid range byte
|
||||
-- * a function, resolving to exactly one valid range byte, evaluated
|
||||
-- after symbols have been resolved
|
||||
M.byte = function(...)
|
||||
return M.byte_impl({...}, byte_normalize)
|
||||
end
|
||||
local byte_encapsulate = function(args)
|
||||
for k,v in ipairs(args) do
|
||||
local vt = type(v)
|
||||
if vt == 'string' or vt == 'table' and (v.type == 'section' or v.type == 'label') then
|
||||
args[k] = function() return v end
|
||||
end
|
||||
end
|
||||
return args
|
||||
end
|
||||
M.byte_hi = function(...)
|
||||
return M.byte_impl(byte_encapsulate{...}, function(v) return (v>>8)&0xff end)
|
||||
end
|
||||
M.byte_lo = function(...)
|
||||
return M.byte_impl(byte_encapsulate{...}, function(v) return v&0xff end)
|
||||
end
|
||||
|
||||
-- word(...)
|
||||
-- Declare words to go into the binary stream.
|
||||
-- Each argument can be either:
|
||||
-- * a section or a label
|
||||
-- * a number resolving to a valid range word
|
||||
-- * a table, with each entry resolving to a valid range word
|
||||
-- * a function, resolving to exactly one valid range word, evaluated
|
||||
-- after symbols have been resolved
|
||||
M.word = function(...)
|
||||
local l65dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local args = {...}
|
||||
local data = {}
|
||||
for k,v in ipairs(args) do
|
||||
local t = type(v)
|
||||
if t == 'number' or t == 'function' or t == 'string' then data[#data+1] = v
|
||||
elseif t == 'table' then
|
||||
if v.type == 'section' or v.type == 'label' then data[#data+1] = function() return v end
|
||||
else table.move(v,1,#v,#data+1,data) end
|
||||
else error("unsupported type for word() argument: " .. t .. ", value: " .. v)
|
||||
end
|
||||
end
|
||||
local size = function()
|
||||
for i,v in ipairs(data) do data[i] = size_dc(v) end
|
||||
return #data*2
|
||||
end
|
||||
local bin = function() local l65dbg=l65dbg
|
||||
local b={}
|
||||
for k,v in ipairs(data) do
|
||||
if type(v) == 'function' then v = v() end
|
||||
local vt = type(v)
|
||||
if vt == 'table' and v.label then v = symbols[v.label]
|
||||
elseif vt == 'string' then v = symbols[v] end
|
||||
if type(v) ~= 'number' then error("unresolved symbol for dc.w, index " .. k) end
|
||||
v = word_normalize(v)
|
||||
b[#b+1] = v&0xff
|
||||
b[#b+1] = v>>8
|
||||
end
|
||||
return b
|
||||
end
|
||||
table.insert(M.section_current.instructions, { data=data, size=size, bin=bin })
|
||||
end
|
||||
|
||||
M.long = function(...)
|
||||
local l65dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local args = {...}
|
||||
local data = {}
|
||||
for k,v in ipairs(args) do
|
||||
local t = type(v)
|
||||
if t == 'number' or t == 'function' or t == 'string' then data[#data+1] = v
|
||||
elseif t == 'table' then
|
||||
if v.type == 'section' or v.type == 'label' then data[#data+1] = function() return v end
|
||||
else table.move(v,1,#v,#data+1,data) end
|
||||
else error("unsupported type for long() argument: " .. t .. ", value: " .. v)
|
||||
end
|
||||
end
|
||||
local size = function()
|
||||
for i,v in ipairs(data) do data[i] = size_dc(v) end
|
||||
return #data*4
|
||||
end
|
||||
local bin = function() local l65dbg=l65dbg
|
||||
local b={}
|
||||
for k,v in ipairs(data) do
|
||||
if type(v) == 'function' then v = v() end
|
||||
local vt = type(v)
|
||||
if vt == 'table' and v.label then v = symbols[v.label]
|
||||
elseif vt == 'string' then v = symbols[v] end
|
||||
if type(v) ~= 'number' then error("unresolved symbol for dc.l, index " .. k) end
|
||||
v = long_normalize(v)
|
||||
b[#b+1] = v&0xff
|
||||
b[#b+1] = (v>>8)&0xff
|
||||
b[#b+1] = (v>>16)&0xff
|
||||
b[#b+1] = v>>24
|
||||
end
|
||||
return b
|
||||
end
|
||||
table.insert(M.section_current.instructions, { data=data, size=size, bin=bin })
|
||||
end
|
||||
|
||||
local op = function(code, cycles, extra_on_crosspage)
|
||||
return { opc=code, cycles=cycles or cycles_def, xcross=extra_on_crosspage or xcross_def }
|
||||
end
|
||||
M.op = op
|
||||
|
||||
local op_eval = function(late, early)
|
||||
local x = early or 0
|
||||
return type(late) == 'function' and late(x,op_resolve) or x+op_resolve(late)
|
||||
end
|
||||
M.op_eval = op_eval
|
||||
|
||||
return M
|
3
l65.lua
3
l65.lua
|
@ -32,7 +32,7 @@ local Keywords = lookupify{
|
|||
'return', 'then', 'true', 'until', 'while',
|
||||
};
|
||||
|
||||
-- 6502
|
||||
-------------------------------------------------------- 6502::begin
|
||||
local Keywords_control = {
|
||||
-- control keywords
|
||||
'samepage', 'crosspage',
|
||||
|
@ -168,6 +168,7 @@ local addressing_map = {
|
|||
iny = opcode_indirect_y,
|
||||
rel = opcode_relative,
|
||||
}
|
||||
-------------------------------------------------------- 6502::end
|
||||
|
||||
local Scope = {
|
||||
new = function(self, parent)
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STBI_ONLY_PNG
|
||||
#define STBI_NO_FAILURE_STRINGS
|
||||
#include "stb_image.h"
|
||||
|
||||
#define LUA_IMPLEMENTATION
|
||||
#include "lua.h"
|
||||
#include "scripts_7801.h"
|
||||
|
||||
extern int luaopen_lpeg(lua_State *L);
|
||||
extern int luaopen_lfs(lua_State *L);
|
||||
|
||||
// l7801 lib
|
||||
static int r_s32be(uint8_t **b) { uint8_t *p = *b; int v = ((int)(p[0]))<<24 | ((int)(p[1]))<<16 | ((int)p[2])<<8 | p[3]; *b += 4; return v; }
|
||||
typedef struct { int len, nam; } chunk_s;
|
||||
static chunk_s r_chunk(uint8_t **b) { int len = r_s32be(b), nam = r_s32be(b); chunk_s c = { len, nam }; return c; }
|
||||
static int open_image(lua_State *L)
|
||||
{
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
FILE *file = fopen(filename, "rb");
|
||||
if (!file)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "failed to open file %s", filename);
|
||||
return 2;
|
||||
}
|
||||
fseek(file, 0, SEEK_END);
|
||||
size_t sz = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
uint8_t *png = malloc(sz);
|
||||
fread(png, sz, 1, file);
|
||||
fclose(file);
|
||||
static uint8_t png_sig[8] = { 137,80,78,71,13,10,26,10 };
|
||||
if (memcmp(png, png_sig, 8) != 0)
|
||||
{
|
||||
free(png);
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "file %s is not a PNG", filename);
|
||||
return 2;
|
||||
}
|
||||
uint8_t *b = png + 8;
|
||||
int w, h;
|
||||
uint8_t *d = 0; long d_sz = 0;
|
||||
#define CHUNK_NAM(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
|
||||
for (;;)
|
||||
{
|
||||
chunk_s chunk = r_chunk(&b);
|
||||
switch (chunk.nam)
|
||||
{
|
||||
case CHUNK_NAM('I','H','D','R'): {
|
||||
w = r_s32be(&b); h = r_s32be(&b);
|
||||
if (b[0] != 8 || b[1] != 3)
|
||||
{
|
||||
free(png);
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "PNG file %s must be 8b indexed", filename);
|
||||
return 2;
|
||||
}
|
||||
b += 9;
|
||||
} break;
|
||||
case CHUNK_NAM('I','D','A','T'): {
|
||||
d = realloc(d, d_sz + chunk.len);
|
||||
memcpy(d + d_sz, b, chunk.len);
|
||||
d_sz += chunk.len;
|
||||
b += chunk.len+4;
|
||||
} break;
|
||||
case CHUNK_NAM('I','E','N','D'): {
|
||||
free(png);
|
||||
if (!d)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "invalid PNG file %s", filename);
|
||||
return 2;
|
||||
}
|
||||
int px_sz;
|
||||
uint8_t *px_raw = (uint8_t*)stbi_zlib_decode_malloc_guesssize_headerflag((void*)d, d_sz, (w+1) * h, &px_sz, 1);
|
||||
free(d);
|
||||
uint8_t *px = calloc(w,h);
|
||||
uint8_t *px0 = px, *px_raw0 = px_raw;
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
int filter = *px_raw++;
|
||||
#define prev (x==0 ? 0 : px[x-1])
|
||||
#define up (px[x-w])
|
||||
#define prevup (x==0 ? 0 : px[x-w-1])
|
||||
switch (filter)
|
||||
{
|
||||
case 0: memcpy(px, px_raw, w); break;
|
||||
case 1: for (int x = 0; x < w; ++x) { px[x] = px_raw[x] + prev; } break;
|
||||
case 2: for (int x = 0; x < w; ++x) { px[x] = px_raw[x] + up; } break;
|
||||
case 3: for (int x = 0; x < w; ++x) { px[x] = px_raw[x] + ((prev+up)>>1); } break;
|
||||
case 4: for (int x = 0; x < w; ++x) { px[x] = px_raw[x] + stbi__paeth(prev,up,prevup); } break;
|
||||
}
|
||||
#undef prev
|
||||
#undef up
|
||||
#undef prevup
|
||||
px += w;
|
||||
px_raw += w;
|
||||
}
|
||||
STBI_FREE(px_raw0);
|
||||
|
||||
lua_createtable(L, w*h, 3);
|
||||
lua_pushstring(L, filename);
|
||||
lua_setfield(L, -2, "filename");
|
||||
lua_pushinteger(L, w);
|
||||
lua_setfield(L, -2, "width");
|
||||
lua_pushinteger(L, h);
|
||||
lua_setfield(L, -2, "height");
|
||||
for (int i = 0; i < w*h; ++i)
|
||||
{
|
||||
lua_pushinteger(L, px0[i]);
|
||||
lua_rawseti(L, -2, i+1);
|
||||
}
|
||||
free(px0);
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
b += chunk.len+4;
|
||||
}
|
||||
}
|
||||
#undef CHUNK_NAM
|
||||
if (d) free(d);
|
||||
free(png);
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "invalid PNG file %s", filename);
|
||||
return 2;
|
||||
}
|
||||
static const struct luaL_Reg l7801lib[] = {
|
||||
{"image", open_image},
|
||||
{NULL, NULL},
|
||||
};
|
||||
static int luaopen_l7801(lua_State *L)
|
||||
{
|
||||
luaL_newlib(L, l7801lib);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define SRC_LUA(name) { #name, 0, script_ ## name ## _lua, sizeof(script_ ## name ## _lua) }
|
||||
#define SRC_L7801(name) { #name, 1, script_ ## name ## _l7801, sizeof(script_ ## name ## _l7801) }
|
||||
static struct script { const char *name; int t; const char *data; size_t sz; } embedded[] = {
|
||||
SRC_LUA(dkjson),
|
||||
SRC_LUA(l65cfg),
|
||||
SRC_LUA(re),
|
||||
SRC_L7801(scv),
|
||||
};
|
||||
#undef SRC_LUA
|
||||
#undef SRC_L7801
|
||||
|
||||
static int getembedded(lua_State *L)
|
||||
{
|
||||
const char *name = lua_tostring(L, 1);
|
||||
for (struct script *s = embedded, *e = s + sizeof(embedded) / sizeof(embedded[0]); s != e; ++s)
|
||||
{
|
||||
if (!strcmp(s->name, name))
|
||||
{
|
||||
lua_pushlstring(L, s->data, s->sz);
|
||||
lua_pushboolean(L, s->t);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msghandler(lua_State *L)
|
||||
{
|
||||
const char *msg = lua_tostring(L, 1);
|
||||
if (msg == NULL)
|
||||
{
|
||||
if (luaL_callmeta(L, 1, "__tostring") && lua_type(L, -1) == LUA_TSTRING)
|
||||
return 1;
|
||||
msg = lua_pushfstring(L, "(error object is a %s value)", luaL_typename(L, 1));
|
||||
}
|
||||
luaL_traceback(L, L, msg, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
lua_State *L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
luaL_requiref(L, "lpeg", luaopen_lpeg, 1); lua_pop(L, 1);
|
||||
luaL_requiref(L, "lfs", luaopen_lfs, 1); lua_pop(L, 1);
|
||||
luaL_requiref(L, "l7801", luaopen_l7801, 1); lua_pop(L, 1);
|
||||
|
||||
// preload embedded lua scripts
|
||||
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
|
||||
luaL_loadbufferx(L, script_asm_lua, sizeof(script_asm_lua), "asm.lua", "b");
|
||||
lua_setfield(L, -2, "asm");
|
||||
luaL_loadbufferx(L, script_uPD7801_lua, sizeof(script_uPD7801_lua), "uPD7801.lua", "b");
|
||||
lua_setfield(L, -2, "uPD7801");
|
||||
lua_pop(L, 1);
|
||||
|
||||
// error handler
|
||||
lua_pushcfunction(L, msghandler);
|
||||
// l65.lua script
|
||||
luaL_loadbufferx(L, script_l7801_lua, sizeof(script_l7801_lua), "l7801.lua", "b");
|
||||
// arg[] table
|
||||
lua_createtable(L, argc-1, 2);
|
||||
lua_pushcfunction(L, getembedded); // pass embedded script lookup function as arg[-1]
|
||||
lua_rawseti(L, -2, -1);
|
||||
for (int i = 0; i < argc; i++) lua_pushstring(L, argv[i]), lua_rawseti(L, -2, i);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setglobal(L, "arg");
|
||||
// ... arguments
|
||||
{ int i; for (i = 1; i < argc; ++i) lua_rawgeti(L, -i, i); lua_remove(L, -i); }
|
||||
// call l7801
|
||||
int status = lua_pcall(L, argc-1, 0, -argc-1);
|
||||
if (status != LUA_OK)
|
||||
{
|
||||
const char *msg = lua_tostring(L, -1);
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1); // remove msghandler
|
||||
lua_close(L);
|
||||
return status;
|
||||
}
|
||||
|
4
main.c
4
main.c
|
@ -164,7 +164,7 @@ static int getembedded(lua_State *L)
|
|||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int msghandler(lua_State *L)
|
||||
{
|
||||
|
@ -189,6 +189,8 @@ int main(int argc, char *argv[])
|
|||
|
||||
// preload embedded lua scripts
|
||||
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
|
||||
luaL_loadbufferx(L, script_asm_lua, sizeof(script_asm_lua), "asm.lua", "b");
|
||||
lua_setfield(L, -2, "asm");
|
||||
luaL_loadbufferx(L, script_6502_lua, sizeof(script_6502_lua), "6502.lua", "b");
|
||||
lua_setfield(L, -2, "6502");
|
||||
lua_pop(L, 1);
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
require 'scv'
|
||||
location(0x8000, 0x8FFF)
|
||||
section{"rom", org=0x8000}
|
||||
dc.b 'H'
|
||||
@main
|
||||
di
|
||||
lxi sp,0xFFD2
|
||||
ei
|
||||
calt 0x8C
|
||||
|
||||
lxi hl,vdc_data
|
||||
lxi de,0x3400
|
||||
mvi c,0x03
|
||||
block
|
||||
|
||||
lxi hl,message
|
||||
lxi de,0x3044
|
||||
lxi bc,0x01ff
|
||||
|
||||
@loop_0
|
||||
block
|
||||
dcr b
|
||||
jr loop_0
|
||||
|
||||
-- beep
|
||||
lxi hl,0x3600
|
||||
calf 0xfb0
|
||||
|
||||
@loop_1
|
||||
nop
|
||||
jr loop_1
|
||||
|
||||
section{"vdc_data", org=0x8030}
|
||||
dc.b 0xC0,0x00,0x00,0xF2
|
||||
|
||||
section{"message", org=0x8040}
|
||||
dc.b "\t\t\t\t Hello world! \t\t\t\t"
|
||||
dc.b 0x00
|
||||
|
||||
writebin(filename .. '.bin')
|
|
@ -0,0 +1,498 @@
|
|||
----------------------------------------------------------------
|
||||
-- Plogue uPD1771C Tester
|
||||
-- BY David Viens january 2010 chipsounds R&D
|
||||
-- (from Hello World! Program Ver 1.1 by) Programmed By Enri
|
||||
-- haxored to emit 7801 instructions using
|
||||
-- Macro Assembler AS V1.42's 7810 mode
|
||||
-- http://john.ccac.rwth-aachen.de:8000/as
|
||||
-- Converted to l65
|
||||
----------------------------------------------------------------
|
||||
|
||||
require 'scv'
|
||||
location(0x8000, 0x9fff)
|
||||
section{"rom", org=0x8000}
|
||||
dc.b 'H' -- Headder
|
||||
|
||||
-- 0FF8X seems reserved, but not FF9X
|
||||
local PARAMS = 0xFF90
|
||||
local ACTIVE_PARAM = 0xFF9A
|
||||
local PLAYING = 0xFF9B
|
||||
|
||||
-------------------------
|
||||
-- Clear Text All Area --
|
||||
-------------------------
|
||||
calt 0x8c -- bios function!!!
|
||||
|
||||
-------------
|
||||
-- Set VDC --
|
||||
-------------
|
||||
lxi hl,VDC_DATA
|
||||
lxi de,0x3400
|
||||
mvi c,0x03
|
||||
block
|
||||
|
||||
---------------------
|
||||
-- Set INITIAL RAM --
|
||||
---------------------
|
||||
lxi hl,INITIAL_RAM
|
||||
lxi de,PARAMS
|
||||
mvi c,0x0F
|
||||
block
|
||||
|
||||
--------------------------------------------------------------
|
||||
----------------- END INITIALISATION POUTINE -----------------
|
||||
--------------------------------------------------------------
|
||||
|
||||
-------------------------
|
||||
-- Print Screen Format --
|
||||
-------------------------
|
||||
lxi hl,DISPLAY_DATA
|
||||
lxi de,0x3040 -- Text RAM Address
|
||||
lxi bc,0x0180
|
||||
@LOOP0
|
||||
block
|
||||
dcr b
|
||||
jr LOOP0
|
||||
|
||||
--------------------------------------------------------------
|
||||
------------------------- MAIN LOOP -------------------------
|
||||
--------------------------------------------------------------
|
||||
@LOOPN
|
||||
-- reposition pointer to current param
|
||||
lxi hl,PARAMS
|
||||
mov b,(ACTIVE_PARAM)
|
||||
dcx hl
|
||||
@POSITIONLOOP
|
||||
inx hl
|
||||
dcr b
|
||||
jmp POSITIONLOOP
|
||||
|
||||
|
||||
lxi de,0x3090
|
||||
-- SLEEP before note
|
||||
mvi c,0x10 -- wait 1 second of vblanks
|
||||
call SLEEPFUNC
|
||||
|
||||
|
||||
mvi a,0xFD -- we want to store that into PA so that portB can be later scanned i guess like the vic/c64 kb
|
||||
mov pa,a
|
||||
mov a,pb -- see which are closed upon return
|
||||
|
||||
oni a,2
|
||||
jr RIGHT_DOWN
|
||||
jr RIGHT_END
|
||||
@RIGHT_DOWN
|
||||
ldax (hl)
|
||||
adi a,1
|
||||
stax (hl)
|
||||
|
||||
-- if playing replay patter
|
||||
mov a,(PLAYING)
|
||||
eqi a,1
|
||||
jmp ALL_DONE
|
||||
-- fake not already playing
|
||||
mvi a,0
|
||||
mov (PLAYING),a -- ON
|
||||
call PLAY_PATTERN
|
||||
jmp ALL_DONE
|
||||
|
||||
@RIGHT_END
|
||||
|
||||
oni a,1
|
||||
jr DOWN_DOWN
|
||||
jr DOWN_END
|
||||
@DOWN_DOWN
|
||||
mov a,(ACTIVE_PARAM)
|
||||
adi a,1
|
||||
mov (ACTIVE_PARAM),a
|
||||
jmp ALL_DONE
|
||||
@DOWN_END
|
||||
|
||||
mvi a,0xFE
|
||||
mov pa,a -- fill port with voltages
|
||||
mov a,pb -- see which are closed upon return
|
||||
|
||||
oni a,1
|
||||
jr LEFT_DOWN
|
||||
jr LEFT_END
|
||||
@LEFT_DOWN
|
||||
ldax (hl)
|
||||
sui a,1
|
||||
stax (hl)
|
||||
|
||||
-- if playing replay patter
|
||||
mov a,(PLAYING)
|
||||
eqi a,1
|
||||
jmp ALL_DONE
|
||||
-- fake not already playing
|
||||
mvi a,0
|
||||
mov (PLAYING),a -- OFF
|
||||
call PLAY_PATTERN
|
||||
jmp ALL_DONE
|
||||
@LEFT_END
|
||||
|
||||
oni a,2
|
||||
jr UP_DOWN
|
||||
jr UP_END
|
||||
@UP_DOWN
|
||||
mov a,(ACTIVE_PARAM)
|
||||
sui a,1
|
||||
mov (ACTIVE_PARAM),a
|
||||
jmp ALL_DONE
|
||||
@UP_END
|
||||
|
||||
oni a,4
|
||||
jr BUTTON_DOWN
|
||||
jr BUTTON_UP
|
||||
@BUTTON_DOWN
|
||||
call PLAY_PATTERN
|
||||
jmp ALL_DONE
|
||||
@BUTTON_UP
|
||||
call STOP_PATTERN
|
||||
jr BUTTON_END
|
||||
@BUTTON_END
|
||||
|
||||
@ALL_DONE
|
||||
|
||||
-- check bounds on active param
|
||||
mov a,(ACTIVE_PARAM)
|
||||
lti a,0x0A
|
||||
jr ACT_GREATER
|
||||
jr ACT_DONE
|
||||
@ACT_GREATER
|
||||
mvi a,0x00
|
||||
mov (ACTIVE_PARAM),a
|
||||
jr ACT_DONE
|
||||
@ACT_DONE
|
||||
|
||||
-- print where we at!
|
||||
call DISPLAY_LOOP
|
||||
|
||||
jmp LOOPN
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- Display init data
|
||||
-------------------------------------------------------------------------
|
||||
@VDC_DATA
|
||||
dc.b 0xC0,0x00,0x00,0xF1 -- 0F1 -> black
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- lame sleep (with C param)
|
||||
-------------------------------------------------------------------------
|
||||
section{"SLEEPFUNC", org=0x8100}
|
||||
-- sleep the amount of time depending on C
|
||||
push bc
|
||||
@SLOOP
|
||||
mvi b,0xff
|
||||
@SLEEP0
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
dcr b
|
||||
jr SLEEP0
|
||||
dcr c
|
||||
jr SLOOP
|
||||
pop bc
|
||||
ret
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- wait on VBLANK
|
||||
-------------------------------------------------------------------------
|
||||
section{"WVBLANK", org=0x8200}
|
||||
skit f2 -- wait until acknowledged
|
||||
jr WVBLANK
|
||||
ret
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- wait on D1771g (wait until INT1=1)
|
||||
-------------------------------------------------------------------------
|
||||
section{"WD1771G", org=0x8220}
|
||||
skit f1
|
||||
jr WD1771G
|
||||
ret
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- Print ONE UINT8_T on screen as HEX (two screen chars printed)
|
||||
--
|
||||
-- A should contain the hex value to print (A returns unchanged)
|
||||
-- D should contain the screen value to dump the high part (D returns unchanged)
|
||||
-- V is thrashed (used as temporary val)
|
||||
-------------------------------------------------------------------------
|
||||
section{"PRINT_HEX", org=0x8240}
|
||||
mvi v,0 -- trick to do V=A
|
||||
add v,a -- trick to do V=A
|
||||
|
||||
ani a,0xF0 -- a = a & 0x0f;
|
||||
clc -- clear carry so not to fuck up the following right shifts
|
||||
rlr a --
|
||||
rlr a --
|
||||
rlr a --
|
||||
rlr a -- ok we got the HEX value for the up 4bits
|
||||
|
||||
gti a,0x09
|
||||
jr HIGH_GREATER
|
||||
jr HIGH_LOWER
|
||||
@HIGH_GREATER
|
||||
adi a,0x30 -- a+='0' (ascii)
|
||||
jr HIGH_DONE
|
||||
@HIGH_LOWER
|
||||
adi a,0x37 -- a+=('A'-10) (ascii)
|
||||
jr HIGH_DONE
|
||||
@HIGH_DONE
|
||||
|
||||
staxi (de) --
|
||||
|
||||
mvi a,0 -- trick to do A=V
|
||||
add a,v -- trick to do A=V
|
||||
ani a,0x0F -- a = a & 0x0f
|
||||
|
||||
gti a,0x09
|
||||
jr LOW_GREATER
|
||||
jr LOW_LOWER
|
||||
@LOW_GREATER
|
||||
adi a,0x30 -- a+='0' (ascii)
|
||||
jr LOW_DONE
|
||||
@LOW_LOWER
|
||||
adi a,0x37 -- a+=('A'-10) (ascii)
|
||||
jr LOW_DONE
|
||||
@LOW_DONE
|
||||
|
||||
staxd (de) --
|
||||
mvi a,0 -- trick to do A=V
|
||||
add a,v -- trick to do A=V
|
||||
ret
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- Prints all current param values
|
||||
-------------------------------------------------------------------------
|
||||
section{"DISPLAY_LOOP", org=0x8280}
|
||||
mvi b,0x0B
|
||||
lxi de,0x3090
|
||||
lxi hl,PARAMS
|
||||
@DLOOP
|
||||
|
||||
-- if b==ACTIVE_PARAM show arrow
|
||||
-- else show space
|
||||
mvi a,0x0B
|
||||
mov c,(ACTIVE_PARAM)
|
||||
sub a,c
|
||||
|
||||
eqa a,b
|
||||
jr NOCURSOR
|
||||
mvi a,0x1C
|
||||
stax (de)
|
||||
jr CURSDONE
|
||||
@NOCURSOR
|
||||
mvi a,0x20
|
||||
stax (de)
|
||||
@CURSDONE
|
||||
-- print all ram
|
||||
ldaxi (hl)
|
||||
-- increase D pos to display in hex
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
call PRINT_HEX
|
||||
dcx de
|
||||
dcx de
|
||||
dcx de
|
||||
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
inx de
|
||||
|
||||
dcr b
|
||||
jmp DLOOP
|
||||
ret
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- Stop current pattern
|
||||
-------------------------------------------------------------------------
|
||||
section{"STOP_PATTERN", org=0x82d0}
|
||||
-- if (!playing) return;
|
||||
mov a,(PLAYING)
|
||||
eqi a,1
|
||||
jr STOP_DONE
|
||||
|
||||
mvi a,0
|
||||
mov (PLAYING),a -- OFF
|
||||
|
||||
di
|
||||
lxi hl,0x3600 -- SOUND REGISTER in H
|
||||
call WVBLANK -- cwait on intf2
|
||||
skit f1
|
||||
nop
|
||||
|
||||
mvix (hl),0x00 -- note OFF
|
||||
|
||||
ei
|
||||
|
||||
@STOP_DONE
|
||||
ret
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- Plays current pattern
|
||||
-- Start with beep please
|
||||
-------------------------------------------------------------------------
|
||||
section{"PLAY_PATTERN", org=0x82f0}
|
||||
mov a,(PLAYING)
|
||||
eqi a,0
|
||||
jmp PLAY_DONE
|
||||
|
||||
-- setting variable true!
|
||||
mvi a,1
|
||||
mov (PLAYING),a -- ON
|
||||
|
||||
lxi de,PARAMS
|
||||
lxi hl,0x3600 -- SOUND REGISTER in H
|
||||
|
||||
|
||||
ldaxi (de)
|
||||
eqi a,1
|
||||
jmp PLAY_TONE
|
||||
jmp PLAY_NOISE
|
||||
|
||||
@PLAY_TONE
|
||||
------------------------ Tone Start ------------------------
|
||||
di
|
||||
call WVBLANK
|
||||
skit f1
|
||||
nop
|
||||
-- instrument params start
|
||||
mvi a,2 -- tone!
|
||||
stax (hl)
|
||||
call WD1771G -- cwait on intf1
|
||||
ldaxi (de)
|
||||
stax (hl)
|
||||
call WD1771G -- cwait on intf1
|
||||
ldaxi (de)
|
||||
stax (hl)
|
||||
call WD1771G -- cwait on intf1
|
||||
ldaxi (de)
|
||||
stax (hl)
|
||||
call WVBLANK -- cwait on intf2
|
||||
-- instrument params end
|
||||
ei
|
||||
jmp PLAY_DONE
|
||||
|
||||
@PLAY_NOISE
|
||||
------------------------ Tone Start ------------------------
|
||||
di
|
||||
call WVBLANK -- cwait on intf2
|
||||
skit f1
|
||||
nop
|
||||
-- instrument params start
|
||||
mvi a,1 -- NOISE
|
||||
stax (hl)
|
||||
call WD1771G -- cwait on intf1
|
||||
ldaxi (de)
|
||||
stax (hl)
|
||||
call WD1771G -- cwait on intf1
|
||||
ldaxi (de)
|
||||
stax (hl)
|
||||
call WD1771G -- cwait on intf1
|
||||
ldaxi (de)
|
||||
stax (hl)
|
||||
call WD1771G -- cwait on intf1
|
||||
ldaxi (de)
|
||||
stax (hl)
|
||||
call WD1771G -- cwait on intf1
|
||||
ldaxi (de)
|
||||
stax (hl)
|
||||
call WD1771G -- cwait on intf1
|
||||
ldaxi (de)
|
||||
stax (hl)
|
||||
call WD1771G -- cwait on intf1
|
||||
ldaxi (de)
|
||||
stax (hl)
|
||||
call WD1771G -- cwait on intf1
|
||||
ldaxi (de)
|
||||
stax (hl)
|
||||
call WD1771G -- cwait on intf1
|
||||
ldaxi (de)
|
||||
stax (hl)
|
||||
call WVBLANK -- cwait on intf2
|
||||
-- instrument params end
|
||||
ei
|
||||
jmp PLAY_DONE
|
||||
|
||||
@PLAY_DONE
|
||||
ret
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- Message Data1
|
||||
-- this version has left+audio changes working
|
||||
-------------------------------------------------------------------------
|
||||
@DISPLAY_DATA
|
||||
dc.b " Plogue uPD1771C Tester "
|
||||
dc.b " v0.0018 "
|
||||
dc.b " Param[0]: ( ) "
|
||||
dc.b " Param[1]: ( ) "
|
||||
dc.b " Param[2]: ( ) "
|
||||
dc.b " Param[3]: ( ) "
|
||||
dc.b " Param[4]: ( ) "
|
||||
dc.b " Param[5]: ( ) "
|
||||
dc.b " Param[6]: ( ) "
|
||||
dc.b " Param[7]: ( ) "
|
||||
dc.b " Param[8]: ( ) "
|
||||
dc.b " Param[9]: ( ) "
|
||||
|
||||
-- go to [FF90;FF9F]
|
||||
@INITIAL_RAM
|
||||
-- params
|
||||
dc.b 0x02
|
||||
dc.b 0x80
|
||||
dc.b 0xFF
|
||||
dc.b 0x1F
|
||||
|
||||
dc.b 0xAB
|
||||
dc.b 0xFE
|
||||
dc.b 0xCD
|
||||
dc.b 0xDC
|
||||
dc.b 0x45
|
||||
dc.b 0x01
|
||||
|
||||
dc.b 0x00 -- FF9A curent param
|
||||
dc.b 0x00 -- FF9B BOOL note on
|
||||
dc.b 0x83 -- misc
|
||||
dc.b 0x39 -- misc
|
||||
dc.b 0x44 -- misc
|
||||
dc.b 0x36 -- misc
|
||||
|
||||
writebin(filename..'.bin', genbin(0xff))
|
|
@ -0,0 +1,738 @@
|
|||
require 'scv'
|
||||
location(0x8000, 0x8FFF)
|
||||
section{"rom", org=0x8000}
|
||||
dc.b 'H'
|
||||
@main
|
||||
block
|
||||
calb
|
||||
ei
|
||||
daa
|
||||
di
|
||||
ex
|
||||
exx
|
||||
halt
|
||||
jb
|
||||
nop
|
||||
ret
|
||||
reti
|
||||
rets
|
||||
sio
|
||||
softi
|
||||
stm
|
||||
table
|
||||
dcr a
|
||||
dcr b
|
||||
dcr c
|
||||
inr a
|
||||
inr b
|
||||
inr c
|
||||
dcx sp
|
||||
inx sp
|
||||
mvi a,0xca
|
||||
mvi b,0xfe
|
||||
mvi c,0xbe
|
||||
mvi d,0xef
|
||||
mvi e,0xf0
|
||||
mvi h,0x0d
|
||||
mvi l,0x78
|
||||
mvi v,0x01
|
||||
aci a,0x0f
|
||||
adi a,0x1e
|
||||
adinc a,0x2d
|
||||
ani a,0x3c
|
||||
eqi a,0x4b
|
||||
gti a,0x5a
|
||||
lti a,0x69
|
||||
nei a,0x87
|
||||
offi a,0x96
|
||||
oni a,0xa5
|
||||
ori a,0xb4
|
||||
sbi a,0xc3
|
||||
sui a,0xd2
|
||||
suinb a,0xe1
|
||||
xri a,0xf0
|
||||
lxi bc,0xabcd
|
||||
lxi de,0xbeef
|
||||
lxi hl,0xcafe
|
||||
lxi sp,0xf00d
|
||||
call 0xd701
|
||||
jmp 0x8e07
|
||||
clc
|
||||
pen
|
||||
per
|
||||
pex
|
||||
rld
|
||||
rrd
|
||||
stc
|
||||
mov a,b
|
||||
mov a,c
|
||||
mov a,d
|
||||
mov a,e
|
||||
mov a,h
|
||||
mov a,l
|
||||
mov b,a
|
||||
mov c,a
|
||||
mov d,a
|
||||
mov e,a
|
||||
mov h,a
|
||||
mov l,a
|
||||
@l0 jre l0
|
||||
@l1 nop
|
||||
jre l1
|
||||
@l2 nop nop
|
||||
jre l2
|
||||
@l3 nop nop nop
|
||||
jre l3
|
||||
@l4 nop nop nop nop
|
||||
jre l4
|
||||
jre l5
|
||||
@l5 jre l6
|
||||
nop
|
||||
@l6 jre l7
|
||||
nop nop
|
||||
@l7 jre l8
|
||||
nop nop nop
|
||||
@l8 jre l9
|
||||
nop nop nop nop
|
||||
@l9
|
||||
ldax (bc)
|
||||
ldax (de)
|
||||
ldax (hl)
|
||||
stax (bc)
|
||||
stax (de)
|
||||
stax (hl)
|
||||
inrw (v,0x01)
|
||||
ldaw (v,0x23)
|
||||
dcrw (v,0x45)
|
||||
staw (v,0x67)
|
||||
bit0 (v,0x89)
|
||||
bit1 (v,0xab)
|
||||
bit2 (v,0xcd)
|
||||
bit3 (v,0xef)
|
||||
bit4 (v,0xfe)
|
||||
bit5 (v,0xdc)
|
||||
bit6 (v,0xba)
|
||||
bit7 (v,0x98)
|
||||
dcx bc
|
||||
dcx de
|
||||
dcx hl
|
||||
inx bc
|
||||
inx de
|
||||
inx hl
|
||||
mvix (bc),0xf9
|
||||
mvix (de),0xe8
|
||||
mvix (hl),0xd7
|
||||
mviw (v,0x9a),0x3f
|
||||
eqiw (v,0xc5),0x1b
|
||||
ldaxd (de)
|
||||
ldaxi (de)
|
||||
ldaxd (hl)
|
||||
ldaxi (hl)
|
||||
staxd (de)
|
||||
staxi (de)
|
||||
staxd (hl)
|
||||
staxi (hl)
|
||||
push bc
|
||||
push de
|
||||
push hl
|
||||
pop hl
|
||||
pop de
|
||||
pop bc
|
||||
push va
|
||||
pop va
|
||||
rll a
|
||||
rlr a
|
||||
rll c
|
||||
rlr c
|
||||
sll a
|
||||
slr a
|
||||
sll c
|
||||
slr c
|
||||
skc
|
||||
skz
|
||||
sknc
|
||||
sknz
|
||||
skit f0
|
||||
skit ft
|
||||
skit f1
|
||||
skit f2
|
||||
skit fs
|
||||
sknit f0
|
||||
sknit ft
|
||||
sknit f1
|
||||
sknit f2
|
||||
sknit fs
|
||||
in 0x00
|
||||
in 0xa7
|
||||
in 0xbf
|
||||
out 0x00
|
||||
out 0x5a
|
||||
out 0xbf
|
||||
mov a,pa
|
||||
mov a,pb
|
||||
mov a,pc
|
||||
mov a,mk
|
||||
mov a,mb
|
||||
mov a,mc
|
||||
mov a,tm0
|
||||
mov a,tm1
|
||||
mov a,s
|
||||
mov pa,a
|
||||
mov pb,a
|
||||
mov pc,a
|
||||
mov mk,a
|
||||
mov mb,a
|
||||
mov mc,a
|
||||
mov tm0,a
|
||||
mov tm1,a
|
||||
mov s,a
|
||||
ana v,a
|
||||
ana a,a
|
||||
ana b,a
|
||||
ana c,a
|
||||
ana d,a
|
||||
ana e,a
|
||||
ana h,a
|
||||
ana l,a
|
||||
xra v,a
|
||||
xra a,a
|
||||
xra b,a
|
||||
xra c,a
|
||||
xra d,a
|
||||
xra e,a
|
||||
xra h,a
|
||||
xra l,a
|
||||
ora v,a
|
||||
ora a,a
|
||||
ora b,a
|
||||
ora c,a
|
||||
ora d,a
|
||||
ora e,a
|
||||
ora h,a
|
||||
ora l,a
|
||||
addnc v,a
|
||||
addnc a,a
|
||||
addnc b,a
|
||||
addnc c,a
|
||||
addnc d,a
|
||||
addnc e,a
|
||||
addnc h,a
|
||||
addnc l,a
|
||||
gta v,a
|
||||
gta a,a
|
||||
gta b,a
|
||||
gta c,a
|
||||
gta d,a
|
||||
gta e,a
|
||||
gta h,a
|
||||
gta l,a
|
||||
subnb v,a
|
||||
subnb a,a
|
||||
subnb b,a
|
||||
subnb c,a
|
||||
subnb d,a
|
||||
subnb e,a
|
||||
subnb h,a
|
||||
subnb l,a
|
||||
lta v,a
|
||||
lta a,a
|
||||
lta b,a
|
||||
lta c,a
|
||||
lta d,a
|
||||
lta e,a
|
||||
lta h,a
|
||||
lta l,a
|
||||
add v,a
|
||||
add a,a
|
||||
add b,a
|
||||
add c,a
|
||||
add d,a
|
||||
add e,a
|
||||
add h,a
|
||||
add l,a
|
||||
adc v,a
|
||||
adc a,a
|
||||
adc b,a
|
||||
adc c,a
|
||||
adc d,a
|
||||
adc e,a
|
||||
adc h,a
|
||||
adc l,a
|
||||
sub v,a
|
||||
sub a,a
|
||||
sub b,a
|
||||
sub c,a
|
||||
sub d,a
|
||||
sub e,a
|
||||
sub h,a
|
||||
sub l,a
|
||||
nea v,a
|
||||
nea a,a
|
||||
nea b,a
|
||||
nea c,a
|
||||
nea d,a
|
||||
nea e,a
|
||||
nea h,a
|
||||
nea l,a
|
||||
sbb v,a
|
||||
sbb a,a
|
||||
sbb b,a
|
||||
sbb c,a
|
||||
sbb d,a
|
||||
sbb e,a
|
||||
sbb h,a
|
||||
sbb l,a
|
||||
eqa v,a
|
||||
eqa a,a
|
||||
eqa b,a
|
||||
eqa c,a
|
||||
eqa d,a
|
||||
eqa e,a
|
||||
eqa h,a
|
||||
eqa l,a
|
||||
ana a,v
|
||||
ana a,a
|
||||
ana a,b
|
||||
ana a,c
|
||||
ana a,d
|
||||
ana a,e
|
||||
ana a,h
|
||||
ana a,l
|
||||
xra a,v
|
||||
xra a,a
|
||||
xra a,b
|
||||
xra a,c
|
||||
xra a,d
|
||||
xra a,e
|
||||
xra a,h
|
||||
xra a,l
|
||||
ora a,v
|
||||
ora a,a
|
||||
ora a,b
|
||||
ora a,c
|
||||
ora a,d
|
||||
ora a,e
|
||||
ora a,h
|
||||
ora a,l
|
||||
addnc a,v
|
||||
addnc a,a
|
||||
addnc a,b
|
||||
addnc a,c
|
||||
addnc a,d
|
||||
addnc a,e
|
||||
addnc a,h
|
||||
addnc a,l
|
||||
gta a,v
|
||||
gta a,a
|
||||
gta a,b
|
||||
gta a,c
|
||||
gta a,d
|
||||
gta a,e
|
||||
gta a,h
|
||||
gta a,l
|
||||
subnb a,v
|
||||
subnb a,a
|
||||
subnb a,b
|
||||
subnb a,c
|
||||
subnb a,d
|
||||
subnb a,e
|
||||
subnb a,h
|
||||
subnb a,l
|
||||
lta a,v
|
||||
lta a,a
|
||||
lta a,b
|
||||
lta a,c
|
||||
lta a,d
|
||||
lta a,e
|
||||
lta a,h
|
||||
lta a,l
|
||||
add a,v
|
||||
add a,a
|
||||
add a,b
|
||||
add a,c
|
||||
add a,d
|
||||
add a,e
|
||||
add a,h
|
||||
add a,l
|
||||
ona a,v
|
||||
ona a,a
|
||||
ona a,b
|
||||
ona a,c
|
||||
ona a,d
|
||||
ona a,e
|
||||
ona a,h
|
||||
ona a,l
|
||||
adc a,v
|
||||
adc a,a
|
||||
adc a,b
|
||||
adc a,c
|
||||
adc a,d
|
||||
adc a,e
|
||||
adc a,h
|
||||
adc a,l
|
||||
offa a,v
|
||||
offa a,a
|
||||
offa a,b
|
||||
offa a,c
|
||||
offa a,d
|
||||
offa a,e
|
||||
offa a,h
|
||||
offa a,l
|
||||
sub a,v
|
||||
sub a,a
|
||||
sub a,b
|
||||
sub a,c
|
||||
sub a,d
|
||||
sub a,e
|
||||
sub a,h
|
||||
sub a,l
|
||||
nea a,v
|
||||
nea a,a
|
||||
nea a,b
|
||||
nea a,c
|
||||
nea a,d
|
||||
nea a,e
|
||||
nea a,h
|
||||
nea a,l
|
||||
sbb a,v
|
||||
sbb a,a
|
||||
sbb a,b
|
||||
sbb a,c
|
||||
sbb a,d
|
||||
sbb a,e
|
||||
sbb a,h
|
||||
sbb a,l
|
||||
eqa a,v
|
||||
eqa a,a
|
||||
eqa a,b
|
||||
eqa a,c
|
||||
eqa a,d
|
||||
eqa a,e
|
||||
eqa a,h
|
||||
eqa a,l
|
||||
ani v,0x00
|
||||
ani a,0x01
|
||||
ani b,0x02
|
||||
ani c,0x03
|
||||
ani d,0x04
|
||||
ani e,0x05
|
||||
ani h,0x06
|
||||
ani l,0x07
|
||||
xri v,0x08
|
||||
xri a,0x09
|
||||
xri b,0x0a
|
||||
xri c,0x0b
|
||||
xri d,0x0c
|
||||
xri e,0x0d
|
||||
xri h,0x0e
|
||||
xri l,0x0f
|
||||
ori v,0x10
|
||||
ori a,0x11
|
||||
ori b,0x12
|
||||
ori c,0x13
|
||||
ori d,0x14
|
||||
ori e,0x15
|
||||
ori h,0x16
|
||||
ori l,0x17
|
||||
adinc v,0x18
|
||||
adinc a,0x19
|
||||
adinc b,0x1a
|
||||
adinc c,0x1b
|
||||
adinc d,0x1c
|
||||
adinc e,0x1d
|
||||
adinc h,0x1e
|
||||
adinc l,0x1f
|
||||
gti v,0x20
|
||||
gti a,0x21
|
||||
gti b,0x22
|
||||
gti c,0x23
|
||||
gti d,0x24
|
||||
gti e,0x25
|
||||
gti h,0x26
|
||||
gti l,0x27
|
||||
suinb v,0x28
|
||||
suinb a,0x29
|
||||
suinb b,0x2a
|
||||
suinb c,0x2b
|
||||
suinb d,0x2c
|
||||
suinb e,0x2d
|
||||
suinb h,0x2e
|
||||
suinb l,0x2f
|
||||
lti v,0x30
|
||||
lti a,0x31
|
||||
lti b,0x32
|
||||
lti c,0x33
|
||||
lti d,0x34
|
||||
lti e,0x35
|
||||
lti h,0x36
|
||||
lti l,0x37
|
||||
adi v,0x38
|
||||
adi a,0x39
|
||||
adi b,0x3a
|
||||
adi c,0x3b
|
||||
adi d,0x3c
|
||||
adi e,0x3d
|
||||
adi h,0x3e
|
||||
adi l,0x4f
|
||||
oni v,0x40
|
||||
oni a,0x41
|
||||
oni b,0x42
|
||||
oni c,0x43
|
||||
oni d,0x44
|
||||
oni e,0x45
|
||||
oni h,0x46
|
||||
oni l,0x47
|
||||
aci v,0x48
|
||||
aci a,0x49
|
||||
aci b,0x4a
|
||||
aci c,0x4b
|
||||
aci d,0x4c
|
||||
aci e,0x4d
|
||||
aci h,0x4e
|
||||
aci l,0x4f
|
||||
offi v,0x50
|
||||
offi a,0x51
|
||||
offi b,0x52
|
||||
offi c,0x53
|
||||
offi d,0x54
|
||||
offi e,0x55
|
||||
offi h,0x56
|
||||
offi l,0x57
|
||||
sui v,0x58
|
||||
sui a,0x59
|
||||
sui b,0x5a
|
||||
sui c,0x5b
|
||||
sui d,0x5c
|
||||
sui e,0x5d
|
||||
sui h,0x5e
|
||||
sui l,0x5f
|
||||
nei v,0x60
|
||||
nei a,0x61
|
||||
nei b,0x62
|
||||
nei c,0x63
|
||||
nei d,0x64
|
||||
nei e,0x65
|
||||
nei h,0x66
|
||||
nei l,0x67
|
||||
sbi v,0x68
|
||||
sbi a,0x69
|
||||
sbi b,0x6a
|
||||
sbi c,0x6b
|
||||
sbi d,0x6c
|
||||
sbi e,0x6d
|
||||
sbi h,0x6e
|
||||
sbi l,0x6f
|
||||
eqi v,0x70
|
||||
eqi a,0x71
|
||||
eqi b,0x72
|
||||
eqi c,0x73
|
||||
eqi d,0x74
|
||||
eqi e,0x75
|
||||
eqi h,0x76
|
||||
eqi l,0x77
|
||||
ani pa,0x78
|
||||
ani pb,0x79
|
||||
ani pc,0x7a
|
||||
ani mk,0x7b
|
||||
xri pa,0x7c
|
||||
xri pb,0x7d
|
||||
xri pc,0x7e
|
||||
xri mk,0x7f
|
||||
ori pa,0x80
|
||||
ori pb,0x81
|
||||
ori pc,0x82
|
||||
ori mk,0x83
|
||||
adinc pa,0x84
|
||||
adinc pb,0x85
|
||||
adinc pc,0x86
|
||||
adinc mk,0x87
|
||||
gti pa,0x88
|
||||
gti pb,0x89
|
||||
gti pc,0x8a
|
||||
gti mk,0x8b
|
||||
suinb pa,0x8c
|
||||
suinb pb,0x8d
|
||||
suinb pc,0x8e
|
||||
suinb mk,0x8f
|
||||
lti pa,0x90
|
||||
lti pb,0x91
|
||||
lti pc,0x92
|
||||
lti mk,0x93
|
||||
adi pa,0x94
|
||||
adi pb,0x95
|
||||
adi pc,0x96
|
||||
adi mk,0x97
|
||||
oni pa,0x98
|
||||
oni pb,0x99
|
||||
oni pc,0x9a
|
||||
oni mk,0x9b
|
||||
aci pa,0x9c
|
||||
aci pb,0x9d
|
||||
aci pc,0x9e
|
||||
aci mk,0x9f
|
||||
offi pa,0xa0
|
||||
offi pb,0xa1
|
||||
offi pc,0xa2
|
||||
offi mk,0xa3
|
||||
sui pa,0xa4
|
||||
sui pb,0xa5
|
||||
sui pc,0xa6
|
||||
sui mk,0xa7
|
||||
nei pa,0xa8
|
||||
nei pb,0xa9
|
||||
nei pc,0xaa
|
||||
nei mk,0xab
|
||||
sbi pa,0xac
|
||||
sbi pb,0xad
|
||||
sbi pc,0xae
|
||||
sbi mk,0xaf
|
||||
eqi pa,0xb0
|
||||
eqi pb,0xb1
|
||||
eqi pc,0xb2
|
||||
eqi mk,0xb3
|
||||
anaw (v,0xf0)
|
||||
xraw (v,0xe1)
|
||||
oraw (v,0xd2)
|
||||
addncw (v,0xc3)
|
||||
gtaw (v,0xb4)
|
||||
subnbw (v,0xa5)
|
||||
ltaw (v,0x96)
|
||||
addw (v,0x87)
|
||||
onaw (v,0x78)
|
||||
adcw (v,0x69)
|
||||
offaw (v,0x5a)
|
||||
subw (v,0x4b)
|
||||
neaw (v,0x3c)
|
||||
sbbw (v,0x2d)
|
||||
eqaw (v,0x1e)
|
||||
sspd (0x8000)
|
||||
lspd (0x8001)
|
||||
sbcd (0x8010)
|
||||
lbcd (0x8011)
|
||||
sded (0x8100)
|
||||
lded (0x8101)
|
||||
shld (0x8110)
|
||||
lhld (0x8111)
|
||||
mov (0xab00),v
|
||||
mov (0xbc01),a
|
||||
mov (0xde02),b
|
||||
mov (0xfa03),c
|
||||
mov (0xeb04),d
|
||||
mov (0xdc05),e
|
||||
mov (0xcd06),h
|
||||
mov (0xbe07),l
|
||||
mov v,(0x000f)
|
||||
mov a,(0x00f0)
|
||||
mov b,(0x00ff)
|
||||
mov c,(0x0f00)
|
||||
mov d,(0x0f0f)
|
||||
mov e,(0x0ff0)
|
||||
mov h,(0x0fff)
|
||||
mov l,(0xf000)
|
||||
anax (bc)
|
||||
xrax (bc)
|
||||
orax (bc)
|
||||
addncx (bc)
|
||||
gtax (bc)
|
||||
subnbx (bc)
|
||||
ltax (bc)
|
||||
addx (bc)
|
||||
onax (bc)
|
||||
adcx (bc)
|
||||
offax (bc)
|
||||
subx (bc)
|
||||
neax (bc)
|
||||
sbbx (bc)
|
||||
eqax (bc)
|
||||
anax (de)
|
||||
xrax (de)
|
||||
orax (de)
|
||||
addncx (de)
|
||||
gtax (de)
|
||||
subnbx (de)
|
||||
ltax (de)
|
||||
addx (de)
|
||||
onax (de)
|
||||
adcx (de)
|
||||
offax (de)
|
||||
subx (de)
|
||||
neax (de)
|
||||
sbbx (de)
|
||||
eqax (de)
|
||||
anax (hl)
|
||||
xrax (hl)
|
||||
orax (hl)
|
||||
addncx (hl)
|
||||
gtax (hl)
|
||||
subnbx (hl)
|
||||
ltax (hl)
|
||||
addx (hl)
|
||||
onax (hl)
|
||||
adcx (hl)
|
||||
offax (hl)
|
||||
subx (hl)
|
||||
neax (hl)
|
||||
sbbx (hl)
|
||||
eqax (hl)
|
||||
anaxi (de)
|
||||
xraxi (de)
|
||||
oraxi (de)
|
||||
addncxi (de)
|
||||
gtaxi (de)
|
||||
subnbxi (de)
|
||||
ltaxi (de)
|
||||
addxi (de)
|
||||
onaxi (de)
|
||||
adcxi (de)
|
||||
offaxi (de)
|
||||
subxi (de)
|
||||
neaxi (de)
|
||||
sbbxi (de)
|
||||
eqaxi (de)
|
||||
anaxi (hl)
|
||||
xraxi (hl)
|
||||
oraxi (hl)
|
||||
addncxi (hl)
|
||||
gtaxi (hl)
|
||||
subnbxi (hl)
|
||||
ltaxi (hl)
|
||||
addxi (hl)
|
||||
onaxi (hl)
|
||||
adcxi (hl)
|
||||
offaxi (hl)
|
||||
subxi (hl)
|
||||
neaxi (hl)
|
||||
sbbxi (hl)
|
||||
eqaxi (hl)
|
||||
anaxd (de)
|
||||
xraxd (de)
|
||||
oraxd (de)
|
||||
addncxd (de)
|
||||
gtaxd (de)
|
||||
subnbxd (de)
|
||||
ltaxd (de)
|
||||
addxd (de)
|
||||
onaxd (de)
|
||||
adcxd (de)
|
||||
offaxd (de)
|
||||
subxd (de)
|
||||
neaxd (de)
|
||||
sbbxd (de)
|
||||
eqaxd (de)
|
||||
anaxd (hl)
|
||||
xraxd (hl)
|
||||
oraxd (hl)
|
||||
addncxd (hl)
|
||||
gtaxd (hl)
|
||||
subnbxd (hl)
|
||||
ltaxd (hl)
|
||||
addxd (hl)
|
||||
onaxd (hl)
|
||||
adcxd (hl)
|
||||
offaxd (hl)
|
||||
subxd (hl)
|
||||
neaxd (hl)
|
||||
sbbxd (hl)
|
||||
eqaxd (hl)
|
||||
|
||||
writebin(filename .. '.bin')
|
|
@ -0,0 +1,638 @@
|
|||
M = require "asm"
|
||||
|
||||
local op_eval_byte = function(late, early) return M.byte_normalize(M.op_eval(late, early)) end
|
||||
M.op_eval_byte = op_eval_byte
|
||||
|
||||
local op_eval_word = function(late, early) return M.word_normalize(M.op_eval(late, early)) end
|
||||
M.op_eval_word = op_eval_word
|
||||
|
||||
local opimp={
|
||||
block=M.op(0x31,13),
|
||||
calb=M.op(0x63,13),
|
||||
daa=M.op(0x61,4),
|
||||
ex=M.op(0x10,4),
|
||||
exx=M.op(0x11,4),
|
||||
halt=M.op(0x01,6),
|
||||
jb=M.op(0x73,4),
|
||||
nop=M.op(0x00,4),
|
||||
ret=M.op(0x08,11),
|
||||
reti=M.op(0x62,15),
|
||||
rets=M.op(0x18,11),
|
||||
sio=M.op(0x09,4),
|
||||
softi=M.op(0x72,19),
|
||||
stm=M.op(0x19,4),
|
||||
['table']=M.op(0x21,19)
|
||||
} M.opimp = opimp
|
||||
for k,v in pairs(opimp) do
|
||||
M[k .. 'imp' ] = function()
|
||||
table.insert(M.section_current.instructions, { size=1, cycles=v.cycles, bin=v.opc })
|
||||
end
|
||||
end
|
||||
|
||||
local opa={
|
||||
dcr=M.op(0x51,4),
|
||||
inr=M.op(0x41,4),
|
||||
} M.opa = opa
|
||||
for k,v in pairs(opa) do
|
||||
M[k .. 'a'] = function()
|
||||
table.insert(M.section_current.instructions, { size=1, cycles=v.cycles, bin=v.opc })
|
||||
end
|
||||
end
|
||||
|
||||
local opb={
|
||||
dcr=M.op(0x52,4),
|
||||
inr=M.op(0x42,4),
|
||||
} M.opb = opb
|
||||
for k,v in pairs(opb) do
|
||||
M[k .. 'b'] = function()
|
||||
table.insert(M.section_current.instructions, { size=1, cycles=v.cycles, bin=v.opc })
|
||||
end
|
||||
end
|
||||
|
||||
local opc={
|
||||
dcr=M.op(0x53,4),
|
||||
inr=M.op(0x43,4),
|
||||
} M.opc = opc
|
||||
for k,v in pairs(opc) do
|
||||
M[k .. 'c'] = function()
|
||||
table.insert(M.section_current.instructions, { size=1, cycles=v.cycles, bin=v.opc })
|
||||
end
|
||||
end
|
||||
|
||||
local opsp={
|
||||
dcx=M.op(0x03,7),
|
||||
inx=M.op(0x02,7)
|
||||
} M.opsp = opsp
|
||||
for k,v in pairs(opsp) do
|
||||
M[k .. 'sp'] = function()
|
||||
table.insert(M.section_current.instructions, { size=1, cycles=v.cycles, bin=v.opc })
|
||||
end
|
||||
end
|
||||
|
||||
local opr16={
|
||||
dcxbc=M.op(0x13,7),
|
||||
dcxde=M.op(0x23,7),
|
||||
dcxhl=M.op(0x33,7),
|
||||
inxbc=M.op(0x12,7),
|
||||
inxde=M.op(0x22,7),
|
||||
inxhl=M.op(0x32,7),
|
||||
ldaxbc=M.op(0x29,7),
|
||||
ldaxdde=M.op(0x2e,7),
|
||||
ldaxde=M.op(0x2a,7),
|
||||
ldaxhl=M.op(0x2b,7),
|
||||
ldaxide=M.op(0x2c,7),
|
||||
ldaxdhl=M.op(0x2f,7),
|
||||
ldaxihl=M.op(0x2d,7),
|
||||
staxbc=M.op(0x39,7),
|
||||
staxde=M.op(0x3a,7),
|
||||
staxdde=M.op(0x3e,7),
|
||||
staxdhl=M.op(0x3f,7),
|
||||
staxhl=M.op(0x3b,7),
|
||||
staxide=M.op(0x3c,7),
|
||||
staxihl=M.op(0x3d,7),
|
||||
} M.opr16 = opr16
|
||||
for k,v in pairs(opr16) do
|
||||
M[k] = function()
|
||||
table.insert(M.section_current.instructions, { size=1, cycles=v.cycles, bin=v.opc })
|
||||
end
|
||||
end
|
||||
|
||||
local opregxx ={
|
||||
mvib=M.op(0x6a,7),
|
||||
mvic=M.op(0x6b,7),
|
||||
mvid=M.op(0x6c,7),
|
||||
mvie=M.op(0x6d,7),
|
||||
mvih=M.op(0x6e,7),
|
||||
mvil=M.op(0x6f,7),
|
||||
mviv=M.op(0x68,7),
|
||||
mvixbc=M.op(0x49,10),
|
||||
mvixde=M.op(0x4a,10),
|
||||
mvixhl=M.op(0x4b,10),
|
||||
} M.opregxx = opregxx
|
||||
for k,v in pairs(opregxx) do
|
||||
M[k] = function(late, early)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local size = function() late,early = M.size_op(late,early) return 2 end
|
||||
local bin = function() local l7801dbg=l7801dbg return { v.opc, M.op_eval_byte(late,early) } end
|
||||
table.insert(M.section_current.instructions, { size=size, cycles=v.cycles, bin=bin })
|
||||
end
|
||||
end
|
||||
|
||||
local opaxx ={
|
||||
aci=M.op(0x56,7),
|
||||
adi=M.op(0x46,7),
|
||||
adinc=M.op(0x26,7),
|
||||
ani=M.op(0x07,7),
|
||||
eqi=M.op(0x77,7),
|
||||
gti=M.op(0x27,7),
|
||||
lti=M.op(0x37,7),
|
||||
mvi=M.op(0x69,7),
|
||||
nei=M.op(0x67,7),
|
||||
offi=M.op(0x57,7),
|
||||
oni=M.op(0x47,7),
|
||||
ori=M.op(0x17,7),
|
||||
sbi=M.op(0x76,7),
|
||||
sui=M.op(0x66,7),
|
||||
suinb=M.op(0x36,7),
|
||||
xri=M.op(0x16,7)
|
||||
} M.opaxx = opaxx
|
||||
for k,v in pairs(opaxx) do
|
||||
M[k .. 'a'] = function(late, early)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local size = function() late,early = M.size_op(late,early) return 2 end
|
||||
local bin = function() local l7801dbg=l7801dbg return { v.opc, M.op_eval_byte(late,early) } end
|
||||
table.insert(M.section_current.instructions, { size=size, cycles=v.cycles, bin=bin })
|
||||
end
|
||||
end
|
||||
|
||||
local opr8r8 ={
|
||||
movab=M.op(0x0a,4), movac=M.op(0x0b,4),
|
||||
movad=M.op(0x0c,4), movae=M.op(0x0d,4),
|
||||
movah=M.op(0x0e,4), moval=M.op(0x0f,4),
|
||||
movba=M.op(0x1a,4), movca=M.op(0x1b,4),
|
||||
movda=M.op(0x1c,4), movea=M.op(0x1d,4),
|
||||
movha=M.op(0x1e,4), movla=M.op(0x1f,4),
|
||||
} M.opr8r8 = opr8r8
|
||||
for k,v in pairs(opr8r8) do
|
||||
M[k] = function()
|
||||
table.insert(M.section_current.instructions, { size=1, cycles=v.cycles, bin=v.opc })
|
||||
end
|
||||
end
|
||||
|
||||
local opw = {
|
||||
call=M.op(0x44,16),
|
||||
jmp=M.op(0x54,10),
|
||||
} M.opw = opw
|
||||
for k,v in pairs(opw) do
|
||||
M[k .. 'imm'] = function(late, early)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local size = function() late,early = M.size_op(late,early) return 3 end
|
||||
local bin = function() local l7801dbg=l7801dbg
|
||||
local x = M.op_eval_word(late,early)
|
||||
return { v.opc, x&0xff, x>>8 }
|
||||
end
|
||||
table.insert(M.section_current.instructions, { size=size, cycles=v.cycles, bin=bin })
|
||||
end
|
||||
end
|
||||
|
||||
local opr16w = {
|
||||
lxisp=M.op(0x04,10),
|
||||
lxibc=M.op(0x14,10),
|
||||
lxide=M.op(0x24,10),
|
||||
lxihl=M.op(0x34,10)
|
||||
} M.opr16w = opr16w
|
||||
for k,v in pairs(opr16w) do
|
||||
M[k] = function(late, early)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local size = function() late,early = M.size_op(late,early) return 3 end
|
||||
local bin = function() local l7801dbg=l7801dbg
|
||||
local x = M.op_eval_word(late,early)
|
||||
return { v.opc, x&0xff, x>>8 }
|
||||
end
|
||||
table.insert(M.section_current.instructions, { size=size, cycles=v.cycles, bin=bin })
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
M['calt' .. 'imm'] = function(late, early)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local op = { cycles=19 }
|
||||
op.size = function() late,early = M.size_op(late,early) return 1 end
|
||||
op.bin = function()
|
||||
local l7801dbg=l7801dbg
|
||||
local x = M.op_eval_byte(late,early)
|
||||
if (x%2 == 1) then error("offset should be even : " .. x) end
|
||||
if x < 0x80 or x > 0xfe then error("offset out of range : " .. x) end
|
||||
x = (x>>1) + 0x40
|
||||
return x
|
||||
end
|
||||
table.insert(M.section_current.instructions, op)
|
||||
end
|
||||
|
||||
M['calf' .. 'imm'] = function(late, early)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local op = { cycles=16 }
|
||||
op.size = function() late,early = M.size_op(late,early) return 2 end
|
||||
op.bin = function() local l7801dbg=l7801dbg
|
||||
local x = 0 + M.op_eval_word(late,early)
|
||||
if x < 0x0800 or x > 0xffff then error("subroutine address out of range [0x0800-0xffff]: " .. x) end
|
||||
x = x - 0x0800;
|
||||
return { 0x78 | ((x>>8) & 0x07), x&0xff }
|
||||
end
|
||||
table.insert(M.section_current.instructions, op)
|
||||
end
|
||||
|
||||
M.jr = function(label)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local parent,offset = M.label_current
|
||||
local section,rorg = M.section_current,M.location_current.rorg
|
||||
local op = { cycles=13 }
|
||||
op.size = function()
|
||||
offset = section.size
|
||||
label = M.size_dc(label)
|
||||
return 1
|
||||
end
|
||||
op.bin = function()
|
||||
local l7801dbg=l7801dbg
|
||||
local x,l = label,label
|
||||
if type(x) == 'function' then x=x() end
|
||||
if type(x) == 'string' then
|
||||
if x:sub(1,1) == '_' then x=parent..x l=x end
|
||||
x = symbols[x]
|
||||
end
|
||||
if type(x) ~= 'number' then error("unresolved branch target: " .. tostring(x)) end
|
||||
x = x-1 - offset - rorg(section.org)
|
||||
if x < -32 or x > 0x32 then error("branch target out of range for " .. l .. ": " .. x)
|
||||
elseif x >= 0 then
|
||||
x = 0xc0 + x
|
||||
return x
|
||||
else
|
||||
return x & 0xff
|
||||
end
|
||||
end
|
||||
table.insert(M.section_current.instructions, op)
|
||||
end
|
||||
|
||||
M.jre = function(label)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local parent,offset = M.label_current
|
||||
local section,rorg = M.section_current,M.location_current.rorg
|
||||
local op = { cycles=17 }
|
||||
op.size = function()
|
||||
offset = section.size
|
||||
label = M.size_dc(label)
|
||||
return 2
|
||||
end
|
||||
op.bin = function()
|
||||
local l7801dbg=l7801dbg
|
||||
local x,l = label,label
|
||||
if type(x) == 'function' then x=x() end
|
||||
if type(x) == 'string' then
|
||||
if x:sub(1,1) == '_' then x=parent..x l=x end
|
||||
x = symbols[x]
|
||||
end
|
||||
if type(x) ~= 'number' then error("unresolved branch target: " .. tostring(x)) end
|
||||
x = x-2 - offset - rorg(section.org)
|
||||
if x < -128 or x > 127 then error("branch target out of range for " .. l .. ": " .. x) end
|
||||
local opcode = x >= 0 and 0x4e or 0x4f
|
||||
return { opcode, x&0xff }
|
||||
end
|
||||
table.insert(M.section_current.instructions, op)
|
||||
end
|
||||
|
||||
local opwa = {
|
||||
inrw=M.op(0x20,13),
|
||||
ldaw=M.op(0x28,10),
|
||||
dcrw=M.op(0x30,13),
|
||||
staw=M.op(0x38,10),
|
||||
bit0=M.op(0x58,10),
|
||||
bit1=M.op(0x59,10),
|
||||
bit2=M.op(0x5a,10),
|
||||
bit3=M.op(0x5b,10),
|
||||
bit4=M.op(0x5c,10),
|
||||
bit5=M.op(0x5d,10),
|
||||
bit6=M.op(0x5e,10),
|
||||
bit7=M.op(0x5f,10)
|
||||
} M.opwa = opwa
|
||||
for k,v in pairs(opwa) do
|
||||
M[k .. 'wa'] = function(late, early)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local size = function() late,early = M.size_op(late,early) return 2 end
|
||||
local bin = function() local l7801dbg=l7801dbg return { v.opc, M.op_eval_byte(late,early) } end
|
||||
table.insert(M.section_current.instructions, { size=size, cycles=v.cycles, bin=bin })
|
||||
end
|
||||
end
|
||||
|
||||
local opwaxx = {
|
||||
mviw=M.op(0x71,3,13),
|
||||
eqiw=M.op(0x75,3,13),
|
||||
} M.opwaxx = opwaxx
|
||||
for k,v in pairs(opwaxx) do
|
||||
M[k .. 'waxx'] = function(late_offset, late_data, early_offset, early_data)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local size = function()
|
||||
late_offset,early_offset = M.size_op(late_offset,early_offset)
|
||||
late_data,early_data = M.size_op(late_data,early_data)
|
||||
return 3
|
||||
end
|
||||
local bin = function()
|
||||
local l7801dbg=l7801dbg
|
||||
return { v.opc, M.op_eval_byte(late_offset,early_offset), M.op_eval_byte(late_data,early_data) }
|
||||
end
|
||||
table.insert(M.section_current.instructions, { size=size, cycles=v.cycles, bin=bin })
|
||||
end
|
||||
end
|
||||
|
||||
local op48imp = {
|
||||
ei=M.op(0x20,8),
|
||||
di=M.op(0x24,8),
|
||||
clc=M.op(0x2a,8),
|
||||
pen=M.op(0x2c,11),
|
||||
per=M.op(0x3c,11),
|
||||
pex=M.op(0x2d,11),
|
||||
rld=M.op(0x38,17),
|
||||
rrd=M.op(0x39,17),
|
||||
skc=M.op(0x0a,8),
|
||||
skz=M.op(0x0c,8),
|
||||
sknc=M.op(0x1a,8),
|
||||
sknz=M.op(0x1c,8),
|
||||
stc=M.op(0x2b,8),
|
||||
} M.op48imp = op48imp
|
||||
for k,v in pairs(op48imp) do
|
||||
M[k .. 'imp'] = function()
|
||||
table.insert(M.section_current.instructions, { size=2, cycles=v.cycles, bin={ 0x48, v.opc } })
|
||||
end
|
||||
end
|
||||
|
||||
local op48r8={
|
||||
rlla=M.op(0x30,8),
|
||||
rlra=M.op(0x31,8),
|
||||
rllc=M.op(0x32,8),
|
||||
rlrc=M.op(0x33,8),
|
||||
slla=M.op(0x34,8),
|
||||
slra=M.op(0x35,8),
|
||||
sllc=M.op(0x36,8),
|
||||
slrc=M.op(0x37,8),
|
||||
} M.op48r8 = op48r8
|
||||
for k,v in pairs(op48r8) do
|
||||
M[k] = function()
|
||||
table.insert(M.section_current.instructions, { size=2, cycles=v.cycles, bin={ 0x48, v.opc } })
|
||||
end
|
||||
end
|
||||
|
||||
local op48r16={
|
||||
pushbc=M.op(0x1e,17),
|
||||
pushde=M.op(0x2e,17),
|
||||
pushhl=M.op(0x3e,17),
|
||||
pushva=M.op(0x0e,17),
|
||||
popbc=M.op(0x1f,15),
|
||||
popde=M.op(0x2f,15),
|
||||
pophl=M.op(0x3f,15),
|
||||
popva=M.op(0x0f,15),
|
||||
} M.op48r16 = op48r16
|
||||
for k,v in pairs(op48r16) do
|
||||
M[k] = function()
|
||||
table.insert(M.section_current.instructions, { size=2, cycles=v.cycles, bin={ 0x48, v.opc } })
|
||||
end
|
||||
end
|
||||
|
||||
local op48int={
|
||||
skitf0=M.op(0x00,8),
|
||||
skitft=M.op(0x01,8),
|
||||
skitf1=M.op(0x02,8),
|
||||
skitf2=M.op(0x03,8),
|
||||
skitfs=M.op(0x04,8),
|
||||
sknitf0=M.op(0x10,8),
|
||||
sknitft=M.op(0x11,8),
|
||||
sknitf1=M.op(0x12,8),
|
||||
sknitf2=M.op(0x13,8),
|
||||
sknitfs=M.op(0x14,8),
|
||||
} M.op48int = op48int
|
||||
for k,v in pairs(op48int) do
|
||||
M[k] = function()
|
||||
table.insert(M.section_current.instructions, { size=2, cycles=v.cycles, bin={ 0x48, v.opc } })
|
||||
end
|
||||
end
|
||||
|
||||
-- IN/OUT
|
||||
local opinout={
|
||||
['in']=M.op(0x4c,10),
|
||||
out=M.op(0x4d,10),
|
||||
} M.opinout = op4inout
|
||||
for k,v in pairs(opinout) do
|
||||
M[k .. 'imm'] = function(late, early)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local op = { cycles=v.cycles }
|
||||
op.size = function() late,early = M.size_op(late,early) return 2 end
|
||||
op.bin = function() local l7801dbg=l7801dbg
|
||||
local x = 0x00 + M.op_eval_byte(late,early)
|
||||
return { v.opc, 0x00, x }
|
||||
end
|
||||
table.insert(M.section_current.instructions, op)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local op4car8={
|
||||
movapa=M.op(0xc0,10),
|
||||
movapb=M.op(0xc1,10),
|
||||
movapc=M.op(0xc2,10),
|
||||
movamk=M.op(0xc3,10),
|
||||
movamb=M.op(0xc4,10),
|
||||
movamc=M.op(0xc5,10),
|
||||
movatm0=M.op(0xc6,10),
|
||||
movatm1=M.op(0xc7,10),
|
||||
movas=M.op(0xc8,10),
|
||||
} M.op4car8 = op4car8
|
||||
for k,v in pairs(op4car8) do
|
||||
M[k] = function()
|
||||
table.insert(M.section_current.instructions, { size=2, cycles=v.cycles, bin={ 0x4c, v.opc } })
|
||||
end
|
||||
end
|
||||
|
||||
local op4dr8a={
|
||||
movpaa=M.op(0xc0,10),
|
||||
movpba=M.op(0xc1,10),
|
||||
movpca=M.op(0xc2,10),
|
||||
movmka=M.op(0xc3,10),
|
||||
movmba=M.op(0xc4,10),
|
||||
movmca=M.op(0xc5,10),
|
||||
movtm0a=M.op(0xc6,10),
|
||||
movtm1a=M.op(0xc7,10),
|
||||
movsa=M.op(0xc8,10),
|
||||
} M.op4dr8a = op4dr8a
|
||||
for k,v in pairs(op4dr8a) do
|
||||
M[k] = function()
|
||||
table.insert(M.section_current.instructions, { size=2, cycles=v.cycles, bin={ 0x4d, v.opc } })
|
||||
end
|
||||
end
|
||||
|
||||
local op60names = {'ana','xra','ora','addnc','gta','subnb','lta','add','','adc','','sub','nea','sbb','eqa'}
|
||||
local register_names = {'v','a','b','c','d','e','h','l'}
|
||||
local k = 0x08
|
||||
for i,o in ipairs(op60names) do
|
||||
if o == '' then
|
||||
k = k + #register_names
|
||||
else
|
||||
for j,r in ipairs(register_names) do
|
||||
local l = k
|
||||
M[o .. r .. 'a'] = function()
|
||||
table.insert(M.section_current.instructions, { size=2, cycles=8, bin={ 0x60, l } })
|
||||
end
|
||||
k = k + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
k = 0x88
|
||||
op60names[9] = 'ona'
|
||||
op60names[11] = 'offa'
|
||||
for i,o in ipairs(op60names) do
|
||||
if o == '' then
|
||||
k = k + #register_names
|
||||
else
|
||||
for j,r in ipairs(register_names) do
|
||||
local l = k
|
||||
local name = o .. 'a' .. r
|
||||
if not M[name] then
|
||||
M[name] = function()
|
||||
table.insert(M.section_current.instructions, { size=2, cycles=8, bin={ 0x60, l } })
|
||||
end
|
||||
end
|
||||
k = k + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
k = 0x08
|
||||
local op64names = { 'ani','xri','ori','adinc','gti','suinb','lti','adi','oni','aci','offi','sui','nei','sbi','eqi' }
|
||||
for i,o in ipairs(op64names) do
|
||||
for j,r in ipairs(register_names) do
|
||||
local name = o .. r
|
||||
if not M[name] then
|
||||
local l = k
|
||||
M[name] = function(late,early)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local op = { cycles=11 }
|
||||
op.size = function() late,early = M.size_op(late,early) return 3 end
|
||||
op.bin = function() local l7801dbg=l7801dbg
|
||||
local x = 0x00 + l;
|
||||
local y = 0x00 + M.op_eval_byte(late,early)
|
||||
return { 0x64, x, y }
|
||||
end
|
||||
table.insert(M.section_current.instructions, op)
|
||||
end
|
||||
end
|
||||
k = k + 1
|
||||
end
|
||||
end
|
||||
|
||||
k = 0x88
|
||||
local ex_register_names = {'pa','pb','pc','mk'}
|
||||
for i,o in ipairs(op64names) do
|
||||
for j,r in ipairs(ex_register_names) do
|
||||
local name = o .. r
|
||||
if not M[name] then
|
||||
local l = k
|
||||
M[name] = function(late,early)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local op = { cycles=11 }
|
||||
op.size = function() late,early = M.size_op(late,early) return 3 end
|
||||
op.bin = function() local l7801dbg=l7801dbg
|
||||
local x = 0x00 + l;
|
||||
local y = 0x00 + M.op_eval_byte(late,early)
|
||||
return { 0x64, x, y }
|
||||
end
|
||||
table.insert(M.section_current.instructions, op)
|
||||
end
|
||||
end
|
||||
k = k + 1
|
||||
end
|
||||
k = k + 4
|
||||
end
|
||||
|
||||
local op74wa = {
|
||||
anaw=M.op(0x88,14),
|
||||
xraw=M.op(0x90,14),
|
||||
oraw=M.op(0x98,14),
|
||||
addncw=M.op(0xa0,14),
|
||||
gtaw=M.op(0xa8,14),
|
||||
subnbw=M.op(0xb0,14),
|
||||
ltaw=M.op(0xb8,14),
|
||||
addw=M.op(0xc0,14),
|
||||
onaw=M.op(0xc8,14),
|
||||
adcw=M.op(0xd0,14),
|
||||
offaw=M.op(0xd8,14),
|
||||
subw=M.op(0xe0,14),
|
||||
neaw=M.op(0xe8,14),
|
||||
sbbw=M.op(0xf0,14),
|
||||
eqaw=M.op(0xf8,14),
|
||||
} M.op74wa = op74wa
|
||||
for k,v in pairs(op74wa) do
|
||||
M[k .. 'wa'] = function(late, early)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local size = function() late,early = M.size_op(late,early) return 3 end
|
||||
local bin = function() local l7801dbg=l7801dbg return { 0x74, v.opc, M.op_eval_byte(late,early) } end
|
||||
table.insert(M.section_current.instructions, { size=size, cycles=v.cycles, bin=bin })
|
||||
end
|
||||
end
|
||||
|
||||
local op70ind = {
|
||||
sspd=M.op(0x0e,20),
|
||||
lspd=M.op(0x0f,20),
|
||||
sbcd=M.op(0x1e,20),
|
||||
lbcd=M.op(0x1f,20),
|
||||
sded=M.op(0x2e,20),
|
||||
lded=M.op(0x2f,20),
|
||||
shld=M.op(0x3e,20),
|
||||
lhld=M.op(0x3f,20),
|
||||
} M.op70ind = op70ind
|
||||
for k,v in pairs(op70ind) do
|
||||
M[k] = function(late, early)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local size = function() late,early = M.size_op(late,early) return 4 end
|
||||
local bin = function() local l7801dbg=l7801dbg
|
||||
local x = M.op_eval_word(late,early)
|
||||
return { 0x70, v.opc, x&0xff, x>>8 }
|
||||
end
|
||||
table.insert(M.section_current.instructions, { size=size, cycles=v.cycles, bin=bin })
|
||||
end
|
||||
end
|
||||
|
||||
local op70indr8 = {
|
||||
movindv=M.op(0x78,17),
|
||||
movinda=M.op(0x79,17),
|
||||
movindb=M.op(0x7a,17),
|
||||
movindc=M.op(0x7b,17),
|
||||
movindd=M.op(0x7c,17),
|
||||
movinde=M.op(0x7d,17),
|
||||
movindh=M.op(0x7e,17),
|
||||
movindl=M.op(0x7f,17),
|
||||
} M.op70indr8 = op70indr8
|
||||
for k,v in pairs(op70indr8) do
|
||||
M[k] = function(late, early)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local size = function() late,early = M.size_op(late,early) return 4 end
|
||||
local bin = function() local l7801dbg=l7801dbg
|
||||
local x = M.op_eval_word(late,early)
|
||||
return { 0x70, v.opc, x&0xff, x>>8 }
|
||||
end
|
||||
table.insert(M.section_current.instructions, { size=size, cycles=v.cycles, bin=bin })
|
||||
end
|
||||
end
|
||||
|
||||
local op70r8ind = {
|
||||
movvind=M.op(0x68,17),
|
||||
movaind=M.op(0x69,17),
|
||||
movbind=M.op(0x6a,17),
|
||||
movcind=M.op(0x6b,17),
|
||||
movdind=M.op(0x6c,17),
|
||||
moveind=M.op(0x6d,17),
|
||||
movhind=M.op(0x6e,17),
|
||||
movlind=M.op(0x6f,17),
|
||||
} M.op70r8ind = op70r8ind
|
||||
for k,v in pairs(op70r8ind) do
|
||||
M[k] = function(late, early)
|
||||
local l7801dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
|
||||
local size = function() late,early = M.size_op(late,early) return 4 end
|
||||
local bin = function() local l7801dbg=l7801dbg
|
||||
local x = M.op_eval_word(late,early)
|
||||
return { 0x70, v.opc, x&0xff, x>>8 }
|
||||
end
|
||||
table.insert(M.section_current.instructions, { size=size, cycles=v.cycles, bin=bin })
|
||||
end
|
||||
end
|
||||
|
||||
k = 0x89
|
||||
local op70names = {'anax','xrax','orax','addncx','gtax','subnbx','ltax','addx','onax','adcx','offax','subx','neax','sbbx','eqax'}
|
||||
local op70suffixes = {'bc','de','hl','ide','ihl','dde','dhl'}
|
||||
for i,o in ipairs(op70names) do
|
||||
for j,s in ipairs(op70suffixes) do
|
||||
local l = 0x00 + k + (j-1) + (8 * (i-1))
|
||||
M[o .. s] = function()
|
||||
table.insert(M.section_current.instructions, { size=2, cycles=11, bin={ 0x70, l } })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
Loading…
Reference in New Issue