| ... | @@ -78,7 +78,7 @@ pub fn findByMnemonic( | ... | @@ -78,7 +78,7 @@ pub fn findByMnemonic( |
| 78 | ), | 78 | ), |
| 79 | .x86_64 => false, | 79 | .x86_64 => false, |
| 80 | }, | 80 | }, |
| 81 | inline .@"invpcid 64bit", .@"rdpid 64bit" => |tag| switch (target.cpu.arch) { | 81 | inline .@"invpcid 64bit", .@"rdpid 64bit", .@"prefetchi 64bit" => |tag| switch (target.cpu.arch) { |
| 82 | else => unreachable, | 82 | else => unreachable, |
| 83 | .x86 => false, | 83 | .x86 => false, |
| 84 | .x86_64 => std.Target.x86.featureSetHas( | 84 | .x86_64 => std.Target.x86.featureSetHas( |
| ... | @@ -86,6 +86,7 @@ pub fn findByMnemonic( | ... | @@ -86,6 +86,7 @@ pub fn findByMnemonic( |
| 86 | @field(std.Target.x86.Feature, @tagName(tag)[0 .. @tagName(tag).len - " 64bit".len]), | 86 | @field(std.Target.x86.Feature, @tagName(tag)[0 .. @tagName(tag).len - " 64bit".len]), |
| 87 | ), | 87 | ), |
| 88 | }, | 88 | }, |
| | 89 | .prefetch => std.Target.x86.featureSetHasAny(target.cpu.features, .{ .sse, .prfchw, .prefetchi, .prefetchwt1 }), |
| 89 | inline else => |tag| has_features: { | 90 | inline else => |tag| has_features: { |
| 90 | comptime var feature_it = std.mem.splitScalar(u8, @tagName(tag), ' '); | 91 | comptime var feature_it = std.mem.splitScalar(u8, @tagName(tag), ' '); |
| 91 | comptime var features: []const std.Target.x86.Feature = &.{}; | 92 | comptime var features: []const std.Target.x86.Feature = &.{}; |
| ... | @@ -375,6 +376,7 @@ pub const Mnemonic = enum { | ... | @@ -375,6 +376,7 @@ pub const Mnemonic = enum { |
| 375 | orps, | 376 | orps, |
| 376 | pextrw, pinsrw, | 377 | pextrw, pinsrw, |
| 377 | pmaxsw, pmaxub, pminsw, pminub, pmovmskb, | 378 | pmaxsw, pmaxub, pminsw, pminub, pmovmskb, |
| | 379 | prefetchit0, prefetchit1, prefetchnta, prefetcht0, prefetcht1, prefetcht2, prefetchw, prefetchwt1, |
| 378 | shufps, | 380 | shufps, |
| 379 | sqrtps, sqrtss, | 381 | sqrtps, sqrtss, |
| 380 | stmxcsr, | 382 | stmxcsr, |
| ... | @@ -562,8 +564,7 @@ pub const Op = enum { | ... | @@ -562,8 +564,7 @@ pub const Op = enum { |
| 562 | r32_m8, r32_m16, r64_m16, | 564 | r32_m8, r32_m16, r64_m16, |
| 563 | m8, m16, m32, m64, m80, m128, m256, | 565 | m8, m16, m32, m64, m80, m128, m256, |
| 564 | rel8, rel16, rel32, | 566 | rel8, rel16, rel32, |
| 565 | m, | 567 | m, moffs, mrip8, |
| 566 | moffs, | | |
| 567 | sreg, | 568 | sreg, |
| 568 | st0, st, mm, mm_m64, | 569 | st0, st, mm, mm_m64, |
| 569 | xmm0, xmm, xmm_m8, xmm_m16, xmm_m32, xmm_m64, xmm_m128, | 570 | xmm0, xmm, xmm_m8, xmm_m16, xmm_m32, xmm_m64, xmm_m128, |
| ... | @@ -617,7 +618,7 @@ pub const Op = enum { | ... | @@ -617,7 +618,7 @@ pub const Op = enum { |
| 617 | | 618 | |
| 618 | .mem => |mem| switch (mem) { | 619 | .mem => |mem| switch (mem) { |
| 619 | .moffs => .moffs, | 620 | .moffs => .moffs, |
| 620 | .sib, .rip => switch (mem.bitSize(target)) { | 621 | .sib => switch (mem.bitSize(target)) { |
| 621 | 0 => .m, | 622 | 0 => .m, |
| 622 | 8 => .m8, | 623 | 8 => .m8, |
| 623 | 16 => .m16, | 624 | 16 => .m16, |
| ... | @@ -628,6 +629,16 @@ pub const Op = enum { | ... | @@ -628,6 +629,16 @@ pub const Op = enum { |
| 628 | 256 => .m256, | 629 | 256 => .m256, |
| 629 | else => unreachable, | 630 | else => unreachable, |
| 630 | }, | 631 | }, |
| | 632 | .rip => switch (mem.bitSize(target)) { |
| | 633 | 0, 8 => .mrip8, |
| | 634 | 16 => .m16, |
| | 635 | 32 => .m32, |
| | 636 | 64 => .m64, |
| | 637 | 80 => .m80, |
| | 638 | 128 => .m128, |
| | 639 | 256 => .m256, |
| | 640 | else => unreachable, |
| | 641 | }, |
| 631 | }, | 642 | }, |
| 632 | | 643 | |
| 633 | .imm => |imm| switch (imm) { | 644 | .imm => |imm| switch (imm) { |
| ... | @@ -680,7 +691,7 @@ pub const Op = enum { | ... | @@ -680,7 +691,7 @@ pub const Op = enum { |
| 680 | | 691 | |
| 681 | pub fn immBitSize(op: Op) u64 { | 692 | pub fn immBitSize(op: Op) u64 { |
| 682 | return switch (op) { | 693 | return switch (op) { |
| 683 | .none, .moffs, .m, .sreg => unreachable, | 694 | .none, .m, .moffs, .mrip8, .sreg => unreachable, |
| 684 | .al, .cl, .dx, .rip, .eip, .ip, .r8, .rm8, .r32_m8 => unreachable, | 695 | .al, .cl, .dx, .rip, .eip, .ip, .r8, .rm8, .r32_m8 => unreachable, |
| 685 | .ax, .r16, .rm16 => unreachable, | 696 | .ax, .r16, .rm16 => unreachable, |
| 686 | .eax, .r32, .rm32, .r32_m16 => unreachable, | 697 | .eax, .r32, .rm32, .r32_m16 => unreachable, |
| ... | @@ -700,7 +711,7 @@ pub const Op = enum { | ... | @@ -700,7 +711,7 @@ pub const Op = enum { |
| 700 | | 711 | |
| 701 | pub fn regBitSize(op: Op) u64 { | 712 | pub fn regBitSize(op: Op) u64 { |
| 702 | return switch (op) { | 713 | return switch (op) { |
| 703 | .none, .moffs, .m, .sreg => unreachable, | 714 | .none, .m, .moffs, .mrip8, .sreg => unreachable, |
| 704 | .unity, .imm8, .imm8s, .imm16, .imm16s, .imm32, .imm32s, .imm64 => unreachable, | 715 | .unity, .imm8, .imm8s, .imm16, .imm16s, .imm32, .imm32s, .imm64 => unreachable, |
| 705 | .rel8, .rel16, .rel32 => unreachable, | 716 | .rel8, .rel16, .rel32 => unreachable, |
| 706 | .m8, .m16, .m32, .m64, .m80, .m128, .m256 => unreachable, | 717 | .m8, .m16, .m32, .m64, .m80, .m128, .m256 => unreachable, |
| ... | @@ -716,13 +727,13 @@ pub const Op = enum { | ... | @@ -716,13 +727,13 @@ pub const Op = enum { |
| 716 | | 727 | |
| 717 | pub fn memBitSize(op: Op) u64 { | 728 | pub fn memBitSize(op: Op) u64 { |
| 718 | return switch (op) { | 729 | return switch (op) { |
| 719 | .none, .moffs, .m, .sreg => unreachable, | 730 | .none, .m, .moffs, .sreg => unreachable, |
| 720 | .unity, .imm8, .imm8s, .imm16, .imm16s, .imm32, .imm32s, .imm64 => unreachable, | 731 | .unity, .imm8, .imm8s, .imm16, .imm16s, .imm32, .imm32s, .imm64 => unreachable, |
| 721 | .rel8, .rel16, .rel32 => unreachable, | 732 | .rel8, .rel16, .rel32 => unreachable, |
| 722 | .al, .cl, .r8, .ax, .dx, .ip, .r16, .eax, .eip, .r32, .rax, .rip, .r64 => unreachable, | 733 | .al, .cl, .r8, .ax, .dx, .ip, .r16, .eax, .eip, .r32, .rax, .rip, .r64 => unreachable, |
| 723 | .st0, .st, .mm, .xmm0, .xmm, .ymm => unreachable, | 734 | .st0, .st, .mm, .xmm0, .xmm, .ymm => unreachable, |
| 724 | .cr, .dr => unreachable, | 735 | .cr, .dr => unreachable, |
| 725 | .m8, .rm8, .r32_m8, .xmm_m8 => 8, | 736 | .mrip8, .m8, .rm8, .r32_m8, .xmm_m8 => 8, |
| 726 | .m16, .rm16, .r32_m16, .r64_m16, .xmm_m16 => 16, | 737 | .m16, .rm16, .r32_m16, .r64_m16, .xmm_m16 => 16, |
| 727 | .m32, .rm32, .xmm_m32 => 32, | 738 | .m32, .rm32, .xmm_m32 => 32, |
| 728 | .m64, .rm64, .mm_m64, .xmm_m64 => 64, | 739 | .m64, .rm64, .mm_m64, .xmm_m64 => 64, |
| ... | @@ -783,7 +794,7 @@ pub const Op = enum { | ... | @@ -783,7 +794,7 @@ pub const Op = enum { |
| 783 | .rm8, .rm16, .rm32, .rm64, | 794 | .rm8, .rm16, .rm32, .rm64, |
| 784 | .r32_m8, .r32_m16, .r64_m16, | 795 | .r32_m8, .r32_m16, .r64_m16, |
| 785 | .m8, .m16, .m32, .m64, .m80, .m128, .m256, | 796 | .m8, .m16, .m32, .m64, .m80, .m128, .m256, |
| 786 | .m, | 797 | .m, .moffs, .mrip8, |
| 787 | .mm_m64, | 798 | .mm_m64, |
| 788 | .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128, | 799 | .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128, |
| 789 | .ymm_m256, | 800 | .ymm_m256, |
| ... | @@ -821,11 +832,7 @@ pub const Op = enum { | ... | @@ -821,11 +832,7 @@ pub const Op = enum { |
| 821 | /// Given an operand `op` checks if `target` is a subset for the purposes of the encoding. | 832 | /// Given an operand `op` checks if `target` is a subset for the purposes of the encoding. |
| 822 | pub fn isSubset(op: Op, target: Op) bool { | 833 | pub fn isSubset(op: Op, target: Op) bool { |
| 823 | switch (op) { | 834 | switch (op) { |
| 824 | .moffs, .sreg => return op == target, | 835 | .none, .m, .moffs, .sreg => return op == target, |
| 825 | .none => switch (target) { | | |
| 826 | .none => return true, | | |
| 827 | else => return false, | | |
| 828 | }, | | |
| 829 | else => { | 836 | else => { |
| 830 | if (op.isRegister() and target.isRegister()) { | 837 | if (op.isRegister() and target.isRegister()) { |
| 831 | return switch (target.toReg()) { | 838 | return switch (target.toReg()) { |
| ... | @@ -836,6 +843,7 @@ pub const Op = enum { | ... | @@ -836,6 +843,7 @@ pub const Op = enum { |
| 836 | if (op.isMemory() and target.isMemory()) { | 843 | if (op.isMemory() and target.isMemory()) { |
| 837 | switch (target) { | 844 | switch (target) { |
| 838 | .m => return true, | 845 | .m => return true, |
| | 846 | .moffs, .mrip8 => return op == target, |
| 839 | else => return op.memBitSize() == target.memBitSize(), | 847 | else => return op.memBitSize() == target.memBitSize(), |
| 840 | } | 848 | } |
| 841 | } | 849 | } |
| ... | @@ -962,6 +970,10 @@ pub const Feature = enum { | ... | @@ -962,6 +970,10 @@ pub const Feature = enum { |
| 962 | @"pclmul avx", | 970 | @"pclmul avx", |
| 963 | pku, | 971 | pku, |
| 964 | popcnt, | 972 | popcnt, |
| | 973 | prefetch, |
| | 974 | @"prefetchi 64bit", |
| | 975 | prefetchwt1, |
| | 976 | prfchw, |
| 965 | rdrnd, | 977 | rdrnd, |
| 966 | rdseed, | 978 | rdseed, |
| 967 | @"rdpid 32bit", | 979 | @"rdpid 32bit", |
| ... | @@ -1002,7 +1014,7 @@ fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Op | ... | @@ -1002,7 +1014,7 @@ fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Op |
| 1002 | } | 1014 | } |
| 1003 | | 1015 | |
| 1004 | const mnemonic_to_encodings_map = init: { | 1016 | const mnemonic_to_encodings_map = init: { |
| 1005 | @setEvalBranchQuota(5_700); | 1017 | @setEvalBranchQuota(5_800); |
| 1006 | const mnemonic_count = @typeInfo(Mnemonic).@"enum".fields.len; | 1018 | const mnemonic_count = @typeInfo(Mnemonic).@"enum".fields.len; |
| 1007 | var mnemonic_map: [mnemonic_count][]Data = @splat(&.{}); | 1019 | var mnemonic_map: [mnemonic_count][]Data = @splat(&.{}); |
| 1008 | const encodings = @import("encodings.zig"); | 1020 | const encodings = @import("encodings.zig"); |