aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/long_mode/display.rs10
-rw-r--r--src/long_mode/mod.rs48
-rw-r--r--test/long_mode/mod.rs24
3 files changed, 72 insertions, 10 deletions
diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs
index 3e38d8d..9986194 100644
--- a/src/long_mode/display.rs
+++ b/src/long_mode/display.rs
@@ -1285,6 +1285,12 @@ const MNEMONICS: &[&'static str] = &[
// CET
"wruss",
"wrss",
+
+ // TDX
+ "tdcall",
+ "seamret",
+ "seamops",
+ "seamcall",
];
impl Opcode {
@@ -2223,6 +2229,10 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color
Opcode::SYSRET |
Opcode::CLTS |
Opcode::SYSCALL |
+ Opcode::TDCALL |
+ Opcode::SEAMRET |
+ Opcode::SEAMOPS |
+ Opcode::SEAMCALL |
Opcode::LSL |
Opcode::SLDT |
Opcode::STR |
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index 9410b2b..5014e05 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -1944,6 +1944,12 @@ pub enum Opcode {
// CET
WRUSS,
WRSS,
+
+ // TDX
+ TDCALL,
+ SEAMRET,
+ SEAMOPS,
+ SEAMCALL,
}
#[derive(Debug)]
@@ -3995,6 +4001,7 @@ 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(),
@@ -4866,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::ModRM_0x0f01),
+ 0x01 => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
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),
@@ -5143,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::ModRM_0x0f01),
+ 0x01 => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
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),
@@ -5420,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_0x0f01),
+ 0x01 => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x660f01),
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),
@@ -8096,6 +8103,41 @@ 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)?;
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index b024103..3e8a307 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -607,13 +607,15 @@ fn test_sse3() {
test_instr(&[0xf2, 0x0f, 0x12, 0xcf], "movddup xmm1, xmm7");
test_instr(&[0xf2, 0x4f, 0x0f, 0x12, 0xcf], "movddup xmm9, xmm15");
- test_instr(&[0x66, 0x0f, 0x01, 0xc8], "monitor");
- test_instr(&[0xf2, 0x0f, 0x01, 0xc8], "monitor");
- test_instr(&[0xf3, 0x0f, 0x01, 0xc8], "monitor");
-
- test_instr(&[0x66, 0x0f, 0x01, 0xc9], "mwait");
- test_instr(&[0xf2, 0x0f, 0x01, 0xc9], "mwait");
- test_instr(&[0xf3, 0x0f, 0x01, 0xc9], "mwait");
+ test_instr(&[0x0f, 0x01, 0xc8], "monitor");
+ test_invalid(&[0x66, 0x0f, 0x01, 0xc8]);
+ test_invalid(&[0xf3, 0x0f, 0x01, 0xc8]);
+ test_invalid(&[0xf2, 0x0f, 0x01, 0xc8]);
+
+ test_instr(&[0x0f, 0x01, 0xc9], "mwait");
+ test_invalid(&[0x66, 0x0f, 0x01, 0xc9]);
+ test_invalid(&[0xf2, 0x0f, 0x01, 0xc9]);
+ test_invalid(&[0xf3, 0x0f, 0x01, 0xc9]);
}
#[test]
@@ -2335,3 +2337,11 @@ fn test_gfni() {
test_display(&[0x66, 0x36, 0x0f, 0x3a, 0xce, 0x8c, 0x56, 0x9e, 0x82, 0xd1, 0xbe, 0xad], "gf2p8affineqb xmm1, [rsi + rdx * 2 - 0x412e7d62], 0xad");
test_display(&[0x66, 0x4e, 0x0f, 0x38, 0xcf, 0x1c, 0x54], "gf2p8mulb xmm11, [rsp + r10 * 2]");
}
+
+#[test]
+fn test_tdx() {
+ test_display(&[0x66, 0x0f, 0x01, 0xcc], "tdcall");
+ test_display(&[0x66, 0x0f, 0x01, 0xcd], "seamret");
+ test_display(&[0x66, 0x0f, 0x01, 0xce], "seamops");
+ test_display(&[0x66, 0x0f, 0x01, 0xcf], "seamcall");
+}