@@ -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" , .{});
0 commit comments