authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-05 15:22:53+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-05 20:30:52+02:00
log508b90fcfa4749b50618f947e2c3573edcf29713
treedb000a2abda242e0e8b7d0584e922fd1ea233479
parent8b24c783c5bd417f84beeb2f3736a78c3f595d22
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: implement basic integer rem/mod


3 files changed, 107 insertions(+), 19 deletions(-)

src/arch/aarch64/CodeGen.zig+72-13
...@@ -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.*);
10391039
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.*);
10421043
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);
10491050
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(
11451151
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}
11511157
...@@ -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", .{});
src/arch/aarch64/Emit.zig+24-6
...@@ -190,6 +190,7 @@ pub fn emitMir(...@@ -190,6 +190,7 @@ pub fn emitMir(
190 .movk => try emit.mirMoveWideImmediate(inst),190 .movk => try emit.mirMoveWideImmediate(inst),
191 .movz => try emit.mirMoveWideImmediate(inst),191 .movz => try emit.mirMoveWideImmediate(inst),
192192
193 .msub => try emit.mirDataProcessing3Source(inst),
193 .mul => try emit.mirDataProcessing3Source(inst),194 .mul => try emit.mirDataProcessing3Source(inst),
194 .smulh => try emit.mirDataProcessing3Source(inst),195 .smulh => try emit.mirDataProcessing3Source(inst),
195 .smull => try emit.mirDataProcessing3Source(inst),196 .smull => try emit.mirDataProcessing3Source(inst),
...@@ -1140,14 +1141,31 @@ fn mirMoveWideImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -1140,14 +1141,31 @@ fn mirMoveWideImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
11401141
1141fn mirDataProcessing3Source(emit: *Emit, inst: Mir.Inst.Index) !void {1142fn mirDataProcessing3Source(emit: *Emit, inst: Mir.Inst.Index) !void {
1142 const tag = emit.mir.instructions.items(.tag)[inst];1143 const tag = emit.mir.instructions.items(.tag)[inst];
1143 const rrr = emit.mir.instructions.items(.data)[inst].rrr;
11441144
1145 switch (tag) {1145 switch (tag) {
1146 .mul => try emit.writeInstruction(Instruction.mul(rrr.rd, rrr.rn, rrr.rm)),1146 .mul,
1147 .smulh => try emit.writeInstruction(Instruction.smulh(rrr.rd, rrr.rn, rrr.rm)),1147 .smulh,
1148 .smull => try emit.writeInstruction(Instruction.smull(rrr.rd, rrr.rn, rrr.rm)),1148 .smull,
1149 .umulh => try emit.writeInstruction(Instruction.umulh(rrr.rd, rrr.rn, rrr.rm)),1149 .umulh,
1150 .umull => try emit.writeInstruction(Instruction.umull(rrr.rd, rrr.rn, rrr.rm)),1150 .umull,
1151 => {
1152 const rrr = emit.mir.instructions.items(.data)[inst].rrr;
1153 switch (tag) {
1154 .mul => try emit.writeInstruction(Instruction.mul(rrr.rd, rrr.rn, rrr.rm)),
1155 .smulh => try emit.writeInstruction(Instruction.smulh(rrr.rd, rrr.rn, rrr.rm)),
1156 .smull => try emit.writeInstruction(Instruction.smull(rrr.rd, rrr.rn, rrr.rm)),
1157 .umulh => try emit.writeInstruction(Instruction.umulh(rrr.rd, rrr.rn, rrr.rm)),
1158 .umull => try emit.writeInstruction(Instruction.umull(rrr.rd, rrr.rn, rrr.rm)),
1159 else => unreachable,
1160 }
1161 },
1162 .msub => {
1163 const rrrr = emit.mir.instructions.items(.data)[inst].rrrr;
1164 switch (tag) {
1165 .msub => try emit.writeInstruction(Instruction.msub(rrrr.rd, rrrr.rn, rrrr.rm, rrrr.ra)),
1166 else => unreachable,
1167 }
1168 },
1151 else => unreachable,1169 else => unreachable,
1152 }1170 }
1153}1171}
src/arch/aarch64/Mir.zig+11
...@@ -148,6 +148,8 @@ pub const Inst = struct {...@@ -148,6 +148,8 @@ pub const Inst = struct {
148 movk,148 movk,
149 /// Move wide with zero149 /// Move wide with zero
150 movz,150 movz,
151 /// Multiply-subtract
152 msub,
151 /// Multiply153 /// Multiply
152 mul,154 mul,
153 /// Bitwise NOT155 /// Bitwise NOT
...@@ -446,6 +448,15 @@ pub const Inst = struct {...@@ -446,6 +448,15 @@ pub const Inst = struct {
446 rn: Register,448 rn: Register,
447 offset: bits.Instruction.LoadStorePairOffset,449 offset: bits.Instruction.LoadStorePairOffset,
448 },450 },
451 /// Four registers
452 ///
453 /// Used by e.g. msub
454 rrrr: struct {
455 rd: Register,
456 rn: Register,
457 rm: Register,
458 ra: Register,
459 },
449 /// Debug info: line and column460 /// Debug info: line and column
450 ///461 ///
451 /// Used by e.g. dbg_line462 /// Used by e.g. dbg_line