diff options
Diffstat (limited to 'dynasm/dasm_arm.lua')
-rw-r--r-- | dynasm/dasm_arm.lua | 73 |
1 files changed, 32 insertions, 41 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 |