| ... | @@ -1120,7 +1120,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { | ... | @@ -1120,7 +1120,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { |
| 1120 | } | 1120 | } |
| 1121 | | 1121 | |
| 1122 | /// A `cc` of `.z_and_np` clobbers `reg2`! | 1122 | /// A `cc` of `.z_and_np` clobbers `reg2`! |
| 1123 | fn asmCmovccRegisterRegister(self: *Self, reg1: Register, reg2: Register, cc: bits.Condition) !void { | 1123 | fn asmCmovccRegisterRegister(self: *Self, cc: bits.Condition, reg1: Register, reg2: Register) !void { |
| 1124 | _ = try self.addInst(.{ | 1124 | _ = try self.addInst(.{ |
| 1125 | .tag = switch (cc) { | 1125 | .tag = switch (cc) { |
| 1126 | else => .cmov, | 1126 | else => .cmov, |
| ... | @@ -1143,7 +1143,7 @@ fn asmCmovccRegisterRegister(self: *Self, reg1: Register, reg2: Register, cc: bi | ... | @@ -1143,7 +1143,7 @@ fn asmCmovccRegisterRegister(self: *Self, reg1: Register, reg2: Register, cc: bi |
| 1143 | } | 1143 | } |
| 1144 | | 1144 | |
| 1145 | /// A `cc` of `.z_and_np` is not supported by this encoding! | 1145 | /// A `cc` of `.z_and_np` is not supported by this encoding! |
| 1146 | fn asmCmovccRegisterMemory(self: *Self, reg: Register, m: Memory, cc: bits.Condition) !void { | 1146 | fn asmCmovccRegisterMemory(self: *Self, cc: bits.Condition, reg: Register, m: Memory) !void { |
| 1147 | _ = try self.addInst(.{ | 1147 | _ = try self.addInst(.{ |
| 1148 | .tag = switch (cc) { | 1148 | .tag = switch (cc) { |
| 1149 | else => .cmov, | 1149 | else => .cmov, |
| ... | @@ -3232,9 +3232,9 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3232,9 +3232,9 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3232 | | 3232 | |
| 3233 | const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2); | 3233 | const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2); |
| 3234 | try self.asmCmovccRegisterRegister( | 3234 | try self.asmCmovccRegisterRegister( |
| | 3235 | cc, |
| 3235 | registerAlias(dst_reg, cmov_abi_size), | 3236 | registerAlias(dst_reg, cmov_abi_size), |
| 3236 | registerAlias(limit_reg, cmov_abi_size), | 3237 | registerAlias(limit_reg, cmov_abi_size), |
| 3237 | cc, | | |
| 3238 | ); | 3238 | ); |
| 3239 | | 3239 | |
| 3240 | if (reg_extra_bits > 0 and ty.isSignedInt(mod)) { | 3240 | if (reg_extra_bits > 0 and ty.isSignedInt(mod)) { |
| ... | @@ -3308,9 +3308,9 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3308,9 +3308,9 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3308 | | 3308 | |
| 3309 | const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2); | 3309 | const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2); |
| 3310 | try self.asmCmovccRegisterRegister( | 3310 | try self.asmCmovccRegisterRegister( |
| | 3311 | cc, |
| 3311 | registerAlias(dst_reg, cmov_abi_size), | 3312 | registerAlias(dst_reg, cmov_abi_size), |
| 3312 | registerAlias(limit_reg, cmov_abi_size), | 3313 | registerAlias(limit_reg, cmov_abi_size), |
| 3313 | cc, | | |
| 3314 | ); | 3314 | ); |
| 3315 | | 3315 | |
| 3316 | if (reg_extra_bits > 0 and ty.isSignedInt(mod)) { | 3316 | if (reg_extra_bits > 0 and ty.isSignedInt(mod)) { |
| ... | @@ -3371,9 +3371,9 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3371,9 +3371,9 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3371 | const dst_mcv = try self.genMulDivBinOp(.mul, inst, ty, ty, lhs_mcv, rhs_mcv); | 3371 | const dst_mcv = try self.genMulDivBinOp(.mul, inst, ty, ty, lhs_mcv, rhs_mcv); |
| 3372 | const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2); | 3372 | const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2); |
| 3373 | try self.asmCmovccRegisterRegister( | 3373 | try self.asmCmovccRegisterRegister( |
| | 3374 | cc, |
| 3374 | registerAlias(dst_mcv.register, cmov_abi_size), | 3375 | registerAlias(dst_mcv.register, cmov_abi_size), |
| 3375 | registerAlias(limit_reg, cmov_abi_size), | 3376 | registerAlias(limit_reg, cmov_abi_size), |
| 3376 | cc, | | |
| 3377 | ); | 3377 | ); |
| 3378 | | 3378 | |
| 3379 | return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); | 3379 | return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); |
| ... | @@ -3743,9 +3743,9 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa | ... | @@ -3743,9 +3743,9 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa |
| 3743 | registerAlias(.rdx, abi_size), | 3743 | registerAlias(.rdx, abi_size), |
| 3744 | ); | 3744 | ); |
| 3745 | try self.asmCmovccRegisterRegister( | 3745 | try self.asmCmovccRegisterRegister( |
| | 3746 | .z, |
| 3746 | registerAlias(divisor, abi_size), | 3747 | registerAlias(divisor, abi_size), |
| 3747 | registerAlias(.rdx, abi_size), | 3748 | registerAlias(.rdx, abi_size), |
| 3748 | .z, | | |
| 3749 | ); | 3749 | ); |
| 3750 | try self.genBinOpMir(.{ ._, .add }, ty, .{ .register = divisor }, .{ .register = .rax }); | 3750 | try self.genBinOpMir(.{ ._, .add }, ty, .{ .register = divisor }, .{ .register = .rax }); |
| 3751 | return MCValue{ .register = divisor }; | 3751 | return MCValue{ .register = divisor }; |
| ... | @@ -4626,7 +4626,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4626,7 +4626,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4626 | tmp_mcv, | 4626 | tmp_mcv, |
| 4627 | mat_src_mcv.address().offset(8).deref(), | 4627 | mat_src_mcv.address().offset(8).deref(), |
| 4628 | ); | 4628 | ); |
| 4629 | try self.asmCmovccRegisterRegister(dst_reg.to32(), tmp_reg.to32(), .nc); | 4629 | try self.asmCmovccRegisterRegister(.nc, dst_reg.to32(), tmp_reg.to32()); |
| 4630 | | 4630 | |
| 4631 | if (src_bits < 128) { | 4631 | if (src_bits < 128) { |
| 4632 | try self.genBinOpMir( | 4632 | try self.genBinOpMir( |
| ... | @@ -4660,9 +4660,9 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4660,9 +4660,9 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4660 | | 4660 | |
| 4661 | const cmov_abi_size = @max(@as(u32, @intCast(dst_ty.abiSize(mod))), 2); | 4661 | const cmov_abi_size = @max(@as(u32, @intCast(dst_ty.abiSize(mod))), 2); |
| 4662 | try self.asmCmovccRegisterRegister( | 4662 | try self.asmCmovccRegisterRegister( |
| | 4663 | .z, |
| 4663 | registerAlias(dst_reg, cmov_abi_size), | 4664 | registerAlias(dst_reg, cmov_abi_size), |
| 4664 | registerAlias(imm_reg, cmov_abi_size), | 4665 | registerAlias(imm_reg, cmov_abi_size), |
| 4665 | .z, | | |
| 4666 | ); | 4666 | ); |
| 4667 | | 4667 | |
| 4668 | try self.genBinOpMir(.{ ._, .xor }, dst_ty, dst_mcv, .{ .immediate = src_bits - 1 }); | 4668 | try self.genBinOpMir(.{ ._, .xor }, dst_ty, dst_mcv, .{ .immediate = src_bits - 1 }); |
| ... | @@ -4687,9 +4687,9 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4687,9 +4687,9 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4687 | | 4687 | |
| 4688 | const cmov_abi_size = @max(@as(u32, @intCast(dst_ty.abiSize(mod))), 2); | 4688 | const cmov_abi_size = @max(@as(u32, @intCast(dst_ty.abiSize(mod))), 2); |
| 4689 | try self.asmCmovccRegisterRegister( | 4689 | try self.asmCmovccRegisterRegister( |
| | 4690 | .nz, |
| 4690 | registerAlias(imm_reg, cmov_abi_size), | 4691 | registerAlias(imm_reg, cmov_abi_size), |
| 4691 | registerAlias(dst_reg, cmov_abi_size), | 4692 | registerAlias(dst_reg, cmov_abi_size), |
| 4692 | .nz, | | |
| 4693 | ); | 4693 | ); |
| 4694 | | 4694 | |
| 4695 | try self.genSetReg(dst_reg, dst_ty, .{ .immediate = src_bits - 1 }); | 4695 | try self.genSetReg(dst_reg, dst_ty, .{ .immediate = src_bits - 1 }); |
| ... | @@ -4764,7 +4764,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4764,7 +4764,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 4764 | try self.genBinOpMir(.{ ._, .tzcnt }, Type.u64, dst_mcv, masked_mcv); | 4764 | try self.genBinOpMir(.{ ._, .tzcnt }, Type.u64, dst_mcv, masked_mcv); |
| 4765 | try self.genBinOpMir(.{ ._, .add }, dst_ty, dst_mcv, .{ .immediate = 64 }); | 4765 | try self.genBinOpMir(.{ ._, .add }, dst_ty, dst_mcv, .{ .immediate = 64 }); |
| 4766 | try self.genBinOpMir(.{ ._, .tzcnt }, Type.u64, tmp_mcv, mat_src_mcv); | 4766 | try self.genBinOpMir(.{ ._, .tzcnt }, Type.u64, tmp_mcv, mat_src_mcv); |
| 4767 | try self.asmCmovccRegisterRegister(dst_reg.to32(), tmp_reg.to32(), .nc); | 4767 | try self.asmCmovccRegisterRegister(.nc, dst_reg.to32(), tmp_reg.to32()); |
| 4768 | } else return self.fail("TODO airCtz of {}", .{src_ty.fmt(mod)}); | 4768 | } else return self.fail("TODO airCtz of {}", .{src_ty.fmt(mod)}); |
| 4769 | break :result dst_mcv; | 4769 | break :result dst_mcv; |
| 4770 | } | 4770 | } |
| ... | @@ -4786,9 +4786,9 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4786,9 +4786,9 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 4786 | | 4786 | |
| 4787 | const cmov_abi_size = @max(@as(u32, @intCast(dst_ty.abiSize(mod))), 2); | 4787 | const cmov_abi_size = @max(@as(u32, @intCast(dst_ty.abiSize(mod))), 2); |
| 4788 | try self.asmCmovccRegisterRegister( | 4788 | try self.asmCmovccRegisterRegister( |
| | 4789 | .z, |
| 4789 | registerAlias(dst_reg, cmov_abi_size), | 4790 | registerAlias(dst_reg, cmov_abi_size), |
| 4790 | registerAlias(width_reg, cmov_abi_size), | 4791 | registerAlias(width_reg, cmov_abi_size), |
| 4791 | .z, | | |
| 4792 | ); | 4792 | ); |
| 4793 | break :result dst_mcv; | 4793 | break :result dst_mcv; |
| 4794 | }; | 4794 | }; |
| ... | @@ -5400,21 +5400,21 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5400,21 +5400,21 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void { |
| 5400 | const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2); | 5400 | const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2); |
| 5401 | switch (src_mcv) { | 5401 | switch (src_mcv) { |
| 5402 | .register => |val_reg| try self.asmCmovccRegisterRegister( | 5402 | .register => |val_reg| try self.asmCmovccRegisterRegister( |
| | 5403 | .l, |
| 5403 | registerAlias(dst_mcv.register, cmov_abi_size), | 5404 | registerAlias(dst_mcv.register, cmov_abi_size), |
| 5404 | registerAlias(val_reg, cmov_abi_size), | 5405 | registerAlias(val_reg, cmov_abi_size), |
| 5405 | .l, | | |
| 5406 | ), | 5406 | ), |
| 5407 | .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory( | 5407 | .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory( |
| | 5408 | .l, |
| 5408 | registerAlias(dst_mcv.register, cmov_abi_size), | 5409 | registerAlias(dst_mcv.register, cmov_abi_size), |
| 5409 | src_mcv.mem(Memory.PtrSize.fromSize(cmov_abi_size)), | 5410 | src_mcv.mem(Memory.PtrSize.fromSize(cmov_abi_size)), |
| 5410 | .l, | | |
| 5411 | ), | 5411 | ), |
| 5412 | else => { | 5412 | else => { |
| 5413 | const val_reg = try self.copyToTmpRegister(ty, src_mcv); | 5413 | const val_reg = try self.copyToTmpRegister(ty, src_mcv); |
| 5414 | try self.asmCmovccRegisterRegister( | 5414 | try self.asmCmovccRegisterRegister( |
| | 5415 | .l, |
| 5415 | registerAlias(dst_mcv.register, cmov_abi_size), | 5416 | registerAlias(dst_mcv.register, cmov_abi_size), |
| 5416 | registerAlias(val_reg, cmov_abi_size), | 5417 | registerAlias(val_reg, cmov_abi_size), |
| 5417 | .l, | | |
| 5418 | ); | 5418 | ); |
| 5419 | }, | 5419 | }, |
| 5420 | } | 5420 | } |
| ... | @@ -6605,11 +6605,11 @@ fn genShiftBinOpMir( | ... | @@ -6605,11 +6605,11 @@ fn genShiftBinOpMir( |
| 6605 | Immediate.u(64), | 6605 | Immediate.u(64), |
| 6606 | ); | 6606 | ); |
| 6607 | try self.asmCmovccRegisterRegister( | 6607 | try self.asmCmovccRegisterRegister( |
| | 6608 | .ae, |
| 6608 | lhs_regs[info.indices[1]], | 6609 | lhs_regs[info.indices[1]], |
| 6609 | lhs_regs[info.indices[0]], | 6610 | lhs_regs[info.indices[0]], |
| 6610 | .ae, | | |
| 6611 | ); | 6611 | ); |
| 6612 | try self.asmCmovccRegisterRegister(lhs_regs[info.indices[0]], tmp_reg, .ae); | 6612 | try self.asmCmovccRegisterRegister(.ae, lhs_regs[info.indices[0]], tmp_reg); |
| 6613 | }, | 6613 | }, |
| 6614 | else => return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{ | 6614 | else => return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{ |
| 6615 | @tagName(lhs_mcv), | 6615 | @tagName(lhs_mcv), |
| ... | @@ -6737,8 +6737,8 @@ fn genShiftBinOpMir( | ... | @@ -6737,8 +6737,8 @@ fn genShiftBinOpMir( |
| 6737 | registerAlias(rhs_reg, 1), | 6737 | registerAlias(rhs_reg, 1), |
| 6738 | Immediate.u(64), | 6738 | Immediate.u(64), |
| 6739 | ); | 6739 | ); |
| 6740 | try self.asmCmovccRegisterRegister(second_reg, first_reg, .ae); | 6740 | try self.asmCmovccRegisterRegister(.ae, second_reg, first_reg); |
| 6741 | try self.asmCmovccRegisterRegister(first_reg, tmp_reg, .ae); | 6741 | try self.asmCmovccRegisterRegister(.ae, first_reg, tmp_reg); |
| 6742 | try self.asmMemoryRegister( | 6742 | try self.asmMemoryRegister( |
| 6743 | .{ ._, .mov }, | 6743 | .{ ._, .mov }, |
| 6744 | Memory.sib(.qword, .{ | 6744 | Memory.sib(.qword, .{ |
| ... | @@ -7138,17 +7138,22 @@ fn genBinOp( | ... | @@ -7138,17 +7138,22 @@ fn genBinOp( |
| 7138 | .Float, .Vector => true, | 7138 | .Float, .Vector => true, |
| 7139 | }; | 7139 | }; |
| 7140 | | 7140 | |
| 7141 | const lhs_lock: ?RegisterLock = switch (lhs_mcv) { | 7141 | const lhs_locks: [2]?RegisterLock = switch (lhs_mcv) { |
| 7142 | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), | 7142 | .register => |lhs_reg| .{ self.register_manager.lockRegAssumeUnused(lhs_reg), null }, |
| 7143 | else => null, | 7143 | .register_pair => |lhs_regs| locks: { |
| | 7144 | const locks = self.register_manager.lockRegsAssumeUnused(2, lhs_regs); |
| | 7145 | break :locks .{ locks[0], locks[1] }; |
| | 7146 | }, |
| | 7147 | else => .{ null, null }, |
| 7144 | }; | 7148 | }; |
| 7145 | defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock); | 7149 | defer for (lhs_locks) |lhs_lock| if (lhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 7146 | | 7150 | |
| 7147 | const rhs_lock: ?RegisterLock = switch (rhs_mcv) { | 7151 | const rhs_locks: [2]?RegisterLock = switch (rhs_mcv) { |
| 7148 | .register => |reg| self.register_manager.lockReg(reg), | 7152 | .register => |rhs_reg| .{ self.register_manager.lockReg(rhs_reg), null }, |
| 7149 | else => null, | 7153 | .register_pair => |rhs_regs| self.register_manager.lockRegs(2, rhs_regs), |
| | 7154 | else => .{ null, null }, |
| 7150 | }; | 7155 | }; |
| 7151 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); | 7156 | defer for (rhs_locks) |rhs_lock| if (rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 7152 | | 7157 | |
| 7153 | var flipped = false; | 7158 | var flipped = false; |
| 7154 | var copied_to_dst = true; | 7159 | var copied_to_dst = true; |
| ... | @@ -7171,11 +7176,12 @@ fn genBinOp( | ... | @@ -7171,11 +7176,12 @@ fn genBinOp( |
| 7171 | try self.genCopy(lhs_ty, dst_mcv, lhs_mcv); | 7176 | try self.genCopy(lhs_ty, dst_mcv, lhs_mcv); |
| 7172 | break :dst dst_mcv; | 7177 | break :dst dst_mcv; |
| 7173 | }; | 7178 | }; |
| 7174 | const dst_lock: ?RegisterLock = switch (dst_mcv) { | 7179 | const dst_locks: [2]?RegisterLock = switch (dst_mcv) { |
| 7175 | .register => |reg| self.register_manager.lockReg(reg), | 7180 | .register => |dst_reg| .{ self.register_manager.lockReg(dst_reg), null }, |
| 7176 | else => null, | 7181 | .register_pair => |dst_regs| self.register_manager.lockRegs(2, dst_regs), |
| | 7182 | else => .{ null, null }, |
| 7177 | }; | 7183 | }; |
| 7178 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | 7184 | defer for (dst_locks) |dst_lock| if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 7179 | | 7185 | |
| 7180 | const unmat_src_mcv = if (flipped) lhs_mcv else rhs_mcv; | 7186 | const unmat_src_mcv = if (flipped) lhs_mcv else rhs_mcv; |
| 7181 | const src_mcv: MCValue = if (maybe_mask_reg) |mask_reg| | 7187 | const src_mcv: MCValue = if (maybe_mask_reg) |mask_reg| |
| ... | @@ -7186,6 +7192,12 @@ fn genBinOp( | ... | @@ -7186,6 +7192,12 @@ fn genBinOp( |
| 7186 | } | 7192 | } |
| 7187 | else | 7193 | else |
| 7188 | unmat_src_mcv; | 7194 | unmat_src_mcv; |
| | 7195 | const src_locks: [2]?RegisterLock = switch (src_mcv) { |
| | 7196 | .register => |src_reg| .{ self.register_manager.lockReg(src_reg), null }, |
| | 7197 | .register_pair => |src_regs| self.register_manager.lockRegs(2, src_regs), |
| | 7198 | else => .{ null, null }, |
| | 7199 | }; |
| | 7200 | defer for (src_locks) |src_lock| if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 7189 | | 7201 | |
| 7190 | if (!vec_op) { | 7202 | if (!vec_op) { |
| 7191 | switch (air_tag) { | 7203 | switch (air_tag) { |
| ... | @@ -7236,102 +7248,166 @@ fn genBinOp( | ... | @@ -7236,102 +7248,166 @@ fn genBinOp( |
| 7236 | else => src_mcv, | 7248 | else => src_mcv, |
| 7237 | .air_ref => |src_ref| try self.resolveInst(src_ref), | 7249 | .air_ref => |src_ref| try self.resolveInst(src_ref), |
| 7238 | }; | 7250 | }; |
| 7239 | const mat_src_mcv: MCValue = if (switch (resolved_src_mcv) { | | |
| 7240 | .immediate, | | |
| 7241 | .eflags, | | |
| 7242 | .register_offset, | | |
| 7243 | .load_direct, | | |
| 7244 | .lea_direct, | | |
| 7245 | .load_got, | | |
| 7246 | .lea_got, | | |
| 7247 | .load_tlv, | | |
| 7248 | .lea_tlv, | | |
| 7249 | .lea_frame, | | |
| 7250 | => true, | | |
| 7251 | .memory => |addr| math.cast(i32, @as(i64, @bitCast(addr))) == null, | | |
| 7252 | else => false, | | |
| 7253 | .register_pair, | | |
| 7254 | .register_overflow, | | |
| 7255 | => unreachable, | | |
| 7256 | }) | | |
| 7257 | .{ .register = try self.copyToTmpRegister(rhs_ty, resolved_src_mcv) } | | |
| 7258 | else | | |
| 7259 | resolved_src_mcv; | | |
| 7260 | const mat_mcv_lock = switch (mat_src_mcv) { | | |
| 7261 | .register => |reg| self.register_manager.lockReg(reg), | | |
| 7262 | else => null, | | |
| 7263 | }; | | |
| 7264 | defer if (mat_mcv_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 7265 | | 7251 | |
| 7266 | try self.genBinOpMir(.{ ._, .cmp }, lhs_ty, dst_mcv, mat_src_mcv); | 7252 | if (abi_size > 8) { |
| | 7253 | const dst_regs = switch (dst_mcv) { |
| | 7254 | .register_pair => |dst_regs| dst_regs, |
| | 7255 | else => dst: { |
| | 7256 | const dst_regs = try self.register_manager.allocRegs( |
| | 7257 | 2, |
| | 7258 | .{ null, null }, |
| | 7259 | abi.RegisterClass.gp, |
| | 7260 | ); |
| | 7261 | const dst_regs_locks = self.register_manager.lockRegs(2, dst_regs); |
| | 7262 | for (dst_regs_locks) |dst_lock| if (dst_lock) |lock| |
| | 7263 | self.register_manager.unlockReg(lock); |
| 7267 | | 7264 | |
| 7268 | const int_info = lhs_ty.intInfo(mod); | 7265 | try self.genCopy(lhs_ty, .{ .register_pair = dst_regs }, dst_mcv); |
| 7269 | const cc: Condition = switch (int_info.signedness) { | 7266 | break :dst dst_regs; |
| 7270 | .unsigned => switch (air_tag) { | 7267 | }, |
| 7271 | .min => .a, | 7268 | }; |
| 7272 | .max => .b, | 7269 | const dst_regs_locks = self.register_manager.lockRegs(2, dst_regs); |
| 7273 | else => unreachable, | 7270 | for (dst_regs_locks) |dst_lock| if (dst_lock) |lock| |
| 7274 | }, | 7271 | self.register_manager.unlockReg(lock); |
| 7275 | .signed => switch (air_tag) { | 7272 | |
| 7276 | .min => .g, | 7273 | const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 7277 | .max => .l, | 7274 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| | 7275 | defer self.register_manager.unlockReg(tmp_lock); |
| | 7276 | |
| | 7277 | const signed = lhs_ty.isSignedInt(mod); |
| | 7278 | const cc: Condition = switch (air_tag) { |
| | 7279 | .min => if (signed) .nl else .nb, |
| | 7280 | .max => if (signed) .nge else .nae, |
| 7278 | else => unreachable, | 7281 | else => unreachable, |
| 7279 | }, | 7282 | }; |
| 7280 | }; | | |
| 7281 | | 7283 | |
| 7282 | const cmov_abi_size = @max(@as(u32, @intCast(lhs_ty.abiSize(mod))), 2); | 7284 | try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, dst_regs[1]); |
| 7283 | const tmp_reg = switch (dst_mcv) { | 7285 | if (src_mcv.isMemory()) { |
| 7284 | .register => |reg| reg, | 7286 | try self.asmRegisterMemory(.{ ._, .cmp }, dst_regs[0], src_mcv.mem(.qword)); |
| 7285 | else => try self.copyToTmpRegister(lhs_ty, dst_mcv), | 7287 | try self.asmRegisterMemory( |
| 7286 | }; | 7288 | .{ ._, .sbb }, |
| 7287 | const tmp_lock = self.register_manager.lockReg(tmp_reg); | 7289 | tmp_reg, |
| 7288 | defer if (tmp_lock) |lock| self.register_manager.unlockReg(lock); | 7290 | src_mcv.address().offset(8).deref().mem(.qword), |
| 7289 | switch (mat_src_mcv) { | 7291 | ); |
| 7290 | .none, | 7292 | try self.asmCmovccRegisterMemory(cc, dst_regs[0], src_mcv.mem(.qword)); |
| 7291 | .unreach, | 7293 | try self.asmCmovccRegisterMemory( |
| 7292 | .dead, | 7294 | cc, |
| 7293 | .undef, | 7295 | dst_regs[1], |
| 7294 | .immediate, | 7296 | src_mcv.address().offset(8).deref().mem(.qword), |
| 7295 | .eflags, | 7297 | ); |
| 7296 | .register_pair, | 7298 | } else { |
| 7297 | .register_offset, | 7299 | try self.asmRegisterRegister( |
| 7298 | .register_overflow, | 7300 | .{ ._, .cmp }, |
| 7299 | .load_direct, | 7301 | dst_regs[0], |
| 7300 | .lea_direct, | 7302 | src_mcv.register_pair[0], |
| 7301 | .load_got, | 7303 | ); |
| 7302 | .lea_got, | 7304 | try self.asmRegisterRegister( |
| 7303 | .load_tlv, | 7305 | .{ ._, .sbb }, |
| 7304 | .lea_tlv, | 7306 | tmp_reg, |
| 7305 | .lea_frame, | 7307 | src_mcv.register_pair[1], |
| 7306 | .reserved_frame, | 7308 | ); |
| 7307 | .air_ref, | 7309 | try self.asmCmovccRegisterRegister(cc, dst_regs[0], src_mcv.register_pair[0]); |
| 7308 | => unreachable, | 7310 | try self.asmCmovccRegisterRegister(cc, dst_regs[1], src_mcv.register_pair[1]); |
| 7309 | .register => |src_reg| try self.asmCmovccRegisterRegister( | 7311 | } |
| 7310 | registerAlias(tmp_reg, cmov_abi_size), | 7312 | try self.genCopy(lhs_ty, dst_mcv, .{ .register_pair = dst_regs }); |
| 7311 | registerAlias(src_reg, cmov_abi_size), | 7313 | } else { |
| 7312 | cc, | 7314 | const mat_src_mcv: MCValue = if (switch (resolved_src_mcv) { |
| 7313 | ), | 7315 | .immediate, |
| 7314 | .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory( | 7316 | .eflags, |
| 7315 | registerAlias(tmp_reg, cmov_abi_size), | 7317 | .register_offset, |
| 7316 | Memory.sib(Memory.PtrSize.fromSize(cmov_abi_size), switch (mat_src_mcv) { | 7318 | .load_direct, |
| 7317 | .memory => |addr| .{ | 7319 | .lea_direct, |
| 7318 | .base = .{ .reg = .ds }, | 7320 | .load_got, |
| 7319 | .disp = @intCast(@as(i64, @bitCast(addr))), | 7321 | .lea_got, |
| 7320 | }, | 7322 | .load_tlv, |
| 7321 | .indirect => |reg_off| .{ | 7323 | .lea_tlv, |
| 7322 | .base = .{ .reg = reg_off.reg }, | 7324 | .lea_frame, |
| 7323 | .disp = reg_off.off, | 7325 | => true, |
| 7324 | }, | 7326 | .memory => |addr| math.cast(i32, @as(i64, @bitCast(addr))) == null, |
| 7325 | .load_frame => |frame_addr| .{ | 7327 | else => false, |
| 7326 | .base = .{ .frame = frame_addr.index }, | 7328 | .register_pair, |
| 7327 | .disp = frame_addr.off, | 7329 | .register_overflow, |
| 7328 | }, | 7330 | => unreachable, |
| | 7331 | }) |
| | 7332 | .{ .register = try self.copyToTmpRegister(rhs_ty, resolved_src_mcv) } |
| | 7333 | else |
| | 7334 | resolved_src_mcv; |
| | 7335 | const mat_mcv_lock = switch (mat_src_mcv) { |
| | 7336 | .register => |reg| self.register_manager.lockReg(reg), |
| | 7337 | else => null, |
| | 7338 | }; |
| | 7339 | defer if (mat_mcv_lock) |lock| self.register_manager.unlockReg(lock); |
| | 7340 | |
| | 7341 | try self.genBinOpMir(.{ ._, .cmp }, lhs_ty, dst_mcv, mat_src_mcv); |
| | 7342 | |
| | 7343 | const int_info = lhs_ty.intInfo(mod); |
| | 7344 | const cc: Condition = switch (int_info.signedness) { |
| | 7345 | .unsigned => switch (air_tag) { |
| | 7346 | .min => .a, |
| | 7347 | .max => .b, |
| 7329 | else => unreachable, | 7348 | else => unreachable, |
| 7330 | }), | 7349 | }, |
| 7331 | cc, | 7350 | .signed => switch (air_tag) { |
| 7332 | ), | 7351 | .min => .g, |
| | 7352 | .max => .l, |
| | 7353 | else => unreachable, |
| | 7354 | }, |
| | 7355 | }; |
| | 7356 | |
| | 7357 | const cmov_abi_size = @max(@as(u32, @intCast(lhs_ty.abiSize(mod))), 2); |
| | 7358 | const tmp_reg = switch (dst_mcv) { |
| | 7359 | .register => |reg| reg, |
| | 7360 | else => try self.copyToTmpRegister(lhs_ty, dst_mcv), |
| | 7361 | }; |
| | 7362 | const tmp_lock = self.register_manager.lockReg(tmp_reg); |
| | 7363 | defer if (tmp_lock) |lock| self.register_manager.unlockReg(lock); |
| | 7364 | switch (mat_src_mcv) { |
| | 7365 | .none, |
| | 7366 | .unreach, |
| | 7367 | .dead, |
| | 7368 | .undef, |
| | 7369 | .immediate, |
| | 7370 | .eflags, |
| | 7371 | .register_pair, |
| | 7372 | .register_offset, |
| | 7373 | .register_overflow, |
| | 7374 | .load_direct, |
| | 7375 | .lea_direct, |
| | 7376 | .load_got, |
| | 7377 | .lea_got, |
| | 7378 | .load_tlv, |
| | 7379 | .lea_tlv, |
| | 7380 | .lea_frame, |
| | 7381 | .reserved_frame, |
| | 7382 | .air_ref, |
| | 7383 | => unreachable, |
| | 7384 | .register => |src_reg| try self.asmCmovccRegisterRegister( |
| | 7385 | cc, |
| | 7386 | registerAlias(tmp_reg, cmov_abi_size), |
| | 7387 | registerAlias(src_reg, cmov_abi_size), |
| | 7388 | ), |
| | 7389 | .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory( |
| | 7390 | cc, |
| | 7391 | registerAlias(tmp_reg, cmov_abi_size), |
| | 7392 | Memory.sib(Memory.PtrSize.fromSize(cmov_abi_size), switch (mat_src_mcv) { |
| | 7393 | .memory => |addr| .{ |
| | 7394 | .base = .{ .reg = .ds }, |
| | 7395 | .disp = @intCast(@as(i64, @bitCast(addr))), |
| | 7396 | }, |
| | 7397 | .indirect => |reg_off| .{ |
| | 7398 | .base = .{ .reg = reg_off.reg }, |
| | 7399 | .disp = reg_off.off, |
| | 7400 | }, |
| | 7401 | .load_frame => |frame_addr| .{ |
| | 7402 | .base = .{ .frame = frame_addr.index }, |
| | 7403 | .disp = frame_addr.off, |
| | 7404 | }, |
| | 7405 | else => unreachable, |
| | 7406 | }), |
| | 7407 | ), |
| | 7408 | } |
| | 7409 | try self.genCopy(lhs_ty, dst_mcv, .{ .register = tmp_reg }); |
| 7333 | } | 7410 | } |
| 7334 | try self.genCopy(lhs_ty, dst_mcv, .{ .register = tmp_reg }); | | |
| 7335 | }, | 7411 | }, |
| 7336 | | 7412 | |
| 7337 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ | 7413 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ |
| ... | @@ -12053,21 +12129,21 @@ fn atomicOp( | ... | @@ -12053,21 +12129,21 @@ fn atomicOp( |
| 12053 | const cmov_abi_size = @max(val_abi_size, 2); | 12129 | const cmov_abi_size = @max(val_abi_size, 2); |
| 12054 | switch (val_mcv) { | 12130 | switch (val_mcv) { |
| 12055 | .register => |val_reg| try self.asmCmovccRegisterRegister( | 12131 | .register => |val_reg| try self.asmCmovccRegisterRegister( |
| | 12132 | cc, |
| 12056 | registerAlias(tmp_reg, cmov_abi_size), | 12133 | registerAlias(tmp_reg, cmov_abi_size), |
| 12057 | registerAlias(val_reg, cmov_abi_size), | 12134 | registerAlias(val_reg, cmov_abi_size), |
| 12058 | cc, | | |
| 12059 | ), | 12135 | ), |
| 12060 | .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory( | 12136 | .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory( |
| | 12137 | cc, |
| 12061 | registerAlias(tmp_reg, cmov_abi_size), | 12138 | registerAlias(tmp_reg, cmov_abi_size), |
| 12062 | val_mcv.mem(Memory.PtrSize.fromSize(cmov_abi_size)), | 12139 | val_mcv.mem(Memory.PtrSize.fromSize(cmov_abi_size)), |
| 12063 | cc, | | |
| 12064 | ), | 12140 | ), |
| 12065 | else => { | 12141 | else => { |
| 12066 | const val_reg = try self.copyToTmpRegister(val_ty, val_mcv); | 12142 | const val_reg = try self.copyToTmpRegister(val_ty, val_mcv); |
| 12067 | try self.asmCmovccRegisterRegister( | 12143 | try self.asmCmovccRegisterRegister( |
| | 12144 | cc, |
| 12068 | registerAlias(tmp_reg, cmov_abi_size), | 12145 | registerAlias(tmp_reg, cmov_abi_size), |
| 12069 | registerAlias(val_reg, cmov_abi_size), | 12146 | registerAlias(val_reg, cmov_abi_size), |
| 12070 | cc, | | |
| 12071 | ); | 12147 | ); |
| 12072 | }, | 12148 | }, |
| 12073 | } | 12149 | } |