|
@@ -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.
|