diff options
Diffstat (limited to 'libs/luajit-cmake/luajit/src/jit')
19 files changed, 6406 insertions, 0 deletions
diff --git a/libs/luajit-cmake/luajit/src/jit/.gitignore b/libs/luajit-cmake/luajit/src/jit/.gitignore new file mode 100644 index 0000000..500e285 --- /dev/null +++ b/libs/luajit-cmake/luajit/src/jit/.gitignore @@ -0,0 +1 @@ +vmdef.lua diff --git a/libs/luajit-cmake/luajit/src/jit/bc.lua b/libs/luajit-cmake/luajit/src/jit/bc.lua new file mode 100644 index 0000000..8d0844c --- /dev/null +++ b/libs/luajit-cmake/luajit/src/jit/bc.lua @@ -0,0 +1,190 @@ +---------------------------------------------------------------------------- +-- LuaJIT bytecode listing module. +-- +-- Copyright (C) 2005-2022 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module lists the bytecode of a Lua function. If it's loaded by -jbc +-- it hooks into the parser and lists all functions of a chunk as they +-- are parsed. +-- +-- Example usage: +-- +-- luajit -jbc -e 'local x=0; for i=1,1e6 do x=x+i end; print(x)' +-- luajit -jbc=- foo.lua +-- luajit -jbc=foo.list foo.lua +-- +-- Default output is to stderr. To redirect the output to a file, pass a +-- filename as an argument (use '-' for stdout) or set the environment +-- variable LUAJIT_LISTFILE. The file is overwritten every time the module +-- is started. +-- +-- This module can also be used programmatically: +-- +-- local bc = require("jit.bc") +-- +-- local function foo() print("hello") end +-- +-- bc.dump(foo) --> -- BYTECODE -- [...] +-- print(bc.line(foo, 2)) --> 0002 KSTR 1 1 ; "hello" +-- +-- local out = { +-- -- Do something with each line: +-- write = function(t, ...) io.write(...) end, +-- close = function(t) end, +-- flush = function(t) end, +-- } +-- bc.dump(foo, out) +-- +------------------------------------------------------------------------------ + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local jutil = require("jit.util") +local vmdef = require("jit.vmdef") +local bit = require("bit") +local sub, gsub, format = string.sub, string.gsub, string.format +local byte, band, shr = string.byte, bit.band, bit.rshift +local funcinfo, funcbc, funck = jutil.funcinfo, jutil.funcbc, jutil.funck +local funcuvname = jutil.funcuvname +local bcnames = vmdef.bcnames +local stdout, stderr = io.stdout, io.stderr + +------------------------------------------------------------------------------ + +local function ctlsub(c) + if c == "\n" then return "\\n" + elseif c == "\r" then return "\\r" + elseif c == "\t" then return "\\t" + else return format("\\%03d", byte(c)) + end +end + +-- Return one bytecode line. +local function bcline(func, pc, prefix) + local ins, m = funcbc(func, pc) + if not ins then return end + local ma, mb, mc = band(m, 7), band(m, 15*8), band(m, 15*128) + local a = band(shr(ins, 8), 0xff) + local oidx = 6*band(ins, 0xff) + local op = sub(bcnames, oidx+1, oidx+6) + local s = format("%04d %s %-6s %3s ", + pc, prefix or " ", op, ma == 0 and "" or a) + local d = shr(ins, 16) + if mc == 13*128 then -- BCMjump + return format("%s=> %04d\n", s, pc+d-0x7fff) + end + if mb ~= 0 then + d = band(d, 0xff) + elseif mc == 0 then + return s.."\n" + end + local kc + if mc == 10*128 then -- BCMstr + kc = funck(func, -d-1) + kc = format(#kc > 40 and '"%.40s"~' or '"%s"', gsub(kc, "%c", ctlsub)) + elseif mc == 9*128 then -- BCMnum + kc = funck(func, d) + if op == "TSETM " then kc = kc - 2^52 end + elseif mc == 12*128 then -- BCMfunc + local fi = funcinfo(funck(func, -d-1)) + if fi.ffid then + kc = vmdef.ffnames[fi.ffid] + else + kc = fi.loc + end + elseif mc == 5*128 then -- BCMuv + kc = funcuvname(func, d) + end + if ma == 5 then -- BCMuv + local ka = funcuvname(func, a) + if kc then kc = ka.." ; "..kc else kc = ka end + end + if mb ~= 0 then + local b = shr(ins, 24) + if kc then return format("%s%3d %3d ; %s\n", s, b, d, kc) end + return format("%s%3d %3d\n", s, b, d) + end + if kc then return format("%s%3d ; %s\n", s, d, kc) end + if mc == 7*128 and d > 32767 then d = d - 65536 end -- BCMlits + return format("%s%3d\n", s, d) +end + +-- Collect branch targets of a function. +local function bctargets(func) + local target = {} + for pc=1,1000000000 do + local ins, m = funcbc(func, pc) + if not ins then break end + if band(m, 15*128) == 13*128 then target[pc+shr(ins, 16)-0x7fff] = true end + end + return target +end + +-- Dump bytecode instructions of a function. +local function bcdump(func, out, all) + if not out then out = stdout end + local fi = funcinfo(func) + if all and fi.children then + for n=-1,-1000000000,-1 do + local k = funck(func, n) + if not k then break end + if type(k) == "proto" then bcdump(k, out, true) end + end + end + out:write(format("-- BYTECODE -- %s-%d\n", fi.loc, fi.lastlinedefined)) + local target = bctargets(func) + for pc=1,1000000000 do + local s = bcline(func, pc, target[pc] and "=>") + if not s then break end + out:write(s) + end + out:write("\n") + out:flush() +end + +------------------------------------------------------------------------------ + +-- Active flag and output file handle. +local active, out + +-- List handler. +local function h_list(func) + return bcdump(func, out) +end + +-- Detach list handler. +local function bclistoff() + if active then + active = false + jit.attach(h_list) + if out and out ~= stdout and out ~= stderr then out:close() end + out = nil + end +end + +-- Open the output file and attach list handler. +local function bcliston(outfile) + if active then bclistoff() end + if not outfile then outfile = os.getenv("LUAJIT_LISTFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stderr + end + jit.attach(h_list, "bc") + active = true +end + +-- Public module functions. +return { + line = bcline, + dump = bcdump, + targets = bctargets, + on = bcliston, + off = bclistoff, + start = bcliston -- For -j command line option. +} + diff --git a/libs/luajit-cmake/luajit/src/jit/bcsave.lua b/libs/luajit-cmake/luajit/src/jit/bcsave.lua new file mode 100644 index 0000000..90fe9da --- /dev/null +++ b/libs/luajit-cmake/luajit/src/jit/bcsave.lua @@ -0,0 +1,705 @@ +---------------------------------------------------------------------------- +-- LuaJIT module to save/list bytecode. +-- +-- Copyright (C) 2005-2022 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module saves or lists the bytecode for an input file. +-- It's run by the -b command line option. +-- +------------------------------------------------------------------------------ + +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local bit = require("bit") + +-- Symbol name prefix for LuaJIT bytecode. +local LJBC_PREFIX = "luaJIT_BC_" + +local type, assert = type, assert +local format = string.format +local tremove, tconcat = table.remove, table.concat + +------------------------------------------------------------------------------ + +local function usage() + io.stderr:write[[ +Save LuaJIT bytecode: luajit -b[options] input output + -l Only list bytecode. + -s Strip debug info (default). + -g Keep debug info. + -n name Set module name (default: auto-detect from input name). + -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. + +File types: c h obj o raw (default) +]] + os.exit(1) +end + +local function check(ok, ...) + if ok then return ok, ... end + io.stderr:write("luajit: ", ...) + io.stderr:write("\n") + os.exit(1) +end + +local function readfile(ctx, input) + if type(input) == "function" then return input end + 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) + if name == "-" then return io.stdout end + 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 = { + raw = "raw", c = "c", h = "h", o = "obj", obj = "obj", +} + +local map_arch = { + x86 = { e = "le", b = 32, m = 3, p = 0x14c, }, + x64 = { e = "le", b = 64, m = 62, p = 0x8664, }, + arm = { e = "le", b = 32, m = 40, p = 0x1c0, }, + arm64 = { e = "le", b = 64, m = 183, p = 0xaa64, }, + arm64be = { e = "be", b = 64, m = 183, }, + ppc = { e = "be", b = 32, m = 20, }, + mips = { e = "be", b = 32, m = 8, f = 0x50001006, }, + mipsel = { e = "le", b = 32, m = 8, f = 0x50001006, }, + mips64 = { e = "be", b = 64, m = 8, f = 0x80000007, }, + mips64el = { e = "le", b = 64, m = 8, f = 0x80000007, }, + mips64r6 = { e = "be", b = 64, m = 8, f = 0xa0000407, }, + mips64r6el = { e = "le", b = 64, m = 8, f = 0xa0000407, }, +} + +local map_os = { + linux = true, windows = true, osx = true, freebsd = true, netbsd = true, + openbsd = true, dragonfly = true, solaris = true, +} + +local function checkarg(str, map, err) + str = str:lower() + local s = check(map[str], "unknown ", err) + return type(s) == "string" and s or str +end + +local function detecttype(str) + local ext = str:lower():match("%.(%a+)$") + return map_type[ext] or "raw" +end + +local function checkmodname(str) + check(str:match("^[%w_.%-]+$"), "bad module name") + return str:gsub("[%.%-]", "_") +end + +local function detectmodname(str) + if type(str) == "string" then + local tail = str:match("[^/\\]+$") + if tail then str = tail end + local head = str:match("^(.*)%.[^.]*$") + if head then str = head end + str = str:match("^[%w_.%-]+") + else + str = nil + end + check(str, "cannot derive module name, use -n name") + return str:gsub("[%.%-]", "_") +end + +------------------------------------------------------------------------------ + +local function bcsave_tail(fp, output, s) + local ok, err = fp:write(s) + if ok and output ~= "-" then ok, err = fp:close() end + check(ok, "cannot write ", output, ": ", err) +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 + +local function bcsave_c(ctx, output, s) + local fp = savefile(output, "w") + if ctx.type == "c" then + fp:write(format([[ +#ifdef __cplusplus +extern "C" +#endif +#ifdef _WIN32 +__declspec(dllexport) +#endif +const unsigned char %s%s[] = { +]], LJBC_PREFIX, ctx.modname)) + else + fp:write(format([[ +#define %s%s_SIZE %d +static const unsigned char %s%s[] = { +]], LJBC_PREFIX, ctx.modname, #s, LJBC_PREFIX, ctx.modname)) + end + local t, n, m = {}, 0, 0 + for i=1,#s do + local b = tostring(string.byte(s, i)) + m = m + #b + 1 + if m > 78 then + fp:write(tconcat(t, ",", 1, n), ",\n") + n, m = 0, #b + 1 + end + n = n + 1 + t[n] = b + end + bcsave_tail(fp, output, tconcat(t, ",", 1, n).."\n};\n") +end + +local function bcsave_elfobj(ctx, output, s, ffi) + ffi.cdef[[ +typedef struct { + uint8_t emagic[4], eclass, eendian, eversion, eosabi, eabiversion, epad[7]; + uint16_t type, machine; + uint32_t version; + uint32_t entry, phofs, shofs; + uint32_t flags; + uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstridx; +} ELF32header; +typedef struct { + uint8_t emagic[4], eclass, eendian, eversion, eosabi, eabiversion, epad[7]; + uint16_t type, machine; + uint32_t version; + uint64_t entry, phofs, shofs; + uint32_t flags; + uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstridx; +} ELF64header; +typedef struct { + uint32_t name, type, flags, addr, ofs, size, link, info, align, entsize; +} ELF32sectheader; +typedef struct { + uint32_t name, type; + uint64_t flags, addr, ofs, size; + uint32_t link, info; + uint64_t align, entsize; +} ELF64sectheader; +typedef struct { + uint32_t name, value, size; + uint8_t info, other; + uint16_t sectidx; +} ELF32symbol; +typedef struct { + uint32_t name; + uint8_t info, other; + uint16_t sectidx; + uint64_t value, size; +} ELF64symbol; +typedef struct { + ELF32header hdr; + ELF32sectheader sect[6]; + ELF32symbol sym[2]; + uint8_t space[4096]; +} ELF32obj; +typedef struct { + ELF64header hdr; + ELF64sectheader sect[6]; + ELF64symbol sym[2]; + uint8_t space[4096]; +} ELF64obj; +]] + local symname = LJBC_PREFIX..ctx.modname + local ai = assert(map_arch[ctx.arch]) + local is64, isbe = ai.b == 64, ai.e == "be" + + -- Handle different host/target endianess. + local function f32(x) return x end + local f16, fofs = f32, f32 + if ffi.abi("be") ~= isbe then + f32 = bit.bswap + function f16(x) return bit.rshift(bit.bswap(x), 16) end + if is64 then + local two32 = ffi.cast("int64_t", 2^32) + function fofs(x) return bit.bswap(x)*two32 end + else + fofs = f32 + end + end + + -- Create ELF object and fill in header. + local o = ffi.new(is64 and "ELF64obj" or "ELF32obj") + local hdr = o.hdr + if ctx.os == "bsd" or ctx.os == "other" then -- Determine native hdr.eosabi. + local bf = assert(io.open("/bin/ls", "rb")) + local bs = bf:read(9) + bf:close() + ffi.copy(o, bs, 9) + check(hdr.emagic[0] == 127, "no support for writing native object files") + else + hdr.emagic = "\127ELF" + hdr.eosabi = ({ freebsd=9, netbsd=2, openbsd=12, solaris=6 })[ctx.os] or 0 + end + hdr.eclass = is64 and 2 or 1 + hdr.eendian = isbe and 2 or 1 + hdr.eversion = 1 + hdr.type = f16(1) + hdr.machine = f16(ai.m) + hdr.flags = f32(ai.f or 0) + hdr.version = f32(1) + hdr.shofs = fofs(ffi.offsetof(o, "sect")) + hdr.ehsize = f16(ffi.sizeof(hdr)) + hdr.shentsize = f16(ffi.sizeof(o.sect[0])) + hdr.shnum = f16(6) + hdr.shstridx = f16(2) + + -- Fill in sections and symbols. + local sofs, ofs = ffi.offsetof(o, "space"), 1 + for i,name in ipairs{ + ".symtab", ".shstrtab", ".strtab", ".rodata", ".note.GNU-stack", + } do + local sect = o.sect[i] + sect.align = fofs(1) + sect.name = f32(ofs) + ffi.copy(o.space+ofs, name) + ofs = ofs + #name+1 + end + o.sect[1].type = f32(2) -- .symtab + o.sect[1].link = f32(3) + o.sect[1].info = f32(1) + o.sect[1].align = fofs(8) + o.sect[1].ofs = fofs(ffi.offsetof(o, "sym")) + o.sect[1].entsize = fofs(ffi.sizeof(o.sym[0])) + o.sect[1].size = fofs(ffi.sizeof(o.sym)) + o.sym[1].name = f32(1) + o.sym[1].sectidx = f16(4) + o.sym[1].size = fofs(#s) + o.sym[1].info = 17 + o.sect[2].type = f32(3) -- .shstrtab + o.sect[2].ofs = fofs(sofs) + o.sect[2].size = fofs(ofs) + o.sect[3].type = f32(3) -- .strtab + o.sect[3].ofs = fofs(sofs + ofs) + o.sect[3].size = fofs(#symname+2) + ffi.copy(o.space+ofs+1, symname) + ofs = ofs + #symname + 2 + o.sect[4].type = f32(1) -- .rodata + o.sect[4].flags = fofs(2) + o.sect[4].ofs = fofs(sofs + ofs) + o.sect[4].size = fofs(#s) + o.sect[5].type = f32(1) -- .note.GNU-stack + o.sect[5].ofs = fofs(sofs + ofs + #s) + + -- Write ELF object file. + local fp = savefile(output, "wb") + fp:write(ffi.string(o, ffi.sizeof(o)-4096+ofs)) + bcsave_tail(fp, output, s) +end + +local function bcsave_peobj(ctx, output, s, ffi) + ffi.cdef[[ +typedef struct { + uint16_t arch, nsects; + uint32_t time, symtabofs, nsyms; + uint16_t opthdrsz, flags; +} PEheader; +typedef struct { + char name[8]; + uint32_t vsize, vaddr, size, ofs, relocofs, lineofs; + uint16_t nreloc, nline; + uint32_t flags; +} PEsection; +typedef struct __attribute((packed)) { + union { + char name[8]; + uint32_t nameref[2]; + }; + uint32_t value; + int16_t sect; + uint16_t type; + uint8_t scl, naux; +} PEsym; +typedef struct __attribute((packed)) { + uint32_t size; + uint16_t nreloc, nline; + uint32_t cksum; + uint16_t assoc; + uint8_t comdatsel, unused[3]; +} PEsymaux; +typedef struct { + PEheader hdr; + PEsection sect[2]; + // Must be an even number of symbol structs. + PEsym sym0; + PEsymaux sym0aux; + PEsym sym1; + PEsymaux sym1aux; + PEsym sym2; + PEsym sym3; + uint32_t strtabsize; + uint8_t space[4096]; +} PEobj; +]] + local symname = LJBC_PREFIX..ctx.modname + local ai = assert(map_arch[ctx.arch]) + local is64 = ai.b == 64 + local symexport = " /EXPORT:"..symname..",DATA " + + -- The file format is always little-endian. Swap if the host is big-endian. + local function f32(x) return x end + local f16 = f32 + if ffi.abi("be") then + f32 = bit.bswap + function f16(x) return bit.rshift(bit.bswap(x), 16) end + end + + -- Create PE object and fill in header. + local o = ffi.new("PEobj") + local hdr = o.hdr + hdr.arch = f16(assert(ai.p)) + hdr.nsects = f16(2) + hdr.symtabofs = f32(ffi.offsetof(o, "sym0")) + hdr.nsyms = f32(6) + + -- Fill in sections and symbols. + o.sect[0].name = ".drectve" + o.sect[0].size = f32(#symexport) + o.sect[0].flags = f32(0x00100a00) + o.sym0.sect = f16(1) + o.sym0.scl = 3 + o.sym0.name = ".drectve" + o.sym0.naux = 1 + o.sym0aux.size = f32(#symexport) + o.sect[1].name = ".rdata" + o.sect[1].size = f32(#s) + o.sect[1].flags = f32(0x40300040) + o.sym1.sect = f16(2) + o.sym1.scl = 3 + o.sym1.name = ".rdata" + o.sym1.naux = 1 + o.sym1aux.size = f32(#s) + o.sym2.sect = f16(2) + o.sym2.scl = 2 + o.sym2.nameref[1] = f32(4) + o.sym3.sect = f16(-1) + o.sym3.scl = 2 + o.sym3.value = f32(1) + o.sym3.name = "@feat.00" -- Mark as SafeSEH compliant. + ffi.copy(o.space, symname) + local ofs = #symname + 1 + o.strtabsize = f32(ofs + 4) + o.sect[0].ofs = f32(ffi.offsetof(o, "space") + ofs) + ffi.copy(o.space + ofs, symexport) + ofs = ofs + #symexport + o.sect[1].ofs = f32(ffi.offsetof(o, "space") + ofs) + + -- Write PE object file. + local fp = savefile(output, "wb") + fp:write(ffi.string(o, ffi.sizeof(o)-4096+ofs)) + bcsave_tail(fp, output, s) +end + +local function bcsave_machobj(ctx, output, s, ffi) + ffi.cdef[[ +typedef struct +{ + uint32_t magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags; +} mach_header; +typedef struct +{ + mach_header; uint32_t reserved; +} mach_header_64; +typedef struct { + uint32_t cmd, cmdsize; + char segname[16]; + uint32_t vmaddr, vmsize, fileoff, filesize; + uint32_t maxprot, initprot, nsects, flags; +} mach_segment_command; +typedef struct { + uint32_t cmd, cmdsize; + char segname[16]; + uint64_t vmaddr, vmsize, fileoff, filesize; + uint32_t maxprot, initprot, nsects, flags; +} mach_segment_command_64; +typedef struct { + char sectname[16], segname[16]; + uint32_t addr, size; + uint32_t offset, align, reloff, nreloc, flags; + uint32_t reserved1, reserved2; +} mach_section; +typedef struct { + char sectname[16], segname[16]; + uint64_t addr, size; + uint32_t offset, align, reloff, nreloc, flags; + uint32_t reserved1, reserved2, reserved3; +} mach_section_64; +typedef struct { + uint32_t cmd, cmdsize, symoff, nsyms, stroff, strsize; +} mach_symtab_command; +typedef struct { + int32_t strx; + uint8_t type, sect; + int16_t desc; + uint32_t value; +} mach_nlist; +typedef struct { + int32_t strx; + uint8_t type, sect; + uint16_t desc; + uint64_t value; +} mach_nlist_64; +typedef struct +{ + int32_t magic, nfat_arch; +} mach_fat_header; +typedef struct +{ + int32_t cputype, cpusubtype, offset, size, align; +} mach_fat_arch; +typedef struct { + struct { + mach_header hdr; + mach_segment_command seg; + mach_section sec; + mach_symtab_command sym; + } arch[1]; + mach_nlist sym_entry; + uint8_t space[4096]; +} mach_obj; +typedef struct { + struct { + mach_header_64 hdr; + mach_segment_command_64 seg; + mach_section_64 sec; + mach_symtab_command sym; + } arch[1]; + mach_nlist_64 sym_entry; + uint8_t space[4096]; +} mach_obj_64; +typedef struct { + mach_fat_header fat; + mach_fat_arch fat_arch[2]; + struct { + mach_header hdr; + mach_segment_command seg; + mach_section sec; + mach_symtab_command sym; + } arch[2]; + 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" + if ctx.arch == "x64" then + is64, align, mobj = true, 8, "mach_obj_64" + 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_64" + else + check(ctx.arch == "x86", "unsupported architecture for OSX") + end + local function aligned(v, a) return bit.band(v+a-1, -a) end + local be32 = bit.bswap -- Mach-O FAT is BE, supported archs are LE. + + -- Create Mach-O object and fill in header. + local o = ffi.new(mobj) + local mach_size = aligned(ffi.offsetof(o, "space")+#symname+2, align) + local cputype = ({ x86={7}, x64={0x01000007}, arm={7,12}, arm64={0x01000007,0x0100000c} })[ctx.arch] + local cpusubtype = ({ x86={3}, x64={3}, arm={3,9}, arm64={3,0} })[ctx.arch] + if isfat then + o.fat.magic = be32(0xcafebabe) + o.fat.nfat_arch = be32(#cpusubtype) + end + + -- Fill in sections and symbols. + for i=0,#cpusubtype-1 do + local ofs = 0 + if isfat then + local a = o.fat_arch[i] + a.cputype = be32(cputype[i+1]) + a.cpusubtype = be32(cpusubtype[i+1]) + -- Subsequent slices overlap each other to share data. + ofs = ffi.offsetof(o, "arch") + i*ffi.sizeof(o.arch[0]) + a.offset = be32(ofs) + a.size = be32(mach_size-ofs+#s) + end + local a = o.arch[i] + a.hdr.magic = is64 and 0xfeedfacf or 0xfeedface + a.hdr.cputype = cputype[i+1] + a.hdr.cpusubtype = cpusubtype[i+1] + a.hdr.filetype = 1 + a.hdr.ncmds = 2 + a.hdr.sizeofcmds = ffi.sizeof(a.seg)+ffi.sizeof(a.sec)+ffi.sizeof(a.sym) + a.seg.cmd = is64 and 0x19 or 0x1 + a.seg.cmdsize = ffi.sizeof(a.seg)+ffi.sizeof(a.sec) + a.seg.vmsize = #s + a.seg.fileoff = mach_size-ofs + a.seg.filesize = #s + a.seg.maxprot = 1 + a.seg.initprot = 1 + a.seg.nsects = 1 + ffi.copy(a.sec.sectname, "__data") + ffi.copy(a.sec.segname, "__DATA") + a.sec.size = #s + a.sec.offset = mach_size-ofs + a.sym.cmd = 2 + a.sym.cmdsize = ffi.sizeof(a.sym) + a.sym.symoff = ffi.offsetof(o, "sym_entry")-ofs + a.sym.nsyms = 1 + a.sym.stroff = ffi.offsetof(o, "sym_entry")+ffi.sizeof(o.sym_entry)-ofs + a.sym.strsize = aligned(#symname+2, align) + end + o.sym_entry.type = 0xf + o.sym_entry.sect = 1 + o.sym_entry.strx = 1 + ffi.copy(o.space+1, symname) + + -- Write Macho-O object file. + local fp = savefile(output, "wb") + fp:write(ffi.string(o, mach_size)) + bcsave_tail(fp, output, s) +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 + return bcsave_machobj(ctx, output, s, ffi) + else + return bcsave_elfobj(ctx, output, s, ffi) + end +end + +------------------------------------------------------------------------------ + +local function bclist(ctx, input, output) + local f = readfile(ctx, input) + require("jit.bc").dump(f, savefile(output, "w"), true) +end + +local function bcsave(ctx, input, output) + local f = readfile(ctx, input) + local s = string.dump(f, ctx.strip) + local t = ctx.type + if not t then + t = detecttype(output) + ctx.type = t + end + if t == "raw" then + bcsave_raw(output, s) + else + if not ctx.modname then ctx.modname = detectmodname(input) end + if t == "obj" then + bcsave_obj(ctx, output, s) + else + bcsave_c(ctx, output, s) + end + end +end + +local function docmd(...) + local arg = {...} + local n = 1 + local list = false + local ctx = { + strip = true, arch = jit.arch, os = jit.os:lower(), + type = false, modname = false, + } + while n <= #arg do + local a = arg[n] + if type(a) == "string" and a:sub(1, 1) == "-" and a ~= "-" then + tremove(arg, n) + if a == "--" then break end + for m=2,#a do + local opt = a:sub(m, m) + if opt == "l" then + list = true + elseif opt == "s" then + ctx.strip = true + elseif opt == "g" then + ctx.strip = false + else + if arg[n] == nil or m ~= #a then usage() end + if opt == "e" then + if n ~= 1 then usage() end + arg[1] = check(loadstring(arg[1])) + elseif opt == "n" then + ctx.modname = checkmodname(tremove(arg, n)) + elseif opt == "t" then + ctx.type = checkarg(tremove(arg, n), map_type, "file type") + elseif opt == "a" then + 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 + end + end + else + n = n + 1 + end + end + if list then + if #arg == 0 or #arg > 2 then usage() end + bclist(ctx, arg[1], arg[2] or "-") + else + if #arg ~= 2 then usage() end + bcsave(ctx, arg[1], arg[2]) + end +end + +------------------------------------------------------------------------------ + +-- Public module functions. +return { + start = docmd -- Process -b command line option. +} + diff --git a/libs/luajit-cmake/luajit/src/jit/dis_arm.lua b/libs/luajit-cmake/luajit/src/jit/dis_arm.lua new file mode 100644 index 0000000..18ab68d --- /dev/null +++ b/libs/luajit-cmake/luajit/src/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/libs/luajit-cmake/luajit/src/jit/dis_arm64.lua b/libs/luajit-cmake/luajit/src/jit/dis_arm64.lua new file mode 100644 index 0000000..531584a --- /dev/null +++ b/libs/luajit-cmake/luajit/src/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 <R>. + 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/libs/luajit-cmake/luajit/src/jit/dis_arm64be.lua b/libs/luajit-cmake/luajit/src/jit/dis_arm64be.lua new file mode 100644 index 0000000..7337f5b --- /dev/null +++ b/libs/luajit-cmake/luajit/src/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/libs/luajit-cmake/luajit/src/jit/dis_mips.lua b/libs/luajit-cmake/luajit/src/jit/dis_mips.lua new file mode 100644 index 0000000..05dc30f --- /dev/null +++ b/libs/luajit-cmake/luajit/src/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/libs/luajit-cmake/luajit/src/jit/dis_mips64.lua b/libs/luajit-cmake/luajit/src/jit/dis_mips64.lua new file mode 100644 index 0000000..1236e52 --- /dev/null +++ b/libs/luajit-cmake/luajit/src/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/libs/luajit-cmake/luajit/src/jit/dis_mips64el.lua b/libs/luajit-cmake/luajit/src/jit/dis_mips64el.lua new file mode 100644 index 0000000..7c478d2 --- /dev/null +++ b/libs/luajit-cmake/luajit/src/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/libs/luajit-cmake/luajit/src/jit/dis_mips64r6.lua b/libs/luajit-cmake/luajit/src/jit/dis_mips64r6.lua new file mode 100644 index 0000000..c5789ce --- /dev/null +++ b/libs/luajit-cmake/luajit/src/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/libs/luajit-cmake/luajit/src/jit/dis_mips64r6el.lua b/libs/luajit-cmake/luajit/src/jit/dis_mips64r6el.lua new file mode 100644 index 0000000..f67f624 --- /dev/null +++ b/libs/luajit-cmake/luajit/src/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/libs/luajit-cmake/luajit/src/jit/dis_mipsel.lua b/libs/luajit-cmake/luajit/src/jit/dis_mipsel.lua new file mode 100644 index 0000000..a4fa6c6 --- /dev/null +++ b/libs/luajit-cmake/luajit/src/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/libs/luajit-cmake/luajit/src/jit/dis_ppc.lua b/libs/luajit-cmake/luajit/src/jit/dis_ppc.lua new file mode 100644 index 0000000..8f65f25 --- /dev/null +++ b/libs/luajit-cmake/luajit/src/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/libs/luajit-cmake/luajit/src/jit/dis_x64.lua b/libs/luajit-cmake/luajit/src/jit/dis_x64.lua new file mode 100644 index 0000000..d076c6a --- /dev/null +++ b/libs/luajit-cmake/luajit/src/jit/dis_x64.lua @@ -0,0 +1,17 @@ +---------------------------------------------------------------------------- +-- LuaJIT x64 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 64 bit functions from the combined +-- x86/x64 disassembler module. All the interesting stuff is there. +------------------------------------------------------------------------------ + +local dis_x86 = require((string.match(..., ".*%.") or "").."dis_x86") +return { + create = dis_x86.create64, + disass = dis_x86.disass64, + regname = dis_x86.regname64 +} + diff --git a/libs/luajit-cmake/luajit/src/jit/dis_x86.lua b/libs/luajit-cmake/luajit/src/jit/dis_x86.lua new file mode 100644 index 0000000..84492ff --- /dev/null +++ b/libs/luajit-cmake/luajit/src/jit/dis_x86.lua @@ -0,0 +1,953 @@ +---------------------------------------------------------------------------- +-- LuaJIT x86/x64 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. +-- +-- Sending small code snippets to an external disassembler and mixing the +-- output with our own stuff was too fragile. So I had to bite the bullet +-- and write yet another x86 disassembler. Oh well ... +-- +-- The output format is very similar to what ndisasm generates. But it has +-- been developed independently by looking at the opcode tables from the +-- Intel and AMD manuals. The supported instruction set is quite extensive +-- and reflects what a current generation Intel or AMD CPU implements in +-- 32 bit and 64 bit mode. Yes, this includes MMX, SSE, SSE2, SSE3, SSSE3, +-- SSE4.1, SSE4.2, SSE4a, AVX, AVX2 and even privileged and hypervisor +-- (VMX/SVM) instructions. +-- +-- Notes: +-- * The (useless) a16 prefix, 3DNow and pre-586 opcodes are unsupported. +-- * No attempt at optimization has been made -- it's fast enough for my needs. +------------------------------------------------------------------------------ + +local type = type +local sub, byte, format = string.sub, string.byte, string.format +local match, gmatch, gsub = string.match, string.gmatch, string.gsub +local lower, rep = string.lower, string.rep +local bit = require("bit") +local tohex = bit.tohex + +-- Map for 1st opcode byte in 32 bit mode. Ugly? Well ... read on. +local map_opc1_32 = { +--0x +[0]="addBmr","addVmr","addBrm","addVrm","addBai","addVai","push es","pop es", +"orBmr","orVmr","orBrm","orVrm","orBai","orVai","push cs","opc2*", +--1x +"adcBmr","adcVmr","adcBrm","adcVrm","adcBai","adcVai","push ss","pop ss", +"sbbBmr","sbbVmr","sbbBrm","sbbVrm","sbbBai","sbbVai","push ds","pop ds", +--2x +"andBmr","andVmr","andBrm","andVrm","andBai","andVai","es:seg","daa", +"subBmr","subVmr","subBrm","subVrm","subBai","subVai","cs:seg","das", +--3x +"xorBmr","xorVmr","xorBrm","xorVrm","xorBai","xorVai","ss:seg","aaa", +"cmpBmr","cmpVmr","cmpBrm","cmpVrm","cmpBai","cmpVai","ds:seg","aas", +--4x +"incVR","incVR","incVR","incVR","incVR","incVR","incVR","incVR", +"decVR","decVR","decVR","decVR","decVR","decVR","decVR","decVR", +--5x +"pushUR","pushUR","pushUR","pushUR","pushUR","pushUR","pushUR","pushUR", +"popUR","popUR","popUR","popUR","popUR","popUR","popUR","popUR", +--6x +"sz*pushaw,pusha","sz*popaw,popa","boundVrm","arplWmr", +"fs:seg","gs:seg","o16:","a16", +"pushUi","imulVrmi","pushBs","imulVrms", +"insb","insVS","outsb","outsVS", +--7x +"joBj","jnoBj","jbBj","jnbBj","jzBj","jnzBj","jbeBj","jaBj", +"jsBj","jnsBj","jpeBj","jpoBj","jlBj","jgeBj","jleBj","jgBj", +--8x +"arith!Bmi","arith!Vmi","arith!Bmi","arith!Vms", +"testBmr","testVmr","xchgBrm","xchgVrm", +"movBmr","movVmr","movBrm","movVrm", +"movVmg","leaVrm","movWgm","popUm", +--9x +"nop*xchgVaR|pause|xchgWaR|repne nop","xchgVaR","xchgVaR","xchgVaR", +"xchgVaR","xchgVaR","xchgVaR","xchgVaR", +"sz*cbw,cwde,cdqe","sz*cwd,cdq,cqo","call farViw","wait", +"sz*pushfw,pushf","sz*popfw,popf","sahf","lahf", +--Ax +"movBao","movVao","movBoa","movVoa", +"movsb","movsVS","cmpsb","cmpsVS", +"testBai","testVai","stosb","stosVS", +"lodsb","lodsVS","scasb","scasVS", +--Bx +"movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi", +"movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI", +--Cx +"shift!Bmu","shift!Vmu","retBw","ret","vex*3$lesVrm","vex*2$ldsVrm","movBmi","movVmi", +"enterBwu","leave","retfBw","retf","int3","intBu","into","iretVS", +--Dx +"shift!Bm1","shift!Vm1","shift!Bmc","shift!Vmc","aamBu","aadBu","salc","xlatb", +"fp*0","fp*1","fp*2","fp*3","fp*4","fp*5","fp*6","fp*7", +--Ex +"loopneBj","loopeBj","loopBj","sz*jcxzBj,jecxzBj,jrcxzBj", +"inBau","inVau","outBua","outVua", +"callVj","jmpVj","jmp farViw","jmpBj","inBad","inVad","outBda","outVda", +--Fx +"lock:","int1","repne:rep","rep:","hlt","cmc","testb!Bm","testv!Vm", +"clc","stc","cli","sti","cld","std","incb!Bm","incd!Vm", +} +assert(#map_opc1_32 == 255) + +-- Map for 1st opcode byte in 64 bit mode (overrides only). +local map_opc1_64 = setmetatable({ + [0x06]=false, [0x07]=false, [0x0e]=false, + [0x16]=false, [0x17]=false, [0x1e]=false, [0x1f]=false, + [0x27]=false, [0x2f]=false, [0x37]=false, [0x3f]=false, + [0x60]=false, [0x61]=false, [0x62]=false, [0x63]="movsxdVrDmt", [0x67]="a32:", + [0x40]="rex*", [0x41]="rex*b", [0x42]="rex*x", [0x43]="rex*xb", + [0x44]="rex*r", [0x45]="rex*rb", [0x46]="rex*rx", [0x47]="rex*rxb", + [0x48]="rex*w", [0x49]="rex*wb", [0x4a]="rex*wx", [0x4b]="rex*wxb", + [0x4c]="rex*wr", [0x4d]="rex*wrb", [0x4e]="rex*wrx", [0x4f]="rex*wrxb", + [0x82]=false, [0x9a]=false, [0xc4]="vex*3", [0xc5]="vex*2", [0xce]=false, + [0xd4]=false, [0xd5]=false, [0xd6]=false, [0xea]=false, +}, { __index = map_opc1_32 }) + +-- Map for 2nd opcode byte (0F xx). True CISC hell. Hey, I told you. +-- Prefix dependent MMX/SSE opcodes: (none)|rep|o16|repne, -|F3|66|F2 +local map_opc2 = { +--0x +[0]="sldt!Dmp","sgdt!Ump","larVrm","lslVrm",nil,"syscall","clts","sysret", +"invd","wbinvd",nil,"ud1",nil,"$prefetch!Bm","femms","3dnowMrmu", +--1x +"movupsXrm|movssXrvm|movupdXrm|movsdXrvm", +"movupsXmr|movssXmvr|movupdXmr|movsdXmvr", +"movhlpsXrm$movlpsXrm|movsldupXrm|movlpdXrm|movddupXrm", +"movlpsXmr||movlpdXmr", +"unpcklpsXrvm||unpcklpdXrvm", +"unpckhpsXrvm||unpckhpdXrvm", +"movlhpsXrm$movhpsXrm|movshdupXrm|movhpdXrm", +"movhpsXmr||movhpdXmr", +"$prefetcht!Bm","hintnopVm","hintnopVm","hintnopVm", +"hintnopVm","hintnopVm","hintnopVm","hintnopVm", +--2x +"movUmx$","movUmy$","movUxm$","movUym$","movUmz$",nil,"movUzm$",nil, +"movapsXrm||movapdXrm", +"movapsXmr||movapdXmr", +"cvtpi2psXrMm|cvtsi2ssXrvVmt|cvtpi2pdXrMm|cvtsi2sdXrvVmt", +"movntpsXmr|movntssXmr|movntpdXmr|movntsdXmr", +"cvttps2piMrXm|cvttss2siVrXm|cvttpd2piMrXm|cvttsd2siVrXm", +"cvtps2piMrXm|cvtss2siVrXm|cvtpd2piMrXm|cvtsd2siVrXm", +"ucomissXrm||ucomisdXrm", +"comissXrm||comisdXrm", +--3x +"wrmsr","rdtsc","rdmsr","rdpmc","sysenter","sysexit",nil,"getsec", +"opc3*38",nil,"opc3*3a",nil,nil,nil,nil,nil, +--4x +"cmovoVrm","cmovnoVrm","cmovbVrm","cmovnbVrm", +"cmovzVrm","cmovnzVrm","cmovbeVrm","cmovaVrm", +"cmovsVrm","cmovnsVrm","cmovpeVrm","cmovpoVrm", +"cmovlVrm","cmovgeVrm","cmovleVrm","cmovgVrm", +--5x +"movmskpsVrXm$||movmskpdVrXm$","sqrtpsXrm|sqrtssXrm|sqrtpdXrm|sqrtsdXrm", +"rsqrtpsXrm|rsqrtssXrvm","rcppsXrm|rcpssXrvm", +"andpsXrvm||andpdXrvm","andnpsXrvm||andnpdXrvm", +"orpsXrvm||orpdXrvm","xorpsXrvm||xorpdXrvm", +"addpsXrvm|addssXrvm|addpdXrvm|addsdXrvm","mulpsXrvm|mulssXrvm|mulpdXrvm|mulsdXrvm", +"cvtps2pdXrm|cvtss2sdXrvm|cvtpd2psXrm|cvtsd2ssXrvm", +"cvtdq2psXrm|cvttps2dqXrm|cvtps2dqXrm", +"subpsXrvm|subssXrvm|subpdXrvm|subsdXrvm","minpsXrvm|minssXrvm|minpdXrvm|minsdXrvm", +"divpsXrvm|divssXrvm|divpdXrvm|divsdXrvm","maxpsXrvm|maxssXrvm|maxpdXrvm|maxsdXrvm", +--6x +"punpcklbwPrvm","punpcklwdPrvm","punpckldqPrvm","packsswbPrvm", +"pcmpgtbPrvm","pcmpgtwPrvm","pcmpgtdPrvm","packuswbPrvm", +"punpckhbwPrvm","punpckhwdPrvm","punpckhdqPrvm","packssdwPrvm", +"||punpcklqdqXrvm","||punpckhqdqXrvm", +"movPrVSm","movqMrm|movdquXrm|movdqaXrm", +--7x +"pshufwMrmu|pshufhwXrmu|pshufdXrmu|pshuflwXrmu","pshiftw!Pvmu", +"pshiftd!Pvmu","pshiftq!Mvmu||pshiftdq!Xvmu", +"pcmpeqbPrvm","pcmpeqwPrvm","pcmpeqdPrvm","emms*|", +"vmreadUmr||extrqXmuu$|insertqXrmuu$","vmwriteUrm||extrqXrm$|insertqXrm$", +nil,nil, +"||haddpdXrvm|haddpsXrvm","||hsubpdXrvm|hsubpsXrvm", +"movVSmMr|movqXrm|movVSmXr","movqMmr|movdquXmr|movdqaXmr", +--8x +"joVj","jnoVj","jbVj","jnbVj","jzVj","jnzVj","jbeVj","jaVj", +"jsVj","jnsVj","jpeVj","jpoVj","jlVj","jgeVj","jleVj","jgVj", +--9x +"setoBm","setnoBm","setbBm","setnbBm","setzBm","setnzBm","setbeBm","setaBm", +"setsBm","setnsBm","setpeBm","setpoBm","setlBm","setgeBm","setleBm","setgBm", +--Ax +"push fs","pop fs","cpuid","btVmr","shldVmru","shldVmrc",nil,nil, +"push gs","pop gs","rsm","btsVmr","shrdVmru","shrdVmrc","fxsave!Dmp","imulVrm", +--Bx +"cmpxchgBmr","cmpxchgVmr","$lssVrm","btrVmr", +"$lfsVrm","$lgsVrm","movzxVrBmt","movzxVrWmt", +"|popcntVrm","ud2Dp","bt!Vmu","btcVmr", +"bsfVrm","bsrVrm|lzcntVrm|bsrWrm","movsxVrBmt","movsxVrWmt", +--Cx +"xaddBmr","xaddVmr", +"cmppsXrvmu|cmpssXrvmu|cmppdXrvmu|cmpsdXrvmu","$movntiVmr|", +"pinsrwPrvWmu","pextrwDrPmu", +"shufpsXrvmu||shufpdXrvmu","$cmpxchg!Qmp", +"bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR", +--Dx +"||addsubpdXrvm|addsubpsXrvm","psrlwPrvm","psrldPrvm","psrlqPrvm", +"paddqPrvm","pmullwPrvm", +"|movq2dqXrMm|movqXmr|movdq2qMrXm$","pmovmskbVrMm||pmovmskbVrXm", +"psubusbPrvm","psubuswPrvm","pminubPrvm","pandPrvm", +"paddusbPrvm","padduswPrvm","pmaxubPrvm","pandnPrvm", +--Ex +"pavgbPrvm","psrawPrvm","psradPrvm","pavgwPrvm", +"pmulhuwPrvm","pmulhwPrvm", +"|cvtdq2pdXrm|cvttpd2dqXrm|cvtpd2dqXrm","$movntqMmr||$movntdqXmr", +"psubsbPrvm","psubswPrvm","pminswPrvm","porPrvm", +"paddsbPrvm","paddswPrvm","pmaxswPrvm","pxorPrvm", +--Fx +"|||lddquXrm","psllwPrvm","pslldPrvm","psllqPrvm", +"pmuludqPrvm","pmaddwdPrvm","psadbwPrvm","maskmovqMrm||maskmovdquXrm$", +"psubbPrvm","psubwPrvm","psubdPrvm","psubqPrvm", +"paddbPrvm","paddwPrvm","padddPrvm","ud", +} +assert(map_opc2[255] == "ud") + +-- Map for three-byte opcodes. Can't wait for their next invention. +local map_opc3 = { +["38"] = { -- [66] 0f 38 xx +--0x +[0]="pshufbPrvm","phaddwPrvm","phadddPrvm","phaddswPrvm", +"pmaddubswPrvm","phsubwPrvm","phsubdPrvm","phsubswPrvm", +"psignbPrvm","psignwPrvm","psigndPrvm","pmulhrswPrvm", +"||permilpsXrvm","||permilpdXrvm",nil,nil, +--1x +"||pblendvbXrma",nil,nil,nil, +"||blendvpsXrma","||blendvpdXrma","||permpsXrvm","||ptestXrm", +"||broadcastssXrm","||broadcastsdXrm","||broadcastf128XrlXm",nil, +"pabsbPrm","pabswPrm","pabsdPrm",nil, +--2x +"||pmovsxbwXrm","||pmovsxbdXrm","||pmovsxbqXrm","||pmovsxwdXrm", +"||pmovsxwqXrm","||pmovsxdqXrm",nil,nil, +"||pmuldqXrvm","||pcmpeqqXrvm","||$movntdqaXrm","||packusdwXrvm", +"||maskmovpsXrvm","||maskmovpdXrvm","||maskmovpsXmvr","||maskmovpdXmvr", +--3x +"||pmovzxbwXrm","||pmovzxbdXrm","||pmovzxbqXrm","||pmovzxwdXrm", +"||pmovzxwqXrm","||pmovzxdqXrm","||permdXrvm","||pcmpgtqXrvm", +"||pminsbXrvm","||pminsdXrvm","||pminuwXrvm","||pminudXrvm", +"||pmaxsbXrvm","||pmaxsdXrvm","||pmaxuwXrvm","||pmaxudXrvm", +--4x +"||pmulddXrvm","||phminposuwXrm",nil,nil, +nil,"||psrlvVSXrvm","||psravdXrvm","||psllvVSXrvm", +--5x +[0x58] = "||pbroadcastdXrlXm",[0x59] = "||pbroadcastqXrlXm", +[0x5a] = "||broadcasti128XrlXm", +--7x +[0x78] = "||pbroadcastbXrlXm",[0x79] = "||pbroadcastwXrlXm", +--8x +[0x8c] = "||pmaskmovXrvVSm", +[0x8e] = "||pmaskmovVSmXvr", +--9x +[0x96] = "||fmaddsub132pHXrvm",[0x97] = "||fmsubadd132pHXrvm", +[0x98] = "||fmadd132pHXrvm",[0x99] = "||fmadd132sHXrvm", +[0x9a] = "||fmsub132pHXrvm",[0x9b] = "||fmsub132sHXrvm", +[0x9c] = "||fnmadd132pHXrvm",[0x9d] = "||fnmadd132sHXrvm", +[0x9e] = "||fnmsub132pHXrvm",[0x9f] = "||fnmsub132sHXrvm", +--Ax +[0xa6] = "||fmaddsub213pHXrvm",[0xa7] = "||fmsubadd213pHXrvm", +[0xa8] = "||fmadd213pHXrvm",[0xa9] = "||fmadd213sHXrvm", +[0xaa] = "||fmsub213pHXrvm",[0xab] = "||fmsub213sHXrvm", +[0xac] = "||fnmadd213pHXrvm",[0xad] = "||fnmadd213sHXrvm", +[0xae] = "||fnmsub213pHXrvm",[0xaf] = "||fnmsub213sHXrvm", +--Bx +[0xb6] = "||fmaddsub231pHXrvm",[0xb7] = "||fmsubadd231pHXrvm", +[0xb8] = "||fmadd231pHXrvm",[0xb9] = "||fmadd231sHXrvm", +[0xba] = "||fmsub231pHXrvm",[0xbb] = "||fmsub231sHXrvm", +[0xbc] = "||fnmadd231pHXrvm",[0xbd] = "||fnmadd231sHXrvm", +[0xbe] = "||fnmsub231pHXrvm",[0xbf] = "||fnmsub231sHXrvm", +--Dx +[0xdc] = "||aesencXrvm", [0xdd] = "||aesenclastXrvm", +[0xde] = "||aesdecXrvm", [0xdf] = "||aesdeclastXrvm", +--Fx +[0xf0] = "|||crc32TrBmt",[0xf1] = "|||crc32TrVmt", +[0xf7] = "| sarxVrmv| shlxVrmv| shrxVrmv", +}, + +["3a"] = { -- [66] 0f 3a xx +--0x +[0x00]="||permqXrmu","||permpdXrmu","||pblenddXrvmu",nil, +"||permilpsXrmu","||permilpdXrmu","||perm2f128Xrvmu",nil, +"||roundpsXrmu","||roundpdXrmu","||roundssXrvmu","||roundsdXrvmu", +"||blendpsXrvmu","||blendpdXrvmu","||pblendwXrvmu","palignrPrvmu", +--1x +nil,nil,nil,nil, +"||pextrbVmXru","||pextrwVmXru","||pextrVmSXru","||extractpsVmXru", +"||insertf128XrvlXmu","||extractf128XlXmYru",nil,nil, +nil,nil,nil,nil, +--2x +"||pinsrbXrvVmu","||insertpsXrvmu","||pinsrXrvVmuS",nil, +--3x +[0x38] = "||inserti128Xrvmu",[0x39] = "||extracti128XlXmYru", +--4x +[0x40] = "||dppsXrvmu", +[0x41] = "||dppdXrvmu", +[0x42] = "||mpsadbwXrvmu", +[0x44] = "||pclmulqdqXrvmu", +[0x46] = "||perm2i128Xrvmu", +[0x4a] = "||blendvpsXrvmb",[0x4b] = "||blendvpdXrvmb", +[0x4c] = "||pblendvbXrvmb", +--6x +[0x60] = "||pcmpestrmXrmu",[0x61] = "||pcmpestriXrmu", +[0x62] = "||pcmpistrmXrmu",[0x63] = "||pcmpistriXrmu", +[0xdf] = "||aeskeygenassistXrmu", +--Fx +[0xf0] = "||| rorxVrmu", +}, +} + +-- Map for VMX/SVM opcodes 0F 01 C0-FF (sgdt group with register operands). +local map_opcvm = { +[0xc1]="vmcall",[0xc2]="vmlaunch",[0xc3]="vmresume",[0xc4]="vmxoff", +[0xc8]="monitor",[0xc9]="mwait", +[0xd8]="vmrun",[0xd9]="vmmcall",[0xda]="vmload",[0xdb]="vmsave", +[0xdc]="stgi",[0xdd]="clgi",[0xde]="skinit",[0xdf]="invlpga", +[0xf8]="swapgs",[0xf9]="rdtscp", +} + +-- Map for FP opcodes. And you thought stack machines are simple? +local map_opcfp = { +-- D8-DF 00-BF: opcodes with a memory operand. +-- D8 +[0]="faddFm","fmulFm","fcomFm","fcompFm","fsubFm","fsubrFm","fdivFm","fdivrFm", +"fldFm",nil,"fstFm","fstpFm","fldenvVm","fldcwWm","fnstenvVm","fnstcwWm", +-- DA +"fiaddDm","fimulDm","ficomDm","ficompDm", +"fisubDm","fisubrDm","fidivDm","fidivrDm", +-- DB +"fildDm","fisttpDm","fistDm","fistpDm",nil,"fld twordFmp",nil,"fstp twordFmp", +-- DC +"faddGm","fmulGm","fcomGm","fcompGm","fsubGm","fsubrGm","fdivGm","fdivrGm", +-- DD +"fldGm","fisttpQm","fstGm","fstpGm","frstorDmp",nil,"fnsaveDmp","fnstswWm", +-- DE +"fiaddWm","fimulWm","ficomWm","ficompWm", +"fisubWm","fisubrWm","fidivWm","fidivrWm", +-- DF +"fildWm","fisttpWm","fistWm","fistpWm", +"fbld twordFmp","fildQm","fbstp twordFmp","fistpQm", +-- xx C0-FF: opcodes with a pseudo-register operand. +-- D8 +"faddFf","fmulFf","fcomFf","fcompFf","fsubFf","fsubrFf","fdivFf","fdivrFf", +-- D9 +"fldFf","fxchFf",{"fnop"},nil, +{"fchs","fabs",nil,nil,"ftst","fxam"}, +{"fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz"}, +{"f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp"}, +{"fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos"}, +-- DA +"fcmovbFf","fcmoveFf","fcmovbeFf","fcmovuFf",nil,{nil,"fucompp"},nil,nil, +-- DB +"fcmovnbFf","fcmovneFf","fcmovnbeFf","fcmovnuFf", +{nil,nil,"fnclex","fninit"},"fucomiFf","fcomiFf",nil, +-- DC +"fadd toFf","fmul toFf",nil,nil, +"fsub toFf","fsubr toFf","fdivr toFf","fdiv toFf", +-- DD +"ffreeFf",nil,"fstFf","fstpFf","fucomFf","fucompFf",nil,nil, +-- DE +"faddpFf","fmulpFf",nil,{nil,"fcompp"}, +"fsubrpFf","fsubpFf","fdivrpFf","fdivpFf", +-- DF +nil,nil,nil,nil,{"fnstsw ax"},"fucomipFf","fcomipFf",nil, +} +assert(map_opcfp[126] == "fcomipFf") + +-- Map for opcode groups. The subkey is sp from the ModRM byte. +local map_opcgroup = { + arith = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" }, + shift = { "rol", "ror", "rcl", "rcr", "shl", "shr", "sal", "sar" }, + testb = { "testBmi", "testBmi", "not", "neg", "mul", "imul", "div", "idiv" }, + testv = { "testVmi", "testVmi", "not", "neg", "mul", "imul", "div", "idiv" }, + incb = { "inc", "dec" }, + incd = { "inc", "dec", "callUmp", "$call farDmp", + "jmpUmp", "$jmp farDmp", "pushUm" }, + sldt = { "sldt", "str", "lldt", "ltr", "verr", "verw" }, + sgdt = { "vm*$sgdt", "vm*$sidt", "$lgdt", "vm*$lidt", + "smsw", nil, "lmsw", "vm*$invlpg" }, + bt = { nil, nil, nil, nil, "bt", "bts", "btr", "btc" }, + cmpxchg = { nil, "sz*,cmpxchg8bQmp,cmpxchg16bXmp", nil, nil, + nil, nil, "vmptrld|vmxon|vmclear", "vmptrst" }, + pshiftw = { nil, nil, "psrlw", nil, "psraw", nil, "psllw" }, + pshiftd = { nil, nil, "psrld", nil, "psrad", nil, "pslld" }, + pshiftq = { nil, nil, "psrlq", nil, nil, nil, "psllq" }, + pshiftdq = { nil, nil, "psrlq", "psrldq", nil, nil, "psllq", "pslldq" }, + fxsave = { "$fxsave", "$fxrstor", "$ldmxcsr", "$stmxcsr", + nil, "lfenceDp$", "mfenceDp$", "sfenceDp$clflush" }, + prefetch = { "prefetch", "prefetchw" }, + prefetcht = { "prefetchnta", "prefetcht0", "prefetcht1", "prefetcht2" }, +} + +------------------------------------------------------------------------------ + +-- Maps for register names. +local map_regs = { + B = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", + "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" }, + B64 = { "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", + "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" }, + W = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", + "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" }, + D = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", + "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" }, + Q = { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" }, + M = { "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", + "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" }, -- No x64 ext! + X = { "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", + "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" }, + Y = { "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", + "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15" }, +} +local map_segregs = { "es", "cs", "ss", "ds", "fs", "gs", "segr6", "segr7" } + +-- Maps for size names. +local map_sz2n = { + B = 1, W = 2, D = 4, Q = 8, M = 8, X = 16, Y = 32, +} +local map_sz2prefix = { + B = "byte", W = "word", D = "dword", + Q = "qword", + M = "qword", X = "xword", Y = "yword", + F = "dword", G = "qword", -- No need for sizes/register names for these two. +} + +------------------------------------------------------------------------------ + +-- Output a nicely formatted line with an opcode and operands. +local function putop(ctx, text, operands) + local code, pos, hex = ctx.code, ctx.pos, "" + local hmax = ctx.hexdump + if hmax > 0 then + for i=ctx.start,pos-1 do + hex = hex..format("%02X", byte(code, i, i)) + end + if #hex > hmax then hex = sub(hex, 1, hmax)..". " + else hex = hex..rep(" ", hmax-#hex+2) end + end + if operands then text = text.." "..operands end + if ctx.o16 then text = "o16 "..text; ctx.o16 = false end + if ctx.a32 then text = "a32 "..text; ctx.a32 = false end + if ctx.rep then text = ctx.rep.." "..text; ctx.rep = false end + if ctx.rex then + local t = (ctx.rexw and "w" or "")..(ctx.rexr and "r" or "").. + (ctx.rexx and "x" or "")..(ctx.rexb and "b" or "").. + (ctx.vexl and "l" or "") + if ctx.vexv and ctx.vexv ~= 0 then t = t.."v"..ctx.vexv end + if t ~= "" then text = ctx.rex.."."..t.." "..gsub(text, "^ ", "") + elseif ctx.rex == "vex" then text = gsub("v"..text, "^v ", "") end + ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false + ctx.rex = false; ctx.vexl = false; ctx.vexv = false + end + if ctx.seg then + local text2, n = gsub(text, "%[", "["..ctx.seg..":") + if n == 0 then text = ctx.seg.." "..text else text = text2 end + ctx.seg = false + end + if ctx.lock then text = "lock "..text; ctx.lock = false end + local imm = ctx.imm + if imm then + local sym = ctx.symtab[imm] + if sym then text = text.."\t->"..sym end + end + ctx.out(format("%08x %s%s\n", ctx.addr+ctx.start, hex, text)) + ctx.mrm = false + ctx.vexv = false + ctx.start = pos + ctx.imm = nil +end + +-- Clear all prefix flags. +local function clearprefixes(ctx) + ctx.o16 = false; ctx.seg = false; ctx.lock = false; ctx.rep = false + ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false + ctx.rex = false; ctx.a32 = false; ctx.vexl = false +end + +-- Fallback for incomplete opcodes at the end. +local function incomplete(ctx) + ctx.pos = ctx.stop+1 + clearprefixes(ctx) + return putop(ctx, "(incomplete)") +end + +-- Fallback for unknown opcodes. +local function unknown(ctx) + clearprefixes(ctx) + return putop(ctx, "(unknown)") +end + +-- Return an immediate of the specified size. +local function getimm(ctx, pos, n) + if pos+n-1 > ctx.stop then return incomplete(ctx) end + local code = ctx.code + if n == 1 then + local b1 = byte(code, pos, pos) + return b1 + elseif n == 2 then + local b1, b2 = byte(code, pos, pos+1) + return b1+b2*256 + else + local b1, b2, b3, b4 = byte(code, pos, pos+3) + local imm = b1+b2*256+b3*65536+b4*16777216 + ctx.imm = imm + return imm + end +end + +-- Process pattern string and generate the operands. +local function putpat(ctx, name, pat) + local operands, regs, sz, mode, sp, rm, sc, rx, sdisp + local code, pos, stop, vexl = ctx.code, ctx.pos, ctx.stop, ctx.vexl + + -- Chars used: 1DFGHIMPQRSTUVWXYabcdfgijlmoprstuvwxyz + for p in gmatch(pat, ".") do + local x = nil + if p == "V" or p == "U" then + if ctx.rexw then sz = "Q"; ctx.rexw = false + elseif ctx.o16 then sz = "W"; ctx.o16 = false + elseif p == "U" and ctx.x64 then sz = "Q" + else sz = "D" end + regs = map_regs[sz] + elseif p == "T" then + if ctx.rexw then sz = "Q"; ctx.rexw = false else sz = "D" end + regs = map_regs[sz] + elseif p == "B" then + sz = "B" + regs = ctx.rex and map_regs.B64 or map_regs.B + elseif match(p, "[WDQMXYFG]") then + sz = p + if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end + regs = map_regs[sz] + elseif p == "P" then + sz = ctx.o16 and "X" or "M"; ctx.o16 = false + if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end + regs = map_regs[sz] + elseif p == "H" then + name = name..(ctx.rexw and "d" or "s") + ctx.rexw = false + elseif p == "S" then + name = name..lower(sz) + elseif p == "s" then + local imm = getimm(ctx, pos, 1); if not imm then return end + x = imm <= 127 and format("+0x%02x", imm) + or format("-0x%02x", 256-imm) + pos = pos+1 + elseif p == "u" then + local imm = getimm(ctx, pos, 1); if not imm then return end + x = format("0x%02x", imm) + pos = pos+1 + elseif p == "b" then + local imm = getimm(ctx, pos, 1); if not imm then return end + x = regs[imm/16+1] + pos = pos+1 + elseif p == "w" then + local imm = getimm(ctx, pos, 2); if not imm then return end + x = format("0x%x", imm) + pos = pos+2 + elseif p == "o" then -- [offset] + if ctx.x64 then + local imm1 = getimm(ctx, pos, 4); if not imm1 then return end + local imm2 = getimm(ctx, pos+4, 4); if not imm2 then return end + x = format("[0x%08x%08x]", imm2, imm1) + pos = pos+8 + else + local imm = getimm(ctx, pos, 4); if not imm then return end + x = format("[0x%08x]", imm) + pos = pos+4 + end + elseif p == "i" or p == "I" then + local n = map_sz2n[sz] + if n == 8 and ctx.x64 and p == "I" then + local imm1 = getimm(ctx, pos, 4); if not imm1 then return end + local imm2 = getimm(ctx, pos+4, 4); if not imm2 then return end + x = format("0x%08x%08x", imm2, imm1) + else + if n == 8 then n = 4 end + local imm = getimm(ctx, pos, n); if not imm then return end + if sz == "Q" and (imm < 0 or imm > 0x7fffffff) then + imm = (0xffffffff+1)-imm + x = format(imm > 65535 and "-0x%08x" or "-0x%x", imm) + else + x = format(imm > 65535 and "0x%08x" or "0x%x", imm) + end + end + pos = pos+n + elseif p == "j" then + local n = map_sz2n[sz] + if n == 8 then n = 4 end + local imm = getimm(ctx, pos, n); if not imm then return end + if sz == "B" and imm > 127 then imm = imm-256 + elseif imm > 2147483647 then imm = imm-4294967296 end + pos = pos+n + imm = imm + pos + ctx.addr + if imm > 4294967295 and not ctx.x64 then imm = imm-4294967296 end + ctx.imm = imm + if sz == "W" then + x = format("word 0x%04x", imm%65536) + elseif ctx.x64 then + local lo = imm % 0x1000000 + x = format("0x%02x%06x", (imm-lo) / 0x1000000, lo) + else + x = "0x"..tohex(imm) + end + elseif p == "R" then + local r = byte(code, pos-1, pos-1)%8 + if ctx.rexb then r = r + 8; ctx.rexb = false end + x = regs[r+1] + elseif p == "a" then x = regs[1] + elseif p == "c" then x = "cl" + elseif p == "d" then x = "dx" + elseif p == "1" then x = "1" + else + if not mode then + mode = ctx.mrm + if not mode then + if pos > stop then return incomplete(ctx) end + mode = byte(code, pos, pos) + pos = pos+1 + end + rm = mode%8; mode = (mode-rm)/8 + sp = mode%8; mode = (mode-sp)/8 + sdisp = "" + if mode < 3 then + if rm == 4 then + if pos > stop then return incomplete(ctx) end + sc = byte(code, pos, pos) + pos = pos+1 + rm = sc%8; sc = (sc-rm)/8 + rx = sc%8; sc = (sc-rx)/8 + if ctx.rexx then rx = rx + 8; ctx.rexx = false end + if rx == 4 then rx = nil end + end + if mode > 0 or rm == 5 then + local dsz = mode + if dsz ~= 1 then dsz = 4 end + local disp = getimm(ctx, pos, dsz); if not disp then return end + if mode == 0 then rm = nil end + if rm or rx or (not sc and ctx.x64 and not ctx.a32) then + if dsz == 1 and disp > 127 then + sdisp = format("-0x%x", 256-disp) + elseif disp >= 0 and disp <= 0x7fffffff then + sdisp = format("+0x%x", disp) + else + sdisp = format("-0x%x", (0xffffffff+1)-disp) + end + else + sdisp = format(ctx.x64 and not ctx.a32 and + not (disp >= 0 and disp <= 0x7fffffff) + and "0xffffffff%08x" or "0x%08x", disp) + end + pos = pos+dsz + end + end + if rm and ctx.rexb then rm = rm + 8; ctx.rexb = false end + if ctx.rexr then sp = sp + 8; ctx.rexr = false end + end + if p == "m" then + if mode == 3 then x = regs[rm+1] + else + local aregs = ctx.a32 and map_regs.D or ctx.aregs + local srm, srx = "", "" + if rm then srm = aregs[rm+1] + elseif not sc and ctx.x64 and not ctx.a32 then srm = "rip" end + ctx.a32 = false + if rx then + if rm then srm = srm.."+" end + srx = aregs[rx+1] + if sc > 0 then srx = srx.."*"..(2^sc) end + end + x = format("[%s%s%s]", srm, srx, sdisp) + end + if mode < 3 and + (not match(pat, "[aRrgp]") or match(pat, "t")) then -- Yuck. + x = map_sz2prefix[sz].." "..x + end + elseif p == "r" then x = regs[sp+1] + elseif p == "g" then x = map_segregs[sp+1] + elseif p == "p" then -- Suppress prefix. + elseif p == "f" then x = "st"..rm + elseif p == "x" then + if sp == 0 and ctx.lock and not ctx.x64 then + x = "CR8"; ctx.lock = false + else + x = "CR"..sp + end + elseif p == "v" then + if ctx.vexv then + x = regs[ctx.vexv+1]; ctx.vexv = false + end + elseif p == "y" then x = "DR"..sp + elseif p == "z" then x = "TR"..sp + elseif p == "l" then vexl = false + elseif p == "t" then + else + error("bad pattern `"..pat.."'") + end + end + if x then operands = operands and operands..", "..x or x end + end + ctx.pos = pos + return putop(ctx, name, operands) +end + +-- Forward declaration. +local map_act + +-- Fetch and cache MRM byte. +local function getmrm(ctx) + local mrm = ctx.mrm + if not mrm then + local pos = ctx.pos + if pos > ctx.stop then return nil end + mrm = byte(ctx.code, pos, pos) + ctx.pos = pos+1 + ctx.mrm = mrm + end + return mrm +end + +-- Dispatch to handler depending on pattern. +local function dispatch(ctx, opat, patgrp) + if not opat then return unknown(ctx) end + if match(opat, "%|") then -- MMX/SSE variants depending on prefix. + local p + if ctx.rep then + p = ctx.rep=="rep" and "%|([^%|]*)" or "%|[^%|]*%|[^%|]*%|([^%|]*)" + ctx.rep = false + elseif ctx.o16 then p = "%|[^%|]*%|([^%|]*)"; ctx.o16 = false + else p = "^[^%|]*" end + opat = match(opat, p) + if not opat then return unknown(ctx) end +-- ctx.rep = false; ctx.o16 = false + --XXX fails for 66 f2 0f 38 f1 06 crc32 eax,WORD PTR [esi] + --XXX remove in branches? + end + if match(opat, "%$") then -- reg$mem variants. + local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end + opat = match(opat, mrm >= 192 and "^[^%$]*" or "%$(.*)") + if opat == "" then return unknown(ctx) end + end + if opat == "" then return unknown(ctx) end + local name, pat = match(opat, "^([a-z0-9 ]*)(.*)") + if pat == "" and patgrp then pat = patgrp end + return map_act[sub(pat, 1, 1)](ctx, name, pat) +end + +-- Get a pattern from an opcode map and dispatch to handler. +local function dispatchmap(ctx, opcmap) + local pos = ctx.pos + local opat = opcmap[byte(ctx.code, pos, pos)] + pos = pos + 1 + ctx.pos = pos + return dispatch(ctx, opat) +end + +-- Map for action codes. The key is the first char after the name. +map_act = { + -- Simple opcodes without operands. + [""] = function(ctx, name, pat) + return putop(ctx, name) + end, + + -- Operand size chars fall right through. + B = putpat, W = putpat, D = putpat, Q = putpat, + V = putpat, U = putpat, T = putpat, + M = putpat, X = putpat, P = putpat, + F = putpat, G = putpat, Y = putpat, + H = putpat, + + -- Collect prefixes. + [":"] = function(ctx, name, pat) + ctx[pat == ":" and name or sub(pat, 2)] = name + if ctx.pos - ctx.start > 5 then return unknown(ctx) end -- Limit #prefixes. + end, + + -- Chain to special handler specified by name. + ["*"] = function(ctx, name, pat) + return map_act[name](ctx, name, sub(pat, 2)) + end, + + -- Use named subtable for opcode group. + ["!"] = function(ctx, name, pat) + local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end + return dispatch(ctx, map_opcgroup[name][((mrm-(mrm%8))/8)%8+1], sub(pat, 2)) + end, + + -- o16,o32[,o64] variants. + sz = function(ctx, name, pat) + if ctx.o16 then ctx.o16 = false + else + pat = match(pat, ",(.*)") + if ctx.rexw then + local p = match(pat, ",(.*)") + if p then pat = p; ctx.rexw = false end + end + end + pat = match(pat, "^[^,]*") + return dispatch(ctx, pat) + end, + + -- Two-byte opcode dispatch. + opc2 = function(ctx, name, pat) + return dispatchmap(ctx, map_opc2) + end, + + -- Three-byte opcode dispatch. + opc3 = function(ctx, name, pat) + return dispatchmap(ctx, map_opc3[pat]) + end, + + -- VMX/SVM dispatch. + vm = function(ctx, name, pat) + return dispatch(ctx, map_opcvm[ctx.mrm]) + end, + + -- Floating point opcode dispatch. + fp = function(ctx, name, pat) + local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end + local rm = mrm%8 + local idx = pat*8 + ((mrm-rm)/8)%8 + if mrm >= 192 then idx = idx + 64 end + local opat = map_opcfp[idx] + if type(opat) == "table" then opat = opat[rm+1] end + return dispatch(ctx, opat) + end, + + -- REX prefix. + rex = function(ctx, name, pat) + if ctx.rex then return unknown(ctx) end -- Only 1 REX or VEX prefix allowed. + for p in gmatch(pat, ".") do ctx["rex"..p] = true end + ctx.rex = "rex" + end, + + -- VEX prefix. + vex = function(ctx, name, pat) + if ctx.rex then return unknown(ctx) end -- Only 1 REX or VEX prefix allowed. + ctx.rex = "vex" + local pos = ctx.pos + if ctx.mrm then + ctx.mrm = nil + pos = pos-1 + end + local b = byte(ctx.code, pos, pos) + if not b then return incomplete(ctx) end + pos = pos+1 + if b < 128 then ctx.rexr = true end + local m = 1 + if pat == "3" then + m = b%32; b = (b-m)/32 + local nb = b%2; b = (b-nb)/2 + if nb == 0 then ctx.rexb = true end + local nx = b%2 + if nx == 0 then ctx.rexx = true end + b = byte(ctx.code, pos, pos) + if not b then return incomplete(ctx) end + pos = pos+1 + if b >= 128 then ctx.rexw = true end + end + ctx.pos = pos + local map + if m == 1 then map = map_opc2 + elseif m == 2 then map = map_opc3["38"] + elseif m == 3 then map = map_opc3["3a"] + else return unknown(ctx) end + local p = b%4; b = (b-p)/4 + if p == 1 then ctx.o16 = "o16" + elseif p == 2 then ctx.rep = "rep" + elseif p == 3 then ctx.rep = "repne" end + local l = b%2; b = (b-l)/2 + if l ~= 0 then ctx.vexl = true end + ctx.vexv = (-1-b)%16 + return dispatchmap(ctx, map) + end, + + -- Special case for nop with REX prefix. + nop = function(ctx, name, pat) + return dispatch(ctx, ctx.rex and pat or "nop") + end, + + -- Special case for 0F 77. + emms = function(ctx, name, pat) + if ctx.rex ~= "vex" then + return putop(ctx, "emms") + elseif ctx.vexl then + ctx.vexl = false + return putop(ctx, "zeroall") + else + return putop(ctx, "zeroupper") + end + 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 + ofs = ofs + 1 + ctx.start = ofs + ctx.pos = ofs + ctx.stop = stop + ctx.imm = nil + ctx.mrm = false + clearprefixes(ctx) + while ctx.pos <= stop do dispatchmap(ctx, ctx.map1) end + if ctx.pos ~= ctx.start then incomplete(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) - 1 + ctx.out = out or io.write + ctx.symtab = {} + ctx.disass = disass_block + ctx.hexdump = 16 + ctx.x64 = false + ctx.map1 = map_opc1_32 + ctx.aregs = map_regs.D + return ctx +end + +local function create64(code, addr, out) + local ctx = create(code, addr, out) + ctx.x64 = true + ctx.map1 = map_opc1_64 + ctx.aregs = map_regs.Q + 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 disass64(code, addr, out) + create64(code, addr, out):disass() +end + +-- Return register name for RID. +local function regname(r) + if r < 8 then return map_regs.D[r+1] end + return map_regs.X[r-7] +end + +local function regname64(r) + if r < 16 then return map_regs.Q[r+1] end + return map_regs.X[r-15] +end + +-- Public module functions. +return { + create = create, + create64 = create64, + disass = disass, + disass64 = disass64, + regname = regname, + regname64 = regname64 +} + diff --git a/libs/luajit-cmake/luajit/src/jit/dump.lua b/libs/luajit-cmake/luajit/src/jit/dump.lua new file mode 100644 index 0000000..18e7a4b --- /dev/null +++ b/libs/luajit-cmake/luajit/src/jit/dump.lua @@ -0,0 +1,726 @@ +---------------------------------------------------------------------------- +-- LuaJIT compiler dump module. +-- +-- Copyright (C) 2005-2022 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module can be used to debug the JIT compiler itself. It dumps the +-- code representations and structures used in various compiler stages. +-- +-- Example usage: +-- +-- luajit -jdump -e "local x=0; for i=1,1e6 do x=x+i end; print(x)" +-- luajit -jdump=im -e "for i=1,1000 do for j=1,1000 do end end" | less -R +-- luajit -jdump=is myapp.lua | less -R +-- luajit -jdump=-b myapp.lua +-- luajit -jdump=+aH,myapp.html myapp.lua +-- luajit -jdump=ixT,myapp.dump myapp.lua +-- +-- The first argument specifies the dump mode. The second argument gives +-- the output file name. Default output is to stdout, unless the environment +-- variable LUAJIT_DUMPFILE is set. The file is overwritten every time the +-- module is started. +-- +-- Different features can be turned on or off with the dump mode. If the +-- mode starts with a '+', the following features are added to the default +-- set of features; a '-' removes them. Otherwise the features are replaced. +-- +-- The following dump features are available (* marks the default): +-- +-- * t Print a line for each started, ended or aborted trace (see also -jv). +-- * b Dump the traced bytecode. +-- * i Dump the IR (intermediate representation). +-- r Augment the IR with register/stack slots. +-- s Dump the snapshot map. +-- * m Dump the generated machine code. +-- x Print each taken trace exit. +-- X Print each taken trace exit and the contents of all registers. +-- a Print the IR of aborted traces, too. +-- +-- The output format can be set with the following characters: +-- +-- T Plain text output. +-- A ANSI-colored text output +-- H Colorized HTML + CSS output. +-- +-- The default output format is plain text. It's set to ANSI-colored text +-- if the COLORTERM variable is set. Note: this is independent of any output +-- redirection, which is actually considered a feature. +-- +-- You probably want to use less -R to enjoy viewing ANSI-colored text from +-- a pipe or a file. Add this to your ~/.bashrc: export LESS="-R" +-- +------------------------------------------------------------------------------ + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local jutil = require("jit.util") +local vmdef = require("jit.vmdef") +local funcinfo, funcbc = jutil.funcinfo, jutil.funcbc +local traceinfo, traceir, tracek = jutil.traceinfo, jutil.traceir, jutil.tracek +local tracemc, tracesnap = jutil.tracemc, jutil.tracesnap +local traceexitstub, ircalladdr = jutil.traceexitstub, jutil.ircalladdr +local bit = require("bit") +local band, shr, tohex = bit.band, bit.rshift, bit.tohex +local sub, gsub, format = string.sub, string.gsub, string.format +local byte, rep = string.byte, string.rep +local type, tostring = type, tostring +local stdout, stderr = io.stdout, io.stderr + +-- Load other modules on-demand. +local bcline, disass + +-- Active flag, output file handle and dump mode. +local active, out, dumpmode + +------------------------------------------------------------------------------ + +local symtabmt = { __index = false } +local symtab = {} +local nexitsym = 0 + +-- Fill nested symbol table with per-trace exit stub addresses. +local function fillsymtab_tr(tr, nexit) + local t = {} + symtabmt.__index = t + if jit.arch:sub(1, 4) == "mips" then + t[traceexitstub(tr, 0)] = "exit" + return + end + for i=0,nexit-1 do + local addr = traceexitstub(tr, i) + if addr < 0 then addr = addr + 2^32 end + t[addr] = tostring(i) + end + local addr = traceexitstub(tr, nexit) + if addr then t[addr] = "stack_check" end +end + +-- Fill symbol table with trace exit stub addresses. +local function fillsymtab(tr, nexit) + local t = symtab + if nexitsym == 0 then + local maskaddr = jit.arch == "arm" and -2 + local ircall = vmdef.ircall + for i=0,#ircall do + local addr = ircalladdr(i) + if addr ~= 0 then + if maskaddr then addr = band(addr, maskaddr) end + if addr < 0 then addr = addr + 2^32 end + t[addr] = ircall[i] + end + end + end + if nexitsym == 1000000 then -- Per-trace exit stubs. + fillsymtab_tr(tr, nexit) + elseif nexit > nexitsym then -- Shared exit stubs. + for i=nexitsym,nexit-1 do + local addr = traceexitstub(i) + if addr == nil then -- Fall back to per-trace exit stubs. + fillsymtab_tr(tr, nexit) + setmetatable(symtab, symtabmt) + nexit = 1000000 + break + end + if addr < 0 then addr = addr + 2^32 end + t[addr] = tostring(i) + end + nexitsym = nexit + end + return t +end + +local function dumpwrite(s) + out:write(s) +end + +-- Disassemble machine code. +local function dump_mcode(tr) + local info = traceinfo(tr) + if not info then return end + local mcode, addr, loop = tracemc(tr) + if not mcode then return end + if not disass then disass = require("jit.dis_"..jit.arch) end + if addr < 0 then addr = addr + 2^32 end + out:write("---- TRACE ", tr, " mcode ", #mcode, "\n") + local ctx = disass.create(mcode, addr, dumpwrite) + ctx.hexdump = 0 + ctx.symtab = fillsymtab(tr, info.nexit) + if loop ~= 0 then + symtab[addr+loop] = "LOOP" + ctx:disass(0, loop) + out:write("->LOOP:\n") + ctx:disass(loop, #mcode-loop) + symtab[addr+loop] = nil + else + ctx:disass(0, #mcode) + end +end + +------------------------------------------------------------------------------ + +local irtype_text = { + [0] = "nil", + "fal", + "tru", + "lud", + "str", + "p32", + "thr", + "pro", + "fun", + "p64", + "cdt", + "tab", + "udt", + "flt", + "num", + "i8 ", + "u8 ", + "i16", + "u16", + "int", + "u32", + "i64", + "u64", + "sfp", +} + +local colortype_ansi = { + [0] = "%s", + "%s", + "%s", + "\027[36m%s\027[m", + "\027[32m%s\027[m", + "%s", + "\027[1m%s\027[m", + "%s", + "\027[1m%s\027[m", + "%s", + "\027[33m%s\027[m", + "\027[31m%s\027[m", + "\027[36m%s\027[m", + "\027[34m%s\027[m", + "\027[34m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", + "\027[35m%s\027[m", +} + +local function colorize_text(s) + return s +end + +local function colorize_ansi(s, t, extra) + local out = format(colortype_ansi[t], s) + if extra then out = "\027[3m"..out end + return out +end + +local irtype_ansi = setmetatable({}, + { __index = function(tab, t) + local s = colorize_ansi(irtype_text[t], t); tab[t] = s; return s; end }) + +local html_escape = { ["<"] = "<", [">"] = ">", ["&"] = "&", } + +local function colorize_html(s, t, extra) + s = gsub(s, "[<>&]", html_escape) + return format('<span class="irt_%s%s">%s</span>', + irtype_text[t], extra and " irt_extra" or "", s) +end + +local irtype_html = setmetatable({}, + { __index = function(tab, t) + local s = colorize_html(irtype_text[t], t); tab[t] = s; return s; end }) + +local header_html = [[ +<style type="text/css"> +background { background: #ffffff; color: #000000; } +pre.ljdump { +font-size: 10pt; +background: #f0f4ff; +color: #000000; +border: 1px solid #bfcfff; +padding: 0.5em; +margin-left: 2em; +margin-right: 2em; +} +span.irt_str { color: #00a000; } +span.irt_thr, span.irt_fun { color: #404040; font-weight: bold; } +span.irt_tab { color: #c00000; } +span.irt_udt, span.irt_lud { color: #00c0c0; } +span.irt_num { color: #4040c0; } +span.irt_int, span.irt_i8, span.irt_u8, span.irt_i16, span.irt_u16 { color: #b040b0; } +span.irt_extra { font-style: italic; } +</style> +]] + +local colorize, irtype + +-- Lookup tables to convert some literals into names. +local litname = { + ["SLOAD "] = setmetatable({}, { __index = function(t, mode) + local s = "" + if band(mode, 1) ~= 0 then s = s.."P" end + if band(mode, 2) ~= 0 then s = s.."F" end + if band(mode, 4) ~= 0 then s = s.."T" end + if band(mode, 8) ~= 0 then s = s.."C" end + if band(mode, 16) ~= 0 then s = s.."R" end + if band(mode, 32) ~= 0 then s = s.."I" end + if band(mode, 64) ~= 0 then s = s.."K" end + t[mode] = s + return s + end}), + ["XLOAD "] = { [0] = "", "R", "V", "RV", "U", "RU", "VU", "RVU", }, + ["CONV "] = setmetatable({}, { __index = function(t, mode) + local s = irtype[band(mode, 31)] + s = irtype[band(shr(mode, 5), 31)].."."..s + if band(mode, 0x800) ~= 0 then s = s.." sext" end + local c = shr(mode, 12) + if c == 1 then s = s.." none" + elseif c == 2 then s = s.." index" + elseif c == 3 then s = s.." check" end + t[mode] = s + return s + end}), + ["FLOAD "] = vmdef.irfield, + ["FREF "] = vmdef.irfield, + ["FPMATH"] = vmdef.irfpm, + ["TMPREF"] = { [0] = "", "IN", "OUT", "INOUT", "", "", "OUT2", "INOUT2" }, + ["BUFHDR"] = { [0] = "RESET", "APPEND", "WRITE" }, + ["TOSTR "] = { [0] = "INT", "NUM", "CHAR" }, +} + +local function ctlsub(c) + if c == "\n" then return "\\n" + elseif c == "\r" then return "\\r" + elseif c == "\t" then return "\\t" + else return format("\\%03d", byte(c)) + end +end + +local function fmtfunc(func, pc) + local fi = funcinfo(func, pc) + if fi.loc then + return fi.loc + elseif fi.ffid then + return vmdef.ffnames[fi.ffid] + elseif fi.addr then + return format("C:%x", fi.addr) + else + return "(?)" + end +end + +local function formatk(tr, idx, sn) + local k, t, slot = tracek(tr, idx) + local tn = type(k) + local s + if tn == "number" then + if t < 12 then + s = k == 0 and "NULL" or format("[0x%08x]", k) + elseif band(sn or 0, 0x30000) ~= 0 then + s = band(sn, 0x20000) ~= 0 and "contpc" or "ftsz" + elseif k == 2^52+2^51 then + s = "bias" + else + s = format(0 < k and k < 0x1p-1026 and "%+a" or "%+.14g", k) + end + elseif tn == "string" then + s = format(#k > 20 and '"%.20s"~' or '"%s"', gsub(k, "%c", ctlsub)) + elseif tn == "function" then + s = fmtfunc(k) + elseif tn == "table" then + s = format("{%p}", k) + elseif tn == "userdata" then + if t == 12 then + s = format("userdata:%p", k) + else + s = format("[%p]", k) + if s == "[NULL]" then s = "NULL" end + end + elseif t == 21 then -- int64_t + s = sub(tostring(k), 1, -3) + if sub(s, 1, 1) ~= "-" then s = "+"..s end + elseif sn == 0x1057fff then -- SNAP(1, SNAP_FRAME | SNAP_NORESTORE, REF_NIL) + return "----" -- Special case for LJ_FR2 slot 1. + else + s = tostring(k) -- For primitives. + end + s = colorize(format("%-4s", s), t, band(sn or 0, 0x100000) ~= 0) + if slot then + s = format("%s @%d", s, slot) + end + return s +end + +local function printsnap(tr, snap) + local n = 2 + for s=0,snap[1]-1 do + local sn = snap[n] + if shr(sn, 24) == s then + n = n + 1 + local ref = band(sn, 0xffff) - 0x8000 -- REF_BIAS + if ref < 0 then + out:write(formatk(tr, ref, sn)) + elseif band(sn, 0x80000) ~= 0 then -- SNAP_SOFTFPNUM + out:write(colorize(format("%04d/%04d", ref, ref+1), 14)) + else + local m, ot, op1, op2 = traceir(tr, ref) + out:write(colorize(format("%04d", ref), band(ot, 31), band(sn, 0x100000) ~= 0)) + end + out:write(band(sn, 0x10000) == 0 and " " or "|") -- SNAP_FRAME + else + out:write("---- ") + end + end + out:write("]\n") +end + +-- Dump snapshots (not interleaved with IR). +local function dump_snap(tr) + out:write("---- TRACE ", tr, " snapshots\n") + for i=0,1000000000 do + local snap = tracesnap(tr, i) + if not snap then break end + out:write(format("#%-3d %04d [ ", i, snap[0])) + printsnap(tr, snap) + end +end + +-- Return a register name or stack slot for a rid/sp location. +local function ridsp_name(ridsp, ins) + if not disass then disass = require("jit.dis_"..jit.arch) end + local rid, slot = band(ridsp, 0xff), shr(ridsp, 8) + if rid == 253 or rid == 254 then + return (slot == 0 or slot == 255) and " {sink" or format(" {%04d", ins-slot) + end + if ridsp > 255 then return format("[%x]", slot*4) end + if rid < 128 then return disass.regname(rid) end + return "" +end + +-- Dump CALL* function ref and return optional ctype. +local function dumpcallfunc(tr, ins) + local ctype + if ins > 0 then + local m, ot, op1, op2 = traceir(tr, ins) + if band(ot, 31) == 0 then -- nil type means CARG(func, ctype). + ins = op1 + ctype = formatk(tr, op2) + end + end + if ins < 0 then + out:write(format("[0x%x](", tonumber((tracek(tr, ins))))) + else + out:write(format("%04d (", ins)) + end + return ctype +end + +-- Recursively gather CALL* args and dump them. +local function dumpcallargs(tr, ins) + if ins < 0 then + out:write(formatk(tr, ins)) + else + local m, ot, op1, op2 = traceir(tr, ins) + local oidx = 6*shr(ot, 8) + local op = sub(vmdef.irnames, oidx+1, oidx+6) + if op == "CARG " then + dumpcallargs(tr, op1) + if op2 < 0 then + out:write(" ", formatk(tr, op2)) + else + out:write(" ", format("%04d", op2)) + end + else + out:write(format("%04d", ins)) + end + end +end + +-- Dump IR and interleaved snapshots. +local function dump_ir(tr, dumpsnap, dumpreg) + local info = traceinfo(tr) + if not info then return end + local nins = info.nins + out:write("---- TRACE ", tr, " IR\n") + local irnames = vmdef.irnames + local snapref = 65536 + local snap, snapno + if dumpsnap then + snap = tracesnap(tr, 0) + snapref = snap[0] + snapno = 0 + end + for ins=1,nins do + if ins >= snapref then + if dumpreg then + out:write(format(".... SNAP #%-3d [ ", snapno)) + else + out:write(format(".... SNAP #%-3d [ ", snapno)) + end + printsnap(tr, snap) + snapno = snapno + 1 + snap = tracesnap(tr, snapno) + snapref = snap and snap[0] or 65536 + end + local m, ot, op1, op2, ridsp = traceir(tr, ins) + local oidx, t = 6*shr(ot, 8), band(ot, 31) + local op = sub(irnames, oidx+1, oidx+6) + if op == "LOOP " then + if dumpreg then + out:write(format("%04d ------------ LOOP ------------\n", ins)) + else + out:write(format("%04d ------ LOOP ------------\n", ins)) + end + elseif op ~= "NOP " and op ~= "CARG " and + (dumpreg or op ~= "RENAME") then + local rid = band(ridsp, 255) + if dumpreg then + out:write(format("%04d %-6s", ins, ridsp_name(ridsp, ins))) + else + out:write(format("%04d ", ins)) + end + out:write(format("%s%s %s %s ", + (rid == 254 or rid == 253) and "}" or + (band(ot, 128) == 0 and " " or ">"), + band(ot, 64) == 0 and " " or "+", + irtype[t], op)) + local m1, m2 = band(m, 3), band(m, 3*4) + if sub(op, 1, 4) == "CALL" then + local ctype + if m2 == 1*4 then -- op2 == IRMlit + out:write(format("%-10s (", vmdef.ircall[op2])) + else + ctype = dumpcallfunc(tr, op2) + end + if op1 ~= -1 then dumpcallargs(tr, op1) end + out:write(")") + if ctype then out:write(" ctype ", ctype) end + elseif op == "CNEW " and op2 == -1 then + out:write(formatk(tr, op1)) + elseif m1 ~= 3 then -- op1 != IRMnone + if op1 < 0 then + out:write(formatk(tr, op1)) + else + out:write(format(m1 == 0 and "%04d" or "#%-3d", op1)) + end + if m2 ~= 3*4 then -- op2 != IRMnone + if m2 == 1*4 then -- op2 == IRMlit + local litn = litname[op] + if litn and litn[op2] then + out:write(" ", litn[op2]) + elseif op == "UREFO " or op == "UREFC " then + out:write(format(" #%-3d", shr(op2, 8))) + else + out:write(format(" #%-3d", op2)) + end + elseif op2 < 0 then + out:write(" ", formatk(tr, op2)) + else + out:write(format(" %04d", op2)) + end + end + end + out:write("\n") + end + end + if snap then + if dumpreg then + out:write(format(".... SNAP #%-3d [ ", snapno)) + else + out:write(format(".... SNAP #%-3d [ ", snapno)) + end + printsnap(tr, snap) + end +end + +------------------------------------------------------------------------------ + +local recprefix = "" +local recdepth = 0 + +-- Format trace error message. +local function fmterr(err, info) + if type(err) == "number" then + if type(info) == "function" then info = fmtfunc(info) end + err = format(vmdef.traceerr[err], info) + end + return err +end + +-- Dump trace states. +local function dump_trace(what, tr, func, pc, otr, oex) + if what == "stop" or (what == "abort" and dumpmode.a) then + if dumpmode.i then dump_ir(tr, dumpmode.s, dumpmode.r and what == "stop") + elseif dumpmode.s then dump_snap(tr) end + if dumpmode.m then dump_mcode(tr) end + end + if what == "start" then + if dumpmode.H then out:write('<pre class="ljdump">\n') end + out:write("---- TRACE ", tr, " ", what) + if otr then out:write(" ", otr, "/", oex == -1 and "stitch" or oex) end + out:write(" ", fmtfunc(func, pc), "\n") + elseif what == "stop" or what == "abort" then + out:write("---- TRACE ", tr, " ", what) + if what == "abort" then + out:write(" ", fmtfunc(func, pc), " -- ", fmterr(otr, oex), "\n") + else + local info = traceinfo(tr) + local link, ltype = info.link, info.linktype + if link == tr or link == 0 then + out:write(" -> ", ltype, "\n") + elseif ltype == "root" then + out:write(" -> ", link, "\n") + else + out:write(" -> ", link, " ", ltype, "\n") + end + end + if dumpmode.H then out:write("</pre>\n\n") else out:write("\n") end + else + if what == "flush" then symtab, nexitsym = {}, 0 end + out:write("---- TRACE ", what, "\n\n") + end + out:flush() +end + +-- Dump recorded bytecode. +local function dump_record(tr, func, pc, depth) + if depth ~= recdepth then + recdepth = depth + recprefix = rep(" .", depth) + end + local line + if pc >= 0 then + line = bcline(func, pc, recprefix) + if dumpmode.H then line = gsub(line, "[<>&]", html_escape) end + else + line = "0000 "..recprefix.." FUNCC \n" + end + if pc <= 0 then + out:write(sub(line, 1, -2), " ; ", fmtfunc(func), "\n") + else + out:write(line) + end + if pc >= 0 and band(funcbc(func, pc), 0xff) < 16 then -- ORDER BC + out:write(bcline(func, pc+1, recprefix)) -- Write JMP for cond. + end +end + +------------------------------------------------------------------------------ + +local gpr64 = jit.arch:match("64") +local fprmips32 = jit.arch == "mips" or jit.arch == "mipsel" + +-- Dump taken trace exits. +local function dump_texit(tr, ex, ngpr, nfpr, ...) + out:write("---- TRACE ", tr, " exit ", ex, "\n") + if dumpmode.X then + local regs = {...} + if gpr64 then + for i=1,ngpr do + out:write(format(" %016x", regs[i])) + if i % 4 == 0 then out:write("\n") end + end + else + for i=1,ngpr do + out:write(" ", tohex(regs[i])) + if i % 8 == 0 then out:write("\n") end + end + end + if fprmips32 then + for i=1,nfpr,2 do + out:write(format(" %+17.14g", regs[ngpr+i])) + if i % 8 == 7 then out:write("\n") end + end + else + for i=1,nfpr do + out:write(format(" %+17.14g", regs[ngpr+i])) + if i % 4 == 0 then out:write("\n") end + end + end + end +end + +------------------------------------------------------------------------------ + +-- Detach dump handlers. +local function dumpoff() + if active then + active = false + jit.attach(dump_texit) + jit.attach(dump_record) + jit.attach(dump_trace) + if out and out ~= stdout and out ~= stderr then out:close() end + out = nil + end +end + +-- Open the output file and attach dump handlers. +local function dumpon(opt, outfile) + if active then dumpoff() end + + local term = os.getenv("TERM") + local colormode = (term and term:match("color") or os.getenv("COLORTERM")) and "A" or "T" + if opt then + opt = gsub(opt, "[TAH]", function(mode) colormode = mode; return ""; end) + end + + local m = { t=true, b=true, i=true, m=true, } + if opt and opt ~= "" then + local o = sub(opt, 1, 1) + if o ~= "+" and o ~= "-" then m = {} end + for i=1,#opt do m[sub(opt, i, i)] = (o ~= "-") end + end + dumpmode = m + + if m.t or m.b or m.i or m.s or m.m then + jit.attach(dump_trace, "trace") + end + if m.b then + jit.attach(dump_record, "record") + if not bcline then bcline = require("jit.bc").line end + end + if m.x or m.X then + jit.attach(dump_texit, "texit") + end + + if not outfile then outfile = os.getenv("LUAJIT_DUMPFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stdout + end + + m[colormode] = true + if colormode == "A" then + colorize = colorize_ansi + irtype = irtype_ansi + elseif colormode == "H" then + colorize = colorize_html + irtype = irtype_html + out:write(header_html) + else + colorize = colorize_text + irtype = irtype_text + end + + active = true +end + +-- Public module functions. +return { + on = dumpon, + off = dumpoff, + start = dumpon -- For -j command line option. +} + diff --git a/libs/luajit-cmake/luajit/src/jit/p.lua b/libs/luajit-cmake/luajit/src/jit/p.lua new file mode 100644 index 0000000..f225c31 --- /dev/null +++ b/libs/luajit-cmake/luajit/src/jit/p.lua @@ -0,0 +1,312 @@ +---------------------------------------------------------------------------- +-- LuaJIT profiler. +-- +-- Copyright (C) 2005-2022 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module is a simple command line interface to the built-in +-- low-overhead profiler of LuaJIT. +-- +-- The lower-level API of the profiler is accessible via the "jit.profile" +-- module or the luaJIT_profile_* C API. +-- +-- Example usage: +-- +-- luajit -jp myapp.lua +-- luajit -jp=s myapp.lua +-- luajit -jp=-s myapp.lua +-- luajit -jp=vl myapp.lua +-- luajit -jp=G,profile.txt myapp.lua +-- +-- The following dump features are available: +-- +-- f Stack dump: function name, otherwise module:line. Default mode. +-- F Stack dump: ditto, but always prepend module. +-- l Stack dump: module:line. +-- <number> stack dump depth (callee < caller). Default: 1. +-- -<number> Inverse stack dump depth (caller > callee). +-- s Split stack dump after first stack level. Implies abs(depth) >= 2. +-- p Show full path for module names. +-- v Show VM states. Can be combined with stack dumps, e.g. vf or fv. +-- z Show zones. Can be combined with stack dumps, e.g. zf or fz. +-- r Show raw sample counts. Default: show percentages. +-- a Annotate excerpts from source code files. +-- A Annotate complete source code files. +-- G Produce raw output suitable for graphical tools (e.g. flame graphs). +-- m<number> Minimum sample percentage to be shown. Default: 3. +-- i<number> Sampling interval in milliseconds. Default: 10. +-- +---------------------------------------------------------------------------- + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local profile = require("jit.profile") +local vmdef = require("jit.vmdef") +local math = math +local pairs, ipairs, tonumber, floor = pairs, ipairs, tonumber, math.floor +local sort, format = table.sort, string.format +local stdout = io.stdout +local zone -- Load jit.zone module on demand. + +-- Output file handle. +local out + +------------------------------------------------------------------------------ + +local prof_ud +local prof_states, prof_split, prof_min, prof_raw, prof_fmt, prof_depth +local prof_ann, prof_count1, prof_count2, prof_samples + +local map_vmmode = { + N = "Compiled", + I = "Interpreted", + C = "C code", + G = "Garbage Collector", + J = "JIT Compiler", +} + +-- Profiler callback. +local function prof_cb(th, samples, vmmode) + prof_samples = prof_samples + samples + local key_stack, key_stack2, key_state + -- Collect keys for sample. + if prof_states then + if prof_states == "v" then + key_state = map_vmmode[vmmode] or vmmode + else + key_state = zone:get() or "(none)" + end + end + if prof_fmt then + key_stack = profile.dumpstack(th, prof_fmt, prof_depth) + key_stack = key_stack:gsub("%[builtin#(%d+)%]", function(x) + return vmdef.ffnames[tonumber(x)] + end) + if prof_split == 2 then + local k1, k2 = key_stack:match("(.-) [<>] (.*)") + if k2 then key_stack, key_stack2 = k1, k2 end + elseif prof_split == 3 then + key_stack2 = profile.dumpstack(th, "l", 1) + end + end + -- Order keys. + local k1, k2 + if prof_split == 1 then + if key_state then + k1 = key_state + if key_stack then k2 = key_stack end + end + elseif key_stack then + k1 = key_stack + if key_stack2 then k2 = key_stack2 elseif key_state then k2 = key_state end + end + -- Coalesce samples in one or two levels. + if k1 then + local t1 = prof_count1 + t1[k1] = (t1[k1] or 0) + samples + if k2 then + local t2 = prof_count2 + local t3 = t2[k1] + if not t3 then t3 = {}; t2[k1] = t3 end + t3[k2] = (t3[k2] or 0) + samples + end + end +end + +------------------------------------------------------------------------------ + +-- Show top N list. +local function prof_top(count1, count2, samples, indent) + local t, n = {}, 0 + for k in pairs(count1) do + n = n + 1 + t[n] = k + end + sort(t, function(a, b) return count1[a] > count1[b] end) + for i=1,n do + local k = t[i] + local v = count1[k] + local pct = floor(v*100/samples + 0.5) + if pct < prof_min then break end + if not prof_raw then + out:write(format("%s%2d%% %s\n", indent, pct, k)) + elseif prof_raw == "r" then + out:write(format("%s%5d %s\n", indent, v, k)) + else + out:write(format("%s %d\n", k, v)) + end + if count2 then + local r = count2[k] + if r then + prof_top(r, nil, v, (prof_split == 3 or prof_split == 1) and " -- " or + (prof_depth < 0 and " -> " or " <- ")) + end + end + end +end + +-- Annotate source code +local function prof_annotate(count1, samples) + local files = {} + local ms = 0 + for k, v in pairs(count1) do + local pct = floor(v*100/samples + 0.5) + ms = math.max(ms, v) + if pct >= prof_min then + local file, line = k:match("^(.*):(%d+)$") + if not file then file = k; line = 0 end + local fl = files[file] + if not fl then fl = {}; files[file] = fl; files[#files+1] = file end + line = tonumber(line) + fl[line] = prof_raw and v or pct + end + end + sort(files) + local fmtv, fmtn = " %3d%% | %s\n", " | %s\n" + if prof_raw then + local n = math.max(5, math.ceil(math.log10(ms))) + fmtv = "%"..n.."d | %s\n" + fmtn = (" "):rep(n).." | %s\n" + end + local ann = prof_ann + for _, file in ipairs(files) do + local f0 = file:byte() + if f0 == 40 or f0 == 91 then + out:write(format("\n====== %s ======\n[Cannot annotate non-file]\n", file)) + break + end + local fp, err = io.open(file) + if not fp then + out:write(format("====== ERROR: %s: %s\n", file, err)) + break + end + out:write(format("\n====== %s ======\n", file)) + local fl = files[file] + local n, show = 1, false + if ann ~= 0 then + for i=1,ann do + if fl[i] then show = true; out:write("@@ 1 @@\n"); break end + end + end + for line in fp:lines() do + if line:byte() == 27 then + out:write("[Cannot annotate bytecode file]\n") + break + end + local v = fl[n] + if ann ~= 0 then + local v2 = fl[n+ann] + if show then + if v2 then show = n+ann elseif v then show = n + elseif show+ann < n then show = false end + elseif v2 then + show = n+ann + out:write(format("@@ %d @@\n", n)) + end + if not show then goto next end + end + if v then + out:write(format(fmtv, v, line)) + else + out:write(format(fmtn, line)) + end + ::next:: + n = n + 1 + end + fp:close() + end +end + +------------------------------------------------------------------------------ + +-- Finish profiling and dump result. +local function prof_finish() + if prof_ud then + profile.stop() + local samples = prof_samples + if samples == 0 then + if prof_raw ~= true then out:write("[No samples collected]\n") end + return + end + if prof_ann then + prof_annotate(prof_count1, samples) + else + prof_top(prof_count1, prof_count2, samples, "") + end + prof_count1 = nil + prof_count2 = nil + prof_ud = nil + if out ~= stdout then out:close() end + end +end + +-- Start profiling. +local function prof_start(mode) + local interval = "" + mode = mode:gsub("i%d*", function(s) interval = s; return "" end) + prof_min = 3 + mode = mode:gsub("m(%d+)", function(s) prof_min = tonumber(s); return "" end) + prof_depth = 1 + mode = mode:gsub("%-?%d+", function(s) prof_depth = tonumber(s); return "" end) + local m = {} + for c in mode:gmatch(".") do m[c] = c end + prof_states = m.z or m.v + if prof_states == "z" then zone = require("jit.zone") end + local scope = m.l or m.f or m.F or (prof_states and "" or "f") + local flags = (m.p or "") + prof_raw = m.r + if m.s then + prof_split = 2 + if prof_depth == -1 or m["-"] then prof_depth = -2 + elseif prof_depth == 1 then prof_depth = 2 end + elseif mode:find("[fF].*l") then + scope = "l" + prof_split = 3 + else + prof_split = (scope == "" or mode:find("[zv].*[lfF]")) and 1 or 0 + end + prof_ann = m.A and 0 or (m.a and 3) + if prof_ann then + scope = "l" + prof_fmt = "pl" + prof_split = 0 + prof_depth = 1 + elseif m.G and scope ~= "" then + prof_fmt = flags..scope.."Z;" + prof_depth = -100 + prof_raw = true + prof_min = 0 + elseif scope == "" then + prof_fmt = false + else + local sc = prof_split == 3 and m.f or m.F or scope + prof_fmt = flags..sc..(prof_depth >= 0 and "Z < " or "Z > ") + end + prof_count1 = {} + prof_count2 = {} + prof_samples = 0 + profile.start(scope:lower()..interval, prof_cb) + prof_ud = newproxy(true) + getmetatable(prof_ud).__gc = prof_finish +end + +------------------------------------------------------------------------------ + +local function start(mode, outfile) + if not outfile then outfile = os.getenv("LUAJIT_PROFILEFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stdout + end + prof_start(mode or "f") +end + +-- Public module functions. +return { + start = start, -- For -j command line option. + stop = prof_finish +} + diff --git a/libs/luajit-cmake/luajit/src/jit/v.lua b/libs/luajit-cmake/luajit/src/jit/v.lua new file mode 100644 index 0000000..ac8b19d --- /dev/null +++ b/libs/luajit-cmake/luajit/src/jit/v.lua @@ -0,0 +1,170 @@ +---------------------------------------------------------------------------- +-- Verbose mode of the LuaJIT compiler. +-- +-- Copyright (C) 2005-2022 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module shows verbose information about the progress of the +-- JIT compiler. It prints one line for each generated trace. This module +-- is useful to see which code has been compiled or where the compiler +-- punts and falls back to the interpreter. +-- +-- Example usage: +-- +-- luajit -jv -e "for i=1,1000 do for j=1,1000 do end end" +-- luajit -jv=myapp.out myapp.lua +-- +-- Default output is to stderr. To redirect the output to a file, pass a +-- filename as an argument (use '-' for stdout) or set the environment +-- variable LUAJIT_VERBOSEFILE. The file is overwritten every time the +-- module is started. +-- +-- The output from the first example should look like this: +-- +-- [TRACE 1 (command line):1 loop] +-- [TRACE 2 (1/3) (command line):1 -> 1] +-- +-- The first number in each line is the internal trace number. Next are +-- the file name ('(command line)') and the line number (':1') where the +-- trace has started. Side traces also show the parent trace number and +-- the exit number where they are attached to in parentheses ('(1/3)'). +-- An arrow at the end shows where the trace links to ('-> 1'), unless +-- it loops to itself. +-- +-- In this case the inner loop gets hot and is traced first, generating +-- a root trace. Then the last exit from the 1st trace gets hot, too, +-- and triggers generation of the 2nd trace. The side trace follows the +-- path along the outer loop and *around* the inner loop, back to its +-- start, and then links to the 1st trace. Yes, this may seem unusual, +-- if you know how traditional compilers work. Trace compilers are full +-- of surprises like this -- have fun! :-) +-- +-- Aborted traces are shown like this: +-- +-- [TRACE --- foo.lua:44 -- leaving loop in root trace at foo:lua:50] +-- +-- Don't worry -- trace aborts are quite common, even in programs which +-- can be fully compiled. The compiler may retry several times until it +-- finds a suitable trace. +-- +-- Of course this doesn't work with features that are not-yet-implemented +-- (NYI error messages). The VM simply falls back to the interpreter. This +-- may not matter at all if the particular trace is not very high up in +-- the CPU usage profile. Oh, and the interpreter is quite fast, too. +-- +-- Also check out the -jdump module, which prints all the gory details. +-- +------------------------------------------------------------------------------ + +-- Cache some library functions and objects. +local jit = require("jit") +assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") +local jutil = require("jit.util") +local vmdef = require("jit.vmdef") +local funcinfo, traceinfo = jutil.funcinfo, jutil.traceinfo +local type, format = type, string.format +local stdout, stderr = io.stdout, io.stderr + +-- Active flag and output file handle. +local active, out + +------------------------------------------------------------------------------ + +local startloc, startex + +local function fmtfunc(func, pc) + local fi = funcinfo(func, pc) + if fi.loc then + return fi.loc + elseif fi.ffid then + return vmdef.ffnames[fi.ffid] + elseif fi.addr then + return format("C:%x", fi.addr) + else + return "(?)" + end +end + +-- Format trace error message. +local function fmterr(err, info) + if type(err) == "number" then + if type(info) == "function" then info = fmtfunc(info) end + err = format(vmdef.traceerr[err], info) + end + return err +end + +-- Dump trace states. +local function dump_trace(what, tr, func, pc, otr, oex) + if what == "start" then + startloc = fmtfunc(func, pc) + startex = otr and "("..otr.."/"..(oex == -1 and "stitch" or oex)..") " or "" + else + if what == "abort" then + local loc = fmtfunc(func, pc) + if loc ~= startloc then + out:write(format("[TRACE --- %s%s -- %s at %s]\n", + startex, startloc, fmterr(otr, oex), loc)) + else + out:write(format("[TRACE --- %s%s -- %s]\n", + startex, startloc, fmterr(otr, oex))) + end + elseif what == "stop" then + local info = traceinfo(tr) + local link, ltype = info.link, info.linktype + if ltype == "interpreter" then + out:write(format("[TRACE %3s %s%s -- fallback to interpreter]\n", + tr, startex, startloc)) + elseif ltype == "stitch" then + out:write(format("[TRACE %3s %s%s %s %s]\n", + tr, startex, startloc, ltype, fmtfunc(func, pc))) + elseif link == tr or link == 0 then + out:write(format("[TRACE %3s %s%s %s]\n", + tr, startex, startloc, ltype)) + elseif ltype == "root" then + out:write(format("[TRACE %3s %s%s -> %d]\n", + tr, startex, startloc, link)) + else + out:write(format("[TRACE %3s %s%s -> %d %s]\n", + tr, startex, startloc, link, ltype)) + end + else + out:write(format("[TRACE %s]\n", what)) + end + out:flush() + end +end + +------------------------------------------------------------------------------ + +-- Detach dump handlers. +local function dumpoff() + if active then + active = false + jit.attach(dump_trace) + if out and out ~= stdout and out ~= stderr then out:close() end + out = nil + end +end + +-- Open the output file and attach dump handlers. +local function dumpon(outfile) + if active then dumpoff() end + if not outfile then outfile = os.getenv("LUAJIT_VERBOSEFILE") end + if outfile then + out = outfile == "-" and stdout or assert(io.open(outfile, "w")) + else + out = stderr + end + jit.attach(dump_trace, "trace") + active = true +end + +-- Public module functions. +return { + on = dumpon, + off = dumpoff, + start = dumpon -- For -j command line option. +} + diff --git a/libs/luajit-cmake/luajit/src/jit/zone.lua b/libs/luajit-cmake/luajit/src/jit/zone.lua new file mode 100644 index 0000000..1308cb7 --- /dev/null +++ b/libs/luajit-cmake/luajit/src/jit/zone.lua @@ -0,0 +1,45 @@ +---------------------------------------------------------------------------- +-- LuaJIT profiler zones. +-- +-- Copyright (C) 2005-2022 Mike Pall. All rights reserved. +-- Released under the MIT license. See Copyright Notice in luajit.h +---------------------------------------------------------------------------- +-- +-- This module implements a simple hierarchical zone model. +-- +-- Example usage: +-- +-- local zone = require("jit.zone") +-- zone("AI") +-- ... +-- zone("A*") +-- ... +-- print(zone:get()) --> "A*" +-- ... +-- zone() +-- ... +-- print(zone:get()) --> "AI" +-- ... +-- zone() +-- +---------------------------------------------------------------------------- + +local remove = table.remove + +return setmetatable({ + flush = function(t) + for i=#t,1,-1 do t[i] = nil end + end, + get = function(t) + return t[#t] + end +}, { + __call = function(t, zone) + if zone then + t[#t+1] = zone + else + return (assert(remove(t), "empty zone stack")) + end + end +}) + |