diff options
Diffstat (limited to 'dynasm/dasm_x86.lua')
-rw-r--r-- | dynasm/dasm_x86.lua | 52 |
1 files changed, 26 insertions, 26 deletions
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 |