aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/luajit-2.0/lib
diff options
context:
space:
mode:
authorDavid Walter Seikel2012-01-23 23:36:30 +1000
committerDavid Walter Seikel2012-01-23 23:36:30 +1000
commit6523585c66c04cea54df50013df8886b589847d8 (patch)
tree0b22aee7064166d88595eda260ca2d17c0773da5 /libraries/luajit-2.0/lib
parentUpdate the EFL to what I'm actually using, coz I'm using some stuff not yet r... (diff)
downloadSledjHamr-6523585c66c04cea54df50013df8886b589847d8.zip
SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.gz
SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.bz2
SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.xz
Add luaproc and LuaJIT libraries.
Two versions of LuaJIT, the stable release, and the dev version. Try the dev version first, until ih fails badly.
Diffstat (limited to 'libraries/luajit-2.0/lib')
-rw-r--r--libraries/luajit-2.0/lib/.gitignore1
-rw-r--r--libraries/luajit-2.0/lib/bc.lua192
-rw-r--r--libraries/luajit-2.0/lib/bcsave.lua496
-rw-r--r--libraries/luajit-2.0/lib/dis_arm.lua543
-rw-r--r--libraries/luajit-2.0/lib/dis_ppc.lua591
-rw-r--r--libraries/luajit-2.0/lib/dis_x64.lua20
-rw-r--r--libraries/luajit-2.0/lib/dis_x86.lua836
-rw-r--r--libraries/luajit-2.0/lib/dump.lua685
-rw-r--r--libraries/luajit-2.0/lib/v.lua167
9 files changed, 3531 insertions, 0 deletions
diff --git a/libraries/luajit-2.0/lib/.gitignore b/libraries/luajit-2.0/lib/.gitignore
new file mode 100644
index 0000000..500e285
--- /dev/null
+++ b/libraries/luajit-2.0/lib/.gitignore
@@ -0,0 +1 @@
vmdef.lua
diff --git a/libraries/luajit-2.0/lib/bc.lua b/libraries/luajit-2.0/lib/bc.lua
new file mode 100644
index 0000000..c2c9502
--- /dev/null
+++ b/libraries/luajit-2.0/lib/bc.lua
@@ -0,0 +1,192 @@
1----------------------------------------------------------------------------
2-- LuaJIT bytecode listing module.
3--
4-- Copyright (C) 2005-2011 Mike Pall. All rights reserved.
5-- Released under the MIT license. See Copyright Notice in luajit.h
6----------------------------------------------------------------------------
7--
8-- This module lists the bytecode of a Lua function. If it's loaded by -jbc
9-- it hooks into the parser and lists all functions of a chunk as they
10-- are parsed.
11--
12-- Example usage:
13--
14-- luajit -jbc -e 'local x=0; for i=1,1e6 do x=x+i end; print(x)'
15-- luajit -jbc=- foo.lua
16-- luajit -jbc=foo.list foo.lua
17--
18-- Default output is to stderr. To redirect the output to a file, pass a
19-- filename as an argument (use '-' for stdout) or set the environment
20-- variable LUAJIT_LISTFILE. The file is overwritten every time the module
21-- is started.
22--
23-- This module can also be used programmatically:
24--
25-- local bc = require("jit.bc")
26--
27-- local function foo() print("hello") end
28--
29-- bc.dump(foo) --> -- BYTECODE -- [...]
30-- print(bc.line(foo, 2)) --> 0002 KSTR 1 1 ; "hello"
31--
32-- local out = {
33-- -- Do something with each line:
34-- write = function(t, ...) io.write(...) end,
35-- close = function(t) end,
36-- flush = function(t) end,
37-- }
38-- bc.dump(foo, out)
39--
40------------------------------------------------------------------------------
41
42-- Cache some library functions and objects.
43local jit = require("jit")
44assert(jit.version_num == 20000, "LuaJIT core/library version mismatch")
45local jutil = require("jit.util")
46local vmdef = require("jit.vmdef")
47local bit = require("bit")
48local sub, gsub, format = string.sub, string.gsub, string.format
49local byte, band, shr = string.byte, bit.band, bit.rshift
50local funcinfo, funcbc, funck = jutil.funcinfo, jutil.funcbc, jutil.funck
51local funcuvname = jutil.funcuvname
52local bcnames = vmdef.bcnames
53local stdout, stderr = io.stdout, io.stderr
54
55------------------------------------------------------------------------------
56
57local function ctlsub(c)
58 if c == "\n" then return "\\n"
59 elseif c == "\r" then return "\\r"
60 elseif c == "\t" then return "\\t"
61 elseif c == "\r" then return "\\r"
62 else return format("\\%03d", byte(c))
63 end
64end
65
66-- Return one bytecode line.
67local function bcline(func, pc, prefix)
68 local ins, m = funcbc(func, pc)
69 if not ins then return end
70 local ma, mb, mc = band(m, 7), band(m, 15*8), band(m, 15*128)
71 local a = band(shr(ins, 8), 0xff)
72 local oidx = 6*band(ins, 0xff)
73 local op = sub(bcnames, oidx+1, oidx+6)
74 local s = format("%04d %s %-6s %3s ",
75 pc, prefix or " ", op, ma == 0 and "" or a)
76 local d = shr(ins, 16)
77 if mc == 13*128 then -- BCMjump
78 return format("%s=> %04d\n", s, pc+d-0x7fff)
79 end
80 if mb ~= 0 then
81 d = band(d, 0xff)
82 elseif mc == 0 then
83 return s.."\n"
84 end
85 local kc
86 if mc == 10*128 then -- BCMstr
87 kc = funck(func, -d-1)
88 kc = format(#kc > 40 and '"%.40s"~' or '"%s"', gsub(kc, "%c", ctlsub))
89 elseif mc == 9*128 then -- BCMnum
90 kc = funck(func, d)
91 if op == "TSETM " then kc = kc - 2^52 end
92 elseif mc == 12*128 then -- BCMfunc
93 local fi = funcinfo(funck(func, -d-1))
94 if fi.ffid then
95 kc = vmdef.ffnames[fi.ffid]
96 else
97 kc = fi.loc
98 end
99 elseif mc == 5*128 then -- BCMuv
100 kc = funcuvname(func, d)
101 end
102 if ma == 5 then -- BCMuv
103 local ka = funcuvname(func, a)
104 if kc then kc = ka.." ; "..kc else kc = ka end
105 end
106 if mb ~= 0 then
107 local b = shr(ins, 24)
108 if kc then return format("%s%3d %3d ; %s\n", s, b, d, kc) end
109 return format("%s%3d %3d\n", s, b, d)
110 end
111 if kc then return format("%s%3d ; %s\n", s, d, kc) end
112 if mc == 7*128 and d > 32767 then d = d - 65536 end -- BCMlits
113 return format("%s%3d\n", s, d)
114end
115
116-- Collect branch targets of a function.
117local function bctargets(func)
118 local target = {}
119 for pc=1,1000000000 do
120 local ins, m = funcbc(func, pc)
121 if not ins then break end
122 if band(m, 15*128) == 13*128 then target[pc+shr(ins, 16)-0x7fff] = true end
123 end
124 return target
125end
126
127-- Dump bytecode instructions of a function.
128local function bcdump(func, out, all)
129 if not out then out = stdout end
130 local fi = funcinfo(func)
131 if all and fi.children then
132 for n=-1,-1000000000,-1 do
133 local k = funck(func, n)
134 if not k then break end
135 if type(k) == "proto" then bcdump(k, out, true) end
136 end
137 end
138 out:write(format("-- BYTECODE -- %s-%d\n", fi.loc, fi.lastlinedefined))
139 local target = bctargets(func)
140 for pc=1,1000000000 do
141 local s = bcline(func, pc, target[pc] and "=>")
142 if not s then break end
143 out:write(s)
144 end
145 out:write("\n")
146 out:flush()
147end
148
149------------------------------------------------------------------------------
150
151-- Active flag and output file handle.
152local active, out
153
154-- List handler.
155local function h_list(func)
156 return bcdump(func, out)
157end
158
159-- Detach list handler.
160local function bclistoff()
161 if active then
162 active = false
163 jit.attach(h_list)
164 if out and out ~= stdout and out ~= stderr then out:close() end
165 out = nil
166 end
167end
168
169-- Open the output file and attach list handler.
170local function bcliston(outfile)
171 if active then bclistoff() end
172 if not outfile then outfile = os.getenv("LUAJIT_LISTFILE") end
173 if outfile then
174 out = outfile == "-" and stdout or assert(io.open(outfile, "w"))
175 else
176 out = stderr
177 end
178 jit.attach(h_list, "bc")
179 active = true
180end
181
182-- Public module functions.
183module(...)
184
185line = bcline
186dump = bcdump
187targets = bctargets
188
189on = bcliston
190off = bclistoff
191start = bcliston -- For -j command line option.
192
diff --git a/libraries/luajit-2.0/lib/bcsave.lua b/libraries/luajit-2.0/lib/bcsave.lua
new file mode 100644
index 0000000..1783014
--- /dev/null
+++ b/libraries/luajit-2.0/lib/bcsave.lua
@@ -0,0 +1,496 @@
1----------------------------------------------------------------------------
2-- LuaJIT module to save/list bytecode.
3--
4-- Copyright (C) 2005-2011 Mike Pall. All rights reserved.
5-- Released under the MIT license. See Copyright Notice in luajit.h
6----------------------------------------------------------------------------
7--
8-- This module saves or lists the bytecode for an input file.
9-- It's run by the -b command line option.
10--
11------------------------------------------------------------------------------
12
13local jit = require("jit")
14assert(jit.version_num == 20000, "LuaJIT core/library version mismatch")
15
16-- Symbol name prefix for LuaJIT bytecode.
17local LJBC_PREFIX = "luaJIT_BC_"
18
19------------------------------------------------------------------------------
20
21local function usage()
22 io.stderr:write[[
23Save LuaJIT bytecode: luajit -b[options] input output
24 -l Only list bytecode.
25 -s Strip debug info (default).
26 -g Keep debug info.
27 -n name Set module name (default: auto-detect from input name).
28 -t type Set output file type (default: auto-detect from output name).
29 -a arch Override architecture for object files (default: native).
30 -o os Override OS for object files (default: native).
31 -e chunk Use chunk string as input.
32 -- Stop handling options.
33 - Use stdin as input and/or stdout as output.
34
35File types: c h obj o raw (default)
36]]
37 os.exit(1)
38end
39
40local function check(ok, ...)
41 if ok then return ok, ... end
42 io.stderr:write("luajit: ", ...)
43 io.stderr:write("\n")
44 os.exit(1)
45end
46
47local function readfile(input)
48 if type(input) == "function" then return input end
49 if input == "-" then input = nil end
50 return check(loadfile(input))
51end
52
53local function savefile(name, mode)
54 if name == "-" then return io.stdout end
55 return check(io.open(name, mode))
56end
57
58------------------------------------------------------------------------------
59
60local map_type = {
61 raw = "raw", c = "c", h = "h", o = "obj", obj = "obj",
62}
63
64local map_arch = {
65 x86 = true, x64 = true, arm = true, ppc = true, ppcspe = true,
66}
67
68local map_os = {
69 linux = true, windows = true, osx = true, freebsd = true, netbsd = true,
70 openbsd = true, solaris = true,
71}
72
73local function checkarg(str, map, err)
74 str = string.lower(str)
75 local s = check(map[str], "unknown ", err)
76 return s == true and str or s
77end
78
79local function detecttype(str)
80 local ext = string.match(string.lower(str), "%.(%a+)$")
81 return map_type[ext] or "raw"
82end
83
84local function checkmodname(str)
85 check(string.match(str, "^[%w_.%-]+$"), "bad module name")
86 return string.gsub(str, "[%.%-]", "_")
87end
88
89local function detectmodname(str)
90 if type(str) == "string" then
91 local tail = string.match(str, "[^/\\]+$")
92 if tail then str = tail end
93 local head = string.match(str, "^(.*)%.[^.]*$")
94 if head then str = head end
95 str = string.match(str, "^[%w_.%-]+")
96 else
97 str = nil
98 end
99 check(str, "cannot derive module name, use -n name")
100 return string.gsub(str, "[%.%-]", "_")
101end
102
103------------------------------------------------------------------------------
104
105local function bcsave_tail(fp, output, s)
106 local ok, err = fp:write(s)
107 if ok and output ~= "-" then ok, err = fp:close() end
108 check(ok, "cannot write ", output, ": ", err)
109end
110
111local function bcsave_raw(output, s)
112 local fp = savefile(output, "wb")
113 bcsave_tail(fp, output, s)
114end
115
116local function bcsave_c(ctx, output, s)
117 local fp = savefile(output, "w")
118 if ctx.type == "c" then
119 fp:write(string.format([[
120#ifdef _cplusplus
121extern "C"
122#endif
123#ifdef _WIN32
124__declspec(dllexport)
125#endif
126const char %s%s[] = {
127]], LJBC_PREFIX, ctx.modname))
128 else
129 fp:write(string.format([[
130#define %s%s_SIZE %d
131static const char %s%s[] = {
132]], LJBC_PREFIX, ctx.modname, #s, LJBC_PREFIX, ctx.modname))
133 end
134 local t, n, m = {}, 0, 0
135 for i=1,#s do
136 local b = tostring(string.byte(s, i))
137 m = m + #b + 1
138 if m > 78 then
139 fp:write(table.concat(t, ",", 1, n), ",\n")
140 n, m = 0, #b + 1
141 end
142 n = n + 1
143 t[n] = b
144 end
145 bcsave_tail(fp, output, table.concat(t, ",", 1, n).."\n};\n")
146end
147
148local function bcsave_elfobj(ctx, output, s, ffi)
149 ffi.cdef[[
150typedef struct {
151 uint8_t emagic[4], eclass, eendian, eversion, eosabi, eabiversion, epad[7];
152 uint16_t type, machine;
153 uint32_t version;
154 uint32_t entry, phofs, shofs;
155 uint32_t flags;
156 uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstridx;
157} ELF32header;
158typedef struct {
159 uint8_t emagic[4], eclass, eendian, eversion, eosabi, eabiversion, epad[7];
160 uint16_t type, machine;
161 uint32_t version;
162 uint64_t entry, phofs, shofs;
163 uint32_t flags;
164 uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstridx;
165} ELF64header;
166typedef struct {
167 uint32_t name, type, flags, addr, ofs, size, link, info, align, entsize;
168} ELF32sectheader;
169typedef struct {
170 uint32_t name, type;
171 uint64_t flags, addr, ofs, size;
172 uint32_t link, info;
173 uint64_t align, entsize;
174} ELF64sectheader;
175typedef struct {
176 uint32_t name, value, size;
177 uint8_t info, other;
178 uint16_t sectidx;
179} ELF32symbol;
180typedef struct {
181 uint32_t name;
182 uint8_t info, other;
183 uint16_t sectidx;
184 uint64_t value, size;
185} ELF64symbol;
186typedef struct {
187 ELF32header hdr;
188 ELF32sectheader sect[6];
189 ELF32symbol sym[2];
190 uint8_t space[4096];
191} ELF32obj;
192typedef struct {
193 ELF64header hdr;
194 ELF64sectheader sect[6];
195 ELF64symbol sym[2];
196 uint8_t space[4096];
197} ELF64obj;
198]]
199 local symname = LJBC_PREFIX..ctx.modname
200 local is64, isbe = false, false
201 if ctx.arch == "x64" then
202 is64 = true
203 elseif ctx.arch == "ppc" or ctx.arch == "ppcspe" then
204 isbe = true
205 end
206
207 -- Handle different host/target endianess.
208 local function f32(x) return x end
209 local f16, fofs = f32, f32
210 if ffi.abi("be") ~= isbe then
211 f32 = bit.bswap
212 function f16(x) return bit.rshift(bit.bswap(x), 16) end
213 if is64 then
214 function fofs(x) return bit.bswap(x)*(2ll^32) end
215 else
216 fofs = f32
217 end
218 end
219
220 -- Create ELF object and fill in header.
221 local o = ffi.new(is64 and "ELF64obj" or "ELF32obj")
222 local hdr = o.hdr
223 if ctx.os == "bsd" or ctx.os == "other" then -- Determine native hdr.eosabi.
224 local bf = assert(io.open("/bin/ls", "rb"))
225 local bs = bf:read(9)
226 bf:close()
227 ffi.copy(o, bs, 9)
228 check(hdr.emagic[0] == 127, "no support for writing native object files")
229 else
230 hdr.emagic = "\127ELF"
231 hdr.eosabi = ({ freebsd=9, netbsd=2, openbsd=12, solaris=6 })[ctx.os] or 0
232 end
233 hdr.eclass = is64 and 2 or 1
234 hdr.eendian = isbe and 2 or 1
235 hdr.eversion = 1
236 hdr.type = f16(1)
237 hdr.machine = f16(({ x86=3, x64=62, arm=40, ppc=20, ppcspe=20 })[ctx.arch])
238 hdr.version = f32(1)
239 hdr.shofs = fofs(ffi.offsetof(o, "sect"))
240 hdr.ehsize = f16(ffi.sizeof(hdr))
241 hdr.shentsize = f16(ffi.sizeof(o.sect[0]))
242 hdr.shnum = f16(6)
243 hdr.shstridx = f16(2)
244
245 -- Fill in sections and symbols.
246 local sofs, ofs = ffi.offsetof(o, "space"), 1
247 for i,name in ipairs{
248 ".symtab", ".shstrtab", ".strtab", ".rodata", ".note.GNU-stack",
249 } do
250 local sect = o.sect[i]
251 sect.align = fofs(1)
252 sect.name = f32(ofs)
253 ffi.copy(o.space+ofs, name)
254 ofs = ofs + #name+1
255 end
256 o.sect[1].type = f32(2) -- .symtab
257 o.sect[1].link = f32(3)
258 o.sect[1].info = f32(1)
259 o.sect[1].align = fofs(8)
260 o.sect[1].ofs = fofs(ffi.offsetof(o, "sym"))
261 o.sect[1].entsize = fofs(ffi.sizeof(o.sym[0]))
262 o.sect[1].size = fofs(ffi.sizeof(o.sym))
263 o.sym[1].name = f32(1)
264 o.sym[1].sectidx = f16(4)
265 o.sym[1].size = fofs(#s)
266 o.sym[1].info = 17
267 o.sect[2].type = f32(3) -- .shstrtab
268 o.sect[2].ofs = fofs(sofs)
269 o.sect[2].size = fofs(ofs)
270 o.sect[3].type = f32(3) -- .strtab
271 o.sect[3].ofs = fofs(sofs + ofs)
272 o.sect[3].size = fofs(#symname+1)
273 ffi.copy(o.space+ofs+1, symname)
274 ofs = ofs + #symname + 2
275 o.sect[4].type = f32(1) -- .rodata
276 o.sect[4].flags = fofs(2)
277 o.sect[4].ofs = fofs(sofs + ofs)
278 o.sect[4].size = fofs(#s)
279 o.sect[5].type = f32(1) -- .note.GNU-stack
280 o.sect[5].ofs = fofs(sofs + ofs + #s)
281
282 -- Write ELF object file.
283 local fp = savefile(output, "wb")
284 fp:write(ffi.string(o, ffi.sizeof(o)-4096+ofs))
285 bcsave_tail(fp, output, s)
286end
287
288local function bcsave_peobj(ctx, output, s, ffi)
289 ffi.cdef[[
290typedef struct {
291 uint16_t arch, nsects;
292 uint32_t time, symtabofs, nsyms;
293 uint16_t opthdrsz, flags;
294} PEheader;
295typedef struct {
296 char name[8];
297 uint32_t vsize, vaddr, size, ofs, relocofs, lineofs;
298 uint16_t nreloc, nline;
299 uint32_t flags;
300} PEsection;
301typedef struct __attribute((packed)) {
302 union {
303 char name[8];
304 uint32_t nameref[2];
305 };
306 uint32_t value;
307 int16_t sect;
308 uint16_t type;
309 uint8_t scl, naux;
310} PEsym;
311typedef struct __attribute((packed)) {
312 uint32_t size;
313 uint16_t nreloc, nline;
314 uint32_t cksum;
315 uint16_t assoc;
316 uint8_t comdatsel, unused[3];
317} PEsymaux;
318typedef struct {
319 PEheader hdr;
320 PEsection sect[2];
321 // Must be an even number of symbol structs.
322 PEsym sym0;
323 PEsymaux sym0aux;
324 PEsym sym1;
325 PEsymaux sym1aux;
326 PEsym sym2;
327 PEsym sym3;
328 uint32_t strtabsize;
329 uint8_t space[4096];
330} PEobj;
331]]
332 local symname = LJBC_PREFIX..ctx.modname
333 local is64 = false
334 if ctx.arch == "x86" then
335 symname = "_"..symname
336 elseif ctx.arch == "x64" then
337 is64 = true
338 end
339 local symexport = " /EXPORT:"..symname..",DATA "
340
341 -- The file format is always little-endian. Swap if the host is big-endian.
342 local function f32(x) return x end
343 local f16 = f32
344 if ffi.abi("be") then
345 f32 = bit.bswap
346 function f16(x) return bit.rshift(bit.bswap(x), 16) end
347 end
348
349 -- Create PE object and fill in header.
350 local o = ffi.new("PEobj")
351 local hdr = o.hdr
352 hdr.arch = f16(({ x86=0x14c, x64=0x8664, arm=0x1c0, ppc=0x1f2 })[ctx.arch])
353 hdr.nsects = f16(2)
354 hdr.symtabofs = f32(ffi.offsetof(o, "sym0"))
355 hdr.nsyms = f32(6)
356
357 -- Fill in sections and symbols.
358 o.sect[0].name = ".drectve"
359 o.sect[0].size = f32(#symexport)
360 o.sect[0].flags = f32(0x00100a00)
361 o.sym0.sect = f16(1)
362 o.sym0.scl = 3
363 o.sym0.name = ".drectve"
364 o.sym0.naux = 1
365 o.sym0aux.size = f32(#symexport)
366 o.sect[1].name = ".rdata"
367 o.sect[1].size = f32(#s)
368 o.sect[1].flags = f32(0x40300040)
369 o.sym1.sect = f16(2)
370 o.sym1.scl = 3
371 o.sym1.name = ".rdata"
372 o.sym1.naux = 1
373 o.sym1aux.size = f32(#s)
374 o.sym2.sect = f16(2)
375 o.sym2.scl = 2
376 o.sym2.nameref[1] = f32(4)
377 o.sym3.sect = f16(-1)
378 o.sym3.scl = 2
379 o.sym3.value = f32(1)
380 o.sym3.name = "@feat.00" -- Mark as SafeSEH compliant.
381 ffi.copy(o.space, symname)
382 local ofs = #symname + 1
383 o.strtabsize = f32(ofs + 4)
384 o.sect[0].ofs = f32(ffi.offsetof(o, "space") + ofs)
385 ffi.copy(o.space + ofs, symexport)
386 ofs = ofs + #symexport
387 o.sect[1].ofs = f32(ffi.offsetof(o, "space") + ofs)
388
389 -- Write PE object file.
390 local fp = savefile(output, "wb")
391 fp:write(ffi.string(o, ffi.sizeof(o)-4096+ofs))
392 bcsave_tail(fp, output, s)
393end
394
395local function bcsave_machobj(ctx, output, s, ffi)
396 check(false, "NYI: no support for writing OSX object files")
397end
398
399local function bcsave_obj(ctx, output, s)
400 local ok, ffi = pcall(require, "ffi")
401 check(ok, "FFI library required to write this file type")
402 if ctx.os == "windows" then
403 return bcsave_peobj(ctx, output, s, ffi)
404 elseif ctx.os == "osx" then
405 return bcsave_machobj(ctx, output, s, ffi)
406 else
407 return bcsave_elfobj(ctx, output, s, ffi)
408 end
409end
410
411------------------------------------------------------------------------------
412
413local function bclist(input, output)
414 local f = readfile(input)
415 require("jit.bc").dump(f, savefile(output, "w"), true)
416end
417
418local function bcsave(ctx, input, output)
419 local f = readfile(input)
420 local s = string.dump(f, ctx.strip)
421 local t = ctx.type
422 if not t then
423 t = detecttype(output)
424 ctx.type = t
425 end
426 if t == "raw" then
427 bcsave_raw(output, s)
428 else
429 if not ctx.modname then ctx.modname = detectmodname(input) end
430 if t == "obj" then
431 bcsave_obj(ctx, output, s)
432 else
433 bcsave_c(ctx, output, s)
434 end
435 end
436end
437
438local function docmd(...)
439 local arg = {...}
440 local n = 1
441 local list = false
442 local ctx = {
443 strip = true, arch = jit.arch, os = string.lower(jit.os),
444 type = false, modname = false,
445 }
446 while n <= #arg do
447 local a = arg[n]
448 if type(a) == "string" and string.sub(a, 1, 1) == "-" and a ~= "-" then
449 table.remove(arg, n)
450 if a == "--" then break end
451 for m=2,#a do
452 local opt = string.sub(a, m, m)
453 if opt == "l" then
454 list = true
455 elseif opt == "s" then
456 ctx.strip = true
457 elseif opt == "g" then
458 ctx.strip = false
459 else
460 if arg[n] == nil or m ~= #a then usage() end
461 if opt == "e" then
462 if n ~= 1 then usage() end
463 arg[1] = check(loadstring(arg[1]))
464 elseif opt == "n" then
465 ctx.modname = checkmodname(table.remove(arg, n))
466 elseif opt == "t" then
467 ctx.type = checkarg(table.remove(arg, n), map_type, "file type")
468 elseif opt == "a" then
469 ctx.arch = checkarg(table.remove(arg, n), map_arch, "architecture")
470 elseif opt == "o" then
471 ctx.os = checkarg(table.remove(arg, n), map_os, "OS name")
472 else
473 usage()
474 end
475 end
476 end
477 else
478 n = n + 1
479 end
480 end
481 if list then
482 if #arg == 0 or #arg > 2 then usage() end
483 bclist(arg[1], arg[2] or "-")
484 else
485 if #arg ~= 2 then usage() end
486 bcsave(ctx, arg[1], arg[2])
487 end
488end
489
490------------------------------------------------------------------------------
491
492-- Public module functions.
493module(...)
494
495start = docmd -- Process -b command line option.
496
diff --git a/libraries/luajit-2.0/lib/dis_arm.lua b/libraries/luajit-2.0/lib/dis_arm.lua
new file mode 100644
index 0000000..c2d1408
--- /dev/null
+++ b/libraries/luajit-2.0/lib/dis_arm.lua
@@ -0,0 +1,543 @@
1----------------------------------------------------------------------------
2-- LuaJIT ARM disassembler module.
3--
4-- Copyright (C) 2005-2010 Mike Pall. All rights reserved.
5-- Released under the MIT license. See Copyright Notice in luajit.h
6----------------------------------------------------------------------------
7-- This is a helper module used by the LuaJIT machine code dumper module.
8--
9-- It disassembles most user-mode ARMv7 instructions
10-- NYI: Advanced SIMD and VFP instructions.
11------------------------------------------------------------------------------
12
13local type = type
14local sub, byte, format = string.sub, string.byte, string.format
15local match, gmatch, gsub = string.match, string.gmatch, string.gsub
16local concat = table.concat
17local bit = require("bit")
18local band, bor, ror, tohex = bit.band, bit.bor, bit.ror, bit.tohex
19local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift
20
21------------------------------------------------------------------------------
22-- Opcode maps
23------------------------------------------------------------------------------
24
25local map_loadc = {
26 shift = 9, mask = 7,
27 [5] = {
28 shift = 0, mask = 0 -- NYI VFP load/store.
29 },
30 _ = {
31 shift = 0, mask = 0 -- NYI ldc, mcrr, mrrc.
32 },
33}
34
35local map_datac = {
36 shift = 24, mask = 1,
37 [0] = {
38 shift = 9, mask = 7,
39 [5] = {
40 shift = 0, mask = 0 -- NYI VFP data.
41 },
42 _ = {
43 shift = 0, mask = 0 -- NYI cdp, mcr, mrc.
44 },
45 },
46 "svcT",
47}
48
49local map_loadcu = {
50 shift = 0, mask = 0, -- NYI unconditional CP load/store.
51}
52
53local map_datacu = {
54 shift = 0, mask = 0, -- NYI unconditional CP data.
55}
56
57local map_simddata = {
58 shift = 0, mask = 0, -- NYI SIMD data.
59}
60
61local map_simdload = {
62 shift = 0, mask = 0, -- NYI SIMD load/store, preload.
63}
64
65local map_preload = {
66 shift = 0, mask = 0, -- NYI preload.
67}
68
69local map_media = {
70 shift = 20, mask = 31,
71 [0] = false,
72 { --01
73 shift = 5, mask = 7,
74 [0] = "sadd16DNM", "sasxDNM", "ssaxDNM", "ssub16DNM",
75 "sadd8DNM", false, false, "ssub8DNM",
76 },
77 { --02
78 shift = 5, mask = 7,
79 [0] = "qadd16DNM", "qasxDNM", "qsaxDNM", "qsub16DNM",
80 "qadd8DNM", false, false, "qsub8DNM",
81 },
82 { --03
83 shift = 5, mask = 7,
84 [0] = "shadd16DNM", "shasxDNM", "shsaxDNM", "shsub16DNM",
85 "shadd8DNM", false, false, "shsub8DNM",
86 },
87 false,
88 { --05
89 shift = 5, mask = 7,
90 [0] = "uadd16DNM", "uasxDNM", "usaxDNM", "usub16DNM",
91 "uadd8DNM", false, false, "usub8DNM",
92 },
93 { --06
94 shift = 5, mask = 7,
95 [0] = "uqadd16DNM", "uqasxDNM", "uqsaxDNM", "uqsub16DNM",
96 "uqadd8DNM", false, false, "uqsub8DNM",
97 },
98 { --07
99 shift = 5, mask = 7,
100 [0] = "uhadd16DNM", "uhasxDNM", "uhsaxDNM", "uhsub16DNM",
101 "uhadd8DNM", false, false, "uhsub8DNM",
102 },
103 { --08
104 shift = 5, mask = 7,
105 [0] = "pkhbtDNMU", false, "pkhtbDNMU",
106 { shift = 16, mask = 15, [15] = "sxtb16DMU", _ = "sxtab16DNMU", },
107 "pkhbtDNMU", "selDNM", "pkhtbDNMU",
108 },
109 false,
110 { --0a
111 shift = 5, mask = 7,
112 [0] = "ssatDxMu", "ssat16DxM", "ssatDxMu",
113 { shift = 16, mask = 15, [15] = "sxtbDMU", _ = "sxtabDNMU", },
114 "ssatDxMu", false, "ssatDxMu",
115 },
116 { --0b
117 shift = 5, mask = 7,
118 [0] = "ssatDxMu", "revDM", "ssatDxMu",
119 { shift = 16, mask = 15, [15] = "sxthDMU", _ = "sxtahDNMU", },
120 "ssatDxMu", "rev16DM", "ssatDxMu",
121 },
122 { --0c
123 shift = 5, mask = 7,
124 [3] = { shift = 16, mask = 15, [15] = "uxtb16DMU", _ = "uxtab16DNMU", },
125 },
126 false,
127 { --0e
128 shift = 5, mask = 7,
129 [0] = "usatDwMu", "usat16DwM", "usatDwMu",
130 { shift = 16, mask = 15, [15] = "uxtbDMU", _ = "uxtabDNMU", },
131 "usatDwMu", false, "usatDwMu",
132 },
133 { --0f
134 shift = 5, mask = 7,
135 [0] = "usatDwMu", "rbitDM", "usatDwMu",
136 { shift = 16, mask = 15, [15] = "uxthDMU", _ = "uxtahDNMU", },
137 "usatDwMu", "revshDM", "usatDwMu",
138 },
139 { --10
140 shift = 12, mask = 15,
141 [15] = {
142 shift = 5, mask = 7,
143 "smuadNMS", "smuadxNMS", "smusdNMS", "smusdxNMS",
144 },
145 _ = {
146 shift = 5, mask = 7,
147 [0] = "smladNMSD", "smladxNMSD", "smlsdNMSD", "smlsdxNMSD",
148 },
149 },
150 false, false, false,
151 { --14
152 shift = 5, mask = 7,
153 [0] = "smlaldDNMS", "smlaldxDNMS", "smlsldDNMS", "smlsldxDNMS",
154 },
155 { --15
156 shift = 5, mask = 7,
157 [0] = { shift = 12, mask = 15, [15] = "smmulNMS", _ = "smmlaNMSD", },
158 { shift = 12, mask = 15, [15] = "smmulrNMS", _ = "smmlarNMSD", },
159 false, false, false, false,
160 "smmlsNMSD", "smmlsrNMSD",
161 },
162 false, false,
163 { --18
164 shift = 5, mask = 7,
165 [0] = { shift = 12, mask = 15, [15] = "usad8NMS", _ = "usada8NMSD", },
166 },
167 false,
168 { --1a
169 shift = 5, mask = 3, [2] = "sbfxDMvw",
170 },
171 { --1b
172 shift = 5, mask = 3, [2] = "sbfxDMvw",
173 },
174 { --1c
175 shift = 5, mask = 3,
176 [0] = { shift = 0, mask = 15, [15] = "bfcDvX", _ = "bfiDMvX", },
177 },
178 { --1d
179 shift = 5, mask = 3,
180 [0] = { shift = 0, mask = 15, [15] = "bfcDvX", _ = "bfiDMvX", },
181 },
182 { --1e
183 shift = 5, mask = 3, [2] = "ubfxDMvw",
184 },
185 { --1f
186 shift = 5, mask = 3, [2] = "ubfxDMvw",
187 },
188}
189
190local map_load = {
191 shift = 21, mask = 9,
192 {
193 shift = 20, mask = 5,
194 [0] = "strtDL", "ldrtDL", [4] = "strbtDL", [5] = "ldrbtDL",
195 },
196 _ = {
197 shift = 20, mask = 5,
198 [0] = "strDL", "ldrDL", [4] = "strbDL", [5] = "ldrbDL",
199 }
200}
201
202local map_load1 = {
203 shift = 4, mask = 1,
204 [0] = map_load, map_media,
205}
206
207local map_loadm = {
208 shift = 20, mask = 1,
209 [0] = {
210 shift = 23, mask = 3,
211 [0] = "stmdaNR", "stmNR",
212 { shift = 16, mask = 63, [45] = "pushR", _ = "stmdbNR", }, "stmibNR",
213 },
214 {
215 shift = 23, mask = 3,
216 [0] = "ldmdaNR", { shift = 16, mask = 63, [61] = "popR", _ = "ldmNR", },
217 "ldmdbNR", "ldmibNR",
218 },
219}
220
221local map_data = {
222 shift = 21, mask = 15,
223 [0] = "andDNPs", "eorDNPs", "subDNPs", "rsbDNPs",
224 "addDNPs", "adcDNPs", "sbcDNPs", "rscDNPs",
225 "tstNP", "teqNP", "cmpNP", "cmnNP",
226 "orrDNPs", "movDPs", "bicDNPs", "mvnDPs",
227}
228
229local map_mul = {
230 shift = 21, mask = 7,
231 [0] = "mulNMSs", "mlaNMSDs", "umaalDNMS", "mlsDNMS",
232 "umullDNMSs", "umlalDNMSs", "smullDNMSs", "smlalDNMSs",
233}
234
235local map_sync = {
236 shift = 20, mask = 15, -- NYI: brackets around N. R(D+1) for ldrexd/strexd.
237 [0] = "swpDMN", false, false, false,
238 "swpbDMN", false, false, false,
239 "strexDMN", "ldrexDN", "strexdDN", "ldrexdDN",
240 "strexbDMN", "ldrexbDN", "strexhDN", "ldrexhDN",
241}
242
243local map_mulh = {
244 shift = 21, mask = 3,
245 [0] = { shift = 5, mask = 3,
246 [0] = "smlabbNMSD", "smlatbNMSD", "smlabtNMSD", "smlattNMSD", },
247 { shift = 5, mask = 3,
248 [0] = "smlawbNMSD", "smulwbNMS", "smlawtNMSD", "smulwtNMS", },
249 { shift = 5, mask = 3,
250 [0] = "smlalbbDNMS", "smlaltbDNMS", "smlalbtDNMS", "smlalttDNMS", },
251 { shift = 5, mask = 3,
252 [0] = "smulbbNMS", "smultbNMS", "smulbtNMS", "smulttNMS", },
253}
254
255local map_misc = {
256 shift = 4, mask = 7,
257 -- NYI: decode PSR bits of msr.
258 [0] = { shift = 21, mask = 1, [0] = "mrsD", "msrM", },
259 { shift = 21, mask = 3, "bxM", false, "clzDM", },
260 { shift = 21, mask = 3, "bxjM", },
261 { shift = 21, mask = 3, "blxM", },
262 false,
263 { shift = 21, mask = 3, [0] = "qaddDMN", "qsubDMN", "qdaddDMN", "qdsubDMN", },
264 false,
265 { shift = 21, mask = 3, "bkptK", },
266}
267
268local map_datar = {
269 shift = 4, mask = 9,
270 [9] = {
271 shift = 5, mask = 3,
272 [0] = { shift = 24, mask = 1, [0] = map_mul, map_sync, },
273 { shift = 20, mask = 1, [0] = "strhDL", "ldrhDL", },
274 { shift = 20, mask = 1, [0] = "ldrdDL", "ldrsbDL", },
275 { shift = 20, mask = 1, [0] = "strdDL", "ldrshDL", },
276 },
277 _ = {
278 shift = 20, mask = 25,
279 [16] = { shift = 7, mask = 1, [0] = map_misc, map_mulh, },
280 _ = {
281 shift = 0, mask = 0xffffffff,
282 [bor(0xe1a00000)] = "nop",
283 _ = map_data,
284 }
285 },
286}
287
288local map_datai = {
289 shift = 20, mask = 31, -- NYI: decode PSR bits of msr. Decode imm12.
290 [16] = "movwDW", [20] = "movtDW",
291 [18] = { shift = 0, mask = 0xf00ff, [0] = "nopv6", _ = "msrNW", },
292 [22] = "msrNW",
293 _ = map_data,
294}
295
296local map_branch = {
297 shift = 24, mask = 1,
298 [0] = "bB", "blB"
299}
300
301local map_condins = {
302 [0] = map_datar, map_datai, map_load, map_load1,
303 map_loadm, map_branch, map_loadc, map_datac
304}
305
306-- NYI: setend.
307local map_uncondins = {
308 [0] = false, map_simddata, map_simdload, map_preload,
309 false, "blxB", map_loadcu, map_datacu,
310}
311
312------------------------------------------------------------------------------
313
314local map_gpr = {
315 [0] = "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
316 "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
317}
318
319local map_cond = {
320 [0] = "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
321 "hi", "ls", "ge", "lt", "gt", "le", "al",
322}
323
324local map_shift = { [0] = "lsl", "lsr", "asr", "ror", }
325
326------------------------------------------------------------------------------
327
328-- Output a nicely formatted line with an opcode and operands.
329local function putop(ctx, text, operands)
330 local pos = ctx.pos
331 local extra = ""
332 if ctx.rel then
333 local sym = ctx.symtab[ctx.rel]
334 if sym then
335 extra = "\t->"..sym
336 elseif band(ctx.op, 0x0e000000) ~= 0x0a000000 then
337 extra = "\t; 0x"..tohex(ctx.rel)
338 end
339 end
340 if ctx.hexdump > 0 then
341 ctx.out(format("%08x %s %-5s %s%s\n",
342 ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra))
343 else
344 ctx.out(format("%08x %-5s %s%s\n",
345 ctx.addr+pos, text, concat(operands, ", "), extra))
346 end
347 ctx.pos = pos + 4
348end
349
350-- Fallback for unknown opcodes.
351local function unknown(ctx)
352 return putop(ctx, ".long", { "0x"..tohex(ctx.op) })
353end
354
355-- Format operand 2 of load/store opcodes.
356local function fmtload(ctx, op, pos)
357 local base = map_gpr[band(rshift(op, 16), 15)]
358 local x, ofs
359 local ext = (band(op, 0x04000000) == 0)
360 if not ext and band(op, 0x02000000) == 0 then
361 ofs = band(op, 4095)
362 if band(op, 0x00800000) == 0 then ofs = -ofs end
363 if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end
364 ofs = "#"..ofs
365 elseif ext and band(op, 0x00400000) ~= 0 then
366 ofs = band(op, 15) + band(rshift(op, 4), 0xf0)
367 if band(op, 0x00800000) == 0 then ofs = -ofs end
368 if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end
369 ofs = "#"..ofs
370 else
371 ofs = map_gpr[band(op, 15)]
372 if ext or band(op, 0xfe0) == 0 then
373 elseif band(op, 0xfe0) == 0x60 then
374 ofs = format("%s, rrx", ofs)
375 else
376 local sh = band(rshift(op, 7), 31)
377 if sh == 0 then sh = 32 end
378 ofs = format("%s, %s #%d", ofs, map_shift[band(rshift(op, 5), 3)], sh)
379 end
380 if band(op, 0x00800000) == 0 then ofs = "-"..ofs end
381 end
382 if ofs == "#0" then
383 x = format("[%s]", base)
384 elseif band(op, 0x01000000) == 0 then
385 x = format("[%s], %s", base, ofs)
386 else
387 x = format("[%s, %s]", base, ofs)
388 end
389 if band(op, 0x01200000) == 0x01200000 then x = x.."!" end
390 return x
391end
392
393-- Disassemble a single instruction.
394local function disass_ins(ctx)
395 local pos = ctx.pos
396 local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4)
397 local op = bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0)
398 local operands = {}
399 local suffix = ""
400 local last, name, pat
401 ctx.op = op
402 ctx.rel = nil
403
404 local cond = rshift(op, 28)
405 local opat
406 if cond == 15 then
407 opat = map_uncondins[band(rshift(op, 25), 7)]
408 else
409 if cond ~= 14 then suffix = map_cond[cond] end
410 opat = map_condins[band(rshift(op, 25), 7)]
411 end
412 while type(opat) ~= "string" do
413 if not opat then return unknown(ctx) end
414 opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._
415 end
416 name, pat = match(opat, "^([a-z0-9]*)(.*)")
417
418 for p in gmatch(pat, ".") do
419 local x = nil
420 if p == "D" then
421 x = map_gpr[band(rshift(op, 12), 15)]
422 elseif p == "N" then
423 x = map_gpr[band(rshift(op, 16), 15)]
424 elseif p == "S" then
425 x = map_gpr[band(rshift(op, 8), 15)]
426 elseif p == "M" then
427 x = map_gpr[band(op, 15)]
428 elseif p == "P" then
429 if band(op, 0x02000000) ~= 0 then
430 x = ror(band(op, 255), 2*band(rshift(op, 8), 15))
431 else
432 x = map_gpr[band(op, 15)]
433 if band(op, 0xff0) ~= 0 then
434 operands[#operands+1] = x
435 local s = map_shift[band(rshift(op, 5), 3)]
436 local r = nil
437 if band(op, 0xf90) == 0 then
438 if s == "ror" then s = "rrx" else r = "#32" end
439 elseif band(op, 0x10) == 0 then
440 r = "#"..band(rshift(op, 7), 31)
441 else
442 r = map_gpr[band(rshift(op, 8), 15)]
443 end
444 if name == "mov" then name = s; x = r
445 elseif r then x = format("%s %s", s, r)
446 else x = s end
447 end
448 end
449 elseif p == "L" then
450 x = fmtload(ctx, op, pos, false)
451 elseif p == "B" then
452 local addr = ctx.addr + pos + 8 + arshift(lshift(op, 8), 6)
453 if cond == 15 then addr = addr + band(rshift(op, 23), 2) end
454 ctx.rel = addr
455 x = "0x"..tohex(addr)
456 elseif p == "R" then
457 if band(op, 0x00200000) ~= 0 and #operands == 1 then
458 operands[1] = operands[1].."!"
459 end
460 local t = {}
461 for i=0,15 do
462 if band(rshift(op, i), 1) == 1 then t[#t+1] = map_gpr[i] end
463 end
464 x = "{"..concat(t, ", ").."}"
465 elseif p == "W" then
466 x = band(op, 0x0fff) + band(rshift(op, 4), 0xf000)
467 elseif p == "T" then
468 x = "#0x"..tohex(band(op, 0x00ffffff), 6)
469 elseif p == "U" then
470 x = band(rshift(op, 7), 31)
471 if x == 0 then x = nil end
472 elseif p == "u" then
473 x = band(rshift(op, 7), 31)
474 if band(op, 0x40) == 0 then
475 if x == 0 then x = nil else x = "lsl #"..x end
476 else
477 if x == 0 then x = "asr #32" else x = "asr #"..x end
478 end
479 elseif p == "v" then
480 x = band(rshift(op, 7), 31)
481 elseif p == "w" then
482 x = band(rshift(op, 16), 31)
483 elseif p == "x" then
484 x = band(rshift(op, 16), 31) + 1
485 elseif p == "X" then
486 x = band(rshift(op, 16), 31) - last + 1
487 elseif p == "K" then
488 x = "#0x"..tohex(band(rshift(op, 4), 0x0000fff0) + band(op, 15), 4)
489 elseif p == "s" then
490 if band(op, 0x00100000) ~= 0 then suffix = "s"..suffix end
491 else
492 assert(false)
493 end
494 if x then
495 last = x
496 if type(x) == "number" then x = "#"..x end
497 operands[#operands+1] = x
498 end
499 end
500
501 return putop(ctx, name..suffix, operands)
502end
503
504------------------------------------------------------------------------------
505
506-- Disassemble a block of code.
507local function disass_block(ctx, ofs, len)
508 if not ofs then ofs = 0 end
509 local stop = len and ofs+len or #ctx.code
510 ctx.pos = ofs
511 ctx.rel = nil
512 while ctx.pos < stop do disass_ins(ctx) end
513end
514
515-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).
516local function create_(code, addr, out)
517 local ctx = {}
518 ctx.code = code
519 ctx.addr = addr or 0
520 ctx.out = out or io.write
521 ctx.symtab = {}
522 ctx.disass = disass_block
523 ctx.hexdump = 8
524 return ctx
525end
526
527-- Simple API: disassemble code (a string) at address and output via out.
528local function disass_(code, addr, out)
529 create_(code, addr, out):disass()
530end
531
532-- Return register name for RID.
533local function regname_(r)
534 return map_gpr[r]
535end
536
537-- Public module functions.
538module(...)
539
540create = create_
541disass = disass_
542regname = regname_
543
diff --git a/libraries/luajit-2.0/lib/dis_ppc.lua b/libraries/luajit-2.0/lib/dis_ppc.lua
new file mode 100644
index 0000000..79b306d
--- /dev/null
+++ b/libraries/luajit-2.0/lib/dis_ppc.lua
@@ -0,0 +1,591 @@
1----------------------------------------------------------------------------
2-- LuaJIT PPC disassembler module.
3--
4-- Copyright (C) 2005-2010 Mike Pall. All rights reserved.
5-- Released under the MIT/X license. See Copyright Notice in luajit.h
6----------------------------------------------------------------------------
7-- This is a helper module used by the LuaJIT machine code dumper module.
8--
9-- It disassembles all common, non-privileged 32/64 bit PowerPC instructions
10-- plus the e500 SPE instructions and some Cell/Xenon extensions.
11--
12-- NYI: VMX, VMX128
13------------------------------------------------------------------------------
14
15local type = type
16local sub, byte, format = string.sub, string.byte, string.format
17local match, gmatch, gsub = string.match, string.gmatch, string.gsub
18local concat = table.concat
19local bit = require("bit")
20local band, bor, tohex = bit.band, bit.bor, bit.tohex
21local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift
22
23------------------------------------------------------------------------------
24-- Primary and extended opcode maps
25------------------------------------------------------------------------------
26
27local map_crops = {
28 shift = 1, mask = 1023,
29 [0] = "mcrfXX",
30 [33] = "crnor|crnotCCC=", [129] = "crandcCCC",
31 [193] = "crxor|crclrCCC%", [225] = "crnandCCC",
32 [257] = "crandCCC", [289] = "creqv|crsetCCC%",
33 [417] = "crorcCCC", [449] = "cror|crmoveCCC=",
34 [16] = "b_lrKB", [528] = "b_ctrKB",
35 [150] = "isync",
36}
37
38local map_rlwinm = setmetatable({
39 shift = 0, mask = -1,
40},
41{ __index = function(t, x)
42 local rot = band(rshift(x, 11), 31)
43 local mb = band(rshift(x, 6), 31)
44 local me = band(rshift(x, 1), 31)
45 if mb == 0 and me == 31-rot then
46 return "slwiRR~A."
47 elseif me == 31 and mb == 32-rot then
48 return "srwiRR~-A."
49 else
50 return "rlwinmRR~AAA."
51 end
52 end
53})
54
55local map_rld = {
56 shift = 2, mask = 7,
57 [0] = "rldiclRR~HM.", "rldicrRR~HM.", "rldicRR~HM.", "rldimiRR~HM.",
58 {
59 shift = 1, mask = 1,
60 [0] = "rldclRR~HM.", "rldcrRR~HM.",
61 },
62}
63
64local map_ext = setmetatable({
65 shift = 1, mask = 1023,
66
67 [0] = "cmp_YLRR", [32] = "cmpl_YLRR",
68 [4] = "twARR", [68] = "tdARR",
69
70 [8] = "subfcRRR.", [40] = "subfRRR.",
71 [104] = "negRR.", [136] = "subfeRRR.",
72 [200] = "subfzeRR.", [232] = "subfmeRR.",
73 [520] = "subfcoRRR.", [552] = "subfoRRR.",
74 [616] = "negoRR.", [648] = "subfeoRRR.",
75 [712] = "subfzeoRR.", [744] = "subfmeoRR.",
76
77 [9] = "mulhduRRR.", [73] = "mulhdRRR.", [233] = "mulldRRR.",
78 [457] = "divduRRR.", [489] = "divdRRR.",
79 [745] = "mulldoRRR.",
80 [969] = "divduoRRR.", [1001] = "divdoRRR.",
81
82 [10] = "addcRRR.", [138] = "addeRRR.",
83 [202] = "addzeRR.", [234] = "addmeRR.", [266] = "addRRR.",
84 [522] = "addcoRRR.", [650] = "addeoRRR.",
85 [714] = "addzeoRR.", [746] = "addmeoRR.", [778] = "addoRRR.",
86
87 [11] = "mulhwuRRR.", [75] = "mulhwRRR.", [235] = "mullwRRR.",
88 [459] = "divwuRRR.", [491] = "divwRRR.",
89 [747] = "mullwoRRR.",
90 [971] = "divwouRRR.", [1003] = "divwoRRR.",
91
92 [15] = "iselltRRR", [47] = "iselgtRRR", [79] = "iseleqRRR",
93
94 [144] = { shift = 20, mask = 1, [0] = "mtcrfRZ~", "mtocrfRZ~", },
95 [19] = { shift = 20, mask = 1, [0] = "mfcrR", "mfocrfRZ", },
96 [371] = { shift = 11, mask = 1023, [392] = "mftbR", [424] = "mftbuR", },
97 [339] = {
98 shift = 11, mask = 1023,
99 [32] = "mferR", [256] = "mflrR", [288] = "mfctrR", [16] = "mfspefscrR",
100 },
101 [467] = {
102 shift = 11, mask = 1023,
103 [32] = "mtxerR", [256] = "mtlrR", [288] = "mtctrR", [16] = "mtspefscrR",
104 },
105
106 [20] = "lwarxRR0R", [84] = "ldarxRR0R",
107
108 [21] = "ldxRR0R", [53] = "lduxRRR",
109 [149] = "stdxRR0R", [181] = "stduxRRR",
110 [341] = "lwaxRR0R", [373] = "lwauxRRR",
111
112 [23] = "lwzxRR0R", [55] = "lwzuxRRR",
113 [87] = "lbzxRR0R", [119] = "lbzuxRRR",
114 [151] = "stwxRR0R", [183] = "stwuxRRR",
115 [215] = "stbxRR0R", [247] = "stbuxRRR",
116 [279] = "lhzxRR0R", [311] = "lhzuxRRR",
117 [343] = "lhaxRR0R", [375] = "lhauxRRR",
118 [407] = "sthxRR0R", [439] = "sthuxRRR",
119
120 [54] = "dcbst-R0R", [86] = "dcbf-R0R",
121 [150] = "stwcxRR0R.", [214] = "stdcxRR0R.",
122 [246] = "dcbtst-R0R", [278] = "dcbt-R0R",
123 [310] = "eciwxRR0R", [438] = "ecowxRR0R",
124 [470] = "dcbi-RR",
125
126 [598] = {
127 shift = 21, mask = 3,
128 [0] = "sync", "lwsync", "ptesync",
129 },
130 [758] = "dcba-RR",
131 [854] = "eieio", [982] = "icbi-R0R", [1014] = "dcbz-R0R",
132
133 [26] = "cntlzwRR~", [58] = "cntlzdRR~",
134 [122] = "popcntbRR~",
135 [154] = "prtywRR~", [186] = "prtydRR~",
136
137 [28] = "andRR~R.", [60] = "andcRR~R.", [124] = "nor|notRR~R=.",
138 [284] = "eqvRR~R.", [316] = "xorRR~R.",
139 [412] = "orcRR~R.", [444] = "or|mrRR~R=.", [476] = "nandRR~R.",
140 [508] = "cmpbRR~R",
141
142 [512] = "mcrxrX",
143
144 [532] = "ldbrxRR0R", [660] = "stdbrxRR0R",
145
146 [533] = "lswxRR0R", [597] = "lswiRR0A",
147 [661] = "stswxRR0R", [725] = "stswiRR0A",
148
149 [534] = "lwbrxRR0R", [662] = "stwbrxRR0R",
150 [790] = "lhbrxRR0R", [918] = "sthbrxRR0R",
151
152 [535] = "lfsxFR0R", [567] = "lfsuxFRR",
153 [599] = "lfdxFR0R", [631] = "lfduxFRR",
154 [663] = "stfsxFR0R", [695] = "stfsuxFRR",
155 [727] = "stfdxFR0R", [759] = "stfduxFR0R",
156 [855] = "lfiwaxFR0R",
157 [983] = "stfiwxFR0R",
158
159 [24] = "slwRR~R.",
160
161 [27] = "sldRR~R.", [536] = "srwRR~R.",
162 [792] = "srawRR~R.", [824] = "srawiRR~A.",
163
164 [794] = "sradRR~R.", [826] = "sradiRR~H.", [827] = "sradiRR~H.",
165 [922] = "extshRR~.", [954] = "extsbRR~.", [986] = "extswRR~.",
166
167 [539] = "srdRR~R.",
168},
169{ __index = function(t, x)
170 if band(x, 31) == 15 then return "iselRRRC" end
171 end
172})
173
174local map_ld = {
175 shift = 0, mask = 3,
176 [0] = "ldRRE", "lduRRE", "lwaRRE",
177}
178
179local map_std = {
180 shift = 0, mask = 3,
181 [0] = "stdRRE", "stduRRE",
182}
183
184local map_fps = {
185 shift = 5, mask = 1,
186 {
187 shift = 1, mask = 15,
188 [0] = false, false, "fdivsFFF.", false,
189 "fsubsFFF.", "faddsFFF.", "fsqrtsF-F.", false,
190 "fresF-F.", "fmulsFF-F.", "frsqrtesF-F.", false,
191 "fmsubsFFFF~.", "fmaddsFFFF~.", "fnmsubsFFFF~.", "fnmaddsFFFF~.",
192 }
193}
194
195local map_fpd = {
196 shift = 5, mask = 1,
197 [0] = {
198 shift = 1, mask = 1023,
199 [0] = "fcmpuXFF", [32] = "fcmpoXFF", [64] = "mcrfsXX",
200 [38] = "mtfsb1A.", [70] = "mtfsb0A.", [134] = "mtfsfiA>>-A>",
201 [8] = "fcpsgnFFF.", [40] = "fnegF-F.", [72] = "fmrF-F.",
202 [136] = "fnabsF-F.", [264] = "fabsF-F.",
203 [12] = "frspF-F.",
204 [14] = "fctiwF-F.", [15] = "fctiwzF-F.",
205 [583] = "mffsF.", [711] = "mtfsfZF.",
206 [392] = "frinF-F.", [424] = "frizF-F.",
207 [456] = "fripF-F.", [488] = "frimF-F.",
208 [814] = "fctidF-F.", [815] = "fctidzF-F.", [846] = "fcfidF-F.",
209 },
210 {
211 shift = 1, mask = 15,
212 [0] = false, false, "fdivFFF.", false,
213 "fsubFFF.", "faddFFF.", "fsqrtF-F.", "fselFFFF~.",
214 "freF-F.", "fmulFF-F.", "frsqrteF-F.", false,
215 "fmsubFFFF~.", "fmaddFFFF~.", "fnmsubFFFF~.", "fnmaddFFFF~.",
216 }
217}
218
219local map_spe = {
220 shift = 0, mask = 2047,
221
222 [512] = "evaddwRRR", [514] = "evaddiwRAR~",
223 [516] = "evsubwRRR~", [518] = "evsubiwRAR~",
224 [520] = "evabsRR", [521] = "evnegRR",
225 [522] = "evextsbRR", [523] = "evextshRR", [524] = "evrndwRR",
226 [525] = "evcntlzwRR", [526] = "evcntlswRR",
227
228 [527] = "brincRRR",
229
230 [529] = "evandRRR", [530] = "evandcRRR", [534] = "evxorRRR",
231 [535] = "evor|evmrRRR=", [536] = "evnor|evnotRRR=",
232 [537] = "eveqvRRR", [539] = "evorcRRR", [542] = "evnandRRR",
233
234 [544] = "evsrwuRRR", [545] = "evsrwsRRR",
235 [546] = "evsrwiuRRA", [547] = "evsrwisRRA",
236 [548] = "evslwRRR", [550] = "evslwiRRA",
237 [552] = "evrlwRRR", [553] = "evsplatiRS",
238 [554] = "evrlwiRRA", [555] = "evsplatfiRS",
239 [556] = "evmergehiRRR", [557] = "evmergeloRRR",
240 [558] = "evmergehiloRRR", [559] = "evmergelohiRRR",
241
242 [560] = "evcmpgtuYRR", [561] = "evcmpgtsYRR",
243 [562] = "evcmpltuYRR", [563] = "evcmpltsYRR",
244 [564] = "evcmpeqYRR",
245
246 [632] = "evselRRR", [633] = "evselRRRW",
247 [634] = "evselRRRW", [635] = "evselRRRW",
248 [636] = "evselRRRW", [637] = "evselRRRW",
249 [638] = "evselRRRW", [639] = "evselRRRW",
250
251 [640] = "evfsaddRRR", [641] = "evfssubRRR",
252 [644] = "evfsabsRR", [645] = "evfsnabsRR", [646] = "evfsnegRR",
253 [648] = "evfsmulRRR", [649] = "evfsdivRRR",
254 [652] = "evfscmpgtYRR", [653] = "evfscmpltYRR", [654] = "evfscmpeqYRR",
255 [656] = "evfscfuiR-R", [657] = "evfscfsiR-R",
256 [658] = "evfscfufR-R", [659] = "evfscfsfR-R",
257 [660] = "evfsctuiR-R", [661] = "evfsctsiR-R",
258 [662] = "evfsctufR-R", [663] = "evfsctsfR-R",
259 [664] = "evfsctuizR-R", [666] = "evfsctsizR-R",
260 [668] = "evfststgtYRR", [669] = "evfststltYRR", [670] = "evfststeqYRR",
261
262 [704] = "efsaddRRR", [705] = "efssubRRR",
263 [708] = "efsabsRR", [709] = "efsnabsRR", [710] = "efsnegRR",
264 [712] = "efsmulRRR", [713] = "efsdivRRR",
265 [716] = "efscmpgtYRR", [717] = "efscmpltYRR", [718] = "efscmpeqYRR",
266 [719] = "efscfdR-R",
267 [720] = "efscfuiR-R", [721] = "efscfsiR-R",
268 [722] = "efscfufR-R", [723] = "efscfsfR-R",
269 [724] = "efsctuiR-R", [725] = "efsctsiR-R",
270 [726] = "efsctufR-R", [727] = "efsctsfR-R",
271 [728] = "efsctuizR-R", [730] = "efsctsizR-R",
272 [732] = "efststgtYRR", [733] = "efststltYRR", [734] = "efststeqYRR",
273
274 [736] = "efdaddRRR", [737] = "efdsubRRR",
275 [738] = "efdcfuidR-R", [739] = "efdcfsidR-R",
276 [740] = "efdabsRR", [741] = "efdnabsRR", [742] = "efdnegRR",
277 [744] = "efdmulRRR", [745] = "efddivRRR",
278 [746] = "efdctuidzR-R", [747] = "efdctsidzR-R",
279 [748] = "efdcmpgtYRR", [749] = "efdcmpltYRR", [750] = "efdcmpeqYRR",
280 [751] = "efdcfsR-R",
281 [752] = "efdcfuiR-R", [753] = "efdcfsiR-R",
282 [754] = "efdcfufR-R", [755] = "efdcfsfR-R",
283 [756] = "efdctuiR-R", [757] = "efdctsiR-R",
284 [758] = "efdctufR-R", [759] = "efdctsfR-R",
285 [760] = "efdctuizR-R", [762] = "efdctsizR-R",
286 [764] = "efdtstgtYRR", [765] = "efdtstltYRR", [766] = "efdtsteqYRR",
287
288 [768] = "evlddxRR0R", [769] = "evlddRR8",
289 [770] = "evldwxRR0R", [771] = "evldwRR8",
290 [772] = "evldhxRR0R", [773] = "evldhRR8",
291 [776] = "evlhhesplatxRR0R", [777] = "evlhhesplatRR2",
292 [780] = "evlhhousplatxRR0R", [781] = "evlhhousplatRR2",
293 [782] = "evlhhossplatxRR0R", [783] = "evlhhossplatRR2",
294 [784] = "evlwhexRR0R", [785] = "evlwheRR4",
295 [788] = "evlwhouxRR0R", [789] = "evlwhouRR4",
296 [790] = "evlwhosxRR0R", [791] = "evlwhosRR4",
297 [792] = "evlwwsplatxRR0R", [793] = "evlwwsplatRR4",
298 [796] = "evlwhsplatxRR0R", [797] = "evlwhsplatRR4",
299
300 [800] = "evstddxRR0R", [801] = "evstddRR8",
301 [802] = "evstdwxRR0R", [803] = "evstdwRR8",
302 [804] = "evstdhxRR0R", [805] = "evstdhRR8",
303 [816] = "evstwhexRR0R", [817] = "evstwheRR4",
304 [820] = "evstwhoxRR0R", [821] = "evstwhoRR4",
305 [824] = "evstwwexRR0R", [825] = "evstwweRR4",
306 [828] = "evstwwoxRR0R", [829] = "evstwwoRR4",
307
308 [1027] = "evmhessfRRR", [1031] = "evmhossfRRR", [1032] = "evmheumiRRR",
309 [1033] = "evmhesmiRRR", [1035] = "evmhesmfRRR", [1036] = "evmhoumiRRR",
310 [1037] = "evmhosmiRRR", [1039] = "evmhosmfRRR", [1059] = "evmhessfaRRR",
311 [1063] = "evmhossfaRRR", [1064] = "evmheumiaRRR", [1065] = "evmhesmiaRRR",
312 [1067] = "evmhesmfaRRR", [1068] = "evmhoumiaRRR", [1069] = "evmhosmiaRRR",
313 [1071] = "evmhosmfaRRR", [1095] = "evmwhssfRRR", [1096] = "evmwlumiRRR",
314 [1100] = "evmwhumiRRR", [1101] = "evmwhsmiRRR", [1103] = "evmwhsmfRRR",
315 [1107] = "evmwssfRRR", [1112] = "evmwumiRRR", [1113] = "evmwsmiRRR",
316 [1115] = "evmwsmfRRR", [1127] = "evmwhssfaRRR", [1128] = "evmwlumiaRRR",
317 [1132] = "evmwhumiaRRR", [1133] = "evmwhsmiaRRR", [1135] = "evmwhsmfaRRR",
318 [1139] = "evmwssfaRRR", [1144] = "evmwumiaRRR", [1145] = "evmwsmiaRRR",
319 [1147] = "evmwsmfaRRR",
320
321 [1216] = "evaddusiaawRR", [1217] = "evaddssiaawRR",
322 [1218] = "evsubfusiaawRR", [1219] = "evsubfssiaawRR",
323 [1220] = "evmraRR",
324 [1222] = "evdivwsRRR", [1223] = "evdivwuRRR",
325 [1224] = "evaddumiaawRR", [1225] = "evaddsmiaawRR",
326 [1226] = "evsubfumiaawRR", [1227] = "evsubfsmiaawRR",
327
328 [1280] = "evmheusiaawRRR", [1281] = "evmhessiaawRRR",
329 [1283] = "evmhessfaawRRR", [1284] = "evmhousiaawRRR",
330 [1285] = "evmhossiaawRRR", [1287] = "evmhossfaawRRR",
331 [1288] = "evmheumiaawRRR", [1289] = "evmhesmiaawRRR",
332 [1291] = "evmhesmfaawRRR", [1292] = "evmhoumiaawRRR",
333 [1293] = "evmhosmiaawRRR", [1295] = "evmhosmfaawRRR",
334 [1320] = "evmhegumiaaRRR", [1321] = "evmhegsmiaaRRR",
335 [1323] = "evmhegsmfaaRRR", [1324] = "evmhogumiaaRRR",
336 [1325] = "evmhogsmiaaRRR", [1327] = "evmhogsmfaaRRR",
337 [1344] = "evmwlusiaawRRR", [1345] = "evmwlssiaawRRR",
338 [1352] = "evmwlumiaawRRR", [1353] = "evmwlsmiaawRRR",
339 [1363] = "evmwssfaaRRR", [1368] = "evmwumiaaRRR",
340 [1369] = "evmwsmiaaRRR", [1371] = "evmwsmfaaRRR",
341 [1408] = "evmheusianwRRR", [1409] = "evmhessianwRRR",
342 [1411] = "evmhessfanwRRR", [1412] = "evmhousianwRRR",
343 [1413] = "evmhossianwRRR", [1415] = "evmhossfanwRRR",
344 [1416] = "evmheumianwRRR", [1417] = "evmhesmianwRRR",
345 [1419] = "evmhesmfanwRRR", [1420] = "evmhoumianwRRR",
346 [1421] = "evmhosmianwRRR", [1423] = "evmhosmfanwRRR",
347 [1448] = "evmhegumianRRR", [1449] = "evmhegsmianRRR",
348 [1451] = "evmhegsmfanRRR", [1452] = "evmhogumianRRR",
349 [1453] = "evmhogsmianRRR", [1455] = "evmhogsmfanRRR",
350 [1472] = "evmwlusianwRRR", [1473] = "evmwlssianwRRR",
351 [1480] = "evmwlumianwRRR", [1481] = "evmwlsmianwRRR",
352 [1491] = "evmwssfanRRR", [1496] = "evmwumianRRR",
353 [1497] = "evmwsmianRRR", [1499] = "evmwsmfanRRR",
354}
355
356local map_pri = {
357 [0] = false, false, "tdiARI", "twiARI",
358 map_spe, false, false, "mulliRRI",
359 "subficRRI", false, "cmpl_iYLRU", "cmp_iYLRI",
360 "addicRRI", "addic.RRI", "addi|liRR0I", "addis|lisRR0I",
361 "b_KBJ", "sc", "bKJ", map_crops,
362 "rlwimiRR~AAA.", map_rlwinm, false, "rlwnmRR~RAA.",
363 "oriNRR~U", "orisRR~U", "xoriRR~U", "xorisRR~U",
364 "andi.RR~U", "andis.RR~U", map_rld, map_ext,
365 "lwzRRD", "lwzuRRD", "lbzRRD", "lbzuRRD",
366 "stwRRD", "stwuRRD", "stbRRD", "stbuRRD",
367 "lhzRRD", "lhzuRRD", "lhaRRD", "lhauRRD",
368 "sthRRD", "sthuRRD", "lmwRRD", "stmwRRD",
369 "lfsFRD", "lfsuFRD", "lfdFRD", "lfduFRD",
370 "stfsFRD", "stfsuFRD", "stfdFRD", "stfduFRD",
371 false, false, map_ld, map_fps,
372 false, false, map_std, map_fpd,
373}
374
375------------------------------------------------------------------------------
376
377local map_gpr = {
378 [0] = "r0", "sp", "r2", "r3", "r4", "r5", "r6", "r7",
379 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
380 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
381 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
382}
383
384local map_cond = { [0] = "lt", "gt", "eq", "so", "ge", "le", "ne", "ns", }
385
386-- Format a condition bit.
387local function condfmt(cond)
388 if cond <= 3 then
389 return map_cond[band(cond, 3)]
390 else
391 return format("4*cr%d+%s", rshift(cond, 2), map_cond[band(cond, 3)])
392 end
393end
394
395------------------------------------------------------------------------------
396
397-- Output a nicely formatted line with an opcode and operands.
398local function putop(ctx, text, operands)
399 local pos = ctx.pos
400 local extra = ""
401 if ctx.rel then
402 local sym = ctx.symtab[ctx.rel]
403 if sym then extra = "\t->"..sym end
404 end
405 if ctx.hexdump > 0 then
406 ctx.out(format("%08x %s %-7s %s%s\n",
407 ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra))
408 else
409 ctx.out(format("%08x %-7s %s%s\n",
410 ctx.addr+pos, text, concat(operands, ", "), extra))
411 end
412 ctx.pos = pos + 4
413end
414
415-- Fallback for unknown opcodes.
416local function unknown(ctx)
417 return putop(ctx, ".long", { "0x"..tohex(ctx.op) })
418end
419
420-- Disassemble a single instruction.
421local function disass_ins(ctx)
422 local pos = ctx.pos
423 local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4)
424 local op = bor(lshift(b0, 24), lshift(b1, 16), lshift(b2, 8), b3)
425 local operands = {}
426 local last = nil
427 local rs = 21
428 ctx.op = op
429 ctx.rel = nil
430
431 local opat = map_pri[rshift(b0, 2)]
432 while type(opat) ~= "string" do
433 if not opat then return unknown(ctx) end
434 opat = opat[band(rshift(op, opat.shift), opat.mask)]
435 end
436 local name, pat = match(opat, "^([a-z0-9_.]*)(.*)")
437 local altname, pat2 = match(pat, "|([a-z0-9_.]*)(.*)")
438 if altname then pat = pat2 end
439
440 for p in gmatch(pat, ".") do
441 local x = nil
442 if p == "R" then
443 x = map_gpr[band(rshift(op, rs), 31)]
444 rs = rs - 5
445 elseif p == "F" then
446 x = "f"..band(rshift(op, rs), 31)
447 rs = rs - 5
448 elseif p == "A" then
449 x = band(rshift(op, rs), 31)
450 rs = rs - 5
451 elseif p == "S" then
452 x = arshift(lshift(op, 27-rs), 27)
453 rs = rs - 5
454 elseif p == "I" then
455 x = arshift(lshift(op, 16), 16)
456 elseif p == "U" then
457 x = band(op, 0xffff)
458 elseif p == "D" or p == "E" then
459 local disp = arshift(lshift(op, 16), 16)
460 if p == "E" then disp = band(disp, -4) end
461 if last == "r0" then last = "0" end
462 operands[#operands] = format("%d(%s)", disp, last)
463 elseif p >= "2" and p <= "8" then
464 local disp = band(rshift(op, rs), 31) * p
465 if last == "r0" then last = "0" end
466 operands[#operands] = format("%d(%s)", disp, last)
467 elseif p == "H" then
468 x = band(rshift(op, rs), 31) + lshift(band(op, 2), 4)
469 rs = rs - 5
470 elseif p == "M" then
471 x = band(rshift(op, rs), 31) + band(op, 0x20)
472 elseif p == "C" then
473 x = condfmt(band(rshift(op, rs), 31))
474 rs = rs - 5
475 elseif p == "B" then
476 local bo = rshift(op, 21)
477 local cond = band(rshift(op, 16), 31)
478 local cn = ""
479 rs = rs - 10
480 if band(bo, 4) == 0 then
481 cn = band(bo, 2) == 0 and "dnz" or "dz"
482 if band(bo, 0x10) == 0 then
483 cn = cn..(band(bo, 8) == 0 and "f" or "t")
484 end
485 if band(bo, 0x10) == 0 then x = condfmt(cond) end
486 name = name..(band(bo, 1) == band(rshift(op, 15), 1) and "-" or "+")
487 elseif band(bo, 0x10) == 0 then
488 cn = map_cond[band(cond, 3) + (band(bo, 8) == 0 and 4 or 0)]
489 if cond > 3 then x = "cr"..rshift(cond, 2) end
490 name = name..(band(bo, 1) == band(rshift(op, 15), 1) and "-" or "+")
491 end
492 name = gsub(name, "_", cn)
493 elseif p == "J" then
494 x = arshift(lshift(op, 27-rs), 29-rs)*4
495 if band(op, 2) == 0 then x = ctx.addr + pos + x end
496 ctx.rel = x
497 x = "0x"..tohex(x)
498 elseif p == "K" then
499 if band(op, 1) ~= 0 then name = name.."l" end
500 if band(op, 2) ~= 0 then name = name.."a" end
501 elseif p == "X" or p == "Y" then
502 x = band(rshift(op, rs+2), 7)
503 if x == 0 and p == "Y" then x = nil else x = "cr"..x end
504 rs = rs - 5
505 elseif p == "W" then
506 x = "cr"..band(op, 7)
507 elseif p == "Z" then
508 x = band(rshift(op, rs-4), 255)
509 rs = rs - 10
510 elseif p == ">" then
511 operands[#operands] = rshift(operands[#operands], 1)
512 elseif p == "0" then
513 if last == "r0" then
514 operands[#operands] = nil
515 if altname then name = altname end
516 end
517 elseif p == "L" then
518 name = gsub(name, "_", band(op, 0x00200000) ~= 0 and "d" or "w")
519 elseif p == "." then
520 if band(op, 1) == 1 then name = name.."." end
521 elseif p == "N" then
522 if op == 0x60000000 then name = "nop"; break end
523 elseif p == "~" then
524 local n = #operands
525 operands[n-1], operands[n] = operands[n], operands[n-1]
526 elseif p == "=" then
527 local n = #operands
528 if last == operands[n-1] then
529 operands[n] = nil
530 name = altname
531 end
532 elseif p == "%" then
533 local n = #operands
534 if last == operands[n-1] and last == operands[n-2] then
535 operands[n] = nil
536 operands[n-1] = nil
537 name = altname
538 end
539 elseif p == "-" then
540 rs = rs - 5
541 else
542 assert(false)
543 end
544 if x then operands[#operands+1] = x; last = x end
545 end
546
547 return putop(ctx, name, operands)
548end
549
550------------------------------------------------------------------------------
551
552-- Disassemble a block of code.
553local function disass_block(ctx, ofs, len)
554 if not ofs then ofs = 0 end
555 local stop = len and ofs+len or #ctx.code
556 stop = stop - stop % 4
557 ctx.pos = ofs - ofs % 4
558 ctx.rel = nil
559 while ctx.pos < stop do disass_ins(ctx) end
560end
561
562-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).
563local function create_(code, addr, out)
564 local ctx = {}
565 ctx.code = code
566 ctx.addr = addr or 0
567 ctx.out = out or io.write
568 ctx.symtab = {}
569 ctx.disass = disass_block
570 ctx.hexdump = 8
571 return ctx
572end
573
574-- Simple API: disassemble code (a string) at address and output via out.
575local function disass_(code, addr, out)
576 create_(code, addr, out):disass()
577end
578
579-- Return register name for RID.
580local function regname_(r)
581 if r < 32 then return map_gpr[r] end
582 return "f"..(r-32)
583end
584
585-- Public module functions.
586module(...)
587
588create = create_
589disass = disass_
590regname = regname_
591
diff --git a/libraries/luajit-2.0/lib/dis_x64.lua b/libraries/luajit-2.0/lib/dis_x64.lua
new file mode 100644
index 0000000..8c9cb4f
--- /dev/null
+++ b/libraries/luajit-2.0/lib/dis_x64.lua
@@ -0,0 +1,20 @@
1----------------------------------------------------------------------------
2-- LuaJIT x64 disassembler wrapper module.
3--
4-- Copyright (C) 2005-2011 Mike Pall. All rights reserved.
5-- Released under the MIT license. See Copyright Notice in luajit.h
6----------------------------------------------------------------------------
7-- This module just exports the 64 bit functions from the combined
8-- x86/x64 disassembler module. All the interesting stuff is there.
9------------------------------------------------------------------------------
10
11local require = require
12
13module(...)
14
15local dis_x86 = require(_PACKAGE.."dis_x86")
16
17create = dis_x86.create64
18disass = dis_x86.disass64
19regname = dis_x86.regname64
20
diff --git a/libraries/luajit-2.0/lib/dis_x86.lua b/libraries/luajit-2.0/lib/dis_x86.lua
new file mode 100644
index 0000000..d9a1f32
--- /dev/null
+++ b/libraries/luajit-2.0/lib/dis_x86.lua
@@ -0,0 +1,836 @@
1----------------------------------------------------------------------------
2-- LuaJIT x86/x64 disassembler module.
3--
4-- Copyright (C) 2005-2011 Mike Pall. All rights reserved.
5-- Released under the MIT license. See Copyright Notice in luajit.h
6----------------------------------------------------------------------------
7-- This is a helper module used by the LuaJIT machine code dumper module.
8--
9-- Sending small code snippets to an external disassembler and mixing the
10-- output with our own stuff was too fragile. So I had to bite the bullet
11-- and write yet another x86 disassembler. Oh well ...
12--
13-- The output format is very similar to what ndisasm generates. But it has
14-- been developed independently by looking at the opcode tables from the
15-- Intel and AMD manuals. The supported instruction set is quite extensive
16-- and reflects what a current generation Intel or AMD CPU implements in
17-- 32 bit and 64 bit mode. Yes, this includes MMX, SSE, SSE2, SSE3, SSSE3,
18-- SSE4.1, SSE4.2, SSE4a and even privileged and hypervisor (VMX/SVM)
19-- instructions.
20--
21-- Notes:
22-- * The (useless) a16 prefix, 3DNow and pre-586 opcodes are unsupported.
23-- * No attempt at optimization has been made -- it's fast enough for my needs.
24-- * The public API may change when more architectures are added.
25------------------------------------------------------------------------------
26
27local type = type
28local sub, byte, format = string.sub, string.byte, string.format
29local match, gmatch, gsub = string.match, string.gmatch, string.gsub
30local lower, rep = string.lower, string.rep
31
32-- Map for 1st opcode byte in 32 bit mode. Ugly? Well ... read on.
33local map_opc1_32 = {
34--0x
35[0]="addBmr","addVmr","addBrm","addVrm","addBai","addVai","push es","pop es",
36"orBmr","orVmr","orBrm","orVrm","orBai","orVai","push cs","opc2*",
37--1x
38"adcBmr","adcVmr","adcBrm","adcVrm","adcBai","adcVai","push ss","pop ss",
39"sbbBmr","sbbVmr","sbbBrm","sbbVrm","sbbBai","sbbVai","push ds","pop ds",
40--2x
41"andBmr","andVmr","andBrm","andVrm","andBai","andVai","es:seg","daa",
42"subBmr","subVmr","subBrm","subVrm","subBai","subVai","cs:seg","das",
43--3x
44"xorBmr","xorVmr","xorBrm","xorVrm","xorBai","xorVai","ss:seg","aaa",
45"cmpBmr","cmpVmr","cmpBrm","cmpVrm","cmpBai","cmpVai","ds:seg","aas",
46--4x
47"incVR","incVR","incVR","incVR","incVR","incVR","incVR","incVR",
48"decVR","decVR","decVR","decVR","decVR","decVR","decVR","decVR",
49--5x
50"pushUR","pushUR","pushUR","pushUR","pushUR","pushUR","pushUR","pushUR",
51"popUR","popUR","popUR","popUR","popUR","popUR","popUR","popUR",
52--6x
53"sz*pushaw,pusha","sz*popaw,popa","boundVrm","arplWmr",
54"fs:seg","gs:seg","o16:","a16",
55"pushUi","imulVrmi","pushBs","imulVrms",
56"insb","insVS","outsb","outsVS",
57--7x
58"joBj","jnoBj","jbBj","jnbBj","jzBj","jnzBj","jbeBj","jaBj",
59"jsBj","jnsBj","jpeBj","jpoBj","jlBj","jgeBj","jleBj","jgBj",
60--8x
61"arith!Bmi","arith!Vmi","arith!Bmi","arith!Vms",
62"testBmr","testVmr","xchgBrm","xchgVrm",
63"movBmr","movVmr","movBrm","movVrm",
64"movVmg","leaVrm","movWgm","popUm",
65--9x
66"nop*xchgVaR|pause|xchgWaR|repne nop","xchgVaR","xchgVaR","xchgVaR",
67"xchgVaR","xchgVaR","xchgVaR","xchgVaR",
68"sz*cbw,cwde,cdqe","sz*cwd,cdq,cqo","call farViw","wait",
69"sz*pushfw,pushf","sz*popfw,popf","sahf","lahf",
70--Ax
71"movBao","movVao","movBoa","movVoa",
72"movsb","movsVS","cmpsb","cmpsVS",
73"testBai","testVai","stosb","stosVS",
74"lodsb","lodsVS","scasb","scasVS",
75--Bx
76"movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi",
77"movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI",
78--Cx
79"shift!Bmu","shift!Vmu","retBw","ret","$lesVrm","$ldsVrm","movBmi","movVmi",
80"enterBwu","leave","retfBw","retf","int3","intBu","into","iretVS",
81--Dx
82"shift!Bm1","shift!Vm1","shift!Bmc","shift!Vmc","aamBu","aadBu","salc","xlatb",
83"fp*0","fp*1","fp*2","fp*3","fp*4","fp*5","fp*6","fp*7",
84--Ex
85"loopneBj","loopeBj","loopBj","sz*jcxzBj,jecxzBj,jrcxzBj",
86"inBau","inVau","outBua","outVua",
87"callVj","jmpVj","jmp farViw","jmpBj","inBad","inVad","outBda","outVda",
88--Fx
89"lock:","int1","repne:rep","rep:","hlt","cmc","testb!Bm","testv!Vm",
90"clc","stc","cli","sti","cld","std","incb!Bm","incd!Vm",
91}
92assert(#map_opc1_32 == 255)
93
94-- Map for 1st opcode byte in 64 bit mode (overrides only).
95local map_opc1_64 = setmetatable({
96 [0x06]=false, [0x07]=false, [0x0e]=false,
97 [0x16]=false, [0x17]=false, [0x1e]=false, [0x1f]=false,
98 [0x27]=false, [0x2f]=false, [0x37]=false, [0x3f]=false,
99 [0x60]=false, [0x61]=false, [0x62]=false, [0x63]="movsxdVrDmt", [0x67]="a32:",
100 [0x40]="rex*", [0x41]="rex*b", [0x42]="rex*x", [0x43]="rex*xb",
101 [0x44]="rex*r", [0x45]="rex*rb", [0x46]="rex*rx", [0x47]="rex*rxb",
102 [0x48]="rex*w", [0x49]="rex*wb", [0x4a]="rex*wx", [0x4b]="rex*wxb",
103 [0x4c]="rex*wr", [0x4d]="rex*wrb", [0x4e]="rex*wrx", [0x4f]="rex*wrxb",
104 [0x82]=false, [0x9a]=false, [0xc4]=false, [0xc5]=false, [0xce]=false,
105 [0xd4]=false, [0xd5]=false, [0xd6]=false, [0xea]=false,
106}, { __index = map_opc1_32 })
107
108-- Map for 2nd opcode byte (0F xx). True CISC hell. Hey, I told you.
109-- Prefix dependent MMX/SSE opcodes: (none)|rep|o16|repne, -|F3|66|F2
110local map_opc2 = {
111--0x
112[0]="sldt!Dmp","sgdt!Ump","larVrm","lslVrm",nil,"syscall","clts","sysret",
113"invd","wbinvd",nil,"ud1",nil,"$prefetch!Bm","femms","3dnowMrmu",
114--1x
115"movupsXrm|movssXrm|movupdXrm|movsdXrm",
116"movupsXmr|movssXmr|movupdXmr|movsdXmr",
117"movhlpsXrm$movlpsXrm|movsldupXrm|movlpdXrm|movddupXrm",
118"movlpsXmr||movlpdXmr",
119"unpcklpsXrm||unpcklpdXrm",
120"unpckhpsXrm||unpckhpdXrm",
121"movlhpsXrm$movhpsXrm|movshdupXrm|movhpdXrm",
122"movhpsXmr||movhpdXmr",
123"$prefetcht!Bm","hintnopVm","hintnopVm","hintnopVm",
124"hintnopVm","hintnopVm","hintnopVm","hintnopVm",
125--2x
126"movUmx$","movUmy$","movUxm$","movUym$","movUmz$",nil,"movUzm$",nil,
127"movapsXrm||movapdXrm",
128"movapsXmr||movapdXmr",
129"cvtpi2psXrMm|cvtsi2ssXrVmt|cvtpi2pdXrMm|cvtsi2sdXrVmt",
130"movntpsXmr|movntssXmr|movntpdXmr|movntsdXmr",
131"cvttps2piMrXm|cvttss2siVrXm|cvttpd2piMrXm|cvttsd2siVrXm",
132"cvtps2piMrXm|cvtss2siVrXm|cvtpd2piMrXm|cvtsd2siVrXm",
133"ucomissXrm||ucomisdXrm",
134"comissXrm||comisdXrm",
135--3x
136"wrmsr","rdtsc","rdmsr","rdpmc","sysenter","sysexit",nil,"getsec",
137"opc3*38",nil,"opc3*3a",nil,nil,nil,nil,nil,
138--4x
139"cmovoVrm","cmovnoVrm","cmovbVrm","cmovnbVrm",
140"cmovzVrm","cmovnzVrm","cmovbeVrm","cmovaVrm",
141"cmovsVrm","cmovnsVrm","cmovpeVrm","cmovpoVrm",
142"cmovlVrm","cmovgeVrm","cmovleVrm","cmovgVrm",
143--5x
144"movmskpsVrXm$||movmskpdVrXm$","sqrtpsXrm|sqrtssXrm|sqrtpdXrm|sqrtsdXrm",
145"rsqrtpsXrm|rsqrtssXrm","rcppsXrm|rcpssXrm",
146"andpsXrm||andpdXrm","andnpsXrm||andnpdXrm",
147"orpsXrm||orpdXrm","xorpsXrm||xorpdXrm",
148"addpsXrm|addssXrm|addpdXrm|addsdXrm","mulpsXrm|mulssXrm|mulpdXrm|mulsdXrm",
149"cvtps2pdXrm|cvtss2sdXrm|cvtpd2psXrm|cvtsd2ssXrm",
150"cvtdq2psXrm|cvttps2dqXrm|cvtps2dqXrm",
151"subpsXrm|subssXrm|subpdXrm|subsdXrm","minpsXrm|minssXrm|minpdXrm|minsdXrm",
152"divpsXrm|divssXrm|divpdXrm|divsdXrm","maxpsXrm|maxssXrm|maxpdXrm|maxsdXrm",
153--6x
154"punpcklbwPrm","punpcklwdPrm","punpckldqPrm","packsswbPrm",
155"pcmpgtbPrm","pcmpgtwPrm","pcmpgtdPrm","packuswbPrm",
156"punpckhbwPrm","punpckhwdPrm","punpckhdqPrm","packssdwPrm",
157"||punpcklqdqXrm","||punpckhqdqXrm",
158"movPrVSm","movqMrm|movdquXrm|movdqaXrm",
159--7x
160"pshufwMrmu|pshufhwXrmu|pshufdXrmu|pshuflwXrmu","pshiftw!Pmu",
161"pshiftd!Pmu","pshiftq!Mmu||pshiftdq!Xmu",
162"pcmpeqbPrm","pcmpeqwPrm","pcmpeqdPrm","emms|",
163"vmreadUmr||extrqXmuu$|insertqXrmuu$","vmwriteUrm||extrqXrm$|insertqXrm$",
164nil,nil,
165"||haddpdXrm|haddpsXrm","||hsubpdXrm|hsubpsXrm",
166"movVSmMr|movqXrm|movVSmXr","movqMmr|movdquXmr|movdqaXmr",
167--8x
168"joVj","jnoVj","jbVj","jnbVj","jzVj","jnzVj","jbeVj","jaVj",
169"jsVj","jnsVj","jpeVj","jpoVj","jlVj","jgeVj","jleVj","jgVj",
170--9x
171"setoBm","setnoBm","setbBm","setnbBm","setzBm","setnzBm","setbeBm","setaBm",
172"setsBm","setnsBm","setpeBm","setpoBm","setlBm","setgeBm","setleBm","setgBm",
173--Ax
174"push fs","pop fs","cpuid","btVmr","shldVmru","shldVmrc",nil,nil,
175"push gs","pop gs","rsm","btsVmr","shrdVmru","shrdVmrc","fxsave!Dmp","imulVrm",
176--Bx
177"cmpxchgBmr","cmpxchgVmr","$lssVrm","btrVmr",
178"$lfsVrm","$lgsVrm","movzxVrBmt","movzxVrWmt",
179"|popcntVrm","ud2Dp","bt!Vmu","btcVmr",
180"bsfVrm","bsrVrm|lzcntVrm|bsrWrm","movsxVrBmt","movsxVrWmt",
181--Cx
182"xaddBmr","xaddVmr",
183"cmppsXrmu|cmpssXrmu|cmppdXrmu|cmpsdXrmu","$movntiVmr|",
184"pinsrwPrWmu","pextrwDrPmu",
185"shufpsXrmu||shufpdXrmu","$cmpxchg!Qmp",
186"bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR",
187--Dx
188"||addsubpdXrm|addsubpsXrm","psrlwPrm","psrldPrm","psrlqPrm",
189"paddqPrm","pmullwPrm",
190"|movq2dqXrMm|movqXmr|movdq2qMrXm$","pmovmskbVrMm||pmovmskbVrXm",
191"psubusbPrm","psubuswPrm","pminubPrm","pandPrm",
192"paddusbPrm","padduswPrm","pmaxubPrm","pandnPrm",
193--Ex
194"pavgbPrm","psrawPrm","psradPrm","pavgwPrm",
195"pmulhuwPrm","pmulhwPrm",
196"|cvtdq2pdXrm|cvttpd2dqXrm|cvtpd2dqXrm","$movntqMmr||$movntdqXmr",
197"psubsbPrm","psubswPrm","pminswPrm","porPrm",
198"paddsbPrm","paddswPrm","pmaxswPrm","pxorPrm",
199--Fx
200"|||lddquXrm","psllwPrm","pslldPrm","psllqPrm",
201"pmuludqPrm","pmaddwdPrm","psadbwPrm","maskmovqMrm||maskmovdquXrm$",
202"psubbPrm","psubwPrm","psubdPrm","psubqPrm",
203"paddbPrm","paddwPrm","padddPrm","ud",
204}
205assert(map_opc2[255] == "ud")
206
207-- Map for three-byte opcodes. Can't wait for their next invention.
208local map_opc3 = {
209["38"] = { -- [66] 0f 38 xx
210--0x
211[0]="pshufbPrm","phaddwPrm","phadddPrm","phaddswPrm",
212"pmaddubswPrm","phsubwPrm","phsubdPrm","phsubswPrm",
213"psignbPrm","psignwPrm","psigndPrm","pmulhrswPrm",
214nil,nil,nil,nil,
215--1x
216"||pblendvbXrma",nil,nil,nil,
217"||blendvpsXrma","||blendvpdXrma",nil,"||ptestXrm",
218nil,nil,nil,nil,
219"pabsbPrm","pabswPrm","pabsdPrm",nil,
220--2x
221"||pmovsxbwXrm","||pmovsxbdXrm","||pmovsxbqXrm","||pmovsxwdXrm",
222"||pmovsxwqXrm","||pmovsxdqXrm",nil,nil,
223"||pmuldqXrm","||pcmpeqqXrm","||$movntdqaXrm","||packusdwXrm",
224nil,nil,nil,nil,
225--3x
226"||pmovzxbwXrm","||pmovzxbdXrm","||pmovzxbqXrm","||pmovzxwdXrm",
227"||pmovzxwqXrm","||pmovzxdqXrm",nil,"||pcmpgtqXrm",
228"||pminsbXrm","||pminsdXrm","||pminuwXrm","||pminudXrm",
229"||pmaxsbXrm","||pmaxsdXrm","||pmaxuwXrm","||pmaxudXrm",
230--4x
231"||pmulddXrm","||phminposuwXrm",
232--Fx
233[0xf0] = "|||crc32TrBmt",[0xf1] = "|||crc32TrVmt",
234},
235
236["3a"] = { -- [66] 0f 3a xx
237--0x
238[0x00]=nil,nil,nil,nil,nil,nil,nil,nil,
239"||roundpsXrmu","||roundpdXrmu","||roundssXrmu","||roundsdXrmu",
240"||blendpsXrmu","||blendpdXrmu","||pblendwXrmu","palignrPrmu",
241--1x
242nil,nil,nil,nil,
243"||pextrbVmXru","||pextrwVmXru","||pextrVmSXru","||extractpsVmXru",
244nil,nil,nil,nil,nil,nil,nil,nil,
245--2x
246"||pinsrbXrVmu","||insertpsXrmu","||pinsrXrVmuS",nil,
247--4x
248[0x40] = "||dppsXrmu",
249[0x41] = "||dppdXrmu",
250[0x42] = "||mpsadbwXrmu",
251--6x
252[0x60] = "||pcmpestrmXrmu",[0x61] = "||pcmpestriXrmu",
253[0x62] = "||pcmpistrmXrmu",[0x63] = "||pcmpistriXrmu",
254},
255}
256
257-- Map for VMX/SVM opcodes 0F 01 C0-FF (sgdt group with register operands).
258local map_opcvm = {
259[0xc1]="vmcall",[0xc2]="vmlaunch",[0xc3]="vmresume",[0xc4]="vmxoff",
260[0xc8]="monitor",[0xc9]="mwait",
261[0xd8]="vmrun",[0xd9]="vmmcall",[0xda]="vmload",[0xdb]="vmsave",
262[0xdc]="stgi",[0xdd]="clgi",[0xde]="skinit",[0xdf]="invlpga",
263[0xf8]="swapgs",[0xf9]="rdtscp",
264}
265
266-- Map for FP opcodes. And you thought stack machines are simple?
267local map_opcfp = {
268-- D8-DF 00-BF: opcodes with a memory operand.
269-- D8
270[0]="faddFm","fmulFm","fcomFm","fcompFm","fsubFm","fsubrFm","fdivFm","fdivrFm",
271"fldFm",nil,"fstFm","fstpFm","fldenvVm","fldcwWm","fnstenvVm","fnstcwWm",
272-- DA
273"fiaddDm","fimulDm","ficomDm","ficompDm",
274"fisubDm","fisubrDm","fidivDm","fidivrDm",
275-- DB
276"fildDm","fisttpDm","fistDm","fistpDm",nil,"fld twordFmp",nil,"fstp twordFmp",
277-- DC
278"faddGm","fmulGm","fcomGm","fcompGm","fsubGm","fsubrGm","fdivGm","fdivrGm",
279-- DD
280"fldGm","fisttpQm","fstGm","fstpGm","frstorDmp",nil,"fnsaveDmp","fnstswWm",
281-- DE
282"fiaddWm","fimulWm","ficomWm","ficompWm",
283"fisubWm","fisubrWm","fidivWm","fidivrWm",
284-- DF
285"fildWm","fisttpWm","fistWm","fistpWm",
286"fbld twordFmp","fildQm","fbstp twordFmp","fistpQm",
287-- xx C0-FF: opcodes with a pseudo-register operand.
288-- D8
289"faddFf","fmulFf","fcomFf","fcompFf","fsubFf","fsubrFf","fdivFf","fdivrFf",
290-- D9
291"fldFf","fxchFf",{"fnop"},nil,
292{"fchs","fabs",nil,nil,"ftst","fxam"},
293{"fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz"},
294{"f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp"},
295{"fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos"},
296-- DA
297"fcmovbFf","fcmoveFf","fcmovbeFf","fcmovuFf",nil,{nil,"fucompp"},nil,nil,
298-- DB
299"fcmovnbFf","fcmovneFf","fcmovnbeFf","fcmovnuFf",
300{nil,nil,"fnclex","fninit"},"fucomiFf","fcomiFf",nil,
301-- DC
302"fadd toFf","fmul toFf",nil,nil,
303"fsub toFf","fsubr toFf","fdivr toFf","fdiv toFf",
304-- DD
305"ffreeFf",nil,"fstFf","fstpFf","fucomFf","fucompFf",nil,nil,
306-- DE
307"faddpFf","fmulpFf",nil,{nil,"fcompp"},
308"fsubrpFf","fsubpFf","fdivrpFf","fdivpFf",
309-- DF
310nil,nil,nil,nil,{"fnstsw ax"},"fucomipFf","fcomipFf",nil,
311}
312assert(map_opcfp[126] == "fcomipFf")
313
314-- Map for opcode groups. The subkey is sp from the ModRM byte.
315local map_opcgroup = {
316 arith = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" },
317 shift = { "rol", "ror", "rcl", "rcr", "shl", "shr", "sal", "sar" },
318 testb = { "testBmi", "testBmi", "not", "neg", "mul", "imul", "div", "idiv" },
319 testv = { "testVmi", "testVmi", "not", "neg", "mul", "imul", "div", "idiv" },
320 incb = { "inc", "dec" },
321 incd = { "inc", "dec", "callUmp", "$call farDmp",
322 "jmpUmp", "$jmp farDmp", "pushUm" },
323 sldt = { "sldt", "str", "lldt", "ltr", "verr", "verw" },
324 sgdt = { "vm*$sgdt", "vm*$sidt", "$lgdt", "vm*$lidt",
325 "smsw", nil, "lmsw", "vm*$invlpg" },
326 bt = { nil, nil, nil, nil, "bt", "bts", "btr", "btc" },
327 cmpxchg = { nil, "sz*,cmpxchg8bQmp,cmpxchg16bXmp", nil, nil,
328 nil, nil, "vmptrld|vmxon|vmclear", "vmptrst" },
329 pshiftw = { nil, nil, "psrlw", nil, "psraw", nil, "psllw" },
330 pshiftd = { nil, nil, "psrld", nil, "psrad", nil, "pslld" },
331 pshiftq = { nil, nil, "psrlq", nil, nil, nil, "psllq" },
332 pshiftdq = { nil, nil, "psrlq", "psrldq", nil, nil, "psllq", "pslldq" },
333 fxsave = { "$fxsave", "$fxrstor", "$ldmxcsr", "$stmxcsr",
334 nil, "lfenceDp$", "mfenceDp$", "sfenceDp$clflush" },
335 prefetch = { "prefetch", "prefetchw" },
336 prefetcht = { "prefetchnta", "prefetcht0", "prefetcht1", "prefetcht2" },
337}
338
339------------------------------------------------------------------------------
340
341-- Maps for register names.
342local map_regs = {
343 B = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
344 "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" },
345 B64 = { "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
346 "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" },
347 W = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
348 "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" },
349 D = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
350 "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" },
351 Q = { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
352 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" },
353 M = { "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
354 "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" }, -- No x64 ext!
355 X = { "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
356 "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" },
357}
358local map_segregs = { "es", "cs", "ss", "ds", "fs", "gs", "segr6", "segr7" }
359
360-- Maps for size names.
361local map_sz2n = {
362 B = 1, W = 2, D = 4, Q = 8, M = 8, X = 16,
363}
364local map_sz2prefix = {
365 B = "byte", W = "word", D = "dword",
366 Q = "qword",
367 M = "qword", X = "xword",
368 F = "dword", G = "qword", -- No need for sizes/register names for these two.
369}
370
371------------------------------------------------------------------------------
372
373-- Output a nicely formatted line with an opcode and operands.
374local function putop(ctx, text, operands)
375 local code, pos, hex = ctx.code, ctx.pos, ""
376 local hmax = ctx.hexdump
377 if hmax > 0 then
378 for i=ctx.start,pos-1 do
379 hex = hex..format("%02X", byte(code, i, i))
380 end
381 if #hex > hmax then hex = sub(hex, 1, hmax)..". "
382 else hex = hex..rep(" ", hmax-#hex+2) end
383 end
384 if operands then text = text.." "..operands end
385 if ctx.o16 then text = "o16 "..text; ctx.o16 = false end
386 if ctx.a32 then text = "a32 "..text; ctx.a32 = false end
387 if ctx.rep then text = ctx.rep.." "..text; ctx.rep = false end
388 if ctx.rex then
389 local t = (ctx.rexw and "w" or "")..(ctx.rexr and "r" or "")..
390 (ctx.rexx and "x" or "")..(ctx.rexb and "b" or "")
391 if t ~= "" then text = "rex."..t.." "..text end
392 ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false
393 ctx.rex = false
394 end
395 if ctx.seg then
396 local text2, n = gsub(text, "%[", "["..ctx.seg..":")
397 if n == 0 then text = ctx.seg.." "..text else text = text2 end
398 ctx.seg = false
399 end
400 if ctx.lock then text = "lock "..text; ctx.lock = false end
401 local imm = ctx.imm
402 if imm then
403 local sym = ctx.symtab[imm]
404 if sym then text = text.."\t->"..sym end
405 end
406 ctx.out(format("%08x %s%s\n", ctx.addr+ctx.start, hex, text))
407 ctx.mrm = false
408 ctx.start = pos
409 ctx.imm = nil
410end
411
412-- Clear all prefix flags.
413local function clearprefixes(ctx)
414 ctx.o16 = false; ctx.seg = false; ctx.lock = false; ctx.rep = false
415 ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false
416 ctx.rex = false; ctx.a32 = false
417end
418
419-- Fallback for incomplete opcodes at the end.
420local function incomplete(ctx)
421 ctx.pos = ctx.stop+1
422 clearprefixes(ctx)
423 return putop(ctx, "(incomplete)")
424end
425
426-- Fallback for unknown opcodes.
427local function unknown(ctx)
428 clearprefixes(ctx)
429 return putop(ctx, "(unknown)")
430end
431
432-- Return an immediate of the specified size.
433local function getimm(ctx, pos, n)
434 if pos+n-1 > ctx.stop then return incomplete(ctx) end
435 local code = ctx.code
436 if n == 1 then
437 local b1 = byte(code, pos, pos)
438 return b1
439 elseif n == 2 then
440 local b1, b2 = byte(code, pos, pos+1)
441 return b1+b2*256
442 else
443 local b1, b2, b3, b4 = byte(code, pos, pos+3)
444 local imm = b1+b2*256+b3*65536+b4*16777216
445 ctx.imm = imm
446 return imm
447 end
448end
449
450-- Process pattern string and generate the operands.
451local function putpat(ctx, name, pat)
452 local operands, regs, sz, mode, sp, rm, sc, rx, sdisp
453 local code, pos, stop = ctx.code, ctx.pos, ctx.stop
454
455 -- Chars used: 1DFGIMPQRSTUVWXacdfgijmoprstuwxyz
456 for p in gmatch(pat, ".") do
457 local x = nil
458 if p == "V" or p == "U" then
459 if ctx.rexw then sz = "Q"; ctx.rexw = false
460 elseif ctx.o16 then sz = "W"; ctx.o16 = false
461 elseif p == "U" and ctx.x64 then sz = "Q"
462 else sz = "D" end
463 regs = map_regs[sz]
464 elseif p == "T" then
465 if ctx.rexw then sz = "Q"; ctx.rexw = false else sz = "D" end
466 regs = map_regs[sz]
467 elseif p == "B" then
468 sz = "B"
469 regs = ctx.rex and map_regs.B64 or map_regs.B
470 elseif match(p, "[WDQMXFG]") then
471 sz = p
472 regs = map_regs[sz]
473 elseif p == "P" then
474 sz = ctx.o16 and "X" or "M"; ctx.o16 = false
475 regs = map_regs[sz]
476 elseif p == "S" then
477 name = name..lower(sz)
478 elseif p == "s" then
479 local imm = getimm(ctx, pos, 1); if not imm then return end
480 x = imm <= 127 and format("+0x%02x", imm)
481 or format("-0x%02x", 256-imm)
482 pos = pos+1
483 elseif p == "u" then
484 local imm = getimm(ctx, pos, 1); if not imm then return end
485 x = format("0x%02x", imm)
486 pos = pos+1
487 elseif p == "w" then
488 local imm = getimm(ctx, pos, 2); if not imm then return end
489 x = format("0x%x", imm)
490 pos = pos+2
491 elseif p == "o" then -- [offset]
492 if ctx.x64 then
493 local imm1 = getimm(ctx, pos, 4); if not imm1 then return end
494 local imm2 = getimm(ctx, pos+4, 4); if not imm2 then return end
495 x = format("[0x%08x%08x]", imm2, imm1)
496 pos = pos+8
497 else
498 local imm = getimm(ctx, pos, 4); if not imm then return end
499 x = format("[0x%08x]", imm)
500 pos = pos+4
501 end
502 elseif p == "i" or p == "I" then
503 local n = map_sz2n[sz]
504 if n == 8 and ctx.x64 and p == "I" then
505 local imm1 = getimm(ctx, pos, 4); if not imm1 then return end
506 local imm2 = getimm(ctx, pos+4, 4); if not imm2 then return end
507 x = format("0x%08x%08x", imm2, imm1)
508 else
509 if n == 8 then n = 4 end
510 local imm = getimm(ctx, pos, n); if not imm then return end
511 if sz == "Q" and (imm < 0 or imm > 0x7fffffff) then
512 imm = (0xffffffff+1)-imm
513 x = format(imm > 65535 and "-0x%08x" or "-0x%x", imm)
514 else
515 x = format(imm > 65535 and "0x%08x" or "0x%x", imm)
516 end
517 end
518 pos = pos+n
519 elseif p == "j" then
520 local n = map_sz2n[sz]
521 if n == 8 then n = 4 end
522 local imm = getimm(ctx, pos, n); if not imm then return end
523 if sz == "B" and imm > 127 then imm = imm-256
524 elseif imm > 2147483647 then imm = imm-4294967296 end
525 pos = pos+n
526 imm = imm + pos + ctx.addr
527 if imm > 4294967295 and not ctx.x64 then imm = imm-4294967296 end
528 ctx.imm = imm
529 if sz == "W" then
530 x = format("word 0x%04x", imm%65536)
531 elseif ctx.x64 then
532 local lo = imm % 0x1000000
533 x = format("0x%02x%06x", (imm-lo) / 0x1000000, lo)
534 else
535 x = format("0x%08x", imm)
536 end
537 elseif p == "R" then
538 local r = byte(code, pos-1, pos-1)%8
539 if ctx.rexb then r = r + 8; ctx.rexb = false end
540 x = regs[r+1]
541 elseif p == "a" then x = regs[1]
542 elseif p == "c" then x = "cl"
543 elseif p == "d" then x = "dx"
544 elseif p == "1" then x = "1"
545 else
546 if not mode then
547 mode = ctx.mrm
548 if not mode then
549 if pos > stop then return incomplete(ctx) end
550 mode = byte(code, pos, pos)
551 pos = pos+1
552 end
553 rm = mode%8; mode = (mode-rm)/8
554 sp = mode%8; mode = (mode-sp)/8
555 sdisp = ""
556 if mode < 3 then
557 if rm == 4 then
558 if pos > stop then return incomplete(ctx) end
559 sc = byte(code, pos, pos)
560 pos = pos+1
561 rm = sc%8; sc = (sc-rm)/8
562 rx = sc%8; sc = (sc-rx)/8
563 if ctx.rexx then rx = rx + 8; ctx.rexx = false end
564 if rx == 4 then rx = nil end
565 end
566 if mode > 0 or rm == 5 then
567 local dsz = mode
568 if dsz ~= 1 then dsz = 4 end
569 local disp = getimm(ctx, pos, dsz); if not disp then return end
570 if mode == 0 then rm = nil end
571 if rm or rx or (not sc and ctx.x64 and not ctx.a32) then
572 if dsz == 1 and disp > 127 then
573 sdisp = format("-0x%x", 256-disp)
574 elseif disp >= 0 and disp <= 0x7fffffff then
575 sdisp = format("+0x%x", disp)
576 else
577 sdisp = format("-0x%x", (0xffffffff+1)-disp)
578 end
579 else
580 sdisp = format(ctx.x64 and not ctx.a32 and
581 not (disp >= 0 and disp <= 0x7fffffff)
582 and "0xffffffff%08x" or "0x%08x", disp)
583 end
584 pos = pos+dsz
585 end
586 end
587 if rm and ctx.rexb then rm = rm + 8; ctx.rexb = false end
588 if ctx.rexr then sp = sp + 8; ctx.rexr = false end
589 end
590 if p == "m" then
591 if mode == 3 then x = regs[rm+1]
592 else
593 local aregs = ctx.a32 and map_regs.D or ctx.aregs
594 local srm, srx = "", ""
595 if rm then srm = aregs[rm+1]
596 elseif not sc and ctx.x64 and not ctx.a32 then srm = "rip" end
597 ctx.a32 = false
598 if rx then
599 if rm then srm = srm.."+" end
600 srx = aregs[rx+1]
601 if sc > 0 then srx = srx.."*"..(2^sc) end
602 end
603 x = format("[%s%s%s]", srm, srx, sdisp)
604 end
605 if mode < 3 and
606 (not match(pat, "[aRrgp]") or match(pat, "t")) then -- Yuck.
607 x = map_sz2prefix[sz].." "..x
608 end
609 elseif p == "r" then x = regs[sp+1]
610 elseif p == "g" then x = map_segregs[sp+1]
611 elseif p == "p" then -- Suppress prefix.
612 elseif p == "f" then x = "st"..rm
613 elseif p == "x" then
614 if sp == 0 and ctx.lock and not ctx.x64 then
615 x = "CR8"; ctx.lock = false
616 else
617 x = "CR"..sp
618 end
619 elseif p == "y" then x = "DR"..sp
620 elseif p == "z" then x = "TR"..sp
621 elseif p == "t" then
622 else
623 error("bad pattern `"..pat.."'")
624 end
625 end
626 if x then operands = operands and operands..", "..x or x end
627 end
628 ctx.pos = pos
629 return putop(ctx, name, operands)
630end
631
632-- Forward declaration.
633local map_act
634
635-- Fetch and cache MRM byte.
636local function getmrm(ctx)
637 local mrm = ctx.mrm
638 if not mrm then
639 local pos = ctx.pos
640 if pos > ctx.stop then return nil end
641 mrm = byte(ctx.code, pos, pos)
642 ctx.pos = pos+1
643 ctx.mrm = mrm
644 end
645 return mrm
646end
647
648-- Dispatch to handler depending on pattern.
649local function dispatch(ctx, opat, patgrp)
650 if not opat then return unknown(ctx) end
651 if match(opat, "%|") then -- MMX/SSE variants depending on prefix.
652 local p
653 if ctx.rep then
654 p = ctx.rep=="rep" and "%|([^%|]*)" or "%|[^%|]*%|[^%|]*%|([^%|]*)"
655 ctx.rep = false
656 elseif ctx.o16 then p = "%|[^%|]*%|([^%|]*)"; ctx.o16 = false
657 else p = "^[^%|]*" end
658 opat = match(opat, p)
659 if not opat then return unknown(ctx) end
660-- ctx.rep = false; ctx.o16 = false
661 --XXX fails for 66 f2 0f 38 f1 06 crc32 eax,WORD PTR [esi]
662 --XXX remove in branches?
663 end
664 if match(opat, "%$") then -- reg$mem variants.
665 local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end
666 opat = match(opat, mrm >= 192 and "^[^%$]*" or "%$(.*)")
667 if opat == "" then return unknown(ctx) end
668 end
669 if opat == "" then return unknown(ctx) end
670 local name, pat = match(opat, "^([a-z0-9 ]*)(.*)")
671 if pat == "" and patgrp then pat = patgrp end
672 return map_act[sub(pat, 1, 1)](ctx, name, pat)
673end
674
675-- Get a pattern from an opcode map and dispatch to handler.
676local function dispatchmap(ctx, opcmap)
677 local pos = ctx.pos
678 local opat = opcmap[byte(ctx.code, pos, pos)]
679 pos = pos + 1
680 ctx.pos = pos
681 return dispatch(ctx, opat)
682end
683
684-- Map for action codes. The key is the first char after the name.
685map_act = {
686 -- Simple opcodes without operands.
687 [""] = function(ctx, name, pat)
688 return putop(ctx, name)
689 end,
690
691 -- Operand size chars fall right through.
692 B = putpat, W = putpat, D = putpat, Q = putpat,
693 V = putpat, U = putpat, T = putpat,
694 M = putpat, X = putpat, P = putpat,
695 F = putpat, G = putpat,
696
697 -- Collect prefixes.
698 [":"] = function(ctx, name, pat)
699 ctx[pat == ":" and name or sub(pat, 2)] = name
700 if ctx.pos - ctx.start > 5 then return unknown(ctx) end -- Limit #prefixes.
701 end,
702
703 -- Chain to special handler specified by name.
704 ["*"] = function(ctx, name, pat)
705 return map_act[name](ctx, name, sub(pat, 2))
706 end,
707
708 -- Use named subtable for opcode group.
709 ["!"] = function(ctx, name, pat)
710 local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end
711 return dispatch(ctx, map_opcgroup[name][((mrm-(mrm%8))/8)%8+1], sub(pat, 2))
712 end,
713
714 -- o16,o32[,o64] variants.
715 sz = function(ctx, name, pat)
716 if ctx.o16 then ctx.o16 = false
717 else
718 pat = match(pat, ",(.*)")
719 if ctx.rexw then
720 local p = match(pat, ",(.*)")
721 if p then pat = p; ctx.rexw = false end
722 end
723 end
724 pat = match(pat, "^[^,]*")
725 return dispatch(ctx, pat)
726 end,
727
728 -- Two-byte opcode dispatch.
729 opc2 = function(ctx, name, pat)
730 return dispatchmap(ctx, map_opc2)
731 end,
732
733 -- Three-byte opcode dispatch.
734 opc3 = function(ctx, name, pat)
735 return dispatchmap(ctx, map_opc3[pat])
736 end,
737
738 -- VMX/SVM dispatch.
739 vm = function(ctx, name, pat)
740 return dispatch(ctx, map_opcvm[ctx.mrm])
741 end,
742
743 -- Floating point opcode dispatch.
744 fp = function(ctx, name, pat)
745 local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end
746 local rm = mrm%8
747 local idx = pat*8 + ((mrm-rm)/8)%8
748 if mrm >= 192 then idx = idx + 64 end
749 local opat = map_opcfp[idx]
750 if type(opat) == "table" then opat = opat[rm+1] end
751 return dispatch(ctx, opat)
752 end,
753
754 -- REX prefix.
755 rex = function(ctx, name, pat)
756 if ctx.rex then return unknown(ctx) end -- Only 1 REX prefix allowed.
757 for p in gmatch(pat, ".") do ctx["rex"..p] = true end
758 ctx.rex = true
759 end,
760
761 -- Special case for nop with REX prefix.
762 nop = function(ctx, name, pat)
763 return dispatch(ctx, ctx.rex and pat or "nop")
764 end,
765}
766
767------------------------------------------------------------------------------
768
769-- Disassemble a block of code.
770local function disass_block(ctx, ofs, len)
771 if not ofs then ofs = 0 end
772 local stop = len and ofs+len or #ctx.code
773 ofs = ofs + 1
774 ctx.start = ofs
775 ctx.pos = ofs
776 ctx.stop = stop
777 ctx.imm = nil
778 ctx.mrm = false
779 clearprefixes(ctx)
780 while ctx.pos <= stop do dispatchmap(ctx, ctx.map1) end
781 if ctx.pos ~= ctx.start then incomplete(ctx) end
782end
783
784-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).
785local function create_(code, addr, out)
786 local ctx = {}
787 ctx.code = code
788 ctx.addr = (addr or 0) - 1
789 ctx.out = out or io.write
790 ctx.symtab = {}
791 ctx.disass = disass_block
792 ctx.hexdump = 16
793 ctx.x64 = false
794 ctx.map1 = map_opc1_32
795 ctx.aregs = map_regs.D
796 return ctx
797end
798
799local function create64_(code, addr, out)
800 local ctx = create_(code, addr, out)
801 ctx.x64 = true
802 ctx.map1 = map_opc1_64
803 ctx.aregs = map_regs.Q
804 return ctx
805end
806
807-- Simple API: disassemble code (a string) at address and output via out.
808local function disass_(code, addr, out)
809 create_(code, addr, out):disass()
810end
811
812local function disass64_(code, addr, out)
813 create64_(code, addr, out):disass()
814end
815
816-- Return register name for RID.
817local function regname_(r)
818 if r < 8 then return map_regs.D[r+1] end
819 return map_regs.X[r-7]
820end
821
822local function regname64_(r)
823 if r < 16 then return map_regs.Q[r+1] end
824 return map_regs.X[r-15]
825end
826
827-- Public module functions.
828module(...)
829
830create = create_
831create64 = create64_
832disass = disass_
833disass64 = disass64_
834regname = regname_
835regname64 = regname64_
836
diff --git a/libraries/luajit-2.0/lib/dump.lua b/libraries/luajit-2.0/lib/dump.lua
new file mode 100644
index 0000000..0f0e905
--- /dev/null
+++ b/libraries/luajit-2.0/lib/dump.lua
@@ -0,0 +1,685 @@
1----------------------------------------------------------------------------
2-- LuaJIT compiler dump module.
3--
4-- Copyright (C) 2005-2011 Mike Pall. All rights reserved.
5-- Released under the MIT license. See Copyright Notice in luajit.h
6----------------------------------------------------------------------------
7--
8-- This module can be used to debug the JIT compiler itself. It dumps the
9-- code representations and structures used in various compiler stages.
10--
11-- Example usage:
12--
13-- luajit -jdump -e "local x=0; for i=1,1e6 do x=x+i end; print(x)"
14-- luajit -jdump=im -e "for i=1,1000 do for j=1,1000 do end end" | less -R
15-- luajit -jdump=is myapp.lua | less -R
16-- luajit -jdump=-b myapp.lua
17-- luajit -jdump=+aH,myapp.html myapp.lua
18-- luajit -jdump=ixT,myapp.dump myapp.lua
19--
20-- The first argument specifies the dump mode. The second argument gives
21-- the output file name. Default output is to stdout, unless the environment
22-- variable LUAJIT_DUMPFILE is set. The file is overwritten every time the
23-- module is started.
24--
25-- Different features can be turned on or off with the dump mode. If the
26-- mode starts with a '+', the following features are added to the default
27-- set of features; a '-' removes them. Otherwise the features are replaced.
28--
29-- The following dump features are available (* marks the default):
30--
31-- * t Print a line for each started, ended or aborted trace (see also -jv).
32-- * b Dump the traced bytecode.
33-- * i Dump the IR (intermediate representation).
34-- r Augment the IR with register/stack slots.
35-- s Dump the snapshot map.
36-- * m Dump the generated machine code.
37-- x Print each taken trace exit.
38-- X Print each taken trace exit and the contents of all registers.
39--
40-- The output format can be set with the following characters:
41--
42-- T Plain text output.
43-- A ANSI-colored text output
44-- H Colorized HTML + CSS output.
45--
46-- The default output format is plain text. It's set to ANSI-colored text
47-- if the COLORTERM variable is set. Note: this is independent of any output
48-- redirection, which is actually considered a feature.
49--
50-- You probably want to use less -R to enjoy viewing ANSI-colored text from
51-- a pipe or a file. Add this to your ~/.bashrc: export LESS="-R"
52--
53------------------------------------------------------------------------------
54
55-- Cache some library functions and objects.
56local jit = require("jit")
57assert(jit.version_num == 20000, "LuaJIT core/library version mismatch")
58local jutil = require("jit.util")
59local vmdef = require("jit.vmdef")
60local funcinfo, funcbc = jutil.funcinfo, jutil.funcbc
61local traceinfo, traceir, tracek = jutil.traceinfo, jutil.traceir, jutil.tracek
62local tracemc, tracesnap = jutil.tracemc, jutil.tracesnap
63local traceexitstub, ircalladdr = jutil.traceexitstub, jutil.ircalladdr
64local bit = require("bit")
65local band, shl, shr = bit.band, bit.lshift, bit.rshift
66local sub, gsub, format = string.sub, string.gsub, string.format
67local byte, char, rep = string.byte, string.char, string.rep
68local type, tostring = type, tostring
69local stdout, stderr = io.stdout, io.stderr
70
71-- Load other modules on-demand.
72local bcline, disass
73
74-- Active flag, output file handle and dump mode.
75local active, out, dumpmode
76
77------------------------------------------------------------------------------
78
79local symtabmt = { __index = false }
80local symtab = {}
81local nexitsym = 0
82
83-- Fill nested symbol table with per-trace exit stub addresses.
84local function fillsymtab_tr(tr, nexit)
85 local t = {}
86 symtabmt.__index = t
87 for i=0,nexit-1 do
88 local addr = traceexitstub(tr, i)
89 t[addr] = tostring(i)
90 end
91 local addr = traceexitstub(tr, nexit)
92 if addr then t[addr] = "stack_check" end
93end
94
95-- Fill symbol table with trace exit stub addresses.
96local function fillsymtab(tr, nexit)
97 local t = symtab
98 if nexitsym == 0 then
99 local ircall = vmdef.ircall
100 for i=0,#ircall do
101 local addr = ircalladdr(i)
102 if addr ~= 0 then t[addr] = ircall[i] end
103 end
104 end
105 if nexitsym == 1000000 then -- Per-trace exit stubs.
106 fillsymtab_tr(tr, nexit)
107 elseif nexit > nexitsym then -- Shared exit stubs.
108 for i=nexitsym,nexit-1 do
109 local addr = traceexitstub(i)
110 if addr == nil then -- Fall back to per-trace exit stubs.
111 fillsymtab_tr(tr, nexit)
112 setmetatable(symtab, symtabmt)
113 nexit = 1000000
114 break
115 end
116 t[addr] = tostring(i)
117 end
118 nexitsym = nexit
119 end
120 return t
121end
122
123local function dumpwrite(s)
124 out:write(s)
125end
126
127-- Disassemble machine code.
128local function dump_mcode(tr)
129 local info = traceinfo(tr)
130 if not info then return end
131 local mcode, addr, loop = tracemc(tr)
132 if not mcode then return end
133 if not disass then disass = require("jit.dis_"..jit.arch) end
134 out:write("---- TRACE ", tr, " mcode ", #mcode, "\n")
135 local ctx = disass.create(mcode, addr, dumpwrite)
136 ctx.hexdump = 0
137 ctx.symtab = fillsymtab(tr, info.nexit)
138 if loop ~= 0 then
139 symtab[addr+loop] = "LOOP"
140 ctx:disass(0, loop)
141 out:write("->LOOP:\n")
142 ctx:disass(loop, #mcode-loop)
143 symtab[addr+loop] = nil
144 else
145 ctx:disass(0, #mcode)
146 end
147end
148
149------------------------------------------------------------------------------
150
151local irtype_text = {
152 [0] = "nil",
153 "fal",
154 "tru",
155 "lud",
156 "str",
157 "p32",
158 "thr",
159 "pro",
160 "fun",
161 "p64",
162 "cdt",
163 "tab",
164 "udt",
165 "flt",
166 "num",
167 "i8 ",
168 "u8 ",
169 "i16",
170 "u16",
171 "int",
172 "u32",
173 "i64",
174 "u64",
175 "sfp",
176}
177
178local colortype_ansi = {
179 [0] = "%s",
180 "%s",
181 "%s",
182 "\027[36m%s\027[m",
183 "\027[32m%s\027[m",
184 "%s",
185 "\027[1m%s\027[m",
186 "%s",
187 "\027[1m%s\027[m",
188 "%s",
189 "\027[33m%s\027[m",
190 "\027[31m%s\027[m",
191 "\027[36m%s\027[m",
192 "\027[34m%s\027[m",
193 "\027[34m%s\027[m",
194 "\027[35m%s\027[m",
195 "\027[35m%s\027[m",
196 "\027[35m%s\027[m",
197 "\027[35m%s\027[m",
198 "\027[35m%s\027[m",
199 "\027[35m%s\027[m",
200 "\027[35m%s\027[m",
201 "\027[35m%s\027[m",
202 "\027[35m%s\027[m",
203}
204
205local function colorize_text(s, t)
206 return s
207end
208
209local function colorize_ansi(s, t)
210 return format(colortype_ansi[t], s)
211end
212
213local irtype_ansi = setmetatable({},
214 { __index = function(tab, t)
215 local s = colorize_ansi(irtype_text[t], t); tab[t] = s; return s; end })
216
217local html_escape = { ["<"] = "&lt;", [">"] = "&gt;", ["&"] = "&amp;", }
218
219local function colorize_html(s, t)
220 s = gsub(s, "[<>&]", html_escape)
221 return format('<span class="irt_%s">%s</span>', irtype_text[t], s)
222end
223
224local irtype_html = setmetatable({},
225 { __index = function(tab, t)
226 local s = colorize_html(irtype_text[t], t); tab[t] = s; return s; end })
227
228local header_html = [[
229<style type="text/css">
230background { background: #ffffff; color: #000000; }
231pre.ljdump {
232font-size: 10pt;
233background: #f0f4ff;
234color: #000000;
235border: 1px solid #bfcfff;
236padding: 0.5em;
237margin-left: 2em;
238margin-right: 2em;
239}
240span.irt_str { color: #00a000; }
241span.irt_thr, span.irt_fun { color: #404040; font-weight: bold; }
242span.irt_tab { color: #c00000; }
243span.irt_udt, span.irt_lud { color: #00c0c0; }
244span.irt_num { color: #4040c0; }
245span.irt_int, span.irt_i8, span.irt_u8, span.irt_i16, span.irt_u16 { color: #b040b0; }
246</style>
247]]
248
249local colorize, irtype
250
251-- Lookup tables to convert some literals into names.
252local litname = {
253 ["SLOAD "] = setmetatable({}, { __index = function(t, mode)
254 local s = ""
255 if band(mode, 1) ~= 0 then s = s.."P" end
256 if band(mode, 2) ~= 0 then s = s.."F" end
257 if band(mode, 4) ~= 0 then s = s.."T" end
258 if band(mode, 8) ~= 0 then s = s.."C" end
259 if band(mode, 16) ~= 0 then s = s.."R" end
260 if band(mode, 32) ~= 0 then s = s.."I" end
261 t[mode] = s
262 return s
263 end}),
264 ["XLOAD "] = { [0] = "", "R", "V", "RV", "U", "RU", "VU", "RVU", },
265 ["CONV "] = setmetatable({}, { __index = function(t, mode)
266 local s = irtype[band(mode, 31)]
267 s = irtype[band(shr(mode, 5), 31)].."."..s
268 if band(mode, 0x400) ~= 0 then s = s.." trunc"
269 elseif band(mode, 0x800) ~= 0 then s = s.." sext" end
270 local c = shr(mode, 14)
271 if c == 2 then s = s.." index" elseif c == 3 then s = s.." check" end
272 t[mode] = s
273 return s
274 end}),
275 ["FLOAD "] = vmdef.irfield,
276 ["FREF "] = vmdef.irfield,
277 ["FPMATH"] = vmdef.irfpm,
278}
279
280local function ctlsub(c)
281 if c == "\n" then return "\\n"
282 elseif c == "\r" then return "\\r"
283 elseif c == "\t" then return "\\t"
284 elseif c == "\r" then return "\\r"
285 else return format("\\%03d", byte(c))
286 end
287end
288
289local function fmtfunc(func, pc)
290 local fi = funcinfo(func, pc)
291 if fi.loc then
292 return fi.loc
293 elseif fi.ffid then
294 return vmdef.ffnames[fi.ffid]
295 elseif fi.addr then
296 return format("C:%x", fi.addr)
297 else
298 return "(?)"
299 end
300end
301
302local function formatk(tr, idx)
303 local k, t, slot = tracek(tr, idx)
304 local tn = type(k)
305 local s
306 if tn == "number" then
307 if k == 2^52+2^51 then
308 s = "bias"
309 else
310 s = format("%+.14g", k)
311 end
312 elseif tn == "string" then
313 s = format(#k > 20 and '"%.20s"~' or '"%s"', gsub(k, "%c", ctlsub))
314 elseif tn == "function" then
315 s = fmtfunc(k)
316 elseif tn == "table" then
317 s = format("{%p}", k)
318 elseif tn == "userdata" then
319 if t == 12 then
320 s = format("userdata:%p", k)
321 else
322 s = format("[%p]", k)
323 if s == "[0x00000000]" then s = "NULL" end
324 end
325 elseif t == 21 then -- int64_t
326 s = sub(tostring(k), 1, -3)
327 if sub(s, 1, 1) ~= "-" then s = "+"..s end
328 else
329 s = tostring(k) -- For primitives.
330 end
331 s = colorize(format("%-4s", s), t)
332 if slot then
333 s = format("%s @%d", s, slot)
334 end
335 return s
336end
337
338local function printsnap(tr, snap)
339 local n = 2
340 for s=0,snap[1]-1 do
341 local sn = snap[n]
342 if shr(sn, 24) == s then
343 n = n + 1
344 local ref = band(sn, 0xffff) - 0x8000 -- REF_BIAS
345 if ref < 0 then
346 out:write(formatk(tr, ref))
347 elseif band(sn, 0x80000) ~= 0 then -- SNAP_SOFTFPNUM
348 out:write(colorize(format("%04d/%04d", ref, ref+1), 14))
349 else
350 local m, ot, op1, op2 = traceir(tr, ref)
351 out:write(colorize(format("%04d", ref), band(ot, 31)))
352 end
353 out:write(band(sn, 0x10000) == 0 and " " or "|") -- SNAP_FRAME
354 else
355 out:write("---- ")
356 end
357 end
358 out:write("]\n")
359end
360
361-- Dump snapshots (not interleaved with IR).
362local function dump_snap(tr)
363 out:write("---- TRACE ", tr, " snapshots\n")
364 for i=0,1000000000 do
365 local snap = tracesnap(tr, i)
366 if not snap then break end
367 out:write(format("#%-3d %04d [ ", i, snap[0]))
368 printsnap(tr, snap)
369 end
370end
371
372-- Return a register name or stack slot for a rid/sp location.
373local function ridsp_name(ridsp)
374 if not disass then disass = require("jit.dis_"..jit.arch) end
375 local rid = band(ridsp, 0xff)
376 if ridsp > 255 then return format("[%x]", shr(ridsp, 8)*4) end
377 if rid < 128 then return disass.regname(rid) end
378 return ""
379end
380
381-- Dump CALL* function ref and return optional ctype.
382local function dumpcallfunc(tr, ins)
383 local ctype
384 if ins > 0 then
385 local m, ot, op1, op2 = traceir(tr, ins)
386 if band(ot, 31) == 0 then -- nil type means CARG(func, ctype).
387 ins = op1
388 ctype = formatk(tr, op2)
389 end
390 end
391 if ins < 0 then
392 out:write(format("[0x%x](", tonumber((tracek(tr, ins)))))
393 else
394 out:write(format("%04d (", ins))
395 end
396 return ctype
397end
398
399-- Recursively gather CALL* args and dump them.
400local function dumpcallargs(tr, ins)
401 if ins < 0 then
402 out:write(formatk(tr, ins))
403 else
404 local m, ot, op1, op2 = traceir(tr, ins)
405 local oidx = 6*shr(ot, 8)
406 local op = sub(vmdef.irnames, oidx+1, oidx+6)
407 if op == "CARG " then
408 dumpcallargs(tr, op1)
409 if op2 < 0 then
410 out:write(" ", formatk(tr, op2))
411 else
412 out:write(" ", format("%04d", op2))
413 end
414 else
415 out:write(format("%04d", ins))
416 end
417 end
418end
419
420-- Dump IR and interleaved snapshots.
421local function dump_ir(tr, dumpsnap, dumpreg)
422 local info = traceinfo(tr)
423 if not info then return end
424 local nins = info.nins
425 out:write("---- TRACE ", tr, " IR\n")
426 local irnames = vmdef.irnames
427 local snapref = 65536
428 local snap, snapno
429 if dumpsnap then
430 snap = tracesnap(tr, 0)
431 snapref = snap[0]
432 snapno = 0
433 end
434 for ins=1,nins do
435 if ins >= snapref then
436 if dumpreg then
437 out:write(format(".... SNAP #%-3d [ ", snapno))
438 else
439 out:write(format(".... SNAP #%-3d [ ", snapno))
440 end
441 printsnap(tr, snap)
442 snapno = snapno + 1
443 snap = tracesnap(tr, snapno)
444 snapref = snap and snap[0] or 65536
445 end
446 local m, ot, op1, op2, ridsp = traceir(tr, ins)
447 local oidx, t = 6*shr(ot, 8), band(ot, 31)
448 local op = sub(irnames, oidx+1, oidx+6)
449 if op == "LOOP " then
450 if dumpreg then
451 out:write(format("%04d ------------ LOOP ------------\n", ins))
452 else
453 out:write(format("%04d ------ LOOP ------------\n", ins))
454 end
455 elseif op ~= "NOP " and op ~= "CARG " and
456 (dumpreg or op ~= "RENAME") then
457 if dumpreg then
458 out:write(format("%04d %-5s ", ins, ridsp_name(ridsp)))
459 else
460 out:write(format("%04d ", ins))
461 end
462 out:write(format("%s%s %s %s ",
463 band(ot, 128) == 0 and " " or ">",
464 band(ot, 64) == 0 and " " or "+",
465 irtype[t], op))
466 local m1, m2 = band(m, 3), band(m, 3*4)
467 if sub(op, 1, 4) == "CALL" then
468 local ctype
469 if m2 == 1*4 then -- op2 == IRMlit
470 out:write(format("%-10s (", vmdef.ircall[op2]))
471 else
472 ctype = dumpcallfunc(tr, op2)
473 end
474 if op1 ~= -1 then dumpcallargs(tr, op1) end
475 out:write(")")
476 if ctype then out:write(" ctype ", ctype) end
477 elseif op == "CNEW " and op2 == -1 then
478 out:write(formatk(tr, op1))
479 elseif m1 ~= 3 then -- op1 != IRMnone
480 if op1 < 0 then
481 out:write(formatk(tr, op1))
482 else
483 out:write(format(m1 == 0 and "%04d" or "#%-3d", op1))
484 end
485 if m2 ~= 3*4 then -- op2 != IRMnone
486 if m2 == 1*4 then -- op2 == IRMlit
487 local litn = litname[op]
488 if litn and litn[op2] then
489 out:write(" ", litn[op2])
490 elseif op == "UREFO " or op == "UREFC " then
491 out:write(format(" #%-3d", shr(op2, 8)))
492 else
493 out:write(format(" #%-3d", op2))
494 end
495 elseif op2 < 0 then
496 out:write(" ", formatk(tr, op2))
497 else
498 out:write(format(" %04d", op2))
499 end
500 end
501 end
502 out:write("\n")
503 end
504 end
505 if snap then
506 if dumpreg then
507 out:write(format(".... SNAP #%-3d [ ", snapno))
508 else
509 out:write(format(".... SNAP #%-3d [ ", snapno))
510 end
511 printsnap(tr, snap)
512 end
513end
514
515------------------------------------------------------------------------------
516
517local recprefix = ""
518local recdepth = 0
519
520-- Format trace error message.
521local function fmterr(err, info)
522 if type(err) == "number" then
523 if type(info) == "function" then info = fmtfunc(info) end
524 err = format(vmdef.traceerr[err], info)
525 end
526 return err
527end
528
529-- Dump trace states.
530local function dump_trace(what, tr, func, pc, otr, oex)
531 if what == "stop" or (what == "abort" and dumpmode.a) then
532 if dumpmode.i then dump_ir(tr, dumpmode.s, dumpmode.r and what == "stop")
533 elseif dumpmode.s then dump_snap(tr) end
534 if dumpmode.m then dump_mcode(tr) end
535 end
536 if what == "start" then
537 if dumpmode.H then out:write('<pre class="ljdump">\n') end
538 out:write("---- TRACE ", tr, " ", what)
539 if otr then out:write(" ", otr, "/", oex) end
540 out:write(" ", fmtfunc(func, pc), "\n")
541 recprefix = ""
542 elseif what == "stop" or what == "abort" then
543 out:write("---- TRACE ", tr, " ", what)
544 recprefix = nil
545 if what == "abort" then
546 out:write(" ", fmtfunc(func, pc), " -- ", fmterr(otr, oex), "\n")
547 else
548 local info = traceinfo(tr)
549 local link, ltype = info.link, info.linktype
550 if link == tr or link == 0 then
551 out:write(" -> ", ltype, "\n")
552 elseif ltype == "root" then
553 out:write(" -> ", link, "\n")
554 else
555 out:write(" -> ", link, " ", ltype, "\n")
556 end
557 end
558 if dumpmode.H then out:write("</pre>\n\n") else out:write("\n") end
559 else
560 out:write("---- TRACE ", what, "\n\n")
561 end
562 out:flush()
563end
564
565-- Dump recorded bytecode.
566local function dump_record(tr, func, pc, depth, callee)
567 if depth ~= recdepth then
568 recdepth = depth
569 recprefix = rep(" .", depth)
570 end
571 local line
572 if pc >= 0 then
573 line = bcline(func, pc, recprefix)
574 if dumpmode.H then line = gsub(line, "[<>&]", html_escape) end
575 else
576 line = "0000 "..recprefix.." FUNCC \n"
577 callee = func
578 end
579 if pc <= 0 then
580 out:write(sub(line, 1, -2), " ; ", fmtfunc(func), "\n")
581 else
582 out:write(line)
583 end
584 if pc >= 0 and band(funcbc(func, pc), 0xff) < 16 then -- ORDER BC
585 out:write(bcline(func, pc+1, recprefix)) -- Write JMP for cond.
586 end
587end
588
589------------------------------------------------------------------------------
590
591-- Dump taken trace exits.
592local function dump_texit(tr, ex, ngpr, nfpr, ...)
593 out:write("---- TRACE ", tr, " exit ", ex, "\n")
594 if dumpmode.X then
595 local regs = {...}
596 if jit.arch == "x64" then
597 for i=1,ngpr do
598 out:write(format(" %016x", regs[i]))
599 if i % 4 == 0 then out:write("\n") end
600 end
601 else
602 for i=1,ngpr do
603 out:write(format(" %08x", regs[i]))
604 if i % 8 == 0 then out:write("\n") end
605 end
606 end
607 for i=1,nfpr do
608 out:write(format(" %+17.14g", regs[ngpr+i]))
609 if i % 4 == 0 then out:write("\n") end
610 end
611 end
612end
613
614------------------------------------------------------------------------------
615
616-- Detach dump handlers.
617local function dumpoff()
618 if active then
619 active = false
620 jit.attach(dump_texit)
621 jit.attach(dump_record)
622 jit.attach(dump_trace)
623 if out and out ~= stdout and out ~= stderr then out:close() end
624 out = nil
625 end
626end
627
628-- Open the output file and attach dump handlers.
629local function dumpon(opt, outfile)
630 if active then dumpoff() end
631
632 local colormode = os.getenv("COLORTERM") and "A" or "T"
633 if opt then
634 opt = gsub(opt, "[TAH]", function(mode) colormode = mode; return ""; end)
635 end
636
637 local m = { t=true, b=true, i=true, m=true, }
638 if opt and opt ~= "" then
639 local o = sub(opt, 1, 1)
640 if o ~= "+" and o ~= "-" then m = {} end
641 for i=1,#opt do m[sub(opt, i, i)] = (o ~= "-") end
642 end
643 dumpmode = m
644
645 if m.t or m.b or m.i or m.s or m.m then
646 jit.attach(dump_trace, "trace")
647 end
648 if m.b then
649 jit.attach(dump_record, "record")
650 if not bcline then bcline = require("jit.bc").line end
651 end
652 if m.x or m.X then
653 jit.attach(dump_texit, "texit")
654 end
655
656 if not outfile then outfile = os.getenv("LUAJIT_DUMPFILE") end
657 if outfile then
658 out = outfile == "-" and stdout or assert(io.open(outfile, "w"))
659 else
660 out = stdout
661 end
662
663 m[colormode] = true
664 if colormode == "A" then
665 colorize = colorize_ansi
666 irtype = irtype_ansi
667 elseif colormode == "H" then
668 colorize = colorize_html
669 irtype = irtype_html
670 out:write(header_html)
671 else
672 colorize = colorize_text
673 irtype = irtype_text
674 end
675
676 active = true
677end
678
679-- Public module functions.
680module(...)
681
682on = dumpon
683off = dumpoff
684start = dumpon -- For -j command line option.
685
diff --git a/libraries/luajit-2.0/lib/v.lua b/libraries/luajit-2.0/lib/v.lua
new file mode 100644
index 0000000..ca9b4ac
--- /dev/null
+++ b/libraries/luajit-2.0/lib/v.lua
@@ -0,0 +1,167 @@
1----------------------------------------------------------------------------
2-- Verbose mode of the LuaJIT compiler.
3--
4-- Copyright (C) 2005-2011 Mike Pall. All rights reserved.
5-- Released under the MIT license. See Copyright Notice in luajit.h
6----------------------------------------------------------------------------
7--
8-- This module shows verbose information about the progress of the
9-- JIT compiler. It prints one line for each generated trace. This module
10-- is useful to see which code has been compiled or where the compiler
11-- punts and falls back to the interpreter.
12--
13-- Example usage:
14--
15-- luajit -jv -e "for i=1,1000 do for j=1,1000 do end end"
16-- luajit -jv=myapp.out myapp.lua
17--
18-- Default output is to stderr. To redirect the output to a file, pass a
19-- filename as an argument (use '-' for stdout) or set the environment
20-- variable LUAJIT_VERBOSEFILE. The file is overwritten every time the
21-- module is started.
22--
23-- The output from the first example should look like this:
24--
25-- [TRACE 1 (command line):1 loop]
26-- [TRACE 2 (1/3) (command line):1 -> 1]
27--
28-- The first number in each line is the internal trace number. Next are
29-- the file name ('(command line)') and the line number (':1') where the
30-- trace has started. Side traces also show the parent trace number and
31-- the exit number where they are attached to in parentheses ('(1/3)').
32-- An arrow at the end shows where the trace links to ('-> 1'), unless
33-- it loops to itself.
34--
35-- In this case the inner loop gets hot and is traced first, generating
36-- a root trace. Then the last exit from the 1st trace gets hot, too,
37-- and triggers generation of the 2nd trace. The side trace follows the
38-- path along the outer loop and *around* the inner loop, back to its
39-- start, and then links to the 1st trace. Yes, this may seem unusual,
40-- if you know how traditional compilers work. Trace compilers are full
41-- of surprises like this -- have fun! :-)
42--
43-- Aborted traces are shown like this:
44--
45-- [TRACE --- foo.lua:44 -- leaving loop in root trace at foo:lua:50]
46--
47-- Don't worry -- trace aborts are quite common, even in programs which
48-- can be fully compiled. The compiler may retry several times until it
49-- finds a suitable trace.
50--
51-- Of course this doesn't work with features that are not-yet-implemented
52-- (NYI error messages). The VM simply falls back to the interpreter. This
53-- may not matter at all if the particular trace is not very high up in
54-- the CPU usage profile. Oh, and the interpreter is quite fast, too.
55--
56-- Also check out the -jdump module, which prints all the gory details.
57--
58------------------------------------------------------------------------------
59
60-- Cache some library functions and objects.
61local jit = require("jit")
62assert(jit.version_num == 20000, "LuaJIT core/library version mismatch")
63local jutil = require("jit.util")
64local vmdef = require("jit.vmdef")
65local funcinfo, traceinfo = jutil.funcinfo, jutil.traceinfo
66local type, format = type, string.format
67local stdout, stderr = io.stdout, io.stderr
68
69-- Active flag and output file handle.
70local active, out
71
72------------------------------------------------------------------------------
73
74local startloc, startex
75
76local function fmtfunc(func, pc)
77 local fi = funcinfo(func, pc)
78 if fi.loc then
79 return fi.loc
80 elseif fi.ffid then
81 return vmdef.ffnames[fi.ffid]
82 elseif fi.addr then
83 return format("C:%x", fi.addr)
84 else
85 return "(?)"
86 end
87end
88
89-- Format trace error message.
90local function fmterr(err, info)
91 if type(err) == "number" then
92 if type(info) == "function" then info = fmtfunc(info) end
93 err = format(vmdef.traceerr[err], info)
94 end
95 return err
96end
97
98-- Dump trace states.
99local function dump_trace(what, tr, func, pc, otr, oex)
100 if what == "start" then
101 startloc = fmtfunc(func, pc)
102 startex = otr and "("..otr.."/"..oex..") " or ""
103 else
104 if what == "abort" then
105 local loc = fmtfunc(func, pc)
106 if loc ~= startloc then
107 out:write(format("[TRACE --- %s%s -- %s at %s]\n",
108 startex, startloc, fmterr(otr, oex), loc))
109 else
110 out:write(format("[TRACE --- %s%s -- %s]\n",
111 startex, startloc, fmterr(otr, oex)))
112 end
113 elseif what == "stop" then
114 local info = traceinfo(tr)
115 local link, ltype = info.link, info.linktype
116 if ltype == "interpreter" then
117 out:write(format("[TRACE %3s %s%s -- fallback to interpreter]\n",
118 tr, startex, startloc))
119 elseif link == tr or link == 0 then
120 out:write(format("[TRACE %3s %s%s %s]\n",
121 tr, startex, startloc, ltype))
122 elseif ltype == "root" then
123 out:write(format("[TRACE %3s %s%s -> %d]\n",
124 tr, startex, startloc, link))
125 else
126 out:write(format("[TRACE %3s %s%s -> %d %s]\n",
127 tr, startex, startloc, link, ltype))
128 end
129 else
130 out:write(format("[TRACE %s]\n", what))
131 end
132 out:flush()
133 end
134end
135
136------------------------------------------------------------------------------
137
138-- Detach dump handlers.
139local function dumpoff()
140 if active then
141 active = false
142 jit.attach(dump_trace)
143 if out and out ~= stdout and out ~= stderr then out:close() end
144 out = nil
145 end
146end
147
148-- Open the output file and attach dump handlers.
149local function dumpon(outfile)
150 if active then dumpoff() end
151 if not outfile then outfile = os.getenv("LUAJIT_VERBOSEFILE") end
152 if outfile then
153 out = outfile == "-" and stdout or assert(io.open(outfile, "w"))
154 else
155 out = stderr
156 end
157 jit.attach(dump_trace, "trace")
158 active = true
159end
160
161-- Public module functions.
162module(...)
163
164on = dumpon
165off = dumpoff
166start = dumpon -- For -j command line option.
167