authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-04-26 22:42:38+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-05 21:43:35+02:00
logaaacda4df97c03cfcea444c1d77c06f46575049d
tree085126d3b0b34ba9e479517a0f82b9c65aa5e26a
parentf267e7a8b45d343eb1c3cf5f0662746912af8c99

stage2 AArch64: implement shl_with_overflow


2 files changed, 48 insertions(+), 4 deletions(-)

src/arch/aarch64/CodeGen.zig+48-2
......@@ -1888,8 +1888,54 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
18881888}
18891889
18901890fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1891 _ = inst;
1892 return self.fail("TODO implement airShlWithOverflow for {}", .{self.target.cpu.arch});
1891 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1892 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
1893 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });
1894 const result: MCValue = result: {
1895 const lhs = try self.resolveInst(extra.lhs);
1896 const rhs = try self.resolveInst(extra.rhs);
1897 const lhs_ty = self.air.typeOf(extra.lhs);
1898 const rhs_ty = self.air.typeOf(extra.rhs);
1899
1900 const tuple_ty = self.air.typeOfIndex(inst);
1901 const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*));
1902 const tuple_align = tuple_ty.abiAlignment(self.target.*);
1903 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*));
1904
1905 switch (lhs_ty.zigTypeTag()) {
1906 .Vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}),
1907 .Int => {
1908 const int_info = lhs_ty.intInfo(self.target.*);
1909 if (int_info.bits <= 64) {
1910 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
1911
1912 if (lhs == .register) self.register_manager.freezeRegs(&.{lhs.register});
1913 defer if (lhs == .register) self.register_manager.unfreezeRegs(&.{lhs.register});
1914
1915 try self.spillCompareFlagsIfOccupied();
1916 self.compare_flags_inst = null;
1917
1918 // lsl dest, lhs, rhs
1919 const dest = try self.binOp(.shl, null, lhs, rhs, lhs_ty, rhs_ty);
1920
1921 // asr/lsr reconstructed, dest, rhs
1922 const reconstructed = try self.binOp(.shr, null, dest, rhs, lhs_ty, rhs_ty);
1923
1924 // cmp lhs, reconstructed
1925 _ = try self.binOp(.cmp_eq, null, lhs, reconstructed, lhs_ty, lhs_ty);
1926
1927 try self.genSetStack(lhs_ty, stack_offset, dest);
1928 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .compare_flags_unsigned = .neq });
1929
1930 break :result MCValue{ .stack_offset = stack_offset };
1931 } else {
1932 return self.fail("TODO overflow operations on integers > u64/i64", .{});
1933 }
1934 },
1935 else => unreachable,
1936 }
1937 };
1938 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
18931939}
18941940
18951941fn airDiv(self: *Self, inst: Air.Inst.Index) !void {
test/behavior/math.zig-2
......@@ -686,7 +686,6 @@ test "@mulWithOverflow" {
686686
687687test "@subWithOverflow" {
688688 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
689 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
690689
691690 var result: u8 = undefined;
692691 try expect(@subWithOverflow(u8, 1, 2, &result));
......@@ -706,7 +705,6 @@ test "@subWithOverflow" {
706705test "@shlWithOverflow" {
707706 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
708707 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
709 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
710708
711709 var result: u16 = undefined;
712710 try expect(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));