diff --git a/.gitignore b/.gitignore index 76b6fab..d581f7d 100644 --- a/.gitignore +++ b/.gitignore @@ -64,6 +64,8 @@ bdshemu_fuzz/out-32 bdshemu_fuzz/out-64 docs/build libbddisasm.pc -build* +build/ .vscode disasmtool_lix/_build +rsbddisasm/target +rsbddisasm/Cargo.lock diff --git a/rsbddisasm/Cargo.toml b/rsbddisasm/Cargo.toml new file mode 100644 index 0000000..46a2f49 --- /dev/null +++ b/rsbddisasm/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] + +members = [ + "bddisasm-sys", + "bddisasm", +] diff --git a/rsbddisasm/README.md b/rsbddisasm/README.md new file mode 100644 index 0000000..a74141e --- /dev/null +++ b/rsbddisasm/README.md @@ -0,0 +1,26 @@ +# bddisasm Rust bindings + +## Build + +Run `cargo build` or `cargo build --release`. + +## Directory structure + +### bddisasm-sys + +This crate uses the [*-sys crate convention](https://doc.rust-lang.org/cargo/reference/build-scripts.html#-sys-packages) and links with `libbddisasm`, exposing a raw, low-level, interface. + +### bddisasm + +This crate aims to offer a higher-level interface over [bddisasm-sys](#bddisasm-sys). It is currently held back by the fact that I don't really know Rust. + +Parts of it are auto-generated, with slight manual changes (for example, the `Mnemonic` enum and related functions). + +#### TODO + +- [ ] encode registers, not just the register index (for example, instead of `Gpr` we should have `Gpr::Rax`, `Gpr::Eax`, etc) +- [ ] more documentation for the `operand` module, with examples on how to work wit h each operand type +- [ ] more examples for `cpuid` +- [ ] more examples for `cpu_modes` +- [ ] an API to check if an instruction is supported with certain CPU modes on or off (currently a user has to manually check the `CpuModes` structure) +- [ ] implement `Display` for more types (especially those in `operand`) diff --git a/rsbddisasm/bddisasm-sys/Cargo.toml b/rsbddisasm/bddisasm-sys/Cargo.toml new file mode 100644 index 0000000..547410f --- /dev/null +++ b/rsbddisasm/bddisasm-sys/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "bddisasm-sys" +version = "0.1.0" +authors = ["Cristi Anichitei "] +edition = "2018" +links = "bddisasm" +build = "build.rs" +license = "Apache-2.0" +repository = "https://github.com/bitdefender/bddisasm" +documentation = "https://docs.rs/bddisasm-sys" +description = """ +Bindings to bddisasm instruction decoder library +""" +categories = ["external-ffi-bindings", "hardware-support"] +keywords = ["disassembler", "decoder", "x86", "amd64", "x86_64", "bindings"] + +[lib] +name = "bddisasm_sys" +path = "src/lib.rs" + +[dependencies] + +[build-dependencies] +bindgen = "0.59.1" +cc = "1.0.70" diff --git a/rsbddisasm/bddisasm-sys/LICENSE b/rsbddisasm/bddisasm-sys/LICENSE new file mode 120000 index 0000000..30cff74 --- /dev/null +++ b/rsbddisasm/bddisasm-sys/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/rsbddisasm/bddisasm-sys/build.rs b/rsbddisasm/bddisasm-sys/build.rs new file mode 100644 index 0000000..9be3215 --- /dev/null +++ b/rsbddisasm/bddisasm-sys/build.rs @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ +use std::env; +use std::path::PathBuf; + +fn main() { + println!("cargo:rerun-if-changed=csrc"); + + cc::Build::new() + .file("csrc/bddisasm/bddisasm.c") + .file("csrc/bddisasm/bdformat.c") + .file("csrc/bddisasm/crt.c") + .include("csrc/bddisasm/include") + .include("csrc/inc") + .define("BDDISASM_HAS_VSNPRINTF", Some("1")) + .define("BDDISASM_HAS_MEMSET", Some("1")) + .compile("bddisasm"); + + let bindings = bindgen::Builder::default() + .header("csrc/bddisasm_wrapper.h") + .allowlist_function("Nd.*") + .allowlist_type("ND.*") + .allowlist_var("ND.*") + .rustified_enum(".*") + .impl_debug(true) + .generate_comments(false) + .parse_callbacks(Box::new(bindgen::CargoCallbacks)) + .generate() + .expect("Unable to generate bindings"); + + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); + + println!("cargo:rustc-link-lib=static=bddisasm"); +} diff --git a/rsbddisasm/bddisasm-sys/csrc/bddisasm b/rsbddisasm/bddisasm-sys/csrc/bddisasm new file mode 120000 index 0000000..00ffb24 --- /dev/null +++ b/rsbddisasm/bddisasm-sys/csrc/bddisasm @@ -0,0 +1 @@ +../../../bddisasm \ No newline at end of file diff --git a/rsbddisasm/bddisasm-sys/csrc/bddisasm_wrapper.h b/rsbddisasm/bddisasm-sys/csrc/bddisasm_wrapper.h new file mode 100644 index 0000000..a79b5d1 --- /dev/null +++ b/rsbddisasm/bddisasm-sys/csrc/bddisasm_wrapper.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2021 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "inc/bddisasm.h" diff --git a/rsbddisasm/bddisasm-sys/csrc/inc b/rsbddisasm/bddisasm-sys/csrc/inc new file mode 120000 index 0000000..3e5b14c --- /dev/null +++ b/rsbddisasm/bddisasm-sys/csrc/inc @@ -0,0 +1 @@ +../../../inc \ No newline at end of file diff --git a/rsbddisasm/bddisasm-sys/src/lib.rs b/rsbddisasm/bddisasm-sys/src/lib.rs new file mode 100644 index 0000000..ecc197f --- /dev/null +++ b/rsbddisasm/bddisasm-sys/src/lib.rs @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2021 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(deref_nullptr)] // See https://github.com/rust-lang/rust-bindgen/issues/1651 +#![allow(clippy::all)] +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + +#[cfg(test)] +mod tests { + use super::*; + use ::std::os::raw::c_char; + use std::mem; + + #[test] + fn get_version() { + let mut major: u32 = 0; + let mut minor: u32 = 0; + let mut revision: u32 = 0; + let mut build_date: *mut c_char = std::ptr::null_mut(); + let mut build_time: *mut c_char = std::ptr::null_mut(); + + unsafe { + NdGetVersion( + &mut major, + &mut minor, + &mut revision, + &mut build_date, + &mut build_time, + ); + } + + println!("major: {} minor: {} rev: {}", major, minor, revision); + + let build_date = unsafe { std::ffi::CStr::from_ptr(build_date) }; + let build_date = build_date.to_str().unwrap().to_string(); + let build_time = unsafe { std::ffi::CStr::from_ptr(build_time) }; + let build_time = build_time.to_str().unwrap().to_string(); + println!("Build date: {} build time: {}", build_date, build_time); + + // There are no other asserts in this test. Enforcing a known minor version is not worth it, we mainly want to + // see that `NdGetVersion` works. + assert_eq!(major, 1); + } + + fn do_decode(code: &[u8]) -> (INSTRUX, NDSTATUS) { + let mut instrux: mem::MaybeUninit = mem::MaybeUninit::uninit(); + let instrux = instrux.as_mut_ptr(); + + let status = unsafe { + NdDecodeEx( + instrux, + code.as_ptr(), + code.len() as u64, + ND_CODE_32 as u8, + ND_DATA_32 as u8, + ) + }; + + (unsafe { *instrux }, status) + } + + #[test] + fn decode() { + let code = vec![0x90]; + let (instrux, status) = do_decode(&code); + + assert_eq!(status, 0, "Failed to decode instruction {:#x?}", code); + assert_eq!( + unsafe { instrux.__bindgen_anon_2.Instruction }, + _ND_INS_CLASS::ND_INS_NOP + ); + } + + #[test] + fn format() { + let code = vec![0x89, 0x29]; + let (instrux, status) = do_decode(&code); + + assert_eq!(status, 0, "Failed to decode instruction {:#x?}", code); + + let mut buffer: [i8; ND_MIN_BUF_SIZE as usize] = [0; ND_MIN_BUF_SIZE as usize]; + let status = unsafe { NdToText(&instrux, 0, ND_MIN_BUF_SIZE, buffer.as_mut_ptr()) }; + assert_eq!(status, 0, "Failed to decode format {:#x?}", code); + + let text = String::from_utf8(buffer.iter().map(|&c| c as u8).collect()).unwrap(); + let text = text.trim_matches(char::from(0)); + assert_eq!(text, "MOV dword ptr [ecx], ebp"); + } +} diff --git a/rsbddisasm/bddisasm/Cargo.toml b/rsbddisasm/bddisasm/Cargo.toml new file mode 100644 index 0000000..c952d1b --- /dev/null +++ b/rsbddisasm/bddisasm/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "bddisasm" +version = "0.1.0" +authors = ["Cristi Anichitei "] +edition = "2018" +license = "Apache-2.0" +readme = "README.md" +repository = "https://github.com/bitdefender/bddisasm" +documentation = "https://docs.rs/bddisasm" +description = """ +Bindings to bddisasm instruction decoder library +""" +categories = ["api-bindings", "hardware-support"] +keywords = ["disassembler", "decoder", "x86", "amd64", "x86_64", "bindings"] + +[dependencies] +bddisasm-sys = { version = "0.1.0", path = "../bddisasm-sys" } diff --git a/rsbddisasm/bddisasm/src/cpu_modes.rs b/rsbddisasm/bddisasm/src/cpu_modes.rs new file mode 100644 index 0000000..3b8a09b --- /dev/null +++ b/rsbddisasm/bddisasm/src/cpu_modes.rs @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2021 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ +//! Offers information about the CPU modes in which an instruction is supported. +//! +//! # Examples +//! +//! ``` +//! # use std::error::Error; +//! # +//! # fn main() -> Result<(), Box> { +//! use bddisasm::decoded_instruction::{DecodedInstruction, DecodeMode, Mnemonic, OperandSize}; +//! +//! // `VMXON qword ptr [rax]` +//! let ins = DecodedInstruction::decode(&[0xf3, 0x0f, 0xc7, 0x30], DecodeMode::Bits64)?; +//! let modes = ins.valid_cpu_modes(); +//! +//! // Check if the instruction is available from user mode +//! if modes.privilege_level.ring3 { +//! println!("Available in user mode"); +//! } else { +//! println!("Not available in user mode"); +//! } +//! +//! # Ok(()) +//! # } + +extern crate bddisasm_sys as ffi; + +// TODO: maybe use something like the `bitflags` crate and have all these as flags? + +/// Privilege levels (rings) in which an instruction is supported. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct PrivilegeLevel { + pub ring0: bool, + pub ring1: bool, + pub ring2: bool, + pub ring3: bool, +} + +/// Operating modes in which an instruction is supported. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct OperatingMode { + /// The instruction is valid in real mode. + pub real: bool, + + /// The instruction is valid in Virtual 8086 mode. + pub v8086: bool, + + /// The instruction is valid in protected mode (32 bit). + pub protected: bool, + + /// The instruction is valid in compatibility mode (32 bit in 64 bit). + pub compat: bool, + + /// The instruction is valid in long mode. + pub long: bool, +} + +/// Special modes - these may be active inside other modes (example: `TSX` in `Long mode`). +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct SpecialModes { + /// The instruction is valid in System Management Mode. + pub smm: bool, + + /// The instruction is valid outside System Management Mode. + pub smm_off: bool, + + /// The instruction is valid in SGX mode. + pub sgx: bool, + + /// The instruction is valid outside SGX mode. + pub sgx_off: bool, + + /// The instruction is valid in transactional regions. + pub tsx: bool, + + /// The instruction is valid in transactional regions. + pub tsx_off: bool, +} + +/// VMX mode - they engulf all the other modes. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct VmxMode { + /// The instruction is valid in VMX root mode. + pub root: bool, + + /// The instruction is valid in VMX non root mode. + pub non_root: bool, + + /// The instruction is valid in VMX root SEAM. + pub root_seam: bool, + + /// The instruction is valid in VMX non-root SEAM. + pub non_root_seam: bool, + + /// The instruction is valid outside VMX operation. + pub off: bool, +} + +/// Indicates in which modes the instruction is valid in +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct CpuModes { + pub privilege_level: PrivilegeLevel, + pub operating_mode: OperatingMode, + pub special_modes: SpecialModes, + pub vmx: VmxMode, +} + +#[doc(hidden)] +impl From for CpuModes { + fn from(raw: ffi::ND_VALID_MODES) -> CpuModes { + let raw = unsafe { raw.__bindgen_anon_1 }; + + CpuModes { + privilege_level: PrivilegeLevel { + ring0: raw.Ring0() != 0, + ring1: raw.Ring1() != 0, + ring2: raw.Ring2() != 0, + ring3: raw.Ring3() != 0, + }, + operating_mode: OperatingMode { + real: raw.Real() != 0, + v8086: raw.V8086() != 0, + protected: raw.Protected() != 0, + compat: raw.Compat() != 0, + long: raw.Long() != 0, + }, + special_modes: SpecialModes { + smm: raw.Smm() != 0, + smm_off: raw.SmmOff() != 0, + sgx: raw.Sgx() != 0, + sgx_off: raw.SgxOff() != 0, + tsx: raw.Tsx() != 0, + tsx_off: raw.TsxOff() != 0, + }, + vmx: VmxMode { + root: raw.VmxRoot() != 0, + non_root: raw.VmxNonRoot() != 0, + root_seam: raw.VmxRootSeam() != 0, + non_root_seam: raw.VmxNonRootSeam() != 0, + off: raw.VmxOff() != 0, + }, + } + } +} diff --git a/rsbddisasm/bddisasm/src/cpuid.rs b/rsbddisasm/bddisasm/src/cpuid.rs new file mode 100644 index 0000000..cacce5f --- /dev/null +++ b/rsbddisasm/bddisasm/src/cpuid.rs @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ +//! CPUID information used to check if an instruction is supported on a CPU or not. +//! +//! # Examples +//! +//! ``` +//! # use std::error::Error; +//! # +//! # fn test() -> Option<()> { +//! use bddisasm::decoded_instruction::{DecodedInstruction, DecodeMode}; +//! +//! // `ENCLS` +//! let ins = DecodedInstruction::decode(&[0x0f, 0x01, 0xcf], DecodeMode::Bits64).ok()?; +//! let cpuid = ins.cpuid()?; +//! println!("Leaf: {}", cpuid.leaf); +//! match cpuid.sub_leaf { +//! Some(sub_leaf) => println!("Sub-leaf: {}", sub_leaf), +//! None => println!("Sub-leaf: None"), +//! } +//! println!("Register to check: {} Bit: {}", cpuid.register, cpuid.bit); +//! +//! # Some(()) +//! # } + +extern crate bddisasm_sys as ffi; + +use std::fmt; + +/// Describes the CPUID leaf, sub-leaf, register & bit that indicate whether an instruction is supported or not. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct Cpuid { + /// CPUID leaf. + pub leaf: u32, + + /// CPUID sub-leaf. + pub sub_leaf: Option, + + /// The register that contains information regarding the instruction. + pub register: u8, + + /// Bit inside the register that indicates whether the instruction is present. + pub bit: u64, +} + +impl fmt::Display for Cpuid { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.sub_leaf { + Some(sub_leaf) => write!( + f, + "leaf: {:#x} sub-leaf: {:#x} register: {} bit to test: {:#x}", + self.leaf, sub_leaf, self.register, self.bit + ), + None => write!( + f, + "leaf: {:#x} sub-leaf: - register: {} bit to test: {:#x}", + self.leaf, self.register, self.bit + ), + } + } +} diff --git a/rsbddisasm/bddisasm/src/decode_error.rs b/rsbddisasm/bddisasm/src/decode_error.rs new file mode 100644 index 0000000..713de56 --- /dev/null +++ b/rsbddisasm/bddisasm/src/decode_error.rs @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2021 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ +//! Errors that can be encountered when decoding an instruction or when trying to get details about a decoded +//! instruction. +//! +//! # Notes +//! +//! All error codes that can be returned by `bddisasm-sys` are encapsulated in the [DecodeError](DecodeError) enum. +//! However, some of these are unlikely to be encountered when using this crate (for example, +//! [BufferOverflow](DecodeError::BufferOverflow)) which indicates that a buffer passed to the `bddisasm` C library is +//! not large enough. +//! +//! Other errors, such as [UnknownStatus](DecodeError::UnknownStatus) or +//! [UnknownInstruction](DecodeError::UnknownInstruction) are used to indicate that this crate is out of sync with +//! `bddisasm-sys`, which also should never happen. + +extern crate bddisasm_sys as ffi; + +use std::error::Error; +use std::fmt; + +/// Holds all the possible errors that can be encountered by the decoder. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum DecodeError { + /// The underlying bddisasm status is not known. The inner value holds the status as it was returned by bddisasm. + /// + /// This usually means that this library is out of sync with bddisasm-sys and is not aware that a new error status + /// was added. + UnknownStatus(u32), + + /// The instruction class returned by bddisasm is not known. The inner value holds the instruction class as it was + /// returned by bddisasm. + /// + /// This usually means that this library is out of sync with bddisasm-sys and is not aware that a new instruction + /// class was added. + UnknownInstruction(u32), + + /// The provided input buffer is too small and does not contain a valid instruction. + BufferTooSmall, + + /// Invalid encoding/instruction. + InvalidEncoding, + + /// Instruction exceeds the maximum 15 bytes. + InstructionTooLong, + + /// Invalid prefix sequence is present. + InvalidPrefixSequence, + + /// The instruction uses an invalid register. + InvalidRegisterInInstruction, + + /// XOP is present, but also a legacy prefix. + XopWithPrefix, + + /// VEX is present, but also a legacy prefix. + VexWithPrefix, + + /// EVEX is present, but also a legacy prefix. + EvexWithPrefix, + + /// Invalid encoding/instruction. + InvalidEncodingInMode, + + /// Invalid usage of LOCK. + BadLockPrefix, + + /// An attempt to load the CS register. + CsLoad, + + /// 0x66 prefix is not accepted. + Prefix66NotAccepted, + + /// 16 bit addressing mode not supported. + AddressingNotSupported16Bit, + + /// RIP-relative addressing not supported. + RipRelAddressingNotSupported, + + /// Instruction uses VSIB, but SIB is not present. + VsibWithoutSib, + + /// VSIB addressing, same vector reg used more than once. + InvalidVsibRegs, + + /// VEX.VVVV field must be zero. + VexVvvvMustBeZero, + + /// Masking is not supported. + MaskNotSupported, + + /// Masking is mandatory. + MaskRequired, + + /// Embedded rounding/SAE not supported. + ErSaeNotSupported, + + /// Zeroing not supported. + ZeroingNotSupported, + + /// Zeroing on memory. + ZeroingOnMemory, + + /// Zeroing without masking. + ZeroingNoMask, + + /// Broadcast not supported. + BroadcastNotSupported, + + /// EVEX.V' field must be one (negated 0). + BadEvexVPrime, + + /// EVEX.L'L field is invalid for the instruction. + BadEvexLl, + + /// Instruction uses SIBMEM, but SIB is not present. + SibmemWithoutSib, + + /// Tile registers are not unique. + InvalidTileRegs, + + /// Destination register is not unique (used as src). + InvalidDestRegs, + + /// An invalid parameter was provided. + InvalidParameter, + + /// The INSTRUX contains unexpected values. + InvalidInstrux, + + /// Not enough space is available. + BufferOverflow, + + /// Internal library error. + InternalError, +} + +impl fmt::Display for DecodeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + DecodeError::UnknownStatus(value) => write!(f, "unknown status: {:#x}", value), + DecodeError::UnknownInstruction(value) => { + write!(f, "unknown instruction: {:#x}", value) + } + DecodeError::BufferTooSmall => write!(f, "the provided input buffer is too small"), + DecodeError::InvalidEncoding => write!(f, "invalid encoding/instruction"), + DecodeError::InstructionTooLong => { + write!(f, "instruction exceeds the maximum 15 bytes") + } + DecodeError::InvalidPrefixSequence => write!(f, "invalid prefix sequence is present"), + DecodeError::InvalidRegisterInInstruction => { + write!(f, "the instruction uses an invalid register") + } + DecodeError::XopWithPrefix => write!(f, "XOP is present, but also a legacy prefix"), + DecodeError::VexWithPrefix => write!(f, "VEX is present, but also a legacy prefix"), + DecodeError::EvexWithPrefix => write!(f, "EVEX is present, but also a legacy prefix"), + DecodeError::InvalidEncodingInMode => write!(f, "invalid encoding/instruction"), + DecodeError::BadLockPrefix => write!(f, "invalid usage of LOCK"), + DecodeError::CsLoad => write!(f, "an attempt to load the CS register"), + DecodeError::Prefix66NotAccepted => write!(f, "0x66 prefix is not accepted"), + DecodeError::AddressingNotSupported16Bit => { + write!(f, "16 bit addressing mode not supported") + } + DecodeError::RipRelAddressingNotSupported => { + write!(f, "RIP-relative addressing not supported") + } + DecodeError::VsibWithoutSib => { + write!(f, "instruction uses VSIB, but SIB is not present") + } + DecodeError::InvalidVsibRegs => { + write!( + f, + "VSIB addressing with the same vector register used more than once" + ) + } + DecodeError::VexVvvvMustBeZero => write!(f, "VEX.VVVV field must be zero"), + DecodeError::MaskNotSupported => write!(f, "masking is not supported"), + DecodeError::MaskRequired => write!(f, "masking is mandatory"), + DecodeError::ErSaeNotSupported => write!(f, "embedded rounding/SAE not supported"), + DecodeError::ZeroingNotSupported => write!(f, "zeroing not supported"), + DecodeError::ZeroingOnMemory => write!(f, "zeroing on memory"), + DecodeError::ZeroingNoMask => write!(f, "zeroing without masking"), + DecodeError::BroadcastNotSupported => write!(f, "broadcast not supported"), + DecodeError::BadEvexVPrime => write!(f, "EVEX.V' field must be one (negated 0)"), + DecodeError::BadEvexLl => write!(f, "EVEX.L'L field is invalid for the instruction"), + DecodeError::SibmemWithoutSib => { + write!(f, "instruction uses SIBMEM, but SIB is not present") + } + DecodeError::InvalidTileRegs => write!(f, "tile registers are not unique"), + DecodeError::InvalidDestRegs => { + write!(f, "destination register is not unique (used as src)") + } + DecodeError::InvalidParameter => write!(f, "an invalid parameter was provided"), + DecodeError::InvalidInstrux => { + write!(f, "the INSTRUX structure contains unexpected values") + } + DecodeError::BufferOverflow => { + write!(f, "not enough space is available to format instruction") + } + DecodeError::InternalError => write!(f, "internal error"), + } + } +} + +impl Error for DecodeError {} + +pub(crate) fn status_to_error(status: ffi::NDSTATUS) -> Result<(), DecodeError> { + if status == ffi::ND_STATUS_SUCCESS || status == ffi::ND_STATUS_HINT_OPERAND_NOT_USED { + Ok(()) + } else { + match status { + ffi::ND_STATUS_BUFFER_TOO_SMALL => Err(DecodeError::BufferTooSmall), + ffi::ND_STATUS_INVALID_ENCODING => Err(DecodeError::InvalidEncoding), + ffi::ND_STATUS_INSTRUCTION_TOO_LONG => Err(DecodeError::InstructionTooLong), + ffi::ND_STATUS_INVALID_PREFIX_SEQUENCE => Err(DecodeError::InvalidPrefixSequence), + ffi::ND_STATUS_INVALID_REGISTER_IN_INSTRUCTION => { + Err(DecodeError::InvalidRegisterInInstruction) + } + ffi::ND_STATUS_XOP_WITH_PREFIX => Err(DecodeError::XopWithPrefix), + ffi::ND_STATUS_VEX_WITH_PREFIX => Err(DecodeError::VexWithPrefix), + ffi::ND_STATUS_EVEX_WITH_PREFIX => Err(DecodeError::EvexWithPrefix), + ffi::ND_STATUS_INVALID_ENCODING_IN_MODE => Err(DecodeError::InvalidEncodingInMode), + ffi::ND_STATUS_BAD_LOCK_PREFIX => Err(DecodeError::BadLockPrefix), + ffi::ND_STATUS_CS_LOAD => Err(DecodeError::CsLoad), + ffi::ND_STATUS_66_NOT_ACCEPTED => Err(DecodeError::Prefix66NotAccepted), + ffi::ND_STATUS_16_BIT_ADDRESSING_NOT_SUPPORTED => { + Err(DecodeError::AddressingNotSupported16Bit) + } + ffi::ND_STATUS_RIP_REL_ADDRESSING_NOT_SUPPORTED => { + Err(DecodeError::RipRelAddressingNotSupported) + } + ffi::ND_STATUS_VSIB_WITHOUT_SIB => Err(DecodeError::VsibWithoutSib), + ffi::ND_STATUS_INVALID_VSIB_REGS => Err(DecodeError::InvalidVsibRegs), + ffi::ND_STATUS_VEX_VVVV_MUST_BE_ZERO => Err(DecodeError::VexVvvvMustBeZero), + ffi::ND_STATUS_MASK_NOT_SUPPORTED => Err(DecodeError::MaskNotSupported), + ffi::ND_STATUS_MASK_REQUIRED => Err(DecodeError::MaskRequired), + ffi::ND_STATUS_ER_SAE_NOT_SUPPORTED => Err(DecodeError::ErSaeNotSupported), + ffi::ND_STATUS_ZEROING_NOT_SUPPORTED => Err(DecodeError::ZeroingNotSupported), + ffi::ND_STATUS_ZEROING_ON_MEMORY => Err(DecodeError::ZeroingOnMemory), + ffi::ND_STATUS_ZEROING_NO_MASK => Err(DecodeError::ZeroingNoMask), + ffi::ND_STATUS_BROADCAST_NOT_SUPPORTED => Err(DecodeError::BroadcastNotSupported), + ffi::ND_STATUS_BAD_EVEX_V_PRIME => Err(DecodeError::BadEvexVPrime), + ffi::ND_STATUS_BAD_EVEX_LL => Err(DecodeError::BadEvexLl), + ffi::ND_STATUS_SIBMEM_WITHOUT_SIB => Err(DecodeError::SibmemWithoutSib), + ffi::ND_STATUS_INVALID_TILE_REGS => Err(DecodeError::InvalidTileRegs), + ffi::ND_STATUS_INVALID_DEST_REGS => Err(DecodeError::InvalidDestRegs), + ffi::ND_STATUS_INVALID_PARAMETER => Err(DecodeError::InvalidParameter), + ffi::ND_STATUS_INVALID_INSTRUX => Err(DecodeError::InvalidInstrux), + ffi::ND_STATUS_BUFFER_OVERFLOW => Err(DecodeError::BufferOverflow), + ffi::ND_STATUS_INTERNAL_ERROR => Err(DecodeError::InternalError), + _ => Err(DecodeError::UnknownStatus(status)), + } + } +} diff --git a/rsbddisasm/bddisasm/src/decoded_instruction.rs b/rsbddisasm/bddisasm/src/decoded_instruction.rs new file mode 100644 index 0000000..6f2541d --- /dev/null +++ b/rsbddisasm/bddisasm/src/decoded_instruction.rs @@ -0,0 +1,1538 @@ +/* + * Copyright (c) 2021 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ +//! Decodes instructions. + +extern crate bddisasm_sys as ffi; + +pub use crate::cpu_modes::CpuModes; +pub use crate::cpuid::Cpuid; +pub use crate::decode_error::DecodeError; +pub use crate::fpu_flags::FpuFlags; +pub use crate::instruction_category::Category; +pub use crate::isa_set::IsaSet; +pub use crate::mnemonic::Mnemonic; +pub use crate::operand; +pub use crate::operand::{OpAccess, OpAddr}; +pub use crate::rflags; +pub use crate::tuple::Tuple; + +use crate::rflags::flags_raw; + +use crate::decode_error; + +use std::fmt; +use std::mem; + +use std::convert::TryFrom; + +/// Represents a succesfull instruction decoding, or failure. +pub type DecodeResult = Result; + +/// The decoding mode to use. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum DecodeMode { + /// 16-bit. + Bits16, + /// 32-bit. + Bits32, + /// 64-bit. + Bits64, +} + +impl From for (u8, u8) { + fn from(mode: DecodeMode) -> Self { + match mode { + DecodeMode::Bits16 => (ffi::ND_CODE_16 as u8, ffi::ND_DATA_16 as u8), + DecodeMode::Bits32 => (ffi::ND_CODE_32 as u8, ffi::ND_DATA_32 as u8), + DecodeMode::Bits64 => (ffi::ND_CODE_64 as u8, ffi::ND_DATA_64 as u8), + } + } +} + +/// Encoding mode. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum EncodingMode { + /// Legacy encoded instruction. + Legacy, + + /// XOP encoded instruction. + Xop, + + /// VEX encoded instruction. + Vex, + + /// EVEX encoded instruction. + Evex, +} + +impl From for EncodingMode { + fn from(value: u32) -> EncodingMode { + match value { + ffi::ND_ENCM_LEGACY => EncodingMode::Legacy, + ffi::ND_ENCM_XOP => EncodingMode::Xop, + ffi::ND_ENCM_VEX => EncodingMode::Vex, + ffi::ND_ENCM_EVEX => EncodingMode::Evex, + _ => panic!("Unexpected encoding mode mode {}", value), + } + } +} + +/// VEX mode. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum VexMode { + /// 2B VEX prefix (0xC5). + Vex2b, + + /// 3B VEX prefix (0xC4). + Vex3b, +} + +impl From for VexMode { + fn from(value: u32) -> VexMode { + match value { + ffi::ND_VEXM_2B => VexMode::Vex2b, + ffi::ND_VEXM_3B => VexMode::Vex3b, + _ => panic!("Unexpected VEX mode mode {}", value), + } + } +} + +/// Addressing mode. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum AddressingMode { + /// 16 bit addressing. + Addr16, + + /// 32 bit addressing. + Addr32, + + /// 64 bit addressing. + Addr64, +} + +impl From for AddressingMode { + fn from(value: u32) -> AddressingMode { + match value { + ffi::ND_ADDR_16 => AddressingMode::Addr16, + ffi::ND_ADDR_32 => AddressingMode::Addr32, + ffi::ND_ADDR_64 => AddressingMode::Addr64, + _ => panic!("Unexpected addressing mode {}", value), + } + } +} + +/// Operand mode/size. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum OperandSize { + /// 16 bit operand size. + OpSize16, + + /// 32 bit operand size. + OpSize32, + + /// 64 bit operand size. + OpSize64, +} + +impl From for OperandSize { + fn from(value: u32) -> OperandSize { + match value { + ffi::ND_OPSZ_16 => OperandSize::OpSize16, + ffi::ND_OPSZ_32 => OperandSize::OpSize32, + ffi::ND_OPSZ_64 => OperandSize::OpSize64, + _ => panic!("Unexpected operand size {}", value), + } + } +} + +/// Operand mode/size. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum VectorSize { + /// 128 bit vector size. + VecSize128, + /// 256 bit vector size. + VecSize256, + /// 512 bit vector size. + VecSize512, +} + +impl From for VectorSize { + fn from(value: u32) -> VectorSize { + match value { + ffi::ND_VECM_128 => VectorSize::VecSize128, + ffi::ND_VECM_256 => VectorSize::VecSize256, + ffi::ND_VECM_512 => VectorSize::VecSize512, + _ => panic!("Unexpected vector size {}", value), + } + } +} + +/// Exception classes. +/// +/// Different instruction sets or encodings are covered by different exception classes. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum ExceptionClass { + None, + + /// SSE/AVX exception class (for legacy encoded SSE instructions and VEX instructions). + SseAvx, + + /// EVEX exception class (for EVEX encoded AVX* instructions). + Evex, + + /// Opmask instructions exception class. + Opmask, + + /// AMX exception class type (for VEX encoded AMX instructions). + Amx, +} + +#[doc(hidden)] +impl From for ExceptionClass { + fn from(value: ffi::ND_EX_CLASS) -> ExceptionClass { + match value { + ffi::_ND_EX_CLASS::ND_EXC_None => ExceptionClass::None, + ffi::_ND_EX_CLASS::ND_EXC_SSE_AVX => ExceptionClass::SseAvx, + ffi::_ND_EX_CLASS::ND_EXC_EVEX => ExceptionClass::Evex, + ffi::_ND_EX_CLASS::ND_EXC_OPMASK => ExceptionClass::Opmask, + ffi::_ND_EX_CLASS::ND_EXC_AMX => ExceptionClass::Amx, + // NOTE: when updating this take care to also update the `From` implementation! + // TODO: any way of keeping these in sync automagically? + } + } +} + +impl From for ExceptionClass { + fn from(value: u8) -> ExceptionClass { + if value == ffi::_ND_EX_CLASS::ND_EXC_None as u8 { + ExceptionClass::None + } else if value == ffi::_ND_EX_CLASS::ND_EXC_SSE_AVX as u8 { + ExceptionClass::SseAvx + } else if value == ffi::_ND_EX_CLASS::ND_EXC_EVEX as u8 { + ExceptionClass::Evex + } else if value == ffi::_ND_EX_CLASS::ND_EXC_OPMASK as u8 { + ExceptionClass::Opmask + } else if value == ffi::_ND_EX_CLASS::ND_EXC_AMX as u8 { + ExceptionClass::Amx + } else { + panic!("Unknown exception class {}", value) + } + } +} + +/// Describes the way an instruction accesses the flags register. +/// +/// Individual bits can be checked using the [rflags](rflags) module. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct FlagsAccess { + /// RFLAGS access mode, as per the entire register. + pub mode: OpAccess, + + /// Tested flags. + pub tested: u32, + + /// Modified (according to the result) flags. + pub modified: u32, + + /// Flags that are always set to 1. + pub set: u32, + + /// Flags that are always cleared to 0. + pub cleared: u32, + + /// Undefined flags. + pub undefined: u32, +} + +/// EVEX rounding mode. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum EvexRounding { + /// Round to nearest equal. + NearestEqual, + /// Round down. + Down, + /// Round up. + Up, + /// round to zero. + Zero, +} + +#[doc(hidden)] +impl From for EvexRounding { + fn from(value: ffi::ND_ROUNDING) -> EvexRounding { + match value { + ffi::_ND_ROUNDING::ND_RND_RNE => EvexRounding::NearestEqual, + ffi::_ND_ROUNDING::ND_RND_RD => EvexRounding::Down, + ffi::_ND_ROUNDING::ND_RND_RU => EvexRounding::Up, + ffi::_ND_ROUNDING::ND_RND_RZ => EvexRounding::Zero, + // NOTE: when updating this take care to also update the `From` implementation! + // TODO: any way of keeping these in sync automagically? + } + } +} + +impl From for EvexRounding { + fn from(value: u8) -> EvexRounding { + if value == ffi::_ND_ROUNDING::ND_RND_RNE as u8 { + EvexRounding::NearestEqual + } else if value == ffi::_ND_ROUNDING::ND_RND_RD as u8 { + EvexRounding::Down + } else if value == ffi::_ND_ROUNDING::ND_RND_RU as u8 { + EvexRounding::Up + } else if value == ffi::_ND_ROUNDING::ND_RND_RZ as u8 { + EvexRounding::Zero + } else { + panic!("Unknown EVEX rounding: {}", value) + } + } +} + +/// Indicates which prefixes are valid for an instruction. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct ValidPrefixes { + /// The instruction supports REP prefix. + pub rep: bool, + /// The instruction supports REPZ/REPNZ prefixes. + pub rep_cond: bool, + /// The instruction supports LOCK prefix. + pub lock: bool, + /// The instruction supports XACQUIRE/XRELEASE prefixes. + pub hle: bool, + /// The instruction supports only XACQUIRE. + pub xacquire: bool, + /// The instruction supports only XRELEASE. + pub xrelease: bool, + /// The instruction supports BND prefix. + pub bnd: bool, + /// The instruction supports branch hints. + pub bhint: bool, + /// HLE prefix is accepted without LOCK. + pub hle_no_lock: bool, + /// The instruction supports the DNT (Do Not Track) CET prefix. + pub dnt: bool, +} + +#[doc(hidden)] +impl From for ValidPrefixes { + fn from(value: ffi::ND_VALID_PREFIXES) -> ValidPrefixes { + let raw = unsafe { value.__bindgen_anon_1 }; + ValidPrefixes { + rep: raw.Rep() != 0, + rep_cond: raw.RepCond() != 0, + lock: raw.Lock() != 0, + hle: raw.Hle() != 0, + xacquire: raw.Xacquire() != 0, + xrelease: raw.Xrelease() != 0, + bnd: raw.Bnd() != 0, + bhint: raw.Bhint() != 0, + hle_no_lock: raw.HleNoLock() != 0, + dnt: raw.Dnt() != 0, + } + } +} + +/// Indicates which decorators are valid for an instruction. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct ValidDecorators { + /// The instruction supports embedded rounding mode. + pub er: bool, + /// The instruction supports suppress all exceptions mode. + pub sae: bool, + /// The instruction supports zeroing. + pub zero: bool, + /// The instruction supports mask registers. + pub mask: bool, + /// The instruction supports broadcast. + pub broadcast: bool, +} + +#[doc(hidden)] +impl From for ValidDecorators { + fn from(value: ffi::ND_VALID_DECORATORS) -> ValidDecorators { + let raw = unsafe { value.__bindgen_anon_1 }; + ValidDecorators { + er: raw.Er() != 0, + sae: raw.Sae() != 0, + zero: raw.Zero() != 0, + mask: raw.Mask() != 0, + broadcast: raw.Broadcast() != 0, + } + } +} + +/// A decoded instruction. +#[derive(Copy, Clone, Debug)] +pub struct DecodedInstruction { + inner: ffi::INSTRUX, + ip: u64, + instruction: Mnemonic, + length: usize, +} + +impl DecodedInstruction { + /// Decodes an array of bytes. + /// + /// # Arguments + /// + /// * `code` - An [u8](u8) slice that holds the code to be decoded. Note that decoding is attempted only from offset + /// 0 inside this code chunk. + /// * `mode` - The mode in which to decode the instruction. + /// * `ip` - The instruction pointer value to use when formatting the decoded instruction. Does not affect the + /// decoding process in any way. If not needed, use [decode](DecodedInstruction::decode) instead. + /// + /// # Errors + /// + /// This function reports back errors returned by the bddisasm library, as well as internal errors that usually + /// signal a bug in this implementation. + /// + /// Note that [`DecodeError::UnknownStatus`] and [`DecodeError::UnknownInstruction`] should never be encountered, + /// unless this crate has fallen out if sync with `bddisasm-sys`, thus they signal a bug in this crate. + /// + /// # Examples + /// + /// ``` + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// use bddisasm::decoder::{DecodedInstruction, DecodeMode, Mnemonic}; + /// + /// let code = vec![0x48, 0x8b, 0x05, 0xf9, 0xff, 0xff, 0xff]; + /// + /// let instruction = DecodedInstruction::decode_with_ip(&code, DecodeMode::Bits64, 0)?; + /// // Will print `MOV rax, qword ptr [rel 0x0]` + /// println!("{}", instruction); + /// + /// let instruction = DecodedInstruction::decode_with_ip(&code, DecodeMode::Bits64, 0x100)?; + /// // Will print `MOV rax, qword ptr [rel 0x100]` + /// println!("{}", instruction); + /// # Ok(()) + /// # } + /// ``` + pub fn decode_with_ip(code: &[u8], mode: DecodeMode, ip: u64) -> DecodeResult { + let mut instrux: mem::MaybeUninit = mem::MaybeUninit::uninit(); + let instrux = instrux.as_mut_ptr(); + + let (code_def, data_def) = mode.into(); + + let status = unsafe { + ffi::NdDecodeEx( + instrux, + code.as_ptr(), + code.len() as u64, + code_def, + data_def, + ) + }; + + decode_error::status_to_error(status)?; + + let instrux = unsafe { *instrux }; + Ok(DecodedInstruction { + inner: instrux, + ip, + instruction: Mnemonic::try_from(unsafe { instrux.__bindgen_anon_2.Instruction })?, + length: instrux.Length as usize, + }) + } + + /// Decodes an array of bytes. + /// + /// This function is a thin wrapper over [decode_with_ip](DecodedInstruction::decode_with_ip) and behaves exactly + /// the same. It sets `ip` to 0. + pub fn decode(code: &[u8], mode: DecodeMode) -> DecodeResult { + Self::decode_with_ip(code, mode, 0) + } + + /// Get the mnemonic of the instruction. + #[inline] + pub fn mnemonic(self) -> Mnemonic { + self.instruction + } + + /// Get the instruction length, in bytes. + /// + /// It is guaranteed that no instruction will exceed a length of 15 bytes. + #[inline] + pub fn length(self) -> usize { + self.length + } + + /// Get the instruction operands. + /// + /// The number of elements in the returned vector will always be equal to + /// [`operands_count`](DecodedInstruction::operands_count). + /// + /// # Examples + /// + /// See [`operand`] for more in-depth examples on how to work with instruction operands. + /// + /// ``` + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// use bddisasm::decoder::{DecodedInstruction, DecodeMode, Mnemonic}; + /// + /// // `MOV ebx, dword ptr [ecx+edi]` + /// let instruction = DecodedInstruction::decode(b"\x8b\x1c\x39", DecodeMode::Bits32)?; /// + /// let operands = instruction.operands(); + /// // The first operand is the destination + /// let dst = operands[0]; + /// // The second operand is the source + /// let src = operands[0]; + /// + /// // Print information about the operands + /// println!("{:#?} {:#?}", dst.info, src.info); + /// # Ok(()) + /// # } + /// ``` + pub fn operands(self) -> Vec { + let mut ops = Vec::new(); + + for op_index in 0..self.inner.OperandsCount { + ops.push(operand::Operand::from( + self.inner.Operands[op_index as usize], + )); + } + + ops + } + + /// Returns the CPUID support flag. + /// + /// If [None](None), the instruction is supported on any CPU, and no CPUID flag exists. + /// + /// # Examples + /// + /// See [cpuid](crate::cpuid) for more in-depth examples on how to use the CPUID information. + /// + /// ``` + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// use bddisasm::decoder::{DecodedInstruction, DecodeMode, Mnemonic}; + /// + /// // `RDMSR` + /// let instruction = DecodedInstruction::decode(b"\x0f\x32", DecodeMode::Bits64)?; + /// let cpuid = instruction.cpuid(); + /// // Will print `leaf: 0x1 sub-leaf: - register: 2 bit to test: 0x5` + /// if let Some(cpuid) = cpuid { + /// println!("{}", cpuid); + /// } + /// + /// # Ok(()) + /// # } + /// ``` + pub fn cpuid(self) -> Option { + let cpuid = unsafe { self.inner.CpuidFlag.__bindgen_anon_1 }; + let leaf = cpuid.Leaf; + if leaf == ffi::ND_CFF_NO_LEAF { + None + } else { + let sub_leaf = cpuid.SubLeaf(); + let sub_leaf = if sub_leaf == ffi::ND_CFF_NO_SUBLEAF { + None + } else { + Some(sub_leaf) + }; + + let register = cpuid.Reg() as u8; + let bit = cpuid.Bit() as u64; + + Some(Cpuid { + leaf, + sub_leaf, + register, + bit, + }) + } + } + + /// Get the encoding mode used. + #[inline] + pub fn encoding_mode(self) -> EncodingMode { + EncodingMode::from(self.inner.EncMode() as u32) + } + + /// Get the VEX mode, if any. + #[inline] + pub fn vex_mode(self) -> Option { + if self.has_vex() { + Some(VexMode::from(self.inner.VexMode() as u32)) + } else { + None + } + } + + /// Get the addressing mode. + #[inline] + pub fn addr_mode(self) -> AddressingMode { + AddressingMode::from(self.inner.AddrMode() as u32) + } + + /// Get the operand mode/size. + /// + /// This is computed based on the passed-in [DecodeMode](DecodeMode) and instruction prefixes. + /// + /// # Remarks + /// + /// The effective mode can be different (see [effective_op_mode](DecodedInstruction::effective_op_mode)). + /// + /// # Examples + /// + /// Using [DecodeMode::Bits64](DecodeMode::Bits64), `0x50` encodes a `PUSH rax` instruction with an operand size of + /// 32 because it has no prefix that promotes it, but the effective size is 64 because the instruction always + /// operates on 64 bits. + /// + /// ``` + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// use bddisasm::decoded_instruction::{DecodedInstruction, DecodeMode, Mnemonic, OperandSize}; + /// + /// let ins = + /// DecodedInstruction::decode(&[0x50], DecodeMode::Bits64)?; + /// assert_eq!(ins.mnemonic(), Mnemonic::Push); + /// assert_eq!(ins.op_mode(), OperandSize::OpSize32); + /// assert_eq!(ins.effective_op_mode(), OperandSize::OpSize64); + /// + /// let ins = + /// DecodedInstruction::decode(&[0x48, 0x50], DecodeMode::Bits64)?; + /// assert_eq!(ins.mnemonic(), Mnemonic::Push); + /// assert_eq!(ins.op_mode(), OperandSize::OpSize64); + /// assert_eq!(ins.effective_op_mode(), OperandSize::OpSize64); + /// # Ok(()) + /// # } + #[inline] + pub fn op_mode(self) -> OperandSize { + OperandSize::from(self.inner.OpMode() as u32) + } + + /// Get the effective operand mode/size. + /// + /// Unlike [op_mode](DecodedInstruction::op_mode), this takes into account the actual instruction. + #[inline] + pub fn effective_op_mode(self) -> OperandSize { + OperandSize::from(self.inner.EfOpMode() as u32) + } + + /// Get the Vector mode/size, if any. + /// + /// This is computed based on the passed-in [DecodeMode](DecodeMode) and instruction prefixes. + /// + /// # Remarks + /// + /// The effective mode can be different (see [effective_vec_mode](DecodedInstruction::effective_vec_mode)). + #[inline] + pub fn vec_mode(self) -> Option { + if self.has_vector() { + Some(VectorSize::from(self.inner.VecMode() as u32)) + } else { + None + } + } + + /// Get the Vector mode/size, if any. + /// + /// Unlike [vec_mode](DecodedInstruction::vec_mode), this takes into account the actual instruction. + #[inline] + pub fn effective_vec_mode(self) -> Option { + if self.has_vector() { + Some(VectorSize::from(self.inner.EfVecMode() as u32)) + } else { + None + } + } + + /// `true` if REX is present. + #[inline] + pub fn has_rex(self) -> bool { + self.inner.HasRex() + } + + /// `true` if VEX is present. + #[inline] + pub fn has_vex(self) -> bool { + self.inner.HasVex() + } + + /// `true` if XOP is present. + #[inline] + pub fn has_xop(self) -> bool { + self.inner.HasXop() + } + + /// `true` if EVEX is present. + #[inline] + pub fn has_evex(self) -> bool { + self.inner.HasEvex() + } + + /// `true` if MVEX is present. + #[inline] + pub fn has_mvex(self) -> bool { + self.inner.HasMvex() + } + + /// `true` if 0x66 is present. + #[inline] + pub fn has_op_size(self) -> bool { + self.inner.HasOpSize() + } + + /// `true` if 0x67 is present. + #[inline] + pub fn has_addr_size(self) -> bool { + self.inner.HasAddrSize() + } + + /// `true` if 0xF0 is present. + #[inline] + pub fn has_lock(self) -> bool { + self.inner.HasLock() + } + + /// `true` if 0xF2 is present. + #[inline] + pub fn has_repnz_xacquire_bnd(self) -> bool { + self.inner.HasRepnzXacquireBnd() + } + + /// `true` if 0xF3 is present. + #[inline] + pub fn has_rep_repz_xrelease(self) -> bool { + self.inner.HasRepRepzXrelease() + } + + /// `true` if segment override is present. + #[inline] + pub fn has_seg(self) -> bool { + self.inner.HasSeg() + } + + /// `true` if the instruction is REPed up to RCX times. + #[inline] + pub fn is_repeated(self) -> bool { + self.inner.IsRepeated() + } + + /// `true` if the instruction is XACQUIRE enabled. + #[inline] + pub fn is_xacquire_enabled(self) -> bool { + self.inner.IsXacquireEnabled() + } + + /// `true` if the instruction is XRELEASE enabled. + #[inline] + pub fn is_xrelease_enabled(self) -> bool { + self.inner.IsXreleaseEnabled() + } + + /// `true` if the instruction uses RIP relative addressing. + #[inline] + pub fn is_rip_relative(self) -> bool { + self.inner.IsRipRelative() + } + + /// `true` if this is an indirect CALL/JMP that is CET tracked. + #[inline] + pub fn is_cet_tracked(self) -> bool { + self.inner.IsCetTracked() + } + + /// `true` if we have valid MODRM. + #[inline] + pub fn has_mod_rm(self) -> bool { + self.inner.HasModRm() + } + + /// `true` if we have valid SIB. + #[inline] + pub fn has_sib(self) -> bool { + self.inner.HasSib() + } + + /// `true` if we have valid DREX. + #[inline] + pub fn has_drex(self) -> bool { + self.inner.HasDrex() + } + + /// `true` if the instruction has displacement. + #[inline] + pub fn has_disp(self) -> bool { + self.inner.HasDisp() + } + + /// `true` if the instruction contains a direct address (ie, `CALL far 0x9A`). + #[inline] + pub fn has_addr(self) -> bool { + self.inner.HasAddr() + } + + /// `true` if the instruction contains a moffset (ie, `MOV al, [mem], 0xA0`). + #[inline] + pub fn has_moffset(self) -> bool { + self.inner.HasMoffset() + } + + /// `true` if immediate is present. + #[inline] + pub fn has_imm1(self) -> bool { + self.inner.HasImm1() + } + + /// `true` if second immediate is present. + #[inline] + pub fn has_imm2(self) -> bool { + self.inner.HasImm2() + } + + /// `true` if third immediate is present. + #[inline] + pub fn has_imm3(self) -> bool { + self.inner.HasImm3() + } + + /// `true` if the instruction contains a relative offset (ie, `Jcc 0x7x`). + #[inline] + pub fn has_rel_offs(self) -> bool { + self.inner.HasRelOffs() + } + + /// `true` if SSE immediate that encodes additional registers is present. + #[inline] + pub fn has_sse_imm(self) -> bool { + self.inner.HasSseImm() + } + + /// `true` if the instruction uses compressed displacement. + #[inline] + pub fn has_comp_disp(self) -> bool { + self.inner.HasCompDisp() + } + + /// `true` if the instruction uses broadcast addressing. + #[inline] + pub fn has_broadcast(self) -> bool { + self.inner.HasBroadcast() + } + + /// `true` if the instruction has mask. + #[inline] + pub fn has_mask(self) -> bool { + self.inner.HasMask() + } + + /// `true` if the instruction uses zeroing. + #[inline] + pub fn has_zero(self) -> bool { + self.inner.HasZero() + } + + /// `true` if the instruction has embedded rounding. + #[inline] + pub fn has_er(self) -> bool { + self.inner.HasEr() + } + + /// `true` if the instruction has SAE. + #[inline] + pub fn has_sae(self) -> bool { + self.inner.HasSae() + } + + /// `true` if the instruction ignores embedded rounding. + #[inline] + pub fn has_ign_er(self) -> bool { + self.inner.HasIgnEr() + } + + /// Displacement sign. `false` if positive, `true` if negative. + #[inline] + pub fn sign_disp(self) -> bool { + self.inner.SignDisp() + } + + /// `true` if changing prefix. + #[inline] + pub fn has_mandatory_66(self) -> bool { + self.inner.HasMandatory66() + } + + /// 0x66 is mandatory prefix. Does not behave as REP prefix. + #[inline] + pub fn has_mandatory_f2(self) -> bool { + self.inner.HasMandatoryF2() + } + + /// 0x66 is mandatory prefix. Does not behave as REP prefix. + #[inline] + pub fn has_mandatory_f3(self) -> bool { + self.inner.HasMandatoryF3() + } + + /// The length of the instruction word. 2, 4 or 8. + #[inline] + pub fn word_length(self) -> usize { + self.inner.WordLength() as usize + } + + /// The total number of bytes consumed by prefixes. + /// + /// This will also be the offset to the first opcode. The primary opcode will always be the last one. + #[inline] + pub fn pref_length(self) -> usize { + self.inner.PrefLength() as usize + } + + /// Number of opcode bytes. Max 3. + #[inline] + pub fn op_length(self) -> usize { + self.inner.OpLength() as usize + } + + /// Displacement length, in bytes. Maximum 4. + #[inline] + pub fn disp_length(self) -> usize { + self.inner.DispLength() as usize + } + + /// Absolute address length, in bytes. Maximum 8 bytes. + #[inline] + pub fn addr_length(self) -> usize { + self.inner.AddrLength() as usize + } + + /// Memory offset length, in bytes. Maximum 8 bytes. + #[inline] + pub fn moffset_length(self) -> usize { + self.inner.MoffsetLength() as usize + } + + /// First immediate length, in bytes. Maximum 8 bytes. + #[inline] + pub fn imm1_length(self) -> usize { + self.inner.Imm1Length() as usize + } + + /// Second immediate length, in bytes. Maximum 8 bytes. + #[inline] + pub fn imm2_length(self) -> usize { + self.inner.Imm2Length() as usize + } + + /// Third immediate length, in bytes. Maximum 8 bytes. + #[inline] + pub fn imm3_length(self) -> usize { + self.inner.Imm3Length() as usize + } + + /// Relative offset length, in bytes. Maximum 4 bytes. + #[inline] + pub fn rel_offs_length(self) -> usize { + self.inner.RelOffsLength() as usize + } + + /// The offset of the first opcode, inside the instruction. + #[inline] + pub fn op_offset(self) -> usize { + self.inner.OpOffset() as usize + } + + /// The offset of the nominal opcode, inside the instruction. + #[inline] + pub fn main_op_offset(self) -> usize { + self.inner.MainOpOffset() as usize + } + + #[inline] + /// The offset of the displacement, inside the instruction. + pub fn disp_offset(self) -> Option { + let value = self.inner.DispOffset() as usize; + if value == 0 { + None + } else { + Some(value) + } + } + + #[inline] + /// The offset of the hard-coded address. + pub fn addr_offset(self) -> Option { + let value = self.inner.AddrOffset() as usize; + if value == 0 { + None + } else { + Some(value) + } + } + + /// The offset of the absolute address, inside the instruction. + #[inline] + pub fn moffset_offset(self) -> Option { + let value = self.inner.MoffsetOffset() as usize; + if value == 0 { + None + } else { + Some(value) + } + } + + /// The offset of the immediate, inside the instruction. + #[inline] + pub fn imm1_offset(self) -> Option { + let value = self.inner.Imm1Offset() as usize; + if value == 0 { + None + } else { + Some(value) + } + } + + /// The offset of the second immediate, if any, inside the instruction. + #[inline] + pub fn imm2_offset(self) -> Option { + let value = self.inner.Imm2Offset() as usize; + if value == 0 { + None + } else { + Some(value) + } + } + + /// The offset of the third immediate, if any, inside the instruction. + #[inline] + pub fn imm3_offset(self) -> Option { + let value = self.inner.Imm3Offset() as usize; + if value == 0 { + None + } else { + Some(value) + } + } + + /// The offset of the relative offset used in instruction. + #[inline] + pub fn rel_offs_offset(self) -> Option { + let value = self.inner.RelOffsOffset() as usize; + if value == 0 { + None + } else { + Some(value) + } + } + + /// The offset of the SSE immediate, if any, inside the instruction. + #[inline] + pub fn sse_imm_offset(self) -> Option { + let value = self.inner.SseImmOffset() as usize; + if value == 0 { + None + } else { + Some(value) + } + } + + /// The offset of the mod rm byte inside the instruction, if any. + #[inline] + pub fn mod_rm_offset(self) -> Option { + let value = self.inner.ModRmOffset() as usize; + if value == 0 { + None + } else { + Some(value) + } + } + + /// Number of words accessed on/from the stack. + #[inline] + pub fn stack_words(self) -> usize { + self.inner.StackWords as usize + } + + /// The last rep/repz/repnz prefix. if any. + #[inline] + pub fn rep(self) -> Option { + let value = self.inner.Rep; + if value == 0 { + None + } else { + Some(value) + } + } + + /// The last segment override prefix. if none. `FS`/`GS` if 64 bit. + #[inline] + pub fn seg(self) -> Option { + let value = self.inner.Seg; + if value == 0 { + None + } else { + Some(value) + } + } + + /// The last segment override indicating a branch hint. + #[inline] + pub fn bhint(self) -> u8 { + self.inner.Bhint + } + + /// Get the REX prefix. + #[inline] + pub fn rex(self) -> Option { + if self.has_rex() { + Some(unsafe { self.inner.Rex.Rex }) + } else { + None + } + } + + /// Get the ModRM byte. + #[inline] + pub fn mod_rm(self) -> Option { + if self.has_mod_rm() { + Some(unsafe { self.inner.ModRm.ModRm }) + } else { + None + } + } + + /// Get the SIB byte. + #[inline] + pub fn sib(self) -> Option { + if self.has_sib() { + Some(unsafe { self.inner.Sib.Sib }) + } else { + None + } + } + + /// Get the 2-bytes VEX. + #[inline] + pub fn vex2(self) -> Option<(u8, u8)> { + if matches!(self.vex_mode(), Some(VexMode::Vex2b)) { + let vex2 = self.inner.__bindgen_anon_1; + let vex2 = unsafe { vex2.Vex2.Vex }; + + Some((vex2[0], vex2[1])) + } else { + None + } + } + + /// Get the 3-bytes VEX. + #[inline] + pub fn vex3(self) -> Option<(u8, u8, u8)> { + if matches!(self.vex_mode(), Some(VexMode::Vex3b)) { + let vex3 = self.inner.__bindgen_anon_1; + let vex3 = unsafe { vex3.Vex3.Vex }; + + Some((vex3[0], vex3[1], vex3[2])) + } else { + None + } + } + + /// Get the XOP bytes. + #[inline] + pub fn xop(self) -> Option<(u8, u8, u8)> { + if self.has_xop() { + let xop = self.inner.__bindgen_anon_1; + let xop = unsafe { xop.Xop.Xop }; + + Some((xop[0], xop[1], xop[2])) + } else { + None + } + } + + /// Get the EVEX bytes. + #[inline] + pub fn evex(self) -> Option<(u8, u8, u8, u8)> { + if self.has_evex() { + let evex = self.inner.__bindgen_anon_1; + let evex = unsafe { evex.Evex.Evex }; + + Some((evex[0], evex[1], evex[2], evex[3])) + } else { + None + } + } + + /// Get the `segment:offset` address accessed by the instruction, if any. + #[inline] + pub fn address(self) -> Option { + if self.has_addr() { + let raw = self.inner.Address; + let raw = unsafe { raw.__bindgen_anon_1 }; + + Some(OpAddr::new(raw.Cs, raw.Ip as u64)) + } else { + None + } + } + + /// Get the absolute offset, if any. + #[inline] + pub fn moffset(self) -> Option { + if self.has_moffset() { + Some(self.inner.Moffset) + } else { + None + } + } + + /// Get the displacement. Max 4 bytes. Used in ModRM instructions. + #[inline] + pub fn disp(self) -> Option { + if self.has_disp() { + Some(self.inner.Displacement) + } else { + None + } + } + + /// Get the relative offset, used for branches. Max 4 bytes. + #[inline] + pub fn rel_offset(self) -> Option { + if self.has_rel_offs() { + Some(self.inner.RelativeOffset) + } else { + None + } + } + + /// Get the first immediate. + #[inline] + pub fn immediate1(self) -> Option { + if self.has_imm1() { + Some(self.inner.Immediate1) + } else { + None + } + } + + /// Get the second immediate. Used mainly for [Mnemonic::Enter](Mnemonic::Enter). + #[inline] + pub fn immediate2(self) -> Option { + if self.has_imm2() { + Some(self.inner.Immediate2) + } else { + None + } + } + + /// Get the third additional immediate. + #[inline] + pub fn immediate3(self) -> Option { + if self.has_imm3() { + Some(self.inner.Immediate3) + } else { + None + } + } + + /// Get the SSE immediate. It is used to select a register. + #[inline] + pub fn sse_immediate(self) -> Option { + if self.has_sse_imm() { + Some(self.inner.SseImmediate) + } else { + None + } + } + + /// Get the SSE condition byte. + #[inline] + pub fn sse_cond(self) -> Option { + if (self.inner.Attributes & ffi::ND_FLAG_SSE_CONDB) != 0 { + Some(self.inner.SseCondition) + } else { + None + } + } + + /// Get the condition byte. + #[inline] + pub fn cond(self) -> Option { + if (self.inner.Attributes & ffi::ND_FLAG_COND) != 0 { + Some(self.inner.Condition) + } else { + None + } + } + + /// Get the number of operands. + #[inline] + pub fn operands_count(self) -> usize { + self.inner.OperandsCount as usize + } + + /// Number of explicit operands. + /// + /// Use this if you want to ignore implicit operands such as stack, flags, etc. + #[inline] + pub fn exp_operands_count(self) -> usize { + self.inner.ExpOperandsCount as usize + } + + /// Get the RIP access mode. + #[inline] + pub fn rip_access(self) -> OpAccess { + OpAccess::from(ffi::ND_OPERAND_ACCESS { + Access: self.inner.RipAccess, + }) + } + + /// Get the stack access mode. + #[inline] + pub fn stack_access(self) -> OpAccess { + OpAccess::from(ffi::ND_OPERAND_ACCESS { + Access: self.inner.StackAccess, + }) + } + + /// Get the memory access mode. + /// + /// This includes the stack or shadow stack access. + #[inline] + pub fn memory_access(self) -> OpAccess { + OpAccess::from(ffi::ND_OPERAND_ACCESS { + Access: self.inner.MemoryAccess, + }) + } + + /// Get the rflags access. + pub fn flags_access(self) -> FlagsAccess { + let facc = self.inner.FlagsAccess; + + let mode = OpAccess::from(ffi::ND_OPERAND_ACCESS { + Access: facc.RegAccess, + }); + + FlagsAccess { + mode, + tested: flags_raw(facc.Tested), + modified: flags_raw(facc.Modified), + set: flags_raw(facc.Set), + cleared: flags_raw(facc.Cleared), + undefined: flags_raw(facc.Undefined), + } + } + + /// FPU status word C0-C3 bits access. + #[inline] + pub fn fpu_flags_access(self) -> FpuFlags { + FpuFlags::from(self.inner.FpuFlagsAccess) + } + + // The exception class. + #[inline] + pub fn exception_class(self) -> ExceptionClass { + ExceptionClass::from(self.inner.ExceptionClass) + } + + /// EVEX tuple type. + #[inline] + pub fn evex_tuple(self) -> Option { + if self.has_evex() { + Some(Tuple::from(self.inner.TupleType as u32)) + } else { + None + } + } + + /// EVEX rounding mode. + #[inline] + pub fn evex_rounding(self) -> Option { + if self.has_er() { + Some(EvexRounding::from(self.inner.RoundingMode)) + } else { + None + } + } + + /// Get the instruction category. + /// + /// # Errors + /// + /// This function can return an error if the category of the instruction is not known. This is most likely a bug + /// in the current implementation. + #[inline] + pub fn category(self) -> Result { + Category::try_from(self.inner.Category) + } + + /// Get the ISA set. + /// + /// # Errors + /// + /// This function can return an error if the ISA set of the instruction is not known. This is most likely a bug + /// in the current implementation. + #[inline] + pub fn isa_set(self) -> Result { + IsaSet::try_from(self.inner.IsaSet) + } + + /// Get the CPU modes in which the instruction is valid. + /// + /// See [cpu_modes](crate::cpu_modes) for examples. + #[inline] + pub fn valid_cpu_modes(self) -> CpuModes { + CpuModes::from(self.inner.ValidModes) + } + + /// Get the valid prefixes for this instruction. + #[inline] + pub fn valid_prefixes(self) -> ValidPrefixes { + ValidPrefixes::from(self.inner.ValidPrefixes) + } + + /// Get the decorators accepted by the instruction. + #[inline] + pub fn valid_decorators(self) -> ValidDecorators { + ValidDecorators::from(self.inner.ValidDecorators) + } + + /// Get the main/nominal opcode. + #[inline] + pub fn primary_op_code(self) -> u8 { + self.inner.PrimaryOpCode + } + + /// `true` if the instruction is a SIMD instruction that operates on vector regs. + #[inline] + pub fn has_vector(self) -> bool { + self.inner.Attributes & ffi::ND_FLAG_VECTOR != 0 + } +} + +impl<'a> DecodedInstruction { + /// Get the instruction bytes. + #[inline] + pub fn bytes(&'a self) -> &'a [u8] { + &self.inner.InstructionBytes[..self.inner.Length as usize] + } + + /// Get the opcode bytes (escape codes and main op code). + #[inline] + pub fn op_code_bytes(&'a self) -> &'a [u8] { + &self.inner.OpCodeBytes[..self.op_length()] + } +} + +impl fmt::Display for DecodedInstruction { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut buffer: [i8; ffi::ND_MIN_BUF_SIZE as usize] = [0; ffi::ND_MIN_BUF_SIZE as usize]; + let status = unsafe { + ffi::NdToText( + &self.inner, + self.ip, + buffer.len() as u32, + buffer.as_mut_ptr(), + ) + }; + match decode_error::status_to_error(status) { + Ok(_) => { + let text = String::from_utf8(buffer.iter().map(|&c| c as u8).collect()).unwrap(); + write!(f, "{}", text.trim_matches(char::from(0))) + } + Err(_) => Err(fmt::Error), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn decode() { + let code = vec![0xb8, 0x00, 0x00, 0x00, 0x00]; + let ins = DecodedInstruction::decode(&code, DecodeMode::Bits32).expect("Unable to decode"); + assert_eq!(ins.instruction, Mnemonic::Mov); + assert_eq!(ins.bytes(), code); + assert_eq!(format!("{}", ins), "MOV eax, 0x00000000"); + } + + #[test] + fn decode_with_ip() { + let code = b"\x48\x8b\x05\xf9\xff\xff\xff"; + let ins = DecodedInstruction::decode_with_ip(code, DecodeMode::Bits64, 0x100) + .expect("Unable to decode"); + assert_eq!(ins.instruction, Mnemonic::Mov); + assert_eq!(ins.bytes(), code); + assert_eq!(format!("{}", ins), "MOV rax, qword ptr [rel 0x100]"); + } + + fn get_tokens(line: &str, index: usize) -> u32 { + let tokens = line.split(" ").collect::>(); + let tokens = tokens + .into_iter() + .filter(|s| !s.is_empty()) + .collect::>(); + + let token = tokens[index]; + if token.starts_with("0x") { + u32::from_str_radix(token.trim_start_matches("0x"), 16).unwrap() + } else { + token.parse().unwrap() + } + } + + #[test] + fn constants() { + // These will probably never change, so it is not really worth it to generate the enums and the `From` + // implementations at every build, but these tests should be enough to catch the unlikely situation in which + // a new constant is added. + let bindings = include_str!("../../bddisasm-sys/csrc/inc/bddisasm.h"); + let mut exc_count: u8 = 0; + let mut shadow_stack_count: u8 = 0; + let mut tuple_count: u32 = 0; + let mut evex_rounding: u8 = 0; + for line in bindings.lines() { + if line.starts_with("#define ND_ENCM_") { + EncodingMode::from(get_tokens(line, 2)); + } else if line.starts_with("#define ND_VEXM_") { + VexMode::from(get_tokens(line, 2)); + } else if line.starts_with("#define ND_ADDR_") { + AddressingMode::from(get_tokens(line, 2)); + } else if line.starts_with("#define ND_OPSZ_") { + OperandSize::from(get_tokens(line, 2)); + } else if line.starts_with("#define ND_VECM_") { + VectorSize::from(get_tokens(line, 2)); + } else if line.starts_with(" ND_EXC_") { + ExceptionClass::from(exc_count); + exc_count += 1; + } else if line.starts_with("#define ND_SIZE_") + && !line.starts_with("#define ND_SIZE_TO_MASK(sz)") + { + // TODO: this test should be in `operand.rs`, but since we are already parsing `bddisasm.h` here it + // felt wastefull to also parse it there. + operand::OpSize::from(get_tokens(line, 2)); + } else if line.starts_with(" ND_SHSTK_") { + // TODO: this test should be in `operand.rs`, but since we are already parsing `bddisasm.h` here it + // felt wastefull to also parse it there. + operand::ShadowStackAccess::from(shadow_stack_count); + shadow_stack_count += 1; + } else if line.starts_with("#define ND_FPU_FLAG_") { + // TODO: this test should be in `fpu_flags.rs`, but since we are already parsing `bddisasm.h` here it + // felt wastefull to also parse it there. + crate::fpu_flags::FpuFlagsAccess::from(get_tokens(line, 2) as u8); + } else if line.starts_with(" ND_TUPLE_") { + // TODO: this test should be in `operand.rs`, but since we are already parsing `bddisasm.h` here it + // felt wastefull to also parse it there. + Tuple::from(tuple_count); + tuple_count += 1; + } else if line.starts_with(" ND_RND_") { + // TODO: this test should be in `operand.rs`, but since we are already parsing `bddisasm.h` here it + // felt wastefull to also parse it there. + EvexRounding::from(evex_rounding); + evex_rounding += 1; + } + } + } +} diff --git a/rsbddisasm/bddisasm/src/decoder.rs b/rsbddisasm/bddisasm/src/decoder.rs new file mode 100644 index 0000000..7f9a588 --- /dev/null +++ b/rsbddisasm/bddisasm/src/decoder.rs @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2021 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ +//! Decodes instructions. + +extern crate bddisasm_sys as ffi; + +pub use crate::decode_error::DecodeError; +pub use crate::decoded_instruction::{DecodeMode, DecodeResult, DecodedInstruction}; +pub use crate::mnemonic::Mnemonic; + +/// Decodes instructions. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct Decoder<'a> { + code: &'a [u8], + ip: u64, + mode: DecodeMode, + offset: usize, +} + +impl<'a> Decoder<'a> { + /// Creates a new decoder. + /// + /// # Arguments + /// + /// * `code` - An [u8](u8) slice that holds the code to be decoded. + /// * `mode` - The mode in which to decode the instruction. + /// * `ip` - The instruction pointer value to use when formatting the decoded instruction. Does not affect the + /// decoding process in any way. + pub fn new(code: &'a [u8], mode: DecodeMode, ip: u64) -> Self { + Self { + code, + mode, + ip, + offset: 0, + } + } + + /// Attempts to decode the next instruction from the given code chunk. + /// + /// # Returns + /// + /// * `Some(DecodeResult)` - if there are still undecoded bytes in the given code chunk. The decoding may have + /// still failed. See `Remarks`. + /// * `None` - if all the bytes in the given code chunk were decoded. + /// + /// # Remarks + /// + /// This function decodes one instruction from the given code chunk at a time. After each call, the offset inside + /// the code chunk is advanced by: + /// + /// - the size of the decoded instruction, if decoding was succesfull + /// - 1, if decoding was not succesfull + /// + /// The `ip` value specified when the decoder was created is automatically updated: + /// + /// - if the decoding was succesfull, it is incremented with the instruction size + /// - if the decoding was not succesfull, it is incremented with 1 + /// + /// # Examples + /// + /// ``` + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// use bddisasm::decoder::{Decoder, DecodeMode}; + /// + /// let mut decoder = Decoder::new(&[0x51, 0x53], DecodeMode::Bits32, 0); + /// + /// // As long as we have something to decode + /// while let Some(result) = decoder.decode_next() { + /// // Check if the decoding succeeded + /// match result { + /// Ok(instruction) => println!("{}", instruction), + /// Err(e) => println!("Unable to decode: {}", e), + /// } + /// } + /// + /// # Ok(()) + /// # } + /// ``` + pub fn decode_next(&mut self) -> Option { + if self.offset >= self.code.len() { + None + } else { + let result = + DecodedInstruction::decode_with_ip(&self.code[self.offset..], self.mode, self.ip); + match result { + Ok(ins) => { + self.offset += ins.length() as usize; + self.ip += ins.length() as u64; + } + Err(_) => { + self.offset += 1; + self.ip += 1; + } + }; + + Some(result) + } + } + + /// Attempts to decode the next instruction from the given code chunk. + /// + /// Behaves like [decode_next](Decoder::decode_next), but in addition to the [DecodeResult](DecodeResult) it will + /// also return the offset from which decoding was attempted, as well as the corresponding instruction pointer. + /// + /// # Examples + /// + /// ``` + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// use bddisasm::decoder::{Decoder, DecodeMode}; + /// + /// let mut decoder = Decoder::new(&[0x51, 0x53], DecodeMode::Bits32, 0x1000); + /// + /// // As long as we have something to decode + /// while let Some((result, offset, ip)) = decoder.decode_next_with_info() { + /// // Check if the decoding succeeded + /// match result { + /// Ok(instruction) => println!("IP: {:#x} {}", ip, instruction), + /// Err(e) => println!("Unable to decode at offset {:#x}: {}", offset, e), + /// } + /// } + /// + /// # Ok(()) + /// # } + /// ``` + pub fn decode_next_with_info(&mut self) -> Option<(DecodeResult, usize, u64)> { + let offset = self.offset; + let ip = self.ip; + + self.decode_next().map(|res| (res, offset, ip)) + } +} + +impl Iterator for Decoder<'_> { + type Item = DecodeResult; + + #[inline] + fn next(&mut self) -> Option { + self.decode_next() + } +} + +impl std::iter::FusedIterator for Decoder<'_> {} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn decode_next() { + let code = vec![0xb8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xf9, 0xff, 0xff]; + let mut decoder = Decoder::new(&code, DecodeMode::Bits64, 0x1000); + let expected: Vec> = vec![ + Ok(( + Mnemonic::Mov, + "MOV eax, 0x00000000", + &[0xb8, 0x00, 0x00, 0x00, 0x00], + )), + Ok((Mnemonic::Mov, "MOV rdi, rcx", &[0x48, 0x8b, 0xf9])), + Err(DecodeError::InvalidEncoding), + Err(DecodeError::BufferTooSmall), + ]; + let mut exected_index = 0usize; + while let Some(ins) = decoder.decode_next() { + match expected[exected_index] { + Ok((i, s, b)) => { + let ins = ins.expect("Unable to decode"); + assert_eq!(i, ins.mnemonic()); + assert_eq!(b, ins.bytes()); + assert_eq!(s, format!("{}", ins)); + } + Err(e) => { + assert_eq!(e, ins.expect_err("Expected error")); + } + }; + + exected_index += 1; + } + } + + #[test] + fn decoder_iter() { + let code = vec![0xb8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xf9, 0xff, 0xff]; + let decoder = Decoder::new(&code, DecodeMode::Bits64, 0x1000); + let expected: Vec> = vec![ + Ok(( + Mnemonic::Mov, + "MOV eax, 0x00000000", + &[0xb8, 0x00, 0x00, 0x00, 0x00], + )), + Ok((Mnemonic::Mov, "MOV rdi, rcx", &[0x48, 0x8b, 0xf9])), + Err(DecodeError::InvalidEncoding), + Err(DecodeError::BufferTooSmall), + ]; + + for (index, ins) in decoder.enumerate() { + match expected[index] { + Ok((i, s, b)) => { + let ins = ins.expect("Unable to decode"); + assert_eq!(i, ins.mnemonic()); + assert_eq!(b, ins.bytes()); + assert_eq!(s, format!("{}", ins)); + } + Err(e) => { + assert_eq!(e, ins.expect_err("Expected error")); + } + }; + } + } +} diff --git a/rsbddisasm/bddisasm/src/fpu_flags.rs b/rsbddisasm/bddisasm/src/fpu_flags.rs new file mode 100644 index 0000000..aa16cae --- /dev/null +++ b/rsbddisasm/bddisasm/src/fpu_flags.rs @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ +//! Offers information about how an instructions accesses the FPU status registers. + +extern crate bddisasm_sys as ffi; + +/// The mode in which a FPU status flag is accessed. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum FpuFlagsAccess { + /// The FPU status flag is cleared to 0. + Cleared, + /// The FPU status flag is set to 1. + Set, + /// The FPU status flag is modified according to a result. + Modified, + /// The FPU status flag is undefined or unaffected. + Undefined, +} + +impl From for FpuFlagsAccess { + fn from(value: u8) -> FpuFlagsAccess { + let value = value as u32; + match value { + ffi::ND_FPU_FLAG_SET_0 => FpuFlagsAccess::Cleared, + ffi::ND_FPU_FLAG_SET_1 => FpuFlagsAccess::Set, + ffi::ND_FPU_FLAG_MODIFIED => FpuFlagsAccess::Modified, + ffi::ND_FPU_FLAG_UNDEFINED => FpuFlagsAccess::Undefined, + _ => panic!("Unexpected FPU flag access: {}", value), + } + } +} + +/// Describes the way an instruction accesses the FPU flags registers. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct FpuFlags { + /// C0 flag access mode. + pub c0: FpuFlagsAccess, + /// C1 flag access mode. + pub c1: FpuFlagsAccess, + /// C2 flag access mode. + pub c2: FpuFlagsAccess, + /// C3 flag access mode. + pub c3: FpuFlagsAccess, +} + +#[doc(hidden)] +impl From for FpuFlags { + fn from(flags: ffi::ND_FPU_FLAGS) -> FpuFlags { + FpuFlags { + c0: FpuFlagsAccess::from(flags.C0()), + c1: FpuFlagsAccess::from(flags.C1()), + c2: FpuFlagsAccess::from(flags.C2()), + c3: FpuFlagsAccess::from(flags.C3()), + } + } +} diff --git a/rsbddisasm/bddisasm/src/instruction_category.rs b/rsbddisasm/bddisasm/src/instruction_category.rs new file mode 100644 index 0000000..e1b32ea --- /dev/null +++ b/rsbddisasm/bddisasm/src/instruction_category.rs @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ +//! Instruction categories. + +extern crate bddisasm_sys as ffi; + +use super::decode_error; +use std::convert::TryFrom; + +/// Instruction category. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum Category { + I3dnow, + Aes, + Aeskl, + Amx, + Arith, + Avx, + Avx2, + Avx2gather, + Avx512, + Avx512bf16, + Avx512fp16, + Avx512vbmi, + Avx512vp2intersect, + Avxvnni, + Bitbyte, + Blend, + Bmi1, + Bmi2, + Broadcast, + Call, + Cet, + Cldemote, + Cmov, + Compress, + CondBr, + Conflict, + Convert, + Dataxfer, + Decimal, + Enqcmd, + Expand, + Flagop, + Fma4, + Fred, + Gather, + Gfni, + Hreset, + I386, + Ifma, + Interrupt, + Io, + Iostringop, + Kl, + Kmask, + Knl, + Lkgs, + Logic, + Logical, + LogicalFp, + Lwp, + Lzcnt, + Misc, + Mmx, + Movdir64b, + Movdiri, + Mpx, + Nop, + Padlock, + Pclmulqdq, + Pconfig, + Pop, + Prefetch, + Ptwrite, + Push, + Rdpid, + Rdrand, + Rdseed, + Rdwrfsgs, + Ret, + Rotate, + Scatter, + Segop, + Semaphore, + Sgx, + Sha, + Shift, + Smap, + Sse, + Sse2, + Stringop, + Sttni, + Syscall, + Sysret, + System, + Tdx, + Ud, + Uintr, + UncondBr, + Unknown, + Vaes, + Vfma, + Vfmaps, + Vnni, + Vnniw, + Vpclmulqdq, + Vpopcnt, + Vtx, + Waitpkg, + Wbnoinvd, + Widenop, + WideKl, + X87Alu, + Xop, + Xsave, +} + +#[doc(hidden)] +impl TryFrom for Category { + type Error = decode_error::DecodeError; + + fn try_from(value: ffi::ND_INS_CATEGORY) -> Result { + match value { + ffi::_ND_INS_TYPE::ND_CAT_INVALID => { + Err(decode_error::DecodeError::UnknownInstruction(value as u32)) + } + ffi::_ND_INS_TYPE::ND_CAT_3DNOW => Ok(Category::I3dnow), + ffi::_ND_INS_TYPE::ND_CAT_AES => Ok(Category::Aes), + ffi::_ND_INS_TYPE::ND_CAT_AESKL => Ok(Category::Aeskl), + ffi::_ND_INS_TYPE::ND_CAT_AMX => Ok(Category::Amx), + ffi::_ND_INS_TYPE::ND_CAT_ARITH => Ok(Category::Arith), + ffi::_ND_INS_TYPE::ND_CAT_AVX => Ok(Category::Avx), + ffi::_ND_INS_TYPE::ND_CAT_AVX2 => Ok(Category::Avx2), + ffi::_ND_INS_TYPE::ND_CAT_AVX2GATHER => Ok(Category::Avx2gather), + ffi::_ND_INS_TYPE::ND_CAT_AVX512 => Ok(Category::Avx512), + ffi::_ND_INS_TYPE::ND_CAT_AVX512BF16 => Ok(Category::Avx512bf16), + ffi::_ND_INS_TYPE::ND_CAT_AVX512FP16 => Ok(Category::Avx512fp16), + ffi::_ND_INS_TYPE::ND_CAT_AVX512VBMI => Ok(Category::Avx512vbmi), + ffi::_ND_INS_TYPE::ND_CAT_AVX512VP2INTERSECT => Ok(Category::Avx512vp2intersect), + ffi::_ND_INS_TYPE::ND_CAT_AVXVNNI => Ok(Category::Avxvnni), + ffi::_ND_INS_TYPE::ND_CAT_BITBYTE => Ok(Category::Bitbyte), + ffi::_ND_INS_TYPE::ND_CAT_BLEND => Ok(Category::Blend), + ffi::_ND_INS_TYPE::ND_CAT_BMI1 => Ok(Category::Bmi1), + ffi::_ND_INS_TYPE::ND_CAT_BMI2 => Ok(Category::Bmi2), + ffi::_ND_INS_TYPE::ND_CAT_BROADCAST => Ok(Category::Broadcast), + ffi::_ND_INS_TYPE::ND_CAT_CALL => Ok(Category::Call), + ffi::_ND_INS_TYPE::ND_CAT_CET => Ok(Category::Cet), + ffi::_ND_INS_TYPE::ND_CAT_CLDEMOTE => Ok(Category::Cldemote), + ffi::_ND_INS_TYPE::ND_CAT_CMOV => Ok(Category::Cmov), + ffi::_ND_INS_TYPE::ND_CAT_COMPRESS => Ok(Category::Compress), + ffi::_ND_INS_TYPE::ND_CAT_COND_BR => Ok(Category::CondBr), + ffi::_ND_INS_TYPE::ND_CAT_CONFLICT => Ok(Category::Conflict), + ffi::_ND_INS_TYPE::ND_CAT_CONVERT => Ok(Category::Convert), + ffi::_ND_INS_TYPE::ND_CAT_DATAXFER => Ok(Category::Dataxfer), + ffi::_ND_INS_TYPE::ND_CAT_DECIMAL => Ok(Category::Decimal), + ffi::_ND_INS_TYPE::ND_CAT_ENQCMD => Ok(Category::Enqcmd), + ffi::_ND_INS_TYPE::ND_CAT_EXPAND => Ok(Category::Expand), + ffi::_ND_INS_TYPE::ND_CAT_FLAGOP => Ok(Category::Flagop), + ffi::_ND_INS_TYPE::ND_CAT_FMA4 => Ok(Category::Fma4), + ffi::_ND_INS_TYPE::ND_CAT_FRED => Ok(Category::Fred), + ffi::_ND_INS_TYPE::ND_CAT_GATHER => Ok(Category::Gather), + ffi::_ND_INS_TYPE::ND_CAT_GFNI => Ok(Category::Gfni), + ffi::_ND_INS_TYPE::ND_CAT_HRESET => Ok(Category::Hreset), + ffi::_ND_INS_TYPE::ND_CAT_I386 => Ok(Category::I386), + ffi::_ND_INS_TYPE::ND_CAT_IFMA => Ok(Category::Ifma), + ffi::_ND_INS_TYPE::ND_CAT_INTERRUPT => Ok(Category::Interrupt), + ffi::_ND_INS_TYPE::ND_CAT_IO => Ok(Category::Io), + ffi::_ND_INS_TYPE::ND_CAT_IOSTRINGOP => Ok(Category::Iostringop), + ffi::_ND_INS_TYPE::ND_CAT_KL => Ok(Category::Kl), + ffi::_ND_INS_TYPE::ND_CAT_KMASK => Ok(Category::Kmask), + ffi::_ND_INS_TYPE::ND_CAT_KNL => Ok(Category::Knl), + ffi::_ND_INS_TYPE::ND_CAT_LKGS => Ok(Category::Lkgs), + ffi::_ND_INS_TYPE::ND_CAT_LOGIC => Ok(Category::Logic), + ffi::_ND_INS_TYPE::ND_CAT_LOGICAL => Ok(Category::Logical), + ffi::_ND_INS_TYPE::ND_CAT_LOGICAL_FP => Ok(Category::LogicalFp), + ffi::_ND_INS_TYPE::ND_CAT_LWP => Ok(Category::Lwp), + ffi::_ND_INS_TYPE::ND_CAT_LZCNT => Ok(Category::Lzcnt), + ffi::_ND_INS_TYPE::ND_CAT_MISC => Ok(Category::Misc), + ffi::_ND_INS_TYPE::ND_CAT_MMX => Ok(Category::Mmx), + ffi::_ND_INS_TYPE::ND_CAT_MOVDIR64B => Ok(Category::Movdir64b), + ffi::_ND_INS_TYPE::ND_CAT_MOVDIRI => Ok(Category::Movdiri), + ffi::_ND_INS_TYPE::ND_CAT_MPX => Ok(Category::Mpx), + ffi::_ND_INS_TYPE::ND_CAT_NOP => Ok(Category::Nop), + ffi::_ND_INS_TYPE::ND_CAT_PADLOCK => Ok(Category::Padlock), + ffi::_ND_INS_TYPE::ND_CAT_PCLMULQDQ => Ok(Category::Pclmulqdq), + ffi::_ND_INS_TYPE::ND_CAT_PCONFIG => Ok(Category::Pconfig), + ffi::_ND_INS_TYPE::ND_CAT_POP => Ok(Category::Pop), + ffi::_ND_INS_TYPE::ND_CAT_PREFETCH => Ok(Category::Prefetch), + ffi::_ND_INS_TYPE::ND_CAT_PTWRITE => Ok(Category::Ptwrite), + ffi::_ND_INS_TYPE::ND_CAT_PUSH => Ok(Category::Push), + ffi::_ND_INS_TYPE::ND_CAT_RDPID => Ok(Category::Rdpid), + ffi::_ND_INS_TYPE::ND_CAT_RDRAND => Ok(Category::Rdrand), + ffi::_ND_INS_TYPE::ND_CAT_RDSEED => Ok(Category::Rdseed), + ffi::_ND_INS_TYPE::ND_CAT_RDWRFSGS => Ok(Category::Rdwrfsgs), + ffi::_ND_INS_TYPE::ND_CAT_RET => Ok(Category::Ret), + ffi::_ND_INS_TYPE::ND_CAT_ROTATE => Ok(Category::Rotate), + ffi::_ND_INS_TYPE::ND_CAT_SCATTER => Ok(Category::Scatter), + ffi::_ND_INS_TYPE::ND_CAT_SEGOP => Ok(Category::Segop), + ffi::_ND_INS_TYPE::ND_CAT_SEMAPHORE => Ok(Category::Semaphore), + ffi::_ND_INS_TYPE::ND_CAT_SGX => Ok(Category::Sgx), + ffi::_ND_INS_TYPE::ND_CAT_SHA => Ok(Category::Sha), + ffi::_ND_INS_TYPE::ND_CAT_SHIFT => Ok(Category::Shift), + ffi::_ND_INS_TYPE::ND_CAT_SMAP => Ok(Category::Smap), + ffi::_ND_INS_TYPE::ND_CAT_SSE => Ok(Category::Sse), + ffi::_ND_INS_TYPE::ND_CAT_SSE2 => Ok(Category::Sse2), + ffi::_ND_INS_TYPE::ND_CAT_STRINGOP => Ok(Category::Stringop), + ffi::_ND_INS_TYPE::ND_CAT_STTNI => Ok(Category::Sttni), + ffi::_ND_INS_TYPE::ND_CAT_SYSCALL => Ok(Category::Syscall), + ffi::_ND_INS_TYPE::ND_CAT_SYSRET => Ok(Category::Sysret), + ffi::_ND_INS_TYPE::ND_CAT_SYSTEM => Ok(Category::System), + ffi::_ND_INS_TYPE::ND_CAT_TDX => Ok(Category::Tdx), + ffi::_ND_INS_TYPE::ND_CAT_UD => Ok(Category::Ud), + ffi::_ND_INS_TYPE::ND_CAT_UINTR => Ok(Category::Uintr), + ffi::_ND_INS_TYPE::ND_CAT_UNCOND_BR => Ok(Category::UncondBr), + ffi::_ND_INS_TYPE::ND_CAT_UNKNOWN => Ok(Category::Unknown), + ffi::_ND_INS_TYPE::ND_CAT_VAES => Ok(Category::Vaes), + ffi::_ND_INS_TYPE::ND_CAT_VFMA => Ok(Category::Vfma), + ffi::_ND_INS_TYPE::ND_CAT_VFMAPS => Ok(Category::Vfmaps), + ffi::_ND_INS_TYPE::ND_CAT_VNNI => Ok(Category::Vnni), + ffi::_ND_INS_TYPE::ND_CAT_VNNIW => Ok(Category::Vnniw), + ffi::_ND_INS_TYPE::ND_CAT_VPCLMULQDQ => Ok(Category::Vpclmulqdq), + ffi::_ND_INS_TYPE::ND_CAT_VPOPCNT => Ok(Category::Vpopcnt), + ffi::_ND_INS_TYPE::ND_CAT_VTX => Ok(Category::Vtx), + ffi::_ND_INS_TYPE::ND_CAT_WAITPKG => Ok(Category::Waitpkg), + ffi::_ND_INS_TYPE::ND_CAT_WBNOINVD => Ok(Category::Wbnoinvd), + ffi::_ND_INS_TYPE::ND_CAT_WIDENOP => Ok(Category::Widenop), + ffi::_ND_INS_TYPE::ND_CAT_WIDE_KL => Ok(Category::WideKl), + ffi::_ND_INS_TYPE::ND_CAT_X87_ALU => Ok(Category::X87Alu), + ffi::_ND_INS_TYPE::ND_CAT_XOP => Ok(Category::Xop), + ffi::_ND_INS_TYPE::ND_CAT_XSAVE => Ok(Category::Xsave), + } + } +} diff --git a/rsbddisasm/bddisasm/src/isa_set.rs b/rsbddisasm/bddisasm/src/isa_set.rs new file mode 100644 index 0000000..1861284 --- /dev/null +++ b/rsbddisasm/bddisasm/src/isa_set.rs @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2021 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ +//! Instruction sets. + +extern crate bddisasm_sys as ffi; + +use super::decode_error; +use std::convert::TryFrom; + +/// ISA set. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum IsaSet { + I3dnow, + Adx, + Aes, + Amd, + Amxbf16, + Amxint8, + Amxtile, + Avx, + Avx2, + Avx2gather, + Avx5124fmaps, + Avx5124vnniw, + Avx512bf16, + Avx512bitalg, + Avx512bw, + Avx512cd, + Avx512dq, + Avx512er, + Avx512f, + Avx512fp16, + Avx512ifma, + Avx512pf, + Avx512vbmi, + Avx512vbmi2, + Avx512vnni, + Avx512vp2intersect, + Avx512vpopcntdq, + Avxvnni, + Bmi1, + Bmi2, + CetIbt, + CetSs, + Cldemote, + Clfsh, + Clfshopt, + Clwb, + Clzero, + Cmpxchg16b, + Cyrix, + CyrixSmm, + Enqcmd, + F16c, + Fma, + Fma4, + Fred, + Fxsave, + Gfni, + Hreset, + I186, + I286prot, + I286real, + I386, + I486, + I486real, + I64, + I86, + Invlpgb, + Invpcid, + Kl, + Lkgs, + Longmode, + Lwp, + Lzcnt, + Mcommit, + Mmx, + Movbe, + Movdir64b, + Movdiri, + Mpx, + Mwaitt, + Pause, + Pclmulqdq, + Pconfig, + Pentiumreal, + Pku, + Popcnt, + Ppro, + PrefetchNop, + Ptwrite, + Rdpid, + Rdpmc, + Rdpru, + Rdrand, + Rdseed, + Rdtscp, + Rdwrfsgs, + Serialize, + Sgx, + Sha, + Smap, + Smx, + Snp, + Sse, + Sse2, + Sse3, + Sse4, + Sse42, + Sse4a, + Ssse3, + Svm, + Tbm, + Tdx, + Tsx, + Tsxldtrk, + Ud, + Uintr, + Unknown, + Vaes, + Vpclmulqdq, + Vtx, + Waitpkg, + Wbnoinvd, + X87, + Xop, + Xsave, + Xsavec, + Xsaves, +} + +#[doc(hidden)] +impl TryFrom for IsaSet { + type Error = decode_error::DecodeError; + + fn try_from(value: ffi::ND_INS_SET) -> Result { + match value { + ffi::_ND_INS_SET::ND_SET_INVALID => { + Err(decode_error::DecodeError::UnknownInstruction(value as u32)) + } + ffi::_ND_INS_SET::ND_SET_3DNOW => Ok(IsaSet::I3dnow), + ffi::_ND_INS_SET::ND_SET_ADX => Ok(IsaSet::Adx), + ffi::_ND_INS_SET::ND_SET_AES => Ok(IsaSet::Aes), + ffi::_ND_INS_SET::ND_SET_AMD => Ok(IsaSet::Amd), + ffi::_ND_INS_SET::ND_SET_AMXBF16 => Ok(IsaSet::Amxbf16), + ffi::_ND_INS_SET::ND_SET_AMXINT8 => Ok(IsaSet::Amxint8), + ffi::_ND_INS_SET::ND_SET_AMXTILE => Ok(IsaSet::Amxtile), + ffi::_ND_INS_SET::ND_SET_AVX => Ok(IsaSet::Avx), + ffi::_ND_INS_SET::ND_SET_AVX2 => Ok(IsaSet::Avx2), + ffi::_ND_INS_SET::ND_SET_AVX2GATHER => Ok(IsaSet::Avx2gather), + ffi::_ND_INS_SET::ND_SET_AVX5124FMAPS => Ok(IsaSet::Avx5124fmaps), + ffi::_ND_INS_SET::ND_SET_AVX5124VNNIW => Ok(IsaSet::Avx5124vnniw), + ffi::_ND_INS_SET::ND_SET_AVX512BF16 => Ok(IsaSet::Avx512bf16), + ffi::_ND_INS_SET::ND_SET_AVX512BITALG => Ok(IsaSet::Avx512bitalg), + ffi::_ND_INS_SET::ND_SET_AVX512BW => Ok(IsaSet::Avx512bw), + ffi::_ND_INS_SET::ND_SET_AVX512CD => Ok(IsaSet::Avx512cd), + ffi::_ND_INS_SET::ND_SET_AVX512DQ => Ok(IsaSet::Avx512dq), + ffi::_ND_INS_SET::ND_SET_AVX512ER => Ok(IsaSet::Avx512er), + ffi::_ND_INS_SET::ND_SET_AVX512F => Ok(IsaSet::Avx512f), + ffi::_ND_INS_SET::ND_SET_AVX512FP16 => Ok(IsaSet::Avx512fp16), + ffi::_ND_INS_SET::ND_SET_AVX512IFMA => Ok(IsaSet::Avx512ifma), + ffi::_ND_INS_SET::ND_SET_AVX512PF => Ok(IsaSet::Avx512pf), + ffi::_ND_INS_SET::ND_SET_AVX512VBMI => Ok(IsaSet::Avx512vbmi), + ffi::_ND_INS_SET::ND_SET_AVX512VBMI2 => Ok(IsaSet::Avx512vbmi2), + ffi::_ND_INS_SET::ND_SET_AVX512VNNI => Ok(IsaSet::Avx512vnni), + ffi::_ND_INS_SET::ND_SET_AVX512VP2INTERSECT => Ok(IsaSet::Avx512vp2intersect), + ffi::_ND_INS_SET::ND_SET_AVX512VPOPCNTDQ => Ok(IsaSet::Avx512vpopcntdq), + ffi::_ND_INS_SET::ND_SET_AVXVNNI => Ok(IsaSet::Avxvnni), + ffi::_ND_INS_SET::ND_SET_BMI1 => Ok(IsaSet::Bmi1), + ffi::_ND_INS_SET::ND_SET_BMI2 => Ok(IsaSet::Bmi2), + ffi::_ND_INS_SET::ND_SET_CET_IBT => Ok(IsaSet::CetIbt), + ffi::_ND_INS_SET::ND_SET_CET_SS => Ok(IsaSet::CetSs), + ffi::_ND_INS_SET::ND_SET_CLDEMOTE => Ok(IsaSet::Cldemote), + ffi::_ND_INS_SET::ND_SET_CLFSH => Ok(IsaSet::Clfsh), + ffi::_ND_INS_SET::ND_SET_CLFSHOPT => Ok(IsaSet::Clfshopt), + ffi::_ND_INS_SET::ND_SET_CLWB => Ok(IsaSet::Clwb), + ffi::_ND_INS_SET::ND_SET_CLZERO => Ok(IsaSet::Clzero), + ffi::_ND_INS_SET::ND_SET_CMPXCHG16B => Ok(IsaSet::Cmpxchg16b), + ffi::_ND_INS_SET::ND_SET_CYRIX => Ok(IsaSet::Cyrix), + ffi::_ND_INS_SET::ND_SET_CYRIX_SMM => Ok(IsaSet::CyrixSmm), + ffi::_ND_INS_SET::ND_SET_ENQCMD => Ok(IsaSet::Enqcmd), + ffi::_ND_INS_SET::ND_SET_F16C => Ok(IsaSet::F16c), + ffi::_ND_INS_SET::ND_SET_FMA => Ok(IsaSet::Fma), + ffi::_ND_INS_SET::ND_SET_FMA4 => Ok(IsaSet::Fma4), + ffi::_ND_INS_SET::ND_SET_FRED => Ok(IsaSet::Fred), + ffi::_ND_INS_SET::ND_SET_FXSAVE => Ok(IsaSet::Fxsave), + ffi::_ND_INS_SET::ND_SET_GFNI => Ok(IsaSet::Gfni), + ffi::_ND_INS_SET::ND_SET_HRESET => Ok(IsaSet::Hreset), + ffi::_ND_INS_SET::ND_SET_I186 => Ok(IsaSet::I186), + ffi::_ND_INS_SET::ND_SET_I286PROT => Ok(IsaSet::I286prot), + ffi::_ND_INS_SET::ND_SET_I286REAL => Ok(IsaSet::I286real), + ffi::_ND_INS_SET::ND_SET_I386 => Ok(IsaSet::I386), + ffi::_ND_INS_SET::ND_SET_I486 => Ok(IsaSet::I486), + ffi::_ND_INS_SET::ND_SET_I486REAL => Ok(IsaSet::I486real), + ffi::_ND_INS_SET::ND_SET_I64 => Ok(IsaSet::I64), + ffi::_ND_INS_SET::ND_SET_I86 => Ok(IsaSet::I86), + ffi::_ND_INS_SET::ND_SET_INVLPGB => Ok(IsaSet::Invlpgb), + ffi::_ND_INS_SET::ND_SET_INVPCID => Ok(IsaSet::Invpcid), + ffi::_ND_INS_SET::ND_SET_KL => Ok(IsaSet::Kl), + ffi::_ND_INS_SET::ND_SET_LKGS => Ok(IsaSet::Lkgs), + ffi::_ND_INS_SET::ND_SET_LONGMODE => Ok(IsaSet::Longmode), + ffi::_ND_INS_SET::ND_SET_LWP => Ok(IsaSet::Lwp), + ffi::_ND_INS_SET::ND_SET_LZCNT => Ok(IsaSet::Lzcnt), + ffi::_ND_INS_SET::ND_SET_MCOMMIT => Ok(IsaSet::Mcommit), + ffi::_ND_INS_SET::ND_SET_MMX => Ok(IsaSet::Mmx), + ffi::_ND_INS_SET::ND_SET_MOVBE => Ok(IsaSet::Movbe), + ffi::_ND_INS_SET::ND_SET_MOVDIR64B => Ok(IsaSet::Movdir64b), + ffi::_ND_INS_SET::ND_SET_MOVDIRI => Ok(IsaSet::Movdiri), + ffi::_ND_INS_SET::ND_SET_MPX => Ok(IsaSet::Mpx), + ffi::_ND_INS_SET::ND_SET_MWAITT => Ok(IsaSet::Mwaitt), + ffi::_ND_INS_SET::ND_SET_PAUSE => Ok(IsaSet::Pause), + ffi::_ND_INS_SET::ND_SET_PCLMULQDQ => Ok(IsaSet::Pclmulqdq), + ffi::_ND_INS_SET::ND_SET_PCONFIG => Ok(IsaSet::Pconfig), + ffi::_ND_INS_SET::ND_SET_PENTIUMREAL => Ok(IsaSet::Pentiumreal), + ffi::_ND_INS_SET::ND_SET_PKU => Ok(IsaSet::Pku), + ffi::_ND_INS_SET::ND_SET_POPCNT => Ok(IsaSet::Popcnt), + ffi::_ND_INS_SET::ND_SET_PPRO => Ok(IsaSet::Ppro), + ffi::_ND_INS_SET::ND_SET_PREFETCH_NOP => Ok(IsaSet::PrefetchNop), + ffi::_ND_INS_SET::ND_SET_PTWRITE => Ok(IsaSet::Ptwrite), + ffi::_ND_INS_SET::ND_SET_RDPID => Ok(IsaSet::Rdpid), + ffi::_ND_INS_SET::ND_SET_RDPMC => Ok(IsaSet::Rdpmc), + ffi::_ND_INS_SET::ND_SET_RDPRU => Ok(IsaSet::Rdpru), + ffi::_ND_INS_SET::ND_SET_RDRAND => Ok(IsaSet::Rdrand), + ffi::_ND_INS_SET::ND_SET_RDSEED => Ok(IsaSet::Rdseed), + ffi::_ND_INS_SET::ND_SET_RDTSCP => Ok(IsaSet::Rdtscp), + ffi::_ND_INS_SET::ND_SET_RDWRFSGS => Ok(IsaSet::Rdwrfsgs), + ffi::_ND_INS_SET::ND_SET_SERIALIZE => Ok(IsaSet::Serialize), + ffi::_ND_INS_SET::ND_SET_SGX => Ok(IsaSet::Sgx), + ffi::_ND_INS_SET::ND_SET_SHA => Ok(IsaSet::Sha), + ffi::_ND_INS_SET::ND_SET_SMAP => Ok(IsaSet::Smap), + ffi::_ND_INS_SET::ND_SET_SMX => Ok(IsaSet::Smx), + ffi::_ND_INS_SET::ND_SET_SNP => Ok(IsaSet::Snp), + ffi::_ND_INS_SET::ND_SET_SSE => Ok(IsaSet::Sse), + ffi::_ND_INS_SET::ND_SET_SSE2 => Ok(IsaSet::Sse2), + ffi::_ND_INS_SET::ND_SET_SSE3 => Ok(IsaSet::Sse3), + ffi::_ND_INS_SET::ND_SET_SSE4 => Ok(IsaSet::Sse4), + ffi::_ND_INS_SET::ND_SET_SSE42 => Ok(IsaSet::Sse42), + ffi::_ND_INS_SET::ND_SET_SSE4A => Ok(IsaSet::Sse4a), + ffi::_ND_INS_SET::ND_SET_SSSE3 => Ok(IsaSet::Ssse3), + ffi::_ND_INS_SET::ND_SET_SVM => Ok(IsaSet::Svm), + ffi::_ND_INS_SET::ND_SET_TBM => Ok(IsaSet::Tbm), + ffi::_ND_INS_SET::ND_SET_TDX => Ok(IsaSet::Tdx), + ffi::_ND_INS_SET::ND_SET_TSX => Ok(IsaSet::Tsx), + ffi::_ND_INS_SET::ND_SET_TSXLDTRK => Ok(IsaSet::Tsxldtrk), + ffi::_ND_INS_SET::ND_SET_UD => Ok(IsaSet::Ud), + ffi::_ND_INS_SET::ND_SET_UINTR => Ok(IsaSet::Uintr), + ffi::_ND_INS_SET::ND_SET_UNKNOWN => Ok(IsaSet::Unknown), + ffi::_ND_INS_SET::ND_SET_VAES => Ok(IsaSet::Vaes), + ffi::_ND_INS_SET::ND_SET_VPCLMULQDQ => Ok(IsaSet::Vpclmulqdq), + ffi::_ND_INS_SET::ND_SET_VTX => Ok(IsaSet::Vtx), + ffi::_ND_INS_SET::ND_SET_WAITPKG => Ok(IsaSet::Waitpkg), + ffi::_ND_INS_SET::ND_SET_WBNOINVD => Ok(IsaSet::Wbnoinvd), + ffi::_ND_INS_SET::ND_SET_X87 => Ok(IsaSet::X87), + ffi::_ND_INS_SET::ND_SET_XOP => Ok(IsaSet::Xop), + ffi::_ND_INS_SET::ND_SET_XSAVE => Ok(IsaSet::Xsave), + ffi::_ND_INS_SET::ND_SET_XSAVEC => Ok(IsaSet::Xsavec), + ffi::_ND_INS_SET::ND_SET_XSAVES => Ok(IsaSet::Xsaves), + } + } +} diff --git a/rsbddisasm/bddisasm/src/lib.rs b/rsbddisasm/bddisasm/src/lib.rs new file mode 100644 index 0000000..7ec0c85 --- /dev/null +++ b/rsbddisasm/bddisasm/src/lib.rs @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2021 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ +//! bddisasm x86/x64 instruction decoder +//! +//! This crate contains bindings for the [bddisasm](https://github.com/bitdefender/bddisasm) x86/x64 decoder library. +//! It supports all existing x86 instruction, offering a wide range of information about each one, including: +//! +//! - operands (implicit and explicit) +//! - access mode for each operand +//! - CPUID feature flags +//! - CPU modes in which an instruction is valid +//! +//! # Usage +//! +//! Add `bddisasm` to your `Cargo.toml`: +//! +//! ```toml +//! [dependencies] +//! bddisasm = "0.1.0" +//! ``` +//! +//! # Examples +//! +//! ## Decoding one instruction +//! +//! Use [DecodedInstruction::decode](crate::decoded_instruction::DecodedInstruction::decode) to decode an instruction +//! from a chunk of code. +//! +//! ``` +//! use bddisasm::decoded_instruction::{DecodedInstruction, DecodeMode, Mnemonic}; +//! +//! let code = vec![0x31, 0xc0]; +//! match DecodedInstruction::decode(&code, DecodeMode::Bits32) { +//! Ok(ins) => { +//! assert_eq!(ins.mnemonic(), Mnemonic::Xor); +//! println!("{}", ins); +//! }, +//! Err(err) => println!("Unable to decode: {}", err), +//! } +//! ``` +//! +//! ## Decoding multiple instructions +//! +//! Use [Decoder](crate::decoder::Decoder) to decode multiple instructions from a chunk of code. +//! +//! ``` +//! use bddisasm::decoder::{Decoder, DecodeMode}; +//! +//! let code = [ +//! // ENCLS +//! 0x0f, 0x01, 0xcf, +//! // MOV rax, qword ptr [rbx+rcx*4+0x1234] +//! 0x48, 0x8b, 0x84, 0x8b, 0x34, 0x12, 0x00, 0x00, +//! // Not a valid instruction +//! 0x0f, +//! // WRMSR +//! 0x0f, 0x30, +//! ]; +//! let decoder = Decoder::new(&code, DecodeMode::Bits64, 0x1234); +//! +//! for ins in decoder { +//! match ins { +//! Ok(ins) => println!("{}", ins), +//! Err(e) => println!("{}", e), +//! } +//! } +//! ``` +//! +//! This will print: +//! +//! ```text +//! ENCLS +//! MOV rax, qword ptr [rbx+rcx*4+0x1234] +//! the provided input buffer is too small +//! WRMSR +//! ``` +//! +//! Use [Decoder::decode_next_with_info](crate::decoder::Decoder::decode_next_with_info) to get information about the +//! offset inside the code chunk at which an instruction was decoded from. +//! +//! ``` +//! use bddisasm::decoder::{Decoder, DecodeMode}; +//! +//! let code = [ +//! // ENCLS +//! 0x0f, 0x01, 0xcf, +//! // MOV rax, qword ptr [rbx+rcx*4+0x1234] +//! 0x48, 0x8b, 0x84, 0x8b, 0x34, 0x12, 0x00, 0x00, +//! // Not a valid instruction +//! 0x0f, +//! // WRMSR +//! 0x0f, 0x30, +//! ]; +//! let mut decoder = Decoder::new(&code, DecodeMode::Bits64, 0x1234); +//! +//! +//! // Keep decoding until there's nothing left to decode +//! while let Some((result, offset, _)) = decoder.decode_next_with_info() { +//! match result { +//! Ok(ins) => println!("{:#x} {}", offset, ins), +//! Err(e) => println!("Error: `{}` at offset {:#x}", e, offset), +//! } +//! } +//! ``` +//! +//! This will print: +//! +//! ```text +//! 0x0 ENCLS +//! 0x3 MOV rax, qword ptr [rbx+rcx*4+0x1234] +//! Error `the provided input buffer is too small` at offset 0xb +//! 0xc WRMSR +//! ``` +//! +//! ## Working with instruction operands +//! +//! Instruction operands can be analyzed using the [operand](crate::operand) module. Rich informaion is offered for +//! each type of operand. Bellow is a minimal example that looks at a memory operand. +//! +//! ``` +//! # use bddisasm::decode_error::DecodeError; +//! # fn test() -> Result<(), DecodeError> { +//! use bddisasm::decoded_instruction::{DecodedInstruction, DecodeMode}; +//! use bddisasm::operand::OpInfo; +//! +//! // ` MOV rax, qword ptr [rcx+r15*2]` +//! let code = b"\x4a\x8b\x04\x79"; +//! let ins = DecodedInstruction::decode(code, DecodeMode::Bits64).unwrap(); +//! // Get the operands +//! let operands = ins.operands(); +//! // Get the second operand which is the source (`[rcx+r15*2]`) +//! let src = operands[1]; +//! +//! println!("Source operand type: {}", src.info); +//! match src.info { +//! OpInfo::Mem(mem) => { +//! if let Some(base) = mem.base { +//! println!("Base register: {}", base); +//! } else { +//! println!("No base register"); +//! } +//! +//! if let Some(index) = mem.index { +//! println!("Index register: {}", index); +//! } else { +//! println!("No index register"); +//! } +//! +//! if let Some(scale) = mem.scale { +//! println!("Scale: {}", scale); +//! } else { +//! println!("No scale"); +//! } +//! +//! if let Some(displacement) = mem.disp { +//! println!("Displacement: {}", displacement); +//! } else { +//! println!("No displacement"); +//! } +//! }, +//! _ => unreachable!(), +//! } +//! # Ok(()) +//! # } +//! ``` +//! +//! Will print: +//! +//! ```text +//! Source operand type: memory +//! Base register: 1 +//! Index register: 15 +//! Scale: 2 +//! No displacement +//! ``` +pub mod cpu_modes; +pub mod cpuid; +pub mod decode_error; +pub mod decoded_instruction; +pub mod decoder; +pub mod fpu_flags; +pub mod instruction_category; +pub mod isa_set; +pub mod mnemonic; +pub mod operand; +pub mod rflags; +pub mod tuple; diff --git a/rsbddisasm/bddisasm/src/mnemonic.rs b/rsbddisasm/bddisasm/src/mnemonic.rs new file mode 100644 index 0000000..15836a3 --- /dev/null +++ b/rsbddisasm/bddisasm/src/mnemonic.rs @@ -0,0 +1,3198 @@ +/* + * Copyright (c) 2021 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ +//! Mnemonics. + +extern crate bddisasm_sys as ffi; + +use super::decode_error; +use std::convert::TryFrom; + +/// Uniquely identifies an instruction. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum Mnemonic { + Aaa, + Aad, + Aam, + Aas, + Adc, + Adcx, + Add, + Addpd, + Addps, + Addsd, + Addss, + Addsubpd, + Addsubps, + Adox, + Aesdec, + Aesdec128kl, + Aesdec256kl, + Aesdeclast, + Aesdecwide128kl, + Aesdecwide256kl, + Aesenc, + Aesenc128kl, + Aesenc256kl, + Aesenclast, + Aesencwide128kl, + Aesencwide256kl, + Aesimc, + Aeskeygenassist, + Altinst, + And, + Andn, + Andnpd, + Andnps, + Andpd, + Andps, + Arpl, + Bextr, + Blcfill, + Blci, + Blcic, + Blcmsk, + Blcs, + Blendpd, + Blendps, + Blendvpd, + Blendvps, + Blsfill, + Blsi, + Blsic, + Blsmsk, + Blsr, + Bndcl, + Bndcn, + Bndcu, + Bndldx, + Bndmk, + Bndmov, + Bndstx, + Bound, + Bsf, + Bsr, + Bswap, + Bt, + Btc, + Btr, + Bts, + Bzhi, + Callfd, + Callfi, + Callni, + Callnr, + Cbw, + Cdq, + Cdqe, + Clac, + Clc, + Cld, + Cldemote, + Clevict0, + Clevict1, + Clflush, + Clflushopt, + Clgi, + Cli, + Clrssbsy, + Clts, + Clui, + Clwb, + Clzero, + Cmc, + Cmovcc, + Cmp, + Cmppd, + Cmpps, + Cmps, + Cmpsd, + Cmpss, + Cmpxchg, + Cmpxchg16b, + Cmpxchg8b, + Comisd, + Comiss, + Cpuid, + CpuRead, + CpuWrite, + Cqo, + Crc32, + Cvtdq2pd, + Cvtdq2ps, + Cvtpd2dq, + Cvtpd2pi, + Cvtpd2ps, + Cvtpi2pd, + Cvtpi2ps, + Cvtps2dq, + Cvtps2pd, + Cvtps2pi, + Cvtsd2si, + Cvtsd2ss, + Cvtsi2sd, + Cvtsi2ss, + Cvtss2sd, + Cvtss2si, + Cvttpd2dq, + Cvttpd2pi, + Cvttps2dq, + Cvttps2pi, + Cvttsd2si, + Cvttss2si, + Cwd, + Cwde, + Daa, + Das, + Dec, + Delay, + Div, + Divpd, + Divps, + Divsd, + Divss, + Dmint, + Dppd, + Dpps, + Emms, + Encls, + Enclu, + Enclv, + Encodekey128, + Encodekey256, + Endbr, + Enqcmd, + Enqcmds, + Enter, + Erets, + Eretu, + Extractps, + Extrq, + F2xm1, + Fabs, + Fadd, + Faddp, + Fbld, + Fbstp, + Fchs, + Fcmovb, + Fcmovbe, + Fcmove, + Fcmovnb, + Fcmovnbe, + Fcmovne, + Fcmovnu, + Fcmovu, + Fcom, + Fcomi, + Fcomip, + Fcomp, + Fcompp, + Fcos, + Fdecstp, + Fdiv, + Fdivp, + Fdivr, + Fdivrp, + Femms, + Ffree, + Ffreep, + Fiadd, + Ficom, + Ficomp, + Fidiv, + Fidivr, + Fild, + Fimul, + Fincstp, + Fist, + Fistp, + Fisttp, + Fisub, + Fisubr, + Fld, + Fld1, + Fldcw, + Fldenv, + Fldl2e, + Fldl2t, + Fldlg2, + Fldln2, + Fldpi, + Fldz, + Fmul, + Fmulp, + Fnclex, + Fndisi, + Fninit, + Fnop, + Fnsave, + Fnstcw, + Fnstenv, + Fnstsw, + Fpatan, + Fprem, + Fprem1, + Fptan, + Frinear, + Frndint, + Frstor, + Fscale, + Fsin, + Fsincos, + Fsqrt, + Fst, + Fstdw, + Fstp, + Fstpnce, + Fstsg, + Fsub, + Fsubp, + Fsubr, + Fsubrp, + Ftst, + Fucom, + Fucomi, + Fucomip, + Fucomp, + Fucompp, + Fxam, + Fxch, + Fxrstor, + Fxrstor64, + Fxsave, + Fxsave64, + Fxtract, + Fyl2x, + Fyl2xp1, + Getsec, + Gf2p8affineinvqb, + Gf2p8affineqb, + Gf2p8mulb, + Haddpd, + Haddps, + Hlt, + Hreset, + Hsubpd, + Hsubps, + Idiv, + Imul, + In, + Inc, + Incssp, + Ins, + Insertps, + Insertq, + Int, + Int1, + Int3, + Into, + Invd, + Invept, + Invlpg, + Invlpga, + Invlpgb, + Invpcid, + Invvpid, + Iret, + Jmpe, + Jmpfd, + Jmpfi, + Jmpni, + Jmpnr, + Jcc, + Jrcxz, + Kadd, + Kand, + Kandn, + Kmerge2l1h, + Kmerge2l1l, + Kmov, + Knot, + Kor, + Kortest, + Kshiftl, + Kshiftr, + Ktest, + Kunpckbw, + Kunpckdq, + Kunpckwd, + Kxnor, + Kxor, + Lahf, + Lar, + Lddqu, + Ldmxcsr, + Lds, + Ldtilecfg, + Lea, + Leave, + Les, + Lfence, + Lfs, + Lgdt, + Lgs, + Lidt, + Lkgs, + Lldt, + Llwpcb, + Lmsw, + Loadiwkey, + Lods, + Loop, + Loopnz, + Loopz, + Lsl, + Lss, + Ltr, + Lwpins, + Lwpval, + Lzcnt, + Maskmovdqu, + Maskmovq, + Maxpd, + Maxps, + Maxsd, + Maxss, + Mcommit, + Mfence, + Minpd, + Minps, + Minsd, + Minss, + Monitor, + Monitorx, + Montmul, + Mov, + Movapd, + Movaps, + Movbe, + Movd, + Movddup, + Movdir64b, + Movdiri, + Movdq2q, + Movdqa, + Movdqu, + Movhlps, + Movhpd, + Movhps, + Movlhps, + Movlpd, + Movlps, + Movmskpd, + Movmskps, + Movntdq, + Movntdqa, + Movnti, + Movntpd, + Movntps, + Movntq, + Movntsd, + Movntss, + Movq, + Movq2dq, + Movs, + Movsd, + Movshdup, + Movsldup, + Movss, + Movsx, + Movsxd, + Movupd, + Movups, + Movzx, + MovCr, + MovDr, + MovTr, + Mpsadbw, + Mul, + Mulpd, + Mulps, + Mulsd, + Mulss, + Mulx, + Mwait, + Mwaitx, + Neg, + Nop, + Not, + Or, + Orpd, + Orps, + Out, + Outs, + Pabsb, + Pabsd, + Pabsw, + Packssdw, + Packsswb, + Packusdw, + Packuswb, + Paddb, + Paddd, + Paddq, + Paddsb, + Paddsw, + Paddusb, + Paddusw, + Paddw, + Palignr, + Pand, + Pandn, + Pause, + Pavgb, + Pavgusb, + Pavgw, + Pblendvb, + Pblendw, + Pclmulqdq, + Pcmpeqb, + Pcmpeqd, + Pcmpeqq, + Pcmpeqw, + Pcmpestri, + Pcmpestrm, + Pcmpgtb, + Pcmpgtd, + Pcmpgtq, + Pcmpgtw, + Pcmpistri, + Pcmpistrm, + Pconfig, + Pdep, + Pext, + Pextrb, + Pextrd, + Pextrq, + Pextrw, + Pf2id, + Pf2iw, + Pfacc, + Pfadd, + Pfcmpeq, + Pfcmpge, + Pfcmpgt, + Pfmax, + Pfmin, + Pfmul, + Pfnacc, + Pfpnacc, + Pfrcp, + Pfrcpit1, + Pfrcpit2, + Pfrcpv, + Pfrsqit1, + Pfrsqrt, + Pfrsqrtv, + Pfsub, + Pfsubr, + Phaddd, + Phaddsw, + Phaddw, + Phminposuw, + Phsubd, + Phsubsw, + Phsubw, + Pi2fd, + Pi2fw, + Pinsrb, + Pinsrd, + Pinsrq, + Pinsrw, + Pmaddubsw, + Pmaddwd, + Pmaxsb, + Pmaxsd, + Pmaxsw, + Pmaxub, + Pmaxud, + Pmaxuw, + Pminsb, + Pminsd, + Pminsw, + Pminub, + Pminud, + Pminuw, + Pmovmskb, + Pmovsxbd, + Pmovsxbq, + Pmovsxbw, + Pmovsxdq, + Pmovsxwd, + Pmovsxwq, + Pmovzxbd, + Pmovzxbq, + Pmovzxbw, + Pmovzxdq, + Pmovzxwd, + Pmovzxwq, + Pmuldq, + Pmulhrsw, + Pmulhrw, + Pmulhuw, + Pmulhw, + Pmulld, + Pmullw, + Pmuludq, + Pop, + Popa, + Popad, + Popcnt, + Popf, + Por, + Prefetch, + Prefetche, + Prefetchm, + Prefetchnta, + Prefetcht0, + Prefetcht1, + Prefetcht2, + Prefetchw, + Prefetchwt1, + Psadbw, + Pshufb, + Pshufd, + Pshufhw, + Pshuflw, + Pshufw, + Psignb, + Psignd, + Psignw, + Pslld, + Pslldq, + Psllq, + Psllw, + Psmash, + Psrad, + Psraw, + Psrld, + Psrldq, + Psrlq, + Psrlw, + Psubb, + Psubd, + Psubq, + Psubsb, + Psubsw, + Psubusb, + Psubusw, + Psubw, + Pswapd, + Ptest, + Ptwrite, + Punpckhbw, + Punpckhdq, + Punpckhqdq, + Punpckhwd, + Punpcklbw, + Punpckldq, + Punpcklqdq, + Punpcklwd, + Push, + Pusha, + Pushad, + Pushf, + Pvalidate, + Pxor, + Rcl, + Rcpps, + Rcpss, + Rcr, + Rdfsbase, + Rdgsbase, + Rdmsr, + Rdpid, + Rdpkru, + Rdpmc, + Rdpru, + Rdrand, + Rdseed, + Rdshr, + Rdtsc, + Rdtscp, + Retf, + Retn, + Rmpadjust, + Rmpupdate, + Rol, + Ror, + Rorx, + Roundpd, + Roundps, + Roundsd, + Roundss, + Rsdc, + Rsldt, + Rsm, + Rsqrtps, + Rsqrtss, + Rsssp, + Rstorssp, + Rsts, + Sahf, + Sal, + Salc, + Sar, + Sarx, + Saveprevssp, + Sbb, + Scas, + Seamcall, + Seamops, + Seamret, + Senduipi, + Serialize, + Setssbsy, + Setcc, + Sfence, + Sgdt, + Sha1msg1, + Sha1msg2, + Sha1nexte, + Sha1rnds4, + Sha256msg1, + Sha256msg2, + Sha256rnds2, + Shl, + Shld, + Shlx, + Shr, + Shrd, + Shrx, + Shufpd, + Shufps, + Sidt, + Skinit, + Sldt, + Slwpcb, + Smint, + Smsw, + Spflt, + Sqrtpd, + Sqrtps, + Sqrtsd, + Sqrtss, + Stac, + Stc, + Std, + Stgi, + Sti, + Stmxcsr, + Stos, + Str, + Sttilecfg, + Stui, + Sub, + Subpd, + Subps, + Subsd, + Subss, + Svdc, + Svldt, + Svts, + Swapgs, + Syscall, + Sysenter, + Sysexit, + Sysret, + T1mskc, + Tdcall, + Tdpbf16ps, + Tdpbssd, + Tdpbsud, + Tdpbusd, + Tdpbuud, + Test, + Testui, + Tileloadd, + Tileloaddt1, + Tilerelease, + Tilestored, + Tilezero, + Tlbsync, + Tpause, + Tzcnt, + Tzmsk, + Ucomisd, + Ucomiss, + Ud0, + Ud1, + Ud2, + Uiret, + Umonitor, + Umwait, + Unpckhpd, + Unpckhps, + Unpcklpd, + Unpcklps, + V4fmaddps, + V4fmaddss, + V4fnmaddps, + V4fnmaddss, + Vaddpd, + Vaddph, + Vaddps, + Vaddsd, + Vaddsh, + Vaddss, + Vaddsubpd, + Vaddsubps, + Vaesdec, + Vaesdeclast, + Vaesenc, + Vaesenclast, + Vaesimc, + Vaeskeygenassist, + Valignd, + Valignq, + Vandnpd, + Vandnps, + Vandpd, + Vandps, + Vblendmpd, + Vblendmps, + Vblendpd, + Vblendps, + Vblendvpd, + Vblendvps, + Vbroadcastf128, + Vbroadcastf32x2, + Vbroadcastf32x4, + Vbroadcastf32x8, + Vbroadcastf64x2, + Vbroadcastf64x4, + Vbroadcasti128, + Vbroadcasti32x2, + Vbroadcasti32x4, + Vbroadcasti32x8, + Vbroadcasti64x2, + Vbroadcasti64x4, + Vbroadcastsd, + Vbroadcastss, + Vcmppd, + Vcmpph, + Vcmpps, + Vcmpsd, + Vcmpsh, + Vcmpss, + Vcomisd, + Vcomish, + Vcomiss, + Vcompresspd, + Vcompressps, + Vcvtdq2pd, + Vcvtdq2ph, + Vcvtdq2ps, + Vcvtne2ps2bf16, + Vcvtneps2bf16, + Vcvtpd2dq, + Vcvtpd2ph, + Vcvtpd2ps, + Vcvtpd2qq, + Vcvtpd2udq, + Vcvtpd2uqq, + Vcvtph2dq, + Vcvtph2pd, + Vcvtph2ps, + Vcvtph2psx, + Vcvtph2qq, + Vcvtph2udq, + Vcvtph2uqq, + Vcvtph2uw, + Vcvtph2w, + Vcvtps2dq, + Vcvtps2pd, + Vcvtps2ph, + Vcvtps2phx, + Vcvtps2qq, + Vcvtps2udq, + Vcvtps2uqq, + Vcvtqq2pd, + Vcvtqq2ph, + Vcvtqq2ps, + Vcvtsd2sh, + Vcvtsd2si, + Vcvtsd2ss, + Vcvtsd2usi, + Vcvtsh2sd, + Vcvtsh2si, + Vcvtsh2ss, + Vcvtsh2usi, + Vcvtsi2sd, + Vcvtsi2sh, + Vcvtsi2ss, + Vcvtss2sd, + Vcvtss2sh, + Vcvtss2si, + Vcvtss2usi, + Vcvttpd2dq, + Vcvttpd2qq, + Vcvttpd2udq, + Vcvttpd2uqq, + Vcvttph2dq, + Vcvttph2qq, + Vcvttph2udq, + Vcvttph2uqq, + Vcvttph2uw, + Vcvttph2w, + Vcvttps2dq, + Vcvttps2qq, + Vcvttps2udq, + Vcvttps2uqq, + Vcvttsd2si, + Vcvttsd2usi, + Vcvttsh2si, + Vcvttsh2usi, + Vcvttss2si, + Vcvttss2usi, + Vcvtudq2pd, + Vcvtudq2ph, + Vcvtudq2ps, + Vcvtuqq2pd, + Vcvtuqq2ph, + Vcvtuqq2ps, + Vcvtusi2sd, + Vcvtusi2sh, + Vcvtusi2ss, + Vcvtuw2ph, + Vcvtw2ph, + Vdbpsadbw, + Vdivpd, + Vdivph, + Vdivps, + Vdivsd, + Vdivsh, + Vdivss, + Vdpbf16ps, + Vdppd, + Vdpps, + Verr, + Verw, + Vexp2pd, + Vexp2ps, + Vexpandpd, + Vexpandps, + Vextractf128, + Vextractf32x4, + Vextractf32x8, + Vextractf64x2, + Vextractf64x4, + Vextracti128, + Vextracti32x4, + Vextracti32x8, + Vextracti64x2, + Vextracti64x4, + Vextractps, + Vfcmaddcph, + Vfcmaddcsh, + Vfcmulcph, + Vfcmulcsh, + Vfixupimmpd, + Vfixupimmps, + Vfixupimmsd, + Vfixupimmss, + Vfmadd132pd, + Vfmadd132ph, + Vfmadd132ps, + Vfmadd132sd, + Vfmadd132sh, + Vfmadd132ss, + Vfmadd213pd, + Vfmadd213ph, + Vfmadd213ps, + Vfmadd213sd, + Vfmadd213sh, + Vfmadd213ss, + Vfmadd231pd, + Vfmadd231ph, + Vfmadd231ps, + Vfmadd231sd, + Vfmadd231sh, + Vfmadd231ss, + Vfmaddcph, + Vfmaddcsh, + Vfmaddpd, + Vfmaddps, + Vfmaddsd, + Vfmaddss, + Vfmaddsub132pd, + Vfmaddsub132ph, + Vfmaddsub132ps, + Vfmaddsub213pd, + Vfmaddsub213ph, + Vfmaddsub213ps, + Vfmaddsub231pd, + Vfmaddsub231ph, + Vfmaddsub231ps, + Vfmaddsubpd, + Vfmaddsubps, + Vfmsub132pd, + Vfmsub132ph, + Vfmsub132ps, + Vfmsub132sd, + Vfmsub132sh, + Vfmsub132ss, + Vfmsub213pd, + Vfmsub213ph, + Vfmsub213ps, + Vfmsub213sd, + Vfmsub213sh, + Vfmsub213ss, + Vfmsub231pd, + Vfmsub231ph, + Vfmsub231ps, + Vfmsub231sd, + Vfmsub231sh, + Vfmsub231ss, + Vfmsubadd132pd, + Vfmsubadd132ph, + Vfmsubadd132ps, + Vfmsubadd213pd, + Vfmsubadd213ph, + Vfmsubadd213ps, + Vfmsubadd231pd, + Vfmsubadd231ph, + Vfmsubadd231ps, + Vfmsubaddpd, + Vfmsubaddps, + Vfmsubpd, + Vfmsubps, + Vfmsubsd, + Vfmsubss, + Vfmulcph, + Vfmulcsh, + Vfnmadd132pd, + Vfnmadd132ph, + Vfnmadd132ps, + Vfnmadd132sd, + Vfnmadd132sh, + Vfnmadd132ss, + Vfnmadd213pd, + Vfnmadd213ph, + Vfnmadd213ps, + Vfnmadd213sd, + Vfnmadd213sh, + Vfnmadd213ss, + Vfnmadd231pd, + Vfnmadd231ph, + Vfnmadd231ps, + Vfnmadd231sd, + Vfnmadd231sh, + Vfnmadd231ss, + Vfnmaddpd, + Vfnmaddps, + Vfnmaddsd, + Vfnmaddss, + Vfnmsub132pd, + Vfnmsub132ph, + Vfnmsub132ps, + Vfnmsub132sd, + Vfnmsub132sh, + Vfnmsub132ss, + Vfnmsub213pd, + Vfnmsub213ph, + Vfnmsub213ps, + Vfnmsub213sd, + Vfnmsub213sh, + Vfnmsub213ss, + Vfnmsub231pd, + Vfnmsub231ph, + Vfnmsub231ps, + Vfnmsub231sd, + Vfnmsub231sh, + Vfnmsub231ss, + Vfnmsubpd, + Vfnmsubps, + Vfnmsubsd, + Vfnmsubss, + Vfpclasspd, + Vfpclassph, + Vfpclassps, + Vfpclasssd, + Vfpclasssh, + Vfpclassss, + Vfrczpd, + Vfrczps, + Vfrczsd, + Vfrczss, + Vgatherdpd, + Vgatherdps, + Vgatherpf0dpd, + Vgatherpf0dps, + Vgatherpf0qpd, + Vgatherpf0qps, + Vgatherpf1dpd, + Vgatherpf1dps, + Vgatherpf1qpd, + Vgatherpf1qps, + Vgatherqpd, + Vgatherqps, + Vgetexppd, + Vgetexpph, + Vgetexpps, + Vgetexpsd, + Vgetexpsh, + Vgetexpss, + Vgetmantpd, + Vgetmantph, + Vgetmantps, + Vgetmantsd, + Vgetmantsh, + Vgetmantss, + Vgf2p8affineinvqb, + Vgf2p8affineqb, + Vgf2p8mulb, + Vhaddpd, + Vhaddps, + Vhsubpd, + Vhsubps, + Vinsertf128, + Vinsertf32x4, + Vinsertf32x8, + Vinsertf64x2, + Vinsertf64x4, + Vinserti128, + Vinserti32x4, + Vinserti32x8, + Vinserti64x2, + Vinserti64x4, + Vinsertps, + Vlddqu, + Vldmxcsr, + Vmaskmovdqu, + Vmaskmovpd, + Vmaskmovps, + Vmaxpd, + Vmaxph, + Vmaxps, + Vmaxsd, + Vmaxsh, + Vmaxss, + Vmcall, + Vmclear, + Vmfunc, + Vmgexit, + Vminpd, + Vminph, + Vminps, + Vminsd, + Vminsh, + Vminss, + Vmlaunch, + Vmload, + Vmmcall, + Vmovapd, + Vmovaps, + Vmovd, + Vmovddup, + Vmovdqa, + Vmovdqa32, + Vmovdqa64, + Vmovdqu, + Vmovdqu16, + Vmovdqu32, + Vmovdqu64, + Vmovdqu8, + Vmovhlps, + Vmovhpd, + Vmovhps, + Vmovlhps, + Vmovlpd, + Vmovlps, + Vmovmskpd, + Vmovmskps, + Vmovntdq, + Vmovntdqa, + Vmovntpd, + Vmovntps, + Vmovq, + Vmovsd, + Vmovsh, + Vmovshdup, + Vmovsldup, + Vmovss, + Vmovupd, + Vmovups, + Vmovw, + Vmpsadbw, + Vmptrld, + Vmptrst, + Vmread, + Vmresume, + Vmrun, + Vmsave, + Vmulpd, + Vmulph, + Vmulps, + Vmulsd, + Vmulsh, + Vmulss, + Vmwrite, + Vmxoff, + Vmxon, + Vorpd, + Vorps, + Vp2intersectd, + Vp2intersectq, + Vp4dpwssd, + Vp4dpwssds, + Vpabsb, + Vpabsd, + Vpabsq, + Vpabsw, + Vpackssdw, + Vpacksswb, + Vpackusdw, + Vpackuswb, + Vpaddb, + Vpaddd, + Vpaddq, + Vpaddsb, + Vpaddsw, + Vpaddusb, + Vpaddusw, + Vpaddw, + Vpalignr, + Vpand, + Vpandd, + Vpandn, + Vpandnd, + Vpandnq, + Vpandq, + Vpavgb, + Vpavgw, + Vpblendd, + Vpblendmb, + Vpblendmd, + Vpblendmq, + Vpblendmw, + Vpblendvb, + Vpblendw, + Vpbroadcastb, + Vpbroadcastd, + Vpbroadcastmb2q, + Vpbroadcastmw2d, + Vpbroadcastq, + Vpbroadcastw, + Vpclmulqdq, + Vpcmov, + Vpcmpb, + Vpcmpd, + Vpcmpeqb, + Vpcmpeqd, + Vpcmpeqq, + Vpcmpeqw, + Vpcmpestri, + Vpcmpestrm, + Vpcmpgtb, + Vpcmpgtd, + Vpcmpgtq, + Vpcmpgtw, + Vpcmpistri, + Vpcmpistrm, + Vpcmpq, + Vpcmpub, + Vpcmpud, + Vpcmpuq, + Vpcmpuw, + Vpcmpw, + Vpcomb, + Vpcomd, + Vpcompressb, + Vpcompressd, + Vpcompressq, + Vpcompressw, + Vpcomq, + Vpcomub, + Vpcomud, + Vpcomuq, + Vpcomuw, + Vpcomw, + Vpconflictd, + Vpconflictq, + Vpdpbusd, + Vpdpbusds, + Vpdpwssd, + Vpdpwssds, + Vperm2f128, + Vperm2i128, + Vpermb, + Vpermd, + Vpermi2b, + Vpermi2d, + Vpermi2pd, + Vpermi2ps, + Vpermi2q, + Vpermi2w, + Vpermil2pd, + Vpermil2ps, + Vpermilpd, + Vpermilps, + Vpermpd, + Vpermps, + Vpermq, + Vpermt2b, + Vpermt2d, + Vpermt2pd, + Vpermt2ps, + Vpermt2q, + Vpermt2w, + Vpermw, + Vpexpandb, + Vpexpandd, + Vpexpandq, + Vpexpandw, + Vpextrb, + Vpextrd, + Vpextrq, + Vpextrw, + Vpgatherdd, + Vpgatherdq, + Vpgatherqd, + Vpgatherqq, + Vphaddbd, + Vphaddbq, + Vphaddbw, + Vphaddd, + Vphadddq, + Vphaddsw, + Vphaddubd, + Vphaddubq, + Vphaddubw, + Vphaddudq, + Vphadduwd, + Vphadduwq, + Vphaddw, + Vphaddwd, + Vphaddwq, + Vphminposuw, + Vphsubbw, + Vphsubd, + Vphsubdq, + Vphsubsw, + Vphsubw, + Vphsubwd, + Vpinsrb, + Vpinsrd, + Vpinsrq, + Vpinsrw, + Vplzcntd, + Vplzcntq, + Vpmacsdd, + Vpmacsdqh, + Vpmacsdql, + Vpmacssdd, + Vpmacssdqh, + Vpmacssdql, + Vpmacsswd, + Vpmacssww, + Vpmacswd, + Vpmacsww, + Vpmadcsswd, + Vpmadcswd, + Vpmadd52huq, + Vpmadd52luq, + Vpmaddubsw, + Vpmaddwd, + Vpmaskmovd, + Vpmaskmovq, + Vpmaxsb, + Vpmaxsd, + Vpmaxsq, + Vpmaxsw, + Vpmaxub, + Vpmaxud, + Vpmaxuq, + Vpmaxuw, + Vpminsb, + Vpminsd, + Vpminsq, + Vpminsw, + Vpminub, + Vpminud, + Vpminuq, + Vpminuw, + Vpmovb2m, + Vpmovd2m, + Vpmovdb, + Vpmovdw, + Vpmovm2b, + Vpmovm2d, + Vpmovm2q, + Vpmovm2w, + Vpmovmskb, + Vpmovq2m, + Vpmovqb, + Vpmovqd, + Vpmovqw, + Vpmovsdb, + Vpmovsdw, + Vpmovsqb, + Vpmovsqd, + Vpmovsqw, + Vpmovswb, + Vpmovsxbd, + Vpmovsxbq, + Vpmovsxbw, + Vpmovsxdq, + Vpmovsxwd, + Vpmovsxwq, + Vpmovusdb, + Vpmovusdw, + Vpmovusqb, + Vpmovusqd, + Vpmovusqw, + Vpmovuswb, + Vpmovw2m, + Vpmovwb, + Vpmovzxbd, + Vpmovzxbq, + Vpmovzxbw, + Vpmovzxdq, + Vpmovzxwd, + Vpmovzxwq, + Vpmuldq, + Vpmulhrsw, + Vpmulhuw, + Vpmulhw, + Vpmulld, + Vpmullq, + Vpmullw, + Vpmultishiftqb, + Vpmuludq, + Vpopcntb, + Vpopcntd, + Vpopcntq, + Vpopcntw, + Vpor, + Vpord, + Vporq, + Vpperm, + Vprold, + Vprolq, + Vprolvd, + Vprolvq, + Vprord, + Vprorq, + Vprorvd, + Vprorvq, + Vprotb, + Vprotd, + Vprotq, + Vprotw, + Vpsadbw, + Vpscatterdd, + Vpscatterdq, + Vpscatterqd, + Vpscatterqq, + Vpshab, + Vpshad, + Vpshaq, + Vpshaw, + Vpshlb, + Vpshld, + Vpshldd, + Vpshldq, + Vpshldvd, + Vpshldvq, + Vpshldvw, + Vpshldw, + Vpshlq, + Vpshlw, + Vpshrdd, + Vpshrdq, + Vpshrdvd, + Vpshrdvq, + Vpshrdvw, + Vpshrdw, + Vpshufb, + Vpshufbitqmb, + Vpshufd, + Vpshufhw, + Vpshuflw, + Vpsignb, + Vpsignd, + Vpsignw, + Vpslld, + Vpslldq, + Vpsllq, + Vpsllvd, + Vpsllvq, + Vpsllvw, + Vpsllw, + Vpsrad, + Vpsraq, + Vpsravd, + Vpsravq, + Vpsravw, + Vpsraw, + Vpsrld, + Vpsrldq, + Vpsrlq, + Vpsrlvd, + Vpsrlvq, + Vpsrlvw, + Vpsrlw, + Vpsubb, + Vpsubd, + Vpsubq, + Vpsubsb, + Vpsubsw, + Vpsubusb, + Vpsubusw, + Vpsubw, + Vpternlogd, + Vpternlogq, + Vptest, + Vptestmb, + Vptestmd, + Vptestmq, + Vptestmw, + Vptestnmb, + Vptestnmd, + Vptestnmq, + Vptestnmw, + Vpunpckhbw, + Vpunpckhdq, + Vpunpckhqdq, + Vpunpckhwd, + Vpunpcklbw, + Vpunpckldq, + Vpunpcklqdq, + Vpunpcklwd, + Vpxor, + Vpxord, + Vpxorq, + Vrangepd, + Vrangeps, + Vrangesd, + Vrangess, + Vrcp14pd, + Vrcp14ps, + Vrcp14sd, + Vrcp14ss, + Vrcp28pd, + Vrcp28ps, + Vrcp28sd, + Vrcp28ss, + Vrcpph, + Vrcpps, + Vrcpsh, + Vrcpss, + Vreducepd, + Vreduceph, + Vreduceps, + Vreducesd, + Vreducesh, + Vreducess, + Vrndscalepd, + Vrndscaleph, + Vrndscaleps, + Vrndscalesd, + Vrndscalesh, + Vrndscaless, + Vroundpd, + Vroundps, + Vroundsd, + Vroundss, + Vrsqrt14pd, + Vrsqrt14ps, + Vrsqrt14sd, + Vrsqrt14ss, + Vrsqrt28pd, + Vrsqrt28ps, + Vrsqrt28sd, + Vrsqrt28ss, + Vrsqrtph, + Vrsqrtps, + Vrsqrtsh, + Vrsqrtss, + Vscalefpd, + Vscalefph, + Vscalefps, + Vscalefsd, + Vscalefsh, + Vscalefss, + Vscatterdpd, + Vscatterdps, + Vscatterpf0dpd, + Vscatterpf0dps, + Vscatterpf0qpd, + Vscatterpf0qps, + Vscatterpf1dpd, + Vscatterpf1dps, + Vscatterpf1qpd, + Vscatterpf1qps, + Vscatterqpd, + Vscatterqps, + Vshuff32x4, + Vshuff64x2, + Vshufi32x4, + Vshufi64x2, + Vshufpd, + Vshufps, + Vsqrtpd, + Vsqrtph, + Vsqrtps, + Vsqrtsd, + Vsqrtsh, + Vsqrtss, + Vstmxcsr, + Vsubpd, + Vsubph, + Vsubps, + Vsubsd, + Vsubsh, + Vsubss, + Vtestpd, + Vtestps, + Vucomisd, + Vucomish, + Vucomiss, + Vunpckhpd, + Vunpckhps, + Vunpcklpd, + Vunpcklps, + Vxorpd, + Vxorps, + Vzeroall, + Vzeroupper, + Wait, + Wbinvd, + Wbnoinvd, + Wrfsbase, + Wrgsbase, + Wrmsr, + Wrpkru, + Wrshr, + Wrss, + Wruss, + Xabort, + Xadd, + Xbegin, + Xchg, + Xcryptcbc, + Xcryptcfb, + Xcryptctr, + Xcryptecb, + Xcryptofb, + Xend, + Xgetbv, + Xlatb, + Xor, + Xorpd, + Xorps, + Xresldtrk, + Xrstor, + Xrstors, + Xsave, + Xsavec, + Xsaveopt, + Xsaves, + Xsetbv, + Xsha1, + Xsha256, + Xstore, + Xsusldtrk, + Xtest, +} + +#[doc(hidden)] +impl TryFrom for Mnemonic { + type Error = decode_error::DecodeError; + + fn try_from(value: ffi::ND_INS_CLASS) -> Result { + match value { + ffi::_ND_INS_CLASS::ND_INS_INVALID => { + Err(decode_error::DecodeError::UnknownInstruction(value as u32)) + } + ffi::_ND_INS_CLASS::ND_INS_AAA => Ok(Mnemonic::Aaa), + ffi::_ND_INS_CLASS::ND_INS_AAD => Ok(Mnemonic::Aad), + ffi::_ND_INS_CLASS::ND_INS_AAM => Ok(Mnemonic::Aam), + ffi::_ND_INS_CLASS::ND_INS_AAS => Ok(Mnemonic::Aas), + ffi::_ND_INS_CLASS::ND_INS_ADC => Ok(Mnemonic::Adc), + ffi::_ND_INS_CLASS::ND_INS_ADCX => Ok(Mnemonic::Adcx), + ffi::_ND_INS_CLASS::ND_INS_ADD => Ok(Mnemonic::Add), + ffi::_ND_INS_CLASS::ND_INS_ADDPD => Ok(Mnemonic::Addpd), + ffi::_ND_INS_CLASS::ND_INS_ADDPS => Ok(Mnemonic::Addps), + ffi::_ND_INS_CLASS::ND_INS_ADDSD => Ok(Mnemonic::Addsd), + ffi::_ND_INS_CLASS::ND_INS_ADDSS => Ok(Mnemonic::Addss), + ffi::_ND_INS_CLASS::ND_INS_ADDSUBPD => Ok(Mnemonic::Addsubpd), + ffi::_ND_INS_CLASS::ND_INS_ADDSUBPS => Ok(Mnemonic::Addsubps), + ffi::_ND_INS_CLASS::ND_INS_ADOX => Ok(Mnemonic::Adox), + ffi::_ND_INS_CLASS::ND_INS_AESDEC => Ok(Mnemonic::Aesdec), + ffi::_ND_INS_CLASS::ND_INS_AESDEC128KL => Ok(Mnemonic::Aesdec128kl), + ffi::_ND_INS_CLASS::ND_INS_AESDEC256KL => Ok(Mnemonic::Aesdec256kl), + ffi::_ND_INS_CLASS::ND_INS_AESDECLAST => Ok(Mnemonic::Aesdeclast), + ffi::_ND_INS_CLASS::ND_INS_AESDECWIDE128KL => Ok(Mnemonic::Aesdecwide128kl), + ffi::_ND_INS_CLASS::ND_INS_AESDECWIDE256KL => Ok(Mnemonic::Aesdecwide256kl), + ffi::_ND_INS_CLASS::ND_INS_AESENC => Ok(Mnemonic::Aesenc), + ffi::_ND_INS_CLASS::ND_INS_AESENC128KL => Ok(Mnemonic::Aesenc128kl), + ffi::_ND_INS_CLASS::ND_INS_AESENC256KL => Ok(Mnemonic::Aesenc256kl), + ffi::_ND_INS_CLASS::ND_INS_AESENCLAST => Ok(Mnemonic::Aesenclast), + ffi::_ND_INS_CLASS::ND_INS_AESENCWIDE128KL => Ok(Mnemonic::Aesencwide128kl), + ffi::_ND_INS_CLASS::ND_INS_AESENCWIDE256KL => Ok(Mnemonic::Aesencwide256kl), + ffi::_ND_INS_CLASS::ND_INS_AESIMC => Ok(Mnemonic::Aesimc), + ffi::_ND_INS_CLASS::ND_INS_AESKEYGENASSIST => Ok(Mnemonic::Aeskeygenassist), + ffi::_ND_INS_CLASS::ND_INS_ALTINST => Ok(Mnemonic::Altinst), + ffi::_ND_INS_CLASS::ND_INS_AND => Ok(Mnemonic::And), + ffi::_ND_INS_CLASS::ND_INS_ANDN => Ok(Mnemonic::Andn), + ffi::_ND_INS_CLASS::ND_INS_ANDNPD => Ok(Mnemonic::Andnpd), + ffi::_ND_INS_CLASS::ND_INS_ANDNPS => Ok(Mnemonic::Andnps), + ffi::_ND_INS_CLASS::ND_INS_ANDPD => Ok(Mnemonic::Andpd), + ffi::_ND_INS_CLASS::ND_INS_ANDPS => Ok(Mnemonic::Andps), + ffi::_ND_INS_CLASS::ND_INS_ARPL => Ok(Mnemonic::Arpl), + ffi::_ND_INS_CLASS::ND_INS_BEXTR => Ok(Mnemonic::Bextr), + ffi::_ND_INS_CLASS::ND_INS_BLCFILL => Ok(Mnemonic::Blcfill), + ffi::_ND_INS_CLASS::ND_INS_BLCI => Ok(Mnemonic::Blci), + ffi::_ND_INS_CLASS::ND_INS_BLCIC => Ok(Mnemonic::Blcic), + ffi::_ND_INS_CLASS::ND_INS_BLCMSK => Ok(Mnemonic::Blcmsk), + ffi::_ND_INS_CLASS::ND_INS_BLCS => Ok(Mnemonic::Blcs), + ffi::_ND_INS_CLASS::ND_INS_BLENDPD => Ok(Mnemonic::Blendpd), + ffi::_ND_INS_CLASS::ND_INS_BLENDPS => Ok(Mnemonic::Blendps), + ffi::_ND_INS_CLASS::ND_INS_BLENDVPD => Ok(Mnemonic::Blendvpd), + ffi::_ND_INS_CLASS::ND_INS_BLENDVPS => Ok(Mnemonic::Blendvps), + ffi::_ND_INS_CLASS::ND_INS_BLSFILL => Ok(Mnemonic::Blsfill), + ffi::_ND_INS_CLASS::ND_INS_BLSI => Ok(Mnemonic::Blsi), + ffi::_ND_INS_CLASS::ND_INS_BLSIC => Ok(Mnemonic::Blsic), + ffi::_ND_INS_CLASS::ND_INS_BLSMSK => Ok(Mnemonic::Blsmsk), + ffi::_ND_INS_CLASS::ND_INS_BLSR => Ok(Mnemonic::Blsr), + ffi::_ND_INS_CLASS::ND_INS_BNDCL => Ok(Mnemonic::Bndcl), + ffi::_ND_INS_CLASS::ND_INS_BNDCN => Ok(Mnemonic::Bndcn), + ffi::_ND_INS_CLASS::ND_INS_BNDCU => Ok(Mnemonic::Bndcu), + ffi::_ND_INS_CLASS::ND_INS_BNDLDX => Ok(Mnemonic::Bndldx), + ffi::_ND_INS_CLASS::ND_INS_BNDMK => Ok(Mnemonic::Bndmk), + ffi::_ND_INS_CLASS::ND_INS_BNDMOV => Ok(Mnemonic::Bndmov), + ffi::_ND_INS_CLASS::ND_INS_BNDSTX => Ok(Mnemonic::Bndstx), + ffi::_ND_INS_CLASS::ND_INS_BOUND => Ok(Mnemonic::Bound), + ffi::_ND_INS_CLASS::ND_INS_BSF => Ok(Mnemonic::Bsf), + ffi::_ND_INS_CLASS::ND_INS_BSR => Ok(Mnemonic::Bsr), + ffi::_ND_INS_CLASS::ND_INS_BSWAP => Ok(Mnemonic::Bswap), + ffi::_ND_INS_CLASS::ND_INS_BT => Ok(Mnemonic::Bt), + ffi::_ND_INS_CLASS::ND_INS_BTC => Ok(Mnemonic::Btc), + ffi::_ND_INS_CLASS::ND_INS_BTR => Ok(Mnemonic::Btr), + ffi::_ND_INS_CLASS::ND_INS_BTS => Ok(Mnemonic::Bts), + ffi::_ND_INS_CLASS::ND_INS_BZHI => Ok(Mnemonic::Bzhi), + ffi::_ND_INS_CLASS::ND_INS_CALLFD => Ok(Mnemonic::Callfd), + ffi::_ND_INS_CLASS::ND_INS_CALLFI => Ok(Mnemonic::Callfi), + ffi::_ND_INS_CLASS::ND_INS_CALLNI => Ok(Mnemonic::Callni), + ffi::_ND_INS_CLASS::ND_INS_CALLNR => Ok(Mnemonic::Callnr), + ffi::_ND_INS_CLASS::ND_INS_CBW => Ok(Mnemonic::Cbw), + ffi::_ND_INS_CLASS::ND_INS_CDQ => Ok(Mnemonic::Cdq), + ffi::_ND_INS_CLASS::ND_INS_CDQE => Ok(Mnemonic::Cdqe), + ffi::_ND_INS_CLASS::ND_INS_CLAC => Ok(Mnemonic::Clac), + ffi::_ND_INS_CLASS::ND_INS_CLC => Ok(Mnemonic::Clc), + ffi::_ND_INS_CLASS::ND_INS_CLD => Ok(Mnemonic::Cld), + ffi::_ND_INS_CLASS::ND_INS_CLDEMOTE => Ok(Mnemonic::Cldemote), + ffi::_ND_INS_CLASS::ND_INS_CLEVICT0 => Ok(Mnemonic::Clevict0), + ffi::_ND_INS_CLASS::ND_INS_CLEVICT1 => Ok(Mnemonic::Clevict1), + ffi::_ND_INS_CLASS::ND_INS_CLFLUSH => Ok(Mnemonic::Clflush), + ffi::_ND_INS_CLASS::ND_INS_CLFLUSHOPT => Ok(Mnemonic::Clflushopt), + ffi::_ND_INS_CLASS::ND_INS_CLGI => Ok(Mnemonic::Clgi), + ffi::_ND_INS_CLASS::ND_INS_CLI => Ok(Mnemonic::Cli), + ffi::_ND_INS_CLASS::ND_INS_CLRSSBSY => Ok(Mnemonic::Clrssbsy), + ffi::_ND_INS_CLASS::ND_INS_CLTS => Ok(Mnemonic::Clts), + ffi::_ND_INS_CLASS::ND_INS_CLUI => Ok(Mnemonic::Clui), + ffi::_ND_INS_CLASS::ND_INS_CLWB => Ok(Mnemonic::Clwb), + ffi::_ND_INS_CLASS::ND_INS_CLZERO => Ok(Mnemonic::Clzero), + ffi::_ND_INS_CLASS::ND_INS_CMC => Ok(Mnemonic::Cmc), + ffi::_ND_INS_CLASS::ND_INS_CMOVcc => Ok(Mnemonic::Cmovcc), + ffi::_ND_INS_CLASS::ND_INS_CMP => Ok(Mnemonic::Cmp), + ffi::_ND_INS_CLASS::ND_INS_CMPPD => Ok(Mnemonic::Cmppd), + ffi::_ND_INS_CLASS::ND_INS_CMPPS => Ok(Mnemonic::Cmpps), + ffi::_ND_INS_CLASS::ND_INS_CMPS => Ok(Mnemonic::Cmps), + ffi::_ND_INS_CLASS::ND_INS_CMPSD => Ok(Mnemonic::Cmpsd), + ffi::_ND_INS_CLASS::ND_INS_CMPSS => Ok(Mnemonic::Cmpss), + ffi::_ND_INS_CLASS::ND_INS_CMPXCHG => Ok(Mnemonic::Cmpxchg), + ffi::_ND_INS_CLASS::ND_INS_CMPXCHG16B => Ok(Mnemonic::Cmpxchg16b), + ffi::_ND_INS_CLASS::ND_INS_CMPXCHG8B => Ok(Mnemonic::Cmpxchg8b), + ffi::_ND_INS_CLASS::ND_INS_COMISD => Ok(Mnemonic::Comisd), + ffi::_ND_INS_CLASS::ND_INS_COMISS => Ok(Mnemonic::Comiss), + ffi::_ND_INS_CLASS::ND_INS_CPUID => Ok(Mnemonic::Cpuid), + ffi::_ND_INS_CLASS::ND_INS_CPU_READ => Ok(Mnemonic::CpuRead), + ffi::_ND_INS_CLASS::ND_INS_CPU_WRITE => Ok(Mnemonic::CpuWrite), + ffi::_ND_INS_CLASS::ND_INS_CQO => Ok(Mnemonic::Cqo), + ffi::_ND_INS_CLASS::ND_INS_CRC32 => Ok(Mnemonic::Crc32), + ffi::_ND_INS_CLASS::ND_INS_CVTDQ2PD => Ok(Mnemonic::Cvtdq2pd), + ffi::_ND_INS_CLASS::ND_INS_CVTDQ2PS => Ok(Mnemonic::Cvtdq2ps), + ffi::_ND_INS_CLASS::ND_INS_CVTPD2DQ => Ok(Mnemonic::Cvtpd2dq), + ffi::_ND_INS_CLASS::ND_INS_CVTPD2PI => Ok(Mnemonic::Cvtpd2pi), + ffi::_ND_INS_CLASS::ND_INS_CVTPD2PS => Ok(Mnemonic::Cvtpd2ps), + ffi::_ND_INS_CLASS::ND_INS_CVTPI2PD => Ok(Mnemonic::Cvtpi2pd), + ffi::_ND_INS_CLASS::ND_INS_CVTPI2PS => Ok(Mnemonic::Cvtpi2ps), + ffi::_ND_INS_CLASS::ND_INS_CVTPS2DQ => Ok(Mnemonic::Cvtps2dq), + ffi::_ND_INS_CLASS::ND_INS_CVTPS2PD => Ok(Mnemonic::Cvtps2pd), + ffi::_ND_INS_CLASS::ND_INS_CVTPS2PI => Ok(Mnemonic::Cvtps2pi), + ffi::_ND_INS_CLASS::ND_INS_CVTSD2SI => Ok(Mnemonic::Cvtsd2si), + ffi::_ND_INS_CLASS::ND_INS_CVTSD2SS => Ok(Mnemonic::Cvtsd2ss), + ffi::_ND_INS_CLASS::ND_INS_CVTSI2SD => Ok(Mnemonic::Cvtsi2sd), + ffi::_ND_INS_CLASS::ND_INS_CVTSI2SS => Ok(Mnemonic::Cvtsi2ss), + ffi::_ND_INS_CLASS::ND_INS_CVTSS2SD => Ok(Mnemonic::Cvtss2sd), + ffi::_ND_INS_CLASS::ND_INS_CVTSS2SI => Ok(Mnemonic::Cvtss2si), + ffi::_ND_INS_CLASS::ND_INS_CVTTPD2DQ => Ok(Mnemonic::Cvttpd2dq), + ffi::_ND_INS_CLASS::ND_INS_CVTTPD2PI => Ok(Mnemonic::Cvttpd2pi), + ffi::_ND_INS_CLASS::ND_INS_CVTTPS2DQ => Ok(Mnemonic::Cvttps2dq), + ffi::_ND_INS_CLASS::ND_INS_CVTTPS2PI => Ok(Mnemonic::Cvttps2pi), + ffi::_ND_INS_CLASS::ND_INS_CVTTSD2SI => Ok(Mnemonic::Cvttsd2si), + ffi::_ND_INS_CLASS::ND_INS_CVTTSS2SI => Ok(Mnemonic::Cvttss2si), + ffi::_ND_INS_CLASS::ND_INS_CWD => Ok(Mnemonic::Cwd), + ffi::_ND_INS_CLASS::ND_INS_CWDE => Ok(Mnemonic::Cwde), + ffi::_ND_INS_CLASS::ND_INS_DAA => Ok(Mnemonic::Daa), + ffi::_ND_INS_CLASS::ND_INS_DAS => Ok(Mnemonic::Das), + ffi::_ND_INS_CLASS::ND_INS_DEC => Ok(Mnemonic::Dec), + ffi::_ND_INS_CLASS::ND_INS_DELAY => Ok(Mnemonic::Delay), + ffi::_ND_INS_CLASS::ND_INS_DIV => Ok(Mnemonic::Div), + ffi::_ND_INS_CLASS::ND_INS_DIVPD => Ok(Mnemonic::Divpd), + ffi::_ND_INS_CLASS::ND_INS_DIVPS => Ok(Mnemonic::Divps), + ffi::_ND_INS_CLASS::ND_INS_DIVSD => Ok(Mnemonic::Divsd), + ffi::_ND_INS_CLASS::ND_INS_DIVSS => Ok(Mnemonic::Divss), + ffi::_ND_INS_CLASS::ND_INS_DMINT => Ok(Mnemonic::Dmint), + ffi::_ND_INS_CLASS::ND_INS_DPPD => Ok(Mnemonic::Dppd), + ffi::_ND_INS_CLASS::ND_INS_DPPS => Ok(Mnemonic::Dpps), + ffi::_ND_INS_CLASS::ND_INS_EMMS => Ok(Mnemonic::Emms), + ffi::_ND_INS_CLASS::ND_INS_ENCLS => Ok(Mnemonic::Encls), + ffi::_ND_INS_CLASS::ND_INS_ENCLU => Ok(Mnemonic::Enclu), + ffi::_ND_INS_CLASS::ND_INS_ENCLV => Ok(Mnemonic::Enclv), + ffi::_ND_INS_CLASS::ND_INS_ENCODEKEY128 => Ok(Mnemonic::Encodekey128), + ffi::_ND_INS_CLASS::ND_INS_ENCODEKEY256 => Ok(Mnemonic::Encodekey256), + ffi::_ND_INS_CLASS::ND_INS_ENDBR => Ok(Mnemonic::Endbr), + ffi::_ND_INS_CLASS::ND_INS_ENQCMD => Ok(Mnemonic::Enqcmd), + ffi::_ND_INS_CLASS::ND_INS_ENQCMDS => Ok(Mnemonic::Enqcmds), + ffi::_ND_INS_CLASS::ND_INS_ENTER => Ok(Mnemonic::Enter), + ffi::_ND_INS_CLASS::ND_INS_ERETS => Ok(Mnemonic::Erets), + ffi::_ND_INS_CLASS::ND_INS_ERETU => Ok(Mnemonic::Eretu), + ffi::_ND_INS_CLASS::ND_INS_EXTRACTPS => Ok(Mnemonic::Extractps), + ffi::_ND_INS_CLASS::ND_INS_EXTRQ => Ok(Mnemonic::Extrq), + ffi::_ND_INS_CLASS::ND_INS_F2XM1 => Ok(Mnemonic::F2xm1), + ffi::_ND_INS_CLASS::ND_INS_FABS => Ok(Mnemonic::Fabs), + ffi::_ND_INS_CLASS::ND_INS_FADD => Ok(Mnemonic::Fadd), + ffi::_ND_INS_CLASS::ND_INS_FADDP => Ok(Mnemonic::Faddp), + ffi::_ND_INS_CLASS::ND_INS_FBLD => Ok(Mnemonic::Fbld), + ffi::_ND_INS_CLASS::ND_INS_FBSTP => Ok(Mnemonic::Fbstp), + ffi::_ND_INS_CLASS::ND_INS_FCHS => Ok(Mnemonic::Fchs), + ffi::_ND_INS_CLASS::ND_INS_FCMOVB => Ok(Mnemonic::Fcmovb), + ffi::_ND_INS_CLASS::ND_INS_FCMOVBE => Ok(Mnemonic::Fcmovbe), + ffi::_ND_INS_CLASS::ND_INS_FCMOVE => Ok(Mnemonic::Fcmove), + ffi::_ND_INS_CLASS::ND_INS_FCMOVNB => Ok(Mnemonic::Fcmovnb), + ffi::_ND_INS_CLASS::ND_INS_FCMOVNBE => Ok(Mnemonic::Fcmovnbe), + ffi::_ND_INS_CLASS::ND_INS_FCMOVNE => Ok(Mnemonic::Fcmovne), + ffi::_ND_INS_CLASS::ND_INS_FCMOVNU => Ok(Mnemonic::Fcmovnu), + ffi::_ND_INS_CLASS::ND_INS_FCMOVU => Ok(Mnemonic::Fcmovu), + ffi::_ND_INS_CLASS::ND_INS_FCOM => Ok(Mnemonic::Fcom), + ffi::_ND_INS_CLASS::ND_INS_FCOMI => Ok(Mnemonic::Fcomi), + ffi::_ND_INS_CLASS::ND_INS_FCOMIP => Ok(Mnemonic::Fcomip), + ffi::_ND_INS_CLASS::ND_INS_FCOMP => Ok(Mnemonic::Fcomp), + ffi::_ND_INS_CLASS::ND_INS_FCOMPP => Ok(Mnemonic::Fcompp), + ffi::_ND_INS_CLASS::ND_INS_FCOS => Ok(Mnemonic::Fcos), + ffi::_ND_INS_CLASS::ND_INS_FDECSTP => Ok(Mnemonic::Fdecstp), + ffi::_ND_INS_CLASS::ND_INS_FDIV => Ok(Mnemonic::Fdiv), + ffi::_ND_INS_CLASS::ND_INS_FDIVP => Ok(Mnemonic::Fdivp), + ffi::_ND_INS_CLASS::ND_INS_FDIVR => Ok(Mnemonic::Fdivr), + ffi::_ND_INS_CLASS::ND_INS_FDIVRP => Ok(Mnemonic::Fdivrp), + ffi::_ND_INS_CLASS::ND_INS_FEMMS => Ok(Mnemonic::Femms), + ffi::_ND_INS_CLASS::ND_INS_FFREE => Ok(Mnemonic::Ffree), + ffi::_ND_INS_CLASS::ND_INS_FFREEP => Ok(Mnemonic::Ffreep), + ffi::_ND_INS_CLASS::ND_INS_FIADD => Ok(Mnemonic::Fiadd), + ffi::_ND_INS_CLASS::ND_INS_FICOM => Ok(Mnemonic::Ficom), + ffi::_ND_INS_CLASS::ND_INS_FICOMP => Ok(Mnemonic::Ficomp), + ffi::_ND_INS_CLASS::ND_INS_FIDIV => Ok(Mnemonic::Fidiv), + ffi::_ND_INS_CLASS::ND_INS_FIDIVR => Ok(Mnemonic::Fidivr), + ffi::_ND_INS_CLASS::ND_INS_FILD => Ok(Mnemonic::Fild), + ffi::_ND_INS_CLASS::ND_INS_FIMUL => Ok(Mnemonic::Fimul), + ffi::_ND_INS_CLASS::ND_INS_FINCSTP => Ok(Mnemonic::Fincstp), + ffi::_ND_INS_CLASS::ND_INS_FIST => Ok(Mnemonic::Fist), + ffi::_ND_INS_CLASS::ND_INS_FISTP => Ok(Mnemonic::Fistp), + ffi::_ND_INS_CLASS::ND_INS_FISTTP => Ok(Mnemonic::Fisttp), + ffi::_ND_INS_CLASS::ND_INS_FISUB => Ok(Mnemonic::Fisub), + ffi::_ND_INS_CLASS::ND_INS_FISUBR => Ok(Mnemonic::Fisubr), + ffi::_ND_INS_CLASS::ND_INS_FLD => Ok(Mnemonic::Fld), + ffi::_ND_INS_CLASS::ND_INS_FLD1 => Ok(Mnemonic::Fld1), + ffi::_ND_INS_CLASS::ND_INS_FLDCW => Ok(Mnemonic::Fldcw), + ffi::_ND_INS_CLASS::ND_INS_FLDENV => Ok(Mnemonic::Fldenv), + ffi::_ND_INS_CLASS::ND_INS_FLDL2E => Ok(Mnemonic::Fldl2e), + ffi::_ND_INS_CLASS::ND_INS_FLDL2T => Ok(Mnemonic::Fldl2t), + ffi::_ND_INS_CLASS::ND_INS_FLDLG2 => Ok(Mnemonic::Fldlg2), + ffi::_ND_INS_CLASS::ND_INS_FLDLN2 => Ok(Mnemonic::Fldln2), + ffi::_ND_INS_CLASS::ND_INS_FLDPI => Ok(Mnemonic::Fldpi), + ffi::_ND_INS_CLASS::ND_INS_FLDZ => Ok(Mnemonic::Fldz), + ffi::_ND_INS_CLASS::ND_INS_FMUL => Ok(Mnemonic::Fmul), + ffi::_ND_INS_CLASS::ND_INS_FMULP => Ok(Mnemonic::Fmulp), + ffi::_ND_INS_CLASS::ND_INS_FNCLEX => Ok(Mnemonic::Fnclex), + ffi::_ND_INS_CLASS::ND_INS_FNDISI => Ok(Mnemonic::Fndisi), + ffi::_ND_INS_CLASS::ND_INS_FNINIT => Ok(Mnemonic::Fninit), + ffi::_ND_INS_CLASS::ND_INS_FNOP => Ok(Mnemonic::Fnop), + ffi::_ND_INS_CLASS::ND_INS_FNSAVE => Ok(Mnemonic::Fnsave), + ffi::_ND_INS_CLASS::ND_INS_FNSTCW => Ok(Mnemonic::Fnstcw), + ffi::_ND_INS_CLASS::ND_INS_FNSTENV => Ok(Mnemonic::Fnstenv), + ffi::_ND_INS_CLASS::ND_INS_FNSTSW => Ok(Mnemonic::Fnstsw), + ffi::_ND_INS_CLASS::ND_INS_FPATAN => Ok(Mnemonic::Fpatan), + ffi::_ND_INS_CLASS::ND_INS_FPREM => Ok(Mnemonic::Fprem), + ffi::_ND_INS_CLASS::ND_INS_FPREM1 => Ok(Mnemonic::Fprem1), + ffi::_ND_INS_CLASS::ND_INS_FPTAN => Ok(Mnemonic::Fptan), + ffi::_ND_INS_CLASS::ND_INS_FRINEAR => Ok(Mnemonic::Frinear), + ffi::_ND_INS_CLASS::ND_INS_FRNDINT => Ok(Mnemonic::Frndint), + ffi::_ND_INS_CLASS::ND_INS_FRSTOR => Ok(Mnemonic::Frstor), + ffi::_ND_INS_CLASS::ND_INS_FSCALE => Ok(Mnemonic::Fscale), + ffi::_ND_INS_CLASS::ND_INS_FSIN => Ok(Mnemonic::Fsin), + ffi::_ND_INS_CLASS::ND_INS_FSINCOS => Ok(Mnemonic::Fsincos), + ffi::_ND_INS_CLASS::ND_INS_FSQRT => Ok(Mnemonic::Fsqrt), + ffi::_ND_INS_CLASS::ND_INS_FST => Ok(Mnemonic::Fst), + ffi::_ND_INS_CLASS::ND_INS_FSTDW => Ok(Mnemonic::Fstdw), + ffi::_ND_INS_CLASS::ND_INS_FSTP => Ok(Mnemonic::Fstp), + ffi::_ND_INS_CLASS::ND_INS_FSTPNCE => Ok(Mnemonic::Fstpnce), + ffi::_ND_INS_CLASS::ND_INS_FSTSG => Ok(Mnemonic::Fstsg), + ffi::_ND_INS_CLASS::ND_INS_FSUB => Ok(Mnemonic::Fsub), + ffi::_ND_INS_CLASS::ND_INS_FSUBP => Ok(Mnemonic::Fsubp), + ffi::_ND_INS_CLASS::ND_INS_FSUBR => Ok(Mnemonic::Fsubr), + ffi::_ND_INS_CLASS::ND_INS_FSUBRP => Ok(Mnemonic::Fsubrp), + ffi::_ND_INS_CLASS::ND_INS_FTST => Ok(Mnemonic::Ftst), + ffi::_ND_INS_CLASS::ND_INS_FUCOM => Ok(Mnemonic::Fucom), + ffi::_ND_INS_CLASS::ND_INS_FUCOMI => Ok(Mnemonic::Fucomi), + ffi::_ND_INS_CLASS::ND_INS_FUCOMIP => Ok(Mnemonic::Fucomip), + ffi::_ND_INS_CLASS::ND_INS_FUCOMP => Ok(Mnemonic::Fucomp), + ffi::_ND_INS_CLASS::ND_INS_FUCOMPP => Ok(Mnemonic::Fucompp), + ffi::_ND_INS_CLASS::ND_INS_FXAM => Ok(Mnemonic::Fxam), + ffi::_ND_INS_CLASS::ND_INS_FXCH => Ok(Mnemonic::Fxch), + ffi::_ND_INS_CLASS::ND_INS_FXRSTOR => Ok(Mnemonic::Fxrstor), + ffi::_ND_INS_CLASS::ND_INS_FXRSTOR64 => Ok(Mnemonic::Fxrstor64), + ffi::_ND_INS_CLASS::ND_INS_FXSAVE => Ok(Mnemonic::Fxsave), + ffi::_ND_INS_CLASS::ND_INS_FXSAVE64 => Ok(Mnemonic::Fxsave64), + ffi::_ND_INS_CLASS::ND_INS_FXTRACT => Ok(Mnemonic::Fxtract), + ffi::_ND_INS_CLASS::ND_INS_FYL2X => Ok(Mnemonic::Fyl2x), + ffi::_ND_INS_CLASS::ND_INS_FYL2XP1 => Ok(Mnemonic::Fyl2xp1), + ffi::_ND_INS_CLASS::ND_INS_GETSEC => Ok(Mnemonic::Getsec), + ffi::_ND_INS_CLASS::ND_INS_GF2P8AFFINEINVQB => Ok(Mnemonic::Gf2p8affineinvqb), + ffi::_ND_INS_CLASS::ND_INS_GF2P8AFFINEQB => Ok(Mnemonic::Gf2p8affineqb), + ffi::_ND_INS_CLASS::ND_INS_GF2P8MULB => Ok(Mnemonic::Gf2p8mulb), + ffi::_ND_INS_CLASS::ND_INS_HADDPD => Ok(Mnemonic::Haddpd), + ffi::_ND_INS_CLASS::ND_INS_HADDPS => Ok(Mnemonic::Haddps), + ffi::_ND_INS_CLASS::ND_INS_HLT => Ok(Mnemonic::Hlt), + ffi::_ND_INS_CLASS::ND_INS_HRESET => Ok(Mnemonic::Hreset), + ffi::_ND_INS_CLASS::ND_INS_HSUBPD => Ok(Mnemonic::Hsubpd), + ffi::_ND_INS_CLASS::ND_INS_HSUBPS => Ok(Mnemonic::Hsubps), + ffi::_ND_INS_CLASS::ND_INS_IDIV => Ok(Mnemonic::Idiv), + ffi::_ND_INS_CLASS::ND_INS_IMUL => Ok(Mnemonic::Imul), + ffi::_ND_INS_CLASS::ND_INS_IN => Ok(Mnemonic::In), + ffi::_ND_INS_CLASS::ND_INS_INC => Ok(Mnemonic::Inc), + ffi::_ND_INS_CLASS::ND_INS_INCSSP => Ok(Mnemonic::Incssp), + ffi::_ND_INS_CLASS::ND_INS_INS => Ok(Mnemonic::Ins), + ffi::_ND_INS_CLASS::ND_INS_INSERTPS => Ok(Mnemonic::Insertps), + ffi::_ND_INS_CLASS::ND_INS_INSERTQ => Ok(Mnemonic::Insertq), + ffi::_ND_INS_CLASS::ND_INS_INT => Ok(Mnemonic::Int), + ffi::_ND_INS_CLASS::ND_INS_INT1 => Ok(Mnemonic::Int1), + ffi::_ND_INS_CLASS::ND_INS_INT3 => Ok(Mnemonic::Int3), + ffi::_ND_INS_CLASS::ND_INS_INTO => Ok(Mnemonic::Into), + ffi::_ND_INS_CLASS::ND_INS_INVD => Ok(Mnemonic::Invd), + ffi::_ND_INS_CLASS::ND_INS_INVEPT => Ok(Mnemonic::Invept), + ffi::_ND_INS_CLASS::ND_INS_INVLPG => Ok(Mnemonic::Invlpg), + ffi::_ND_INS_CLASS::ND_INS_INVLPGA => Ok(Mnemonic::Invlpga), + ffi::_ND_INS_CLASS::ND_INS_INVLPGB => Ok(Mnemonic::Invlpgb), + ffi::_ND_INS_CLASS::ND_INS_INVPCID => Ok(Mnemonic::Invpcid), + ffi::_ND_INS_CLASS::ND_INS_INVVPID => Ok(Mnemonic::Invvpid), + ffi::_ND_INS_CLASS::ND_INS_IRET => Ok(Mnemonic::Iret), + ffi::_ND_INS_CLASS::ND_INS_JMPE => Ok(Mnemonic::Jmpe), + ffi::_ND_INS_CLASS::ND_INS_JMPFD => Ok(Mnemonic::Jmpfd), + ffi::_ND_INS_CLASS::ND_INS_JMPFI => Ok(Mnemonic::Jmpfi), + ffi::_ND_INS_CLASS::ND_INS_JMPNI => Ok(Mnemonic::Jmpni), + ffi::_ND_INS_CLASS::ND_INS_JMPNR => Ok(Mnemonic::Jmpnr), + ffi::_ND_INS_CLASS::ND_INS_Jcc => Ok(Mnemonic::Jcc), + ffi::_ND_INS_CLASS::ND_INS_JrCXZ => Ok(Mnemonic::Jrcxz), + ffi::_ND_INS_CLASS::ND_INS_KADD => Ok(Mnemonic::Kadd), + ffi::_ND_INS_CLASS::ND_INS_KAND => Ok(Mnemonic::Kand), + ffi::_ND_INS_CLASS::ND_INS_KANDN => Ok(Mnemonic::Kandn), + ffi::_ND_INS_CLASS::ND_INS_KMERGE2L1H => Ok(Mnemonic::Kmerge2l1h), + ffi::_ND_INS_CLASS::ND_INS_KMERGE2L1L => Ok(Mnemonic::Kmerge2l1l), + ffi::_ND_INS_CLASS::ND_INS_KMOV => Ok(Mnemonic::Kmov), + ffi::_ND_INS_CLASS::ND_INS_KNOT => Ok(Mnemonic::Knot), + ffi::_ND_INS_CLASS::ND_INS_KOR => Ok(Mnemonic::Kor), + ffi::_ND_INS_CLASS::ND_INS_KORTEST => Ok(Mnemonic::Kortest), + ffi::_ND_INS_CLASS::ND_INS_KSHIFTL => Ok(Mnemonic::Kshiftl), + ffi::_ND_INS_CLASS::ND_INS_KSHIFTR => Ok(Mnemonic::Kshiftr), + ffi::_ND_INS_CLASS::ND_INS_KTEST => Ok(Mnemonic::Ktest), + ffi::_ND_INS_CLASS::ND_INS_KUNPCKBW => Ok(Mnemonic::Kunpckbw), + ffi::_ND_INS_CLASS::ND_INS_KUNPCKDQ => Ok(Mnemonic::Kunpckdq), + ffi::_ND_INS_CLASS::ND_INS_KUNPCKWD => Ok(Mnemonic::Kunpckwd), + ffi::_ND_INS_CLASS::ND_INS_KXNOR => Ok(Mnemonic::Kxnor), + ffi::_ND_INS_CLASS::ND_INS_KXOR => Ok(Mnemonic::Kxor), + ffi::_ND_INS_CLASS::ND_INS_LAHF => Ok(Mnemonic::Lahf), + ffi::_ND_INS_CLASS::ND_INS_LAR => Ok(Mnemonic::Lar), + ffi::_ND_INS_CLASS::ND_INS_LDDQU => Ok(Mnemonic::Lddqu), + ffi::_ND_INS_CLASS::ND_INS_LDMXCSR => Ok(Mnemonic::Ldmxcsr), + ffi::_ND_INS_CLASS::ND_INS_LDS => Ok(Mnemonic::Lds), + ffi::_ND_INS_CLASS::ND_INS_LDTILECFG => Ok(Mnemonic::Ldtilecfg), + ffi::_ND_INS_CLASS::ND_INS_LEA => Ok(Mnemonic::Lea), + ffi::_ND_INS_CLASS::ND_INS_LEAVE => Ok(Mnemonic::Leave), + ffi::_ND_INS_CLASS::ND_INS_LES => Ok(Mnemonic::Les), + ffi::_ND_INS_CLASS::ND_INS_LFENCE => Ok(Mnemonic::Lfence), + ffi::_ND_INS_CLASS::ND_INS_LFS => Ok(Mnemonic::Lfs), + ffi::_ND_INS_CLASS::ND_INS_LGDT => Ok(Mnemonic::Lgdt), + ffi::_ND_INS_CLASS::ND_INS_LGS => Ok(Mnemonic::Lgs), + ffi::_ND_INS_CLASS::ND_INS_LIDT => Ok(Mnemonic::Lidt), + ffi::_ND_INS_CLASS::ND_INS_LKGS => Ok(Mnemonic::Lkgs), + ffi::_ND_INS_CLASS::ND_INS_LLDT => Ok(Mnemonic::Lldt), + ffi::_ND_INS_CLASS::ND_INS_LLWPCB => Ok(Mnemonic::Llwpcb), + ffi::_ND_INS_CLASS::ND_INS_LMSW => Ok(Mnemonic::Lmsw), + ffi::_ND_INS_CLASS::ND_INS_LOADIWKEY => Ok(Mnemonic::Loadiwkey), + ffi::_ND_INS_CLASS::ND_INS_LODS => Ok(Mnemonic::Lods), + ffi::_ND_INS_CLASS::ND_INS_LOOP => Ok(Mnemonic::Loop), + ffi::_ND_INS_CLASS::ND_INS_LOOPNZ => Ok(Mnemonic::Loopnz), + ffi::_ND_INS_CLASS::ND_INS_LOOPZ => Ok(Mnemonic::Loopz), + ffi::_ND_INS_CLASS::ND_INS_LSL => Ok(Mnemonic::Lsl), + ffi::_ND_INS_CLASS::ND_INS_LSS => Ok(Mnemonic::Lss), + ffi::_ND_INS_CLASS::ND_INS_LTR => Ok(Mnemonic::Ltr), + ffi::_ND_INS_CLASS::ND_INS_LWPINS => Ok(Mnemonic::Lwpins), + ffi::_ND_INS_CLASS::ND_INS_LWPVAL => Ok(Mnemonic::Lwpval), + ffi::_ND_INS_CLASS::ND_INS_LZCNT => Ok(Mnemonic::Lzcnt), + ffi::_ND_INS_CLASS::ND_INS_MASKMOVDQU => Ok(Mnemonic::Maskmovdqu), + ffi::_ND_INS_CLASS::ND_INS_MASKMOVQ => Ok(Mnemonic::Maskmovq), + ffi::_ND_INS_CLASS::ND_INS_MAXPD => Ok(Mnemonic::Maxpd), + ffi::_ND_INS_CLASS::ND_INS_MAXPS => Ok(Mnemonic::Maxps), + ffi::_ND_INS_CLASS::ND_INS_MAXSD => Ok(Mnemonic::Maxsd), + ffi::_ND_INS_CLASS::ND_INS_MAXSS => Ok(Mnemonic::Maxss), + ffi::_ND_INS_CLASS::ND_INS_MCOMMIT => Ok(Mnemonic::Mcommit), + ffi::_ND_INS_CLASS::ND_INS_MFENCE => Ok(Mnemonic::Mfence), + ffi::_ND_INS_CLASS::ND_INS_MINPD => Ok(Mnemonic::Minpd), + ffi::_ND_INS_CLASS::ND_INS_MINPS => Ok(Mnemonic::Minps), + ffi::_ND_INS_CLASS::ND_INS_MINSD => Ok(Mnemonic::Minsd), + ffi::_ND_INS_CLASS::ND_INS_MINSS => Ok(Mnemonic::Minss), + ffi::_ND_INS_CLASS::ND_INS_MONITOR => Ok(Mnemonic::Monitor), + ffi::_ND_INS_CLASS::ND_INS_MONITORX => Ok(Mnemonic::Monitorx), + ffi::_ND_INS_CLASS::ND_INS_MONTMUL => Ok(Mnemonic::Montmul), + ffi::_ND_INS_CLASS::ND_INS_MOV => Ok(Mnemonic::Mov), + ffi::_ND_INS_CLASS::ND_INS_MOVAPD => Ok(Mnemonic::Movapd), + ffi::_ND_INS_CLASS::ND_INS_MOVAPS => Ok(Mnemonic::Movaps), + ffi::_ND_INS_CLASS::ND_INS_MOVBE => Ok(Mnemonic::Movbe), + ffi::_ND_INS_CLASS::ND_INS_MOVD => Ok(Mnemonic::Movd), + ffi::_ND_INS_CLASS::ND_INS_MOVDDUP => Ok(Mnemonic::Movddup), + ffi::_ND_INS_CLASS::ND_INS_MOVDIR64B => Ok(Mnemonic::Movdir64b), + ffi::_ND_INS_CLASS::ND_INS_MOVDIRI => Ok(Mnemonic::Movdiri), + ffi::_ND_INS_CLASS::ND_INS_MOVDQ2Q => Ok(Mnemonic::Movdq2q), + ffi::_ND_INS_CLASS::ND_INS_MOVDQA => Ok(Mnemonic::Movdqa), + ffi::_ND_INS_CLASS::ND_INS_MOVDQU => Ok(Mnemonic::Movdqu), + ffi::_ND_INS_CLASS::ND_INS_MOVHLPS => Ok(Mnemonic::Movhlps), + ffi::_ND_INS_CLASS::ND_INS_MOVHPD => Ok(Mnemonic::Movhpd), + ffi::_ND_INS_CLASS::ND_INS_MOVHPS => Ok(Mnemonic::Movhps), + ffi::_ND_INS_CLASS::ND_INS_MOVLHPS => Ok(Mnemonic::Movlhps), + ffi::_ND_INS_CLASS::ND_INS_MOVLPD => Ok(Mnemonic::Movlpd), + ffi::_ND_INS_CLASS::ND_INS_MOVLPS => Ok(Mnemonic::Movlps), + ffi::_ND_INS_CLASS::ND_INS_MOVMSKPD => Ok(Mnemonic::Movmskpd), + ffi::_ND_INS_CLASS::ND_INS_MOVMSKPS => Ok(Mnemonic::Movmskps), + ffi::_ND_INS_CLASS::ND_INS_MOVNTDQ => Ok(Mnemonic::Movntdq), + ffi::_ND_INS_CLASS::ND_INS_MOVNTDQA => Ok(Mnemonic::Movntdqa), + ffi::_ND_INS_CLASS::ND_INS_MOVNTI => Ok(Mnemonic::Movnti), + ffi::_ND_INS_CLASS::ND_INS_MOVNTPD => Ok(Mnemonic::Movntpd), + ffi::_ND_INS_CLASS::ND_INS_MOVNTPS => Ok(Mnemonic::Movntps), + ffi::_ND_INS_CLASS::ND_INS_MOVNTQ => Ok(Mnemonic::Movntq), + ffi::_ND_INS_CLASS::ND_INS_MOVNTSD => Ok(Mnemonic::Movntsd), + ffi::_ND_INS_CLASS::ND_INS_MOVNTSS => Ok(Mnemonic::Movntss), + ffi::_ND_INS_CLASS::ND_INS_MOVQ => Ok(Mnemonic::Movq), + ffi::_ND_INS_CLASS::ND_INS_MOVQ2DQ => Ok(Mnemonic::Movq2dq), + ffi::_ND_INS_CLASS::ND_INS_MOVS => Ok(Mnemonic::Movs), + ffi::_ND_INS_CLASS::ND_INS_MOVSD => Ok(Mnemonic::Movsd), + ffi::_ND_INS_CLASS::ND_INS_MOVSHDUP => Ok(Mnemonic::Movshdup), + ffi::_ND_INS_CLASS::ND_INS_MOVSLDUP => Ok(Mnemonic::Movsldup), + ffi::_ND_INS_CLASS::ND_INS_MOVSS => Ok(Mnemonic::Movss), + ffi::_ND_INS_CLASS::ND_INS_MOVSX => Ok(Mnemonic::Movsx), + ffi::_ND_INS_CLASS::ND_INS_MOVSXD => Ok(Mnemonic::Movsxd), + ffi::_ND_INS_CLASS::ND_INS_MOVUPD => Ok(Mnemonic::Movupd), + ffi::_ND_INS_CLASS::ND_INS_MOVUPS => Ok(Mnemonic::Movups), + ffi::_ND_INS_CLASS::ND_INS_MOVZX => Ok(Mnemonic::Movzx), + ffi::_ND_INS_CLASS::ND_INS_MOV_CR => Ok(Mnemonic::MovCr), + ffi::_ND_INS_CLASS::ND_INS_MOV_DR => Ok(Mnemonic::MovDr), + ffi::_ND_INS_CLASS::ND_INS_MOV_TR => Ok(Mnemonic::MovTr), + ffi::_ND_INS_CLASS::ND_INS_MPSADBW => Ok(Mnemonic::Mpsadbw), + ffi::_ND_INS_CLASS::ND_INS_MUL => Ok(Mnemonic::Mul), + ffi::_ND_INS_CLASS::ND_INS_MULPD => Ok(Mnemonic::Mulpd), + ffi::_ND_INS_CLASS::ND_INS_MULPS => Ok(Mnemonic::Mulps), + ffi::_ND_INS_CLASS::ND_INS_MULSD => Ok(Mnemonic::Mulsd), + ffi::_ND_INS_CLASS::ND_INS_MULSS => Ok(Mnemonic::Mulss), + ffi::_ND_INS_CLASS::ND_INS_MULX => Ok(Mnemonic::Mulx), + ffi::_ND_INS_CLASS::ND_INS_MWAIT => Ok(Mnemonic::Mwait), + ffi::_ND_INS_CLASS::ND_INS_MWAITX => Ok(Mnemonic::Mwaitx), + ffi::_ND_INS_CLASS::ND_INS_NEG => Ok(Mnemonic::Neg), + ffi::_ND_INS_CLASS::ND_INS_NOP => Ok(Mnemonic::Nop), + ffi::_ND_INS_CLASS::ND_INS_NOT => Ok(Mnemonic::Not), + ffi::_ND_INS_CLASS::ND_INS_OR => Ok(Mnemonic::Or), + ffi::_ND_INS_CLASS::ND_INS_ORPD => Ok(Mnemonic::Orpd), + ffi::_ND_INS_CLASS::ND_INS_ORPS => Ok(Mnemonic::Orps), + ffi::_ND_INS_CLASS::ND_INS_OUT => Ok(Mnemonic::Out), + ffi::_ND_INS_CLASS::ND_INS_OUTS => Ok(Mnemonic::Outs), + ffi::_ND_INS_CLASS::ND_INS_PABSB => Ok(Mnemonic::Pabsb), + ffi::_ND_INS_CLASS::ND_INS_PABSD => Ok(Mnemonic::Pabsd), + ffi::_ND_INS_CLASS::ND_INS_PABSW => Ok(Mnemonic::Pabsw), + ffi::_ND_INS_CLASS::ND_INS_PACKSSDW => Ok(Mnemonic::Packssdw), + ffi::_ND_INS_CLASS::ND_INS_PACKSSWB => Ok(Mnemonic::Packsswb), + ffi::_ND_INS_CLASS::ND_INS_PACKUSDW => Ok(Mnemonic::Packusdw), + ffi::_ND_INS_CLASS::ND_INS_PACKUSWB => Ok(Mnemonic::Packuswb), + ffi::_ND_INS_CLASS::ND_INS_PADDB => Ok(Mnemonic::Paddb), + ffi::_ND_INS_CLASS::ND_INS_PADDD => Ok(Mnemonic::Paddd), + ffi::_ND_INS_CLASS::ND_INS_PADDQ => Ok(Mnemonic::Paddq), + ffi::_ND_INS_CLASS::ND_INS_PADDSB => Ok(Mnemonic::Paddsb), + ffi::_ND_INS_CLASS::ND_INS_PADDSW => Ok(Mnemonic::Paddsw), + ffi::_ND_INS_CLASS::ND_INS_PADDUSB => Ok(Mnemonic::Paddusb), + ffi::_ND_INS_CLASS::ND_INS_PADDUSW => Ok(Mnemonic::Paddusw), + ffi::_ND_INS_CLASS::ND_INS_PADDW => Ok(Mnemonic::Paddw), + ffi::_ND_INS_CLASS::ND_INS_PALIGNR => Ok(Mnemonic::Palignr), + ffi::_ND_INS_CLASS::ND_INS_PAND => Ok(Mnemonic::Pand), + ffi::_ND_INS_CLASS::ND_INS_PANDN => Ok(Mnemonic::Pandn), + ffi::_ND_INS_CLASS::ND_INS_PAUSE => Ok(Mnemonic::Pause), + ffi::_ND_INS_CLASS::ND_INS_PAVGB => Ok(Mnemonic::Pavgb), + ffi::_ND_INS_CLASS::ND_INS_PAVGUSB => Ok(Mnemonic::Pavgusb), + ffi::_ND_INS_CLASS::ND_INS_PAVGW => Ok(Mnemonic::Pavgw), + ffi::_ND_INS_CLASS::ND_INS_PBLENDVB => Ok(Mnemonic::Pblendvb), + ffi::_ND_INS_CLASS::ND_INS_PBLENDW => Ok(Mnemonic::Pblendw), + ffi::_ND_INS_CLASS::ND_INS_PCLMULQDQ => Ok(Mnemonic::Pclmulqdq), + ffi::_ND_INS_CLASS::ND_INS_PCMPEQB => Ok(Mnemonic::Pcmpeqb), + ffi::_ND_INS_CLASS::ND_INS_PCMPEQD => Ok(Mnemonic::Pcmpeqd), + ffi::_ND_INS_CLASS::ND_INS_PCMPEQQ => Ok(Mnemonic::Pcmpeqq), + ffi::_ND_INS_CLASS::ND_INS_PCMPEQW => Ok(Mnemonic::Pcmpeqw), + ffi::_ND_INS_CLASS::ND_INS_PCMPESTRI => Ok(Mnemonic::Pcmpestri), + ffi::_ND_INS_CLASS::ND_INS_PCMPESTRM => Ok(Mnemonic::Pcmpestrm), + ffi::_ND_INS_CLASS::ND_INS_PCMPGTB => Ok(Mnemonic::Pcmpgtb), + ffi::_ND_INS_CLASS::ND_INS_PCMPGTD => Ok(Mnemonic::Pcmpgtd), + ffi::_ND_INS_CLASS::ND_INS_PCMPGTQ => Ok(Mnemonic::Pcmpgtq), + ffi::_ND_INS_CLASS::ND_INS_PCMPGTW => Ok(Mnemonic::Pcmpgtw), + ffi::_ND_INS_CLASS::ND_INS_PCMPISTRI => Ok(Mnemonic::Pcmpistri), + ffi::_ND_INS_CLASS::ND_INS_PCMPISTRM => Ok(Mnemonic::Pcmpistrm), + ffi::_ND_INS_CLASS::ND_INS_PCONFIG => Ok(Mnemonic::Pconfig), + ffi::_ND_INS_CLASS::ND_INS_PDEP => Ok(Mnemonic::Pdep), + ffi::_ND_INS_CLASS::ND_INS_PEXT => Ok(Mnemonic::Pext), + ffi::_ND_INS_CLASS::ND_INS_PEXTRB => Ok(Mnemonic::Pextrb), + ffi::_ND_INS_CLASS::ND_INS_PEXTRD => Ok(Mnemonic::Pextrd), + ffi::_ND_INS_CLASS::ND_INS_PEXTRQ => Ok(Mnemonic::Pextrq), + ffi::_ND_INS_CLASS::ND_INS_PEXTRW => Ok(Mnemonic::Pextrw), + ffi::_ND_INS_CLASS::ND_INS_PF2ID => Ok(Mnemonic::Pf2id), + ffi::_ND_INS_CLASS::ND_INS_PF2IW => Ok(Mnemonic::Pf2iw), + ffi::_ND_INS_CLASS::ND_INS_PFACC => Ok(Mnemonic::Pfacc), + ffi::_ND_INS_CLASS::ND_INS_PFADD => Ok(Mnemonic::Pfadd), + ffi::_ND_INS_CLASS::ND_INS_PFCMPEQ => Ok(Mnemonic::Pfcmpeq), + ffi::_ND_INS_CLASS::ND_INS_PFCMPGE => Ok(Mnemonic::Pfcmpge), + ffi::_ND_INS_CLASS::ND_INS_PFCMPGT => Ok(Mnemonic::Pfcmpgt), + ffi::_ND_INS_CLASS::ND_INS_PFMAX => Ok(Mnemonic::Pfmax), + ffi::_ND_INS_CLASS::ND_INS_PFMIN => Ok(Mnemonic::Pfmin), + ffi::_ND_INS_CLASS::ND_INS_PFMUL => Ok(Mnemonic::Pfmul), + ffi::_ND_INS_CLASS::ND_INS_PFNACC => Ok(Mnemonic::Pfnacc), + ffi::_ND_INS_CLASS::ND_INS_PFPNACC => Ok(Mnemonic::Pfpnacc), + ffi::_ND_INS_CLASS::ND_INS_PFRCP => Ok(Mnemonic::Pfrcp), + ffi::_ND_INS_CLASS::ND_INS_PFRCPIT1 => Ok(Mnemonic::Pfrcpit1), + ffi::_ND_INS_CLASS::ND_INS_PFRCPIT2 => Ok(Mnemonic::Pfrcpit2), + ffi::_ND_INS_CLASS::ND_INS_PFRCPV => Ok(Mnemonic::Pfrcpv), + ffi::_ND_INS_CLASS::ND_INS_PFRSQIT1 => Ok(Mnemonic::Pfrsqit1), + ffi::_ND_INS_CLASS::ND_INS_PFRSQRT => Ok(Mnemonic::Pfrsqrt), + ffi::_ND_INS_CLASS::ND_INS_PFRSQRTV => Ok(Mnemonic::Pfrsqrtv), + ffi::_ND_INS_CLASS::ND_INS_PFSUB => Ok(Mnemonic::Pfsub), + ffi::_ND_INS_CLASS::ND_INS_PFSUBR => Ok(Mnemonic::Pfsubr), + ffi::_ND_INS_CLASS::ND_INS_PHADDD => Ok(Mnemonic::Phaddd), + ffi::_ND_INS_CLASS::ND_INS_PHADDSW => Ok(Mnemonic::Phaddsw), + ffi::_ND_INS_CLASS::ND_INS_PHADDW => Ok(Mnemonic::Phaddw), + ffi::_ND_INS_CLASS::ND_INS_PHMINPOSUW => Ok(Mnemonic::Phminposuw), + ffi::_ND_INS_CLASS::ND_INS_PHSUBD => Ok(Mnemonic::Phsubd), + ffi::_ND_INS_CLASS::ND_INS_PHSUBSW => Ok(Mnemonic::Phsubsw), + ffi::_ND_INS_CLASS::ND_INS_PHSUBW => Ok(Mnemonic::Phsubw), + ffi::_ND_INS_CLASS::ND_INS_PI2FD => Ok(Mnemonic::Pi2fd), + ffi::_ND_INS_CLASS::ND_INS_PI2FW => Ok(Mnemonic::Pi2fw), + ffi::_ND_INS_CLASS::ND_INS_PINSRB => Ok(Mnemonic::Pinsrb), + ffi::_ND_INS_CLASS::ND_INS_PINSRD => Ok(Mnemonic::Pinsrd), + ffi::_ND_INS_CLASS::ND_INS_PINSRQ => Ok(Mnemonic::Pinsrq), + ffi::_ND_INS_CLASS::ND_INS_PINSRW => Ok(Mnemonic::Pinsrw), + ffi::_ND_INS_CLASS::ND_INS_PMADDUBSW => Ok(Mnemonic::Pmaddubsw), + ffi::_ND_INS_CLASS::ND_INS_PMADDWD => Ok(Mnemonic::Pmaddwd), + ffi::_ND_INS_CLASS::ND_INS_PMAXSB => Ok(Mnemonic::Pmaxsb), + ffi::_ND_INS_CLASS::ND_INS_PMAXSD => Ok(Mnemonic::Pmaxsd), + ffi::_ND_INS_CLASS::ND_INS_PMAXSW => Ok(Mnemonic::Pmaxsw), + ffi::_ND_INS_CLASS::ND_INS_PMAXUB => Ok(Mnemonic::Pmaxub), + ffi::_ND_INS_CLASS::ND_INS_PMAXUD => Ok(Mnemonic::Pmaxud), + ffi::_ND_INS_CLASS::ND_INS_PMAXUW => Ok(Mnemonic::Pmaxuw), + ffi::_ND_INS_CLASS::ND_INS_PMINSB => Ok(Mnemonic::Pminsb), + ffi::_ND_INS_CLASS::ND_INS_PMINSD => Ok(Mnemonic::Pminsd), + ffi::_ND_INS_CLASS::ND_INS_PMINSW => Ok(Mnemonic::Pminsw), + ffi::_ND_INS_CLASS::ND_INS_PMINUB => Ok(Mnemonic::Pminub), + ffi::_ND_INS_CLASS::ND_INS_PMINUD => Ok(Mnemonic::Pminud), + ffi::_ND_INS_CLASS::ND_INS_PMINUW => Ok(Mnemonic::Pminuw), + ffi::_ND_INS_CLASS::ND_INS_PMOVMSKB => Ok(Mnemonic::Pmovmskb), + ffi::_ND_INS_CLASS::ND_INS_PMOVSXBD => Ok(Mnemonic::Pmovsxbd), + ffi::_ND_INS_CLASS::ND_INS_PMOVSXBQ => Ok(Mnemonic::Pmovsxbq), + ffi::_ND_INS_CLASS::ND_INS_PMOVSXBW => Ok(Mnemonic::Pmovsxbw), + ffi::_ND_INS_CLASS::ND_INS_PMOVSXDQ => Ok(Mnemonic::Pmovsxdq), + ffi::_ND_INS_CLASS::ND_INS_PMOVSXWD => Ok(Mnemonic::Pmovsxwd), + ffi::_ND_INS_CLASS::ND_INS_PMOVSXWQ => Ok(Mnemonic::Pmovsxwq), + ffi::_ND_INS_CLASS::ND_INS_PMOVZXBD => Ok(Mnemonic::Pmovzxbd), + ffi::_ND_INS_CLASS::ND_INS_PMOVZXBQ => Ok(Mnemonic::Pmovzxbq), + ffi::_ND_INS_CLASS::ND_INS_PMOVZXBW => Ok(Mnemonic::Pmovzxbw), + ffi::_ND_INS_CLASS::ND_INS_PMOVZXDQ => Ok(Mnemonic::Pmovzxdq), + ffi::_ND_INS_CLASS::ND_INS_PMOVZXWD => Ok(Mnemonic::Pmovzxwd), + ffi::_ND_INS_CLASS::ND_INS_PMOVZXWQ => Ok(Mnemonic::Pmovzxwq), + ffi::_ND_INS_CLASS::ND_INS_PMULDQ => Ok(Mnemonic::Pmuldq), + ffi::_ND_INS_CLASS::ND_INS_PMULHRSW => Ok(Mnemonic::Pmulhrsw), + ffi::_ND_INS_CLASS::ND_INS_PMULHRW => Ok(Mnemonic::Pmulhrw), + ffi::_ND_INS_CLASS::ND_INS_PMULHUW => Ok(Mnemonic::Pmulhuw), + ffi::_ND_INS_CLASS::ND_INS_PMULHW => Ok(Mnemonic::Pmulhw), + ffi::_ND_INS_CLASS::ND_INS_PMULLD => Ok(Mnemonic::Pmulld), + ffi::_ND_INS_CLASS::ND_INS_PMULLW => Ok(Mnemonic::Pmullw), + ffi::_ND_INS_CLASS::ND_INS_PMULUDQ => Ok(Mnemonic::Pmuludq), + ffi::_ND_INS_CLASS::ND_INS_POP => Ok(Mnemonic::Pop), + ffi::_ND_INS_CLASS::ND_INS_POPA => Ok(Mnemonic::Popa), + ffi::_ND_INS_CLASS::ND_INS_POPAD => Ok(Mnemonic::Popad), + ffi::_ND_INS_CLASS::ND_INS_POPCNT => Ok(Mnemonic::Popcnt), + ffi::_ND_INS_CLASS::ND_INS_POPF => Ok(Mnemonic::Popf), + ffi::_ND_INS_CLASS::ND_INS_POR => Ok(Mnemonic::Por), + ffi::_ND_INS_CLASS::ND_INS_PREFETCH => Ok(Mnemonic::Prefetch), + ffi::_ND_INS_CLASS::ND_INS_PREFETCHE => Ok(Mnemonic::Prefetche), + ffi::_ND_INS_CLASS::ND_INS_PREFETCHM => Ok(Mnemonic::Prefetchm), + ffi::_ND_INS_CLASS::ND_INS_PREFETCHNTA => Ok(Mnemonic::Prefetchnta), + ffi::_ND_INS_CLASS::ND_INS_PREFETCHT0 => Ok(Mnemonic::Prefetcht0), + ffi::_ND_INS_CLASS::ND_INS_PREFETCHT1 => Ok(Mnemonic::Prefetcht1), + ffi::_ND_INS_CLASS::ND_INS_PREFETCHT2 => Ok(Mnemonic::Prefetcht2), + ffi::_ND_INS_CLASS::ND_INS_PREFETCHW => Ok(Mnemonic::Prefetchw), + ffi::_ND_INS_CLASS::ND_INS_PREFETCHWT1 => Ok(Mnemonic::Prefetchwt1), + ffi::_ND_INS_CLASS::ND_INS_PSADBW => Ok(Mnemonic::Psadbw), + ffi::_ND_INS_CLASS::ND_INS_PSHUFB => Ok(Mnemonic::Pshufb), + ffi::_ND_INS_CLASS::ND_INS_PSHUFD => Ok(Mnemonic::Pshufd), + ffi::_ND_INS_CLASS::ND_INS_PSHUFHW => Ok(Mnemonic::Pshufhw), + ffi::_ND_INS_CLASS::ND_INS_PSHUFLW => Ok(Mnemonic::Pshuflw), + ffi::_ND_INS_CLASS::ND_INS_PSHUFW => Ok(Mnemonic::Pshufw), + ffi::_ND_INS_CLASS::ND_INS_PSIGNB => Ok(Mnemonic::Psignb), + ffi::_ND_INS_CLASS::ND_INS_PSIGND => Ok(Mnemonic::Psignd), + ffi::_ND_INS_CLASS::ND_INS_PSIGNW => Ok(Mnemonic::Psignw), + ffi::_ND_INS_CLASS::ND_INS_PSLLD => Ok(Mnemonic::Pslld), + ffi::_ND_INS_CLASS::ND_INS_PSLLDQ => Ok(Mnemonic::Pslldq), + ffi::_ND_INS_CLASS::ND_INS_PSLLQ => Ok(Mnemonic::Psllq), + ffi::_ND_INS_CLASS::ND_INS_PSLLW => Ok(Mnemonic::Psllw), + ffi::_ND_INS_CLASS::ND_INS_PSMASH => Ok(Mnemonic::Psmash), + ffi::_ND_INS_CLASS::ND_INS_PSRAD => Ok(Mnemonic::Psrad), + ffi::_ND_INS_CLASS::ND_INS_PSRAW => Ok(Mnemonic::Psraw), + ffi::_ND_INS_CLASS::ND_INS_PSRLD => Ok(Mnemonic::Psrld), + ffi::_ND_INS_CLASS::ND_INS_PSRLDQ => Ok(Mnemonic::Psrldq), + ffi::_ND_INS_CLASS::ND_INS_PSRLQ => Ok(Mnemonic::Psrlq), + ffi::_ND_INS_CLASS::ND_INS_PSRLW => Ok(Mnemonic::Psrlw), + ffi::_ND_INS_CLASS::ND_INS_PSUBB => Ok(Mnemonic::Psubb), + ffi::_ND_INS_CLASS::ND_INS_PSUBD => Ok(Mnemonic::Psubd), + ffi::_ND_INS_CLASS::ND_INS_PSUBQ => Ok(Mnemonic::Psubq), + ffi::_ND_INS_CLASS::ND_INS_PSUBSB => Ok(Mnemonic::Psubsb), + ffi::_ND_INS_CLASS::ND_INS_PSUBSW => Ok(Mnemonic::Psubsw), + ffi::_ND_INS_CLASS::ND_INS_PSUBUSB => Ok(Mnemonic::Psubusb), + ffi::_ND_INS_CLASS::ND_INS_PSUBUSW => Ok(Mnemonic::Psubusw), + ffi::_ND_INS_CLASS::ND_INS_PSUBW => Ok(Mnemonic::Psubw), + ffi::_ND_INS_CLASS::ND_INS_PSWAPD => Ok(Mnemonic::Pswapd), + ffi::_ND_INS_CLASS::ND_INS_PTEST => Ok(Mnemonic::Ptest), + ffi::_ND_INS_CLASS::ND_INS_PTWRITE => Ok(Mnemonic::Ptwrite), + ffi::_ND_INS_CLASS::ND_INS_PUNPCKHBW => Ok(Mnemonic::Punpckhbw), + ffi::_ND_INS_CLASS::ND_INS_PUNPCKHDQ => Ok(Mnemonic::Punpckhdq), + ffi::_ND_INS_CLASS::ND_INS_PUNPCKHQDQ => Ok(Mnemonic::Punpckhqdq), + ffi::_ND_INS_CLASS::ND_INS_PUNPCKHWD => Ok(Mnemonic::Punpckhwd), + ffi::_ND_INS_CLASS::ND_INS_PUNPCKLBW => Ok(Mnemonic::Punpcklbw), + ffi::_ND_INS_CLASS::ND_INS_PUNPCKLDQ => Ok(Mnemonic::Punpckldq), + ffi::_ND_INS_CLASS::ND_INS_PUNPCKLQDQ => Ok(Mnemonic::Punpcklqdq), + ffi::_ND_INS_CLASS::ND_INS_PUNPCKLWD => Ok(Mnemonic::Punpcklwd), + ffi::_ND_INS_CLASS::ND_INS_PUSH => Ok(Mnemonic::Push), + ffi::_ND_INS_CLASS::ND_INS_PUSHA => Ok(Mnemonic::Pusha), + ffi::_ND_INS_CLASS::ND_INS_PUSHAD => Ok(Mnemonic::Pushad), + ffi::_ND_INS_CLASS::ND_INS_PUSHF => Ok(Mnemonic::Pushf), + ffi::_ND_INS_CLASS::ND_INS_PVALIDATE => Ok(Mnemonic::Pvalidate), + ffi::_ND_INS_CLASS::ND_INS_PXOR => Ok(Mnemonic::Pxor), + ffi::_ND_INS_CLASS::ND_INS_RCL => Ok(Mnemonic::Rcl), + ffi::_ND_INS_CLASS::ND_INS_RCPPS => Ok(Mnemonic::Rcpps), + ffi::_ND_INS_CLASS::ND_INS_RCPSS => Ok(Mnemonic::Rcpss), + ffi::_ND_INS_CLASS::ND_INS_RCR => Ok(Mnemonic::Rcr), + ffi::_ND_INS_CLASS::ND_INS_RDFSBASE => Ok(Mnemonic::Rdfsbase), + ffi::_ND_INS_CLASS::ND_INS_RDGSBASE => Ok(Mnemonic::Rdgsbase), + ffi::_ND_INS_CLASS::ND_INS_RDMSR => Ok(Mnemonic::Rdmsr), + ffi::_ND_INS_CLASS::ND_INS_RDPID => Ok(Mnemonic::Rdpid), + ffi::_ND_INS_CLASS::ND_INS_RDPKRU => Ok(Mnemonic::Rdpkru), + ffi::_ND_INS_CLASS::ND_INS_RDPMC => Ok(Mnemonic::Rdpmc), + ffi::_ND_INS_CLASS::ND_INS_RDPRU => Ok(Mnemonic::Rdpru), + ffi::_ND_INS_CLASS::ND_INS_RDRAND => Ok(Mnemonic::Rdrand), + ffi::_ND_INS_CLASS::ND_INS_RDSEED => Ok(Mnemonic::Rdseed), + ffi::_ND_INS_CLASS::ND_INS_RDSHR => Ok(Mnemonic::Rdshr), + ffi::_ND_INS_CLASS::ND_INS_RDTSC => Ok(Mnemonic::Rdtsc), + ffi::_ND_INS_CLASS::ND_INS_RDTSCP => Ok(Mnemonic::Rdtscp), + ffi::_ND_INS_CLASS::ND_INS_RETF => Ok(Mnemonic::Retf), + ffi::_ND_INS_CLASS::ND_INS_RETN => Ok(Mnemonic::Retn), + ffi::_ND_INS_CLASS::ND_INS_RMPADJUST => Ok(Mnemonic::Rmpadjust), + ffi::_ND_INS_CLASS::ND_INS_RMPUPDATE => Ok(Mnemonic::Rmpupdate), + ffi::_ND_INS_CLASS::ND_INS_ROL => Ok(Mnemonic::Rol), + ffi::_ND_INS_CLASS::ND_INS_ROR => Ok(Mnemonic::Ror), + ffi::_ND_INS_CLASS::ND_INS_RORX => Ok(Mnemonic::Rorx), + ffi::_ND_INS_CLASS::ND_INS_ROUNDPD => Ok(Mnemonic::Roundpd), + ffi::_ND_INS_CLASS::ND_INS_ROUNDPS => Ok(Mnemonic::Roundps), + ffi::_ND_INS_CLASS::ND_INS_ROUNDSD => Ok(Mnemonic::Roundsd), + ffi::_ND_INS_CLASS::ND_INS_ROUNDSS => Ok(Mnemonic::Roundss), + ffi::_ND_INS_CLASS::ND_INS_RSDC => Ok(Mnemonic::Rsdc), + ffi::_ND_INS_CLASS::ND_INS_RSLDT => Ok(Mnemonic::Rsldt), + ffi::_ND_INS_CLASS::ND_INS_RSM => Ok(Mnemonic::Rsm), + ffi::_ND_INS_CLASS::ND_INS_RSQRTPS => Ok(Mnemonic::Rsqrtps), + ffi::_ND_INS_CLASS::ND_INS_RSQRTSS => Ok(Mnemonic::Rsqrtss), + ffi::_ND_INS_CLASS::ND_INS_RSSSP => Ok(Mnemonic::Rsssp), + ffi::_ND_INS_CLASS::ND_INS_RSTORSSP => Ok(Mnemonic::Rstorssp), + ffi::_ND_INS_CLASS::ND_INS_RSTS => Ok(Mnemonic::Rsts), + ffi::_ND_INS_CLASS::ND_INS_SAHF => Ok(Mnemonic::Sahf), + ffi::_ND_INS_CLASS::ND_INS_SAL => Ok(Mnemonic::Sal), + ffi::_ND_INS_CLASS::ND_INS_SALC => Ok(Mnemonic::Salc), + ffi::_ND_INS_CLASS::ND_INS_SAR => Ok(Mnemonic::Sar), + ffi::_ND_INS_CLASS::ND_INS_SARX => Ok(Mnemonic::Sarx), + ffi::_ND_INS_CLASS::ND_INS_SAVEPREVSSP => Ok(Mnemonic::Saveprevssp), + ffi::_ND_INS_CLASS::ND_INS_SBB => Ok(Mnemonic::Sbb), + ffi::_ND_INS_CLASS::ND_INS_SCAS => Ok(Mnemonic::Scas), + ffi::_ND_INS_CLASS::ND_INS_SEAMCALL => Ok(Mnemonic::Seamcall), + ffi::_ND_INS_CLASS::ND_INS_SEAMOPS => Ok(Mnemonic::Seamops), + ffi::_ND_INS_CLASS::ND_INS_SEAMRET => Ok(Mnemonic::Seamret), + ffi::_ND_INS_CLASS::ND_INS_SENDUIPI => Ok(Mnemonic::Senduipi), + ffi::_ND_INS_CLASS::ND_INS_SERIALIZE => Ok(Mnemonic::Serialize), + ffi::_ND_INS_CLASS::ND_INS_SETSSBSY => Ok(Mnemonic::Setssbsy), + ffi::_ND_INS_CLASS::ND_INS_SETcc => Ok(Mnemonic::Setcc), + ffi::_ND_INS_CLASS::ND_INS_SFENCE => Ok(Mnemonic::Sfence), + ffi::_ND_INS_CLASS::ND_INS_SGDT => Ok(Mnemonic::Sgdt), + ffi::_ND_INS_CLASS::ND_INS_SHA1MSG1 => Ok(Mnemonic::Sha1msg1), + ffi::_ND_INS_CLASS::ND_INS_SHA1MSG2 => Ok(Mnemonic::Sha1msg2), + ffi::_ND_INS_CLASS::ND_INS_SHA1NEXTE => Ok(Mnemonic::Sha1nexte), + ffi::_ND_INS_CLASS::ND_INS_SHA1RNDS4 => Ok(Mnemonic::Sha1rnds4), + ffi::_ND_INS_CLASS::ND_INS_SHA256MSG1 => Ok(Mnemonic::Sha256msg1), + ffi::_ND_INS_CLASS::ND_INS_SHA256MSG2 => Ok(Mnemonic::Sha256msg2), + ffi::_ND_INS_CLASS::ND_INS_SHA256RNDS2 => Ok(Mnemonic::Sha256rnds2), + ffi::_ND_INS_CLASS::ND_INS_SHL => Ok(Mnemonic::Shl), + ffi::_ND_INS_CLASS::ND_INS_SHLD => Ok(Mnemonic::Shld), + ffi::_ND_INS_CLASS::ND_INS_SHLX => Ok(Mnemonic::Shlx), + ffi::_ND_INS_CLASS::ND_INS_SHR => Ok(Mnemonic::Shr), + ffi::_ND_INS_CLASS::ND_INS_SHRD => Ok(Mnemonic::Shrd), + ffi::_ND_INS_CLASS::ND_INS_SHRX => Ok(Mnemonic::Shrx), + ffi::_ND_INS_CLASS::ND_INS_SHUFPD => Ok(Mnemonic::Shufpd), + ffi::_ND_INS_CLASS::ND_INS_SHUFPS => Ok(Mnemonic::Shufps), + ffi::_ND_INS_CLASS::ND_INS_SIDT => Ok(Mnemonic::Sidt), + ffi::_ND_INS_CLASS::ND_INS_SKINIT => Ok(Mnemonic::Skinit), + ffi::_ND_INS_CLASS::ND_INS_SLDT => Ok(Mnemonic::Sldt), + ffi::_ND_INS_CLASS::ND_INS_SLWPCB => Ok(Mnemonic::Slwpcb), + ffi::_ND_INS_CLASS::ND_INS_SMINT => Ok(Mnemonic::Smint), + ffi::_ND_INS_CLASS::ND_INS_SMSW => Ok(Mnemonic::Smsw), + ffi::_ND_INS_CLASS::ND_INS_SPFLT => Ok(Mnemonic::Spflt), + ffi::_ND_INS_CLASS::ND_INS_SQRTPD => Ok(Mnemonic::Sqrtpd), + ffi::_ND_INS_CLASS::ND_INS_SQRTPS => Ok(Mnemonic::Sqrtps), + ffi::_ND_INS_CLASS::ND_INS_SQRTSD => Ok(Mnemonic::Sqrtsd), + ffi::_ND_INS_CLASS::ND_INS_SQRTSS => Ok(Mnemonic::Sqrtss), + ffi::_ND_INS_CLASS::ND_INS_STAC => Ok(Mnemonic::Stac), + ffi::_ND_INS_CLASS::ND_INS_STC => Ok(Mnemonic::Stc), + ffi::_ND_INS_CLASS::ND_INS_STD => Ok(Mnemonic::Std), + ffi::_ND_INS_CLASS::ND_INS_STGI => Ok(Mnemonic::Stgi), + ffi::_ND_INS_CLASS::ND_INS_STI => Ok(Mnemonic::Sti), + ffi::_ND_INS_CLASS::ND_INS_STMXCSR => Ok(Mnemonic::Stmxcsr), + ffi::_ND_INS_CLASS::ND_INS_STOS => Ok(Mnemonic::Stos), + ffi::_ND_INS_CLASS::ND_INS_STR => Ok(Mnemonic::Str), + ffi::_ND_INS_CLASS::ND_INS_STTILECFG => Ok(Mnemonic::Sttilecfg), + ffi::_ND_INS_CLASS::ND_INS_STUI => Ok(Mnemonic::Stui), + ffi::_ND_INS_CLASS::ND_INS_SUB => Ok(Mnemonic::Sub), + ffi::_ND_INS_CLASS::ND_INS_SUBPD => Ok(Mnemonic::Subpd), + ffi::_ND_INS_CLASS::ND_INS_SUBPS => Ok(Mnemonic::Subps), + ffi::_ND_INS_CLASS::ND_INS_SUBSD => Ok(Mnemonic::Subsd), + ffi::_ND_INS_CLASS::ND_INS_SUBSS => Ok(Mnemonic::Subss), + ffi::_ND_INS_CLASS::ND_INS_SVDC => Ok(Mnemonic::Svdc), + ffi::_ND_INS_CLASS::ND_INS_SVLDT => Ok(Mnemonic::Svldt), + ffi::_ND_INS_CLASS::ND_INS_SVTS => Ok(Mnemonic::Svts), + ffi::_ND_INS_CLASS::ND_INS_SWAPGS => Ok(Mnemonic::Swapgs), + ffi::_ND_INS_CLASS::ND_INS_SYSCALL => Ok(Mnemonic::Syscall), + ffi::_ND_INS_CLASS::ND_INS_SYSENTER => Ok(Mnemonic::Sysenter), + ffi::_ND_INS_CLASS::ND_INS_SYSEXIT => Ok(Mnemonic::Sysexit), + ffi::_ND_INS_CLASS::ND_INS_SYSRET => Ok(Mnemonic::Sysret), + ffi::_ND_INS_CLASS::ND_INS_T1MSKC => Ok(Mnemonic::T1mskc), + ffi::_ND_INS_CLASS::ND_INS_TDCALL => Ok(Mnemonic::Tdcall), + ffi::_ND_INS_CLASS::ND_INS_TDPBF16PS => Ok(Mnemonic::Tdpbf16ps), + ffi::_ND_INS_CLASS::ND_INS_TDPBSSD => Ok(Mnemonic::Tdpbssd), + ffi::_ND_INS_CLASS::ND_INS_TDPBSUD => Ok(Mnemonic::Tdpbsud), + ffi::_ND_INS_CLASS::ND_INS_TDPBUSD => Ok(Mnemonic::Tdpbusd), + ffi::_ND_INS_CLASS::ND_INS_TDPBUUD => Ok(Mnemonic::Tdpbuud), + ffi::_ND_INS_CLASS::ND_INS_TEST => Ok(Mnemonic::Test), + ffi::_ND_INS_CLASS::ND_INS_TESTUI => Ok(Mnemonic::Testui), + ffi::_ND_INS_CLASS::ND_INS_TILELOADD => Ok(Mnemonic::Tileloadd), + ffi::_ND_INS_CLASS::ND_INS_TILELOADDT1 => Ok(Mnemonic::Tileloaddt1), + ffi::_ND_INS_CLASS::ND_INS_TILERELEASE => Ok(Mnemonic::Tilerelease), + ffi::_ND_INS_CLASS::ND_INS_TILESTORED => Ok(Mnemonic::Tilestored), + ffi::_ND_INS_CLASS::ND_INS_TILEZERO => Ok(Mnemonic::Tilezero), + ffi::_ND_INS_CLASS::ND_INS_TLBSYNC => Ok(Mnemonic::Tlbsync), + ffi::_ND_INS_CLASS::ND_INS_TPAUSE => Ok(Mnemonic::Tpause), + ffi::_ND_INS_CLASS::ND_INS_TZCNT => Ok(Mnemonic::Tzcnt), + ffi::_ND_INS_CLASS::ND_INS_TZMSK => Ok(Mnemonic::Tzmsk), + ffi::_ND_INS_CLASS::ND_INS_UCOMISD => Ok(Mnemonic::Ucomisd), + ffi::_ND_INS_CLASS::ND_INS_UCOMISS => Ok(Mnemonic::Ucomiss), + ffi::_ND_INS_CLASS::ND_INS_UD0 => Ok(Mnemonic::Ud0), + ffi::_ND_INS_CLASS::ND_INS_UD1 => Ok(Mnemonic::Ud1), + ffi::_ND_INS_CLASS::ND_INS_UD2 => Ok(Mnemonic::Ud2), + ffi::_ND_INS_CLASS::ND_INS_UIRET => Ok(Mnemonic::Uiret), + ffi::_ND_INS_CLASS::ND_INS_UMONITOR => Ok(Mnemonic::Umonitor), + ffi::_ND_INS_CLASS::ND_INS_UMWAIT => Ok(Mnemonic::Umwait), + ffi::_ND_INS_CLASS::ND_INS_UNPCKHPD => Ok(Mnemonic::Unpckhpd), + ffi::_ND_INS_CLASS::ND_INS_UNPCKHPS => Ok(Mnemonic::Unpckhps), + ffi::_ND_INS_CLASS::ND_INS_UNPCKLPD => Ok(Mnemonic::Unpcklpd), + ffi::_ND_INS_CLASS::ND_INS_UNPCKLPS => Ok(Mnemonic::Unpcklps), + ffi::_ND_INS_CLASS::ND_INS_V4FMADDPS => Ok(Mnemonic::V4fmaddps), + ffi::_ND_INS_CLASS::ND_INS_V4FMADDSS => Ok(Mnemonic::V4fmaddss), + ffi::_ND_INS_CLASS::ND_INS_V4FNMADDPS => Ok(Mnemonic::V4fnmaddps), + ffi::_ND_INS_CLASS::ND_INS_V4FNMADDSS => Ok(Mnemonic::V4fnmaddss), + ffi::_ND_INS_CLASS::ND_INS_VADDPD => Ok(Mnemonic::Vaddpd), + ffi::_ND_INS_CLASS::ND_INS_VADDPH => Ok(Mnemonic::Vaddph), + ffi::_ND_INS_CLASS::ND_INS_VADDPS => Ok(Mnemonic::Vaddps), + ffi::_ND_INS_CLASS::ND_INS_VADDSD => Ok(Mnemonic::Vaddsd), + ffi::_ND_INS_CLASS::ND_INS_VADDSH => Ok(Mnemonic::Vaddsh), + ffi::_ND_INS_CLASS::ND_INS_VADDSS => Ok(Mnemonic::Vaddss), + ffi::_ND_INS_CLASS::ND_INS_VADDSUBPD => Ok(Mnemonic::Vaddsubpd), + ffi::_ND_INS_CLASS::ND_INS_VADDSUBPS => Ok(Mnemonic::Vaddsubps), + ffi::_ND_INS_CLASS::ND_INS_VAESDEC => Ok(Mnemonic::Vaesdec), + ffi::_ND_INS_CLASS::ND_INS_VAESDECLAST => Ok(Mnemonic::Vaesdeclast), + ffi::_ND_INS_CLASS::ND_INS_VAESENC => Ok(Mnemonic::Vaesenc), + ffi::_ND_INS_CLASS::ND_INS_VAESENCLAST => Ok(Mnemonic::Vaesenclast), + ffi::_ND_INS_CLASS::ND_INS_VAESIMC => Ok(Mnemonic::Vaesimc), + ffi::_ND_INS_CLASS::ND_INS_VAESKEYGENASSIST => Ok(Mnemonic::Vaeskeygenassist), + ffi::_ND_INS_CLASS::ND_INS_VALIGND => Ok(Mnemonic::Valignd), + ffi::_ND_INS_CLASS::ND_INS_VALIGNQ => Ok(Mnemonic::Valignq), + ffi::_ND_INS_CLASS::ND_INS_VANDNPD => Ok(Mnemonic::Vandnpd), + ffi::_ND_INS_CLASS::ND_INS_VANDNPS => Ok(Mnemonic::Vandnps), + ffi::_ND_INS_CLASS::ND_INS_VANDPD => Ok(Mnemonic::Vandpd), + ffi::_ND_INS_CLASS::ND_INS_VANDPS => Ok(Mnemonic::Vandps), + ffi::_ND_INS_CLASS::ND_INS_VBLENDMPD => Ok(Mnemonic::Vblendmpd), + ffi::_ND_INS_CLASS::ND_INS_VBLENDMPS => Ok(Mnemonic::Vblendmps), + ffi::_ND_INS_CLASS::ND_INS_VBLENDPD => Ok(Mnemonic::Vblendpd), + ffi::_ND_INS_CLASS::ND_INS_VBLENDPS => Ok(Mnemonic::Vblendps), + ffi::_ND_INS_CLASS::ND_INS_VBLENDVPD => Ok(Mnemonic::Vblendvpd), + ffi::_ND_INS_CLASS::ND_INS_VBLENDVPS => Ok(Mnemonic::Vblendvps), + ffi::_ND_INS_CLASS::ND_INS_VBROADCASTF128 => Ok(Mnemonic::Vbroadcastf128), + ffi::_ND_INS_CLASS::ND_INS_VBROADCASTF32X2 => Ok(Mnemonic::Vbroadcastf32x2), + ffi::_ND_INS_CLASS::ND_INS_VBROADCASTF32X4 => Ok(Mnemonic::Vbroadcastf32x4), + ffi::_ND_INS_CLASS::ND_INS_VBROADCASTF32X8 => Ok(Mnemonic::Vbroadcastf32x8), + ffi::_ND_INS_CLASS::ND_INS_VBROADCASTF64X2 => Ok(Mnemonic::Vbroadcastf64x2), + ffi::_ND_INS_CLASS::ND_INS_VBROADCASTF64X4 => Ok(Mnemonic::Vbroadcastf64x4), + ffi::_ND_INS_CLASS::ND_INS_VBROADCASTI128 => Ok(Mnemonic::Vbroadcasti128), + ffi::_ND_INS_CLASS::ND_INS_VBROADCASTI32X2 => Ok(Mnemonic::Vbroadcasti32x2), + ffi::_ND_INS_CLASS::ND_INS_VBROADCASTI32X4 => Ok(Mnemonic::Vbroadcasti32x4), + ffi::_ND_INS_CLASS::ND_INS_VBROADCASTI32X8 => Ok(Mnemonic::Vbroadcasti32x8), + ffi::_ND_INS_CLASS::ND_INS_VBROADCASTI64X2 => Ok(Mnemonic::Vbroadcasti64x2), + ffi::_ND_INS_CLASS::ND_INS_VBROADCASTI64X4 => Ok(Mnemonic::Vbroadcasti64x4), + ffi::_ND_INS_CLASS::ND_INS_VBROADCASTSD => Ok(Mnemonic::Vbroadcastsd), + ffi::_ND_INS_CLASS::ND_INS_VBROADCASTSS => Ok(Mnemonic::Vbroadcastss), + ffi::_ND_INS_CLASS::ND_INS_VCMPPD => Ok(Mnemonic::Vcmppd), + ffi::_ND_INS_CLASS::ND_INS_VCMPPH => Ok(Mnemonic::Vcmpph), + ffi::_ND_INS_CLASS::ND_INS_VCMPPS => Ok(Mnemonic::Vcmpps), + ffi::_ND_INS_CLASS::ND_INS_VCMPSD => Ok(Mnemonic::Vcmpsd), + ffi::_ND_INS_CLASS::ND_INS_VCMPSH => Ok(Mnemonic::Vcmpsh), + ffi::_ND_INS_CLASS::ND_INS_VCMPSS => Ok(Mnemonic::Vcmpss), + ffi::_ND_INS_CLASS::ND_INS_VCOMISD => Ok(Mnemonic::Vcomisd), + ffi::_ND_INS_CLASS::ND_INS_VCOMISH => Ok(Mnemonic::Vcomish), + ffi::_ND_INS_CLASS::ND_INS_VCOMISS => Ok(Mnemonic::Vcomiss), + ffi::_ND_INS_CLASS::ND_INS_VCOMPRESSPD => Ok(Mnemonic::Vcompresspd), + ffi::_ND_INS_CLASS::ND_INS_VCOMPRESSPS => Ok(Mnemonic::Vcompressps), + ffi::_ND_INS_CLASS::ND_INS_VCVTDQ2PD => Ok(Mnemonic::Vcvtdq2pd), + ffi::_ND_INS_CLASS::ND_INS_VCVTDQ2PH => Ok(Mnemonic::Vcvtdq2ph), + ffi::_ND_INS_CLASS::ND_INS_VCVTDQ2PS => Ok(Mnemonic::Vcvtdq2ps), + ffi::_ND_INS_CLASS::ND_INS_VCVTNE2PS2BF16 => Ok(Mnemonic::Vcvtne2ps2bf16), + ffi::_ND_INS_CLASS::ND_INS_VCVTNEPS2BF16 => Ok(Mnemonic::Vcvtneps2bf16), + ffi::_ND_INS_CLASS::ND_INS_VCVTPD2DQ => Ok(Mnemonic::Vcvtpd2dq), + ffi::_ND_INS_CLASS::ND_INS_VCVTPD2PH => Ok(Mnemonic::Vcvtpd2ph), + ffi::_ND_INS_CLASS::ND_INS_VCVTPD2PS => Ok(Mnemonic::Vcvtpd2ps), + ffi::_ND_INS_CLASS::ND_INS_VCVTPD2QQ => Ok(Mnemonic::Vcvtpd2qq), + ffi::_ND_INS_CLASS::ND_INS_VCVTPD2UDQ => Ok(Mnemonic::Vcvtpd2udq), + ffi::_ND_INS_CLASS::ND_INS_VCVTPD2UQQ => Ok(Mnemonic::Vcvtpd2uqq), + ffi::_ND_INS_CLASS::ND_INS_VCVTPH2DQ => Ok(Mnemonic::Vcvtph2dq), + ffi::_ND_INS_CLASS::ND_INS_VCVTPH2PD => Ok(Mnemonic::Vcvtph2pd), + ffi::_ND_INS_CLASS::ND_INS_VCVTPH2PS => Ok(Mnemonic::Vcvtph2ps), + ffi::_ND_INS_CLASS::ND_INS_VCVTPH2PSX => Ok(Mnemonic::Vcvtph2psx), + ffi::_ND_INS_CLASS::ND_INS_VCVTPH2QQ => Ok(Mnemonic::Vcvtph2qq), + ffi::_ND_INS_CLASS::ND_INS_VCVTPH2UDQ => Ok(Mnemonic::Vcvtph2udq), + ffi::_ND_INS_CLASS::ND_INS_VCVTPH2UQQ => Ok(Mnemonic::Vcvtph2uqq), + ffi::_ND_INS_CLASS::ND_INS_VCVTPH2UW => Ok(Mnemonic::Vcvtph2uw), + ffi::_ND_INS_CLASS::ND_INS_VCVTPH2W => Ok(Mnemonic::Vcvtph2w), + ffi::_ND_INS_CLASS::ND_INS_VCVTPS2DQ => Ok(Mnemonic::Vcvtps2dq), + ffi::_ND_INS_CLASS::ND_INS_VCVTPS2PD => Ok(Mnemonic::Vcvtps2pd), + ffi::_ND_INS_CLASS::ND_INS_VCVTPS2PH => Ok(Mnemonic::Vcvtps2ph), + ffi::_ND_INS_CLASS::ND_INS_VCVTPS2PHX => Ok(Mnemonic::Vcvtps2phx), + ffi::_ND_INS_CLASS::ND_INS_VCVTPS2QQ => Ok(Mnemonic::Vcvtps2qq), + ffi::_ND_INS_CLASS::ND_INS_VCVTPS2UDQ => Ok(Mnemonic::Vcvtps2udq), + ffi::_ND_INS_CLASS::ND_INS_VCVTPS2UQQ => Ok(Mnemonic::Vcvtps2uqq), + ffi::_ND_INS_CLASS::ND_INS_VCVTQQ2PD => Ok(Mnemonic::Vcvtqq2pd), + ffi::_ND_INS_CLASS::ND_INS_VCVTQQ2PH => Ok(Mnemonic::Vcvtqq2ph), + ffi::_ND_INS_CLASS::ND_INS_VCVTQQ2PS => Ok(Mnemonic::Vcvtqq2ps), + ffi::_ND_INS_CLASS::ND_INS_VCVTSD2SH => Ok(Mnemonic::Vcvtsd2sh), + ffi::_ND_INS_CLASS::ND_INS_VCVTSD2SI => Ok(Mnemonic::Vcvtsd2si), + ffi::_ND_INS_CLASS::ND_INS_VCVTSD2SS => Ok(Mnemonic::Vcvtsd2ss), + ffi::_ND_INS_CLASS::ND_INS_VCVTSD2USI => Ok(Mnemonic::Vcvtsd2usi), + ffi::_ND_INS_CLASS::ND_INS_VCVTSH2SD => Ok(Mnemonic::Vcvtsh2sd), + ffi::_ND_INS_CLASS::ND_INS_VCVTSH2SI => Ok(Mnemonic::Vcvtsh2si), + ffi::_ND_INS_CLASS::ND_INS_VCVTSH2SS => Ok(Mnemonic::Vcvtsh2ss), + ffi::_ND_INS_CLASS::ND_INS_VCVTSH2USI => Ok(Mnemonic::Vcvtsh2usi), + ffi::_ND_INS_CLASS::ND_INS_VCVTSI2SD => Ok(Mnemonic::Vcvtsi2sd), + ffi::_ND_INS_CLASS::ND_INS_VCVTSI2SH => Ok(Mnemonic::Vcvtsi2sh), + ffi::_ND_INS_CLASS::ND_INS_VCVTSI2SS => Ok(Mnemonic::Vcvtsi2ss), + ffi::_ND_INS_CLASS::ND_INS_VCVTSS2SD => Ok(Mnemonic::Vcvtss2sd), + ffi::_ND_INS_CLASS::ND_INS_VCVTSS2SH => Ok(Mnemonic::Vcvtss2sh), + ffi::_ND_INS_CLASS::ND_INS_VCVTSS2SI => Ok(Mnemonic::Vcvtss2si), + ffi::_ND_INS_CLASS::ND_INS_VCVTSS2USI => Ok(Mnemonic::Vcvtss2usi), + ffi::_ND_INS_CLASS::ND_INS_VCVTTPD2DQ => Ok(Mnemonic::Vcvttpd2dq), + ffi::_ND_INS_CLASS::ND_INS_VCVTTPD2QQ => Ok(Mnemonic::Vcvttpd2qq), + ffi::_ND_INS_CLASS::ND_INS_VCVTTPD2UDQ => Ok(Mnemonic::Vcvttpd2udq), + ffi::_ND_INS_CLASS::ND_INS_VCVTTPD2UQQ => Ok(Mnemonic::Vcvttpd2uqq), + ffi::_ND_INS_CLASS::ND_INS_VCVTTPH2DQ => Ok(Mnemonic::Vcvttph2dq), + ffi::_ND_INS_CLASS::ND_INS_VCVTTPH2QQ => Ok(Mnemonic::Vcvttph2qq), + ffi::_ND_INS_CLASS::ND_INS_VCVTTPH2UDQ => Ok(Mnemonic::Vcvttph2udq), + ffi::_ND_INS_CLASS::ND_INS_VCVTTPH2UQQ => Ok(Mnemonic::Vcvttph2uqq), + ffi::_ND_INS_CLASS::ND_INS_VCVTTPH2UW => Ok(Mnemonic::Vcvttph2uw), + ffi::_ND_INS_CLASS::ND_INS_VCVTTPH2W => Ok(Mnemonic::Vcvttph2w), + ffi::_ND_INS_CLASS::ND_INS_VCVTTPS2DQ => Ok(Mnemonic::Vcvttps2dq), + ffi::_ND_INS_CLASS::ND_INS_VCVTTPS2QQ => Ok(Mnemonic::Vcvttps2qq), + ffi::_ND_INS_CLASS::ND_INS_VCVTTPS2UDQ => Ok(Mnemonic::Vcvttps2udq), + ffi::_ND_INS_CLASS::ND_INS_VCVTTPS2UQQ => Ok(Mnemonic::Vcvttps2uqq), + ffi::_ND_INS_CLASS::ND_INS_VCVTTSD2SI => Ok(Mnemonic::Vcvttsd2si), + ffi::_ND_INS_CLASS::ND_INS_VCVTTSD2USI => Ok(Mnemonic::Vcvttsd2usi), + ffi::_ND_INS_CLASS::ND_INS_VCVTTSH2SI => Ok(Mnemonic::Vcvttsh2si), + ffi::_ND_INS_CLASS::ND_INS_VCVTTSH2USI => Ok(Mnemonic::Vcvttsh2usi), + ffi::_ND_INS_CLASS::ND_INS_VCVTTSS2SI => Ok(Mnemonic::Vcvttss2si), + ffi::_ND_INS_CLASS::ND_INS_VCVTTSS2USI => Ok(Mnemonic::Vcvttss2usi), + ffi::_ND_INS_CLASS::ND_INS_VCVTUDQ2PD => Ok(Mnemonic::Vcvtudq2pd), + ffi::_ND_INS_CLASS::ND_INS_VCVTUDQ2PH => Ok(Mnemonic::Vcvtudq2ph), + ffi::_ND_INS_CLASS::ND_INS_VCVTUDQ2PS => Ok(Mnemonic::Vcvtudq2ps), + ffi::_ND_INS_CLASS::ND_INS_VCVTUQQ2PD => Ok(Mnemonic::Vcvtuqq2pd), + ffi::_ND_INS_CLASS::ND_INS_VCVTUQQ2PH => Ok(Mnemonic::Vcvtuqq2ph), + ffi::_ND_INS_CLASS::ND_INS_VCVTUQQ2PS => Ok(Mnemonic::Vcvtuqq2ps), + ffi::_ND_INS_CLASS::ND_INS_VCVTUSI2SD => Ok(Mnemonic::Vcvtusi2sd), + ffi::_ND_INS_CLASS::ND_INS_VCVTUSI2SH => Ok(Mnemonic::Vcvtusi2sh), + ffi::_ND_INS_CLASS::ND_INS_VCVTUSI2SS => Ok(Mnemonic::Vcvtusi2ss), + ffi::_ND_INS_CLASS::ND_INS_VCVTUW2PH => Ok(Mnemonic::Vcvtuw2ph), + ffi::_ND_INS_CLASS::ND_INS_VCVTW2PH => Ok(Mnemonic::Vcvtw2ph), + ffi::_ND_INS_CLASS::ND_INS_VDBPSADBW => Ok(Mnemonic::Vdbpsadbw), + ffi::_ND_INS_CLASS::ND_INS_VDIVPD => Ok(Mnemonic::Vdivpd), + ffi::_ND_INS_CLASS::ND_INS_VDIVPH => Ok(Mnemonic::Vdivph), + ffi::_ND_INS_CLASS::ND_INS_VDIVPS => Ok(Mnemonic::Vdivps), + ffi::_ND_INS_CLASS::ND_INS_VDIVSD => Ok(Mnemonic::Vdivsd), + ffi::_ND_INS_CLASS::ND_INS_VDIVSH => Ok(Mnemonic::Vdivsh), + ffi::_ND_INS_CLASS::ND_INS_VDIVSS => Ok(Mnemonic::Vdivss), + ffi::_ND_INS_CLASS::ND_INS_VDPBF16PS => Ok(Mnemonic::Vdpbf16ps), + ffi::_ND_INS_CLASS::ND_INS_VDPPD => Ok(Mnemonic::Vdppd), + ffi::_ND_INS_CLASS::ND_INS_VDPPS => Ok(Mnemonic::Vdpps), + ffi::_ND_INS_CLASS::ND_INS_VERR => Ok(Mnemonic::Verr), + ffi::_ND_INS_CLASS::ND_INS_VERW => Ok(Mnemonic::Verw), + ffi::_ND_INS_CLASS::ND_INS_VEXP2PD => Ok(Mnemonic::Vexp2pd), + ffi::_ND_INS_CLASS::ND_INS_VEXP2PS => Ok(Mnemonic::Vexp2ps), + ffi::_ND_INS_CLASS::ND_INS_VEXPANDPD => Ok(Mnemonic::Vexpandpd), + ffi::_ND_INS_CLASS::ND_INS_VEXPANDPS => Ok(Mnemonic::Vexpandps), + ffi::_ND_INS_CLASS::ND_INS_VEXTRACTF128 => Ok(Mnemonic::Vextractf128), + ffi::_ND_INS_CLASS::ND_INS_VEXTRACTF32X4 => Ok(Mnemonic::Vextractf32x4), + ffi::_ND_INS_CLASS::ND_INS_VEXTRACTF32X8 => Ok(Mnemonic::Vextractf32x8), + ffi::_ND_INS_CLASS::ND_INS_VEXTRACTF64X2 => Ok(Mnemonic::Vextractf64x2), + ffi::_ND_INS_CLASS::ND_INS_VEXTRACTF64X4 => Ok(Mnemonic::Vextractf64x4), + ffi::_ND_INS_CLASS::ND_INS_VEXTRACTI128 => Ok(Mnemonic::Vextracti128), + ffi::_ND_INS_CLASS::ND_INS_VEXTRACTI32X4 => Ok(Mnemonic::Vextracti32x4), + ffi::_ND_INS_CLASS::ND_INS_VEXTRACTI32X8 => Ok(Mnemonic::Vextracti32x8), + ffi::_ND_INS_CLASS::ND_INS_VEXTRACTI64X2 => Ok(Mnemonic::Vextracti64x2), + ffi::_ND_INS_CLASS::ND_INS_VEXTRACTI64X4 => Ok(Mnemonic::Vextracti64x4), + ffi::_ND_INS_CLASS::ND_INS_VEXTRACTPS => Ok(Mnemonic::Vextractps), + ffi::_ND_INS_CLASS::ND_INS_VFCMADDCPH => Ok(Mnemonic::Vfcmaddcph), + ffi::_ND_INS_CLASS::ND_INS_VFCMADDCSH => Ok(Mnemonic::Vfcmaddcsh), + ffi::_ND_INS_CLASS::ND_INS_VFCMULCPH => Ok(Mnemonic::Vfcmulcph), + ffi::_ND_INS_CLASS::ND_INS_VFCMULCSH => Ok(Mnemonic::Vfcmulcsh), + ffi::_ND_INS_CLASS::ND_INS_VFIXUPIMMPD => Ok(Mnemonic::Vfixupimmpd), + ffi::_ND_INS_CLASS::ND_INS_VFIXUPIMMPS => Ok(Mnemonic::Vfixupimmps), + ffi::_ND_INS_CLASS::ND_INS_VFIXUPIMMSD => Ok(Mnemonic::Vfixupimmsd), + ffi::_ND_INS_CLASS::ND_INS_VFIXUPIMMSS => Ok(Mnemonic::Vfixupimmss), + ffi::_ND_INS_CLASS::ND_INS_VFMADD132PD => Ok(Mnemonic::Vfmadd132pd), + ffi::_ND_INS_CLASS::ND_INS_VFMADD132PH => Ok(Mnemonic::Vfmadd132ph), + ffi::_ND_INS_CLASS::ND_INS_VFMADD132PS => Ok(Mnemonic::Vfmadd132ps), + ffi::_ND_INS_CLASS::ND_INS_VFMADD132SD => Ok(Mnemonic::Vfmadd132sd), + ffi::_ND_INS_CLASS::ND_INS_VFMADD132SH => Ok(Mnemonic::Vfmadd132sh), + ffi::_ND_INS_CLASS::ND_INS_VFMADD132SS => Ok(Mnemonic::Vfmadd132ss), + ffi::_ND_INS_CLASS::ND_INS_VFMADD213PD => Ok(Mnemonic::Vfmadd213pd), + ffi::_ND_INS_CLASS::ND_INS_VFMADD213PH => Ok(Mnemonic::Vfmadd213ph), + ffi::_ND_INS_CLASS::ND_INS_VFMADD213PS => Ok(Mnemonic::Vfmadd213ps), + ffi::_ND_INS_CLASS::ND_INS_VFMADD213SD => Ok(Mnemonic::Vfmadd213sd), + ffi::_ND_INS_CLASS::ND_INS_VFMADD213SH => Ok(Mnemonic::Vfmadd213sh), + ffi::_ND_INS_CLASS::ND_INS_VFMADD213SS => Ok(Mnemonic::Vfmadd213ss), + ffi::_ND_INS_CLASS::ND_INS_VFMADD231PD => Ok(Mnemonic::Vfmadd231pd), + ffi::_ND_INS_CLASS::ND_INS_VFMADD231PH => Ok(Mnemonic::Vfmadd231ph), + ffi::_ND_INS_CLASS::ND_INS_VFMADD231PS => Ok(Mnemonic::Vfmadd231ps), + ffi::_ND_INS_CLASS::ND_INS_VFMADD231SD => Ok(Mnemonic::Vfmadd231sd), + ffi::_ND_INS_CLASS::ND_INS_VFMADD231SH => Ok(Mnemonic::Vfmadd231sh), + ffi::_ND_INS_CLASS::ND_INS_VFMADD231SS => Ok(Mnemonic::Vfmadd231ss), + ffi::_ND_INS_CLASS::ND_INS_VFMADDCPH => Ok(Mnemonic::Vfmaddcph), + ffi::_ND_INS_CLASS::ND_INS_VFMADDCSH => Ok(Mnemonic::Vfmaddcsh), + ffi::_ND_INS_CLASS::ND_INS_VFMADDPD => Ok(Mnemonic::Vfmaddpd), + ffi::_ND_INS_CLASS::ND_INS_VFMADDPS => Ok(Mnemonic::Vfmaddps), + ffi::_ND_INS_CLASS::ND_INS_VFMADDSD => Ok(Mnemonic::Vfmaddsd), + ffi::_ND_INS_CLASS::ND_INS_VFMADDSS => Ok(Mnemonic::Vfmaddss), + ffi::_ND_INS_CLASS::ND_INS_VFMADDSUB132PD => Ok(Mnemonic::Vfmaddsub132pd), + ffi::_ND_INS_CLASS::ND_INS_VFMADDSUB132PH => Ok(Mnemonic::Vfmaddsub132ph), + ffi::_ND_INS_CLASS::ND_INS_VFMADDSUB132PS => Ok(Mnemonic::Vfmaddsub132ps), + ffi::_ND_INS_CLASS::ND_INS_VFMADDSUB213PD => Ok(Mnemonic::Vfmaddsub213pd), + ffi::_ND_INS_CLASS::ND_INS_VFMADDSUB213PH => Ok(Mnemonic::Vfmaddsub213ph), + ffi::_ND_INS_CLASS::ND_INS_VFMADDSUB213PS => Ok(Mnemonic::Vfmaddsub213ps), + ffi::_ND_INS_CLASS::ND_INS_VFMADDSUB231PD => Ok(Mnemonic::Vfmaddsub231pd), + ffi::_ND_INS_CLASS::ND_INS_VFMADDSUB231PH => Ok(Mnemonic::Vfmaddsub231ph), + ffi::_ND_INS_CLASS::ND_INS_VFMADDSUB231PS => Ok(Mnemonic::Vfmaddsub231ps), + ffi::_ND_INS_CLASS::ND_INS_VFMADDSUBPD => Ok(Mnemonic::Vfmaddsubpd), + ffi::_ND_INS_CLASS::ND_INS_VFMADDSUBPS => Ok(Mnemonic::Vfmaddsubps), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB132PD => Ok(Mnemonic::Vfmsub132pd), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB132PH => Ok(Mnemonic::Vfmsub132ph), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB132PS => Ok(Mnemonic::Vfmsub132ps), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB132SD => Ok(Mnemonic::Vfmsub132sd), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB132SH => Ok(Mnemonic::Vfmsub132sh), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB132SS => Ok(Mnemonic::Vfmsub132ss), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB213PD => Ok(Mnemonic::Vfmsub213pd), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB213PH => Ok(Mnemonic::Vfmsub213ph), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB213PS => Ok(Mnemonic::Vfmsub213ps), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB213SD => Ok(Mnemonic::Vfmsub213sd), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB213SH => Ok(Mnemonic::Vfmsub213sh), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB213SS => Ok(Mnemonic::Vfmsub213ss), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB231PD => Ok(Mnemonic::Vfmsub231pd), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB231PH => Ok(Mnemonic::Vfmsub231ph), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB231PS => Ok(Mnemonic::Vfmsub231ps), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB231SD => Ok(Mnemonic::Vfmsub231sd), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB231SH => Ok(Mnemonic::Vfmsub231sh), + ffi::_ND_INS_CLASS::ND_INS_VFMSUB231SS => Ok(Mnemonic::Vfmsub231ss), + ffi::_ND_INS_CLASS::ND_INS_VFMSUBADD132PD => Ok(Mnemonic::Vfmsubadd132pd), + ffi::_ND_INS_CLASS::ND_INS_VFMSUBADD132PH => Ok(Mnemonic::Vfmsubadd132ph), + ffi::_ND_INS_CLASS::ND_INS_VFMSUBADD132PS => Ok(Mnemonic::Vfmsubadd132ps), + ffi::_ND_INS_CLASS::ND_INS_VFMSUBADD213PD => Ok(Mnemonic::Vfmsubadd213pd), + ffi::_ND_INS_CLASS::ND_INS_VFMSUBADD213PH => Ok(Mnemonic::Vfmsubadd213ph), + ffi::_ND_INS_CLASS::ND_INS_VFMSUBADD213PS => Ok(Mnemonic::Vfmsubadd213ps), + ffi::_ND_INS_CLASS::ND_INS_VFMSUBADD231PD => Ok(Mnemonic::Vfmsubadd231pd), + ffi::_ND_INS_CLASS::ND_INS_VFMSUBADD231PH => Ok(Mnemonic::Vfmsubadd231ph), + ffi::_ND_INS_CLASS::ND_INS_VFMSUBADD231PS => Ok(Mnemonic::Vfmsubadd231ps), + ffi::_ND_INS_CLASS::ND_INS_VFMSUBADDPD => Ok(Mnemonic::Vfmsubaddpd), + ffi::_ND_INS_CLASS::ND_INS_VFMSUBADDPS => Ok(Mnemonic::Vfmsubaddps), + ffi::_ND_INS_CLASS::ND_INS_VFMSUBPD => Ok(Mnemonic::Vfmsubpd), + ffi::_ND_INS_CLASS::ND_INS_VFMSUBPS => Ok(Mnemonic::Vfmsubps), + ffi::_ND_INS_CLASS::ND_INS_VFMSUBSD => Ok(Mnemonic::Vfmsubsd), + ffi::_ND_INS_CLASS::ND_INS_VFMSUBSS => Ok(Mnemonic::Vfmsubss), + ffi::_ND_INS_CLASS::ND_INS_VFMULCPH => Ok(Mnemonic::Vfmulcph), + ffi::_ND_INS_CLASS::ND_INS_VFMULCSH => Ok(Mnemonic::Vfmulcsh), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD132PD => Ok(Mnemonic::Vfnmadd132pd), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD132PH => Ok(Mnemonic::Vfnmadd132ph), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD132PS => Ok(Mnemonic::Vfnmadd132ps), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD132SD => Ok(Mnemonic::Vfnmadd132sd), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD132SH => Ok(Mnemonic::Vfnmadd132sh), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD132SS => Ok(Mnemonic::Vfnmadd132ss), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD213PD => Ok(Mnemonic::Vfnmadd213pd), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD213PH => Ok(Mnemonic::Vfnmadd213ph), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD213PS => Ok(Mnemonic::Vfnmadd213ps), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD213SD => Ok(Mnemonic::Vfnmadd213sd), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD213SH => Ok(Mnemonic::Vfnmadd213sh), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD213SS => Ok(Mnemonic::Vfnmadd213ss), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD231PD => Ok(Mnemonic::Vfnmadd231pd), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD231PH => Ok(Mnemonic::Vfnmadd231ph), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD231PS => Ok(Mnemonic::Vfnmadd231ps), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD231SD => Ok(Mnemonic::Vfnmadd231sd), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD231SH => Ok(Mnemonic::Vfnmadd231sh), + ffi::_ND_INS_CLASS::ND_INS_VFNMADD231SS => Ok(Mnemonic::Vfnmadd231ss), + ffi::_ND_INS_CLASS::ND_INS_VFNMADDPD => Ok(Mnemonic::Vfnmaddpd), + ffi::_ND_INS_CLASS::ND_INS_VFNMADDPS => Ok(Mnemonic::Vfnmaddps), + ffi::_ND_INS_CLASS::ND_INS_VFNMADDSD => Ok(Mnemonic::Vfnmaddsd), + ffi::_ND_INS_CLASS::ND_INS_VFNMADDSS => Ok(Mnemonic::Vfnmaddss), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB132PD => Ok(Mnemonic::Vfnmsub132pd), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB132PH => Ok(Mnemonic::Vfnmsub132ph), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB132PS => Ok(Mnemonic::Vfnmsub132ps), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB132SD => Ok(Mnemonic::Vfnmsub132sd), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB132SH => Ok(Mnemonic::Vfnmsub132sh), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB132SS => Ok(Mnemonic::Vfnmsub132ss), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB213PD => Ok(Mnemonic::Vfnmsub213pd), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB213PH => Ok(Mnemonic::Vfnmsub213ph), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB213PS => Ok(Mnemonic::Vfnmsub213ps), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB213SD => Ok(Mnemonic::Vfnmsub213sd), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB213SH => Ok(Mnemonic::Vfnmsub213sh), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB213SS => Ok(Mnemonic::Vfnmsub213ss), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB231PD => Ok(Mnemonic::Vfnmsub231pd), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB231PH => Ok(Mnemonic::Vfnmsub231ph), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB231PS => Ok(Mnemonic::Vfnmsub231ps), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB231SD => Ok(Mnemonic::Vfnmsub231sd), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB231SH => Ok(Mnemonic::Vfnmsub231sh), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUB231SS => Ok(Mnemonic::Vfnmsub231ss), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUBPD => Ok(Mnemonic::Vfnmsubpd), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUBPS => Ok(Mnemonic::Vfnmsubps), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUBSD => Ok(Mnemonic::Vfnmsubsd), + ffi::_ND_INS_CLASS::ND_INS_VFNMSUBSS => Ok(Mnemonic::Vfnmsubss), + ffi::_ND_INS_CLASS::ND_INS_VFPCLASSPD => Ok(Mnemonic::Vfpclasspd), + ffi::_ND_INS_CLASS::ND_INS_VFPCLASSPH => Ok(Mnemonic::Vfpclassph), + ffi::_ND_INS_CLASS::ND_INS_VFPCLASSPS => Ok(Mnemonic::Vfpclassps), + ffi::_ND_INS_CLASS::ND_INS_VFPCLASSSD => Ok(Mnemonic::Vfpclasssd), + ffi::_ND_INS_CLASS::ND_INS_VFPCLASSSH => Ok(Mnemonic::Vfpclasssh), + ffi::_ND_INS_CLASS::ND_INS_VFPCLASSSS => Ok(Mnemonic::Vfpclassss), + ffi::_ND_INS_CLASS::ND_INS_VFRCZPD => Ok(Mnemonic::Vfrczpd), + ffi::_ND_INS_CLASS::ND_INS_VFRCZPS => Ok(Mnemonic::Vfrczps), + ffi::_ND_INS_CLASS::ND_INS_VFRCZSD => Ok(Mnemonic::Vfrczsd), + ffi::_ND_INS_CLASS::ND_INS_VFRCZSS => Ok(Mnemonic::Vfrczss), + ffi::_ND_INS_CLASS::ND_INS_VGATHERDPD => Ok(Mnemonic::Vgatherdpd), + ffi::_ND_INS_CLASS::ND_INS_VGATHERDPS => Ok(Mnemonic::Vgatherdps), + ffi::_ND_INS_CLASS::ND_INS_VGATHERPF0DPD => Ok(Mnemonic::Vgatherpf0dpd), + ffi::_ND_INS_CLASS::ND_INS_VGATHERPF0DPS => Ok(Mnemonic::Vgatherpf0dps), + ffi::_ND_INS_CLASS::ND_INS_VGATHERPF0QPD => Ok(Mnemonic::Vgatherpf0qpd), + ffi::_ND_INS_CLASS::ND_INS_VGATHERPF0QPS => Ok(Mnemonic::Vgatherpf0qps), + ffi::_ND_INS_CLASS::ND_INS_VGATHERPF1DPD => Ok(Mnemonic::Vgatherpf1dpd), + ffi::_ND_INS_CLASS::ND_INS_VGATHERPF1DPS => Ok(Mnemonic::Vgatherpf1dps), + ffi::_ND_INS_CLASS::ND_INS_VGATHERPF1QPD => Ok(Mnemonic::Vgatherpf1qpd), + ffi::_ND_INS_CLASS::ND_INS_VGATHERPF1QPS => Ok(Mnemonic::Vgatherpf1qps), + ffi::_ND_INS_CLASS::ND_INS_VGATHERQPD => Ok(Mnemonic::Vgatherqpd), + ffi::_ND_INS_CLASS::ND_INS_VGATHERQPS => Ok(Mnemonic::Vgatherqps), + ffi::_ND_INS_CLASS::ND_INS_VGETEXPPD => Ok(Mnemonic::Vgetexppd), + ffi::_ND_INS_CLASS::ND_INS_VGETEXPPH => Ok(Mnemonic::Vgetexpph), + ffi::_ND_INS_CLASS::ND_INS_VGETEXPPS => Ok(Mnemonic::Vgetexpps), + ffi::_ND_INS_CLASS::ND_INS_VGETEXPSD => Ok(Mnemonic::Vgetexpsd), + ffi::_ND_INS_CLASS::ND_INS_VGETEXPSH => Ok(Mnemonic::Vgetexpsh), + ffi::_ND_INS_CLASS::ND_INS_VGETEXPSS => Ok(Mnemonic::Vgetexpss), + ffi::_ND_INS_CLASS::ND_INS_VGETMANTPD => Ok(Mnemonic::Vgetmantpd), + ffi::_ND_INS_CLASS::ND_INS_VGETMANTPH => Ok(Mnemonic::Vgetmantph), + ffi::_ND_INS_CLASS::ND_INS_VGETMANTPS => Ok(Mnemonic::Vgetmantps), + ffi::_ND_INS_CLASS::ND_INS_VGETMANTSD => Ok(Mnemonic::Vgetmantsd), + ffi::_ND_INS_CLASS::ND_INS_VGETMANTSH => Ok(Mnemonic::Vgetmantsh), + ffi::_ND_INS_CLASS::ND_INS_VGETMANTSS => Ok(Mnemonic::Vgetmantss), + ffi::_ND_INS_CLASS::ND_INS_VGF2P8AFFINEINVQB => Ok(Mnemonic::Vgf2p8affineinvqb), + ffi::_ND_INS_CLASS::ND_INS_VGF2P8AFFINEQB => Ok(Mnemonic::Vgf2p8affineqb), + ffi::_ND_INS_CLASS::ND_INS_VGF2P8MULB => Ok(Mnemonic::Vgf2p8mulb), + ffi::_ND_INS_CLASS::ND_INS_VHADDPD => Ok(Mnemonic::Vhaddpd), + ffi::_ND_INS_CLASS::ND_INS_VHADDPS => Ok(Mnemonic::Vhaddps), + ffi::_ND_INS_CLASS::ND_INS_VHSUBPD => Ok(Mnemonic::Vhsubpd), + ffi::_ND_INS_CLASS::ND_INS_VHSUBPS => Ok(Mnemonic::Vhsubps), + ffi::_ND_INS_CLASS::ND_INS_VINSERTF128 => Ok(Mnemonic::Vinsertf128), + ffi::_ND_INS_CLASS::ND_INS_VINSERTF32X4 => Ok(Mnemonic::Vinsertf32x4), + ffi::_ND_INS_CLASS::ND_INS_VINSERTF32X8 => Ok(Mnemonic::Vinsertf32x8), + ffi::_ND_INS_CLASS::ND_INS_VINSERTF64X2 => Ok(Mnemonic::Vinsertf64x2), + ffi::_ND_INS_CLASS::ND_INS_VINSERTF64X4 => Ok(Mnemonic::Vinsertf64x4), + ffi::_ND_INS_CLASS::ND_INS_VINSERTI128 => Ok(Mnemonic::Vinserti128), + ffi::_ND_INS_CLASS::ND_INS_VINSERTI32X4 => Ok(Mnemonic::Vinserti32x4), + ffi::_ND_INS_CLASS::ND_INS_VINSERTI32X8 => Ok(Mnemonic::Vinserti32x8), + ffi::_ND_INS_CLASS::ND_INS_VINSERTI64X2 => Ok(Mnemonic::Vinserti64x2), + ffi::_ND_INS_CLASS::ND_INS_VINSERTI64X4 => Ok(Mnemonic::Vinserti64x4), + ffi::_ND_INS_CLASS::ND_INS_VINSERTPS => Ok(Mnemonic::Vinsertps), + ffi::_ND_INS_CLASS::ND_INS_VLDDQU => Ok(Mnemonic::Vlddqu), + ffi::_ND_INS_CLASS::ND_INS_VLDMXCSR => Ok(Mnemonic::Vldmxcsr), + ffi::_ND_INS_CLASS::ND_INS_VMASKMOVDQU => Ok(Mnemonic::Vmaskmovdqu), + ffi::_ND_INS_CLASS::ND_INS_VMASKMOVPD => Ok(Mnemonic::Vmaskmovpd), + ffi::_ND_INS_CLASS::ND_INS_VMASKMOVPS => Ok(Mnemonic::Vmaskmovps), + ffi::_ND_INS_CLASS::ND_INS_VMAXPD => Ok(Mnemonic::Vmaxpd), + ffi::_ND_INS_CLASS::ND_INS_VMAXPH => Ok(Mnemonic::Vmaxph), + ffi::_ND_INS_CLASS::ND_INS_VMAXPS => Ok(Mnemonic::Vmaxps), + ffi::_ND_INS_CLASS::ND_INS_VMAXSD => Ok(Mnemonic::Vmaxsd), + ffi::_ND_INS_CLASS::ND_INS_VMAXSH => Ok(Mnemonic::Vmaxsh), + ffi::_ND_INS_CLASS::ND_INS_VMAXSS => Ok(Mnemonic::Vmaxss), + ffi::_ND_INS_CLASS::ND_INS_VMCALL => Ok(Mnemonic::Vmcall), + ffi::_ND_INS_CLASS::ND_INS_VMCLEAR => Ok(Mnemonic::Vmclear), + ffi::_ND_INS_CLASS::ND_INS_VMFUNC => Ok(Mnemonic::Vmfunc), + ffi::_ND_INS_CLASS::ND_INS_VMGEXIT => Ok(Mnemonic::Vmgexit), + ffi::_ND_INS_CLASS::ND_INS_VMINPD => Ok(Mnemonic::Vminpd), + ffi::_ND_INS_CLASS::ND_INS_VMINPH => Ok(Mnemonic::Vminph), + ffi::_ND_INS_CLASS::ND_INS_VMINPS => Ok(Mnemonic::Vminps), + ffi::_ND_INS_CLASS::ND_INS_VMINSD => Ok(Mnemonic::Vminsd), + ffi::_ND_INS_CLASS::ND_INS_VMINSH => Ok(Mnemonic::Vminsh), + ffi::_ND_INS_CLASS::ND_INS_VMINSS => Ok(Mnemonic::Vminss), + ffi::_ND_INS_CLASS::ND_INS_VMLAUNCH => Ok(Mnemonic::Vmlaunch), + ffi::_ND_INS_CLASS::ND_INS_VMLOAD => Ok(Mnemonic::Vmload), + ffi::_ND_INS_CLASS::ND_INS_VMMCALL => Ok(Mnemonic::Vmmcall), + ffi::_ND_INS_CLASS::ND_INS_VMOVAPD => Ok(Mnemonic::Vmovapd), + ffi::_ND_INS_CLASS::ND_INS_VMOVAPS => Ok(Mnemonic::Vmovaps), + ffi::_ND_INS_CLASS::ND_INS_VMOVD => Ok(Mnemonic::Vmovd), + ffi::_ND_INS_CLASS::ND_INS_VMOVDDUP => Ok(Mnemonic::Vmovddup), + ffi::_ND_INS_CLASS::ND_INS_VMOVDQA => Ok(Mnemonic::Vmovdqa), + ffi::_ND_INS_CLASS::ND_INS_VMOVDQA32 => Ok(Mnemonic::Vmovdqa32), + ffi::_ND_INS_CLASS::ND_INS_VMOVDQA64 => Ok(Mnemonic::Vmovdqa64), + ffi::_ND_INS_CLASS::ND_INS_VMOVDQU => Ok(Mnemonic::Vmovdqu), + ffi::_ND_INS_CLASS::ND_INS_VMOVDQU16 => Ok(Mnemonic::Vmovdqu16), + ffi::_ND_INS_CLASS::ND_INS_VMOVDQU32 => Ok(Mnemonic::Vmovdqu32), + ffi::_ND_INS_CLASS::ND_INS_VMOVDQU64 => Ok(Mnemonic::Vmovdqu64), + ffi::_ND_INS_CLASS::ND_INS_VMOVDQU8 => Ok(Mnemonic::Vmovdqu8), + ffi::_ND_INS_CLASS::ND_INS_VMOVHLPS => Ok(Mnemonic::Vmovhlps), + ffi::_ND_INS_CLASS::ND_INS_VMOVHPD => Ok(Mnemonic::Vmovhpd), + ffi::_ND_INS_CLASS::ND_INS_VMOVHPS => Ok(Mnemonic::Vmovhps), + ffi::_ND_INS_CLASS::ND_INS_VMOVLHPS => Ok(Mnemonic::Vmovlhps), + ffi::_ND_INS_CLASS::ND_INS_VMOVLPD => Ok(Mnemonic::Vmovlpd), + ffi::_ND_INS_CLASS::ND_INS_VMOVLPS => Ok(Mnemonic::Vmovlps), + ffi::_ND_INS_CLASS::ND_INS_VMOVMSKPD => Ok(Mnemonic::Vmovmskpd), + ffi::_ND_INS_CLASS::ND_INS_VMOVMSKPS => Ok(Mnemonic::Vmovmskps), + ffi::_ND_INS_CLASS::ND_INS_VMOVNTDQ => Ok(Mnemonic::Vmovntdq), + ffi::_ND_INS_CLASS::ND_INS_VMOVNTDQA => Ok(Mnemonic::Vmovntdqa), + ffi::_ND_INS_CLASS::ND_INS_VMOVNTPD => Ok(Mnemonic::Vmovntpd), + ffi::_ND_INS_CLASS::ND_INS_VMOVNTPS => Ok(Mnemonic::Vmovntps), + ffi::_ND_INS_CLASS::ND_INS_VMOVQ => Ok(Mnemonic::Vmovq), + ffi::_ND_INS_CLASS::ND_INS_VMOVSD => Ok(Mnemonic::Vmovsd), + ffi::_ND_INS_CLASS::ND_INS_VMOVSH => Ok(Mnemonic::Vmovsh), + ffi::_ND_INS_CLASS::ND_INS_VMOVSHDUP => Ok(Mnemonic::Vmovshdup), + ffi::_ND_INS_CLASS::ND_INS_VMOVSLDUP => Ok(Mnemonic::Vmovsldup), + ffi::_ND_INS_CLASS::ND_INS_VMOVSS => Ok(Mnemonic::Vmovss), + ffi::_ND_INS_CLASS::ND_INS_VMOVUPD => Ok(Mnemonic::Vmovupd), + ffi::_ND_INS_CLASS::ND_INS_VMOVUPS => Ok(Mnemonic::Vmovups), + ffi::_ND_INS_CLASS::ND_INS_VMOVW => Ok(Mnemonic::Vmovw), + ffi::_ND_INS_CLASS::ND_INS_VMPSADBW => Ok(Mnemonic::Vmpsadbw), + ffi::_ND_INS_CLASS::ND_INS_VMPTRLD => Ok(Mnemonic::Vmptrld), + ffi::_ND_INS_CLASS::ND_INS_VMPTRST => Ok(Mnemonic::Vmptrst), + ffi::_ND_INS_CLASS::ND_INS_VMREAD => Ok(Mnemonic::Vmread), + ffi::_ND_INS_CLASS::ND_INS_VMRESUME => Ok(Mnemonic::Vmresume), + ffi::_ND_INS_CLASS::ND_INS_VMRUN => Ok(Mnemonic::Vmrun), + ffi::_ND_INS_CLASS::ND_INS_VMSAVE => Ok(Mnemonic::Vmsave), + ffi::_ND_INS_CLASS::ND_INS_VMULPD => Ok(Mnemonic::Vmulpd), + ffi::_ND_INS_CLASS::ND_INS_VMULPH => Ok(Mnemonic::Vmulph), + ffi::_ND_INS_CLASS::ND_INS_VMULPS => Ok(Mnemonic::Vmulps), + ffi::_ND_INS_CLASS::ND_INS_VMULSD => Ok(Mnemonic::Vmulsd), + ffi::_ND_INS_CLASS::ND_INS_VMULSH => Ok(Mnemonic::Vmulsh), + ffi::_ND_INS_CLASS::ND_INS_VMULSS => Ok(Mnemonic::Vmulss), + ffi::_ND_INS_CLASS::ND_INS_VMWRITE => Ok(Mnemonic::Vmwrite), + ffi::_ND_INS_CLASS::ND_INS_VMXOFF => Ok(Mnemonic::Vmxoff), + ffi::_ND_INS_CLASS::ND_INS_VMXON => Ok(Mnemonic::Vmxon), + ffi::_ND_INS_CLASS::ND_INS_VORPD => Ok(Mnemonic::Vorpd), + ffi::_ND_INS_CLASS::ND_INS_VORPS => Ok(Mnemonic::Vorps), + ffi::_ND_INS_CLASS::ND_INS_VP2INTERSECTD => Ok(Mnemonic::Vp2intersectd), + ffi::_ND_INS_CLASS::ND_INS_VP2INTERSECTQ => Ok(Mnemonic::Vp2intersectq), + ffi::_ND_INS_CLASS::ND_INS_VP4DPWSSD => Ok(Mnemonic::Vp4dpwssd), + ffi::_ND_INS_CLASS::ND_INS_VP4DPWSSDS => Ok(Mnemonic::Vp4dpwssds), + ffi::_ND_INS_CLASS::ND_INS_VPABSB => Ok(Mnemonic::Vpabsb), + ffi::_ND_INS_CLASS::ND_INS_VPABSD => Ok(Mnemonic::Vpabsd), + ffi::_ND_INS_CLASS::ND_INS_VPABSQ => Ok(Mnemonic::Vpabsq), + ffi::_ND_INS_CLASS::ND_INS_VPABSW => Ok(Mnemonic::Vpabsw), + ffi::_ND_INS_CLASS::ND_INS_VPACKSSDW => Ok(Mnemonic::Vpackssdw), + ffi::_ND_INS_CLASS::ND_INS_VPACKSSWB => Ok(Mnemonic::Vpacksswb), + ffi::_ND_INS_CLASS::ND_INS_VPACKUSDW => Ok(Mnemonic::Vpackusdw), + ffi::_ND_INS_CLASS::ND_INS_VPACKUSWB => Ok(Mnemonic::Vpackuswb), + ffi::_ND_INS_CLASS::ND_INS_VPADDB => Ok(Mnemonic::Vpaddb), + ffi::_ND_INS_CLASS::ND_INS_VPADDD => Ok(Mnemonic::Vpaddd), + ffi::_ND_INS_CLASS::ND_INS_VPADDQ => Ok(Mnemonic::Vpaddq), + ffi::_ND_INS_CLASS::ND_INS_VPADDSB => Ok(Mnemonic::Vpaddsb), + ffi::_ND_INS_CLASS::ND_INS_VPADDSW => Ok(Mnemonic::Vpaddsw), + ffi::_ND_INS_CLASS::ND_INS_VPADDUSB => Ok(Mnemonic::Vpaddusb), + ffi::_ND_INS_CLASS::ND_INS_VPADDUSW => Ok(Mnemonic::Vpaddusw), + ffi::_ND_INS_CLASS::ND_INS_VPADDW => Ok(Mnemonic::Vpaddw), + ffi::_ND_INS_CLASS::ND_INS_VPALIGNR => Ok(Mnemonic::Vpalignr), + ffi::_ND_INS_CLASS::ND_INS_VPAND => Ok(Mnemonic::Vpand), + ffi::_ND_INS_CLASS::ND_INS_VPANDD => Ok(Mnemonic::Vpandd), + ffi::_ND_INS_CLASS::ND_INS_VPANDN => Ok(Mnemonic::Vpandn), + ffi::_ND_INS_CLASS::ND_INS_VPANDND => Ok(Mnemonic::Vpandnd), + ffi::_ND_INS_CLASS::ND_INS_VPANDNQ => Ok(Mnemonic::Vpandnq), + ffi::_ND_INS_CLASS::ND_INS_VPANDQ => Ok(Mnemonic::Vpandq), + ffi::_ND_INS_CLASS::ND_INS_VPAVGB => Ok(Mnemonic::Vpavgb), + ffi::_ND_INS_CLASS::ND_INS_VPAVGW => Ok(Mnemonic::Vpavgw), + ffi::_ND_INS_CLASS::ND_INS_VPBLENDD => Ok(Mnemonic::Vpblendd), + ffi::_ND_INS_CLASS::ND_INS_VPBLENDMB => Ok(Mnemonic::Vpblendmb), + ffi::_ND_INS_CLASS::ND_INS_VPBLENDMD => Ok(Mnemonic::Vpblendmd), + ffi::_ND_INS_CLASS::ND_INS_VPBLENDMQ => Ok(Mnemonic::Vpblendmq), + ffi::_ND_INS_CLASS::ND_INS_VPBLENDMW => Ok(Mnemonic::Vpblendmw), + ffi::_ND_INS_CLASS::ND_INS_VPBLENDVB => Ok(Mnemonic::Vpblendvb), + ffi::_ND_INS_CLASS::ND_INS_VPBLENDW => Ok(Mnemonic::Vpblendw), + ffi::_ND_INS_CLASS::ND_INS_VPBROADCASTB => Ok(Mnemonic::Vpbroadcastb), + ffi::_ND_INS_CLASS::ND_INS_VPBROADCASTD => Ok(Mnemonic::Vpbroadcastd), + ffi::_ND_INS_CLASS::ND_INS_VPBROADCASTMB2Q => Ok(Mnemonic::Vpbroadcastmb2q), + ffi::_ND_INS_CLASS::ND_INS_VPBROADCASTMW2D => Ok(Mnemonic::Vpbroadcastmw2d), + ffi::_ND_INS_CLASS::ND_INS_VPBROADCASTQ => Ok(Mnemonic::Vpbroadcastq), + ffi::_ND_INS_CLASS::ND_INS_VPBROADCASTW => Ok(Mnemonic::Vpbroadcastw), + ffi::_ND_INS_CLASS::ND_INS_VPCLMULQDQ => Ok(Mnemonic::Vpclmulqdq), + ffi::_ND_INS_CLASS::ND_INS_VPCMOV => Ok(Mnemonic::Vpcmov), + ffi::_ND_INS_CLASS::ND_INS_VPCMPB => Ok(Mnemonic::Vpcmpb), + ffi::_ND_INS_CLASS::ND_INS_VPCMPD => Ok(Mnemonic::Vpcmpd), + ffi::_ND_INS_CLASS::ND_INS_VPCMPEQB => Ok(Mnemonic::Vpcmpeqb), + ffi::_ND_INS_CLASS::ND_INS_VPCMPEQD => Ok(Mnemonic::Vpcmpeqd), + ffi::_ND_INS_CLASS::ND_INS_VPCMPEQQ => Ok(Mnemonic::Vpcmpeqq), + ffi::_ND_INS_CLASS::ND_INS_VPCMPEQW => Ok(Mnemonic::Vpcmpeqw), + ffi::_ND_INS_CLASS::ND_INS_VPCMPESTRI => Ok(Mnemonic::Vpcmpestri), + ffi::_ND_INS_CLASS::ND_INS_VPCMPESTRM => Ok(Mnemonic::Vpcmpestrm), + ffi::_ND_INS_CLASS::ND_INS_VPCMPGTB => Ok(Mnemonic::Vpcmpgtb), + ffi::_ND_INS_CLASS::ND_INS_VPCMPGTD => Ok(Mnemonic::Vpcmpgtd), + ffi::_ND_INS_CLASS::ND_INS_VPCMPGTQ => Ok(Mnemonic::Vpcmpgtq), + ffi::_ND_INS_CLASS::ND_INS_VPCMPGTW => Ok(Mnemonic::Vpcmpgtw), + ffi::_ND_INS_CLASS::ND_INS_VPCMPISTRI => Ok(Mnemonic::Vpcmpistri), + ffi::_ND_INS_CLASS::ND_INS_VPCMPISTRM => Ok(Mnemonic::Vpcmpistrm), + ffi::_ND_INS_CLASS::ND_INS_VPCMPQ => Ok(Mnemonic::Vpcmpq), + ffi::_ND_INS_CLASS::ND_INS_VPCMPUB => Ok(Mnemonic::Vpcmpub), + ffi::_ND_INS_CLASS::ND_INS_VPCMPUD => Ok(Mnemonic::Vpcmpud), + ffi::_ND_INS_CLASS::ND_INS_VPCMPUQ => Ok(Mnemonic::Vpcmpuq), + ffi::_ND_INS_CLASS::ND_INS_VPCMPUW => Ok(Mnemonic::Vpcmpuw), + ffi::_ND_INS_CLASS::ND_INS_VPCMPW => Ok(Mnemonic::Vpcmpw), + ffi::_ND_INS_CLASS::ND_INS_VPCOMB => Ok(Mnemonic::Vpcomb), + ffi::_ND_INS_CLASS::ND_INS_VPCOMD => Ok(Mnemonic::Vpcomd), + ffi::_ND_INS_CLASS::ND_INS_VPCOMPRESSB => Ok(Mnemonic::Vpcompressb), + ffi::_ND_INS_CLASS::ND_INS_VPCOMPRESSD => Ok(Mnemonic::Vpcompressd), + ffi::_ND_INS_CLASS::ND_INS_VPCOMPRESSQ => Ok(Mnemonic::Vpcompressq), + ffi::_ND_INS_CLASS::ND_INS_VPCOMPRESSW => Ok(Mnemonic::Vpcompressw), + ffi::_ND_INS_CLASS::ND_INS_VPCOMQ => Ok(Mnemonic::Vpcomq), + ffi::_ND_INS_CLASS::ND_INS_VPCOMUB => Ok(Mnemonic::Vpcomub), + ffi::_ND_INS_CLASS::ND_INS_VPCOMUD => Ok(Mnemonic::Vpcomud), + ffi::_ND_INS_CLASS::ND_INS_VPCOMUQ => Ok(Mnemonic::Vpcomuq), + ffi::_ND_INS_CLASS::ND_INS_VPCOMUW => Ok(Mnemonic::Vpcomuw), + ffi::_ND_INS_CLASS::ND_INS_VPCOMW => Ok(Mnemonic::Vpcomw), + ffi::_ND_INS_CLASS::ND_INS_VPCONFLICTD => Ok(Mnemonic::Vpconflictd), + ffi::_ND_INS_CLASS::ND_INS_VPCONFLICTQ => Ok(Mnemonic::Vpconflictq), + ffi::_ND_INS_CLASS::ND_INS_VPDPBUSD => Ok(Mnemonic::Vpdpbusd), + ffi::_ND_INS_CLASS::ND_INS_VPDPBUSDS => Ok(Mnemonic::Vpdpbusds), + ffi::_ND_INS_CLASS::ND_INS_VPDPWSSD => Ok(Mnemonic::Vpdpwssd), + ffi::_ND_INS_CLASS::ND_INS_VPDPWSSDS => Ok(Mnemonic::Vpdpwssds), + ffi::_ND_INS_CLASS::ND_INS_VPERM2F128 => Ok(Mnemonic::Vperm2f128), + ffi::_ND_INS_CLASS::ND_INS_VPERM2I128 => Ok(Mnemonic::Vperm2i128), + ffi::_ND_INS_CLASS::ND_INS_VPERMB => Ok(Mnemonic::Vpermb), + ffi::_ND_INS_CLASS::ND_INS_VPERMD => Ok(Mnemonic::Vpermd), + ffi::_ND_INS_CLASS::ND_INS_VPERMI2B => Ok(Mnemonic::Vpermi2b), + ffi::_ND_INS_CLASS::ND_INS_VPERMI2D => Ok(Mnemonic::Vpermi2d), + ffi::_ND_INS_CLASS::ND_INS_VPERMI2PD => Ok(Mnemonic::Vpermi2pd), + ffi::_ND_INS_CLASS::ND_INS_VPERMI2PS => Ok(Mnemonic::Vpermi2ps), + ffi::_ND_INS_CLASS::ND_INS_VPERMI2Q => Ok(Mnemonic::Vpermi2q), + ffi::_ND_INS_CLASS::ND_INS_VPERMI2W => Ok(Mnemonic::Vpermi2w), + ffi::_ND_INS_CLASS::ND_INS_VPERMIL2PD => Ok(Mnemonic::Vpermil2pd), + ffi::_ND_INS_CLASS::ND_INS_VPERMIL2PS => Ok(Mnemonic::Vpermil2ps), + ffi::_ND_INS_CLASS::ND_INS_VPERMILPD => Ok(Mnemonic::Vpermilpd), + ffi::_ND_INS_CLASS::ND_INS_VPERMILPS => Ok(Mnemonic::Vpermilps), + ffi::_ND_INS_CLASS::ND_INS_VPERMPD => Ok(Mnemonic::Vpermpd), + ffi::_ND_INS_CLASS::ND_INS_VPERMPS => Ok(Mnemonic::Vpermps), + ffi::_ND_INS_CLASS::ND_INS_VPERMQ => Ok(Mnemonic::Vpermq), + ffi::_ND_INS_CLASS::ND_INS_VPERMT2B => Ok(Mnemonic::Vpermt2b), + ffi::_ND_INS_CLASS::ND_INS_VPERMT2D => Ok(Mnemonic::Vpermt2d), + ffi::_ND_INS_CLASS::ND_INS_VPERMT2PD => Ok(Mnemonic::Vpermt2pd), + ffi::_ND_INS_CLASS::ND_INS_VPERMT2PS => Ok(Mnemonic::Vpermt2ps), + ffi::_ND_INS_CLASS::ND_INS_VPERMT2Q => Ok(Mnemonic::Vpermt2q), + ffi::_ND_INS_CLASS::ND_INS_VPERMT2W => Ok(Mnemonic::Vpermt2w), + ffi::_ND_INS_CLASS::ND_INS_VPERMW => Ok(Mnemonic::Vpermw), + ffi::_ND_INS_CLASS::ND_INS_VPEXPANDB => Ok(Mnemonic::Vpexpandb), + ffi::_ND_INS_CLASS::ND_INS_VPEXPANDD => Ok(Mnemonic::Vpexpandd), + ffi::_ND_INS_CLASS::ND_INS_VPEXPANDQ => Ok(Mnemonic::Vpexpandq), + ffi::_ND_INS_CLASS::ND_INS_VPEXPANDW => Ok(Mnemonic::Vpexpandw), + ffi::_ND_INS_CLASS::ND_INS_VPEXTRB => Ok(Mnemonic::Vpextrb), + ffi::_ND_INS_CLASS::ND_INS_VPEXTRD => Ok(Mnemonic::Vpextrd), + ffi::_ND_INS_CLASS::ND_INS_VPEXTRQ => Ok(Mnemonic::Vpextrq), + ffi::_ND_INS_CLASS::ND_INS_VPEXTRW => Ok(Mnemonic::Vpextrw), + ffi::_ND_INS_CLASS::ND_INS_VPGATHERDD => Ok(Mnemonic::Vpgatherdd), + ffi::_ND_INS_CLASS::ND_INS_VPGATHERDQ => Ok(Mnemonic::Vpgatherdq), + ffi::_ND_INS_CLASS::ND_INS_VPGATHERQD => Ok(Mnemonic::Vpgatherqd), + ffi::_ND_INS_CLASS::ND_INS_VPGATHERQQ => Ok(Mnemonic::Vpgatherqq), + ffi::_ND_INS_CLASS::ND_INS_VPHADDBD => Ok(Mnemonic::Vphaddbd), + ffi::_ND_INS_CLASS::ND_INS_VPHADDBQ => Ok(Mnemonic::Vphaddbq), + ffi::_ND_INS_CLASS::ND_INS_VPHADDBW => Ok(Mnemonic::Vphaddbw), + ffi::_ND_INS_CLASS::ND_INS_VPHADDD => Ok(Mnemonic::Vphaddd), + ffi::_ND_INS_CLASS::ND_INS_VPHADDDQ => Ok(Mnemonic::Vphadddq), + ffi::_ND_INS_CLASS::ND_INS_VPHADDSW => Ok(Mnemonic::Vphaddsw), + ffi::_ND_INS_CLASS::ND_INS_VPHADDUBD => Ok(Mnemonic::Vphaddubd), + ffi::_ND_INS_CLASS::ND_INS_VPHADDUBQ => Ok(Mnemonic::Vphaddubq), + ffi::_ND_INS_CLASS::ND_INS_VPHADDUBW => Ok(Mnemonic::Vphaddubw), + ffi::_ND_INS_CLASS::ND_INS_VPHADDUDQ => Ok(Mnemonic::Vphaddudq), + ffi::_ND_INS_CLASS::ND_INS_VPHADDUWD => Ok(Mnemonic::Vphadduwd), + ffi::_ND_INS_CLASS::ND_INS_VPHADDUWQ => Ok(Mnemonic::Vphadduwq), + ffi::_ND_INS_CLASS::ND_INS_VPHADDW => Ok(Mnemonic::Vphaddw), + ffi::_ND_INS_CLASS::ND_INS_VPHADDWD => Ok(Mnemonic::Vphaddwd), + ffi::_ND_INS_CLASS::ND_INS_VPHADDWQ => Ok(Mnemonic::Vphaddwq), + ffi::_ND_INS_CLASS::ND_INS_VPHMINPOSUW => Ok(Mnemonic::Vphminposuw), + ffi::_ND_INS_CLASS::ND_INS_VPHSUBBW => Ok(Mnemonic::Vphsubbw), + ffi::_ND_INS_CLASS::ND_INS_VPHSUBD => Ok(Mnemonic::Vphsubd), + ffi::_ND_INS_CLASS::ND_INS_VPHSUBDQ => Ok(Mnemonic::Vphsubdq), + ffi::_ND_INS_CLASS::ND_INS_VPHSUBSW => Ok(Mnemonic::Vphsubsw), + ffi::_ND_INS_CLASS::ND_INS_VPHSUBW => Ok(Mnemonic::Vphsubw), + ffi::_ND_INS_CLASS::ND_INS_VPHSUBWD => Ok(Mnemonic::Vphsubwd), + ffi::_ND_INS_CLASS::ND_INS_VPINSRB => Ok(Mnemonic::Vpinsrb), + ffi::_ND_INS_CLASS::ND_INS_VPINSRD => Ok(Mnemonic::Vpinsrd), + ffi::_ND_INS_CLASS::ND_INS_VPINSRQ => Ok(Mnemonic::Vpinsrq), + ffi::_ND_INS_CLASS::ND_INS_VPINSRW => Ok(Mnemonic::Vpinsrw), + ffi::_ND_INS_CLASS::ND_INS_VPLZCNTD => Ok(Mnemonic::Vplzcntd), + ffi::_ND_INS_CLASS::ND_INS_VPLZCNTQ => Ok(Mnemonic::Vplzcntq), + ffi::_ND_INS_CLASS::ND_INS_VPMACSDD => Ok(Mnemonic::Vpmacsdd), + ffi::_ND_INS_CLASS::ND_INS_VPMACSDQH => Ok(Mnemonic::Vpmacsdqh), + ffi::_ND_INS_CLASS::ND_INS_VPMACSDQL => Ok(Mnemonic::Vpmacsdql), + ffi::_ND_INS_CLASS::ND_INS_VPMACSSDD => Ok(Mnemonic::Vpmacssdd), + ffi::_ND_INS_CLASS::ND_INS_VPMACSSDQH => Ok(Mnemonic::Vpmacssdqh), + ffi::_ND_INS_CLASS::ND_INS_VPMACSSDQL => Ok(Mnemonic::Vpmacssdql), + ffi::_ND_INS_CLASS::ND_INS_VPMACSSWD => Ok(Mnemonic::Vpmacsswd), + ffi::_ND_INS_CLASS::ND_INS_VPMACSSWW => Ok(Mnemonic::Vpmacssww), + ffi::_ND_INS_CLASS::ND_INS_VPMACSWD => Ok(Mnemonic::Vpmacswd), + ffi::_ND_INS_CLASS::ND_INS_VPMACSWW => Ok(Mnemonic::Vpmacsww), + ffi::_ND_INS_CLASS::ND_INS_VPMADCSSWD => Ok(Mnemonic::Vpmadcsswd), + ffi::_ND_INS_CLASS::ND_INS_VPMADCSWD => Ok(Mnemonic::Vpmadcswd), + ffi::_ND_INS_CLASS::ND_INS_VPMADD52HUQ => Ok(Mnemonic::Vpmadd52huq), + ffi::_ND_INS_CLASS::ND_INS_VPMADD52LUQ => Ok(Mnemonic::Vpmadd52luq), + ffi::_ND_INS_CLASS::ND_INS_VPMADDUBSW => Ok(Mnemonic::Vpmaddubsw), + ffi::_ND_INS_CLASS::ND_INS_VPMADDWD => Ok(Mnemonic::Vpmaddwd), + ffi::_ND_INS_CLASS::ND_INS_VPMASKMOVD => Ok(Mnemonic::Vpmaskmovd), + ffi::_ND_INS_CLASS::ND_INS_VPMASKMOVQ => Ok(Mnemonic::Vpmaskmovq), + ffi::_ND_INS_CLASS::ND_INS_VPMAXSB => Ok(Mnemonic::Vpmaxsb), + ffi::_ND_INS_CLASS::ND_INS_VPMAXSD => Ok(Mnemonic::Vpmaxsd), + ffi::_ND_INS_CLASS::ND_INS_VPMAXSQ => Ok(Mnemonic::Vpmaxsq), + ffi::_ND_INS_CLASS::ND_INS_VPMAXSW => Ok(Mnemonic::Vpmaxsw), + ffi::_ND_INS_CLASS::ND_INS_VPMAXUB => Ok(Mnemonic::Vpmaxub), + ffi::_ND_INS_CLASS::ND_INS_VPMAXUD => Ok(Mnemonic::Vpmaxud), + ffi::_ND_INS_CLASS::ND_INS_VPMAXUQ => Ok(Mnemonic::Vpmaxuq), + ffi::_ND_INS_CLASS::ND_INS_VPMAXUW => Ok(Mnemonic::Vpmaxuw), + ffi::_ND_INS_CLASS::ND_INS_VPMINSB => Ok(Mnemonic::Vpminsb), + ffi::_ND_INS_CLASS::ND_INS_VPMINSD => Ok(Mnemonic::Vpminsd), + ffi::_ND_INS_CLASS::ND_INS_VPMINSQ => Ok(Mnemonic::Vpminsq), + ffi::_ND_INS_CLASS::ND_INS_VPMINSW => Ok(Mnemonic::Vpminsw), + ffi::_ND_INS_CLASS::ND_INS_VPMINUB => Ok(Mnemonic::Vpminub), + ffi::_ND_INS_CLASS::ND_INS_VPMINUD => Ok(Mnemonic::Vpminud), + ffi::_ND_INS_CLASS::ND_INS_VPMINUQ => Ok(Mnemonic::Vpminuq), + ffi::_ND_INS_CLASS::ND_INS_VPMINUW => Ok(Mnemonic::Vpminuw), + ffi::_ND_INS_CLASS::ND_INS_VPMOVB2M => Ok(Mnemonic::Vpmovb2m), + ffi::_ND_INS_CLASS::ND_INS_VPMOVD2M => Ok(Mnemonic::Vpmovd2m), + ffi::_ND_INS_CLASS::ND_INS_VPMOVDB => Ok(Mnemonic::Vpmovdb), + ffi::_ND_INS_CLASS::ND_INS_VPMOVDW => Ok(Mnemonic::Vpmovdw), + ffi::_ND_INS_CLASS::ND_INS_VPMOVM2B => Ok(Mnemonic::Vpmovm2b), + ffi::_ND_INS_CLASS::ND_INS_VPMOVM2D => Ok(Mnemonic::Vpmovm2d), + ffi::_ND_INS_CLASS::ND_INS_VPMOVM2Q => Ok(Mnemonic::Vpmovm2q), + ffi::_ND_INS_CLASS::ND_INS_VPMOVM2W => Ok(Mnemonic::Vpmovm2w), + ffi::_ND_INS_CLASS::ND_INS_VPMOVMSKB => Ok(Mnemonic::Vpmovmskb), + ffi::_ND_INS_CLASS::ND_INS_VPMOVQ2M => Ok(Mnemonic::Vpmovq2m), + ffi::_ND_INS_CLASS::ND_INS_VPMOVQB => Ok(Mnemonic::Vpmovqb), + ffi::_ND_INS_CLASS::ND_INS_VPMOVQD => Ok(Mnemonic::Vpmovqd), + ffi::_ND_INS_CLASS::ND_INS_VPMOVQW => Ok(Mnemonic::Vpmovqw), + ffi::_ND_INS_CLASS::ND_INS_VPMOVSDB => Ok(Mnemonic::Vpmovsdb), + ffi::_ND_INS_CLASS::ND_INS_VPMOVSDW => Ok(Mnemonic::Vpmovsdw), + ffi::_ND_INS_CLASS::ND_INS_VPMOVSQB => Ok(Mnemonic::Vpmovsqb), + ffi::_ND_INS_CLASS::ND_INS_VPMOVSQD => Ok(Mnemonic::Vpmovsqd), + ffi::_ND_INS_CLASS::ND_INS_VPMOVSQW => Ok(Mnemonic::Vpmovsqw), + ffi::_ND_INS_CLASS::ND_INS_VPMOVSWB => Ok(Mnemonic::Vpmovswb), + ffi::_ND_INS_CLASS::ND_INS_VPMOVSXBD => Ok(Mnemonic::Vpmovsxbd), + ffi::_ND_INS_CLASS::ND_INS_VPMOVSXBQ => Ok(Mnemonic::Vpmovsxbq), + ffi::_ND_INS_CLASS::ND_INS_VPMOVSXBW => Ok(Mnemonic::Vpmovsxbw), + ffi::_ND_INS_CLASS::ND_INS_VPMOVSXDQ => Ok(Mnemonic::Vpmovsxdq), + ffi::_ND_INS_CLASS::ND_INS_VPMOVSXWD => Ok(Mnemonic::Vpmovsxwd), + ffi::_ND_INS_CLASS::ND_INS_VPMOVSXWQ => Ok(Mnemonic::Vpmovsxwq), + ffi::_ND_INS_CLASS::ND_INS_VPMOVUSDB => Ok(Mnemonic::Vpmovusdb), + ffi::_ND_INS_CLASS::ND_INS_VPMOVUSDW => Ok(Mnemonic::Vpmovusdw), + ffi::_ND_INS_CLASS::ND_INS_VPMOVUSQB => Ok(Mnemonic::Vpmovusqb), + ffi::_ND_INS_CLASS::ND_INS_VPMOVUSQD => Ok(Mnemonic::Vpmovusqd), + ffi::_ND_INS_CLASS::ND_INS_VPMOVUSQW => Ok(Mnemonic::Vpmovusqw), + ffi::_ND_INS_CLASS::ND_INS_VPMOVUSWB => Ok(Mnemonic::Vpmovuswb), + ffi::_ND_INS_CLASS::ND_INS_VPMOVW2M => Ok(Mnemonic::Vpmovw2m), + ffi::_ND_INS_CLASS::ND_INS_VPMOVWB => Ok(Mnemonic::Vpmovwb), + ffi::_ND_INS_CLASS::ND_INS_VPMOVZXBD => Ok(Mnemonic::Vpmovzxbd), + ffi::_ND_INS_CLASS::ND_INS_VPMOVZXBQ => Ok(Mnemonic::Vpmovzxbq), + ffi::_ND_INS_CLASS::ND_INS_VPMOVZXBW => Ok(Mnemonic::Vpmovzxbw), + ffi::_ND_INS_CLASS::ND_INS_VPMOVZXDQ => Ok(Mnemonic::Vpmovzxdq), + ffi::_ND_INS_CLASS::ND_INS_VPMOVZXWD => Ok(Mnemonic::Vpmovzxwd), + ffi::_ND_INS_CLASS::ND_INS_VPMOVZXWQ => Ok(Mnemonic::Vpmovzxwq), + ffi::_ND_INS_CLASS::ND_INS_VPMULDQ => Ok(Mnemonic::Vpmuldq), + ffi::_ND_INS_CLASS::ND_INS_VPMULHRSW => Ok(Mnemonic::Vpmulhrsw), + ffi::_ND_INS_CLASS::ND_INS_VPMULHUW => Ok(Mnemonic::Vpmulhuw), + ffi::_ND_INS_CLASS::ND_INS_VPMULHW => Ok(Mnemonic::Vpmulhw), + ffi::_ND_INS_CLASS::ND_INS_VPMULLD => Ok(Mnemonic::Vpmulld), + ffi::_ND_INS_CLASS::ND_INS_VPMULLQ => Ok(Mnemonic::Vpmullq), + ffi::_ND_INS_CLASS::ND_INS_VPMULLW => Ok(Mnemonic::Vpmullw), + ffi::_ND_INS_CLASS::ND_INS_VPMULTISHIFTQB => Ok(Mnemonic::Vpmultishiftqb), + ffi::_ND_INS_CLASS::ND_INS_VPMULUDQ => Ok(Mnemonic::Vpmuludq), + ffi::_ND_INS_CLASS::ND_INS_VPOPCNTB => Ok(Mnemonic::Vpopcntb), + ffi::_ND_INS_CLASS::ND_INS_VPOPCNTD => Ok(Mnemonic::Vpopcntd), + ffi::_ND_INS_CLASS::ND_INS_VPOPCNTQ => Ok(Mnemonic::Vpopcntq), + ffi::_ND_INS_CLASS::ND_INS_VPOPCNTW => Ok(Mnemonic::Vpopcntw), + ffi::_ND_INS_CLASS::ND_INS_VPOR => Ok(Mnemonic::Vpor), + ffi::_ND_INS_CLASS::ND_INS_VPORD => Ok(Mnemonic::Vpord), + ffi::_ND_INS_CLASS::ND_INS_VPORQ => Ok(Mnemonic::Vporq), + ffi::_ND_INS_CLASS::ND_INS_VPPERM => Ok(Mnemonic::Vpperm), + ffi::_ND_INS_CLASS::ND_INS_VPROLD => Ok(Mnemonic::Vprold), + ffi::_ND_INS_CLASS::ND_INS_VPROLQ => Ok(Mnemonic::Vprolq), + ffi::_ND_INS_CLASS::ND_INS_VPROLVD => Ok(Mnemonic::Vprolvd), + ffi::_ND_INS_CLASS::ND_INS_VPROLVQ => Ok(Mnemonic::Vprolvq), + ffi::_ND_INS_CLASS::ND_INS_VPRORD => Ok(Mnemonic::Vprord), + ffi::_ND_INS_CLASS::ND_INS_VPRORQ => Ok(Mnemonic::Vprorq), + ffi::_ND_INS_CLASS::ND_INS_VPRORVD => Ok(Mnemonic::Vprorvd), + ffi::_ND_INS_CLASS::ND_INS_VPRORVQ => Ok(Mnemonic::Vprorvq), + ffi::_ND_INS_CLASS::ND_INS_VPROTB => Ok(Mnemonic::Vprotb), + ffi::_ND_INS_CLASS::ND_INS_VPROTD => Ok(Mnemonic::Vprotd), + ffi::_ND_INS_CLASS::ND_INS_VPROTQ => Ok(Mnemonic::Vprotq), + ffi::_ND_INS_CLASS::ND_INS_VPROTW => Ok(Mnemonic::Vprotw), + ffi::_ND_INS_CLASS::ND_INS_VPSADBW => Ok(Mnemonic::Vpsadbw), + ffi::_ND_INS_CLASS::ND_INS_VPSCATTERDD => Ok(Mnemonic::Vpscatterdd), + ffi::_ND_INS_CLASS::ND_INS_VPSCATTERDQ => Ok(Mnemonic::Vpscatterdq), + ffi::_ND_INS_CLASS::ND_INS_VPSCATTERQD => Ok(Mnemonic::Vpscatterqd), + ffi::_ND_INS_CLASS::ND_INS_VPSCATTERQQ => Ok(Mnemonic::Vpscatterqq), + ffi::_ND_INS_CLASS::ND_INS_VPSHAB => Ok(Mnemonic::Vpshab), + ffi::_ND_INS_CLASS::ND_INS_VPSHAD => Ok(Mnemonic::Vpshad), + ffi::_ND_INS_CLASS::ND_INS_VPSHAQ => Ok(Mnemonic::Vpshaq), + ffi::_ND_INS_CLASS::ND_INS_VPSHAW => Ok(Mnemonic::Vpshaw), + ffi::_ND_INS_CLASS::ND_INS_VPSHLB => Ok(Mnemonic::Vpshlb), + ffi::_ND_INS_CLASS::ND_INS_VPSHLD => Ok(Mnemonic::Vpshld), + ffi::_ND_INS_CLASS::ND_INS_VPSHLDD => Ok(Mnemonic::Vpshldd), + ffi::_ND_INS_CLASS::ND_INS_VPSHLDQ => Ok(Mnemonic::Vpshldq), + ffi::_ND_INS_CLASS::ND_INS_VPSHLDVD => Ok(Mnemonic::Vpshldvd), + ffi::_ND_INS_CLASS::ND_INS_VPSHLDVQ => Ok(Mnemonic::Vpshldvq), + ffi::_ND_INS_CLASS::ND_INS_VPSHLDVW => Ok(Mnemonic::Vpshldvw), + ffi::_ND_INS_CLASS::ND_INS_VPSHLDW => Ok(Mnemonic::Vpshldw), + ffi::_ND_INS_CLASS::ND_INS_VPSHLQ => Ok(Mnemonic::Vpshlq), + ffi::_ND_INS_CLASS::ND_INS_VPSHLW => Ok(Mnemonic::Vpshlw), + ffi::_ND_INS_CLASS::ND_INS_VPSHRDD => Ok(Mnemonic::Vpshrdd), + ffi::_ND_INS_CLASS::ND_INS_VPSHRDQ => Ok(Mnemonic::Vpshrdq), + ffi::_ND_INS_CLASS::ND_INS_VPSHRDVD => Ok(Mnemonic::Vpshrdvd), + ffi::_ND_INS_CLASS::ND_INS_VPSHRDVQ => Ok(Mnemonic::Vpshrdvq), + ffi::_ND_INS_CLASS::ND_INS_VPSHRDVW => Ok(Mnemonic::Vpshrdvw), + ffi::_ND_INS_CLASS::ND_INS_VPSHRDW => Ok(Mnemonic::Vpshrdw), + ffi::_ND_INS_CLASS::ND_INS_VPSHUFB => Ok(Mnemonic::Vpshufb), + ffi::_ND_INS_CLASS::ND_INS_VPSHUFBITQMB => Ok(Mnemonic::Vpshufbitqmb), + ffi::_ND_INS_CLASS::ND_INS_VPSHUFD => Ok(Mnemonic::Vpshufd), + ffi::_ND_INS_CLASS::ND_INS_VPSHUFHW => Ok(Mnemonic::Vpshufhw), + ffi::_ND_INS_CLASS::ND_INS_VPSHUFLW => Ok(Mnemonic::Vpshuflw), + ffi::_ND_INS_CLASS::ND_INS_VPSIGNB => Ok(Mnemonic::Vpsignb), + ffi::_ND_INS_CLASS::ND_INS_VPSIGND => Ok(Mnemonic::Vpsignd), + ffi::_ND_INS_CLASS::ND_INS_VPSIGNW => Ok(Mnemonic::Vpsignw), + ffi::_ND_INS_CLASS::ND_INS_VPSLLD => Ok(Mnemonic::Vpslld), + ffi::_ND_INS_CLASS::ND_INS_VPSLLDQ => Ok(Mnemonic::Vpslldq), + ffi::_ND_INS_CLASS::ND_INS_VPSLLQ => Ok(Mnemonic::Vpsllq), + ffi::_ND_INS_CLASS::ND_INS_VPSLLVD => Ok(Mnemonic::Vpsllvd), + ffi::_ND_INS_CLASS::ND_INS_VPSLLVQ => Ok(Mnemonic::Vpsllvq), + ffi::_ND_INS_CLASS::ND_INS_VPSLLVW => Ok(Mnemonic::Vpsllvw), + ffi::_ND_INS_CLASS::ND_INS_VPSLLW => Ok(Mnemonic::Vpsllw), + ffi::_ND_INS_CLASS::ND_INS_VPSRAD => Ok(Mnemonic::Vpsrad), + ffi::_ND_INS_CLASS::ND_INS_VPSRAQ => Ok(Mnemonic::Vpsraq), + ffi::_ND_INS_CLASS::ND_INS_VPSRAVD => Ok(Mnemonic::Vpsravd), + ffi::_ND_INS_CLASS::ND_INS_VPSRAVQ => Ok(Mnemonic::Vpsravq), + ffi::_ND_INS_CLASS::ND_INS_VPSRAVW => Ok(Mnemonic::Vpsravw), + ffi::_ND_INS_CLASS::ND_INS_VPSRAW => Ok(Mnemonic::Vpsraw), + ffi::_ND_INS_CLASS::ND_INS_VPSRLD => Ok(Mnemonic::Vpsrld), + ffi::_ND_INS_CLASS::ND_INS_VPSRLDQ => Ok(Mnemonic::Vpsrldq), + ffi::_ND_INS_CLASS::ND_INS_VPSRLQ => Ok(Mnemonic::Vpsrlq), + ffi::_ND_INS_CLASS::ND_INS_VPSRLVD => Ok(Mnemonic::Vpsrlvd), + ffi::_ND_INS_CLASS::ND_INS_VPSRLVQ => Ok(Mnemonic::Vpsrlvq), + ffi::_ND_INS_CLASS::ND_INS_VPSRLVW => Ok(Mnemonic::Vpsrlvw), + ffi::_ND_INS_CLASS::ND_INS_VPSRLW => Ok(Mnemonic::Vpsrlw), + ffi::_ND_INS_CLASS::ND_INS_VPSUBB => Ok(Mnemonic::Vpsubb), + ffi::_ND_INS_CLASS::ND_INS_VPSUBD => Ok(Mnemonic::Vpsubd), + ffi::_ND_INS_CLASS::ND_INS_VPSUBQ => Ok(Mnemonic::Vpsubq), + ffi::_ND_INS_CLASS::ND_INS_VPSUBSB => Ok(Mnemonic::Vpsubsb), + ffi::_ND_INS_CLASS::ND_INS_VPSUBSW => Ok(Mnemonic::Vpsubsw), + ffi::_ND_INS_CLASS::ND_INS_VPSUBUSB => Ok(Mnemonic::Vpsubusb), + ffi::_ND_INS_CLASS::ND_INS_VPSUBUSW => Ok(Mnemonic::Vpsubusw), + ffi::_ND_INS_CLASS::ND_INS_VPSUBW => Ok(Mnemonic::Vpsubw), + ffi::_ND_INS_CLASS::ND_INS_VPTERNLOGD => Ok(Mnemonic::Vpternlogd), + ffi::_ND_INS_CLASS::ND_INS_VPTERNLOGQ => Ok(Mnemonic::Vpternlogq), + ffi::_ND_INS_CLASS::ND_INS_VPTEST => Ok(Mnemonic::Vptest), + ffi::_ND_INS_CLASS::ND_INS_VPTESTMB => Ok(Mnemonic::Vptestmb), + ffi::_ND_INS_CLASS::ND_INS_VPTESTMD => Ok(Mnemonic::Vptestmd), + ffi::_ND_INS_CLASS::ND_INS_VPTESTMQ => Ok(Mnemonic::Vptestmq), + ffi::_ND_INS_CLASS::ND_INS_VPTESTMW => Ok(Mnemonic::Vptestmw), + ffi::_ND_INS_CLASS::ND_INS_VPTESTNMB => Ok(Mnemonic::Vptestnmb), + ffi::_ND_INS_CLASS::ND_INS_VPTESTNMD => Ok(Mnemonic::Vptestnmd), + ffi::_ND_INS_CLASS::ND_INS_VPTESTNMQ => Ok(Mnemonic::Vptestnmq), + ffi::_ND_INS_CLASS::ND_INS_VPTESTNMW => Ok(Mnemonic::Vptestnmw), + ffi::_ND_INS_CLASS::ND_INS_VPUNPCKHBW => Ok(Mnemonic::Vpunpckhbw), + ffi::_ND_INS_CLASS::ND_INS_VPUNPCKHDQ => Ok(Mnemonic::Vpunpckhdq), + ffi::_ND_INS_CLASS::ND_INS_VPUNPCKHQDQ => Ok(Mnemonic::Vpunpckhqdq), + ffi::_ND_INS_CLASS::ND_INS_VPUNPCKHWD => Ok(Mnemonic::Vpunpckhwd), + ffi::_ND_INS_CLASS::ND_INS_VPUNPCKLBW => Ok(Mnemonic::Vpunpcklbw), + ffi::_ND_INS_CLASS::ND_INS_VPUNPCKLDQ => Ok(Mnemonic::Vpunpckldq), + ffi::_ND_INS_CLASS::ND_INS_VPUNPCKLQDQ => Ok(Mnemonic::Vpunpcklqdq), + ffi::_ND_INS_CLASS::ND_INS_VPUNPCKLWD => Ok(Mnemonic::Vpunpcklwd), + ffi::_ND_INS_CLASS::ND_INS_VPXOR => Ok(Mnemonic::Vpxor), + ffi::_ND_INS_CLASS::ND_INS_VPXORD => Ok(Mnemonic::Vpxord), + ffi::_ND_INS_CLASS::ND_INS_VPXORQ => Ok(Mnemonic::Vpxorq), + ffi::_ND_INS_CLASS::ND_INS_VRANGEPD => Ok(Mnemonic::Vrangepd), + ffi::_ND_INS_CLASS::ND_INS_VRANGEPS => Ok(Mnemonic::Vrangeps), + ffi::_ND_INS_CLASS::ND_INS_VRANGESD => Ok(Mnemonic::Vrangesd), + ffi::_ND_INS_CLASS::ND_INS_VRANGESS => Ok(Mnemonic::Vrangess), + ffi::_ND_INS_CLASS::ND_INS_VRCP14PD => Ok(Mnemonic::Vrcp14pd), + ffi::_ND_INS_CLASS::ND_INS_VRCP14PS => Ok(Mnemonic::Vrcp14ps), + ffi::_ND_INS_CLASS::ND_INS_VRCP14SD => Ok(Mnemonic::Vrcp14sd), + ffi::_ND_INS_CLASS::ND_INS_VRCP14SS => Ok(Mnemonic::Vrcp14ss), + ffi::_ND_INS_CLASS::ND_INS_VRCP28PD => Ok(Mnemonic::Vrcp28pd), + ffi::_ND_INS_CLASS::ND_INS_VRCP28PS => Ok(Mnemonic::Vrcp28ps), + ffi::_ND_INS_CLASS::ND_INS_VRCP28SD => Ok(Mnemonic::Vrcp28sd), + ffi::_ND_INS_CLASS::ND_INS_VRCP28SS => Ok(Mnemonic::Vrcp28ss), + ffi::_ND_INS_CLASS::ND_INS_VRCPPH => Ok(Mnemonic::Vrcpph), + ffi::_ND_INS_CLASS::ND_INS_VRCPPS => Ok(Mnemonic::Vrcpps), + ffi::_ND_INS_CLASS::ND_INS_VRCPSH => Ok(Mnemonic::Vrcpsh), + ffi::_ND_INS_CLASS::ND_INS_VRCPSS => Ok(Mnemonic::Vrcpss), + ffi::_ND_INS_CLASS::ND_INS_VREDUCEPD => Ok(Mnemonic::Vreducepd), + ffi::_ND_INS_CLASS::ND_INS_VREDUCEPH => Ok(Mnemonic::Vreduceph), + ffi::_ND_INS_CLASS::ND_INS_VREDUCEPS => Ok(Mnemonic::Vreduceps), + ffi::_ND_INS_CLASS::ND_INS_VREDUCESD => Ok(Mnemonic::Vreducesd), + ffi::_ND_INS_CLASS::ND_INS_VREDUCESH => Ok(Mnemonic::Vreducesh), + ffi::_ND_INS_CLASS::ND_INS_VREDUCESS => Ok(Mnemonic::Vreducess), + ffi::_ND_INS_CLASS::ND_INS_VRNDSCALEPD => Ok(Mnemonic::Vrndscalepd), + ffi::_ND_INS_CLASS::ND_INS_VRNDSCALEPH => Ok(Mnemonic::Vrndscaleph), + ffi::_ND_INS_CLASS::ND_INS_VRNDSCALEPS => Ok(Mnemonic::Vrndscaleps), + ffi::_ND_INS_CLASS::ND_INS_VRNDSCALESD => Ok(Mnemonic::Vrndscalesd), + ffi::_ND_INS_CLASS::ND_INS_VRNDSCALESH => Ok(Mnemonic::Vrndscalesh), + ffi::_ND_INS_CLASS::ND_INS_VRNDSCALESS => Ok(Mnemonic::Vrndscaless), + ffi::_ND_INS_CLASS::ND_INS_VROUNDPD => Ok(Mnemonic::Vroundpd), + ffi::_ND_INS_CLASS::ND_INS_VROUNDPS => Ok(Mnemonic::Vroundps), + ffi::_ND_INS_CLASS::ND_INS_VROUNDSD => Ok(Mnemonic::Vroundsd), + ffi::_ND_INS_CLASS::ND_INS_VROUNDSS => Ok(Mnemonic::Vroundss), + ffi::_ND_INS_CLASS::ND_INS_VRSQRT14PD => Ok(Mnemonic::Vrsqrt14pd), + ffi::_ND_INS_CLASS::ND_INS_VRSQRT14PS => Ok(Mnemonic::Vrsqrt14ps), + ffi::_ND_INS_CLASS::ND_INS_VRSQRT14SD => Ok(Mnemonic::Vrsqrt14sd), + ffi::_ND_INS_CLASS::ND_INS_VRSQRT14SS => Ok(Mnemonic::Vrsqrt14ss), + ffi::_ND_INS_CLASS::ND_INS_VRSQRT28PD => Ok(Mnemonic::Vrsqrt28pd), + ffi::_ND_INS_CLASS::ND_INS_VRSQRT28PS => Ok(Mnemonic::Vrsqrt28ps), + ffi::_ND_INS_CLASS::ND_INS_VRSQRT28SD => Ok(Mnemonic::Vrsqrt28sd), + ffi::_ND_INS_CLASS::ND_INS_VRSQRT28SS => Ok(Mnemonic::Vrsqrt28ss), + ffi::_ND_INS_CLASS::ND_INS_VRSQRTPH => Ok(Mnemonic::Vrsqrtph), + ffi::_ND_INS_CLASS::ND_INS_VRSQRTPS => Ok(Mnemonic::Vrsqrtps), + ffi::_ND_INS_CLASS::ND_INS_VRSQRTSH => Ok(Mnemonic::Vrsqrtsh), + ffi::_ND_INS_CLASS::ND_INS_VRSQRTSS => Ok(Mnemonic::Vrsqrtss), + ffi::_ND_INS_CLASS::ND_INS_VSCALEFPD => Ok(Mnemonic::Vscalefpd), + ffi::_ND_INS_CLASS::ND_INS_VSCALEFPH => Ok(Mnemonic::Vscalefph), + ffi::_ND_INS_CLASS::ND_INS_VSCALEFPS => Ok(Mnemonic::Vscalefps), + ffi::_ND_INS_CLASS::ND_INS_VSCALEFSD => Ok(Mnemonic::Vscalefsd), + ffi::_ND_INS_CLASS::ND_INS_VSCALEFSH => Ok(Mnemonic::Vscalefsh), + ffi::_ND_INS_CLASS::ND_INS_VSCALEFSS => Ok(Mnemonic::Vscalefss), + ffi::_ND_INS_CLASS::ND_INS_VSCATTERDPD => Ok(Mnemonic::Vscatterdpd), + ffi::_ND_INS_CLASS::ND_INS_VSCATTERDPS => Ok(Mnemonic::Vscatterdps), + ffi::_ND_INS_CLASS::ND_INS_VSCATTERPF0DPD => Ok(Mnemonic::Vscatterpf0dpd), + ffi::_ND_INS_CLASS::ND_INS_VSCATTERPF0DPS => Ok(Mnemonic::Vscatterpf0dps), + ffi::_ND_INS_CLASS::ND_INS_VSCATTERPF0QPD => Ok(Mnemonic::Vscatterpf0qpd), + ffi::_ND_INS_CLASS::ND_INS_VSCATTERPF0QPS => Ok(Mnemonic::Vscatterpf0qps), + ffi::_ND_INS_CLASS::ND_INS_VSCATTERPF1DPD => Ok(Mnemonic::Vscatterpf1dpd), + ffi::_ND_INS_CLASS::ND_INS_VSCATTERPF1DPS => Ok(Mnemonic::Vscatterpf1dps), + ffi::_ND_INS_CLASS::ND_INS_VSCATTERPF1QPD => Ok(Mnemonic::Vscatterpf1qpd), + ffi::_ND_INS_CLASS::ND_INS_VSCATTERPF1QPS => Ok(Mnemonic::Vscatterpf1qps), + ffi::_ND_INS_CLASS::ND_INS_VSCATTERQPD => Ok(Mnemonic::Vscatterqpd), + ffi::_ND_INS_CLASS::ND_INS_VSCATTERQPS => Ok(Mnemonic::Vscatterqps), + ffi::_ND_INS_CLASS::ND_INS_VSHUFF32X4 => Ok(Mnemonic::Vshuff32x4), + ffi::_ND_INS_CLASS::ND_INS_VSHUFF64X2 => Ok(Mnemonic::Vshuff64x2), + ffi::_ND_INS_CLASS::ND_INS_VSHUFI32X4 => Ok(Mnemonic::Vshufi32x4), + ffi::_ND_INS_CLASS::ND_INS_VSHUFI64X2 => Ok(Mnemonic::Vshufi64x2), + ffi::_ND_INS_CLASS::ND_INS_VSHUFPD => Ok(Mnemonic::Vshufpd), + ffi::_ND_INS_CLASS::ND_INS_VSHUFPS => Ok(Mnemonic::Vshufps), + ffi::_ND_INS_CLASS::ND_INS_VSQRTPD => Ok(Mnemonic::Vsqrtpd), + ffi::_ND_INS_CLASS::ND_INS_VSQRTPH => Ok(Mnemonic::Vsqrtph), + ffi::_ND_INS_CLASS::ND_INS_VSQRTPS => Ok(Mnemonic::Vsqrtps), + ffi::_ND_INS_CLASS::ND_INS_VSQRTSD => Ok(Mnemonic::Vsqrtsd), + ffi::_ND_INS_CLASS::ND_INS_VSQRTSH => Ok(Mnemonic::Vsqrtsh), + ffi::_ND_INS_CLASS::ND_INS_VSQRTSS => Ok(Mnemonic::Vsqrtss), + ffi::_ND_INS_CLASS::ND_INS_VSTMXCSR => Ok(Mnemonic::Vstmxcsr), + ffi::_ND_INS_CLASS::ND_INS_VSUBPD => Ok(Mnemonic::Vsubpd), + ffi::_ND_INS_CLASS::ND_INS_VSUBPH => Ok(Mnemonic::Vsubph), + ffi::_ND_INS_CLASS::ND_INS_VSUBPS => Ok(Mnemonic::Vsubps), + ffi::_ND_INS_CLASS::ND_INS_VSUBSD => Ok(Mnemonic::Vsubsd), + ffi::_ND_INS_CLASS::ND_INS_VSUBSH => Ok(Mnemonic::Vsubsh), + ffi::_ND_INS_CLASS::ND_INS_VSUBSS => Ok(Mnemonic::Vsubss), + ffi::_ND_INS_CLASS::ND_INS_VTESTPD => Ok(Mnemonic::Vtestpd), + ffi::_ND_INS_CLASS::ND_INS_VTESTPS => Ok(Mnemonic::Vtestps), + ffi::_ND_INS_CLASS::ND_INS_VUCOMISD => Ok(Mnemonic::Vucomisd), + ffi::_ND_INS_CLASS::ND_INS_VUCOMISH => Ok(Mnemonic::Vucomish), + ffi::_ND_INS_CLASS::ND_INS_VUCOMISS => Ok(Mnemonic::Vucomiss), + ffi::_ND_INS_CLASS::ND_INS_VUNPCKHPD => Ok(Mnemonic::Vunpckhpd), + ffi::_ND_INS_CLASS::ND_INS_VUNPCKHPS => Ok(Mnemonic::Vunpckhps), + ffi::_ND_INS_CLASS::ND_INS_VUNPCKLPD => Ok(Mnemonic::Vunpcklpd), + ffi::_ND_INS_CLASS::ND_INS_VUNPCKLPS => Ok(Mnemonic::Vunpcklps), + ffi::_ND_INS_CLASS::ND_INS_VXORPD => Ok(Mnemonic::Vxorpd), + ffi::_ND_INS_CLASS::ND_INS_VXORPS => Ok(Mnemonic::Vxorps), + ffi::_ND_INS_CLASS::ND_INS_VZEROALL => Ok(Mnemonic::Vzeroall), + ffi::_ND_INS_CLASS::ND_INS_VZEROUPPER => Ok(Mnemonic::Vzeroupper), + ffi::_ND_INS_CLASS::ND_INS_WAIT => Ok(Mnemonic::Wait), + ffi::_ND_INS_CLASS::ND_INS_WBINVD => Ok(Mnemonic::Wbinvd), + ffi::_ND_INS_CLASS::ND_INS_WBNOINVD => Ok(Mnemonic::Wbnoinvd), + ffi::_ND_INS_CLASS::ND_INS_WRFSBASE => Ok(Mnemonic::Wrfsbase), + ffi::_ND_INS_CLASS::ND_INS_WRGSBASE => Ok(Mnemonic::Wrgsbase), + ffi::_ND_INS_CLASS::ND_INS_WRMSR => Ok(Mnemonic::Wrmsr), + ffi::_ND_INS_CLASS::ND_INS_WRPKRU => Ok(Mnemonic::Wrpkru), + ffi::_ND_INS_CLASS::ND_INS_WRSHR => Ok(Mnemonic::Wrshr), + ffi::_ND_INS_CLASS::ND_INS_WRSS => Ok(Mnemonic::Wrss), + ffi::_ND_INS_CLASS::ND_INS_WRUSS => Ok(Mnemonic::Wruss), + ffi::_ND_INS_CLASS::ND_INS_XABORT => Ok(Mnemonic::Xabort), + ffi::_ND_INS_CLASS::ND_INS_XADD => Ok(Mnemonic::Xadd), + ffi::_ND_INS_CLASS::ND_INS_XBEGIN => Ok(Mnemonic::Xbegin), + ffi::_ND_INS_CLASS::ND_INS_XCHG => Ok(Mnemonic::Xchg), + ffi::_ND_INS_CLASS::ND_INS_XCRYPTCBC => Ok(Mnemonic::Xcryptcbc), + ffi::_ND_INS_CLASS::ND_INS_XCRYPTCFB => Ok(Mnemonic::Xcryptcfb), + ffi::_ND_INS_CLASS::ND_INS_XCRYPTCTR => Ok(Mnemonic::Xcryptctr), + ffi::_ND_INS_CLASS::ND_INS_XCRYPTECB => Ok(Mnemonic::Xcryptecb), + ffi::_ND_INS_CLASS::ND_INS_XCRYPTOFB => Ok(Mnemonic::Xcryptofb), + ffi::_ND_INS_CLASS::ND_INS_XEND => Ok(Mnemonic::Xend), + ffi::_ND_INS_CLASS::ND_INS_XGETBV => Ok(Mnemonic::Xgetbv), + ffi::_ND_INS_CLASS::ND_INS_XLATB => Ok(Mnemonic::Xlatb), + ffi::_ND_INS_CLASS::ND_INS_XOR => Ok(Mnemonic::Xor), + ffi::_ND_INS_CLASS::ND_INS_XORPD => Ok(Mnemonic::Xorpd), + ffi::_ND_INS_CLASS::ND_INS_XORPS => Ok(Mnemonic::Xorps), + ffi::_ND_INS_CLASS::ND_INS_XRESLDTRK => Ok(Mnemonic::Xresldtrk), + ffi::_ND_INS_CLASS::ND_INS_XRSTOR => Ok(Mnemonic::Xrstor), + ffi::_ND_INS_CLASS::ND_INS_XRSTORS => Ok(Mnemonic::Xrstors), + ffi::_ND_INS_CLASS::ND_INS_XSAVE => Ok(Mnemonic::Xsave), + ffi::_ND_INS_CLASS::ND_INS_XSAVEC => Ok(Mnemonic::Xsavec), + ffi::_ND_INS_CLASS::ND_INS_XSAVEOPT => Ok(Mnemonic::Xsaveopt), + ffi::_ND_INS_CLASS::ND_INS_XSAVES => Ok(Mnemonic::Xsaves), + ffi::_ND_INS_CLASS::ND_INS_XSETBV => Ok(Mnemonic::Xsetbv), + ffi::_ND_INS_CLASS::ND_INS_XSHA1 => Ok(Mnemonic::Xsha1), + ffi::_ND_INS_CLASS::ND_INS_XSHA256 => Ok(Mnemonic::Xsha256), + ffi::_ND_INS_CLASS::ND_INS_XSTORE => Ok(Mnemonic::Xstore), + ffi::_ND_INS_CLASS::ND_INS_XSUSLDTRK => Ok(Mnemonic::Xsusldtrk), + ffi::_ND_INS_CLASS::ND_INS_XTEST => Ok(Mnemonic::Xtest), + } + } +} diff --git a/rsbddisasm/bddisasm/src/operand.rs b/rsbddisasm/bddisasm/src/operand.rs new file mode 100644 index 0000000..524f903 --- /dev/null +++ b/rsbddisasm/bddisasm/src/operand.rs @@ -0,0 +1,767 @@ +/* + * Copyright (c) 2021 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ +//! Operand types and details. + +extern crate bddisasm_sys as ffi; + +use std::fmt; + +/// Describes an address operand. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct OpAddr { + /// The ID of the base segment selector. + /// + /// `ES` = 0, `CS` = 1, `SS` = 2, `DS` = 3, `FS` = 4, `GS` = 5. + pub base_seg: u16, + + /// Offset inside the segment. + pub offset: u64, +} + +#[doc(hidden)] +impl From for OpAddr { + fn from(op: ffi::ND_OPDESC_ADDRESS) -> OpAddr { + OpAddr { + base_seg: op.BaseSeg, + offset: op.Offset, + } + } +} + +#[doc(hidden)] +impl OpAddr { + pub(crate) fn new(base_seg: u16, offset: u64) -> Self { + Self { base_seg, offset } + } +} + +/// The type of a register. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum OpRegType { + /// The register is a 8/16/32/64 bit general purpose register. + Gpr, + + /// The register is a segment register. + Seg, + + /// The register is a 80-bit FPU register. + Fpu, + + /// The register is a 64-bit MMX register. + Mmx, + + /// The register is a 128/256/512 bit SSE vector register. + Sse, + + /// The register is a control register. + Cr, + + /// The register is a debug register. + Dr, + + /// The register is a test register. + Tr, + + /// The register is a bound register. + Bnd, + + /// The register is a mask register. + Msk, + + /// The register is a tile register. + Tile, + + /// The register is a model specific register. + Msr, + + /// The register is a extended control register. + Xcr, + + /// The register is a system register. + Sys, + + /// The register is a x87 status/control register. + X87, + + /// The register is the MXCSR register. + Mxcsr, + + /// The register is the PKRU register. + Pkru, + + /// The register is the SSP (Shadow Stack Pointer) register. + Ssp, + + /// The register is the FLAGS register. + Flg, + + /// The register is the instruction pointer register. + Rip, + + /// The register is the User Interrupt Flag. + Uif, +} + +#[doc(hidden)] +impl From for OpRegType { + fn from(op: ffi::ND_OPDESC_REGISTER) -> OpRegType { + match op.Type { + ffi::_ND_REG_TYPE::ND_REG_NOT_PRESENT => panic!("Unexpected ND_REG_NOT_PRESENT"), + ffi::_ND_REG_TYPE::ND_REG_GPR => OpRegType::Gpr, + ffi::_ND_REG_TYPE::ND_REG_SEG => OpRegType::Seg, + ffi::_ND_REG_TYPE::ND_REG_FPU => OpRegType::Fpu, + ffi::_ND_REG_TYPE::ND_REG_MMX => OpRegType::Mmx, + ffi::_ND_REG_TYPE::ND_REG_SSE => OpRegType::Sse, + ffi::_ND_REG_TYPE::ND_REG_CR => OpRegType::Cr, + ffi::_ND_REG_TYPE::ND_REG_DR => OpRegType::Dr, + ffi::_ND_REG_TYPE::ND_REG_TR => OpRegType::Tr, + ffi::_ND_REG_TYPE::ND_REG_BND => OpRegType::Bnd, + ffi::_ND_REG_TYPE::ND_REG_MSK => OpRegType::Msk, + ffi::_ND_REG_TYPE::ND_REG_TILE => OpRegType::Tile, + ffi::_ND_REG_TYPE::ND_REG_MSR => OpRegType::Msr, + ffi::_ND_REG_TYPE::ND_REG_XCR => OpRegType::Xcr, + ffi::_ND_REG_TYPE::ND_REG_SYS => OpRegType::Sys, + ffi::_ND_REG_TYPE::ND_REG_X87 => OpRegType::X87, + ffi::_ND_REG_TYPE::ND_REG_MXCSR => OpRegType::Mxcsr, + ffi::_ND_REG_TYPE::ND_REG_PKRU => OpRegType::Pkru, + ffi::_ND_REG_TYPE::ND_REG_SSP => OpRegType::Ssp, + ffi::_ND_REG_TYPE::ND_REG_FLG => OpRegType::Flg, + ffi::_ND_REG_TYPE::ND_REG_RIP => OpRegType::Rip, + ffi::_ND_REG_TYPE::ND_REG_UIF => OpRegType::Uif, + } + } +} + +impl fmt::Display for OpRegType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Gpr => write!(f, "GPR"), + Self::Seg => write!(f, "Segment"), + Self::Fpu => write!(f, "FPU"), + Self::Mmx => write!(f, "MMX"), + Self::Sse => write!(f, "SSE"), + Self::Cr => write!(f, "CR"), + Self::Dr => write!(f, "DR"), + Self::Tr => write!(f, "TR"), + Self::Bnd => write!(f, "BND"), + Self::Msk => write!(f, "MSK"), + Self::Tile => write!(f, "Tile"), + Self::Msr => write!(f, "MSR"), + Self::Xcr => write!(f, "XCR"), + Self::Sys => write!(f, "Sys"), + Self::X87 => write!(f, "X87"), + Self::Mxcsr => write!(f, "MXCSR"), + Self::Pkru => write!(f, "PKRU"), + Self::Ssp => write!(f, "SSP"), + Self::Flg => write!(f, "Flg"), + Self::Rip => write!(f, "RIP"), + Self::Uif => write!(f, "UIF"), + } + } +} + +/// Describes a register operand. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct OpReg { + /// The type of the register. + pub kind: OpRegType, + + /// Indicates the register size, in bytes. + /// + /// This may not be equal to the [`Operand::size`] field, as a smaller amount of data may be processed from a + /// register (especially if we have a SSE register or a mask register). + pub size: u32, + + // TODO: create an enum for each register, instead of using an ID. + /// The register index/ID. + /// + /// Registers are numbered as they are in the Intel documentation. Examples: + /// + /// - `AL` = `AX` = `EAX` = `RAX` = 0 + /// - `R15B` = `R15W` = `R15D` = `R15` = 15 + /// - `XMM0` = 0 + /// - `ZMM31` = 31 + /// - `ES` = 0 + /// - `CS` = 1 + /// + /// # Remarks + /// + /// If [kind](OpReg::kind) is [OpRegType::Gpr](OpRegType::Gpr), the high and low part of 16-bit registers will have + /// the same index (for example, `AH` and `AL`). To differentiate between them use [is_high8](OpReg::is_high8). + pub index: usize, + + /// The number of registers accessed, starting with [id](OpReg::index). + pub count: u32, + + /// `true` if this is the high part of a 16-bit GPR: `AH`, `CH`, `DH`, or `BH`. + pub is_high8: bool, + + /// `true` if this is a block register addressing. + pub is_block: bool, +} + +#[doc(hidden)] +impl From for OpReg { + fn from(op: ffi::ND_OPDESC_REGISTER) -> OpReg { + let kind = OpRegType::from(op); + let is_high8 = op.IsHigh8(); + let index = match kind { + OpRegType::Gpr => { + if is_high8 { + // See `ShemuGetGprValue` in `bdshemu.c`. + op.Reg - 4 + } else { + op.Reg + } + } + _ => op.Reg, + } as usize; + + OpReg { + kind, + size: op.Size, + index, + count: op.Count, + is_high8, + is_block: op.IsBlock(), + } + } +} + +/// Holds extra information for instruction that use VSIB addressing. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct Vsib { + /// VSIB element size. + pub vsib_element_size: u8, + + /// Number of elements scattered/gathered/prefetched. + pub vsib_element_count: u8, +} + +/// Shadow stack access types. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum ShadowStackAccess { + None, + + /// Explicit memory operand accessed as shadow stack. + Explicit, + + /// Shadow Stack Pointer (`SSP`) used as base for addressing using conventional load/store. + SspLdSt, + + /// Shadow Stack Pointer (`SSP`) used as base for addressing using `push`/`pop`. + SspPushPop, + + /// Privilege 0 `SSP` (`IA32_PL0_SSP`) used (`SETSSBSY`). + Pl0Ssp, +} + +#[doc(hidden)] +impl From for ShadowStackAccess { + fn from(acc: ffi::ND_SHSTK_ACCESS) -> ShadowStackAccess { + match acc { + ffi::_ND_SHSTK_ACCESS::ND_SHSTK_NONE => ShadowStackAccess::None, + ffi::_ND_SHSTK_ACCESS::ND_SHSTK_EXPLICIT => ShadowStackAccess::Explicit, + ffi::_ND_SHSTK_ACCESS::ND_SHSTK_SSP_LD_ST => ShadowStackAccess::SspLdSt, + ffi::_ND_SHSTK_ACCESS::ND_SHSTK_SSP_PUSH_POP => ShadowStackAccess::SspPushPop, + ffi::_ND_SHSTK_ACCESS::ND_SHSTK_PL0_SSP => ShadowStackAccess::Pl0Ssp, + // NOTE: when updating this take care to also update the `From` implementation! + // TODO: any way of keeping these in sync automagically? + } + } +} + +impl From for ShadowStackAccess { + fn from(acc: u8) -> ShadowStackAccess { + if acc == ffi::_ND_SHSTK_ACCESS::ND_SHSTK_NONE as u8 { + ShadowStackAccess::None + } else if acc == ffi::_ND_SHSTK_ACCESS::ND_SHSTK_EXPLICIT as u8 { + ShadowStackAccess::Explicit + } else if acc == ffi::_ND_SHSTK_ACCESS::ND_SHSTK_SSP_LD_ST as u8 { + ShadowStackAccess::SspLdSt + } else if acc == ffi::_ND_SHSTK_ACCESS::ND_SHSTK_SSP_PUSH_POP as u8 { + ShadowStackAccess::SspPushPop + } else if acc == ffi::_ND_SHSTK_ACCESS::ND_SHSTK_PL0_SSP as u8 { + ShadowStackAccess::Pl0Ssp + } else { + panic!("Unexpected shadow stack access type: {}", acc) + } + } +} + +/// Describes a memory operand. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct OpMem { + /// `true` if the memory operand is a broadcast operand. + pub has_broadcast: bool, + + /// `true` if this is a rip-relative addressing. Base, Index, Scale are all ignored. + pub is_rip_rel: bool, + + /// `true` if this is a stack op. + /// + /// # Note + /// + /// Explicit stack accesses are not included (eg: `mov eax, [rsp]`). + pub is_stack: bool, + + /// `true` for `[RSI]` and `[RDI]` operands inside string operations. + pub is_string: bool, + + /// `true` if direct addressing (`MOV [...], EAX, 0xA3`). + pub is_direct: bool, + /// `true` if this is a bit base. Used for `BT*` instructions. + /// + /// The bitbase stored in the second operand must be added to the linear address. + pub is_bitbase: bool, + + /// `true` if the memory operand is address generation and no memory access is made. + pub is_ag: bool, + + /// `true` MIB addressing is used (MPX instructions). + pub is_mib: bool, + + /// `true` the addressing uses sibmem (AMX instructions). + pub is_sib_mem: bool, + + /// Base segment used to address the memory. + pub seg: Option, + + /// Base register. + pub base: Option, + + /// Base register size, in bytes. Max 8 bytes. + pub base_size: Option, + + /// Index register. Can be a vector reg (ZMM0-ZMM31). + pub index: Option, + + /// Index register size, in bytes. Max 8 bytes. + pub index_size: Option, + + /// The `index` register selects a vector register. + pub vsib: Option, + + /// Scale: 1, 2, 4 or 8. Always present if `index` is present. + pub scale: Option, + + /// Sign extended displacement. + pub disp: Option, + + /// Displacement size. Max 4 bytes. + pub disp_size: Option, + + /// Compressed displacement size - 1, 2, 4, 8, 16, 32, 64. + pub comp_disp_size: Option, + + /// Shadow stack access type. + /// + /// Will be `None` if the shadow stack is not accessed. + pub shadow_stack_access: Option, +} + +#[doc(hidden)] +impl From for OpMem { + fn from(op: ffi::ND_OPDESC_MEMORY) -> OpMem { + let seg = if op.HasSeg() { Some(op.Seg) } else { None }; + + let (base, base_size) = if op.HasBase() { + (Some(op.Base), Some(op.BaseSize)) + } else { + (None, None) + }; + + let (index, index_size, scale) = if op.HasIndex() { + (Some(op.Index), Some(op.IndexSize), Some(op.Scale)) + } else { + (None, None, None) + }; + + let (disp, disp_size) = if op.HasDisp() { + (Some(op.Disp), Some(op.DispSize)) + } else { + (None, None) + }; + + let comp_disp_size = if op.HasCompDisp() { + Some(op.CompDispSize) + } else { + None + }; + + let (vsib, index_size) = if op.IsVsib() { + ( + Some(Vsib { + vsib_element_size: op.Vsib.ElemSize, + vsib_element_count: op.Vsib.ElemCount, + }), + Some(op.Vsib.IndexSize as u32), + ) + } else { + (None, index_size) + }; + + let shadow_stack_access = if op.IsShadowStack() { + Some(ShadowStackAccess::from(op.ShStkType)) + } else { + None + }; + + OpMem { + has_broadcast: op.HasBroadcast(), + is_rip_rel: op.IsRipRel(), + is_stack: op.IsStack(), + is_string: op.IsString(), + is_direct: op.IsDirect(), + is_bitbase: op.IsBitbase(), + is_ag: op.IsAG(), + is_mib: op.IsMib(), + is_sib_mem: op.IsSibMem(), + seg, + base, + base_size, + index, + index_size, + vsib, + scale, + disp, + disp_size, + comp_disp_size, + shadow_stack_access, + } + } +} + +/// Extended operand information, based on the actual type of the operand. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum OpInfo { + None, + + /// The operand is a register. + Reg(OpReg), + + /// The operand is located in memory. + Mem(OpMem), + + /// The operand is an immediate. + Imm(u64), + + /// The operand is a relative offset. + Offs(u64), + + /// The operand is an absolute address, in the form `seg:offset`. + Addr(OpAddr), + + /// The operand is an implicit constant. + Const(u64), + + /// An entire bank/set of registers are being accessed. Used in `PUSHA`/`POPA`/`XSAVE`/`LOADALL`. + Bank, +} + +#[doc(hidden)] +impl From for OpInfo { + fn from(op: ffi::ND_OPERAND) -> OpInfo { + match op.Type { + ffi::_ND_OPERAND_TYPE::ND_OP_NOT_PRESENT => OpInfo::None, + ffi::_ND_OPERAND_TYPE::ND_OP_REG => { + OpInfo::Reg(OpReg::from(unsafe { op.Info.Register })) + } + ffi::_ND_OPERAND_TYPE::ND_OP_MEM => OpInfo::Mem(OpMem::from(unsafe { op.Info.Memory })), + ffi::_ND_OPERAND_TYPE::ND_OP_IMM => OpInfo::Imm(unsafe { op.Info.Immediate }.Imm), + ffi::_ND_OPERAND_TYPE::ND_OP_OFFS => { + OpInfo::Offs(unsafe { op.Info.RelativeOffset }.Rel) + } + ffi::_ND_OPERAND_TYPE::ND_OP_ADDR => { + OpInfo::Addr(OpAddr::from(unsafe { op.Info.Address })) + } + ffi::_ND_OPERAND_TYPE::ND_OP_CONST => OpInfo::Const(unsafe { op.Info.Constant }.Const), + ffi::_ND_OPERAND_TYPE::ND_OP_BANK => OpInfo::Bank, + } + } +} + +impl fmt::Display for OpInfo { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::None => write!(f, "None"), + Self::Reg(_) => write!(f, "register"), + Self::Mem(_) => write!(f, "memory"), + Self::Imm(_) => write!(f, "immediate"), + Self::Offs(_) => write!(f, "relative offset"), + Self::Addr(_) => write!(f, "absolute address"), + Self::Const(_) => write!(f, "implicit constant"), + Self::Bank => write!(f, "register bank"), + } + } +} + +/// Operand size. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum OpSize { + /// The inner value contains the operand size in bytes. + Bytes(usize), + + /// The size of a cache line. + CacheLine, + + /// Unknown size. + Unknown, +} + +impl fmt::Display for OpSize { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Bytes(size) => write!(f, "{} bytes", size), + Self::CacheLine => write!(f, "cache line"), + Self::Unknown => write!(f, "unknown"), + } + } +} + +#[doc(hidden)] +impl From for OpSize { + fn from(sz: ffi::ND_OPERAND_SIZE) -> OpSize { + match sz { + ffi::ND_SIZE_8BIT => OpSize::Bytes(1), + ffi::ND_SIZE_16BIT => OpSize::Bytes(2), + ffi::ND_SIZE_32BIT => OpSize::Bytes(4), + ffi::ND_SIZE_48BIT => OpSize::Bytes(6), + ffi::ND_SIZE_64BIT => OpSize::Bytes(8), + ffi::ND_SIZE_80BIT => OpSize::Bytes(10), + ffi::ND_SIZE_112BIT => OpSize::Bytes(14), + ffi::ND_SIZE_128BIT => OpSize::Bytes(16), + ffi::ND_SIZE_224BIT => OpSize::Bytes(28), + ffi::ND_SIZE_256BIT => OpSize::Bytes(32), + ffi::ND_SIZE_384BIT => OpSize::Bytes(48), + ffi::ND_SIZE_512BIT => OpSize::Bytes(64), + ffi::ND_SIZE_752BIT => OpSize::Bytes(94), + ffi::ND_SIZE_864BIT => OpSize::Bytes(108), + ffi::ND_SIZE_4096BIT => OpSize::Bytes(512), + ffi::ND_SIZE_1KB => OpSize::Bytes(1024), + ffi::ND_SIZE_CACHE_LINE => OpSize::CacheLine, + ffi::ND_SIZE_UNKNOWN => OpSize::Unknown, + _ => panic!("Unespected operand size: {}", sz), + } + } +} + +/// Operand access mode. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct OpAccess { + /// The operand is read. + pub read: bool, + + /// The operand is written. + pub write: bool, + + /// The operand is read only under some conditions. + pub cond_read: bool, + + /// The operand is written only under some conditions. + pub cond_write: bool, + + /// The operand is prefetched. + pub prefetch: bool, +} + +#[doc(hidden)] +impl From for OpAccess { + fn from(acc: ffi::ND_OPERAND_ACCESS) -> OpAccess { + let acc = unsafe { acc.__bindgen_anon_1 }; + + OpAccess { + read: acc.Read() != 0, + write: acc.Write() != 0, + cond_read: acc.CondRead() != 0, + cond_write: acc.CondWrite() != 0, + prefetch: acc.Prefetch() != 0, + } + } +} + +/// Broadcast specifier. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct Broadcast { + /// Number of times to broadcast the element. + pub count: u8, + + /// Size of one element. + pub size: u8, +} + +/// Decorator information. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct Decorator { + /// If mask is present, holds the ID of the mask register (`K0` - `K7`) used. + pub mask_register: Option, + + /// `true` if zeroing will be made, `false` if merging will be made. + pub has_zero: bool, + + /// If broadcasting is being made, holds the broadcast specifier. + pub broadcast: Option, +} + +#[doc(hidden)] +impl From for Decorator { + fn from(decorator: ffi::ND_OPERAND_DECORATOR) -> Decorator { + let mask_register = if decorator.HasMask() { + Some(decorator.Mask.Msk) + } else { + None + }; + + let broadcast = if decorator.HasBroadcast() { + Some(Broadcast { + count: decorator.Broadcast.Count, + size: decorator.Broadcast.Size, + }) + } else { + None + }; + + Decorator { + mask_register, + has_zero: decorator.HasZero(), + broadcast, + } + } +} + +/// Describes an instruction operand. +/// +/// Each operand type encodes different information. See [`OpInfo`] for details. +/// +/// # Examples +/// +/// ``` +/// # use std::error::Error; +/// # +/// # fn main() -> Result<(), Box> { +/// use bddisasm::decoder::{DecodedInstruction, DecodeMode}; +/// use bddisasm::operand::*; +/// +/// // `MOV ah, byte ptr [rcx+rdx*2+0x8]` +/// let code = vec![0x8a, 0x64, 0x51, 0x08]; +/// let ins = DecodedInstruction::decode(&code, DecodeMode::Bits64)?; +/// +/// let operands = ins.operands(); +/// let dst = operands[0]; +/// let src = operands[1]; +/// +/// // Get the size of each operand +/// println!("Destination size: {}", dst.size); +/// println!("Source size: {}", src.size); +/// +/// // Get the type of the destination operand +/// match dst.info { +/// OpInfo::Reg(reg) => { +/// println!("Register kind: {} Size: {} Index: {}", reg.kind, reg.size, reg.index) +/// }, +/// // In this case we know that the destination operand is a register +/// _ => println!("Unexpected operand info type"), +/// } +/// +/// # Ok(()) +/// # } +/// ``` +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct Operand { + /// Extended operand information. + pub info: OpInfo, + + // Operand size in bytes. + // + // This should be used when operating with the operand. It includes sign-extension or zero-extensions. + // + // # Note + /// + /// It indicates the actual amount of data used for processing. If the operand is a [register](OpInfo::Reg), it + /// MAY NOT indicate the register size. Use the [info](Operand::info) field to get the actual register size in these + /// cases. + pub size: OpSize, + + /// Raw size inside the instruction. + /// + /// This will usually be identical to [size](Operand::size), however, some instructions force the actual size of + /// their operands to 64 bit (`PUSH`/`POP` or branches are good examples). + /// + /// Although the raw size of the relative offset or the immediate will be [raw_size](Operand::raw_size), internally, + /// the CPU will use [size](Operand::size) (usually sign-extended). + pub raw_size: OpSize, + + /// Access mode. + pub access: OpAccess, + + /// `true` if the operand is default. This also applies to implicit operands. + pub is_default: bool, + + /// Decorator information. + pub decorator: Decorator, +} + +#[doc(hidden)] +impl From for Operand { + fn from(op: ffi::ND_OPERAND) -> Operand { + Operand { + info: OpInfo::from(op), + size: OpSize::from(op.Size), + raw_size: OpSize::from(op.RawSize), + access: OpAccess::from(op.Access), + is_default: unsafe { op.Flags.__bindgen_anon_1 }.IsDefault() != 0, + decorator: Decorator::from(op.Decorator), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::decoded_instruction::{DecodeMode, DecodedInstruction}; + + #[test] + fn ops() { + let code = vec![0x8a, 0x64, 0x51, 0x08]; + let ins = DecodedInstruction::decode(&code, DecodeMode::Bits64).unwrap(); + + let operands = ins.operands(); + assert_eq!(operands.len(), 2); + + let dest = operands[0]; + assert_eq!(dest.size, OpSize::Bytes(1)); + assert_eq!(dest.raw_size, OpSize::Bytes(1)); + assert_eq!(dest.is_default, false); + assert!(dest.access.write); + + if let OpInfo::Reg(dst_reg) = dest.info { + assert_eq!(dst_reg.kind, OpRegType::Gpr); + assert_eq!(dst_reg.size, 1); + assert_eq!(dst_reg.index, 0); + assert_eq!(dst_reg.is_high8, true); + } else { + unreachable!(); + } + + let src = operands[1]; + assert_eq!(src.size, OpSize::Bytes(1)); + assert_eq!(src.raw_size, OpSize::Bytes(1)); + assert_eq!(src.is_default, false); + assert!(src.access.read); + + if let OpInfo::Mem(src_mem) = src.info { + assert_eq!(src_mem.seg, Some(3)); + assert_eq!(src_mem.base, Some(1)); + assert_eq!(src_mem.base_size, Some(8)); + assert_eq!(src_mem.index, Some(2)); + assert_eq!(src_mem.index_size, Some(8)); + assert_eq!(src_mem.scale, Some(2)); + assert_eq!(src_mem.disp, Some(8)); + assert_eq!(src_mem.disp_size, Some(1)); + } else { + unreachable!(); + } + } +} diff --git a/rsbddisasm/bddisasm/src/rflags.rs b/rsbddisasm/bddisasm/src/rflags.rs new file mode 100644 index 0000000..5ab896d --- /dev/null +++ b/rsbddisasm/bddisasm/src/rflags.rs @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ +//! Describes the bits in the FLAGS register. + +extern crate bddisasm_sys as ffi; + +/// Carry flag. +pub const CF: u32 = ffi::NDR_RFLAG_CF; +/// Parity flag. +pub const PF: u32 = ffi::NDR_RFLAG_PF; +/// Auxiliary flag. +pub const AF: u32 = ffi::NDR_RFLAG_AF; +/// Zero flag. +pub const ZF: u32 = ffi::NDR_RFLAG_ZF; +/// Sign flag. +pub const SF: u32 = ffi::NDR_RFLAG_SF; +/// Trap flag. +pub const TF: u32 = ffi::NDR_RFLAG_TF; +/// Interrupt flag. +pub const IF: u32 = ffi::NDR_RFLAG_IF; +/// Direction flag. +pub const DF: u32 = ffi::NDR_RFLAG_DF; +/// Overflow flag. +pub const OF: u32 = ffi::NDR_RFLAG_OF; +/// I/O privilege level flag. +pub const IOPL: u32 = ffi::NDR_RFLAG_IOPL; +/// Nested task flag. +pub const NT: u32 = ffi::NDR_RFLAG_NT; +/// Resume flag. +pub const RF: u32 = ffi::NDR_RFLAG_RF; +/// Virtual mode flag. +pub const VM: u32 = ffi::NDR_RFLAG_VM; +/// Alignment check flag. +pub const AC: u32 = ffi::NDR_RFLAG_AC; +/// Virtual interrupts flag. +pub const VIF: u32 = ffi::NDR_RFLAG_VIF; +/// Virtual interrupt pending flag. +pub const VIP: u32 = ffi::NDR_RFLAG_VIP; +/// CPUID identification flag. +pub const ID: u32 = ffi::NDR_RFLAG_ID; + +pub(crate) fn flags_raw(flags: ffi::ND_RFLAGS) -> u32 { + unsafe { flags.Raw } +} diff --git a/rsbddisasm/bddisasm/src/tuple.rs b/rsbddisasm/bddisasm/src/tuple.rs new file mode 100644 index 0000000..9991b6e --- /dev/null +++ b/rsbddisasm/bddisasm/src/tuple.rs @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2021 Bitdefender + * SPDX-License-Identifier: Apache-2.0 + */ +//! Instruction tuple type. + +extern crate bddisasm_sys as ffi; + +/// Instruction tuple type. +/// +/// Used to determine compressed displacement size for `disp8 EVEX` instructions. Note that most of the `EVEX` encoded +/// instructions use the compressed displacement addressing scheme. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub enum Tuple { + None, + /// Full Vector. + Fv, + /// Half Vector. + Hv, + /// Quarter Vector. + Qv, + /// Tuple1 scalar, size 8 bit. + T1S8, + /// Tuple1 scalar, size 16 bit. + T1S16, + /// Tuple1 scalar, size 32/64 bit. + T1S, + /// Tuple1 float, size 32/64 bit. + T1F, + /// Tuple2, 64/128 bit. + T2, + /// Tuple4, 128/256 bit. + T4, + /// Tuple8, 256 bit. + T8, + /// Full Vector Memory. + Fvm, + /// Half Vector Memory. + Hvm, + /// Quarter Vector Memory. + Qvm, + /// Oct Vector Memory. + OVm, + /// M128, 128 bit. + M128, + /// DUP (VMOVDDUP). + Dup, + /// 4 x 32 bit Memory Elements are referenced. + T14X, +} + +#[doc(hidden)] +impl From for Tuple { + fn from(value: ffi::ND_TUPLE) -> Tuple { + match value { + ffi::_ND_TUPLE::ND_TUPLE_None => Tuple::None, + ffi::_ND_TUPLE::ND_TUPLE_FV => Tuple::Fv, + ffi::_ND_TUPLE::ND_TUPLE_HV => Tuple::Hv, + ffi::_ND_TUPLE::ND_TUPLE_QV => Tuple::Qv, + ffi::_ND_TUPLE::ND_TUPLE_T1S8 => Tuple::T1S8, + ffi::_ND_TUPLE::ND_TUPLE_T1S16 => Tuple::T1S16, + ffi::_ND_TUPLE::ND_TUPLE_T1S => Tuple::T1S, + ffi::_ND_TUPLE::ND_TUPLE_T1F => Tuple::T1F, + ffi::_ND_TUPLE::ND_TUPLE_T2 => Tuple::T2, + ffi::_ND_TUPLE::ND_TUPLE_T4 => Tuple::T4, + ffi::_ND_TUPLE::ND_TUPLE_T8 => Tuple::T8, + ffi::_ND_TUPLE::ND_TUPLE_FVM => Tuple::Fvm, + ffi::_ND_TUPLE::ND_TUPLE_HVM => Tuple::Hvm, + ffi::_ND_TUPLE::ND_TUPLE_QVM => Tuple::Qvm, + ffi::_ND_TUPLE::ND_TUPLE_OVM => Tuple::OVm, + ffi::_ND_TUPLE::ND_TUPLE_M128 => Tuple::M128, + ffi::_ND_TUPLE::ND_TUPLE_DUP => Tuple::Dup, + ffi::_ND_TUPLE::ND_TUPLE_T1_4X => Tuple::T14X, + // NOTE: when updating this take care to also update the `From` implementation! + // TODO: any way of keeping these in sync automagically? + } + } +} + +impl From for Tuple { + fn from(value: u32) -> Tuple { + if value == ffi::_ND_TUPLE::ND_TUPLE_None as u32 { + Tuple::None + } else if value == ffi::_ND_TUPLE::ND_TUPLE_FV as u32 { + Tuple::Fv + } else if value == ffi::_ND_TUPLE::ND_TUPLE_HV as u32 { + Tuple::Hv + } else if value == ffi::_ND_TUPLE::ND_TUPLE_QV as u32 { + Tuple::Qv + } else if value == ffi::_ND_TUPLE::ND_TUPLE_T1S8 as u32 { + Tuple::T1S8 + } else if value == ffi::_ND_TUPLE::ND_TUPLE_T1S16 as u32 { + Tuple::T1S16 + } else if value == ffi::_ND_TUPLE::ND_TUPLE_T1S as u32 { + Tuple::T1S + } else if value == ffi::_ND_TUPLE::ND_TUPLE_T1F as u32 { + Tuple::T1F + } else if value == ffi::_ND_TUPLE::ND_TUPLE_T2 as u32 { + Tuple::T2 + } else if value == ffi::_ND_TUPLE::ND_TUPLE_T4 as u32 { + Tuple::T4 + } else if value == ffi::_ND_TUPLE::ND_TUPLE_T8 as u32 { + Tuple::T8 + } else if value == ffi::_ND_TUPLE::ND_TUPLE_FVM as u32 { + Tuple::Fvm + } else if value == ffi::_ND_TUPLE::ND_TUPLE_HVM as u32 { + Tuple::Hvm + } else if value == ffi::_ND_TUPLE::ND_TUPLE_QVM as u32 { + Tuple::Qvm + } else if value == ffi::_ND_TUPLE::ND_TUPLE_OVM as u32 { + Tuple::OVm + } else if value == ffi::_ND_TUPLE::ND_TUPLE_M128 as u32 { + Tuple::M128 + } else if value == ffi::_ND_TUPLE::ND_TUPLE_DUP as u32 { + Tuple::Dup + } else if value == ffi::_ND_TUPLE::ND_TUPLE_T1_4X as u32 { + Tuple::T14X + } else { + panic!("Unknown tuple: {}", value) + } + } +}