use std::fmt;
use std::sync::LazyLock;
use crate::named;
use crate::regs::{PhysReg, Segment};
use crate::x86_64::text::{Arg, Width};
use Fits::{Signed8, Signed32};
use Size::{
Byte, Double, DoubleQuad, Long, Quad, Single, SingleQuad, Untracked, Word, WordDouble, WordQuad,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Kind {
Reg,
Vec,
Mem,
Imm,
Dest,
Mask,
Stack,
Control,
Debug,
Seg,
}
impl Kind {
#[must_use]
pub fn of(arg: Arg) -> Self {
match arg {
Arg::Reg(_, _) | Arg::Low(_) | Arg::High(_) | Arg::Through => Kind::Reg,
Arg::Named(name) if name.starts_with("zmm") || name.starts_with("xmm") => Kind::Vec,
Arg::Named(name) if name.starts_with('k') => Kind::Mask,
Arg::Named(_) => Kind::Reg,
Arg::Xmm(_) => Kind::Vec,
Arg::Stack(_) => Kind::Stack,
Arg::Mem => Kind::Mem,
Arg::Imm | Arg::Lit(_) => Kind::Imm,
Arg::Symbol | Arg::Label => Kind::Dest,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Size {
Byte,
Word,
Long,
Quad,
Single,
Double,
WordQuad,
SingleQuad,
DoubleQuad,
WordDouble,
Untracked,
}
impl Size {
const fn prefix(self) -> Option<u8> {
match self {
Word | WordQuad => Some(0x66),
Single | SingleQuad => Some(0xF3),
Double | DoubleQuad | WordDouble => Some(0xF2),
Untracked => Some(0x3E),
Byte | Long | Quad => None,
}
}
pub(crate) const fn wide(self) -> bool {
matches!(self, Quad | WordQuad | SingleQuad | DoubleQuad)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash)]
pub enum Mode {
#[default]
Bits64,
Bits32,
}
impl Mode {
#[must_use]
pub const fn rex(self, byte: u8) -> Option<u8> {
match self {
Mode::Bits64 if byte & 0xF0 == 0x40 => Some(byte & 0x0F),
_ => None,
}
}
#[must_use]
pub const fn counted(self, byte: u8) -> Option<(&'static str, PhysReg)> {
match self {
Mode::Bits32 if byte & 0xF0 == 0x40 => {
let reg = PhysReg::new(byte & 7);
Some((if byte & 8 == 0 { "incl" } else { "decl" }, reg))
}
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Fields {
None,
Ext {
rm: u8,
ext: u8,
},
Pair {
rm: u8,
reg: u8,
},
Plus {
reg: u8,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ImmSize {
None,
Ib,
Iw,
Id,
Io,
Cd,
Cb,
Is4,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Fits {
Any,
Signed8,
Signed32,
Byte,
Word,
Long,
}
fn quietly(imm: i64, bits: u32) -> bool {
let above = !((1i64 << bits) - 1);
imm & above == 0 || imm.wrapping_neg() & above == 0
}
impl Fits {
fn holds(self, imm: i64) -> bool {
match self {
Fits::Any => true,
Signed8 => i8::try_from(imm).is_ok(),
Signed32 => i32::try_from(imm).is_ok(),
Fits::Byte => quietly(imm, 8),
Fits::Word => quietly(imm, 16),
Fits::Long => quietly(imm, 32),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Map {
Escape,
Escape38,
Escape3A,
}
impl Map {
const fn bits(self) -> u8 {
match self {
Map::Escape => 1,
Map::Escape38 => 2,
Map::Escape3A => 3,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Vex {
pub map: Map,
pub vvvv: Option<u8>,
pub long: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Length {
Xmm,
Ymm,
Zmm,
}
impl Length {
const fn bits(self) -> u8 {
match self {
Length::Xmm => 0,
Length::Ymm => 1,
Length::Zmm => 2,
}
}
#[must_use]
pub const fn bytes(self) -> u8 {
match self {
Length::Xmm => 16,
Length::Ymm => 32,
Length::Zmm => 64,
}
}
#[must_use]
pub const fn letter(self) -> char {
match self {
Length::Xmm => 'x',
Length::Ymm => 'y',
Length::Zmm => 'z',
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Tuple {
Full,
Fixed(u8),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Evex {
pub map: Map,
pub w: bool,
pub vvvv: Option<u8>,
pub tuple: Tuple,
pub vex: Option<bool>,
}
impl Evex {
const fn new(map: Map, w: bool) -> Evex {
Evex { map, w, vvvv: None, tuple: Tuple::Full, vex: None }
}
const fn third(self, at: u8) -> Evex {
Evex { vvvv: Some(at), ..self }
}
const fn fixed(self, bytes: u8) -> Evex {
Evex { tuple: Tuple::Fixed(bytes), ..self }
}
const fn or_vex(self, w: bool) -> Evex {
Evex { vex: Some(w), ..self }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Encoding {
pub mnemonic: &'static str,
pub args: &'static [Kind],
pub fits: Fits,
pub size: Size,
pub opcode: &'static [u8],
pub fields: Fields,
pub imm: ImmSize,
pub wait: bool,
pub vex: Option<Vex>,
pub evex: Option<Evex>,
}
const fn bytes(
mnemonic: &'static str,
args: &'static [Kind],
size: Size,
opcode: &'static [u8],
fields: Fields,
imm: ImmSize,
) -> Encoding {
Encoding {
mnemonic,
args,
fits: if matches!(imm, ImmSize::Ib) { Fits::Byte } else { Fits::Any },
size,
opcode,
fields,
imm,
wait: false,
vex: None,
evex: None,
}
}
const fn third(
mnemonic: &'static str,
args: &'static [Kind],
size: Size,
map: Map,
opcode: &'static [u8],
vvvv: u8,
fields: Fields,
) -> Encoding {
Encoding {
mnemonic,
args,
fits: Fits::Any,
size,
opcode,
fields,
imm: NO_IMM,
wait: false,
vex: Some(Vex { map, vvvv: Some(vvvv), long: false }),
evex: None,
}
}
const fn takes(
mnemonic: &'static str,
args: &'static [Kind],
fits: Fits,
size: Size,
opcode: &'static [u8],
fields: Fields,
imm: ImmSize,
) -> Encoding {
Encoding { mnemonic, args, fits, size, opcode, fields, imm, wait: false, vex: None, evex: None }
}
const fn waits(
mnemonic: &'static str,
args: &'static [Kind],
size: Size,
opcode: &'static [u8],
fields: Fields,
) -> Encoding {
Encoding {
mnemonic,
args,
fits: Fits::Any,
size,
opcode,
fields,
imm: NO_IMM,
wait: true,
vex: None,
evex: None,
}
}
const fn vexed(
mnemonic: &'static str,
args: &'static [Kind],
size: Size,
opcode: &'static [u8],
fields: Fields,
) -> Encoding {
Encoding {
mnemonic,
args,
fits: Fits::Any,
size,
opcode,
fields,
imm: NO_IMM,
wait: false,
vex: Some(Vex { map: Map::Escape, vvvv: None, long: false }),
evex: None,
}
}
const fn avx(
mnemonic: &'static str,
args: &'static [Kind],
size: Size,
map: Map,
opcode: &'static [u8],
vvvv: Option<u8>,
fields: Fields,
) -> Encoding {
let imm = matches!(args.first(), Some(Kind::Imm));
Encoding {
mnemonic,
args,
fits: if imm { Fits::Byte } else { Fits::Any },
size,
opcode,
fields,
imm: if imm { ImmSize::Ib } else { NO_IMM },
wait: false,
vex: Some(Vex { map, vvvv, long: false }),
evex: None,
}
}
const fn evex(
mnemonic: &'static str,
args: &'static [Kind],
size: Size,
opcode: &'static [u8],
fields: Fields,
evex: Evex,
) -> Encoding {
let imm = matches!(args.first(), Some(Kind::Imm));
Encoding {
mnemonic,
args,
fits: if imm { Fits::Byte } else { Fits::Any },
size,
opcode,
fields,
imm: if imm { ImmSize::Ib } else { NO_IMM },
wait: false,
vex: None,
evex: Some(evex),
}
}
const fn ext(rm: u8, ext: u8) -> Fields {
Fields::Ext { rm, ext }
}
const fn pair(rm: u8, reg: u8) -> Fields {
Fields::Pair { rm, reg }
}
const fn plus(reg: u8) -> Fields {
Fields::Plus { reg }
}
const NO_MODRM: Fields = Fields::None;
const NO_IMM: ImmSize = ImmSize::None;
static NO_ARGS: [Kind; 0] = [];
static R: [Kind; 1] = [Kind::Reg];
static RR: [Kind; 2] = [Kind::Reg, Kind::Reg];
static IR: [Kind; 2] = [Kind::Imm, Kind::Reg];
static IRR: [Kind; 3] = [Kind::Imm, Kind::Reg, Kind::Reg];
static IMR: [Kind; 3] = [Kind::Imm, Kind::Mem, Kind::Reg];
static RRR: [Kind; 3] = [Kind::Reg, Kind::Reg, Kind::Reg];
static MRR: [Kind; 3] = [Kind::Mem, Kind::Reg, Kind::Reg];
static RMR: [Kind; 3] = [Kind::Reg, Kind::Mem, Kind::Reg];
static MR: [Kind; 2] = [Kind::Mem, Kind::Reg];
static IM: [Kind; 2] = [Kind::Imm, Kind::Mem];
static RM: [Kind; 2] = [Kind::Reg, Kind::Mem];
static D: [Kind; 1] = [Kind::Dest];
static I: [Kind; 1] = [Kind::Imm];
static M: [Kind; 1] = [Kind::Mem];
static VV: [Kind; 2] = [Kind::Vec, Kind::Vec];
static MV: [Kind; 2] = [Kind::Mem, Kind::Vec];
static VM: [Kind; 2] = [Kind::Vec, Kind::Mem];
static RV: [Kind; 2] = [Kind::Reg, Kind::Vec];
static VR: [Kind; 2] = [Kind::Vec, Kind::Reg];
static IV: [Kind; 2] = [Kind::Imm, Kind::Vec];
static IMV: [Kind; 3] = [Kind::Imm, Kind::Mem, Kind::Vec];
static IRV: [Kind; 3] = [Kind::Imm, Kind::Reg, Kind::Vec];
static IVR: [Kind; 3] = [Kind::Imm, Kind::Vec, Kind::Reg];
static IVV: [Kind; 3] = [Kind::Imm, Kind::Vec, Kind::Vec];
static IVM: [Kind; 3] = [Kind::Imm, Kind::Vec, Kind::Mem];
static VVV: [Kind; 3] = [Kind::Vec, Kind::Vec, Kind::Vec];
static MVV: [Kind; 3] = [Kind::Mem, Kind::Vec, Kind::Vec];
static IVVV: [Kind; 4] = [Kind::Imm, Kind::Vec, Kind::Vec, Kind::Vec];
static IMVV: [Kind; 4] = [Kind::Imm, Kind::Mem, Kind::Vec, Kind::Vec];
static IRVV: [Kind; 4] = [Kind::Imm, Kind::Reg, Kind::Vec, Kind::Vec];
static RK: [Kind; 2] = [Kind::Reg, Kind::Mask];
static KR: [Kind; 2] = [Kind::Mask, Kind::Reg];
static KKK: [Kind; 3] = [Kind::Mask, Kind::Mask, Kind::Mask];
static IVVK: [Kind; 4] = [Kind::Imm, Kind::Vec, Kind::Vec, Kind::Mask];
static IMVK: [Kind; 4] = [Kind::Imm, Kind::Mem, Kind::Vec, Kind::Mask];
static VVK: [Kind; 3] = [Kind::Vec, Kind::Vec, Kind::Mask];
static MVK: [Kind; 3] = [Kind::Mem, Kind::Vec, Kind::Mask];
static KV: [Kind; 2] = [Kind::Mask, Kind::Vec];
static VVVV: [Kind; 4] = [Kind::Vec, Kind::Vec, Kind::Vec, Kind::Vec];
static VMVV: [Kind; 4] = [Kind::Vec, Kind::Mem, Kind::Vec, Kind::Vec];
static S: [Kind; 1] = [Kind::Stack];
static SS: [Kind; 2] = [Kind::Stack, Kind::Stack];
static RI: [Kind; 2] = [Kind::Reg, Kind::Imm];
static CONTROL_R: [Kind; 2] = [Kind::Control, Kind::Reg];
static R_CONTROL: [Kind; 2] = [Kind::Reg, Kind::Control];
static DEBUG_R: [Kind; 2] = [Kind::Debug, Kind::Reg];
static R_DEBUG: [Kind; 2] = [Kind::Reg, Kind::Debug];
static SEG_R: [Kind; 2] = [Kind::Seg, Kind::Reg];
static R_SEG: [Kind; 2] = [Kind::Reg, Kind::Seg];
static SEG_M: [Kind; 2] = [Kind::Seg, Kind::Mem];
static M_SEG: [Kind; 2] = [Kind::Mem, Kind::Seg];
static ENCODINGS: &[Encoding] = &[
takes("movb", &IR, Fits::Byte, Byte, &[0xB0], plus(1), ImmSize::Ib),
takes("movw", &IR, Fits::Word, Word, &[0xB8], plus(1), ImmSize::Iw),
takes("movl", &IR, Fits::Long, Long, &[0xB8], plus(1), ImmSize::Id),
takes("movq", &IR, Signed32, Quad, &[0xC7], ext(1, 0), ImmSize::Id),
bytes("movq", &IR, Quad, &[0xB8], plus(1), ImmSize::Io),
takes("movb", &IM, Fits::Byte, Byte, &[0xC6], ext(1, 0), ImmSize::Ib),
takes("movw", &IM, Fits::Word, Word, &[0xC7], ext(1, 0), ImmSize::Iw),
takes("movl", &IM, Fits::Long, Long, &[0xC7], ext(1, 0), ImmSize::Id),
takes("movq", &IM, Signed32, Quad, &[0xC7], ext(1, 0), ImmSize::Id),
bytes("movabsq", &IR, Quad, &[0xB8], plus(1), ImmSize::Io),
bytes("addb", &RR, Byte, &[0x00], pair(1, 0), NO_IMM),
bytes("addw", &RR, Word, &[0x01], pair(1, 0), NO_IMM),
bytes("addl", &RR, Long, &[0x01], pair(1, 0), NO_IMM),
bytes("addq", &RR, Quad, &[0x01], pair(1, 0), NO_IMM),
bytes("subb", &RR, Byte, &[0x28], pair(1, 0), NO_IMM),
bytes("subw", &RR, Word, &[0x29], pair(1, 0), NO_IMM),
bytes("subl", &RR, Long, &[0x29], pair(1, 0), NO_IMM),
bytes("subq", &RR, Quad, &[0x29], pair(1, 0), NO_IMM),
bytes("andb", &RR, Byte, &[0x20], pair(1, 0), NO_IMM),
bytes("andw", &RR, Word, &[0x21], pair(1, 0), NO_IMM),
bytes("andl", &RR, Long, &[0x21], pair(1, 0), NO_IMM),
bytes("andq", &RR, Quad, &[0x21], pair(1, 0), NO_IMM),
bytes("orb", &RR, Byte, &[0x08], pair(1, 0), NO_IMM),
bytes("orw", &RR, Word, &[0x09], pair(1, 0), NO_IMM),
bytes("orl", &RR, Long, &[0x09], pair(1, 0), NO_IMM),
bytes("orq", &RR, Quad, &[0x09], pair(1, 0), NO_IMM),
bytes("xorb", &RR, Byte, &[0x30], pair(1, 0), NO_IMM),
bytes("xorw", &RR, Word, &[0x31], pair(1, 0), NO_IMM),
bytes("xorl", &RR, Long, &[0x31], pair(1, 0), NO_IMM),
bytes("xorq", &RR, Quad, &[0x31], pair(1, 0), NO_IMM),
bytes("adcb", &RR, Byte, &[0x10], pair(1, 0), NO_IMM),
bytes("adcw", &RR, Word, &[0x11], pair(1, 0), NO_IMM),
bytes("adcl", &RR, Long, &[0x11], pair(1, 0), NO_IMM),
bytes("adcq", &RR, Quad, &[0x11], pair(1, 0), NO_IMM),
bytes("sbbb", &RR, Byte, &[0x18], pair(1, 0), NO_IMM),
bytes("sbbw", &RR, Word, &[0x19], pair(1, 0), NO_IMM),
bytes("sbbl", &RR, Long, &[0x19], pair(1, 0), NO_IMM),
bytes("sbbq", &RR, Quad, &[0x19], pair(1, 0), NO_IMM),
bytes("imulw", &RR, Word, &[0x0F, 0xAF], pair(0, 1), NO_IMM),
bytes("imull", &RR, Long, &[0x0F, 0xAF], pair(0, 1), NO_IMM),
bytes("imulq", &RR, Quad, &[0x0F, 0xAF], pair(0, 1), NO_IMM),
bytes("addb", &MR, Byte, &[0x02], pair(0, 1), NO_IMM),
bytes("addw", &MR, Word, &[0x03], pair(0, 1), NO_IMM),
bytes("addl", &MR, Long, &[0x03], pair(0, 1), NO_IMM),
bytes("addq", &MR, Quad, &[0x03], pair(0, 1), NO_IMM),
bytes("subb", &MR, Byte, &[0x2A], pair(0, 1), NO_IMM),
bytes("subw", &MR, Word, &[0x2B], pair(0, 1), NO_IMM),
bytes("subl", &MR, Long, &[0x2B], pair(0, 1), NO_IMM),
bytes("subq", &MR, Quad, &[0x2B], pair(0, 1), NO_IMM),
bytes("andb", &MR, Byte, &[0x22], pair(0, 1), NO_IMM),
bytes("andw", &MR, Word, &[0x23], pair(0, 1), NO_IMM),
bytes("andl", &MR, Long, &[0x23], pair(0, 1), NO_IMM),
bytes("andq", &MR, Quad, &[0x23], pair(0, 1), NO_IMM),
bytes("orb", &MR, Byte, &[0x0A], pair(0, 1), NO_IMM),
bytes("orw", &MR, Word, &[0x0B], pair(0, 1), NO_IMM),
bytes("orl", &MR, Long, &[0x0B], pair(0, 1), NO_IMM),
bytes("orq", &MR, Quad, &[0x0B], pair(0, 1), NO_IMM),
bytes("xorb", &MR, Byte, &[0x32], pair(0, 1), NO_IMM),
bytes("xorw", &MR, Word, &[0x33], pair(0, 1), NO_IMM),
bytes("xorl", &MR, Long, &[0x33], pair(0, 1), NO_IMM),
bytes("xorq", &MR, Quad, &[0x33], pair(0, 1), NO_IMM),
bytes("adcb", &MR, Byte, &[0x12], pair(0, 1), NO_IMM),
bytes("adcw", &MR, Word, &[0x13], pair(0, 1), NO_IMM),
bytes("adcl", &MR, Long, &[0x13], pair(0, 1), NO_IMM),
bytes("adcq", &MR, Quad, &[0x13], pair(0, 1), NO_IMM),
bytes("sbbb", &MR, Byte, &[0x1A], pair(0, 1), NO_IMM),
bytes("sbbw", &MR, Word, &[0x1B], pair(0, 1), NO_IMM),
bytes("sbbl", &MR, Long, &[0x1B], pair(0, 1), NO_IMM),
bytes("sbbq", &MR, Quad, &[0x1B], pair(0, 1), NO_IMM),
bytes("imulw", &MR, Word, &[0x0F, 0xAF], pair(0, 1), NO_IMM),
bytes("imull", &MR, Long, &[0x0F, 0xAF], pair(0, 1), NO_IMM),
bytes("imulq", &MR, Quad, &[0x0F, 0xAF], pair(0, 1), NO_IMM),
bytes("cmpb", &MR, Byte, &[0x3A], pair(0, 1), NO_IMM),
bytes("cmpw", &MR, Word, &[0x3B], pair(0, 1), NO_IMM),
bytes("cmpl", &MR, Long, &[0x3B], pair(0, 1), NO_IMM),
bytes("cmpq", &MR, Quad, &[0x3B], pair(0, 1), NO_IMM),
bytes("addb", &RM, Byte, &[0x00], pair(1, 0), NO_IMM),
bytes("addw", &RM, Word, &[0x01], pair(1, 0), NO_IMM),
bytes("addl", &RM, Long, &[0x01], pair(1, 0), NO_IMM),
bytes("addq", &RM, Quad, &[0x01], pair(1, 0), NO_IMM),
bytes("orb", &RM, Byte, &[0x08], pair(1, 0), NO_IMM),
bytes("orw", &RM, Word, &[0x09], pair(1, 0), NO_IMM),
bytes("orl", &RM, Long, &[0x09], pair(1, 0), NO_IMM),
bytes("orq", &RM, Quad, &[0x09], pair(1, 0), NO_IMM),
bytes("adcb", &RM, Byte, &[0x10], pair(1, 0), NO_IMM),
bytes("adcw", &RM, Word, &[0x11], pair(1, 0), NO_IMM),
bytes("adcl", &RM, Long, &[0x11], pair(1, 0), NO_IMM),
bytes("adcq", &RM, Quad, &[0x11], pair(1, 0), NO_IMM),
bytes("sbbb", &RM, Byte, &[0x18], pair(1, 0), NO_IMM),
bytes("sbbw", &RM, Word, &[0x19], pair(1, 0), NO_IMM),
bytes("sbbl", &RM, Long, &[0x19], pair(1, 0), NO_IMM),
bytes("sbbq", &RM, Quad, &[0x19], pair(1, 0), NO_IMM),
bytes("andb", &RM, Byte, &[0x20], pair(1, 0), NO_IMM),
bytes("andw", &RM, Word, &[0x21], pair(1, 0), NO_IMM),
bytes("andl", &RM, Long, &[0x21], pair(1, 0), NO_IMM),
bytes("andq", &RM, Quad, &[0x21], pair(1, 0), NO_IMM),
bytes("subb", &RM, Byte, &[0x28], pair(1, 0), NO_IMM),
bytes("subw", &RM, Word, &[0x29], pair(1, 0), NO_IMM),
bytes("subl", &RM, Long, &[0x29], pair(1, 0), NO_IMM),
bytes("subq", &RM, Quad, &[0x29], pair(1, 0), NO_IMM),
bytes("xorb", &RM, Byte, &[0x30], pair(1, 0), NO_IMM),
bytes("xorw", &RM, Word, &[0x31], pair(1, 0), NO_IMM),
bytes("xorl", &RM, Long, &[0x31], pair(1, 0), NO_IMM),
bytes("xorq", &RM, Quad, &[0x31], pair(1, 0), NO_IMM),
bytes("cmpb", &RM, Byte, &[0x38], pair(1, 0), NO_IMM),
bytes("cmpw", &RM, Word, &[0x39], pair(1, 0), NO_IMM),
bytes("cmpl", &RM, Long, &[0x39], pair(1, 0), NO_IMM),
bytes("cmpq", &RM, Quad, &[0x39], pair(1, 0), NO_IMM),
takes("addb", &IR, Fits::Byte, Byte, &[0x80], ext(1, 0), ImmSize::Ib),
takes("addw", &IR, Signed8, Word, &[0x83], ext(1, 0), ImmSize::Ib),
takes("addw", &IR, Fits::Word, Word, &[0x81], ext(1, 0), ImmSize::Iw),
takes("addl", &IR, Signed8, Long, &[0x83], ext(1, 0), ImmSize::Ib),
takes("addl", &IR, Fits::Long, Long, &[0x81], ext(1, 0), ImmSize::Id),
takes("addq", &IR, Signed8, Quad, &[0x83], ext(1, 0), ImmSize::Ib),
takes("addq", &IR, Signed32, Quad, &[0x81], ext(1, 0), ImmSize::Id),
takes("subb", &IR, Fits::Byte, Byte, &[0x80], ext(1, 5), ImmSize::Ib),
takes("subw", &IR, Signed8, Word, &[0x83], ext(1, 5), ImmSize::Ib),
takes("subw", &IR, Fits::Word, Word, &[0x81], ext(1, 5), ImmSize::Iw),
takes("subl", &IR, Signed8, Long, &[0x83], ext(1, 5), ImmSize::Ib),
takes("subl", &IR, Fits::Long, Long, &[0x81], ext(1, 5), ImmSize::Id),
takes("subq", &IR, Signed8, Quad, &[0x83], ext(1, 5), ImmSize::Ib),
takes("subq", &IR, Signed32, Quad, &[0x81], ext(1, 5), ImmSize::Id),
takes("andb", &IR, Fits::Byte, Byte, &[0x80], ext(1, 4), ImmSize::Ib),
takes("andw", &IR, Signed8, Word, &[0x83], ext(1, 4), ImmSize::Ib),
takes("andw", &IR, Fits::Word, Word, &[0x81], ext(1, 4), ImmSize::Iw),
takes("andl", &IR, Signed8, Long, &[0x83], ext(1, 4), ImmSize::Ib),
takes("andl", &IR, Fits::Long, Long, &[0x81], ext(1, 4), ImmSize::Id),
takes("andq", &IR, Signed8, Quad, &[0x83], ext(1, 4), ImmSize::Ib),
takes("andq", &IR, Signed32, Quad, &[0x81], ext(1, 4), ImmSize::Id),
takes("orb", &IR, Fits::Byte, Byte, &[0x80], ext(1, 1), ImmSize::Ib),
takes("orw", &IR, Signed8, Word, &[0x83], ext(1, 1), ImmSize::Ib),
takes("orw", &IR, Fits::Word, Word, &[0x81], ext(1, 1), ImmSize::Iw),
takes("orl", &IR, Signed8, Long, &[0x83], ext(1, 1), ImmSize::Ib),
takes("orl", &IR, Fits::Long, Long, &[0x81], ext(1, 1), ImmSize::Id),
takes("orq", &IR, Signed8, Quad, &[0x83], ext(1, 1), ImmSize::Ib),
takes("orq", &IR, Signed32, Quad, &[0x81], ext(1, 1), ImmSize::Id),
takes("xorb", &IR, Fits::Byte, Byte, &[0x80], ext(1, 6), ImmSize::Ib),
takes("xorw", &IR, Signed8, Word, &[0x83], ext(1, 6), ImmSize::Ib),
takes("xorw", &IR, Fits::Word, Word, &[0x81], ext(1, 6), ImmSize::Iw),
takes("xorl", &IR, Signed8, Long, &[0x83], ext(1, 6), ImmSize::Ib),
takes("xorl", &IR, Fits::Long, Long, &[0x81], ext(1, 6), ImmSize::Id),
takes("xorq", &IR, Signed8, Quad, &[0x83], ext(1, 6), ImmSize::Ib),
takes("xorq", &IR, Signed32, Quad, &[0x81], ext(1, 6), ImmSize::Id),
takes("adcb", &IR, Fits::Byte, Byte, &[0x80], ext(1, 2), ImmSize::Ib),
takes("adcw", &IR, Signed8, Word, &[0x83], ext(1, 2), ImmSize::Ib),
takes("adcw", &IR, Fits::Word, Word, &[0x81], ext(1, 2), ImmSize::Iw),
takes("adcl", &IR, Signed8, Long, &[0x83], ext(1, 2), ImmSize::Ib),
takes("adcl", &IR, Fits::Long, Long, &[0x81], ext(1, 2), ImmSize::Id),
takes("adcq", &IR, Signed8, Quad, &[0x83], ext(1, 2), ImmSize::Ib),
takes("adcq", &IR, Signed32, Quad, &[0x81], ext(1, 2), ImmSize::Id),
takes("sbbb", &IR, Fits::Byte, Byte, &[0x80], ext(1, 3), ImmSize::Ib),
takes("sbbw", &IR, Signed8, Word, &[0x83], ext(1, 3), ImmSize::Ib),
takes("sbbw", &IR, Fits::Word, Word, &[0x81], ext(1, 3), ImmSize::Iw),
takes("sbbl", &IR, Signed8, Long, &[0x83], ext(1, 3), ImmSize::Ib),
takes("sbbl", &IR, Fits::Long, Long, &[0x81], ext(1, 3), ImmSize::Id),
takes("sbbq", &IR, Signed8, Quad, &[0x83], ext(1, 3), ImmSize::Ib),
takes("sbbq", &IR, Signed32, Quad, &[0x81], ext(1, 3), ImmSize::Id),
takes("cmpb", &IR, Fits::Byte, Byte, &[0x80], ext(1, 7), ImmSize::Ib),
takes("cmpw", &IR, Signed8, Word, &[0x83], ext(1, 7), ImmSize::Ib),
takes("cmpw", &IR, Fits::Word, Word, &[0x81], ext(1, 7), ImmSize::Iw),
takes("cmpl", &IR, Signed8, Long, &[0x83], ext(1, 7), ImmSize::Ib),
takes("cmpl", &IR, Fits::Long, Long, &[0x81], ext(1, 7), ImmSize::Id),
takes("cmpq", &IR, Signed8, Quad, &[0x83], ext(1, 7), ImmSize::Ib),
takes("cmpq", &IR, Signed32, Quad, &[0x81], ext(1, 7), ImmSize::Id),
takes("addb", &IM, Fits::Byte, Byte, &[0x80], ext(1, 0), ImmSize::Ib),
takes("addw", &IM, Signed8, Word, &[0x83], ext(1, 0), ImmSize::Ib),
takes("addw", &IM, Fits::Word, Word, &[0x81], ext(1, 0), ImmSize::Iw),
takes("addl", &IM, Signed8, Long, &[0x83], ext(1, 0), ImmSize::Ib),
takes("addl", &IM, Fits::Long, Long, &[0x81], ext(1, 0), ImmSize::Id),
takes("addq", &IM, Signed8, Quad, &[0x83], ext(1, 0), ImmSize::Ib),
takes("addq", &IM, Signed32, Quad, &[0x81], ext(1, 0), ImmSize::Id),
takes("orb", &IM, Fits::Byte, Byte, &[0x80], ext(1, 1), ImmSize::Ib),
takes("orw", &IM, Signed8, Word, &[0x83], ext(1, 1), ImmSize::Ib),
takes("orw", &IM, Fits::Word, Word, &[0x81], ext(1, 1), ImmSize::Iw),
takes("orl", &IM, Signed8, Long, &[0x83], ext(1, 1), ImmSize::Ib),
takes("orl", &IM, Fits::Long, Long, &[0x81], ext(1, 1), ImmSize::Id),
takes("orq", &IM, Signed8, Quad, &[0x83], ext(1, 1), ImmSize::Ib),
takes("orq", &IM, Signed32, Quad, &[0x81], ext(1, 1), ImmSize::Id),
takes("adcb", &IM, Fits::Byte, Byte, &[0x80], ext(1, 2), ImmSize::Ib),
takes("adcw", &IM, Signed8, Word, &[0x83], ext(1, 2), ImmSize::Ib),
takes("adcw", &IM, Fits::Word, Word, &[0x81], ext(1, 2), ImmSize::Iw),
takes("adcl", &IM, Signed8, Long, &[0x83], ext(1, 2), ImmSize::Ib),
takes("adcl", &IM, Fits::Long, Long, &[0x81], ext(1, 2), ImmSize::Id),
takes("adcq", &IM, Signed8, Quad, &[0x83], ext(1, 2), ImmSize::Ib),
takes("adcq", &IM, Signed32, Quad, &[0x81], ext(1, 2), ImmSize::Id),
takes("sbbb", &IM, Fits::Byte, Byte, &[0x80], ext(1, 3), ImmSize::Ib),
takes("sbbw", &IM, Signed8, Word, &[0x83], ext(1, 3), ImmSize::Ib),
takes("sbbw", &IM, Fits::Word, Word, &[0x81], ext(1, 3), ImmSize::Iw),
takes("sbbl", &IM, Signed8, Long, &[0x83], ext(1, 3), ImmSize::Ib),
takes("sbbl", &IM, Fits::Long, Long, &[0x81], ext(1, 3), ImmSize::Id),
takes("sbbq", &IM, Signed8, Quad, &[0x83], ext(1, 3), ImmSize::Ib),
takes("sbbq", &IM, Signed32, Quad, &[0x81], ext(1, 3), ImmSize::Id),
takes("andb", &IM, Fits::Byte, Byte, &[0x80], ext(1, 4), ImmSize::Ib),
takes("andw", &IM, Signed8, Word, &[0x83], ext(1, 4), ImmSize::Ib),
takes("andw", &IM, Fits::Word, Word, &[0x81], ext(1, 4), ImmSize::Iw),
takes("andl", &IM, Signed8, Long, &[0x83], ext(1, 4), ImmSize::Ib),
takes("andl", &IM, Fits::Long, Long, &[0x81], ext(1, 4), ImmSize::Id),
takes("andq", &IM, Signed8, Quad, &[0x83], ext(1, 4), ImmSize::Ib),
takes("andq", &IM, Signed32, Quad, &[0x81], ext(1, 4), ImmSize::Id),
takes("subb", &IM, Fits::Byte, Byte, &[0x80], ext(1, 5), ImmSize::Ib),
takes("subw", &IM, Signed8, Word, &[0x83], ext(1, 5), ImmSize::Ib),
takes("subw", &IM, Fits::Word, Word, &[0x81], ext(1, 5), ImmSize::Iw),
takes("subl", &IM, Signed8, Long, &[0x83], ext(1, 5), ImmSize::Ib),
takes("subl", &IM, Fits::Long, Long, &[0x81], ext(1, 5), ImmSize::Id),
takes("subq", &IM, Signed8, Quad, &[0x83], ext(1, 5), ImmSize::Ib),
takes("subq", &IM, Signed32, Quad, &[0x81], ext(1, 5), ImmSize::Id),
takes("xorb", &IM, Fits::Byte, Byte, &[0x80], ext(1, 6), ImmSize::Ib),
takes("xorw", &IM, Signed8, Word, &[0x83], ext(1, 6), ImmSize::Ib),
takes("xorw", &IM, Fits::Word, Word, &[0x81], ext(1, 6), ImmSize::Iw),
takes("xorl", &IM, Signed8, Long, &[0x83], ext(1, 6), ImmSize::Ib),
takes("xorl", &IM, Fits::Long, Long, &[0x81], ext(1, 6), ImmSize::Id),
takes("xorq", &IM, Signed8, Quad, &[0x83], ext(1, 6), ImmSize::Ib),
takes("xorq", &IM, Signed32, Quad, &[0x81], ext(1, 6), ImmSize::Id),
takes("cmpb", &IM, Fits::Byte, Byte, &[0x80], ext(1, 7), ImmSize::Ib),
takes("cmpw", &IM, Signed8, Word, &[0x83], ext(1, 7), ImmSize::Ib),
takes("cmpw", &IM, Fits::Word, Word, &[0x81], ext(1, 7), ImmSize::Iw),
takes("cmpl", &IM, Signed8, Long, &[0x83], ext(1, 7), ImmSize::Ib),
takes("cmpl", &IM, Fits::Long, Long, &[0x81], ext(1, 7), ImmSize::Id),
takes("cmpq", &IM, Signed8, Quad, &[0x83], ext(1, 7), ImmSize::Ib),
takes("cmpq", &IM, Signed32, Quad, &[0x81], ext(1, 7), ImmSize::Id),
takes("imulw", &IRR, Signed8, Word, &[0x6B], pair(1, 2), ImmSize::Ib),
takes("imulw", &IRR, Fits::Word, Word, &[0x69], pair(1, 2), ImmSize::Iw),
takes("imull", &IRR, Signed8, Long, &[0x6B], pair(1, 2), ImmSize::Ib),
takes("imull", &IRR, Fits::Long, Long, &[0x69], pair(1, 2), ImmSize::Id),
takes("imulq", &IRR, Signed8, Quad, &[0x6B], pair(1, 2), ImmSize::Ib),
takes("imulq", &IRR, Signed32, Quad, &[0x69], pair(1, 2), ImmSize::Id),
takes("imulw", &IMR, Signed8, Word, &[0x6B], pair(1, 2), ImmSize::Ib),
takes("imulw", &IMR, Fits::Word, Word, &[0x69], pair(1, 2), ImmSize::Iw),
takes("imull", &IMR, Signed8, Long, &[0x6B], pair(1, 2), ImmSize::Ib),
takes("imull", &IMR, Fits::Long, Long, &[0x69], pair(1, 2), ImmSize::Id),
takes("imulq", &IMR, Signed8, Quad, &[0x6B], pair(1, 2), ImmSize::Ib),
takes("imulq", &IMR, Signed32, Quad, &[0x69], pair(1, 2), ImmSize::Id),
bytes("negb", &R, Byte, &[0xF6], ext(0, 3), NO_IMM),
bytes("negw", &R, Word, &[0xF7], ext(0, 3), NO_IMM),
bytes("negl", &R, Long, &[0xF7], ext(0, 3), NO_IMM),
bytes("negq", &R, Quad, &[0xF7], ext(0, 3), NO_IMM),
bytes("notb", &R, Byte, &[0xF6], ext(0, 2), NO_IMM),
bytes("notw", &R, Word, &[0xF7], ext(0, 2), NO_IMM),
bytes("notl", &R, Long, &[0xF7], ext(0, 2), NO_IMM),
bytes("notq", &R, Quad, &[0xF7], ext(0, 2), NO_IMM),
bytes("incb", &R, Byte, &[0xFE], ext(0, 0), NO_IMM),
bytes("incw", &R, Word, &[0xFF], ext(0, 0), NO_IMM),
bytes("incl", &R, Long, &[0xFF], ext(0, 0), NO_IMM),
bytes("incq", &R, Quad, &[0xFF], ext(0, 0), NO_IMM),
bytes("decb", &R, Byte, &[0xFE], ext(0, 1), NO_IMM),
bytes("decw", &R, Word, &[0xFF], ext(0, 1), NO_IMM),
bytes("decl", &R, Long, &[0xFF], ext(0, 1), NO_IMM),
bytes("decq", &R, Quad, &[0xFF], ext(0, 1), NO_IMM),
bytes("cbtw", &NO_ARGS, Word, &[0x98], NO_MODRM, NO_IMM),
bytes("cwtd", &NO_ARGS, Word, &[0x99], NO_MODRM, NO_IMM),
bytes("cltd", &NO_ARGS, Long, &[0x99], NO_MODRM, NO_IMM),
bytes("cqto", &NO_ARGS, Quad, &[0x99], NO_MODRM, NO_IMM),
bytes("cwtl", &NO_ARGS, Long, &[0x98], NO_MODRM, NO_IMM),
bytes("cltq", &NO_ARGS, Quad, &[0x98], NO_MODRM, NO_IMM),
bytes("idivb", &R, Byte, &[0xF6], ext(0, 7), NO_IMM),
bytes("idivw", &R, Word, &[0xF7], ext(0, 7), NO_IMM),
bytes("idivl", &R, Long, &[0xF7], ext(0, 7), NO_IMM),
bytes("idivq", &R, Quad, &[0xF7], ext(0, 7), NO_IMM),
bytes("divb", &R, Byte, &[0xF6], ext(0, 6), NO_IMM),
bytes("divw", &R, Word, &[0xF7], ext(0, 6), NO_IMM),
bytes("divl", &R, Long, &[0xF7], ext(0, 6), NO_IMM),
bytes("divq", &R, Quad, &[0xF7], ext(0, 6), NO_IMM),
bytes("mulb", &R, Byte, &[0xF6], ext(0, 4), NO_IMM),
bytes("mulw", &R, Word, &[0xF7], ext(0, 4), NO_IMM),
bytes("mull", &R, Long, &[0xF7], ext(0, 4), NO_IMM),
bytes("mulq", &R, Quad, &[0xF7], ext(0, 4), NO_IMM),
bytes("imulb", &R, Byte, &[0xF6], ext(0, 5), NO_IMM),
bytes("imulw", &R, Word, &[0xF7], ext(0, 5), NO_IMM),
bytes("imull", &R, Long, &[0xF7], ext(0, 5), NO_IMM),
bytes("imulq", &R, Quad, &[0xF7], ext(0, 5), NO_IMM),
bytes("negb", &M, Byte, &[0xF6], ext(0, 3), NO_IMM),
bytes("negw", &M, Word, &[0xF7], ext(0, 3), NO_IMM),
bytes("negl", &M, Long, &[0xF7], ext(0, 3), NO_IMM),
bytes("negq", &M, Quad, &[0xF7], ext(0, 3), NO_IMM),
bytes("notb", &M, Byte, &[0xF6], ext(0, 2), NO_IMM),
bytes("notw", &M, Word, &[0xF7], ext(0, 2), NO_IMM),
bytes("notl", &M, Long, &[0xF7], ext(0, 2), NO_IMM),
bytes("notq", &M, Quad, &[0xF7], ext(0, 2), NO_IMM),
bytes("mulb", &M, Byte, &[0xF6], ext(0, 4), NO_IMM),
bytes("mulw", &M, Word, &[0xF7], ext(0, 4), NO_IMM),
bytes("mull", &M, Long, &[0xF7], ext(0, 4), NO_IMM),
bytes("mulq", &M, Quad, &[0xF7], ext(0, 4), NO_IMM),
bytes("imulb", &M, Byte, &[0xF6], ext(0, 5), NO_IMM),
bytes("imulw", &M, Word, &[0xF7], ext(0, 5), NO_IMM),
bytes("imull", &M, Long, &[0xF7], ext(0, 5), NO_IMM),
bytes("imulq", &M, Quad, &[0xF7], ext(0, 5), NO_IMM),
bytes("divb", &M, Byte, &[0xF6], ext(0, 6), NO_IMM),
bytes("divw", &M, Word, &[0xF7], ext(0, 6), NO_IMM),
bytes("divl", &M, Long, &[0xF7], ext(0, 6), NO_IMM),
bytes("divq", &M, Quad, &[0xF7], ext(0, 6), NO_IMM),
bytes("idivb", &M, Byte, &[0xF6], ext(0, 7), NO_IMM),
bytes("idivw", &M, Word, &[0xF7], ext(0, 7), NO_IMM),
bytes("idivl", &M, Long, &[0xF7], ext(0, 7), NO_IMM),
bytes("idivq", &M, Quad, &[0xF7], ext(0, 7), NO_IMM),
bytes("incb", &M, Byte, &[0xFE], ext(0, 0), NO_IMM),
bytes("incw", &M, Word, &[0xFF], ext(0, 0), NO_IMM),
bytes("incl", &M, Long, &[0xFF], ext(0, 0), NO_IMM),
bytes("incq", &M, Quad, &[0xFF], ext(0, 0), NO_IMM),
bytes("decb", &M, Byte, &[0xFE], ext(0, 1), NO_IMM),
bytes("decw", &M, Word, &[0xFF], ext(0, 1), NO_IMM),
bytes("decl", &M, Long, &[0xFF], ext(0, 1), NO_IMM),
bytes("decq", &M, Quad, &[0xFF], ext(0, 1), NO_IMM),
takes("shlb", &IR, Fits::Byte, Byte, &[0xC0], ext(1, 4), ImmSize::Ib),
takes("shlw", &IR, Fits::Byte, Word, &[0xC1], ext(1, 4), ImmSize::Ib),
takes("shll", &IR, Fits::Byte, Long, &[0xC1], ext(1, 4), ImmSize::Ib),
takes("shlq", &IR, Fits::Byte, Quad, &[0xC1], ext(1, 4), ImmSize::Ib),
takes("shrb", &IR, Fits::Byte, Byte, &[0xC0], ext(1, 5), ImmSize::Ib),
takes("shrw", &IR, Fits::Byte, Word, &[0xC1], ext(1, 5), ImmSize::Ib),
takes("shrl", &IR, Fits::Byte, Long, &[0xC1], ext(1, 5), ImmSize::Ib),
takes("shrq", &IR, Fits::Byte, Quad, &[0xC1], ext(1, 5), ImmSize::Ib),
takes("sarb", &IR, Fits::Byte, Byte, &[0xC0], ext(1, 7), ImmSize::Ib),
takes("sarw", &IR, Fits::Byte, Word, &[0xC1], ext(1, 7), ImmSize::Ib),
takes("sarl", &IR, Fits::Byte, Long, &[0xC1], ext(1, 7), ImmSize::Ib),
takes("sarq", &IR, Fits::Byte, Quad, &[0xC1], ext(1, 7), ImmSize::Ib),
takes("rolb", &IR, Fits::Byte, Byte, &[0xC0], ext(1, 0), ImmSize::Ib),
takes("rolw", &IR, Fits::Byte, Word, &[0xC1], ext(1, 0), ImmSize::Ib),
takes("roll", &IR, Fits::Byte, Long, &[0xC1], ext(1, 0), ImmSize::Ib),
takes("rolq", &IR, Fits::Byte, Quad, &[0xC1], ext(1, 0), ImmSize::Ib),
takes("rorb", &IR, Fits::Byte, Byte, &[0xC0], ext(1, 1), ImmSize::Ib),
takes("rorw", &IR, Fits::Byte, Word, &[0xC1], ext(1, 1), ImmSize::Ib),
takes("rorl", &IR, Fits::Byte, Long, &[0xC1], ext(1, 1), ImmSize::Ib),
takes("rorq", &IR, Fits::Byte, Quad, &[0xC1], ext(1, 1), ImmSize::Ib),
bytes("shlb", &RR, Byte, &[0xD2], ext(1, 4), NO_IMM),
bytes("shlw", &RR, Word, &[0xD3], ext(1, 4), NO_IMM),
bytes("shll", &RR, Long, &[0xD3], ext(1, 4), NO_IMM),
bytes("shlq", &RR, Quad, &[0xD3], ext(1, 4), NO_IMM),
bytes("shrb", &RR, Byte, &[0xD2], ext(1, 5), NO_IMM),
bytes("shrw", &RR, Word, &[0xD3], ext(1, 5), NO_IMM),
bytes("shrl", &RR, Long, &[0xD3], ext(1, 5), NO_IMM),
bytes("shrq", &RR, Quad, &[0xD3], ext(1, 5), NO_IMM),
bytes("sarb", &RR, Byte, &[0xD2], ext(1, 7), NO_IMM),
bytes("sarw", &RR, Word, &[0xD3], ext(1, 7), NO_IMM),
bytes("sarl", &RR, Long, &[0xD3], ext(1, 7), NO_IMM),
bytes("sarq", &RR, Quad, &[0xD3], ext(1, 7), NO_IMM),
bytes("rolb", &RR, Byte, &[0xD2], ext(1, 0), NO_IMM),
bytes("rolw", &RR, Word, &[0xD3], ext(1, 0), NO_IMM),
bytes("roll", &RR, Long, &[0xD3], ext(1, 0), NO_IMM),
bytes("rolq", &RR, Quad, &[0xD3], ext(1, 0), NO_IMM),
bytes("rorb", &RR, Byte, &[0xD2], ext(1, 1), NO_IMM),
bytes("rorw", &RR, Word, &[0xD3], ext(1, 1), NO_IMM),
bytes("rorl", &RR, Long, &[0xD3], ext(1, 1), NO_IMM),
bytes("rorq", &RR, Quad, &[0xD3], ext(1, 1), NO_IMM),
takes("rclb", &IR, Fits::Byte, Byte, &[0xC0], ext(1, 2), ImmSize::Ib),
takes("rclw", &IR, Fits::Byte, Word, &[0xC1], ext(1, 2), ImmSize::Ib),
takes("rcll", &IR, Fits::Byte, Long, &[0xC1], ext(1, 2), ImmSize::Ib),
takes("rclq", &IR, Fits::Byte, Quad, &[0xC1], ext(1, 2), ImmSize::Ib),
takes("rcrb", &IR, Fits::Byte, Byte, &[0xC0], ext(1, 3), ImmSize::Ib),
takes("rcrw", &IR, Fits::Byte, Word, &[0xC1], ext(1, 3), ImmSize::Ib),
takes("rcrl", &IR, Fits::Byte, Long, &[0xC1], ext(1, 3), ImmSize::Ib),
takes("rcrq", &IR, Fits::Byte, Quad, &[0xC1], ext(1, 3), ImmSize::Ib),
bytes("rclb", &RR, Byte, &[0xD2], ext(1, 2), NO_IMM),
bytes("rclw", &RR, Word, &[0xD3], ext(1, 2), NO_IMM),
bytes("rcll", &RR, Long, &[0xD3], ext(1, 2), NO_IMM),
bytes("rclq", &RR, Quad, &[0xD3], ext(1, 2), NO_IMM),
bytes("rcrb", &RR, Byte, &[0xD2], ext(1, 3), NO_IMM),
bytes("rcrw", &RR, Word, &[0xD3], ext(1, 3), NO_IMM),
bytes("rcrl", &RR, Long, &[0xD3], ext(1, 3), NO_IMM),
bytes("rcrq", &RR, Quad, &[0xD3], ext(1, 3), NO_IMM),
bytes("rolb", &R, Byte, &[0xD0], ext(0, 0), NO_IMM),
bytes("rolw", &R, Word, &[0xD1], ext(0, 0), NO_IMM),
bytes("roll", &R, Long, &[0xD1], ext(0, 0), NO_IMM),
bytes("rolq", &R, Quad, &[0xD1], ext(0, 0), NO_IMM),
bytes("rorb", &R, Byte, &[0xD0], ext(0, 1), NO_IMM),
bytes("rorw", &R, Word, &[0xD1], ext(0, 1), NO_IMM),
bytes("rorl", &R, Long, &[0xD1], ext(0, 1), NO_IMM),
bytes("rorq", &R, Quad, &[0xD1], ext(0, 1), NO_IMM),
bytes("rclb", &R, Byte, &[0xD0], ext(0, 2), NO_IMM),
bytes("rclw", &R, Word, &[0xD1], ext(0, 2), NO_IMM),
bytes("rcll", &R, Long, &[0xD1], ext(0, 2), NO_IMM),
bytes("rclq", &R, Quad, &[0xD1], ext(0, 2), NO_IMM),
bytes("rcrb", &R, Byte, &[0xD0], ext(0, 3), NO_IMM),
bytes("rcrw", &R, Word, &[0xD1], ext(0, 3), NO_IMM),
bytes("rcrl", &R, Long, &[0xD1], ext(0, 3), NO_IMM),
bytes("rcrq", &R, Quad, &[0xD1], ext(0, 3), NO_IMM),
bytes("shlb", &R, Byte, &[0xD0], ext(0, 4), NO_IMM),
bytes("shlw", &R, Word, &[0xD1], ext(0, 4), NO_IMM),
bytes("shll", &R, Long, &[0xD1], ext(0, 4), NO_IMM),
bytes("shlq", &R, Quad, &[0xD1], ext(0, 4), NO_IMM),
bytes("shrb", &R, Byte, &[0xD0], ext(0, 5), NO_IMM),
bytes("shrw", &R, Word, &[0xD1], ext(0, 5), NO_IMM),
bytes("shrl", &R, Long, &[0xD1], ext(0, 5), NO_IMM),
bytes("shrq", &R, Quad, &[0xD1], ext(0, 5), NO_IMM),
bytes("sarb", &R, Byte, &[0xD0], ext(0, 7), NO_IMM),
bytes("sarw", &R, Word, &[0xD1], ext(0, 7), NO_IMM),
bytes("sarl", &R, Long, &[0xD1], ext(0, 7), NO_IMM),
bytes("sarq", &R, Quad, &[0xD1], ext(0, 7), NO_IMM),
takes("rolb", &IM, Fits::Byte, Byte, &[0xC0], ext(1, 0), ImmSize::Ib),
takes("rolw", &IM, Fits::Byte, Word, &[0xC1], ext(1, 0), ImmSize::Ib),
takes("roll", &IM, Fits::Byte, Long, &[0xC1], ext(1, 0), ImmSize::Ib),
takes("rolq", &IM, Fits::Byte, Quad, &[0xC1], ext(1, 0), ImmSize::Ib),
takes("rorb", &IM, Fits::Byte, Byte, &[0xC0], ext(1, 1), ImmSize::Ib),
takes("rorw", &IM, Fits::Byte, Word, &[0xC1], ext(1, 1), ImmSize::Ib),
takes("rorl", &IM, Fits::Byte, Long, &[0xC1], ext(1, 1), ImmSize::Ib),
takes("rorq", &IM, Fits::Byte, Quad, &[0xC1], ext(1, 1), ImmSize::Ib),
takes("rclb", &IM, Fits::Byte, Byte, &[0xC0], ext(1, 2), ImmSize::Ib),
takes("rclw", &IM, Fits::Byte, Word, &[0xC1], ext(1, 2), ImmSize::Ib),
takes("rcll", &IM, Fits::Byte, Long, &[0xC1], ext(1, 2), ImmSize::Ib),
takes("rclq", &IM, Fits::Byte, Quad, &[0xC1], ext(1, 2), ImmSize::Ib),
takes("rcrb", &IM, Fits::Byte, Byte, &[0xC0], ext(1, 3), ImmSize::Ib),
takes("rcrw", &IM, Fits::Byte, Word, &[0xC1], ext(1, 3), ImmSize::Ib),
takes("rcrl", &IM, Fits::Byte, Long, &[0xC1], ext(1, 3), ImmSize::Ib),
takes("rcrq", &IM, Fits::Byte, Quad, &[0xC1], ext(1, 3), ImmSize::Ib),
takes("shlb", &IM, Fits::Byte, Byte, &[0xC0], ext(1, 4), ImmSize::Ib),
takes("shlw", &IM, Fits::Byte, Word, &[0xC1], ext(1, 4), ImmSize::Ib),
takes("shll", &IM, Fits::Byte, Long, &[0xC1], ext(1, 4), ImmSize::Ib),
takes("shlq", &IM, Fits::Byte, Quad, &[0xC1], ext(1, 4), ImmSize::Ib),
takes("shrb", &IM, Fits::Byte, Byte, &[0xC0], ext(1, 5), ImmSize::Ib),
takes("shrw", &IM, Fits::Byte, Word, &[0xC1], ext(1, 5), ImmSize::Ib),
takes("shrl", &IM, Fits::Byte, Long, &[0xC1], ext(1, 5), ImmSize::Ib),
takes("shrq", &IM, Fits::Byte, Quad, &[0xC1], ext(1, 5), ImmSize::Ib),
takes("sarb", &IM, Fits::Byte, Byte, &[0xC0], ext(1, 7), ImmSize::Ib),
takes("sarw", &IM, Fits::Byte, Word, &[0xC1], ext(1, 7), ImmSize::Ib),
takes("sarl", &IM, Fits::Byte, Long, &[0xC1], ext(1, 7), ImmSize::Ib),
takes("sarq", &IM, Fits::Byte, Quad, &[0xC1], ext(1, 7), ImmSize::Ib),
bytes("rolb", &RM, Byte, &[0xD2], ext(1, 0), NO_IMM),
bytes("rolw", &RM, Word, &[0xD3], ext(1, 0), NO_IMM),
bytes("roll", &RM, Long, &[0xD3], ext(1, 0), NO_IMM),
bytes("rolq", &RM, Quad, &[0xD3], ext(1, 0), NO_IMM),
bytes("rorb", &RM, Byte, &[0xD2], ext(1, 1), NO_IMM),
bytes("rorw", &RM, Word, &[0xD3], ext(1, 1), NO_IMM),
bytes("rorl", &RM, Long, &[0xD3], ext(1, 1), NO_IMM),
bytes("rorq", &RM, Quad, &[0xD3], ext(1, 1), NO_IMM),
bytes("rclb", &RM, Byte, &[0xD2], ext(1, 2), NO_IMM),
bytes("rclw", &RM, Word, &[0xD3], ext(1, 2), NO_IMM),
bytes("rcll", &RM, Long, &[0xD3], ext(1, 2), NO_IMM),
bytes("rclq", &RM, Quad, &[0xD3], ext(1, 2), NO_IMM),
bytes("rcrb", &RM, Byte, &[0xD2], ext(1, 3), NO_IMM),
bytes("rcrw", &RM, Word, &[0xD3], ext(1, 3), NO_IMM),
bytes("rcrl", &RM, Long, &[0xD3], ext(1, 3), NO_IMM),
bytes("rcrq", &RM, Quad, &[0xD3], ext(1, 3), NO_IMM),
bytes("shlb", &RM, Byte, &[0xD2], ext(1, 4), NO_IMM),
bytes("shlw", &RM, Word, &[0xD3], ext(1, 4), NO_IMM),
bytes("shll", &RM, Long, &[0xD3], ext(1, 4), NO_IMM),
bytes("shlq", &RM, Quad, &[0xD3], ext(1, 4), NO_IMM),
bytes("shrb", &RM, Byte, &[0xD2], ext(1, 5), NO_IMM),
bytes("shrw", &RM, Word, &[0xD3], ext(1, 5), NO_IMM),
bytes("shrl", &RM, Long, &[0xD3], ext(1, 5), NO_IMM),
bytes("shrq", &RM, Quad, &[0xD3], ext(1, 5), NO_IMM),
bytes("sarb", &RM, Byte, &[0xD2], ext(1, 7), NO_IMM),
bytes("sarw", &RM, Word, &[0xD3], ext(1, 7), NO_IMM),
bytes("sarl", &RM, Long, &[0xD3], ext(1, 7), NO_IMM),
bytes("sarq", &RM, Quad, &[0xD3], ext(1, 7), NO_IMM),
bytes("rolb", &M, Byte, &[0xD0], ext(0, 0), NO_IMM),
bytes("rolw", &M, Word, &[0xD1], ext(0, 0), NO_IMM),
bytes("roll", &M, Long, &[0xD1], ext(0, 0), NO_IMM),
bytes("rolq", &M, Quad, &[0xD1], ext(0, 0), NO_IMM),
bytes("rorb", &M, Byte, &[0xD0], ext(0, 1), NO_IMM),
bytes("rorw", &M, Word, &[0xD1], ext(0, 1), NO_IMM),
bytes("rorl", &M, Long, &[0xD1], ext(0, 1), NO_IMM),
bytes("rorq", &M, Quad, &[0xD1], ext(0, 1), NO_IMM),
bytes("rclb", &M, Byte, &[0xD0], ext(0, 2), NO_IMM),
bytes("rclw", &M, Word, &[0xD1], ext(0, 2), NO_IMM),
bytes("rcll", &M, Long, &[0xD1], ext(0, 2), NO_IMM),
bytes("rclq", &M, Quad, &[0xD1], ext(0, 2), NO_IMM),
bytes("rcrb", &M, Byte, &[0xD0], ext(0, 3), NO_IMM),
bytes("rcrw", &M, Word, &[0xD1], ext(0, 3), NO_IMM),
bytes("rcrl", &M, Long, &[0xD1], ext(0, 3), NO_IMM),
bytes("rcrq", &M, Quad, &[0xD1], ext(0, 3), NO_IMM),
bytes("shlb", &M, Byte, &[0xD0], ext(0, 4), NO_IMM),
bytes("shlw", &M, Word, &[0xD1], ext(0, 4), NO_IMM),
bytes("shll", &M, Long, &[0xD1], ext(0, 4), NO_IMM),
bytes("shlq", &M, Quad, &[0xD1], ext(0, 4), NO_IMM),
bytes("shrb", &M, Byte, &[0xD0], ext(0, 5), NO_IMM),
bytes("shrw", &M, Word, &[0xD1], ext(0, 5), NO_IMM),
bytes("shrl", &M, Long, &[0xD1], ext(0, 5), NO_IMM),
bytes("shrq", &M, Quad, &[0xD1], ext(0, 5), NO_IMM),
bytes("sarb", &M, Byte, &[0xD0], ext(0, 7), NO_IMM),
bytes("sarw", &M, Word, &[0xD1], ext(0, 7), NO_IMM),
bytes("sarl", &M, Long, &[0xD1], ext(0, 7), NO_IMM),
bytes("sarq", &M, Quad, &[0xD1], ext(0, 7), NO_IMM),
takes("shldw", &IRR, Fits::Byte, Word, &[0x0F, 0xA4], pair(2, 1), ImmSize::Ib),
takes("shldl", &IRR, Fits::Byte, Long, &[0x0F, 0xA4], pair(2, 1), ImmSize::Ib),
takes("shldq", &IRR, Fits::Byte, Quad, &[0x0F, 0xA4], pair(2, 1), ImmSize::Ib),
takes("shrdw", &IRR, Fits::Byte, Word, &[0x0F, 0xAC], pair(2, 1), ImmSize::Ib),
takes("shrdl", &IRR, Fits::Byte, Long, &[0x0F, 0xAC], pair(2, 1), ImmSize::Ib),
takes("shrdq", &IRR, Fits::Byte, Quad, &[0x0F, 0xAC], pair(2, 1), ImmSize::Ib),
bytes("shldw", &RRR, Word, &[0x0F, 0xA5], pair(2, 1), NO_IMM),
bytes("shldl", &RRR, Long, &[0x0F, 0xA5], pair(2, 1), NO_IMM),
bytes("shldq", &RRR, Quad, &[0x0F, 0xA5], pair(2, 1), NO_IMM),
bytes("shrdw", &RRR, Word, &[0x0F, 0xAD], pair(2, 1), NO_IMM),
bytes("shrdl", &RRR, Long, &[0x0F, 0xAD], pair(2, 1), NO_IMM),
bytes("shrdq", &RRR, Quad, &[0x0F, 0xAD], pair(2, 1), NO_IMM),
third("shlxl", &RRR, Word, Map::Escape38, &[0xF7], 0, pair(1, 2)),
third("shlxq", &RRR, WordQuad, Map::Escape38, &[0xF7], 0, pair(1, 2)),
third("sarxl", &RRR, Single, Map::Escape38, &[0xF7], 0, pair(1, 2)),
third("sarxq", &RRR, SingleQuad, Map::Escape38, &[0xF7], 0, pair(1, 2)),
third("shrxl", &RRR, Double, Map::Escape38, &[0xF7], 0, pair(1, 2)),
third("shrxq", &RRR, DoubleQuad, Map::Escape38, &[0xF7], 0, pair(1, 2)),
bytes("cmpb", &RR, Byte, &[0x38], pair(1, 0), NO_IMM),
bytes("cmpw", &RR, Word, &[0x39], pair(1, 0), NO_IMM),
bytes("cmpl", &RR, Long, &[0x39], pair(1, 0), NO_IMM),
bytes("cmpq", &RR, Quad, &[0x39], pair(1, 0), NO_IMM),
bytes("cmovew", &RR, Word, &[0x0F, 0x44], pair(0, 1), NO_IMM),
bytes("cmovel", &RR, Long, &[0x0F, 0x44], pair(0, 1), NO_IMM),
bytes("cmoveq", &RR, Quad, &[0x0F, 0x44], pair(0, 1), NO_IMM),
bytes("cmovnew", &RR, Word, &[0x0F, 0x45], pair(0, 1), NO_IMM),
bytes("cmovnel", &RR, Long, &[0x0F, 0x45], pair(0, 1), NO_IMM),
bytes("cmovneq", &RR, Quad, &[0x0F, 0x45], pair(0, 1), NO_IMM),
bytes("cmovlw", &RR, Word, &[0x0F, 0x4C], pair(0, 1), NO_IMM),
bytes("cmovll", &RR, Long, &[0x0F, 0x4C], pair(0, 1), NO_IMM),
bytes("cmovlq", &RR, Quad, &[0x0F, 0x4C], pair(0, 1), NO_IMM),
bytes("cmovlew", &RR, Word, &[0x0F, 0x4E], pair(0, 1), NO_IMM),
bytes("cmovlel", &RR, Long, &[0x0F, 0x4E], pair(0, 1), NO_IMM),
bytes("cmovleq", &RR, Quad, &[0x0F, 0x4E], pair(0, 1), NO_IMM),
bytes("cmovgw", &RR, Word, &[0x0F, 0x4F], pair(0, 1), NO_IMM),
bytes("cmovgl", &RR, Long, &[0x0F, 0x4F], pair(0, 1), NO_IMM),
bytes("cmovgq", &RR, Quad, &[0x0F, 0x4F], pair(0, 1), NO_IMM),
bytes("cmovgew", &RR, Word, &[0x0F, 0x4D], pair(0, 1), NO_IMM),
bytes("cmovgel", &RR, Long, &[0x0F, 0x4D], pair(0, 1), NO_IMM),
bytes("cmovgeq", &RR, Quad, &[0x0F, 0x4D], pair(0, 1), NO_IMM),
bytes("cmovbw", &RR, Word, &[0x0F, 0x42], pair(0, 1), NO_IMM),
bytes("cmovbl", &RR, Long, &[0x0F, 0x42], pair(0, 1), NO_IMM),
bytes("cmovbq", &RR, Quad, &[0x0F, 0x42], pair(0, 1), NO_IMM),
bytes("cmovbew", &RR, Word, &[0x0F, 0x46], pair(0, 1), NO_IMM),
bytes("cmovbel", &RR, Long, &[0x0F, 0x46], pair(0, 1), NO_IMM),
bytes("cmovbeq", &RR, Quad, &[0x0F, 0x46], pair(0, 1), NO_IMM),
bytes("cmovaw", &RR, Word, &[0x0F, 0x47], pair(0, 1), NO_IMM),
bytes("cmoval", &RR, Long, &[0x0F, 0x47], pair(0, 1), NO_IMM),
bytes("cmovaq", &RR, Quad, &[0x0F, 0x47], pair(0, 1), NO_IMM),
bytes("cmovaew", &RR, Word, &[0x0F, 0x43], pair(0, 1), NO_IMM),
bytes("cmovael", &RR, Long, &[0x0F, 0x43], pair(0, 1), NO_IMM),
bytes("cmovaeq", &RR, Quad, &[0x0F, 0x43], pair(0, 1), NO_IMM),
bytes("cmovow", &RR, Word, &[0x0F, 0x40], pair(0, 1), NO_IMM),
bytes("cmovol", &RR, Long, &[0x0F, 0x40], pair(0, 1), NO_IMM),
bytes("cmovoq", &RR, Quad, &[0x0F, 0x40], pair(0, 1), NO_IMM),
bytes("cmovnow", &RR, Word, &[0x0F, 0x41], pair(0, 1), NO_IMM),
bytes("cmovnol", &RR, Long, &[0x0F, 0x41], pair(0, 1), NO_IMM),
bytes("cmovnoq", &RR, Quad, &[0x0F, 0x41], pair(0, 1), NO_IMM),
bytes("cmovsw", &RR, Word, &[0x0F, 0x48], pair(0, 1), NO_IMM),
bytes("cmovsl", &RR, Long, &[0x0F, 0x48], pair(0, 1), NO_IMM),
bytes("cmovsq", &RR, Quad, &[0x0F, 0x48], pair(0, 1), NO_IMM),
bytes("cmovnsw", &RR, Word, &[0x0F, 0x49], pair(0, 1), NO_IMM),
bytes("cmovnsl", &RR, Long, &[0x0F, 0x49], pair(0, 1), NO_IMM),
bytes("cmovnsq", &RR, Quad, &[0x0F, 0x49], pair(0, 1), NO_IMM),
bytes("cmovpw", &RR, Word, &[0x0F, 0x4A], pair(0, 1), NO_IMM),
bytes("cmovpl", &RR, Long, &[0x0F, 0x4A], pair(0, 1), NO_IMM),
bytes("cmovpq", &RR, Quad, &[0x0F, 0x4A], pair(0, 1), NO_IMM),
bytes("cmovnpw", &RR, Word, &[0x0F, 0x4B], pair(0, 1), NO_IMM),
bytes("cmovnpl", &RR, Long, &[0x0F, 0x4B], pair(0, 1), NO_IMM),
bytes("cmovnpq", &RR, Quad, &[0x0F, 0x4B], pair(0, 1), NO_IMM),
bytes("cmovow", &MR, Word, &[0x0F, 0x40], pair(0, 1), NO_IMM),
bytes("cmovol", &MR, Long, &[0x0F, 0x40], pair(0, 1), NO_IMM),
bytes("cmovoq", &MR, Quad, &[0x0F, 0x40], pair(0, 1), NO_IMM),
bytes("cmovnow", &MR, Word, &[0x0F, 0x41], pair(0, 1), NO_IMM),
bytes("cmovnol", &MR, Long, &[0x0F, 0x41], pair(0, 1), NO_IMM),
bytes("cmovnoq", &MR, Quad, &[0x0F, 0x41], pair(0, 1), NO_IMM),
bytes("cmovbw", &MR, Word, &[0x0F, 0x42], pair(0, 1), NO_IMM),
bytes("cmovbl", &MR, Long, &[0x0F, 0x42], pair(0, 1), NO_IMM),
bytes("cmovbq", &MR, Quad, &[0x0F, 0x42], pair(0, 1), NO_IMM),
bytes("cmovaew", &MR, Word, &[0x0F, 0x43], pair(0, 1), NO_IMM),
bytes("cmovael", &MR, Long, &[0x0F, 0x43], pair(0, 1), NO_IMM),
bytes("cmovaeq", &MR, Quad, &[0x0F, 0x43], pair(0, 1), NO_IMM),
bytes("cmovew", &MR, Word, &[0x0F, 0x44], pair(0, 1), NO_IMM),
bytes("cmovel", &MR, Long, &[0x0F, 0x44], pair(0, 1), NO_IMM),
bytes("cmoveq", &MR, Quad, &[0x0F, 0x44], pair(0, 1), NO_IMM),
bytes("cmovnew", &MR, Word, &[0x0F, 0x45], pair(0, 1), NO_IMM),
bytes("cmovnel", &MR, Long, &[0x0F, 0x45], pair(0, 1), NO_IMM),
bytes("cmovneq", &MR, Quad, &[0x0F, 0x45], pair(0, 1), NO_IMM),
bytes("cmovbew", &MR, Word, &[0x0F, 0x46], pair(0, 1), NO_IMM),
bytes("cmovbel", &MR, Long, &[0x0F, 0x46], pair(0, 1), NO_IMM),
bytes("cmovbeq", &MR, Quad, &[0x0F, 0x46], pair(0, 1), NO_IMM),
bytes("cmovaw", &MR, Word, &[0x0F, 0x47], pair(0, 1), NO_IMM),
bytes("cmoval", &MR, Long, &[0x0F, 0x47], pair(0, 1), NO_IMM),
bytes("cmovaq", &MR, Quad, &[0x0F, 0x47], pair(0, 1), NO_IMM),
bytes("cmovsw", &MR, Word, &[0x0F, 0x48], pair(0, 1), NO_IMM),
bytes("cmovsl", &MR, Long, &[0x0F, 0x48], pair(0, 1), NO_IMM),
bytes("cmovsq", &MR, Quad, &[0x0F, 0x48], pair(0, 1), NO_IMM),
bytes("cmovnsw", &MR, Word, &[0x0F, 0x49], pair(0, 1), NO_IMM),
bytes("cmovnsl", &MR, Long, &[0x0F, 0x49], pair(0, 1), NO_IMM),
bytes("cmovnsq", &MR, Quad, &[0x0F, 0x49], pair(0, 1), NO_IMM),
bytes("cmovpw", &MR, Word, &[0x0F, 0x4A], pair(0, 1), NO_IMM),
bytes("cmovpl", &MR, Long, &[0x0F, 0x4A], pair(0, 1), NO_IMM),
bytes("cmovpq", &MR, Quad, &[0x0F, 0x4A], pair(0, 1), NO_IMM),
bytes("cmovnpw", &MR, Word, &[0x0F, 0x4B], pair(0, 1), NO_IMM),
bytes("cmovnpl", &MR, Long, &[0x0F, 0x4B], pair(0, 1), NO_IMM),
bytes("cmovnpq", &MR, Quad, &[0x0F, 0x4B], pair(0, 1), NO_IMM),
bytes("cmovlw", &MR, Word, &[0x0F, 0x4C], pair(0, 1), NO_IMM),
bytes("cmovll", &MR, Long, &[0x0F, 0x4C], pair(0, 1), NO_IMM),
bytes("cmovlq", &MR, Quad, &[0x0F, 0x4C], pair(0, 1), NO_IMM),
bytes("cmovgew", &MR, Word, &[0x0F, 0x4D], pair(0, 1), NO_IMM),
bytes("cmovgel", &MR, Long, &[0x0F, 0x4D], pair(0, 1), NO_IMM),
bytes("cmovgeq", &MR, Quad, &[0x0F, 0x4D], pair(0, 1), NO_IMM),
bytes("cmovlew", &MR, Word, &[0x0F, 0x4E], pair(0, 1), NO_IMM),
bytes("cmovlel", &MR, Long, &[0x0F, 0x4E], pair(0, 1), NO_IMM),
bytes("cmovleq", &MR, Quad, &[0x0F, 0x4E], pair(0, 1), NO_IMM),
bytes("cmovgw", &MR, Word, &[0x0F, 0x4F], pair(0, 1), NO_IMM),
bytes("cmovgl", &MR, Long, &[0x0F, 0x4F], pair(0, 1), NO_IMM),
bytes("cmovgq", &MR, Quad, &[0x0F, 0x4F], pair(0, 1), NO_IMM),
bytes("sete", &R, Byte, &[0x0F, 0x94], ext(0, 0), NO_IMM),
bytes("setne", &R, Byte, &[0x0F, 0x95], ext(0, 0), NO_IMM),
bytes("setl", &R, Byte, &[0x0F, 0x9C], ext(0, 0), NO_IMM),
bytes("setle", &R, Byte, &[0x0F, 0x9E], ext(0, 0), NO_IMM),
bytes("setg", &R, Byte, &[0x0F, 0x9F], ext(0, 0), NO_IMM),
bytes("setge", &R, Byte, &[0x0F, 0x9D], ext(0, 0), NO_IMM),
bytes("setb", &R, Byte, &[0x0F, 0x92], ext(0, 0), NO_IMM),
bytes("setbe", &R, Byte, &[0x0F, 0x96], ext(0, 0), NO_IMM),
bytes("seta", &R, Byte, &[0x0F, 0x97], ext(0, 0), NO_IMM),
bytes("setae", &R, Byte, &[0x0F, 0x93], ext(0, 0), NO_IMM),
bytes("setp", &R, Byte, &[0x0F, 0x9A], ext(0, 0), NO_IMM),
bytes("setnp", &R, Byte, &[0x0F, 0x9B], ext(0, 0), NO_IMM),
bytes("seto", &R, Byte, &[0x0F, 0x90], ext(0, 0), NO_IMM),
bytes("setno", &R, Byte, &[0x0F, 0x91], ext(0, 0), NO_IMM),
bytes("sets", &R, Byte, &[0x0F, 0x98], ext(0, 0), NO_IMM),
bytes("setns", &R, Byte, &[0x0F, 0x99], ext(0, 0), NO_IMM),
bytes("seto", &M, Byte, &[0x0F, 0x90], ext(0, 0), NO_IMM),
bytes("setno", &M, Byte, &[0x0F, 0x91], ext(0, 0), NO_IMM),
bytes("setb", &M, Byte, &[0x0F, 0x92], ext(0, 0), NO_IMM),
bytes("setae", &M, Byte, &[0x0F, 0x93], ext(0, 0), NO_IMM),
bytes("sete", &M, Byte, &[0x0F, 0x94], ext(0, 0), NO_IMM),
bytes("setne", &M, Byte, &[0x0F, 0x95], ext(0, 0), NO_IMM),
bytes("setbe", &M, Byte, &[0x0F, 0x96], ext(0, 0), NO_IMM),
bytes("seta", &M, Byte, &[0x0F, 0x97], ext(0, 0), NO_IMM),
bytes("sets", &M, Byte, &[0x0F, 0x98], ext(0, 0), NO_IMM),
bytes("setns", &M, Byte, &[0x0F, 0x99], ext(0, 0), NO_IMM),
bytes("setp", &M, Byte, &[0x0F, 0x9A], ext(0, 0), NO_IMM),
bytes("setnp", &M, Byte, &[0x0F, 0x9B], ext(0, 0), NO_IMM),
bytes("setl", &M, Byte, &[0x0F, 0x9C], ext(0, 0), NO_IMM),
bytes("setge", &M, Byte, &[0x0F, 0x9D], ext(0, 0), NO_IMM),
bytes("setle", &M, Byte, &[0x0F, 0x9E], ext(0, 0), NO_IMM),
bytes("setg", &M, Byte, &[0x0F, 0x9F], ext(0, 0), NO_IMM),
bytes("movzbw", &RR, Word, &[0x0F, 0xB6], pair(0, 1), NO_IMM),
bytes("movzbl", &RR, Long, &[0x0F, 0xB6], pair(0, 1), NO_IMM),
bytes("movzbq", &RR, Quad, &[0x0F, 0xB6], pair(0, 1), NO_IMM),
bytes("movzwl", &RR, Long, &[0x0F, 0xB7], pair(0, 1), NO_IMM),
bytes("movzwq", &RR, Quad, &[0x0F, 0xB7], pair(0, 1), NO_IMM),
bytes("movsbw", &RR, Word, &[0x0F, 0xBE], pair(0, 1), NO_IMM),
bytes("movsbl", &RR, Long, &[0x0F, 0xBE], pair(0, 1), NO_IMM),
bytes("movsbq", &RR, Quad, &[0x0F, 0xBE], pair(0, 1), NO_IMM),
bytes("movswl", &RR, Long, &[0x0F, 0xBF], pair(0, 1), NO_IMM),
bytes("movswq", &RR, Quad, &[0x0F, 0xBF], pair(0, 1), NO_IMM),
bytes("movslq", &RR, Quad, &[0x63], pair(0, 1), NO_IMM),
bytes("movzbw", &MR, Word, &[0x0F, 0xB6], pair(0, 1), NO_IMM),
bytes("movzbq", &MR, Quad, &[0x0F, 0xB6], pair(0, 1), NO_IMM),
bytes("movzwl", &MR, Long, &[0x0F, 0xB7], pair(0, 1), NO_IMM),
bytes("movzwq", &MR, Quad, &[0x0F, 0xB7], pair(0, 1), NO_IMM),
bytes("movsbw", &MR, Word, &[0x0F, 0xBE], pair(0, 1), NO_IMM),
bytes("movsbl", &MR, Long, &[0x0F, 0xBE], pair(0, 1), NO_IMM),
bytes("movsbq", &MR, Quad, &[0x0F, 0xBE], pair(0, 1), NO_IMM),
bytes("movswl", &MR, Long, &[0x0F, 0xBF], pair(0, 1), NO_IMM),
bytes("movswq", &MR, Quad, &[0x0F, 0xBF], pair(0, 1), NO_IMM),
bytes("movslq", &MR, Quad, &[0x63], pair(0, 1), NO_IMM),
takes("btw", &IR, Fits::Byte, Word, &[0x0F, 0xBA], ext(1, 4), ImmSize::Ib),
takes("btl", &IR, Fits::Byte, Long, &[0x0F, 0xBA], ext(1, 4), ImmSize::Ib),
takes("btq", &IR, Fits::Byte, Quad, &[0x0F, 0xBA], ext(1, 4), ImmSize::Ib),
takes("btsw", &IR, Fits::Byte, Word, &[0x0F, 0xBA], ext(1, 5), ImmSize::Ib),
takes("btsl", &IR, Fits::Byte, Long, &[0x0F, 0xBA], ext(1, 5), ImmSize::Ib),
takes("btsq", &IR, Fits::Byte, Quad, &[0x0F, 0xBA], ext(1, 5), ImmSize::Ib),
takes("btrw", &IR, Fits::Byte, Word, &[0x0F, 0xBA], ext(1, 6), ImmSize::Ib),
takes("btrl", &IR, Fits::Byte, Long, &[0x0F, 0xBA], ext(1, 6), ImmSize::Ib),
takes("btrq", &IR, Fits::Byte, Quad, &[0x0F, 0xBA], ext(1, 6), ImmSize::Ib),
takes("btcw", &IR, Fits::Byte, Word, &[0x0F, 0xBA], ext(1, 7), ImmSize::Ib),
takes("btcl", &IR, Fits::Byte, Long, &[0x0F, 0xBA], ext(1, 7), ImmSize::Ib),
takes("btcq", &IR, Fits::Byte, Quad, &[0x0F, 0xBA], ext(1, 7), ImmSize::Ib),
bytes("btw", &RR, Word, &[0x0F, 0xA3], pair(1, 0), NO_IMM),
bytes("btl", &RR, Long, &[0x0F, 0xA3], pair(1, 0), NO_IMM),
bytes("btq", &RR, Quad, &[0x0F, 0xA3], pair(1, 0), NO_IMM),
bytes("btsw", &RR, Word, &[0x0F, 0xAB], pair(1, 0), NO_IMM),
bytes("btsl", &RR, Long, &[0x0F, 0xAB], pair(1, 0), NO_IMM),
bytes("btsq", &RR, Quad, &[0x0F, 0xAB], pair(1, 0), NO_IMM),
bytes("btrw", &RR, Word, &[0x0F, 0xB3], pair(1, 0), NO_IMM),
bytes("btrl", &RR, Long, &[0x0F, 0xB3], pair(1, 0), NO_IMM),
bytes("btrq", &RR, Quad, &[0x0F, 0xB3], pair(1, 0), NO_IMM),
bytes("btcw", &RR, Word, &[0x0F, 0xBB], pair(1, 0), NO_IMM),
bytes("btcl", &RR, Long, &[0x0F, 0xBB], pair(1, 0), NO_IMM),
bytes("btcq", &RR, Quad, &[0x0F, 0xBB], pair(1, 0), NO_IMM),
takes("btw", &IM, Fits::Byte, Word, &[0x0F, 0xBA], ext(1, 4), ImmSize::Ib),
takes("btl", &IM, Fits::Byte, Long, &[0x0F, 0xBA], ext(1, 4), ImmSize::Ib),
takes("btq", &IM, Fits::Byte, Quad, &[0x0F, 0xBA], ext(1, 4), ImmSize::Ib),
takes("btsw", &IM, Fits::Byte, Word, &[0x0F, 0xBA], ext(1, 5), ImmSize::Ib),
takes("btsl", &IM, Fits::Byte, Long, &[0x0F, 0xBA], ext(1, 5), ImmSize::Ib),
takes("btsq", &IM, Fits::Byte, Quad, &[0x0F, 0xBA], ext(1, 5), ImmSize::Ib),
takes("btrw", &IM, Fits::Byte, Word, &[0x0F, 0xBA], ext(1, 6), ImmSize::Ib),
takes("btrl", &IM, Fits::Byte, Long, &[0x0F, 0xBA], ext(1, 6), ImmSize::Ib),
takes("btrq", &IM, Fits::Byte, Quad, &[0x0F, 0xBA], ext(1, 6), ImmSize::Ib),
takes("btcw", &IM, Fits::Byte, Word, &[0x0F, 0xBA], ext(1, 7), ImmSize::Ib),
takes("btcl", &IM, Fits::Byte, Long, &[0x0F, 0xBA], ext(1, 7), ImmSize::Ib),
takes("btcq", &IM, Fits::Byte, Quad, &[0x0F, 0xBA], ext(1, 7), ImmSize::Ib),
bytes("btw", &RM, Word, &[0x0F, 0xA3], pair(1, 0), NO_IMM),
bytes("btl", &RM, Long, &[0x0F, 0xA3], pair(1, 0), NO_IMM),
bytes("btq", &RM, Quad, &[0x0F, 0xA3], pair(1, 0), NO_IMM),
bytes("btsw", &RM, Word, &[0x0F, 0xAB], pair(1, 0), NO_IMM),
bytes("btsl", &RM, Long, &[0x0F, 0xAB], pair(1, 0), NO_IMM),
bytes("btsq", &RM, Quad, &[0x0F, 0xAB], pair(1, 0), NO_IMM),
bytes("btrw", &RM, Word, &[0x0F, 0xB3], pair(1, 0), NO_IMM),
bytes("btrl", &RM, Long, &[0x0F, 0xB3], pair(1, 0), NO_IMM),
bytes("btrq", &RM, Quad, &[0x0F, 0xB3], pair(1, 0), NO_IMM),
bytes("btcw", &RM, Word, &[0x0F, 0xBB], pair(1, 0), NO_IMM),
bytes("btcl", &RM, Long, &[0x0F, 0xBB], pair(1, 0), NO_IMM),
bytes("btcq", &RM, Quad, &[0x0F, 0xBB], pair(1, 0), NO_IMM),
bytes("bsfw", &RR, Word, &[0x0F, 0xBC], pair(0, 1), NO_IMM),
bytes("bsfl", &RR, Long, &[0x0F, 0xBC], pair(0, 1), NO_IMM),
bytes("bsfq", &RR, Quad, &[0x0F, 0xBC], pair(0, 1), NO_IMM),
bytes("bsrw", &RR, Word, &[0x0F, 0xBD], pair(0, 1), NO_IMM),
bytes("bsrl", &RR, Long, &[0x0F, 0xBD], pair(0, 1), NO_IMM),
bytes("bsrq", &RR, Quad, &[0x0F, 0xBD], pair(0, 1), NO_IMM),
bytes("bsfw", &MR, Word, &[0x0F, 0xBC], pair(0, 1), NO_IMM),
bytes("bsfl", &MR, Long, &[0x0F, 0xBC], pair(0, 1), NO_IMM),
bytes("bsfq", &MR, Quad, &[0x0F, 0xBC], pair(0, 1), NO_IMM),
bytes("bsrw", &MR, Word, &[0x0F, 0xBD], pair(0, 1), NO_IMM),
bytes("bsrl", &MR, Long, &[0x0F, 0xBD], pair(0, 1), NO_IMM),
bytes("bsrq", &MR, Quad, &[0x0F, 0xBD], pair(0, 1), NO_IMM),
bytes("lzcntl", &RR, Single, &[0x0F, 0xBD], pair(0, 1), NO_IMM),
bytes("lzcntq", &RR, SingleQuad, &[0x0F, 0xBD], pair(0, 1), NO_IMM),
bytes("tzcntl", &RR, Single, &[0x0F, 0xBC], pair(0, 1), NO_IMM),
bytes("tzcntq", &RR, SingleQuad, &[0x0F, 0xBC], pair(0, 1), NO_IMM),
bytes("lzcntl", &MR, Single, &[0x0F, 0xBD], pair(0, 1), NO_IMM),
bytes("lzcntq", &MR, SingleQuad, &[0x0F, 0xBD], pair(0, 1), NO_IMM),
bytes("tzcntl", &MR, Single, &[0x0F, 0xBC], pair(0, 1), NO_IMM),
bytes("tzcntq", &MR, SingleQuad, &[0x0F, 0xBC], pair(0, 1), NO_IMM),
bytes("popcntl", &RR, Single, &[0x0F, 0xB8], pair(0, 1), NO_IMM),
bytes("popcntq", &RR, SingleQuad, &[0x0F, 0xB8], pair(0, 1), NO_IMM),
bytes("popcntl", &MR, Single, &[0x0F, 0xB8], pair(0, 1), NO_IMM),
bytes("popcntq", &MR, SingleQuad, &[0x0F, 0xB8], pair(0, 1), NO_IMM),
bytes("crc32b", &RR, Double, &[0x0F, 0x38, 0xF0], pair(0, 1), NO_IMM),
bytes("crc32w", &RR, WordDouble, &[0x0F, 0x38, 0xF1], pair(0, 1), NO_IMM),
bytes("crc32l", &RR, Double, &[0x0F, 0x38, 0xF1], pair(0, 1), NO_IMM),
bytes("crc32q", &RR, DoubleQuad, &[0x0F, 0x38, 0xF1], pair(0, 1), NO_IMM),
bytes("crc32b", &MR, Double, &[0x0F, 0x38, 0xF0], pair(0, 1), NO_IMM),
bytes("crc32w", &MR, WordDouble, &[0x0F, 0x38, 0xF1], pair(0, 1), NO_IMM),
bytes("crc32l", &MR, Double, &[0x0F, 0x38, 0xF1], pair(0, 1), NO_IMM),
bytes("crc32q", &MR, DoubleQuad, &[0x0F, 0x38, 0xF1], pair(0, 1), NO_IMM),
bytes("bswapl", &R, Long, &[0x0F, 0xC8], plus(0), NO_IMM),
bytes("bswapq", &R, Quad, &[0x0F, 0xC8], plus(0), NO_IMM),
bytes("movb", &RR, Byte, &[0x88], pair(1, 0), NO_IMM),
bytes("movw", &RR, Word, &[0x89], pair(1, 0), NO_IMM),
bytes("movl", &RR, Long, &[0x89], pair(1, 0), NO_IMM),
bytes("movq", &RR, Quad, &[0x89], pair(1, 0), NO_IMM),
bytes("leaq", &MR, Quad, &[0x8D], pair(0, 1), NO_IMM),
bytes("leal", &MR, Long, &[0x8D], pair(0, 1), NO_IMM),
bytes("movb", &MR, Byte, &[0x8A], pair(0, 1), NO_IMM),
bytes("movw", &MR, Word, &[0x8B], pair(0, 1), NO_IMM),
bytes("movl", &MR, Long, &[0x8B], pair(0, 1), NO_IMM),
bytes("movq", &MR, Quad, &[0x8B], pair(0, 1), NO_IMM),
bytes("movb", &RM, Byte, &[0x88], pair(1, 0), NO_IMM),
bytes("movw", &RM, Word, &[0x89], pair(1, 0), NO_IMM),
bytes("movl", &RM, Long, &[0x89], pair(1, 0), NO_IMM),
bytes("movq", &RM, Quad, &[0x89], pair(1, 0), NO_IMM),
bytes("movzbl", &MR, Long, &[0x0F, 0xB6], pair(0, 1), NO_IMM),
bytes("call", &D, Long, &[0xE8], NO_MODRM, ImmSize::Cd),
bytes("call", &R, Long, &[0xFF], ext(0, 2), NO_IMM),
bytes("call", &M, Long, &[0xFF], ext(0, 2), NO_IMM),
bytes("testb", &RR, Byte, &[0x84], pair(1, 0), NO_IMM),
bytes("testw", &RR, Word, &[0x85], pair(1, 0), NO_IMM),
bytes("testl", &RR, Long, &[0x85], pair(1, 0), NO_IMM),
bytes("testq", &RR, Quad, &[0x85], pair(1, 0), NO_IMM),
bytes("testb", &RM, Byte, &[0x84], pair(1, 0), NO_IMM),
bytes("testw", &RM, Word, &[0x85], pair(1, 0), NO_IMM),
bytes("testl", &RM, Long, &[0x85], pair(1, 0), NO_IMM),
bytes("testq", &RM, Quad, &[0x85], pair(1, 0), NO_IMM),
bytes("testb", &MR, Byte, &[0x84], pair(0, 1), NO_IMM),
bytes("testw", &MR, Word, &[0x85], pair(0, 1), NO_IMM),
bytes("testl", &MR, Long, &[0x85], pair(0, 1), NO_IMM),
bytes("testq", &MR, Quad, &[0x85], pair(0, 1), NO_IMM),
takes("testb", &IR, Fits::Byte, Byte, &[0xF6], ext(1, 0), ImmSize::Ib),
takes("testw", &IR, Fits::Word, Word, &[0xF7], ext(1, 0), ImmSize::Iw),
takes("testl", &IR, Fits::Long, Long, &[0xF7], ext(1, 0), ImmSize::Id),
takes("testq", &IR, Signed32, Quad, &[0xF7], ext(1, 0), ImmSize::Id),
takes("testb", &IM, Fits::Byte, Byte, &[0xF6], ext(1, 0), ImmSize::Ib),
takes("testw", &IM, Fits::Word, Word, &[0xF7], ext(1, 0), ImmSize::Iw),
takes("testl", &IM, Fits::Long, Long, &[0xF7], ext(1, 0), ImmSize::Id),
takes("testq", &IM, Signed32, Quad, &[0xF7], ext(1, 0), ImmSize::Id),
bytes("clc", &NO_ARGS, Long, &[0xF8], NO_MODRM, NO_IMM),
bytes("stc", &NO_ARGS, Long, &[0xF9], NO_MODRM, NO_IMM),
bytes("cmc", &NO_ARGS, Long, &[0xF5], NO_MODRM, NO_IMM),
bytes("movsb", &NO_ARGS, Byte, &[0xA4], NO_MODRM, NO_IMM),
bytes("movsw", &NO_ARGS, Word, &[0xA5], NO_MODRM, NO_IMM),
bytes("movsl", &NO_ARGS, Long, &[0xA5], NO_MODRM, NO_IMM),
bytes("movsq", &NO_ARGS, Quad, &[0xA5], NO_MODRM, NO_IMM),
bytes("je", &D, Long, &[0x0F, 0x84], NO_MODRM, ImmSize::Cd),
bytes("jne", &D, Long, &[0x0F, 0x85], NO_MODRM, ImmSize::Cd),
bytes("jl", &D, Long, &[0x0F, 0x8C], NO_MODRM, ImmSize::Cd),
bytes("jle", &D, Long, &[0x0F, 0x8E], NO_MODRM, ImmSize::Cd),
bytes("jg", &D, Long, &[0x0F, 0x8F], NO_MODRM, ImmSize::Cd),
bytes("jge", &D, Long, &[0x0F, 0x8D], NO_MODRM, ImmSize::Cd),
bytes("jb", &D, Long, &[0x0F, 0x82], NO_MODRM, ImmSize::Cd),
bytes("jbe", &D, Long, &[0x0F, 0x86], NO_MODRM, ImmSize::Cd),
bytes("ja", &D, Long, &[0x0F, 0x87], NO_MODRM, ImmSize::Cd),
bytes("jae", &D, Long, &[0x0F, 0x83], NO_MODRM, ImmSize::Cd),
bytes("jo", &D, Long, &[0x0F, 0x80], NO_MODRM, ImmSize::Cd),
bytes("jno", &D, Long, &[0x0F, 0x81], NO_MODRM, ImmSize::Cd),
bytes("js", &D, Long, &[0x0F, 0x88], NO_MODRM, ImmSize::Cd),
bytes("jns", &D, Long, &[0x0F, 0x89], NO_MODRM, ImmSize::Cd),
bytes("jp", &D, Long, &[0x0F, 0x8A], NO_MODRM, ImmSize::Cd),
bytes("jnp", &D, Long, &[0x0F, 0x8B], NO_MODRM, ImmSize::Cd),
bytes("jmp", &D, Long, &[0xE9], NO_MODRM, ImmSize::Cd),
bytes("jrcxz", &D, Long, &[0xE3], NO_MODRM, ImmSize::Cb),
bytes("loop", &D, Long, &[0xE2], NO_MODRM, ImmSize::Cb),
bytes("loope", &D, Long, &[0xE1], NO_MODRM, ImmSize::Cb),
bytes("loopz", &D, Long, &[0xE1], NO_MODRM, ImmSize::Cb),
bytes("loopne", &D, Long, &[0xE0], NO_MODRM, ImmSize::Cb),
bytes("loopnz", &D, Long, &[0xE0], NO_MODRM, ImmSize::Cb),
bytes("jmp", &R, Long, &[0xFF], ext(0, 4), NO_IMM),
bytes("jmp", &M, Long, &[0xFF], ext(0, 4), NO_IMM),
bytes("notrack jmp", &R, Untracked, &[0xFF], ext(0, 4), NO_IMM),
bytes("notrack jmp", &M, Untracked, &[0xFF], ext(0, 4), NO_IMM),
bytes("notrack call", &R, Untracked, &[0xFF], ext(0, 2), NO_IMM),
bytes("notrack call", &M, Untracked, &[0xFF], ext(0, 2), NO_IMM),
bytes("pushq", &R, Long, &[0x50], plus(0), NO_IMM),
bytes("popq", &R, Long, &[0x58], plus(0), NO_IMM),
bytes("pushq", &M, Long, &[0xFF], ext(0, 6), NO_IMM),
bytes("popq", &M, Long, &[0x8F], ext(0, 0), NO_IMM),
takes("pushq", &I, Signed8, Long, &[0x6A], NO_MODRM, ImmSize::Ib),
takes("pushq", &I, Signed32, Long, &[0x68], NO_MODRM, ImmSize::Id),
bytes("pushfq", &NO_ARGS, Long, &[0x9C], NO_MODRM, NO_IMM),
bytes("popfq", &NO_ARGS, Long, &[0x9D], NO_MODRM, NO_IMM),
bytes("pushw", &R, Word, &[0x50], plus(0), NO_IMM),
bytes("popw", &R, Word, &[0x58], plus(0), NO_IMM),
bytes("pushw", &M, Word, &[0xFF], ext(0, 6), NO_IMM),
bytes("popw", &M, Word, &[0x8F], ext(0, 0), NO_IMM),
takes("pushw", &I, Signed8, Word, &[0x6A], NO_MODRM, ImmSize::Ib),
takes("pushw", &I, Fits::Word, Word, &[0x68], NO_MODRM, ImmSize::Iw),
bytes("ret", &NO_ARGS, Long, &[0xC3], NO_MODRM, NO_IMM),
takes("ret", &I, Fits::Word, Long, &[0xC2], NO_MODRM, ImmSize::Iw),
bytes("leave", &NO_ARGS, Long, &[0xC9], NO_MODRM, NO_IMM),
bytes("mfence", &NO_ARGS, Long, &[0x0F, 0xAE, 0xF0], NO_MODRM, NO_IMM),
bytes("prefetchnta", &M, Long, &[0x0F, 0x18], ext(0, 0), NO_IMM),
bytes("prefetcht0", &M, Long, &[0x0F, 0x18], ext(0, 1), NO_IMM),
bytes("prefetcht1", &M, Long, &[0x0F, 0x18], ext(0, 2), NO_IMM),
bytes("prefetcht2", &M, Long, &[0x0F, 0x18], ext(0, 3), NO_IMM),
bytes("prefetch", &M, Long, &[0x0F, 0x0D], ext(0, 0), NO_IMM),
bytes("prefetchw", &M, Long, &[0x0F, 0x0D], ext(0, 1), NO_IMM),
bytes("ud2", &NO_ARGS, Long, &[0x0F, 0x0B], NO_MODRM, NO_IMM),
bytes("int3", &NO_ARGS, Long, &[0xCC], NO_MODRM, NO_IMM),
bytes("endbr64", &NO_ARGS, Long, &[0xF3, 0x0F, 0x1E, 0xFA], NO_MODRM, NO_IMM),
bytes("nop", &NO_ARGS, Long, &[0x90], NO_MODRM, NO_IMM),
bytes("pause", &NO_ARGS, Long, &[0xF3, 0x90], NO_MODRM, NO_IMM),
bytes("cpuid", &NO_ARGS, Long, &[0x0F, 0xA2], NO_MODRM, NO_IMM),
bytes("xgetbv", &NO_ARGS, Long, &[0x0F, 0x01, 0xD0], NO_MODRM, NO_IMM),
bytes("clts", &NO_ARGS, Long, &[0x0F, 0x06], NO_MODRM, NO_IMM),
bytes("invd", &NO_ARGS, Long, &[0x0F, 0x08], NO_MODRM, NO_IMM),
bytes("wbinvd", &NO_ARGS, Long, &[0x0F, 0x09], NO_MODRM, NO_IMM),
bytes("wbnoinvd", &NO_ARGS, Long, &[0xF3, 0x0F, 0x09], NO_MODRM, NO_IMM),
bytes("wrmsr", &NO_ARGS, Long, &[0x0F, 0x30], NO_MODRM, NO_IMM),
bytes("rdtsc", &NO_ARGS, Long, &[0x0F, 0x31], NO_MODRM, NO_IMM),
bytes("rdmsr", &NO_ARGS, Long, &[0x0F, 0x32], NO_MODRM, NO_IMM),
bytes("rdpmc", &NO_ARGS, Long, &[0x0F, 0x33], NO_MODRM, NO_IMM),
bytes("wrmsrns", &NO_ARGS, Long, &[0x0F, 0x01, 0xC6], NO_MODRM, NO_IMM),
bytes("rdtscp", &NO_ARGS, Long, &[0x0F, 0x01, 0xF9], NO_MODRM, NO_IMM),
bytes("swapgs", &NO_ARGS, Long, &[0x0F, 0x01, 0xF8], NO_MODRM, NO_IMM),
bytes("syscall", &NO_ARGS, Long, &[0x0F, 0x05], NO_MODRM, NO_IMM),
bytes("sysenter", &NO_ARGS, Long, &[0x0F, 0x34], NO_MODRM, NO_IMM),
bytes("sysret", &NO_ARGS, Long, &[0x0F, 0x07], NO_MODRM, NO_IMM),
bytes("sysretl", &NO_ARGS, Long, &[0x0F, 0x07], NO_MODRM, NO_IMM),
bytes("sysretq", &NO_ARGS, Quad, &[0x0F, 0x07], NO_MODRM, NO_IMM),
bytes("sysexit", &NO_ARGS, Long, &[0x0F, 0x35], NO_MODRM, NO_IMM),
bytes("sysexitl", &NO_ARGS, Long, &[0x0F, 0x35], NO_MODRM, NO_IMM),
bytes("sysexitq", &NO_ARGS, Quad, &[0x0F, 0x35], NO_MODRM, NO_IMM),
bytes("iret", &NO_ARGS, Long, &[0xCF], NO_MODRM, NO_IMM),
bytes("iretw", &NO_ARGS, Word, &[0xCF], NO_MODRM, NO_IMM),
bytes("iretl", &NO_ARGS, Long, &[0xCF], NO_MODRM, NO_IMM),
bytes("iretq", &NO_ARGS, Quad, &[0xCF], NO_MODRM, NO_IMM),
bytes("lret", &NO_ARGS, Long, &[0xCB], NO_MODRM, NO_IMM),
bytes("lretl", &NO_ARGS, Long, &[0xCB], NO_MODRM, NO_IMM),
bytes("lretq", &NO_ARGS, Quad, &[0xCB], NO_MODRM, NO_IMM),
takes("lret", &I, Fits::Word, Long, &[0xCA], NO_MODRM, ImmSize::Iw),
takes("lretl", &I, Fits::Word, Long, &[0xCA], NO_MODRM, ImmSize::Iw),
takes("lretq", &I, Fits::Word, Quad, &[0xCA], NO_MODRM, ImmSize::Iw),
bytes("ljmp", &M, Long, &[0xFF], ext(0, 5), NO_IMM),
bytes("ljmpl", &M, Long, &[0xFF], ext(0, 5), NO_IMM),
bytes("ljmpq", &M, Quad, &[0xFF], ext(0, 5), NO_IMM),
bytes("lcall", &M, Long, &[0xFF], ext(0, 3), NO_IMM),
bytes("lcalll", &M, Long, &[0xFF], ext(0, 3), NO_IMM),
bytes("lcallq", &M, Quad, &[0xFF], ext(0, 3), NO_IMM),
bytes("cli", &NO_ARGS, Long, &[0xFA], NO_MODRM, NO_IMM),
bytes("sti", &NO_ARGS, Long, &[0xFB], NO_MODRM, NO_IMM),
bytes("hlt", &NO_ARGS, Long, &[0xF4], NO_MODRM, NO_IMM),
bytes("int1", &NO_ARGS, Long, &[0xF1], NO_MODRM, NO_IMM),
bytes("icebp", &NO_ARGS, Long, &[0xF1], NO_MODRM, NO_IMM),
takes("int", &I, Fits::Byte, Long, &[0xCD], NO_MODRM, ImmSize::Ib),
bytes("cld", &NO_ARGS, Long, &[0xFC], NO_MODRM, NO_IMM),
bytes("std", &NO_ARGS, Long, &[0xFD], NO_MODRM, NO_IMM),
bytes("lahf", &NO_ARGS, Long, &[0x9F], NO_MODRM, NO_IMM),
bytes("sahf", &NO_ARGS, Long, &[0x9E], NO_MODRM, NO_IMM),
bytes("rsm", &NO_ARGS, Long, &[0x0F, 0xAA], NO_MODRM, NO_IMM),
bytes("clac", &NO_ARGS, Long, &[0x0F, 0x01, 0xCA], NO_MODRM, NO_IMM),
bytes("stac", &NO_ARGS, Long, &[0x0F, 0x01, 0xCB], NO_MODRM, NO_IMM),
bytes("rdpkru", &NO_ARGS, Long, &[0x0F, 0x01, 0xEE], NO_MODRM, NO_IMM),
bytes("wrpkru", &NO_ARGS, Long, &[0x0F, 0x01, 0xEF], NO_MODRM, NO_IMM),
bytes("monitor", &NO_ARGS, Long, &[0x0F, 0x01, 0xC8], NO_MODRM, NO_IMM),
bytes("monitor", &RRR, Long, &[0x0F, 0x01, 0xC8], NO_MODRM, NO_IMM),
bytes("mwait", &NO_ARGS, Long, &[0x0F, 0x01, 0xC9], NO_MODRM, NO_IMM),
bytes("mwait", &RR, Long, &[0x0F, 0x01, 0xC9], NO_MODRM, NO_IMM),
bytes("monitorx", &NO_ARGS, Long, &[0x0F, 0x01, 0xFA], NO_MODRM, NO_IMM),
bytes("monitorx", &RRR, Long, &[0x0F, 0x01, 0xFA], NO_MODRM, NO_IMM),
bytes("mwaitx", &NO_ARGS, Long, &[0x0F, 0x01, 0xFB], NO_MODRM, NO_IMM),
bytes("mwaitx", &RRR, Long, &[0x0F, 0x01, 0xFB], NO_MODRM, NO_IMM),
bytes("lfence", &NO_ARGS, Long, &[0x0F, 0xAE, 0xE8], NO_MODRM, NO_IMM),
bytes("sfence", &NO_ARGS, Long, &[0x0F, 0xAE, 0xF8], NO_MODRM, NO_IMM),
bytes("serialize", &NO_ARGS, Long, &[0x0F, 0x01, 0xE8], NO_MODRM, NO_IMM),
bytes("endbr32", &NO_ARGS, Long, &[0xF3, 0x0F, 0x1E, 0xFB], NO_MODRM, NO_IMM),
bytes("xsetbv", &NO_ARGS, Long, &[0x0F, 0x01, 0xD1], NO_MODRM, NO_IMM),
bytes("xend", &NO_ARGS, Long, &[0x0F, 0x01, 0xD5], NO_MODRM, NO_IMM),
bytes("xtest", &NO_ARGS, Long, &[0x0F, 0x01, 0xD6], NO_MODRM, NO_IMM),
takes("xabort", &I, Fits::Byte, Long, &[0xC6, 0xF8], NO_MODRM, ImmSize::Ib),
bytes("fnclex", &NO_ARGS, Long, &[0xDB, 0xE2], NO_MODRM, NO_IMM),
bytes("fwait", &NO_ARGS, Long, &[0x9B], NO_MODRM, NO_IMM),
bytes("wait", &NO_ARGS, Long, &[0x9B], NO_MODRM, NO_IMM),
bytes("emms", &NO_ARGS, Long, &[0x0F, 0x77], NO_MODRM, NO_IMM),
bytes("fnsave", &M, Long, &[0xDD], ext(0, 6), NO_IMM),
waits("fsave", &M, Long, &[0xDD], ext(0, 6)),
bytes("frstor", &M, Long, &[0xDD], ext(0, 4), NO_IMM),
bytes("fldenv", &M, Long, &[0xD9], ext(0, 4), NO_IMM),
bytes("vmcall", &NO_ARGS, Long, &[0x0F, 0x01, 0xC1], NO_MODRM, NO_IMM),
bytes("vmlaunch", &NO_ARGS, Long, &[0x0F, 0x01, 0xC2], NO_MODRM, NO_IMM),
bytes("vmresume", &NO_ARGS, Long, &[0x0F, 0x01, 0xC3], NO_MODRM, NO_IMM),
bytes("vmxoff", &NO_ARGS, Long, &[0x0F, 0x01, 0xC4], NO_MODRM, NO_IMM),
bytes("vmfunc", &NO_ARGS, Long, &[0x0F, 0x01, 0xD4], NO_MODRM, NO_IMM),
bytes("vmxon", &M, Single, &[0x0F, 0xC7], ext(0, 6), NO_IMM),
bytes("vmclear", &M, Word, &[0x0F, 0xC7], ext(0, 6), NO_IMM),
bytes("vmptrld", &M, Long, &[0x0F, 0xC7], ext(0, 6), NO_IMM),
bytes("vmptrst", &M, Long, &[0x0F, 0xC7], ext(0, 7), NO_IMM),
bytes("vmreadq", &RR, Long, &[0x0F, 0x78], pair(1, 0), NO_IMM),
bytes("vmreadq", &RM, Long, &[0x0F, 0x78], pair(1, 0), NO_IMM),
bytes("vmwriteq", &RR, Long, &[0x0F, 0x79], pair(0, 1), NO_IMM),
bytes("vmwriteq", &MR, Long, &[0x0F, 0x79], pair(0, 1), NO_IMM),
bytes("invept", &MR, Word, &[0x0F, 0x38, 0x80], pair(0, 1), NO_IMM),
bytes("invvpid", &MR, Word, &[0x0F, 0x38, 0x81], pair(0, 1), NO_IMM),
bytes("vmmcall", &NO_ARGS, Long, &[0x0F, 0x01, 0xD9], NO_MODRM, NO_IMM),
bytes("vmgexit", &NO_ARGS, Long, &[0xF3, 0x0F, 0x01, 0xD9], NO_MODRM, NO_IMM),
bytes("vmrun", &NO_ARGS, Long, &[0x0F, 0x01, 0xD8], NO_MODRM, NO_IMM),
bytes("vmrun", &R, Long, &[0x0F, 0x01, 0xD8], NO_MODRM, NO_IMM),
bytes("vmload", &NO_ARGS, Long, &[0x0F, 0x01, 0xDA], NO_MODRM, NO_IMM),
bytes("vmload", &R, Long, &[0x0F, 0x01, 0xDA], NO_MODRM, NO_IMM),
bytes("vmsave", &NO_ARGS, Long, &[0x0F, 0x01, 0xDB], NO_MODRM, NO_IMM),
bytes("vmsave", &R, Long, &[0x0F, 0x01, 0xDB], NO_MODRM, NO_IMM),
bytes("stgi", &NO_ARGS, Long, &[0x0F, 0x01, 0xDC], NO_MODRM, NO_IMM),
bytes("clgi", &NO_ARGS, Long, &[0x0F, 0x01, 0xDD], NO_MODRM, NO_IMM),
bytes("skinit", &NO_ARGS, Long, &[0x0F, 0x01, 0xDE], NO_MODRM, NO_IMM),
bytes("skinit", &R, Long, &[0x0F, 0x01, 0xDE], NO_MODRM, NO_IMM),
bytes("invlpga", &NO_ARGS, Long, &[0x0F, 0x01, 0xDF], NO_MODRM, NO_IMM),
bytes("invlpga", &RR, Long, &[0x0F, 0x01, 0xDF], NO_MODRM, NO_IMM),
bytes("pvalidate", &NO_ARGS, Long, &[0xF2, 0x0F, 0x01, 0xFF], NO_MODRM, NO_IMM),
bytes("rmpadjust", &NO_ARGS, Long, &[0xF3, 0x0F, 0x01, 0xFE], NO_MODRM, NO_IMM),
bytes("rmpupdate", &NO_ARGS, Long, &[0xF2, 0x0F, 0x01, 0xFE], NO_MODRM, NO_IMM),
bytes("psmash", &NO_ARGS, Long, &[0xF3, 0x0F, 0x01, 0xFF], NO_MODRM, NO_IMM),
bytes("tdcall", &NO_ARGS, Long, &[0x66, 0x0F, 0x01, 0xCC], NO_MODRM, NO_IMM),
bytes("seamret", &NO_ARGS, Long, &[0x66, 0x0F, 0x01, 0xCD], NO_MODRM, NO_IMM),
bytes("seamops", &NO_ARGS, Long, &[0x66, 0x0F, 0x01, 0xCE], NO_MODRM, NO_IMM),
bytes("seamcall", &NO_ARGS, Long, &[0x66, 0x0F, 0x01, 0xCF], NO_MODRM, NO_IMM),
bytes("enclv", &NO_ARGS, Long, &[0x0F, 0x01, 0xC0], NO_MODRM, NO_IMM),
bytes("pconfig", &NO_ARGS, Long, &[0x0F, 0x01, 0xC5], NO_MODRM, NO_IMM),
bytes("encls", &NO_ARGS, Long, &[0x0F, 0x01, 0xCF], NO_MODRM, NO_IMM),
bytes("enclu", &NO_ARGS, Long, &[0x0F, 0x01, 0xD7], NO_MODRM, NO_IMM),
bytes("eretu", &NO_ARGS, Long, &[0xF3, 0x0F, 0x01, 0xCA], NO_MODRM, NO_IMM),
bytes("erets", &NO_ARGS, Long, &[0xF2, 0x0F, 0x01, 0xCA], NO_MODRM, NO_IMM),
bytes("sgdt", &M, Long, &[0x0F, 0x01], ext(0, 0), NO_IMM),
bytes("sgdtq", &M, Long, &[0x0F, 0x01], ext(0, 0), NO_IMM),
bytes("sidt", &M, Long, &[0x0F, 0x01], ext(0, 1), NO_IMM),
bytes("sidtq", &M, Long, &[0x0F, 0x01], ext(0, 1), NO_IMM),
bytes("lgdt", &M, Long, &[0x0F, 0x01], ext(0, 2), NO_IMM),
bytes("lgdtq", &M, Long, &[0x0F, 0x01], ext(0, 2), NO_IMM),
bytes("lidt", &M, Long, &[0x0F, 0x01], ext(0, 3), NO_IMM),
bytes("lidtq", &M, Long, &[0x0F, 0x01], ext(0, 3), NO_IMM),
bytes("sldt", &M, Long, &[0x0F, 0x00], ext(0, 0), NO_IMM),
bytes("sldtw", &R, Word, &[0x0F, 0x00], ext(0, 0), NO_IMM),
bytes("sldtl", &R, Long, &[0x0F, 0x00], ext(0, 0), NO_IMM),
bytes("sldtq", &R, Quad, &[0x0F, 0x00], ext(0, 0), NO_IMM),
bytes("str", &M, Long, &[0x0F, 0x00], ext(0, 1), NO_IMM),
bytes("strw", &R, Word, &[0x0F, 0x00], ext(0, 1), NO_IMM),
bytes("strl", &R, Long, &[0x0F, 0x00], ext(0, 1), NO_IMM),
bytes("strq", &R, Quad, &[0x0F, 0x00], ext(0, 1), NO_IMM),
bytes("lldt", &R, Long, &[0x0F, 0x00], ext(0, 2), NO_IMM),
bytes("lldt", &M, Long, &[0x0F, 0x00], ext(0, 2), NO_IMM),
bytes("ltr", &R, Long, &[0x0F, 0x00], ext(0, 3), NO_IMM),
bytes("ltr", &M, Long, &[0x0F, 0x00], ext(0, 3), NO_IMM),
bytes("verr", &R, Long, &[0x0F, 0x00], ext(0, 4), NO_IMM),
bytes("verr", &M, Long, &[0x0F, 0x00], ext(0, 4), NO_IMM),
bytes("verw", &R, Long, &[0x0F, 0x00], ext(0, 5), NO_IMM),
bytes("verw", &M, Long, &[0x0F, 0x00], ext(0, 5), NO_IMM),
bytes("smsw", &M, Long, &[0x0F, 0x01], ext(0, 4), NO_IMM),
bytes("smsww", &R, Word, &[0x0F, 0x01], ext(0, 4), NO_IMM),
bytes("smswl", &R, Long, &[0x0F, 0x01], ext(0, 4), NO_IMM),
bytes("smswq", &R, Quad, &[0x0F, 0x01], ext(0, 4), NO_IMM),
bytes("lmsw", &R, Long, &[0x0F, 0x01], ext(0, 6), NO_IMM),
bytes("lmsw", &M, Long, &[0x0F, 0x01], ext(0, 6), NO_IMM),
bytes("larw", &RR, Word, &[0x0F, 0x02], pair(0, 1), NO_IMM),
bytes("larw", &MR, Word, &[0x0F, 0x02], pair(0, 1), NO_IMM),
bytes("larl", &RR, Long, &[0x0F, 0x02], pair(0, 1), NO_IMM),
bytes("larl", &MR, Long, &[0x0F, 0x02], pair(0, 1), NO_IMM),
bytes("larq", &RR, Quad, &[0x0F, 0x02], pair(0, 1), NO_IMM),
bytes("larq", &MR, Quad, &[0x0F, 0x02], pair(0, 1), NO_IMM),
bytes("lslw", &RR, Word, &[0x0F, 0x03], pair(0, 1), NO_IMM),
bytes("lslw", &MR, Word, &[0x0F, 0x03], pair(0, 1), NO_IMM),
bytes("lsll", &RR, Long, &[0x0F, 0x03], pair(0, 1), NO_IMM),
bytes("lsll", &MR, Long, &[0x0F, 0x03], pair(0, 1), NO_IMM),
bytes("lslq", &RR, Quad, &[0x0F, 0x03], pair(0, 1), NO_IMM),
bytes("lslq", &MR, Quad, &[0x0F, 0x03], pair(0, 1), NO_IMM),
bytes("movq", &CONTROL_R, Long, &[0x0F, 0x20], pair(1, 0), NO_IMM),
bytes("movq", &R_CONTROL, Long, &[0x0F, 0x22], pair(0, 1), NO_IMM),
bytes("movq", &DEBUG_R, Long, &[0x0F, 0x21], pair(1, 0), NO_IMM),
bytes("movq", &R_DEBUG, Long, &[0x0F, 0x23], pair(0, 1), NO_IMM),
bytes("movl", &CONTROL_R, Long, &[0x0F, 0x20], pair(1, 0), NO_IMM),
bytes("movl", &R_CONTROL, Long, &[0x0F, 0x22], pair(0, 1), NO_IMM),
bytes("movl", &DEBUG_R, Long, &[0x0F, 0x21], pair(1, 0), NO_IMM),
bytes("movl", &R_DEBUG, Long, &[0x0F, 0x23], pair(0, 1), NO_IMM),
bytes("movw", &SEG_R, Word, &[0x8C], pair(1, 0), NO_IMM),
bytes("movl", &SEG_R, Long, &[0x8C], pair(1, 0), NO_IMM),
bytes("movq", &SEG_R, Quad, &[0x8C], pair(1, 0), NO_IMM),
bytes("movw", &R_SEG, Long, &[0x8E], pair(0, 1), NO_IMM),
bytes("movl", &R_SEG, Long, &[0x8E], pair(0, 1), NO_IMM),
bytes("movq", &R_SEG, Quad, &[0x8E], pair(0, 1), NO_IMM),
bytes("mov", &SEG_M, Long, &[0x8C], pair(1, 0), NO_IMM),
bytes("movw", &SEG_M, Long, &[0x8C], pair(1, 0), NO_IMM),
bytes("mov", &M_SEG, Long, &[0x8E], pair(0, 1), NO_IMM),
bytes("movw", &M_SEG, Long, &[0x8E], pair(0, 1), NO_IMM),
bytes("pushq %fs", &NO_ARGS, Long, &[0x0F, 0xA0], NO_MODRM, NO_IMM),
bytes("popq %fs", &NO_ARGS, Long, &[0x0F, 0xA1], NO_MODRM, NO_IMM),
bytes("pushq %gs", &NO_ARGS, Long, &[0x0F, 0xA8], NO_MODRM, NO_IMM),
bytes("popq %gs", &NO_ARGS, Long, &[0x0F, 0xA9], NO_MODRM, NO_IMM),
bytes("rdfsbasel", &R, Single, &[0x0F, 0xAE], ext(0, 0), NO_IMM),
bytes("rdfsbaseq", &R, SingleQuad, &[0x0F, 0xAE], ext(0, 0), NO_IMM),
bytes("rdgsbasel", &R, Single, &[0x0F, 0xAE], ext(0, 1), NO_IMM),
bytes("rdgsbaseq", &R, SingleQuad, &[0x0F, 0xAE], ext(0, 1), NO_IMM),
bytes("wrfsbasel", &R, Single, &[0x0F, 0xAE], ext(0, 2), NO_IMM),
bytes("wrfsbaseq", &R, SingleQuad, &[0x0F, 0xAE], ext(0, 2), NO_IMM),
bytes("wrgsbasel", &R, Single, &[0x0F, 0xAE], ext(0, 3), NO_IMM),
bytes("wrgsbaseq", &R, SingleQuad, &[0x0F, 0xAE], ext(0, 3), NO_IMM),
bytes("invlpg", &M, Long, &[0x0F, 0x01], ext(0, 7), NO_IMM),
bytes("invpcid", &MR, Word, &[0x0F, 0x38, 0x82], pair(0, 1), NO_IMM),
bytes("clflush", &M, Long, &[0x0F, 0xAE], ext(0, 7), NO_IMM),
bytes("clflushopt", &M, Word, &[0x0F, 0xAE], ext(0, 7), NO_IMM),
bytes("clwb", &M, Word, &[0x0F, 0xAE], ext(0, 6), NO_IMM),
bytes("fxsave", &M, Long, &[0x0F, 0xAE], ext(0, 0), NO_IMM),
bytes("fxsave64", &M, Quad, &[0x0F, 0xAE], ext(0, 0), NO_IMM),
bytes("fxsaveq", &M, Quad, &[0x0F, 0xAE], ext(0, 0), NO_IMM),
bytes("fxrstor", &M, Long, &[0x0F, 0xAE], ext(0, 1), NO_IMM),
bytes("fxrstor64", &M, Quad, &[0x0F, 0xAE], ext(0, 1), NO_IMM),
bytes("fxrstorq", &M, Quad, &[0x0F, 0xAE], ext(0, 1), NO_IMM),
bytes("ldmxcsr", &M, Long, &[0x0F, 0xAE], ext(0, 2), NO_IMM),
bytes("stmxcsr", &M, Long, &[0x0F, 0xAE], ext(0, 3), NO_IMM),
bytes("xsave", &M, Long, &[0x0F, 0xAE], ext(0, 4), NO_IMM),
bytes("xsave64", &M, Quad, &[0x0F, 0xAE], ext(0, 4), NO_IMM),
bytes("xrstor", &M, Long, &[0x0F, 0xAE], ext(0, 5), NO_IMM),
bytes("xrstor64", &M, Quad, &[0x0F, 0xAE], ext(0, 5), NO_IMM),
bytes("xsaveopt", &M, Long, &[0x0F, 0xAE], ext(0, 6), NO_IMM),
bytes("xsaveopt64", &M, Quad, &[0x0F, 0xAE], ext(0, 6), NO_IMM),
bytes("xrstors", &M, Long, &[0x0F, 0xC7], ext(0, 3), NO_IMM),
bytes("xrstors64", &M, Quad, &[0x0F, 0xC7], ext(0, 3), NO_IMM),
bytes("xsavec", &M, Long, &[0x0F, 0xC7], ext(0, 4), NO_IMM),
bytes("xsavec64", &M, Quad, &[0x0F, 0xC7], ext(0, 4), NO_IMM),
bytes("xsaves", &M, Long, &[0x0F, 0xC7], ext(0, 5), NO_IMM),
bytes("xsaves64", &M, Quad, &[0x0F, 0xC7], ext(0, 5), NO_IMM),
bytes("rdrandw", &R, Word, &[0x0F, 0xC7], ext(0, 6), NO_IMM),
bytes("rdrandl", &R, Long, &[0x0F, 0xC7], ext(0, 6), NO_IMM),
bytes("rdrandq", &R, Quad, &[0x0F, 0xC7], ext(0, 6), NO_IMM),
bytes("rdseedw", &R, Word, &[0x0F, 0xC7], ext(0, 7), NO_IMM),
bytes("rdseedl", &R, Long, &[0x0F, 0xC7], ext(0, 7), NO_IMM),
bytes("rdseedq", &R, Quad, &[0x0F, 0xC7], ext(0, 7), NO_IMM),
bytes("rdpid", &R, Single, &[0x0F, 0xC7], ext(0, 7), NO_IMM),
bytes("ud1l", &RR, Long, &[0x0F, 0xB9], pair(0, 1), NO_IMM),
bytes("ud1l", &MR, Long, &[0x0F, 0xB9], pair(0, 1), NO_IMM),
bytes("ud1q", &RR, Quad, &[0x0F, 0xB9], pair(0, 1), NO_IMM),
bytes("ud1q", &MR, Quad, &[0x0F, 0xB9], pair(0, 1), NO_IMM),
bytes("movdir64b", &MR, Word, &[0x0F, 0x38, 0xF8], pair(0, 1), NO_IMM),
bytes("enqcmds", &MR, Single, &[0x0F, 0x38, 0xF8], pair(0, 1), NO_IMM),
bytes("enqcmd", &MR, Double, &[0x0F, 0x38, 0xF8], pair(0, 1), NO_IMM),
bytes("movdiril", &RM, Long, &[0x0F, 0x38, 0xF9], pair(1, 0), NO_IMM),
bytes("movdiriq", &RM, Quad, &[0x0F, 0x38, 0xF9], pair(1, 0), NO_IMM),
bytes("wrssd", &RM, Long, &[0x0F, 0x38, 0xF6], pair(1, 0), NO_IMM),
bytes("wrssq", &RM, Quad, &[0x0F, 0x38, 0xF6], pair(1, 0), NO_IMM),
bytes("wrussd", &RM, Word, &[0x0F, 0x38, 0xF5], pair(1, 0), NO_IMM),
bytes("wrussq", &RM, WordQuad, &[0x0F, 0x38, 0xF5], pair(1, 0), NO_IMM),
bytes("rdsspd", &R, Single, &[0x0F, 0x1E], ext(0, 1), NO_IMM),
bytes("rdsspq", &R, SingleQuad, &[0x0F, 0x1E], ext(0, 1), NO_IMM),
bytes("incsspd", &R, Single, &[0x0F, 0xAE], ext(0, 5), NO_IMM),
bytes("incsspq", &R, SingleQuad, &[0x0F, 0xAE], ext(0, 5), NO_IMM),
bytes("rstorssp", &M, Single, &[0x0F, 0x01], ext(0, 5), NO_IMM),
bytes("clrssbsy", &M, Single, &[0x0F, 0xAE], ext(0, 6), NO_IMM),
bytes("saveprevssp", &NO_ARGS, Long, &[0xF3, 0x0F, 0x01, 0xEA], NO_MODRM, NO_IMM),
bytes("setssbsy", &NO_ARGS, Long, &[0xF3, 0x0F, 0x01, 0xE8], NO_MODRM, NO_IMM),
bytes("tpause", &R, Word, &[0x0F, 0xAE], ext(0, 6), NO_IMM),
bytes("umwait", &R, Double, &[0x0F, 0xAE], ext(0, 6), NO_IMM),
bytes("umonitor", &R, Single, &[0x0F, 0xAE], ext(0, 6), NO_IMM),
bytes("inb", &RR, Long, &[0xEC], NO_MODRM, NO_IMM),
bytes("inw", &RR, Word, &[0xED], NO_MODRM, NO_IMM),
bytes("inl", &RR, Long, &[0xED], NO_MODRM, NO_IMM),
takes("inb", &IR, Fits::Byte, Long, &[0xE4], NO_MODRM, ImmSize::Ib),
takes("inw", &IR, Fits::Byte, Word, &[0xE5], NO_MODRM, ImmSize::Ib),
takes("inl", &IR, Fits::Byte, Long, &[0xE5], NO_MODRM, ImmSize::Ib),
bytes("outb", &RR, Long, &[0xEE], NO_MODRM, NO_IMM),
bytes("outw", &RR, Word, &[0xEF], NO_MODRM, NO_IMM),
bytes("outl", &RR, Long, &[0xEF], NO_MODRM, NO_IMM),
takes("outb", &RI, Fits::Byte, Long, &[0xE6], NO_MODRM, ImmSize::Ib),
takes("outw", &RI, Fits::Byte, Word, &[0xE7], NO_MODRM, ImmSize::Ib),
takes("outl", &RI, Fits::Byte, Long, &[0xE7], NO_MODRM, ImmSize::Ib),
bytes("insb", &NO_ARGS, Byte, &[0x6C], NO_MODRM, NO_IMM),
bytes("insw", &NO_ARGS, Word, &[0x6D], NO_MODRM, NO_IMM),
bytes("insl", &NO_ARGS, Long, &[0x6D], NO_MODRM, NO_IMM),
bytes("outsb", &NO_ARGS, Byte, &[0x6E], NO_MODRM, NO_IMM),
bytes("outsw", &NO_ARGS, Word, &[0x6F], NO_MODRM, NO_IMM),
bytes("outsl", &NO_ARGS, Long, &[0x6F], NO_MODRM, NO_IMM),
bytes("rep insb", &NO_ARGS, Single, &[0x6C], NO_MODRM, NO_IMM),
bytes("rep insw", &NO_ARGS, Word, &[0xF3, 0x6D], NO_MODRM, NO_IMM),
bytes("rep insl", &NO_ARGS, Single, &[0x6D], NO_MODRM, NO_IMM),
bytes("rep outsb", &NO_ARGS, Single, &[0x6E], NO_MODRM, NO_IMM),
bytes("rep outsw", &NO_ARGS, Word, &[0xF3, 0x6F], NO_MODRM, NO_IMM),
bytes("rep outsl", &NO_ARGS, Single, &[0x6F], NO_MODRM, NO_IMM),
bytes("rep lodsb", &NO_ARGS, Single, &[0xAC], NO_MODRM, NO_IMM),
bytes("rep lodsw", &NO_ARGS, Word, &[0xF3, 0xAD], NO_MODRM, NO_IMM),
bytes("rep lodsl", &NO_ARGS, Single, &[0xAD], NO_MODRM, NO_IMM),
bytes("rep lodsq", &NO_ARGS, SingleQuad, &[0xAD], NO_MODRM, NO_IMM),
bytes("es", &NO_ARGS, Long, &[0x26], NO_MODRM, NO_IMM),
bytes("cs", &NO_ARGS, Long, &[0x2E], NO_MODRM, NO_IMM),
bytes("ss", &NO_ARGS, Long, &[0x36], NO_MODRM, NO_IMM),
bytes("ds", &NO_ARGS, Long, &[0x3E], NO_MODRM, NO_IMM),
bytes("notrack", &NO_ARGS, Long, &[0x3E], NO_MODRM, NO_IMM),
bytes("fs", &NO_ARGS, Long, &[0x64], NO_MODRM, NO_IMM),
bytes("gs", &NO_ARGS, Long, &[0x65], NO_MODRM, NO_IMM),
bytes("data16", &NO_ARGS, Long, &[0x66], NO_MODRM, NO_IMM),
bytes("addr32", &NO_ARGS, Long, &[0x67], NO_MODRM, NO_IMM),
bytes("rex64", &NO_ARGS, Long, &[0x48], NO_MODRM, NO_IMM),
bytes("xacquire", &NO_ARGS, Long, &[0xF2], NO_MODRM, NO_IMM),
bytes("xrelease", &NO_ARGS, Long, &[0xF3], NO_MODRM, NO_IMM),
bytes("rep movsb", &NO_ARGS, Single, &[0xA4], NO_MODRM, NO_IMM),
bytes("rep movsw", &NO_ARGS, Word, &[0xF3, 0xA5], NO_MODRM, NO_IMM),
bytes("rep movsl", &NO_ARGS, Single, &[0xA5], NO_MODRM, NO_IMM),
bytes("rep movsq", &NO_ARGS, SingleQuad, &[0xA5], NO_MODRM, NO_IMM),
bytes("stosb", &NO_ARGS, Byte, &[0xAA], NO_MODRM, NO_IMM),
bytes("stosw", &NO_ARGS, Word, &[0xAB], NO_MODRM, NO_IMM),
bytes("stosl", &NO_ARGS, Long, &[0xAB], NO_MODRM, NO_IMM),
bytes("stosq", &NO_ARGS, Quad, &[0xAB], NO_MODRM, NO_IMM),
bytes("rep stosb", &NO_ARGS, Single, &[0xAA], NO_MODRM, NO_IMM),
bytes("rep stosw", &NO_ARGS, Word, &[0xF3, 0xAB], NO_MODRM, NO_IMM),
bytes("rep stosl", &NO_ARGS, Single, &[0xAB], NO_MODRM, NO_IMM),
bytes("rep stosq", &NO_ARGS, SingleQuad, &[0xAB], NO_MODRM, NO_IMM),
bytes("lodsb", &NO_ARGS, Byte, &[0xAC], NO_MODRM, NO_IMM),
bytes("lodsw", &NO_ARGS, Word, &[0xAD], NO_MODRM, NO_IMM),
bytes("lodsl", &NO_ARGS, Long, &[0xAD], NO_MODRM, NO_IMM),
bytes("lodsq", &NO_ARGS, Quad, &[0xAD], NO_MODRM, NO_IMM),
bytes("scasb", &NO_ARGS, Byte, &[0xAE], NO_MODRM, NO_IMM),
bytes("scasw", &NO_ARGS, Word, &[0xAF], NO_MODRM, NO_IMM),
bytes("scasl", &NO_ARGS, Long, &[0xAF], NO_MODRM, NO_IMM),
bytes("scasq", &NO_ARGS, Quad, &[0xAF], NO_MODRM, NO_IMM),
bytes("repe scasb", &NO_ARGS, Single, &[0xAE], NO_MODRM, NO_IMM),
bytes("repe scasw", &NO_ARGS, Word, &[0xF3, 0xAF], NO_MODRM, NO_IMM),
bytes("repe scasl", &NO_ARGS, Single, &[0xAF], NO_MODRM, NO_IMM),
bytes("repe scasq", &NO_ARGS, SingleQuad, &[0xAF], NO_MODRM, NO_IMM),
bytes("repne scasb", &NO_ARGS, Double, &[0xAE], NO_MODRM, NO_IMM),
bytes("repne scasw", &NO_ARGS, Word, &[0xF2, 0xAF], NO_MODRM, NO_IMM),
bytes("repne scasl", &NO_ARGS, Double, &[0xAF], NO_MODRM, NO_IMM),
bytes("repne scasq", &NO_ARGS, DoubleQuad, &[0xAF], NO_MODRM, NO_IMM),
bytes("cmpsb", &NO_ARGS, Byte, &[0xA6], NO_MODRM, NO_IMM),
bytes("cmpsw", &NO_ARGS, Word, &[0xA7], NO_MODRM, NO_IMM),
bytes("cmpsl", &NO_ARGS, Long, &[0xA7], NO_MODRM, NO_IMM),
bytes("cmpsq", &NO_ARGS, Quad, &[0xA7], NO_MODRM, NO_IMM),
bytes("repe cmpsb", &NO_ARGS, Single, &[0xA6], NO_MODRM, NO_IMM),
bytes("repe cmpsw", &NO_ARGS, Word, &[0xF3, 0xA7], NO_MODRM, NO_IMM),
bytes("repe cmpsl", &NO_ARGS, Single, &[0xA7], NO_MODRM, NO_IMM),
bytes("repe cmpsq", &NO_ARGS, SingleQuad, &[0xA7], NO_MODRM, NO_IMM),
bytes("repne cmpsb", &NO_ARGS, Double, &[0xA6], NO_MODRM, NO_IMM),
bytes("repne cmpsw", &NO_ARGS, Word, &[0xF2, 0xA7], NO_MODRM, NO_IMM),
bytes("repne cmpsl", &NO_ARGS, Double, &[0xA7], NO_MODRM, NO_IMM),
bytes("repne cmpsq", &NO_ARGS, DoubleQuad, &[0xA7], NO_MODRM, NO_IMM),
bytes("lock", &NO_ARGS, Long, &[0xF0], NO_MODRM, NO_IMM),
bytes("rep", &NO_ARGS, Long, &[0xF3], NO_MODRM, NO_IMM),
bytes("repe", &NO_ARGS, Long, &[0xF3], NO_MODRM, NO_IMM),
bytes("repz", &NO_ARGS, Long, &[0xF3], NO_MODRM, NO_IMM),
bytes("repne", &NO_ARGS, Long, &[0xF2], NO_MODRM, NO_IMM),
bytes("repnz", &NO_ARGS, Long, &[0xF2], NO_MODRM, NO_IMM),
bytes("cmpxchgb", &RM, Byte, &[0x0F, 0xB0], pair(1, 0), NO_IMM),
bytes("cmpxchgw", &RM, Word, &[0x0F, 0xB1], pair(1, 0), NO_IMM),
bytes("cmpxchgl", &RM, Long, &[0x0F, 0xB1], pair(1, 0), NO_IMM),
bytes("cmpxchgq", &RM, Quad, &[0x0F, 0xB1], pair(1, 0), NO_IMM),
bytes("cmpxchg8b", &M, Long, &[0x0F, 0xC7], ext(0, 1), NO_IMM),
bytes("cmpxchg16b", &M, Quad, &[0x0F, 0xC7], ext(0, 1), NO_IMM),
bytes("xchgb", &RM, Byte, &[0x86], pair(1, 0), NO_IMM),
bytes("xchgw", &RM, Word, &[0x87], pair(1, 0), NO_IMM),
bytes("xchgl", &RM, Long, &[0x87], pair(1, 0), NO_IMM),
bytes("xchgq", &RM, Quad, &[0x87], pair(1, 0), NO_IMM),
bytes("xchgb", &RR, Byte, &[0x86], pair(1, 0), NO_IMM),
bytes("xchgw", &RR, Word, &[0x87], pair(1, 0), NO_IMM),
bytes("xchgl", &RR, Long, &[0x87], pair(1, 0), NO_IMM),
bytes("xchgq", &RR, Quad, &[0x87], pair(1, 0), NO_IMM),
bytes("xaddb", &RM, Byte, &[0x0F, 0xC0], pair(1, 0), NO_IMM),
bytes("xaddw", &RM, Word, &[0x0F, 0xC1], pair(1, 0), NO_IMM),
bytes("xaddl", &RM, Long, &[0x0F, 0xC1], pair(1, 0), NO_IMM),
bytes("xaddq", &RM, Quad, &[0x0F, 0xC1], pair(1, 0), NO_IMM),
bytes("movaps", &VV, Long, &[0x0F, 0x28], pair(0, 1), NO_IMM),
bytes("movaps", &MV, Long, &[0x0F, 0x28], pair(0, 1), NO_IMM),
bytes("movaps", &VM, Long, &[0x0F, 0x29], pair(1, 0), NO_IMM),
bytes("movss", &MV, Single, &[0x0F, 0x10], pair(0, 1), NO_IMM),
bytes("movsd", &MV, Double, &[0x0F, 0x10], pair(0, 1), NO_IMM),
bytes("movss", &VM, Single, &[0x0F, 0x11], pair(1, 0), NO_IMM),
bytes("movsd", &VM, Double, &[0x0F, 0x11], pair(1, 0), NO_IMM),
bytes("movss", &VV, Single, &[0x0F, 0x10], pair(0, 1), NO_IMM),
bytes("movsd", &VV, Double, &[0x0F, 0x10], pair(0, 1), NO_IMM),
bytes("addss", &VV, Single, &[0x0F, 0x58], pair(0, 1), NO_IMM),
bytes("addsd", &VV, Double, &[0x0F, 0x58], pair(0, 1), NO_IMM),
bytes("mulss", &VV, Single, &[0x0F, 0x59], pair(0, 1), NO_IMM),
bytes("mulsd", &VV, Double, &[0x0F, 0x59], pair(0, 1), NO_IMM),
bytes("subss", &VV, Single, &[0x0F, 0x5C], pair(0, 1), NO_IMM),
bytes("subsd", &VV, Double, &[0x0F, 0x5C], pair(0, 1), NO_IMM),
bytes("divss", &VV, Single, &[0x0F, 0x5E], pair(0, 1), NO_IMM),
bytes("divsd", &VV, Double, &[0x0F, 0x5E], pair(0, 1), NO_IMM),
bytes("cvtss2sd", &VV, Single, &[0x0F, 0x5A], pair(0, 1), NO_IMM),
bytes("cvtsd2ss", &VV, Double, &[0x0F, 0x5A], pair(0, 1), NO_IMM),
bytes("cvttss2sil", &VR, Single, &[0x0F, 0x2C], pair(0, 1), NO_IMM),
bytes("cvttss2siq", &VR, SingleQuad, &[0x0F, 0x2C], pair(0, 1), NO_IMM),
bytes("cvttsd2sil", &VR, Double, &[0x0F, 0x2C], pair(0, 1), NO_IMM),
bytes("cvttsd2siq", &VR, DoubleQuad, &[0x0F, 0x2C], pair(0, 1), NO_IMM),
bytes("cvtsi2ssl", &RV, Single, &[0x0F, 0x2A], pair(0, 1), NO_IMM),
bytes("cvtsi2ssq", &RV, SingleQuad, &[0x0F, 0x2A], pair(0, 1), NO_IMM),
bytes("cvtsi2sdl", &RV, Double, &[0x0F, 0x2A], pair(0, 1), NO_IMM),
bytes("cvtsi2sdq", &RV, DoubleQuad, &[0x0F, 0x2A], pair(0, 1), NO_IMM),
bytes("movd", &RV, Word, &[0x0F, 0x6E], pair(0, 1), NO_IMM),
bytes("movq", &RV, WordQuad, &[0x0F, 0x6E], pair(0, 1), NO_IMM),
bytes("movd", &VR, Word, &[0x0F, 0x7E], pair(1, 0), NO_IMM),
bytes("movq", &VR, WordQuad, &[0x0F, 0x7E], pair(1, 0), NO_IMM),
bytes("pinsrw", &IMV, Word, &[0x0F, 0xC4], pair(1, 2), ImmSize::Ib),
bytes("pinsrw", &IRV, Word, &[0x0F, 0xC4], pair(1, 2), ImmSize::Ib),
bytes("pextrw", &IVR, Word, &[0x0F, 0xC5], pair(1, 2), ImmSize::Ib),
bytes("ucomiss", &VV, Long, &[0x0F, 0x2E], pair(0, 1), NO_IMM),
bytes("ucomisd", &VV, Word, &[0x0F, 0x2E], pair(0, 1), NO_IMM),
bytes("movq", &MV, Single, &[0x0F, 0x7E], pair(0, 1), NO_IMM),
bytes("movq", &VM, Word, &[0x0F, 0xD6], pair(1, 0), NO_IMM),
bytes("movdqa", &VV, Word, &[0x0F, 0x6F], pair(0, 1), NO_IMM),
bytes("movdqa", &MV, Word, &[0x0F, 0x6F], pair(0, 1), NO_IMM),
bytes("movdqa", &VM, Word, &[0x0F, 0x7F], pair(1, 0), NO_IMM),
bytes("movdqu", &VV, Single, &[0x0F, 0x6F], pair(0, 1), NO_IMM),
bytes("movdqu", &MV, Single, &[0x0F, 0x6F], pair(0, 1), NO_IMM),
bytes("movdqu", &VM, Single, &[0x0F, 0x7F], pair(1, 0), NO_IMM),
bytes("punpcklqdq", &VV, Word, &[0x0F, 0x6C], pair(0, 1), NO_IMM),
bytes("punpcklqdq", &MV, Word, &[0x0F, 0x6C], pair(0, 1), NO_IMM),
bytes("punpckhqdq", &VV, Word, &[0x0F, 0x6D], pair(0, 1), NO_IMM),
bytes("punpckhqdq", &MV, Word, &[0x0F, 0x6D], pair(0, 1), NO_IMM),
bytes("pand", &VV, Word, &[0x0F, 0xDB], pair(0, 1), NO_IMM),
bytes("pand", &MV, Word, &[0x0F, 0xDB], pair(0, 1), NO_IMM),
bytes("pandn", &VV, Word, &[0x0F, 0xDF], pair(0, 1), NO_IMM),
bytes("pandn", &MV, Word, &[0x0F, 0xDF], pair(0, 1), NO_IMM),
bytes("por", &VV, Word, &[0x0F, 0xEB], pair(0, 1), NO_IMM),
bytes("por", &MV, Word, &[0x0F, 0xEB], pair(0, 1), NO_IMM),
bytes("pxor", &VV, Word, &[0x0F, 0xEF], pair(0, 1), NO_IMM),
bytes("pxor", &MV, Word, &[0x0F, 0xEF], pair(0, 1), NO_IMM),
bytes("pcmpeqb", &VV, Word, &[0x0F, 0x74], pair(0, 1), NO_IMM),
bytes("pcmpeqb", &MV, Word, &[0x0F, 0x74], pair(0, 1), NO_IMM),
bytes("pcmpeqw", &VV, Word, &[0x0F, 0x75], pair(0, 1), NO_IMM),
bytes("pcmpeqw", &MV, Word, &[0x0F, 0x75], pair(0, 1), NO_IMM),
bytes("pcmpeqd", &VV, Word, &[0x0F, 0x76], pair(0, 1), NO_IMM),
bytes("pcmpeqd", &MV, Word, &[0x0F, 0x76], pair(0, 1), NO_IMM),
bytes("paddb", &VV, Word, &[0x0F, 0xFC], pair(0, 1), NO_IMM),
bytes("paddw", &VV, Word, &[0x0F, 0xFD], pair(0, 1), NO_IMM),
bytes("paddd", &VV, Word, &[0x0F, 0xFE], pair(0, 1), NO_IMM),
bytes("paddq", &VV, Word, &[0x0F, 0xD4], pair(0, 1), NO_IMM),
bytes("psubb", &VV, Word, &[0x0F, 0xF8], pair(0, 1), NO_IMM),
bytes("psubw", &VV, Word, &[0x0F, 0xF9], pair(0, 1), NO_IMM),
bytes("psubd", &VV, Word, &[0x0F, 0xFA], pair(0, 1), NO_IMM),
bytes("psubq", &VV, Word, &[0x0F, 0xFB], pair(0, 1), NO_IMM),
bytes("psllw", &VV, Word, &[0x0F, 0xF1], pair(0, 1), NO_IMM),
bytes("pslld", &VV, Word, &[0x0F, 0xF2], pair(0, 1), NO_IMM),
bytes("psllq", &VV, Word, &[0x0F, 0xF3], pair(0, 1), NO_IMM),
bytes("psrlw", &VV, Word, &[0x0F, 0xD1], pair(0, 1), NO_IMM),
bytes("psrld", &VV, Word, &[0x0F, 0xD2], pair(0, 1), NO_IMM),
bytes("psrlq", &VV, Word, &[0x0F, 0xD3], pair(0, 1), NO_IMM),
bytes("psraw", &VV, Word, &[0x0F, 0xE1], pair(0, 1), NO_IMM),
bytes("psrad", &VV, Word, &[0x0F, 0xE2], pair(0, 1), NO_IMM),
bytes("psllw", &IV, Word, &[0x0F, 0x71], ext(1, 6), ImmSize::Ib),
bytes("psrlw", &IV, Word, &[0x0F, 0x71], ext(1, 2), ImmSize::Ib),
bytes("psraw", &IV, Word, &[0x0F, 0x71], ext(1, 4), ImmSize::Ib),
bytes("pslld", &IV, Word, &[0x0F, 0x72], ext(1, 6), ImmSize::Ib),
bytes("psrld", &IV, Word, &[0x0F, 0x72], ext(1, 2), ImmSize::Ib),
bytes("psrad", &IV, Word, &[0x0F, 0x72], ext(1, 4), ImmSize::Ib),
bytes("psllq", &IV, Word, &[0x0F, 0x73], ext(1, 6), ImmSize::Ib),
bytes("psrlq", &IV, Word, &[0x0F, 0x73], ext(1, 2), ImmSize::Ib),
bytes("pslldq", &IV, Word, &[0x0F, 0x73], ext(1, 7), ImmSize::Ib),
bytes("psrldq", &IV, Word, &[0x0F, 0x73], ext(1, 3), ImmSize::Ib),
bytes("addss", &MV, Single, &[0x0F, 0x58], pair(0, 1), NO_IMM),
bytes("addsd", &MV, Double, &[0x0F, 0x58], pair(0, 1), NO_IMM),
bytes("mulss", &MV, Single, &[0x0F, 0x59], pair(0, 1), NO_IMM),
bytes("mulsd", &MV, Double, &[0x0F, 0x59], pair(0, 1), NO_IMM),
bytes("subss", &MV, Single, &[0x0F, 0x5C], pair(0, 1), NO_IMM),
bytes("subsd", &MV, Double, &[0x0F, 0x5C], pair(0, 1), NO_IMM),
bytes("divss", &MV, Single, &[0x0F, 0x5E], pair(0, 1), NO_IMM),
bytes("divsd", &MV, Double, &[0x0F, 0x5E], pair(0, 1), NO_IMM),
bytes("sqrtss", &VV, Single, &[0x0F, 0x51], pair(0, 1), NO_IMM),
bytes("sqrtsd", &VV, Double, &[0x0F, 0x51], pair(0, 1), NO_IMM),
bytes("sqrtss", &MV, Single, &[0x0F, 0x51], pair(0, 1), NO_IMM),
bytes("sqrtsd", &MV, Double, &[0x0F, 0x51], pair(0, 1), NO_IMM),
bytes("minss", &VV, Single, &[0x0F, 0x5D], pair(0, 1), NO_IMM),
bytes("minsd", &VV, Double, &[0x0F, 0x5D], pair(0, 1), NO_IMM),
bytes("minss", &MV, Single, &[0x0F, 0x5D], pair(0, 1), NO_IMM),
bytes("minsd", &MV, Double, &[0x0F, 0x5D], pair(0, 1), NO_IMM),
bytes("maxss", &VV, Single, &[0x0F, 0x5F], pair(0, 1), NO_IMM),
bytes("maxsd", &VV, Double, &[0x0F, 0x5F], pair(0, 1), NO_IMM),
bytes("maxss", &MV, Single, &[0x0F, 0x5F], pair(0, 1), NO_IMM),
bytes("maxsd", &MV, Double, &[0x0F, 0x5F], pair(0, 1), NO_IMM),
bytes("cvtss2sd", &MV, Single, &[0x0F, 0x5A], pair(0, 1), NO_IMM),
bytes("cvtsd2ss", &MV, Double, &[0x0F, 0x5A], pair(0, 1), NO_IMM),
bytes("cvtsi2ssl", &MV, Single, &[0x0F, 0x2A], pair(0, 1), NO_IMM),
bytes("cvtsi2ssq", &MV, SingleQuad, &[0x0F, 0x2A], pair(0, 1), NO_IMM),
bytes("cvtsi2sdl", &MV, Double, &[0x0F, 0x2A], pair(0, 1), NO_IMM),
bytes("cvtsi2sdq", &MV, DoubleQuad, &[0x0F, 0x2A], pair(0, 1), NO_IMM),
bytes("cvttss2sil", &MR, Single, &[0x0F, 0x2C], pair(0, 1), NO_IMM),
bytes("cvttss2siq", &MR, SingleQuad, &[0x0F, 0x2C], pair(0, 1), NO_IMM),
bytes("cvttsd2sil", &MR, Double, &[0x0F, 0x2C], pair(0, 1), NO_IMM),
bytes("cvttsd2siq", &MR, DoubleQuad, &[0x0F, 0x2C], pair(0, 1), NO_IMM),
bytes("ucomiss", &MV, Long, &[0x0F, 0x2E], pair(0, 1), NO_IMM),
bytes("ucomisd", &MV, Word, &[0x0F, 0x2E], pair(0, 1), NO_IMM),
bytes("comiss", &VV, Long, &[0x0F, 0x2F], pair(0, 1), NO_IMM),
bytes("comisd", &VV, Word, &[0x0F, 0x2F], pair(0, 1), NO_IMM),
bytes("comiss", &MV, Long, &[0x0F, 0x2F], pair(0, 1), NO_IMM),
bytes("comisd", &MV, Word, &[0x0F, 0x2F], pair(0, 1), NO_IMM),
bytes("movups", &VV, Long, &[0x0F, 0x10], pair(0, 1), NO_IMM),
bytes("movups", &MV, Long, &[0x0F, 0x10], pair(0, 1), NO_IMM),
bytes("movups", &VM, Long, &[0x0F, 0x11], pair(1, 0), NO_IMM),
bytes("movupd", &VV, Word, &[0x0F, 0x10], pair(0, 1), NO_IMM),
bytes("movupd", &MV, Word, &[0x0F, 0x10], pair(0, 1), NO_IMM),
bytes("movupd", &VM, Word, &[0x0F, 0x11], pair(1, 0), NO_IMM),
bytes("movapd", &VV, Word, &[0x0F, 0x28], pair(0, 1), NO_IMM),
bytes("movapd", &MV, Word, &[0x0F, 0x28], pair(0, 1), NO_IMM),
bytes("movapd", &VM, Word, &[0x0F, 0x29], pair(1, 0), NO_IMM),
bytes("andps", &VV, Long, &[0x0F, 0x54], pair(0, 1), NO_IMM),
bytes("andpd", &VV, Word, &[0x0F, 0x54], pair(0, 1), NO_IMM),
bytes("andps", &MV, Long, &[0x0F, 0x54], pair(0, 1), NO_IMM),
bytes("andpd", &MV, Word, &[0x0F, 0x54], pair(0, 1), NO_IMM),
bytes("andnps", &VV, Long, &[0x0F, 0x55], pair(0, 1), NO_IMM),
bytes("andnpd", &VV, Word, &[0x0F, 0x55], pair(0, 1), NO_IMM),
bytes("andnps", &MV, Long, &[0x0F, 0x55], pair(0, 1), NO_IMM),
bytes("andnpd", &MV, Word, &[0x0F, 0x55], pair(0, 1), NO_IMM),
bytes("orps", &VV, Long, &[0x0F, 0x56], pair(0, 1), NO_IMM),
bytes("orpd", &VV, Word, &[0x0F, 0x56], pair(0, 1), NO_IMM),
bytes("orps", &MV, Long, &[0x0F, 0x56], pair(0, 1), NO_IMM),
bytes("orpd", &MV, Word, &[0x0F, 0x56], pair(0, 1), NO_IMM),
bytes("xorps", &VV, Long, &[0x0F, 0x57], pair(0, 1), NO_IMM),
bytes("xorpd", &VV, Word, &[0x0F, 0x57], pair(0, 1), NO_IMM),
bytes("xorps", &MV, Long, &[0x0F, 0x57], pair(0, 1), NO_IMM),
bytes("xorpd", &MV, Word, &[0x0F, 0x57], pair(0, 1), NO_IMM),
bytes("movlps", &MV, Long, &[0x0F, 0x12], pair(0, 1), NO_IMM),
bytes("movlps", &VM, Long, &[0x0F, 0x13], pair(1, 0), NO_IMM),
bytes("movhps", &MV, Long, &[0x0F, 0x16], pair(0, 1), NO_IMM),
bytes("movhps", &VM, Long, &[0x0F, 0x17], pair(1, 0), NO_IMM),
bytes("movlpd", &MV, Word, &[0x0F, 0x12], pair(0, 1), NO_IMM),
bytes("movlpd", &VM, Word, &[0x0F, 0x13], pair(1, 0), NO_IMM),
bytes("movhpd", &MV, Word, &[0x0F, 0x16], pair(0, 1), NO_IMM),
bytes("movhpd", &VM, Word, &[0x0F, 0x17], pair(1, 0), NO_IMM),
bytes("movhlps", &VV, Long, &[0x0F, 0x12], pair(0, 1), NO_IMM),
bytes("movlhps", &VV, Long, &[0x0F, 0x16], pair(0, 1), NO_IMM),
bytes("movd", &MV, Word, &[0x0F, 0x6E], pair(0, 1), NO_IMM),
bytes("movd", &VM, Word, &[0x0F, 0x7E], pair(1, 0), NO_IMM),
bytes("shufps", &IVV, Long, &[0x0F, 0xC6], pair(1, 2), ImmSize::Ib),
bytes("shufps", &IMV, Long, &[0x0F, 0xC6], pair(1, 2), ImmSize::Ib),
bytes("shufpd", &IVV, Word, &[0x0F, 0xC6], pair(1, 2), ImmSize::Ib),
bytes("shufpd", &IMV, Word, &[0x0F, 0xC6], pair(1, 2), ImmSize::Ib),
bytes("pshufd", &IVV, Word, &[0x0F, 0x70], pair(1, 2), ImmSize::Ib),
bytes("pshufd", &IMV, Word, &[0x0F, 0x70], pair(1, 2), ImmSize::Ib),
bytes("pshuflw", &IVV, Double, &[0x0F, 0x70], pair(1, 2), ImmSize::Ib),
bytes("pshuflw", &IMV, Double, &[0x0F, 0x70], pair(1, 2), ImmSize::Ib),
bytes("pshufhw", &IVV, Single, &[0x0F, 0x70], pair(1, 2), ImmSize::Ib),
bytes("pshufhw", &IMV, Single, &[0x0F, 0x70], pair(1, 2), ImmSize::Ib),
bytes("pshufb", &VV, Word, &[0x0F, 0x38, 0x00], pair(0, 1), NO_IMM),
bytes("pshufb", &MV, Word, &[0x0F, 0x38, 0x00], pair(0, 1), NO_IMM),
bytes("palignr", &IVV, Word, &[0x0F, 0x3A, 0x0F], pair(1, 2), ImmSize::Ib),
bytes("palignr", &IMV, Word, &[0x0F, 0x3A, 0x0F], pair(1, 2), ImmSize::Ib),
bytes("aesenc", &VV, Word, &[0x0F, 0x38, 0xDC], pair(0, 1), NO_IMM),
bytes("aesenc", &MV, Word, &[0x0F, 0x38, 0xDC], pair(0, 1), NO_IMM),
bytes("aesenclast", &VV, Word, &[0x0F, 0x38, 0xDD], pair(0, 1), NO_IMM),
bytes("aesenclast", &MV, Word, &[0x0F, 0x38, 0xDD], pair(0, 1), NO_IMM),
bytes("aesdec", &VV, Word, &[0x0F, 0x38, 0xDE], pair(0, 1), NO_IMM),
bytes("aesdec", &MV, Word, &[0x0F, 0x38, 0xDE], pair(0, 1), NO_IMM),
bytes("aesdeclast", &VV, Word, &[0x0F, 0x38, 0xDF], pair(0, 1), NO_IMM),
bytes("aesdeclast", &MV, Word, &[0x0F, 0x38, 0xDF], pair(0, 1), NO_IMM),
bytes("aesimc", &VV, Word, &[0x0F, 0x38, 0xDB], pair(0, 1), NO_IMM),
bytes("aesimc", &MV, Word, &[0x0F, 0x38, 0xDB], pair(0, 1), NO_IMM),
bytes("aeskeygenassist", &IVV, Word, &[0x0F, 0x3A, 0xDF], pair(1, 2), ImmSize::Ib),
bytes("aeskeygenassist", &IMV, Word, &[0x0F, 0x3A, 0xDF], pair(1, 2), ImmSize::Ib),
bytes("pclmulqdq", &IVV, Word, &[0x0F, 0x3A, 0x44], pair(1, 2), ImmSize::Ib),
bytes("pclmulqdq", &IMV, Word, &[0x0F, 0x3A, 0x44], pair(1, 2), ImmSize::Ib),
bytes("pinsrb", &IRV, Word, &[0x0F, 0x3A, 0x20], pair(1, 2), ImmSize::Ib),
bytes("pinsrb", &IMV, Word, &[0x0F, 0x3A, 0x20], pair(1, 2), ImmSize::Ib),
bytes("pinsrd", &IRV, Word, &[0x0F, 0x3A, 0x22], pair(1, 2), ImmSize::Ib),
bytes("pinsrd", &IMV, Word, &[0x0F, 0x3A, 0x22], pair(1, 2), ImmSize::Ib),
bytes("pinsrq", &IRV, WordQuad, &[0x0F, 0x3A, 0x22], pair(1, 2), ImmSize::Ib),
bytes("pinsrq", &IMV, WordQuad, &[0x0F, 0x3A, 0x22], pair(1, 2), ImmSize::Ib),
bytes("pextrb", &IVR, Word, &[0x0F, 0x3A, 0x14], pair(2, 1), ImmSize::Ib),
bytes("pextrb", &IVM, Word, &[0x0F, 0x3A, 0x14], pair(2, 1), ImmSize::Ib),
bytes("pextrd", &IVR, Word, &[0x0F, 0x3A, 0x16], pair(2, 1), ImmSize::Ib),
bytes("pextrd", &IVM, Word, &[0x0F, 0x3A, 0x16], pair(2, 1), ImmSize::Ib),
bytes("pextrq", &IVR, WordQuad, &[0x0F, 0x3A, 0x16], pair(2, 1), ImmSize::Ib),
bytes("pextrq", &IVM, WordQuad, &[0x0F, 0x3A, 0x16], pair(2, 1), ImmSize::Ib),
bytes("addsubps", &VV, Double, &[0x0F, 0xD0], pair(0, 1), NO_IMM),
bytes("addsubps", &MV, Double, &[0x0F, 0xD0], pair(0, 1), NO_IMM),
bytes("addsubpd", &VV, Word, &[0x0F, 0xD0], pair(0, 1), NO_IMM),
bytes("addsubpd", &MV, Word, &[0x0F, 0xD0], pair(0, 1), NO_IMM),
bytes("haddps", &VV, Double, &[0x0F, 0x7C], pair(0, 1), NO_IMM),
bytes("haddps", &MV, Double, &[0x0F, 0x7C], pair(0, 1), NO_IMM),
bytes("haddpd", &VV, Word, &[0x0F, 0x7C], pair(0, 1), NO_IMM),
bytes("haddpd", &MV, Word, &[0x0F, 0x7C], pair(0, 1), NO_IMM),
bytes("hsubps", &VV, Double, &[0x0F, 0x7D], pair(0, 1), NO_IMM),
bytes("hsubps", &MV, Double, &[0x0F, 0x7D], pair(0, 1), NO_IMM),
bytes("hsubpd", &VV, Word, &[0x0F, 0x7D], pair(0, 1), NO_IMM),
bytes("hsubpd", &MV, Word, &[0x0F, 0x7D], pair(0, 1), NO_IMM),
bytes("movshdup", &VV, Single, &[0x0F, 0x16], pair(0, 1), NO_IMM),
bytes("movshdup", &MV, Single, &[0x0F, 0x16], pair(0, 1), NO_IMM),
bytes("movsldup", &VV, Single, &[0x0F, 0x12], pair(0, 1), NO_IMM),
bytes("movsldup", &MV, Single, &[0x0F, 0x12], pair(0, 1), NO_IMM),
bytes("movddup", &VV, Double, &[0x0F, 0x12], pair(0, 1), NO_IMM),
bytes("movddup", &MV, Double, &[0x0F, 0x12], pair(0, 1), NO_IMM),
bytes("lddqu", &MV, Double, &[0x0F, 0xF0], pair(0, 1), NO_IMM),
bytes("phaddw", &VV, Word, &[0x0F, 0x38, 0x01], pair(0, 1), NO_IMM),
bytes("phaddw", &MV, Word, &[0x0F, 0x38, 0x01], pair(0, 1), NO_IMM),
bytes("phaddd", &VV, Word, &[0x0F, 0x38, 0x02], pair(0, 1), NO_IMM),
bytes("phaddd", &MV, Word, &[0x0F, 0x38, 0x02], pair(0, 1), NO_IMM),
bytes("phaddsw", &VV, Word, &[0x0F, 0x38, 0x03], pair(0, 1), NO_IMM),
bytes("phaddsw", &MV, Word, &[0x0F, 0x38, 0x03], pair(0, 1), NO_IMM),
bytes("pmaddubsw", &VV, Word, &[0x0F, 0x38, 0x04], pair(0, 1), NO_IMM),
bytes("pmaddubsw", &MV, Word, &[0x0F, 0x38, 0x04], pair(0, 1), NO_IMM),
bytes("phsubw", &VV, Word, &[0x0F, 0x38, 0x05], pair(0, 1), NO_IMM),
bytes("phsubw", &MV, Word, &[0x0F, 0x38, 0x05], pair(0, 1), NO_IMM),
bytes("phsubd", &VV, Word, &[0x0F, 0x38, 0x06], pair(0, 1), NO_IMM),
bytes("phsubd", &MV, Word, &[0x0F, 0x38, 0x06], pair(0, 1), NO_IMM),
bytes("phsubsw", &VV, Word, &[0x0F, 0x38, 0x07], pair(0, 1), NO_IMM),
bytes("phsubsw", &MV, Word, &[0x0F, 0x38, 0x07], pair(0, 1), NO_IMM),
bytes("psignb", &VV, Word, &[0x0F, 0x38, 0x08], pair(0, 1), NO_IMM),
bytes("psignb", &MV, Word, &[0x0F, 0x38, 0x08], pair(0, 1), NO_IMM),
bytes("psignw", &VV, Word, &[0x0F, 0x38, 0x09], pair(0, 1), NO_IMM),
bytes("psignw", &MV, Word, &[0x0F, 0x38, 0x09], pair(0, 1), NO_IMM),
bytes("psignd", &VV, Word, &[0x0F, 0x38, 0x0A], pair(0, 1), NO_IMM),
bytes("psignd", &MV, Word, &[0x0F, 0x38, 0x0A], pair(0, 1), NO_IMM),
bytes("pmulhrsw", &VV, Word, &[0x0F, 0x38, 0x0B], pair(0, 1), NO_IMM),
bytes("pmulhrsw", &MV, Word, &[0x0F, 0x38, 0x0B], pair(0, 1), NO_IMM),
bytes("pabsb", &VV, Word, &[0x0F, 0x38, 0x1C], pair(0, 1), NO_IMM),
bytes("pabsb", &MV, Word, &[0x0F, 0x38, 0x1C], pair(0, 1), NO_IMM),
bytes("pabsw", &VV, Word, &[0x0F, 0x38, 0x1D], pair(0, 1), NO_IMM),
bytes("pabsw", &MV, Word, &[0x0F, 0x38, 0x1D], pair(0, 1), NO_IMM),
bytes("pabsd", &VV, Word, &[0x0F, 0x38, 0x1E], pair(0, 1), NO_IMM),
bytes("pabsd", &MV, Word, &[0x0F, 0x38, 0x1E], pair(0, 1), NO_IMM),
bytes("pblendvb", &VV, Word, &[0x0F, 0x38, 0x10], pair(0, 1), NO_IMM),
bytes("pblendvb", &MV, Word, &[0x0F, 0x38, 0x10], pair(0, 1), NO_IMM),
bytes("blendvps", &VV, Word, &[0x0F, 0x38, 0x14], pair(0, 1), NO_IMM),
bytes("blendvps", &MV, Word, &[0x0F, 0x38, 0x14], pair(0, 1), NO_IMM),
bytes("blendvpd", &VV, Word, &[0x0F, 0x38, 0x15], pair(0, 1), NO_IMM),
bytes("blendvpd", &MV, Word, &[0x0F, 0x38, 0x15], pair(0, 1), NO_IMM),
bytes("ptest", &VV, Word, &[0x0F, 0x38, 0x17], pair(0, 1), NO_IMM),
bytes("ptest", &MV, Word, &[0x0F, 0x38, 0x17], pair(0, 1), NO_IMM),
bytes("pmovsxbw", &VV, Word, &[0x0F, 0x38, 0x20], pair(0, 1), NO_IMM),
bytes("pmovsxbw", &MV, Word, &[0x0F, 0x38, 0x20], pair(0, 1), NO_IMM),
bytes("pmovsxbd", &VV, Word, &[0x0F, 0x38, 0x21], pair(0, 1), NO_IMM),
bytes("pmovsxbd", &MV, Word, &[0x0F, 0x38, 0x21], pair(0, 1), NO_IMM),
bytes("pmovsxbq", &VV, Word, &[0x0F, 0x38, 0x22], pair(0, 1), NO_IMM),
bytes("pmovsxbq", &MV, Word, &[0x0F, 0x38, 0x22], pair(0, 1), NO_IMM),
bytes("pmovsxwd", &VV, Word, &[0x0F, 0x38, 0x23], pair(0, 1), NO_IMM),
bytes("pmovsxwd", &MV, Word, &[0x0F, 0x38, 0x23], pair(0, 1), NO_IMM),
bytes("pmovsxwq", &VV, Word, &[0x0F, 0x38, 0x24], pair(0, 1), NO_IMM),
bytes("pmovsxwq", &MV, Word, &[0x0F, 0x38, 0x24], pair(0, 1), NO_IMM),
bytes("pmovsxdq", &VV, Word, &[0x0F, 0x38, 0x25], pair(0, 1), NO_IMM),
bytes("pmovsxdq", &MV, Word, &[0x0F, 0x38, 0x25], pair(0, 1), NO_IMM),
bytes("pmuldq", &VV, Word, &[0x0F, 0x38, 0x28], pair(0, 1), NO_IMM),
bytes("pmuldq", &MV, Word, &[0x0F, 0x38, 0x28], pair(0, 1), NO_IMM),
bytes("pcmpeqq", &VV, Word, &[0x0F, 0x38, 0x29], pair(0, 1), NO_IMM),
bytes("pcmpeqq", &MV, Word, &[0x0F, 0x38, 0x29], pair(0, 1), NO_IMM),
bytes("packusdw", &VV, Word, &[0x0F, 0x38, 0x2B], pair(0, 1), NO_IMM),
bytes("packusdw", &MV, Word, &[0x0F, 0x38, 0x2B], pair(0, 1), NO_IMM),
bytes("pmovzxbw", &VV, Word, &[0x0F, 0x38, 0x30], pair(0, 1), NO_IMM),
bytes("pmovzxbw", &MV, Word, &[0x0F, 0x38, 0x30], pair(0, 1), NO_IMM),
bytes("pmovzxbd", &VV, Word, &[0x0F, 0x38, 0x31], pair(0, 1), NO_IMM),
bytes("pmovzxbd", &MV, Word, &[0x0F, 0x38, 0x31], pair(0, 1), NO_IMM),
bytes("pmovzxbq", &VV, Word, &[0x0F, 0x38, 0x32], pair(0, 1), NO_IMM),
bytes("pmovzxbq", &MV, Word, &[0x0F, 0x38, 0x32], pair(0, 1), NO_IMM),
bytes("pmovzxwd", &VV, Word, &[0x0F, 0x38, 0x33], pair(0, 1), NO_IMM),
bytes("pmovzxwd", &MV, Word, &[0x0F, 0x38, 0x33], pair(0, 1), NO_IMM),
bytes("pmovzxwq", &VV, Word, &[0x0F, 0x38, 0x34], pair(0, 1), NO_IMM),
bytes("pmovzxwq", &MV, Word, &[0x0F, 0x38, 0x34], pair(0, 1), NO_IMM),
bytes("pmovzxdq", &VV, Word, &[0x0F, 0x38, 0x35], pair(0, 1), NO_IMM),
bytes("pmovzxdq", &MV, Word, &[0x0F, 0x38, 0x35], pair(0, 1), NO_IMM),
bytes("pcmpgtq", &VV, Word, &[0x0F, 0x38, 0x37], pair(0, 1), NO_IMM),
bytes("pcmpgtq", &MV, Word, &[0x0F, 0x38, 0x37], pair(0, 1), NO_IMM),
bytes("pminsb", &VV, Word, &[0x0F, 0x38, 0x38], pair(0, 1), NO_IMM),
bytes("pminsb", &MV, Word, &[0x0F, 0x38, 0x38], pair(0, 1), NO_IMM),
bytes("pminsd", &VV, Word, &[0x0F, 0x38, 0x39], pair(0, 1), NO_IMM),
bytes("pminsd", &MV, Word, &[0x0F, 0x38, 0x39], pair(0, 1), NO_IMM),
bytes("pminuw", &VV, Word, &[0x0F, 0x38, 0x3A], pair(0, 1), NO_IMM),
bytes("pminuw", &MV, Word, &[0x0F, 0x38, 0x3A], pair(0, 1), NO_IMM),
bytes("pminud", &VV, Word, &[0x0F, 0x38, 0x3B], pair(0, 1), NO_IMM),
bytes("pminud", &MV, Word, &[0x0F, 0x38, 0x3B], pair(0, 1), NO_IMM),
bytes("pmaxsb", &VV, Word, &[0x0F, 0x38, 0x3C], pair(0, 1), NO_IMM),
bytes("pmaxsb", &MV, Word, &[0x0F, 0x38, 0x3C], pair(0, 1), NO_IMM),
bytes("pmaxsd", &VV, Word, &[0x0F, 0x38, 0x3D], pair(0, 1), NO_IMM),
bytes("pmaxsd", &MV, Word, &[0x0F, 0x38, 0x3D], pair(0, 1), NO_IMM),
bytes("pmaxuw", &VV, Word, &[0x0F, 0x38, 0x3E], pair(0, 1), NO_IMM),
bytes("pmaxuw", &MV, Word, &[0x0F, 0x38, 0x3E], pair(0, 1), NO_IMM),
bytes("pmaxud", &VV, Word, &[0x0F, 0x38, 0x3F], pair(0, 1), NO_IMM),
bytes("pmaxud", &MV, Word, &[0x0F, 0x38, 0x3F], pair(0, 1), NO_IMM),
bytes("pmulld", &VV, Word, &[0x0F, 0x38, 0x40], pair(0, 1), NO_IMM),
bytes("pmulld", &MV, Word, &[0x0F, 0x38, 0x40], pair(0, 1), NO_IMM),
bytes("phminposuw", &VV, Word, &[0x0F, 0x38, 0x41], pair(0, 1), NO_IMM),
bytes("phminposuw", &MV, Word, &[0x0F, 0x38, 0x41], pair(0, 1), NO_IMM),
bytes("movntdqa", &MV, Word, &[0x0F, 0x38, 0x2A], pair(0, 1), NO_IMM),
bytes("movntdq", &VM, Word, &[0x0F, 0xE7], pair(1, 0), NO_IMM),
bytes("movntil", &RM, Long, &[0x0F, 0xC3], pair(1, 0), NO_IMM),
bytes("movntiq", &RM, Quad, &[0x0F, 0xC3], pair(1, 0), NO_IMM),
bytes("roundps", &IVV, Word, &[0x0F, 0x3A, 0x08], pair(1, 2), ImmSize::Ib),
bytes("roundps", &IMV, Word, &[0x0F, 0x3A, 0x08], pair(1, 2), ImmSize::Ib),
bytes("roundpd", &IVV, Word, &[0x0F, 0x3A, 0x09], pair(1, 2), ImmSize::Ib),
bytes("roundpd", &IMV, Word, &[0x0F, 0x3A, 0x09], pair(1, 2), ImmSize::Ib),
bytes("roundss", &IVV, Word, &[0x0F, 0x3A, 0x0A], pair(1, 2), ImmSize::Ib),
bytes("roundss", &IMV, Word, &[0x0F, 0x3A, 0x0A], pair(1, 2), ImmSize::Ib),
bytes("roundsd", &IVV, Word, &[0x0F, 0x3A, 0x0B], pair(1, 2), ImmSize::Ib),
bytes("roundsd", &IMV, Word, &[0x0F, 0x3A, 0x0B], pair(1, 2), ImmSize::Ib),
bytes("blendps", &IVV, Word, &[0x0F, 0x3A, 0x0C], pair(1, 2), ImmSize::Ib),
bytes("blendps", &IMV, Word, &[0x0F, 0x3A, 0x0C], pair(1, 2), ImmSize::Ib),
bytes("blendpd", &IVV, Word, &[0x0F, 0x3A, 0x0D], pair(1, 2), ImmSize::Ib),
bytes("blendpd", &IMV, Word, &[0x0F, 0x3A, 0x0D], pair(1, 2), ImmSize::Ib),
bytes("pblendw", &IVV, Word, &[0x0F, 0x3A, 0x0E], pair(1, 2), ImmSize::Ib),
bytes("pblendw", &IMV, Word, &[0x0F, 0x3A, 0x0E], pair(1, 2), ImmSize::Ib),
bytes("insertps", &IVV, Word, &[0x0F, 0x3A, 0x21], pair(1, 2), ImmSize::Ib),
bytes("insertps", &IMV, Word, &[0x0F, 0x3A, 0x21], pair(1, 2), ImmSize::Ib),
bytes("dpps", &IVV, Word, &[0x0F, 0x3A, 0x40], pair(1, 2), ImmSize::Ib),
bytes("dpps", &IMV, Word, &[0x0F, 0x3A, 0x40], pair(1, 2), ImmSize::Ib),
bytes("dppd", &IVV, Word, &[0x0F, 0x3A, 0x41], pair(1, 2), ImmSize::Ib),
bytes("dppd", &IMV, Word, &[0x0F, 0x3A, 0x41], pair(1, 2), ImmSize::Ib),
bytes("mpsadbw", &IVV, Word, &[0x0F, 0x3A, 0x42], pair(1, 2), ImmSize::Ib),
bytes("mpsadbw", &IMV, Word, &[0x0F, 0x3A, 0x42], pair(1, 2), ImmSize::Ib),
bytes("pcmpestrm", &IVV, Word, &[0x0F, 0x3A, 0x60], pair(1, 2), ImmSize::Ib),
bytes("pcmpestrm", &IMV, Word, &[0x0F, 0x3A, 0x60], pair(1, 2), ImmSize::Ib),
bytes("pcmpestri", &IVV, Word, &[0x0F, 0x3A, 0x61], pair(1, 2), ImmSize::Ib),
bytes("pcmpestri", &IMV, Word, &[0x0F, 0x3A, 0x61], pair(1, 2), ImmSize::Ib),
bytes("pcmpistrm", &IVV, Word, &[0x0F, 0x3A, 0x62], pair(1, 2), ImmSize::Ib),
bytes("pcmpistrm", &IMV, Word, &[0x0F, 0x3A, 0x62], pair(1, 2), ImmSize::Ib),
bytes("pcmpistri", &IVV, Word, &[0x0F, 0x3A, 0x63], pair(1, 2), ImmSize::Ib),
bytes("pcmpistri", &IMV, Word, &[0x0F, 0x3A, 0x63], pair(1, 2), ImmSize::Ib),
bytes("extractps", &IVR, Word, &[0x0F, 0x3A, 0x17], pair(2, 1), ImmSize::Ib),
bytes("extractps", &IVM, Word, &[0x0F, 0x3A, 0x17], pair(2, 1), ImmSize::Ib),
bytes("sha1rnds4", &IVV, Long, &[0x0F, 0x3A, 0xCC], pair(1, 2), ImmSize::Ib),
bytes("sha1rnds4", &IMV, Long, &[0x0F, 0x3A, 0xCC], pair(1, 2), ImmSize::Ib),
bytes("sha1nexte", &VV, Long, &[0x0F, 0x38, 0xC8], pair(0, 1), NO_IMM),
bytes("sha1nexte", &MV, Long, &[0x0F, 0x38, 0xC8], pair(0, 1), NO_IMM),
bytes("sha1msg1", &VV, Long, &[0x0F, 0x38, 0xC9], pair(0, 1), NO_IMM),
bytes("sha1msg1", &MV, Long, &[0x0F, 0x38, 0xC9], pair(0, 1), NO_IMM),
bytes("sha1msg2", &VV, Long, &[0x0F, 0x38, 0xCA], pair(0, 1), NO_IMM),
bytes("sha1msg2", &MV, Long, &[0x0F, 0x38, 0xCA], pair(0, 1), NO_IMM),
bytes("sha256rnds2", &VV, Long, &[0x0F, 0x38, 0xCB], pair(0, 1), NO_IMM),
bytes("sha256rnds2", &MV, Long, &[0x0F, 0x38, 0xCB], pair(0, 1), NO_IMM),
bytes("sha256msg1", &VV, Long, &[0x0F, 0x38, 0xCC], pair(0, 1), NO_IMM),
bytes("sha256msg1", &MV, Long, &[0x0F, 0x38, 0xCC], pair(0, 1), NO_IMM),
bytes("sha256msg2", &VV, Long, &[0x0F, 0x38, 0xCD], pair(0, 1), NO_IMM),
bytes("sha256msg2", &MV, Long, &[0x0F, 0x38, 0xCD], pair(0, 1), NO_IMM),
bytes("cmpss", &IVV, Single, &[0x0F, 0xC2], pair(1, 2), ImmSize::Ib),
bytes("cmpss", &IMV, Single, &[0x0F, 0xC2], pair(1, 2), ImmSize::Ib),
bytes("cmpsd", &IVV, Double, &[0x0F, 0xC2], pair(1, 2), ImmSize::Ib),
bytes("cmpsd", &IMV, Double, &[0x0F, 0xC2], pair(1, 2), ImmSize::Ib),
bytes("cmpps", &IVV, Long, &[0x0F, 0xC2], pair(1, 2), ImmSize::Ib),
bytes("cmpps", &IMV, Long, &[0x0F, 0xC2], pair(1, 2), ImmSize::Ib),
bytes("cmppd", &IVV, Word, &[0x0F, 0xC2], pair(1, 2), ImmSize::Ib),
bytes("cmppd", &IMV, Word, &[0x0F, 0xC2], pair(1, 2), ImmSize::Ib),
bytes("punpcklbw", &VV, Word, &[0x0F, 0x60], pair(0, 1), NO_IMM),
bytes("punpcklbw", &MV, Word, &[0x0F, 0x60], pair(0, 1), NO_IMM),
bytes("punpcklwd", &VV, Word, &[0x0F, 0x61], pair(0, 1), NO_IMM),
bytes("punpcklwd", &MV, Word, &[0x0F, 0x61], pair(0, 1), NO_IMM),
bytes("punpckldq", &VV, Word, &[0x0F, 0x62], pair(0, 1), NO_IMM),
bytes("punpckldq", &MV, Word, &[0x0F, 0x62], pair(0, 1), NO_IMM),
bytes("punpckhbw", &VV, Word, &[0x0F, 0x68], pair(0, 1), NO_IMM),
bytes("punpckhbw", &MV, Word, &[0x0F, 0x68], pair(0, 1), NO_IMM),
bytes("punpckhwd", &VV, Word, &[0x0F, 0x69], pair(0, 1), NO_IMM),
bytes("punpckhwd", &MV, Word, &[0x0F, 0x69], pair(0, 1), NO_IMM),
bytes("punpckhdq", &VV, Word, &[0x0F, 0x6A], pair(0, 1), NO_IMM),
bytes("punpckhdq", &MV, Word, &[0x0F, 0x6A], pair(0, 1), NO_IMM),
bytes("pcmpgtb", &VV, Word, &[0x0F, 0x64], pair(0, 1), NO_IMM),
bytes("pcmpgtb", &MV, Word, &[0x0F, 0x64], pair(0, 1), NO_IMM),
bytes("pcmpgtw", &VV, Word, &[0x0F, 0x65], pair(0, 1), NO_IMM),
bytes("pcmpgtw", &MV, Word, &[0x0F, 0x65], pair(0, 1), NO_IMM),
bytes("pcmpgtd", &VV, Word, &[0x0F, 0x66], pair(0, 1), NO_IMM),
bytes("pcmpgtd", &MV, Word, &[0x0F, 0x66], pair(0, 1), NO_IMM),
bytes("pmuludq", &VV, Word, &[0x0F, 0xF4], pair(0, 1), NO_IMM),
bytes("pmuludq", &MV, Word, &[0x0F, 0xF4], pair(0, 1), NO_IMM),
bytes("paddb", &MV, Word, &[0x0F, 0xFC], pair(0, 1), NO_IMM),
bytes("paddw", &MV, Word, &[0x0F, 0xFD], pair(0, 1), NO_IMM),
bytes("paddd", &MV, Word, &[0x0F, 0xFE], pair(0, 1), NO_IMM),
bytes("paddq", &MV, Word, &[0x0F, 0xD4], pair(0, 1), NO_IMM),
bytes("psubb", &MV, Word, &[0x0F, 0xF8], pair(0, 1), NO_IMM),
bytes("psubw", &MV, Word, &[0x0F, 0xF9], pair(0, 1), NO_IMM),
bytes("psubd", &MV, Word, &[0x0F, 0xFA], pair(0, 1), NO_IMM),
bytes("psubq", &MV, Word, &[0x0F, 0xFB], pair(0, 1), NO_IMM),
bytes("fldt", &M, Long, &[0xDB], ext(0, 5), NO_IMM),
bytes("fstpt", &M, Long, &[0xDB], ext(0, 7), NO_IMM),
bytes("flds", &M, Long, &[0xD9], ext(0, 0), NO_IMM),
bytes("fldl", &M, Long, &[0xDD], ext(0, 0), NO_IMM),
bytes("fildl", &M, Long, &[0xDB], ext(0, 0), NO_IMM),
bytes("fildll", &M, Long, &[0xDF], ext(0, 5), NO_IMM),
bytes("fstps", &M, Long, &[0xD9], ext(0, 3), NO_IMM),
bytes("fstpl", &M, Long, &[0xDD], ext(0, 3), NO_IMM),
bytes("fistpl", &M, Long, &[0xDB], ext(0, 3), NO_IMM),
bytes("fistpll", &M, Long, &[0xDF], ext(0, 7), NO_IMM),
bytes("fadds", &M, Long, &[0xD8], ext(0, 0), NO_IMM),
bytes("faddl", &M, Long, &[0xDC], ext(0, 0), NO_IMM),
bytes("fmuls", &M, Long, &[0xD8], ext(0, 1), NO_IMM),
bytes("fmull", &M, Long, &[0xDC], ext(0, 1), NO_IMM),
bytes("fcoms", &M, Long, &[0xD8], ext(0, 2), NO_IMM),
bytes("fcoml", &M, Long, &[0xDC], ext(0, 2), NO_IMM),
bytes("fcomps", &M, Long, &[0xD8], ext(0, 3), NO_IMM),
bytes("fcompl", &M, Long, &[0xDC], ext(0, 3), NO_IMM),
bytes("fsubs", &M, Long, &[0xD8], ext(0, 4), NO_IMM),
bytes("fsubl", &M, Long, &[0xDC], ext(0, 4), NO_IMM),
bytes("fsubrs", &M, Long, &[0xD8], ext(0, 5), NO_IMM),
bytes("fsubrl", &M, Long, &[0xDC], ext(0, 5), NO_IMM),
bytes("fdivs", &M, Long, &[0xD8], ext(0, 6), NO_IMM),
bytes("fdivl", &M, Long, &[0xDC], ext(0, 6), NO_IMM),
bytes("fdivrs", &M, Long, &[0xD8], ext(0, 7), NO_IMM),
bytes("fdivrl", &M, Long, &[0xDC], ext(0, 7), NO_IMM),
bytes("fnstcw", &M, Long, &[0xD9], ext(0, 7), NO_IMM),
bytes("fldcw", &M, Long, &[0xD9], ext(0, 5), NO_IMM),
waits("fstcw", &M, Long, &[0xD9], ext(0, 7)),
bytes("fnstenv", &M, Long, &[0xD9], ext(0, 6), NO_IMM),
waits("fstenv", &M, Long, &[0xD9], ext(0, 6)),
bytes("fninit", &NO_ARGS, Long, &[0xDB, 0xE3], NO_MODRM, NO_IMM),
waits("finit", &NO_ARGS, Long, &[0xDB, 0xE3], NO_MODRM),
bytes("faddp", &SS, Long, &[0xDE, 0xC1], NO_MODRM, NO_IMM),
bytes("fsubp", &SS, Long, &[0xDE, 0xE1], NO_MODRM, NO_IMM),
bytes("fsubrp", &SS, Long, &[0xDE, 0xE9], NO_MODRM, NO_IMM),
bytes("fmulp", &SS, Long, &[0xDE, 0xC9], NO_MODRM, NO_IMM),
bytes("fdivp", &SS, Long, &[0xDE, 0xF1], NO_MODRM, NO_IMM),
bytes("fdivrp", &SS, Long, &[0xDE, 0xF9], NO_MODRM, NO_IMM),
bytes("fchs", &NO_ARGS, Long, &[0xD9, 0xE0], NO_MODRM, NO_IMM),
bytes("fabs", &NO_ARGS, Long, &[0xD9, 0xE1], NO_MODRM, NO_IMM),
bytes("fucomip", &SS, Long, &[0xDF, 0xE9], NO_MODRM, NO_IMM),
bytes("fstp", &S, Long, &[0xDD, 0xD8], NO_MODRM, NO_IMM),
bytes("fprem", &NO_ARGS, Long, &[0xD9, 0xF8], NO_MODRM, NO_IMM),
bytes("f2xm1", &NO_ARGS, Long, &[0xD9, 0xF0], NO_MODRM, NO_IMM),
bytes("fyl2x", &NO_ARGS, Long, &[0xD9, 0xF1], NO_MODRM, NO_IMM),
bytes("fptan", &NO_ARGS, Long, &[0xD9, 0xF2], NO_MODRM, NO_IMM),
bytes("fpatan", &NO_ARGS, Long, &[0xD9, 0xF3], NO_MODRM, NO_IMM),
bytes("fxtract", &NO_ARGS, Long, &[0xD9, 0xF4], NO_MODRM, NO_IMM),
bytes("fprem1", &NO_ARGS, Long, &[0xD9, 0xF5], NO_MODRM, NO_IMM),
bytes("fyl2xp1", &NO_ARGS, Long, &[0xD9, 0xF9], NO_MODRM, NO_IMM),
bytes("fsqrt", &NO_ARGS, Long, &[0xD9, 0xFA], NO_MODRM, NO_IMM),
bytes("fsincos", &NO_ARGS, Long, &[0xD9, 0xFB], NO_MODRM, NO_IMM),
bytes("frndint", &NO_ARGS, Long, &[0xD9, 0xFC], NO_MODRM, NO_IMM),
bytes("fscale", &NO_ARGS, Long, &[0xD9, 0xFD], NO_MODRM, NO_IMM),
bytes("fsin", &NO_ARGS, Long, &[0xD9, 0xFE], NO_MODRM, NO_IMM),
bytes("fcos", &NO_ARGS, Long, &[0xD9, 0xFF], NO_MODRM, NO_IMM),
bytes("ftst", &NO_ARGS, Long, &[0xD9, 0xE4], NO_MODRM, NO_IMM),
bytes("fxam", &NO_ARGS, Long, &[0xD9, 0xE5], NO_MODRM, NO_IMM),
bytes("fld1", &NO_ARGS, Long, &[0xD9, 0xE8], NO_MODRM, NO_IMM),
bytes("fldl2t", &NO_ARGS, Long, &[0xD9, 0xE9], NO_MODRM, NO_IMM),
bytes("fldl2e", &NO_ARGS, Long, &[0xD9, 0xEA], NO_MODRM, NO_IMM),
bytes("fldpi", &NO_ARGS, Long, &[0xD9, 0xEB], NO_MODRM, NO_IMM),
bytes("fldlg2", &NO_ARGS, Long, &[0xD9, 0xEC], NO_MODRM, NO_IMM),
bytes("fldln2", &NO_ARGS, Long, &[0xD9, 0xED], NO_MODRM, NO_IMM),
bytes("fldz", &NO_ARGS, Long, &[0xD9, 0xEE], NO_MODRM, NO_IMM),
bytes("fnstsw", &R, Long, &[0xDF, 0xE0], NO_MODRM, NO_IMM),
bytes("fnstsw", &M, Long, &[0xDD], ext(0, 7), NO_IMM),
evex("vmovdqu64", &VV, Single, &[0x6F], pair(0, 1), Evex::new(Map::Escape, true)),
evex("vmovdqu64", &MV, Single, &[0x6F], pair(0, 1), Evex::new(Map::Escape, true)),
evex("vmovdqu64", &VM, Single, &[0x7F], pair(1, 0), Evex::new(Map::Escape, true)),
evex("vmovdqa64", &VV, Word, &[0x6F], pair(0, 1), Evex::new(Map::Escape, true)),
evex("vmovdqa64", &MV, Word, &[0x6F], pair(0, 1), Evex::new(Map::Escape, true)),
evex("vmovdqa64", &VM, Word, &[0x7F], pair(1, 0), Evex::new(Map::Escape, true)),
evex("vmovntdq", &VM, Word, &[0xE7], pair(1, 0), Evex::new(Map::Escape, false).or_vex(false)),
evex("vmovdqu8", &VV, Double, &[0x6F], pair(0, 1), Evex::new(Map::Escape, false)),
evex("vmovdqu8", &MV, Double, &[0x6F], pair(0, 1), Evex::new(Map::Escape, false)),
evex("vmovdqu8", &VM, Double, &[0x7F], pair(1, 0), Evex::new(Map::Escape, false)),
evex(
"vpaddq",
&VVV,
Word,
&[0xD4],
pair(0, 2),
Evex::new(Map::Escape, true).third(1).or_vex(false),
),
evex(
"vpaddq",
&MVV,
Word,
&[0xD4],
pair(0, 2),
Evex::new(Map::Escape, true).third(1).or_vex(false),
),
evex("vpandq", &VVV, Word, &[0xDB], pair(0, 2), Evex::new(Map::Escape, true).third(1)),
evex("vpandq", &MVV, Word, &[0xDB], pair(0, 2), Evex::new(Map::Escape, true).third(1)),
evex("vpxorq", &VVV, Word, &[0xEF], pair(0, 2), Evex::new(Map::Escape, true).third(1)),
evex("vpxorq", &MVV, Word, &[0xEF], pair(0, 2), Evex::new(Map::Escape, true).third(1)),
evex("vpternlogq", &IVVV, Word, &[0x25], pair(1, 3), Evex::new(Map::Escape3A, true).third(2)),
evex("vpternlogq", &IMVV, Word, &[0x25], pair(1, 3), Evex::new(Map::Escape3A, true).third(2)),
evex("vpopcntq", &VV, Word, &[0x55], pair(0, 1), Evex::new(Map::Escape38, true)),
evex("vpopcntq", &MV, Word, &[0x55], pair(0, 1), Evex::new(Map::Escape38, true)),
evex(
"vpclmulqdq",
&IVVV,
Word,
&[0x44],
pair(1, 3),
Evex::new(Map::Escape3A, false).third(2).or_vex(false),
),
evex(
"vpclmulqdq",
&IMVV,
Word,
&[0x44],
pair(1, 3),
Evex::new(Map::Escape3A, false).third(2).or_vex(false),
),
evex(
"vextracti32x4",
&IVV,
Word,
&[0x39],
pair(2, 1),
Evex::new(Map::Escape3A, false).fixed(16),
),
evex(
"vextracti32x4",
&IVM,
Word,
&[0x39],
pair(2, 1),
Evex::new(Map::Escape3A, false).fixed(16),
),
evex(
"vextracti64x4",
&IVV,
Word,
&[0x3B],
pair(2, 1),
Evex::new(Map::Escape3A, true).fixed(32),
),
evex(
"vextracti64x4",
&IVM,
Word,
&[0x3B],
pair(2, 1),
Evex::new(Map::Escape3A, true).fixed(32),
),
evex(
"vbroadcasti32x4",
&MV,
Word,
&[0x5A],
pair(0, 1),
Evex::new(Map::Escape38, false).fixed(16),
),
evex("vpbroadcastb", &RV, Word, &[0x7A], pair(0, 1), Evex::new(Map::Escape38, false)),
evex("vshufi64x2", &IVVV, Word, &[0x43], pair(1, 3), Evex::new(Map::Escape3A, true).third(2)),
evex("vshufi64x2", &IMVV, Word, &[0x43], pair(1, 3), Evex::new(Map::Escape3A, true).third(2)),
evex("vpshufd", &IVV, Word, &[0x70], pair(1, 2), Evex::new(Map::Escape, false).or_vex(false)),
evex("vpshufd", &IMV, Word, &[0x70], pair(1, 2), Evex::new(Map::Escape, false).or_vex(false)),
evex(
"vmovq",
&VR,
Word,
&[0x7E],
pair(1, 0),
Evex::new(Map::Escape, true).fixed(8).or_vex(true),
),
evex(
"vmovq",
&RV,
Word,
&[0x6E],
pair(0, 1),
Evex::new(Map::Escape, true).fixed(8).or_vex(true),
),
evex("vpxord", &VVV, Word, &[0xEF], pair(0, 2), Evex::new(Map::Escape, false).third(1)),
evex("vpxord", &MVV, Word, &[0xEF], pair(0, 2), Evex::new(Map::Escape, false).third(1)),
evex("vpternlogd", &IVVV, Word, &[0x25], pair(1, 3), Evex::new(Map::Escape3A, false).third(2)),
evex("vpternlogd", &IMVV, Word, &[0x25], pair(1, 3), Evex::new(Map::Escape3A, false).third(2)),
evex("vprold", &IVV, Word, &[0x72], ext(1, 1), Evex::new(Map::Escape, false).third(2)),
evex("vprold", &IMV, Word, &[0x72], ext(1, 1), Evex::new(Map::Escape, false).third(2)),
evex("vprord", &IVV, Word, &[0x72], ext(1, 0), Evex::new(Map::Escape, false).third(2)),
evex("vprord", &IMV, Word, &[0x72], ext(1, 0), Evex::new(Map::Escape, false).third(2)),
evex("vpermi2d", &VVV, Word, &[0x76], pair(0, 2), Evex::new(Map::Escape38, false).third(1)),
evex("vpermi2d", &MVV, Word, &[0x76], pair(0, 2), Evex::new(Map::Escape38, false).third(1)),
evex(
"vinserti32x4",
&IVVV,
Word,
&[0x38],
pair(1, 3),
Evex::new(Map::Escape3A, false).third(2).fixed(16),
),
evex(
"vinserti32x4",
&IMVV,
Word,
&[0x38],
pair(1, 3),
Evex::new(Map::Escape3A, false).third(2).fixed(16),
),
evex(
"vinserti64x4",
&IVVV,
Word,
&[0x3A],
pair(1, 3),
Evex::new(Map::Escape3A, true).third(2).fixed(32),
),
evex(
"vinserti64x4",
&IMVV,
Word,
&[0x3A],
pair(1, 3),
Evex::new(Map::Escape3A, true).third(2).fixed(32),
),
evex(
"vbroadcasti64x2",
&MV,
Word,
&[0x5A],
pair(0, 1),
Evex::new(Map::Escape38, true).fixed(16),
),
evex("vpcmpuq", &IVVK, Word, &[0x1E], pair(1, 3), Evex::new(Map::Escape3A, true).third(2)),
evex("vpcmpuq", &IMVK, Word, &[0x1E], pair(1, 3), Evex::new(Map::Escape3A, true).third(2)),
evex("vpcmpgtb", &VVK, Word, &[0x64], pair(0, 2), Evex::new(Map::Escape, false).third(1)),
evex("vpcmpgtb", &MVK, Word, &[0x64], pair(0, 2), Evex::new(Map::Escape, false).third(1)),
evex("vpmovm2b", &KV, Single, &[0x28], pair(0, 1), Evex::new(Map::Escape38, false)),
evex(
"vgf2p8affineqb",
&IVVV,
Word,
&[0xCE],
pair(1, 3),
Evex::new(Map::Escape3A, true).third(2).or_vex(true),
),
evex(
"vgf2p8affineqb",
&IMVV,
Word,
&[0xCE],
pair(1, 3),
Evex::new(Map::Escape3A, true).third(2).or_vex(true),
),
evex(
"vgf2p8affineinvqb",
&IVVV,
Word,
&[0xCF],
pair(1, 3),
Evex::new(Map::Escape3A, true).third(2).or_vex(true),
),
evex(
"vgf2p8affineinvqb",
&IMVV,
Word,
&[0xCF],
pair(1, 3),
Evex::new(Map::Escape3A, true).third(2).or_vex(true),
),
vexed("kmovq", &RK, DoubleQuad, &[0x92], pair(0, 1)),
vexed("kmovq", &KR, DoubleQuad, &[0x93], pair(0, 1)),
vexed("kmovd", &RK, Double, &[0x92], pair(0, 1)),
vexed("kmovd", &KR, Double, &[0x93], pair(0, 1)),
Encoding {
vex: Some(Vex { map: Map::Escape, vvvv: Some(1), long: true }),
..vexed("kaddb", &KKK, Word, &[0x4A], pair(0, 2))
},
Encoding {
vex: Some(Vex { map: Map::Escape, vvvv: Some(1), long: true }),
..vexed("kxorw", &KKK, Long, &[0x47], pair(0, 2))
},
avx("vandps", &VVV, Long, Map::Escape, &[0x54], Some(1), pair(0, 2)),
avx("vandps", &MVV, Long, Map::Escape, &[0x54], Some(1), pair(0, 2)),
avx("vandpd", &VVV, Word, Map::Escape, &[0x54], Some(1), pair(0, 2)),
avx("vandpd", &MVV, Word, Map::Escape, &[0x54], Some(1), pair(0, 2)),
avx("vandnps", &VVV, Long, Map::Escape, &[0x55], Some(1), pair(0, 2)),
avx("vandnps", &MVV, Long, Map::Escape, &[0x55], Some(1), pair(0, 2)),
avx("vandnpd", &VVV, Word, Map::Escape, &[0x55], Some(1), pair(0, 2)),
avx("vandnpd", &MVV, Word, Map::Escape, &[0x55], Some(1), pair(0, 2)),
avx("vorps", &VVV, Long, Map::Escape, &[0x56], Some(1), pair(0, 2)),
avx("vorps", &MVV, Long, Map::Escape, &[0x56], Some(1), pair(0, 2)),
avx("vorpd", &VVV, Word, Map::Escape, &[0x56], Some(1), pair(0, 2)),
avx("vorpd", &MVV, Word, Map::Escape, &[0x56], Some(1), pair(0, 2)),
evex(
"vxorps",
&VVV,
Long,
&[0x57],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).or_vex(false),
),
avx("vxorps", &MVV, Long, Map::Escape, &[0x57], Some(1), pair(0, 2)),
avx("vxorpd", &VVV, Word, Map::Escape, &[0x57], Some(1), pair(0, 2)),
avx("vxorpd", &MVV, Word, Map::Escape, &[0x57], Some(1), pair(0, 2)),
avx("vpxor", &VVV, Word, Map::Escape, &[0xEF], Some(1), pair(0, 2)),
avx("vpxor", &MVV, Word, Map::Escape, &[0xEF], Some(1), pair(0, 2)),
avx("vpor", &VVV, Word, Map::Escape, &[0xEB], Some(1), pair(0, 2)),
avx("vpor", &MVV, Word, Map::Escape, &[0xEB], Some(1), pair(0, 2)),
avx("vpand", &VVV, Word, Map::Escape, &[0xDB], Some(1), pair(0, 2)),
avx("vpand", &MVV, Word, Map::Escape, &[0xDB], Some(1), pair(0, 2)),
avx("vpandn", &VVV, Word, Map::Escape, &[0xDF], Some(1), pair(0, 2)),
avx("vpandn", &MVV, Word, Map::Escape, &[0xDF], Some(1), pair(0, 2)),
evex(
"vpaddb",
&VVV,
Word,
&[0xFC],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).or_vex(false),
),
evex(
"vpaddb",
&MVV,
Word,
&[0xFC],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).or_vex(false),
),
evex(
"vpaddd",
&VVV,
Word,
&[0xFE],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).or_vex(false),
),
evex(
"vpaddd",
&MVV,
Word,
&[0xFE],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).or_vex(false),
),
evex(
"vpsubd",
&VVV,
Word,
&[0xFA],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).or_vex(false),
),
evex(
"vpsubd",
&MVV,
Word,
&[0xFA],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).or_vex(false),
),
evex(
"vpsubq",
&VVV,
Word,
&[0xFB],
pair(0, 2),
Evex::new(Map::Escape, true).third(1).or_vex(false),
),
evex(
"vpsubq",
&MVV,
Word,
&[0xFB],
pair(0, 2),
Evex::new(Map::Escape, true).third(1).or_vex(false),
),
evex(
"vpmuludq",
&VVV,
Word,
&[0xF4],
pair(0, 2),
Evex::new(Map::Escape, true).third(1).or_vex(false),
),
evex(
"vpmuludq",
&MVV,
Word,
&[0xF4],
pair(0, 2),
Evex::new(Map::Escape, true).third(1).or_vex(false),
),
avx("vpcmpeqd", &VVV, Word, Map::Escape, &[0x76], Some(1), pair(0, 2)),
avx("vpcmpeqd", &MVV, Word, Map::Escape, &[0x76], Some(1), pair(0, 2)),
avx("vpcmpgtb", &VVV, Word, Map::Escape, &[0x64], Some(1), pair(0, 2)),
avx("vpcmpgtb", &MVV, Word, Map::Escape, &[0x64], Some(1), pair(0, 2)),
evex(
"vpunpckhdq",
&VVV,
Word,
&[0x6A],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).or_vex(false),
),
evex(
"vpunpckhdq",
&MVV,
Word,
&[0x6A],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).or_vex(false),
),
evex(
"vpunpckldq",
&VVV,
Word,
&[0x62],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).or_vex(false),
),
evex(
"vpunpckldq",
&MVV,
Word,
&[0x62],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).or_vex(false),
),
evex(
"vpunpckhqdq",
&VVV,
Word,
&[0x6D],
pair(0, 2),
Evex::new(Map::Escape, true).third(1).or_vex(false),
),
evex(
"vpunpckhqdq",
&MVV,
Word,
&[0x6D],
pair(0, 2),
Evex::new(Map::Escape, true).third(1).or_vex(false),
),
evex(
"vpunpcklqdq",
&VVV,
Word,
&[0x6C],
pair(0, 2),
Evex::new(Map::Escape, true).third(1).or_vex(false),
),
evex(
"vpunpcklqdq",
&MVV,
Word,
&[0x6C],
pair(0, 2),
Evex::new(Map::Escape, true).third(1).or_vex(false),
),
evex(
"vpslld",
&VVV,
Word,
&[0xF2],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).fixed(16).or_vex(false),
),
evex(
"vpslld",
&MVV,
Word,
&[0xF2],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).fixed(16).or_vex(false),
),
evex(
"vpsrld",
&VVV,
Word,
&[0xD2],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).fixed(16).or_vex(false),
),
evex(
"vpsrld",
&MVV,
Word,
&[0xD2],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).fixed(16).or_vex(false),
),
evex(
"vpsrad",
&VVV,
Word,
&[0xE2],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).fixed(16).or_vex(false),
),
evex(
"vpsrad",
&MVV,
Word,
&[0xE2],
pair(0, 2),
Evex::new(Map::Escape, false).third(1).fixed(16).or_vex(false),
),
evex(
"vpsllq",
&VVV,
Word,
&[0xF3],
pair(0, 2),
Evex::new(Map::Escape, true).third(1).fixed(16).or_vex(false),
),
evex(
"vpsllq",
&MVV,
Word,
&[0xF3],
pair(0, 2),
Evex::new(Map::Escape, true).third(1).fixed(16).or_vex(false),
),
evex(
"vpsrlq",
&VVV,
Word,
&[0xD3],
pair(0, 2),
Evex::new(Map::Escape, true).third(1).fixed(16).or_vex(false),
),
evex(
"vpsrlq",
&MVV,
Word,
&[0xD3],
pair(0, 2),
Evex::new(Map::Escape, true).third(1).fixed(16).or_vex(false),
),
evex(
"vpshufb",
&VVV,
Word,
&[0x00],
pair(0, 2),
Evex::new(Map::Escape38, false).third(1).or_vex(false),
),
evex(
"vpshufb",
&MVV,
Word,
&[0x00],
pair(0, 2),
Evex::new(Map::Escape38, false).third(1).or_vex(false),
),
avx("vpcmpeqq", &VVV, Word, Map::Escape38, &[0x29], Some(1), pair(0, 2)),
avx("vpcmpeqq", &MVV, Word, Map::Escape38, &[0x29], Some(1), pair(0, 2)),
evex(
"vaesenc",
&VVV,
Word,
&[0xDC],
pair(0, 2),
Evex::new(Map::Escape38, false).third(1).or_vex(false),
),
evex(
"vaesenc",
&MVV,
Word,
&[0xDC],
pair(0, 2),
Evex::new(Map::Escape38, false).third(1).or_vex(false),
),
evex(
"vaesenclast",
&VVV,
Word,
&[0xDD],
pair(0, 2),
Evex::new(Map::Escape38, false).third(1).or_vex(false),
),
evex(
"vaesenclast",
&MVV,
Word,
&[0xDD],
pair(0, 2),
Evex::new(Map::Escape38, false).third(1).or_vex(false),
),
evex(
"vaesdec",
&VVV,
Word,
&[0xDE],
pair(0, 2),
Evex::new(Map::Escape38, false).third(1).or_vex(false),
),
evex(
"vaesdec",
&MVV,
Word,
&[0xDE],
pair(0, 2),
Evex::new(Map::Escape38, false).third(1).or_vex(false),
),
evex(
"vaesdeclast",
&VVV,
Word,
&[0xDF],
pair(0, 2),
Evex::new(Map::Escape38, false).third(1).or_vex(false),
),
evex(
"vaesdeclast",
&MVV,
Word,
&[0xDF],
pair(0, 2),
Evex::new(Map::Escape38, false).third(1).or_vex(false),
),
evex("vpabsb", &VV, Word, &[0x1C], pair(0, 1), Evex::new(Map::Escape38, false).or_vex(false)),
evex("vpabsb", &MV, Word, &[0x1C], pair(0, 1), Evex::new(Map::Escape38, false).or_vex(false)),
avx("vptest", &VV, Word, Map::Escape38, &[0x17], None, pair(0, 1)),
avx("vptest", &MV, Word, Map::Escape38, &[0x17], None, pair(0, 1)),
avx("vpmovsxbw", &VV, Word, Map::Escape38, &[0x20], None, pair(0, 1)),
avx("vpmovsxbw", &MV, Word, Map::Escape38, &[0x20], None, pair(0, 1)),
avx("vpmovsxbd", &VV, Word, Map::Escape38, &[0x21], None, pair(0, 1)),
avx("vpmovsxbd", &MV, Word, Map::Escape38, &[0x21], None, pair(0, 1)),
avx("vpmovsxbq", &VV, Word, Map::Escape38, &[0x22], None, pair(0, 1)),
avx("vpmovsxbq", &MV, Word, Map::Escape38, &[0x22], None, pair(0, 1)),
avx("vpmovsxwd", &VV, Word, Map::Escape38, &[0x23], None, pair(0, 1)),
avx("vpmovsxwd", &MV, Word, Map::Escape38, &[0x23], None, pair(0, 1)),
avx("vpmovsxwq", &VV, Word, Map::Escape38, &[0x24], None, pair(0, 1)),
avx("vpmovsxwq", &MV, Word, Map::Escape38, &[0x24], None, pair(0, 1)),
avx("vpmovsxdq", &VV, Word, Map::Escape38, &[0x25], None, pair(0, 1)),
avx("vpmovsxdq", &MV, Word, Map::Escape38, &[0x25], None, pair(0, 1)),
avx("vpmovzxbw", &VV, Word, Map::Escape38, &[0x30], None, pair(0, 1)),
avx("vpmovzxbw", &MV, Word, Map::Escape38, &[0x30], None, pair(0, 1)),
avx("vpmovzxbd", &VV, Word, Map::Escape38, &[0x31], None, pair(0, 1)),
avx("vpmovzxbd", &MV, Word, Map::Escape38, &[0x31], None, pair(0, 1)),
avx("vpmovzxbq", &VV, Word, Map::Escape38, &[0x32], None, pair(0, 1)),
avx("vpmovzxbq", &MV, Word, Map::Escape38, &[0x32], None, pair(0, 1)),
avx("vpmovzxwd", &VV, Word, Map::Escape38, &[0x33], None, pair(0, 1)),
avx("vpmovzxwd", &MV, Word, Map::Escape38, &[0x33], None, pair(0, 1)),
avx("vpmovzxwq", &VV, Word, Map::Escape38, &[0x34], None, pair(0, 1)),
avx("vpmovzxwq", &MV, Word, Map::Escape38, &[0x34], None, pair(0, 1)),
avx("vpmovzxdq", &VV, Word, Map::Escape38, &[0x35], None, pair(0, 1)),
avx("vpmovzxdq", &MV, Word, Map::Escape38, &[0x35], None, pair(0, 1)),
evex(
"vpbroadcastd",
&VV,
Word,
&[0x58],
pair(0, 1),
Evex::new(Map::Escape38, false).fixed(4).or_vex(false),
),
evex(
"vpbroadcastd",
&MV,
Word,
&[0x58],
pair(0, 1),
Evex::new(Map::Escape38, false).fixed(4).or_vex(false),
),
evex(
"vpbroadcastq",
&VV,
Word,
&[0x59],
pair(0, 1),
Evex::new(Map::Escape38, true).fixed(8).or_vex(false),
),
evex(
"vpbroadcastq",
&MV,
Word,
&[0x59],
pair(0, 1),
Evex::new(Map::Escape38, true).fixed(8).or_vex(false),
),
evex(
"vbroadcastss",
&VV,
Word,
&[0x18],
pair(0, 1),
Evex::new(Map::Escape38, false).fixed(4).or_vex(false),
),
evex(
"vbroadcastss",
&MV,
Word,
&[0x18],
pair(0, 1),
Evex::new(Map::Escape38, false).fixed(4).or_vex(false),
),
avx("vaesimc", &VV, Word, Map::Escape38, &[0xDB], None, pair(0, 1)),
avx("vaesimc", &MV, Word, Map::Escape38, &[0xDB], None, pair(0, 1)),
avx("vbroadcasti128", &MV, Word, Map::Escape38, &[0x5A], None, pair(0, 1)),
evex(
"vpbroadcastb",
&VV,
Word,
&[0x78],
pair(0, 1),
Evex::new(Map::Escape38, false).fixed(1).or_vex(false),
),
evex(
"vpbroadcastb",
&MV,
Word,
&[0x78],
pair(0, 1),
Evex::new(Map::Escape38, false).fixed(1).or_vex(false),
),
avx("vmovq", &VV, Single, Map::Escape, &[0x7E], None, pair(0, 1)),
avx("vmovq", &MV, Single, Map::Escape, &[0x7E], None, pair(0, 1)),
avx("vmovq", &VM, Word, Map::Escape, &[0xD6], None, pair(1, 0)),
avx("vmovdqu", &VV, Single, Map::Escape, &[0x6F], None, pair(0, 1)),
avx("vmovdqu", &MV, Single, Map::Escape, &[0x6F], None, pair(0, 1)),
avx("vmovdqu", &VM, Single, Map::Escape, &[0x7F], None, pair(1, 0)),
avx("vmovdqa", &VV, Word, Map::Escape, &[0x6F], None, pair(0, 1)),
avx("vmovdqa", &MV, Word, Map::Escape, &[0x6F], None, pair(0, 1)),
avx("vmovdqa", &VM, Word, Map::Escape, &[0x7F], None, pair(1, 0)),
avx("vmovups", &VV, Long, Map::Escape, &[0x10], None, pair(0, 1)),
avx("vmovups", &MV, Long, Map::Escape, &[0x10], None, pair(0, 1)),
avx("vmovups", &VM, Long, Map::Escape, &[0x11], None, pair(1, 0)),
avx("vmovapd", &VV, Word, Map::Escape, &[0x28], None, pair(0, 1)),
avx("vmovapd", &MV, Word, Map::Escape, &[0x28], None, pair(0, 1)),
avx("vmovapd", &VM, Word, Map::Escape, &[0x29], None, pair(1, 0)),
avx("vmovaps", &VV, Long, Map::Escape, &[0x28], None, pair(0, 1)),
avx("vmovaps", &MV, Long, Map::Escape, &[0x28], None, pair(0, 1)),
avx("vmovaps", &VM, Long, Map::Escape, &[0x29], None, pair(1, 0)),
avx("vmovupd", &VV, Word, Map::Escape, &[0x10], None, pair(0, 1)),
avx("vmovupd", &MV, Word, Map::Escape, &[0x10], None, pair(0, 1)),
avx("vmovupd", &VM, Word, Map::Escape, &[0x11], None, pair(1, 0)),
evex("vmovups", &VV, Long, &[0x10], pair(0, 1), Evex::new(Map::Escape, false)),
evex("vmovups", &MV, Long, &[0x10], pair(0, 1), Evex::new(Map::Escape, false)),
evex("vmovups", &VM, Long, &[0x11], pair(1, 0), Evex::new(Map::Escape, false)),
evex("vmovapd", &VV, Word, &[0x28], pair(0, 1), Evex::new(Map::Escape, true)),
evex("vmovapd", &MV, Word, &[0x28], pair(0, 1), Evex::new(Map::Escape, true)),
evex("vmovapd", &VM, Word, &[0x29], pair(1, 0), Evex::new(Map::Escape, true)),
evex("vmovaps", &VV, Long, &[0x28], pair(0, 1), Evex::new(Map::Escape, false)),
evex("vmovaps", &MV, Long, &[0x28], pair(0, 1), Evex::new(Map::Escape, false)),
evex("vmovaps", &VM, Long, &[0x29], pair(1, 0), Evex::new(Map::Escape, false)),
evex("vmovupd", &VV, Word, &[0x10], pair(0, 1), Evex::new(Map::Escape, true)),
evex("vmovupd", &MV, Word, &[0x10], pair(0, 1), Evex::new(Map::Escape, true)),
evex("vmovupd", &VM, Word, &[0x11], pair(1, 0), Evex::new(Map::Escape, true)),
avx("vmovd", &RV, Word, Map::Escape, &[0x6E], None, pair(0, 1)),
avx("vmovd", &MV, Word, Map::Escape, &[0x6E], None, pair(0, 1)),
avx("vmovd", &VR, Word, Map::Escape, &[0x7E], None, pair(1, 0)),
avx("vmovd", &VM, Word, Map::Escape, &[0x7E], None, pair(1, 0)),
evex(
"vpalignr",
&IVVV,
Word,
&[0x0F],
pair(1, 3),
Evex::new(Map::Escape3A, false).third(2).or_vex(false),
),
evex(
"vpalignr",
&IMVV,
Word,
&[0x0F],
pair(1, 3),
Evex::new(Map::Escape3A, false).third(2).or_vex(false),
),
Encoding {
imm: ImmSize::Is4,
..avx("vpblendvb", &VVVV, Word, Map::Escape3A, &[0x4C], Some(2), pair(1, 3))
},
Encoding {
imm: ImmSize::Is4,
..avx("vpblendvb", &VMVV, Word, Map::Escape3A, &[0x4C], Some(2), pair(1, 3))
},
avx("vpblendd", &IVVV, Word, Map::Escape3A, &[0x02], Some(2), pair(1, 3)),
avx("vpblendd", &IMVV, Word, Map::Escape3A, &[0x02], Some(2), pair(1, 3)),
avx("vinserti128", &IVVV, Word, Map::Escape3A, &[0x38], Some(2), pair(1, 3)),
avx("vinserti128", &IMVV, Word, Map::Escape3A, &[0x38], Some(2), pair(1, 3)),
avx("vinsertf128", &IVVV, Word, Map::Escape3A, &[0x18], Some(2), pair(1, 3)),
avx("vinsertf128", &IMVV, Word, Map::Escape3A, &[0x18], Some(2), pair(1, 3)),
avx("vperm2i128", &IVVV, Word, Map::Escape3A, &[0x46], Some(2), pair(1, 3)),
avx("vperm2i128", &IMVV, Word, Map::Escape3A, &[0x46], Some(2), pair(1, 3)),
avx("vperm2f128", &IVVV, Word, Map::Escape3A, &[0x06], Some(2), pair(1, 3)),
avx("vperm2f128", &IMVV, Word, Map::Escape3A, &[0x06], Some(2), pair(1, 3)),
evex(
"vpslld",
&IVV,
Word,
&[0x72],
ext(1, 6),
Evex::new(Map::Escape, false).third(2).or_vex(false),
),
evex(
"vpsrld",
&IVV,
Word,
&[0x72],
ext(1, 2),
Evex::new(Map::Escape, false).third(2).or_vex(false),
),
evex(
"vpsrad",
&IVV,
Word,
&[0x72],
ext(1, 4),
Evex::new(Map::Escape, false).third(2).or_vex(false),
),
evex(
"vpsraw",
&IVV,
Word,
&[0x71],
ext(1, 4),
Evex::new(Map::Escape, false).third(2).or_vex(false),
),
evex(
"vpsllq",
&IVV,
Word,
&[0x73],
ext(1, 6),
Evex::new(Map::Escape, true).third(2).or_vex(false),
),
evex(
"vpsrlq",
&IVV,
Word,
&[0x73],
ext(1, 2),
Evex::new(Map::Escape, true).third(2).or_vex(false),
),
evex(
"vpslldq",
&IVV,
Word,
&[0x73],
ext(1, 7),
Evex::new(Map::Escape, false).third(2).or_vex(false),
),
evex(
"vpsrldq",
&IVV,
Word,
&[0x73],
ext(1, 3),
Evex::new(Map::Escape, false).third(2).or_vex(false),
),
avx("vextracti128", &IVV, Word, Map::Escape3A, &[0x39], None, pair(2, 1)),
avx("vextracti128", &IVM, Word, Map::Escape3A, &[0x39], None, pair(2, 1)),
avx("vpextrq", &IVR, WordQuad, Map::Escape3A, &[0x16], None, pair(2, 1)),
avx("vpextrq", &IVM, WordQuad, Map::Escape3A, &[0x16], None, pair(2, 1)),
avx("vpinsrq", &IRVV, WordQuad, Map::Escape3A, &[0x22], Some(2), pair(1, 3)),
avx("vpinsrq", &IMVV, WordQuad, Map::Escape3A, &[0x22], Some(2), pair(1, 3)),
avx("vpextrb", &IVR, Word, Map::Escape3A, &[0x14], None, pair(2, 1)),
avx("vpextrb", &IVM, Word, Map::Escape3A, &[0x14], None, pair(2, 1)),
avx("vpextrw", &IVR, Word, Map::Escape, &[0xC5], None, pair(1, 2)),
avx("vpextrw", &IVM, Word, Map::Escape3A, &[0x15], None, pair(2, 1)),
avx("vpextrd", &IVR, Word, Map::Escape3A, &[0x16], None, pair(2, 1)),
avx("vpextrd", &IVM, Word, Map::Escape3A, &[0x16], None, pair(2, 1)),
avx("vpinsrb", &IRVV, Word, Map::Escape3A, &[0x20], Some(2), pair(1, 3)),
avx("vpinsrb", &IMVV, Word, Map::Escape3A, &[0x20], Some(2), pair(1, 3)),
avx("vpinsrw", &IRVV, Word, Map::Escape, &[0xC4], Some(2), pair(1, 3)),
avx("vpinsrw", &IMVV, Word, Map::Escape, &[0xC4], Some(2), pair(1, 3)),
avx("vpinsrd", &IRVV, Word, Map::Escape3A, &[0x22], Some(2), pair(1, 3)),
avx("vpinsrd", &IMVV, Word, Map::Escape3A, &[0x22], Some(2), pair(1, 3)),
avx("vzeroupper", &NO_ARGS, Long, Map::Escape, &[0x77], None, NO_MODRM),
Encoding {
vex: Some(Vex { map: Map::Escape, vvvv: None, long: true }),
..avx("vzeroall", &NO_ARGS, Long, Map::Escape, &[0x77], None, NO_MODRM)
},
avx("rorxl", &IRR, Double, Map::Escape3A, &[0xF0], None, pair(1, 2)),
avx("rorxl", &IMR, Double, Map::Escape3A, &[0xF0], None, pair(1, 2)),
avx("rorxq", &IRR, DoubleQuad, Map::Escape3A, &[0xF0], None, pair(1, 2)),
avx("rorxq", &IMR, DoubleQuad, Map::Escape3A, &[0xF0], None, pair(1, 2)),
avx("andnl", &RRR, Long, Map::Escape38, &[0xF2], Some(1), pair(0, 2)),
avx("andnl", &MRR, Long, Map::Escape38, &[0xF2], Some(1), pair(0, 2)),
avx("andnq", &RRR, Quad, Map::Escape38, &[0xF2], Some(1), pair(0, 2)),
avx("andnq", &MRR, Quad, Map::Escape38, &[0xF2], Some(1), pair(0, 2)),
avx("bzhil", &RRR, Long, Map::Escape38, &[0xF5], Some(0), pair(1, 2)),
avx("bzhil", &RMR, Long, Map::Escape38, &[0xF5], Some(0), pair(1, 2)),
avx("bzhiq", &RRR, Quad, Map::Escape38, &[0xF5], Some(0), pair(1, 2)),
avx("bzhiq", &RMR, Quad, Map::Escape38, &[0xF5], Some(0), pair(1, 2)),
];
static ONLY32: &[Encoding] = &[
bytes("incw", &R, Word, &[0x40], plus(0), NO_IMM),
bytes("incl", &R, Long, &[0x40], plus(0), NO_IMM),
bytes("decw", &R, Word, &[0x48], plus(0), NO_IMM),
bytes("decl", &R, Long, &[0x48], plus(0), NO_IMM),
bytes("pushl", &R, Long, &[0x50], plus(0), NO_IMM),
bytes("popl", &R, Long, &[0x58], plus(0), NO_IMM),
bytes("pushl", &M, Long, &[0xFF], ext(0, 6), NO_IMM),
bytes("popl", &M, Long, &[0x8F], ext(0, 0), NO_IMM),
takes("pushl", &I, Signed8, Long, &[0x6A], NO_MODRM, ImmSize::Ib),
takes("pushl", &I, Fits::Long, Long, &[0x68], NO_MODRM, ImmSize::Id),
bytes("pushfl", &NO_ARGS, Long, &[0x9C], NO_MODRM, NO_IMM),
bytes("popfl", &NO_ARGS, Long, &[0x9D], NO_MODRM, NO_IMM),
bytes("sgdtl", &M, Long, &[0x0F, 0x01], ext(0, 0), NO_IMM),
bytes("sidtl", &M, Long, &[0x0F, 0x01], ext(0, 1), NO_IMM),
bytes("lgdtl", &M, Long, &[0x0F, 0x01], ext(0, 2), NO_IMM),
bytes("lidtl", &M, Long, &[0x0F, 0x01], ext(0, 3), NO_IMM),
];
const ONLY64: [&str; 4] = ["pushq", "popq", "pushfq", "popfq"];
#[must_use]
pub fn encoding(mnemonic: &str, args: &[Kind], imm: i64) -> Option<&'static Encoding> {
encoding_in(Mode::Bits64, mnemonic, args, imm)
}
#[must_use]
pub fn encoding_in(
mode: Mode,
mnemonic: &str,
args: &[Kind],
imm: i64,
) -> Option<&'static Encoding> {
rows_in(mode, mnemonic, args).find(|row| row.fits.holds(seen(row, imm)))
}
fn seen(row: &Encoding, imm: i64) -> i64 {
match (row.fits, row.size) {
(Signed8, Long) => u32::try_from(imm).map_or(imm, |bits| i64::from(bits as i32)),
(Signed8, Word) => u16::try_from(imm).map_or(imm, |bits| i64::from(bits as i16)),
_ => imm,
}
}
fn rows_in<'a>(
mode: Mode,
mnemonic: &'a str,
args: &'a [Kind],
) -> impl Iterator<Item = &'static Encoding> + 'a {
let (only, shared): (&'static [Encoding], bool) = match mode {
Mode::Bits64 => (&[], true),
Mode::Bits32 => (ONLY32, !ONLY64.contains(&mnemonic)),
};
only.iter()
.filter(move |row| row.mnemonic == mnemonic && row.args == args)
.chain(rows(mnemonic, args).filter(move |_| shared))
}
fn rows<'a>(mnemonic: &'a str, args: &'a [Kind]) -> impl Iterator<Item = &'static Encoding> + 'a {
static AT: LazyLock<named::Names<Vec<usize>>> =
LazyLock::new(|| named::every(ENCODINGS, |row| row.mnemonic));
AT.get(mnemonic)
.into_iter()
.flatten()
.map(|&at| &ENCODINGS[at])
.filter(move |row| row.args == args)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Addr {
pub base: Option<PhysReg>,
pub index: Option<PhysReg>,
pub scale: u8,
pub disp: i32,
pub rip: bool,
pub segment: Option<Segment>,
pub linked: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Value {
Reg(PhysReg, Width),
Xmm(PhysReg),
Vector(u8, Length),
Mask(u8),
High(PhysReg),
Mem(Addr),
Imm(i64),
Dest,
Stack,
Control(u8),
Debug(u8),
Seg(Segment),
}
impl Value {
#[must_use]
pub fn kind(self) -> Kind {
match self {
Value::Control(_) => Kind::Control,
Value::Debug(_) => Kind::Debug,
Value::Seg(_) => Kind::Seg,
Value::Reg(_, _) | Value::High(_) => Kind::Reg,
Value::Xmm(_) | Value::Vector(_, _) => Kind::Vec,
Value::Mask(_) => Kind::Mask,
Value::Mem(_) => Kind::Mem,
Value::Imm(_) => Kind::Imm,
Value::Dest => Kind::Dest,
Value::Stack => Kind::Stack,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Holes {
pub dest: Option<usize>,
pub rip: Option<usize>,
pub disp: Option<usize>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Error {
Unwritten {
mnemonic: String,
args: Vec<Kind>,
},
Immediate {
mnemonic: String,
imm: i64,
},
Crowded {
mnemonic: String,
},
Scale {
scale: u8,
},
Index,
Argument {
mnemonic: String,
at: u8,
},
Mask {
mnemonic: String,
},
Register {
mnemonic: String,
number: u8,
},
Wide {
mnemonic: String,
},
Relative {
mnemonic: String,
},
Vex {
mnemonic: String,
},
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Unwritten { mnemonic, args } => {
write!(f, "no encoding for {mnemonic} with {} arguments {args:?}", args.len())
}
Error::Immediate { mnemonic, imm } => {
write!(f, "no form of {mnemonic} can carry the immediate {imm}")
}
Error::Crowded { mnemonic } => {
write!(f, "{mnemonic} names ah and a register that needs a rex byte")
}
Error::Scale { scale } => write!(f, "{scale} is not a scale this machine has"),
Error::Index => write!(f, "the stack pointer cannot be an index"),
Error::Argument { mnemonic, at } => {
write!(f, "argument {at} of {mnemonic} is not what its encoding expects")
}
Error::Mask { mnemonic } => write!(f, "{mnemonic} cannot take a mask"),
Error::Register { mnemonic, number } => {
write!(f, "{mnemonic} names register {number}, which 32 bit mode cannot name")
}
Error::Wide { mnemonic } => {
write!(f, "{mnemonic} has a 64 bit operand, which 32 bit mode cannot write")
}
Error::Relative { mnemonic } => write!(
f,
"{mnemonic} has an address counted from the instruction, which 32 bit mode lacks"
),
Error::Vex { mnemonic } => write!(
f,
"{mnemonic} is only written here with a VEX prefix, which cannot name a zmm \
register or one numbered 16 or above"
),
}
}
}
impl std::error::Error for Error {}
const REX_W: u8 = 0b1000;
const REX_R: u8 = 0b0100;
const REX_X: u8 = 0b0010;
const REX_B: u8 = 0b0001;
pub fn encode(mnemonic: &str, values: &[Value], out: &mut Vec<u8>) -> Result<Holes, Error> {
encode_masked(mnemonic, values, Opmask::default(), out)
}
pub fn encode_in(
mode: Mode,
mnemonic: &str,
values: &[Value],
out: &mut Vec<u8>,
) -> Result<Holes, Error> {
encode_masked_in(mode, mnemonic, values, Opmask::default(), out)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Opmask {
pub k: u8,
pub zero: bool,
}
pub fn encode_masked(
mnemonic: &str,
values: &[Value],
mask: Opmask,
out: &mut Vec<u8>,
) -> Result<Holes, Error> {
encode_masked_in(Mode::Bits64, mnemonic, values, mask, out)
}
pub fn encode_masked_in(
mode: Mode,
mnemonic: &str,
values: &[Value],
mask: Opmask,
out: &mut Vec<u8>,
) -> Result<Holes, Error> {
if mode == Mode::Bits32 && ONLY64.contains(&mnemonic) {
return Err(Error::Wide { mnemonic: mnemonic.to_owned() });
}
let mut few = [Kind::Imm; 4];
let many: Vec<Kind>;
let args: &[Kind] = if values.len() <= few.len() {
for (kind, value) in few.iter_mut().zip(values) {
*kind = value.kind();
}
&few[..values.len()]
} else {
many = values.iter().map(|value| value.kind()).collect();
&many
};
let imm = values
.iter()
.find_map(|value| match value {
Value::Imm(number) => Some(*number),
_ => None,
})
.unwrap_or(0);
let Some(row) = encoding_in(mode, mnemonic, args, imm) else {
return Err(if rows_in(mode, mnemonic, args).next().is_some() {
Error::Immediate { mnemonic: mnemonic.to_owned(), imm }
} else {
Error::Unwritten { mnemonic: mnemonic.to_owned(), args: args.to_vec() }
});
};
let row = widened(mode, row, values, mask).unwrap_or(row);
let row = flipped(mode, row, values).unwrap_or(row);
if mask != Opmask::default() && row.evex.is_none() {
return Err(Error::Mask { mnemonic: mnemonic.to_owned() });
}
if mode == Mode::Bits32 && row.size.wide() {
return Err(Error::Wide { mnemonic: mnemonic.to_owned() });
}
let mut writer = Writer {
row,
values,
mode,
rex: 0,
high: 0,
forced: false,
banned: false,
evex: None,
scale: 1,
length: Length::Xmm,
};
if let Some(evex) = row.evex {
writer.choose(evex, mask);
} else if row.vex.is_some() {
writer.measure()?;
}
writer.write(out, imm, mask)
}
fn widened(
mode: Mode,
row: &Encoding,
values: &[Value],
mask: Opmask,
) -> Option<&'static Encoding> {
if row.evex.is_some() || row.vex.is_none() {
return None;
}
let wide = values.iter().any(|value| {
matches!(*value, Value::Vector(number, length) if number >= 16 || length == Length::Zmm)
});
if !wide && mask == Opmask::default() {
return None;
}
let args: Vec<Kind> = values.iter().map(|value| value.kind()).collect();
rows_in(mode, row.mnemonic, &args).find(|other| other.evex.is_some())
}
fn flipped(mode: Mode, row: &Encoding, values: &[Value]) -> Option<&'static Encoding> {
let number = |value: &Value| match *value {
Value::Xmm(reg) => Some(reg.number()),
Value::Vector(number, _) => Some(number),
_ => None,
};
let [from, to] = values else { return None };
let high = number(from)? >= 8 && number(to)? < 8;
if !high || row.evex.is_some() || row.vex.is_none_or(|vex| vex.map != Map::Escape) {
return None;
}
rows_in(mode, row.mnemonic, &VM).find(|store| store.vex.is_some())
}
struct Writer<'a> {
row: &'a Encoding,
values: &'a [Value],
mode: Mode,
rex: u8,
forced: bool,
banned: bool,
high: u8,
evex: Option<Evex>,
scale: i32,
length: Length,
}
impl Writer<'_> {
fn measure(&mut self) -> Result<(), Error> {
for value in self.values {
if let Value::Vector(number, length) = *value {
if number >= 16 || length == Length::Zmm {
return Err(Error::Vex { mnemonic: self.row.mnemonic.to_owned() });
}
self.length = self.length.max(length);
}
}
Ok(())
}
fn choose(&mut self, evex: Evex, mask: Opmask) {
let mut high = false;
for value in self.values {
if let Value::Vector(number, length) = *value {
self.length = self.length.max(length);
high |= number >= 16;
}
}
let plain = mask == Opmask::default() && !high && self.length != Length::Zmm;
if evex.vex.is_some() && plain {
return;
}
self.evex = Some(evex);
self.scale = i32::from(match evex.tuple {
Tuple::Full => self.length.bytes(),
Tuple::Fixed(bytes) => bytes,
});
}
fn write(mut self, out: &mut Vec<u8>, imm: i64, mask: Opmask) -> Result<Holes, Error> {
let mut tail = Vec::new();
let mut holes = Holes::default();
let mut plus = 0;
match self.row.fields {
Fields::None => {}
Fields::Ext { rm, ext } => self.address(rm, ext, &mut tail, &mut holes)?,
Fields::Pair { rm, reg } => {
let reg = self.number(reg, REX_R)?;
self.address(rm, reg, &mut tail, &mut holes)?;
}
Fields::Plus { reg } => plus = self.number(reg, REX_B)?,
}
if self.banned && (self.forced || self.rex != 0) {
return Err(Error::Crowded { mnemonic: self.row.mnemonic.to_owned() });
}
let vex = match self.row.evex {
Some(evex) if self.evex.is_none() => evex.vex.map(|wide| {
(Vex { map: evex.map, vvvv: evex.vvvv, long: self.length == Length::Ymm }, wide)
}),
_ => self.row.vex.map(|vex| {
(Vex { long: vex.long || self.length == Length::Ymm, ..vex }, self.row.size.wide())
}),
};
if let Some(evex) = self.evex {
if let Some(prefix) = self.segment() {
out.push(prefix);
}
let vvvv = match evex.vvvv {
Some(at) => self.vvvv(at)?,
None => 0,
};
self.evex_prefix(evex, vvvv, mask, out);
} else if let Some((vex, wide)) = vex {
if let Some(prefix) = self.segment() {
out.push(prefix);
}
let vvvv = match vex.vvvv {
Some(at) => self.vvvv(at)?,
None => 0,
};
self.prefix(vex, wide, vvvv, out);
} else {
self.legacy(out);
}
let (last, front) = self.row.opcode.split_last().expect("an opcode is at least one byte");
out.extend_from_slice(front);
out.push(last + plus);
let at = out.len();
for hole in [&mut holes.dest, &mut holes.rip, &mut holes.disp].into_iter().flatten() {
*hole += at;
}
out.extend_from_slice(&tail);
match self.row.imm {
ImmSize::None => {}
ImmSize::Ib => out.push(imm as u8),
ImmSize::Iw => out.extend_from_slice(&(imm as u16).to_le_bytes()),
ImmSize::Id => out.extend_from_slice(&(imm as u32).to_le_bytes()),
ImmSize::Io => out.extend_from_slice(&imm.to_le_bytes()),
ImmSize::Cd => {
holes.dest = Some(out.len());
out.extend_from_slice(&0i32.to_le_bytes());
}
ImmSize::Cb => {
holes.dest = Some(out.len());
out.push(0);
}
ImmSize::Is4 => out.push(self.vvvv(0)? << 4),
}
Ok(holes)
}
fn prefix(&self, vex: Vex, wide: bool, vvvv: u8, out: &mut Vec<u8>) {
let pp = self.pp();
let tail = ((!vvvv & 0xF) << 3) | (u8::from(vex.long) << 2) | pp;
let short = !wide && vex.map == Map::Escape && self.rex & (REX_X | REX_B) == 0;
if short {
out.push(0xC5);
out.push((u8::from(self.rex & REX_R == 0) << 7) | tail);
return;
}
out.push(0xC4);
out.push(
(u8::from(self.rex & REX_R == 0) << 7)
| (u8::from(self.rex & REX_X == 0) << 6)
| (u8::from(self.rex & REX_B == 0) << 5)
| vex.map.bits(),
);
out.push((u8::from(wide) << 7) | tail);
}
fn pp(&self) -> u8 {
match self.row.size.prefix() {
None => 0,
Some(0x66) => 1,
Some(0xF3) => 2,
Some(0xF2) => 3,
Some(_) => unreachable!("a size writes one of those three bytes or none"),
}
}
fn evex_prefix(&self, evex: Evex, vvvv: u8, mask: Opmask, out: &mut Vec<u8>) {
let x = self.rex & REX_X != 0 || self.high & REX_B != 0;
out.push(0x62);
out.push(
(u8::from(self.rex & REX_R == 0) << 7)
| (u8::from(!x) << 6)
| (u8::from(self.rex & REX_B == 0) << 5)
| (u8::from(self.high & REX_R == 0) << 4)
| evex.map.bits(),
);
out.push((u8::from(evex.w) << 7) | ((!vvvv & 0xF) << 3) | 0b100 | self.pp());
out.push(
(u8::from(mask.zero) << 7)
| (self.length.bits() << 5)
| (u8::from(vvvv & 0x10 == 0) << 3)
| (mask.k & 7),
);
}
fn legacy(&self, out: &mut Vec<u8>) {
if self.row.wait {
out.push(0x9B);
}
if let Some(prefix) = self.segment() {
out.push(prefix);
}
if self.row.size == WordDouble {
out.push(0x66);
}
if let Some(prefix) = self.row.size.prefix() {
out.push(prefix);
}
let rex = if self.row.size.wide() { self.rex | REX_W } else { self.rex };
if rex != 0 || (self.forced && !self.banned) {
out.push(0x40 | rex);
}
}
fn segment(&self) -> Option<u8> {
self.values.iter().find_map(|value| match value {
Value::Mem(addr) => addr.segment.map(Segment::prefix),
_ => None,
})
}
fn number(&mut self, at: u8, bit: u8) -> Result<u8, Error> {
match self.values.get(usize::from(at)) {
Some(&Value::Reg(reg, width)) => {
let number = reg.number();
if self.mode == Mode::Bits32
&& (number >= 8 || (width == Width::Byte && (4..8).contains(&number)))
{
return Err(self.unnamed(number));
}
if number >= 8 {
self.rex |= bit;
}
if width == Width::Byte && (4..8).contains(&number) {
self.forced = true;
}
Ok(number & 7)
}
Some(&Value::Xmm(reg)) => {
let number = reg.number();
if self.mode == Mode::Bits32 && number >= 8 {
return Err(self.unnamed(number));
}
if number >= 8 {
self.rex |= bit;
}
Ok(number & 7)
}
Some(&Value::Vector(number, _))
if (self.row.evex.is_some() && (number < 16 || self.evex.is_some()))
|| (self.row.vex.is_some() && number < 16) =>
{
if self.mode == Mode::Bits32 && number >= 8 {
return Err(self.unnamed(number));
}
if number & 8 != 0 {
self.rex |= bit;
}
if number & 16 != 0 {
self.high |= bit;
}
Ok(number & 7)
}
Some(&Value::Mask(number)) if number < 8 => Ok(number),
Some(&(Value::Control(number) | Value::Debug(number))) if number < 16 => {
if number >= 8 {
self.rex |= bit;
}
Ok(number & 7)
}
Some(&Value::Seg(segment)) => Ok(segment.number()),
Some(&Value::High(reg)) if reg.number() < 4 => {
self.banned = true;
Ok(reg.number() + 4)
}
_ => Err(Error::Argument { mnemonic: self.row.mnemonic.to_owned(), at }),
}
}
fn vvvv(&self, at: u8) -> Result<u8, Error> {
let number = match self.values.get(usize::from(at)) {
Some(&Value::Reg(reg, _)) | Some(&Value::Xmm(reg)) => reg.number(),
Some(&Value::Vector(number, _)) if number < 32 => number,
Some(&Value::Mask(number)) if number < 8 => number,
_ => return Err(Error::Argument { mnemonic: self.row.mnemonic.to_owned(), at }),
};
if self.mode == Mode::Bits32 && number >= 8 {
return Err(self.unnamed(number));
}
Ok(number)
}
fn unnamed(&self, number: u8) -> Error {
Error::Register { mnemonic: self.row.mnemonic.to_owned(), number }
}
fn address(
&mut self,
at: u8,
reg: u8,
out: &mut Vec<u8>,
holes: &mut Holes,
) -> Result<(), Error> {
match self.values.get(usize::from(at)) {
Some(Value::Mem(addr)) => self.mem(*addr, reg, out, holes),
Some(_) => {
let rm = self.number(at, REX_B)?;
out.push(0b1100_0000 | (reg << 3) | rm);
Ok(())
}
None => Err(Error::Argument { mnemonic: self.row.mnemonic.to_owned(), at }),
}
}
fn mem(
&mut self,
addr: Addr,
reg: u8,
out: &mut Vec<u8>,
holes: &mut Holes,
) -> Result<(), Error> {
if addr.rip {
if self.mode == Mode::Bits32 {
return Err(Error::Relative { mnemonic: self.row.mnemonic.to_owned() });
}
out.push((reg << 3) | 0b101);
holes.rip = Some(out.len());
out.extend_from_slice(&addr.disp.to_le_bytes());
return Ok(());
}
let index = match addr.index {
Some(index) if index.number() == 4 => return Err(Error::Index),
Some(index) if self.mode == Mode::Bits32 && index.number() >= 8 => {
return Err(self.unnamed(index.number()));
}
Some(index) => {
if index.number() >= 8 {
self.rex |= REX_X;
}
Some(index.number() & 7)
}
None => None,
};
let scale = match addr.scale {
_ if index.is_none() => 0,
1 => 0,
2 => 1,
4 => 2,
8 => 3,
scale => return Err(Error::Scale { scale }),
};
let far = addr.base.map(PhysReg::number).filter(|&number| number >= 8);
if let Some(number) = far.filter(|_| self.mode == Mode::Bits32) {
return Err(self.unnamed(number));
}
let base = addr.base.map(|base| {
if base.number() >= 8 {
self.rex |= REX_B;
}
base.number() & 7
});
if self.mode == Mode::Bits32 && base.is_none() && index.is_none() {
out.push((reg << 3) | 0b101);
if addr.linked {
holes.disp = Some(out.len());
}
out.extend_from_slice(&addr.disp.to_le_bytes());
return Ok(());
}
let second = index.is_some() || base == Some(4) || base.is_none();
let mode = match base {
None => 0,
Some(base) => {
if addr.linked {
2
} else if addr.disp == 0 && base != 5 {
0
} else if addr.disp % self.scale == 0
&& i8::try_from(addr.disp / self.scale).is_ok()
{
1
} else {
2
}
}
};
out.push((mode << 6) | (reg << 3) | if second { 0b100 } else { base.unwrap_or(0) });
if second {
out.push((scale << 6) | (index.unwrap_or(4) << 3) | base.unwrap_or(5));
}
match mode {
0 if base.is_none() => {
if addr.linked {
holes.disp = Some(out.len());
}
out.extend_from_slice(&addr.disp.to_le_bytes());
}
0 => {}
1 => out.push((addr.disp / self.scale) as u8),
_ => {
if addr.linked {
holes.disp = Some(out.len());
}
out.extend_from_slice(&addr.disp.to_le_bytes());
}
}
Ok(())
}
}
const NOPS: [&[u8]; 11] = [
&[0x90],
&[0x66, 0x90],
&[0x0f, 0x1f, 0x00],
&[0x0f, 0x1f, 0x40, 0x00],
&[0x0f, 0x1f, 0x44, 0x00, 0x00],
&[0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00],
&[0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00],
&[0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00],
&[0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00],
&[0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00],
&[0x66, 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00],
];
pub fn nops(count: usize, out: &mut Vec<u8>) {
let mut left = count;
while left > 0 {
let take = left.min(NOPS.len());
out.extend_from_slice(NOPS[take - 1]);
left -= take;
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::x86_64::text::written;
use crate::x86_64::{
INSTS, R8, R9, R10, R11, R12, R13, R15, RAX, RBP, RBX, RCX, RDI, RDX, RSI, RSP, xmm,
};
fn hex(mnemonic: &str, values: &[Value]) -> String {
let mut out = Vec::new();
encode(mnemonic, values, &mut out).expect("an instruction this target encodes");
out.iter().map(|byte| format!("{byte:02x}")).collect::<Vec<_>>().join(" ")
}
fn quad(reg: PhysReg) -> Value {
Value::Reg(reg, Width::Quad)
}
fn long(reg: PhysReg) -> Value {
Value::Reg(reg, Width::Long)
}
fn word(reg: PhysReg) -> Value {
Value::Reg(reg, Width::Word)
}
fn byte(reg: PhysReg) -> Value {
Value::Reg(reg, Width::Byte)
}
#[test]
fn every_instruction_the_listing_writes_is_one_this_encodes() {
for &(opcode, _) in INSTS {
let insts = written(opcode).expect("every described opcode is a written opcode");
for inst in insts {
let args: Vec<Kind> = inst.args.iter().map(|&arg| Kind::of(arg)).collect();
assert!(
encoding(inst.mnemonic, &args, 0).is_some()
|| encoding_in(Mode::Bits32, inst.mnemonic, &args, 0).is_some(),
"{opcode} writes {} with {args:?} and nothing encodes it",
inst.mnemonic
);
}
}
}
const PROBES: [i64; 11] =
[0, 1, -1, 127, 128, -128, -129, 0xffff, 0x1_0000, 0x7fff_ffff, 0x1_0000_0000];
#[test]
fn the_rows_of_one_instruction_go_from_the_smallest_immediate_to_the_largest() {
for (at, row) in ENCODINGS.iter().enumerate() {
for other in &ENCODINGS[at + 1..] {
if other.mnemonic != row.mnemonic || other.args != row.args {
continue;
}
if row.evex.is_none() && other.evex.is_some() {
continue;
}
for imm in PROBES {
assert!(
!row.fits.holds(imm) || other.fits.holds(imm),
"{} takes {imm} in front of a row that does not",
row.mnemonic
);
}
assert!(
PROBES.iter().any(|&imm| other.fits.holds(imm) && !row.fits.holds(imm)),
"{} has a row behind another that holds no more than it",
row.mnemonic
);
}
}
}
#[test]
fn an_immediate_no_form_of_an_instruction_can_hold_is_refused_rather_than_cut_down() {
let mut out = Vec::new();
let big = 0x1_2345_6789;
let error = encode("addq", &[Value::Imm(big), quad(RAX)], &mut out)
.expect_err("more than four bytes of immediate");
assert_eq!(error, Error::Immediate { mnemonic: "addq".to_owned(), imm: big });
assert_eq!(out, Vec::<u8>::new());
assert!(encode("movq", &[Value::Imm(big), quad(RAX)], &mut out).is_ok());
assert_eq!(hex("movl", &[Value::Imm(0xffff_ffff), long(RAX)]), "b8 ff ff ff ff");
assert_eq!(hex("addb", &[Value::Imm(200), byte(RAX)]), "80 c0 c8");
assert_eq!(hex("shlq", &[Value::Imm(63), quad(RAX)]), "48 c1 e0 3f");
}
#[test]
fn a_negative_number_is_cut_to_the_width_as_far_as_gas_does_it_quietly() {
assert_eq!(hex("andb", &[Value::Imm(-129), byte(RAX)]), "80 e0 7f");
assert_eq!(hex("andb", &[Value::Imm(-255), byte(RCX)]), "80 e1 01");
assert_eq!(
hex("andw", &[Value::Imm(-32769), Value::Reg(RCX, Width::Word)]),
"66 81 e1 ff 7f"
);
assert_eq!(hex("andl", &[Value::Imm(-0xffff_ffff), long(RCX)]), "81 e1 01 00 00 00");
let mut out = Vec::new();
assert!(encode("andb", &[Value::Imm(-256), byte(RCX)], &mut out).is_err());
assert!(encode("andb", &[Value::Imm(256), byte(RCX)], &mut out).is_err());
assert!(
encode("andw", &[Value::Imm(-65536), Value::Reg(RCX, Width::Word)], &mut out).is_err()
);
}
#[test]
fn an_instruction_with_two_registers_is_the_opcode_and_one_byte_that_names_both() {
assert_eq!(hex("addl", &[long(RCX), long(RAX)]), "01 c8");
assert_eq!(hex("addl", &[long(RAX), long(RCX)]), "01 c1");
assert_eq!(hex("addq", &[quad(RCX), quad(RAX)]), "48 01 c8");
let word = [Value::Reg(RCX, Width::Word), Value::Reg(RAX, Width::Word)];
assert_eq!(hex("addw", &word), "66 01 c8");
assert_eq!(hex("imull", &[long(RCX), long(RAX)]), "0f af c1");
}
#[test]
fn a_register_the_second_half_of_the_machine_added_is_named_in_the_byte_in_front() {
assert_eq!(hex("addl", &[long(R8), long(RAX)]), "44 01 c0");
assert_eq!(hex("addl", &[long(RAX), long(R8)]), "41 01 c0");
assert_eq!(hex("addq", &[quad(R8), quad(R8)]), "4d 01 c0");
assert_eq!(hex("pushq", &[quad(R12)]), "41 54");
assert_eq!(hex("popq", &[quad(RAX)]), "58");
}
#[test]
fn a_conditional_move_names_its_destination_in_the_register_field() {
assert_eq!(hex("cmovnel", &[long(RSI), long(RAX)]), "0f 45 c6");
assert_eq!(hex("cmovneq", &[quad(RSI), quad(RAX)]), "48 0f 45 c6");
assert_eq!(hex("cmovnew", &[word(RSI), word(RAX)]), "66 0f 45 c6");
assert_eq!(hex("cmovnel", &[long(R8), long(RAX)]), "41 0f 45 c0");
assert_eq!(hex("cmovnel", &[long(RAX), long(R8)]), "44 0f 45 c0");
}
#[test]
fn a_byte_register_the_machine_could_not_reach_before_forces_a_byte_that_says_nothing_else() {
assert_eq!(hex("movb", &[byte(RSI), byte(RAX)]), "40 88 f0");
assert_eq!(hex("sete", &[byte(RSI)]), "40 0f 94 c6");
assert_eq!(hex("sete", &[byte(RAX)]), "0f 94 c0");
assert_eq!(hex("movb", &[Value::High(RAX), byte(RDX)]), "88 e2");
let mut out = Vec::new();
let error = encode("movb", &[Value::High(RAX), byte(RSI)], &mut out)
.expect_err("ah and sil in one instruction");
assert_eq!(error, Error::Crowded { mnemonic: "movb".to_owned() });
}
#[test]
fn an_immediate_is_written_in_as_few_bytes_as_it_fits_in() {
assert_eq!(hex("addl", &[Value::Imm(1), long(RCX)]), "83 c1 01");
assert_eq!(hex("addl", &[Value::Imm(-1), long(RCX)]), "83 c1 ff");
assert_eq!(hex("addl", &[Value::Imm(1000), long(RCX)]), "81 c1 e8 03 00 00");
assert_eq!(hex("addq", &[Value::Imm(8), quad(RSP)]), "48 83 c4 08");
assert_eq!(hex("movq", &[Value::Imm(1), quad(RAX)]), "48 c7 c0 01 00 00 00");
assert_eq!(
hex("movq", &[Value::Imm(0x1_2345_6789), quad(RAX)]),
"48 b8 89 67 45 23 01 00 00 00"
);
assert_eq!(hex("movl", &[Value::Imm(1), long(RAX)]), "b8 01 00 00 00");
assert_eq!(hex("movl", &[Value::Imm(1), long(RCX)]), "b9 01 00 00 00");
assert_eq!(hex("movw", &[Value::Imm(1), word(RAX)]), "66 b8 01 00");
assert_eq!(hex("movb", &[Value::Imm(1), byte(RCX)]), "b1 01");
assert_eq!(hex("movb", &[Value::Imm(1), byte(RSI)]), "40 b6 01");
}
#[test]
fn a_comparison_against_an_immediate_is_the_eighth_column_of_the_shared_opcode() {
assert_eq!(hex("cmpl", &[Value::Imm(1), long(RCX)]), "83 f9 01");
assert_eq!(hex("cmpl", &[Value::Imm(-1), long(RCX)]), "83 f9 ff");
assert_eq!(hex("cmpl", &[Value::Imm(1000), long(RCX)]), "81 f9 e8 03 00 00");
assert_eq!(hex("cmpq", &[Value::Imm(8), quad(RSP)]), "48 83 fc 08");
assert_eq!(hex("cmpq", &[Value::Imm(100_000), quad(RAX)]), "48 81 f8 a0 86 01 00");
assert_eq!(hex("cmpw", &[Value::Imm(1), word(RAX)]), "66 83 f8 01");
assert_eq!(hex("cmpw", &[Value::Imm(1000), word(RAX)]), "66 81 f8 e8 03");
assert_eq!(hex("cmpb", &[Value::Imm(200), byte(RAX)]), "80 f8 c8");
let mut out = Vec::new();
let big = 0x1_2345_6789;
let error = encode("cmpq", &[Value::Imm(big), quad(RAX)], &mut out)
.expect_err("more than four bytes of immediate");
assert_eq!(error, Error::Immediate { mnemonic: "cmpq".to_owned(), imm: big });
}
#[test]
fn an_address_is_the_registers_it_names_and_whatever_is_added_to_them() {
let base = Addr { base: Some(RCX), ..Addr::default() };
assert_eq!(hex("movq", &[Value::Mem(base), quad(RAX)]), "48 8b 01");
let near = Addr { base: Some(RCX), disp: -16, ..Addr::default() };
assert_eq!(hex("movq", &[Value::Mem(near), quad(RAX)]), "48 8b 41 f0");
let far = Addr { base: Some(RCX), disp: 1000, ..Addr::default() };
assert_eq!(hex("movq", &[Value::Mem(far), quad(RAX)]), "48 8b 81 e8 03 00 00");
let indexed =
Addr { base: Some(RCX), index: Some(RDX), scale: 4, disp: -16, ..Addr::default() };
assert_eq!(hex("leaq", &[Value::Mem(indexed), quad(RAX)]), "48 8d 44 91 f0");
assert_eq!(hex("movl", &[long(RAX), Value::Mem(near)]), "89 41 f0");
}
#[test]
fn a_bit_in_memory_is_set_where_it_lives() {
let base = Addr { base: Some(RCX), ..Addr::default() };
assert_eq!(hex("btsl", &[long(RAX), Value::Mem(base)]), "0f ab 01");
assert_eq!(hex("btrq", &[quad(RAX), Value::Mem(base)]), "48 0f b3 01");
assert_eq!(hex("btsl", &[Value::Imm(5), Value::Mem(base)]), "0f ba 29 05");
assert_eq!(hex("btcw", &[Value::Imm(3), Value::Mem(base)]), "66 0f ba 39 03");
}
#[test]
fn a_repeat_prefix_is_in_front_of_everything_but_the_operand_size() {
assert_eq!(hex("rep movsl", &[]), "f3 a5");
assert_eq!(hex("rep movsq", &[]), "f3 48 a5");
assert_eq!(hex("rep movsw", &[]), "66 f3 a5");
assert_eq!(hex("repne scasb", &[]), "f2 ae");
assert_eq!(hex("repe cmpsq", &[]), "f3 48 a7");
assert_eq!(hex("lodsb", &[]), "ac");
assert_eq!(hex("stosw", &[]), "66 ab");
}
#[test]
fn the_two_registers_an_address_cannot_be_written_with_plainly_are_written_around() {
let stack = Addr { base: Some(RSP), disp: 8, ..Addr::default() };
assert_eq!(hex("movq", &[Value::Mem(stack), quad(RAX)]), "48 8b 44 24 08");
let frame = Addr { base: Some(RBP), ..Addr::default() };
assert_eq!(hex("movq", &[Value::Mem(frame), quad(RAX)]), "48 8b 45 00");
let twelve = Addr { base: Some(R12), disp: 8, ..Addr::default() };
assert_eq!(hex("movq", &[Value::Mem(twelve), quad(RAX)]), "49 8b 44 24 08");
let thirteen = Addr { base: Some(R13), ..Addr::default() };
assert_eq!(hex("movq", &[Value::Mem(thirteen), quad(RAX)]), "49 8b 45 00");
let mut out = Vec::new();
let bad = Addr { base: Some(RCX), index: Some(RSP), scale: 1, ..Addr::default() };
let error = encode("leaq", &[Value::Mem(bad), quad(RAX)], &mut out)
.expect_err("the stack pointer as an index");
assert_eq!(error, Error::Index);
}
#[test]
fn an_address_in_a_thread_s_own_block_is_a_prefix_and_a_constant_and_no_register() {
let guard = Addr { segment: Some(Segment::Fs), disp: 40, ..Addr::default() };
assert_eq!(hex("movq", &[Value::Mem(guard), quad(RAX)]), "64 48 8b 04 25 28 00 00 00");
let other = Addr { segment: Some(Segment::Gs), disp: 40, ..Addr::default() };
assert_eq!(hex("movq", &[Value::Mem(other), quad(RAX)]), "65 48 8b 04 25 28 00 00 00");
let guard = Addr { segment: Some(Segment::Fs), disp: 40, ..Addr::default() };
assert_eq!(hex("movq", &[Value::Mem(guard), quad(R12)]), "64 4c 8b 24 25 28 00 00 00");
}
#[test]
fn the_probe_a_prologue_touches_a_page_with_is_the_shortest_write_the_machine_has() {
let top = Addr { base: Some(RSP), ..Addr::default() };
assert_eq!(hex("orb", &[Value::Imm(0), Value::Mem(top)]), "80 0c 24 00");
let down = Addr { base: Some(RSP), disp: -4096, ..Addr::default() };
assert_eq!(hex("orb", &[Value::Imm(0), Value::Mem(down)]), "80 8c 24 00 f0 ff ff 00");
}
#[test]
fn the_landing_pad_is_four_bytes_and_none_of_them_are_worked_out() {
assert_eq!(hex("endbr64", &[]), "f3 0f 1e fa");
assert_eq!(hex("ud2", &[]), "0f 0b");
}
#[test]
fn the_breakpoint_and_the_segment_override_are_one_byte_each() {
assert_eq!(hex("int3", &[]), "cc");
assert_eq!(hex("cs", &[]), "2e");
}
#[test]
fn the_x87_load_and_store_are_one_opcode_with_two_extensions() {
let base = Addr { base: Some(RCX), ..Addr::default() };
assert_eq!(hex("fldt", &[Value::Mem(base)]), "db 29");
assert_eq!(hex("fstpt", &[Value::Mem(base)]), "db 39");
let near = Addr { base: Some(RCX), disp: -16, ..Addr::default() };
assert_eq!(hex("fldt", &[Value::Mem(near)]), "db 69 f0");
let stack = Addr { base: Some(RSP), disp: 8, ..Addr::default() };
assert_eq!(hex("fstpt", &[Value::Mem(stack)]), "db 7c 24 08");
let frame = Addr { base: Some(RBP), ..Addr::default() };
assert_eq!(hex("fldt", &[Value::Mem(frame)]), "db 6d 00");
let thirteen = Addr { base: Some(R13), disp: -16, ..Addr::default() };
assert_eq!(hex("fstpt", &[Value::Mem(thirteen)]), "41 db 7d f0");
let indexed = Addr { base: Some(RCX), index: Some(RDX), scale: 4, ..Addr::default() };
assert_eq!(hex("fldt", &[Value::Mem(indexed)]), "db 2c 91");
}
#[test]
fn the_x87_conversions_put_the_width_in_the_opcode_and_the_direction_in_the_extension() {
let base = Addr { base: Some(RCX), ..Addr::default() };
let at = |mnemonic| hex(mnemonic, &[Value::Mem(base)]);
assert_eq!(at("flds"), "d9 01");
assert_eq!(at("fldl"), "dd 01");
assert_eq!(at("fildl"), "db 01");
assert_eq!(at("fildll"), "df 29");
assert_eq!(at("fstps"), "d9 19");
assert_eq!(at("fstpl"), "dd 19");
assert_eq!(at("fistpl"), "db 19");
assert_eq!(at("fistpll"), "df 39");
assert_eq!(at("fnstcw"), "d9 39");
assert_eq!(at("fldcw"), "d9 29");
let frame = Addr { base: Some(RBP), disp: -16, ..Addr::default() };
assert_eq!(hex("fildl", &[Value::Mem(frame)]), "db 45 f0");
let stack = Addr { base: Some(RSP), disp: 8, ..Addr::default() };
assert_eq!(hex("fistpll", &[Value::Mem(stack)]), "df 7c 24 08");
}
#[test]
fn the_x87_arithmetic_is_two_constant_bytes_with_the_operation_in_the_second() {
let pair = [Value::Stack, Value::Stack];
let op = |mnemonic| hex(mnemonic, &pair);
assert_eq!(op("faddp"), "de c1");
assert_eq!(op("fmulp"), "de c9");
assert_eq!(op("fsubp"), "de e1");
assert_eq!(op("fsubrp"), "de e9");
assert_eq!(op("fdivp"), "de f1");
assert_eq!(op("fdivrp"), "de f9");
assert_eq!(hex("fchs", &[]), "d9 e0");
assert_eq!(hex("fabs", &[]), "d9 e1");
assert_eq!(op("fucomip"), "df e9");
assert_eq!(hex("fstp", &[Value::Stack]), "dd d8");
assert_eq!(hex("fprem", &[]), "d9 f8");
assert_eq!(hex("fpatan", &[]), "d9 f3");
assert_eq!(hex("fsqrt", &[]), "d9 fa");
assert_eq!(hex("fldpi", &[]), "d9 eb");
assert_eq!(hex("fldz", &[]), "d9 ee");
assert_eq!(hex("fnstsw", &[Value::Reg(RAX, Width::Word)]), "df e0");
}
#[test]
fn an_address_counted_from_the_end_of_the_instruction_leaves_its_displacement_open() {
let global = Addr { rip: true, ..Addr::default() };
let mut out = vec![0xcc];
let holes = encode("movq", &[Value::Mem(global), quad(RAX)], &mut out).expect("a global");
assert_eq!(out, [0xcc, 0x48, 0x8b, 0x05, 0, 0, 0, 0]);
assert_eq!(holes.rip, Some(4));
assert_eq!(holes.dest, None);
}
#[test]
fn a_jump_leaves_the_distance_to_where_it_goes_open() {
let mut out = Vec::new();
let holes = encode("jmp", &[Value::Dest], &mut out).expect("a jump");
assert_eq!(out, [0xe9, 0, 0, 0, 0]);
assert_eq!(holes.dest, Some(1));
out.clear();
let holes = encode("je", &[Value::Dest], &mut out).expect("a conditional jump");
assert_eq!(out, [0x0f, 0x84, 0, 0, 0, 0]);
assert_eq!(holes.dest, Some(2));
}
#[test]
fn an_instruction_with_no_arguments_is_the_opcode_and_whatever_says_how_wide_it_is() {
assert_eq!(hex("ret", &[]), "c3");
assert_eq!(hex("cltd", &[]), "99");
assert_eq!(hex("cqto", &[]), "48 99");
assert_eq!(hex("cwtd", &[]), "66 99");
assert_eq!(hex("cbtw", &[]), "66 98");
assert_eq!(hex("cwtl", &[]), "98");
assert_eq!(hex("cltq", &[]), "48 98");
assert_eq!(hex("leave", &[]), "c9");
}
#[test]
fn a_long_immediate_with_every_bit_set_takes_the_byte_form() {
assert_eq!(hex("andl", &[Value::Imm(0xFFFF_FFFF), long(RAX)]), "83 e0 ff");
assert_eq!(hex("andw", &[Value::Imm(0xFFFF), Value::Reg(RAX, Width::Word)]), "66 83 e0 ff");
assert_eq!(hex("andl", &[Value::Imm(0x8000_0000), long(RAX)]), "81 e0 00 00 00 80");
}
#[test]
fn notrack_goes_in_front_of_the_rex_byte() {
assert_eq!(hex("notrack jmp", &[quad(RAX)]), "3e ff e0");
assert_eq!(hex("notrack jmp", &[quad(R8)]), "3e 41 ff e0");
assert_eq!(hex("notrack call", &[quad(RDX)]), "3e ff d2");
}
#[test]
fn a_shift_by_a_count_does_not_encode_the_count_because_the_machine_knows_where_it_is() {
assert_eq!(hex("shlq", &[byte(RCX), quad(RAX)]), "48 d3 e0");
assert_eq!(hex("sarl", &[byte(RCX), long(RCX)]), "d3 f9");
assert_eq!(hex("shll", &[Value::Imm(3), long(RAX)]), "c1 e0 03");
}
#[test]
fn a_division_is_the_widening_and_then_the_instruction_that_names_only_its_divisor() {
assert_eq!(hex("idivl", &[long(RCX)]), "f7 f9");
assert_eq!(hex("idivq", &[quad(RSI)]), "48 f7 fe");
assert_eq!(hex("divl", &[long(RCX)]), "f7 f1");
assert_eq!(hex("negl", &[long(RAX)]), "f7 d8");
assert_eq!(hex("notq", &[quad(RAX)]), "48 f7 d0");
}
#[test]
fn a_compare_and_exchange_is_the_prefix_and_then_a_store_shaped_instruction() {
let at = Addr { base: Some(RAX), ..Addr::default() };
assert_eq!(hex("lock", &[]), "f0");
assert_eq!(hex("cmpxchgb", &[byte(RCX), Value::Mem(at)]), "0f b0 08");
assert_eq!(hex("cmpxchgw", &[word(RCX), Value::Mem(at)]), "66 0f b1 08");
assert_eq!(hex("cmpxchgl", &[long(RCX), Value::Mem(at)]), "0f b1 08");
assert_eq!(hex("cmpxchgq", &[quad(RCX), Value::Mem(at)]), "48 0f b1 08");
assert_eq!(hex("cmpxchgb", &[byte(RSI), Value::Mem(at)]), "40 0f b0 30");
}
#[test]
fn a_read_modify_write_names_the_address_the_way_a_compare_and_exchange_does() {
let at = Addr { base: Some(RAX), ..Addr::default() };
assert_eq!(hex("xchgb", &[byte(RCX), Value::Mem(at)]), "86 08");
assert_eq!(hex("xchgw", &[word(RCX), Value::Mem(at)]), "66 87 08");
assert_eq!(hex("xchgl", &[long(RCX), Value::Mem(at)]), "87 08");
assert_eq!(hex("xchgq", &[quad(RCX), Value::Mem(at)]), "48 87 08");
assert_eq!(hex("xaddb", &[byte(RCX), Value::Mem(at)]), "0f c0 08");
assert_eq!(hex("xaddw", &[word(RCX), Value::Mem(at)]), "66 0f c1 08");
assert_eq!(hex("xaddl", &[long(RCX), Value::Mem(at)]), "0f c1 08");
assert_eq!(hex("xaddq", &[quad(RCX), Value::Mem(at)]), "48 0f c1 08");
assert_eq!(hex("xchgb", &[byte(RSI), Value::Mem(at)]), "40 86 30");
}
#[test]
fn the_high_byte_of_a_register_is_the_low_one_four_places_along() {
assert_eq!(hex("xchgb", &[byte(RAX), Value::High(RAX)]), "86 c4");
assert_eq!(hex("xchgb", &[byte(RCX), Value::High(RCX)]), "86 cd");
assert_eq!(hex("xchgb", &[byte(RDX), Value::High(RDX)]), "86 d6");
assert_eq!(hex("xchgb", &[byte(RBX), Value::High(RBX)]), "86 df");
}
#[test]
fn a_conversion_puts_its_destination_where_the_arithmetic_puts_its_source() {
assert_eq!(hex("movzbl", &[byte(RAX), long(RCX)]), "0f b6 c8");
assert_eq!(hex("movsbq", &[byte(RAX), quad(RCX)]), "48 0f be c8");
assert_eq!(hex("movslq", &[long(RSI), quad(RAX)]), "48 63 c6");
assert_eq!(hex("movzwl", &[Value::Reg(RSI, Width::Word), long(RAX)]), "0f b7 c6");
}
#[test]
fn the_instructions_a_hand_written_file_uses_and_a_compiler_never_emits() {
assert_eq!(hex("adcb", &[byte(RCX), byte(RAX)]), "10 c8");
assert_eq!(hex("adcw", &[word(RCX), word(RAX)]), "66 11 c8");
assert_eq!(hex("adcl", &[long(RCX), long(RAX)]), "11 c8");
assert_eq!(hex("adcq", &[quad(RCX), quad(RAX)]), "48 11 c8");
assert_eq!(hex("sbbq", &[quad(RCX), quad(RAX)]), "48 19 c8");
let at = Addr { base: Some(RDX), ..Addr::default() };
assert_eq!(hex("adcq", &[Value::Mem(at), quad(R8)]), "4c 13 02");
assert_eq!(hex("sbbb", &[Value::Mem(at), byte(RAX)]), "1a 02");
assert_eq!(hex("adcq", &[Value::Imm(1), quad(RAX)]), "48 83 d0 01");
assert_eq!(hex("adcl", &[Value::Imm(1000), long(RCX)]), "81 d1 e8 03 00 00");
assert_eq!(hex("sbbq", &[Value::Imm(-1), quad(R8)]), "49 83 d8 ff");
assert_eq!(hex("adcb", &[Value::Imm(200), byte(RCX)]), "80 d1 c8");
assert_eq!(hex("incl", &[long(RAX)]), "ff c0");
assert_eq!(hex("incq", &[quad(RCX)]), "48 ff c1");
assert_eq!(hex("incw", &[word(RAX)]), "66 ff c0");
assert_eq!(hex("incb", &[byte(RSI)]), "40 fe c6");
assert_eq!(hex("decq", &[quad(RCX)]), "48 ff c9");
assert_eq!(hex("mulq", &[quad(RDX)]), "48 f7 e2");
assert_eq!(hex("mulb", &[byte(RCX)]), "f6 e1");
assert_eq!(hex("imulq", &[quad(RDX)]), "48 f7 ea");
assert_eq!(hex("rolq", &[Value::Imm(3), quad(RAX)]), "48 c1 c0 03");
assert_eq!(hex("rorl", &[Value::Imm(5), long(RCX)]), "c1 c9 05");
assert_eq!(hex("rolb", &[byte(RCX), byte(RDX)]), "d2 c2");
assert_eq!(hex("rorq", &[byte(RCX), quad(RAX)]), "48 d3 c8");
assert_eq!(hex("btq", &[Value::Imm(0), quad(R8)]), "49 0f ba e0 00");
assert_eq!(hex("btsq", &[Value::Imm(63), quad(RAX)]), "48 0f ba e8 3f");
assert_eq!(hex("btrl", &[Value::Imm(2), long(RCX)]), "0f ba f1 02");
assert_eq!(hex("btcw", &[Value::Imm(1), word(RDX)]), "66 0f ba fa 01");
assert_eq!(hex("btq", &[quad(RDX), quad(RAX)]), "48 0f a3 d0");
assert_eq!(hex("btsl", &[long(RCX), long(RAX)]), "0f ab c8");
assert_eq!(hex("bsfq", &[quad(RAX), quad(RDX)]), "48 0f bc d0");
assert_eq!(hex("bsrl", &[long(RAX), long(RCX)]), "0f bd c8");
assert_eq!(hex("lzcntl", &[long(RDX), long(RAX)]), "f3 0f bd c2");
assert_eq!(hex("lzcntq", &[quad(RDX), quad(RAX)]), "f3 48 0f bd c2");
assert_eq!(hex("tzcntl", &[long(RDX), long(RAX)]), "f3 0f bc c2");
assert_eq!(hex("tzcntq", &[quad(RDX), quad(RAX)]), "f3 48 0f bc c2");
let counted = Addr { base: Some(RBX), ..Addr::default() };
assert_eq!(hex("lzcntq", &[Value::Mem(counted), quad(RAX)]), "f3 48 0f bd 03");
assert_eq!(hex("tzcntl", &[Value::Mem(counted), long(RAX)]), "f3 0f bc 03");
assert_eq!(hex("popcntl", &[long(RDX), long(RAX)]), "f3 0f b8 c2");
assert_eq!(hex("popcntq", &[quad(RDX), quad(RAX)]), "f3 48 0f b8 c2");
assert_eq!(hex("popcntq", &[quad(R8), quad(RAX)]), "f3 49 0f b8 c0");
assert_eq!(hex("popcntl", &[Value::Mem(counted), long(RAX)]), "f3 0f b8 03");
assert_eq!(hex("crc32b", &[byte(RCX), long(RAX)]), "f2 0f 38 f0 c1");
assert_eq!(hex("crc32b", &[byte(RSI), long(RAX)]), "f2 40 0f 38 f0 c6");
assert_eq!(hex("crc32w", &[word(RCX), long(RAX)]), "66 f2 0f 38 f1 c1");
assert_eq!(hex("crc32w", &[word(R9), long(R10)]), "66 f2 45 0f 38 f1 d1");
assert_eq!(hex("crc32l", &[long(RCX), long(RAX)]), "f2 0f 38 f1 c1");
assert_eq!(hex("crc32l", &[long(R8), long(RDX)]), "f2 41 0f 38 f1 d0");
assert_eq!(hex("crc32q", &[quad(RCX), quad(RAX)]), "f2 48 0f 38 f1 c1");
assert_eq!(hex("crc32q", &[quad(R12), quad(R13)]), "f2 4d 0f 38 f1 ec");
assert_eq!(hex("crc32b", &[Value::Mem(counted), long(RAX)]), "f2 0f 38 f0 03");
assert_eq!(hex("crc32q", &[Value::Mem(counted), quad(RAX)]), "f2 48 0f 38 f1 03");
assert_eq!(hex("bswapl", &[long(RAX)]), "0f c8");
assert_eq!(hex("bswapq", &[quad(RAX)]), "48 0f c8");
assert_eq!(hex("bswapl", &[long(RDX)]), "0f ca");
assert_eq!(hex("bswapq", &[quad(R12)]), "49 0f cc");
let from = Addr { base: Some(RSI), ..Addr::default() };
assert_eq!(hex("movzbq", &[Value::Mem(from), quad(RAX)]), "48 0f b6 06");
assert_eq!(hex("movzwl", &[Value::Mem(from), long(RAX)]), "0f b7 06");
assert_eq!(hex("movsbl", &[Value::Mem(from), long(RAX)]), "0f be 06");
assert_eq!(hex("movslq", &[Value::Mem(from), quad(RAX)]), "48 63 06");
let along = Addr { base: Some(RSI), disp: 4, ..Addr::default() };
assert_eq!(hex("movswq", &[Value::Mem(along), quad(RDX)]), "48 0f bf 56 04");
let sum = Addr { base: Some(RSI), index: Some(RDX), scale: 2, ..Addr::default() };
assert_eq!(hex("leal", &[Value::Mem(sum), long(RAX)]), "8d 04 56");
assert_eq!(hex("movabsq", &[Value::Imm(-1), quad(RAX)]), "48 b8 ff ff ff ff ff ff ff ff");
let deep = Addr { base: Some(RAX), ..Addr::default() };
assert_eq!(hex("pushq", &[Value::Mem(deep)]), "ff 30");
assert_eq!(hex("popq", &[Value::Mem(deep)]), "8f 00");
assert_eq!(hex("xchgl", &[long(RCX), long(RDX)]), "87 ca");
assert_eq!(hex("movss", &[Value::Xmm(xmm(0)), Value::Xmm(xmm(1))]), "f3 0f 10 c8");
assert_eq!(hex("movsd", &[Value::Xmm(xmm(2)), Value::Xmm(xmm(3))]), "f2 0f 10 da");
}
#[test]
fn the_instructions_a_hand_written_loop_writes_into_memory() {
let at = Addr { base: Some(RDI), ..Addr::default() };
assert_eq!(hex("addq", &[quad(RAX), Value::Mem(at)]), "48 01 07");
assert_eq!(hex("addb", &[byte(RAX), Value::Mem(at)]), "00 07");
assert_eq!(hex("addw", &[word(RAX), Value::Mem(at)]), "66 01 07");
assert_eq!(hex("orq", &[quad(R8), Value::Mem(at)]), "4c 09 07");
assert_eq!(hex("sbbq", &[quad(RAX), Value::Mem(at)]), "48 19 07");
assert_eq!(hex("andq", &[quad(RAX), Value::Mem(at)]), "48 21 07");
assert_eq!(hex("subq", &[quad(RAX), Value::Mem(at)]), "48 29 07");
assert_eq!(hex("xorq", &[quad(RAX), Value::Mem(at)]), "48 31 07");
assert_eq!(hex("cmpq", &[quad(RAX), Value::Mem(at)]), "48 39 07");
assert_eq!(hex("cmpq", &[Value::Mem(at), quad(RAX)]), "48 3b 07");
let indexed = Addr { base: Some(RDI), index: Some(R8), scale: 8, disp: 8, ..at };
assert_eq!(hex("adcq", &[quad(R15), Value::Mem(indexed)]), "4e 11 7c c7 08");
assert_eq!(hex("addq", &[Value::Imm(1), Value::Mem(at)]), "48 83 07 01");
assert_eq!(hex("addq", &[Value::Imm(1000), Value::Mem(at)]), "48 81 07 e8 03 00 00");
assert_eq!(hex("addl", &[Value::Imm(1), Value::Mem(at)]), "83 07 01");
assert_eq!(hex("addw", &[Value::Imm(1), Value::Mem(at)]), "66 83 07 01");
assert_eq!(hex("addb", &[Value::Imm(1), Value::Mem(at)]), "80 07 01");
assert_eq!(hex("subq", &[Value::Imm(8), Value::Mem(at)]), "48 83 2f 08");
assert_eq!(hex("cmpq", &[Value::Imm(0), Value::Mem(at)]), "48 83 3f 00");
assert_eq!(hex("andl", &[Value::Imm(255), Value::Mem(at)]), "81 27 ff 00 00 00");
assert_eq!(hex("testq", &[quad(RAX), quad(RAX)]), "48 85 c0");
assert_eq!(hex("testl", &[long(RAX), long(RAX)]), "85 c0");
assert_eq!(hex("testw", &[word(RAX), word(RAX)]), "66 85 c0");
assert_eq!(hex("testq", &[quad(RAX), Value::Mem(at)]), "48 85 07");
assert_eq!(hex("testq", &[Value::Mem(at), quad(RAX)]), "48 85 07");
assert_eq!(hex("testq", &[Value::Imm(1), quad(R10)]), "49 f7 c2 01 00 00 00");
assert_eq!(hex("testq", &[Value::Imm(1), Value::Mem(at)]), "48 f7 07 01 00 00 00");
assert_eq!(hex("testb", &[Value::Imm(1), byte(RCX)]), "f6 c1 01");
let sixteen = Addr { base: Some(R8), disp: 16, ..Addr::default() };
assert_eq!(hex("mulq", &[Value::Mem(sixteen)]), "49 f7 60 10");
assert_eq!(hex("mull", &[Value::Mem(at)]), "f7 27");
assert_eq!(hex("imulq", &[Value::Mem(at)]), "48 f7 2f");
assert_eq!(hex("divq", &[Value::Mem(at)]), "48 f7 37");
assert_eq!(hex("idivq", &[Value::Mem(at)]), "48 f7 3f");
assert_eq!(hex("negq", &[Value::Mem(at)]), "48 f7 1f");
assert_eq!(hex("notq", &[Value::Mem(at)]), "48 f7 17");
assert_eq!(hex("incq", &[Value::Mem(at)]), "48 ff 07");
assert_eq!(hex("decq", &[Value::Mem(at)]), "48 ff 0f");
assert_eq!(hex("incb", &[Value::Mem(at)]), "fe 07");
let four = Addr { base: Some(RSI), disp: 4, ..Addr::default() };
assert_eq!(hex("decl", &[Value::Mem(four)]), "ff 4e 04");
}
#[test]
fn the_shifts_a_number_wider_than_a_register_needs() {
assert_eq!(hex("rclq", &[Value::Imm(3), quad(RAX)]), "48 c1 d0 03");
assert_eq!(hex("rcrq", &[Value::Imm(3), quad(RAX)]), "48 c1 d8 03");
assert_eq!(hex("rclq", &[byte(RCX), quad(RAX)]), "48 d3 d0");
assert_eq!(hex("rcrq", &[byte(RCX), quad(RAX)]), "48 d3 d8");
assert_eq!(hex("rolq", &[quad(RAX)]), "48 d1 c0");
assert_eq!(hex("rorq", &[quad(RAX)]), "48 d1 c8");
assert_eq!(hex("rclq", &[quad(RAX)]), "48 d1 d0");
assert_eq!(hex("rcrq", &[quad(RAX)]), "48 d1 d8");
assert_eq!(hex("shlq", &[quad(RAX)]), "48 d1 e0");
assert_eq!(hex("shrq", &[quad(RAX)]), "48 d1 e8");
assert_eq!(hex("sarq", &[quad(RAX)]), "48 d1 f8");
assert_eq!(hex("shrl", &[long(RAX)]), "d1 e8");
assert_eq!(hex("shrb", &[byte(RAX)]), "d0 e8");
assert_eq!(hex("shrw", &[word(RAX)]), "66 d1 e8");
let five = Value::Imm(5);
assert_eq!(hex("shldq", &[five, quad(RSI), quad(RDI)]), "48 0f a4 f7 05");
assert_eq!(hex("shrdq", &[five, quad(RSI), quad(RDI)]), "48 0f ac f7 05");
assert_eq!(hex("shldl", &[five, long(RSI), long(RDI)]), "0f a4 f7 05");
assert_eq!(hex("shldq", &[byte(RCX), quad(RSI), quad(RDI)]), "48 0f a5 f7");
assert_eq!(hex("shrdq", &[byte(RCX), quad(RSI), quad(RDI)]), "48 0f ad f7");
assert_eq!(hex("shldw", &[byte(RCX), word(RSI), word(RDI)]), "66 0f a5 f7");
}
#[test]
fn the_shifts_that_take_their_count_in_any_register() {
assert_eq!(hex("shlxq", &[quad(RCX), quad(RSI), quad(RDI)]), "c4 e2 f1 f7 fe");
assert_eq!(hex("shlxl", &[long(RCX), long(RSI), long(RDI)]), "c4 e2 71 f7 fe");
assert_eq!(hex("sarxq", &[quad(RCX), quad(RSI), quad(RDI)]), "c4 e2 f2 f7 fe");
assert_eq!(hex("sarxl", &[long(RCX), long(RSI), long(RDI)]), "c4 e2 72 f7 fe");
assert_eq!(hex("shrxq", &[quad(RCX), quad(RSI), quad(RDI)]), "c4 e2 f3 f7 fe");
assert_eq!(hex("shrxl", &[long(RCX), long(RSI), long(RDI)]), "c4 e2 73 f7 fe");
assert_eq!(hex("shlxq", &[quad(R15), quad(RAX), quad(RAX)]), "c4 e2 81 f7 c0");
assert_eq!(hex("shlxq", &[quad(RAX), quad(RAX), quad(RAX)]), "c4 e2 f9 f7 c0");
assert_eq!(hex("shlxq", &[quad(RAX), quad(R8), quad(R8)]), "c4 42 f9 f7 c0");
assert_eq!(hex("shrxq", &[quad(R15), quad(R15), quad(R15)]), "c4 42 83 f7 ff");
assert_eq!(hex("shlxl", &[long(RAX), long(RAX), long(RAX)]), "c4 e2 79 f7 c0");
assert_eq!(hex("sarxl", &[long(RAX), long(RAX), long(RAX)]), "c4 e2 7a f7 c0");
}
#[test]
fn the_conditions_a_compiler_never_reaches_and_the_move_that_reads_memory() {
assert_eq!(hex("cmovsq", &[quad(RAX), quad(RBX)]), "48 0f 48 d8");
assert_eq!(hex("cmovnsq", &[quad(RAX), quad(RBX)]), "48 0f 49 d8");
assert_eq!(hex("cmovoq", &[quad(RAX), quad(RBX)]), "48 0f 40 d8");
assert_eq!(hex("cmovnoq", &[quad(RAX), quad(RBX)]), "48 0f 41 d8");
assert_eq!(hex("cmovpq", &[quad(RAX), quad(RBX)]), "48 0f 4a d8");
assert_eq!(hex("cmovnpq", &[quad(RAX), quad(RBX)]), "48 0f 4b d8");
assert_eq!(hex("cmovsl", &[long(RAX), long(RBX)]), "0f 48 d8");
let at = Addr { base: Some(R8), disp: 16, ..Addr::default() };
assert_eq!(hex("cmovbq", &[Value::Mem(at), quad(RBX)]), "49 0f 42 58 10");
let plain = Addr { base: Some(RDI), ..Addr::default() };
assert_eq!(hex("cmoveq", &[Value::Mem(plain), quad(RAX)]), "48 0f 44 07");
assert_eq!(hex("cmovnsw", &[Value::Mem(plain), word(RAX)]), "66 0f 49 07");
let four = Addr { base: Some(RSI), disp: 4, ..Addr::default() };
assert_eq!(hex("cmovgl", &[Value::Mem(four), long(RDX)]), "0f 4f 56 04");
assert_eq!(hex("seto", &[byte(RAX)]), "0f 90 c0");
assert_eq!(hex("setno", &[byte(RAX)]), "0f 91 c0");
assert_eq!(hex("sets", &[byte(RAX)]), "0f 98 c0");
assert_eq!(hex("setns", &[byte(RBX)]), "0f 99 c3");
for (mnemonic, opcode) in
[("jo", 0x80), ("jno", 0x81), ("js", 0x88), ("jns", 0x89), ("jp", 0x8A), ("jnp", 0x8B)]
{
let mut out = Vec::new();
let holes = encode(mnemonic, &[Value::Dest], &mut out).expect(mnemonic);
assert_eq!(out, vec![0x0F, opcode, 0, 0, 0, 0], "{mnemonic}");
assert_eq!(holes.dest, Some(2), "{mnemonic}");
}
}
#[test]
fn the_flag_and_the_string_instructions_a_compiler_has_no_use_for() {
assert_eq!(hex("clc", &[]), "f8");
assert_eq!(hex("stc", &[]), "f9");
assert_eq!(hex("cmc", &[]), "f5");
assert_eq!(hex("movsb", &[]), "a4");
assert_eq!(hex("movsw", &[]), "66 a5");
assert_eq!(hex("movsl", &[]), "a5");
assert_eq!(hex("movsq", &[]), "48 a5");
assert_eq!(hex("rep", &[]), "f3");
assert_eq!(hex("repe", &[]), "f3");
assert_eq!(hex("repz", &[]), "f3");
assert_eq!(hex("repne", &[]), "f2");
assert_eq!(hex("repnz", &[]), "f2");
}
#[test]
fn the_vector_instructions_that_treat_a_register_as_whole_numbers() {
let from = Addr { base: Some(RSI), ..Addr::default() };
let to = Addr { base: Some(RDI), ..Addr::default() };
assert_eq!(hex("movq", &[Value::Mem(from), Value::Xmm(xmm(1))]), "f3 0f 7e 0e");
assert_eq!(hex("movq", &[Value::Xmm(xmm(0)), Value::Mem(to)]), "66 0f d6 07");
assert_eq!(hex("movdqu", &[Value::Mem(from), Value::Xmm(xmm(0))]), "f3 0f 6f 06");
assert_eq!(hex("movdqa", &[Value::Xmm(xmm(0)), Value::Mem(to)]), "66 0f 7f 07");
assert_eq!(hex("movdqa", &[Value::Xmm(xmm(1)), Value::Xmm(xmm(0))]), "66 0f 6f c1");
assert_eq!(hex("movdqu", &[Value::Xmm(xmm(9)), Value::Xmm(xmm(8))]), "f3 45 0f 6f c1");
let along =
Addr { base: Some(RSI), index: Some(RDX), scale: 8, disp: -16, ..Addr::default() };
assert_eq!(hex("movdqu", &[Value::Mem(along), Value::Xmm(xmm(7))]), "f3 0f 6f 7c d6 f0");
assert_eq!(hex("pcmpeqb", &[Value::Xmm(xmm(3)), Value::Xmm(xmm(3))]), "66 0f 74 db");
assert_eq!(hex("pcmpeqd", &[Value::Xmm(xmm(0)), Value::Xmm(xmm(1))]), "66 0f 76 c8");
assert_eq!(hex("pxor", &[Value::Xmm(xmm(7)), Value::Xmm(xmm(0))]), "66 0f ef c7");
assert_eq!(hex("por", &[Value::Xmm(xmm(1)), Value::Xmm(xmm(0))]), "66 0f eb c1");
assert_eq!(hex("pand", &[Value::Xmm(xmm(2)), Value::Xmm(xmm(5))]), "66 0f db ea");
assert_eq!(hex("pandn", &[Value::Xmm(xmm(2)), Value::Xmm(xmm(5))]), "66 0f df ea");
assert_eq!(hex("psllq", &[Value::Xmm(xmm(4)), Value::Xmm(xmm(0))]), "66 0f f3 c4");
assert_eq!(hex("psrlq", &[Value::Xmm(xmm(5)), Value::Xmm(xmm(1))]), "66 0f d3 cd");
assert_eq!(hex("psrad", &[Value::Xmm(xmm(1)), Value::Xmm(xmm(2))]), "66 0f e2 d1");
assert_eq!(hex("psllq", &[Value::Imm(3), Value::Xmm(xmm(0))]), "66 0f 73 f0 03");
assert_eq!(hex("psrlw", &[Value::Imm(1), Value::Xmm(xmm(6))]), "66 0f 71 d6 01");
assert_eq!(hex("psrldq", &[Value::Imm(8), Value::Xmm(xmm(2))]), "66 0f 73 da 08");
assert_eq!(hex("pslldq", &[Value::Imm(8), Value::Xmm(xmm(2))]), "66 0f 73 fa 08");
assert_eq!(hex("punpcklqdq", &[Value::Xmm(xmm(1)), Value::Xmm(xmm(0))]), "66 0f 6c c1");
assert_eq!(hex("punpckhqdq", &[Value::Xmm(xmm(1)), Value::Xmm(xmm(0))]), "66 0f 6d c1");
assert_eq!(hex("paddq", &[Value::Xmm(xmm(1)), Value::Xmm(xmm(0))]), "66 0f d4 c1");
assert_eq!(hex("psubb", &[Value::Xmm(xmm(1)), Value::Xmm(xmm(0))]), "66 0f f8 c1");
}
#[test]
fn the_vector_forms_gcc_writes_read_as_gas_reads_them() {
let from = Addr { base: Some(RSI), ..Addr::default() };
let to = Addr { base: Some(RDI), disp: 16, ..Addr::default() };
let x = |n| Value::Xmm(xmm(n));
assert_eq!(hex("movups", &[x(0), Value::Mem(to)]), "0f 11 47 10");
assert_eq!(hex("mulsd", &[Value::Mem(from), x(0)]), "f2 0f 59 06");
let at = Addr { base: Some(RDI), ..Addr::default() };
assert_eq!(hex("cvtsi2sdq", &[Value::Mem(at), x(0)]), "f2 48 0f 2a 07");
assert_eq!(hex("comisd", &[x(1), x(0)]), "66 0f 2f c1");
assert_eq!(hex("pshufd", &[Value::Imm(78), x(0), x(10)]), "66 44 0f 70 d0 4e");
let mut out = Vec::new();
assert!(encode("pshufd", &[Value::Imm(1000), x(1), x(0)], &mut out).is_err());
assert!(encode("shufps", &[Value::Imm(0x1_2345_6789), x(1), x(0)], &mut out).is_err());
assert_eq!(hex("pshufd", &[Value::Imm(-1), x(1), x(0)]), "66 0f 70 c1 ff");
assert_eq!(hex("punpckldq", &[x(1), x(0)]), "66 0f 62 c1");
assert_eq!(hex("xorpd", &[x(1), x(1)]), "66 0f 57 c9");
assert_eq!(hex("movhps", &[Value::Mem(from), x(1)]), "0f 16 0e");
assert_eq!(hex("movd", &[Value::Mem(from), x(0)]), "66 0f 6e 06");
assert_eq!(hex("sqrtsd", &[x(1), x(0)]), "f2 0f 51 c1");
assert_eq!(hex("cvttsd2siq", &[Value::Mem(from), quad(RAX)]), "f2 48 0f 2c 06");
}
#[test]
fn the_one_branch_with_nowhere_but_a_byte_to_say_where_it_goes() {
let mut out = Vec::new();
let holes = encode("jrcxz", &[Value::Dest], &mut out).expect("a jump on a register");
assert_eq!(out, vec![0xE3, 0x00], "the opcode and the room for the distance");
assert_eq!(holes.dest, Some(1), "the distance goes in the byte behind the opcode");
let row = encoding("jrcxz", &[Kind::Dest], 0).expect("the row it was encoded from");
assert_eq!(row.imm, ImmSize::Cb, "the row is what says how much room there is");
}
#[test]
fn a_mnemonic_with_arguments_it_does_not_take_is_refused_rather_than_encoded() {
let mut out = Vec::new();
let error = encode("ret", &[quad(RAX)], &mut out).expect_err("a return of a register");
assert_eq!(error, Error::Unwritten { mnemonic: "ret".to_owned(), args: vec![Kind::Reg] });
assert_eq!(out, Vec::<u8>::new(), "nothing is written for an instruction that is refused");
let error = encode("frobnicate", &[], &mut out).expect_err("no such instruction");
assert!(matches!(error, Error::Unwritten { .. }), "{error}");
assert_eq!(encoding("addl", &[Kind::Reg], 0), None);
}
#[test]
fn padding_is_as_long_as_asked_and_one_instruction_while_it_can_be() {
for count in 0..=25 {
let mut out = Vec::new();
nops(count, &mut out);
assert_eq!(out.len(), count, "{count} bytes of padding");
}
let mut out = Vec::new();
nops(10, &mut out);
assert_eq!(out, [0x66, 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0], "cs nopw 0(%rax,%rax,1)");
let mut out = Vec::new();
nops(3, &mut out);
assert_eq!(out, [0x0f, 0x1f, 0x00], "nopl (%rax)");
let mut out = Vec::new();
nops(11, &mut out);
assert_eq!(out, [0x66, 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0], "data16 cs nopw");
let mut out = Vec::new();
nops(13, &mut out);
assert_eq!(out[11..], [0x66, 0x90], "eleven bytes and then two");
}
fn z(number: u8) -> Value {
Value::Vector(number, Length::Zmm)
}
fn y(number: u8) -> Value {
Value::Vector(number, Length::Ymm)
}
fn x(number: u8) -> Value {
Value::Vector(number, Length::Xmm)
}
fn at(base: PhysReg, disp: i32) -> Value {
Value::Mem(Addr { base: Some(base), scale: 1, disp, ..Addr::default() })
}
#[test]
fn an_avx512_instruction_is_the_four_byte_prefix_and_then_what_a_vex_one_would_be() {
assert_eq!(hex("vmovdqu64", &[at(RDI, 0), z(16)]), "62 e1 fe 48 6f 07");
assert_eq!(hex("vmovdqu64", &[z(16), at(RAX, 0)]), "62 e1 fe 48 7f 00");
assert_eq!(hex("vmovdqu64", &[z(16), z(17)]), "62 a1 fe 48 6f c8");
assert_eq!(hex("vmovdqu64", &[z(0), z(1)]), "62 f1 fe 48 6f c8");
assert_eq!(hex("vmovdqu64", &[z(8), z(25)]), "62 41 fe 48 6f c8");
assert_eq!(hex("vmovdqu64", &[at(R12, 0), z(9)]), "62 51 fe 48 6f 0c 24");
assert_eq!(hex("vmovdqa64", &[z(17), z(18)]), "62 a1 fd 48 6f d1");
assert_eq!(hex("vmovdqa64", &[x(17), x(18)]), "62 a1 fd 08 6f d1");
assert_eq!(hex("vmovdqa64", &[Value::Xmm(xmm(1)), x(18)]), "62 e1 fd 08 6f d1");
assert_eq!(hex("vpaddq", &[z(16), z(17), z(18)]), "62 a1 f5 40 d4 d0");
assert_eq!(hex("vpaddq", &[z(29), z(30), z(31)]), "62 01 8d 40 d4 fd");
assert_eq!(hex("vpxorq", &[z(16), z(16), z(16)]), "62 a1 fd 40 ef c0");
assert_eq!(
hex("vpternlogq", &[Value::Imm(0x96), z(16), z(17), z(18)]),
"62 a3 f5 40 25 d0 96"
);
assert_eq!(hex("vpopcntq", &[z(1), z(2)]), "62 f2 fd 48 55 d1");
assert_eq!(
hex("vpclmulqdq", &[Value::Imm(0x11), z(1), z(2), z(3)]),
"62 f3 6d 48 44 d9 11"
);
assert_eq!(hex("vextracti32x4", &[Value::Imm(1), z(16), x(17)]), "62 a3 7d 48 39 c1 01");
assert_eq!(hex("vextracti32x4", &[Value::Imm(1), y(16), x(17)]), "62 a3 7d 28 39 c1 01");
assert_eq!(hex("vextracti64x4", &[Value::Imm(1), z(16), y(17)]), "62 a3 fd 48 3b c1 01");
assert_eq!(hex("vpbroadcastb", &[long(R10), z(31)]), "62 42 7d 48 7a fa");
assert_eq!(
hex("vshufi64x2", &[Value::Imm(0x4e), z(16), z(16), z(17)]),
"62 a3 fd 40 43 c8 4e"
);
assert_eq!(hex("vpshufd", &[Value::Imm(0x4e), x(16), x(17)]), "62 a1 7d 08 70 c8 4e");
assert_eq!(hex("vmovq", &[x(31), quad(R11)]), "62 41 fd 08 7e fb");
assert_eq!(hex("vmovq", &[quad(RAX), x(16)]), "62 e1 fd 08 6e c0");
}
#[test]
fn a_one_byte_displacement_under_avx512_is_counted_in_whole_accesses() {
assert_eq!(hex("vmovdqu64", &[at(RDI, 64), z(17)]), "62 e1 fe 48 6f 4f 01");
assert_eq!(hex("vmovdqu64", &[at(RSP, -128), z(31)]), "62 61 fe 48 6f 7c 24 fe");
assert_eq!(hex("vmovdqu64", &[at(RDI, 100), z(16)]), "62 e1 fe 48 6f 87 64 00 00 00");
assert_eq!(hex("vmovdqu64", &[at(RDI, 0x2000), z(16)]), "62 e1 fe 48 6f 87 00 20 00 00");
assert_eq!(hex("vmovdqu64", &[at(RAX, 16), x(17)]), "62 e1 fe 08 6f 48 01");
assert_eq!(hex("vmovdqu64", &[y(16), at(RAX, 32)]), "62 e1 fe 28 7f 40 01");
assert_eq!(hex("vpaddq", &[at(RAX, 128), z(17), z(18)]), "62 e1 f5 40 d4 50 02");
let scaled = Value::Mem(Addr {
base: Some(RSP),
index: Some(RCX),
scale: 8,
disp: 64,
..Addr::default()
});
assert_eq!(hex("vmovdqu64", &[z(20), scaled]), "62 e1 fe 48 7f 64 cc 01");
assert_eq!(hex("vbroadcasti32x4", &[at(RAX, 32), z(16)]), "62 e2 7d 48 5a 40 02");
assert_eq!(hex("vbroadcasti32x4", &[at(RAX, 16), y(16)]), "62 e2 7d 28 5a 40 01");
assert_eq!(
hex("vextracti32x4", &[Value::Imm(2), z(16), at(RAX, 32)]),
"62 e3 7d 48 39 40 02 02"
);
assert_eq!(
hex("vpternlogq", &[Value::Imm(0x96), at(RAX, 64), z(17), z(18)]),
"62 e3 f5 40 25 50 01 96"
);
}
#[test]
fn an_instruction_with_a_vex_form_is_written_that_way_unless_something_needs_evex() {
assert_eq!(hex("vpaddq", &[x(1), x(2), x(3)]), "c5 e9 d4 d9");
assert_eq!(hex("vpaddq", &[y(9), y(10), y(11)]), "c4 41 2d d4 d9");
assert_eq!(hex("vpaddq", &[at(RAX, 0), y(2), y(3)]), "c5 ed d4 18");
assert_eq!(hex("vpaddq", &[z(1), z(2), z(3)]), "62 f1 ed 48 d4 d9");
assert_eq!(hex("vpaddq", &[x(16), x(17), x(18)]), "62 a1 f5 00 d4 d0");
assert_eq!(hex("vpclmulqdq", &[Value::Imm(0), x(1), x(2), x(3)]), "c4 e3 69 44 d9 00");
assert_eq!(hex("vpclmulqdq", &[Value::Imm(0), y(1), y(2), y(3)]), "c4 e3 6d 44 d9 00");
assert_eq!(
hex("vpclmulqdq", &[Value::Imm(0), x(16), x(17), x(18)]),
"62 a3 75 00 44 d0 00"
);
assert_eq!(hex("vpshufd", &[Value::Imm(0x4e), x(1), x(2)]), "c5 f9 70 d1 4e");
assert_eq!(hex("vmovq", &[x(1), quad(RAX)]), "c4 e1 f9 7e c8");
assert_eq!(hex("vmovq", &[quad(RAX), x(1)]), "c4 e1 f9 6e c8");
assert_eq!(
hex("vpternlogq", &[Value::Imm(0x96), x(1), x(2), x(3)]),
"62 f3 ed 08 25 d9 96"
);
}
#[test]
fn a_mask_and_zeroing_go_in_the_last_byte_of_the_prefix() {
let masked = |mask: Opmask, values: &[Value]| {
let mut out = Vec::new();
encode_masked("vmovdqu8", values, mask, &mut out).expect("vmovdqu8 takes a mask");
out.iter().map(|byte| format!("{byte:02x}")).collect::<Vec<_>>().join(" ")
};
let index =
Value::Mem(Addr { base: Some(R9), index: Some(R10), scale: 1, ..Addr::default() });
assert_eq!(masked(Opmask { k: 1, zero: true }, &[at(RBX, 0), z(16)]), "62 e1 7f c9 6f 03");
assert_eq!(masked(Opmask { k: 7, zero: true }, &[index, z(30)]), "62 01 7f cf 6f 34 11");
assert_eq!(masked(Opmask { k: 1, zero: false }, &[at(RBX, 0), z(16)]), "62 e1 7f 49 6f 03");
assert_eq!(masked(Opmask::default(), &[z(16), at(RBX, 0)]), "62 e1 7f 48 7f 03");
assert_eq!(masked(Opmask { k: 2, zero: false }, &[z(16), at(RBX, 0)]), "62 e1 7f 4a 7f 03");
let mut out = Vec::new();
let error =
encode_masked("addq", &[quad(RAX), quad(RBX)], Opmask { k: 1, zero: false }, &mut out);
assert!(matches!(error, Err(Error::Mask { .. })), "{error:?}");
}
#[test]
fn a_mask_register_moves_to_and_from_a_general_purpose_one_vex_encoded() {
assert_eq!(hex("kmovq", &[quad(RAX), Value::Mask(1)]), "c4 e1 fb 92 c8");
assert_eq!(hex("kmovq", &[quad(R13), Value::Mask(7)]), "c4 c1 fb 92 fd");
assert_eq!(hex("kmovq", &[Value::Mask(1), quad(RAX)]), "c4 e1 fb 93 c1");
assert_eq!(hex("kmovq", &[Value::Mask(3), quad(R9)]), "c4 61 fb 93 cb");
}
#[test]
fn a_mask_register_is_cleared_with_kxorw() {
let k = Value::Mask;
assert_eq!(hex("kxorw", &[k(0), k(0), k(0)]), "c5 fc 47 c0");
assert_eq!(hex("kxorw", &[k(7), k(7), k(7)]), "c5 c4 47 ff");
}
#[test]
fn vxorps_reaches_the_upper_sixteen_registers_with_evex() {
assert_eq!(hex("vxorps", &[x(16), x(16), x(16)]), "62 a1 7c 00 57 c0");
assert_eq!(hex("vxorps", &[x(31), x(31), x(31)]), "62 01 04 00 57 ff");
assert_eq!(hex("vxorps", &[x(1), x(1), x(1)]), "c5 f0 57 c9");
assert_eq!(hex("vpxord", &[z(16), z(16), z(16)]), "62 a1 7d 40 ef c0");
}
#[test]
fn the_bitwise_operations_on_packed_floats_are_the_bytes_gas_writes() {
assert_eq!(hex("vxorps", &[at(RAX, 0), y(0), y(0)]), "c5 fc 57 00");
assert_eq!(hex("vxorps", &[y(1), y(2), y(3)]), "c5 ec 57 d9");
assert_eq!(hex("vxorps", &[y(9), y(13), y(0)]), "c4 c1 14 57 c1");
assert_eq!(hex("vxorpd", &[at(RCX, 32), x(4), x(5)]), "c5 d9 57 69 20");
assert_eq!(hex("vandps", &[y(1), y(2), y(3)]), "c5 ec 54 d9");
assert_eq!(hex("vandnpd", &[x(11), x(2), x(3)]), "c4 c1 69 55 db");
assert_eq!(hex("vorps", &[at(R8, 0), y(12), y(2)]), "c4 c1 1c 56 10");
assert_eq!(hex("vorpd", &[y(1), y(2), y(3)]), "c5 ed 56 d9");
assert_eq!(hex("vandpd", &[x(1), x(2), x(3)]), "c5 e9 54 d9");
assert_eq!(hex("vandnps", &[y(1), y(2), y(3)]), "c5 ec 55 d9");
}
#[test]
fn a_floating_point_move_is_evex_encoded_only_when_vex_cannot_say_it() {
assert_eq!(hex("vmovapd", &[z(0), z(13)]), "62 71 fd 48 28 e8");
assert_eq!(hex("vmovapd", &[z(13), z(0)]), "62 d1 fd 48 28 c5");
assert_eq!(hex("vmovapd", &[at(RAX, 0), z(9)]), "62 71 fd 48 28 08");
assert_eq!(hex("vmovapd", &[z(9), at(RAX, 64)]), "62 71 fd 48 29 48 01");
assert_eq!(hex("vmovapd", &[y(17), y(0)]), "62 b1 fd 28 28 c1");
assert_eq!(hex("vmovapd", &[y(13), y(0)]), "c5 7d 29 e8");
assert_eq!(hex("vmovaps", &[z(1), z(2)]), "62 f1 7c 48 28 d1");
assert_eq!(hex("vmovaps", &[y(13), y(0)]), "c5 7c 29 e8");
assert_eq!(hex("vmovaps", &[at(RCX, 0), x(3)]), "c5 f8 28 19");
assert_eq!(hex("vmovups", &[z(20), at(RDX, 0)]), "62 e1 7c 48 11 22");
assert_eq!(hex("vmovupd", &[at(RAX, 128), z(5)]), "62 f1 fd 48 10 68 02");
assert_eq!(hex("vmovupd", &[x(1), x(2)]), "c5 f9 10 d1");
}
#[test]
fn the_stores_and_shifts_raid6_writes_are_the_bytes_gas_writes() {
let to = Addr { base: Some(R8), disp: 16, ..Addr::default() };
assert_eq!(hex("movntdq", &[Value::Xmm(xmm(0)), at(RAX, 0)]), "66 0f e7 00");
assert_eq!(hex("movntdq", &[Value::Xmm(xmm(9)), Value::Mem(to)]), "66 45 0f e7 48 10");
assert_eq!(hex("vmovntdq", &[y(0), at(RAX, 0)]), "c5 fd e7 00");
assert_eq!(hex("vmovntdq", &[y(9), at(R8, 32)]), "c4 41 7d e7 48 20");
assert_eq!(hex("vmovntdq", &[x(2), at(RCX, 0)]), "c5 f9 e7 11");
assert_eq!(hex("vmovntdq", &[z(2), at(RAX, 0)]), "62 f1 7d 48 e7 10");
assert_eq!(hex("vmovntdq", &[z(17), at(RDX, 64)]), "62 e1 7d 48 e7 4a 01");
assert_eq!(hex("vmovntdq", &[y(20), at(RAX, 32)]), "62 e1 7d 28 e7 60 01");
assert_eq!(hex("vpsraw", &[Value::Imm(7), y(2), y(3)]), "c5 e5 71 e2 07");
assert_eq!(hex("vpsraw", &[Value::Imm(1), x(9), x(12)]), "c4 c1 19 71 e1 01");
assert_eq!(hex("vpsraw", &[Value::Imm(3), z(2), z(3)]), "62 f1 65 48 71 e2 03");
assert_eq!(hex("vpcmpgtb", &[z(4), z(1), Value::Mask(1)]), "62 f1 75 48 64 cc");
assert_eq!(hex("vpcmpgtb", &[z(14), z(15), Value::Mask(4)]), "62 d1 05 48 64 e6");
assert_eq!(hex("vpcmpgtb", &[z(20), z(1), Value::Mask(7)]), "62 b1 75 48 64 fc");
assert_eq!(hex("vpcmpgtb", &[at(RAX, 64), z(1), Value::Mask(2)]), "62 f1 75 48 64 50 01");
assert_eq!(hex("vpmovm2b", &[Value::Mask(1), z(5)]), "62 f2 7e 48 28 e9");
assert_eq!(hex("vpmovm2b", &[Value::Mask(4), z(15)]), "62 72 7e 48 28 fc");
assert_eq!(hex("vpmovm2b", &[Value::Mask(2), z(21)]), "62 e2 7e 48 28 ea");
assert_eq!(hex("vpmovm2b", &[Value::Mask(1), y(5)]), "62 f2 7e 28 28 e9");
assert_eq!(hex("vmovapd", &[y(0), y(13)]), "c5 7d 28 e8");
assert_eq!(hex("vmovapd", &[y(13), y(0)]), "c5 7d 29 e8");
assert_eq!(hex("vmovapd", &[at(RAX, 0), y(9)]), "c5 7d 28 08");
assert_eq!(hex("vmovapd", &[y(9), at(RAX, 32)]), "c5 7d 29 48 20");
}
#[test]
fn a_control_debug_or_segment_register_is_the_register_field_of_the_addressing_byte() {
let cr = Value::Control;
let dr = Value::Debug;
assert_eq!(hex("movq", &[cr(3), quad(R9)]), "41 0f 20 d9");
assert_eq!(hex("movq", &[quad(RAX), cr(8)]), "44 0f 22 c0");
assert_eq!(hex("movq", &[dr(7), quad(RAX)]), "0f 21 f8");
assert_eq!(hex("movq", &[quad(R10), dr(1)]), "41 0f 23 ca");
let mut out = Vec::new();
assert!(encode("movq", &[cr(16), quad(RAX)], &mut out).is_err());
let ds = Value::Seg(Segment::Ds);
let gs = Value::Seg(Segment::Gs);
assert_eq!(hex("movl", &[ds, long(RAX)]), "8c d8");
assert_eq!(hex("movw", &[ds, word(RAX)]), "66 8c d8");
assert_eq!(hex("movq", &[ds, quad(RAX)]), "48 8c d8");
assert_eq!(hex("movl", &[gs, long(R8)]), "41 8c e8");
assert_eq!(hex("movw", &[word(RAX), Value::Seg(Segment::Es)]), "8e c0");
let at = Value::Mem(Addr { base: Some(RAX), scale: 1, ..Addr::default() });
assert_eq!(hex("mov", &[at, ds]), "8e 18");
assert_eq!(hex("mov", &[ds, at]), "8c 18");
assert_eq!(hex("pushq %fs", &[]), "0f a0");
assert_eq!(hex("popq %gs", &[]), "0f a9");
}
#[test]
fn every_segment_override_is_its_own_prefix() {
for (segment, prefix) in [
(Segment::Es, "26"),
(Segment::Cs, "2e"),
(Segment::Ss, "36"),
(Segment::Ds, "3e"),
(Segment::Fs, "64"),
(Segment::Gs, "65"),
] {
let at = Value::Mem(Addr {
segment: Some(segment),
base: Some(RAX),
scale: 1,
..Addr::default()
});
assert_eq!(hex("movl", &[at, long(RAX)]), format!("{prefix} 8b 00"));
}
}
#[test]
fn the_system_instructions_are_the_manuals_bytes() {
assert_eq!(hex("swapgs", &[]), "0f 01 f8");
assert_eq!(hex("sysretq", &[]), "48 0f 07");
assert_eq!(hex("iretq", &[]), "48 cf");
assert_eq!(hex("wrmsrns", &[]), "0f 01 c6");
assert_eq!(hex("eretu", &[]), "f3 0f 01 ca");
assert_eq!(hex("tdcall", &[]), "66 0f 01 cc");
assert_eq!(hex("int", &[Value::Imm(0x80)]), "cd 80");
assert_eq!(hex("lretq", &[Value::Imm(8)]), "48 ca 08 00");
let at = Value::Mem(Addr { base: Some(RDI), scale: 1, ..Addr::default() });
assert_eq!(hex("xsaves64", &[at]), "48 0f c7 2f");
assert_eq!(hex("wrussq", &[quad(RAX), at]), "66 48 0f 38 f5 07");
assert_eq!(hex("rdfsbaseq", &[quad(RAX)]), "f3 48 0f ae c0");
assert_eq!(hex("inw", &[word(RDX), word(RAX)]), "66 ed");
assert_eq!(hex("outb", &[byte(RAX), Value::Imm(0x80)]), "e6 80");
assert_eq!(hex("rep insw", &[]), "66 f3 6d");
}
#[test]
fn a_register_past_fifteen_is_refused_by_a_row_that_cannot_name_it() {
let mut out = Vec::new();
let error = encode("addss", &[x(16), Value::Xmm(xmm(1))], &mut out);
assert!(matches!(error, Err(Error::Argument { .. })), "{error:?}");
}
fn hex32(mnemonic: &str, values: &[Value]) -> String {
let mut out = Vec::new();
encode_in(Mode::Bits32, mnemonic, values, &mut out)
.unwrap_or_else(|error| panic!("{mnemonic} {values:?}: {error}"));
out.iter().map(|byte| format!("{byte:02x}")).collect::<Vec<_>>().join(" ")
}
#[test]
fn an_i386_instruction_is_the_bytes_an_i386_assembler_writes() {
let mem = |base, index, scale, disp| {
Value::Mem(Addr { base, index, scale, disp, ..Addr::default() })
};
let absolute = mem(None, None, 1, 0x1234);
let indexed = mem(None, Some(RAX), 4, 0x1234);
let sum = mem(Some(RBX), Some(RSI), 2, 4);
let wide = mem(Some(RBX), Some(RCX), 8, 0x40);
let tls = Value::Mem(Addr { disp: 0x14, segment: Some(Segment::Gs), ..Addr::default() });
let table: [(&str, Vec<Value>, &str); 44] = [
("incl", vec![long(RAX)], "40"), ("decl", vec![long(RDI)], "4f"), ("incw", vec![word(RCX)], "66 41"), ("decw", vec![word(RDX)], "66 4a"), ("incb", vec![byte(RAX)], "fe c0"), ("incl", vec![at(RAX, 0)], "ff 00"), ("decl", vec![at(RSI, 4)], "ff 4e 04"), ("pushl", vec![long(RBP)], "55"), ("popl", vec![long(RBP)], "5d"), ("pushl", vec![long(RDI)], "57"), ("pushl", vec![Value::Imm(1)], "6a 01"), ("pushl", vec![Value::Imm(0x12345)], "68 45 23 01 00"), ("pushl", vec![at(RBP, 8)], "ff 75 08"), ("popl", vec![at(RAX, 0)], "8f 00"), ("pushfl", vec![], "9c"), ("popfl", vec![], "9d"), ("movl", vec![long(RSP), long(RBP)], "89 e5"), ("movl", vec![at(RBP, 8), long(RAX)], "8b 45 08"), ("movl", vec![absolute, long(RCX)], "8b 0d 34 12 00 00"), ("movl", vec![long(RDX), indexed], "89 14 85 34 12 00 00"), ("movl", vec![at(RSP, 0), long(RAX)], "8b 04 24"), ("movl", vec![long(RBX), at(RBP, -4)], "89 5d fc"), ("leal", vec![sum, long(RDI)], "8d 7c 73 04"), ("addl", vec![Value::Imm(1000), long(RBX)], "81 c3 e8 03 00 00"), ("subl", vec![Value::Imm(16), long(RSP)], "83 ec 10"), ("movb", vec![Value::High(RAX), byte(RBX)], "88 e3"), ("movb", vec![byte(RDX), Value::High(RBX)], "88 d7"), ("movzbl", vec![byte(RBX), long(RAX)], "0f b6 c3"), ("movl", vec![tls, long(RCX)], "65 8b 0d 14 00 00 00"), ("movsd", vec![at(RSP, 8), Value::Xmm(xmm(7))], "f2 0f 10 7c 24 08"), ("addsd", vec![Value::Xmm(xmm(1)), Value::Xmm(xmm(0))], "f2 0f 58 c1"), ("cvtsi2sdl", vec![long(RAX), Value::Xmm(xmm(0))], "f2 0f 2a c0"), ("call", vec![long(RAX)], "ff d0"), ("call", vec![at(RBX, 4)], "ff 53 04"), ("ret", vec![], "c3"), ("leave", vec![], "c9"), ("cltd", vec![], "99"), ("bswapl", vec![long(RCX)], "0f c9"), ("fldl", vec![at(RSP, 8)], "dd 44 24 08"), ("imull", vec![Value::Imm(3), long(RCX), long(RDX)], "6b d1 03"), ("shldl", vec![Value::Imm(5), long(RSI), long(RDI)], "0f a4 f7 05"), ("xorl", vec![long(RAX), long(RAX)], "31 c0"), ("cmpl", vec![Value::Imm(1), at(RBP, 0)], "83 7d 00 01"), ("movl", vec![Value::Imm(0x1234_5678), wide], "c7 44 cb 40 78 56 34 12"), ];
for (mnemonic, values, bytes) in table {
assert_eq!(hex32(mnemonic, &values), bytes, "{mnemonic} {values:?}");
}
}
#[test]
fn an_i386_absolute_address_the_linker_fills_in_leaves_its_four_bytes_open() {
let mut out = Vec::new();
let named = Addr { linked: true, ..Addr::default() };
let holes = encode_in(Mode::Bits32, "movl", &[Value::Mem(named), long(RCX)], &mut out)
.expect("an absolute load");
assert_eq!(out, [0x8b, 0x0d, 0, 0, 0, 0]);
assert_eq!(holes, Holes { disp: Some(2), ..Holes::default() });
}
#[test]
fn what_i386_has_no_way_to_write_is_refused_rather_than_written_as_something_else() {
let refused = |mnemonic: &str, values: &[Value]| {
let mut out = Vec::new();
let error = encode_in(Mode::Bits32, mnemonic, values, &mut out)
.expect_err("an instruction i386 cannot write");
assert!(out.is_empty(), "{mnemonic} wrote {out:02x?} before it was refused");
error
};
let register =
|mnemonic: &str, number| Error::Register { mnemonic: mnemonic.into(), number };
let wide = |mnemonic: &str| Error::Wide { mnemonic: mnemonic.into() };
assert_eq!(refused("addl", &[long(R8), long(RAX)]), register("addl", 8));
assert_eq!(refused("addl", &[long(RAX), long(R15)]), register("addl", 15));
assert_eq!(refused("movb", &[byte(RSI), byte(RAX)]), register("movb", 6));
assert_eq!(refused("movl", &[at(R9, 0), long(RAX)]), register("movl", 9));
let index =
Value::Mem(Addr { base: Some(RAX), index: Some(R10), scale: 1, ..Addr::default() });
assert_eq!(refused("movl", &[index, long(RAX)]), register("movl", 10));
let sse = [Value::Xmm(xmm(8)), Value::Xmm(xmm(0))];
assert_eq!(refused("addsd", &sse), register("addsd", 8));
assert_eq!(refused("addq", &[quad(RAX), quad(RBX)]), wide("addq"));
assert_eq!(refused("cltq", &[]), wide("cltq"));
assert_eq!(refused("movabsq", &[Value::Imm(1 << 40), quad(RAX)]), wide("movabsq"));
assert_eq!(refused("pushq", &[quad(RBP)]), wide("pushq"));
assert_eq!(refused("popfq", &[]), wide("popfq"));
let rip = Value::Mem(Addr { rip: true, ..Addr::default() });
assert_eq!(refused("movl", &[rip, long(RAX)]), Error::Relative { mnemonic: "movl".into() });
}
#[test]
fn a_sixty_four_bit_instruction_is_the_same_bytes_it_was_before_there_were_two_modes() {
assert_eq!(hex("incl", &[long(RAX)]), "ff c0");
assert_eq!(hex("decw", &[word(RDX)]), "66 ff ca");
assert_eq!(hex("pushq", &[quad(RBP)]), "55");
let absolute = Value::Mem(Addr { disp: 0x1234, ..Addr::default() });
assert_eq!(hex("movl", &[absolute, long(RCX)]), "8b 0c 25 34 12 00 00");
let mut out = Vec::new();
let error = encode("pushl", &[long(RBP)], &mut out);
assert!(matches!(error, Err(Error::Unwritten { .. })), "{error:?}");
}
#[test]
fn a_shared_row_naming_only_what_i386_has_is_the_same_bytes_in_both_modes() {
let value = |kind: Kind| match kind {
Kind::Reg => long(RCX),
Kind::Vec => Value::Xmm(xmm(2)),
Kind::Mem => at(RBX, 8),
Kind::Imm => Value::Imm(1),
Kind::Dest => Value::Dest,
Kind::Mask => Value::Mask(1),
Kind::Stack => Value::Stack,
Kind::Control => Value::Control(0),
Kind::Debug => Value::Debug(0),
Kind::Seg => Value::Seg(Segment::Es),
};
let mut compared = 0;
for row in ENCODINGS {
let values: Vec<Value> = row.args.iter().map(|&kind| value(kind)).collect();
let chosen = encoding_in(Mode::Bits32, row.mnemonic, row.args, 1);
if !chosen.is_some_and(|chosen| {
std::ptr::eq(chosen, encoding(row.mnemonic, row.args, 1).unwrap())
}) {
continue;
}
let (mut long_mode, mut legacy) = (Vec::new(), Vec::new());
let Ok(holes) = encode_in(Mode::Bits32, row.mnemonic, &values, &mut legacy) else {
continue;
};
let same = encode(row.mnemonic, &values, &mut long_mode).expect("both modes encode it");
assert_eq!(legacy, long_mode, "{} {:?}", row.mnemonic, row.args);
assert_eq!(holes, same);
compared += 1;
}
assert!(compared > 500, "only {compared} rows compared");
}
#[test]
fn a_byte_from_0x40_to_0x4f_is_a_prefix_in_one_mode_and_an_instruction_in_the_other() {
assert_eq!(Mode::Bits64.rex(0x48), Some(0x8));
assert_eq!(Mode::Bits64.rex(0x41), Some(0x1));
assert_eq!(Mode::Bits64.rex(0x8b), None);
assert_eq!(Mode::Bits32.rex(0x48), None);
assert_eq!(Mode::Bits32.counted(0x40), Some(("incl", RAX)));
assert_eq!(Mode::Bits32.counted(0x47), Some(("incl", RDI)));
assert_eq!(Mode::Bits32.counted(0x48), Some(("decl", RAX)));
assert_eq!(Mode::Bits32.counted(0x4f), Some(("decl", RDI)));
assert_eq!(Mode::Bits32.counted(0x50), None);
assert_eq!(Mode::Bits64.counted(0x40), None);
for (mnemonic, reg) in [("incl", RBX), ("decl", RSI)] {
let mut out = Vec::new();
encode_in(Mode::Bits32, mnemonic, &[long(reg)], &mut out).expect("a one byte form");
assert_eq!(Mode::Bits32.counted(out[0]), Some((mnemonic, reg)));
}
}
}