aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/luajit-2.0/lib/dis_arm.lua
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/luajit-2.0/lib/dis_arm.lua')
-rw-r--r--libraries/luajit-2.0/lib/dis_arm.lua543
1 files changed, 0 insertions, 543 deletions
diff --git a/libraries/luajit-2.0/lib/dis_arm.lua b/libraries/luajit-2.0/lib/dis_arm.lua
deleted file mode 100644
index c2d1408..0000000
--- a/libraries/luajit-2.0/lib/dis_arm.lua
+++ /dev/null
@@ -1,543 +0,0 @@
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