aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2019-12-01 15:27:15 -0800
committeriximeow <me@iximeow.net>2020-01-12 16:10:13 -0800
commit071dbfd2f1407842a6487a67e6ce83e80fedb99c (patch)
treea0d261d728973feb637549e62ba5f91e44f5d767
parentda63e8df700520ad396b754427f90ef92cc2425d (diff)
pshuf/psr/shld/shrd plus some test fixes
this makes all current non-vex/evex tests pass!!!
-rw-r--r--src/lib.rs150
-rw-r--r--test/test.rs15
2 files changed, 151 insertions, 14 deletions
diff --git a/src/lib.rs b/src/lib.rs
index c827dfb..84e71ed 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -247,6 +247,7 @@ impl OperandSpec {
OperandSpec::ImmU64 |
OperandSpec::RegRRR |
OperandSpec::RegMMM |
+ OperandSpec::CL |
OperandSpec::Nothing => {
false
}
@@ -267,6 +268,9 @@ impl Operand {
OperandSpec::RegMMM => {
Operand::Register(inst.modrm_mmm)
}
+ OperandSpec::CL => {
+ Operand::Register(RegSpec::cl())
+ }
OperandSpec::ImmI8 => Operand::ImmediateI8(inst.imm as i8),
OperandSpec::ImmU8 => Operand::ImmediateU8(inst.imm as u8),
OperandSpec::ImmI16 => Operand::ImmediateI16(inst.imm as i16),
@@ -733,6 +737,8 @@ enum OperandSpec {
RegRRR,
// the register in modrm_mmm (eg modrm mod bits were 11)
RegMMM,
+ // the register `cl`. Used for SHLD and SHRD.
+ CL,
ImmI8,
ImmI16,
ImmI32,
@@ -1185,13 +1191,14 @@ pub enum OperandCode {
Gv_Ew = 0x61,
Gdq_Ed = 0x62,
G_E_xmm = 0x63,
- G_E_xmm_Ib = 0x64,
- AL_Ib = 0x65,
- AX_Ivd = 0x66,
- AL_Ob = 0x67,
- AL_Xb = 0x68,
- AX_AL = 0x69,
- AX_Ov = 0x6a,
+ G_E_mm_Ib = 0x64,
+ G_E_xmm_Ib = 0x65,
+ AL_Ib = 0x66,
+ AX_Ivd = 0x67,
+ AL_Ob = 0x68,
+ AL_Xb = 0x69,
+ AX_AL = 0x6a,
+ AX_Ov = 0x6b,
Eb_Gb = 0x80,
Ev_Gv = 0x81,
@@ -1238,6 +1245,8 @@ pub enum OperandCode {
G_xmm_E_mm = 0xed,
G_xmm_Edq = 0xef,
G_U_mm = 0xf1,
+ Ev_Gv_Ib = 0xf3,
+ Ev_Gv_CL = 0xf5,
}
fn base_opcode_map(v: u8) -> Opcode {
@@ -2262,7 +2271,7 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [
OpcodeRecord(Interpretation::Instruction(Opcode::MOVQ), OperandCode::G_mm_E),
// 0x70
- OpcodeRecord(Interpretation::Instruction(Opcode::PSHUFW), OperandCode::G_E_xmm_Ib),
+ OpcodeRecord(Interpretation::Instruction(Opcode::PSHUFW), OperandCode::G_E_mm_Ib),
OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f71),
OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f72),
OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f73),
@@ -2317,19 +2326,19 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [
// 0xa0
OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::FS),
- OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::GS),
+ OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::FS),
OpcodeRecord(Interpretation::Instruction(Opcode::CPUID), OperandCode::Nothing),
OpcodeRecord(Interpretation::Instruction(Opcode::BT), OperandCode::Ev_Gv),
- OpcodeRecord(Interpretation::Instruction(Opcode::SHLD), OperandCode::Unsupported),
- OpcodeRecord(Interpretation::Instruction(Opcode::SHLD), OperandCode::Unsupported),
+ OpcodeRecord(Interpretation::Instruction(Opcode::SHLD), OperandCode::Ev_Gv_Ib),
+ OpcodeRecord(Interpretation::Instruction(Opcode::SHLD), OperandCode::Ev_Gv_CL),
OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::GS),
OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::GS),
OpcodeRecord(Interpretation::Instruction(Opcode::RSM), OperandCode::Nothing),
OpcodeRecord(Interpretation::Instruction(Opcode::BTS), OperandCode::Ev_Gv),
- OpcodeRecord(Interpretation::Instruction(Opcode::SHRD), OperandCode::Unsupported),
- OpcodeRecord(Interpretation::Instruction(Opcode::SHRD), OperandCode::Unsupported),
+ OpcodeRecord(Interpretation::Instruction(Opcode::SHRD), OperandCode::Ev_Gv_Ib),
+ OpcodeRecord(Interpretation::Instruction(Opcode::SHRD), OperandCode::Ev_Gv_CL),
OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0fae),
OpcodeRecord(Interpretation::Instruction(Opcode::IMUL), OperandCode::Gv_Ev),
@@ -3031,6 +3040,7 @@ pub fn read_instr<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Ins
}
}
};
+ println!("loaded record {:?}", record);
if let Interpretation::Instruction(opcode) = record.0 {
instruction.opcode = opcode;
} else {
@@ -3474,6 +3484,20 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
instruction.operands[0] = OperandSpec::RegRRR;
instruction.operand_count = 2;
},
+ OperandCode::G_E_mm_Ib => {
+ let modrm = read_modrm(&mut bytes_iter, instruction, length)?;
+ bytes_read = 1;
+
+// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m);
+ instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?;
+ instruction.modrm_rrr = RegSpec { bank: RegisterBank::MM, num: (modrm >> 3) & 7 };
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.imm =
+ read_num(&mut bytes_iter, 1)? as u8 as u64;
+ *length += 1;
+ instruction.operands[2] = OperandSpec::ImmI8;
+ instruction.operand_count = 3;
+ },
OperandCode::G_mm_Ew_Ib => {
let modrm = read_modrm(&mut bytes_iter, instruction, length)?;
bytes_read = 1;
@@ -3568,6 +3592,22 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
};
instruction.operand_count = 3;
}
+ OperandCode::Ev_Gv_Ib => {
+ let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes);
+ instruction.operands[0] = mem_oper;
+ instruction.operands[1] = OperandSpec::RegRRR;
+ instruction.imm =
+ read_imm_signed(&mut bytes_iter, 1, length)? as u64;
+ instruction.operands[2] = OperandSpec::ImmI8;
+ instruction.operand_count = 3;
+ }
+ OperandCode::Ev_Gv_CL => {
+ let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes);
+ instruction.operands[0] = mem_oper;
+ instruction.operands[1] = OperandSpec::RegRRR;
+ instruction.operands[2] = OperandSpec::CL;
+ instruction.operand_count = 3;
+ }
OperandCode::Nothing => {
instruction.operand_count = 0;
}
@@ -3582,6 +3622,90 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Instruction, operand_code: OperandCode, mem_oper: OperandSpec, length: &mut u8) -> Result<(), ()> {
let mut bytes_read = 0;
match operand_code {
+ OperandCode::ModRM_0x0f71 => {
+ instruction.operand_count = 2;
+
+ let modrm = read_modrm(&mut bytes_iter, instruction, length)?;
+ if modrm & 0xc0 != 0xc0 {
+ return Err(());
+ }
+
+ let r = (modrm >> 3) & 7;
+ match r {
+ 2 => {
+ instruction.opcode = Opcode::PSRLW;
+ }
+ 4 => {
+ instruction.opcode = Opcode::PSRAW;
+ }
+ 6 => {
+ instruction.opcode = Opcode::PSLLW;
+ }
+ _ => {
+ return Err(());
+ }
+ }
+
+ instruction.modrm_mmm = RegSpec { bank: RegisterBank::MM, num: modrm & 7 };
+ instruction.operands[0] = OperandSpec::RegMMM;
+ instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64;
+ instruction.operands[1] = OperandSpec::ImmI8;
+ },
+ OperandCode::ModRM_0x0f72 => {
+ instruction.operand_count = 2;
+
+ let modrm = read_modrm(&mut bytes_iter, instruction, length)?;
+ if modrm & 0xc0 != 0xc0 {
+ return Err(());
+ }
+
+ let r = (modrm >> 3) & 7;
+ match r {
+ 2 => {
+ instruction.opcode = Opcode::PSRLD;
+ }
+ 4 => {
+ instruction.opcode = Opcode::PSRAD;
+ }
+ 6 => {
+ instruction.opcode = Opcode::PSLLD;
+ }
+ _ => {
+ return Err(());
+ }
+ }
+
+ instruction.modrm_mmm = RegSpec { bank: RegisterBank::MM, num: modrm & 7 };
+ instruction.operands[0] = OperandSpec::RegMMM;
+ instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64;
+ instruction.operands[1] = OperandSpec::ImmI8;
+ },
+ OperandCode::ModRM_0x0f73 => {
+ instruction.operand_count = 2;
+
+ let modrm = read_modrm(&mut bytes_iter, instruction, length)?;
+ if modrm & 0xc0 != 0xc0 {
+ return Err(());
+ }
+
+ let r = (modrm >> 3) & 7;
+ match r {
+ 2 => {
+ instruction.opcode = Opcode::PSRLQ;
+ }
+ 6 => {
+ instruction.opcode = Opcode::PSLLQ;
+ }
+ _ => {
+ return Err(());
+ }
+ }
+
+ instruction.modrm_mmm = RegSpec { bank: RegisterBank::MM, num: modrm & 7 };
+ instruction.operands[0] = OperandSpec::RegMMM;
+ instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64;
+ instruction.operands[1] = OperandSpec::ImmI8;
+ },
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 e3ffa30..2d9c95e 100644
--- a/test/test.rs
+++ b/test/test.rs
@@ -265,6 +265,7 @@ fn evex() {
}
#[test]
+#[ignore]
fn vex() {
}
@@ -367,17 +368,29 @@ fn prefixed_0f() {
test_display(&[0x0f, 0x6e, 0xc2], "movd mm0, edx");
test_display(&[0x0f, 0x6f, 0x00], "movq mm0, [rax]");
test_display(&[0x0f, 0x6f, 0xc2], "movq mm0, mm2");
- test_display(&[0x0f, 0x70, 0x00, 0x7f], "pshufw mm0, qword [rax], 0x7f");
+ test_display(&[0x0f, 0x70, 0x00, 0x7f], "pshufw mm0, [rax], 0x7f");
+ test_display(&[0x4f, 0x0f, 0x70, 0x00, 0x7f], "pshufw mm0, [r8], 0x7f");
+ test_invalid(&[0x0f, 0x71, 0x00, 0x7f]);
+ test_invalid(&[0x0f, 0x71, 0xc0, 0x7f]);
test_display(&[0x0f, 0x71, 0xd0, 0x7f], "psrlw mm0, 0x7f");
test_display(&[0x0f, 0x71, 0xe0, 0x7f], "psraw mm0, 0x7f");
test_display(&[0x0f, 0x71, 0xf0, 0x7f], "psllw mm0, 0x7f");
+ test_invalid(&[0x0f, 0x72, 0x00, 0x7f]);
+ test_invalid(&[0x0f, 0x72, 0xc0, 0x7f]);
test_display(&[0x0f, 0x72, 0xd0, 0x7f], "psrld mm0, 0x7f");
test_display(&[0x0f, 0x72, 0xe0, 0x7f], "psrad mm0, 0x7f");
test_display(&[0x0f, 0x72, 0xf0, 0x7f], "pslld mm0, 0x7f");
+ test_invalid(&[0x0f, 0x73, 0x00, 0x7f]);
+ test_invalid(&[0x0f, 0x73, 0xc0, 0x7f]);
+ test_display(&[0x0f, 0x73, 0xd0, 0x7f], "psrlq mm0, 0x7f");
+ test_invalid(&[0x0f, 0x73, 0xe0, 0x7f]);
+ test_display(&[0x0f, 0x73, 0xf0, 0x7f], "psllq mm0, 0x7f");
test_display(&[0x0f, 0xa0], "push fs");
test_display(&[0x0f, 0xa1], "pop fs");
test_display(&[0x0f, 0xa2], "cpuid");
test_display(&[0x0f, 0xa4, 0xc0, 0x11], "shld eax, eax, 0x11");
+ test_display(&[0x66, 0x0f, 0xa4, 0xcf, 0x11], "shld di, cx, 0x11");
+ test_display(&[0x66, 0x45, 0x0f, 0xa4, 0xcf, 0x11], "shld r15w, r9w, 0x11");
test_display(&[0x0f, 0xa5, 0xc0], "shld eax, eax, cl");
test_display(&[0x0f, 0xa5, 0xc9], "shld ecx, ecx, cl");
}