authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-07-12 23:22:15+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-07-12 23:22:15+02:00
logf89ace4d04f8567ae92dce74ffb0e0d416077492
treed33ef859f90233de486309b7e0628c7f1dd9de8d
parent47d1874218219d6eddbc96e9bafef81f24911033
signaturelock-open Commit is signed but in an unrecognized format.

stage2 ARM: add integer modulo with constant power-of-two rhs


1 files changed, 74 insertions(+), 14 deletions(-)

src/arch/arm/CodeGen.zig+74-14
......@@ -571,6 +571,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
571571 .div_trunc => try self.airBinOp(inst, .div_trunc),
572572 .div_floor => try self.airBinOp(inst, .div_floor),
573573 .div_exact => try self.airBinOp(inst, .div_exact),
574 .rem => try self.airBinOp(inst, .rem),
575 .mod => try self.airBinOp(inst, .mod),
574576
575577 .ptr_add => try self.airPtrArithmetic(inst, .ptr_add),
576578 .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub),
......@@ -581,8 +583,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
581583 .add_sat => try self.airAddSat(inst),
582584 .sub_sat => try self.airSubSat(inst),
583585 .mul_sat => try self.airMulSat(inst),
584 .rem => try self.airRem(inst),
585 .mod => try self.airMod(inst),
586586 .shl_sat => try self.airShlSat(inst),
587587 .slice => try self.airSlice(inst),
588588
......@@ -1731,18 +1731,6 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
17311731 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
17321732}
17331733
1734fn airRem(self: *Self, inst: Air.Inst.Index) !void {
1735 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1736 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement rem for {}", .{self.target.cpu.arch});
1737 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1738}
1739
1740fn airMod(self: *Self, inst: Air.Inst.Index) !void {
1741 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1742 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement mod for {}", .{self.target.cpu.arch});
1743 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1744}
1745
17461734fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
17471735 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
17481736 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch});
......@@ -2923,6 +2911,78 @@ fn binOp(
29232911 else => unreachable,
29242912 }
29252913 },
2914 .rem => {
2915 switch (lhs_ty.zigTypeTag()) {
2916 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
2917 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
2918 .Int => {
2919 const mod = self.bin_file.options.module.?;
2920 assert(lhs_ty.eql(rhs_ty, mod));
2921 const int_info = lhs_ty.intInfo(self.target.*);
2922 if (int_info.bits <= 32) {
2923 switch (int_info.signedness) {
2924 .signed => {
2925 return self.fail("TODO ARM signed integer mod", .{});
2926 },
2927 .unsigned => {
2928 switch (rhs) {
2929 .immediate => |imm| {
2930 if (std.math.isPowerOfTwo(imm)) {
2931 const log2 = std.math.log2_int(u32, imm);
2932
2933 const lhs_is_register = lhs == .register;
2934
2935 const lhs_lock: ?RegisterLock = if (lhs_is_register)
2936 self.register_manager.lockReg(lhs.register)
2937 else
2938 null;
2939 defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg);
2940
2941 const lhs_reg = if (lhs_is_register) lhs.register else blk: {
2942 const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: {
2943 break :inst Air.refToIndex(md.lhs).?;
2944 } else null;
2945
2946 break :blk try self.prepareNewRegForMoving(track_inst, gp, lhs);
2947 };
2948 const new_lhs_lock = self.register_manager.lockReg(lhs_reg);
2949 defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
2950
2951 const dest_reg = if (metadata) |md| blk: {
2952 if (lhs_is_register and self.reuseOperand(md.inst, md.lhs, 0, lhs)) {
2953 break :blk lhs_reg;
2954 } else {
2955 break :blk try self.register_manager.allocReg(md.inst, gp);
2956 }
2957 } else try self.register_manager.allocReg(null, gp);
2958
2959 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
2960
2961 try self.truncRegister(lhs_reg, dest_reg, int_info.signedness, log2);
2962 return MCValue{ .register = dest_reg };
2963 } else {
2964 return self.fail("TODO ARM integer mod by constants", .{});
2965 }
2966 },
2967 else => return self.fail("TODO ARM integer mod", .{}),
2968 }
2969 },
2970 }
2971 } else {
2972 return self.fail("TODO ARM integer division for integers > u32/i32", .{});
2973 }
2974 },
2975 else => unreachable,
2976 }
2977 },
2978 .mod => {
2979 switch (lhs_ty.zigTypeTag()) {
2980 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
2981 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
2982 .Int => return self.fail("TODO ARM mod", .{}),
2983 else => unreachable,
2984 }
2985 },
29262986 .addwrap,
29272987 .subwrap,
29282988 .mulwrap,