diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 112c9ac106..436fe4ea56 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -1857,18 +1857,15 @@ fn airAddSubShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const tag = self.air.instructions.items(.tag)[inst]; const ty = self.air.typeOf(bin_op.lhs); - const abi_size = ty.abiSize(self.target.*); switch (ty.zigTypeTag()) { .Vector => return self.fail("TODO implement add/sub/shl with overflow for Vector type", .{}), .Int => { - if (abi_size > 8) { - return self.fail("TODO implement add/sub/shl with overflow for Ints larger than 64bits", .{}); - } - try self.spillEflagsIfOccupied(); if (tag == .shl_with_overflow) { try self.spillRegisters(&.{.rcx}); + // cf/of don't work for shifts other than 1 + return self.fail("TODO implement shl_with_overflow for x86_64", .{}); } const partial: MCValue = switch (tag) { @@ -1885,16 +1882,29 @@ fn airAddSubShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { }; const int_info = ty.intInfo(self.target.*); - if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) { - self.eflags_inst = inst; - break :result .{ .register_overflow = .{ - .reg = partial.register, - .eflags = switch (int_info.signedness) { - .unsigned => .c, - .signed => .o, + const cc: Condition = switch (int_info.signedness) { + .unsigned => .c, + .signed => .o, + }; + switch (partial) { + .register => |reg| { + self.eflags_inst = inst; + break :result .{ .register_overflow = .{ .reg = reg, .eflags = cc } }; }, - } }; + else => {}, + } + + const abi_size = @intCast(i32, ty.abiSize(self.target.*)); + const dst_mcv = try self.allocRegOrMem(inst, false); + try self.genSetStack( + Type.u1, + dst_mcv.stack_offset - abi_size, + .{ .eflags = cc }, + .{}, + ); + try self.genSetStack(ty, dst_mcv.stack_offset, partial, .{}); + break :result dst_mcv; } const tuple_ty = self.air.typeOfIndex(inst); diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index 7fa8066505..533d6080ae 100644 --- a/test/behavior/eval.zig +++ b/test/behavior/eval.zig @@ -488,6 +488,7 @@ test "comptime bitwise operators" { test "comptime shlWithOverflow" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO const ct_shifted = @shlWithOverflow(~@as(u64, 0), 16)[0]; var a = ~@as(u64, 0); diff --git a/test/behavior/int128.zig b/test/behavior/int128.zig index 166b03809b..b21a480a16 100644 --- a/test/behavior/int128.zig +++ b/test/behavior/int128.zig @@ -40,7 +40,6 @@ test "undefined 128 bit int" { } test "int128" { - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO diff --git a/test/behavior/math.zig b/test/behavior/math.zig index 9e3c2b02fd..acdbb2748e 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -1237,6 +1237,8 @@ fn testShlTrunc(x: u16) !void { } test "exact shift left" { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + try testShlExact(0b00110101); comptime try testShlExact(0b00110101); }