aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2023-07-23 13:13:44 -0700
committeriximeow <me@iximeow.net>2023-07-23 13:13:44 -0700
commit855fa08f1d2f4bc405a1cfc205b5e9321dd4ebf5 (patch)
tree83dc40b8d30b9a9a3a76b94ea6760cfe2163e4e5
parent4e5dfd758a22818c5f8496025e8c0b3dd00f0f50 (diff)
fix inconsistently-poreted memory access size of vcvt{,t}{sd,si}
-rw-r--r--CHANGELOG4
-rw-r--r--src/long_mode/vex.rs86
-rw-r--r--src/protected_mode/vex.rs63
-rw-r--r--src/real_mode/vex.rs65
-rw-r--r--test/long_mode/mod.rs18
-rw-r--r--test/protected_mode/mod.rs11
-rw-r--r--test/real_mode/mod.rs2
-rw-r--r--todo_notes10
8 files changed, 215 insertions, 44 deletions
diff --git a/CHANGELOG b/CHANGELOG
index f59fac1..81a1f46 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -21,6 +21,10 @@
* extended support for some newer instructions (pconfig, movdir64b) from just
64-bit to all decode modes
* fix cvttsd2si/cvtsd2si reporting xmm registers as destinations in 64-bit mode
+* fix inconsistently-reported memory access size of vcvt{,t}{sd,si} across
+ encodings and bitness
+ * in some cases, instructions loading a single-precision float reported 8-byte loads
+ * in some cases, instructions loading a double-precision float reported 4-byte loads
## 1.1.5
* fix several typos across crate docs - thank you Bruce! (aka github user waywardmonkeys)
diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs
index e83c735..2ee9749 100644
--- a/src/long_mode/vex.rs
+++ b/src/long_mode/vex.rs
@@ -80,6 +80,8 @@ enum VEXOperandCode {
G_V_E_xmm,
G_V_E_xmm_imm8,
G_V_E_xmm_xmm4,
+ G_V_Ed_xmm,
+ G_V_Eq_xmm,
G_V_E_ymm,
G_V_E_ymm_imm8,
G_V_E_ymm_ymm4,
@@ -95,7 +97,9 @@ enum VEXOperandCode {
G_V_E,
G_E_Ib,
VCVT_Gd_Ed_xmm,
+ VCVT_Gd_Eq_xmm,
VCVT_Gq_Eq_xmm,
+ VCVT_Gq_Ed_xmm,
BMI1_F3,
MXCSR,
}
@@ -634,6 +638,42 @@ fn read_vex_operands<
instruction.operand_count = 2;
Ok(())
}
+ VEXOperandCode::VCVT_Gd_Eq_xmm => {
+ if instruction.regs[3].num != 0 {
+ return Err(DecodeError::InvalidOperand);
+ }
+ let modrm = read_modrm(words)?;
+ instruction.regs[0] =
+ RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::D);
+ let mem_oper = read_E(words, instruction, modrm, RegisterBank::D, sink)?;
+ if let OperandSpec::RegMMM = mem_oper {
+ instruction.regs[1].bank = RegisterBank::X;
+ } else {
+ instruction.mem_size = 8;
+ }
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = mem_oper;
+ instruction.operand_count = 2;
+ Ok(())
+ }
+ VEXOperandCode::VCVT_Gq_Ed_xmm => {
+ if instruction.regs[3].num != 0 {
+ return Err(DecodeError::InvalidOperand);
+ }
+ let modrm = read_modrm(words)?;
+ instruction.regs[0] =
+ RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::Q);
+ let mem_oper = read_E(words, instruction, modrm, RegisterBank::D, sink)?;
+ if let OperandSpec::RegMMM = mem_oper {
+ instruction.regs[1].bank = RegisterBank::X;
+ } else {
+ instruction.mem_size = 4;
+ }
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = mem_oper;
+ instruction.operand_count = 2;
+ Ok(())
+ }
VEXOperandCode::VCVT_Gq_Eq_xmm => {
if instruction.regs[3].num != 0 {
return Err(DecodeError::InvalidOperand);
@@ -645,11 +685,7 @@ fn read_vex_operands<
if let OperandSpec::RegMMM = mem_oper {
instruction.regs[1].bank = RegisterBank::X;
} else {
- if instruction.opcode == Opcode::VCVTSS2SI {
- instruction.mem_size = 4;
- } else {
- instruction.mem_size = 8;
- }
+ instruction.mem_size = 8;
}
instruction.operands[0] = OperandSpec::RegRRR;
instruction.operands[1] = mem_oper;
@@ -1202,6 +1238,34 @@ fn read_vex_operands<
instruction.operand_count = 3;
Ok(())
}
+ VEXOperandCode::G_V_Ed_xmm => {
+ let modrm = read_modrm(words)?;
+ instruction.regs[0] =
+ RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X);
+ let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = OperandSpec::RegVex;
+ instruction.operands[2] = mem_oper;
+ if mem_oper != OperandSpec::RegMMM {
+ instruction.mem_size = 4;
+ }
+ instruction.operand_count = 3;
+ Ok(())
+ }
+ VEXOperandCode::G_V_Eq_xmm => {
+ let modrm = read_modrm(words)?;
+ instruction.regs[0] =
+ RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X);
+ let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = OperandSpec::RegVex;
+ instruction.operands[2] = mem_oper;
+ if mem_oper != OperandSpec::RegMMM {
+ instruction.mem_size = 8;
+ }
+ instruction.operand_count = 3;
+ Ok(())
+ }
VEXOperandCode::G_V_xmm_Ed => {
let modrm = read_modrm(words)?;
instruction.regs[0] =
@@ -1912,17 +1976,17 @@ fn read_vex_instruction<
0x2c => (Opcode::VCVTTSD2SI, if instruction.prefixes.vex_unchecked().w() {
VEXOperandCode::VCVT_Gq_Eq_xmm // 64-bit
} else {
- VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit
+ VEXOperandCode::VCVT_Gd_Eq_xmm // 32-bit
}),
0x2d => (Opcode::VCVTSD2SI, if instruction.prefixes.vex_unchecked().w() {
VEXOperandCode::VCVT_Gq_Eq_xmm // 64-bit
} else {
- VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit
+ VEXOperandCode::VCVT_Gd_Eq_xmm // 32-bit
}),
0x51 => (Opcode::VSQRTSD, VEXOperandCode::G_V_E_xmm),
0x58 => (Opcode::VADDSD, VEXOperandCode::G_V_E_xmm),
0x59 => (Opcode::VMULSD, VEXOperandCode::G_V_E_xmm),
- 0x5a => (Opcode::VCVTSD2SS, VEXOperandCode::G_V_E_xmm),
+ 0x5a => (Opcode::VCVTSD2SS, VEXOperandCode::G_V_Eq_xmm),
0x5c => (Opcode::VSUBSD, VEXOperandCode::G_V_E_xmm),
0x5d => (Opcode::VMINSD, VEXOperandCode::G_V_E_xmm),
0x5e => (Opcode::VDIVSD, VEXOperandCode::G_V_E_xmm),
@@ -1959,12 +2023,12 @@ fn read_vex_instruction<
VEXOperandCode::G_V_xmm_Ed
}),
0x2c => (Opcode::VCVTTSS2SI, if instruction.prefixes.vex_unchecked().w() {
- VEXOperandCode::VCVT_Gq_Eq_xmm
+ VEXOperandCode::VCVT_Gq_Ed_xmm
} else {
VEXOperandCode::VCVT_Gd_Ed_xmm
}),
0x2d => (Opcode::VCVTSS2SI, if instruction.prefixes.vex_unchecked().w() {
- VEXOperandCode::VCVT_Gq_Eq_xmm
+ VEXOperandCode::VCVT_Gq_Ed_xmm
} else {
VEXOperandCode::VCVT_Gd_Ed_xmm
}),
@@ -1973,7 +2037,7 @@ fn read_vex_instruction<
0x53 => (Opcode::VRCPSS, VEXOperandCode::G_V_E_xmm),
0x58 => (Opcode::VADDSS, VEXOperandCode::G_V_E_xmm),
0x59 => (Opcode::VMULSS, VEXOperandCode::G_V_E_xmm),
- 0x5a => (Opcode::VCVTSS2SD, VEXOperandCode::G_V_E_xmm),
+ 0x5a => (Opcode::VCVTSS2SD, VEXOperandCode::G_V_Ed_xmm),
0x5b => (Opcode::VCVTTPS2DQ, if L { VEXOperandCode::G_ymm_E_ymm } else { VEXOperandCode::G_xmm_E_xmm }),
0x5c => (Opcode::VSUBSS, VEXOperandCode::G_V_E_xmm),
0x5d => (Opcode::VMINSS, VEXOperandCode::G_V_E_xmm),
diff --git a/src/protected_mode/vex.rs b/src/protected_mode/vex.rs
index bac5ee1..337e9bc 100644
--- a/src/protected_mode/vex.rs
+++ b/src/protected_mode/vex.rs
@@ -79,6 +79,8 @@ enum VEXOperandCode {
G_V_E_xmm,
G_V_E_xmm_imm8,
G_V_E_xmm_xmm4,
+ G_V_Ed_xmm,
+ G_V_Eq_xmm,
G_V_E_ymm,
G_V_E_ymm_imm8,
G_V_E_ymm_ymm4,
@@ -92,6 +94,7 @@ enum VEXOperandCode {
G_V_E,
G_E_Ib,
VCVT_Gd_Ed_xmm,
+ VCVT_Gd_Eq_xmm,
BMI1_F3,
MXCSR,
}
@@ -591,11 +594,25 @@ fn read_vex_operands<
if let OperandSpec::RegMMM = mem_oper {
instruction.regs[1].bank = RegisterBank::X;
} else {
- if instruction.opcode == Opcode::VCVTTSD2SI || instruction.opcode == Opcode::VCVTSD2SI {
- instruction.mem_size = 8;
- } else {
- instruction.mem_size = 4;
- }
+ instruction.mem_size = 4;
+ }
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = mem_oper;
+ instruction.operand_count = 2;
+ Ok(())
+ }
+ VEXOperandCode::VCVT_Gd_Eq_xmm => {
+ if instruction.regs[3].num != 0 {
+ return Err(DecodeError::InvalidOperand);
+ }
+ let modrm = read_modrm(words)?;
+ instruction.regs[0] =
+ RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D);
+ let mem_oper = read_E(words, instruction, modrm, RegisterBank::D, sink)?;
+ if let OperandSpec::RegMMM = mem_oper {
+ instruction.regs[1].bank = RegisterBank::X;
+ } else {
+ instruction.mem_size = 8;
}
instruction.operands[0] = OperandSpec::RegRRR;
instruction.operands[1] = mem_oper;
@@ -1148,6 +1165,34 @@ fn read_vex_operands<
instruction.operand_count = 3;
Ok(())
}
+ VEXOperandCode::G_V_Ed_xmm => {
+ let modrm = read_modrm(words)?;
+ instruction.regs[0] =
+ RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);
+ let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = OperandSpec::RegVex;
+ instruction.operands[2] = mem_oper;
+ if mem_oper != OperandSpec::RegMMM {
+ instruction.mem_size = 4;
+ }
+ instruction.operand_count = 3;
+ Ok(())
+ }
+ VEXOperandCode::G_V_Eq_xmm => {
+ let modrm = read_modrm(words)?;
+ instruction.regs[0] =
+ RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);
+ let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = OperandSpec::RegVex;
+ instruction.operands[2] = mem_oper;
+ if mem_oper != OperandSpec::RegMMM {
+ instruction.mem_size = 8;
+ }
+ instruction.operand_count = 3;
+ Ok(())
+ }
VEXOperandCode::G_V_xmm_Ed => {
let modrm = read_modrm(words)?;
instruction.regs[0] =
@@ -1810,15 +1855,15 @@ fn read_vex_instruction<
VEXOperandCode::G_V_xmm_Ed // 32-bit last operand
}),
0x2c => (Opcode::VCVTTSD2SI, {
- VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit
+ VEXOperandCode::VCVT_Gd_Eq_xmm
}),
0x2d => (Opcode::VCVTSD2SI, {
- VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit
+ VEXOperandCode::VCVT_Gd_Eq_xmm
}),
0x51 => (Opcode::VSQRTSD, VEXOperandCode::G_V_E_xmm),
0x58 => (Opcode::VADDSD, VEXOperandCode::G_V_E_xmm),
0x59 => (Opcode::VMULSD, VEXOperandCode::G_V_E_xmm),
- 0x5a => (Opcode::VCVTSD2SS, VEXOperandCode::G_V_E_xmm),
+ 0x5a => (Opcode::VCVTSD2SS, VEXOperandCode::G_V_Eq_xmm),
0x5c => (Opcode::VSUBSD, VEXOperandCode::G_V_E_xmm),
0x5d => (Opcode::VMINSD, VEXOperandCode::G_V_E_xmm),
0x5e => (Opcode::VDIVSD, VEXOperandCode::G_V_E_xmm),
@@ -1863,7 +1908,7 @@ fn read_vex_instruction<
0x53 => (Opcode::VRCPSS, VEXOperandCode::G_V_E_xmm),
0x58 => (Opcode::VADDSS, VEXOperandCode::G_V_E_xmm),
0x59 => (Opcode::VMULSS, VEXOperandCode::G_V_E_xmm),
- 0x5a => (Opcode::VCVTSS2SD, VEXOperandCode::G_V_E_xmm),
+ 0x5a => (Opcode::VCVTSS2SD, VEXOperandCode::G_V_Ed_xmm),
0x5b => (Opcode::VCVTTPS2DQ, if L { VEXOperandCode::G_ymm_E_ymm } else { VEXOperandCode::G_xmm_E_xmm }),
0x5c => (Opcode::VSUBSS, VEXOperandCode::G_V_E_xmm),
0x5d => (Opcode::VMINSS, VEXOperandCode::G_V_E_xmm),
diff --git a/src/real_mode/vex.rs b/src/real_mode/vex.rs
index 79c6961..afa9565 100644
--- a/src/real_mode/vex.rs
+++ b/src/real_mode/vex.rs
@@ -79,6 +79,8 @@ enum VEXOperandCode {
G_V_E_xmm,
G_V_E_xmm_imm8,
G_V_E_xmm_xmm4,
+ G_V_Ed_xmm,
+ G_V_Eq_xmm,
G_V_E_ymm,
G_V_E_ymm_imm8,
G_V_E_ymm_ymm4,
@@ -92,6 +94,7 @@ enum VEXOperandCode {
G_V_E,
G_E_Ib,
VCVT_Gd_Ed_xmm,
+ VCVT_Gd_Eq_xmm,
BMI1_F3,
MXCSR,
}
@@ -591,11 +594,25 @@ fn read_vex_operands<
if let OperandSpec::RegMMM = mem_oper {
instruction.regs[1].bank = RegisterBank::X;
} else {
- if instruction.opcode == Opcode::VCVTTSD2SI || instruction.opcode == Opcode::VCVTSD2SI {
- instruction.mem_size = 8;
- } else {
- instruction.mem_size = 4;
- }
+ instruction.mem_size = 4;
+ }
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = mem_oper;
+ instruction.operand_count = 2;
+ Ok(())
+ }
+ VEXOperandCode::VCVT_Gd_Eq_xmm => {
+ if instruction.regs[3].num != 0 {
+ return Err(DecodeError::InvalidOperand);
+ }
+ let modrm = read_modrm(words)?;
+ instruction.regs[0] =
+ RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D);
+ let mem_oper = read_E(words, instruction, modrm, RegisterBank::D, sink)?;
+ if let OperandSpec::RegMMM = mem_oper {
+ instruction.regs[1].bank = RegisterBank::X;
+ } else {
+ instruction.mem_size = 8;
}
instruction.operands[0] = OperandSpec::RegRRR;
instruction.operands[1] = mem_oper;
@@ -1148,6 +1165,34 @@ fn read_vex_operands<
instruction.operand_count = 3;
Ok(())
}
+ VEXOperandCode::G_V_Ed_xmm => {
+ let modrm = read_modrm(words)?;
+ instruction.regs[0] =
+ RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);
+ let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = OperandSpec::RegVex;
+ instruction.operands[2] = mem_oper;
+ if mem_oper != OperandSpec::RegMMM {
+ instruction.mem_size = 4;
+ }
+ instruction.operand_count = 3;
+ Ok(())
+ }
+ VEXOperandCode::G_V_Eq_xmm => {
+ let modrm = read_modrm(words)?;
+ instruction.regs[0] =
+ RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);
+ let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = OperandSpec::RegVex;
+ instruction.operands[2] = mem_oper;
+ if mem_oper != OperandSpec::RegMMM {
+ instruction.mem_size = 8;
+ }
+ instruction.operand_count = 3;
+ Ok(())
+ }
VEXOperandCode::G_V_xmm_Ed => {
let modrm = read_modrm(words)?;
instruction.regs[0] =
@@ -1810,15 +1855,15 @@ fn read_vex_instruction<
VEXOperandCode::G_V_xmm_Ed // 32-bit last operand
}),
0x2c => (Opcode::VCVTTSD2SI, {
- VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit
+ VEXOperandCode::VCVT_Gd_Eq_xmm
}),
0x2d => (Opcode::VCVTSD2SI, {
- VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit
+ VEXOperandCode::VCVT_Gd_Eq_xmm
}),
0x51 => (Opcode::VSQRTSD, VEXOperandCode::G_V_E_xmm),
0x58 => (Opcode::VADDSD, VEXOperandCode::G_V_E_xmm),
0x59 => (Opcode::VMULSD, VEXOperandCode::G_V_E_xmm),
- 0x5a => (Opcode::VCVTSD2SS, VEXOperandCode::G_V_E_xmm),
+ 0x5a => (Opcode::VCVTSD2SS, VEXOperandCode::G_V_Eq_xmm),
0x5c => (Opcode::VSUBSD, VEXOperandCode::G_V_E_xmm),
0x5d => (Opcode::VMINSD, VEXOperandCode::G_V_E_xmm),
0x5e => (Opcode::VDIVSD, VEXOperandCode::G_V_E_xmm),
@@ -1862,8 +1907,8 @@ fn read_vex_instruction<
0x52 => (Opcode::VRSQRTSS, VEXOperandCode::G_V_E_xmm),
0x53 => (Opcode::VRCPSS, VEXOperandCode::G_V_E_xmm),
0x58 => (Opcode::VADDSS, VEXOperandCode::G_V_E_xmm),
- 0x59 => (Opcode::VMULSS, VEXOperandCode::G_V_E_xmm),
- 0x5a => (Opcode::VCVTSS2SD, VEXOperandCode::G_V_E_xmm),
+ 0x59 => (Opcode::VMULSS, VEXOperandCode::G_V_Ed_xmm),
+ 0x5a => (Opcode::VCVTSS2SD, VEXOperandCode::G_V_Ed_xmm),
0x5b => (Opcode::VCVTTPS2DQ, if L { VEXOperandCode::G_ymm_E_ymm } else { VEXOperandCode::G_xmm_E_xmm }),
0x5c => (Opcode::VSUBSS, VEXOperandCode::G_V_E_xmm),
0x5d => (Opcode::VMINSS, VEXOperandCode::G_V_E_xmm),
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index 50745dc..9144dbe 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -1976,6 +1976,8 @@ fn test_vex() {
test_instr(&[0xc4, 0b000_00001, 0b0_1111_010, 0x2c, 0b11_001_010], "vcvttss2si r9d, xmm10");
test_instr(&[0xc4, 0b000_00001, 0b0_1111_110, 0x2c, 0b11_001_010], "vcvttss2si r9d, xmm10");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x2c, 0b11_001_010], "vcvttss2si r9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_110, 0x2c, 0b00_001_010], "vcvttss2si r9d, dword [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x2c, 0b00_001_010], "vcvttss2si r9, dword [r10]");
test_instr(&[0xc5, 0b0_1111_010, 0x2c, 0b11_001_010], "vcvttss2si r9d, xmm2");
test_instr(&[0xc5, 0b0_1111_010, 0x2c, 0b00_001_010], "vcvttss2si r9d, dword [rdx]");
test_instr(&[0xc5, 0b0_1111_110, 0x2c, 0b11_001_010], "vcvttss2si r9d, xmm2");
@@ -1983,10 +1985,10 @@ fn test_vex() {
test_instr(&[0xc4, 0b000_00001, 0b0_1111_111, 0x2c, 0b11_001_010], "vcvttsd2si r9d, xmm10");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_111, 0x2c, 0b11_001_010], "vcvttsd2si r9, xmm10");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_111, 0x2c, 0b00_001_010], "vcvttsd2si r9, qword [r10]");
- test_instr(&[0xc4, 0b000_00001, 0b0_1111_111, 0x2c, 0b00_001_010], "vcvttsd2si r9d, dword [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_111, 0x2c, 0b00_001_010], "vcvttsd2si r9d, qword [r10]");
test_instr(&[0xc5, 0b0_1111_011, 0x2c, 0b11_001_010], "vcvttsd2si r9d, xmm2");
test_instr(&[0xc5, 0b0_1111_111, 0x2c, 0b11_001_010], "vcvttsd2si r9d, xmm2");
- test_instr(&[0xc5, 0b0_1111_111, 0x2c, 0b00_001_010], "vcvttsd2si r9d, dword [rdx]");
+ test_instr(&[0xc5, 0b0_1111_111, 0x2c, 0b00_001_010], "vcvttsd2si r9d, qword [rdx]");
test_instr(&[0xc4, 0b000_00001, 0b0_1111_010, 0x2d, 0b11_001_010], "vcvtss2si r9d, xmm10");
test_instr(&[0xc4, 0b000_00001, 0b0_1111_110, 0x2d, 0b11_001_010], "vcvtss2si r9d, xmm10");
test_instr(&[0xc4, 0b000_00001, 0b0_1111_110, 0x2d, 0b00_001_010], "vcvtss2si r9d, dword [r10]");
@@ -1994,9 +1996,9 @@ fn test_vex() {
test_instr(&[0xc5, 0b0_1111_010, 0x2d, 0b11_001_010], "vcvtss2si r9d, xmm2");
test_instr(&[0xc5, 0b0_1111_110, 0x2d, 0b11_001_010], "vcvtss2si r9d, xmm2");
test_instr(&[0xc4, 0b000_00001, 0b0_1111_011, 0x2d, 0b11_001_010], "vcvtsd2si r9d, xmm10");
- test_instr(&[0xc4, 0b000_00001, 0b0_1111_011, 0x2d, 0b00_001_010], "vcvtsd2si r9d, dword [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_011, 0x2d, 0b00_001_010], "vcvtsd2si r9d, qword [r10]");
test_instr(&[0xc4, 0b000_00001, 0b0_1111_111, 0x2d, 0b11_001_010], "vcvtsd2si r9d, xmm10");
- test_instr(&[0xc4, 0b000_00001, 0b0_1111_111, 0x2d, 0b00_001_010], "vcvtsd2si r9d, dword [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_111, 0x2d, 0b00_001_010], "vcvtsd2si r9d, qword [r10]");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_111, 0x2d, 0b11_001_010], "vcvtsd2si r9, xmm10");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_011, 0x2d, 0b00_001_010], "vcvtsd2si r9, qword [r10]");
test_instr(&[0xc5, 0b0_1111_011, 0x2d, 0b11_001_010], "vcvtsd2si r9d, xmm2");
@@ -2105,8 +2107,16 @@ fn test_vex() {
test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0x5a, 0b11_001_010], "vcvtpd2ps xmm9, ymm10");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_011, 0x5a, 0b11_001_010], "vcvtsd2ss xmm9, xmm0, xmm10");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_111, 0x5a, 0b11_001_010], "vcvtsd2ss xmm9, xmm0, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_011, 0x5a, 0b00_001_010], "vcvtsd2ss xmm9, xmm0, qword [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_111, 0x5a, 0b00_001_010], "vcvtsd2ss xmm9, xmm0, qword [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_011, 0x5a, 0b00_001_010], "vcvtsd2ss xmm9, xmm0, qword [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_111, 0x5a, 0b00_001_010], "vcvtsd2ss xmm9, xmm0, qword [r10]");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0x5a, 0b11_001_010], "vcvtss2sd xmm9, xmm0, xmm10");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x5a, 0b11_001_010], "vcvtss2sd xmm9, xmm0, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0x5a, 0b00_001_010], "vcvtss2sd xmm9, xmm0, dword [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x5a, 0b00_001_010], "vcvtss2sd xmm9, xmm0, dword [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_010, 0x5a, 0b00_001_010], "vcvtss2sd xmm9, xmm0, dword [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_110, 0x5a, 0b00_001_010], "vcvtss2sd xmm9, xmm0, dword [r10]");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x5b, 0b11_001_010], "vcvtps2dq xmm9, xmm10");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0x5b, 0b11_001_010], "vcvtps2dq ymm9, ymm10");
diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs
index 5a6c832..5229617 100644
--- a/test/protected_mode/mod.rs
+++ b/test/protected_mode/mod.rs
@@ -1840,6 +1840,8 @@ fn test_vex() {
test_instr(&[0xc4, 0b110_00001, 0b0_1111_010, 0x2c, 0b11_001_010], "vcvttss2si ecx, xmm2");
test_instr(&[0xc4, 0b110_00001, 0b0_1111_110, 0x2c, 0b11_001_010], "vcvttss2si ecx, xmm2");
test_instr(&[0xc4, 0b110_00001, 0b1_1111_110, 0x2c, 0b11_001_010], "vcvttss2si ecx, xmm2");
+ test_instr(&[0xc4, 0b110_00001, 0b0_1111_110, 0x2c, 0b00_001_010], "vcvttss2si ecx, dword [edx]");
+ test_instr(&[0xc4, 0b110_00001, 0b1_1111_110, 0x2c, 0b00_001_010], "vcvttss2si ecx, dword [edx]");
test_instr(&[0xc5, 0b1_1111_010, 0x2c, 0b11_001_010], "vcvttss2si ecx, xmm2");
test_instr(&[0xc5, 0b1_1111_010, 0x2c, 0b00_001_010], "vcvttss2si ecx, dword [edx]");
test_instr(&[0xc5, 0b1_1111_110, 0x2c, 0b11_001_010], "vcvttss2si ecx, xmm2");
@@ -1856,6 +1858,7 @@ fn test_vex() {
test_instr(&[0xc4, 0b110_00001, 0b0_1111_110, 0x2d, 0b00_001_010], "vcvtss2si ecx, dword [edx]");
test_instr(&[0xc4, 0b110_00001, 0b1_1111_110, 0x2d, 0b00_001_010], "vcvtss2si ecx, dword [edx]");
test_instr(&[0xc5, 0b1_1111_010, 0x2d, 0b11_001_010], "vcvtss2si ecx, xmm2");
+ test_instr(&[0xc5, 0b1_1111_010, 0x2d, 0b00_001_010], "vcvtss2si ecx, dword [edx]");
test_instr(&[0xc5, 0b1_1111_110, 0x2d, 0b11_001_010], "vcvtss2si ecx, xmm2");
test_instr(&[0xc4, 0b110_00001, 0b0_1111_011, 0x2d, 0b11_001_010], "vcvtsd2si ecx, xmm2");
test_instr(&[0xc4, 0b110_00001, 0b0_1111_011, 0x2d, 0b00_001_010], "vcvtsd2si ecx, qword [edx]");
@@ -1969,8 +1972,16 @@ fn test_vex() {
test_instr(&[0xc4, 0b110_00001, 0b1_1111_101, 0x5a, 0b11_001_010], "vcvtpd2ps xmm1, ymm2");
test_instr(&[0xc4, 0b110_00001, 0b1_1111_011, 0x5a, 0b11_001_010], "vcvtsd2ss xmm1, xmm0, xmm2");
test_instr(&[0xc4, 0b110_00001, 0b1_1111_111, 0x5a, 0b11_001_010], "vcvtsd2ss xmm1, xmm0, xmm2");
+ test_instr(&[0xc4, 0b110_00001, 0b1_1111_011, 0x5a, 0b00_001_010], "vcvtsd2ss xmm1, xmm0, qword [edx]");
+ test_instr(&[0xc4, 0b110_00001, 0b1_1111_111, 0x5a, 0b00_001_010], "vcvtsd2ss xmm1, xmm0, qword [edx]");
+ test_instr(&[0xc4, 0b110_00001, 0b0_1111_011, 0x5a, 0b00_001_010], "vcvtsd2ss xmm1, xmm0, qword [edx]");
+ test_instr(&[0xc4, 0b110_00001, 0b0_1111_111, 0x5a, 0b00_001_010], "vcvtsd2ss xmm1, xmm0, qword [edx]");
test_instr(&[0xc4, 0b110_00001, 0b1_1111_010, 0x5a, 0b11_001_010], "vcvtss2sd xmm1, xmm0, xmm2");
test_instr(&[0xc4, 0b110_00001, 0b1_1111_110, 0x5a, 0b11_001_010], "vcvtss2sd xmm1, xmm0, xmm2");
+ test_instr(&[0xc4, 0b110_00001, 0b1_1111_010, 0x5a, 0b00_001_010], "vcvtss2sd xmm1, xmm0, dword [edx]");
+ test_instr(&[0xc4, 0b110_00001, 0b1_1111_010, 0x5a, 0b00_001_010], "vcvtss2sd xmm1, xmm0, dword [edx]");
+ test_instr(&[0xc4, 0b110_00001, 0b0_1111_110, 0x5a, 0b00_001_010], "vcvtss2sd xmm1, xmm0, dword [edx]");
+ test_instr(&[0xc4, 0b110_00001, 0b0_1111_110, 0x5a, 0b00_001_010], "vcvtss2sd xmm1, xmm0, dword [edx]");
test_instr(&[0xc4, 0b110_00001, 0b1_1111_001, 0x5b, 0b11_001_010], "vcvtps2dq xmm1, xmm2");
test_instr(&[0xc4, 0b110_00001, 0b1_1111_101, 0x5b, 0b11_001_010], "vcvtps2dq ymm1, ymm2");
diff --git a/test/real_mode/mod.rs b/test/real_mode/mod.rs
index 04ea687..7cf5fc2 100644
--- a/test/real_mode/mod.rs
+++ b/test/real_mode/mod.rs
@@ -17305,6 +17305,7 @@ fn test_real_mode() {
test_display(&[0xc4, 0xc1, 0xfa, 0x51, 0x0a], "vsqrtss xmm1, xmm0, dword [bp + si * 1]");
test_display(&[0xc4, 0xc1, 0xfa, 0x52, 0xca], "vrsqrtss xmm1, xmm0, xmm2");
test_display(&[0xc4, 0xc1, 0xfa, 0x53, 0xca], "vrcpss xmm1, xmm0, xmm2");
+ test_display(&[0xc4, 0xc1, 0xfa, 0x5a, 0x0a], "vcvtss2sd xmm1, xmm0, dword [bp + si * 1]");
test_display(&[0xc4, 0xc1, 0xfa, 0x5a, 0xca], "vcvtss2sd xmm1, xmm0, xmm2");
test_display(&[0xc4, 0xc1, 0xfa, 0x5b, 0xca], "vcvttps2dq xmm1, xmm2");
test_display(&[0xc4, 0xc1, 0xfa, 0x70, 0xca, 0x77], "vpshufhw xmm1, xmm2, 0x77");
@@ -17313,6 +17314,7 @@ fn test_real_mode() {
test_display(&[0xc4, 0xc1, 0xfb, 0x11, 0x0a], "vmovsd qword [bp + si * 1], xmm1");
test_display(&[0xc4, 0xc1, 0xfb, 0x2a, 0x0a], "vcvtsi2sd xmm1, xmm0, dword [bp + si * 1]");
test_display(&[0xc4, 0xc1, 0xfb, 0x2d, 0x0a], "vcvtsd2si ecx, qword [bp + si * 1]");
+ test_display(&[0xc4, 0xc1, 0xfb, 0x5a, 0x0a], "vcvtsd2ss xmm1, xmm0, qword [bp + si * 1]");
test_display(&[0xc4, 0xc1, 0xfb, 0x5a, 0xca], "vcvtsd2ss xmm1, xmm0, xmm2");
test_display(&[0xc4, 0xc1, 0xfb, 0x70, 0xca, 0x77], "vpshuflw xmm1, xmm2, 0x77");
test_display(&[0xc4, 0xc1, 0xfb, 0xe6, 0xca], "vcvtpd2dq xmm1, xmm2");
diff --git a/todo_notes b/todo_notes
index 2004332..f0785d7 100644
--- a/todo_notes
+++ b/todo_notes
@@ -1,11 +1 @@
-cvttsd2si xmm9, xmm15
-should be... cvttsd2si ecx, xmm15
-
-vcvttsd2si, vcvtsd2si,
-sd2si is decoded as if some loads could be only 4 bytes, all are 8...
-ss2si is decdoed as if some loads could be 8 bytes, all are 4...
-
-movdir64b is decodable in protected mode, real mode
-pconfig is decodable in protected mode, real mode
-
lsl seems just... wrong. check alternate prefixes in 32-/61-bit