mikepaul-LuaJIT/dynasm/dasm_s390x.lua
Michael Munday 89ca41cca5 Add sp -> r15 mapping and don't special case or_2
It's convenient for sp to be a pseudonym for r15 (the stack pointer).
'or_2' doesn't need to be special cased ('or' did because it is a
keyword).
2016-11-29 13:59:37 -05:00

1413 lines
50 KiB
Lua
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

------------------------------------------------------------------------------
-- DynASM s390x module.
--
-- Copyright (C) 2005-2016 Mike Pall. All rights reserved.
-- See dynasm.lua for full copyright notice.
------------------------------------------------------------------------------
-- Module information:
local _info = {
arch = "s390x",
description = "DynASM s390x module",
version = "1.4.0",
vernum = 10400,
release = "2015-10-18",
author = "Mike Pall",
license = "MIT",
}
-- Exported glue functions for the arch-specific module.
local _M = { _info = _info }
-- Cache library functions.
local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
local assert, setmetatable, rawget = assert, setmetatable, rawget
local _s = string
local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub
local concat, sort, insert = table.concat, table.sort, table.insert
local bit = bit or require("bit")
local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
local ror, tohex = bit.ror, bit.tohex
-- Inherited tables and callbacks.
local g_opt, g_arch
local wline, werror, wfatal, wwarn
-- Action name list.
-- CHECK: Keep this in sync with the C code!
local action_names = {
"STOP", "SECTION", "ESC", "REL_EXT",
"ALIGN", "REL_LG", "LABEL_LG",
"REL_PC", "LABEL_PC", "IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML",
}
-- Maximum number of section buffer positions for dasm_put().
-- CHECK: Keep this in sync with the C code!
local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.
-- Action name -> action number.
local map_action = {}
for n,name in ipairs(action_names) do
map_action[name] = n-1
end
-- Action list buffer.
local actlist = {}
-- Argument list for next dasm_put(). Start with offset 0 into action list.
local actargs = { 0 }
-- Current number of section buffer positions for dasm_put().
local secpos = 1
------------------------------------------------------------------------------
-- Dump action names and numbers.
local function dumpactions(out)
out:write("DynASM encoding engine action codes:\n")
for n,name in ipairs(action_names) do
local num = map_action[name]
out:write(format(" %-10s %02X %d\n", name, num, num))
end
out:write("\n")
end
-- Write action list buffer as a huge static C array.
local function writeactions(out, name)
local nn = #actlist
if nn == 0 then nn = 1; actlist[0] = map_action.STOP end
out:write("static const unsigned int ", name, "[", nn, "] = {\n")
for i = 1,nn-1 do
assert(out:write("0x", tohex(actlist[i]), ",\n"))
end
assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n"))
end
------------------------------------------------------------------------------
-- Add word to action list.
local function wputxw(n)
assert(n >= 0 and n <= 0xffffffffffff and n % 1 == 0, "word out of range") -- s390x inst can be 6 bytes
actlist[#actlist+1] = n
end
-- Add action to list with optional arg. Advance buffer pos, too.
local function waction(action, val, a, num)
local w = assert(map_action[action], "bad action name `"..action.."'")
wputxw(w * 0x10000 + (val or 0))
if a then actargs[#actargs+1] = a end
if a or num then secpos = secpos + (num or 1) end
end
-- Flush action list (intervening C code or buffer pos overflow).
local function wflush(term)
if #actlist == actargs[1] then return end -- Nothing to flush.
if not term then waction("STOP") end -- Terminate action list.
wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true)
actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().
secpos = 1 -- The actionlist offset occupies a buffer position, too.
end
-- Put escaped word. --Need to check this as well, not sure how it will work on s390x
local function wputw(n)
if n <= 0x000fffff then waction("ESC") end
wputxw(n)
end
-- Reserve position for word.
local function wpos()
local pos = #actlist+1
actlist[pos] = ""
return pos
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.
local next_global = 20
local map_global = setmetatable({}, { __index = function(t, name)
if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end
local n = next_global
if n > 2047 then werror("too many global labels") end
next_global = n + 1
t[name] = n
return n
end})
-- Dump global labels.
local function dumpglobals(out, lvl)
local t = {}
for name, n in pairs(map_global) do t[n] = name end
out:write("Global labels:\n")
for i=20,next_global-1 do
out:write(format(" %s\n", t[i]))
end
out:write("\n")
end
-- Write global label enum.
local function writeglobals(out, prefix)
local t = {}
for name, n in pairs(map_global) do t[n] = name end
out:write("enum {\n")
for i=20,next_global-1 do
out:write(" ", prefix, t[i], ",\n")
end
out:write(" ", prefix, "_MAX\n};\n")
end
-- Write global label names.
local function writeglobalnames(out, name)
local t = {}
for name, n in pairs(map_global) do t[n] = name end
out:write("static const char *const ", name, "[] = {\n")
for i=20,next_global-1 do
out:write(" \"", t[i], "\",\n")
end
out:write(" (const char *)0\n};\n")
end
------------------------------------------------------------------------------
-- Extern label name -> extern label number. With auto assignment on 1st use.
local next_extern = 0
local map_extern_ = {}
local map_extern = setmetatable({}, { __index = function(t, name)
-- No restrictions on the name for now.
local n = next_extern
if n > 2047 then werror("too many extern labels") end
next_extern = n + 1
t[name] = n
map_extern_[n] = name
return n
end})
-- Dump extern labels.
local function dumpexterns(out, lvl)
out:write("Extern labels:\n")
for i=0,next_extern-1 do
out:write(format(" %s\n", map_extern_[i]))
end
out:write("\n")
end
-- Write extern label names.
local function writeexternnames(out, name)
out:write("static const char *const ", name, "[] = {\n")
for i=0,next_extern-1 do
out:write(" \"", map_extern_[i], "\",\n")
end
out:write(" (const char *)0\n};\n")
end
------------------------------------------------------------------------------
-- Arch-specific maps.
-- Ext. register name -> int. name.
local map_archdef = { sp = "r15" }
-- Int. register name -> ext. name.
local map_reg_rev = { r15 = "sp" }
local map_type = {} -- Type name -> { ctype, reg }
local ctypenum = 0 -- Type number (for Dt... macros).
-- Reverse defines for registers.
function _M.revdef(s)
return map_reg_rev[s] or s
end
-- not sure of these
local map_shift = { lsl = 0, lsr = 1, asr = 2, }
local map_extend = {
uxtb = 0, uxth = 1, uxtw = 2, uxtx = 3,
sxtb = 4, sxth = 5, sxtw = 6, sxtx = 7,
}
local map_cond = {
o = 1, h = 2, hle = 3, l = 4,
nhe = 5, lh = 6, ne = 7, e = 8,
nlh = 9, he = 10, nl = 11, le = 12,
nh = 13, no = 14, [""] = 15,
}
------------------------------------------------------------------------------
local parse_reg_type
local function parse_gpr(expr)
-- assuming we get r0-r31 for now
local r = match(expr, "^r([1-3]?[0-9])$")
if r then
r = tonumber(r)
if r <= 31 then return r, tp end
end
werror("bad register name `"..expr.."'")
end
local function parse_fpr(expr)
local r = match(expr, "^f([1-3]?[0-9])$")
if r then
r = tonumber(r)
if r <= 31 then return r end
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)
if parse_reg_type ~= "x" then werror("bad register type") end
parse_reg_type = false
return shl(base, 5), tp -- why is it shifted not able to make out
end
local parse_ctx = {}
local loadenv = setfenv and function(s)
local code = loadstring(s, "")
if code then setfenv(code, parse_ctx) end
return code
end or function(s)
return load(s, "", nil, parse_ctx)
end
-- Try to parse simple arithmetic, too, since some basic ops are aliases.
local function parse_number(n)
local x = tonumber(n)
if x then return x end
local code = loadenv("return "..n)
if code then
local ok, y = pcall(code)
if ok then return y end
end
return nil
end
local function parse_imm(imm, bits, shift, scale, signed)
imm = match(imm, "^#(.*)$")
if not imm then werror("expected immediate operand") end
local n = parse_number(imm)
if n then
local m = sar(n, scale)
if shl(m, scale) == n then
if signed then
local s = sar(m, bits-1)
if s == 0 then return shl(m, shift)
elseif s == -1 then return shl(m + shl(1, bits), shift) end
else
if sar(m, bits) == 0 then return shl(m, shift) end
end
end
werror("out of range immediate `"..imm.."'")
else
waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm)
return 0
end
end
local function parse_imm12(imm)
imm = match(imm, "^#(.*)$")
if not imm then werror("expected immediate operand") end
local n = parse_number(imm)
if n then
if shr(n, 12) == 0 then
return shl(n, 10)
elseif band(n, 0xff000fff) == 0 then
return shr(n, 2) + 0x00400000
end
werror("out of range immediate `"..imm.."'")
else
waction("IMM12", 0, imm)
return 0
end
end
local function parse_imm13(imm)
imm = match(imm, "^#(.*)$")
if not imm then werror("expected immediate operand") end
local n = parse_number(imm)
local r64 = parse_reg_type == "x"
if n and n % 1 == 0 and n >= 0 and n <= 0xffffffff then
local inv = false
if band(n, 1) == 1 then n = bit.bnot(n); inv = true end
local t = {}
for i=1,32 do t[i] = band(n, 1); n = shr(n, 1) end
local b = table.concat(t)
b = b..(r64 and (inv and "1" or "0"):rep(32) or b)
local p0, p1, p0a, p1a = b:match("^(0+)(1+)(0*)(1*)")
if p0 then
local w = p1a == "" and (r64 and 64 or 32) or #p1+#p0a
if band(w, w-1) == 0 and b == b:sub(1, w):rep(64/w) then
local s = band(-2*w, 0x3f) - 1
if w == 64 then s = s + 0x1000 end
if inv then
return shl(w-#p1-#p0, 16) + shl(s+w-#p1, 10)
else
return shl(w-#p0, 16) + shl(s+#p1, 10)
end
end
end
werror("out of range immediate `"..imm.."'")
elseif r64 then
waction("IMM13X", 0, format("(unsigned int)(%s)", imm))
actargs[#actargs+1] = format("(unsigned int)((unsigned long long)(%s)>>32)", imm)
return 0
else
waction("IMM13W", 0, imm)
return 0
end
end
local function parse_imm6(imm)
imm = match(imm, "^#(.*)$")
if not imm then werror("expected immediate operand") end
local n = parse_number(imm)
if n then
if n >= 0 and n <= 63 then
return shl(band(n, 0x1f), 19) + (n >= 32 and 0x80000000 or 0)
end
werror("out of range immediate `"..imm.."'")
else
waction("IMM6", 0, imm)
return 0
end
end
local function parse_imm_load(imm, scale)
local n = parse_number(imm)
if n then
local m = sar(n, scale)
if shl(m, scale) == n and m >= 0 and m < 0x1000 then
return shl(m, 10) + 0x01000000 -- Scaled, unsigned 12 bit offset.
elseif n >= -256 and n < 256 then
return shl(band(n, 511), 12) -- Unscaled, signed 9 bit offset.
end
werror("out of range immediate `"..imm.."'")
else
waction("IMML", 0, imm)
return 0
end
end
local function parse_fpimm(imm)
imm = match(imm, "^#(.*)$")
if not imm then werror("expected immediate operand") end
local n = parse_number(imm)
if n then
local m, e = math.frexp(n)
local s, e2 = 0, band(e-2, 7)
if m < 0 then m = -m; s = 0x00100000 end
m = m*32-16
if m % 1 == 0 and m >= 0 and m <= 15 and sar(shl(e2, 29), 29)+2 == e then
return s + shl(e2, 17) + shl(m, 13)
end
werror("out of range immediate `"..imm.."'")
else
werror("NYI fpimm action")
end
end
local function parse_shift(expr)
local s, s2 = match(expr, "^(%S+)%s*(.*)$")
s = map_shift[s]
if not s then werror("expected shift operand") end
return parse_imm(s2, 6, 10, 0, false) + shl(s, 22)
end
local function parse_lslx16(expr)
local n = match(expr, "^lsl%s*#(%d+)$")
n = tonumber(n)
if not n then werror("expected shift operand") end
if band(n, parse_reg_type == "x" and 0xffffffcf or 0xffffffef) ~= 0 then
werror("bad shift amount")
end
return shl(n, 17)
end
local function parse_extend(expr)
local s, s2 = match(expr, "^(%S+)%s*(.*)$")
if s == "lsl" then
s = parse_reg_type == "x" and 3 or 2
else
s = map_extend[s]
end
if not s then werror("expected extend operand") end
return (s2 == "" and 0 or parse_imm(s2, 3, 10, 0, false)) + shl(s, 13)
end
local function parse_cond(expr, inv)
local c = map_cond[expr]
if not c then werror("expected condition operand") end
return shl(bit.bxor(c, inv), 12)
end
local function parse_load(params, nparams, n, op)
if params[n+2] then werror("too many operands") end
local pn, p2 = params[n], params[n+1]
local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
if not p1 then
if not p2 then
local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$")
if reg and tailr ~= "" then
local base, tp = parse_reg_base(reg)
if tp then
waction("IMML", 0, 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
elseif wb == "!" then
local p1a, p2a = match(p1, "^([^,%s]*)%s*,%s*(.*)$")
if not p1a then werror("bad use of '!'") end
op = op + parse_reg_base(p1a) + parse_imm(p2a, 9, 12, 0, true) + 0xc00
else
local p1a, p2a = match(p1, "^([^,%s]*)%s*(.*)$")
op = op + parse_reg_base(p1a)
if p2a ~= "" then
local imm = match(p2a, "^,%s*#(.*)$")
if imm then
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
if parse_reg_type ~= "x" and parse_reg_type ~= "w" then
werror("bad index register type")
end
if p3b == "" then
if parse_reg_type ~= "x" then werror("bad index register type") end
op = op + 0x6000
else
if p3s == "" or p3s == "#0" then
elseif p3s == "#"..scale then
op = op + 0x1000
else
werror("bad scale")
end
if parse_reg_type == "x" then
if p3b == "lsl" and p3s ~= "" then op = op + 0x6000
elseif p3b == "sxtx" then op = op + 0xe000
else
werror("bad extend/shift specifier")
end
else
if p3b == "uxtw" then op = op + 0x4000
elseif p3b == "sxtw" then op = op + 0xc000
else
werror("bad extend/shift specifier")
end
end
end
end
else
if wb == "!" then werror("bad use of '!'") end
op = op + 0x01000000
end
end
return op
end
local function parse_load_pair(params, nparams, n, op)
if params[n+2] then werror("too many operands") end
local pn, p2 = params[n], params[n+1]
local scale = shr(op, 30) == 0 and 2 or 3
local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
if not p1 then
if not p2 then
local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$")
if reg and tailr ~= "" then
local base, tp = parse_reg_base(reg)
if tp then
waction("IMM", 32768+7*32+15+scale*1024, format(tp.ctypefmt, tailr))
return op + base + 0x01000000
end
end
end
werror("expected address operand")
end
if p2 then
if wb == "!" then werror("bad use of '!'") end
op = op + 0x00800000
else
local p1a, p2a = match(p1, "^([^,%s]*)%s*,%s*(.*)$")
if p1a then p1, p2 = p1a, p2a else p2 = "#0" end
op = op + (wb == "!" and 0x01800000 or 0x01000000)
end
return op + parse_reg_base(p1) + parse_imm(p2, 7, 15, scale, true)
end
local function parse_label(label, def)
local prefix = sub(label, 1, 2)
-- =>label (pc label reference)
if prefix == "=>" then
return "PC", 0, sub(label, 3)
end
-- ->name (global label reference)
if prefix == "->" then
return "LG", map_global[sub(label, 3)]
end
if def then
-- [1-9] (local label definition)
if match(label, "^[1-9]$") then
return "LG", 10+tonumber(label)
end
else
-- [<>][1-9] (local label reference)
local dir, lnum = match(label, "^([<>])([1-9])$")
if dir then -- Fwd: 1-9, Bkwd: 11-19.
return "LG", lnum + (dir == ">" and 0 or 10)
end
-- extern label (extern label reference)
local extname = match(label, "^extern%s+(%S+)$")
if extname then
return "EXT", map_extern[extname]
end
end
werror("bad label `"..label.."'")
end
local function branch_type(op)
if band(op, 0x7c000000) == 0x14000000 then return 0 -- B, BL
elseif shr(op, 24) == 0x54 or band(op, 0x7e000000) == 0x34000000 or
band(op, 0x3b000000) == 0x18000000 then
return 0x800 -- B.cond, CBZ, CBNZ, LDR* literal
elseif band(op, 0x7e000000) == 0x36000000 then return 0x1000 -- TBZ, TBNZ
elseif band(op, 0x9f000000) == 0x10000000 then return 0x2000 -- ADR
elseif band(op, 0x9f000000) == band(0x90000000) then return 0x3000 -- ADRP
else
assert(false, "unknown branch type")
end
end
------------------------------------------------------------------------------
local map_op, op_template
local function op_alias(opname, f)
return function(params, nparams)
if not params then return "-> "..opname:sub(1, -3) end
f(params, nparams)
op_template(params, map_op[opname], nparams)
end
end
local function alias_bfx(p)
p[4] = "#("..p[3]:sub(2)..")+("..p[4]:sub(2)..")-1"
end
local function alias_bfiz(p)
parse_reg(p[1])
if parse_reg_type == "w" then
p[3] = "#-("..p[3]:sub(2)..")%32"
p[4] = "#("..p[4]:sub(2)..")-1"
else
p[3] = "#-("..p[3]:sub(2)..")%64"
p[4] = "#("..p[4]:sub(2)..")-1"
end
end
local alias_lslimm = op_alias("ubfm_4", function(p)
parse_reg(p[1])
local sh = p[3]:sub(2)
if parse_reg_type == "w" then
p[3] = "#-("..sh..")%32"
p[4] = "#31-("..sh..")"
else
p[3] = "#-("..sh..")%64"
p[4] = "#63-("..sh..")"
end
end)
-- Template strings for s390x instructions.
map_op = {
a_4 = "000000005a000000j",
ar_2 = "0000000000001a00g",
ay_5 = "0000e3000000005al",
ag_5 = "0000e30000000008l",
agr_2 = "00000000b9080000h",
agf_5 = "0000e30000000018l",
agfr_2 = "00000000b9180000h",
axbr_2 = "00000000b34a0000h",
adbr_2 = "00000000b31a0000h",
aebr_2 = "00000000b30a0000h",
ah_4 = "000000004a000000j",
ahy_5 = "0000e3000000007al",
afi_3 = "0000c20900000000n",
agfi_3 = "0000c20800000000n",
aih_3 = "0000cc0800000000n",
al_4 = "000000005e000000j",
alr_2 = "0000000000001e00g",
aly_5 = "0000e3000000005el",
alg_5 = "0000e3000000000al",
algr_2 = "00000000b90a0000h",
algf_5 = "0000e3000000001al",
algfr_2 = "00000000b91a0000h",
alfi_3 = "0000c20b00000000n",
algfi_3 = "0000c20a00000000n",
alc_5 = "0000e30000000098l",
alcr_2 = "00000000b9980000h",
alcg_5 = "0000e30000000088l",
alcgr_2 = "00000000b9880000h",
alsih_3 = "0000cc0a00000000n",
alsihn_3 = "0000cc0b00000000n",
axr_2 = "0000000000003600g",
ad_4 = "000000006a000000j",
adr_2 = "0000000000002a00g",
ae_4 = "000000007a000000j",
aer_2 = "0000000000003a00g",
aw_4 = "000000006e000000j",
awr_2 = "0000000000002e00g",
au_4 = "000000007e000000j",
aur_2 = "0000000000003e00g",
n_4 = "0000000054000000j",
nr_2 = "0000000000001400g",
ny_5 = "0000e30000000054l",
ng_5 = "0000e30000000080l",
ngr_2 = "00000000b9800000h",
nihf_3 = "0000c00a00000000n",
nilf_3 = "0000c00b00000000n",
bal_4 = "0000000045000000j",
balr_2 = "000000000000500g",
bas_4 = "000000004d000000j",
basr_2 = "0000000000000d00g",
bassm_2 = "0000000000000c00g",
bsa_2 = "00000000b25a0000h",
bsm_2 = "0000000000000b00g",
bakr_2 = "00000000b2400000h",
bsg_2 = "00000000b2580000h",
bc_4 = "0000000047000000k",
bcr_2 = "000000000000700g",
bct_4 = "0000000046000000j",
bctr_2 = "000000000000600g",
bctg_5 = "0000e30000000046l",
bctgr_2 = "00000000b9460000h",
bxh_4 = "0000000086000000q",
bxhg_5 = "0000eb0000000044s",
bxle_4 = "0000000087000000q",
bxleg_5 = "0000eb0000000045s",
brasl_3 = "0000c00500000000o",
brcl_3 = "0000c00400000000p",
brcth_3 = "0000cc0600000000o",
cksm_2 = "00000000b2410000h",
km_2 = "00000000b92e0000h",
kmf_2 = "00000000b92a0000h",
kmc_2 = "00000000b92f0000h",
kmo_2 = "00000000b92b0000h",
c_4 = "0000000059000000j",
cr_2 = "0000000000001900g",
cy_5 = "0000e30000000059l",
cg_5 = "0000e30000000020l",
cgr_2 = "00000000b9200000h",
cgf_5 = "0000e30000000030l",
cgfr_2 = "00000000b9300000h",
cxbr_2 = "00000000b3490000h",
cxtr_2 = "00000000b3ec0000h",
cxr_2 = "00000000b3690000h",
cdbr_2 = "00000000b3190000h",
cdtr_2 = "00000000b3e40000h",
cd_4 = "0000000069000000j",
cdr_2 = "0000000000002900g",
cebr_2 = "00000000b3090000h",
ce_4 = "0000000079000000j",
cer_2 = "0000000000003900g",
kxbr_2 = "00000000b3480000h",
kxtr_2 = "00000000b3e80000h",
kdbr_2 = "00000000b3180000h",
kdtr_2 = "00000000b3e00000h",
kebr_2 = "00000000b3080000h",
cs_4 = "00000000ba000000q",
csy_5 = "0000eb0000000014s",
csg_5 = "0000eb0000000030s",
csp_2 = "00000000b2500000h",
cspg_2 = "00000000b98a0000h",
cextr_2 = "00000000b3fc0000h",
cedtr_2 = "00000000b3f40000h",
cds_4 = "00000000bb000000q",
cdsy_5 = "0000eb0000000031s",
cdsg_5 = "0000eb000000003es",
ch_4 = "0000000049000000j",
chy_5 = "0000e30000000079l",
cgh_5 = "0000e30000000034l",
chrl_3 = "0000c60500000000o",
cghrl_3 = "0000c60400000000o",
chf_5 = "0000e300000000cdl",
chhr_2 = "00000000b9cd0000h",
chlr_2 = "00000000b9dd0000h",
cfi_3 = "0000c20d00000000n",
cgfi_3 = "0000c20c00000000n",
cih_3 = "0000cc0d00000000n",
cl_4 = "0000000055000000j",
clr_2 = "0000000000001500g",
cly_5 = "0000e30000000055l",
clg_5 = "0000e30000000021l",
clgr_2 = "00000000b9210000h",
clgf_5 = "0000e30000000031l",
clgfr_2 = "00000000b9310000h",
clmh_5 = "0000eb0000000020t",
clm_4 = "00000000bd000000r",
clmy_5 = "0000eb0000000021t",
clhf_5 = "0000e300000000cfl",
clhhr_2 = "00000000b9cf0000h",
clhlr_2 = "00000000b9df0000h",
clfi_3 = "0000c20f00000000n",
clgfi_3 = "0000c20e00000000n",
clih_3 = "0000cc0f00000000n",
clcl_2 = "0000000000000f00g",
clcle_4 = "00000000a9000000q",
clclu_5 = "0000eb000000008fs",
clrl_3 = "0000c60f00000000o",
clhrl_3 = "0000c60700000000o",
clgrl_3 = "0000c60a00000000o",
clghrl_3 = "0000c60600000000o",
clgfrl_3 = "0000c60e00000000o",
clst_2 = "00000000b25d0000h",
crl_3 = "0000c60d00000000o",
cgrl_3 = "0000c60800000000o",
cgfrl_3 = "0000c60c00000000o",
cuse_2 = "00000000b2570000h",
cmpsc_2 = "00000000b2630000h",
kimd_2 = "00000000b93e0000h",
klmd_2 = "00000000b93f0000h",
kmac_2 = "00000000b91e0000h",
thdr_2 = "00000000b3590000h",
thder_2 = "00000000b3580000h",
cxfbr_2 = "00000000b3960000h",
cxftr_2 = "00000000b9590000h",
cxfr_2 = "00000000b3b60000h",
cdfbr_2 = "00000000b3950000h",
cdftr_2 = "00000000b9510000h",
cdfr_2 = "00000000b3b50000h",
cefbr_2 = "00000000b3940000h",
cefr_2 = "00000000b3b40000h",
cxgbr_2 = "00000000b3a60000h",
cxgtr_2 = "00000000b3f90000h",
cxgr_2 = "00000000b3c60000h",
cdgbr_2 = "00000000b3a50000h",
cdgtr_2 = "00000000b3f10000h",
cdgr_2 = "00000000b3c50000h",
cegbr_2 = "00000000b3a40000h",
cegr_2 = "00000000b3c40000h",
cxstr_2 = "00000000b3fb0000h",
cdstr_2 = "00000000b3f30000h",
cxutr_2 = "00000000b3fa0000h",
cdutr_2 = "00000000b3f20000h",
cvb_4 = "000000004f000000j",
cvby_5 = "0000e30000000006l",
cvbg_5 = "0000e3000000000el",
cvd_4 = "000000004e000000j",
cvdy_5 = "0000e30000000026l",
cvdg_5 = "0000e3000000002el",
cuxtr_2 = "00000000b3ea0000h",
cudtr_2 = "00000000b3e20000h",
cu42_2 = "00000000b9b30000h",
cu41_2 = "00000000b9b20000h",
cpya_2 = "00000000b24d0000h",
d_4 = "000000005d000000j",
dr_2 = "0000000000001d00g",
dxbr_2 = "00000000b34d0000h",
dxr_2 = "00000000b22d0000h",
ddbr_2 = "00000000b31d0000h",
dd_4 = "000000006d000000j",
ddr_2 = "0000000000002d00g",
debr_2 = "00000000b30d0000h",
de_4 = "000000007d000000j",
der_2 = "0000000000003d00g",
dl_5 = "0000e30000000097l",
dlr_2 = "00000000b9970000h",
dlg_5 = "0000e30000000087l",
dlgr_2 = "00000000b9870000h",
dsg_5 = "0000e3000000000dl",
dsgr_2 = "00000000b90d0000h",
dsgf_5 = "0000e3000000001dl",
dsgfr_2 = "00000000b91d0000h",
x_4 = "0000000057000000j",
xr_2 = "0000000000001700g",
xy_5 = "0000e30000000057l",
xg_5 = "0000e30000000082l",
xgr_2 = "00000000b9820000h",
xihf_3 = "0000c00600000000n",
xilf_3 = "0000c00700000000n",
ex_4 = "0000000044000000j",
exrl_3 = "0000c60000000000o",
ear_2 = "00000000b24f0000h",
esea_2 = "00000000b99d0000h",
eextr_2 = "00000000b3ed0000h",
eedtr_2 = "00000000b3e50000h",
ecag_5 = "0000eb000000004cs",
efpc_2 = "00000000b38c0000h",
epar_2 = "00000000b2260000h",
epair_2 = "00000000b99a0000h",
epsw_2 = "00000000b98d0000h",
esar_2 = "00000000b2270000h",
esair_2 = "00000000b99b0000h",
esxtr_2 = "00000000b3ef0000h",
esdtr_2 = "00000000b3e70000h",
ereg_2 = "00000000b2490000h",
eregg_2 = "00000000b90e0000h",
esta_2 = "00000000b24a0000h",
flogr_2 = "00000000b9830000h",
hdr_2 = "0000000000002400g",
her_2 = "0000000000003400g",
iac_2 = "00000000b2240000h",
ic_4 = "0000000043000000j",
icy_5 = "0000e30000000073l",
icmh_5 = "0000eb0000000080t",
icm_4 = "00000000bf000000r",
icmy_5 = "0000eb0000000081t",
iihf_3 = "0000c00800000000n",
iilf_3 = "0000c00900000000n",
ipm_2 = "00000000b2220000h",
iske_2 = "00000000b2290000h",
ivsk_2 = "00000000b2230000h",
l_4 = "0000000058000000j",
lr_2 = "0000000000001800g",
ly_5 = "0000e30000000058l",
lg_5 = "0000e30000000004l",
lgr_2 = "00000000b9040000h",
lgf_5 = "0000e30000000014l",
lgfr_2 = "00000000b9140000h",
lxr_2 = "00000000b3650000h",
ld_4 = "0000000068000000j",
ldr_2 = "0000000000002800g",
ldy_5 = "0000ed0000000065l",
le_4 = "0000000078000000j",
ler_2 = "0000000000003800g",
ley_5 = "0000ed0000000064l",
lam_4 = "000000009a000000q",
lamy_5 = "0000eb000000009as",
la_4 = "0000000041000000j",
lay_5 = "0000e30000000071l",
lae_4 = "0000000051000000j",
laey_5 = "0000e30000000075l",
larl_3 = "0000c00000000000o",
laa_5 = "0000eb00000000f8s",
laag_5 = "0000eb00000000e8s",
laal_5 = "0000eb00000000fas",
laalg_5 = "0000eb00000000eas",
lan_5 = "0000eb00000000f4s",
lang_5 = "0000eb00000000e4s",
lax_5 = "0000eb00000000f7s",
laxg_5 = "0000eb00000000e7s",
lao_5 = "0000eb00000000f6s",
laog_5 = "0000eb00000000e6s",
lt_5 = "0000e30000000012l",
ltr_2 = "0000000000001200g",
ltg_5 = "0000e30000000002l",
ltgr_2 = "00000000b9020000h",
ltgf_5 = "0000e30000000032l",
ltgfr_2 = "00000000b9120000h",
ltxbr_2 = "00000000b3420000h",
ltxtr_2 = "00000000b3de0000h",
ltxr_2 = "00000000b3620000h",
ltdbr_2 = "00000000b3120000h",
ltdtr_2 = "00000000b3d60000h",
ltdr_2 = "0000000000002200g",
ltebr_2 = "00000000b3020000h",
lter_2 = "0000000000003200g",
lb_5 = "0000e30000000076l",
lbr_2 = "00000000b9260000h",
lgb_5 = "0000e30000000077l",
lgbr_2 = "00000000b9060000h",
lbh_5 = "0000e300000000c0l",
lcr_2 = "0000000000001300g",
lcgr_2 = "00000000b9030000h",
lcgfr_2 = "00000000b9130000h",
lcxbr_2 = "00000000b3430000h",
lcxr_2 = "00000000b3630000h",
lcdbr_2 = "00000000b3130000h",
lcdr_2 = "0000000000002300g",
lcdfr_2 = "00000000b3730000h",
lcebr_2 = "00000000b3030000h",
lcer_2 = "0000000000003300g",
lctl_4 = "00000000b7000000q",
lctlg_5 = "0000eb000000002fs",
fixr_2 = "00000000b3670000h",
fidr_2 = "00000000b37f0000h",
fier_2 = "00000000b3770000h",
ldgr_2 = "00000000b3c10000h",
lgdr_2 = "00000000b3cd0000h",
lh_4 = "0000000048000000j",
lhr_2 = "00000000b9270000h",
lhy_5 = "0000e30000000078l",
lgh_5 = "0000e30000000015l",
lghr_2 = "00000000b9070000h",
lhh_5 = "0000e300000000c4l",
lhrl_3 = "0000c40500000000o",
lghrl_3 = "0000c40400000000o",
lfh_5 = "0000e300000000cal",
lgfi_3 = "0000c00100000000n",
lxdbr_2 = "00000000b3050000h",
lxdr_2 = "00000000b3250000h",
lxebr_2 = "00000000b3060000h",
lxer_2 = "00000000b3260000h",
ldebr_2 = "00000000b3040000h",
lder_2 = "00000000b3240000h",
llgf_5 = "0000e30000000016l",
llgfr_2 = "00000000b9160000h",
llc_5 = "0000e30000000094l",
llcr_2 = "00000000b9940000h",
llgc_5 = "0000e30000000090l",
llgcr_2 = "00000000b9840000h",
llch_5 = "0000e300000000c2l",
llh_5 = "0000e30000000095l",
llhr_2 = "00000000b9950000h",
llgh_5 = "0000e30000000091l",
llghr_2 = "00000000b9850000h",
llhh_5 = "0000e300000000c6l",
llhrl_3 = "0000c40200000000o",
llghrl_3 = "0000c40600000000o",
llihf_3 = "0000c00e00000000n",
llilf_3 = "0000c00f00000000n",
llgfrl_3 = "0000c40e00000000o",
llgt_5 = "0000e30000000017l",
llgtr_2 = "00000000b9170000h",
lm_4 = "0000000098000000q",
lmy_5 = "0000eb0000000098s",
lmg_5 = "0000eb0000000004s",
lmh_5 = "0000eb0000000096s",
lnr_2 = "0000000000001100g",
lngr_2 = "00000000b9010000h",
lngfr_2 = "00000000b9110000h",
lnxbr_2 = "00000000b3410000h",
lnxr_2 = "00000000b3610000h",
lndbr_2 = "00000000b3110000h",
lndr_2 = "0000000000002100g",
lndfr_2 = "00000000b3710000h",
lnebr_2 = "00000000b3010000h",
lner_2 = "0000000000003100g",
loc_5 = "0000eb00000000f2t",
locg_5 = "0000eb00000000e2t",
lpq_5 = "0000e3000000008fl",
lpr_2 = "0000000000001000g",
lpgr_2 = "00000000b9000000h",
lpgfr_2 = "00000000b9100000h",
lpxbr_2 = "00000000b3400000h",
lpxr_2 = "00000000b3600000h",
lpdbr_2 = "00000000b3100000h",
lpdr_2 = "0000000000002000g",
lpdfr_2 = "00000000b3700000h",
lpebr_2 = "00000000b3000000h",
lper_2 = "0000000000003000g",
lra_4 = "00000000b1000000j",
lray_5 = "0000e30000000013l",
lrag_5 = "0000e30000000003l",
lrl_3 = "0000c40d00000000o",
lgrl_3 = "0000c40800000000o",
lgfrl_3 = "0000c40c00000000o",
lrvh_5 = "0000e3000000001fl",
lrv_5 = "0000e3000000001el",
lrvr_2 = "00000000b91f0000h",
lrvg_5 = "0000e3000000000fl",
lrvgr_2 = "00000000b90f0000h",
ldxbr_2 = "00000000b3450000h",
ldxr_2 = "0000000000002500g",
lrdr_2 = "0000000000002500g",
lexbr_2 = "00000000b3460000h",
lexr_2 = "00000000b3660000h",
ledbr_2 = "00000000b3440000h",
ledr_2 = "0000000000003500g",
lrer_2 = "0000000000003500g",
lura_2 = "00000000b24b0000h",
lurag_2 = "00000000b9050000h",
lzxr_2 = "00000000b3760000h",
lzdr_2 = "00000000b3750000h",
lzer_2 = "00000000b3740000h",
msta_2 = "00000000b2470000h",
mvcl_2 = "0000000000000e00g",
mvcle_4 = "00000000a8000000q",
mvclu_5 = "0000eb000000008es",
mvpg_2 = "00000000b2540000h",
mvst_2 = "00000000b2550000h",
m_4 = "000000005c000000j",
mfy_5 = "0000e3000000005cl",
mr_2 = "0000000000001c00g",
mxbr_2 = "00000000b34c0000h",
mxr_2 = "0000000000002600g",
mdbr_2 = "00000000b31c0000h",
md_4 = "000000006c000000j",
mdr_2 = "0000000000002c00g",
mxdbr_2 = "00000000b3070000h",
mxd_4 = "0000000067000000j",
mxdr_2 = "0000000000002700g",
meebr_2 = "00000000b3170000h",
meer_2 = "00000000b3370000h",
mdebr_2 = "00000000b30c0000h",
mde_4 = "000000007c000000j",
mder_2 = "0000000000003c00g",
me_4 = "000000007c000000j",
mer_2 = "0000000000003c00g",
mh_4 = "000000004c000000j",
mhy_5 = "0000e3000000007cl",
mlg_5 = "0000e30000000086l",
mlgr_2 = "00000000b9860000h",
ml_5 = "0000e30000000096l",
mlr_2 = "00000000b9960000h",
ms_4 = "0000000071000000j",
msr_2 = "00000000b2520000h",
msy_5 = "0000e30000000051l",
msg_5 = "0000e3000000000cl",
msgr_2 = "00000000b90c0000h",
msgf_5 = "0000e3000000001cl",
msgfr_2 = "00000000b91c0000h",
msfi_3 = "0000c20100000000n",
msgfi_3 = "0000c20000000000n",
o_4 = "0000000056000000j",
or_2 = "0000000000001600g",
oy_5 = "0000e30000000056l",
og_5 = "0000e30000000081l",
ogr_2 = "00000000b9810000h",
oihf_3 = "0000c00c00000000n",
oilf_3 = "0000c00d00000000n",
pgin_2 = "00000000b22e0000h",
pgout_2 = "00000000b22f0000h",
pcc_2 = "00000000b92c0000h",
pckmo_2 = "00000000b9280000h",
pfmf_2 = "00000000b9af0000h",
ptf_2 = "00000000b9a20000h",
popcnt_2 = "00000000b9e10000h",
pfd_5 = "0000e30000000036m",
pfdrl_3 = "0000c60200000000p",
pt_2 = "00000000b2280000h",
pti_2 = "00000000b99e0000h",
palb_2 = "00000000b2480000h",
rrbe_2 = "00000000b22a0000h",
rrbm_2 = "00000000b9ae0000h",
rll_5 = "0000eb000000001ds",
rllg_5 = "0000eb000000001cs",
srst_2 = "00000000b25e0000h",
srstu_2 = "00000000b9be0000h",
sar_2 = "00000000b24e0000h",
sfpc_2 = "00000000b3840000h",
sfasr_2 = "00000000b3850000h",
spm_2 = "000000000000400g",
ssar_2 = "00000000b2250000h",
ssair_2 = "00000000b99f0000h",
slda_4 = "000000008f000000q",
sldl_4 = "000000008d000000q",
sla_4 = "000000008b000000q",
slak_5 = "0000eb00000000dds",
slag_5 = "0000eb000000000bs",
sll_4 = "0000000089000000q",
sllk_5 = "0000eb00000000dfs",
sllg_5 = "0000eb000000000ds",
srda_4 = "000000008e000000q",
srdl_4 = "000000008c000000q",
sra_4 = "000000008a000000q",
srak_5 = "0000eb00000000dcs",
srag_5 = "0000eb000000000as",
srl_4 = "0000000088000000q",
srlk_5 = "0000eb00000000des",
srlg_5 = "0000eb000000000cs",
sqxbr_2 = "00000000b3160000h",
sqxr_2 = "00000000b3360000h",
sqdbr_2 = "00000000b3150000h",
sqdr_2 = "00000000b2440000h",
sqebr_2 = "00000000b3140000h",
sqer_2 = "00000000b2450000h",
st_4 = "0000000050000000j",
sty_5 = "0000e30000000050l",
stg_5 = "0000e30000000024l",
std_4 = "0000000060000000j",
stdy_5 = "0000ed0000000067l",
ste_4 = "0000000070000000j",
stey_5 = "0000ed0000000066l",
stam_4 = "000000009b000000q",
stamy_5 = "0000eb000000009bs",
stc_4 = "0000000042000000j",
stcy_5 = "0000e30000000072l",
stch_5 = "0000e300000000c3l",
stcmh_5 = "0000eb000000002ct",
stcm_4 = "00000000be000000r",
stcmy_5 = "0000eb000000002dt",
stctl_4 = "00000000b6000000q",
stctg_5 = "0000eb0000000025s",
sth_4 = "0000000040000000j",
sthy_5 = "0000e30000000070l",
sthh_5 = "0000e300000000c7l",
sthrl_3 = "0000c40700000000o",
stfh_5 = "0000e300000000cbl",
stm_4 = "0000000090000000q",
stmy_5 = "0000eb0000000090s",
stmg_5 = "0000eb0000000024s",
stmh_5 = "0000eb0000000026s",
stoc_5 = "0000eb00000000f3t",
stocg_5 = "0000eb00000000e3t",
stpq_5 = "0000e3000000008el",
strl_3 = "0000c40f00000000o",
stgrl_3 = "0000c40b00000000o",
strvh_5 = "0000e3000000003fl",
strv_5 = "0000e3000000003el",
strvg_5 = "0000e3000000002fl",
stura_2 = "00000000b2460000h",
sturg_2 = "00000000b9250000h",
s_4 = "000000005b000000j",
sr_2 = "0000000000001b00g",
sy_5 = "0000e3000000005bl",
sg_5 = "0000e30000000009l",
sgr_2 = "00000000b9090000h",
sgf_5 = "0000e30000000019l",
sgfr_2 = "00000000b9190000h",
sxbr_2 = "00000000b34b0000h",
sdbr_2 = "00000000b31b0000h",
sebr_2 = "00000000b30b0000h",
sh_4 = "000000004b000000j",
shy_5 = "0000e3000000007bl",
sl_4 = "000000005f000000j",
slr_2 = "0000000000001f00g",
sly_5 = "0000e3000000005fl",
slg_5 = "0000e3000000000bl",
slgr_2 = "00000000b90b0000h",
slgf_5 = "0000e3000000001bl",
slgfr_2 = "00000000b91b0000h",
slfi_3 = "0000c20500000000n",
slgfi_3 = "0000c20400000000n",
slb_5 = "0000e30000000099l",
slbr_2 = "00000000b9990000h",
slbg_5 = "0000e30000000089l",
slbgr_2 = "00000000b9890000h",
sxr_2 = "0000000000003700g",
sd_4 = "000000006b000000j",
sdr_2 = "0000000000002b00g",
se_4 = "000000007b000000j",
ser_2 = "0000000000003b00g",
su_4 = "000000007f000000j",
sur_2 = "0000000000003f00g",
sw_4 = "000000006f000000j",
swr_2 = "0000000000002f00g",
tar_2 = "00000000b24c0000h",
tb_2 = "00000000b22c0000h",
trace_4 = "0000000099000000q",
tracg_5 = "0000eb000000000fs",
tre_2 = "00000000b2a50000h",
}
for cond,c in pairs(map_cond) do
-- Extended mnemonics for branches.
-- TODO: replace 'B' with correct encoding.
-- brc
map_op["j"..cond.."_1"] = "00000000"..tohex(0xa7040000+shl(c, 20)).."B"
-- brcl
map_op["jg"..cond.."_1"] = tohex(0xc004+shl(c, 4)).."00000000".."B"
-- bc
map_op["b"..cond.."_1"] = "00000000"..tohex(0x47000000+shl(c, 20)).."B"
-- bcr
map_op["b"..cond.."r_1"] = "00000000"..tohex(0x0700+shl(c, 4)).."B"
end
------------------------------------------------------------------------------
-- Handle opcodes defined with template strings.
local function parse_template(params, template, nparams, pos)
local op = tonumber(sub(template, 1, 16), 16) --
-- 00000000005a0000 converts to 90
local n,rs = 1,26
parse_reg_type = false
-- Process each character.
for p in gmatch(sub(template, 17), ".") do
local pr1,pr2,pr3
if p == "g" then
pr1,pr2=param[n],param[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=param[n],param[n+1]
op = op + shl(parse_reg(pr1),4) + parse_reg(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
wputpos(pos, op)
end
function op_template(params, template, nparams)
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().
-- A single opcode needs a maximum of 3 positions.
if secpos+3 > maxsecpos then wflush() end
local pos = wpos()
local lpos, apos, spos = #actlist, #actargs, secpos
local ok, err
for t in gmatch(template, "[^|]+") do
ok, err = pcall(parse_template, params, t, nparams, pos)
if ok then return end
secpos = spos
actlist[lpos+1] = nil
actlist[lpos+2] = nil
actlist[lpos+3] = nil
actargs[apos+1] = nil
actargs[apos+2] = nil
actargs[apos+3] = nil
end
error(err, 0)
end
map_op[".template__"] = op_template
------------------------------------------------------------------------------
-- Pseudo-opcode to mark the position where the action list is to be emitted.
map_op[".actionlist_1"] = function(params)
if not params then return "cvar" end
local name = params[1] -- No syntax check. You get to keep the pieces.
wline(function(out) writeactions(out, name) end)
end
-- Pseudo-opcode to mark the position where the global enum is to be emitted.
map_op[".globals_1"] = function(params)
if not params then return "prefix" end
local prefix = params[1] -- No syntax check. You get to keep the pieces.
wline(function(out) writeglobals(out, prefix) end)
end
-- Pseudo-opcode to mark the position where the global names are to be emitted.
map_op[".globalnames_1"] = function(params)
if not params then return "cvar" end
local name = params[1] -- No syntax check. You get to keep the pieces.
wline(function(out) writeglobalnames(out, name) end)
end
-- Pseudo-opcode to mark the position where the extern names are to be emitted.
map_op[".externnames_1"] = function(params)
if not params then return "cvar" end
local name = params[1] -- No syntax check. You get to keep the pieces.
wline(function(out) writeexternnames(out, name) end)
end
------------------------------------------------------------------------------
-- Label pseudo-opcode (converted from trailing colon form).
map_op[".label_1"] = function(params)
if not params then return "[1-9] | ->global | =>pcexpr" end
if secpos+1 > maxsecpos then wflush() end
local mode, n, s = parse_label(params[1], true)
if mode == "EXT" then werror("bad label definition") end
waction("LABEL_"..mode, n, s, 1)
end
------------------------------------------------------------------------------
-- Pseudo-opcodes for data storage.
map_op[".long_*"] = function(params)
if not params then return "imm..." end
for _,p in ipairs(params) do
local n = tonumber(p)
if not n then werror("bad immediate `"..p.."'") end
if n < 0 then n = n + 2^32 end
wputw(n)
if secpos+2 > maxsecpos then wflush() end
end
end
-- Alignment pseudo-opcode.
map_op[".align_1"] = function(params)
if not params then return "numpow2" end
if secpos+1 > maxsecpos then wflush() end
local align = tonumber(params[1])
if align then
local x = align
-- Must be a power of 2 in the range (2 ... 256).
for i=1,8 do
x = x / 2
if x == 1 then
waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1.
return
end
end
end
werror("bad alignment")
end
------------------------------------------------------------------------------
-- Pseudo-opcode for (primitive) type definitions (map to C types).
map_op[".type_3"] = function(params, nparams)
if not params then
return nparams == 2 and "name, ctype" or "name, ctype, reg"
end
local name, ctype, reg = params[1], params[2], params[3]
if not match(name, "^[%a_][%w_]*$") then
werror("bad type name `"..name.."'")
end
local tp = map_type[name]
if tp then
werror("duplicate type `"..name.."'")
end
-- Add #type to defines. A bit unclean to put it in map_archdef.
map_archdef["#"..name] = "sizeof("..ctype..")"
-- Add new type and emit shortcut define.
local num = ctypenum + 1
map_type[name] = {
ctype = ctype,
ctypefmt = format("Dt%X(%%s)", num),
reg = reg,
}
wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype))
ctypenum = num
end
map_op[".type_2"] = map_op[".type_3"]
-- Dump type definitions.
local function dumptypes(out, lvl)
local t = {}
for name in pairs(map_type) do t[#t+1] = name end
sort(t)
out:write("Type definitions:\n")
for _,name in ipairs(t) do
local tp = map_type[name]
local reg = tp.reg or ""
out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg))
end
out:write("\n")
end
------------------------------------------------------------------------------
-- Set the current section.
function _M.section(num)
waction("SECTION", num)
wflush(true) -- SECTION is a terminal action.
end
------------------------------------------------------------------------------
-- Dump architecture description.
function _M.dumparch(out)
out:write(format("DynASM %s version %s, released %s\n\n",
_info.arch, _info.version, _info.release))
dumpactions(out)
end
-- Dump all user defined elements.
function _M.dumpdef(out, lvl)
dumptypes(out, lvl)
dumpglobals(out, lvl)
dumpexterns(out, lvl)
end
------------------------------------------------------------------------------
-- Pass callbacks from/to the DynASM core.
function _M.passcb(wl, we, wf, ww)
wline, werror, wfatal, wwarn = wl, we, wf, ww
return wflush
end
-- Setup the arch-specific module.
function _M.setup(arch, opt)
g_arch, g_opt = arch, opt
end
-- Merge the core maps and the arch-specific maps.
function _M.mergemaps(map_coreop, map_def)
setmetatable(map_op, { __index = map_coreop })
setmetatable(map_def, { __index = map_archdef })
return map_op, map_def
end
return _M
------------------------------------------------------------------------------