diff --git a/bin/linux32/libluajit.a b/bin/linux32/libluajit.a
new file mode 100644
index 0000000..f5f5346
Binary files /dev/null and b/bin/linux32/libluajit.a differ
diff --git a/bin/linux32/libluajit.so b/bin/linux32/libluajit.so
new file mode 100755
index 0000000..dce9425
Binary files /dev/null and b/bin/linux32/libluajit.so differ
diff --git a/bin/linux32/luajit-bin b/bin/linux32/luajit-bin
new file mode 100755
index 0000000..48a5848
Binary files /dev/null and b/bin/linux32/luajit-bin differ
diff --git a/bin/linux64/libluajit.a b/bin/linux64/libluajit.a
index 65579ec..f70519b 100644
Binary files a/bin/linux64/libluajit.a and b/bin/linux64/libluajit.a differ
diff --git a/bin/linux64/libluajit.so b/bin/linux64/libluajit.so
index 0ee9928..a72f3da 100755
Binary files a/bin/linux64/libluajit.so and b/bin/linux64/libluajit.so differ
diff --git a/bin/linux64/luajit b/bin/linux64/luajit
deleted file mode 100755
index 741a312..0000000
Binary files a/bin/linux64/luajit and /dev/null differ
diff --git a/bin/linux64/luajit-bin b/bin/linux64/luajit-bin
new file mode 100755
index 0000000..7a37147
Binary files /dev/null and b/bin/linux64/luajit-bin differ
diff --git a/bin/mingw32/lua51.dll b/bin/mingw32/lua51.dll
new file mode 100755
index 0000000..0af04b0
Binary files /dev/null and b/bin/mingw32/lua51.dll differ
diff --git a/bin/mingw32/luajit.a b/bin/mingw32/luajit.a
new file mode 100644
index 0000000..402adfd
Binary files /dev/null and b/bin/mingw32/luajit.a differ
diff --git a/bin/mingw32/luajit.exe b/bin/mingw32/luajit.exe
new file mode 100755
index 0000000..2fb5396
Binary files /dev/null and b/bin/mingw32/luajit.exe differ
diff --git a/bin/mingw64/lua51.dll b/bin/mingw64/lua51.dll
old mode 100644
new mode 100755
index eef6c27..c885dba
Binary files a/bin/mingw64/lua51.dll and b/bin/mingw64/lua51.dll differ
diff --git a/bin/mingw64/luajit.a b/bin/mingw64/luajit.a
index 47c9e26..f5b60e7 100644
Binary files a/bin/mingw64/luajit.a and b/bin/mingw64/luajit.a differ
diff --git a/bin/mingw64/luajit.exe b/bin/mingw64/luajit.exe
old mode 100644
new mode 100755
index e7c6f97..c715cd8
Binary files a/bin/mingw64/luajit.exe and b/bin/mingw64/luajit.exe differ
diff --git a/bin/mingw64/luajit.exe.manifest b/bin/mingw64/luajit.exe.manifest
deleted file mode 100644
index 48ec101..0000000
--- a/bin/mingw64/luajit.exe.manifest
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-LuaJIT
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/bin/osx64/libluajit.a b/bin/osx64/libluajit.a
index 99a609d..8aa2a9f 100644
Binary files a/bin/osx64/libluajit.a and b/bin/osx64/libluajit.a differ
diff --git a/bin/osx64/libluajit.dylib b/bin/osx64/libluajit.dylib
index 4d3b945..4c452e8 100755
Binary files a/bin/osx64/libluajit.dylib and b/bin/osx64/libluajit.dylib differ
diff --git a/bin/osx64/luajit b/bin/osx64/luajit
deleted file mode 100755
index 9e957c3..0000000
Binary files a/bin/osx64/luajit and /dev/null differ
diff --git a/bin/osx64/luajit-bin b/bin/osx64/luajit-bin
new file mode 100755
index 0000000..8bf43d3
Binary files /dev/null and b/bin/osx64/luajit-bin differ
diff --git a/csrc/luajit/build-osx64.sh b/csrc/luajit/build-osx64.sh
index d2ee4e0..46a22d1 100755
--- a/csrc/luajit/build-osx64.sh
+++ b/csrc/luajit/build-osx64.sh
@@ -1,4 +1,4 @@
-[ `uname` = Linux ] && { export CROSS=x86_64-apple-darwin15-; export TARGET_SYS=Darwin; }
+[ `uname` = Linux ] && { export CROSS=x86_64-apple-darwin19-; export TARGET_SYS=Darwin; }
P=osx64 HOST_CC="gcc" CFLAGS="-fPIC" \
TARGET_CFLAGS="-arch x86_64 -fPIC" \
TARGET_LDFLAGS="-arch x86_64" ./build-osx.sh
diff --git a/csrc/luajit/build.sh b/csrc/luajit/build.sh
index c06dc5a..83fb99b 100755
--- a/csrc/luajit/build.sh
+++ b/csrc/luajit/build.sh
@@ -16,6 +16,8 @@ CFLAGS="$CFLAGS \
"$MAKE" VERBOSE=1 HOST_CC="$HOST_CC" CC="$CC" clean
"$MAKE" VERBOSE=1 HOST_CC="$HOST_CC" CC="$CC" amalg Q=" " CFLAGS="$CFLAGS"
+mkdir -p $bindir
+
[ "$X0" ] || X0=$X; cp -f $X0 "$bindir/$X"
[ "$D0" ] || D0=$D; cp -f $D0 "$bindir/$D"
diff --git a/jit/bc.lua b/jit/bc.lua
index 14c2816..031b590 100644
--- a/jit/bc.lua
+++ b/jit/bc.lua
@@ -1,7 +1,7 @@
----------------------------------------------------------------------------
-- LuaJIT bytecode listing module.
--
--- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h
----------------------------------------------------------------------------
--
diff --git a/jit/bcsave.lua b/jit/bcsave.lua
index 929b713..b8859a1 100644
--- a/jit/bcsave.lua
+++ b/jit/bcsave.lua
@@ -1,7 +1,7 @@
----------------------------------------------------------------------------
-- LuaJIT module to save/list bytecode.
--
--- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h
----------------------------------------------------------------------------
--
@@ -34,6 +34,7 @@ Save LuaJIT bytecode: luajit -b[options] input output
-t type Set output file type (default: auto-detect from output name).
-a arch Override architecture for object files (default: native).
-o os Override OS for object files (default: native).
+ -F name Override filename (default: input filename).
-e chunk Use chunk string as input.
-- Stop handling options.
- Use stdin as input and/or stdout as output.
@@ -50,10 +51,22 @@ local function check(ok, ...)
os.exit(1)
end
-local function readfile(input)
+local function readfile(ctx, input)
if type(input) == "function" then return input end
- if input == "-" then input = nil end
- return check(loadfile(input))
+ if ctx.filename then
+ local data
+ if input == "-" then
+ data = io.stdin:read("*a")
+ else
+ local fp = assert(io.open(input, "rb"))
+ data = assert(fp:read("*a"))
+ assert(fp:close())
+ end
+ return check(load(data, ctx.filename))
+ else
+ if input == "-" then input = nil end
+ return check(loadfile(input))
+ end
end
local function savefile(name, mode)
@@ -61,6 +74,11 @@ local function savefile(name, mode)
return check(io.open(name, mode))
end
+local function set_stdout_binary(ffi)
+ ffi.cdef[[int _setmode(int fd, int mode);]]
+ ffi.C._setmode(1, 0x8000)
+end
+
------------------------------------------------------------------------------
local map_type = {
@@ -126,6 +144,11 @@ local function bcsave_tail(fp, output, s)
end
local function bcsave_raw(output, s)
+ if output == "-" and jit.os == "Windows" then
+ local ok, ffi = pcall(require, "ffi")
+ check(ok, "FFI library required to write binary file to stdout")
+ set_stdout_binary(ffi)
+ end
local fp = savefile(output, "wb")
bcsave_tail(fp, output, s)
end
@@ -447,18 +470,18 @@ typedef struct {
uint32_t value;
} mach_nlist;
typedef struct {
- uint32_t strx;
+ int32_t strx;
uint8_t type, sect;
uint16_t desc;
uint64_t value;
} mach_nlist_64;
typedef struct
{
- uint32_t magic, nfat_arch;
+ int32_t magic, nfat_arch;
} mach_fat_header;
typedef struct
{
- uint32_t cputype, cpusubtype, offset, size, align;
+ int32_t cputype, cpusubtype, offset, size, align;
} mach_fat_arch;
typedef struct {
struct {
@@ -492,6 +515,18 @@ typedef struct {
mach_nlist sym_entry;
uint8_t space[4096];
} mach_fat_obj;
+typedef struct {
+ mach_fat_header fat;
+ mach_fat_arch fat_arch[2];
+ struct {
+ mach_header_64 hdr;
+ mach_segment_command_64 seg;
+ mach_section_64 sec;
+ mach_symtab_command sym;
+ } arch[2];
+ mach_nlist_64 sym_entry;
+ uint8_t space[4096];
+} mach_fat_obj_64;
]]
local symname = '_'..LJBC_PREFIX..ctx.modname
local isfat, is64, align, mobj = false, false, 4, "mach_obj"
@@ -500,7 +535,7 @@ typedef struct {
elseif ctx.arch == "arm" then
isfat, mobj = true, "mach_fat_obj"
elseif ctx.arch == "arm64" then
- is64, align, isfat, mobj = true, 8, true, "mach_fat_obj"
+ is64, align, isfat, mobj = true, 8, true, "mach_fat_obj_64"
else
check(ctx.arch == "x86", "unsupported architecture for OSX")
end
@@ -569,6 +604,9 @@ end
local function bcsave_obj(ctx, output, s)
local ok, ffi = pcall(require, "ffi")
check(ok, "FFI library required to write this file type")
+ if output == "-" and jit.os == "Windows" then
+ set_stdout_binary(ffi)
+ end
if ctx.os == "windows" then
return bcsave_peobj(ctx, output, s, ffi)
elseif ctx.os == "osx" then
@@ -580,13 +618,13 @@ end
------------------------------------------------------------------------------
-local function bclist(input, output, lineinfo)
- local f = readfile(input)
+local function bclist(ctx, input, output, lineinfo)
+ local f = readfile(ctx, input)
require("jit.bc").dump(f, savefile(output, "w"), true, lineinfo)
end
local function bcsave(ctx, input, output)
- local f = readfile(input)
+ local f = readfile(ctx, input)
local s = string.dump(f, ctx.strip)
local t = ctx.type
if not t then
@@ -643,6 +681,8 @@ local function docmd(...)
ctx.arch = checkarg(tremove(arg, n), map_arch, "architecture")
elseif opt == "o" then
ctx.os = checkarg(tremove(arg, n), map_os, "OS name")
+ elseif opt == "F" then
+ ctx.filename = "@"..tremove(arg, n)
else
usage()
end
@@ -654,7 +694,7 @@ local function docmd(...)
end
if list then
if #arg == 0 or #arg > 2 then usage() end
- bclist(arg[1], arg[2] or "-", lineinfo)
+ bclist(ctx, arg[1], arg[2] or "-", lineinfo)
else
if #arg ~= 2 then usage() end
bcsave(ctx, arg[1], arg[2])
diff --git a/jit/dis_arm.lua b/jit/dis_arm.lua
new file mode 100644
index 0000000..18ab68d
--- /dev/null
+++ b/jit/dis_arm.lua
@@ -0,0 +1,689 @@
+----------------------------------------------------------------------------
+-- LuaJIT ARM disassembler module.
+--
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
+-- Released under the MIT license. See Copyright Notice in luajit.h
+----------------------------------------------------------------------------
+-- This is a helper module used by the LuaJIT machine code dumper module.
+--
+-- It disassembles most user-mode ARMv7 instructions
+-- NYI: Advanced SIMD and VFP instructions.
+------------------------------------------------------------------------------
+
+local type = type
+local sub, byte, format = string.sub, string.byte, string.format
+local match, gmatch = string.match, string.gmatch
+local concat = table.concat
+local bit = require("bit")
+local band, bor, ror, tohex = bit.band, bit.bor, bit.ror, bit.tohex
+local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift
+
+------------------------------------------------------------------------------
+-- Opcode maps
+------------------------------------------------------------------------------
+
+local map_loadc = {
+ shift = 8, mask = 15,
+ [10] = {
+ shift = 20, mask = 1,
+ [0] = {
+ shift = 23, mask = 3,
+ [0] = "vmovFmDN", "vstmFNdr",
+ _ = {
+ shift = 21, mask = 1,
+ [0] = "vstrFdl",
+ { shift = 16, mask = 15, [13] = "vpushFdr", _ = "vstmdbFNdr", }
+ },
+ },
+ {
+ shift = 23, mask = 3,
+ [0] = "vmovFDNm",
+ { shift = 16, mask = 15, [13] = "vpopFdr", _ = "vldmFNdr", },
+ _ = {
+ shift = 21, mask = 1,
+ [0] = "vldrFdl", "vldmdbFNdr",
+ },
+ },
+ },
+ [11] = {
+ shift = 20, mask = 1,
+ [0] = {
+ shift = 23, mask = 3,
+ [0] = "vmovGmDN", "vstmGNdr",
+ _ = {
+ shift = 21, mask = 1,
+ [0] = "vstrGdl",
+ { shift = 16, mask = 15, [13] = "vpushGdr", _ = "vstmdbGNdr", }
+ },
+ },
+ {
+ shift = 23, mask = 3,
+ [0] = "vmovGDNm",
+ { shift = 16, mask = 15, [13] = "vpopGdr", _ = "vldmGNdr", },
+ _ = {
+ shift = 21, mask = 1,
+ [0] = "vldrGdl", "vldmdbGNdr",
+ },
+ },
+ },
+ _ = {
+ shift = 0, mask = 0 -- NYI ldc, mcrr, mrrc.
+ },
+}
+
+local map_vfps = {
+ shift = 6, mask = 0x2c001,
+ [0] = "vmlaF.dnm", "vmlsF.dnm",
+ [0x04000] = "vnmlsF.dnm", [0x04001] = "vnmlaF.dnm",
+ [0x08000] = "vmulF.dnm", [0x08001] = "vnmulF.dnm",
+ [0x0c000] = "vaddF.dnm", [0x0c001] = "vsubF.dnm",
+ [0x20000] = "vdivF.dnm",
+ [0x24000] = "vfnmsF.dnm", [0x24001] = "vfnmaF.dnm",
+ [0x28000] = "vfmaF.dnm", [0x28001] = "vfmsF.dnm",
+ [0x2c000] = "vmovF.dY",
+ [0x2c001] = {
+ shift = 7, mask = 0x1e01,
+ [0] = "vmovF.dm", "vabsF.dm",
+ [0x0200] = "vnegF.dm", [0x0201] = "vsqrtF.dm",
+ [0x0800] = "vcmpF.dm", [0x0801] = "vcmpeF.dm",
+ [0x0a00] = "vcmpzF.d", [0x0a01] = "vcmpzeF.d",
+ [0x0e01] = "vcvtG.dF.m",
+ [0x1000] = "vcvt.f32.u32Fdm", [0x1001] = "vcvt.f32.s32Fdm",
+ [0x1800] = "vcvtr.u32F.dm", [0x1801] = "vcvt.u32F.dm",
+ [0x1a00] = "vcvtr.s32F.dm", [0x1a01] = "vcvt.s32F.dm",
+ },
+}
+
+local map_vfpd = {
+ shift = 6, mask = 0x2c001,
+ [0] = "vmlaG.dnm", "vmlsG.dnm",
+ [0x04000] = "vnmlsG.dnm", [0x04001] = "vnmlaG.dnm",
+ [0x08000] = "vmulG.dnm", [0x08001] = "vnmulG.dnm",
+ [0x0c000] = "vaddG.dnm", [0x0c001] = "vsubG.dnm",
+ [0x20000] = "vdivG.dnm",
+ [0x24000] = "vfnmsG.dnm", [0x24001] = "vfnmaG.dnm",
+ [0x28000] = "vfmaG.dnm", [0x28001] = "vfmsG.dnm",
+ [0x2c000] = "vmovG.dY",
+ [0x2c001] = {
+ shift = 7, mask = 0x1e01,
+ [0] = "vmovG.dm", "vabsG.dm",
+ [0x0200] = "vnegG.dm", [0x0201] = "vsqrtG.dm",
+ [0x0800] = "vcmpG.dm", [0x0801] = "vcmpeG.dm",
+ [0x0a00] = "vcmpzG.d", [0x0a01] = "vcmpzeG.d",
+ [0x0e01] = "vcvtF.dG.m",
+ [0x1000] = "vcvt.f64.u32GdFm", [0x1001] = "vcvt.f64.s32GdFm",
+ [0x1800] = "vcvtr.u32FdG.m", [0x1801] = "vcvt.u32FdG.m",
+ [0x1a00] = "vcvtr.s32FdG.m", [0x1a01] = "vcvt.s32FdG.m",
+ },
+}
+
+local map_datac = {
+ shift = 24, mask = 1,
+ [0] = {
+ shift = 4, mask = 1,
+ [0] = {
+ shift = 8, mask = 15,
+ [10] = map_vfps,
+ [11] = map_vfpd,
+ -- NYI cdp, mcr, mrc.
+ },
+ {
+ shift = 8, mask = 15,
+ [10] = {
+ shift = 20, mask = 15,
+ [0] = "vmovFnD", "vmovFDn",
+ [14] = "vmsrD",
+ [15] = { shift = 12, mask = 15, [15] = "vmrs", _ = "vmrsD", },
+ },
+ },
+ },
+ "svcT",
+}
+
+local map_loadcu = {
+ shift = 0, mask = 0, -- NYI unconditional CP load/store.
+}
+
+local map_datacu = {
+ shift = 0, mask = 0, -- NYI unconditional CP data.
+}
+
+local map_simddata = {
+ shift = 0, mask = 0, -- NYI SIMD data.
+}
+
+local map_simdload = {
+ shift = 0, mask = 0, -- NYI SIMD load/store, preload.
+}
+
+local map_preload = {
+ shift = 0, mask = 0, -- NYI preload.
+}
+
+local map_media = {
+ shift = 20, mask = 31,
+ [0] = false,
+ { --01
+ shift = 5, mask = 7,
+ [0] = "sadd16DNM", "sasxDNM", "ssaxDNM", "ssub16DNM",
+ "sadd8DNM", false, false, "ssub8DNM",
+ },
+ { --02
+ shift = 5, mask = 7,
+ [0] = "qadd16DNM", "qasxDNM", "qsaxDNM", "qsub16DNM",
+ "qadd8DNM", false, false, "qsub8DNM",
+ },
+ { --03
+ shift = 5, mask = 7,
+ [0] = "shadd16DNM", "shasxDNM", "shsaxDNM", "shsub16DNM",
+ "shadd8DNM", false, false, "shsub8DNM",
+ },
+ false,
+ { --05
+ shift = 5, mask = 7,
+ [0] = "uadd16DNM", "uasxDNM", "usaxDNM", "usub16DNM",
+ "uadd8DNM", false, false, "usub8DNM",
+ },
+ { --06
+ shift = 5, mask = 7,
+ [0] = "uqadd16DNM", "uqasxDNM", "uqsaxDNM", "uqsub16DNM",
+ "uqadd8DNM", false, false, "uqsub8DNM",
+ },
+ { --07
+ shift = 5, mask = 7,
+ [0] = "uhadd16DNM", "uhasxDNM", "uhsaxDNM", "uhsub16DNM",
+ "uhadd8DNM", false, false, "uhsub8DNM",
+ },
+ { --08
+ shift = 5, mask = 7,
+ [0] = "pkhbtDNMU", false, "pkhtbDNMU",
+ { shift = 16, mask = 15, [15] = "sxtb16DMU", _ = "sxtab16DNMU", },
+ "pkhbtDNMU", "selDNM", "pkhtbDNMU",
+ },
+ false,
+ { --0a
+ shift = 5, mask = 7,
+ [0] = "ssatDxMu", "ssat16DxM", "ssatDxMu",
+ { shift = 16, mask = 15, [15] = "sxtbDMU", _ = "sxtabDNMU", },
+ "ssatDxMu", false, "ssatDxMu",
+ },
+ { --0b
+ shift = 5, mask = 7,
+ [0] = "ssatDxMu", "revDM", "ssatDxMu",
+ { shift = 16, mask = 15, [15] = "sxthDMU", _ = "sxtahDNMU", },
+ "ssatDxMu", "rev16DM", "ssatDxMu",
+ },
+ { --0c
+ shift = 5, mask = 7,
+ [3] = { shift = 16, mask = 15, [15] = "uxtb16DMU", _ = "uxtab16DNMU", },
+ },
+ false,
+ { --0e
+ shift = 5, mask = 7,
+ [0] = "usatDwMu", "usat16DwM", "usatDwMu",
+ { shift = 16, mask = 15, [15] = "uxtbDMU", _ = "uxtabDNMU", },
+ "usatDwMu", false, "usatDwMu",
+ },
+ { --0f
+ shift = 5, mask = 7,
+ [0] = "usatDwMu", "rbitDM", "usatDwMu",
+ { shift = 16, mask = 15, [15] = "uxthDMU", _ = "uxtahDNMU", },
+ "usatDwMu", "revshDM", "usatDwMu",
+ },
+ { --10
+ shift = 12, mask = 15,
+ [15] = {
+ shift = 5, mask = 7,
+ "smuadNMS", "smuadxNMS", "smusdNMS", "smusdxNMS",
+ },
+ _ = {
+ shift = 5, mask = 7,
+ [0] = "smladNMSD", "smladxNMSD", "smlsdNMSD", "smlsdxNMSD",
+ },
+ },
+ false, false, false,
+ { --14
+ shift = 5, mask = 7,
+ [0] = "smlaldDNMS", "smlaldxDNMS", "smlsldDNMS", "smlsldxDNMS",
+ },
+ { --15
+ shift = 5, mask = 7,
+ [0] = { shift = 12, mask = 15, [15] = "smmulNMS", _ = "smmlaNMSD", },
+ { shift = 12, mask = 15, [15] = "smmulrNMS", _ = "smmlarNMSD", },
+ false, false, false, false,
+ "smmlsNMSD", "smmlsrNMSD",
+ },
+ false, false,
+ { --18
+ shift = 5, mask = 7,
+ [0] = { shift = 12, mask = 15, [15] = "usad8NMS", _ = "usada8NMSD", },
+ },
+ false,
+ { --1a
+ shift = 5, mask = 3, [2] = "sbfxDMvw",
+ },
+ { --1b
+ shift = 5, mask = 3, [2] = "sbfxDMvw",
+ },
+ { --1c
+ shift = 5, mask = 3,
+ [0] = { shift = 0, mask = 15, [15] = "bfcDvX", _ = "bfiDMvX", },
+ },
+ { --1d
+ shift = 5, mask = 3,
+ [0] = { shift = 0, mask = 15, [15] = "bfcDvX", _ = "bfiDMvX", },
+ },
+ { --1e
+ shift = 5, mask = 3, [2] = "ubfxDMvw",
+ },
+ { --1f
+ shift = 5, mask = 3, [2] = "ubfxDMvw",
+ },
+}
+
+local map_load = {
+ shift = 21, mask = 9,
+ {
+ shift = 20, mask = 5,
+ [0] = "strtDL", "ldrtDL", [4] = "strbtDL", [5] = "ldrbtDL",
+ },
+ _ = {
+ shift = 20, mask = 5,
+ [0] = "strDL", "ldrDL", [4] = "strbDL", [5] = "ldrbDL",
+ }
+}
+
+local map_load1 = {
+ shift = 4, mask = 1,
+ [0] = map_load, map_media,
+}
+
+local map_loadm = {
+ shift = 20, mask = 1,
+ [0] = {
+ shift = 23, mask = 3,
+ [0] = "stmdaNR", "stmNR",
+ { shift = 16, mask = 63, [45] = "pushR", _ = "stmdbNR", }, "stmibNR",
+ },
+ {
+ shift = 23, mask = 3,
+ [0] = "ldmdaNR", { shift = 16, mask = 63, [61] = "popR", _ = "ldmNR", },
+ "ldmdbNR", "ldmibNR",
+ },
+}
+
+local map_data = {
+ shift = 21, mask = 15,
+ [0] = "andDNPs", "eorDNPs", "subDNPs", "rsbDNPs",
+ "addDNPs", "adcDNPs", "sbcDNPs", "rscDNPs",
+ "tstNP", "teqNP", "cmpNP", "cmnNP",
+ "orrDNPs", "movDPs", "bicDNPs", "mvnDPs",
+}
+
+local map_mul = {
+ shift = 21, mask = 7,
+ [0] = "mulNMSs", "mlaNMSDs", "umaalDNMS", "mlsDNMS",
+ "umullDNMSs", "umlalDNMSs", "smullDNMSs", "smlalDNMSs",
+}
+
+local map_sync = {
+ shift = 20, mask = 15, -- NYI: brackets around N. R(D+1) for ldrexd/strexd.
+ [0] = "swpDMN", false, false, false,
+ "swpbDMN", false, false, false,
+ "strexDMN", "ldrexDN", "strexdDN", "ldrexdDN",
+ "strexbDMN", "ldrexbDN", "strexhDN", "ldrexhDN",
+}
+
+local map_mulh = {
+ shift = 21, mask = 3,
+ [0] = { shift = 5, mask = 3,
+ [0] = "smlabbNMSD", "smlatbNMSD", "smlabtNMSD", "smlattNMSD", },
+ { shift = 5, mask = 3,
+ [0] = "smlawbNMSD", "smulwbNMS", "smlawtNMSD", "smulwtNMS", },
+ { shift = 5, mask = 3,
+ [0] = "smlalbbDNMS", "smlaltbDNMS", "smlalbtDNMS", "smlalttDNMS", },
+ { shift = 5, mask = 3,
+ [0] = "smulbbNMS", "smultbNMS", "smulbtNMS", "smulttNMS", },
+}
+
+local map_misc = {
+ shift = 4, mask = 7,
+ -- NYI: decode PSR bits of msr.
+ [0] = { shift = 21, mask = 1, [0] = "mrsD", "msrM", },
+ { shift = 21, mask = 3, "bxM", false, "clzDM", },
+ { shift = 21, mask = 3, "bxjM", },
+ { shift = 21, mask = 3, "blxM", },
+ false,
+ { shift = 21, mask = 3, [0] = "qaddDMN", "qsubDMN", "qdaddDMN", "qdsubDMN", },
+ false,
+ { shift = 21, mask = 3, "bkptK", },
+}
+
+local map_datar = {
+ shift = 4, mask = 9,
+ [9] = {
+ shift = 5, mask = 3,
+ [0] = { shift = 24, mask = 1, [0] = map_mul, map_sync, },
+ { shift = 20, mask = 1, [0] = "strhDL", "ldrhDL", },
+ { shift = 20, mask = 1, [0] = "ldrdDL", "ldrsbDL", },
+ { shift = 20, mask = 1, [0] = "strdDL", "ldrshDL", },
+ },
+ _ = {
+ shift = 20, mask = 25,
+ [16] = { shift = 7, mask = 1, [0] = map_misc, map_mulh, },
+ _ = {
+ shift = 0, mask = 0xffffffff,
+ [bor(0xe1a00000)] = "nop",
+ _ = map_data,
+ }
+ },
+}
+
+local map_datai = {
+ shift = 20, mask = 31, -- NYI: decode PSR bits of msr. Decode imm12.
+ [16] = "movwDW", [20] = "movtDW",
+ [18] = { shift = 0, mask = 0xf00ff, [0] = "nopv6", _ = "msrNW", },
+ [22] = "msrNW",
+ _ = map_data,
+}
+
+local map_branch = {
+ shift = 24, mask = 1,
+ [0] = "bB", "blB"
+}
+
+local map_condins = {
+ [0] = map_datar, map_datai, map_load, map_load1,
+ map_loadm, map_branch, map_loadc, map_datac
+}
+
+-- NYI: setend.
+local map_uncondins = {
+ [0] = false, map_simddata, map_simdload, map_preload,
+ false, "blxB", map_loadcu, map_datacu,
+}
+
+------------------------------------------------------------------------------
+
+local map_gpr = {
+ [0] = "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
+}
+
+local map_cond = {
+ [0] = "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
+ "hi", "ls", "ge", "lt", "gt", "le", "al",
+}
+
+local map_shift = { [0] = "lsl", "lsr", "asr", "ror", }
+
+------------------------------------------------------------------------------
+
+-- Output a nicely formatted line with an opcode and operands.
+local function putop(ctx, text, operands)
+ local pos = ctx.pos
+ local extra = ""
+ if ctx.rel then
+ local sym = ctx.symtab[ctx.rel]
+ if sym then
+ extra = "\t->"..sym
+ elseif band(ctx.op, 0x0e000000) ~= 0x0a000000 then
+ extra = "\t; 0x"..tohex(ctx.rel)
+ end
+ end
+ if ctx.hexdump > 0 then
+ ctx.out(format("%08x %s %-5s %s%s\n",
+ ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra))
+ else
+ ctx.out(format("%08x %-5s %s%s\n",
+ ctx.addr+pos, text, concat(operands, ", "), extra))
+ end
+ ctx.pos = pos + 4
+end
+
+-- Fallback for unknown opcodes.
+local function unknown(ctx)
+ return putop(ctx, ".long", { "0x"..tohex(ctx.op) })
+end
+
+-- Format operand 2 of load/store opcodes.
+local function fmtload(ctx, op, pos)
+ local base = map_gpr[band(rshift(op, 16), 15)]
+ local x, ofs
+ local ext = (band(op, 0x04000000) == 0)
+ if not ext and band(op, 0x02000000) == 0 then
+ ofs = band(op, 4095)
+ if band(op, 0x00800000) == 0 then ofs = -ofs end
+ if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end
+ ofs = "#"..ofs
+ elseif ext and band(op, 0x00400000) ~= 0 then
+ ofs = band(op, 15) + band(rshift(op, 4), 0xf0)
+ if band(op, 0x00800000) == 0 then ofs = -ofs end
+ if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end
+ ofs = "#"..ofs
+ else
+ ofs = map_gpr[band(op, 15)]
+ if ext or band(op, 0xfe0) == 0 then
+ elseif band(op, 0xfe0) == 0x60 then
+ ofs = format("%s, rrx", ofs)
+ else
+ local sh = band(rshift(op, 7), 31)
+ if sh == 0 then sh = 32 end
+ ofs = format("%s, %s #%d", ofs, map_shift[band(rshift(op, 5), 3)], sh)
+ end
+ if band(op, 0x00800000) == 0 then ofs = "-"..ofs end
+ end
+ if ofs == "#0" then
+ x = format("[%s]", base)
+ elseif band(op, 0x01000000) == 0 then
+ x = format("[%s], %s", base, ofs)
+ else
+ x = format("[%s, %s]", base, ofs)
+ end
+ if band(op, 0x01200000) == 0x01200000 then x = x.."!" end
+ return x
+end
+
+-- Format operand 2 of vector load/store opcodes.
+local function fmtvload(ctx, op, pos)
+ local base = map_gpr[band(rshift(op, 16), 15)]
+ local ofs = band(op, 255)*4
+ if band(op, 0x00800000) == 0 then ofs = -ofs end
+ if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end
+ if ofs == 0 then
+ return format("[%s]", base)
+ else
+ return format("[%s, #%d]", base, ofs)
+ end
+end
+
+local function fmtvr(op, vr, sh0, sh1)
+ if vr == "s" then
+ return format("s%d", 2*band(rshift(op, sh0), 15)+band(rshift(op, sh1), 1))
+ else
+ return format("d%d", band(rshift(op, sh0), 15)+band(rshift(op, sh1-4), 16))
+ end
+end
+
+-- Disassemble a single instruction.
+local function disass_ins(ctx)
+ local pos = ctx.pos
+ local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4)
+ local op = bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0)
+ local operands = {}
+ local suffix = ""
+ local last, name, pat
+ local vr
+ ctx.op = op
+ ctx.rel = nil
+
+ local cond = rshift(op, 28)
+ local opat
+ if cond == 15 then
+ opat = map_uncondins[band(rshift(op, 25), 7)]
+ else
+ if cond ~= 14 then suffix = map_cond[cond] end
+ opat = map_condins[band(rshift(op, 25), 7)]
+ end
+ while type(opat) ~= "string" do
+ if not opat then return unknown(ctx) end
+ opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._
+ end
+ name, pat = match(opat, "^([a-z0-9]*)(.*)")
+ if sub(pat, 1, 1) == "." then
+ local s2, p2 = match(pat, "^([a-z0-9.]*)(.*)")
+ suffix = suffix..s2
+ pat = p2
+ end
+
+ for p in gmatch(pat, ".") do
+ local x = nil
+ if p == "D" then
+ x = map_gpr[band(rshift(op, 12), 15)]
+ elseif p == "N" then
+ x = map_gpr[band(rshift(op, 16), 15)]
+ elseif p == "S" then
+ x = map_gpr[band(rshift(op, 8), 15)]
+ elseif p == "M" then
+ x = map_gpr[band(op, 15)]
+ elseif p == "d" then
+ x = fmtvr(op, vr, 12, 22)
+ elseif p == "n" then
+ x = fmtvr(op, vr, 16, 7)
+ elseif p == "m" then
+ x = fmtvr(op, vr, 0, 5)
+ elseif p == "P" then
+ if band(op, 0x02000000) ~= 0 then
+ x = ror(band(op, 255), 2*band(rshift(op, 8), 15))
+ else
+ x = map_gpr[band(op, 15)]
+ if band(op, 0xff0) ~= 0 then
+ operands[#operands+1] = x
+ local s = map_shift[band(rshift(op, 5), 3)]
+ local r = nil
+ if band(op, 0xf90) == 0 then
+ if s == "ror" then s = "rrx" else r = "#32" end
+ elseif band(op, 0x10) == 0 then
+ r = "#"..band(rshift(op, 7), 31)
+ else
+ r = map_gpr[band(rshift(op, 8), 15)]
+ end
+ if name == "mov" then name = s; x = r
+ elseif r then x = format("%s %s", s, r)
+ else x = s end
+ end
+ end
+ elseif p == "L" then
+ x = fmtload(ctx, op, pos)
+ elseif p == "l" then
+ x = fmtvload(ctx, op, pos)
+ elseif p == "B" then
+ local addr = ctx.addr + pos + 8 + arshift(lshift(op, 8), 6)
+ if cond == 15 then addr = addr + band(rshift(op, 23), 2) end
+ ctx.rel = addr
+ x = "0x"..tohex(addr)
+ elseif p == "F" then
+ vr = "s"
+ elseif p == "G" then
+ vr = "d"
+ elseif p == "." then
+ suffix = suffix..(vr == "s" and ".f32" or ".f64")
+ elseif p == "R" then
+ if band(op, 0x00200000) ~= 0 and #operands == 1 then
+ operands[1] = operands[1].."!"
+ end
+ local t = {}
+ for i=0,15 do
+ if band(rshift(op, i), 1) == 1 then t[#t+1] = map_gpr[i] end
+ end
+ x = "{"..concat(t, ", ").."}"
+ elseif p == "r" then
+ if band(op, 0x00200000) ~= 0 and #operands == 2 then
+ operands[1] = operands[1].."!"
+ end
+ local s = tonumber(sub(last, 2))
+ local n = band(op, 255)
+ if vr == "d" then n = rshift(n, 1) end
+ operands[#operands] = format("{%s-%s%d}", last, vr, s+n-1)
+ elseif p == "W" then
+ x = band(op, 0x0fff) + band(rshift(op, 4), 0xf000)
+ elseif p == "T" then
+ x = "#0x"..tohex(band(op, 0x00ffffff), 6)
+ elseif p == "U" then
+ x = band(rshift(op, 7), 31)
+ if x == 0 then x = nil end
+ elseif p == "u" then
+ x = band(rshift(op, 7), 31)
+ if band(op, 0x40) == 0 then
+ if x == 0 then x = nil else x = "lsl #"..x end
+ else
+ if x == 0 then x = "asr #32" else x = "asr #"..x end
+ end
+ elseif p == "v" then
+ x = band(rshift(op, 7), 31)
+ elseif p == "w" then
+ x = band(rshift(op, 16), 31)
+ elseif p == "x" then
+ x = band(rshift(op, 16), 31) + 1
+ elseif p == "X" then
+ x = band(rshift(op, 16), 31) - last + 1
+ elseif p == "Y" then
+ x = band(rshift(op, 12), 0xf0) + band(op, 0x0f)
+ elseif p == "K" then
+ x = "#0x"..tohex(band(rshift(op, 4), 0x0000fff0) + band(op, 15), 4)
+ elseif p == "s" then
+ if band(op, 0x00100000) ~= 0 then suffix = "s"..suffix end
+ else
+ assert(false)
+ end
+ if x then
+ last = x
+ if type(x) == "number" then x = "#"..x end
+ operands[#operands+1] = x
+ end
+ end
+
+ return putop(ctx, name..suffix, operands)
+end
+
+------------------------------------------------------------------------------
+
+-- Disassemble a block of code.
+local function disass_block(ctx, ofs, len)
+ if not ofs then ofs = 0 end
+ local stop = len and ofs+len or #ctx.code
+ ctx.pos = ofs
+ ctx.rel = nil
+ while ctx.pos < stop do disass_ins(ctx) end
+end
+
+-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).
+local function create(code, addr, out)
+ local ctx = {}
+ ctx.code = code
+ ctx.addr = addr or 0
+ ctx.out = out or io.write
+ ctx.symtab = {}
+ ctx.disass = disass_block
+ ctx.hexdump = 8
+ return ctx
+end
+
+-- Simple API: disassemble code (a string) at address and output via out.
+local function disass(code, addr, out)
+ create(code, addr, out):disass()
+end
+
+-- Return register name for RID.
+local function regname(r)
+ if r < 16 then return map_gpr[r] end
+ return "d"..(r-16)
+end
+
+-- Public module functions.
+return {
+ create = create,
+ disass = disass,
+ regname = regname
+}
+
diff --git a/jit/dis_arm64.lua b/jit/dis_arm64.lua
new file mode 100644
index 0000000..531584a
--- /dev/null
+++ b/jit/dis_arm64.lua
@@ -0,0 +1,1216 @@
+----------------------------------------------------------------------------
+-- LuaJIT ARM64 disassembler module.
+--
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
+-- Released under the MIT license. See Copyright Notice in luajit.h
+--
+-- Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com.
+-- Sponsored by Cisco Systems, Inc.
+----------------------------------------------------------------------------
+-- This is a helper module used by the LuaJIT machine code dumper module.
+--
+-- It disassembles most user-mode AArch64 instructions.
+-- NYI: Advanced SIMD and VFP instructions.
+------------------------------------------------------------------------------
+
+local type = type
+local sub, byte, format = string.sub, string.byte, string.format
+local match, gmatch, gsub = string.match, string.gmatch, string.gsub
+local concat = table.concat
+local bit = require("bit")
+local band, bor, bxor, tohex = bit.band, bit.bor, bit.bxor, bit.tohex
+local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift
+local ror = bit.ror
+
+------------------------------------------------------------------------------
+-- Opcode maps
+------------------------------------------------------------------------------
+
+local map_adr = { -- PC-relative addressing.
+ shift = 31, mask = 1,
+ [0] = "adrDBx", "adrpDBx"
+}
+
+local map_addsubi = { -- Add/subtract immediate.
+ shift = 29, mask = 3,
+ [0] = "add|movDNIg", "adds|cmnD0NIg", "subDNIg", "subs|cmpD0NIg",
+}
+
+local map_logi = { -- Logical immediate.
+ shift = 31, mask = 1,
+ [0] = {
+ shift = 22, mask = 1,
+ [0] = {
+ shift = 29, mask = 3,
+ [0] = "andDNig", "orr|movDN0ig", "eorDNig", "ands|tstD0Nig"
+ },
+ false -- unallocated
+ },
+ {
+ shift = 29, mask = 3,
+ [0] = "andDNig", "orr|movDN0ig", "eorDNig", "ands|tstD0Nig"
+ }
+}
+
+local map_movwi = { -- Move wide immediate.
+ shift = 31, mask = 1,
+ [0] = {
+ shift = 22, mask = 1,
+ [0] = {
+ shift = 29, mask = 3,
+ [0] = "movnDWRg", false, "movz|movDYRg", "movkDWRg"
+ }, false -- unallocated
+ },
+ {
+ shift = 29, mask = 3,
+ [0] = "movnDWRg", false, "movz|movDYRg", "movkDWRg"
+ },
+}
+
+local map_bitf = { -- Bitfield.
+ shift = 31, mask = 1,
+ [0] = {
+ shift = 22, mask = 1,
+ [0] = {
+ shift = 29, mask = 3,
+ [0] = "sbfm|sbfiz|sbfx|asr|sxtw|sxth|sxtbDN12w",
+ "bfm|bfi|bfxilDN13w",
+ "ubfm|ubfiz|ubfx|lsr|lsl|uxth|uxtbDN12w"
+ }
+ },
+ {
+ shift = 22, mask = 1,
+ {
+ shift = 29, mask = 3,
+ [0] = "sbfm|sbfiz|sbfx|asr|sxtw|sxth|sxtbDN12x",
+ "bfm|bfi|bfxilDN13x",
+ "ubfm|ubfiz|ubfx|lsr|lsl|uxth|uxtbDN12x"
+ }
+ }
+}
+
+local map_datai = { -- Data processing - immediate.
+ shift = 23, mask = 7,
+ [0] = map_adr, map_adr, map_addsubi, false,
+ map_logi, map_movwi, map_bitf,
+ {
+ shift = 15, mask = 0x1c0c1,
+ [0] = "extr|rorDNM4w", [0x10080] = "extr|rorDNM4x",
+ [0x10081] = "extr|rorDNM4x"
+ }
+}
+
+local map_logsr = { -- Logical, shifted register.
+ shift = 31, mask = 1,
+ [0] = {
+ shift = 15, mask = 1,
+ [0] = {
+ shift = 29, mask = 3,
+ [0] = {
+ shift = 21, mask = 7,
+ [0] = "andDNMSg", "bicDNMSg", "andDNMSg", "bicDNMSg",
+ "andDNMSg", "bicDNMSg", "andDNMg", "bicDNMg"
+ },
+ {
+ shift = 21, mask = 7,
+ [0] ="orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0MSg", "orn|mvnDN0MSg",
+ "orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0Mg", "orn|mvnDN0Mg"
+ },
+ {
+ shift = 21, mask = 7,
+ [0] = "eorDNMSg", "eonDNMSg", "eorDNMSg", "eonDNMSg",
+ "eorDNMSg", "eonDNMSg", "eorDNMg", "eonDNMg"
+ },
+ {
+ shift = 21, mask = 7,
+ [0] = "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMSg", "bicsDNMSg",
+ "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMg", "bicsDNMg"
+ }
+ },
+ false -- unallocated
+ },
+ {
+ shift = 29, mask = 3,
+ [0] = {
+ shift = 21, mask = 7,
+ [0] = "andDNMSg", "bicDNMSg", "andDNMSg", "bicDNMSg",
+ "andDNMSg", "bicDNMSg", "andDNMg", "bicDNMg"
+ },
+ {
+ shift = 21, mask = 7,
+ [0] = "orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0MSg", "orn|mvnDN0MSg",
+ "orr|movDN0MSg", "orn|mvnDN0MSg", "orr|movDN0Mg", "orn|mvnDN0Mg"
+ },
+ {
+ shift = 21, mask = 7,
+ [0] = "eorDNMSg", "eonDNMSg", "eorDNMSg", "eonDNMSg",
+ "eorDNMSg", "eonDNMSg", "eorDNMg", "eonDNMg"
+ },
+ {
+ shift = 21, mask = 7,
+ [0] = "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMSg", "bicsDNMSg",
+ "ands|tstD0NMSg", "bicsDNMSg", "ands|tstD0NMg", "bicsDNMg"
+ }
+ }
+}
+
+local map_assh = {
+ shift = 31, mask = 1,
+ [0] = {
+ shift = 15, mask = 1,
+ [0] = {
+ shift = 29, mask = 3,
+ [0] = {
+ shift = 22, mask = 3,
+ [0] = "addDNMSg", "addDNMSg", "addDNMSg", "addDNMg"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "adds|cmnD0NMSg", "adds|cmnD0NMSg",
+ "adds|cmnD0NMSg", "adds|cmnD0NMg"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0Mg"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0MzSg",
+ "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0Mzg"
+ },
+ },
+ false -- unallocated
+ },
+ {
+ shift = 29, mask = 3,
+ [0] = {
+ shift = 22, mask = 3,
+ [0] = "addDNMSg", "addDNMSg", "addDNMSg", "addDNMg"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "adds|cmnD0NMSg", "adds|cmnD0NMSg", "adds|cmnD0NMSg",
+ "adds|cmnD0NMg"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0MSg", "sub|negDN0Mg"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0MzSg",
+ "subs|cmp|negsD0N0MzSg", "subs|cmp|negsD0N0Mzg"
+ }
+ }
+}
+
+local map_addsubsh = { -- Add/subtract, shifted register.
+ shift = 22, mask = 3,
+ [0] = map_assh, map_assh, map_assh
+}
+
+local map_addsubex = { -- Add/subtract, extended register.
+ shift = 22, mask = 3,
+ [0] = {
+ shift = 29, mask = 3,
+ [0] = "addDNMXg", "adds|cmnD0NMXg", "subDNMXg", "subs|cmpD0NMzXg",
+ }
+}
+
+local map_addsubc = { -- Add/subtract, with carry.
+ shift = 10, mask = 63,
+ [0] = {
+ shift = 29, mask = 3,
+ [0] = "adcDNMg", "adcsDNMg", "sbc|ngcDN0Mg", "sbcs|ngcsDN0Mg",
+ }
+}
+
+local map_ccomp = {
+ shift = 4, mask = 1,
+ [0] = {
+ shift = 10, mask = 3,
+ [0] = { -- Conditional compare register.
+ shift = 29, mask = 3,
+ "ccmnNMVCg", false, "ccmpNMVCg",
+ },
+ [2] = { -- Conditional compare immediate.
+ shift = 29, mask = 3,
+ "ccmnN5VCg", false, "ccmpN5VCg",
+ }
+ }
+}
+
+local map_csel = { -- Conditional select.
+ shift = 11, mask = 1,
+ [0] = {
+ shift = 10, mask = 1,
+ [0] = {
+ shift = 29, mask = 3,
+ [0] = "cselDNMzCg", false, "csinv|cinv|csetmDNMcg", false,
+ },
+ {
+ shift = 29, mask = 3,
+ [0] = "csinc|cinc|csetDNMcg", false, "csneg|cnegDNMcg", false,
+ }
+ }
+}
+
+local map_data1s = { -- Data processing, 1 source.
+ shift = 29, mask = 1,
+ [0] = {
+ shift = 31, mask = 1,
+ [0] = {
+ shift = 10, mask = 0x7ff,
+ [0] = "rbitDNg", "rev16DNg", "revDNw", false, "clzDNg", "clsDNg"
+ },
+ {
+ shift = 10, mask = 0x7ff,
+ [0] = "rbitDNg", "rev16DNg", "rev32DNx", "revDNx", "clzDNg", "clsDNg"
+ }
+ }
+}
+
+local map_data2s = { -- Data processing, 2 sources.
+ shift = 29, mask = 1,
+ [0] = {
+ shift = 10, mask = 63,
+ false, "udivDNMg", "sdivDNMg", false, false, false, false, "lslDNMg",
+ "lsrDNMg", "asrDNMg", "rorDNMg"
+ }
+}
+
+local map_data3s = { -- Data processing, 3 sources.
+ shift = 29, mask = 7,
+ [0] = {
+ shift = 21, mask = 7,
+ [0] = {
+ shift = 15, mask = 1,
+ [0] = "madd|mulDNMA0g", "msub|mnegDNMA0g"
+ }
+ }, false, false, false,
+ {
+ shift = 15, mask = 1,
+ [0] = {
+ shift = 21, mask = 7,
+ [0] = "madd|mulDNMA0g", "smaddl|smullDxNMwA0x", "smulhDNMx", false,
+ false, "umaddl|umullDxNMwA0x", "umulhDNMx"
+ },
+ {
+ shift = 21, mask = 7,
+ [0] = "msub|mnegDNMA0g", "smsubl|smneglDxNMwA0x", false, false,
+ false, "umsubl|umneglDxNMwA0x"
+ }
+ }
+}
+
+local map_datar = { -- Data processing, register.
+ shift = 28, mask = 1,
+ [0] = {
+ shift = 24, mask = 1,
+ [0] = map_logsr,
+ {
+ shift = 21, mask = 1,
+ [0] = map_addsubsh, map_addsubex
+ }
+ },
+ {
+ shift = 21, mask = 15,
+ [0] = map_addsubc, false, map_ccomp, false, map_csel, false,
+ {
+ shift = 30, mask = 1,
+ [0] = map_data2s, map_data1s
+ },
+ false, map_data3s, map_data3s, map_data3s, map_data3s, map_data3s,
+ map_data3s, map_data3s, map_data3s
+ }
+}
+
+local map_lrl = { -- Load register, literal.
+ shift = 26, mask = 1,
+ [0] = {
+ shift = 30, mask = 3,
+ [0] = "ldrDwB", "ldrDxB", "ldrswDxB"
+ },
+ {
+ shift = 30, mask = 3,
+ [0] = "ldrDsB", "ldrDdB"
+ }
+}
+
+local map_lsriind = { -- Load/store register, immediate pre/post-indexed.
+ shift = 30, mask = 3,
+ [0] = {
+ shift = 26, mask = 1,
+ [0] = {
+ shift = 22, mask = 3,
+ [0] = "strbDwzL", "ldrbDwzL", "ldrsbDxzL", "ldrsbDwzL"
+ }
+ },
+ {
+ shift = 26, mask = 1,
+ [0] = {
+ shift = 22, mask = 3,
+ [0] = "strhDwzL", "ldrhDwzL", "ldrshDxzL", "ldrshDwzL"
+ }
+ },
+ {
+ shift = 26, mask = 1,
+ [0] = {
+ shift = 22, mask = 3,
+ [0] = "strDwzL", "ldrDwzL", "ldrswDxzL"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "strDszL", "ldrDszL"
+ }
+ },
+ {
+ shift = 26, mask = 1,
+ [0] = {
+ shift = 22, mask = 3,
+ [0] = "strDxzL", "ldrDxzL"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "strDdzL", "ldrDdzL"
+ }
+ }
+}
+
+local map_lsriro = {
+ shift = 21, mask = 1,
+ [0] = { -- Load/store register immediate.
+ shift = 10, mask = 3,
+ [0] = { -- Unscaled immediate.
+ shift = 26, mask = 1,
+ [0] = {
+ shift = 30, mask = 3,
+ [0] = {
+ shift = 22, mask = 3,
+ [0] = "sturbDwK", "ldurbDwK"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "sturhDwK", "ldurhDwK"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "sturDwK", "ldurDwK"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "sturDxK", "ldurDxK"
+ }
+ }
+ }, map_lsriind, false, map_lsriind
+ },
+ { -- Load/store register, register offset.
+ shift = 10, mask = 3,
+ [2] = {
+ shift = 26, mask = 1,
+ [0] = {
+ shift = 30, mask = 3,
+ [0] = {
+ shift = 22, mask = 3,
+ [0] = "strbDwO", "ldrbDwO", "ldrsbDxO", "ldrsbDwO"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "strhDwO", "ldrhDwO", "ldrshDxO", "ldrshDwO"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "strDwO", "ldrDwO", "ldrswDxO"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "strDxO", "ldrDxO"
+ }
+ },
+ {
+ shift = 30, mask = 3,
+ [2] = {
+ shift = 22, mask = 3,
+ [0] = "strDsO", "ldrDsO"
+ },
+ [3] = {
+ shift = 22, mask = 3,
+ [0] = "strDdO", "ldrDdO"
+ }
+ }
+ }
+ }
+}
+
+local map_lsp = { -- Load/store register pair, offset.
+ shift = 22, mask = 1,
+ [0] = {
+ shift = 30, mask = 3,
+ [0] = {
+ shift = 26, mask = 1,
+ [0] = "stpDzAzwP", "stpDzAzsP",
+ },
+ {
+ shift = 26, mask = 1,
+ "stpDzAzdP"
+ },
+ {
+ shift = 26, mask = 1,
+ [0] = "stpDzAzxP"
+ }
+ },
+ {
+ shift = 30, mask = 3,
+ [0] = {
+ shift = 26, mask = 1,
+ [0] = "ldpDzAzwP", "ldpDzAzsP",
+ },
+ {
+ shift = 26, mask = 1,
+ [0] = "ldpswDAxP", "ldpDzAzdP"
+ },
+ {
+ shift = 26, mask = 1,
+ [0] = "ldpDzAzxP"
+ }
+ }
+}
+
+local map_ls = { -- Loads and stores.
+ shift = 24, mask = 0x31,
+ [0x10] = map_lrl, [0x30] = map_lsriro,
+ [0x20] = {
+ shift = 23, mask = 3,
+ map_lsp, map_lsp, map_lsp
+ },
+ [0x21] = {
+ shift = 23, mask = 3,
+ map_lsp, map_lsp, map_lsp
+ },
+ [0x31] = {
+ shift = 26, mask = 1,
+ [0] = {
+ shift = 30, mask = 3,
+ [0] = {
+ shift = 22, mask = 3,
+ [0] = "strbDwzU", "ldrbDwzU"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "strhDwzU", "ldrhDwzU"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "strDwzU", "ldrDwzU"
+ },
+ {
+ shift = 22, mask = 3,
+ [0] = "strDxzU", "ldrDxzU"
+ }
+ },
+ {
+ shift = 30, mask = 3,
+ [2] = {
+ shift = 22, mask = 3,
+ [0] = "strDszU", "ldrDszU"
+ },
+ [3] = {
+ shift = 22, mask = 3,
+ [0] = "strDdzU", "ldrDdzU"
+ }
+ }
+ },
+}
+
+local map_datafp = { -- Data processing, SIMD and FP.
+ shift = 28, mask = 7,
+ { -- 001
+ shift = 24, mask = 1,
+ [0] = {
+ shift = 21, mask = 1,
+ {
+ shift = 10, mask = 3,
+ [0] = {
+ shift = 12, mask = 1,
+ [0] = {
+ shift = 13, mask = 1,
+ [0] = {
+ shift = 14, mask = 1,
+ [0] = {
+ shift = 15, mask = 1,
+ [0] = { -- FP/int conversion.
+ shift = 31, mask = 1,
+ [0] = {
+ shift = 16, mask = 0xff,
+ [0x20] = "fcvtnsDwNs", [0x21] = "fcvtnuDwNs",
+ [0x22] = "scvtfDsNw", [0x23] = "ucvtfDsNw",
+ [0x24] = "fcvtasDwNs", [0x25] = "fcvtauDwNs",
+ [0x26] = "fmovDwNs", [0x27] = "fmovDsNw",
+ [0x28] = "fcvtpsDwNs", [0x29] = "fcvtpuDwNs",
+ [0x30] = "fcvtmsDwNs", [0x31] = "fcvtmuDwNs",
+ [0x38] = "fcvtzsDwNs", [0x39] = "fcvtzuDwNs",
+ [0x60] = "fcvtnsDwNd", [0x61] = "fcvtnuDwNd",
+ [0x62] = "scvtfDdNw", [0x63] = "ucvtfDdNw",
+ [0x64] = "fcvtasDwNd", [0x65] = "fcvtauDwNd",
+ [0x68] = "fcvtpsDwNd", [0x69] = "fcvtpuDwNd",
+ [0x70] = "fcvtmsDwNd", [0x71] = "fcvtmuDwNd",
+ [0x78] = "fcvtzsDwNd", [0x79] = "fcvtzuDwNd"
+ },
+ {
+ shift = 16, mask = 0xff,
+ [0x20] = "fcvtnsDxNs", [0x21] = "fcvtnuDxNs",
+ [0x22] = "scvtfDsNx", [0x23] = "ucvtfDsNx",
+ [0x24] = "fcvtasDxNs", [0x25] = "fcvtauDxNs",
+ [0x28] = "fcvtpsDxNs", [0x29] = "fcvtpuDxNs",
+ [0x30] = "fcvtmsDxNs", [0x31] = "fcvtmuDxNs",
+ [0x38] = "fcvtzsDxNs", [0x39] = "fcvtzuDxNs",
+ [0x60] = "fcvtnsDxNd", [0x61] = "fcvtnuDxNd",
+ [0x62] = "scvtfDdNx", [0x63] = "ucvtfDdNx",
+ [0x64] = "fcvtasDxNd", [0x65] = "fcvtauDxNd",
+ [0x66] = "fmovDxNd", [0x67] = "fmovDdNx",
+ [0x68] = "fcvtpsDxNd", [0x69] = "fcvtpuDxNd",
+ [0x70] = "fcvtmsDxNd", [0x71] = "fcvtmuDxNd",
+ [0x78] = "fcvtzsDxNd", [0x79] = "fcvtzuDxNd"
+ }
+ }
+ },
+ { -- FP data-processing, 1 source.
+ shift = 31, mask = 1,
+ [0] = {
+ shift = 22, mask = 3,
+ [0] = {
+ shift = 15, mask = 63,
+ [0] = "fmovDNf", "fabsDNf", "fnegDNf",
+ "fsqrtDNf", false, "fcvtDdNs", false, false,
+ "frintnDNf", "frintpDNf", "frintmDNf", "frintzDNf",
+ "frintaDNf", false, "frintxDNf", "frintiDNf",
+ },
+ {
+ shift = 15, mask = 63,
+ [0] = "fmovDNf", "fabsDNf", "fnegDNf",
+ "fsqrtDNf", "fcvtDsNd", false, false, false,
+ "frintnDNf", "frintpDNf", "frintmDNf", "frintzDNf",
+ "frintaDNf", false, "frintxDNf", "frintiDNf",
+ }
+ }
+ }
+ },
+ { -- FP compare.
+ shift = 31, mask = 1,
+ [0] = {
+ shift = 14, mask = 3,
+ [0] = {
+ shift = 23, mask = 1,
+ [0] = {
+ shift = 0, mask = 31,
+ [0] = "fcmpNMf", [8] = "fcmpNZf",
+ [16] = "fcmpeNMf", [24] = "fcmpeNZf",
+ }
+ }
+ }
+ }
+ },
+ { -- FP immediate.
+ shift = 31, mask = 1,
+ [0] = {
+ shift = 5, mask = 31,
+ [0] = {
+ shift = 23, mask = 1,
+ [0] = "fmovDFf"
+ }
+ }
+ }
+ },
+ { -- FP conditional compare.
+ shift = 31, mask = 1,
+ [0] = {
+ shift = 23, mask = 1,
+ [0] = {
+ shift = 4, mask = 1,
+ [0] = "fccmpNMVCf", "fccmpeNMVCf"
+ }
+ }
+ },
+ { -- FP data-processing, 2 sources.
+ shift = 31, mask = 1,
+ [0] = {
+ shift = 23, mask = 1,
+ [0] = {
+ shift = 12, mask = 15,
+ [0] = "fmulDNMf", "fdivDNMf", "faddDNMf", "fsubDNMf",
+ "fmaxDNMf", "fminDNMf", "fmaxnmDNMf", "fminnmDNMf",
+ "fnmulDNMf"
+ }
+ }
+ },
+ { -- FP conditional select.
+ shift = 31, mask = 1,
+ [0] = {
+ shift = 23, mask = 1,
+ [0] = "fcselDNMCf"
+ }
+ }
+ }
+ },
+ { -- FP data-processing, 3 sources.
+ shift = 31, mask = 1,
+ [0] = {
+ shift = 15, mask = 1,
+ [0] = {
+ shift = 21, mask = 5,
+ [0] = "fmaddDNMAf", "fnmaddDNMAf"
+ },
+ {
+ shift = 21, mask = 5,
+ [0] = "fmsubDNMAf", "fnmsubDNMAf"
+ }
+ }
+ }
+ }
+}
+
+local map_br = { -- Branches, exception generating and system instructions.
+ shift = 29, mask = 7,
+ [0] = "bB",
+ { -- Compare & branch, immediate.
+ shift = 24, mask = 3,
+ [0] = "cbzDBg", "cbnzDBg", "tbzDTBw", "tbnzDTBw"
+ },
+ { -- Conditional branch, immediate.
+ shift = 24, mask = 3,
+ [0] = {
+ shift = 4, mask = 1,
+ [0] = {
+ shift = 0, mask = 15,
+ [0] = "beqB", "bneB", "bhsB", "bloB", "bmiB", "bplB", "bvsB", "bvcB",
+ "bhiB", "blsB", "bgeB", "bltB", "bgtB", "bleB", "balB"
+ }
+ }
+ }, false, "blB",
+ { -- Compare & branch, immediate.
+ shift = 24, mask = 3,
+ [0] = "cbzDBg", "cbnzDBg", "tbzDTBx", "tbnzDTBx"
+ },
+ {
+ shift = 24, mask = 3,
+ [0] = { -- Exception generation.
+ shift = 0, mask = 0xe0001f,
+ [0x200000] = "brkW"
+ },
+ { -- System instructions.
+ shift = 0, mask = 0x3fffff,
+ [0x03201f] = "nop"
+ },
+ { -- Unconditional branch, register.
+ shift = 0, mask = 0xfffc1f,
+ [0x1f0000] = "brNx", [0x3f0000] = "blrNx",
+ [0x5f0000] = "retNx"
+ },
+ }
+}
+
+local map_init = {
+ shift = 25, mask = 15,
+ [0] = false, false, false, false, map_ls, map_datar, map_ls, map_datafp,
+ map_datai, map_datai, map_br, map_br, map_ls, map_datar, map_ls, map_datafp
+}
+
+------------------------------------------------------------------------------
+
+local map_regs = { x = {}, w = {}, d = {}, s = {} }
+
+for i=0,30 do
+ map_regs.x[i] = "x"..i
+ map_regs.w[i] = "w"..i
+ map_regs.d[i] = "d"..i
+ map_regs.s[i] = "s"..i
+end
+map_regs.x[31] = "sp"
+map_regs.w[31] = "wsp"
+map_regs.d[31] = "d31"
+map_regs.s[31] = "s31"
+
+local map_cond = {
+ [0] = "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
+ "hi", "ls", "ge", "lt", "gt", "le", "al",
+}
+
+local map_shift = { [0] = "lsl", "lsr", "asr", }
+
+local map_extend = {
+ [0] = "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx",
+}
+
+------------------------------------------------------------------------------
+
+-- Output a nicely formatted line with an opcode and operands.
+local function putop(ctx, text, operands)
+ local pos = ctx.pos
+ local extra = ""
+ if ctx.rel then
+ local sym = ctx.symtab[ctx.rel]
+ if sym then
+ extra = "\t->"..sym
+ end
+ end
+ if ctx.hexdump > 0 then
+ ctx.out(format("%08x %s %-5s %s%s\n",
+ ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra))
+ else
+ ctx.out(format("%08x %-5s %s%s\n",
+ ctx.addr+pos, text, concat(operands, ", "), extra))
+ end
+ ctx.pos = pos + 4
+end
+
+-- Fallback for unknown opcodes.
+local function unknown(ctx)
+ return putop(ctx, ".long", { "0x"..tohex(ctx.op) })
+end
+
+local function match_reg(p, pat, regnum)
+ return map_regs[match(pat, p.."%w-([xwds])")][regnum]
+end
+
+local function fmt_hex32(x)
+ if x < 0 then
+ return tohex(x)
+ else
+ return format("%x", x)
+ end
+end
+
+local imm13_rep = { 0x55555555, 0x11111111, 0x01010101, 0x00010001, 0x00000001 }
+
+local function decode_imm13(op)
+ local imms = band(rshift(op, 10), 63)
+ local immr = band(rshift(op, 16), 63)
+ if band(op, 0x00400000) == 0 then
+ local len = 5
+ if imms >= 56 then
+ if imms >= 60 then len = 1 else len = 2 end
+ elseif imms >= 48 then len = 3 elseif imms >= 32 then len = 4 end
+ local l = lshift(1, len)-1
+ local s = band(imms, l)
+ local r = band(immr, l)
+ local imm = ror(rshift(-1, 31-s), r)
+ if len ~= 5 then imm = band(imm, lshift(1, l)-1) + rshift(imm, 31-l) end
+ imm = imm * imm13_rep[len]
+ local ix = fmt_hex32(imm)
+ if rshift(op, 31) ~= 0 then
+ return ix..tohex(imm)
+ else
+ return ix
+ end
+ else
+ local lo, hi = -1, 0
+ if imms < 32 then lo = rshift(-1, 31-imms) else hi = rshift(-1, 63-imms) end
+ if immr ~= 0 then
+ lo, hi = ror(lo, immr), ror(hi, immr)
+ local x = immr == 32 and 0 or band(bxor(lo, hi), lshift(-1, 32-immr))
+ lo, hi = bxor(lo, x), bxor(hi, x)
+ if immr >= 32 then lo, hi = hi, lo end
+ end
+ if hi ~= 0 then
+ return fmt_hex32(hi)..tohex(lo)
+ else
+ return fmt_hex32(lo)
+ end
+ end
+end
+
+local function parse_immpc(op, name)
+ if name == "b" or name == "bl" then
+ return arshift(lshift(op, 6), 4)
+ elseif name == "adr" or name == "adrp" then
+ local immlo = band(rshift(op, 29), 3)
+ local immhi = lshift(arshift(lshift(op, 8), 13), 2)
+ return bor(immhi, immlo)
+ elseif name == "tbz" or name == "tbnz" then
+ return lshift(arshift(lshift(op, 13), 18), 2)
+ else
+ return lshift(arshift(lshift(op, 8), 13), 2)
+ end
+end
+
+local function parse_fpimm8(op)
+ local sign = band(op, 0x100000) == 0 and 1 or -1
+ local exp = bxor(rshift(arshift(lshift(op, 12), 5), 24), 0x80) - 131
+ local frac = 16+band(rshift(op, 13), 15)
+ return sign * frac * 2^exp
+end
+
+local function prefer_bfx(sf, uns, imms, immr)
+ if imms < immr or imms == 31 or imms == 63 then
+ return false
+ end
+ if immr == 0 then
+ if sf == 0 and (imms == 7 or imms == 15) then
+ return false
+ end
+ if sf ~= 0 and uns == 0 and (imms == 7 or imms == 15 or imms == 31) then
+ return false
+ end
+ end
+ return true
+end
+
+-- Disassemble a single instruction.
+local function disass_ins(ctx)
+ local pos = ctx.pos
+ local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4)
+ local op = bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0)
+ local operands = {}
+ local suffix = ""
+ local last, name, pat
+ local map_reg
+ ctx.op = op
+ ctx.rel = nil
+ last = nil
+ local opat
+ opat = map_init[band(rshift(op, 25), 15)]
+ while type(opat) ~= "string" do
+ if not opat then return unknown(ctx) end
+ opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._
+ end
+ name, pat = match(opat, "^([a-z0-9]*)(.*)")
+ local altname, pat2 = match(pat, "|([a-z0-9_.|]*)(.*)")
+ if altname then pat = pat2 end
+ if sub(pat, 1, 1) == "." then
+ local s2, p2 = match(pat, "^([a-z0-9.]*)(.*)")
+ suffix = suffix..s2
+ pat = p2
+ end
+
+ local rt = match(pat, "[gf]")
+ if rt then
+ if rt == "g" then
+ map_reg = band(op, 0x80000000) ~= 0 and map_regs.x or map_regs.w
+ else
+ map_reg = band(op, 0x400000) ~= 0 and map_regs.d or map_regs.s
+ end
+ end
+
+ local second0, immr
+
+ for p in gmatch(pat, ".") do
+ local x = nil
+ if p == "D" then
+ local regnum = band(op, 31)
+ x = rt and map_reg[regnum] or match_reg(p, pat, regnum)
+ elseif p == "N" then
+ local regnum = band(rshift(op, 5), 31)
+ x = rt and map_reg[regnum] or match_reg(p, pat, regnum)
+ elseif p == "M" then
+ local regnum = band(rshift(op, 16), 31)
+ x = rt and map_reg[regnum] or match_reg(p, pat, regnum)
+ elseif p == "A" then
+ local regnum = band(rshift(op, 10), 31)
+ x = rt and map_reg[regnum] or match_reg(p, pat, regnum)
+ elseif p == "B" then
+ local addr = ctx.addr + pos + parse_immpc(op, name)
+ ctx.rel = addr
+ x = "0x"..tohex(addr)
+ elseif p == "T" then
+ x = bor(band(rshift(op, 26), 32), band(rshift(op, 19), 31))
+ elseif p == "V" then
+ x = band(op, 15)
+ elseif p == "C" then
+ x = map_cond[band(rshift(op, 12), 15)]
+ elseif p == "c" then
+ local rn = band(rshift(op, 5), 31)
+ local rm = band(rshift(op, 16), 31)
+ local cond = band(rshift(op, 12), 15)
+ local invc = bxor(cond, 1)
+ x = map_cond[cond]
+ if altname and cond ~= 14 and cond ~= 15 then
+ local a1, a2 = match(altname, "([^|]*)|(.*)")
+ if rn == rm then
+ local n = #operands
+ operands[n] = nil
+ x = map_cond[invc]
+ if rn ~= 31 then
+ if a1 then name = a1 else name = altname end
+ else
+ operands[n-1] = nil
+ name = a2
+ end
+ end
+ end
+ elseif p == "W" then
+ x = band(rshift(op, 5), 0xffff)
+ elseif p == "Y" then
+ x = band(rshift(op, 5), 0xffff)
+ local hw = band(rshift(op, 21), 3)
+ if altname and (hw == 0 or x ~= 0) then
+ name = altname
+ end
+ elseif p == "L" then
+ local rn = map_regs.x[band(rshift(op, 5), 31)]
+ local imm9 = arshift(lshift(op, 11), 23)
+ if band(op, 0x800) ~= 0 then
+ x = "["..rn..", #"..imm9.."]!"
+ else
+ x = "["..rn.."], #"..imm9
+ end
+ elseif p == "U" then
+ local rn = map_regs.x[band(rshift(op, 5), 31)]
+ local sz = band(rshift(op, 30), 3)
+ local imm12 = lshift(arshift(lshift(op, 10), 20), sz)
+ if imm12 ~= 0 then
+ x = "["..rn..", #"..imm12.."]"
+ else
+ x = "["..rn.."]"
+ end
+ elseif p == "K" then
+ local rn = map_regs.x[band(rshift(op, 5), 31)]
+ local imm9 = arshift(lshift(op, 11), 23)
+ if imm9 ~= 0 then
+ x = "["..rn..", #"..imm9.."]"
+ else
+ x = "["..rn.."]"
+ end
+ elseif p == "O" then
+ local rn, rm = map_regs.x[band(rshift(op, 5), 31)]
+ local m = band(rshift(op, 13), 1)
+ if m == 0 then
+ rm = map_regs.w[band(rshift(op, 16), 31)]
+ else
+ rm = map_regs.x[band(rshift(op, 16), 31)]
+ end
+ x = "["..rn..", "..rm
+ local opt = band(rshift(op, 13), 7)
+ local s = band(rshift(op, 12), 1)
+ local sz = band(rshift(op, 30), 3)
+ -- extension to be applied
+ if opt == 3 then
+ if s == 0 then x = x.."]"
+ else x = x..", lsl #"..sz.."]" end
+ elseif opt == 2 or opt == 6 or opt == 7 then
+ if s == 0 then x = x..", "..map_extend[opt].."]"
+ else x = x..", "..map_extend[opt].." #"..sz.."]" end
+ else
+ x = x.."]"
+ end
+ elseif p == "P" then
+ local opcv, sh = rshift(op, 26), 2
+ if opcv >= 0x2a then sh = 4 elseif opcv >= 0x1b then sh = 3 end
+ local imm7 = lshift(arshift(lshift(op, 10), 25), sh)
+ local rn = map_regs.x[band(rshift(op, 5), 31)]
+ local ind = band(rshift(op, 23), 3)
+ if ind == 1 then
+ x = "["..rn.."], #"..imm7
+ elseif ind == 2 then
+ if imm7 == 0 then
+ x = "["..rn.."]"
+ else
+ x = "["..rn..", #"..imm7.."]"
+ end
+ elseif ind == 3 then
+ x = "["..rn..", #"..imm7.."]!"
+ end
+ elseif p == "I" then
+ local shf = band(rshift(op, 22), 3)
+ local imm12 = band(rshift(op, 10), 0x0fff)
+ local rn, rd = band(rshift(op, 5), 31), band(op, 31)
+ if altname == "mov" and shf == 0 and imm12 == 0 and (rn == 31 or rd == 31) then
+ name = altname
+ x = nil
+ elseif shf == 0 then
+ x = imm12
+ elseif shf == 1 then
+ x = imm12..", lsl #12"
+ end
+ elseif p == "i" then
+ x = "#0x"..decode_imm13(op)
+ elseif p == "1" then
+ immr = band(rshift(op, 16), 63)
+ x = immr
+ elseif p == "2" then
+ x = band(rshift(op, 10), 63)
+ if altname then
+ local a1, a2, a3, a4, a5, a6 =
+ match(altname, "([^|]*)|([^|]*)|([^|]*)|([^|]*)|([^|]*)|(.*)")
+ local sf = band(rshift(op, 26), 32)
+ local uns = band(rshift(op, 30), 1)
+ if prefer_bfx(sf, uns, x, immr) then
+ name = a2
+ x = x - immr + 1
+ elseif immr == 0 and x == 7 then
+ local n = #operands
+ operands[n] = nil
+ if sf ~= 0 then
+ operands[n-1] = gsub(operands[n-1], "x", "w")
+ end
+ last = operands[n-1]
+ name = a6
+ x = nil
+ elseif immr == 0 and x == 15 then
+ local n = #operands
+ operands[n] = nil
+ if sf ~= 0 then
+ operands[n-1] = gsub(operands[n-1], "x", "w")
+ end
+ last = operands[n-1]
+ name = a5
+ x = nil
+ elseif x == 31 or x == 63 then
+ if x == 31 and immr == 0 and name == "sbfm" then
+ name = a4
+ local n = #operands
+ operands[n] = nil
+ if sf ~= 0 then
+ operands[n-1] = gsub(operands[n-1], "x", "w")
+ end
+ last = operands[n-1]
+ else
+ name = a3
+ end
+ x = nil
+ elseif band(x, 31) ~= 31 and immr == x+1 and name == "ubfm" then
+ name = a4
+ last = "#"..(sf+32 - immr)
+ operands[#operands] = last
+ x = nil
+ elseif x < immr then
+ name = a1
+ last = "#"..(sf+32 - immr)
+ operands[#operands] = last
+ x = x + 1
+ end
+ end
+ elseif p == "3" then
+ x = band(rshift(op, 10), 63)
+ if altname then
+ local a1, a2 = match(altname, "([^|]*)|(.*)")
+ if x < immr then
+ name = a1
+ local sf = band(rshift(op, 26), 32)
+ last = "#"..(sf+32 - immr)
+ operands[#operands] = last
+ x = x + 1
+ else
+ name = a2
+ x = x - immr + 1
+ end
+ end
+ elseif p == "4" then
+ x = band(rshift(op, 10), 63)
+ local rn = band(rshift(op, 5), 31)
+ local rm = band(rshift(op, 16), 31)
+ if altname and rn == rm then
+ local n = #operands
+ operands[n] = nil
+ last = operands[n-1]
+ name = altname
+ end
+ elseif p == "5" then
+ x = band(rshift(op, 16), 31)
+ elseif p == "S" then
+ x = band(rshift(op, 10), 63)
+ if x == 0 then x = nil
+ else x = map_shift[band(rshift(op, 22), 3)].." #"..x end
+ elseif p == "X" then
+ local opt = band(rshift(op, 13), 7)
+ -- Width specifier .
+ if opt ~= 3 and opt ~= 7 then
+ last = map_regs.w[band(rshift(op, 16), 31)]
+ operands[#operands] = last
+ end
+ x = band(rshift(op, 10), 7)
+ -- Extension.
+ if opt == 2 + band(rshift(op, 31), 1) and
+ band(rshift(op, second0 and 5 or 0), 31) == 31 then
+ if x == 0 then x = nil
+ else x = "lsl #"..x end
+ else
+ if x == 0 then x = map_extend[band(rshift(op, 13), 7)]
+ else x = map_extend[band(rshift(op, 13), 7)].." #"..x end
+ end
+ elseif p == "R" then
+ x = band(rshift(op,21), 3)
+ if x == 0 then x = nil
+ else x = "lsl #"..x*16 end
+ elseif p == "z" then
+ local n = #operands
+ if operands[n] == "sp" then operands[n] = "xzr"
+ elseif operands[n] == "wsp" then operands[n] = "wzr"
+ end
+ elseif p == "Z" then
+ x = 0
+ elseif p == "F" then
+ x = parse_fpimm8(op)
+ elseif p == "g" or p == "f" or p == "x" or p == "w" or
+ p == "d" or p == "s" then
+ -- These are handled in D/N/M/A.
+ elseif p == "0" then
+ if last == "sp" or last == "wsp" then
+ local n = #operands
+ operands[n] = nil
+ last = operands[n-1]
+ if altname then
+ local a1, a2 = match(altname, "([^|]*)|(.*)")
+ if not a1 then
+ name = altname
+ elseif second0 then
+ name, altname = a2, a1
+ else
+ name, altname = a1, a2
+ end
+ end
+ end
+ second0 = true
+ else
+ assert(false)
+ end
+ if x then
+ last = x
+ if type(x) == "number" then x = "#"..x end
+ operands[#operands+1] = x
+ end
+ end
+
+ return putop(ctx, name..suffix, operands)
+end
+
+------------------------------------------------------------------------------
+
+-- Disassemble a block of code.
+local function disass_block(ctx, ofs, len)
+ if not ofs then ofs = 0 end
+ local stop = len and ofs+len or #ctx.code
+ ctx.pos = ofs
+ ctx.rel = nil
+ while ctx.pos < stop do disass_ins(ctx) end
+end
+
+-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).
+local function create(code, addr, out)
+ local ctx = {}
+ ctx.code = code
+ ctx.addr = addr or 0
+ ctx.out = out or io.write
+ ctx.symtab = {}
+ ctx.disass = disass_block
+ ctx.hexdump = 8
+ return ctx
+end
+
+-- Simple API: disassemble code (a string) at address and output via out.
+local function disass(code, addr, out)
+ create(code, addr, out):disass()
+end
+
+-- Return register name for RID.
+local function regname(r)
+ if r < 32 then return map_regs.x[r] end
+ return map_regs.d[r-32]
+end
+
+-- Public module functions.
+return {
+ create = create,
+ disass = disass,
+ regname = regname
+}
+
diff --git a/jit/dis_arm64be.lua b/jit/dis_arm64be.lua
new file mode 100644
index 0000000..7337f5b
--- /dev/null
+++ b/jit/dis_arm64be.lua
@@ -0,0 +1,12 @@
+----------------------------------------------------------------------------
+-- LuaJIT ARM64BE disassembler wrapper module.
+--
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
+-- Released under the MIT license. See Copyright Notice in luajit.h
+----------------------------------------------------------------------------
+-- ARM64 instructions are always little-endian. So just forward to the
+-- common ARM64 disassembler module. All the interesting stuff is there.
+------------------------------------------------------------------------------
+
+return require((string.match(..., ".*%.") or "").."dis_arm64")
+
diff --git a/jit/dis_mips.lua b/jit/dis_mips.lua
new file mode 100644
index 0000000..05dc30f
--- /dev/null
+++ b/jit/dis_mips.lua
@@ -0,0 +1,694 @@
+----------------------------------------------------------------------------
+-- LuaJIT MIPS disassembler module.
+--
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
+-- Released under the MIT/X license. See Copyright Notice in luajit.h
+----------------------------------------------------------------------------
+-- This is a helper module used by the LuaJIT machine code dumper module.
+--
+-- It disassembles all standard MIPS32R1/R2 instructions.
+-- Default mode is big-endian, but see: dis_mipsel.lua
+------------------------------------------------------------------------------
+
+local type = type
+local byte, format = string.byte, string.format
+local match, gmatch = string.match, string.gmatch
+local concat = table.concat
+local bit = require("bit")
+local band, bor, tohex = bit.band, bit.bor, bit.tohex
+local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift
+
+------------------------------------------------------------------------------
+-- Extended opcode maps common to all MIPS releases
+------------------------------------------------------------------------------
+
+local map_srl = { shift = 21, mask = 1, [0] = "srlDTA", "rotrDTA", }
+local map_srlv = { shift = 6, mask = 1, [0] = "srlvDTS", "rotrvDTS", }
+
+local map_cop0 = {
+ shift = 25, mask = 1,
+ [0] = {
+ shift = 21, mask = 15,
+ [0] = "mfc0TDW", [4] = "mtc0TDW",
+ [10] = "rdpgprDT",
+ [11] = { shift = 5, mask = 1, [0] = "diT0", "eiT0", },
+ [14] = "wrpgprDT",
+ }, {
+ shift = 0, mask = 63,
+ [1] = "tlbr", [2] = "tlbwi", [6] = "tlbwr", [8] = "tlbp",
+ [24] = "eret", [31] = "deret",
+ [32] = "wait",
+ },
+}
+
+------------------------------------------------------------------------------
+-- Primary and extended opcode maps for MIPS R1-R5
+------------------------------------------------------------------------------
+
+local map_movci = { shift = 16, mask = 1, [0] = "movfDSC", "movtDSC", }
+
+local map_special = {
+ shift = 0, mask = 63,
+ [0] = { shift = 0, mask = -1, [0] = "nop", _ = "sllDTA" },
+ map_movci, map_srl, "sraDTA",
+ "sllvDTS", false, map_srlv, "sravDTS",
+ "jrS", "jalrD1S", "movzDST", "movnDST",
+ "syscallY", "breakY", false, "sync",
+ "mfhiD", "mthiS", "mfloD", "mtloS",
+ "dsllvDST", false, "dsrlvDST", "dsravDST",
+ "multST", "multuST", "divST", "divuST",
+ "dmultST", "dmultuST", "ddivST", "ddivuST",
+ "addDST", "addu|moveDST0", "subDST", "subu|neguDS0T",
+ "andDST", "or|moveDST0", "xorDST", "nor|notDST0",
+ false, false, "sltDST", "sltuDST",
+ "daddDST", "dadduDST", "dsubDST", "dsubuDST",
+ "tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ",
+ "teqSTZ", false, "tneSTZ", false,
+ "dsllDTA", false, "dsrlDTA", "dsraDTA",
+ "dsll32DTA", false, "dsrl32DTA", "dsra32DTA",
+}
+
+local map_special2 = {
+ shift = 0, mask = 63,
+ [0] = "maddST", "madduST", "mulDST", false,
+ "msubST", "msubuST",
+ [32] = "clzDS", [33] = "cloDS",
+ [63] = "sdbbpY",
+}
+
+local map_bshfl = {
+ shift = 6, mask = 31,
+ [2] = "wsbhDT",
+ [16] = "sebDT",
+ [24] = "sehDT",
+}
+
+local map_dbshfl = {
+ shift = 6, mask = 31,
+ [2] = "dsbhDT",
+ [5] = "dshdDT",
+}
+
+local map_special3 = {
+ shift = 0, mask = 63,
+ [0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK",
+ [4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL",
+ [32] = map_bshfl, [36] = map_dbshfl, [59] = "rdhwrTD",
+}
+
+local map_regimm = {
+ shift = 16, mask = 31,
+ [0] = "bltzSB", "bgezSB", "bltzlSB", "bgezlSB",
+ false, false, false, false,
+ "tgeiSI", "tgeiuSI", "tltiSI", "tltiuSI",
+ "teqiSI", false, "tneiSI", false,
+ "bltzalSB", "bgezalSB", "bltzallSB", "bgezallSB",
+ false, false, false, false,
+ false, false, false, false,
+ false, false, false, "synciSO",
+}
+
+local map_cop1s = {
+ shift = 0, mask = 63,
+ [0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH",
+ "sqrt.sFG", "abs.sFG", "mov.sFG", "neg.sFG",
+ "round.l.sFG", "trunc.l.sFG", "ceil.l.sFG", "floor.l.sFG",
+ "round.w.sFG", "trunc.w.sFG", "ceil.w.sFG", "floor.w.sFG",
+ false,
+ { shift = 16, mask = 1, [0] = "movf.sFGC", "movt.sFGC" },
+ "movz.sFGT", "movn.sFGT",
+ false, "recip.sFG", "rsqrt.sFG", false,
+ false, false, false, false,
+ false, false, false, false,
+ false, "cvt.d.sFG", false, false,
+ "cvt.w.sFG", "cvt.l.sFG", "cvt.ps.sFGH", false,
+ false, false, false, false,
+ false, false, false, false,
+ "c.f.sVGH", "c.un.sVGH", "c.eq.sVGH", "c.ueq.sVGH",
+ "c.olt.sVGH", "c.ult.sVGH", "c.ole.sVGH", "c.ule.sVGH",
+ "c.sf.sVGH", "c.ngle.sVGH", "c.seq.sVGH", "c.ngl.sVGH",
+ "c.lt.sVGH", "c.nge.sVGH", "c.le.sVGH", "c.ngt.sVGH",
+}
+
+local map_cop1d = {
+ shift = 0, mask = 63,
+ [0] = "add.dFGH", "sub.dFGH", "mul.dFGH", "div.dFGH",
+ "sqrt.dFG", "abs.dFG", "mov.dFG", "neg.dFG",
+ "round.l.dFG", "trunc.l.dFG", "ceil.l.dFG", "floor.l.dFG",
+ "round.w.dFG", "trunc.w.dFG", "ceil.w.dFG", "floor.w.dFG",
+ false,
+ { shift = 16, mask = 1, [0] = "movf.dFGC", "movt.dFGC" },
+ "movz.dFGT", "movn.dFGT",
+ false, "recip.dFG", "rsqrt.dFG", false,
+ false, false, false, false,
+ false, false, false, false,
+ "cvt.s.dFG", false, false, false,
+ "cvt.w.dFG", "cvt.l.dFG", false, false,
+ false, false, false, false,
+ false, false, false, false,
+ "c.f.dVGH", "c.un.dVGH", "c.eq.dVGH", "c.ueq.dVGH",
+ "c.olt.dVGH", "c.ult.dVGH", "c.ole.dVGH", "c.ule.dVGH",
+ "c.df.dVGH", "c.ngle.dVGH", "c.deq.dVGH", "c.ngl.dVGH",
+ "c.lt.dVGH", "c.nge.dVGH", "c.le.dVGH", "c.ngt.dVGH",
+}
+
+local map_cop1ps = {
+ shift = 0, mask = 63,
+ [0] = "add.psFGH", "sub.psFGH", "mul.psFGH", false,
+ false, "abs.psFG", "mov.psFG", "neg.psFG",
+ false, false, false, false,
+ false, false, false, false,
+ false,
+ { shift = 16, mask = 1, [0] = "movf.psFGC", "movt.psFGC" },
+ "movz.psFGT", "movn.psFGT",
+ false, false, false, false,
+ false, false, false, false,
+ false, false, false, false,
+ "cvt.s.puFG", false, false, false,
+ false, false, false, false,
+ "cvt.s.plFG", false, false, false,
+ "pll.psFGH", "plu.psFGH", "pul.psFGH", "puu.psFGH",
+ "c.f.psVGH", "c.un.psVGH", "c.eq.psVGH", "c.ueq.psVGH",
+ "c.olt.psVGH", "c.ult.psVGH", "c.ole.psVGH", "c.ule.psVGH",
+ "c.psf.psVGH", "c.ngle.psVGH", "c.pseq.psVGH", "c.ngl.psVGH",
+ "c.lt.psVGH", "c.nge.psVGH", "c.le.psVGH", "c.ngt.psVGH",
+}
+
+local map_cop1w = {
+ shift = 0, mask = 63,
+ [32] = "cvt.s.wFG", [33] = "cvt.d.wFG",
+}
+
+local map_cop1l = {
+ shift = 0, mask = 63,
+ [32] = "cvt.s.lFG", [33] = "cvt.d.lFG",
+}
+
+local map_cop1bc = {
+ shift = 16, mask = 3,
+ [0] = "bc1fCB", "bc1tCB", "bc1flCB", "bc1tlCB",
+}
+
+local map_cop1 = {
+ shift = 21, mask = 31,
+ [0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG",
+ "mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG",
+ map_cop1bc, false, false, false,
+ false, false, false, false,
+ map_cop1s, map_cop1d, false, false,
+ map_cop1w, map_cop1l, map_cop1ps,
+}
+
+local map_cop1x = {
+ shift = 0, mask = 63,
+ [0] = "lwxc1FSX", "ldxc1FSX", false, false,
+ false, "luxc1FSX", false, false,
+ "swxc1FSX", "sdxc1FSX", false, false,
+ false, "suxc1FSX", false, "prefxMSX",
+ false, false, false, false,
+ false, false, false, false,
+ false, false, false, false,
+ false, false, "alnv.psFGHS", false,
+ "madd.sFRGH", "madd.dFRGH", false, false,
+ false, false, "madd.psFRGH", false,
+ "msub.sFRGH", "msub.dFRGH", false, false,
+ false, false, "msub.psFRGH", false,
+ "nmadd.sFRGH", "nmadd.dFRGH", false, false,
+ false, false, "nmadd.psFRGH", false,
+ "nmsub.sFRGH", "nmsub.dFRGH", false, false,
+ false, false, "nmsub.psFRGH", false,
+}
+
+local map_pri = {
+ [0] = map_special, map_regimm, "jJ", "jalJ",
+ "beq|beqz|bST00B", "bne|bnezST0B", "blezSB", "bgtzSB",
+ "addiTSI", "addiu|liTS0I", "sltiTSI", "sltiuTSI",
+ "andiTSU", "ori|liTS0U", "xoriTSU", "luiTU",
+ map_cop0, map_cop1, false, map_cop1x,
+ "beql|beqzlST0B", "bnel|bnezlST0B", "blezlSB", "bgtzlSB",
+ "daddiTSI", "daddiuTSI", false, false,
+ map_special2, "jalxJ", false, map_special3,
+ "lbTSO", "lhTSO", "lwlTSO", "lwTSO",
+ "lbuTSO", "lhuTSO", "lwrTSO", false,
+ "sbTSO", "shTSO", "swlTSO", "swTSO",
+ false, false, "swrTSO", "cacheNSO",
+ "llTSO", "lwc1HSO", "lwc2TSO", "prefNSO",
+ false, "ldc1HSO", "ldc2TSO", "ldTSO",
+ "scTSO", "swc1HSO", "swc2TSO", false,
+ false, "sdc1HSO", "sdc2TSO", "sdTSO",
+}
+
+------------------------------------------------------------------------------
+-- Primary and extended opcode maps for MIPS R6
+------------------------------------------------------------------------------
+
+local map_mul_r6 = { shift = 6, mask = 3, [2] = "mulDST", [3] = "muhDST" }
+local map_mulu_r6 = { shift = 6, mask = 3, [2] = "muluDST", [3] = "muhuDST" }
+local map_div_r6 = { shift = 6, mask = 3, [2] = "divDST", [3] = "modDST" }
+local map_divu_r6 = { shift = 6, mask = 3, [2] = "divuDST", [3] = "moduDST" }
+local map_dmul_r6 = { shift = 6, mask = 3, [2] = "dmulDST", [3] = "dmuhDST" }
+local map_dmulu_r6 = { shift = 6, mask = 3, [2] = "dmuluDST", [3] = "dmuhuDST" }
+local map_ddiv_r6 = { shift = 6, mask = 3, [2] = "ddivDST", [3] = "dmodDST" }
+local map_ddivu_r6 = { shift = 6, mask = 3, [2] = "ddivuDST", [3] = "dmoduDST" }
+
+local map_special_r6 = {
+ shift = 0, mask = 63,
+ [0] = { shift = 0, mask = -1, [0] = "nop", _ = "sllDTA" },
+ false, map_srl, "sraDTA",
+ "sllvDTS", false, map_srlv, "sravDTS",
+ "jrS", "jalrD1S", false, false,
+ "syscallY", "breakY", false, "sync",
+ "clzDS", "cloDS", "dclzDS", "dcloDS",
+ "dsllvDST", "dlsaDSTA", "dsrlvDST", "dsravDST",
+ map_mul_r6, map_mulu_r6, map_div_r6, map_divu_r6,
+ map_dmul_r6, map_dmulu_r6, map_ddiv_r6, map_ddivu_r6,
+ "addDST", "addu|moveDST0", "subDST", "subu|neguDS0T",
+ "andDST", "or|moveDST0", "xorDST", "nor|notDST0",
+ false, false, "sltDST", "sltuDST",
+ "daddDST", "dadduDST", "dsubDST", "dsubuDST",
+ "tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ",
+ "teqSTZ", "seleqzDST", "tneSTZ", "selnezDST",
+ "dsllDTA", false, "dsrlDTA", "dsraDTA",
+ "dsll32DTA", false, "dsrl32DTA", "dsra32DTA",
+}
+
+local map_bshfl_r6 = {
+ shift = 9, mask = 3,
+ [1] = "alignDSTa",
+ _ = {
+ shift = 6, mask = 31,
+ [0] = "bitswapDT",
+ [2] = "wsbhDT",
+ [16] = "sebDT",
+ [24] = "sehDT",
+ }
+}
+
+local map_dbshfl_r6 = {
+ shift = 9, mask = 3,
+ [1] = "dalignDSTa",
+ _ = {
+ shift = 6, mask = 31,
+ [0] = "dbitswapDT",
+ [2] = "dsbhDT",
+ [5] = "dshdDT",
+ }
+}
+
+local map_special3_r6 = {
+ shift = 0, mask = 63,
+ [0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK",
+ [4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL",
+ [32] = map_bshfl_r6, [36] = map_dbshfl_r6, [59] = "rdhwrTD",
+}
+
+local map_regimm_r6 = {
+ shift = 16, mask = 31,
+ [0] = "bltzSB", [1] = "bgezSB",
+ [6] = "dahiSI", [30] = "datiSI",
+ [23] = "sigrieI", [31] = "synciSO",
+}
+
+local map_pcrel_r6 = {
+ shift = 19, mask = 3,
+ [0] = "addiupcS2", "lwpcS2", "lwupcS2", {
+ shift = 18, mask = 1,
+ [0] = "ldpcS3", { shift = 16, mask = 3, [2] = "auipcSI", [3] = "aluipcSI" }
+ }
+}
+
+local map_cop1s_r6 = {
+ shift = 0, mask = 63,
+ [0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH",
+ "sqrt.sFG", "abs.sFG", "mov.sFG", "neg.sFG",
+ "round.l.sFG", "trunc.l.sFG", "ceil.l.sFG", "floor.l.sFG",
+ "round.w.sFG", "trunc.w.sFG", "ceil.w.sFG", "floor.w.sFG",
+ "sel.sFGH", false, false, false,
+ "seleqz.sFGH", "recip.sFG", "rsqrt.sFG", "selnez.sFGH",
+ "maddf.sFGH", "msubf.sFGH", "rint.sFG", "class.sFG",
+ "min.sFGH", "mina.sFGH", "max.sFGH", "maxa.sFGH",
+ false, "cvt.d.sFG", false, false,
+ "cvt.w.sFG", "cvt.l.sFG",
+}
+
+local map_cop1d_r6 = {
+ shift = 0, mask = 63,
+ [0] = "add.dFGH", "sub.dFGH", "mul.dFGH", "div.dFGH",
+ "sqrt.dFG", "abs.dFG", "mov.dFG", "neg.dFG",
+ "round.l.dFG", "trunc.l.dFG", "ceil.l.dFG", "floor.l.dFG",
+ "round.w.dFG", "trunc.w.dFG", "ceil.w.dFG", "floor.w.dFG",
+ "sel.dFGH", false, false, false,
+ "seleqz.dFGH", "recip.dFG", "rsqrt.dFG", "selnez.dFGH",
+ "maddf.dFGH", "msubf.dFGH", "rint.dFG", "class.dFG",
+ "min.dFGH", "mina.dFGH", "max.dFGH", "maxa.dFGH",
+ "cvt.s.dFG", false, false, false,
+ "cvt.w.dFG", "cvt.l.dFG",
+}
+
+local map_cop1w_r6 = {
+ shift = 0, mask = 63,
+ [0] = "cmp.af.sFGH", "cmp.un.sFGH", "cmp.eq.sFGH", "cmp.ueq.sFGH",
+ "cmp.lt.sFGH", "cmp.ult.sFGH", "cmp.le.sFGH", "cmp.ule.sFGH",
+ "cmp.saf.sFGH", "cmp.sun.sFGH", "cmp.seq.sFGH", "cmp.sueq.sFGH",
+ "cmp.slt.sFGH", "cmp.sult.sFGH", "cmp.sle.sFGH", "cmp.sule.sFGH",
+ false, "cmp.or.sFGH", "cmp.une.sFGH", "cmp.ne.sFGH",
+ false, false, false, false,
+ false, "cmp.sor.sFGH", "cmp.sune.sFGH", "cmp.sne.sFGH",
+ false, false, false, false,
+ "cvt.s.wFG", "cvt.d.wFG",
+}
+
+local map_cop1l_r6 = {
+ shift = 0, mask = 63,
+ [0] = "cmp.af.dFGH", "cmp.un.dFGH", "cmp.eq.dFGH", "cmp.ueq.dFGH",
+ "cmp.lt.dFGH", "cmp.ult.dFGH", "cmp.le.dFGH", "cmp.ule.dFGH",
+ "cmp.saf.dFGH", "cmp.sun.dFGH", "cmp.seq.dFGH", "cmp.sueq.dFGH",
+ "cmp.slt.dFGH", "cmp.sult.dFGH", "cmp.sle.dFGH", "cmp.sule.dFGH",
+ false, "cmp.or.dFGH", "cmp.une.dFGH", "cmp.ne.dFGH",
+ false, false, false, false,
+ false, "cmp.sor.dFGH", "cmp.sune.dFGH", "cmp.sne.dFGH",
+ false, false, false, false,
+ "cvt.s.lFG", "cvt.d.lFG",
+}
+
+local map_cop1_r6 = {
+ shift = 21, mask = 31,
+ [0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG",
+ "mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG",
+ false, "bc1eqzHB", false, false,
+ false, "bc1nezHB", false, false,
+ map_cop1s_r6, map_cop1d_r6, false, false,
+ map_cop1w_r6, map_cop1l_r6,
+}
+
+local function maprs_popTS(rs, rt)
+ if rt == 0 then return 0 elseif rs == 0 then return 1
+ elseif rs == rt then return 2 else return 3 end
+end
+
+local map_pop06_r6 = {
+ maprs = maprs_popTS, [0] = "blezSB", "blezalcTB", "bgezalcTB", "bgeucSTB"
+}
+local map_pop07_r6 = {
+ maprs = maprs_popTS, [0] = "bgtzSB", "bgtzalcTB", "bltzalcTB", "bltucSTB"
+}
+local map_pop26_r6 = {
+ maprs = maprs_popTS, "blezcTB", "bgezcTB", "bgecSTB"
+}
+local map_pop27_r6 = {
+ maprs = maprs_popTS, "bgtzcTB", "bltzcTB", "bltcSTB"
+}
+
+local function maprs_popS(rs, rt)
+ if rs == 0 then return 0 else return 1 end
+end
+
+local map_pop66_r6 = {
+ maprs = maprs_popS, [0] = "jicTI", "beqzcSb"
+}
+local map_pop76_r6 = {
+ maprs = maprs_popS, [0] = "jialcTI", "bnezcSb"
+}
+
+local function maprs_popST(rs, rt)
+ if rs >= rt then return 0 elseif rs == 0 then return 1 else return 2 end
+end
+
+local map_pop10_r6 = {
+ maprs = maprs_popST, [0] = "bovcSTB", "beqzalcTB", "beqcSTB"
+}
+local map_pop30_r6 = {
+ maprs = maprs_popST, [0] = "bnvcSTB", "bnezalcTB", "bnecSTB"
+}
+
+local map_pri_r6 = {
+ [0] = map_special_r6, map_regimm_r6, "jJ", "jalJ",
+ "beq|beqz|bST00B", "bne|bnezST0B", map_pop06_r6, map_pop07_r6,
+ map_pop10_r6, "addiu|liTS0I", "sltiTSI", "sltiuTSI",
+ "andiTSU", "ori|liTS0U", "xoriTSU", "aui|luiTS0U",
+ map_cop0, map_cop1_r6, false, false,
+ false, false, map_pop26_r6, map_pop27_r6,
+ map_pop30_r6, "daddiuTSI", false, false,
+ false, "dauiTSI", false, map_special3_r6,
+ "lbTSO", "lhTSO", false, "lwTSO",
+ "lbuTSO", "lhuTSO", false, false,
+ "sbTSO", "shTSO", false, "swTSO",
+ false, false, false, false,
+ false, "lwc1HSO", "bc#", false,
+ false, "ldc1HSO", map_pop66_r6, "ldTSO",
+ false, "swc1HSO", "balc#", map_pcrel_r6,
+ false, "sdc1HSO", map_pop76_r6, "sdTSO",
+}
+
+------------------------------------------------------------------------------
+
+local map_gpr = {
+ [0] = "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "sp", "r30", "ra",
+}
+
+------------------------------------------------------------------------------
+
+-- Output a nicely formatted line with an opcode and operands.
+local function putop(ctx, text, operands)
+ local pos = ctx.pos
+ local extra = ""
+ if ctx.rel then
+ local sym = ctx.symtab[ctx.rel]
+ if sym then extra = "\t->"..sym end
+ end
+ if ctx.hexdump > 0 then
+ ctx.out(format("%08x %s %-7s %s%s\n",
+ ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra))
+ else
+ ctx.out(format("%08x %-7s %s%s\n",
+ ctx.addr+pos, text, concat(operands, ", "), extra))
+ end
+ ctx.pos = pos + 4
+end
+
+-- Fallback for unknown opcodes.
+local function unknown(ctx)
+ return putop(ctx, ".long", { "0x"..tohex(ctx.op) })
+end
+
+local function get_be(ctx)
+ local pos = ctx.pos
+ local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4)
+ return bor(lshift(b0, 24), lshift(b1, 16), lshift(b2, 8), b3)
+end
+
+local function get_le(ctx)
+ local pos = ctx.pos
+ local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4)
+ return bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0)
+end
+
+-- Disassemble a single instruction.
+local function disass_ins(ctx)
+ local op = ctx:get()
+ local operands = {}
+ local last = nil
+ ctx.op = op
+ ctx.rel = nil
+
+ local opat = ctx.map_pri[rshift(op, 26)]
+ while type(opat) ~= "string" do
+ if not opat then return unknown(ctx) end
+ if opat.maprs then
+ opat = opat[opat.maprs(band(rshift(op,21),31), band(rshift(op,16),31))]
+ else
+ opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._
+ end
+ end
+ local name, pat = match(opat, "^([a-z0-9_.]*)(.*)")
+ local altname, pat2 = match(pat, "|([a-z0-9_.|]*)(.*)")
+ if altname then pat = pat2 end
+
+ for p in gmatch(pat, ".") do
+ local x = nil
+ if p == "S" then
+ x = map_gpr[band(rshift(op, 21), 31)]
+ elseif p == "T" then
+ x = map_gpr[band(rshift(op, 16), 31)]
+ elseif p == "D" then
+ x = map_gpr[band(rshift(op, 11), 31)]
+ elseif p == "F" then
+ x = "f"..band(rshift(op, 6), 31)
+ elseif p == "G" then
+ x = "f"..band(rshift(op, 11), 31)
+ elseif p == "H" then
+ x = "f"..band(rshift(op, 16), 31)
+ elseif p == "R" then
+ x = "f"..band(rshift(op, 21), 31)
+ elseif p == "A" then
+ x = band(rshift(op, 6), 31)
+ elseif p == "a" then
+ x = band(rshift(op, 6), 7)
+ elseif p == "E" then
+ x = band(rshift(op, 6), 31) + 32
+ elseif p == "M" then
+ x = band(rshift(op, 11), 31)
+ elseif p == "N" then
+ x = band(rshift(op, 16), 31)
+ elseif p == "C" then
+ x = band(rshift(op, 18), 7)
+ if x == 0 then x = nil end
+ elseif p == "K" then
+ x = band(rshift(op, 11), 31) + 1
+ elseif p == "P" then
+ x = band(rshift(op, 11), 31) + 33
+ elseif p == "L" then
+ x = band(rshift(op, 11), 31) - last + 1
+ elseif p == "Q" then
+ x = band(rshift(op, 11), 31) - last + 33
+ elseif p == "I" then
+ x = arshift(lshift(op, 16), 16)
+ elseif p == "2" then
+ x = arshift(lshift(op, 13), 11)
+ elseif p == "3" then
+ x = arshift(lshift(op, 14), 11)
+ elseif p == "U" then
+ x = band(op, 0xffff)
+ elseif p == "O" then
+ local disp = arshift(lshift(op, 16), 16)
+ operands[#operands] = format("%d(%s)", disp, last)
+ elseif p == "X" then
+ local index = map_gpr[band(rshift(op, 16), 31)]
+ operands[#operands] = format("%s(%s)", index, last)
+ elseif p == "B" then
+ x = ctx.addr + ctx.pos + arshift(lshift(op, 16), 14) + 4
+ ctx.rel = x
+ x = format("0x%08x", x)
+ elseif p == "b" then
+ x = ctx.addr + ctx.pos + arshift(lshift(op, 11), 9) + 4
+ ctx.rel = x
+ x = format("0x%08x", x)
+ elseif p == "#" then
+ x = ctx.addr + ctx.pos + arshift(lshift(op, 6), 4) + 4
+ ctx.rel = x
+ x = format("0x%08x", x)
+ elseif p == "J" then
+ local a = ctx.addr + ctx.pos
+ x = a - band(a, 0x0fffffff) + band(op, 0x03ffffff)*4
+ ctx.rel = x
+ x = format("0x%08x", x)
+ elseif p == "V" then
+ x = band(rshift(op, 8), 7)
+ if x == 0 then x = nil end
+ elseif p == "W" then
+ x = band(op, 7)
+ if x == 0 then x = nil end
+ elseif p == "Y" then
+ x = band(rshift(op, 6), 0x000fffff)
+ if x == 0 then x = nil end
+ elseif p == "Z" then
+ x = band(rshift(op, 6), 1023)
+ if x == 0 then x = nil end
+ elseif p == "0" then
+ if last == "r0" or last == 0 then
+ local n = #operands
+ operands[n] = nil
+ last = operands[n-1]
+ if altname then
+ local a1, a2 = match(altname, "([^|]*)|(.*)")
+ if a1 then name, altname = a1, a2
+ else name = altname end
+ end
+ end
+ elseif p == "1" then
+ if last == "ra" then
+ operands[#operands] = nil
+ end
+ else
+ assert(false)
+ end
+ if x then operands[#operands+1] = x; last = x end
+ end
+
+ return putop(ctx, name, operands)
+end
+
+------------------------------------------------------------------------------
+
+-- Disassemble a block of code.
+local function disass_block(ctx, ofs, len)
+ if not ofs then ofs = 0 end
+ local stop = len and ofs+len or #ctx.code
+ stop = stop - stop % 4
+ ctx.pos = ofs - ofs % 4
+ ctx.rel = nil
+ while ctx.pos < stop do disass_ins(ctx) end
+end
+
+-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).
+local function create(code, addr, out)
+ local ctx = {}
+ ctx.code = code
+ ctx.addr = addr or 0
+ ctx.out = out or io.write
+ ctx.symtab = {}
+ ctx.disass = disass_block
+ ctx.hexdump = 8
+ ctx.get = get_be
+ ctx.map_pri = map_pri
+ return ctx
+end
+
+local function create_el(code, addr, out)
+ local ctx = create(code, addr, out)
+ ctx.get = get_le
+ return ctx
+end
+
+local function create_r6(code, addr, out)
+ local ctx = create(code, addr, out)
+ ctx.map_pri = map_pri_r6
+ return ctx
+end
+
+local function create_r6_el(code, addr, out)
+ local ctx = create(code, addr, out)
+ ctx.get = get_le
+ ctx.map_pri = map_pri_r6
+ return ctx
+end
+
+-- Simple API: disassemble code (a string) at address and output via out.
+local function disass(code, addr, out)
+ create(code, addr, out):disass()
+end
+
+local function disass_el(code, addr, out)
+ create_el(code, addr, out):disass()
+end
+
+local function disass_r6(code, addr, out)
+ create_r6(code, addr, out):disass()
+end
+
+local function disass_r6_el(code, addr, out)
+ create_r6_el(code, addr, out):disass()
+end
+
+-- Return register name for RID.
+local function regname(r)
+ if r < 32 then return map_gpr[r] end
+ return "f"..(r-32)
+end
+
+-- Public module functions.
+return {
+ create = create,
+ create_el = create_el,
+ create_r6 = create_r6,
+ create_r6_el = create_r6_el,
+ disass = disass,
+ disass_el = disass_el,
+ disass_r6 = disass_r6,
+ disass_r6_el = disass_r6_el,
+ regname = regname
+}
+
diff --git a/jit/dis_mips64.lua b/jit/dis_mips64.lua
new file mode 100644
index 0000000..1236e52
--- /dev/null
+++ b/jit/dis_mips64.lua
@@ -0,0 +1,17 @@
+----------------------------------------------------------------------------
+-- LuaJIT MIPS64 disassembler wrapper module.
+--
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
+-- Released under the MIT license. See Copyright Notice in luajit.h
+----------------------------------------------------------------------------
+-- This module just exports the big-endian functions from the
+-- MIPS disassembler module. All the interesting stuff is there.
+------------------------------------------------------------------------------
+
+local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips")
+return {
+ create = dis_mips.create,
+ disass = dis_mips.disass,
+ regname = dis_mips.regname
+}
+
diff --git a/jit/dis_mips64el.lua b/jit/dis_mips64el.lua
new file mode 100644
index 0000000..7c478d2
--- /dev/null
+++ b/jit/dis_mips64el.lua
@@ -0,0 +1,17 @@
+----------------------------------------------------------------------------
+-- LuaJIT MIPS64EL disassembler wrapper module.
+--
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
+-- Released under the MIT license. See Copyright Notice in luajit.h
+----------------------------------------------------------------------------
+-- This module just exports the little-endian functions from the
+-- MIPS disassembler module. All the interesting stuff is there.
+------------------------------------------------------------------------------
+
+local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips")
+return {
+ create = dis_mips.create_el,
+ disass = dis_mips.disass_el,
+ regname = dis_mips.regname
+}
+
diff --git a/jit/dis_mips64r6.lua b/jit/dis_mips64r6.lua
new file mode 100644
index 0000000..c5789ce
--- /dev/null
+++ b/jit/dis_mips64r6.lua
@@ -0,0 +1,17 @@
+----------------------------------------------------------------------------
+-- LuaJIT MIPS64R6 disassembler wrapper module.
+--
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
+-- Released under the MIT license. See Copyright Notice in luajit.h
+----------------------------------------------------------------------------
+-- This module just exports the r6 big-endian functions from the
+-- MIPS disassembler module. All the interesting stuff is there.
+------------------------------------------------------------------------------
+
+local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips")
+return {
+ create = dis_mips.create_r6,
+ disass = dis_mips.disass_r6,
+ regname = dis_mips.regname
+}
+
diff --git a/jit/dis_mips64r6el.lua b/jit/dis_mips64r6el.lua
new file mode 100644
index 0000000..f67f624
--- /dev/null
+++ b/jit/dis_mips64r6el.lua
@@ -0,0 +1,17 @@
+----------------------------------------------------------------------------
+-- LuaJIT MIPS64R6EL disassembler wrapper module.
+--
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
+-- Released under the MIT license. See Copyright Notice in luajit.h
+----------------------------------------------------------------------------
+-- This module just exports the r6 little-endian functions from the
+-- MIPS disassembler module. All the interesting stuff is there.
+------------------------------------------------------------------------------
+
+local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips")
+return {
+ create = dis_mips.create_r6_el,
+ disass = dis_mips.disass_r6_el,
+ regname = dis_mips.regname
+}
+
diff --git a/jit/dis_mipsel.lua b/jit/dis_mipsel.lua
new file mode 100644
index 0000000..a4fa6c6
--- /dev/null
+++ b/jit/dis_mipsel.lua
@@ -0,0 +1,17 @@
+----------------------------------------------------------------------------
+-- LuaJIT MIPSEL disassembler wrapper module.
+--
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
+-- Released under the MIT license. See Copyright Notice in luajit.h
+----------------------------------------------------------------------------
+-- This module just exports the little-endian functions from the
+-- MIPS disassembler module. All the interesting stuff is there.
+------------------------------------------------------------------------------
+
+local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips")
+return {
+ create = dis_mips.create_el,
+ disass = dis_mips.disass_el,
+ regname = dis_mips.regname
+}
+
diff --git a/jit/dis_ppc.lua b/jit/dis_ppc.lua
new file mode 100644
index 0000000..8f65f25
--- /dev/null
+++ b/jit/dis_ppc.lua
@@ -0,0 +1,591 @@
+----------------------------------------------------------------------------
+-- LuaJIT PPC disassembler module.
+--
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
+-- Released under the MIT/X license. See Copyright Notice in luajit.h
+----------------------------------------------------------------------------
+-- This is a helper module used by the LuaJIT machine code dumper module.
+--
+-- It disassembles all common, non-privileged 32/64 bit PowerPC instructions
+-- plus the e500 SPE instructions and some Cell/Xenon extensions.
+--
+-- NYI: VMX, VMX128
+------------------------------------------------------------------------------
+
+local type = type
+local byte, format = string.byte, string.format
+local match, gmatch, gsub = string.match, string.gmatch, string.gsub
+local concat = table.concat
+local bit = require("bit")
+local band, bor, tohex = bit.band, bit.bor, bit.tohex
+local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift
+
+------------------------------------------------------------------------------
+-- Primary and extended opcode maps
+------------------------------------------------------------------------------
+
+local map_crops = {
+ shift = 1, mask = 1023,
+ [0] = "mcrfXX",
+ [33] = "crnor|crnotCCC=", [129] = "crandcCCC",
+ [193] = "crxor|crclrCCC%", [225] = "crnandCCC",
+ [257] = "crandCCC", [289] = "creqv|crsetCCC%",
+ [417] = "crorcCCC", [449] = "cror|crmoveCCC=",
+ [16] = "b_lrKB", [528] = "b_ctrKB",
+ [150] = "isync",
+}
+
+local map_rlwinm = setmetatable({
+ shift = 0, mask = -1,
+},
+{ __index = function(t, x)
+ local rot = band(rshift(x, 11), 31)
+ local mb = band(rshift(x, 6), 31)
+ local me = band(rshift(x, 1), 31)
+ if mb == 0 and me == 31-rot then
+ return "slwiRR~A."
+ elseif me == 31 and mb == 32-rot then
+ return "srwiRR~-A."
+ else
+ return "rlwinmRR~AAA."
+ end
+ end
+})
+
+local map_rld = {
+ shift = 2, mask = 7,
+ [0] = "rldiclRR~HM.", "rldicrRR~HM.", "rldicRR~HM.", "rldimiRR~HM.",
+ {
+ shift = 1, mask = 1,
+ [0] = "rldclRR~RM.", "rldcrRR~RM.",
+ },
+}
+
+local map_ext = setmetatable({
+ shift = 1, mask = 1023,
+
+ [0] = "cmp_YLRR", [32] = "cmpl_YLRR",
+ [4] = "twARR", [68] = "tdARR",
+
+ [8] = "subfcRRR.", [40] = "subfRRR.",
+ [104] = "negRR.", [136] = "subfeRRR.",
+ [200] = "subfzeRR.", [232] = "subfmeRR.",
+ [520] = "subfcoRRR.", [552] = "subfoRRR.",
+ [616] = "negoRR.", [648] = "subfeoRRR.",
+ [712] = "subfzeoRR.", [744] = "subfmeoRR.",
+
+ [9] = "mulhduRRR.", [73] = "mulhdRRR.", [233] = "mulldRRR.",
+ [457] = "divduRRR.", [489] = "divdRRR.",
+ [745] = "mulldoRRR.",
+ [969] = "divduoRRR.", [1001] = "divdoRRR.",
+
+ [10] = "addcRRR.", [138] = "addeRRR.",
+ [202] = "addzeRR.", [234] = "addmeRR.", [266] = "addRRR.",
+ [522] = "addcoRRR.", [650] = "addeoRRR.",
+ [714] = "addzeoRR.", [746] = "addmeoRR.", [778] = "addoRRR.",
+
+ [11] = "mulhwuRRR.", [75] = "mulhwRRR.", [235] = "mullwRRR.",
+ [459] = "divwuRRR.", [491] = "divwRRR.",
+ [747] = "mullwoRRR.",
+ [971] = "divwouRRR.", [1003] = "divwoRRR.",
+
+ [15] = "iselltRRR", [47] = "iselgtRRR", [79] = "iseleqRRR",
+
+ [144] = { shift = 20, mask = 1, [0] = "mtcrfRZ~", "mtocrfRZ~", },
+ [19] = { shift = 20, mask = 1, [0] = "mfcrR", "mfocrfRZ", },
+ [371] = { shift = 11, mask = 1023, [392] = "mftbR", [424] = "mftbuR", },
+ [339] = {
+ shift = 11, mask = 1023,
+ [32] = "mferR", [256] = "mflrR", [288] = "mfctrR", [16] = "mfspefscrR",
+ },
+ [467] = {
+ shift = 11, mask = 1023,
+ [32] = "mtxerR", [256] = "mtlrR", [288] = "mtctrR", [16] = "mtspefscrR",
+ },
+
+ [20] = "lwarxRR0R", [84] = "ldarxRR0R",
+
+ [21] = "ldxRR0R", [53] = "lduxRRR",
+ [149] = "stdxRR0R", [181] = "stduxRRR",
+ [341] = "lwaxRR0R", [373] = "lwauxRRR",
+
+ [23] = "lwzxRR0R", [55] = "lwzuxRRR",
+ [87] = "lbzxRR0R", [119] = "lbzuxRRR",
+ [151] = "stwxRR0R", [183] = "stwuxRRR",
+ [215] = "stbxRR0R", [247] = "stbuxRRR",
+ [279] = "lhzxRR0R", [311] = "lhzuxRRR",
+ [343] = "lhaxRR0R", [375] = "lhauxRRR",
+ [407] = "sthxRR0R", [439] = "sthuxRRR",
+
+ [54] = "dcbst-R0R", [86] = "dcbf-R0R",
+ [150] = "stwcxRR0R.", [214] = "stdcxRR0R.",
+ [246] = "dcbtst-R0R", [278] = "dcbt-R0R",
+ [310] = "eciwxRR0R", [438] = "ecowxRR0R",
+ [470] = "dcbi-RR",
+
+ [598] = {
+ shift = 21, mask = 3,
+ [0] = "sync", "lwsync", "ptesync",
+ },
+ [758] = "dcba-RR",
+ [854] = "eieio", [982] = "icbi-R0R", [1014] = "dcbz-R0R",
+
+ [26] = "cntlzwRR~", [58] = "cntlzdRR~",
+ [122] = "popcntbRR~",
+ [154] = "prtywRR~", [186] = "prtydRR~",
+
+ [28] = "andRR~R.", [60] = "andcRR~R.", [124] = "nor|notRR~R=.",
+ [284] = "eqvRR~R.", [316] = "xorRR~R.",
+ [412] = "orcRR~R.", [444] = "or|mrRR~R=.", [476] = "nandRR~R.",
+ [508] = "cmpbRR~R",
+
+ [512] = "mcrxrX",
+
+ [532] = "ldbrxRR0R", [660] = "stdbrxRR0R",
+
+ [533] = "lswxRR0R", [597] = "lswiRR0A",
+ [661] = "stswxRR0R", [725] = "stswiRR0A",
+
+ [534] = "lwbrxRR0R", [662] = "stwbrxRR0R",
+ [790] = "lhbrxRR0R", [918] = "sthbrxRR0R",
+
+ [535] = "lfsxFR0R", [567] = "lfsuxFRR",
+ [599] = "lfdxFR0R", [631] = "lfduxFRR",
+ [663] = "stfsxFR0R", [695] = "stfsuxFRR",
+ [727] = "stfdxFR0R", [759] = "stfduxFR0R",
+ [855] = "lfiwaxFR0R",
+ [983] = "stfiwxFR0R",
+
+ [24] = "slwRR~R.",
+
+ [27] = "sldRR~R.", [536] = "srwRR~R.",
+ [792] = "srawRR~R.", [824] = "srawiRR~A.",
+
+ [794] = "sradRR~R.", [826] = "sradiRR~H.", [827] = "sradiRR~H.",
+ [922] = "extshRR~.", [954] = "extsbRR~.", [986] = "extswRR~.",
+
+ [539] = "srdRR~R.",
+},
+{ __index = function(t, x)
+ if band(x, 31) == 15 then return "iselRRRC" end
+ end
+})
+
+local map_ld = {
+ shift = 0, mask = 3,
+ [0] = "ldRRE", "lduRRE", "lwaRRE",
+}
+
+local map_std = {
+ shift = 0, mask = 3,
+ [0] = "stdRRE", "stduRRE",
+}
+
+local map_fps = {
+ shift = 5, mask = 1,
+ {
+ shift = 1, mask = 15,
+ [0] = false, false, "fdivsFFF.", false,
+ "fsubsFFF.", "faddsFFF.", "fsqrtsF-F.", false,
+ "fresF-F.", "fmulsFF-F.", "frsqrtesF-F.", false,
+ "fmsubsFFFF~.", "fmaddsFFFF~.", "fnmsubsFFFF~.", "fnmaddsFFFF~.",
+ }
+}
+
+local map_fpd = {
+ shift = 5, mask = 1,
+ [0] = {
+ shift = 1, mask = 1023,
+ [0] = "fcmpuXFF", [32] = "fcmpoXFF", [64] = "mcrfsXX",
+ [38] = "mtfsb1A.", [70] = "mtfsb0A.", [134] = "mtfsfiA>>-A>",
+ [8] = "fcpsgnFFF.", [40] = "fnegF-F.", [72] = "fmrF-F.",
+ [136] = "fnabsF-F.", [264] = "fabsF-F.",
+ [12] = "frspF-F.",
+ [14] = "fctiwF-F.", [15] = "fctiwzF-F.",
+ [583] = "mffsF.", [711] = "mtfsfZF.",
+ [392] = "frinF-F.", [424] = "frizF-F.",
+ [456] = "fripF-F.", [488] = "frimF-F.",
+ [814] = "fctidF-F.", [815] = "fctidzF-F.", [846] = "fcfidF-F.",
+ },
+ {
+ shift = 1, mask = 15,
+ [0] = false, false, "fdivFFF.", false,
+ "fsubFFF.", "faddFFF.", "fsqrtF-F.", "fselFFFF~.",
+ "freF-F.", "fmulFF-F.", "frsqrteF-F.", false,
+ "fmsubFFFF~.", "fmaddFFFF~.", "fnmsubFFFF~.", "fnmaddFFFF~.",
+ }
+}
+
+local map_spe = {
+ shift = 0, mask = 2047,
+
+ [512] = "evaddwRRR", [514] = "evaddiwRAR~",
+ [516] = "evsubwRRR~", [518] = "evsubiwRAR~",
+ [520] = "evabsRR", [521] = "evnegRR",
+ [522] = "evextsbRR", [523] = "evextshRR", [524] = "evrndwRR",
+ [525] = "evcntlzwRR", [526] = "evcntlswRR",
+
+ [527] = "brincRRR",
+
+ [529] = "evandRRR", [530] = "evandcRRR", [534] = "evxorRRR",
+ [535] = "evor|evmrRRR=", [536] = "evnor|evnotRRR=",
+ [537] = "eveqvRRR", [539] = "evorcRRR", [542] = "evnandRRR",
+
+ [544] = "evsrwuRRR", [545] = "evsrwsRRR",
+ [546] = "evsrwiuRRA", [547] = "evsrwisRRA",
+ [548] = "evslwRRR", [550] = "evslwiRRA",
+ [552] = "evrlwRRR", [553] = "evsplatiRS",
+ [554] = "evrlwiRRA", [555] = "evsplatfiRS",
+ [556] = "evmergehiRRR", [557] = "evmergeloRRR",
+ [558] = "evmergehiloRRR", [559] = "evmergelohiRRR",
+
+ [560] = "evcmpgtuYRR", [561] = "evcmpgtsYRR",
+ [562] = "evcmpltuYRR", [563] = "evcmpltsYRR",
+ [564] = "evcmpeqYRR",
+
+ [632] = "evselRRR", [633] = "evselRRRW",
+ [634] = "evselRRRW", [635] = "evselRRRW",
+ [636] = "evselRRRW", [637] = "evselRRRW",
+ [638] = "evselRRRW", [639] = "evselRRRW",
+
+ [640] = "evfsaddRRR", [641] = "evfssubRRR",
+ [644] = "evfsabsRR", [645] = "evfsnabsRR", [646] = "evfsnegRR",
+ [648] = "evfsmulRRR", [649] = "evfsdivRRR",
+ [652] = "evfscmpgtYRR", [653] = "evfscmpltYRR", [654] = "evfscmpeqYRR",
+ [656] = "evfscfuiR-R", [657] = "evfscfsiR-R",
+ [658] = "evfscfufR-R", [659] = "evfscfsfR-R",
+ [660] = "evfsctuiR-R", [661] = "evfsctsiR-R",
+ [662] = "evfsctufR-R", [663] = "evfsctsfR-R",
+ [664] = "evfsctuizR-R", [666] = "evfsctsizR-R",
+ [668] = "evfststgtYRR", [669] = "evfststltYRR", [670] = "evfststeqYRR",
+
+ [704] = "efsaddRRR", [705] = "efssubRRR",
+ [708] = "efsabsRR", [709] = "efsnabsRR", [710] = "efsnegRR",
+ [712] = "efsmulRRR", [713] = "efsdivRRR",
+ [716] = "efscmpgtYRR", [717] = "efscmpltYRR", [718] = "efscmpeqYRR",
+ [719] = "efscfdR-R",
+ [720] = "efscfuiR-R", [721] = "efscfsiR-R",
+ [722] = "efscfufR-R", [723] = "efscfsfR-R",
+ [724] = "efsctuiR-R", [725] = "efsctsiR-R",
+ [726] = "efsctufR-R", [727] = "efsctsfR-R",
+ [728] = "efsctuizR-R", [730] = "efsctsizR-R",
+ [732] = "efststgtYRR", [733] = "efststltYRR", [734] = "efststeqYRR",
+
+ [736] = "efdaddRRR", [737] = "efdsubRRR",
+ [738] = "efdcfuidR-R", [739] = "efdcfsidR-R",
+ [740] = "efdabsRR", [741] = "efdnabsRR", [742] = "efdnegRR",
+ [744] = "efdmulRRR", [745] = "efddivRRR",
+ [746] = "efdctuidzR-R", [747] = "efdctsidzR-R",
+ [748] = "efdcmpgtYRR", [749] = "efdcmpltYRR", [750] = "efdcmpeqYRR",
+ [751] = "efdcfsR-R",
+ [752] = "efdcfuiR-R", [753] = "efdcfsiR-R",
+ [754] = "efdcfufR-R", [755] = "efdcfsfR-R",
+ [756] = "efdctuiR-R", [757] = "efdctsiR-R",
+ [758] = "efdctufR-R", [759] = "efdctsfR-R",
+ [760] = "efdctuizR-R", [762] = "efdctsizR-R",
+ [764] = "efdtstgtYRR", [765] = "efdtstltYRR", [766] = "efdtsteqYRR",
+
+ [768] = "evlddxRR0R", [769] = "evlddRR8",
+ [770] = "evldwxRR0R", [771] = "evldwRR8",
+ [772] = "evldhxRR0R", [773] = "evldhRR8",
+ [776] = "evlhhesplatxRR0R", [777] = "evlhhesplatRR2",
+ [780] = "evlhhousplatxRR0R", [781] = "evlhhousplatRR2",
+ [782] = "evlhhossplatxRR0R", [783] = "evlhhossplatRR2",
+ [784] = "evlwhexRR0R", [785] = "evlwheRR4",
+ [788] = "evlwhouxRR0R", [789] = "evlwhouRR4",
+ [790] = "evlwhosxRR0R", [791] = "evlwhosRR4",
+ [792] = "evlwwsplatxRR0R", [793] = "evlwwsplatRR4",
+ [796] = "evlwhsplatxRR0R", [797] = "evlwhsplatRR4",
+
+ [800] = "evstddxRR0R", [801] = "evstddRR8",
+ [802] = "evstdwxRR0R", [803] = "evstdwRR8",
+ [804] = "evstdhxRR0R", [805] = "evstdhRR8",
+ [816] = "evstwhexRR0R", [817] = "evstwheRR4",
+ [820] = "evstwhoxRR0R", [821] = "evstwhoRR4",
+ [824] = "evstwwexRR0R", [825] = "evstwweRR4",
+ [828] = "evstwwoxRR0R", [829] = "evstwwoRR4",
+
+ [1027] = "evmhessfRRR", [1031] = "evmhossfRRR", [1032] = "evmheumiRRR",
+ [1033] = "evmhesmiRRR", [1035] = "evmhesmfRRR", [1036] = "evmhoumiRRR",
+ [1037] = "evmhosmiRRR", [1039] = "evmhosmfRRR", [1059] = "evmhessfaRRR",
+ [1063] = "evmhossfaRRR", [1064] = "evmheumiaRRR", [1065] = "evmhesmiaRRR",
+ [1067] = "evmhesmfaRRR", [1068] = "evmhoumiaRRR", [1069] = "evmhosmiaRRR",
+ [1071] = "evmhosmfaRRR", [1095] = "evmwhssfRRR", [1096] = "evmwlumiRRR",
+ [1100] = "evmwhumiRRR", [1101] = "evmwhsmiRRR", [1103] = "evmwhsmfRRR",
+ [1107] = "evmwssfRRR", [1112] = "evmwumiRRR", [1113] = "evmwsmiRRR",
+ [1115] = "evmwsmfRRR", [1127] = "evmwhssfaRRR", [1128] = "evmwlumiaRRR",
+ [1132] = "evmwhumiaRRR", [1133] = "evmwhsmiaRRR", [1135] = "evmwhsmfaRRR",
+ [1139] = "evmwssfaRRR", [1144] = "evmwumiaRRR", [1145] = "evmwsmiaRRR",
+ [1147] = "evmwsmfaRRR",
+
+ [1216] = "evaddusiaawRR", [1217] = "evaddssiaawRR",
+ [1218] = "evsubfusiaawRR", [1219] = "evsubfssiaawRR",
+ [1220] = "evmraRR",
+ [1222] = "evdivwsRRR", [1223] = "evdivwuRRR",
+ [1224] = "evaddumiaawRR", [1225] = "evaddsmiaawRR",
+ [1226] = "evsubfumiaawRR", [1227] = "evsubfsmiaawRR",
+
+ [1280] = "evmheusiaawRRR", [1281] = "evmhessiaawRRR",
+ [1283] = "evmhessfaawRRR", [1284] = "evmhousiaawRRR",
+ [1285] = "evmhossiaawRRR", [1287] = "evmhossfaawRRR",
+ [1288] = "evmheumiaawRRR", [1289] = "evmhesmiaawRRR",
+ [1291] = "evmhesmfaawRRR", [1292] = "evmhoumiaawRRR",
+ [1293] = "evmhosmiaawRRR", [1295] = "evmhosmfaawRRR",
+ [1320] = "evmhegumiaaRRR", [1321] = "evmhegsmiaaRRR",
+ [1323] = "evmhegsmfaaRRR", [1324] = "evmhogumiaaRRR",
+ [1325] = "evmhogsmiaaRRR", [1327] = "evmhogsmfaaRRR",
+ [1344] = "evmwlusiaawRRR", [1345] = "evmwlssiaawRRR",
+ [1352] = "evmwlumiaawRRR", [1353] = "evmwlsmiaawRRR",
+ [1363] = "evmwssfaaRRR", [1368] = "evmwumiaaRRR",
+ [1369] = "evmwsmiaaRRR", [1371] = "evmwsmfaaRRR",
+ [1408] = "evmheusianwRRR", [1409] = "evmhessianwRRR",
+ [1411] = "evmhessfanwRRR", [1412] = "evmhousianwRRR",
+ [1413] = "evmhossianwRRR", [1415] = "evmhossfanwRRR",
+ [1416] = "evmheumianwRRR", [1417] = "evmhesmianwRRR",
+ [1419] = "evmhesmfanwRRR", [1420] = "evmhoumianwRRR",
+ [1421] = "evmhosmianwRRR", [1423] = "evmhosmfanwRRR",
+ [1448] = "evmhegumianRRR", [1449] = "evmhegsmianRRR",
+ [1451] = "evmhegsmfanRRR", [1452] = "evmhogumianRRR",
+ [1453] = "evmhogsmianRRR", [1455] = "evmhogsmfanRRR",
+ [1472] = "evmwlusianwRRR", [1473] = "evmwlssianwRRR",
+ [1480] = "evmwlumianwRRR", [1481] = "evmwlsmianwRRR",
+ [1491] = "evmwssfanRRR", [1496] = "evmwumianRRR",
+ [1497] = "evmwsmianRRR", [1499] = "evmwsmfanRRR",
+}
+
+local map_pri = {
+ [0] = false, false, "tdiARI", "twiARI",
+ map_spe, false, false, "mulliRRI",
+ "subficRRI", false, "cmpl_iYLRU", "cmp_iYLRI",
+ "addicRRI", "addic.RRI", "addi|liRR0I", "addis|lisRR0I",
+ "b_KBJ", "sc", "bKJ", map_crops,
+ "rlwimiRR~AAA.", map_rlwinm, false, "rlwnmRR~RAA.",
+ "oriNRR~U", "orisRR~U", "xoriRR~U", "xorisRR~U",
+ "andi.RR~U", "andis.RR~U", map_rld, map_ext,
+ "lwzRRD", "lwzuRRD", "lbzRRD", "lbzuRRD",
+ "stwRRD", "stwuRRD", "stbRRD", "stbuRRD",
+ "lhzRRD", "lhzuRRD", "lhaRRD", "lhauRRD",
+ "sthRRD", "sthuRRD", "lmwRRD", "stmwRRD",
+ "lfsFRD", "lfsuFRD", "lfdFRD", "lfduFRD",
+ "stfsFRD", "stfsuFRD", "stfdFRD", "stfduFRD",
+ false, false, map_ld, map_fps,
+ false, false, map_std, map_fpd,
+}
+
+------------------------------------------------------------------------------
+
+local map_gpr = {
+ [0] = "r0", "sp", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+}
+
+local map_cond = { [0] = "lt", "gt", "eq", "so", "ge", "le", "ne", "ns", }
+
+-- Format a condition bit.
+local function condfmt(cond)
+ if cond <= 3 then
+ return map_cond[band(cond, 3)]
+ else
+ return format("4*cr%d+%s", rshift(cond, 2), map_cond[band(cond, 3)])
+ end
+end
+
+------------------------------------------------------------------------------
+
+-- Output a nicely formatted line with an opcode and operands.
+local function putop(ctx, text, operands)
+ local pos = ctx.pos
+ local extra = ""
+ if ctx.rel then
+ local sym = ctx.symtab[ctx.rel]
+ if sym then extra = "\t->"..sym end
+ end
+ if ctx.hexdump > 0 then
+ ctx.out(format("%08x %s %-7s %s%s\n",
+ ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra))
+ else
+ ctx.out(format("%08x %-7s %s%s\n",
+ ctx.addr+pos, text, concat(operands, ", "), extra))
+ end
+ ctx.pos = pos + 4
+end
+
+-- Fallback for unknown opcodes.
+local function unknown(ctx)
+ return putop(ctx, ".long", { "0x"..tohex(ctx.op) })
+end
+
+-- Disassemble a single instruction.
+local function disass_ins(ctx)
+ local pos = ctx.pos
+ local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4)
+ local op = bor(lshift(b0, 24), lshift(b1, 16), lshift(b2, 8), b3)
+ local operands = {}
+ local last = nil
+ local rs = 21
+ ctx.op = op
+ ctx.rel = nil
+
+ local opat = map_pri[rshift(b0, 2)]
+ while type(opat) ~= "string" do
+ if not opat then return unknown(ctx) end
+ opat = opat[band(rshift(op, opat.shift), opat.mask)]
+ end
+ local name, pat = match(opat, "^([a-z0-9_.]*)(.*)")
+ local altname, pat2 = match(pat, "|([a-z0-9_.]*)(.*)")
+ if altname then pat = pat2 end
+
+ for p in gmatch(pat, ".") do
+ local x = nil
+ if p == "R" then
+ x = map_gpr[band(rshift(op, rs), 31)]
+ rs = rs - 5
+ elseif p == "F" then
+ x = "f"..band(rshift(op, rs), 31)
+ rs = rs - 5
+ elseif p == "A" then
+ x = band(rshift(op, rs), 31)
+ rs = rs - 5
+ elseif p == "S" then
+ x = arshift(lshift(op, 27-rs), 27)
+ rs = rs - 5
+ elseif p == "I" then
+ x = arshift(lshift(op, 16), 16)
+ elseif p == "U" then
+ x = band(op, 0xffff)
+ elseif p == "D" or p == "E" then
+ local disp = arshift(lshift(op, 16), 16)
+ if p == "E" then disp = band(disp, -4) end
+ if last == "r0" then last = "0" end
+ operands[#operands] = format("%d(%s)", disp, last)
+ elseif p >= "2" and p <= "8" then
+ local disp = band(rshift(op, rs), 31) * p
+ if last == "r0" then last = "0" end
+ operands[#operands] = format("%d(%s)", disp, last)
+ elseif p == "H" then
+ x = band(rshift(op, rs), 31) + lshift(band(op, 2), 4)
+ rs = rs - 5
+ elseif p == "M" then
+ x = band(rshift(op, rs), 31) + band(op, 0x20)
+ elseif p == "C" then
+ x = condfmt(band(rshift(op, rs), 31))
+ rs = rs - 5
+ elseif p == "B" then
+ local bo = rshift(op, 21)
+ local cond = band(rshift(op, 16), 31)
+ local cn = ""
+ rs = rs - 10
+ if band(bo, 4) == 0 then
+ cn = band(bo, 2) == 0 and "dnz" or "dz"
+ if band(bo, 0x10) == 0 then
+ cn = cn..(band(bo, 8) == 0 and "f" or "t")
+ end
+ if band(bo, 0x10) == 0 then x = condfmt(cond) end
+ name = name..(band(bo, 1) == band(rshift(op, 15), 1) and "-" or "+")
+ elseif band(bo, 0x10) == 0 then
+ cn = map_cond[band(cond, 3) + (band(bo, 8) == 0 and 4 or 0)]
+ if cond > 3 then x = "cr"..rshift(cond, 2) end
+ name = name..(band(bo, 1) == band(rshift(op, 15), 1) and "-" or "+")
+ end
+ name = gsub(name, "_", cn)
+ elseif p == "J" then
+ x = arshift(lshift(op, 27-rs), 29-rs)*4
+ if band(op, 2) == 0 then x = ctx.addr + pos + x end
+ ctx.rel = x
+ x = "0x"..tohex(x)
+ elseif p == "K" then
+ if band(op, 1) ~= 0 then name = name.."l" end
+ if band(op, 2) ~= 0 then name = name.."a" end
+ elseif p == "X" or p == "Y" then
+ x = band(rshift(op, rs+2), 7)
+ if x == 0 and p == "Y" then x = nil else x = "cr"..x end
+ rs = rs - 5
+ elseif p == "W" then
+ x = "cr"..band(op, 7)
+ elseif p == "Z" then
+ x = band(rshift(op, rs-4), 255)
+ rs = rs - 10
+ elseif p == ">" then
+ operands[#operands] = rshift(operands[#operands], 1)
+ elseif p == "0" then
+ if last == "r0" then
+ operands[#operands] = nil
+ if altname then name = altname end
+ end
+ elseif p == "L" then
+ name = gsub(name, "_", band(op, 0x00200000) ~= 0 and "d" or "w")
+ elseif p == "." then
+ if band(op, 1) == 1 then name = name.."." end
+ elseif p == "N" then
+ if op == 0x60000000 then name = "nop"; break end
+ elseif p == "~" then
+ local n = #operands
+ operands[n-1], operands[n] = operands[n], operands[n-1]
+ elseif p == "=" then
+ local n = #operands
+ if last == operands[n-1] then
+ operands[n] = nil
+ name = altname
+ end
+ elseif p == "%" then
+ local n = #operands
+ if last == operands[n-1] and last == operands[n-2] then
+ operands[n] = nil
+ operands[n-1] = nil
+ name = altname
+ end
+ elseif p == "-" then
+ rs = rs - 5
+ else
+ assert(false)
+ end
+ if x then operands[#operands+1] = x; last = x end
+ end
+
+ return putop(ctx, name, operands)
+end
+
+------------------------------------------------------------------------------
+
+-- Disassemble a block of code.
+local function disass_block(ctx, ofs, len)
+ if not ofs then ofs = 0 end
+ local stop = len and ofs+len or #ctx.code
+ stop = stop - stop % 4
+ ctx.pos = ofs - ofs % 4
+ ctx.rel = nil
+ while ctx.pos < stop do disass_ins(ctx) end
+end
+
+-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).
+local function create(code, addr, out)
+ local ctx = {}
+ ctx.code = code
+ ctx.addr = addr or 0
+ ctx.out = out or io.write
+ ctx.symtab = {}
+ ctx.disass = disass_block
+ ctx.hexdump = 8
+ return ctx
+end
+
+-- Simple API: disassemble code (a string) at address and output via out.
+local function disass(code, addr, out)
+ create(code, addr, out):disass()
+end
+
+-- Return register name for RID.
+local function regname(r)
+ if r < 32 then return map_gpr[r] end
+ return "f"..(r-32)
+end
+
+-- Public module functions.
+return {
+ create = create,
+ disass = disass,
+ regname = regname
+}
+
diff --git a/jit/dis_x64.lua b/jit/dis_x64.lua
index 2d37423..d076c6a 100644
--- a/jit/dis_x64.lua
+++ b/jit/dis_x64.lua
@@ -1,7 +1,7 @@
----------------------------------------------------------------------------
-- LuaJIT x64 disassembler wrapper module.
--
--- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h
----------------------------------------------------------------------------
-- This module just exports the 64 bit functions from the combined
diff --git a/jit/dis_x86.lua b/jit/dis_x86.lua
index 5480854..84492ff 100644
--- a/jit/dis_x86.lua
+++ b/jit/dis_x86.lua
@@ -1,7 +1,7 @@
----------------------------------------------------------------------------
-- LuaJIT x86/x64 disassembler module.
--
--- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h
----------------------------------------------------------------------------
-- This is a helper module used by the LuaJIT machine code dumper module.
diff --git a/jit/dump.lua b/jit/dump.lua
index f8a5319..e64d6f9 100644
--- a/jit/dump.lua
+++ b/jit/dump.lua
@@ -1,7 +1,7 @@
----------------------------------------------------------------------------
-- LuaJIT compiler dump module.
--
--- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h
----------------------------------------------------------------------------
--
diff --git a/jit/p.lua b/jit/p.lua
index c9ec1d8..f225c31 100644
--- a/jit/p.lua
+++ b/jit/p.lua
@@ -1,7 +1,7 @@
----------------------------------------------------------------------------
-- LuaJIT profiler.
--
--- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h
----------------------------------------------------------------------------
--
diff --git a/jit/v.lua b/jit/v.lua
index 8358914..ac8b19d 100644
--- a/jit/v.lua
+++ b/jit/v.lua
@@ -1,7 +1,7 @@
----------------------------------------------------------------------------
-- Verbose mode of the LuaJIT compiler.
--
--- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h
----------------------------------------------------------------------------
--
diff --git a/jit/vmdef_linux32.lua b/jit/vmdef_linux32.lua
new file mode 100644
index 0000000..481f979
--- /dev/null
+++ b/jit/vmdef_linux32.lua
@@ -0,0 +1,409 @@
+-- This is a generated file. DO NOT EDIT!
+
+return {
+
+bcnames = "ISLT ISGE ISLE ISGT ISEQV ISNEV ISEQS ISNES ISEQN ISNEN ISEQP ISNEP ISTC ISFC IST ISF ISTYPEISNUM MOV NOT UNM LEN ADDVN SUBVN MULVN DIVVN MODVN ADDNV SUBNV MULNV DIVNV MODNV ADDVV SUBVV MULVV DIVVV MODVV POW CAT KSTR KCDATAKSHORTKNUM KPRI KNIL UGET USETV USETS USETN USETP UCLO FNEW TNEW TDUP GGET GSET TGETV TGETS TGETB TGETR TSETV TSETS TSETB TSETM TSETR CALLM CALL CALLMTCALLT ITERC ITERN VARG ISNEXTRETM RET RET0 RET1 FORI JFORI FORL IFORL JFORL ITERL IITERLJITERLLOOP ILOOP JLOOP JMP FUNCF IFUNCFJFUNCFFUNCV IFUNCVJFUNCVFUNCC FUNCCW",
+
+irnames = "LT GE LE GT ULT UGE ULE UGT EQ NE ABC RETF NOP BASE PVAL GCSTEPHIOP LOOP USE PHI RENAMEPROF KPRI KINT KGC KPTR KKPTR KNULL KNUM KINT64KSLOT BNOT BSWAP BAND BOR BXOR BSHL BSHR BSAR BROL BROR ADD SUB MUL DIV MOD POW NEG ABS LDEXP MIN MAX FPMATHADDOV SUBOV MULOV AREF HREFK HREF NEWREFUREFO UREFC FREF TMPREFSTRREFLREF ALOAD HLOAD ULOAD FLOAD XLOAD SLOAD VLOAD ALEN ASTOREHSTOREUSTOREFSTOREXSTORESNEW XSNEW TNEW TDUP CNEW CNEWI BUFHDRBUFPUTBUFSTRTBAR OBAR XBAR CONV TOBIT TOSTR STRTO CALLN CALLA CALLL CALLS CALLXSCARG ",
+
+irfpm = { [0]="floor", "ceil", "trunc", "sqrt", "log", "log2", "other", },
+
+irfield = { [0]="str.len", "func.env", "func.pc", "func.ffid", "thread.env", "thread.exdata", "thread.exdata2", "tab.meta", "tab.array", "tab.node", "tab.asize", "tab.hmask", "tab.nomm", "udata.meta", "udata.udtype", "udata.file", "sbuf.w", "sbuf.e", "sbuf.b", "sbuf.l", "sbuf.ref", "sbuf.r", "cdata.ctypeid", "cdata.ptr", "cdata.int", "cdata.int64", "cdata.int64_4", },
+
+ircall = {
+[0]="lj_str_cmp",
+"lj_str_find",
+"lj_str_new",
+"lj_strscan_num",
+"lj_strfmt_int",
+"lj_strfmt_num",
+"lj_strfmt_char",
+"lj_strfmt_putint",
+"lj_strfmt_putnum",
+"lj_strfmt_putquoted",
+"lj_strfmt_putfxint",
+"lj_strfmt_putfnum_int",
+"lj_strfmt_putfnum_uint",
+"lj_strfmt_putfnum",
+"lj_strfmt_putfstr",
+"lj_strfmt_putfchar",
+"lj_buf_putmem",
+"lj_buf_putstr",
+"lj_buf_putchar",
+"lj_buf_putstr_reverse",
+"lj_buf_putstr_lower",
+"lj_buf_putstr_upper",
+"lj_buf_putstr_rep",
+"lj_buf_puttab",
+"lj_bufx_set",
+"lj_bufx_more",
+"lj_serialize_put",
+"lj_serialize_get",
+"lj_serialize_encode",
+"lj_serialize_decode",
+"lj_buf_tostr",
+"lj_tab_new_ah",
+"lj_tab_new1",
+"lj_tab_dup",
+"lj_tab_clear",
+"lj_tab_newkey",
+"lj_tab_keyindex",
+"lj_vm_next",
+"lj_tab_len",
+"lj_tab_clone",
+"lj_tab_isarray",
+"lj_tab_nkeys",
+"lj_tab_isempty",
+"lj_tab_len_hint",
+"lj_gc_step_jit",
+"lj_gc_barrieruv",
+"lj_mem_newgco",
+"lj_prng_u64d",
+"lj_vm_modi",
+"log10",
+"exp",
+"sin",
+"cos",
+"tan",
+"asin",
+"acos",
+"atan",
+"sinh",
+"cosh",
+"tanh",
+"fputc",
+"fwrite",
+"fflush",
+"lj_vm_floor",
+"lj_vm_ceil",
+"lj_vm_trunc",
+"sqrt",
+"log",
+"lj_vm_log2",
+"pow",
+"atan2",
+"ldexp",
+"lj_vm_tobit",
+"softfp_add",
+"softfp_sub",
+"softfp_mul",
+"softfp_div",
+"softfp_cmp",
+"softfp_i2d",
+"softfp_d2i",
+"lj_vm_sfmin",
+"lj_vm_sfmax",
+"lj_vm_tointg",
+"softfp_ui2d",
+"softfp_f2d",
+"softfp_d2ui",
+"softfp_d2f",
+"softfp_i2f",
+"softfp_ui2f",
+"softfp_f2i",
+"softfp_f2ui",
+"fp64_l2d",
+"fp64_ul2d",
+"fp64_l2f",
+"fp64_ul2f",
+"fp64_d2l",
+"fp64_d2ul",
+"fp64_f2l",
+"fp64_f2ul",
+"lj_carith_divi64",
+"lj_carith_divu64",
+"lj_carith_modi64",
+"lj_carith_modu64",
+"lj_carith_powi64",
+"lj_carith_powu64",
+"lj_cdata_newv",
+"lj_cdata_setfin",
+"strlen",
+"memcpy",
+"memset",
+"lj_vm_errno",
+"lj_carith_mul64",
+"lj_carith_shl64",
+"lj_carith_shr64",
+"lj_carith_sar64",
+"lj_carith_rol64",
+"lj_carith_ror64",
+},
+
+traceerr = {
+[0]="error thrown or hook called during recording",
+"trace too short",
+"trace too long",
+"trace too deep",
+"too many snapshots",
+"blacklisted",
+"retry recording",
+"NYI: bytecode %d",
+"leaving loop in root trace",
+"inner loop in root trace",
+"loop unroll limit reached",
+"bad argument type",
+"JIT compilation disabled for function",
+"call unroll limit reached",
+"down-recursion, restarting",
+"NYI: unsupported variant of FastFunc %s",
+"NYI: return to lower frame",
+"store with nil or NaN key",
+"missing metamethod",
+"looping index lookup",
+"NYI: mixed sparse/dense table",
+"symbol not in cache",
+"NYI: unsupported C type conversion",
+"NYI: unsupported C function type",
+"guard would always fail",
+"too many PHIs",
+"persistent type instability",
+"failed to allocate mcode memory",
+"machine code too long",
+"hit mcode limit (retrying)",
+"too many spill slots",
+"inconsistent register allocation",
+"NYI: cannot assemble IR instruction %d",
+"NYI: PHI shuffling too complex",
+"NYI: register coalescing too complex",
+},
+
+ffnames = {
+[0]="Lua",
+"C",
+"assert",
+"type",
+"next",
+"pairs",
+"ipairs_aux",
+"ipairs",
+"getmetatable",
+"setmetatable",
+"getfenv",
+"setfenv",
+"rawget",
+"rawset",
+"rawequal",
+"rawlen",
+"unpack",
+"select",
+"tonumber",
+"tostring",
+"error",
+"pcall",
+"xpcall",
+"loadfile",
+"load",
+"loadstring",
+"dofile",
+"gcinfo",
+"collectgarbage",
+"newproxy",
+"print",
+"coroutine.status",
+"coroutine.running",
+"coroutine.isyieldable",
+"coroutine.create",
+"coroutine.yield",
+"coroutine.resume",
+"coroutine.wrap_aux",
+"coroutine.wrap",
+"thread.exdata",
+"thread.exdata2",
+"math.abs",
+"math.floor",
+"math.ceil",
+"math.sqrt",
+"math.log10",
+"math.exp",
+"math.sin",
+"math.cos",
+"math.tan",
+"math.asin",
+"math.acos",
+"math.atan",
+"math.sinh",
+"math.cosh",
+"math.tanh",
+"math.frexp",
+"math.modf",
+"math.log",
+"math.atan2",
+"math.pow",
+"math.fmod",
+"math.ldexp",
+"math.min",
+"math.max",
+"math.random",
+"math.randomseed",
+"bit.tobit",
+"bit.bnot",
+"bit.bswap",
+"bit.lshift",
+"bit.rshift",
+"bit.arshift",
+"bit.rol",
+"bit.ror",
+"bit.band",
+"bit.bor",
+"bit.bxor",
+"bit.tohex",
+"string.byte",
+"string.char",
+"string.sub",
+"string.rep",
+"string.reverse",
+"string.lower",
+"string.upper",
+"string.dump",
+"string.find",
+"string.match",
+"string.gmatch_aux",
+"string.gmatch",
+"string.gsub",
+"string.format",
+"table.maxn",
+"table.insert",
+"table.concat",
+"table.clone",
+"table.isarray",
+"table.nkeys",
+"table.isempty",
+"table.sort",
+"table.pack",
+"table.new",
+"table.clear",
+"io.method.close",
+"io.method.read",
+"io.method.write",
+"io.method.flush",
+"io.method.seek",
+"io.method.setvbuf",
+"io.method.lines",
+"io.method.__gc",
+"io.method.__tostring",
+"io.open",
+"io.popen",
+"io.tmpfile",
+"io.close",
+"io.read",
+"io.write",
+"io.flush",
+"io.input",
+"io.output",
+"io.lines",
+"io.type",
+"os.execute",
+"os.remove",
+"os.rename",
+"os.tmpname",
+"os.getenv",
+"os.exit",
+"os.clock",
+"os.date",
+"os.time",
+"os.difftime",
+"os.setlocale",
+"debug.getregistry",
+"debug.getmetatable",
+"debug.setmetatable",
+"debug.getfenv",
+"debug.setfenv",
+"debug.getinfo",
+"debug.getlocal",
+"debug.setlocal",
+"debug.getupvalue",
+"debug.setupvalue",
+"debug.upvalueid",
+"debug.upvaluejoin",
+"debug.getuservalue",
+"debug.setuservalue",
+"debug.sethook",
+"debug.gethook",
+"debug.debug",
+"debug.traceback",
+"jit.on",
+"jit.off",
+"jit.flush",
+"jit.status",
+"jit.security",
+"jit.attach",
+"jit.prngstate",
+"jit.util.funcinfo",
+"jit.util.funcbc",
+"jit.util.funck",
+"jit.util.funcuvname",
+"jit.util.traceinfo",
+"jit.util.traceir",
+"jit.util.tracek",
+"jit.util.tracesnap",
+"jit.util.tracemc",
+"jit.util.traceexitstub",
+"jit.util.ircalladdr",
+"jit.opt.start",
+"jit.profile.start",
+"jit.profile.stop",
+"jit.profile.dumpstack",
+"ffi.meta.__index",
+"ffi.meta.__newindex",
+"ffi.meta.__eq",
+"ffi.meta.__len",
+"ffi.meta.__lt",
+"ffi.meta.__le",
+"ffi.meta.__concat",
+"ffi.meta.__call",
+"ffi.meta.__add",
+"ffi.meta.__sub",
+"ffi.meta.__mul",
+"ffi.meta.__div",
+"ffi.meta.__mod",
+"ffi.meta.__pow",
+"ffi.meta.__unm",
+"ffi.meta.__tostring",
+"ffi.meta.__pairs",
+"ffi.meta.__ipairs",
+"ffi.clib.__index",
+"ffi.clib.__newindex",
+"ffi.clib.__gc",
+"ffi.callback.free",
+"ffi.callback.set",
+"ffi.cdef",
+"ffi.new",
+"ffi.cast",
+"ffi.typeof",
+"ffi.typeinfo",
+"ffi.istype",
+"ffi.sizeof",
+"ffi.alignof",
+"ffi.offsetof",
+"ffi.errno",
+"ffi.string",
+"ffi.copy",
+"ffi.fill",
+"ffi.abi",
+"ffi.metatype",
+"ffi.gc",
+"ffi.load",
+"buffer.method.free",
+"buffer.method.reset",
+"buffer.method.skip",
+"buffer.method.set",
+"buffer.method.put",
+"buffer.method.putf",
+"buffer.method.get",
+"buffer.method.putcdata",
+"buffer.method.reserve",
+"buffer.method.commit",
+"buffer.method.ref",
+"buffer.method.encode",
+"buffer.method.decode",
+"buffer.method.__gc",
+"buffer.method.__tostring",
+"buffer.method.__len",
+"buffer.new",
+"buffer.encode",
+"buffer.decode",
+},
+
+}
+
diff --git a/jit/vmdef_linux64.lua b/jit/vmdef_linux64.lua
index a25bee8..481f979 100644
--- a/jit/vmdef_linux64.lua
+++ b/jit/vmdef_linux64.lua
@@ -80,7 +80,6 @@ ircall = {
"sqrt",
"log",
"lj_vm_log2",
-"lj_vm_powi",
"pow",
"atan2",
"ldexp",
diff --git a/jit/vmdef_mingw32.lua b/jit/vmdef_mingw32.lua
new file mode 100644
index 0000000..481f979
--- /dev/null
+++ b/jit/vmdef_mingw32.lua
@@ -0,0 +1,409 @@
+-- This is a generated file. DO NOT EDIT!
+
+return {
+
+bcnames = "ISLT ISGE ISLE ISGT ISEQV ISNEV ISEQS ISNES ISEQN ISNEN ISEQP ISNEP ISTC ISFC IST ISF ISTYPEISNUM MOV NOT UNM LEN ADDVN SUBVN MULVN DIVVN MODVN ADDNV SUBNV MULNV DIVNV MODNV ADDVV SUBVV MULVV DIVVV MODVV POW CAT KSTR KCDATAKSHORTKNUM KPRI KNIL UGET USETV USETS USETN USETP UCLO FNEW TNEW TDUP GGET GSET TGETV TGETS TGETB TGETR TSETV TSETS TSETB TSETM TSETR CALLM CALL CALLMTCALLT ITERC ITERN VARG ISNEXTRETM RET RET0 RET1 FORI JFORI FORL IFORL JFORL ITERL IITERLJITERLLOOP ILOOP JLOOP JMP FUNCF IFUNCFJFUNCFFUNCV IFUNCVJFUNCVFUNCC FUNCCW",
+
+irnames = "LT GE LE GT ULT UGE ULE UGT EQ NE ABC RETF NOP BASE PVAL GCSTEPHIOP LOOP USE PHI RENAMEPROF KPRI KINT KGC KPTR KKPTR KNULL KNUM KINT64KSLOT BNOT BSWAP BAND BOR BXOR BSHL BSHR BSAR BROL BROR ADD SUB MUL DIV MOD POW NEG ABS LDEXP MIN MAX FPMATHADDOV SUBOV MULOV AREF HREFK HREF NEWREFUREFO UREFC FREF TMPREFSTRREFLREF ALOAD HLOAD ULOAD FLOAD XLOAD SLOAD VLOAD ALEN ASTOREHSTOREUSTOREFSTOREXSTORESNEW XSNEW TNEW TDUP CNEW CNEWI BUFHDRBUFPUTBUFSTRTBAR OBAR XBAR CONV TOBIT TOSTR STRTO CALLN CALLA CALLL CALLS CALLXSCARG ",
+
+irfpm = { [0]="floor", "ceil", "trunc", "sqrt", "log", "log2", "other", },
+
+irfield = { [0]="str.len", "func.env", "func.pc", "func.ffid", "thread.env", "thread.exdata", "thread.exdata2", "tab.meta", "tab.array", "tab.node", "tab.asize", "tab.hmask", "tab.nomm", "udata.meta", "udata.udtype", "udata.file", "sbuf.w", "sbuf.e", "sbuf.b", "sbuf.l", "sbuf.ref", "sbuf.r", "cdata.ctypeid", "cdata.ptr", "cdata.int", "cdata.int64", "cdata.int64_4", },
+
+ircall = {
+[0]="lj_str_cmp",
+"lj_str_find",
+"lj_str_new",
+"lj_strscan_num",
+"lj_strfmt_int",
+"lj_strfmt_num",
+"lj_strfmt_char",
+"lj_strfmt_putint",
+"lj_strfmt_putnum",
+"lj_strfmt_putquoted",
+"lj_strfmt_putfxint",
+"lj_strfmt_putfnum_int",
+"lj_strfmt_putfnum_uint",
+"lj_strfmt_putfnum",
+"lj_strfmt_putfstr",
+"lj_strfmt_putfchar",
+"lj_buf_putmem",
+"lj_buf_putstr",
+"lj_buf_putchar",
+"lj_buf_putstr_reverse",
+"lj_buf_putstr_lower",
+"lj_buf_putstr_upper",
+"lj_buf_putstr_rep",
+"lj_buf_puttab",
+"lj_bufx_set",
+"lj_bufx_more",
+"lj_serialize_put",
+"lj_serialize_get",
+"lj_serialize_encode",
+"lj_serialize_decode",
+"lj_buf_tostr",
+"lj_tab_new_ah",
+"lj_tab_new1",
+"lj_tab_dup",
+"lj_tab_clear",
+"lj_tab_newkey",
+"lj_tab_keyindex",
+"lj_vm_next",
+"lj_tab_len",
+"lj_tab_clone",
+"lj_tab_isarray",
+"lj_tab_nkeys",
+"lj_tab_isempty",
+"lj_tab_len_hint",
+"lj_gc_step_jit",
+"lj_gc_barrieruv",
+"lj_mem_newgco",
+"lj_prng_u64d",
+"lj_vm_modi",
+"log10",
+"exp",
+"sin",
+"cos",
+"tan",
+"asin",
+"acos",
+"atan",
+"sinh",
+"cosh",
+"tanh",
+"fputc",
+"fwrite",
+"fflush",
+"lj_vm_floor",
+"lj_vm_ceil",
+"lj_vm_trunc",
+"sqrt",
+"log",
+"lj_vm_log2",
+"pow",
+"atan2",
+"ldexp",
+"lj_vm_tobit",
+"softfp_add",
+"softfp_sub",
+"softfp_mul",
+"softfp_div",
+"softfp_cmp",
+"softfp_i2d",
+"softfp_d2i",
+"lj_vm_sfmin",
+"lj_vm_sfmax",
+"lj_vm_tointg",
+"softfp_ui2d",
+"softfp_f2d",
+"softfp_d2ui",
+"softfp_d2f",
+"softfp_i2f",
+"softfp_ui2f",
+"softfp_f2i",
+"softfp_f2ui",
+"fp64_l2d",
+"fp64_ul2d",
+"fp64_l2f",
+"fp64_ul2f",
+"fp64_d2l",
+"fp64_d2ul",
+"fp64_f2l",
+"fp64_f2ul",
+"lj_carith_divi64",
+"lj_carith_divu64",
+"lj_carith_modi64",
+"lj_carith_modu64",
+"lj_carith_powi64",
+"lj_carith_powu64",
+"lj_cdata_newv",
+"lj_cdata_setfin",
+"strlen",
+"memcpy",
+"memset",
+"lj_vm_errno",
+"lj_carith_mul64",
+"lj_carith_shl64",
+"lj_carith_shr64",
+"lj_carith_sar64",
+"lj_carith_rol64",
+"lj_carith_ror64",
+},
+
+traceerr = {
+[0]="error thrown or hook called during recording",
+"trace too short",
+"trace too long",
+"trace too deep",
+"too many snapshots",
+"blacklisted",
+"retry recording",
+"NYI: bytecode %d",
+"leaving loop in root trace",
+"inner loop in root trace",
+"loop unroll limit reached",
+"bad argument type",
+"JIT compilation disabled for function",
+"call unroll limit reached",
+"down-recursion, restarting",
+"NYI: unsupported variant of FastFunc %s",
+"NYI: return to lower frame",
+"store with nil or NaN key",
+"missing metamethod",
+"looping index lookup",
+"NYI: mixed sparse/dense table",
+"symbol not in cache",
+"NYI: unsupported C type conversion",
+"NYI: unsupported C function type",
+"guard would always fail",
+"too many PHIs",
+"persistent type instability",
+"failed to allocate mcode memory",
+"machine code too long",
+"hit mcode limit (retrying)",
+"too many spill slots",
+"inconsistent register allocation",
+"NYI: cannot assemble IR instruction %d",
+"NYI: PHI shuffling too complex",
+"NYI: register coalescing too complex",
+},
+
+ffnames = {
+[0]="Lua",
+"C",
+"assert",
+"type",
+"next",
+"pairs",
+"ipairs_aux",
+"ipairs",
+"getmetatable",
+"setmetatable",
+"getfenv",
+"setfenv",
+"rawget",
+"rawset",
+"rawequal",
+"rawlen",
+"unpack",
+"select",
+"tonumber",
+"tostring",
+"error",
+"pcall",
+"xpcall",
+"loadfile",
+"load",
+"loadstring",
+"dofile",
+"gcinfo",
+"collectgarbage",
+"newproxy",
+"print",
+"coroutine.status",
+"coroutine.running",
+"coroutine.isyieldable",
+"coroutine.create",
+"coroutine.yield",
+"coroutine.resume",
+"coroutine.wrap_aux",
+"coroutine.wrap",
+"thread.exdata",
+"thread.exdata2",
+"math.abs",
+"math.floor",
+"math.ceil",
+"math.sqrt",
+"math.log10",
+"math.exp",
+"math.sin",
+"math.cos",
+"math.tan",
+"math.asin",
+"math.acos",
+"math.atan",
+"math.sinh",
+"math.cosh",
+"math.tanh",
+"math.frexp",
+"math.modf",
+"math.log",
+"math.atan2",
+"math.pow",
+"math.fmod",
+"math.ldexp",
+"math.min",
+"math.max",
+"math.random",
+"math.randomseed",
+"bit.tobit",
+"bit.bnot",
+"bit.bswap",
+"bit.lshift",
+"bit.rshift",
+"bit.arshift",
+"bit.rol",
+"bit.ror",
+"bit.band",
+"bit.bor",
+"bit.bxor",
+"bit.tohex",
+"string.byte",
+"string.char",
+"string.sub",
+"string.rep",
+"string.reverse",
+"string.lower",
+"string.upper",
+"string.dump",
+"string.find",
+"string.match",
+"string.gmatch_aux",
+"string.gmatch",
+"string.gsub",
+"string.format",
+"table.maxn",
+"table.insert",
+"table.concat",
+"table.clone",
+"table.isarray",
+"table.nkeys",
+"table.isempty",
+"table.sort",
+"table.pack",
+"table.new",
+"table.clear",
+"io.method.close",
+"io.method.read",
+"io.method.write",
+"io.method.flush",
+"io.method.seek",
+"io.method.setvbuf",
+"io.method.lines",
+"io.method.__gc",
+"io.method.__tostring",
+"io.open",
+"io.popen",
+"io.tmpfile",
+"io.close",
+"io.read",
+"io.write",
+"io.flush",
+"io.input",
+"io.output",
+"io.lines",
+"io.type",
+"os.execute",
+"os.remove",
+"os.rename",
+"os.tmpname",
+"os.getenv",
+"os.exit",
+"os.clock",
+"os.date",
+"os.time",
+"os.difftime",
+"os.setlocale",
+"debug.getregistry",
+"debug.getmetatable",
+"debug.setmetatable",
+"debug.getfenv",
+"debug.setfenv",
+"debug.getinfo",
+"debug.getlocal",
+"debug.setlocal",
+"debug.getupvalue",
+"debug.setupvalue",
+"debug.upvalueid",
+"debug.upvaluejoin",
+"debug.getuservalue",
+"debug.setuservalue",
+"debug.sethook",
+"debug.gethook",
+"debug.debug",
+"debug.traceback",
+"jit.on",
+"jit.off",
+"jit.flush",
+"jit.status",
+"jit.security",
+"jit.attach",
+"jit.prngstate",
+"jit.util.funcinfo",
+"jit.util.funcbc",
+"jit.util.funck",
+"jit.util.funcuvname",
+"jit.util.traceinfo",
+"jit.util.traceir",
+"jit.util.tracek",
+"jit.util.tracesnap",
+"jit.util.tracemc",
+"jit.util.traceexitstub",
+"jit.util.ircalladdr",
+"jit.opt.start",
+"jit.profile.start",
+"jit.profile.stop",
+"jit.profile.dumpstack",
+"ffi.meta.__index",
+"ffi.meta.__newindex",
+"ffi.meta.__eq",
+"ffi.meta.__len",
+"ffi.meta.__lt",
+"ffi.meta.__le",
+"ffi.meta.__concat",
+"ffi.meta.__call",
+"ffi.meta.__add",
+"ffi.meta.__sub",
+"ffi.meta.__mul",
+"ffi.meta.__div",
+"ffi.meta.__mod",
+"ffi.meta.__pow",
+"ffi.meta.__unm",
+"ffi.meta.__tostring",
+"ffi.meta.__pairs",
+"ffi.meta.__ipairs",
+"ffi.clib.__index",
+"ffi.clib.__newindex",
+"ffi.clib.__gc",
+"ffi.callback.free",
+"ffi.callback.set",
+"ffi.cdef",
+"ffi.new",
+"ffi.cast",
+"ffi.typeof",
+"ffi.typeinfo",
+"ffi.istype",
+"ffi.sizeof",
+"ffi.alignof",
+"ffi.offsetof",
+"ffi.errno",
+"ffi.string",
+"ffi.copy",
+"ffi.fill",
+"ffi.abi",
+"ffi.metatype",
+"ffi.gc",
+"ffi.load",
+"buffer.method.free",
+"buffer.method.reset",
+"buffer.method.skip",
+"buffer.method.set",
+"buffer.method.put",
+"buffer.method.putf",
+"buffer.method.get",
+"buffer.method.putcdata",
+"buffer.method.reserve",
+"buffer.method.commit",
+"buffer.method.ref",
+"buffer.method.encode",
+"buffer.method.decode",
+"buffer.method.__gc",
+"buffer.method.__tostring",
+"buffer.method.__len",
+"buffer.new",
+"buffer.encode",
+"buffer.decode",
+},
+
+}
+
diff --git a/jit/vmdef_mingw64.lua b/jit/vmdef_mingw64.lua
index 6a7544f..481f979 100644
--- a/jit/vmdef_mingw64.lua
+++ b/jit/vmdef_mingw64.lua
@@ -1,410 +1,409 @@
--- This is a generated file. DO NOT EDIT!
-
-return {
-
-bcnames = "ISLT ISGE ISLE ISGT ISEQV ISNEV ISEQS ISNES ISEQN ISNEN ISEQP ISNEP ISTC ISFC IST ISF ISTYPEISNUM MOV NOT UNM LEN ADDVN SUBVN MULVN DIVVN MODVN ADDNV SUBNV MULNV DIVNV MODNV ADDVV SUBVV MULVV DIVVV MODVV POW CAT KSTR KCDATAKSHORTKNUM KPRI KNIL UGET USETV USETS USETN USETP UCLO FNEW TNEW TDUP GGET GSET TGETV TGETS TGETB TGETR TSETV TSETS TSETB TSETM TSETR CALLM CALL CALLMTCALLT ITERC ITERN VARG ISNEXTRETM RET RET0 RET1 FORI JFORI FORL IFORL JFORL ITERL IITERLJITERLLOOP ILOOP JLOOP JMP FUNCF IFUNCFJFUNCFFUNCV IFUNCVJFUNCVFUNCC FUNCCW",
-
-irnames = "LT GE LE GT ULT UGE ULE UGT EQ NE ABC RETF NOP BASE PVAL GCSTEPHIOP LOOP USE PHI RENAMEPROF KPRI KINT KGC KPTR KKPTR KNULL KNUM KINT64KSLOT BNOT BSWAP BAND BOR BXOR BSHL BSHR BSAR BROL BROR ADD SUB MUL DIV MOD POW NEG ABS LDEXP MIN MAX FPMATHADDOV SUBOV MULOV AREF HREFK HREF NEWREFUREFO UREFC FREF TMPREFSTRREFLREF ALOAD HLOAD ULOAD FLOAD XLOAD SLOAD VLOAD ALEN ASTOREHSTOREUSTOREFSTOREXSTORESNEW XSNEW TNEW TDUP CNEW CNEWI BUFHDRBUFPUTBUFSTRTBAR OBAR XBAR CONV TOBIT TOSTR STRTO CALLN CALLA CALLL CALLS CALLXSCARG ",
-
-irfpm = { [0]="floor", "ceil", "trunc", "sqrt", "log", "log2", "other", },
-
-irfield = { [0]="str.len", "func.env", "func.pc", "func.ffid", "thread.env", "thread.exdata", "thread.exdata2", "tab.meta", "tab.array", "tab.node", "tab.asize", "tab.hmask", "tab.nomm", "udata.meta", "udata.udtype", "udata.file", "sbuf.w", "sbuf.e", "sbuf.b", "sbuf.l", "sbuf.ref", "sbuf.r", "cdata.ctypeid", "cdata.ptr", "cdata.int", "cdata.int64", "cdata.int64_4", },
-
-ircall = {
-[0]="lj_str_cmp",
-"lj_str_find",
-"lj_str_new",
-"lj_strscan_num",
-"lj_strfmt_int",
-"lj_strfmt_num",
-"lj_strfmt_char",
-"lj_strfmt_putint",
-"lj_strfmt_putnum",
-"lj_strfmt_putquoted",
-"lj_strfmt_putfxint",
-"lj_strfmt_putfnum_int",
-"lj_strfmt_putfnum_uint",
-"lj_strfmt_putfnum",
-"lj_strfmt_putfstr",
-"lj_strfmt_putfchar",
-"lj_buf_putmem",
-"lj_buf_putstr",
-"lj_buf_putchar",
-"lj_buf_putstr_reverse",
-"lj_buf_putstr_lower",
-"lj_buf_putstr_upper",
-"lj_buf_putstr_rep",
-"lj_buf_puttab",
-"lj_bufx_set",
-"lj_bufx_more",
-"lj_serialize_put",
-"lj_serialize_get",
-"lj_serialize_encode",
-"lj_serialize_decode",
-"lj_buf_tostr",
-"lj_tab_new_ah",
-"lj_tab_new1",
-"lj_tab_dup",
-"lj_tab_clear",
-"lj_tab_newkey",
-"lj_tab_keyindex",
-"lj_vm_next",
-"lj_tab_len",
-"lj_tab_clone",
-"lj_tab_isarray",
-"lj_tab_nkeys",
-"lj_tab_isempty",
-"lj_tab_len_hint",
-"lj_gc_step_jit",
-"lj_gc_barrieruv",
-"lj_mem_newgco",
-"lj_prng_u64d",
-"lj_vm_modi",
-"log10",
-"exp",
-"sin",
-"cos",
-"tan",
-"asin",
-"acos",
-"atan",
-"sinh",
-"cosh",
-"tanh",
-"fputc",
-"fwrite",
-"fflush",
-"lj_vm_floor",
-"lj_vm_ceil",
-"lj_vm_trunc",
-"sqrt",
-"log",
-"lj_vm_log2",
-"lj_vm_powi",
-"pow",
-"atan2",
-"ldexp",
-"lj_vm_tobit",
-"softfp_add",
-"softfp_sub",
-"softfp_mul",
-"softfp_div",
-"softfp_cmp",
-"softfp_i2d",
-"softfp_d2i",
-"lj_vm_sfmin",
-"lj_vm_sfmax",
-"lj_vm_tointg",
-"softfp_ui2d",
-"softfp_f2d",
-"softfp_d2ui",
-"softfp_d2f",
-"softfp_i2f",
-"softfp_ui2f",
-"softfp_f2i",
-"softfp_f2ui",
-"fp64_l2d",
-"fp64_ul2d",
-"fp64_l2f",
-"fp64_ul2f",
-"fp64_d2l",
-"fp64_d2ul",
-"fp64_f2l",
-"fp64_f2ul",
-"lj_carith_divi64",
-"lj_carith_divu64",
-"lj_carith_modi64",
-"lj_carith_modu64",
-"lj_carith_powi64",
-"lj_carith_powu64",
-"lj_cdata_newv",
-"lj_cdata_setfin",
-"strlen",
-"memcpy",
-"memset",
-"lj_vm_errno",
-"lj_carith_mul64",
-"lj_carith_shl64",
-"lj_carith_shr64",
-"lj_carith_sar64",
-"lj_carith_rol64",
-"lj_carith_ror64",
-},
-
-traceerr = {
-[0]="error thrown or hook called during recording",
-"trace too short",
-"trace too long",
-"trace too deep",
-"too many snapshots",
-"blacklisted",
-"retry recording",
-"NYI: bytecode %d",
-"leaving loop in root trace",
-"inner loop in root trace",
-"loop unroll limit reached",
-"bad argument type",
-"JIT compilation disabled for function",
-"call unroll limit reached",
-"down-recursion, restarting",
-"NYI: unsupported variant of FastFunc %s",
-"NYI: return to lower frame",
-"store with nil or NaN key",
-"missing metamethod",
-"looping index lookup",
-"NYI: mixed sparse/dense table",
-"symbol not in cache",
-"NYI: unsupported C type conversion",
-"NYI: unsupported C function type",
-"guard would always fail",
-"too many PHIs",
-"persistent type instability",
-"failed to allocate mcode memory",
-"machine code too long",
-"hit mcode limit (retrying)",
-"too many spill slots",
-"inconsistent register allocation",
-"NYI: cannot assemble IR instruction %d",
-"NYI: PHI shuffling too complex",
-"NYI: register coalescing too complex",
-},
-
-ffnames = {
-[0]="Lua",
-"C",
-"assert",
-"type",
-"next",
-"pairs",
-"ipairs_aux",
-"ipairs",
-"getmetatable",
-"setmetatable",
-"getfenv",
-"setfenv",
-"rawget",
-"rawset",
-"rawequal",
-"rawlen",
-"unpack",
-"select",
-"tonumber",
-"tostring",
-"error",
-"pcall",
-"xpcall",
-"loadfile",
-"load",
-"loadstring",
-"dofile",
-"gcinfo",
-"collectgarbage",
-"newproxy",
-"print",
-"coroutine.status",
-"coroutine.running",
-"coroutine.isyieldable",
-"coroutine.create",
-"coroutine.yield",
-"coroutine.resume",
-"coroutine.wrap_aux",
-"coroutine.wrap",
-"thread.exdata",
-"thread.exdata2",
-"math.abs",
-"math.floor",
-"math.ceil",
-"math.sqrt",
-"math.log10",
-"math.exp",
-"math.sin",
-"math.cos",
-"math.tan",
-"math.asin",
-"math.acos",
-"math.atan",
-"math.sinh",
-"math.cosh",
-"math.tanh",
-"math.frexp",
-"math.modf",
-"math.log",
-"math.atan2",
-"math.pow",
-"math.fmod",
-"math.ldexp",
-"math.min",
-"math.max",
-"math.random",
-"math.randomseed",
-"bit.tobit",
-"bit.bnot",
-"bit.bswap",
-"bit.lshift",
-"bit.rshift",
-"bit.arshift",
-"bit.rol",
-"bit.ror",
-"bit.band",
-"bit.bor",
-"bit.bxor",
-"bit.tohex",
-"string.byte",
-"string.char",
-"string.sub",
-"string.rep",
-"string.reverse",
-"string.lower",
-"string.upper",
-"string.dump",
-"string.find",
-"string.match",
-"string.gmatch_aux",
-"string.gmatch",
-"string.gsub",
-"string.format",
-"table.maxn",
-"table.insert",
-"table.concat",
-"table.clone",
-"table.isarray",
-"table.nkeys",
-"table.isempty",
-"table.sort",
-"table.pack",
-"table.new",
-"table.clear",
-"io.method.close",
-"io.method.read",
-"io.method.write",
-"io.method.flush",
-"io.method.seek",
-"io.method.setvbuf",
-"io.method.lines",
-"io.method.__gc",
-"io.method.__tostring",
-"io.open",
-"io.popen",
-"io.tmpfile",
-"io.close",
-"io.read",
-"io.write",
-"io.flush",
-"io.input",
-"io.output",
-"io.lines",
-"io.type",
-"os.execute",
-"os.remove",
-"os.rename",
-"os.tmpname",
-"os.getenv",
-"os.exit",
-"os.clock",
-"os.date",
-"os.time",
-"os.difftime",
-"os.setlocale",
-"debug.getregistry",
-"debug.getmetatable",
-"debug.setmetatable",
-"debug.getfenv",
-"debug.setfenv",
-"debug.getinfo",
-"debug.getlocal",
-"debug.setlocal",
-"debug.getupvalue",
-"debug.setupvalue",
-"debug.upvalueid",
-"debug.upvaluejoin",
-"debug.getuservalue",
-"debug.setuservalue",
-"debug.sethook",
-"debug.gethook",
-"debug.debug",
-"debug.traceback",
-"jit.on",
-"jit.off",
-"jit.flush",
-"jit.status",
-"jit.security",
-"jit.attach",
-"jit.prngstate",
-"jit.util.funcinfo",
-"jit.util.funcbc",
-"jit.util.funck",
-"jit.util.funcuvname",
-"jit.util.traceinfo",
-"jit.util.traceir",
-"jit.util.tracek",
-"jit.util.tracesnap",
-"jit.util.tracemc",
-"jit.util.traceexitstub",
-"jit.util.ircalladdr",
-"jit.opt.start",
-"jit.profile.start",
-"jit.profile.stop",
-"jit.profile.dumpstack",
-"ffi.meta.__index",
-"ffi.meta.__newindex",
-"ffi.meta.__eq",
-"ffi.meta.__len",
-"ffi.meta.__lt",
-"ffi.meta.__le",
-"ffi.meta.__concat",
-"ffi.meta.__call",
-"ffi.meta.__add",
-"ffi.meta.__sub",
-"ffi.meta.__mul",
-"ffi.meta.__div",
-"ffi.meta.__mod",
-"ffi.meta.__pow",
-"ffi.meta.__unm",
-"ffi.meta.__tostring",
-"ffi.meta.__pairs",
-"ffi.meta.__ipairs",
-"ffi.clib.__index",
-"ffi.clib.__newindex",
-"ffi.clib.__gc",
-"ffi.callback.free",
-"ffi.callback.set",
-"ffi.cdef",
-"ffi.new",
-"ffi.cast",
-"ffi.typeof",
-"ffi.typeinfo",
-"ffi.istype",
-"ffi.sizeof",
-"ffi.alignof",
-"ffi.offsetof",
-"ffi.errno",
-"ffi.string",
-"ffi.copy",
-"ffi.fill",
-"ffi.abi",
-"ffi.metatype",
-"ffi.gc",
-"ffi.load",
-"buffer.method.free",
-"buffer.method.reset",
-"buffer.method.skip",
-"buffer.method.set",
-"buffer.method.put",
-"buffer.method.putf",
-"buffer.method.get",
-"buffer.method.putcdata",
-"buffer.method.reserve",
-"buffer.method.commit",
-"buffer.method.ref",
-"buffer.method.encode",
-"buffer.method.decode",
-"buffer.method.__gc",
-"buffer.method.__tostring",
-"buffer.method.__len",
-"buffer.new",
-"buffer.encode",
-"buffer.decode",
-},
-
-}
-
+-- This is a generated file. DO NOT EDIT!
+
+return {
+
+bcnames = "ISLT ISGE ISLE ISGT ISEQV ISNEV ISEQS ISNES ISEQN ISNEN ISEQP ISNEP ISTC ISFC IST ISF ISTYPEISNUM MOV NOT UNM LEN ADDVN SUBVN MULVN DIVVN MODVN ADDNV SUBNV MULNV DIVNV MODNV ADDVV SUBVV MULVV DIVVV MODVV POW CAT KSTR KCDATAKSHORTKNUM KPRI KNIL UGET USETV USETS USETN USETP UCLO FNEW TNEW TDUP GGET GSET TGETV TGETS TGETB TGETR TSETV TSETS TSETB TSETM TSETR CALLM CALL CALLMTCALLT ITERC ITERN VARG ISNEXTRETM RET RET0 RET1 FORI JFORI FORL IFORL JFORL ITERL IITERLJITERLLOOP ILOOP JLOOP JMP FUNCF IFUNCFJFUNCFFUNCV IFUNCVJFUNCVFUNCC FUNCCW",
+
+irnames = "LT GE LE GT ULT UGE ULE UGT EQ NE ABC RETF NOP BASE PVAL GCSTEPHIOP LOOP USE PHI RENAMEPROF KPRI KINT KGC KPTR KKPTR KNULL KNUM KINT64KSLOT BNOT BSWAP BAND BOR BXOR BSHL BSHR BSAR BROL BROR ADD SUB MUL DIV MOD POW NEG ABS LDEXP MIN MAX FPMATHADDOV SUBOV MULOV AREF HREFK HREF NEWREFUREFO UREFC FREF TMPREFSTRREFLREF ALOAD HLOAD ULOAD FLOAD XLOAD SLOAD VLOAD ALEN ASTOREHSTOREUSTOREFSTOREXSTORESNEW XSNEW TNEW TDUP CNEW CNEWI BUFHDRBUFPUTBUFSTRTBAR OBAR XBAR CONV TOBIT TOSTR STRTO CALLN CALLA CALLL CALLS CALLXSCARG ",
+
+irfpm = { [0]="floor", "ceil", "trunc", "sqrt", "log", "log2", "other", },
+
+irfield = { [0]="str.len", "func.env", "func.pc", "func.ffid", "thread.env", "thread.exdata", "thread.exdata2", "tab.meta", "tab.array", "tab.node", "tab.asize", "tab.hmask", "tab.nomm", "udata.meta", "udata.udtype", "udata.file", "sbuf.w", "sbuf.e", "sbuf.b", "sbuf.l", "sbuf.ref", "sbuf.r", "cdata.ctypeid", "cdata.ptr", "cdata.int", "cdata.int64", "cdata.int64_4", },
+
+ircall = {
+[0]="lj_str_cmp",
+"lj_str_find",
+"lj_str_new",
+"lj_strscan_num",
+"lj_strfmt_int",
+"lj_strfmt_num",
+"lj_strfmt_char",
+"lj_strfmt_putint",
+"lj_strfmt_putnum",
+"lj_strfmt_putquoted",
+"lj_strfmt_putfxint",
+"lj_strfmt_putfnum_int",
+"lj_strfmt_putfnum_uint",
+"lj_strfmt_putfnum",
+"lj_strfmt_putfstr",
+"lj_strfmt_putfchar",
+"lj_buf_putmem",
+"lj_buf_putstr",
+"lj_buf_putchar",
+"lj_buf_putstr_reverse",
+"lj_buf_putstr_lower",
+"lj_buf_putstr_upper",
+"lj_buf_putstr_rep",
+"lj_buf_puttab",
+"lj_bufx_set",
+"lj_bufx_more",
+"lj_serialize_put",
+"lj_serialize_get",
+"lj_serialize_encode",
+"lj_serialize_decode",
+"lj_buf_tostr",
+"lj_tab_new_ah",
+"lj_tab_new1",
+"lj_tab_dup",
+"lj_tab_clear",
+"lj_tab_newkey",
+"lj_tab_keyindex",
+"lj_vm_next",
+"lj_tab_len",
+"lj_tab_clone",
+"lj_tab_isarray",
+"lj_tab_nkeys",
+"lj_tab_isempty",
+"lj_tab_len_hint",
+"lj_gc_step_jit",
+"lj_gc_barrieruv",
+"lj_mem_newgco",
+"lj_prng_u64d",
+"lj_vm_modi",
+"log10",
+"exp",
+"sin",
+"cos",
+"tan",
+"asin",
+"acos",
+"atan",
+"sinh",
+"cosh",
+"tanh",
+"fputc",
+"fwrite",
+"fflush",
+"lj_vm_floor",
+"lj_vm_ceil",
+"lj_vm_trunc",
+"sqrt",
+"log",
+"lj_vm_log2",
+"pow",
+"atan2",
+"ldexp",
+"lj_vm_tobit",
+"softfp_add",
+"softfp_sub",
+"softfp_mul",
+"softfp_div",
+"softfp_cmp",
+"softfp_i2d",
+"softfp_d2i",
+"lj_vm_sfmin",
+"lj_vm_sfmax",
+"lj_vm_tointg",
+"softfp_ui2d",
+"softfp_f2d",
+"softfp_d2ui",
+"softfp_d2f",
+"softfp_i2f",
+"softfp_ui2f",
+"softfp_f2i",
+"softfp_f2ui",
+"fp64_l2d",
+"fp64_ul2d",
+"fp64_l2f",
+"fp64_ul2f",
+"fp64_d2l",
+"fp64_d2ul",
+"fp64_f2l",
+"fp64_f2ul",
+"lj_carith_divi64",
+"lj_carith_divu64",
+"lj_carith_modi64",
+"lj_carith_modu64",
+"lj_carith_powi64",
+"lj_carith_powu64",
+"lj_cdata_newv",
+"lj_cdata_setfin",
+"strlen",
+"memcpy",
+"memset",
+"lj_vm_errno",
+"lj_carith_mul64",
+"lj_carith_shl64",
+"lj_carith_shr64",
+"lj_carith_sar64",
+"lj_carith_rol64",
+"lj_carith_ror64",
+},
+
+traceerr = {
+[0]="error thrown or hook called during recording",
+"trace too short",
+"trace too long",
+"trace too deep",
+"too many snapshots",
+"blacklisted",
+"retry recording",
+"NYI: bytecode %d",
+"leaving loop in root trace",
+"inner loop in root trace",
+"loop unroll limit reached",
+"bad argument type",
+"JIT compilation disabled for function",
+"call unroll limit reached",
+"down-recursion, restarting",
+"NYI: unsupported variant of FastFunc %s",
+"NYI: return to lower frame",
+"store with nil or NaN key",
+"missing metamethod",
+"looping index lookup",
+"NYI: mixed sparse/dense table",
+"symbol not in cache",
+"NYI: unsupported C type conversion",
+"NYI: unsupported C function type",
+"guard would always fail",
+"too many PHIs",
+"persistent type instability",
+"failed to allocate mcode memory",
+"machine code too long",
+"hit mcode limit (retrying)",
+"too many spill slots",
+"inconsistent register allocation",
+"NYI: cannot assemble IR instruction %d",
+"NYI: PHI shuffling too complex",
+"NYI: register coalescing too complex",
+},
+
+ffnames = {
+[0]="Lua",
+"C",
+"assert",
+"type",
+"next",
+"pairs",
+"ipairs_aux",
+"ipairs",
+"getmetatable",
+"setmetatable",
+"getfenv",
+"setfenv",
+"rawget",
+"rawset",
+"rawequal",
+"rawlen",
+"unpack",
+"select",
+"tonumber",
+"tostring",
+"error",
+"pcall",
+"xpcall",
+"loadfile",
+"load",
+"loadstring",
+"dofile",
+"gcinfo",
+"collectgarbage",
+"newproxy",
+"print",
+"coroutine.status",
+"coroutine.running",
+"coroutine.isyieldable",
+"coroutine.create",
+"coroutine.yield",
+"coroutine.resume",
+"coroutine.wrap_aux",
+"coroutine.wrap",
+"thread.exdata",
+"thread.exdata2",
+"math.abs",
+"math.floor",
+"math.ceil",
+"math.sqrt",
+"math.log10",
+"math.exp",
+"math.sin",
+"math.cos",
+"math.tan",
+"math.asin",
+"math.acos",
+"math.atan",
+"math.sinh",
+"math.cosh",
+"math.tanh",
+"math.frexp",
+"math.modf",
+"math.log",
+"math.atan2",
+"math.pow",
+"math.fmod",
+"math.ldexp",
+"math.min",
+"math.max",
+"math.random",
+"math.randomseed",
+"bit.tobit",
+"bit.bnot",
+"bit.bswap",
+"bit.lshift",
+"bit.rshift",
+"bit.arshift",
+"bit.rol",
+"bit.ror",
+"bit.band",
+"bit.bor",
+"bit.bxor",
+"bit.tohex",
+"string.byte",
+"string.char",
+"string.sub",
+"string.rep",
+"string.reverse",
+"string.lower",
+"string.upper",
+"string.dump",
+"string.find",
+"string.match",
+"string.gmatch_aux",
+"string.gmatch",
+"string.gsub",
+"string.format",
+"table.maxn",
+"table.insert",
+"table.concat",
+"table.clone",
+"table.isarray",
+"table.nkeys",
+"table.isempty",
+"table.sort",
+"table.pack",
+"table.new",
+"table.clear",
+"io.method.close",
+"io.method.read",
+"io.method.write",
+"io.method.flush",
+"io.method.seek",
+"io.method.setvbuf",
+"io.method.lines",
+"io.method.__gc",
+"io.method.__tostring",
+"io.open",
+"io.popen",
+"io.tmpfile",
+"io.close",
+"io.read",
+"io.write",
+"io.flush",
+"io.input",
+"io.output",
+"io.lines",
+"io.type",
+"os.execute",
+"os.remove",
+"os.rename",
+"os.tmpname",
+"os.getenv",
+"os.exit",
+"os.clock",
+"os.date",
+"os.time",
+"os.difftime",
+"os.setlocale",
+"debug.getregistry",
+"debug.getmetatable",
+"debug.setmetatable",
+"debug.getfenv",
+"debug.setfenv",
+"debug.getinfo",
+"debug.getlocal",
+"debug.setlocal",
+"debug.getupvalue",
+"debug.setupvalue",
+"debug.upvalueid",
+"debug.upvaluejoin",
+"debug.getuservalue",
+"debug.setuservalue",
+"debug.sethook",
+"debug.gethook",
+"debug.debug",
+"debug.traceback",
+"jit.on",
+"jit.off",
+"jit.flush",
+"jit.status",
+"jit.security",
+"jit.attach",
+"jit.prngstate",
+"jit.util.funcinfo",
+"jit.util.funcbc",
+"jit.util.funck",
+"jit.util.funcuvname",
+"jit.util.traceinfo",
+"jit.util.traceir",
+"jit.util.tracek",
+"jit.util.tracesnap",
+"jit.util.tracemc",
+"jit.util.traceexitstub",
+"jit.util.ircalladdr",
+"jit.opt.start",
+"jit.profile.start",
+"jit.profile.stop",
+"jit.profile.dumpstack",
+"ffi.meta.__index",
+"ffi.meta.__newindex",
+"ffi.meta.__eq",
+"ffi.meta.__len",
+"ffi.meta.__lt",
+"ffi.meta.__le",
+"ffi.meta.__concat",
+"ffi.meta.__call",
+"ffi.meta.__add",
+"ffi.meta.__sub",
+"ffi.meta.__mul",
+"ffi.meta.__div",
+"ffi.meta.__mod",
+"ffi.meta.__pow",
+"ffi.meta.__unm",
+"ffi.meta.__tostring",
+"ffi.meta.__pairs",
+"ffi.meta.__ipairs",
+"ffi.clib.__index",
+"ffi.clib.__newindex",
+"ffi.clib.__gc",
+"ffi.callback.free",
+"ffi.callback.set",
+"ffi.cdef",
+"ffi.new",
+"ffi.cast",
+"ffi.typeof",
+"ffi.typeinfo",
+"ffi.istype",
+"ffi.sizeof",
+"ffi.alignof",
+"ffi.offsetof",
+"ffi.errno",
+"ffi.string",
+"ffi.copy",
+"ffi.fill",
+"ffi.abi",
+"ffi.metatype",
+"ffi.gc",
+"ffi.load",
+"buffer.method.free",
+"buffer.method.reset",
+"buffer.method.skip",
+"buffer.method.set",
+"buffer.method.put",
+"buffer.method.putf",
+"buffer.method.get",
+"buffer.method.putcdata",
+"buffer.method.reserve",
+"buffer.method.commit",
+"buffer.method.ref",
+"buffer.method.encode",
+"buffer.method.decode",
+"buffer.method.__gc",
+"buffer.method.__tostring",
+"buffer.method.__len",
+"buffer.new",
+"buffer.encode",
+"buffer.decode",
+},
+
+}
+
diff --git a/jit/vmdef_osx64.lua b/jit/vmdef_osx64.lua
index c8128e5..481f979 100644
--- a/jit/vmdef_osx64.lua
+++ b/jit/vmdef_osx64.lua
@@ -4,11 +4,11 @@ return {
bcnames = "ISLT ISGE ISLE ISGT ISEQV ISNEV ISEQS ISNES ISEQN ISNEN ISEQP ISNEP ISTC ISFC IST ISF ISTYPEISNUM MOV NOT UNM LEN ADDVN SUBVN MULVN DIVVN MODVN ADDNV SUBNV MULNV DIVNV MODNV ADDVV SUBVV MULVV DIVVV MODVV POW CAT KSTR KCDATAKSHORTKNUM KPRI KNIL UGET USETV USETS USETN USETP UCLO FNEW TNEW TDUP GGET GSET TGETV TGETS TGETB TGETR TSETV TSETS TSETB TSETM TSETR CALLM CALL CALLMTCALLT ITERC ITERN VARG ISNEXTRETM RET RET0 RET1 FORI JFORI FORL IFORL JFORL ITERL IITERLJITERLLOOP ILOOP JLOOP JMP FUNCF IFUNCFJFUNCFFUNCV IFUNCVJFUNCVFUNCC FUNCCW",
-irnames = "LT GE LE GT ULT UGE ULE UGT EQ NE ABC RETF NOP BASE PVAL GCSTEPHIOP LOOP USE PHI RENAMEPROF KPRI KINT KGC KPTR KKPTR KNULL KNUM KINT64KSLOT BNOT BSWAP BAND BOR BXOR BSHL BSHR BSAR BROL BROR ADD SUB MUL DIV MOD POW NEG ABS ATAN2 LDEXP MIN MAX FPMATHADDOV SUBOV MULOV AREF HREFK HREF NEWREFUREFO UREFC FREF STRREFLREF ALOAD HLOAD ULOAD FLOAD XLOAD SLOAD VLOAD ASTOREHSTOREUSTOREFSTOREXSTORESNEW XSNEW TNEW TDUP CNEW CNEWI BUFHDRBUFPUTBUFSTRTBAR OBAR XBAR CONV TOBIT TOSTR STRTO CALLN CALLA CALLL CALLS CALLXSCARG ",
+irnames = "LT GE LE GT ULT UGE ULE UGT EQ NE ABC RETF NOP BASE PVAL GCSTEPHIOP LOOP USE PHI RENAMEPROF KPRI KINT KGC KPTR KKPTR KNULL KNUM KINT64KSLOT BNOT BSWAP BAND BOR BXOR BSHL BSHR BSAR BROL BROR ADD SUB MUL DIV MOD POW NEG ABS LDEXP MIN MAX FPMATHADDOV SUBOV MULOV AREF HREFK HREF NEWREFUREFO UREFC FREF TMPREFSTRREFLREF ALOAD HLOAD ULOAD FLOAD XLOAD SLOAD VLOAD ALEN ASTOREHSTOREUSTOREFSTOREXSTORESNEW XSNEW TNEW TDUP CNEW CNEWI BUFHDRBUFPUTBUFSTRTBAR OBAR XBAR CONV TOBIT TOSTR STRTO CALLN CALLA CALLL CALLS CALLXSCARG ",
-irfpm = { [0]="floor", "ceil", "trunc", "sqrt", "exp", "exp2", "log", "log2", "log10", "sin", "cos", "tan", "other", },
+irfpm = { [0]="floor", "ceil", "trunc", "sqrt", "log", "log2", "other", },
-irfield = { [0]="str.len", "func.env", "func.pc", "func.ffid", "thread.env", "thread.exdata", "tab.meta", "tab.array", "tab.node", "tab.asize", "tab.hmask", "tab.nomm", "udata.meta", "udata.udtype", "udata.file", "cdata.ctypeid", "cdata.ptr", "cdata.int", "cdata.int64", "cdata.int64_4", },
+irfield = { [0]="str.len", "func.env", "func.pc", "func.ffid", "thread.env", "thread.exdata", "thread.exdata2", "tab.meta", "tab.array", "tab.node", "tab.asize", "tab.hmask", "tab.nomm", "udata.meta", "udata.udtype", "udata.file", "sbuf.w", "sbuf.e", "sbuf.b", "sbuf.l", "sbuf.ref", "sbuf.r", "cdata.ctypeid", "cdata.ptr", "cdata.int", "cdata.int64", "cdata.int64_4", },
ircall = {
[0]="lj_str_cmp",
@@ -35,22 +35,39 @@ ircall = {
"lj_buf_putstr_upper",
"lj_buf_putstr_rep",
"lj_buf_puttab",
+"lj_bufx_set",
+"lj_bufx_more",
+"lj_serialize_put",
+"lj_serialize_get",
+"lj_serialize_encode",
+"lj_serialize_decode",
"lj_buf_tostr",
"lj_tab_new_ah",
"lj_tab_new1",
"lj_tab_dup",
"lj_tab_clear",
"lj_tab_newkey",
+"lj_tab_keyindex",
+"lj_vm_next",
"lj_tab_len",
"lj_tab_clone",
"lj_tab_isarray",
"lj_tab_nkeys",
"lj_tab_isempty",
+"lj_tab_len_hint",
"lj_gc_step_jit",
"lj_gc_barrieruv",
"lj_mem_newgco",
-"lj_math_random_step",
+"lj_prng_u64d",
"lj_vm_modi",
+"log10",
+"exp",
+"sin",
+"cos",
+"tan",
+"asin",
+"acos",
+"atan",
"sinh",
"cosh",
"tanh",
@@ -61,15 +78,8 @@ ircall = {
"lj_vm_ceil",
"lj_vm_trunc",
"sqrt",
-"exp",
-"lj_vm_exp2",
"log",
"lj_vm_log2",
-"log10",
-"sin",
-"cos",
-"tan",
-"lj_vm_powi",
"pow",
"atan2",
"ldexp",
@@ -199,6 +209,7 @@ ffnames = {
"coroutine.wrap_aux",
"coroutine.wrap",
"thread.exdata",
+"thread.exdata2",
"math.abs",
"math.floor",
"math.ceil",
@@ -315,6 +326,7 @@ ffnames = {
"jit.off",
"jit.flush",
"jit.status",
+"jit.security",
"jit.attach",
"jit.prngstate",
"jit.util.funcinfo",
@@ -372,6 +384,25 @@ ffnames = {
"ffi.metatype",
"ffi.gc",
"ffi.load",
+"buffer.method.free",
+"buffer.method.reset",
+"buffer.method.skip",
+"buffer.method.set",
+"buffer.method.put",
+"buffer.method.putf",
+"buffer.method.get",
+"buffer.method.putcdata",
+"buffer.method.reserve",
+"buffer.method.commit",
+"buffer.method.ref",
+"buffer.method.encode",
+"buffer.method.decode",
+"buffer.method.__gc",
+"buffer.method.__tostring",
+"buffer.method.__len",
+"buffer.new",
+"buffer.encode",
+"buffer.decode",
},
}
diff --git a/jit/zone.lua b/jit/zone.lua
index 9435785..1308cb7 100644
--- a/jit/zone.lua
+++ b/jit/zone.lua
@@ -1,7 +1,7 @@
----------------------------------------------------------------------------
-- LuaJIT profiler zones.
--
--- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
+-- Copyright (C) 2005-2022 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h
----------------------------------------------------------------------------
--