dynasm\arch\aarch64/
aarch64data.rs

1use crate::common::Size;
2use super::ast::Modifier;
3
4use lazy_static::lazy_static;
5use std::collections::{HashMap, hash_map};
6
7#[derive(Debug, Clone, Copy, PartialEq)]
8pub enum Matcher {
9    // a literal "."
10    Dot,
11
12    // a specific literal (basically just an ident)
13    Lit(&'static str),
14
15    // immediate literal
16    LitInt(u32),
17
18    // float literal
19    LitFloat(f32),
20
21    // a random ident
22    Ident,
23
24    // a condition code literal
25    Cond,
26
27    // immediate
28    Imm,
29
30    // Wregisters, XRegisters, etc. match any static register in their family except for SP
31    W,
32    X,
33
34    // same but addressing the stack pointer instead of the zero register. match any static register in their family except for ZR
35    WSP,
36    XSP,
37
38    // scalar simd regs
39    B,
40    H,
41    S,
42    D,
43    Q,
44
45    // vector simd regs
46    /// vector register with elements of the specified size. Accepts a lane count of either 64 or 128 total bits
47    V(Size),
48    /// vector register with elements of the specifized size, with the specified lane count
49    VStatic(Size, u8),
50    /// vector register with element specifier, with the element of the specified size. The lane count is unchecked.
51    VElement(Size),
52    /// vector register with element specifier, with the element of the specified size and the element index set to the provided value
53    VElementStatic(Size, u8),
54    /// vector register with elements of the specified size, with the specified lane count, with an element specifier
55    VStaticElement(Size, u8),
56
57    // register list with .0 items, with the elements of size .1
58    RegList(u8, Size),
59    // register list with .0 items, with the elements of size .1 and a lane count of .2
60    RegListStatic(u8, Size, u8),
61    // register list with element specifier. It has .0 items with a size of .1
62    RegListElement(u8, Size),
63
64    // jump offsets
65    Offset,
66
67    // references
68    RefBase,
69    RefOffset,
70    RefPre,
71    RefIndex,
72
73    // a single modifier
74    LitMod(Modifier),
75
76    // a set of allowed modifiers
77    Mod(&'static [Modifier]),
78
79    // possible op mnemnonic end (everything after this point uses the default encoding)
80    End,
81}
82
83#[derive(Debug, Clone, Copy, PartialEq, Eq)]
84pub enum Command {
85    // commands that advance the argument pointer
86    R(u8), // encode a register, or reference base, into a 5-bit bitfield.
87    REven(u8), // same as R, but requires that the register is even.
88    RNoZr(u8), // same as R, but does not allow register 31.
89    R4(u8), // encode a register in the range 0-15 into a 4-bit bitfield
90    RNext, // encode that this register should be the previous register, plus one
91
92    // unsigned immediate encodings
93
94    /// format: `(pos, len)`
95    /// `immediate` is in the range `0 .. (1<<len)`.
96    /// `immediate` is encoded directly in a bitfield of length `len` at offset `pos`.
97    Ubits(u8, u8),
98    /// format: `(pos, len, shift)`
99    /// `immediate >> shift` is in the range `0 .. (1 << len)`. Bottom `shift` bits are zero.
100    /// `immediate >> shift` is encoded directly in a bitfield of length `len` at offset `pos`.
101    Uscaled(u8, u8, u8),
102    /// format: `(pos, [options])`
103    /// `immediate` is one of the options in `options`.
104    /// the index of `immediate` in options is encoded directly in a bitfield at offset `pos`.
105    Ulist(u8, &'static [u16]),
106    /// format: `(pos, min, max)`
107    /// `immediate - min` is in the range `0 ..= max - min`.
108    /// `immediate - min` is encoded in a bitfield starting at `pos`
109    Urange(u8, u8, u8),
110
111    /// format: `(pos, len)`
112    /// `immediate` is in the range `1 ..= (1 << len)`.
113    /// `(1 << len) - value)` is encoded in a bitfield of length `len` at offset `pos`.
114    Usubone(u8, u8),
115    /// format: `(pos, len)`
116    /// `immediate`is in the range `0 .. (1 << len)`.
117    /// `(1 << len) - 1 - value)` is encoded in a bitfield of length `len` at offset `pos`.
118    Usubzero(u8, u8),
119    /// format: `(pos, len)`
120    /// `immediate` is in the range `0 .. (1 << len)`.
121    /// `(-value) & ((1 << len) - 1)` is encoded in a bitfield of length `len` at offset `pos`.
122    Usubmod(u8, u8),
123    /// format: `(pos, len)`
124    /// `immediate` is in the range `1 ..= (1 << len) - prev_arg`
125    /// `immediate + prev_arg - 1` is encoded in a a bitfield of length `len` at offset `pos`
126    Usum(u8, u8),
127    /// format: `([offsets])`
128    /// `immediate` is in the range `0 .. (1 << offsets.len())`
129    /// `immediate` is encoded with bit N of the number at offsets[N]
130    Ufields(&'static [u8]),
131
132    // signed immediate encodings
133
134    /// format: `(pos, len)`
135    /// `immediate + (1 << (len - 1))` is in the range `0 .. (1<<len)`.
136    /// `immediate` is encoded directly in a bitfield of length `len` at offset `pos`.
137    Sbits(u8, u8),
138    /// format: `(pos, len, shift)`
139    /// `(immediate >> shift) + (1 << (len - 1))` is in the range `0 .. (1 << len)`. Bottom `shift` bits are zero.
140    /// `immediate >> shift` is encoded directly in a bitfield of length `len` at offset `pos`.
141    Sscaled(u8, u8, u8),
142
143    // pure validation encodings. These just check some precondition of the current argument, and don't advance to the next.
144
145    /// format: `(len)`
146    /// `immediate` is in the range `0 .. (1<<len)`.
147    CUbits(u8),
148    /// format: `(len)`
149    /// `immediate` is in the range `1 ..= (1 << len) - prev_arg`
150    CUsum(u8),
151    /// format: `(len, shift)`
152    /// `(immediate >> shift) + (1 << (len - 1))` is in the range `1 ..= (1 << len)`. Bottom `shift` bits are zero.
153    CSscaled(u8, u8),
154    /// format: `(min, max)`
155    /// `immediate - min` is in the range `0 ..= max - min`.
156    CUrange(u8, u8),
157
158    // bit slice encodings. These encode part of a value
159
160    /// format: `(pos, len, offset)`
161    /// `immediate >> offset` is encoded in a bitfield of length `len` at offset `pos`.
162    Uslice(u8, u8, u8),
163    /// format: `(pos, len, offset)`
164    /// `immediate >> offset` is encoded in a bitfield of length `len` at offset `pos`.
165    Sslice(u8, u8, u8),
166
167    // special immediate encodings
168    Special(u8, SpecialComm),
169
170    // SIMD 128-bit indicator
171    Rwidth(u8),
172
173    // Extend/Shift fields
174    Rotates(u8), // 2-bits field encoding [LSL, LSR, ASR, ROR]
175    ExtendsW(u8), // 3-bits field encoding [UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX]. Additionally, LSL is interpreted as UXTW
176    ExtendsX(u8), // 3-bits field encoding [UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX]. Additionally, LSL is interpreted as UXTX
177
178    // Condition encodings.
179    /// Normal condition code 4-bit encoding
180    Cond(u8),
181    /// Condition 4-bit encoding, but the last bit is inverted. No AL/NV allowed
182    CondInv(u8),
183
184    // Mapping of literal -> bitvalue
185    LitList(u8, &'static str),
186
187    // Offsets
188    Offset(Relocation),
189
190    // special commands
191    A, // advances the argument pointer, only needed to skip over an argument.
192    C, // moves the argument pointer back.
193}
194
195#[derive(Debug, Clone, Copy, PartialEq, Eq)]
196#[allow(non_camel_case_types)]
197pub enum SpecialComm {
198    INVERTED_WIDE_IMMEDIATE_W,
199    INVERTED_WIDE_IMMEDIATE_X,
200    WIDE_IMMEDIATE_W,
201    WIDE_IMMEDIATE_X,
202    STRETCHED_IMMEDIATE,
203    LOGICAL_IMMEDIATE_W,
204    LOGICAL_IMMEDIATE_X,
205    FLOAT_IMMEDIATE,
206    SPLIT_FLOAT_IMMEDIATE,
207}
208
209#[derive(Debug, Clone, Copy, PartialEq, Eq)]
210pub enum Relocation {
211    // b, bl 26 bits, dword aligned
212    B = 0,
213    // b.cond, cbnz, cbz, ldr, ldrsw, prfm: 19 bits, dword aligned
214    BCOND = 1,
215    // adr split 21 bit, byte aligned
216    ADR = 2,
217    // adrp split 21 bit, 4096-byte aligned
218    ADRP = 3,
219    // tbnz, tbz: 14 bits, dword aligned
220    TBZ = 4,
221    // 8-bit literal
222    LITERAL8 = 5,
223    // 16-bit literal
224    LITERAL16 = 6,
225    // 32-bit literal
226    LITERAL32 = 8,
227    // 64-bit literal
228    LITERAL64 = 12,
229}
230
231impl Relocation {
232    pub fn to_id(self) -> u8 {
233        self as u8
234    }
235}
236
237
238#[derive(Debug, Clone, Copy)]
239pub struct Opdata {
240    /// The base template for the encoding.
241    pub base: u32,
242    /// A set of matchers capable of matching the instruction encoding that this instruction represents.
243    pub matchers: &'static [Matcher],
244    /// A sequence of encoder commands that check the matched instruction on validity and whose output gets orred together with the original template at runtime.
245    pub commands: &'static [Command]
246}
247
248macro_rules! SingleOp {
249    ( $base:expr, [ $( $matcher:expr ),* ], [ $( $command:expr ),* ] ) => {
250        {
251            const MATCHERS: &'static [Matcher] = {
252                #[allow(unused_imports)]
253                use self::Matcher::*;
254                &[ $(
255                    $matcher
256                ),* ]
257            };
258            const COMMANDS: &'static [Command] = {
259                #[allow(unused_imports)]
260                use self::Command::*;
261                &[ $(
262                    $command
263                ),* ]
264            };
265            Opdata {
266                base: $base,
267                matchers: MATCHERS,
268                commands: COMMANDS,
269            }
270        }
271    }
272}
273
274macro_rules! Ops {
275    ( $( $name:tt = [ $( $base:tt = [ $( $matcher:expr ),* ] => [ $( $command:expr ),* ] ; )+ ] )* ) => {
276        [ $(
277            (
278                $name,
279                &[ $(
280                    SingleOp!( $base, [ $( $matcher ),* ], [ $( $command ),* ] )
281                ),+ ] as &[_]
282            )
283        ),* ]
284    }
285}
286
287pub fn get_mnemonic_data(name: &str) -> Option<&'static [Opdata]> {
288    OPMAP.get(&name).cloned()
289}
290
291#[allow(dead_code)]
292pub fn mnemnonics() -> hash_map::Keys<'static, &'static str, &'static [Opdata]> {
293    OPMAP.keys()
294}
295
296lazy_static! {
297    static ref OPMAP: HashMap<&'static str, &'static [Opdata]> = {
298        use super::ast::Modifier::*;
299        use crate::common::Size::*;
300        use self::SpecialComm::*;
301        use self::Relocation::*;
302
303        const EXTENDS: &[super::ast::Modifier] = &[UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX, LSL];
304        const EXTENDS_W: &[super::ast::Modifier] = &[UXTB, UXTH, UXTW, SXTB, SXTH, SXTW];
305        const EXTENDS_X: &[super::ast::Modifier] = &[UXTX, SXTX, LSL];
306        const SHIFTS: &[super::ast::Modifier] = &[LSL, LSR, ASR];
307        const ROTATES: &[super::ast::Modifier] = &[LSL, LSR, ASR, ROR];
308
309        static MAP: &[(&str, &[Opdata])] = &include!("opmap.rs");
310        MAP.iter().cloned().collect()
311    };
312
313    /// A map of existing condition codes and their normal encoding
314    pub static ref COND_MAP: HashMap<&'static str, u8> = {
315        static MAP: &[(&str, u8)] = &[
316            ("eq", 0),
317            ("ne", 1),
318            ("cs", 2),
319            ("hs", 2),
320            ("cc", 3),
321            ("lo", 3),
322            ("mi", 4),
323            ("pl", 5),
324            ("vs", 6),
325            ("vc", 7),
326            ("hi", 8),
327            ("ls", 9),
328            ("ge", 10),
329            ("lt", 11),
330            ("gt", 12),
331            ("le", 13),
332            ("al", 14),
333            ("nv", 15),
334        ];
335        MAP.iter().cloned().collect()
336    };
337
338    // special ident maps
339    pub static ref SPECIAL_IDENT_MAP: HashMap<&'static str, HashMap<&'static str, u32>> = {
340        let mut mapmap = HashMap::new();
341        mapmap.insert("AT_OPS", {
342            static MAP: &[(&str, u32)] = &[
343                ("s1e1r",  0b00_0011_1100_0000),
344                ("s1e1w",  0b00_0011_1100_0001),
345                ("s1e0r",  0b00_0011_1100_0010),
346                ("s1e0w",  0b00_0011_1100_0011),
347                ("s1e2r",  0b10_0011_1100_0000),
348                ("s1e2w",  0b10_0011_1100_0001),
349                ("s12e1r", 0b10_0011_1100_0100),
350                ("s12e1w", 0b10_0011_1100_0101),
351                ("s12e0r", 0b10_0011_1100_0110),
352                ("s12e0w", 0b10_0011_1100_0111),
353                ("s1e3r",  0b11_0011_1100_0000),
354                ("s1e3w",  0b11_0011_1100_0001),
355                ("s1e1rp", 0b00_0011_1100_1000),
356                ("s1e1wp", 0b00_0011_1100_1001),
357            ];
358            MAP.iter().cloned().collect()
359        });
360        mapmap.insert("IC_OPS", {
361            static MAP: &[(&str, u32)] = &[
362                ("ialluis", 0b00_0011_1000_1000),
363                ("iallu",   0b00_0011_1010_1000),
364            ];
365            MAP.iter().cloned().collect()
366        });
367        mapmap.insert("DC_OPS", {
368            static MAP: &[(&str, u32)] = &[
369                ("ivac",  0b00_0011_1011_0001),
370                ("isw",   0b00_0011_1011_0010),
371                ("csw",   0b00_0011_1101_0010),
372                ("cisw",  0b00_0011_1111_0010),
373                ("zva",   0b01_1011_1010_0001),
374                ("cvac",  0b01_1011_1101_0001),
375                ("cvau",  0b01_1011_1101_1001),
376                ("civac", 0b01_1011_1111_0001),
377                ("cvap",  0b01_1011_1110_0001),
378            ];
379            MAP.iter().cloned().collect()
380        });
381        mapmap.insert("BARRIER_OPS", {
382            static MAP: &[(&str, u32)] = &[
383                ("sy",    0b1111),
384                ("st",    0b1110),
385                ("ld",    0b1101),
386                ("ish",   0b1011),
387                ("ishst", 0b1010),
388                ("ishld", 0b1001),
389                ("nsh",   0b0111),
390                ("nshst", 0b0110),
391                ("nshld", 0b0101),
392                ("osh",   0b0011),
393                ("oshst", 0b0010),
394                ("oshld", 0b0001),
395            ];
396            MAP.iter().cloned().collect()
397        });
398        mapmap.insert("MSR_IMM_OPS", {
399            static MAP: &[(&str, u32)] = &[
400                ("spsel",   0b00_0010_0000_0101),
401                ("daifset", 0b01_1010_0000_0110),
402                ("daifclr", 0b01_1010_0000_0111),
403                ("uao",     0b00_0010_0000_0011),
404                ("pan",     0b00_0010_0000_0100),
405                ("dit",     0b01_1010_0000_0010),
406            ];
407            MAP.iter().cloned().collect()
408        });
409        mapmap.insert("CONTROL_REGS", {
410            static MAP: &[(&str, u32)] = &[
411                ("c0",  0),
412                ("c1",  1),
413                ("c2",  2),
414                ("c3",  3),
415                ("c4",  4),
416                ("c5",  5),
417                ("c6",  6),
418                ("c7",  7),
419                ("c8",  8),
420                ("c9",  9),
421                ("c10", 10),
422                ("c11", 11),
423                ("c12", 12),
424                ("c13", 13),
425                ("c14", 14),
426                ("c15", 15),
427            ];
428            MAP.iter().cloned().collect()
429        });
430        mapmap.insert("TLBI_OPS", {
431            static MAP: &[(&str, u32)] = &[
432                ("vmalle1is",    0b00_0100_0001_1000),
433                ("vae1is",       0b00_0100_0001_1001),
434                ("aside1is",     0b00_0100_0001_1010),
435                ("vaae1is",      0b00_0100_0001_1011),
436                ("vale1is",      0b00_0100_0001_1101),
437                ("vaale1is",     0b00_0100_0001_1111),
438                ("vmalle1",      0b00_0100_0011_1000),
439                ("vae1",         0b00_0100_0011_1001),
440                ("aside1",       0b00_0100_0011_1010),
441                ("vaae1",        0b00_0100_0011_1011),
442                ("vale1",        0b00_0100_0011_1101),
443                ("vaale1",       0b00_0100_0011_1111),
444                ("ipas2e1is",    0b10_0100_0000_0001),
445                ("ipas2le1is",   0b10_0100_0000_0101),
446                ("alle2is",      0b10_0100_0001_1000),
447                ("vae2is",       0b10_0100_0001_1001),
448                ("alle1is",      0b10_0100_0001_1100),
449                ("vale2is",      0b10_0100_0001_1101),
450                ("vmalls12e1is", 0b10_0100_0001_1110),
451                ("ipas2e1",      0b10_0100_0010_0001),
452                ("ipas2le1",     0b10_0100_0010_0101),
453                ("alle2",        0b10_0100_0011_1000),
454                ("vae2",         0b10_0100_0011_1001),
455                ("alle1",        0b10_0100_0011_1100),
456                ("vale2",        0b10_0100_0011_1101),
457                ("vmalls12e1",   0b10_0100_0011_1110),
458                ("alle3is",      0b11_0100_0001_1000),
459                ("vae3is",       0b11_0100_0001_1001),
460                ("vale3is",      0b11_0100_0001_1101),
461                ("alle3",        0b11_0100_0011_1000),
462                ("vae3",         0b11_0100_0011_1001),
463                ("vale3",        0b11_0100_0011_1101),
464                ("vmalle1os",    0b00_0100_0000_1000),
465                ("vae1os",       0b00_0100_0000_1001),
466                ("aside1os",     0b00_0100_0000_1010),
467                ("vaae1os",      0b00_0100_0000_1011),
468                ("vale1os",      0b00_0100_0000_1101),
469                ("vaale1os",     0b00_0100_0000_1111),
470                ("rvae1is",      0b00_0100_0001_0001),
471                ("rvaae1is",     0b00_0100_0001_0011),
472                ("rvale1is",     0b00_0100_0001_0101),
473                ("rvaale1is",    0b00_0100_0001_0111),
474                ("rvae1os",      0b00_0100_0010_1001),
475                ("rvaae1os",     0b00_0100_0010_1011),
476                ("rvale1os",     0b00_0100_0010_1101),
477                ("rvaale1os",    0b00_0100_0010_1111),
478                ("rvae1",        0b00_0100_0011_0001),
479                ("rvaae1",       0b00_0100_0011_0011),
480                ("rvale1",       0b00_0100_0011_0101),
481                ("rvaale1",      0b00_0100_0011_0111),
482                ("ripas2e1is",   0b10_0100_0000_0010),
483                ("ripas2le1is",  0b10_0100_0000_0110),
484                ("alle2os",      0b10_0100_0000_1000),
485                ("vae2os",       0b10_0100_0000_1001),
486                ("alle1os",      0b10_0100_0000_1100),
487                ("vale2os",      0b10_0100_0000_1101),
488                ("vmalls12e1os", 0b10_0100_0000_1110),
489                ("rvae2is",      0b10_0100_0001_0001),
490                ("rvale2is",     0b10_0100_0001_0101),
491                ("ipas2e1os",    0b10_0100_0010_0000),
492                ("ripas2e1",     0b10_0100_0010_0010),
493                ("ripas2e1os",   0b10_0100_0010_0011),
494                ("ipas2le1os",   0b10_0100_0010_0100),
495                ("ripas2le1",    0b10_0100_0010_0110),
496                ("ripas2le1os",  0b10_0100_0010_0111),
497                ("rvae2os",      0b10_0100_0010_1001),
498                ("rvale2os",     0b10_0100_0010_1101),
499                ("rvae2",        0b10_0100_0011_0001),
500                ("rvale2",       0b10_0100_0011_0101),
501                ("alle3os",      0b11_0100_0000_1000),
502                ("vae3os",       0b11_0100_0000_1001),
503                ("vale3os",      0b11_0100_0000_1101),
504                ("rvae3is",      0b11_0100_0001_0001),
505                ("rvale3is",     0b11_0100_0001_0101),
506                ("rvae3os",      0b11_0100_0010_1001),
507                ("rvale3os",     0b11_0100_0010_1101),
508                ("rvae3",        0b11_0100_0011_0001),
509                ("rvale3",       0b11_0100_0011_0101),
510            ];
511            MAP.iter().cloned().collect()
512        });
513        mapmap
514    };
515}