aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-03-21 01:42:24 -0700
committeriximeow <me@iximeow.net>2021-03-21 01:42:24 -0700
commit0a3811ec18d2154f050aaf6e611a3d65f467c0cc (patch)
treeb10f4737ba9fed51285a765272da4997565e9eb3
parent68e719a30e989d6580f8077cb9afa5af3ddffa9a (diff)
add waitpkg, clean up unused values, old comments
-rw-r--r--src/long_mode/display.rs8
-rw-r--r--src/long_mode/mod.rs174
-rw-r--r--test/long_mode/mod.rs7
3 files changed, 113 insertions, 76 deletions
diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs
index 9986194..8f7bd9b 100644
--- a/src/long_mode/display.rs
+++ b/src/long_mode/display.rs
@@ -1291,6 +1291,11 @@ const MNEMONICS: &[&'static str] = &[
"seamret",
"seamops",
"seamcall",
+
+ // WAITPKG
+ "tpause",
+ "umonitor",
+ "umwait",
];
impl Opcode {
@@ -2233,6 +2238,9 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color
Opcode::SEAMRET |
Opcode::SEAMOPS |
Opcode::SEAMCALL |
+ Opcode::TPAUSE |
+ Opcode::UMONITOR |
+ Opcode::UMWAIT |
Opcode::LSL |
Opcode::SLDT |
Opcode::STR |
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index 5014e05..8e64021 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -881,10 +881,6 @@ const XSAVE: [Opcode; 10] = [
Opcode::XSETBV,
];
-// TODO:
-// TPAUSE
-// UMONITOR
-// UMWAIT
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Opcode {
@@ -1950,6 +1946,11 @@ pub enum Opcode {
SEAMRET,
SEAMOPS,
SEAMCALL,
+
+ // WAITPKG
+ TPAUSE,
+ UMONITOR,
+ UMWAIT,
}
#[derive(Debug)]
@@ -4001,7 +4002,6 @@ enum OperandCode {
ModRM_0x0f00 = OperandCodeBuilder::new().read_modrm().special_case(40).bits(),
ModRM_0x0f01 = OperandCodeBuilder::new().read_modrm().special_case(41).bits(),
- ModRM_0x660f01 = OperandCodeBuilder::new().read_modrm().special_case(52).bits(),
ModRM_0x0f0d = OperandCodeBuilder::new().read_modrm().special_case(42).bits(),
ModRM_0x0f0f = OperandCodeBuilder::new().read_modrm().special_case(65).bits(), // 3dnow
ModRM_0x0fae = OperandCodeBuilder::new().read_modrm().special_case(43).bits(),
@@ -4208,7 +4208,7 @@ enum OperandCode {
Gdq_Ed = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(17).bits(),
Gd_Ed = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(51).bits(),
Md_Gd = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(52).bits(),
- Edq_Gdq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(49).bits(),
+// Edq_Gdq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(49).bits(),
Gdq_Ev = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(40).bits(),
Mdq_Gdq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(51).bits(),
G_E_mm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().with_imm(false, 0).reg_mem().operand_case(29).bits(),
@@ -4873,7 +4873,7 @@ fn read_0f_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord {
if prefixes.repnz() {
match opcode {
0x00 => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00),
- 0x01 => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
+ 0x01 => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01),
0x02 => OpcodeRecord(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew),
0x03 => OpcodeRecord(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_Ew_LSL),
0x04 => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
@@ -5150,7 +5150,7 @@ fn read_0f_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord {
} else if prefixes.rep() {
match opcode {
0x00 => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00),
- 0x01 => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
+ 0x01 => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01),
0x02 => OpcodeRecord(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew),
0x03 => OpcodeRecord(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_Ew_LSL),
0x04 => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
@@ -5427,7 +5427,7 @@ fn read_0f_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord {
} else if prefixes.operand_size() {
match opcode {
0x00 => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00),
- 0x01 => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x660f01),
+ 0x01 => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01),
0x02 => OpcodeRecord(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew),
0x03 => OpcodeRecord(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_Ew_LSL),
0x04 => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
@@ -6088,9 +6088,6 @@ fn read_0f38_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord {
};
} else {
return match opcode {
- // TODO: straggler? 0x0f => Opcode::PALIGNR,
- // PALIGNR
- // OperandCode::G_E_mm_Ib
0x00 => OpcodeRecord(Interpretation::Instruction(Opcode::PSHUFB), OperandCode::G_E_mm),
0x01 => OpcodeRecord(Interpretation::Instruction(Opcode::PHADDW), OperandCode::G_E_mm),
0x02 => OpcodeRecord(Interpretation::Instruction(Opcode::PHADDD), OperandCode::G_E_mm),
@@ -6115,7 +6112,6 @@ fn read_0f38_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord {
0xf0 => OpcodeRecord(Interpretation::Instruction(Opcode::MOVBE), OperandCode::Gv_M),
0xf1 => OpcodeRecord(Interpretation::Instruction(Opcode::MOVBE), OperandCode::M_Gv),
0xf6 => OpcodeRecord(Interpretation::Instruction(Opcode::WRSS), OperandCode::Mdq_Gdq),
- // TODO: always 32-bit mov, be careful about memory size
0xf9 => OpcodeRecord(Interpretation::Instruction(Opcode::MOVDIRI), OperandCode::Md_Gd),
_ => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
};
@@ -6915,6 +6911,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
instruction.operands[0] = mem_oper;
instruction.operand_count = 2;
}
+ /*
OperandCode::Edq_Gdq => {
let bank = if instruction.prefixes.rex().w() {
RegisterBank::Q
@@ -6930,6 +6927,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
instruction.operands[0] = mem_oper;
instruction.operand_count = 2;
}
+ */
OperandCode::G_U_xmm => {
instruction.modrm_rrr.bank = RegisterBank::X;
if mem_oper != OperandSpec::RegMMM {
@@ -8103,41 +8101,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
}
instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?;
}
- OperandCode::ModRM_0x660f01 => {
- let modrm = read_modrm(&mut bytes_iter, length)?;
- let r = (modrm >> 3) & 7;
- if r == 1 {
- let mod_bits = modrm >> 6;
- let m = modrm & 7;
- if mod_bits == 0b11 {
- instruction.operands[0] = OperandSpec::Nothing;
- instruction.operand_count = 0;
- match m {
- 0b100 => {
- instruction.opcode = Opcode::TDCALL;
- }
- 0b101 => {
- instruction.opcode = Opcode::SEAMRET;
- }
- 0b110 => {
- instruction.opcode = Opcode::SEAMOPS;
- }
- 0b111 => {
- instruction.opcode = Opcode::SEAMCALL;
- }
- _ => {
- instruction.opcode = Opcode::Invalid;
- return Err(DecodeError::InvalidOpcode);
- }
- }
- return Ok(());
- } else {
- return Err(DecodeError::InvalidOpcode);
- }
- } else {
- return Err(DecodeError::InvalidOpcode);
- }
- }
OperandCode::ModRM_0x0f01 => {
let opwidth = imm_width_from_prefixes_64(SizeCode::vq, instruction.prefixes);
let modrm = read_modrm(&mut bytes_iter, length)?;
@@ -8180,26 +8143,50 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
if mod_bits == 0b11 {
instruction.operands[0] = OperandSpec::Nothing;
instruction.operand_count = 0;
- match m {
- 0b000 => {
- instruction.opcode = Opcode::MONITOR;
- }
- 0b001 => {
- instruction.opcode = Opcode::MWAIT;
- },
- 0b010 => {
- instruction.opcode = Opcode::CLAC;
- }
- 0b011 => {
- instruction.opcode = Opcode::STAC;
- }
- 0b111 => {
- instruction.opcode = Opcode::ENCLS;
+ if instruction.prefixes.operand_size() {
+ match m {
+ 0b100 => {
+ instruction.opcode = Opcode::TDCALL;
+ }
+ 0b101 => {
+ instruction.opcode = Opcode::SEAMRET;
+ }
+ 0b110 => {
+ instruction.opcode = Opcode::SEAMOPS;
+ }
+ 0b111 => {
+ instruction.opcode = Opcode::SEAMCALL;
+ }
+ _ => {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ }
}
- _ => {
- instruction.opcode = Opcode::Invalid;
+ } else {
+ if instruction.prefixes.rep() || instruction.prefixes.repnz() {
return Err(DecodeError::InvalidOpcode);
}
+ match m {
+ 0b000 => {
+ instruction.opcode = Opcode::MONITOR;
+ }
+ 0b001 => {
+ instruction.opcode = Opcode::MWAIT;
+ },
+ 0b010 => {
+ instruction.opcode = Opcode::CLAC;
+ }
+ 0b011 => {
+ instruction.opcode = Opcode::STAC;
+ }
+ 0b111 => {
+ instruction.opcode = Opcode::ENCLS;
+ }
+ _ => {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ }
+ }
}
} else {
instruction.opcode = Opcode::SIDT;
@@ -8398,8 +8385,12 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
}
}
OperandCode::ModRM_0x0fae => {
+ let modrm = read_modrm(&mut bytes_iter, length)?;
+ let r = (modrm >> 3) & 7;
+ let m = modrm & 7;
+
if instruction.prefixes.operand_size() && !(instruction.prefixes.rep() || instruction.prefixes.repnz()) {
- let modrm = read_modrm(&mut bytes_iter, length)?;
+ instruction.prefixes.unset_operand_size();
if modrm < 0xc0 {
instruction.opcode = match (modrm >> 3) & 7 {
6 => {
@@ -8416,17 +8407,45 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 1 /* opwidth */, length)?;
instruction.operand_count = 1;
} else {
- instruction.opcode = Opcode::Invalid;
- return Err(DecodeError::InvalidOpcode);
+ instruction.opcode = match (modrm >> 3) & 7 {
+ 6 => {
+ Opcode::TPAUSE
+ }
+ _ => {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ }
+ };
+ let opwidth = if instruction.prefixes.rex().w() { 8 } else { 4 };
+ instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?;
+ instruction.operand_count = 1;
}
return Ok(());
}
- if instruction.prefixes.rep() {
- let modrm = read_modrm(&mut bytes_iter, length)?;
- let r = (modrm >> 3) & 7;
+ if instruction.prefixes.repnz() {
+ if (modrm & 0xc0) == 0xc0 {
+ match r {
+ 6 => {
+ instruction.opcode = Opcode::UMWAIT;
+ instruction.modrm_rrr = RegSpec {
+ bank: if instruction.prefixes.rex().w() { RegisterBank::Q } else { RegisterBank::D },
+ num: m + if instruction.prefixes.rex().x() { 0b1000 } else { 0 },
+ };
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operand_count = 1;
+ }
+ _ => {
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ }
+ }
+ return Ok(());
+ }
+ }
+ if instruction.prefixes.rep() {
if r == 4 {
if instruction.prefixes.operand_size() {
// xed specifically rejects this. seeems out of line since rep takes
@@ -8444,7 +8463,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
return Ok(());
}
if (modrm & 0xc0) == 0xc0 {
- let m = modrm & 7;
match r {
0 => {
instruction.opcode = Opcode::RDFSBASE;
@@ -8491,6 +8509,15 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
instruction.operands[0] = OperandSpec::RegMMM;
instruction.operand_count = 1;
}
+ 6 => {
+ instruction.opcode = Opcode::UMONITOR;
+ instruction.modrm_rrr = RegSpec {
+ bank: RegisterBank::Q,
+ num: m + if instruction.prefixes.rex().x() { 0b1000 } else { 0 },
+ };
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operand_count = 1;
+ }
_ => {
instruction.opcode = Opcode::Invalid;
return Err(DecodeError::InvalidOpcode);
@@ -8502,15 +8529,12 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
}
}
- let modrm = read_modrm(&mut bytes_iter, length)?;
- let r = (modrm >> 3) & 7;
let mod_bits = modrm >> 6;
// all the 0b11 instructions are err or no-operands
if mod_bits == 0b11 {
instruction.operands[0] = OperandSpec::Nothing;
instruction.operand_count = 0;
- let m = modrm & 7;
match r {
// invalid rrr for 0x0fae, mod: 11
0 | 1 | 2 | 3 | 4 => {
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index 3e8a307..130a7ab 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -1375,7 +1375,10 @@ fn test_misc() {
test_display(&[0x66, 0x0f, 0xae, 0x3f], "clflushopt [rdi]"); // or clflush without 66
test_invalid(&[0x66, 0x0f, 0xae, 0xff]);
test_display(&[0x66, 0x0f, 0xae, 0x37], "clwb [rdi]");
- test_invalid(&[0x66, 0x0f, 0xae, 0xf7]);
+ test_display(&[0x66, 0x0f, 0xae, 0xf7], "tpause edi");
+ test_display(&[0xf3, 0x0f, 0xae, 0xf1], "umonitor rcx");
+ test_display(&[0xf2, 0x0f, 0xae, 0xf1], "umwait ecx");
+ test_display(&[0xf2, 0x4f, 0x0f, 0xae, 0xf1], "umwait r9");
test_display(&[0x66, 0x0f, 0x38, 0x80, 0x2f], "invept ebp, [rdi]");
test_display(&[0x66, 0x49, 0x0f, 0x38, 0x80, 0x2f], "invept rbp, [r15]");
test_invalid(&[0x0f, 0x38, 0x80, 0x2f]);
@@ -1388,6 +1391,8 @@ fn test_misc() {
test_display(&[0x66, 0x49, 0x0f, 0x38, 0x82, 0x2f], "invpcid rbp, [r15]");
test_invalid(&[0x0f, 0x38, 0x82, 0x2f]);
test_invalid(&[0x43, 0x0f, 0x38, 0x82, 0x2f]);
+ test_display(&[0x66, 0x0f, 0xae, 0xf1], "tpause ecx");
+ test_display(&[0x66, 0x4f, 0x0f, 0xae, 0xf1], "tpause r9");
}
#[test]