Browse Source

Change DynASM bit operations to use Lua BitOp.

Mike Pall 13 years ago
parent
commit
c00ffcb870
5 changed files with 106 additions and 131 deletions
  1. 32 41
      dynasm/dasm_arm.lua
  2. 19 25
      dynasm/dasm_mips.lua
  3. 28 38
      dynasm/dasm_ppc.lua
  4. 26 26
      dynasm/dasm_x86.lua
  5. 1 1
      src/Makefile

+ 32 - 41
dynasm/dasm_arm.lua

@@ -26,6 +26,9 @@ local _s = string
 local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
 local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
 local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub
 local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub
 local concat, sort, insert = table.concat, table.sort, table.insert
 local concat, sort, insert = table.concat, table.sort, table.insert
+local bit = bit or require("bit")
+local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
+local ror, tohex = bit.ror, bit.tohex
 
 
 -- Inherited tables and callbacks.
 -- Inherited tables and callbacks.
 local g_opt, g_arch
 local g_opt, g_arch
@@ -60,11 +63,6 @@ local secpos = 1
 
 
 ------------------------------------------------------------------------------
 ------------------------------------------------------------------------------
 
 
--- Return 8 digit hex number.
-local function tohex(x)
-  return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua.
-end
-
 -- Dump action names and numbers.
 -- Dump action names and numbers.
 local function dumpactions(out)
 local function dumpactions(out)
   out:write("DynASM encoding engine action codes:\n")
   out:write("DynASM encoding engine action codes:\n")
@@ -483,8 +481,8 @@ local function parse_reglist(reglist)
   if not reglist then werror("register list expected") end
   if not reglist then werror("register list expected") end
   local rr = 0
   local rr = 0
   for p in gmatch(reglist..",", "%s*([^,]*),") do
   for p in gmatch(reglist..",", "%s*([^,]*),") do
-    local rbit = 2^parse_gpr(gsub(p, "%s+$", ""))
-    if ((rr - (rr % rbit)) / rbit) % 2 ~= 0 then
+    local rbit = shl(1, parse_gpr(gsub(p, "%s+$", "")))
+    if band(rr, rbit) ~= 0 then
       werror("duplicate register `"..p.."'")
       werror("duplicate register `"..p.."'")
     end
     end
     rr = rr + rbit
     rr = rr + rbit
@@ -497,16 +495,14 @@ local function parse_imm(imm, bits, shift, scale, signed)
   if not imm then werror("expected immediate operand") end
   if not imm then werror("expected immediate operand") end
   local n = tonumber(imm)
   local n = tonumber(imm)
   if n then
   if n then
-    if n % 2^scale == 0 then
-      n = n / 2^scale
+    local m = sar(n, scale)
+    if shl(m, scale) == n then
       if signed then
       if signed then
-	if n >= 0 then
-	  if n < 2^(bits-1) then return n*2^shift end
-	else
-	  if n >= -(2^(bits-1))-1 then return (n+2^bits)*2^shift end
-	end
+	local s = sar(m, bits-1)
+	if s == 0 then return shl(m, shift)
+	elseif s == -1 then return shl(m + shl(1, bits), shift) end
       else
       else
-	if n >= 0 and n <= 2^bits-1 then return n*2^shift end
+	if sar(m, bits) == 0 then return shl(m, shift) end
       end
       end
     end
     end
     werror("out of range immediate `"..imm.."'")
     werror("out of range immediate `"..imm.."'")
@@ -519,11 +515,10 @@ end
 local function parse_imm12(imm)
 local function parse_imm12(imm)
   local n = tonumber(imm)
   local n = tonumber(imm)
   if n then
   if n then
-    local m = n
+    local m = band(n)
     for i=0,-15,-1 do
     for i=0,-15,-1 do
-      if m >= 0 and m <= 255 and n % 1 == 0 then return m + (i%16) * 256 end
-      local t = m % 4
-      m = (m - t) / 4 + t * 2^30
+      if shr(m, 8) == 0 then return m + shl(band(i, 15), 8) end
+      m = ror(m, 2)
     end
     end
     werror("out of range immediate `"..imm.."'")
     werror("out of range immediate `"..imm.."'")
   else
   else
@@ -537,10 +532,7 @@ local function parse_imm16(imm)
   if not imm then werror("expected immediate operand") end
   if not imm then werror("expected immediate operand") end
   local n = tonumber(imm)
   local n = tonumber(imm)
   if n then
   if n then
-    if n >= 0 and n <= 65535 and n % 1 == 0 then
-      local t = n % 4096
-      return (n - t) * 16 + t
-    end
+    if shr(n, 16) == 0 then return band(n, 0x0fff) + shl(band(n, 0xf000), 4) end
     werror("out of range immediate `"..imm.."'")
     werror("out of range immediate `"..imm.."'")
   else
   else
     waction("IMM16", 32*16, imm)
     waction("IMM16", 32*16, imm)
@@ -555,7 +547,7 @@ local function parse_imm_load(imm, ext)
       if n >= -255 and n <= 255 then
       if n >= -255 and n <= 255 then
 	local up = 0x00800000
 	local up = 0x00800000
 	if n < 0 then n = -n; up = 0 end
 	if n < 0 then n = -n; up = 0 end
-	return (n-(n%16))*16+(n%16) + up
+	return shl(band(n, 0xf0), 4) + band(n, 0x0f) + up
       end
       end
     else
     else
       if n >= -4095 and n <= 4095 then
       if n >= -4095 and n <= 4095 then
@@ -565,7 +557,7 @@ local function parse_imm_load(imm, ext)
     end
     end
     werror("out of range immediate `"..imm.."'")
     werror("out of range immediate `"..imm.."'")
   else
   else
-    waction(ext and "IMML8" or "IMML12", 32768 + 32*(ext and 8 or 12), imm)
+    waction(ext and "IMML8" or "IMML12", 32768 + shl(ext and 8 or 12, 5), imm)
     return 0
     return 0
   end
   end
 end
 end
@@ -578,10 +570,10 @@ local function parse_shift(shift, gprok)
     s = map_shift[s]
     s = map_shift[s]
     if not s then werror("expected shift operand") end
     if not s then werror("expected shift operand") end
     if sub(s2, 1, 1) == "#" then
     if sub(s2, 1, 1) == "#" then
-      return parse_imm(s2, 5, 7, 0, false) + s * 32
+      return parse_imm(s2, 5, 7, 0, false) + shl(s, 5)
     else
     else
       if not gprok then werror("expected immediate shift operand") end
       if not gprok then werror("expected immediate shift operand") end
-      return parse_gpr(s2) * 256 + s * 32 + 16
+      return shl(parse_gpr(s2), 8) + shl(s, 5) + 16
     end
     end
   end
   end
 end
 end
@@ -617,12 +609,12 @@ local function parse_label(label, def)
 end
 end
 
 
 local function parse_load(params, nparams, n, op)
 local function parse_load(params, nparams, n, op)
-  local oplo = op % 256
+  local oplo = band(op, 255)
   local ext, ldrd = (oplo ~= 0), (oplo == 208)
   local ext, ldrd = (oplo ~= 0), (oplo == 208)
   local d
   local d
   if (ldrd or oplo == 240) then
   if (ldrd or oplo == 240) then
-    d = ((op - (op % 4096)) / 4096) % 16
-    if d % 2 ~= 0 then werror("odd destination register") end
+    d = band(shr(op, 12), 15)
+    if band(d, 1) ~= 0 then werror("odd destination register") end
   end
   end
   local pn = params[n]
   local pn = params[n]
   local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
   local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
@@ -640,7 +632,7 @@ local function parse_load(params, nparams, n, op)
 	if tp then
 	if tp then
 	  waction(ext and "IMML8" or "IMML12", 32768 + 32*(ext and 8 or 12),
 	  waction(ext and "IMML8" or "IMML12", 32768 + 32*(ext and 8 or 12),
 		  format(tp.ctypefmt, tailr))
 		  format(tp.ctypefmt, tailr))
-	  return op + d * 65536 + 0x01000000 + (ext and 0x00400000 or 0)
+	  return op + shl(d, 16) + 0x01000000 + (ext and 0x00400000 or 0)
 	end
 	end
       end
       end
     end
     end
@@ -650,7 +642,7 @@ local function parse_load(params, nparams, n, op)
   if p2 then
   if p2 then
     if wb == "!" then werror("bad use of '!'") end
     if wb == "!" then werror("bad use of '!'") end
     local p3 = params[n+2]
     local p3 = params[n+2]
-    op = op + parse_gpr(p1) * 65536
+    op = op + shl(parse_gpr(p1), 16)
     local imm = match(p2, "^#(.*)$")
     local imm = match(p2, "^#(.*)$")
     if imm then
     if imm then
       local m = parse_imm_load(imm, ext)
       local m = parse_imm_load(imm, ext)
@@ -664,7 +656,7 @@ local function parse_load(params, nparams, n, op)
     end
     end
   else
   else
     local p1a, p2 = match(p1, "^([^,%s]*)%s*(.*)$")
     local p1a, p2 = match(p1, "^([^,%s]*)%s*(.*)$")
-    op = op + parse_gpr(p1a) * 65536 + 0x01000000
+    op = op + shl(parse_gpr(p1a), 16) + 0x01000000
     if p2 ~= "" then
     if p2 ~= "" then
       local imm = match(p2, "^,%s*#(.*)$")
       local imm = match(p2, "^,%s*#(.*)$")
       if imm then
       if imm then
@@ -704,11 +696,11 @@ map_op[".template__"] = function(params, template, nparams)
   -- Process each character.
   -- Process each character.
   for p in gmatch(sub(template, 9), ".") do
   for p in gmatch(sub(template, 9), ".") do
     if p == "D" then
     if p == "D" then
-      op = op + parse_gpr(params[n]) * 4096; n = n + 1
+      op = op + shl(parse_gpr(params[n]), 12); n = n + 1
     elseif p == "N" then
     elseif p == "N" then
-      op = op + parse_gpr(params[n]) * 65536; n = n + 1
+      op = op + shl(parse_gpr(params[n]), 16); n = n + 1
     elseif p == "S" then
     elseif p == "S" then
-      op = op + parse_gpr(params[n]) * 256; n = n + 1
+      op = op + shl(parse_gpr(params[n]), 8); n = n + 1
     elseif p == "M" then
     elseif p == "M" then
       op = op + parse_gpr(params[n]); n = n + 1
       op = op + parse_gpr(params[n]); n = n + 1
     elseif p == "P" then
     elseif p == "P" then
@@ -738,7 +730,7 @@ map_op[".template__"] = function(params, template, nparams)
       end
       end
     elseif p == "n" then
     elseif p == "n" then
       local r, wb = match(params[n], "^([^!]*)(!?)$")
       local r, wb = match(params[n], "^([^!]*)(!?)$")
-      op = op + parse_gpr(r) * 65536 + (wb == "!" and 0x00200000 or 0)
+      op = op + shl(parse_gpr(r), 16) + (wb == "!" and 0x00200000 or 0)
       n = n + 1
       n = n + 1
     elseif p == "R" then
     elseif p == "R" then
       op = op + parse_reglist(params[n]); n = n + 1
       op = op + parse_reglist(params[n]); n = n + 1
@@ -751,17 +743,16 @@ map_op[".template__"] = function(params, template, nparams)
       if imm then
       if imm then
 	op = op + parse_imm(params[n], 5, 7, 0, false); n = n + 1
 	op = op + parse_imm(params[n], 5, 7, 0, false); n = n + 1
       else
       else
-	op = op + parse_gpr(params[n]) * 256 + 16
+	op = op + shl(parse_gpr(params[n]), 8) + 16
       end
       end
     elseif p == "X" then
     elseif p == "X" then
       op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1
       op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1
     elseif p == "K" then
     elseif p == "K" then
       local imm = tonumber(match(params[n], "^#(.*)$")); n = n + 1
       local imm = tonumber(match(params[n], "^#(.*)$")); n = n + 1
-      if not imm or imm % 1 ~= 0 or imm < 0 or imm > 0xffff then
+      if not imm or shr(imm, 16) ~= 0 then
 	werror("bad immediate operand")
 	werror("bad immediate operand")
       end
       end
-      local t = imm % 16
-      op = op + (imm - t) * 16 + t
+      op = op + shl(band(imm, 0xfff0), 4) + band(imm, 0x000f)
     elseif p == "T" then
     elseif p == "T" then
       op = op + parse_imm(params[n], 24, 0, 0, false); n = n + 1
       op = op + parse_imm(params[n], 24, 0, 0, false); n = n + 1
     elseif p == "s" then
     elseif p == "s" then

+ 19 - 25
dynasm/dasm_mips.lua

@@ -26,6 +26,8 @@ local _s = string
 local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
 local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
 local match, gmatch = _s.match, _s.gmatch
 local match, gmatch = _s.match, _s.gmatch
 local concat, sort = table.concat, table.sort
 local concat, sort = table.concat, table.sort
+local bit = bit or require("bit")
+local band, shl, sar, tohex = bit.band, bit.lshift, bit.arshift, bit.tohex
 
 
 -- Inherited tables and callbacks.
 -- Inherited tables and callbacks.
 local g_opt, g_arch
 local g_opt, g_arch
@@ -60,11 +62,6 @@ local secpos = 1
 
 
 ------------------------------------------------------------------------------
 ------------------------------------------------------------------------------
 
 
--- Return 8 digit hex number.
-local function tohex(x)
-  return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua.
-end
-
 -- Dump action names and numbers.
 -- Dump action names and numbers.
 local function dumpactions(out)
 local function dumpactions(out)
   out:write("DynASM encoding engine action codes:\n")
   out:write("DynASM encoding engine action codes:\n")
@@ -639,16 +636,14 @@ end
 local function parse_imm(imm, bits, shift, scale, signed)
 local function parse_imm(imm, bits, shift, scale, signed)
   local n = tonumber(imm)
   local n = tonumber(imm)
   if n then
   if n then
-    if n % 2^scale == 0 then
-      n = n / 2^scale
+    local m = sar(n, scale)
+    if shl(m, scale) == n then
       if signed then
       if signed then
-	if n >= 0 then
-	  if n < 2^(bits-1) then return n*2^shift end
-	else
-	  if n >= -(2^(bits-1))-1 then return (n+2^bits)*2^shift end
-	end
+	local s = sar(m, bits-1)
+	if s == 0 then return shl(m, shift)
+	elseif s == -1 then return shl(m + shl(1, bits), shift) end
       else
       else
-	if n >= 0 and n <= 2^bits-1 then return n*2^shift end
+	if sar(m, bits) == 0 then return shl(m, shift) end
       end
       end
     end
     end
     werror("out of range immediate `"..imm.."'")
     werror("out of range immediate `"..imm.."'")
@@ -664,7 +659,7 @@ end
 local function parse_disp(disp)
 local function parse_disp(disp)
   local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$")
   local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$")
   if imm then
   if imm then
-    local r = parse_gpr(reg)*2^21
+    local r = shl(parse_gpr(reg), 21)
     local extname = match(imm, "^extern%s+(%S+)$")
     local extname = match(imm, "^extern%s+(%S+)$")
     if extname then
     if extname then
       waction("REL_EXT", map_extern[extname], nil, 1)
       waction("REL_EXT", map_extern[extname], nil, 1)
@@ -678,7 +673,7 @@ local function parse_disp(disp)
     local r, tp = parse_gpr(reg)
     local r, tp = parse_gpr(reg)
     if tp then
     if tp then
       waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr))
       waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr))
-      return r*2^21
+      return shl(r, 21)
     end
     end
   end
   end
   werror("bad displacement `"..disp.."'")
   werror("bad displacement `"..disp.."'")
@@ -689,7 +684,7 @@ local function parse_index(idx)
   if rt then
   if rt then
     rt = parse_gpr(rt)
     rt = parse_gpr(rt)
     rs = parse_gpr(rs)
     rs = parse_gpr(rs)
-    return rt*2^16 + rs*2^21
+    return shl(rt, 16) + shl(rs, 21)
   end
   end
   werror("bad index `"..idx.."'")
   werror("bad index `"..idx.."'")
 end
 end
@@ -740,19 +735,19 @@ map_op[".template__"] = function(params, template, nparams)
   -- Process each character.
   -- Process each character.
   for p in gmatch(sub(template, 9), ".") do
   for p in gmatch(sub(template, 9), ".") do
     if p == "D" then
     if p == "D" then
-      op = op + parse_gpr(params[n]) * 2^11; n = n + 1
+      op = op + shl(parse_gpr(params[n]), 11); n = n + 1
     elseif p == "T" then
     elseif p == "T" then
-      op = op + parse_gpr(params[n]) * 2^16; n = n + 1
+      op = op + shl(parse_gpr(params[n]), 16); n = n + 1
     elseif p == "S" then
     elseif p == "S" then
-      op = op + parse_gpr(params[n]) * 2^21; n = n + 1
+      op = op + shl(parse_gpr(params[n]), 21); n = n + 1
     elseif p == "F" then
     elseif p == "F" then
-      op = op + parse_fpr(params[n]) * 2^6; n = n + 1
+      op = op + shl(parse_fpr(params[n]), 6); n = n + 1
     elseif p == "G" then
     elseif p == "G" then
-      op = op + parse_fpr(params[n]) * 2^11; n = n + 1
+      op = op + shl(parse_fpr(params[n]), 11); n = n + 1
     elseif p == "H" then
     elseif p == "H" then
-      op = op + parse_fpr(params[n]) * 2^16; n = n + 1
+      op = op + shl(parse_fpr(params[n]), 16); n = n + 1
     elseif p == "R" then
     elseif p == "R" then
-      op = op + parse_fpr(params[n]) * 2^21; n = n + 1
+      op = op + shl(parse_fpr(params[n]), 21); n = n + 1
     elseif p == "I" then
     elseif p == "I" then
       op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1
       op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1
     elseif p == "U" then
     elseif p == "U" then
@@ -783,8 +778,7 @@ map_op[".template__"] = function(params, template, nparams)
     elseif p == "Z" then
     elseif p == "Z" then
       op = op + parse_imm(params[n], 10, 6, 0, false); n = n + 1
       op = op + parse_imm(params[n], 10, 6, 0, false); n = n + 1
     elseif p == "=" then
     elseif p == "=" then
-      local d = ((op - op % 2^11) / 2^11) % 32
-      op = op + d * 2^16 -- Copy D to T for clz, clo.
+      op = op + shl(band(op, 0xf800), 5) -- Copy D to T for clz, clo.
     else
     else
       assert(false)
       assert(false)
     end
     end

+ 28 - 38
dynasm/dasm_ppc.lua

@@ -26,6 +26,9 @@ local _s = string
 local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
 local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
 local match, gmatch = _s.match, _s.gmatch
 local match, gmatch = _s.match, _s.gmatch
 local concat, sort = table.concat, table.sort
 local concat, sort = table.concat, table.sort
+local bit = bit or require("bit")
+local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
+local tohex = bit.tohex
 
 
 -- Inherited tables and callbacks.
 -- Inherited tables and callbacks.
 local g_opt, g_arch
 local g_opt, g_arch
@@ -60,11 +63,6 @@ local secpos = 1
 
 
 ------------------------------------------------------------------------------
 ------------------------------------------------------------------------------
 
 
--- Return 8 digit hex number.
-local function tohex(x)
-  return sub(format("%08x", x), -8) -- Avoid 64 bit portability problem in Lua.
-end
-
 -- Dump action names and numbers.
 -- Dump action names and numbers.
 local function dumpactions(out)
 local function dumpactions(out)
   out:write("DynASM encoding engine action codes:\n")
   out:write("DynASM encoding engine action codes:\n")
@@ -837,7 +835,7 @@ end
 -- Add more branch mnemonics.
 -- Add more branch mnemonics.
 for cond,c in pairs(map_cond) do
 for cond,c in pairs(map_cond) do
   local b1 = "b"..cond
   local b1 = "b"..cond
-  local c1 = (c%4)*0x00010000 + (c < 4 and 0x01000000 or 0)
+  local c1 = shl(band(c, 3), 16) + (c < 4 and 0x01000000 or 0)
   -- bX[l]
   -- bX[l]
   map_op[b1.."_1"] = tohex(0x40800000 + c1).."K"
   map_op[b1.."_1"] = tohex(0x40800000 + c1).."K"
   map_op[b1.."y_1"] = tohex(0x40a00000 + c1).."K"
   map_op[b1.."y_1"] = tohex(0x40a00000 + c1).."K"
@@ -905,16 +903,14 @@ end
 local function parse_imm(imm, bits, shift, scale, signed)
 local function parse_imm(imm, bits, shift, scale, signed)
   local n = tonumber(imm)
   local n = tonumber(imm)
   if n then
   if n then
-    if n % 2^scale == 0 then
-      n = n / 2^scale
+    local m = sar(n, scale)
+    if shl(m, scale) == n then
       if signed then
       if signed then
-	if n >= 0 then
-	  if n < 2^(bits-1) then return n*2^shift end
-	else
-	  if n >= -(2^(bits-1))-1 then return (n+2^bits)*2^shift end
-	end
+	local s = sar(m, bits-1)
+	if s == 0 then return shl(m, shift)
+	elseif s == -1 then return shl(m + shl(1, bits), shift) end
       else
       else
-	if n >= 0 and n <= 2^bits-1 then return n*2^shift end
+	if sar(m, bits) == 0 then return shl(m, shift) end
       end
       end
     end
     end
     werror("out of range immediate `"..imm.."'")
     werror("out of range immediate `"..imm.."'")
@@ -930,10 +926,10 @@ end
 local function parse_shiftmask(imm, isshift)
 local function parse_shiftmask(imm, isshift)
   local n = tonumber(imm)
   local n = tonumber(imm)
   if n then
   if n then
-    if n % 1 == 0 and n >= 0 and n <= 63 then
-      local lsb = imm % 32
+    if shr(n, 6) == 0 then
+      local lsb = band(imm, 31)
       local msb = imm - lsb
       local msb = imm - lsb
-      return isshift and (lsb*2048+msb/16) or (lsb*64+msb)
+      return isshift and (shl(lsb, 11)+shr(msb, 4)) or (shl(lsb, 6)+msb)
     end
     end
     werror("out of range immediate `"..imm.."'")
     werror("out of range immediate `"..imm.."'")
   elseif match(imm, "^r([1-3]?[0-9])$") or
   elseif match(imm, "^r([1-3]?[0-9])$") or
@@ -949,7 +945,7 @@ local function parse_disp(disp)
   if imm then
   if imm then
     local r = parse_gpr(reg)
     local r = parse_gpr(reg)
     if r == 0 then werror("cannot use r0 in displacement") end
     if r == 0 then werror("cannot use r0 in displacement") end
-    return r*65536 + parse_imm(imm, 16, 0, 0, true)
+    return shl(r, 16) + parse_imm(imm, 16, 0, 0, true)
   end
   end
   local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$")
   local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$")
   if reg and tailr ~= "" then
   if reg and tailr ~= "" then
@@ -957,7 +953,7 @@ local function parse_disp(disp)
     if r == 0 then werror("cannot use r0 in displacement") end
     if r == 0 then werror("cannot use r0 in displacement") end
     if tp then
     if tp then
       waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr))
       waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr))
-      return r*65536
+      return shl(r, 16)
     end
     end
   end
   end
   werror("bad displacement `"..disp.."'")
   werror("bad displacement `"..disp.."'")
@@ -968,7 +964,7 @@ local function parse_u5disp(disp, scale)
   if imm then
   if imm then
     local r = parse_gpr(reg)
     local r = parse_gpr(reg)
     if r == 0 then werror("cannot use r0 in displacement") end
     if r == 0 then werror("cannot use r0 in displacement") end
-    return r*65536 + parse_imm(imm, 5, 11, scale, false)
+    return shl(r, 16) + parse_imm(imm, 5, 11, scale, false)
   end
   end
   local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$")
   local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$")
   if reg and tailr ~= "" then
   if reg and tailr ~= "" then
@@ -976,7 +972,7 @@ local function parse_u5disp(disp, scale)
     if r == 0 then werror("cannot use r0 in displacement") end
     if r == 0 then werror("cannot use r0 in displacement") end
     if tp then
     if tp then
       waction("IMM", scale*1024+5*32+11, format(tp.ctypefmt, tailr))
       waction("IMM", scale*1024+5*32+11, format(tp.ctypefmt, tailr))
-      return r*65536
+      return shl(r, 16)
     end
     end
   end
   end
   werror("bad displacement `"..disp.."'")
   werror("bad displacement `"..disp.."'")
@@ -1028,9 +1024,9 @@ map_op[".template__"] = function(params, template, nparams)
   -- Process each character.
   -- Process each character.
   for p in gmatch(sub(template, 9), ".") do
   for p in gmatch(sub(template, 9), ".") do
     if p == "R" then
     if p == "R" then
-      rs = rs - 5; op = op + parse_gpr(params[n]) * 2^rs; n = n + 1
+      rs = rs - 5; op = op + shl(parse_gpr(params[n]), rs); n = n + 1
     elseif p == "F" then
     elseif p == "F" then
-      rs = rs - 5; op = op + parse_fpr(params[n]) * 2^rs; n = n + 1
+      rs = rs - 5; op = op + shl(parse_fpr(params[n]), rs); n = n + 1
     elseif p == "A" then
     elseif p == "A" then
       rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, false); n = n + 1
       rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, false); n = n + 1
     elseif p == "S" then
     elseif p == "S" then
@@ -1048,9 +1044,9 @@ map_op[".template__"] = function(params, template, nparams)
     elseif p == "8" then
     elseif p == "8" then
       op = op + parse_u5disp(params[n], 3); n = n + 1
       op = op + parse_u5disp(params[n], 3); n = n + 1
     elseif p == "C" then
     elseif p == "C" then
-      rs = rs - 5; op = op + parse_cond(params[n]) * 2^rs; n = n + 1
+      rs = rs - 5; op = op + shl(parse_cond(params[n]), rs); n = n + 1
     elseif p == "X" then
     elseif p == "X" then
-      rs = rs - 5; op = op + parse_cr(params[n]) * 2^(rs+2); n = n + 1
+      rs = rs - 5; op = op + shl(parse_cr(params[n]), rs+2); n = n + 1
     elseif p == "W" then
     elseif p == "W" then
       op = op + parse_cr(params[n]); n = n + 1
       op = op + parse_cr(params[n]); n = n + 1
     elseif p == "G" then
     elseif p == "G" then
@@ -1065,22 +1061,16 @@ map_op[".template__"] = function(params, template, nparams)
       waction("REL_"..mode, n, s, 1)
       waction("REL_"..mode, n, s, 1)
       n = n + 1
       n = n + 1
     elseif p == "0" then
     elseif p == "0" then
-      local mm = 2^rs
-      local t = op % mm
-      if ((op - t) / mm) % 32 == 0 then werror("cannot use r0") end
+      if band(shr(op, rs), 31) == 0 then werror("cannot use r0") end
     elseif p == "=" or p == "%" then
     elseif p == "=" or p == "%" then
-      local mm = 2^(rs + (p == "%" and 5 or 0))
-      local t = ((op - op % mm) / mm) % 32
+      local t = band(shr(op, p == "%" and rs+5 or rs), 31)
       rs = rs - 5
       rs = rs - 5
-      op = op + t * 2^rs
+      op = op + shl(t, rs)
     elseif p == "~" then
     elseif p == "~" then
-      local mm = 2^rs
-      local t1l = op % mm
-      local t1h = (op - t1l) / mm
-      local t2l = t1h % 32
-      local t2h = (t1h - t2l) / 32
-      local t3l = t2h % 32
-      op = ((t2h - t3l + t2l)*32 + t3l)*mm + t1l
+      local mm = shl(31, rs)
+      local lo = band(op, mm)
+      local hi = band(op, shl(mm, 5))
+      op = op - lo - hi + shl(lo, 5) + shr(hi, 5)
     elseif p == "-" then
     elseif p == "-" then
       rs = rs - 5
       rs = rs - 5
     elseif p == "." then
     elseif p == "." then

+ 26 - 26
dynasm/dasm_x86.lua

@@ -28,6 +28,8 @@ local _s = string
 local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
 local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
 local find, match, gmatch, gsub = _s.find, _s.match, _s.gmatch, _s.gsub
 local find, match, gmatch, gsub = _s.find, _s.match, _s.gmatch, _s.gsub
 local concat, sort = table.concat, table.sort
 local concat, sort = table.concat, table.sort
+local bit = bit or require("bit")
+local band, shl, shr = bit.band, bit.lshift, bit.rshift
 
 
 -- Inherited tables and callbacks.
 -- Inherited tables and callbacks.
 local g_opt, g_arch
 local g_opt, g_arch
@@ -426,10 +428,10 @@ end
 -- Put unsigned word or arg.
 -- Put unsigned word or arg.
 local function wputwarg(n)
 local function wputwarg(n)
   if type(n) == "number" then
   if type(n) == "number" then
-    if n < 0 or n > 65535 then
+    if shr(n, 16) ~= 0 then
       werror("unsigned immediate word out of range")
       werror("unsigned immediate word out of range")
     end
     end
-    local r = n%256; n = (n-r)/256; wputb(r); wputb(n);
+    wputb(band(n, 255)); wputb(shr(n, 8));
   else waction("IMM_W", n) end
   else waction("IMM_W", n) end
 end
 end
 
 
@@ -437,10 +439,10 @@ end
 local function wputdarg(n)
 local function wputdarg(n)
   local tn = type(n)
   local tn = type(n)
   if tn == "number" then
   if tn == "number" then
-    if n < 0 then n = n + 4294967296 end
-    local r = n%256; n = (n-r)/256; wputb(r);
-    r = n%256; n = (n-r)/256; wputb(r);
-    r = n%256; n = (n-r)/256; wputb(r); wputb(n);
+    wputb(band(n, 255))
+    wputb(band(shr(n, 8), 255))
+    wputb(band(shr(n, 16), 255))
+    wputb(shr(n, 24))
   elseif tn == "table" then
   elseif tn == "table" then
     wputlabel("IMM_", n[1], 1)
     wputlabel("IMM_", n[1], 1)
   else
   else
@@ -464,24 +466,23 @@ local function wputop(sz, op, rex)
   if sz == "w" then wputb(102) end
   if sz == "w" then wputb(102) end
   -- Needs >32 bit numbers, but only for crc32 eax, word [ebx]
   -- Needs >32 bit numbers, but only for crc32 eax, word [ebx]
   if op >= 4294967296 then r = op%4294967296 wputb((op-r)/4294967296) op = r end
   if op >= 4294967296 then r = op%4294967296 wputb((op-r)/4294967296) op = r end
-  if op >= 16777216 then r = op % 16777216 wputb((op-r) / 16777216) op = r end
+  if op >= 16777216 then wputb(shr(op, 24)); op = band(op, 0xffffff) end
   if op >= 65536 then
   if op >= 65536 then
     if rex ~= 0 then
     if rex ~= 0 then
-      local opc3 = op - op % 256
+      local opc3 = band(op, 0xffff00)
       if opc3 == 0x0f3a00 or opc3 == 0x0f3800 then
       if opc3 == 0x0f3a00 or opc3 == 0x0f3800 then
-	wputb(64 + rex % 16); rex = 0
+	wputb(64 + band(rex, 15)); rex = 0
       end
       end
     end
     end
-    r = op % 65536 wputb((op-r) / 65536) op = r
+    wputb(shr(op, 16)); op = band(op, 0xffff)
   end
   end
   if op >= 256 then
   if op >= 256 then
-    r = op % 256
-    local b = (op-r) / 256
-    if b == 15 and rex ~= 0 then wputb(64 + rex % 16); rex = 0 end
+    local b = shr(op, 8)
+    if b == 15 and rex ~= 0 then wputb(64 + band(rex, 15)); rex = 0 end
     wputb(b)
     wputb(b)
-    op = r
+    op = band(op, 255)
   end
   end
-  if rex ~= 0 then wputb(64 + rex % 16) end
+  if rex ~= 0 then wputb(64 + band(rex, 15)) end
   if sz == "b" then op = op - 1 end
   if sz == "b" then op = op - 1 end
   wputb(op)
   wputb(op)
 end
 end
@@ -489,7 +490,7 @@ end
 -- Put ModRM or SIB formatted byte.
 -- Put ModRM or SIB formatted byte.
 local function wputmodrm(m, s, rm, vs, vrm)
 local function wputmodrm(m, s, rm, vs, vrm)
   assert(m < 4 and s < 16 and rm < 16, "bad modrm operands")
   assert(m < 4 and s < 16 and rm < 16, "bad modrm operands")
-  wputb(64*m + 8*(s%8) + (rm%8))
+  wputb(shl(m, 6) + shl(band(s, 7), 3) + band(rm, 7))
 end
 end
 
 
 -- Put ModRM/SIB plus optional displacement.
 -- Put ModRM/SIB plus optional displacement.
@@ -548,7 +549,7 @@ local function wputmrmsib(t, imark, s, vsreg)
 
 
   local m
   local m
   if tdisp == "number" then -- Check displacement size at assembly time.
   if tdisp == "number" then -- Check displacement size at assembly time.
-    if disp == 0 and (reg%8) ~= 5 then -- [ebp] -> [ebp+0] (in SIB, too)
+    if disp == 0 and band(reg, 7) ~= 5 then -- [ebp] -> [ebp+0] (in SIB, too)
       if not vreg then m = 0 end -- Force DISP to allow [Rd(5)] -> [ebp+0]
       if not vreg then m = 0 end -- Force DISP to allow [Rd(5)] -> [ebp+0]
     elseif disp >= -128 and disp <= 127 then m = 1
     elseif disp >= -128 and disp <= 127 then m = 1
     else m = 2 end
     else m = 2 end
@@ -557,7 +558,7 @@ local function wputmrmsib(t, imark, s, vsreg)
   end
   end
 
 
   -- Index register present or esp as base register: need SIB encoding.
   -- Index register present or esp as base register: need SIB encoding.
-  if xreg or (reg%8) == 4 then
+  if xreg or band(reg, 7) == 4 then
     wputmodrm(m or 2, s, 4) -- ModRM.
     wputmodrm(m or 2, s, 4) -- ModRM.
     if m == nil or imark == "I" then waction("MARK") end
     if m == nil or imark == "I" then waction("MARK") end
     if vsreg then waction("VREG", vsreg); wputxb(2) end
     if vsreg then waction("VREG", vsreg); wputxb(2) end
@@ -1410,7 +1411,7 @@ local map_op = {
 -- Arithmetic ops.
 -- Arithmetic ops.
 for name,n in pairs{ add = 0, ["or"] = 1, adc = 2, sbb = 3,
 for name,n in pairs{ add = 0, ["or"] = 1, adc = 2, sbb = 3,
 		     ["and"] = 4, sub = 5, xor = 6, cmp = 7 } do
 		     ["and"] = 4, sub = 5, xor = 6, cmp = 7 } do
-  local n8 = n * 8
+  local n8 = shl(n, 3)
   map_op[name.."_2"] = format(
   map_op[name.."_2"] = format(
     "mr:%02XRm|rm:%02XrM|mI1qdw:81%XmI|mS1qdw:83%XmS|Ri1qdwb:%02Xri|mi1qdwb:81%Xmi",
     "mr:%02XRm|rm:%02XrM|mI1qdw:81%XmI|mS1qdw:83%XmS|Ri1qdwb:%02Xri|mi1qdwb:81%Xmi",
     1+n8, 3+n8, n, n, 5+n8, n)
     1+n8, 3+n8, n, n, 5+n8, n)
@@ -1432,7 +1433,7 @@ end
 -- FP arithmetic ops.
 -- FP arithmetic ops.
 for name,n in pairs{ add = 0, mul = 1, com = 2, comp = 3,
 for name,n in pairs{ add = 0, mul = 1, com = 2, comp = 3,
 		     sub = 4, subr = 5, div = 6, divr = 7 } do
 		     sub = 4, subr = 5, div = 6, divr = 7 } do
-  local nc = 192 + n * 8
+  local nc = 0xc0 + shl(n, 3)
   local nr = nc + (n < 4 and 0 or (n % 2 == 0 and 8 or -8))
   local nr = nc + (n < 4 and 0 or (n % 2 == 0 and 8 or -8))
   local fn = "f"..name
   local fn = "f"..name
   map_op[fn.."_1"] = format("ff:D8%02Xr|xd:D8%Xm|xq:nDC%Xm", nc, n, n)
   map_op[fn.."_1"] = format("ff:D8%02Xr|xd:D8%Xm|xq:nDC%Xm", nc, n, n)
@@ -1448,8 +1449,7 @@ end
 
 
 -- FP conditional moves.
 -- FP conditional moves.
 for cc,n in pairs{ b=0, e=1, be=2, u=3, nb=4, ne=5, nbe=6, nu=7 } do
 for cc,n in pairs{ b=0, e=1, be=2, u=3, nb=4, ne=5, nbe=6, nu=7 } do
-  local n4 = n % 4
-  local nc = 56000 + n4 * 8 + (n-n4) * 64
+  local nc = 0xdac0 + shl(band(n, 3), 3) + shl(band(n, 4), 6)
   map_op["fcmov"..cc.."_1"] = format("ff:%04Xr", nc) -- P6+
   map_op["fcmov"..cc.."_1"] = format("ff:%04Xr", nc) -- P6+
   map_op["fcmov"..cc.."_2"] = format("Fff:%04XR", nc) -- P6+
   map_op["fcmov"..cc.."_2"] = format("Fff:%04XR", nc) -- P6+
 end
 end
@@ -1499,10 +1499,10 @@ local function dopattern(pat, args, sz, op, needrex)
       local s
       local s
       if addin then
       if addin then
 	s = addin.reg
 	s = addin.reg
-	opcode = opcode - (s%8)	-- Undo regno opcode merge.
+	opcode = opcode - band(s, 7)	-- Undo regno opcode merge.
       else
       else
-	s = opcode % 16		-- Undo last digit.
-	opcode = (opcode - s) / 16
+	s = band(opcode, 15)	-- Undo last digit.
+	opcode = shr(opcode, 4)
       end
       end
       local nn = c == "m" and 1 or 2
       local nn = c == "m" and 1 or 2
       local t = args[nn]
       local t = args[nn]
@@ -1699,7 +1699,7 @@ if x64 then
 	  werror("bad operand mode")
 	  werror("bad operand mode")
 	end
 	end
 	op64 = params[2]
 	op64 = params[2]
-	opcode = 0xb8 + (a.reg%8) -- !x64: no VREG support.
+	opcode = 0xb8 + band(a.reg, 7) -- !x64: no VREG support.
 	rex = a.reg > 7 and 9 or 8
 	rex = a.reg > 7 and 9 or 8
       end
       end
     end
     end

+ 1 - 1
src/Makefile

@@ -168,7 +168,7 @@ LDOPTIONS= $(CCDEBUG) $(LDFLAGS)
 HOST_CC= $(CC)
 HOST_CC= $(CC)
 HOST_RM= rm -f
 HOST_RM= rm -f
 # If left blank, minilua is built and used. You can supply an installed
 # If left blank, minilua is built and used. You can supply an installed
-# copy of (plain) Lua 5.1 or 5.2, e.g. with: HOST_LUA=lua
+# copy of (plain) Lua 5.1 or 5.2, plus Lua BitOp. E.g. with: HOST_LUA=lua
 HOST_LUA=
 HOST_LUA=
 
 
 HOST_XCFLAGS= -I.
 HOST_XCFLAGS= -I.