Commit fb38e3d6b2
Changed files (3)
src
arch
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);
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,
});
}
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