From e15ef43a243ae0e0db369cead1786f4f2c4e690e Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 4 Jul 2021 13:21:09 -0700 Subject: support xacquire/xrelease prefixing --- src/long_mode/display.rs | 25 +++++++++++++++++++++++-- src/long_mode/mod.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ src/protected_mode/display.rs | 25 +++++++++++++++++++++++-- src/protected_mode/mod.rs | 41 +++++++++++++++++++++++++++++++++++++++++ src/real_mode/display.rs | 25 +++++++++++++++++++++++-- src/real_mode/mod.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 193 insertions(+), 6 deletions(-) (limited to 'src') 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(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(instr: &Instruction, colors: fn contextualize_c(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(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(instr: &Instruction, colors: fn contextualize_c(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(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(instr: &Instruction, colors: fn contextualize_c(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)] -- cgit v1.1