| ... | ... | @@ -7962,10 +7962,10 @@ fn genBinOpMir( |
| 7962 | 7962 | .air_ref, |
| 7963 | 7963 | => unreachable, |
| 7964 | 7964 | .immediate, |
| 7965 | .eflags, |
| 7965 | 7966 | .register, |
| 7966 | 7967 | .register_pair, |
| 7967 | 7968 | .register_offset, |
| 7968 | | .eflags, |
| 7969 | 7969 | .indirect, |
| 7970 | 7970 | .lea_direct, |
| 7971 | 7971 | .lea_got, |
| ... | ... | @@ -8750,33 +8750,122 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8750 | 8750 | .lt, .gte => {}, |
| 8751 | 8751 | .lte, .gt => unreachable, |
| 8752 | 8752 | .eq, .neq => { |
| 8753 | | const dst_addr_mcv: MCValue = switch (dst_mcv) { |
| 8754 | | .memory, .indirect, .load_frame => dst_mcv.address(), |
| 8755 | | else => .{ .register = try self.copyToTmpRegister( |
| 8756 | | Type.usize, |
| 8757 | | dst_mcv.address(), |
| 8758 | | ) }, |
| 8753 | const OpInfo = ?struct { addr_reg: Register, addr_lock: RegisterLock }; |
| 8754 | |
| 8755 | const resolved_dst_mcv = switch (dst_mcv) { |
| 8756 | else => dst_mcv, |
| 8757 | .air_ref => |dst_ref| try self.resolveInst(dst_ref), |
| 8759 | 8758 | }; |
| 8760 | | const dst_addr_lock = if (dst_addr_mcv.getReg()) |reg| |
| 8761 | | self.register_manager.lockReg(reg) |
| 8762 | | else |
| 8763 | | null; |
| 8764 | | defer if (dst_addr_lock) |lock| self.register_manager.unlockReg(lock); |
| 8759 | const dst_info: OpInfo = switch (resolved_dst_mcv) { |
| 8760 | .none, |
| 8761 | .unreach, |
| 8762 | .dead, |
| 8763 | .undef, |
| 8764 | .immediate, |
| 8765 | .eflags, |
| 8766 | .register, |
| 8767 | .register_offset, |
| 8768 | .register_overflow, |
| 8769 | .indirect, |
| 8770 | .lea_direct, |
| 8771 | .lea_got, |
| 8772 | .lea_tlv, |
| 8773 | .lea_frame, |
| 8774 | .reserved_frame, |
| 8775 | .air_ref, |
| 8776 | => unreachable, |
| 8777 | .register_pair, .load_frame => null, |
| 8778 | .memory, .load_got, .load_direct, .load_tlv => dst: { |
| 8779 | switch (resolved_dst_mcv) { |
| 8780 | .memory => |addr| if (math.cast( |
| 8781 | i32, |
| 8782 | @as(i64, @bitCast(addr)), |
| 8783 | ) != null and math.cast( |
| 8784 | i32, |
| 8785 | @as(i64, @bitCast(addr)) + abi_size - 8, |
| 8786 | ) != null) break :dst null, |
| 8787 | .load_got, .load_direct, .load_tlv => {}, |
| 8788 | else => unreachable, |
| 8789 | } |
| 8790 | |
| 8791 | const dst_addr_reg = |
| 8792 | (try self.register_manager.allocReg(null, gp)).to64(); |
| 8793 | const dst_addr_lock = |
| 8794 | self.register_manager.lockRegAssumeUnused(dst_addr_reg); |
| 8795 | errdefer self.register_manager.unlockReg(dst_addr_lock); |
| 8796 | |
| 8797 | try self.genSetReg( |
| 8798 | dst_addr_reg, |
| 8799 | Type.usize, |
| 8800 | resolved_dst_mcv.address(), |
| 8801 | ); |
| 8802 | break :dst .{ |
| 8803 | .addr_reg = dst_addr_reg, |
| 8804 | .addr_lock = dst_addr_lock, |
| 8805 | }; |
| 8806 | }, |
| 8807 | }; |
| 8808 | defer if (dst_info) |info| |
| 8809 | self.register_manager.unlockReg(info.addr_lock); |
| 8765 | 8810 | |
| 8766 | | const src_addr_mcv: MCValue = switch (src_mcv) { |
| 8767 | | .memory, .indirect, .load_frame => src_mcv.address(), |
| 8768 | | else => .{ .register = try self.copyToTmpRegister( |
| 8769 | | Type.usize, |
| 8770 | | src_mcv.address(), |
| 8771 | | ) }, |
| 8811 | const resolved_src_mcv = switch (src_mcv) { |
| 8812 | else => src_mcv, |
| 8813 | .air_ref => |src_ref| try self.resolveInst(src_ref), |
| 8772 | 8814 | }; |
| 8773 | | const src_addr_lock = if (src_addr_mcv.getReg()) |reg| |
| 8774 | | self.register_manager.lockReg(reg) |
| 8775 | | else |
| 8776 | | null; |
| 8777 | | defer if (src_addr_lock) |lock| self.register_manager.unlockReg(lock); |
| 8815 | const src_info: OpInfo = switch (resolved_src_mcv) { |
| 8816 | .none, |
| 8817 | .unreach, |
| 8818 | .dead, |
| 8819 | .undef, |
| 8820 | .immediate, |
| 8821 | .eflags, |
| 8822 | .register, |
| 8823 | .register_offset, |
| 8824 | .register_overflow, |
| 8825 | .indirect, |
| 8826 | .lea_direct, |
| 8827 | .lea_got, |
| 8828 | .lea_tlv, |
| 8829 | .lea_frame, |
| 8830 | .reserved_frame, |
| 8831 | .air_ref, |
| 8832 | => unreachable, |
| 8833 | .register_pair, .load_frame => null, |
| 8834 | .memory, .load_got, .load_direct, .load_tlv => src: { |
| 8835 | switch (resolved_src_mcv) { |
| 8836 | .memory => |addr| if (math.cast( |
| 8837 | i32, |
| 8838 | @as(i64, @bitCast(addr)), |
| 8839 | ) != null and math.cast( |
| 8840 | i32, |
| 8841 | @as(i64, @bitCast(addr)) + abi_size - 8, |
| 8842 | ) != null) break :src null, |
| 8843 | .load_got, .load_direct, .load_tlv => {}, |
| 8844 | else => unreachable, |
| 8845 | } |
| 8846 | |
| 8847 | const src_addr_reg = |
| 8848 | (try self.register_manager.allocReg(null, gp)).to64(); |
| 8849 | const src_addr_lock = |
| 8850 | self.register_manager.lockRegAssumeUnused(src_addr_reg); |
| 8851 | errdefer self.register_manager.unlockReg(src_addr_lock); |
| 8852 | |
| 8853 | try self.genSetReg( |
| 8854 | src_addr_reg, |
| 8855 | Type.usize, |
| 8856 | resolved_src_mcv.address(), |
| 8857 | ); |
| 8858 | break :src .{ |
| 8859 | .addr_reg = src_addr_reg, |
| 8860 | .addr_lock = src_addr_lock, |
| 8861 | }; |
| 8862 | }, |
| 8863 | }; |
| 8864 | defer if (src_info) |info| |
| 8865 | self.register_manager.unlockReg(info.addr_lock); |
| 8778 | 8866 | |
| 8779 | | const regs = try self.register_manager.allocRegs(2, .{ null, null }, gp); |
| 8867 | const regs = |
| 8868 | try self.register_manager.allocRegs(2, .{ null, null }, gp); |
| 8780 | 8869 | const acc_reg = regs[0].to64(); |
| 8781 | 8870 | const locks = self.register_manager.lockRegsAssumeUnused(2, regs); |
| 8782 | 8871 | defer for (locks) |lock| self.register_manager.unlockReg(lock); |
| ... | ... | @@ -8784,18 +8873,52 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8784 | 8873 | const limbs_len = std.math.divCeil(u16, abi_size, 8) catch unreachable; |
| 8785 | 8874 | var limb_i: u16 = 0; |
| 8786 | 8875 | while (limb_i < limbs_len) : (limb_i += 1) { |
| 8876 | const off = limb_i * 8; |
| 8787 | 8877 | const tmp_reg = regs[@min(limb_i, 1)].to64(); |
| 8788 | | try self.genSetReg( |
| 8789 | | tmp_reg, |
| 8790 | | Type.usize, |
| 8791 | | dst_addr_mcv.offset(limb_i * 8).deref(), |
| 8792 | | ); |
| 8878 | |
| 8879 | try self.genSetReg(tmp_reg, Type.usize, if (dst_info) |info| .{ |
| 8880 | .indirect = .{ .reg = info.addr_reg, .off = off }, |
| 8881 | } else switch (resolved_dst_mcv) { |
| 8882 | .register_pair => |dst_regs| .{ .register = dst_regs[limb_i] }, |
| 8883 | .memory => |dst_addr| .{ |
| 8884 | .memory = @bitCast(@as(i64, @bitCast(dst_addr)) + off), |
| 8885 | }, |
| 8886 | .indirect => |reg_off| .{ .indirect = .{ |
| 8887 | .reg = reg_off.reg, |
| 8888 | .off = reg_off.off + off, |
| 8889 | } }, |
| 8890 | .load_frame => |frame_addr| .{ .load_frame = .{ |
| 8891 | .index = frame_addr.index, |
| 8892 | .off = frame_addr.off + off, |
| 8893 | } }, |
| 8894 | else => unreachable, |
| 8895 | }); |
| 8896 | |
| 8793 | 8897 | try self.genBinOpMir( |
| 8794 | 8898 | .{ ._, .xor }, |
| 8795 | 8899 | Type.usize, |
| 8796 | 8900 | .{ .register = tmp_reg }, |
| 8797 | | src_addr_mcv.offset(limb_i * 8).deref(), |
| 8901 | if (src_info) |info| .{ |
| 8902 | .indirect = .{ .reg = info.addr_reg, .off = off }, |
| 8903 | } else switch (resolved_src_mcv) { |
| 8904 | .register_pair => |src_regs| .{ |
| 8905 | .register = src_regs[limb_i], |
| 8906 | }, |
| 8907 | .memory => |src_addr| .{ |
| 8908 | .memory = @bitCast(@as(i64, @bitCast(src_addr)) + off), |
| 8909 | }, |
| 8910 | .indirect => |reg_off| .{ .indirect = .{ |
| 8911 | .reg = reg_off.reg, |
| 8912 | .off = reg_off.off + off, |
| 8913 | } }, |
| 8914 | .load_frame => |frame_addr| .{ .load_frame = .{ |
| 8915 | .index = frame_addr.index, |
| 8916 | .off = frame_addr.off + off, |
| 8917 | } }, |
| 8918 | else => unreachable, |
| 8919 | }, |
| 8798 | 8920 | ); |
| 8921 | |
| 8799 | 8922 | if (limb_i > 0) try self.asmRegisterRegister( |
| 8800 | 8923 | .{ ._, .@"or" }, |
| 8801 | 8924 | acc_reg, |