authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-04-02 05:15:26-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-04-02 05:16:46-04:00
log0e289cc8269c9c18358b511564718972808d2efe
tree2e8cd639a8e419af4acea83a99d2a39f1c614665
parentc713c863896d4ef6b4fd0817e8db59f5992b2303

x86_64: implement large add/sub with overflow


4 files changed, 26 insertions(+), 14 deletions(-)

src/arch/x86_64/CodeGen.zig+23-13
...@@ -1857,18 +1857,15 @@ fn airAddSubShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1857,18 +1857,15 @@ fn airAddSubShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1857 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1857 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1858 const tag = self.air.instructions.items(.tag)[inst];1858 const tag = self.air.instructions.items(.tag)[inst];
1859 const ty = self.air.typeOf(bin_op.lhs);1859 const ty = self.air.typeOf(bin_op.lhs);
1860 const abi_size = ty.abiSize(self.target.*);
1861 switch (ty.zigTypeTag()) {1860 switch (ty.zigTypeTag()) {
1862 .Vector => return self.fail("TODO implement add/sub/shl with overflow for Vector type", .{}),1861 .Vector => return self.fail("TODO implement add/sub/shl with overflow for Vector type", .{}),
1863 .Int => {1862 .Int => {
1864 if (abi_size > 8) {
1865 return self.fail("TODO implement add/sub/shl with overflow for Ints larger than 64bits", .{});
1866 }
1867
1868 try self.spillEflagsIfOccupied();1863 try self.spillEflagsIfOccupied();
18691864
1870 if (tag == .shl_with_overflow) {1865 if (tag == .shl_with_overflow) {
1871 try self.spillRegisters(&.{.rcx});1866 try self.spillRegisters(&.{.rcx});
1867 // cf/of don't work for shifts other than 1
1868 return self.fail("TODO implement shl_with_overflow for x86_64", .{});
1872 }1869 }
18731870
1874 const partial: MCValue = switch (tag) {1871 const partial: MCValue = switch (tag) {
...@@ -1885,16 +1882,29 @@ fn airAddSubShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1885,16 +1882,29 @@ fn airAddSubShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1885 };1882 };
18861883
1887 const int_info = ty.intInfo(self.target.*);1884 const int_info = ty.intInfo(self.target.*);
1888
1889 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {1885 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
1890 self.eflags_inst = inst;1886 const cc: Condition = switch (int_info.signedness) {
1891 break :result .{ .register_overflow = .{1887 .unsigned => .c,
1892 .reg = partial.register,1888 .signed => .o,
1893 .eflags = switch (int_info.signedness) {1889 };
1894 .unsigned => .c,1890 switch (partial) {
1895 .signed => .o,1891 .register => |reg| {
1892 self.eflags_inst = inst;
1893 break :result .{ .register_overflow = .{ .reg = reg, .eflags = cc } };
1896 },1894 },
1897 } };1895 else => {},
1896 }
1897
1898 const abi_size = @intCast(i32, ty.abiSize(self.target.*));
1899 const dst_mcv = try self.allocRegOrMem(inst, false);
1900 try self.genSetStack(
1901 Type.u1,
1902 dst_mcv.stack_offset - abi_size,
1903 .{ .eflags = cc },
1904 .{},
1905 );
1906 try self.genSetStack(ty, dst_mcv.stack_offset, partial, .{});
1907 break :result dst_mcv;
1898 }1908 }
18991909
1900 const tuple_ty = self.air.typeOfIndex(inst);1910 const tuple_ty = self.air.typeOfIndex(inst);
test/behavior/eval.zig+1
...@@ -488,6 +488,7 @@ test "comptime bitwise operators" {...@@ -488,6 +488,7 @@ test "comptime bitwise operators" {
488test "comptime shlWithOverflow" {488test "comptime shlWithOverflow" {
489 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO489 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
490 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO490 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
491 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
491492
492 const ct_shifted = @shlWithOverflow(~@as(u64, 0), 16)[0];493 const ct_shifted = @shlWithOverflow(~@as(u64, 0), 16)[0];
493 var a = ~@as(u64, 0);494 var a = ~@as(u64, 0);
test/behavior/int128.zig-1
...@@ -40,7 +40,6 @@ test "undefined 128 bit int" {...@@ -40,7 +40,6 @@ test "undefined 128 bit int" {
40}40}
4141
42test "int128" {42test "int128" {
43 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
44 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO43 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
45 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO44 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
46 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO45 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/math.zig+2
...@@ -1237,6 +1237,8 @@ fn testShlTrunc(x: u16) !void {...@@ -1237,6 +1237,8 @@ fn testShlTrunc(x: u16) !void {
1237}1237}
12381238
1239test "exact shift left" {1239test "exact shift left" {
1240 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1241
1240 try testShlExact(0b00110101);1242 try testShlExact(0b00110101);
1241 comptime try testShlExact(0b00110101);1243 comptime try testShlExact(0b00110101);
1242}1244}