diff options
| -rw-r--r-- | CHANGELOG | 1 | ||||
| -rw-r--r-- | src/long_mode/mod.rs | 15 | ||||
| -rw-r--r-- | src/protected_mode/mod.rs | 16 | ||||
| -rw-r--r-- | src/real_mode/mod.rs | 18 | ||||
| -rw-r--r-- | test/long_mode/mod.rs | 12 | 
5 files changed, 46 insertions, 16 deletions
@@ -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");  | 
