authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-13 09:56:17+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-13 13:30:24+02:00
logd25c93a868585e4e2f5941fcff15fa49c90510e9
tree191902004783169c5c4fadb5a50e4af5ab87793a
parentffcf0478fe646569465ac509b3e60faadd9b3697

x86_64: emit call rel32 for near calls with linker reloc


7 files changed, 138 insertions(+), 118 deletions(-)

src/arch/x86_64/CodeGen.zig+26-34
......@@ -1379,14 +1379,19 @@ fn asmImmediate(self: *Self, tag: Mir.Inst.FixedTag, imm: Immediate) !void {
13791379 .ops = switch (imm) {
13801380 .signed => .i_s,
13811381 .unsigned => .i_u,
1382 .reloc => .rel,
1383 },
1384 .data = switch (imm) {
1385 .reloc => |x| .{ .reloc = x },
1386 .signed, .unsigned => .{ .i = .{
1387 .fixes = tag[0],
1388 .i = switch (imm) {
1389 .signed => |s| @bitCast(s),
1390 .unsigned => |u| @intCast(u),
1391 .reloc => unreachable,
1392 },
1393 } },
13821394 },
1383 .data = .{ .i = .{
1384 .fixes = tag[0],
1385 .i = switch (imm) {
1386 .signed => |s| @bitCast(s),
1387 .unsigned => |u| @intCast(u),
1388 },
1389 } },
13901395 });
13911396}
13921397
......@@ -1406,6 +1411,7 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, imm:
14061411 const ops: Mir.Inst.Ops = switch (imm) {
14071412 .signed => .ri_s,
14081413 .unsigned => |u| if (math.cast(u32, u)) |_| .ri_u else .ri64,
1414 .reloc => unreachable,
14091415 };
14101416 _ = try self.addInst(.{
14111417 .tag = tag[1],
......@@ -1417,6 +1423,7 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, imm:
14171423 .i = switch (imm) {
14181424 .signed => |s| @bitCast(s),
14191425 .unsigned => |u| @intCast(u),
1426 .reloc => unreachable,
14201427 },
14211428 } },
14221429 .ri64 => .{ .rx = .{
......@@ -1488,6 +1495,7 @@ fn asmRegisterRegisterRegisterImmediate(
14881495 .i = switch (imm) {
14891496 .signed => |s| @bitCast(@as(i8, @intCast(s))),
14901497 .unsigned => |u| @intCast(u),
1498 .reloc => unreachable,
14911499 },
14921500 } },
14931501 });
......@@ -1505,6 +1513,7 @@ fn asmRegisterRegisterImmediate(
15051513 .ops = switch (imm) {
15061514 .signed => .rri_s,
15071515 .unsigned => .rri_u,
1516 .reloc => unreachable,
15081517 },
15091518 .data = .{ .rri = .{
15101519 .fixes = tag[0],
......@@ -1513,6 +1522,7 @@ fn asmRegisterRegisterImmediate(
15131522 .i = switch (imm) {
15141523 .signed => |s| @bitCast(s),
15151524 .unsigned => |u| @intCast(u),
1525 .reloc => unreachable,
15161526 },
15171527 } },
15181528 });
......@@ -1610,6 +1620,7 @@ fn asmRegisterMemoryImmediate(
16101620 if (switch (imm) {
16111621 .signed => |s| if (math.cast(i16, s)) |x| @as(u16, @bitCast(x)) else null,
16121622 .unsigned => |u| math.cast(u16, u),
1623 .reloc => unreachable,
16131624 }) |small_imm| {
16141625 _ = try self.addInst(.{
16151626 .tag = tag[1],
......@@ -1625,6 +1636,7 @@ fn asmRegisterMemoryImmediate(
16251636 const payload = try self.addExtra(Mir.Imm32{ .imm = switch (imm) {
16261637 .signed => |s| @bitCast(s),
16271638 .unsigned => unreachable,
1639 .reloc => unreachable,
16281640 } });
16291641 assert(payload + 1 == try self.addExtra(Mir.Memory.encode(m)));
16301642 _ = try self.addInst(.{
......@@ -1632,6 +1644,7 @@ fn asmRegisterMemoryImmediate(
16321644 .ops = switch (imm) {
16331645 .signed => .rmi_s,
16341646 .unsigned => .rmi_u,
1647 .reloc => unreachable,
16351648 },
16361649 .data = .{ .rx = .{
16371650 .fixes = tag[0],
......@@ -1679,6 +1692,7 @@ fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, imm: Immed
16791692 const payload = try self.addExtra(Mir.Imm32{ .imm = switch (imm) {
16801693 .signed => |s| @bitCast(s),
16811694 .unsigned => |u| @intCast(u),
1695 .reloc => unreachable,
16821696 } });
16831697 assert(payload + 1 == try self.addExtra(Mir.Memory.encode(m)));
16841698 _ = try self.addInst(.{
......@@ -1686,6 +1700,7 @@ fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, imm: Immed
16861700 .ops = switch (imm) {
16871701 .signed => .mi_s,
16881702 .unsigned => .mi_u,
1703 .reloc => unreachable,
16891704 },
16901705 .data = .{ .x = .{
16911706 .fixes = tag[0],
......@@ -12310,33 +12325,10 @@ fn genCall(self: *Self, info: union(enum) {
1231012325 if (self.bin_file.cast(.elf)) |elf_file| {
1231112326 const zo = elf_file.zigObjectPtr().?;
1231212327 const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);
12313 if (self.mod.pic) {
12314 const callee_reg: Register = switch (resolved_cc) {
12315 .SysV => callee: {
12316 if (!fn_info.is_var_args) break :callee .rax;
12317 const param_regs = abi.getCAbiIntParamRegs(resolved_cc);
12318 break :callee if (call_info.gp_count < param_regs.len)
12319 param_regs[call_info.gp_count]
12320 else
12321 .r10;
12322 },
12323 .Win64 => .rax,
12324 else => unreachable,
12325 };
12326 try self.genSetReg(
12327 callee_reg,
12328 Type.usize,
12329 .{ .lea_symbol = .{ .sym = sym_index } },
12330 .{},
12331 );
12332 try self.asmRegister(.{ ._, .call }, callee_reg);
12333 } else try self.asmMemory(.{ ._, .call }, .{
12334 .base = .{ .reloc = .{
12335 .atom_index = try self.owner.getSymbolIndex(self),
12336 .sym_index = sym_index,
12337 } },
12338 .mod = .{ .rm = .{ .size = .qword } },
12339 });
12328 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
12329 .atom_index = try self.owner.getSymbolIndex(self),
12330 .sym_index = sym_index,
12331 }));
1234012332 } else if (self.bin_file.cast(.coff)) |coff_file| {
1234112333 const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);
1234212334 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
src/arch/x86_64/Disassembler.zig+1-1
......@@ -8,7 +8,7 @@ const bits = @import("bits.zig");
88const encoder = @import("encoder.zig");
99
1010const Encoding = @import("Encoding.zig");
11const Immediate = bits.Immediate;
11const Immediate = Instruction.Immediate;
1212const Instruction = encoder.Instruction;
1313const LegacyPrefixes = encoder.LegacyPrefixes;
1414const Memory = Instruction.Memory;
src/arch/x86_64/Lower.zig+3-3
......@@ -475,7 +475,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
475475 .rrmi => inst.data.rrix.fixes,
476476 .mi_u, .mi_s => inst.data.x.fixes,
477477 .m => inst.data.x.fixes,
478 .extern_fn_reloc, .got_reloc, .direct_reloc, .import_reloc, .tlv_reloc => ._,
478 .extern_fn_reloc, .got_reloc, .direct_reloc, .import_reloc, .tlv_reloc, .rel => ._,
479479 else => return lower.fail("TODO lower .{s}", .{@tagName(inst.ops)}),
480480 };
481481 try lower.emit(switch (fixes) {
......@@ -607,7 +607,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
607607 .{ .mem = lower.mem(inst.data.rrix.payload) },
608608 .{ .imm = lower.imm(inst.ops, inst.data.rrix.i) },
609609 },
610 .extern_fn_reloc => &.{
610 .extern_fn_reloc, .rel => &.{
611611 .{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc }) },
612612 },
613613 .got_reloc, .direct_reloc, .import_reloc => ops: {
......@@ -650,7 +650,7 @@ const std = @import("std");
650650const Air = @import("../../Air.zig");
651651const Allocator = std.mem.Allocator;
652652const ErrorMsg = Zcu.ErrorMsg;
653const Immediate = bits.Immediate;
653const Immediate = Instruction.Immediate;
654654const Instruction = encoder.Instruction;
655655const Lower = @This();
656656const Memory = Instruction.Memory;
src/arch/x86_64/Mir.zig+1-1
......@@ -769,7 +769,7 @@ pub const Inst = struct {
769769 /// Uses `imm` payload.
770770 i_u,
771771 /// Relative displacement operand.
772 /// Uses `imm` payload.
772 /// Uses `reloc` payload.
773773 rel,
774774 /// Register, memory operands.
775775 /// Uses `rx` payload with extra data of type `Memory`.
src/arch/x86_64/bits.zig+13-32
......@@ -569,6 +569,7 @@ pub const Memory = struct {
569569pub const Immediate = union(enum) {
570570 signed: i32,
571571 unsigned: u64,
572 reloc: Symbol,
572573
573574 pub fn u(x: u64) Immediate {
574575 return .{ .unsigned = x };
......@@ -578,39 +579,19 @@ pub const Immediate = union(enum) {
578579 return .{ .signed = x };
579580 }
580581
581 pub fn asSigned(imm: Immediate, bit_size: u64) i64 {
582 return switch (imm) {
583 .signed => |x| switch (bit_size) {
584 1, 8 => @as(i8, @intCast(x)),
585 16 => @as(i16, @intCast(x)),
586 32, 64 => x,
587 else => unreachable,
588 },
589 .unsigned => |x| switch (bit_size) {
590 1, 8 => @as(i8, @bitCast(@as(u8, @intCast(x)))),
591 16 => @as(i16, @bitCast(@as(u16, @intCast(x)))),
592 32 => @as(i32, @bitCast(@as(u32, @intCast(x)))),
593 64 => @bitCast(x),
594 else => unreachable,
595 },
596 };
582 pub fn rel(symbol: Symbol) Immediate {
583 return .{ .reloc = symbol };
597584 }
598585
599 pub fn asUnsigned(imm: Immediate, bit_size: u64) u64 {
600 return switch (imm) {
601 .signed => |x| switch (bit_size) {
602 1, 8 => @as(u8, @bitCast(@as(i8, @intCast(x)))),
603 16 => @as(u16, @bitCast(@as(i16, @intCast(x)))),
604 32, 64 => @as(u32, @bitCast(x)),
605 else => unreachable,
606 },
607 .unsigned => |x| switch (bit_size) {
608 1, 8 => @as(u8, @intCast(x)),
609 16 => @as(u16, @intCast(x)),
610 32 => @as(u32, @intCast(x)),
611 64 => x,
612 else => unreachable,
613 },
614 };
586 pub fn format(
587 imm: Immediate,
588 comptime fmt: []const u8,
589 options: std.fmt.FormatOptions,
590 writer: anytype,
591 ) @TypeOf(writer).Error!void {
592 switch (imm) {
593 .reloc => |x| try std.fmt.formatType(x, fmt, options, writer, 0),
594 inline else => |x| try writer.print("{d}", .{x}),
595 }
615596 }
616597};
src/arch/x86_64/encoder.zig+91-43
......@@ -7,7 +7,6 @@ const testing = std.testing;
77const bits = @import("bits.zig");
88const Encoding = @import("Encoding.zig");
99const FrameIndex = bits.FrameIndex;
10const Immediate = bits.Immediate;
1110const Register = bits.Register;
1211const Symbol = bits.Symbol;
1312
......@@ -28,6 +27,55 @@ pub const Instruction = struct {
2827 repnz,
2928 };
3029
30 pub const Immediate = union(enum) {
31 signed: i32,
32 unsigned: u64,
33
34 pub fn u(x: u64) Immediate {
35 return .{ .unsigned = x };
36 }
37
38 pub fn s(x: i32) Immediate {
39 return .{ .signed = x };
40 }
41
42 pub fn asSigned(imm: Immediate, bit_size: u64) i64 {
43 return switch (imm) {
44 .signed => |x| switch (bit_size) {
45 1, 8 => @as(i8, @intCast(x)),
46 16 => @as(i16, @intCast(x)),
47 32, 64 => x,
48 else => unreachable,
49 },
50 .unsigned => |x| switch (bit_size) {
51 1, 8 => @as(i8, @bitCast(@as(u8, @intCast(x)))),
52 16 => @as(i16, @bitCast(@as(u16, @intCast(x)))),
53 32 => @as(i32, @bitCast(@as(u32, @intCast(x)))),
54 64 => @bitCast(x),
55 else => unreachable,
56 },
57 };
58 }
59
60 pub fn asUnsigned(imm: Immediate, bit_size: u64) u64 {
61 return switch (imm) {
62 .signed => |x| switch (bit_size) {
63 1, 8 => @as(u8, @bitCast(@as(i8, @intCast(x)))),
64 16 => @as(u16, @bitCast(@as(i16, @intCast(x)))),
65 32, 64 => @as(u32, @bitCast(x)),
66 else => unreachable,
67 },
68 .unsigned => |x| switch (bit_size) {
69 1, 8 => @as(u8, @intCast(x)),
70 16 => @as(u16, @intCast(x)),
71 32 => @as(u32, @intCast(x)),
72 64 => x,
73 else => unreachable,
74 },
75 };
76 }
77 };
78
3179 pub const Memory = union(enum) {
3280 sib: Sib,
3381 rip: Rip,
......@@ -1119,7 +1167,7 @@ test "encode" {
11191167
11201168 const inst = try Instruction.new(.none, .mov, &.{
11211169 .{ .reg = .rbx },
1122 .{ .imm = Immediate.u(4) },
1170 .{ .imm = Instruction.Immediate.u(4) },
11231171 });
11241172 try inst.encode(buf.writer(), .{});
11251173 try testing.expectEqualSlices(u8, &.{ 0x48, 0xc7, 0xc3, 0x4, 0x0, 0x0, 0x0 }, buf.items);
......@@ -1129,47 +1177,47 @@ test "lower I encoding" {
11291177 var enc = TestEncode{};
11301178
11311179 try enc.encode(.push, &.{
1132 .{ .imm = Immediate.u(0x10) },
1180 .{ .imm = Instruction.Immediate.u(0x10) },
11331181 });
11341182 try expectEqualHexStrings("\x6A\x10", enc.code(), "push 0x10");
11351183
11361184 try enc.encode(.push, &.{
1137 .{ .imm = Immediate.u(0x1000) },
1185 .{ .imm = Instruction.Immediate.u(0x1000) },
11381186 });
11391187 try expectEqualHexStrings("\x66\x68\x00\x10", enc.code(), "push 0x1000");
11401188
11411189 try enc.encode(.push, &.{
1142 .{ .imm = Immediate.u(0x10000000) },
1190 .{ .imm = Instruction.Immediate.u(0x10000000) },
11431191 });
11441192 try expectEqualHexStrings("\x68\x00\x00\x00\x10", enc.code(), "push 0x10000000");
11451193
11461194 try enc.encode(.adc, &.{
11471195 .{ .reg = .rax },
1148 .{ .imm = Immediate.u(0x10000000) },
1196 .{ .imm = Instruction.Immediate.u(0x10000000) },
11491197 });
11501198 try expectEqualHexStrings("\x48\x15\x00\x00\x00\x10", enc.code(), "adc rax, 0x10000000");
11511199
11521200 try enc.encode(.add, &.{
11531201 .{ .reg = .al },
1154 .{ .imm = Immediate.u(0x10) },
1202 .{ .imm = Instruction.Immediate.u(0x10) },
11551203 });
11561204 try expectEqualHexStrings("\x04\x10", enc.code(), "add al, 0x10");
11571205
11581206 try enc.encode(.add, &.{
11591207 .{ .reg = .rax },
1160 .{ .imm = Immediate.u(0x10) },
1208 .{ .imm = Instruction.Immediate.u(0x10) },
11611209 });
11621210 try expectEqualHexStrings("\x48\x83\xC0\x10", enc.code(), "add rax, 0x10");
11631211
11641212 try enc.encode(.sbb, &.{
11651213 .{ .reg = .ax },
1166 .{ .imm = Immediate.u(0x10) },
1214 .{ .imm = Instruction.Immediate.u(0x10) },
11671215 });
11681216 try expectEqualHexStrings("\x66\x1D\x10\x00", enc.code(), "sbb ax, 0x10");
11691217
11701218 try enc.encode(.xor, &.{
11711219 .{ .reg = .al },
1172 .{ .imm = Immediate.u(0x10) },
1220 .{ .imm = Instruction.Immediate.u(0x10) },
11731221 });
11741222 try expectEqualHexStrings("\x34\x10", enc.code(), "xor al, 0x10");
11751223}
......@@ -1179,43 +1227,43 @@ test "lower MI encoding" {
11791227
11801228 try enc.encode(.mov, &.{
11811229 .{ .reg = .r12 },
1182 .{ .imm = Immediate.u(0x1000) },
1230 .{ .imm = Instruction.Immediate.u(0x1000) },
11831231 });
11841232 try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");
11851233
11861234 try enc.encode(.mov, &.{
11871235 .{ .mem = Instruction.Memory.sib(.byte, .{ .base = .{ .reg = .r12 } }) },
1188 .{ .imm = Immediate.u(0x10) },
1236 .{ .imm = Instruction.Immediate.u(0x10) },
11891237 });
11901238 try expectEqualHexStrings("\x41\xC6\x04\x24\x10", enc.code(), "mov BYTE PTR [r12], 0x10");
11911239
11921240 try enc.encode(.mov, &.{
11931241 .{ .reg = .r12 },
1194 .{ .imm = Immediate.u(0x1000) },
1242 .{ .imm = Instruction.Immediate.u(0x1000) },
11951243 });
11961244 try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");
11971245
11981246 try enc.encode(.mov, &.{
11991247 .{ .reg = .r12 },
1200 .{ .imm = Immediate.u(0x1000) },
1248 .{ .imm = Instruction.Immediate.u(0x1000) },
12011249 });
12021250 try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");
12031251
12041252 try enc.encode(.mov, &.{
12051253 .{ .reg = .rax },
1206 .{ .imm = Immediate.u(0x10) },
1254 .{ .imm = Instruction.Immediate.u(0x10) },
12071255 });
12081256 try expectEqualHexStrings("\x48\xc7\xc0\x10\x00\x00\x00", enc.code(), "mov rax, 0x10");
12091257
12101258 try enc.encode(.mov, &.{
12111259 .{ .mem = Instruction.Memory.sib(.dword, .{ .base = .{ .reg = .r11 } }) },
1212 .{ .imm = Immediate.u(0x10) },
1260 .{ .imm = Instruction.Immediate.u(0x10) },
12131261 });
12141262 try expectEqualHexStrings("\x41\xc7\x03\x10\x00\x00\x00", enc.code(), "mov DWORD PTR [r11], 0x10");
12151263
12161264 try enc.encode(.mov, &.{
12171265 .{ .mem = Instruction.Memory.rip(.qword, 0x10) },
1218 .{ .imm = Immediate.u(0x10) },
1266 .{ .imm = Instruction.Immediate.u(0x10) },
12191267 });
12201268 try expectEqualHexStrings(
12211269 "\x48\xC7\x05\x10\x00\x00\x00\x10\x00\x00\x00",
......@@ -1225,19 +1273,19 @@ test "lower MI encoding" {
12251273
12261274 try enc.encode(.mov, &.{
12271275 .{ .mem = Instruction.Memory.sib(.qword, .{ .base = .{ .reg = .rbp }, .disp = -8 }) },
1228 .{ .imm = Immediate.u(0x10) },
1276 .{ .imm = Instruction.Immediate.u(0x10) },
12291277 });
12301278 try expectEqualHexStrings("\x48\xc7\x45\xf8\x10\x00\x00\x00", enc.code(), "mov QWORD PTR [rbp - 8], 0x10");
12311279
12321280 try enc.encode(.mov, &.{
12331281 .{ .mem = Instruction.Memory.sib(.word, .{ .base = .{ .reg = .rbp }, .disp = -2 }) },
1234 .{ .imm = Immediate.s(-16) },
1282 .{ .imm = Instruction.Immediate.s(-16) },
12351283 });
12361284 try expectEqualHexStrings("\x66\xC7\x45\xFE\xF0\xFF", enc.code(), "mov WORD PTR [rbp - 2], -16");
12371285
12381286 try enc.encode(.mov, &.{
12391287 .{ .mem = Instruction.Memory.sib(.byte, .{ .base = .{ .reg = .rbp }, .disp = -1 }) },
1240 .{ .imm = Immediate.u(0x10) },
1288 .{ .imm = Instruction.Immediate.u(0x10) },
12411289 });
12421290 try expectEqualHexStrings("\xC6\x45\xFF\x10", enc.code(), "mov BYTE PTR [rbp - 1], 0x10");
12431291
......@@ -1247,7 +1295,7 @@ test "lower MI encoding" {
12471295 .disp = 0x10000000,
12481296 .scale_index = .{ .scale = 2, .index = .rcx },
12491297 }) },
1250 .{ .imm = Immediate.u(0x10) },
1298 .{ .imm = Instruction.Immediate.u(0x10) },
12511299 });
12521300 try expectEqualHexStrings(
12531301 "\x48\xC7\x04\x4D\x00\x00\x00\x10\x10\x00\x00\x00",
......@@ -1257,43 +1305,43 @@ test "lower MI encoding" {
12571305
12581306 try enc.encode(.adc, &.{
12591307 .{ .mem = Instruction.Memory.sib(.byte, .{ .base = .{ .reg = .rbp }, .disp = -0x10 }) },
1260 .{ .imm = Immediate.u(0x10) },
1308 .{ .imm = Instruction.Immediate.u(0x10) },
12611309 });
12621310 try expectEqualHexStrings("\x80\x55\xF0\x10", enc.code(), "adc BYTE PTR [rbp - 0x10], 0x10");
12631311
12641312 try enc.encode(.adc, &.{
12651313 .{ .mem = Instruction.Memory.rip(.qword, 0) },
1266 .{ .imm = Immediate.u(0x10) },
1314 .{ .imm = Instruction.Immediate.u(0x10) },
12671315 });
12681316 try expectEqualHexStrings("\x48\x83\x15\x00\x00\x00\x00\x10", enc.code(), "adc QWORD PTR [rip], 0x10");
12691317
12701318 try enc.encode(.adc, &.{
12711319 .{ .reg = .rax },
1272 .{ .imm = Immediate.u(0x10) },
1320 .{ .imm = Instruction.Immediate.u(0x10) },
12731321 });
12741322 try expectEqualHexStrings("\x48\x83\xD0\x10", enc.code(), "adc rax, 0x10");
12751323
12761324 try enc.encode(.add, &.{
12771325 .{ .mem = Instruction.Memory.sib(.dword, .{ .base = .{ .reg = .rdx }, .disp = -8 }) },
1278 .{ .imm = Immediate.u(0x10) },
1326 .{ .imm = Instruction.Immediate.u(0x10) },
12791327 });
12801328 try expectEqualHexStrings("\x83\x42\xF8\x10", enc.code(), "add DWORD PTR [rdx - 8], 0x10");
12811329
12821330 try enc.encode(.add, &.{
12831331 .{ .reg = .rax },
1284 .{ .imm = Immediate.u(0x10) },
1332 .{ .imm = Instruction.Immediate.u(0x10) },
12851333 });
12861334 try expectEqualHexStrings("\x48\x83\xC0\x10", enc.code(), "add rax, 0x10");
12871335
12881336 try enc.encode(.add, &.{
12891337 .{ .mem = Instruction.Memory.sib(.qword, .{ .base = .{ .reg = .rbp }, .disp = -0x10 }) },
1290 .{ .imm = Immediate.s(-0x10) },
1338 .{ .imm = Instruction.Immediate.s(-0x10) },
12911339 });
12921340 try expectEqualHexStrings("\x48\x83\x45\xF0\xF0", enc.code(), "add QWORD PTR [rbp - 0x10], -0x10");
12931341
12941342 try enc.encode(.@"and", &.{
12951343 .{ .mem = Instruction.Memory.sib(.dword, .{ .base = .{ .reg = .ds }, .disp = 0x10000000 }) },
1296 .{ .imm = Immediate.u(0x10) },
1344 .{ .imm = Instruction.Immediate.u(0x10) },
12971345 });
12981346 try expectEqualHexStrings(
12991347 "\x83\x24\x25\x00\x00\x00\x10\x10",
......@@ -1303,7 +1351,7 @@ test "lower MI encoding" {
13031351
13041352 try enc.encode(.@"and", &.{
13051353 .{ .mem = Instruction.Memory.sib(.dword, .{ .base = .{ .reg = .es }, .disp = 0x10000000 }) },
1306 .{ .imm = Immediate.u(0x10) },
1354 .{ .imm = Instruction.Immediate.u(0x10) },
13071355 });
13081356 try expectEqualHexStrings(
13091357 "\x26\x83\x24\x25\x00\x00\x00\x10\x10",
......@@ -1313,7 +1361,7 @@ test "lower MI encoding" {
13131361
13141362 try enc.encode(.@"and", &.{
13151363 .{ .mem = Instruction.Memory.sib(.dword, .{ .base = .{ .reg = .r12 }, .disp = 0x10000000 }) },
1316 .{ .imm = Immediate.u(0x10) },
1364 .{ .imm = Instruction.Immediate.u(0x10) },
13171365 });
13181366 try expectEqualHexStrings(
13191367 "\x41\x83\xA4\x24\x00\x00\x00\x10\x10",
......@@ -1323,7 +1371,7 @@ test "lower MI encoding" {
13231371
13241372 try enc.encode(.sub, &.{
13251373 .{ .mem = Instruction.Memory.sib(.dword, .{ .base = .{ .reg = .r11 }, .disp = 0x10000000 }) },
1326 .{ .imm = Immediate.u(0x10) },
1374 .{ .imm = Instruction.Immediate.u(0x10) },
13271375 });
13281376 try expectEqualHexStrings(
13291377 "\x41\x83\xAB\x00\x00\x00\x10\x10",
......@@ -1542,14 +1590,14 @@ test "lower RMI encoding" {
15421590 try enc.encode(.imul, &.{
15431591 .{ .reg = .r11 },
15441592 .{ .reg = .r12 },
1545 .{ .imm = Immediate.s(-2) },
1593 .{ .imm = Instruction.Immediate.s(-2) },
15461594 });
15471595 try expectEqualHexStrings("\x4D\x6B\xDC\xFE", enc.code(), "imul r11, r12, -2");
15481596
15491597 try enc.encode(.imul, &.{
15501598 .{ .reg = .r11 },
15511599 .{ .mem = Instruction.Memory.rip(.qword, -16) },
1552 .{ .imm = Immediate.s(-1024) },
1600 .{ .imm = Instruction.Immediate.s(-1024) },
15531601 });
15541602 try expectEqualHexStrings(
15551603 "\x4C\x69\x1D\xF0\xFF\xFF\xFF\x00\xFC\xFF\xFF",
......@@ -1560,7 +1608,7 @@ test "lower RMI encoding" {
15601608 try enc.encode(.imul, &.{
15611609 .{ .reg = .bx },
15621610 .{ .mem = Instruction.Memory.sib(.word, .{ .base = .{ .reg = .rbp }, .disp = -16 }) },
1563 .{ .imm = Immediate.s(-1024) },
1611 .{ .imm = Instruction.Immediate.s(-1024) },
15641612 });
15651613 try expectEqualHexStrings(
15661614 "\x66\x69\x5D\xF0\x00\xFC",
......@@ -1571,7 +1619,7 @@ test "lower RMI encoding" {
15711619 try enc.encode(.imul, &.{
15721620 .{ .reg = .bx },
15731621 .{ .mem = Instruction.Memory.sib(.word, .{ .base = .{ .reg = .rbp }, .disp = -16 }) },
1574 .{ .imm = Immediate.u(1024) },
1622 .{ .imm = Instruction.Immediate.u(1024) },
15751623 });
15761624 try expectEqualHexStrings(
15771625 "\x66\x69\x5D\xF0\x00\x04",
......@@ -1687,7 +1735,7 @@ test "lower M encoding" {
16871735 try expectEqualHexStrings("\x65\xFF\x14\x25\x00\x00\x00\x00", enc.code(), "call gs:0x0");
16881736
16891737 try enc.encode(.call, &.{
1690 .{ .imm = Immediate.s(0) },
1738 .{ .imm = Instruction.Immediate.s(0) },
16911739 });
16921740 try expectEqualHexStrings("\xE8\x00\x00\x00\x00", enc.code(), "call 0x0");
16931741
......@@ -1746,7 +1794,7 @@ test "lower OI encoding" {
17461794
17471795 try enc.encode(.mov, &.{
17481796 .{ .reg = .rax },
1749 .{ .imm = Immediate.u(0x1000000000000000) },
1797 .{ .imm = Instruction.Immediate.u(0x1000000000000000) },
17501798 });
17511799 try expectEqualHexStrings(
17521800 "\x48\xB8\x00\x00\x00\x00\x00\x00\x00\x10",
......@@ -1756,7 +1804,7 @@ test "lower OI encoding" {
17561804
17571805 try enc.encode(.mov, &.{
17581806 .{ .reg = .r11 },
1759 .{ .imm = Immediate.u(0x1000000000000000) },
1807 .{ .imm = Instruction.Immediate.u(0x1000000000000000) },
17601808 });
17611809 try expectEqualHexStrings(
17621810 "\x49\xBB\x00\x00\x00\x00\x00\x00\x00\x10",
......@@ -1766,19 +1814,19 @@ test "lower OI encoding" {
17661814
17671815 try enc.encode(.mov, &.{
17681816 .{ .reg = .r11d },
1769 .{ .imm = Immediate.u(0x10000000) },
1817 .{ .imm = Instruction.Immediate.u(0x10000000) },
17701818 });
17711819 try expectEqualHexStrings("\x41\xBB\x00\x00\x00\x10", enc.code(), "mov r11d, 0x10000000");
17721820
17731821 try enc.encode(.mov, &.{
17741822 .{ .reg = .r11w },
1775 .{ .imm = Immediate.u(0x1000) },
1823 .{ .imm = Instruction.Immediate.u(0x1000) },
17761824 });
17771825 try expectEqualHexStrings("\x66\x41\xBB\x00\x10", enc.code(), "mov r11w, 0x1000");
17781826
17791827 try enc.encode(.mov, &.{
17801828 .{ .reg = .r11b },
1781 .{ .imm = Immediate.u(0x10) },
1829 .{ .imm = Instruction.Immediate.u(0x10) },
17821830 });
17831831 try expectEqualHexStrings("\x41\xB3\x10", enc.code(), "mov r11b, 0x10");
17841832}
......@@ -1900,7 +1948,7 @@ test "invalid instruction" {
19001948 .{ .reg = .r12d },
19011949 });
19021950 try invalidInstruction(.push, &.{
1903 .{ .imm = Immediate.u(0x1000000000000000) },
1951 .{ .imm = Instruction.Immediate.u(0x1000000000000000) },
19041952 });
19051953}
19061954
......@@ -2213,7 +2261,7 @@ const Assembler = struct {
22132261 .immediate => {
22142262 const is_neg = if (as.expect(.minus)) |_| true else |_| false;
22152263 const imm_tok = try as.expect(.numeral);
2216 const imm: Immediate = if (is_neg) blk: {
2264 const imm: Instruction.Immediate = if (is_neg) blk: {
22172265 const imm = try std.fmt.parseInt(i32, as.source(imm_tok), 0);
22182266 break :blk .{ .signed = imm * -1 };
22192267 } else .{ .unsigned = try std.fmt.parseInt(u64, as.source(imm_tok), 0) };
src/link/Elf/Atom.zig+3-4
......@@ -1215,12 +1215,11 @@ const x86_64 = struct {
12151215 );
12161216 },
12171217
1218 .PLT32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),
1219
1220 .PC32 => {
1218 .PLT32 => {
12211219 const S_ = if (target.flags.zig_jump_table) ZJT else S;
12221220 try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);
12231221 },
1222 .PC32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),
12241223
12251224 .GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little),
12261225 .GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little),
......@@ -1620,7 +1619,7 @@ const x86_64 = struct {
16201619 const bits = @import("../../arch/x86_64/bits.zig");
16211620 const encoder = @import("../../arch/x86_64/encoder.zig");
16221621 const Disassembler = @import("../../arch/x86_64/Disassembler.zig");
1623 const Immediate = bits.Immediate;
1622 const Immediate = Instruction.Immediate;
16241623 const Instruction = encoder.Instruction;
16251624};
16261625