authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-11 16:32:30+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-11 20:05:50+01:00
logfb38e3d6b29f71834c7ea4ef21e4d3f607c03777
tree468c8ba37e6fb648c0f138569fe8ea88c40342f3
parent0a8b5c20aa2402361a4e5698100902e47bd2c7c6

x86_64: simplify immediate handling at MIR level


3 files changed, 128 insertions(+), 146 deletions(-)

src/arch/x86_64/CodeGen.zig+34-43
......@@ -460,15 +460,13 @@ fn asmRegister(self: *Self, tag: Mir.Inst.Tag, reg: Register) !void {
460460
461461fn asmImmediate(self: *Self, tag: Mir.Inst.Tag, imm: Immediate) !void {
462462 const ops: Mir.Inst.Ops = if (imm == .signed) .imm_s else .imm_u;
463 const data: Mir.Inst.Data = switch (ops) {
464 .imm_s => .{ .imm_s = imm.signed },
465 .imm_u => .{ .imm_u = @intCast(u32, imm.unsigned) },
466 else => unreachable,
467 };
468463 _ = try self.addInst(.{
469464 .tag = tag,
470465 .ops = ops,
471 .data = data,
466 .data = .{ .imm = switch (imm) {
467 .signed => |x| @bitCast(u32, x),
468 .unsigned => |x| @intCast(u32, x),
469 } },
472470 });
473471}
474472
......@@ -489,11 +487,11 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Imme
489487 .unsigned => |x| if (x <= math.maxInt(u32)) .ri_u else .ri64,
490488 };
491489 const data: Mir.Inst.Data = switch (ops) {
492 .ri_s => .{ .ri_s = .{
490 .ri_s => .{ .ri = .{
493491 .r1 = reg,
494 .imm = imm.signed,
492 .imm = @bitCast(u32, imm.signed),
495493 } },
496 .ri_u => .{ .ri_u = .{
494 .ri_u => .{ .ri = .{
497495 .r1 = reg,
498496 .imm = @intCast(u32, imm.unsigned),
499497 } },
......@@ -522,12 +520,12 @@ fn asmRegisterRegisterImmediate(
522520 .unsigned => .rri_u,
523521 };
524522 const data: Mir.Inst.Data = switch (ops) {
525 .rri_s => .{ .rri_s = .{
523 .rri_s => .{ .rri = .{
526524 .r1 = reg1,
527525 .r2 = reg2,
528 .imm = imm.signed,
526 .imm = @bitCast(u32, imm.signed),
529527 } },
530 .rri_u => .{ .rri_u = .{
528 .rri_u => .{ .rri = .{
531529 .r1 = reg1,
532530 .r2 = reg2,
533531 .imm = @intCast(u32, imm.unsigned),
......@@ -547,11 +545,11 @@ fn asmMemory(self: *Self, tag: Mir.Inst.Tag, m: Memory) !void {
547545 .rip => .m_rip,
548546 else => unreachable,
549547 };
550 const data: Mir.Inst.Data = switch (ops) {
551 .m_sib => .{ .payload = try self.addExtra(Mir.MemorySib.encode(m)) },
552 .m_rip => .{ .payload = try self.addExtra(Mir.MemoryRip.encode(m)) },
548 const data: Mir.Inst.Data = .{ .payload = switch (ops) {
549 .m_sib => try self.addExtra(Mir.MemorySib.encode(m)),
550 .m_rip => try self.addExtra(Mir.MemoryRip.encode(m)),
553551 else => unreachable,
554 };
552 } };
555553 _ = try self.addInst(.{
556554 .tag = tag,
557555 .ops = ops,
......@@ -570,10 +568,11 @@ fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.Tag, m: Memory, imm: Immediate)
570568 .mi_s_rip, .mi_u_rip => try self.addExtra(Mir.MemoryRip.encode(m)),
571569 else => unreachable,
572570 };
573 const data: Mir.Inst.Data = switch (ops) {
574 .mi_s_sib, .mi_s_rip => .{ .xi_s = .{ .imm = imm.signed, .payload = payload } },
575 .mi_u_sib, .mi_u_rip => .{ .xi_u = .{ .imm = @intCast(u32, imm.unsigned), .payload = payload } },
576 else => unreachable,
571 const data: Mir.Inst.Data = .{
572 .xi = .{ .payload = payload, .imm = switch (imm) {
573 .signed => |x| @bitCast(u32, x),
574 .unsigned => |x| @intCast(u32, x),
575 } },
577576 };
578577 _ = try self.addInst(.{
579578 .tag = tag,
......@@ -588,16 +587,12 @@ fn asmRegisterMemory(self: *Self, tag: Mir.Inst.Tag, reg: Register, m: Memory) !
588587 .rip => .rm_rip,
589588 else => unreachable,
590589 };
591 const data: Mir.Inst.Data = switch (ops) {
592 .rm_sib => .{ .rx = .{
593 .r1 = reg,
594 .payload = try self.addExtra(Mir.MemorySib.encode(m)),
595 } },
596 .rm_rip => .{ .rx = .{
597 .r1 = reg,
598 .payload = try self.addExtra(Mir.MemoryRip.encode(m)),
590 const data: Mir.Inst.Data = .{
591 .rx = .{ .r1 = reg, .payload = switch (ops) {
592 .rm_sib => try self.addExtra(Mir.MemorySib.encode(m)),
593 .rm_rip => try self.addExtra(Mir.MemoryRip.encode(m)),
594 else => unreachable,
599595 } },
600 else => unreachable,
601596 };
602597 _ = try self.addInst(.{
603598 .tag = tag,
......@@ -612,16 +607,12 @@ fn asmMemoryRegister(self: *Self, tag: Mir.Inst.Tag, m: Memory, reg: Register) !
612607 .rip => .mr_rip,
613608 else => unreachable,
614609 };
615 const data: Mir.Inst.Data = switch (ops) {
616 .mr_sib => .{ .rx = .{
617 .r1 = reg,
618 .payload = try self.addExtra(Mir.MemorySib.encode(m)),
619 } },
620 .mr_rip => .{ .rx = .{
621 .r1 = reg,
622 .payload = try self.addExtra(Mir.MemoryRip.encode(m)),
610 const data: Mir.Inst.Data = .{
611 .rx = .{ .r1 = reg, .payload = switch (ops) {
612 .mr_sib => try self.addExtra(Mir.MemorySib.encode(m)),
613 .mr_rip => try self.addExtra(Mir.MemoryRip.encode(m)),
614 else => unreachable,
623615 } },
624 else => unreachable,
625616 };
626617 _ = try self.addInst(.{
627618 .tag = tag,
......@@ -733,7 +724,7 @@ fn gen(self: *Self) InnerError!void {
733724 self.mir_instructions.set(backpatch_stack_sub, .{
734725 .tag = .sub,
735726 .ops = .ri_u,
736 .data = .{ .ri_u = .{
727 .data = .{ .ri = .{
737728 .r1 = .rsp,
738729 .imm = aligned_stack_end,
739730 } },
......@@ -741,7 +732,7 @@ fn gen(self: *Self) InnerError!void {
741732 self.mir_instructions.set(backpatch_stack_add, .{
742733 .tag = .add,
743734 .ops = .ri_u,
744 .data = .{ .ri_u = .{
735 .data = .{ .ri = .{
745736 .r1 = .rsp,
746737 .imm = aligned_stack_end,
747738 } },
......@@ -5602,7 +5593,7 @@ fn genInlineMemcpy(
56025593 const loop_start = try self.addInst(.{
56035594 .tag = .cmp,
56045595 .ops = .ri_u,
5605 .data = .{ .ri_u = .{
5596 .data = .{ .ri = .{
56065597 .r1 = count_reg,
56075598 .imm = 0,
56085599 } },
......@@ -5681,9 +5672,9 @@ fn genInlineMemset(
56815672 const loop_start = try self.addInst(.{
56825673 .tag = .cmp,
56835674 .ops = .ri_s,
5684 .data = .{ .ri_s = .{
5675 .data = .{ .ri = .{
56855676 .r1 = index_reg,
5686 .imm = -1,
5677 .imm = @bitCast(u32, @as(i32, -1)),
56875678 } },
56885679 });
56895680 const loop_reloc = try self.asmJccReloc(undefined, .e);
src/arch/x86_64/Emit.zig+76-66
......@@ -194,105 +194,115 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE
194194 const ops = emit.mir.instructions.items(.ops)[inst];
195195 const data = emit.mir.instructions.items(.data)[inst];
196196
197 var operands = [4]Instruction.Operand{ .none, .none, .none, .none };
197 var op1: Instruction.Operand = .none;
198 var op2: Instruction.Operand = .none;
199 var op3: Instruction.Operand = .none;
200 var op4: Instruction.Operand = .none;
201
198202 switch (ops) {
199203 .none => {},
200 .imm_s => operands[0] = .{ .imm = Immediate.s(data.imm_s) },
201 .imm_u => operands[0] = .{ .imm = Immediate.u(data.imm_u) },
202 .r => operands[0] = .{ .reg = data.r },
203 .rr => operands[0..2].* = .{
204 .{ .reg = data.rr.r1 },
205 .{ .reg = data.rr.r2 },
206 },
207 .ri_s => operands[0..2].* = .{
208 .{ .reg = data.ri_s.r1 },
209 .{ .imm = Immediate.s(data.ri_s.imm) },
204 .imm_s => op1 = .{ .imm = Immediate.s(@bitCast(i32, data.imm)) },
205 .imm_u => op1 = .{ .imm = Immediate.u(data.imm) },
206 .r => op1 = .{ .reg = data.r },
207 .rr => {
208 op1 = .{ .reg = data.rr.r1 };
209 op2 = .{ .reg = data.rr.r2 };
210210 },
211 .ri_u => operands[0..2].* = .{
212 .{ .reg = data.ri_u.r1 },
213 .{ .imm = Immediate.u(data.ri_u.imm) },
211 .ri_s, .ri_u => {
212 const imm = switch (ops) {
213 .ri_s => Immediate.s(@bitCast(i32, data.ri.imm)),
214 .ri_u => Immediate.u(data.ri.imm),
215 else => unreachable,
216 };
217 op1 = .{ .reg = data.ri.r1 };
218 op2 = .{ .imm = imm };
214219 },
215220 .ri64 => {
216221 const imm64 = emit.mir.extraData(Mir.Imm64, data.rx.payload).data;
217 operands[0..2].* = .{
218 .{ .reg = data.rx.r1 },
219 .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) },
220 };
221 },
222 .rri_s => operands[0..3].* = .{
223 .{ .reg = data.rri_s.r1 },
224 .{ .reg = data.rri_s.r2 },
225 .{ .imm = Immediate.s(data.rri_s.imm) },
222 op1 = .{ .reg = data.rx.r1 };
223 op2 = .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) };
226224 },
227 .rri_u => operands[0..3].* = .{
228 .{ .reg = data.rri_u.r1 },
229 .{ .reg = data.rri_u.r2 },
230 .{ .imm = Immediate.u(data.rri_u.imm) },
225 .rri_s, .rri_u => {
226 const imm = switch (ops) {
227 .rri_s => Immediate.s(@bitCast(i32, data.rri.imm)),
228 .rri_u => Immediate.u(data.rri.imm),
229 else => unreachable,
230 };
231 op1 = .{ .reg = data.rri.r1 };
232 op2 = .{ .reg = data.rri.r2 };
233 op3 = .{ .imm = imm };
231234 },
232235 .m_sib => {
233236 const msib = emit.mir.extraData(Mir.MemorySib, data.payload).data;
234 operands[0] = .{ .mem = Mir.MemorySib.decode(msib) };
237 op1 = .{ .mem = Mir.MemorySib.decode(msib) };
235238 },
236239 .m_rip => {
237240 const mrip = emit.mir.extraData(Mir.MemoryRip, data.payload).data;
238 operands[0] = .{ .mem = Mir.MemoryRip.decode(mrip) };
239 },
240 .mi_u_sib => {
241 const msib = emit.mir.extraData(Mir.MemorySib, data.xi_u.payload).data;
242 operands[0..2].* = .{
243 .{ .mem = Mir.MemorySib.decode(msib) },
244 .{ .imm = Immediate.u(data.xi_u.imm) },
245 };
246 },
247 .mi_s_sib => {
248 const msib = emit.mir.extraData(Mir.MemorySib, data.xi_s.payload).data;
249 operands[0..2].* = .{
250 .{ .mem = Mir.MemorySib.decode(msib) },
251 .{ .imm = Immediate.s(data.xi_s.imm) },
252 };
241 op1 = .{ .mem = Mir.MemoryRip.decode(mrip) };
253242 },
254 .mi_u_rip => {
255 const mrip = emit.mir.extraData(Mir.MemoryRip, data.xi_u.payload).data;
256 operands[0..2].* = .{
257 .{ .mem = Mir.MemoryRip.decode(mrip) },
258 .{ .imm = Immediate.u(data.xi_u.imm) },
243 .mi_s_sib, .mi_u_sib => {
244 const msib = emit.mir.extraData(Mir.MemorySib, data.xi.payload).data;
245 const imm = switch (ops) {
246 .mi_s_sib => Immediate.s(@bitCast(i32, data.xi.imm)),
247 .mi_u_sib => Immediate.u(data.xi.imm),
248 else => unreachable,
259249 };
250 op1 = .{ .mem = Mir.MemorySib.decode(msib) };
251 op2 = .{ .imm = imm };
260252 },
261 .mi_s_rip => {
262 const mrip = emit.mir.extraData(Mir.MemoryRip, data.xi_s.payload).data;
263 operands[0..2].* = .{
264 .{ .mem = Mir.MemoryRip.decode(mrip) },
265 .{ .imm = Immediate.s(data.xi_s.imm) },
253 .mi_u_rip, .mi_s_rip => {
254 const mrip = emit.mir.extraData(Mir.MemoryRip, data.xi.payload).data;
255 const imm = switch (ops) {
256 .mi_s_rip => Immediate.s(@bitCast(i32, data.xi.imm)),
257 .mi_u_rip => Immediate.u(data.xi.imm),
258 else => unreachable,
266259 };
260 op1 = .{ .mem = Mir.MemoryRip.decode(mrip) };
261 op2 = .{ .imm = imm };
267262 },
268263 .rm_sib, .mr_sib => {
269264 const msib = emit.mir.extraData(Mir.MemorySib, data.rx.payload).data;
270 const op1 = .{ .reg = data.rx.r1 };
271 const op2 = .{ .mem = Mir.MemorySib.decode(msib) };
265 const op_r = .{ .reg = data.rx.r1 };
266 const op_m = .{ .mem = Mir.MemorySib.decode(msib) };
272267 switch (ops) {
273 .rm_sib => operands[0..2].* = .{ op1, op2 },
274 .mr_sib => operands[0..2].* = .{ op2, op1 },
268 .rm_sib => {
269 op1 = op_r;
270 op2 = op_m;
271 },
272 .mr_sib => {
273 op1 = op_m;
274 op2 = op_r;
275 },
275276 else => unreachable,
276277 }
277278 },
278279 .rm_rip, .mr_rip => {
279280 const mrip = emit.mir.extraData(Mir.MemoryRip, data.rx.payload).data;
280 const op1 = .{ .reg = data.rx.r1 };
281 const op2 = .{ .mem = Mir.MemoryRip.decode(mrip) };
281 const op_r = .{ .reg = data.rx.r1 };
282 const op_m = .{ .mem = Mir.MemoryRip.decode(mrip) };
282283 switch (ops) {
283 .rm_rip => operands[0..2].* = .{ op1, op2 },
284 .mr_rip => operands[0..2].* = .{ op2, op1 },
284 .rm_sib => {
285 op1 = op_r;
286 op2 = op_m;
287 },
288 .mr_sib => {
289 op1 = op_m;
290 op2 = op_r;
291 },
285292 else => unreachable,
286293 }
287294 },
288 else => unreachable, // TODO
295 else => return emit.fail("TODO handle generic encoding: {s}, {s}", .{
296 @tagName(mnemonic),
297 @tagName(ops),
298 }),
289299 }
290300
291301 return emit.encode(mnemonic, .{
292 .op1 = operands[0],
293 .op2 = operands[1],
294 .op3 = operands[2],
295 .op4 = operands[3],
302 .op1 = op1,
303 .op2 = op2,
304 .op3 = op3,
305 .op4 = op4,
296306 });
297307}
298308
src/arch/x86_64/Mir.zig+18-37
......@@ -182,10 +182,10 @@ pub const Inst = struct {
182182 /// Uses `rrr` payload.
183183 rrr,
184184 /// Register, register, immediate (sign-extended) operands.
185 /// Uses `rri_s` payload.
185 /// Uses `rri` payload.
186186 rri_s,
187187 /// Register, register, immediate (unsigned) operands.
188 /// Uses `rri_u` payload.
188 /// Uses `rri` payload.
189189 rri_u,
190190 /// Register with condition code (CC).
191191 /// Uses `r_c` payload.
......@@ -194,22 +194,22 @@ pub const Inst = struct {
194194 /// Uses `rr_c` payload.
195195 rr_c,
196196 /// Register, immediate (sign-extended) operands.
197 /// Uses `ri_s` payload.
197 /// Uses `ri` payload.
198198 ri_s,
199199 /// Register, immediate (unsigned) operands.
200 /// Uses `ri_u` payload.
200 /// Uses `ri` payload.
201201 ri_u,
202202 /// Register, 64-bit unsigned immediate operands.
203203 /// Uses `rx` payload with payload type `Imm64`.
204204 ri64,
205205 /// Immediate (sign-extended) operand.
206 /// Uses `imm_s` payload.
206 /// Uses `imm` payload.
207207 imm_s,
208208 /// Immediate (unsigned) operand.
209 /// Uses `imm_u` payload.
209 /// Uses `imm` payload.
210210 imm_u,
211211 /// Relative displacement operand.
212 /// Uses `rel` payload.
212 /// Uses `imm` payload.
213213 rel,
214214 /// Register, memory (SIB) operands.
215215 /// Uses `rx` payload.
......@@ -224,16 +224,16 @@ pub const Inst = struct {
224224 /// Uses `payload` with extra data of type `MemoryRip`.
225225 m_rip,
226226 /// Memory (SIB), immediate (unsigned) operands.
227 /// Uses `xi_u` payload with extra data of type `MemorySib`.
227 /// Uses `xi` payload with extra data of type `MemorySib`.
228228 mi_u_sib,
229229 /// Memory (RIP), immediate (unsigned) operands.
230 /// Uses `xi_u` payload with extra data of type `MemoryRip`.
230 /// Uses `xi` payload with extra data of type `MemoryRip`.
231231 mi_u_rip,
232232 /// Memory (SIB), immediate (sign-extend) operands.
233 /// Uses `xi_s` payload with extra data of type `MemorySib`.
233 /// Uses `xi` payload with extra data of type `MemorySib`.
234234 mi_s_sib,
235235 /// Memory (RIP), immediate (sign-extend) operands.
236 /// Uses `xi_s` payload with extra data of type `MemoryRip`.
236 /// Uses `xi` payload with extra data of type `MemoryRip`.
237237 mi_s_rip,
238238 /// Memory (SIB), register operands.
239239 /// Uses `rx` payload with extra data of type `MemorySib`.
......@@ -281,12 +281,8 @@ pub const Inst = struct {
281281 /// A condition code for use with EFLAGS register.
282282 cc: bits.Condition,
283283 },
284 /// A 32-bit signed immediate value.
285 imm_s: i32,
286 /// A 32-bit unsigned immediate value.
287 imm_u: u32,
288 /// A 32-bit signed relative offset value.
289 rel: i32,
284 /// A 32-bit immediate value.
285 imm: u32,
290286 r: Register,
291287 rr: struct {
292288 r1: Register,
......@@ -297,12 +293,7 @@ pub const Inst = struct {
297293 r2: Register,
298294 r3: Register,
299295 },
300 rri_s: struct {
301 r1: Register,
302 r2: Register,
303 imm: i32,
304 },
305 rri_u: struct {
296 rri: struct {
306297 r1: Register,
307298 r2: Register,
308299 imm: u32,
......@@ -318,13 +309,8 @@ pub const Inst = struct {
318309 r2: Register,
319310 cc: bits.Condition,
320311 },
321 /// Register, signed immediate.
322 ri_s: struct {
323 r1: Register,
324 imm: i32,
325 },
326 /// Register, unsigned immediate.
327 ri_u: struct {
312 /// Register, immediate.
313 ri: struct {
328314 r1: Register,
329315 imm: u32,
330316 },
......@@ -333,16 +319,11 @@ pub const Inst = struct {
333319 r1: Register,
334320 payload: u32,
335321 },
336 /// Custom payload followed by an unsigned immediate.
337 xi_u: struct {
322 /// Custom payload followed by an immediate.
323 xi: struct {
338324 payload: u32,
339325 imm: u32,
340326 },
341 /// Custom payload followed by a signed immediate.
342 xi_s: struct {
343 payload: u32,
344 imm: i32,
345 },
346327 /// Relocation for the linker where:
347328 /// * `atom_index` is the index of the source
348329 /// * `sym_index` is the index of the target