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}
222
223impl Relocation {
224    pub fn to_id(self) -> u8 {
225        self as u8
226    }
227}
228
229
230#[derive(Debug, Clone, Copy)]
231pub struct Opdata {
232    /// The base template for the encoding.
233    pub base: u32,
234    /// A set of matchers capable of matching the instruction encoding that this instruction represents.
235    pub matchers: &'static [Matcher],
236    /// A sequence of encoder commands that check the matched instruction on validity and whose output gets orred together with the original template at runtime.
237    pub commands: &'static [Command]
238}
239
240macro_rules! SingleOp {
241    ( $base:expr, [ $( $matcher:expr ),* ], [ $( $command:expr ),* ] ) => {
242        {
243            const MATCHERS: &'static [Matcher] = {
244                #[allow(unused_imports)]
245                use self::Matcher::*;
246                &[ $(
247                    $matcher
248                ),* ]
249            };
250            const COMMANDS: &'static [Command] = {
251                #[allow(unused_imports)]
252                use self::Command::*;
253                &[ $(
254                    $command
255                ),* ]
256            };
257            Opdata {
258                base: $base,
259                matchers: MATCHERS,
260                commands: COMMANDS,
261            }
262        }
263    }
264}
265
266macro_rules! Ops {
267    ( $( $name:tt = [ $( $base:tt = [ $( $matcher:expr ),* ] => [ $( $command:expr ),* ] ; )+ ] )* ) => {
268        [ $(
269            (
270                $name,
271                &[ $(
272                    SingleOp!( $base, [ $( $matcher ),* ], [ $( $command ),* ] )
273                ),+ ] as &[_]
274            )
275        ),* ]
276    }
277}
278
279pub fn get_mnemonic_data(name: &str) -> Option<&'static [Opdata]> {
280    OPMAP.get(&name).cloned()
281}
282
283#[allow(dead_code)]
284pub fn mnemnonics() -> hash_map::Keys<'static, &'static str, &'static [Opdata]> {
285    OPMAP.keys()
286}
287
288lazy_static! {
289    static ref OPMAP: HashMap<&'static str, &'static [Opdata]> = {
290        use super::ast::Modifier::*;
291        use crate::common::Size::*;
292        use self::SpecialComm::*;
293        use self::Relocation::*;
294
295        const EXTENDS: &[super::ast::Modifier] = &[UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX, LSL];
296        const EXTENDS_W: &[super::ast::Modifier] = &[UXTB, UXTH, UXTW, SXTB, SXTH, SXTW];
297        const EXTENDS_X: &[super::ast::Modifier] = &[UXTX, SXTX, LSL];
298        const SHIFTS: &[super::ast::Modifier] = &[LSL, LSR, ASR];
299        const ROTATES: &[super::ast::Modifier] = &[LSL, LSR, ASR, ROR];
300
301        static MAP: &[(&str, &[Opdata])] = &include!("opmap.rs");
302        MAP.iter().cloned().collect()
303    };
304
305    /// A map of existing condition codes and their normal encoding
306    pub static ref COND_MAP: HashMap<&'static str, u8> = {
307        static MAP: &[(&str, u8)] = &[
308            ("eq", 0),
309            ("ne", 1),
310            ("cs", 2),
311            ("hs", 2),
312            ("cc", 3),
313            ("lo", 3),
314            ("mi", 4),
315            ("pl", 5),
316            ("vs", 6),
317            ("vc", 7),
318            ("hi", 8),
319            ("ls", 9),
320            ("ge", 10),
321            ("lt", 11),
322            ("gt", 12),
323            ("le", 13),
324            ("al", 14),
325            ("nv", 15),
326        ];
327        MAP.iter().cloned().collect()
328    };
329
330    // special ident maps
331    pub static ref SPECIAL_IDENT_MAP: HashMap<&'static str, HashMap<&'static str, u32>> = {
332        let mut mapmap = HashMap::new();
333        mapmap.insert("AT_OPS", {
334            static MAP: &[(&str, u32)] = &[
335                ("s1e1r",  0b00_0011_1100_0000),
336                ("s1e1w",  0b00_0011_1100_0001),
337                ("s1e0r",  0b00_0011_1100_0010),
338                ("s1e0w",  0b00_0011_1100_0011),
339                ("s1e2r",  0b10_0011_1100_0000),
340                ("s1e2w",  0b10_0011_1100_0001),
341                ("s12e1r", 0b10_0011_1100_0100),
342                ("s12e1w", 0b10_0011_1100_0101),
343                ("s12e0r", 0b10_0011_1100_0110),
344                ("s12e0w", 0b10_0011_1100_0111),
345                ("s1e3r",  0b11_0011_1100_0000),
346                ("s1e3w",  0b11_0011_1100_0001),
347                ("s1e1rp", 0b00_0011_1100_1000),
348                ("s1e1wp", 0b00_0011_1100_1001),
349            ];
350            MAP.iter().cloned().collect()
351        });
352        mapmap.insert("IC_OPS", {
353            static MAP: &[(&str, u32)] = &[
354                ("ialluis", 0b00_0011_1000_1000),
355                ("iallu",   0b00_0011_1010_1000),
356            ];
357            MAP.iter().cloned().collect()
358        });
359        mapmap.insert("DC_OPS", {
360            static MAP: &[(&str, u32)] = &[
361                ("ivac",  0b00_0011_1011_0001),
362                ("isw",   0b00_0011_1011_0010),
363                ("csw",   0b00_0011_1101_0010),
364                ("cisw",  0b00_0011_1111_0010),
365                ("zva",   0b01_1011_1010_0001),
366                ("cvac",  0b01_1011_1101_0001),
367                ("cvau",  0b01_1011_1101_1001),
368                ("civac", 0b01_1011_1111_0001),
369                ("cvap",  0b01_1011_1110_0001),
370            ];
371            MAP.iter().cloned().collect()
372        });
373        mapmap.insert("BARRIER_OPS", {
374            static MAP: &[(&str, u32)] = &[
375                ("sy",    0b1111),
376                ("st",    0b1110),
377                ("ld",    0b1101),
378                ("ish",   0b1011),
379                ("ishst", 0b1010),
380                ("ishld", 0b1001),
381                ("nsh",   0b0111),
382                ("nshst", 0b0110),
383                ("nshld", 0b0101),
384                ("osh",   0b0011),
385                ("oshst", 0b0010),
386                ("oshld", 0b0001),
387            ];
388            MAP.iter().cloned().collect()
389        });
390        mapmap.insert("MSR_IMM_OPS", {
391            static MAP: &[(&str, u32)] = &[
392                ("spsel",   0b00_0010_0000_0101),
393                ("daifset", 0b01_1010_0000_0110),
394                ("daifclr", 0b01_1010_0000_0111),
395                ("uao",     0b00_0010_0000_0011),
396                ("pan",     0b00_0010_0000_0100),
397                ("dit",     0b01_1010_0000_0010),
398            ];
399            MAP.iter().cloned().collect()
400        });
401        mapmap.insert("CONTROL_REGS", {
402            static MAP: &[(&str, u32)] = &[
403                ("c0",  0),
404                ("c1",  1),
405                ("c2",  2),
406                ("c3",  3),
407                ("c4",  4),
408                ("c5",  5),
409                ("c6",  6),
410                ("c7",  7),
411                ("c8",  8),
412                ("c9",  9),
413                ("c10", 10),
414                ("c11", 11),
415                ("c12", 12),
416                ("c13", 13),
417                ("c14", 14),
418                ("c15", 15),
419            ];
420            MAP.iter().cloned().collect()
421        });
422        mapmap.insert("TLBI_OPS", {
423            static MAP: &[(&str, u32)] = &[
424                ("vmalle1is",    0b00_0100_0001_1000),
425                ("vae1is",       0b00_0100_0001_1001),
426                ("aside1is",     0b00_0100_0001_1010),
427                ("vaae1is",      0b00_0100_0001_1011),
428                ("vale1is",      0b00_0100_0001_1101),
429                ("vaale1is",     0b00_0100_0001_1111),
430                ("vmalle1",      0b00_0100_0011_1000),
431                ("vae1",         0b00_0100_0011_1001),
432                ("aside1",       0b00_0100_0011_1010),
433                ("vaae1",        0b00_0100_0011_1011),
434                ("vale1",        0b00_0100_0011_1101),
435                ("vaale1",       0b00_0100_0011_1111),
436                ("ipas2e1is",    0b10_0100_0000_0001),
437                ("ipas2le1is",   0b10_0100_0000_0101),
438                ("alle2is",      0b10_0100_0001_1000),
439                ("vae2is",       0b10_0100_0001_1001),
440                ("alle1is",      0b10_0100_0001_1100),
441                ("vale2is",      0b10_0100_0001_1101),
442                ("vmalls12e1is", 0b10_0100_0001_1110),
443                ("ipas2e1",      0b10_0100_0010_0001),
444                ("ipas2le1",     0b10_0100_0010_0101),
445                ("alle2",        0b10_0100_0011_1000),
446                ("vae2",         0b10_0100_0011_1001),
447                ("alle1",        0b10_0100_0011_1100),
448                ("vale2",        0b10_0100_0011_1101),
449                ("vmalls12e1",   0b10_0100_0011_1110),
450                ("alle3is",      0b11_0100_0001_1000),
451                ("vae3is",       0b11_0100_0001_1001),
452                ("vale3is",      0b11_0100_0001_1101),
453                ("alle3",        0b11_0100_0011_1000),
454                ("vae3",         0b11_0100_0011_1001),
455                ("vale3",        0b11_0100_0011_1101),
456                ("vmalle1os",    0b00_0100_0000_1000),
457                ("vae1os",       0b00_0100_0000_1001),
458                ("aside1os",     0b00_0100_0000_1010),
459                ("vaae1os",      0b00_0100_0000_1011),
460                ("vale1os",      0b00_0100_0000_1101),
461                ("vaale1os",     0b00_0100_0000_1111),
462                ("rvae1is",      0b00_0100_0001_0001),
463                ("rvaae1is",     0b00_0100_0001_0011),
464                ("rvale1is",     0b00_0100_0001_0101),
465                ("rvaale1is",    0b00_0100_0001_0111),
466                ("rvae1os",      0b00_0100_0010_1001),
467                ("rvaae1os",     0b00_0100_0010_1011),
468                ("rvale1os",     0b00_0100_0010_1101),
469                ("rvaale1os",    0b00_0100_0010_1111),
470                ("rvae1",        0b00_0100_0011_0001),
471                ("rvaae1",       0b00_0100_0011_0011),
472                ("rvale1",       0b00_0100_0011_0101),
473                ("rvaale1",      0b00_0100_0011_0111),
474                ("ripas2e1is",   0b10_0100_0000_0010),
475                ("ripas2le1is",  0b10_0100_0000_0110),
476                ("alle2os",      0b10_0100_0000_1000),
477                ("vae2os",       0b10_0100_0000_1001),
478                ("alle1os",      0b10_0100_0000_1100),
479                ("vale2os",      0b10_0100_0000_1101),
480                ("vmalls12e1os", 0b10_0100_0000_1110),
481                ("rvae2is",      0b10_0100_0001_0001),
482                ("rvale2is",     0b10_0100_0001_0101),
483                ("ipas2e1os",    0b10_0100_0010_0000),
484                ("ripas2e1",     0b10_0100_0010_0010),
485                ("ripas2e1os",   0b10_0100_0010_0011),
486                ("ipas2le1os",   0b10_0100_0010_0100),
487                ("ripas2le1",    0b10_0100_0010_0110),
488                ("ripas2le1os",  0b10_0100_0010_0111),
489                ("rvae2os",      0b10_0100_0010_1001),
490                ("rvale2os",     0b10_0100_0010_1101),
491                ("rvae2",        0b10_0100_0011_0001),
492                ("rvale2",       0b10_0100_0011_0101),
493                ("alle3os",      0b11_0100_0000_1000),
494                ("vae3os",       0b11_0100_0000_1001),
495                ("vale3os",      0b11_0100_0000_1101),
496                ("rvae3is",      0b11_0100_0001_0001),
497                ("rvale3is",     0b11_0100_0001_0101),
498                ("rvae3os",      0b11_0100_0010_1001),
499                ("rvale3os",     0b11_0100_0010_1101),
500                ("rvae3",        0b11_0100_0011_0001),
501                ("rvale3",       0b11_0100_0011_0101),
502            ];
503            MAP.iter().cloned().collect()
504        });
505        mapmap
506    };
507}