| ... | @@ -534,7 +534,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -534,7 +534,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 534 | | 534 | |
| 535 | .add_with_overflow => try self.airAddSubWithOverflow(inst), | 535 | .add_with_overflow => try self.airAddSubWithOverflow(inst), |
| 536 | .sub_with_overflow => try self.airAddSubWithOverflow(inst), | 536 | .sub_with_overflow => try self.airAddSubWithOverflow(inst), |
| 537 | .mul_with_overflow => @panic("TODO try self.airMulWithOverflow(inst)"), | 537 | .mul_with_overflow => try self.airMulWithOverflow(inst), |
| 538 | .shl_with_overflow => @panic("TODO try self.airShlWithOverflow(inst)"), | 538 | .shl_with_overflow => @panic("TODO try self.airShlWithOverflow(inst)"), |
| 539 | | 539 | |
| 540 | .div_float, .div_trunc, .div_floor, .div_exact => try self.airDiv(inst), | 540 | .div_float, .div_trunc, .div_floor, .div_exact => try self.airDiv(inst), |
| ... | @@ -1792,6 +1792,73 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1792,6 +1792,73 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void { |
| 1792 | return self.finishAir(inst, .{ .register = mod_reg }, .{ bin_op.lhs, bin_op.rhs, .none }); | 1792 | return self.finishAir(inst, .{ .register = mod_reg }, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1793 | } | 1793 | } |
| 1794 | | 1794 | |
| | 1795 | fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| | 1796 | //const tag = self.air.instructions.items(.tag)[inst]; |
| | 1797 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| | 1798 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| | 1799 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| | 1800 | const lhs = try self.resolveInst(extra.lhs); |
| | 1801 | const rhs = try self.resolveInst(extra.rhs); |
| | 1802 | const lhs_ty = self.air.typeOf(extra.lhs); |
| | 1803 | const rhs_ty = self.air.typeOf(extra.rhs); |
| | 1804 | |
| | 1805 | switch (lhs_ty.zigTypeTag()) { |
| | 1806 | .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}), |
| | 1807 | .Int => { |
| | 1808 | const mod = self.bin_file.options.module.?; |
| | 1809 | assert(lhs_ty.eql(rhs_ty, mod)); |
| | 1810 | const int_info = lhs_ty.intInfo(self.target.*); |
| | 1811 | switch (int_info.bits) { |
| | 1812 | 1...32 => { |
| | 1813 | try self.spillConditionFlagsIfOccupied(); |
| | 1814 | self.condition_flags_inst = inst; |
| | 1815 | |
| | 1816 | const dest = try self.binOp(.mul, lhs, rhs, lhs_ty, rhs_ty, null); |
| | 1817 | |
| | 1818 | const dest_reg = dest.register; |
| | 1819 | const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg); |
| | 1820 | defer self.register_manager.unlockReg(dest_reg_lock); |
| | 1821 | |
| | 1822 | const truncated_reg = try self.register_manager.allocReg(null, gp); |
| | 1823 | const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg); |
| | 1824 | defer self.register_manager.unlockReg(truncated_reg_lock); |
| | 1825 | |
| | 1826 | try self.truncRegister( |
| | 1827 | dest_reg, |
| | 1828 | truncated_reg, |
| | 1829 | int_info.signedness, |
| | 1830 | int_info.bits, |
| | 1831 | ); |
| | 1832 | |
| | 1833 | _ = try self.addInst(.{ |
| | 1834 | .tag = .cmp, |
| | 1835 | .data = .{ .arithmetic_2op = .{ |
| | 1836 | .is_imm = false, |
| | 1837 | .rs1 = dest_reg, |
| | 1838 | .rs2_or_imm = .{ .rs2 = truncated_reg }, |
| | 1839 | } }, |
| | 1840 | }); |
| | 1841 | |
| | 1842 | const cond = Instruction.ICondition.ne; |
| | 1843 | const ccr = Instruction.CCR.xcc; |
| | 1844 | |
| | 1845 | break :result MCValue{ .register_with_overflow = .{ |
| | 1846 | .reg = truncated_reg, |
| | 1847 | .flag = .{ .cond = cond, .ccr = ccr }, |
| | 1848 | } }; |
| | 1849 | }, |
| | 1850 | // XXX DO NOT call __multi3 directly as it'll result in us doing six multiplications, |
| | 1851 | // which is far more than strictly necessary |
| | 1852 | 33...64 => return self.fail("TODO copy compiler-rt's mulddi3 for a 64x64->128 multiply", .{}), |
| | 1853 | else => return self.fail("TODO overflow operations on other integer sizes", .{}), |
| | 1854 | } |
| | 1855 | }, |
| | 1856 | else => unreachable, |
| | 1857 | } |
| | 1858 | }; |
| | 1859 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); |
| | 1860 | } |
| | 1861 | |
| 1795 | fn airNot(self: *Self, inst: Air.Inst.Index) !void { | 1862 | fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 1796 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1863 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1797 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1864 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |