#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod enums;
mod enums_shared;
#[cfg(feature = "fast_fmt")]
mod fast;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod fmt_consts;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod fmt_opt_provider;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod fmt_opts;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod fmt_utils;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm", feature = "fast_fmt"))]
mod fmt_utils_all;
#[cfg(feature = "gas")]
mod gas;
#[cfg(feature = "intel")]
mod intel;
#[cfg(feature = "masm")]
mod masm;
#[cfg(feature = "nasm")]
mod nasm;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod num_fmt;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod num_fmt_opts;
mod pseudo_ops;
mod regs_tbl;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod string_output;
mod strings_data;
mod strings_tbl;
mod symres;
#[cfg(test)]
pub(crate) mod tests;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use self::enums::*;
pub use self::enums_shared::*;
#[cfg(feature = "fast_fmt")]
pub use self::fast::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use self::fmt_opt_provider::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use self::fmt_opts::*;
#[cfg(feature = "gas")]
pub use self::gas::*;
#[cfg(feature = "intel")]
pub use self::intel::*;
#[cfg(feature = "masm")]
pub use self::masm::*;
#[cfg(feature = "nasm")]
pub use self::nasm::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
use self::num_fmt::NumberFormatter;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use self::num_fmt_opts::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use self::string_output::*;
pub use self::symres::*;
use super::*;
#[cfg(not(feature = "std"))]
use alloc::string::String;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use core::{i16, i32};
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
use core::{i8, u16, u32, u8};
#[derive(Debug, Default, Clone)]
struct FormatterString {
lower: String,
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
upper: String,
}
impl FormatterString {
#[cfg_attr(has_must_use, must_use)]
fn new(lower: String) -> Self {
debug_assert_eq!(lower, lower.to_lowercase());
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
{
Self { upper: lower.to_uppercase(), lower }
}
#[cfg(not(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm")))]
{
Self { lower }
}
}
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
#[cfg_attr(has_must_use, must_use)]
fn with_strings(strings: Vec<String>) -> Vec<Self> {
strings.into_iter().map(FormatterString::new).collect()
}
#[cfg_attr(has_must_use, must_use)]
fn new_str(lower: &str) -> Self {
debug_assert_eq!(lower, lower.to_lowercase());
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
{
Self { lower: String::from(lower), upper: lower.to_uppercase() }
}
#[cfg(not(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm")))]
{
Self { lower: String::from(lower) }
}
}
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
#[cfg_attr(has_must_use, must_use)]
#[inline]
fn len(&self) -> usize {
self.lower.len()
}
#[cfg(any(feature = "gas", feature = "intel", feature = "nasm"))]
#[cfg_attr(has_must_use, must_use)]
#[inline]
fn is_default(&self) -> bool {
self.lower.is_empty()
}
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
#[cfg_attr(has_must_use, must_use)]
#[inline]
fn get(&self, upper: bool) -> &str {
if upper {
&self.upper
} else {
&self.lower
}
}
#[cfg(feature = "fast_fmt")]
#[cfg_attr(has_must_use, must_use)]
#[inline]
fn lower(&self) -> &str {
&self.lower
}
}
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub trait FormatterOutput {
fn write(&mut self, text: &str, kind: FormatterTextKind);
#[inline]
#[allow(unused_variables)]
fn write_prefix(&mut self, instruction: &Instruction, text: &str, prefix: PrefixKind) {
self.write(text, FormatterTextKind::Prefix);
}
#[inline]
#[allow(unused_variables)]
fn write_mnemonic(&mut self, instruction: &Instruction, text: &str) {
self.write(text, FormatterTextKind::Mnemonic);
}
#[inline]
#[cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))]
#[allow(unused_variables)]
fn write_number(
&mut self, instruction: &Instruction, operand: u32, instruction_operand: Option<u32>, text: &str, value: u64, number_kind: NumberKind,
kind: FormatterTextKind,
) {
self.write(text, kind);
}
#[inline]
#[allow(unused_variables)]
fn write_decorator(&mut self, instruction: &Instruction, operand: u32, instruction_operand: Option<u32>, text: &str, decorator: DecoratorKind) {
self.write(text, FormatterTextKind::Decorator);
}
#[inline]
#[allow(unused_variables)]
fn write_register(&mut self, instruction: &Instruction, operand: u32, instruction_operand: Option<u32>, text: &str, register: Register) {
self.write(text, FormatterTextKind::Register);
}
#[inline]
#[allow(unused_variables)]
fn write_symbol(&mut self, instruction: &Instruction, operand: u32, instruction_operand: Option<u32>, address: u64, symbol: &SymbolResult) {
match symbol.text {
SymResTextInfo::Text(ref part) => {
let s = match &part.text {
&SymResString::Str(s) => s,
&SymResString::String(ref s) => s.as_str(),
};
self.write(s, part.color);
}
SymResTextInfo::TextVec(v) => {
for part in v.iter() {
let s = match &part.text {
&SymResString::Str(s) => s,
&SymResString::String(ref s) => s.as_str(),
};
self.write(s, part.color);
}
}
}
}
}
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
struct FormatterOutputMethods;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
impl FormatterOutputMethods {
#[cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))]
fn write1(
output: &mut FormatterOutput, instruction: &Instruction, operand: u32, instruction_operand: Option<u32>, options: &FormatterOptions,
number_formatter: &mut NumberFormatter, number_options: &NumberFormattingOptions, address: u64, symbol: &SymbolResult,
show_symbol_address: bool,
) {
FormatterOutputMethods::write2(
output,
instruction,
operand,
instruction_operand,
options,
number_formatter,
number_options,
address,
symbol,
show_symbol_address,
true,
false,
);
}
#[cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))]
fn write2(
output: &mut FormatterOutput, instruction: &Instruction, operand: u32, instruction_operand: Option<u32>, options: &FormatterOptions,
number_formatter: &mut NumberFormatter, number_options: &NumberFormattingOptions, address: u64, symbol: &SymbolResult,
show_symbol_address: bool, write_minus_if_signed: bool, spaces_between_op: bool,
) {
let mut displ = address.wrapping_sub(symbol.address) as i64;
if (symbol.flags & SymbolFlags::SIGNED) != 0 {
if write_minus_if_signed {
output.write("-", FormatterTextKind::Operator);
}
displ = displ.wrapping_neg();
}
output.write_symbol(instruction, operand, instruction_operand, address, symbol);
let mut number_kind: NumberKind;
if displ != 0 {
if spaces_between_op {
output.write(" ", FormatterTextKind::Text);
}
let orig_displ = displ as u64;
if displ < 0 {
output.write("-", FormatterTextKind::Operator);
displ = displ.wrapping_neg();
if displ <= i8::MAX as i64 + 1 {
number_kind = NumberKind::Int8;
} else if displ <= i16::MAX as i64 + 1 {
number_kind = NumberKind::Int16;
} else if displ <= i32::MAX as i64 + 1 {
number_kind = NumberKind::Int32;
} else {
number_kind = NumberKind::Int64;
}
} else {
output.write("+", FormatterTextKind::Operator);
if displ <= i8::MAX as i64 {
number_kind = NumberKind::Int8;
} else if displ <= i16::MAX as i64 {
number_kind = NumberKind::Int16;
} else if displ <= i32::MAX as i64 {
number_kind = NumberKind::Int32;
} else {
number_kind = NumberKind::Int64;
}
}
if spaces_between_op {
output.write(" ", FormatterTextKind::Text);
}
let s = number_formatter.format_u64_zeroes(options, number_options, displ as u64, false);
output.write_number(instruction, operand, instruction_operand, s, orig_displ, number_kind, FormatterTextKind::Number);
}
if show_symbol_address {
output.write(" ", FormatterTextKind::Text);
output.write("(", FormatterTextKind::Punctuation);
let s = if address <= u16::MAX as u64 {
number_kind = NumberKind::UInt16;
number_formatter.format_u16_zeroes(options, number_options, address as u16, true)
} else if address <= u32::MAX as u64 {
number_kind = NumberKind::UInt32;
number_formatter.format_u32_zeroes(options, number_options, address as u32, true)
} else {
number_kind = NumberKind::UInt64;
number_formatter.format_u64_zeroes(options, number_options, address, true)
};
output.write_number(instruction, operand, instruction_operand, s, address, number_kind, FormatterTextKind::Number);
output.write(")", FormatterTextKind::Punctuation);
}
}
}
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub trait Formatter: private::Sealed {
fn format(&mut self, instruction: &Instruction, output: &mut FormatterOutput);
#[cfg_attr(has_must_use, must_use)]
fn options(&self) -> &FormatterOptions;
#[cfg_attr(has_must_use, must_use)]
fn options_mut(&mut self) -> &mut FormatterOptions;
#[inline]
fn format_mnemonic(&mut self, instruction: &Instruction, output: &mut FormatterOutput) {
self.format_mnemonic_options(instruction, output, FormatMnemonicOptions::NONE);
}
fn format_mnemonic_options(&mut self, instruction: &Instruction, output: &mut FormatterOutput, options: u32);
#[cfg_attr(has_must_use, must_use)]
fn operand_count(&mut self, instruction: &Instruction) -> u32;
#[cfg(feature = "instr_info")]
#[cfg_attr(has_must_use, must_use)]
fn op_access(&mut self, instruction: &Instruction, operand: u32) -> Option<OpAccess>;
#[cfg_attr(has_must_use, must_use)]
fn get_instruction_operand(&mut self, instruction: &Instruction, operand: u32) -> Option<u32>;
#[cfg_attr(has_must_use, must_use)]
fn get_formatter_operand(&mut self, instruction: &Instruction, instruction_operand: u32) -> Option<u32>;
fn format_operand(&mut self, instruction: &Instruction, output: &mut FormatterOutput, operand: u32);
fn format_operand_separator(&mut self, instruction: &Instruction, output: &mut FormatterOutput);
fn format_all_operands(&mut self, instruction: &Instruction, output: &mut FormatterOutput);
#[cfg_attr(has_must_use, must_use)]
fn format_register(&mut self, register: Register) -> &str;
#[cfg_attr(has_must_use, must_use)]
fn format_i8(&mut self, value: i8) -> &str;
#[cfg_attr(has_must_use, must_use)]
fn format_i16(&mut self, value: i16) -> &str;
#[cfg_attr(has_must_use, must_use)]
fn format_i32(&mut self, value: i32) -> &str;
#[cfg_attr(has_must_use, must_use)]
fn format_i64(&mut self, value: i64) -> &str;
#[cfg_attr(has_must_use, must_use)]
fn format_u8(&mut self, value: u8) -> &str;
#[cfg_attr(has_must_use, must_use)]
fn format_u16(&mut self, value: u16) -> &str;
#[cfg_attr(has_must_use, must_use)]
fn format_u32(&mut self, value: u32) -> &str;
#[cfg_attr(has_must_use, must_use)]
fn format_u64(&mut self, value: u64) -> &str;
#[cfg_attr(has_must_use, must_use)]
fn format_i8_options(&mut self, value: i8, number_options: &NumberFormattingOptions) -> &str;
#[cfg_attr(has_must_use, must_use)]
fn format_i16_options(&mut self, value: i16, number_options: &NumberFormattingOptions) -> &str;
#[cfg_attr(has_must_use, must_use)]
fn format_i32_options(&mut self, value: i32, number_options: &NumberFormattingOptions) -> &str;
#[cfg_attr(has_must_use, must_use)]
fn format_i64_options(&mut self, value: i64, number_options: &NumberFormattingOptions) -> &str;
#[cfg_attr(has_must_use, must_use)]
fn format_u8_options(&mut self, value: u8, number_options: &NumberFormattingOptions) -> &str;
#[cfg_attr(has_must_use, must_use)]
fn format_u16_options(&mut self, value: u16, number_options: &NumberFormattingOptions) -> &str;
#[cfg_attr(has_must_use, must_use)]
fn format_u32_options(&mut self, value: u32, number_options: &NumberFormattingOptions) -> &str;
#[cfg_attr(has_must_use, must_use)]
fn format_u64_options(&mut self, value: u64, number_options: &NumberFormattingOptions) -> &str;
}
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod private {
pub trait Sealed {}
#[cfg(feature = "gas")]
impl Sealed for super::gas::GasFormatter {}
#[cfg(feature = "intel")]
impl Sealed for super::intel::IntelFormatter {}
#[cfg(feature = "masm")]
impl Sealed for super::masm::MasmFormatter {}
#[cfg(feature = "nasm")]
impl Sealed for super::nasm::NasmFormatter {}
}
fn to_owned<'a>(sym_res: Option<SymbolResult>, vec: &'a mut Vec<SymResTextPart<'a>>) -> Option<SymbolResult<'a>> {
match sym_res {
None => None,
Some(sym_res) => Some(sym_res.to_owned(vec)),
}
}
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
fn get_mnemonic_cc<'a, 'b>(options: &'a FormatterOptions, cc_index: u32, mnemonics: &'b [FormatterString]) -> &'b FormatterString {
let index = match cc_index {
0 => {
debug_assert_eq!(1, mnemonics.len());
0
}
1 => {
debug_assert_eq!(1, mnemonics.len());
0
}
2 => {
debug_assert_eq!(3, mnemonics.len());
options.cc_b() as usize
}
3 => {
debug_assert_eq!(3, mnemonics.len());
options.cc_ae() as usize
}
4 => {
debug_assert_eq!(2, mnemonics.len());
options.cc_e() as usize
}
5 => {
debug_assert_eq!(2, mnemonics.len());
options.cc_ne() as usize
}
6 => {
debug_assert_eq!(2, mnemonics.len());
options.cc_be() as usize
}
7 => {
debug_assert_eq!(2, mnemonics.len());
options.cc_a() as usize
}
8 => {
debug_assert_eq!(1, mnemonics.len());
0
}
9 => {
debug_assert_eq!(1, mnemonics.len());
0
}
10 => {
debug_assert_eq!(2, mnemonics.len());
options.cc_p() as usize
}
11 => {
debug_assert_eq!(2, mnemonics.len());
options.cc_np() as usize
}
12 => {
debug_assert_eq!(2, mnemonics.len());
options.cc_l() as usize
}
13 => {
debug_assert_eq!(2, mnemonics.len());
options.cc_ge() as usize
}
14 => {
debug_assert_eq!(2, mnemonics.len());
options.cc_le() as usize
}
15 => {
debug_assert_eq!(2, mnemonics.len());
options.cc_g() as usize
}
_ => unreachable!(),
};
debug_assert!(index < mnemonics.len());
&mnemonics[index]
}