| ... | ... | @@ -1734,10 +1734,10 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 1734 | 1734 | }; |
| 1735 | 1735 | try self.genBinOpMir(.add, ty, dst_mcv, rhs_mcv); |
| 1736 | 1736 | |
| 1737 | | const abi_size = @intCast(u32, @max(ty.abiSize(self.target.*), 2)); |
| 1737 | const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2); |
| 1738 | 1738 | try self.asmCmovccRegisterRegister( |
| 1739 | | registerAlias(dst_reg, abi_size), |
| 1740 | | registerAlias(limit_reg, abi_size), |
| 1739 | registerAlias(dst_reg, cmov_abi_size), |
| 1740 | registerAlias(limit_reg, cmov_abi_size), |
| 1741 | 1741 | cc, |
| 1742 | 1742 | ); |
| 1743 | 1743 | break :result dst_mcv; |
| ... | ... | @@ -1785,10 +1785,10 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 1785 | 1785 | }; |
| 1786 | 1786 | try self.genBinOpMir(.sub, ty, dst_mcv, rhs_mcv); |
| 1787 | 1787 | |
| 1788 | | const abi_size = @intCast(u32, @max(ty.abiSize(self.target.*), 2)); |
| 1788 | const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2); |
| 1789 | 1789 | try self.asmCmovccRegisterRegister( |
| 1790 | | registerAlias(dst_reg, abi_size), |
| 1791 | | registerAlias(limit_reg, abi_size), |
| 1790 | registerAlias(dst_reg, cmov_abi_size), |
| 1791 | registerAlias(limit_reg, cmov_abi_size), |
| 1792 | 1792 | cc, |
| 1793 | 1793 | ); |
| 1794 | 1794 | break :result dst_mcv; |
| ... | ... | @@ -1841,10 +1841,10 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 1841 | 1841 | }; |
| 1842 | 1842 | |
| 1843 | 1843 | const dst_mcv = try self.genMulDivBinOp(.mul, inst, ty, ty, lhs_mcv, rhs_mcv); |
| 1844 | | const abi_size = @intCast(u32, @max(ty.abiSize(self.target.*), 2)); |
| 1844 | const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2); |
| 1845 | 1845 | try self.asmCmovccRegisterRegister( |
| 1846 | | registerAlias(dst_mcv.register, abi_size), |
| 1847 | | registerAlias(limit_reg, abi_size), |
| 1846 | registerAlias(dst_mcv.register, cmov_abi_size), |
| 1847 | registerAlias(limit_reg, cmov_abi_size), |
| 1848 | 1848 | cc, |
| 1849 | 1849 | ); |
| 1850 | 1850 | break :result dst_mcv; |
| ... | ... | @@ -3102,10 +3102,10 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 3102 | 3102 | try self.copyToRegisterWithInstTracking(inst, dst_ty, .{ .immediate = src_bits }); |
| 3103 | 3103 | try self.genBinOpMir(.bsr, src_ty, dst_mcv, mat_src_mcv); |
| 3104 | 3104 | |
| 3105 | | const dst_abi_size = @intCast(u32, @max(dst_ty.abiSize(self.target.*), 2)); |
| 3105 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); |
| 3106 | 3106 | try self.asmCmovccRegisterRegister( |
| 3107 | | registerAlias(dst_reg, dst_abi_size), |
| 3108 | | registerAlias(width_mcv.register, dst_abi_size), |
| 3107 | registerAlias(dst_reg, cmov_abi_size), |
| 3108 | registerAlias(width_mcv.register, cmov_abi_size), |
| 3109 | 3109 | .z, |
| 3110 | 3110 | ); |
| 3111 | 3111 | |
| ... | ... | @@ -3162,10 +3162,10 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 3162 | 3162 | const width_reg = try self.copyToTmpRegister(dst_ty, .{ .immediate = src_bits }); |
| 3163 | 3163 | try self.genBinOpMir(.bsf, src_ty, dst_mcv, mat_src_mcv); |
| 3164 | 3164 | |
| 3165 | | const abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); |
| 3165 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); |
| 3166 | 3166 | try self.asmCmovccRegisterRegister( |
| 3167 | | registerAlias(dst_reg, abi_size), |
| 3168 | | registerAlias(width_reg, abi_size), |
| 3167 | registerAlias(dst_reg, cmov_abi_size), |
| 3168 | registerAlias(width_reg, cmov_abi_size), |
| 3169 | 3169 | .z, |
| 3170 | 3170 | ); |
| 3171 | 3171 | break :result dst_mcv; |
| ... | ... | @@ -4766,7 +4766,7 @@ fn genBinOp( |
| 4766 | 4766 | }, |
| 4767 | 4767 | }; |
| 4768 | 4768 | |
| 4769 | | const abi_size = @intCast(u32, lhs_ty.abiSize(self.target.*)); |
| 4769 | const cmov_abi_size = @max(@intCast(u32, lhs_ty.abiSize(self.target.*)), 2); |
| 4770 | 4770 | const tmp_reg = switch (dst_mcv) { |
| 4771 | 4771 | .register => |reg| reg, |
| 4772 | 4772 | else => try self.copyToTmpRegister(lhs_ty, dst_mcv), |
| ... | ... | @@ -4784,13 +4784,13 @@ fn genBinOp( |
| 4784 | 4784 | .ptr_stack_offset, |
| 4785 | 4785 | => unreachable, |
| 4786 | 4786 | .register => |src_reg| try self.asmCmovccRegisterRegister( |
| 4787 | | registerAlias(tmp_reg, abi_size), |
| 4788 | | registerAlias(src_reg, abi_size), |
| 4787 | registerAlias(tmp_reg, cmov_abi_size), |
| 4788 | registerAlias(src_reg, cmov_abi_size), |
| 4789 | 4789 | cc, |
| 4790 | 4790 | ), |
| 4791 | 4791 | .stack_offset => |off| try self.asmCmovccRegisterMemory( |
| 4792 | | registerAlias(tmp_reg, abi_size), |
| 4793 | | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 4792 | registerAlias(tmp_reg, cmov_abi_size), |
| 4793 | Memory.sib(Memory.PtrSize.fromSize(cmov_abi_size), .{ |
| 4794 | 4794 | .base = .rbp, |
| 4795 | 4795 | .disp = -off, |
| 4796 | 4796 | }), |
| ... | ... | @@ -4803,8 +4803,8 @@ fn genBinOp( |
| 4803 | 4803 | |
| 4804 | 4804 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, mat_src_mcv); |
| 4805 | 4805 | try self.asmCmovccRegisterMemory( |
| 4806 | | registerAlias(tmp_reg, abi_size), |
| 4807 | | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = addr_reg }), |
| 4806 | registerAlias(tmp_reg, cmov_abi_size), |
| 4807 | Memory.sib(Memory.PtrSize.fromSize(cmov_abi_size), .{ .base = addr_reg }), |
| 4808 | 4808 | cc, |
| 4809 | 4809 | ); |
| 4810 | 4810 | }, |
| ... | ... | @@ -7727,7 +7727,6 @@ fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void { |
| 7727 | 7727 | |
| 7728 | 7728 | fn atomicOp( |
| 7729 | 7729 | self: *Self, |
| 7730 | | dst_reg: Register, |
| 7731 | 7730 | ptr_mcv: MCValue, |
| 7732 | 7731 | val_mcv: MCValue, |
| 7733 | 7732 | ptr_ty: Type, |
| ... | ... | @@ -7735,11 +7734,7 @@ fn atomicOp( |
| 7735 | 7734 | unused: bool, |
| 7736 | 7735 | rmw_op: ?std.builtin.AtomicRmwOp, |
| 7737 | 7736 | order: std.builtin.AtomicOrder, |
| 7738 | | ) InnerError!void { |
| 7739 | | const dst_mcv = MCValue{ .register = dst_reg }; |
| 7740 | | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 7741 | | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 7742 | | |
| 7737 | ) InnerError!MCValue { |
| 7743 | 7738 | const ptr_lock = switch (ptr_mcv) { |
| 7744 | 7739 | .register => |reg| self.register_manager.lockReg(reg), |
| 7745 | 7740 | else => null, |
| ... | ... | @@ -7794,9 +7789,14 @@ fn atomicOp( |
| 7794 | 7789 | .SeqCst => .xchg, |
| 7795 | 7790 | }; |
| 7796 | 7791 | |
| 7792 | const dst_reg = try self.register_manager.allocReg(null, gp); |
| 7793 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 7794 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 7795 | defer self.register_manager.unlockReg(dst_lock); |
| 7796 | |
| 7797 | 7797 | try self.genSetReg(val_ty, dst_reg, val_mcv); |
| 7798 | 7798 | if (rmw_op == std.builtin.AtomicRmwOp.Sub and tag == .xadd) { |
| 7799 | | try self.genUnOpMir(.neg, val_ty, .{ .register = dst_reg }); |
| 7799 | try self.genUnOpMir(.neg, val_ty, dst_mcv); |
| 7800 | 7800 | } |
| 7801 | 7801 | _ = try self.addInst(.{ .tag = tag, .ops = switch (tag) { |
| 7802 | 7802 | .mov, .xchg => .mr_sib, |
| ... | ... | @@ -7806,25 +7806,31 @@ fn atomicOp( |
| 7806 | 7806 | .r = registerAlias(dst_reg, val_abi_size), |
| 7807 | 7807 | .payload = try self.addExtra(Mir.MemorySib.encode(ptr_mem)), |
| 7808 | 7808 | } } }); |
| 7809 | |
| 7810 | return if (unused) .none else dst_mcv; |
| 7809 | 7811 | }, |
| 7810 | | .loop => _ = try self.asmJccReloc(if (val_abi_size <= 8) loop: { |
| 7811 | | try self.genSetReg(val_ty, dst_reg, val_mcv); |
| 7812 | .loop => _ = if (val_abi_size <= 8) { |
| 7813 | const tmp_reg = try self.register_manager.allocReg(null, gp); |
| 7814 | const tmp_mcv = MCValue{ .register = tmp_reg }; |
| 7815 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7816 | defer self.register_manager.unlockReg(tmp_lock); |
| 7817 | |
| 7812 | 7818 | try self.asmRegisterMemory(.mov, registerAlias(.rax, val_abi_size), ptr_mem); |
| 7813 | 7819 | const loop = @intCast(u32, self.mir_instructions.len); |
| 7814 | 7820 | if (rmw_op != std.builtin.AtomicRmwOp.Xchg) { |
| 7815 | | try self.genSetReg(val_ty, dst_reg, .{ .register = .rax }); |
| 7821 | try self.genSetReg(val_ty, tmp_reg, .{ .register = .rax }); |
| 7816 | 7822 | } |
| 7817 | 7823 | if (rmw_op) |op| switch (op) { |
| 7818 | | .Xchg => try self.genSetReg(val_ty, dst_reg, val_mcv), |
| 7819 | | .Add => try self.genBinOpMir(.add, val_ty, dst_mcv, val_mcv), |
| 7820 | | .Sub => try self.genBinOpMir(.sub, val_ty, dst_mcv, val_mcv), |
| 7821 | | .And => try self.genBinOpMir(.@"and", val_ty, dst_mcv, val_mcv), |
| 7824 | .Xchg => try self.genSetReg(val_ty, tmp_reg, val_mcv), |
| 7825 | .Add => try self.genBinOpMir(.add, val_ty, tmp_mcv, val_mcv), |
| 7826 | .Sub => try self.genBinOpMir(.sub, val_ty, tmp_mcv, val_mcv), |
| 7827 | .And => try self.genBinOpMir(.@"and", val_ty, tmp_mcv, val_mcv), |
| 7822 | 7828 | .Nand => { |
| 7823 | | try self.genBinOpMir(.@"and", val_ty, dst_mcv, val_mcv); |
| 7824 | | try self.genUnOpMir(.not, val_ty, dst_mcv); |
| 7829 | try self.genBinOpMir(.@"and", val_ty, tmp_mcv, val_mcv); |
| 7830 | try self.genUnOpMir(.not, val_ty, tmp_mcv); |
| 7825 | 7831 | }, |
| 7826 | | .Or => try self.genBinOpMir(.@"or", val_ty, dst_mcv, val_mcv), |
| 7827 | | .Xor => try self.genBinOpMir(.xor, val_ty, dst_mcv, val_mcv), |
| 7832 | .Or => try self.genBinOpMir(.@"or", val_ty, tmp_mcv, val_mcv), |
| 7833 | .Xor => try self.genBinOpMir(.xor, val_ty, tmp_mcv, val_mcv), |
| 7828 | 7834 | .Min, .Max => { |
| 7829 | 7835 | const cc: Condition = switch (if (val_ty.isAbiInt()) |
| 7830 | 7836 | val_ty.intInfo(self.target.*).signedness |
| ... | ... | @@ -7842,17 +7848,18 @@ fn atomicOp( |
| 7842 | 7848 | }, |
| 7843 | 7849 | }; |
| 7844 | 7850 | |
| 7845 | | try self.genBinOpMir(.cmp, val_ty, dst_mcv, val_mcv); |
| 7851 | try self.genBinOpMir(.cmp, val_ty, tmp_mcv, val_mcv); |
| 7852 | const cmov_abi_size = @max(val_abi_size, 2); |
| 7846 | 7853 | switch (val_mcv) { |
| 7847 | 7854 | .register => |val_reg| try self.asmCmovccRegisterRegister( |
| 7848 | | registerAlias(dst_reg, val_abi_size), |
| 7849 | | registerAlias(val_reg, val_abi_size), |
| 7855 | registerAlias(tmp_reg, cmov_abi_size), |
| 7856 | registerAlias(val_reg, cmov_abi_size), |
| 7850 | 7857 | cc, |
| 7851 | 7858 | ), |
| 7852 | 7859 | .stack_offset => |val_off| try self.asmCmovccRegisterMemory( |
| 7853 | | registerAlias(dst_reg, val_abi_size), |
| 7860 | registerAlias(tmp_reg, cmov_abi_size), |
| 7854 | 7861 | Memory.sib( |
| 7855 | | Memory.PtrSize.fromSize(val_abi_size), |
| 7862 | Memory.PtrSize.fromSize(cmov_abi_size), |
| 7856 | 7863 | .{ .base = .rbp, .disp = -val_off }, |
| 7857 | 7864 | ), |
| 7858 | 7865 | cc, |
| ... | ... | @@ -7860,8 +7867,8 @@ fn atomicOp( |
| 7860 | 7867 | else => { |
| 7861 | 7868 | const val_reg = try self.copyToTmpRegister(val_ty, val_mcv); |
| 7862 | 7869 | try self.asmCmovccRegisterRegister( |
| 7863 | | registerAlias(dst_reg, val_abi_size), |
| 7864 | | registerAlias(val_reg, val_abi_size), |
| 7870 | registerAlias(tmp_reg, cmov_abi_size), |
| 7871 | registerAlias(val_reg, cmov_abi_size), |
| 7865 | 7872 | cc, |
| 7866 | 7873 | ); |
| 7867 | 7874 | }, |
| ... | ... | @@ -7869,11 +7876,12 @@ fn atomicOp( |
| 7869 | 7876 | }, |
| 7870 | 7877 | }; |
| 7871 | 7878 | _ = try self.addInst(.{ .tag = .cmpxchg, .ops = .lock_mr_sib, .data = .{ .rx = .{ |
| 7872 | | .r = registerAlias(dst_reg, val_abi_size), |
| 7879 | .r = registerAlias(tmp_reg, val_abi_size), |
| 7873 | 7880 | .payload = try self.addExtra(Mir.MemorySib.encode(ptr_mem)), |
| 7874 | 7881 | } } }); |
| 7875 | | break :loop loop; |
| 7876 | | } else loop: { |
| 7882 | _ = try self.asmJccReloc(loop, .ne); |
| 7883 | return if (unused) .none else .{ .register = .rax }; |
| 7884 | } else { |
| 7877 | 7885 | try self.asmRegisterMemory(.mov, .rax, Memory.sib(.qword, .{ |
| 7878 | 7886 | .base = ptr_mem.sib.base, |
| 7879 | 7887 | .scale_index = ptr_mem.sib.scale_index, |
| ... | ... | @@ -7939,8 +7947,22 @@ fn atomicOp( |
| 7939 | 7947 | _ = try self.addInst(.{ .tag = .cmpxchgb, .ops = .lock_m_sib, .data = .{ |
| 7940 | 7948 | .payload = try self.addExtra(Mir.MemorySib.encode(ptr_mem)), |
| 7941 | 7949 | } }); |
| 7942 | | break :loop loop; |
| 7943 | | }, .ne), |
| 7950 | _ = try self.asmJccReloc(loop, .ne); |
| 7951 | |
| 7952 | if (unused) return .none; |
| 7953 | const dst_mcv = try self.allocTempRegOrMem(val_ty, false); |
| 7954 | try self.asmMemoryRegister( |
| 7955 | .mov, |
| 7956 | Memory.sib(.qword, .{ .base = .rbp, .disp = 0 - dst_mcv.stack_offset }), |
| 7957 | .rax, |
| 7958 | ); |
| 7959 | try self.asmMemoryRegister( |
| 7960 | .mov, |
| 7961 | Memory.sib(.qword, .{ .base = .rbp, .disp = 8 - dst_mcv.stack_offset }), |
| 7962 | .rdx, |
| 7963 | ); |
| 7964 | return dst_mcv; |
| 7965 | }, |
| 7944 | 7966 | .libcall => return self.fail("TODO implement x86 atomic libcall", .{}), |
| 7945 | 7967 | } |
| 7946 | 7968 | } |
| ... | ... | @@ -7954,7 +7976,6 @@ fn airAtomicRmw(self: *Self, inst: Air.Inst.Index) !void { |
| 7954 | 7976 | defer for (regs_lock) |lock| self.register_manager.unlockReg(lock); |
| 7955 | 7977 | |
| 7956 | 7978 | const unused = self.liveness.isUnused(inst); |
| 7957 | | const dst_reg = try self.register_manager.allocReg(if (unused) null else inst, gp); |
| 7958 | 7979 | |
| 7959 | 7980 | const ptr_ty = self.air.typeOf(pl_op.operand); |
| 7960 | 7981 | const ptr_mcv = try self.resolveInst(pl_op.operand); |
| ... | ... | @@ -7962,8 +7983,8 @@ fn airAtomicRmw(self: *Self, inst: Air.Inst.Index) !void { |
| 7962 | 7983 | const val_ty = self.air.typeOf(extra.operand); |
| 7963 | 7984 | const val_mcv = try self.resolveInst(extra.operand); |
| 7964 | 7985 | |
| 7965 | | try self.atomicOp(dst_reg, ptr_mcv, val_mcv, ptr_ty, val_ty, unused, extra.op(), extra.ordering()); |
| 7966 | | const result: MCValue = if (unused) .dead else .{ .register = dst_reg }; |
| 7986 | const result = |
| 7987 | try self.atomicOp(ptr_mcv, val_mcv, ptr_ty, val_ty, unused, extra.op(), extra.ordering()); |
| 7967 | 7988 | return self.finishAir(inst, result, .{ pl_op.operand, extra.operand, .none }); |
| 7968 | 7989 | } |
| 7969 | 7990 | |
| ... | ... | @@ -7996,16 +8017,14 @@ fn airAtomicLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 7996 | 8017 | fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOrder) !void { |
| 7997 | 8018 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7998 | 8019 | |
| 7999 | | const dst_reg = try self.register_manager.allocReg(null, gp); |
| 8000 | | |
| 8001 | 8020 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| 8002 | 8021 | const ptr_mcv = try self.resolveInst(bin_op.lhs); |
| 8003 | 8022 | |
| 8004 | 8023 | const val_ty = self.air.typeOf(bin_op.rhs); |
| 8005 | 8024 | const val_mcv = try self.resolveInst(bin_op.rhs); |
| 8006 | 8025 | |
| 8007 | | try self.atomicOp(dst_reg, ptr_mcv, val_mcv, ptr_ty, val_ty, true, null, order); |
| 8008 | | return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 8026 | const result = try self.atomicOp(ptr_mcv, val_mcv, ptr_ty, val_ty, true, null, order); |
| 8027 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 8009 | 8028 | } |
| 8010 | 8029 | |
| 8011 | 8030 | fn airMemset(self: *Self, inst: Air.Inst.Index) !void { |