diff options
-rw-r--r-- | src/lib.rs | 58 | ||||
-rw-r--r-- | test/test.rs | 32 |
2 files changed, 86 insertions, 4 deletions
@@ -2344,6 +2344,8 @@ pub enum OperandCode { ModRM_0x0fba, ModRM_0xf238, ModRM_0xf30fc7, + ModRM_0x660f38, + ModRM_0x660f3a, CVT_AA, CVT_DA, Rq_Cq_0, @@ -2578,9 +2580,9 @@ const OPCODE_660F_MAP: [OpcodeRecord; 256] = [ OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x660f38), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x660f3a), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), @@ -3689,7 +3691,7 @@ enum Interpretation { Prefix, } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq)] // this should be a 32-byte struct.. struct OpcodeRecord(Interpretation, OperandCode); @@ -4222,7 +4224,7 @@ pub fn read_instr<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T read_opcode_f30f_map(&mut bytes_iter, &mut length)? }, }; - if rec.0 == Interpretation::Instruction(Opcode::Invalid) { + if rec == OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing) { escapes_are_prefixes_actually(&mut prefixes, &mut Some(opcode_map)); OPCODE_0F_MAP[opcode_byte as usize] } else { @@ -4997,6 +4999,54 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; instruction.operands[1] = OperandSpec::ImmI8; }, + OperandCode::ModRM_0x660f38 => { + let op = bytes_iter.next().map(|b| { *length += 1; b }).ok_or(())?; + match op { + 0xdb => { instruction.opcode = Opcode::AESIMC; } + 0xdc => { instruction.opcode = Opcode::AESENC; } + 0xdd => { instruction.opcode = Opcode::AESENCLAST; } + 0xde => { instruction.opcode = Opcode::AESDEC; } + 0xdf => { instruction.opcode = Opcode::AESDECLAST; } + _ => { + instruction.opcode = Opcode::Invalid; + return Err(()); + } + }; + // all these SO FAR are G_E_xmm + let modrm = read_modrm(&mut bytes_iter, instruction, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X); + + + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?; + instruction.operand_count = 2; + } + OperandCode::ModRM_0x660f3a => { + let op = bytes_iter.next().map(|b| { *length += 1; b }).ok_or(())?; + match op { + 0xdf => { + instruction.opcode = Opcode::AESKEYGENASSIST; + // read operands right here right now + + let modrm = read_modrm(&mut bytes_iter, instruction, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X); + + + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?; + instruction.imm = + read_imm_unsigned(&mut bytes_iter, 1)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + } + _ => { + instruction.opcode = Opcode::Invalid; + return Err(()); + } + }; + } OperandCode::G_mm_Edq => { instruction.operands[1] = mem_oper; instruction.modrm_rrr.bank = RegisterBank::MM; diff --git a/test/test.rs b/test/test.rs index e2c52fe..cd2f6c0 100644 --- a/test/test.rs +++ b/test/test.rs @@ -98,6 +98,38 @@ fn test_cvt() { } #[test] +fn test_aesni() { + fn test_instr(bytes: &[u8], text: &'static str) { + test_display_under(&InstDecoder::minimal().with_aesni(), bytes, text); + test_display_under(&InstDecoder::default(), bytes, text); + test_invalid_under(&InstDecoder::minimal(), bytes); + } + + fn test_instr_invalid(bytes: &[u8]) { + test_invalid_under(&InstDecoder::minimal().with_aesni(), bytes); + test_invalid_under(&InstDecoder::default(), bytes); + } + + test_instr(&[0x66, 0x0f, 0x38, 0xdb, 0x0f], "aesimc xmm1, [rdi]"); + test_instr(&[0x66, 0x4f, 0x0f, 0x38, 0xdb, 0xcf], "aesimc xmm9, xmm15"); + + test_instr(&[0x66, 0x0f, 0x38, 0xdc, 0x0f], "aesenc xmm1, [rdi]"); + test_instr(&[0x66, 0x4f, 0x0f, 0x38, 0xdc, 0xcf], "aesenc xmm9, xmm15"); + + test_instr(&[0x66, 0x0f, 0x38, 0xdd, 0x0f], "aesenclast xmm1, [rdi]"); + test_instr(&[0x66, 0x4f, 0x0f, 0x38, 0xdd, 0xcf], "aesenclast xmm9, xmm15"); + + test_instr(&[0x66, 0x0f, 0x38, 0xde, 0x0f], "aesdec xmm1, [rdi]"); + test_instr(&[0x66, 0x4f, 0x0f, 0x38, 0xde, 0xcf], "aesdec xmm9, xmm15"); + + test_instr(&[0x66, 0x0f, 0x38, 0xdf, 0x0f], "aesdeclast xmm1, [rdi]"); + test_instr(&[0x66, 0x4f, 0x0f, 0x38, 0xdf, 0xcf], "aesdeclast xmm9, xmm15"); + + test_instr(&[0x66, 0x0f, 0x3a, 0xdf, 0x0f, 0xaa], "aeskeygenassist xmm1, [rdi], 0xaa"); + test_instr(&[0x66, 0x4f, 0x0f, 0x3a, 0xdf, 0xcf, 0xaa], "aeskeygenassist xmm9, xmm15, 0xaa"); +} + +#[test] fn test_sse3() { fn test_instr(bytes: &[u8], text: &'static str) { test_display_under(&InstDecoder::minimal().with_sse3(), bytes, text); |