| ... | @@ -7962,10 +7962,10 @@ fn genBinOpMir( | ... | @@ -7962,10 +7962,10 @@ fn genBinOpMir( |
| 7962 | .air_ref, | 7962 | .air_ref, |
| 7963 | => unreachable, | 7963 | => unreachable, |
| 7964 | .immediate, | 7964 | .immediate, |
| | 7965 | .eflags, |
| 7965 | .register, | 7966 | .register, |
| 7966 | .register_pair, | 7967 | .register_pair, |
| 7967 | .register_offset, | 7968 | .register_offset, |
| 7968 | .eflags, | | |
| 7969 | .indirect, | 7969 | .indirect, |
| 7970 | .lea_direct, | 7970 | .lea_direct, |
| 7971 | .lea_got, | 7971 | .lea_got, |
| ... | @@ -8750,33 +8750,122 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -8750,33 +8750,122 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8750 | .lt, .gte => {}, | 8750 | .lt, .gte => {}, |
| 8751 | .lte, .gt => unreachable, | 8751 | .lte, .gt => unreachable, |
| 8752 | .eq, .neq => { | 8752 | .eq, .neq => { |
| 8753 | const dst_addr_mcv: MCValue = switch (dst_mcv) { | 8753 | const OpInfo = ?struct { addr_reg: Register, addr_lock: RegisterLock }; |
| 8754 | .memory, .indirect, .load_frame => dst_mcv.address(), | 8754 | |
| 8755 | else => .{ .register = try self.copyToTmpRegister( | 8755 | const resolved_dst_mcv = switch (dst_mcv) { |
| 8756 | Type.usize, | 8756 | else => dst_mcv, |
| 8757 | dst_mcv.address(), | 8757 | .air_ref => |dst_ref| try self.resolveInst(dst_ref), |
| 8758 | ) }, | | |
| 8759 | }; | 8758 | }; |
| 8760 | const dst_addr_lock = if (dst_addr_mcv.getReg()) |reg| | 8759 | const dst_info: OpInfo = switch (resolved_dst_mcv) { |
| 8761 | self.register_manager.lockReg(reg) | 8760 | .none, |
| 8762 | else | 8761 | .unreach, |
| 8763 | null; | 8762 | .dead, |
| 8764 | defer if (dst_addr_lock) |lock| self.register_manager.unlockReg(lock); | 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) { | 8811 | const resolved_src_mcv = switch (src_mcv) { |
| 8767 | .memory, .indirect, .load_frame => src_mcv.address(), | 8812 | else => src_mcv, |
| 8768 | else => .{ .register = try self.copyToTmpRegister( | 8813 | .air_ref => |src_ref| try self.resolveInst(src_ref), |
| 8769 | Type.usize, | | |
| 8770 | src_mcv.address(), | | |
| 8771 | ) }, | | |
| 8772 | }; | 8814 | }; |
| 8773 | const src_addr_lock = if (src_addr_mcv.getReg()) |reg| | 8815 | const src_info: OpInfo = switch (resolved_src_mcv) { |
| 8774 | self.register_manager.lockReg(reg) | 8816 | .none, |
| 8775 | else | 8817 | .unreach, |
| 8776 | null; | 8818 | .dead, |
| 8777 | defer if (src_addr_lock) |lock| self.register_manager.unlockReg(lock); | 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 | const acc_reg = regs[0].to64(); | 8869 | const acc_reg = regs[0].to64(); |
| 8781 | const locks = self.register_manager.lockRegsAssumeUnused(2, regs); | 8870 | const locks = self.register_manager.lockRegsAssumeUnused(2, regs); |
| 8782 | defer for (locks) |lock| self.register_manager.unlockReg(lock); | 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,18 +8873,52 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8784 | const limbs_len = std.math.divCeil(u16, abi_size, 8) catch unreachable; | 8873 | const limbs_len = std.math.divCeil(u16, abi_size, 8) catch unreachable; |
| 8785 | var limb_i: u16 = 0; | 8874 | var limb_i: u16 = 0; |
| 8786 | while (limb_i < limbs_len) : (limb_i += 1) { | 8875 | while (limb_i < limbs_len) : (limb_i += 1) { |
| | 8876 | const off = limb_i * 8; |
| 8787 | const tmp_reg = regs[@min(limb_i, 1)].to64(); | 8877 | const tmp_reg = regs[@min(limb_i, 1)].to64(); |
| 8788 | try self.genSetReg( | 8878 | |
| 8789 | tmp_reg, | 8879 | try self.genSetReg(tmp_reg, Type.usize, if (dst_info) |info| .{ |
| 8790 | Type.usize, | 8880 | .indirect = .{ .reg = info.addr_reg, .off = off }, |
| 8791 | dst_addr_mcv.offset(limb_i * 8).deref(), | 8881 | } else switch (resolved_dst_mcv) { |
| 8792 | ); | 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 | try self.genBinOpMir( | 8897 | try self.genBinOpMir( |
| 8794 | .{ ._, .xor }, | 8898 | .{ ._, .xor }, |
| 8795 | Type.usize, | 8899 | Type.usize, |
| 8796 | .{ .register = tmp_reg }, | 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 | if (limb_i > 0) try self.asmRegisterRegister( | 8922 | if (limb_i > 0) try self.asmRegisterRegister( |
| 8800 | .{ ._, .@"or" }, | 8923 | .{ ._, .@"or" }, |
| 8801 | acc_reg, | 8924 | acc_reg, |