Skip to main content

charm/core/a64/config/
mod.rs

1//! Default configuration objects and all configuration-related types.
2
3use super::consts::config::ConfigInstructions;
4
5// -----------------------------------------------------------------------------------------------
6// Config
7// -----------------------------------------------------------------------------------------------
8
9/// Main configuration object.
10#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Default)]
11pub struct Config {
12    /// Global configuration.
13    ///
14    /// This is where the default behavior is set. Values in this structure
15    /// act as a fallback if there is no per-instruction settings.
16    pub global: ConfigGlobal,
17    /// Per-instruction settings that override the default behavior in the global config.
18    pub instructions: ConfigInstructions,
19}
20
21impl Config {
22    /// Creates a new configuration object with default values.
23    pub fn new() -> Self {
24        Self::default()
25    }
26}
27
28/// Type that represents the global configuration.
29#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Default)]
30pub struct ConfigGlobal {
31    /// Global syntax rules.
32    pub syntax: FormatSyntaxGlobal,
33    /// Global aliases rules.
34    pub aliases: FormatAliasGlobal,
35}
36
37impl ConfigGlobal {
38    /// Creates a new global configuration object.
39    pub fn new() -> Self {
40        Self::default()
41    }
42}
43
44/// Type that represents the configuration of an instruction.
45#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
46pub struct ConfigInstruction<A> {
47    /// Per-instruction syntax rules.
48    pub syntax: FormatSyntax,
49    /// Per-instruction qualifier rules.
50    ///
51    /// If `None`, defaults to the corresponding global configuration value.
52    pub aliases: Option<FormatAliasInstruction<A>>,
53}
54
55impl<A> ConfigInstruction<A> {
56    pub fn new() -> Self {
57        Self::default()
58    }
59}
60
61impl<A> Default for ConfigInstruction<A> {
62    fn default() -> Self {
63        Self {
64            syntax: FormatSyntax::default(),
65            aliases: None,
66        }
67    }
68}
69
70/// Trait to retrieve the syntax and qualifier object.
71pub trait HasConfigInstruction {
72    fn syntax(&self) -> &FormatSyntax;
73}
74
75impl<A> HasConfigInstruction for ConfigInstruction<A> {
76    fn syntax(&self) -> &FormatSyntax {
77        &self.syntax
78    }
79}
80
81// -----------------------------------------------------------------------------------------------
82// Aliases
83// -----------------------------------------------------------------------------------------------
84
85/// Type that represents the global alias settings.
86///
87/// It specifies Charm's default behavior when using an alias is possible.
88#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Default)]
89pub enum FormatAliasGlobal {
90    /// Never use the alias, regardless of any condition.
91    Never,
92    /// Follows ARM's recommendations.
93    #[default]
94    Recommended,
95    /// Always use the alias, regardless of any condition.
96    Always,
97}
98
99/// Type that represents the per-instruction alias settings.
100///
101/// It specifies Charm's behavior for a given encoding when using an alias is possible.
102#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Default)]
103pub enum FormatAliasInstruction<A> {
104    /// Never use the alias, regardless of any condition.
105    Never,
106    /// Follows ARM's recommendations.
107    #[default]
108    Recommended,
109    /// If multiple aliases are possible, try to use this alias first.
110    Preferred(A),
111    /// Always use the alias, regardless of any condition.
112    Always(A),
113}
114
115// -----------------------------------------------------------------------------------------------
116// Syntax
117// -----------------------------------------------------------------------------------------------
118
119/// Type that represent the integer formatting configuration.
120#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Default)]
121pub enum FormatInteger {
122    /// Display integers as signed decimal numbers.
123    #[default]
124    DecimalSigned,
125    /// Display integers as unsigned decimal numbers.
126    DecimalUnsigned,
127    /// Display integers as signed hexdecimal numbers.
128    HexadecimalSigned,
129    /// Display integers as unsigned hexdecimal numbers.
130    HexadecimalUnsigned,
131}
132
133/// Type that represents the global syntax settings.
134#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Default)]
135pub struct FormatSyntaxGlobal {
136    /// Settings for a register that can be omitted when it is *used* as both the source and the
137    /// destination.
138    /// For example, in `ADCS{<q>} {<Rdn>, }<Rdn>, <Rm>`, this would control whether or not `<Rdn>`
139    /// is displayed.
140    pub omit_src_dst_same_reg: bool,
141    /// Controls if a register that can be omitted when it *can* be used as both the source and the
142    /// destination should be displayed.
143    /// For example, in `ADC{<c>}{<q>} {<Rd>, }<Rn>, <Rm>, RRX`, this would control whether or not
144    /// `<Rd>` is displayed if `<Rd> == <Rn>`.
145    pub omit_src_dst_diff_reg: bool,
146    /// Controls if optional null integers in dereferencing groups should be displayed.
147    /// For example, in `LDXRB <Wt>, [<Xn|SP>{, #0}]`, this would control whether or not #0 is
148    /// displayed.
149    pub omit_deref_null_const: bool,
150    /// Controls how positive numbers are displayed.
151    pub positive_integer_format: FormatInteger,
152    /// Controls how negative numbers are displayed.
153    pub negative_integer_format: FormatInteger,
154}
155
156/// Type that represents the per-instruction syntax settings.
157#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Default)]
158pub struct FormatSyntax {
159    /// Settings for a register that can be omitted when it is *used* as both the source and the
160    /// destination.
161    /// For example, in `ADCS{<q>} {<Rdn>, }<Rdn>, <Rm>`, this would control whether or not `<Rdn>`
162    /// is displayed.
163    ///
164    /// If `None`, defaults to the corresponding global configuration value.
165    pub omit_src_dst_same_reg: Option<bool>,
166    /// Controls if a register that can be omitted when it *can* be used as both the source and the
167    /// destination should be displayed.
168    /// For example, in `ADC{<c>}{<q>} {<Rd>, }<Rn>, <Rm>, RRX`, this would control whether or not
169    /// `<Rd>` is displayed if `<Rd> == <Rn>`.
170    ///
171    /// If `None`, defaults to the corresponding global configuration value.
172    pub omit_src_dst_diff_reg: Option<bool>,
173    /// Controls if optional null integers in dereferencing groups should be displayed.
174    /// For example, in `LDXRB <Wt>, [<Xn|SP>{, #0}]`, this would control whether or not #0 is
175    /// displayed.
176    ///
177    /// If `None`, defaults to the corresponding global configuration value.
178    pub omit_deref_null_const: Option<bool>,
179    /// Controls how positive numbers are displayed.
180    ///
181    /// If `None`, defaults to the corresponding global configuration value.
182    pub positive_integer_format: Option<FormatInteger>,
183    /// Controls how negative numbers are displayed.
184    ///
185    /// If `None`, defaults to the corresponding global configuration value.
186    pub negative_integer_format: Option<FormatInteger>,
187}
188
189impl FormatSyntax {
190    pub fn new() -> Self {
191        Self::default()
192    }
193
194    pub fn get_omit_src_dst_same_reg(&self, global: &FormatSyntaxGlobal) -> bool {
195        if let Some(value) = self.omit_src_dst_same_reg {
196            return value;
197        }
198        global.omit_src_dst_same_reg
199    }
200
201    pub fn get_omit_src_dst_diff_reg(&self, global: &FormatSyntaxGlobal) -> bool {
202        if let Some(value) = self.omit_src_dst_diff_reg {
203            return value;
204        }
205        global.omit_src_dst_diff_reg
206    }
207
208    pub fn get_positive_integer_format(&self, global: &FormatSyntaxGlobal) -> FormatInteger {
209        if let Some(value) = self.positive_integer_format {
210            return value;
211        }
212        global.positive_integer_format
213    }
214
215    pub fn get_negative_integer_format(&self, global: &FormatSyntaxGlobal) -> FormatInteger {
216        if let Some(value) = self.negative_integer_format {
217            return value;
218        }
219        global.negative_integer_format
220    }
221}
222
223// -----------------------------------------------------------------------------------------------
224// LLVM Config
225// -----------------------------------------------------------------------------------------------
226
227/// Configuration making Charm behave similarly to LLVM.
228pub struct ConfigLLVM {}
229
230impl ConfigLLVM {
231    /// Creates a new LLVM configuration.
232    pub fn new() -> Config {
233        let mut config = Config::default();
234
235        // ---------------------------------------------------------------------------------------
236        // Global - Syntax
237        config.global.syntax.omit_src_dst_same_reg = true;
238        config.global.syntax.omit_src_dst_diff_reg = false;
239        config.global.syntax.omit_deref_null_const = true;
240
241        // ---------------------------------------------------------------------------------------
242        // Per-instruction - Syntax
243        config
244            .instructions
245            .and_32_log_imm
246            .syntax
247            .positive_integer_format = Some(FormatInteger::HexadecimalUnsigned);
248        config
249            .instructions
250            .and_32_log_imm
251            .syntax
252            .negative_integer_format = Some(FormatInteger::HexadecimalUnsigned);
253        config
254            .instructions
255            .and_64_log_imm
256            .syntax
257            .positive_integer_format = Some(FormatInteger::HexadecimalUnsigned);
258        config
259            .instructions
260            .and_64_log_imm
261            .syntax
262            .negative_integer_format = Some(FormatInteger::HexadecimalUnsigned);
263        config
264            .instructions
265            .ands_32s_log_imm
266            .syntax
267            .positive_integer_format = Some(FormatInteger::HexadecimalUnsigned);
268        config
269            .instructions
270            .ands_32s_log_imm
271            .syntax
272            .negative_integer_format = Some(FormatInteger::HexadecimalUnsigned);
273        config
274            .instructions
275            .ands_64s_log_imm
276            .syntax
277            .positive_integer_format = Some(FormatInteger::HexadecimalUnsigned);
278        config
279            .instructions
280            .ands_64s_log_imm
281            .syntax
282            .negative_integer_format = Some(FormatInteger::HexadecimalUnsigned);
283        config
284            .instructions
285            .eor_32_log_imm
286            .syntax
287            .positive_integer_format = Some(FormatInteger::HexadecimalUnsigned);
288        config
289            .instructions
290            .eor_32_log_imm
291            .syntax
292            .negative_integer_format = Some(FormatInteger::HexadecimalUnsigned);
293        config
294            .instructions
295            .eor_64_log_imm
296            .syntax
297            .positive_integer_format = Some(FormatInteger::HexadecimalUnsigned);
298        config
299            .instructions
300            .eor_64_log_imm
301            .syntax
302            .negative_integer_format = Some(FormatInteger::HexadecimalUnsigned);
303        config
304            .instructions
305            .orr_32_log_imm
306            .syntax
307            .positive_integer_format = Some(FormatInteger::HexadecimalUnsigned);
308        config
309            .instructions
310            .orr_32_log_imm
311            .syntax
312            .negative_integer_format = Some(FormatInteger::HexadecimalUnsigned);
313        config
314            .instructions
315            .orr_64_log_imm
316            .syntax
317            .positive_integer_format = Some(FormatInteger::HexadecimalUnsigned);
318        config
319            .instructions
320            .orr_64_log_imm
321            .syntax
322            .negative_integer_format = Some(FormatInteger::HexadecimalUnsigned);
323        config
324            .instructions
325            .tst_ands_32s_log_imm
326            .syntax
327            .positive_integer_format = Some(FormatInteger::HexadecimalUnsigned);
328        config
329            .instructions
330            .tst_ands_32s_log_imm
331            .syntax
332            .negative_integer_format = Some(FormatInteger::HexadecimalUnsigned);
333        config
334            .instructions
335            .tst_ands_64s_log_imm
336            .syntax
337            .positive_integer_format = Some(FormatInteger::HexadecimalUnsigned);
338        config
339            .instructions
340            .tst_ands_64s_log_imm
341            .syntax
342            .negative_integer_format = Some(FormatInteger::HexadecimalUnsigned);
343
344        // ---------------------------------------------------------------------------------------
345        // Per-instruction - Aliases
346        config.instructions.ldtadd_32_memop_unpriv.aliases = Some(FormatAliasInstruction::Never);
347        config.instructions.ldtadd_64_memop_unpriv.aliases = Some(FormatAliasInstruction::Never);
348        config.instructions.ldtaddl_32_memop_unpriv.aliases = Some(FormatAliasInstruction::Never);
349        config.instructions.ldtaddl_64_memop_unpriv.aliases = Some(FormatAliasInstruction::Never);
350        config.instructions.ldtclr_32_memop_unpriv.aliases = Some(FormatAliasInstruction::Never);
351        config.instructions.ldtclr_64_memop_unpriv.aliases = Some(FormatAliasInstruction::Never);
352        config.instructions.ldtclrl_32_memop_unpriv.aliases = Some(FormatAliasInstruction::Never);
353        config.instructions.ldtclrl_64_memop_unpriv.aliases = Some(FormatAliasInstruction::Never);
354        config.instructions.ldtset_32_memop_unpriv.aliases = Some(FormatAliasInstruction::Never);
355        config.instructions.ldtset_64_memop_unpriv.aliases = Some(FormatAliasInstruction::Never);
356        config.instructions.ldtsetl_32_memop_unpriv.aliases = Some(FormatAliasInstruction::Never);
357        config.instructions.ldtsetl_64_memop_unpriv.aliases = Some(FormatAliasInstruction::Never);
358        config.instructions.subps_64s_dp_2src.aliases = Some(FormatAliasInstruction::Never);
359
360        config
361    }
362}