aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-06-07 19:10:26 +0200
committerJakub Konka <kubkon@jakubkonka.com>2022-06-07 19:33:43 +0200
commit76ad7af4d87982ef62876df2a2df7bbb2ac312e8 (patch)
tree728a86acc80780fc4e2af45121ace6b89049c679
parent03068ce6a67d2cf83954606dc96329b85bd4be1a (diff)
downloadzig-76ad7af4d87982ef62876df2a2df7bbb2ac312e8.tar.gz
zig-76ad7af4d87982ef62876df2a2df7bbb2ac312e8.zip
x64: pull common codepath between store and genSetStack into a helper
-rw-r--r--src/arch/x86_64/CodeGen.zig142
1 files changed, 63 insertions, 79 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index 839063e0e4..f4444d56a6 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -2738,46 +2738,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
}
},
.register => |src_reg| {
- const src_reg_lock = self.register_manager.lockReg(src_reg);
- defer if (src_reg_lock) |lock| self.register_manager.unlockReg(lock);
-
- // TODO common code-path with genSetStack, refactor!
- if (!math.isPowerOfTwo(abi_size)) {
- const tmp_reg = try self.copyToTmpRegister(value_ty, value);
-
- var next_offset: i32 = 0;
- var remainder = abi_size;
- while (remainder > 0) {
- const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder));
-
- _ = try self.addInst(.{
- .tag = .mov,
- .ops = Mir.Inst.Ops.encode(.{
- .reg1 = reg.to64(),
- .reg2 = registerAlias(tmp_reg, nearest_power_of_two),
- .flags = 0b10,
- }),
- .data = .{ .imm = @bitCast(u32, -next_offset) },
- });
-
- if (nearest_power_of_two > 1) {
- try self.genShiftBinOpMir(.shr, value_ty, tmp_reg, .{ .immediate = nearest_power_of_two * 8 });
- }
-
- remainder -= nearest_power_of_two;
- next_offset -= nearest_power_of_two;
- }
- } else {
- _ = try self.addInst(.{
- .tag = .mov,
- .ops = Mir.Inst.Ops.encode(.{
- .reg1 = reg.to64(),
- .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)),
- .flags = 0b10,
- }),
- .data = .{ .imm = 0 },
- });
- }
+ try self.genInlineMemcpyRegisterRegister(value_ty, reg, src_reg, 0);
},
.got_load,
.direct_load,
@@ -5638,45 +5599,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
return self.fail("TODO genSetStack for register for type float with no intrinsics", .{});
},
else => {
- if (!math.isPowerOfTwo(abi_size)) {
- const reg_lock = self.register_manager.lockReg(reg);
- defer if (reg_lock) |lock| self.register_manager.unlockReg(lock);
-
- const tmp_reg = try self.copyToTmpRegister(ty, mcv);
-
- var next_offset = stack_offset;
- var remainder = abi_size;
- while (remainder > 0) {
- const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder));
-
- _ = try self.addInst(.{
- .tag = .mov,
- .ops = Mir.Inst.Ops.encode(.{
- .reg1 = base_reg,
- .reg2 = registerAlias(tmp_reg, nearest_power_of_two),
- .flags = 0b10,
- }),
- .data = .{ .imm = @bitCast(u32, -next_offset) },
- });
-
- if (nearest_power_of_two > 1) {
- try self.genShiftBinOpMir(.shr, ty, tmp_reg, .{ .immediate = nearest_power_of_two * 8 });
- }
-
- remainder -= nearest_power_of_two;
- next_offset -= nearest_power_of_two;
- }
- } else {
- _ = try self.addInst(.{
- .tag = .mov,
- .ops = Mir.Inst.Ops.encode(.{
- .reg1 = base_reg,
- .reg2 = registerAlias(reg, @intCast(u32, abi_size)),
- .flags = 0b10,
- }),
- .data = .{ .imm = @bitCast(u32, -stack_offset) },
- });
- }
+ try self.genInlineMemcpyRegisterRegister(ty, base_reg, reg, stack_offset);
},
}
},
@@ -5711,6 +5634,67 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
}
}
+/// Like `genInlineMemcpy` but copies value from a register to an address via dereferencing
+/// of destination register.
+/// Boils down to MOV r/m64, r64.
+fn genInlineMemcpyRegisterRegister(
+ self: *Self,
+ ty: Type,
+ dst_reg: Register,
+ src_reg: Register,
+ offset: i32,
+) InnerError!void {
+ assert(dst_reg.size() == 64);
+
+ const dst_reg_lock = self.register_manager.lockReg(dst_reg);
+ defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
+
+ const src_reg_lock = self.register_manager.lockReg(src_reg);
+ defer if (src_reg_lock) |lock| self.register_manager.unlockReg(lock);
+
+ const abi_size = @intCast(u32, ty.abiSize(self.target.*));
+
+ // TODO common code-path with genSetStack, refactor!
+ if (!math.isPowerOfTwo(abi_size)) {
+ const tmp_reg = try self.copyToTmpRegister(ty, .{ .register = src_reg });
+
+ var next_offset = offset;
+ var remainder = abi_size;
+ while (remainder > 0) {
+ const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder));
+
+ _ = try self.addInst(.{
+ .tag = .mov,
+ .ops = Mir.Inst.Ops.encode(.{
+ .reg1 = dst_reg,
+ .reg2 = registerAlias(tmp_reg, nearest_power_of_two),
+ .flags = 0b10,
+ }),
+ .data = .{ .imm = @bitCast(u32, -next_offset) },
+ });
+
+ if (nearest_power_of_two > 1) {
+ try self.genShiftBinOpMir(.shr, ty, tmp_reg, .{
+ .immediate = nearest_power_of_two * 8,
+ });
+ }
+
+ remainder -= nearest_power_of_two;
+ next_offset -= nearest_power_of_two;
+ }
+ } else {
+ _ = try self.addInst(.{
+ .tag = .mov,
+ .ops = Mir.Inst.Ops.encode(.{
+ .reg1 = dst_reg,
+ .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)),
+ .flags = 0b10,
+ }),
+ .data = .{ .imm = @bitCast(u32, -offset) },
+ });
+ }
+}
+
const InlineMemcpyOpts = struct {
source_stack_base: ?Register = null,
dest_stack_base: ?Register = null,