diff --git a/modules/arch/x86/gen_x86_insn.py b/modules/arch/x86/gen_x86_insn.py index b48f806e..eacb0e51 100755 --- a/modules/arch/x86/gen_x86_insn.py +++ b/modules/arch/x86/gen_x86_insn.py @@ -43,7 +43,8 @@ ordered_cpu_features = [ "FPU", "Cyrix", "AMD", "MMX", "3DNow", "SMM", "SSE", "SSE2", "SSE3", "SVM", "PadLock", "SSSE3", "SSE41", "SSE42", "SSE4a", "SSE5", "AVX", "FMA", "AES", "CLMUL", "MOVBE", "XOP", "FMA4", "F16C", - "FSGSBASE", "RDRAND", "XSAVEOPT", "EPTVPID", "SMX"] + "FSGSBASE", "RDRAND", "XSAVEOPT", "EPTVPID", "SMX", "AVX2", "BMI1", + "BMI2", "INVPCID", "LZCNT"] unordered_cpu_features = ["Priv", "Prot", "Undoc", "Obs"] # Predefined VEX prefix field values @@ -6607,7 +6608,7 @@ add_group("vfma_ps", Operand(type="SIMDReg", size=256, dest="VEX"), Operand(type="SIMDRM", size=256, relaxed=True, dest="EA")]) -### 128/256b FMA PD(W=1) +### 128/256b FMA PD(W=1) add_group("vfma_pd", cpu=["FMA"], modifiers=["Op2Add"], @@ -7352,6 +7353,115 @@ for sz in (16, 32, 64): Operand(type="Reg", size=sz, dest="Spare")]) add_insn("movbe", "movbe") +##################################################################### +# Intel advanced bit manipulations (BMI1/2) +##################################################################### + +add_insn("tzcnt", "cnt", modifiers=[0xBC], cpu=["BMI1"]) +# LZCNT is present as AMD ext + +for sfx, sz in zip("wlq", [32, 64]): + add_group("vex_gpr_ndd_rm_0F38_regext", + suffix=sfx, + modifiers=["PreAdd", "Op2Add", "SpAdd" ], + opersize=sz, + prefix=0x00, + opcode=[0x0F, 0x38, 0x00], + vex=0, ## VEX.L=0 + operands=[Operand(type="Reg", size=sz, dest="VEX"), + Operand(type="RM", size=sz, relaxed=True, dest="EA")]) + + +add_insn("blsr", "vex_gpr_ndd_rm_0F38_regext", modifiers=[0x00, 0xF3, 1], + cpu=["BMI1"]) +add_insn("blsmsk", "vex_gpr_ndd_rm_0F38_regext", modifiers=[0x00, 0xF3, 2], + cpu=["BMI1"]) +add_insn("blsi", "vex_gpr_ndd_rm_0F38_regext", modifiers=[0x00, 0xF3, 3], + cpu=["BMI1"]) + +for sfx, sz in zip("wlq", [32, 64]): + add_group("vex_gpr_reg_rm_0F_imm8", + suffix=sfx, + modifiers=["PreAdd", "Op1Add", "Op2Add"], + opersize=sz, + prefix=0x00, + opcode=[0x0F, 0x00, 0x00], + vex=0, ## VEX.L=0 + operands=[Operand(type="Reg", size=sz, dest="Spare"), + Operand(type="RM", size=sz, relaxed=True, dest="EA"), + Operand(type="Imm", size=8, relaxed=True, dest="Imm")]) + +add_insn("rorx", "vex_gpr_reg_rm_0F_imm8", modifiers=[0xF2, 0x3A, 0xF0], + cpu=["BMI2"]) + +for sfx, sz in zip("lq", [32, 64]): # no 16-bit forms + add_group("vex_gpr_reg_nds_rm_0F", + suffix=sfx, + modifiers=["PreAdd", "Op1Add", "Op2Add"], + opersize=sz, + prefix=0x00, + opcode=[0x0F, 0x00, 0x00], + vex=0, + operands=[Operand(type="Reg", size=sz, dest="Spare"), + Operand(type="Reg", size=sz, dest="VEX"), + Operand(type="RM", size=sz, relaxed=True, dest="EA")]) + +add_insn("andn", "vex_gpr_reg_nds_rm_0F", modifiers=[0x00, 0x38, 0xF2], + cpu=["BMI1"]) + +add_insn("pdep", "vex_gpr_reg_nds_rm_0F", modifiers=[0xF2, 0x38, 0xF5], + cpu=["BMI2"]) +add_insn("pext", "vex_gpr_reg_nds_rm_0F", modifiers=[0xF3, 0x38, 0xF5], + cpu=["BMI2"]) + +for sfx, sz in zip("lq", [32, 64]): # no 16-bit forms + add_group("vex_gpr_reg_rm_nds_0F", + suffix=sfx, + modifiers=["PreAdd", "Op1Add", "Op2Add"], + opersize=sz, + prefix=0x00, + opcode=[0x0F, 0x00, 0x00], + vex=0, + operands=[Operand(type="Reg", size=sz, dest="Spare"), + Operand(type="RM", size=sz, relaxed=True, dest="EA"), + Operand(type="Reg", size=sz, dest="VEX")]) + +add_insn("bzhi", "vex_gpr_reg_rm_nds_0F", modifiers=[0x00, 0x38, 0xF5], + cpu=["BMI2"]) +add_insn("bextr","vex_gpr_reg_rm_nds_0F", modifiers=[0x00, 0x38, 0xF7], + cpu=["BMI1"]) +add_insn("shlx", "vex_gpr_reg_rm_nds_0F", modifiers=[0x66, 0x38, 0xF7], + cpu=["BMI2"]) +add_insn("shrx", "vex_gpr_reg_rm_nds_0F", modifiers=[0xF2, 0x38, 0xF7], + cpu=["BMI2"]) +add_insn("sarx", "vex_gpr_reg_rm_nds_0F", modifiers=[0xF3, 0x38, 0xF7], + cpu=["BMI2"]) + +add_insn("mulx", "vex_gpr_reg_nds_rm_0F", modifiers=[0xF2, 0x38, 0xF6], + cpu=["BMI2"]) + + + +##################################################################### +# Intel INVPCID instruction +##################################################################### +add_group("invpcid", + cpu=["INVPCID", "Priv"], + not64=True, + prefix=0x66, + opcode=[0x0F, 0x38, 0x82], + operands=[Operand(type="Reg", size=32, dest="Spare"), + Operand(type="Mem", size=128, relaxed=True, dest="EA")]) +add_group("invpcid", + cpu=["INVPCID", "Priv"], + only64=True, + def_opersize_64=64, + prefix=0x66, + opcode=[0x0F, 0x38, 0x82], + operands=[Operand(type="Reg", size=64, dest="Spare"), + Operand(type="Mem", size=128, relaxed=True, dest="EA")]) +add_insn("invpcid", "invpcid") + ##################################################################### # AMD 3DNow! instructions ##################################################################### @@ -7400,7 +7510,7 @@ add_insn("syscall", "twobyte", modifiers=[0x0F, 0x05], cpu=["686", "AMD"]) for sfx in [None, "l", "q"]: add_insn("sysret"+(sfx or ""), "twobyte", suffix=sfx, modifiers=[0x0F, 0x07], cpu=["686", "AMD", "Priv"]) -add_insn("lzcnt", "cnt", modifiers=[0xBD], cpu=["686", "AMD"]) +add_insn("lzcnt", "cnt", modifiers=[0xBD], cpu=["LZCNT"]) ##################################################################### # AMD x86-64 extensions diff --git a/modules/arch/x86/tests/Makefile.inc b/modules/arch/x86/tests/Makefile.inc index 5ce31e56..fab543b3 100644 --- a/modules/arch/x86/tests/Makefile.inc +++ b/modules/arch/x86/tests/Makefile.inc @@ -29,6 +29,10 @@ EXTRA_DIST += modules/arch/x86/tests/avxcc.asm EXTRA_DIST += modules/arch/x86/tests/avxcc.hex EXTRA_DIST += modules/arch/x86/tests/bittest.asm EXTRA_DIST += modules/arch/x86/tests/bittest.hex +EXTRA_DIST += modules/arch/x86/tests/bmi1.asm +EXTRA_DIST += modules/arch/x86/tests/bmi1.hex +EXTRA_DIST += modules/arch/x86/tests/bmi2.asm +EXTRA_DIST += modules/arch/x86/tests/bmi2.hex EXTRA_DIST += modules/arch/x86/tests/bswap64.asm EXTRA_DIST += modules/arch/x86/tests/bswap64.hex EXTRA_DIST += modules/arch/x86/tests/clmul.asm @@ -79,6 +83,8 @@ EXTRA_DIST += modules/arch/x86/tests/genopcode.hex EXTRA_DIST += modules/arch/x86/tests/imm64.asm EXTRA_DIST += modules/arch/x86/tests/imm64.errwarn EXTRA_DIST += modules/arch/x86/tests/imm64.hex +EXTRA_DIST += modules/arch/x86/tests/invpcid.asm +EXTRA_DIST += modules/arch/x86/tests/invpcid.hex EXTRA_DIST += modules/arch/x86/tests/iret.asm EXTRA_DIST += modules/arch/x86/tests/iret.hex EXTRA_DIST += modules/arch/x86/tests/jmp64-1.asm @@ -105,6 +111,8 @@ EXTRA_DIST += modules/arch/x86/tests/loopadsz.asm EXTRA_DIST += modules/arch/x86/tests/loopadsz.hex EXTRA_DIST += modules/arch/x86/tests/lsahf.asm EXTRA_DIST += modules/arch/x86/tests/lsahf.hex +EXTRA_DIST += modules/arch/x86/tests/lzcnt.asm +EXTRA_DIST += modules/arch/x86/tests/lzcnt.hex EXTRA_DIST += modules/arch/x86/tests/mem64-err.asm EXTRA_DIST += modules/arch/x86/tests/mem64-err.errwarn EXTRA_DIST += modules/arch/x86/tests/mem64.asm diff --git a/modules/arch/x86/tests/bmi1.asm b/modules/arch/x86/tests/bmi1.asm new file mode 100644 index 00000000..4913a4f8 --- /dev/null +++ b/modules/arch/x86/tests/bmi1.asm @@ -0,0 +1,32 @@ +[bits 64] +andn eax, ebx, ecx ; c4 e2 60 f2 c1 +andn eax, ebx, [0] ; c4 e2 60 f2 04 25 00 00 00 00 +andn rax, rbx, rcx ; c4 e2 e0 f2 c1 +andn rax, rbx, [0] ; c4 e2 e0 f2 04 25 00 00 00 00 + +bextr eax, ebx, ecx ; c4 e2 70 f7 c3 +bextr eax, [0], ecx ; c4 e2 70 f7 04 25 00 00 00 00 +bextr rax, rbx, rcx ; c4 e2 f0 f7 c3 +bextr rax, [0], rcx ; c4 e2 f0 f7 04 25 00 00 00 00 + +blsi eax, ecx ; c4 e2 78 f3 d9 +blsi eax, [0] ; c4 e2 78 f3 1c 25 00 00 00 00 +blsi rax, rcx ; c4 e2 f8 f3 d9 +blsi rax, [0] ; c4 e2 f8 f3 1c 25 00 00 00 00 + +blsmsk eax, ecx ; c4 e2 78 f3 d1 +blsmsk eax, [0] ; c4 e2 78 f3 14 25 00 00 00 00 +blsmsk rax, rcx ; c4 e2 f8 f3 d1 +blsmsk rax, [0] ; c4 e2 f8 f3 14 25 00 00 00 00 + +blsr eax, ecx ; c4 e2 78 f3 c9 +blsr eax, [0] ; c4 e2 78 f3 0c 25 00 00 00 00 +blsr rax, rcx ; c4 e2 f8 f3 c9 +blsr rax, [0] ; c4 e2 f8 f3 0c 25 00 00 00 00 + +tzcnt ax, bx ; 66 f3 0f bc c3 +tzcnt ax, [0] ; 66 f3 0f bc 04 25 00 00 00 00 +tzcnt eax, ebx ; f3 0f bc c3 +tzcnt eax, [0] ; f3 0f bc 04 25 00 00 00 00 +tzcnt rax, rbx ; f3 48 0f bc c3 +tzcnt rax, [0] ; f3 48 0f bc 04 25 00 00 00 00 diff --git a/modules/arch/x86/tests/bmi1.hex b/modules/arch/x86/tests/bmi1.hex new file mode 100644 index 00000000..fc692cde --- /dev/null +++ b/modules/arch/x86/tests/bmi1.hex @@ -0,0 +1,193 @@ +c4 +e2 +60 +f2 +c1 +c4 +e2 +60 +f2 +04 +25 +00 +00 +00 +00 +c4 +e2 +e0 +f2 +c1 +c4 +e2 +e0 +f2 +04 +25 +00 +00 +00 +00 +c4 +e2 +70 +f7 +c3 +c4 +e2 +70 +f7 +04 +25 +00 +00 +00 +00 +c4 +e2 +f0 +f7 +c3 +c4 +e2 +f0 +f7 +04 +25 +00 +00 +00 +00 +c4 +e2 +78 +f3 +d9 +c4 +e2 +78 +f3 +1c +25 +00 +00 +00 +00 +c4 +e2 +f8 +f3 +d9 +c4 +e2 +f8 +f3 +1c +25 +00 +00 +00 +00 +c4 +e2 +78 +f3 +d1 +c4 +e2 +78 +f3 +14 +25 +00 +00 +00 +00 +c4 +e2 +f8 +f3 +d1 +c4 +e2 +f8 +f3 +14 +25 +00 +00 +00 +00 +c4 +e2 +78 +f3 +c9 +c4 +e2 +78 +f3 +0c +25 +00 +00 +00 +00 +c4 +e2 +f8 +f3 +c9 +c4 +e2 +f8 +f3 +0c +25 +00 +00 +00 +00 +66 +f3 +0f +bc +c3 +66 +f3 +0f +bc +04 +25 +00 +00 +00 +00 +f3 +0f +bc +c3 +f3 +0f +bc +04 +25 +00 +00 +00 +00 +f3 +48 +0f +bc +c3 +f3 +48 +0f +bc +04 +25 +00 +00 +00 +00 diff --git a/modules/arch/x86/tests/bmi2.asm b/modules/arch/x86/tests/bmi2.asm new file mode 100644 index 00000000..d19d7f3a --- /dev/null +++ b/modules/arch/x86/tests/bmi2.asm @@ -0,0 +1,40 @@ +[bits 64] +bzhi eax, ebx, ecx ; c4 e2 70 f5 c3 +bzhi eax, [0], ecx ; c4 e2 70 f5 04 25 00 00 00 00 +bzhi rax, rbx, rcx ; c4 e2 f0 f5 c3 +bzhi rax, [0], rcx ; c4 e2 f0 f5 04 25 00 00 00 00 + +mulx eax, ebx, ecx ; c4 e2 63 f6 c1 +mulx eax, ebx, [0] ; c4 e2 63 f6 04 25 00 00 00 00 +mulx rax, rbx, rcx ; c4 e2 e3 f6 c1 +mulx rax, rbx, [0] ; c4 e2 e3 f6 04 25 00 00 00 00 + +pdep eax, ebx, ecx ; c4 e2 63 f5 c1 +pdep eax, ebx, [0] ; c4 e2 63 f5 04 25 00 00 00 00 +pdep rax, rbx, rcx ; c4 e2 e3 f5 c1 +pdep rax, rbx, [0] ; c4 e2 e3 f5 04 25 00 00 00 00 + +pext eax, ebx, ecx ; c4 e2 62 f5 c1 +pext eax, ebx, [0] ; c4 e2 62 f5 04 25 00 00 00 00 +pext rax, rbx, rcx ; c4 e2 e2 f5 c1 +pext rax, rbx, [0] ; c4 e2 e2 f5 04 25 00 00 00 00 + +rorx eax, ebx, 3 ; c4 e3 7b f0 c3 03 +rorx eax, [0], 3 ; c4 e3 7b f0 04 25 00 00 00 00 03 +rorx rax, rbx, 3 ; c4 e3 fb f0 c3 03 +rorx rax, [0], 3 ; c4 e3 fb f0 04 25 00 00 00 00 03 + +sarx eax, ebx, ecx ; c4 e2 72 f7 c3 +sarx eax, [0], ecx ; c4 e2 72 f7 04 25 00 00 00 00 +sarx rax, rbx, rcx ; c4 e2 f2 f7 c3 +sarx rax, [0], rcx ; c4 e2 f2 f7 04 25 00 00 00 00 + +shlx eax, ebx, ecx ; c4 e2 71 f7 c3 +shlx eax, [0], ecx ; c4 e2 71 f7 04 25 00 00 00 00 +shlx rax, rbx, rcx ; c4 e2 f1 f7 c3 +shlx rax, [0], rcx ; c4 e2 f1 f7 04 25 00 00 00 00 + +shrx eax, ebx, ecx ; c4 e2 73 f7 c3 +shrx eax, [0], ecx ; c4 e2 73 f7 04 25 00 00 00 00 +shrx rax, rbx, rcx ; c4 e2 f3 f7 c3 +shrx rax, [0], rcx ; c4 e2 f3 f7 04 25 00 00 00 00 diff --git a/modules/arch/x86/tests/bmi2.hex b/modules/arch/x86/tests/bmi2.hex new file mode 100644 index 00000000..c1529729 --- /dev/null +++ b/modules/arch/x86/tests/bmi2.hex @@ -0,0 +1,244 @@ +c4 +e2 +70 +f5 +c3 +c4 +e2 +70 +f5 +04 +25 +00 +00 +00 +00 +c4 +e2 +f0 +f5 +c3 +c4 +e2 +f0 +f5 +04 +25 +00 +00 +00 +00 +c4 +e2 +63 +f6 +c1 +c4 +e2 +63 +f6 +04 +25 +00 +00 +00 +00 +c4 +e2 +e3 +f6 +c1 +c4 +e2 +e3 +f6 +04 +25 +00 +00 +00 +00 +c4 +e2 +63 +f5 +c1 +c4 +e2 +63 +f5 +04 +25 +00 +00 +00 +00 +c4 +e2 +e3 +f5 +c1 +c4 +e2 +e3 +f5 +04 +25 +00 +00 +00 +00 +c4 +e2 +62 +f5 +c1 +c4 +e2 +62 +f5 +04 +25 +00 +00 +00 +00 +c4 +e2 +e2 +f5 +c1 +c4 +e2 +e2 +f5 +04 +25 +00 +00 +00 +00 +c4 +e3 +7b +f0 +c3 +03 +c4 +e3 +7b +f0 +04 +25 +00 +00 +00 +00 +03 +c4 +e3 +fb +f0 +c3 +03 +c4 +e3 +fb +f0 +04 +25 +00 +00 +00 +00 +03 +c4 +e2 +72 +f7 +c3 +c4 +e2 +72 +f7 +04 +25 +00 +00 +00 +00 +c4 +e2 +f2 +f7 +c3 +c4 +e2 +f2 +f7 +04 +25 +00 +00 +00 +00 +c4 +e2 +71 +f7 +c3 +c4 +e2 +71 +f7 +04 +25 +00 +00 +00 +00 +c4 +e2 +f1 +f7 +c3 +c4 +e2 +f1 +f7 +04 +25 +00 +00 +00 +00 +c4 +e2 +73 +f7 +c3 +c4 +e2 +73 +f7 +04 +25 +00 +00 +00 +00 +c4 +e2 +f3 +f7 +c3 +c4 +e2 +f3 +f7 +04 +25 +00 +00 +00 +00 diff --git a/modules/arch/x86/tests/invpcid.asm b/modules/arch/x86/tests/invpcid.asm new file mode 100644 index 00000000..90f517aa --- /dev/null +++ b/modules/arch/x86/tests/invpcid.asm @@ -0,0 +1,6 @@ +[bits 32] +invpcid eax, oword [0] ; 66 0f 38 82 05 00 00 00 00 + +[bits 64] +invpcid rax, oword [0] ; 66 0f 38 82 04 25 00 00 00 00 + diff --git a/modules/arch/x86/tests/invpcid.hex b/modules/arch/x86/tests/invpcid.hex new file mode 100644 index 00000000..cfc8726b --- /dev/null +++ b/modules/arch/x86/tests/invpcid.hex @@ -0,0 +1,19 @@ +66 +0f +38 +82 +05 +00 +00 +00 +00 +66 +0f +38 +82 +04 +25 +00 +00 +00 +00 diff --git a/modules/arch/x86/tests/lzcnt.asm b/modules/arch/x86/tests/lzcnt.asm new file mode 100644 index 00000000..4e545dfa --- /dev/null +++ b/modules/arch/x86/tests/lzcnt.asm @@ -0,0 +1,8 @@ +[bits 64] + +lzcnt ax, bx ; 66 f3 0f bd c3 +lzcnt ax, [0] ; 66 f3 0f bd 04 25 00 00 00 00 +lzcnt eax, ebx ; f3 0f bd c3 +lzcnt eax, [0] ; f3 0f bd 04 25 00 00 00 00 +lzcnt rax, rbx ; f3 48 0f bd c3 +lzcnt rax, [0] ; f3 48 0f bd 04 25 00 00 00 00 diff --git a/modules/arch/x86/tests/lzcnt.hex b/modules/arch/x86/tests/lzcnt.hex new file mode 100644 index 00000000..ed14eb0e --- /dev/null +++ b/modules/arch/x86/tests/lzcnt.hex @@ -0,0 +1,43 @@ +66 +f3 +0f +bd +c3 +66 +f3 +0f +bd +04 +25 +00 +00 +00 +00 +f3 +0f +bd +c3 +f3 +0f +bd +04 +25 +00 +00 +00 +00 +f3 +48 +0f +bd +c3 +f3 +48 +0f +bd +04 +25 +00 +00 +00 +00 diff --git a/modules/arch/x86/x86arch.h b/modules/arch/x86/x86arch.h index d1ba2325..8e7caf82 100644 --- a/modules/arch/x86/x86arch.h +++ b/modules/arch/x86/x86arch.h @@ -78,6 +78,11 @@ #define CPU_XSAVEOPT 44 /* Intel XSAVEOPT instruction */ #define CPU_EPTVPID 45 /* Intel INVEPT, INVVPID instructions */ #define CPU_SMX 46 /* Intel SMX instruction (GETSEC) */ +#define CPU_AVX2 47 /* Intel AVX2 instructions */ +#define CPU_BMI1 48 /* Intel BMI1 instructions */ +#define CPU_BMI2 49 /* Intel BMI2 instructions */ +#define CPU_INVPCID 50 /* Intel INVPCID instruction */ +#define CPU_LZCNT 51 /* Intel LZCNT instruction */ enum x86_parser_type { X86_PARSER_NASM = 0, diff --git a/modules/arch/x86/x86cpu.gperf b/modules/arch/x86/x86cpu.gperf index e83be09a..8939d636 100644 --- a/modules/arch/x86/x86cpu.gperf +++ b/modules/arch/x86/x86cpu.gperf @@ -389,6 +389,16 @@ eptvpid, x86_cpu_set, CPU_EPTVPID noeptvpid, x86_cpu_clear, CPU_EPTVPID smx, x86_cpu_set, CPU_SMX nosmx, x86_cpu_clear, CPU_SMX +avx2, x86_cpu_set, CPU_AVX2 +noavx2, x86_cpu_clear, CPU_AVX2 +bmi1, x86_cpu_set, CPU_BMI1 +nobmi1, x86_cpu_clear, CPU_BMI1 +bmi2, x86_cpu_set, CPU_BMI2 +nobmi2, x86_cpu_clear, CPU_BMI2 +invpcid, x86_cpu_set, CPU_INVPCID +noinvpcid, x86_cpu_clear, CPU_INVPCID +lzcnt, x86_cpu_set, CPU_LZCNT +nolzcnt, x86_cpu_clear, CPU_LZCNT # Change NOP patterns basicnop, x86_nop, X86_NOP_BASIC intelnop, x86_nop, X86_NOP_INTEL