From f3d8bb582c1c3e97d8002975a3da6223b263b40f Mon Sep 17 00:00:00 2001 From: iximeow Date: Sat, 22 Feb 2020 16:21:03 -0800 Subject: support most avx operand codes avx is still incomplete, but less so avx is still practically untested --- src/long_mode/vex.rs | 181 +++++++++++++++++++++++++++++++++++++++++++++++---- test/test.rs | 8 ++- 2 files changed, 173 insertions(+), 16 deletions(-) diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs index 5c671d8..fe50c4e 100644 --- a/src/long_mode/vex.rs +++ b/src/long_mode/vex.rs @@ -391,6 +391,58 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.imm = read_imm_unsigned(bytes, 1, length)?; Ok(()) }, + VEXOperandCode::G_xmm_Eq => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E(bytes, instruction, modrm, 8, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + Ok(()) + } + VEXOperandCode::G_xmm_Ed => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + Ok(()) + } + VEXOperandCode::Eq_G_xmm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E(bytes, instruction, modrm, 8, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + Ok(()) + } + VEXOperandCode::Ed_G_xmm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + Ok(()) + } _op @ VEXOperandCode::E_G_xmm | _op @ VEXOperandCode::U_G_xmm | _op @ VEXOperandCode::M_G_xmm | @@ -408,6 +460,19 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operands[1] = OperandSpec::RegRRR; Ok(()) } + _op @ VEXOperandCode::E_xmm_G_ymm_imm8 => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + Ok(()) + } _op @ VEXOperandCode::G_M_xmm | _op @ VEXOperandCode::G_U_xmm | @@ -425,6 +490,58 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operands[1] = mem_oper; Ok(()) } + _op @ VEXOperandCode::G_xmm_E_xmm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + Ok(()) + } + _op @ VEXOperandCode::G_xmm_E_ymm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + Ok(()) + } + _op @ VEXOperandCode::G_ymm_E_xmm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + Ok(()) + } + _op @ VEXOperandCode::G_ymm_E_ymm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + Ok(()) + } _op @ VEXOperandCode::E_G_ymm | _op @ VEXOperandCode::U_G_ymm | @@ -469,6 +586,19 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operands[2] = mem_oper; Ok(()) } + _op @ VEXOperandCode::G_V_E_ymm_imm8 => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); + instruction.vex_reg.bank = RegisterBank::Y; + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[3] = OperandSpec::ImmU8; + Ok(()) + } _op @ VEXOperandCode::E_V_G_ymm | _op @ VEXOperandCode::M_V_G_ymm => { let modrm = read_modrm(bytes, length)?; @@ -492,7 +622,43 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operands[2] = mem_oper; Ok(()) } - + _op @ VEXOperandCode::G_V_E_xmm_imm8 => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[3] = OperandSpec::ImmU8; + Ok(()) + } + _op @ VEXOperandCode::V_ymm_G_ymm_E_xmm_imm8 => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); + instruction.vex_reg.bank = RegisterBank::Y; + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegVex; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operands[2] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[3] = OperandSpec::ImmU8; + Ok(()) + } + _op @ VEXOperandCode::V_xmm_G_ymm_E_ymm_imm8 => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegVex; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operands[2] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[3] = OperandSpec::ImmU8; + Ok(()) + } _op @ VEXOperandCode::E_V_G_xmm | _op @ VEXOperandCode::M_V_G_xmm => { let modrm = read_modrm(bytes, length)?; @@ -529,22 +695,9 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst Ok(()) } - VEXOperandCode::E_xmm_G_ymm_imm8 | VEXOperandCode::G_E_ymm_imm8 | - VEXOperandCode::G_xmm_E_xmm | - VEXOperandCode::G_xmm_E_ymm | - VEXOperandCode::G_ymm_E_xmm | - VEXOperandCode::G_ymm_E_ymm | - VEXOperandCode::G_V_E_xmm_imm8 | VEXOperandCode::G_V_E_xmm_xmm4 | - VEXOperandCode::G_V_E_ymm_imm8 | VEXOperandCode::G_V_E_ymm_ymm4 | - VEXOperandCode::V_xmm_G_ymm_E_ymm_imm8 | - VEXOperandCode::V_ymm_G_ymm_E_xmm_imm8 | - VEXOperandCode::Eq_G_xmm | - VEXOperandCode::Ed_G_xmm | - VEXOperandCode::G_xmm_Ed | - VEXOperandCode::G_xmm_Eq | VEXOperandCode::G_V_ymm_E_xmm | VEXOperandCode::G_V_xmm_Ew_imm8 => { Err(DecodeError::IncompleteDecoder) // :) diff --git a/test/test.rs b/test/test.rs index 28263ae..0c43b83 100644 --- a/test/test.rs +++ b/test/test.rs @@ -856,7 +856,7 @@ fn test_vex() { } test_instr(&[0xc5, 0xf8, 0x10, 0x00], "vmovups xmm0, [rax]"); - test_instr(&[0xc5, 0xf8, 0x10, 0x00], "vmovups xmm0, [rax]"); + test_instr(&[0xc5, 0xf8, 0x10, 0x01], "vmovups xmm0, [rcx]"); test_instr(&[0xc5, 0x78, 0x10, 0x0f], "vmovups xmm9, [rdi]"); test_instr(&[0xc5, 0xf8, 0x10, 0xcf], "vmovups xmm1, xmm7"); test_instr(&[0xc5, 0xf9, 0x10, 0x0f], "vmovupd xmm1, [rdi]"); @@ -865,7 +865,11 @@ fn test_vex() { test_instr(&[0xc5, 0xfd, 0x10, 0x0f], "vmovupd ymm1, [rdi]"); test_instr(&[0xc5, 0xfe, 0x10, 0x0f], "vmovss xmm1, [rdi]"); test_instr(&[0xc5, 0xff, 0x10, 0xcf], "vmovsd xmm1, xmm0, xmm7"); - test_instr(&[0xc5, 0xff, 0x10, 0x00], "vmovsd xmm0, [rax]"); + test_instr(&[0xc5, 0xff, 0x10, 0x01], "vmovsd xmm0, [rcx]"); + test_instr(&[0xc5, 0xf9, 0x6e, 0xc6], "vmovd xmm0, esi"); + test_instr(&[0xc5, 0xf9, 0x6e, 0x13], "vmovd xmm2, [rbx]"); + test_instr(&[0xc5, 0xf9, 0x7e, 0xc6], "vmovd esi, xmm0"); + test_instr(&[0xc5, 0xf9, 0x7e, 0x13], "vmovd [rbx], xmm2"); test_instr_invalid(&[0x4f, 0xc5, 0xf8, 0x10, 0x00]); test_instr_invalid(&[0xf0, 0xc5, 0xf8, 0x10, 0x00]); test_instr(&[0xc4, 0x02, 0x71, 0x00, 0x0f], "vpshufb xmm9, xmm1, [r15]"); -- cgit v1.1