aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-03-21 02:48:11 -0700
committeriximeow <me@iximeow.net>2021-03-21 02:48:11 -0700
commit5223427b217cc567deb55ea420b8da58aea64d68 (patch)
tree4b8256c45706e3ea94dd7234616a69e79ae45bff
parent0a3811ec18d2154f050aaf6e611a3d65f467c0cc (diff)
complete CET support, add UINTR, add missing VORP{S,D}, other cleanup
-rw-r--r--src/long_mode/display.rs26
-rw-r--r--src/long_mode/mod.rs116
-rw-r--r--src/long_mode/vex.rs10
-rw-r--r--test/long_mode/display.rs2
-rw-r--r--test/long_mode/mod.rs30
5 files changed, 160 insertions, 24 deletions
diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs
index 8f7bd9b..5c733a2 100644
--- a/src/long_mode/display.rs
+++ b/src/long_mode/display.rs
@@ -848,6 +848,8 @@ const MNEMONICS: &[&'static str] = &[
"vpalignr",
"vandps",
"vandpd",
+ "vorps",
+ "vorpd",
"vandnps",
"vandnpd",
"vpand",
@@ -1285,6 +1287,11 @@ const MNEMONICS: &[&'static str] = &[
// CET
"wruss",
"wrss",
+ "incssp",
+ "saveprevssp",
+ "setssbsy",
+ "clrssbsy",
+ "rstorssp",
// TDX
"tdcall",
@@ -1296,6 +1303,13 @@ const MNEMONICS: &[&'static str] = &[
"tpause",
"umonitor",
"umwait",
+
+ // UINTR
+ "uiret",
+ "testui",
+ "clui",
+ "stui",
+ "senduipi",
];
impl Opcode {
@@ -1462,6 +1476,8 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color
Opcode::VDPPD |
Opcode::VDPPS |
Opcode::VRCPPS |
+ Opcode::VORPD |
+ Opcode::VORPS |
Opcode::VANDPD |
Opcode::VANDPS |
Opcode::VANDNPD |
@@ -2298,6 +2314,11 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color
Opcode::ENQCMD |
Opcode::ENQCMDS |
Opcode::PTWRITE |
+ Opcode::UIRET |
+ Opcode::TESTUI |
+ Opcode::CLUI |
+ Opcode::STUI |
+ Opcode::SENDUIPI |
Opcode::LAR => { write!(out, "{}", colors.platform_op(self)) }
Opcode::CRC32 |
@@ -2330,6 +2351,11 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color
Opcode::LOADIWKEY |
Opcode::WRUSS |
Opcode::WRSS |
+ Opcode::INCSSP |
+ Opcode::SAVEPREVSSP |
+ Opcode::SETSSBSY |
+ Opcode::CLRSSBSY |
+ Opcode::RSTORSSP |
Opcode::AESDEC |
Opcode::AESDECLAST |
Opcode::AESENC |
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index 8e64021..266bd2e 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -1488,6 +1488,8 @@ pub enum Opcode {
VPALIGNR,
VANDPD,
VANDPS,
+ VORPD,
+ VORPS,
VANDNPD,
VANDNPS,
VPAND,
@@ -1940,6 +1942,11 @@ pub enum Opcode {
// CET
WRUSS,
WRSS,
+ INCSSP,
+ SAVEPREVSSP,
+ SETSSBSY,
+ CLRSSBSY,
+ RSTORSSP,
// TDX
TDCALL,
@@ -1951,6 +1958,13 @@ pub enum Opcode {
TPAUSE,
UMONITOR,
UMWAIT,
+
+ // UINTR
+ UIRET,
+ TESTUI,
+ CLUI,
+ STUI,
+ SENDUIPI,
}
#[derive(Debug)]
@@ -3109,6 +3123,8 @@ impl InstDecoder {
Opcode::VANDPS |
Opcode::VANDNPD |
Opcode::VANDNPS |
+ Opcode::VORPD |
+ Opcode::VORPS |
Opcode::VPANDN |
Opcode::VPAVGB |
Opcode::VPAVGW |
@@ -7233,9 +7249,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
0x1d => {
instruction.opcode = Opcode::PF2ID;
}
- 0x59 => {
- instruction.opcode = Opcode::PMULHRW;
- }
0x8a => {
instruction.opcode = Opcode::PFNACC;
}
@@ -7293,9 +7306,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
0xbb => {
instruction.opcode = Opcode::PSWAPD;
}
- 0xbe => {
- instruction.opcode = Opcode::PFPNACC;
- }
0xbf => {
instruction.opcode = Opcode::PAVGUSB;
}
@@ -7414,9 +7424,10 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
instruction.opcode = Opcode::VMXON;
instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?;
if instruction.operands[0] == OperandSpec::RegMMM {
- // this would be invalid as `vmxon`, so fall back to the parse as
- // f3-prefixed rdrand
- instruction.opcode = Opcode::RDRAND;
+ // invalid as `vmxon`, reg-form is `senduipi`
+ instruction.opcode = Opcode::SENDUIPI;
+ // and the operand is always a qword register
+ instruction.modrm_mmm.bank = RegisterBank::Q;
}
instruction.operand_count = 1;
}
@@ -8301,20 +8312,69 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
} 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);
+ if !instruction.prefixes.rep() {
+ return Err(DecodeError::InvalidOpcode);
+ }
+ instruction.opcode = Opcode::RSTORSSP;
+ instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 8, length)?;
+ instruction.operand_count = 1;
+ return Ok(());
}
let m = modrm & 7;
match m {
+ 0b000 => {
+ if !instruction.prefixes.rep() || instruction.prefixes.operand_size() || instruction.prefixes.repnz() {
+ return Err(DecodeError::InvalidOpcode);
+ }
+ instruction.opcode = Opcode::SETSSBSY;
+ instruction.operands[0] = OperandSpec::Nothing;
+ instruction.operand_count = 0;
+ }
+ 0b010 => {
+ if !instruction.prefixes.rep() || instruction.prefixes.operand_size() || instruction.prefixes.repnz() {
+ return Err(DecodeError::InvalidOpcode);
+ }
+ instruction.opcode = Opcode::SAVEPREVSSP;
+ instruction.operands[0] = OperandSpec::Nothing;
+ instruction.operand_count = 0;
+ }
+ 0b100 => {
+ if instruction.prefixes.rep() {
+ instruction.opcode = Opcode::UIRET;
+ instruction.operands[0] = OperandSpec::Nothing;
+ instruction.operand_count = 0;
+ }
+ }
+ 0b101 => {
+ if instruction.prefixes.rep() {
+ instruction.opcode = Opcode::TESTUI;
+ instruction.operands[0] = OperandSpec::Nothing;
+ instruction.operand_count = 0;
+ }
+ }
0b110 => {
+ if instruction.prefixes.rep() {
+ instruction.opcode = Opcode::CLUI;
+ instruction.operands[0] = OperandSpec::Nothing;
+ instruction.operand_count = 0;
+ return Ok(());
+ } else if instruction.prefixes.operand_size() || instruction.prefixes.repnz() {
+ return Err(DecodeError::InvalidOpcode);
+ }
instruction.opcode = Opcode::RDPKRU;
instruction.operands[0] = OperandSpec::Nothing;
instruction.operand_count = 0;
}
0b111 => {
+ if instruction.prefixes.rep() {
+ instruction.opcode = Opcode::STUI;
+ instruction.operands[0] = OperandSpec::Nothing;
+ instruction.operand_count = 0;
+ return Ok(());
+ } else if instruction.prefixes.operand_size() || instruction.prefixes.repnz() {
+ return Err(DecodeError::InvalidOpcode);
+ }
instruction.opcode = Opcode::WRPKRU;
instruction.operands[0] = OperandSpec::Nothing;
instruction.operand_count = 0;
@@ -8509,13 +8569,21 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
instruction.operands[0] = OperandSpec::RegMMM;
instruction.operand_count = 1;
}
+ 5 => {
+ instruction.opcode = Opcode::INCSSP;
+ let opwidth = if instruction.prefixes.rex().w() {
+ RegisterBank::Q
+ } else {
+ RegisterBank::D
+ };
+ instruction.modrm_mmm = RegSpec::from_parts(m, instruction.prefixes.rex().x(), opwidth);
+ 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.modrm_mmm = RegSpec::from_parts(m, instruction.prefixes.rex().x(), RegisterBank::Q);
+ instruction.operands[0] = OperandSpec::RegMMM;
instruction.operand_count = 1;
}
_ => {
@@ -8525,7 +8593,17 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter
}
return Ok(());
} else {
- return Err(DecodeError::InvalidOperand);
+ match r {
+ 6 => {
+ instruction.opcode = Opcode::CLRSSBSY;
+ instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 8, length)?;
+ instruction.operand_count = 1;
+ return Ok(());
+ }
+ _ => {
+ return Err(DecodeError::InvalidOperand);
+ }
+ }
}
}
diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs
index 71a5724..41f5c29 100644
--- a/src/long_mode/vex.rs
+++ b/src/long_mode/vex.rs
@@ -952,6 +952,11 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &
} else {
VEXOperandCode::G_V_E_xmm
}),
+ 0x56 => (Opcode::VORPS, if L {
+ VEXOperandCode::G_V_E_ymm
+ } else {
+ VEXOperandCode::G_V_E_xmm
+ }),
0x57 => (Opcode::VXORPS, if L {
VEXOperandCode::G_V_E_ymm
} else {
@@ -1099,6 +1104,11 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &
} else {
VEXOperandCode::G_V_E_xmm
}),
+ 0x56 => (Opcode::VORPD, if L {
+ VEXOperandCode::G_V_E_ymm
+ } else {
+ VEXOperandCode::G_V_E_xmm
+ }),
0x57 => (Opcode::VXORPD, if L {
VEXOperandCode::G_V_E_ymm
} else {
diff --git a/test/long_mode/display.rs b/test/long_mode/display.rs
index 7017270..2d1a540 100644
--- a/test/long_mode/display.rs
+++ b/test/long_mode/display.rs
@@ -1,7 +1,7 @@
use std::fmt::Write;
use yaxpeax_arch::{AddressBase, Decoder, LengthedInstruction};
-use yaxpeax_x86::long_mode::{DisplayStyle, InstDecoder, Opcode};
+use yaxpeax_x86::long_mode::{DisplayStyle, InstDecoder};
fn test_display(data: &[u8], expected: &'static str) {
test_display_under(&InstDecoder::default(), data, expected);
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index 130a7ab..fff10a2 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -5,7 +5,7 @@ mod display;
use std::fmt::Write;
use yaxpeax_arch::{AddressBase, Decoder, LengthedInstruction};
-use yaxpeax_x86::long_mode::{InstDecoder, Opcode};
+use yaxpeax_x86::long_mode::InstDecoder;
fn test_invalid(data: &[u8]) {
test_invalid_under(&InstDecoder::default(), data);
@@ -904,10 +904,10 @@ fn test_0f01() {
test_invalid(&[0x0f, 0x01, 0xe9]);
test_invalid(&[0x0f, 0x01, 0xea]);
test_invalid(&[0x0f, 0x01, 0xeb]);
- test_invalid(&[0x0f, 0x01, 0xec]);
- test_invalid(&[0x0f, 0x01, 0xed]);
test_display(&[0x0f, 0x01, 0xee], "rdpkru");
test_display(&[0x0f, 0x01, 0xef], "wrpkru");
+ test_invalid(&[0xf2, 0x0f, 0x01, 0xee]);
+ test_invalid(&[0xf2, 0x0f, 0x01, 0xef]);
test_display(&[0x4f, 0x0f, 0x01, 0xf0], "lmsw r8w");
test_display(&[0x0f, 0x01, 0xf0], "lmsw ax");
test_display(&[0x0f, 0x01, 0xf1], "lmsw cx");
@@ -1548,6 +1548,8 @@ fn test_vex() {
test_instr(&[0xc5, 0xe1, 0x54, 0x03], "vandps xmm0, xmm3, [rbx]");
test_instr(&[0xc5, 0xe0, 0x55, 0x03], "vandnpd xmm0, xmm3, [rbx]");
test_instr(&[0xc5, 0xe1, 0x55, 0x03], "vandnps xmm0, xmm3, [rbx]");
+ test_instr(&[0xc5, 0xe0, 0x56, 0x03], "vorpd xmm0, xmm3, [rbx]");
+ test_instr(&[0xc5, 0xe1, 0x56, 0x03], "vorps xmm0, xmm3, [rbx]");
}
#[test]
@@ -1801,7 +1803,6 @@ fn test_sha() {
fn test_vmx() {
test_display(&[0x0f, 0xc7, 0x3f], "vmptrst [rdi]");
test_display(&[0x0f, 0xc7, 0x37], "vmptrld [rdi]");
- test_display(&[0xf3, 0x0f, 0xc7, 0xf7], "rdrand edi");
test_display(&[0xf3, 0x0f, 0xc7, 0x37], "vmxon [rdi]");
test_display(&[0x66, 0x0f, 0xc7, 0xf7], "rdrand di");
test_display(&[0x66, 0x0f, 0xc7, 0x37], "vmclear [rdi]");
@@ -2274,10 +2275,17 @@ fn test_cet() {
// clrssbsy f3 0f ae /6
// endbr64 f3 0f ae fa
// endbr32 f3 0f ae fb
+ test_display(&[0xf3, 0x4f, 0x0f, 0xae, 0xe9], "incssp r9");
+ test_display(&[0xf3, 0x0f, 0xae, 0xe9], "incssp ecx");
test_display(&[0x3e, 0x4f, 0x0f, 0x38, 0xf6, 0x23], "wrss [r11], r12");
test_display(&[0x66, 0x0f, 0x38, 0xf5, 0x47, 0xe9], "wruss [rdi - 0x17], eax");
test_invalid(&[0x0f, 0x38, 0xf5, 0x47, 0xe9]);
test_invalid(&[0x66, 0x3e, 0x65, 0x3e, 0x0f, 0x38, 0xf5, 0xf0]);
+ test_display(&[0xf3, 0x0f, 0x01, 0xe8], "setssbsy");
+ test_display(&[0xf3, 0x0f, 0x01, 0xea], "saveprevssp");
+ test_display(&[0xf3, 0x0f, 0x01, 0x29], "rstorssp [rcx]");
+ test_display(&[0xf3, 0x66, 0x0f, 0x01, 0x29], "rstorssp [rcx]");
+ test_display(&[0xf3, 0x0f, 0xae, 0x30], "clrssbsy [rax]");
}
#[test]
@@ -2329,6 +2337,20 @@ fn test_key_locker() {
test_display(&[0xf3, 0x0f, 0x38, 0xfb, 0xde], "encodekey256 ebx, esi");
}
+// these uinter test cases come from llvm:
+// https://reviews.llvm.org/differential/changeset/?ref=2226860
+#[test]
+fn test_uintr() {
+ test_display(&[0xf3, 0x0f, 0x01, 0xec], "uiret");
+ test_display(&[0xf3, 0x0f, 0x01, 0xed], "testui");
+ test_display(&[0xf3, 0x0f, 0x01, 0xee], "clui");
+ test_display(&[0xf3, 0x0f, 0x01, 0xef], "stui");
+ test_display(&[0xf3, 0x0f, 0xc7, 0xf0], "senduipi rax");
+ test_display(&[0xf3, 0x0f, 0xc7, 0xf2], "senduipi rdx");
+ test_display(&[0xf3, 0x41, 0x0f, 0xc7, 0xf0], "senduipi r8");
+ test_display(&[0xf3, 0x41, 0x0f, 0xc7, 0xf5], "senduipi r13");
+}
+
// started shipping in sapphire rapids
#[test]
fn test_enqcmd() {