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 {...@@ -561,33 +561,38 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
561561
562 switch (air_tags[inst]) {562 switch (air_tags[inst]) {
563 // zig fmt: off563 // zig fmt: off
564 .add => try self.airBinOp(inst, .add),564 .add => try self.airBinOp(inst, .add),
565 .addwrap => try self.airBinOp(inst, .addwrap),565 .addwrap => try self.airBinOp(inst, .addwrap),
566 .sub => try self.airBinOp(inst, .sub),566 .sub => try self.airBinOp(inst, .sub),
567 .subwrap => try self.airBinOp(inst, .subwrap),567 .subwrap => try self.airBinOp(inst, .subwrap),
568 .mul => try self.airBinOp(inst, .mul),568 .mul => try self.airBinOp(inst, .mul),
569 .mulwrap => try self.airBinOp(inst, .mulwrap),569 .mulwrap => try self.airBinOp(inst, .mulwrap),
570 .shl => try self.airBinOp(inst, .shl),570 .shl => try self.airBinOp(inst, .shl),
571 .shl_exact => try self.airBinOp(inst, .shl_exact),571 .shl_exact => try self.airBinOp(inst, .shl_exact),
572 .bool_and => try self.airBinOp(inst, .bool_and),572 .bool_and => try self.airBinOp(inst, .bool_and),
573 .bool_or => try self.airBinOp(inst, .bool_or),573 .bool_or => try self.airBinOp(inst, .bool_or),
574 .bit_and => try self.airBinOp(inst, .bit_and),574 .bit_and => try self.airBinOp(inst, .bit_and),
575 .bit_or => try self.airBinOp(inst, .bit_or),575 .bit_or => try self.airBinOp(inst, .bit_or),
576 .xor => try self.airBinOp(inst, .xor),576 .xor => try self.airBinOp(inst, .xor),
577 .shr => try self.airBinOp(inst, .shr),577 .shr => try self.airBinOp(inst, .shr),
578 .shr_exact => try self.airBinOp(inst, .shr_exact),578 .shr_exact => try self.airBinOp(inst, .shr_exact),
579579 .div_float => try self.airBinOp(inst, .div_float),
580 .ptr_add => try self.airPtrArithmetic(inst, .ptr_add),580 .div_trunc => try self.airBinOp(inst, .div_trunc),
581 .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub),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
583 .add_sat => try self.airAddSat(inst),592 .add_sat => try self.airAddSat(inst),
584 .sub_sat => try self.airSubSat(inst),593 .sub_sat => try self.airSubSat(inst),
585 .mul_sat => try self.airMulSat(inst),594 .mul_sat => try self.airMulSat(inst),
586 .rem => try self.airRem(inst),
587 .mod => try self.airMod(inst),
588 .shl_sat => try self.airShlSat(inst),595 .shl_sat => try self.airShlSat(inst),
589 .min => try self.airMin(inst),
590 .max => try self.airMax(inst),
591 .slice => try self.airSlice(inst),596 .slice => try self.airSlice(inst),
592597
593 .sqrt,598 .sqrt,
...@@ -612,8 +617,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -612,8 +617,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
612 .mul_with_overflow => try self.airMulWithOverflow(inst),617 .mul_with_overflow => try self.airMulWithOverflow(inst),
613 .shl_with_overflow => try self.airShlWithOverflow(inst),618 .shl_with_overflow => try self.airShlWithOverflow(inst),
614619
615 .div_float, .div_trunc, .div_floor, .div_exact => try self.airDiv(inst),
616
617 .cmp_lt => try self.airCmp(inst, .lt),620 .cmp_lt => try self.airCmp(inst, .lt),
618 .cmp_lte => try self.airCmp(inst, .lte),621 .cmp_lte => try self.airCmp(inst, .lte),
619 .cmp_eq => try self.airCmp(inst, .eq),622 .cmp_eq => try self.airCmp(inst, .eq),
...@@ -1391,6 +1394,8 @@ fn binOpRegister(...@@ -1391,6 +1394,8 @@ fn binOpRegister(
1391 .lsl_register,1394 .lsl_register,
1392 .asr_register,1395 .asr_register,
1393 .lsr_register,1396 .lsr_register,
1397 .sdiv,
1398 .udiv,
1394 => .{ .rrr = .{1399 => .{ .rrr = .{
1395 .rd = dest_reg,1400 .rd = dest_reg,
1396 .rn = lhs_reg,1401 .rn = lhs_reg,
...@@ -1629,6 +1634,67 @@ fn binOp(...@@ -1629,6 +1634,67 @@ fn binOp(
1629 else => unreachable,1634 else => unreachable,
1630 }1635 }
1631 },1636 },
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 },
1632 .addwrap,1698 .addwrap,
1633 .subwrap,1699 .subwrap,
1634 .mulwrap,1700 .mulwrap,
...@@ -2300,24 +2366,6 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2300,24 +2366,6 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2300 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });2366 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
2301}2367}
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
2321fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {2369fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
2322 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2370 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2323 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch});2371 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(...@@ -91,9 +91,11 @@ pub fn emitMir(
91 .sub_immediate => try emit.mirAddSubtractImmediate(inst),91 .sub_immediate => try emit.mirAddSubtractImmediate(inst),
92 .subs_immediate => try emit.mirAddSubtractImmediate(inst),92 .subs_immediate => try emit.mirAddSubtractImmediate(inst),
9393
94 .asr_register => try emit.mirShiftRegister(inst),94 .asr_register => try emit.mirDataProcessing2Source(inst),
95 .lsl_register => try emit.mirShiftRegister(inst),95 .lsl_register => try emit.mirDataProcessing2Source(inst),
96 .lsr_register => try emit.mirShiftRegister(inst),96 .lsr_register => try emit.mirDataProcessing2Source(inst),
97 .sdiv => try emit.mirDataProcessing2Source(inst),
98 .udiv => try emit.mirDataProcessing2Source(inst),
9799
98 .asr_immediate => try emit.mirShiftImmediate(inst),100 .asr_immediate => try emit.mirShiftImmediate(inst),
99 .lsl_immediate => try emit.mirShiftImmediate(inst),101 .lsl_immediate => try emit.mirShiftImmediate(inst),
...@@ -520,7 +522,7 @@ fn mirAddSubtractImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -520,7 +522,7 @@ fn mirAddSubtractImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
520 }522 }
521}523}
522524
523fn mirShiftRegister(emit: *Emit, inst: Mir.Inst.Index) !void {525fn mirDataProcessing2Source(emit: *Emit, inst: Mir.Inst.Index) !void {
524 const tag = emit.mir.instructions.items(.tag)[inst];526 const tag = emit.mir.instructions.items(.tag)[inst];
525 const rrr = emit.mir.instructions.items(.data)[inst].rrr;527 const rrr = emit.mir.instructions.items(.data)[inst].rrr;
526 const rd = rrr.rd;528 const rd = rrr.rd;
...@@ -531,6 +533,8 @@ fn mirShiftRegister(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -531,6 +533,8 @@ fn mirShiftRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
531 .asr_register => try emit.writeInstruction(Instruction.asrRegister(rd, rn, rm)),533 .asr_register => try emit.writeInstruction(Instruction.asrRegister(rd, rn, rm)),
532 .lsl_register => try emit.writeInstruction(Instruction.lslRegister(rd, rn, rm)),534 .lsl_register => try emit.writeInstruction(Instruction.lslRegister(rd, rn, rm)),
533 .lsr_register => try emit.writeInstruction(Instruction.lsrRegister(rd, rn, rm)),535 .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)),
534 else => unreachable,538 else => unreachable,
535 }539 }
536}540}
src/arch/aarch64/Mir.zig+4
...@@ -164,6 +164,8 @@ pub const Inst = struct {...@@ -164,6 +164,8 @@ pub const Inst = struct {
164 ret,164 ret,
165 /// Signed bitfield extract165 /// Signed bitfield extract
166 sbfx,166 sbfx,
167 /// Signed divide
168 sdiv,
167 /// Signed multiply high169 /// Signed multiply high
168 smulh,170 smulh,
169 /// Signed multiply long171 /// Signed multiply long
...@@ -212,6 +214,8 @@ pub const Inst = struct {...@@ -212,6 +214,8 @@ pub const Inst = struct {
212 tst_immediate,214 tst_immediate,
213 /// Unsigned bitfield extract215 /// Unsigned bitfield extract
214 ubfx,216 ubfx,
217 /// Unsigned divide
218 udiv,
215 /// Unsigned multiply high219 /// Unsigned multiply high
216 umulh,220 umulh,
217 /// Unsigned multiply long221 /// Unsigned multiply long
src/arch/aarch64/bits.zig+8
...@@ -1698,6 +1698,14 @@ pub const Instruction = union(enum) {...@@ -1698,6 +1698,14 @@ pub const Instruction = union(enum) {
16981698
1699 // Data processing (2 source)1699 // 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
1701 pub fn lslv(rd: Register, rn: Register, rm: Register) Instruction {1709 pub fn lslv(rd: Register, rn: Register, rm: Register) Instruction {
1702 return dataProcessing2Source(0b0, 0b001000, rd, rn, rm);1710 return dataProcessing2Source(0b0, 0b001000, rd, rn, rm);
1703 }1711 }