Skip to main content

asmkit/aarch64/
assembler.rs

1use crate::aarch64::opcodes::{Encoding, Opcode, INST_INFO};
2use crate::core::buffer::{LabelUse, Reloc, RelocTarget};
3use crate::core::operand::*;
4use crate::core::{buffer::CodeBuffer, emitter::Emitter, patch::PatchSiteId};
5use crate::AsmError;
6
7use super::emitter::A64EmitterExplicit;
8pub struct Assembler<'a> {
9    pub buffer: &'a mut CodeBuffer,
10    last_error: Option<AsmError>,
11}
12
13impl<'a> Assembler<'a> {
14    pub fn patchable_b(&mut self, label: Label) -> PatchSiteId {
15        let offset = self.buffer.cur_offset();
16        self.b(label);
17        self.buffer
18            .record_label_patch_site(offset, label, LabelUse::A64Branch26)
19    }
20
21    pub fn patchable_call(&mut self, label: Label) -> PatchSiteId {
22        let offset = self.buffer.cur_offset();
23        self.bl(label);
24        self.buffer
25            .record_label_patch_site(offset, label, LabelUse::A64Branch26)
26    }
27}
28
29fn imm_add(value: i64) -> u32 {
30    let mut inst = 0;
31    let mut uval = value as u64;
32    if value < 0 {
33        inst = 0x40000000;
34        uval = !uval;
35    }
36
37    if (uval & 0xfff) == uval {
38        return inst | (uval << 10) as u32;
39    }
40
41    if (uval & 0xfff000) == uval {
42        return inst | 1 << 22 | (uval >> 2) as u32;
43    }
44
45    u32::MAX
46}
47
48fn imm_logical(mut value: u64, is64: bool) -> u32 {
49    if !is64 {
50        value = value | (value << 32);
51    }
52
53    if value == 0 || !value == 0 {
54        return u32::MAX;
55    }
56
57    let clz = value.leading_zeros();
58    let iclz = (!value).leading_zeros();
59    let ctz = value.trailing_zeros();
60    let ictz = (!value).trailing_zeros();
61    let mut popcount = value.count_ones();
62    let mut elog = 0;
63    let mut shift = 64;
64    let mut imms = (0x1780) | (popcount - 1);
65    while elog < 6 {
66        if (clz + ctz) == (shift - popcount) {
67            return (((if ctz != 0 { shift - ctz } else { 0 }) << 6) | (imms & 0x103f)) << 10;
68        } else if (iclz + ictz) == popcount {
69            return ((iclz << 6) | (imms & 0x103f)) << 10;
70        }
71        elog += 1;
72        popcount >>= 1;
73        shift >>= 1;
74        imms >>= 1;
75        let mask = (1u64 << shift) - 1;
76        if (value & mask) != (value >> shift & mask) {
77            break;
78        }
79    }
80
81    unreachable!()
82}
83
84fn imm_fmov32(value: f32) -> u32 {
85    let vi = value.to_bits();
86    if (vi & 0x7ffff) == 0 && ((vi >> 25 & 0x3f) - 0x1f) <= 1 {
87        return (vi >> 19 & 0x7f) | (vi >> 24 & 0x80);
88    }
89    return 0xffffffff;
90}
91
92fn imm_fmov64(value: f64) -> u64 {
93    let vi = value.to_bits();
94    if (vi & 0xffffffffffff) != 0 && ((vi >> 54 & 0x1ff) - 0xff) <= 1 {
95        return (vi >> 48 & 0x7f) | (vi >> 56 & 0x80);
96    }
97    return 0xffffffff;
98}
99
100const fn movi_encode(imm8: u32, op: u32, cmode: u32) -> u32 {
101    let x = if op != 0 { 0x20000000 } else { 0 };
102    x | ((cmode) << 12) | (((imm8) << 11) & 0x70000) | (((imm8) << 5) & 0x3e0)
103}
104
105fn imm_simdmovi(value: u64) -> u32 {
106    let imm8 = || {
107        return movi_encode((value & 0xff) as u32, 0, 0xe);
108    };
109    let mask64 = || {
110        let mut imm8 = 0u32;
111        for i in 0..8 {
112            let byte = value >> 8 * i & 0xff;
113            if byte == 0xff {
114                imm8 |= 1 << i;
115            } else if byte != 0 {
116                return u32::MAX;
117            }
118        }
119
120        return movi_encode(imm8, 1, 0xe);
121    };
122
123    if value == 0 || !value == 0 {
124        return imm8();
125    }
126    if (value & u32::MAX as u64) != value >> 32 {
127        return mask64();
128    }
129
130    if (value & 0xffff) != (value >> 16 & 0xffff) {
131        let value32 = value as u32;
132        let clz = value32.leading_zeros() >> 3;
133        let iclz = (!value32).leading_zeros() >> 3;
134        let ctz = value32.trailing_zeros() >> 3;
135        let ictz = (!value32).trailing_zeros() >> 3;
136
137        if clz + ctz >= 3 {
138            return movi_encode((value >> ctz * 8) as u32, 0, ctz * 2);
139        }
140        if iclz + ictz >= 3 {
141            return movi_encode((!value >> ictz * 8) as u32, 1, ictz * 2);
142        }
143        if clz + ictz >= 3 {
144            return movi_encode((value >> ictz * 8) as u32, 0, 0xc + ictz - 1);
145        }
146
147        if iclz + ctz >= 3 {
148            return movi_encode((!value >> ctz * 8) as u32, 1, 0xc + ctz - 1);
149        }
150
151        return mask64();
152    }
153
154    if (value & 0xff) != (value >> 8 & 0xff) {
155        let low8 = value & 0xff;
156        let high8 = value >> 8 & 0xff;
157
158        if high8 == 0 {
159            return movi_encode(low8 as _, 0, 0x8);
160        }
161
162        if high8 == 0xff {
163            return movi_encode((!low8) as u32, 1, 0x8);
164        }
165
166        if low8 == 0 {
167            return movi_encode(high8 as _, 0, 0xa);
168        }
169
170        if low8 == 0xff {
171            return movi_encode((!high8) as u32, 1, 0xa);
172        }
173    }
174
175    imm8()
176}
177
178impl<'a> Assembler<'a> {
179    pub fn last_error(&self) -> Option<&AsmError> {
180        self.last_error.as_ref()
181    }
182
183    pub fn new(buffer: &'a mut CodeBuffer) -> Self {
184        Assembler {
185            buffer,
186            last_error: None,
187        }
188    }
189
190    fn use_label(&mut self, label: &Operand, kind: LabelUse) {
191        let off = self.buffer.cur_offset();
192        self.buffer
193            .use_label_at_offset(off, label.as_::<Label>(), kind);
194    }
195}
196
197macro_rules! enc_ops1 {
198    ($op0:ident) => {
199        OperandType::$op0 as u32
200    };
201}
202
203macro_rules! enc_ops2 {
204    ($op0:ident, $op1:ident) => {
205        (OperandType::$op0 as u32) | ((OperandType::$op1 as u32) << 3)
206    };
207}
208
209macro_rules! enc_ops3 {
210    ($op0:ident, $op1:ident, $op2:ident) => {
211        (OperandType::$op0 as u32)
212            | ((OperandType::$op1 as u32) << 3)
213            | ((OperandType::$op2 as u32) << 6)
214    };
215}
216
217macro_rules! enc_ops4 {
218    ($op0:ident, $op1:ident, $op2:ident, $op3:ident) => {
219        (OperandType::$op0 as u32)
220            | ((OperandType::$op1 as u32) << 3)
221            | ((OperandType::$op2 as u32) << 6)
222            | ((OperandType::$op3 as u32) << 9)
223    };
224}
225
226impl<'a> Emitter for Assembler<'a> {
227    fn emit_n(&mut self, opcode: i64, ops: &[&Operand]) {
228        assert!(opcode < Opcode::LAST as i64);
229
230        let opcode: Opcode = unsafe { core::mem::transmute(opcode as u16) };
231
232        let info = &INST_INFO[opcode as usize];
233
234        let isign3 = match ops {
235            [] => 0,
236            [op0] => op0.op_type() as u32,
237            [op0, op1] => op0.op_type() as u32 + ((op1.op_type() as u32) << 3),
238            [op0, op1, op2, ..] => {
239                op0.op_type() as u32 + ((op1.op_type() as u32) << 3) + ((op2.op_type() as u32) << 6)
240            }
241        };
242
243        let isign4 = match ops {
244            [] => 0,
245            [op0] => op0.op_type() as u32,
246            [op0, op1] => op0.op_type() as u32 + ((op1.op_type() as u32) << 3),
247            [op0, op1, op2] => {
248                op0.op_type() as u32 + ((op1.op_type() as u32) << 3) + ((op2.op_type() as u32) << 6)
249            }
250            [op0, op1, op2, op3, ..] => {
251                op0.op_type() as u32
252                    + ((op1.op_type() as u32) << 3)
253                    + ((op2.op_type() as u32) << 6)
254                    + ((op3.op_type() as u32) << 9)
255            }
256        };
257
258        let mut err = None;
259
260        match info.encoding {
261            Encoding::Empty => {
262                self.buffer.put4(info.val);
263                return;
264            }
265
266            Encoding::CondRelAddr19 => {
267                if isign3 == enc_ops2!(Imm, Label) {
268                    let cond = ops[0].as_::<Imm>().value() as u32;
269
270                    self.use_label(ops[1], LabelUse::A64Branch19);
271                    self.buffer
272                        .put4(info.val | (0 & 0x7ffff) << 5 | ((cond & 0xf) << 0));
273                    return;
274                } else if isign3 == enc_ops2!(Imm, Imm) {
275                    let cond = ops[0].as_::<Imm>().value() as u32;
276                    let imm = ops[1].as_::<Imm>().value() as u32;
277                    self.buffer
278                        .put4(info.val | ((imm & 0x7ffff) << 5) | ((cond & 0xf) << 0));
279                    return;
280                } else {
281                }
282            }
283
284            Encoding::RelAddr26 => {
285                if isign3 == enc_ops1!(Label) {
286                    self.use_label(ops[0], LabelUse::A64Branch26);
287                    self.buffer.put4(info.val);
288                    return;
289                } else if isign3 == enc_ops1!(Imm) {
290                    let imm26 = ops[0].as_::<Imm>().value() as u32;
291                    self.buffer.put4(info.val | (imm26 & 0x03ff_ffff));
292                    return;
293                }
294            }
295
296            Encoding::Const0 => {
297                self.buffer.put4(info.val | (0 & 0xf) << 8);
298                return;
299            }
300
301            Encoding::Const15 => {
302                self.buffer.put4(info.val | (15 & 0xf) << 8);
303                return;
304            }
305
306            Encoding::FpConst0 => {
307                if isign3 == enc_ops1!(Reg) {
308                    let rn = ops[0].id();
309                    self.buffer
310                        .put4(info.val | (0 & 0x1f) << 16 | (rn & 0x1f) << 5);
311                    return;
312                }
313            }
314
315            Encoding::FpFp => {
316                if isign3 == enc_ops2!(Reg, Reg) {
317                    let rm = ops[0].id();
318                    let rn = ops[1].id();
319                    self.buffer
320                        .put4(info.val | (rm & 0x1f) << 16 | (rn & 0x1f) << 5);
321                    return;
322                }
323            }
324
325            Encoding::FpFpConst0 => {
326                if isign3 == enc_ops2!(Reg, Reg) {
327                    let rd = ops[0].id();
328                    let rn = ops[1].id();
329                    self.buffer
330                        .put4(info.val | (0 & 0x7) << 16 | (rn & 0x1f) << 5 | (rd & 0x1f) << 0);
331                    return;
332                }
333            }
334
335            Encoding::FpFpFp => {
336                if isign3 == enc_ops3!(Reg, Reg, Reg) {
337                    let rd = ops[0].id();
338                    let rn = ops[1].id();
339                    let rm = ops[2].id();
340
341                    self.buffer.put4(
342                        info.val | ((rm & 0x1f) << 16) | (rn & 0x1f) << 5 | ((rd & 0x1f) << 0),
343                    );
344                    return;
345                }
346            }
347
348            Encoding::FpFpFpCond => {
349                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
350                    let rd = ops[0].id();
351                    let rn = ops[1].id();
352                    let rm = ops[2].id();
353                    let cond = ops[3].as_::<Imm>().value();
354
355                    self.buffer.put4(
356                        info.val
357                            | ((rm & 0x1f) << 16)
358                            | ((cond as u32 & 0xf) << 12)
359                            | (rn & 0x1f) << 5
360                            | ((rd & 0x1f) << 0),
361                    );
362                    return;
363                }
364            }
365
366            Encoding::FpFpFpFp => {
367                if isign4 == enc_ops4!(Reg, Reg, Reg, Reg) {
368                    let rd = ops[0].id();
369                    let rn = ops[1].id();
370                    let rm = ops[2].id();
371                    let ra = ops[3].id();
372
373                    self.buffer.put4(
374                        info.val
375                            | ((rm & 0x1f) << 16)
376                            | ((ra & 0x1f) << 10)
377                            | (rn & 0x1f) << 5
378                            | ((rd & 0x1f) << 0),
379                    );
380                    return;
381                }
382            }
383
384            Encoding::FpFpFpImm => {
385                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
386                    let rd = ops[0].id();
387                    let rn = ops[1].id();
388                    let rm = ops[2].id();
389                    let imm4 = ops[3].as_::<Imm>().value() as i32 as u32;
390
391                    self.buffer.put4(
392                        info.val
393                            | ((rm & 0x1f) << 16)
394                            | ((imm4 & 0xf) << 11)
395                            | ((rn & 0x1f) << 5)
396                            | ((rd & 0x1f) << 0),
397                    );
398                    return;
399                }
400            }
401
402            Encoding::FpFpFpImmRotAdd => {
403                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
404                    let rd = ops[0].id();
405                    let rn = ops[1].id();
406                    let rm = ops[2].id();
407                    let rot = ops[3].as_::<Imm>().value() as i32 as u32;
408                    if rot == 90 || rot == 270 {
409                        self.buffer.put4(
410                            info.val
411                                | ((rm & 0x1f) << 16)
412                                | (((rot / 90 - 1) & 0x3) << 11)
413                                | ((rn & 0x1f) << 5)
414                                | ((rd & 0x1f) << 0),
415                        );
416                        return;
417                    } else {
418                    }
419                } else {
420                }
421            }
422
423            Encoding::FpFpFpImmRotMul => {
424                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
425                    let rd = ops[0].id();
426                    let rn = ops[1].id();
427                    let rm = ops[2].id();
428                    let rot = ops[3].as_::<Imm>().value() as i32 as u32;
429                    if rot < 360 && rot % 90 == 0 {
430                        self.buffer.put4(
431                            info.val
432                                | ((rm & 0x1f) << 16)
433                                | (((rot / 90) & 0x3) << 11)
434                                | ((rn & 0x1f) << 5)
435                                | ((rd & 0x1f) << 0),
436                        );
437                        return;
438                    } else {
439                    }
440                } else {
441                }
442            }
443
444            Encoding::FpFpFpVelElemIdx0_1 => {
445                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
446                    let rd = ops[0].id();
447                    let rn = ops[1].id();
448                    let mrm = ops[2].id();
449                    let elemidx = ops[3].as_::<Imm>().value() as u32;
450                    // TODO: Broken
451                    if mrm < 16 && elemidx < (1 << (4 - 1)) {
452                        let v = info.val ^ mrm << 16
453                            | ((((elemidx << 1) >> 2) & 0x1) << 21)
454                            | ((((elemidx << 1) >> 1) & 0x1) << 20)
455                            | (((((elemidx << 1) & 1) << 3) & 0xf) << 16)
456                            | ((((elemidx << 1) >> 3) & 0x1) << 11)
457                            | ((rn & 0x1f) << 5)
458                            | ((rd & 0x1f) << 0);
459
460                        self.buffer.put4(v);
461                        return;
462                    } else {
463                    }
464                } else {
465                }
466            }
467
468            Encoding::FpFpFpVelElemIdx1 => {
469                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
470                    let rd = ops[0].id();
471                    let rn = ops[1].id();
472                    let mrm = ops[2].id();
473
474                    let elemidx = ops[3].id() as u32;
475                    let val = (info.val ^ mrm << 16)
476                        | ((((elemidx << 1) >> 2) & 0x1) << 21)
477                        | ((((elemidx << 1) >> 1) & 0x1) << 20)
478                        | (((0) & 0xf) << 16)
479                        | ((((elemidx << 1) >> 3) & 0x1) << 11)
480                        | ((rn & 0x1f) << 5)
481                        | ((rd & 0x1f) << 0);
482                    self.buffer.put4(val);
483                    return;
484                }
485            }
486
487            Encoding::FpFpFpVelElemIdx2 => {
488                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
489                    let rd = ops[0].id();
490                    let rn = ops[1].id();
491                    let mrm = ops[2].id();
492
493                    let elemidx = ops[3].id() as u32;
494                    let val = (info.val ^ mrm << 16)
495                        | ((((elemidx << 1) >> 2) & 0x1) << 21)
496                        | ((((elemidx << 1) >> 1) & 0x1) << 20)
497                        | (((0) & 0xf) << 16)
498                        | ((((elemidx << 1) >> 3) & 0x1) << 11)
499                        | ((rn & 0x1f) << 5)
500                        | ((rd & 0x1f) << 0);
501                    self.buffer.put4(val);
502                    return;
503                }
504            }
505
506            Encoding::FpFpFpVelElemIdx3 => {
507                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
508                    let rd = ops[0].id();
509                    let rn = ops[1].id();
510                    let mrm = ops[2].id();
511
512                    let elemidx = ops[3].id() as u32;
513                    let val = (info.val ^ mrm << 16)
514                        | ((((elemidx << 2) >> 2) & 0x1) << 21)
515                        | ((((elemidx << 2) >> 1) & 0x1) << 20)
516                        | (((0) & 0xf) << 16)
517                        | ((((elemidx << 2) >> 3) & 0x1) << 11)
518                        | ((rn & 0x1f) << 5)
519                        | ((rd & 0x1f) << 0);
520                    self.buffer.put4(val);
521                    return;
522                }
523            }
524
525            Encoding::FpFpFpVelElemIdxLim2_2ImmRotMul => {
526                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) && ops.len() == 5 && ops[4].is_imm() {
527                    let rd = ops[0].id();
528                    let rn = ops[1].id();
529                    let mrm = ops[2].id();
530
531                    let elemidx = ops[3].id() as u32;
532                    let rot = ops[4].id() as u32;
533                    let val = (info.val ^ mrm << 16)
534                        | ((((elemidx << 2) >> 2) & 0x1) << 21)
535                        | ((((elemidx << 2) >> 1) & 0x1) << 20)
536                        | (((0) & 0xf) << 16)
537                        | (((rot / 90) & 0x3) << 13)
538                        | ((((elemidx << 2) >> 3) & 0x1) << 11)
539                        | ((rn & 0x1f) << 5)
540                        | ((rd & 0x1f) << 0);
541
542                    self.buffer.put4(val);
543                    return;
544                }
545            }
546
547            Encoding::FpFpFpVelElemIdxLim2_4ImmRotMul => {
548                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) && ops.len() == 5 && ops[4].is_imm() {
549                    let rd = ops[0].id();
550                    let rn = ops[1].id();
551                    let mrm = ops[2].id();
552
553                    let elemidx = ops[3].id() as u32;
554                    let rot = ops[4].id() as u32;
555                    let val = (info.val ^ mrm << 16)
556                        | ((((elemidx << 2) >> 2) & 0x1) << 21)
557                        | ((((elemidx << 2) >> 1) & 0x1) << 20)
558                        | (((0) & 0xf) << 16)
559                        | (((rot / 90) & 0x3) << 13)
560                        | ((((elemidx << 2) >> 3) & 0x1) << 11)
561                        | ((rn & 0x1f) << 5)
562                        | ((rd & 0x1f) << 0);
563
564                    self.buffer.put4(val);
565                    return;
566                }
567            }
568            //
569            Encoding::FpFpFpVelElemIdxLim3_4ImmRotMul => {
570                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) && ops.len() == 5 && ops[4].is_imm() {
571                    let rd = ops[0].id();
572                    let rn = ops[1].id();
573                    let mrm = ops[2].id();
574
575                    let elemidx = ops[3].id() as u32;
576                    let rot = ops[4].id() as u32;
577                    let val = (info.val ^ mrm << 16)
578                        | ((((elemidx << 3) >> 2) & 0x1) << 21)
579                        | ((((elemidx << 3) >> 1) & 0x1) << 20)
580                        | (((0) & 0xf) << 16)
581                        | (((rot / 90) & 0x3) << 13)
582                        | ((((elemidx << 3) >> 3) & 0x1) << 11)
583                        | ((rn & 0x1f) << 5)
584                        | ((rd & 0x1f) << 0);
585
586                    self.buffer.put4(val);
587                    return;
588                }
589            }
590            Encoding::FpFpGpSImm7_2 => {
591                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
592                    let rt = ops[0].id();
593                    let rt2 = ops[1].id();
594                    let rn = ops[2].id();
595                    let imm7 = ops[3].as_::<Imm>().value() as i32 as u32;
596
597                    let val = info.val
598                        | (((imm7 / (1 << 2)) & 0x7f) << 15)
599                        | ((rt2 & 0x1f) << 10)
600                        | ((rn & 0x1f) << 5)
601                        | ((rt & 0x1f) << 0);
602                    self.buffer.put4(val);
603                    return;
604                }
605            }
606
607            Encoding::FpFpGpSImm7_3 => {
608                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
609                    let rt = ops[0].id();
610                    let rt2 = ops[1].id();
611                    let rn = ops[2].id();
612                    let imm7 = ops[3].as_::<Imm>().value() as i32 as u32;
613
614                    let val = info.val
615                        | (((imm7 / (1 << 3)) & 0x7f) << 15)
616                        | ((rt2 & 0x1f) << 10)
617                        | ((rn & 0x1f) << 5)
618                        | ((rt & 0x1f) << 0);
619                    self.buffer.put4(val);
620                    return;
621                }
622            }
623
624            Encoding::FpFpGpSImm7_4 => {
625                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
626                    let rt = ops[0].id();
627                    let rt2 = ops[1].id();
628                    let rn = ops[2].id();
629                    let imm7 = ops[3].as_::<Imm>().value() as i32 as u32;
630
631                    let val = info.val
632                        | (((imm7 / (1 << 4)) & 0x7f) << 15)
633                        | ((rt2 & 0x1f) << 10)
634                        | ((rn & 0x1f) << 5)
635                        | ((rt & 0x1f) << 0);
636                    self.buffer.put4(val);
637                    return;
638                }
639            }
640
641            Encoding::FpFpImmCond => {
642                if isign4 == enc_ops4!(Reg, Reg, Imm, Imm) {
643                    let rn = ops[0].id();
644                    let rm = ops[1].id();
645                    let nzcv = ops[2].as_::<Imm>().value() as u32;
646                    let cond = ops[3].as_::<Imm>().value() as u32;
647
648                    let val = info.val
649                        | ((rm & 0x1f) << 16)
650                        | ((cond & 0xf) << 12)
651                        | ((rn & 0x1f) << 5)
652                        | ((nzcv & 0xf) << 0);
653                    self.buffer.put4(val);
654                    return;
655                }
656            }
657
658            Encoding::FpFpImmShiftl16 => {
659                if isign3 == enc_ops3!(Reg, Reg, Imm) {
660                    let rd = ops[0].id();
661                    let rn = ops[1].id();
662                    let imm = ops[2].as_::<Imm>().value() as u32;
663
664                    let val = (info.val ^ imm << 16)
665                        | ((0 & 0xf) << 19)
666                        | ((0 & 0x7) << 16)
667                        | ((rn & 0x1f) << 5)
668                        | ((rd & 0x1f) << 0);
669                    self.buffer.put4(val);
670                    return;
671                }
672            }
673
674            Encoding::FpFpImmShiftl32 => {
675                if isign3 == enc_ops3!(Reg, Reg, Imm) {
676                    let rd = ops[0].id();
677                    let rn = ops[1].id();
678                    let imm = ops[2].as_::<Imm>().value() as u32;
679
680                    let val = (info.val ^ imm << 16)
681                        | ((0 & 0xf) << 19)
682                        | ((0 & 0x7) << 16)
683                        | ((rn & 0x1f) << 5)
684                        | ((rd & 0x1f) << 0);
685                    self.buffer.put4(val);
686                    return;
687                }
688            }
689
690            Encoding::FpFpImmShiftl64 => {
691                if isign3 == enc_ops3!(Reg, Reg, Imm) {
692                    let rd = ops[0].id();
693                    let rn = ops[1].id();
694                    let imm = ops[2].as_::<Imm>().value() as u32;
695
696                    let val = ((info.val ^ imm) << 16)
697                        | ((0 & 0xf) << 19)
698                        | ((0 & 0x7) << 16)
699                        | ((rn & 0x1f) << 5)
700                        | ((rd & 0x1f) << 0);
701                    self.buffer.put4(val);
702                    return;
703                }
704            }
705
706            Encoding::FpFpImmShiftl8 => {
707                if isign3 == enc_ops3!(Reg, Reg, Imm) {
708                    let rd = ops[0].id();
709                    let rn = ops[1].id();
710                    let imm = ops[2].as_::<Imm>().value() as i32 as u32;
711
712                    let val = (info.val ^ imm << 16)
713                        | ((0 & 0xf) << 19)
714                        | ((0 & 0x7) << 16)
715                        | ((rn & 0x1f) << 5)
716                        | ((rd & 0x1f) << 0);
717
718                    self.buffer.put4(val);
719                    return;
720                }
721            }
722
723            Encoding::FpFpImmShiftr8 => {
724                if isign3 == enc_ops3!(Reg, Reg, Imm) {
725                    let rd = ops[0].id();
726                    let rn = ops[1].id();
727                    let imm = ops[2].as_::<Imm>().value() as u32;
728
729                    let val = (info.val ^ 8u32.wrapping_sub(imm << 16))
730                        | ((0 & 0xf) << 19)
731                        | ((0 & 0x7) << 16)
732                        | ((rn & 0x1f) << 5)
733                        | ((rd & 0) << 0);
734                    self.buffer.put4(val);
735                    return;
736                }
737            }
738
739            Encoding::FpFpImmShiftr16 => {
740                if isign3 == enc_ops3!(Reg, Reg, Imm) {
741                    let rd = ops[0].id();
742                    let rn = ops[1].id();
743                    let imm = ops[2].as_::<Imm>().value() as u32;
744
745                    let val = (info.val ^ 16u32.wrapping_sub(imm << 16))
746                        | ((0 & 0xf) << 19)
747                        | ((0 & 0x7) << 16)
748                        | ((rn & 0x1f) << 5)
749                        | ((rd & 0) << 0);
750                    self.buffer.put4(val);
751                    return;
752                }
753            }
754
755            Encoding::FpFpImmShiftr32 => {
756                if isign3 == enc_ops3!(Reg, Reg, Imm) {
757                    let rd = ops[0].id();
758                    let rn = ops[1].id();
759                    let imm = ops[2].as_::<Imm>().value() as u32;
760
761                    let val = (info.val ^ 32u32.wrapping_sub(imm << 16))
762                        | ((0 & 0xf) << 19)
763                        | ((0 & 0x7) << 16)
764                        | ((rn & 0x1f) << 5)
765                        | ((rd & 0) << 0);
766                    self.buffer.put4(val);
767                    return;
768                }
769            }
770
771            Encoding::FpFpImmShiftr64 => {
772                if isign3 == enc_ops3!(Reg, Reg, Imm) {
773                    let rd = ops[0].id();
774                    let rn = ops[1].id();
775                    let imm = ops[2].as_::<Imm>().value() as u32;
776
777                    let val = (info.val ^ 64u32.wrapping_sub(imm << 16))
778                        | ((0 & 0xf) << 19)
779                        | ((0 & 0x7) << 16)
780                        | ((rn & 0x1f) << 5)
781                        | ((rd & 0) << 0);
782                    self.buffer.put4(val);
783                    return;
784                }
785            }
786
787            Encoding::FpFpImmVIdx0_1 => {
788                if isign3 == enc_ops3!(Reg, Reg, Imm) {
789                    let rd = ops[0].id();
790                    let rn = ops[1].id();
791                    let imm5 = ops[2].as_::<Imm>().value() as u32;
792
793                    let val = info.val
794                        | (((imm5 << (0 + 1)) & 0x1f) << 16)
795                        | ((rn & 0x1f) << 5)
796                        | ((rd & 0x1f) << 0);
797                    self.buffer.put4(val);
798                    return;
799                }
800            }
801
802            Encoding::FpFpImmVIdx1_1 => {
803                if isign3 == enc_ops3!(Reg, Reg, Imm) {
804                    let rd = ops[0].id();
805                    let rn = ops[1].id();
806                    let imm5 = ops[2].as_::<Imm>().value() as u32;
807
808                    let val = info.val
809                        | (((imm5 << (1 + 1)) & 0x1f) << 16)
810                        | ((rn & 0x1f) << 5)
811                        | ((rd & 0x1f) << 0);
812                    self.buffer.put4(val);
813                    return;
814                }
815            }
816
817            Encoding::FpFpImmVIdx2_1 => {
818                if isign3 == enc_ops3!(Reg, Reg, Imm) {
819                    let rd = ops[0].id();
820                    let rn = ops[1].id();
821                    let imm5 = ops[2].as_::<Imm>().value() as u32;
822
823                    let val = info.val
824                        | (((imm5 << (2 + 1)) & 0x1f) << 16)
825                        | ((rn & 0x1f) << 5)
826                        | ((rd & 0x1f) << 0);
827                    self.buffer.put4(val);
828                    return;
829                }
830            }
831            Encoding::FpFpImmVIdx3_1 => {
832                if isign3 == enc_ops3!(Reg, Reg, Imm) {
833                    let rd = ops[0].id();
834                    let rn = ops[1].id();
835                    let imm5 = ops[2].as_::<Imm>().value() as u32;
836
837                    let val = info.val
838                        | (((imm5 << (3 + 1)) & 0x1f) << 16)
839                        | ((rn & 0x1f) << 5)
840                        | ((rd & 0x1f) << 0);
841                    self.buffer.put4(val);
842                    return;
843                }
844            }
845
846            Encoding::FpGpFcvtFixScale => {
847                if isign3 == enc_ops3!(Reg, Reg, Imm) {
848                    let rd = ops[0].id();
849                    let rn = ops[1].id();
850                    let fbits = ops[2].as_::<Imm>().value() as u32;
851                    let val = info.val
852                        | (((64 - fbits) & 0x3f) << 10)
853                        | ((rn & 0x1f) << 5)
854                        | ((rd & 0x1f) << 0);
855                    self.buffer.put4(val);
856                    return;
857                }
858            }
859
860            Encoding::FpGpGp => {
861                if isign3 == enc_ops3!(Reg, Reg, Reg) {
862                    let rt = ops[0].id();
863                    let rn = ops[1].id();
864                    let rm = ops[2].id();
865
866                    let val =
867                        info.val | ((rm & 0x1f) << 16) | ((rn & 0x1f) << 5) | ((rt & 0x1f) << 0);
868                    self.buffer.put4(val);
869                    return;
870                }
871            }
872
873            Encoding::FpGpGpBool => {
874                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
875                    let rt = ops[0].id();
876                    let rn = ops[1].id();
877                    let rm = ops[2].id();
878                    let sc = ops[3].as_::<Imm>().value() as u32;
879
880                    let val = info.val
881                        | ((rm & 0x1f) << 16)
882                        | ((sc & 0x1) << 12)
883                        | ((rn & 0x1f) << 5)
884                        | ((rt & 0x1f) << 0);
885                    self.buffer.put4(val);
886                    return;
887                }
888            }
889
890            Encoding::FpGpSImm9_0 => {
891                if isign3 == enc_ops3!(Reg, Reg, Imm) {
892                    let rt = ops[0].id();
893                    let rn = ops[1].id();
894                    let imm9 = ops[2].as_::<Imm>().value() as i32 as u32;
895                    let val = info.val
896                        | (((imm9 / (1 << 0)) & 0x1ff) << 12)
897                        | ((rn & 0x1f) << 5)
898                        | ((rt & 0x1f) << 0);
899                    self.buffer.put4(val);
900                    return;
901                }
902            }
903
904            Encoding::FpGpUImm12_0 => {
905                if isign3 == enc_ops3!(Reg, Reg, Imm) {
906                    let rt = ops[0].id();
907                    let rn = ops[1].id();
908                    let imm12 = ops[2].as_::<Imm>().value() as i32 as u32;
909                    let val = info.val
910                        | (((imm12 >> 0) & 0xfff) << 10)
911                        | ((rn & 0x1f) << 5)
912                        | ((rt & 0x1f) << 0);
913                    self.buffer.put4(val);
914                    return;
915                }
916            }
917
918            Encoding::FpGpUImm12_1 => {
919                if isign3 == enc_ops3!(Reg, Reg, Imm) {
920                    let rt = ops[0].id();
921                    let rn = ops[1].id();
922                    let imm12 = ops[2].as_::<Imm>().value() as i32 as u32;
923                    let val = info.val
924                        | (((imm12 >> 1) & 0xfff) << 10)
925                        | ((rn & 0x1f) << 5)
926                        | ((rt & 0x1f) << 0);
927                    self.buffer.put4(val);
928                    return;
929                }
930            }
931
932            Encoding::FpGpUImm12_2 => {
933                if isign3 == enc_ops3!(Reg, Reg, Imm) {
934                    let rt = ops[0].id();
935                    let rn = ops[1].id();
936                    let imm12 = ops[2].as_::<Imm>().value() as i32 as u32;
937                    let val = info.val
938                        | (((imm12 >> 2) & 0xfff) << 10)
939                        | ((rn & 0x1f) << 5)
940                        | ((rt & 0x1f) << 0);
941                    self.buffer.put4(val);
942                    return;
943                }
944            }
945
946            Encoding::FpGpUImm12_3 => {
947                if isign3 == enc_ops3!(Reg, Reg, Imm) {
948                    let rt = ops[0].id();
949                    let rn = ops[1].id();
950                    let imm12 = ops[2].as_::<Imm>().value() as i32 as u32;
951                    let val = info.val
952                        | (((imm12 >> 3) & 0xfff) << 10)
953                        | ((rn & 0x1f) << 5)
954                        | ((rt & 0x1f) << 0);
955                    self.buffer.put4(val);
956                    return;
957                }
958            }
959
960            Encoding::FpGpUImm12_4 => {
961                if isign3 == enc_ops3!(Reg, Reg, Imm) {
962                    let rt = ops[0].id();
963                    let rn = ops[1].id();
964                    let imm12 = ops[2].as_::<Imm>().value() as i32 as u32;
965                    let val = info.val
966                        | (((imm12 >> 4) & 0xfff) << 10)
967                        | ((rn & 0x1f) << 5)
968                        | ((rt & 0x1f) << 0);
969                    self.buffer.put4(val);
970                    return;
971                }
972            }
973
974            Encoding::FpGpZero => {
975                if isign3 == enc_ops2!(Reg, Reg) {
976                    let rt = ops[0].id();
977                    let rn = ops[1].id();
978
979                    let val =
980                        info.val | (((31) & 0x1f) << 16) | ((rn & 0x1f) << 5) | ((rt & 0x1f) << 0);
981
982                    self.buffer.put4(val);
983                    return;
984                }
985            }
986
987            Encoding::FpImmFMov32 => {
988                if isign3 == enc_ops2!(Reg, Imm) {
989                    let rd = ops[0].id();
990                    let imm = ops[1].as_::<Imm>().value_f32();
991                    let val = info.val | ((imm_fmov32(imm) & 0xff) << 13) | ((rd & 0x1f) << 0);
992                    self.buffer.put4(val);
993                    return;
994                }
995            }
996
997            Encoding::FpImmFMov64 => {
998                if isign3 == enc_ops2!(Reg, Imm) {
999                    let rd = ops[0].id();
1000                    let imm = ops[1].as_::<Imm>().value_f64();
1001                    let val =
1002                        info.val | (((imm_fmov64(imm) & 0xff) as u32) << 13) | ((rd & 0x1f) << 0);
1003                    self.buffer.put4(val);
1004                    return;
1005                }
1006            }
1007
1008            Encoding::FpImmSIMD8Fmov => {
1009                if isign3 == enc_ops2!(Reg, Imm) {
1010                    let rd = ops[0].id();
1011                    let imm = ops[1].as_::<Imm>().value_f32();
1012                    let val = info.val
1013                        | (((imm_fmov32(imm) >> 5) & 0x7) << 16)
1014                        | (((imm_fmov32(imm) & 0x1f) & 0x1f) << 5)
1015                        | ((rd & 0x1f) << 0);
1016                    self.buffer.put4(val);
1017                    return;
1018                }
1019            }
1020
1021            Encoding::FpImmSIMD8Lsl => {
1022                if isign3 == enc_ops3!(Reg, Imm, Imm) {
1023                    let rd = ops[0].id();
1024                    let imm = ops[1].as_::<Imm>().value() as u32;
1025                    let lsl = ops[2].as_::<Imm>().value() as u32;
1026
1027                    let val = info.val
1028                        | (((imm >> 5) & 0x7) << 16)
1029                        | (((lsl >> 2 | 1) & 0x1f) << 12)
1030                        | (((imm & 0x1f) & 0x1f) << 5)
1031                        | ((rd & 0x1f) << 0);
1032                    self.buffer.put4(val);
1033                    return;
1034                }
1035            }
1036
1037            Encoding::FpImmSIMD8Movi => {
1038                if isign3 == enc_ops2!(Reg, Imm) {
1039                    let rd = ops[0].id();
1040                    let imm64 = ops[1].as_::<Imm>().value() as u64;
1041
1042                    let val = (info.val ^ imm_simdmovi(imm64))
1043                        | ((0 & 0x1) << 29)
1044                        | ((0 & 0x7) << 16)
1045                        | ((0 & 0xf) << 12)
1046                        | ((0 & 0x1f) << 5)
1047                        | ((rd & 0x1f) << 0);
1048
1049                    self.buffer.put4(val);
1050                    return;
1051                }
1052            }
1053
1054            Encoding::FpImmVIdx0_1FpImmVIdx0_0 => {
1055                if isign4 == enc_ops4!(Reg, Imm, Reg, Imm) {
1056                    let rd = ops[0].id();
1057                    let imm5 = ops[1].as_::<Imm>().value() as u32;
1058                    let rn = ops[2].id();
1059                    let imm4 = ops[3].as_::<Imm>().value() as u32;
1060
1061                    let val = info.val
1062                        | (((imm5 << (0 + 1)) & 0x1f) << 16)
1063                        | (((imm4 << (0 + 0)) & 0xf) << 11)
1064                        | ((rn & 0x1f) << 5)
1065                        | ((rd & 0x1f) << 0);
1066                    self.buffer.put4(val);
1067                    return;
1068                }
1069            }
1070
1071            Encoding::FpImmVIdx0_1Gp => {
1072                if enc_ops3!(Reg, Imm, Reg) == isign3 {
1073                    let rd = ops[0].id();
1074                    let imm5 = ops[1].as_::<Imm>().value() as u32;
1075                    let rn = ops[2].id();
1076
1077                    let val = info.val
1078                        | (((imm5 << (0 + 1)) & 0x1f) << 16)
1079                        | ((rn & 0x1f) << 5)
1080                        | ((rd & 0x1f) << 0);
1081                    self.buffer.put4(val);
1082                    return;
1083                }
1084            }
1085
1086            Encoding::FpImmVIdx1_1FpImmVIdx1_0 => {
1087                if isign4 == enc_ops4!(Reg, Imm, Reg, Imm) {
1088                    let rd = ops[0].id();
1089                    let imm5 = ops[1].as_::<Imm>().value() as u32;
1090                    let rn = ops[2].id();
1091                    let imm4 = ops[3].as_::<Imm>().value() as u32;
1092
1093                    let val = info.val
1094                        | (((imm5 << (1 + 1)) & 0x1f) << 16)
1095                        | (((imm4 << (0 + 0)) & 0xf) << 11)
1096                        | ((rn & 0x1f) << 5)
1097                        | ((rd & 0x1f) << 0);
1098                    self.buffer.put4(val);
1099                    return;
1100                }
1101            }
1102
1103            Encoding::FpImmVIdx1_1Gp => {
1104                if enc_ops3!(Reg, Imm, Reg) == isign3 {
1105                    let rd = ops[0].id();
1106                    let imm5 = ops[1].as_::<Imm>().value() as u32;
1107                    let rn = ops[2].id();
1108
1109                    let val = info.val
1110                        | (((imm5 << (1 + 1)) & 0x1f) << 16)
1111                        | ((rn & 0x1f) << 5)
1112                        | ((rd & 0x1f) << 0);
1113                    self.buffer.put4(val);
1114                    return;
1115                }
1116            }
1117
1118            Encoding::FpImmVIdx2_1FpImmVIdx2_0 => {
1119                if isign4 == enc_ops4!(Reg, Imm, Reg, Imm) {
1120                    let rd = ops[0].id();
1121                    let imm5 = ops[1].as_::<Imm>().value() as u32;
1122                    let rn = ops[2].id();
1123                    let imm4 = ops[3].as_::<Imm>().value() as u32;
1124
1125                    let val = info.val
1126                        | (((imm5 << (2 + 1)) & 0x1f) << 16)
1127                        | (((imm4 << (2 + 0)) & 0xf) << 11)
1128                        | ((rn & 0x1f) << 5)
1129                        | ((rd & 0x1f) << 0);
1130                    self.buffer.put4(val);
1131                    return;
1132                }
1133            }
1134
1135            Encoding::FpImmVIdx2_1Gp => {
1136                if enc_ops3!(Reg, Imm, Reg) == isign3 {
1137                    let rd = ops[0].id();
1138                    let imm5 = ops[1].as_::<Imm>().value() as u32;
1139                    let rn = ops[2].id();
1140
1141                    let val = info.val
1142                        | (((imm5 << (2 + 1)) & 0x1f) << 16)
1143                        | ((rn & 0x1f) << 5)
1144                        | ((rd & 0x1f) << 0);
1145                    self.buffer.put4(val);
1146                    return;
1147                }
1148            }
1149
1150            Encoding::FpImmVIdx3_1FpImmVIdx3_0 => {
1151                if isign4 == enc_ops4!(Reg, Imm, Reg, Imm) {
1152                    let rd = ops[0].id();
1153                    let imm5 = ops[1].as_::<Imm>().value() as u32;
1154                    let rn = ops[2].id();
1155                    let imm4 = ops[3].as_::<Imm>().value() as u32;
1156
1157                    let val = info.val
1158                        | (((imm5 << (3 + 1)) & 0x1f) << 16)
1159                        | (((imm4 << (3 + 0)) & 0xf) << 11)
1160                        | ((rn & 0x1f) << 5)
1161                        | ((rd & 0x1f) << 0);
1162                    self.buffer.put4(val);
1163                    return;
1164                }
1165            }
1166
1167            Encoding::FpImmVIdx3_1Gp => {
1168                if enc_ops3!(Reg, Imm, Reg) == isign3 {
1169                    let rd = ops[0].id();
1170                    let imm5 = ops[1].as_::<Imm>().value() as u32;
1171                    let rn = ops[2].id();
1172
1173                    let val = info.val
1174                        | (((imm5 << (3 + 1)) & 0x1f) << 16)
1175                        | ((rn & 0x1f) << 5)
1176                        | ((rd & 0x1f) << 0);
1177                    self.buffer.put4(val);
1178                    return;
1179                }
1180            }
1181
1182            Encoding::FpMemSIMDIdx0Gp => {
1183                if isign3 == enc_ops3!(Reg, Imm, Reg) {
1184                    let rt = ops[0].id();
1185                    let elemidx = ops[1].as_::<Imm>().value() as usize as u32;
1186                    let rn = ops[2].id();
1187
1188                    let val = info.val
1189                        | ((((elemidx << 0) >> 3) & 0x1) << 30)
1190                        | ((((elemidx << 0) >> 2) & 0x1) << 12)
1191                        | (((elemidx << 0) & 0x3) << 10)
1192                        | ((rn & 0x1f) << 5)
1193                        | ((rt & 0x1f) << 0);
1194                    self.buffer.put4(val);
1195                    return;
1196                }
1197            }
1198
1199            Encoding::FpMemSIMDIdx0GpGp => {
1200                if isign4 == enc_ops4!(Reg, Imm, Reg, Reg) {
1201                    let rt = ops[0].id();
1202                    let elemidx = ops[1].as_::<Imm>().value() as u32;
1203                    let rn = ops[2].id();
1204                    let rm = ops[3].id();
1205
1206                    let val = info.val
1207                        | ((((elemidx << 0) >> 3) & 0x1) << 30)
1208                        | ((rm & 0x1f) << 16)
1209                        | ((((elemidx << 0) >> 2) & 0x1) << 12)
1210                        | (((elemidx << 0) & 0x3) << 10)
1211                        | ((rn & 0x1f) << 5)
1212                        | ((rt & 0x1f) << 0);
1213                    self.buffer.put4(val);
1214                    return;
1215                }
1216            }
1217
1218            Encoding::FpMemSIMDIdx0GpZero => {
1219                if isign3 == enc_ops3!(Reg, Imm, Reg) {
1220                    let rt = ops[0].id();
1221                    let elemidx = ops[1].as_::<Imm>().value() as u32;
1222                    let rn = ops[2].id();
1223
1224                    let val = info.val
1225                        | ((((elemidx << 0) >> 3) & 0x1) << 30)
1226                        | (((31) & 0x1f) << 16)
1227                        | ((((elemidx << 0) >> 2) & 0x1) << 12)
1228                        | (((elemidx << 0) & 0x3) << 10)
1229                        | ((rn & 0x1f) << 5)
1230                        | ((rt & 0x1f) << 0);
1231                    self.buffer.put4(val);
1232                    return;
1233                }
1234            }
1235
1236            Encoding::FpMemSIMDIdx1GpGp => {
1237                if isign4 == enc_ops4!(Reg, Imm, Reg, Reg) {
1238                    let rt = ops[0].id();
1239                    let elemidx = ops[1].as_::<Imm>().value() as u32;
1240                    let rn = ops[2].id();
1241                    let rm = ops[3].id();
1242
1243                    let val = info.val
1244                        | ((((elemidx << 1) >> 3) & 0x1) << 30)
1245                        | ((rm & 0x1f) << 16)
1246                        | ((((elemidx << 1) >> 2) & 0x1) << 12)
1247                        | (((elemidx << 1) & 0x3) << 10)
1248                        | ((rn & 0x1f) << 5)
1249                        | ((rt & 0x1f) << 0);
1250                    self.buffer.put4(val);
1251                    return;
1252                }
1253            }
1254
1255            Encoding::FpMemSIMDIdx1GpZero => {
1256                if isign3 == enc_ops3!(Reg, Imm, Reg) {
1257                    let rt = ops[0].id();
1258                    let elemidx = ops[1].as_::<Imm>().value() as u32;
1259                    let rn = ops[2].id();
1260
1261                    let val = info.val
1262                        | ((((elemidx << 1) >> 3) & 0x1) << 30)
1263                        | (((31) & 0x1f) << 16)
1264                        | ((((elemidx << 1) >> 2) & 0x1) << 12)
1265                        | (((elemidx << 1) & 0x3) << 10)
1266                        | ((rn & 0x1f) << 5)
1267                        | ((rt & 0x1f) << 0);
1268                    self.buffer.put4(val);
1269                    return;
1270                }
1271            }
1272
1273            Encoding::FpMemSIMDIdx2Gp => {
1274                if isign4 == enc_ops4!(Reg, Imm, Reg, Reg) {
1275                    let rt = ops[0].id();
1276                    let elemidx = ops[1].as_::<Imm>().value() as u32;
1277                    let rn = ops[1].id();
1278                    let rm = ops[2].id();
1279
1280                    let val = info.val
1281                        | ((((elemidx << 2) >> 3) & 0x1) << 30)
1282                        | ((rm & 0x1f) << 16)
1283                        | ((((elemidx << 2) >> 2) & 0x1) << 12)
1284                        | (((elemidx << 2) & 0x3) << 10)
1285                        | ((rn & 0x1f) << 5)
1286                        | ((rt & 0x1f) << 0);
1287                    self.buffer.put4(val);
1288                    return;
1289                }
1290            }
1291
1292            Encoding::FpMemSIMDIdx2GpGp => {
1293                if isign4 == enc_ops4!(Reg, Imm, Reg, Reg) {
1294                    let rt = ops[0].id();
1295                    let elemidx = ops[1].as_::<Imm>().value() as u32;
1296                    let rn = ops[2].id();
1297                    let rm = ops[3].id();
1298
1299                    let val = info.val
1300                        | ((((elemidx << 2) >> 3) & 0x1) << 30)
1301                        | ((rm & 0x1f) << 16)
1302                        | ((((elemidx << 2) >> 2) & 0x1) << 12)
1303                        | (((elemidx << 2) & 0x3) << 10)
1304                        | ((rn & 0x1f) << 5)
1305                        | ((rt & 0x1f) << 0);
1306                    self.buffer.put4(val);
1307                    return;
1308                }
1309            }
1310
1311            Encoding::FpMemSIMDIdx2GpZero => {
1312                if isign3 == enc_ops3!(Reg, Imm, Reg) {
1313                    let rt = ops[0].id();
1314                    let elemidx = ops[1].as_::<Imm>().value() as u32;
1315                    let rn = ops[2].id();
1316
1317                    let val = info.val
1318                        | ((((elemidx << 2) >> 3) & 0x1) << 30)
1319                        | (((31) & 0x1f) << 16)
1320                        | ((((elemidx << 2) >> 2) & 0x1) << 12)
1321                        | (((elemidx << 2) & 0x3) << 10)
1322                        | ((rn & 0x1f) << 5)
1323                        | ((rt & 0x1f) << 0);
1324                    self.buffer.put4(val);
1325                    return;
1326                }
1327            }
1328
1329            Encoding::FpMemSIMDIdx3Gp => {
1330                if isign4 == enc_ops4!(Reg, Imm, Reg, Reg) {
1331                    let rt = ops[0].id();
1332                    let elemidx = ops[1].as_::<Imm>().value() as u32;
1333                    let rn = ops[1].id();
1334                    let rm = ops[2].id();
1335
1336                    let val = info.val
1337                        | ((((elemidx << 3) >> 3) & 0x1) << 30)
1338                        | ((rm & 0x1f) << 16)
1339                        | ((((elemidx << 3) >> 2) & 0x1) << 12)
1340                        | (((elemidx << 3) & 0x3) << 10)
1341                        | ((rn & 0x1f) << 5)
1342                        | ((rt & 0x1f) << 0);
1343                    self.buffer.put4(val);
1344                    return;
1345                }
1346            }
1347
1348            Encoding::FpMemSIMDIdx3GpGp => {
1349                if isign4 == enc_ops4!(Reg, Imm, Reg, Reg) {
1350                    let rt = ops[0].id();
1351                    let elemidx = ops[1].as_::<Imm>().value() as u32;
1352                    let rn = ops[2].id();
1353                    let rm = ops[3].id();
1354
1355                    let val = info.val
1356                        | ((((elemidx << 3) >> 3) & 0x1) << 30)
1357                        | ((rm & 0x1f) << 16)
1358                        | ((((elemidx << 3) >> 2) & 0x1) << 12)
1359                        | (((elemidx << 3) & 0x3) << 10)
1360                        | ((rn & 0x1f) << 5)
1361                        | ((rt & 0x1f) << 0);
1362                    self.buffer.put4(val);
1363                    return;
1364                }
1365            }
1366
1367            Encoding::FpMemSIMDIdx3GpZero => {
1368                if isign3 == enc_ops3!(Reg, Imm, Reg) {
1369                    let rt = ops[0].id();
1370                    let elemidx = ops[1].as_::<Imm>().value() as u32;
1371                    let rn = ops[2].id();
1372
1373                    let val = info.val
1374                        | ((((elemidx << 3) >> 3) & 0x1) << 30)
1375                        | (((31) & 0x1f) << 16)
1376                        | ((((elemidx << 3) >> 2) & 0x1) << 12)
1377                        | (((elemidx << 3) & 0x3) << 10)
1378                        | ((rn & 0x1f) << 5)
1379                        | ((rt & 0x1f) << 0);
1380                    self.buffer.put4(val);
1381                    return;
1382                }
1383            }
1384
1385            Encoding::FpRelAddr19 => {
1386                if isign3 == enc_ops2!(Reg, Imm) {
1387                    let rt = ops[0].id();
1388                    let imm19 = ops[1].as_::<Imm>().value() as isize as i32 as u32;
1389
1390                    let val = info.val | ((imm19 & 0x7ffff) << 5) | ((rt & 0x1f) << 0);
1391
1392                    self.buffer.put4(val);
1393                    return;
1394                } else if isign3 == enc_ops2!(Reg, Label) {
1395                    let rt = ops[0].id();
1396
1397                    self.use_label(ops[1], LabelUse::A64Branch19);
1398
1399                    let val = info.val | ((0 & 0x7ffff) << 5) | ((rt & 0x1f) << 0);
1400
1401                    self.buffer.put4(val);
1402                    return;
1403                }
1404            }
1405
1406            Encoding::GpFp => {
1407                if isign3 == enc_ops2!(Reg, Reg) {
1408                    let rd = ops[0].id();
1409                    let rn = ops[1].id();
1410
1411                    let val = info.val | ((rn & 0x1f) << 5) | ((rd & 0x1f) << 0);
1412                    self.buffer.put4(val);
1413                    return;
1414                }
1415            }
1416
1417            Encoding::GpFpFcvtFixScale => {
1418                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1419                    let rd = ops[0].id();
1420                    let rn = ops[1].id();
1421                    let fbits = ops[2].as_::<Imm>().value() as u32;
1422
1423                    let val = info.val
1424                        | (((64 - fbits) & &0x3f) << 10)
1425                        | ((rn & 0x1f) << 5)
1426                        | ((rd & 0x1f) << 0);
1427                    self.buffer.put4(val);
1428                    return;
1429                }
1430            }
1431
1432            Encoding::GpFpImmVIdx0_1 => {
1433                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1434                    let rd = ops[0].id();
1435                    let rn = ops[1].id();
1436                    let imm5 = ops[2].as_::<Imm>().value() as u32;
1437                    let val = info.val
1438                        | (((imm5 << (0 + 1)) & 0x1f) << 16)
1439                        | ((rn & 0x1f) << 5)
1440                        | ((rd & 0x1f) << 0);
1441                    self.buffer.put4(val);
1442                    return;
1443                }
1444            }
1445
1446            Encoding::GpFpImmVIdx1_1 => {
1447                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1448                    let rd = ops[0].id();
1449                    let rn = ops[1].id();
1450                    let imm5 = ops[2].as_::<Imm>().value() as u32;
1451                    let val = info.val
1452                        | (((imm5 << (1 + 1)) & 0x1f) << 16)
1453                        | ((rn & 0x1f) << 5)
1454                        | ((rd & 0x1f) << 0);
1455                    self.buffer.put4(val);
1456                    return;
1457                }
1458            }
1459
1460            Encoding::GpFpImmVIdx2_1 => {
1461                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1462                    let rd = ops[0].id();
1463                    let rn = ops[1].id();
1464                    let imm5 = ops[2].as_::<Imm>().value() as u32;
1465                    let val = info.val
1466                        | (((imm5 << (2 + 1)) & 0x1f) << 16)
1467                        | ((rn & 0x1f) << 5)
1468                        | ((rd & 0x1f) << 0);
1469                    self.buffer.put4(val);
1470                    return;
1471                }
1472            }
1473
1474            Encoding::GpFpImmVIdx3_1 => {
1475                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1476                    let rd = ops[0].id();
1477                    let rn = ops[1].id();
1478                    let imm5 = ops[2].as_::<Imm>().value() as u32;
1479                    let val = info.val
1480                        | (((imm5 << (3 + 1)) & 0x1f) << 16)
1481                        | ((rn & 0x1f) << 5)
1482                        | ((rd & 0x1f) << 0);
1483                    self.buffer.put4(val);
1484                    return;
1485                }
1486            }
1487
1488            Encoding::GpGpConst0Const0 => {
1489                if isign3 == enc_ops2!(Reg, Reg) {
1490                    let rd = ops[0].id();
1491                    let rn = ops[1].id();
1492
1493                    let val = info.val
1494                        | ((0 & 0x3) << 22)
1495                        | ((0 & 0xfff) << 10)
1496                        | ((rn & 0x1f) << 5)
1497                        | ((rd & 0x1f) << 0);
1498                    self.buffer.put4(val);
1499                    return;
1500                }
1501            }
1502
1503            Encoding::GpGpConst0Const15 => {
1504                if isign3 == enc_ops2!(Reg, Reg) {
1505                    let rd = ops[0].id();
1506                    let rn = ops[1].id();
1507
1508                    let val = info.val
1509                        | ((0 & 0x3) << 16)
1510                        | ((15 & 0x3f) << 10)
1511                        | ((rn & 0x1f) << 5)
1512                        | ((rd & 0x1f) << 0);
1513                    self.buffer.put4(val);
1514                    return;
1515                }
1516            }
1517
1518            Encoding::GpGpConst0Const31 => {
1519                if isign3 == enc_ops2!(Reg, Reg) {
1520                    let rd = ops[0].id();
1521                    let rn = ops[1].id();
1522
1523                    let val = info.val
1524                        | ((0 & 0x3) << 16)
1525                        | ((31 & 0x3f) << 10)
1526                        | ((rn & 0x1f) << 5)
1527                        | ((rd & 0x1f) << 0);
1528                    self.buffer.put4(val);
1529                    return;
1530                }
1531            }
1532            Encoding::GpGpConst0Const7 => {
1533                if isign3 == enc_ops2!(Reg, Reg) {
1534                    let rd = ops[0].id();
1535                    let rn = ops[1].id();
1536
1537                    let val = info.val
1538                        | ((0 & 0x3) << 16)
1539                        | ((7 & 0x3f) << 10)
1540                        | ((rn & 0x1f) << 5)
1541                        | ((rd & 0x1f) << 0);
1542                    self.buffer.put4(val);
1543                    return;
1544                }
1545            }
1546
1547            Encoding::GpGpGpBool => {
1548                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
1549                    let rt = ops[0].id();
1550                    let rn = ops[1].id();
1551                    let rm = ops[2].id();
1552                    let sc = ops[3].as_::<Imm>().value() as u32;
1553
1554                    let val = info.val
1555                        | ((rm & 0x1f) << 16)
1556                        | ((sc & 0x1) << 12)
1557                        | ((rn & 0x1f) << 5)
1558                        | ((rt & 0x1f) << 0);
1559                    self.buffer.put4(val);
1560                    return;
1561                }
1562            }
1563
1564            Encoding::GpGpGpCond => {
1565                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
1566                    let rt = ops[0].id();
1567                    let rn = ops[1].id();
1568                    let rm = ops[2].id();
1569                    let sc = ops[3].as_::<Imm>().value() as u32;
1570
1571                    let val = info.val
1572                        | ((rm & 0x1f) << 16)
1573                        | ((sc & 0xf) << 12)
1574                        | ((rn & 0x1f) << 5)
1575                        | ((rt & 0x1f) << 0);
1576                    self.buffer.put4(val);
1577                    return;
1578                }
1579            }
1580
1581            Encoding::GpGpGpGp => {
1582                if isign4 == enc_ops4!(Reg, Reg, Reg, Reg) {
1583                    let rs = ops[0].id();
1584                    let rt = ops[1].id();
1585                    let rt2 = ops[2].id();
1586                    let rn = ops[3].id();
1587
1588                    let val = info.val
1589                        | ((rs & 0x1f) << 16)
1590                        | ((rt2 & 0x1f) << 10)
1591                        | ((rn & 0x1f) << 5)
1592                        | ((rt & 0x1f) << 0);
1593                    self.buffer.put4(val);
1594                    return;
1595                }
1596            }
1597
1598            Encoding::GpGpGpImm => {
1599                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
1600                    let rd = ops[0].id();
1601                    let rn = ops[1].id();
1602                    let rm = ops[2].id();
1603                    let imm3 = ops[3].as_::<Imm>().value() as i32 as u32;
1604
1605                    self.buffer.put4(
1606                        info.val
1607                            | ((rm & 0x1f) << 16)
1608                            | ((imm3 & 0x7) << 10)
1609                            | ((rn & 0x1f) << 5)
1610                            | ((rd & 0x1f) << 0),
1611                    );
1612                    return;
1613                }
1614            }
1615
1616            Encoding::GpGpGpSImm7_2 => {
1617                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
1618                    let rt = ops[0].id();
1619                    let rt2 = ops[1].id();
1620                    let rn = ops[2].id();
1621                    let imm7 = ops[3].as_::<Imm>().value() as i32 as u32;
1622
1623                    let val = info.val
1624                        | (((imm7 / (1 << 2)) & 0x7f) << 15)
1625                        | ((rt2 & 0x1f) << 10)
1626                        | ((rn & 0x1f) << 5)
1627                        | ((rt & 0x1f) << 0);
1628                    self.buffer.put4(val);
1629                    return;
1630                }
1631            }
1632
1633            Encoding::GpGpGpSImm7_3 => {
1634                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
1635                    let rt = ops[0].id();
1636                    let rt2 = ops[1].id();
1637                    let rn = ops[2].id();
1638                    let imm7 = ops[3].as_::<Imm>().value() as i32 as u32;
1639
1640                    let val = info.val
1641                        | (((imm7 / (1 << 3)) & 0x7f) << 15)
1642                        | ((rt2 & 0x1f) << 10)
1643                        | ((rn & 0x1f) << 5)
1644                        | ((rt & 0x1f) << 0);
1645                    self.buffer.put4(val);
1646                    return;
1647                }
1648            }
1649            Encoding::GpGpGpSImm7_4 => {
1650                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
1651                    let rt = ops[0].id();
1652                    let rt2 = ops[1].id();
1653                    let rn = ops[2].id();
1654                    let imm7 = ops[3].as_::<Imm>().value() as i32 as u32;
1655
1656                    let val = info.val
1657                        | (((imm7 / (1 << 4)) & 0x7f) << 15)
1658                        | ((rt2 & 0x1f) << 10)
1659                        | ((rn & 0x1f) << 5)
1660                        | ((rt & 0x1f) << 0);
1661                    self.buffer.put4(val);
1662                    return;
1663                }
1664            }
1665
1666            Encoding::GpGpGpZero => {
1667                if isign3 == enc_ops3!(Reg, Reg, Reg) {
1668                    let rd = ops[0].id();
1669                    let rn = ops[1].id();
1670                    let rm = ops[2].id();
1671
1672                    let val = info.val
1673                        | ((rm & 0x1f) << 16)
1674                        | ((31 & 0x1f) << 10)
1675                        | ((rn & 0x1f) << 5)
1676                        | ((rd & 0x1f) << 0);
1677                    self.buffer.put4(val);
1678                    return;
1679                }
1680            }
1681
1682            Encoding::GpGpImmAdd32 => {
1683                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1684                    let rd = ops[0].id();
1685                    let rn = ops[1].id();
1686                    let imm = ops[2].as_::<Imm>().value();
1687
1688                    let val = (info.val ^ imm_add(imm))
1689                        | ((0 & 0x3) << 22)
1690                        | ((0 & 0xfff) << 10)
1691                        | ((rn & 0x1f) << 5)
1692                        | ((rd & 0x1f) << 0);
1693                    self.buffer.put4(val);
1694                    return;
1695                }
1696            }
1697
1698            Encoding::GpGpImmAdd64 => {
1699                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1700                    let rd = ops[0].id();
1701                    let rn = ops[1].id();
1702                    let imm = ops[2].as_::<Imm>().value();
1703
1704                    let val = (info.val ^ imm_add(imm))
1705                        | ((0 & 0x3) << 22)
1706                        | ((0 & 0xfff) << 10)
1707                        | ((rn & 0x1f) << 5)
1708                        | ((rd & 0x1f) << 0);
1709                    self.buffer.put4(val);
1710                    return;
1711                }
1712            }
1713
1714            Encoding::GpGpImmCond => {
1715                if isign4 == enc_ops4!(Reg, Reg, Imm, Imm) {
1716                    let rn = ops[0].id();
1717                    let rm = ops[1].id();
1718                    let nzcv = ops[2].as_::<Imm>().value() as u32;
1719                    let cond = ops[3].as_::<Imm>().value() as u32;
1720
1721                    let val = info.val
1722                        | ((rm & 0x1f) << 16)
1723                        | ((cond & 0xf) << 12)
1724                        | ((rn & 0x1f) << 5)
1725                        | ((nzcv & 0xf) << 0);
1726                    self.buffer.put4(val);
1727                    return;
1728                }
1729            }
1730
1731            // rd, rn, immr
1732            Encoding::GpGpImmConst31 => {
1733                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1734                    let rd = ops[0].id();
1735                    let rn = ops[1].id();
1736                    let immr = ops[2].as_::<Imm>().value() as u32;
1737
1738                    let val = info.val
1739                        | ((immr & 0x3f) << 16)
1740                        | ((31 & 0x3f) << 10)
1741                        | ((rn & 0x1f) << 5)
1742                        | ((rd & 0x1f) << 0);
1743                    self.buffer.put4(val);
1744                    return;
1745                }
1746            }
1747
1748            Encoding::GpGpImmConst63 => {
1749                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1750                    let rd = ops[0].id();
1751                    let rn = ops[1].id();
1752                    let immr = ops[2].as_::<Imm>().value() as u32;
1753
1754                    let val = info.val
1755                        | ((immr & 0x3f) << 16)
1756                        | ((63 & 0x3f) << 10)
1757                        | ((rn & 0x1f) << 5)
1758                        | ((rd & 0x1f) << 0);
1759                    self.buffer.put4(val);
1760                    return;
1761                }
1762            }
1763
1764            // Rd, Rn, immr, imms
1765            Encoding::GpGpImmImm => {
1766                if isign4 == enc_ops4!(Reg, Reg, Imm, Imm) {
1767                    let rd = ops[0].id();
1768                    let rn = ops[1].id();
1769                    let immr = ops[2].as_::<Imm>().value() as u32;
1770                    let imms = ops[3].as_::<Imm>().value() as u32;
1771
1772                    let val = info.val
1773                        | ((immr & 0x3f) << 16)
1774                        | ((imms & 0x3f) << 10)
1775                        | ((rn & 0x1f) << 5)
1776                        | ((rd & 0x1f) << 0);
1777                    self.buffer.put4(val);
1778                    return;
1779                }
1780            }
1781
1782            // rt, rn, simm9
1783            Encoding::GpGpImmLDraut => {
1784                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1785                    let rt = ops[0].id();
1786                    let rn = ops[1].id();
1787                    let simm9 = ops[2].as_::<Imm>().value() as i32 as u32;
1788
1789                    let val = info.val
1790                        | ((((simm9 >> 12) & 1) & 0x1) << 22)
1791                        | ((((simm9 & 0xff8) >> 3) & 0x1ff) << 12)
1792                        | ((rn & 0x1f) << 5)
1793                        | ((rt & 0x1f) << 0);
1794                    self.buffer.put4(val);
1795                    return;
1796                }
1797            }
1798
1799            // rd, rn, imm
1800            Encoding::GpGpImmLogical32 => {
1801                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1802                    let rd = ops[0].id();
1803                    let rn = ops[1].id();
1804                    let imm = ops[2].as_::<Imm>().value() as u64;
1805
1806                    let val = (info.val ^ imm_logical(imm, (32 >> 6) != 0))
1807                        | ((0 & 0x3f) << 16)
1808                        | ((0 & 0x3f) << 10)
1809                        | ((rn & 0x1f) << 5)
1810                        | ((rd & 0x1f) << 0);
1811                    self.buffer.put4(val);
1812                    return;
1813                }
1814            }
1815
1816            // rd, rn, imm
1817            Encoding::GpGpImmLogical64 => {
1818                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1819                    let rd = ops[0].id();
1820                    let rn = ops[1].id();
1821                    let imm = ops[2].as_::<Imm>().value() as u64;
1822
1823                    let val = (info.val ^ imm_logical(imm, (64 >> 6) != 0))
1824                        | ((0 & 0x3f) << 16)
1825                        | ((0 & 0x3f) << 10)
1826                        | ((rn & 0x1f) << 5)
1827                        | ((rd & 0x1f) << 0);
1828                    self.buffer.put4(val);
1829                    return;
1830                }
1831            }
1832
1833            // rd, rn, cond
1834            Encoding::GpGpInvCond => {
1835                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1836                    let rd = ops[0].id();
1837                    let rn = ops[1].id();
1838                    let cond = ops[2].as_::<Imm>().value() as u32;
1839
1840                    let val = info.val
1841                        | ((rn & 0x1f) << 16)
1842                        | (((cond ^ 1) & 0xf) << 12)
1843                        | ((rn & 0x1f) << 5)
1844                        | ((rd & 0x1f) << 0);
1845                    self.buffer.put4(val);
1846                    return;
1847                }
1848            }
1849
1850            // rs, rt, rn
1851            Encoding::GpGpLs64Gp => {
1852                if isign3 == enc_ops3!(Reg, Reg, Reg) {
1853                    let rs = ops[0].id();
1854                    let rt = ops[1].id();
1855                    let rn = ops[2].id();
1856
1857                    let val =
1858                        info.val | ((rs & 0x1f) << 16) | ((rt & 0x1f) << 5) | ((rn & 0x1f) << 0);
1859                    self.buffer.put4(val);
1860                    return;
1861                }
1862            }
1863
1864            // rd, rn, imm8
1865            Encoding::GpGpSImm8_0 => {
1866                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1867                    let rd = ops[0].id();
1868                    let rn = ops[1].id();
1869                    let imm8 = ops[2].as_::<Imm>().value() as u32;
1870
1871                    let val = info.val
1872                        | (((imm8 / (1 << 0)) & 0xff) << 10)
1873                        | (((rn) & 0x1f) << 5)
1874                        | (((rd) & 0x1f) << 0);
1875                    self.buffer.put4(val);
1876                    return;
1877                }
1878            }
1879
1880            Encoding::GpGpSImm9_0 => {
1881                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1882                    let rd = ops[0].id();
1883                    let rn = ops[1].id();
1884                    let imm9 = ops[2].as_::<Imm>().value() as u32;
1885
1886                    let val = info.val
1887                        | (((imm9 / (1 << 0)) & 0x1ff) << 12)
1888                        | (((rn) & 0x1f) << 5)
1889                        | (((rd) & 0x1f) << 0);
1890                    self.buffer.put4(val);
1891                    return;
1892                }
1893            }
1894
1895            Encoding::GpGpSImm9_4 => {
1896                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1897                    let rd = ops[0].id();
1898                    let rn = ops[1].id();
1899                    let imm9 = ops[2].as_::<Imm>().value() as u32;
1900
1901                    let val = info.val
1902                        | (((imm9 / (1 << 4)) & 0x1ff) << 12)
1903                        | (((rn) & 0x1f) << 5)
1904                        | (((rd) & 0x1f) << 0);
1905                    self.buffer.put4(val);
1906                    return;
1907                }
1908            }
1909
1910            Encoding::GpGpUImm12_0 => {
1911                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1912                    let rt = ops[0].id();
1913                    let rn = ops[1].id();
1914                    let imm12 = ops[2].as_::<Imm>().value() as i32 as u32;
1915
1916                    let val = info.val
1917                        | (((imm12 >> 0) & 0xfff) << 10)
1918                        | ((rn & 0x1f) << 5)
1919                        | ((rt & 0x1f) << 0);
1920                    self.buffer.put4(val);
1921                    return;
1922                }
1923            }
1924
1925            Encoding::GpGpUImm12_1 => {
1926                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1927                    let rt = ops[0].id();
1928                    let rn = ops[1].id();
1929                    let imm12 = ops[2].as_::<Imm>().value() as i32 as u32;
1930
1931                    let val = info.val
1932                        | (((imm12 >> 1) & 0xfff) << 10)
1933                        | ((rn & 0x1f) << 5)
1934                        | ((rt & 0x1f) << 0);
1935                    self.buffer.put4(val);
1936                    return;
1937                }
1938            }
1939
1940            Encoding::GpGpUImm12_2 => {
1941                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1942                    let rt = ops[0].id();
1943                    let rn = ops[1].id();
1944                    let imm12 = ops[2].as_::<Imm>().value() as i32 as u32;
1945
1946                    let val = info.val
1947                        | (((imm12 >> 2) & 0xfff) << 10)
1948                        | ((rn & 0x1f) << 5)
1949                        | ((rt & 0x1f) << 0);
1950                    self.buffer.put4(val);
1951                    return;
1952                }
1953            }
1954
1955            Encoding::GpGpUImm12_3 => {
1956                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1957                    let rt = ops[0].id();
1958                    let rn = ops[1].id();
1959                    let imm12 = ops[2].as_::<Imm>().value() as i32 as u32;
1960
1961                    let val = info.val
1962                        | (((imm12 >> 3) & 0xfff) << 10)
1963                        | ((rn & 0x1f) << 5)
1964                        | ((rt & 0x1f) << 0);
1965                    self.buffer.put4(val);
1966                    return;
1967                }
1968            }
1969
1970            // rd, rn, uimm6, uimm4
1971            Encoding::GpGpUImm6_4UImm4_0Const0 => {
1972                if isign4 == enc_ops4!(Reg, Reg, Imm, Imm) {
1973                    let rd = ops[0].id();
1974                    let rn = ops[1].id();
1975                    let imm6 = ops[2].as_::<Imm>().value() as u32;
1976                    let imm4 = ops[3].as_::<Imm>().value() as u32;
1977
1978                    let val = info.val
1979                        | ((rn & 0x1f) << 5)
1980                        | ((rd & 0x1f) << 0)
1981                        | ((0 & 0x3) << 14)
1982                        | (((imm4 >> 0) & 0xf) << 10)
1983                        | (((imm6 >> 4) & 0x3f) << 16);
1984
1985                    self.buffer.put4(val);
1986                    return;
1987                }
1988            }
1989
1990            // rd, rn, imm8
1991            Encoding::GpGpUImm8_0 => {
1992                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1993                    let rd = ops[0].id();
1994                    let rn = ops[1].id();
1995                    let imm8 = ops[2].as_::<Imm>().value() as u32;
1996
1997                    let val = info.val
1998                        | (((imm8 >> 0) & 0xff) << 12)
1999                        | ((rn & 0x1f) << 5)
2000                        | ((rd & 0x1f) << 0);
2001                    self.buffer.put4(val);
2002                    return;
2003                }
2004            }
2005
2006            // rs, rt, rn
2007            Encoding::GpGpZeroGp => {
2008                if isign3 == enc_ops3!(Reg, Reg, Reg) {
2009                    let rs = ops[0].id();
2010                    let rn = ops[1].id();
2011                    let rt = ops[2].id();
2012
2013                    let val = info.val
2014                        | ((31 & 0x1f) << 10)
2015                        | ((rn & 0x1f) << 5)
2016                        | ((rt & 0x1f) << 0)
2017                        | ((rs & 0x1f) << 16);
2018
2019                    self.buffer.put4(val);
2020                    return;
2021                }
2022            }
2023
2024            // rd, rn, lsb, width
2025            Encoding::GpGplsbwidth => {
2026                if isign4 == enc_ops4!(Reg, Reg, Imm, Imm) {
2027                    let rd = ops[0].id();
2028                    let rn = ops[1].id();
2029                    let lsb = ops[2].as_::<Imm>().value() as u32;
2030                    let width = ops[3].as_::<Imm>().value() as u32;
2031
2032                    let val = info.val
2033                        | (((lsb + width - 1) & 0x3f) << 10)
2034                        | (((rn) & 0x1f) << 5)
2035                        | (((rd) & 0x1f) << 0);
2036                    self.buffer.put4(val);
2037                    return;
2038                }
2039            }
2040
2041            Encoding::GpGplsl32 => {
2042                if isign3 == enc_ops3!(Reg, Reg, Imm) {
2043                    let rd = ops[0].id();
2044                    let rn = ops[1].id();
2045                    let lsl32 = ops[2].as_::<Imm>().value() as u32;
2046
2047                    let val = info.val
2048                        | (((32 - 1 - lsl32) & 0x3f) << 10)
2049                        | (((rn) & 0x1f) << 5)
2050                        | (((rd) & 0x1f) << 0);
2051                    self.buffer.put4(val);
2052                    return;
2053                }
2054            }
2055
2056            Encoding::GpGplsl64 => {
2057                if isign3 == enc_ops3!(Reg, Reg, Imm) {
2058                    let rd = ops[0].id();
2059                    let rn = ops[1].id();
2060                    let lsl64 = ops[2].as_::<Imm>().value() as u32;
2061
2062                    let val = info.val
2063                        | (((64 - 1 - lsl64) & 0x3f) << 10)
2064                        | (((rn) & 0x1f) << 5)
2065                        | (((rd) & 0x1f) << 0);
2066                    self.buffer.put4(val);
2067                    return;
2068                }
2069            }
2070
2071            // rd, target
2072            Encoding::GpImmAddr => {
2073                if isign3 == enc_ops2!(Reg, Imm) {
2074                    let rd = ops[0].id();
2075                    let target = ops[1].as_::<Imm>().value() as i32 as u32;
2076
2077                    let val = info.val
2078                        | (((target & 3) & 0x3) << 29)
2079                        | (((target >> 2) & 0x7ffff) << 5)
2080                        | ((rd & 0x1f) << 0);
2081
2082                    self.buffer.put4(val);
2083                    return;
2084                } else if isign3 == enc_ops2!(Reg, Label) {
2085                    let rd = ops[0].id();
2086                    self.use_label(&ops[1], LabelUse::A64Adr21);
2087                    let val = info.val | (rd & 0x1f) << 0;
2088                    self.buffer.put4(val);
2089                    return;
2090                }
2091            }
2092
2093            Encoding::GpImmAddrP => {
2094                if isign3 == enc_ops2!(Reg, Imm) {
2095                    let rd = ops[0].id();
2096                    let target = ops[1].as_::<Imm>().value() as u64;
2097
2098                    let val = info.val
2099                        | ((((target & !0xfffu64) >> 12) as u32 & 3) << 29)
2100                        | ((((target & !0xfffu64) >> 14) as u32 & 0x7ffff) << 5)
2101                        | ((rd & 0x1f) << 0);
2102
2103                    self.buffer.put4(val);
2104                    return;
2105                } else if isign3 == enc_ops2!(Reg, Label) {
2106                    let rd = ops[0].id();
2107                    self.use_label(&ops[1], LabelUse::A64Adr21);
2108                    let val = info.val | (rd & 0x1f) << 0;
2109                    self.buffer.put4(val);
2110                    return;
2111                } else if isign3 == enc_ops2!(Reg, Sym) {
2112                    let rd = ops[0].id();
2113                    self.buffer.add_reloc(
2114                        Reloc::Aarch64AdrGotPage21,
2115                        RelocTarget::Sym(ops[1].as_::<Sym>()),
2116                        0,
2117                    );
2118                    let val = info.val | (rd & 0x1f) << 0;
2119                    self.buffer.put4(val);
2120                    return;
2121                }
2122            }
2123
2124            // rn, imm5, nzcv, cond
2125            Encoding::GpImmImmCond => {
2126                if isign4 == enc_ops4!(Reg, Imm, Imm, Imm) {
2127                    let rn = ops[0].id();
2128                    let imm5 = ops[1].as_::<Imm>().value() as u32;
2129                    let nzcv = ops[2].as_::<Imm>().value() as u32;
2130                    let cond = ops[3].as_::<Imm>().value() as u32;
2131                    let val = info.val
2132                        | ((imm5 & 0x1f) << 16)
2133                        | ((cond & 0xf) << 12)
2134                        | ((rn & 0x1f) << 5)
2135                        | ((nzcv & 0xf) << 0);
2136
2137                    self.buffer.put4(val);
2138                    return;
2139                }
2140            }
2141
2142            // rt, imm19
2143            Encoding::GpRelAddr19 => {
2144                if isign3 == enc_ops2!(Reg, Imm) {
2145                    let rt = ops[0].id();
2146                    let imm19 = ops[1].as_::<Imm>().value() as i32 as u32;
2147
2148                    let val = info.val | (((imm19 & 0x7ffff) << 5) & 0x7ffff0) | ((rt & 0x1f) << 0);
2149
2150                    self.buffer.put4(val);
2151                    return;
2152                } else if isign3 == enc_ops2!(Reg, Label) {
2153                    let rt = ops[0].id();
2154                    self.use_label(&ops[1], LabelUse::A64Ldr19);
2155                    let val = info.val | (rt & 0x1f) << 0;
2156                    self.buffer.put4(val);
2157                    return;
2158                }
2159            }
2160            // rt, bit, imm14
2161            Encoding::GpTBZRelAddr14 => {
2162                if isign3 == enc_ops3!(Reg, Imm, Label) {
2163                    let rt = ops[0].id();
2164                    let bit = ops[1].as_::<Imm>().value() as u32;
2165
2166                    self.use_label(ops[2], LabelUse::A64Branch14);
2167                    let val = info.val
2168                        | (((bit >> 5) & 0x1) << 31)
2169                        | (((bit & 0x1f) & 0x1f) << 19)
2170                        | (((0 >> 2) & 0x3fff) << 5)
2171                        | ((rt & 0x1f) << 0);
2172
2173                    self.buffer.put4(val);
2174                    return;
2175                } else if isign3 == enc_ops3!(Reg, Imm, Imm) {
2176                    let rt = ops[0].id();
2177                    let bit = ops[1].as_::<Imm>().value() as u32;
2178                    let imm14 = ops[2].as_::<Imm>();
2179
2180                    let val = info.val
2181                        | (((bit >> 5) & 0x1) << 31)
2182                        | (((bit & 0x1f) & 0x1f) << 19)
2183                        | (((imm14.value() as i32 as u32 >> 2) & 0x3fff) << 5)
2184                        | ((rt & 0x1f) << 0);
2185
2186                    self.buffer.put4(val);
2187                    return;
2188                }
2189            }
2190
2191            // rd, imm16 e.g MOVNw
2192            Encoding::GpUImm16_0 => {
2193                if isign3 == enc_ops2!(Reg, Imm) {
2194                    let rd = ops[0].id();
2195                    let imm16 = ops[1].as_::<Imm>().value() as u32;
2196
2197                    let val = info.val | (((imm16 >> 0) & 0xffff) << 5) | ((rd & 0x1f) << 0);
2198
2199                    self.buffer.put4(val);
2200                    return;
2201                }
2202            }
2203
2204            // rd, imm16, hw
2205            Encoding::GpUImm16_0Imm => {
2206                if isign3 == enc_ops3!(Reg, Imm, Imm) {
2207                    let rd = ops[0].id();
2208                    let imm16 = ops[1].as_::<Imm>().value() as u32;
2209                    let hw = ops[2].as_::<Imm>().value() as u32;
2210
2211                    let val = info.val
2212                        | (((imm16 >> 0) & 0xffff) << 5)
2213                        | (((hw >> 0) & 0x3) << 21)
2214                        | ((rd & 0x1f) << 0);
2215
2216                    self.buffer.put4(val);
2217                    return;
2218                }
2219            }
2220
2221            Encoding::GpZeroGpConst0 => {
2222                todo!()
2223            }
2224
2225            Encoding::GpConst0 => {
2226                if isign3 == enc_ops1!(Reg) {
2227                    let rn = ops[0].id();
2228                    self.buffer.put4(info.val | ((rn & 0x1f) << 5));
2229                    return;
2230                }
2231            }
2232
2233            Encoding::GpGpGp => {
2234                if isign3 == enc_ops3!(Reg, Reg, Reg) {
2235                    let rd = ops[0].id();
2236                    let rn = ops[1].id();
2237                    let rm = ops[2].id();
2238
2239                    self.buffer.put4(
2240                        info.val
2241                            | ((rm & 0x1f) << 16)
2242                            | (0 << 10)
2243                            | (rn & 0x1f) << 5
2244                            | ((rd & 0x1f) << 0),
2245                    );
2246                    return;
2247                }
2248            }
2249
2250            Encoding::GpGpGpConst0 => {
2251                if isign3 == enc_ops3!(Reg, Reg, Reg) {
2252                    let rd = ops[0].id();
2253                    let rn = ops[1].id();
2254                    let rm = ops[2].id();
2255
2256                    self.buffer.put4(
2257                        info.val
2258                            | ((rm & 0x1f) << 16)
2259                            | (0 << 10)
2260                            | (rn & 0x1f) << 5
2261                            | ((rd & 0x1f) << 0),
2262                    );
2263                    return;
2264                }
2265            }
2266
2267            _ => panic!("{:?}", info.encoding),
2268        };
2269        if err.is_none() {
2270            err = Some(AsmError::InvalidOperand);
2271        }
2272        self.last_error = err;
2273    }
2274
2275    fn emit(&mut self, opcode: i64, op0: &Operand, op1: &Operand, op2: &Operand, op3: &Operand) {
2276        let _ = opcode;
2277        let _ = op0;
2278        let _ = op1;
2279        let _ = op2;
2280        let _ = op3;
2281        todo!()
2282    }
2283}
2284
2285impl<'a> A64EmitterExplicit for Assembler<'a> {}