aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2023-03-09 09:38:59 +0100
committerJakub Konka <kubkon@jakubkonka.com>2023-03-11 20:05:49 +0100
commitf61a70e812b0301f4e54e38ff4ce2b041f395e8d (patch)
tree6da2945145d580f4df1c868e4e6c1bffc72e2a20 /src
parentaa8fda799e64c02d44fe80d1297b5ec8ae6b7677 (diff)
downloadzig-f61a70e812b0301f4e54e38ff4ce2b041f395e8d.tar.gz
zig-f61a70e812b0301f4e54e38ff4ce2b041f395e8d.zip
x86_64: handle encoding and decoding Imm64 unsigned
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86_64/CodeGen.zig37
-rw-r--r--src/arch/x86_64/Emit.zig8
2 files changed, 24 insertions, 21 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index 6dacbadd8f..d6dd63ee57 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -417,7 +417,6 @@ fn asmRegister(self: *Self, tag: Mir.Inst.Tag, reg: Register) !void {
}
fn asmImmediate(self: *Self, tag: Mir.Inst.Tag, imm: Immediate) !void {
- // TODO imm64
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 },
@@ -443,7 +442,10 @@ fn asmRegisterRegister(self: *Self, tag: Mir.Inst.Tag, reg1: Register, reg2: Reg
}
fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Immediate) !void {
- const ops: Mir.Inst.Ops = if (imm == .signed) .ri_s else .ri_u;
+ const ops: Mir.Inst.Ops = switch (imm) {
+ .signed => .ri_s,
+ .unsigned => |x| if (x <= math.maxInt(u32)) .ri_u else .ri64,
+ };
const data: Mir.Inst.Data = switch (ops) {
.ri_s => .{ .ri_s = .{
.r1 = reg,
@@ -453,6 +455,10 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Imme
.r1 = reg,
.imm = @intCast(u32, imm.unsigned),
} },
+ .ri64 => .{ .rx = .{
+ .r1 = reg,
+ .payload = try self.addExtra(Mir.Imm64.encode(imm.unsigned)),
+ } },
else => unreachable,
};
_ = try self.addInst(.{
@@ -6118,32 +6124,23 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
// });
},
.immediate => |x| {
- // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit
- // register is the fastest way to zero a register.
if (x == 0) {
+ // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit
+ // register is the fastest way to zero a register.
return self.asmRegisterRegister(.xor, reg.to32(), reg.to32());
}
- if (x <= math.maxInt(i32)) {
- // Next best case: if we set the lower four bytes, the upper four will be zeroed.
+ if (ty.isSignedInt() and x <= math.maxInt(i32)) {
return self.asmRegisterImmediate(
.mov,
registerAlias(reg, abi_size),
- Immediate.u(@intCast(u32, x)),
+ Immediate.s(@intCast(i32, @bitCast(i64, x))),
);
}
- // Worst case: we need to load the 64-bit register with the IMM. GNU's assemblers calls
- // this `movabs`, though this is officially just a different variant of the plain `mov`
- // instruction.
- //
- // This encoding is, in fact, the *same* as the one used for 32-bit loads. The only
- // difference is that we set REX.W before the instruction, which extends the load to
- // 64-bit and uses the full bit-width of the register.
- // const payload = try self.addExtra(Mir.Imm64.encode(x));
- // _ = try self.addInst(.{
- // .tag = .movabs,
- // .ops = Mir.Inst.Ops.encode(.{ .reg1 = reg.to64() }),
- // .data = .{ .payload = payload },
- // });
+ return self.asmRegisterImmediate(
+ .mov,
+ registerAlias(reg, abi_size),
+ Immediate.u(x),
+ );
},
.register => |src_reg| {
// If the registers are the same, nothing to do.
diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig
index 15f41a943c..35b8b59846 100644
--- a/src/arch/x86_64/Emit.zig
+++ b/src/arch/x86_64/Emit.zig
@@ -178,9 +178,10 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE
if (mem.eql(u8, field.name, @tagName(tag))) break @field(Instruction.Mnemonic, field.name);
} else unreachable;
- var operands = [4]Instruction.Operand{ .none, .none, .none, .none };
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 };
switch (ops) {
.none => {},
.imm_s => operands[0] = .{ .imm = Immediate.s(data.imm_s) },
@@ -198,6 +199,11 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE
.{ .reg = data.ri_u.r1 },
.{ .imm = Immediate.u(data.ri_u.imm) },
},
+ .ri64 => {
+ operands[0] = .{ .reg = data.rx.r1 };
+ const imm64 = emit.mir.extraData(Mir.Imm64, data.rx.payload).data;
+ operands[1] = .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) };
+ },
else => unreachable,
}