Added ability to define the zero page outside 00-FF, with PC-Engine in mind.

This commit is contained in:
g012 2017-12-25 23:23:22 +01:00
parent 75db428750
commit f3bd018090
3 changed files with 33 additions and 18 deletions

View File

@ -808,6 +808,9 @@ M.long = function(...)
table.insert(M.section_current.instructions, { data=data, size=size, bin=bin }) table.insert(M.section_current.instructions, { data=data, size=size, bin=bin })
end end
-- Return a value in rage [0x00, 0xff] if x is to use zeropage addressing mode. Defaults to range [0x0000-0x00ff].
M.zeropage = function(x) if x >= -128 and x <= 0xff then return byte_normalize(x) end end
local op,cycles_def,xcross_def local op,cycles_def,xcross_def
op = function(code, cycles, extra_on_crosspage) op = function(code, cycles, extra_on_crosspage)
return { opc=code, cycles=cycles or cycles_def, xcross=extra_on_crosspage or xcross_def } return { opc=code, cycles=cycles or cycles_def, xcross=extra_on_crosspage or xcross_def }
@ -816,7 +819,12 @@ local op_eval = function(late, early)
local x = early or 0 local x = early or 0
return type(late) == 'function' and late(x,op_resolve) or x+op_resolve(late) return type(late) == 'function' and late(x,op_resolve) or x+op_resolve(late)
end end
local op_eval_byte = function(late, early) return byte_normalize(op_eval(late, early)) end local op_eval_byte = function(late, early, nozp)
local v = op_eval(late, early)
local zpv = zeropage(v)
if not nozp and zpv then return zpv end
return byte_normalize(v)
end
local op_eval_word = function(late, early) return word_normalize(op_eval(late, early)) end local op_eval_word = function(late, early) return word_normalize(op_eval(late, early)) end
cycles_def=2 xcross_def=0 local opimp={ cycles_def=2 xcross_def=0 local opimp={
asl=op(0x0a), brk=op(0x00,7), clc=op(0x18), cld=op(0xd8), cli=op(0x58), clv=op(0xb8), dex=op(0xca), dey=op(0x88), asl=op(0x0a), brk=op(0x00,7), clc=op(0x18), cld=op(0xd8), cli=op(0x58), clv=op(0xb8), dex=op(0xca), dey=op(0x88),
@ -839,7 +847,7 @@ for k,v in pairs(opimm) do
M[k .. 'imm'] = function(late, early) M[k .. 'imm'] = function(late, early)
local l65dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) } local l65dbg = { info=debug.getinfo(2, 'Sl'), trace=debug.traceback(nil, 1) }
local size = function() late,early = size_op(late,early) return 2 end local size = function() late,early = size_op(late,early) return 2 end
local bin = function() local l65dbg=l65dbg return { v.opc, op_eval_byte(late,early) } end local bin = function() local l65dbg=l65dbg return { v.opc, op_eval_byte(late,early,true) } end
table.insert(M.section_current.instructions, { size=size, cycles=2, bin=bin }) table.insert(M.section_current.instructions, { size=size, cycles=2, bin=bin })
end end
end end
@ -882,7 +890,7 @@ for k,_ in pairs(opzab) do
M[k .. 'zab'] = function(late, early) M[k .. 'zab'] = function(late, early)
if type(late) ~= 'function' then if type(late) ~= 'function' then
local x = (early or 0) + late local x = (early or 0) + late
if x >= -128 and x <= 0xff then return M[k .. 'zpg'](late, early) end if zeropage(x) then return M[k .. 'zpg'](late, early) end
if x >= -32768 and x <= 0xffff then return M[k .. 'abs'](late, early) end if x >= -32768 and x <= 0xffff then return M[k .. 'abs'](late, early) end
error("value out of word range: " .. x) error("value out of word range: " .. x)
end end
@ -894,11 +902,11 @@ for k,_ in pairs(opzab) do
if not r then return 3 end if not r then return 3 end
size_ref(x) size_ref(x)
x = word_normalize(x) x = word_normalize(x)
local zpg = opzpg[k] local zpg,zpv = opzpg[k], zeropage(x)
if x <= 0xff and zpg then if zpv and zpg then
ins.size = 2 ins.size = 2
ins.cycles = zpg.cycles ins.cycles = zpg.cycles
ins.bin = function() return { zpg.opc, x } end ins.bin = function() return { zpg.opc, zpv } end
return 2 return 2
end end
ins.size = 3 ins.size = 3
@ -908,7 +916,7 @@ for k,_ in pairs(opzab) do
ins.bin = function() local l65dbg=l65dbg ins.bin = function() local l65dbg=l65dbg
local x = word_normalize(op_eval(late, early)) local x = word_normalize(op_eval(late, early))
-- since we assumed absolute on link phase, we must generate absolute in binary -- since we assumed absolute on link phase, we must generate absolute in binary
if x <= 0xff and opzpg[k] then io.stderr:write("warning: forcing abs on zpg operand for opcode " .. k .. "\n") end if zeropage(x) and opzpg[k] then io.stderr:write("warning: forcing abs on zpg operand for opcode " .. k .. "\n") end
return { abs.opc, x&0xff, x>>8 } return { abs.opc, x&0xff, x>>8 }
end end
table.insert(M.section_current.instructions, ins) table.insert(M.section_current.instructions, ins)
@ -950,7 +958,7 @@ for k,_ in pairs(opzax) do
M[k .. 'zax'] = function(late, early) M[k .. 'zax'] = function(late, early)
if type(late) ~= 'function' then if type(late) ~= 'function' then
local x = (early or 0) + late local x = (early or 0) + late
if x >= -128 and x <= 0xff then return M[k .. 'zpx'](late, early) end if zeropage(x) then return M[k .. 'zpx'](late, early) end
if x >= -32768 and x <= 0xffff then return M[k .. 'abx'](late, early) end if x >= -32768 and x <= 0xffff then return M[k .. 'abx'](late, early) end
error("value out of word range: " .. x) error("value out of word range: " .. x)
end end
@ -962,11 +970,11 @@ for k,_ in pairs(opzax) do
if not r then return 3 end if not r then return 3 end
size_ref(x) size_ref(x)
x = word_normalize(x) x = word_normalize(x)
local zpx = opzpx[k] local zpx,zpv = opzpx[k], zeropage(x)
if x <= 0xff and zpx then if zpv and zpx then
ins.size = 2 ins.size = 2
ins.cycles = zpx.cycles ins.cycles = zpx.cycles
ins.bin = function() return { zpx.opc, x } end ins.bin = function() return { zpx.opc, zpv } end
return 2 return 2
end end
ins.size = 3 ins.size = 3
@ -976,7 +984,7 @@ for k,_ in pairs(opzax) do
ins.bin = function() local l65dbg=l65dbg ins.bin = function() local l65dbg=l65dbg
local x = word_normalize(op_eval(late, early)) local x = word_normalize(op_eval(late, early))
-- since we assumed absolute on link phase, we must generate absolute in binary -- since we assumed absolute on link phase, we must generate absolute in binary
if x <= 0xff and opzpx[k] then io.stderr:write("warning: forcing abx on zpx operand for opcode " .. k .. "\n") end if zeropage(x) and opzpx[k] then io.stderr:write("warning: forcing abx on zpx operand for opcode " .. k .. "\n") end
return { abx.opc, x&0xff, x>>8 } return { abx.opc, x&0xff, x>>8 }
end end
table.insert(M.section_current.instructions, ins) table.insert(M.section_current.instructions, ins)
@ -1017,7 +1025,7 @@ for k,_ in pairs(opzay) do
M[k .. 'zay'] = function(late, early) M[k .. 'zay'] = function(late, early)
if type(late) ~= 'function' then if type(late) ~= 'function' then
local x = (early or 0) + late local x = (early or 0) + late
if x >= -128 and x <= 0xff then return M[k .. 'zpy'](late, early) end if zeropage(x) then return M[k .. 'zpy'](late, early) end
if x >= -32768 and x <= 0xffff then return M[k .. 'aby'](late, early) end if x >= -32768 and x <= 0xffff then return M[k .. 'aby'](late, early) end
error("value out of word range: " .. x) error("value out of word range: " .. x)
end end
@ -1029,11 +1037,11 @@ for k,_ in pairs(opzay) do
if not r then return 3 end if not r then return 3 end
size_ref(x) size_ref(x)
x = word_normalize(x) x = word_normalize(x)
local zpy = opzpy[k] local zpy,zpv = opzpy[k], zeropage(x)
if x <= 0xff and zpy then if zpv and zpy then
ins.size = 2 ins.size = 2
ins.cycles = zpy.cycles ins.cycles = zpy.cycles
ins.bin = function() return { zpy.opc, x } end ins.bin = function() return { zpy.opc, zpv } end
return 2 return 2
end end
ins.size = 3 ins.size = 3
@ -1043,7 +1051,7 @@ for k,_ in pairs(opzay) do
ins.bin = function() local l65dbg=l65dbg ins.bin = function() local l65dbg=l65dbg
local x = word_normalize(op_eval(late, early)) local x = word_normalize(op_eval(late, early))
-- since we assumed absolute on link phase, we must generate absolute in binary -- since we assumed absolute on link phase, we must generate absolute in binary
if x <= 0xff and opzpy[k] then io.stderr:write("warning: forcing aby on zpy operand for opcode " .. k .. "\n") end if zeropage(x) and opzpy[k] then io.stderr:write("warning: forcing aby on zpy operand for opcode " .. k .. "\n") end
return { aby.opc, x&0xff, x>>8 } return { aby.opc, x&0xff, x>>8 }
end end
table.insert(M.section_current.instructions, ins) table.insert(M.section_current.instructions, ins)

View File

@ -317,6 +317,8 @@ Check if `v` is within long range, call `error` if it is not, or convert negativ
`pcall_za`: ...unless this field is set to system's `pcall`. Defaults to module's `pcall`. This field is used only by the `za*` (`zab`, `zax`, `zay`) virtual addressing modes, to discriminate between zeropage and absolute addressing. `pcall_za`: ...unless this field is set to system's `pcall`. Defaults to module's `pcall`. This field is used only by the `za*` (`zab`, `zax`, `zay`) virtual addressing modes, to discriminate between zeropage and absolute addressing.
`zeropage`: a function with one number parameter, returning its zeropage byte value if it is within zero/direct page addressing range, nothing otherwise. Set by default to page [0x0000, 0x00ff].
`symbols`: list of symbols, resolved or not. Values can be anything before the resolve phase, but must be numbers after (except for the metatable fields). Set as the metatable of the 6502 module, which itself should be set as the metatable of the current `_ENV` environment. `symbols`: list of symbols, resolved or not. Values can be anything before the resolve phase, but must be numbers after (except for the metatable fields). Set as the metatable of the 6502 module, which itself should be set as the metatable of the current `_ENV` environment.
`locations`: list of all the registered locations. `locations`: list of all the registered locations.
@ -336,7 +338,7 @@ Check if `v` is within long range, call `error` if it is not, or convert negativ
`id()`: return a new unique numeric identifier. `id()`: return a new unique numeric identifier.
`stats`: a table of statistics regarding the build: `stats`: a table of statistics regarding the build:
* `cycles`: the total 6502 cycle count of the program, considering no branch is taken and no page is crossed. * `cycles`: the total 6502 cycle count of the program, assuming no branch is taken and no page is crossed.
* `used`: the total ROM bytes actually used by the program. * `used`: the total ROM bytes actually used by the program.
* `unused`: total empty ROM space. * `unused`: total empty ROM space.
* `resolved_count`: number of symbols resolved during resolve phase. * `resolved_count`: number of symbols resolved during resolve phase.

5
pce.l65 Normal file
View File

@ -0,0 +1,5 @@
-- set cpu to HuC6280
cpu = require "6502"
setmetatable(_ENV, cpu)
cpu.zeropage = function(x) if x >= 0x2000 and x <= 0x20ff then return x&0xff end end