mirror of
https://github.com/ziglang/zig.git
synced 2025-12-27 16:43:07 +00:00
Merge pull request #12095 from joachimschmidt557/stage2-arm
stage2 ARM: add integer div+mod with constant power-of-twos
This commit is contained in:
commit
1fee9eac8b
@ -567,6 +567,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.xor => try self.airBinOp(inst, .xor),
|
||||
.shr => try self.airBinOp(inst, .shr),
|
||||
.shr_exact => try self.airBinOp(inst, .shr_exact),
|
||||
.div_float => try self.airBinOp(inst, .div_float),
|
||||
.div_trunc => try self.airBinOp(inst, .div_trunc),
|
||||
.div_floor => try self.airBinOp(inst, .div_floor),
|
||||
.div_exact => try self.airBinOp(inst, .div_exact),
|
||||
.rem => try self.airBinOp(inst, .rem),
|
||||
.mod => try self.airBinOp(inst, .mod),
|
||||
|
||||
.ptr_add => try self.airPtrArithmetic(inst, .ptr_add),
|
||||
.ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub),
|
||||
@ -577,8 +583,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.add_sat => try self.airAddSat(inst),
|
||||
.sub_sat => try self.airSubSat(inst),
|
||||
.mul_sat => try self.airMulSat(inst),
|
||||
.rem => try self.airRem(inst),
|
||||
.mod => try self.airMod(inst),
|
||||
.shl_sat => try self.airShlSat(inst),
|
||||
.slice => try self.airSlice(inst),
|
||||
|
||||
@ -604,8 +608,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.mul_with_overflow => try self.airMulWithOverflow(inst),
|
||||
.shl_with_overflow => try self.airShlWithOverflow(inst),
|
||||
|
||||
.div_float, .div_trunc, .div_floor, .div_exact => try self.airDiv(inst),
|
||||
|
||||
.cmp_lt => try self.airCmp(inst, .lt),
|
||||
.cmp_lte => try self.airCmp(inst, .lte),
|
||||
.cmp_eq => try self.airCmp(inst, .eq),
|
||||
@ -1729,24 +1731,6 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
|
||||
return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
|
||||
}
|
||||
|
||||
fn airDiv(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement div for {}", .{self.target.cpu.arch});
|
||||
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
|
||||
}
|
||||
|
||||
fn airRem(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement rem for {}", .{self.target.cpu.arch});
|
||||
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
|
||||
}
|
||||
|
||||
fn airMod(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement mod for {}", .{self.target.cpu.arch});
|
||||
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
|
||||
}
|
||||
|
||||
fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch});
|
||||
@ -2878,6 +2862,127 @@ fn binOp(
|
||||
else => unreachable,
|
||||
}
|
||||
},
|
||||
.div_float => {
|
||||
switch (lhs_ty.zigTypeTag()) {
|
||||
.Float => return self.fail("TODO ARM binary operations on floats", .{}),
|
||||
.Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
|
||||
else => unreachable,
|
||||
}
|
||||
},
|
||||
.div_trunc, .div_floor => {
|
||||
switch (lhs_ty.zigTypeTag()) {
|
||||
.Float => return self.fail("TODO ARM binary operations on floats", .{}),
|
||||
.Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
|
||||
.Int => {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
assert(lhs_ty.eql(rhs_ty, mod));
|
||||
const int_info = lhs_ty.intInfo(self.target.*);
|
||||
if (int_info.bits <= 32) {
|
||||
switch (int_info.signedness) {
|
||||
.signed => {
|
||||
return self.fail("TODO ARM signed integer division", .{});
|
||||
},
|
||||
.unsigned => {
|
||||
switch (rhs) {
|
||||
.immediate => |imm| {
|
||||
if (std.math.isPowerOfTwo(imm)) {
|
||||
const shift = MCValue{ .immediate = std.math.log2_int(u32, imm) };
|
||||
return try self.binOp(.shr, lhs, shift, lhs_ty, rhs_ty, metadata);
|
||||
} else {
|
||||
return self.fail("TODO ARM integer division by constants", .{});
|
||||
}
|
||||
},
|
||||
else => return self.fail("TODO ARM integer division", .{}),
|
||||
}
|
||||
},
|
||||
}
|
||||
} else {
|
||||
return self.fail("TODO ARM integer division for integers > u32/i32", .{});
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
},
|
||||
.div_exact => {
|
||||
switch (lhs_ty.zigTypeTag()) {
|
||||
.Float => return self.fail("TODO ARM binary operations on floats", .{}),
|
||||
.Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
|
||||
.Int => return self.fail("TODO ARM div_exact", .{}),
|
||||
else => unreachable,
|
||||
}
|
||||
},
|
||||
.rem => {
|
||||
switch (lhs_ty.zigTypeTag()) {
|
||||
.Float => return self.fail("TODO ARM binary operations on floats", .{}),
|
||||
.Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
|
||||
.Int => {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
assert(lhs_ty.eql(rhs_ty, mod));
|
||||
const int_info = lhs_ty.intInfo(self.target.*);
|
||||
if (int_info.bits <= 32) {
|
||||
switch (int_info.signedness) {
|
||||
.signed => {
|
||||
return self.fail("TODO ARM signed integer mod", .{});
|
||||
},
|
||||
.unsigned => {
|
||||
switch (rhs) {
|
||||
.immediate => |imm| {
|
||||
if (std.math.isPowerOfTwo(imm)) {
|
||||
const log2 = std.math.log2_int(u32, imm);
|
||||
|
||||
const lhs_is_register = lhs == .register;
|
||||
|
||||
const lhs_lock: ?RegisterLock = if (lhs_is_register)
|
||||
self.register_manager.lockReg(lhs.register)
|
||||
else
|
||||
null;
|
||||
defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg);
|
||||
|
||||
const lhs_reg = if (lhs_is_register) lhs.register else blk: {
|
||||
const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: {
|
||||
break :inst Air.refToIndex(md.lhs).?;
|
||||
} else null;
|
||||
|
||||
break :blk try self.prepareNewRegForMoving(track_inst, gp, lhs);
|
||||
};
|
||||
const new_lhs_lock = self.register_manager.lockReg(lhs_reg);
|
||||
defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
|
||||
|
||||
const dest_reg = if (metadata) |md| blk: {
|
||||
if (lhs_is_register and self.reuseOperand(md.inst, md.lhs, 0, lhs)) {
|
||||
break :blk lhs_reg;
|
||||
} else {
|
||||
break :blk try self.register_manager.allocReg(md.inst, gp);
|
||||
}
|
||||
} else try self.register_manager.allocReg(null, gp);
|
||||
|
||||
if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
|
||||
|
||||
try self.truncRegister(lhs_reg, dest_reg, int_info.signedness, log2);
|
||||
return MCValue{ .register = dest_reg };
|
||||
} else {
|
||||
return self.fail("TODO ARM integer mod by constants", .{});
|
||||
}
|
||||
},
|
||||
else => return self.fail("TODO ARM integer mod", .{}),
|
||||
}
|
||||
},
|
||||
}
|
||||
} else {
|
||||
return self.fail("TODO ARM integer division for integers > u32/i32", .{});
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
},
|
||||
.mod => {
|
||||
switch (lhs_ty.zigTypeTag()) {
|
||||
.Float => return self.fail("TODO ARM binary operations on floats", .{}),
|
||||
.Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
|
||||
.Int => return self.fail("TODO ARM mod", .{}),
|
||||
else => unreachable,
|
||||
}
|
||||
},
|
||||
.addwrap,
|
||||
.subwrap,
|
||||
.mulwrap,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user