diff options
author | Mike Pall <mike> | 2012-07-29 12:17:13 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2012-07-29 12:17:13 +0200 |
commit | b98c1582c9129e7db59e4edaf7236671b36b523c (patch) | |
tree | 849a8d0fa91148b9fbe15d2a867f9ed9fbc72812 /src/jit | |
parent | 2d58872cb5ce72bb99ec5a8ed941cc3a7930a95c (diff) | |
download | luajit-b98c1582c9129e7db59e4edaf7236671b36b523c.tar.gz luajit-b98c1582c9129e7db59e4edaf7236671b36b523c.tar.bz2 luajit-b98c1582c9129e7db59e4edaf7236671b36b523c.zip |
ARM: Add VFP instructions to ARM disassembler.
Diffstat (limited to 'src/jit')
-rw-r--r-- | src/jit/dis_arm.lua | 163 |
1 files changed, 154 insertions, 9 deletions
diff --git a/src/jit/dis_arm.lua b/src/jit/dis_arm.lua index 0fcd1bed..ecca392f 100644 --- a/src/jit/dis_arm.lua +++ b/src/jit/dis_arm.lua | |||
@@ -23,24 +23,118 @@ local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift | |||
23 | ------------------------------------------------------------------------------ | 23 | ------------------------------------------------------------------------------ |
24 | 24 | ||
25 | local map_loadc = { | 25 | local map_loadc = { |
26 | shift = 9, mask = 7, | 26 | shift = 8, mask = 15, |
27 | [5] = { | 27 | [10] = { |
28 | shift = 0, mask = 0 -- NYI VFP load/store. | 28 | shift = 20, mask = 1, |
29 | [0] = { | ||
30 | shift = 23, mask = 3, | ||
31 | [0] = "vmovFmDN", "vstmFNdr", | ||
32 | _ = { | ||
33 | shift = 21, mask = 1, | ||
34 | [0] = "vstrFdl", | ||
35 | { shift = 16, mask = 15, [13] = "vpushFdr", _ = "vstmdbFNdr", } | ||
36 | }, | ||
37 | }, | ||
38 | { | ||
39 | shift = 23, mask = 3, | ||
40 | [0] = "vmovFDNm", | ||
41 | { shift = 16, mask = 15, [13] = "vpopFdr", _ = "vldmFNdr", }, | ||
42 | _ = { | ||
43 | shift = 21, mask = 1, | ||
44 | [0] = "vldrFdl", "vldmdbFNdr", | ||
45 | }, | ||
46 | }, | ||
47 | }, | ||
48 | [11] = { | ||
49 | shift = 20, mask = 1, | ||
50 | [0] = { | ||
51 | shift = 23, mask = 3, | ||
52 | [0] = "vmovGmDN", "vstmGNdr", | ||
53 | _ = { | ||
54 | shift = 21, mask = 1, | ||
55 | [0] = "vstrGdl", | ||
56 | { shift = 16, mask = 15, [13] = "vpushGdr", _ = "vstmdbGNdr", } | ||
57 | }, | ||
58 | }, | ||
59 | { | ||
60 | shift = 23, mask = 3, | ||
61 | [0] = "vmovGDNm", | ||
62 | { shift = 16, mask = 15, [13] = "vpopGdr", _ = "vldmGNdr", }, | ||
63 | _ = { | ||
64 | shift = 21, mask = 1, | ||
65 | [0] = "vldrGdl", "vldmdbGNdr", | ||
66 | }, | ||
67 | }, | ||
29 | }, | 68 | }, |
30 | _ = { | 69 | _ = { |
31 | shift = 0, mask = 0 -- NYI ldc, mcrr, mrrc. | 70 | shift = 0, mask = 0 -- NYI ldc, mcrr, mrrc. |
32 | }, | 71 | }, |
33 | } | 72 | } |
34 | 73 | ||
74 | local map_vfps = { | ||
75 | shift = 6, mask = 0x2c001, | ||
76 | [0] = "vmlaF.dnm", "vmlsF.dnm", | ||
77 | [0x04000] = "vnmlsF.dnm", [0x04001] = "vnmlaF.dnm", | ||
78 | [0x08000] = "vmulF.dnm", [0x08001] = "vnmulF.dnm", | ||
79 | [0x0c000] = "vaddF.dnm", [0x0c001] = "vsubF.dnm", | ||
80 | [0x20000] = "vdivF.dnm", | ||
81 | [0x24000] = "vfnmsF.dnm", [0x24001] = "vfnmaF.dnm", | ||
82 | [0x28000] = "vfmaF.dnm", [0x28001] = "vfmsF.dnm", | ||
83 | [0x2c000] = "vmovF.dY", | ||
84 | [0x2c001] = { | ||
85 | shift = 7, mask = 0x1e01, | ||
86 | [0] = "vmovF.dm", "vabsF.dm", | ||
87 | [0x0200] = "vnegF.dm", [0x0201] = "vsqrtF.dm", | ||
88 | [0x0800] = "vcmpF.dm", [0x0801] = "vcmpeF.dm", | ||
89 | [0x0a00] = "vcmpzF.d", [0x0a01] = "vcmpzeF.d", | ||
90 | [0x0e01] = "vcvtG.dF.m", | ||
91 | [0x1000] = "vcvt.f32.u32Fdm", [0x1001] = "vcvt.f32.s32Fdm", | ||
92 | [0x1800] = "vcvtr.u32F.dm", [0x1801] = "vcvt.u32F.dm", | ||
93 | [0x1a00] = "vcvtr.s32F.dm", [0x1a01] = "vcvt.s32F.dm", | ||
94 | }, | ||
95 | } | ||
96 | |||
97 | local map_vfpd = { | ||
98 | shift = 6, mask = 0x2c001, | ||
99 | [0] = "vmlaG.dnm", "vmlsG.dnm", | ||
100 | [0x04000] = "vnmlsG.dnm", [0x04001] = "vnmlaG.dnm", | ||
101 | [0x08000] = "vmulG.dnm", [0x08001] = "vnmulG.dnm", | ||
102 | [0x0c000] = "vaddG.dnm", [0x0c001] = "vsubG.dnm", | ||
103 | [0x20000] = "vdivG.dnm", | ||
104 | [0x24000] = "vfnmsG.dnm", [0x24001] = "vfnmaG.dnm", | ||
105 | [0x28000] = "vfmaG.dnm", [0x28001] = "vfmsG.dnm", | ||
106 | [0x2c000] = "vmovG.dY", | ||
107 | [0x2c001] = { | ||
108 | shift = 7, mask = 0x1e01, | ||
109 | [0] = "vmovG.dm", "vabsG.dm", | ||
110 | [0x0200] = "vnegG.dm", [0x0201] = "vsqrtG.dm", | ||
111 | [0x0800] = "vcmpG.dm", [0x0801] = "vcmpeG.dm", | ||
112 | [0x0a00] = "vcmpzG.d", [0x0a01] = "vcmpzeG.d", | ||
113 | [0x0e01] = "vcvtF.dG.m", | ||
114 | [0x1000] = "vcvt.f64.u32GdFm", [0x1001] = "vcvt.f64.s32GdFm", | ||
115 | [0x1800] = "vcvtr.u32FdG.m", [0x1801] = "vcvt.u32FdG.m", | ||
116 | [0x1a00] = "vcvtr.s32FdG.m", [0x1a01] = "vcvt.s32FdG.m", | ||
117 | }, | ||
118 | } | ||
119 | |||
35 | local map_datac = { | 120 | local map_datac = { |
36 | shift = 24, mask = 1, | 121 | shift = 24, mask = 1, |
37 | [0] = { | 122 | [0] = { |
38 | shift = 9, mask = 7, | 123 | shift = 4, mask = 1, |
39 | [5] = { | 124 | [0] = { |
40 | shift = 0, mask = 0 -- NYI VFP data. | 125 | shift = 8, mask = 15, |
126 | [10] = map_vfps, | ||
127 | [11] = map_vfpd, | ||
128 | -- NYI cdp, mcr, mrc. | ||
41 | }, | 129 | }, |
42 | _ = { | 130 | { |
43 | shift = 0, mask = 0 -- NYI cdp, mcr, mrc. | 131 | shift = 8, mask = 15, |
132 | [10] = { | ||
133 | shift = 20, mask = 15, | ||
134 | [0] = "vmovFnD", "vmovFDn", | ||
135 | [14] = "vmsrD", | ||
136 | [15] = { shift = 12, mask = 15, [15] = "vmrs", _ = "vmrsD", }, | ||
137 | }, | ||
44 | }, | 138 | }, |
45 | }, | 139 | }, |
46 | "svcT", | 140 | "svcT", |
@@ -390,6 +484,27 @@ local function fmtload(ctx, op, pos) | |||
390 | return x | 484 | return x |
391 | end | 485 | end |
392 | 486 | ||
487 | -- Format operand 2 of vector load/store opcodes. | ||
488 | local function fmtvload(ctx, op, pos) | ||
489 | local base = map_gpr[band(rshift(op, 16), 15)] | ||
490 | local ofs = band(op, 255)*4 | ||
491 | if band(op, 0x00800000) == 0 then ofs = -ofs end | ||
492 | if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end | ||
493 | if ofs == 0 then | ||
494 | return format("[%s]", base) | ||
495 | else | ||
496 | return format("[%s, #%d]", base, ofs) | ||
497 | end | ||
498 | end | ||
499 | |||
500 | local function fmtvr(op, vr, sh0, sh1) | ||
501 | if vr == "s" then | ||
502 | return format("s%d", 2*band(rshift(op, sh0), 15)+band(rshift(op, sh1), 1)) | ||
503 | else | ||
504 | return format("d%d", band(rshift(op, sh0), 15)+band(rshift(op, sh1-4), 16)) | ||
505 | end | ||
506 | end | ||
507 | |||
393 | -- Disassemble a single instruction. | 508 | -- Disassemble a single instruction. |
394 | local function disass_ins(ctx) | 509 | local function disass_ins(ctx) |
395 | local pos = ctx.pos | 510 | local pos = ctx.pos |
@@ -398,6 +513,7 @@ local function disass_ins(ctx) | |||
398 | local operands = {} | 513 | local operands = {} |
399 | local suffix = "" | 514 | local suffix = "" |
400 | local last, name, pat | 515 | local last, name, pat |
516 | local vr | ||
401 | ctx.op = op | 517 | ctx.op = op |
402 | ctx.rel = nil | 518 | ctx.rel = nil |
403 | 519 | ||
@@ -414,6 +530,11 @@ local function disass_ins(ctx) | |||
414 | opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ | 530 | opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ |
415 | end | 531 | end |
416 | name, pat = match(opat, "^([a-z0-9]*)(.*)") | 532 | name, pat = match(opat, "^([a-z0-9]*)(.*)") |
533 | if sub(pat, 1, 1) == "." then | ||
534 | local s2, p2 = match(pat, "^([a-z0-9.]*)(.*)") | ||
535 | suffix = suffix..s2 | ||
536 | pat = p2 | ||
537 | end | ||
417 | 538 | ||
418 | for p in gmatch(pat, ".") do | 539 | for p in gmatch(pat, ".") do |
419 | local x = nil | 540 | local x = nil |
@@ -425,6 +546,12 @@ local function disass_ins(ctx) | |||
425 | x = map_gpr[band(rshift(op, 8), 15)] | 546 | x = map_gpr[band(rshift(op, 8), 15)] |
426 | elseif p == "M" then | 547 | elseif p == "M" then |
427 | x = map_gpr[band(op, 15)] | 548 | x = map_gpr[band(op, 15)] |
549 | elseif p == "d" then | ||
550 | x = fmtvr(op, vr, 12, 22) | ||
551 | elseif p == "n" then | ||
552 | x = fmtvr(op, vr, 16, 7) | ||
553 | elseif p == "m" then | ||
554 | x = fmtvr(op, vr, 0, 5) | ||
428 | elseif p == "P" then | 555 | elseif p == "P" then |
429 | if band(op, 0x02000000) ~= 0 then | 556 | if band(op, 0x02000000) ~= 0 then |
430 | x = ror(band(op, 255), 2*band(rshift(op, 8), 15)) | 557 | x = ror(band(op, 255), 2*band(rshift(op, 8), 15)) |
@@ -447,12 +574,20 @@ local function disass_ins(ctx) | |||
447 | end | 574 | end |
448 | end | 575 | end |
449 | elseif p == "L" then | 576 | elseif p == "L" then |
450 | x = fmtload(ctx, op, pos, false) | 577 | x = fmtload(ctx, op, pos) |
578 | elseif p == "l" then | ||
579 | x = fmtvload(ctx, op, pos) | ||
451 | elseif p == "B" then | 580 | elseif p == "B" then |
452 | local addr = ctx.addr + pos + 8 + arshift(lshift(op, 8), 6) | 581 | local addr = ctx.addr + pos + 8 + arshift(lshift(op, 8), 6) |
453 | if cond == 15 then addr = addr + band(rshift(op, 23), 2) end | 582 | if cond == 15 then addr = addr + band(rshift(op, 23), 2) end |
454 | ctx.rel = addr | 583 | ctx.rel = addr |
455 | x = "0x"..tohex(addr) | 584 | x = "0x"..tohex(addr) |
585 | elseif p == "F" then | ||
586 | vr = "s" | ||
587 | elseif p == "G" then | ||
588 | vr = "d" | ||
589 | elseif p == "." then | ||
590 | suffix = suffix..(vr == "s" and ".f32" or ".f64") | ||
456 | elseif p == "R" then | 591 | elseif p == "R" then |
457 | if band(op, 0x00200000) ~= 0 and #operands == 1 then | 592 | if band(op, 0x00200000) ~= 0 and #operands == 1 then |
458 | operands[1] = operands[1].."!" | 593 | operands[1] = operands[1].."!" |
@@ -462,6 +597,14 @@ local function disass_ins(ctx) | |||
462 | if band(rshift(op, i), 1) == 1 then t[#t+1] = map_gpr[i] end | 597 | if band(rshift(op, i), 1) == 1 then t[#t+1] = map_gpr[i] end |
463 | end | 598 | end |
464 | x = "{"..concat(t, ", ").."}" | 599 | x = "{"..concat(t, ", ").."}" |
600 | elseif p == "r" then | ||
601 | if band(op, 0x00200000) ~= 0 and #operands == 2 then | ||
602 | operands[1] = operands[1].."!" | ||
603 | end | ||
604 | local s = tonumber(sub(last, 2)) | ||
605 | local n = band(op, 255) | ||
606 | if vr == "d" then n = rshift(n, 1) end | ||
607 | operands[#operands] = format("{%s-%s%d}", last, vr, s+n-1) | ||
465 | elseif p == "W" then | 608 | elseif p == "W" then |
466 | x = band(op, 0x0fff) + band(rshift(op, 4), 0xf000) | 609 | x = band(op, 0x0fff) + band(rshift(op, 4), 0xf000) |
467 | elseif p == "T" then | 610 | elseif p == "T" then |
@@ -484,6 +627,8 @@ local function disass_ins(ctx) | |||
484 | x = band(rshift(op, 16), 31) + 1 | 627 | x = band(rshift(op, 16), 31) + 1 |
485 | elseif p == "X" then | 628 | elseif p == "X" then |
486 | x = band(rshift(op, 16), 31) - last + 1 | 629 | x = band(rshift(op, 16), 31) - last + 1 |
630 | elseif p == "Y" then | ||
631 | x = band(rshift(op, 12), 0xf0) + band(op, 0x0f) | ||
487 | elseif p == "K" then | 632 | elseif p == "K" then |
488 | x = "#0x"..tohex(band(rshift(op, 4), 0x0000fff0) + band(op, 15), 4) | 633 | x = "#0x"..tohex(band(rshift(op, 4), 0x0000fff0) + band(op, 15), 4) |
489 | elseif p == "s" then | 634 | elseif p == "s" then |