| ... | @@ -1038,6 +1038,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1038,6 +1038,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 1038 | const operand_info = operand_ty.intInfo(self.target.*); | 1038 | const operand_info = operand_ty.intInfo(self.target.*); |
| 1039 | | 1039 | |
| 1040 | const dest_ty = self.air.typeOfIndex(inst); | 1040 | const dest_ty = self.air.typeOfIndex(inst); |
| | 1041 | const dest_abi_size = dest_ty.abiSize(self.target.*); |
| 1041 | const dest_info = dest_ty.intInfo(self.target.*); | 1042 | const dest_info = dest_ty.intInfo(self.target.*); |
| 1042 | | 1043 | |
| 1043 | const result: MCValue = result: { | 1044 | const result: MCValue = result: { |
| ... | @@ -1047,16 +1048,21 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1047,16 +1048,21 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 1047 | }; | 1048 | }; |
| 1048 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); | 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 | if (dest_info.bits > operand_info.bits) { | 1056 | if (dest_info.bits > operand_info.bits) { |
| 1051 | const dest_mcv = try self.allocRegOrMem(inst, true); | 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 | break :result dest_mcv; | 1059 | break :result dest_mcv; |
| 1054 | } else { | 1060 | } else { |
| 1055 | if (self.reuseOperand(inst, operand, 0, operand_mcv)) { | 1061 | if (self.reuseOperand(inst, operand, 0, truncated)) { |
| 1056 | break :result operand_mcv; | 1062 | break :result truncated; |
| 1057 | } else { | 1063 | } else { |
| 1058 | const dest_mcv = try self.allocRegOrMem(inst, true); | 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 | break :result dest_mcv; | 1066 | break :result dest_mcv; |
| 1061 | } | 1067 | } |
| 1062 | } | 1068 | } |
| ... | @@ -1145,7 +1151,7 @@ fn trunc( | ... | @@ -1145,7 +1151,7 @@ fn trunc( |
| 1145 | | 1151 | |
| 1146 | return MCValue{ .register = dest_reg }; | 1152 | return MCValue{ .register = dest_reg }; |
| 1147 | } else { | 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,14 +1685,67 @@ fn binOp( |
| 1679 | .Int => { | 1685 | .Int => { |
| 1680 | assert(lhs_ty.eql(rhs_ty, mod)); | 1686 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 1681 | const int_info = lhs_ty.intInfo(self.target.*); | 1687 | const int_info = lhs_ty.intInfo(self.target.*); |
| 1682 | if (int_info.bits <= 32) { | 1688 | if (int_info.bits <= 64) { |
| 1683 | switch (int_info.signedness) { | 1689 | if (int_info.signedness == .signed and tag == .mod) { |
| 1684 | .signed => { | 1690 | return self.fail("TODO mod on signed integers", .{}); |
| 1685 | return self.fail("TODO rem/mod on signed integers", .{}); | 1691 | } else { |
| 1686 | }, | 1692 | const lhs_is_register = lhs == .register; |
| 1687 | .unsigned => { | 1693 | const rhs_is_register = rhs == .register; |
| 1688 | return self.fail("TODO rem/mod on unsigned integers", .{}); | 1694 | |
| 1689 | }, | 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 | } else { | 1750 | } else { |
| 1692 | return self.fail("TODO rem/mod for integers with bits > 64", .{}); | 1751 | return self.fail("TODO rem/mod for integers with bits > 64", .{}); |