iced_x86/formatter/fast/
options.rs

1// SPDX-License-Identifier: MIT
2// Copyright (C) 2018-present iced project and contributors
3
4struct Flags1;
5impl Flags1 {
6	const SPACE_AFTER_OPERAND_SEPARATOR: u32 = 0x0000_0001;
7	const RIP_RELATIVE_ADDRESSES: u32 = 0x0000_0002;
8	const USE_PSEUDO_OPS: u32 = 0x0000_0004;
9	const SHOW_SYMBOL_ADDRESS: u32 = 0x0000_0008;
10	const ALWAYS_SHOW_SEGMENT_REGISTER: u32 = 0x0000_0010;
11	const ALWAYS_SHOW_MEMORY_SIZE: u32 = 0x0000_0020;
12	const UPPERCASE_HEX: u32 = 0x0000_0040;
13	const USE_HEX_PREFIX: u32 = 0x0000_0080;
14}
15
16/// Fast formatter options
17#[derive(Debug, Clone, Eq, PartialEq, Hash)]
18#[allow(missing_copy_implementations)]
19pub struct FastFormatterOptions {
20	options1: u32,
21}
22
23impl FastFormatterOptions {
24	#[must_use]
25	#[inline]
26	pub(super) const fn new() -> Self {
27		Self { options1: Flags1::USE_PSEUDO_OPS | Flags1::UPPERCASE_HEX }
28	}
29
30	// NOTE: These tables must render correctly by `cargo doc` and inside of IDEs, eg. VSCode.
31
32	/// Add a space after the operand separator
33	///
34	/// Default | Value | Example
35	/// --------|-------|--------
36	/// _ | `true` | `mov rax, rcx`
37	/// 👍 | `false` | `mov rax,rcx`
38	#[must_use]
39	#[inline]
40	pub const fn space_after_operand_separator(&self) -> bool {
41		(self.options1 & Flags1::SPACE_AFTER_OPERAND_SEPARATOR) != 0
42	}
43
44	/// Add a space after the operand separator
45	///
46	/// Default | Value | Example
47	/// --------|-------|--------
48	/// _ | `true` | `mov rax, rcx`
49	/// 👍 | `false` | `mov rax,rcx`
50	///
51	/// # Arguments
52	///
53	/// * `value`: New value
54	#[inline]
55	pub fn set_space_after_operand_separator(&mut self, value: bool) {
56		if value {
57			self.options1 |= Flags1::SPACE_AFTER_OPERAND_SEPARATOR;
58		} else {
59			self.options1 &= !Flags1::SPACE_AFTER_OPERAND_SEPARATOR;
60		}
61	}
62
63	/// Show `RIP+displ` or the virtual address
64	///
65	/// Default | Value | Example
66	/// --------|-------|--------
67	/// _ | `true` | `mov eax,[rip+12345678h]`
68	/// 👍 | `false` | `mov eax,[1029384756AFBECDh]`
69	#[must_use]
70	#[inline]
71	pub const fn rip_relative_addresses(&self) -> bool {
72		(self.options1 & Flags1::RIP_RELATIVE_ADDRESSES) != 0
73	}
74
75	/// Show `RIP+displ` or the virtual address
76	///
77	/// Default | Value | Example
78	/// --------|-------|--------
79	/// _ | `true` | `mov eax,[rip+12345678h]`
80	/// 👍 | `false` | `mov eax,[1029384756AFBECDh]`
81	///
82	/// # Arguments
83	///
84	/// * `value`: New value
85	#[inline]
86	pub fn set_rip_relative_addresses(&mut self, value: bool) {
87		if value {
88			self.options1 |= Flags1::RIP_RELATIVE_ADDRESSES;
89		} else {
90			self.options1 &= !Flags1::RIP_RELATIVE_ADDRESSES;
91		}
92	}
93
94	/// Use pseudo instructions
95	///
96	/// Default | Value | Example
97	/// --------|-------|--------
98	/// 👍 | `true` | `vcmpnltsd xmm2,xmm6,xmm3`
99	/// _ | `false` | `vcmpsd xmm2,xmm6,xmm3,5h`
100	#[must_use]
101	#[inline]
102	pub const fn use_pseudo_ops(&self) -> bool {
103		(self.options1 & Flags1::USE_PSEUDO_OPS) != 0
104	}
105
106	/// Use pseudo instructions
107	///
108	/// Default | Value | Example
109	/// --------|-------|--------
110	/// 👍 | `true` | `vcmpnltsd xmm2,xmm6,xmm3`
111	/// _ | `false` | `vcmpsd xmm2,xmm6,xmm3,5h`
112	///
113	/// # Arguments
114	///
115	/// * `value`: New value
116	#[inline]
117	pub fn set_use_pseudo_ops(&mut self, value: bool) {
118		if value {
119			self.options1 |= Flags1::USE_PSEUDO_OPS;
120		} else {
121			self.options1 &= !Flags1::USE_PSEUDO_OPS;
122		}
123	}
124
125	/// Show the original value after the symbol name
126	///
127	/// Default | Value | Example
128	/// --------|-------|--------
129	/// _ | `true` | `mov eax,[myfield (12345678)]`
130	/// 👍 | `false` | `mov eax,[myfield]`
131	#[must_use]
132	#[inline]
133	pub const fn show_symbol_address(&self) -> bool {
134		(self.options1 & Flags1::SHOW_SYMBOL_ADDRESS) != 0
135	}
136
137	/// Show the original value after the symbol name
138	///
139	/// Default | Value | Example
140	/// --------|-------|--------
141	/// _ | `true` | `mov eax,[myfield (12345678)]`
142	/// 👍 | `false` | `mov eax,[myfield]`
143	///
144	/// # Arguments
145	///
146	/// * `value`: New value
147	#[inline]
148	pub fn set_show_symbol_address(&mut self, value: bool) {
149		if value {
150			self.options1 |= Flags1::SHOW_SYMBOL_ADDRESS;
151		} else {
152			self.options1 &= !Flags1::SHOW_SYMBOL_ADDRESS;
153		}
154	}
155
156	/// Always show the effective segment register. If the option is `false`, only show the segment register if
157	/// there's a segment override prefix.
158	///
159	/// Default | Value | Example
160	/// --------|-------|--------
161	/// _ | `true` | `mov eax,ds:[ecx]`
162	/// 👍 | `false` | `mov eax,[ecx]`
163	#[must_use]
164	#[inline]
165	pub const fn always_show_segment_register(&self) -> bool {
166		(self.options1 & Flags1::ALWAYS_SHOW_SEGMENT_REGISTER) != 0
167	}
168
169	/// Always show the effective segment register. If the option is `false`, only show the segment register if
170	/// there's a segment override prefix.
171	///
172	/// Default | Value | Example
173	/// --------|-------|--------
174	/// _ | `true` | `mov eax,ds:[ecx]`
175	/// 👍 | `false` | `mov eax,[ecx]`
176	///
177	/// # Arguments
178	///
179	/// * `value`: New value
180	#[inline]
181	pub fn set_always_show_segment_register(&mut self, value: bool) {
182		if value {
183			self.options1 |= Flags1::ALWAYS_SHOW_SEGMENT_REGISTER;
184		} else {
185			self.options1 &= !Flags1::ALWAYS_SHOW_SEGMENT_REGISTER;
186		}
187	}
188
189	/// Always show the size of memory operands
190	///
191	/// Default | Value | Example | Example
192	/// --------|-------|---------|--------
193	/// _ | `true` | `mov eax,dword ptr [ebx]` | `add byte ptr [eax],0x12`
194	/// 👍 | `false` | `mov eax,[ebx]` | `add byte ptr [eax],0x12`
195	#[must_use]
196	#[inline]
197	pub const fn always_show_memory_size(&self) -> bool {
198		(self.options1 & Flags1::ALWAYS_SHOW_MEMORY_SIZE) != 0
199	}
200
201	/// Always show the size of memory operands
202	///
203	/// Default | Value | Example | Example
204	/// --------|-------|---------|--------
205	/// _ | `true` | `mov eax,dword ptr [ebx]` | `add byte ptr [eax],0x12`
206	/// 👍 | `false` | `mov eax,[ebx]` | `add byte ptr [eax],0x12`
207	///
208	/// # Arguments
209	///
210	/// * `value`: New value
211	#[inline]
212	pub fn set_always_show_memory_size(&mut self, value: bool) {
213		if value {
214			self.options1 |= Flags1::ALWAYS_SHOW_MEMORY_SIZE;
215		} else {
216			self.options1 &= !Flags1::ALWAYS_SHOW_MEMORY_SIZE;
217		}
218	}
219
220	/// Use uppercase hex digits
221	///
222	/// Default | Value | Example
223	/// --------|-------|--------
224	/// 👍 | `true` | `0xFF`
225	/// _ | `false` | `0xff`
226	#[must_use]
227	#[inline]
228	pub const fn uppercase_hex(&self) -> bool {
229		(self.options1 & Flags1::UPPERCASE_HEX) != 0
230	}
231
232	/// Use uppercase hex digits
233	///
234	/// Default | Value | Example
235	/// --------|-------|--------
236	/// 👍 | `true` | `0xFF`
237	/// _ | `false` | `0xff`
238	///
239	/// # Arguments
240	///
241	/// * `value`: New value
242	#[inline]
243	pub fn set_uppercase_hex(&mut self, value: bool) {
244		if value {
245			self.options1 |= Flags1::UPPERCASE_HEX;
246		} else {
247			self.options1 &= !Flags1::UPPERCASE_HEX;
248		}
249	}
250
251	/// Use a hex prefix (`0x`) or a hex suffix (`h`)
252	///
253	/// Default | Value | Example
254	/// --------|-------|--------
255	/// _ | `true` | `0x5A`
256	/// 👍 | `false` | `5Ah`
257	#[must_use]
258	#[inline]
259	pub const fn use_hex_prefix(&self) -> bool {
260		(self.options1 & Flags1::USE_HEX_PREFIX) != 0
261	}
262
263	/// Use a hex prefix (`0x`) or a hex suffix (`h`)
264	///
265	/// Default | Value | Example
266	/// --------|-------|--------
267	/// _ | `true` | `0x5A`
268	/// 👍 | `false` | `5Ah`
269	///
270	/// # Arguments
271	///
272	/// * `value`: New value
273	#[inline]
274	pub fn set_use_hex_prefix(&mut self, value: bool) {
275		if value {
276			self.options1 |= Flags1::USE_HEX_PREFIX;
277		} else {
278			self.options1 &= !Flags1::USE_HEX_PREFIX;
279		}
280	}
281}