mirror of
https://github.com/ziglang/zig.git
synced 2026-01-07 14:03:26 +00:00
x86_64: simplify immediate handling at MIR level
This commit is contained in:
parent
0a8b5c20aa
commit
fb38e3d6b2
@ -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)),
|
||||
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,
|
||||
} },
|
||||
.rm_rip => .{ .rx = .{
|
||||
.r1 = reg,
|
||||
.payload = try self.addExtra(Mir.MemoryRip.encode(m)),
|
||||
} },
|
||||
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)),
|
||||
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,
|
||||
} },
|
||||
.mr_rip => .{ .rx = .{
|
||||
.r1 = reg,
|
||||
.payload = try self.addExtra(Mir.MemoryRip.encode(m)),
|
||||
} },
|
||||
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);
|
||||
|
||||
@ -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 },
|
||||
.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_s => operands[0..2].* = .{
|
||||
.{ .reg = data.ri_s.r1 },
|
||||
.{ .imm = Immediate.s(data.ri_s.imm) },
|
||||
},
|
||||
.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)) },
|
||||
op1 = .{ .reg = data.rx.r1 };
|
||||
op2 = .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) };
|
||||
},
|
||||
.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,
|
||||
};
|
||||
},
|
||||
.rri_s => operands[0..3].* = .{
|
||||
.{ .reg = data.rri_s.r1 },
|
||||
.{ .reg = data.rri_s.r2 },
|
||||
.{ .imm = Immediate.s(data.rri_s.imm) },
|
||||
},
|
||||
.rri_u => operands[0..3].* = .{
|
||||
.{ .reg = data.rri_u.r1 },
|
||||
.{ .reg = data.rri_u.r2 },
|
||||
.{ .imm = Immediate.u(data.rri_u.imm) },
|
||||
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) };
|
||||
op1 = .{ .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, .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_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) },
|
||||
};
|
||||
},
|
||||
.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_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,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user