Skip to content

Commit f89ace4

Browse files
stage2 ARM: add integer modulo with constant power-of-two rhs
1 parent 47d1874 commit f89ace4

File tree

1 file changed

+74
-14
lines changed

1 file changed

+74
-14
lines changed

src/arch/arm/CodeGen.zig

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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

1734-
fn 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-
1740-
fn 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-
17461734
fn 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,

0 commit comments

Comments
 (0)