| ... | ... | @@ -1120,7 +1120,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { |
| 1120 | 1120 | } |
| 1121 | 1121 | |
| 1122 | 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 | 1124 | _ = try self.addInst(.{ |
| 1125 | 1125 | .tag = switch (cc) { |
| 1126 | 1126 | else => .cmov, |
| ... | ... | @@ -1143,7 +1143,7 @@ fn asmCmovccRegisterRegister(self: *Self, reg1: Register, reg2: Register, cc: bi |
| 1143 | 1143 | } |
| 1144 | 1144 | |
| 1145 | 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 | 1147 | _ = try self.addInst(.{ |
| 1148 | 1148 | .tag = switch (cc) { |
| 1149 | 1149 | else => .cmov, |
| ... | ... | @@ -3232,9 +3232,9 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3232 | 3232 | |
| 3233 | 3233 | const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2); |
| 3234 | 3234 | try self.asmCmovccRegisterRegister( |
| 3235 | cc, |
| 3235 | 3236 | registerAlias(dst_reg, cmov_abi_size), |
| 3236 | 3237 | registerAlias(limit_reg, cmov_abi_size), |
| 3237 | | cc, |
| 3238 | 3238 | ); |
| 3239 | 3239 | |
| 3240 | 3240 | if (reg_extra_bits > 0 and ty.isSignedInt(mod)) { |
| ... | ... | @@ -3308,9 +3308,9 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3308 | 3308 | |
| 3309 | 3309 | const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2); |
| 3310 | 3310 | try self.asmCmovccRegisterRegister( |
| 3311 | cc, |
| 3311 | 3312 | registerAlias(dst_reg, cmov_abi_size), |
| 3312 | 3313 | registerAlias(limit_reg, cmov_abi_size), |
| 3313 | | cc, |
| 3314 | 3314 | ); |
| 3315 | 3315 | |
| 3316 | 3316 | if (reg_extra_bits > 0 and ty.isSignedInt(mod)) { |
| ... | ... | @@ -3371,9 +3371,9 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3371 | 3371 | const dst_mcv = try self.genMulDivBinOp(.mul, inst, ty, ty, lhs_mcv, rhs_mcv); |
| 3372 | 3372 | const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2); |
| 3373 | 3373 | try self.asmCmovccRegisterRegister( |
| 3374 | cc, |
| 3374 | 3375 | registerAlias(dst_mcv.register, cmov_abi_size), |
| 3375 | 3376 | registerAlias(limit_reg, cmov_abi_size), |
| 3376 | | cc, |
| 3377 | 3377 | ); |
| 3378 | 3378 | |
| 3379 | 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 | 3743 | registerAlias(.rdx, abi_size), |
| 3744 | 3744 | ); |
| 3745 | 3745 | try self.asmCmovccRegisterRegister( |
| 3746 | .z, |
| 3746 | 3747 | registerAlias(divisor, abi_size), |
| 3747 | 3748 | registerAlias(.rdx, abi_size), |
| 3748 | | .z, |
| 3749 | 3749 | ); |
| 3750 | 3750 | try self.genBinOpMir(.{ ._, .add }, ty, .{ .register = divisor }, .{ .register = .rax }); |
| 3751 | 3751 | return MCValue{ .register = divisor }; |
| ... | ... | @@ -4626,7 +4626,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4626 | 4626 | tmp_mcv, |
| 4627 | 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 | 4631 | if (src_bits < 128) { |
| 4632 | 4632 | try self.genBinOpMir( |
| ... | ... | @@ -4660,9 +4660,9 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4660 | 4660 | |
| 4661 | 4661 | const cmov_abi_size = @max(@as(u32, @intCast(dst_ty.abiSize(mod))), 2); |
| 4662 | 4662 | try self.asmCmovccRegisterRegister( |
| 4663 | .z, |
| 4663 | 4664 | registerAlias(dst_reg, cmov_abi_size), |
| 4664 | 4665 | registerAlias(imm_reg, cmov_abi_size), |
| 4665 | | .z, |
| 4666 | 4666 | ); |
| 4667 | 4667 | |
| 4668 | 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 | 4687 | |
| 4688 | 4688 | const cmov_abi_size = @max(@as(u32, @intCast(dst_ty.abiSize(mod))), 2); |
| 4689 | 4689 | try self.asmCmovccRegisterRegister( |
| 4690 | .nz, |
| 4690 | 4691 | registerAlias(imm_reg, cmov_abi_size), |
| 4691 | 4692 | registerAlias(dst_reg, cmov_abi_size), |
| 4692 | | .nz, |
| 4693 | 4693 | ); |
| 4694 | 4694 | |
| 4695 | 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 | 4764 | try self.genBinOpMir(.{ ._, .tzcnt }, Type.u64, dst_mcv, masked_mcv); |
| 4765 | 4765 | try self.genBinOpMir(.{ ._, .add }, dst_ty, dst_mcv, .{ .immediate = 64 }); |
| 4766 | 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 | 4768 | } else return self.fail("TODO airCtz of {}", .{src_ty.fmt(mod)}); |
| 4769 | 4769 | break :result dst_mcv; |
| 4770 | 4770 | } |
| ... | ... | @@ -4786,9 +4786,9 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 4786 | 4786 | |
| 4787 | 4787 | const cmov_abi_size = @max(@as(u32, @intCast(dst_ty.abiSize(mod))), 2); |
| 4788 | 4788 | try self.asmCmovccRegisterRegister( |
| 4789 | .z, |
| 4789 | 4790 | registerAlias(dst_reg, cmov_abi_size), |
| 4790 | 4791 | registerAlias(width_reg, cmov_abi_size), |
| 4791 | | .z, |
| 4792 | 4792 | ); |
| 4793 | 4793 | break :result dst_mcv; |
| 4794 | 4794 | }; |
| ... | ... | @@ -5400,21 +5400,21 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void { |
| 5400 | 5400 | const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2); |
| 5401 | 5401 | switch (src_mcv) { |
| 5402 | 5402 | .register => |val_reg| try self.asmCmovccRegisterRegister( |
| 5403 | .l, |
| 5403 | 5404 | registerAlias(dst_mcv.register, cmov_abi_size), |
| 5404 | 5405 | registerAlias(val_reg, cmov_abi_size), |
| 5405 | | .l, |
| 5406 | 5406 | ), |
| 5407 | 5407 | .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory( |
| 5408 | .l, |
| 5408 | 5409 | registerAlias(dst_mcv.register, cmov_abi_size), |
| 5409 | 5410 | src_mcv.mem(Memory.PtrSize.fromSize(cmov_abi_size)), |
| 5410 | | .l, |
| 5411 | 5411 | ), |
| 5412 | 5412 | else => { |
| 5413 | 5413 | const val_reg = try self.copyToTmpRegister(ty, src_mcv); |
| 5414 | 5414 | try self.asmCmovccRegisterRegister( |
| 5415 | .l, |
| 5415 | 5416 | registerAlias(dst_mcv.register, cmov_abi_size), |
| 5416 | 5417 | registerAlias(val_reg, cmov_abi_size), |
| 5417 | | .l, |
| 5418 | 5418 | ); |
| 5419 | 5419 | }, |
| 5420 | 5420 | } |
| ... | ... | @@ -6605,11 +6605,11 @@ fn genShiftBinOpMir( |
| 6605 | 6605 | Immediate.u(64), |
| 6606 | 6606 | ); |
| 6607 | 6607 | try self.asmCmovccRegisterRegister( |
| 6608 | .ae, |
| 6608 | 6609 | lhs_regs[info.indices[1]], |
| 6609 | 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 | 6614 | else => return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{ |
| 6615 | 6615 | @tagName(lhs_mcv), |
| ... | ... | @@ -6737,8 +6737,8 @@ fn genShiftBinOpMir( |
| 6737 | 6737 | registerAlias(rhs_reg, 1), |
| 6738 | 6738 | Immediate.u(64), |
| 6739 | 6739 | ); |
| 6740 | | try self.asmCmovccRegisterRegister(second_reg, first_reg, .ae); |
| 6741 | | try self.asmCmovccRegisterRegister(first_reg, tmp_reg, .ae); |
| 6740 | try self.asmCmovccRegisterRegister(.ae, second_reg, first_reg); |
| 6741 | try self.asmCmovccRegisterRegister(.ae, first_reg, tmp_reg); |
| 6742 | 6742 | try self.asmMemoryRegister( |
| 6743 | 6743 | .{ ._, .mov }, |
| 6744 | 6744 | Memory.sib(.qword, .{ |
| ... | ... | @@ -7138,17 +7138,22 @@ fn genBinOp( |
| 7138 | 7138 | .Float, .Vector => true, |
| 7139 | 7139 | }; |
| 7140 | 7140 | |
| 7141 | | const lhs_lock: ?RegisterLock = switch (lhs_mcv) { |
| 7142 | | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), |
| 7143 | | else => null, |
| 7141 | const lhs_locks: [2]?RegisterLock = switch (lhs_mcv) { |
| 7142 | .register => |lhs_reg| .{ self.register_manager.lockRegAssumeUnused(lhs_reg), 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) { |
| 7148 | | .register => |reg| self.register_manager.lockReg(reg), |
| 7149 | | else => null, |
| 7151 | const rhs_locks: [2]?RegisterLock = switch (rhs_mcv) { |
| 7152 | .register => |rhs_reg| .{ self.register_manager.lockReg(rhs_reg), 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 | 7158 | var flipped = false; |
| 7154 | 7159 | var copied_to_dst = true; |
| ... | ... | @@ -7171,11 +7176,12 @@ fn genBinOp( |
| 7171 | 7176 | try self.genCopy(lhs_ty, dst_mcv, lhs_mcv); |
| 7172 | 7177 | break :dst dst_mcv; |
| 7173 | 7178 | }; |
| 7174 | | const dst_lock: ?RegisterLock = switch (dst_mcv) { |
| 7175 | | .register => |reg| self.register_manager.lockReg(reg), |
| 7176 | | else => null, |
| 7179 | const dst_locks: [2]?RegisterLock = switch (dst_mcv) { |
| 7180 | .register => |dst_reg| .{ self.register_manager.lockReg(dst_reg), 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 | 7186 | const unmat_src_mcv = if (flipped) lhs_mcv else rhs_mcv; |
| 7181 | 7187 | const src_mcv: MCValue = if (maybe_mask_reg) |mask_reg| |
| ... | ... | @@ -7186,6 +7192,12 @@ fn genBinOp( |
| 7186 | 7192 | } |
| 7187 | 7193 | else |
| 7188 | 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 | 7202 | if (!vec_op) { |
| 7191 | 7203 | switch (air_tag) { |
| ... | ... | @@ -7236,102 +7248,166 @@ fn genBinOp( |
| 7236 | 7248 | else => src_mcv, |
| 7237 | 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); |
| 7269 | | const cc: Condition = switch (int_info.signedness) { |
| 7270 | | .unsigned => switch (air_tag) { |
| 7271 | | .min => .a, |
| 7272 | | .max => .b, |
| 7273 | | else => unreachable, |
| 7274 | | }, |
| 7275 | | .signed => switch (air_tag) { |
| 7276 | | .min => .g, |
| 7277 | | .max => .l, |
| 7265 | try self.genCopy(lhs_ty, .{ .register_pair = dst_regs }, dst_mcv); |
| 7266 | break :dst dst_regs; |
| 7267 | }, |
| 7268 | }; |
| 7269 | const dst_regs_locks = self.register_manager.lockRegs(2, dst_regs); |
| 7270 | for (dst_regs_locks) |dst_lock| if (dst_lock) |lock| |
| 7271 | self.register_manager.unlockReg(lock); |
| 7272 | |
| 7273 | const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 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 | 7281 | else => unreachable, |
| 7279 | | }, |
| 7280 | | }; |
| 7282 | }; |
| 7281 | 7283 | |
| 7282 | | const cmov_abi_size = @max(@as(u32, @intCast(lhs_ty.abiSize(mod))), 2); |
| 7283 | | const tmp_reg = switch (dst_mcv) { |
| 7284 | | .register => |reg| reg, |
| 7285 | | else => try self.copyToTmpRegister(lhs_ty, dst_mcv), |
| 7286 | | }; |
| 7287 | | const tmp_lock = self.register_manager.lockReg(tmp_reg); |
| 7288 | | defer if (tmp_lock) |lock| self.register_manager.unlockReg(lock); |
| 7289 | | switch (mat_src_mcv) { |
| 7290 | | .none, |
| 7291 | | .unreach, |
| 7292 | | .dead, |
| 7293 | | .undef, |
| 7294 | | .immediate, |
| 7295 | | .eflags, |
| 7296 | | .register_pair, |
| 7297 | | .register_offset, |
| 7298 | | .register_overflow, |
| 7299 | | .load_direct, |
| 7300 | | .lea_direct, |
| 7301 | | .load_got, |
| 7302 | | .lea_got, |
| 7303 | | .load_tlv, |
| 7304 | | .lea_tlv, |
| 7305 | | .lea_frame, |
| 7306 | | .reserved_frame, |
| 7307 | | .air_ref, |
| 7308 | | => unreachable, |
| 7309 | | .register => |src_reg| try self.asmCmovccRegisterRegister( |
| 7310 | | registerAlias(tmp_reg, cmov_abi_size), |
| 7311 | | registerAlias(src_reg, cmov_abi_size), |
| 7312 | | cc, |
| 7313 | | ), |
| 7314 | | .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory( |
| 7315 | | registerAlias(tmp_reg, cmov_abi_size), |
| 7316 | | Memory.sib(Memory.PtrSize.fromSize(cmov_abi_size), switch (mat_src_mcv) { |
| 7317 | | .memory => |addr| .{ |
| 7318 | | .base = .{ .reg = .ds }, |
| 7319 | | .disp = @intCast(@as(i64, @bitCast(addr))), |
| 7320 | | }, |
| 7321 | | .indirect => |reg_off| .{ |
| 7322 | | .base = .{ .reg = reg_off.reg }, |
| 7323 | | .disp = reg_off.off, |
| 7324 | | }, |
| 7325 | | .load_frame => |frame_addr| .{ |
| 7326 | | .base = .{ .frame = frame_addr.index }, |
| 7327 | | .disp = frame_addr.off, |
| 7328 | | }, |
| 7284 | try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, dst_regs[1]); |
| 7285 | if (src_mcv.isMemory()) { |
| 7286 | try self.asmRegisterMemory(.{ ._, .cmp }, dst_regs[0], src_mcv.mem(.qword)); |
| 7287 | try self.asmRegisterMemory( |
| 7288 | .{ ._, .sbb }, |
| 7289 | tmp_reg, |
| 7290 | src_mcv.address().offset(8).deref().mem(.qword), |
| 7291 | ); |
| 7292 | try self.asmCmovccRegisterMemory(cc, dst_regs[0], src_mcv.mem(.qword)); |
| 7293 | try self.asmCmovccRegisterMemory( |
| 7294 | cc, |
| 7295 | dst_regs[1], |
| 7296 | src_mcv.address().offset(8).deref().mem(.qword), |
| 7297 | ); |
| 7298 | } else { |
| 7299 | try self.asmRegisterRegister( |
| 7300 | .{ ._, .cmp }, |
| 7301 | dst_regs[0], |
| 7302 | src_mcv.register_pair[0], |
| 7303 | ); |
| 7304 | try self.asmRegisterRegister( |
| 7305 | .{ ._, .sbb }, |
| 7306 | tmp_reg, |
| 7307 | src_mcv.register_pair[1], |
| 7308 | ); |
| 7309 | try self.asmCmovccRegisterRegister(cc, dst_regs[0], src_mcv.register_pair[0]); |
| 7310 | try self.asmCmovccRegisterRegister(cc, dst_regs[1], src_mcv.register_pair[1]); |
| 7311 | } |
| 7312 | try self.genCopy(lhs_ty, dst_mcv, .{ .register_pair = dst_regs }); |
| 7313 | } else { |
| 7314 | const mat_src_mcv: MCValue = if (switch (resolved_src_mcv) { |
| 7315 | .immediate, |
| 7316 | .eflags, |
| 7317 | .register_offset, |
| 7318 | .load_direct, |
| 7319 | .lea_direct, |
| 7320 | .load_got, |
| 7321 | .lea_got, |
| 7322 | .load_tlv, |
| 7323 | .lea_tlv, |
| 7324 | .lea_frame, |
| 7325 | => true, |
| 7326 | .memory => |addr| math.cast(i32, @as(i64, @bitCast(addr))) == null, |
| 7327 | else => false, |
| 7328 | .register_pair, |
| 7329 | .register_overflow, |
| 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 | 7348 | else => unreachable, |
| 7330 | | }), |
| 7331 | | cc, |
| 7332 | | ), |
| 7349 | }, |
| 7350 | .signed => switch (air_tag) { |
| 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 | 7413 | else => return self.fail("TODO implement genBinOp for {s} {}", .{ |
| ... | ... | @@ -12053,21 +12129,21 @@ fn atomicOp( |
| 12053 | 12129 | const cmov_abi_size = @max(val_abi_size, 2); |
| 12054 | 12130 | switch (val_mcv) { |
| 12055 | 12131 | .register => |val_reg| try self.asmCmovccRegisterRegister( |
| 12132 | cc, |
| 12056 | 12133 | registerAlias(tmp_reg, cmov_abi_size), |
| 12057 | 12134 | registerAlias(val_reg, cmov_abi_size), |
| 12058 | | cc, |
| 12059 | 12135 | ), |
| 12060 | 12136 | .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory( |
| 12137 | cc, |
| 12061 | 12138 | registerAlias(tmp_reg, cmov_abi_size), |
| 12062 | 12139 | val_mcv.mem(Memory.PtrSize.fromSize(cmov_abi_size)), |
| 12063 | | cc, |
| 12064 | 12140 | ), |
| 12065 | 12141 | else => { |
| 12066 | 12142 | const val_reg = try self.copyToTmpRegister(val_ty, val_mcv); |
| 12067 | 12143 | try self.asmCmovccRegisterRegister( |
| 12144 | cc, |
| 12068 | 12145 | registerAlias(tmp_reg, cmov_abi_size), |
| 12069 | 12146 | registerAlias(val_reg, cmov_abi_size), |
| 12070 | | cc, |
| 12071 | 12147 | ); |
| 12072 | 12148 | }, |
| 12073 | 12149 | } |