authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-03-12 22:09:46-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-03-21 21:51:09-04:00
log2361468e23b18a35578deddd6c4641114ed02ebf
treee9d424ab4c8a09fad04228dfbd5e61dbe32e644b
parentaff2be01c95516489ba8355f4de6218c92608b8e

x86_64: rewrite scalar shifts


5 files changed, 1071 insertions(+), 64 deletions(-)

src/arch/x86_64/CodeGen.zig+1000-39
......@@ -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(13_800);
2421 @setEvalBranchQuota(13_900);
24222422 const pt = cg.pt;
24232423 const zcu = pt.zcu;
24242424 const ip = &zcu.intern_pool;
......@@ -2454,9 +2454,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
24542454 try cg.inst_tracking.ensureUnusedCapacity(cg.gpa, 1);
24552455 switch (air_tags[@intFromEnum(inst)]) {
24562456 // zig fmt: off
2457 .shr, .shr_exact => try cg.airShlShrBinOp(inst),
2458 .shl, .shl_exact => try cg.airShlShrBinOp(inst),
2459
24602457 .add_sat => try cg.airAddSat(inst),
24612458 .sub_sat => try cg.airSubSat(inst),
24622459 .mul_sat => try cg.airMulSat(inst),
......@@ -28416,6 +28413,947 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2841628413 };
2841728414 try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
2841828415 },
28416 .shr, .shr_exact => |air_tag| if (use_old) try cg.airShlShrBinOp(inst) else fallback: {
28417 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
28418 if (cg.typeOf(bin_op.lhs).isVector(zcu)) break :fallback try cg.airShlShrBinOp(inst);
28419 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
28420 var res: [1]Temp = undefined;
28421 cg.select(&res, &.{cg.typeOf(bin_op.lhs)}, &ops, comptime &.{ .{
28422 .src_constraints = .{ .{ .signed_int = .byte }, .{ .unsigned_int = .byte }, .any },
28423 .patterns = &.{
28424 .{ .src = .{ .mut_mem, .imm8, .none } },
28425 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28426 .{ .src = .{ .mut_mem, .{ .to_reg = .cl }, .none } },
28427 .{ .src = .{ .to_mut_gpr, .{ .to_reg = .cl }, .none } },
28428 },
28429 .dst_temps = .{ .{ .ref = .src0 }, .unused },
28430 .clobbers = .{ .eflags = true },
28431 .each = .{ .once = &.{
28432 .{ ._, ._r, .sa, .dst0b, .src1b, ._, ._ },
28433 } },
28434 }, .{
28435 .src_constraints = .{ .{ .unsigned_int = .byte }, .{ .unsigned_int = .byte }, .any },
28436 .patterns = &.{
28437 .{ .src = .{ .mut_mem, .imm8, .none } },
28438 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28439 .{ .src = .{ .mut_mem, .{ .to_reg = .cl }, .none } },
28440 .{ .src = .{ .to_mut_gpr, .{ .to_reg = .cl }, .none } },
28441 },
28442 .dst_temps = .{ .{ .ref = .src0 }, .unused },
28443 .clobbers = .{ .eflags = true },
28444 .each = .{ .once = &.{
28445 .{ ._, ._r, .sh, .dst0b, .src1b, ._, ._ },
28446 } },
28447 }, .{
28448 .src_constraints = .{ .{ .signed_int = .word }, .{ .exact_unsigned_int = 4 }, .any },
28449 .patterns = &.{
28450 .{ .src = .{ .mut_mem, .imm8, .none } },
28451 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28452 .{ .src = .{ .mut_mem, .{ .to_reg = .cl }, .none } },
28453 .{ .src = .{ .to_mut_gpr, .{ .to_reg = .cl }, .none } },
28454 },
28455 .dst_temps = .{ .{ .ref = .src0 }, .unused },
28456 .clobbers = .{ .eflags = true },
28457 .each = .{ .once = &.{
28458 .{ ._, ._r, .sa, .dst0w, .src1b, ._, ._ },
28459 } },
28460 }, .{
28461 .src_constraints = .{ .{ .unsigned_int = .word }, .{ .exact_unsigned_int = 4 }, .any },
28462 .patterns = &.{
28463 .{ .src = .{ .mut_mem, .imm8, .none } },
28464 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28465 .{ .src = .{ .mut_mem, .{ .to_reg = .cl }, .none } },
28466 .{ .src = .{ .to_mut_gpr, .{ .to_reg = .cl }, .none } },
28467 },
28468 .dst_temps = .{ .{ .ref = .src0 }, .unused },
28469 .clobbers = .{ .eflags = true },
28470 .each = .{ .once = &.{
28471 .{ ._, ._r, .sh, .dst0w, .src1b, ._, ._ },
28472 } },
28473 }, .{
28474 .src_constraints = .{ .{ .signed_int = .dword }, .{ .exact_unsigned_int = 5 }, .any },
28475 .patterns = &.{
28476 .{ .src = .{ .mut_mem, .imm8, .none } },
28477 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28478 },
28479 .dst_temps = .{ .{ .ref = .src0 }, .unused },
28480 .clobbers = .{ .eflags = true },
28481 .each = .{ .once = &.{
28482 .{ ._, ._r, .sa, .dst0d, .src1b, ._, ._ },
28483 } },
28484 }, .{
28485 .src_constraints = .{ .{ .unsigned_int = .dword }, .{ .exact_unsigned_int = 5 }, .any },
28486 .patterns = &.{
28487 .{ .src = .{ .mut_mem, .imm8, .none } },
28488 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28489 },
28490 .dst_temps = .{ .{ .ref = .src0 }, .unused },
28491 .clobbers = .{ .eflags = true },
28492 .each = .{ .once = &.{
28493 .{ ._, ._r, .sh, .dst0d, .src1b, ._, ._ },
28494 } },
28495 }, .{
28496 .required_features = .{ .bmi2, null, null, null },
28497 .src_constraints = .{ .{ .signed_int = .dword }, .{ .exact_unsigned_int = 5 }, .any },
28498 .patterns = &.{
28499 .{ .src = .{ .mem, .to_gpr, .none } },
28500 .{ .src = .{ .to_gpr, .to_gpr, .none } },
28501 },
28502 .dst_temps = .{ .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } }, .unused },
28503 .each = .{ .once = &.{
28504 .{ ._, ._rx, .sa, .dst0d, .src0d, .src1d, ._ },
28505 } },
28506 }, .{
28507 .required_features = .{ .bmi2, null, null, null },
28508 .src_constraints = .{ .{ .unsigned_int = .dword }, .{ .exact_unsigned_int = 5 }, .any },
28509 .patterns = &.{
28510 .{ .src = .{ .mem, .to_gpr, .none } },
28511 .{ .src = .{ .to_gpr, .to_gpr, .none } },
28512 },
28513 .dst_temps = .{ .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } }, .unused },
28514 .each = .{ .once = &.{
28515 .{ ._, ._rx, .sh, .dst0d, .src0d, .src1d, ._ },
28516 } },
28517 }, .{
28518 .src_constraints = .{ .{ .signed_int = .dword }, .{ .exact_unsigned_int = 5 }, .any },
28519 .patterns = &.{
28520 .{ .src = .{ .mut_mem, .{ .to_reg = .cl }, .none } },
28521 .{ .src = .{ .to_mut_gpr, .{ .to_reg = .cl }, .none } },
28522 },
28523 .dst_temps = .{ .{ .ref = .src0 }, .unused },
28524 .clobbers = .{ .eflags = true },
28525 .each = .{ .once = &.{
28526 .{ ._, ._r, .sa, .dst0d, .src1b, ._, ._ },
28527 } },
28528 }, .{
28529 .src_constraints = .{ .{ .unsigned_int = .dword }, .{ .exact_unsigned_int = 5 }, .any },
28530 .patterns = &.{
28531 .{ .src = .{ .mut_mem, .{ .to_reg = .cl }, .none } },
28532 .{ .src = .{ .to_mut_gpr, .{ .to_reg = .cl }, .none } },
28533 },
28534 .dst_temps = .{ .{ .ref = .src0 }, .unused },
28535 .clobbers = .{ .eflags = true },
28536 .each = .{ .once = &.{
28537 .{ ._, ._r, .sh, .dst0d, .src1b, ._, ._ },
28538 } },
28539 }, .{
28540 .required_features = .{ .@"64bit", null, null, null },
28541 .src_constraints = .{ .{ .signed_int = .qword }, .{ .exact_unsigned_int = 6 }, .any },
28542 .patterns = &.{
28543 .{ .src = .{ .mut_mem, .imm8, .none } },
28544 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28545 },
28546 .dst_temps = .{ .{ .ref = .src0 }, .unused },
28547 .clobbers = .{ .eflags = true },
28548 .each = .{ .once = &.{
28549 .{ ._, ._r, .sa, .dst0q, .src1b, ._, ._ },
28550 } },
28551 }, .{
28552 .required_features = .{ .@"64bit", null, null, null },
28553 .src_constraints = .{ .{ .unsigned_int = .qword }, .{ .exact_unsigned_int = 6 }, .any },
28554 .patterns = &.{
28555 .{ .src = .{ .mut_mem, .imm8, .none } },
28556 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28557 },
28558 .dst_temps = .{ .{ .ref = .src0 }, .unused },
28559 .clobbers = .{ .eflags = true },
28560 .each = .{ .once = &.{
28561 .{ ._, ._r, .sh, .dst0q, .src1b, ._, ._ },
28562 } },
28563 }, .{
28564 .required_features = .{ .@"64bit", .bmi2, null, null },
28565 .src_constraints = .{ .{ .signed_int = .qword }, .{ .exact_unsigned_int = 6 }, .any },
28566 .patterns = &.{
28567 .{ .src = .{ .mem, .to_gpr, .none } },
28568 .{ .src = .{ .to_gpr, .to_gpr, .none } },
28569 },
28570 .dst_temps = .{ .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } }, .unused },
28571 .each = .{ .once = &.{
28572 .{ ._, ._rx, .sa, .dst0q, .src0q, .src1q, ._ },
28573 } },
28574 }, .{
28575 .required_features = .{ .@"64bit", .bmi2, null, null },
28576 .src_constraints = .{ .{ .unsigned_int = .qword }, .{ .exact_unsigned_int = 6 }, .any },
28577 .patterns = &.{
28578 .{ .src = .{ .mem, .to_gpr, .none } },
28579 .{ .src = .{ .to_gpr, .to_gpr, .none } },
28580 },
28581 .dst_temps = .{ .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } }, .unused },
28582 .each = .{ .once = &.{
28583 .{ ._, ._rx, .sh, .dst0q, .src0q, .src1q, ._ },
28584 } },
28585 }, .{
28586 .required_features = .{ .@"64bit", null, null, null },
28587 .src_constraints = .{ .{ .signed_int = .qword }, .{ .exact_unsigned_int = 6 }, .any },
28588 .patterns = &.{
28589 .{ .src = .{ .mut_mem, .{ .to_reg = .cl }, .none } },
28590 .{ .src = .{ .to_mut_gpr, .{ .to_reg = .cl }, .none } },
28591 },
28592 .dst_temps = .{ .{ .ref = .src0 }, .unused },
28593 .clobbers = .{ .eflags = true },
28594 .each = .{ .once = &.{
28595 .{ ._, ._r, .sa, .dst0q, .src1b, ._, ._ },
28596 } },
28597 }, .{
28598 .required_features = .{ .@"64bit", null, null, null },
28599 .src_constraints = .{ .{ .unsigned_int = .qword }, .{ .exact_unsigned_int = 6 }, .any },
28600 .patterns = &.{
28601 .{ .src = .{ .mut_mem, .{ .to_reg = .cl }, .none } },
28602 .{ .src = .{ .to_mut_gpr, .{ .to_reg = .cl }, .none } },
28603 },
28604 .dst_temps = .{ .{ .ref = .src0 }, .unused },
28605 .clobbers = .{ .eflags = true },
28606 .each = .{ .once = &.{
28607 .{ ._, ._r, .sh, .dst0q, .src1b, ._, ._ },
28608 } },
28609 }, .{
28610 .required_features = .{ .@"64bit", .slow_incdec, null, null },
28611 .src_constraints = .{
28612 .{ .remainder_signed_int = .{ .of = .qword, .is = .qword } },
28613 .{ .unsigned_int = .byte },
28614 .any,
28615 },
28616 .patterns = &.{
28617 .{ .src = .{ .to_mem, .{ .to_reg = .cl }, .none } },
28618 },
28619 .extra_temps = .{
28620 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
28621 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28622 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
28623 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28624 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28625 .unused,
28626 .unused,
28627 .unused,
28628 .unused,
28629 .unused,
28630 .unused,
28631 },
28632 .dst_temps = .{ .mem, .unused },
28633 .clobbers = .{ .eflags = true },
28634 .each = .{ .once = &.{
28635 .{ ._, ._, .movzx, .tmp0d, .src1b, ._, ._ },
28636 .{ ._, ._r, .sh, .tmp0d, .ui(6), ._, ._ },
28637 .{ ._, ._, .lea, .tmp1p, .leasia(.none, .@"8", .tmp0, .sub_src0_size), ._, ._ },
28638 .{ ._, ._, .not, .tmp0p, ._, ._, ._ },
28639 .{ ._, ._, .lea, .tmp2p, .memsia(.dst0, .@"8", .tmp0, .add_size), ._, ._ },
28640 .{ ._, ._, .mov, .tmp3q, .memia(.src0q, .tmp1, .add_size), ._, ._ },
28641 .{ ._, ._mp, .j, .@"1f", ._, ._, ._ },
28642 .{ .@"0:", ._, .mov, .tmp4q, .memia(.src0q, .tmp1, .add_size), ._, ._ },
28643 .{ ._, ._rd, .sh, .tmp3q, .tmp4q, .src1b, ._ },
28644 .{ ._, ._, .mov, .leai(.tmp2q, .tmp1), .tmp3q, ._, ._ },
28645 .{ ._, ._, .mov, .tmp3q, .tmp4q, ._, ._ },
28646 .{ .@"1:", ._, .add, .tmp1p, .si(8), ._, ._ },
28647 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
28648 .{ ._, ._r, .sa, .tmp3q, .src1b, ._, ._ },
28649 .{ .@"0:", ._, .mov, .memsia(.dst0q, .@"8", .tmp0, .add_size), .tmp3q, ._, ._ },
28650 .{ ._, ._r, .sa, .tmp3q, .ui(63), ._, ._ },
28651 .{ ._, ._, .add, .tmp0p, .si(1), ._, ._ },
28652 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
28653 } },
28654 }, .{
28655 .required_features = .{ .@"64bit", null, null, null },
28656 .src_constraints = .{
28657 .{ .remainder_signed_int = .{ .of = .qword, .is = .qword } },
28658 .{ .unsigned_int = .byte },
28659 .any,
28660 },
28661 .patterns = &.{
28662 .{ .src = .{ .to_mem, .{ .to_reg = .cl }, .none } },
28663 },
28664 .extra_temps = .{
28665 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
28666 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28667 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
28668 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28669 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28670 .unused,
28671 .unused,
28672 .unused,
28673 .unused,
28674 .unused,
28675 .unused,
28676 },
28677 .dst_temps = .{ .mem, .unused },
28678 .clobbers = .{ .eflags = true },
28679 .each = .{ .once = &.{
28680 .{ ._, ._, .movzx, .tmp0d, .src1b, ._, ._ },
28681 .{ ._, ._r, .sh, .tmp0d, .ui(6), ._, ._ },
28682 .{ ._, ._, .lea, .tmp1p, .leasia(.none, .@"8", .tmp0, .sub_src0_size), ._, ._ },
28683 .{ ._, ._, .not, .tmp0p, ._, ._, ._ },
28684 .{ ._, ._, .lea, .tmp2p, .memsia(.dst0, .@"8", .tmp0, .add_size), ._, ._ },
28685 .{ ._, ._, .mov, .tmp3q, .memia(.src0q, .tmp1, .add_size), ._, ._ },
28686 .{ ._, ._mp, .j, .@"1f", ._, ._, ._ },
28687 .{ .@"0:", ._, .mov, .tmp4q, .memia(.src0q, .tmp1, .add_size), ._, ._ },
28688 .{ ._, ._rd, .sh, .tmp3q, .tmp4q, .src1b, ._ },
28689 .{ ._, ._, .mov, .leai(.tmp2q, .tmp1), .tmp3q, ._, ._ },
28690 .{ ._, ._, .mov, .tmp3q, .tmp4q, ._, ._ },
28691 .{ .@"1:", ._, .add, .tmp1p, .si(8), ._, ._ },
28692 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
28693 .{ ._, ._r, .sa, .tmp3q, .src1b, ._, ._ },
28694 .{ .@"0:", ._, .mov, .memsia(.dst0q, .@"8", .tmp0, .add_size), .tmp3q, ._, ._ },
28695 .{ ._, ._r, .sa, .tmp3q, .ui(63), ._, ._ },
28696 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
28697 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
28698 } },
28699 }, .{
28700 .required_features = .{ .@"64bit", .slow_incdec, null, null },
28701 .src_constraints = .{
28702 .{ .remainder_unsigned_int = .{ .of = .qword, .is = .qword } },
28703 .{ .unsigned_int = .byte },
28704 .any,
28705 },
28706 .patterns = &.{
28707 .{ .src = .{ .to_mem, .{ .to_reg = .cl }, .none } },
28708 },
28709 .extra_temps = .{
28710 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
28711 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28712 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
28713 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28714 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28715 .unused,
28716 .unused,
28717 .unused,
28718 .unused,
28719 .unused,
28720 .unused,
28721 },
28722 .dst_temps = .{ .mem, .unused },
28723 .clobbers = .{ .eflags = true },
28724 .each = .{ .once = &.{
28725 .{ ._, ._, .movzx, .tmp0d, .src1b, ._, ._ },
28726 .{ ._, ._r, .sh, .tmp0d, .ui(6), ._, ._ },
28727 .{ ._, ._, .lea, .tmp1p, .leasia(.none, .@"8", .tmp0, .sub_src0_size), ._, ._ },
28728 .{ ._, ._, .not, .tmp0p, ._, ._, ._ },
28729 .{ ._, ._, .lea, .tmp2p, .memsia(.dst0, .@"8", .tmp0, .add_size), ._, ._ },
28730 .{ ._, ._, .mov, .tmp3q, .memia(.src0q, .tmp1, .add_size), ._, ._ },
28731 .{ ._, ._mp, .j, .@"1f", ._, ._, ._ },
28732 .{ .@"0:", ._, .mov, .tmp4q, .memia(.src0q, .tmp1, .add_size), ._, ._ },
28733 .{ ._, ._rd, .sh, .tmp3q, .tmp4q, .src1b, ._ },
28734 .{ ._, ._, .mov, .leai(.tmp2q, .tmp1), .tmp3q, ._, ._ },
28735 .{ ._, ._, .mov, .tmp3q, .tmp4q, ._, ._ },
28736 .{ .@"1:", ._, .add, .tmp1p, .si(8), ._, ._ },
28737 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
28738 .{ ._, ._r, .sh, .tmp3q, .src1b, ._, ._ },
28739 .{ .@"0:", ._, .mov, .memsia(.dst0q, .@"8", .tmp0, .add_size), .tmp3q, ._, ._ },
28740 .{ ._, ._, .xor, .tmp3d, .tmp3d, ._, ._ },
28741 .{ ._, ._, .add, .tmp0p, .si(1), ._, ._ },
28742 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
28743 } },
28744 }, .{
28745 .required_features = .{ .@"64bit", null, null, null },
28746 .src_constraints = .{
28747 .{ .remainder_unsigned_int = .{ .of = .qword, .is = .qword } },
28748 .{ .unsigned_int = .byte },
28749 .any,
28750 },
28751 .patterns = &.{
28752 .{ .src = .{ .to_mem, .{ .to_reg = .cl }, .none } },
28753 },
28754 .extra_temps = .{
28755 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
28756 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28757 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
28758 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28759 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28760 .unused,
28761 .unused,
28762 .unused,
28763 .unused,
28764 .unused,
28765 .unused,
28766 },
28767 .dst_temps = .{ .mem, .unused },
28768 .clobbers = .{ .eflags = true },
28769 .each = .{ .once = &.{
28770 .{ ._, ._, .movzx, .tmp0d, .src1b, ._, ._ },
28771 .{ ._, ._r, .sh, .tmp0d, .ui(6), ._, ._ },
28772 .{ ._, ._, .lea, .tmp1p, .leasia(.none, .@"8", .tmp0, .sub_src0_size), ._, ._ },
28773 .{ ._, ._, .not, .tmp0p, ._, ._, ._ },
28774 .{ ._, ._, .lea, .tmp2p, .memsia(.dst0, .@"8", .tmp0, .add_size), ._, ._ },
28775 .{ ._, ._, .mov, .tmp3q, .memia(.src0q, .tmp1, .add_size), ._, ._ },
28776 .{ ._, ._mp, .j, .@"1f", ._, ._, ._ },
28777 .{ .@"0:", ._, .mov, .tmp4q, .memia(.src0q, .tmp1, .add_size), ._, ._ },
28778 .{ ._, ._rd, .sh, .tmp3q, .tmp4q, .src1b, ._ },
28779 .{ ._, ._, .mov, .leai(.tmp2q, .tmp1), .tmp3q, ._, ._ },
28780 .{ ._, ._, .mov, .tmp3q, .tmp4q, ._, ._ },
28781 .{ .@"1:", ._, .add, .tmp1p, .si(8), ._, ._ },
28782 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
28783 .{ ._, ._r, .sh, .tmp3q, .src1b, ._, ._ },
28784 .{ .@"0:", ._, .mov, .memsia(.dst0q, .@"8", .tmp0, .add_size), .tmp3q, ._, ._ },
28785 .{ ._, ._, .xor, .tmp3d, .tmp3d, ._, ._ },
28786 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
28787 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
28788 } },
28789 }, .{
28790 .required_features = .{ .@"64bit", .slow_incdec, null, null },
28791 .src_constraints = .{
28792 .{ .remainder_signed_int = .{ .of = .qword, .is = .qword } },
28793 .{ .unsigned_int = .word },
28794 .any,
28795 },
28796 .patterns = &.{
28797 .{ .src = .{ .to_mem, .{ .to_reg = .cx }, .none } },
28798 },
28799 .extra_temps = .{
28800 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
28801 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28802 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
28803 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28804 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28805 .unused,
28806 .unused,
28807 .unused,
28808 .unused,
28809 .unused,
28810 .unused,
28811 },
28812 .dst_temps = .{ .mem, .unused },
28813 .clobbers = .{ .eflags = true },
28814 .each = .{ .once = &.{
28815 .{ ._, ._, .movzx, .tmp0d, .src1w, ._, ._ },
28816 .{ ._, ._r, .sh, .tmp0d, .ui(6), ._, ._ },
28817 .{ ._, ._, .lea, .tmp1p, .leasia(.none, .@"8", .tmp0, .sub_src0_size), ._, ._ },
28818 .{ ._, ._, .not, .tmp0p, ._, ._, ._ },
28819 .{ ._, ._, .lea, .tmp2p, .memsia(.dst0, .@"8", .tmp0, .add_size), ._, ._ },
28820 .{ ._, ._, .mov, .tmp3q, .memia(.src0q, .tmp1, .add_size), ._, ._ },
28821 .{ ._, ._mp, .j, .@"1f", ._, ._, ._ },
28822 .{ .@"0:", ._, .mov, .tmp4q, .memia(.src0q, .tmp1, .add_size), ._, ._ },
28823 .{ ._, ._rd, .sh, .tmp3q, .tmp4q, .src1b, ._ },
28824 .{ ._, ._, .mov, .leai(.tmp2q, .tmp1), .tmp3q, ._, ._ },
28825 .{ ._, ._, .mov, .tmp3q, .tmp4q, ._, ._ },
28826 .{ .@"1:", ._, .add, .tmp1p, .si(8), ._, ._ },
28827 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
28828 .{ ._, ._r, .sa, .tmp3q, .src1b, ._, ._ },
28829 .{ .@"0:", ._, .mov, .memsia(.dst0q, .@"8", .tmp0, .add_size), .tmp3q, ._, ._ },
28830 .{ ._, ._r, .sa, .tmp3q, .ui(63), ._, ._ },
28831 .{ ._, ._, .add, .tmp0p, .si(1), ._, ._ },
28832 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
28833 } },
28834 }, .{
28835 .required_features = .{ .@"64bit", null, null, null },
28836 .src_constraints = .{
28837 .{ .remainder_signed_int = .{ .of = .qword, .is = .qword } },
28838 .{ .unsigned_int = .word },
28839 .any,
28840 },
28841 .patterns = &.{
28842 .{ .src = .{ .to_mem, .{ .to_reg = .cx }, .none } },
28843 },
28844 .extra_temps = .{
28845 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
28846 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28847 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
28848 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28849 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28850 .unused,
28851 .unused,
28852 .unused,
28853 .unused,
28854 .unused,
28855 .unused,
28856 },
28857 .dst_temps = .{ .mem, .unused },
28858 .clobbers = .{ .eflags = true },
28859 .each = .{ .once = &.{
28860 .{ ._, ._, .movzx, .tmp0d, .src1w, ._, ._ },
28861 .{ ._, ._r, .sh, .tmp0d, .ui(6), ._, ._ },
28862 .{ ._, ._, .lea, .tmp1p, .leasia(.none, .@"8", .tmp0, .sub_src0_size), ._, ._ },
28863 .{ ._, ._, .not, .tmp0p, ._, ._, ._ },
28864 .{ ._, ._, .lea, .tmp2p, .memsia(.dst0, .@"8", .tmp0, .add_size), ._, ._ },
28865 .{ ._, ._, .mov, .tmp3q, .memia(.src0q, .tmp1, .add_size), ._, ._ },
28866 .{ ._, ._mp, .j, .@"1f", ._, ._, ._ },
28867 .{ .@"0:", ._, .mov, .tmp4q, .memia(.src0q, .tmp1, .add_size), ._, ._ },
28868 .{ ._, ._rd, .sh, .tmp3q, .tmp4q, .src1b, ._ },
28869 .{ ._, ._, .mov, .leai(.tmp2q, .tmp1), .tmp3q, ._, ._ },
28870 .{ ._, ._, .mov, .tmp3q, .tmp4q, ._, ._ },
28871 .{ .@"1:", ._, .add, .tmp1p, .si(8), ._, ._ },
28872 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
28873 .{ ._, ._r, .sa, .tmp3q, .src1b, ._, ._ },
28874 .{ .@"0:", ._, .mov, .memsia(.dst0q, .@"8", .tmp0, .add_size), .tmp3q, ._, ._ },
28875 .{ ._, ._r, .sa, .tmp3q, .ui(63), ._, ._ },
28876 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
28877 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
28878 } },
28879 }, .{
28880 .required_features = .{ .@"64bit", .slow_incdec, null, null },
28881 .src_constraints = .{
28882 .{ .remainder_unsigned_int = .{ .of = .qword, .is = .qword } },
28883 .{ .unsigned_int = .word },
28884 .any,
28885 },
28886 .patterns = &.{
28887 .{ .src = .{ .to_mem, .{ .to_reg = .cx }, .none } },
28888 },
28889 .extra_temps = .{
28890 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
28891 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28892 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
28893 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28894 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28895 .unused,
28896 .unused,
28897 .unused,
28898 .unused,
28899 .unused,
28900 .unused,
28901 },
28902 .dst_temps = .{ .mem, .unused },
28903 .clobbers = .{ .eflags = true },
28904 .each = .{ .once = &.{
28905 .{ ._, ._, .movzx, .tmp0d, .src1w, ._, ._ },
28906 .{ ._, ._r, .sh, .tmp0d, .ui(6), ._, ._ },
28907 .{ ._, ._, .lea, .tmp1p, .leasia(.none, .@"8", .tmp0, .sub_src0_size), ._, ._ },
28908 .{ ._, ._, .not, .tmp0p, ._, ._, ._ },
28909 .{ ._, ._, .lea, .tmp2p, .memsia(.dst0, .@"8", .tmp0, .add_size), ._, ._ },
28910 .{ ._, ._, .mov, .tmp3q, .memia(.src0q, .tmp1, .add_size), ._, ._ },
28911 .{ ._, ._mp, .j, .@"1f", ._, ._, ._ },
28912 .{ .@"0:", ._, .mov, .tmp4q, .memia(.src0q, .tmp1, .add_size), ._, ._ },
28913 .{ ._, ._rd, .sh, .tmp3q, .tmp4q, .src1b, ._ },
28914 .{ ._, ._, .mov, .leai(.tmp2q, .tmp1), .tmp3q, ._, ._ },
28915 .{ ._, ._, .mov, .tmp3q, .tmp4q, ._, ._ },
28916 .{ .@"1:", ._, .add, .tmp1p, .si(8), ._, ._ },
28917 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
28918 .{ ._, ._r, .sh, .tmp3q, .src1b, ._, ._ },
28919 .{ .@"0:", ._, .mov, .memsia(.dst0q, .@"8", .tmp0, .add_size), .tmp3q, ._, ._ },
28920 .{ ._, ._, .xor, .tmp3d, .tmp3d, ._, ._ },
28921 .{ ._, ._, .add, .tmp0p, .si(1), ._, ._ },
28922 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
28923 } },
28924 }, .{
28925 .required_features = .{ .@"64bit", null, null, null },
28926 .src_constraints = .{
28927 .{ .remainder_unsigned_int = .{ .of = .qword, .is = .qword } },
28928 .{ .unsigned_int = .word },
28929 .any,
28930 },
28931 .patterns = &.{
28932 .{ .src = .{ .to_mem, .{ .to_reg = .cx }, .none } },
28933 },
28934 .extra_temps = .{
28935 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
28936 .{ .type = .isize, .kind = .{ .rc = .general_purpose } },
28937 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
28938 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28939 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
28940 .unused,
28941 .unused,
28942 .unused,
28943 .unused,
28944 .unused,
28945 .unused,
28946 },
28947 .dst_temps = .{ .mem, .unused },
28948 .clobbers = .{ .eflags = true },
28949 .each = .{ .once = &.{
28950 .{ ._, ._, .movzx, .tmp0d, .src1w, ._, ._ },
28951 .{ ._, ._r, .sh, .tmp0d, .ui(6), ._, ._ },
28952 .{ ._, ._, .lea, .tmp1p, .leasia(.none, .@"8", .tmp0, .sub_src0_size), ._, ._ },
28953 .{ ._, ._, .not, .tmp0p, ._, ._, ._ },
28954 .{ ._, ._, .lea, .tmp2p, .memsia(.dst0, .@"8", .tmp0, .add_size), ._, ._ },
28955 .{ ._, ._, .mov, .tmp3q, .memia(.src0q, .tmp1, .add_size), ._, ._ },
28956 .{ ._, ._mp, .j, .@"1f", ._, ._, ._ },
28957 .{ .@"0:", ._, .mov, .tmp4q, .memia(.src0q, .tmp1, .add_size), ._, ._ },
28958 .{ ._, ._rd, .sh, .tmp3q, .tmp4q, .src1b, ._ },
28959 .{ ._, ._, .mov, .leai(.tmp2q, .tmp1), .tmp3q, ._, ._ },
28960 .{ ._, ._, .mov, .tmp3q, .tmp4q, ._, ._ },
28961 .{ .@"1:", ._, .add, .tmp1p, .si(8), ._, ._ },
28962 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
28963 .{ ._, ._r, .sh, .tmp3q, .src1b, ._, ._ },
28964 .{ .@"0:", ._, .mov, .memsia(.dst0q, .@"8", .tmp0, .add_size), .tmp3q, ._, ._ },
28965 .{ ._, ._, .xor, .tmp3d, .tmp3d, ._, ._ },
28966 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
28967 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
28968 } },
28969 } }) catch |err| switch (err) {
28970 error.SelectFailed => return cg.fail("failed to select {s} {} {} {} {}", .{
28971 @tagName(air_tag),
28972 cg.typeOf(bin_op.lhs).fmt(pt),
28973 cg.typeOf(bin_op.rhs).fmt(pt),
28974 ops[0].tracking(cg),
28975 ops[1].tracking(cg),
28976 }),
28977 else => |e| return e,
28978 };
28979 try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
28980 },
28981 .shl, .shl_exact => |air_tag| if (use_old) try cg.airShlShrBinOp(inst) else fallback: {
28982 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
28983 if (cg.typeOf(bin_op.lhs).isVector(zcu)) break :fallback try cg.airShlShrBinOp(inst);
28984 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
28985 var res: [1]Temp = undefined;
28986 cg.select(&res, &.{cg.typeOf(bin_op.lhs)}, &ops, comptime &.{ .{
28987 .src_constraints = .{ .{ .signed_int = .byte }, .{ .unsigned_int = .byte }, .any },
28988 .patterns = &.{
28989 .{ .src = .{ .mut_mem, .imm8, .none } },
28990 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
28991 .{ .src = .{ .mut_mem, .{ .to_reg = .cl }, .none } },
28992 .{ .src = .{ .to_mut_gpr, .{ .to_reg = .cl }, .none } },
28993 },
28994 .dst_temps = .{ .{ .ref = .src0 }, .unused },
28995 .clobbers = .{ .eflags = true },
28996 .each = .{ .once = &.{
28997 .{ ._, ._l, .sa, .dst0b, .src1b, ._, ._ },
28998 } },
28999 }, .{
29000 .src_constraints = .{ .{ .unsigned_int = .byte }, .{ .unsigned_int = .byte }, .any },
29001 .patterns = &.{
29002 .{ .src = .{ .mut_mem, .imm8, .none } },
29003 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
29004 .{ .src = .{ .mut_mem, .{ .to_reg = .cl }, .none } },
29005 .{ .src = .{ .to_mut_gpr, .{ .to_reg = .cl }, .none } },
29006 },
29007 .dst_temps = .{ .{ .ref = .src0 }, .unused },
29008 .clobbers = .{ .eflags = true },
29009 .each = .{ .once = &.{
29010 .{ ._, ._l, .sh, .dst0b, .src1b, ._, ._ },
29011 } },
29012 }, .{
29013 .src_constraints = .{ .{ .signed_int = .word }, .{ .exact_unsigned_int = 4 }, .any },
29014 .patterns = &.{
29015 .{ .src = .{ .mut_mem, .imm8, .none } },
29016 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
29017 .{ .src = .{ .mut_mem, .{ .to_reg = .cl }, .none } },
29018 .{ .src = .{ .to_mut_gpr, .{ .to_reg = .cl }, .none } },
29019 },
29020 .dst_temps = .{ .{ .ref = .src0 }, .unused },
29021 .clobbers = .{ .eflags = true },
29022 .each = .{ .once = &.{
29023 .{ ._, ._l, .sa, .dst0w, .src1b, ._, ._ },
29024 } },
29025 }, .{
29026 .src_constraints = .{ .{ .unsigned_int = .word }, .{ .exact_unsigned_int = 4 }, .any },
29027 .patterns = &.{
29028 .{ .src = .{ .mut_mem, .imm8, .none } },
29029 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
29030 .{ .src = .{ .mut_mem, .{ .to_reg = .cl }, .none } },
29031 .{ .src = .{ .to_mut_gpr, .{ .to_reg = .cl }, .none } },
29032 },
29033 .dst_temps = .{ .{ .ref = .src0 }, .unused },
29034 .clobbers = .{ .eflags = true },
29035 .each = .{ .once = &.{
29036 .{ ._, ._l, .sh, .dst0w, .src1b, ._, ._ },
29037 } },
29038 }, .{
29039 .src_constraints = .{ .{ .signed_int = .dword }, .{ .exact_unsigned_int = 5 }, .any },
29040 .patterns = &.{
29041 .{ .src = .{ .mut_mem, .imm8, .none } },
29042 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
29043 },
29044 .dst_temps = .{ .{ .ref = .src0 }, .unused },
29045 .clobbers = .{ .eflags = true },
29046 .each = .{ .once = &.{
29047 .{ ._, ._l, .sa, .dst0d, .src1b, ._, ._ },
29048 } },
29049 }, .{
29050 .src_constraints = .{ .{ .unsigned_int = .dword }, .{ .exact_unsigned_int = 5 }, .any },
29051 .patterns = &.{
29052 .{ .src = .{ .mut_mem, .imm8, .none } },
29053 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
29054 },
29055 .dst_temps = .{ .{ .ref = .src0 }, .unused },
29056 .clobbers = .{ .eflags = true },
29057 .each = .{ .once = &.{
29058 .{ ._, ._l, .sh, .dst0d, .src1b, ._, ._ },
29059 } },
29060 }, .{
29061 .required_features = .{ .bmi2, null, null, null },
29062 .src_constraints = .{ .{ .int = .dword }, .{ .exact_unsigned_int = 5 }, .any },
29063 .patterns = &.{
29064 .{ .src = .{ .mem, .to_gpr, .none } },
29065 .{ .src = .{ .to_gpr, .to_gpr, .none } },
29066 },
29067 .dst_temps = .{ .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } }, .unused },
29068 .each = .{ .once = &.{
29069 .{ ._, ._lx, .sh, .dst0d, .src0d, .src1d, ._ },
29070 } },
29071 }, .{
29072 .src_constraints = .{ .{ .signed_int = .dword }, .{ .exact_unsigned_int = 5 }, .any },
29073 .patterns = &.{
29074 .{ .src = .{ .mut_mem, .{ .to_reg = .cl }, .none } },
29075 .{ .src = .{ .to_mut_gpr, .{ .to_reg = .cl }, .none } },
29076 },
29077 .dst_temps = .{ .{ .ref = .src0 }, .unused },
29078 .clobbers = .{ .eflags = true },
29079 .each = .{ .once = &.{
29080 .{ ._, ._l, .sa, .dst0d, .src1b, ._, ._ },
29081 } },
29082 }, .{
29083 .src_constraints = .{ .{ .unsigned_int = .dword }, .{ .exact_unsigned_int = 5 }, .any },
29084 .patterns = &.{
29085 .{ .src = .{ .mut_mem, .{ .to_reg = .cl }, .none } },
29086 .{ .src = .{ .to_mut_gpr, .{ .to_reg = .cl }, .none } },
29087 },
29088 .dst_temps = .{ .{ .ref = .src0 }, .unused },
29089 .clobbers = .{ .eflags = true },
29090 .each = .{ .once = &.{
29091 .{ ._, ._l, .sh, .dst0d, .src1b, ._, ._ },
29092 } },
29093 }, .{
29094 .required_features = .{ .@"64bit", null, null, null },
29095 .src_constraints = .{ .{ .signed_int = .qword }, .{ .exact_unsigned_int = 6 }, .any },
29096 .patterns = &.{
29097 .{ .src = .{ .mut_mem, .imm8, .none } },
29098 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
29099 },
29100 .dst_temps = .{ .{ .ref = .src0 }, .unused },
29101 .clobbers = .{ .eflags = true },
29102 .each = .{ .once = &.{
29103 .{ ._, ._l, .sa, .dst0q, .src1b, ._, ._ },
29104 } },
29105 }, .{
29106 .required_features = .{ .@"64bit", null, null, null },
29107 .src_constraints = .{ .{ .unsigned_int = .qword }, .{ .exact_unsigned_int = 6 }, .any },
29108 .patterns = &.{
29109 .{ .src = .{ .mut_mem, .imm8, .none } },
29110 .{ .src = .{ .to_mut_gpr, .imm8, .none } },
29111 },
29112 .dst_temps = .{ .{ .ref = .src0 }, .unused },
29113 .clobbers = .{ .eflags = true },
29114 .each = .{ .once = &.{
29115 .{ ._, ._l, .sh, .dst0q, .src1b, ._, ._ },
29116 } },
29117 }, .{
29118 .required_features = .{ .@"64bit", .bmi2, null, null },
29119 .src_constraints = .{ .{ .int = .qword }, .{ .exact_unsigned_int = 6 }, .any },
29120 .patterns = &.{
29121 .{ .src = .{ .mem, .to_gpr, .none } },
29122 .{ .src = .{ .to_gpr, .to_gpr, .none } },
29123 },
29124 .dst_temps = .{ .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } }, .unused },
29125 .each = .{ .once = &.{
29126 .{ ._, ._lx, .sh, .dst0q, .src0q, .src1q, ._ },
29127 } },
29128 }, .{
29129 .required_features = .{ .@"64bit", null, null, null },
29130 .src_constraints = .{ .{ .signed_int = .qword }, .{ .exact_unsigned_int = 6 }, .any },
29131 .patterns = &.{
29132 .{ .src = .{ .mut_mem, .{ .to_reg = .cl }, .none } },
29133 .{ .src = .{ .to_mut_gpr, .{ .to_reg = .cl }, .none } },
29134 },
29135 .dst_temps = .{ .{ .ref = .src0 }, .unused },
29136 .clobbers = .{ .eflags = true },
29137 .each = .{ .once = &.{
29138 .{ ._, ._l, .sa, .dst0q, .src1b, ._, ._ },
29139 } },
29140 }, .{
29141 .required_features = .{ .@"64bit", null, null, null },
29142 .src_constraints = .{ .{ .unsigned_int = .qword }, .{ .exact_unsigned_int = 6 }, .any },
29143 .patterns = &.{
29144 .{ .src = .{ .mut_mem, .{ .to_reg = .cl }, .none } },
29145 .{ .src = .{ .to_mut_gpr, .{ .to_reg = .cl }, .none } },
29146 },
29147 .dst_temps = .{ .{ .ref = .src0 }, .unused },
29148 .clobbers = .{ .eflags = true },
29149 .each = .{ .once = &.{
29150 .{ ._, ._l, .sh, .dst0q, .src1b, ._, ._ },
29151 } },
29152 }, .{
29153 .required_features = .{ .@"64bit", .slow_incdec, null, null },
29154 .src_constraints = .{
29155 .{ .remainder_int = .{ .of = .qword, .is = .qword } },
29156 .{ .unsigned_int = .byte },
29157 .any,
29158 },
29159 .patterns = &.{
29160 .{ .src = .{ .to_mem, .{ .to_reg = .cl }, .none } },
29161 },
29162 .extra_temps = .{
29163 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
29164 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
29165 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
29166 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29167 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29168 .unused,
29169 .unused,
29170 .unused,
29171 .unused,
29172 .unused,
29173 .unused,
29174 },
29175 .dst_temps = .{ .mem, .unused },
29176 .clobbers = .{ .eflags = true },
29177 .each = .{ .once = &.{
29178 .{ ._, ._, .movzx, .tmp0d, .src1b, ._, ._ },
29179 .{ ._, ._, .mov, .tmp1d, .sia(-1, .src0, .add_size_div_8), ._, ._ },
29180 .{ ._, ._r, .sh, .tmp0d, .ui(6), ._, ._ },
29181 .{ ._, ._, .sub, .tmp1d, .tmp0d, ._, ._ },
29182 .{ ._, ._, .lea, .tmp2p, .memsid(.dst0, .@"8", .tmp0, 8), ._, ._ },
29183 .{ ._, ._, .mov, .tmp3q, .memsi(.src0q, .@"8", .tmp1), ._, ._ },
29184 .{ ._, ._mp, .j, .@"1f", ._, ._, ._ },
29185 .{ .@"0:", ._, .mov, .tmp4q, .memsi(.src0q, .@"8", .tmp1), ._, ._ },
29186 .{ ._, ._ld, .sh, .tmp3q, .tmp4q, .src1b, ._ },
29187 .{ ._, ._, .mov, .leasi(.tmp2q, .@"8", .tmp1), .tmp3q, ._, ._ },
29188 .{ ._, ._, .mov, .tmp3q, .tmp4q, ._, ._ },
29189 .{ .@"1:", ._, .sub, .tmp1d, .si(1), ._, ._ },
29190 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
29191 .{ ._, ._l, .sh, .tmp3q, .src1b, ._, ._ },
29192 .{ .@"0:", ._, .mov, .memsi(.dst0q, .@"8", .tmp0), .tmp3q, ._, ._ },
29193 .{ ._, ._, .xor, .tmp3d, .tmp3d, ._, ._ },
29194 .{ ._, ._, .sub, .tmp0d, .si(1), ._, ._ },
29195 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
29196 } },
29197 }, .{
29198 .required_features = .{ .@"64bit", null, null, null },
29199 .src_constraints = .{
29200 .{ .remainder_int = .{ .of = .qword, .is = .qword } },
29201 .{ .unsigned_int = .byte },
29202 .any,
29203 },
29204 .patterns = &.{
29205 .{ .src = .{ .to_mem, .{ .to_reg = .cl }, .none } },
29206 },
29207 .extra_temps = .{
29208 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
29209 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
29210 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
29211 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29212 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29213 .unused,
29214 .unused,
29215 .unused,
29216 .unused,
29217 .unused,
29218 .unused,
29219 },
29220 .dst_temps = .{ .mem, .unused },
29221 .clobbers = .{ .eflags = true },
29222 .each = .{ .once = &.{
29223 .{ ._, ._, .movzx, .tmp0d, .src1b, ._, ._ },
29224 .{ ._, ._, .mov, .tmp1d, .sia(-1, .src0, .add_size_div_8), ._, ._ },
29225 .{ ._, ._r, .sh, .tmp0d, .ui(6), ._, ._ },
29226 .{ ._, ._, .sub, .tmp1d, .tmp0d, ._, ._ },
29227 .{ ._, ._, .lea, .tmp2p, .memsid(.dst0, .@"8", .tmp0, 8), ._, ._ },
29228 .{ ._, ._, .mov, .tmp3q, .memsi(.src0q, .@"8", .tmp1), ._, ._ },
29229 .{ ._, ._mp, .j, .@"1f", ._, ._, ._ },
29230 .{ .@"0:", ._, .mov, .tmp4q, .memsi(.src0q, .@"8", .tmp1), ._, ._ },
29231 .{ ._, ._ld, .sh, .tmp3q, .tmp4q, .src1b, ._ },
29232 .{ ._, ._, .mov, .leasi(.tmp2q, .@"8", .tmp1), .tmp3q, ._, ._ },
29233 .{ ._, ._, .mov, .tmp3q, .tmp4q, ._, ._ },
29234 .{ .@"1:", ._c, .de, .tmp1d, ._, ._, ._ },
29235 .{ ._, ._ns, .j, .@"0b", ._, ._, ._ },
29236 .{ ._, ._l, .sh, .tmp3q, .src1b, ._, ._ },
29237 .{ .@"0:", ._, .mov, .memsi(.dst0q, .@"8", .tmp0), .tmp3q, ._, ._ },
29238 .{ ._, ._, .xor, .tmp3d, .tmp3d, ._, ._ },
29239 .{ ._, ._c, .de, .tmp0d, ._, ._, ._ },
29240 .{ ._, ._ns, .j, .@"0b", ._, ._, ._ },
29241 } },
29242 }, .{
29243 .required_features = .{ .@"64bit", .slow_incdec, null, null },
29244 .src_constraints = .{
29245 .{ .remainder_int = .{ .of = .qword, .is = .qword } },
29246 .{ .unsigned_int = .word },
29247 .any,
29248 },
29249 .patterns = &.{
29250 .{ .src = .{ .to_mem, .{ .to_reg = .cx }, .none } },
29251 },
29252 .extra_temps = .{
29253 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
29254 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
29255 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
29256 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29257 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29258 .unused,
29259 .unused,
29260 .unused,
29261 .unused,
29262 .unused,
29263 .unused,
29264 },
29265 .dst_temps = .{ .mem, .unused },
29266 .clobbers = .{ .eflags = true },
29267 .each = .{ .once = &.{
29268 .{ ._, ._, .movzx, .tmp0d, .src1w, ._, ._ },
29269 .{ ._, ._, .mov, .tmp1d, .sia(-1, .src0, .add_size_div_8), ._, ._ },
29270 .{ ._, ._r, .sh, .tmp0d, .ui(6), ._, ._ },
29271 .{ ._, ._, .sub, .tmp1d, .tmp0d, ._, ._ },
29272 .{ ._, ._, .lea, .tmp2p, .memsid(.dst0, .@"8", .tmp0, 8), ._, ._ },
29273 .{ ._, ._, .mov, .tmp3q, .memsi(.src0q, .@"8", .tmp1), ._, ._ },
29274 .{ ._, ._mp, .j, .@"1f", ._, ._, ._ },
29275 .{ .@"0:", ._, .mov, .tmp4q, .memsi(.src0q, .@"8", .tmp1), ._, ._ },
29276 .{ ._, ._ld, .sh, .tmp3q, .tmp4q, .src1b, ._ },
29277 .{ ._, ._, .mov, .leasi(.tmp2q, .@"8", .tmp1), .tmp3q, ._, ._ },
29278 .{ ._, ._, .mov, .tmp3q, .tmp4q, ._, ._ },
29279 .{ .@"1:", ._, .sub, .tmp1d, .si(1), ._, ._ },
29280 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
29281 .{ ._, ._l, .sh, .tmp3q, .src1b, ._, ._ },
29282 .{ .@"0:", ._, .mov, .memsi(.dst0q, .@"8", .tmp0), .tmp3q, ._, ._ },
29283 .{ ._, ._, .xor, .tmp3d, .tmp3d, ._, ._ },
29284 .{ ._, ._, .sub, .tmp0d, .si(1), ._, ._ },
29285 .{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
29286 } },
29287 }, .{
29288 .required_features = .{ .@"64bit", null, null, null },
29289 .src_constraints = .{
29290 .{ .remainder_int = .{ .of = .qword, .is = .qword } },
29291 .{ .unsigned_int = .word },
29292 .any,
29293 },
29294 .patterns = &.{
29295 .{ .src = .{ .to_mem, .{ .to_reg = .cx }, .none } },
29296 },
29297 .extra_temps = .{
29298 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
29299 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
29300 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
29301 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29302 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
29303 .unused,
29304 .unused,
29305 .unused,
29306 .unused,
29307 .unused,
29308 .unused,
29309 },
29310 .dst_temps = .{ .mem, .unused },
29311 .clobbers = .{ .eflags = true },
29312 .each = .{ .once = &.{
29313 .{ ._, ._, .movzx, .tmp0d, .src1w, ._, ._ },
29314 .{ ._, ._, .mov, .tmp1d, .sia(-1, .src0, .add_size_div_8), ._, ._ },
29315 .{ ._, ._r, .sh, .tmp0d, .ui(6), ._, ._ },
29316 .{ ._, ._, .sub, .tmp1d, .tmp0d, ._, ._ },
29317 .{ ._, ._, .lea, .tmp2p, .memsid(.dst0, .@"8", .tmp0, 8), ._, ._ },
29318 .{ ._, ._, .mov, .tmp3q, .memsi(.src0q, .@"8", .tmp1), ._, ._ },
29319 .{ ._, ._mp, .j, .@"1f", ._, ._, ._ },
29320 .{ .@"0:", ._, .mov, .tmp4q, .memsi(.src0q, .@"8", .tmp1), ._, ._ },
29321 .{ ._, ._ld, .sh, .tmp3q, .tmp4q, .src1b, ._ },
29322 .{ ._, ._, .mov, .leasi(.tmp2q, .@"8", .tmp1), .tmp3q, ._, ._ },
29323 .{ ._, ._, .mov, .tmp3q, .tmp4q, ._, ._ },
29324 .{ .@"1:", ._c, .de, .tmp1d, ._, ._, ._ },
29325 .{ ._, ._ns, .j, .@"0b", ._, ._, ._ },
29326 .{ ._, ._l, .sh, .tmp3q, .src1b, ._, ._ },
29327 .{ .@"0:", ._, .mov, .memsi(.dst0q, .@"8", .tmp0), .tmp3q, ._, ._ },
29328 .{ ._, ._, .xor, .tmp3d, .tmp3d, ._, ._ },
29329 .{ ._, ._c, .de, .tmp0d, ._, ._, ._ },
29330 .{ ._, ._ns, .j, .@"0b", ._, ._, ._ },
29331 } },
29332 } }) catch |err| switch (err) {
29333 error.SelectFailed => return cg.fail("failed to select {s} {} {} {} {}", .{
29334 @tagName(air_tag),
29335 cg.typeOf(bin_op.lhs).fmt(pt),
29336 cg.typeOf(bin_op.rhs).fmt(pt),
29337 ops[0].tracking(cg),
29338 ops[1].tracking(cg),
29339 }),
29340 else => |e| return e,
29341 };
29342 switch (air_tag) {
29343 else => unreachable,
29344 .shl => res[0].wrapInt(cg) catch |err| switch (err) {
29345 error.SelectFailed => return cg.fail("failed to select wrap {} {} {} {}", .{
29346 cg.typeOf(bin_op.lhs).fmt(pt),
29347 cg.typeOf(bin_op.rhs).fmt(pt),
29348 ops[0].tracking(cg),
29349 ops[1].tracking(cg),
29350 }),
29351 else => |e| return e,
29352 },
29353 .shl_exact => {},
29354 }
29355 try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
29356 },
2841929357 .not => |air_tag| if (use_old) try cg.airUnOp(inst, air_tag) else {
2842029358 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
2842129359 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
......@@ -85342,7 +86280,7 @@ fn regClassForType(self: *CodeGen, ty: Type) Register.Class {
8534286280fn regSetForRegClass(rc: Register.Class) RegisterManager.RegisterBitSet {
8534386281 return switch (rc) {
8534486282 .general_purpose => abi.RegisterClass.gp,
85345 .segment, .ip, .cr, .dr => unreachable,
86283 .gphi, .segment, .ip, .cr, .dr => unreachable,
8534686284 .x87 => abi.RegisterClass.x87,
8534786285 .mmx => @panic("TODO"),
8534886286 .sse => abi.RegisterClass.sse,
......@@ -97763,7 +98701,7 @@ fn moveStrategy(cg: *CodeGen, ty: Type, class: Register.Class, aligned: bool) !M
9776398701 const pt = cg.pt;
9776498702 const zcu = pt.zcu;
9776598703 switch (class) {
97766 .general_purpose, .segment => return .{ .load_store = .{ ._, .mov } },
98704 .general_purpose, .gphi, .segment => return .{ .load_store = .{ ._, .mov } },
9776798705 .x87 => return .load_store_x87,
9776898706 .mmx => {},
9776998707 .sse => switch (ty.zigTypeTag(zcu)) {
......@@ -98239,7 +99177,7 @@ fn genSetReg(
9823999177 .reserved_frame,
9824099178 => unreachable,
9824199179 .undef => if (opts.safety) switch (dst_reg.class()) {
98242 .general_purpose => switch (abi_size) {
99180 .general_purpose, .gphi => switch (abi_size) {
9824399181 1 => try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to8(), .u(0xaa)),
9824499182 2 => try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to16(), .u(0xaaaa)),
9824599183 3...4 => try self.asmRegisterImmediate(
......@@ -98296,8 +99234,8 @@ fn genSetReg(
9829699234 }
9829799235 },
9829899236 .register => |src_reg| if (dst_reg.id() != src_reg.id()) switch (dst_reg.class()) {
98299 .general_purpose => switch (src_reg.class()) {
98300 .general_purpose => try self.asmRegisterRegister(
99237 .general_purpose, .gphi => switch (src_reg.class()) {
99238 .general_purpose, .gphi => try self.asmRegisterRegister(
9830199239 .{ ._, .mov },
9830299240 dst_alias,
9830399241 registerAlias(src_reg, abi_size),
......@@ -98341,13 +99279,13 @@ fn genSetReg(
9834199279 .{ ._, .mov },
9834299280 dst_reg,
9834399281 switch (src_reg.class()) {
98344 .general_purpose, .segment => registerAlias(src_reg, abi_size),
99282 .general_purpose, .gphi, .segment => registerAlias(src_reg, abi_size),
9834599283 .x87, .mmx, .ip, .cr, .dr => unreachable,
9834699284 .sse => try self.copyToTmpRegister(ty, src_mcv),
9834799285 },
9834899286 ),
9834999287 .x87 => switch (src_reg.class()) {
98350 .general_purpose, .segment => unreachable,
99288 .general_purpose, .gphi, .segment => unreachable,
9835199289 .x87 => switch (src_reg) {
9835299290 .st0 => try self.asmRegister(.{ .f_, .st }, dst_reg),
9835399291 .st1, .st2, .st3, .st4, .st5, .st6 => switch (dst_reg) {
......@@ -98376,7 +99314,7 @@ fn genSetReg(
9837699314 },
9837799315 .mmx => unreachable,
9837899316 .sse => switch (src_reg.class()) {
98379 .general_purpose => if (self.hasFeature(.sse2)) try self.asmRegisterRegister(
99317 .general_purpose, .gphi => if (self.hasFeature(.sse2)) try self.asmRegisterRegister(
9838099318 switch (abi_size) {
9838199319 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },
9838299320 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov },
......@@ -98602,7 +99540,7 @@ fn genSetReg(
9860299540 } },
9860399541 }),
9860499542 .load_symbol => |sym_off| switch (dst_reg.class()) {
98605 .general_purpose => {
99543 .general_purpose, .gphi => {
9860699544 assert(sym_off.off == 0);
9860799545 try self.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{
9860899546 .base = .{ .reloc = sym_off.sym_index },
......@@ -98617,7 +99555,7 @@ fn genSetReg(
9861799555 .x87, .sse => {},
9861899556 },
9861999557 .load_direct => |sym_index| switch (dst_reg.class()) {
98620 .general_purpose => {
99558 .general_purpose, .gphi => {
9862199559 _ = try self.addInst(.{
9862299560 .tag = .mov,
9862399561 .ops = .direct_reloc,
......@@ -98781,7 +99719,7 @@ fn genSetMem(
9878199719 };
9878299720 const src_alias = registerAlias(src_reg, abi_size);
9878399721 const src_size: u32 = @intCast(switch (src_alias.class()) {
98784 .general_purpose, .segment, .x87, .ip, .cr, .dr => @divExact(src_alias.bitSize(), 8),
99722 .general_purpose, .gphi, .segment, .x87, .ip, .cr, .dr => @divExact(src_alias.bitSize(), 8),
9878599723 .mmx, .sse => abi_size,
9878699724 });
9878799725 const src_align: InternPool.Alignment = .fromNonzeroByteUnits(
......@@ -103089,7 +104027,7 @@ fn resolveCallingConventionValues(
103089104027 const ret_gpr = abi.getCAbiIntReturnRegs(cc);
103090104028 const ret_size: u31 = @intCast(ret_ty.abiSize(zcu));
103091104029 if (abi.zigcc.return_in_regs) switch (self.regClassForType(ret_ty)) {
103092 .general_purpose => if (ret_size <= @as(u4, switch (self.target.cpu.arch) {
104030 .general_purpose, .gphi => if (ret_size <= @as(u4, switch (self.target.cpu.arch) {
103093104031 else => unreachable,
103094104032 .x86 => 4,
103095104033 .x86_64 => 8,
......@@ -103119,7 +104057,7 @@ fn resolveCallingConventionValues(
103119104057 }
103120104058 const param_size: u31 = @intCast(param_ty.abiSize(zcu));
103121104059 if (abi.zigcc.params_in_regs) switch (self.regClassForType(param_ty)) {
103122 .general_purpose => if (param_gpr.len >= 1 and param_size <= @as(u4, switch (self.target.cpu.arch) {
104060 .general_purpose, .gphi => if (param_gpr.len >= 1 and param_size <= @as(u4, switch (self.target.cpu.arch) {
103123104061 else => unreachable,
103124104062 .x86 => 4,
103125104063 .x86_64 => 8,
......@@ -103192,10 +104130,9 @@ fn parseRegName(name: []const u8) ?Register {
103192104130
103193104131/// Returns register wide enough to hold at least `size_bytes`.
103194104132fn registerAlias(reg: Register, size_bytes: u32) Register {
104133 if (size_bytes == 0) unreachable; // should be comptime-known
103195104134 return switch (reg.class()) {
103196 .general_purpose => if (size_bytes == 0)
103197 unreachable // should be comptime-known
103198 else if (size_bytes <= 1)
104135 .general_purpose => if (size_bytes <= 1)
103199104136 reg.to8()
103200104137 else if (size_bytes <= 2)
103201104138 reg.to16()
......@@ -103205,6 +104142,16 @@ fn registerAlias(reg: Register, size_bytes: u32) Register {
103205104142 reg.to64()
103206104143 else
103207104144 unreachable,
104145 .gphi => if (size_bytes <= 1)
104146 reg
104147 else if (size_bytes <= 2)
104148 reg.to16()
104149 else if (size_bytes <= 4)
104150 reg.to32()
104151 else if (size_bytes <= 8)
104152 reg.to64()
104153 else
104154 unreachable,
103208104155 .segment => if (size_bytes <= 2)
103209104156 reg
103210104157 else
......@@ -104566,6 +105513,7 @@ const Temp = struct {
104566105513 .required_features = .{ .@"64bit", .bmi2, null, null },
104567105514 .src_constraints = .{ .{ .unsigned_int = .qword }, .any, .any },
104568105515 .patterns = &.{
105516 .{ .src = .{ .mem, .none, .none } },
104569105517 .{ .src = .{ .to_gpr, .none, .none } },
104570105518 },
104571105519 .extra_temps = .{
......@@ -104594,6 +105542,19 @@ const Temp = struct {
104594105542 .{ .src = .{ .mut_mem, .none, .none } },
104595105543 .{ .src = .{ .to_mut_gpr, .none, .none } },
104596105544 },
105545 .extra_temps = .{
105546 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
105547 .unused,
105548 .unused,
105549 .unused,
105550 .unused,
105551 .unused,
105552 .unused,
105553 .unused,
105554 .unused,
105555 .unused,
105556 .unused,
105557 },
104597105558 .dst_temps = .{ .{ .ref = .src0 }, .unused },
104598105559 .clobbers = .{ .eflags = true },
104599105560 .each = .{ .once = &.{
......@@ -108625,7 +109586,7 @@ const Temp = struct {
108625109586 ) InnerError!void {
108626109587 const tomb_bits = cg.liveness.getTombBits(inst);
108627109588 for (0.., op_refs, op_temps) |op_index, op_ref, op_temp| {
108628 if (op_temp.index != temp.index) try op_temp.die(cg);
109589 if (op_temp.index != temp.index and op_temp.tracking(cg).short != .dead) try op_temp.die(cg);
108629109590 if (tomb_bits & @as(Liveness.Bpi, 1) << @intCast(op_index) == 0) continue;
108630109591 if (cg.reused_operands.isSet(op_index)) continue;
108631109592 try cg.processDeath(op_ref.toIndexAllowNone() orelse continue);
......@@ -110197,7 +111158,10 @@ const Select = struct {
110197111158 }
110198111159
110199111160 fn valueOf(ref: Ref, s: *const Select) MCValue {
110200 return s.temps[@intFromEnum(ref)].tracking(s.cg).short;
111161 return switch (ref) {
111162 .none => .none,
111163 else => s.temps[@intFromEnum(ref)].tracking(s.cg).short,
111164 };
110201111165 }
110202111166 };
110203111167
......@@ -110742,42 +111706,39 @@ const Select = struct {
110742111706 .lea => .{ .mem = .{
110743111707 .base = switch (op.flags.base.ref.valueOf(s)) {
110744111708 else => unreachable,
111709 .none => .none,
110745111710 .register => |base_reg| .{ .reg = registerAlias(base_reg, @divExact(s.cg.target.ptrBitWidth(), 8)) },
110746111711 .register_offset => |base_reg_off| .{ .reg = registerAlias(base_reg_off.reg, @divExact(s.cg.target.ptrBitWidth(), 8)) },
110747111712 .lea_symbol => |base_sym_off| .{ .reloc = base_sym_off.sym_index },
110748111713 },
110749111714 .mod = .{ .rm = .{
110750111715 .size = op.flags.base.size,
110751 .index = switch (op.flags.index.ref) {
110752 else => |index_ref| switch (index_ref.valueOf(s)) {
110753 else => unreachable,
110754 .register => |index_reg| registerAlias(index_reg, @divExact(s.cg.target.ptrBitWidth(), 8)),
110755 .register_offset => |index_reg_off| registerAlias(index_reg_off.reg, @divExact(s.cg.target.ptrBitWidth(), 8)),
110756 },
111716 .index = switch (op.flags.index.ref.valueOf(s)) {
111717 else => unreachable,
110757111718 .none => .none,
111719 .register => |index_reg| registerAlias(index_reg, @divExact(s.cg.target.ptrBitWidth(), 8)),
111720 .register_offset => |index_reg_off| registerAlias(index_reg_off.reg, @divExact(s.cg.target.ptrBitWidth(), 8)),
110758111721 },
110759111722 .scale = op.flags.index.scale,
110760111723 .disp = op.adjustedImm(i32, s) + switch (op.flags.base.ref.valueOf(s)) {
110761111724 else => unreachable,
110762 .register => 0,
111725 .none, .register => 0,
111726 .register_offset => |base_reg_off| base_reg_off.off,
111727 .lea_symbol => |base_sym_off| base_sym_off.off,
111728 } + switch (op.flags.index.ref.valueOf(s)) {
111729 else => unreachable,
111730 .none, .register => 0,
110763111731 .register_offset => |base_reg_off| base_reg_off.off,
110764111732 .lea_symbol => |base_sym_off| base_sym_off.off,
110765 } + switch (op.flags.index.ref) {
110766 else => |index_ref| switch (index_ref.valueOf(s)) {
110767 else => unreachable,
110768 .register => 0,
110769 .register_offset => |base_reg_off| base_reg_off.off,
110770 .lea_symbol => |base_sym_off| base_sym_off.off,
110771 },
110772 .none => 0,
110773111733 },
110774111734 } },
110775111735 } },
110776111736 .mem => .{ .mem = try op.flags.base.ref.valueOf(s).mem(s.cg, .{
110777111737 .size = op.flags.base.size,
110778 .index = switch (op.flags.index.ref) {
110779 else => |index_ref| registerAlias(index_ref.valueOf(s).register, @divExact(s.cg.target.ptrBitWidth(), 8)),
111738 .index = switch (op.flags.index.ref.valueOf(s)) {
111739 else => unreachable,
110780111740 .none => .none,
111741 .register => |index_reg| registerAlias(index_reg, @divExact(s.cg.target.ptrBitWidth(), 8)),
110781111742 },
110782111743 .scale = op.flags.index.scale,
110783111744 .disp = op.adjustedImm(i32, s),
src/arch/x86_64/Encoding.zig+1
......@@ -592,6 +592,7 @@ pub const Op = enum {
592592 else => unreachable,
593593 },
594594 },
595 .gphi => .r8,
595596 .segment => .sreg,
596597 .x87 => switch (reg) {
597598 .st0 => .st0,
src/arch/x86_64/bits.zig+3-3
......@@ -384,6 +384,7 @@ pub const Register = enum(u8) {
384384
385385 pub const Class = enum {
386386 general_purpose,
387 gphi,
387388 segment,
388389 x87,
389390 mmx,
......@@ -400,7 +401,7 @@ pub const Register = enum(u8) {
400401 @intFromEnum(Register.eax) ... @intFromEnum(Register.r15d) => .general_purpose,
401402 @intFromEnum(Register.ax) ... @intFromEnum(Register.r15w) => .general_purpose,
402403 @intFromEnum(Register.al) ... @intFromEnum(Register.r15b) => .general_purpose,
403 @intFromEnum(Register.ah) ... @intFromEnum(Register.bh) => .general_purpose,
404 @intFromEnum(Register.ah) ... @intFromEnum(Register.bh) => .gphi,
404405
405406 @intFromEnum(Register.ymm0) ... @intFromEnum(Register.ymm15) => .sse,
406407 @intFromEnum(Register.xmm0) ... @intFromEnum(Register.xmm15) => .sse,
......@@ -525,7 +526,6 @@ pub const Register = enum(u8) {
525526 }
526527
527528 fn gpBase(reg: Register) u7 {
528 assert(reg.class() == .general_purpose);
529529 return switch (@intFromEnum(reg)) {
530530 // zig fmt: off
531531 @intFromEnum(Register.rax) ... @intFromEnum(Register.r15) => @intFromEnum(Register.rax),
......@@ -577,7 +577,7 @@ pub const Register = enum(u8) {
577577 /// DWARF register encoding
578578 pub fn dwarfNum(reg: Register) u6 {
579579 return switch (reg.class()) {
580 .general_purpose => if (reg.isExtended())
580 .general_purpose, .gphi => if (reg.isExtended())
581581 reg.enc()
582582 else
583583 @as(u3, @truncate(@as(u24, 0o54673120) >> @as(u5, reg.enc()) * 3)),
test/behavior/x86_64/binary.zig+66-22
......@@ -1,4 +1,5 @@
11const AddOneBit = math.AddOneBit;
2const cast = math.cast;
23const checkExpected = math.checkExpected;
34const Compare = math.Compare;
45const DoubleBits = math.DoubleBits;
......@@ -6,6 +7,7 @@ const fmax = math.fmax;
67const fmin = math.fmin;
78const Gpr = math.Gpr;
89const inf = math.inf;
10const Log2Int = math.Log2Int;
911const math = @import("math.zig");
1012const nan = math.nan;
1113const Scalar = math.Scalar;
......@@ -5582,6 +5584,28 @@ test mod {
55825584 try test_mod.testFloatVectors();
55835585}
55845586
5587inline fn max(comptime Type: type, lhs: Type, rhs: Type) Type {
5588 return @max(lhs, rhs);
5589}
5590test max {
5591 const test_max = binary(max, .{});
5592 try test_max.testInts();
5593 try test_max.testIntVectors();
5594 try test_max.testFloats();
5595 try test_max.testFloatVectors();
5596}
5597
5598inline fn min(comptime Type: type, lhs: Type, rhs: Type) Type {
5599 return @min(lhs, rhs);
5600}
5601test min {
5602 const test_min = binary(min, .{});
5603 try test_min.testInts();
5604 try test_min.testIntVectors();
5605 try test_min.testFloats();
5606 try test_min.testFloatVectors();
5607}
5608
55855609inline fn equal(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs == rhs) {
55865610 return lhs == rhs;
55875611}
......@@ -5654,35 +5678,55 @@ test bitOr {
56545678 try test_bit_or.testIntVectors();
56555679}
56565680
5657inline fn bitXor(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs ^ rhs) {
5658 return lhs ^ rhs;
5681inline fn shr(comptime Type: type, lhs: Type, rhs: Type) Type {
5682 const bit_cast_rhs: @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(Type) } }) = @bitCast(rhs);
5683 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);
5684 return lhs >> if (comptime cast(Log2Int(Type), @bitSizeOf(Type))) |bits| truncate_rhs % bits else truncate_rhs;
56595685}
5660test bitXor {
5661 const test_bit_xor = binary(bitXor, .{});
5662 try test_bit_xor.testInts();
5663 try test_bit_xor.testIntVectors();
5686test shr {
5687 const test_shr = binary(shr, .{});
5688 try test_shr.testInts();
56645689}
56655690
5666inline fn min(comptime Type: type, lhs: Type, rhs: Type) Type {
5667 return @min(lhs, rhs);
5691inline fn shrExact(comptime Type: type, lhs: Type, rhs: Type) Type {
5692 const bit_cast_rhs: @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(Type) } }) = @bitCast(rhs);
5693 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);
5694 const final_rhs = if (comptime cast(Log2Int(Type), @bitSizeOf(Type))) |bits| truncate_rhs % bits else truncate_rhs;
5695 return @shrExact(lhs >> final_rhs << final_rhs, final_rhs);
56685696}
5669test min {
5670 const test_min = binary(min, .{});
5671 try test_min.testInts();
5672 try test_min.testIntVectors();
5673 try test_min.testFloats();
5674 try test_min.testFloatVectors();
5697test shrExact {
5698 const test_shr_exact = binary(shrExact, .{});
5699 try test_shr_exact.testInts();
56755700}
56765701
5677inline fn max(comptime Type: type, lhs: Type, rhs: Type) Type {
5678 return @max(lhs, rhs);
5702inline fn shl(comptime Type: type, lhs: Type, rhs: Type) Type {
5703 const bit_cast_rhs: @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(Type) } }) = @bitCast(rhs);
5704 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);
5705 return lhs << if (comptime cast(Log2Int(Type), @bitSizeOf(Type))) |bits| truncate_rhs % bits else truncate_rhs;
56795706}
5680test max {
5681 const test_max = binary(max, .{});
5682 try test_max.testInts();
5683 try test_max.testIntVectors();
5684 try test_max.testFloats();
5685 try test_max.testFloatVectors();
5707test shl {
5708 const test_shl = binary(shl, .{});
5709 try test_shl.testInts();
5710}
5711
5712inline fn shlExact(comptime Type: type, lhs: Type, rhs: Type) Type {
5713 const bit_cast_rhs: @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(Type) } }) = @bitCast(rhs);
5714 const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs);
5715 const final_rhs = if (comptime cast(Log2Int(Type), @bitSizeOf(Type))) |bits| truncate_rhs % bits else truncate_rhs;
5716 return @shlExact(lhs << final_rhs >> final_rhs, final_rhs);
5717}
5718test shlExact {
5719 const test_shl_exact = binary(shlExact, .{});
5720 try test_shl_exact.testInts();
5721}
5722
5723inline fn bitXor(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs ^ rhs) {
5724 return lhs ^ rhs;
5725}
5726test bitXor {
5727 const test_bit_xor = binary(bitXor, .{});
5728 try test_bit_xor.testInts();
5729 try test_bit_xor.testIntVectors();
56865730}
56875731
56885732inline fn optionalsEqual(comptime Type: type, lhs: Type, rhs: Type) bool {
test/behavior/x86_64/math.zig+1
......@@ -2,6 +2,7 @@ const builtin = @import("builtin");
22const math = std.math;
33const std = @import("std");
44
5pub const cast = math.cast;
56pub const fmax = math.floatMax;
67pub const fmin = math.floatMin;
78pub const imax = math.maxInt;