| ... | ... | @@ -1038,6 +1038,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 1038 | 1038 | const operand_info = operand_ty.intInfo(self.target.*); |
| 1039 | 1039 | |
| 1040 | 1040 | const dest_ty = self.air.typeOfIndex(inst); |
| 1041 | const dest_abi_size = dest_ty.abiSize(self.target.*); |
| 1041 | 1042 | const dest_info = dest_ty.intInfo(self.target.*); |
| 1042 | 1043 | |
| 1043 | 1044 | const result: MCValue = result: { |
| ... | ... | @@ -1047,16 +1048,21 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 1047 | 1048 | }; |
| 1048 | 1049 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); |
| 1049 | 1050 | |
| 1051 | const truncated: MCValue = switch (operand_mcv) { |
| 1052 | .register => |r| MCValue{ .register = registerAlias(r, dest_abi_size) }, |
| 1053 | else => operand_mcv, |
| 1054 | }; |
| 1055 | |
| 1050 | 1056 | if (dest_info.bits > operand_info.bits) { |
| 1051 | 1057 | const dest_mcv = try self.allocRegOrMem(inst, true); |
| 1052 | | try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, operand_mcv); |
| 1058 | try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, truncated); |
| 1053 | 1059 | break :result dest_mcv; |
| 1054 | 1060 | } else { |
| 1055 | | if (self.reuseOperand(inst, operand, 0, operand_mcv)) { |
| 1056 | | break :result operand_mcv; |
| 1061 | if (self.reuseOperand(inst, operand, 0, truncated)) { |
| 1062 | break :result truncated; |
| 1057 | 1063 | } else { |
| 1058 | 1064 | const dest_mcv = try self.allocRegOrMem(inst, true); |
| 1059 | | try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, operand_mcv); |
| 1065 | try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, truncated); |
| 1060 | 1066 | break :result dest_mcv; |
| 1061 | 1067 | } |
| 1062 | 1068 | } |
| ... | ... | @@ -1145,7 +1151,7 @@ fn trunc( |
| 1145 | 1151 | |
| 1146 | 1152 | return MCValue{ .register = dest_reg }; |
| 1147 | 1153 | } else { |
| 1148 | | return self.fail("TODO: truncate to ints > 32 bits", .{}); |
| 1154 | return self.fail("TODO: truncate to ints > 64 bits", .{}); |
| 1149 | 1155 | } |
| 1150 | 1156 | } |
| 1151 | 1157 | |
| ... | ... | @@ -1679,14 +1685,67 @@ fn binOp( |
| 1679 | 1685 | .Int => { |
| 1680 | 1686 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 1681 | 1687 | const int_info = lhs_ty.intInfo(self.target.*); |
| 1682 | | if (int_info.bits <= 32) { |
| 1683 | | switch (int_info.signedness) { |
| 1684 | | .signed => { |
| 1685 | | return self.fail("TODO rem/mod on signed integers", .{}); |
| 1686 | | }, |
| 1687 | | .unsigned => { |
| 1688 | | return self.fail("TODO rem/mod on unsigned integers", .{}); |
| 1689 | | }, |
| 1688 | if (int_info.bits <= 64) { |
| 1689 | if (int_info.signedness == .signed and tag == .mod) { |
| 1690 | return self.fail("TODO mod on signed integers", .{}); |
| 1691 | } else { |
| 1692 | const lhs_is_register = lhs == .register; |
| 1693 | const rhs_is_register = rhs == .register; |
| 1694 | |
| 1695 | const lhs_lock: ?RegisterLock = if (lhs_is_register) |
| 1696 | self.register_manager.lockReg(lhs.register) |
| 1697 | else |
| 1698 | null; |
| 1699 | defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg); |
| 1700 | |
| 1701 | const lhs_reg = if (lhs_is_register) |
| 1702 | lhs.register |
| 1703 | else |
| 1704 | try self.register_manager.allocReg(null, gp); |
| 1705 | const new_lhs_lock = self.register_manager.lockReg(lhs_reg); |
| 1706 | defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg); |
| 1707 | |
| 1708 | const rhs_reg = if (rhs_is_register) |
| 1709 | rhs.register |
| 1710 | else |
| 1711 | try self.register_manager.allocReg(null, gp); |
| 1712 | const new_rhs_lock = self.register_manager.lockReg(rhs_reg); |
| 1713 | defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg); |
| 1714 | |
| 1715 | const dest_regs = try self.register_manager.allocRegs(2, .{ null, null }, gp); |
| 1716 | const dest_regs_locks = self.register_manager.lockRegsAssumeUnused(2, dest_regs); |
| 1717 | defer for (dest_regs_locks) |reg| { |
| 1718 | self.register_manager.unlockReg(reg); |
| 1719 | }; |
| 1720 | const quotient_reg = dest_regs[0]; |
| 1721 | const remainder_reg = dest_regs[1]; |
| 1722 | |
| 1723 | if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); |
| 1724 | if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs); |
| 1725 | |
| 1726 | _ = try self.addInst(.{ |
| 1727 | .tag = switch (int_info.signedness) { |
| 1728 | .signed => .sdiv, |
| 1729 | .unsigned => .udiv, |
| 1730 | }, |
| 1731 | .data = .{ .rrr = .{ |
| 1732 | .rd = quotient_reg, |
| 1733 | .rn = lhs_reg, |
| 1734 | .rm = rhs_reg, |
| 1735 | } }, |
| 1736 | }); |
| 1737 | |
| 1738 | _ = try self.addInst(.{ |
| 1739 | .tag = .msub, |
| 1740 | .data = .{ .rrrr = .{ |
| 1741 | .rd = remainder_reg, |
| 1742 | .rn = quotient_reg, |
| 1743 | .rm = rhs_reg, |
| 1744 | .ra = lhs_reg, |
| 1745 | } }, |
| 1746 | }); |
| 1747 | |
| 1748 | return MCValue{ .register = remainder_reg }; |
| 1690 | 1749 | } |
| 1691 | 1750 | } else { |
| 1692 | 1751 | return self.fail("TODO rem/mod for integers with bits > 64", .{}); |