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}