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