aboutsummaryrefslogtreecommitdiff
path: root/src/jit/dis_x86.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/dis_x86.lua')
-rw-r--r--src/jit/dis_x86.lua152
1 files changed, 74 insertions, 78 deletions
diff --git a/src/jit/dis_x86.lua b/src/jit/dis_x86.lua
index 80bf721b1..b85061292 100644
--- a/src/jit/dis_x86.lua
+++ b/src/jit/dis_x86.lua
@@ -421,21 +421,21 @@ local function putop(ctx, text, operands)
421 local hmax = ctx.hexdump 421 local hmax = ctx.hexdump
422 if hmax > 0 then 422 if hmax > 0 then
423 for i=ctx.start,pos-1 do 423 for i=ctx.start,pos-1 do
424 hex = hex..format("%02X", byte(code, i, i)) 424 hex ..= format("%02X", byte(code, i))
425 end 425 end
426 if #hex > hmax then hex = sub(hex, 1, hmax)..". " 426 if #hex > hmax then hex = sub(hex, 1, hmax)..". "
427 else hex = hex..rep(" ", hmax-#hex+2) end 427 else hex ..= rep(" ", hmax-#hex+2) end
428 end 428 end
429 if operands then text = text.." "..operands end 429 if operands then text = text.." "..operands end
430 if ctx.o16 then text = "o16 "..text; ctx.o16 = false end 430 if ctx.o16 then text = "o16 "..text; ctx.o16 = false end
431 if ctx.a32 then text = "a32 "..text; ctx.a32 = false end 431 if ctx.a32 then text = "a32 "..text; ctx.a32 = false end
432 if ctx.rep then text = ctx.rep.." "..text; ctx.rep = false end 432 if ctx.rep then text = ctx.rep.." "..text; ctx.rep = false end
433 if ctx.rex then 433 if ctx.rex then
434 local t = (ctx.rexw and "w" or "")..(ctx.rexr and "r" or "").. 434 local t = (ctx.rexw ? "w" : "")..(ctx.rexr ? "r" : "")..
435 (ctx.rexx and "x" or "")..(ctx.rexb and "b" or "").. 435 (ctx.rexx ? "x" : "")..(ctx.rexb ? "b" : "")..
436 (ctx.vexl and "l" or "") 436 (ctx.vexl ? "l" : "")
437 if ctx.vexv and ctx.vexv ~= 0 then t = t.."v"..ctx.vexv end 437 if ctx.vexv and ctx.vexv != 0 then t = t.."v"..ctx.vexv end
438 if t ~= "" then text = ctx.rex.."."..t.." "..gsub(text, "^ ", "") 438 if t != "" then text = ctx.rex.."."..t.." "..gsub(text, "^ ", "")
439 elseif ctx.rex == "vex" then text = gsub("v"..text, "^v ", "") end 439 elseif ctx.rex == "vex" then text = gsub("v"..text, "^v ", "") end
440 ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false 440 ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false
441 ctx.rex = false; ctx.vexl = false; ctx.vexv = false 441 ctx.rex = false; ctx.vexl = false; ctx.vexv = false
@@ -483,7 +483,7 @@ local function getimm(ctx, pos, n)
483 if pos+n-1 > ctx.stop then return incomplete(ctx) end 483 if pos+n-1 > ctx.stop then return incomplete(ctx) end
484 local code = ctx.code 484 local code = ctx.code
485 if n == 1 then 485 if n == 1 then
486 local b1 = byte(code, pos, pos) 486 local b1 = byte(code, pos)
487 return b1 487 return b1
488 elseif n == 2 then 488 elseif n == 2 then
489 local b1, b2 = byte(code, pos, pos+1) 489 local b1, b2 = byte(code, pos, pos+1)
@@ -521,41 +521,41 @@ local function putpat(ctx, name, pat)
521 if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end 521 if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end
522 regs = map_regs[sz] 522 regs = map_regs[sz]
523 elseif p == "P" then 523 elseif p == "P" then
524 sz = ctx.o16 and "X" or "M"; ctx.o16 = false 524 sz = ctx.o16 ? "X" : "M"; ctx.o16 = false
525 if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end 525 if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end
526 regs = map_regs[sz] 526 regs = map_regs[sz]
527 elseif p == "H" then 527 elseif p == "H" then
528 name = name..(ctx.rexw and "d" or "s") 528 name ..= ctx.rexw ? "d" : "s"
529 ctx.rexw = false 529 ctx.rexw = false
530 elseif p == "S" then 530 elseif p == "S" then
531 name = name..lower(sz) 531 name ..= lower(sz)
532 elseif p == "s" then 532 elseif p == "s" then
533 local imm = getimm(ctx, pos, 1); if not imm then return end 533 local imm = getimm(ctx, pos, 1); if not imm then return end
534 x = imm <= 127 and format("+0x%02x", imm) 534 x = imm <= 127 ? format("+0x%02x", imm)
535 or format("-0x%02x", 256-imm) 535 : format("-0x%02x", 256-imm)
536 pos = pos+1 536 pos += 1
537 elseif p == "u" then 537 elseif p == "u" then
538 local imm = getimm(ctx, pos, 1); if not imm then return end 538 local imm = getimm(ctx, pos, 1); if not imm then return end
539 x = format("0x%02x", imm) 539 x = format("0x%02x", imm)
540 pos = pos+1 540 pos += 1
541 elseif p == "b" then 541 elseif p == "b" then
542 local imm = getimm(ctx, pos, 1); if not imm then return end 542 local imm = getimm(ctx, pos, 1); if not imm then return end
543 x = regs[imm/16+1] 543 x = regs[imm/16+1]
544 pos = pos+1 544 pos += 1
545 elseif p == "w" then 545 elseif p == "w" then
546 local imm = getimm(ctx, pos, 2); if not imm then return end 546 local imm = getimm(ctx, pos, 2); if not imm then return end
547 x = format("0x%x", imm) 547 x = format("0x%x", imm)
548 pos = pos+2 548 pos += 2
549 elseif p == "o" then -- [offset] 549 elseif p == "o" then -- [offset]
550 if ctx.x64 then 550 if ctx.x64 then
551 local imm1 = getimm(ctx, pos, 4); if not imm1 then return end 551 local imm1 = getimm(ctx, pos, 4); if not imm1 then return end
552 local imm2 = getimm(ctx, pos+4, 4); if not imm2 then return end 552 local imm2 = getimm(ctx, pos+4, 4); if not imm2 then return end
553 x = format("[0x%08x%08x]", imm2, imm1) 553 x = format("[0x%08x%08x]", imm2, imm1)
554 pos = pos+8 554 pos += 8
555 else 555 else
556 local imm = getimm(ctx, pos, 4); if not imm then return end 556 local imm = getimm(ctx, pos, 4); if not imm then return end
557 x = format("[0x%08x]", imm) 557 x = format("[0x%08x]", imm)
558 pos = pos+4 558 pos += 4
559 end 559 end
560 elseif p == "i" or p == "I" then 560 elseif p == "i" or p == "I" then
561 local n = map_sz2n[sz] 561 local n = map_sz2n[sz]
@@ -568,21 +568,21 @@ local function putpat(ctx, name, pat)
568 local imm = getimm(ctx, pos, n); if not imm then return end 568 local imm = getimm(ctx, pos, n); if not imm then return end
569 if sz == "Q" and (imm < 0 or imm > 0x7fffffff) then 569 if sz == "Q" and (imm < 0 or imm > 0x7fffffff) then
570 imm = (0xffffffff+1)-imm 570 imm = (0xffffffff+1)-imm
571 x = format(imm > 65535 and "-0x%08x" or "-0x%x", imm) 571 x = format(imm > 65535 ? "-0x%08x" : "-0x%x", imm)
572 else 572 else
573 x = format(imm > 65535 and "0x%08x" or "0x%x", imm) 573 x = format(imm > 65535 ? "0x%08x" : "0x%x", imm)
574 end 574 end
575 end 575 end
576 pos = pos+n 576 pos += n
577 elseif p == "j" then 577 elseif p == "j" then
578 local n = map_sz2n[sz] 578 local n = map_sz2n[sz]
579 if n == 8 then n = 4 end 579 if n == 8 then n = 4 end
580 local imm = getimm(ctx, pos, n); if not imm then return end 580 local imm = getimm(ctx, pos, n); if not imm then return end
581 if sz == "B" and imm > 127 then imm = imm-256 581 if sz == "B" and imm > 127 then imm -= 256
582 elseif imm > 2147483647 then imm = imm-4294967296 end 582 elseif imm > 2147483647 then imm -= 4294967296 end
583 pos = pos+n 583 pos += n
584 imm = imm + pos + ctx.addr 584 imm = imm + pos + ctx.addr
585 if imm > 4294967295 and not ctx.x64 then imm = imm-4294967296 end 585 if imm > 4294967295 and not ctx.x64 then imm -= 4294967296 end
586 ctx.imm = imm 586 ctx.imm = imm
587 if sz == "W" then 587 if sz == "W" then
588 x = format("word 0x%04x", imm%65536) 588 x = format("word 0x%04x", imm%65536)
@@ -593,8 +593,8 @@ local function putpat(ctx, name, pat)
593 x = "0x"..tohex(imm) 593 x = "0x"..tohex(imm)
594 end 594 end
595 elseif p == "R" then 595 elseif p == "R" then
596 local r = byte(code, pos-1, pos-1)%8 596 local r = byte(code, pos-1) & 7
597 if ctx.rexb then r = r + 8; ctx.rexb = false end 597 if ctx.rexb then r += 8; ctx.rexb = false end
598 x = regs[r+1] 598 x = regs[r+1]
599 elseif p == "a" then x = regs[1] 599 elseif p == "a" then x = regs[1]
600 elseif p == "c" then x = "cl" 600 elseif p == "c" then x = "cl"
@@ -605,25 +605,25 @@ local function putpat(ctx, name, pat)
605 mode = ctx.mrm 605 mode = ctx.mrm
606 if not mode then 606 if not mode then
607 if pos > stop then return incomplete(ctx) end 607 if pos > stop then return incomplete(ctx) end
608 mode = byte(code, pos, pos) 608 mode = byte(code, pos)
609 pos = pos+1 609 pos += 1
610 end 610 end
611 rm = mode%8; mode = (mode-rm)/8 611 rm = mode & 7; mode >>= 3
612 sp = mode%8; mode = (mode-sp)/8 612 sp = mode & 7; mode >>= 3
613 sdisp = "" 613 sdisp = ""
614 if mode < 3 then 614 if mode < 3 then
615 if rm == 4 then 615 if rm == 4 then
616 if pos > stop then return incomplete(ctx) end 616 if pos > stop then return incomplete(ctx) end
617 sc = byte(code, pos, pos) 617 sc = byte(code, pos)
618 pos = pos+1 618 pos += 1
619 rm = sc%8; sc = (sc-rm)/8 619 rm = sc & 7; sc >>= 3
620 rx = sc%8; sc = (sc-rx)/8 620 rx = sc & 7; sc >>= 3
621 if ctx.rexx then rx = rx + 8; ctx.rexx = false end 621 if ctx.rexx then rx += 8; ctx.rexx = false end
622 if rx == 4 then rx = nil end 622 if rx == 4 then rx = nil end
623 end 623 end
624 if mode > 0 or rm == 5 then 624 if mode > 0 or rm == 5 then
625 local dsz = mode 625 local dsz = mode
626 if dsz ~= 1 then dsz = 4 end 626 if dsz != 1 then dsz = 4 end
627 local disp = getimm(ctx, pos, dsz); if not disp then return end 627 local disp = getimm(ctx, pos, dsz); if not disp then return end
628 if mode == 0 then rm = nil end 628 if mode == 0 then rm = nil end
629 if rm or rx or (not sc and ctx.x64 and not ctx.a32) then 629 if rm or rx or (not sc and ctx.x64 and not ctx.a32) then
@@ -637,26 +637,26 @@ local function putpat(ctx, name, pat)
637 else 637 else
638 sdisp = format(ctx.x64 and not ctx.a32 and 638 sdisp = format(ctx.x64 and not ctx.a32 and
639 not (disp >= 0 and disp <= 0x7fffffff) 639 not (disp >= 0 and disp <= 0x7fffffff)
640 and "0xffffffff%08x" or "0x%08x", disp) 640 ? "0xffffffff%08x" : "0x%08x", disp)
641 end 641 end
642 pos = pos+dsz 642 pos += dsz
643 end 643 end
644 end 644 end
645 if rm and ctx.rexb then rm = rm + 8; ctx.rexb = false end 645 if rm and ctx.rexb then rm += 8; ctx.rexb = false end
646 if ctx.rexr then sp = sp + 8; ctx.rexr = false end 646 if ctx.rexr then sp += 8; ctx.rexr = false end
647 end 647 end
648 if p == "m" then 648 if p == "m" then
649 if mode == 3 then x = regs[rm+1] 649 if mode == 3 then x = regs[rm+1]
650 else 650 else
651 local aregs = ctx.a32 and map_regs.D or ctx.aregs 651 local aregs = ctx.a32 ? map_regs.D : ctx.aregs
652 local srm, srx = "", "" 652 local srm, srx = "", ""
653 if rm then srm = aregs[rm+1] 653 if rm then srm = aregs[rm+1]
654 elseif not sc and ctx.x64 and not ctx.a32 then srm = "rip" end 654 elseif not sc and ctx.x64 and not ctx.a32 then srm = "rip" end
655 ctx.a32 = false 655 ctx.a32 = false
656 if rx then 656 if rx then
657 if rm then srm = srm.."+" end 657 if rm then srm ..= "+" end
658 srx = aregs[rx+1] 658 srx = aregs[rx+1]
659 if sc > 0 then srx = srx.."*"..(2^sc) end 659 if sc > 0 then srx = srx.."*"..(1 << sc) end
660 end 660 end
661 x = format("[%s%s%s]", srm, srx, sdisp) 661 x = format("[%s%s%s]", srm, srx, sdisp)
662 end 662 end
@@ -686,7 +686,7 @@ local function putpat(ctx, name, pat)
686 error("bad pattern `"..pat.."'") 686 error("bad pattern `"..pat.."'")
687 end 687 end
688 end 688 end
689 if x then operands = operands and operands..", "..x or x end 689 if x then operands = operands ? operands..", "..x : x end
690 end 690 end
691 ctx.pos = pos 691 ctx.pos = pos
692 return putop(ctx, name, operands) 692 return putop(ctx, name, operands)
@@ -701,8 +701,8 @@ local function getmrm(ctx)
701 if not mrm then 701 if not mrm then
702 local pos = ctx.pos 702 local pos = ctx.pos
703 if pos > ctx.stop then return nil end 703 if pos > ctx.stop then return nil end
704 mrm = byte(ctx.code, pos, pos) 704 mrm = byte(ctx.code, pos)
705 ctx.pos = pos+1 705 ctx.pos = pos + 1
706 ctx.mrm = mrm 706 ctx.mrm = mrm
707 end 707 end
708 return mrm 708 return mrm
@@ -714,7 +714,7 @@ local function dispatch(ctx, opat, patgrp)
714 if match(opat, "%|") then -- MMX/SSE variants depending on prefix. 714 if match(opat, "%|") then -- MMX/SSE variants depending on prefix.
715 local p 715 local p
716 if ctx.rep then 716 if ctx.rep then
717 p = ctx.rep=="rep" and "%|([^%|]*)" or "%|[^%|]*%|[^%|]*%|([^%|]*)" 717 p = ctx.rep == "rep" ? "%|([^%|]*)" : "%|[^%|]*%|[^%|]*%|([^%|]*)"
718 ctx.rep = false 718 ctx.rep = false
719 elseif ctx.o16 then p = "%|[^%|]*%|([^%|]*)"; ctx.o16 = false 719 elseif ctx.o16 then p = "%|[^%|]*%|([^%|]*)"; ctx.o16 = false
720 else p = "^[^%|]*" end 720 else p = "^[^%|]*" end
@@ -726,7 +726,7 @@ local function dispatch(ctx, opat, patgrp)
726 end 726 end
727 if match(opat, "%$") then -- reg$mem variants. 727 if match(opat, "%$") then -- reg$mem variants.
728 local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end 728 local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end
729 opat = match(opat, mrm >= 192 and "^[^%$]*" or "%$(.*)") 729 opat = match(opat, mrm >= 192 ? "^[^%$]*" : "%$(.*)")
730 if opat == "" then return unknown(ctx) end 730 if opat == "" then return unknown(ctx) end
731 end 731 end
732 if opat == "" then return unknown(ctx) end 732 if opat == "" then return unknown(ctx) end
@@ -738,9 +738,8 @@ end
738-- Get a pattern from an opcode map and dispatch to handler. 738-- Get a pattern from an opcode map and dispatch to handler.
739local function dispatchmap(ctx, opcmap) 739local function dispatchmap(ctx, opcmap)
740 local pos = ctx.pos 740 local pos = ctx.pos
741 local opat = opcmap[byte(ctx.code, pos, pos)] 741 local opat = opcmap[byte(ctx.code, pos)]
742 pos = pos + 1 742 ctx.pos = pos + 1
743 ctx.pos = pos
744 return dispatch(ctx, opat) 743 return dispatch(ctx, opat)
745end 744end
746 745
@@ -760,7 +759,7 @@ map_act = {
760 759
761 -- Collect prefixes. 760 -- Collect prefixes.
762 [":"] = function(ctx, name, pat) 761 [":"] = function(ctx, name, pat)
763 ctx[pat == ":" and name or sub(pat, 2)] = name 762 ctx[pat == ":" ? name : sub(pat, 2)] = name
764 if ctx.pos - ctx.start > 5 then return unknown(ctx) end -- Limit #prefixes. 763 if ctx.pos - ctx.start > 5 then return unknown(ctx) end -- Limit #prefixes.
765 end, 764 end,
766 765
@@ -772,7 +771,7 @@ map_act = {
772 -- Use named subtable for opcode group. 771 -- Use named subtable for opcode group.
773 ["!"] = function(ctx, name, pat) 772 ["!"] = function(ctx, name, pat)
774 local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end 773 local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end
775 return dispatch(ctx, map_opcgroup[name][((mrm-(mrm%8))/8)%8+1], sub(pat, 2)) 774 return dispatch(ctx, map_opcgroup[name][((mrm >> 3) & 7)+1], sub(pat, 2))
776 end, 775 end,
777 776
778 -- o16,o32[,o64] variants. 777 -- o16,o32[,o64] variants.
@@ -825,9 +824,9 @@ map_act = {
825 -- Floating point opcode dispatch. 824 -- Floating point opcode dispatch.
826 fp = function(ctx, name, pat) 825 fp = function(ctx, name, pat)
827 local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end 826 local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end
828 local rm = mrm%8 827 local rm = mrm & 7
829 local idx = pat*8 + ((mrm-rm)/8)%8 828 local idx = ((byte(pat) - 0x30) << 3) | ((mrm >> 3) & 7)
830 if mrm >= 192 then idx = idx + 64 end 829 if mrm >= 192 then idx += 64 end
831 local opat = map_opcfp[idx] 830 local opat = map_opcfp[idx]
832 if type(opat) == "table" then opat = opat[rm+1] end 831 if type(opat) == "table" then opat = opat[rm+1] end
833 return dispatch(ctx, opat) 832 return dispatch(ctx, opat)
@@ -847,23 +846,21 @@ map_act = {
847 local pos = ctx.pos 846 local pos = ctx.pos
848 if ctx.mrm then 847 if ctx.mrm then
849 ctx.mrm = nil 848 ctx.mrm = nil
850 pos = pos-1 849 pos -= 1
851 end 850 end
852 local b = byte(ctx.code, pos, pos) 851 local b = byte(ctx.code, pos)
853 if not b then return incomplete(ctx) end 852 if not b then return incomplete(ctx) end
854 pos = pos+1 853 pos += 1
855 if b < 128 then ctx.rexr = true end 854 if b < 128 then ctx.rexr = true end
856 local m = 1 855 local m = 1
857 if pat == "3" then 856 if pat == "3" then
858 m = b%32; b = (b-m)/32 857 m = b & 0x1f
859 local nb = b%2; b = (b-nb)/2 858 if b & 0x20 == 0 then ctx.rexb = true end
860 if nb == 0 then ctx.rexb = true end 859 if b & 0x40 == 0 then ctx.rexx = true end
861 local nx = b%2 860 b = byte(ctx.code, pos)
862 if nx == 0 then ctx.rexx = true end
863 b = byte(ctx.code, pos, pos)
864 if not b then return incomplete(ctx) end 861 if not b then return incomplete(ctx) end
865 pos = pos+1 862 pos += 1
866 if b >= 128 then ctx.rexw = true end 863 if b & 0x80 then ctx.rexw = true end
867 end 864 end
868 ctx.pos = pos 865 ctx.pos = pos
869 local map 866 local map
@@ -871,24 +868,23 @@ map_act = {
871 elseif m == 2 then map = map_opc3["38"] 868 elseif m == 2 then map = map_opc3["38"]
872 elseif m == 3 then map = map_opc3["3a"] 869 elseif m == 3 then map = map_opc3["3a"]
873 else return unknown(ctx) end 870 else return unknown(ctx) end
874 local p = b%4; b = (b-p)/4 871 local p = b & 3
875 if p == 1 then ctx.o16 = "o16" 872 if p == 1 then ctx.o16 = "o16"
876 elseif p == 2 then ctx.rep = "rep" 873 elseif p == 2 then ctx.rep = "rep"
877 elseif p == 3 then ctx.rep = "repne" end 874 elseif p == 3 then ctx.rep = "repne" end
878 local l = b%2; b = (b-l)/2 875 if b & 4 != 0 then ctx.vexl = true end
879 if l ~= 0 then ctx.vexl = true end 876 ctx.vexv = ~(b >> 3) & 15
880 ctx.vexv = (-1-b)%16
881 return dispatchmap(ctx, map) 877 return dispatchmap(ctx, map)
882 end, 878 end,
883 879
884 -- Special case for nop with REX prefix. 880 -- Special case for nop with REX prefix.
885 nop = function(ctx, name, pat) 881 nop = function(ctx, name, pat)
886 return dispatch(ctx, ctx.rex and pat or "nop") 882 return dispatch(ctx, ctx.rex ? pat : "nop")
887 end, 883 end,
888 884
889 -- Special case for 0F 77. 885 -- Special case for 0F 77.
890 emms = function(ctx, name, pat) 886 emms = function(ctx, name, pat)
891 if ctx.rex ~= "vex" then 887 if ctx.rex != "vex" then
892 return putop(ctx, "emms") 888 return putop(ctx, "emms")
893 elseif ctx.vexl then 889 elseif ctx.vexl then
894 ctx.vexl = false 890 ctx.vexl = false
@@ -904,8 +900,8 @@ map_act = {
904-- Disassemble a block of code. 900-- Disassemble a block of code.
905local function disass_block(ctx, ofs, len) 901local function disass_block(ctx, ofs, len)
906 if not ofs then ofs = 0 end 902 if not ofs then ofs = 0 end
907 local stop = len and ofs+len or #ctx.code 903 local stop = len ? ofs+len : #ctx.code
908 ofs = ofs + 1 904 ofs += 1
909 ctx.start = ofs 905 ctx.start = ofs
910 ctx.pos = ofs 906 ctx.pos = ofs
911 ctx.stop = stop 907 ctx.stop = stop
@@ -913,7 +909,7 @@ local function disass_block(ctx, ofs, len)
913 ctx.mrm = false 909 ctx.mrm = false
914 clearprefixes(ctx) 910 clearprefixes(ctx)
915 while ctx.pos <= stop do dispatchmap(ctx, ctx.map1) end 911 while ctx.pos <= stop do dispatchmap(ctx, ctx.map1) end
916 if ctx.pos ~= ctx.start then incomplete(ctx) end 912 if ctx.pos != ctx.start then incomplete(ctx) end
917end 913end
918 914
919-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). 915-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).