diff options
| -rw-r--r-- | src/long_mode/behavior.rs | 30 | ||||
| -rw-r--r-- | test/long_mode/behavior.rs | 46 |
2 files changed, 65 insertions, 11 deletions
diff --git a/src/long_mode/behavior.rs b/src/long_mode/behavior.rs index aaf3f8a..56cb270 100644 --- a/src/long_mode/behavior.rs +++ b/src/long_mode/behavior.rs @@ -2758,8 +2758,10 @@ fn opcode2behavior(opc: &Opcode) -> Option<BehaviorDigest> { ANDPS => GENERAL_RW_R, ANDPD => GENERAL_RW_R, BSWAP => GENERAL_RW, - CMPPD => { panic!("todo: cmppd"); }, - CMPPS => { panic!("todo: cmpps"); }, + CMPPD => GENERAL_RW_R + .set_operand(2, Access::Read), + CMPPS => GENERAL_RW_R + .set_operand(2, Access::Read), COMISD => GENERAL_R_R_FLAGWRITE, COMISS => GENERAL_R_R_FLAGWRITE, CVTDQ2PS => GENERAL_W_R, @@ -2885,8 +2887,8 @@ fn opcode2behavior(opc: &Opcode) -> Option<BehaviorDigest> { RSQRTPS => GENERAL_W_R, SHLD => GENERAL_RW_R_R .set_flags_access(Access::Write), - SHUFPD => { panic!("todo: shufpd"); }, - SHUFPS => { panic!("todo: shufps"); }, + SHUFPD => GENERAL_RW_R_R, + SHUFPS => GENERAL_RW_R_R, SLHD => { panic!("todo: slhd"); }, SQRTPS => GENERAL_W_R, SQRTPD => GENERAL_W_R, @@ -2938,7 +2940,8 @@ fn opcode2behavior(opc: &Opcode) -> Option<BehaviorDigest> { .set_operand(3, Access::Read), VCMPPD => GENERAL_W_R_R .set_operand(3, Access::Read), - VCMPPS => { panic!("todo: vcmpps"); }, + VCMPPS => GENERAL_W_R_R + .set_operand(3, Access::Read), VCVTDQ2PD => { panic!("todo: vcvtdq2pd"); }, VCVTDQ2PS => GENERAL_W_R, VCVTPD2PS => { panic!("todo: vcvtpd2ps"); }, @@ -3232,8 +3235,10 @@ fn opcode2behavior(opc: &Opcode) -> Option<BehaviorDigest> { VRSQRTPS => GENERAL_W_R, VRSQRTSS => GENERAL_RW_R, VRCPSS => { panic!("todo: vrcpss"); }, - VSHUFPD => { panic!("todo: vshufpd"); }, - VSHUFPS => { panic!("todo: vshufps"); }, + VSHUFPD => GENERAL_W_R_R + .set_operand(3, Access::Read), + VSHUFPS => GENERAL_W_R_R + .set_operand(3, Access::Read), VSQRTPD => GENERAL_W_R, VSQRTPS => GENERAL_W_R, VSQRTSS => GENERAL_RW_R, @@ -3345,7 +3350,8 @@ fn opcode2behavior(opc: &Opcode) -> Option<BehaviorDigest> { SHA256MSG1 => GENERAL_RW_R, SHA256MSG2 => GENERAL_RW_R, - LZCNT => { panic!("todo: lzcnt"); }, + LZCNT => GENERAL_W_R + .set_flags_access(Access::Write), CLGI => { panic!("todo: clgi"); }, STGI => { panic!("todo: stgi"); }, SKINIT => { panic!("todo: skinit"); }, @@ -3366,8 +3372,10 @@ fn opcode2behavior(opc: &Opcode) -> Option<BehaviorDigest> { MOVBE => GENERAL_W_R, - ADCX => { panic!("todo: adcx"); }, - ADOX => { panic!("todo: adox"); }, + ADCX => GENERAL_RW_R + .set_flags_access(Access::ReadWrite), + ADOX => GENERAL_RW_R + .set_flags_access(Access::ReadWrite), PREFETCHW => { panic!("todo: prefetchw"); }, @@ -3395,7 +3403,7 @@ fn opcode2behavior(opc: &Opcode) -> Option<BehaviorDigest> { WRFSBASE => { panic!("todo: wrfsbase"); }, WRGSBASE => { panic!("todo: wrgsbase"); }, - CRC32 => { panic!("todo: crc32"); }, + CRC32 => GENERAL_RW_R, SALC => { panic!("todo: salc"); }, XLAT => BehaviorDigest::empty() .set_implicit_ops(XLAT_IDX) diff --git a/test/long_mode/behavior.rs b/test/long_mode/behavior.rs index dd3d270..dc10b03 100644 --- a/test/long_mode/behavior.rs +++ b/test/long_mode/behavior.rs @@ -1520,6 +1520,52 @@ mod kvm { } } + // use the generic test harness for a handful of instructions that don't get covered in the + // general enumeration above + #[test] + fn behavior_verify_kvm_misc() { + use yaxpeax_arch::{Decoder, U8Reader}; + use yaxpeax_x86::long_mode::{Instruction, Opcode}; + + let mut vm = create_test_vm(); + vm.set_single_step(true).expect("can enable single-step"); + + // TODO: happen to be testing on a zen 5 system, so i picked a zen 5 decoder. + let decoder = long_mode::uarch::amd::zen5(); + let mut buf = Instruction::default(); + let initial_regs = vm.get_regs().unwrap(); + + static MISC_INSTS: &'static [&'static [u8]] = &[ + // cmppd xmm0, xmmword [rcx], 0x75 + &[0x66, 0x0f, 0xc2, 0x01, 0x75], + // cmpps xmm0, xmmword [rcx], 0x75 + &[0x0f, 0xc2, 0x01, 0x75], + // shufpd xmm0, xmmword [rcx], 0x75 + &[0x66, 0x0f, 0xc6, 0x01, 0x75], + // shufps xmm0, xmmword [rcx], 0x75 + &[0x0f, 0xc6, 0x01, 0x75], + // lzcnt eax, dword [rcx] + &[0xf3, 0x0f, 0xbd, 0x01], + // adcx eax, dword [rcx] + &[0x66, 0x0f, 0x38, 0xf6, 0x01], + // adox eax, dword [rcx] + &[0xf3, 0x0f, 0x38, 0xf6, 0x01], + ]; + for bytes in MISC_INSTS.iter() { + let mut reader = U8Reader::new(&bytes); + if decoder.decode_into(&mut buf, &mut reader).is_ok() { + eprint!("checking behavior of {:02x}", bytes[0]); + for b in &bytes[1..] { + eprint!(" {:02x}", b); + } + eprint!("\n"); + + vm.set_regs(&initial_regs).unwrap(); + check_behavior(&mut vm, bytes).expect("behavior check is ok"); + } + } + } + use yaxpeax_x86::long_mode::Opcode; use yaxpeax_x86::long_mode::Operand; fn not_generic(instr: &Instruction) -> bool { |
