DynASM/ARM64: Add VREG support.

Contributed by Hao Sun and Nick Gasson.
This commit is contained in:
Mike Pall
2021-03-31 18:11:32 +02:00
parent 66563bdab0
commit d1132afb25
2 changed files with 41 additions and 18 deletions

View File

@@ -40,6 +40,7 @@ local action_names = {
"STOP", "SECTION", "ESC", "REL_EXT",
"ALIGN", "REL_LG", "LABEL_LG",
"REL_PC", "LABEL_PC", "IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML",
"VREG",
}
-- Maximum number of section buffer positions for dasm_put().
@@ -246,9 +247,12 @@ local map_cond = {
local parse_reg_type
local function parse_reg(expr)
local function parse_reg(expr, shift)
if not expr then werror("expected register name") end
local tname, ovreg = match(expr, "^([%w_]+):(@?%l%d+)$")
if not tname then
tname, ovreg = match(expr, "^([%w_]+):(R[xwqdshb]%b())$")
end
local tp = map_type[tname or expr]
if tp then
local reg = ovreg or tp.reg
@@ -266,18 +270,28 @@ local function parse_reg(expr)
elseif parse_reg_type ~= rt then
werror("register size mismatch")
end
return r, tp
return shl(r, shift), tp
end
end
local vrt, vreg = match(expr, "^R([xwqdshb])(%b())$")
if vreg then
if not parse_reg_type then
parse_reg_type = vrt
elseif parse_reg_type ~= vrt then
werror("register size mismatch")
end
if shift then waction("VREG", shift, vreg) end
return 0
end
werror("bad register name `"..expr.."'")
end
local function parse_reg_base(expr)
if expr == "sp" then return 0x3e0 end
local base, tp = parse_reg(expr)
local base, tp = parse_reg(expr, 5)
if parse_reg_type ~= "x" then werror("bad register type") end
parse_reg_type = false
return shl(base, 5), tp
return base, tp
end
local parse_ctx = {}
@@ -403,7 +417,7 @@ local function parse_imm_load(imm, scale)
end
werror("out of range immediate `"..imm.."'")
else
waction("IMML", 0, imm)
waction("IMML", scale, imm)
return 0
end
end
@@ -462,6 +476,7 @@ end
local function parse_load(params, nparams, n, op)
if params[n+2] then werror("too many operands") end
local scale = shr(op, 30)
local pn, p2 = params[n], params[n+1]
local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
if not p1 then
@@ -470,14 +485,13 @@ local function parse_load(params, nparams, n, op)
if reg and tailr ~= "" then
local base, tp = parse_reg_base(reg)
if tp then
waction("IMML", 0, format(tp.ctypefmt, tailr))
waction("IMML", scale, format(tp.ctypefmt, tailr))
return op + base
end
end
end
werror("expected address operand")
end
local scale = shr(op, 30)
if p2 then
if wb == "!" then werror("bad use of '!'") end
op = op + parse_reg_base(p1) + parse_imm(p2, 9, 12, 0, true) + 0x400
@@ -494,7 +508,7 @@ local function parse_load(params, nparams, n, op)
op = op + parse_imm_load(imm, scale)
else
local p2b, p3b, p3s = match(p2a, "^,%s*([^,%s]*)%s*,?%s*(%S*)%s*(.*)$")
op = op + shl(parse_reg(p2b), 16) + 0x00200800
op = op + parse_reg(p2b, 16) + 0x00200800
if parse_reg_type ~= "x" and parse_reg_type ~= "w" then
werror("bad index register type")
end
@@ -620,7 +634,7 @@ local function alias_bfx(p)
end
local function alias_bfiz(p)
parse_reg(p[1])
parse_reg(p[1], 0)
if parse_reg_type == "w" then
p[3] = "#-("..p[3]:sub(2)..")%32"
p[4] = "#("..p[4]:sub(2)..")-1"
@@ -631,7 +645,7 @@ local function alias_bfiz(p)
end
local alias_lslimm = op_alias("ubfm_4", function(p)
parse_reg(p[1])
parse_reg(p[1], 0)
local sh = p[3]:sub(2)
if parse_reg_type == "w" then
p[3] = "#-("..sh..")%32"
@@ -891,15 +905,15 @@ local function parse_template(params, template, nparams, pos)
for p in gmatch(sub(template, 9), ".") do
local q = params[n]
if p == "D" then
op = op + parse_reg(q); n = n + 1
op = op + parse_reg(q, 0); n = n + 1
elseif p == "N" then
op = op + shl(parse_reg(q), 5); n = n + 1
op = op + parse_reg(q, 5); n = n + 1
elseif p == "M" then
op = op + shl(parse_reg(q), 16); n = n + 1
op = op + parse_reg(q, 16); n = n + 1
elseif p == "A" then
op = op + shl(parse_reg(q), 10); n = n + 1
op = op + parse_reg(q, 10); n = n + 1
elseif p == "m" then
op = op + shl(parse_reg(params[n-1]), 16)
op = op + parse_reg(params[n-1], 16)
elseif p == "p" then
if q == "sp" then params[n] = "@x31" end