• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 //   * Redistributions of source code must retain the above copyright notice,
8 //     this list of conditions and the following disclaimer.
9 //   * Redistributions in binary form must reproduce the above copyright notice,
10 //     this list of conditions and the following disclaimer in the documentation
11 //     and/or other materials provided with the distribution.
12 //   * Neither the name of ARM Limited nor the names of its contributors may be
13 //     used to endorse or promote products derived from this software without
14 //     specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #include <cstdlib>
28 #include <sstream>
29 
30 #include "disasm-aarch64.h"
31 
32 namespace vixl {
33 namespace aarch64 {
34 
35 
Disassembler()36 Disassembler::Disassembler() {
37   buffer_size_ = 256;
38   buffer_ = reinterpret_cast<char *>(malloc(buffer_size_));
39   buffer_pos_ = 0;
40   own_buffer_ = true;
41   code_address_offset_ = 0;
42 }
43 
44 
Disassembler(char * text_buffer,int buffer_size)45 Disassembler::Disassembler(char *text_buffer, int buffer_size) {
46   buffer_size_ = buffer_size;
47   buffer_ = text_buffer;
48   buffer_pos_ = 0;
49   own_buffer_ = false;
50   code_address_offset_ = 0;
51 }
52 
53 
~Disassembler()54 Disassembler::~Disassembler() {
55   if (own_buffer_) {
56     free(buffer_);
57   }
58 }
59 
60 
GetOutput()61 char *Disassembler::GetOutput() { return buffer_; }
62 
63 
VisitAddSubImmediate(const Instruction * instr)64 void Disassembler::VisitAddSubImmediate(const Instruction *instr) {
65   bool rd_is_zr = RdIsZROrSP(instr);
66   bool stack_op =
67       (rd_is_zr || RnIsZROrSP(instr)) && (instr->GetImmAddSub() == 0) ? true
68                                                                       : false;
69   const char *mnemonic = "";
70   const char *form = "'Rds, 'Rns, 'IAddSub";
71   const char *form_cmp = "'Rns, 'IAddSub";
72   const char *form_mov = "'Rds, 'Rns";
73 
74   switch (instr->Mask(AddSubImmediateMask)) {
75     case ADD_w_imm:
76     case ADD_x_imm: {
77       mnemonic = "add";
78       if (stack_op) {
79         mnemonic = "mov";
80         form = form_mov;
81       }
82       break;
83     }
84     case ADDS_w_imm:
85     case ADDS_x_imm: {
86       mnemonic = "adds";
87       if (rd_is_zr) {
88         mnemonic = "cmn";
89         form = form_cmp;
90       }
91       break;
92     }
93     case SUB_w_imm:
94     case SUB_x_imm:
95       mnemonic = "sub";
96       break;
97     case SUBS_w_imm:
98     case SUBS_x_imm: {
99       mnemonic = "subs";
100       if (rd_is_zr) {
101         mnemonic = "cmp";
102         form = form_cmp;
103       }
104       break;
105     }
106     default:
107       VIXL_UNREACHABLE();
108   }
109   Format(instr, mnemonic, form);
110 }
111 
112 
VisitAddSubShifted(const Instruction * instr)113 void Disassembler::VisitAddSubShifted(const Instruction *instr) {
114   bool rd_is_zr = RdIsZROrSP(instr);
115   bool rn_is_zr = RnIsZROrSP(instr);
116   const char *mnemonic = "";
117   const char *form = "'Rd, 'Rn, 'Rm'NDP";
118   const char *form_cmp = "'Rn, 'Rm'NDP";
119   const char *form_neg = "'Rd, 'Rm'NDP";
120 
121   switch (instr->Mask(AddSubShiftedMask)) {
122     case ADD_w_shift:
123     case ADD_x_shift:
124       mnemonic = "add";
125       break;
126     case ADDS_w_shift:
127     case ADDS_x_shift: {
128       mnemonic = "adds";
129       if (rd_is_zr) {
130         mnemonic = "cmn";
131         form = form_cmp;
132       }
133       break;
134     }
135     case SUB_w_shift:
136     case SUB_x_shift: {
137       mnemonic = "sub";
138       if (rn_is_zr) {
139         mnemonic = "neg";
140         form = form_neg;
141       }
142       break;
143     }
144     case SUBS_w_shift:
145     case SUBS_x_shift: {
146       mnemonic = "subs";
147       if (rd_is_zr) {
148         mnemonic = "cmp";
149         form = form_cmp;
150       } else if (rn_is_zr) {
151         mnemonic = "negs";
152         form = form_neg;
153       }
154       break;
155     }
156     default:
157       VIXL_UNREACHABLE();
158   }
159   Format(instr, mnemonic, form);
160 }
161 
162 
VisitAddSubExtended(const Instruction * instr)163 void Disassembler::VisitAddSubExtended(const Instruction *instr) {
164   bool rd_is_zr = RdIsZROrSP(instr);
165   const char *mnemonic = "";
166   Extend mode = static_cast<Extend>(instr->GetExtendMode());
167   const char *form = ((mode == UXTX) || (mode == SXTX)) ? "'Rds, 'Rns, 'Xm'Ext"
168                                                         : "'Rds, 'Rns, 'Wm'Ext";
169   const char *form_cmp =
170       ((mode == UXTX) || (mode == SXTX)) ? "'Rns, 'Xm'Ext" : "'Rns, 'Wm'Ext";
171 
172   switch (instr->Mask(AddSubExtendedMask)) {
173     case ADD_w_ext:
174     case ADD_x_ext:
175       mnemonic = "add";
176       break;
177     case ADDS_w_ext:
178     case ADDS_x_ext: {
179       mnemonic = "adds";
180       if (rd_is_zr) {
181         mnemonic = "cmn";
182         form = form_cmp;
183       }
184       break;
185     }
186     case SUB_w_ext:
187     case SUB_x_ext:
188       mnemonic = "sub";
189       break;
190     case SUBS_w_ext:
191     case SUBS_x_ext: {
192       mnemonic = "subs";
193       if (rd_is_zr) {
194         mnemonic = "cmp";
195         form = form_cmp;
196       }
197       break;
198     }
199     default:
200       VIXL_UNREACHABLE();
201   }
202   Format(instr, mnemonic, form);
203 }
204 
205 
VisitAddSubWithCarry(const Instruction * instr)206 void Disassembler::VisitAddSubWithCarry(const Instruction *instr) {
207   bool rn_is_zr = RnIsZROrSP(instr);
208   const char *mnemonic = "";
209   const char *form = "'Rd, 'Rn, 'Rm";
210   const char *form_neg = "'Rd, 'Rm";
211 
212   switch (instr->Mask(AddSubWithCarryMask)) {
213     case ADC_w:
214     case ADC_x:
215       mnemonic = "adc";
216       break;
217     case ADCS_w:
218     case ADCS_x:
219       mnemonic = "adcs";
220       break;
221     case SBC_w:
222     case SBC_x: {
223       mnemonic = "sbc";
224       if (rn_is_zr) {
225         mnemonic = "ngc";
226         form = form_neg;
227       }
228       break;
229     }
230     case SBCS_w:
231     case SBCS_x: {
232       mnemonic = "sbcs";
233       if (rn_is_zr) {
234         mnemonic = "ngcs";
235         form = form_neg;
236       }
237       break;
238     }
239     default:
240       VIXL_UNREACHABLE();
241   }
242   Format(instr, mnemonic, form);
243 }
244 
245 
VisitLogicalImmediate(const Instruction * instr)246 void Disassembler::VisitLogicalImmediate(const Instruction *instr) {
247   bool rd_is_zr = RdIsZROrSP(instr);
248   bool rn_is_zr = RnIsZROrSP(instr);
249   const char *mnemonic = "";
250   const char *form = "'Rds, 'Rn, 'ITri";
251 
252   if (instr->GetImmLogical() == 0) {
253     // The immediate encoded in the instruction is not in the expected format.
254     Format(instr, "unallocated", "(LogicalImmediate)");
255     return;
256   }
257 
258   switch (instr->Mask(LogicalImmediateMask)) {
259     case AND_w_imm:
260     case AND_x_imm:
261       mnemonic = "and";
262       break;
263     case ORR_w_imm:
264     case ORR_x_imm: {
265       mnemonic = "orr";
266       unsigned reg_size =
267           (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
268       if (rn_is_zr && !IsMovzMovnImm(reg_size, instr->GetImmLogical())) {
269         mnemonic = "mov";
270         form = "'Rds, 'ITri";
271       }
272       break;
273     }
274     case EOR_w_imm:
275     case EOR_x_imm:
276       mnemonic = "eor";
277       break;
278     case ANDS_w_imm:
279     case ANDS_x_imm: {
280       mnemonic = "ands";
281       if (rd_is_zr) {
282         mnemonic = "tst";
283         form = "'Rn, 'ITri";
284       }
285       break;
286     }
287     default:
288       VIXL_UNREACHABLE();
289   }
290   Format(instr, mnemonic, form);
291 }
292 
293 
IsMovzMovnImm(unsigned reg_size,uint64_t value)294 bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
295   VIXL_ASSERT((reg_size == kXRegSize) ||
296               ((reg_size == kWRegSize) && (value <= 0xffffffff)));
297 
298   // Test for movz: 16 bits set at positions 0, 16, 32 or 48.
299   if (((value & UINT64_C(0xffffffffffff0000)) == 0) ||
300       ((value & UINT64_C(0xffffffff0000ffff)) == 0) ||
301       ((value & UINT64_C(0xffff0000ffffffff)) == 0) ||
302       ((value & UINT64_C(0x0000ffffffffffff)) == 0)) {
303     return true;
304   }
305 
306   // Test for movn: NOT(16 bits set at positions 0, 16, 32 or 48).
307   if ((reg_size == kXRegSize) &&
308       (((~value & UINT64_C(0xffffffffffff0000)) == 0) ||
309        ((~value & UINT64_C(0xffffffff0000ffff)) == 0) ||
310        ((~value & UINT64_C(0xffff0000ffffffff)) == 0) ||
311        ((~value & UINT64_C(0x0000ffffffffffff)) == 0))) {
312     return true;
313   }
314   if ((reg_size == kWRegSize) && (((value & 0xffff0000) == 0xffff0000) ||
315                                   ((value & 0x0000ffff) == 0x0000ffff))) {
316     return true;
317   }
318   return false;
319 }
320 
321 
VisitLogicalShifted(const Instruction * instr)322 void Disassembler::VisitLogicalShifted(const Instruction *instr) {
323   bool rd_is_zr = RdIsZROrSP(instr);
324   bool rn_is_zr = RnIsZROrSP(instr);
325   const char *mnemonic = "";
326   const char *form = "'Rd, 'Rn, 'Rm'NLo";
327 
328   switch (instr->Mask(LogicalShiftedMask)) {
329     case AND_w:
330     case AND_x:
331       mnemonic = "and";
332       break;
333     case BIC_w:
334     case BIC_x:
335       mnemonic = "bic";
336       break;
337     case EOR_w:
338     case EOR_x:
339       mnemonic = "eor";
340       break;
341     case EON_w:
342     case EON_x:
343       mnemonic = "eon";
344       break;
345     case BICS_w:
346     case BICS_x:
347       mnemonic = "bics";
348       break;
349     case ANDS_w:
350     case ANDS_x: {
351       mnemonic = "ands";
352       if (rd_is_zr) {
353         mnemonic = "tst";
354         form = "'Rn, 'Rm'NLo";
355       }
356       break;
357     }
358     case ORR_w:
359     case ORR_x: {
360       mnemonic = "orr";
361       if (rn_is_zr && (instr->GetImmDPShift() == 0) &&
362           (instr->GetShiftDP() == LSL)) {
363         mnemonic = "mov";
364         form = "'Rd, 'Rm";
365       }
366       break;
367     }
368     case ORN_w:
369     case ORN_x: {
370       mnemonic = "orn";
371       if (rn_is_zr) {
372         mnemonic = "mvn";
373         form = "'Rd, 'Rm'NLo";
374       }
375       break;
376     }
377     default:
378       VIXL_UNREACHABLE();
379   }
380 
381   Format(instr, mnemonic, form);
382 }
383 
384 
VisitConditionalCompareRegister(const Instruction * instr)385 void Disassembler::VisitConditionalCompareRegister(const Instruction *instr) {
386   const char *mnemonic = "";
387   const char *form = "'Rn, 'Rm, 'INzcv, 'Cond";
388 
389   switch (instr->Mask(ConditionalCompareRegisterMask)) {
390     case CCMN_w:
391     case CCMN_x:
392       mnemonic = "ccmn";
393       break;
394     case CCMP_w:
395     case CCMP_x:
396       mnemonic = "ccmp";
397       break;
398     default:
399       VIXL_UNREACHABLE();
400   }
401   Format(instr, mnemonic, form);
402 }
403 
404 
VisitConditionalCompareImmediate(const Instruction * instr)405 void Disassembler::VisitConditionalCompareImmediate(const Instruction *instr) {
406   const char *mnemonic = "";
407   const char *form = "'Rn, 'IP, 'INzcv, 'Cond";
408 
409   switch (instr->Mask(ConditionalCompareImmediateMask)) {
410     case CCMN_w_imm:
411     case CCMN_x_imm:
412       mnemonic = "ccmn";
413       break;
414     case CCMP_w_imm:
415     case CCMP_x_imm:
416       mnemonic = "ccmp";
417       break;
418     default:
419       VIXL_UNREACHABLE();
420   }
421   Format(instr, mnemonic, form);
422 }
423 
424 
VisitConditionalSelect(const Instruction * instr)425 void Disassembler::VisitConditionalSelect(const Instruction *instr) {
426   bool rnm_is_zr = (RnIsZROrSP(instr) && RmIsZROrSP(instr));
427   bool rn_is_rm = (instr->GetRn() == instr->GetRm());
428   const char *mnemonic = "";
429   const char *form = "'Rd, 'Rn, 'Rm, 'Cond";
430   const char *form_test = "'Rd, 'CInv";
431   const char *form_update = "'Rd, 'Rn, 'CInv";
432 
433   Condition cond = static_cast<Condition>(instr->GetCondition());
434   bool invertible_cond = (cond != al) && (cond != nv);
435 
436   switch (instr->Mask(ConditionalSelectMask)) {
437     case CSEL_w:
438     case CSEL_x:
439       mnemonic = "csel";
440       break;
441     case CSINC_w:
442     case CSINC_x: {
443       mnemonic = "csinc";
444       if (rnm_is_zr && invertible_cond) {
445         mnemonic = "cset";
446         form = form_test;
447       } else if (rn_is_rm && invertible_cond) {
448         mnemonic = "cinc";
449         form = form_update;
450       }
451       break;
452     }
453     case CSINV_w:
454     case CSINV_x: {
455       mnemonic = "csinv";
456       if (rnm_is_zr && invertible_cond) {
457         mnemonic = "csetm";
458         form = form_test;
459       } else if (rn_is_rm && invertible_cond) {
460         mnemonic = "cinv";
461         form = form_update;
462       }
463       break;
464     }
465     case CSNEG_w:
466     case CSNEG_x: {
467       mnemonic = "csneg";
468       if (rn_is_rm && invertible_cond) {
469         mnemonic = "cneg";
470         form = form_update;
471       }
472       break;
473     }
474     default:
475       VIXL_UNREACHABLE();
476   }
477   Format(instr, mnemonic, form);
478 }
479 
480 
VisitBitfield(const Instruction * instr)481 void Disassembler::VisitBitfield(const Instruction *instr) {
482   unsigned s = instr->GetImmS();
483   unsigned r = instr->GetImmR();
484   unsigned rd_size_minus_1 =
485       ((instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize) - 1;
486   const char *mnemonic = "";
487   const char *form = "";
488   const char *form_shift_right = "'Rd, 'Rn, 'IBr";
489   const char *form_extend = "'Rd, 'Wn";
490   const char *form_bfiz = "'Rd, 'Rn, 'IBZ-r, 'IBs+1";
491   const char *form_bfc = "'Rd, 'IBZ-r, 'IBs+1";
492   const char *form_bfx = "'Rd, 'Rn, 'IBr, 'IBs-r+1";
493   const char *form_lsl = "'Rd, 'Rn, 'IBZ-r";
494 
495   switch (instr->Mask(BitfieldMask)) {
496     case SBFM_w:
497     case SBFM_x: {
498       mnemonic = "sbfx";
499       form = form_bfx;
500       if (r == 0) {
501         form = form_extend;
502         if (s == 7) {
503           mnemonic = "sxtb";
504         } else if (s == 15) {
505           mnemonic = "sxth";
506         } else if ((s == 31) && (instr->GetSixtyFourBits() == 1)) {
507           mnemonic = "sxtw";
508         } else {
509           form = form_bfx;
510         }
511       } else if (s == rd_size_minus_1) {
512         mnemonic = "asr";
513         form = form_shift_right;
514       } else if (s < r) {
515         mnemonic = "sbfiz";
516         form = form_bfiz;
517       }
518       break;
519     }
520     case UBFM_w:
521     case UBFM_x: {
522       mnemonic = "ubfx";
523       form = form_bfx;
524       if (r == 0) {
525         form = form_extend;
526         if (s == 7) {
527           mnemonic = "uxtb";
528         } else if (s == 15) {
529           mnemonic = "uxth";
530         } else {
531           form = form_bfx;
532         }
533       }
534       if (s == rd_size_minus_1) {
535         mnemonic = "lsr";
536         form = form_shift_right;
537       } else if (r == s + 1) {
538         mnemonic = "lsl";
539         form = form_lsl;
540       } else if (s < r) {
541         mnemonic = "ubfiz";
542         form = form_bfiz;
543       }
544       break;
545     }
546     case BFM_w:
547     case BFM_x: {
548       mnemonic = "bfxil";
549       form = form_bfx;
550       if (s < r) {
551         if (instr->GetRn() == kZeroRegCode) {
552           mnemonic = "bfc";
553           form = form_bfc;
554         } else {
555           mnemonic = "bfi";
556           form = form_bfiz;
557         }
558       }
559     }
560   }
561   Format(instr, mnemonic, form);
562 }
563 
564 
VisitExtract(const Instruction * instr)565 void Disassembler::VisitExtract(const Instruction *instr) {
566   const char *mnemonic = "";
567   const char *form = "'Rd, 'Rn, 'Rm, 'IExtract";
568 
569   switch (instr->Mask(ExtractMask)) {
570     case EXTR_w:
571     case EXTR_x: {
572       if (instr->GetRn() == instr->GetRm()) {
573         mnemonic = "ror";
574         form = "'Rd, 'Rn, 'IExtract";
575       } else {
576         mnemonic = "extr";
577       }
578       break;
579     }
580     default:
581       VIXL_UNREACHABLE();
582   }
583   Format(instr, mnemonic, form);
584 }
585 
586 
VisitPCRelAddressing(const Instruction * instr)587 void Disassembler::VisitPCRelAddressing(const Instruction *instr) {
588   switch (instr->Mask(PCRelAddressingMask)) {
589     case ADR:
590       Format(instr, "adr", "'Xd, 'AddrPCRelByte");
591       break;
592     case ADRP:
593       Format(instr, "adrp", "'Xd, 'AddrPCRelPage");
594       break;
595     default:
596       Format(instr, "unimplemented", "(PCRelAddressing)");
597   }
598 }
599 
600 
VisitConditionalBranch(const Instruction * instr)601 void Disassembler::VisitConditionalBranch(const Instruction *instr) {
602   switch (instr->Mask(ConditionalBranchMask)) {
603     case B_cond:
604       Format(instr, "b.'CBrn", "'TImmCond");
605       break;
606     default:
607       VIXL_UNREACHABLE();
608   }
609 }
610 
611 
VisitUnconditionalBranchToRegister(const Instruction * instr)612 void Disassembler::VisitUnconditionalBranchToRegister(
613     const Instruction *instr) {
614   const char *mnemonic = "unimplemented";
615   const char *form;
616 
617   switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
618     case BR:
619       mnemonic = "br";
620       form = "'Xn";
621       break;
622     case BLR:
623       mnemonic = "blr";
624       form = "'Xn";
625       break;
626     case RET: {
627       mnemonic = "ret";
628       if (instr->GetRn() == kLinkRegCode) {
629         form = NULL;
630       } else {
631         form = "'Xn";
632       }
633       break;
634     }
635     case BRAAZ:
636       mnemonic = "braaz";
637       form = "'Xn";
638       break;
639     case BRABZ:
640       mnemonic = "brabz";
641       form = "'Xn";
642       break;
643     case BLRAAZ:
644       mnemonic = "blraaz";
645       form = "'Xn";
646       break;
647     case BLRABZ:
648       mnemonic = "blrabz";
649       form = "'Xn";
650       break;
651     case RETAA:
652       mnemonic = "retaa";
653       form = NULL;
654       break;
655     case RETAB:
656       mnemonic = "retab";
657       form = NULL;
658       break;
659     case BRAA:
660       mnemonic = "braa";
661       form = "'Xn, 'Xds";
662       break;
663     case BRAB:
664       mnemonic = "brab";
665       form = "'Xn, 'Xds";
666       break;
667     case BLRAA:
668       mnemonic = "blraa";
669       form = "'Xn, 'Xds";
670       break;
671     case BLRAB:
672       mnemonic = "blrab";
673       form = "'Xn, 'Xds";
674       break;
675     default:
676       form = "(UnconditionalBranchToRegister)";
677   }
678   Format(instr, mnemonic, form);
679 }
680 
681 
VisitUnconditionalBranch(const Instruction * instr)682 void Disassembler::VisitUnconditionalBranch(const Instruction *instr) {
683   const char *mnemonic = "";
684   const char *form = "'TImmUncn";
685 
686   switch (instr->Mask(UnconditionalBranchMask)) {
687     case B:
688       mnemonic = "b";
689       break;
690     case BL:
691       mnemonic = "bl";
692       break;
693     default:
694       VIXL_UNREACHABLE();
695   }
696   Format(instr, mnemonic, form);
697 }
698 
699 
VisitDataProcessing1Source(const Instruction * instr)700 void Disassembler::VisitDataProcessing1Source(const Instruction *instr) {
701   const char *mnemonic = "";
702   const char *form = "'Rd, 'Rn";
703 
704   switch (instr->Mask(DataProcessing1SourceMask)) {
705 #define FORMAT(A, B) \
706   case A##_w:        \
707   case A##_x:        \
708     mnemonic = B;    \
709     break;
710     FORMAT(RBIT, "rbit");
711     FORMAT(REV16, "rev16");
712     FORMAT(REV, "rev");
713     FORMAT(CLZ, "clz");
714     FORMAT(CLS, "cls");
715 #undef FORMAT
716 
717 #define PAUTH_VARIATIONS(V) \
718   V(PACI, "paci")           \
719   V(PACD, "pacd")           \
720   V(AUTI, "auti")           \
721   V(AUTD, "autd")
722 #define PAUTH_CASE(NAME, MN) \
723   case NAME##A:              \
724     mnemonic = MN "a";       \
725     form = "'Xd, 'Xns";      \
726     break;                   \
727   case NAME##ZA:             \
728     mnemonic = MN "za";      \
729     form = "'Xd";            \
730     break;                   \
731   case NAME##B:              \
732     mnemonic = MN "b";       \
733     form = "'Xd, 'Xns";      \
734     break;                   \
735   case NAME##ZB:             \
736     mnemonic = MN "zb";      \
737     form = "'Xd";            \
738     break;
739 
740     PAUTH_VARIATIONS(PAUTH_CASE)
741 #undef PAUTH_CASE
742 
743     case XPACI:
744       mnemonic = "xpaci";
745       form = "'Xd";
746       break;
747     case XPACD:
748       mnemonic = "xpacd";
749       form = "'Xd";
750       break;
751     case REV32_x:
752       mnemonic = "rev32";
753       break;
754     default:
755       VIXL_UNREACHABLE();
756   }
757   Format(instr, mnemonic, form);
758 }
759 
760 
VisitDataProcessing2Source(const Instruction * instr)761 void Disassembler::VisitDataProcessing2Source(const Instruction *instr) {
762   const char *mnemonic = "unimplemented";
763   const char *form = "'Rd, 'Rn, 'Rm";
764   const char *form_wwx = "'Wd, 'Wn, 'Xm";
765 
766   switch (instr->Mask(DataProcessing2SourceMask)) {
767 #define FORMAT(A, B) \
768   case A##_w:        \
769   case A##_x:        \
770     mnemonic = B;    \
771     break;
772     FORMAT(UDIV, "udiv");
773     FORMAT(SDIV, "sdiv");
774     FORMAT(LSLV, "lsl");
775     FORMAT(LSRV, "lsr");
776     FORMAT(ASRV, "asr");
777     FORMAT(RORV, "ror");
778 #undef FORMAT
779     case PACGA:
780       mnemonic = "pacga";
781       form = "'Xd, 'Xn, 'Xms";
782       break;
783     case CRC32B:
784       mnemonic = "crc32b";
785       break;
786     case CRC32H:
787       mnemonic = "crc32h";
788       break;
789     case CRC32W:
790       mnemonic = "crc32w";
791       break;
792     case CRC32X:
793       mnemonic = "crc32x";
794       form = form_wwx;
795       break;
796     case CRC32CB:
797       mnemonic = "crc32cb";
798       break;
799     case CRC32CH:
800       mnemonic = "crc32ch";
801       break;
802     case CRC32CW:
803       mnemonic = "crc32cw";
804       break;
805     case CRC32CX:
806       mnemonic = "crc32cx";
807       form = form_wwx;
808       break;
809     default:
810       form = "(DataProcessing2Source)";
811   }
812   Format(instr, mnemonic, form);
813 }
814 
815 
VisitDataProcessing3Source(const Instruction * instr)816 void Disassembler::VisitDataProcessing3Source(const Instruction *instr) {
817   bool ra_is_zr = RaIsZROrSP(instr);
818   const char *mnemonic = "";
819   const char *form = "'Xd, 'Wn, 'Wm, 'Xa";
820   const char *form_rrr = "'Rd, 'Rn, 'Rm";
821   const char *form_rrrr = "'Rd, 'Rn, 'Rm, 'Ra";
822   const char *form_xww = "'Xd, 'Wn, 'Wm";
823   const char *form_xxx = "'Xd, 'Xn, 'Xm";
824 
825   switch (instr->Mask(DataProcessing3SourceMask)) {
826     case MADD_w:
827     case MADD_x: {
828       mnemonic = "madd";
829       form = form_rrrr;
830       if (ra_is_zr) {
831         mnemonic = "mul";
832         form = form_rrr;
833       }
834       break;
835     }
836     case MSUB_w:
837     case MSUB_x: {
838       mnemonic = "msub";
839       form = form_rrrr;
840       if (ra_is_zr) {
841         mnemonic = "mneg";
842         form = form_rrr;
843       }
844       break;
845     }
846     case SMADDL_x: {
847       mnemonic = "smaddl";
848       if (ra_is_zr) {
849         mnemonic = "smull";
850         form = form_xww;
851       }
852       break;
853     }
854     case SMSUBL_x: {
855       mnemonic = "smsubl";
856       if (ra_is_zr) {
857         mnemonic = "smnegl";
858         form = form_xww;
859       }
860       break;
861     }
862     case UMADDL_x: {
863       mnemonic = "umaddl";
864       if (ra_is_zr) {
865         mnemonic = "umull";
866         form = form_xww;
867       }
868       break;
869     }
870     case UMSUBL_x: {
871       mnemonic = "umsubl";
872       if (ra_is_zr) {
873         mnemonic = "umnegl";
874         form = form_xww;
875       }
876       break;
877     }
878     case SMULH_x: {
879       mnemonic = "smulh";
880       form = form_xxx;
881       break;
882     }
883     case UMULH_x: {
884       mnemonic = "umulh";
885       form = form_xxx;
886       break;
887     }
888     default:
889       VIXL_UNREACHABLE();
890   }
891   Format(instr, mnemonic, form);
892 }
893 
894 
VisitCompareBranch(const Instruction * instr)895 void Disassembler::VisitCompareBranch(const Instruction *instr) {
896   const char *mnemonic = "";
897   const char *form = "'Rt, 'TImmCmpa";
898 
899   switch (instr->Mask(CompareBranchMask)) {
900     case CBZ_w:
901     case CBZ_x:
902       mnemonic = "cbz";
903       break;
904     case CBNZ_w:
905     case CBNZ_x:
906       mnemonic = "cbnz";
907       break;
908     default:
909       VIXL_UNREACHABLE();
910   }
911   Format(instr, mnemonic, form);
912 }
913 
914 
VisitTestBranch(const Instruction * instr)915 void Disassembler::VisitTestBranch(const Instruction *instr) {
916   const char *mnemonic = "";
917   // If the top bit of the immediate is clear, the tested register is
918   // disassembled as Wt, otherwise Xt. As the top bit of the immediate is
919   // encoded in bit 31 of the instruction, we can reuse the Rt form, which
920   // uses bit 31 (normally "sf") to choose the register size.
921   const char *form = "'Rt, 'IS, 'TImmTest";
922 
923   switch (instr->Mask(TestBranchMask)) {
924     case TBZ:
925       mnemonic = "tbz";
926       break;
927     case TBNZ:
928       mnemonic = "tbnz";
929       break;
930     default:
931       VIXL_UNREACHABLE();
932   }
933   Format(instr, mnemonic, form);
934 }
935 
936 
VisitMoveWideImmediate(const Instruction * instr)937 void Disassembler::VisitMoveWideImmediate(const Instruction *instr) {
938   const char *mnemonic = "";
939   const char *form = "'Rd, 'IMoveImm";
940 
941   // Print the shift separately for movk, to make it clear which half word will
942   // be overwritten. Movn and movz print the computed immediate, which includes
943   // shift calculation.
944   switch (instr->Mask(MoveWideImmediateMask)) {
945     case MOVN_w:
946     case MOVN_x:
947       if ((instr->GetImmMoveWide()) || (instr->GetShiftMoveWide() == 0)) {
948         if ((instr->GetSixtyFourBits() == 0) &&
949             (instr->GetImmMoveWide() == 0xffff)) {
950           mnemonic = "movn";
951         } else {
952           mnemonic = "mov";
953           form = "'Rd, 'IMoveNeg";
954         }
955       } else {
956         mnemonic = "movn";
957       }
958       break;
959     case MOVZ_w:
960     case MOVZ_x:
961       if ((instr->GetImmMoveWide()) || (instr->GetShiftMoveWide() == 0))
962         mnemonic = "mov";
963       else
964         mnemonic = "movz";
965       break;
966     case MOVK_w:
967     case MOVK_x:
968       mnemonic = "movk";
969       form = "'Rd, 'IMoveLSL";
970       break;
971     default:
972       VIXL_UNREACHABLE();
973   }
974   Format(instr, mnemonic, form);
975 }
976 
977 
978 #define LOAD_STORE_LIST(V)   \
979   V(STRB_w, "strb", "'Wt")   \
980   V(STRH_w, "strh", "'Wt")   \
981   V(STR_w, "str", "'Wt")     \
982   V(STR_x, "str", "'Xt")     \
983   V(LDRB_w, "ldrb", "'Wt")   \
984   V(LDRH_w, "ldrh", "'Wt")   \
985   V(LDR_w, "ldr", "'Wt")     \
986   V(LDR_x, "ldr", "'Xt")     \
987   V(LDRSB_x, "ldrsb", "'Xt") \
988   V(LDRSH_x, "ldrsh", "'Xt") \
989   V(LDRSW_x, "ldrsw", "'Xt") \
990   V(LDRSB_w, "ldrsb", "'Wt") \
991   V(LDRSH_w, "ldrsh", "'Wt") \
992   V(STR_b, "str", "'Bt")     \
993   V(STR_h, "str", "'Ht")     \
994   V(STR_s, "str", "'St")     \
995   V(STR_d, "str", "'Dt")     \
996   V(LDR_b, "ldr", "'Bt")     \
997   V(LDR_h, "ldr", "'Ht")     \
998   V(LDR_s, "ldr", "'St")     \
999   V(LDR_d, "ldr", "'Dt")     \
1000   V(STR_q, "str", "'Qt")     \
1001   V(LDR_q, "ldr", "'Qt")
1002 
VisitLoadStorePreIndex(const Instruction * instr)1003 void Disassembler::VisitLoadStorePreIndex(const Instruction *instr) {
1004   const char *mnemonic = "unimplemented";
1005   const char *form = "(LoadStorePreIndex)";
1006 
1007   switch (instr->Mask(LoadStorePreIndexMask)) {
1008 #define LS_PREINDEX(A, B, C)   \
1009   case A##_pre:                \
1010     mnemonic = B;              \
1011     form = C ", ['Xns'ILSi]!"; \
1012     break;
1013     LOAD_STORE_LIST(LS_PREINDEX)
1014 #undef LS_PREINDEX
1015   }
1016   Format(instr, mnemonic, form);
1017 }
1018 
1019 
VisitLoadStorePostIndex(const Instruction * instr)1020 void Disassembler::VisitLoadStorePostIndex(const Instruction *instr) {
1021   const char *mnemonic = "unimplemented";
1022   const char *form = "(LoadStorePostIndex)";
1023 
1024   switch (instr->Mask(LoadStorePostIndexMask)) {
1025 #define LS_POSTINDEX(A, B, C) \
1026   case A##_post:              \
1027     mnemonic = B;             \
1028     form = C ", ['Xns]'ILSi"; \
1029     break;
1030     LOAD_STORE_LIST(LS_POSTINDEX)
1031 #undef LS_POSTINDEX
1032   }
1033   Format(instr, mnemonic, form);
1034 }
1035 
1036 
VisitLoadStoreUnsignedOffset(const Instruction * instr)1037 void Disassembler::VisitLoadStoreUnsignedOffset(const Instruction *instr) {
1038   const char *mnemonic = "unimplemented";
1039   const char *form = "(LoadStoreUnsignedOffset)";
1040 
1041   switch (instr->Mask(LoadStoreUnsignedOffsetMask)) {
1042 #define LS_UNSIGNEDOFFSET(A, B, C) \
1043   case A##_unsigned:               \
1044     mnemonic = B;                  \
1045     form = C ", ['Xns'ILU]";       \
1046     break;
1047     LOAD_STORE_LIST(LS_UNSIGNEDOFFSET)
1048 #undef LS_UNSIGNEDOFFSET
1049     case PRFM_unsigned:
1050       mnemonic = "prfm";
1051       form = "'PrefOp, ['Xns'ILU]";
1052   }
1053   Format(instr, mnemonic, form);
1054 }
1055 
1056 
VisitLoadStoreRegisterOffset(const Instruction * instr)1057 void Disassembler::VisitLoadStoreRegisterOffset(const Instruction *instr) {
1058   const char *mnemonic = "unimplemented";
1059   const char *form = "(LoadStoreRegisterOffset)";
1060 
1061   switch (instr->Mask(LoadStoreRegisterOffsetMask)) {
1062 #define LS_REGISTEROFFSET(A, B, C)   \
1063   case A##_reg:                      \
1064     mnemonic = B;                    \
1065     form = C ", ['Xns, 'Offsetreg]"; \
1066     break;
1067     LOAD_STORE_LIST(LS_REGISTEROFFSET)
1068 #undef LS_REGISTEROFFSET
1069     case PRFM_reg:
1070       mnemonic = "prfm";
1071       form = "'PrefOp, ['Xns, 'Offsetreg]";
1072   }
1073   Format(instr, mnemonic, form);
1074 }
1075 
1076 
VisitLoadStoreUnscaledOffset(const Instruction * instr)1077 void Disassembler::VisitLoadStoreUnscaledOffset(const Instruction *instr) {
1078   const char *mnemonic = "unimplemented";
1079   const char *form = "'Wt, ['Xns'ILS]";
1080   const char *form_x = "'Xt, ['Xns'ILS]";
1081   const char *form_b = "'Bt, ['Xns'ILS]";
1082   const char *form_h = "'Ht, ['Xns'ILS]";
1083   const char *form_s = "'St, ['Xns'ILS]";
1084   const char *form_d = "'Dt, ['Xns'ILS]";
1085   const char *form_q = "'Qt, ['Xns'ILS]";
1086   const char *form_prefetch = "'PrefOp, ['Xns'ILS]";
1087 
1088   switch (instr->Mask(LoadStoreUnscaledOffsetMask)) {
1089     case STURB_w:
1090       mnemonic = "sturb";
1091       break;
1092     case STURH_w:
1093       mnemonic = "sturh";
1094       break;
1095     case STUR_w:
1096       mnemonic = "stur";
1097       break;
1098     case STUR_x:
1099       mnemonic = "stur";
1100       form = form_x;
1101       break;
1102     case STUR_b:
1103       mnemonic = "stur";
1104       form = form_b;
1105       break;
1106     case STUR_h:
1107       mnemonic = "stur";
1108       form = form_h;
1109       break;
1110     case STUR_s:
1111       mnemonic = "stur";
1112       form = form_s;
1113       break;
1114     case STUR_d:
1115       mnemonic = "stur";
1116       form = form_d;
1117       break;
1118     case STUR_q:
1119       mnemonic = "stur";
1120       form = form_q;
1121       break;
1122     case LDURB_w:
1123       mnemonic = "ldurb";
1124       break;
1125     case LDURH_w:
1126       mnemonic = "ldurh";
1127       break;
1128     case LDUR_w:
1129       mnemonic = "ldur";
1130       break;
1131     case LDUR_x:
1132       mnemonic = "ldur";
1133       form = form_x;
1134       break;
1135     case LDUR_b:
1136       mnemonic = "ldur";
1137       form = form_b;
1138       break;
1139     case LDUR_h:
1140       mnemonic = "ldur";
1141       form = form_h;
1142       break;
1143     case LDUR_s:
1144       mnemonic = "ldur";
1145       form = form_s;
1146       break;
1147     case LDUR_d:
1148       mnemonic = "ldur";
1149       form = form_d;
1150       break;
1151     case LDUR_q:
1152       mnemonic = "ldur";
1153       form = form_q;
1154       break;
1155     case LDURSB_x:
1156       form = form_x;
1157       VIXL_FALLTHROUGH();
1158     case LDURSB_w:
1159       mnemonic = "ldursb";
1160       break;
1161     case LDURSH_x:
1162       form = form_x;
1163       VIXL_FALLTHROUGH();
1164     case LDURSH_w:
1165       mnemonic = "ldursh";
1166       break;
1167     case LDURSW_x:
1168       mnemonic = "ldursw";
1169       form = form_x;
1170       break;
1171     case PRFUM:
1172       mnemonic = "prfum";
1173       form = form_prefetch;
1174       break;
1175     default:
1176       form = "(LoadStoreUnscaledOffset)";
1177   }
1178   Format(instr, mnemonic, form);
1179 }
1180 
1181 
VisitLoadLiteral(const Instruction * instr)1182 void Disassembler::VisitLoadLiteral(const Instruction *instr) {
1183   const char *mnemonic = "ldr";
1184   const char *form = "(LoadLiteral)";
1185 
1186   switch (instr->Mask(LoadLiteralMask)) {
1187     case LDR_w_lit:
1188       form = "'Wt, 'ILLiteral 'LValue";
1189       break;
1190     case LDR_x_lit:
1191       form = "'Xt, 'ILLiteral 'LValue";
1192       break;
1193     case LDR_s_lit:
1194       form = "'St, 'ILLiteral 'LValue";
1195       break;
1196     case LDR_d_lit:
1197       form = "'Dt, 'ILLiteral 'LValue";
1198       break;
1199     case LDR_q_lit:
1200       form = "'Qt, 'ILLiteral 'LValue";
1201       break;
1202     case LDRSW_x_lit: {
1203       mnemonic = "ldrsw";
1204       form = "'Xt, 'ILLiteral 'LValue";
1205       break;
1206     }
1207     case PRFM_lit: {
1208       mnemonic = "prfm";
1209       form = "'PrefOp, 'ILLiteral 'LValue";
1210       break;
1211     }
1212     default:
1213       mnemonic = "unimplemented";
1214   }
1215   Format(instr, mnemonic, form);
1216 }
1217 
1218 
1219 #define LOAD_STORE_PAIR_LIST(V)         \
1220   V(STP_w, "stp", "'Wt, 'Wt2", "2")     \
1221   V(LDP_w, "ldp", "'Wt, 'Wt2", "2")     \
1222   V(LDPSW_x, "ldpsw", "'Xt, 'Xt2", "2") \
1223   V(STP_x, "stp", "'Xt, 'Xt2", "3")     \
1224   V(LDP_x, "ldp", "'Xt, 'Xt2", "3")     \
1225   V(STP_s, "stp", "'St, 'St2", "2")     \
1226   V(LDP_s, "ldp", "'St, 'St2", "2")     \
1227   V(STP_d, "stp", "'Dt, 'Dt2", "3")     \
1228   V(LDP_d, "ldp", "'Dt, 'Dt2", "3")     \
1229   V(LDP_q, "ldp", "'Qt, 'Qt2", "4")     \
1230   V(STP_q, "stp", "'Qt, 'Qt2", "4")
1231 
VisitLoadStorePairPostIndex(const Instruction * instr)1232 void Disassembler::VisitLoadStorePairPostIndex(const Instruction *instr) {
1233   const char *mnemonic = "unimplemented";
1234   const char *form = "(LoadStorePairPostIndex)";
1235 
1236   switch (instr->Mask(LoadStorePairPostIndexMask)) {
1237 #define LSP_POSTINDEX(A, B, C, D)  \
1238   case A##_post:                   \
1239     mnemonic = B;                  \
1240     form = C ", ['Xns]'ILP" D "i"; \
1241     break;
1242     LOAD_STORE_PAIR_LIST(LSP_POSTINDEX)
1243 #undef LSP_POSTINDEX
1244   }
1245   Format(instr, mnemonic, form);
1246 }
1247 
1248 
VisitLoadStorePairPreIndex(const Instruction * instr)1249 void Disassembler::VisitLoadStorePairPreIndex(const Instruction *instr) {
1250   const char *mnemonic = "unimplemented";
1251   const char *form = "(LoadStorePairPreIndex)";
1252 
1253   switch (instr->Mask(LoadStorePairPreIndexMask)) {
1254 #define LSP_PREINDEX(A, B, C, D)    \
1255   case A##_pre:                     \
1256     mnemonic = B;                   \
1257     form = C ", ['Xns'ILP" D "i]!"; \
1258     break;
1259     LOAD_STORE_PAIR_LIST(LSP_PREINDEX)
1260 #undef LSP_PREINDEX
1261   }
1262   Format(instr, mnemonic, form);
1263 }
1264 
1265 
VisitLoadStorePairOffset(const Instruction * instr)1266 void Disassembler::VisitLoadStorePairOffset(const Instruction *instr) {
1267   const char *mnemonic = "unimplemented";
1268   const char *form = "(LoadStorePairOffset)";
1269 
1270   switch (instr->Mask(LoadStorePairOffsetMask)) {
1271 #define LSP_OFFSET(A, B, C, D)    \
1272   case A##_off:                   \
1273     mnemonic = B;                 \
1274     form = C ", ['Xns'ILP" D "]"; \
1275     break;
1276     LOAD_STORE_PAIR_LIST(LSP_OFFSET)
1277 #undef LSP_OFFSET
1278   }
1279   Format(instr, mnemonic, form);
1280 }
1281 
1282 
VisitLoadStorePairNonTemporal(const Instruction * instr)1283 void Disassembler::VisitLoadStorePairNonTemporal(const Instruction *instr) {
1284   const char *mnemonic = "unimplemented";
1285   const char *form;
1286 
1287   switch (instr->Mask(LoadStorePairNonTemporalMask)) {
1288     case STNP_w:
1289       mnemonic = "stnp";
1290       form = "'Wt, 'Wt2, ['Xns'ILP2]";
1291       break;
1292     case LDNP_w:
1293       mnemonic = "ldnp";
1294       form = "'Wt, 'Wt2, ['Xns'ILP2]";
1295       break;
1296     case STNP_x:
1297       mnemonic = "stnp";
1298       form = "'Xt, 'Xt2, ['Xns'ILP3]";
1299       break;
1300     case LDNP_x:
1301       mnemonic = "ldnp";
1302       form = "'Xt, 'Xt2, ['Xns'ILP3]";
1303       break;
1304     case STNP_s:
1305       mnemonic = "stnp";
1306       form = "'St, 'St2, ['Xns'ILP2]";
1307       break;
1308     case LDNP_s:
1309       mnemonic = "ldnp";
1310       form = "'St, 'St2, ['Xns'ILP2]";
1311       break;
1312     case STNP_d:
1313       mnemonic = "stnp";
1314       form = "'Dt, 'Dt2, ['Xns'ILP3]";
1315       break;
1316     case LDNP_d:
1317       mnemonic = "ldnp";
1318       form = "'Dt, 'Dt2, ['Xns'ILP3]";
1319       break;
1320     case STNP_q:
1321       mnemonic = "stnp";
1322       form = "'Qt, 'Qt2, ['Xns'ILP4]";
1323       break;
1324     case LDNP_q:
1325       mnemonic = "ldnp";
1326       form = "'Qt, 'Qt2, ['Xns'ILP4]";
1327       break;
1328     default:
1329       form = "(LoadStorePairNonTemporal)";
1330   }
1331   Format(instr, mnemonic, form);
1332 }
1333 
1334 // clang-format off
1335 #define LOAD_STORE_EXCLUSIVE_LIST(V)                  \
1336   V(STXRB_w,  "stxrb",  "'Ws, 'Wt")                   \
1337   V(STXRH_w,  "stxrh",  "'Ws, 'Wt")                   \
1338   V(STXR_w,   "stxr",   "'Ws, 'Wt")                   \
1339   V(STXR_x,   "stxr",   "'Ws, 'Xt")                   \
1340   V(LDXRB_w,  "ldxrb",  "'Wt")                        \
1341   V(LDXRH_w,  "ldxrh",  "'Wt")                        \
1342   V(LDXR_w,   "ldxr",   "'Wt")                        \
1343   V(LDXR_x,   "ldxr",   "'Xt")                        \
1344   V(STXP_w,   "stxp",   "'Ws, 'Wt, 'Wt2")             \
1345   V(STXP_x,   "stxp",   "'Ws, 'Xt, 'Xt2")             \
1346   V(LDXP_w,   "ldxp",   "'Wt, 'Wt2")                  \
1347   V(LDXP_x,   "ldxp",   "'Xt, 'Xt2")                  \
1348   V(STLXRB_w, "stlxrb", "'Ws, 'Wt")                   \
1349   V(STLXRH_w, "stlxrh", "'Ws, 'Wt")                   \
1350   V(STLXR_w,  "stlxr",  "'Ws, 'Wt")                   \
1351   V(STLXR_x,  "stlxr",  "'Ws, 'Xt")                   \
1352   V(LDAXRB_w, "ldaxrb", "'Wt")                        \
1353   V(LDAXRH_w, "ldaxrh", "'Wt")                        \
1354   V(LDAXR_w,  "ldaxr",  "'Wt")                        \
1355   V(LDAXR_x,  "ldaxr",  "'Xt")                        \
1356   V(STLXP_w,  "stlxp",  "'Ws, 'Wt, 'Wt2")             \
1357   V(STLXP_x,  "stlxp",  "'Ws, 'Xt, 'Xt2")             \
1358   V(LDAXP_w,  "ldaxp",  "'Wt, 'Wt2")                  \
1359   V(LDAXP_x,  "ldaxp",  "'Xt, 'Xt2")                  \
1360   V(STLRB_w,  "stlrb",  "'Wt")                        \
1361   V(STLRH_w,  "stlrh",  "'Wt")                        \
1362   V(STLR_w,   "stlr",   "'Wt")                        \
1363   V(STLR_x,   "stlr",   "'Xt")                        \
1364   V(LDARB_w,  "ldarb",  "'Wt")                        \
1365   V(LDARH_w,  "ldarh",  "'Wt")                        \
1366   V(LDAR_w,   "ldar",   "'Wt")                        \
1367   V(LDAR_x,   "ldar",   "'Xt")                        \
1368   V(STLLRB,   "stllrb", "'Wt")                        \
1369   V(STLLRH,   "stllrh", "'Wt")                        \
1370   V(STLLR_w,  "stllr",  "'Wt")                        \
1371   V(STLLR_x,  "stllr",  "'Xt")                        \
1372   V(LDLARB,   "ldlarb", "'Wt")                        \
1373   V(LDLARH,   "ldlarh", "'Wt")                        \
1374   V(LDLAR_w,  "ldlar",  "'Wt")                        \
1375   V(LDLAR_x,  "ldlar",  "'Xt")                        \
1376   V(CAS_w,    "cas",    "'Ws, 'Wt")                   \
1377   V(CAS_x,    "cas",    "'Xs, 'Xt")                   \
1378   V(CASA_w,   "casa",   "'Ws, 'Wt")                   \
1379   V(CASA_x,   "casa",   "'Xs, 'Xt")                   \
1380   V(CASL_w,   "casl",   "'Ws, 'Wt")                   \
1381   V(CASL_x,   "casl",   "'Xs, 'Xt")                   \
1382   V(CASAL_w,  "casal",  "'Ws, 'Wt")                   \
1383   V(CASAL_x,  "casal",  "'Xs, 'Xt")                   \
1384   V(CASB,     "casb",   "'Ws, 'Wt")                   \
1385   V(CASAB,    "casab",  "'Ws, 'Wt")                   \
1386   V(CASLB,    "caslb",  "'Ws, 'Wt")                   \
1387   V(CASALB,   "casalb", "'Ws, 'Wt")                   \
1388   V(CASH,     "cash",   "'Ws, 'Wt")                   \
1389   V(CASAH,    "casah",  "'Ws, 'Wt")                   \
1390   V(CASLH,    "caslh",  "'Ws, 'Wt")                   \
1391   V(CASALH,   "casalh", "'Ws, 'Wt")                   \
1392   V(CASP_w,   "casp",   "'Ws, 'W(s+1), 'Wt, 'W(t+1)") \
1393   V(CASP_x,   "casp",   "'Xs, 'X(s+1), 'Xt, 'X(t+1)") \
1394   V(CASPA_w,  "caspa",  "'Ws, 'W(s+1), 'Wt, 'W(t+1)") \
1395   V(CASPA_x,  "caspa",  "'Xs, 'X(s+1), 'Xt, 'X(t+1)") \
1396   V(CASPL_w,  "caspl",  "'Ws, 'W(s+1), 'Wt, 'W(t+1)") \
1397   V(CASPL_x,  "caspl",  "'Xs, 'X(s+1), 'Xt, 'X(t+1)") \
1398   V(CASPAL_w, "caspal", "'Ws, 'W(s+1), 'Wt, 'W(t+1)") \
1399   V(CASPAL_x, "caspal", "'Xs, 'X(s+1), 'Xt, 'X(t+1)")
1400 // clang-format on
1401 
1402 
VisitLoadStoreExclusive(const Instruction * instr)1403 void Disassembler::VisitLoadStoreExclusive(const Instruction *instr) {
1404   const char *mnemonic = "unimplemented";
1405   const char *form;
1406 
1407   switch (instr->Mask(LoadStoreExclusiveMask)) {
1408 #define LSX(A, B, C)     \
1409   case A:                \
1410     mnemonic = B;        \
1411     form = C ", ['Xns]"; \
1412     break;
1413     LOAD_STORE_EXCLUSIVE_LIST(LSX)
1414 #undef LSX
1415     default:
1416       form = "(LoadStoreExclusive)";
1417   }
1418 
1419   switch (instr->Mask(LoadStoreExclusiveMask)) {
1420     case CASP_w:
1421     case CASP_x:
1422     case CASPA_w:
1423     case CASPA_x:
1424     case CASPL_w:
1425     case CASPL_x:
1426     case CASPAL_w:
1427     case CASPAL_x:
1428       if ((instr->GetRs() % 2 == 1) || (instr->GetRt() % 2 == 1)) {
1429         mnemonic = "unallocated";
1430         form = "(LoadStoreExclusive)";
1431       }
1432       break;
1433   }
1434 
1435   Format(instr, mnemonic, form);
1436 }
1437 
1438 #define ATOMIC_MEMORY_SIMPLE_LIST(V) \
1439   V(LDADD, "add")                    \
1440   V(LDCLR, "clr")                    \
1441   V(LDEOR, "eor")                    \
1442   V(LDSET, "set")                    \
1443   V(LDSMAX, "smax")                  \
1444   V(LDSMIN, "smin")                  \
1445   V(LDUMAX, "umax")                  \
1446   V(LDUMIN, "umin")
1447 
VisitAtomicMemory(const Instruction * instr)1448 void Disassembler::VisitAtomicMemory(const Instruction *instr) {
1449   const int kMaxAtomicOpMnemonicLength = 16;
1450   const char *mnemonic;
1451   const char *form = "'Ws, 'Wt, ['Xns]";
1452 
1453   switch (instr->Mask(AtomicMemoryMask)) {
1454 #define AMS(A, MN)             \
1455   case A##B:                   \
1456     mnemonic = MN "b";         \
1457     break;                     \
1458   case A##AB:                  \
1459     mnemonic = MN "ab";        \
1460     break;                     \
1461   case A##LB:                  \
1462     mnemonic = MN "lb";        \
1463     break;                     \
1464   case A##ALB:                 \
1465     mnemonic = MN "alb";       \
1466     break;                     \
1467   case A##H:                   \
1468     mnemonic = MN "h";         \
1469     break;                     \
1470   case A##AH:                  \
1471     mnemonic = MN "ah";        \
1472     break;                     \
1473   case A##LH:                  \
1474     mnemonic = MN "lh";        \
1475     break;                     \
1476   case A##ALH:                 \
1477     mnemonic = MN "alh";       \
1478     break;                     \
1479   case A##_w:                  \
1480     mnemonic = MN;             \
1481     break;                     \
1482   case A##A_w:                 \
1483     mnemonic = MN "a";         \
1484     break;                     \
1485   case A##L_w:                 \
1486     mnemonic = MN "l";         \
1487     break;                     \
1488   case A##AL_w:                \
1489     mnemonic = MN "al";        \
1490     break;                     \
1491   case A##_x:                  \
1492     mnemonic = MN;             \
1493     form = "'Xs, 'Xt, ['Xns]"; \
1494     break;                     \
1495   case A##A_x:                 \
1496     mnemonic = MN "a";         \
1497     form = "'Xs, 'Xt, ['Xns]"; \
1498     break;                     \
1499   case A##L_x:                 \
1500     mnemonic = MN "l";         \
1501     form = "'Xs, 'Xt, ['Xns]"; \
1502     break;                     \
1503   case A##AL_x:                \
1504     mnemonic = MN "al";        \
1505     form = "'Xs, 'Xt, ['Xns]"; \
1506     break;
1507     ATOMIC_MEMORY_SIMPLE_LIST(AMS)
1508 
1509     // SWP has the same semantics as ldadd etc but without the store aliases.
1510     AMS(SWP, "swp")
1511 #undef AMS
1512 
1513     case LDAPRB:
1514       mnemonic = "ldaprb";
1515       form = "'Wt, ['Xns]";
1516       break;
1517     case LDAPRH:
1518       mnemonic = "ldaprh";
1519       form = "'Wt, ['Xns]";
1520       break;
1521     case LDAPR_w:
1522       mnemonic = "ldapr";
1523       form = "'Wt, ['Xns]";
1524       break;
1525     case LDAPR_x:
1526       mnemonic = "ldapr";
1527       form = "'Xt, ['Xns]";
1528       break;
1529     default:
1530       mnemonic = "unimplemented";
1531       form = "(AtomicMemory)";
1532   }
1533 
1534   const char *prefix = "";
1535   switch (instr->Mask(AtomicMemoryMask)) {
1536 #define AMS(A, MN)                   \
1537   case A##AB:                        \
1538   case A##ALB:                       \
1539   case A##AH:                        \
1540   case A##ALH:                       \
1541   case A##A_w:                       \
1542   case A##AL_w:                      \
1543   case A##A_x:                       \
1544   case A##AL_x:                      \
1545     prefix = "ld";                   \
1546     break;                           \
1547   case A##B:                         \
1548   case A##LB:                        \
1549   case A##H:                         \
1550   case A##LH:                        \
1551   case A##_w:                        \
1552   case A##L_w: {                     \
1553     prefix = "ld";                   \
1554     unsigned rt = instr->GetRt();    \
1555     if (Register(rt, 32).IsZero()) { \
1556       prefix = "st";                 \
1557       form = "'Ws, ['Xns]";          \
1558     }                                \
1559     break;                           \
1560   }                                  \
1561   case A##_x:                        \
1562   case A##L_x: {                     \
1563     prefix = "ld";                   \
1564     unsigned rt = instr->GetRt();    \
1565     if (Register(rt, 64).IsZero()) { \
1566       prefix = "st";                 \
1567       form = "'Xs, ['Xns]";          \
1568     }                                \
1569     break;                           \
1570   }
1571     ATOMIC_MEMORY_SIMPLE_LIST(AMS)
1572 #undef AMS
1573   }
1574 
1575   char buffer[kMaxAtomicOpMnemonicLength];
1576   if (strlen(prefix) > 0) {
1577     snprintf(buffer, kMaxAtomicOpMnemonicLength, "%s%s", prefix, mnemonic);
1578     mnemonic = buffer;
1579   }
1580 
1581   Format(instr, mnemonic, form);
1582 }
1583 
1584 
VisitFPCompare(const Instruction * instr)1585 void Disassembler::VisitFPCompare(const Instruction *instr) {
1586   const char *mnemonic = "unimplemented";
1587   const char *form = "'Fn, 'Fm";
1588   const char *form_zero = "'Fn, #0.0";
1589 
1590   switch (instr->Mask(FPCompareMask)) {
1591     case FCMP_h_zero:
1592     case FCMP_s_zero:
1593     case FCMP_d_zero:
1594       form = form_zero;
1595       VIXL_FALLTHROUGH();
1596     case FCMP_h:
1597     case FCMP_s:
1598     case FCMP_d:
1599       mnemonic = "fcmp";
1600       break;
1601     case FCMPE_h_zero:
1602     case FCMPE_s_zero:
1603     case FCMPE_d_zero:
1604       form = form_zero;
1605       VIXL_FALLTHROUGH();
1606     case FCMPE_h:
1607     case FCMPE_s:
1608     case FCMPE_d:
1609       mnemonic = "fcmpe";
1610       break;
1611     default:
1612       form = "(FPCompare)";
1613   }
1614   Format(instr, mnemonic, form);
1615 }
1616 
1617 
VisitFPConditionalCompare(const Instruction * instr)1618 void Disassembler::VisitFPConditionalCompare(const Instruction *instr) {
1619   const char *mnemonic = "unmplemented";
1620   const char *form = "'Fn, 'Fm, 'INzcv, 'Cond";
1621 
1622   switch (instr->Mask(FPConditionalCompareMask)) {
1623     case FCCMP_h:
1624     case FCCMP_s:
1625     case FCCMP_d:
1626       mnemonic = "fccmp";
1627       break;
1628     case FCCMPE_h:
1629     case FCCMPE_s:
1630     case FCCMPE_d:
1631       mnemonic = "fccmpe";
1632       break;
1633     default:
1634       form = "(FPConditionalCompare)";
1635   }
1636   Format(instr, mnemonic, form);
1637 }
1638 
1639 
VisitFPConditionalSelect(const Instruction * instr)1640 void Disassembler::VisitFPConditionalSelect(const Instruction *instr) {
1641   const char *mnemonic = "";
1642   const char *form = "'Fd, 'Fn, 'Fm, 'Cond";
1643 
1644   switch (instr->Mask(FPConditionalSelectMask)) {
1645     case FCSEL_h:
1646     case FCSEL_s:
1647     case FCSEL_d:
1648       mnemonic = "fcsel";
1649       break;
1650     default:
1651       VIXL_UNREACHABLE();
1652   }
1653   Format(instr, mnemonic, form);
1654 }
1655 
1656 
VisitFPDataProcessing1Source(const Instruction * instr)1657 void Disassembler::VisitFPDataProcessing1Source(const Instruction *instr) {
1658   const char *mnemonic = "unimplemented";
1659   const char *form = "'Fd, 'Fn";
1660 
1661   switch (instr->Mask(FPDataProcessing1SourceMask)) {
1662 #define FORMAT(A, B) \
1663   case A##_h:        \
1664   case A##_s:        \
1665   case A##_d:        \
1666     mnemonic = B;    \
1667     break;
1668     FORMAT(FMOV, "fmov");
1669     FORMAT(FABS, "fabs");
1670     FORMAT(FNEG, "fneg");
1671     FORMAT(FSQRT, "fsqrt");
1672     FORMAT(FRINTN, "frintn");
1673     FORMAT(FRINTP, "frintp");
1674     FORMAT(FRINTM, "frintm");
1675     FORMAT(FRINTZ, "frintz");
1676     FORMAT(FRINTA, "frinta");
1677     FORMAT(FRINTX, "frintx");
1678     FORMAT(FRINTI, "frinti");
1679 #undef FORMAT
1680     case FCVT_ds:
1681       mnemonic = "fcvt";
1682       form = "'Dd, 'Sn";
1683       break;
1684     case FCVT_sd:
1685       mnemonic = "fcvt";
1686       form = "'Sd, 'Dn";
1687       break;
1688     case FCVT_hs:
1689       mnemonic = "fcvt";
1690       form = "'Hd, 'Sn";
1691       break;
1692     case FCVT_sh:
1693       mnemonic = "fcvt";
1694       form = "'Sd, 'Hn";
1695       break;
1696     case FCVT_dh:
1697       mnemonic = "fcvt";
1698       form = "'Dd, 'Hn";
1699       break;
1700     case FCVT_hd:
1701       mnemonic = "fcvt";
1702       form = "'Hd, 'Dn";
1703       break;
1704     default:
1705       form = "(FPDataProcessing1Source)";
1706   }
1707   Format(instr, mnemonic, form);
1708 }
1709 
1710 
VisitFPDataProcessing2Source(const Instruction * instr)1711 void Disassembler::VisitFPDataProcessing2Source(const Instruction *instr) {
1712   const char *mnemonic = "";
1713   const char *form = "'Fd, 'Fn, 'Fm";
1714 
1715   switch (instr->Mask(FPDataProcessing2SourceMask)) {
1716 #define FORMAT(A, B) \
1717   case A##_h:        \
1718   case A##_s:        \
1719   case A##_d:        \
1720     mnemonic = B;    \
1721     break;
1722     FORMAT(FADD, "fadd");
1723     FORMAT(FSUB, "fsub");
1724     FORMAT(FMUL, "fmul");
1725     FORMAT(FDIV, "fdiv");
1726     FORMAT(FMAX, "fmax");
1727     FORMAT(FMIN, "fmin");
1728     FORMAT(FMAXNM, "fmaxnm");
1729     FORMAT(FMINNM, "fminnm");
1730     FORMAT(FNMUL, "fnmul");
1731 #undef FORMAT
1732     default:
1733       VIXL_UNREACHABLE();
1734   }
1735   Format(instr, mnemonic, form);
1736 }
1737 
1738 
VisitFPDataProcessing3Source(const Instruction * instr)1739 void Disassembler::VisitFPDataProcessing3Source(const Instruction *instr) {
1740   const char *mnemonic = "";
1741   const char *form = "'Fd, 'Fn, 'Fm, 'Fa";
1742 
1743   switch (instr->Mask(FPDataProcessing3SourceMask)) {
1744 #define FORMAT(A, B) \
1745   case A##_h:        \
1746   case A##_s:        \
1747   case A##_d:        \
1748     mnemonic = B;    \
1749     break;
1750     FORMAT(FMADD, "fmadd");
1751     FORMAT(FMSUB, "fmsub");
1752     FORMAT(FNMADD, "fnmadd");
1753     FORMAT(FNMSUB, "fnmsub");
1754 #undef FORMAT
1755     default:
1756       VIXL_UNREACHABLE();
1757   }
1758   Format(instr, mnemonic, form);
1759 }
1760 
1761 
VisitFPImmediate(const Instruction * instr)1762 void Disassembler::VisitFPImmediate(const Instruction *instr) {
1763   const char *mnemonic = "";
1764   const char *form = "(FPImmediate)";
1765   switch (instr->Mask(FPImmediateMask)) {
1766     case FMOV_h_imm:
1767       mnemonic = "fmov";
1768       form = "'Hd, 'IFPHalf";
1769       break;
1770     case FMOV_s_imm:
1771       mnemonic = "fmov";
1772       form = "'Sd, 'IFPSingle";
1773       break;
1774     case FMOV_d_imm:
1775       mnemonic = "fmov";
1776       form = "'Dd, 'IFPDouble";
1777       break;
1778     default:
1779       VIXL_UNREACHABLE();
1780   }
1781   Format(instr, mnemonic, form);
1782 }
1783 
1784 
VisitFPIntegerConvert(const Instruction * instr)1785 void Disassembler::VisitFPIntegerConvert(const Instruction *instr) {
1786   const char *mnemonic = "unimplemented";
1787   const char *form = "(FPIntegerConvert)";
1788   const char *form_rf = "'Rd, 'Fn";
1789   const char *form_fr = "'Fd, 'Rn";
1790 
1791   switch (instr->Mask(FPIntegerConvertMask)) {
1792     case FMOV_wh:
1793     case FMOV_xh:
1794     case FMOV_ws:
1795     case FMOV_xd:
1796       mnemonic = "fmov";
1797       form = form_rf;
1798       break;
1799     case FMOV_hw:
1800     case FMOV_hx:
1801     case FMOV_sw:
1802     case FMOV_dx:
1803       mnemonic = "fmov";
1804       form = form_fr;
1805       break;
1806     case FMOV_d1_x:
1807       mnemonic = "fmov";
1808       form = "'Vd.D[1], 'Rn";
1809       break;
1810     case FMOV_x_d1:
1811       mnemonic = "fmov";
1812       form = "'Rd, 'Vn.D[1]";
1813       break;
1814     case FCVTAS_wh:
1815     case FCVTAS_xh:
1816     case FCVTAS_ws:
1817     case FCVTAS_xs:
1818     case FCVTAS_wd:
1819     case FCVTAS_xd:
1820       mnemonic = "fcvtas";
1821       form = form_rf;
1822       break;
1823     case FCVTAU_wh:
1824     case FCVTAU_xh:
1825     case FCVTAU_ws:
1826     case FCVTAU_xs:
1827     case FCVTAU_wd:
1828     case FCVTAU_xd:
1829       mnemonic = "fcvtau";
1830       form = form_rf;
1831       break;
1832     case FCVTMS_wh:
1833     case FCVTMS_xh:
1834     case FCVTMS_ws:
1835     case FCVTMS_xs:
1836     case FCVTMS_wd:
1837     case FCVTMS_xd:
1838       mnemonic = "fcvtms";
1839       form = form_rf;
1840       break;
1841     case FCVTMU_wh:
1842     case FCVTMU_xh:
1843     case FCVTMU_ws:
1844     case FCVTMU_xs:
1845     case FCVTMU_wd:
1846     case FCVTMU_xd:
1847       mnemonic = "fcvtmu";
1848       form = form_rf;
1849       break;
1850     case FCVTNS_wh:
1851     case FCVTNS_xh:
1852     case FCVTNS_ws:
1853     case FCVTNS_xs:
1854     case FCVTNS_wd:
1855     case FCVTNS_xd:
1856       mnemonic = "fcvtns";
1857       form = form_rf;
1858       break;
1859     case FCVTNU_wh:
1860     case FCVTNU_xh:
1861     case FCVTNU_ws:
1862     case FCVTNU_xs:
1863     case FCVTNU_wd:
1864     case FCVTNU_xd:
1865       mnemonic = "fcvtnu";
1866       form = form_rf;
1867       break;
1868     case FCVTZU_wh:
1869     case FCVTZU_xh:
1870     case FCVTZU_ws:
1871     case FCVTZU_xs:
1872     case FCVTZU_wd:
1873     case FCVTZU_xd:
1874       mnemonic = "fcvtzu";
1875       form = form_rf;
1876       break;
1877     case FCVTZS_wh:
1878     case FCVTZS_xh:
1879     case FCVTZS_ws:
1880     case FCVTZS_xs:
1881     case FCVTZS_wd:
1882     case FCVTZS_xd:
1883       mnemonic = "fcvtzs";
1884       form = form_rf;
1885       break;
1886     case FCVTPU_wh:
1887     case FCVTPU_xh:
1888     case FCVTPU_xs:
1889     case FCVTPU_wd:
1890     case FCVTPU_ws:
1891     case FCVTPU_xd:
1892       mnemonic = "fcvtpu";
1893       form = form_rf;
1894       break;
1895     case FCVTPS_wh:
1896     case FCVTPS_xh:
1897     case FCVTPS_ws:
1898     case FCVTPS_xs:
1899     case FCVTPS_wd:
1900     case FCVTPS_xd:
1901       mnemonic = "fcvtps";
1902       form = form_rf;
1903       break;
1904     case SCVTF_hw:
1905     case SCVTF_hx:
1906     case SCVTF_sw:
1907     case SCVTF_sx:
1908     case SCVTF_dw:
1909     case SCVTF_dx:
1910       mnemonic = "scvtf";
1911       form = form_fr;
1912       break;
1913     case UCVTF_hw:
1914     case UCVTF_hx:
1915     case UCVTF_sw:
1916     case UCVTF_sx:
1917     case UCVTF_dw:
1918     case UCVTF_dx:
1919       mnemonic = "ucvtf";
1920       form = form_fr;
1921       break;
1922     case FJCVTZS:
1923       mnemonic = "fjcvtzs";
1924       form = form_rf;
1925       break;
1926   }
1927   Format(instr, mnemonic, form);
1928 }
1929 
1930 
VisitFPFixedPointConvert(const Instruction * instr)1931 void Disassembler::VisitFPFixedPointConvert(const Instruction *instr) {
1932   const char *mnemonic = "";
1933   const char *form = "'Rd, 'Fn, 'IFPFBits";
1934   const char *form_fr = "'Fd, 'Rn, 'IFPFBits";
1935 
1936   switch (instr->Mask(FPFixedPointConvertMask)) {
1937     case FCVTZS_wh_fixed:
1938     case FCVTZS_xh_fixed:
1939     case FCVTZS_ws_fixed:
1940     case FCVTZS_xs_fixed:
1941     case FCVTZS_wd_fixed:
1942     case FCVTZS_xd_fixed:
1943       mnemonic = "fcvtzs";
1944       break;
1945     case FCVTZU_wh_fixed:
1946     case FCVTZU_xh_fixed:
1947     case FCVTZU_ws_fixed:
1948     case FCVTZU_xs_fixed:
1949     case FCVTZU_wd_fixed:
1950     case FCVTZU_xd_fixed:
1951       mnemonic = "fcvtzu";
1952       break;
1953     case SCVTF_hw_fixed:
1954     case SCVTF_hx_fixed:
1955     case SCVTF_sw_fixed:
1956     case SCVTF_sx_fixed:
1957     case SCVTF_dw_fixed:
1958     case SCVTF_dx_fixed:
1959       mnemonic = "scvtf";
1960       form = form_fr;
1961       break;
1962     case UCVTF_hw_fixed:
1963     case UCVTF_hx_fixed:
1964     case UCVTF_sw_fixed:
1965     case UCVTF_sx_fixed:
1966     case UCVTF_dw_fixed:
1967     case UCVTF_dx_fixed:
1968       mnemonic = "ucvtf";
1969       form = form_fr;
1970       break;
1971     default:
1972       VIXL_UNREACHABLE();
1973   }
1974   Format(instr, mnemonic, form);
1975 }
1976 
1977 // clang-format off
1978 #define PAUTH_SYSTEM_MNEMONICS(V) \
1979   V(PACIA1716, "pacia1716")       \
1980   V(PACIB1716, "pacib1716")       \
1981   V(AUTIA1716, "autia1716")       \
1982   V(AUTIB1716, "autib1716")       \
1983   V(PACIAZ,    "paciaz")          \
1984   V(PACIASP,   "paciasp")         \
1985   V(PACIBZ,    "pacibz")          \
1986   V(PACIBSP,   "pacibsp")         \
1987   V(AUTIAZ,    "autiaz")          \
1988   V(AUTIASP,   "autiasp")         \
1989   V(AUTIBZ,    "autibz")          \
1990   V(AUTIBSP,   "autibsp")
1991 // clang-format on
1992 
VisitSystem(const Instruction * instr)1993 void Disassembler::VisitSystem(const Instruction *instr) {
1994   // Some system instructions hijack their Op and Cp fields to represent a
1995   // range of immediates instead of indicating a different instruction. This
1996   // makes the decoding tricky.
1997   const char *mnemonic = "unimplemented";
1998   const char *form = "(System)";
1999   if (instr->GetInstructionBits() == XPACLRI) {
2000     mnemonic = "xpaclri";
2001     form = NULL;
2002   } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
2003     switch (instr->Mask(SystemPAuthMask)) {
2004 #define PAUTH_CASE(NAME, MN) \
2005   case NAME:                 \
2006     mnemonic = MN;           \
2007     form = NULL;             \
2008     break;
2009 
2010       PAUTH_SYSTEM_MNEMONICS(PAUTH_CASE)
2011 #undef PAUTH_CASE
2012     }
2013   } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
2014              SystemExclusiveMonitorFixed) {
2015     switch (instr->Mask(SystemExclusiveMonitorMask)) {
2016       case CLREX: {
2017         mnemonic = "clrex";
2018         form = (instr->GetCRm() == 0xf) ? NULL : "'IX";
2019         break;
2020       }
2021     }
2022   } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
2023     switch (instr->Mask(SystemSysRegMask)) {
2024       case MRS: {
2025         mnemonic = "mrs";
2026         form = "'Xt, 'IY";
2027         break;
2028       }
2029       case MSR: {
2030         mnemonic = "msr";
2031         form = "'IY, 'Xt";
2032         break;
2033       }
2034     }
2035   } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
2036     switch (instr->GetImmHint()) {
2037       case NOP: {
2038         form = NULL;
2039         mnemonic = "nop";
2040         break;
2041       }
2042       case YIELD: {
2043         form = NULL;
2044         mnemonic = "yield";
2045         break;
2046       }
2047       case WFE: {
2048         form = NULL;
2049         mnemonic = "wfe";
2050         break;
2051       }
2052       case WFI: {
2053         form = NULL;
2054         mnemonic = "wfi";
2055         break;
2056       }
2057       case SEV: {
2058         form = NULL;
2059         mnemonic = "sev";
2060         break;
2061       }
2062       case SEVL: {
2063         form = NULL;
2064         mnemonic = "sevl";
2065         break;
2066       }
2067       case ESB: {
2068         form = NULL;
2069         mnemonic = "esb";
2070         break;
2071       }
2072       case CSDB: {
2073         form = NULL;
2074         mnemonic = "csdb";
2075         break;
2076       }
2077       default: {
2078         // Fall back to 'hint #<imm7>'.
2079         form = "'IH";
2080         mnemonic = "hint";
2081         break;
2082       }
2083     }
2084   } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
2085     switch (instr->Mask(MemBarrierMask)) {
2086       case DMB: {
2087         mnemonic = "dmb";
2088         form = "'M";
2089         break;
2090       }
2091       case DSB: {
2092         mnemonic = "dsb";
2093         form = "'M";
2094         break;
2095       }
2096       case ISB: {
2097         mnemonic = "isb";
2098         form = NULL;
2099         break;
2100       }
2101     }
2102   } else if (instr->Mask(SystemSysFMask) == SystemSysFixed) {
2103     switch (instr->GetSysOp()) {
2104       case IVAU:
2105         mnemonic = "ic";
2106         form = "ivau, 'Xt";
2107         break;
2108       case CVAC:
2109         mnemonic = "dc";
2110         form = "cvac, 'Xt";
2111         break;
2112       case CVAU:
2113         mnemonic = "dc";
2114         form = "cvau, 'Xt";
2115         break;
2116       case CIVAC:
2117         mnemonic = "dc";
2118         form = "civac, 'Xt";
2119         break;
2120       case ZVA:
2121         mnemonic = "dc";
2122         form = "zva, 'Xt";
2123         break;
2124       default:
2125         mnemonic = "sys";
2126         if (instr->GetRt() == 31) {
2127           form = "'G1, 'Kn, 'Km, 'G2";
2128         } else {
2129           form = "'G1, 'Kn, 'Km, 'G2, 'Xt";
2130         }
2131         break;
2132     }
2133   }
2134   Format(instr, mnemonic, form);
2135 }
2136 
2137 
VisitException(const Instruction * instr)2138 void Disassembler::VisitException(const Instruction *instr) {
2139   const char *mnemonic = "unimplemented";
2140   const char *form = "'IDebug";
2141 
2142   switch (instr->Mask(ExceptionMask)) {
2143     case HLT:
2144       mnemonic = "hlt";
2145       break;
2146     case BRK:
2147       mnemonic = "brk";
2148       break;
2149     case SVC:
2150       mnemonic = "svc";
2151       break;
2152     case HVC:
2153       mnemonic = "hvc";
2154       break;
2155     case SMC:
2156       mnemonic = "smc";
2157       break;
2158     case DCPS1:
2159       mnemonic = "dcps1";
2160       form = "{'IDebug}";
2161       break;
2162     case DCPS2:
2163       mnemonic = "dcps2";
2164       form = "{'IDebug}";
2165       break;
2166     case DCPS3:
2167       mnemonic = "dcps3";
2168       form = "{'IDebug}";
2169       break;
2170     default:
2171       form = "(Exception)";
2172   }
2173   Format(instr, mnemonic, form);
2174 }
2175 
2176 
VisitCrypto2RegSHA(const Instruction * instr)2177 void Disassembler::VisitCrypto2RegSHA(const Instruction *instr) {
2178   VisitUnimplemented(instr);
2179 }
2180 
2181 
VisitCrypto3RegSHA(const Instruction * instr)2182 void Disassembler::VisitCrypto3RegSHA(const Instruction *instr) {
2183   VisitUnimplemented(instr);
2184 }
2185 
2186 
VisitCryptoAES(const Instruction * instr)2187 void Disassembler::VisitCryptoAES(const Instruction *instr) {
2188   VisitUnimplemented(instr);
2189 }
2190 
2191 
VisitNEON2RegMisc(const Instruction * instr)2192 void Disassembler::VisitNEON2RegMisc(const Instruction *instr) {
2193   const char *mnemonic = "unimplemented";
2194   const char *form = "'Vd.%s, 'Vn.%s";
2195   const char *form_cmp_zero = "'Vd.%s, 'Vn.%s, #0";
2196   const char *form_fcmp_zero = "'Vd.%s, 'Vn.%s, #0.0";
2197   NEONFormatDecoder nfd(instr);
2198 
2199   static const NEONFormatMap map_lp_ta =
2200       {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
2201 
2202   static const NEONFormatMap map_cvt_ta = {{22}, {NF_4S, NF_2D}};
2203 
2204   static const NEONFormatMap map_cvt_tb = {{22, 30},
2205                                            {NF_4H, NF_8H, NF_2S, NF_4S}};
2206 
2207   if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
2208     // These instructions all use a two bit size field, except NOT and RBIT,
2209     // which use the field to encode the operation.
2210     switch (instr->Mask(NEON2RegMiscMask)) {
2211       case NEON_REV64:
2212         mnemonic = "rev64";
2213         break;
2214       case NEON_REV32:
2215         mnemonic = "rev32";
2216         break;
2217       case NEON_REV16:
2218         mnemonic = "rev16";
2219         break;
2220       case NEON_SADDLP:
2221         mnemonic = "saddlp";
2222         nfd.SetFormatMap(0, &map_lp_ta);
2223         break;
2224       case NEON_UADDLP:
2225         mnemonic = "uaddlp";
2226         nfd.SetFormatMap(0, &map_lp_ta);
2227         break;
2228       case NEON_SUQADD:
2229         mnemonic = "suqadd";
2230         break;
2231       case NEON_USQADD:
2232         mnemonic = "usqadd";
2233         break;
2234       case NEON_CLS:
2235         mnemonic = "cls";
2236         break;
2237       case NEON_CLZ:
2238         mnemonic = "clz";
2239         break;
2240       case NEON_CNT:
2241         mnemonic = "cnt";
2242         break;
2243       case NEON_SADALP:
2244         mnemonic = "sadalp";
2245         nfd.SetFormatMap(0, &map_lp_ta);
2246         break;
2247       case NEON_UADALP:
2248         mnemonic = "uadalp";
2249         nfd.SetFormatMap(0, &map_lp_ta);
2250         break;
2251       case NEON_SQABS:
2252         mnemonic = "sqabs";
2253         break;
2254       case NEON_SQNEG:
2255         mnemonic = "sqneg";
2256         break;
2257       case NEON_CMGT_zero:
2258         mnemonic = "cmgt";
2259         form = form_cmp_zero;
2260         break;
2261       case NEON_CMGE_zero:
2262         mnemonic = "cmge";
2263         form = form_cmp_zero;
2264         break;
2265       case NEON_CMEQ_zero:
2266         mnemonic = "cmeq";
2267         form = form_cmp_zero;
2268         break;
2269       case NEON_CMLE_zero:
2270         mnemonic = "cmle";
2271         form = form_cmp_zero;
2272         break;
2273       case NEON_CMLT_zero:
2274         mnemonic = "cmlt";
2275         form = form_cmp_zero;
2276         break;
2277       case NEON_ABS:
2278         mnemonic = "abs";
2279         break;
2280       case NEON_NEG:
2281         mnemonic = "neg";
2282         break;
2283       case NEON_RBIT_NOT:
2284         switch (instr->GetFPType()) {
2285           case 0:
2286             mnemonic = "mvn";
2287             break;
2288           case 1:
2289             mnemonic = "rbit";
2290             break;
2291           default:
2292             form = "(NEON2RegMisc)";
2293         }
2294         nfd.SetFormatMaps(nfd.LogicalFormatMap());
2295         break;
2296     }
2297   } else {
2298     // These instructions all use a one bit size field, except XTN, SQXTUN,
2299     // SHLL, SQXTN and UQXTN, which use a two bit size field.
2300     nfd.SetFormatMaps(nfd.FPFormatMap());
2301     switch (instr->Mask(NEON2RegMiscFPMask)) {
2302       case NEON_FABS:
2303         mnemonic = "fabs";
2304         break;
2305       case NEON_FNEG:
2306         mnemonic = "fneg";
2307         break;
2308       case NEON_FCVTN:
2309         mnemonic = instr->Mask(NEON_Q) ? "fcvtn2" : "fcvtn";
2310         nfd.SetFormatMap(0, &map_cvt_tb);
2311         nfd.SetFormatMap(1, &map_cvt_ta);
2312         break;
2313       case NEON_FCVTXN:
2314         mnemonic = instr->Mask(NEON_Q) ? "fcvtxn2" : "fcvtxn";
2315         nfd.SetFormatMap(0, &map_cvt_tb);
2316         nfd.SetFormatMap(1, &map_cvt_ta);
2317         break;
2318       case NEON_FCVTL:
2319         mnemonic = instr->Mask(NEON_Q) ? "fcvtl2" : "fcvtl";
2320         nfd.SetFormatMap(0, &map_cvt_ta);
2321         nfd.SetFormatMap(1, &map_cvt_tb);
2322         break;
2323       case NEON_FRINTN:
2324         mnemonic = "frintn";
2325         break;
2326       case NEON_FRINTA:
2327         mnemonic = "frinta";
2328         break;
2329       case NEON_FRINTP:
2330         mnemonic = "frintp";
2331         break;
2332       case NEON_FRINTM:
2333         mnemonic = "frintm";
2334         break;
2335       case NEON_FRINTX:
2336         mnemonic = "frintx";
2337         break;
2338       case NEON_FRINTZ:
2339         mnemonic = "frintz";
2340         break;
2341       case NEON_FRINTI:
2342         mnemonic = "frinti";
2343         break;
2344       case NEON_FCVTNS:
2345         mnemonic = "fcvtns";
2346         break;
2347       case NEON_FCVTNU:
2348         mnemonic = "fcvtnu";
2349         break;
2350       case NEON_FCVTPS:
2351         mnemonic = "fcvtps";
2352         break;
2353       case NEON_FCVTPU:
2354         mnemonic = "fcvtpu";
2355         break;
2356       case NEON_FCVTMS:
2357         mnemonic = "fcvtms";
2358         break;
2359       case NEON_FCVTMU:
2360         mnemonic = "fcvtmu";
2361         break;
2362       case NEON_FCVTZS:
2363         mnemonic = "fcvtzs";
2364         break;
2365       case NEON_FCVTZU:
2366         mnemonic = "fcvtzu";
2367         break;
2368       case NEON_FCVTAS:
2369         mnemonic = "fcvtas";
2370         break;
2371       case NEON_FCVTAU:
2372         mnemonic = "fcvtau";
2373         break;
2374       case NEON_FSQRT:
2375         mnemonic = "fsqrt";
2376         break;
2377       case NEON_SCVTF:
2378         mnemonic = "scvtf";
2379         break;
2380       case NEON_UCVTF:
2381         mnemonic = "ucvtf";
2382         break;
2383       case NEON_URSQRTE:
2384         mnemonic = "ursqrte";
2385         break;
2386       case NEON_URECPE:
2387         mnemonic = "urecpe";
2388         break;
2389       case NEON_FRSQRTE:
2390         mnemonic = "frsqrte";
2391         break;
2392       case NEON_FRECPE:
2393         mnemonic = "frecpe";
2394         break;
2395       case NEON_FCMGT_zero:
2396         mnemonic = "fcmgt";
2397         form = form_fcmp_zero;
2398         break;
2399       case NEON_FCMGE_zero:
2400         mnemonic = "fcmge";
2401         form = form_fcmp_zero;
2402         break;
2403       case NEON_FCMEQ_zero:
2404         mnemonic = "fcmeq";
2405         form = form_fcmp_zero;
2406         break;
2407       case NEON_FCMLE_zero:
2408         mnemonic = "fcmle";
2409         form = form_fcmp_zero;
2410         break;
2411       case NEON_FCMLT_zero:
2412         mnemonic = "fcmlt";
2413         form = form_fcmp_zero;
2414         break;
2415       default:
2416         if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
2417             (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
2418           nfd.SetFormatMap(0, nfd.IntegerFormatMap());
2419           nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
2420 
2421           switch (instr->Mask(NEON2RegMiscMask)) {
2422             case NEON_XTN:
2423               mnemonic = "xtn";
2424               break;
2425             case NEON_SQXTN:
2426               mnemonic = "sqxtn";
2427               break;
2428             case NEON_UQXTN:
2429               mnemonic = "uqxtn";
2430               break;
2431             case NEON_SQXTUN:
2432               mnemonic = "sqxtun";
2433               break;
2434             case NEON_SHLL:
2435               mnemonic = "shll";
2436               nfd.SetFormatMap(0, nfd.LongIntegerFormatMap());
2437               nfd.SetFormatMap(1, nfd.IntegerFormatMap());
2438               switch (instr->GetNEONSize()) {
2439                 case 0:
2440                   form = "'Vd.%s, 'Vn.%s, #8";
2441                   break;
2442                 case 1:
2443                   form = "'Vd.%s, 'Vn.%s, #16";
2444                   break;
2445                 case 2:
2446                   form = "'Vd.%s, 'Vn.%s, #32";
2447                   break;
2448                 default:
2449                   Format(instr, "unallocated", "(NEON2RegMisc)");
2450                   return;
2451               }
2452           }
2453           Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
2454           return;
2455         } else {
2456           form = "(NEON2RegMisc)";
2457         }
2458     }
2459   }
2460   Format(instr, mnemonic, nfd.Substitute(form));
2461 }
2462 
VisitNEON2RegMiscFP16(const Instruction * instr)2463 void Disassembler::VisitNEON2RegMiscFP16(const Instruction *instr) {
2464   const char *mnemonic = "unimplemented";
2465   const char *form = "'Vd.%s, 'Vn.%s";
2466   const char *form_cmp = "'Vd.%s, 'Vn.%s, #0.0";
2467 
2468   static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
2469   NEONFormatDecoder nfd(instr, &map_half);
2470 
2471   switch (instr->Mask(NEON2RegMiscFP16Mask)) {
2472 // clang-format off
2473 #define FORMAT(A, B) \
2474   case NEON_##A##_H: \
2475     mnemonic = B;    \
2476     break;
2477     FORMAT(FABS,    "fabs")
2478     FORMAT(FCVTAS,  "fcvtas")
2479     FORMAT(FCVTAU,  "fcvtau")
2480     FORMAT(FCVTMS,  "fcvtms")
2481     FORMAT(FCVTMU,  "fcvtmu")
2482     FORMAT(FCVTNS,  "fcvtns")
2483     FORMAT(FCVTNU,  "fcvtnu")
2484     FORMAT(FCVTPS,  "fcvtps")
2485     FORMAT(FCVTPU,  "fcvtpu")
2486     FORMAT(FCVTZS,  "fcvtzs")
2487     FORMAT(FCVTZU,  "fcvtzu")
2488     FORMAT(FNEG,    "fneg")
2489     FORMAT(FRECPE,  "frecpe")
2490     FORMAT(FRINTA,  "frinta")
2491     FORMAT(FRINTI,  "frinti")
2492     FORMAT(FRINTM,  "frintm")
2493     FORMAT(FRINTN,  "frintn")
2494     FORMAT(FRINTP,  "frintp")
2495     FORMAT(FRINTX,  "frintx")
2496     FORMAT(FRINTZ,  "frintz")
2497     FORMAT(FRSQRTE, "frsqrte")
2498     FORMAT(FSQRT,   "fsqrt")
2499     FORMAT(SCVTF,   "scvtf")
2500     FORMAT(UCVTF,   "ucvtf")
2501 // clang-format on
2502 #undef FORMAT
2503 
2504     case NEON_FCMEQ_H_zero:
2505       mnemonic = "fcmeq";
2506       form = form_cmp;
2507       break;
2508     case NEON_FCMGT_H_zero:
2509       mnemonic = "fcmgt";
2510       form = form_cmp;
2511       break;
2512     case NEON_FCMGE_H_zero:
2513       mnemonic = "fcmge";
2514       form = form_cmp;
2515       break;
2516     case NEON_FCMLT_H_zero:
2517       mnemonic = "fcmlt";
2518       form = form_cmp;
2519       break;
2520     case NEON_FCMLE_H_zero:
2521       mnemonic = "fcmle";
2522       form = form_cmp;
2523       break;
2524     default:
2525       form = "(NEON2RegMiscFP16)";
2526   }
2527   Format(instr, mnemonic, nfd.Substitute(form));
2528 }
2529 
2530 
VisitNEON3Same(const Instruction * instr)2531 void Disassembler::VisitNEON3Same(const Instruction *instr) {
2532   const char *mnemonic = "unimplemented";
2533   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
2534   NEONFormatDecoder nfd(instr);
2535 
2536   if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
2537     switch (instr->Mask(NEON3SameLogicalMask)) {
2538       case NEON_AND:
2539         mnemonic = "and";
2540         break;
2541       case NEON_ORR:
2542         mnemonic = "orr";
2543         if (instr->GetRm() == instr->GetRn()) {
2544           mnemonic = "mov";
2545           form = "'Vd.%s, 'Vn.%s";
2546         }
2547         break;
2548       case NEON_ORN:
2549         mnemonic = "orn";
2550         break;
2551       case NEON_EOR:
2552         mnemonic = "eor";
2553         break;
2554       case NEON_BIC:
2555         mnemonic = "bic";
2556         break;
2557       case NEON_BIF:
2558         mnemonic = "bif";
2559         break;
2560       case NEON_BIT:
2561         mnemonic = "bit";
2562         break;
2563       case NEON_BSL:
2564         mnemonic = "bsl";
2565         break;
2566       default:
2567         form = "(NEON3Same)";
2568     }
2569     nfd.SetFormatMaps(nfd.LogicalFormatMap());
2570   } else {
2571     static const char *mnemonics[] = {"shadd",
2572                                       "uhadd",
2573                                       "shadd",
2574                                       "uhadd",
2575                                       "sqadd",
2576                                       "uqadd",
2577                                       "sqadd",
2578                                       "uqadd",
2579                                       "srhadd",
2580                                       "urhadd",
2581                                       "srhadd",
2582                                       "urhadd",
2583                                       // Handled by logical cases above.
2584                                       NULL,
2585                                       NULL,
2586                                       NULL,
2587                                       NULL,
2588                                       "shsub",
2589                                       "uhsub",
2590                                       "shsub",
2591                                       "uhsub",
2592                                       "sqsub",
2593                                       "uqsub",
2594                                       "sqsub",
2595                                       "uqsub",
2596                                       "cmgt",
2597                                       "cmhi",
2598                                       "cmgt",
2599                                       "cmhi",
2600                                       "cmge",
2601                                       "cmhs",
2602                                       "cmge",
2603                                       "cmhs",
2604                                       "sshl",
2605                                       "ushl",
2606                                       "sshl",
2607                                       "ushl",
2608                                       "sqshl",
2609                                       "uqshl",
2610                                       "sqshl",
2611                                       "uqshl",
2612                                       "srshl",
2613                                       "urshl",
2614                                       "srshl",
2615                                       "urshl",
2616                                       "sqrshl",
2617                                       "uqrshl",
2618                                       "sqrshl",
2619                                       "uqrshl",
2620                                       "smax",
2621                                       "umax",
2622                                       "smax",
2623                                       "umax",
2624                                       "smin",
2625                                       "umin",
2626                                       "smin",
2627                                       "umin",
2628                                       "sabd",
2629                                       "uabd",
2630                                       "sabd",
2631                                       "uabd",
2632                                       "saba",
2633                                       "uaba",
2634                                       "saba",
2635                                       "uaba",
2636                                       "add",
2637                                       "sub",
2638                                       "add",
2639                                       "sub",
2640                                       "cmtst",
2641                                       "cmeq",
2642                                       "cmtst",
2643                                       "cmeq",
2644                                       "mla",
2645                                       "mls",
2646                                       "mla",
2647                                       "mls",
2648                                       "mul",
2649                                       "pmul",
2650                                       "mul",
2651                                       "pmul",
2652                                       "smaxp",
2653                                       "umaxp",
2654                                       "smaxp",
2655                                       "umaxp",
2656                                       "sminp",
2657                                       "uminp",
2658                                       "sminp",
2659                                       "uminp",
2660                                       "sqdmulh",
2661                                       "sqrdmulh",
2662                                       "sqdmulh",
2663                                       "sqrdmulh",
2664                                       "addp",
2665                                       "unallocated",
2666                                       "addp",
2667                                       "unallocated",
2668                                       "fmaxnm",
2669                                       "fmaxnmp",
2670                                       "fminnm",
2671                                       "fminnmp",
2672                                       "fmla",
2673                                       "unallocated",
2674                                       "fmls",
2675                                       "unallocated",
2676                                       "fadd",
2677                                       "faddp",
2678                                       "fsub",
2679                                       "fabd",
2680                                       "fmulx",
2681                                       "fmul",
2682                                       "unallocated",
2683                                       "unallocated",
2684                                       "fcmeq",
2685                                       "fcmge",
2686                                       "unallocated",
2687                                       "fcmgt",
2688                                       "unallocated",
2689                                       "facge",
2690                                       "unallocated",
2691                                       "facgt",
2692                                       "fmax",
2693                                       "fmaxp",
2694                                       "fmin",
2695                                       "fminp",
2696                                       "frecps",
2697                                       "fdiv",
2698                                       "frsqrts",
2699                                       "unallocated"};
2700 
2701     // Operation is determined by the opcode bits (15-11), the top bit of
2702     // size (23) and the U bit (29).
2703     unsigned index = (instr->ExtractBits(15, 11) << 2) |
2704                      (instr->ExtractBit(23) << 1) | instr->ExtractBit(29);
2705     VIXL_ASSERT(index < ArrayLength(mnemonics));
2706     mnemonic = mnemonics[index];
2707     // Assert that index is not one of the previously handled logical
2708     // instructions.
2709     VIXL_ASSERT(mnemonic != NULL);
2710 
2711     if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
2712       nfd.SetFormatMaps(nfd.FPFormatMap());
2713     }
2714   }
2715   Format(instr, mnemonic, nfd.Substitute(form));
2716 }
2717 
VisitNEON3SameFP16(const Instruction * instr)2718 void Disassembler::VisitNEON3SameFP16(const Instruction *instr) {
2719   const char *mnemonic = "unimplemented";
2720   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
2721 
2722   NEONFormatDecoder nfd(instr);
2723   nfd.SetFormatMaps(nfd.FP16FormatMap());
2724 
2725   switch (instr->Mask(NEON3SameFP16Mask)) {
2726 #define FORMAT(A, B) \
2727   case NEON_##A##_H: \
2728     mnemonic = B;    \
2729     break;
2730     FORMAT(FMAXNM, "fmaxnm");
2731     FORMAT(FMLA, "fmla");
2732     FORMAT(FADD, "fadd");
2733     FORMAT(FMULX, "fmulx");
2734     FORMAT(FCMEQ, "fcmeq");
2735     FORMAT(FMAX, "fmax");
2736     FORMAT(FRECPS, "frecps");
2737     FORMAT(FMINNM, "fminnm");
2738     FORMAT(FMLS, "fmls");
2739     FORMAT(FSUB, "fsub");
2740     FORMAT(FMIN, "fmin");
2741     FORMAT(FRSQRTS, "frsqrts");
2742     FORMAT(FMAXNMP, "fmaxnmp");
2743     FORMAT(FADDP, "faddp");
2744     FORMAT(FMUL, "fmul");
2745     FORMAT(FCMGE, "fcmge");
2746     FORMAT(FACGE, "facge");
2747     FORMAT(FMAXP, "fmaxp");
2748     FORMAT(FDIV, "fdiv");
2749     FORMAT(FMINNMP, "fminnmp");
2750     FORMAT(FABD, "fabd");
2751     FORMAT(FCMGT, "fcmgt");
2752     FORMAT(FACGT, "facgt");
2753     FORMAT(FMINP, "fminp");
2754 #undef FORMAT
2755     default:
2756       form = "(NEON3SameFP16)";
2757   }
2758 
2759   Format(instr, mnemonic, nfd.Substitute(form));
2760 }
2761 
VisitNEON3SameExtra(const Instruction * instr)2762 void Disassembler::VisitNEON3SameExtra(const Instruction *instr) {
2763   static const NEONFormatMap map_usdot = {{30}, {NF_8B, NF_16B}};
2764 
2765   const char *mnemonic = "unallocated";
2766   const char *form = "(NEON3SameExtra)";
2767 
2768   NEONFormatDecoder nfd(instr);
2769 
2770   if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
2771     mnemonic = "fcmla";
2772     form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVFCNM";
2773   } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
2774     mnemonic = "fcadd";
2775     form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVFCNA";
2776   } else {
2777     form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
2778     switch (instr->Mask(NEON3SameExtraMask)) {
2779       case NEON_SDOT:
2780         mnemonic = "sdot";
2781         nfd.SetFormatMap(1, &map_usdot);
2782         nfd.SetFormatMap(2, &map_usdot);
2783         break;
2784       case NEON_SQRDMLAH:
2785         mnemonic = "sqrdmlah";
2786         break;
2787       case NEON_UDOT:
2788         mnemonic = "udot";
2789         nfd.SetFormatMap(1, &map_usdot);
2790         nfd.SetFormatMap(2, &map_usdot);
2791         break;
2792       case NEON_SQRDMLSH:
2793         mnemonic = "sqrdmlsh";
2794         break;
2795     }
2796   }
2797 
2798   Format(instr, mnemonic, nfd.Substitute(form));
2799 }
2800 
2801 
VisitNEON3Different(const Instruction * instr)2802 void Disassembler::VisitNEON3Different(const Instruction *instr) {
2803   const char *mnemonic = "unimplemented";
2804   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
2805 
2806   NEONFormatDecoder nfd(instr);
2807   nfd.SetFormatMap(0, nfd.LongIntegerFormatMap());
2808 
2809   // Ignore the Q bit. Appending a "2" suffix is handled later.
2810   switch (instr->Mask(NEON3DifferentMask) & ~NEON_Q) {
2811     case NEON_PMULL:
2812       mnemonic = "pmull";
2813       break;
2814     case NEON_SABAL:
2815       mnemonic = "sabal";
2816       break;
2817     case NEON_SABDL:
2818       mnemonic = "sabdl";
2819       break;
2820     case NEON_SADDL:
2821       mnemonic = "saddl";
2822       break;
2823     case NEON_SMLAL:
2824       mnemonic = "smlal";
2825       break;
2826     case NEON_SMLSL:
2827       mnemonic = "smlsl";
2828       break;
2829     case NEON_SMULL:
2830       mnemonic = "smull";
2831       break;
2832     case NEON_SSUBL:
2833       mnemonic = "ssubl";
2834       break;
2835     case NEON_SQDMLAL:
2836       mnemonic = "sqdmlal";
2837       break;
2838     case NEON_SQDMLSL:
2839       mnemonic = "sqdmlsl";
2840       break;
2841     case NEON_SQDMULL:
2842       mnemonic = "sqdmull";
2843       break;
2844     case NEON_UABAL:
2845       mnemonic = "uabal";
2846       break;
2847     case NEON_UABDL:
2848       mnemonic = "uabdl";
2849       break;
2850     case NEON_UADDL:
2851       mnemonic = "uaddl";
2852       break;
2853     case NEON_UMLAL:
2854       mnemonic = "umlal";
2855       break;
2856     case NEON_UMLSL:
2857       mnemonic = "umlsl";
2858       break;
2859     case NEON_UMULL:
2860       mnemonic = "umull";
2861       break;
2862     case NEON_USUBL:
2863       mnemonic = "usubl";
2864       break;
2865     case NEON_SADDW:
2866       mnemonic = "saddw";
2867       nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
2868       break;
2869     case NEON_SSUBW:
2870       mnemonic = "ssubw";
2871       nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
2872       break;
2873     case NEON_UADDW:
2874       mnemonic = "uaddw";
2875       nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
2876       break;
2877     case NEON_USUBW:
2878       mnemonic = "usubw";
2879       nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
2880       break;
2881     case NEON_ADDHN:
2882       mnemonic = "addhn";
2883       nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
2884       nfd.SetFormatMap(0, nfd.IntegerFormatMap());
2885       break;
2886     case NEON_RADDHN:
2887       mnemonic = "raddhn";
2888       nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
2889       nfd.SetFormatMap(0, nfd.IntegerFormatMap());
2890       break;
2891     case NEON_RSUBHN:
2892       mnemonic = "rsubhn";
2893       nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
2894       nfd.SetFormatMap(0, nfd.IntegerFormatMap());
2895       break;
2896     case NEON_SUBHN:
2897       mnemonic = "subhn";
2898       nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
2899       nfd.SetFormatMap(0, nfd.IntegerFormatMap());
2900       break;
2901     default:
2902       form = "(NEON3Different)";
2903   }
2904   Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
2905 }
2906 
2907 
VisitNEONAcrossLanes(const Instruction * instr)2908 void Disassembler::VisitNEONAcrossLanes(const Instruction *instr) {
2909   const char *mnemonic = "unimplemented";
2910   const char *form = "%sd, 'Vn.%s";
2911   const char *form_half = "'Hd, 'Vn.%s";
2912   bool half_op = false;
2913   static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
2914 
2915   NEONFormatDecoder nfd(instr,
2916                         NEONFormatDecoder::ScalarFormatMap(),
2917                         NEONFormatDecoder::IntegerFormatMap());
2918 
2919   if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
2920     half_op = true;
2921     form = form_half;
2922     nfd.SetFormatMaps(&map_half);
2923     switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
2924       case NEON_FMAXV_H:
2925         mnemonic = "fmaxv";
2926         break;
2927       case NEON_FMINV_H:
2928         mnemonic = "fminv";
2929         break;
2930       case NEON_FMAXNMV_H:
2931         mnemonic = "fmaxnmv";
2932         break;
2933       case NEON_FMINNMV_H:
2934         mnemonic = "fminnmv";
2935         break;
2936     }
2937   } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
2938     nfd.SetFormatMap(0, nfd.FPScalarFormatMap());
2939     nfd.SetFormatMap(1, nfd.FPFormatMap());
2940     switch (instr->Mask(NEONAcrossLanesFPMask)) {
2941       case NEON_FMAXV:
2942         mnemonic = "fmaxv";
2943         break;
2944       case NEON_FMINV:
2945         mnemonic = "fminv";
2946         break;
2947       case NEON_FMAXNMV:
2948         mnemonic = "fmaxnmv";
2949         break;
2950       case NEON_FMINNMV:
2951         mnemonic = "fminnmv";
2952         break;
2953       default:
2954         form = "(NEONAcrossLanes)";
2955         break;
2956     }
2957   } else if (instr->Mask(NEONAcrossLanesFMask) == NEONAcrossLanesFixed) {
2958     switch (instr->Mask(NEONAcrossLanesMask)) {
2959       case NEON_ADDV:
2960         mnemonic = "addv";
2961         break;
2962       case NEON_SMAXV:
2963         mnemonic = "smaxv";
2964         break;
2965       case NEON_SMINV:
2966         mnemonic = "sminv";
2967         break;
2968       case NEON_UMAXV:
2969         mnemonic = "umaxv";
2970         break;
2971       case NEON_UMINV:
2972         mnemonic = "uminv";
2973         break;
2974       case NEON_SADDLV:
2975         mnemonic = "saddlv";
2976         nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
2977         break;
2978       case NEON_UADDLV:
2979         mnemonic = "uaddlv";
2980         nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
2981         break;
2982       default:
2983         form = "(NEONAcrossLanes)";
2984         break;
2985     }
2986   }
2987 
2988   if (half_op) {
2989     Format(instr, mnemonic, nfd.Substitute(form));
2990   } else {
2991     Format(instr,
2992            mnemonic,
2993            nfd.Substitute(form,
2994                           NEONFormatDecoder::kPlaceholder,
2995                           NEONFormatDecoder::kFormat));
2996   }
2997 }
2998 
2999 
VisitNEONByIndexedElement(const Instruction * instr)3000 void Disassembler::VisitNEONByIndexedElement(const Instruction *instr) {
3001   const char *mnemonic = "unimplemented";
3002   bool l_instr = false;
3003   bool fp_instr = false;
3004   bool cn_instr = false;
3005   bool half_instr = false;
3006 
3007   const char *form = "'Vd.%s, 'Vn.%s, 'Ve.%s['IVByElemIndex]";
3008 
3009   static const NEONFormatMap map_ta = {{23, 22}, {NF_UNDEF, NF_4S, NF_2D}};
3010   static const NEONFormatMap map_cn =
3011       {{23, 22, 30},
3012        {NF_UNDEF, NF_UNDEF, NF_4H, NF_8H, NF_UNDEF, NF_4S, NF_UNDEF, NF_UNDEF}};
3013   static const NEONFormatMap map_usdot = {{30}, {NF_8B, NF_16B}};
3014   static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
3015 
3016   NEONFormatDecoder nfd(instr,
3017                         &map_ta,
3018                         NEONFormatDecoder::IntegerFormatMap(),
3019                         NEONFormatDecoder::ScalarFormatMap());
3020 
3021   switch (instr->Mask(NEONByIndexedElementMask)) {
3022     case NEON_SMULL_byelement:
3023       mnemonic = "smull";
3024       l_instr = true;
3025       break;
3026     case NEON_UMULL_byelement:
3027       mnemonic = "umull";
3028       l_instr = true;
3029       break;
3030     case NEON_SMLAL_byelement:
3031       mnemonic = "smlal";
3032       l_instr = true;
3033       break;
3034     case NEON_UMLAL_byelement:
3035       mnemonic = "umlal";
3036       l_instr = true;
3037       break;
3038     case NEON_SMLSL_byelement:
3039       mnemonic = "smlsl";
3040       l_instr = true;
3041       break;
3042     case NEON_UMLSL_byelement:
3043       mnemonic = "umlsl";
3044       l_instr = true;
3045       break;
3046     case NEON_SQDMULL_byelement:
3047       mnemonic = "sqdmull";
3048       l_instr = true;
3049       break;
3050     case NEON_SQDMLAL_byelement:
3051       mnemonic = "sqdmlal";
3052       l_instr = true;
3053       break;
3054     case NEON_SQDMLSL_byelement:
3055       mnemonic = "sqdmlsl";
3056       l_instr = true;
3057       break;
3058     case NEON_MUL_byelement:
3059       mnemonic = "mul";
3060       break;
3061     case NEON_MLA_byelement:
3062       mnemonic = "mla";
3063       break;
3064     case NEON_MLS_byelement:
3065       mnemonic = "mls";
3066       break;
3067     case NEON_SQDMULH_byelement:
3068       mnemonic = "sqdmulh";
3069       break;
3070     case NEON_SQRDMULH_byelement:
3071       mnemonic = "sqrdmulh";
3072       break;
3073     case NEON_SDOT_byelement:
3074       mnemonic = "sdot";
3075       form = "'Vd.%s, 'Vn.%s, 'Ve.4b['IVByElemIndex]";
3076       nfd.SetFormatMap(1, &map_usdot);
3077       break;
3078     case NEON_SQRDMLAH_byelement:
3079       mnemonic = "sqrdmlah";
3080       break;
3081     case NEON_UDOT_byelement:
3082       mnemonic = "udot";
3083       form = "'Vd.%s, 'Vn.%s, 'Ve.4b['IVByElemIndex]";
3084       nfd.SetFormatMap(1, &map_usdot);
3085       break;
3086     case NEON_SQRDMLSH_byelement:
3087       mnemonic = "sqrdmlsh";
3088       break;
3089     default:
3090       switch (instr->Mask(NEONByIndexedElementFPMask)) {
3091         case NEON_FMUL_byelement:
3092           mnemonic = "fmul";
3093           fp_instr = true;
3094           break;
3095         case NEON_FMLA_byelement:
3096           mnemonic = "fmla";
3097           fp_instr = true;
3098           break;
3099         case NEON_FMLS_byelement:
3100           mnemonic = "fmls";
3101           fp_instr = true;
3102           break;
3103         case NEON_FMULX_byelement:
3104           mnemonic = "fmulx";
3105           fp_instr = true;
3106           break;
3107         case NEON_FMLA_H_byelement:
3108           mnemonic = "fmla";
3109           half_instr = true;
3110           break;
3111         case NEON_FMLS_H_byelement:
3112           mnemonic = "fmls";
3113           half_instr = true;
3114           break;
3115         case NEON_FMUL_H_byelement:
3116           mnemonic = "fmul";
3117           half_instr = true;
3118           break;
3119         case NEON_FMULX_H_byelement:
3120           mnemonic = "fmulx";
3121           half_instr = true;
3122           break;
3123         default:
3124           switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
3125             case NEON_FCMLA_byelement:
3126               mnemonic = "fcmla";
3127               cn_instr = true;
3128               form = "'Vd.%s, 'Vn.%s, 'Ve.%s['IVByElemIndexRot], 'ILFCNR";
3129               break;
3130           }
3131       }
3132   }
3133 
3134   if (half_instr) {
3135     form = "'Vd.%s, 'Vn.%s, 'Ve.h['IVByElemIndex]";
3136     nfd.SetFormatMaps(&map_half, &map_half);
3137     Format(instr, mnemonic, nfd.Substitute(form));
3138   } else if (l_instr) {
3139     Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
3140   } else if (fp_instr) {
3141     nfd.SetFormatMap(0, nfd.FPFormatMap());
3142     Format(instr, mnemonic, nfd.Substitute(form));
3143   } else if (cn_instr) {
3144     nfd.SetFormatMap(0, &map_cn);
3145     nfd.SetFormatMap(1, &map_cn);
3146     Format(instr, mnemonic, nfd.Substitute(form));
3147   } else {
3148     nfd.SetFormatMap(0, nfd.IntegerFormatMap());
3149     Format(instr, mnemonic, nfd.Substitute(form));
3150   }
3151 }
3152 
3153 
VisitNEONCopy(const Instruction * instr)3154 void Disassembler::VisitNEONCopy(const Instruction *instr) {
3155   const char *mnemonic = "unimplemented";
3156   const char *form = "(NEONCopy)";
3157 
3158   NEONFormatDecoder nfd(instr,
3159                         NEONFormatDecoder::TriangularFormatMap(),
3160                         NEONFormatDecoder::TriangularScalarFormatMap());
3161 
3162   if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
3163     mnemonic = "mov";
3164     nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
3165     form = "'Vd.%s['IVInsIndex1], 'Vn.%s['IVInsIndex2]";
3166   } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
3167     mnemonic = "mov";
3168     nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
3169     if (nfd.GetVectorFormat() == kFormatD) {
3170       form = "'Vd.%s['IVInsIndex1], 'Xn";
3171     } else {
3172       form = "'Vd.%s['IVInsIndex1], 'Wn";
3173     }
3174   } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
3175     if (instr->Mask(NEON_Q) || ((instr->GetImmNEON5() & 7) == 4)) {
3176       mnemonic = "mov";
3177     } else {
3178       mnemonic = "umov";
3179     }
3180     nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
3181     if (nfd.GetVectorFormat() == kFormatD) {
3182       form = "'Xd, 'Vn.%s['IVInsIndex1]";
3183     } else {
3184       form = "'Wd, 'Vn.%s['IVInsIndex1]";
3185     }
3186   } else if (instr->Mask(NEONCopySmovMask) == NEON_SMOV) {
3187     mnemonic = "smov";
3188     nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
3189     form = "'Rdq, 'Vn.%s['IVInsIndex1]";
3190   } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
3191     mnemonic = "dup";
3192     form = "'Vd.%s, 'Vn.%s['IVInsIndex1]";
3193   } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
3194     mnemonic = "dup";
3195     if (nfd.GetVectorFormat() == kFormat2D) {
3196       form = "'Vd.%s, 'Xn";
3197     } else {
3198       form = "'Vd.%s, 'Wn";
3199     }
3200   }
3201   Format(instr, mnemonic, nfd.Substitute(form));
3202 }
3203 
3204 
VisitNEONExtract(const Instruction * instr)3205 void Disassembler::VisitNEONExtract(const Instruction *instr) {
3206   const char *mnemonic = "unimplemented";
3207   const char *form = "(NEONExtract)";
3208   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
3209   if (instr->Mask(NEONExtractMask) == NEON_EXT) {
3210     mnemonic = "ext";
3211     form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVExtract";
3212   }
3213   Format(instr, mnemonic, nfd.Substitute(form));
3214 }
3215 
3216 
VisitNEONLoadStoreMultiStruct(const Instruction * instr)3217 void Disassembler::VisitNEONLoadStoreMultiStruct(const Instruction *instr) {
3218   const char *mnemonic = NULL;
3219   const char *form = NULL;
3220   const char *form_1v = "{'Vt.%1$s}, ['Xns]";
3221   const char *form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns]";
3222   const char *form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns]";
3223   const char *form_4v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]";
3224   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3225 
3226   switch (instr->Mask(NEONLoadStoreMultiStructMask)) {
3227     case NEON_LD1_1v:
3228       mnemonic = "ld1";
3229       form = form_1v;
3230       break;
3231     case NEON_LD1_2v:
3232       mnemonic = "ld1";
3233       form = form_2v;
3234       break;
3235     case NEON_LD1_3v:
3236       mnemonic = "ld1";
3237       form = form_3v;
3238       break;
3239     case NEON_LD1_4v:
3240       mnemonic = "ld1";
3241       form = form_4v;
3242       break;
3243     case NEON_LD2:
3244       mnemonic = "ld2";
3245       form = form_2v;
3246       break;
3247     case NEON_LD3:
3248       mnemonic = "ld3";
3249       form = form_3v;
3250       break;
3251     case NEON_LD4:
3252       mnemonic = "ld4";
3253       form = form_4v;
3254       break;
3255     case NEON_ST1_1v:
3256       mnemonic = "st1";
3257       form = form_1v;
3258       break;
3259     case NEON_ST1_2v:
3260       mnemonic = "st1";
3261       form = form_2v;
3262       break;
3263     case NEON_ST1_3v:
3264       mnemonic = "st1";
3265       form = form_3v;
3266       break;
3267     case NEON_ST1_4v:
3268       mnemonic = "st1";
3269       form = form_4v;
3270       break;
3271     case NEON_ST2:
3272       mnemonic = "st2";
3273       form = form_2v;
3274       break;
3275     case NEON_ST3:
3276       mnemonic = "st3";
3277       form = form_3v;
3278       break;
3279     case NEON_ST4:
3280       mnemonic = "st4";
3281       form = form_4v;
3282       break;
3283     default:
3284       break;
3285   }
3286 
3287   // Work out unallocated encodings.
3288   bool allocated = (mnemonic != NULL);
3289   switch (instr->Mask(NEONLoadStoreMultiStructMask)) {
3290     case NEON_LD2:
3291     case NEON_LD3:
3292     case NEON_LD4:
3293     case NEON_ST2:
3294     case NEON_ST3:
3295     case NEON_ST4:
3296       // LD[2-4] and ST[2-4] cannot use .1d format.
3297       allocated = (instr->GetNEONQ() != 0) || (instr->GetNEONLSSize() != 3);
3298       break;
3299     default:
3300       break;
3301   }
3302   if (allocated) {
3303     VIXL_ASSERT(mnemonic != NULL);
3304     VIXL_ASSERT(form != NULL);
3305   } else {
3306     mnemonic = "unallocated";
3307     form = "(NEONLoadStoreMultiStruct)";
3308   }
3309 
3310   Format(instr, mnemonic, nfd.Substitute(form));
3311 }
3312 
3313 
VisitNEONLoadStoreMultiStructPostIndex(const Instruction * instr)3314 void Disassembler::VisitNEONLoadStoreMultiStructPostIndex(
3315     const Instruction *instr) {
3316   const char *mnemonic = NULL;
3317   const char *form = NULL;
3318   const char *form_1v = "{'Vt.%1$s}, ['Xns], 'Xmr1";
3319   const char *form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns], 'Xmr2";
3320   const char *form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns], 'Xmr3";
3321   const char *form_4v =
3322       "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmr4";
3323   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3324 
3325   switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
3326     case NEON_LD1_1v_post:
3327       mnemonic = "ld1";
3328       form = form_1v;
3329       break;
3330     case NEON_LD1_2v_post:
3331       mnemonic = "ld1";
3332       form = form_2v;
3333       break;
3334     case NEON_LD1_3v_post:
3335       mnemonic = "ld1";
3336       form = form_3v;
3337       break;
3338     case NEON_LD1_4v_post:
3339       mnemonic = "ld1";
3340       form = form_4v;
3341       break;
3342     case NEON_LD2_post:
3343       mnemonic = "ld2";
3344       form = form_2v;
3345       break;
3346     case NEON_LD3_post:
3347       mnemonic = "ld3";
3348       form = form_3v;
3349       break;
3350     case NEON_LD4_post:
3351       mnemonic = "ld4";
3352       form = form_4v;
3353       break;
3354     case NEON_ST1_1v_post:
3355       mnemonic = "st1";
3356       form = form_1v;
3357       break;
3358     case NEON_ST1_2v_post:
3359       mnemonic = "st1";
3360       form = form_2v;
3361       break;
3362     case NEON_ST1_3v_post:
3363       mnemonic = "st1";
3364       form = form_3v;
3365       break;
3366     case NEON_ST1_4v_post:
3367       mnemonic = "st1";
3368       form = form_4v;
3369       break;
3370     case NEON_ST2_post:
3371       mnemonic = "st2";
3372       form = form_2v;
3373       break;
3374     case NEON_ST3_post:
3375       mnemonic = "st3";
3376       form = form_3v;
3377       break;
3378     case NEON_ST4_post:
3379       mnemonic = "st4";
3380       form = form_4v;
3381       break;
3382     default:
3383       break;
3384   }
3385 
3386   // Work out unallocated encodings.
3387   bool allocated = (mnemonic != NULL);
3388   switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
3389     case NEON_LD2_post:
3390     case NEON_LD3_post:
3391     case NEON_LD4_post:
3392     case NEON_ST2_post:
3393     case NEON_ST3_post:
3394     case NEON_ST4_post:
3395       // LD[2-4] and ST[2-4] cannot use .1d format.
3396       allocated = (instr->GetNEONQ() != 0) || (instr->GetNEONLSSize() != 3);
3397       break;
3398     default:
3399       break;
3400   }
3401   if (allocated) {
3402     VIXL_ASSERT(mnemonic != NULL);
3403     VIXL_ASSERT(form != NULL);
3404   } else {
3405     mnemonic = "unallocated";
3406     form = "(NEONLoadStoreMultiStructPostIndex)";
3407   }
3408 
3409   Format(instr, mnemonic, nfd.Substitute(form));
3410 }
3411 
3412 
VisitNEONLoadStoreSingleStruct(const Instruction * instr)3413 void Disassembler::VisitNEONLoadStoreSingleStruct(const Instruction *instr) {
3414   const char *mnemonic = NULL;
3415   const char *form = NULL;
3416 
3417   const char *form_1b = "{'Vt.b}['IVLSLane0], ['Xns]";
3418   const char *form_1h = "{'Vt.h}['IVLSLane1], ['Xns]";
3419   const char *form_1s = "{'Vt.s}['IVLSLane2], ['Xns]";
3420   const char *form_1d = "{'Vt.d}['IVLSLane3], ['Xns]";
3421   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3422 
3423   switch (instr->Mask(NEONLoadStoreSingleStructMask)) {
3424     case NEON_LD1_b:
3425       mnemonic = "ld1";
3426       form = form_1b;
3427       break;
3428     case NEON_LD1_h:
3429       mnemonic = "ld1";
3430       form = form_1h;
3431       break;
3432     case NEON_LD1_s:
3433       mnemonic = "ld1";
3434       VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
3435       form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
3436       break;
3437     case NEON_ST1_b:
3438       mnemonic = "st1";
3439       form = form_1b;
3440       break;
3441     case NEON_ST1_h:
3442       mnemonic = "st1";
3443       form = form_1h;
3444       break;
3445     case NEON_ST1_s:
3446       mnemonic = "st1";
3447       VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
3448       form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
3449       break;
3450     case NEON_LD1R:
3451       mnemonic = "ld1r";
3452       form = "{'Vt.%s}, ['Xns]";
3453       break;
3454     case NEON_LD2_b:
3455     case NEON_ST2_b:
3456       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3457       form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns]";
3458       break;
3459     case NEON_LD2_h:
3460     case NEON_ST2_h:
3461       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3462       form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns]";
3463       break;
3464     case NEON_LD2_s:
3465     case NEON_ST2_s:
3466       VIXL_STATIC_ASSERT((NEON_ST2_s | (1 << NEONLSSize_offset)) == NEON_ST2_d);
3467       VIXL_STATIC_ASSERT((NEON_LD2_s | (1 << NEONLSSize_offset)) == NEON_LD2_d);
3468       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3469       if ((instr->GetNEONLSSize() & 1) == 0) {
3470         form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns]";
3471       } else {
3472         form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns]";
3473       }
3474       break;
3475     case NEON_LD2R:
3476       mnemonic = "ld2r";
3477       form = "{'Vt.%s, 'Vt2.%s}, ['Xns]";
3478       break;
3479     case NEON_LD3_b:
3480     case NEON_ST3_b:
3481       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3482       form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns]";
3483       break;
3484     case NEON_LD3_h:
3485     case NEON_ST3_h:
3486       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3487       form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns]";
3488       break;
3489     case NEON_LD3_s:
3490     case NEON_ST3_s:
3491       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3492       if ((instr->GetNEONLSSize() & 1) == 0) {
3493         form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns]";
3494       } else {
3495         form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns]";
3496       }
3497       break;
3498     case NEON_LD3R:
3499       mnemonic = "ld3r";
3500       form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns]";
3501       break;
3502     case NEON_LD4_b:
3503     case NEON_ST4_b:
3504       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3505       form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns]";
3506       break;
3507     case NEON_LD4_h:
3508     case NEON_ST4_h:
3509       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3510       form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns]";
3511       break;
3512     case NEON_LD4_s:
3513     case NEON_ST4_s:
3514       VIXL_STATIC_ASSERT((NEON_LD4_s | (1 << NEONLSSize_offset)) == NEON_LD4_d);
3515       VIXL_STATIC_ASSERT((NEON_ST4_s | (1 << NEONLSSize_offset)) == NEON_ST4_d);
3516       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3517       if ((instr->GetNEONLSSize() & 1) == 0) {
3518         form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns]";
3519       } else {
3520         form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns]";
3521       }
3522       break;
3523     case NEON_LD4R:
3524       mnemonic = "ld4r";
3525       form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]";
3526       break;
3527     default:
3528       break;
3529   }
3530 
3531   // Work out unallocated encodings.
3532   bool allocated = (mnemonic != NULL);
3533   switch (instr->Mask(NEONLoadStoreSingleStructMask)) {
3534     case NEON_LD1_h:
3535     case NEON_LD2_h:
3536     case NEON_LD3_h:
3537     case NEON_LD4_h:
3538     case NEON_ST1_h:
3539     case NEON_ST2_h:
3540     case NEON_ST3_h:
3541     case NEON_ST4_h:
3542       VIXL_ASSERT(allocated);
3543       allocated = ((instr->GetNEONLSSize() & 1) == 0);
3544       break;
3545     case NEON_LD1_s:
3546     case NEON_LD2_s:
3547     case NEON_LD3_s:
3548     case NEON_LD4_s:
3549     case NEON_ST1_s:
3550     case NEON_ST2_s:
3551     case NEON_ST3_s:
3552     case NEON_ST4_s:
3553       VIXL_ASSERT(allocated);
3554       allocated = (instr->GetNEONLSSize() <= 1) &&
3555                   ((instr->GetNEONLSSize() == 0) || (instr->GetNEONS() == 0));
3556       break;
3557     case NEON_LD1R:
3558     case NEON_LD2R:
3559     case NEON_LD3R:
3560     case NEON_LD4R:
3561       VIXL_ASSERT(allocated);
3562       allocated = (instr->GetNEONS() == 0);
3563       break;
3564     default:
3565       break;
3566   }
3567   if (allocated) {
3568     VIXL_ASSERT(mnemonic != NULL);
3569     VIXL_ASSERT(form != NULL);
3570   } else {
3571     mnemonic = "unallocated";
3572     form = "(NEONLoadStoreSingleStruct)";
3573   }
3574 
3575   Format(instr, mnemonic, nfd.Substitute(form));
3576 }
3577 
3578 
VisitNEONLoadStoreSingleStructPostIndex(const Instruction * instr)3579 void Disassembler::VisitNEONLoadStoreSingleStructPostIndex(
3580     const Instruction *instr) {
3581   const char *mnemonic = NULL;
3582   const char *form = NULL;
3583 
3584   const char *form_1b = "{'Vt.b}['IVLSLane0], ['Xns], 'Xmb1";
3585   const char *form_1h = "{'Vt.h}['IVLSLane1], ['Xns], 'Xmb2";
3586   const char *form_1s = "{'Vt.s}['IVLSLane2], ['Xns], 'Xmb4";
3587   const char *form_1d = "{'Vt.d}['IVLSLane3], ['Xns], 'Xmb8";
3588   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3589 
3590   switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
3591     case NEON_LD1_b_post:
3592       mnemonic = "ld1";
3593       form = form_1b;
3594       break;
3595     case NEON_LD1_h_post:
3596       mnemonic = "ld1";
3597       form = form_1h;
3598       break;
3599     case NEON_LD1_s_post:
3600       mnemonic = "ld1";
3601       VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
3602       form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
3603       break;
3604     case NEON_ST1_b_post:
3605       mnemonic = "st1";
3606       form = form_1b;
3607       break;
3608     case NEON_ST1_h_post:
3609       mnemonic = "st1";
3610       form = form_1h;
3611       break;
3612     case NEON_ST1_s_post:
3613       mnemonic = "st1";
3614       VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
3615       form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
3616       break;
3617     case NEON_LD1R_post:
3618       mnemonic = "ld1r";
3619       form = "{'Vt.%s}, ['Xns], 'Xmz1";
3620       break;
3621     case NEON_LD2_b_post:
3622     case NEON_ST2_b_post:
3623       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3624       form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns], 'Xmb2";
3625       break;
3626     case NEON_ST2_h_post:
3627     case NEON_LD2_h_post:
3628       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3629       form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns], 'Xmb4";
3630       break;
3631     case NEON_LD2_s_post:
3632     case NEON_ST2_s_post:
3633       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3634       if ((instr->GetNEONLSSize() & 1) == 0)
3635         form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns], 'Xmb8";
3636       else
3637         form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns], 'Xmb16";
3638       break;
3639     case NEON_LD2R_post:
3640       mnemonic = "ld2r";
3641       form = "{'Vt.%s, 'Vt2.%s}, ['Xns], 'Xmz2";
3642       break;
3643     case NEON_LD3_b_post:
3644     case NEON_ST3_b_post:
3645       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3646       form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns], 'Xmb3";
3647       break;
3648     case NEON_LD3_h_post:
3649     case NEON_ST3_h_post:
3650       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3651       form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns], 'Xmb6";
3652       break;
3653     case NEON_LD3_s_post:
3654     case NEON_ST3_s_post:
3655       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3656       if ((instr->GetNEONLSSize() & 1) == 0)
3657         form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns], 'Xmb12";
3658       else
3659         form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns], 'Xmb24";
3660       break;
3661     case NEON_LD3R_post:
3662       mnemonic = "ld3r";
3663       form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns], 'Xmz3";
3664       break;
3665     case NEON_LD4_b_post:
3666     case NEON_ST4_b_post:
3667       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3668       form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns], 'Xmb4";
3669       break;
3670     case NEON_LD4_h_post:
3671     case NEON_ST4_h_post:
3672       mnemonic = (instr->GetLdStXLoad()) == 1 ? "ld4" : "st4";
3673       form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns], 'Xmb8";
3674       break;
3675     case NEON_LD4_s_post:
3676     case NEON_ST4_s_post:
3677       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3678       if ((instr->GetNEONLSSize() & 1) == 0)
3679         form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns], 'Xmb16";
3680       else
3681         form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns], 'Xmb32";
3682       break;
3683     case NEON_LD4R_post:
3684       mnemonic = "ld4r";
3685       form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmz4";
3686       break;
3687     default:
3688       break;
3689   }
3690 
3691   // Work out unallocated encodings.
3692   bool allocated = (mnemonic != NULL);
3693   switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
3694     case NEON_LD1_h_post:
3695     case NEON_LD2_h_post:
3696     case NEON_LD3_h_post:
3697     case NEON_LD4_h_post:
3698     case NEON_ST1_h_post:
3699     case NEON_ST2_h_post:
3700     case NEON_ST3_h_post:
3701     case NEON_ST4_h_post:
3702       VIXL_ASSERT(allocated);
3703       allocated = ((instr->GetNEONLSSize() & 1) == 0);
3704       break;
3705     case NEON_LD1_s_post:
3706     case NEON_LD2_s_post:
3707     case NEON_LD3_s_post:
3708     case NEON_LD4_s_post:
3709     case NEON_ST1_s_post:
3710     case NEON_ST2_s_post:
3711     case NEON_ST3_s_post:
3712     case NEON_ST4_s_post:
3713       VIXL_ASSERT(allocated);
3714       allocated = (instr->GetNEONLSSize() <= 1) &&
3715                   ((instr->GetNEONLSSize() == 0) || (instr->GetNEONS() == 0));
3716       break;
3717     case NEON_LD1R_post:
3718     case NEON_LD2R_post:
3719     case NEON_LD3R_post:
3720     case NEON_LD4R_post:
3721       VIXL_ASSERT(allocated);
3722       allocated = (instr->GetNEONS() == 0);
3723       break;
3724     default:
3725       break;
3726   }
3727   if (allocated) {
3728     VIXL_ASSERT(mnemonic != NULL);
3729     VIXL_ASSERT(form != NULL);
3730   } else {
3731     mnemonic = "unallocated";
3732     form = "(NEONLoadStoreSingleStructPostIndex)";
3733   }
3734 
3735   Format(instr, mnemonic, nfd.Substitute(form));
3736 }
3737 
3738 
VisitNEONModifiedImmediate(const Instruction * instr)3739 void Disassembler::VisitNEONModifiedImmediate(const Instruction *instr) {
3740   const char *mnemonic = "unimplemented";
3741   const char *form = "'Vt.%s, 'IVMIImm8, lsl 'IVMIShiftAmt1";
3742 
3743   int half_enc = instr->ExtractBit(11);
3744   int cmode = instr->GetNEONCmode();
3745   int cmode_3 = (cmode >> 3) & 1;
3746   int cmode_2 = (cmode >> 2) & 1;
3747   int cmode_1 = (cmode >> 1) & 1;
3748   int cmode_0 = cmode & 1;
3749   int q = instr->GetNEONQ();
3750   int op = instr->GetNEONModImmOp();
3751 
3752   static const NEONFormatMap map_b = {{30}, {NF_8B, NF_16B}};
3753   static const NEONFormatMap map_h = {{30}, {NF_4H, NF_8H}};
3754   static const NEONFormatMap map_s = {{30}, {NF_2S, NF_4S}};
3755   NEONFormatDecoder nfd(instr, &map_b);
3756   if (cmode_3 == 0) {
3757     if (cmode_0 == 0) {
3758       mnemonic = (op == 1) ? "mvni" : "movi";
3759     } else {  // cmode<0> == '1'.
3760       mnemonic = (op == 1) ? "bic" : "orr";
3761     }
3762     nfd.SetFormatMap(0, &map_s);
3763   } else {  // cmode<3> == '1'.
3764     if (cmode_2 == 0) {
3765       if (cmode_0 == 0) {
3766         mnemonic = (op == 1) ? "mvni" : "movi";
3767       } else {  // cmode<0> == '1'.
3768         mnemonic = (op == 1) ? "bic" : "orr";
3769       }
3770       nfd.SetFormatMap(0, &map_h);
3771     } else {  // cmode<2> == '1'.
3772       if (cmode_1 == 0) {
3773         mnemonic = (op == 1) ? "mvni" : "movi";
3774         form = "'Vt.%s, 'IVMIImm8, msl 'IVMIShiftAmt2";
3775         nfd.SetFormatMap(0, &map_s);
3776       } else {  // cmode<1> == '1'.
3777         if (cmode_0 == 0) {
3778           mnemonic = "movi";
3779           if (op == 0) {
3780             form = "'Vt.%s, 'IVMIImm8";
3781           } else {
3782             form = (q == 0) ? "'Dd, 'IVMIImm" : "'Vt.2d, 'IVMIImm";
3783           }
3784         } else {  // cmode<0> == '1'
3785           mnemonic = "fmov";
3786           if (half_enc == 1) {
3787             form = "'Vt.%s, 'IVMIImmFPHalf";
3788             nfd.SetFormatMap(0, &map_h);
3789           } else if (op == 0) {
3790             form = "'Vt.%s, 'IVMIImmFPSingle";
3791             nfd.SetFormatMap(0, &map_s);
3792           } else {
3793             if (q == 1) {
3794               form = "'Vt.2d, 'IVMIImmFPDouble";
3795             } else {
3796               mnemonic = "unallocated";
3797               form = "(NEONModifiedImmediate)";
3798             }
3799           }
3800         }
3801       }
3802     }
3803   }
3804   Format(instr, mnemonic, nfd.Substitute(form));
3805 }
3806 
3807 
VisitNEONScalar2RegMisc(const Instruction * instr)3808 void Disassembler::VisitNEONScalar2RegMisc(const Instruction *instr) {
3809   const char *mnemonic = "unimplemented";
3810   const char *form = "%sd, %sn";
3811   const char *form_0 = "%sd, %sn, #0";
3812   const char *form_fp0 = "%sd, %sn, #0.0";
3813 
3814   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
3815 
3816   if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
3817     // These instructions all use a two bit size field, except NOT and RBIT,
3818     // which use the field to encode the operation.
3819     switch (instr->Mask(NEONScalar2RegMiscMask)) {
3820       case NEON_CMGT_zero_scalar:
3821         mnemonic = "cmgt";
3822         form = form_0;
3823         break;
3824       case NEON_CMGE_zero_scalar:
3825         mnemonic = "cmge";
3826         form = form_0;
3827         break;
3828       case NEON_CMLE_zero_scalar:
3829         mnemonic = "cmle";
3830         form = form_0;
3831         break;
3832       case NEON_CMLT_zero_scalar:
3833         mnemonic = "cmlt";
3834         form = form_0;
3835         break;
3836       case NEON_CMEQ_zero_scalar:
3837         mnemonic = "cmeq";
3838         form = form_0;
3839         break;
3840       case NEON_NEG_scalar:
3841         mnemonic = "neg";
3842         break;
3843       case NEON_SQNEG_scalar:
3844         mnemonic = "sqneg";
3845         break;
3846       case NEON_ABS_scalar:
3847         mnemonic = "abs";
3848         break;
3849       case NEON_SQABS_scalar:
3850         mnemonic = "sqabs";
3851         break;
3852       case NEON_SUQADD_scalar:
3853         mnemonic = "suqadd";
3854         break;
3855       case NEON_USQADD_scalar:
3856         mnemonic = "usqadd";
3857         break;
3858       default:
3859         form = "(NEONScalar2RegMisc)";
3860     }
3861   } else {
3862     // These instructions all use a one bit size field, except SQXTUN, SQXTN
3863     // and UQXTN, which use a two bit size field.
3864     nfd.SetFormatMaps(nfd.FPScalarFormatMap());
3865     switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
3866       case NEON_FRSQRTE_scalar:
3867         mnemonic = "frsqrte";
3868         break;
3869       case NEON_FRECPE_scalar:
3870         mnemonic = "frecpe";
3871         break;
3872       case NEON_SCVTF_scalar:
3873         mnemonic = "scvtf";
3874         break;
3875       case NEON_UCVTF_scalar:
3876         mnemonic = "ucvtf";
3877         break;
3878       case NEON_FCMGT_zero_scalar:
3879         mnemonic = "fcmgt";
3880         form = form_fp0;
3881         break;
3882       case NEON_FCMGE_zero_scalar:
3883         mnemonic = "fcmge";
3884         form = form_fp0;
3885         break;
3886       case NEON_FCMLE_zero_scalar:
3887         mnemonic = "fcmle";
3888         form = form_fp0;
3889         break;
3890       case NEON_FCMLT_zero_scalar:
3891         mnemonic = "fcmlt";
3892         form = form_fp0;
3893         break;
3894       case NEON_FCMEQ_zero_scalar:
3895         mnemonic = "fcmeq";
3896         form = form_fp0;
3897         break;
3898       case NEON_FRECPX_scalar:
3899         mnemonic = "frecpx";
3900         break;
3901       case NEON_FCVTNS_scalar:
3902         mnemonic = "fcvtns";
3903         break;
3904       case NEON_FCVTNU_scalar:
3905         mnemonic = "fcvtnu";
3906         break;
3907       case NEON_FCVTPS_scalar:
3908         mnemonic = "fcvtps";
3909         break;
3910       case NEON_FCVTPU_scalar:
3911         mnemonic = "fcvtpu";
3912         break;
3913       case NEON_FCVTMS_scalar:
3914         mnemonic = "fcvtms";
3915         break;
3916       case NEON_FCVTMU_scalar:
3917         mnemonic = "fcvtmu";
3918         break;
3919       case NEON_FCVTZS_scalar:
3920         mnemonic = "fcvtzs";
3921         break;
3922       case NEON_FCVTZU_scalar:
3923         mnemonic = "fcvtzu";
3924         break;
3925       case NEON_FCVTAS_scalar:
3926         mnemonic = "fcvtas";
3927         break;
3928       case NEON_FCVTAU_scalar:
3929         mnemonic = "fcvtau";
3930         break;
3931       case NEON_FCVTXN_scalar:
3932         nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
3933         mnemonic = "fcvtxn";
3934         break;
3935       default:
3936         nfd.SetFormatMap(0, nfd.ScalarFormatMap());
3937         nfd.SetFormatMap(1, nfd.LongScalarFormatMap());
3938         switch (instr->Mask(NEONScalar2RegMiscMask)) {
3939           case NEON_SQXTN_scalar:
3940             mnemonic = "sqxtn";
3941             break;
3942           case NEON_UQXTN_scalar:
3943             mnemonic = "uqxtn";
3944             break;
3945           case NEON_SQXTUN_scalar:
3946             mnemonic = "sqxtun";
3947             break;
3948           default:
3949             form = "(NEONScalar2RegMisc)";
3950         }
3951     }
3952   }
3953   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
3954 }
3955 
VisitNEONScalar2RegMiscFP16(const Instruction * instr)3956 void Disassembler::VisitNEONScalar2RegMiscFP16(const Instruction *instr) {
3957   const char *mnemonic = "unimplemented";
3958   const char *form = "'Hd, 'Hn";
3959   const char *form_fp0 = "'Hd, 'Hn, #0.0";
3960 
3961   switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
3962 #define FORMAT(A, B)        \
3963   case NEON_##A##_H_scalar: \
3964     mnemonic = B;           \
3965     break;
3966     // clang-format off
3967     FORMAT(FCVTNS,  "fcvtns")
3968     FORMAT(FCVTMS,  "fcvtms")
3969     FORMAT(FCVTAS,  "fcvtas")
3970     FORMAT(SCVTF,   "scvtf")
3971     FORMAT(FCVTPS,  "fcvtps")
3972     FORMAT(FCVTZS,  "fcvtzs")
3973     FORMAT(FRECPE,  "frecpe")
3974     FORMAT(FRECPX,  "frecpx")
3975     FORMAT(FCVTNU,  "fcvtnu")
3976     FORMAT(FCVTMU,  "fcvtmu")
3977     FORMAT(FCVTAU,  "fcvtau")
3978     FORMAT(UCVTF,   "ucvtf")
3979     FORMAT(FCVTPU,  "fcvtpu")
3980     FORMAT(FCVTZU,  "fcvtzu")
3981     FORMAT(FRSQRTE, "frsqrte")
3982 // clang-format on
3983 #undef FORMAT
3984 #define FORMAT(A, B)             \
3985   case NEON_##A##_H_zero_scalar: \
3986     mnemonic = B;                \
3987     form = form_fp0;             \
3988     break;
3989     FORMAT(FCMGT, "fcmgt")
3990     FORMAT(FCMEQ, "fcmeq")
3991     FORMAT(FCMLT, "fcmlt")
3992     FORMAT(FCMGE, "fcmge")
3993     FORMAT(FCMLE, "fcmle")
3994 #undef FORMAT
3995 
3996     default:
3997       VIXL_UNREACHABLE();
3998   }
3999   Format(instr, mnemonic, form);
4000 }
4001 
4002 
VisitNEONScalar3Diff(const Instruction * instr)4003 void Disassembler::VisitNEONScalar3Diff(const Instruction *instr) {
4004   const char *mnemonic = "unimplemented";
4005   const char *form = "%sd, %sn, %sm";
4006   NEONFormatDecoder nfd(instr,
4007                         NEONFormatDecoder::LongScalarFormatMap(),
4008                         NEONFormatDecoder::ScalarFormatMap());
4009 
4010   switch (instr->Mask(NEONScalar3DiffMask)) {
4011     case NEON_SQDMLAL_scalar:
4012       mnemonic = "sqdmlal";
4013       break;
4014     case NEON_SQDMLSL_scalar:
4015       mnemonic = "sqdmlsl";
4016       break;
4017     case NEON_SQDMULL_scalar:
4018       mnemonic = "sqdmull";
4019       break;
4020     default:
4021       form = "(NEONScalar3Diff)";
4022   }
4023   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
4024 }
4025 
4026 
VisitNEONScalar3Same(const Instruction * instr)4027 void Disassembler::VisitNEONScalar3Same(const Instruction *instr) {
4028   const char *mnemonic = "unimplemented";
4029   const char *form = "%sd, %sn, %sm";
4030   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4031 
4032   if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
4033     nfd.SetFormatMaps(nfd.FPScalarFormatMap());
4034     switch (instr->Mask(NEONScalar3SameFPMask)) {
4035       case NEON_FACGE_scalar:
4036         mnemonic = "facge";
4037         break;
4038       case NEON_FACGT_scalar:
4039         mnemonic = "facgt";
4040         break;
4041       case NEON_FCMEQ_scalar:
4042         mnemonic = "fcmeq";
4043         break;
4044       case NEON_FCMGE_scalar:
4045         mnemonic = "fcmge";
4046         break;
4047       case NEON_FCMGT_scalar:
4048         mnemonic = "fcmgt";
4049         break;
4050       case NEON_FMULX_scalar:
4051         mnemonic = "fmulx";
4052         break;
4053       case NEON_FRECPS_scalar:
4054         mnemonic = "frecps";
4055         break;
4056       case NEON_FRSQRTS_scalar:
4057         mnemonic = "frsqrts";
4058         break;
4059       case NEON_FABD_scalar:
4060         mnemonic = "fabd";
4061         break;
4062       default:
4063         form = "(NEONScalar3Same)";
4064     }
4065   } else {
4066     switch (instr->Mask(NEONScalar3SameMask)) {
4067       case NEON_ADD_scalar:
4068         mnemonic = "add";
4069         break;
4070       case NEON_SUB_scalar:
4071         mnemonic = "sub";
4072         break;
4073       case NEON_CMEQ_scalar:
4074         mnemonic = "cmeq";
4075         break;
4076       case NEON_CMGE_scalar:
4077         mnemonic = "cmge";
4078         break;
4079       case NEON_CMGT_scalar:
4080         mnemonic = "cmgt";
4081         break;
4082       case NEON_CMHI_scalar:
4083         mnemonic = "cmhi";
4084         break;
4085       case NEON_CMHS_scalar:
4086         mnemonic = "cmhs";
4087         break;
4088       case NEON_CMTST_scalar:
4089         mnemonic = "cmtst";
4090         break;
4091       case NEON_UQADD_scalar:
4092         mnemonic = "uqadd";
4093         break;
4094       case NEON_SQADD_scalar:
4095         mnemonic = "sqadd";
4096         break;
4097       case NEON_UQSUB_scalar:
4098         mnemonic = "uqsub";
4099         break;
4100       case NEON_SQSUB_scalar:
4101         mnemonic = "sqsub";
4102         break;
4103       case NEON_USHL_scalar:
4104         mnemonic = "ushl";
4105         break;
4106       case NEON_SSHL_scalar:
4107         mnemonic = "sshl";
4108         break;
4109       case NEON_UQSHL_scalar:
4110         mnemonic = "uqshl";
4111         break;
4112       case NEON_SQSHL_scalar:
4113         mnemonic = "sqshl";
4114         break;
4115       case NEON_URSHL_scalar:
4116         mnemonic = "urshl";
4117         break;
4118       case NEON_SRSHL_scalar:
4119         mnemonic = "srshl";
4120         break;
4121       case NEON_UQRSHL_scalar:
4122         mnemonic = "uqrshl";
4123         break;
4124       case NEON_SQRSHL_scalar:
4125         mnemonic = "sqrshl";
4126         break;
4127       case NEON_SQDMULH_scalar:
4128         mnemonic = "sqdmulh";
4129         break;
4130       case NEON_SQRDMULH_scalar:
4131         mnemonic = "sqrdmulh";
4132         break;
4133       default:
4134         form = "(NEONScalar3Same)";
4135     }
4136   }
4137   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
4138 }
4139 
VisitNEONScalar3SameFP16(const Instruction * instr)4140 void Disassembler::VisitNEONScalar3SameFP16(const Instruction *instr) {
4141   const char *mnemonic = NULL;
4142   const char *form = "'Hd, 'Hn, 'Hm";
4143 
4144   switch (instr->Mask(NEONScalar3SameFP16Mask)) {
4145     case NEON_FABD_H_scalar:
4146       mnemonic = "fabd";
4147       break;
4148     case NEON_FMULX_H_scalar:
4149       mnemonic = "fmulx";
4150       break;
4151     case NEON_FCMEQ_H_scalar:
4152       mnemonic = "fcmeq";
4153       break;
4154     case NEON_FCMGE_H_scalar:
4155       mnemonic = "fcmge";
4156       break;
4157     case NEON_FCMGT_H_scalar:
4158       mnemonic = "fcmgt";
4159       break;
4160     case NEON_FACGE_H_scalar:
4161       mnemonic = "facge";
4162       break;
4163     case NEON_FACGT_H_scalar:
4164       mnemonic = "facgt";
4165       break;
4166     case NEON_FRECPS_H_scalar:
4167       mnemonic = "frecps";
4168       break;
4169     case NEON_FRSQRTS_H_scalar:
4170       mnemonic = "frsqrts";
4171       break;
4172     default:
4173       VIXL_UNREACHABLE();
4174   }
4175   Format(instr, mnemonic, form);
4176 }
4177 
VisitNEONScalar3SameExtra(const Instruction * instr)4178 void Disassembler::VisitNEONScalar3SameExtra(const Instruction *instr) {
4179   const char *mnemonic = "unimplemented";
4180   const char *form = "%sd, %sn, %sm";
4181   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4182 
4183   switch (instr->Mask(NEONScalar3SameExtraMask)) {
4184     case NEON_SQRDMLAH_scalar:
4185       mnemonic = "sqrdmlah";
4186       break;
4187     case NEON_SQRDMLSH_scalar:
4188       mnemonic = "sqrdmlsh";
4189       break;
4190     default:
4191       form = "(NEONScalar3SameExtra)";
4192   }
4193   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
4194 }
4195 
4196 
VisitNEONScalarByIndexedElement(const Instruction * instr)4197 void Disassembler::VisitNEONScalarByIndexedElement(const Instruction *instr) {
4198   const char *mnemonic = "unimplemented";
4199   const char *form = "%sd, %sn, 'Ve.%s['IVByElemIndex]";
4200   const char *form_half = "'Hd, 'Hn, 'Ve.h['IVByElemIndex]";
4201   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4202   bool long_instr = false;
4203 
4204   switch (instr->Mask(NEONScalarByIndexedElementMask)) {
4205     case NEON_SQDMULL_byelement_scalar:
4206       mnemonic = "sqdmull";
4207       long_instr = true;
4208       break;
4209     case NEON_SQDMLAL_byelement_scalar:
4210       mnemonic = "sqdmlal";
4211       long_instr = true;
4212       break;
4213     case NEON_SQDMLSL_byelement_scalar:
4214       mnemonic = "sqdmlsl";
4215       long_instr = true;
4216       break;
4217     case NEON_SQDMULH_byelement_scalar:
4218       mnemonic = "sqdmulh";
4219       break;
4220     case NEON_SQRDMULH_byelement_scalar:
4221       mnemonic = "sqrdmulh";
4222       break;
4223     case NEON_SQRDMLAH_byelement_scalar:
4224       mnemonic = "sqrdmlah";
4225       break;
4226     case NEON_SQRDMLSH_byelement_scalar:
4227       mnemonic = "sqrdmlsh";
4228       break;
4229     default:
4230       nfd.SetFormatMap(0, nfd.FPScalarFormatMap());
4231       switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
4232         case NEON_FMUL_byelement_scalar:
4233           mnemonic = "fmul";
4234           break;
4235         case NEON_FMLA_byelement_scalar:
4236           mnemonic = "fmla";
4237           break;
4238         case NEON_FMLS_byelement_scalar:
4239           mnemonic = "fmls";
4240           break;
4241         case NEON_FMULX_byelement_scalar:
4242           mnemonic = "fmulx";
4243           break;
4244         case NEON_FMLA_H_byelement_scalar:
4245           mnemonic = "fmla";
4246           form = form_half;
4247           break;
4248         case NEON_FMLS_H_byelement_scalar:
4249           mnemonic = "fmls";
4250           form = form_half;
4251           break;
4252         case NEON_FMUL_H_byelement_scalar:
4253           mnemonic = "fmul";
4254           form = form_half;
4255           break;
4256         case NEON_FMULX_H_byelement_scalar:
4257           mnemonic = "fmulx";
4258           form = form_half;
4259           break;
4260         default:
4261           form = "(NEONScalarByIndexedElement)";
4262       }
4263   }
4264 
4265   if (long_instr) {
4266     nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
4267   }
4268 
4269   Format(instr,
4270          mnemonic,
4271          nfd.Substitute(form, nfd.kPlaceholder, nfd.kPlaceholder, nfd.kFormat));
4272 }
4273 
4274 
VisitNEONScalarCopy(const Instruction * instr)4275 void Disassembler::VisitNEONScalarCopy(const Instruction *instr) {
4276   const char *mnemonic = "unimplemented";
4277   const char *form = "(NEONScalarCopy)";
4278 
4279   NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
4280 
4281   if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
4282     mnemonic = "mov";
4283     form = "%sd, 'Vn.%s['IVInsIndex1]";
4284   }
4285 
4286   Format(instr, mnemonic, nfd.Substitute(form, nfd.kPlaceholder, nfd.kFormat));
4287 }
4288 
4289 
VisitNEONScalarPairwise(const Instruction * instr)4290 void Disassembler::VisitNEONScalarPairwise(const Instruction *instr) {
4291   const char *mnemonic = "unimplemented";
4292   const char *form = "%sd, 'Vn.%s";
4293   NEONFormatMap map = {{22}, {NF_2S, NF_2D}};
4294   NEONFormatDecoder nfd(instr,
4295                         NEONFormatDecoder::FPScalarPairwiseFormatMap(),
4296                         &map);
4297 
4298   switch (instr->Mask(NEONScalarPairwiseMask)) {
4299     case NEON_ADDP_scalar:
4300       // All pairwise operations except ADDP use bit U to differentiate FP16
4301       // from FP32/FP64 variations.
4302       nfd.SetFormatMap(0, NEONFormatDecoder::FPScalarFormatMap());
4303       mnemonic = "addp";
4304       break;
4305     case NEON_FADDP_h_scalar:
4306       form = "%sd, 'Vn.2h";
4307       VIXL_FALLTHROUGH();
4308     case NEON_FADDP_scalar:
4309       mnemonic = "faddp";
4310       break;
4311     case NEON_FMAXP_h_scalar:
4312       form = "%sd, 'Vn.2h";
4313       VIXL_FALLTHROUGH();
4314     case NEON_FMAXP_scalar:
4315       mnemonic = "fmaxp";
4316       break;
4317     case NEON_FMAXNMP_h_scalar:
4318       form = "%sd, 'Vn.2h";
4319       VIXL_FALLTHROUGH();
4320     case NEON_FMAXNMP_scalar:
4321       mnemonic = "fmaxnmp";
4322       break;
4323     case NEON_FMINP_h_scalar:
4324       form = "%sd, 'Vn.2h";
4325       VIXL_FALLTHROUGH();
4326     case NEON_FMINP_scalar:
4327       mnemonic = "fminp";
4328       break;
4329     case NEON_FMINNMP_h_scalar:
4330       form = "%sd, 'Vn.2h";
4331       VIXL_FALLTHROUGH();
4332     case NEON_FMINNMP_scalar:
4333       mnemonic = "fminnmp";
4334       break;
4335     default:
4336       form = "(NEONScalarPairwise)";
4337   }
4338   Format(instr,
4339          mnemonic,
4340          nfd.Substitute(form,
4341                         NEONFormatDecoder::kPlaceholder,
4342                         NEONFormatDecoder::kFormat));
4343 }
4344 
4345 
VisitNEONScalarShiftImmediate(const Instruction * instr)4346 void Disassembler::VisitNEONScalarShiftImmediate(const Instruction *instr) {
4347   const char *mnemonic = "unimplemented";
4348   const char *form = "%sd, %sn, 'Is1";
4349   const char *form_2 = "%sd, %sn, 'Is2";
4350 
4351   static const NEONFormatMap map_shift = {{22, 21, 20, 19},
4352                                           {NF_UNDEF,
4353                                            NF_B,
4354                                            NF_H,
4355                                            NF_H,
4356                                            NF_S,
4357                                            NF_S,
4358                                            NF_S,
4359                                            NF_S,
4360                                            NF_D,
4361                                            NF_D,
4362                                            NF_D,
4363                                            NF_D,
4364                                            NF_D,
4365                                            NF_D,
4366                                            NF_D,
4367                                            NF_D}};
4368   static const NEONFormatMap map_shift_narrow =
4369       {{21, 20, 19}, {NF_UNDEF, NF_H, NF_S, NF_S, NF_D, NF_D, NF_D, NF_D}};
4370   NEONFormatDecoder nfd(instr, &map_shift);
4371 
4372   if (instr->GetImmNEONImmh()) {  // immh has to be non-zero.
4373     switch (instr->Mask(NEONScalarShiftImmediateMask)) {
4374       case NEON_FCVTZU_imm_scalar:
4375         mnemonic = "fcvtzu";
4376         break;
4377       case NEON_FCVTZS_imm_scalar:
4378         mnemonic = "fcvtzs";
4379         break;
4380       case NEON_SCVTF_imm_scalar:
4381         mnemonic = "scvtf";
4382         break;
4383       case NEON_UCVTF_imm_scalar:
4384         mnemonic = "ucvtf";
4385         break;
4386       case NEON_SRI_scalar:
4387         mnemonic = "sri";
4388         break;
4389       case NEON_SSHR_scalar:
4390         mnemonic = "sshr";
4391         break;
4392       case NEON_USHR_scalar:
4393         mnemonic = "ushr";
4394         break;
4395       case NEON_SRSHR_scalar:
4396         mnemonic = "srshr";
4397         break;
4398       case NEON_URSHR_scalar:
4399         mnemonic = "urshr";
4400         break;
4401       case NEON_SSRA_scalar:
4402         mnemonic = "ssra";
4403         break;
4404       case NEON_USRA_scalar:
4405         mnemonic = "usra";
4406         break;
4407       case NEON_SRSRA_scalar:
4408         mnemonic = "srsra";
4409         break;
4410       case NEON_URSRA_scalar:
4411         mnemonic = "ursra";
4412         break;
4413       case NEON_SHL_scalar:
4414         mnemonic = "shl";
4415         form = form_2;
4416         break;
4417       case NEON_SLI_scalar:
4418         mnemonic = "sli";
4419         form = form_2;
4420         break;
4421       case NEON_SQSHLU_scalar:
4422         mnemonic = "sqshlu";
4423         form = form_2;
4424         break;
4425       case NEON_SQSHL_imm_scalar:
4426         mnemonic = "sqshl";
4427         form = form_2;
4428         break;
4429       case NEON_UQSHL_imm_scalar:
4430         mnemonic = "uqshl";
4431         form = form_2;
4432         break;
4433       case NEON_UQSHRN_scalar:
4434         mnemonic = "uqshrn";
4435         nfd.SetFormatMap(1, &map_shift_narrow);
4436         break;
4437       case NEON_UQRSHRN_scalar:
4438         mnemonic = "uqrshrn";
4439         nfd.SetFormatMap(1, &map_shift_narrow);
4440         break;
4441       case NEON_SQSHRN_scalar:
4442         mnemonic = "sqshrn";
4443         nfd.SetFormatMap(1, &map_shift_narrow);
4444         break;
4445       case NEON_SQRSHRN_scalar:
4446         mnemonic = "sqrshrn";
4447         nfd.SetFormatMap(1, &map_shift_narrow);
4448         break;
4449       case NEON_SQSHRUN_scalar:
4450         mnemonic = "sqshrun";
4451         nfd.SetFormatMap(1, &map_shift_narrow);
4452         break;
4453       case NEON_SQRSHRUN_scalar:
4454         mnemonic = "sqrshrun";
4455         nfd.SetFormatMap(1, &map_shift_narrow);
4456         break;
4457       default:
4458         form = "(NEONScalarShiftImmediate)";
4459     }
4460   } else {
4461     form = "(NEONScalarShiftImmediate)";
4462   }
4463   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
4464 }
4465 
4466 
VisitNEONShiftImmediate(const Instruction * instr)4467 void Disassembler::VisitNEONShiftImmediate(const Instruction *instr) {
4468   const char *mnemonic = "unimplemented";
4469   const char *form = "'Vd.%s, 'Vn.%s, 'Is1";
4470   const char *form_shift_2 = "'Vd.%s, 'Vn.%s, 'Is2";
4471   const char *form_xtl = "'Vd.%s, 'Vn.%s";
4472 
4473   // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
4474   static const NEONFormatMap map_shift_ta =
4475       {{22, 21, 20, 19},
4476        {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
4477 
4478   // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
4479   // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
4480   static const NEONFormatMap map_shift_tb =
4481       {{22, 21, 20, 19, 30},
4482        {NF_UNDEF, NF_UNDEF, NF_8B,    NF_16B,   NF_4H,    NF_8H,    NF_4H,
4483         NF_8H,    NF_2S,    NF_4S,    NF_2S,    NF_4S,    NF_2S,    NF_4S,
4484         NF_2S,    NF_4S,    NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,    NF_UNDEF,
4485         NF_2D,    NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,
4486         NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D}};
4487 
4488   NEONFormatDecoder nfd(instr, &map_shift_tb);
4489 
4490   if (instr->GetImmNEONImmh()) {  // immh has to be non-zero.
4491     switch (instr->Mask(NEONShiftImmediateMask)) {
4492       case NEON_SQSHLU:
4493         mnemonic = "sqshlu";
4494         form = form_shift_2;
4495         break;
4496       case NEON_SQSHL_imm:
4497         mnemonic = "sqshl";
4498         form = form_shift_2;
4499         break;
4500       case NEON_UQSHL_imm:
4501         mnemonic = "uqshl";
4502         form = form_shift_2;
4503         break;
4504       case NEON_SHL:
4505         mnemonic = "shl";
4506         form = form_shift_2;
4507         break;
4508       case NEON_SLI:
4509         mnemonic = "sli";
4510         form = form_shift_2;
4511         break;
4512       case NEON_SCVTF_imm:
4513         mnemonic = "scvtf";
4514         break;
4515       case NEON_UCVTF_imm:
4516         mnemonic = "ucvtf";
4517         break;
4518       case NEON_FCVTZU_imm:
4519         mnemonic = "fcvtzu";
4520         break;
4521       case NEON_FCVTZS_imm:
4522         mnemonic = "fcvtzs";
4523         break;
4524       case NEON_SRI:
4525         mnemonic = "sri";
4526         break;
4527       case NEON_SSHR:
4528         mnemonic = "sshr";
4529         break;
4530       case NEON_USHR:
4531         mnemonic = "ushr";
4532         break;
4533       case NEON_SRSHR:
4534         mnemonic = "srshr";
4535         break;
4536       case NEON_URSHR:
4537         mnemonic = "urshr";
4538         break;
4539       case NEON_SSRA:
4540         mnemonic = "ssra";
4541         break;
4542       case NEON_USRA:
4543         mnemonic = "usra";
4544         break;
4545       case NEON_SRSRA:
4546         mnemonic = "srsra";
4547         break;
4548       case NEON_URSRA:
4549         mnemonic = "ursra";
4550         break;
4551       case NEON_SHRN:
4552         mnemonic = instr->Mask(NEON_Q) ? "shrn2" : "shrn";
4553         nfd.SetFormatMap(1, &map_shift_ta);
4554         break;
4555       case NEON_RSHRN:
4556         mnemonic = instr->Mask(NEON_Q) ? "rshrn2" : "rshrn";
4557         nfd.SetFormatMap(1, &map_shift_ta);
4558         break;
4559       case NEON_UQSHRN:
4560         mnemonic = instr->Mask(NEON_Q) ? "uqshrn2" : "uqshrn";
4561         nfd.SetFormatMap(1, &map_shift_ta);
4562         break;
4563       case NEON_UQRSHRN:
4564         mnemonic = instr->Mask(NEON_Q) ? "uqrshrn2" : "uqrshrn";
4565         nfd.SetFormatMap(1, &map_shift_ta);
4566         break;
4567       case NEON_SQSHRN:
4568         mnemonic = instr->Mask(NEON_Q) ? "sqshrn2" : "sqshrn";
4569         nfd.SetFormatMap(1, &map_shift_ta);
4570         break;
4571       case NEON_SQRSHRN:
4572         mnemonic = instr->Mask(NEON_Q) ? "sqrshrn2" : "sqrshrn";
4573         nfd.SetFormatMap(1, &map_shift_ta);
4574         break;
4575       case NEON_SQSHRUN:
4576         mnemonic = instr->Mask(NEON_Q) ? "sqshrun2" : "sqshrun";
4577         nfd.SetFormatMap(1, &map_shift_ta);
4578         break;
4579       case NEON_SQRSHRUN:
4580         mnemonic = instr->Mask(NEON_Q) ? "sqrshrun2" : "sqrshrun";
4581         nfd.SetFormatMap(1, &map_shift_ta);
4582         break;
4583       case NEON_SSHLL:
4584         nfd.SetFormatMap(0, &map_shift_ta);
4585         if (instr->GetImmNEONImmb() == 0 &&
4586             CountSetBits(instr->GetImmNEONImmh(), 32) == 1) {  // sxtl variant.
4587           form = form_xtl;
4588           mnemonic = instr->Mask(NEON_Q) ? "sxtl2" : "sxtl";
4589         } else {  // sshll variant.
4590           form = form_shift_2;
4591           mnemonic = instr->Mask(NEON_Q) ? "sshll2" : "sshll";
4592         }
4593         break;
4594       case NEON_USHLL:
4595         nfd.SetFormatMap(0, &map_shift_ta);
4596         if (instr->GetImmNEONImmb() == 0 &&
4597             CountSetBits(instr->GetImmNEONImmh(), 32) == 1) {  // uxtl variant.
4598           form = form_xtl;
4599           mnemonic = instr->Mask(NEON_Q) ? "uxtl2" : "uxtl";
4600         } else {  // ushll variant.
4601           form = form_shift_2;
4602           mnemonic = instr->Mask(NEON_Q) ? "ushll2" : "ushll";
4603         }
4604         break;
4605       default:
4606         form = "(NEONShiftImmediate)";
4607     }
4608   } else {
4609     form = "(NEONShiftImmediate)";
4610   }
4611   Format(instr, mnemonic, nfd.Substitute(form));
4612 }
4613 
4614 
VisitNEONTable(const Instruction * instr)4615 void Disassembler::VisitNEONTable(const Instruction *instr) {
4616   const char *mnemonic = "unimplemented";
4617   const char *form = "(NEONTable)";
4618   const char form_1v[] = "'Vd.%%s, {'Vn.16b}, 'Vm.%%s";
4619   const char form_2v[] = "'Vd.%%s, {'Vn.16b, v%d.16b}, 'Vm.%%s";
4620   const char form_3v[] = "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b}, 'Vm.%%s";
4621   const char form_4v[] =
4622       "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b, v%d.16b}, 'Vm.%%s";
4623   static const NEONFormatMap map_b = {{30}, {NF_8B, NF_16B}};
4624   NEONFormatDecoder nfd(instr, &map_b);
4625 
4626   switch (instr->Mask(NEONTableMask)) {
4627     case NEON_TBL_1v:
4628       mnemonic = "tbl";
4629       form = form_1v;
4630       break;
4631     case NEON_TBL_2v:
4632       mnemonic = "tbl";
4633       form = form_2v;
4634       break;
4635     case NEON_TBL_3v:
4636       mnemonic = "tbl";
4637       form = form_3v;
4638       break;
4639     case NEON_TBL_4v:
4640       mnemonic = "tbl";
4641       form = form_4v;
4642       break;
4643     case NEON_TBX_1v:
4644       mnemonic = "tbx";
4645       form = form_1v;
4646       break;
4647     case NEON_TBX_2v:
4648       mnemonic = "tbx";
4649       form = form_2v;
4650       break;
4651     case NEON_TBX_3v:
4652       mnemonic = "tbx";
4653       form = form_3v;
4654       break;
4655     case NEON_TBX_4v:
4656       mnemonic = "tbx";
4657       form = form_4v;
4658       break;
4659     default:
4660       break;
4661   }
4662 
4663   char re_form[sizeof(form_4v) + 6];
4664   int reg_num = instr->GetRn();
4665   snprintf(re_form,
4666            sizeof(re_form),
4667            form,
4668            (reg_num + 1) % kNumberOfVRegisters,
4669            (reg_num + 2) % kNumberOfVRegisters,
4670            (reg_num + 3) % kNumberOfVRegisters);
4671 
4672   Format(instr, mnemonic, nfd.Substitute(re_form));
4673 }
4674 
4675 
VisitNEONPerm(const Instruction * instr)4676 void Disassembler::VisitNEONPerm(const Instruction *instr) {
4677   const char *mnemonic = "unimplemented";
4678   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
4679   NEONFormatDecoder nfd(instr);
4680 
4681   switch (instr->Mask(NEONPermMask)) {
4682     case NEON_TRN1:
4683       mnemonic = "trn1";
4684       break;
4685     case NEON_TRN2:
4686       mnemonic = "trn2";
4687       break;
4688     case NEON_UZP1:
4689       mnemonic = "uzp1";
4690       break;
4691     case NEON_UZP2:
4692       mnemonic = "uzp2";
4693       break;
4694     case NEON_ZIP1:
4695       mnemonic = "zip1";
4696       break;
4697     case NEON_ZIP2:
4698       mnemonic = "zip2";
4699       break;
4700     default:
4701       form = "(NEONPerm)";
4702   }
4703   Format(instr, mnemonic, nfd.Substitute(form));
4704 }
4705 
4706 
VisitUnimplemented(const Instruction * instr)4707 void Disassembler::VisitUnimplemented(const Instruction *instr) {
4708   Format(instr, "unimplemented", "(Unimplemented)");
4709 }
4710 
4711 
VisitUnallocated(const Instruction * instr)4712 void Disassembler::VisitUnallocated(const Instruction *instr) {
4713   Format(instr, "unallocated", "(Unallocated)");
4714 }
4715 
4716 
ProcessOutput(const Instruction *)4717 void Disassembler::ProcessOutput(const Instruction * /*instr*/) {
4718   // The base disasm does nothing more than disassembling into a buffer.
4719 }
4720 
4721 
AppendRegisterNameToOutput(const Instruction * instr,const CPURegister & reg)4722 void Disassembler::AppendRegisterNameToOutput(const Instruction *instr,
4723                                               const CPURegister &reg) {
4724   USE(instr);
4725   VIXL_ASSERT(reg.IsValid());
4726   char reg_char;
4727 
4728   if (reg.IsRegister()) {
4729     reg_char = reg.Is64Bits() ? 'x' : 'w';
4730   } else {
4731     VIXL_ASSERT(reg.IsVRegister());
4732     switch (reg.GetSizeInBits()) {
4733       case kBRegSize:
4734         reg_char = 'b';
4735         break;
4736       case kHRegSize:
4737         reg_char = 'h';
4738         break;
4739       case kSRegSize:
4740         reg_char = 's';
4741         break;
4742       case kDRegSize:
4743         reg_char = 'd';
4744         break;
4745       default:
4746         VIXL_ASSERT(reg.Is128Bits());
4747         reg_char = 'q';
4748     }
4749   }
4750 
4751   if (reg.IsVRegister() || !(reg.Aliases(sp) || reg.Aliases(xzr))) {
4752     // A core or scalar/vector register: [wx]0 - 30, [bhsdq]0 - 31.
4753     AppendToOutput("%c%d", reg_char, reg.GetCode());
4754   } else if (reg.Aliases(sp)) {
4755     // Disassemble w31/x31 as stack pointer wsp/sp.
4756     AppendToOutput("%s", reg.Is64Bits() ? "sp" : "wsp");
4757   } else {
4758     // Disassemble w31/x31 as zero register wzr/xzr.
4759     AppendToOutput("%czr", reg_char);
4760   }
4761 }
4762 
4763 
AppendPCRelativeOffsetToOutput(const Instruction * instr,int64_t offset)4764 void Disassembler::AppendPCRelativeOffsetToOutput(const Instruction *instr,
4765                                                   int64_t offset) {
4766   USE(instr);
4767   if (offset < 0) {
4768     // Cast to uint64_t so that INT64_MIN is handled in a well-defined way.
4769     uint64_t abs_offset = -static_cast<uint64_t>(offset);
4770     AppendToOutput("#-0x%" PRIx64, abs_offset);
4771   } else {
4772     AppendToOutput("#+0x%" PRIx64, offset);
4773   }
4774 }
4775 
4776 
AppendAddressToOutput(const Instruction * instr,const void * addr)4777 void Disassembler::AppendAddressToOutput(const Instruction *instr,
4778                                          const void *addr) {
4779   USE(instr);
4780   AppendToOutput("(addr 0x%" PRIxPTR ")", reinterpret_cast<uintptr_t>(addr));
4781 }
4782 
4783 
AppendCodeAddressToOutput(const Instruction * instr,const void * addr)4784 void Disassembler::AppendCodeAddressToOutput(const Instruction *instr,
4785                                              const void *addr) {
4786   AppendAddressToOutput(instr, addr);
4787 }
4788 
4789 
AppendDataAddressToOutput(const Instruction * instr,const void * addr)4790 void Disassembler::AppendDataAddressToOutput(const Instruction *instr,
4791                                              const void *addr) {
4792   AppendAddressToOutput(instr, addr);
4793 }
4794 
4795 
AppendCodeRelativeAddressToOutput(const Instruction * instr,const void * addr)4796 void Disassembler::AppendCodeRelativeAddressToOutput(const Instruction *instr,
4797                                                      const void *addr) {
4798   USE(instr);
4799   int64_t rel_addr = CodeRelativeAddress(addr);
4800   if (rel_addr >= 0) {
4801     AppendToOutput("(addr 0x%" PRIx64 ")", rel_addr);
4802   } else {
4803     AppendToOutput("(addr -0x%" PRIx64 ")", -rel_addr);
4804   }
4805 }
4806 
4807 
AppendCodeRelativeCodeAddressToOutput(const Instruction * instr,const void * addr)4808 void Disassembler::AppendCodeRelativeCodeAddressToOutput(
4809     const Instruction *instr, const void *addr) {
4810   AppendCodeRelativeAddressToOutput(instr, addr);
4811 }
4812 
4813 
AppendCodeRelativeDataAddressToOutput(const Instruction * instr,const void * addr)4814 void Disassembler::AppendCodeRelativeDataAddressToOutput(
4815     const Instruction *instr, const void *addr) {
4816   AppendCodeRelativeAddressToOutput(instr, addr);
4817 }
4818 
4819 
MapCodeAddress(int64_t base_address,const Instruction * instr_address)4820 void Disassembler::MapCodeAddress(int64_t base_address,
4821                                   const Instruction *instr_address) {
4822   set_code_address_offset(base_address -
4823                           reinterpret_cast<intptr_t>(instr_address));
4824 }
CodeRelativeAddress(const void * addr)4825 int64_t Disassembler::CodeRelativeAddress(const void *addr) {
4826   return reinterpret_cast<intptr_t>(addr) + code_address_offset();
4827 }
4828 
4829 
Format(const Instruction * instr,const char * mnemonic,const char * format)4830 void Disassembler::Format(const Instruction *instr,
4831                           const char *mnemonic,
4832                           const char *format) {
4833   VIXL_ASSERT(mnemonic != NULL);
4834   ResetOutput();
4835   Substitute(instr, mnemonic);
4836   if (format != NULL) {
4837     VIXL_ASSERT(buffer_pos_ < buffer_size_);
4838     buffer_[buffer_pos_++] = ' ';
4839     Substitute(instr, format);
4840   }
4841   VIXL_ASSERT(buffer_pos_ < buffer_size_);
4842   buffer_[buffer_pos_] = 0;
4843   ProcessOutput(instr);
4844 }
4845 
4846 
Substitute(const Instruction * instr,const char * string)4847 void Disassembler::Substitute(const Instruction *instr, const char *string) {
4848   char chr = *string++;
4849   while (chr != '\0') {
4850     if (chr == '\'') {
4851       string += SubstituteField(instr, string);
4852     } else {
4853       VIXL_ASSERT(buffer_pos_ < buffer_size_);
4854       buffer_[buffer_pos_++] = chr;
4855     }
4856     chr = *string++;
4857   }
4858 }
4859 
4860 
SubstituteField(const Instruction * instr,const char * format)4861 int Disassembler::SubstituteField(const Instruction *instr,
4862                                   const char *format) {
4863   switch (format[0]) {
4864     // NB. The remaining substitution prefix characters are: GJKUZ.
4865     case 'R':  // Register. X or W, selected by sf bit.
4866     case 'F':  // FP register. S or D, selected by type field.
4867     case 'V':  // Vector register, V, vector format.
4868     case 'W':
4869     case 'X':
4870     case 'B':
4871     case 'H':
4872     case 'S':
4873     case 'D':
4874     case 'Q':
4875       return SubstituteRegisterField(instr, format);
4876     case 'I':
4877       return SubstituteImmediateField(instr, format);
4878     case 'L':
4879       return SubstituteLiteralField(instr, format);
4880     case 'N':
4881       return SubstituteShiftField(instr, format);
4882     case 'P':
4883       return SubstitutePrefetchField(instr, format);
4884     case 'C':
4885       return SubstituteConditionField(instr, format);
4886     case 'E':
4887       return SubstituteExtendField(instr, format);
4888     case 'A':
4889       return SubstitutePCRelAddressField(instr, format);
4890     case 'T':
4891       return SubstituteBranchTargetField(instr, format);
4892     case 'O':
4893       return SubstituteLSRegOffsetField(instr, format);
4894     case 'M':
4895       return SubstituteBarrierField(instr, format);
4896     case 'K':
4897       return SubstituteCrField(instr, format);
4898     case 'G':
4899       return SubstituteSysOpField(instr, format);
4900     default: {
4901       VIXL_UNREACHABLE();
4902       return 1;
4903     }
4904   }
4905 }
4906 
4907 
SubstituteRegisterField(const Instruction * instr,const char * format)4908 int Disassembler::SubstituteRegisterField(const Instruction *instr,
4909                                           const char *format) {
4910   char reg_prefix = format[0];
4911   unsigned reg_num = 0;
4912   unsigned field_len = 2;
4913 
4914   switch (format[1]) {
4915     case 'd':
4916       reg_num = instr->GetRd();
4917       if (format[2] == 'q') {
4918         reg_prefix = instr->GetNEONQ() ? 'X' : 'W';
4919         field_len = 3;
4920       }
4921       break;
4922     case 'n':
4923       reg_num = instr->GetRn();
4924       break;
4925     case 'm':
4926       reg_num = instr->GetRm();
4927       switch (format[2]) {
4928         // Handle registers tagged with b (bytes), z (instruction), or
4929         // r (registers), used for address updates in
4930         // NEON load/store instructions.
4931         case 'r':
4932         case 'b':
4933         case 'z': {
4934           field_len = 3;
4935           char *eimm;
4936           int imm = static_cast<int>(strtol(&format[3], &eimm, 10));
4937           field_len += eimm - &format[3];
4938           if (reg_num == 31) {
4939             switch (format[2]) {
4940               case 'z':
4941                 imm *= (1 << instr->GetNEONLSSize());
4942                 break;
4943               case 'r':
4944                 imm *= (instr->GetNEONQ() == 0) ? kDRegSizeInBytes
4945                                                 : kQRegSizeInBytes;
4946                 break;
4947               case 'b':
4948                 break;
4949             }
4950             AppendToOutput("#%d", imm);
4951             return field_len;
4952           }
4953           break;
4954         }
4955       }
4956       break;
4957     case 'e':
4958       // This is register Rm, but using a 4-bit specifier. Used in NEON
4959       // by-element instructions.
4960       reg_num = (instr->GetRm() & 0xf);
4961       break;
4962     case 'a':
4963       reg_num = instr->GetRa();
4964       break;
4965     case 's':
4966       reg_num = instr->GetRs();
4967       break;
4968     case 't':
4969       reg_num = instr->GetRt();
4970       if (format[0] == 'V') {
4971         if ((format[2] >= '2') && (format[2] <= '4')) {
4972           // Handle consecutive vector register specifiers Vt2, Vt3 and Vt4.
4973           reg_num = (reg_num + format[2] - '1') % 32;
4974           field_len = 3;
4975         }
4976       } else {
4977         if (format[2] == '2') {
4978           // Handle register specifier Rt2.
4979           reg_num = instr->GetRt2();
4980           field_len = 3;
4981         }
4982       }
4983       break;
4984     case '(': {
4985       switch (format[2]) {
4986         case 's':
4987           reg_num = instr->GetRs();
4988           break;
4989         case 't':
4990           reg_num = instr->GetRt();
4991           break;
4992         default:
4993           VIXL_UNREACHABLE();
4994       }
4995 
4996       VIXL_ASSERT(format[3] == '+');
4997       int i = 4;
4998       int addition = 0;
4999       while (format[i] != ')') {
5000         VIXL_ASSERT((format[i] >= '0') && (format[i] <= '9'));
5001         addition *= 10;
5002         addition += format[i] - '0';
5003         ++i;
5004       }
5005       reg_num += addition;
5006       field_len = i + 1;
5007       break;
5008     }
5009     default:
5010       VIXL_UNREACHABLE();
5011   }
5012 
5013   // Increase field length for registers tagged as stack.
5014   if (format[1] != '(' && format[2] == 's') {
5015     field_len = 3;
5016   }
5017 
5018   CPURegister::RegisterType reg_type = CPURegister::kRegister;
5019   unsigned reg_size = kXRegSize;
5020 
5021   switch (reg_prefix) {
5022     case 'R':
5023       reg_prefix = instr->GetSixtyFourBits() ? 'X' : 'W';
5024       break;
5025     case 'F':
5026       switch (instr->GetFPType()) {
5027         case 3:
5028           reg_prefix = 'H';
5029           break;
5030         case 0:
5031           reg_prefix = 'S';
5032           break;
5033         default:
5034           reg_prefix = 'D';
5035       }
5036   }
5037 
5038   switch (reg_prefix) {
5039     case 'W':
5040       reg_type = CPURegister::kRegister;
5041       reg_size = kWRegSize;
5042       break;
5043     case 'X':
5044       reg_type = CPURegister::kRegister;
5045       reg_size = kXRegSize;
5046       break;
5047     case 'B':
5048       reg_type = CPURegister::kVRegister;
5049       reg_size = kBRegSize;
5050       break;
5051     case 'H':
5052       reg_type = CPURegister::kVRegister;
5053       reg_size = kHRegSize;
5054       break;
5055     case 'S':
5056       reg_type = CPURegister::kVRegister;
5057       reg_size = kSRegSize;
5058       break;
5059     case 'D':
5060       reg_type = CPURegister::kVRegister;
5061       reg_size = kDRegSize;
5062       break;
5063     case 'Q':
5064       reg_type = CPURegister::kVRegister;
5065       reg_size = kQRegSize;
5066       break;
5067     case 'V':
5068       AppendToOutput("v%d", reg_num);
5069       return field_len;
5070     default:
5071       VIXL_UNREACHABLE();
5072   }
5073 
5074   if ((reg_type == CPURegister::kRegister) && (reg_num == kZeroRegCode) &&
5075       (format[2] == 's')) {
5076     reg_num = kSPRegInternalCode;
5077   }
5078 
5079   AppendRegisterNameToOutput(instr, CPURegister(reg_num, reg_size, reg_type));
5080 
5081   return field_len;
5082 }
5083 
5084 
SubstituteImmediateField(const Instruction * instr,const char * format)5085 int Disassembler::SubstituteImmediateField(const Instruction *instr,
5086                                            const char *format) {
5087   VIXL_ASSERT(format[0] == 'I');
5088 
5089   switch (format[1]) {
5090     case 'M': {  // IMoveImm, IMoveNeg or IMoveLSL.
5091       if (format[5] == 'L') {
5092         AppendToOutput("#0x%" PRIx32, instr->GetImmMoveWide());
5093         if (instr->GetShiftMoveWide() > 0) {
5094           AppendToOutput(", lsl #%" PRId32, 16 * instr->GetShiftMoveWide());
5095         }
5096       } else {
5097         VIXL_ASSERT((format[5] == 'I') || (format[5] == 'N'));
5098         uint64_t imm = static_cast<uint64_t>(instr->GetImmMoveWide())
5099                        << (16 * instr->GetShiftMoveWide());
5100         if (format[5] == 'N') imm = ~imm;
5101         if (!instr->GetSixtyFourBits()) imm &= UINT64_C(0xffffffff);
5102         AppendToOutput("#0x%" PRIx64, imm);
5103       }
5104       return 8;
5105     }
5106     case 'L': {
5107       switch (format[2]) {
5108         case 'L': {  // ILLiteral - Immediate Load Literal.
5109           AppendToOutput("pc%+" PRId32,
5110                          instr->GetImmLLiteral() *
5111                              static_cast<int>(kLiteralEntrySize));
5112           return 9;
5113         }
5114         case 'S': {  // ILS - Immediate Load/Store.
5115                      // ILSi - As above, but an index field which must not be
5116                      // omitted even if it is zero.
5117           bool is_index = format[3] == 'i';
5118           if (is_index || (instr->GetImmLS() != 0)) {
5119             AppendToOutput(", #%" PRId32, instr->GetImmLS());
5120           }
5121           return is_index ? 4 : 3;
5122         }
5123         case 'P': {  // ILPx - Immediate Load/Store Pair, x = access size.
5124                      // ILPxi - As above, but an index field which must not be
5125                      // omitted even if it is zero.
5126           VIXL_ASSERT((format[3] >= '0') && (format[3] <= '9'));
5127           bool is_index = format[4] == 'i';
5128           if (is_index || (instr->GetImmLSPair() != 0)) {
5129             // format[3] is the scale value. Convert to a number.
5130             int scale = 1 << (format[3] - '0');
5131             AppendToOutput(", #%" PRId32, instr->GetImmLSPair() * scale);
5132           }
5133           return is_index ? 5 : 4;
5134         }
5135         case 'U': {  // ILU - Immediate Load/Store Unsigned.
5136           if (instr->GetImmLSUnsigned() != 0) {
5137             int shift = instr->GetSizeLS();
5138             AppendToOutput(", #%" PRId32, instr->GetImmLSUnsigned() << shift);
5139           }
5140           return 3;
5141         }
5142         case 'F': {  // ILF(CNR) - Immediate Rotation Value for Complex Numbers
5143           AppendToOutput("#%" PRId32, instr->GetImmRotFcmlaSca() * 90);
5144           return strlen("ILFCNR");
5145         }
5146         default: {
5147           VIXL_UNIMPLEMENTED();
5148           return 0;
5149         }
5150       }
5151     }
5152     case 'C': {  // ICondB - Immediate Conditional Branch.
5153       int64_t offset = instr->GetImmCondBranch() << 2;
5154       AppendPCRelativeOffsetToOutput(instr, offset);
5155       return 6;
5156     }
5157     case 'A': {  // IAddSub.
5158       VIXL_ASSERT(instr->GetShiftAddSub() <= 1);
5159       int64_t imm = instr->GetImmAddSub() << (12 * instr->GetShiftAddSub());
5160       AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm);
5161       return 7;
5162     }
5163     case 'F': {                // IFPHalf, IFPSingle, IFPDouble, or IFPFBits.
5164       if (format[3] == 'F') {  // IFPFbits.
5165         AppendToOutput("#%" PRId32, 64 - instr->GetFPScale());
5166         return 8;
5167       } else {
5168         AppendToOutput("#0x%" PRIx32 " (%.4f)",
5169                        instr->GetImmFP(),
5170                        format[3] == 'H'
5171                            ? FPToFloat(instr->GetImmFP16(), kIgnoreDefaultNaN)
5172                            : (format[3] == 'S') ? instr->GetImmFP32()
5173                                                 : instr->GetImmFP64());
5174         if (format[3] == 'H') {
5175           return 7;
5176         } else {
5177           return 9;
5178         }
5179       }
5180     }
5181     case 'H': {  // IH - ImmHint
5182       AppendToOutput("#%" PRId32, instr->GetImmHint());
5183       return 2;
5184     }
5185     case 'T': {  // ITri - Immediate Triangular Encoded.
5186       AppendToOutput("#0x%" PRIx64, instr->GetImmLogical());
5187       return 4;
5188     }
5189     case 'N': {  // INzcv.
5190       int nzcv = (instr->GetNzcv() << Flags_offset);
5191       AppendToOutput("#%c%c%c%c",
5192                      ((nzcv & NFlag) == 0) ? 'n' : 'N',
5193                      ((nzcv & ZFlag) == 0) ? 'z' : 'Z',
5194                      ((nzcv & CFlag) == 0) ? 'c' : 'C',
5195                      ((nzcv & VFlag) == 0) ? 'v' : 'V');
5196       return 5;
5197     }
5198     case 'P': {  // IP - Conditional compare.
5199       AppendToOutput("#%" PRId32, instr->GetImmCondCmp());
5200       return 2;
5201     }
5202     case 'B': {  // Bitfields.
5203       return SubstituteBitfieldImmediateField(instr, format);
5204     }
5205     case 'E': {  // IExtract.
5206       AppendToOutput("#%" PRId32, instr->GetImmS());
5207       return 8;
5208     }
5209     case 'S': {  // IS - Test and branch bit.
5210       AppendToOutput("#%" PRId32,
5211                      (instr->GetImmTestBranchBit5() << 5) |
5212                          instr->GetImmTestBranchBit40());
5213       return 2;
5214     }
5215     case 's': {  // Is - Shift (immediate).
5216       switch (format[2]) {
5217         case '1': {  // Is1 - SSHR.
5218           int shift = 16 << HighestSetBitPosition(instr->GetImmNEONImmh());
5219           shift -= instr->GetImmNEONImmhImmb();
5220           AppendToOutput("#%d", shift);
5221           return 3;
5222         }
5223         case '2': {  // Is2 - SLI.
5224           int shift = instr->GetImmNEONImmhImmb();
5225           shift -= 8 << HighestSetBitPosition(instr->GetImmNEONImmh());
5226           AppendToOutput("#%d", shift);
5227           return 3;
5228         }
5229         default: {
5230           VIXL_UNIMPLEMENTED();
5231           return 0;
5232         }
5233       }
5234     }
5235     case 'D': {  // IDebug - HLT and BRK instructions.
5236       AppendToOutput("#0x%" PRIx32, instr->GetImmException());
5237       return 6;
5238     }
5239     case 'V': {  // Immediate Vector.
5240       switch (format[2]) {
5241         case 'F': {
5242           switch (format[5]) {
5243             // Convert 'rot' bit encodings into equivalent angle rotation
5244             case 'A':
5245               AppendToOutput("#%" PRId32,
5246                              instr->GetImmRotFcadd() == 1 ? 270 : 90);
5247               break;
5248             case 'M':
5249               AppendToOutput("#%" PRId32, instr->GetImmRotFcmlaVec() * 90);
5250               break;
5251           }
5252           return strlen("IVFCN") + 1;
5253         }
5254         case 'E': {  // IVExtract.
5255           AppendToOutput("#%" PRId32, instr->GetImmNEONExt());
5256           return 9;
5257         }
5258         case 'B': {  // IVByElemIndex.
5259           int ret = strlen("IVByElemIndex");
5260           int vm_index = (instr->GetNEONH() << 1) | instr->GetNEONL();
5261           if ((strncmp(format,
5262                        "IVByElemIndexRot",
5263                        strlen("IVByElemIndexRot")) == 0)) {
5264             // FCMLA uses 'H' bit index when SIZE is 2, else H:L
5265             if (instr->GetNEONSize() == 2) {
5266               vm_index = instr->GetNEONH();
5267             }
5268             ret += 3;
5269           } else if (instr->GetNEONSize() == 1) {
5270             vm_index = (vm_index << 1) | instr->GetNEONM();
5271           } else if (instr->GetNEONSize() == 0) {
5272             // Half-precision FP ops use H:L:M bit index
5273             vm_index = (instr->GetNEONH() << 2) | (instr->GetNEONL() << 1) |
5274                        instr->GetNEONM();
5275           }
5276           AppendToOutput("%d", vm_index);
5277           return ret;
5278         }
5279         case 'I': {  // INS element.
5280           if (strncmp(format, "IVInsIndex", strlen("IVInsIndex")) == 0) {
5281             unsigned rd_index, rn_index;
5282             unsigned imm5 = instr->GetImmNEON5();
5283             unsigned imm4 = instr->GetImmNEON4();
5284             int tz = CountTrailingZeros(imm5, 32);
5285             if (tz <= 3) {  // Defined for tz = 0 to 3 only.
5286               rd_index = imm5 >> (tz + 1);
5287               rn_index = imm4 >> tz;
5288               if (strncmp(format, "IVInsIndex1", strlen("IVInsIndex1")) == 0) {
5289                 AppendToOutput("%d", rd_index);
5290                 return strlen("IVInsIndex1");
5291               } else if (strncmp(format,
5292                                  "IVInsIndex2",
5293                                  strlen("IVInsIndex2")) == 0) {
5294                 AppendToOutput("%d", rn_index);
5295                 return strlen("IVInsIndex2");
5296               }
5297             }
5298             return 0;
5299           }
5300           VIXL_FALLTHROUGH();
5301         }
5302         case 'L': {  // IVLSLane[0123] - suffix indicates access size shift.
5303           AppendToOutput("%d", instr->GetNEONLSIndex(format[8] - '0'));
5304           return 9;
5305         }
5306         case 'M': {  // Modified Immediate cases.
5307           if (strncmp(format, "IVMIImmFPHalf", strlen("IVMIImmFPHalf")) == 0) {
5308             AppendToOutput("#0x%" PRIx32 " (%.4f)",
5309                            instr->GetImmNEONabcdefgh(),
5310                            FPToFloat(instr->GetImmNEONFP16(),
5311                                      kIgnoreDefaultNaN));
5312             return strlen("IVMIImmFPHalf");
5313           } else if (strncmp(format,
5314                              "IVMIImmFPSingle",
5315                              strlen("IVMIImmFPSingle")) == 0) {
5316             AppendToOutput("#0x%" PRIx32 " (%.4f)",
5317                            instr->GetImmNEONabcdefgh(),
5318                            instr->GetImmNEONFP32());
5319             return strlen("IVMIImmFPSingle");
5320           } else if (strncmp(format,
5321                              "IVMIImmFPDouble",
5322                              strlen("IVMIImmFPDouble")) == 0) {
5323             AppendToOutput("#0x%" PRIx32 " (%.4f)",
5324                            instr->GetImmNEONabcdefgh(),
5325                            instr->GetImmNEONFP64());
5326             return strlen("IVMIImmFPDouble");
5327           } else if (strncmp(format, "IVMIImm8", strlen("IVMIImm8")) == 0) {
5328             uint64_t imm8 = instr->GetImmNEONabcdefgh();
5329             AppendToOutput("#0x%" PRIx64, imm8);
5330             return strlen("IVMIImm8");
5331           } else if (strncmp(format, "IVMIImm", strlen("IVMIImm")) == 0) {
5332             uint64_t imm8 = instr->GetImmNEONabcdefgh();
5333             uint64_t imm = 0;
5334             for (int i = 0; i < 8; ++i) {
5335               if (imm8 & (1 << i)) {
5336                 imm |= (UINT64_C(0xff) << (8 * i));
5337               }
5338             }
5339             AppendToOutput("#0x%" PRIx64, imm);
5340             return strlen("IVMIImm");
5341           } else if (strncmp(format,
5342                              "IVMIShiftAmt1",
5343                              strlen("IVMIShiftAmt1")) == 0) {
5344             int cmode = instr->GetNEONCmode();
5345             int shift_amount = 8 * ((cmode >> 1) & 3);
5346             AppendToOutput("#%d", shift_amount);
5347             return strlen("IVMIShiftAmt1");
5348           } else if (strncmp(format,
5349                              "IVMIShiftAmt2",
5350                              strlen("IVMIShiftAmt2")) == 0) {
5351             int cmode = instr->GetNEONCmode();
5352             int shift_amount = 8 << (cmode & 1);
5353             AppendToOutput("#%d", shift_amount);
5354             return strlen("IVMIShiftAmt2");
5355           } else {
5356             VIXL_UNIMPLEMENTED();
5357             return 0;
5358           }
5359         }
5360         default: {
5361           VIXL_UNIMPLEMENTED();
5362           return 0;
5363         }
5364       }
5365     }
5366     case 'X': {  // IX - CLREX instruction.
5367       AppendToOutput("#0x%" PRIx32, instr->GetCRm());
5368       return 2;
5369     }
5370     case 'Y': {  // IY - system register immediate.
5371       switch (instr->GetImmSystemRegister()) {
5372         case NZCV:
5373           AppendToOutput("nzcv");
5374           break;
5375         case FPCR:
5376           AppendToOutput("fpcr");
5377           break;
5378         default:
5379           AppendToOutput("S%d_%d_c%d_c%d_%d",
5380                          instr->GetSysOp0(),
5381                          instr->GetSysOp1(),
5382                          instr->GetCRn(),
5383                          instr->GetCRm(),
5384                          instr->GetSysOp2());
5385           break;
5386       }
5387       return 2;
5388     }
5389     default: {
5390       VIXL_UNIMPLEMENTED();
5391       return 0;
5392     }
5393   }
5394 }
5395 
5396 
SubstituteBitfieldImmediateField(const Instruction * instr,const char * format)5397 int Disassembler::SubstituteBitfieldImmediateField(const Instruction *instr,
5398                                                    const char *format) {
5399   VIXL_ASSERT((format[0] == 'I') && (format[1] == 'B'));
5400   unsigned r = instr->GetImmR();
5401   unsigned s = instr->GetImmS();
5402 
5403   switch (format[2]) {
5404     case 'r': {  // IBr.
5405       AppendToOutput("#%d", r);
5406       return 3;
5407     }
5408     case 's': {  // IBs+1 or IBs-r+1.
5409       if (format[3] == '+') {
5410         AppendToOutput("#%d", s + 1);
5411         return 5;
5412       } else {
5413         VIXL_ASSERT(format[3] == '-');
5414         AppendToOutput("#%d", s - r + 1);
5415         return 7;
5416       }
5417     }
5418     case 'Z': {  // IBZ-r.
5419       VIXL_ASSERT((format[3] == '-') && (format[4] == 'r'));
5420       unsigned reg_size =
5421           (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
5422       AppendToOutput("#%d", reg_size - r);
5423       return 5;
5424     }
5425     default: {
5426       VIXL_UNREACHABLE();
5427       return 0;
5428     }
5429   }
5430 }
5431 
5432 
SubstituteLiteralField(const Instruction * instr,const char * format)5433 int Disassembler::SubstituteLiteralField(const Instruction *instr,
5434                                          const char *format) {
5435   VIXL_ASSERT(strncmp(format, "LValue", 6) == 0);
5436   USE(format);
5437 
5438   const void *address = instr->GetLiteralAddress<const void *>();
5439   switch (instr->Mask(LoadLiteralMask)) {
5440     case LDR_w_lit:
5441     case LDR_x_lit:
5442     case LDRSW_x_lit:
5443     case LDR_s_lit:
5444     case LDR_d_lit:
5445     case LDR_q_lit:
5446       AppendCodeRelativeDataAddressToOutput(instr, address);
5447       break;
5448     case PRFM_lit: {
5449       // Use the prefetch hint to decide how to print the address.
5450       switch (instr->GetPrefetchHint()) {
5451         case 0x0:  // PLD: prefetch for load.
5452         case 0x2:  // PST: prepare for store.
5453           AppendCodeRelativeDataAddressToOutput(instr, address);
5454           break;
5455         case 0x1:  // PLI: preload instructions.
5456           AppendCodeRelativeCodeAddressToOutput(instr, address);
5457           break;
5458         case 0x3:  // Unallocated hint.
5459           AppendCodeRelativeAddressToOutput(instr, address);
5460           break;
5461       }
5462       break;
5463     }
5464     default:
5465       VIXL_UNREACHABLE();
5466   }
5467 
5468   return 6;
5469 }
5470 
5471 
SubstituteShiftField(const Instruction * instr,const char * format)5472 int Disassembler::SubstituteShiftField(const Instruction *instr,
5473                                        const char *format) {
5474   VIXL_ASSERT(format[0] == 'N');
5475   VIXL_ASSERT(instr->GetShiftDP() <= 0x3);
5476 
5477   switch (format[1]) {
5478     case 'D': {  // HDP.
5479       VIXL_ASSERT(instr->GetShiftDP() != ROR);
5480       VIXL_FALLTHROUGH();
5481     }
5482     case 'L': {  // HLo.
5483       if (instr->GetImmDPShift() != 0) {
5484         const char *shift_type[] = {"lsl", "lsr", "asr", "ror"};
5485         AppendToOutput(", %s #%" PRId32,
5486                        shift_type[instr->GetShiftDP()],
5487                        instr->GetImmDPShift());
5488       }
5489       return 3;
5490     }
5491     default:
5492       VIXL_UNIMPLEMENTED();
5493       return 0;
5494   }
5495 }
5496 
5497 
SubstituteConditionField(const Instruction * instr,const char * format)5498 int Disassembler::SubstituteConditionField(const Instruction *instr,
5499                                            const char *format) {
5500   VIXL_ASSERT(format[0] == 'C');
5501   const char *condition_code[] = {"eq",
5502                                   "ne",
5503                                   "hs",
5504                                   "lo",
5505                                   "mi",
5506                                   "pl",
5507                                   "vs",
5508                                   "vc",
5509                                   "hi",
5510                                   "ls",
5511                                   "ge",
5512                                   "lt",
5513                                   "gt",
5514                                   "le",
5515                                   "al",
5516                                   "nv"};
5517   int cond;
5518   switch (format[1]) {
5519     case 'B':
5520       cond = instr->GetConditionBranch();
5521       break;
5522     case 'I': {
5523       cond = InvertCondition(static_cast<Condition>(instr->GetCondition()));
5524       break;
5525     }
5526     default:
5527       cond = instr->GetCondition();
5528   }
5529   AppendToOutput("%s", condition_code[cond]);
5530   return 4;
5531 }
5532 
5533 
SubstitutePCRelAddressField(const Instruction * instr,const char * format)5534 int Disassembler::SubstitutePCRelAddressField(const Instruction *instr,
5535                                               const char *format) {
5536   VIXL_ASSERT((strcmp(format, "AddrPCRelByte") == 0) ||  // Used by `adr`.
5537               (strcmp(format, "AddrPCRelPage") == 0));   // Used by `adrp`.
5538 
5539   int64_t offset = instr->GetImmPCRel();
5540 
5541   // Compute the target address based on the effective address (after applying
5542   // code_address_offset). This is required for correct behaviour of adrp.
5543   const Instruction *base = instr + code_address_offset();
5544   if (format[9] == 'P') {
5545     offset *= kPageSize;
5546     base = AlignDown(base, kPageSize);
5547   }
5548   // Strip code_address_offset before printing, so we can use the
5549   // semantically-correct AppendCodeRelativeAddressToOutput.
5550   const void *target =
5551       reinterpret_cast<const void *>(base + offset - code_address_offset());
5552 
5553   AppendPCRelativeOffsetToOutput(instr, offset);
5554   AppendToOutput(" ");
5555   AppendCodeRelativeAddressToOutput(instr, target);
5556   return 13;
5557 }
5558 
5559 
SubstituteBranchTargetField(const Instruction * instr,const char * format)5560 int Disassembler::SubstituteBranchTargetField(const Instruction *instr,
5561                                               const char *format) {
5562   VIXL_ASSERT(strncmp(format, "TImm", 4) == 0);
5563 
5564   int64_t offset = 0;
5565   switch (format[5]) {
5566     // BImmUncn - unconditional branch immediate.
5567     case 'n':
5568       offset = instr->GetImmUncondBranch();
5569       break;
5570     // BImmCond - conditional branch immediate.
5571     case 'o':
5572       offset = instr->GetImmCondBranch();
5573       break;
5574     // BImmCmpa - compare and branch immediate.
5575     case 'm':
5576       offset = instr->GetImmCmpBranch();
5577       break;
5578     // BImmTest - test and branch immediate.
5579     case 'e':
5580       offset = instr->GetImmTestBranch();
5581       break;
5582     default:
5583       VIXL_UNIMPLEMENTED();
5584   }
5585   offset *= static_cast<int>(kInstructionSize);
5586   const void *target_address = reinterpret_cast<const void *>(instr + offset);
5587   VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
5588 
5589   AppendPCRelativeOffsetToOutput(instr, offset);
5590   AppendToOutput(" ");
5591   AppendCodeRelativeCodeAddressToOutput(instr, target_address);
5592 
5593   return 8;
5594 }
5595 
5596 
SubstituteExtendField(const Instruction * instr,const char * format)5597 int Disassembler::SubstituteExtendField(const Instruction *instr,
5598                                         const char *format) {
5599   VIXL_ASSERT(strncmp(format, "Ext", 3) == 0);
5600   VIXL_ASSERT(instr->GetExtendMode() <= 7);
5601   USE(format);
5602 
5603   const char *extend_mode[] =
5604       {"uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx"};
5605 
5606   // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit
5607   // registers becomes lsl.
5608   if (((instr->GetRd() == kZeroRegCode) || (instr->GetRn() == kZeroRegCode)) &&
5609       (((instr->GetExtendMode() == UXTW) && (instr->GetSixtyFourBits() == 0)) ||
5610        (instr->GetExtendMode() == UXTX))) {
5611     if (instr->GetImmExtendShift() > 0) {
5612       AppendToOutput(", lsl #%" PRId32, instr->GetImmExtendShift());
5613     }
5614   } else {
5615     AppendToOutput(", %s", extend_mode[instr->GetExtendMode()]);
5616     if (instr->GetImmExtendShift() > 0) {
5617       AppendToOutput(" #%" PRId32, instr->GetImmExtendShift());
5618     }
5619   }
5620   return 3;
5621 }
5622 
5623 
SubstituteLSRegOffsetField(const Instruction * instr,const char * format)5624 int Disassembler::SubstituteLSRegOffsetField(const Instruction *instr,
5625                                              const char *format) {
5626   VIXL_ASSERT(strncmp(format, "Offsetreg", 9) == 0);
5627   const char *extend_mode[] = {"undefined",
5628                                "undefined",
5629                                "uxtw",
5630                                "lsl",
5631                                "undefined",
5632                                "undefined",
5633                                "sxtw",
5634                                "sxtx"};
5635   USE(format);
5636 
5637   unsigned shift = instr->GetImmShiftLS();
5638   Extend ext = static_cast<Extend>(instr->GetExtendMode());
5639   char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x';
5640 
5641   unsigned rm = instr->GetRm();
5642   if (rm == kZeroRegCode) {
5643     AppendToOutput("%czr", reg_type);
5644   } else {
5645     AppendToOutput("%c%d", reg_type, rm);
5646   }
5647 
5648   // Extend mode UXTX is an alias for shift mode LSL here.
5649   if (!((ext == UXTX) && (shift == 0))) {
5650     AppendToOutput(", %s", extend_mode[ext]);
5651     if (shift != 0) {
5652       AppendToOutput(" #%d", instr->GetSizeLS());
5653     }
5654   }
5655   return 9;
5656 }
5657 
5658 
SubstitutePrefetchField(const Instruction * instr,const char * format)5659 int Disassembler::SubstitutePrefetchField(const Instruction *instr,
5660                                           const char *format) {
5661   VIXL_ASSERT(format[0] == 'P');
5662   USE(format);
5663 
5664   static const char *hints[] = {"ld", "li", "st"};
5665   static const char *stream_options[] = {"keep", "strm"};
5666 
5667   unsigned hint = instr->GetPrefetchHint();
5668   unsigned target = instr->GetPrefetchTarget() + 1;
5669   unsigned stream = instr->GetPrefetchStream();
5670 
5671   if ((hint >= ArrayLength(hints)) || (target > 3)) {
5672     // Unallocated prefetch operations.
5673     int prefetch_mode = instr->GetImmPrefetchOperation();
5674     AppendToOutput("#0b%c%c%c%c%c",
5675                    (prefetch_mode & (1 << 4)) ? '1' : '0',
5676                    (prefetch_mode & (1 << 3)) ? '1' : '0',
5677                    (prefetch_mode & (1 << 2)) ? '1' : '0',
5678                    (prefetch_mode & (1 << 1)) ? '1' : '0',
5679                    (prefetch_mode & (1 << 0)) ? '1' : '0');
5680   } else {
5681     VIXL_ASSERT(stream < ArrayLength(stream_options));
5682     AppendToOutput("p%sl%d%s", hints[hint], target, stream_options[stream]);
5683   }
5684   return 6;
5685 }
5686 
SubstituteBarrierField(const Instruction * instr,const char * format)5687 int Disassembler::SubstituteBarrierField(const Instruction *instr,
5688                                          const char *format) {
5689   VIXL_ASSERT(format[0] == 'M');
5690   USE(format);
5691 
5692   static const char *options[4][4] = {{"sy (0b0000)", "oshld", "oshst", "osh"},
5693                                       {"sy (0b0100)", "nshld", "nshst", "nsh"},
5694                                       {"sy (0b1000)", "ishld", "ishst", "ish"},
5695                                       {"sy (0b1100)", "ld", "st", "sy"}};
5696   int domain = instr->GetImmBarrierDomain();
5697   int type = instr->GetImmBarrierType();
5698 
5699   AppendToOutput("%s", options[domain][type]);
5700   return 1;
5701 }
5702 
SubstituteSysOpField(const Instruction * instr,const char * format)5703 int Disassembler::SubstituteSysOpField(const Instruction *instr,
5704                                        const char *format) {
5705   VIXL_ASSERT(format[0] == 'G');
5706   int op = -1;
5707   switch (format[1]) {
5708     case '1':
5709       op = instr->GetSysOp1();
5710       break;
5711     case '2':
5712       op = instr->GetSysOp2();
5713       break;
5714     default:
5715       VIXL_UNREACHABLE();
5716   }
5717   AppendToOutput("#%d", op);
5718   return 2;
5719 }
5720 
SubstituteCrField(const Instruction * instr,const char * format)5721 int Disassembler::SubstituteCrField(const Instruction *instr,
5722                                     const char *format) {
5723   VIXL_ASSERT(format[0] == 'K');
5724   int cr = -1;
5725   switch (format[1]) {
5726     case 'n':
5727       cr = instr->GetCRn();
5728       break;
5729     case 'm':
5730       cr = instr->GetCRm();
5731       break;
5732     default:
5733       VIXL_UNREACHABLE();
5734   }
5735   AppendToOutput("C%d", cr);
5736   return 2;
5737 }
5738 
ResetOutput()5739 void Disassembler::ResetOutput() {
5740   buffer_pos_ = 0;
5741   buffer_[buffer_pos_] = 0;
5742 }
5743 
5744 
AppendToOutput(const char * format,...)5745 void Disassembler::AppendToOutput(const char *format, ...) {
5746   va_list args;
5747   va_start(args, format);
5748   buffer_pos_ += vsnprintf(&buffer_[buffer_pos_],
5749                            buffer_size_ - buffer_pos_,
5750                            format,
5751                            args);
5752   va_end(args);
5753 }
5754 
5755 
Disassemble(const Instruction * instr)5756 void PrintDisassembler::Disassemble(const Instruction *instr) {
5757   Decoder decoder;
5758   if (cpu_features_auditor_ != NULL) {
5759     decoder.AppendVisitor(cpu_features_auditor_);
5760   }
5761   decoder.AppendVisitor(this);
5762   decoder.Decode(instr);
5763 }
5764 
DisassembleBuffer(const Instruction * start,const Instruction * end)5765 void PrintDisassembler::DisassembleBuffer(const Instruction *start,
5766                                           const Instruction *end) {
5767   Decoder decoder;
5768   if (cpu_features_auditor_ != NULL) {
5769     decoder.AppendVisitor(cpu_features_auditor_);
5770   }
5771   decoder.AppendVisitor(this);
5772   decoder.Decode(start, end);
5773 }
5774 
DisassembleBuffer(const Instruction * start,uint64_t size)5775 void PrintDisassembler::DisassembleBuffer(const Instruction *start,
5776                                           uint64_t size) {
5777   DisassembleBuffer(start, start + size);
5778 }
5779 
5780 
ProcessOutput(const Instruction * instr)5781 void PrintDisassembler::ProcessOutput(const Instruction *instr) {
5782   int bytes_printed = fprintf(stream_,
5783                               "0x%016" PRIx64 "  %08" PRIx32 "\t\t%s",
5784                               reinterpret_cast<uint64_t>(instr),
5785                               instr->GetInstructionBits(),
5786                               GetOutput());
5787   if (cpu_features_auditor_ != NULL) {
5788     CPUFeatures needs = cpu_features_auditor_->GetInstructionFeatures();
5789     needs.Remove(cpu_features_auditor_->GetAvailableFeatures());
5790     if (needs != CPUFeatures::None()) {
5791       // Try to align annotations. This value is arbitrary, but based on looking
5792       // good with most instructions. Note that, for historical reasons, the
5793       // disassembly itself is printed with tab characters, so bytes_printed is
5794       // _not_ equivalent to the number of occupied screen columns. However, the
5795       // prefix before the tabs is always the same length, so the annotation
5796       // indentation does not change from one line to the next.
5797       const int indent_to = 70;
5798       // Always allow some space between the instruction and the annotation.
5799       const int min_pad = 2;
5800 
5801       int pad = std::max(min_pad, (indent_to - bytes_printed));
5802       fprintf(stream_, "%*s", pad, "");
5803 
5804       std::stringstream features;
5805       features << needs;
5806       fprintf(stream_,
5807               "%s%s%s",
5808               cpu_features_prefix_,
5809               features.str().c_str(),
5810               cpu_features_suffix_);
5811     }
5812   }
5813   fprintf(stream_, "\n");
5814 }
5815 
5816 }  // namespace aarch64
5817 }  // namespace vixl
5818