authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-03-30 11:09:05+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-04-01 22:02:56+02:00
log77e70189f438316a8d4e48b2457be0b5eb5974f3
tree4e1766b7c0f35d9a0fa17cecd582d45bdca754fe
parent37a8c28802b418718487995a1fa6000b0aab8a84
signature Commit is signed but in an unrecognized format.

stage2 ARM: implement shl_with_overflow for ints <= 32 bits


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

src/arch/arm/CodeGen.zig+48-2
...@@ -1457,8 +1457,54 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1457,8 +1457,54 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1457}1457}
14581458
1459fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {1459fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1460 _ = inst;1460 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1461 return self.fail("TODO implement airShlWithOverflow for {}", .{self.target.cpu.arch});1461 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
1462 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });
1463 const result: MCValue = result: {
1464 const lhs = try self.resolveInst(extra.lhs);
1465 const rhs = try self.resolveInst(extra.rhs);
1466 const lhs_ty = self.air.typeOf(extra.lhs);
1467 const rhs_ty = self.air.typeOf(extra.rhs);
1468
1469 const tuple_ty = self.air.typeOfIndex(inst);
1470 const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*));
1471 const tuple_align = tuple_ty.abiAlignment(self.target.*);
1472 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*));
1473
1474 switch (lhs_ty.zigTypeTag()) {
1475 .Vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}),
1476 .Int => {
1477 const int_info = lhs_ty.intInfo(self.target.*);
1478 if (int_info.bits <= 32) {
1479 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
1480
1481 if (lhs == .register) self.register_manager.freezeRegs(&.{lhs.register});
1482 defer if (lhs == .register) self.register_manager.unfreezeRegs(&.{lhs.register});
1483
1484 try self.spillCompareFlagsIfOccupied();
1485 self.compare_flags_inst = null;
1486
1487 // lsl dest, lhs, rhs
1488 const dest = try self.binOp(.shl, null, lhs, rhs, lhs_ty, rhs_ty);
1489
1490 // asr/lsr reconstructed, dest, rhs
1491 const reconstructed = try self.binOp(.shr, null, dest, rhs, lhs_ty, rhs_ty);
1492
1493 // cmp lhs, reconstructed
1494 _ = try self.binOp(.cmp_eq, null, lhs, reconstructed, lhs_ty, lhs_ty);
1495
1496 try self.genSetStack(lhs_ty, stack_offset, dest);
1497 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .compare_flags_unsigned = .neq });
1498
1499 break :result MCValue{ .stack_offset = stack_offset };
1500 } else {
1501 return self.fail("TODO ARM overflow operations on integers > u32/i32", .{});
1502 }
1503 },
1504 else => unreachable,
1505 }
1506 };
1507 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
1462}1508}
14631509
1464fn airDiv(self: *Self, inst: Air.Inst.Index) !void {1510fn airDiv(self: *Self, inst: Air.Inst.Index) !void {
test/behavior/math.zig-1
...@@ -719,7 +719,6 @@ test "@shlWithOverflow" {...@@ -719,7 +719,6 @@ test "@shlWithOverflow" {
719 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO719 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
720 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO720 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
721 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO721 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
722 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
723722
724 var result: u16 = undefined;723 var result: u16 = undefined;
725 try expect(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));724 try expect(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));