mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-08 15:34:09 +00:00
Breakup instructions and action list into halfword chunks.
This should allow us to encode the instructions relatively naturally and efficiently. For now I've escaped halfwords with a value <= the maximum action. This means that 0 is escaped which probably isn't ideal, so we may want to revisit that decision at some point.
This commit is contained in:
parent
d97dea2e3f
commit
000b1a84f0
@ -48,8 +48,10 @@ local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
|
|||||||
|
|
||||||
-- Action name -> action number.
|
-- Action name -> action number.
|
||||||
local map_action = {}
|
local map_action = {}
|
||||||
|
local max_action = 0
|
||||||
for n,name in ipairs(action_names) do
|
for n,name in ipairs(action_names) do
|
||||||
map_action[name] = n-1
|
map_action[name] = n-1
|
||||||
|
max_action = n
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Action list buffer.
|
-- Action list buffer.
|
||||||
@ -77,25 +79,35 @@ end
|
|||||||
local function writeactions(out, name)
|
local function writeactions(out, name)
|
||||||
local nn = #actlist
|
local nn = #actlist
|
||||||
if nn == 0 then nn = 1; actlist[0] = map_action.STOP end
|
if nn == 0 then nn = 1; actlist[0] = map_action.STOP end
|
||||||
out:write("static const unsigned int ", name, "[", nn, "] = {\n")
|
out:write("static const unsigned short ", name, "[", nn, "] = {")
|
||||||
for i = 1,nn-1 do
|
local esc = false -- also need to escape for action arguments
|
||||||
assert(out:write("0x", tohex(actlist[i]), ",\n"))
|
for i = 1,nn do
|
||||||
|
assert(out:write("\n 0x", sub(tohex(actlist[i]), 5, 8)))
|
||||||
|
if i ~= nn then assert(out:write(",")) end
|
||||||
|
local name = action_names[actlist[i]+1]
|
||||||
|
if not esc and name then
|
||||||
|
assert(out:write(" /* ", name, " */"))
|
||||||
|
esc = name == "ESC" or name == "SECTION"
|
||||||
|
else
|
||||||
|
esc = false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n"))
|
assert(out:write("\n};\n\n"))
|
||||||
end
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- Add word to action list.
|
-- Add halfword to action list.
|
||||||
local function wputxw(n)
|
local function wputxhw(n)
|
||||||
assert(n >= 0 and n <= 0xffffffffffff and n % 1 == 0, "word out of range") -- s390x inst can be 6 bytes
|
assert(n >= 0 and n <= 0xffff, "halfword out of range")
|
||||||
actlist[#actlist+1] = n
|
actlist[#actlist+1] = n
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add action to list with optional arg. Advance buffer pos, too.
|
-- Add action to list with optional arg. Advance buffer pos, too.
|
||||||
local function waction(action, val, a, num)
|
local function waction(action, val, a, num)
|
||||||
local w = assert(map_action[action], "bad action name `"..action.."'")
|
local w = assert(map_action[action], "bad action name `"..action.."'")
|
||||||
wputxw(w * 0x10000 + (val or 0))
|
wputxhw(w)
|
||||||
|
if val then wputxhw(val) end -- Not sure about this, do we always have one arg?
|
||||||
if a then actargs[#actargs+1] = a end
|
if a then actargs[#actargs+1] = a end
|
||||||
if a or num then secpos = secpos + (num or 1) end
|
if a or num then secpos = secpos + (num or 1) end
|
||||||
end
|
end
|
||||||
@ -109,29 +121,19 @@ local function wflush(term)
|
|||||||
secpos = 1 -- The actionlist offset occupies a buffer position, too.
|
secpos = 1 -- The actionlist offset occupies a buffer position, too.
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Put escaped word. --Need to check this as well, not sure how it will work on s390x
|
-- Put escaped halfword.
|
||||||
local function wputw(n)
|
local function wputhw(n)
|
||||||
if n <= 0x000fffff then waction("ESC") end
|
if n <= max_action then waction("ESC") end
|
||||||
wputxw(n)
|
wputxhw(n)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Reserve position for word.
|
-- Reserve position for halfword.
|
||||||
local function wpos()
|
local function wpos()
|
||||||
local pos = #actlist+1
|
local pos = #actlist+1
|
||||||
actlist[pos] = ""
|
actlist[pos] = ""
|
||||||
return pos
|
return pos
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Store word to reserved position. -- added 2 bytes more since s390x has 6 bytes inst as well
|
|
||||||
local function wputpos(pos, n)
|
|
||||||
assert(n >= 0 and n <= 0xffffffffffff and n % 1 == 0, "word out of range")
|
|
||||||
if n <= 0x000fffff then
|
|
||||||
insert(actlist, pos+1, n)
|
|
||||||
n = map_action.ESC * 0x10000
|
|
||||||
end
|
|
||||||
actlist[pos] = n
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- Global label name -> global label number. With auto assignment on 1st use.
|
-- Global label name -> global label number. With auto assignment on 1st use.
|
||||||
@ -942,35 +944,16 @@ end
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- Handle opcodes defined with template strings.
|
-- Handle opcodes defined with template strings.
|
||||||
local function parse_template(params, template, nparams, pos)
|
local function parse_template(params, template, nparams, pos)
|
||||||
local op = tonumber(sub(template, 1, 16), 16) --
|
-- Read the template in 16-bit chunks.
|
||||||
-- 00000000005a0000 converts to 90
|
-- Leading halfword zeroes should not be written out.
|
||||||
|
local op0 = tonumber(sub(template, 5, 8), 16)
|
||||||
|
local op1 = tonumber(sub(template, 9, 12), 16)
|
||||||
|
local op2 = tonumber(sub(template, 13, 16), 16)
|
||||||
|
|
||||||
local n,rs = 1,26
|
local n,rs = 1,26
|
||||||
|
|
||||||
parse_reg_type = false
|
parse_reg_type = false
|
||||||
-- Process each character.
|
-- Process each character.
|
||||||
for p in gmatch(sub(template, 17), ".") do
|
|
||||||
local pr1,pr2,pr3
|
|
||||||
if p == "g" then
|
|
||||||
pr1,pr2=params[n],params[n+1]
|
|
||||||
op = op + shl(parse_reg(pr1),4) + parse_reg(pr2); n = n + 1 -- not sure if we will require n later, so keeping it as it is now
|
|
||||||
elseif p == "h" then
|
|
||||||
pr1,pr2=params[n],params[n+1]
|
|
||||||
op = op + shl(parse_gpr(pr1),4) + parse_gpr(pr2)
|
|
||||||
elseif p == "j" then
|
|
||||||
op = op + shl(parse_reg(param[1]),24) + shl(parse_reg(param[2]),20) + shl(parse_reg(param[3]),16) + parse_number(param[4])
|
|
||||||
-- assuming that the parameters are passes in order (R1,X2,B2,D) --only RX-a is satisfied
|
|
||||||
elseif p == "k" then
|
|
||||||
op = op + shl(parse_reg(param[1]),40) + shl(parse_reg(param[2]),36) + shl(parse_reg(param[3]),32) + parse_number(param[4]) + parse_number(param[5])
|
|
||||||
-- assuming params are passed as (R1,X2,B2,DL2,DH2)
|
|
||||||
elseif p == "l" then
|
|
||||||
|
|
||||||
elseif p == "m" then
|
|
||||||
|
|
||||||
elseif p == "n" then
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- TODO
|
-- TODO
|
||||||
-- 12-bit displacements (DISP12) and 16-bit immediates (IMM16) can be put at
|
-- 12-bit displacements (DISP12) and 16-bit immediates (IMM16) can be put at
|
||||||
-- one of two locations relative to the end of the instruction.
|
-- one of two locations relative to the end of the instruction.
|
||||||
@ -982,19 +965,42 @@ local function parse_template(params, template, nparams, pos)
|
|||||||
-- oorr iiii 00oo
|
-- oorr iiii 00oo
|
||||||
-- This should be emitted as oorr, followed by the immediate action, followed by
|
-- This should be emitted as oorr, followed by the immediate action, followed by
|
||||||
-- 00oo.
|
-- 00oo.
|
||||||
|
for p in gmatch(sub(template, 17), ".") do
|
||||||
|
local pr1,pr2,pr3
|
||||||
|
if p == "g" then
|
||||||
|
pr1,pr2=params[n],params[n+1]
|
||||||
|
op2 = op2 + shl(parse_reg(pr1),4) + parse_reg(pr2)
|
||||||
|
wputhw(op2)
|
||||||
|
elseif p == "h" then
|
||||||
|
pr1,pr2=params[n],params[n+1]
|
||||||
|
op2 = op2 + shl(parse_gpr(pr1),4) + parse_gpr(pr2)
|
||||||
|
wputhw(op1); wputhw(op2)
|
||||||
|
elseif p == "j" then
|
||||||
|
op1 = op1 + shl(parse_reg(param[1], 8))
|
||||||
|
wputhw(op1); wputhw(op2)
|
||||||
|
-- TODO: parse param[2] using parse_mem_bx, need to put x into op1, b and d
|
||||||
|
-- into op2, emitting an action for the DISP12 afterwards if necessary.
|
||||||
|
elseif p == "k" then
|
||||||
|
|
||||||
|
elseif p == "l" then
|
||||||
|
|
||||||
|
elseif p == "m" then
|
||||||
|
|
||||||
|
elseif p == "n" then
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
wputpos(pos, op)
|
|
||||||
end
|
end
|
||||||
function op_template(params, template, nparams)
|
function op_template(params, template, nparams)
|
||||||
if not params then return template:gsub("%x%x%x%x%x%x%x%x", "") end
|
if not params then return template:gsub("%x%x%x%x%x%x%x%x", "") end
|
||||||
-- Limit number of section buffer positions used by a single dasm_put().
|
-- Limit number of section buffer positions used by a single dasm_put().
|
||||||
-- A single opcode needs a maximum of 3 positions.
|
-- A single opcode needs a maximum of 3 positions.
|
||||||
if secpos+3 > maxsecpos then wflush() end
|
if secpos+3 > maxsecpos then wflush() end
|
||||||
local pos = wpos()
|
|
||||||
local lpos, apos, spos = #actlist, #actargs, secpos
|
local lpos, apos, spos = #actlist, #actargs, secpos
|
||||||
local ok, err
|
local ok, err
|
||||||
for t in gmatch(template, "[^|]+") do
|
for t in gmatch(template, "[^|]+") do
|
||||||
ok, err = pcall(parse_template, params, t, nparams, pos)
|
ok, err = pcall(parse_template, params, t, nparams)
|
||||||
if ok then return end
|
if ok then return end
|
||||||
secpos = spos
|
secpos = spos
|
||||||
actlist[lpos+1] = nil
|
actlist[lpos+1] = nil
|
||||||
|
Loading…
Reference in New Issue
Block a user