extern crate yaxpeax_arch; use core::fmt; use yaxpeax_arch::{Colorize, ShowContextual, NoColors, YaxColors}; use yaxpeax_arch::display::*; use crate::long_mode::{RegSpec, Opcode, Operand, InstDecoder, Instruction, Segment, PrefixRex, OperandSpec}; impl fmt::Display for InstDecoder { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self == &InstDecoder::default() { return write!(f, ""); } else if self == &InstDecoder::minimal() { return write!(f, ""); } if self.sse3() { write!(f, "sse3 ")? } if self.ssse3() { write!(f, "ssse3 ")? } if self.monitor() { write!(f, "monitor ")? } if self.vmx() { write!(f, "vmx ")? } if self.fma3() { write!(f, "fma3 ")? } if self.cmpxchg16b() { write!(f, "cmpxchg16b ")? } if self.sse4_1() { write!(f, "sse4_1 ")? } if self.sse4_2() { write!(f, "sse4_2 ")? } if self.movbe() { write!(f, "movbe ")? } if self.popcnt() { write!(f, "popcnt ")? } if self.aesni() { write!(f, "aesni ")? } if self.xsave() { write!(f, "xsave ")? } if self.rdrand() { write!(f, "rdrand ")? } if self.sgx() { write!(f, "sgx ")? } if self.bmi1() { write!(f, "bmi1 ")? } if self.avx2() { write!(f, "avx2 ")? } if self.bmi2() { write!(f, "bmi2 ")? } if self.invpcid() { write!(f, "invpcid ")? } if self.mpx() { write!(f, "mpx ")? } if self.avx512_f() { write!(f, "avx512_f ")? } if self.avx512_dq() { write!(f, "avx512_dq ")? } if self.rdseed() { write!(f, "rdseed ")? } if self.adx() { write!(f, "adx ")? } if self.avx512_fma() { write!(f, "avx512_fma ")? } if self.pcommit() { write!(f, "pcommit ")? } if self.clflushopt() { write!(f, "clflushopt ")? } if self.clwb() { write!(f, "clwb ")? } if self.avx512_pf() { write!(f, "avx512_pf ")? } if self.avx512_er() { write!(f, "avx512_er ")? } if self.avx512_cd() { write!(f, "avx512_cd ")? } if self.sha() { write!(f, "sha ")? } if self.avx512_bw() { write!(f, "avx512_bw ")? } if self.avx512_vl() { write!(f, "avx512_vl ")? } if self.prefetchwt1() { write!(f, "prefetchwt1 ")? } if self.avx512_vbmi() { write!(f, "avx512_vbmi ")? } if self.avx512_vbmi2() { write!(f, "avx512_vbmi2 ")? } if self.gfni() { write!(f, "gfni ")? } if self.vaes() { write!(f, "vaes ")? } if self.pclmulqdq() { write!(f, "pclmulqdq ")? } if self.avx_vnni() { write!(f, "avx_vnni ")? } if self.avx512_bitalg() { write!(f, "avx512_bitalg ")? } if self.avx512_vpopcntdq() { write!(f, "avx512_vpopcntdq ")? } if self.avx512_4vnniw() { write!(f, "avx512_4vnniw ")? } if self.avx512_4fmaps() { write!(f, "avx512_4fmaps ")? } if self.cx8() { write!(f, "cx8 ")? } if self.syscall() { write!(f, "syscall ")? } if self.rdtscp() { write!(f, "rdtscp ")? } if self.abm() { write!(f, "abm ")? } if self.sse4a() { write!(f, "sse4a ")? } if self._3dnowprefetch() { write!(f, "_3dnowprefetch ")? } if self.xop() { write!(f, "xop ")? } if self.skinit() { write!(f, "skinit ")? } if self.tbm() { write!(f, "tbm ")? } if self.intel_quirks() { write!(f, "intel_quirks ")? } if self.amd_quirks() { write!(f, "amd_quirks ")? } if self.avx() { write!(f, "avx ")? } Ok(()) } } impl fmt::Display for PrefixRex { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.present() { write!(f, "rex:{}{}{}{}", if self.w() { "w" } else { "-" }, if self.r() { "r" } else { "-" }, if self.x() { "x" } else { "-" }, if self.b() { "b" } else { "-" }, ) } else { write!(f, "rex:none") } } } impl fmt::Display for Segment { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Segment::CS => write!(f, "cs"), Segment::DS => write!(f, "ds"), Segment::ES => write!(f, "es"), Segment::FS => write!(f, "fs"), Segment::GS => write!(f, "gs"), Segment::SS => write!(f, "ss"), } } } // register names are grouped by indices scaled by 16. // xmm, ymm, zmm all get two indices. const REG_NAMES: &[&'static str] = &[ "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d", "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w", "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", "", "", "", "", "", "", "", "", "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b", "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15", "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", "dr8", "dr9", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15", "es", "cs", "ss", "ds", "fs", "gs", "", "", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31", "st(0)", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)", "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7", "eip", "k1", "k2", "k3", "k4", "k5", "k6", "k7", "rip", "k1", "k2", "k3", "k4", "k5", "k6", "k7", "eflags", "k1", "k2", "k3", "k4", "k5", "k6", "k7", "rflags", "k1", "k2", "k3", "k4", "k5", "k6", "k7", ]; pub(crate) fn regspec_label(spec: &RegSpec) -> &'static str { unsafe { REG_NAMES.get_unchecked((spec.num as u16 + ((spec.bank as u16) << 3)) as usize) } } impl fmt::Display for RegSpec { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(regspec_label(self)) } } impl fmt::Display for Operand { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { self.colorize(&NoColors, fmt) } } impl Colorize for Operand { fn colorize(&self, colors: &Y, f: &mut T) -> fmt::Result { match self { &Operand::ImmediateU8(imm) => { write!(f, "{}", colors.number(u8_hex(imm))) } &Operand::ImmediateI8(imm) => { write!(f, "{}", colors.number(signed_i8_hex(imm))) }, &Operand::ImmediateU16(imm) => { write!(f, "{}", colors.number(u16_hex(imm))) } &Operand::ImmediateI16(imm) => { write!(f, "{}", colors.number(signed_i16_hex(imm))) }, &Operand::ImmediateU32(imm) => { write!(f, "{}", colors.number(u32_hex(imm))) } &Operand::ImmediateI32(imm) => { write!(f, "{}", colors.number(signed_i32_hex(imm))) }, &Operand::ImmediateU64(imm) => { write!(f, "{}", colors.number(u64_hex(imm))) } &Operand::ImmediateI64(imm) => { write!(f, "{}", colors.number(signed_i64_hex(imm))) }, &Operand::Register(ref spec) => { f.write_str(regspec_label(spec)) } &Operand::DisplacementU32(imm) => { write!(f, "[{}]", colors.address(u32_hex(imm))) } &Operand::DisplacementU64(imm) => { write!(f, "[{}]", colors.address(u64_hex(imm))) } &Operand::RegDisp(ref spec, disp) => { write!(f, "[{} ", regspec_label(spec))?; format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?; write!(f, "]") }, &Operand::RegDeref(ref spec) => { f.write_str("[")?; f.write_str(regspec_label(spec))?; f.write_str("]") }, &Operand::RegScale(ref spec, scale) => { write!(f, "[{} * {}]", regspec_label(spec), colors.number(scale) ) }, &Operand::RegScaleDisp(ref spec, scale, disp) => { write!(f, "[{} * {} ", regspec_label(spec), colors.number(scale), )?; format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?; write!(f, "]") }, &Operand::RegIndexBase(ref base, ref index) => { f.write_str("[")?; f.write_str(regspec_label(base))?; f.write_str(" + ")?; f.write_str(regspec_label(index))?; f.write_str("]") } &Operand::RegIndexBaseDisp(ref base, ref index, disp) => { write!(f, "[{} + {} ", regspec_label(base), regspec_label(index), )?; format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?; write!(f, "]") }, &Operand::RegIndexBaseScale(ref base, ref index, scale) => { write!(f, "[{} + {} * {}]", regspec_label(base), regspec_label(index), colors.number(scale) ) } &Operand::RegIndexBaseScaleDisp(ref base, ref index, scale, disp) => { write!(f, "[{} + {} * {} ", regspec_label(base), regspec_label(index), colors.number(scale), )?; format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?; write!(f, "]") }, &Operand::Nothing => { Ok(()) }, } } } impl fmt::Display for Opcode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(self.name()) } } const MNEMONICS: &[&'static str] = &[ "invalid", "add", "or", "adc", "sbb", "and", "xor", "sub", "cmp", "xadd", "bt", "bts", "btc", "btr", "bsf", "bsr", "tzcnt", "movss", "addss", "subss", "mulss", "divss", "minss", "maxss", "sqrtss", "movsd", "sqrtsd", "addsd", "subsd", "mulsd", "divsd", "minsd", "maxsd", "movsldup", "movshdup", "movddup", "haddps", "hsubps", "addsubpd", "addsubps", "cvtsi2ss", "cvtsi2sd", "cvttsd2si", "cvttps2dq", "cvtpd2dq", "cvtpd2ps", "cvtps2dq", "cvtsd2si", "cvtsd2ss", "cvttss2si", "cvtss2si", "cvtss2sd", "cvtdq2pd", "lddqu", "movsx", "movsx", "movzx", "movzx", "movsx", "movsxd", "sar", "sal", "shr", "shrd", "shl", "rcr", "rcl", "ror", "rol", "inc", "dec", "hlt", "call", "callf", "jmp", "jmpf", "push", "pop", "lea", "nop", "prefetchnta", "prefetch0", "prefetch1", "prefetch2", "xchg", "popf", "int", "into", "iret", "iretd", "iretq", "retf", "enter", "leave", "mov", "ret", "pushf", "wait", "cbw", "cwde", "cdqe", "cwd", "cdq", "cqo", "lods", "stos", "lahf", "sahf", "cmps", "scas", "movs", "test", "ins", "in", "outs", "out", "imul", "jo", "jno", "jb", "jnb", "jz", "jnz", "ja", "jna", "js", "jns", "jp", "jnp", "jl", "jge", "jle", "jg", "cmova", "cmovb", "cmovg", "cmovge", "cmovl", "cmovle", "cmovna", "cmovnb", "cmovno", "cmovnp", "cmovns", "cmovnz", "cmovo", "cmovp", "cmovs", "cmovz", "div", "idiv", "mul", "neg", "not", "cmpxchg", "seto", "setno", "setb", "setae", "setz", "setnz", "setbe", "seta", "sets", "setns", "setp", "setnp", "setl", "setge", "setle", "setg", "cpuid", "ud0", "ud1", "ud2", "wbinvd", "invd", "sysret", "clts", "syscall", "lsl", "lar", "sgdt", "sidt", "lgdt", "lidt", "smsw", "lmsw", "swapgs", "rdtscp", "invlpg", "fxsave", "fxrstor", "ldmxcsr", "stmxcsr", "xsave", "xrstor", "xsaveopt", "lfence", "mfence", "sfence", "clflush", "clflushopt", "clwb", "wrmsr", "rdtsc", "rdmsr", "rdpmc", "sldt", "str", "lldt", "ltr", "verr", "verw", "cmc", "clc", "stc", "cli", "sti", "cld", "std", "jmpe", "popcnt", "movdqu", "movdqa", "movq", "cmpss", "cmpsd", "unpcklps", "unpcklpd", "unpckhps", "unpckhpd", "pshufhw", "pshuflw", "movups", "movq2dq", "movdq2q", "rsqrtss", "rcpss", "andn", "bextr", "blsi", "blsmsk", "blsr", "vmclear", "vmxon", "vmcall", "vmlaunch", "vmresume", "vmxoff", "monitor", "mwait", "monitorx", "mwaitx", "clac", "stac", "encls", "enclv", "xgetbv", "xsetbv", "vmfunc", "xabort", "xbegin", "xend", "xtest", "enclu", "rdpkru", "wrpkru", "rdpru", "clzero", "rdseed", "rdrand", "addps", "addpd", "andnps", "andnpd", "andps", "andpd", "bswap", "cmppd", "cmpps", "comisd", "comiss", "cvtdq2ps", "cvtpi2ps", "cvtpi2pd", "cvtps2pd", "cvtps2pi", "cvtpd2pi", "cvttps2pi", "cvttpd2pi", "cvttpd2dq", "divps", "divpd", "emms", "getsec", "lfs", "lgs", "lss", "maskmovq", "maskmovdqu", "maxps", "maxpd", "minps", "minpd", "movaps", "movapd", "movd", "movlps", "movlpd", "movhps", "movhpd", "movlhps", "movhlps", "movupd", "movmskps", "movmskpd", "movnti", "movntps", "movntpd", "extrq", "insertq", "movntss", "movntsd", "movntq", "movntdq", "mulps", "mulpd", "orps", "orpd", "packssdw", "packsswb", "packuswb", "paddb", "paddd", "paddq", "paddsb", "paddsw", "paddusb", "paddusw", "paddw", "pand", "pandn", "pavgb", "pavgw", "pcmpeqb", "pcmpeqd", "pcmpeqw", "pcmpgtb", "pcmpgtd", "pcmpgtw", "pinsrw", "pmaddwd", "pmaxsw", "pmaxub", "pminsw", "pminub", "pmovmskb", "pmulhuw", "pmulhw", "pmullw", "pmuludq", "por", "psadbw", "pshufw", "pshufd", "pslld", "pslldq", "psllq", "psllw", "psrad", "psraw", "psrld", "psrldq", "psrlq", "psrlw", "psubb", "psubd", "psubq", "psubsb", "psubsw", "psubusb", "psubusw", "psubw", "punpckhbw", "punpckhdq", "punpckhwd", "punpcklbw", "punpckldq", "punpcklwd", "punpcklqdq", "punpckhqdq", "pxor", "rcpps", "rsm", "rsqrtps", "shld", "shufpd", "shufps", "slhd", "sqrtps", "sqrtpd", "subps", "subpd", "sysenter", "sysexit", "ucomisd", "ucomiss", "vmread", "vmwrite", "xorps", "xorpd", "vmovddup", "vpshuflw", "vhaddps", "vhsubps", "vaddsubps", "vcvtpd2dq", "vlddqu", "vcomisd", "vcomiss", "vucomisd", "vucomiss", "vaddpd", "vaddps", "vaddsd", "vaddss", "vaddsubpd", "vaesdec", "vaesdeclast", "vaesenc", "vaesenclast", "vaesimc", "vaeskeygenassist", "vblendpd", "vblendps", "vblendvpd", "vblendvps", "vbroadcastf128", "vbroadcasti128", "vbroadcastsd", "vbroadcastss", "vcmpsd", "vcmpss", "vcmppd", "vcmpps", "vcvtdq2pd", "vcvtdq2ps", "vcvtpd2ps", "vcvtph2ps", "vcvtps2dq", "vcvtps2pd", "vcvtss2sd", "vcvtsi2ss", "vcvtsi2sd", "vcvtsd2si", "vcvtsd2ss", "vcvtps2ph", "vcvtss2si", "vcvttpd2dq", "vcvttps2dq", "vcvttss2si", "vcvttsd2si", "vdivpd", "vdivps", "vdivsd", "vdivss", "vdppd", "vdpps", "vextractf128", "vextracti128", "vextractps", "vfmadd132pd", "vfmadd132ps", "vfmadd132sd", "vfmadd132ss", "vfmadd213pd", "vfmadd213ps", "vfmadd213sd", "vfmadd213ss", "vfmadd231pd", "vfmadd231ps", "vfmadd231sd", "vfmadd231ss", "vfmaddsub132pd", "vfmaddsub132ps", "vfmaddsub213pd", "vfmaddsub213ps", "vfmaddsub231pd", "vfmaddsub231ps", "vfmsub132pd", "vfmsub132ps", "vfmsub132sd", "vfmsub132ss", "vfmsub213pd", "vfmsub213ps", "vfmsub213sd", "vfmsub213ss", "vfmsub231pd", "vfmsub231ps", "vfmsub231sd", "vfmsub231ss", "vfmsubadd132pd", "vfmsubadd132ps", "vfmsubadd213pd", "vfmsubadd213ps", "vfmsubadd231pd", "vfmsubadd231ps", "vfnmadd132pd", "vfnmadd132ps", "vfnmadd132sd", "vfnmadd132ss", "vfnmadd213pd", "vfnmadd213ps", "vfnmadd213sd", "vfnmadd213ss", "vfnmadd231pd", "vfnmadd231ps", "vfnmadd231sd", "vfnmadd231ss", "vfnmsub132pd", "vfnmsub132ps", "vfnmsub132sd", "vfnmsub132ss", "vfnmsub213pd", "vfnmsub213ps", "vfnmsub213sd", "vfnmsub213ss", "vfnmsub231pd", "vfnmsub231ps", "vfnmsub231sd", "vfnmsub231ss", "vgatherdpd", "vgatherdps", "vgatherqpd", "vgatherqps", "vhaddpd", "vhsubpd", "vinsertf128", "vinserti128", "vinsertps", "vmaskmovdqu", "vmaskmovpd", "vmaskmovps", "vmaxpd", "vmaxps", "vmaxsd", "vmaxss", "vminpd", "vminps", "vminsd", "vminss", "vmovapd", "vmovaps", "vmovd", "vmovdqa", "vmovdqu", "vmovhlps", "vmovhpd", "vmovhps", "vmovlhps", "vmovlpd", "vmovlps", "vmovmskpd", "vmovmskps", "vmovntdq", "vmovntdqa", "vmovntpd", "vmovntps", "vmovq", "vmovss", "vmovsd", "vmovshdup", "vmovsldup", "vmovupd", "vmovups", "vmpsadbw", "vmulpd", "vmulps", "vmulsd", "vmulss", "vpabsb", "vpabsd", "vpabsw", "vpackssdw", "vpacksswb", "vpackuswb", "vpaddb", "vpaddd", "vpaddq", "vpaddsb", "vpaddsw", "vpaddusb", "vpaddusw", "vpaddw", "vpalignr", "vandps", "vandpd", "vorps", "vorpd", "vandnps", "vandnpd", "vpand", "vpandn", "vpavgb", "vpavgw", "vpblendd", "vpblendvb", "vpblendw", "vpbroadcastb", "vpbroadcastd", "vpbroadcastq", "vpbroadcastw", "vpclmulqdq", "vpcmpeqb", "vpcmpeqd", "vpcmpeqq", "vpcmpeqw", "vpcmpgtb", "vpcmpgtd", "vpcmpgtq", "vpcmpgtw", "vpcmpistri", "vpcmpistrm", "vperm2f128", "vperm2i128", "vpermd", "vpermilpd", "vpermilps", "vpermpd", "vpermps", "vpermq", "vpextrb", "vpextrd", "vpextrq", "vpextrw", "vpgatherdd", "vpgatherdq", "vpgatherqd", "vpgatherqq", "vphaddd", "vphaddsw", "vphaddw", "vphaddubsw", "vphminposuw", "vphsubd", "vphsubsw", "vphsubw", "vpinsrb", "vpinsrd", "vpinsrq", "vpinsrw", "vpmaddwd", "vpmaskmovd", "vpmaskmovq", "vpmaxsb", "vpmaxsd", "vpmaxsw", "vpmaxub", "vpmaxuw", "vpmaxud", "vpminsw", "vpminsd", "vpminud", "vpmovmskb", "vpmovsxbd", "vpmovsxbq", "vpmovsxbw", "vpmovsxdq", "vpmovsxwd", "vpmovsxwq", "vpmovzxbd", "vpmovzxbq", "vpmovzxbw", "vpmovzxdq", "vpmovzxwd", "vpmovzxwq", "vpmuldq", "vpmulhrsw", "vpmulhuw", "vpmulhw", "vpmulld", "vpmullw", "vpmuludq", "vpor", "vpsadbw", "vpshufb", "vpshufd", "vpsignb", "vpsignd", "vpsignw", "vpslld", "vpslldq", "vpsllq", "vpsllvd", "vpsllvq", "vpsllw", "vpsrad", "vpsravd", "vpsraw", "vpsrld", "vpsrldq", "vpsrlq", "vpsrlvd", "vpsrlvq", "vpsrlw", "vpsubb", "vpsubd", "vpsubq", "vpsubsb", "vpsubsw", "vpsubusb", "vpsubusw", "vpsubw", "vptest", "vpunpckhbw", "vpunpckhdq", "vpunpckhqdq", "vpunpckhwd", "vpunpcklbw", "vpunpckldq", "vpunpcklqdq", "vpunpcklwd", "vpxor", "vrcpps", "vroundpd", "vroundps", "vroundsd", "vroundss", "vrsqrtps", "vrsqrtss", "vrcpss", "vshufpd", "vshufps", "vsqrtpd", "vsqrtps", "vsqrtss", "vsqrtsd", "vsubpd", "vsubps", "vsubsd", "vsubss", "vtestpd", "vtestps", "vunpckhpd", "vunpckhps", "vunpcklpd", "vunpcklps", "vxorpd", "vxorps", "vzeroupper", "pclmulqdq", "aeskeygenassist", "aesimc", "aesenc", "aesenclast", "aesdec", "aesdeclast", "pcmpgtq", "pcmpistrm", "pcmpistri", "pcmpestri", "packusdw", "pcmpestrm", "pcmpeqq", "ptest", "phminposuw", "dpps", "dppd", "mpsadbw", "pmovzxdq", "pmovsxdq", "pmovzxbd", "pmovsxbd", "pmovzxwq", "pmovsxwq", "pmovzxbq", "pmovsxbq", "pmovsxwd", "pmovzxwd", "pextrq", "pextrd", "pextrw", "pextrb", "pmovsxbw", "pmovzxbw", "pinsrq", "pinsrd", "pinsrb", "extractps", "insertps", "roundss", "roundsd", "roundps", "roundpd", "pmaxsb", "pmaxsd", "pmaxuw", "pmaxud", "pminsd", "pminsb", "pminud", "pminuw", "blendw", "pblendvb", "pblendw", "blendvps", "blendvpd", "blendps", "blendpd", "pmuldq", "movntdqa", "pmulld", "palignr", "psignw", "psignd", "psignb", "pshufb", "pmulhrsw", "pmaddubsw", "pabsd", "pabsw", "pabsb", "phsubsw", "phsubw", "phsubd", "phaddd", "phaddsw", "phaddw", "hsubpd", "haddpd", "sha1rnds4", "sha1nexte", "sha1msg1", "sha1msg2", "sha256rnds2", "sha256msg1", "sha256msg2", "lzcnt", "clgi", "stgi", "skinit", "vmload", "vmmcall", "vmsave", "vmrun", "invlpga", "invlpgb", "tlbsync", "movbe", "adcx", "adox", "prefetchw", "rdpid", "cmpxchg8b", "cmpxchg16b", "vmptrld", "vmptrst", "bzhi", "mulx", "shlx", "shrx", "sarx", "pdep", "pext", "rorx", "xrstors", "xrstors64", "xsavec", "xsavec64", "xsaves", "xsaves64", "rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase", "crc32", "salc", "xlat", "f2xm1", "fabs", "fadd", "faddp", "fbld", "fbstp", "fchs", "fcmovb", "fcmovbe", "fcmove", "fcmovnb", "fcmovnbe", "fcmovne", "fcmovnu", "fcmovu", "fcom", "fcomi", "fcomip", "fcomp", "fcompp", "fcos", "fdecstp", "fdisi8087_nop", "fdiv", "fdivp", "fdivr", "fdivrp", "feni8087_nop", "ffree", "ffreep", "fiadd", "ficom", "ficomp", "fidiv", "fidivr", "fild", "fimul", "fincstp", "fist", "fistp", "fisttp", "fisub", "fisubr", "fld", "fld1", "fldcw", "fldenv", "fldl2e", "fldl2t", "fldlg2", "fldln2", "fldpi", "fldz", "fmul", "fmulp", "fnclex", "fninit", "fnop", "fnsave", "fnstcw", "fnstenv", "fnstor", "fnstsw", "fpatan", "fprem", "fprem1", "fptan", "frndint", "frstor", "fscale", "fsetpm287_nop", "fsin", "fsincos", "fsqrt", "fst", "fstp", "fstpnce", "fsub", "fsubp", "fsubr", "fsubrp", "ftst", "fucom", "fucomi", "fucomip", "fucomp", "fucompp", "fxam", "fxch", "fxtract", "fyl2x", "fyl2xp1", "loopnz", "loopz", "loop", "jrcxz", "movdir64b", "movdiri", "aesdec128kl", "aesdec256kl", "aesdecwide128kl", "aesdecwide256kl", "aesenc128kl", "aesenc256kl", "aesencwide128kl", "aesencwide256kl", "encodekey128", "encodekey256", "loadiwkey", // 3dnow "femms", "pi2fw", "pi2fd", "pi2iw", "pi2id", "pmulhrw", "pfcmpge", "pfmin", "pfrcp", "pfrsqrt", "pfsub", "pfadd", "pfcmpgt", "pfmax", "pfrcpit1", "pfrsqit1", "pfsubr", "pfacc", "pfcmpeq", "pfmul", "pfmulhrw", "pfrcpit2", "pfnacc", "pfpnacc", "pswapd", "pavgusb", // ENQCMD "enqcmd", "enqcmds", // INVPCID, "invept", "invvpid", "invpcid", // PTWRITE "ptwrite", // GFNI "gf2p8affineqb", "gf2p8affineinvqb", "gf2p8mulb", // CET "wruss", "wrss", "incssp", "saveprevssp", "setssbsy", "clrssbsy", "rstorssp", // TDX "tdcall", "seamret", "seamops", "seamcall", // WAITPKG "tpause", "umonitor", "umwait", // UINTR "uiret", "testui", "clui", "stui", "senduipi", // TSXLDTRK "xsusldtrk", "xresldtrk", ]; impl Opcode { fn name(&self) -> &'static str { unsafe { MNEMONICS.get_unchecked(*self as usize) } } } impl Colorize for Opcode { fn colorize(&self, colors: &Y, out: &mut T) -> fmt::Result { match self { Opcode::VHADDPS | Opcode::VHSUBPS | Opcode::VADDSUBPS | Opcode::VADDPD | Opcode::VADDPS | Opcode::VADDSD | Opcode::VADDSS | Opcode::VADDSUBPD | Opcode::VFMADD132PD | Opcode::VFMADD132PS | Opcode::VFMADD132SD | Opcode::VFMADD132SS | Opcode::VFMADD213PD | Opcode::VFMADD213PS | Opcode::VFMADD213SD | Opcode::VFMADD213SS | Opcode::VFMADD231PD | Opcode::VFMADD231PS | Opcode::VFMADD231SD | Opcode::VFMADD231SS | Opcode::VFMADDSUB132PD | Opcode::VFMADDSUB132PS | Opcode::VFMADDSUB213PD | Opcode::VFMADDSUB213PS | Opcode::VFMADDSUB231PD | Opcode::VFMADDSUB231PS | Opcode::VFMSUB132PD | Opcode::VFMSUB132PS | Opcode::VFMSUB132SD | Opcode::VFMSUB132SS | Opcode::VFMSUB213PD | Opcode::VFMSUB213PS | Opcode::VFMSUB213SD | Opcode::VFMSUB213SS | Opcode::VFMSUB231PD | Opcode::VFMSUB231PS | Opcode::VFMSUB231SD | Opcode::VFMSUB231SS | Opcode::VFMSUBADD132PD | Opcode::VFMSUBADD132PS | Opcode::VFMSUBADD213PD | Opcode::VFMSUBADD213PS | Opcode::VFMSUBADD231PD | Opcode::VFMSUBADD231PS | Opcode::VFNMADD132PD | Opcode::VFNMADD132PS | Opcode::VFNMADD132SD | Opcode::VFNMADD132SS | Opcode::VFNMADD213PD | Opcode::VFNMADD213PS | Opcode::VFNMADD213SD | Opcode::VFNMADD213SS | Opcode::VFNMADD231PD | Opcode::VFNMADD231PS | Opcode::VFNMADD231SD | Opcode::VFNMADD231SS | Opcode::VFNMSUB132PD | Opcode::VFNMSUB132PS | Opcode::VFNMSUB132SD | Opcode::VFNMSUB132SS | Opcode::VFNMSUB213PD | Opcode::VFNMSUB213PS | Opcode::VFNMSUB213SD | Opcode::VFNMSUB213SS | Opcode::VFNMSUB231PD | Opcode::VFNMSUB231PS | Opcode::VFNMSUB231SD | Opcode::VFNMSUB231SS | Opcode::VDIVPD | Opcode::VDIVPS | Opcode::VDIVSD | Opcode::VDIVSS | Opcode::VHADDPD | Opcode::VHSUBPD | Opcode::HADDPD | Opcode::HSUBPD | Opcode::VMULPD | Opcode::VMULPS | Opcode::VMULSD | Opcode::VMULSS | Opcode::VPABSB | Opcode::VPABSD | Opcode::VPABSW | Opcode::PABSB | Opcode::PABSD | Opcode::PABSW | Opcode::VPSIGNB | Opcode::VPSIGND | Opcode::VPSIGNW | Opcode::PSIGNB | Opcode::PSIGND | Opcode::PSIGNW | Opcode::VPADDB | Opcode::VPADDD | Opcode::VPADDQ | Opcode::VPADDSB | Opcode::VPADDSW | Opcode::VPADDUSB | Opcode::VPADDUSW | Opcode::VPADDW | Opcode::VPAVGB | Opcode::VPAVGW | Opcode::VPMULDQ | Opcode::VPMULHRSW | Opcode::VPMULHUW | Opcode::VPMULHW | Opcode::VPMULLD | Opcode::VPMULLW | Opcode::VPMULUDQ | Opcode::PCLMULQDQ | Opcode::PMULDQ | Opcode::PMULHRSW | Opcode::PMULLD | Opcode::VPSUBB | Opcode::VPSUBD | Opcode::VPSUBQ | Opcode::VPSUBSB | Opcode::VPSUBSW | Opcode::VPSUBUSB | Opcode::VPSUBUSW | Opcode::VPSUBW | Opcode::VROUNDPD | Opcode::VROUNDPS | Opcode::VRSQRTPS | Opcode::VSQRTPD | Opcode::VSQRTPS | Opcode::VSUBPD | Opcode::VSUBPS | Opcode::VSUBSD | Opcode::VSUBSS | Opcode::VRCPSS | Opcode::VROUNDSD | Opcode::VROUNDSS | Opcode::ROUNDPD | Opcode::ROUNDPS | Opcode::ROUNDSD | Opcode::ROUNDSS | Opcode::VRSQRTSS | Opcode::VSQRTSD | Opcode::VSQRTSS | Opcode::VPSADBW | Opcode::VMPSADBW | Opcode::VPHADDD | Opcode::VPHADDSW | Opcode::VPHADDW | Opcode::VPHSUBD | Opcode::VPHSUBSW | Opcode::VPHSUBW | Opcode::VPHADDUBSW | Opcode::VPMADDWD | Opcode::VDPPD | Opcode::VDPPS | Opcode::VRCPPS | Opcode::VORPD | Opcode::VORPS | Opcode::VANDPD | Opcode::VANDPS | Opcode::VANDNPD | Opcode::VANDNPS | Opcode::VPAND | Opcode::VPANDN | Opcode::VPOR | Opcode::VPXOR | Opcode::VXORPD | Opcode::VXORPS | Opcode::VPSLLD | Opcode::VPSLLDQ | Opcode::VPSLLQ | Opcode::VPSLLVD | Opcode::VPSLLVQ | Opcode::VPSLLW | Opcode::VPSRAD | Opcode::VPSRAVD | Opcode::VPSRAW | Opcode::VPSRLD | Opcode::VPSRLDQ | Opcode::VPSRLQ | Opcode::VPSRLVD | Opcode::VPSRLVQ | Opcode::VPSRLW | Opcode::PHADDD | Opcode::PHADDSW | Opcode::PHADDW | Opcode::PHSUBD | Opcode::PHSUBSW | Opcode::PHSUBW | Opcode::PMADDUBSW | Opcode::ADDSUBPD | Opcode::DPPS | Opcode::DPPD | Opcode::MPSADBW | Opcode::RCPSS | Opcode::RSQRTSS | Opcode::SQRTSD | Opcode::ADDSD | Opcode::SUBSD | Opcode::MULSD | Opcode::DIVSD | Opcode::SQRTSS | Opcode::ADDSS | Opcode::SUBSS | Opcode::MULSS | Opcode::DIVSS | Opcode::HADDPS | Opcode::HSUBPS | Opcode::ADDSUBPS | Opcode::PMULHRW | Opcode::PFRCP | Opcode::PFRSQRT | Opcode::PFSUB | Opcode::PFADD | Opcode::PFRCPIT1 | Opcode::PFRSQIT1 | Opcode::PFSUBR | Opcode::PFACC | Opcode::PFMUL | Opcode::PFMULHRW | Opcode::PFRCPIT2 | Opcode::PFNACC | Opcode::PFPNACC | Opcode::PSWAPD | Opcode::PAVGUSB | Opcode::XADD| Opcode::DIV | Opcode::IDIV | Opcode::MUL | Opcode::MULX | Opcode::NEG | Opcode::NOT | Opcode::SAR | Opcode::SAL | Opcode::SHR | Opcode::SARX | Opcode::SHLX | Opcode::SHRX | Opcode::SHRD | Opcode::SHL | Opcode::RCR | Opcode::RCL | Opcode::ROR | Opcode::RORX | Opcode::ROL | Opcode::INC | Opcode::DEC | Opcode::SBB | Opcode::AND | Opcode::XOR | Opcode::OR | Opcode::LEA | Opcode::ADD | Opcode::ADC | Opcode::ADCX | Opcode::ADOX | Opcode::SUB | Opcode::POPCNT | Opcode::LZCNT | Opcode::BT | Opcode::BTS | Opcode::BTR | Opcode::BTC | Opcode::BSF | Opcode::BSR | Opcode::BZHI | Opcode::PDEP | Opcode::PEXT | Opcode::TZCNT | Opcode::ANDN | Opcode::BEXTR | Opcode::BLSI | Opcode::BLSMSK | Opcode::BLSR | Opcode::ADDPS | Opcode::ADDPD | Opcode::ANDNPS | Opcode::ANDNPD | Opcode::ANDPS | Opcode::ANDPD | Opcode::COMISD | Opcode::COMISS | Opcode::DIVPS | Opcode::DIVPD | Opcode::MULPS | Opcode::MULPD | Opcode::ORPS | Opcode::ORPD | Opcode::PADDB | Opcode::PADDD | Opcode::PADDQ | Opcode::PADDSB | Opcode::PADDSW | Opcode::PADDUSB | Opcode::PADDUSW | Opcode::PADDW | Opcode::PAND | Opcode::PANDN | Opcode::PAVGB | Opcode::PAVGW | Opcode::PMADDWD | Opcode::PMULHUW | Opcode::PMULHW | Opcode::PMULLW | Opcode::PMULUDQ | Opcode::POR | Opcode::PSADBW | Opcode::PSHUFD | Opcode::PSHUFW | Opcode::PSHUFB | Opcode::PSLLD | Opcode::PSLLDQ | Opcode::PSLLQ | Opcode::PSLLW | Opcode::PSRAD | Opcode::PSRAW | Opcode::PSRLD | Opcode::PSRLDQ | Opcode::PSRLQ | Opcode::PSRLW | Opcode::PSUBB | Opcode::PSUBD | Opcode::PSUBQ | Opcode::PSUBSB | Opcode::PSUBSW | Opcode::PSUBUSB | Opcode::PSUBUSW | Opcode::PSUBW | Opcode::PXOR | Opcode::RSQRTPS | Opcode::SQRTPS | Opcode::SQRTPD | Opcode::SUBPS | Opcode::SUBPD | Opcode::XORPS | Opcode::XORPD | Opcode::RCPPS | Opcode::SHLD | Opcode::SLHD | Opcode::UCOMISD | Opcode::UCOMISS | Opcode::F2XM1 | Opcode::FABS | Opcode::FADD | Opcode::FADDP | Opcode::FCHS | Opcode::FCOS | Opcode::FDIV | Opcode::FDIVP | Opcode::FDIVR | Opcode::FDIVRP | Opcode::FIADD | Opcode::FIDIV | Opcode::FIDIVR | Opcode::FIMUL | Opcode::FISUB | Opcode::FISUBR | Opcode::FMUL | Opcode::FMULP | Opcode::FNCLEX | Opcode::FNINIT | Opcode::FPATAN | Opcode::FPREM | Opcode::FPREM1 | Opcode::FPTAN | Opcode::FRNDINT | Opcode::FSCALE | Opcode::FSIN | Opcode::FSINCOS | Opcode::FSQRT | Opcode::FSUB | Opcode::FSUBP | Opcode::FSUBR | Opcode::FSUBRP | Opcode::FXTRACT | Opcode::FYL2X | Opcode::FYL2XP1 | Opcode::IMUL => { write!(out, "{}", colors.arithmetic_op(self)) } Opcode::POPF | Opcode::PUSHF | Opcode::ENTER | Opcode::LEAVE | Opcode::PUSH | Opcode::POP => { write!(out, "{}", colors.stack_op(self)) } Opcode::WAIT | Opcode::FNOP | Opcode::FDISI8087_NOP | Opcode::FENI8087_NOP | Opcode::FSETPM287_NOP | Opcode::PREFETCHNTA | Opcode::PREFETCH0 | Opcode::PREFETCH1 | Opcode::PREFETCH2 | Opcode::PREFETCHW | Opcode::NOP => { write!(out, "{}", colors.nop_op(self)) } /* Control flow */ Opcode::HLT | Opcode::INT | Opcode::INTO | Opcode::IRET | Opcode::IRETD | Opcode::IRETQ | Opcode::RETF | Opcode::RETURN => { write!(out, "{}", colors.stop_op(self)) } Opcode::LOOPNZ | Opcode::LOOPZ | Opcode::LOOP | Opcode::JRCXZ | Opcode::CALL | Opcode::CALLF | Opcode::JMP | Opcode::JMPF | Opcode::JO | Opcode::JNO | Opcode::JB | Opcode::JNB | Opcode::JZ | Opcode::JNZ | Opcode::JA | Opcode::JNA | Opcode::JS | Opcode::JNS | Opcode::JP | Opcode::JNP | Opcode::JL | Opcode::JGE | Opcode::JLE | Opcode::JG => { write!(out, "{}", colors.control_flow_op(self)) } /* Data transfer */ Opcode::PI2FW | Opcode::PI2FD | Opcode::PF2ID | Opcode::PF2IW | Opcode::VCVTDQ2PD | Opcode::VCVTDQ2PS | Opcode::VCVTPD2DQ | Opcode::VCVTPD2PS | Opcode::VCVTPH2PS | Opcode::VCVTPS2DQ | Opcode::VCVTPS2PD | Opcode::VCVTPS2PH | Opcode::VCVTTPD2DQ | Opcode::VCVTTPS2DQ | Opcode::VCVTSD2SI | Opcode::VCVTSD2SS | Opcode::VCVTSI2SD | Opcode::VCVTSI2SS | Opcode::VCVTSS2SD | Opcode::VCVTSS2SI | Opcode::VCVTTSD2SI | Opcode::VCVTTSS2SI | Opcode::VMOVDDUP | Opcode::VPSHUFLW | Opcode::VBLENDPD | Opcode::VBLENDPS | Opcode::VBLENDVPD | Opcode::VBLENDVPS | Opcode::PBLENDVB | Opcode::PBLENDW | Opcode::BLENDPD | Opcode::BLENDPS | Opcode::BLENDVPD | Opcode::BLENDVPS | Opcode::BLENDW | Opcode::VBROADCASTF128 | Opcode::VBROADCASTI128 | Opcode::VBROADCASTSD | Opcode::VBROADCASTSS | Opcode::VEXTRACTF128 | Opcode::VEXTRACTI128 | Opcode::VEXTRACTPS | Opcode::EXTRACTPS | Opcode::VGATHERDPD | Opcode::VGATHERDPS | Opcode::VGATHERQPD | Opcode::VGATHERQPS | Opcode::VINSERTF128 | Opcode::VINSERTI128 | Opcode::VINSERTPS | Opcode::INSERTPS | Opcode::VMASKMOVDQU | Opcode::VMASKMOVPD | Opcode::VMASKMOVPS | Opcode::VMOVAPD | Opcode::VMOVAPS | Opcode::VMOVD | Opcode::VMOVDQA | Opcode::VMOVDQU | Opcode::VMOVHLPS | Opcode::VMOVHPD | Opcode::VMOVHPS | Opcode::VMOVLHPS | Opcode::VMOVLPD | Opcode::VMOVLPS | Opcode::VMOVMSKPD | Opcode::VMOVMSKPS | Opcode::VMOVNTDQ | Opcode::VMOVNTDQA | Opcode::VMOVNTPD | Opcode::VMOVNTPS | Opcode::MOVDIR64B | Opcode::MOVDIRI | Opcode::MOVNTDQA | Opcode::VMOVQ | Opcode::VMOVSHDUP | Opcode::VMOVSLDUP | Opcode::VMOVUPD | Opcode::VMOVUPS | Opcode::VMOVSD | Opcode::VMOVSS | Opcode::VPBLENDD | Opcode::VPBLENDVB | Opcode::VPBLENDW | Opcode::VPBROADCASTB | Opcode::VPBROADCASTD | Opcode::VPBROADCASTQ | Opcode::VPBROADCASTW | Opcode::VPGATHERDD | Opcode::VPGATHERDQ | Opcode::VPGATHERQD | Opcode::VPGATHERQQ | Opcode::VPCLMULQDQ | Opcode::VPMOVMSKB | Opcode::VPMOVSXBD | Opcode::VPMOVSXBQ | Opcode::VPMOVSXBW | Opcode::VPMOVSXDQ | Opcode::VPMOVSXWD | Opcode::VPMOVSXWQ | Opcode::VPMOVZXBD | Opcode::VPMOVZXBQ | Opcode::VPMOVZXBW | Opcode::VPMOVZXDQ | Opcode::VPMOVZXWD | Opcode::VPMOVZXWQ | Opcode::PMOVSXBD | Opcode::PMOVSXBQ | Opcode::PMOVSXBW | Opcode::PMOVSXDQ | Opcode::PMOVSXWD | Opcode::PMOVSXWQ | Opcode::PMOVZXBD | Opcode::PMOVZXBQ | Opcode::PMOVZXBW | Opcode::PMOVZXDQ | Opcode::PMOVZXWD | Opcode::PMOVZXWQ | Opcode::VUNPCKHPD | Opcode::VUNPCKHPS | Opcode::VUNPCKLPD | Opcode::VUNPCKLPS | Opcode::VPUNPCKHBW | Opcode::VPUNPCKHDQ | Opcode::VPUNPCKHQDQ | Opcode::VPUNPCKHWD | Opcode::VPUNPCKLBW | Opcode::VPUNPCKLDQ | Opcode::VPUNPCKLQDQ | Opcode::VPUNPCKLWD | Opcode::VSHUFPD | Opcode::VSHUFPS | Opcode::VPACKSSDW | Opcode::PACKUSDW | Opcode::VPACKSSWB | Opcode::VPACKUSWB | Opcode::VPALIGNR | Opcode::PALIGNR | Opcode::VPERM2F128 | Opcode::VPERM2I128 | Opcode::VPERMD | Opcode::VPERMILPD | Opcode::VPERMILPS | Opcode::VPERMPD | Opcode::VPERMPS | Opcode::VPERMQ | Opcode::VPEXTRB | Opcode::VPEXTRD | Opcode::VPEXTRQ | Opcode::VPEXTRW | Opcode::PEXTRB | Opcode::PEXTRD | Opcode::PEXTRQ | Opcode::EXTRQ | Opcode::PINSRB | Opcode::PINSRD | Opcode::PINSRQ | Opcode::INSERTQ | Opcode::VPINSRB | Opcode::VPINSRD | Opcode::VPINSRQ | Opcode::VPINSRW | Opcode::VPMASKMOVD | Opcode::VPMASKMOVQ | Opcode::VPSHUFB | Opcode::VPSHUFD | Opcode::VPHMINPOSUW | Opcode::PHMINPOSUW | Opcode::VZEROUPPER | Opcode::VLDDQU | Opcode::BSWAP | Opcode::CVTDQ2PD | Opcode::CVTDQ2PS | Opcode::CVTPS2DQ | Opcode::CVTPD2DQ | Opcode::CVTPI2PS | Opcode::CVTPI2PD | Opcode::CVTPS2PD | Opcode::CVTPD2PS | Opcode::CVTPS2PI | Opcode::CVTPD2PI | Opcode::CVTSD2SI | Opcode::CVTSD2SS | Opcode::CVTSI2SD | Opcode::CVTSI2SS | Opcode::CVTSS2SD | Opcode::CVTSS2SI | Opcode::CVTTPD2DQ | Opcode::CVTTPS2DQ | Opcode::CVTTPS2PI | Opcode::CVTTPD2PI | Opcode::CVTTSD2SI | Opcode::CVTTSS2SI | Opcode::MASKMOVQ | Opcode::MASKMOVDQU | Opcode::MOVAPS | Opcode::MOVAPD | Opcode::MOVD | Opcode::MOVHPS | Opcode::MOVHPD | Opcode::MOVHLPS | Opcode::MOVLPS | Opcode::MOVLPD | Opcode::MOVLHPS | Opcode::MOVMSKPS | Opcode::MOVMSKPD | Opcode::MOVNTI | Opcode::MOVNTPS | Opcode::MOVNTPD | Opcode::MOVNTSS | Opcode::MOVNTSD | Opcode::MOVNTQ | Opcode::MOVNTDQ | Opcode::MOVSD | Opcode::MOVSS | Opcode::MOVUPD | Opcode::PSHUFHW | Opcode::PSHUFLW | Opcode::PUNPCKHBW | Opcode::PUNPCKHDQ | Opcode::PUNPCKHWD | Opcode::PUNPCKLBW | Opcode::PUNPCKLDQ | Opcode::PUNPCKLWD | Opcode::PUNPCKLQDQ | Opcode::PUNPCKHQDQ | Opcode::PACKSSDW | Opcode::PACKSSWB | Opcode::PACKUSWB | Opcode::UNPCKHPS | Opcode::UNPCKHPD | Opcode::UNPCKLPS | Opcode::UNPCKLPD | Opcode::SHUFPD | Opcode::SHUFPS | Opcode::PMOVMSKB | Opcode::LDDQU | Opcode::CMC | Opcode::CLC | Opcode::CLI | Opcode::CLD | Opcode::STC | Opcode::STI | Opcode::STD | Opcode::CBW | Opcode::CWDE | Opcode::CDQE | Opcode::CWD | Opcode::CDQ | Opcode::CQO | Opcode::MOVDDUP | Opcode::MOVSLDUP | Opcode::MOVDQ2Q | Opcode::MOVDQU | Opcode::MOVDQA | Opcode::MOVQ | Opcode::MOVQ2DQ | Opcode::MOVSHDUP | Opcode::MOVUPS | Opcode::PEXTRW | Opcode::PINSRW | Opcode::MOV | Opcode::MOVBE | Opcode::LODS | Opcode::STOS | Opcode::LAHF | Opcode::SAHF | Opcode::MOVS | Opcode::INS | Opcode::IN | Opcode::OUTS | Opcode::OUT | Opcode::MOVSX_b | Opcode::MOVSX_w | Opcode::MOVZX_b | Opcode::MOVZX_w | Opcode::MOVSX | Opcode::MOVSXD | Opcode::FILD | Opcode::FBLD | Opcode::FBSTP | Opcode::FIST | Opcode::FISTP | Opcode::FISTTP | Opcode::FLD | Opcode::FLD1 | Opcode::FLDCW | Opcode::FLDENV | Opcode::FLDL2E | Opcode::FLDL2T | Opcode::FLDLG2 | Opcode::FLDLN2 | Opcode::FLDPI | Opcode::FLDZ | Opcode::FST | Opcode::FSTP | Opcode::FSTPNCE | Opcode::FNSAVE | Opcode::FNSTCW | Opcode::FNSTENV | Opcode::FNSTOR | Opcode::FNSTSW | Opcode::FRSTOR | Opcode::FXCH | Opcode::XCHG | Opcode::XLAT | Opcode::CMOVA | Opcode::CMOVB | Opcode::CMOVG | Opcode::CMOVGE | Opcode::CMOVL | Opcode::CMOVLE | Opcode::CMOVNA | Opcode::CMOVNB | Opcode::CMOVNO | Opcode::CMOVNP | Opcode::CMOVNS | Opcode::CMOVNZ | Opcode::CMOVO | Opcode::CMOVP | Opcode::CMOVS | Opcode::CMOVZ | Opcode::FCMOVB | Opcode::FCMOVBE | Opcode::FCMOVE | Opcode::FCMOVNB | Opcode::FCMOVNBE | Opcode::FCMOVNE | Opcode::FCMOVNU | Opcode::FCMOVU | Opcode::SALC | Opcode::SETO | Opcode::SETNO | Opcode::SETB | Opcode::SETAE | Opcode::SETZ | Opcode::SETNZ | Opcode::SETBE | Opcode::SETA | Opcode::SETS | Opcode::SETNS | Opcode::SETP | Opcode::SETNP | Opcode::SETL | Opcode::SETGE | Opcode::SETLE | Opcode::SETG => { write!(out, "{}", colors.data_op(self)) } Opcode::VCOMISD | Opcode::VCOMISS | Opcode::VUCOMISD | Opcode::VUCOMISS | Opcode::VCMPPD | Opcode::VCMPPS | Opcode::VCMPSD | Opcode::VCMPSS | Opcode::VMAXPD | Opcode::VMAXPS | Opcode::VMAXSD | Opcode::VMAXSS | Opcode::VMINPD | Opcode::VMINPS | Opcode::VMINSD | Opcode::VMINSS | Opcode::VPCMPEQB | Opcode::VPCMPEQD | Opcode::VPCMPEQQ | Opcode::VPCMPEQW | Opcode::VPCMPGTB | Opcode::VPCMPGTD | Opcode::VPCMPGTQ | Opcode::VPCMPGTW | Opcode::VPCMPISTRI | Opcode::VPCMPISTRM | Opcode::VPMAXSB | Opcode::VPMAXSD | Opcode::VPMAXSW | Opcode::VPMAXUB | Opcode::VPMAXUW | Opcode::VPMAXUD | Opcode::VPMINSW | Opcode::VPMINSD | Opcode::VPMINUD | Opcode::VPTEST | Opcode::VTESTPD | Opcode::VTESTPS | Opcode::PCMPEQB | Opcode::PCMPEQD | Opcode::PCMPEQQ | Opcode::PCMPEQW | Opcode::PCMPESTRI | Opcode::PCMPESTRM | Opcode::PCMPGTB | Opcode::PCMPGTD | Opcode::PCMPGTQ | Opcode::PCMPGTW | Opcode::PCMPISTRI | Opcode::PCMPISTRM | Opcode::PTEST | Opcode::MAXPD | Opcode::MAXPS | Opcode::MAXSD | Opcode::MAXSS | Opcode::MINPD | Opcode::MINPS | Opcode::MINSD | Opcode::MINSS | Opcode::PMAXSB | Opcode::PMAXSD | Opcode::PMAXSW | Opcode::PMAXUB | Opcode::PMAXUD | Opcode::PMAXUW | Opcode::PMINSB | Opcode::PMINSD | Opcode::PMINSW | Opcode::PMINUB | Opcode::PMINUD | Opcode::PMINUW | Opcode::PFCMPGE | Opcode::PFMIN | Opcode::PFCMPGT | Opcode::PFMAX | Opcode::PFCMPEQ | Opcode::CMPS | Opcode::SCAS | Opcode::TEST | Opcode::FTST | Opcode::FXAM | Opcode::FUCOM | Opcode::FUCOMI | Opcode::FUCOMIP | Opcode::FUCOMP | Opcode::FUCOMPP | Opcode::FCOM | Opcode::FCOMI | Opcode::FCOMIP | Opcode::FCOMP | Opcode::FCOMPP | Opcode::FICOM | Opcode::FICOMP | Opcode::CMPSD | Opcode::CMPSS | Opcode::CMP | Opcode::CMPPS | Opcode::CMPPD | Opcode::CMPXCHG8B | Opcode::CMPXCHG16B | Opcode::CMPXCHG => { write!(out, "{}", colors.comparison_op(self)) } Opcode::WRMSR | Opcode::RDMSR | Opcode::RDTSC | Opcode::RDPMC | Opcode::RDPID | Opcode::RDFSBASE | Opcode::RDGSBASE | Opcode::WRFSBASE | Opcode::WRGSBASE | Opcode::FXSAVE | Opcode::FXRSTOR | Opcode::LDMXCSR | Opcode::STMXCSR | Opcode::XSAVE | Opcode::XSAVEC | Opcode::XSAVES | Opcode::XSAVEC64 | Opcode::XSAVES64 | Opcode::XRSTOR | Opcode::XRSTORS | Opcode::XRSTORS64 | Opcode::XSAVEOPT | Opcode::LFENCE | Opcode::MFENCE | Opcode::SFENCE | Opcode::CLFLUSH | Opcode::CLFLUSHOPT | Opcode::CLWB | Opcode::SGDT | Opcode::SIDT | Opcode::LGDT | Opcode::LIDT | Opcode::SMSW | Opcode::LMSW | Opcode::SWAPGS | Opcode::RDTSCP | Opcode::INVEPT | Opcode::INVVPID | Opcode::INVPCID | Opcode::INVLPG | Opcode::INVLPGA | Opcode::INVLPGB | Opcode::TLBSYNC | Opcode::CPUID | Opcode::WBINVD | Opcode::INVD | Opcode::SYSRET | Opcode::CLTS | Opcode::SYSCALL | Opcode::TDCALL | Opcode::SEAMRET | Opcode::SEAMOPS | Opcode::SEAMCALL | Opcode::TPAUSE | Opcode::UMONITOR | Opcode::UMWAIT | Opcode::LSL | Opcode::SLDT | Opcode::STR | Opcode::LLDT | Opcode::LTR | Opcode::VERR | Opcode::VERW | Opcode::JMPE | Opcode::EMMS | Opcode::FEMMS | Opcode::GETSEC | Opcode::LFS | Opcode::LGS | Opcode::LSS | Opcode::RSM | Opcode::SYSENTER | Opcode::SYSEXIT | Opcode::VMREAD | Opcode::VMWRITE | Opcode::VMCLEAR | Opcode::VMPTRLD | Opcode::VMPTRST | Opcode::VMXON | Opcode::VMCALL | Opcode::VMLAUNCH | Opcode::VMRESUME | Opcode::VMLOAD | Opcode::VMMCALL | Opcode::VMSAVE | Opcode::VMRUN | Opcode::VMXOFF | Opcode::MONITOR | Opcode::MWAIT | Opcode::MONITORX | Opcode::MWAITX | Opcode::SKINIT | Opcode::CLGI | Opcode::STGI | Opcode::CLAC | Opcode::STAC | Opcode::ENCLS | Opcode::ENCLV | Opcode::XGETBV | Opcode::XSETBV | Opcode::VMFUNC | Opcode::XEND | Opcode::XTEST | Opcode::XABORT | Opcode::XBEGIN | Opcode::ENCLU | Opcode::RDPKRU | Opcode::WRPKRU | Opcode::RDPRU | Opcode::CLZERO | Opcode::ENQCMD | Opcode::ENQCMDS | Opcode::PTWRITE | Opcode::UIRET | Opcode::TESTUI | Opcode::CLUI | Opcode::STUI | Opcode::SENDUIPI | Opcode::XSUSLDTRK | Opcode::XRESLDTRK | Opcode::LAR => { write!(out, "{}", colors.platform_op(self)) } Opcode::CRC32 | Opcode::RDSEED | Opcode::RDRAND | Opcode::SHA1RNDS4 | Opcode::SHA1NEXTE | Opcode::SHA1MSG1 | Opcode::SHA1MSG2 | Opcode::SHA256RNDS2 | Opcode::SHA256MSG1 | Opcode::SHA256MSG2 | Opcode::FFREE | Opcode::FFREEP | Opcode::FDECSTP | Opcode::FINCSTP | Opcode::GF2P8MULB | Opcode::GF2P8AFFINEQB | Opcode::GF2P8AFFINEINVQB | Opcode::AESDEC128KL | Opcode::AESDEC256KL | Opcode::AESDECWIDE128KL | Opcode::AESDECWIDE256KL | Opcode::AESENC128KL | Opcode::AESENC256KL | Opcode::AESENCWIDE128KL | Opcode::AESENCWIDE256KL | Opcode::ENCODEKEY128 | Opcode::ENCODEKEY256 | Opcode::LOADIWKEY | Opcode::WRUSS | Opcode::WRSS | Opcode::INCSSP | Opcode::SAVEPREVSSP | Opcode::SETSSBSY | Opcode::CLRSSBSY | Opcode::RSTORSSP | Opcode::AESDEC | Opcode::AESDECLAST | Opcode::AESENC | Opcode::AESENCLAST | Opcode::AESIMC | Opcode::AESKEYGENASSIST | Opcode::VAESDEC | Opcode::VAESDECLAST | Opcode::VAESENC | Opcode::VAESENCLAST | Opcode::VAESIMC | Opcode::VAESKEYGENASSIST => { write!(out, "{}", colors.misc_op(self)) } Opcode::UD0 | Opcode::UD1 | Opcode::UD2 | Opcode::Invalid => { write!(out, "{}", colors.invalid_op(self)) } } } } impl fmt::Display for Instruction { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { self.display_with(DisplayStyle::Intel).colorize(&NoColors, fmt) } } impl<'instr> fmt::Display for InstructionDisplayer<'instr> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { self.colorize(&NoColors, fmt) } } /// enum controlling how `Instruction::display_with` renders instructions. `Intel` is more or less /// intel syntax, though memory operand sizes are elided if they can be inferred from other /// operands. #[derive(Copy, Clone)] pub enum DisplayStyle { /// intel-style syntax for instructions, like /// `add rax, [rdx + rcx * 2 + 0x1234]` Intel, /// C-style syntax for instructions, like /// `rax += [rdx + rcx * 2 + 0x1234]` C, // one might imagine an ATT style here, which is mostly interesting for reversing operand // order. // well. // it also complicates memory operands in an offset-only operand, and is just kind of awful, so // it's just not implemented yet. // ATT, } pub struct InstructionDisplayer<'instr> { pub(crate) instr: &'instr Instruction, pub(crate) style: DisplayStyle, } /* * Can't implement this as accepting a formatter because rust * doesn't let me build one outside println! or write! or whatever. * * can't write this as an intermediate struct because i refuse to copy * all data into the struct, and having a function producing a struct with * some lifetimes gets really hairy if it's from a trait - same GAT kind * of nonsense as i saw with ContextRead, because someone could hold onto * the dang intermediate struct forever. * * so write to some Write thing i guess. bite me. i really just want to * stop thinking about how to support printing instructions... */ impl <'instr, T: fmt::Write, Y: YaxColors> Colorize for InstructionDisplayer<'instr> { fn colorize(&self, colors: &Y, out: &mut T) -> fmt::Result { // TODO: I DONT LIKE THIS, there is no address i can give contextualize here, // the address operand maybe should be optional.. self.contextualize(colors, 0, Some(&NoContext), out) } } /// No per-operand context when contextualizing an instruction! struct NoContext; impl Instruction { pub fn write_to(&self, out: &mut T) -> fmt::Result { self.display_with(DisplayStyle::Intel).contextualize(&NoColors, 0, Some(&NoContext), out) } } fn contextualize_intel(instr: &Instruction, colors: &Y, _address: u64, _context: Option<&NoContext>, out: &mut T) -> fmt::Result { if instr.prefixes.lock() { write!(out, "lock ")?; } if instr.prefixes.rep_any() { if [Opcode::MOVS, Opcode::CMPS, Opcode::LODS, Opcode::STOS, Opcode::INS, Opcode::OUTS].contains(&instr.opcode) { // only a few of you actually use the prefix... if instr.prefixes.rep() { write!(out, "rep ")?; } else if instr.prefixes.repz() { write!(out, "repz ")?; } else if instr.prefixes.repnz() { write!(out, "repnz ")?; } } } out.write_str(instr.opcode.name())?; if instr.opcode == Opcode::XBEGIN { return write!(out, " $+{}", colors.number(signed_i32_hex(instr.imm as i32))); } if instr.operand_count > 0 { out.write_str(" ")?; if let Some(prefix) = instr.segment_override_for_op(0) { write!(out, "{}:", prefix)?; } let x = Operand::from_spec(instr, instr.operands[0]); x.colorize(colors, out)?; for i in 1..instr.operand_count { match instr.opcode { Opcode::MOVSX_b | Opcode::MOVZX_b => { match &instr.operands[i as usize] { &OperandSpec::Nothing => { return Ok(()); }, &OperandSpec::RegMMM => { out.write_str(", ")?; } _ => { out.write_str(", byte ")?; if let Some(prefix) = instr.segment_override_for_op(i) { write!(out, "{}:", prefix)?; } } } let x = Operand::from_spec(instr, instr.operands[i as usize]); x.colorize(colors, out)? }, Opcode::MOVSX_w | Opcode::MOVZX_w => { match &instr.operands[i as usize] { &OperandSpec::Nothing => { return Ok(()); }, &OperandSpec::RegMMM => { out.write_str(", ")?; } _ => { out.write_str(", word ")?; if let Some(prefix) = instr.segment_override_for_op(i) { write!(out, "{}:", prefix)?; } } } let x = Operand::from_spec(instr, instr.operands[i as usize]); x.colorize(colors, out)? }, _ => { match &instr.operands[i as usize] { &OperandSpec::Nothing => { return Ok(()); }, _ => { out.write_str(", ")?; if let Some(prefix) = instr.segment_override_for_op(i) { write!(out, "{}:", prefix)?; } let x = Operand::from_spec(instr, instr.operands[i as usize]); x.colorize(colors, out)? } } } } } } Ok(()) } fn contextualize_c(instr: &Instruction, _colors: &Y, _address: u64, _context: Option<&NoContext>, out: &mut T) -> fmt::Result { let mut brace_count = 0; if instr.prefixes.lock() { out.write_str("lock { ")?; brace_count += 1; } if instr.prefixes.rep_any() { if [Opcode::MOVS, Opcode::CMPS, Opcode::LODS, Opcode::STOS, Opcode::INS, Opcode::OUTS].contains(&instr.opcode) { let word_str = match instr.mem_size { 1 => "byte", 2 => "word", 4 => "dword", 8 => "qword", _ => { unreachable!("invalid word size") } }; // only a few of you actually use the prefix... if instr.prefixes.rep() { out.write_str("rep ")?; } else if instr.prefixes.repz() { out.write_str("repz ")?; } else if instr.prefixes.repnz() { out.write_str("repnz ")?; } // TODO: other rep kinds? out.write_str(word_str)?; out.write_str(" { ")?; brace_count += 1; } } match instr.opcode { Opcode::Invalid => { out.write_str("invalid")?; }, Opcode::MOVS => { out.write_str("es:[rdi++] = ds:[rsi++]")?; }, Opcode::CMPS => { out.write_str("rflags = flags(ds:[rsi++] - es:[rdi++])")?; }, Opcode::LODS => { // TODO: size out.write_str("rax = ds:[rsi++]")?; }, Opcode::STOS => { // TODO: size out.write_str("es:[rdi++] = rax")?; }, Opcode::INS => { // TODO: size out.write_str("es:[rdi++] = port(dx)")?; }, Opcode::OUTS => { // TODO: size out.write_str("port(dx) = ds:[rsi++]")?; } Opcode::ADD => { write!(out, "{} += {}", instr.operand(0), instr.operand(1))?; } Opcode::OR => { write!(out, "{} |= {}", instr.operand(0), instr.operand(1))?; } Opcode::ADC => { write!(out, "{} += {} + rflags.cf", instr.operand(0), instr.operand(1))?; } Opcode::ADCX => { write!(out, "{} += {} + rflags.cf", instr.operand(0), instr.operand(1))?; } Opcode::ADOX => { write!(out, "{} += {} + rflags.of", instr.operand(0), instr.operand(1))?; } Opcode::SBB => { write!(out, "{} -= {} + rflags.cf", instr.operand(0), instr.operand(1))?; } Opcode::AND => { write!(out, "{} &= {}", instr.operand(0), instr.operand(1))?; } Opcode::XOR => { write!(out, "{} ^= {}", instr.operand(0), instr.operand(1))?; } Opcode::SUB => { write!(out, "{} -= {}", instr.operand(0), instr.operand(1))?; } Opcode::CMP => { write!(out, "rflags = flags({} - {})", instr.operand(0), instr.operand(1))?; } Opcode::TEST => { write!(out, "rflags = flags({} & {})", instr.operand(0), instr.operand(1))?; } Opcode::XADD => { write!(out, "({}, {}) = ({} + {}, {})", instr.operand(0), instr.operand(1), instr.operand(0), instr.operand(1), instr.operand(0))?; } Opcode::BT => { write!(out, "bt")?; } Opcode::BTS => { write!(out, "bts")?; } Opcode::BTC => { write!(out, "btc")?; } Opcode::BSR => { write!(out, "{} = msb({})", instr.operand(0), instr.operand(1))?; } Opcode::BSF => { write!(out, "{} = lsb({}) (x86 bsf)", instr.operand(0), instr.operand(1))?; } Opcode::TZCNT => { write!(out, "{} = lsb({})", instr.operand(0), instr.operand(1))?; } Opcode::MOV => { write!(out, "{} = {}", instr.operand(0), instr.operand(1))?; } Opcode::SAR => { write!(out, "{} = {} >>> {}", instr.operand(0), instr.operand(0), instr.operand(1))?; } Opcode::SAL => { write!(out, "{} = {} <<< {}", instr.operand(0), instr.operand(0), instr.operand(1))?; } Opcode::SHR => { write!(out, "{} = {} >> {}", instr.operand(0), instr.operand(0), instr.operand(1))?; } Opcode::SHRX => { write!(out, "{} = {} >> {} (x86 shrx)", instr.operand(0), instr.operand(1), instr.operand(2))?; } Opcode::SHL => { write!(out, "{} = {} << {}", instr.operand(0), instr.operand(0), instr.operand(1))?; } Opcode::SHLX => { write!(out, "{} = {} << {} (x86 shlx)", instr.operand(0), instr.operand(1), instr.operand(2))?; } Opcode::ROR => { write!(out, "{} = {} ror {}", instr.operand(0), instr.operand(0), instr.operand(1))?; } Opcode::RORX => { write!(out, "{} = {} ror {} (x86 rorx)", instr.operand(0), instr.operand(1), instr.operand(2))?; } Opcode::ROL => { write!(out, "{} = {} rol {}", instr.operand(0), instr.operand(0), instr.operand(1))?; } Opcode::RCR => { write!(out, "{} = {} rcr {}", instr.operand(0), instr.operand(0), instr.operand(1))?; } Opcode::RCL => { write!(out, "{} = {} rcl {}", instr.operand(0), instr.operand(0), instr.operand(1))?; } Opcode::PUSH => { write!(out, "push({})", instr.operand(0))?; } Opcode::POP => { write!(out, "{} = pop()", instr.operand(0))?; } Opcode::MOVD => { write!(out, "{} = movd({})", instr.operand(0), instr.operand(1))?; } Opcode::MOVQ => { write!(out, "{} = movq({})", instr.operand(0), instr.operand(1))?; } Opcode::MOVNTQ => { write!(out, "{} = movntq({})", instr.operand(0), instr.operand(1))?; } Opcode::INC => { if instr.operand(0).is_memory() { match instr.mem_size { 1 => { write!(out, "byte {}++", instr.operand(0))?; }, 2 => { write!(out, "word {}++", instr.operand(0))?; }, 4 => { write!(out, "dword {}++", instr.operand(0))?; }, _ => { write!(out, "qword {}++", instr.operand(0))?; }, // sizes that are not 1, 2, or 4, *better* be 8. } } else { write!(out, "{}++", instr.operand(0))?; } } Opcode::DEC => { if instr.operand(0).is_memory() { match instr.mem_size { 1 => { write!(out, "byte {}--", instr.operand(0))?; }, 2 => { write!(out, "word {}--", instr.operand(0))?; }, 4 => { write!(out, "dword {}--", instr.operand(0))?; }, _ => { write!(out, "qword {}--", instr.operand(0))?; }, // sizes that are not 1, 2, or 4, *better* be 8. } } else { write!(out, "{}--", instr.operand(0))?; } } Opcode::JG => { write!(out, "if greater(rflags) then jmp {}", instr.operand(0))?; } Opcode::NOP => { write!(out, "nop")?; } _ => { if instr.operand_count() == 0 { write!(out, "{}()", instr.opcode())?; } else { write!(out, "{} = {}({}", instr.operand(0), instr.opcode(), instr.operand(0))?; let mut comma = true; for i in 1..instr.operand_count() { if comma { write!(out, ", ")?; } write!(out, "{}", instr.operand(i))?; comma = true; } write!(out, ")")?; } } } while brace_count > 0 { out.write_str(" }")?; brace_count -= 1; } Ok(()) } impl <'instr, T: fmt::Write, Y: YaxColors> ShowContextual for InstructionDisplayer<'instr> { fn contextualize(&self, colors: &Y, address: u64, context: Option<&NoContext>, out: &mut T) -> fmt::Result { let InstructionDisplayer { instr, style, } = self; match style { DisplayStyle::Intel => { contextualize_intel(instr, colors, address, context, out) } DisplayStyle::C => { contextualize_c(instr, colors, address, context, out) } } } } #[cfg(feature="std")] impl ShowContextual], T, Y> for Instruction { fn contextualize(&self, colors: &Y, _address: u64, context: Option<&[Option]>, out: &mut T) -> fmt::Result { if self.prefixes.lock() { write!(out, "lock ")?; } if [Opcode::MOVS, Opcode::CMPS, Opcode::LODS, Opcode::STOS, Opcode::INS, Opcode::OUTS].contains(&self.opcode) { // only a few of you actually use the prefix... if self.prefixes.rep() { write!(out, "rep ")?; } else if self.prefixes.repz() { write!(out, "repz ")?; } else if self.prefixes.repnz() { write!(out, "repnz ")?; } } self.opcode.colorize(colors, out)?; match context.and_then(|xs| xs[0].as_ref()) { Some(s) => { write!(out, " {}", s)?; }, None => { match self.operands[0] { OperandSpec::Nothing => { return Ok(()); }, _ => { write!(out, " ")?; if let Some(prefix) = self.segment_override_for_op(0) { write!(out, "{}:", prefix)?; } } } let x = Operand::from_spec(self, self.operands[0]); x.colorize(colors, out)?; } }; for i in 1..4 { match self.opcode { Opcode::MOVSX_b | Opcode::MOVZX_b => { match context.and_then(|xs| xs[i].as_ref()) { Some(s) => { write!(out, ", {}", s)? } None => { match &self.operands[i] { &OperandSpec::Nothing => { return Ok(()); }, &OperandSpec::RegMMM => { write!(out, ", ")?; } _ => { write!(out, ", byte ")?; if let Some(prefix) = self.segment_override_for_op(1) { write!(out, "{}:", prefix)?; } } } let x = Operand::from_spec(self, self.operands[i]); x.colorize(colors, out)? } } }, Opcode::MOVSX_w | Opcode::MOVZX_w => { match context.and_then(|xs| xs[i].as_ref()) { Some(s) => { write!(out, ", {}", s)? } None => { match &self.operands[i] { &OperandSpec::Nothing => { return Ok(()); }, &OperandSpec::RegMMM => { write!(out, ", ")?; } _ => { write!(out, ", word ")?; if let Some(prefix) = self.segment_override_for_op(1) { write!(out, "{}:", prefix)?; } } } let x = Operand::from_spec(self, self.operands[i]); x.colorize(colors, out)? } } }, _ => { match context.and_then(|xs| xs[i].as_ref()) { Some(s) => { write!(out, ", {}", s)? } None => { match &self.operands[i] { &OperandSpec::Nothing => { return Ok(()); }, _ => { write!(out, ", ")?; if let Some(prefix) = self.segment_override_for_op(1) { write!(out, "{}:", prefix)?; } let x = Operand::from_spec(self, self.operands[i]); x.colorize(colors, out)? } } } } } } } Ok(()) } }