aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/long_mode/behavior.rs30
-rw-r--r--test/long_mode/behavior.rs46
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 {