| ... | @@ -468,7 +468,15 @@ fn mirArithMemImm(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void { | ... | @@ -468,7 +468,15 @@ fn mirArithMemImm(emit: *Emit, tag: Tag, inst: Mir.Inst.Index) InnerError!void { |
| 468 | ) catch |err| emit.failWithLoweringError(err); | 468 | ) catch |err| emit.failWithLoweringError(err); |
| 469 | } | 469 | } |
| 470 | | 470 | |
| 471 | fn immOpSize(imm: i64) u8 { | 471 | inline fn setRexWRegister(reg: Register) bool { |
| | 472 | if (reg.size() == 64) return true; |
| | 473 | return switch (reg) { |
| | 474 | .ah, .bh, .ch, .dh => true, |
| | 475 | else => false, |
| | 476 | }; |
| | 477 | } |
| | 478 | |
| | 479 | inline fn immOpSize(imm: i64) u8 { |
| 472 | blk: { | 480 | blk: { |
| 473 | _ = math.cast(i8, imm) catch break :blk; | 481 | _ = math.cast(i8, imm) catch break :blk; |
| 474 | return 8; | 482 | return 8; |
| ... | @@ -1370,7 +1378,10 @@ fn lowerToMEnc(tag: Tag, reg_or_mem: RegisterOrMemory, code: *std.ArrayList(u8)) | ... | @@ -1370,7 +1378,10 @@ fn lowerToMEnc(tag: Tag, reg_or_mem: RegisterOrMemory, code: *std.ArrayList(u8)) |
| 1370 | encoder.opcode_1byte(0x66); | 1378 | encoder.opcode_1byte(0x66); |
| 1371 | } | 1379 | } |
| 1372 | encoder.rex(.{ | 1380 | encoder.rex(.{ |
| 1373 | .w = tag.isSetCC(), | 1381 | .w = switch (reg) { |
| | 1382 | .ah, .bh, .ch, .dh => true, |
| | 1383 | else => false, |
| | 1384 | }, |
| 1374 | .b = reg.isExtended(), | 1385 | .b = reg.isExtended(), |
| 1375 | }); | 1386 | }); |
| 1376 | opc.encode(encoder); | 1387 | opc.encode(encoder); |
| ... | @@ -1389,7 +1400,7 @@ fn lowerToMEnc(tag: Tag, reg_or_mem: RegisterOrMemory, code: *std.ArrayList(u8)) | ... | @@ -1389,7 +1400,7 @@ fn lowerToMEnc(tag: Tag, reg_or_mem: RegisterOrMemory, code: *std.ArrayList(u8)) |
| 1389 | return error.OperandSizeMismatch; | 1400 | return error.OperandSizeMismatch; |
| 1390 | } | 1401 | } |
| 1391 | encoder.rex(.{ | 1402 | encoder.rex(.{ |
| 1392 | .w = tag.isSetCC(), | 1403 | .w = false, |
| 1393 | .b = reg.isExtended(), | 1404 | .b = reg.isExtended(), |
| 1394 | }); | 1405 | }); |
| 1395 | opc.encode(encoder); | 1406 | opc.encode(encoder); |
| ... | @@ -1455,7 +1466,7 @@ fn lowerToTdFdEnc(tag: Tag, reg: Register, moffs: i64, code: *std.ArrayList(u8), | ... | @@ -1455,7 +1466,7 @@ fn lowerToTdFdEnc(tag: Tag, reg: Register, moffs: i64, code: *std.ArrayList(u8), |
| 1455 | encoder.opcode_1byte(0x66); | 1466 | encoder.opcode_1byte(0x66); |
| 1456 | } | 1467 | } |
| 1457 | encoder.rex(.{ | 1468 | encoder.rex(.{ |
| 1458 | .w = reg.size() == 64, | 1469 | .w = setRexWRegister(reg), |
| 1459 | }); | 1470 | }); |
| 1460 | opc.encode(encoder); | 1471 | opc.encode(encoder); |
| 1461 | switch (reg.size()) { | 1472 | switch (reg.size()) { |
| ... | @@ -1488,7 +1499,7 @@ fn lowerToOiEnc(tag: Tag, reg: Register, imm: i64, code: *std.ArrayList(u8)) Low | ... | @@ -1488,7 +1499,7 @@ fn lowerToOiEnc(tag: Tag, reg: Register, imm: i64, code: *std.ArrayList(u8)) Low |
| 1488 | encoder.opcode_1byte(0x66); | 1499 | encoder.opcode_1byte(0x66); |
| 1489 | } | 1500 | } |
| 1490 | encoder.rex(.{ | 1501 | encoder.rex(.{ |
| 1491 | .w = reg.size() == 64, | 1502 | .w = setRexWRegister(reg), |
| 1492 | .b = reg.isExtended(), | 1503 | .b = reg.isExtended(), |
| 1493 | }); | 1504 | }); |
| 1494 | opc.encodeWithReg(encoder, reg); | 1505 | opc.encodeWithReg(encoder, reg); |
| ... | @@ -1525,7 +1536,7 @@ fn lowerToMiEnc(tag: Tag, reg_or_mem: RegisterOrMemory, imm: i32, code: *std.Arr | ... | @@ -1525,7 +1536,7 @@ fn lowerToMiEnc(tag: Tag, reg_or_mem: RegisterOrMemory, imm: i32, code: *std.Arr |
| 1525 | encoder.opcode_1byte(0x66); | 1536 | encoder.opcode_1byte(0x66); |
| 1526 | } | 1537 | } |
| 1527 | encoder.rex(.{ | 1538 | encoder.rex(.{ |
| 1528 | .w = dst_reg.size() == 64, | 1539 | .w = setRexWRegister(dst_reg), |
| 1529 | .b = dst_reg.isExtended(), | 1540 | .b = dst_reg.isExtended(), |
| 1530 | }); | 1541 | }); |
| 1531 | opc.encode(encoder); | 1542 | opc.encode(encoder); |
| ... | @@ -1623,7 +1634,7 @@ fn lowerToRmEnc( | ... | @@ -1623,7 +1634,7 @@ fn lowerToRmEnc( |
| 1623 | } | 1634 | } |
| 1624 | const encoder = try Encoder.init(code, 3); | 1635 | const encoder = try Encoder.init(code, 3); |
| 1625 | encoder.rex(.{ | 1636 | encoder.rex(.{ |
| 1626 | .w = reg.size() == 64, | 1637 | .w = setRexWRegister(reg) or setRexWRegister(src_reg), |
| 1627 | .r = reg.isExtended(), | 1638 | .r = reg.isExtended(), |
| 1628 | .b = src_reg.isExtended(), | 1639 | .b = src_reg.isExtended(), |
| 1629 | }); | 1640 | }); |
| ... | @@ -1645,7 +1656,7 @@ fn lowerToRmEnc( | ... | @@ -1645,7 +1656,7 @@ fn lowerToRmEnc( |
| 1645 | return error.OperandSizeMismatch; | 1656 | return error.OperandSizeMismatch; |
| 1646 | } | 1657 | } |
| 1647 | encoder.rex(.{ | 1658 | encoder.rex(.{ |
| 1648 | .w = reg.size() == 64, | 1659 | .w = setRexWRegister(reg), |
| 1649 | .r = reg.isExtended(), | 1660 | .r = reg.isExtended(), |
| 1650 | .b = src_reg.isExtended(), | 1661 | .b = src_reg.isExtended(), |
| 1651 | }); | 1662 | }); |
| ... | @@ -1676,7 +1687,7 @@ fn lowerToRmEnc( | ... | @@ -1676,7 +1687,7 @@ fn lowerToRmEnc( |
| 1676 | } | 1687 | } |
| 1677 | } else { | 1688 | } else { |
| 1678 | encoder.rex(.{ | 1689 | encoder.rex(.{ |
| 1679 | .w = reg.size() == 64, | 1690 | .w = setRexWRegister(reg), |
| 1680 | .r = reg.isExtended(), | 1691 | .r = reg.isExtended(), |
| 1681 | }); | 1692 | }); |
| 1682 | opc.encode(encoder); | 1693 | opc.encode(encoder); |
| ... | @@ -1706,7 +1717,7 @@ fn lowerToMrEnc( | ... | @@ -1706,7 +1717,7 @@ fn lowerToMrEnc( |
| 1706 | } | 1717 | } |
| 1707 | const encoder = try Encoder.init(code, 3); | 1718 | const encoder = try Encoder.init(code, 3); |
| 1708 | encoder.rex(.{ | 1719 | encoder.rex(.{ |
| 1709 | .w = dst_reg.size() == 64, | 1720 | .w = setRexWRegister(dst_reg) or setRexWRegister(reg), |
| 1710 | .r = reg.isExtended(), | 1721 | .r = reg.isExtended(), |
| 1711 | .b = dst_reg.isExtended(), | 1722 | .b = dst_reg.isExtended(), |
| 1712 | }); | 1723 | }); |
| ... | @@ -1726,7 +1737,7 @@ fn lowerToMrEnc( | ... | @@ -1726,7 +1737,7 @@ fn lowerToMrEnc( |
| 1726 | return error.OperandSizeMismatch; | 1737 | return error.OperandSizeMismatch; |
| 1727 | } | 1738 | } |
| 1728 | encoder.rex(.{ | 1739 | encoder.rex(.{ |
| 1729 | .w = dst_mem.ptr_size == .qword_ptr, | 1740 | .w = dst_mem.ptr_size == .qword_ptr or setRexWRegister(reg), |
| 1730 | .r = reg.isExtended(), | 1741 | .r = reg.isExtended(), |
| 1731 | .b = dst_reg.isExtended(), | 1742 | .b = dst_reg.isExtended(), |
| 1732 | }); | 1743 | }); |
| ... | @@ -1757,7 +1768,7 @@ fn lowerToMrEnc( | ... | @@ -1757,7 +1768,7 @@ fn lowerToMrEnc( |
| 1757 | } | 1768 | } |
| 1758 | } else { | 1769 | } else { |
| 1759 | encoder.rex(.{ | 1770 | encoder.rex(.{ |
| 1760 | .w = dst_mem.ptr_size == .qword_ptr, | 1771 | .w = dst_mem.ptr_size == .qword_ptr or setRexWRegister(reg), |
| 1761 | .r = reg.isExtended(), | 1772 | .r = reg.isExtended(), |
| 1762 | }); | 1773 | }); |
| 1763 | opc.encode(encoder); | 1774 | opc.encode(encoder); |
| ... | @@ -1794,7 +1805,7 @@ fn lowerToRmiEnc( | ... | @@ -1794,7 +1805,7 @@ fn lowerToRmiEnc( |
| 1794 | return error.OperandSizeMismatch; | 1805 | return error.OperandSizeMismatch; |
| 1795 | } | 1806 | } |
| 1796 | encoder.rex(.{ | 1807 | encoder.rex(.{ |
| 1797 | .w = reg.size() == 64, | 1808 | .w = setRexWRegister(reg) or setRexWRegister(src_reg), |
| 1798 | .r = reg.isExtended(), | 1809 | .r = reg.isExtended(), |
| 1799 | .b = src_reg.isExtended(), | 1810 | .b = src_reg.isExtended(), |
| 1800 | }); | 1811 | }); |
| ... | @@ -1812,7 +1823,7 @@ fn lowerToRmiEnc( | ... | @@ -1812,7 +1823,7 @@ fn lowerToRmiEnc( |
| 1812 | return error.OperandSizeMismatch; | 1823 | return error.OperandSizeMismatch; |
| 1813 | } | 1824 | } |
| 1814 | encoder.rex(.{ | 1825 | encoder.rex(.{ |
| 1815 | .w = reg.size() == 64, | 1826 | .w = setRexWRegister(reg), |
| 1816 | .r = reg.isExtended(), | 1827 | .r = reg.isExtended(), |
| 1817 | .b = src_reg.isExtended(), | 1828 | .b = src_reg.isExtended(), |
| 1818 | }); | 1829 | }); |
| ... | @@ -1843,7 +1854,7 @@ fn lowerToRmiEnc( | ... | @@ -1843,7 +1854,7 @@ fn lowerToRmiEnc( |
| 1843 | } | 1854 | } |
| 1844 | } else { | 1855 | } else { |
| 1845 | encoder.rex(.{ | 1856 | encoder.rex(.{ |
| 1846 | .w = reg.size() == 64, | 1857 | .w = setRexWRegister(reg), |
| 1847 | .r = reg.isExtended(), | 1858 | .r = reg.isExtended(), |
| 1848 | }); | 1859 | }); |
| 1849 | opc.encode(encoder); | 1860 | opc.encode(encoder); |
| ... | @@ -2089,7 +2100,7 @@ test "lower M encoding" { | ... | @@ -2089,7 +2100,7 @@ test "lower M encoding" { |
| 2089 | try lowerToMEnc(.jmp_near, RegisterOrMemory.mem(null, 0x10, .qword_ptr), code.buffer()); | 2100 | try lowerToMEnc(.jmp_near, RegisterOrMemory.mem(null, 0x10, .qword_ptr), code.buffer()); |
| 2090 | try expectEqualHexStrings("\xFF\x24\x25\x10\x00\x00\x00", code.emitted(), "jmp qword ptr [ds:0x10]"); | 2101 | try expectEqualHexStrings("\xFF\x24\x25\x10\x00\x00\x00", code.emitted(), "jmp qword ptr [ds:0x10]"); |
| 2091 | try lowerToMEnc(.seta, RegisterOrMemory.reg(.r11b), code.buffer()); | 2102 | try lowerToMEnc(.seta, RegisterOrMemory.reg(.r11b), code.buffer()); |
| 2092 | try expectEqualHexStrings("\x49\x0F\x97\xC3", code.emitted(), "seta r11b"); | 2103 | try expectEqualHexStrings("\x41\x0F\x97\xC3", code.emitted(), "seta r11b"); |
| 2093 | } | 2104 | } |
| 2094 | | 2105 | |
| 2095 | test "lower O encoding" { | 2106 | test "lower O encoding" { |
| ... | @@ -2111,9 +2122,9 @@ test "lower RMI encoding" { | ... | @@ -2111,9 +2122,9 @@ test "lower RMI encoding" { |
| 2111 | "imul rax, qword ptr [rbp - 8], 0x10", | 2122 | "imul rax, qword ptr [rbp - 8], 0x10", |
| 2112 | ); | 2123 | ); |
| 2113 | try lowerToRmiEnc(.imul, .eax, RegisterOrMemory.mem(.rbp, -4, .dword_ptr), 0x10, code.buffer()); | 2124 | try lowerToRmiEnc(.imul, .eax, RegisterOrMemory.mem(.rbp, -4, .dword_ptr), 0x10, code.buffer()); |
| 2114 | try expectEqualHexStrings("\x69\x45\xFC\x10\x00\x00\x00", code.emitted(), "imul ax, [rbp - 2], 0x10"); | 2125 | try expectEqualHexStrings("\x69\x45\xFC\x10\x00\x00\x00", code.emitted(), "imul eax, dword ptr [rbp - 4], 0x10"); |
| 2115 | try lowerToRmiEnc(.imul, .ax, RegisterOrMemory.mem(.rbp, -2, .word_ptr), 0x10, code.buffer()); | 2126 | try lowerToRmiEnc(.imul, .ax, RegisterOrMemory.mem(.rbp, -2, .word_ptr), 0x10, code.buffer()); |
| 2116 | try expectEqualHexStrings("\x66\x69\x45\xFE\x10\x00", code.emitted(), "imul eax, [rbp - 4], 0x10"); | 2127 | try expectEqualHexStrings("\x66\x69\x45\xFE\x10\x00", code.emitted(), "imul ax, word ptr [rbp - 2], 0x10"); |
| 2117 | try lowerToRmiEnc(.imul, .r12, RegisterOrMemory.reg(.r12), 0x10, code.buffer()); | 2128 | try lowerToRmiEnc(.imul, .r12, RegisterOrMemory.reg(.r12), 0x10, code.buffer()); |
| 2118 | try expectEqualHexStrings("\x4D\x69\xE4\x10\x00\x00\x00", code.emitted(), "imul r12, r12, 0x10"); | 2129 | try expectEqualHexStrings("\x4D\x69\xE4\x10\x00\x00\x00", code.emitted(), "imul r12, r12, 0x10"); |
| 2119 | try lowerToRmiEnc(.imul, .r12w, RegisterOrMemory.reg(.r12w), 0x10, code.buffer()); | 2130 | try lowerToRmiEnc(.imul, .r12w, RegisterOrMemory.reg(.r12w), 0x10, code.buffer()); |