authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-04 21:05:11+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-05 20:30:51+02:00
log8b24c783c5bd417f84beeb2f3736a78c3f595d22
tree460fd5b85032a6a71c60f3bf7fa2056b0c83c86c
parentdcb236acf432c1d772b2f7d65074735eeae4c4c2
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: implement basic integer division


4 files changed, 110 insertions(+), 46 deletions(-)

src/arch/aarch64/CodeGen.zig+90-42
......@@ -561,33 +561,38 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
561561
562562 switch (air_tags[inst]) {
563563 // zig fmt: off
564 .add => try self.airBinOp(inst, .add),
565 .addwrap => try self.airBinOp(inst, .addwrap),
566 .sub => try self.airBinOp(inst, .sub),
567 .subwrap => try self.airBinOp(inst, .subwrap),
568 .mul => try self.airBinOp(inst, .mul),
569 .mulwrap => try self.airBinOp(inst, .mulwrap),
570 .shl => try self.airBinOp(inst, .shl),
571 .shl_exact => try self.airBinOp(inst, .shl_exact),
572 .bool_and => try self.airBinOp(inst, .bool_and),
573 .bool_or => try self.airBinOp(inst, .bool_or),
574 .bit_and => try self.airBinOp(inst, .bit_and),
575 .bit_or => try self.airBinOp(inst, .bit_or),
576 .xor => try self.airBinOp(inst, .xor),
577 .shr => try self.airBinOp(inst, .shr),
578 .shr_exact => try self.airBinOp(inst, .shr_exact),
579
580 .ptr_add => try self.airPtrArithmetic(inst, .ptr_add),
581 .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub),
564 .add => try self.airBinOp(inst, .add),
565 .addwrap => try self.airBinOp(inst, .addwrap),
566 .sub => try self.airBinOp(inst, .sub),
567 .subwrap => try self.airBinOp(inst, .subwrap),
568 .mul => try self.airBinOp(inst, .mul),
569 .mulwrap => try self.airBinOp(inst, .mulwrap),
570 .shl => try self.airBinOp(inst, .shl),
571 .shl_exact => try self.airBinOp(inst, .shl_exact),
572 .bool_and => try self.airBinOp(inst, .bool_and),
573 .bool_or => try self.airBinOp(inst, .bool_or),
574 .bit_and => try self.airBinOp(inst, .bit_and),
575 .bit_or => try self.airBinOp(inst, .bit_or),
576 .xor => try self.airBinOp(inst, .xor),
577 .shr => try self.airBinOp(inst, .shr),
578 .shr_exact => try self.airBinOp(inst, .shr_exact),
579 .div_float => try self.airBinOp(inst, .div_float),
580 .div_trunc => try self.airBinOp(inst, .div_trunc),
581 .div_floor => try self.airBinOp(inst, .div_floor),
582 .div_exact => try self.airBinOp(inst, .div_exact),
583 .rem => try self.airBinOp(inst, .rem),
584 .mod => try self.airBinOp(inst, .mod),
585
586 .ptr_add => try self.airPtrArithmetic(inst, .ptr_add),
587 .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub),
588
589 .min => try self.airMin(inst),
590 .max => try self.airMax(inst),
582591
583592 .add_sat => try self.airAddSat(inst),
584593 .sub_sat => try self.airSubSat(inst),
585594 .mul_sat => try self.airMulSat(inst),
586 .rem => try self.airRem(inst),
587 .mod => try self.airMod(inst),
588595 .shl_sat => try self.airShlSat(inst),
589 .min => try self.airMin(inst),
590 .max => try self.airMax(inst),
591596 .slice => try self.airSlice(inst),
592597
593598 .sqrt,
......@@ -612,8 +617,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
612617 .mul_with_overflow => try self.airMulWithOverflow(inst),
613618 .shl_with_overflow => try self.airShlWithOverflow(inst),
614619
615 .div_float, .div_trunc, .div_floor, .div_exact => try self.airDiv(inst),
616
617620 .cmp_lt => try self.airCmp(inst, .lt),
618621 .cmp_lte => try self.airCmp(inst, .lte),
619622 .cmp_eq => try self.airCmp(inst, .eq),
......@@ -1391,6 +1394,8 @@ fn binOpRegister(
13911394 .lsl_register,
13921395 .asr_register,
13931396 .lsr_register,
1397 .sdiv,
1398 .udiv,
13941399 => .{ .rrr = .{
13951400 .rd = dest_reg,
13961401 .rn = lhs_reg,
......@@ -1629,6 +1634,67 @@ fn binOp(
16291634 else => unreachable,
16301635 }
16311636 },
1637 .div_float => {
1638 switch (lhs_ty.zigTypeTag()) {
1639 .Float => return self.fail("TODO div_float", .{}),
1640 .Vector => return self.fail("TODO div_float on vectors", .{}),
1641 else => unreachable,
1642 }
1643 },
1644 .div_trunc, .div_floor, .div_exact => {
1645 switch (lhs_ty.zigTypeTag()) {
1646 .Float => return self.fail("TODO div on floats", .{}),
1647 .Vector => return self.fail("TODO div on vectors", .{}),
1648 .Int => {
1649 assert(lhs_ty.eql(rhs_ty, mod));
1650 const int_info = lhs_ty.intInfo(self.target.*);
1651 if (int_info.bits <= 64) {
1652 switch (int_info.signedness) {
1653 .signed => {
1654 switch (tag) {
1655 .div_trunc, .div_exact => {
1656 // TODO optimize integer division by constants
1657 return try self.binOpRegister(.sdiv, lhs, rhs, lhs_ty, rhs_ty, metadata);
1658 },
1659 .div_floor => return self.fail("TODO div_floor on signed integers", .{}),
1660 else => unreachable,
1661 }
1662 },
1663 .unsigned => {
1664 // TODO optimize integer division by constants
1665 return try self.binOpRegister(.udiv, lhs, rhs, lhs_ty, rhs_ty, metadata);
1666 },
1667 }
1668 } else {
1669 return self.fail("TODO integer division for ints with bits > 64", .{});
1670 }
1671 },
1672 else => unreachable,
1673 }
1674 },
1675 .rem, .mod => {
1676 switch (lhs_ty.zigTypeTag()) {
1677 .Float => return self.fail("TODO rem/mod on floats", .{}),
1678 .Vector => return self.fail("TODO rem/mod on vectors", .{}),
1679 .Int => {
1680 assert(lhs_ty.eql(rhs_ty, mod));
1681 const int_info = lhs_ty.intInfo(self.target.*);
1682 if (int_info.bits <= 32) {
1683 switch (int_info.signedness) {
1684 .signed => {
1685 return self.fail("TODO rem/mod on signed integers", .{});
1686 },
1687 .unsigned => {
1688 return self.fail("TODO rem/mod on unsigned integers", .{});
1689 },
1690 }
1691 } else {
1692 return self.fail("TODO rem/mod for integers with bits > 64", .{});
1693 }
1694 },
1695 else => unreachable,
1696 }
1697 },
16321698 .addwrap,
16331699 .subwrap,
16341700 .mulwrap,
......@@ -2300,24 +2366,6 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
23002366 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
23012367}
23022368
2303fn airDiv(self: *Self, inst: Air.Inst.Index) !void {
2304 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2305 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement div for {}", .{self.target.cpu.arch});
2306 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2307}
2308
2309fn airRem(self: *Self, inst: Air.Inst.Index) !void {
2310 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2311 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement rem for {}", .{self.target.cpu.arch});
2312 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2313}
2314
2315fn airMod(self: *Self, inst: Air.Inst.Index) !void {
2316 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2317 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement mod for {}", .{self.target.cpu.arch});
2318 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2319}
2320
23212369fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
23222370 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
23232371 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+8-4
......@@ -91,9 +91,11 @@ pub fn emitMir(
9191 .sub_immediate => try emit.mirAddSubtractImmediate(inst),
9292 .subs_immediate => try emit.mirAddSubtractImmediate(inst),
9393
94 .asr_register => try emit.mirShiftRegister(inst),
95 .lsl_register => try emit.mirShiftRegister(inst),
96 .lsr_register => try emit.mirShiftRegister(inst),
94 .asr_register => try emit.mirDataProcessing2Source(inst),
95 .lsl_register => try emit.mirDataProcessing2Source(inst),
96 .lsr_register => try emit.mirDataProcessing2Source(inst),
97 .sdiv => try emit.mirDataProcessing2Source(inst),
98 .udiv => try emit.mirDataProcessing2Source(inst),
9799
98100 .asr_immediate => try emit.mirShiftImmediate(inst),
99101 .lsl_immediate => try emit.mirShiftImmediate(inst),
......@@ -520,7 +522,7 @@ fn mirAddSubtractImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
520522 }
521523}
522524
523fn mirShiftRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
525fn mirDataProcessing2Source(emit: *Emit, inst: Mir.Inst.Index) !void {
524526 const tag = emit.mir.instructions.items(.tag)[inst];
525527 const rrr = emit.mir.instructions.items(.data)[inst].rrr;
526528 const rd = rrr.rd;
......@@ -531,6 +533,8 @@ fn mirShiftRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
531533 .asr_register => try emit.writeInstruction(Instruction.asrRegister(rd, rn, rm)),
532534 .lsl_register => try emit.writeInstruction(Instruction.lslRegister(rd, rn, rm)),
533535 .lsr_register => try emit.writeInstruction(Instruction.lsrRegister(rd, rn, rm)),
536 .sdiv => try emit.writeInstruction(Instruction.sdiv(rd, rn, rm)),
537 .udiv => try emit.writeInstruction(Instruction.udiv(rd, rn, rm)),
534538 else => unreachable,
535539 }
536540}
src/arch/aarch64/Mir.zig+4
......@@ -164,6 +164,8 @@ pub const Inst = struct {
164164 ret,
165165 /// Signed bitfield extract
166166 sbfx,
167 /// Signed divide
168 sdiv,
167169 /// Signed multiply high
168170 smulh,
169171 /// Signed multiply long
......@@ -212,6 +214,8 @@ pub const Inst = struct {
212214 tst_immediate,
213215 /// Unsigned bitfield extract
214216 ubfx,
217 /// Unsigned divide
218 udiv,
215219 /// Unsigned multiply high
216220 umulh,
217221 /// Unsigned multiply long
src/arch/aarch64/bits.zig+8
......@@ -1698,6 +1698,14 @@ pub const Instruction = union(enum) {
16981698
16991699 // Data processing (2 source)
17001700
1701 pub fn udiv(rd: Register, rn: Register, rm: Register) Instruction {
1702 return dataProcessing2Source(0b0, 0b000010, rd, rn, rm);
1703 }
1704
1705 pub fn sdiv(rd: Register, rn: Register, rm: Register) Instruction {
1706 return dataProcessing2Source(0b0, 0b000011, rd, rn, rm);
1707 }
1708
17011709 pub fn lslv(rd: Register, rn: Register, rm: Register) Instruction {
17021710 return dataProcessing2Source(0b0, 0b001000, rd, rn, rm);
17031711 }