aboutsummaryrefslogtreecommitdiff
path: root/src/protected_mode/mod.rs
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-01-15 14:52:11 -0800
committeriximeow <me@iximeow.net>2021-01-15 14:52:11 -0800
commitf057c712f91b215034fe84fa0f22694aaa8dffb3 (patch)
tree6c28340154b900ba984ccd188fd7149aa4de6d75 /src/protected_mode/mod.rs
parent81e9b93aab9217cf7cb508f64b19fc1c0df024b5 (diff)
fix several missing or invalid decodings among 0f01 opcodes
* `mwaitx`, `monitorx`, `rdpru`, and `clzero` are now supported * swapgs is no longer decoded in protected mode * rdpkru and wrpkru are no longer decoded if mod bits != 11
Diffstat (limited to 'src/protected_mode/mod.rs')
-rw-r--r--src/protected_mode/mod.rs42
1 files changed, 39 insertions, 3 deletions
diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs
index b60ff34..9327f64 100644
--- a/src/protected_mode/mod.rs
+++ b/src/protected_mode/mod.rs
@@ -1036,6 +1036,8 @@ pub enum Opcode {
VMXOFF,
MONITOR,
MWAIT,
+ MONITORX,
+ MWAITX,
CLAC,
STAC,
ENCLS,
@@ -1051,6 +1053,9 @@ pub enum Opcode {
RDPKRU,
WRPKRU,
+ RDPRU,
+ CLZERO,
+
RDSEED,
RDRAND,
@@ -3191,6 +3196,12 @@ impl InstDecoder {
return Err(DecodeError::InvalidOpcode);
}
}
+ Opcode::MONITORX | Opcode::MWAITX | // these are gated on the `monitorx` and `mwaitx` cpuid bits, but are AMD-only.
+ Opcode::CLZERO | Opcode::RDPRU => { // again, gated on specific cpuid bits, but AMD-only.
+ if !self.amd_quirks() {
+ return Err(DecodeError::InvalidOpcode);
+ }
+ }
other => {
if !self.bmi1() {
if BMI1.contains(&other) {
@@ -7893,6 +7904,14 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
instruction.operand_count = 1;
instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?;
} else if r == 5 {
+ let mod_bits = modrm >> 6;
+ if mod_bits != 0b11 {
+ instruction.opcode = Opcode::Invalid;
+ instruction.operands[0] = OperandSpec::Nothing;
+ instruction.operand_count = 0;
+ return Err(DecodeError::InvalidOpcode);
+ }
+
let m = modrm & 7;
match m {
0b110 => {
@@ -7921,13 +7940,30 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
let m = modrm & 7;
if mod_bits == 0b11 {
if m == 0 {
- instruction.opcode = Opcode::SWAPGS;
- instruction.operands[0] = OperandSpec::Nothing;
- instruction.operand_count = 0;
+ // swapgs is not valid in modes other than 64-bit
+ instruction.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
} else if m == 1 {
instruction.opcode = Opcode::RDTSCP;
instruction.operands[0] = OperandSpec::Nothing;
instruction.operand_count = 0;
+ } else if m == 2 {
+ instruction.opcode = Opcode::MONITORX;
+ instruction.operands[0] = OperandSpec::Nothing;
+ instruction.operand_count = 0;
+ } else if m == 3 {
+ instruction.opcode = Opcode::MWAITX;
+ instruction.operands[0] = OperandSpec::Nothing;
+ instruction.operand_count = 0;
+ } else if m == 4 {
+ instruction.opcode = Opcode::CLZERO;
+ instruction.operands[0] = OperandSpec::Nothing;
+ instruction.operand_count = 0;
+ } else if m == 5 {
+ instruction.opcode = Opcode::RDPRU;
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.modrm_rrr = RegSpec::ecx();
+ instruction.operand_count = 1;
} else {
instruction.opcode = Opcode::Invalid;
return Err(DecodeError::InvalidOpcode);