| ... | ... | @@ -2520,7 +2520,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 2520 | 2520 | tuple_ty: Type, |
| 2521 | 2521 | frame_index: FrameIndex, |
| 2522 | 2522 | src_mcv: MCValue, |
| 2523 | | cc: Condition, |
| 2523 | overflow_cc: ?Condition, |
| 2524 | 2524 | ) !void { |
| 2525 | 2525 | const src_lock = switch (src_mcv) { |
| 2526 | 2526 | .register => |reg| self.register_manager.lockReg(reg), |
| ... | ... | @@ -2551,7 +2551,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 2551 | 2551 | defer for (temp_locks) |lock| self.register_manager.unlockReg(lock); |
| 2552 | 2552 | |
| 2553 | 2553 | const overflow_reg = temp_regs[0]; |
| 2554 | | try self.asmSetccRegister(overflow_reg.to8(), cc); |
| 2554 | if (overflow_cc) |cc| try self.asmSetccRegister(overflow_reg.to8(), cc); |
| 2555 | 2555 | |
| 2556 | 2556 | const scratch_reg = temp_regs[1]; |
| 2557 | 2557 | const hi_limb_off = if (int_info.bits <= 64) 0 else (int_info.bits - 1) / 64 * 8; |
| ... | ... | @@ -2564,8 +2564,10 @@ fn genSetFrameTruncatedOverflowCompare( |
| 2564 | 2564 | try self.genBinOpMir(.cmp, hi_limb_ty, .{ .register = scratch_reg }, hi_limb_mcv); |
| 2565 | 2565 | |
| 2566 | 2566 | const eq_reg = temp_regs[2]; |
| 2567 | | try self.asmSetccRegister(eq_reg.to8(), .ne); |
| 2568 | | try self.genBinOpMir(.@"or", Type.u8, .{ .register = overflow_reg }, .{ .register = eq_reg }); |
| 2567 | if (overflow_cc) |_| { |
| 2568 | try self.asmSetccRegister(eq_reg.to8(), .ne); |
| 2569 | try self.genBinOpMir(.@"or", Type.u8, .{ .register = overflow_reg }, .{ .register = eq_reg }); |
| 2570 | } |
| 2569 | 2571 | |
| 2570 | 2572 | const payload_off = @intCast(i32, tuple_ty.structFieldOffset(0, self.target.*)); |
| 2571 | 2573 | if (hi_limb_off > 0) try self.genSetMem(.{ .frame = frame_index }, payload_off, rest_ty, src_mcv); |
| ... | ... | @@ -2579,7 +2581,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 2579 | 2581 | .{ .frame = frame_index }, |
| 2580 | 2582 | @intCast(i32, tuple_ty.structFieldOffset(1, self.target.*)), |
| 2581 | 2583 | tuple_ty.structFieldType(1), |
| 2582 | | .{ .register = overflow_reg.to8() }, |
| 2584 | if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne }, |
| 2583 | 2585 | ); |
| 2584 | 2586 | } |
| 2585 | 2587 | |
| ... | ... | @@ -2654,27 +2656,36 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2654 | 2656 | try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc); |
| 2655 | 2657 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| 2656 | 2658 | }, |
| 2657 | | // For now, this is the only supported multiply that doesn't fit in a register. |
| 2658 | | else => assert(dst_info.bits <= 128 and src_pl.data == 64), |
| 2659 | | } |
| 2659 | else => { |
| 2660 | // For now, this is the only supported multiply that doesn't fit in a register, |
| 2661 | // so cc being set is impossible. |
| 2660 | 2662 | |
| 2661 | | const frame_index = |
| 2662 | | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*)); |
| 2663 | | if (dst_info.bits >= lhs_active_bits + rhs_active_bits) { |
| 2664 | | try self.genSetMem( |
| 2665 | | .{ .frame = frame_index }, |
| 2666 | | @intCast(i32, tuple_ty.structFieldOffset(0, self.target.*)), |
| 2667 | | tuple_ty.structFieldType(0), |
| 2668 | | partial_mcv, |
| 2669 | | ); |
| 2670 | | try self.genSetMem( |
| 2671 | | .{ .frame = frame_index }, |
| 2672 | | @intCast(i32, tuple_ty.structFieldOffset(1, self.target.*)), |
| 2673 | | tuple_ty.structFieldType(1), |
| 2674 | | .{ .immediate = 0 }, // overflow is impossible for 64-bit*64-bit -> 128-bit |
| 2675 | | ); |
| 2676 | | } else try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc); |
| 2677 | | break :result .{ .load_frame = .{ .index = frame_index } }; |
| 2663 | assert(dst_info.bits <= 128 and src_pl.data == 64); |
| 2664 | |
| 2665 | const frame_index = |
| 2666 | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*)); |
| 2667 | if (dst_info.bits >= lhs_active_bits + rhs_active_bits) { |
| 2668 | try self.genSetMem( |
| 2669 | .{ .frame = frame_index }, |
| 2670 | @intCast(i32, tuple_ty.structFieldOffset(0, self.target.*)), |
| 2671 | tuple_ty.structFieldType(0), |
| 2672 | partial_mcv, |
| 2673 | ); |
| 2674 | try self.genSetMem( |
| 2675 | .{ .frame = frame_index }, |
| 2676 | @intCast(i32, tuple_ty.structFieldOffset(1, self.target.*)), |
| 2677 | tuple_ty.structFieldType(1), |
| 2678 | .{ .immediate = 0 }, |
| 2679 | ); |
| 2680 | } else try self.genSetFrameTruncatedOverflowCompare( |
| 2681 | tuple_ty, |
| 2682 | frame_index, |
| 2683 | partial_mcv, |
| 2684 | null, |
| 2685 | ); |
| 2686 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| 2687 | }, |
| 2688 | } |
| 2678 | 2689 | }, |
| 2679 | 2690 | else => unreachable, |
| 2680 | 2691 | }; |