diff options
Diffstat (limited to 'src/real_mode')
| -rw-r--r-- | src/real_mode/vex.rs | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/src/real_mode/vex.rs b/src/real_mode/vex.rs index bb41165..9e24ee8 100644 --- a/src/real_mode/vex.rs +++ b/src/real_mode/vex.rs @@ -46,7 +46,7 @@ enum VEXOperandCode { VMOVHPS_16, M_G_xmm, G_M_xmm, - G_U_xmm, + G_U_xmm_vmaskmovdqu, Gd_U_xmm, E_G_xmm_imm8, Ud_G_xmm_imm8, @@ -784,17 +784,12 @@ fn read_vex_operands< } op @ VEXOperandCode::G_M_xmm | - op @ VEXOperandCode::G_U_xmm | op @ VEXOperandCode::G_E_xmm => { if instruction.regs[3].num != 0 { return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; match (op, modrm & 0xc0) { - (VEXOperandCode::G_U_xmm, 0xc0) => { - /* this is the only accepted operand */ - } - (VEXOperandCode::G_U_xmm, _) | (VEXOperandCode::G_M_xmm, 0xc0) => { return Err(DecodeError::InvalidOperand); } @@ -820,6 +815,23 @@ fn read_vex_operands< instruction.operand_count = 2; Ok(()) } + VEXOperandCode::G_U_xmm_vmaskmovdqu => { + if instruction.regs[3].num != 0 { + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(words)?; + if modrm & 0xc0 != 0xc0 { + return Err(DecodeError::InvalidOperand); + } + 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] = mem_oper; + instruction.mem_size = 16; + instruction.operand_count = 2; + Ok(()) + } VEXOperandCode::G_xmm_E_xmm => { if instruction.regs[3].num != 0 { return Err(DecodeError::InvalidOperand); @@ -1040,7 +1052,7 @@ fn read_vex_operands< RegSpec::from_parts((modrm >> 3) & 7, bank); let mem_oper = read_E(words, instruction, modrm, bank, sink)?; if mem_oper != OperandSpec::RegMMM { - if instruction.opcode == Opcode::VMOVLPD || instruction.opcode == Opcode::VMOVHPD || instruction.opcode == Opcode::VMOVHPS { + if instruction.opcode == Opcode::VMOVLPD || instruction.opcode == Opcode::VMOVHPD || instruction.opcode == Opcode::VMOVHPS || instruction.opcode == Opcode::VMOVQ { instruction.mem_size = 8; } else { if L { @@ -1769,10 +1781,10 @@ fn read_vex_instruction< }), 0xD4 => (Opcode::VPADDQ, VEXOperandCode::G_V_E_xyLmm), 0xD5 => (Opcode::VPMULLW, VEXOperandCode::G_V_E_xyLmm), - 0xD6 => (Opcode::VMOVD, if L { + 0xD6 => (Opcode::VMOVQ, if L { return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_E_xmm + VEXOperandCode::E_G_xyLmm }), 0xD7 => (Opcode::VPMOVMSKB, VEXOperandCode::Ud_G_xyLmm), 0xD8 => (Opcode::VPSUBUSB, VEXOperandCode::G_V_E_xyLmm), @@ -1832,7 +1844,7 @@ fn read_vex_instruction< 0xF7 => (Opcode::VMASKMOVDQU, if L { return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_U_xmm + VEXOperandCode::G_U_xmm_vmaskmovdqu }), 0xF8 => (Opcode::VPSUBB, VEXOperandCode::G_V_E_xyLmm), 0xF9 => (Opcode::VPSUBW, VEXOperandCode::G_V_E_xyLmm), @@ -1916,7 +1928,7 @@ fn read_vex_instruction< 0x5f => (Opcode::VMAXSS, VEXOperandCode::G_V_E_xmm), 0x6f => (Opcode::VMOVDQU, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), 0x70 => (Opcode::VPSHUFHW, VEXOperandCode::G_E_xyLmm_imm8), - 0x7e => (Opcode::VMOVD, if L { return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_xmm }), + 0x7e => (Opcode::VMOVQ, if L { return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_xmm }), 0x7f => (Opcode::VMOVDQU, VEXOperandCode::E_G_xyLmm), 0xc2 => (Opcode::VCMPSS, VEXOperandCode::G_V_E_xmm_imm8), 0xe6 => (Opcode::VCVTDQ2PD, if L { VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_xmm_E_xmm }), |
