diff options
Diffstat (limited to 'src/jit/dis_arm.lua')
| -rw-r--r-- | src/jit/dis_arm.lua | 137 |
1 files changed, 68 insertions, 69 deletions
diff --git a/src/jit/dis_arm.lua b/src/jit/dis_arm.lua index 0adc799de..e2334ebbc 100644 --- a/src/jit/dis_arm.lua +++ b/src/jit/dis_arm.lua | |||
| @@ -15,8 +15,7 @@ local sub, byte, format = string.sub, string.byte, string.format | |||
| 15 | local match, gmatch = string.match, string.gmatch | 15 | local match, gmatch = string.match, string.gmatch |
| 16 | local concat = table.concat | 16 | local concat = table.concat |
| 17 | local bit = require("bit") | 17 | local bit = require("bit") |
| 18 | local band, bor, ror, tohex = bit.band, bit.bor, bit.ror, bit.tohex | 18 | local ror, tohex = bit.ror, bit.tohex |
| 19 | local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift | ||
| 20 | 19 | ||
| 21 | ------------------------------------------------------------------------------ | 20 | ------------------------------------------------------------------------------ |
| 22 | -- Opcode maps | 21 | -- Opcode maps |
| @@ -373,7 +372,7 @@ local map_datar = { | |||
| 373 | [16] = { shift = 7, mask = 1, [0] = map_misc, map_mulh, }, | 372 | [16] = { shift = 7, mask = 1, [0] = map_misc, map_mulh, }, |
| 374 | _ = { | 373 | _ = { |
| 375 | shift = 0, mask = 0xffffffff, | 374 | shift = 0, mask = 0xffffffff, |
| 376 | [bor(0xe1a00000)] = "nop", | 375 | [0xe1a00000|0] = "nop", |
| 377 | _ = map_data, | 376 | _ = map_data, |
| 378 | } | 377 | } |
| 379 | }, | 378 | }, |
| @@ -427,7 +426,7 @@ local function putop(ctx, text, operands) | |||
| 427 | local sym = ctx.symtab[ctx.rel] | 426 | local sym = ctx.symtab[ctx.rel] |
| 428 | if sym then | 427 | if sym then |
| 429 | extra = "\t->"..sym | 428 | extra = "\t->"..sym |
| 430 | elseif band(ctx.op, 0x0e000000) ~= 0x0a000000 then | 429 | elseif ctx.op & 0x0e000000 != 0x0a000000 then |
| 431 | extra = "\t; 0x"..tohex(ctx.rel) | 430 | extra = "\t; 0x"..tohex(ctx.rel) |
| 432 | end | 431 | end |
| 433 | end | 432 | end |
| @@ -448,47 +447,47 @@ end | |||
| 448 | 447 | ||
| 449 | -- Format operand 2 of load/store opcodes. | 448 | -- Format operand 2 of load/store opcodes. |
| 450 | local function fmtload(ctx, op, pos) | 449 | local function fmtload(ctx, op, pos) |
| 451 | local base = map_gpr[band(rshift(op, 16), 15)] | 450 | local base = map_gpr[(op >> 16) & 15] |
| 452 | local x, ofs | 451 | local x, ofs |
| 453 | local ext = (band(op, 0x04000000) == 0) | 452 | local ext = (op & 0x04000000 == 0) |
| 454 | if not ext and band(op, 0x02000000) == 0 then | 453 | if not ext and op & 0x02000000 == 0 then |
| 455 | ofs = band(op, 4095) | 454 | ofs = op & 4095 |
| 456 | if band(op, 0x00800000) == 0 then ofs = -ofs end | 455 | if op & 0x00800000 == 0 then ofs = -ofs end |
| 457 | if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end | 456 | if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end |
| 458 | ofs = "#"..ofs | 457 | ofs = "#"..ofs |
| 459 | elseif ext and band(op, 0x00400000) ~= 0 then | 458 | elseif ext and op & 0x00400000 != 0 then |
| 460 | ofs = band(op, 15) + band(rshift(op, 4), 0xf0) | 459 | ofs = (op & 0x0f) | ((op >> 4) & 0xf0) |
| 461 | if band(op, 0x00800000) == 0 then ofs = -ofs end | 460 | if op & 0x00800000 == 0 then ofs = -ofs end |
| 462 | if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end | 461 | if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end |
| 463 | ofs = "#"..ofs | 462 | ofs = "#"..ofs |
| 464 | else | 463 | else |
| 465 | ofs = map_gpr[band(op, 15)] | 464 | ofs = map_gpr[op & 15] |
| 466 | if ext or band(op, 0xfe0) == 0 then | 465 | if ext or op & 0xfe0 == 0 then |
| 467 | elseif band(op, 0xfe0) == 0x60 then | 466 | elseif op & 0xfe0 == 0x60 then |
| 468 | ofs = format("%s, rrx", ofs) | 467 | ofs = format("%s, rrx", ofs) |
| 469 | else | 468 | else |
| 470 | local sh = band(rshift(op, 7), 31) | 469 | local sh = (op >> 7) & 31 |
| 471 | if sh == 0 then sh = 32 end | 470 | if sh == 0 then sh = 32 end |
| 472 | ofs = format("%s, %s #%d", ofs, map_shift[band(rshift(op, 5), 3)], sh) | 471 | ofs = format("%s, %s #%d", ofs, map_shift[(op >> 5) & 3], sh) |
| 473 | end | 472 | end |
| 474 | if band(op, 0x00800000) == 0 then ofs = "-"..ofs end | 473 | if op & 0x00800000 == 0 then ofs = "-"..ofs end |
| 475 | end | 474 | end |
| 476 | if ofs == "#0" then | 475 | if ofs == "#0" then |
| 477 | x = format("[%s]", base) | 476 | x = format("[%s]", base) |
| 478 | elseif band(op, 0x01000000) == 0 then | 477 | elseif op & 0x01000000 == 0 then |
| 479 | x = format("[%s], %s", base, ofs) | 478 | x = format("[%s], %s", base, ofs) |
| 480 | else | 479 | else |
| 481 | x = format("[%s, %s]", base, ofs) | 480 | x = format("[%s, %s]", base, ofs) |
| 482 | end | 481 | end |
| 483 | if band(op, 0x01200000) == 0x01200000 then x = x.."!" end | 482 | if op & 0x01200000 == 0x01200000 then x ..= "!" end |
| 484 | return x | 483 | return x |
| 485 | end | 484 | end |
| 486 | 485 | ||
| 487 | -- Format operand 2 of vector load/store opcodes. | 486 | -- Format operand 2 of vector load/store opcodes. |
| 488 | local function fmtvload(ctx, op, pos) | 487 | local function fmtvload(ctx, op, pos) |
| 489 | local base = map_gpr[band(rshift(op, 16), 15)] | 488 | local base = map_gpr[(op >> 16) & 15] |
| 490 | local ofs = band(op, 255)*4 | 489 | local ofs = (op & 255) << 2 |
| 491 | if band(op, 0x00800000) == 0 then ofs = -ofs end | 490 | if op & 0x00800000 == 0 then ofs = -ofs end |
| 492 | if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end | 491 | if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end |
| 493 | if ofs == 0 then | 492 | if ofs == 0 then |
| 494 | return format("[%s]", base) | 493 | return format("[%s]", base) |
| @@ -499,9 +498,9 @@ end | |||
| 499 | 498 | ||
| 500 | local function fmtvr(op, vr, sh0, sh1) | 499 | local function fmtvr(op, vr, sh0, sh1) |
| 501 | if vr == "s" then | 500 | if vr == "s" then |
| 502 | return format("s%d", 2*band(rshift(op, sh0), 15)+band(rshift(op, sh1), 1)) | 501 | return format("s%d", ((op >> sh0-1) & 0x1e) | ((op >> sh1) & 1)) |
| 503 | else | 502 | else |
| 504 | return format("d%d", band(rshift(op, sh0), 15)+band(rshift(op, sh1-4), 16)) | 503 | return format("d%d", ((op >> sh0) & 15) | ((op >> sh1-4) & 16)) |
| 505 | end | 504 | end |
| 506 | end | 505 | end |
| 507 | 506 | ||
| @@ -509,7 +508,7 @@ end | |||
| 509 | local function disass_ins(ctx) | 508 | local function disass_ins(ctx) |
| 510 | local pos = ctx.pos | 509 | local pos = ctx.pos |
| 511 | local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) | 510 | local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) |
| 512 | local op = bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0) | 511 | local op = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0 |
| 513 | local operands = {} | 512 | local operands = {} |
| 514 | local suffix = "" | 513 | local suffix = "" |
| 515 | local last, name, pat | 514 | local last, name, pat |
| @@ -517,35 +516,35 @@ local function disass_ins(ctx) | |||
| 517 | ctx.op = op | 516 | ctx.op = op |
| 518 | ctx.rel = nil | 517 | ctx.rel = nil |
| 519 | 518 | ||
| 520 | local cond = rshift(op, 28) | 519 | local cond = op >> 28 |
| 521 | local opat | 520 | local opat |
| 522 | if cond == 15 then | 521 | if cond == 15 then |
| 523 | opat = map_uncondins[band(rshift(op, 25), 7)] | 522 | opat = map_uncondins[(op >> 25) & 7] |
| 524 | else | 523 | else |
| 525 | if cond ~= 14 then suffix = map_cond[cond] end | 524 | if cond != 14 then suffix = map_cond[cond] end |
| 526 | opat = map_condins[band(rshift(op, 25), 7)] | 525 | opat = map_condins[(op >> 25) & 7] |
| 527 | end | 526 | end |
| 528 | while type(opat) ~= "string" do | 527 | while type(opat) != "string" do |
| 529 | if not opat then return unknown(ctx) end | 528 | if not opat then return unknown(ctx) end |
| 530 | opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ | 529 | opat = opat[(op >> opat.shift) & opat.mask] or opat._ |
| 531 | end | 530 | end |
| 532 | name, pat = match(opat, "^([a-z0-9]*)(.*)") | 531 | name, pat = match(opat, "^([a-z0-9]*)(.*)") |
| 533 | if sub(pat, 1, 1) == "." then | 532 | if sub(pat, 1, 1) == "." then |
| 534 | local s2, p2 = match(pat, "^([a-z0-9.]*)(.*)") | 533 | local s2, p2 = match(pat, "^([a-z0-9.]*)(.*)") |
| 535 | suffix = suffix..s2 | 534 | suffix ..= s2 |
| 536 | pat = p2 | 535 | pat = p2 |
| 537 | end | 536 | end |
| 538 | 537 | ||
| 539 | for p in gmatch(pat, ".") do | 538 | for p in gmatch(pat, ".") do |
| 540 | local x = nil | 539 | local x = nil |
| 541 | if p == "D" then | 540 | if p == "D" then |
| 542 | x = map_gpr[band(rshift(op, 12), 15)] | 541 | x = map_gpr[(op >> 12) & 15] |
| 543 | elseif p == "N" then | 542 | elseif p == "N" then |
| 544 | x = map_gpr[band(rshift(op, 16), 15)] | 543 | x = map_gpr[(op >> 16) & 15] |
| 545 | elseif p == "S" then | 544 | elseif p == "S" then |
| 546 | x = map_gpr[band(rshift(op, 8), 15)] | 545 | x = map_gpr[(op >> 8) & 15] |
| 547 | elseif p == "M" then | 546 | elseif p == "M" then |
| 548 | x = map_gpr[band(op, 15)] | 547 | x = map_gpr[op & 15] |
| 549 | elseif p == "d" then | 548 | elseif p == "d" then |
| 550 | x = fmtvr(op, vr, 12, 22) | 549 | x = fmtvr(op, vr, 12, 22) |
| 551 | elseif p == "n" then | 550 | elseif p == "n" then |
| @@ -553,20 +552,20 @@ local function disass_ins(ctx) | |||
| 553 | elseif p == "m" then | 552 | elseif p == "m" then |
| 554 | x = fmtvr(op, vr, 0, 5) | 553 | x = fmtvr(op, vr, 0, 5) |
| 555 | elseif p == "P" then | 554 | elseif p == "P" then |
| 556 | if band(op, 0x02000000) ~= 0 then | 555 | if op & 0x02000000 != 0 then |
| 557 | x = ror(band(op, 255), 2*band(rshift(op, 8), 15)) | 556 | x = ror(op & 0xff, (op >> 7) & 0x1e) |
| 558 | else | 557 | else |
| 559 | x = map_gpr[band(op, 15)] | 558 | x = map_gpr[op & 15] |
| 560 | if band(op, 0xff0) ~= 0 then | 559 | if op & 0xff0 != 0 then |
| 561 | operands[#operands+1] = x | 560 | operands[#operands+1] = x |
| 562 | local s = map_shift[band(rshift(op, 5), 3)] | 561 | local s = map_shift[(op >> 5) & 3] |
| 563 | local r = nil | 562 | local r = nil |
| 564 | if band(op, 0xf90) == 0 then | 563 | if op & 0xf90 == 0 then |
| 565 | if s == "ror" then s = "rrx" else r = "#32" end | 564 | if s == "ror" then s = "rrx" else r = "#32" end |
| 566 | elseif band(op, 0x10) == 0 then | 565 | elseif op & 0x10 == 0 then |
| 567 | r = "#"..band(rshift(op, 7), 31) | 566 | r = "#"..((op >> 7) & 31) |
| 568 | else | 567 | else |
| 569 | r = map_gpr[band(rshift(op, 8), 15)] | 568 | r = map_gpr[(op >> 8) & 15] |
| 570 | end | 569 | end |
| 571 | if name == "mov" then name = s; x = r | 570 | if name == "mov" then name = s; x = r |
| 572 | elseif r then x = format("%s %s", s, r) | 571 | elseif r then x = format("%s %s", s, r) |
| @@ -578,8 +577,8 @@ local function disass_ins(ctx) | |||
| 578 | elseif p == "l" then | 577 | elseif p == "l" then |
| 579 | x = fmtvload(ctx, op, pos) | 578 | x = fmtvload(ctx, op, pos) |
| 580 | elseif p == "B" then | 579 | elseif p == "B" then |
| 581 | local addr = ctx.addr + pos + 8 + arshift(lshift(op, 8), 6) | 580 | local addr = ctx.addr + pos + 8 + ((op << 8) ~>> 6) |
| 582 | if cond == 15 then addr = addr + band(rshift(op, 23), 2) end | 581 | if cond == 15 then addr += (op >> 23) & 2 end |
| 583 | ctx.rel = addr | 582 | ctx.rel = addr |
| 584 | x = "0x"..tohex(addr) | 583 | x = "0x"..tohex(addr) |
| 585 | elseif p == "F" then | 584 | elseif p == "F" then |
| @@ -587,52 +586,52 @@ local function disass_ins(ctx) | |||
| 587 | elseif p == "G" then | 586 | elseif p == "G" then |
| 588 | vr = "d" | 587 | vr = "d" |
| 589 | elseif p == "." then | 588 | elseif p == "." then |
| 590 | suffix = suffix..(vr == "s" and ".f32" or ".f64") | 589 | suffix ..= vr == "s" ? ".f32" : ".f64" |
| 591 | elseif p == "R" then | 590 | elseif p == "R" then |
| 592 | if band(op, 0x00200000) ~= 0 and #operands == 1 then | 591 | if op & 0x00200000 != 0 and #operands == 1 then |
| 593 | operands[1] = operands[1].."!" | 592 | operands[1] = operands[1].."!" |
| 594 | end | 593 | end |
| 595 | local t = {} | 594 | local t = {} |
| 596 | for i=0,15 do | 595 | for i=0,15 do |
| 597 | if band(rshift(op, i), 1) == 1 then t[#t+1] = map_gpr[i] end | 596 | if (op >> i) & 1 == 1 then t[#t+1] = map_gpr[i] end |
| 598 | end | 597 | end |
| 599 | x = "{"..concat(t, ", ").."}" | 598 | x = "{"..concat(t, ", ").."}" |
| 600 | elseif p == "r" then | 599 | elseif p == "r" then |
| 601 | if band(op, 0x00200000) ~= 0 and #operands == 2 then | 600 | if op & 0x00200000 != 0 and #operands == 2 then |
| 602 | operands[1] = operands[1].."!" | 601 | operands[1] = operands[1].."!" |
| 603 | end | 602 | end |
| 604 | local s = tonumber(sub(last, 2)) | 603 | local s = tonumber(sub(last, 2)) |
| 605 | local n = band(op, 255) | 604 | local n = op & 0xff |
| 606 | if vr == "d" then n = rshift(n, 1) end | 605 | if vr == "d" then n >>= 1 end |
| 607 | operands[#operands] = format("{%s-%s%d}", last, vr, s+n-1) | 606 | operands[#operands] = format("{%s-%s%d}", last, vr, s+n-1) |
| 608 | elseif p == "W" then | 607 | elseif p == "W" then |
| 609 | x = band(op, 0x0fff) + band(rshift(op, 4), 0xf000) | 608 | x = (op & 0x0fff) | ((op >> 4) & 0xf000) |
| 610 | elseif p == "T" then | 609 | elseif p == "T" then |
| 611 | x = "#0x"..tohex(band(op, 0x00ffffff), 6) | 610 | x = "#0x"..tohex(op & 0x00ffffff, 6) |
| 612 | elseif p == "U" then | 611 | elseif p == "U" then |
| 613 | x = band(rshift(op, 7), 31) | 612 | x = (op >> 7) & 31 |
| 614 | if x == 0 then x = nil end | 613 | if x == 0 then x = nil end |
| 615 | elseif p == "u" then | 614 | elseif p == "u" then |
| 616 | x = band(rshift(op, 7), 31) | 615 | x = (op >> 7) & 31 |
| 617 | if band(op, 0x40) == 0 then | 616 | if op & 0x40 == 0 then |
| 618 | if x == 0 then x = nil else x = "lsl #"..x end | 617 | x = x == 0 ? nil : "lsl #"..x |
| 619 | else | 618 | else |
| 620 | if x == 0 then x = "asr #32" else x = "asr #"..x end | 619 | x = x == 0 ? "asr #32" : "asr #"..x |
| 621 | end | 620 | end |
| 622 | elseif p == "v" then | 621 | elseif p == "v" then |
| 623 | x = band(rshift(op, 7), 31) | 622 | x = (op >> 7) & 31 |
| 624 | elseif p == "w" then | 623 | elseif p == "w" then |
| 625 | x = band(rshift(op, 16), 31) | 624 | x = (op >> 16) & 31 |
| 626 | elseif p == "x" then | 625 | elseif p == "x" then |
| 627 | x = band(rshift(op, 16), 31) + 1 | 626 | x = ((op >> 16) & 31) + 1 |
| 628 | elseif p == "X" then | 627 | elseif p == "X" then |
| 629 | x = band(rshift(op, 16), 31) - last + 1 | 628 | x = ((op >> 16) & 31) - last + 1 |
| 630 | elseif p == "Y" then | 629 | elseif p == "Y" then |
| 631 | x = band(rshift(op, 12), 0xf0) + band(op, 0x0f) | 630 | x = ((op >> 12) & 0xf0) | (op & 0x0f) |
| 632 | elseif p == "K" then | 631 | elseif p == "K" then |
| 633 | x = "#0x"..tohex(band(rshift(op, 4), 0x0000fff0) + band(op, 15), 4) | 632 | x = "#0x"..tohex(((op >> 4) & 0xfff0) | (op & 0x000f), 4) |
| 634 | elseif p == "s" then | 633 | elseif p == "s" then |
| 635 | if band(op, 0x00100000) ~= 0 then suffix = "s"..suffix end | 634 | if op & 0x00100000 != 0 then suffix = "s"..suffix end |
| 636 | else | 635 | else |
| 637 | assert(false) | 636 | assert(false) |
| 638 | end | 637 | end |
| @@ -651,7 +650,7 @@ end | |||
| 651 | -- Disassemble a block of code. | 650 | -- Disassemble a block of code. |
| 652 | local function disass_block(ctx, ofs, len) | 651 | local function disass_block(ctx, ofs, len) |
| 653 | if not ofs then ofs = 0 end | 652 | if not ofs then ofs = 0 end |
| 654 | local stop = len and ofs+len or #ctx.code | 653 | local stop = len ? ofs+len : #ctx.code |
| 655 | ctx.pos = ofs | 654 | ctx.pos = ofs |
| 656 | ctx.rel = nil | 655 | ctx.rel = nil |
| 657 | while ctx.pos < stop do disass_ins(ctx) end | 656 | while ctx.pos < stop do disass_ins(ctx) end |
