From b270bf026ed1f30334a8634dc2e0a07a3cf889f9 Mon Sep 17 00:00:00 2001 From: Luke Gorrie Date: Mon, 13 Mar 2017 11:25:02 +0000 Subject: [PATCH] Remove jit.p, jit.v, jit.dump, disassemblers RaptorJIT strategy is not to do this introspectively with a Lua API but rather to export the necessary data to external tools (that need to be developed.) --- src/jit/dis_arm.lua | 689 --------------------- src/jit/dis_arm64.lua | 1216 -------------------------------------- src/jit/dis_mips.lua | 443 -------------- src/jit/dis_mips64.lua | 17 - src/jit/dis_mips64el.lua | 17 - src/jit/dis_mipsel.lua | 17 - src/jit/dis_ppc.lua | 591 ------------------ src/jit/dis_x64.lua | 17 - src/jit/dis_x86.lua | 931 ----------------------------- src/jit/dump.lua | 712 ---------------------- src/jit/p.lua | 311 ---------- src/jit/v.lua | 170 ------ src/jit/zone.lua | 45 -- 13 files changed, 5176 deletions(-) delete mode 100644 src/jit/dis_arm.lua delete mode 100644 src/jit/dis_arm64.lua delete mode 100644 src/jit/dis_mips.lua delete mode 100644 src/jit/dis_mips64.lua delete mode 100644 src/jit/dis_mips64el.lua delete mode 100644 src/jit/dis_mipsel.lua delete mode 100644 src/jit/dis_ppc.lua delete mode 100644 src/jit/dis_x64.lua delete mode 100644 src/jit/dis_x86.lua delete mode 100644 src/jit/dump.lua delete mode 100644 src/jit/p.lua delete mode 100644 src/jit/v.lua delete mode 100644 src/jit/zone.lua diff --git a/src/jit/dis_arm.lua b/src/jit/dis_arm.lua deleted file mode 100644 index c2dd776991..0000000000 --- a/src/jit/dis_arm.lua +++ /dev/null @@ -1,689 +0,0 @@ ----------------------------------------------------------------------------- --- LuaJIT ARM disassembler module. --- --- Copyright (C) 2005-2017 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/src/jit/dis_arm64.lua b/src/jit/dis_arm64.lua deleted file mode 100644 index a7173326ac..0000000000 --- a/src/jit/dis_arm64.lua +++ /dev/null @@ -1,1216 +0,0 @@ ----------------------------------------------------------------------------- --- LuaJIT ARM64 disassembler module. --- --- Copyright (C) 2005-2017 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 - elseif x >= immr then - name = a2 - x = x - immr + 1 - end - end - elseif p == "4" then - x = band(rshift(op, 10), 63) - local rn = band(rshift(op, 5), 31) - local rm = band(rshift(op, 16), 31) - if altname and rn == rm then - local n = #operands - operands[n] = nil - last = operands[n-1] - name = altname - end - elseif p == "5" then - x = band(rshift(op, 16), 31) - elseif p == "S" then - x = band(rshift(op, 10), 63) - if x == 0 then x = nil - else x = map_shift[band(rshift(op, 22), 3)].." #"..x end - elseif p == "X" then - local opt = band(rshift(op, 13), 7) - -- Width specifier . - if opt ~= 3 and opt ~= 7 then - last = map_regs.w[band(rshift(op, 16), 31)] - operands[#operands] = last - end - x = band(rshift(op, 10), 7) - -- Extension. - if opt == 2 + band(rshift(op, 31), 1) and - band(rshift(op, second0 and 5 or 0), 31) == 31 then - if x == 0 then x = nil - else x = "lsl #"..x end - else - if x == 0 then x = map_extend[band(rshift(op, 13), 7)] - else x = map_extend[band(rshift(op, 13), 7)].." #"..x end - end - elseif p == "R" then - x = band(rshift(op,21), 3) - if x == 0 then x = nil - else x = "lsl #"..x*16 end - elseif p == "z" then - local n = #operands - if operands[n] == "sp" then operands[n] = "xzr" - elseif operands[n] == "wsp" then operands[n] = "wzr" - end - elseif p == "Z" then - x = 0 - elseif p == "F" then - x = parse_fpimm8(op) - elseif p == "g" or p == "f" or p == "x" or p == "w" or - p == "d" or p == "s" then - -- These are handled in D/N/M/A. - elseif p == "0" then - if last == "sp" or last == "wsp" then - local n = #operands - operands[n] = nil - last = operands[n-1] - if altname then - local a1, a2 = match(altname, "([^|]*)|(.*)") - if not a1 then - name = altname - elseif second0 then - name, altname = a2, a1 - else - name, altname = a1, a2 - end - end - end - second0 = true - else - assert(false) - end - if x then - last = x - if type(x) == "number" then x = "#"..x end - operands[#operands+1] = x - end - end - - return putop(ctx, name..suffix, operands) -end - ------------------------------------------------------------------------------- - --- Disassemble a block of code. -local function disass_block(ctx, ofs, len) - if not ofs then ofs = 0 end - local stop = len and ofs+len or #ctx.code - ctx.pos = ofs - ctx.rel = nil - while ctx.pos < stop do disass_ins(ctx) end -end - --- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). -local function create(code, addr, out) - local ctx = {} - ctx.code = code - ctx.addr = addr or 0 - ctx.out = out or io.write - ctx.symtab = {} - ctx.disass = disass_block - ctx.hexdump = 8 - return ctx -end - --- Simple API: disassemble code (a string) at address and output via out. -local function disass(code, addr, out) - create(code, addr, out):disass() -end - --- Return register name for RID. -local function regname(r) - if r < 32 then return map_regs.x[r] end - return map_regs.d[r-32] -end - --- Public module functions. -return { - create = create, - disass = disass, - regname = regname -} - diff --git a/src/jit/dis_mips.lua b/src/jit/dis_mips.lua deleted file mode 100644 index a12b8e62f3..0000000000 --- a/src/jit/dis_mips.lua +++ /dev/null @@ -1,443 +0,0 @@ ----------------------------------------------------------------------------- --- LuaJIT MIPS disassembler module. --- --- Copyright (C) 2005-2017 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 - ------------------------------------------------------------------------------- --- Primary and extended opcode maps ------------------------------------------------------------------------------- - -local map_movci = { shift = 16, mask = 1, [0] = "movfDSC", "movtDSC", } -local map_srl = { shift = 21, mask = 1, [0] = "srlDTA", "rotrDTA", } -local map_srlv = { shift = 6, mask = 1, [0] = "srlvDTS", "rotrvDTS", } - -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_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", - }, -} - -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", -} - ------------------------------------------------------------------------------- - -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 = map_pri[rshift(op, 26)] - 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 - 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 == "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 == "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), 16)*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 - return ctx -end - -local function create_el(code, addr, out) - local ctx = create(code, addr, out) - ctx.get = get_le - 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 - --- 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, - disass = disass, - disass_el = disass_el, - regname = regname -} - diff --git a/src/jit/dis_mips64.lua b/src/jit/dis_mips64.lua deleted file mode 100644 index c4374928ab..0000000000 --- a/src/jit/dis_mips64.lua +++ /dev/null @@ -1,17 +0,0 @@ ----------------------------------------------------------------------------- --- LuaJIT MIPS64 disassembler wrapper module. --- --- Copyright (C) 2005-2017 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/src/jit/dis_mips64el.lua b/src/jit/dis_mips64el.lua deleted file mode 100644 index 2b1470af50..0000000000 --- a/src/jit/dis_mips64el.lua +++ /dev/null @@ -1,17 +0,0 @@ ----------------------------------------------------------------------------- --- LuaJIT MIPS64EL disassembler wrapper module. --- --- Copyright (C) 2005-2017 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/src/jit/dis_mipsel.lua b/src/jit/dis_mipsel.lua deleted file mode 100644 index f69b11f01f..0000000000 --- a/src/jit/dis_mipsel.lua +++ /dev/null @@ -1,17 +0,0 @@ ----------------------------------------------------------------------------- --- LuaJIT MIPSEL disassembler wrapper module. --- --- Copyright (C) 2005-2017 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/src/jit/dis_ppc.lua b/src/jit/dis_ppc.lua deleted file mode 100644 index 2aeb1b2924..0000000000 --- a/src/jit/dis_ppc.lua +++ /dev/null @@ -1,591 +0,0 @@ ----------------------------------------------------------------------------- --- LuaJIT PPC disassembler module. --- --- Copyright (C) 2005-2017 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/src/jit/dis_x64.lua b/src/jit/dis_x64.lua deleted file mode 100644 index d5714ee1f7..0000000000 --- a/src/jit/dis_x64.lua +++ /dev/null @@ -1,17 +0,0 @@ ----------------------------------------------------------------------------- --- LuaJIT x64 disassembler wrapper module. --- --- Copyright (C) 2005-2017 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/src/jit/dis_x86.lua b/src/jit/dis_x86.lua deleted file mode 100644 index 4371233d2b..0000000000 --- a/src/jit/dis_x86.lua +++ /dev/null @@ -1,931 +0,0 @@ ----------------------------------------------------------------------------- --- LuaJIT x86/x64 disassembler module. --- --- Copyright (C) 2005-2017 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", ---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: 1DFGIMPQRSTUVWXYabcdfgijlmoprstuvwxyz - 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 == "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, - - -- 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/src/jit/dump.lua b/src/jit/dump.lua deleted file mode 100644 index 2bea652bf8..0000000000 --- a/src/jit/dump.lua +++ /dev/null @@ -1,712 +0,0 @@ ----------------------------------------------------------------------------- --- LuaJIT compiler dump module. --- --- Copyright (C) 2005-2017 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 ircall = vmdef.ircall - for i=0,#ircall do - local addr = ircalladdr(i) - if addr ~= 0 then - 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) - return format(colortype_ansi[t], s) -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) - s = gsub(s, "[<>&]", html_escape) - return format('%s', irtype_text[t], 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 = [[ - -]] - -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 - 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, 14) - if 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, - ["BUFHDR"] = { [0] = "RESET", "APPEND" }, - ["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 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) - 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))) - 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('
\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("
\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, callee) - 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" - callee = func - 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 - ------------------------------------------------------------------------------- - --- 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 jit.arch == "x64" 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 jit.arch == "mips" or jit.arch == "mipsel" 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/src/jit/p.lua b/src/jit/p.lua deleted file mode 100644 index 7be105863d..0000000000 --- a/src/jit/p.lua +++ /dev/null @@ -1,311 +0,0 @@ ----------------------------------------------------------------------------- --- LuaJIT profiler. --- --- Copyright (C) 2005-2017 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. --- stack dump depth (callee < caller). Default: 1. --- - 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 Minimum sample percentage to be shown. Default: 3. --- i 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 - 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/src/jit/v.lua b/src/jit/v.lua deleted file mode 100644 index 934de9859c..0000000000 --- a/src/jit/v.lua +++ /dev/null @@ -1,170 +0,0 @@ ----------------------------------------------------------------------------- --- Verbose mode of the LuaJIT compiler. --- --- Copyright (C) 2005-2017 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/src/jit/zone.lua b/src/jit/zone.lua deleted file mode 100644 index fa702c4e98..0000000000 --- a/src/jit/zone.lua +++ /dev/null @@ -1,45 +0,0 @@ ----------------------------------------------------------------------------- --- LuaJIT profiler zones. --- --- Copyright (C) 2005-2017 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 -}) -