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