authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-09 02:45:03-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-09 03:11:41-04:00
logd559c61902cce2966e9ef9d080dccf6d7e41140e
tree9c4bbe3367ba604b4e3640a466e7636bb94feac1
parent21948d754002d932f27f4f07f5f61061eb49ae1c

x86_64: implement `@min` and `@max` for 128-bit integers


1 files changed, 199 insertions(+), 123 deletions(-)

src/arch/x86_64/CodeGen.zig+199-123
...@@ -1120,7 +1120,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {...@@ -1120,7 +1120,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
1120}1120}
11211121
1122/// A `cc` of `.z_and_np` clobbers `reg2`!1122/// A `cc` of `.z_and_np` clobbers `reg2`!
1123fn asmCmovccRegisterRegister(self: *Self, reg1: Register, reg2: Register, cc: bits.Condition) !void {1123fn 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}
11441144
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!
1146fn asmCmovccRegisterMemory(self: *Self, reg: Register, m: Memory, cc: bits.Condition) !void {1146fn 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 {
32323232
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 );
32393239
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 {
33083308
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 );
33153315
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 );
33783378
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());
46304630
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 {
46604660
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 );
46674667
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 {
46874687
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 );
46944694
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 {
47864786
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 };
71407140
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);
71467150
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);
71527157
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);
71797185
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 else7193 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);
71897201
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);
72657251
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);
72677264
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 };
72817283
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 },
73367412
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 }