| ... | @@ -2738,46 +2738,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2738,46 +2738,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2738 | } | 2738 | } |
| 2739 | }, | 2739 | }, |
| 2740 | .register => |src_reg| { | 2740 | .register => |src_reg| { |
| 2741 | const src_reg_lock = self.register_manager.lockReg(src_reg); | 2741 | try self.genInlineMemcpyRegisterRegister(value_ty, reg, src_reg, 0); |
| 2742 | defer if (src_reg_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 2743 | | | |
| 2744 | // TODO common code-path with genSetStack, refactor! | | |
| 2745 | if (!math.isPowerOfTwo(abi_size)) { | | |
| 2746 | const tmp_reg = try self.copyToTmpRegister(value_ty, value); | | |
| 2747 | | | |
| 2748 | var next_offset: i32 = 0; | | |
| 2749 | var remainder = abi_size; | | |
| 2750 | while (remainder > 0) { | | |
| 2751 | const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder)); | | |
| 2752 | | | |
| 2753 | _ = try self.addInst(.{ | | |
| 2754 | .tag = .mov, | | |
| 2755 | .ops = Mir.Inst.Ops.encode(.{ | | |
| 2756 | .reg1 = reg.to64(), | | |
| 2757 | .reg2 = registerAlias(tmp_reg, nearest_power_of_two), | | |
| 2758 | .flags = 0b10, | | |
| 2759 | }), | | |
| 2760 | .data = .{ .imm = @bitCast(u32, -next_offset) }, | | |
| 2761 | }); | | |
| 2762 | | | |
| 2763 | if (nearest_power_of_two > 1) { | | |
| 2764 | try self.genShiftBinOpMir(.shr, value_ty, tmp_reg, .{ .immediate = nearest_power_of_two * 8 }); | | |
| 2765 | } | | |
| 2766 | | | |
| 2767 | remainder -= nearest_power_of_two; | | |
| 2768 | next_offset -= nearest_power_of_two; | | |
| 2769 | } | | |
| 2770 | } else { | | |
| 2771 | _ = try self.addInst(.{ | | |
| 2772 | .tag = .mov, | | |
| 2773 | .ops = Mir.Inst.Ops.encode(.{ | | |
| 2774 | .reg1 = reg.to64(), | | |
| 2775 | .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)), | | |
| 2776 | .flags = 0b10, | | |
| 2777 | }), | | |
| 2778 | .data = .{ .imm = 0 }, | | |
| 2779 | }); | | |
| 2780 | } | | |
| 2781 | }, | 2742 | }, |
| 2782 | .got_load, | 2743 | .got_load, |
| 2783 | .direct_load, | 2744 | .direct_load, |
| ... | @@ -5638,45 +5599,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl | ... | @@ -5638,45 +5599,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5638 | return self.fail("TODO genSetStack for register for type float with no intrinsics", .{}); | 5599 | return self.fail("TODO genSetStack for register for type float with no intrinsics", .{}); |
| 5639 | }, | 5600 | }, |
| 5640 | else => { | 5601 | else => { |
| 5641 | if (!math.isPowerOfTwo(abi_size)) { | 5602 | try self.genInlineMemcpyRegisterRegister(ty, base_reg, reg, stack_offset); |
| 5642 | const reg_lock = self.register_manager.lockReg(reg); | | |
| 5643 | defer if (reg_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 5644 | | | |
| 5645 | const tmp_reg = try self.copyToTmpRegister(ty, mcv); | | |
| 5646 | | | |
| 5647 | var next_offset = stack_offset; | | |
| 5648 | var remainder = abi_size; | | |
| 5649 | while (remainder > 0) { | | |
| 5650 | const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder)); | | |
| 5651 | | | |
| 5652 | _ = try self.addInst(.{ | | |
| 5653 | .tag = .mov, | | |
| 5654 | .ops = Mir.Inst.Ops.encode(.{ | | |
| 5655 | .reg1 = base_reg, | | |
| 5656 | .reg2 = registerAlias(tmp_reg, nearest_power_of_two), | | |
| 5657 | .flags = 0b10, | | |
| 5658 | }), | | |
| 5659 | .data = .{ .imm = @bitCast(u32, -next_offset) }, | | |
| 5660 | }); | | |
| 5661 | | | |
| 5662 | if (nearest_power_of_two > 1) { | | |
| 5663 | try self.genShiftBinOpMir(.shr, ty, tmp_reg, .{ .immediate = nearest_power_of_two * 8 }); | | |
| 5664 | } | | |
| 5665 | | | |
| 5666 | remainder -= nearest_power_of_two; | | |
| 5667 | next_offset -= nearest_power_of_two; | | |
| 5668 | } | | |
| 5669 | } else { | | |
| 5670 | _ = try self.addInst(.{ | | |
| 5671 | .tag = .mov, | | |
| 5672 | .ops = Mir.Inst.Ops.encode(.{ | | |
| 5673 | .reg1 = base_reg, | | |
| 5674 | .reg2 = registerAlias(reg, @intCast(u32, abi_size)), | | |
| 5675 | .flags = 0b10, | | |
| 5676 | }), | | |
| 5677 | .data = .{ .imm = @bitCast(u32, -stack_offset) }, | | |
| 5678 | }); | | |
| 5679 | } | | |
| 5680 | }, | 5603 | }, |
| 5681 | } | 5604 | } |
| 5682 | }, | 5605 | }, |
| ... | @@ -5711,6 +5634,67 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl | ... | @@ -5711,6 +5634,67 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5711 | } | 5634 | } |
| 5712 | } | 5635 | } |
| 5713 | | 5636 | |
| | 5637 | /// Like `genInlineMemcpy` but copies value from a register to an address via dereferencing |
| | 5638 | /// of destination register. |
| | 5639 | /// Boils down to MOV r/m64, r64. |
| | 5640 | fn genInlineMemcpyRegisterRegister( |
| | 5641 | self: *Self, |
| | 5642 | ty: Type, |
| | 5643 | dst_reg: Register, |
| | 5644 | src_reg: Register, |
| | 5645 | offset: i32, |
| | 5646 | ) InnerError!void { |
| | 5647 | assert(dst_reg.size() == 64); |
| | 5648 | |
| | 5649 | const dst_reg_lock = self.register_manager.lockReg(dst_reg); |
| | 5650 | defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock); |
| | 5651 | |
| | 5652 | const src_reg_lock = self.register_manager.lockReg(src_reg); |
| | 5653 | defer if (src_reg_lock) |lock| self.register_manager.unlockReg(lock); |
| | 5654 | |
| | 5655 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| | 5656 | |
| | 5657 | // TODO common code-path with genSetStack, refactor! |
| | 5658 | if (!math.isPowerOfTwo(abi_size)) { |
| | 5659 | const tmp_reg = try self.copyToTmpRegister(ty, .{ .register = src_reg }); |
| | 5660 | |
| | 5661 | var next_offset = offset; |
| | 5662 | var remainder = abi_size; |
| | 5663 | while (remainder > 0) { |
| | 5664 | const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder)); |
| | 5665 | |
| | 5666 | _ = try self.addInst(.{ |
| | 5667 | .tag = .mov, |
| | 5668 | .ops = Mir.Inst.Ops.encode(.{ |
| | 5669 | .reg1 = dst_reg, |
| | 5670 | .reg2 = registerAlias(tmp_reg, nearest_power_of_two), |
| | 5671 | .flags = 0b10, |
| | 5672 | }), |
| | 5673 | .data = .{ .imm = @bitCast(u32, -next_offset) }, |
| | 5674 | }); |
| | 5675 | |
| | 5676 | if (nearest_power_of_two > 1) { |
| | 5677 | try self.genShiftBinOpMir(.shr, ty, tmp_reg, .{ |
| | 5678 | .immediate = nearest_power_of_two * 8, |
| | 5679 | }); |
| | 5680 | } |
| | 5681 | |
| | 5682 | remainder -= nearest_power_of_two; |
| | 5683 | next_offset -= nearest_power_of_two; |
| | 5684 | } |
| | 5685 | } else { |
| | 5686 | _ = try self.addInst(.{ |
| | 5687 | .tag = .mov, |
| | 5688 | .ops = Mir.Inst.Ops.encode(.{ |
| | 5689 | .reg1 = dst_reg, |
| | 5690 | .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)), |
| | 5691 | .flags = 0b10, |
| | 5692 | }), |
| | 5693 | .data = .{ .imm = @bitCast(u32, -offset) }, |
| | 5694 | }); |
| | 5695 | } |
| | 5696 | } |
| | 5697 | |
| 5714 | const InlineMemcpyOpts = struct { | 5698 | const InlineMemcpyOpts = struct { |
| 5715 | source_stack_base: ?Register = null, | 5699 | source_stack_base: ?Register = null, |
| 5716 | dest_stack_base: ?Register = null, | 5700 | dest_stack_base: ?Register = null, |