diff options
| author | iximeow <me@iximeow.net> | 2021-07-04 13:21:09 -0700 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2021-07-04 13:21:09 -0700 | 
| commit | e15ef43a243ae0e0db369cead1786f4f2c4e690e (patch) | |
| tree | e6ee5bebf5c1681cc67712b01d3b89c04b824af9 | |
| parent | 2c84821ee0d9807d20ea82b8550edde09426a867 (diff) | |
support xacquire/xrelease prefixing
| -rw-r--r-- | src/long_mode/display.rs | 25 | ||||
| -rw-r--r-- | src/long_mode/mod.rs | 42 | ||||
| -rw-r--r-- | src/protected_mode/display.rs | 25 | ||||
| -rw-r--r-- | src/protected_mode/mod.rs | 41 | ||||
| -rw-r--r-- | src/real_mode/display.rs | 25 | ||||
| -rw-r--r-- | src/real_mode/mod.rs | 41 | ||||
| -rw-r--r-- | test/long_mode/mod.rs | 2 | ||||
| -rw-r--r-- | test/protected_mode/mod.rs | 2 | ||||
| -rw-r--r-- | test/real_mode/mod.rs | 3 | 
9 files changed, 196 insertions, 10 deletions
diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs index 948df53..7f21b35 100644 --- a/src/long_mode/display.rs +++ b/src/long_mode/display.rs @@ -3311,8 +3311,14 @@ impl Instruction {  }  fn contextualize_intel<T: fmt::Write, Y: YaxColors>(instr: &Instruction, colors: &Y, _address: u64, _context: Option<&NoContext>, out: &mut T) -> fmt::Result { +    if instr.xacquire() { +        out.write_str("xacquire ")?; +    } +    if instr.xrelease() { +        out.write_str("xrelease ")?; +    }      if instr.prefixes.lock() { -        write!(out, "lock ")?; +        out.write_str("lock ")?;      }      if instr.prefixes.rep_any() { @@ -3423,8 +3429,23 @@ fn contextualize_intel<T: fmt::Write, Y: YaxColors>(instr: &Instruction, colors:  fn contextualize_c<T: fmt::Write, Y: YaxColors>(instr: &Instruction, _colors: &Y, _address: u64, _context: Option<&NoContext>, out: &mut T) -> fmt::Result {      let mut brace_count = 0; +    let mut prefixed = false; + +    if instr.xacquire() { +        out.write_str("xacquire ")?; +        prefixed = true; +    } +    if instr.xrelease() { +        out.write_str("xrelease ")?; +        prefixed = true; +    }      if instr.prefixes.lock() { -        out.write_str("lock { ")?; +        out.write_str("lock ")?; +        prefixed = true; +    } + +    if prefixed { +        out.write_str("{ ")?;          brace_count += 1;      } diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 79f3fee..6e3e21d 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -4470,6 +4470,48 @@ impl Instruction {              instr: self,          }      } + +    /// does this instruction include the `xacquire` hint for hardware lock elision? +    pub fn xacquire(&self) -> bool { +        if self.prefixes.repnz() { +            // xacquire is permitted on typical `lock` instructions, OR `xchg` with memory operand, +            // regardless of `lock` prefix. +            if self.prefixes.lock() { +                true +            } else if self.opcode == Opcode::XCHG { +                self.operands[0] != OperandSpec::RegMMM && self.operands[1] != OperandSpec::RegMMM +            } else { +                false +            } +        } else { +            false +        } +    } + +    /// does this instruction include the `xrelease` hint for hardware lock elision? +    pub fn xrelease(&self) -> bool { +        if self.prefixes.rep() { +            // xrelease is permitted on typical `lock` instructions, OR `xchg` with memory operand, +            // regardless of `lock` prefix. additionally, xrelease is permitted on some forms of mov. +            if self.prefixes.lock() { +                true +            } else if self.opcode == Opcode::XCHG { +                self.operands[0] != OperandSpec::RegMMM && self.operands[1] != OperandSpec::RegMMM +            } else if self.opcode == Opcode::MOV { +                self.operands[0] != OperandSpec::RegMMM && ( +                    self.operands[1] == OperandSpec::RegRRR || +                    self.operands[1] == OperandSpec::ImmI8 || +                    self.operands[1] == OperandSpec::ImmI16 || +                    self.operands[1] == OperandSpec::ImmI32 || +                    self.operands[1] == OperandSpec::ImmI64 +                ) +            } else { +                false +            } +        } else { +            false +        } +    }  }  #[derive(Debug, Copy, Clone, Eq, PartialEq)] diff --git a/src/protected_mode/display.rs b/src/protected_mode/display.rs index c5892c2..0b11ea0 100644 --- a/src/protected_mode/display.rs +++ b/src/protected_mode/display.rs @@ -3324,8 +3324,14 @@ impl Instruction {  }  fn contextualize_intel<T: fmt::Write, Y: YaxColors>(instr: &Instruction, colors: &Y, _address: u32, _context: Option<&NoContext>, out: &mut T) -> fmt::Result { +    if instr.xacquire() { +        out.write_str("xacquire ")?; +    } +    if instr.xrelease() { +        out.write_str("xrelease ")?; +    }      if instr.prefixes.lock() { -        write!(out, "lock ")?; +        out.write_str("lock ")?;      }      if instr.prefixes.rep_any() { @@ -3436,8 +3442,23 @@ fn contextualize_intel<T: fmt::Write, Y: YaxColors>(instr: &Instruction, colors:  fn contextualize_c<T: fmt::Write, Y: YaxColors>(instr: &Instruction, _colors: &Y, _address: u32, _context: Option<&NoContext>, out: &mut T) -> fmt::Result {      let mut brace_count = 0; +    let mut prefixed = false; + +    if instr.xacquire() { +        out.write_str("xacquire ")?; +        prefixed = true; +    } +    if instr.xrelease() { +        out.write_str("xrelease ")?; +        prefixed = true; +    }      if instr.prefixes.lock() { -        out.write_str("lock { ")?; +        out.write_str("lock ")?; +        prefixed = true; +    } + +    if prefixed { +        out.write_str("{ ")?;          brace_count += 1;      } diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index f5d7981..aedbbea 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -4412,6 +4412,47 @@ impl Instruction {              instr: self,          }      } + +    /// does this instruction include the `xacquire` hint for hardware lock elision? +    pub fn xacquire(&self) -> bool { +        if self.prefixes.repnz() { +            // xacquire is permitted on typical `lock` instructions, OR `xchg` with memory operand, +            // regardless of `lock` prefix. +            if self.prefixes.lock() { +                true +            } else if self.opcode == Opcode::XCHG { +                self.operands[0] != OperandSpec::RegMMM && self.operands[1] != OperandSpec::RegMMM +            } else { +                false +            } +        } else { +            false +        } +    } + +    /// does this instruction include the `xrelease` hint for hardware lock elision? +    pub fn xrelease(&self) -> bool { +        if self.prefixes.rep() { +            // xrelease is permitted on typical `lock` instructions, OR `xchg` with memory operand, +            // regardless of `lock` prefix. additionally, xrelease is permitted on some forms of mov. +            if self.prefixes.lock() { +                true +            } else if self.opcode == Opcode::XCHG { +                self.operands[0] != OperandSpec::RegMMM && self.operands[1] != OperandSpec::RegMMM +            } else if self.opcode == Opcode::MOV { +                self.operands[0] != OperandSpec::RegMMM && ( +                    self.operands[1] == OperandSpec::RegRRR || +                    self.operands[1] == OperandSpec::ImmI8 || +                    self.operands[1] == OperandSpec::ImmI16 || +                    self.operands[1] == OperandSpec::ImmI32 +                ) +            } else { +                false +            } +        } else { +            false +        } +    }  }  #[derive(Debug, Copy, Clone, Eq, PartialEq)] diff --git a/src/real_mode/display.rs b/src/real_mode/display.rs index a6e0a32..29bfa3a 100644 --- a/src/real_mode/display.rs +++ b/src/real_mode/display.rs @@ -3324,8 +3324,14 @@ impl Instruction {  }  fn contextualize_intel<T: fmt::Write, Y: YaxColors>(instr: &Instruction, colors: &Y, _address: u32, _context: Option<&NoContext>, out: &mut T) -> fmt::Result { +    if instr.xacquire() { +        out.write_str("xacquire ")?; +    } +    if instr.xrelease() { +        out.write_str("xrelease ")?; +    }      if instr.prefixes.lock() { -        write!(out, "lock ")?; +        out.write_str("lock ")?;      }      if instr.prefixes.rep_any() { @@ -3436,8 +3442,23 @@ fn contextualize_intel<T: fmt::Write, Y: YaxColors>(instr: &Instruction, colors:  fn contextualize_c<T: fmt::Write, Y: YaxColors>(instr: &Instruction, _colors: &Y, _address: u32, _context: Option<&NoContext>, out: &mut T) -> fmt::Result {      let mut brace_count = 0; +    let mut prefixed = false; + +    if instr.xacquire() { +        out.write_str("xacquire ")?; +        prefixed = true; +    } +    if instr.xrelease() { +        out.write_str("xrelease ")?; +        prefixed = true; +    }      if instr.prefixes.lock() { -        out.write_str("lock { ")?; +        out.write_str("lock ")?; +        prefixed = true; +    } + +    if prefixed { +        out.write_str("{ ")?;          brace_count += 1;      } diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs index 8376230..bfcb79f 100644 --- a/src/real_mode/mod.rs +++ b/src/real_mode/mod.rs @@ -4422,6 +4422,47 @@ impl Instruction {              instr: self,          }      } + +    /// does this instruction include the `xacquire` hint for hardware lock elision? +    pub fn xacquire(&self) -> bool { +        if self.prefixes.repnz() { +            // xacquire is permitted on typical `lock` instructions, OR `xchg` with memory operand, +            // regardless of `lock` prefix. +            if self.prefixes.lock() { +                true +            } else if self.opcode == Opcode::XCHG { +                self.operands[0] != OperandSpec::RegMMM && self.operands[1] != OperandSpec::RegMMM +            } else { +                false +            } +        } else { +            false +        } +    } + +    /// does this instruction include the `xrelease` hint for hardware lock elision? +    pub fn xrelease(&self) -> bool { +        if self.prefixes.rep() { +            // xrelease is permitted on typical `lock` instructions, OR `xchg` with memory operand, +            // regardless of `lock` prefix. additionally, xrelease is permitted on some forms of mov. +            if self.prefixes.lock() { +                true +            } else if self.opcode == Opcode::XCHG { +                self.operands[0] != OperandSpec::RegMMM && self.operands[1] != OperandSpec::RegMMM +            } else if self.opcode == Opcode::MOV { +                self.operands[0] != OperandSpec::RegMMM && ( +                    self.operands[1] == OperandSpec::RegRRR || +                    self.operands[1] == OperandSpec::ImmI8 || +                    self.operands[1] == OperandSpec::ImmI16 || +                    self.operands[1] == OperandSpec::ImmI32 +                ) +            } else { +                false +            } +        } else { +            false +        } +    }  }  #[derive(Debug, Copy, Clone, Eq, PartialEq)] diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs index 6c2cdc9..1573580 100644 --- a/test/long_mode/mod.rs +++ b/test/long_mode/mod.rs @@ -1194,7 +1194,7 @@ fn test_prefixes() {      test_display(&[0xf0, 0x31, 0x00], "lock xor dword [rax], eax");      test_display(&[0xf0, 0x80, 0x30, 0x00], "lock xor byte [rax], 0x0");      test_display(&[0xf0, 0x0f, 0xbb, 0x17], "lock btc dword [rdi], edx"); -    test_display(&[0x66, 0x2e, 0xf2, 0xf0, 0x0f, 0xbb, 0x13], "lock btc word [rbx], dx"); +    test_display(&[0x66, 0x2e, 0xf2, 0xf0, 0x0f, 0xbb, 0x13], "xacquire lock btc word [rbx], dx");      test_invalid(&[0xf0, 0xc7, 0x00, 0x00, 0x00, 0x00]);      test_display(&[0x0f, 0xc1, 0xcc], "xadd esp, ecx");      test_display(&[0x66, 0x0f, 0xc1, 0xcc], "xadd sp, cx"); diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs index dd52cfe..65e112f 100644 --- a/test/protected_mode/mod.rs +++ b/test/protected_mode/mod.rs @@ -1080,7 +1080,7 @@ fn test_prefixes() {      test_display(&[0xf0, 0x31, 0x00], "lock xor dword [eax], eax");      test_display(&[0xf0, 0x80, 0x30, 0x00], "lock xor byte [eax], 0x0");      test_display(&[0xf0, 0x0f, 0xbb, 0x17], "lock btc dword [edi], edx"); -    test_display(&[0x66, 0x2e, 0xf2, 0xf0, 0x0f, 0xbb, 0x13], "lock btc word cs:[ebx], dx"); +    test_display(&[0x66, 0x2e, 0xf2, 0xf0, 0x0f, 0xbb, 0x13], "xacquire lock btc word cs:[ebx], dx");      test_invalid(&[0xf0, 0xc7, 0x00, 0x00, 0x00, 0x00]);      test_display(&[0x0f, 0xc1, 0xcc], "xadd esp, ecx");      test_display(&[0x66, 0x0f, 0xc1, 0xcc], "xadd sp, cx"); diff --git a/test/real_mode/mod.rs b/test/real_mode/mod.rs index b182880..54bae05 100644 --- a/test/real_mode/mod.rs +++ b/test/real_mode/mod.rs @@ -16878,8 +16878,7 @@ fn test_real_mode() {      test_display(&[0x66, 0x0f, 0xfe, 0xc1], "paddd xmm0, xmm1");      test_display(&[0x66, 0x0f, 0xff, 0x01], "ud0 eax, dword [bx + di]");      test_display(&[0x66, 0x0f, 0xff, 0xc1], "ud0 eax, ecx"); -// TODO: -//    test_display(&[0x66, 0x2e, 0xf2, 0xf0, 0x0f, 0xbb, 0x13], "xacquire lock btc dword cs:[bp + di], edx"); +    test_display(&[0x66, 0x2e, 0xf2, 0xf0, 0x0f, 0xbb, 0x13], "xacquire lock btc dword cs:[bp + di], edx");      test_display(&[0x66, 0x31, 0xc0], "xor eax, eax");      test_display(&[0x66, 0x32, 0xc0], "xor al, al");      test_display(&[0x66, 0x32, 0xc5], "xor al, ch");  | 
