aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2020-02-22 16:21:03 -0800
committeriximeow <me@iximeow.net>2020-02-22 16:21:03 -0800
commitf3d8bb582c1c3e97d8002975a3da6223b263b40f (patch)
treeaf1a700e29b4cbc77f037cafb64fb5d653b7f689
parent802679e4f8362d3c819b83223854c638cc8f2b7f (diff)
support most avx operand codes
avx is still incomplete, but less so avx is still practically untested
-rw-r--r--src/long_mode/vex.rs181
-rw-r--r--test/test.rs8
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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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]");