aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/long_mode/behavior.rs55
-rw-r--r--test/long_mode/behavior.rs60
2 files changed, 91 insertions, 24 deletions
diff --git a/src/long_mode/behavior.rs b/src/long_mode/behavior.rs
index 56cb270..a5e5757 100644
--- a/src/long_mode/behavior.rs
+++ b/src/long_mode/behavior.rs
@@ -975,6 +975,10 @@ pub enum ComplexOp {
BTS,
/// TODO: document
+ SYSCALL,
+ SYSRET,
+
+ /// TODO: document
SWAPGS,
RDFSBASE,
WRFSBASE,
@@ -2594,7 +2598,8 @@ fn opcode2behavior(opc: &Opcode) -> Option<BehaviorDigest> {
.set_pl0(),
INVD => BehaviorDigest::empty()
.set_pl0(),
- SYSRET => { panic!("todo: sysret"); },
+ SYSRET => BehaviorDigest::empty()
+ .set_pl0(),
CLTS => BehaviorDigest::empty()
.set_implicit_ops(CLTS_IDX)
.set_pl0(),
@@ -2903,7 +2908,7 @@ fn opcode2behavior(opc: &Opcode) -> Option<BehaviorDigest> {
XORPS => GENERAL_RW_R,
XORPD => GENERAL_RW_R,
- VMOVDDUP => { panic!("todo: vmovddup"); },
+ VMOVDDUP => GENERAL_W_R,
VPSHUFLW => { panic!("todo: vpshuflw"); },
VPSHUFHW => { panic!("todo: vpshufhw"); },
VHADDPS => GENERAL_W_R_R,
@@ -3053,12 +3058,12 @@ fn opcode2behavior(opc: &Opcode) -> Option<BehaviorDigest> {
VMOVD => GENERAL_W_R,
VMOVDQA => { panic!("todo: vmovdqa"); },
VMOVDQU => { panic!("todo: vmovdqu"); },
- VMOVHLPS => { panic!("todo: vmovhlps"); },
- VMOVHPD => { panic!("todo: vmovhpd"); },
- VMOVHPS => { panic!("todo: vmovhps"); },
- VMOVLHPS => { panic!("todo: vmovlhps"); },
- VMOVLPD => { panic!("todo: vmovlpd"); },
- VMOVLPS => { panic!("todo: vmovlps"); },
+ VMOVHLPS => GENERAL_W_R_R,
+ VMOVHPD => GENERAL_W_R,
+ VMOVHPS => GENERAL_W_R,
+ VMOVLHPS => GENERAL_W_R_R,
+ VMOVLPD => GENERAL_W_R,
+ VMOVLPS => GENERAL_W_R,
VMOVMSKPD => { panic!("todo: vmovmskpd"); },
VMOVMSKPS => { panic!("todo: vmovmskps"); },
VMOVNTDQ => { panic!("todo: vmovntdq"); },
@@ -3066,12 +3071,12 @@ fn opcode2behavior(opc: &Opcode) -> Option<BehaviorDigest> {
VMOVNTPD => { panic!("todo: vmovntpd"); },
VMOVNTPS => { panic!("todo: vmovntps"); },
VMOVQ => GENERAL_W_R,
- VMOVSS => { panic!("todo: vmovss"); },
- VMOVSD => { panic!("todo: vmovsd"); },
+ VMOVSS => GENERAL_W_R_R,
+ VMOVSD => GENERAL_W_R_R,
VMOVSHDUP => GENERAL_W_R,
VMOVSLDUP => GENERAL_W_R,
- VMOVUPD => { panic!("todo: vmovupd"); },
- VMOVUPS => { panic!("todo: vmovups"); },
+ VMOVUPD => GENERAL_W_R,
+ VMOVUPS => GENERAL_W_R,
VMPSADBW => { panic!("todo: vmpsadbw"); },
VMULPD => GENERAL_W_R_R,
VMULPS => GENERAL_W_R_R,
@@ -3126,10 +3131,10 @@ fn opcode2behavior(opc: &Opcode) -> Option<BehaviorDigest> {
VPERM2F128 => { panic!("todo: vperm2f128"); },
VPERM2I128 => { panic!("todo: vperm2i128"); },
VPERMD => { panic!("todo: vpermd"); },
- VPERMILPD => { panic!("todo: vpermilpd"); },
- VPERMILPS => { panic!("todo: vpermilps"); },
- VPERMPD => { panic!("todo: vpermpd"); },
- VPERMPS => { panic!("todo: vpermps"); },
+ VPERMILPD => GENERAL_W_R_R,
+ VPERMILPS => GENERAL_W_R_R,
+ VPERMPD => GENERAL_W_R_R,
+ VPERMPS => GENERAL_W_R_R,
VPERMQ => { panic!("todo: vpermq"); },
VPEXTRB => { panic!("todo: vpextrb"); },
VPEXTRD => { panic!("todo: vpextrd"); },
@@ -3139,14 +3144,14 @@ fn opcode2behavior(opc: &Opcode) -> Option<BehaviorDigest> {
VPGATHERDQ => { panic!("todo: vpgatherdq"); },
VPGATHERQD => { panic!("todo: vpgatherqd"); },
VPGATHERQQ => { panic!("todo: vpgatherqq"); },
- VPHADDD => { panic!("todo: vphaddd"); },
- VPHADDSW => { panic!("todo: vphaddsw"); },
- VPHADDW => { panic!("todo: vphaddw"); },
+ VPHADDD => GENERAL_W_R_R,
+ VPHADDSW => GENERAL_W_R_R,
+ VPHADDW => GENERAL_W_R_R,
VPMADDUBSW => GENERAL_W_R_R,
VPHMINPOSUW => { panic!("todo: vphminposuw"); },
- VPHSUBD => { panic!("todo: vphsubd"); },
- VPHSUBSW => { panic!("todo: vphsubsw"); },
- VPHSUBW => { panic!("todo: vphsubw"); },
+ VPHSUBD => GENERAL_W_R_R,
+ VPHSUBSW => GENERAL_W_R_R,
+ VPHSUBW => GENERAL_W_R_R,
VPINSRB => { panic!("todo: vpinsrb"); },
VPINSRD => { panic!("todo: vpinsrd"); },
VPINSRQ => { panic!("todo: vpinsrq"); },
@@ -3247,8 +3252,10 @@ fn opcode2behavior(opc: &Opcode) -> Option<BehaviorDigest> {
VSUBPS => { panic!("todo: vsubps"); },
VSUBSD => { panic!("todo: vsubsd"); },
VSUBSS => { panic!("todo: vsubss"); },
- VTESTPD => { panic!("todo: vtestpd"); },
- VTESTPS => { panic!("todo: vtestps"); },
+ VTESTPD => GENERAL_R_R
+ .set_flags_access(Access::Write),
+ VTESTPS => GENERAL_R_R
+ .set_flags_access(Access::Write),
VUNPCKHPD => { panic!("todo: vunpckhpd"); },
VUNPCKHPS => { panic!("todo: vunpckhps"); },
VUNPCKLPD => { panic!("todo: vunpcklpd"); },
diff --git a/test/long_mode/behavior.rs b/test/long_mode/behavior.rs
index 15e3660..19f6336 100644
--- a/test/long_mode/behavior.rs
+++ b/test/long_mode/behavior.rs
@@ -1520,6 +1520,66 @@ mod kvm {
}
}
+ #[test]
+ fn behavior_verify_kvm_vex() {
+ use yaxpeax_arch::{Decoder, U8Reader};
+ use yaxpeax_x86::long_mode::Instruction;
+
+ 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();
+
+ #[allow(non_snake_case)]
+ for opcode in 0x00..=u8::MAX {
+ for prefix_bits in 0x00..0x400u16 {
+ let mmmmm = prefix_bits & 0b11111;
+ let prefix_1 = (0xe0 | mmmmm) as u8;
+
+ let pp = (prefix_bits >> 5) & 0b11;
+ let W = (prefix_bits >> 7) & 1;
+ let L = (prefix_bits >> 8) & 1;
+ let prefix_2 = (0x78 | (W << 7) | (L << 2) | pp) as u8;
+
+ let operands = (prefix_bits >> 9) & 0b1;
+ static OPC_BYTE_TABLE: [u8; 2] = [0xc1, 0x01];
+
+ let bytes: [u8; 5] = [0xc4, prefix_1, prefix_2, opcode, OPC_BYTE_TABLE[operands as usize]];
+ let mut reader = U8Reader::new(&bytes);
+ if decoder.decode_into(&mut buf, &mut reader).is_ok() {
+ // two byte instructions were covered by `verify_kvm`, novel instructions are three
+ // bytes (or longer..?)
+ use yaxpeax_arch::LengthedInstruction;
+ let inst_len = 0.wrapping_offset(buf.len()) as usize;
+ if inst_len != bytes.len() {
+ continue;
+ }
+
+ if not_generic(&buf) {
+ continue;
+ }
+
+ let mut printed = false;
+ eprint!("checking behavior of ");
+ for b in bytes.iter() {
+ if printed {
+ eprint!(" ");
+ }
+ eprint!("{:02x}", b);
+ printed = true;
+ }
+ eprintln!(": {}", buf);
+
+ vm.set_regs(&initial_regs).unwrap();
+ check_behavior(&mut vm, &bytes[..inst_len]).expect("behavior check is ok");
+ }
+ }
+ }
+ }
+
// use the generic test harness for a handful of instructions that don't get covered in the
// general enumeration above
#[test]