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
log80068b6e592c72ac891f5c4cb7129444c301b357
treec212c4db25c238230adcc251127b0f519088f2dc
parent426684b2f84bfa6389553c8dfee921875eb8c888

x86_64: rewrite scalar `@addWithOverflow`


4 files changed, 998 insertions(+), 20 deletions(-)

src/arch/x86_64/CodeGen.zig+961-11
...@@ -2418,7 +2418,7 @@ fn genBodyBlock(self: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2418,7 +2418,7 @@ fn genBodyBlock(self: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2418}2418}
24192419
2420fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {2420fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2421 @setEvalBranchQuota(13_900);2421 @setEvalBranchQuota(14_100);
2422 const pt = cg.pt;2422 const pt = cg.pt;
2423 const zcu = pt.zcu;2423 const zcu = pt.zcu;
2424 const ip = &zcu.intern_pool;2424 const ip = &zcu.intern_pool;
...@@ -2459,7 +2459,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2459,7 +2459,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2459 .mul_sat => try cg.airMulSat(inst),2459 .mul_sat => try cg.airMulSat(inst),
2460 .shl_sat => try cg.airShlSat(inst),2460 .shl_sat => try cg.airShlSat(inst),
24612461
2462 .add_with_overflow => try cg.airAddSubWithOverflow(inst),
2463 .sub_with_overflow => try cg.airAddSubWithOverflow(inst),2462 .sub_with_overflow => try cg.airAddSubWithOverflow(inst),
2464 .mul_with_overflow => try cg.airMulWithOverflow(inst),2463 .mul_with_overflow => try cg.airMulWithOverflow(inst),
2465 .shl_with_overflow => try cg.airShlWithOverflow(inst),2464 .shl_with_overflow => try cg.airShlWithOverflow(inst),
...@@ -28019,6 +28018,857 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -28019,6 +28018,857 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
28019 };28018 };
28020 try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);28019 try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
28021 },28020 },
28021 .add_with_overflow => |air_tag| if (use_old) try cg.airAddSubWithOverflow(inst) else fallback: {
28022 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
28023 const bin_op = cg.air.extraData(Air.Bin, ty_pl.payload).data;
28024 if (cg.typeOf(bin_op.lhs).isVector(zcu)) break :fallback try cg.airAddSubWithOverflow(inst);
28025 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
28026 var res: [2]Temp = undefined;
28027 cg.select(&res, &.{ ty_pl.ty.toType(), .u1 }, &ops, comptime &.{ .{
28028 .src_constraints = .{ .{ .exact_signed_int = 8 }, .{ .exact_signed_int = 8 }, .any },
28029 .patterns = &.{
28030 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28031 .{ .src = .{ .imm8, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28032 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28033 .{ .src = .{ .mem, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28034 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28035 },
28036 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
28037 .clobbers = .{ .eflags = true },
28038 .each = .{ .once = &.{
28039 .{ ._, ._, .add, .dst0b, .src1b, ._, ._ },
28040 } },
28041 }, .{
28042 .src_constraints = .{ .{ .exact_unsigned_int = 8 }, .{ .exact_unsigned_int = 8 }, .any },
28043 .patterns = &.{
28044 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28045 .{ .src = .{ .imm8, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28046 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28047 .{ .src = .{ .mem, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28048 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28049 },
28050 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .c } },
28051 .clobbers = .{ .eflags = true },
28052 .each = .{ .once = &.{
28053 .{ ._, ._, .add, .dst0b, .src1b, ._, ._ },
28054 } },
28055 }, .{
28056 .src_constraints = .{ .{ .signed_int = .byte }, .{ .signed_int = .byte }, .any },
28057 .patterns = &.{
28058 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28059 .{ .src = .{ .imm8, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28060 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28061 .{ .src = .{ .mem, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28062 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28063 },
28064 .extra_temps = .{
28065 .{ .type = .i8, .kind = .{ .mut_rc = .{ .ref = .src1, .rc = .general_purpose } } },
28066 .unused,
28067 .unused,
28068 .unused,
28069 .unused,
28070 .unused,
28071 .unused,
28072 .unused,
28073 .unused,
28074 .unused,
28075 .unused,
28076 },
28077 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .po } },
28078 .clobbers = .{ .eflags = true },
28079 .each = .{ .once = &.{
28080 .{ ._, ._, .add, .dst0b, .src1b, ._, ._ },
28081 .{ ._, ._, .mov, .tmp0d, .dst0d, ._, ._ },
28082 .{ ._, ._l, .sa, .dst0b, .uia(8, .src0, .sub_bit_size), ._, ._ },
28083 .{ ._, ._r, .sa, .dst0b, .uia(8, .src0, .sub_bit_size), ._, ._ },
28084 .{ ._, ._, .@"test", .tmp0b, .sia(-1 << 7, .src0, .sub_smin), ._, ._ },
28085 } },
28086 }, .{
28087 .src_constraints = .{ .{ .unsigned_int = .byte }, .{ .unsigned_int = .byte }, .any },
28088 .patterns = &.{
28089 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28090 .{ .src = .{ .imm8, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28091 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28092 },
28093 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .b } },
28094 .clobbers = .{ .eflags = true },
28095 .each = .{ .once = &.{
28096 .{ ._, ._, .add, .dst0b, .src1b, ._, ._ },
28097 .{ ._, ._, .@"and", .dst0b, .ua(.src0, .add_umax), ._, ._ },
28098 .{ ._, ._, .cmp, .dst0b, .src1b, ._, ._ },
28099 } },
28100 }, .{
28101 .src_constraints = .{ .{ .exact_signed_int = 16 }, .{ .exact_signed_int = 16 }, .any },
28102 .patterns = &.{
28103 .{ .src = .{ .to_mut_gpr, .imm16, .none } },
28104 .{ .src = .{ .imm16, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28105 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28106 .{ .src = .{ .mem, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28107 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28108 },
28109 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
28110 .clobbers = .{ .eflags = true },
28111 .each = .{ .once = &.{
28112 .{ ._, ._, .add, .dst0w, .src1w, ._, ._ },
28113 } },
28114 }, .{
28115 .src_constraints = .{ .{ .exact_unsigned_int = 16 }, .{ .exact_unsigned_int = 16 }, .any },
28116 .patterns = &.{
28117 .{ .src = .{ .to_mut_gpr, .imm16, .none } },
28118 .{ .src = .{ .imm16, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28119 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28120 .{ .src = .{ .mem, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28121 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28122 },
28123 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .c } },
28124 .clobbers = .{ .eflags = true },
28125 .each = .{ .once = &.{
28126 .{ ._, ._, .add, .dst0w, .src1w, ._, ._ },
28127 } },
28128 }, .{
28129 .required_features = .{ .fast_imm16, null, null, null },
28130 .src_constraints = .{ .{ .signed_int = .word }, .{ .signed_int = .word }, .any },
28131 .patterns = &.{
28132 .{ .src = .{ .to_mut_gpr, .imm16, .none } },
28133 .{ .src = .{ .imm16, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28134 },
28135 .extra_temps = .{
28136 .{ .type = .i32, .kind = .{ .mut_rc = .{ .ref = .src1, .rc = .general_purpose } } },
28137 .unused,
28138 .unused,
28139 .unused,
28140 .unused,
28141 .unused,
28142 .unused,
28143 .unused,
28144 .unused,
28145 .unused,
28146 .unused,
28147 },
28148 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
28149 .clobbers = .{ .eflags = true },
28150 .each = .{ .once = &.{
28151 .{ ._, ._, .add, .dst0w, .src1w, ._, ._ },
28152 .{ ._, ._l, .ro, .dst0d, .uia(32, .src0, .sub_bit_size), ._, ._ },
28153 .{ ._, ._, .mov, .tmp0d, .dst0d, ._, ._ },
28154 .{ ._, ._r, .sa, .dst0d, .uia(32, .src0, .sub_bit_size), ._, ._ },
28155 .{ ._, ._r, .ro, .tmp0d, .ui(1), ._, ._ },
28156 } },
28157 }, .{
28158 .src_constraints = .{ .{ .signed_int = .word }, .{ .signed_int = .word }, .any },
28159 .patterns = &.{
28160 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28161 .{ .src = .{ .mem, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28162 },
28163 .extra_temps = .{
28164 .{ .type = .i32, .kind = .{ .mut_rc = .{ .ref = .src1, .rc = .general_purpose } } },
28165 .unused,
28166 .unused,
28167 .unused,
28168 .unused,
28169 .unused,
28170 .unused,
28171 .unused,
28172 .unused,
28173 .unused,
28174 .unused,
28175 },
28176 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
28177 .clobbers = .{ .eflags = true },
28178 .each = .{ .once = &.{
28179 .{ ._, ._, .add, .dst0w, .src1w, ._, ._ },
28180 .{ ._, ._l, .ro, .dst0d, .uia(32, .src0, .sub_bit_size), ._, ._ },
28181 .{ ._, ._, .mov, .tmp0d, .dst0d, ._, ._ },
28182 .{ ._, ._r, .sa, .dst0d, .uia(32, .src0, .sub_bit_size), ._, ._ },
28183 .{ ._, ._r, .ro, .tmp0d, .ui(1), ._, ._ },
28184 } },
28185 }, .{
28186 .required_features = .{ .fast_imm16, null, null, null },
28187 .src_constraints = .{ .{ .unsigned_int = .word }, .{ .unsigned_int = .word }, .any },
28188 .patterns = &.{
28189 .{ .src = .{ .to_mut_gpr, .imm16, .none } },
28190 .{ .src = .{ .imm16, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28191 },
28192 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .b } },
28193 .clobbers = .{ .eflags = true },
28194 .each = .{ .once = &.{
28195 .{ ._, ._, .add, .dst0w, .src1w, ._, ._ },
28196 .{ ._, ._, .@"and", .dst0w, .ua(.src0, .add_umax), ._, ._ },
28197 .{ ._, ._, .cmp, .dst0w, .src1w, ._, ._ },
28198 } },
28199 }, .{
28200 .required_features = .{ .fast_imm16, null, null, null },
28201 .src_constraints = .{ .{ .unsigned_int = .word }, .{ .unsigned_int = .word }, .any },
28202 .patterns = &.{
28203 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28204 },
28205 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .b } },
28206 .clobbers = .{ .eflags = true },
28207 .each = .{ .once = &.{
28208 .{ ._, ._, .add, .dst0d, .src1d, ._, ._ },
28209 .{ ._, ._, .@"and", .dst0w, .ua(.src0, .add_umax), ._, ._ },
28210 .{ ._, ._, .cmp, .dst0w, .src1w, ._, ._ },
28211 } },
28212 }, .{
28213 .src_constraints = .{ .{ .unsigned_int = .word }, .{ .unsigned_int = .word }, .any },
28214 .patterns = &.{
28215 .{ .src = .{ .to_mut_gpr, .imm16, .none } },
28216 .{ .src = .{ .imm16, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28217 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28218 },
28219 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .b } },
28220 .clobbers = .{ .eflags = true },
28221 .each = .{ .once = &.{
28222 .{ ._, ._, .add, .dst0d, .src1d, ._, ._ },
28223 .{ ._, ._, .@"and", .dst0d, .ua(.src0, .add_umax), ._, ._ },
28224 .{ ._, ._, .cmp, .dst0w, .src1w, ._, ._ },
28225 } },
28226 }, .{
28227 .src_constraints = .{ .{ .exact_signed_int = 32 }, .{ .exact_signed_int = 32 }, .any },
28228 .patterns = &.{
28229 .{ .src = .{ .to_mut_gpr, .imm32, .none } },
28230 .{ .src = .{ .imm32, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28231 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28232 .{ .src = .{ .mem, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28233 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28234 },
28235 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
28236 .clobbers = .{ .eflags = true },
28237 .each = .{ .once = &.{
28238 .{ ._, ._, .add, .dst0d, .src1d, ._, ._ },
28239 } },
28240 }, .{
28241 .src_constraints = .{ .{ .exact_unsigned_int = 32 }, .{ .exact_unsigned_int = 32 }, .any },
28242 .patterns = &.{
28243 .{ .src = .{ .to_mut_gpr, .imm32, .none } },
28244 .{ .src = .{ .imm32, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28245 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28246 .{ .src = .{ .mem, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28247 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28248 },
28249 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .c } },
28250 .clobbers = .{ .eflags = true },
28251 .each = .{ .once = &.{
28252 .{ ._, ._, .add, .dst0d, .src1d, ._, ._ },
28253 } },
28254 }, .{
28255 .required_features = .{ .bmi2, null, null, null },
28256 .src_constraints = .{ .{ .exact_signed_int = 31 }, .{ .exact_signed_int = 31 }, .any },
28257 .patterns = &.{
28258 .{ .src = .{ .to_mut_gpr, .imm32, .none } },
28259 .{ .src = .{ .imm32, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28260 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28261 .{ .src = .{ .mem, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28262 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28263 },
28264 .extra_temps = .{
28265 .{ .type = .u8, .kind = .{ .mut_rc = .{ .ref = .src1, .rc = .general_purpose } } },
28266 .unused,
28267 .unused,
28268 .unused,
28269 .unused,
28270 .unused,
28271 .unused,
28272 .unused,
28273 .unused,
28274 .unused,
28275 .unused,
28276 },
28277 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
28278 .clobbers = .{ .eflags = true },
28279 .each = .{ .once = &.{
28280 .{ ._, ._, .add, .dst0d, .src1d, ._, ._ },
28281 .{ ._, ._, .mov, .tmp0d, .ui(1), ._, ._ },
28282 .{ ._, ._, .add, .dst0d, .dst0d, ._, ._ },
28283 .{ ._, ._rx, .sa, .dst0d, .dst0d, .tmp0d, ._ },
28284 } },
28285 }, .{
28286 .src_constraints = .{ .{ .signed_int = .dword }, .{ .signed_int = .dword }, .any },
28287 .patterns = &.{
28288 .{ .src = .{ .to_mut_gpr, .imm32, .none } },
28289 .{ .src = .{ .imm32, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28290 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28291 .{ .src = .{ .mem, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28292 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28293 },
28294 .extra_temps = .{
28295 .{ .type = .i32, .kind = .{ .mut_rc = .{ .ref = .src1, .rc = .general_purpose } } },
28296 .unused,
28297 .unused,
28298 .unused,
28299 .unused,
28300 .unused,
28301 .unused,
28302 .unused,
28303 .unused,
28304 .unused,
28305 .unused,
28306 },
28307 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
28308 .clobbers = .{ .eflags = true },
28309 .each = .{ .once = &.{
28310 .{ ._, ._, .add, .dst0d, .src1d, ._, ._ },
28311 .{ ._, ._l, .ro, .dst0d, .uia(32, .src0, .sub_bit_size), ._, ._ },
28312 .{ ._, ._, .mov, .tmp0d, .dst0d, ._, ._ },
28313 .{ ._, ._r, .sa, .dst0d, .uia(32, .src0, .sub_bit_size), ._, ._ },
28314 .{ ._, ._r, .ro, .tmp0d, .ui(1), ._, ._ },
28315 } },
28316 }, .{
28317 .src_constraints = .{ .{ .unsigned_int = .dword }, .{ .unsigned_int = .dword }, .any },
28318 .patterns = &.{
28319 .{ .src = .{ .to_mut_gpr, .imm32, .none } },
28320 .{ .src = .{ .imm32, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28321 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28322 },
28323 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .b } },
28324 .clobbers = .{ .eflags = true },
28325 .each = .{ .once = &.{
28326 .{ ._, ._, .add, .dst0d, .src1d, ._, ._ },
28327 .{ ._, ._, .@"and", .dst0d, .ua(.src0, .add_umax), ._, ._ },
28328 .{ ._, ._, .cmp, .dst0d, .src1d, ._, ._ },
28329 } },
28330 }, .{
28331 .required_features = .{ .@"64bit", null, null, null },
28332 .src_constraints = .{ .{ .exact_signed_int = 64 }, .{ .exact_signed_int = 64 }, .any },
28333 .patterns = &.{
28334 .{ .src = .{ .to_mut_gpr, .simm32, .none } },
28335 .{ .src = .{ .simm32, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28336 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28337 .{ .src = .{ .mem, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28338 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28339 },
28340 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
28341 .clobbers = .{ .eflags = true },
28342 .each = .{ .once = &.{
28343 .{ ._, ._, .add, .dst0q, .src1q, ._, ._ },
28344 } },
28345 }, .{
28346 .required_features = .{ .@"64bit", null, null, null },
28347 .src_constraints = .{ .{ .exact_unsigned_int = 64 }, .{ .exact_unsigned_int = 64 }, .any },
28348 .patterns = &.{
28349 .{ .src = .{ .to_mut_gpr, .simm32, .none } },
28350 .{ .src = .{ .simm32, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28351 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28352 .{ .src = .{ .mem, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28353 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28354 },
28355 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .c } },
28356 .clobbers = .{ .eflags = true },
28357 .each = .{ .once = &.{
28358 .{ ._, ._, .add, .dst0q, .src1q, ._, ._ },
28359 } },
28360 }, .{
28361 .required_features = .{ .@"64bit", .bmi2, null, null },
28362 .src_constraints = .{ .{ .exact_signed_int = 63 }, .{ .exact_signed_int = 63 }, .any },
28363 .patterns = &.{
28364 .{ .src = .{ .to_mut_gpr, .simm32, .none } },
28365 .{ .src = .{ .simm32, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28366 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28367 .{ .src = .{ .mem, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28368 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28369 },
28370 .extra_temps = .{
28371 .{ .type = .u8, .kind = .{ .mut_rc = .{ .ref = .src1, .rc = .general_purpose } } },
28372 .unused,
28373 .unused,
28374 .unused,
28375 .unused,
28376 .unused,
28377 .unused,
28378 .unused,
28379 .unused,
28380 .unused,
28381 .unused,
28382 },
28383 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
28384 .clobbers = .{ .eflags = true },
28385 .each = .{ .once = &.{
28386 .{ ._, ._, .add, .dst0q, .src1q, ._, ._ },
28387 .{ ._, ._, .mov, .tmp0d, .ui(1), ._, ._ },
28388 .{ ._, ._, .add, .dst0q, .dst0q, ._, ._ },
28389 .{ ._, ._rx, .sa, .dst0q, .dst0q, .tmp0q, ._ },
28390 } },
28391 }, .{
28392 .required_features = .{ .@"64bit", null, null, null },
28393 .src_constraints = .{ .{ .signed_int = .qword }, .{ .signed_int = .qword }, .any },
28394 .patterns = &.{
28395 .{ .src = .{ .to_mut_gpr, .simm32, .none } },
28396 .{ .src = .{ .simm32, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28397 .{ .src = .{ .to_mut_gpr, .mem, .none } },
28398 .{ .src = .{ .mem, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28399 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28400 },
28401 .extra_temps = .{
28402 .{ .type = .i64, .kind = .{ .mut_rc = .{ .ref = .src1, .rc = .general_purpose } } },
28403 .unused,
28404 .unused,
28405 .unused,
28406 .unused,
28407 .unused,
28408 .unused,
28409 .unused,
28410 .unused,
28411 .unused,
28412 .unused,
28413 },
28414 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .o } },
28415 .clobbers = .{ .eflags = true },
28416 .each = .{ .once = &.{
28417 .{ ._, ._, .add, .dst0q, .src1q, ._, ._ },
28418 .{ ._, ._l, .ro, .dst0q, .uia(64, .src0, .sub_bit_size), ._, ._ },
28419 .{ ._, ._, .mov, .tmp0q, .dst0q, ._, ._ },
28420 .{ ._, ._r, .sa, .dst0q, .uia(64, .src0, .sub_bit_size), ._, ._ },
28421 .{ ._, ._r, .ro, .tmp0q, .ui(1), ._, ._ },
28422 } },
28423 }, .{
28424 .required_features = .{ .@"64bit", .bmi2, null, null },
28425 .src_constraints = .{ .{ .unsigned_int = .qword }, .{ .unsigned_int = .qword }, .any },
28426 .patterns = &.{
28427 .{ .src = .{ .to_mut_gpr, .simm32, .none } },
28428 .{ .src = .{ .simm32, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28429 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28430 },
28431 .extra_temps = .{
28432 .{ .type = .u8, .kind = .{ .rc = .general_purpose } },
28433 .unused,
28434 .unused,
28435 .unused,
28436 .unused,
28437 .unused,
28438 .unused,
28439 .unused,
28440 .unused,
28441 .unused,
28442 .unused,
28443 },
28444 .dst_temps = .{ .{ .ref = .src0 }, .{ .cc = .b } },
28445 .clobbers = .{ .eflags = true },
28446 .each = .{ .once = &.{
28447 .{ ._, ._, .mov, .tmp0d, .ua(.src0, .add_bit_size), ._, ._ },
28448 .{ ._, ._, .add, .dst0q, .src1q, ._, ._ },
28449 .{ ._, ._, .bzhi, .dst0q, .dst0q, .tmp0q, ._ },
28450 .{ ._, ._, .cmp, .dst0q, .src1q, ._, ._ },
28451 } },
28452 }, .{
28453 .required_features = .{ .@"64bit", null, null, null },
28454 .src_constraints = .{ .{ .unsigned_int = .qword }, .{ .unsigned_int = .qword }, .any },
28455 .patterns = &.{
28456 .{ .src = .{ .to_mut_gpr, .simm32, .none } },
28457 .{ .src = .{ .simm32, .to_mut_gpr, .none }, .commute = .{ 0, 1 } },
28458 .{ .src = .{ .to_mut_gpr, .to_gpr, .none } },
28459 },
28460 .dst_temps = .{ .{ .rc = .general_purpose }, .{ .cc = .b } },
28461 .clobbers = .{ .eflags = true },
28462 .each = .{ .once = &.{
28463 .{ ._, ._, .mov, .dst0q, .ua(.src0, .add_umax), ._, ._ },
28464 .{ ._, ._, .add, .src0q, .src1q, ._, ._ },
28465 .{ ._, ._, .@"and", .dst0q, .src0q, ._, ._ },
28466 .{ ._, ._, .cmp, .dst0q, .src1q, ._, ._ },
28467 } },
28468 }, .{
28469 .required_features = .{ .@"64bit", null, null, null },
28470 .src_constraints = .{
28471 .{ .exact_remainder_signed_int = .{ .of = .xword, .is = .qword } },
28472 .{ .exact_remainder_signed_int = .{ .of = .xword, .is = .qword } },
28473 .any,
28474 },
28475 .patterns = &.{
28476 .{ .src = .{ .to_mem, .to_mem, .none } },
28477 },
28478 .extra_temps = .{
28479 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28480 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28481 .unused,
28482 .unused,
28483 .unused,
28484 .unused,
28485 .unused,
28486 .unused,
28487 .unused,
28488 .unused,
28489 .unused,
28490 },
28491 .dst_temps = .{ .mem, .none },
28492 .clobbers = .{ .eflags = true },
28493 .each = .{ .once = &.{
28494 .{ ._, ._, .mov, .tmp0p, .sia(2, .src0, .sub_size_div_8), ._, ._ },
28495 .{ ._, ._c, .cl, ._, ._, ._, ._ },
28496 .{ .@"0:", ._, .mov, .tmp1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -16), ._, ._ },
28497 .{ ._, ._, .adc, .tmp1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -16), ._, ._ },
28498 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -16), .tmp1q, ._, ._ },
28499 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
28500 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
28501 .{ ._, ._, .mov, .tmp1q, .memad(.src0q, .add_size, -16), ._, ._ },
28502 .{ ._, ._, .adc, .tmp1q, .memad(.src1q, .add_size, -16), ._, ._ },
28503 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -16), .tmp1q, ._, ._ },
28504 .{ ._, ._o, .set, .mema(.dst0b, .add_src0_size), ._, ._, ._ },
28505 .{ ._, ._r, .sa, .tmp1q, .ui(63), ._, ._ },
28506 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp1q, ._, ._ },
28507 } },
28508 }, .{
28509 .required_features = .{ .@"64bit", null, null, null },
28510 .src_constraints = .{
28511 .{ .exact_remainder_unsigned_int = .{ .of = .xword, .is = .qword } },
28512 .{ .exact_remainder_unsigned_int = .{ .of = .xword, .is = .qword } },
28513 .any,
28514 },
28515 .patterns = &.{
28516 .{ .src = .{ .to_mem, .to_mem, .none } },
28517 },
28518 .extra_temps = .{
28519 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28520 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28521 .unused,
28522 .unused,
28523 .unused,
28524 .unused,
28525 .unused,
28526 .unused,
28527 .unused,
28528 .unused,
28529 .unused,
28530 },
28531 .dst_temps = .{ .mem, .{ .cc = .c } },
28532 .clobbers = .{ .eflags = true },
28533 .each = .{ .once = &.{
28534 .{ ._, ._, .mov, .tmp0p, .sia(1, .src0, .sub_size_div_8), ._, ._ },
28535 .{ ._, ._c, .cl, ._, ._, ._, ._ },
28536 .{ .@"0:", ._, .mov, .tmp1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -8), ._, ._ },
28537 .{ ._, ._, .adc, .tmp1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -8), ._, ._ },
28538 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -8), .tmp1q, ._, ._ },
28539 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
28540 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
28541 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .ui(0), ._, ._ },
28542 } },
28543 }, .{
28544 .required_features = .{ .@"64bit", null, null, null },
28545 .src_constraints = .{
28546 .{ .exact_remainder_signed_int = .{ .of = .xword, .is = .xword } },
28547 .{ .exact_remainder_signed_int = .{ .of = .xword, .is = .xword } },
28548 .any,
28549 },
28550 .patterns = &.{
28551 .{ .src = .{ .to_mem, .to_mem, .none } },
28552 },
28553 .extra_temps = .{
28554 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28555 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28556 .unused,
28557 .unused,
28558 .unused,
28559 .unused,
28560 .unused,
28561 .unused,
28562 .unused,
28563 .unused,
28564 .unused,
28565 },
28566 .dst_temps = .{ .mem, .{ .cc = .o } },
28567 .clobbers = .{ .eflags = true },
28568 .each = .{ .once = &.{
28569 .{ ._, ._, .mov, .tmp0p, .sia(1, .src0, .sub_size_div_8), ._, ._ },
28570 .{ ._, ._c, .cl, ._, ._, ._, ._ },
28571 .{ .@"0:", ._, .mov, .tmp1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -8), ._, ._ },
28572 .{ ._, ._, .adc, .tmp1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -8), ._, ._ },
28573 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -8), .tmp1q, ._, ._ },
28574 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
28575 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
28576 .{ ._, ._, .mov, .tmp1q, .memad(.src0q, .add_size, -8), ._, ._ },
28577 .{ ._, ._, .adc, .tmp1q, .memad(.src1q, .add_size, -8), ._, ._ },
28578 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp1q, ._, ._ },
28579 } },
28580 }, .{
28581 .required_features = .{ .@"64bit", null, null, null },
28582 .src_constraints = .{
28583 .{ .exact_remainder_unsigned_int = .{ .of = .xword, .is = .xword } },
28584 .{ .exact_remainder_unsigned_int = .{ .of = .xword, .is = .xword } },
28585 .any,
28586 },
28587 .patterns = &.{
28588 .{ .src = .{ .to_mem, .to_mem, .none } },
28589 },
28590 .extra_temps = .{
28591 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28592 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28593 .unused,
28594 .unused,
28595 .unused,
28596 .unused,
28597 .unused,
28598 .unused,
28599 .unused,
28600 .unused,
28601 .unused,
28602 },
28603 .dst_temps = .{ .mem, .{ .cc = .c } },
28604 .clobbers = .{ .eflags = true },
28605 .each = .{ .once = &.{
28606 .{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_size_div_8), ._, ._ },
28607 .{ ._, ._c, .cl, ._, ._, ._, ._ },
28608 .{ .@"0:", ._, .mov, .tmp1q, .memsia(.src0q, .@"8", .tmp0, .add_size), ._, ._ },
28609 .{ ._, ._, .adc, .tmp1q, .memsia(.src1q, .@"8", .tmp0, .add_size), ._, ._ },
28610 .{ ._, ._, .mov, .memsia(.dst0q, .@"8", .tmp0, .add_src0_size), .tmp1q, ._, ._ },
28611 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
28612 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
28613 } },
28614 }, .{
28615 .required_features = .{ .@"64bit", null, null, null },
28616 .src_constraints = .{
28617 .{ .remainder_signed_int = .{ .of = .xword, .is = .qword } },
28618 .{ .remainder_signed_int = .{ .of = .xword, .is = .qword } },
28619 .any,
28620 },
28621 .patterns = &.{
28622 .{ .src = .{ .to_mem, .to_mem, .none } },
28623 },
28624 .extra_temps = .{
28625 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28626 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28627 .unused,
28628 .unused,
28629 .unused,
28630 .unused,
28631 .unused,
28632 .unused,
28633 .unused,
28634 .unused,
28635 .unused,
28636 },
28637 .dst_temps = .{ .mem, .{ .cc = .o } },
28638 .clobbers = .{ .eflags = true },
28639 .each = .{ .once = &.{
28640 .{ ._, ._, .mov, .tmp0p, .sia(2, .src0, .sub_size_div_8), ._, ._ },
28641 .{ ._, ._c, .cl, ._, ._, ._, ._ },
28642 .{ .@"0:", ._, .mov, .tmp1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -16), ._, ._ },
28643 .{ ._, ._, .adc, .tmp1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -16), ._, ._ },
28644 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -16), .tmp1q, ._, ._ },
28645 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
28646 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
28647 .{ ._, ._, .mov, .tmp1q, .memad(.src0q, .add_size, -16), ._, ._ },
28648 .{ ._, ._, .adc, .tmp1q, .memad(.src1q, .add_size, -16), ._, ._ },
28649 .{ ._, ._l, .ro, .tmp1q, .uia(64, .src0, .sub_bit_size_rem_64), ._, ._ },
28650 .{ ._, ._, .mov, .tmp0q, .tmp1q, ._, ._ },
28651 .{ ._, ._r, .sa, .tmp1q, .uia(64, .src0, .sub_bit_size_rem_64), ._, ._ },
28652 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -16), .tmp1q, ._, ._ },
28653 .{ ._, ._r, .sa, .tmp1q, .ui(63), ._, ._ },
28654 .{ ._, ._r, .ro, .tmp0q, .ui(1), ._, ._ },
28655 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp1q, ._, ._ },
28656 } },
28657 }, .{
28658 .required_features = .{ .@"64bit", .bmi2, null, null },
28659 .src_constraints = .{
28660 .{ .remainder_unsigned_int = .{ .of = .xword, .is = .qword } },
28661 .{ .remainder_unsigned_int = .{ .of = .xword, .is = .qword } },
28662 .any,
28663 },
28664 .patterns = &.{
28665 .{ .src = .{ .to_mem, .to_mem, .none } },
28666 },
28667 .extra_temps = .{
28668 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28669 .unused,
28670 .unused,
28671 .unused,
28672 .unused,
28673 .unused,
28674 .unused,
28675 .unused,
28676 .unused,
28677 .unused,
28678 .unused,
28679 },
28680 .dst_temps = .{ .mem, .{ .rc = .general_purpose } },
28681 .clobbers = .{ .eflags = true },
28682 .each = .{ .once = &.{
28683 .{ ._, ._, .mov, .tmp0p, .sia(2, .src0, .sub_size_div_8), ._, ._ },
28684 .{ ._, ._c, .cl, ._, ._, ._, ._ },
28685 .{ .@"0:", ._, .mov, .dst1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -16), ._, ._ },
28686 .{ ._, ._, .adc, .dst1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -16), ._, ._ },
28687 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -16), .dst1q, ._, ._ },
28688 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
28689 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
28690 .{ ._, ._, .mov, .dst1q, .memad(.src0q, .add_size, -16), ._, ._ },
28691 .{ ._, ._, .mov, .tmp0d, .ua(.src0, .add_bit_size_rem_64), ._, ._ },
28692 .{ ._, ._, .adc, .dst1q, .memad(.src1q, .add_size, -16), ._, ._ },
28693 .{ ._, ._, .bzhi, .tmp0q, .dst1q, .tmp0q, ._ },
28694 .{ ._, ._r, .sh, .dst1q, .ua(.src0, .add_bit_size_rem_64), ._, ._ },
28695 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -16), .tmp0q, ._, ._ },
28696 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .ui(0), ._, ._ },
28697 } },
28698 }, .{
28699 .required_features = .{ .@"64bit", null, null, null },
28700 .src_constraints = .{
28701 .{ .remainder_unsigned_int = .{ .of = .xword, .is = .qword } },
28702 .{ .remainder_unsigned_int = .{ .of = .xword, .is = .qword } },
28703 .any,
28704 },
28705 .patterns = &.{
28706 .{ .src = .{ .to_mem, .to_mem, .none } },
28707 },
28708 .extra_temps = .{
28709 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28710 .unused,
28711 .unused,
28712 .unused,
28713 .unused,
28714 .unused,
28715 .unused,
28716 .unused,
28717 .unused,
28718 .unused,
28719 .unused,
28720 },
28721 .dst_temps = .{ .mem, .{ .rc = .general_purpose } },
28722 .clobbers = .{ .eflags = true },
28723 .each = .{ .once = &.{
28724 .{ ._, ._, .mov, .tmp0p, .sia(2, .src0, .sub_size_div_8), ._, ._ },
28725 .{ ._, ._c, .cl, ._, ._, ._, ._ },
28726 .{ .@"0:", ._, .mov, .dst1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -16), ._, ._ },
28727 .{ ._, ._, .adc, .dst1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -16), ._, ._ },
28728 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -16), .dst1q, ._, ._ },
28729 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
28730 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
28731 .{ ._, ._, .mov, .dst1q, .memad(.src0q, .add_size, -16), ._, ._ },
28732 .{ ._, ._, .mov, .tmp0q, .ua(.src0, .add_umax), ._, ._ },
28733 .{ ._, ._, .adc, .dst1q, .memad(.src1q, .add_size, -16), ._, ._ },
28734 .{ ._, ._, .@"and", .tmp0q, .dst1q, ._, ._ },
28735 .{ ._, ._r, .sh, .dst1q, .ua(.src0, .add_bit_size_rem_64), ._, ._ },
28736 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -16), .tmp0q, ._, ._ },
28737 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .ui(0), ._, ._ },
28738 } },
28739 }, .{
28740 .required_features = .{ .@"64bit", null, null, null },
28741 .src_constraints = .{
28742 .{ .remainder_signed_int = .{ .of = .xword, .is = .xword } },
28743 .{ .remainder_signed_int = .{ .of = .xword, .is = .xword } },
28744 .any,
28745 },
28746 .patterns = &.{
28747 .{ .src = .{ .to_mem, .to_mem, .none } },
28748 },
28749 .extra_temps = .{
28750 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28751 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28752 .unused,
28753 .unused,
28754 .unused,
28755 .unused,
28756 .unused,
28757 .unused,
28758 .unused,
28759 .unused,
28760 .unused,
28761 },
28762 .dst_temps = .{ .mem, .{ .cc = .o } },
28763 .clobbers = .{ .eflags = true },
28764 .each = .{ .once = &.{
28765 .{ ._, ._, .mov, .tmp0p, .sia(1, .src0, .sub_size_div_8), ._, ._ },
28766 .{ ._, ._c, .cl, ._, ._, ._, ._ },
28767 .{ .@"0:", ._, .mov, .tmp1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -8), ._, ._ },
28768 .{ ._, ._, .adc, .tmp1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -8), ._, ._ },
28769 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -8), .tmp1q, ._, ._ },
28770 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
28771 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
28772 .{ ._, ._, .mov, .tmp1q, .memad(.src0q, .add_size, -8), ._, ._ },
28773 .{ ._, ._, .adc, .tmp1q, .memad(.src1q, .add_size, -8), ._, ._ },
28774 .{ ._, ._l, .ro, .tmp1q, .uia(64, .src0, .sub_bit_size_rem_64), ._, ._ },
28775 .{ ._, ._, .mov, .tmp0q, .tmp1q, ._, ._ },
28776 .{ ._, ._r, .sa, .tmp1q, .uia(64, .src0, .sub_bit_size_rem_64), ._, ._ },
28777 .{ ._, ._r, .ro, .tmp0q, .ui(1), ._, ._ },
28778 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp1q, ._, ._ },
28779 } },
28780 }, .{
28781 .required_features = .{ .@"64bit", .bmi2, null, null },
28782 .src_constraints = .{
28783 .{ .remainder_unsigned_int = .{ .of = .xword, .is = .xword } },
28784 .{ .remainder_unsigned_int = .{ .of = .xword, .is = .xword } },
28785 .any,
28786 },
28787 .patterns = &.{
28788 .{ .src = .{ .to_mem, .to_mem, .none } },
28789 },
28790 .extra_temps = .{
28791 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28792 .unused,
28793 .unused,
28794 .unused,
28795 .unused,
28796 .unused,
28797 .unused,
28798 .unused,
28799 .unused,
28800 .unused,
28801 .unused,
28802 },
28803 .dst_temps = .{ .mem, .{ .rc = .general_purpose } },
28804 .clobbers = .{ .eflags = true },
28805 .each = .{ .once = &.{
28806 .{ ._, ._, .mov, .tmp0p, .sia(1, .src0, .sub_size_div_8), ._, ._ },
28807 .{ ._, ._c, .cl, ._, ._, ._, ._ },
28808 .{ .@"0:", ._, .mov, .dst1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -8), ._, ._ },
28809 .{ ._, ._, .adc, .dst1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -8), ._, ._ },
28810 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -8), .dst1q, ._, ._ },
28811 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
28812 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
28813 .{ ._, ._, .mov, .dst1q, .memad(.src0q, .add_size, -8), ._, ._ },
28814 .{ ._, ._, .mov, .tmp0d, .ua(.src0, .add_bit_size_rem_64), ._, ._ },
28815 .{ ._, ._, .adc, .dst1q, .memad(.src1q, .add_size, -8), ._, ._ },
28816 .{ ._, ._, .bzhi, .tmp0q, .dst1q, .tmp0q, ._ },
28817 .{ ._, ._r, .sh, .dst1q, .ua(.src0, .add_bit_size_rem_64), ._, ._ },
28818 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ },
28819 } },
28820 }, .{
28821 .required_features = .{ .@"64bit", null, null, null },
28822 .src_constraints = .{
28823 .{ .remainder_unsigned_int = .{ .of = .xword, .is = .xword } },
28824 .{ .remainder_unsigned_int = .{ .of = .xword, .is = .xword } },
28825 .any,
28826 },
28827 .patterns = &.{
28828 .{ .src = .{ .to_mem, .to_mem, .none } },
28829 },
28830 .extra_temps = .{
28831 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28832 .unused,
28833 .unused,
28834 .unused,
28835 .unused,
28836 .unused,
28837 .unused,
28838 .unused,
28839 .unused,
28840 .unused,
28841 .unused,
28842 },
28843 .dst_temps = .{ .mem, .{ .rc = .general_purpose } },
28844 .clobbers = .{ .eflags = true },
28845 .each = .{ .once = &.{
28846 .{ ._, ._, .mov, .tmp0p, .sia(1, .src0, .sub_size_div_8), ._, ._ },
28847 .{ ._, ._c, .cl, ._, ._, ._, ._ },
28848 .{ .@"0:", ._, .mov, .dst1q, .memsiad(.src0q, .@"8", .tmp0, .add_size, -8), ._, ._ },
28849 .{ ._, ._, .adc, .dst1q, .memsiad(.src1q, .@"8", .tmp0, .add_size, -8), ._, ._ },
28850 .{ ._, ._, .mov, .memsiad(.dst0q, .@"8", .tmp0, .add_src0_size, -8), .dst1q, ._, ._ },
28851 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
28852 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
28853 .{ ._, ._, .mov, .dst1q, .memad(.src0q, .add_size, -8), ._, ._ },
28854 .{ ._, ._, .mov, .tmp0q, .ua(.src0, .add_umax), ._, ._ },
28855 .{ ._, ._, .adc, .dst1q, .memad(.src1q, .add_size, -8), ._, ._ },
28856 .{ ._, ._, .@"and", .tmp0q, .dst1q, ._, ._ },
28857 .{ ._, ._r, .sh, .dst1q, .ua(.src0, .add_bit_size_rem_64), ._, ._ },
28858 .{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ },
28859 } },
28860 } }) catch |err| switch (err) {
28861 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{
28862 @tagName(air_tag),
28863 ty_pl.ty.toType().fmt(pt),
28864 ops[0].tracking(cg),
28865 ops[1].tracking(cg),
28866 }),
28867 else => |e| return e,
28868 };
28869 try res[0].withOverflow(&res[1], cg);
28870 try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
28871 },
28022 .alloc => if (use_old) try cg.airAlloc(inst) else {28872 .alloc => if (use_old) try cg.airAlloc(inst) else {
28023 const ty = air_datas[@intFromEnum(inst)].ty;28873 const ty = air_datas[@intFromEnum(inst)].ty;
28024 const slot = try cg.tempInit(ty, .{ .lea_frame = .{28874 const slot = try cg.tempInit(ty, .{ .lea_frame = .{
...@@ -104205,13 +105055,21 @@ fn memSize(self: *CodeGen, ty: Type) Memory.Size {...@@ -104205,13 +105055,21 @@ fn memSize(self: *CodeGen, ty: Type) Memory.Size {
104205fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Type {105055fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Type {
104206 const pt = self.pt;105056 const pt = self.pt;
104207 const zcu = pt.zcu;105057 const zcu = pt.zcu;
105058 const ip = &zcu.intern_pool;
104208 var parts: [parts_len]Type = undefined;105059 var parts: [parts_len]Type = undefined;
104209 if (ty.isVector(zcu)) if (std.math.divExact(u32, ty.vectorLen(zcu), parts_len)) |vec_len| return .{105060 switch (ip.indexToKey(ty.toIntern())) {
104210 try pt.vectorType(.{ .len = vec_len, .child = ty.scalarType(zcu).toIntern() }),105061 .vector_type => |vector_type| if (std.math.divExact(u32, vector_type.len, parts_len)) |vec_len| return .{
104211 } ** parts_len else |err| switch (err) {105062 try pt.vectorType(.{ .len = vec_len, .child = vector_type.child }),
104212 error.DivisionByZero => unreachable,105063 } ** parts_len else |err| switch (err) {
104213 error.UnexpectedRemainder => {},105064 error.DivisionByZero => unreachable,
104214 };105065 error.UnexpectedRemainder => {},
105066 },
105067 .tuple_type => |tuple_type| if (tuple_type.types.len == parts_len) {
105068 for (&parts, tuple_type.types.get(ip)) |*part, part_ty| part.* = .fromInterned(part_ty);
105069 return parts;
105070 },
105071 else => {},
105072 }
104215 const classes = std.mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target, .other), .none);105073 const classes = std.mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target, .other), .none);
104216 if (classes.len == parts_len) for (&parts, classes, 0..) |*part, class, part_i| {105074 if (classes.len == parts_len) for (&parts, classes, 0..) |*part, class, part_i| {
104217 part.* = switch (class) {105075 part.* = switch (class) {
...@@ -104896,6 +105754,52 @@ const Temp = struct {...@@ -104896,6 +105754,52 @@ const Temp = struct {
104896 second_temp.* = result_temp;105754 second_temp.* = result_temp;
104897 }105755 }
104898105756
105757 fn withOverflow(temp: *Temp, overflow_temp: *Temp, cg: *CodeGen) InnerError!void {
105758 const temp_index = temp.unwrap(cg).temp;
105759 const temp_tracking = temp_index.tracking(cg);
105760 const overflow_temp_tracking = overflow_temp.unwrap(cg).temp.tracking(cg);
105761 switch (temp_tracking.short) {
105762 .register => |reg| switch (overflow_temp_tracking.short) {
105763 .eflags => |overflow_cc| {
105764 const result_temp_index = cg.next_temp_index;
105765 const result_temp: Temp = .{ .index = result_temp_index.toIndex() };
105766 assert(cg.reuseTemp(result_temp.index, temp.index, temp_tracking));
105767 assert(cg.reuseTemp(result_temp.index, overflow_temp.index, overflow_temp_tracking));
105768 result_temp_index.tracking(cg).* = .init(.{ .register_overflow = .{ .reg = reg, .eflags = overflow_cc } });
105769 cg.temp_type[@intFromEnum(result_temp_index)] = .slice_const_u8;
105770 cg.next_temp_index = @enumFromInt(@intFromEnum(result_temp_index) + 1);
105771 temp.* = result_temp;
105772 overflow_temp.* = result_temp;
105773 return;
105774 },
105775 .register => |overflow_reg| {
105776 const result_temp_index = cg.next_temp_index;
105777 const result_temp: Temp = .{ .index = result_temp_index.toIndex() };
105778 assert(cg.reuseTemp(result_temp.index, temp.index, temp_tracking));
105779 assert(cg.reuseTemp(result_temp.index, overflow_temp.index, overflow_temp_tracking));
105780 result_temp_index.tracking(cg).* = .init(.{ .register_pair = .{ reg, overflow_reg } });
105781 cg.temp_type[@intFromEnum(result_temp_index)] = .slice_const_u8;
105782 cg.next_temp_index = @enumFromInt(@intFromEnum(result_temp_index) + 1);
105783 temp.* = result_temp;
105784 overflow_temp.* = result_temp;
105785 return;
105786 },
105787 else => {},
105788 },
105789 .load_frame => {
105790 const zcu = cg.pt.zcu;
105791 const ip = &zcu.intern_pool;
105792 const field_tys = ip.indexToKey(temp_index.typeOf(cg).toIntern()).tuple_type.types.get(ip);
105793 try temp.write(overflow_temp, .{ .disp = @intCast(Type.fromInterned(field_tys[0]).abiSize(zcu)) }, cg);
105794 try overflow_temp.die(cg);
105795 overflow_temp.* = temp.*;
105796 return;
105797 },
105798 else => {},
105799 }
105800 std.debug.panic("{s}: {} {}\n", .{ @src().fn_name, temp_tracking, overflow_temp_tracking });
105801 }
105802
104899 fn asMask(temp: Temp, info: MaskInfo, cg: *CodeGen) void {105803 fn asMask(temp: Temp, info: MaskInfo, cg: *CodeGen) void {
104900 assert(info.scalar != .none);105804 assert(info.scalar != .none);
104901 const mcv = &temp.unwrap(cg).temp.tracking(cg).short;105805 const mcv = &temp.unwrap(cg).temp.tracking(cg).short;
...@@ -105581,6 +106485,42 @@ const Temp = struct {...@@ -105581,6 +106485,42 @@ const Temp = struct {
105581 },106485 },
105582 .dst_temps = .{ .{ .ref = .src0 }, .unused },106486 .dst_temps = .{ .{ .ref = .src0 }, .unused },
105583 .each = .{ .once = &.{} },106487 .each = .{ .once = &.{} },
106488 }, .{
106489 .required_features = .{ .@"64bit", null, null, null },
106490 .src_constraints = .{ .{ .exact_remainder_signed_int = .{ .of = .xword, .is = .qword } }, .any, .any },
106491 .patterns = &.{
106492 .{ .src = .{ .mut_mem, .none, .none } },
106493 },
106494 .extra_temps = .{
106495 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
106496 .unused,
106497 .unused,
106498 .unused,
106499 .unused,
106500 .unused,
106501 .unused,
106502 .unused,
106503 .unused,
106504 .unused,
106505 .unused,
106506 },
106507 .dst_temps = .{ .{ .ref = .src0 }, .unused },
106508 .clobbers = .{ .eflags = true },
106509 .each = .{ .once = &.{
106510 .{ ._, ._, .mov, .tmp0q, .memad(.src0q, .add_size, -16), ._, ._ },
106511 .{ ._, ._r, .sa, .tmp0q, .ui(63), ._, ._ },
106512 .{ ._, ._, .mov, .memad(.dst0q, .add_size, -8), .tmp0q, ._, ._ },
106513 } },
106514 }, .{
106515 .required_features = .{ .@"64bit", null, null, null },
106516 .src_constraints = .{ .{ .exact_remainder_unsigned_int = .{ .of = .xword, .is = .qword } }, .any, .any },
106517 .patterns = &.{
106518 .{ .src = .{ .mut_mem, .none, .none } },
106519 },
106520 .dst_temps = .{ .{ .ref = .src0 }, .unused },
106521 .each = .{ .once = &.{
106522 .{ ._, ._, .mov, .memad(.dst0q, .add_size, -8), .si(0), ._, ._ },
106523 } },
105584 }, .{106524 }, .{
105585 .required_features = .{ .@"64bit", null, null, null },106525 .required_features = .{ .@"64bit", null, null, null },
105586 .src_constraints = .{ .{ .remainder_signed_int = .{ .of = .xword, .is = .qword } }, .any, .any },106526 .src_constraints = .{ .{ .remainder_signed_int = .{ .of = .xword, .is = .qword } }, .any, .any },
...@@ -110362,15 +111302,18 @@ const Select = struct {...@@ -110362,15 +111302,18 @@ const Select = struct {
110362 return switch (src) {111302 return switch (src) {
110363 .none => temp.tracking(cg).short == .none,111303 .none => temp.tracking(cg).short == .none,
110364 .imm8 => switch (temp.tracking(cg).short) {111304 .imm8 => switch (temp.tracking(cg).short) {
110365 .immediate => |imm| std.math.cast(u8, imm) != null,111305 .immediate => |imm| std.math.cast(u8, imm) != null or
111306 std.math.cast(i8, @as(i64, @bitCast(imm))) != null,
110366 else => false,111307 else => false,
110367 },111308 },
110368 .imm16 => switch (temp.tracking(cg).short) {111309 .imm16 => switch (temp.tracking(cg).short) {
110369 .immediate => |imm| std.math.cast(u16, imm) != null,111310 .immediate => |imm| std.math.cast(u16, imm) != null or
111311 std.math.cast(i16, @as(i64, @bitCast(imm))) != null,
110370 else => false,111312 else => false,
110371 },111313 },
110372 .imm32 => switch (temp.tracking(cg).short) {111314 .imm32 => switch (temp.tracking(cg).short) {
110373 .immediate => |imm| std.math.cast(u32, imm) != null,111315 .immediate => |imm| std.math.cast(u32, imm) != null or
111316 std.math.cast(i32, @as(i64, @bitCast(imm))) != null,
110374 else => false,111317 else => false,
110375 },111318 },
110376 .simm32 => switch (temp.tracking(cg).short) {111319 .simm32 => switch (temp.tracking(cg).short) {
...@@ -110494,6 +111437,8 @@ const Select = struct {...@@ -110494,6 +111437,8 @@ const Select = struct {
110494 const Kind = union(enum) {111437 const Kind = union(enum) {
110495 unused,111438 unused,
110496 any,111439 any,
111440 none,
111441 undef,
110497 cc: Condition,111442 cc: Condition,
110498 ref: Select.Operand.Ref,111443 ref: Select.Operand.Ref,
110499 reg: Register,111444 reg: Register,
...@@ -110580,6 +111525,8 @@ const Select = struct {...@@ -110580,6 +111525,8 @@ const Select = struct {
110580 return switch (spec.kind) {111525 return switch (spec.kind) {
110581 .unused => .{ undefined, false },111526 .unused => .{ undefined, false },
110582 .any => .{ try cg.tempAlloc(spec.type), true },111527 .any => .{ try cg.tempAlloc(spec.type), true },
111528 .none => .{ try cg.tempInit(spec.type, .none), true },
111529 .undef => .{ try cg.tempInit(spec.type, .undef), true },
110583 .cc => |cc| .{ try cg.tempInit(spec.type, .{ .eflags = cc }), true },111530 .cc => |cc| .{ try cg.tempInit(spec.type, .{ .eflags = cc }), true },
110584 .ref => |ref| .{ ref.tempOf(s), false },111531 .ref => |ref| .{ ref.tempOf(s), false },
110585 .reg => |reg| .{ try cg.tempInit(spec.type, .{ .register = reg }), true },111532 .reg => |reg| .{ try cg.tempInit(spec.type, .{ .register = reg }), true },
...@@ -110922,6 +111869,7 @@ const Select = struct {...@@ -110922,6 +111869,7 @@ const Select = struct {
110922 const sub_size: Adjust = .{ .sign = .neg, .lhs = .size, .op = .mul, .rhs = .@"1" };111869 const sub_size: Adjust = .{ .sign = .neg, .lhs = .size, .op = .mul, .rhs = .@"1" };
110923 const sub_src0_size_div_8: Adjust = .{ .sign = .neg, .lhs = .src0_size, .op = .div, .rhs = .@"8" };111870 const sub_src0_size_div_8: Adjust = .{ .sign = .neg, .lhs = .src0_size, .op = .div, .rhs = .@"8" };
110924 const sub_src0_size: Adjust = .{ .sign = .neg, .lhs = .src0_size, .op = .mul, .rhs = .@"1" };111871 const sub_src0_size: Adjust = .{ .sign = .neg, .lhs = .src0_size, .op = .mul, .rhs = .@"1" };
111872 const add_src0_size: Adjust = .{ .sign = .pos, .lhs = .src0_size, .op = .mul, .rhs = .@"1" };
110925 const add_8_src0_size: Adjust = .{ .sign = .pos, .lhs = .src0_size, .op = .mul, .rhs = .@"8" };111873 const add_8_src0_size: Adjust = .{ .sign = .pos, .lhs = .src0_size, .op = .mul, .rhs = .@"8" };
110926 const add_delta_size_div_8: Adjust = .{ .sign = .pos, .lhs = .delta_size, .op = .div, .rhs = .@"8" };111874 const add_delta_size_div_8: Adjust = .{ .sign = .pos, .lhs = .delta_size, .op = .div, .rhs = .@"8" };
110927 const add_delta_elem_size: Adjust = .{ .sign = .pos, .lhs = .delta_elem_size, .op = .mul, .rhs = .@"1" };111875 const add_delta_elem_size: Adjust = .{ .sign = .pos, .lhs = .delta_elem_size, .op = .mul, .rhs = .@"1" };
...@@ -110965,6 +111913,7 @@ const Select = struct {...@@ -110965,6 +111913,7 @@ const Select = struct {
110965 const add_dst0_elem_size: Adjust = .{ .sign = .pos, .lhs = .dst0_elem_size, .op = .mul, .rhs = .@"1" };111913 const add_dst0_elem_size: Adjust = .{ .sign = .pos, .lhs = .dst0_elem_size, .op = .mul, .rhs = .@"1" };
110966 const add_elem_limbs: Adjust = .{ .sign = .pos, .lhs = .elem_limbs, .op = .mul, .rhs = .@"1" };111914 const add_elem_limbs: Adjust = .{ .sign = .pos, .lhs = .elem_limbs, .op = .mul, .rhs = .@"1" };
110967 const add_smin: Adjust = .{ .sign = .pos, .lhs = .smin, .op = .mul, .rhs = .@"1" };111915 const add_smin: Adjust = .{ .sign = .pos, .lhs = .smin, .op = .mul, .rhs = .@"1" };
111916 const sub_smin: Adjust = .{ .sign = .neg, .lhs = .smin, .op = .mul, .rhs = .@"1" };
110968 const add_umax: Adjust = .{ .sign = .pos, .lhs = .umax, .op = .mul, .rhs = .@"1" };111917 const add_umax: Adjust = .{ .sign = .pos, .lhs = .umax, .op = .mul, .rhs = .@"1" };
110969 const repeat: Adjust = .{ .sign = .pos, .lhs = .repeat, .op = .mul, .rhs = .@"1" };111918 const repeat: Adjust = .{ .sign = .pos, .lhs = .repeat, .op = .mul, .rhs = .@"1" };
110970 };111919 };
...@@ -111783,6 +112732,7 @@ fn select(...@@ -111783,6 +112732,7 @@ fn select(
111783 if (std.debug.runtime_safety) {112732 if (std.debug.runtime_safety) {
111784 for (case.src_constraints[src_temps.len..]) |src_constraint| assert(src_constraint == .any);112733 for (case.src_constraints[src_temps.len..]) |src_constraint| assert(src_constraint == .any);
111785 for (case.dst_constraints[dst_temps.len..]) |dst_constraint| assert(dst_constraint == .any);112734 for (case.dst_constraints[dst_temps.len..]) |dst_constraint| assert(dst_constraint == .any);
112735 for (case.dst_temps[dst_temps.len..]) |dst_temp| assert(dst_temp == .unused);
111786 }112736 }
111787 patterns: for (case.patterns) |pattern| {112737 patterns: for (case.patterns) |pattern| {
111788 for (pattern.src[0..src_temps.len], src_temps) |src_pattern, src_temp| if (!src_pattern.matches(src_temp, cg)) continue :patterns;112738 for (pattern.src[0..src_temps.len], src_temps) |src_pattern, src_temp| if (!src_pattern.matches(src_temp, cg)) continue :patterns;
src/arch/x86_64/abi.zig+10-5
...@@ -266,7 +266,8 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont...@@ -266,7 +266,8 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont
266 // separately.".266 // separately.".
267 const ty_size = ty.abiSize(zcu);267 const ty_size = ty.abiSize(zcu);
268 switch (ty.containerLayout(zcu)) {268 switch (ty.containerLayout(zcu)) {
269 .auto, .@"extern" => {},269 .auto => unreachable,
270 .@"extern" => {},
270 .@"packed" => {271 .@"packed" => {
271 assert(ty_size <= 16);272 assert(ty_size <= 16);
272 result[0] = .integer;273 result[0] = .integer;
...@@ -345,7 +346,8 @@ fn classifySystemVStruct(...@@ -345,7 +346,8 @@ fn classifySystemVStruct(
345 );346 );
346 if (zcu.typeToStruct(field_ty)) |field_loaded_struct| {347 if (zcu.typeToStruct(field_ty)) |field_loaded_struct| {
347 switch (field_loaded_struct.layout) {348 switch (field_loaded_struct.layout) {
348 .auto, .@"extern" => {349 .auto => unreachable,
350 .@"extern" => {
349 byte_offset = classifySystemVStruct(result, byte_offset, field_loaded_struct, zcu, target);351 byte_offset = classifySystemVStruct(result, byte_offset, field_loaded_struct, zcu, target);
350 continue;352 continue;
351 },353 },
...@@ -353,7 +355,8 @@ fn classifySystemVStruct(...@@ -353,7 +355,8 @@ fn classifySystemVStruct(
353 }355 }
354 } else if (zcu.typeToUnion(field_ty)) |field_loaded_union| {356 } else if (zcu.typeToUnion(field_ty)) |field_loaded_union| {
355 switch (field_loaded_union.flagsUnordered(ip).layout) {357 switch (field_loaded_union.flagsUnordered(ip).layout) {
356 .auto, .@"extern" => {358 .auto => unreachable,
359 .@"extern" => {
357 byte_offset = classifySystemVUnion(result, byte_offset, field_loaded_union, zcu, target);360 byte_offset = classifySystemVUnion(result, byte_offset, field_loaded_union, zcu, target);
358 continue;361 continue;
359 },362 },
...@@ -386,7 +389,8 @@ fn classifySystemVUnion(...@@ -386,7 +389,8 @@ fn classifySystemVUnion(
386 const field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]);389 const field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]);
387 if (zcu.typeToStruct(field_ty)) |field_loaded_struct| {390 if (zcu.typeToStruct(field_ty)) |field_loaded_struct| {
388 switch (field_loaded_struct.layout) {391 switch (field_loaded_struct.layout) {
389 .auto, .@"extern" => {392 .auto => unreachable,
393 .@"extern" => {
390 _ = classifySystemVStruct(result, starting_byte_offset, field_loaded_struct, zcu, target);394 _ = classifySystemVStruct(result, starting_byte_offset, field_loaded_struct, zcu, target);
391 continue;395 continue;
392 },396 },
...@@ -394,7 +398,8 @@ fn classifySystemVUnion(...@@ -394,7 +398,8 @@ fn classifySystemVUnion(
394 }398 }
395 } else if (zcu.typeToUnion(field_ty)) |field_loaded_union| {399 } else if (zcu.typeToUnion(field_ty)) |field_loaded_union| {
396 switch (field_loaded_union.flagsUnordered(ip).layout) {400 switch (field_loaded_union.flagsUnordered(ip).layout) {
397 .auto, .@"extern" => {401 .auto => unreachable,
402 .@"extern" => {
398 _ = classifySystemVUnion(result, starting_byte_offset, field_loaded_union, zcu, target);403 _ = classifySystemVUnion(result, starting_byte_offset, field_loaded_union, zcu, target);
399 continue;404 continue;
400 },405 },
test/behavior/x86_64/binary.zig+24-4
...@@ -5262,6 +5262,17 @@ test addUnsafe {...@@ -5262,6 +5262,17 @@ test addUnsafe {
5262 try test_add_unsafe.testFloatVectors();5262 try test_add_unsafe.testFloatVectors();
5263}5263}
52645264
5265inline fn addSafe(comptime Type: type, lhs: Type, rhs: Type) AddOneBit(Type) {
5266 @setRuntimeSafety(true);
5267 return @as(AddOneBit(Type), lhs) + rhs;
5268}
5269test addSafe {
5270 const test_add_safe = binary(addSafe, .{});
5271 try test_add_safe.testInts();
5272 try test_add_safe.testFloats();
5273 try test_add_safe.testFloatVectors();
5274}
5275
5265inline fn addWrap(comptime Type: type, lhs: Type, rhs: Type) Type {5276inline fn addWrap(comptime Type: type, lhs: Type, rhs: Type) Type {
5266 return lhs +% rhs;5277 return lhs +% rhs;
5267}5278}
...@@ -5416,6 +5427,14 @@ test min {...@@ -5416,6 +5427,14 @@ test min {
5416 try test_min.testFloatVectors();5427 try test_min.testFloatVectors();
5417}5428}
54185429
5430inline fn addWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, u1 } {
5431 return @addWithOverflow(lhs, rhs);
5432}
5433test addWithOverflow {
5434 const test_add_with_overflow = binary(addWithOverflow, .{});
5435 try test_add_with_overflow.testInts();
5436}
5437
5419inline fn equal(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs == rhs) {5438inline fn equal(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs == rhs) {
5420 return lhs == rhs;5439 return lhs == rhs;
5421}5440}
...@@ -5519,15 +5538,16 @@ test shl {...@@ -5519,15 +5538,16 @@ test shl {
5519 try test_shl.testInts();5538 try test_shl.testInts();
5520}5539}
55215540
5522inline fn shlExact(comptime Type: type, lhs: Type, rhs: Type) Type {5541inline fn shlExactUnsafe(comptime Type: type, lhs: Type, rhs: Type) Type {
5542 @setRuntimeSafety(false);
5523 const bit_cast_rhs: @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(Type) } }) = @bitCast(rhs);5543 const bit_cast_rhs: @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(Type) } }) = @bitCast(rhs);
5524 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);5544 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);
5525 const final_rhs = if (comptime cast(Log2Int(Type), @bitSizeOf(Type))) |bits| truncate_rhs % bits else truncate_rhs;5545 const final_rhs = if (comptime cast(Log2Int(Type), @bitSizeOf(Type))) |bits| truncate_rhs % bits else truncate_rhs;
5526 return @shlExact(lhs << final_rhs >> final_rhs, final_rhs);5546 return @shlExact(lhs << final_rhs >> final_rhs, final_rhs);
5527}5547}
5528test shlExact {5548test shlExactUnsafe {
5529 const test_shl_exact = binary(shlExact, .{});5549 const test_shl_exact_unsafe = binary(shlExactUnsafe, .{});
5530 try test_shl_exact.testInts();5550 try test_shl_exact_unsafe.testInts();
5531}5551}
55325552
5533inline fn bitXor(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs ^ rhs) {5553inline fn bitXor(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs ^ rhs) {
test/behavior/x86_64/math.zig+3
...@@ -153,6 +153,9 @@ pub noinline fn checkExpected(expected: anytype, actual: @TypeOf(expected), comp...@@ -153,6 +153,9 @@ pub noinline fn checkExpected(expected: anytype, actual: @TypeOf(expected), comp
153 );153 );
154 },154 },
155 },155 },
156 .@"struct" => |@"struct"| inline for (@"struct".fields) |field| {
157 try checkExpected(@field(expected, field.name), @field(actual, field.name), compare);
158 } else return,
156 };159 };
157 if (switch (@typeInfo(Expected)) {160 if (switch (@typeInfo(Expected)) {
158 else => unexpected,161 else => unexpected,