diff --git a/dynasm/dasm_ppc.lua b/dynasm/dasm_ppc.lua index 784223df..278f0952 100644 --- a/dynasm/dasm_ppc.lua +++ b/dynasm/dasm_ppc.lua @@ -230,8 +230,18 @@ local map_cond = { ------------------------------------------------------------------------------ +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 + -- Template strings for PPC instructions. -local map_op = { +map_op = { tdi_3 = "08000000ARI", twi_3 = "0c000000ARI", mulli_3 = "1c000000RRI", @@ -299,6 +309,33 @@ local map_op = { std_2 = "f8000000RD", stdu_2 = "f8000001RD", + subi_3 = op_alias("addi_3", function(p) p[3] = "-("..p[3]..")" end), + subis_3 = op_alias("addis_3", function(p) p[3] = "-("..p[3]..")" end), + subic_3 = op_alias("addic_3", function(p) p[3] = "-("..p[3]..")" end), + ["subic._3"] = op_alias("addic._3", function(p) p[3] = "-("..p[3]..")" end), + + rotlwi_3 = op_alias("rlwinm_5", function(p) + p[4] = "0"; p[5] = "31" + end), + rotrwi_3 = op_alias("rlwinm_5", function(p) + p[3] = "32-("..p[3]..")"; p[4] = "0"; p[5] = "31" + end), + rotlw_3 = op_alias("rlwnm_5", function(p) + p[4] = "0"; p[5] = "31" + end), + slwi_3 = op_alias("rlwinm_5", function(p) + p[5] = "31-("..p[3]..")"; p[4] = "0" + end), + srwi_3 = op_alias("rlwinm_5", function(p) + p[4] = p[3]; p[3] = "32-("..p[3]..")"; p[5] = "31" + end), + clrlwi_3 = op_alias("rlwinm_5", function(p) + p[4] = p[3]; p[3] = "0"; p[5] = "31" + end), + clrrwi_3 = op_alias("rlwinm_5", function(p) + p[5] = "31-("..p[3]..")"; p[3] = "0"; p[4] = "0" + end), + -- Primary opcode 4: mulhhwu_3 = "10000010RRR.", machhwu_3 = "10000018RRR.", @@ -790,6 +827,28 @@ local map_op = { rldcl_4 = "78000010RR~RM.", rldcr_4 = "78000012RR~RM.", + rotldi_3 = op_alias("rldicl_4", function(p) + p[4] = "0" + end), + rotrdi_3 = op_alias("rldicl_4", function(p) + p[3] = "64-("..p[3]..")"; p[4] = "0" + end), + rotld_3 = op_alias("rldcl_4", function(p) + p[4] = "0" + end), + sldi_3 = op_alias("rldicr_4", function(p) + p[4] = "63-("..p[3]..")" + end), + srdi_3 = op_alias("rldicl_4", function(p) + p[4] = p[3]; p[3] = "64-("..p[3]..")" + end), + clrldi_3 = op_alias("rldicl_4", function(p) + p[4] = p[3]; p[3] = "0" + end), + clrrdi_3 = op_alias("rldicr_4", function(p) + p[4] = "63-("..p[3]..")"; p[3] = "0" + end), + -- Primary opcode 56: lq_2 = "e0000000R:D", -- NYI: displacement must be divisible by 8. @@ -1358,7 +1417,7 @@ local map_op = { do local t = {} for k,v in pairs(map_op) do - if sub(v, -1) == "." then + if type(v) == "string" and sub(v, -1) == "." then local v2 = sub(v, 1, 7)..char(byte(v, 8)+1)..sub(v, 9, -2) t[sub(k, 1, -3).."."..sub(k, -2)] = v2 end @@ -1454,8 +1513,30 @@ local function parse_cond(expr) werror("bad condition bit name `"..expr.."'") 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) - local n = tonumber(imm) + local n = parse_number(imm) if n then local m = sar(n, scale) if shl(m, scale) == n then @@ -1479,7 +1560,7 @@ local function parse_imm(imm, bits, shift, scale, signed) end local function parse_shiftmask(imm, isshift) - local n = tonumber(imm) + local n = parse_number(imm) if n then if shr(n, 6) == 0 then local lsb = band(n, 31) @@ -1567,7 +1648,7 @@ end ------------------------------------------------------------------------------ -- Handle opcodes defined with template strings. -map_op[".template__"] = function(params, template, nparams) +op_template = function(params, template, nparams) if not params then return sub(template, 9) end local op = tonumber(sub(template, 1, 8), 16) local n, rs = 1, 26 @@ -1669,6 +1750,8 @@ map_op[".template__"] = function(params, template, nparams) wputpos(pos, op) end +map_op[".template__"] = op_template + ------------------------------------------------------------------------------ -- Pseudo-opcode to mark the position where the action list is to be emitted. diff --git a/src/vm_ppc.dasc b/src/vm_ppc.dasc index 8e5278af..9299c554 100644 --- a/src/vm_ppc.dasc +++ b/src/vm_ppc.dasc @@ -320,13 +320,6 @@ | |//----------------------------------------------------------------------- | -|// These basic macros should really be part of DynASM. -|.macro srwi, rx, ry, n; rlwinm rx, ry, 32-n, n, 31; .endmacro -|.macro slwi, rx, ry, n; rlwinm rx, ry, n, 0, 31-n; .endmacro -|.macro rotlwi, rx, ry, n; rlwinm rx, ry, n, 0, 31; .endmacro -|.macro rotlw, rx, ry, rn; rlwnm rx, ry, rn, 0, 31; .endmacro -|.macro subi, rx, ry, i; addi rx, ry, -i; .endmacro -| |// Trap for not-yet-implemented parts. |.macro NYI; tw 4, sp, sp; .endmacro |