aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2023-07-23 11:06:55 -0700
committeriximeow <me@iximeow.net>2023-07-23 11:06:55 -0700
commit4e5dfd758a22818c5f8496025e8c0b3dd00f0f50 (patch)
tree18fbb66846d8095331209bd39416b40272ca13cf
parent69eafa6d98ddd61daf85bd3fe371f50b3355fe06 (diff)
fix + better test cvttsd2si+cvtsd2si (misdecode under 64-bit)
-rw-r--r--CHANGELOG1
-rw-r--r--src/long_mode/mod.rs15
-rw-r--r--src/protected_mode/mod.rs16
-rw-r--r--src/real_mode/mod.rs18
-rw-r--r--test/long_mode/mod.rs12
5 files changed, 46 insertions, 16 deletions
diff --git a/CHANGELOG b/CHANGELOG
index ff41043..f59fac1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -20,6 +20,7 @@
* reporting index register as ymm when it is actually xmm
* 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
## 1.1.5
* fix several typos across crate docs - thank you Bruce! (aka github user waywardmonkeys)
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index cf40ac5..71b2373 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -5061,6 +5061,7 @@ enum OperandCase {
G_xmm_Eq,
G_mm_E_xmm,
Gd_U_xmm,
+ Gdq_Eq_xmm,
Gv_E_xmm,
G_xmm_Ew_Ib,
G_E_xmm_Ub,
@@ -5407,6 +5408,7 @@ enum OperandCode {
G_xmm_Eq = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_xmm_Eq).bits(),
G_mm_E_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_mm_E_xmm).bits(),
Gd_U_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gd_U_xmm).bits(),
+ Gdq_Eq_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gdq_Eq_xmm).bits(),
Gv_E_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gv_E_xmm).bits(),
//= 0x816f, // mirror G_xmm_Edq, but also read an immediate
G_xmm_Ew_Ib = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_xmm_Ew_Ib).bits(),
@@ -9049,6 +9051,15 @@ fn read_operands<
instruction.regs[0].bank = RegisterBank::D;
instruction.regs[1].bank = RegisterBank::X;
}
+ OperandCase::Gdq_Eq_xmm => {
+ if instruction.operands[1] == OperandSpec::RegMMM {
+ instruction.regs[1].bank = RegisterBank::X;
+ } else {
+ // should not be possible to reach `instruction.regs[0].bank == W`, as that would
+ // be `cvttpd2pi mm, xmm`
+ instruction.mem_size = 8;
+ }
+ }
OperandCase::Gv_E_xmm => {
if instruction.operands[1] == OperandSpec::RegMMM {
instruction.regs[1].bank = RegisterBank::X;
@@ -10902,8 +10913,8 @@ const REPNZ_0F_CODES: [OpcodeRecord; 256] = [
OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
OpcodeRecord::new(Interpretation::Instruction(Opcode::CVTSI2SD), OperandCode::G_xmm_Edq),
OpcodeRecord::new(Interpretation::Instruction(Opcode::MOVNTSD), OperandCode::M_G_xmm),
- OpcodeRecord::new(Interpretation::Instruction(Opcode::CVTTSD2SI), OperandCode::PMOVX_G_E_xmm),
- OpcodeRecord::new(Interpretation::Instruction(Opcode::CVTSD2SI), OperandCode::PMOVX_G_E_xmm),
+ OpcodeRecord::new(Interpretation::Instruction(Opcode::CVTTSD2SI), OperandCode::Gdq_Eq_xmm),
+ OpcodeRecord::new(Interpretation::Instruction(Opcode::CVTSD2SI), OperandCode::Gdq_Eq_xmm),
OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs
index 9b891bf..f4e355f 100644
--- a/src/protected_mode/mod.rs
+++ b/src/protected_mode/mod.rs
@@ -4960,6 +4960,7 @@ enum OperandCase {
G_xmm_Ed,
G_mm_E_xmm,
Gd_U_xmm,
+ Gd_Eq_xmm,
Gv_E_xmm,
G_xmm_Ew_Ib,
G_E_xmm_Ub,
@@ -5298,6 +5299,7 @@ enum OperandCode {
G_xmm_Ed = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_xmm_Ed).bits(),
G_mm_E_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_mm_E_xmm).bits(),
Gd_U_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gd_U_xmm).bits(),
+ Gd_Eq_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gd_Eq_xmm).bits(),
Gv_E_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gv_E_xmm).bits(),
//= 0x816f, // mirror G_xmm_Ed, but also read an immediate
G_xmm_Ew_Ib = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_xmm_Ew_Ib).bits(),
@@ -7625,9 +7627,6 @@ fn read_operands<
}
OperandCase::PMOVX_G_E_xmm => {
instruction.regs[0].bank = RegisterBank::X;
- if instruction.opcode == Opcode::CVTTSD2SI || instruction.opcode == Opcode::CVTSD2SI {
- instruction.regs[0].bank = RegisterBank::D;
- }
instruction.operands[0] = OperandSpec::RegRRR;
instruction.operands[1] = mem_oper;
if instruction.operands[1] != OperandSpec::RegMMM {
@@ -8904,6 +8903,13 @@ fn read_operands<
instruction.regs[0].bank = RegisterBank::D;
instruction.regs[1].bank = RegisterBank::X;
}
+ OperandCase::Gd_Eq_xmm => {
+ if instruction.operands[1] == OperandSpec::RegMMM {
+ instruction.regs[1].bank = RegisterBank::X;
+ } else {
+ instruction.mem_size = 8;
+ }
+ }
OperandCase::Gv_E_xmm => {
if instruction.operands[1] == OperandSpec::RegMMM {
instruction.regs[1].bank = RegisterBank::X;
@@ -10781,8 +10787,8 @@ const REPNZ_0F_CODES: [OpcodeRecord; 256] = [
OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
OpcodeRecord::new(Interpretation::Instruction(Opcode::CVTSI2SD), OperandCode::G_xmm_Ed),
OpcodeRecord::new(Interpretation::Instruction(Opcode::MOVNTSD), OperandCode::M_G_xmm),
- OpcodeRecord::new(Interpretation::Instruction(Opcode::CVTTSD2SI), OperandCode::PMOVX_G_E_xmm),
- OpcodeRecord::new(Interpretation::Instruction(Opcode::CVTSD2SI), OperandCode::PMOVX_G_E_xmm),
+ OpcodeRecord::new(Interpretation::Instruction(Opcode::CVTTSD2SI), OperandCode::Gd_Eq_xmm),
+ OpcodeRecord::new(Interpretation::Instruction(Opcode::CVTSD2SI), OperandCode::Gd_Eq_xmm),
OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs
index ae191ec..924f46c 100644
--- a/src/real_mode/mod.rs
+++ b/src/real_mode/mod.rs
@@ -4960,6 +4960,7 @@ enum OperandCase {
G_xmm_Ed,
G_mm_E_xmm,
Gd_U_xmm,
+ Gd_Eq_xmm,
Gv_E_xmm,
G_xmm_Ew_Ib,
G_E_xmm_Ub,
@@ -5298,6 +5299,7 @@ enum OperandCode {
G_xmm_Ed = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_xmm_Ed).bits(),
G_mm_E_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_mm_E_xmm).bits(),
Gd_U_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gd_U_xmm).bits(),
+ Gd_Eq_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gd_Eq_xmm).bits(),
Gv_E_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gv_E_xmm).bits(),
//= 0x816f, // mirror G_xmm_Ed, but also read an immediate
G_xmm_Ew_Ib = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_xmm_Ew_Ib).bits(),
@@ -7629,9 +7631,6 @@ fn read_operands<
}
OperandCase::PMOVX_G_E_xmm => {
instruction.regs[0].bank = RegisterBank::X;
- if instruction.opcode == Opcode::CVTTSD2SI || instruction.opcode == Opcode::CVTSD2SI {
- instruction.regs[0].bank = RegisterBank::D;
- }
instruction.operands[0] = OperandSpec::RegRRR;
instruction.operands[1] = mem_oper;
if instruction.operands[1] != OperandSpec::RegMMM {
@@ -8910,6 +8909,15 @@ fn read_operands<
instruction.regs[0].bank = RegisterBank::D;
instruction.regs[1].bank = RegisterBank::X;
}
+ OperandCase::Gd_Eq_xmm => {
+ // in real-mode the register is always dword, regardless of prefixing
+ instruction.regs[0].bank = RegisterBank::D;
+ if instruction.operands[1] == OperandSpec::RegMMM {
+ instruction.regs[1].bank = RegisterBank::X;
+ } else {
+ instruction.mem_size = 8;
+ }
+ }
OperandCase::Gv_E_xmm => {
// in real-mode the register is always dword, regardless of prefixing
instruction.regs[0].bank = RegisterBank::D;
@@ -10791,8 +10799,8 @@ const REPNZ_0F_CODES: [OpcodeRecord; 256] = [
OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
OpcodeRecord::new(Interpretation::Instruction(Opcode::CVTSI2SD), OperandCode::G_xmm_Ed),
OpcodeRecord::new(Interpretation::Instruction(Opcode::MOVNTSD), OperandCode::M_G_xmm),
- OpcodeRecord::new(Interpretation::Instruction(Opcode::CVTTSD2SI), OperandCode::PMOVX_G_E_xmm),
- OpcodeRecord::new(Interpretation::Instruction(Opcode::CVTSD2SI), OperandCode::PMOVX_G_E_xmm),
+ OpcodeRecord::new(Interpretation::Instruction(Opcode::CVTTSD2SI), OperandCode::Gd_Eq_xmm),
+ OpcodeRecord::new(Interpretation::Instruction(Opcode::CVTSD2SI), OperandCode::Gd_Eq_xmm),
OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index 3c53fce..50745dc 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -329,12 +329,16 @@ fn test_sse2() {
test_instr(&[0x66, 0x4f, 0x0f, 0x2b, 0x0f], "movntpd xmmword [r15], xmm9");
test_instr(&[0x66, 0x4f, 0x0f, 0x2c, 0xcf], "cvttpd2pi mm1, xmm15");
test_instr(&[0x66, 0x4f, 0x0f, 0x2c, 0x0f], "cvttpd2pi mm1, xmmword [r15]");
- test_instr(&[0xf2, 0x4f, 0x0f, 0x2c, 0xcf], "cvttsd2si xmm9, xmm15");
- test_instr(&[0xf2, 0x4f, 0x0f, 0x2c, 0x0f], "cvttsd2si xmm9, qword [r15]");
+ test_instr(&[0xf2, 0x4f, 0x0f, 0x2c, 0xcf], "cvttsd2si r9, xmm15");
+ test_instr(&[0xf2, 0x4f, 0x0f, 0x2c, 0x0f], "cvttsd2si r9, qword [r15]");
+ test_instr(&[0xf2, 0x40, 0x0f, 0x2c, 0xcf], "cvttsd2si ecx, xmm7");
+ test_instr(&[0xf2, 0x40, 0x0f, 0x2c, 0x0f], "cvttsd2si ecx, qword [rdi]");
test_instr(&[0x66, 0x4f, 0x0f, 0x2d, 0xcf], "cvtpd2pi mm1, xmm15");
test_instr(&[0x66, 0x4f, 0x0f, 0x2d, 0x0f], "cvtpd2pi mm1, xmmword [r15]");
- test_instr(&[0xf2, 0x4f, 0x0f, 0x2d, 0xcf], "cvtsd2si xmm9, xmm15");
- test_instr(&[0xf2, 0x4f, 0x0f, 0x2d, 0x0f], "cvtsd2si xmm9, qword [r15]");
+ test_instr(&[0xf2, 0x4f, 0x0f, 0x2d, 0xcf], "cvtsd2si r9, xmm15");
+ test_instr(&[0xf2, 0x4f, 0x0f, 0x2d, 0x0f], "cvtsd2si r9, qword [r15]");
+ test_instr(&[0xf2, 0x40, 0x0f, 0x2d, 0xcf], "cvtsd2si ecx, xmm7");
+ test_instr(&[0xf2, 0x40, 0x0f, 0x2d, 0x0f], "cvtsd2si ecx, qword [rdi]");
test_instr(&[0x66, 0x4f, 0x0f, 0x2e, 0xcf], "ucomisd xmm9, xmm15");
test_instr(&[0x66, 0x4f, 0x0f, 0x2e, 0x0f], "ucomisd xmm9, qword [r15]");
test_instr(&[0x66, 0x4f, 0x0f, 0x2f, 0xcf], "comisd xmm9, xmm15");