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