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}