aboutsummaryrefslogtreecommitdiff
path: root/dynasm/dasm_arm.lua
diff options
context:
space:
mode:
Diffstat (limited to 'dynasm/dasm_arm.lua')
-rw-r--r--dynasm/dasm_arm.lua73
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
26local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char 26local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
27local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub 27local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub
28local concat, sort, insert = table.concat, table.sort, table.insert 28local concat, sort, insert = table.concat, table.sort, table.insert
29local bit = bit or require("bit")
30local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
31local ror, tohex = bit.ror, bit.tohex
29 32
30-- Inherited tables and callbacks. 33-- Inherited tables and callbacks.
31local g_opt, g_arch 34local g_opt, g_arch
@@ -60,11 +63,6 @@ local secpos = 1
60 63
61------------------------------------------------------------------------------ 64------------------------------------------------------------------------------
62 65
63-- Return 8 digit hex number.
64local function tohex(x)
65 return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua.
66end
67
68-- Dump action names and numbers. 66-- Dump action names and numbers.
69local function dumpactions(out) 67local 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
519local function parse_imm12(imm) 515local 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
571end 563end
@@ -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
587end 579end
@@ -617,12 +609,12 @@ local function parse_label(label, def)
617end 609end
618 610
619local function parse_load(params, nparams, n, op) 611local 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