From 6f0426bc30ae65aac2f08cbf90aafa823f4554bc Mon Sep 17 00:00:00 2001 From: iximeow Date: Mon, 11 May 2026 02:01:16 +0000 Subject: the rest of x86-64 behaviors. so far. --- src/long_mode/behavior.rs | 2005 ++++++++++++++++++++++++++++++++------------- 1 file changed, 1425 insertions(+), 580 deletions(-) (limited to 'src/long_mode/behavior.rs') diff --git a/src/long_mode/behavior.rs b/src/long_mode/behavior.rs index bd2f0b9..65d9276 100644 --- a/src/long_mode/behavior.rs +++ b/src/long_mode/behavior.rs @@ -149,22 +149,36 @@ impl Instruction { behavior = behavior .set_implicit_ops(RDI_MEMWRITE_IDX); } - } else if self.opcode() == Opcode::VPCMPESTRI { + } else if self.opcode() == Opcode::PCMPESTRI || self.opcode() == Opcode::VPCMPESTRI { if self.prefixes.vex_unchecked().w() { behavior = behavior - .set_implicit_ops(VPCMPESTRI_64B_IDX); + .set_implicit_ops(PCMPESTRI_64B_IDX); } else { behavior = behavior - .set_implicit_ops(VPCMPESTRI_32B_IDX); + .set_implicit_ops(PCMPESTRI_32B_IDX); } - } else if self.opcode() == Opcode::VPCMPESTRM { + } else if self.opcode() == Opcode::PCMPESTRM || self.opcode() == Opcode::VPCMPESTRM { if self.prefixes.vex_unchecked().w() { behavior = behavior - .set_implicit_ops(VPCMPESTRM_64B_IDX); + .set_implicit_ops(PCMPESTRM_64B_IDX); } else { behavior = behavior - .set_implicit_ops(VPCMPESTRM_32B_IDX); + .set_implicit_ops(PCMPESTRM_32B_IDX); } + } else if self.opcode() == Opcode::LOOPNZ + || self.opcode() == Opcode::LOOPZ + || self.opcode() == Opcode::LOOP + || self.opcode() == Opcode::JRCXZ { + if self.prefixes.rex_unchecked().w() { + behavior = behavior + .set_implicit_ops(RW_RCX_IDX); + } else if self.prefixes.operand_size() { + behavior = behavior + .set_implicit_ops(RW_CX_IDX); + } else { + behavior = behavior + .set_implicit_ops(RW_ECX_IDX); + } } else { // TODO: words unreachable!(); @@ -1214,6 +1228,12 @@ pub enum ComplexOp { /// TODO: document ENQCMD, ENQCMDS, + + /// TODO: document + V4FNMADDSS, + V4FNMADDPS, + V4FMADDSS, + V4FMADDPS, } /// a visitor for collecting architectural accesses for an `Instruction`. used with @@ -1881,6 +1901,39 @@ static LEAVE_OPS: &'static [ImplicitOperand] = &[ } ]; +static ENTER_OPS: &'static [ImplicitOperand] = &[ + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::rsp(), + disp: 0, + write: true, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::rbp(), + disp: 0, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::rbp(), + disp: 0, + write: true, + }, + ImplicitOperand { + spec: OperandSpec::Deref, + reg: RegSpec::rsp(), + disp: -8i32, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::rsp(), + disp: 0, + write: true, + } +]; + static XLAT_OPS: &'static [ImplicitOperand] = &[ ImplicitOperand { // xlat is the only implicit operand to use a base/index addressing scheme, so note the @@ -2257,18 +2310,46 @@ static CALLF_OPS: &'static [ImplicitOperand] = &[ write: true, }, ImplicitOperand { + spec: OperandSpec::Disp, + reg: RegSpec::rsp(), + disp: -10i32, + write: true, + }, + // push.. pushes the value (above), then does a RMW on rsp. + ImplicitOperand { spec: OperandSpec::RegRRR, - reg: RegSpec::cs(), + reg: RegSpec::rsp(), disp: 0, - write: true, + write: false, }, ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::rsp(), + disp: 0, + write: true, + } +]; + +static RETF_OPS: &'static [ImplicitOperand] = &[ + ImplicitOperand { spec: OperandSpec::Disp, reg: RegSpec::rsp(), - disp: -8i32, + disp: 0i32, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::rip(), + disp: 0, write: true, }, - // push.. pushes the value (above), then does a RMW on rsp. + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::cs(), + disp: 0, + write: true, + }, + // pop.. pops the value (above), then does a RMW on rsp. ImplicitOperand { spec: OperandSpec::RegRRR, reg: RegSpec::rsp(), @@ -2524,7 +2605,7 @@ static RDI_MEMWRITE_OPS: &'static [ImplicitOperand] = &[ }, ]; -static VPCMPESTRI_64B_OPS: &'static [ImplicitOperand] = &[ +static PCMPESTRI_64B_OPS: &'static [ImplicitOperand] = &[ ImplicitOperand { spec: OperandSpec::RegRRR, reg: RegSpec::rax(), @@ -2545,7 +2626,7 @@ static VPCMPESTRI_64B_OPS: &'static [ImplicitOperand] = &[ }, ]; -static VPCMPESTRI_32B_OPS: &'static [ImplicitOperand] = &[ +static PCMPESTRI_32B_OPS: &'static [ImplicitOperand] = &[ ImplicitOperand { spec: OperandSpec::RegRRR, reg: RegSpec::eax(), @@ -2566,7 +2647,7 @@ static VPCMPESTRI_32B_OPS: &'static [ImplicitOperand] = &[ }, ]; -static VPCMPESTRM_64B_OPS: &'static [ImplicitOperand] = &[ +static PCMPESTRM_64B_OPS: &'static [ImplicitOperand] = &[ ImplicitOperand { spec: OperandSpec::RegRRR, reg: RegSpec::rax(), @@ -2587,7 +2668,7 @@ static VPCMPESTRM_64B_OPS: &'static [ImplicitOperand] = &[ }, ]; -static VPCMPESTRM_32B_OPS: &'static [ImplicitOperand] = &[ +static PCMPESTRM_32B_OPS: &'static [ImplicitOperand] = &[ ImplicitOperand { spec: OperandSpec::RegRRR, reg: RegSpec::eax(), @@ -2608,7 +2689,7 @@ static VPCMPESTRM_32B_OPS: &'static [ImplicitOperand] = &[ }, ]; -static VPCMPISTRI_OPS: &'static [ImplicitOperand] = &[ +static PCMPISTRI_OPS: &'static [ImplicitOperand] = &[ ImplicitOperand { spec: OperandSpec::RegRRR, reg: RegSpec::ecx(), @@ -2617,7 +2698,7 @@ static VPCMPISTRI_OPS: &'static [ImplicitOperand] = &[ }, ]; -static VPCMPISTRM_OPS: &'static [ImplicitOperand] = &[ +static PCMPISTRM_OPS: &'static [ImplicitOperand] = &[ ImplicitOperand { spec: OperandSpec::RegRRR, reg: RegSpec::xmm0(), @@ -2626,189 +2707,478 @@ static VPCMPISTRM_OPS: &'static [ImplicitOperand] = &[ }, ]; -const PUSH_OPS_IDX: u16 = 1; -const POP_OPS_IDX: u16 = 2; -const JCC_OPS_IDX: u16 = 3; -const CBW_IDX: u16 = 4; -const CWDE_IDX: u16 = 5; -const CDQE_IDX: u16 = 6; -const CWD_IDX: u16 = 7; -const CDQ_IDX: u16 = 8; -const CQO_IDX: u16 = 9; -const PUSHF_IDX: u16 = 10; -const POPF_IDX: u16 = 11; -const SAHF_IDX: u16 = 12; -const LAHF_IDX: u16 = 13; -const MOVS_IDX: u16 = 14; -const LODS_IDX: u16 = 15; -const STOS_IDX: u16 = 16; -const SCAS_IDX: u16 = 17; -const RETURN_IDX: u16 = 18; -const LEAVE_IDX: u16 = 19; -const XLAT_IDX: u16 = 20; -const CLTS_IDX: u16 = 21; -const MUL_IDX_1OP_BYTE: u16 = 22; -const MUL_IDX_1OP_WORD: u16 = 23; -const MUL_IDX_1OP_DWORD: u16 = 24; -const MUL_IDX_1OP_QWORD: u16 = 25; -const DIV_IDX_1OP_BYTE: u16 = 26; -const DIV_IDX_1OP_WORD: u16 = 27; -const DIV_IDX_1OP_DWORD: u16 = 28; -const DIV_IDX_1OP_QWORD: u16 = 29; -const RDTSC_IDX: u16 = 30; -const RDPMC_IDX: u16 = 31; -const CPUID_IDX: u16 = 32; -const CALL_OPS_IDX: u16 = 33; -const JMP_OPS_IDX: u16 = 34; -const CALLF_OPS_IDX: u16 = 35; -const JMPF_OPS_IDX: u16 = 36; -const LFS_IDX: u16 = 37; -const LGS_IDX: u16 = 38; -const LSS_IDX: u16 = 39; -const CMPXCHG_IDX_BYTE: u16 = 40; -const CMPXCHG_IDX_WORD: u16 = 41; -const CMPXCHG_IDX_DWORD: u16 = 42; -const CMPXCHG_IDX_QWORD: u16 = 43; -const CMPXCHG8B_IDX: u16 = 44; -const CMPXCHG16B_IDX: u16 = 45; -const RDTSCP_IDX: u16 = 46; -const MASKMOVQ_IDX: u16 = 47; -const MONITOR_IDX: u16 = 48; -const XMM0_READ_IDX: u16 = 49; -const MULX_64B_IDX: u16 = 50; -const MULX_32B_IDX: u16 = 51; -const EDI_MEMWRITE_IDX: u16 = 52; -const RDI_MEMWRITE_IDX: u16 = 53; -const VPCMPESTRI_64B_IDX: u16 = 54; -const VPCMPESTRI_32B_IDX: u16 = 55; -const VPCMPESTRM_64B_IDX: u16 = 56; -const VPCMPESTRM_32B_IDX: u16 = 57; -const VPCMPISTRI_IDX: u16 = 58; -const VPCMPISTRM_IDX: u16 = 59; - -static IMPLICIT_OPS_LIST: [&[ImplicitOperand]; 60] = [ - &[], // implicit ops list 0 is not used - PUSH_OPS, - POP_OPS, - JCC_OPS, - CBW_OPS, - CWDE_OPS, - CDQE_OPS, - CWD_OPS, - CDQ_OPS, - CQO_OPS, - PUSHF_OPS, - POPF_OPS, - SAHF_OPS, - LAHF_OPS, - MOVS_OPS, - LODS_OPS, - STOS_OPS, - SCAS_OPS, - RETURN_OPS, - LEAVE_OPS, - XLAT_OPS, - CLTS_OPS, - MUL_OPS_1OP_BYTE, - MUL_OPS_1OP_WORD, - MUL_OPS_1OP_DWORD, - MUL_OPS_1OP_QWORD, - DIV_OPS_1OP_BYTE, - DIV_OPS_1OP_WORD, - DIV_OPS_1OP_DWORD, - DIV_OPS_1OP_QWORD, - RDTSC_OPS, - RDPMC_OPS, - CPUID_OPS, - CALL_OPS, - JMP_OPS, - CALLF_OPS, - JMPF_OPS, - LFS_OPS, - LGS_OPS, - LSS_OPS, - CMPXCHG_OPS_BYTE, - CMPXCHG_OPS_WORD, - CMPXCHG_OPS_DWORD, - CMPXCHG_OPS_QWORD, - CMPXCHG8B_OPS, - CMPXCHG16B_OPS, - RDTSCP_OPS, - MASKMOVQ_OPS, - MONITOR_OPS, - XMM0_READ_OPS, - MULX_64B_OPS, - MULX_32B_OPS, - EDI_MEMWRITE_OPS, - RDI_MEMWRITE_OPS, - VPCMPESTRI_64B_OPS, - VPCMPESTRI_32B_OPS, - VPCMPESTRM_64B_OPS, - VPCMPESTRM_32B_OPS, - VPCMPISTRI_OPS, - VPCMPISTRM_OPS, +static READ_EDX_EAX_OPS: &'static [ImplicitOperand] = &[ + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::eax(), + disp: 0i32, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::edx(), + disp: 0i32, + write: false, + }, ]; -#[inline(never)] -#[unsafe(no_mangle)] -fn opcode2behavior(opc: &Opcode) -> Option { - use Opcode::*; - if opc == &MUL || opc == &IMUL || opc == &DIV || opc == &IDIV || opc == &NOP || opc == &CMPXCHG { - return None; - } - if opc == &VMOVHPS || opc == &VMOVHPD || opc == &VMOVLPS || opc == &VMOVLPD { - return None; - } +static LMSW_OPS: &'static [ImplicitOperand] = &[ + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::cr0(), + disp: 0i32, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::cr0(), + disp: 0i32, + write: true, + }, +]; - let behavior = match opc { - ADD => GENERAL_RW_R_FLAGWRITE, - OR => GENERAL_RW_R_FLAGWRITE, - ADC => GENERAL_RW_R_FLAGRW, - SBB => GENERAL_RW_R_FLAGRW, - AND => GENERAL_RW_R_FLAGWRITE, - SUB => GENERAL_RW_R_FLAGWRITE, - XOR => GENERAL_RW_R_FLAGWRITE, - CMP => GENERAL_R_R_FLAGWRITE, - ROL => GENERAL_RW_R_FLAGWRITE, - ROR => GENERAL_RW_R_FLAGWRITE, - RCL => GENERAL_RW_R_FLAGRW, - RCR => GENERAL_RW_R_FLAGRW, - SHL => GENERAL_RW_R_FLAGWRITE, - SHR => GENERAL_RW_R_FLAGWRITE, - SAL => GENERAL_RW_R_FLAGWRITE, - SAR => GENERAL_RW_R_FLAGWRITE, - BTC => GENERAL_RW_R_FLAGWRITE - .set_complex(true), - BTR => GENERAL_RW_R_FLAGWRITE - .set_complex(true), - BTS => GENERAL_RW_R_FLAGWRITE - .set_complex(true), - CMPXCHG => GENERAL_RW_R_FLAGWRITE, - CMPXCHG8B => GENERAL_RW_R_FLAGWRITE - .set_implicit_ops(CMPXCHG8B_IDX), - CMPXCHG16B => GENERAL_RW_R_FLAGWRITE - .set_implicit_ops(CMPXCHG16B_IDX), - DEC => GENERAL_RW_FLAGWRITE, - INC => GENERAL_RW_FLAGWRITE, - NEG => GENERAL_RW_FLAGWRITE, - NOT => GENERAL_RW, - XADD => GENERAL_RW_RW_FLAGRW, - XCHG => GENERAL_RW_RW, +static SMSW_OPS: &'static [ImplicitOperand] = &[ + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::cr0(), + disp: 0i32, + write: false, + }, +]; - CMPS => GENERAL_RW_RW_FLAGWRITE - .set_implicit_ops(MOVS_IDX), - SCAS => GENERAL_W_R_FLAGREAD - .set_implicit_ops(SCAS_IDX), // TODO: second operand is `aX`, right? - MOVS => GENERAL_W_R_FLAGREAD - .set_implicit_ops(MOVS_IDX), - LODS => GENERAL_W_R_FLAGREAD - .set_implicit_ops(LODS_IDX), - STOS => GENERAL_W_R_FLAGREAD +static READ_EAX_OPS: &'static [ImplicitOperand] = &[ + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::eax(), + disp: 0i32, + write: false, + }, +]; + +static WRITE_AL_OPS: &'static [ImplicitOperand] = &[ + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::al(), + disp: 0i32, + write: true, + }, +]; + +static RW_XMM0TO7_OPS: &'static [ImplicitOperand] = &[ + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(0), + disp: 0i32, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(1), + disp: 0i32, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(2), + disp: 0i32, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(3), + disp: 0i32, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(4), + disp: 0i32, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(5), + disp: 0i32, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(6), + disp: 0i32, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(7), + disp: 0i32, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(0), + disp: 0i32, + write: true, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(1), + disp: 0i32, + write: true, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(2), + disp: 0i32, + write: true, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(3), + disp: 0i32, + write: true, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(4), + disp: 0i32, + write: true, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(5), + disp: 0i32, + write: true, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(6), + disp: 0i32, + write: true, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(7), + disp: 0i32, + write: true, + }, +]; + +static ENCODEKEY_OPS: &'static [ImplicitOperand] = &[ + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(0), + disp: 0i32, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(0), + disp: 0i32, + write: true, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(1), + disp: 0i32, + write: true, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(2), + disp: 0i32, + write: true, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(4), + disp: 0i32, + write: true, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(5), + disp: 0i32, + write: true, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(6), + disp: 0i32, + write: true, + }, +]; + +static LOADIWKEY_OPS: &'static [ImplicitOperand] = &[ + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::eax(), + disp: 0i32, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::xmm(0), + disp: 0i32, + write: false, + }, +]; + +static RW_RCX_OPS: &'static [ImplicitOperand] = &[ + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::rcx(), + disp: 0, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::rcx(), + disp: 0, + write: true, + }, +]; + +static RW_ECX_OPS: &'static [ImplicitOperand] = &[ + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::ecx(), + disp: 0, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::ecx(), + disp: 0, + write: true, + }, +]; + +static RW_CX_OPS: &'static [ImplicitOperand] = &[ + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::cx(), + disp: 0, + write: false, + }, + ImplicitOperand { + spec: OperandSpec::RegRRR, + reg: RegSpec::cx(), + disp: 0, + write: true, + }, +]; + +const PUSH_OPS_IDX: u16 = 1; +const POP_OPS_IDX: u16 = 2; +const JCC_OPS_IDX: u16 = 3; +const CBW_IDX: u16 = 4; +const CWDE_IDX: u16 = 5; +const CDQE_IDX: u16 = 6; +const CWD_IDX: u16 = 7; +const CDQ_IDX: u16 = 8; +const CQO_IDX: u16 = 9; +const PUSHF_IDX: u16 = 10; +const POPF_IDX: u16 = 11; +const SAHF_IDX: u16 = 12; +const LAHF_IDX: u16 = 13; +const MOVS_IDX: u16 = 14; +const LODS_IDX: u16 = 15; +const STOS_IDX: u16 = 16; +const SCAS_IDX: u16 = 17; +const RETURN_IDX: u16 = 18; +const LEAVE_IDX: u16 = 19; +const XLAT_IDX: u16 = 20; +const CLTS_IDX: u16 = 21; +const MUL_IDX_1OP_BYTE: u16 = 22; +const MUL_IDX_1OP_WORD: u16 = 23; +const MUL_IDX_1OP_DWORD: u16 = 24; +const MUL_IDX_1OP_QWORD: u16 = 25; +const DIV_IDX_1OP_BYTE: u16 = 26; +const DIV_IDX_1OP_WORD: u16 = 27; +const DIV_IDX_1OP_DWORD: u16 = 28; +const DIV_IDX_1OP_QWORD: u16 = 29; +const RDTSC_IDX: u16 = 30; +const RDPMC_IDX: u16 = 31; +const CPUID_IDX: u16 = 32; +const CALL_OPS_IDX: u16 = 33; +const JMP_OPS_IDX: u16 = 34; +const CALLF_OPS_IDX: u16 = 35; +const JMPF_OPS_IDX: u16 = 36; +const LFS_IDX: u16 = 37; +const LGS_IDX: u16 = 38; +const LSS_IDX: u16 = 39; +const CMPXCHG_IDX_BYTE: u16 = 40; +const CMPXCHG_IDX_WORD: u16 = 41; +const CMPXCHG_IDX_DWORD: u16 = 42; +const CMPXCHG_IDX_QWORD: u16 = 43; +const CMPXCHG8B_IDX: u16 = 44; +const CMPXCHG16B_IDX: u16 = 45; +const RDTSCP_IDX: u16 = 46; +const MASKMOVQ_IDX: u16 = 47; +const MONITOR_IDX: u16 = 48; +const XMM0_READ_IDX: u16 = 49; +const MULX_64B_IDX: u16 = 50; +const MULX_32B_IDX: u16 = 51; +const EDI_MEMWRITE_IDX: u16 = 52; +const RDI_MEMWRITE_IDX: u16 = 53; +const PCMPESTRI_64B_IDX: u16 = 54; +const PCMPESTRI_32B_IDX: u16 = 55; +const PCMPESTRM_64B_IDX: u16 = 56; +const PCMPESTRM_32B_IDX: u16 = 57; +const PCMPISTRI_IDX: u16 = 58; +const PCMPISTRM_IDX: u16 = 59; +const READ_EDX_EAX_IDX: u16 = 60; +const RETF_IDX: u16 = 61; +const LMSW_IDX: u16 = 62; +const SMSW_IDX: u16 = 63; +const READ_EAX_IDX: u16 = 64; +const WRITE_AL_IDX: u16 = 65; +const RW_XMM0TO7_IDX: u16 = 66; +const ENCODEKEY_IDX: u16 = 67; +const LOADIWKEY_IDX: u16 = 68; +const RW_RCX_IDX: u16 = 69; +const RW_ECX_IDX: u16 = 70; +const RW_CX_IDX: u16 = 71; +const ENTER_IDX: u16 = 72; + +static IMPLICIT_OPS_LIST: [&[ImplicitOperand]; 73] = [ + &[], // implicit ops list 0 is not used + PUSH_OPS, + POP_OPS, + JCC_OPS, + CBW_OPS, + CWDE_OPS, + CDQE_OPS, + CWD_OPS, + CDQ_OPS, + CQO_OPS, + PUSHF_OPS, + POPF_OPS, + SAHF_OPS, + LAHF_OPS, + MOVS_OPS, + LODS_OPS, + STOS_OPS, + SCAS_OPS, + RETURN_OPS, + LEAVE_OPS, + XLAT_OPS, + CLTS_OPS, + MUL_OPS_1OP_BYTE, + MUL_OPS_1OP_WORD, + MUL_OPS_1OP_DWORD, + MUL_OPS_1OP_QWORD, + DIV_OPS_1OP_BYTE, + DIV_OPS_1OP_WORD, + DIV_OPS_1OP_DWORD, + DIV_OPS_1OP_QWORD, + RDTSC_OPS, + RDPMC_OPS, + CPUID_OPS, + CALL_OPS, + JMP_OPS, + CALLF_OPS, + JMPF_OPS, + LFS_OPS, + LGS_OPS, + LSS_OPS, + CMPXCHG_OPS_BYTE, + CMPXCHG_OPS_WORD, + CMPXCHG_OPS_DWORD, + CMPXCHG_OPS_QWORD, + CMPXCHG8B_OPS, + CMPXCHG16B_OPS, + RDTSCP_OPS, + MASKMOVQ_OPS, + MONITOR_OPS, + XMM0_READ_OPS, + MULX_64B_OPS, + MULX_32B_OPS, + EDI_MEMWRITE_OPS, + RDI_MEMWRITE_OPS, + PCMPESTRI_64B_OPS, + PCMPESTRI_32B_OPS, + PCMPESTRM_64B_OPS, + PCMPESTRM_32B_OPS, + PCMPISTRI_OPS, + PCMPISTRM_OPS, + READ_EDX_EAX_OPS, + RETF_OPS, + LMSW_OPS, + SMSW_OPS, + READ_EAX_OPS, + WRITE_AL_OPS, + RW_XMM0TO7_OPS, + ENCODEKEY_OPS, + LOADIWKEY_OPS, + RW_RCX_OPS, + RW_ECX_OPS, + RW_CX_OPS, + ENTER_OPS, +]; + +#[inline(never)] +#[unsafe(no_mangle)] +fn opcode2behavior(opc: &Opcode) -> Option { + use Opcode::*; + if opc == &MUL || opc == &IMUL || opc == &DIV || opc == &IDIV || opc == &NOP || opc == &CMPXCHG { + return None; + } + if opc == &VMOVHPS || opc == &VMOVHPD || opc == &VMOVLPS || opc == &VMOVLPD { + return None; + } + + let behavior = match opc { + ADD => GENERAL_RW_R_FLAGWRITE, + OR => GENERAL_RW_R_FLAGWRITE, + ADC => GENERAL_RW_R_FLAGRW, + SBB => GENERAL_RW_R_FLAGRW, + AND => GENERAL_RW_R_FLAGWRITE, + SUB => GENERAL_RW_R_FLAGWRITE, + XOR => GENERAL_RW_R_FLAGWRITE, + CMP => GENERAL_R_R_FLAGWRITE, + ROL => GENERAL_RW_R_FLAGWRITE, + ROR => GENERAL_RW_R_FLAGWRITE, + RCL => GENERAL_RW_R_FLAGRW, + RCR => GENERAL_RW_R_FLAGRW, + SHL => GENERAL_RW_R_FLAGWRITE, + SHR => GENERAL_RW_R_FLAGWRITE, + SAL => GENERAL_RW_R_FLAGWRITE, + SAR => GENERAL_RW_R_FLAGWRITE, + BTC => GENERAL_RW_R_FLAGWRITE + .set_complex(true), + BTR => GENERAL_RW_R_FLAGWRITE + .set_complex(true), + BTS => GENERAL_RW_R_FLAGWRITE + .set_complex(true), + CMPXCHG => GENERAL_RW_R_FLAGWRITE, + CMPXCHG8B => GENERAL_RW_R_FLAGWRITE + .set_implicit_ops(CMPXCHG8B_IDX), + CMPXCHG16B => GENERAL_RW_R_FLAGWRITE + .set_implicit_ops(CMPXCHG16B_IDX), + DEC => GENERAL_RW_FLAGWRITE, + INC => GENERAL_RW_FLAGWRITE, + NEG => GENERAL_RW_FLAGWRITE, + NOT => GENERAL_RW, + XADD => GENERAL_RW_RW_FLAGRW, + XCHG => GENERAL_RW_RW, + + CMPS => GENERAL_RW_RW_FLAGWRITE + .set_implicit_ops(MOVS_IDX), + SCAS => GENERAL_W_R_FLAGREAD + .set_implicit_ops(SCAS_IDX), // TODO: second operand is `aX`, right? + MOVS => GENERAL_W_R_FLAGREAD + .set_implicit_ops(MOVS_IDX), + LODS => GENERAL_W_R_FLAGREAD + .set_implicit_ops(LODS_IDX), + STOS => GENERAL_W_R_FLAGREAD .set_implicit_ops(STOS_IDX), INS => GENERAL_W_R, OUTS => GENERAL_R_R, - Invalid => { panic!("todo: invalid"); }, + // "Invalid" should never be a publicly-visible Opcode variant.. + Invalid => BehaviorDigest::empty() + .set_complex(true), BT => GENERAL_R_R_FLAGWRITE .set_complex(true), BSF => GENERAL_RW_R_FLAGWRITE, @@ -2894,17 +3264,33 @@ fn opcode2behavior(opc: &Opcode) -> Option { .set_pl_any(), INT => GENERAL_R, INTO => GENERAL_R_FLAGREAD, - IRET => { panic!("todo: iret"); }, - IRETD => { panic!("todo: iretd"); }, - IRETQ => { panic!("todo: iretq"); }, - RETF => { panic!("todo: retf"); }, - ENTER => { panic!("todo: enter"); }, + // TODO: should there be implicit operands for the iret instructions? they're complex + // anyway.. + IRET => BehaviorDigest::empty() + .set_pl_special() + .set_complex(true), + IRETD => BehaviorDigest::empty() + .set_pl_special() + .set_complex(true), + IRETQ => BehaviorDigest::empty() + .set_pl_special() + .set_complex(true), + RETF => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true) + .set_implicit_ops(RETF_IDX), + ENTER => BehaviorDigest::empty() + .set_implicit_ops(ENTER_IDX) + .set_operand(0, Access::Read) + .set_operand(1, Access::Read) + .set_pl_any(), LEAVE => BehaviorDigest::empty() .set_implicit_ops(LEAVE_IDX) .set_pl_any(), MOV => GENERAL_RW_R, RETURN => BehaviorDigest::empty() .set_implicit_ops(RETURN_IDX) + .set_complex(true) .set_pl_any(), PUSHF => BehaviorDigest::empty() .set_implicit_ops(PUSHF_IDX) @@ -2935,8 +3321,16 @@ fn opcode2behavior(opc: &Opcode) -> Option { .set_implicit_ops(SAHF_IDX) .set_pl_any(), TEST => GENERAL_R_R_FLAGWRITE, - IN => { panic!("todo: in"); }, - OUT => { panic!("todo: out"); }, + IN => BehaviorDigest::empty() + .set_complex(true) + .set_pl_special() + .set_operand(0, Access::Write) + .set_operand(1, Access::Read), + OUT => BehaviorDigest::empty() + .set_complex(true) + .set_pl_special() + .set_operand(0, Access::Read) + .set_operand(1, Access::Read), IMUL => BehaviorDigest::empty(), // unreachable due to branch above match JO => JCC, JNO => JCC, @@ -3006,7 +3400,9 @@ fn opcode2behavior(opc: &Opcode) -> Option { CLTS => BehaviorDigest::empty() .set_implicit_ops(CLTS_IDX) .set_pl0(), - SYSCALL => { panic!("todo: syscall"); }, + SYSCALL => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), LSL => BehaviorDigest::empty() .set_pl_any() .set_operand(0, Access::Write) @@ -3029,8 +3425,14 @@ fn opcode2behavior(opc: &Opcode) -> Option { LIDT => BehaviorDigest::empty() .set_pl0() .set_operand(0, Access::Read), - SMSW => { panic!("todo: smsw"); }, - LMSW => { panic!("todo: lmsw"); }, + SMSW => BehaviorDigest::empty() + .set_pl0() + .set_operand(0, Access::Write) + .set_implicit_ops(SMSW_IDX), + LMSW => BehaviorDigest::empty() + .set_pl0() + .set_operand(0, Access::Read) + .set_implicit_ops(LMSW_IDX), SWAPGS => BehaviorDigest::empty() .set_pl0(), RDTSCP => BehaviorDigest::empty() @@ -3041,13 +3443,38 @@ fn opcode2behavior(opc: &Opcode) -> Option { INVLPG => BehaviorDigest::empty() .set_pl0() .set_operand(0, Access::Read), - FXSAVE => { panic!("todo: fxsave"); }, - FXRSTOR => { panic!("todo: fxrstor"); }, - LDMXCSR => { panic!("todo: ldmxcsr"); }, - STMXCSR => { panic!("todo: stmxcsr"); }, - XSAVE => { panic!("todo: xsave"); }, - XRSTOR => { panic!("todo: xrstor"); }, - XSAVEOPT => { panic!("todo: xsaveopt"); }, + // TODO: this is only complex because while the memory access is 512 bytes, + // `MemoryAccessSize::bytes_size()` does not report it as such. + FXSAVE => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Write) + .set_complex(true), + // TODO: this is only complex because while the memory access is 512 bytes, + // `MemoryAccessSize::bytes_size()` does not report it as such. + FXRSTOR => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Read) + .set_complex(true), + LDMXCSR => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true) + .set_pl_any(), + STMXCSR => BehaviorDigest::empty() + .set_operand(0, Access::Write) + .set_complex(true) + .set_pl_any(), + XSAVE => BehaviorDigest::empty() + .set_operand(0, Access::Write) + .set_pl_any() + .set_complex(true), + XRSTOR => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_pl_any() + .set_complex(true), + XSAVEOPT => BehaviorDigest::empty() + .set_operand(0, Access::Write) + .set_pl_any() + .set_complex(true), LFENCE => GENERAL, MFENCE => GENERAL, SFENCE => GENERAL, @@ -3062,22 +3489,34 @@ fn opcode2behavior(opc: &Opcode) -> Option { CLFLUSHOPT => GENERAL_W, // same argument as `clflush`. CLWB => GENERAL_W, - WRMSR => { panic!("todo: wrmsr"); }, + WRMSR => BehaviorDigest::empty() + .set_pl0() + .set_complex(true), RDTSC => BehaviorDigest::empty() .set_implicit_ops(RDTSC_IDX) .set_pl_special(), - RDMSR => { panic!("todo: rdmsr"); }, + RDMSR => BehaviorDigest::empty() + .set_pl0() + .set_complex(true), RDPMC => BehaviorDigest::empty() .set_implicit_ops(RDPMC_IDX) .set_pl_special(), SLDT => BehaviorDigest::empty() .set_pl_special() - .set_operand(0, Access::Write), - STR => { panic!("todo: str"); }, + .set_operand(0, Access::Write) + .set_complex(true), + STR => BehaviorDigest::empty() + .set_pl0() + .set_operand(0, Access::Write) + .set_complex(true), LLDT => BehaviorDigest::empty() .set_pl0() - .set_operand(0, Access::Read), - LTR => { panic!("todo: ltr"); }, + .set_operand(0, Access::Read) + .set_complex(true), + LTR => BehaviorDigest::empty() + .set_pl0() + .set_operand(0, Access::Read) + .set_complex(true), VERR => GENERAL_R_FLAGWRITE, VERW => GENERAL_R_FLAGWRITE, CMC => GENERAL_FLAGRW, @@ -3089,7 +3528,10 @@ fn opcode2behavior(opc: &Opcode) -> Option { .set_pl_special(), CLD => GENERAL_FLAGRW, STD => GENERAL_FLAGRW, - JMPE => { panic!("todo: jmpe"); }, + JMPE => BehaviorDigest::empty() + .set_pl_any() // TODO: don't have a processor with jmpe to validate + .set_operand(0, Access::Read) + .set_implicit_ops(JMP_OPS_IDX), POPCNT => GENERAL_W_R_FLAGWRITE, MOVDQU => GENERAL_W_R, MOVDQA => GENERAL_W_R, @@ -3102,8 +3544,10 @@ fn opcode2behavior(opc: &Opcode) -> Option { UNPCKLPD => GENERAL_RW_R, UNPCKHPS => GENERAL_RW_R, UNPCKHPD => GENERAL_RW_R, - PSHUFHW => GENERAL_W_R, - PSHUFLW => GENERAL_W_R, + PSHUFHW => GENERAL_W_R + .set_operand(2, Access::Read), + PSHUFLW => GENERAL_W_R + .set_operand(2, Access::Read), MOVUPS => GENERAL_W_R, MOVQ2DQ => GENERAL_W_R, MOVDQ2Q => GENERAL_W_R, @@ -3117,40 +3561,87 @@ fn opcode2behavior(opc: &Opcode) -> Option { BLSI => GENERAL_W_R_FLAGWRITE, BLSMSK => GENERAL_W_R_FLAGWRITE, BLSR => GENERAL_W_R_FLAGWRITE, - VMCLEAR => { panic!("todo: vmclear"); }, - VMXON => { panic!("todo: vmxon"); }, - VMCALL => { panic!("todo: vmcall"); }, - VMLAUNCH => { panic!("todo: vmlaunch"); }, - VMRESUME => { panic!("todo: vmresume"); }, - VMXOFF => { panic!("todo: vmxoff"); }, - PCONFIG => { panic!("todo: pconfig"); }, - MONITOR => BehaviorDigest::empty() + VMCLEAR => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), + VMXON => BehaviorDigest::empty() + .set_pl0() + .set_complex(true), + VMCALL => BehaviorDigest::empty() + .set_complex(true), + VMLAUNCH => BehaviorDigest::empty() + .set_pl0() + .set_complex(true), + VMRESUME => BehaviorDigest::empty() .set_pl0() - .set_implicit_ops(MONITOR_IDX), - MWAIT => { panic!("todo: mwait"); }, - MONITORX => { panic!("todo: monitorx"); }, - MWAITX => { panic!("todo: mwaitx"); }, + .set_complex(true), + VMXOFF => BehaviorDigest::empty() + .set_pl0() + .set_complex(true), + PCONFIG => BehaviorDigest::empty() + .set_complex(true), + MONITOR => BehaviorDigest::empty() + .set_pl_special() + .set_implicit_ops(MONITOR_IDX) + .set_complex(true), + MWAIT => BehaviorDigest::empty() + .set_pl_special() + .set_complex(true), + MONITORX => BehaviorDigest::empty() + .set_pl_any() + .set_implicit_ops(MONITOR_IDX) + .set_complex(true), + MWAITX => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), CLAC => BehaviorDigest::empty() .set_pl0() .set_flags_access(Access::Write), STAC => BehaviorDigest::empty() .set_pl0() .set_flags_access(Access::Write), - ENCLS => { panic!("todo: encls"); }, - ENCLV => { panic!("todo: enclv"); }, - XGETBV => { panic!("todo: xgetbv"); }, - XSETBV => { panic!("todo: xsetbv"); }, - VMFUNC => { panic!("todo: vmfunc"); }, - XABORT => { panic!("todo: xabort"); }, - XBEGIN => { panic!("todo: xbegin"); }, - XEND => { panic!("todo: xend"); }, - XTEST => { panic!("todo: xtest"); }, - ENCLU => { panic!("todo: enclu"); }, - RDPKRU => { panic!("todo: rdpkru"); }, - WRPKRU => { panic!("todo: wrpkru"); }, - - RDPRU => { panic!("todo: rdpru"); }, - CLZERO => { panic!("todo: clzero"); }, + ENCLS => BehaviorDigest::empty() + .set_pl0() + .set_complex(true), + ENCLV => BehaviorDigest::empty() + .set_pl0() + .set_complex(true), + XGETBV => BehaviorDigest::empty() + .set_complex(true), + XSETBV => BehaviorDigest::empty() + .set_pl0() + .set_complex(true), + VMFUNC => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + XABORT => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + XBEGIN => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + XEND => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + XTEST => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + ENCLU => BehaviorDigest::empty() + .set_pl_special() + .set_complex(true), + RDPKRU => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + WRPKRU => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + + RDPRU => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + CLZERO => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), RDSEED => BehaviorDigest::empty() .set_operand(0, Access::Write) @@ -3189,7 +3680,9 @@ fn opcode2behavior(opc: &Opcode) -> Option { DIVPS => GENERAL_RW_R, DIVPD => GENERAL_RW_R, EMMS => GENERAL, - GETSEC => { panic!("todo: getsec"); }, + // TODO: untested, don't have relevant hardware.. + GETSEC => BehaviorDigest::empty() + .set_pl_any(), LFS => GENERAL_W_R .set_implicit_ops(LFS_IDX), LGS => GENERAL_W_R @@ -3250,7 +3743,8 @@ fn opcode2behavior(opc: &Opcode) -> Option { PCMPGTB => GENERAL_RW_R, PCMPGTD => GENERAL_RW_R, PCMPGTW => GENERAL_RW_R, - PINSRW => GENERAL_RW_R, + PINSRW => GENERAL_RW_R + .set_operand(2, Access::Read), PMADDWD => GENERAL_RW_R, PMAXSW => GENERAL_RW_R, PMAXUB => GENERAL_RW_R, @@ -3263,8 +3757,10 @@ fn opcode2behavior(opc: &Opcode) -> Option { PMULUDQ => GENERAL_RW_R, POR => GENERAL_RW_R, PSADBW => GENERAL_RW_R, - PSHUFW => GENERAL_RW_R, - PSHUFD => GENERAL_RW_R, + PSHUFW => GENERAL_RW_R + .set_operand(2, Access::Read), + PSHUFD => GENERAL_RW_R + .set_operand(2, Access::Read), PSLLD => GENERAL_RW_R, PSLLDQ => GENERAL_RW_R, PSLLQ => GENERAL_RW_R, @@ -3293,23 +3789,38 @@ fn opcode2behavior(opc: &Opcode) -> Option { PUNPCKHQDQ => GENERAL_RW_R, PXOR => GENERAL_RW_R, RCPPS => GENERAL_W_R, - RSM => { panic!("todo: rsm"); }, + RSM => BehaviorDigest::empty() + .set_pl_special() + .set_complex(true), RSQRTPS => GENERAL_W_R, SHLD => GENERAL_RW_R_R .set_flags_access(Access::Write), SHUFPD => GENERAL_RW_R_R, SHUFPS => GENERAL_RW_R_R, - SLHD => { panic!("todo: slhd"); }, + // TODO: slhd is not real, typo of shld + SLHD => BehaviorDigest::empty(), SQRTPS => GENERAL_W_R, SQRTPD => GENERAL_W_R, SUBPS => GENERAL_RW_R, SUBPD => GENERAL_RW_R, - SYSENTER => { panic!("todo: sysenter"); }, - SYSEXIT => { panic!("todo: sysexit"); }, + SYSENTER => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + SYSEXIT => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), UCOMISD => GENERAL_R_R_FLAGWRITE, UCOMISS => GENERAL_R_R_FLAGWRITE, - VMREAD => { panic!("todo: vmread"); }, - VMWRITE => { panic!("todo: vmwrite"); }, + VMREAD => BehaviorDigest::empty() + .set_operand(0, Access::Write) + .set_operand(1, Access::Read) + .set_pl0() + .set_complex(true), + VMWRITE => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_operand(1, Access::Read) + .set_pl0() + .set_complex(true), XORPS => GENERAL_RW_R, XORPD => GENERAL_RW_R, @@ -3563,11 +4074,11 @@ fn opcode2behavior(opc: &Opcode) -> Option { VPCMPISTRI => GENERAL_R_R .set_operand(2, Access::Read) .set_flags_access(Access::Write) - .set_implicit_ops(VPCMPISTRI_IDX), + .set_implicit_ops(PCMPISTRI_IDX), VPCMPISTRM => GENERAL_R_R .set_operand(2, Access::Read) .set_flags_access(Access::Write) - .set_implicit_ops(VPCMPISTRM_IDX), + .set_implicit_ops(PCMPISTRM_IDX), VPERM2F128 => GENERAL_W_R_R .set_operand(3, Access::Read), VPERM2I128 => GENERAL_W_R_R @@ -3719,31 +4230,56 @@ fn opcode2behavior(opc: &Opcode) -> Option { VUNPCKLPS => GENERAL_W_R_R, VXORPD => GENERAL_W_R_R, VXORPS => GENERAL_W_R_R, - VZEROUPPER => { panic!("todo: vzeroupper"); }, - VZEROALL => { panic!("todo: vzeroall"); }, - VLDMXCSR => { panic!("todo: vldmxcsr"); }, - VSTMXCSR => { panic!("todo: vstmxcsr"); }, + VZEROUPPER => BehaviorDigest::empty() + .set_complex(true), + VZEROALL => BehaviorDigest::empty() + .set_complex(true), + VLDMXCSR => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true) + .set_pl_any(), + VSTMXCSR => BehaviorDigest::empty() + .set_operand(0, Access::Write) + .set_complex(true) + .set_pl_any(), - PCLMULQDQ => { panic!("todo: pclmulqdq"); }, - AESKEYGENASSIST => { panic!("todo: aeskeygenassist"); }, + PCLMULQDQ => GENERAL_RW_R + .set_operand(2, Access::Read), + AESKEYGENASSIST => GENERAL_W_R + .set_operand(2, Access::Read), AESIMC => GENERAL_W_R, AESENC => GENERAL_RW_R, AESENCLAST => GENERAL_RW_R, AESDEC => GENERAL_RW_R, AESDECLAST => GENERAL_RW_R, PCMPGTQ => GENERAL_RW_R, - PCMPISTRM => { panic!("todo: pcmpistrm"); }, - PCMPISTRI => { panic!("todo: pcmpistri"); }, - PCMPESTRI => { panic!("todo: pcmpestri"); }, + PCMPISTRM => GENERAL_R_R + .set_operand(2, Access::Read) + .set_flags_access(Access::Write) + .set_implicit_ops(PCMPISTRM_IDX), + PCMPISTRI => GENERAL_R_R + .set_operand(2, Access::Read) + .set_flags_access(Access::Write) + .set_implicit_ops(PCMPISTRI_IDX), + PCMPESTRI => GENERAL_R_R + .set_operand(2, Access::Read) + .set_flags_access(Access::Write) + .set_nontrivial(true), PACKUSDW => GENERAL_RW_R, - PCMPESTRM => { panic!("todo: pcmpestrm"); }, + PCMPESTRM => GENERAL_R_R + .set_operand(2, Access::Read) + .set_flags_access(Access::Write) + .set_nontrivial(true), PCMPEQQ => GENERAL_RW_R, PTEST => GENERAL_R_R .set_flags_access(Access::Write), PHMINPOSUW => GENERAL_W_R, - DPPS => { panic!("todo: dpps"); }, - DPPD => { panic!("todo: dppd"); }, - MPSADBW => { panic!("todo: mpsadbw"); }, + DPPS => GENERAL_RW_R + .set_operand(2, Access::Read), + DPPD => GENERAL_RW_R + .set_operand(2, Access::Read), + MPSADBW => GENERAL_RW_R + .set_operand(2, Access::Read), PMOVZXDQ => GENERAL_RW_R, PMOVSXDQ => GENERAL_RW_R, PMOVZXBD => GENERAL_RW_R, @@ -3764,11 +4300,16 @@ fn opcode2behavior(opc: &Opcode) -> Option { .set_operand(2, Access::Read), PMOVSXBW => GENERAL_RW_R, PMOVZXBW => GENERAL_RW_R, - PINSRQ => { panic!("todo: pinsrq"); }, - PINSRD => { panic!("todo: pinsrd"); }, - PINSRB => { panic!("todo: pinsrb"); }, - EXTRACTPS => { panic!("todo: extractps"); }, - INSERTPS => { panic!("todo: insertps"); }, + PINSRQ => GENERAL_RW_R + .set_operand(2, Access::Read), + PINSRD => GENERAL_RW_R + .set_operand(2, Access::Read), + PINSRB => GENERAL_RW_R + .set_operand(2, Access::Read), + EXTRACTPS => GENERAL_W_R + .set_operand(2, Access::Read), + INSERTPS => GENERAL_W_R + .set_operand(2, Access::Read), ROUNDSS => GENERAL_RW_R .set_operand(2, Access::Read), ROUNDSD => GENERAL_RW_R @@ -3785,7 +4326,8 @@ fn opcode2behavior(opc: &Opcode) -> Option { PMINSB => GENERAL_RW_R, PMINUD => GENERAL_RW_R, PMINUW => GENERAL_RW_R, - BLENDW => { panic!("todo: blendw"); }, + // TODO: need to remove; doesn't exist + BLENDW => BehaviorDigest::empty(), PBLENDVB => GENERAL_RW_R .set_implicit_ops(XMM0_READ_IDX), PBLENDW => GENERAL_RW_R @@ -3832,13 +4374,31 @@ fn opcode2behavior(opc: &Opcode) -> Option { LZCNT => GENERAL_W_R .set_flags_access(Access::Write), - CLGI => { panic!("todo: clgi"); }, - STGI => { panic!("todo: stgi"); }, - SKINIT => { panic!("todo: skinit"); }, - VMLOAD => { panic!("todo: vmload"); }, - VMMCALL => { panic!("todo: vmmcall"); }, - VMSAVE => { panic!("todo: vmsave"); }, - VMRUN => { panic!("todo: vmrun"); }, + CLGI => BehaviorDigest::empty() + .set_pl0() + .set_complex(true), + STGI => BehaviorDigest::empty() + .set_pl0() + .set_complex(true), + SKINIT => BehaviorDigest::empty() + .set_pl0() + .set_complex(true) + .set_operand(0, Access::Read), + VMLOAD => BehaviorDigest::empty() + .set_pl0() + .set_complex(true) + .set_operand(0, Access::Read), + VMMCALL => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + VMSAVE => BehaviorDigest::empty() + .set_pl0() + .set_complex(true) + .set_operand(0, Access::Read), + VMRUN => BehaviorDigest::empty() + .set_pl0() + .set_complex(true) + .set_operand(0, Access::Read), INVLPGA => BehaviorDigest::empty() .set_pl0() .set_operand(0, Access::Read) @@ -3848,7 +4408,8 @@ fn opcode2behavior(opc: &Opcode) -> Option { .set_operand(0, Access::Read) .set_operand(1, Access::Read) .set_operand(2, Access::Read), - TLBSYNC => { panic!("todo: tlbsync"); }, + TLBSYNC => BehaviorDigest::empty() + .set_pl0(), MOVBE => GENERAL_W_R, @@ -3857,11 +4418,21 @@ fn opcode2behavior(opc: &Opcode) -> Option { ADOX => GENERAL_RW_R .set_flags_access(Access::ReadWrite), - PREFETCHW => { panic!("todo: prefetchw"); }, + PREFETCHW => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Read), - RDPID => { panic!("todo: rdpid"); }, - VMPTRLD => { panic!("todo: vmptrld"); }, - VMPTRST => { panic!("todo: vmptrst"); }, + RDPID => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Write), + VMPTRLD => BehaviorDigest::empty() + .set_pl0() + .set_operand(0, Access::Read) + .set_complex(true), + VMPTRST => BehaviorDigest::empty() + .set_pl0() + .set_operand(0, Access::Write) + .set_complex(true), BZHI => GENERAL_W_R_R .set_flags_access(Access::Write), @@ -3876,20 +4447,55 @@ fn opcode2behavior(opc: &Opcode) -> Option { PDEP => GENERAL_W_R_R, PEXT => GENERAL_W_R_R, RORX => GENERAL_W_R_R, - XRSTORS => { panic!("todo: xrstors"); }, - XRSTORS64 => { panic!("todo: xrstors64"); }, - XSAVEC => { panic!("todo: xsavec"); }, - XSAVEC64 => { panic!("todo: xsavec64"); }, - XSAVES => { panic!("todo: xsaves"); }, - XSAVES64 => { panic!("todo: xsaves64"); }, - - RDFSBASE => { panic!("todo: rdfsbase"); }, - RDGSBASE => { panic!("todo: rdgsbase"); }, - WRFSBASE => { panic!("todo: wrfsbase"); }, - WRGSBASE => { panic!("todo: wrgsbase"); }, + XRSTORS => BehaviorDigest::empty() + .set_pl0() + .set_complex(true) + .set_operand(0, Access::Read) + .set_implicit_ops(READ_EDX_EAX_IDX), + XRSTORS64 => BehaviorDigest::empty() + .set_pl0() + .set_complex(true) + .set_operand(0, Access::Read) + .set_implicit_ops(READ_EDX_EAX_IDX), + XSAVEC => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true) + .set_operand(0, Access::Write) + .set_implicit_ops(READ_EDX_EAX_IDX), + XSAVEC64 => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true) + .set_operand(0, Access::Write) + .set_implicit_ops(READ_EDX_EAX_IDX), + XSAVES => BehaviorDigest::empty() + .set_pl0() + .set_complex(true) + .set_operand(0, Access::Write) + .set_implicit_ops(READ_EDX_EAX_IDX), + XSAVES64 => BehaviorDigest::empty() + .set_pl0() + .set_complex(true) + .set_operand(0, Access::Write) + .set_implicit_ops(READ_EDX_EAX_IDX), + + RDFSBASE => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Write), + RDGSBASE => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Write), + WRFSBASE => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Read), + WRGSBASE => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Read), CRC32 => GENERAL_RW_R, - SALC => { panic!("todo: salc"); }, + SALC => BehaviorDigest::empty() + .set_pl_any() + .set_flags_access(Access::Read) + .set_implicit_ops(WRITE_AL_IDX), XLAT => BehaviorDigest::empty() .set_implicit_ops(XLAT_IDX) .set_pl_any(), @@ -3995,11 +4601,24 @@ fn opcode2behavior(opc: &Opcode) -> Option { .set_pl_any(), FNOP => BehaviorDigest::empty() .set_pl_any(), - FNSAVE => { panic!("todo: fnsave"); }, - FNSTCW => { panic!("todo: fnstcw"); }, - FNSTENV => { panic!("todo: fnstenv"); }, - FNSTOR => { panic!("todo: fnstor"); }, - FNSTSW => { panic!("todo: fnstsw"); }, + FNSAVE => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Write) + .set_complex(true), + FNSTCW => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Write) + .set_complex(true), + FNSTENV => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Write) + .set_complex(true), + // TODO: never produced.. + FNSTOR => BehaviorDigest::empty(), + FNSTSW => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Write) + .set_complex(true), // TODO: read st(1) with atan(st(1)/st(0)) and pop FPATAN => BehaviorDigest::empty() .set_pl_any(), @@ -4015,7 +4634,10 @@ fn opcode2behavior(opc: &Opcode) -> Option { // TODO: read st(0), write, push? FRNDINT => BehaviorDigest::empty() .set_pl_any(), - FRSTOR => { panic!("todo: frstor"); }, + FRSTOR => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Write) + .set_complex(true), // TODO: read st(0), st(1) FSCALE => BehaviorDigest::empty() .set_pl_any(), @@ -4060,10 +4682,25 @@ fn opcode2behavior(opc: &Opcode) -> Option { FYL2XP1 => BehaviorDigest::empty() .set_pl_any(), - LOOPNZ => { panic!("todo: loopnz"); }, - LOOPZ => { panic!("todo: loopz"); }, - LOOP => { panic!("todo: loop"); }, - JRCXZ => { panic!("todo: jrcxz"); }, + LOOPNZ => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Read) + .set_flags_access(Access::ReadWrite) + .set_nontrivial(true), + LOOPZ => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Read) + .set_flags_access(Access::ReadWrite) + .set_nontrivial(true), + LOOP => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Read) + .set_flags_access(Access::ReadWrite) + .set_nontrivial(true), + JRCXZ => BehaviorDigest::empty() + .set_pl_any() + .set_operand(0, Access::Read) + .set_nontrivial(true), // started shipping in Tremont, 2020 sept 23 // while this instruction is marked "write, read", the written first operand is a register @@ -4073,48 +4710,71 @@ fn opcode2behavior(opc: &Opcode) -> Option { MOVDIRI => GENERAL_W_R, // started shipping in Tiger Lake, 2020 sept 2 - AESDEC128KL => { panic!("todo: aesdec128kl"); }, - AESDEC256KL => { panic!("todo: aesdec256kl"); }, - AESDECWIDE128KL => { panic!("todo: aesdecwide128kl"); }, - AESDECWIDE256KL => { panic!("todo: aesdecwide256kl"); }, - AESENC128KL => { panic!("todo: aesenc128kl"); }, - AESENC256KL => { panic!("todo: aesenc256kl"); }, - AESENCWIDE128KL => { panic!("todo: aesencwide128kl"); }, - AESENCWIDE256KL => { panic!("todo: aesencwide256kl"); }, - ENCODEKEY128 => { panic!("todo: encodekey128"); }, - ENCODEKEY256 => { panic!("todo: encodekey256"); }, - LOADIWKEY => { panic!("todo: loadiwkey"); }, + AESDEC128KL => GENERAL_RW_R + .set_flags_access(Access::Write), + AESDEC256KL => GENERAL_RW_R + .set_flags_access(Access::Write), + AESDECWIDE128KL => GENERAL_R + .set_implicit_ops(RW_XMM0TO7_IDX) + .set_flags_access(Access::Write), + AESDECWIDE256KL => GENERAL_R + .set_implicit_ops(RW_XMM0TO7_IDX) + .set_flags_access(Access::Write), + AESENC128KL => GENERAL_RW_R + .set_flags_access(Access::Write), + AESENC256KL => GENERAL_RW_R + .set_flags_access(Access::Write), + AESENCWIDE128KL => GENERAL_R + .set_implicit_ops(RW_XMM0TO7_IDX) + .set_flags_access(Access::Write), + AESENCWIDE256KL => GENERAL_R + .set_implicit_ops(RW_XMM0TO7_IDX) + .set_flags_access(Access::Write), + ENCODEKEY128 => GENERAL_W_R + .set_implicit_ops(ENCODEKEY_IDX) + .set_flags_access(Access::Write), + ENCODEKEY256 => GENERAL_W_R + .set_implicit_ops(ENCODEKEY_IDX) + .set_flags_access(Access::Write), + LOADIWKEY => GENERAL_R_R + .set_implicit_ops(LOADIWKEY_IDX) + .set_flags_access(Access::Write), // unsure - HRESET => { panic!("todo: hreset"); }, + HRESET => BehaviorDigest::empty() + .set_operand(0, Access::Read) // but really, "explicit imm8 operand is ignored" + .set_implicit_ops(READ_EAX_IDX) + .set_complex(true), // 3dnow. note these are yet untested! + // the 3dnow DSP instructions (pi2fw, pf2iw, pfnacc, pfpnacc, pswapd) + // are even more untested. FEMMS => GENERAL, - PI2FW => { panic!("todo: pi2fw"); }, - PI2FD => { panic!("todo: pi2fd"); }, - PF2IW => { panic!("todo: pf2iw"); }, - PF2ID => { panic!("todo: pf2id"); }, - PMULHRW => { panic!("todo: pmulhrw"); }, - PFCMPGE => { panic!("todo: pfcmpge"); }, - PFMIN => { panic!("todo: pfmin"); }, - PFRCP => { panic!("todo: pfrcp"); }, - PFRSQRT => { panic!("todo: pfrsqrt"); }, - PFSUB => { panic!("todo: pfsub"); }, - PFADD => { panic!("todo: pfadd"); }, - PFCMPGT => { panic!("todo: pfcmpgt"); }, - PFMAX => { panic!("todo: pfmax"); }, - PFRCPIT1 => { panic!("todo: pfrcpit1"); }, - PFRSQIT1 => { panic!("todo: pfrsqit1"); }, - PFSUBR => { panic!("todo: pfsubr"); }, - PFACC => { panic!("todo: pfacc"); }, - PFCMPEQ => { panic!("todo: pfcmpeq"); }, - PFMUL => { panic!("todo: pfmul"); }, - PFMULHRW => { panic!("todo: pfmulhrw"); }, - PFRCPIT2 => { panic!("todo: pfrcpit2"); }, - PFNACC => { panic!("todo: pfnacc"); }, - PFPNACC => { panic!("todo: pfpnacc"); }, - PSWAPD => { panic!("todo: pswapd"); }, - PAVGUSB => { panic!("todo: pavgusb"); }, + PI2FW => GENERAL_RW_R, + PI2FD => GENERAL_W_R, + PF2IW => GENERAL_RW_R, + PF2ID => GENERAL_W_R, + PMULHRW => GENERAL_RW_R, + PFCMPGE => GENERAL_RW_R, + PFMIN => GENERAL_RW_R, + PFRCP => GENERAL_W_R, + PFRSQRT => GENERAL_W_R, + PFSUB => GENERAL_RW_R, + PFADD => GENERAL_RW_R, + PFCMPGT => GENERAL_RW_R, + PFMAX => GENERAL_RW_R, + PFRCPIT1 => GENERAL_RW_R, + PFRSQIT1 => GENERAL_RW_R, + PFSUBR => GENERAL_RW_R, + PFACC => GENERAL_RW_R, + PFCMPEQ => GENERAL_RW_R, + PFMUL => GENERAL_RW_R, + PFMULHRW => GENERAL_RW_R, + PFRCPIT2 => GENERAL_RW_R, + PFNACC => GENERAL_RW_R, + PFPNACC => GENERAL_RW_R, + PSWAPD => GENERAL_RW_RW, + PAVGUSB => GENERAL_RW_R, // ENQCMD // similar to movdir64b, but more complex; the first operand is also an address for a @@ -4138,7 +4798,10 @@ fn opcode2behavior(opc: &Opcode) -> Option { INVPCID => GENERAL_R_R, // PTWRITE - PTWRITE => { panic!("todo: ptwrite"); }, + // TODO: untested + PTWRITE => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), // GFNI GF2P8AFFINEQB => GENERAL_RW_R @@ -4148,45 +4811,101 @@ fn opcode2behavior(opc: &Opcode) -> Option { GF2P8MULB => GENERAL_RW_R, // CET - WRUSS => { panic!("todo: wruss"); }, - WRSS => { panic!("todo: wrss"); }, - INCSSP => { panic!("todo: incssp"); }, - SAVEPREVSSP => { panic!("todo: saveprevssp"); }, - SETSSBSY => { panic!("todo: setssbsy"); }, - CLRSSBSY => { panic!("todo: clrssbsy"); }, - RSTORSSP => { panic!("todo: rstorssp"); }, - ENDBR64 => { panic!("todo: endbr64"); }, - ENDBR32 => { panic!("todo: endbr32"); }, + WRUSS => GENERAL_W_R + .set_pl0() + .set_complex(true), + WRSS => GENERAL_W_R + .set_pl_special() + .set_complex(true), + INCSSP => GENERAL_R + .set_pl_special() + .set_complex(true), + SAVEPREVSSP => BehaviorDigest::empty() + .set_pl_special() + .set_complex(true), + SETSSBSY => BehaviorDigest::empty() + .set_pl0() + .set_complex(true), + CLRSSBSY => BehaviorDigest::empty() + .set_pl0() + .set_operand(0, Access::ReadWrite) + .set_flags_access(Access::Write) + .set_complex(true), + RSTORSSP => BehaviorDigest::empty() + .set_pl_special() + .set_operand(0, Access::ReadWrite) + .set_flags_access(Access::Write) + .set_complex(true), + ENDBR64 => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + ENDBR32 => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), // TDX - TDCALL => { panic!("todo: tdcall"); }, - SEAMRET => { panic!("todo: seamret"); }, - SEAMOPS => { panic!("todo: seamops"); }, - SEAMCALL => { panic!("todo: seamcall"); }, + TDCALL => BehaviorDigest::empty() + .set_pl0() + .set_complex(true), + SEAMRET => BehaviorDigest::empty() + .set_pl0() + .set_complex(true), + SEAMOPS => BehaviorDigest::empty() + .set_pl0() + .set_complex(true), + SEAMCALL => BehaviorDigest::empty() + .set_pl0() + .set_complex(true), // WAITPKG - TPAUSE => { panic!("todo: tpause"); }, - UMONITOR => { panic!("todo: umonitor"); }, - UMWAIT => { panic!("todo: umwait"); }, + TPAUSE => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + UMONITOR => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + UMWAIT => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), // UINTR - UIRET => { panic!("todo: uiret"); }, - TESTUI => { panic!("todo: testui"); }, - CLUI => { panic!("todo: clui"); }, - STUI => { panic!("todo: stui"); }, - SENDUIPI => { panic!("todo: senduipi"); }, + UIRET => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + TESTUI => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + CLUI => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + STUI => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), + SENDUIPI => BehaviorDigest::empty() + .set_pl_any() + .set_complex(true), // TSXLDTRK - XSUSLDTRK => { panic!("todo: xsusldtrk"); }, - XRESLDTRK => { panic!("todo: xresldtrk"); }, + // arguably these should be considered "complex" similar to `uintr` instructions above, but + // they are not (at this time). the arbitrary distinction here is that x{sus,res}ldtrk + // operate on nothing *but* the trackedness of loads, so interactions with this processor + // state can be easily determined by looking for these instructions. additionally, a user + // interested in this state is probably already looking for these instructions, so + // declaring them complex adds burden to all other use for no benefit. + XSUSLDTRK => BehaviorDigest::empty() + .set_pl_any(), + XRESLDTRK => BehaviorDigest::empty() + .set_pl_any(), // AVX512F - VALIGND => { panic!("todo: valignd"); }, - VALIGNQ => { panic!("todo: valignq"); }, + VALIGND => GENERAL_W_R_R + .set_operand(3, Access::Read), + VALIGNQ => GENERAL_W_R_R + .set_operand(3, Access::Read), VBLENDMPD => GENERAL_W_R_R, VBLENDMPS => GENERAL_W_R_R, - VCOMPRESSPD => { panic!("todo: vcompresspd"); }, - VCOMPRESSPS => { panic!("todo: vcompressps"); }, + VCOMPRESSPD => GENERAL_W_R, + VCOMPRESSPS => GENERAL_W_R, VCVTPD2UDQ => GENERAL_W_R, VCVTTPD2UDQ => GENERAL_W_R, VCVTPS2UDQ => GENERAL_W_R, @@ -4201,39 +4920,58 @@ fn opcode2behavior(opc: &Opcode) -> Option { VCVTUDQ2PS => GENERAL_W_R, VCVTUSI2USD => GENERAL_W_R, VCVTUSI2USS => GENERAL_W_R, - VEXPANDPD => { panic!("todo: vexpandpd"); }, - VEXPANDPS => { panic!("todo: vexpandps"); }, - VEXTRACTF32X4 => { panic!("todo: vextractf32x4"); }, - VEXTRACTF64X4 => { panic!("todo: vextractf64x4"); }, - VEXTRACTI32X4 => { panic!("todo: vextracti32x4"); }, - VEXTRACTI64X4 => { panic!("todo: vextracti64x4"); }, - VFIXUPIMMPD => { panic!("todo: vfixupimmpd"); }, - VFIXUPIMMPS => { panic!("todo: vfixupimmps"); }, - VFIXUPIMMSD => { panic!("todo: vfixupimmsd"); }, - VFIXUPIMMSS => { panic!("todo: vfixupimmss"); }, + VEXPANDPD => GENERAL_W_R, + VEXPANDPS => GENERAL_W_R, + VEXTRACTF32X4 => GENERAL_W_R + .set_operand(2, Access::Read), + VEXTRACTF64X4 => GENERAL_W_R + .set_operand(2, Access::Read), + VEXTRACTI32X4 => GENERAL_W_R + .set_operand(2, Access::Read), + VEXTRACTI64X4 => GENERAL_W_R + .set_operand(2, Access::Read), + VFIXUPIMMPD => GENERAL_RW_R_R + .set_operand(3, Access::Read), + VFIXUPIMMPS => GENERAL_RW_R_R + .set_operand(3, Access::Read), + VFIXUPIMMSD => GENERAL_RW_R_R + .set_operand(3, Access::Read), + VFIXUPIMMSS => GENERAL_RW_R_R + .set_operand(3, Access::Read), VGETEXPPD => GENERAL_W_R, VGETEXPPS => GENERAL_W_R, VGETEXPSD => GENERAL_W_R_R, VGETEXPSS => GENERAL_W_R_R, - VGETMANTPD => GENERAL_W_R, - VGETMANTPS => GENERAL_W_R, - VGETMANTSD => GENERAL_W_R, - VGETMANTSS => GENERAL_W_R, - VINSERTF32X4 => { panic!("todo: vinsertf32x4"); }, - VINSERTF64X4 => { panic!("todo: vinsertf64x4"); }, - VINSERTI64X4 => { panic!("todo: vinserti64x4"); }, + VGETMANTPD => GENERAL_W_R + .set_operand(2, Access::Read), + VGETMANTPS => GENERAL_W_R + .set_operand(2, Access::Read), + VGETMANTSD => GENERAL_W_R_R + .set_operand(3, Access::Read), + VGETMANTSS => GENERAL_W_R_R + .set_operand(3, Access::Read), + VINSERTF32X4 => GENERAL_W_R_R + .set_operand(3, Access::Read), + VINSERTF64X4 => GENERAL_W_R_R + .set_operand(3, Access::Read), + VINSERTI64X4 => GENERAL_W_R_R + .set_operand(3, Access::Read), VMOVDQA32 => GENERAL_W_R, VMOVDQA64 => GENERAL_W_R, VMOVDQU32 => GENERAL_W_R, VMOVDQU64 => GENERAL_W_R, VPBLENDMD => GENERAL_W_R_R, VPBLENDMQ => GENERAL_W_R_R, - VPCMPD => { panic!("todo: vpcmpd"); }, - VPCMPUD => { panic!("todo: vpcmpud"); }, - VPCMPQ => { panic!("todo: vpcmpq"); }, - VPCMPUQ => { panic!("todo: vpcmpuq"); }, - VPCOMPRESSQ => { panic!("todo: vpcompressq"); }, - VPCOMPRESSD => { panic!("todo: vpcompressd"); }, + VPCMPD => GENERAL_W_R_R + .set_operand(3, Access::Read), + VPCMPUD => GENERAL_W_R_R + .set_operand(3, Access::Read), + VPCMPQ => GENERAL_W_R_R + .set_operand(3, Access::Read), + VPCMPUQ => GENERAL_W_R_R + .set_operand(3, Access::Read), + VPCOMPRESSQ => GENERAL_W_R, + VPCOMPRESSD => GENERAL_W_R, VPERMI2D => GENERAL_W_R_R, VPERMI2Q => GENERAL_W_R_R, VPERMI2PD => GENERAL_W_R_R, @@ -4273,38 +5011,50 @@ fn opcode2behavior(opc: &Opcode) -> Option { .set_complex(true), VPSCATTERQQ => BehaviorDigest::empty() .set_complex(true), - VPSRAQ => { panic!("todo: vpsraq"); }, + VPSRAQ => GENERAL_W_R_R, VPSRAVQ => GENERAL_W_R_R, VPTESTNMD => GENERAL_W_R_R, VPTESTNMQ => GENERAL_W_R_R, - VPTERNLOGD => { panic!("todo: vpternlogd"); }, - VPTERNLOGQ => { panic!("todo: vpternlogq"); }, + VPTERNLOGD => GENERAL_W_R_R + .set_operand(3, Access::Read), + VPTERNLOGQ => GENERAL_W_R_R + .set_operand(3, Access::Read), VPTESTMD => GENERAL_W_R_R, VPTESTMQ => GENERAL_W_R_R, VRCP14PD => GENERAL_W_R, VRCP14PS => GENERAL_W_R, VRCP14SD => GENERAL_W_R_R, VRCP14SS => GENERAL_W_R_R, - VRNDSCALEPD => { panic!("todo: vrndscalepd"); }, - VRNDSCALEPS => { panic!("todo: vrndscaleps"); }, - VRNDSCALESD => { panic!("todo: vrndscalesd"); }, - VRNDSCALESS => { panic!("todo: vrndscaless"); }, + VRNDSCALEPD => GENERAL_W_R + .set_operand(2, Access::Read), + VRNDSCALEPS => GENERAL_W_R + .set_operand(2, Access::Read), + VRNDSCALESD => GENERAL_W_R_R + .set_operand(3, Access::Read), + VRNDSCALESS => GENERAL_W_R_R + .set_operand(3, Access::Read), VRSQRT14PD => GENERAL_W_R, VRSQRT14PS => GENERAL_W_R, VRSQRT14SD => GENERAL_W_R_R, VRSQRT14SS => GENERAL_W_R_R, - VSCALEDPD => { panic!("todo: vscaledpd"); }, - VSCALEDPS => { panic!("todo: vscaledps"); }, - VSCALEDSD => { panic!("todo: vscaledsd"); }, - VSCALEDSS => { panic!("todo: vscaledss"); }, - VSCATTERDD => { panic!("todo: vscatterdd"); }, - VSCATTERDQ => { panic!("todo: vscatterdq"); }, - VSCATTERQD => { panic!("todo: vscatterqd"); }, - VSCATTERQQ => { panic!("todo: vscatterqq"); }, - VSHUFF32X4 => { panic!("todo: vshuff32x4"); }, - VSHUFF64X2 => { panic!("todo: vshuff64x2"); }, - VSHUFI32X4 => { panic!("todo: vshufi32x4"); }, - VSHUFI64X2 => { panic!("todo: vshufi64x2"); }, + // vvv --- these don't exist.. + VSCALEDPD => BehaviorDigest::empty(), + VSCALEDPS => BehaviorDigest::empty(), + VSCALEDSD => BehaviorDigest::empty(), + VSCALEDSS => BehaviorDigest::empty(), + VSCATTERDD => BehaviorDigest::empty(), + VSCATTERDQ => BehaviorDigest::empty(), + VSCATTERQD => BehaviorDigest::empty(), + VSCATTERQQ => BehaviorDigest::empty(), + // ^^^ --- these don't exist.. + VSHUFF32X4 => GENERAL_W_R_R + .set_operand(3, Access::Read), + VSHUFF64X2 => GENERAL_W_R_R + .set_operand(3, Access::Read), + VSHUFI32X4 => GENERAL_W_R_R + .set_operand(3, Access::Read), + VSHUFI64X2 => GENERAL_W_R_R + .set_operand(3, Access::Read), // AVX512DQ VCVTTPD2QQ => GENERAL_W_R, @@ -4317,44 +5067,65 @@ fn opcode2behavior(opc: &Opcode) -> Option { VCVTPS2UQQ => GENERAL_W_R, VCVTUQQ2PD => GENERAL_W_R, VCVTUQQ2PS => GENERAL_W_R, - VEXTRACTF64X2 => { panic!("todo: vextractf64x2"); }, - VEXTRACTI64X2 => { panic!("todo: vextracti64x2"); }, - VFPCLASSPD => { panic!("todo: vfpclasspd"); }, - VFPCLASSPS => { panic!("todo: vfpclassps"); }, - VFPCLASSSD => { panic!("todo: vfpclasssd"); }, - VFPCLASSSS => { panic!("todo: vfpclassss"); }, - VINSERTF64X2 => { panic!("todo: vinsertf64x2"); }, - VINSERTI64X2 => { panic!("todo: vinserti64x2"); }, - VPMOVM2D => { panic!("todo: vpmovm2d"); }, - VPMOVM2Q => { panic!("todo: vpmovm2q"); }, - VPMOVB2D => { panic!("todo: vpmovb2d"); }, - VPMOVQ2M => { panic!("todo: vpmovq2m"); }, - VRANGEPD => { panic!("todo: vrangepd"); }, - VRANGEPS => { panic!("todo: vrangeps"); }, - VRANGESD => { panic!("todo: vrangesd"); }, - VRANGESS => { panic!("todo: vrangess"); }, - VREDUCEPD => { panic!("todo: vreducepd"); }, - VREDUCEPS => { panic!("todo: vreduceps"); }, - VREDUCESD => { panic!("todo: vreducesd"); }, - VREDUCESS => { panic!("todo: vreducess"); }, + VEXTRACTF64X2 => GENERAL_W_R + .set_operand(2, Access::Read), + VEXTRACTI64X2 => GENERAL_W_R + .set_operand(2, Access::Read), + VFPCLASSPD => GENERAL_W_R + .set_operand(2, Access::Read), + VFPCLASSPS => GENERAL_W_R + .set_operand(2, Access::Read), + VFPCLASSSD => GENERAL_W_R + .set_operand(2, Access::Read), + VFPCLASSSS => GENERAL_W_R + .set_operand(2, Access::Read), + VINSERTF64X2 => GENERAL_W_R_R + .set_operand(3, Access::Read), + VINSERTI64X2 => GENERAL_W_R_R + .set_operand(3, Access::Read), + VPMOVM2D => GENERAL_W_R, + VPMOVM2Q => GENERAL_W_R, + VPMOVB2D => GENERAL_W_R, + VPMOVQ2M => GENERAL_W_R, + VRANGEPD => GENERAL_W_R_R + .set_operand(3, Access::Read), + VRANGEPS => GENERAL_W_R_R + .set_operand(3, Access::Read), + VRANGESD => GENERAL_W_R_R + .set_operand(3, Access::Read), + VRANGESS => GENERAL_W_R_R + .set_operand(3, Access::Read), + VREDUCEPD => GENERAL_W_R_R + .set_operand(2, Access::Read), + VREDUCEPS => GENERAL_W_R_R + .set_operand(2, Access::Read), + VREDUCESD => GENERAL_W_R_R + .set_operand(3, Access::Read), + VREDUCESS => GENERAL_W_R_R + .set_operand(3, Access::Read), // AVX512BW - VDBPSADBW => { panic!("todo: vdbpsadbw"); }, + VDBPSADBW => GENERAL_W_R_R + .set_operand(3, Access::Read), VMOVDQU8 => GENERAL_W_R, VMOVDQU16 => GENERAL_W_R, VPBLENDMB => GENERAL_W_R_R, VPBLENDMW => GENERAL_W_R_R, - VPCMPB => { panic!("todo: vpcmpb"); }, - VPCMPUB => { panic!("todo: vpcmpub"); }, - VPCMPW => { panic!("todo: vpcmpw"); }, - VPCMPUW => { panic!("todo: vpcmpuw"); }, - VPERMW => { panic!("todo: vpermw"); }, + VPCMPB => GENERAL_W_R_R + .set_operand(3, Access::Read), + VPCMPUB => GENERAL_W_R_R + .set_operand(3, Access::Read), + VPCMPW => GENERAL_W_R_R + .set_operand(3, Access::Read), + VPCMPUW => GENERAL_W_R_R + .set_operand(3, Access::Read), + VPERMW => GENERAL_W_R_R, VPERMI2B => GENERAL_W_R_R, VPERMI2W => GENERAL_W_R_R, - VPMOVM2B => { panic!("todo: vpmovm2b"); }, - VPMOVM2W => { panic!("todo: vpmovm2w"); }, - VPMOVB2M => { panic!("todo: vpmovb2m"); }, - VPMOVW2M => { panic!("todo: vpmovw2m"); }, + VPMOVM2B => GENERAL_W_R, + VPMOVM2W => GENERAL_W_R, + VPMOVB2M => GENERAL_W_R, + VPMOVW2M => GENERAL_W_R, VPMOVSWB => GENERAL_W_R, VPMOVUSWB => GENERAL_W_R, VPSLLVW => GENERAL_W_R_R, @@ -4366,114 +5137,167 @@ fn opcode2behavior(opc: &Opcode) -> Option { VPTESTMW => GENERAL_W_R_R, // AVX512CD - VPBROADCASTM => { panic!("todo: vpbroadcastm"); }, - VPCONFLICTD => { panic!("todo: vpconflictd"); }, - VPCONFLICTQ => { panic!("todo: vpconflictq"); }, + // TODO: this one does not exist + VPBROADCASTM => BehaviorDigest::empty(), + VPCONFLICTD => GENERAL_W_R, + VPCONFLICTQ => GENERAL_W_R, VPLZCNTD => GENERAL_W_R, VPLZCNTQ => GENERAL_W_R, - KUNPCKBW => { panic!("todo: kunpckbw"); }, - KUNPCKWD => { panic!("todo: kunpckwd"); }, - KUNPCKDQ => { panic!("todo: kunpckdq"); }, - - KADDB => { panic!("todo: kaddb"); }, - KANDB => { panic!("todo: kandb"); }, - KANDNB => { panic!("todo: kandnb"); }, - KMOVB => { panic!("todo: kmovb"); }, - KNOTB => { panic!("todo: knotb"); }, - KORB => { panic!("todo: korb"); }, - KORTESTB => { panic!("todo: kortestb"); }, - KSHIFTLB => { panic!("todo: kshiftlb"); }, - KSHIFTRB => { panic!("todo: kshiftrb"); }, - KTESTB => { panic!("todo: ktestb"); }, - KXNORB => { panic!("todo: kxnorb"); }, - KXORB => { panic!("todo: kxorb"); }, - KADDW => { panic!("todo: kaddw"); }, - KANDW => { panic!("todo: kandw"); }, - KANDNW => { panic!("todo: kandnw"); }, - KMOVW => { panic!("todo: kmovw"); }, - KNOTW => { panic!("todo: knotw"); }, - KORW => { panic!("todo: korw"); }, - KORTESTW => { panic!("todo: kortestw"); }, - KSHIFTLW => { panic!("todo: kshiftlw"); }, - KSHIFTRW => { panic!("todo: kshiftrw"); }, - KTESTW => { panic!("todo: ktestw"); }, - KXNORW => { panic!("todo: kxnorw"); }, - KXORW => { panic!("todo: kxorw"); }, - KADDD => { panic!("todo: kaddd"); }, - KANDD => { panic!("todo: kandd"); }, - KANDND => { panic!("todo: kandnd"); }, - KMOVD => { panic!("todo: kmovd"); }, - KNOTD => { panic!("todo: knotd"); }, - KORD => { panic!("todo: kord"); }, - KORTESTD => { panic!("todo: kortestd"); }, - KSHIFTLD => { panic!("todo: kshiftld"); }, - KSHIFTRD => { panic!("todo: kshiftrd"); }, - KTESTD => { panic!("todo: ktestd"); }, - KXNORD => { panic!("todo: kxnord"); }, - KXORD => { panic!("todo: kxord"); }, - KADDQ => { panic!("todo: kaddq"); }, - KANDQ => { panic!("todo: kandq"); }, - KANDNQ => { panic!("todo: kandnq"); }, - KMOVQ => { panic!("todo: kmovq"); }, - KNOTQ => { panic!("todo: knotq"); }, - KORQ => { panic!("todo: korq"); }, - KORTESTQ => { panic!("todo: kortestq"); }, - KSHIFTLQ => { panic!("todo: kshiftlq"); }, - KSHIFTRQ => { panic!("todo: kshiftrq"); }, - KTESTQ => { panic!("todo: ktestq"); }, - KXNORQ => { panic!("todo: kxnorq"); }, - KXORQ => { panic!("todo: kxorq"); }, + KUNPCKBW => GENERAL_W_R_R, + KUNPCKWD => GENERAL_W_R_R, + KUNPCKDQ => GENERAL_W_R_R, + + KADDB => GENERAL_W_R_R, + KANDB => GENERAL_W_R_R, + KANDNB => GENERAL_W_R_R, + KMOVB => GENERAL_W_R, + KNOTB => GENERAL_W_R, + KORB => GENERAL_W_R_R, + KORTESTB => GENERAL_R_R + .set_flags_access(Access::Write), + KSHIFTLB => GENERAL_W_R_R, + KSHIFTRB => GENERAL_W_R_R, + KTESTB => GENERAL_R_R + .set_flags_access(Access::Write), + KXNORB => GENERAL_W_R_R, + KXORB => GENERAL_W_R_R, + KADDW => GENERAL_W_R_R, + KANDW => GENERAL_W_R_R, + KANDNW => GENERAL_W_R_R, + KMOVW => GENERAL_W_R, + KNOTW => GENERAL_W_R, + KORW => GENERAL_W_R_R, + KORTESTW => GENERAL_W_R_R + .set_flags_access(Access::Write), + KSHIFTLW => GENERAL_W_R_R, + KSHIFTRW => GENERAL_W_R_R, + KTESTW => GENERAL_W_R_R + .set_flags_access(Access::Write), + KXNORW => GENERAL_W_R_R, + KXORW => GENERAL_W_R_R, + KADDD => GENERAL_W_R_R, + KANDD => GENERAL_W_R_R, + KANDND => GENERAL_W_R_R, + KMOVD => GENERAL_W_R, + KNOTD => GENERAL_W_R, + KORD => GENERAL_W_R_R, + KORTESTD => GENERAL_W_R_R + .set_flags_access(Access::Write), + KSHIFTLD => GENERAL_W_R_R, + KSHIFTRD => GENERAL_W_R_R, + KTESTD => GENERAL_W_R_R + .set_flags_access(Access::Write), + KXNORD => GENERAL_W_R_R, + KXORD => GENERAL_W_R_R, + KADDQ => GENERAL_W_R_R, + KANDQ => GENERAL_W_R_R, + KANDNQ => GENERAL_W_R_R, + KMOVQ => GENERAL_W_R, + KNOTQ => GENERAL_W_R, + KORQ => GENERAL_W_R_R, + KORTESTQ => GENERAL_W_R_R + .set_flags_access(Access::Write), + KSHIFTLQ => GENERAL_W_R_R, + KSHIFTRQ => GENERAL_W_R_R, + KTESTQ => GENERAL_W_R_R + .set_flags_access(Access::Write), + KXNORQ => GENERAL_W_R_R, + KXORQ => GENERAL_W_R_R, // AVX512ER - VEXP2PD => { panic!("todo: vexp2pd"); }, - VEXP2PS => { panic!("todo: vexp2ps"); }, - VEXP2SD => { panic!("todo: vexp2sd"); }, - VEXP2SS => { panic!("todo: vexp2ss"); }, - VRCP28PD => { panic!("todo: vrcp28pd"); }, - VRCP28PS => { panic!("todo: vrcp28ps"); }, - VRCP28SD => { panic!("todo: vrcp28sd"); }, - VRCP28SS => { panic!("todo: vrcp28ss"); }, - VRSQRT28PD => { panic!("todo: vrsqrt28pd"); }, - VRSQRT28PS => { panic!("todo: vrsqrt28ps"); }, - VRSQRT28SD => { panic!("todo: vrsqrt28sd"); }, - VRSQRT28SS => { panic!("todo: vrsqrt28ss"); }, + VEXP2PD => GENERAL_W_R, + VEXP2PS => GENERAL_W_R, + // TODO: well, this one isn't real. + VEXP2SD => BehaviorDigest::empty(), + // TODO: or this one. + VEXP2SS => BehaviorDigest::empty(), + VRCP28PD => GENERAL_W_R, + VRCP28PS => GENERAL_W_R, + VRCP28SD => GENERAL_W_R_R, + VRCP28SS => GENERAL_W_R_R, + VRSQRT28PD => GENERAL_W_R, + VRSQRT28PS => GENERAL_W_R, + VRSQRT28SD => GENERAL_W_R_R, + VRSQRT28SS => GENERAL_W_R_R, // AVX512PF - VGATHERPF0DPD => { panic!("todo: vgatherpf0dpd"); }, - VGATHERPF0DPS => { panic!("todo: vgatherpf0dps"); }, - VGATHERPF0QPD => { panic!("todo: vgatherpf0qpd"); }, - VGATHERPF0QPS => { panic!("todo: vgatherpf0qps"); }, - VGATHERPF1DPD => { panic!("todo: vgatherpf1dpd"); }, - VGATHERPF1DPS => { panic!("todo: vgatherpf1dps"); }, - VGATHERPF1QPD => { panic!("todo: vgatherpf1qpd"); }, - VGATHERPF1QPS => { panic!("todo: vgatherpf1qps"); }, - VSCATTERPF0DPD => { panic!("todo: vscatterpf0dpd"); }, - VSCATTERPF0DPS => { panic!("todo: vscatterpf0dps"); }, - VSCATTERPF0QPD => { panic!("todo: vscatterpf0qpd"); }, - VSCATTERPF0QPS => { panic!("todo: vscatterpf0qps"); }, - VSCATTERPF1DPD => { panic!("todo: vscatterpf1dpd"); }, - VSCATTERPF1DPS => { panic!("todo: vscatterpf1dps"); }, - VSCATTERPF1QPD => { panic!("todo: vscatterpf1qpd"); }, - VSCATTERPF1QPS => { panic!("todo: vscatterpf1qps"); }, + VGATHERPF0DPD => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), + VGATHERPF0DPS => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), + VGATHERPF0QPD => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), + VGATHERPF0QPS => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), + VGATHERPF1DPD => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), + VGATHERPF1DPS => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), + VGATHERPF1QPD => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), + VGATHERPF1QPS => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), + VSCATTERPF0DPD => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), + VSCATTERPF0DPS => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), + VSCATTERPF0QPD => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), + VSCATTERPF0QPS => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), + VSCATTERPF1DPD => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), + VSCATTERPF1DPS => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), + VSCATTERPF1QPD => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), + VSCATTERPF1QPS => BehaviorDigest::empty() + .set_operand(0, Access::Read) + .set_complex(true), // MPX - BNDMK => { panic!("todo: bndmk"); }, - BNDCL => { panic!("todo: bndcl"); }, - BNDCU => { panic!("todo: bndcu"); }, - BNDCN => { panic!("todo: bndcn"); }, - BNDMOV => { panic!("todo: bndmov"); }, - BNDLDX => { panic!("todo: bndldx"); }, - BNDSTX => { panic!("todo: bndstx"); }, - - VGF2P8AFFINEQB => { panic!("todo: vgf2p8affineqb"); }, - VGF2P8AFFINEINVQB => { panic!("todo: vgf2p8affineinvqb"); }, - VPSHRDQ => { panic!("todo: vpshrdq"); }, - VPSHRDD => { panic!("todo: vpshrdd"); }, - VPSHRDW => { panic!("todo: vpshrdw"); }, - VPSHLDQ => { panic!("todo: vpshldq"); }, - VPSHLDD => { panic!("todo: vpshldd"); }, - VPSHLDW => { panic!("todo: vpshldw"); }, + BNDMK => GENERAL_W_R, + BNDCL => GENERAL_R, + BNDCU => GENERAL_R, + BNDCN => GENERAL_R, + BNDMOV => GENERAL_W_R, + BNDLDX => GENERAL_W_R + .set_complex(true), + BNDSTX => GENERAL_W_R + .set_complex(true), + + VGF2P8AFFINEQB => GENERAL_W_R_R + .set_operand(3, Access::Read), + VGF2P8AFFINEINVQB => GENERAL_W_R_R + .set_operand(3, Access::Read), + VPSHRDQ => GENERAL_W_R_R + .set_operand(3, Access::Read), + VPSHRDD => GENERAL_W_R_R + .set_operand(3, Access::Read), + VPSHRDW => GENERAL_W_R_R + .set_operand(3, Access::Read), + VPSHLDQ => GENERAL_W_R_R + .set_operand(3, Access::Read), + VPSHLDD => GENERAL_W_R_R + .set_operand(3, Access::Read), + VPSHLDW => GENERAL_W_R_R + .set_operand(3, Access::Read), VBROADCASTF32X8 => GENERAL_W_R, VBROADCASTF64X4 => GENERAL_W_R, VBROADCASTF32X4 => GENERAL_W_R, @@ -4484,16 +5308,25 @@ fn opcode2behavior(opc: &Opcode) -> Option { VBROADCASTI32X4 => GENERAL_W_R, VBROADCASTI64X2 => GENERAL_W_R, VBROADCASTI32X2 => GENERAL_W_R, - VEXTRACTI32X8 => { panic!("todo: vextracti32x8"); }, - VEXTRACTF32X8 => { panic!("todo: vextractf32x8"); }, - VINSERTI32X8 => { panic!("todo: vinserti32x8"); }, - VINSERTF32X8 => { panic!("todo: vinsertf32x8"); }, - VINSERTI32X4 => { panic!("todo: vinserti32x4"); }, - V4FNMADDSS => { panic!("todo: v4fnmaddss"); }, - V4FNMADDPS => { panic!("todo: v4fnmaddps"); }, + VEXTRACTI32X8 => GENERAL_W_R + .set_operand(2, Access::Read), + VEXTRACTF32X8 => GENERAL_W_R + .set_operand(2, Access::Read), + VINSERTI32X8 => GENERAL_W_R_R + .set_operand(3, Access::Read), + VINSERTF32X8 => GENERAL_W_R_R + .set_operand(3, Access::Read), + VINSERTI32X4 => GENERAL_W_R_R + .set_operand(3, Access::Read), + V4FNMADDSS => GENERAL_RW_R_R + .set_complex(true), + V4FNMADDPS => GENERAL_RW_R_R + .set_complex(true), VCVTNEPS2BF16 => GENERAL_W_R, - V4FMADDSS => { panic!("todo: v4fmaddss"); }, - V4FMADDPS => { panic!("todo: v4fmaddps"); }, + V4FMADDSS => GENERAL_RW_R_R + .set_complex(true), + V4FMADDPS => GENERAL_RW_R_R + .set_complex(true), VCVTNE2PS2BF16 => GENERAL_W_R_R, VP2INTERSECTD => GENERAL_W_R_R, VP2INTERSECTQ => GENERAL_W_R_R, @@ -4503,26 +5336,26 @@ fn opcode2behavior(opc: &Opcode) -> Option { VPDPWSSD => GENERAL_RW_R_R, VPDPBUSDS => GENERAL_RW_R_R, VDPBF16PS => GENERAL_RW_R_R, - VPBROADCASTMW2D => { panic!("todo: vpbroadcastmw2d"); }, - VPBROADCASTMB2Q => { panic!("todo: vpbroadcastmb2q"); }, - VPMOVD2M => { panic!("todo: vpmovd2m"); }, + VPBROADCASTMW2D => GENERAL_W_R, + VPBROADCASTMB2Q => GENERAL_W_R, + VPMOVD2M => GENERAL_W_R, VPMOVQD => GENERAL_W_R, VPMOVWB => GENERAL_W_R, VPMOVDB => GENERAL_W_R, VPMOVDW => GENERAL_W_R, VPMOVQB => GENERAL_W_R, VPMOVQW => GENERAL_W_R, - VGF2P8MULB => { panic!("todo: vgf2p8mulb"); }, - VPMADD52HUQ => { panic!("todo: vpmadd52huq"); }, - VPMADD52LUQ => { panic!("todo: vpmadd52luq"); }, - VPSHUFBITQMB => { panic!("todo: vpshufbitqmb"); }, - VPERMB => { panic!("todo: vpermb"); }, - VPEXPANDD => { panic!("todo: vpexpandd"); }, - VPEXPANDQ => { panic!("todo: vpexpandq"); }, + VGF2P8MULB => GENERAL_RW_R_R, + VPMADD52HUQ => GENERAL_RW_R_R, + VPMADD52LUQ => GENERAL_RW_R_R, + VPSHUFBITQMB => GENERAL_W_R_R, + VPERMB => GENERAL_W_R_R, + VPEXPANDD => GENERAL_W_R, + VPEXPANDQ => GENERAL_W_R, VPABSQ => GENERAL_W_R, VPRORVD => GENERAL_W_R_R, VPRORVQ => GENERAL_W_R_R, - VPMULTISHIFTQB => { panic!("todo: vpmultishiftqb"); }, + VPMULTISHIFTQB => GENERAL_W_R_R, VPERMT2B => GENERAL_RW_R_R, VPERMT2W => GENERAL_RW_R_R, VPSHRDVQ => GENERAL_RW_R_R, @@ -4544,21 +5377,33 @@ fn opcode2behavior(opc: &Opcode) -> Option { VSCALEFPS => GENERAL_W_R_R, VSCALEFPD => GENERAL_W_R_R, VPDPBUSD => GENERAL_W_R_R, - VCVTUSI2SD => { panic!("todo: vcvtusi2sd"); }, - VCVTUSI2SS => { panic!("todo: vcvtusi2ss"); }, - VPXORD => { panic!("todo: vpxord"); }, - VPXORQ => { panic!("todo: vpxorq"); }, - VPORD => { panic!("todo: vpord"); }, - VPORQ => { panic!("todo: vporq"); }, - VPANDND => { panic!("todo: vpandnd"); }, - VPANDNQ => { panic!("todo: vpandnq"); }, - VPANDD => { panic!("todo: vpandd"); }, - VPANDQ => { panic!("todo: vpandq"); }, - - PSMASH => { panic!("todo: psmash"); }, - PVALIDATE => { panic!("todo: pvalidate"); }, - RMPADJUST => { panic!("todo: rmpadjust"); }, - RMPUPDATE => { panic!("todo: rmpupdate"); }, + VCVTUSI2SD => GENERAL_W_R_R, + VCVTUSI2SS => GENERAL_W_R_R, + VPXORD => GENERAL_W_R_R, + VPXORQ => GENERAL_W_R_R, + VPORD => GENERAL_W_R_R, + VPORQ => GENERAL_W_R_R, + VPANDND => GENERAL_W_R_R, + VPANDNQ => GENERAL_W_R_R, + VPANDD => GENERAL_W_R_R, + VPANDQ => GENERAL_W_R_R, + + PSMASH => BehaviorDigest::empty() + .set_pl0() + .set_flags_access(Access::Write) + .set_complex(true), + PVALIDATE => BehaviorDigest::empty() + .set_pl0() + .set_flags_access(Access::Write) + .set_complex(true), + RMPADJUST => BehaviorDigest::empty() + .set_pl0() + .set_flags_access(Access::Write) + .set_complex(true), + RMPUPDATE => BehaviorDigest::empty() + .set_pl0() + .set_flags_access(Access::Write) + .set_complex(true), }; Some(behavior) -- cgit v1.1