| ... | ... | @@ -5553,7 +5553,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5553 | 5553 | return func.fail("TODO: Implement overflow arithmetic for integer bitsize: {d}", .{int_info.bits}); |
| 5554 | 5554 | }; |
| 5555 | 5555 | |
| 5556 | | if (wasm_bits > 32) { |
| 5556 | if (wasm_bits > 64) { |
| 5557 | 5557 | return func.fail("TODO: Implement `@mulWithOverflow` for integer bitsize: {d}", .{int_info.bits}); |
| 5558 | 5558 | } |
| 5559 | 5559 | |
| ... | ... | @@ -5586,7 +5586,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5586 | 5586 | try func.addLabel(.local_set, overflow_bit.local.value); |
| 5587 | 5587 | break :blk down_cast; |
| 5588 | 5588 | } |
| 5589 | | } else if (int_info.signedness == .signed) blk: { |
| 5589 | } else if (int_info.signedness == .signed and wasm_bits == 32) blk: { |
| 5590 | 5590 | const lhs_abs = try func.signAbsValue(lhs, lhs_ty); |
| 5591 | 5591 | const rhs_abs = try func.signAbsValue(rhs, lhs_ty); |
| 5592 | 5592 | const bin_op = try (try func.binOp(lhs_abs, rhs_abs, lhs_ty, .mul)).toLocal(func, lhs_ty); |
| ... | ... | @@ -5594,7 +5594,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5594 | 5594 | _ = try func.cmp(mul_abs, bin_op, lhs_ty, .neq); |
| 5595 | 5595 | try func.addLabel(.local_set, overflow_bit.local.value); |
| 5596 | 5596 | break :blk try func.wrapOperand(bin_op, lhs_ty); |
| 5597 | | } else blk: { |
| 5597 | } else if (wasm_bits == 32) blk: { |
| 5598 | 5598 | var bin_op = try (try func.binOp(lhs, rhs, lhs_ty, .mul)).toLocal(func, lhs_ty); |
| 5599 | 5599 | defer bin_op.free(func); |
| 5600 | 5600 | const shift_imm = if (wasm_bits == 32) |
| ... | ... | @@ -5605,7 +5605,40 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5605 | 5605 | _ = try func.cmp(shr, zero, lhs_ty, .neq); |
| 5606 | 5606 | try func.addLabel(.local_set, overflow_bit.local.value); |
| 5607 | 5607 | break :blk try func.wrapOperand(bin_op, lhs_ty); |
| 5608 | | }; |
| 5608 | } else if (int_info.bits == 64 and int_info.signedness == .unsigned) blk: { |
| 5609 | const new_ty = Type.initTag(.u128); |
| 5610 | var lhs_upcast = try (try func.intcast(lhs, lhs_ty, new_ty)).toLocal(func, lhs_ty); |
| 5611 | defer lhs_upcast.free(func); |
| 5612 | var rhs_upcast = try (try func.intcast(rhs, lhs_ty, new_ty)).toLocal(func, lhs_ty); |
| 5613 | defer rhs_upcast.free(func); |
| 5614 | const bin_op = try func.binOp(lhs_upcast, rhs_upcast, new_ty, .mul); |
| 5615 | const lsb = try func.load(bin_op, lhs_ty, 8); |
| 5616 | _ = try func.cmp(lsb, zero, lhs_ty, .neq); |
| 5617 | try func.addLabel(.local_set, overflow_bit.local.value); |
| 5618 | |
| 5619 | break :blk try func.load(bin_op, lhs_ty, 0); |
| 5620 | } else if (int_info.bits == 64 and int_info.signedness == .signed) blk: { |
| 5621 | const shift_val: WValue = .{ .imm64 = 63 }; |
| 5622 | var lhs_shifted = try (try func.binOp(lhs, shift_val, lhs_ty, .shr)).toLocal(func, lhs_ty); |
| 5623 | defer lhs_shifted.free(func); |
| 5624 | var rhs_shifted = try (try func.binOp(rhs, shift_val, lhs_ty, .shr)).toLocal(func, lhs_ty); |
| 5625 | defer rhs_shifted.free(func); |
| 5626 | |
| 5627 | const bin_op = try func.callIntrinsic( |
| 5628 | "__multi3", |
| 5629 | &[_]Type{Type.i64} ** 4, |
| 5630 | Type.initTag(.i128), |
| 5631 | &.{ lhs, lhs_shifted, rhs, rhs_shifted }, |
| 5632 | ); |
| 5633 | const res = try func.allocLocal(lhs_ty); |
| 5634 | const msb = try func.load(bin_op, lhs_ty, 0); |
| 5635 | try func.addLabel(.local_tee, res.local.value); |
| 5636 | const msb_shifted = try func.binOp(msb, shift_val, lhs_ty, .shr); |
| 5637 | const lsb = try func.load(bin_op, lhs_ty, 8); |
| 5638 | _ = try func.cmp(lsb, msb_shifted, lhs_ty, .neq); |
| 5639 | try func.addLabel(.local_set, overflow_bit.local.value); |
| 5640 | break :blk res; |
| 5641 | } else return func.fail("TODO: @mulWithOverflow for integers between 32 and 64 bits", .{}); |
| 5609 | 5642 | var bin_op_local = try bin_op.toLocal(func, lhs_ty); |
| 5610 | 5643 | defer bin_op_local.free(func); |
| 5611 | 5644 | |