| author | |
| committer | |
| log | 53ec2a955eb02dc829af8610f17af42717d512fb |
| tree | 68b2ef11487f4415186efbd6bb1fed8bf0bb8add |
| parent | edd63f9abaa7dae1786a4cd91cc3031264bd3ef0 |
5 files changed, 169 insertions(+), 17 deletions(-)
src/arch/x86_64/CodeGen.zig+128-13| ... | @@ -2597,28 +2597,143 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2597,28 +2597,143 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 2597 | 2597 | ||
| 2598 | fn airClz(self: *Self, inst: Air.Inst.Index) !void { | 2598 | fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 2599 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2599 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2600 | const result: MCValue = if (self.liveness.isUnused(inst)) | 2600 | const result = result: { |
| 2601 | .dead | 2601 | if (self.liveness.isUnused(inst)) break :result .dead; |
| 2602 | else | 2602 | |
| 2603 | return self.fail("TODO implement airClz for {}", .{self.target.cpu.arch}); | 2603 | const dst_ty = self.air.typeOfIndex(inst); |
| 2604 | const src_ty = self.air.typeOf(ty_op.operand); | ||
| 2605 | const src_bits = src_ty.bitSize(self.target.*); | ||
| 2606 | |||
| 2607 | const src_mcv = try self.resolveInst(ty_op.operand); | ||
| 2608 | const mat_src_mcv = switch (src_mcv) { | ||
| 2609 | .immediate => MCValue{ .register = try self.copyToTmpRegister(src_ty, src_mcv) }, | ||
| 2610 | else => src_mcv, | ||
| 2611 | }; | ||
| 2612 | const mat_src_lock = switch (mat_src_mcv) { | ||
| 2613 | .register => |reg| self.register_manager.lockReg(reg), | ||
| 2614 | else => null, | ||
| 2615 | }; | ||
| 2616 | defer if (mat_src_lock) |lock| self.register_manager.unlockReg(lock); | ||
| 2617 | |||
| 2618 | const dst_reg = try self.register_manager.allocReg(inst, gp); | ||
| 2619 | const dst_mcv = MCValue{ .register = dst_reg }; | ||
| 2620 | const dst_lock = self.register_manager.lockReg(dst_reg); | ||
| 2621 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | ||
| 2622 | |||
| 2623 | if (Target.x86.featureSetHas(self.target.cpu.features, .lzcnt)) { | ||
| 2624 | try self.genBinOpMir(.lzcnt, src_ty, dst_mcv, mat_src_mcv); | ||
| 2625 | const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*)); | ||
| 2626 | const extra_bits = registerAlias(dst_reg, src_abi_size).bitSize() - src_bits; | ||
| 2627 | if (extra_bits > 0) { | ||
| 2628 | try self.genBinOpMir(.sub, dst_ty, dst_mcv, .{ .immediate = extra_bits }); | ||
| 2629 | } | ||
| 2630 | break :result dst_mcv; | ||
| 2631 | } | ||
| 2632 | |||
| 2633 | const width_reg = try self.copyToTmpRegister(dst_ty, .{ .immediate = src_bits }); | ||
| 2634 | const width_mcv = MCValue{ .register = width_reg }; | ||
| 2635 | try self.genBinOpMir(.bsr, src_ty, dst_mcv, mat_src_mcv); | ||
| 2636 | |||
| 2637 | const dst_abi_size = @intCast(u32, @max(dst_ty.abiSize(self.target.*), 2)); | ||
| 2638 | try self.asmCmovccRegisterRegister( | ||
| 2639 | registerAlias(dst_reg, dst_abi_size), | ||
| 2640 | registerAlias(width_reg, dst_abi_size), | ||
| 2641 | .z, | ||
| 2642 | ); | ||
| 2643 | |||
| 2644 | try self.genBinOpMir(.sub, dst_ty, width_mcv, dst_mcv); | ||
| 2645 | break :result width_mcv; | ||
| 2646 | }; | ||
| 2604 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 2647 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2605 | } | 2648 | } |
| 2606 | 2649 | ||
| 2607 | fn airCtz(self: *Self, inst: Air.Inst.Index) !void { | 2650 | fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 2608 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2651 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2609 | const result: MCValue = if (self.liveness.isUnused(inst)) | 2652 | const result = result: { |
| 2610 | .dead | 2653 | if (self.liveness.isUnused(inst)) break :result .dead; |
| 2611 | else | 2654 | |
| 2612 | return self.fail("TODO implement airCtz for {}", .{self.target.cpu.arch}); | 2655 | const dst_ty = self.air.typeOfIndex(inst); |
| 2656 | const src_ty = self.air.typeOf(ty_op.operand); | ||
| 2657 | const src_bits = src_ty.bitSize(self.target.*); | ||
| 2658 | |||
| 2659 | const src_mcv = try self.resolveInst(ty_op.operand); | ||
| 2660 | const mat_src_mcv = switch (src_mcv) { | ||
| 2661 | .immediate => MCValue{ .register = try self.copyToTmpRegister(src_ty, src_mcv) }, | ||
| 2662 | else => src_mcv, | ||
| 2663 | }; | ||
| 2664 | const mat_src_lock = switch (mat_src_mcv) { | ||
| 2665 | .register => |reg| self.register_manager.lockReg(reg), | ||
| 2666 | else => null, | ||
| 2667 | }; | ||
| 2668 | defer if (mat_src_lock) |lock| self.register_manager.unlockReg(lock); | ||
| 2669 | |||
| 2670 | const dst_reg = try self.register_manager.allocReg(inst, gp); | ||
| 2671 | const dst_mcv = MCValue{ .register = dst_reg }; | ||
| 2672 | const dst_lock = self.register_manager.lockReg(dst_reg); | ||
| 2673 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | ||
| 2674 | |||
| 2675 | if (Target.x86.featureSetHas(self.target.cpu.features, .bmi)) { | ||
| 2676 | const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*)); | ||
| 2677 | const extra_bits = registerAlias(dst_reg, src_abi_size).bitSize() - src_bits; | ||
| 2678 | const masked_mcv = if (extra_bits > 0) masked: { | ||
| 2679 | const mask_mcv = MCValue{ | ||
| 2680 | .immediate = ((@as(u64, 1) << @intCast(u6, extra_bits)) - 1) << @intCast(u6, src_bits), | ||
| 2681 | }; | ||
| 2682 | const tmp_mcv = tmp: { | ||
| 2683 | if (src_mcv.isImmediate() or self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) { | ||
| 2684 | break :tmp src_mcv; | ||
| 2685 | } | ||
| 2686 | try self.genSetReg(src_ty, dst_reg, src_mcv); | ||
| 2687 | break :tmp dst_mcv; | ||
| 2688 | }; | ||
| 2689 | try self.genBinOpMir(.@"or", src_ty, tmp_mcv, mask_mcv); | ||
| 2690 | break :masked tmp_mcv; | ||
| 2691 | } else mat_src_mcv; | ||
| 2692 | try self.genBinOpMir(.tzcnt, src_ty, dst_mcv, masked_mcv); | ||
| 2693 | break :result dst_mcv; | ||
| 2694 | } | ||
| 2695 | |||
| 2696 | const width_reg = try self.copyToTmpRegister(dst_ty, .{ .immediate = src_bits }); | ||
| 2697 | try self.genBinOpMir(.bsf, src_ty, dst_mcv, mat_src_mcv); | ||
| 2698 | |||
| 2699 | const abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); | ||
| 2700 | try self.asmCmovccRegisterRegister( | ||
| 2701 | registerAlias(dst_reg, abi_size), | ||
| 2702 | registerAlias(width_reg, abi_size), | ||
| 2703 | .z, | ||
| 2704 | ); | ||
| 2705 | |||
| 2706 | break :result dst_mcv; | ||
| 2707 | }; | ||
| 2613 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 2708 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2614 | } | 2709 | } |
| 2615 | 2710 | ||
| 2616 | fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { | 2711 | fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 2617 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2712 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2618 | const result: MCValue = if (self.liveness.isUnused(inst)) | 2713 | const result = result: { |
| 2619 | .dead | 2714 | if (self.liveness.isUnused(inst)) break :result .dead; |
| 2620 | else | 2715 | |
| 2621 | return self.fail("TODO implement airPopcount for {}", .{self.target.cpu.arch}); | 2716 | const op_ty = self.air.typeOf(ty_op.operand); |
| 2717 | |||
| 2718 | if (Target.x86.featureSetHas(self.target.cpu.features, .popcnt)) { | ||
| 2719 | const op_mcv = try self.resolveInst(ty_op.operand); | ||
| 2720 | const mat_op_mcv = switch (op_mcv) { | ||
| 2721 | .immediate => MCValue{ .register = try self.copyToTmpRegister(op_ty, op_mcv) }, | ||
| 2722 | else => op_mcv, | ||
| 2723 | }; | ||
| 2724 | const mat_op_lock = switch (mat_op_mcv) { | ||
| 2725 | .register => |reg| self.register_manager.lockReg(reg), | ||
| 2726 | else => null, | ||
| 2727 | }; | ||
| 2728 | defer if (mat_op_lock) |lock| self.register_manager.unlockReg(lock); | ||
| 2729 | |||
| 2730 | const dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, gp) }; | ||
| 2731 | try self.genBinOpMir(.popcnt, op_ty, dst_mcv, mat_op_mcv); | ||
| 2732 | break :result dst_mcv; | ||
| 2733 | } | ||
| 2734 | |||
| 2735 | return self.fail("TODO implement airPopcount for {}", .{op_ty.fmt(self.bin_file.options.module.?)}); | ||
| 2736 | }; | ||
| 2622 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 2737 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2623 | } | 2738 | } |
| 2624 | 2739 | ||
| ... | @@ -3491,7 +3606,7 @@ fn genBinOp( | ... | @@ -3491,7 +3606,7 @@ fn genBinOp( |
| 3491 | if (lhs.isRegister() and self.reuseOperand(inst, lhs_air, 0, lhs)) { | 3606 | if (lhs.isRegister() and self.reuseOperand(inst, lhs_air, 0, lhs)) { |
| 3492 | break :blk lhs; | 3607 | break :blk lhs; |
| 3493 | } | 3608 | } |
| 3494 | if (rhs.isRegister() and is_commutative and self.reuseOperand(inst, rhs_air, 1, rhs)) { | 3609 | if (is_commutative and rhs.isRegister() and self.reuseOperand(inst, rhs_air, 1, rhs)) { |
| 3495 | flipped = true; | 3610 | flipped = true; |
| 3496 | break :blk rhs; | 3611 | break :blk rhs; |
| 3497 | } | 3612 | } |
src/arch/x86_64/Emit.zig+5| ... | @@ -73,6 +73,8 @@ pub fn lowerMir(emit: *Emit) InnerError!void { | ... | @@ -73,6 +73,8 @@ pub fn lowerMir(emit: *Emit) InnerError!void { |
| 73 | .adc, | 73 | .adc, |
| 74 | .add, | 74 | .add, |
| 75 | .@"and", | 75 | .@"and", |
| 76 | .bsf, | ||
| 77 | .bsr, | ||
| 76 | .call, | 78 | .call, |
| 77 | .cbw, | 79 | .cbw, |
| 78 | .cwde, | 80 | .cwde, |
| ... | @@ -89,12 +91,14 @@ pub fn lowerMir(emit: *Emit) InnerError!void { | ... | @@ -89,12 +91,14 @@ pub fn lowerMir(emit: *Emit) InnerError!void { |
| 89 | .int3, | 91 | .int3, |
| 90 | .jmp, | 92 | .jmp, |
| 91 | .lea, | 93 | .lea, |
| 94 | .lzcnt, | ||
| 92 | .mov, | 95 | .mov, |
| 93 | .movzx, | 96 | .movzx, |
| 94 | .mul, | 97 | .mul, |
| 95 | .nop, | 98 | .nop, |
| 96 | .@"or", | 99 | .@"or", |
| 97 | .pop, | 100 | .pop, |
| 101 | .popcnt, | ||
| 98 | .push, | 102 | .push, |
| 99 | .ret, | 103 | .ret, |
| 100 | .sal, | 104 | .sal, |
| ... | @@ -105,6 +109,7 @@ pub fn lowerMir(emit: *Emit) InnerError!void { | ... | @@ -105,6 +109,7 @@ pub fn lowerMir(emit: *Emit) InnerError!void { |
| 105 | .sub, | 109 | .sub, |
| 106 | .syscall, | 110 | .syscall, |
| 107 | .@"test", | 111 | .@"test", |
| 112 | .tzcnt, | ||
| 108 | .ud2, | 113 | .ud2, |
| 109 | .xor, | 114 | .xor, |
| 110 | 115 |
src/arch/x86_64/Encoding.zig+4-2| ... | @@ -307,6 +307,7 @@ pub const Mnemonic = enum { | ... | @@ -307,6 +307,7 @@ pub const Mnemonic = enum { |
| 307 | // zig fmt: off | 307 | // zig fmt: off |
| 308 | // General-purpose | 308 | // General-purpose |
| 309 | adc, add, @"and", | 309 | adc, add, @"and", |
| 310 | bsf, bsr, | ||
| 310 | call, cbw, cdq, cdqe, | 311 | call, cbw, cdq, cdqe, |
| 311 | cmova, cmovae, cmovb, cmovbe, cmovc, cmove, cmovg, cmovge, cmovl, cmovle, cmovna, | 312 | cmova, cmovae, cmovb, cmovbe, cmovc, cmove, cmovg, cmovge, cmovl, cmovle, cmovna, |
| 312 | cmovnae, cmovnb, cmovnbe, cmovnc, cmovne, cmovng, cmovnge, cmovnl, cmovnle, cmovno, | 313 | cmovnae, cmovnb, cmovnbe, cmovnc, cmovne, cmovng, cmovnge, cmovnl, cmovnle, cmovno, |
| ... | @@ -322,12 +323,13 @@ pub const Mnemonic = enum { | ... | @@ -322,12 +323,13 @@ pub const Mnemonic = enum { |
| 322 | jmp, | 323 | jmp, |
| 323 | lea, | 324 | lea, |
| 324 | lods, lodsb, lodsd, lodsq, lodsw, | 325 | lods, lodsb, lodsd, lodsq, lodsw, |
| 326 | lzcnt, | ||
| 325 | mov, | 327 | mov, |
| 326 | movs, movsb, movsd, movsq, movsw, | 328 | movs, movsb, movsd, movsq, movsw, |
| 327 | movsx, movsxd, movzx, mul, | 329 | movsx, movsxd, movzx, mul, |
| 328 | nop, | 330 | nop, |
| 329 | @"or", | 331 | @"or", |
| 330 | pop, push, | 332 | pop, popcnt, push, |
| 331 | ret, | 333 | ret, |
| 332 | sal, sar, sbb, | 334 | sal, sar, sbb, |
| 333 | scas, scasb, scasd, scasq, scasw, | 335 | scas, scasb, scasd, scasq, scasw, |
| ... | @@ -336,7 +338,7 @@ pub const Mnemonic = enum { | ... | @@ -336,7 +338,7 @@ pub const Mnemonic = enum { |
| 336 | setnb, setnbe, setnc, setne, setng, setnge, setnl, setnle, setno, setnp, setns, | 338 | setnb, setnbe, setnc, setne, setng, setnge, setnl, setnle, setno, setnp, setns, |
| 337 | setnz, seto, setp, setpe, setpo, sets, setz, | 339 | setnz, seto, setp, setpe, setpo, sets, setz, |
| 338 | stos, stosb, stosd, stosq, stosw, | 340 | stos, stosb, stosd, stosq, stosw, |
| 339 | @"test", | 341 | @"test", tzcnt, |
| 340 | ud2, | 342 | ud2, |
| 341 | xor, | 343 | xor, |
| 342 | // SSE | 344 | // SSE |
src/arch/x86_64/Mir.zig+10| ... | @@ -38,6 +38,10 @@ pub const Inst = struct { | ... | @@ -38,6 +38,10 @@ pub const Inst = struct { |
| 38 | add, | 38 | add, |
| 39 | /// Logical and | 39 | /// Logical and |
| 40 | @"and", | 40 | @"and", |
| 41 | /// Bit scan forward | ||
| 42 | bsf, | ||
| 43 | /// Bit scan reverse | ||
| 44 | bsr, | ||
| 41 | /// Call | 45 | /// Call |
| 42 | call, | 46 | call, |
| 43 | /// Convert byte to word | 47 | /// Convert byte to word |
| ... | @@ -70,6 +74,8 @@ pub const Inst = struct { | ... | @@ -70,6 +74,8 @@ pub const Inst = struct { |
| 70 | jmp, | 74 | jmp, |
| 71 | /// Load effective address | 75 | /// Load effective address |
| 72 | lea, | 76 | lea, |
| 77 | /// Count the number of leading zero bits | ||
| 78 | lzcnt, | ||
| 73 | /// Move | 79 | /// Move |
| 74 | mov, | 80 | mov, |
| 75 | /// Move with sign extension | 81 | /// Move with sign extension |
| ... | @@ -84,6 +90,8 @@ pub const Inst = struct { | ... | @@ -84,6 +90,8 @@ pub const Inst = struct { |
| 84 | @"or", | 90 | @"or", |
| 85 | /// Pop | 91 | /// Pop |
| 86 | pop, | 92 | pop, |
| 93 | /// Return the count of number of bits set to 1 | ||
| 94 | popcnt, | ||
| 87 | /// Push | 95 | /// Push |
| 88 | push, | 96 | push, |
| 89 | /// Return | 97 | /// Return |
| ... | @@ -104,6 +112,8 @@ pub const Inst = struct { | ... | @@ -104,6 +112,8 @@ pub const Inst = struct { |
| 104 | syscall, | 112 | syscall, |
| 105 | /// Test condition | 113 | /// Test condition |
| 106 | @"test", | 114 | @"test", |
| 115 | /// Count the number of trailing zero bits | ||
| 116 | tzcnt, | ||
| 107 | /// Undefined instruction | 117 | /// Undefined instruction |
| 108 | ud2, | 118 | ud2, |
| 109 | /// Logical exclusive-or | 119 | /// Logical exclusive-or |
src/arch/x86_64/encodings.zig+22-2| ... | @@ -81,6 +81,14 @@ pub const table = &[_]Entry{ | ... | @@ -81,6 +81,14 @@ pub const table = &[_]Entry{ |
| 81 | .{ .@"and", .rm, .r32, .rm32, .none, .none, &.{ 0x23 }, 0, .none }, | 81 | .{ .@"and", .rm, .r32, .rm32, .none, .none, &.{ 0x23 }, 0, .none }, |
| 82 | .{ .@"and", .rm, .r64, .rm64, .none, .none, &.{ 0x23 }, 0, .long }, | 82 | .{ .@"and", .rm, .r64, .rm64, .none, .none, &.{ 0x23 }, 0, .long }, |
| 83 | 83 | ||
| 84 | .{ .bsf, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0xbc }, 0, .none }, | ||
| 85 | .{ .bsf, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0xbc }, 0, .none }, | ||
| 86 | .{ .bsf, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0xbc }, 0, .long }, | ||
| 87 | |||
| 88 | .{ .bsr, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0xbd }, 0, .none }, | ||
| 89 | .{ .bsr, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0xbd }, 0, .none }, | ||
| 90 | .{ .bsr, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0xbd }, 0, .long }, | ||
| 91 | |||
| 84 | // This is M encoding according to Intel, but D makes more sense here. | 92 | // This is M encoding according to Intel, but D makes more sense here. |
| 85 | .{ .call, .d, .rel32, .none, .none, .none, &.{ 0xe8 }, 0, .none }, | 93 | .{ .call, .d, .rel32, .none, .none, .none, &.{ 0xe8 }, 0, .none }, |
| 86 | .{ .call, .m, .rm64, .none, .none, .none, &.{ 0xff }, 2, .none }, | 94 | .{ .call, .m, .rm64, .none, .none, .none, &.{ 0xff }, 2, .none }, |
| ... | @@ -301,6 +309,10 @@ pub const table = &[_]Entry{ | ... | @@ -301,6 +309,10 @@ pub const table = &[_]Entry{ |
| 301 | .{ .lodsd, .np, .none, .none, .none, .none, &.{ 0xad }, 0, .none }, | 309 | .{ .lodsd, .np, .none, .none, .none, .none, &.{ 0xad }, 0, .none }, |
| 302 | .{ .lodsq, .np, .none, .none, .none, .none, &.{ 0xad }, 0, .long }, | 310 | .{ .lodsq, .np, .none, .none, .none, .none, &.{ 0xad }, 0, .long }, |
| 303 | 311 | ||
| 312 | .{ .lzcnt, .rm, .r16, .rm16, .none, .none, &.{ 0xf3, 0x0f, 0xbd }, 0, .none }, | ||
| 313 | .{ .lzcnt, .rm, .r32, .rm32, .none, .none, &.{ 0xf3, 0x0f, 0xbd }, 0, .none }, | ||
| 314 | .{ .lzcnt, .rm, .r64, .rm64, .none, .none, &.{ 0xf3, 0x0f, 0xbd }, 0, .long }, | ||
| 315 | |||
| 304 | .{ .mov, .mr, .rm8, .r8, .none, .none, &.{ 0x88 }, 0, .none }, | 316 | .{ .mov, .mr, .rm8, .r8, .none, .none, &.{ 0x88 }, 0, .none }, |
| 305 | .{ .mov, .mr, .rm8, .r8, .none, .none, &.{ 0x88 }, 0, .rex }, | 317 | .{ .mov, .mr, .rm8, .r8, .none, .none, &.{ 0x88 }, 0, .rex }, |
| 306 | .{ .mov, .mr, .rm16, .r16, .none, .none, &.{ 0x89 }, 0, .none }, | 318 | .{ .mov, .mr, .rm16, .r16, .none, .none, &.{ 0x89 }, 0, .none }, |
| ... | @@ -397,6 +409,10 @@ pub const table = &[_]Entry{ | ... | @@ -397,6 +409,10 @@ pub const table = &[_]Entry{ |
| 397 | .{ .pop, .m, .rm16, .none, .none, .none, &.{ 0x8f }, 0, .none }, | 409 | .{ .pop, .m, .rm16, .none, .none, .none, &.{ 0x8f }, 0, .none }, |
| 398 | .{ .pop, .m, .rm64, .none, .none, .none, &.{ 0x8f }, 0, .none }, | 410 | .{ .pop, .m, .rm64, .none, .none, .none, &.{ 0x8f }, 0, .none }, |
| 399 | 411 | ||
| 412 | .{ .popcnt, .rm, .r16, .rm16, .none, .none, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none }, | ||
| 413 | .{ .popcnt, .rm, .r32, .rm32, .none, .none, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none }, | ||
| 414 | .{ .popcnt, .rm, .r64, .rm64, .none, .none, &.{ 0xf3, 0x0f, 0xb8 }, 0, .long }, | ||
| 415 | |||
| 400 | .{ .push, .o, .r16, .none, .none, .none, &.{ 0x50 }, 0, .none }, | 416 | .{ .push, .o, .r16, .none, .none, .none, &.{ 0x50 }, 0, .none }, |
| 401 | .{ .push, .o, .r64, .none, .none, .none, &.{ 0x50 }, 0, .none }, | 417 | .{ .push, .o, .r64, .none, .none, .none, &.{ 0x50 }, 0, .none }, |
| 402 | .{ .push, .m, .rm16, .none, .none, .none, &.{ 0xff }, 6, .none }, | 418 | .{ .push, .m, .rm16, .none, .none, .none, &.{ 0xff }, 6, .none }, |
| ... | @@ -596,8 +612,8 @@ pub const table = &[_]Entry{ | ... | @@ -596,8 +612,8 @@ pub const table = &[_]Entry{ |
| 596 | .{ .sub, .rm, .r32, .rm32, .none, .none, &.{ 0x2b }, 0, .none }, | 612 | .{ .sub, .rm, .r32, .rm32, .none, .none, &.{ 0x2b }, 0, .none }, |
| 597 | .{ .sub, .rm, .r64, .rm64, .none, .none, &.{ 0x2b }, 0, .long }, | 613 | .{ .sub, .rm, .r64, .rm64, .none, .none, &.{ 0x2b }, 0, .long }, |
| 598 | 614 | ||
| 599 | .{ .syscall, .np, .none, .none, .none, .none, &.{ 0x0f, 0x05 }, 0, .none }, | 615 | .{ .syscall, .np, .none, .none, .none, .none, &.{ 0x0f, 0x05 }, 0, .none } |
| 600 | 616 | , | |
| 601 | .{ .@"test", .zi, .al, .imm8, .none, .none, &.{ 0xa8 }, 0, .none }, | 617 | .{ .@"test", .zi, .al, .imm8, .none, .none, &.{ 0xa8 }, 0, .none }, |
| 602 | .{ .@"test", .zi, .ax, .imm16, .none, .none, &.{ 0xa9 }, 0, .none }, | 618 | .{ .@"test", .zi, .ax, .imm16, .none, .none, &.{ 0xa9 }, 0, .none }, |
| 603 | .{ .@"test", .zi, .eax, .imm32, .none, .none, &.{ 0xa9 }, 0, .none }, | 619 | .{ .@"test", .zi, .eax, .imm32, .none, .none, &.{ 0xa9 }, 0, .none }, |
| ... | @@ -613,6 +629,10 @@ pub const table = &[_]Entry{ | ... | @@ -613,6 +629,10 @@ pub const table = &[_]Entry{ |
| 613 | .{ .@"test", .mr, .rm32, .r32, .none, .none, &.{ 0x85 }, 0, .none }, | 629 | .{ .@"test", .mr, .rm32, .r32, .none, .none, &.{ 0x85 }, 0, .none }, |
| 614 | .{ .@"test", .mr, .rm64, .r64, .none, .none, &.{ 0x85 }, 0, .long }, | 630 | .{ .@"test", .mr, .rm64, .r64, .none, .none, &.{ 0x85 }, 0, .long }, |
| 615 | 631 | ||
| 632 | .{ .tzcnt, .rm, .r16, .rm16, .none, .none, &.{ 0xf3, 0x0f, 0xbc }, 0, .none }, | ||
| 633 | .{ .tzcnt, .rm, .r32, .rm32, .none, .none, &.{ 0xf3, 0x0f, 0xbc }, 0, .none }, | ||
| 634 | .{ .tzcnt, .rm, .r64, .rm64, .none, .none, &.{ 0xf3, 0x0f, 0xbc }, 0, .long }, | ||
| 635 | |||
| 616 | .{ .ud2, .np, .none, .none, .none, .none, &.{ 0x0f, 0x0b }, 0, .none }, | 636 | .{ .ud2, .np, .none, .none, .none, .none, &.{ 0x0f, 0x0b }, 0, .none }, |
| 617 | 637 | ||
| 618 | .{ .xor, .zi, .al, .imm8, .none, .none, &.{ 0x34 }, 0, .none }, | 638 | .{ .xor, .zi, .al, .imm8, .none, .none, &.{ 0x34 }, 0, .none }, |