aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib.rs58
-rw-r--r--test/test.rs32
2 files changed, 86 insertions, 4 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 15cee14..c583031 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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);