Commit 8b24c783c5
Changed files (4)
src
arch
src/arch/aarch64/bits.zig
@@ -1698,6 +1698,14 @@ pub const Instruction = union(enum) {
// Data processing (2 source)
+ pub fn udiv(rd: Register, rn: Register, rm: Register) Instruction {
+ return dataProcessing2Source(0b0, 0b000010, rd, rn, rm);
+ }
+
+ pub fn sdiv(rd: Register, rn: Register, rm: Register) Instruction {
+ return dataProcessing2Source(0b0, 0b000011, rd, rn, rm);
+ }
+
pub fn lslv(rd: Register, rn: Register, rm: Register) Instruction {
return dataProcessing2Source(0b0, 0b001000, rd, rn, rm);
}
src/arch/aarch64/CodeGen.zig
@@ -561,33 +561,38 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
switch (air_tags[inst]) {
// zig fmt: off
- .add => try self.airBinOp(inst, .add),
- .addwrap => try self.airBinOp(inst, .addwrap),
- .sub => try self.airBinOp(inst, .sub),
- .subwrap => try self.airBinOp(inst, .subwrap),
- .mul => try self.airBinOp(inst, .mul),
- .mulwrap => try self.airBinOp(inst, .mulwrap),
- .shl => try self.airBinOp(inst, .shl),
- .shl_exact => try self.airBinOp(inst, .shl_exact),
- .bool_and => try self.airBinOp(inst, .bool_and),
- .bool_or => try self.airBinOp(inst, .bool_or),
- .bit_and => try self.airBinOp(inst, .bit_and),
- .bit_or => try self.airBinOp(inst, .bit_or),
- .xor => try self.airBinOp(inst, .xor),
- .shr => try self.airBinOp(inst, .shr),
- .shr_exact => try self.airBinOp(inst, .shr_exact),
-
- .ptr_add => try self.airPtrArithmetic(inst, .ptr_add),
- .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub),
+ .add => try self.airBinOp(inst, .add),
+ .addwrap => try self.airBinOp(inst, .addwrap),
+ .sub => try self.airBinOp(inst, .sub),
+ .subwrap => try self.airBinOp(inst, .subwrap),
+ .mul => try self.airBinOp(inst, .mul),
+ .mulwrap => try self.airBinOp(inst, .mulwrap),
+ .shl => try self.airBinOp(inst, .shl),
+ .shl_exact => try self.airBinOp(inst, .shl_exact),
+ .bool_and => try self.airBinOp(inst, .bool_and),
+ .bool_or => try self.airBinOp(inst, .bool_or),
+ .bit_and => try self.airBinOp(inst, .bit_and),
+ .bit_or => try self.airBinOp(inst, .bit_or),
+ .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),
+
+ .min => try self.airMin(inst),
+ .max => try self.airMax(inst),
.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),
- .min => try self.airMin(inst),
- .max => try self.airMax(inst),
.slice => try self.airSlice(inst),
.sqrt,
@@ -612,8 +617,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),
@@ -1391,6 +1394,8 @@ fn binOpRegister(
.lsl_register,
.asr_register,
.lsr_register,
+ .sdiv,
+ .udiv,
=> .{ .rrr = .{
.rd = dest_reg,
.rn = lhs_reg,
@@ -1629,6 +1634,67 @@ fn binOp(
else => unreachable,
}
},
+ .div_float => {
+ switch (lhs_ty.zigTypeTag()) {
+ .Float => return self.fail("TODO div_float", .{}),
+ .Vector => return self.fail("TODO div_float on vectors", .{}),
+ else => unreachable,
+ }
+ },
+ .div_trunc, .div_floor, .div_exact => {
+ switch (lhs_ty.zigTypeTag()) {
+ .Float => return self.fail("TODO div on floats", .{}),
+ .Vector => return self.fail("TODO div on vectors", .{}),
+ .Int => {
+ assert(lhs_ty.eql(rhs_ty, mod));
+ const int_info = lhs_ty.intInfo(self.target.*);
+ if (int_info.bits <= 64) {
+ switch (int_info.signedness) {
+ .signed => {
+ switch (tag) {
+ .div_trunc, .div_exact => {
+ // TODO optimize integer division by constants
+ return try self.binOpRegister(.sdiv, lhs, rhs, lhs_ty, rhs_ty, metadata);
+ },
+ .div_floor => return self.fail("TODO div_floor on signed integers", .{}),
+ else => unreachable,
+ }
+ },
+ .unsigned => {
+ // TODO optimize integer division by constants
+ return try self.binOpRegister(.udiv, lhs, rhs, lhs_ty, rhs_ty, metadata);
+ },
+ }
+ } else {
+ return self.fail("TODO integer division for ints with bits > 64", .{});
+ }
+ },
+ else => unreachable,
+ }
+ },
+ .rem, .mod => {
+ switch (lhs_ty.zigTypeTag()) {
+ .Float => return self.fail("TODO rem/mod on floats", .{}),
+ .Vector => return self.fail("TODO rem/mod on vectors", .{}),
+ .Int => {
+ 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 rem/mod on signed integers", .{});
+ },
+ .unsigned => {
+ return self.fail("TODO rem/mod on unsigned integers", .{});
+ },
+ }
+ } else {
+ return self.fail("TODO rem/mod for integers with bits > 64", .{});
+ }
+ },
+ else => unreachable,
+ }
+ },
.addwrap,
.subwrap,
.mulwrap,
@@ -2300,24 +2366,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});
src/arch/aarch64/Emit.zig
@@ -91,9 +91,11 @@ pub fn emitMir(
.sub_immediate => try emit.mirAddSubtractImmediate(inst),
.subs_immediate => try emit.mirAddSubtractImmediate(inst),
- .asr_register => try emit.mirShiftRegister(inst),
- .lsl_register => try emit.mirShiftRegister(inst),
- .lsr_register => try emit.mirShiftRegister(inst),
+ .asr_register => try emit.mirDataProcessing2Source(inst),
+ .lsl_register => try emit.mirDataProcessing2Source(inst),
+ .lsr_register => try emit.mirDataProcessing2Source(inst),
+ .sdiv => try emit.mirDataProcessing2Source(inst),
+ .udiv => try emit.mirDataProcessing2Source(inst),
.asr_immediate => try emit.mirShiftImmediate(inst),
.lsl_immediate => try emit.mirShiftImmediate(inst),
@@ -520,7 +522,7 @@ fn mirAddSubtractImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
}
}
-fn mirShiftRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
+fn mirDataProcessing2Source(emit: *Emit, inst: Mir.Inst.Index) !void {
const tag = emit.mir.instructions.items(.tag)[inst];
const rrr = emit.mir.instructions.items(.data)[inst].rrr;
const rd = rrr.rd;
@@ -531,6 +533,8 @@ fn mirShiftRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
.asr_register => try emit.writeInstruction(Instruction.asrRegister(rd, rn, rm)),
.lsl_register => try emit.writeInstruction(Instruction.lslRegister(rd, rn, rm)),
.lsr_register => try emit.writeInstruction(Instruction.lsrRegister(rd, rn, rm)),
+ .sdiv => try emit.writeInstruction(Instruction.sdiv(rd, rn, rm)),
+ .udiv => try emit.writeInstruction(Instruction.udiv(rd, rn, rm)),
else => unreachable,
}
}
src/arch/aarch64/Mir.zig
@@ -164,6 +164,8 @@ pub const Inst = struct {
ret,
/// Signed bitfield extract
sbfx,
+ /// Signed divide
+ sdiv,
/// Signed multiply high
smulh,
/// Signed multiply long
@@ -212,6 +214,8 @@ pub const Inst = struct {
tst_immediate,
/// Unsigned bitfield extract
ubfx,
+ /// Unsigned divide
+ udiv,
/// Unsigned multiply high
umulh,
/// Unsigned multiply long