diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-11 16:32:30 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-11 20:05:50 +0100 |
| commit | fb38e3d6b29f71834c7ea4ef21e4d3f607c03777 (patch) | |
| tree | 468c8ba37e6fb648c0f138569fe8ea88c40342f3 /src | |
| parent | 0a8b5c20aa2402361a4e5698100902e47bd2c7c6 (diff) | |
| download | zig-fb38e3d6b29f71834c7ea4ef21e4d3f607c03777.tar.gz zig-fb38e3d6b29f71834c7ea4ef21e4d3f607c03777.zip | |
x86_64: simplify immediate handling at MIR level
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 77 | ||||
| -rw-r--r-- | src/arch/x86_64/Emit.zig | 142 | ||||
| -rw-r--r-- | src/arch/x86_64/Mir.zig | 55 |
3 files changed, 128 insertions, 146 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 21c7adec3c..df06b90e4a 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -460,15 +460,13 @@ fn asmRegister(self: *Self, tag: Mir.Inst.Tag, reg: Register) !void { fn asmImmediate(self: *Self, tag: Mir.Inst.Tag, imm: Immediate) !void { const ops: Mir.Inst.Ops = if (imm == .signed) .imm_s else .imm_u; - const data: Mir.Inst.Data = switch (ops) { - .imm_s => .{ .imm_s = imm.signed }, - .imm_u => .{ .imm_u = @intCast(u32, imm.unsigned) }, - else => unreachable, - }; _ = try self.addInst(.{ .tag = tag, .ops = ops, - .data = data, + .data = .{ .imm = switch (imm) { + .signed => |x| @bitCast(u32, x), + .unsigned => |x| @intCast(u32, x), + } }, }); } @@ -489,11 +487,11 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Imme .unsigned => |x| if (x <= math.maxInt(u32)) .ri_u else .ri64, }; const data: Mir.Inst.Data = switch (ops) { - .ri_s => .{ .ri_s = .{ + .ri_s => .{ .ri = .{ .r1 = reg, - .imm = imm.signed, + .imm = @bitCast(u32, imm.signed), } }, - .ri_u => .{ .ri_u = .{ + .ri_u => .{ .ri = .{ .r1 = reg, .imm = @intCast(u32, imm.unsigned), } }, @@ -522,12 +520,12 @@ fn asmRegisterRegisterImmediate( .unsigned => .rri_u, }; const data: Mir.Inst.Data = switch (ops) { - .rri_s => .{ .rri_s = .{ + .rri_s => .{ .rri = .{ .r1 = reg1, .r2 = reg2, - .imm = imm.signed, + .imm = @bitCast(u32, imm.signed), } }, - .rri_u => .{ .rri_u = .{ + .rri_u => .{ .rri = .{ .r1 = reg1, .r2 = reg2, .imm = @intCast(u32, imm.unsigned), @@ -547,11 +545,11 @@ fn asmMemory(self: *Self, tag: Mir.Inst.Tag, m: Memory) !void { .rip => .m_rip, else => unreachable, }; - const data: Mir.Inst.Data = switch (ops) { - .m_sib => .{ .payload = try self.addExtra(Mir.MemorySib.encode(m)) }, - .m_rip => .{ .payload = try self.addExtra(Mir.MemoryRip.encode(m)) }, + const data: Mir.Inst.Data = .{ .payload = switch (ops) { + .m_sib => try self.addExtra(Mir.MemorySib.encode(m)), + .m_rip => try self.addExtra(Mir.MemoryRip.encode(m)), else => unreachable, - }; + } }; _ = try self.addInst(.{ .tag = tag, .ops = ops, @@ -570,10 +568,11 @@ fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.Tag, m: Memory, imm: Immediate) .mi_s_rip, .mi_u_rip => try self.addExtra(Mir.MemoryRip.encode(m)), else => unreachable, }; - const data: Mir.Inst.Data = switch (ops) { - .mi_s_sib, .mi_s_rip => .{ .xi_s = .{ .imm = imm.signed, .payload = payload } }, - .mi_u_sib, .mi_u_rip => .{ .xi_u = .{ .imm = @intCast(u32, imm.unsigned), .payload = payload } }, - else => unreachable, + const data: Mir.Inst.Data = .{ + .xi = .{ .payload = payload, .imm = switch (imm) { + .signed => |x| @bitCast(u32, x), + .unsigned => |x| @intCast(u32, x), + } }, }; _ = try self.addInst(.{ .tag = tag, @@ -588,16 +587,12 @@ fn asmRegisterMemory(self: *Self, tag: Mir.Inst.Tag, reg: Register, m: Memory) ! .rip => .rm_rip, else => unreachable, }; - const data: Mir.Inst.Data = switch (ops) { - .rm_sib => .{ .rx = .{ - .r1 = reg, - .payload = try self.addExtra(Mir.MemorySib.encode(m)), - } }, - .rm_rip => .{ .rx = .{ - .r1 = reg, - .payload = try self.addExtra(Mir.MemoryRip.encode(m)), + const data: Mir.Inst.Data = .{ + .rx = .{ .r1 = reg, .payload = switch (ops) { + .rm_sib => try self.addExtra(Mir.MemorySib.encode(m)), + .rm_rip => try self.addExtra(Mir.MemoryRip.encode(m)), + else => unreachable, } }, - else => unreachable, }; _ = try self.addInst(.{ .tag = tag, @@ -612,16 +607,12 @@ fn asmMemoryRegister(self: *Self, tag: Mir.Inst.Tag, m: Memory, reg: Register) ! .rip => .mr_rip, else => unreachable, }; - const data: Mir.Inst.Data = switch (ops) { - .mr_sib => .{ .rx = .{ - .r1 = reg, - .payload = try self.addExtra(Mir.MemorySib.encode(m)), - } }, - .mr_rip => .{ .rx = .{ - .r1 = reg, - .payload = try self.addExtra(Mir.MemoryRip.encode(m)), + const data: Mir.Inst.Data = .{ + .rx = .{ .r1 = reg, .payload = switch (ops) { + .mr_sib => try self.addExtra(Mir.MemorySib.encode(m)), + .mr_rip => try self.addExtra(Mir.MemoryRip.encode(m)), + else => unreachable, } }, - else => unreachable, }; _ = try self.addInst(.{ .tag = tag, @@ -733,7 +724,7 @@ fn gen(self: *Self) InnerError!void { self.mir_instructions.set(backpatch_stack_sub, .{ .tag = .sub, .ops = .ri_u, - .data = .{ .ri_u = .{ + .data = .{ .ri = .{ .r1 = .rsp, .imm = aligned_stack_end, } }, @@ -741,7 +732,7 @@ fn gen(self: *Self) InnerError!void { self.mir_instructions.set(backpatch_stack_add, .{ .tag = .add, .ops = .ri_u, - .data = .{ .ri_u = .{ + .data = .{ .ri = .{ .r1 = .rsp, .imm = aligned_stack_end, } }, @@ -5602,7 +5593,7 @@ fn genInlineMemcpy( const loop_start = try self.addInst(.{ .tag = .cmp, .ops = .ri_u, - .data = .{ .ri_u = .{ + .data = .{ .ri = .{ .r1 = count_reg, .imm = 0, } }, @@ -5681,9 +5672,9 @@ fn genInlineMemset( const loop_start = try self.addInst(.{ .tag = .cmp, .ops = .ri_s, - .data = .{ .ri_s = .{ + .data = .{ .ri = .{ .r1 = index_reg, - .imm = -1, + .imm = @bitCast(u32, @as(i32, -1)), } }, }); const loop_reloc = try self.asmJccReloc(undefined, .e); diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index 161c436323..5a7f2ef224 100644 --- a/src/arch/x86_64/Emit.zig +++ b/src/arch/x86_64/Emit.zig @@ -194,105 +194,115 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE const ops = emit.mir.instructions.items(.ops)[inst]; const data = emit.mir.instructions.items(.data)[inst]; - var operands = [4]Instruction.Operand{ .none, .none, .none, .none }; + var op1: Instruction.Operand = .none; + var op2: Instruction.Operand = .none; + var op3: Instruction.Operand = .none; + var op4: Instruction.Operand = .none; + switch (ops) { .none => {}, - .imm_s => operands[0] = .{ .imm = Immediate.s(data.imm_s) }, - .imm_u => operands[0] = .{ .imm = Immediate.u(data.imm_u) }, - .r => operands[0] = .{ .reg = data.r }, - .rr => operands[0..2].* = .{ - .{ .reg = data.rr.r1 }, - .{ .reg = data.rr.r2 }, - }, - .ri_s => operands[0..2].* = .{ - .{ .reg = data.ri_s.r1 }, - .{ .imm = Immediate.s(data.ri_s.imm) }, + .imm_s => op1 = .{ .imm = Immediate.s(@bitCast(i32, data.imm)) }, + .imm_u => op1 = .{ .imm = Immediate.u(data.imm) }, + .r => op1 = .{ .reg = data.r }, + .rr => { + op1 = .{ .reg = data.rr.r1 }; + op2 = .{ .reg = data.rr.r2 }; }, - .ri_u => operands[0..2].* = .{ - .{ .reg = data.ri_u.r1 }, - .{ .imm = Immediate.u(data.ri_u.imm) }, + .ri_s, .ri_u => { + const imm = switch (ops) { + .ri_s => Immediate.s(@bitCast(i32, data.ri.imm)), + .ri_u => Immediate.u(data.ri.imm), + else => unreachable, + }; + op1 = .{ .reg = data.ri.r1 }; + op2 = .{ .imm = imm }; }, .ri64 => { const imm64 = emit.mir.extraData(Mir.Imm64, data.rx.payload).data; - operands[0..2].* = .{ - .{ .reg = data.rx.r1 }, - .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) }, - }; - }, - .rri_s => operands[0..3].* = .{ - .{ .reg = data.rri_s.r1 }, - .{ .reg = data.rri_s.r2 }, - .{ .imm = Immediate.s(data.rri_s.imm) }, + op1 = .{ .reg = data.rx.r1 }; + op2 = .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) }; }, - .rri_u => operands[0..3].* = .{ - .{ .reg = data.rri_u.r1 }, - .{ .reg = data.rri_u.r2 }, - .{ .imm = Immediate.u(data.rri_u.imm) }, + .rri_s, .rri_u => { + const imm = switch (ops) { + .rri_s => Immediate.s(@bitCast(i32, data.rri.imm)), + .rri_u => Immediate.u(data.rri.imm), + else => unreachable, + }; + op1 = .{ .reg = data.rri.r1 }; + op2 = .{ .reg = data.rri.r2 }; + op3 = .{ .imm = imm }; }, .m_sib => { const msib = emit.mir.extraData(Mir.MemorySib, data.payload).data; - operands[0] = .{ .mem = Mir.MemorySib.decode(msib) }; + op1 = .{ .mem = Mir.MemorySib.decode(msib) }; }, .m_rip => { const mrip = emit.mir.extraData(Mir.MemoryRip, data.payload).data; - operands[0] = .{ .mem = Mir.MemoryRip.decode(mrip) }; - }, - .mi_u_sib => { - const msib = emit.mir.extraData(Mir.MemorySib, data.xi_u.payload).data; - operands[0..2].* = .{ - .{ .mem = Mir.MemorySib.decode(msib) }, - .{ .imm = Immediate.u(data.xi_u.imm) }, - }; - }, - .mi_s_sib => { - const msib = emit.mir.extraData(Mir.MemorySib, data.xi_s.payload).data; - operands[0..2].* = .{ - .{ .mem = Mir.MemorySib.decode(msib) }, - .{ .imm = Immediate.s(data.xi_s.imm) }, - }; + op1 = .{ .mem = Mir.MemoryRip.decode(mrip) }; }, - .mi_u_rip => { - const mrip = emit.mir.extraData(Mir.MemoryRip, data.xi_u.payload).data; - operands[0..2].* = .{ - .{ .mem = Mir.MemoryRip.decode(mrip) }, - .{ .imm = Immediate.u(data.xi_u.imm) }, + .mi_s_sib, .mi_u_sib => { + const msib = emit.mir.extraData(Mir.MemorySib, data.xi.payload).data; + const imm = switch (ops) { + .mi_s_sib => Immediate.s(@bitCast(i32, data.xi.imm)), + .mi_u_sib => Immediate.u(data.xi.imm), + else => unreachable, }; + op1 = .{ .mem = Mir.MemorySib.decode(msib) }; + op2 = .{ .imm = imm }; }, - .mi_s_rip => { - const mrip = emit.mir.extraData(Mir.MemoryRip, data.xi_s.payload).data; - operands[0..2].* = .{ - .{ .mem = Mir.MemoryRip.decode(mrip) }, - .{ .imm = Immediate.s(data.xi_s.imm) }, + .mi_u_rip, .mi_s_rip => { + const mrip = emit.mir.extraData(Mir.MemoryRip, data.xi.payload).data; + const imm = switch (ops) { + .mi_s_rip => Immediate.s(@bitCast(i32, data.xi.imm)), + .mi_u_rip => Immediate.u(data.xi.imm), + else => unreachable, }; + op1 = .{ .mem = Mir.MemoryRip.decode(mrip) }; + op2 = .{ .imm = imm }; }, .rm_sib, .mr_sib => { const msib = emit.mir.extraData(Mir.MemorySib, data.rx.payload).data; - const op1 = .{ .reg = data.rx.r1 }; - const op2 = .{ .mem = Mir.MemorySib.decode(msib) }; + const op_r = .{ .reg = data.rx.r1 }; + const op_m = .{ .mem = Mir.MemorySib.decode(msib) }; switch (ops) { - .rm_sib => operands[0..2].* = .{ op1, op2 }, - .mr_sib => operands[0..2].* = .{ op2, op1 }, + .rm_sib => { + op1 = op_r; + op2 = op_m; + }, + .mr_sib => { + op1 = op_m; + op2 = op_r; + }, else => unreachable, } }, .rm_rip, .mr_rip => { const mrip = emit.mir.extraData(Mir.MemoryRip, data.rx.payload).data; - const op1 = .{ .reg = data.rx.r1 }; - const op2 = .{ .mem = Mir.MemoryRip.decode(mrip) }; + const op_r = .{ .reg = data.rx.r1 }; + const op_m = .{ .mem = Mir.MemoryRip.decode(mrip) }; switch (ops) { - .rm_rip => operands[0..2].* = .{ op1, op2 }, - .mr_rip => operands[0..2].* = .{ op2, op1 }, + .rm_sib => { + op1 = op_r; + op2 = op_m; + }, + .mr_sib => { + op1 = op_m; + op2 = op_r; + }, else => unreachable, } }, - else => unreachable, // TODO + else => return emit.fail("TODO handle generic encoding: {s}, {s}", .{ + @tagName(mnemonic), + @tagName(ops), + }), } return emit.encode(mnemonic, .{ - .op1 = operands[0], - .op2 = operands[1], - .op3 = operands[2], - .op4 = operands[3], + .op1 = op1, + .op2 = op2, + .op3 = op3, + .op4 = op4, }); } diff --git a/src/arch/x86_64/Mir.zig b/src/arch/x86_64/Mir.zig index 4cde4dd240..2f611258fd 100644 --- a/src/arch/x86_64/Mir.zig +++ b/src/arch/x86_64/Mir.zig @@ -182,10 +182,10 @@ pub const Inst = struct { /// Uses `rrr` payload. rrr, /// Register, register, immediate (sign-extended) operands. - /// Uses `rri_s` payload. + /// Uses `rri` payload. rri_s, /// Register, register, immediate (unsigned) operands. - /// Uses `rri_u` payload. + /// Uses `rri` payload. rri_u, /// Register with condition code (CC). /// Uses `r_c` payload. @@ -194,22 +194,22 @@ pub const Inst = struct { /// Uses `rr_c` payload. rr_c, /// Register, immediate (sign-extended) operands. - /// Uses `ri_s` payload. + /// Uses `ri` payload. ri_s, /// Register, immediate (unsigned) operands. - /// Uses `ri_u` payload. + /// Uses `ri` payload. ri_u, /// Register, 64-bit unsigned immediate operands. /// Uses `rx` payload with payload type `Imm64`. ri64, /// Immediate (sign-extended) operand. - /// Uses `imm_s` payload. + /// Uses `imm` payload. imm_s, /// Immediate (unsigned) operand. - /// Uses `imm_u` payload. + /// Uses `imm` payload. imm_u, /// Relative displacement operand. - /// Uses `rel` payload. + /// Uses `imm` payload. rel, /// Register, memory (SIB) operands. /// Uses `rx` payload. @@ -224,16 +224,16 @@ pub const Inst = struct { /// Uses `payload` with extra data of type `MemoryRip`. m_rip, /// Memory (SIB), immediate (unsigned) operands. - /// Uses `xi_u` payload with extra data of type `MemorySib`. + /// Uses `xi` payload with extra data of type `MemorySib`. mi_u_sib, /// Memory (RIP), immediate (unsigned) operands. - /// Uses `xi_u` payload with extra data of type `MemoryRip`. + /// Uses `xi` payload with extra data of type `MemoryRip`. mi_u_rip, /// Memory (SIB), immediate (sign-extend) operands. - /// Uses `xi_s` payload with extra data of type `MemorySib`. + /// Uses `xi` payload with extra data of type `MemorySib`. mi_s_sib, /// Memory (RIP), immediate (sign-extend) operands. - /// Uses `xi_s` payload with extra data of type `MemoryRip`. + /// Uses `xi` payload with extra data of type `MemoryRip`. mi_s_rip, /// Memory (SIB), register operands. /// Uses `rx` payload with extra data of type `MemorySib`. @@ -281,12 +281,8 @@ pub const Inst = struct { /// A condition code for use with EFLAGS register. cc: bits.Condition, }, - /// A 32-bit signed immediate value. - imm_s: i32, - /// A 32-bit unsigned immediate value. - imm_u: u32, - /// A 32-bit signed relative offset value. - rel: i32, + /// A 32-bit immediate value. + imm: u32, r: Register, rr: struct { r1: Register, @@ -297,12 +293,7 @@ pub const Inst = struct { r2: Register, r3: Register, }, - rri_s: struct { - r1: Register, - r2: Register, - imm: i32, - }, - rri_u: struct { + rri: struct { r1: Register, r2: Register, imm: u32, @@ -318,13 +309,8 @@ pub const Inst = struct { r2: Register, cc: bits.Condition, }, - /// Register, signed immediate. - ri_s: struct { - r1: Register, - imm: i32, - }, - /// Register, unsigned immediate. - ri_u: struct { + /// Register, immediate. + ri: struct { r1: Register, imm: u32, }, @@ -333,16 +319,11 @@ pub const Inst = struct { r1: Register, payload: u32, }, - /// Custom payload followed by an unsigned immediate. - xi_u: struct { + /// Custom payload followed by an immediate. + xi: struct { payload: u32, imm: u32, }, - /// Custom payload followed by a signed immediate. - xi_s: struct { - payload: u32, - imm: i32, - }, /// Relocation for the linker where: /// * `atom_index` is the index of the source /// * `sym_index` is the index of the target |
