authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-25 17:15:48-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-26 21:45:57-04:00
log5e83441096ca77b379be55ad2c197f70ce374eac
treee7d6616bb07da1bf53af1bafe1d735433af198e1
parentda06269d706087207fc94c2039006f2f2d18aa2e

x86_64: implement `@divFloor` and `@mod` for `i128`


8 files changed, 147 insertions(+), 87 deletions(-)

lib/std/fs.zig+1-3
...@@ -3248,9 +3248,7 @@ test {...@@ -3248,9 +3248,7 @@ test {
3248 _ = &makeDirAbsolute;3248 _ = &makeDirAbsolute;
3249 _ = &makeDirAbsoluteZ;3249 _ = &makeDirAbsoluteZ;
3250 _ = &copyFileAbsolute;3250 _ = &copyFileAbsolute;
3251 if (builtin.zig_backend != .stage2_x86_64) {3251 _ = &updateFileAbsolute;
3252 _ = &updateFileAbsolute;
3253 }
3254 }3252 }
3255 _ = &Dir.copyFile;3253 _ = &Dir.copyFile;
3256 _ = @import("fs/test.zig");3254 _ = @import("fs/test.zig");
lib/std/fs/test.zig-4
...@@ -1460,8 +1460,6 @@ test "walker without fully iterating" {...@@ -1460,8 +1460,6 @@ test "walker without fully iterating" {
1460test ". and .. in fs.Dir functions" {1460test ". and .. in fs.Dir functions" {
1461 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;1461 if (builtin.os.tag == .wasi and builtin.link_libc) return error.SkipZigTest;
14621462
1463 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1464
1465 if (builtin.os.tag == .windows and builtin.cpu.arch == .aarch64) {1463 if (builtin.os.tag == .windows and builtin.cpu.arch == .aarch64) {
1466 // https://github.com/ziglang/zig/issues/171341464 // https://github.com/ziglang/zig/issues/17134
1467 return error.SkipZigTest;1465 return error.SkipZigTest;
...@@ -1502,8 +1500,6 @@ test ". and .. in fs.Dir functions" {...@@ -1502,8 +1500,6 @@ test ". and .. in fs.Dir functions" {
1502test ". and .. in absolute functions" {1500test ". and .. in absolute functions" {
1503 if (builtin.os.tag == .wasi) return error.SkipZigTest;1501 if (builtin.os.tag == .wasi) return error.SkipZigTest;
15041502
1505 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1506
1507 var tmp = tmpDir(.{});1503 var tmp = tmpDir(.{});
1508 defer tmp.cleanup();1504 defer tmp.cleanup();
15091505
lib/std/io/test.zig-2
...@@ -161,8 +161,6 @@ test "setEndPos" {...@@ -161,8 +161,6 @@ test "setEndPos" {
161}161}
162162
163test "updateTimes" {163test "updateTimes" {
164 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
165
166 var tmp = tmpDir(.{});164 var tmp = tmpDir(.{});
167 defer tmp.cleanup();165 defer tmp.cleanup();
168166
lib/std/math/big/int_test.zig-20
...@@ -1182,8 +1182,6 @@ test "big.int div single-single with rem" {...@@ -1182,8 +1182,6 @@ test "big.int div single-single with rem" {
1182}1182}
11831183
1184test "big.int div multi-single no rem" {1184test "big.int div multi-single no rem" {
1185 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1186
1187 var op1: u128 = 0xffffeeeeddddcccc;1185 var op1: u128 = 0xffffeeeeddddcccc;
1188 var op2: u128 = 34;1186 var op2: u128 = 34;
11891187
...@@ -1203,8 +1201,6 @@ test "big.int div multi-single no rem" {...@@ -1203,8 +1201,6 @@ test "big.int div multi-single no rem" {
1203}1201}
12041202
1205test "big.int div multi-single with rem" {1203test "big.int div multi-single with rem" {
1206 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1207
1208 var op1: u128 = 0xffffeeeeddddcccf;1204 var op1: u128 = 0xffffeeeeddddcccf;
1209 var op2: u128 = 34;1205 var op2: u128 = 34;
12101206
...@@ -1224,8 +1220,6 @@ test "big.int div multi-single with rem" {...@@ -1224,8 +1220,6 @@ test "big.int div multi-single with rem" {
1224}1220}
12251221
1226test "big.int div multi>2-single" {1222test "big.int div multi>2-single" {
1227 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1228
1229 var op1: u128 = 0xfefefefefefefefefefefefefefefefe;1223 var op1: u128 = 0xfefefefefefefefefefefefefefefefe;
1230 var op2: u128 = 0xefab8;1224 var op2: u128 = 0xefab8;
12311225
...@@ -1405,8 +1399,6 @@ test "big.int div trunc single-single -/-" {...@@ -1405,8 +1399,6 @@ test "big.int div trunc single-single -/-" {
1405}1399}
14061400
1407test "big.int divTrunc #15535" {1401test "big.int divTrunc #15535" {
1408 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1409
1410 var one = try Managed.initSet(testing.allocator, 1);1402 var one = try Managed.initSet(testing.allocator, 1);
1411 defer one.deinit();1403 defer one.deinit();
1412 var x = try Managed.initSet(testing.allocator, std.math.pow(u128, 2, 64));1404 var x = try Managed.initSet(testing.allocator, std.math.pow(u128, 2, 64));
...@@ -1949,8 +1941,6 @@ test "big.int truncate multi to multi signed" {...@@ -1949,8 +1941,6 @@ test "big.int truncate multi to multi signed" {
1949}1941}
19501942
1951test "big.int truncate negative multi to single" {1943test "big.int truncate negative multi to single" {
1952 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1953
1954 var a = try Managed.initSet(testing.allocator, -@as(SignedDoubleLimb, maxInt(Limb) + 1));1944 var a = try Managed.initSet(testing.allocator, -@as(SignedDoubleLimb, maxInt(Limb) + 1));
1955 defer a.deinit();1945 defer a.deinit();
19561946
...@@ -2362,8 +2352,6 @@ test "big.int bitwise xor simple" {...@@ -2362,8 +2352,6 @@ test "big.int bitwise xor simple" {
2362}2352}
23632353
2364test "big.int bitwise xor multi-limb" {2354test "big.int bitwise xor multi-limb" {
2365 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2366
2367 var x: DoubleLimb = maxInt(Limb) + 1;2355 var x: DoubleLimb = maxInt(Limb) + 1;
2368 var y: DoubleLimb = maxInt(Limb);2356 var y: DoubleLimb = maxInt(Limb);
2369 var a = try Managed.initSet(testing.allocator, x);2357 var a = try Managed.initSet(testing.allocator, x);
...@@ -2538,8 +2526,6 @@ test "big.int var args" {...@@ -2538,8 +2526,6 @@ test "big.int var args" {
2538}2526}
25392527
2540test "big.int gcd non-one small" {2528test "big.int gcd non-one small" {
2541 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2542
2543 var a = try Managed.initSet(testing.allocator, 17);2529 var a = try Managed.initSet(testing.allocator, 17);
2544 defer a.deinit();2530 defer a.deinit();
2545 var b = try Managed.initSet(testing.allocator, 97);2531 var b = try Managed.initSet(testing.allocator, 97);
...@@ -2553,8 +2539,6 @@ test "big.int gcd non-one small" {...@@ -2553,8 +2539,6 @@ test "big.int gcd non-one small" {
2553}2539}
25542540
2555test "big.int gcd non-one medium" {2541test "big.int gcd non-one medium" {
2556 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2557
2558 var a = try Managed.initSet(testing.allocator, 4864);2542 var a = try Managed.initSet(testing.allocator, 4864);
2559 defer a.deinit();2543 defer a.deinit();
2560 var b = try Managed.initSet(testing.allocator, 3458);2544 var b = try Managed.initSet(testing.allocator, 3458);
...@@ -2568,8 +2552,6 @@ test "big.int gcd non-one medium" {...@@ -2568,8 +2552,6 @@ test "big.int gcd non-one medium" {
2568}2552}
25692553
2570test "big.int gcd non-one large" {2554test "big.int gcd non-one large" {
2571 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2572
2573 var a = try Managed.initSet(testing.allocator, 0xffffffffffffffff);2555 var a = try Managed.initSet(testing.allocator, 0xffffffffffffffff);
2574 defer a.deinit();2556 defer a.deinit();
2575 var b = try Managed.initSet(testing.allocator, 0xffffffffffffffff7777);2557 var b = try Managed.initSet(testing.allocator, 0xffffffffffffffff7777);
...@@ -2602,8 +2584,6 @@ test "big.int gcd large multi-limb result" {...@@ -2602,8 +2584,6 @@ test "big.int gcd large multi-limb result" {
2602}2584}
26032585
2604test "big.int gcd one large" {2586test "big.int gcd one large" {
2605 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2606
2607 var a = try Managed.initSet(testing.allocator, 1897056385327307);2587 var a = try Managed.initSet(testing.allocator, 1897056385327307);
2608 defer a.deinit();2588 defer a.deinit();
2609 var b = try Managed.initSet(testing.allocator, 2251799813685248);2589 var b = try Managed.initSet(testing.allocator, 2251799813685248);
lib/std/math/big/rational.zig-20
...@@ -514,8 +514,6 @@ test "big.rational extractLowBits" {...@@ -514,8 +514,6 @@ test "big.rational extractLowBits" {
514}514}
515515
516test "big.rational set" {516test "big.rational set" {
517 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
518
519 var a = try Rational.init(testing.allocator);517 var a = try Rational.init(testing.allocator);
520 defer a.deinit();518 defer a.deinit();
521519
...@@ -615,8 +613,6 @@ test "big.rational set/to Float round-trip" {...@@ -615,8 +613,6 @@ test "big.rational set/to Float round-trip" {
615}613}
616614
617test "big.rational copy" {615test "big.rational copy" {
618 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
619
620 var a = try Rational.init(testing.allocator);616 var a = try Rational.init(testing.allocator);
621 defer a.deinit();617 defer a.deinit();
622618
...@@ -681,8 +677,6 @@ test "big.rational abs" {...@@ -681,8 +677,6 @@ test "big.rational abs" {
681}677}
682678
683test "big.rational swap" {679test "big.rational swap" {
684 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
685
686 var a = try Rational.init(testing.allocator);680 var a = try Rational.init(testing.allocator);
687 defer a.deinit();681 defer a.deinit();
688 var b = try Rational.init(testing.allocator);682 var b = try Rational.init(testing.allocator);
...@@ -707,8 +701,6 @@ test "big.rational swap" {...@@ -707,8 +701,6 @@ test "big.rational swap" {
707}701}
708702
709test "big.rational order" {703test "big.rational order" {
710 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
711
712 var a = try Rational.init(testing.allocator);704 var a = try Rational.init(testing.allocator);
713 defer a.deinit();705 defer a.deinit();
714 var b = try Rational.init(testing.allocator);706 var b = try Rational.init(testing.allocator);
...@@ -724,8 +716,6 @@ test "big.rational order" {...@@ -724,8 +716,6 @@ test "big.rational order" {
724}716}
725717
726test "big.rational order/orderAbs with negative" {718test "big.rational order/orderAbs with negative" {
727 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
728
729 var a = try Rational.init(testing.allocator);719 var a = try Rational.init(testing.allocator);
730 defer a.deinit();720 defer a.deinit();
731 var b = try Rational.init(testing.allocator);721 var b = try Rational.init(testing.allocator);
...@@ -738,8 +728,6 @@ test "big.rational order/orderAbs with negative" {...@@ -738,8 +728,6 @@ test "big.rational order/orderAbs with negative" {
738}728}
739729
740test "big.rational add single-limb" {730test "big.rational add single-limb" {
741 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
742
743 var a = try Rational.init(testing.allocator);731 var a = try Rational.init(testing.allocator);
744 defer a.deinit();732 defer a.deinit();
745 var b = try Rational.init(testing.allocator);733 var b = try Rational.init(testing.allocator);
...@@ -755,8 +743,6 @@ test "big.rational add single-limb" {...@@ -755,8 +743,6 @@ test "big.rational add single-limb" {
755}743}
756744
757test "big.rational add" {745test "big.rational add" {
758 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
759
760 var a = try Rational.init(testing.allocator);746 var a = try Rational.init(testing.allocator);
761 defer a.deinit();747 defer a.deinit();
762 var b = try Rational.init(testing.allocator);748 var b = try Rational.init(testing.allocator);
...@@ -773,8 +759,6 @@ test "big.rational add" {...@@ -773,8 +759,6 @@ test "big.rational add" {
773}759}
774760
775test "big.rational sub" {761test "big.rational sub" {
776 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
777
778 var a = try Rational.init(testing.allocator);762 var a = try Rational.init(testing.allocator);
779 defer a.deinit();763 defer a.deinit();
780 var b = try Rational.init(testing.allocator);764 var b = try Rational.init(testing.allocator);
...@@ -791,8 +775,6 @@ test "big.rational sub" {...@@ -791,8 +775,6 @@ test "big.rational sub" {
791}775}
792776
793test "big.rational mul" {777test "big.rational mul" {
794 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
795
796 var a = try Rational.init(testing.allocator);778 var a = try Rational.init(testing.allocator);
797 defer a.deinit();779 defer a.deinit();
798 var b = try Rational.init(testing.allocator);780 var b = try Rational.init(testing.allocator);
...@@ -809,8 +791,6 @@ test "big.rational mul" {...@@ -809,8 +791,6 @@ test "big.rational mul" {
809}791}
810792
811test "big.rational div" {793test "big.rational div" {
812 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
813
814 {794 {
815 var a = try Rational.init(testing.allocator);795 var a = try Rational.init(testing.allocator);
816 defer a.deinit();796 defer a.deinit();
lib/std/os/linux/io_uring.zig-2
...@@ -2204,8 +2204,6 @@ test "sendmsg/recvmsg" {...@@ -2204,8 +2204,6 @@ test "sendmsg/recvmsg" {
2204test "timeout (after a relative time)" {2204test "timeout (after a relative time)" {
2205 if (builtin.os.tag != .linux) return error.SkipZigTest;2205 if (builtin.os.tag != .linux) return error.SkipZigTest;
22062206
2207 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2208
2209 var ring = IO_Uring.init(1, 0) catch |err| switch (err) {2207 var ring = IO_Uring.init(1, 0) catch |err| switch (err) {
2210 error.SystemOutdated => return error.SkipZigTest,2208 error.SystemOutdated => return error.SkipZigTest,
2211 error.PermissionDenied => return error.SkipZigTest,2209 error.PermissionDenied => return error.SkipZigTest,
lib/std/time.zig-2
...@@ -122,8 +122,6 @@ pub fn nanoTimestamp() i128 {...@@ -122,8 +122,6 @@ pub fn nanoTimestamp() i128 {
122}122}
123123
124test "timestamp" {124test "timestamp" {
125 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
126
127 const margin = ns_per_ms * 50;125 const margin = ns_per_ms * 50;
128126
129 const time_0 = milliTimestamp();127 const time_0 = milliTimestamp();
src/arch/x86_64/CodeGen.zig+146-34
...@@ -3221,6 +3221,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -3221,6 +3221,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
3221 .Float, .Vector => break :result try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs),3221 .Float, .Vector => break :result try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs),
3222 else => {},3222 else => {},
3223 }3223 }
3224 const dst_abi_size: u32 = @intCast(dst_ty.abiSize(mod));
32243225
3225 const dst_info = dst_ty.intInfo(mod);3226 const dst_info = dst_ty.intInfo(mod);
3226 const src_ty = try mod.intType(dst_info.signedness, switch (tag) {3227 const src_ty = try mod.intType(dst_info.signedness, switch (tag) {
...@@ -3232,12 +3233,153 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -3232,12 +3233,153 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
3232 ),3233 ),
3233 .div_trunc, .div_floor, .div_exact, .rem, .mod => dst_info.bits,3234 .div_trunc, .div_floor, .div_exact, .rem, .mod => dst_info.bits,
3234 });3235 });
3236 const src_abi_size: u32 = @intCast(src_ty.abiSize(mod));
3237
3238 if (dst_abi_size == 16 and src_abi_size == 16) switch (tag) {
3239 else => unreachable,
3240 .mul, .mul_wrap => {},
3241 .div_trunc, .div_floor, .div_exact, .rem, .mod => {
3242 const signed = dst_ty.isSignedInt(mod);
3243 var callee_buf: ["__udiv?i3".len]u8 = undefined;
3244 const signed_div_floor_state: struct {
3245 frame_index: FrameIndex,
3246 reloc: Mir.Inst.Index,
3247 } = if (signed and tag == .div_floor) state: {
3248 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(Type.usize, mod));
3249 try self.asmMemoryImmediate(
3250 .{ ._, .mov },
3251 Memory.sib(.qword, .{ .base = .{ .frame = frame_index } }),
3252 Immediate.u(0),
3253 );
3254
3255 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
3256 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
3257 defer self.register_manager.unlockReg(tmp_lock);
3258
3259 const lhs_mcv = try self.resolveInst(bin_op.lhs);
3260 if (lhs_mcv.isMemory()) try self.asmRegisterMemory(
3261 .{ ._, .mov },
3262 tmp_reg,
3263 lhs_mcv.address().offset(8).deref().mem(.qword),
3264 ) else try self.asmRegisterRegister(
3265 .{ ._, .mov },
3266 tmp_reg,
3267 lhs_mcv.register_pair[1],
3268 );
3269
3270 const rhs_mcv = try self.resolveInst(bin_op.rhs);
3271 if (rhs_mcv.isMemory()) try self.asmRegisterMemory(
3272 .{ ._, .xor },
3273 tmp_reg,
3274 rhs_mcv.address().offset(8).deref().mem(.qword),
3275 ) else try self.asmRegisterRegister(
3276 .{ ._, .xor },
3277 tmp_reg,
3278 rhs_mcv.register_pair[1],
3279 );
3280 const reloc = try self.asmJccReloc(.ns, undefined);
3281
3282 break :state .{ .frame_index = frame_index, .reloc = reloc };
3283 } else undefined;
3284 const call_mcv = try self.genCall(
3285 .{ .lib = .{
3286 .return_type = dst_ty.toIntern(),
3287 .param_types = &.{ src_ty.toIntern(), src_ty.toIntern() },
3288 .callee = std.fmt.bufPrint(&callee_buf, "__{s}{s}{c}i3", .{
3289 if (signed) "" else "u",
3290 switch (tag) {
3291 .div_trunc, .div_exact => "div",
3292 .div_floor => if (signed) "mod" else "div",
3293 .rem, .mod => "mod",
3294 else => unreachable,
3295 },
3296 intCompilerRtAbiName(@intCast(dst_ty.bitSize(mod))),
3297 }) catch unreachable,
3298 } },
3299 &.{ src_ty, src_ty },
3300 &.{ .{ .air_ref = bin_op.lhs }, .{ .air_ref = bin_op.rhs } },
3301 );
3302 break :result if (signed) switch (tag) {
3303 .div_floor => {
3304 try self.asmRegisterRegister(
3305 .{ ._, .@"or" },
3306 call_mcv.register_pair[0],
3307 call_mcv.register_pair[1],
3308 );
3309 try self.asmSetccMemory(.nz, Memory.sib(.byte, .{
3310 .base = .{ .frame = signed_div_floor_state.frame_index },
3311 }));
3312 try self.performReloc(signed_div_floor_state.reloc);
3313 const dst_mcv = try self.genCall(
3314 .{ .lib = .{
3315 .return_type = dst_ty.toIntern(),
3316 .param_types = &.{ src_ty.toIntern(), src_ty.toIntern() },
3317 .callee = std.fmt.bufPrint(&callee_buf, "__div{c}i3", .{
3318 intCompilerRtAbiName(@intCast(dst_ty.bitSize(mod))),
3319 }) catch unreachable,
3320 } },
3321 &.{ src_ty, src_ty },
3322 &.{ .{ .air_ref = bin_op.lhs }, .{ .air_ref = bin_op.rhs } },
3323 );
3324 try self.asmRegisterMemory(
3325 .{ ._, .sub },
3326 dst_mcv.register_pair[0],
3327 Memory.sib(.qword, .{
3328 .base = .{ .frame = signed_div_floor_state.frame_index },
3329 }),
3330 );
3331 try self.asmRegisterImmediate(
3332 .{ ._, .sbb },
3333 dst_mcv.register_pair[1],
3334 Immediate.u(0),
3335 );
3336 try self.freeValue(
3337 .{ .load_frame = .{ .index = signed_div_floor_state.frame_index } },
3338 );
3339 break :result dst_mcv;
3340 },
3341 .mod => {
3342 const dst_regs = call_mcv.register_pair;
3343 const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs);
3344 defer for (dst_locks) |lock| self.register_manager.unlockReg(lock);
3345
3346 const tmp_regs =
3347 try self.register_manager.allocRegs(2, .{null} ** 2, abi.RegisterClass.gp);
3348 const tmp_locks = self.register_manager.lockRegsAssumeUnused(2, tmp_regs);
3349 defer for (tmp_locks) |lock| self.register_manager.unlockReg(lock);
3350
3351 const rhs_mcv = try self.resolveInst(bin_op.rhs);
3352
3353 for (tmp_regs, dst_regs) |tmp_reg, dst_reg|
3354 try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, dst_reg);
3355 if (rhs_mcv.isMemory()) {
3356 try self.asmRegisterMemory(.{ ._, .add }, tmp_regs[0], rhs_mcv.mem(.qword));
3357 try self.asmRegisterMemory(
3358 .{ ._, .adc },
3359 tmp_regs[1],
3360 rhs_mcv.address().offset(8).deref().mem(.qword),
3361 );
3362 } else for (
3363 [_]Mir.Inst.Tag{ .add, .adc },
3364 tmp_regs,
3365 rhs_mcv.register_pair,
3366 ) |op, tmp_reg, rhs_reg|
3367 try self.asmRegisterRegister(.{ ._, op }, tmp_reg, rhs_reg);
3368 try self.asmRegisterRegister(.{ ._, .@"test" }, dst_regs[1], dst_regs[1]);
3369 for (dst_regs, tmp_regs) |dst_reg, tmp_reg|
3370 try self.asmCmovccRegisterRegister(.s, dst_reg, tmp_reg);
3371 break :result call_mcv;
3372 },
3373 else => call_mcv,
3374 } else call_mcv;
3375 },
3376 };
32353377
3236 try self.spillEflagsIfOccupied();3378 try self.spillEflagsIfOccupied();
3237 try self.spillRegisters(&.{ .rax, .rdx });3379 try self.spillRegisters(&.{ .rax, .rdx });
3238 const lhs = try self.resolveInst(bin_op.lhs);3380 const lhs_mcv = try self.resolveInst(bin_op.lhs);
3239 const rhs = try self.resolveInst(bin_op.rhs);3381 const rhs_mcv = try self.resolveInst(bin_op.rhs);
3240 break :result try self.genMulDivBinOp(tag, inst, dst_ty, src_ty, lhs, rhs);3382 break :result try self.genMulDivBinOp(tag, inst, dst_ty, src_ty, lhs_mcv, rhs_mcv);
3241 };3383 };
3242 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });3384 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
3243}3385}
...@@ -7201,37 +7343,7 @@ fn genMulDivBinOp(...@@ -7201,37 +7343,7 @@ fn genMulDivBinOp(
7201 assert(self.eflags_inst == null);7343 assert(self.eflags_inst == null);
72027344
7203 if (dst_abi_size == 16 and src_abi_size == 16) {7345 if (dst_abi_size == 16 and src_abi_size == 16) {
7204 switch (tag) {7346 assert(tag == .mul or tag == .mul_wrap);
7205 else => unreachable,
7206 .mul, .mul_wrap => {},
7207 .div_trunc, .div_floor, .div_exact, .rem, .mod => {
7208 const signed = dst_ty.isSignedInt(mod);
7209 if (signed) switch (tag) {
7210 .div_floor, .mod => return self.fail(
7211 "TODO implement genMulDivBinOp for {s} from {} to {}",
7212 .{ @tagName(tag), src_ty.fmt(mod), dst_ty.fmt(mod) },
7213 ),
7214 else => {},
7215 };
7216 var callee_buf: ["__udiv?i3".len]u8 = undefined;
7217 return try self.genCall(.{ .lib = .{
7218 .return_type = dst_ty.toIntern(),
7219 .param_types = &.{ src_ty.toIntern(), src_ty.toIntern() },
7220 .callee = std.fmt.bufPrint(&callee_buf, "__{s}{s}{c}i3", .{
7221 if (signed) "" else "u",
7222 switch (tag) {
7223 .div_trunc, .div_exact => "div",
7224 .div_floor => if (signed) unreachable else "div",
7225 .rem => "mod",
7226 .mod => if (signed) unreachable else "mod",
7227 else => unreachable,
7228 },
7229 intCompilerRtAbiName(@intCast(dst_ty.bitSize(mod))),
7230 }) catch unreachable,
7231 } }, &.{ src_ty, src_ty }, &.{ lhs_mcv, rhs_mcv });
7232 },
7233 }
7234
7235 const reg_locks = self.register_manager.lockRegsAssumeUnused(2, .{ .rax, .rdx });7347 const reg_locks = self.register_manager.lockRegsAssumeUnused(2, .{ .rax, .rdx });
7236 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);7348 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
72377349