| ... | ... | @@ -2738,46 +2738,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2738 | 2738 | } |
| 2739 | 2739 | }, |
| 2740 | 2740 | .register => |src_reg| { |
| 2741 | | const src_reg_lock = self.register_manager.lockReg(src_reg); |
| 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 | | } |
| 2741 | try self.genInlineMemcpyRegisterRegister(value_ty, reg, src_reg, 0); |
| 2781 | 2742 | }, |
| 2782 | 2743 | .got_load, |
| 2783 | 2744 | .direct_load, |
| ... | ... | @@ -5638,45 +5599,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5638 | 5599 | return self.fail("TODO genSetStack for register for type float with no intrinsics", .{}); |
| 5639 | 5600 | }, |
| 5640 | 5601 | else => { |
| 5641 | | if (!math.isPowerOfTwo(abi_size)) { |
| 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 | | } |
| 5602 | try self.genInlineMemcpyRegisterRegister(ty, base_reg, reg, stack_offset); |
| 5680 | 5603 | }, |
| 5681 | 5604 | } |
| 5682 | 5605 | }, |
| ... | ... | @@ -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 | 5698 | const InlineMemcpyOpts = struct { |
| 5715 | 5699 | source_stack_base: ?Register = null, |
| 5716 | 5700 | dest_stack_base: ?Register = null, |