authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-12-22 23:07:46+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-12-22 23:07:46+01:00
log362eccf539db6bb89e222916f3c4a45b0eb2bece
treeffb37c893f424f29589dcba0926d0df0562abad4
parentb40e5adf54de878c2745bcf6e266239b7f5c40b6

stage2: handle RIP relative addressing in MI, RM and MR


1 files changed, 47 insertions(+), 47 deletions(-)

src/arch/x86_64/Emit.zig+47-47
......@@ -581,6 +581,7 @@ inline fn getOpCode(tag: Mir.Inst.Tag, enc: Encoding) u8 {
581581 .sbb => 0x1b,
582582 .cmp => 0x3b,
583583 .mov => 0x8b,
584 .lea => 0x8d,
584585 else => unreachable,
585586 },
586587 .oi => return switch (tag) {
......@@ -621,6 +622,7 @@ const ScaleIndexBase = struct {
621622
622623const Memory = struct {
623624 reg: ?Register,
625 rip: bool = false,
624626 disp: i32,
625627 sib: ?ScaleIndexBase = null,
626628};
......@@ -641,6 +643,16 @@ const RegisterOrMemory = union(enum) {
641643 },
642644 };
643645 }
646
647 fn rip(disp: i32) RegisterOrMemory {
648 return .{
649 .memory = .{
650 .reg = null,
651 .rip = true,
652 .disp = disp,
653 },
654 };
655 }
644656};
645657
646658fn lowerToTdEnc(
......@@ -813,8 +825,12 @@ fn lowerToMiEnc(
813825 }
814826 } else {
815827 encoder.opcode_1byte(opc);
816 encoder.modRm_SIBDisp0(modrm_ext);
817 encoder.sib_disp32();
828 if (dst_mem.rip) {
829 encoder.modRm_RIPDisp32(modrm_ext);
830 } else {
831 encoder.modRm_SIBDisp0(modrm_ext);
832 encoder.sib_disp32();
833 }
818834 encoder.disp32(dst_mem.disp);
819835 }
820836 encoder.imm32(imm);
......@@ -880,8 +896,12 @@ fn lowerToRmEnc(
880896 .r = reg.isExtended(),
881897 });
882898 encoder.opcode_1byte(opc);
883 encoder.modRm_SIBDisp0(reg.lowId());
884 encoder.sib_disp32();
899 if (src_mem.rip) {
900 encoder.modRm_RIPDisp32(reg.lowId());
901 } else {
902 encoder.modRm_SIBDisp0(reg.lowId());
903 encoder.sib_disp32();
904 }
885905 encoder.disp32(src_mem.disp);
886906 }
887907 },
......@@ -950,8 +970,12 @@ fn lowerToMrEnc(
950970 .r = reg.isExtended(),
951971 });
952972 encoder.opcode_1byte(opc);
953 encoder.modRm_SIBDisp0(reg.lowId());
954 encoder.sib_disp32();
973 if (dst_mem.rip) {
974 encoder.modRm_RIPDisp32(reg.lowId());
975 } else {
976 encoder.modRm_SIBDisp0(reg.lowId());
977 encoder.sib_disp32();
978 }
955979 encoder.disp32(dst_mem.disp);
956980 }
957981 },
......@@ -1206,37 +1230,7 @@ fn mirLea(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
12061230 const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
12071231 assert(ops.flags == 0b01);
12081232 const imm = emit.mir.instructions.items(.data)[inst].imm;
1209
1210 if (imm == 0) {
1211 const encoder = try Encoder.init(emit.code, 3);
1212 encoder.rex(.{
1213 .w = ops.reg1.size() == 64,
1214 .r = ops.reg1.isExtended(),
1215 .b = ops.reg2.isExtended(),
1216 });
1217 encoder.opcode_1byte(0x8d);
1218 encoder.modRm_indirectDisp0(ops.reg1.lowId(), ops.reg2.lowId());
1219 } else if (imm <= math.maxInt(i8)) {
1220 const encoder = try Encoder.init(emit.code, 4);
1221 encoder.rex(.{
1222 .w = ops.reg1.size() == 64,
1223 .r = ops.reg1.isExtended(),
1224 .b = ops.reg2.isExtended(),
1225 });
1226 encoder.opcode_1byte(0x8d);
1227 encoder.modRm_indirectDisp8(ops.reg1.lowId(), ops.reg2.lowId());
1228 encoder.disp8(@intCast(i8, imm));
1229 } else {
1230 const encoder = try Encoder.init(emit.code, 7);
1231 encoder.rex(.{
1232 .w = ops.reg1.size() == 64,
1233 .r = ops.reg1.isExtended(),
1234 .b = ops.reg2.isExtended(),
1235 });
1236 encoder.opcode_1byte(0x8d);
1237 encoder.modRm_indirectDisp32(ops.reg1.lowId(), ops.reg2.lowId());
1238 encoder.disp32(imm);
1239 }
1233 return lowerToRmEnc(tag, ops.reg1, RegisterOrMemory.mem(ops.reg2, imm), emit.code);
12401234}
12411235
12421236fn mirLeaRip(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
......@@ -1244,26 +1238,22 @@ fn mirLeaRip(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
12441238 assert(tag == .lea_rip);
12451239 const ops = Mir.Ops.decode(emit.mir.instructions.items(.ops)[inst]);
12461240 const start_offset = emit.code.items.len;
1247 const encoder = try Encoder.init(emit.code, 7);
1248 encoder.rex(.{
1249 .w = ops.reg1.size() == 64,
1250 .r = ops.reg1.isExtended(),
1251 });
1252 encoder.opcode_1byte(0x8d);
1253 encoder.modRm_RIPDisp32(ops.reg1.lowId());
1241 try lowerToRmEnc(.lea, ops.reg1, RegisterOrMemory.rip(0), emit.code);
12541242 const end_offset = emit.code.items.len;
12551243 if (@truncate(u1, ops.flags) == 0b0) {
1244 // Backpatch the displacement
1245 // TODO figure out if this can be simplified
12561246 const payload = emit.mir.instructions.items(.data)[inst].payload;
12571247 const imm = emit.mir.extraData(Mir.Imm64, payload).data.decode();
1258 encoder.disp32(@intCast(i32, @intCast(i64, imm) - @intCast(i64, end_offset - start_offset + 4)));
1248 const disp = @intCast(i32, @intCast(i64, imm) - @intCast(i64, end_offset - start_offset));
1249 mem.writeIntLittle(i32, emit.code.items[end_offset - 4 ..][0..4], disp);
12591250 } else {
12601251 const got_entry = emit.mir.instructions.items(.data)[inst].got_entry;
1261 encoder.disp32(0);
12621252 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
12631253 // TODO I think the reloc might be in the wrong place.
12641254 const decl = macho_file.active_decl.?;
12651255 try decl.link.macho.relocs.append(emit.bin_file.allocator, .{
1266 .offset = @intCast(u32, end_offset),
1256 .offset = @intCast(u32, end_offset - 4),
12671257 .target = .{ .local = got_entry },
12681258 .addend = 0,
12691259 .subtractor = null,
......@@ -1530,6 +1520,12 @@ test "lower MI encoding" {
15301520 code.emitted(),
15311521 "and dword ptr [r12 + 0x10000000], 0x10",
15321522 );
1523 try lowerToMiEnc(.mov, RegisterOrMemory.rip(0x10), 0x10, code.buffer());
1524 try expectEqualHexStrings(
1525 "\xC7\x05\x10\x00\x00\x00\x10\x00\x00\x00",
1526 code.emitted(),
1527 "mov [rip + 0x10], 0x10",
1528 );
15331529}
15341530
15351531test "lower RM encoding" {
......@@ -1565,6 +1561,8 @@ test "lower RM encoding" {
15651561 );
15661562 try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.rbp, -4), code.buffer());
15671563 try expectEqualHexStrings("\x48\x8B\x45\xFC", code.emitted(), "mov rax, qword ptr [rbp - 4]");
1564 try lowerToRmEnc(.lea, .rax, RegisterOrMemory.rip(0x10), code.buffer());
1565 try expectEqualHexStrings("\x48\x8D\x05\x10\x00\x00\x00", code.emitted(), "lea rax, [rip + 0x10]");
15681566}
15691567
15701568test "lower MR encoding" {
......@@ -1592,6 +1590,8 @@ test "lower MR encoding" {
15921590 code.emitted(),
15931591 "sub qword ptr [r11 + 0x10000000], r12",
15941592 );
1593 try lowerToMrEnc(.mov, RegisterOrMemory.rip(0x10), .r12, code.buffer());
1594 try expectEqualHexStrings("\x4C\x89\x25\x10\x00\x00\x00", code.emitted(), "mov qword ptr [rip + 0x10], r12");
15951595}
15961596
15971597test "lower OI encoding" {