diff options
| -rw-r--r-- | src/long_mode/display.rs | 26 | ||||
| -rw-r--r-- | src/long_mode/mod.rs | 116 | ||||
| -rw-r--r-- | src/long_mode/vex.rs | 10 | ||||
| -rw-r--r-- | test/long_mode/display.rs | 2 | ||||
| -rw-r--r-- | test/long_mode/mod.rs | 30 | 
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() {  | 
