authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-03-25 07:45:52-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-04-09 20:14:12-04:00
log55ce756868fbe2cfc6cec956122d27af762b78f6
tree846b114003c86668289bec87eab8b18fc24206ef
parent80068b6e592c72ac891f5c4cb7129444c301b357

x86_64: rewrite scalar `@subWithOverflow`


2 files changed, 946 insertions(+), 10 deletions(-)

src/arch/x86_64/CodeGen.zig+915-4
......@@ -2418,7 +2418,7 @@ fn genBodyBlock(self: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
24182418}
24192419
24202420fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2421 @setEvalBranchQuota(14_100);
2421 @setEvalBranchQuota(14_200);
24222422 const pt = cg.pt;
24232423 const zcu = pt.zcu;
24242424 const ip = &zcu.intern_pool;
......@@ -2459,7 +2459,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
24592459 .mul_sat => try cg.airMulSat(inst),
24602460 .shl_sat => try cg.airShlSat(inst),
24612461
2462 .sub_with_overflow => try cg.airAddSubWithOverflow(inst),
24632462 .mul_with_overflow => try cg.airMulWithOverflow(inst),
24642463 .shl_with_overflow => try cg.airShlWithOverflow(inst),
24652464
......@@ -28500,8 +28499,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2850028499 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
2850128500 .{ ._, ._, .mov, .tmp1q, .memad(.src0q, .add_size, -16), ._, ._ },
2850228501 .{ ._, ._, .adc, .tmp1q, .memad(.src1q, .add_size, -16), ._, ._ },
28503 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -16), .tmp1q, ._, ._ },
2850428502 .{ ._, ._o, .set, .mema(.dst0b, .add_src0_size), ._, ._, ._ },
28503 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -16), .tmp1q, ._, ._ },
2850528504 .{ ._, ._r, .sa, .tmp1q, .ui(63), ._, ._ },
2850628505 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp1q, ._, ._ },
2850728506 } },
......@@ -28869,6 +28868,912 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2886928868 try res[0].withOverflow(&res[1], cg);
2887028869 try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
2887128870 },
28871 .sub_with_overflow => |air_tag| if (use_old) try cg.airAddSubWithOverflow(inst) else fallback: {
28872 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
28873 const bin_op = cg.air.extraData(Air.Bin, ty_pl.payload).data;
28874 if (cg.typeOf(bin_op.lhs).isVector(zcu)) break :fallback try cg.airAddSubWithOverflow(inst);
28875 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
28876 var res: [2]Temp = undefined;
28877 cg.select(&res, &.{ ty_pl.ty.toType(), .u1 }, &ops, comptime &.{ .{
28878 .src_constraints = .{ .{ .exact_signed_int = 8 }, .{ .exact_signed_int = 8 }, .any },
28879 .patterns = &.{
28880 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28881 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28882 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28883 },
28884 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
28885 .clobbers = .{ .eflags = true },
28886 .each = .{ .once = &.{
28887 .{ ._, ._, .sub, .dst0b, .src1b, ._, ._ },
28888 } },
28889 }, .{
28890 .src_constraints = .{ .{ .exact_unsigned_int = 8 }, .{ .exact_unsigned_int = 8 }, .any },
28891 .patterns = &.{
28892 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28893 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28894 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28895 },
28896 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .c } },
28897 .clobbers = .{ .eflags = true },
28898 .each = .{ .once = &.{
28899 .{ ._, ._, .sub, .dst0b, .src1b, ._, ._ },
28900 } },
28901 }, .{
28902 .src_constraints = .{ .{ .signed_int = .byte }, .{ .signed_int = .byte }, .any },
28903 .patterns = &.{
28904 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28905 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28906 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28907 },
28908 .extra_temps = .{
28909 .{ .type = .i8, .kind = .{ .mut_rc = .{ .ref = .src1, .rc = .general_purpose } } },
28910 .unused,
28911 .unused,
28912 .unused,
28913 .unused,
28914 .unused,
28915 .unused,
28916 .unused,
28917 .unused,
28918 .unused,
28919 .unused,
28920 },
28921 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .po } },
28922 .clobbers = .{ .eflags = true },
28923 .each = .{ .once = &.{
28924 .{ ._, ._, .sub, .dst0b, .src1b, ._, ._ },
28925 .{ ._, ._, .mov, .tmp0d, .dst0d, ._, ._ },
28926 .{ ._, ._l, .sa, .dst0b, .uia(8, .src0, .sub_bit_size), ._, ._ },
28927 .{ ._, ._r, .sa, .dst0b, .uia(8, .src0, .sub_bit_size), ._, ._ },
28928 .{ ._, ._, .@"test", .tmp0b, .sia(-1 << 7, .src0, .sub_smin), ._, ._ },
28929 } },
28930 }, .{
28931 .src_constraints = .{ .{ .unsigned_int = .byte }, .{ .unsigned_int = .byte }, .any },
28932 .patterns = &.{
28933 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28934 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28935 .{ .src = .{ .to_mut_gpr, .immut_gpr, .none } },
28936 },
28937 .dst_temps = .{ .{ .ref = .src0 }, .{ .rc = .general_purpose } },
28938 .clobbers = .{ .eflags = true },
28939 .each = .{ .once = &.{
28940 .{ ._, ._, .xor, .dst1d, .dst1d, ._, ._ },
28941 .{ ._, ._, .sub, .dst0b, .src1b, ._, ._ },
28942 .{ ._, ._c, .set, .dst1b, ._, ._, ._ },
28943 .{ ._, ._, .@"and", .dst0b, .ua(.src0, .add_umax), ._, ._ },
28944 } },
28945 }, .{
28946 .src_constraints = .{ .{ .unsigned_int = .byte }, .{ .unsigned_int = .byte }, .any },
28947 .patterns = &.{
28948 .{ .src = .{ .to_mut_gpr, .to_mut_gpr, .none } },
28949 },
28950 .dst_temps = .{ .{ .ref = .src0 }, .{ .ref = .src1 } },
28951 .clobbers = .{ .eflags = true },
28952 .each = .{ .once = &.{
28953 .{ ._, ._, .sub, .dst0b, .src1b, ._, ._ },
28954 .{ ._, ._c, .set, .dst1b, ._, ._, ._ },
28955 .{ ._, ._, .@"and", .dst0b, .ua(.src0, .add_umax), ._, ._ },
28956 } },
28957 }, .{
28958 .src_constraints = .{ .{ .exact_signed_int = 16 }, .{ .exact_signed_int = 16 }, .any },
28959 .patterns = &.{
28960 .{ .src = .{ .to_mut_gpr, .imm16, .none } },
28961 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28962 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28963 },
28964 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
28965 .clobbers = .{ .eflags = true },
28966 .each = .{ .once = &.{
28967 .{ ._, ._, .sub, .dst0w, .src1w, ._, ._ },
28968 } },
28969 }, .{
28970 .src_constraints = .{ .{ .exact_unsigned_int = 16 }, .{ .exact_unsigned_int = 16 }, .any },
28971 .patterns = &.{
28972 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28973 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28974 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28975 },
28976 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .c } },
28977 .clobbers = .{ .eflags = true },
28978 .each = .{ .once = &.{
28979 .{ ._, ._, .sub, .dst0w, .src1w, ._, ._ },
28980 } },
28981 }, .{
28982 .src_constraints = .{ .{ .signed_int = .word }, .{ .signed_int = .word }, .any },
28983 .patterns = &.{
28984 .{ .src = .{ .to_mut_gpr, .imm16, .none } },
28985 },
28986 .extra_temps = .{
28987 .{ .type = .i32, .kind = .{ .mut_rc = .{ .ref = .src1, .rc = .general_purpose } } },
28988 .unused,
28989 .unused,
28990 .unused,
28991 .unused,
28992 .unused,
28993 .unused,
28994 .unused,
28995 .unused,
28996 .unused,
28997 .unused,
28998 },
28999 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
29000 .clobbers = .{ .eflags = true },
29001 .each = .{ .once = &.{
29002 .{ ._, ._, .sub, .dst0w, .src1w, ._, ._ },
29003 .{ ._, ._l, .ro, .dst0d, .uia(32, .src0, .sub_bit_size), ._, ._ },
29004 .{ ._, ._, .mov, .tmp0d, .dst0d, ._, ._ },
29005 .{ ._, ._r, .sa, .dst0d, .uia(32, .src0, .sub_bit_size), ._, ._ },
29006 .{ ._, ._r, .ro, .tmp0d, .ui(1), ._, ._ },
29007 } },
29008 }, .{
29009 .src_constraints = .{ .{ .signed_int = .word }, .{ .signed_int = .word }, .any },
29010 .patterns = &.{
29011 .{ .src = .{ .to_mut_gpr, .mem, .none } },
29012 },
29013 .extra_temps = .{
29014 .{ .type = .i32, .kind = .{ .mut_rc = .{ .ref = .src1, .rc = .general_purpose } } },
29015 .unused,
29016 .unused,
29017 .unused,
29018 .unused,
29019 .unused,
29020 .unused,
29021 .unused,
29022 .unused,
29023 .unused,
29024 .unused,
29025 },
29026 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
29027 .clobbers = .{ .eflags = true },
29028 .each = .{ .once = &.{
29029 .{ ._, ._, .sub, .dst0w, .src1w, ._, ._ },
29030 .{ ._, ._l, .ro, .dst0d, .uia(32, .src0, .sub_bit_size), ._, ._ },
29031 .{ ._, ._, .mov, .tmp0d, .dst0d, ._, ._ },
29032 .{ ._, ._r, .sa, .dst0d, .uia(32, .src0, .sub_bit_size), ._, ._ },
29033 .{ ._, ._r, .ro, .tmp0d, .ui(1), ._, ._ },
29034 } },
29035 }, .{
29036 .required_features = .{ .fast_imm16, null, null, null },
29037 .src_constraints = .{ .{ .unsigned_int = .word }, .{ .unsigned_int = .word }, .any },
29038 .patterns = &.{
29039 .{ .src = .{ .to_mut_gpr, .imm16, .none } },
29040 .{ .src = .{ .to_mut_gpr, .mem, .none } },
29041 .{ .src = .{ .to_mut_gpr, .immut_gpr, .none } },
29042 },
29043 .dst_temps = .{ .{ .ref = .src0 }, .{ .rc = .general_purpose } },
29044 .clobbers = .{ .eflags = true },
29045 .each = .{ .once = &.{
29046 .{ ._, ._, .xor, .dst1d, .dst1d, ._, ._ },
29047 .{ ._, ._, .sub, .dst0w, .src1w, ._, ._ },
29048 .{ ._, ._c, .set, .dst1b, ._, ._, ._ },
29049 .{ ._, ._, .@"and", .dst0w, .ua(.src0, .add_umax), ._, ._ },
29050 } },
29051 }, .{
29052 .required_features = .{ .fast_imm16, null, null, null },
29053 .src_constraints = .{ .{ .unsigned_int = .word }, .{ .unsigned_int = .word }, .any },
29054 .patterns = &.{
29055 .{ .src = .{ .to_mut_gpr, .to_mut_gpr, .none } },
29056 },
29057 .dst_temps = .{ .{ .ref = .src0 }, .{ .ref = .src1 } },
29058 .clobbers = .{ .eflags = true },
29059 .each = .{ .once = &.{
29060 .{ ._, ._, .sub, .dst0w, .src1w, ._, ._ },
29061 .{ ._, ._c, .set, .dst1b, ._, ._, ._ },
29062 .{ ._, ._, .@"and", .dst0w, .ua(.src0, .add_umax), ._, ._ },
29063 } },
29064 }, .{
29065 .src_constraints = .{ .{ .unsigned_int = .word }, .{ .unsigned_int = .word }, .any },
29066 .patterns = &.{
29067 .{ .src = .{ .to_mut_gpr, .imm16, .none } },
29068 .{ .src = .{ .to_mut_gpr, .mem, .none } },
29069 .{ .src = .{ .to_mut_gpr, .immut_gpr, .none } },
29070 },
29071 .dst_temps = .{ .{ .ref = .src0 }, .{ .rc = .general_purpose } },
29072 .clobbers = .{ .eflags = true },
29073 .each = .{ .once = &.{
29074 .{ ._, ._, .xor, .dst1d, .dst1d, ._, ._ },
29075 .{ ._, ._, .sub, .dst0w, .src1w, ._, ._ },
29076 .{ ._, ._c, .set, .dst1b, ._, ._, ._ },
29077 .{ ._, ._, .@"and", .dst0d, .ua(.src0, .add_umax), ._, ._ },
29078 } },
29079 }, .{
29080 .src_constraints = .{ .{ .unsigned_int = .word }, .{ .unsigned_int = .word }, .any },
29081 .patterns = &.{
29082 .{ .src = .{ .to_mut_gpr, .to_mut_gpr, .none } },
29083 },
29084 .dst_temps = .{ .{ .ref = .src0 }, .{ .ref = .src1 } },
29085 .clobbers = .{ .eflags = true },
29086 .each = .{ .once = &.{
29087 .{ ._, ._, .sub, .dst0w, .src1w, ._, ._ },
29088 .{ ._, ._c, .set, .dst1b, ._, ._, ._ },
29089 .{ ._, ._, .@"and", .dst0d, .ua(.src0, .add_umax), ._, ._ },
29090 } },
29091 }, .{
29092 .src_constraints = .{ .{ .exact_signed_int = 32 }, .{ .exact_signed_int = 32 }, .any },
29093 .patterns = &.{
29094 .{ .src = .{ .to_mut_gpr, .imm32, .none } },
29095 .{ .src = .{ .to_mut_gpr, .mem, .none } },
29096 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
29097 },
29098 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
29099 .clobbers = .{ .eflags = true },
29100 .each = .{ .once = &.{
29101 .{ ._, ._, .sub, .dst0d, .src1d, ._, ._ },
29102 } },
29103 }, .{
29104 .src_constraints = .{ .{ .exact_unsigned_int = 32 }, .{ .exact_unsigned_int = 32 }, .any },
29105 .patterns = &.{
29106 .{ .src = .{ .to_mut_gpr, .imm32, .none } },
29107 .{ .src = .{ .to_mut_gpr, .mem, .none } },
29108 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
29109 },
29110 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .c } },
29111 .clobbers = .{ .eflags = true },
29112 .each = .{ .once = &.{
29113 .{ ._, ._, .sub, .dst0d, .src1d, ._, ._ },
29114 } },
29115 }, .{
29116 .required_features = .{ .bmi2, null, null, null },
29117 .src_constraints = .{ .{ .exact_signed_int = 31 }, .{ .exact_signed_int = 31 }, .any },
29118 .patterns = &.{
29119 .{ .src = .{ .to_mut_gpr, .imm32, .none } },
29120 .{ .src = .{ .to_mut_gpr, .mem, .none } },
29121 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
29122 },
29123 .extra_temps = .{
29124 .{ .type = .u8, .kind = .{ .mut_rc = .{ .ref = .src1, .rc = .general_purpose } } },
29125 .unused,
29126 .unused,
29127 .unused,
29128 .unused,
29129 .unused,
29130 .unused,
29131 .unused,
29132 .unused,
29133 .unused,
29134 .unused,
29135 },
29136 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
29137 .clobbers = .{ .eflags = true },
29138 .each = .{ .once = &.{
29139 .{ ._, ._, .sub, .dst0d, .src1d, ._, ._ },
29140 .{ ._, ._, .mov, .tmp0d, .ui(1), ._, ._ },
29141 .{ ._, ._, .add, .dst0d, .dst0d, ._, ._ },
29142 .{ ._, ._rx, .sa, .dst0d, .dst0d, .tmp0d, ._ },
29143 } },
29144 }, .{
29145 .src_constraints = .{ .{ .signed_int = .dword }, .{ .signed_int = .dword }, .any },
29146 .patterns = &.{
29147 .{ .src = .{ .to_mut_gpr, .imm32, .none } },
29148 .{ .src = .{ .to_mut_gpr, .mem, .none } },
29149 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
29150 },
29151 .extra_temps = .{
29152 .{ .type = .i32, .kind = .{ .mut_rc = .{ .ref = .src1, .rc = .general_purpose } } },
29153 .unused,
29154 .unused,
29155 .unused,
29156 .unused,
29157 .unused,
29158 .unused,
29159 .unused,
29160 .unused,
29161 .unused,
29162 .unused,
29163 },
29164 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
29165 .clobbers = .{ .eflags = true },
29166 .each = .{ .once = &.{
29167 .{ ._, ._, .sub, .dst0d, .src1d, ._, ._ },
29168 .{ ._, ._l, .ro, .dst0d, .uia(32, .src0, .sub_bit_size), ._, ._ },
29169 .{ ._, ._, .mov, .tmp0d, .dst0d, ._, ._ },
29170 .{ ._, ._r, .sa, .dst0d, .uia(32, .src0, .sub_bit_size), ._, ._ },
29171 .{ ._, ._r, .ro, .tmp0d, .ui(1), ._, ._ },
29172 } },
29173 }, .{
29174 .src_constraints = .{ .{ .unsigned_int = .dword }, .{ .unsigned_int = .dword }, .any },
29175 .patterns = &.{
29176 .{ .src = .{ .to_mut_gpr, .imm32, .none } },
29177 .{ .src = .{ .to_mut_gpr, .mem, .none } },
29178 .{ .src = .{ .to_mut_gpr, .immut_gpr, .none } },
29179 },
29180 .dst_temps = .{ .{ .ref = .src0 }, .{ .rc = .general_purpose } },
29181 .clobbers = .{ .eflags = true },
29182 .each = .{ .once = &.{
29183 .{ ._, ._, .xor, .dst1d, .dst1d, ._, ._ },
29184 .{ ._, ._, .sub, .dst0d, .src1d, ._, ._ },
29185 .{ ._, ._c, .set, .dst1b, ._, ._, ._ },
29186 .{ ._, ._, .@"and", .dst0d, .ua(.src0, .add_umax), ._, ._ },
29187 } },
29188 }, .{
29189 .src_constraints = .{ .{ .unsigned_int = .dword }, .{ .unsigned_int = .dword }, .any },
29190 .patterns = &.{
29191 .{ .src = .{ .to_mut_gpr, .to_mut_gpr, .none } },
29192 },
29193 .dst_temps = .{ .{ .ref = .src0 }, .{ .ref = .src1 } },
29194 .clobbers = .{ .eflags = true },
29195 .each = .{ .once = &.{
29196 .{ ._, ._, .sub, .dst0d, .src1d, ._, ._ },
29197 .{ ._, ._c, .set, .dst1b, ._, ._, ._ },
29198 .{ ._, ._, .@"and", .dst0d, .ua(.src0, .add_umax), ._, ._ },
29199 } },
29200 }, .{
29201 .required_features = .{ .@"64bit", null, null, null },
29202 .src_constraints = .{ .{ .exact_signed_int = 64 }, .{ .exact_signed_int = 64 }, .any },
29203 .patterns = &.{
29204 .{ .src = .{ .to_mut_gpr, .simm32, .none } },
29205 .{ .src = .{ .to_mut_gpr, .mem, .none } },
29206 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
29207 },
29208 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
29209 .clobbers = .{ .eflags = true },
29210 .each = .{ .once = &.{
29211 .{ ._, ._, .sub, .dst0q, .src1q, ._, ._ },
29212 } },
29213 }, .{
29214 .required_features = .{ .@"64bit", null, null, null },
29215 .src_constraints = .{ .{ .exact_unsigned_int = 64 }, .{ .exact_unsigned_int = 64 }, .any },
29216 .patterns = &.{
29217 .{ .src = .{ .to_mut_gpr, .simm32, .none } },
29218 .{ .src = .{ .to_mut_gpr, .mem, .none } },
29219 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
29220 },
29221 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .c } },
29222 .clobbers = .{ .eflags = true },
29223 .each = .{ .once = &.{
29224 .{ ._, ._, .sub, .dst0q, .src1q, ._, ._ },
29225 } },
29226 }, .{
29227 .required_features = .{ .@"64bit", .bmi2, null, null },
29228 .src_constraints = .{ .{ .exact_signed_int = 63 }, .{ .exact_signed_int = 63 }, .any },
29229 .patterns = &.{
29230 .{ .src = .{ .to_mut_gpr, .simm32, .none } },
29231 .{ .src = .{ .to_mut_gpr, .mem, .none } },
29232 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
29233 },
29234 .extra_temps = .{
29235 .{ .type = .u8, .kind = .{ .mut_rc = .{ .ref = .src1, .rc = .general_purpose } } },
29236 .unused,
29237 .unused,
29238 .unused,
29239 .unused,
29240 .unused,
29241 .unused,
29242 .unused,
29243 .unused,
29244 .unused,
29245 .unused,
29246 },
29247 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
29248 .clobbers = .{ .eflags = true },
29249 .each = .{ .once = &.{
29250 .{ ._, ._, .sub, .dst0q, .src1q, ._, ._ },
29251 .{ ._, ._, .mov, .tmp0d, .ui(1), ._, ._ },
29252 .{ ._, ._, .add, .dst0q, .dst0q, ._, ._ },
29253 .{ ._, ._rx, .sa, .dst0q, .dst0q, .tmp0q, ._ },
29254 } },
29255 }, .{
29256 .required_features = .{ .@"64bit", null, null, null },
29257 .src_constraints = .{ .{ .signed_int = .qword }, .{ .signed_int = .qword }, .any },
29258 .patterns = &.{
29259 .{ .src = .{ .to_mut_gpr, .simm32, .none } },
29260 .{ .src = .{ .to_mut_gpr, .mem, .none } },
29261 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
29262 },
29263 .extra_temps = .{
29264 .{ .type = .i64, .kind = .{ .mut_rc = .{ .ref = .src1, .rc = .general_purpose } } },
29265 .unused,
29266 .unused,
29267 .unused,
29268 .unused,
29269 .unused,
29270 .unused,
29271 .unused,
29272 .unused,
29273 .unused,
29274 .unused,
29275 },
29276 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
29277 .clobbers = .{ .eflags = true },
29278 .each = .{ .once = &.{
29279 .{ ._, ._, .sub, .dst0q, .src1q, ._, ._ },
29280 .{ ._, ._l, .ro, .dst0q, .uia(64, .src0, .sub_bit_size), ._, ._ },
29281 .{ ._, ._, .mov, .tmp0q, .dst0q, ._, ._ },
29282 .{ ._, ._r, .sa, .dst0q, .uia(64, .src0, .sub_bit_size), ._, ._ },
29283 .{ ._, ._r, .ro, .tmp0q, .ui(1), ._, ._ },
29284 } },
29285 }, .{
29286 .required_features = .{ .@"64bit", .bmi2, null, null },
29287 .src_constraints = .{ .{ .unsigned_int = .qword }, .{ .unsigned_int = .qword }, .any },
29288 .patterns = &.{
29289 .{ .src = .{ .to_mut_gpr, .simm32, .none } },
29290 .{ .src = .{ .to_mut_gpr, .mem, .none } },
29291 .{ .src = .{ .to_mut_gpr, .immut_gpr, .none } },
29292 },
29293 .extra_temps = .{
29294 .{ .type = .u8, .kind = .{ .rc = .general_purpose } },
29295 .unused,
29296 .unused,
29297 .unused,
29298 .unused,
29299 .unused,
29300 .unused,
29301 .unused,
29302 .unused,
29303 .unused,
29304 .unused,
29305 },
29306 .dst_temps = .{ .{ .ref = .src0 }, .{ .rc = .general_purpose } },
29307 .clobbers = .{ .eflags = true },
29308 .each = .{ .once = &.{
29309 .{ ._, ._, .xor, .dst1d, .dst1d, ._, ._ },
29310 .{ ._, ._, .mov, .tmp0d, .ua(.src0, .add_bit_size), ._, ._ },
29311 .{ ._, ._, .sub, .dst0q, .src1q, ._, ._ },
29312 .{ ._, ._c, .set, .dst1b, ._, ._, ._ },
29313 .{ ._, ._, .bzhi, .dst0q, .dst0q, .tmp0q, ._ },
29314 } },
29315 }, .{
29316 .required_features = .{ .@"64bit", .bmi2, null, null },
29317 .src_constraints = .{ .{ .unsigned_int = .qword }, .{ .unsigned_int = .qword }, .any },
29318 .patterns = &.{
29319 .{ .src = .{ .to_mut_gpr, .to_mut_gpr, .none } },
29320 },
29321 .extra_temps = .{
29322 .{ .type = .u8, .kind = .{ .rc = .general_purpose } },
29323 .unused,
29324 .unused,
29325 .unused,
29326 .unused,
29327 .unused,
29328 .unused,
29329 .unused,
29330 .unused,
29331 .unused,
29332 .unused,
29333 },
29334 .dst_temps = .{ .{ .ref = .src0 }, .{ .ref = .src1 } },
29335 .clobbers = .{ .eflags = true },
29336 .each = .{ .once = &.{
29337 .{ ._, ._, .mov, .tmp0d, .ua(.src0, .add_bit_size), ._, ._ },
29338 .{ ._, ._, .sub, .dst0q, .src1q, ._, ._ },
29339 .{ ._, ._c, .set, .dst1b, ._, ._, ._ },
29340 .{ ._, ._, .bzhi, .dst0q, .dst0q, .tmp0q, ._ },
29341 } },
29342 }, .{
29343 .required_features = .{ .@"64bit", null, null, null },
29344 .src_constraints = .{ .{ .unsigned_int = .qword }, .{ .unsigned_int = .qword }, .any },
29345 .patterns = &.{
29346 .{ .src = .{ .to_mut_gpr, .simm32, .none } },
29347 .{ .src = .{ .to_mut_gpr, .mem, .none } },
29348 .{ .src = .{ .to_mut_gpr, .immut_gpr, .none } },
29349 },
29350 .dst_temps = .{ .{ .rc = .general_purpose }, .{ .rc = .general_purpose } },
29351 .clobbers = .{ .eflags = true },
29352 .each = .{ .once = &.{
29353 .{ ._, ._, .xor, .dst1d, .dst1d, ._, ._ },
29354 .{ ._, ._, .mov, .dst0q, .ua(.src0, .add_umax), ._, ._ },
29355 .{ ._, ._, .sub, .src0q, .src1q, ._, ._ },
29356 .{ ._, ._c, .set, .dst1b, ._, ._, ._ },
29357 .{ ._, ._, .@"and", .dst0q, .src0q, ._, ._ },
29358 } },
29359 }, .{
29360 .required_features = .{ .@"64bit", null, null, null },
29361 .src_constraints = .{ .{ .unsigned_int = .qword }, .{ .unsigned_int = .qword }, .any },
29362 .patterns = &.{
29363 .{ .src = .{ .to_mut_gpr, .to_mut_gpr, .none } },
29364 },
29365 .dst_temps = .{ .{ .rc = .general_purpose }, .{ .ref = .src1 } },
29366 .clobbers = .{ .eflags = true },
29367 .each = .{ .once = &.{
29368 .{ ._, ._, .mov, .dst0q, .ua(.src0, .add_umax), ._, ._ },
29369 .{ ._, ._, .sub, .src0q, .src1q, ._, ._ },
29370 .{ ._, ._c, .set, .dst1b, ._, ._, ._ },
29371 .{ ._, ._, .@"and", .dst0q, .src0q, ._, ._ },
29372 } },
29373 }, .{
29374 .required_features = .{ .@"64bit", null, null, null },
29375 .src_constraints = .{
29376 .{ .exact_remainder_signed_int = .{ .of = .xword, .is = .qword } },
29377 .{ .exact_remainder_signed_int = .{ .of = .xword, .is = .qword } },
29378 .any,
29379 },
29380 .patterns = &.{
29381 .{ .src = .{ .to_mem, .to_mem, .none } },
29382 },
29383 .extra_temps = .{
29384 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
29385 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29386 .unused,
29387 .unused,
29388 .unused,
29389 .unused,
29390 .unused,
29391 .unused,
29392 .unused,
29393 .unused,
29394 .unused,
29395 },
29396 .dst_temps = .{ .mem, .none },
29397 .clobbers = .{ .eflags = true },
29398 .each = .{ .once = &.{
29399 .{ ._, ._, .mov, .tmp0p, .sia(2, .src0, .sub_size_div_8), ._, ._ },
29400 .{ ._, ._c, .cl, ._, ._, ._, ._ },
29401 .{ .@"0:", ._, .mov, .tmp1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -16), ._, ._ },
29402 .{ ._, ._, .sbb, .tmp1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -16), ._, ._ },
29403 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -16), .tmp1q, ._, ._ },
29404 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
29405 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
29406 .{ ._, ._, .mov, .tmp1q, .memad(.src0q, .add_size, -16), ._, ._ },
29407 .{ ._, ._, .sbb, .tmp1q, .memad(.src1q, .add_size, -16), ._, ._ },
29408 .{ ._, ._o, .set, .mema(.dst0b, .add_src0_size), ._, ._, ._ },
29409 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -16), .tmp1q, ._, ._ },
29410 .{ ._, ._r, .sa, .tmp1q, .ui(63), ._, ._ },
29411 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp1q, ._, ._ },
29412 } },
29413 }, .{
29414 .required_features = .{ .@"64bit", null, null, null },
29415 .src_constraints = .{
29416 .{ .exact_remainder_unsigned_int = .{ .of = .xword, .is = .qword } },
29417 .{ .exact_remainder_unsigned_int = .{ .of = .xword, .is = .qword } },
29418 .any,
29419 },
29420 .patterns = &.{
29421 .{ .src = .{ .to_mem, .to_mem, .none } },
29422 },
29423 .extra_temps = .{
29424 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
29425 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29426 .unused,
29427 .unused,
29428 .unused,
29429 .unused,
29430 .unused,
29431 .unused,
29432 .unused,
29433 .unused,
29434 .unused,
29435 },
29436 .dst_temps = .{ .mem, .{ .cc = .c } },
29437 .clobbers = .{ .eflags = true },
29438 .each = .{ .once = &.{
29439 .{ ._, ._, .mov, .tmp0p, .sia(1, .src0, .sub_size_div_8), ._, ._ },
29440 .{ ._, ._c, .cl, ._, ._, ._, ._ },
29441 .{ .@"0:", ._, .mov, .tmp1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -8), ._, ._ },
29442 .{ ._, ._, .sbb, .tmp1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -8), ._, ._ },
29443 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -8), .tmp1q, ._, ._ },
29444 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
29445 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
29446 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .ui(0), ._, ._ },
29447 } },
29448 }, .{
29449 .required_features = .{ .@"64bit", null, null, null },
29450 .src_constraints = .{
29451 .{ .exact_remainder_signed_int = .{ .of = .xword, .is = .xword } },
29452 .{ .exact_remainder_signed_int = .{ .of = .xword, .is = .xword } },
29453 .any,
29454 },
29455 .patterns = &.{
29456 .{ .src = .{ .to_mem, .to_mem, .none } },
29457 },
29458 .extra_temps = .{
29459 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
29460 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29461 .unused,
29462 .unused,
29463 .unused,
29464 .unused,
29465 .unused,
29466 .unused,
29467 .unused,
29468 .unused,
29469 .unused,
29470 },
29471 .dst_temps = .{ .mem, .{ .cc = .o } },
29472 .clobbers = .{ .eflags = true },
29473 .each = .{ .once = &.{
29474 .{ ._, ._, .mov, .tmp0p, .sia(1, .src0, .sub_size_div_8), ._, ._ },
29475 .{ ._, ._c, .cl, ._, ._, ._, ._ },
29476 .{ .@"0:", ._, .mov, .tmp1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -8), ._, ._ },
29477 .{ ._, ._, .sbb, .tmp1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -8), ._, ._ },
29478 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -8), .tmp1q, ._, ._ },
29479 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
29480 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
29481 .{ ._, ._, .mov, .tmp1q, .memad(.src0q, .add_size, -8), ._, ._ },
29482 .{ ._, ._, .sbb, .tmp1q, .memad(.src1q, .add_size, -8), ._, ._ },
29483 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp1q, ._, ._ },
29484 } },
29485 }, .{
29486 .required_features = .{ .@"64bit", null, null, null },
29487 .src_constraints = .{
29488 .{ .exact_remainder_unsigned_int = .{ .of = .xword, .is = .xword } },
29489 .{ .exact_remainder_unsigned_int = .{ .of = .xword, .is = .xword } },
29490 .any,
29491 },
29492 .patterns = &.{
29493 .{ .src = .{ .to_mem, .to_mem, .none } },
29494 },
29495 .extra_temps = .{
29496 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
29497 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29498 .unused,
29499 .unused,
29500 .unused,
29501 .unused,
29502 .unused,
29503 .unused,
29504 .unused,
29505 .unused,
29506 .unused,
29507 },
29508 .dst_temps = .{ .mem, .{ .cc = .c } },
29509 .clobbers = .{ .eflags = true },
29510 .each = .{ .once = &.{
29511 .{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_size_div_8), ._, ._ },
29512 .{ ._, ._c, .cl, ._, ._, ._, ._ },
29513 .{ .@"0:", ._, .mov, .tmp1q, .memsia(.src0q, .@"8", .tmp0, .add_size), ._, ._ },
29514 .{ ._, ._, .sbb, .tmp1q, .memsia(.src1q, .@"8", .tmp0, .add_size), ._, ._ },
29515 .{ ._, ._, .mov, .memsia(.dst0q, .@"8", .tmp0, .add_src0_size), .tmp1q, ._, ._ },
29516 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
29517 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
29518 } },
29519 }, .{
29520 .required_features = .{ .@"64bit", null, null, null },
29521 .src_constraints = .{
29522 .{ .remainder_signed_int = .{ .of = .xword, .is = .qword } },
29523 .{ .remainder_signed_int = .{ .of = .xword, .is = .qword } },
29524 .any,
29525 },
29526 .patterns = &.{
29527 .{ .src = .{ .to_mem, .to_mem, .none } },
29528 },
29529 .extra_temps = .{
29530 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
29531 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29532 .unused,
29533 .unused,
29534 .unused,
29535 .unused,
29536 .unused,
29537 .unused,
29538 .unused,
29539 .unused,
29540 .unused,
29541 },
29542 .dst_temps = .{ .mem, .{ .cc = .o } },
29543 .clobbers = .{ .eflags = true },
29544 .each = .{ .once = &.{
29545 .{ ._, ._, .mov, .tmp0p, .sia(2, .src0, .sub_size_div_8), ._, ._ },
29546 .{ ._, ._c, .cl, ._, ._, ._, ._ },
29547 .{ .@"0:", ._, .mov, .tmp1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -16), ._, ._ },
29548 .{ ._, ._, .sbb, .tmp1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -16), ._, ._ },
29549 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -16), .tmp1q, ._, ._ },
29550 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
29551 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
29552 .{ ._, ._, .mov, .tmp1q, .memad(.src0q, .add_size, -16), ._, ._ },
29553 .{ ._, ._, .sbb, .tmp1q, .memad(.src1q, .add_size, -16), ._, ._ },
29554 .{ ._, ._l, .ro, .tmp1q, .uia(64, .src0, .sub_bit_size_rem_64), ._, ._ },
29555 .{ ._, ._, .mov, .tmp0q, .tmp1q, ._, ._ },
29556 .{ ._, ._r, .sa, .tmp1q, .uia(64, .src0, .sub_bit_size_rem_64), ._, ._ },
29557 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -16), .tmp1q, ._, ._ },
29558 .{ ._, ._r, .sa, .tmp1q, .ui(63), ._, ._ },
29559 .{ ._, ._r, .ro, .tmp0q, .ui(1), ._, ._ },
29560 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp1q, ._, ._ },
29561 } },
29562 }, .{
29563 .required_features = .{ .@"64bit", .bmi2, null, null },
29564 .src_constraints = .{
29565 .{ .remainder_unsigned_int = .{ .of = .xword, .is = .qword } },
29566 .{ .remainder_unsigned_int = .{ .of = .xword, .is = .qword } },
29567 .any,
29568 },
29569 .patterns = &.{
29570 .{ .src = .{ .to_mem, .to_mem, .none } },
29571 },
29572 .extra_temps = .{
29573 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
29574 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29575 .unused,
29576 .unused,
29577 .unused,
29578 .unused,
29579 .unused,
29580 .unused,
29581 .unused,
29582 .unused,
29583 .unused,
29584 },
29585 .dst_temps = .{ .mem, .none },
29586 .clobbers = .{ .eflags = true },
29587 .each = .{ .once = &.{
29588 .{ ._, ._, .mov, .tmp0p, .sia(2, .src0, .sub_size_div_8), ._, ._ },
29589 .{ ._, ._c, .cl, ._, ._, ._, ._ },
29590 .{ .@"0:", ._, .mov, .tmp1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -16), ._, ._ },
29591 .{ ._, ._, .sbb, .tmp1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -16), ._, ._ },
29592 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -16), .tmp1q, ._, ._ },
29593 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
29594 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
29595 .{ ._, ._, .mov, .tmp1q, .memad(.src0q, .add_size, -16), ._, ._ },
29596 .{ ._, ._, .mov, .tmp0d, .ua(.src0, .add_bit_size_rem_64), ._, ._ },
29597 .{ ._, ._, .sbb, .tmp1q, .memad(.src1q, .add_size, -16), ._, ._ },
29598 .{ ._, ._c, .set, .mema(.dst0b, .add_src0_size), ._, ._, ._ },
29599 .{ ._, ._, .bzhi, .tmp0q, .tmp1q, .tmp0q, ._ },
29600 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .ui(0), ._, ._ },
29601 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -16), .tmp0q, ._, ._ },
29602 } },
29603 }, .{
29604 .required_features = .{ .@"64bit", null, null, null },
29605 .src_constraints = .{
29606 .{ .remainder_unsigned_int = .{ .of = .xword, .is = .qword } },
29607 .{ .remainder_unsigned_int = .{ .of = .xword, .is = .qword } },
29608 .any,
29609 },
29610 .patterns = &.{
29611 .{ .src = .{ .to_mem, .to_mem, .none } },
29612 },
29613 .extra_temps = .{
29614 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
29615 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29616 .unused,
29617 .unused,
29618 .unused,
29619 .unused,
29620 .unused,
29621 .unused,
29622 .unused,
29623 .unused,
29624 .unused,
29625 },
29626 .dst_temps = .{ .mem, .none },
29627 .clobbers = .{ .eflags = true },
29628 .each = .{ .once = &.{
29629 .{ ._, ._, .mov, .tmp0p, .sia(2, .src0, .sub_size_div_8), ._, ._ },
29630 .{ ._, ._c, .cl, ._, ._, ._, ._ },
29631 .{ .@"0:", ._, .mov, .tmp1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -16), ._, ._ },
29632 .{ ._, ._, .sbb, .tmp1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -16), ._, ._ },
29633 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -16), .tmp1q, ._, ._ },
29634 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
29635 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
29636 .{ ._, ._, .mov, .tmp1q, .memad(.src0q, .add_size, -16), ._, ._ },
29637 .{ ._, ._, .mov, .tmp0q, .ua(.src0, .add_umax), ._, ._ },
29638 .{ ._, ._, .sbb, .tmp1q, .memad(.src1q, .add_size, -16), ._, ._ },
29639 .{ ._, ._c, .set, .mema(.dst0b, .add_src0_size), ._, ._, ._ },
29640 .{ ._, ._, .@"and", .tmp0q, .tmp1q, ._, ._ },
29641 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .ui(0), ._, ._ },
29642 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -16), .tmp0q, ._, ._ },
29643 } },
29644 }, .{
29645 .required_features = .{ .@"64bit", null, null, null },
29646 .src_constraints = .{
29647 .{ .remainder_signed_int = .{ .of = .xword, .is = .xword } },
29648 .{ .remainder_signed_int = .{ .of = .xword, .is = .xword } },
29649 .any,
29650 },
29651 .patterns = &.{
29652 .{ .src = .{ .to_mem, .to_mem, .none } },
29653 },
29654 .extra_temps = .{
29655 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
29656 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29657 .unused,
29658 .unused,
29659 .unused,
29660 .unused,
29661 .unused,
29662 .unused,
29663 .unused,
29664 .unused,
29665 .unused,
29666 },
29667 .dst_temps = .{ .mem, .{ .cc = .o } },
29668 .clobbers = .{ .eflags = true },
29669 .each = .{ .once = &.{
29670 .{ ._, ._, .mov, .tmp0p, .sia(1, .src0, .sub_size_div_8), ._, ._ },
29671 .{ ._, ._c, .cl, ._, ._, ._, ._ },
29672 .{ .@"0:", ._, .mov, .tmp1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -8), ._, ._ },
29673 .{ ._, ._, .sbb, .tmp1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -8), ._, ._ },
29674 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -8), .tmp1q, ._, ._ },
29675 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
29676 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
29677 .{ ._, ._, .mov, .tmp1q, .memad(.src0q, .add_size, -8), ._, ._ },
29678 .{ ._, ._, .sbb, .tmp1q, .memad(.src1q, .add_size, -8), ._, ._ },
29679 .{ ._, ._l, .ro, .tmp1q, .uia(64, .src0, .sub_bit_size_rem_64), ._, ._ },
29680 .{ ._, ._, .mov, .tmp0q, .tmp1q, ._, ._ },
29681 .{ ._, ._r, .sa, .tmp1q, .uia(64, .src0, .sub_bit_size_rem_64), ._, ._ },
29682 .{ ._, ._r, .ro, .tmp0q, .ui(1), ._, ._ },
29683 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp1q, ._, ._ },
29684 } },
29685 }, .{
29686 .required_features = .{ .@"64bit", .bmi2, null, null },
29687 .src_constraints = .{
29688 .{ .remainder_unsigned_int = .{ .of = .xword, .is = .xword } },
29689 .{ .remainder_unsigned_int = .{ .of = .xword, .is = .xword } },
29690 .any,
29691 },
29692 .patterns = &.{
29693 .{ .src = .{ .to_mem, .to_mem, .none } },
29694 },
29695 .extra_temps = .{
29696 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
29697 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29698 .unused,
29699 .unused,
29700 .unused,
29701 .unused,
29702 .unused,
29703 .unused,
29704 .unused,
29705 .unused,
29706 .unused,
29707 },
29708 .dst_temps = .{ .mem, .none },
29709 .clobbers = .{ .eflags = true },
29710 .each = .{ .once = &.{
29711 .{ ._, ._, .mov, .tmp0p, .sia(1, .src0, .sub_size_div_8), ._, ._ },
29712 .{ ._, ._c, .cl, ._, ._, ._, ._ },
29713 .{ .@"0:", ._, .mov, .tmp1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -8), ._, ._ },
29714 .{ ._, ._, .sbb, .tmp1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -8), ._, ._ },
29715 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -8), .tmp1q, ._, ._ },
29716 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
29717 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
29718 .{ ._, ._, .mov, .tmp1q, .memad(.src0q, .add_size, -8), ._, ._ },
29719 .{ ._, ._, .mov, .tmp0d, .ua(.src0, .add_bit_size_rem_64), ._, ._ },
29720 .{ ._, ._, .sbb, .tmp1q, .memad(.src1q, .add_size, -8), ._, ._ },
29721 .{ ._, ._c, .set, .mema(.dst0b, .add_src0_size), ._, ._, ._ },
29722 .{ ._, ._, .bzhi, .tmp0q, .tmp1q, .tmp0q, ._ },
29723 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ },
29724 } },
29725 }, .{
29726 .required_features = .{ .@"64bit", null, null, null },
29727 .src_constraints = .{
29728 .{ .remainder_unsigned_int = .{ .of = .xword, .is = .xword } },
29729 .{ .remainder_unsigned_int = .{ .of = .xword, .is = .xword } },
29730 .any,
29731 },
29732 .patterns = &.{
29733 .{ .src = .{ .to_mem, .to_mem, .none } },
29734 },
29735 .extra_temps = .{
29736 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
29737 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29738 .unused,
29739 .unused,
29740 .unused,
29741 .unused,
29742 .unused,
29743 .unused,
29744 .unused,
29745 .unused,
29746 .unused,
29747 },
29748 .dst_temps = .{ .mem, .none },
29749 .clobbers = .{ .eflags = true },
29750 .each = .{ .once = &.{
29751 .{ ._, ._, .mov, .tmp0p, .sia(1, .src0, .sub_size_div_8), ._, ._ },
29752 .{ ._, ._c, .cl, ._, ._, ._, ._ },
29753 .{ .@"0:", ._, .mov, .tmp1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -8), ._, ._ },
29754 .{ ._, ._, .sbb, .tmp1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -8), ._, ._ },
29755 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -8), .tmp1q, ._, ._ },
29756 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
29757 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
29758 .{ ._, ._, .mov, .tmp1q, .memad(.src0q, .add_size, -8), ._, ._ },
29759 .{ ._, ._, .mov, .tmp0q, .ua(.src0, .add_umax), ._, ._ },
29760 .{ ._, ._, .sbb, .tmp1q, .memad(.src1q, .add_size, -8), ._, ._ },
29761 .{ ._, ._c, .set, .mema(.dst0b, .add_src0_size), ._, ._, ._ },
29762 .{ ._, ._, .@"and", .tmp0q, .tmp1q, ._, ._ },
29763 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ },
29764 } },
29765 } }) catch |err| switch (err) {
29766 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{
29767 @tagName(air_tag),
29768 ty_pl.ty.toType().fmt(pt),
29769 ops[0].tracking(cg),
29770 ops[1].tracking(cg),
29771 }),
29772 else => |e| return e,
29773 };
29774 try res[0].withOverflow(&res[1], cg);
29775 try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
29776 },
2887229777 .alloc => if (use_old) try cg.airAlloc(inst) else {
2887329778 const ty = air_datas[@intFromEnum(inst)].ty;
2887429779 const slot = try cg.tempInit(ty, .{ .lea_frame = .{
......@@ -111270,6 +112175,7 @@ const Select = struct {
111270112175 mut_mem,
111271112176 to_mut_mem,
111272112177 gpr,
112178 immut_gpr,
111273112179 to_gpr,
111274112180 mut_gpr,
111275112181 to_mut_gpr,
......@@ -111329,6 +112235,11 @@ const Select = struct {
111329112235 .register_offset => |reg_off| reg_off.reg.class() == .general_purpose and reg_off.off == 0,
111330112236 else => false,
111331112237 },
112238 .immut_gpr => !temp.isMut(cg) and temp.typeOf(cg).abiSize(cg.pt.zcu) <= 8 and switch (temp.tracking(cg).short) {
112239 .register => |reg| reg.class() == .general_purpose,
112240 .register_offset => |reg_off| reg_off.reg.class() == .general_purpose and reg_off.off == 0,
112241 else => false,
112242 },
111332112243 .mut_gpr => temp.isMut(cg) and temp.typeOf(cg).abiSize(cg.pt.zcu) <= 8 and switch (temp.tracking(cg).short) {
111333112244 .register => |reg| reg.class() == .general_purpose,
111334112245 .register_offset => |reg_off| reg_off.reg.class() == .general_purpose and reg_off.off == 0,
......@@ -111415,7 +112326,7 @@ const Select = struct {
111415112326 .to_param_gpr_pair => |param_spec| try temp.toRegPair(abi.getCAbiIntParamRegs(param_spec.tag(cg))[param_spec.index..][0..2].*, cg),
111416112327 .to_ret_gpr => |ret_spec| try temp.toReg(abi.getCAbiIntReturnRegs(ret_spec.tag(cg))[ret_spec.index], cg),
111417112328 .to_ret_gpr_pair => |ret_spec| try temp.toRegPair(abi.getCAbiIntReturnRegs(ret_spec.tag(cg))[ret_spec.index..][0..2].*, cg),
111418 .gpr, .to_gpr => try temp.toRegClass(false, .general_purpose, cg),
112329 .gpr, .immut_gpr, .to_gpr => try temp.toRegClass(false, .general_purpose, cg),
111419112330 .mut_gpr, .to_mut_gpr => try temp.toRegClass(true, .general_purpose, cg),
111420112331 .x87, .to_x87 => try temp.toRegClass(false, .x87, cg),
111421112332 .mut_x87, .to_mut_x87 => try temp.toRegClass(true, .x87, cg),
test/behavior/x86_64/binary.zig+31-6
......@@ -5284,15 +5284,14 @@ test addWrap {
52845284
52855285inline fn subUnsafe(comptime Type: type, lhs: Type, rhs: Type) AddOneBit(Type) {
52865286 @setRuntimeSafety(false);
5287 switch (@typeInfo(Scalar(Type))) {
5287 return switch (@typeInfo(Scalar(Type))) {
52885288 else => @compileError(@typeName(Type)),
52895289 .int => |int| switch (int.signedness) {
5290 .signed => {},
5291 .unsigned => return @as(AddOneBit(Type), @max(lhs, rhs)) - @min(lhs, rhs),
5290 .signed => @as(AddOneBit(Type), lhs) - rhs,
5291 .unsigned => @as(AddOneBit(Type), @max(lhs, rhs)) - @min(lhs, rhs),
52925292 },
5293 .float => {},
5294 }
5295 return @as(AddOneBit(Type), lhs) - rhs;
5293 .float => lhs - rhs,
5294 };
52965295}
52975296test subUnsafe {
52985297 const test_sub_unsafe = binary(subUnsafe, .{});
......@@ -5302,6 +5301,24 @@ test subUnsafe {
53025301 try test_sub_unsafe.testFloatVectors();
53035302}
53045303
5304inline fn subSafe(comptime Type: type, lhs: Type, rhs: Type) AddOneBit(Type) {
5305 @setRuntimeSafety(true);
5306 return switch (@typeInfo(Scalar(Type))) {
5307 else => @compileError(@typeName(Type)),
5308 .int => |int| switch (int.signedness) {
5309 .signed => @as(AddOneBit(Type), lhs) - rhs,
5310 .unsigned => @as(AddOneBit(Type), @max(lhs, rhs)) - @min(lhs, rhs),
5311 },
5312 .float => lhs - rhs,
5313 };
5314}
5315test subSafe {
5316 const test_sub_safe = binary(subSafe, .{});
5317 try test_sub_safe.testInts();
5318 try test_sub_safe.testFloats();
5319 try test_sub_safe.testFloatVectors();
5320}
5321
53055322inline fn subWrap(comptime Type: type, lhs: Type, rhs: Type) Type {
53065323 return lhs -% rhs;
53075324}
......@@ -5435,6 +5452,14 @@ test addWithOverflow {
54355452 try test_add_with_overflow.testInts();
54365453}
54375454
5455inline fn subWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, u1 } {
5456 return @subWithOverflow(lhs, rhs);
5457}
5458test subWithOverflow {
5459 const test_sub_with_overflow = binary(subWithOverflow, .{});
5460 try test_sub_with_overflow.testInts();
5461}
5462
54385463inline fn equal(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs == rhs) {
54395464 return lhs == rhs;
54405465}