authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-02 22:24:07+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-04 01:21:23+01:00
logf37598c779b921d5fc4f97cdcfab523e3fb5fc69
tree6e4f89963d21fb2d5984208027062a7d1406ea06
parent978de7038161dffbd805e33f27ade177ec873bcc

stage2: clean up encoding of memory operands


1 files changed, 63 insertions(+), 74 deletions(-)

src/arch/x86_64/Isel.zig+63-74
...@@ -1230,18 +1230,17 @@ inline fn getModRmExt(tag: Tag) ?u3 {...@@ -1230,18 +1230,17 @@ inline fn getModRmExt(tag: Tag) ?u3 {
1230 };1230 };
1231}1231}
12321232
1233const ScaleIndexBase = struct {1233const ScaleIndex = struct {
1234 scale: u2,1234 scale: u2,
1235 index_reg: ?Register,1235 index: Register,
1236 base_reg: ?Register,
1237};1236};
12381237
1239const Memory = struct {1238const Memory = struct {
1240 reg: ?Register,1239 base: ?Register,
1241 rip: bool = false,1240 rip: bool = false,
1242 disp: i32,1241 disp: i32,
1243 ptr_size: PtrSize,1242 ptr_size: PtrSize,
1244 sib: ?ScaleIndexBase = null,1243 scale_index: ?ScaleIndex = null,
12451244
1246 const PtrSize = enum {1245 const PtrSize = enum {
1247 byte_ptr,1246 byte_ptr,
...@@ -1270,42 +1269,44 @@ const Memory = struct {...@@ -1270,42 +1269,44 @@ const Memory = struct {
1270 }1269 }
1271 };1270 };
12721271
1273 fn encodeWithReg(encoder: Encoder, dst: u3, src: u3, disp: i32) void {1272 fn encode(mem_op: Memory, encoder: Encoder, operand: u3) void {
1274 if (dst == 4) {1273 if (mem_op.base) |base| {
1275 if (disp == 0) {1274 const dst = base.lowId();
1276 encoder.modRm_SIBDisp0(src);1275 const src = operand;
1277 encoder.sib_base(dst);1276 if (dst == 4) {
1278 } else if (immOpSize(disp) == 8) {1277 if (mem_op.disp == 0) {
1279 encoder.modRm_SIBDisp8(src);1278 encoder.modRm_SIBDisp0(src);
1280 encoder.sib_baseDisp8(dst);1279 encoder.sib_base(dst);
1281 encoder.disp8(@intCast(i8, disp));1280 } else if (immOpSize(mem_op.disp) == 8) {
1281 encoder.modRm_SIBDisp8(src);
1282 encoder.sib_baseDisp8(dst);
1283 encoder.disp8(@intCast(i8, mem_op.disp));
1284 } else {
1285 encoder.modRm_SIBDisp32(src);
1286 encoder.sib_baseDisp32(dst);
1287 encoder.disp32(mem_op.disp);
1288 }
1282 } else {1289 } else {
1283 encoder.modRm_SIBDisp32(src);1290 if (mem_op.disp == 0) {
1284 encoder.sib_baseDisp32(dst);1291 encoder.modRm_indirectDisp0(src, dst);
1285 encoder.disp32(disp);1292 } else if (immOpSize(mem_op.disp) == 8) {
1293 encoder.modRm_indirectDisp8(src, dst);
1294 encoder.disp8(@intCast(i8, mem_op.disp));
1295 } else {
1296 encoder.modRm_indirectDisp32(src, dst);
1297 encoder.disp32(mem_op.disp);
1298 }
1286 }1299 }
1287 } else {1300 } else {
1288 if (disp == 0) {1301 if (mem_op.rip) {
1289 encoder.modRm_indirectDisp0(src, dst);1302 encoder.modRm_RIPDisp32(operand);
1290 } else if (immOpSize(disp) == 8) {
1291 encoder.modRm_indirectDisp8(src, dst);
1292 encoder.disp8(@intCast(i8, disp));
1293 } else {1303 } else {
1294 encoder.modRm_indirectDisp32(src, dst);1304 encoder.modRm_SIBDisp0(operand);
1295 encoder.disp32(disp);1305 encoder.sib_disp32();
1296 }1306 }
1307 encoder.disp32(mem_op.disp);
1297 }1308 }
1298 }1309 }
1299
1300 fn encodeDsOrRip(encoder: Encoder, op: u3, disp: i32, rip: bool) void {
1301 if (rip) {
1302 encoder.modRm_RIPDisp32(op);
1303 } else {
1304 encoder.modRm_SIBDisp0(op);
1305 encoder.sib_disp32();
1306 }
1307 encoder.disp32(disp);
1308 }
1309};1310};
13101311
1311fn encodeImm(encoder: Encoder, imm: i32, size: u64) void {1312fn encodeImm(encoder: Encoder, imm: i32, size: u64) void {
...@@ -1325,10 +1326,10 @@ const RegisterOrMemory = union(enum) {...@@ -1325,10 +1326,10 @@ const RegisterOrMemory = union(enum) {
1325 return .{ .register = register };1326 return .{ .register = register };
1326 }1327 }
13271328
1328 fn mem(register: ?Register, disp: i32, ptr_size: Memory.PtrSize) RegisterOrMemory {1329 fn mem(base: ?Register, disp: i32, ptr_size: Memory.PtrSize) RegisterOrMemory {
1329 return .{1330 return .{
1330 .memory = .{1331 .memory = .{
1331 .reg = register,1332 .base = base,
1332 .disp = disp,1333 .disp = disp,
1333 .ptr_size = ptr_size,1334 .ptr_size = ptr_size,
1334 },1335 },
...@@ -1338,7 +1339,7 @@ const RegisterOrMemory = union(enum) {...@@ -1338,7 +1339,7 @@ const RegisterOrMemory = union(enum) {
1338 fn rip(disp: i32, ptr_size: Memory.PtrSize) RegisterOrMemory {1339 fn rip(disp: i32, ptr_size: Memory.PtrSize) RegisterOrMemory {
1339 return .{1340 return .{
1340 .memory = .{1341 .memory = .{
1341 .reg = null,1342 .base = null,
1342 .rip = true,1343 .rip = true,
1343 .disp = disp,1344 .disp = disp,
1344 .ptr_size = ptr_size,1345 .ptr_size = ptr_size,
...@@ -1435,20 +1436,17 @@ fn lowerToMEnc(tag: Tag, reg_or_mem: RegisterOrMemory, code: *std.ArrayList(u8))...@@ -1435,20 +1436,17 @@ fn lowerToMEnc(tag: Tag, reg_or_mem: RegisterOrMemory, code: *std.ArrayList(u8))
1435 if (mem_op.ptr_size == .word_ptr) {1436 if (mem_op.ptr_size == .word_ptr) {
1436 encoder.prefix16BitMode();1437 encoder.prefix16BitMode();
1437 }1438 }
1438 if (mem_op.reg) |reg| {1439 if (mem_op.base) |base| {
1439 if (reg.size() != 64) {1440 if (base.size() != 64) {
1440 return error.OperandSizeMismatch;1441 return error.OperandSizeMismatch;
1441 }1442 }
1442 encoder.rex(.{1443 encoder.rex(.{
1443 .w = false,1444 .w = false,
1444 .b = reg.isExtended(),1445 .b = base.isExtended(),
1445 });1446 });
1446 opc.encode(encoder);
1447 Memory.encodeWithReg(encoder, reg.lowId(), modrm_ext, mem_op.disp);
1448 } else {
1449 opc.encode(encoder);
1450 Memory.encodeDsOrRip(encoder, modrm_ext, mem_op.disp, mem_op.rip);
1451 }1447 }
1448 opc.encode(encoder);
1449 mem_op.encode(encoder, modrm_ext);
1452 },1450 },
1453 }1451 }
1454}1452}
...@@ -1560,20 +1558,17 @@ fn lowerToMiEnc(tag: Tag, reg_or_mem: RegisterOrMemory, imm: i32, code: *std.Arr...@@ -1560,20 +1558,17 @@ fn lowerToMiEnc(tag: Tag, reg_or_mem: RegisterOrMemory, imm: i32, code: *std.Arr
1560 if (dst_mem.ptr_size == .word_ptr) {1558 if (dst_mem.ptr_size == .word_ptr) {
1561 encoder.prefix16BitMode();1559 encoder.prefix16BitMode();
1562 }1560 }
1563 if (dst_mem.reg) |dst_reg| {1561 if (dst_mem.base) |base| {
1564 if (dst_reg.size() != 64) {1562 if (base.size() != 64) {
1565 return error.OperandSizeMismatch;1563 return error.OperandSizeMismatch;
1566 }1564 }
1567 encoder.rex(.{1565 encoder.rex(.{
1568 .w = dst_mem.ptr_size == .qword_ptr,1566 .w = dst_mem.ptr_size == .qword_ptr,
1569 .b = dst_reg.isExtended(),1567 .b = base.isExtended(),
1570 });1568 });
1571 opc.encode(encoder);
1572 Memory.encodeWithReg(encoder, dst_reg.lowId(), modrm_ext, dst_mem.disp);
1573 } else {
1574 opc.encode(encoder);
1575 Memory.encodeDsOrRip(encoder, modrm_ext, dst_mem.disp, dst_mem.rip);
1576 }1569 }
1570 opc.encode(encoder);
1571 dst_mem.encode(encoder, modrm_ext);
1577 encodeImm(encoder, imm, dst_mem.ptr_size.size());1572 encodeImm(encoder, imm, dst_mem.ptr_size.size());
1578 },1573 },
1579 }1574 }
...@@ -1608,27 +1603,25 @@ fn lowerToRmEnc(...@@ -1608,27 +1603,25 @@ fn lowerToRmEnc(
1608 if (reg.size() == 16) {1603 if (reg.size() == 16) {
1609 encoder.prefix16BitMode();1604 encoder.prefix16BitMode();
1610 }1605 }
1611 if (src_mem.reg) |src_reg| {1606 if (src_mem.base) |base| {
1612 // TODO handle 32-bit base register - requires prefix 0x671607 // TODO handle 32-bit base register - requires prefix 0x67
1613 // Intel Manual, Vol 1, chapter 3.6 and 3.6.11608 // Intel Manual, Vol 1, chapter 3.6 and 3.6.1
1614 if (src_reg.size() != 64) {1609 if (base.size() != 64) {
1615 return error.OperandSizeMismatch;1610 return error.OperandSizeMismatch;
1616 }1611 }
1617 encoder.rex(.{1612 encoder.rex(.{
1618 .w = setRexWRegister(reg),1613 .w = setRexWRegister(reg),
1619 .r = reg.isExtended(),1614 .r = reg.isExtended(),
1620 .b = src_reg.isExtended(),1615 .b = base.isExtended(),
1621 });1616 });
1622 opc.encode(encoder);
1623 Memory.encodeWithReg(encoder, src_reg.lowId(), reg.lowId(), src_mem.disp);
1624 } else {1617 } else {
1625 encoder.rex(.{1618 encoder.rex(.{
1626 .w = setRexWRegister(reg),1619 .w = setRexWRegister(reg),
1627 .r = reg.isExtended(),1620 .r = reg.isExtended(),
1628 });1621 });
1629 opc.encode(encoder);
1630 Memory.encodeDsOrRip(encoder, reg.lowId(), src_mem.disp, src_mem.rip);
1631 }1622 }
1623 opc.encode(encoder);
1624 src_mem.encode(encoder, reg.lowId());
1632 },1625 },
1633 }1626 }
1634}1627}
...@@ -1662,25 +1655,23 @@ fn lowerToMrEnc(...@@ -1662,25 +1655,23 @@ fn lowerToMrEnc(
1662 if (reg.size() == 16) {1655 if (reg.size() == 16) {
1663 encoder.prefix16BitMode();1656 encoder.prefix16BitMode();
1664 }1657 }
1665 if (dst_mem.reg) |dst_reg| {1658 if (dst_mem.base) |base| {
1666 if (dst_reg.size() != 64) {1659 if (base.size() != 64) {
1667 return error.OperandSizeMismatch;1660 return error.OperandSizeMismatch;
1668 }1661 }
1669 encoder.rex(.{1662 encoder.rex(.{
1670 .w = dst_mem.ptr_size == .qword_ptr or setRexWRegister(reg),1663 .w = dst_mem.ptr_size == .qword_ptr or setRexWRegister(reg),
1671 .r = reg.isExtended(),1664 .r = reg.isExtended(),
1672 .b = dst_reg.isExtended(),1665 .b = base.isExtended(),
1673 });1666 });
1674 opc.encode(encoder);
1675 Memory.encodeWithReg(encoder, dst_reg.lowId(), reg.lowId(), dst_mem.disp);
1676 } else {1667 } else {
1677 encoder.rex(.{1668 encoder.rex(.{
1678 .w = dst_mem.ptr_size == .qword_ptr or setRexWRegister(reg),1669 .w = dst_mem.ptr_size == .qword_ptr or setRexWRegister(reg),
1679 .r = reg.isExtended(),1670 .r = reg.isExtended(),
1680 });1671 });
1681 opc.encode(encoder);
1682 Memory.encodeDsOrRip(encoder, reg.lowId(), dst_mem.disp, dst_mem.rip);
1683 }1672 }
1673 opc.encode(encoder);
1674 dst_mem.encode(encoder, reg.lowId());
1684 },1675 },
1685 }1676 }
1686}1677}
...@@ -1714,10 +1705,10 @@ fn lowerToRmiEnc(...@@ -1714,10 +1705,10 @@ fn lowerToRmiEnc(
1714 encoder.modRm_direct(reg.lowId(), src_reg.lowId());1705 encoder.modRm_direct(reg.lowId(), src_reg.lowId());
1715 },1706 },
1716 .memory => |src_mem| {1707 .memory => |src_mem| {
1717 if (src_mem.reg) |src_reg| {1708 if (src_mem.base) |base| {
1718 // TODO handle 32-bit base register - requires prefix 0x671709 // TODO handle 32-bit base register - requires prefix 0x67
1719 // Intel Manual, Vol 1, chapter 3.6 and 3.6.11710 // Intel Manual, Vol 1, chapter 3.6 and 3.6.1
1720 if (src_reg.size() != 64) {1711 if (base.size() != 64) {
1721 return error.OperandSizeMismatch;1712 return error.OperandSizeMismatch;
1722 }1713 }
1723 if (src_mem.ptr_size == .byte_ptr) {1714 if (src_mem.ptr_size == .byte_ptr) {
...@@ -1726,18 +1717,16 @@ fn lowerToRmiEnc(...@@ -1726,18 +1717,16 @@ fn lowerToRmiEnc(
1726 encoder.rex(.{1717 encoder.rex(.{
1727 .w = setRexWRegister(reg),1718 .w = setRexWRegister(reg),
1728 .r = reg.isExtended(),1719 .r = reg.isExtended(),
1729 .b = src_reg.isExtended(),1720 .b = base.isExtended(),
1730 });1721 });
1731 opc.encode(encoder);
1732 Memory.encodeWithReg(encoder, src_reg.lowId(), reg.lowId(), src_mem.disp);
1733 } else {1722 } else {
1734 encoder.rex(.{1723 encoder.rex(.{
1735 .w = setRexWRegister(reg),1724 .w = setRexWRegister(reg),
1736 .r = reg.isExtended(),1725 .r = reg.isExtended(),
1737 });1726 });
1738 opc.encode(encoder);
1739 Memory.encodeDsOrRip(encoder, reg.lowId(), src_mem.disp, src_mem.rip);
1740 }1727 }
1728 opc.encode(encoder);
1729 src_mem.encode(encoder, reg.lowId());
1741 },1730 },
1742 }1731 }
1743 encodeImm(encoder, imm, reg.size());1732 encodeImm(encoder, imm, reg.size());