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 | |
| 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')
| -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 |
