diff options
author | Mike Pall <mike> | 2012-07-08 16:25:38 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2012-07-08 16:27:18 +0200 |
commit | c00ffcb870cd51849ee2a0f1bf1862ac965026b7 (patch) | |
tree | e9af978c9883e709b1b5e5a845ce8ef5b6d0c490 /dynasm | |
parent | e3dec0438d50dbdf0184078d4e0233e399725787 (diff) | |
download | luajit-c00ffcb870cd51849ee2a0f1bf1862ac965026b7.tar.gz luajit-c00ffcb870cd51849ee2a0f1bf1862ac965026b7.tar.bz2 luajit-c00ffcb870cd51849ee2a0f1bf1862ac965026b7.zip |
Change DynASM bit operations to use Lua BitOp.
Diffstat (limited to 'dynasm')
-rw-r--r-- | dynasm/dasm_arm.lua | 73 | ||||
-rw-r--r-- | dynasm/dasm_mips.lua | 44 | ||||
-rw-r--r-- | dynasm/dasm_ppc.lua | 66 | ||||
-rw-r--r-- | dynasm/dasm_x86.lua | 52 |
4 files changed, 105 insertions, 130 deletions
diff --git a/dynasm/dasm_arm.lua b/dynasm/dasm_arm.lua index cc4fa177..4735f323 100644 --- a/dynasm/dasm_arm.lua +++ b/dynasm/dasm_arm.lua | |||
@@ -26,6 +26,9 @@ local _s = string | |||
26 | local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char | 26 | local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char |
27 | local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub | 27 | local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub |
28 | local concat, sort, insert = table.concat, table.sort, table.insert | 28 | local concat, sort, insert = table.concat, table.sort, table.insert |
29 | local bit = bit or require("bit") | ||
30 | local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift | ||
31 | local ror, tohex = bit.ror, bit.tohex | ||
29 | 32 | ||
30 | -- Inherited tables and callbacks. | 33 | -- Inherited tables and callbacks. |
31 | local g_opt, g_arch | 34 | local g_opt, g_arch |
@@ -60,11 +63,6 @@ local secpos = 1 | |||
60 | 63 | ||
61 | ------------------------------------------------------------------------------ | 64 | ------------------------------------------------------------------------------ |
62 | 65 | ||
63 | -- Return 8 digit hex number. | ||
64 | local function tohex(x) | ||
65 | return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua. | ||
66 | end | ||
67 | |||
68 | -- Dump action names and numbers. | 66 | -- Dump action names and numbers. |
69 | local function dumpactions(out) | 67 | local function dumpactions(out) |
70 | out:write("DynASM encoding engine action codes:\n") | 68 | out:write("DynASM encoding engine action codes:\n") |
@@ -483,8 +481,8 @@ local function parse_reglist(reglist) | |||
483 | if not reglist then werror("register list expected") end | 481 | if not reglist then werror("register list expected") end |
484 | local rr = 0 | 482 | local rr = 0 |
485 | for p in gmatch(reglist..",", "%s*([^,]*),") do | 483 | for p in gmatch(reglist..",", "%s*([^,]*),") do |
486 | local rbit = 2^parse_gpr(gsub(p, "%s+$", "")) | 484 | local rbit = shl(1, parse_gpr(gsub(p, "%s+$", ""))) |
487 | if ((rr - (rr % rbit)) / rbit) % 2 ~= 0 then | 485 | if band(rr, rbit) ~= 0 then |
488 | werror("duplicate register `"..p.."'") | 486 | werror("duplicate register `"..p.."'") |
489 | end | 487 | end |
490 | rr = rr + rbit | 488 | rr = rr + rbit |
@@ -497,16 +495,14 @@ local function parse_imm(imm, bits, shift, scale, signed) | |||
497 | if not imm then werror("expected immediate operand") end | 495 | if not imm then werror("expected immediate operand") end |
498 | local n = tonumber(imm) | 496 | local n = tonumber(imm) |
499 | if n then | 497 | if n then |
500 | if n % 2^scale == 0 then | 498 | local m = sar(n, scale) |
501 | n = n / 2^scale | 499 | if shl(m, scale) == n then |
502 | if signed then | 500 | if signed then |
503 | if n >= 0 then | 501 | local s = sar(m, bits-1) |
504 | if n < 2^(bits-1) then return n*2^shift end | 502 | if s == 0 then return shl(m, shift) |
505 | else | 503 | elseif s == -1 then return shl(m + shl(1, bits), shift) end |
506 | if n >= -(2^(bits-1))-1 then return (n+2^bits)*2^shift end | ||
507 | end | ||
508 | else | 504 | else |
509 | if n >= 0 and n <= 2^bits-1 then return n*2^shift end | 505 | if sar(m, bits) == 0 then return shl(m, shift) end |
510 | end | 506 | end |
511 | end | 507 | end |
512 | werror("out of range immediate `"..imm.."'") | 508 | werror("out of range immediate `"..imm.."'") |
@@ -519,11 +515,10 @@ end | |||
519 | local function parse_imm12(imm) | 515 | local function parse_imm12(imm) |
520 | local n = tonumber(imm) | 516 | local n = tonumber(imm) |
521 | if n then | 517 | if n then |
522 | local m = n | 518 | local m = band(n) |
523 | for i=0,-15,-1 do | 519 | for i=0,-15,-1 do |
524 | if m >= 0 and m <= 255 and n % 1 == 0 then return m + (i%16) * 256 end | 520 | if shr(m, 8) == 0 then return m + shl(band(i, 15), 8) end |
525 | local t = m % 4 | 521 | m = ror(m, 2) |
526 | m = (m - t) / 4 + t * 2^30 | ||
527 | end | 522 | end |
528 | werror("out of range immediate `"..imm.."'") | 523 | werror("out of range immediate `"..imm.."'") |
529 | else | 524 | else |
@@ -537,10 +532,7 @@ local function parse_imm16(imm) | |||
537 | if not imm then werror("expected immediate operand") end | 532 | if not imm then werror("expected immediate operand") end |
538 | local n = tonumber(imm) | 533 | local n = tonumber(imm) |
539 | if n then | 534 | if n then |
540 | if n >= 0 and n <= 65535 and n % 1 == 0 then | 535 | if shr(n, 16) == 0 then return band(n, 0x0fff) + shl(band(n, 0xf000), 4) end |
541 | local t = n % 4096 | ||
542 | return (n - t) * 16 + t | ||
543 | end | ||
544 | werror("out of range immediate `"..imm.."'") | 536 | werror("out of range immediate `"..imm.."'") |
545 | else | 537 | else |
546 | waction("IMM16", 32*16, imm) | 538 | waction("IMM16", 32*16, imm) |
@@ -555,7 +547,7 @@ local function parse_imm_load(imm, ext) | |||
555 | if n >= -255 and n <= 255 then | 547 | if n >= -255 and n <= 255 then |
556 | local up = 0x00800000 | 548 | local up = 0x00800000 |
557 | if n < 0 then n = -n; up = 0 end | 549 | if n < 0 then n = -n; up = 0 end |
558 | return (n-(n%16))*16+(n%16) + up | 550 | return shl(band(n, 0xf0), 4) + band(n, 0x0f) + up |
559 | end | 551 | end |
560 | else | 552 | else |
561 | if n >= -4095 and n <= 4095 then | 553 | if n >= -4095 and n <= 4095 then |
@@ -565,7 +557,7 @@ local function parse_imm_load(imm, ext) | |||
565 | end | 557 | end |
566 | werror("out of range immediate `"..imm.."'") | 558 | werror("out of range immediate `"..imm.."'") |
567 | else | 559 | else |
568 | waction(ext and "IMML8" or "IMML12", 32768 + 32*(ext and 8 or 12), imm) | 560 | waction(ext and "IMML8" or "IMML12", 32768 + shl(ext and 8 or 12, 5), imm) |
569 | return 0 | 561 | return 0 |
570 | end | 562 | end |
571 | end | 563 | end |
@@ -578,10 +570,10 @@ local function parse_shift(shift, gprok) | |||
578 | s = map_shift[s] | 570 | s = map_shift[s] |
579 | if not s then werror("expected shift operand") end | 571 | if not s then werror("expected shift operand") end |
580 | if sub(s2, 1, 1) == "#" then | 572 | if sub(s2, 1, 1) == "#" then |
581 | return parse_imm(s2, 5, 7, 0, false) + s * 32 | 573 | return parse_imm(s2, 5, 7, 0, false) + shl(s, 5) |
582 | else | 574 | else |
583 | if not gprok then werror("expected immediate shift operand") end | 575 | if not gprok then werror("expected immediate shift operand") end |
584 | return parse_gpr(s2) * 256 + s * 32 + 16 | 576 | return shl(parse_gpr(s2), 8) + shl(s, 5) + 16 |
585 | end | 577 | end |
586 | end | 578 | end |
587 | end | 579 | end |
@@ -617,12 +609,12 @@ local function parse_label(label, def) | |||
617 | end | 609 | end |
618 | 610 | ||
619 | local function parse_load(params, nparams, n, op) | 611 | local function parse_load(params, nparams, n, op) |
620 | local oplo = op % 256 | 612 | local oplo = band(op, 255) |
621 | local ext, ldrd = (oplo ~= 0), (oplo == 208) | 613 | local ext, ldrd = (oplo ~= 0), (oplo == 208) |
622 | local d | 614 | local d |
623 | if (ldrd or oplo == 240) then | 615 | if (ldrd or oplo == 240) then |
624 | d = ((op - (op % 4096)) / 4096) % 16 | 616 | d = band(shr(op, 12), 15) |
625 | if d % 2 ~= 0 then werror("odd destination register") end | 617 | if band(d, 1) ~= 0 then werror("odd destination register") end |
626 | end | 618 | end |
627 | local pn = params[n] | 619 | local pn = params[n] |
628 | local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$") | 620 | local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$") |
@@ -640,7 +632,7 @@ local function parse_load(params, nparams, n, op) | |||
640 | if tp then | 632 | if tp then |
641 | waction(ext and "IMML8" or "IMML12", 32768 + 32*(ext and 8 or 12), | 633 | waction(ext and "IMML8" or "IMML12", 32768 + 32*(ext and 8 or 12), |
642 | format(tp.ctypefmt, tailr)) | 634 | format(tp.ctypefmt, tailr)) |
643 | return op + d * 65536 + 0x01000000 + (ext and 0x00400000 or 0) | 635 | return op + shl(d, 16) + 0x01000000 + (ext and 0x00400000 or 0) |
644 | end | 636 | end |
645 | end | 637 | end |
646 | end | 638 | end |
@@ -650,7 +642,7 @@ local function parse_load(params, nparams, n, op) | |||
650 | if p2 then | 642 | if p2 then |
651 | if wb == "!" then werror("bad use of '!'") end | 643 | if wb == "!" then werror("bad use of '!'") end |
652 | local p3 = params[n+2] | 644 | local p3 = params[n+2] |
653 | op = op + parse_gpr(p1) * 65536 | 645 | op = op + shl(parse_gpr(p1), 16) |
654 | local imm = match(p2, "^#(.*)$") | 646 | local imm = match(p2, "^#(.*)$") |
655 | if imm then | 647 | if imm then |
656 | local m = parse_imm_load(imm, ext) | 648 | local m = parse_imm_load(imm, ext) |
@@ -664,7 +656,7 @@ local function parse_load(params, nparams, n, op) | |||
664 | end | 656 | end |
665 | else | 657 | else |
666 | local p1a, p2 = match(p1, "^([^,%s]*)%s*(.*)$") | 658 | local p1a, p2 = match(p1, "^([^,%s]*)%s*(.*)$") |
667 | op = op + parse_gpr(p1a) * 65536 + 0x01000000 | 659 | op = op + shl(parse_gpr(p1a), 16) + 0x01000000 |
668 | if p2 ~= "" then | 660 | if p2 ~= "" then |
669 | local imm = match(p2, "^,%s*#(.*)$") | 661 | local imm = match(p2, "^,%s*#(.*)$") |
670 | if imm then | 662 | if imm then |
@@ -704,11 +696,11 @@ map_op[".template__"] = function(params, template, nparams) | |||
704 | -- Process each character. | 696 | -- Process each character. |
705 | for p in gmatch(sub(template, 9), ".") do | 697 | for p in gmatch(sub(template, 9), ".") do |
706 | if p == "D" then | 698 | if p == "D" then |
707 | op = op + parse_gpr(params[n]) * 4096; n = n + 1 | 699 | op = op + shl(parse_gpr(params[n]), 12); n = n + 1 |
708 | elseif p == "N" then | 700 | elseif p == "N" then |
709 | op = op + parse_gpr(params[n]) * 65536; n = n + 1 | 701 | op = op + shl(parse_gpr(params[n]), 16); n = n + 1 |
710 | elseif p == "S" then | 702 | elseif p == "S" then |
711 | op = op + parse_gpr(params[n]) * 256; n = n + 1 | 703 | op = op + shl(parse_gpr(params[n]), 8); n = n + 1 |
712 | elseif p == "M" then | 704 | elseif p == "M" then |
713 | op = op + parse_gpr(params[n]); n = n + 1 | 705 | op = op + parse_gpr(params[n]); n = n + 1 |
714 | elseif p == "P" then | 706 | elseif p == "P" then |
@@ -738,7 +730,7 @@ map_op[".template__"] = function(params, template, nparams) | |||
738 | end | 730 | end |
739 | elseif p == "n" then | 731 | elseif p == "n" then |
740 | local r, wb = match(params[n], "^([^!]*)(!?)$") | 732 | local r, wb = match(params[n], "^([^!]*)(!?)$") |
741 | op = op + parse_gpr(r) * 65536 + (wb == "!" and 0x00200000 or 0) | 733 | op = op + shl(parse_gpr(r), 16) + (wb == "!" and 0x00200000 or 0) |
742 | n = n + 1 | 734 | n = n + 1 |
743 | elseif p == "R" then | 735 | elseif p == "R" then |
744 | op = op + parse_reglist(params[n]); n = n + 1 | 736 | op = op + parse_reglist(params[n]); n = n + 1 |
@@ -751,17 +743,16 @@ map_op[".template__"] = function(params, template, nparams) | |||
751 | if imm then | 743 | if imm then |
752 | op = op + parse_imm(params[n], 5, 7, 0, false); n = n + 1 | 744 | op = op + parse_imm(params[n], 5, 7, 0, false); n = n + 1 |
753 | else | 745 | else |
754 | op = op + parse_gpr(params[n]) * 256 + 16 | 746 | op = op + shl(parse_gpr(params[n]), 8) + 16 |
755 | end | 747 | end |
756 | elseif p == "X" then | 748 | elseif p == "X" then |
757 | op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1 | 749 | op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1 |
758 | elseif p == "K" then | 750 | elseif p == "K" then |
759 | local imm = tonumber(match(params[n], "^#(.*)$")); n = n + 1 | 751 | local imm = tonumber(match(params[n], "^#(.*)$")); n = n + 1 |
760 | if not imm or imm % 1 ~= 0 or imm < 0 or imm > 0xffff then | 752 | if not imm or shr(imm, 16) ~= 0 then |
761 | werror("bad immediate operand") | 753 | werror("bad immediate operand") |
762 | end | 754 | end |
763 | local t = imm % 16 | 755 | op = op + shl(band(imm, 0xfff0), 4) + band(imm, 0x000f) |
764 | op = op + (imm - t) * 16 + t | ||
765 | elseif p == "T" then | 756 | elseif p == "T" then |
766 | op = op + parse_imm(params[n], 24, 0, 0, false); n = n + 1 | 757 | op = op + parse_imm(params[n], 24, 0, 0, false); n = n + 1 |
767 | elseif p == "s" then | 758 | elseif p == "s" then |
diff --git a/dynasm/dasm_mips.lua b/dynasm/dasm_mips.lua index aa33f0cc..c387d292 100644 --- a/dynasm/dasm_mips.lua +++ b/dynasm/dasm_mips.lua | |||
@@ -26,6 +26,8 @@ local _s = string | |||
26 | local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char | 26 | local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char |
27 | local match, gmatch = _s.match, _s.gmatch | 27 | local match, gmatch = _s.match, _s.gmatch |
28 | local concat, sort = table.concat, table.sort | 28 | local concat, sort = table.concat, table.sort |
29 | local bit = bit or require("bit") | ||
30 | local band, shl, sar, tohex = bit.band, bit.lshift, bit.arshift, bit.tohex | ||
29 | 31 | ||
30 | -- Inherited tables and callbacks. | 32 | -- Inherited tables and callbacks. |
31 | local g_opt, g_arch | 33 | local g_opt, g_arch |
@@ -60,11 +62,6 @@ local secpos = 1 | |||
60 | 62 | ||
61 | ------------------------------------------------------------------------------ | 63 | ------------------------------------------------------------------------------ |
62 | 64 | ||
63 | -- Return 8 digit hex number. | ||
64 | local function tohex(x) | ||
65 | return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua. | ||
66 | end | ||
67 | |||
68 | -- Dump action names and numbers. | 65 | -- Dump action names and numbers. |
69 | local function dumpactions(out) | 66 | local function dumpactions(out) |
70 | out:write("DynASM encoding engine action codes:\n") | 67 | out:write("DynASM encoding engine action codes:\n") |
@@ -639,16 +636,14 @@ end | |||
639 | local function parse_imm(imm, bits, shift, scale, signed) | 636 | local function parse_imm(imm, bits, shift, scale, signed) |
640 | local n = tonumber(imm) | 637 | local n = tonumber(imm) |
641 | if n then | 638 | if n then |
642 | if n % 2^scale == 0 then | 639 | local m = sar(n, scale) |
643 | n = n / 2^scale | 640 | if shl(m, scale) == n then |
644 | if signed then | 641 | if signed then |
645 | if n >= 0 then | 642 | local s = sar(m, bits-1) |
646 | if n < 2^(bits-1) then return n*2^shift end | 643 | if s == 0 then return shl(m, shift) |
647 | else | 644 | elseif s == -1 then return shl(m + shl(1, bits), shift) end |
648 | if n >= -(2^(bits-1))-1 then return (n+2^bits)*2^shift end | ||
649 | end | ||
650 | else | 645 | else |
651 | if n >= 0 and n <= 2^bits-1 then return n*2^shift end | 646 | if sar(m, bits) == 0 then return shl(m, shift) end |
652 | end | 647 | end |
653 | end | 648 | end |
654 | werror("out of range immediate `"..imm.."'") | 649 | werror("out of range immediate `"..imm.."'") |
@@ -664,7 +659,7 @@ end | |||
664 | local function parse_disp(disp) | 659 | local function parse_disp(disp) |
665 | local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$") | 660 | local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$") |
666 | if imm then | 661 | if imm then |
667 | local r = parse_gpr(reg)*2^21 | 662 | local r = shl(parse_gpr(reg), 21) |
668 | local extname = match(imm, "^extern%s+(%S+)$") | 663 | local extname = match(imm, "^extern%s+(%S+)$") |
669 | if extname then | 664 | if extname then |
670 | waction("REL_EXT", map_extern[extname], nil, 1) | 665 | waction("REL_EXT", map_extern[extname], nil, 1) |
@@ -678,7 +673,7 @@ local function parse_disp(disp) | |||
678 | local r, tp = parse_gpr(reg) | 673 | local r, tp = parse_gpr(reg) |
679 | if tp then | 674 | if tp then |
680 | waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr)) | 675 | waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr)) |
681 | return r*2^21 | 676 | return shl(r, 21) |
682 | end | 677 | end |
683 | end | 678 | end |
684 | werror("bad displacement `"..disp.."'") | 679 | werror("bad displacement `"..disp.."'") |
@@ -689,7 +684,7 @@ local function parse_index(idx) | |||
689 | if rt then | 684 | if rt then |
690 | rt = parse_gpr(rt) | 685 | rt = parse_gpr(rt) |
691 | rs = parse_gpr(rs) | 686 | rs = parse_gpr(rs) |
692 | return rt*2^16 + rs*2^21 | 687 | return shl(rt, 16) + shl(rs, 21) |
693 | end | 688 | end |
694 | werror("bad index `"..idx.."'") | 689 | werror("bad index `"..idx.."'") |
695 | end | 690 | end |
@@ -740,19 +735,19 @@ map_op[".template__"] = function(params, template, nparams) | |||
740 | -- Process each character. | 735 | -- Process each character. |
741 | for p in gmatch(sub(template, 9), ".") do | 736 | for p in gmatch(sub(template, 9), ".") do |
742 | if p == "D" then | 737 | if p == "D" then |
743 | op = op + parse_gpr(params[n]) * 2^11; n = n + 1 | 738 | op = op + shl(parse_gpr(params[n]), 11); n = n + 1 |
744 | elseif p == "T" then | 739 | elseif p == "T" then |
745 | op = op + parse_gpr(params[n]) * 2^16; n = n + 1 | 740 | op = op + shl(parse_gpr(params[n]), 16); n = n + 1 |
746 | elseif p == "S" then | 741 | elseif p == "S" then |
747 | op = op + parse_gpr(params[n]) * 2^21; n = n + 1 | 742 | op = op + shl(parse_gpr(params[n]), 21); n = n + 1 |
748 | elseif p == "F" then | 743 | elseif p == "F" then |
749 | op = op + parse_fpr(params[n]) * 2^6; n = n + 1 | 744 | op = op + shl(parse_fpr(params[n]), 6); n = n + 1 |
750 | elseif p == "G" then | 745 | elseif p == "G" then |
751 | op = op + parse_fpr(params[n]) * 2^11; n = n + 1 | 746 | op = op + shl(parse_fpr(params[n]), 11); n = n + 1 |
752 | elseif p == "H" then | 747 | elseif p == "H" then |
753 | op = op + parse_fpr(params[n]) * 2^16; n = n + 1 | 748 | op = op + shl(parse_fpr(params[n]), 16); n = n + 1 |
754 | elseif p == "R" then | 749 | elseif p == "R" then |
755 | op = op + parse_fpr(params[n]) * 2^21; n = n + 1 | 750 | op = op + shl(parse_fpr(params[n]), 21); n = n + 1 |
756 | elseif p == "I" then | 751 | elseif p == "I" then |
757 | op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1 | 752 | op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1 |
758 | elseif p == "U" then | 753 | elseif p == "U" then |
@@ -783,8 +778,7 @@ map_op[".template__"] = function(params, template, nparams) | |||
783 | elseif p == "Z" then | 778 | elseif p == "Z" then |
784 | op = op + parse_imm(params[n], 10, 6, 0, false); n = n + 1 | 779 | op = op + parse_imm(params[n], 10, 6, 0, false); n = n + 1 |
785 | elseif p == "=" then | 780 | elseif p == "=" then |
786 | local d = ((op - op % 2^11) / 2^11) % 32 | 781 | op = op + shl(band(op, 0xf800), 5) -- Copy D to T for clz, clo. |
787 | op = op + d * 2^16 -- Copy D to T for clz, clo. | ||
788 | else | 782 | else |
789 | assert(false) | 783 | assert(false) |
790 | end | 784 | end |
diff --git a/dynasm/dasm_ppc.lua b/dynasm/dasm_ppc.lua index 7d64d81c..020ef0d9 100644 --- a/dynasm/dasm_ppc.lua +++ b/dynasm/dasm_ppc.lua | |||
@@ -26,6 +26,9 @@ local _s = string | |||
26 | local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char | 26 | local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char |
27 | local match, gmatch = _s.match, _s.gmatch | 27 | local match, gmatch = _s.match, _s.gmatch |
28 | local concat, sort = table.concat, table.sort | 28 | local concat, sort = table.concat, table.sort |
29 | local bit = bit or require("bit") | ||
30 | local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift | ||
31 | local tohex = bit.tohex | ||
29 | 32 | ||
30 | -- Inherited tables and callbacks. | 33 | -- Inherited tables and callbacks. |
31 | local g_opt, g_arch | 34 | local g_opt, g_arch |
@@ -60,11 +63,6 @@ local secpos = 1 | |||
60 | 63 | ||
61 | ------------------------------------------------------------------------------ | 64 | ------------------------------------------------------------------------------ |
62 | 65 | ||
63 | -- Return 8 digit hex number. | ||
64 | local function tohex(x) | ||
65 | return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua. | ||
66 | end | ||
67 | |||
68 | -- Dump action names and numbers. | 66 | -- Dump action names and numbers. |
69 | local function dumpactions(out) | 67 | local function dumpactions(out) |
70 | out:write("DynASM encoding engine action codes:\n") | 68 | out:write("DynASM encoding engine action codes:\n") |
@@ -837,7 +835,7 @@ end | |||
837 | -- Add more branch mnemonics. | 835 | -- Add more branch mnemonics. |
838 | for cond,c in pairs(map_cond) do | 836 | for cond,c in pairs(map_cond) do |
839 | local b1 = "b"..cond | 837 | local b1 = "b"..cond |
840 | local c1 = (c%4)*0x00010000 + (c < 4 and 0x01000000 or 0) | 838 | local c1 = shl(band(c, 3), 16) + (c < 4 and 0x01000000 or 0) |
841 | -- bX[l] | 839 | -- bX[l] |
842 | map_op[b1.."_1"] = tohex(0x40800000 + c1).."K" | 840 | map_op[b1.."_1"] = tohex(0x40800000 + c1).."K" |
843 | map_op[b1.."y_1"] = tohex(0x40a00000 + c1).."K" | 841 | map_op[b1.."y_1"] = tohex(0x40a00000 + c1).."K" |
@@ -905,16 +903,14 @@ end | |||
905 | local function parse_imm(imm, bits, shift, scale, signed) | 903 | local function parse_imm(imm, bits, shift, scale, signed) |
906 | local n = tonumber(imm) | 904 | local n = tonumber(imm) |
907 | if n then | 905 | if n then |
908 | if n % 2^scale == 0 then | 906 | local m = sar(n, scale) |
909 | n = n / 2^scale | 907 | if shl(m, scale) == n then |
910 | if signed then | 908 | if signed then |
911 | if n >= 0 then | 909 | local s = sar(m, bits-1) |
912 | if n < 2^(bits-1) then return n*2^shift end | 910 | if s == 0 then return shl(m, shift) |
913 | else | 911 | elseif s == -1 then return shl(m + shl(1, bits), shift) end |
914 | if n >= -(2^(bits-1))-1 then return (n+2^bits)*2^shift end | ||
915 | end | ||
916 | else | 912 | else |
917 | if n >= 0 and n <= 2^bits-1 then return n*2^shift end | 913 | if sar(m, bits) == 0 then return shl(m, shift) end |
918 | end | 914 | end |
919 | end | 915 | end |
920 | werror("out of range immediate `"..imm.."'") | 916 | werror("out of range immediate `"..imm.."'") |
@@ -930,10 +926,10 @@ end | |||
930 | local function parse_shiftmask(imm, isshift) | 926 | local function parse_shiftmask(imm, isshift) |
931 | local n = tonumber(imm) | 927 | local n = tonumber(imm) |
932 | if n then | 928 | if n then |
933 | if n % 1 == 0 and n >= 0 and n <= 63 then | 929 | if shr(n, 6) == 0 then |
934 | local lsb = imm % 32 | 930 | local lsb = band(imm, 31) |
935 | local msb = imm - lsb | 931 | local msb = imm - lsb |
936 | return isshift and (lsb*2048+msb/16) or (lsb*64+msb) | 932 | return isshift and (shl(lsb, 11)+shr(msb, 4)) or (shl(lsb, 6)+msb) |
937 | end | 933 | end |
938 | werror("out of range immediate `"..imm.."'") | 934 | werror("out of range immediate `"..imm.."'") |
939 | elseif match(imm, "^r([1-3]?[0-9])$") or | 935 | elseif match(imm, "^r([1-3]?[0-9])$") or |
@@ -949,7 +945,7 @@ local function parse_disp(disp) | |||
949 | if imm then | 945 | if imm then |
950 | local r = parse_gpr(reg) | 946 | local r = parse_gpr(reg) |
951 | if r == 0 then werror("cannot use r0 in displacement") end | 947 | if r == 0 then werror("cannot use r0 in displacement") end |
952 | return r*65536 + parse_imm(imm, 16, 0, 0, true) | 948 | return shl(r, 16) + parse_imm(imm, 16, 0, 0, true) |
953 | end | 949 | end |
954 | local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$") | 950 | local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$") |
955 | if reg and tailr ~= "" then | 951 | if reg and tailr ~= "" then |
@@ -957,7 +953,7 @@ local function parse_disp(disp) | |||
957 | if r == 0 then werror("cannot use r0 in displacement") end | 953 | if r == 0 then werror("cannot use r0 in displacement") end |
958 | if tp then | 954 | if tp then |
959 | waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr)) | 955 | waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr)) |
960 | return r*65536 | 956 | return shl(r, 16) |
961 | end | 957 | end |
962 | end | 958 | end |
963 | werror("bad displacement `"..disp.."'") | 959 | werror("bad displacement `"..disp.."'") |
@@ -968,7 +964,7 @@ local function parse_u5disp(disp, scale) | |||
968 | if imm then | 964 | if imm then |
969 | local r = parse_gpr(reg) | 965 | local r = parse_gpr(reg) |
970 | if r == 0 then werror("cannot use r0 in displacement") end | 966 | if r == 0 then werror("cannot use r0 in displacement") end |
971 | return r*65536 + parse_imm(imm, 5, 11, scale, false) | 967 | return shl(r, 16) + parse_imm(imm, 5, 11, scale, false) |
972 | end | 968 | end |
973 | local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$") | 969 | local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$") |
974 | if reg and tailr ~= "" then | 970 | if reg and tailr ~= "" then |
@@ -976,7 +972,7 @@ local function parse_u5disp(disp, scale) | |||
976 | if r == 0 then werror("cannot use r0 in displacement") end | 972 | if r == 0 then werror("cannot use r0 in displacement") end |
977 | if tp then | 973 | if tp then |
978 | waction("IMM", scale*1024+5*32+11, format(tp.ctypefmt, tailr)) | 974 | waction("IMM", scale*1024+5*32+11, format(tp.ctypefmt, tailr)) |
979 | return r*65536 | 975 | return shl(r, 16) |
980 | end | 976 | end |
981 | end | 977 | end |
982 | werror("bad displacement `"..disp.."'") | 978 | werror("bad displacement `"..disp.."'") |
@@ -1028,9 +1024,9 @@ map_op[".template__"] = function(params, template, nparams) | |||
1028 | -- Process each character. | 1024 | -- Process each character. |
1029 | for p in gmatch(sub(template, 9), ".") do | 1025 | for p in gmatch(sub(template, 9), ".") do |
1030 | if p == "R" then | 1026 | if p == "R" then |
1031 | rs = rs - 5; op = op + parse_gpr(params[n]) * 2^rs; n = n + 1 | 1027 | rs = rs - 5; op = op + shl(parse_gpr(params[n]), rs); n = n + 1 |
1032 | elseif p == "F" then | 1028 | elseif p == "F" then |
1033 | rs = rs - 5; op = op + parse_fpr(params[n]) * 2^rs; n = n + 1 | 1029 | rs = rs - 5; op = op + shl(parse_fpr(params[n]), rs); n = n + 1 |
1034 | elseif p == "A" then | 1030 | elseif p == "A" then |
1035 | rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, false); n = n + 1 | 1031 | rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, false); n = n + 1 |
1036 | elseif p == "S" then | 1032 | elseif p == "S" then |
@@ -1048,9 +1044,9 @@ map_op[".template__"] = function(params, template, nparams) | |||
1048 | elseif p == "8" then | 1044 | elseif p == "8" then |
1049 | op = op + parse_u5disp(params[n], 3); n = n + 1 | 1045 | op = op + parse_u5disp(params[n], 3); n = n + 1 |
1050 | elseif p == "C" then | 1046 | elseif p == "C" then |
1051 | rs = rs - 5; op = op + parse_cond(params[n]) * 2^rs; n = n + 1 | 1047 | rs = rs - 5; op = op + shl(parse_cond(params[n]), rs); n = n + 1 |
1052 | elseif p == "X" then | 1048 | elseif p == "X" then |
1053 | rs = rs - 5; op = op + parse_cr(params[n]) * 2^(rs+2); n = n + 1 | 1049 | rs = rs - 5; op = op + shl(parse_cr(params[n]), rs+2); n = n + 1 |
1054 | elseif p == "W" then | 1050 | elseif p == "W" then |
1055 | op = op + parse_cr(params[n]); n = n + 1 | 1051 | op = op + parse_cr(params[n]); n = n + 1 |
1056 | elseif p == "G" then | 1052 | elseif p == "G" then |
@@ -1065,22 +1061,16 @@ map_op[".template__"] = function(params, template, nparams) | |||
1065 | waction("REL_"..mode, n, s, 1) | 1061 | waction("REL_"..mode, n, s, 1) |
1066 | n = n + 1 | 1062 | n = n + 1 |
1067 | elseif p == "0" then | 1063 | elseif p == "0" then |
1068 | local mm = 2^rs | 1064 | if band(shr(op, rs), 31) == 0 then werror("cannot use r0") end |
1069 | local t = op % mm | ||
1070 | if ((op - t) / mm) % 32 == 0 then werror("cannot use r0") end | ||
1071 | elseif p == "=" or p == "%" then | 1065 | elseif p == "=" or p == "%" then |
1072 | local mm = 2^(rs + (p == "%" and 5 or 0)) | 1066 | local t = band(shr(op, p == "%" and rs+5 or rs), 31) |
1073 | local t = ((op - op % mm) / mm) % 32 | ||
1074 | rs = rs - 5 | 1067 | rs = rs - 5 |
1075 | op = op + t * 2^rs | 1068 | op = op + shl(t, rs) |
1076 | elseif p == "~" then | 1069 | elseif p == "~" then |
1077 | local mm = 2^rs | 1070 | local mm = shl(31, rs) |
1078 | local t1l = op % mm | 1071 | local lo = band(op, mm) |
1079 | local t1h = (op - t1l) / mm | 1072 | local hi = band(op, shl(mm, 5)) |
1080 | local t2l = t1h % 32 | 1073 | op = op - lo - hi + shl(lo, 5) + shr(hi, 5) |
1081 | local t2h = (t1h - t2l) / 32 | ||
1082 | local t3l = t2h % 32 | ||
1083 | op = ((t2h - t3l + t2l)*32 + t3l)*mm + t1l | ||
1084 | elseif p == "-" then | 1074 | elseif p == "-" then |
1085 | rs = rs - 5 | 1075 | rs = rs - 5 |
1086 | elseif p == "." then | 1076 | elseif p == "." then |
diff --git a/dynasm/dasm_x86.lua b/dynasm/dasm_x86.lua index 3bebb83c..a5f5c37d 100644 --- a/dynasm/dasm_x86.lua +++ b/dynasm/dasm_x86.lua | |||
@@ -28,6 +28,8 @@ local _s = string | |||
28 | local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char | 28 | local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char |
29 | local find, match, gmatch, gsub = _s.find, _s.match, _s.gmatch, _s.gsub | 29 | local find, match, gmatch, gsub = _s.find, _s.match, _s.gmatch, _s.gsub |
30 | local concat, sort = table.concat, table.sort | 30 | local concat, sort = table.concat, table.sort |
31 | local bit = bit or require("bit") | ||
32 | local band, shl, shr = bit.band, bit.lshift, bit.rshift | ||
31 | 33 | ||
32 | -- Inherited tables and callbacks. | 34 | -- Inherited tables and callbacks. |
33 | local g_opt, g_arch | 35 | local g_opt, g_arch |
@@ -426,10 +428,10 @@ end | |||
426 | -- Put unsigned word or arg. | 428 | -- Put unsigned word or arg. |
427 | local function wputwarg(n) | 429 | local function wputwarg(n) |
428 | if type(n) == "number" then | 430 | if type(n) == "number" then |
429 | if n < 0 or n > 65535 then | 431 | if shr(n, 16) ~= 0 then |
430 | werror("unsigned immediate word out of range") | 432 | werror("unsigned immediate word out of range") |
431 | end | 433 | end |
432 | local r = n%256; n = (n-r)/256; wputb(r); wputb(n); | 434 | wputb(band(n, 255)); wputb(shr(n, 8)); |
433 | else waction("IMM_W", n) end | 435 | else waction("IMM_W", n) end |
434 | end | 436 | end |
435 | 437 | ||
@@ -437,10 +439,10 @@ end | |||
437 | local function wputdarg(n) | 439 | local function wputdarg(n) |
438 | local tn = type(n) | 440 | local tn = type(n) |
439 | if tn == "number" then | 441 | if tn == "number" then |
440 | if n < 0 then n = n + 4294967296 end | 442 | wputb(band(n, 255)) |
441 | local r = n%256; n = (n-r)/256; wputb(r); | 443 | wputb(band(shr(n, 8), 255)) |
442 | r = n%256; n = (n-r)/256; wputb(r); | 444 | wputb(band(shr(n, 16), 255)) |
443 | r = n%256; n = (n-r)/256; wputb(r); wputb(n); | 445 | wputb(shr(n, 24)) |
444 | elseif tn == "table" then | 446 | elseif tn == "table" then |
445 | wputlabel("IMM_", n[1], 1) | 447 | wputlabel("IMM_", n[1], 1) |
446 | else | 448 | else |
@@ -464,24 +466,23 @@ local function wputop(sz, op, rex) | |||
464 | if sz == "w" then wputb(102) end | 466 | if sz == "w" then wputb(102) end |
465 | -- Needs >32 bit numbers, but only for crc32 eax, word [ebx] | 467 | -- Needs >32 bit numbers, but only for crc32 eax, word [ebx] |
466 | if op >= 4294967296 then r = op%4294967296 wputb((op-r)/4294967296) op = r end | 468 | if op >= 4294967296 then r = op%4294967296 wputb((op-r)/4294967296) op = r end |
467 | if op >= 16777216 then r = op % 16777216 wputb((op-r) / 16777216) op = r end | 469 | if op >= 16777216 then wputb(shr(op, 24)); op = band(op, 0xffffff) end |
468 | if op >= 65536 then | 470 | if op >= 65536 then |
469 | if rex ~= 0 then | 471 | if rex ~= 0 then |
470 | local opc3 = op - op % 256 | 472 | local opc3 = band(op, 0xffff00) |
471 | if opc3 == 0x0f3a00 or opc3 == 0x0f3800 then | 473 | if opc3 == 0x0f3a00 or opc3 == 0x0f3800 then |
472 | wputb(64 + rex % 16); rex = 0 | 474 | wputb(64 + band(rex, 15)); rex = 0 |
473 | end | 475 | end |
474 | end | 476 | end |
475 | r = op % 65536 wputb((op-r) / 65536) op = r | 477 | wputb(shr(op, 16)); op = band(op, 0xffff) |
476 | end | 478 | end |
477 | if op >= 256 then | 479 | if op >= 256 then |
478 | r = op % 256 | 480 | local b = shr(op, 8) |
479 | local b = (op-r) / 256 | 481 | if b == 15 and rex ~= 0 then wputb(64 + band(rex, 15)); rex = 0 end |
480 | if b == 15 and rex ~= 0 then wputb(64 + rex % 16); rex = 0 end | ||
481 | wputb(b) | 482 | wputb(b) |
482 | op = r | 483 | op = band(op, 255) |
483 | end | 484 | end |
484 | if rex ~= 0 then wputb(64 + rex % 16) end | 485 | if rex ~= 0 then wputb(64 + band(rex, 15)) end |
485 | if sz == "b" then op = op - 1 end | 486 | if sz == "b" then op = op - 1 end |
486 | wputb(op) | 487 | wputb(op) |
487 | end | 488 | end |
@@ -489,7 +490,7 @@ end | |||
489 | -- Put ModRM or SIB formatted byte. | 490 | -- Put ModRM or SIB formatted byte. |
490 | local function wputmodrm(m, s, rm, vs, vrm) | 491 | local function wputmodrm(m, s, rm, vs, vrm) |
491 | assert(m < 4 and s < 16 and rm < 16, "bad modrm operands") | 492 | assert(m < 4 and s < 16 and rm < 16, "bad modrm operands") |
492 | wputb(64*m + 8*(s%8) + (rm%8)) | 493 | wputb(shl(m, 6) + shl(band(s, 7), 3) + band(rm, 7)) |
493 | end | 494 | end |
494 | 495 | ||
495 | -- Put ModRM/SIB plus optional displacement. | 496 | -- Put ModRM/SIB plus optional displacement. |
@@ -548,7 +549,7 @@ local function wputmrmsib(t, imark, s, vsreg) | |||
548 | 549 | ||
549 | local m | 550 | local m |
550 | if tdisp == "number" then -- Check displacement size at assembly time. | 551 | if tdisp == "number" then -- Check displacement size at assembly time. |
551 | if disp == 0 and (reg%8) ~= 5 then -- [ebp] -> [ebp+0] (in SIB, too) | 552 | if disp == 0 and band(reg, 7) ~= 5 then -- [ebp] -> [ebp+0] (in SIB, too) |
552 | if not vreg then m = 0 end -- Force DISP to allow [Rd(5)] -> [ebp+0] | 553 | if not vreg then m = 0 end -- Force DISP to allow [Rd(5)] -> [ebp+0] |
553 | elseif disp >= -128 and disp <= 127 then m = 1 | 554 | elseif disp >= -128 and disp <= 127 then m = 1 |
554 | else m = 2 end | 555 | else m = 2 end |
@@ -557,7 +558,7 @@ local function wputmrmsib(t, imark, s, vsreg) | |||
557 | end | 558 | end |
558 | 559 | ||
559 | -- Index register present or esp as base register: need SIB encoding. | 560 | -- Index register present or esp as base register: need SIB encoding. |
560 | if xreg or (reg%8) == 4 then | 561 | if xreg or band(reg, 7) == 4 then |
561 | wputmodrm(m or 2, s, 4) -- ModRM. | 562 | wputmodrm(m or 2, s, 4) -- ModRM. |
562 | if m == nil or imark == "I" then waction("MARK") end | 563 | if m == nil or imark == "I" then waction("MARK") end |
563 | if vsreg then waction("VREG", vsreg); wputxb(2) end | 564 | if vsreg then waction("VREG", vsreg); wputxb(2) end |
@@ -1410,7 +1411,7 @@ local map_op = { | |||
1410 | -- Arithmetic ops. | 1411 | -- Arithmetic ops. |
1411 | for name,n in pairs{ add = 0, ["or"] = 1, adc = 2, sbb = 3, | 1412 | for name,n in pairs{ add = 0, ["or"] = 1, adc = 2, sbb = 3, |
1412 | ["and"] = 4, sub = 5, xor = 6, cmp = 7 } do | 1413 | ["and"] = 4, sub = 5, xor = 6, cmp = 7 } do |
1413 | local n8 = n * 8 | 1414 | local n8 = shl(n, 3) |
1414 | map_op[name.."_2"] = format( | 1415 | map_op[name.."_2"] = format( |
1415 | "mr:%02XRm|rm:%02XrM|mI1qdw:81%XmI|mS1qdw:83%XmS|Ri1qdwb:%02Xri|mi1qdwb:81%Xmi", | 1416 | "mr:%02XRm|rm:%02XrM|mI1qdw:81%XmI|mS1qdw:83%XmS|Ri1qdwb:%02Xri|mi1qdwb:81%Xmi", |
1416 | 1+n8, 3+n8, n, n, 5+n8, n) | 1417 | 1+n8, 3+n8, n, n, 5+n8, n) |
@@ -1432,7 +1433,7 @@ end | |||
1432 | -- FP arithmetic ops. | 1433 | -- FP arithmetic ops. |
1433 | for name,n in pairs{ add = 0, mul = 1, com = 2, comp = 3, | 1434 | for name,n in pairs{ add = 0, mul = 1, com = 2, comp = 3, |
1434 | sub = 4, subr = 5, div = 6, divr = 7 } do | 1435 | sub = 4, subr = 5, div = 6, divr = 7 } do |
1435 | local nc = 192 + n * 8 | 1436 | local nc = 0xc0 + shl(n, 3) |
1436 | local nr = nc + (n < 4 and 0 or (n % 2 == 0 and 8 or -8)) | 1437 | local nr = nc + (n < 4 and 0 or (n % 2 == 0 and 8 or -8)) |
1437 | local fn = "f"..name | 1438 | local fn = "f"..name |
1438 | map_op[fn.."_1"] = format("ff:D8%02Xr|xd:D8%Xm|xq:nDC%Xm", nc, n, n) | 1439 | map_op[fn.."_1"] = format("ff:D8%02Xr|xd:D8%Xm|xq:nDC%Xm", nc, n, n) |
@@ -1448,8 +1449,7 @@ end | |||
1448 | 1449 | ||
1449 | -- FP conditional moves. | 1450 | -- FP conditional moves. |
1450 | for cc,n in pairs{ b=0, e=1, be=2, u=3, nb=4, ne=5, nbe=6, nu=7 } do | 1451 | for cc,n in pairs{ b=0, e=1, be=2, u=3, nb=4, ne=5, nbe=6, nu=7 } do |
1451 | local n4 = n % 4 | 1452 | local nc = 0xdac0 + shl(band(n, 3), 3) + shl(band(n, 4), 6) |
1452 | local nc = 56000 + n4 * 8 + (n-n4) * 64 | ||
1453 | map_op["fcmov"..cc.."_1"] = format("ff:%04Xr", nc) -- P6+ | 1453 | map_op["fcmov"..cc.."_1"] = format("ff:%04Xr", nc) -- P6+ |
1454 | map_op["fcmov"..cc.."_2"] = format("Fff:%04XR", nc) -- P6+ | 1454 | map_op["fcmov"..cc.."_2"] = format("Fff:%04XR", nc) -- P6+ |
1455 | end | 1455 | end |
@@ -1499,10 +1499,10 @@ local function dopattern(pat, args, sz, op, needrex) | |||
1499 | local s | 1499 | local s |
1500 | if addin then | 1500 | if addin then |
1501 | s = addin.reg | 1501 | s = addin.reg |
1502 | opcode = opcode - (s%8) -- Undo regno opcode merge. | 1502 | opcode = opcode - band(s, 7) -- Undo regno opcode merge. |
1503 | else | 1503 | else |
1504 | s = opcode % 16 -- Undo last digit. | 1504 | s = band(opcode, 15) -- Undo last digit. |
1505 | opcode = (opcode - s) / 16 | 1505 | opcode = shr(opcode, 4) |
1506 | end | 1506 | end |
1507 | local nn = c == "m" and 1 or 2 | 1507 | local nn = c == "m" and 1 or 2 |
1508 | local t = args[nn] | 1508 | local t = args[nn] |
@@ -1699,7 +1699,7 @@ if x64 then | |||
1699 | werror("bad operand mode") | 1699 | werror("bad operand mode") |
1700 | end | 1700 | end |
1701 | op64 = params[2] | 1701 | op64 = params[2] |
1702 | opcode = 0xb8 + (a.reg%8) -- !x64: no VREG support. | 1702 | opcode = 0xb8 + band(a.reg, 7) -- !x64: no VREG support. |
1703 | rex = a.reg > 7 and 9 or 8 | 1703 | rex = a.reg > 7 and 9 or 8 |
1704 | end | 1704 | end |
1705 | end | 1705 | end |