From 4e5dfd758a22818c5f8496025e8c0b3dd00f0f50 Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 23 Jul 2023 11:06:55 -0700 Subject: fix + better test cvttsd2si+cvtsd2si (misdecode under 64-bit) --- src/long_mode/mod.rs | 15 +++++++++++++-- src/protected_mode/mod.rs | 16 +++++++++++----- src/real_mode/mod.rs | 18 +++++++++++++----- 3 files changed, 37 insertions(+), 12 deletions(-) (limited to 'src') 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), -- cgit v1.1