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}