• 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 <bitset>
28 #include <cstdlib>
29 #include <sstream>
30 
31 #include "disasm-aarch64.h"
32 
33 namespace vixl {
34 namespace aarch64 {
35 
36 
Disassembler()37 Disassembler::Disassembler() {
38   buffer_size_ = 256;
39   buffer_ = reinterpret_cast<char *>(malloc(buffer_size_));
40   buffer_pos_ = 0;
41   own_buffer_ = true;
42   code_address_offset_ = 0;
43 }
44 
45 
Disassembler(char * text_buffer,int buffer_size)46 Disassembler::Disassembler(char *text_buffer, int buffer_size) {
47   buffer_size_ = buffer_size;
48   buffer_ = text_buffer;
49   buffer_pos_ = 0;
50   own_buffer_ = false;
51   code_address_offset_ = 0;
52 }
53 
54 
~Disassembler()55 Disassembler::~Disassembler() {
56   if (own_buffer_) {
57     free(buffer_);
58   }
59 }
60 
61 
GetOutput()62 char *Disassembler::GetOutput() { return buffer_; }
63 
64 
VisitAddSubImmediate(const Instruction * instr)65 void Disassembler::VisitAddSubImmediate(const Instruction *instr) {
66   bool rd_is_zr = RdIsZROrSP(instr);
67   bool stack_op =
68       (rd_is_zr || RnIsZROrSP(instr)) && (instr->GetImmAddSub() == 0) ? true
69                                                                       : false;
70   const char *mnemonic = "";
71   const char *form = "'Rds, 'Rns, 'IAddSub";
72   const char *form_cmp = "'Rns, 'IAddSub";
73   const char *form_mov = "'Rds, 'Rns";
74 
75   switch (instr->Mask(AddSubImmediateMask)) {
76     case ADD_w_imm:
77     case ADD_x_imm: {
78       mnemonic = "add";
79       if (stack_op) {
80         mnemonic = "mov";
81         form = form_mov;
82       }
83       break;
84     }
85     case ADDS_w_imm:
86     case ADDS_x_imm: {
87       mnemonic = "adds";
88       if (rd_is_zr) {
89         mnemonic = "cmn";
90         form = form_cmp;
91       }
92       break;
93     }
94     case SUB_w_imm:
95     case SUB_x_imm:
96       mnemonic = "sub";
97       break;
98     case SUBS_w_imm:
99     case SUBS_x_imm: {
100       mnemonic = "subs";
101       if (rd_is_zr) {
102         mnemonic = "cmp";
103         form = form_cmp;
104       }
105       break;
106     }
107     default:
108       VIXL_UNREACHABLE();
109   }
110   Format(instr, mnemonic, form);
111 }
112 
113 
VisitAddSubShifted(const Instruction * instr)114 void Disassembler::VisitAddSubShifted(const Instruction *instr) {
115   bool rd_is_zr = RdIsZROrSP(instr);
116   bool rn_is_zr = RnIsZROrSP(instr);
117   const char *mnemonic = "";
118   const char *form = "'Rd, 'Rn, 'Rm'NDP";
119   const char *form_cmp = "'Rn, 'Rm'NDP";
120   const char *form_neg = "'Rd, 'Rm'NDP";
121 
122   switch (instr->Mask(AddSubShiftedMask)) {
123     case ADD_w_shift:
124     case ADD_x_shift:
125       mnemonic = "add";
126       break;
127     case ADDS_w_shift:
128     case ADDS_x_shift: {
129       mnemonic = "adds";
130       if (rd_is_zr) {
131         mnemonic = "cmn";
132         form = form_cmp;
133       }
134       break;
135     }
136     case SUB_w_shift:
137     case SUB_x_shift: {
138       mnemonic = "sub";
139       if (rn_is_zr) {
140         mnemonic = "neg";
141         form = form_neg;
142       }
143       break;
144     }
145     case SUBS_w_shift:
146     case SUBS_x_shift: {
147       mnemonic = "subs";
148       if (rd_is_zr) {
149         mnemonic = "cmp";
150         form = form_cmp;
151       } else if (rn_is_zr) {
152         mnemonic = "negs";
153         form = form_neg;
154       }
155       break;
156     }
157     default:
158       VIXL_UNREACHABLE();
159   }
160   Format(instr, mnemonic, form);
161 }
162 
163 
VisitAddSubExtended(const Instruction * instr)164 void Disassembler::VisitAddSubExtended(const Instruction *instr) {
165   bool rd_is_zr = RdIsZROrSP(instr);
166   const char *mnemonic = "";
167   Extend mode = static_cast<Extend>(instr->GetExtendMode());
168   const char *form = ((mode == UXTX) || (mode == SXTX)) ? "'Rds, 'Rns, 'Xm'Ext"
169                                                         : "'Rds, 'Rns, 'Wm'Ext";
170   const char *form_cmp =
171       ((mode == UXTX) || (mode == SXTX)) ? "'Rns, 'Xm'Ext" : "'Rns, 'Wm'Ext";
172 
173   switch (instr->Mask(AddSubExtendedMask)) {
174     case ADD_w_ext:
175     case ADD_x_ext:
176       mnemonic = "add";
177       break;
178     case ADDS_w_ext:
179     case ADDS_x_ext: {
180       mnemonic = "adds";
181       if (rd_is_zr) {
182         mnemonic = "cmn";
183         form = form_cmp;
184       }
185       break;
186     }
187     case SUB_w_ext:
188     case SUB_x_ext:
189       mnemonic = "sub";
190       break;
191     case SUBS_w_ext:
192     case SUBS_x_ext: {
193       mnemonic = "subs";
194       if (rd_is_zr) {
195         mnemonic = "cmp";
196         form = form_cmp;
197       }
198       break;
199     }
200     default:
201       VIXL_UNREACHABLE();
202   }
203   Format(instr, mnemonic, form);
204 }
205 
206 
VisitAddSubWithCarry(const Instruction * instr)207 void Disassembler::VisitAddSubWithCarry(const Instruction *instr) {
208   bool rn_is_zr = RnIsZROrSP(instr);
209   const char *mnemonic = "";
210   const char *form = "'Rd, 'Rn, 'Rm";
211   const char *form_neg = "'Rd, 'Rm";
212 
213   switch (instr->Mask(AddSubWithCarryMask)) {
214     case ADC_w:
215     case ADC_x:
216       mnemonic = "adc";
217       break;
218     case ADCS_w:
219     case ADCS_x:
220       mnemonic = "adcs";
221       break;
222     case SBC_w:
223     case SBC_x: {
224       mnemonic = "sbc";
225       if (rn_is_zr) {
226         mnemonic = "ngc";
227         form = form_neg;
228       }
229       break;
230     }
231     case SBCS_w:
232     case SBCS_x: {
233       mnemonic = "sbcs";
234       if (rn_is_zr) {
235         mnemonic = "ngcs";
236         form = form_neg;
237       }
238       break;
239     }
240     default:
241       VIXL_UNREACHABLE();
242   }
243   Format(instr, mnemonic, form);
244 }
245 
246 
VisitRotateRightIntoFlags(const Instruction * instr)247 void Disassembler::VisitRotateRightIntoFlags(const Instruction *instr) {
248   const char *mnemonic = "unimplemented";
249   const char *form = "(RotateRightIntoFlags)";
250 
251   switch (instr->Mask(RotateRightIntoFlagsMask)) {
252     case RMIF:
253       mnemonic = "rmif";
254       form = "'Xn, 'IRr, 'INzcv";
255       break;
256     default:
257       VIXL_UNREACHABLE();
258   }
259 
260   Format(instr, mnemonic, form);
261 }
262 
263 
VisitEvaluateIntoFlags(const Instruction * instr)264 void Disassembler::VisitEvaluateIntoFlags(const Instruction *instr) {
265   const char *mnemonic = "unimplemented";
266   const char *form = "(EvaluateIntoFlags)";
267 
268   switch (instr->Mask(EvaluateIntoFlagsMask)) {
269     case SETF8:
270       mnemonic = "setf8";
271       form = "'Wn";
272       break;
273     case SETF16:
274       mnemonic = "setf16";
275       form = "'Wn";
276       break;
277     default:
278       VIXL_UNREACHABLE();
279   }
280 
281   Format(instr, mnemonic, form);
282 }
283 
284 
VisitLogicalImmediate(const Instruction * instr)285 void Disassembler::VisitLogicalImmediate(const Instruction *instr) {
286   bool rd_is_zr = RdIsZROrSP(instr);
287   bool rn_is_zr = RnIsZROrSP(instr);
288   const char *mnemonic = "";
289   const char *form = "'Rds, 'Rn, 'ITri";
290 
291   if (instr->GetImmLogical() == 0) {
292     // The immediate encoded in the instruction is not in the expected format.
293     Format(instr, "unallocated", "(LogicalImmediate)");
294     return;
295   }
296 
297   switch (instr->Mask(LogicalImmediateMask)) {
298     case AND_w_imm:
299     case AND_x_imm:
300       mnemonic = "and";
301       break;
302     case ORR_w_imm:
303     case ORR_x_imm: {
304       mnemonic = "orr";
305       unsigned reg_size =
306           (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
307       if (rn_is_zr && !IsMovzMovnImm(reg_size, instr->GetImmLogical())) {
308         mnemonic = "mov";
309         form = "'Rds, 'ITri";
310       }
311       break;
312     }
313     case EOR_w_imm:
314     case EOR_x_imm:
315       mnemonic = "eor";
316       break;
317     case ANDS_w_imm:
318     case ANDS_x_imm: {
319       mnemonic = "ands";
320       if (rd_is_zr) {
321         mnemonic = "tst";
322         form = "'Rn, 'ITri";
323       }
324       break;
325     }
326     default:
327       VIXL_UNREACHABLE();
328   }
329   Format(instr, mnemonic, form);
330 }
331 
332 
IsMovzMovnImm(unsigned reg_size,uint64_t value)333 bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
334   VIXL_ASSERT((reg_size == kXRegSize) ||
335               ((reg_size == kWRegSize) && (value <= 0xffffffff)));
336 
337   // Test for movz: 16 bits set at positions 0, 16, 32 or 48.
338   if (((value & UINT64_C(0xffffffffffff0000)) == 0) ||
339       ((value & UINT64_C(0xffffffff0000ffff)) == 0) ||
340       ((value & UINT64_C(0xffff0000ffffffff)) == 0) ||
341       ((value & UINT64_C(0x0000ffffffffffff)) == 0)) {
342     return true;
343   }
344 
345   // Test for movn: NOT(16 bits set at positions 0, 16, 32 or 48).
346   if ((reg_size == kXRegSize) &&
347       (((~value & UINT64_C(0xffffffffffff0000)) == 0) ||
348        ((~value & UINT64_C(0xffffffff0000ffff)) == 0) ||
349        ((~value & UINT64_C(0xffff0000ffffffff)) == 0) ||
350        ((~value & UINT64_C(0x0000ffffffffffff)) == 0))) {
351     return true;
352   }
353   if ((reg_size == kWRegSize) && (((value & 0xffff0000) == 0xffff0000) ||
354                                   ((value & 0x0000ffff) == 0x0000ffff))) {
355     return true;
356   }
357   return false;
358 }
359 
360 
VisitLogicalShifted(const Instruction * instr)361 void Disassembler::VisitLogicalShifted(const Instruction *instr) {
362   bool rd_is_zr = RdIsZROrSP(instr);
363   bool rn_is_zr = RnIsZROrSP(instr);
364   const char *mnemonic = "";
365   const char *form = "'Rd, 'Rn, 'Rm'NLo";
366 
367   switch (instr->Mask(LogicalShiftedMask)) {
368     case AND_w:
369     case AND_x:
370       mnemonic = "and";
371       break;
372     case BIC_w:
373     case BIC_x:
374       mnemonic = "bic";
375       break;
376     case EOR_w:
377     case EOR_x:
378       mnemonic = "eor";
379       break;
380     case EON_w:
381     case EON_x:
382       mnemonic = "eon";
383       break;
384     case BICS_w:
385     case BICS_x:
386       mnemonic = "bics";
387       break;
388     case ANDS_w:
389     case ANDS_x: {
390       mnemonic = "ands";
391       if (rd_is_zr) {
392         mnemonic = "tst";
393         form = "'Rn, 'Rm'NLo";
394       }
395       break;
396     }
397     case ORR_w:
398     case ORR_x: {
399       mnemonic = "orr";
400       if (rn_is_zr && (instr->GetImmDPShift() == 0) &&
401           (instr->GetShiftDP() == LSL)) {
402         mnemonic = "mov";
403         form = "'Rd, 'Rm";
404       }
405       break;
406     }
407     case ORN_w:
408     case ORN_x: {
409       mnemonic = "orn";
410       if (rn_is_zr) {
411         mnemonic = "mvn";
412         form = "'Rd, 'Rm'NLo";
413       }
414       break;
415     }
416     default:
417       VIXL_UNREACHABLE();
418   }
419 
420   Format(instr, mnemonic, form);
421 }
422 
423 
VisitConditionalCompareRegister(const Instruction * instr)424 void Disassembler::VisitConditionalCompareRegister(const Instruction *instr) {
425   const char *mnemonic = "";
426   const char *form = "'Rn, 'Rm, 'INzcv, 'Cond";
427 
428   switch (instr->Mask(ConditionalCompareRegisterMask)) {
429     case CCMN_w:
430     case CCMN_x:
431       mnemonic = "ccmn";
432       break;
433     case CCMP_w:
434     case CCMP_x:
435       mnemonic = "ccmp";
436       break;
437     default:
438       VIXL_UNREACHABLE();
439   }
440   Format(instr, mnemonic, form);
441 }
442 
443 
VisitConditionalCompareImmediate(const Instruction * instr)444 void Disassembler::VisitConditionalCompareImmediate(const Instruction *instr) {
445   const char *mnemonic = "";
446   const char *form = "'Rn, 'IP, 'INzcv, 'Cond";
447 
448   switch (instr->Mask(ConditionalCompareImmediateMask)) {
449     case CCMN_w_imm:
450     case CCMN_x_imm:
451       mnemonic = "ccmn";
452       break;
453     case CCMP_w_imm:
454     case CCMP_x_imm:
455       mnemonic = "ccmp";
456       break;
457     default:
458       VIXL_UNREACHABLE();
459   }
460   Format(instr, mnemonic, form);
461 }
462 
463 
VisitConditionalSelect(const Instruction * instr)464 void Disassembler::VisitConditionalSelect(const Instruction *instr) {
465   bool rnm_is_zr = (RnIsZROrSP(instr) && RmIsZROrSP(instr));
466   bool rn_is_rm = (instr->GetRn() == instr->GetRm());
467   const char *mnemonic = "";
468   const char *form = "'Rd, 'Rn, 'Rm, 'Cond";
469   const char *form_test = "'Rd, 'CInv";
470   const char *form_update = "'Rd, 'Rn, 'CInv";
471 
472   Condition cond = static_cast<Condition>(instr->GetCondition());
473   bool invertible_cond = (cond != al) && (cond != nv);
474 
475   switch (instr->Mask(ConditionalSelectMask)) {
476     case CSEL_w:
477     case CSEL_x:
478       mnemonic = "csel";
479       break;
480     case CSINC_w:
481     case CSINC_x: {
482       mnemonic = "csinc";
483       if (rnm_is_zr && invertible_cond) {
484         mnemonic = "cset";
485         form = form_test;
486       } else if (rn_is_rm && invertible_cond) {
487         mnemonic = "cinc";
488         form = form_update;
489       }
490       break;
491     }
492     case CSINV_w:
493     case CSINV_x: {
494       mnemonic = "csinv";
495       if (rnm_is_zr && invertible_cond) {
496         mnemonic = "csetm";
497         form = form_test;
498       } else if (rn_is_rm && invertible_cond) {
499         mnemonic = "cinv";
500         form = form_update;
501       }
502       break;
503     }
504     case CSNEG_w:
505     case CSNEG_x: {
506       mnemonic = "csneg";
507       if (rn_is_rm && invertible_cond) {
508         mnemonic = "cneg";
509         form = form_update;
510       }
511       break;
512     }
513     default:
514       VIXL_UNREACHABLE();
515   }
516   Format(instr, mnemonic, form);
517 }
518 
519 
VisitBitfield(const Instruction * instr)520 void Disassembler::VisitBitfield(const Instruction *instr) {
521   unsigned s = instr->GetImmS();
522   unsigned r = instr->GetImmR();
523   unsigned rd_size_minus_1 =
524       ((instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize) - 1;
525   const char *mnemonic = "";
526   const char *form = "";
527   const char *form_shift_right = "'Rd, 'Rn, 'IBr";
528   const char *form_extend = "'Rd, 'Wn";
529   const char *form_bfiz = "'Rd, 'Rn, 'IBZ-r, 'IBs+1";
530   const char *form_bfc = "'Rd, 'IBZ-r, 'IBs+1";
531   const char *form_bfx = "'Rd, 'Rn, 'IBr, 'IBs-r+1";
532   const char *form_lsl = "'Rd, 'Rn, 'IBZ-r";
533 
534   switch (instr->Mask(BitfieldMask)) {
535     case SBFM_w:
536     case SBFM_x: {
537       mnemonic = "sbfx";
538       form = form_bfx;
539       if (r == 0) {
540         form = form_extend;
541         if (s == 7) {
542           mnemonic = "sxtb";
543         } else if (s == 15) {
544           mnemonic = "sxth";
545         } else if ((s == 31) && (instr->GetSixtyFourBits() == 1)) {
546           mnemonic = "sxtw";
547         } else {
548           form = form_bfx;
549         }
550       } else if (s == rd_size_minus_1) {
551         mnemonic = "asr";
552         form = form_shift_right;
553       } else if (s < r) {
554         mnemonic = "sbfiz";
555         form = form_bfiz;
556       }
557       break;
558     }
559     case UBFM_w:
560     case UBFM_x: {
561       mnemonic = "ubfx";
562       form = form_bfx;
563       if (r == 0) {
564         form = form_extend;
565         if (s == 7) {
566           mnemonic = "uxtb";
567         } else if (s == 15) {
568           mnemonic = "uxth";
569         } else {
570           form = form_bfx;
571         }
572       }
573       if (s == rd_size_minus_1) {
574         mnemonic = "lsr";
575         form = form_shift_right;
576       } else if (r == s + 1) {
577         mnemonic = "lsl";
578         form = form_lsl;
579       } else if (s < r) {
580         mnemonic = "ubfiz";
581         form = form_bfiz;
582       }
583       break;
584     }
585     case BFM_w:
586     case BFM_x: {
587       mnemonic = "bfxil";
588       form = form_bfx;
589       if (s < r) {
590         if (instr->GetRn() == kZeroRegCode) {
591           mnemonic = "bfc";
592           form = form_bfc;
593         } else {
594           mnemonic = "bfi";
595           form = form_bfiz;
596         }
597       }
598     }
599   }
600   Format(instr, mnemonic, form);
601 }
602 
603 
VisitExtract(const Instruction * instr)604 void Disassembler::VisitExtract(const Instruction *instr) {
605   const char *mnemonic = "";
606   const char *form = "'Rd, 'Rn, 'Rm, 'IExtract";
607 
608   switch (instr->Mask(ExtractMask)) {
609     case EXTR_w:
610     case EXTR_x: {
611       if (instr->GetRn() == instr->GetRm()) {
612         mnemonic = "ror";
613         form = "'Rd, 'Rn, 'IExtract";
614       } else {
615         mnemonic = "extr";
616       }
617       break;
618     }
619     default:
620       VIXL_UNREACHABLE();
621   }
622   Format(instr, mnemonic, form);
623 }
624 
625 
VisitPCRelAddressing(const Instruction * instr)626 void Disassembler::VisitPCRelAddressing(const Instruction *instr) {
627   switch (instr->Mask(PCRelAddressingMask)) {
628     case ADR:
629       Format(instr, "adr", "'Xd, 'AddrPCRelByte");
630       break;
631     case ADRP:
632       Format(instr, "adrp", "'Xd, 'AddrPCRelPage");
633       break;
634     default:
635       Format(instr, "unimplemented", "(PCRelAddressing)");
636   }
637 }
638 
639 
VisitConditionalBranch(const Instruction * instr)640 void Disassembler::VisitConditionalBranch(const Instruction *instr) {
641   switch (instr->Mask(ConditionalBranchMask)) {
642     case B_cond:
643       Format(instr, "b.'CBrn", "'TImmCond");
644       break;
645     default:
646       VIXL_UNREACHABLE();
647   }
648 }
649 
650 
VisitUnconditionalBranchToRegister(const Instruction * instr)651 void Disassembler::VisitUnconditionalBranchToRegister(
652     const Instruction *instr) {
653   const char *mnemonic = "unimplemented";
654   const char *form;
655 
656   switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
657     case BR:
658       mnemonic = "br";
659       form = "'Xn";
660       break;
661     case BLR:
662       mnemonic = "blr";
663       form = "'Xn";
664       break;
665     case RET: {
666       mnemonic = "ret";
667       if (instr->GetRn() == kLinkRegCode) {
668         form = NULL;
669       } else {
670         form = "'Xn";
671       }
672       break;
673     }
674     case BRAAZ:
675       mnemonic = "braaz";
676       form = "'Xn";
677       break;
678     case BRABZ:
679       mnemonic = "brabz";
680       form = "'Xn";
681       break;
682     case BLRAAZ:
683       mnemonic = "blraaz";
684       form = "'Xn";
685       break;
686     case BLRABZ:
687       mnemonic = "blrabz";
688       form = "'Xn";
689       break;
690     case RETAA:
691       mnemonic = "retaa";
692       form = NULL;
693       break;
694     case RETAB:
695       mnemonic = "retab";
696       form = NULL;
697       break;
698     case BRAA:
699       mnemonic = "braa";
700       form = "'Xn, 'Xds";
701       break;
702     case BRAB:
703       mnemonic = "brab";
704       form = "'Xn, 'Xds";
705       break;
706     case BLRAA:
707       mnemonic = "blraa";
708       form = "'Xn, 'Xds";
709       break;
710     case BLRAB:
711       mnemonic = "blrab";
712       form = "'Xn, 'Xds";
713       break;
714     default:
715       form = "(UnconditionalBranchToRegister)";
716   }
717   Format(instr, mnemonic, form);
718 }
719 
720 
VisitUnconditionalBranch(const Instruction * instr)721 void Disassembler::VisitUnconditionalBranch(const Instruction *instr) {
722   const char *mnemonic = "";
723   const char *form = "'TImmUncn";
724 
725   switch (instr->Mask(UnconditionalBranchMask)) {
726     case B:
727       mnemonic = "b";
728       break;
729     case BL:
730       mnemonic = "bl";
731       break;
732     default:
733       VIXL_UNREACHABLE();
734   }
735   Format(instr, mnemonic, form);
736 }
737 
738 
VisitDataProcessing1Source(const Instruction * instr)739 void Disassembler::VisitDataProcessing1Source(const Instruction *instr) {
740   const char *mnemonic = "";
741   const char *form = "'Rd, 'Rn";
742 
743   switch (instr->Mask(DataProcessing1SourceMask)) {
744 #define FORMAT(A, B) \
745   case A##_w:        \
746   case A##_x:        \
747     mnemonic = B;    \
748     break;
749     FORMAT(RBIT, "rbit");
750     FORMAT(REV16, "rev16");
751     FORMAT(REV, "rev");
752     FORMAT(CLZ, "clz");
753     FORMAT(CLS, "cls");
754 #undef FORMAT
755 
756 #define PAUTH_VARIATIONS(V) \
757   V(PACI, "paci")           \
758   V(PACD, "pacd")           \
759   V(AUTI, "auti")           \
760   V(AUTD, "autd")
761 #define PAUTH_CASE(NAME, MN) \
762   case NAME##A:              \
763     mnemonic = MN "a";       \
764     form = "'Xd, 'Xns";      \
765     break;                   \
766   case NAME##ZA:             \
767     mnemonic = MN "za";      \
768     form = "'Xd";            \
769     break;                   \
770   case NAME##B:              \
771     mnemonic = MN "b";       \
772     form = "'Xd, 'Xns";      \
773     break;                   \
774   case NAME##ZB:             \
775     mnemonic = MN "zb";      \
776     form = "'Xd";            \
777     break;
778 
779     PAUTH_VARIATIONS(PAUTH_CASE)
780 #undef PAUTH_CASE
781 
782     case XPACI:
783       mnemonic = "xpaci";
784       form = "'Xd";
785       break;
786     case XPACD:
787       mnemonic = "xpacd";
788       form = "'Xd";
789       break;
790     case REV32_x:
791       mnemonic = "rev32";
792       break;
793     default:
794       VIXL_UNREACHABLE();
795   }
796   Format(instr, mnemonic, form);
797 }
798 
799 
VisitDataProcessing2Source(const Instruction * instr)800 void Disassembler::VisitDataProcessing2Source(const Instruction *instr) {
801   const char *mnemonic = "unimplemented";
802   const char *form = "'Rd, 'Rn, 'Rm";
803   const char *form_wwx = "'Wd, 'Wn, 'Xm";
804 
805   switch (instr->Mask(DataProcessing2SourceMask)) {
806 #define FORMAT(A, B) \
807   case A##_w:        \
808   case A##_x:        \
809     mnemonic = B;    \
810     break;
811     FORMAT(UDIV, "udiv");
812     FORMAT(SDIV, "sdiv");
813     FORMAT(LSLV, "lsl");
814     FORMAT(LSRV, "lsr");
815     FORMAT(ASRV, "asr");
816     FORMAT(RORV, "ror");
817 #undef FORMAT
818     case PACGA:
819       mnemonic = "pacga";
820       form = "'Xd, 'Xn, 'Xms";
821       break;
822     case CRC32B:
823       mnemonic = "crc32b";
824       break;
825     case CRC32H:
826       mnemonic = "crc32h";
827       break;
828     case CRC32W:
829       mnemonic = "crc32w";
830       break;
831     case CRC32X:
832       mnemonic = "crc32x";
833       form = form_wwx;
834       break;
835     case CRC32CB:
836       mnemonic = "crc32cb";
837       break;
838     case CRC32CH:
839       mnemonic = "crc32ch";
840       break;
841     case CRC32CW:
842       mnemonic = "crc32cw";
843       break;
844     case CRC32CX:
845       mnemonic = "crc32cx";
846       form = form_wwx;
847       break;
848     default:
849       form = "(DataProcessing2Source)";
850   }
851   Format(instr, mnemonic, form);
852 }
853 
854 
VisitDataProcessing3Source(const Instruction * instr)855 void Disassembler::VisitDataProcessing3Source(const Instruction *instr) {
856   bool ra_is_zr = RaIsZROrSP(instr);
857   const char *mnemonic = "";
858   const char *form = "'Xd, 'Wn, 'Wm, 'Xa";
859   const char *form_rrr = "'Rd, 'Rn, 'Rm";
860   const char *form_rrrr = "'Rd, 'Rn, 'Rm, 'Ra";
861   const char *form_xww = "'Xd, 'Wn, 'Wm";
862   const char *form_xxx = "'Xd, 'Xn, 'Xm";
863 
864   switch (instr->Mask(DataProcessing3SourceMask)) {
865     case MADD_w:
866     case MADD_x: {
867       mnemonic = "madd";
868       form = form_rrrr;
869       if (ra_is_zr) {
870         mnemonic = "mul";
871         form = form_rrr;
872       }
873       break;
874     }
875     case MSUB_w:
876     case MSUB_x: {
877       mnemonic = "msub";
878       form = form_rrrr;
879       if (ra_is_zr) {
880         mnemonic = "mneg";
881         form = form_rrr;
882       }
883       break;
884     }
885     case SMADDL_x: {
886       mnemonic = "smaddl";
887       if (ra_is_zr) {
888         mnemonic = "smull";
889         form = form_xww;
890       }
891       break;
892     }
893     case SMSUBL_x: {
894       mnemonic = "smsubl";
895       if (ra_is_zr) {
896         mnemonic = "smnegl";
897         form = form_xww;
898       }
899       break;
900     }
901     case UMADDL_x: {
902       mnemonic = "umaddl";
903       if (ra_is_zr) {
904         mnemonic = "umull";
905         form = form_xww;
906       }
907       break;
908     }
909     case UMSUBL_x: {
910       mnemonic = "umsubl";
911       if (ra_is_zr) {
912         mnemonic = "umnegl";
913         form = form_xww;
914       }
915       break;
916     }
917     case SMULH_x: {
918       mnemonic = "smulh";
919       form = form_xxx;
920       break;
921     }
922     case UMULH_x: {
923       mnemonic = "umulh";
924       form = form_xxx;
925       break;
926     }
927     default:
928       VIXL_UNREACHABLE();
929   }
930   Format(instr, mnemonic, form);
931 }
932 
933 
VisitCompareBranch(const Instruction * instr)934 void Disassembler::VisitCompareBranch(const Instruction *instr) {
935   const char *mnemonic = "";
936   const char *form = "'Rt, 'TImmCmpa";
937 
938   switch (instr->Mask(CompareBranchMask)) {
939     case CBZ_w:
940     case CBZ_x:
941       mnemonic = "cbz";
942       break;
943     case CBNZ_w:
944     case CBNZ_x:
945       mnemonic = "cbnz";
946       break;
947     default:
948       VIXL_UNREACHABLE();
949   }
950   Format(instr, mnemonic, form);
951 }
952 
953 
VisitTestBranch(const Instruction * instr)954 void Disassembler::VisitTestBranch(const Instruction *instr) {
955   const char *mnemonic = "";
956   // If the top bit of the immediate is clear, the tested register is
957   // disassembled as Wt, otherwise Xt. As the top bit of the immediate is
958   // encoded in bit 31 of the instruction, we can reuse the Rt form, which
959   // uses bit 31 (normally "sf") to choose the register size.
960   const char *form = "'Rt, 'It, 'TImmTest";
961 
962   switch (instr->Mask(TestBranchMask)) {
963     case TBZ:
964       mnemonic = "tbz";
965       break;
966     case TBNZ:
967       mnemonic = "tbnz";
968       break;
969     default:
970       VIXL_UNREACHABLE();
971   }
972   Format(instr, mnemonic, form);
973 }
974 
975 
VisitMoveWideImmediate(const Instruction * instr)976 void Disassembler::VisitMoveWideImmediate(const Instruction *instr) {
977   const char *mnemonic = "";
978   const char *form = "'Rd, 'IMoveImm";
979 
980   // Print the shift separately for movk, to make it clear which half word will
981   // be overwritten. Movn and movz print the computed immediate, which includes
982   // shift calculation.
983   switch (instr->Mask(MoveWideImmediateMask)) {
984     case MOVN_w:
985     case MOVN_x:
986       if ((instr->GetImmMoveWide()) || (instr->GetShiftMoveWide() == 0)) {
987         if ((instr->GetSixtyFourBits() == 0) &&
988             (instr->GetImmMoveWide() == 0xffff)) {
989           mnemonic = "movn";
990         } else {
991           mnemonic = "mov";
992           form = "'Rd, 'IMoveNeg";
993         }
994       } else {
995         mnemonic = "movn";
996       }
997       break;
998     case MOVZ_w:
999     case MOVZ_x:
1000       if ((instr->GetImmMoveWide()) || (instr->GetShiftMoveWide() == 0))
1001         mnemonic = "mov";
1002       else
1003         mnemonic = "movz";
1004       break;
1005     case MOVK_w:
1006     case MOVK_x:
1007       mnemonic = "movk";
1008       form = "'Rd, 'IMoveLSL";
1009       break;
1010     default:
1011       VIXL_UNREACHABLE();
1012   }
1013   Format(instr, mnemonic, form);
1014 }
1015 
1016 
1017 #define LOAD_STORE_LIST(V)   \
1018   V(STRB_w, "strb", "'Wt")   \
1019   V(STRH_w, "strh", "'Wt")   \
1020   V(STR_w, "str", "'Wt")     \
1021   V(STR_x, "str", "'Xt")     \
1022   V(LDRB_w, "ldrb", "'Wt")   \
1023   V(LDRH_w, "ldrh", "'Wt")   \
1024   V(LDR_w, "ldr", "'Wt")     \
1025   V(LDR_x, "ldr", "'Xt")     \
1026   V(LDRSB_x, "ldrsb", "'Xt") \
1027   V(LDRSH_x, "ldrsh", "'Xt") \
1028   V(LDRSW_x, "ldrsw", "'Xt") \
1029   V(LDRSB_w, "ldrsb", "'Wt") \
1030   V(LDRSH_w, "ldrsh", "'Wt") \
1031   V(STR_b, "str", "'Bt")     \
1032   V(STR_h, "str", "'Ht")     \
1033   V(STR_s, "str", "'St")     \
1034   V(STR_d, "str", "'Dt")     \
1035   V(LDR_b, "ldr", "'Bt")     \
1036   V(LDR_h, "ldr", "'Ht")     \
1037   V(LDR_s, "ldr", "'St")     \
1038   V(LDR_d, "ldr", "'Dt")     \
1039   V(STR_q, "str", "'Qt")     \
1040   V(LDR_q, "ldr", "'Qt")
1041 
VisitLoadStorePreIndex(const Instruction * instr)1042 void Disassembler::VisitLoadStorePreIndex(const Instruction *instr) {
1043   const char *mnemonic = "unimplemented";
1044   const char *form = "(LoadStorePreIndex)";
1045 
1046   switch (instr->Mask(LoadStorePreIndexMask)) {
1047 #define LS_PREINDEX(A, B, C)   \
1048   case A##_pre:                \
1049     mnemonic = B;              \
1050     form = C ", ['Xns'ILSi]!"; \
1051     break;
1052     LOAD_STORE_LIST(LS_PREINDEX)
1053 #undef LS_PREINDEX
1054   }
1055   Format(instr, mnemonic, form);
1056 }
1057 
1058 
VisitLoadStorePostIndex(const Instruction * instr)1059 void Disassembler::VisitLoadStorePostIndex(const Instruction *instr) {
1060   const char *mnemonic = "unimplemented";
1061   const char *form = "(LoadStorePostIndex)";
1062 
1063   switch (instr->Mask(LoadStorePostIndexMask)) {
1064 #define LS_POSTINDEX(A, B, C) \
1065   case A##_post:              \
1066     mnemonic = B;             \
1067     form = C ", ['Xns]'ILSi"; \
1068     break;
1069     LOAD_STORE_LIST(LS_POSTINDEX)
1070 #undef LS_POSTINDEX
1071   }
1072   Format(instr, mnemonic, form);
1073 }
1074 
1075 
VisitLoadStoreUnsignedOffset(const Instruction * instr)1076 void Disassembler::VisitLoadStoreUnsignedOffset(const Instruction *instr) {
1077   const char *mnemonic = "unimplemented";
1078   const char *form = "(LoadStoreUnsignedOffset)";
1079 
1080   switch (instr->Mask(LoadStoreUnsignedOffsetMask)) {
1081 #define LS_UNSIGNEDOFFSET(A, B, C) \
1082   case A##_unsigned:               \
1083     mnemonic = B;                  \
1084     form = C ", ['Xns'ILU]";       \
1085     break;
1086     LOAD_STORE_LIST(LS_UNSIGNEDOFFSET)
1087 #undef LS_UNSIGNEDOFFSET
1088     case PRFM_unsigned:
1089       mnemonic = "prfm";
1090       form = "'prefOp, ['Xns'ILU]";
1091   }
1092   Format(instr, mnemonic, form);
1093 }
1094 
1095 
VisitLoadStoreRCpcUnscaledOffset(const Instruction * instr)1096 void Disassembler::VisitLoadStoreRCpcUnscaledOffset(const Instruction *instr) {
1097   const char *mnemonic;
1098   const char *form = "'Wt, ['Xns'ILS]";
1099   const char *form_x = "'Xt, ['Xns'ILS]";
1100 
1101   switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
1102     case STLURB:
1103       mnemonic = "stlurb";
1104       break;
1105     case LDAPURB:
1106       mnemonic = "ldapurb";
1107       break;
1108     case LDAPURSB_w:
1109       mnemonic = "ldapursb";
1110       break;
1111     case LDAPURSB_x:
1112       mnemonic = "ldapursb";
1113       form = form_x;
1114       break;
1115     case STLURH:
1116       mnemonic = "stlurh";
1117       break;
1118     case LDAPURH:
1119       mnemonic = "ldapurh";
1120       break;
1121     case LDAPURSH_w:
1122       mnemonic = "ldapursh";
1123       break;
1124     case LDAPURSH_x:
1125       mnemonic = "ldapursh";
1126       form = form_x;
1127       break;
1128     case STLUR_w:
1129       mnemonic = "stlur";
1130       break;
1131     case LDAPUR_w:
1132       mnemonic = "ldapur";
1133       break;
1134     case LDAPURSW:
1135       mnemonic = "ldapursw";
1136       form = form_x;
1137       break;
1138     case STLUR_x:
1139       mnemonic = "stlur";
1140       form = form_x;
1141       break;
1142     case LDAPUR_x:
1143       mnemonic = "ldapur";
1144       form = form_x;
1145       break;
1146     default:
1147       mnemonic = "unimplemented";
1148       form = "(LoadStoreRCpcUnscaledOffset)";
1149   }
1150 
1151   Format(instr, mnemonic, form);
1152 }
1153 
1154 
VisitLoadStoreRegisterOffset(const Instruction * instr)1155 void Disassembler::VisitLoadStoreRegisterOffset(const Instruction *instr) {
1156   const char *mnemonic = "unimplemented";
1157   const char *form = "(LoadStoreRegisterOffset)";
1158 
1159   switch (instr->Mask(LoadStoreRegisterOffsetMask)) {
1160 #define LS_REGISTEROFFSET(A, B, C)   \
1161   case A##_reg:                      \
1162     mnemonic = B;                    \
1163     form = C ", ['Xns, 'Offsetreg]"; \
1164     break;
1165     LOAD_STORE_LIST(LS_REGISTEROFFSET)
1166 #undef LS_REGISTEROFFSET
1167     case PRFM_reg:
1168       mnemonic = "prfm";
1169       form = "'prefOp, ['Xns, 'Offsetreg]";
1170   }
1171   Format(instr, mnemonic, form);
1172 }
1173 
1174 
VisitLoadStoreUnscaledOffset(const Instruction * instr)1175 void Disassembler::VisitLoadStoreUnscaledOffset(const Instruction *instr) {
1176   const char *mnemonic = "unimplemented";
1177   const char *form = "'Wt, ['Xns'ILS]";
1178   const char *form_x = "'Xt, ['Xns'ILS]";
1179   const char *form_b = "'Bt, ['Xns'ILS]";
1180   const char *form_h = "'Ht, ['Xns'ILS]";
1181   const char *form_s = "'St, ['Xns'ILS]";
1182   const char *form_d = "'Dt, ['Xns'ILS]";
1183   const char *form_q = "'Qt, ['Xns'ILS]";
1184   const char *form_prefetch = "'prefOp, ['Xns'ILS]";
1185 
1186   switch (instr->Mask(LoadStoreUnscaledOffsetMask)) {
1187     case STURB_w:
1188       mnemonic = "sturb";
1189       break;
1190     case STURH_w:
1191       mnemonic = "sturh";
1192       break;
1193     case STUR_w:
1194       mnemonic = "stur";
1195       break;
1196     case STUR_x:
1197       mnemonic = "stur";
1198       form = form_x;
1199       break;
1200     case STUR_b:
1201       mnemonic = "stur";
1202       form = form_b;
1203       break;
1204     case STUR_h:
1205       mnemonic = "stur";
1206       form = form_h;
1207       break;
1208     case STUR_s:
1209       mnemonic = "stur";
1210       form = form_s;
1211       break;
1212     case STUR_d:
1213       mnemonic = "stur";
1214       form = form_d;
1215       break;
1216     case STUR_q:
1217       mnemonic = "stur";
1218       form = form_q;
1219       break;
1220     case LDURB_w:
1221       mnemonic = "ldurb";
1222       break;
1223     case LDURH_w:
1224       mnemonic = "ldurh";
1225       break;
1226     case LDUR_w:
1227       mnemonic = "ldur";
1228       break;
1229     case LDUR_x:
1230       mnemonic = "ldur";
1231       form = form_x;
1232       break;
1233     case LDUR_b:
1234       mnemonic = "ldur";
1235       form = form_b;
1236       break;
1237     case LDUR_h:
1238       mnemonic = "ldur";
1239       form = form_h;
1240       break;
1241     case LDUR_s:
1242       mnemonic = "ldur";
1243       form = form_s;
1244       break;
1245     case LDUR_d:
1246       mnemonic = "ldur";
1247       form = form_d;
1248       break;
1249     case LDUR_q:
1250       mnemonic = "ldur";
1251       form = form_q;
1252       break;
1253     case LDURSB_x:
1254       form = form_x;
1255       VIXL_FALLTHROUGH();
1256     case LDURSB_w:
1257       mnemonic = "ldursb";
1258       break;
1259     case LDURSH_x:
1260       form = form_x;
1261       VIXL_FALLTHROUGH();
1262     case LDURSH_w:
1263       mnemonic = "ldursh";
1264       break;
1265     case LDURSW_x:
1266       mnemonic = "ldursw";
1267       form = form_x;
1268       break;
1269     case PRFUM:
1270       mnemonic = "prfum";
1271       form = form_prefetch;
1272       break;
1273     default:
1274       form = "(LoadStoreUnscaledOffset)";
1275   }
1276   Format(instr, mnemonic, form);
1277 }
1278 
1279 
VisitLoadLiteral(const Instruction * instr)1280 void Disassembler::VisitLoadLiteral(const Instruction *instr) {
1281   const char *mnemonic = "ldr";
1282   const char *form = "(LoadLiteral)";
1283 
1284   switch (instr->Mask(LoadLiteralMask)) {
1285     case LDR_w_lit:
1286       form = "'Wt, 'ILLiteral 'LValue";
1287       break;
1288     case LDR_x_lit:
1289       form = "'Xt, 'ILLiteral 'LValue";
1290       break;
1291     case LDR_s_lit:
1292       form = "'St, 'ILLiteral 'LValue";
1293       break;
1294     case LDR_d_lit:
1295       form = "'Dt, 'ILLiteral 'LValue";
1296       break;
1297     case LDR_q_lit:
1298       form = "'Qt, 'ILLiteral 'LValue";
1299       break;
1300     case LDRSW_x_lit: {
1301       mnemonic = "ldrsw";
1302       form = "'Xt, 'ILLiteral 'LValue";
1303       break;
1304     }
1305     case PRFM_lit: {
1306       mnemonic = "prfm";
1307       form = "'prefOp, 'ILLiteral 'LValue";
1308       break;
1309     }
1310     default:
1311       mnemonic = "unimplemented";
1312   }
1313   Format(instr, mnemonic, form);
1314 }
1315 
1316 
1317 #define LOAD_STORE_PAIR_LIST(V)         \
1318   V(STP_w, "stp", "'Wt, 'Wt2", "2")     \
1319   V(LDP_w, "ldp", "'Wt, 'Wt2", "2")     \
1320   V(LDPSW_x, "ldpsw", "'Xt, 'Xt2", "2") \
1321   V(STP_x, "stp", "'Xt, 'Xt2", "3")     \
1322   V(LDP_x, "ldp", "'Xt, 'Xt2", "3")     \
1323   V(STP_s, "stp", "'St, 'St2", "2")     \
1324   V(LDP_s, "ldp", "'St, 'St2", "2")     \
1325   V(STP_d, "stp", "'Dt, 'Dt2", "3")     \
1326   V(LDP_d, "ldp", "'Dt, 'Dt2", "3")     \
1327   V(LDP_q, "ldp", "'Qt, 'Qt2", "4")     \
1328   V(STP_q, "stp", "'Qt, 'Qt2", "4")
1329 
VisitLoadStorePairPostIndex(const Instruction * instr)1330 void Disassembler::VisitLoadStorePairPostIndex(const Instruction *instr) {
1331   const char *mnemonic = "unimplemented";
1332   const char *form = "(LoadStorePairPostIndex)";
1333 
1334   switch (instr->Mask(LoadStorePairPostIndexMask)) {
1335 #define LSP_POSTINDEX(A, B, C, D)  \
1336   case A##_post:                   \
1337     mnemonic = B;                  \
1338     form = C ", ['Xns]'ILP" D "i"; \
1339     break;
1340     LOAD_STORE_PAIR_LIST(LSP_POSTINDEX)
1341 #undef LSP_POSTINDEX
1342   }
1343   Format(instr, mnemonic, form);
1344 }
1345 
1346 
VisitLoadStorePairPreIndex(const Instruction * instr)1347 void Disassembler::VisitLoadStorePairPreIndex(const Instruction *instr) {
1348   const char *mnemonic = "unimplemented";
1349   const char *form = "(LoadStorePairPreIndex)";
1350 
1351   switch (instr->Mask(LoadStorePairPreIndexMask)) {
1352 #define LSP_PREINDEX(A, B, C, D)    \
1353   case A##_pre:                     \
1354     mnemonic = B;                   \
1355     form = C ", ['Xns'ILP" D "i]!"; \
1356     break;
1357     LOAD_STORE_PAIR_LIST(LSP_PREINDEX)
1358 #undef LSP_PREINDEX
1359   }
1360   Format(instr, mnemonic, form);
1361 }
1362 
1363 
VisitLoadStorePairOffset(const Instruction * instr)1364 void Disassembler::VisitLoadStorePairOffset(const Instruction *instr) {
1365   const char *mnemonic = "unimplemented";
1366   const char *form = "(LoadStorePairOffset)";
1367 
1368   switch (instr->Mask(LoadStorePairOffsetMask)) {
1369 #define LSP_OFFSET(A, B, C, D)    \
1370   case A##_off:                   \
1371     mnemonic = B;                 \
1372     form = C ", ['Xns'ILP" D "]"; \
1373     break;
1374     LOAD_STORE_PAIR_LIST(LSP_OFFSET)
1375 #undef LSP_OFFSET
1376   }
1377   Format(instr, mnemonic, form);
1378 }
1379 
1380 
VisitLoadStorePairNonTemporal(const Instruction * instr)1381 void Disassembler::VisitLoadStorePairNonTemporal(const Instruction *instr) {
1382   const char *mnemonic = "unimplemented";
1383   const char *form;
1384 
1385   switch (instr->Mask(LoadStorePairNonTemporalMask)) {
1386     case STNP_w:
1387       mnemonic = "stnp";
1388       form = "'Wt, 'Wt2, ['Xns'ILP2]";
1389       break;
1390     case LDNP_w:
1391       mnemonic = "ldnp";
1392       form = "'Wt, 'Wt2, ['Xns'ILP2]";
1393       break;
1394     case STNP_x:
1395       mnemonic = "stnp";
1396       form = "'Xt, 'Xt2, ['Xns'ILP3]";
1397       break;
1398     case LDNP_x:
1399       mnemonic = "ldnp";
1400       form = "'Xt, 'Xt2, ['Xns'ILP3]";
1401       break;
1402     case STNP_s:
1403       mnemonic = "stnp";
1404       form = "'St, 'St2, ['Xns'ILP2]";
1405       break;
1406     case LDNP_s:
1407       mnemonic = "ldnp";
1408       form = "'St, 'St2, ['Xns'ILP2]";
1409       break;
1410     case STNP_d:
1411       mnemonic = "stnp";
1412       form = "'Dt, 'Dt2, ['Xns'ILP3]";
1413       break;
1414     case LDNP_d:
1415       mnemonic = "ldnp";
1416       form = "'Dt, 'Dt2, ['Xns'ILP3]";
1417       break;
1418     case STNP_q:
1419       mnemonic = "stnp";
1420       form = "'Qt, 'Qt2, ['Xns'ILP4]";
1421       break;
1422     case LDNP_q:
1423       mnemonic = "ldnp";
1424       form = "'Qt, 'Qt2, ['Xns'ILP4]";
1425       break;
1426     default:
1427       form = "(LoadStorePairNonTemporal)";
1428   }
1429   Format(instr, mnemonic, form);
1430 }
1431 
1432 // clang-format off
1433 #define LOAD_STORE_EXCLUSIVE_LIST(V)                  \
1434   V(STXRB_w,  "stxrb",  "'Ws, 'Wt")                   \
1435   V(STXRH_w,  "stxrh",  "'Ws, 'Wt")                   \
1436   V(STXR_w,   "stxr",   "'Ws, 'Wt")                   \
1437   V(STXR_x,   "stxr",   "'Ws, 'Xt")                   \
1438   V(LDXRB_w,  "ldxrb",  "'Wt")                        \
1439   V(LDXRH_w,  "ldxrh",  "'Wt")                        \
1440   V(LDXR_w,   "ldxr",   "'Wt")                        \
1441   V(LDXR_x,   "ldxr",   "'Xt")                        \
1442   V(STXP_w,   "stxp",   "'Ws, 'Wt, 'Wt2")             \
1443   V(STXP_x,   "stxp",   "'Ws, 'Xt, 'Xt2")             \
1444   V(LDXP_w,   "ldxp",   "'Wt, 'Wt2")                  \
1445   V(LDXP_x,   "ldxp",   "'Xt, 'Xt2")                  \
1446   V(STLXRB_w, "stlxrb", "'Ws, 'Wt")                   \
1447   V(STLXRH_w, "stlxrh", "'Ws, 'Wt")                   \
1448   V(STLXR_w,  "stlxr",  "'Ws, 'Wt")                   \
1449   V(STLXR_x,  "stlxr",  "'Ws, 'Xt")                   \
1450   V(LDAXRB_w, "ldaxrb", "'Wt")                        \
1451   V(LDAXRH_w, "ldaxrh", "'Wt")                        \
1452   V(LDAXR_w,  "ldaxr",  "'Wt")                        \
1453   V(LDAXR_x,  "ldaxr",  "'Xt")                        \
1454   V(STLXP_w,  "stlxp",  "'Ws, 'Wt, 'Wt2")             \
1455   V(STLXP_x,  "stlxp",  "'Ws, 'Xt, 'Xt2")             \
1456   V(LDAXP_w,  "ldaxp",  "'Wt, 'Wt2")                  \
1457   V(LDAXP_x,  "ldaxp",  "'Xt, 'Xt2")                  \
1458   V(STLRB_w,  "stlrb",  "'Wt")                        \
1459   V(STLRH_w,  "stlrh",  "'Wt")                        \
1460   V(STLR_w,   "stlr",   "'Wt")                        \
1461   V(STLR_x,   "stlr",   "'Xt")                        \
1462   V(LDARB_w,  "ldarb",  "'Wt")                        \
1463   V(LDARH_w,  "ldarh",  "'Wt")                        \
1464   V(LDAR_w,   "ldar",   "'Wt")                        \
1465   V(LDAR_x,   "ldar",   "'Xt")                        \
1466   V(STLLRB,   "stllrb", "'Wt")                        \
1467   V(STLLRH,   "stllrh", "'Wt")                        \
1468   V(STLLR_w,  "stllr",  "'Wt")                        \
1469   V(STLLR_x,  "stllr",  "'Xt")                        \
1470   V(LDLARB,   "ldlarb", "'Wt")                        \
1471   V(LDLARH,   "ldlarh", "'Wt")                        \
1472   V(LDLAR_w,  "ldlar",  "'Wt")                        \
1473   V(LDLAR_x,  "ldlar",  "'Xt")                        \
1474   V(CAS_w,    "cas",    "'Ws, 'Wt")                   \
1475   V(CAS_x,    "cas",    "'Xs, 'Xt")                   \
1476   V(CASA_w,   "casa",   "'Ws, 'Wt")                   \
1477   V(CASA_x,   "casa",   "'Xs, 'Xt")                   \
1478   V(CASL_w,   "casl",   "'Ws, 'Wt")                   \
1479   V(CASL_x,   "casl",   "'Xs, 'Xt")                   \
1480   V(CASAL_w,  "casal",  "'Ws, 'Wt")                   \
1481   V(CASAL_x,  "casal",  "'Xs, 'Xt")                   \
1482   V(CASB,     "casb",   "'Ws, 'Wt")                   \
1483   V(CASAB,    "casab",  "'Ws, 'Wt")                   \
1484   V(CASLB,    "caslb",  "'Ws, 'Wt")                   \
1485   V(CASALB,   "casalb", "'Ws, 'Wt")                   \
1486   V(CASH,     "cash",   "'Ws, 'Wt")                   \
1487   V(CASAH,    "casah",  "'Ws, 'Wt")                   \
1488   V(CASLH,    "caslh",  "'Ws, 'Wt")                   \
1489   V(CASALH,   "casalh", "'Ws, 'Wt")                   \
1490   V(CASP_w,   "casp",   "'Ws, 'Ws+, 'Wt, 'Wt+")       \
1491   V(CASP_x,   "casp",   "'Xs, 'Xs+, 'Xt, 'Xt+")       \
1492   V(CASPA_w,  "caspa",  "'Ws, 'Ws+, 'Wt, 'Wt+")       \
1493   V(CASPA_x,  "caspa",  "'Xs, 'Xs+, 'Xt, 'Xt+")       \
1494   V(CASPL_w,  "caspl",  "'Ws, 'Ws+, 'Wt, 'Wt+")       \
1495   V(CASPL_x,  "caspl",  "'Xs, 'Xs+, 'Xt, 'Xt+")       \
1496   V(CASPAL_w, "caspal", "'Ws, 'Ws+, 'Wt, 'Wt+")       \
1497   V(CASPAL_x, "caspal", "'Xs, 'Xs+, 'Xt, 'Xt+")
1498 // clang-format on
1499 
1500 
VisitLoadStoreExclusive(const Instruction * instr)1501 void Disassembler::VisitLoadStoreExclusive(const Instruction *instr) {
1502   const char *mnemonic = "unimplemented";
1503   const char *form;
1504 
1505   switch (instr->Mask(LoadStoreExclusiveMask)) {
1506 #define LSX(A, B, C)     \
1507   case A:                \
1508     mnemonic = B;        \
1509     form = C ", ['Xns]"; \
1510     break;
1511     LOAD_STORE_EXCLUSIVE_LIST(LSX)
1512 #undef LSX
1513     default:
1514       form = "(LoadStoreExclusive)";
1515   }
1516 
1517   switch (instr->Mask(LoadStoreExclusiveMask)) {
1518     case CASP_w:
1519     case CASP_x:
1520     case CASPA_w:
1521     case CASPA_x:
1522     case CASPL_w:
1523     case CASPL_x:
1524     case CASPAL_w:
1525     case CASPAL_x:
1526       if ((instr->GetRs() % 2 == 1) || (instr->GetRt() % 2 == 1)) {
1527         mnemonic = "unallocated";
1528         form = "(LoadStoreExclusive)";
1529       }
1530       break;
1531   }
1532 
1533   Format(instr, mnemonic, form);
1534 }
1535 
VisitLoadStorePAC(const Instruction * instr)1536 void Disassembler::VisitLoadStorePAC(const Instruction *instr) {
1537   const char *mnemonic = "unimplemented";
1538   const char *form = "(LoadStorePAC)";
1539 
1540   switch (instr->Mask(LoadStorePACMask)) {
1541     case LDRAA:
1542       mnemonic = "ldraa";
1543       form = "'Xt, ['Xns'ILA]";
1544       break;
1545     case LDRAB:
1546       mnemonic = "ldrab";
1547       form = "'Xt, ['Xns'ILA]";
1548       break;
1549     case LDRAA_pre:
1550       mnemonic = "ldraa";
1551       form = "'Xt, ['Xns'ILA]!";
1552       break;
1553     case LDRAB_pre:
1554       mnemonic = "ldrab";
1555       form = "'Xt, ['Xns'ILA]!";
1556       break;
1557   }
1558 
1559   Format(instr, mnemonic, form);
1560 }
1561 
1562 #define ATOMIC_MEMORY_SIMPLE_LIST(V) \
1563   V(LDADD, "add")                    \
1564   V(LDCLR, "clr")                    \
1565   V(LDEOR, "eor")                    \
1566   V(LDSET, "set")                    \
1567   V(LDSMAX, "smax")                  \
1568   V(LDSMIN, "smin")                  \
1569   V(LDUMAX, "umax")                  \
1570   V(LDUMIN, "umin")
1571 
VisitAtomicMemory(const Instruction * instr)1572 void Disassembler::VisitAtomicMemory(const Instruction *instr) {
1573   const int kMaxAtomicOpMnemonicLength = 16;
1574   const char *mnemonic;
1575   const char *form = "'Ws, 'Wt, ['Xns]";
1576 
1577   switch (instr->Mask(AtomicMemoryMask)) {
1578 #define AMS(A, MN)             \
1579   case A##B:                   \
1580     mnemonic = MN "b";         \
1581     break;                     \
1582   case A##AB:                  \
1583     mnemonic = MN "ab";        \
1584     break;                     \
1585   case A##LB:                  \
1586     mnemonic = MN "lb";        \
1587     break;                     \
1588   case A##ALB:                 \
1589     mnemonic = MN "alb";       \
1590     break;                     \
1591   case A##H:                   \
1592     mnemonic = MN "h";         \
1593     break;                     \
1594   case A##AH:                  \
1595     mnemonic = MN "ah";        \
1596     break;                     \
1597   case A##LH:                  \
1598     mnemonic = MN "lh";        \
1599     break;                     \
1600   case A##ALH:                 \
1601     mnemonic = MN "alh";       \
1602     break;                     \
1603   case A##_w:                  \
1604     mnemonic = MN;             \
1605     break;                     \
1606   case A##A_w:                 \
1607     mnemonic = MN "a";         \
1608     break;                     \
1609   case A##L_w:                 \
1610     mnemonic = MN "l";         \
1611     break;                     \
1612   case A##AL_w:                \
1613     mnemonic = MN "al";        \
1614     break;                     \
1615   case A##_x:                  \
1616     mnemonic = MN;             \
1617     form = "'Xs, 'Xt, ['Xns]"; \
1618     break;                     \
1619   case A##A_x:                 \
1620     mnemonic = MN "a";         \
1621     form = "'Xs, 'Xt, ['Xns]"; \
1622     break;                     \
1623   case A##L_x:                 \
1624     mnemonic = MN "l";         \
1625     form = "'Xs, 'Xt, ['Xns]"; \
1626     break;                     \
1627   case A##AL_x:                \
1628     mnemonic = MN "al";        \
1629     form = "'Xs, 'Xt, ['Xns]"; \
1630     break;
1631     ATOMIC_MEMORY_SIMPLE_LIST(AMS)
1632 
1633     // SWP has the same semantics as ldadd etc but without the store aliases.
1634     AMS(SWP, "swp")
1635 #undef AMS
1636 
1637     case LDAPRB:
1638       mnemonic = "ldaprb";
1639       form = "'Wt, ['Xns]";
1640       break;
1641     case LDAPRH:
1642       mnemonic = "ldaprh";
1643       form = "'Wt, ['Xns]";
1644       break;
1645     case LDAPR_w:
1646       mnemonic = "ldapr";
1647       form = "'Wt, ['Xns]";
1648       break;
1649     case LDAPR_x:
1650       mnemonic = "ldapr";
1651       form = "'Xt, ['Xns]";
1652       break;
1653     default:
1654       mnemonic = "unimplemented";
1655       form = "(AtomicMemory)";
1656   }
1657 
1658   const char *prefix = "";
1659   switch (instr->Mask(AtomicMemoryMask)) {
1660 #define AMS(A, MN)                   \
1661   case A##AB:                        \
1662   case A##ALB:                       \
1663   case A##AH:                        \
1664   case A##ALH:                       \
1665   case A##A_w:                       \
1666   case A##AL_w:                      \
1667   case A##A_x:                       \
1668   case A##AL_x:                      \
1669     prefix = "ld";                   \
1670     break;                           \
1671   case A##B:                         \
1672   case A##LB:                        \
1673   case A##H:                         \
1674   case A##LH:                        \
1675   case A##_w:                        \
1676   case A##L_w: {                     \
1677     prefix = "ld";                   \
1678     unsigned rt = instr->GetRt();    \
1679     if (Register(rt, 32).IsZero()) { \
1680       prefix = "st";                 \
1681       form = "'Ws, ['Xns]";          \
1682     }                                \
1683     break;                           \
1684   }                                  \
1685   case A##_x:                        \
1686   case A##L_x: {                     \
1687     prefix = "ld";                   \
1688     unsigned rt = instr->GetRt();    \
1689     if (Register(rt, 64).IsZero()) { \
1690       prefix = "st";                 \
1691       form = "'Xs, ['Xns]";          \
1692     }                                \
1693     break;                           \
1694   }
1695     ATOMIC_MEMORY_SIMPLE_LIST(AMS)
1696 #undef AMS
1697   }
1698 
1699   char buffer[kMaxAtomicOpMnemonicLength];
1700   if (strlen(prefix) > 0) {
1701     snprintf(buffer, kMaxAtomicOpMnemonicLength, "%s%s", prefix, mnemonic);
1702     mnemonic = buffer;
1703   }
1704 
1705   Format(instr, mnemonic, form);
1706 }
1707 
1708 
VisitFPCompare(const Instruction * instr)1709 void Disassembler::VisitFPCompare(const Instruction *instr) {
1710   const char *mnemonic = "unimplemented";
1711   const char *form = "'Fn, 'Fm";
1712   const char *form_zero = "'Fn, #0.0";
1713 
1714   switch (instr->Mask(FPCompareMask)) {
1715     case FCMP_h_zero:
1716     case FCMP_s_zero:
1717     case FCMP_d_zero:
1718       form = form_zero;
1719       VIXL_FALLTHROUGH();
1720     case FCMP_h:
1721     case FCMP_s:
1722     case FCMP_d:
1723       mnemonic = "fcmp";
1724       break;
1725     case FCMPE_h_zero:
1726     case FCMPE_s_zero:
1727     case FCMPE_d_zero:
1728       form = form_zero;
1729       VIXL_FALLTHROUGH();
1730     case FCMPE_h:
1731     case FCMPE_s:
1732     case FCMPE_d:
1733       mnemonic = "fcmpe";
1734       break;
1735     default:
1736       form = "(FPCompare)";
1737   }
1738   Format(instr, mnemonic, form);
1739 }
1740 
1741 
VisitFPConditionalCompare(const Instruction * instr)1742 void Disassembler::VisitFPConditionalCompare(const Instruction *instr) {
1743   const char *mnemonic = "unmplemented";
1744   const char *form = "'Fn, 'Fm, 'INzcv, 'Cond";
1745 
1746   switch (instr->Mask(FPConditionalCompareMask)) {
1747     case FCCMP_h:
1748     case FCCMP_s:
1749     case FCCMP_d:
1750       mnemonic = "fccmp";
1751       break;
1752     case FCCMPE_h:
1753     case FCCMPE_s:
1754     case FCCMPE_d:
1755       mnemonic = "fccmpe";
1756       break;
1757     default:
1758       form = "(FPConditionalCompare)";
1759   }
1760   Format(instr, mnemonic, form);
1761 }
1762 
1763 
VisitFPConditionalSelect(const Instruction * instr)1764 void Disassembler::VisitFPConditionalSelect(const Instruction *instr) {
1765   const char *mnemonic = "";
1766   const char *form = "'Fd, 'Fn, 'Fm, 'Cond";
1767 
1768   switch (instr->Mask(FPConditionalSelectMask)) {
1769     case FCSEL_h:
1770     case FCSEL_s:
1771     case FCSEL_d:
1772       mnemonic = "fcsel";
1773       break;
1774     default:
1775       VIXL_UNREACHABLE();
1776   }
1777   Format(instr, mnemonic, form);
1778 }
1779 
1780 
VisitFPDataProcessing1Source(const Instruction * instr)1781 void Disassembler::VisitFPDataProcessing1Source(const Instruction *instr) {
1782   const char *mnemonic = "unimplemented";
1783   const char *form = "'Fd, 'Fn";
1784 
1785   switch (instr->Mask(FPDataProcessing1SourceMask)) {
1786 #define FORMAT(A, B) \
1787   case A##_h:        \
1788   case A##_s:        \
1789   case A##_d:        \
1790     mnemonic = B;    \
1791     break;
1792     FORMAT(FMOV, "fmov");
1793     FORMAT(FABS, "fabs");
1794     FORMAT(FNEG, "fneg");
1795     FORMAT(FSQRT, "fsqrt");
1796     FORMAT(FRINTN, "frintn");
1797     FORMAT(FRINTP, "frintp");
1798     FORMAT(FRINTM, "frintm");
1799     FORMAT(FRINTZ, "frintz");
1800     FORMAT(FRINTA, "frinta");
1801     FORMAT(FRINTX, "frintx");
1802     FORMAT(FRINTI, "frinti");
1803 #undef FORMAT
1804 #define FORMAT(A, B) \
1805   case A##_s:        \
1806   case A##_d:        \
1807     mnemonic = B;    \
1808     break;
1809     FORMAT(FRINT32X, "frint32x");
1810     FORMAT(FRINT32Z, "frint32z");
1811     FORMAT(FRINT64X, "frint64x");
1812     FORMAT(FRINT64Z, "frint64z");
1813 #undef FORMAT
1814     case FCVT_ds:
1815       mnemonic = "fcvt";
1816       form = "'Dd, 'Sn";
1817       break;
1818     case FCVT_sd:
1819       mnemonic = "fcvt";
1820       form = "'Sd, 'Dn";
1821       break;
1822     case FCVT_hs:
1823       mnemonic = "fcvt";
1824       form = "'Hd, 'Sn";
1825       break;
1826     case FCVT_sh:
1827       mnemonic = "fcvt";
1828       form = "'Sd, 'Hn";
1829       break;
1830     case FCVT_dh:
1831       mnemonic = "fcvt";
1832       form = "'Dd, 'Hn";
1833       break;
1834     case FCVT_hd:
1835       mnemonic = "fcvt";
1836       form = "'Hd, 'Dn";
1837       break;
1838     default:
1839       form = "(FPDataProcessing1Source)";
1840   }
1841   Format(instr, mnemonic, form);
1842 }
1843 
1844 
VisitFPDataProcessing2Source(const Instruction * instr)1845 void Disassembler::VisitFPDataProcessing2Source(const Instruction *instr) {
1846   const char *mnemonic = "";
1847   const char *form = "'Fd, 'Fn, 'Fm";
1848 
1849   switch (instr->Mask(FPDataProcessing2SourceMask)) {
1850 #define FORMAT(A, B) \
1851   case A##_h:        \
1852   case A##_s:        \
1853   case A##_d:        \
1854     mnemonic = B;    \
1855     break;
1856     FORMAT(FADD, "fadd");
1857     FORMAT(FSUB, "fsub");
1858     FORMAT(FMUL, "fmul");
1859     FORMAT(FDIV, "fdiv");
1860     FORMAT(FMAX, "fmax");
1861     FORMAT(FMIN, "fmin");
1862     FORMAT(FMAXNM, "fmaxnm");
1863     FORMAT(FMINNM, "fminnm");
1864     FORMAT(FNMUL, "fnmul");
1865 #undef FORMAT
1866     default:
1867       VIXL_UNREACHABLE();
1868   }
1869   Format(instr, mnemonic, form);
1870 }
1871 
1872 
VisitFPDataProcessing3Source(const Instruction * instr)1873 void Disassembler::VisitFPDataProcessing3Source(const Instruction *instr) {
1874   const char *mnemonic = "";
1875   const char *form = "'Fd, 'Fn, 'Fm, 'Fa";
1876 
1877   switch (instr->Mask(FPDataProcessing3SourceMask)) {
1878 #define FORMAT(A, B) \
1879   case A##_h:        \
1880   case A##_s:        \
1881   case A##_d:        \
1882     mnemonic = B;    \
1883     break;
1884     FORMAT(FMADD, "fmadd");
1885     FORMAT(FMSUB, "fmsub");
1886     FORMAT(FNMADD, "fnmadd");
1887     FORMAT(FNMSUB, "fnmsub");
1888 #undef FORMAT
1889     default:
1890       VIXL_UNREACHABLE();
1891   }
1892   Format(instr, mnemonic, form);
1893 }
1894 
1895 
VisitFPImmediate(const Instruction * instr)1896 void Disassembler::VisitFPImmediate(const Instruction *instr) {
1897   const char *mnemonic = "";
1898   const char *form = "(FPImmediate)";
1899   switch (instr->Mask(FPImmediateMask)) {
1900     case FMOV_h_imm:
1901       mnemonic = "fmov";
1902       form = "'Hd, 'IFP";
1903       break;
1904     case FMOV_s_imm:
1905       mnemonic = "fmov";
1906       form = "'Sd, 'IFP";
1907       break;
1908     case FMOV_d_imm:
1909       mnemonic = "fmov";
1910       form = "'Dd, 'IFP";
1911       break;
1912     default:
1913       VIXL_UNREACHABLE();
1914   }
1915   Format(instr, mnemonic, form);
1916 }
1917 
1918 
VisitFPIntegerConvert(const Instruction * instr)1919 void Disassembler::VisitFPIntegerConvert(const Instruction *instr) {
1920   const char *mnemonic = "unimplemented";
1921   const char *form = "(FPIntegerConvert)";
1922   const char *form_rf = "'Rd, 'Fn";
1923   const char *form_fr = "'Fd, 'Rn";
1924 
1925   switch (instr->Mask(FPIntegerConvertMask)) {
1926     case FMOV_wh:
1927     case FMOV_xh:
1928     case FMOV_ws:
1929     case FMOV_xd:
1930       mnemonic = "fmov";
1931       form = form_rf;
1932       break;
1933     case FMOV_hw:
1934     case FMOV_hx:
1935     case FMOV_sw:
1936     case FMOV_dx:
1937       mnemonic = "fmov";
1938       form = form_fr;
1939       break;
1940     case FMOV_d1_x:
1941       mnemonic = "fmov";
1942       form = "'Vd.D[1], 'Rn";
1943       break;
1944     case FMOV_x_d1:
1945       mnemonic = "fmov";
1946       form = "'Rd, 'Vn.D[1]";
1947       break;
1948     case FCVTAS_wh:
1949     case FCVTAS_xh:
1950     case FCVTAS_ws:
1951     case FCVTAS_xs:
1952     case FCVTAS_wd:
1953     case FCVTAS_xd:
1954       mnemonic = "fcvtas";
1955       form = form_rf;
1956       break;
1957     case FCVTAU_wh:
1958     case FCVTAU_xh:
1959     case FCVTAU_ws:
1960     case FCVTAU_xs:
1961     case FCVTAU_wd:
1962     case FCVTAU_xd:
1963       mnemonic = "fcvtau";
1964       form = form_rf;
1965       break;
1966     case FCVTMS_wh:
1967     case FCVTMS_xh:
1968     case FCVTMS_ws:
1969     case FCVTMS_xs:
1970     case FCVTMS_wd:
1971     case FCVTMS_xd:
1972       mnemonic = "fcvtms";
1973       form = form_rf;
1974       break;
1975     case FCVTMU_wh:
1976     case FCVTMU_xh:
1977     case FCVTMU_ws:
1978     case FCVTMU_xs:
1979     case FCVTMU_wd:
1980     case FCVTMU_xd:
1981       mnemonic = "fcvtmu";
1982       form = form_rf;
1983       break;
1984     case FCVTNS_wh:
1985     case FCVTNS_xh:
1986     case FCVTNS_ws:
1987     case FCVTNS_xs:
1988     case FCVTNS_wd:
1989     case FCVTNS_xd:
1990       mnemonic = "fcvtns";
1991       form = form_rf;
1992       break;
1993     case FCVTNU_wh:
1994     case FCVTNU_xh:
1995     case FCVTNU_ws:
1996     case FCVTNU_xs:
1997     case FCVTNU_wd:
1998     case FCVTNU_xd:
1999       mnemonic = "fcvtnu";
2000       form = form_rf;
2001       break;
2002     case FCVTZU_wh:
2003     case FCVTZU_xh:
2004     case FCVTZU_ws:
2005     case FCVTZU_xs:
2006     case FCVTZU_wd:
2007     case FCVTZU_xd:
2008       mnemonic = "fcvtzu";
2009       form = form_rf;
2010       break;
2011     case FCVTZS_wh:
2012     case FCVTZS_xh:
2013     case FCVTZS_ws:
2014     case FCVTZS_xs:
2015     case FCVTZS_wd:
2016     case FCVTZS_xd:
2017       mnemonic = "fcvtzs";
2018       form = form_rf;
2019       break;
2020     case FCVTPU_wh:
2021     case FCVTPU_xh:
2022     case FCVTPU_xs:
2023     case FCVTPU_wd:
2024     case FCVTPU_ws:
2025     case FCVTPU_xd:
2026       mnemonic = "fcvtpu";
2027       form = form_rf;
2028       break;
2029     case FCVTPS_wh:
2030     case FCVTPS_xh:
2031     case FCVTPS_ws:
2032     case FCVTPS_xs:
2033     case FCVTPS_wd:
2034     case FCVTPS_xd:
2035       mnemonic = "fcvtps";
2036       form = form_rf;
2037       break;
2038     case SCVTF_hw:
2039     case SCVTF_hx:
2040     case SCVTF_sw:
2041     case SCVTF_sx:
2042     case SCVTF_dw:
2043     case SCVTF_dx:
2044       mnemonic = "scvtf";
2045       form = form_fr;
2046       break;
2047     case UCVTF_hw:
2048     case UCVTF_hx:
2049     case UCVTF_sw:
2050     case UCVTF_sx:
2051     case UCVTF_dw:
2052     case UCVTF_dx:
2053       mnemonic = "ucvtf";
2054       form = form_fr;
2055       break;
2056     case FJCVTZS:
2057       mnemonic = "fjcvtzs";
2058       form = form_rf;
2059       break;
2060   }
2061   Format(instr, mnemonic, form);
2062 }
2063 
2064 
VisitFPFixedPointConvert(const Instruction * instr)2065 void Disassembler::VisitFPFixedPointConvert(const Instruction *instr) {
2066   const char *mnemonic = "";
2067   const char *form = "'Rd, 'Fn, 'IFPFBits";
2068   const char *form_fr = "'Fd, 'Rn, 'IFPFBits";
2069 
2070   switch (instr->Mask(FPFixedPointConvertMask)) {
2071     case FCVTZS_wh_fixed:
2072     case FCVTZS_xh_fixed:
2073     case FCVTZS_ws_fixed:
2074     case FCVTZS_xs_fixed:
2075     case FCVTZS_wd_fixed:
2076     case FCVTZS_xd_fixed:
2077       mnemonic = "fcvtzs";
2078       break;
2079     case FCVTZU_wh_fixed:
2080     case FCVTZU_xh_fixed:
2081     case FCVTZU_ws_fixed:
2082     case FCVTZU_xs_fixed:
2083     case FCVTZU_wd_fixed:
2084     case FCVTZU_xd_fixed:
2085       mnemonic = "fcvtzu";
2086       break;
2087     case SCVTF_hw_fixed:
2088     case SCVTF_hx_fixed:
2089     case SCVTF_sw_fixed:
2090     case SCVTF_sx_fixed:
2091     case SCVTF_dw_fixed:
2092     case SCVTF_dx_fixed:
2093       mnemonic = "scvtf";
2094       form = form_fr;
2095       break;
2096     case UCVTF_hw_fixed:
2097     case UCVTF_hx_fixed:
2098     case UCVTF_sw_fixed:
2099     case UCVTF_sx_fixed:
2100     case UCVTF_dw_fixed:
2101     case UCVTF_dx_fixed:
2102       mnemonic = "ucvtf";
2103       form = form_fr;
2104       break;
2105     default:
2106       VIXL_UNREACHABLE();
2107   }
2108   Format(instr, mnemonic, form);
2109 }
2110 
2111 // clang-format off
2112 #define PAUTH_SYSTEM_MNEMONICS(V) \
2113   V(PACIA1716, "pacia1716")       \
2114   V(PACIB1716, "pacib1716")       \
2115   V(AUTIA1716, "autia1716")       \
2116   V(AUTIB1716, "autib1716")       \
2117   V(PACIAZ,    "paciaz")          \
2118   V(PACIASP,   "paciasp")         \
2119   V(PACIBZ,    "pacibz")          \
2120   V(PACIBSP,   "pacibsp")         \
2121   V(AUTIAZ,    "autiaz")          \
2122   V(AUTIASP,   "autiasp")         \
2123   V(AUTIBZ,    "autibz")          \
2124   V(AUTIBSP,   "autibsp")
2125 // clang-format on
2126 
VisitSystem(const Instruction * instr)2127 void Disassembler::VisitSystem(const Instruction *instr) {
2128   // Some system instructions hijack their Op and Cp fields to represent a
2129   // range of immediates instead of indicating a different instruction. This
2130   // makes the decoding tricky.
2131   const char *mnemonic = "unimplemented";
2132   const char *form = "(System)";
2133   if (instr->GetInstructionBits() == XPACLRI) {
2134     mnemonic = "xpaclri";
2135     form = NULL;
2136   } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
2137     switch (instr->Mask(SystemPStateMask)) {
2138       case CFINV:
2139         mnemonic = "cfinv";
2140         form = NULL;
2141         break;
2142       case AXFLAG:
2143         mnemonic = "axflag";
2144         form = NULL;
2145         break;
2146       case XAFLAG:
2147         mnemonic = "xaflag";
2148         form = NULL;
2149         break;
2150     }
2151   } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
2152     switch (instr->Mask(SystemPAuthMask)) {
2153 #define PAUTH_CASE(NAME, MN) \
2154   case NAME:                 \
2155     mnemonic = MN;           \
2156     form = NULL;             \
2157     break;
2158 
2159       PAUTH_SYSTEM_MNEMONICS(PAUTH_CASE)
2160 #undef PAUTH_CASE
2161     }
2162   } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
2163              SystemExclusiveMonitorFixed) {
2164     switch (instr->Mask(SystemExclusiveMonitorMask)) {
2165       case CLREX: {
2166         mnemonic = "clrex";
2167         form = (instr->GetCRm() == 0xf) ? NULL : "'IX";
2168         break;
2169       }
2170     }
2171   } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
2172     switch (instr->Mask(SystemSysRegMask)) {
2173       case MRS: {
2174         mnemonic = "mrs";
2175         form = "'Xt, 'IY";
2176         break;
2177       }
2178       case MSR: {
2179         mnemonic = "msr";
2180         form = "'IY, 'Xt";
2181         break;
2182       }
2183     }
2184   } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
2185     form = NULL;
2186     switch (instr->GetImmHint()) {
2187       case NOP:
2188         mnemonic = "nop";
2189         break;
2190       case YIELD:
2191         mnemonic = "yield";
2192         break;
2193       case WFE:
2194         mnemonic = "wfe";
2195         break;
2196       case WFI:
2197         mnemonic = "wfi";
2198         break;
2199       case SEV:
2200         mnemonic = "sev";
2201         break;
2202       case SEVL:
2203         mnemonic = "sevl";
2204         break;
2205       case ESB:
2206         mnemonic = "esb";
2207         break;
2208       case CSDB:
2209         mnemonic = "csdb";
2210         break;
2211       case BTI:
2212         mnemonic = "bti";
2213         break;
2214       case BTI_c:
2215         mnemonic = "bti c";
2216         break;
2217       case BTI_j:
2218         mnemonic = "bti j";
2219         break;
2220       case BTI_jc:
2221         mnemonic = "bti jc";
2222         break;
2223       default:
2224         // Fall back to 'hint #<imm7>'.
2225         form = "'IH";
2226         mnemonic = "hint";
2227         break;
2228     }
2229   } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
2230     switch (instr->Mask(MemBarrierMask)) {
2231       case DMB: {
2232         mnemonic = "dmb";
2233         form = "'M";
2234         break;
2235       }
2236       case DSB: {
2237         mnemonic = "dsb";
2238         form = "'M";
2239         break;
2240       }
2241       case ISB: {
2242         mnemonic = "isb";
2243         form = NULL;
2244         break;
2245       }
2246     }
2247   } else if (instr->Mask(SystemSysFMask) == SystemSysFixed) {
2248     switch (instr->GetSysOp()) {
2249       case IVAU:
2250         mnemonic = "ic";
2251         form = "ivau, 'Xt";
2252         break;
2253       case CVAC:
2254         mnemonic = "dc";
2255         form = "cvac, 'Xt";
2256         break;
2257       case CVAU:
2258         mnemonic = "dc";
2259         form = "cvau, 'Xt";
2260         break;
2261       case CVAP:
2262         mnemonic = "dc";
2263         form = "cvap, 'Xt";
2264         break;
2265       case CVADP:
2266         mnemonic = "dc";
2267         form = "cvadp, 'Xt";
2268         break;
2269       case CIVAC:
2270         mnemonic = "dc";
2271         form = "civac, 'Xt";
2272         break;
2273       case ZVA:
2274         mnemonic = "dc";
2275         form = "zva, 'Xt";
2276         break;
2277       default:
2278         mnemonic = "sys";
2279         if (instr->GetRt() == 31) {
2280           form = "'G1, 'Kn, 'Km, 'G2";
2281         } else {
2282           form = "'G1, 'Kn, 'Km, 'G2, 'Xt";
2283         }
2284         break;
2285     }
2286   }
2287   Format(instr, mnemonic, form);
2288 }
2289 
2290 
VisitException(const Instruction * instr)2291 void Disassembler::VisitException(const Instruction *instr) {
2292   const char *mnemonic = "unimplemented";
2293   const char *form = "'IDebug";
2294 
2295   switch (instr->Mask(ExceptionMask)) {
2296     case HLT:
2297       mnemonic = "hlt";
2298       break;
2299     case BRK:
2300       mnemonic = "brk";
2301       break;
2302     case SVC:
2303       mnemonic = "svc";
2304       break;
2305     case HVC:
2306       mnemonic = "hvc";
2307       break;
2308     case SMC:
2309       mnemonic = "smc";
2310       break;
2311     case DCPS1:
2312       mnemonic = "dcps1";
2313       form = "{'IDebug}";
2314       break;
2315     case DCPS2:
2316       mnemonic = "dcps2";
2317       form = "{'IDebug}";
2318       break;
2319     case DCPS3:
2320       mnemonic = "dcps3";
2321       form = "{'IDebug}";
2322       break;
2323     default:
2324       form = "(Exception)";
2325   }
2326   Format(instr, mnemonic, form);
2327 }
2328 
2329 
VisitCrypto2RegSHA(const Instruction * instr)2330 void Disassembler::VisitCrypto2RegSHA(const Instruction *instr) {
2331   VisitUnimplemented(instr);
2332 }
2333 
2334 
VisitCrypto3RegSHA(const Instruction * instr)2335 void Disassembler::VisitCrypto3RegSHA(const Instruction *instr) {
2336   VisitUnimplemented(instr);
2337 }
2338 
2339 
VisitCryptoAES(const Instruction * instr)2340 void Disassembler::VisitCryptoAES(const Instruction *instr) {
2341   VisitUnimplemented(instr);
2342 }
2343 
2344 
VisitNEON2RegMisc(const Instruction * instr)2345 void Disassembler::VisitNEON2RegMisc(const Instruction *instr) {
2346   const char *mnemonic = "unimplemented";
2347   const char *form = "'Vd.%s, 'Vn.%s";
2348   const char *form_cmp_zero = "'Vd.%s, 'Vn.%s, #0";
2349   const char *form_fcmp_zero = "'Vd.%s, 'Vn.%s, #0.0";
2350   NEONFormatDecoder nfd(instr);
2351 
2352   static const NEONFormatMap map_lp_ta =
2353       {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
2354 
2355   static const NEONFormatMap map_cvt_ta = {{22}, {NF_4S, NF_2D}};
2356 
2357   static const NEONFormatMap map_cvt_tb = {{22, 30},
2358                                            {NF_4H, NF_8H, NF_2S, NF_4S}};
2359 
2360   if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
2361     // These instructions all use a two bit size field, except NOT and RBIT,
2362     // which use the field to encode the operation.
2363     switch (instr->Mask(NEON2RegMiscMask)) {
2364       case NEON_REV64:
2365         mnemonic = "rev64";
2366         break;
2367       case NEON_REV32:
2368         mnemonic = "rev32";
2369         break;
2370       case NEON_REV16:
2371         mnemonic = "rev16";
2372         break;
2373       case NEON_SADDLP:
2374         mnemonic = "saddlp";
2375         nfd.SetFormatMap(0, &map_lp_ta);
2376         break;
2377       case NEON_UADDLP:
2378         mnemonic = "uaddlp";
2379         nfd.SetFormatMap(0, &map_lp_ta);
2380         break;
2381       case NEON_SUQADD:
2382         mnemonic = "suqadd";
2383         break;
2384       case NEON_USQADD:
2385         mnemonic = "usqadd";
2386         break;
2387       case NEON_CLS:
2388         mnemonic = "cls";
2389         break;
2390       case NEON_CLZ:
2391         mnemonic = "clz";
2392         break;
2393       case NEON_CNT:
2394         mnemonic = "cnt";
2395         break;
2396       case NEON_SADALP:
2397         mnemonic = "sadalp";
2398         nfd.SetFormatMap(0, &map_lp_ta);
2399         break;
2400       case NEON_UADALP:
2401         mnemonic = "uadalp";
2402         nfd.SetFormatMap(0, &map_lp_ta);
2403         break;
2404       case NEON_SQABS:
2405         mnemonic = "sqabs";
2406         break;
2407       case NEON_SQNEG:
2408         mnemonic = "sqneg";
2409         break;
2410       case NEON_CMGT_zero:
2411         mnemonic = "cmgt";
2412         form = form_cmp_zero;
2413         break;
2414       case NEON_CMGE_zero:
2415         mnemonic = "cmge";
2416         form = form_cmp_zero;
2417         break;
2418       case NEON_CMEQ_zero:
2419         mnemonic = "cmeq";
2420         form = form_cmp_zero;
2421         break;
2422       case NEON_CMLE_zero:
2423         mnemonic = "cmle";
2424         form = form_cmp_zero;
2425         break;
2426       case NEON_CMLT_zero:
2427         mnemonic = "cmlt";
2428         form = form_cmp_zero;
2429         break;
2430       case NEON_ABS:
2431         mnemonic = "abs";
2432         break;
2433       case NEON_NEG:
2434         mnemonic = "neg";
2435         break;
2436       case NEON_RBIT_NOT:
2437         switch (instr->GetFPType()) {
2438           case 0:
2439             mnemonic = "mvn";
2440             break;
2441           case 1:
2442             mnemonic = "rbit";
2443             break;
2444           default:
2445             form = "(NEON2RegMisc)";
2446         }
2447         nfd.SetFormatMaps(nfd.LogicalFormatMap());
2448         break;
2449     }
2450   } else {
2451     // These instructions all use a one bit size field, except XTN, SQXTUN,
2452     // SHLL, SQXTN and UQXTN, which use a two bit size field.
2453     nfd.SetFormatMaps(nfd.FPFormatMap());
2454     switch (instr->Mask(NEON2RegMiscFPMask)) {
2455       case NEON_FABS:
2456         mnemonic = "fabs";
2457         break;
2458       case NEON_FNEG:
2459         mnemonic = "fneg";
2460         break;
2461       case NEON_FCVTN:
2462         mnemonic = instr->Mask(NEON_Q) ? "fcvtn2" : "fcvtn";
2463         nfd.SetFormatMap(0, &map_cvt_tb);
2464         nfd.SetFormatMap(1, &map_cvt_ta);
2465         break;
2466       case NEON_FCVTXN:
2467         mnemonic = instr->Mask(NEON_Q) ? "fcvtxn2" : "fcvtxn";
2468         nfd.SetFormatMap(0, &map_cvt_tb);
2469         nfd.SetFormatMap(1, &map_cvt_ta);
2470         break;
2471       case NEON_FCVTL:
2472         mnemonic = instr->Mask(NEON_Q) ? "fcvtl2" : "fcvtl";
2473         nfd.SetFormatMap(0, &map_cvt_ta);
2474         nfd.SetFormatMap(1, &map_cvt_tb);
2475         break;
2476       case NEON_FRINT32X:
2477         mnemonic = "frint32x";
2478         break;
2479       case NEON_FRINT32Z:
2480         mnemonic = "frint32z";
2481         break;
2482       case NEON_FRINT64X:
2483         mnemonic = "frint64x";
2484         break;
2485       case NEON_FRINT64Z:
2486         mnemonic = "frint64z";
2487         break;
2488       case NEON_FRINTN:
2489         mnemonic = "frintn";
2490         break;
2491       case NEON_FRINTA:
2492         mnemonic = "frinta";
2493         break;
2494       case NEON_FRINTP:
2495         mnemonic = "frintp";
2496         break;
2497       case NEON_FRINTM:
2498         mnemonic = "frintm";
2499         break;
2500       case NEON_FRINTX:
2501         mnemonic = "frintx";
2502         break;
2503       case NEON_FRINTZ:
2504         mnemonic = "frintz";
2505         break;
2506       case NEON_FRINTI:
2507         mnemonic = "frinti";
2508         break;
2509       case NEON_FCVTNS:
2510         mnemonic = "fcvtns";
2511         break;
2512       case NEON_FCVTNU:
2513         mnemonic = "fcvtnu";
2514         break;
2515       case NEON_FCVTPS:
2516         mnemonic = "fcvtps";
2517         break;
2518       case NEON_FCVTPU:
2519         mnemonic = "fcvtpu";
2520         break;
2521       case NEON_FCVTMS:
2522         mnemonic = "fcvtms";
2523         break;
2524       case NEON_FCVTMU:
2525         mnemonic = "fcvtmu";
2526         break;
2527       case NEON_FCVTZS:
2528         mnemonic = "fcvtzs";
2529         break;
2530       case NEON_FCVTZU:
2531         mnemonic = "fcvtzu";
2532         break;
2533       case NEON_FCVTAS:
2534         mnemonic = "fcvtas";
2535         break;
2536       case NEON_FCVTAU:
2537         mnemonic = "fcvtau";
2538         break;
2539       case NEON_FSQRT:
2540         mnemonic = "fsqrt";
2541         break;
2542       case NEON_SCVTF:
2543         mnemonic = "scvtf";
2544         break;
2545       case NEON_UCVTF:
2546         mnemonic = "ucvtf";
2547         break;
2548       case NEON_URSQRTE:
2549         mnemonic = "ursqrte";
2550         break;
2551       case NEON_URECPE:
2552         mnemonic = "urecpe";
2553         break;
2554       case NEON_FRSQRTE:
2555         mnemonic = "frsqrte";
2556         break;
2557       case NEON_FRECPE:
2558         mnemonic = "frecpe";
2559         break;
2560       case NEON_FCMGT_zero:
2561         mnemonic = "fcmgt";
2562         form = form_fcmp_zero;
2563         break;
2564       case NEON_FCMGE_zero:
2565         mnemonic = "fcmge";
2566         form = form_fcmp_zero;
2567         break;
2568       case NEON_FCMEQ_zero:
2569         mnemonic = "fcmeq";
2570         form = form_fcmp_zero;
2571         break;
2572       case NEON_FCMLE_zero:
2573         mnemonic = "fcmle";
2574         form = form_fcmp_zero;
2575         break;
2576       case NEON_FCMLT_zero:
2577         mnemonic = "fcmlt";
2578         form = form_fcmp_zero;
2579         break;
2580       default:
2581         if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
2582             (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
2583           nfd.SetFormatMap(0, nfd.IntegerFormatMap());
2584           nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
2585 
2586           switch (instr->Mask(NEON2RegMiscMask)) {
2587             case NEON_XTN:
2588               mnemonic = "xtn";
2589               break;
2590             case NEON_SQXTN:
2591               mnemonic = "sqxtn";
2592               break;
2593             case NEON_UQXTN:
2594               mnemonic = "uqxtn";
2595               break;
2596             case NEON_SQXTUN:
2597               mnemonic = "sqxtun";
2598               break;
2599             case NEON_SHLL:
2600               mnemonic = "shll";
2601               nfd.SetFormatMap(0, nfd.LongIntegerFormatMap());
2602               nfd.SetFormatMap(1, nfd.IntegerFormatMap());
2603               switch (instr->GetNEONSize()) {
2604                 case 0:
2605                   form = "'Vd.%s, 'Vn.%s, #8";
2606                   break;
2607                 case 1:
2608                   form = "'Vd.%s, 'Vn.%s, #16";
2609                   break;
2610                 case 2:
2611                   form = "'Vd.%s, 'Vn.%s, #32";
2612                   break;
2613                 default:
2614                   Format(instr, "unallocated", "(NEON2RegMisc)");
2615                   return;
2616               }
2617           }
2618           Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
2619           return;
2620         } else {
2621           form = "(NEON2RegMisc)";
2622         }
2623     }
2624   }
2625   Format(instr, mnemonic, nfd.Substitute(form));
2626 }
2627 
VisitNEON2RegMiscFP16(const Instruction * instr)2628 void Disassembler::VisitNEON2RegMiscFP16(const Instruction *instr) {
2629   const char *mnemonic = "unimplemented";
2630   const char *form = "'Vd.%s, 'Vn.%s";
2631   const char *form_cmp = "'Vd.%s, 'Vn.%s, #0.0";
2632 
2633   static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
2634   NEONFormatDecoder nfd(instr, &map_half);
2635 
2636   switch (instr->Mask(NEON2RegMiscFP16Mask)) {
2637 // clang-format off
2638 #define FORMAT(A, B) \
2639   case NEON_##A##_H: \
2640     mnemonic = B;    \
2641     break;
2642     FORMAT(FABS,    "fabs")
2643     FORMAT(FCVTAS,  "fcvtas")
2644     FORMAT(FCVTAU,  "fcvtau")
2645     FORMAT(FCVTMS,  "fcvtms")
2646     FORMAT(FCVTMU,  "fcvtmu")
2647     FORMAT(FCVTNS,  "fcvtns")
2648     FORMAT(FCVTNU,  "fcvtnu")
2649     FORMAT(FCVTPS,  "fcvtps")
2650     FORMAT(FCVTPU,  "fcvtpu")
2651     FORMAT(FCVTZS,  "fcvtzs")
2652     FORMAT(FCVTZU,  "fcvtzu")
2653     FORMAT(FNEG,    "fneg")
2654     FORMAT(FRECPE,  "frecpe")
2655     FORMAT(FRINTA,  "frinta")
2656     FORMAT(FRINTI,  "frinti")
2657     FORMAT(FRINTM,  "frintm")
2658     FORMAT(FRINTN,  "frintn")
2659     FORMAT(FRINTP,  "frintp")
2660     FORMAT(FRINTX,  "frintx")
2661     FORMAT(FRINTZ,  "frintz")
2662     FORMAT(FRSQRTE, "frsqrte")
2663     FORMAT(FSQRT,   "fsqrt")
2664     FORMAT(SCVTF,   "scvtf")
2665     FORMAT(UCVTF,   "ucvtf")
2666 // clang-format on
2667 #undef FORMAT
2668 
2669     case NEON_FCMEQ_H_zero:
2670       mnemonic = "fcmeq";
2671       form = form_cmp;
2672       break;
2673     case NEON_FCMGT_H_zero:
2674       mnemonic = "fcmgt";
2675       form = form_cmp;
2676       break;
2677     case NEON_FCMGE_H_zero:
2678       mnemonic = "fcmge";
2679       form = form_cmp;
2680       break;
2681     case NEON_FCMLT_H_zero:
2682       mnemonic = "fcmlt";
2683       form = form_cmp;
2684       break;
2685     case NEON_FCMLE_H_zero:
2686       mnemonic = "fcmle";
2687       form = form_cmp;
2688       break;
2689     default:
2690       form = "(NEON2RegMiscFP16)";
2691   }
2692   Format(instr, mnemonic, nfd.Substitute(form));
2693 }
2694 
2695 
VisitNEON3Same(const Instruction * instr)2696 void Disassembler::VisitNEON3Same(const Instruction *instr) {
2697   const char *mnemonic = "unimplemented";
2698   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
2699   NEONFormatDecoder nfd(instr);
2700 
2701   if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
2702     switch (instr->Mask(NEON3SameLogicalMask)) {
2703       case NEON_AND:
2704         mnemonic = "and";
2705         break;
2706       case NEON_ORR:
2707         mnemonic = "orr";
2708         if (instr->GetRm() == instr->GetRn()) {
2709           mnemonic = "mov";
2710           form = "'Vd.%s, 'Vn.%s";
2711         }
2712         break;
2713       case NEON_ORN:
2714         mnemonic = "orn";
2715         break;
2716       case NEON_EOR:
2717         mnemonic = "eor";
2718         break;
2719       case NEON_BIC:
2720         mnemonic = "bic";
2721         break;
2722       case NEON_BIF:
2723         mnemonic = "bif";
2724         break;
2725       case NEON_BIT:
2726         mnemonic = "bit";
2727         break;
2728       case NEON_BSL:
2729         mnemonic = "bsl";
2730         break;
2731       default:
2732         form = "(NEON3Same)";
2733     }
2734     nfd.SetFormatMaps(nfd.LogicalFormatMap());
2735   } else {
2736     static const char kUnknown[] = "unallocated";
2737     static const char *mnemonics[] = {"shadd",
2738                                       "uhadd",
2739                                       "shadd",
2740                                       "uhadd",
2741                                       "sqadd",
2742                                       "uqadd",
2743                                       "sqadd",
2744                                       "uqadd",
2745                                       "srhadd",
2746                                       "urhadd",
2747                                       "srhadd",
2748                                       "urhadd",
2749                                       // Handled by logical cases above.
2750                                       NULL,
2751                                       NULL,
2752                                       NULL,
2753                                       NULL,
2754                                       "shsub",
2755                                       "uhsub",
2756                                       "shsub",
2757                                       "uhsub",
2758                                       "sqsub",
2759                                       "uqsub",
2760                                       "sqsub",
2761                                       "uqsub",
2762                                       "cmgt",
2763                                       "cmhi",
2764                                       "cmgt",
2765                                       "cmhi",
2766                                       "cmge",
2767                                       "cmhs",
2768                                       "cmge",
2769                                       "cmhs",
2770                                       "sshl",
2771                                       "ushl",
2772                                       "sshl",
2773                                       "ushl",
2774                                       "sqshl",
2775                                       "uqshl",
2776                                       "sqshl",
2777                                       "uqshl",
2778                                       "srshl",
2779                                       "urshl",
2780                                       "srshl",
2781                                       "urshl",
2782                                       "sqrshl",
2783                                       "uqrshl",
2784                                       "sqrshl",
2785                                       "uqrshl",
2786                                       "smax",
2787                                       "umax",
2788                                       "smax",
2789                                       "umax",
2790                                       "smin",
2791                                       "umin",
2792                                       "smin",
2793                                       "umin",
2794                                       "sabd",
2795                                       "uabd",
2796                                       "sabd",
2797                                       "uabd",
2798                                       "saba",
2799                                       "uaba",
2800                                       "saba",
2801                                       "uaba",
2802                                       "add",
2803                                       "sub",
2804                                       "add",
2805                                       "sub",
2806                                       "cmtst",
2807                                       "cmeq",
2808                                       "cmtst",
2809                                       "cmeq",
2810                                       "mla",
2811                                       "mls",
2812                                       "mla",
2813                                       "mls",
2814                                       "mul",
2815                                       "pmul",
2816                                       "mul",
2817                                       "pmul",
2818                                       "smaxp",
2819                                       "umaxp",
2820                                       "smaxp",
2821                                       "umaxp",
2822                                       "sminp",
2823                                       "uminp",
2824                                       "sminp",
2825                                       "uminp",
2826                                       "sqdmulh",
2827                                       "sqrdmulh",
2828                                       "sqdmulh",
2829                                       "sqrdmulh",
2830                                       "addp",
2831                                       kUnknown,
2832                                       "addp",
2833                                       kUnknown,
2834                                       "fmaxnm",
2835                                       "fmaxnmp",
2836                                       "fminnm",
2837                                       "fminnmp",
2838                                       "fmla",
2839                                       kUnknown,  // FMLAL2 or unallocated
2840                                       "fmls",
2841                                       kUnknown,  // FMLSL2 or unallocated
2842                                       "fadd",
2843                                       "faddp",
2844                                       "fsub",
2845                                       "fabd",
2846                                       "fmulx",
2847                                       "fmul",
2848                                       kUnknown,
2849                                       kUnknown,
2850                                       "fcmeq",
2851                                       "fcmge",
2852                                       kUnknown,
2853                                       "fcmgt",
2854                                       kUnknown,  // FMLAL or unallocated
2855                                       "facge",
2856                                       kUnknown,  // FMLSL or unallocated
2857                                       "facgt",
2858                                       "fmax",
2859                                       "fmaxp",
2860                                       "fmin",
2861                                       "fminp",
2862                                       "frecps",
2863                                       "fdiv",
2864                                       "frsqrts",
2865                                       kUnknown};
2866 
2867     // Operation is determined by the opcode bits (15-11), the top bit of
2868     // size (23) and the U bit (29).
2869     unsigned index = (instr->ExtractBits(15, 11) << 2) |
2870                      (instr->ExtractBit(23) << 1) | instr->ExtractBit(29);
2871     VIXL_ASSERT(index < ArrayLength(mnemonics));
2872     mnemonic = mnemonics[index];
2873     // Assert that index is not one of the previously handled logical
2874     // instructions.
2875     VIXL_ASSERT(mnemonic != NULL);
2876 
2877     if (mnemonic == kUnknown) {
2878       // Catch special cases where we need to check more bits than we have in
2879       // the table index. Anything not matched here is unallocated.
2880 
2881       const char *fhm_form = (instr->Mask(NEON_Q) == 0)
2882                                  ? "'Vd.2s, 'Vn.2h, 'Vm.2h"
2883                                  : "'Vd.4s, 'Vn.4h, 'Vm.4h";
2884       switch (instr->Mask(NEON3SameFHMMask)) {
2885         case NEON_FMLAL:
2886           mnemonic = "fmlal";
2887           form = fhm_form;
2888           break;
2889         case NEON_FMLAL2:
2890           mnemonic = "fmlal2";
2891           form = fhm_form;
2892           break;
2893         case NEON_FMLSL:
2894           mnemonic = "fmlsl";
2895           form = fhm_form;
2896           break;
2897         case NEON_FMLSL2:
2898           mnemonic = "fmlsl2";
2899           form = fhm_form;
2900           break;
2901         default:
2902           VIXL_ASSERT(strcmp(mnemonic, "unallocated") == 0);
2903           form = "(NEON3Same)";
2904           break;
2905       }
2906     }
2907 
2908     if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
2909       nfd.SetFormatMaps(nfd.FPFormatMap());
2910     }
2911   }
2912   Format(instr, mnemonic, nfd.Substitute(form));
2913 }
2914 
VisitNEON3SameFP16(const Instruction * instr)2915 void Disassembler::VisitNEON3SameFP16(const Instruction *instr) {
2916   const char *mnemonic = "unimplemented";
2917   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
2918 
2919   NEONFormatDecoder nfd(instr);
2920   nfd.SetFormatMaps(nfd.FP16FormatMap());
2921 
2922   switch (instr->Mask(NEON3SameFP16Mask)) {
2923 #define FORMAT(A, B) \
2924   case NEON_##A##_H: \
2925     mnemonic = B;    \
2926     break;
2927     FORMAT(FMAXNM, "fmaxnm");
2928     FORMAT(FMLA, "fmla");
2929     FORMAT(FADD, "fadd");
2930     FORMAT(FMULX, "fmulx");
2931     FORMAT(FCMEQ, "fcmeq");
2932     FORMAT(FMAX, "fmax");
2933     FORMAT(FRECPS, "frecps");
2934     FORMAT(FMINNM, "fminnm");
2935     FORMAT(FMLS, "fmls");
2936     FORMAT(FSUB, "fsub");
2937     FORMAT(FMIN, "fmin");
2938     FORMAT(FRSQRTS, "frsqrts");
2939     FORMAT(FMAXNMP, "fmaxnmp");
2940     FORMAT(FADDP, "faddp");
2941     FORMAT(FMUL, "fmul");
2942     FORMAT(FCMGE, "fcmge");
2943     FORMAT(FACGE, "facge");
2944     FORMAT(FMAXP, "fmaxp");
2945     FORMAT(FDIV, "fdiv");
2946     FORMAT(FMINNMP, "fminnmp");
2947     FORMAT(FABD, "fabd");
2948     FORMAT(FCMGT, "fcmgt");
2949     FORMAT(FACGT, "facgt");
2950     FORMAT(FMINP, "fminp");
2951 #undef FORMAT
2952     default:
2953       form = "(NEON3SameFP16)";
2954   }
2955 
2956   Format(instr, mnemonic, nfd.Substitute(form));
2957 }
2958 
VisitNEON3SameExtra(const Instruction * instr)2959 void Disassembler::VisitNEON3SameExtra(const Instruction *instr) {
2960   static const NEONFormatMap map_usdot = {{30}, {NF_8B, NF_16B}};
2961 
2962   const char *mnemonic = "unallocated";
2963   const char *form = "(NEON3SameExtra)";
2964 
2965   NEONFormatDecoder nfd(instr);
2966 
2967   if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
2968     mnemonic = "fcmla";
2969     form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVFCNM";
2970   } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
2971     mnemonic = "fcadd";
2972     form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVFCNA";
2973   } else {
2974     form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
2975     switch (instr->Mask(NEON3SameExtraMask)) {
2976       case NEON_SDOT:
2977         mnemonic = "sdot";
2978         nfd.SetFormatMap(1, &map_usdot);
2979         nfd.SetFormatMap(2, &map_usdot);
2980         break;
2981       case NEON_SQRDMLAH:
2982         mnemonic = "sqrdmlah";
2983         break;
2984       case NEON_UDOT:
2985         mnemonic = "udot";
2986         nfd.SetFormatMap(1, &map_usdot);
2987         nfd.SetFormatMap(2, &map_usdot);
2988         break;
2989       case NEON_SQRDMLSH:
2990         mnemonic = "sqrdmlsh";
2991         break;
2992     }
2993   }
2994 
2995   Format(instr, mnemonic, nfd.Substitute(form));
2996 }
2997 
2998 
VisitNEON3Different(const Instruction * instr)2999 void Disassembler::VisitNEON3Different(const Instruction *instr) {
3000   const char *mnemonic = "unimplemented";
3001   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
3002 
3003   NEONFormatDecoder nfd(instr);
3004   nfd.SetFormatMap(0, nfd.LongIntegerFormatMap());
3005 
3006   // Ignore the Q bit. Appending a "2" suffix is handled later.
3007   switch (instr->Mask(NEON3DifferentMask) & ~NEON_Q) {
3008     case NEON_PMULL:
3009       mnemonic = "pmull";
3010       break;
3011     case NEON_SABAL:
3012       mnemonic = "sabal";
3013       break;
3014     case NEON_SABDL:
3015       mnemonic = "sabdl";
3016       break;
3017     case NEON_SADDL:
3018       mnemonic = "saddl";
3019       break;
3020     case NEON_SMLAL:
3021       mnemonic = "smlal";
3022       break;
3023     case NEON_SMLSL:
3024       mnemonic = "smlsl";
3025       break;
3026     case NEON_SMULL:
3027       mnemonic = "smull";
3028       break;
3029     case NEON_SSUBL:
3030       mnemonic = "ssubl";
3031       break;
3032     case NEON_SQDMLAL:
3033       mnemonic = "sqdmlal";
3034       break;
3035     case NEON_SQDMLSL:
3036       mnemonic = "sqdmlsl";
3037       break;
3038     case NEON_SQDMULL:
3039       mnemonic = "sqdmull";
3040       break;
3041     case NEON_UABAL:
3042       mnemonic = "uabal";
3043       break;
3044     case NEON_UABDL:
3045       mnemonic = "uabdl";
3046       break;
3047     case NEON_UADDL:
3048       mnemonic = "uaddl";
3049       break;
3050     case NEON_UMLAL:
3051       mnemonic = "umlal";
3052       break;
3053     case NEON_UMLSL:
3054       mnemonic = "umlsl";
3055       break;
3056     case NEON_UMULL:
3057       mnemonic = "umull";
3058       break;
3059     case NEON_USUBL:
3060       mnemonic = "usubl";
3061       break;
3062     case NEON_SADDW:
3063       mnemonic = "saddw";
3064       nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
3065       break;
3066     case NEON_SSUBW:
3067       mnemonic = "ssubw";
3068       nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
3069       break;
3070     case NEON_UADDW:
3071       mnemonic = "uaddw";
3072       nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
3073       break;
3074     case NEON_USUBW:
3075       mnemonic = "usubw";
3076       nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
3077       break;
3078     case NEON_ADDHN:
3079       mnemonic = "addhn";
3080       nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
3081       nfd.SetFormatMap(0, nfd.IntegerFormatMap());
3082       break;
3083     case NEON_RADDHN:
3084       mnemonic = "raddhn";
3085       nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
3086       nfd.SetFormatMap(0, nfd.IntegerFormatMap());
3087       break;
3088     case NEON_RSUBHN:
3089       mnemonic = "rsubhn";
3090       nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
3091       nfd.SetFormatMap(0, nfd.IntegerFormatMap());
3092       break;
3093     case NEON_SUBHN:
3094       mnemonic = "subhn";
3095       nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
3096       nfd.SetFormatMap(0, nfd.IntegerFormatMap());
3097       break;
3098     default:
3099       form = "(NEON3Different)";
3100   }
3101   Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
3102 }
3103 
3104 
VisitNEONAcrossLanes(const Instruction * instr)3105 void Disassembler::VisitNEONAcrossLanes(const Instruction *instr) {
3106   const char *mnemonic = "unimplemented";
3107   const char *form = "%sd, 'Vn.%s";
3108   const char *form_half = "'Hd, 'Vn.%s";
3109   bool half_op = false;
3110   static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
3111 
3112   NEONFormatDecoder nfd(instr,
3113                         NEONFormatDecoder::ScalarFormatMap(),
3114                         NEONFormatDecoder::IntegerFormatMap());
3115 
3116   if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
3117     half_op = true;
3118     form = form_half;
3119     nfd.SetFormatMaps(&map_half);
3120     switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
3121       case NEON_FMAXV_H:
3122         mnemonic = "fmaxv";
3123         break;
3124       case NEON_FMINV_H:
3125         mnemonic = "fminv";
3126         break;
3127       case NEON_FMAXNMV_H:
3128         mnemonic = "fmaxnmv";
3129         break;
3130       case NEON_FMINNMV_H:
3131         mnemonic = "fminnmv";
3132         break;
3133     }
3134   } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
3135     nfd.SetFormatMap(0, nfd.FPScalarFormatMap());
3136     nfd.SetFormatMap(1, nfd.FPFormatMap());
3137     switch (instr->Mask(NEONAcrossLanesFPMask)) {
3138       case NEON_FMAXV:
3139         mnemonic = "fmaxv";
3140         break;
3141       case NEON_FMINV:
3142         mnemonic = "fminv";
3143         break;
3144       case NEON_FMAXNMV:
3145         mnemonic = "fmaxnmv";
3146         break;
3147       case NEON_FMINNMV:
3148         mnemonic = "fminnmv";
3149         break;
3150       default:
3151         form = "(NEONAcrossLanes)";
3152         break;
3153     }
3154   } else if (instr->Mask(NEONAcrossLanesFMask) == NEONAcrossLanesFixed) {
3155     switch (instr->Mask(NEONAcrossLanesMask)) {
3156       case NEON_ADDV:
3157         mnemonic = "addv";
3158         break;
3159       case NEON_SMAXV:
3160         mnemonic = "smaxv";
3161         break;
3162       case NEON_SMINV:
3163         mnemonic = "sminv";
3164         break;
3165       case NEON_UMAXV:
3166         mnemonic = "umaxv";
3167         break;
3168       case NEON_UMINV:
3169         mnemonic = "uminv";
3170         break;
3171       case NEON_SADDLV:
3172         mnemonic = "saddlv";
3173         nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
3174         break;
3175       case NEON_UADDLV:
3176         mnemonic = "uaddlv";
3177         nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
3178         break;
3179       default:
3180         form = "(NEONAcrossLanes)";
3181         break;
3182     }
3183   }
3184 
3185   if (half_op) {
3186     Format(instr, mnemonic, nfd.Substitute(form));
3187   } else {
3188     Format(instr,
3189            mnemonic,
3190            nfd.Substitute(form,
3191                           NEONFormatDecoder::kPlaceholder,
3192                           NEONFormatDecoder::kFormat));
3193   }
3194 }
3195 
3196 
VisitNEONByIndexedElement(const Instruction * instr)3197 void Disassembler::VisitNEONByIndexedElement(const Instruction *instr) {
3198   const char *mnemonic = "unimplemented";
3199   bool l_instr = false;
3200   bool fp_instr = false;
3201   bool cn_instr = false;
3202   bool half_instr = false;
3203   bool fhm_instr = false;  // FMLAL{2}, FMLSL{2}
3204 
3205   const char *form = "'Vd.%s, 'Vn.%s, 'Ve.%s['IVByElemIndex]";
3206 
3207   static const NEONFormatMap map_ta = {{23, 22}, {NF_UNDEF, NF_4S, NF_2D}};
3208   static const NEONFormatMap map_cn =
3209       {{23, 22, 30},
3210        {NF_UNDEF, NF_UNDEF, NF_4H, NF_8H, NF_UNDEF, NF_4S, NF_UNDEF, NF_UNDEF}};
3211   static const NEONFormatMap map_usdot = {{30}, {NF_8B, NF_16B}};
3212   static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
3213 
3214   NEONFormatDecoder nfd(instr,
3215                         &map_ta,
3216                         NEONFormatDecoder::IntegerFormatMap(),
3217                         NEONFormatDecoder::ScalarFormatMap());
3218 
3219   switch (instr->Mask(NEONByIndexedElementMask)) {
3220     case NEON_SMULL_byelement:
3221       mnemonic = "smull";
3222       l_instr = true;
3223       break;
3224     case NEON_UMULL_byelement:
3225       mnemonic = "umull";
3226       l_instr = true;
3227       break;
3228     case NEON_SMLAL_byelement:
3229       mnemonic = "smlal";
3230       l_instr = true;
3231       break;
3232     case NEON_UMLAL_byelement:
3233       mnemonic = "umlal";
3234       l_instr = true;
3235       break;
3236     case NEON_SMLSL_byelement:
3237       mnemonic = "smlsl";
3238       l_instr = true;
3239       break;
3240     case NEON_UMLSL_byelement:
3241       mnemonic = "umlsl";
3242       l_instr = true;
3243       break;
3244     case NEON_SQDMULL_byelement:
3245       mnemonic = "sqdmull";
3246       l_instr = true;
3247       break;
3248     case NEON_SQDMLAL_byelement:
3249       mnemonic = "sqdmlal";
3250       l_instr = true;
3251       break;
3252     case NEON_SQDMLSL_byelement:
3253       mnemonic = "sqdmlsl";
3254       l_instr = true;
3255       break;
3256     case NEON_MUL_byelement:
3257       mnemonic = "mul";
3258       break;
3259     case NEON_MLA_byelement:
3260       mnemonic = "mla";
3261       break;
3262     case NEON_MLS_byelement:
3263       mnemonic = "mls";
3264       break;
3265     case NEON_SQDMULH_byelement:
3266       mnemonic = "sqdmulh";
3267       break;
3268     case NEON_SQRDMULH_byelement:
3269       mnemonic = "sqrdmulh";
3270       break;
3271     case NEON_SDOT_byelement:
3272       mnemonic = "sdot";
3273       form = "'Vd.%s, 'Vn.%s, 'Ve.4b['IVByElemIndex]";
3274       nfd.SetFormatMap(1, &map_usdot);
3275       break;
3276     case NEON_SQRDMLAH_byelement:
3277       mnemonic = "sqrdmlah";
3278       break;
3279     case NEON_UDOT_byelement:
3280       mnemonic = "udot";
3281       form = "'Vd.%s, 'Vn.%s, 'Ve.4b['IVByElemIndex]";
3282       nfd.SetFormatMap(1, &map_usdot);
3283       break;
3284     case NEON_SQRDMLSH_byelement:
3285       mnemonic = "sqrdmlsh";
3286       break;
3287     default: {
3288       switch (instr->Mask(NEONByIndexedElementFPLongMask)) {
3289         case NEON_FMLAL_H_byelement:
3290           mnemonic = "fmlal";
3291           fhm_instr = true;
3292           break;
3293         case NEON_FMLAL2_H_byelement:
3294           mnemonic = "fmlal2";
3295           fhm_instr = true;
3296           break;
3297         case NEON_FMLSL_H_byelement:
3298           mnemonic = "fmlsl";
3299           fhm_instr = true;
3300           break;
3301         case NEON_FMLSL2_H_byelement:
3302           mnemonic = "fmlsl2";
3303           fhm_instr = true;
3304           break;
3305         default:
3306           switch (instr->Mask(NEONByIndexedElementFPMask)) {
3307             case NEON_FMUL_byelement:
3308               mnemonic = "fmul";
3309               fp_instr = true;
3310               break;
3311             case NEON_FMLA_byelement:
3312               mnemonic = "fmla";
3313               fp_instr = true;
3314               break;
3315             case NEON_FMLS_byelement:
3316               mnemonic = "fmls";
3317               fp_instr = true;
3318               break;
3319             case NEON_FMULX_byelement:
3320               mnemonic = "fmulx";
3321               fp_instr = true;
3322               break;
3323             case NEON_FMLA_H_byelement:
3324               mnemonic = "fmla";
3325               half_instr = true;
3326               break;
3327             case NEON_FMLS_H_byelement:
3328               mnemonic = "fmls";
3329               half_instr = true;
3330               break;
3331             case NEON_FMUL_H_byelement:
3332               mnemonic = "fmul";
3333               half_instr = true;
3334               break;
3335             case NEON_FMULX_H_byelement:
3336               mnemonic = "fmulx";
3337               half_instr = true;
3338               break;
3339             default:
3340               switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
3341                 case NEON_FCMLA_byelement:
3342                   mnemonic = "fcmla";
3343                   cn_instr = true;
3344                   form = "'Vd.%s, 'Vn.%s, 'Ve.%s['IVByElemIndexRot], 'ILFCNR";
3345                   break;
3346               }
3347           }
3348       }
3349     }
3350   }
3351 
3352   if (fhm_instr) {
3353     // These are oddballs. Set the format manually.
3354     form = (instr->Mask(NEON_Q) == 0)
3355                ? "'Vd.2s, 'Vn.2h, 'Ve.h['IVByElemIndexFHM]"
3356                : "'Vd.4s, 'Vn.4h, 'Ve.h['IVByElemIndexFHM]";
3357     Format(instr, mnemonic, nfd.Substitute(form));
3358   } else if (half_instr) {
3359     form = "'Vd.%s, 'Vn.%s, 'Ve.h['IVByElemIndex]";
3360     nfd.SetFormatMaps(&map_half, &map_half);
3361     Format(instr, mnemonic, nfd.Substitute(form));
3362   } else if (l_instr) {
3363     Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
3364   } else if (fp_instr) {
3365     nfd.SetFormatMap(0, nfd.FPFormatMap());
3366     Format(instr, mnemonic, nfd.Substitute(form));
3367   } else if (cn_instr) {
3368     nfd.SetFormatMap(0, &map_cn);
3369     nfd.SetFormatMap(1, &map_cn);
3370     Format(instr, mnemonic, nfd.Substitute(form));
3371   } else {
3372     nfd.SetFormatMap(0, nfd.IntegerFormatMap());
3373     Format(instr, mnemonic, nfd.Substitute(form));
3374   }
3375 }
3376 
3377 
VisitNEONCopy(const Instruction * instr)3378 void Disassembler::VisitNEONCopy(const Instruction *instr) {
3379   const char *mnemonic = "unimplemented";
3380   const char *form = "(NEONCopy)";
3381 
3382   NEONFormatDecoder nfd(instr,
3383                         NEONFormatDecoder::TriangularFormatMap(),
3384                         NEONFormatDecoder::TriangularScalarFormatMap());
3385 
3386   if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
3387     mnemonic = "mov";
3388     nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
3389     form = "'Vd.%s['IVInsIndex1], 'Vn.%s['IVInsIndex2]";
3390   } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
3391     mnemonic = "mov";
3392     nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
3393     if (nfd.GetVectorFormat() == kFormatD) {
3394       form = "'Vd.%s['IVInsIndex1], 'Xn";
3395     } else {
3396       form = "'Vd.%s['IVInsIndex1], 'Wn";
3397     }
3398   } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
3399     if (instr->Mask(NEON_Q) || ((instr->GetImmNEON5() & 7) == 4)) {
3400       mnemonic = "mov";
3401     } else {
3402       mnemonic = "umov";
3403     }
3404     nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
3405     if (nfd.GetVectorFormat() == kFormatD) {
3406       form = "'Xd, 'Vn.%s['IVInsIndex1]";
3407     } else {
3408       form = "'Wd, 'Vn.%s['IVInsIndex1]";
3409     }
3410   } else if (instr->Mask(NEONCopySmovMask) == NEON_SMOV) {
3411     mnemonic = "smov";
3412     nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
3413     form = "'R30d, 'Vn.%s['IVInsIndex1]";
3414   } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
3415     mnemonic = "dup";
3416     form = "'Vd.%s, 'Vn.%s['IVInsIndex1]";
3417   } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
3418     mnemonic = "dup";
3419     if (nfd.GetVectorFormat() == kFormat2D) {
3420       form = "'Vd.%s, 'Xn";
3421     } else {
3422       form = "'Vd.%s, 'Wn";
3423     }
3424   }
3425   Format(instr, mnemonic, nfd.Substitute(form));
3426 }
3427 
3428 
VisitNEONExtract(const Instruction * instr)3429 void Disassembler::VisitNEONExtract(const Instruction *instr) {
3430   const char *mnemonic = "unimplemented";
3431   const char *form = "(NEONExtract)";
3432   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
3433   if (instr->Mask(NEONExtractMask) == NEON_EXT) {
3434     mnemonic = "ext";
3435     form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVExtract";
3436   }
3437   Format(instr, mnemonic, nfd.Substitute(form));
3438 }
3439 
3440 
VisitNEONLoadStoreMultiStruct(const Instruction * instr)3441 void Disassembler::VisitNEONLoadStoreMultiStruct(const Instruction *instr) {
3442   const char *mnemonic = NULL;
3443   const char *form = NULL;
3444   const char *form_1v = "{'Vt.%1$s}, ['Xns]";
3445   const char *form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns]";
3446   const char *form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns]";
3447   const char *form_4v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]";
3448   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3449 
3450   switch (instr->Mask(NEONLoadStoreMultiStructMask)) {
3451     case NEON_LD1_1v:
3452       mnemonic = "ld1";
3453       form = form_1v;
3454       break;
3455     case NEON_LD1_2v:
3456       mnemonic = "ld1";
3457       form = form_2v;
3458       break;
3459     case NEON_LD1_3v:
3460       mnemonic = "ld1";
3461       form = form_3v;
3462       break;
3463     case NEON_LD1_4v:
3464       mnemonic = "ld1";
3465       form = form_4v;
3466       break;
3467     case NEON_LD2:
3468       mnemonic = "ld2";
3469       form = form_2v;
3470       break;
3471     case NEON_LD3:
3472       mnemonic = "ld3";
3473       form = form_3v;
3474       break;
3475     case NEON_LD4:
3476       mnemonic = "ld4";
3477       form = form_4v;
3478       break;
3479     case NEON_ST1_1v:
3480       mnemonic = "st1";
3481       form = form_1v;
3482       break;
3483     case NEON_ST1_2v:
3484       mnemonic = "st1";
3485       form = form_2v;
3486       break;
3487     case NEON_ST1_3v:
3488       mnemonic = "st1";
3489       form = form_3v;
3490       break;
3491     case NEON_ST1_4v:
3492       mnemonic = "st1";
3493       form = form_4v;
3494       break;
3495     case NEON_ST2:
3496       mnemonic = "st2";
3497       form = form_2v;
3498       break;
3499     case NEON_ST3:
3500       mnemonic = "st3";
3501       form = form_3v;
3502       break;
3503     case NEON_ST4:
3504       mnemonic = "st4";
3505       form = form_4v;
3506       break;
3507     default:
3508       break;
3509   }
3510 
3511   // Work out unallocated encodings.
3512   bool allocated = (mnemonic != NULL);
3513   switch (instr->Mask(NEONLoadStoreMultiStructMask)) {
3514     case NEON_LD2:
3515     case NEON_LD3:
3516     case NEON_LD4:
3517     case NEON_ST2:
3518     case NEON_ST3:
3519     case NEON_ST4:
3520       // LD[2-4] and ST[2-4] cannot use .1d format.
3521       allocated = (instr->GetNEONQ() != 0) || (instr->GetNEONLSSize() != 3);
3522       break;
3523     default:
3524       break;
3525   }
3526   if (allocated) {
3527     VIXL_ASSERT(mnemonic != NULL);
3528     VIXL_ASSERT(form != NULL);
3529   } else {
3530     mnemonic = "unallocated";
3531     form = "(NEONLoadStoreMultiStruct)";
3532   }
3533 
3534   Format(instr, mnemonic, nfd.Substitute(form));
3535 }
3536 
3537 
VisitNEONLoadStoreMultiStructPostIndex(const Instruction * instr)3538 void Disassembler::VisitNEONLoadStoreMultiStructPostIndex(
3539     const Instruction *instr) {
3540   const char *mnemonic = NULL;
3541   const char *form = NULL;
3542   const char *form_1v = "{'Vt.%1$s}, ['Xns], 'Xmr1";
3543   const char *form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns], 'Xmr2";
3544   const char *form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns], 'Xmr3";
3545   const char *form_4v =
3546       "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmr4";
3547   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3548 
3549   switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
3550     case NEON_LD1_1v_post:
3551       mnemonic = "ld1";
3552       form = form_1v;
3553       break;
3554     case NEON_LD1_2v_post:
3555       mnemonic = "ld1";
3556       form = form_2v;
3557       break;
3558     case NEON_LD1_3v_post:
3559       mnemonic = "ld1";
3560       form = form_3v;
3561       break;
3562     case NEON_LD1_4v_post:
3563       mnemonic = "ld1";
3564       form = form_4v;
3565       break;
3566     case NEON_LD2_post:
3567       mnemonic = "ld2";
3568       form = form_2v;
3569       break;
3570     case NEON_LD3_post:
3571       mnemonic = "ld3";
3572       form = form_3v;
3573       break;
3574     case NEON_LD4_post:
3575       mnemonic = "ld4";
3576       form = form_4v;
3577       break;
3578     case NEON_ST1_1v_post:
3579       mnemonic = "st1";
3580       form = form_1v;
3581       break;
3582     case NEON_ST1_2v_post:
3583       mnemonic = "st1";
3584       form = form_2v;
3585       break;
3586     case NEON_ST1_3v_post:
3587       mnemonic = "st1";
3588       form = form_3v;
3589       break;
3590     case NEON_ST1_4v_post:
3591       mnemonic = "st1";
3592       form = form_4v;
3593       break;
3594     case NEON_ST2_post:
3595       mnemonic = "st2";
3596       form = form_2v;
3597       break;
3598     case NEON_ST3_post:
3599       mnemonic = "st3";
3600       form = form_3v;
3601       break;
3602     case NEON_ST4_post:
3603       mnemonic = "st4";
3604       form = form_4v;
3605       break;
3606     default:
3607       break;
3608   }
3609 
3610   // Work out unallocated encodings.
3611   bool allocated = (mnemonic != NULL);
3612   switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
3613     case NEON_LD2_post:
3614     case NEON_LD3_post:
3615     case NEON_LD4_post:
3616     case NEON_ST2_post:
3617     case NEON_ST3_post:
3618     case NEON_ST4_post:
3619       // LD[2-4] and ST[2-4] cannot use .1d format.
3620       allocated = (instr->GetNEONQ() != 0) || (instr->GetNEONLSSize() != 3);
3621       break;
3622     default:
3623       break;
3624   }
3625   if (allocated) {
3626     VIXL_ASSERT(mnemonic != NULL);
3627     VIXL_ASSERT(form != NULL);
3628   } else {
3629     mnemonic = "unallocated";
3630     form = "(NEONLoadStoreMultiStructPostIndex)";
3631   }
3632 
3633   Format(instr, mnemonic, nfd.Substitute(form));
3634 }
3635 
3636 
VisitNEONLoadStoreSingleStruct(const Instruction * instr)3637 void Disassembler::VisitNEONLoadStoreSingleStruct(const Instruction *instr) {
3638   const char *mnemonic = NULL;
3639   const char *form = NULL;
3640 
3641   const char *form_1b = "{'Vt.b}['IVLSLane0], ['Xns]";
3642   const char *form_1h = "{'Vt.h}['IVLSLane1], ['Xns]";
3643   const char *form_1s = "{'Vt.s}['IVLSLane2], ['Xns]";
3644   const char *form_1d = "{'Vt.d}['IVLSLane3], ['Xns]";
3645   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3646 
3647   switch (instr->Mask(NEONLoadStoreSingleStructMask)) {
3648     case NEON_LD1_b:
3649       mnemonic = "ld1";
3650       form = form_1b;
3651       break;
3652     case NEON_LD1_h:
3653       mnemonic = "ld1";
3654       form = form_1h;
3655       break;
3656     case NEON_LD1_s:
3657       mnemonic = "ld1";
3658       VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
3659       form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
3660       break;
3661     case NEON_ST1_b:
3662       mnemonic = "st1";
3663       form = form_1b;
3664       break;
3665     case NEON_ST1_h:
3666       mnemonic = "st1";
3667       form = form_1h;
3668       break;
3669     case NEON_ST1_s:
3670       mnemonic = "st1";
3671       VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
3672       form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
3673       break;
3674     case NEON_LD1R:
3675       mnemonic = "ld1r";
3676       form = "{'Vt.%s}, ['Xns]";
3677       break;
3678     case NEON_LD2_b:
3679     case NEON_ST2_b:
3680       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3681       form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns]";
3682       break;
3683     case NEON_LD2_h:
3684     case NEON_ST2_h:
3685       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3686       form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns]";
3687       break;
3688     case NEON_LD2_s:
3689     case NEON_ST2_s:
3690       VIXL_STATIC_ASSERT((NEON_ST2_s | (1 << NEONLSSize_offset)) == NEON_ST2_d);
3691       VIXL_STATIC_ASSERT((NEON_LD2_s | (1 << NEONLSSize_offset)) == NEON_LD2_d);
3692       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3693       if ((instr->GetNEONLSSize() & 1) == 0) {
3694         form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns]";
3695       } else {
3696         form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns]";
3697       }
3698       break;
3699     case NEON_LD2R:
3700       mnemonic = "ld2r";
3701       form = "{'Vt.%s, 'Vt2.%s}, ['Xns]";
3702       break;
3703     case NEON_LD3_b:
3704     case NEON_ST3_b:
3705       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3706       form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns]";
3707       break;
3708     case NEON_LD3_h:
3709     case NEON_ST3_h:
3710       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3711       form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns]";
3712       break;
3713     case NEON_LD3_s:
3714     case NEON_ST3_s:
3715       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3716       if ((instr->GetNEONLSSize() & 1) == 0) {
3717         form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns]";
3718       } else {
3719         form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns]";
3720       }
3721       break;
3722     case NEON_LD3R:
3723       mnemonic = "ld3r";
3724       form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns]";
3725       break;
3726     case NEON_LD4_b:
3727     case NEON_ST4_b:
3728       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3729       form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns]";
3730       break;
3731     case NEON_LD4_h:
3732     case NEON_ST4_h:
3733       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3734       form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns]";
3735       break;
3736     case NEON_LD4_s:
3737     case NEON_ST4_s:
3738       VIXL_STATIC_ASSERT((NEON_LD4_s | (1 << NEONLSSize_offset)) == NEON_LD4_d);
3739       VIXL_STATIC_ASSERT((NEON_ST4_s | (1 << NEONLSSize_offset)) == NEON_ST4_d);
3740       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3741       if ((instr->GetNEONLSSize() & 1) == 0) {
3742         form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns]";
3743       } else {
3744         form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns]";
3745       }
3746       break;
3747     case NEON_LD4R:
3748       mnemonic = "ld4r";
3749       form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]";
3750       break;
3751     default:
3752       break;
3753   }
3754 
3755   // Work out unallocated encodings.
3756   bool allocated = (mnemonic != NULL);
3757   switch (instr->Mask(NEONLoadStoreSingleStructMask)) {
3758     case NEON_LD1_h:
3759     case NEON_LD2_h:
3760     case NEON_LD3_h:
3761     case NEON_LD4_h:
3762     case NEON_ST1_h:
3763     case NEON_ST2_h:
3764     case NEON_ST3_h:
3765     case NEON_ST4_h:
3766       VIXL_ASSERT(allocated);
3767       allocated = ((instr->GetNEONLSSize() & 1) == 0);
3768       break;
3769     case NEON_LD1_s:
3770     case NEON_LD2_s:
3771     case NEON_LD3_s:
3772     case NEON_LD4_s:
3773     case NEON_ST1_s:
3774     case NEON_ST2_s:
3775     case NEON_ST3_s:
3776     case NEON_ST4_s:
3777       VIXL_ASSERT(allocated);
3778       allocated = (instr->GetNEONLSSize() <= 1) &&
3779                   ((instr->GetNEONLSSize() == 0) || (instr->GetNEONS() == 0));
3780       break;
3781     case NEON_LD1R:
3782     case NEON_LD2R:
3783     case NEON_LD3R:
3784     case NEON_LD4R:
3785       VIXL_ASSERT(allocated);
3786       allocated = (instr->GetNEONS() == 0);
3787       break;
3788     default:
3789       break;
3790   }
3791   if (allocated) {
3792     VIXL_ASSERT(mnemonic != NULL);
3793     VIXL_ASSERT(form != NULL);
3794   } else {
3795     mnemonic = "unallocated";
3796     form = "(NEONLoadStoreSingleStruct)";
3797   }
3798 
3799   Format(instr, mnemonic, nfd.Substitute(form));
3800 }
3801 
3802 
VisitNEONLoadStoreSingleStructPostIndex(const Instruction * instr)3803 void Disassembler::VisitNEONLoadStoreSingleStructPostIndex(
3804     const Instruction *instr) {
3805   const char *mnemonic = NULL;
3806   const char *form = NULL;
3807 
3808   const char *form_1b = "{'Vt.b}['IVLSLane0], ['Xns], 'Xmb1";
3809   const char *form_1h = "{'Vt.h}['IVLSLane1], ['Xns], 'Xmb2";
3810   const char *form_1s = "{'Vt.s}['IVLSLane2], ['Xns], 'Xmb4";
3811   const char *form_1d = "{'Vt.d}['IVLSLane3], ['Xns], 'Xmb8";
3812   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3813 
3814   switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
3815     case NEON_LD1_b_post:
3816       mnemonic = "ld1";
3817       form = form_1b;
3818       break;
3819     case NEON_LD1_h_post:
3820       mnemonic = "ld1";
3821       form = form_1h;
3822       break;
3823     case NEON_LD1_s_post:
3824       mnemonic = "ld1";
3825       VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
3826       form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
3827       break;
3828     case NEON_ST1_b_post:
3829       mnemonic = "st1";
3830       form = form_1b;
3831       break;
3832     case NEON_ST1_h_post:
3833       mnemonic = "st1";
3834       form = form_1h;
3835       break;
3836     case NEON_ST1_s_post:
3837       mnemonic = "st1";
3838       VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
3839       form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
3840       break;
3841     case NEON_LD1R_post:
3842       mnemonic = "ld1r";
3843       form = "{'Vt.%s}, ['Xns], 'Xmz1";
3844       break;
3845     case NEON_LD2_b_post:
3846     case NEON_ST2_b_post:
3847       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3848       form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns], 'Xmb2";
3849       break;
3850     case NEON_ST2_h_post:
3851     case NEON_LD2_h_post:
3852       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3853       form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns], 'Xmb4";
3854       break;
3855     case NEON_LD2_s_post:
3856     case NEON_ST2_s_post:
3857       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3858       if ((instr->GetNEONLSSize() & 1) == 0)
3859         form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns], 'Xmb8";
3860       else
3861         form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns], 'Xmb16";
3862       break;
3863     case NEON_LD2R_post:
3864       mnemonic = "ld2r";
3865       form = "{'Vt.%s, 'Vt2.%s}, ['Xns], 'Xmz2";
3866       break;
3867     case NEON_LD3_b_post:
3868     case NEON_ST3_b_post:
3869       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3870       form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns], 'Xmb3";
3871       break;
3872     case NEON_LD3_h_post:
3873     case NEON_ST3_h_post:
3874       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3875       form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns], 'Xmb6";
3876       break;
3877     case NEON_LD3_s_post:
3878     case NEON_ST3_s_post:
3879       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3880       if ((instr->GetNEONLSSize() & 1) == 0)
3881         form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns], 'Xmb12";
3882       else
3883         form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns], 'Xmb24";
3884       break;
3885     case NEON_LD3R_post:
3886       mnemonic = "ld3r";
3887       form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns], 'Xmz3";
3888       break;
3889     case NEON_LD4_b_post:
3890     case NEON_ST4_b_post:
3891       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3892       form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns], 'Xmb4";
3893       break;
3894     case NEON_LD4_h_post:
3895     case NEON_ST4_h_post:
3896       mnemonic = (instr->GetLdStXLoad()) == 1 ? "ld4" : "st4";
3897       form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns], 'Xmb8";
3898       break;
3899     case NEON_LD4_s_post:
3900     case NEON_ST4_s_post:
3901       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3902       if ((instr->GetNEONLSSize() & 1) == 0)
3903         form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns], 'Xmb16";
3904       else
3905         form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns], 'Xmb32";
3906       break;
3907     case NEON_LD4R_post:
3908       mnemonic = "ld4r";
3909       form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmz4";
3910       break;
3911     default:
3912       break;
3913   }
3914 
3915   // Work out unallocated encodings.
3916   bool allocated = (mnemonic != NULL);
3917   switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
3918     case NEON_LD1_h_post:
3919     case NEON_LD2_h_post:
3920     case NEON_LD3_h_post:
3921     case NEON_LD4_h_post:
3922     case NEON_ST1_h_post:
3923     case NEON_ST2_h_post:
3924     case NEON_ST3_h_post:
3925     case NEON_ST4_h_post:
3926       VIXL_ASSERT(allocated);
3927       allocated = ((instr->GetNEONLSSize() & 1) == 0);
3928       break;
3929     case NEON_LD1_s_post:
3930     case NEON_LD2_s_post:
3931     case NEON_LD3_s_post:
3932     case NEON_LD4_s_post:
3933     case NEON_ST1_s_post:
3934     case NEON_ST2_s_post:
3935     case NEON_ST3_s_post:
3936     case NEON_ST4_s_post:
3937       VIXL_ASSERT(allocated);
3938       allocated = (instr->GetNEONLSSize() <= 1) &&
3939                   ((instr->GetNEONLSSize() == 0) || (instr->GetNEONS() == 0));
3940       break;
3941     case NEON_LD1R_post:
3942     case NEON_LD2R_post:
3943     case NEON_LD3R_post:
3944     case NEON_LD4R_post:
3945       VIXL_ASSERT(allocated);
3946       allocated = (instr->GetNEONS() == 0);
3947       break;
3948     default:
3949       break;
3950   }
3951   if (allocated) {
3952     VIXL_ASSERT(mnemonic != NULL);
3953     VIXL_ASSERT(form != NULL);
3954   } else {
3955     mnemonic = "unallocated";
3956     form = "(NEONLoadStoreSingleStructPostIndex)";
3957   }
3958 
3959   Format(instr, mnemonic, nfd.Substitute(form));
3960 }
3961 
3962 
VisitNEONModifiedImmediate(const Instruction * instr)3963 void Disassembler::VisitNEONModifiedImmediate(const Instruction *instr) {
3964   const char *mnemonic = "unimplemented";
3965   const char *form = "'Vt.%s, 'IVMIImm8, lsl 'IVMIShiftAmt1";
3966 
3967   int half_enc = instr->ExtractBit(11);
3968   int cmode = instr->GetNEONCmode();
3969   int cmode_3 = (cmode >> 3) & 1;
3970   int cmode_2 = (cmode >> 2) & 1;
3971   int cmode_1 = (cmode >> 1) & 1;
3972   int cmode_0 = cmode & 1;
3973   int q = instr->GetNEONQ();
3974   int op = instr->GetNEONModImmOp();
3975 
3976   static const NEONFormatMap map_b = {{30}, {NF_8B, NF_16B}};
3977   static const NEONFormatMap map_h = {{30}, {NF_4H, NF_8H}};
3978   static const NEONFormatMap map_s = {{30}, {NF_2S, NF_4S}};
3979   NEONFormatDecoder nfd(instr, &map_b);
3980   if (cmode_3 == 0) {
3981     if (cmode_0 == 0) {
3982       mnemonic = (op == 1) ? "mvni" : "movi";
3983     } else {  // cmode<0> == '1'.
3984       mnemonic = (op == 1) ? "bic" : "orr";
3985     }
3986     nfd.SetFormatMap(0, &map_s);
3987   } else {  // cmode<3> == '1'.
3988     if (cmode_2 == 0) {
3989       if (cmode_0 == 0) {
3990         mnemonic = (op == 1) ? "mvni" : "movi";
3991       } else {  // cmode<0> == '1'.
3992         mnemonic = (op == 1) ? "bic" : "orr";
3993       }
3994       nfd.SetFormatMap(0, &map_h);
3995     } else {  // cmode<2> == '1'.
3996       if (cmode_1 == 0) {
3997         mnemonic = (op == 1) ? "mvni" : "movi";
3998         form = "'Vt.%s, 'IVMIImm8, msl 'IVMIShiftAmt2";
3999         nfd.SetFormatMap(0, &map_s);
4000       } else {  // cmode<1> == '1'.
4001         if (cmode_0 == 0) {
4002           mnemonic = "movi";
4003           if (op == 0) {
4004             form = "'Vt.%s, 'IVMIImm8";
4005           } else {
4006             form = (q == 0) ? "'Dd, 'IVMIImm" : "'Vt.2d, 'IVMIImm";
4007           }
4008         } else {  // cmode<0> == '1'
4009           mnemonic = "fmov";
4010           form = "'Vt.%s, 'IFPNeon";
4011           if (half_enc == 1) {
4012             nfd.SetFormatMap(0, &map_h);
4013           } else if (op == 0) {
4014             nfd.SetFormatMap(0, &map_s);
4015           } else if (q == 1) {
4016             form = "'Vt.2d, 'IFPNeon";
4017           } else {
4018             mnemonic = "unallocated";
4019             form = "(NEONModifiedImmediate)";
4020           }
4021         }
4022       }
4023     }
4024   }
4025   Format(instr, mnemonic, nfd.Substitute(form));
4026 }
4027 
4028 
VisitNEONScalar2RegMisc(const Instruction * instr)4029 void Disassembler::VisitNEONScalar2RegMisc(const Instruction *instr) {
4030   const char *mnemonic = "unimplemented";
4031   const char *form = "%sd, %sn";
4032   const char *form_0 = "%sd, %sn, #0";
4033   const char *form_fp0 = "%sd, %sn, #0.0";
4034 
4035   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4036 
4037   if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
4038     // These instructions all use a two bit size field, except NOT and RBIT,
4039     // which use the field to encode the operation.
4040     switch (instr->Mask(NEONScalar2RegMiscMask)) {
4041       case NEON_CMGT_zero_scalar:
4042         mnemonic = "cmgt";
4043         form = form_0;
4044         break;
4045       case NEON_CMGE_zero_scalar:
4046         mnemonic = "cmge";
4047         form = form_0;
4048         break;
4049       case NEON_CMLE_zero_scalar:
4050         mnemonic = "cmle";
4051         form = form_0;
4052         break;
4053       case NEON_CMLT_zero_scalar:
4054         mnemonic = "cmlt";
4055         form = form_0;
4056         break;
4057       case NEON_CMEQ_zero_scalar:
4058         mnemonic = "cmeq";
4059         form = form_0;
4060         break;
4061       case NEON_NEG_scalar:
4062         mnemonic = "neg";
4063         break;
4064       case NEON_SQNEG_scalar:
4065         mnemonic = "sqneg";
4066         break;
4067       case NEON_ABS_scalar:
4068         mnemonic = "abs";
4069         break;
4070       case NEON_SQABS_scalar:
4071         mnemonic = "sqabs";
4072         break;
4073       case NEON_SUQADD_scalar:
4074         mnemonic = "suqadd";
4075         break;
4076       case NEON_USQADD_scalar:
4077         mnemonic = "usqadd";
4078         break;
4079       default:
4080         form = "(NEONScalar2RegMisc)";
4081     }
4082   } else {
4083     // These instructions all use a one bit size field, except SQXTUN, SQXTN
4084     // and UQXTN, which use a two bit size field.
4085     nfd.SetFormatMaps(nfd.FPScalarFormatMap());
4086     switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
4087       case NEON_FRSQRTE_scalar:
4088         mnemonic = "frsqrte";
4089         break;
4090       case NEON_FRECPE_scalar:
4091         mnemonic = "frecpe";
4092         break;
4093       case NEON_SCVTF_scalar:
4094         mnemonic = "scvtf";
4095         break;
4096       case NEON_UCVTF_scalar:
4097         mnemonic = "ucvtf";
4098         break;
4099       case NEON_FCMGT_zero_scalar:
4100         mnemonic = "fcmgt";
4101         form = form_fp0;
4102         break;
4103       case NEON_FCMGE_zero_scalar:
4104         mnemonic = "fcmge";
4105         form = form_fp0;
4106         break;
4107       case NEON_FCMLE_zero_scalar:
4108         mnemonic = "fcmle";
4109         form = form_fp0;
4110         break;
4111       case NEON_FCMLT_zero_scalar:
4112         mnemonic = "fcmlt";
4113         form = form_fp0;
4114         break;
4115       case NEON_FCMEQ_zero_scalar:
4116         mnemonic = "fcmeq";
4117         form = form_fp0;
4118         break;
4119       case NEON_FRECPX_scalar:
4120         mnemonic = "frecpx";
4121         break;
4122       case NEON_FCVTNS_scalar:
4123         mnemonic = "fcvtns";
4124         break;
4125       case NEON_FCVTNU_scalar:
4126         mnemonic = "fcvtnu";
4127         break;
4128       case NEON_FCVTPS_scalar:
4129         mnemonic = "fcvtps";
4130         break;
4131       case NEON_FCVTPU_scalar:
4132         mnemonic = "fcvtpu";
4133         break;
4134       case NEON_FCVTMS_scalar:
4135         mnemonic = "fcvtms";
4136         break;
4137       case NEON_FCVTMU_scalar:
4138         mnemonic = "fcvtmu";
4139         break;
4140       case NEON_FCVTZS_scalar:
4141         mnemonic = "fcvtzs";
4142         break;
4143       case NEON_FCVTZU_scalar:
4144         mnemonic = "fcvtzu";
4145         break;
4146       case NEON_FCVTAS_scalar:
4147         mnemonic = "fcvtas";
4148         break;
4149       case NEON_FCVTAU_scalar:
4150         mnemonic = "fcvtau";
4151         break;
4152       case NEON_FCVTXN_scalar:
4153         nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
4154         mnemonic = "fcvtxn";
4155         break;
4156       default:
4157         nfd.SetFormatMap(0, nfd.ScalarFormatMap());
4158         nfd.SetFormatMap(1, nfd.LongScalarFormatMap());
4159         switch (instr->Mask(NEONScalar2RegMiscMask)) {
4160           case NEON_SQXTN_scalar:
4161             mnemonic = "sqxtn";
4162             break;
4163           case NEON_UQXTN_scalar:
4164             mnemonic = "uqxtn";
4165             break;
4166           case NEON_SQXTUN_scalar:
4167             mnemonic = "sqxtun";
4168             break;
4169           default:
4170             form = "(NEONScalar2RegMisc)";
4171         }
4172     }
4173   }
4174   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
4175 }
4176 
VisitNEONScalar2RegMiscFP16(const Instruction * instr)4177 void Disassembler::VisitNEONScalar2RegMiscFP16(const Instruction *instr) {
4178   const char *mnemonic = "unimplemented";
4179   const char *form = "'Hd, 'Hn";
4180   const char *form_fp0 = "'Hd, 'Hn, #0.0";
4181 
4182   switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
4183 #define FORMAT(A, B)        \
4184   case NEON_##A##_H_scalar: \
4185     mnemonic = B;           \
4186     break;
4187     // clang-format off
4188     FORMAT(FCVTNS,  "fcvtns")
4189     FORMAT(FCVTMS,  "fcvtms")
4190     FORMAT(FCVTAS,  "fcvtas")
4191     FORMAT(SCVTF,   "scvtf")
4192     FORMAT(FCVTPS,  "fcvtps")
4193     FORMAT(FCVTZS,  "fcvtzs")
4194     FORMAT(FRECPE,  "frecpe")
4195     FORMAT(FRECPX,  "frecpx")
4196     FORMAT(FCVTNU,  "fcvtnu")
4197     FORMAT(FCVTMU,  "fcvtmu")
4198     FORMAT(FCVTAU,  "fcvtau")
4199     FORMAT(UCVTF,   "ucvtf")
4200     FORMAT(FCVTPU,  "fcvtpu")
4201     FORMAT(FCVTZU,  "fcvtzu")
4202     FORMAT(FRSQRTE, "frsqrte")
4203 // clang-format on
4204 #undef FORMAT
4205 #define FORMAT(A, B)             \
4206   case NEON_##A##_H_zero_scalar: \
4207     mnemonic = B;                \
4208     form = form_fp0;             \
4209     break;
4210     FORMAT(FCMGT, "fcmgt")
4211     FORMAT(FCMEQ, "fcmeq")
4212     FORMAT(FCMLT, "fcmlt")
4213     FORMAT(FCMGE, "fcmge")
4214     FORMAT(FCMLE, "fcmle")
4215 #undef FORMAT
4216 
4217     default:
4218       VIXL_UNREACHABLE();
4219   }
4220   Format(instr, mnemonic, form);
4221 }
4222 
4223 
VisitNEONScalar3Diff(const Instruction * instr)4224 void Disassembler::VisitNEONScalar3Diff(const Instruction *instr) {
4225   const char *mnemonic = "unimplemented";
4226   const char *form = "%sd, %sn, %sm";
4227   NEONFormatDecoder nfd(instr,
4228                         NEONFormatDecoder::LongScalarFormatMap(),
4229                         NEONFormatDecoder::ScalarFormatMap());
4230 
4231   switch (instr->Mask(NEONScalar3DiffMask)) {
4232     case NEON_SQDMLAL_scalar:
4233       mnemonic = "sqdmlal";
4234       break;
4235     case NEON_SQDMLSL_scalar:
4236       mnemonic = "sqdmlsl";
4237       break;
4238     case NEON_SQDMULL_scalar:
4239       mnemonic = "sqdmull";
4240       break;
4241     default:
4242       form = "(NEONScalar3Diff)";
4243   }
4244   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
4245 }
4246 
4247 
VisitNEONScalar3Same(const Instruction * instr)4248 void Disassembler::VisitNEONScalar3Same(const Instruction *instr) {
4249   const char *mnemonic = "unimplemented";
4250   const char *form = "%sd, %sn, %sm";
4251   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4252 
4253   if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
4254     nfd.SetFormatMaps(nfd.FPScalarFormatMap());
4255     switch (instr->Mask(NEONScalar3SameFPMask)) {
4256       case NEON_FACGE_scalar:
4257         mnemonic = "facge";
4258         break;
4259       case NEON_FACGT_scalar:
4260         mnemonic = "facgt";
4261         break;
4262       case NEON_FCMEQ_scalar:
4263         mnemonic = "fcmeq";
4264         break;
4265       case NEON_FCMGE_scalar:
4266         mnemonic = "fcmge";
4267         break;
4268       case NEON_FCMGT_scalar:
4269         mnemonic = "fcmgt";
4270         break;
4271       case NEON_FMULX_scalar:
4272         mnemonic = "fmulx";
4273         break;
4274       case NEON_FRECPS_scalar:
4275         mnemonic = "frecps";
4276         break;
4277       case NEON_FRSQRTS_scalar:
4278         mnemonic = "frsqrts";
4279         break;
4280       case NEON_FABD_scalar:
4281         mnemonic = "fabd";
4282         break;
4283       default:
4284         form = "(NEONScalar3Same)";
4285     }
4286   } else {
4287     switch (instr->Mask(NEONScalar3SameMask)) {
4288       case NEON_ADD_scalar:
4289         mnemonic = "add";
4290         break;
4291       case NEON_SUB_scalar:
4292         mnemonic = "sub";
4293         break;
4294       case NEON_CMEQ_scalar:
4295         mnemonic = "cmeq";
4296         break;
4297       case NEON_CMGE_scalar:
4298         mnemonic = "cmge";
4299         break;
4300       case NEON_CMGT_scalar:
4301         mnemonic = "cmgt";
4302         break;
4303       case NEON_CMHI_scalar:
4304         mnemonic = "cmhi";
4305         break;
4306       case NEON_CMHS_scalar:
4307         mnemonic = "cmhs";
4308         break;
4309       case NEON_CMTST_scalar:
4310         mnemonic = "cmtst";
4311         break;
4312       case NEON_UQADD_scalar:
4313         mnemonic = "uqadd";
4314         break;
4315       case NEON_SQADD_scalar:
4316         mnemonic = "sqadd";
4317         break;
4318       case NEON_UQSUB_scalar:
4319         mnemonic = "uqsub";
4320         break;
4321       case NEON_SQSUB_scalar:
4322         mnemonic = "sqsub";
4323         break;
4324       case NEON_USHL_scalar:
4325         mnemonic = "ushl";
4326         break;
4327       case NEON_SSHL_scalar:
4328         mnemonic = "sshl";
4329         break;
4330       case NEON_UQSHL_scalar:
4331         mnemonic = "uqshl";
4332         break;
4333       case NEON_SQSHL_scalar:
4334         mnemonic = "sqshl";
4335         break;
4336       case NEON_URSHL_scalar:
4337         mnemonic = "urshl";
4338         break;
4339       case NEON_SRSHL_scalar:
4340         mnemonic = "srshl";
4341         break;
4342       case NEON_UQRSHL_scalar:
4343         mnemonic = "uqrshl";
4344         break;
4345       case NEON_SQRSHL_scalar:
4346         mnemonic = "sqrshl";
4347         break;
4348       case NEON_SQDMULH_scalar:
4349         mnemonic = "sqdmulh";
4350         break;
4351       case NEON_SQRDMULH_scalar:
4352         mnemonic = "sqrdmulh";
4353         break;
4354       default:
4355         form = "(NEONScalar3Same)";
4356     }
4357   }
4358   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
4359 }
4360 
VisitNEONScalar3SameFP16(const Instruction * instr)4361 void Disassembler::VisitNEONScalar3SameFP16(const Instruction *instr) {
4362   const char *mnemonic = NULL;
4363   const char *form = "'Hd, 'Hn, 'Hm";
4364 
4365   switch (instr->Mask(NEONScalar3SameFP16Mask)) {
4366     case NEON_FABD_H_scalar:
4367       mnemonic = "fabd";
4368       break;
4369     case NEON_FMULX_H_scalar:
4370       mnemonic = "fmulx";
4371       break;
4372     case NEON_FCMEQ_H_scalar:
4373       mnemonic = "fcmeq";
4374       break;
4375     case NEON_FCMGE_H_scalar:
4376       mnemonic = "fcmge";
4377       break;
4378     case NEON_FCMGT_H_scalar:
4379       mnemonic = "fcmgt";
4380       break;
4381     case NEON_FACGE_H_scalar:
4382       mnemonic = "facge";
4383       break;
4384     case NEON_FACGT_H_scalar:
4385       mnemonic = "facgt";
4386       break;
4387     case NEON_FRECPS_H_scalar:
4388       mnemonic = "frecps";
4389       break;
4390     case NEON_FRSQRTS_H_scalar:
4391       mnemonic = "frsqrts";
4392       break;
4393     default:
4394       VIXL_UNREACHABLE();
4395   }
4396   Format(instr, mnemonic, form);
4397 }
4398 
VisitNEONScalar3SameExtra(const Instruction * instr)4399 void Disassembler::VisitNEONScalar3SameExtra(const Instruction *instr) {
4400   const char *mnemonic = "unimplemented";
4401   const char *form = "%sd, %sn, %sm";
4402   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4403 
4404   switch (instr->Mask(NEONScalar3SameExtraMask)) {
4405     case NEON_SQRDMLAH_scalar:
4406       mnemonic = "sqrdmlah";
4407       break;
4408     case NEON_SQRDMLSH_scalar:
4409       mnemonic = "sqrdmlsh";
4410       break;
4411     default:
4412       form = "(NEONScalar3SameExtra)";
4413   }
4414   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
4415 }
4416 
4417 
VisitNEONScalarByIndexedElement(const Instruction * instr)4418 void Disassembler::VisitNEONScalarByIndexedElement(const Instruction *instr) {
4419   const char *mnemonic = "unimplemented";
4420   const char *form = "%sd, %sn, 'Ve.%s['IVByElemIndex]";
4421   const char *form_half = "'Hd, 'Hn, 'Ve.h['IVByElemIndex]";
4422   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4423   bool long_instr = false;
4424 
4425   switch (instr->Mask(NEONScalarByIndexedElementMask)) {
4426     case NEON_SQDMULL_byelement_scalar:
4427       mnemonic = "sqdmull";
4428       long_instr = true;
4429       break;
4430     case NEON_SQDMLAL_byelement_scalar:
4431       mnemonic = "sqdmlal";
4432       long_instr = true;
4433       break;
4434     case NEON_SQDMLSL_byelement_scalar:
4435       mnemonic = "sqdmlsl";
4436       long_instr = true;
4437       break;
4438     case NEON_SQDMULH_byelement_scalar:
4439       mnemonic = "sqdmulh";
4440       break;
4441     case NEON_SQRDMULH_byelement_scalar:
4442       mnemonic = "sqrdmulh";
4443       break;
4444     case NEON_SQRDMLAH_byelement_scalar:
4445       mnemonic = "sqrdmlah";
4446       break;
4447     case NEON_SQRDMLSH_byelement_scalar:
4448       mnemonic = "sqrdmlsh";
4449       break;
4450     default:
4451       nfd.SetFormatMap(0, nfd.FPScalarFormatMap());
4452       switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
4453         case NEON_FMUL_byelement_scalar:
4454           mnemonic = "fmul";
4455           break;
4456         case NEON_FMLA_byelement_scalar:
4457           mnemonic = "fmla";
4458           break;
4459         case NEON_FMLS_byelement_scalar:
4460           mnemonic = "fmls";
4461           break;
4462         case NEON_FMULX_byelement_scalar:
4463           mnemonic = "fmulx";
4464           break;
4465         case NEON_FMLA_H_byelement_scalar:
4466           mnemonic = "fmla";
4467           form = form_half;
4468           break;
4469         case NEON_FMLS_H_byelement_scalar:
4470           mnemonic = "fmls";
4471           form = form_half;
4472           break;
4473         case NEON_FMUL_H_byelement_scalar:
4474           mnemonic = "fmul";
4475           form = form_half;
4476           break;
4477         case NEON_FMULX_H_byelement_scalar:
4478           mnemonic = "fmulx";
4479           form = form_half;
4480           break;
4481         default:
4482           form = "(NEONScalarByIndexedElement)";
4483       }
4484   }
4485 
4486   if (long_instr) {
4487     nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
4488   }
4489 
4490   Format(instr,
4491          mnemonic,
4492          nfd.Substitute(form, nfd.kPlaceholder, nfd.kPlaceholder, nfd.kFormat));
4493 }
4494 
4495 
VisitNEONScalarCopy(const Instruction * instr)4496 void Disassembler::VisitNEONScalarCopy(const Instruction *instr) {
4497   const char *mnemonic = "unimplemented";
4498   const char *form = "(NEONScalarCopy)";
4499 
4500   NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
4501 
4502   if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
4503     mnemonic = "mov";
4504     form = "%sd, 'Vn.%s['IVInsIndex1]";
4505   }
4506 
4507   Format(instr, mnemonic, nfd.Substitute(form, nfd.kPlaceholder, nfd.kFormat));
4508 }
4509 
4510 
VisitNEONScalarPairwise(const Instruction * instr)4511 void Disassembler::VisitNEONScalarPairwise(const Instruction *instr) {
4512   const char *mnemonic = "unimplemented";
4513   const char *form = "%sd, 'Vn.%s";
4514   NEONFormatMap map = {{22}, {NF_2S, NF_2D}};
4515   NEONFormatDecoder nfd(instr,
4516                         NEONFormatDecoder::FPScalarPairwiseFormatMap(),
4517                         &map);
4518 
4519   switch (instr->Mask(NEONScalarPairwiseMask)) {
4520     case NEON_ADDP_scalar:
4521       // All pairwise operations except ADDP use bit U to differentiate FP16
4522       // from FP32/FP64 variations.
4523       nfd.SetFormatMap(0, NEONFormatDecoder::FPScalarFormatMap());
4524       mnemonic = "addp";
4525       break;
4526     case NEON_FADDP_h_scalar:
4527       form = "%sd, 'Vn.2h";
4528       VIXL_FALLTHROUGH();
4529     case NEON_FADDP_scalar:
4530       mnemonic = "faddp";
4531       break;
4532     case NEON_FMAXP_h_scalar:
4533       form = "%sd, 'Vn.2h";
4534       VIXL_FALLTHROUGH();
4535     case NEON_FMAXP_scalar:
4536       mnemonic = "fmaxp";
4537       break;
4538     case NEON_FMAXNMP_h_scalar:
4539       form = "%sd, 'Vn.2h";
4540       VIXL_FALLTHROUGH();
4541     case NEON_FMAXNMP_scalar:
4542       mnemonic = "fmaxnmp";
4543       break;
4544     case NEON_FMINP_h_scalar:
4545       form = "%sd, 'Vn.2h";
4546       VIXL_FALLTHROUGH();
4547     case NEON_FMINP_scalar:
4548       mnemonic = "fminp";
4549       break;
4550     case NEON_FMINNMP_h_scalar:
4551       form = "%sd, 'Vn.2h";
4552       VIXL_FALLTHROUGH();
4553     case NEON_FMINNMP_scalar:
4554       mnemonic = "fminnmp";
4555       break;
4556     default:
4557       form = "(NEONScalarPairwise)";
4558   }
4559   Format(instr,
4560          mnemonic,
4561          nfd.Substitute(form,
4562                         NEONFormatDecoder::kPlaceholder,
4563                         NEONFormatDecoder::kFormat));
4564 }
4565 
4566 
VisitNEONScalarShiftImmediate(const Instruction * instr)4567 void Disassembler::VisitNEONScalarShiftImmediate(const Instruction *instr) {
4568   const char *mnemonic = "unimplemented";
4569   const char *form = "%sd, %sn, 'Is1";
4570   const char *form_2 = "%sd, %sn, 'Is2";
4571 
4572   static const NEONFormatMap map_shift = {{22, 21, 20, 19},
4573                                           {NF_UNDEF,
4574                                            NF_B,
4575                                            NF_H,
4576                                            NF_H,
4577                                            NF_S,
4578                                            NF_S,
4579                                            NF_S,
4580                                            NF_S,
4581                                            NF_D,
4582                                            NF_D,
4583                                            NF_D,
4584                                            NF_D,
4585                                            NF_D,
4586                                            NF_D,
4587                                            NF_D,
4588                                            NF_D}};
4589   static const NEONFormatMap map_shift_narrow =
4590       {{21, 20, 19}, {NF_UNDEF, NF_H, NF_S, NF_S, NF_D, NF_D, NF_D, NF_D}};
4591   NEONFormatDecoder nfd(instr, &map_shift);
4592 
4593   if (instr->GetImmNEONImmh()) {  // immh has to be non-zero.
4594     switch (instr->Mask(NEONScalarShiftImmediateMask)) {
4595       case NEON_FCVTZU_imm_scalar:
4596         mnemonic = "fcvtzu";
4597         break;
4598       case NEON_FCVTZS_imm_scalar:
4599         mnemonic = "fcvtzs";
4600         break;
4601       case NEON_SCVTF_imm_scalar:
4602         mnemonic = "scvtf";
4603         break;
4604       case NEON_UCVTF_imm_scalar:
4605         mnemonic = "ucvtf";
4606         break;
4607       case NEON_SRI_scalar:
4608         mnemonic = "sri";
4609         break;
4610       case NEON_SSHR_scalar:
4611         mnemonic = "sshr";
4612         break;
4613       case NEON_USHR_scalar:
4614         mnemonic = "ushr";
4615         break;
4616       case NEON_SRSHR_scalar:
4617         mnemonic = "srshr";
4618         break;
4619       case NEON_URSHR_scalar:
4620         mnemonic = "urshr";
4621         break;
4622       case NEON_SSRA_scalar:
4623         mnemonic = "ssra";
4624         break;
4625       case NEON_USRA_scalar:
4626         mnemonic = "usra";
4627         break;
4628       case NEON_SRSRA_scalar:
4629         mnemonic = "srsra";
4630         break;
4631       case NEON_URSRA_scalar:
4632         mnemonic = "ursra";
4633         break;
4634       case NEON_SHL_scalar:
4635         mnemonic = "shl";
4636         form = form_2;
4637         break;
4638       case NEON_SLI_scalar:
4639         mnemonic = "sli";
4640         form = form_2;
4641         break;
4642       case NEON_SQSHLU_scalar:
4643         mnemonic = "sqshlu";
4644         form = form_2;
4645         break;
4646       case NEON_SQSHL_imm_scalar:
4647         mnemonic = "sqshl";
4648         form = form_2;
4649         break;
4650       case NEON_UQSHL_imm_scalar:
4651         mnemonic = "uqshl";
4652         form = form_2;
4653         break;
4654       case NEON_UQSHRN_scalar:
4655         mnemonic = "uqshrn";
4656         nfd.SetFormatMap(1, &map_shift_narrow);
4657         break;
4658       case NEON_UQRSHRN_scalar:
4659         mnemonic = "uqrshrn";
4660         nfd.SetFormatMap(1, &map_shift_narrow);
4661         break;
4662       case NEON_SQSHRN_scalar:
4663         mnemonic = "sqshrn";
4664         nfd.SetFormatMap(1, &map_shift_narrow);
4665         break;
4666       case NEON_SQRSHRN_scalar:
4667         mnemonic = "sqrshrn";
4668         nfd.SetFormatMap(1, &map_shift_narrow);
4669         break;
4670       case NEON_SQSHRUN_scalar:
4671         mnemonic = "sqshrun";
4672         nfd.SetFormatMap(1, &map_shift_narrow);
4673         break;
4674       case NEON_SQRSHRUN_scalar:
4675         mnemonic = "sqrshrun";
4676         nfd.SetFormatMap(1, &map_shift_narrow);
4677         break;
4678       default:
4679         form = "(NEONScalarShiftImmediate)";
4680     }
4681   } else {
4682     form = "(NEONScalarShiftImmediate)";
4683   }
4684   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
4685 }
4686 
4687 
VisitNEONShiftImmediate(const Instruction * instr)4688 void Disassembler::VisitNEONShiftImmediate(const Instruction *instr) {
4689   const char *mnemonic = "unimplemented";
4690   const char *form = "'Vd.%s, 'Vn.%s, 'Is1";
4691   const char *form_shift_2 = "'Vd.%s, 'Vn.%s, 'Is2";
4692   const char *form_xtl = "'Vd.%s, 'Vn.%s";
4693 
4694   // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
4695   static const NEONFormatMap map_shift_ta =
4696       {{22, 21, 20, 19},
4697        {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
4698 
4699   // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
4700   // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
4701   static const NEONFormatMap map_shift_tb =
4702       {{22, 21, 20, 19, 30},
4703        {NF_UNDEF, NF_UNDEF, NF_8B,    NF_16B,   NF_4H,    NF_8H,    NF_4H,
4704         NF_8H,    NF_2S,    NF_4S,    NF_2S,    NF_4S,    NF_2S,    NF_4S,
4705         NF_2S,    NF_4S,    NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,    NF_UNDEF,
4706         NF_2D,    NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,
4707         NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D}};
4708 
4709   NEONFormatDecoder nfd(instr, &map_shift_tb);
4710 
4711   if (instr->GetImmNEONImmh()) {  // immh has to be non-zero.
4712     switch (instr->Mask(NEONShiftImmediateMask)) {
4713       case NEON_SQSHLU:
4714         mnemonic = "sqshlu";
4715         form = form_shift_2;
4716         break;
4717       case NEON_SQSHL_imm:
4718         mnemonic = "sqshl";
4719         form = form_shift_2;
4720         break;
4721       case NEON_UQSHL_imm:
4722         mnemonic = "uqshl";
4723         form = form_shift_2;
4724         break;
4725       case NEON_SHL:
4726         mnemonic = "shl";
4727         form = form_shift_2;
4728         break;
4729       case NEON_SLI:
4730         mnemonic = "sli";
4731         form = form_shift_2;
4732         break;
4733       case NEON_SCVTF_imm:
4734         mnemonic = "scvtf";
4735         break;
4736       case NEON_UCVTF_imm:
4737         mnemonic = "ucvtf";
4738         break;
4739       case NEON_FCVTZU_imm:
4740         mnemonic = "fcvtzu";
4741         break;
4742       case NEON_FCVTZS_imm:
4743         mnemonic = "fcvtzs";
4744         break;
4745       case NEON_SRI:
4746         mnemonic = "sri";
4747         break;
4748       case NEON_SSHR:
4749         mnemonic = "sshr";
4750         break;
4751       case NEON_USHR:
4752         mnemonic = "ushr";
4753         break;
4754       case NEON_SRSHR:
4755         mnemonic = "srshr";
4756         break;
4757       case NEON_URSHR:
4758         mnemonic = "urshr";
4759         break;
4760       case NEON_SSRA:
4761         mnemonic = "ssra";
4762         break;
4763       case NEON_USRA:
4764         mnemonic = "usra";
4765         break;
4766       case NEON_SRSRA:
4767         mnemonic = "srsra";
4768         break;
4769       case NEON_URSRA:
4770         mnemonic = "ursra";
4771         break;
4772       case NEON_SHRN:
4773         mnemonic = instr->Mask(NEON_Q) ? "shrn2" : "shrn";
4774         nfd.SetFormatMap(1, &map_shift_ta);
4775         break;
4776       case NEON_RSHRN:
4777         mnemonic = instr->Mask(NEON_Q) ? "rshrn2" : "rshrn";
4778         nfd.SetFormatMap(1, &map_shift_ta);
4779         break;
4780       case NEON_UQSHRN:
4781         mnemonic = instr->Mask(NEON_Q) ? "uqshrn2" : "uqshrn";
4782         nfd.SetFormatMap(1, &map_shift_ta);
4783         break;
4784       case NEON_UQRSHRN:
4785         mnemonic = instr->Mask(NEON_Q) ? "uqrshrn2" : "uqrshrn";
4786         nfd.SetFormatMap(1, &map_shift_ta);
4787         break;
4788       case NEON_SQSHRN:
4789         mnemonic = instr->Mask(NEON_Q) ? "sqshrn2" : "sqshrn";
4790         nfd.SetFormatMap(1, &map_shift_ta);
4791         break;
4792       case NEON_SQRSHRN:
4793         mnemonic = instr->Mask(NEON_Q) ? "sqrshrn2" : "sqrshrn";
4794         nfd.SetFormatMap(1, &map_shift_ta);
4795         break;
4796       case NEON_SQSHRUN:
4797         mnemonic = instr->Mask(NEON_Q) ? "sqshrun2" : "sqshrun";
4798         nfd.SetFormatMap(1, &map_shift_ta);
4799         break;
4800       case NEON_SQRSHRUN:
4801         mnemonic = instr->Mask(NEON_Q) ? "sqrshrun2" : "sqrshrun";
4802         nfd.SetFormatMap(1, &map_shift_ta);
4803         break;
4804       case NEON_SSHLL:
4805         nfd.SetFormatMap(0, &map_shift_ta);
4806         if (instr->GetImmNEONImmb() == 0 &&
4807             CountSetBits(instr->GetImmNEONImmh(), 32) == 1) {  // sxtl variant.
4808           form = form_xtl;
4809           mnemonic = instr->Mask(NEON_Q) ? "sxtl2" : "sxtl";
4810         } else {  // sshll variant.
4811           form = form_shift_2;
4812           mnemonic = instr->Mask(NEON_Q) ? "sshll2" : "sshll";
4813         }
4814         break;
4815       case NEON_USHLL:
4816         nfd.SetFormatMap(0, &map_shift_ta);
4817         if (instr->GetImmNEONImmb() == 0 &&
4818             CountSetBits(instr->GetImmNEONImmh(), 32) == 1) {  // uxtl variant.
4819           form = form_xtl;
4820           mnemonic = instr->Mask(NEON_Q) ? "uxtl2" : "uxtl";
4821         } else {  // ushll variant.
4822           form = form_shift_2;
4823           mnemonic = instr->Mask(NEON_Q) ? "ushll2" : "ushll";
4824         }
4825         break;
4826       default:
4827         form = "(NEONShiftImmediate)";
4828     }
4829   } else {
4830     form = "(NEONShiftImmediate)";
4831   }
4832   Format(instr, mnemonic, nfd.Substitute(form));
4833 }
4834 
4835 
VisitNEONTable(const Instruction * instr)4836 void Disassembler::VisitNEONTable(const Instruction *instr) {
4837   const char *mnemonic = "unimplemented";
4838   const char *form = "(NEONTable)";
4839   const char form_1v[] = "'Vd.%%s, {'Vn.16b}, 'Vm.%%s";
4840   const char form_2v[] = "'Vd.%%s, {'Vn.16b, v%d.16b}, 'Vm.%%s";
4841   const char form_3v[] = "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b}, 'Vm.%%s";
4842   const char form_4v[] =
4843       "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b, v%d.16b}, 'Vm.%%s";
4844   static const NEONFormatMap map_b = {{30}, {NF_8B, NF_16B}};
4845   NEONFormatDecoder nfd(instr, &map_b);
4846 
4847   switch (instr->Mask(NEONTableMask)) {
4848     case NEON_TBL_1v:
4849       mnemonic = "tbl";
4850       form = form_1v;
4851       break;
4852     case NEON_TBL_2v:
4853       mnemonic = "tbl";
4854       form = form_2v;
4855       break;
4856     case NEON_TBL_3v:
4857       mnemonic = "tbl";
4858       form = form_3v;
4859       break;
4860     case NEON_TBL_4v:
4861       mnemonic = "tbl";
4862       form = form_4v;
4863       break;
4864     case NEON_TBX_1v:
4865       mnemonic = "tbx";
4866       form = form_1v;
4867       break;
4868     case NEON_TBX_2v:
4869       mnemonic = "tbx";
4870       form = form_2v;
4871       break;
4872     case NEON_TBX_3v:
4873       mnemonic = "tbx";
4874       form = form_3v;
4875       break;
4876     case NEON_TBX_4v:
4877       mnemonic = "tbx";
4878       form = form_4v;
4879       break;
4880     default:
4881       break;
4882   }
4883 
4884   char re_form[sizeof(form_4v) + 6];
4885   int reg_num = instr->GetRn();
4886   snprintf(re_form,
4887            sizeof(re_form),
4888            form,
4889            (reg_num + 1) % kNumberOfVRegisters,
4890            (reg_num + 2) % kNumberOfVRegisters,
4891            (reg_num + 3) % kNumberOfVRegisters);
4892 
4893   Format(instr, mnemonic, nfd.Substitute(re_form));
4894 }
4895 
4896 
VisitNEONPerm(const Instruction * instr)4897 void Disassembler::VisitNEONPerm(const Instruction *instr) {
4898   const char *mnemonic = "unimplemented";
4899   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
4900   NEONFormatDecoder nfd(instr);
4901 
4902   switch (instr->Mask(NEONPermMask)) {
4903     case NEON_TRN1:
4904       mnemonic = "trn1";
4905       break;
4906     case NEON_TRN2:
4907       mnemonic = "trn2";
4908       break;
4909     case NEON_UZP1:
4910       mnemonic = "uzp1";
4911       break;
4912     case NEON_UZP2:
4913       mnemonic = "uzp2";
4914       break;
4915     case NEON_ZIP1:
4916       mnemonic = "zip1";
4917       break;
4918     case NEON_ZIP2:
4919       mnemonic = "zip2";
4920       break;
4921     default:
4922       form = "(NEONPerm)";
4923   }
4924   Format(instr, mnemonic, nfd.Substitute(form));
4925 }
4926 
4927 void Disassembler::
VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(const Instruction * instr)4928     VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
4929         const Instruction *instr) {
4930   const char *mnemonic = "unimplemented";
4931   const char *form = "{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw #1]";
4932 
4933   switch (instr->Mask(
4934       SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
4935     case LD1H_z_p_bz_s_x32_scaled:
4936       mnemonic = "ld1h";
4937       break;
4938     case LD1SH_z_p_bz_s_x32_scaled:
4939       mnemonic = "ld1sh";
4940       break;
4941     case LDFF1H_z_p_bz_s_x32_scaled:
4942       mnemonic = "ldff1h";
4943       break;
4944     case LDFF1SH_z_p_bz_s_x32_scaled:
4945       mnemonic = "ldff1sh";
4946       break;
4947     default:
4948       form = "(SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets)";
4949       break;
4950   }
4951   Format(instr, mnemonic, form);
4952 }
4953 
VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(const Instruction * instr)4954 void Disassembler::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
4955     const Instruction *instr) {
4956   const char *mnemonic = "unimplemented";
4957   const char *form = "{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw #2]";
4958 
4959   switch (
4960       instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
4961     case LD1W_z_p_bz_s_x32_scaled:
4962       mnemonic = "ld1w";
4963       break;
4964     case LDFF1W_z_p_bz_s_x32_scaled:
4965       mnemonic = "ldff1w";
4966       break;
4967     default:
4968       form = "(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets)";
4969       break;
4970   }
4971   Format(instr, mnemonic, form);
4972 }
4973 
VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(const Instruction * instr)4974 void Disassembler::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
4975     const Instruction *instr) {
4976   const char *form = "{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw]";
4977 
4978   const char *mnemonic = "unimplemented";
4979   switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
4980     case LD1B_z_p_bz_s_x32_unscaled:
4981       mnemonic = "ld1b";
4982       break;
4983     case LD1H_z_p_bz_s_x32_unscaled:
4984       mnemonic = "ld1h";
4985       break;
4986     case LD1SB_z_p_bz_s_x32_unscaled:
4987       mnemonic = "ld1sb";
4988       break;
4989     case LD1SH_z_p_bz_s_x32_unscaled:
4990       mnemonic = "ld1sh";
4991       break;
4992     case LD1W_z_p_bz_s_x32_unscaled:
4993       mnemonic = "ld1w";
4994       break;
4995     case LDFF1B_z_p_bz_s_x32_unscaled:
4996       mnemonic = "ldff1b";
4997       break;
4998     case LDFF1H_z_p_bz_s_x32_unscaled:
4999       mnemonic = "ldff1h";
5000       break;
5001     case LDFF1SB_z_p_bz_s_x32_unscaled:
5002       mnemonic = "ldff1sb";
5003       break;
5004     case LDFF1SH_z_p_bz_s_x32_unscaled:
5005       mnemonic = "ldff1sh";
5006       break;
5007     case LDFF1W_z_p_bz_s_x32_unscaled:
5008       mnemonic = "ldff1w";
5009       break;
5010     default:
5011       form = "(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets)";
5012       break;
5013   }
5014   Format(instr, mnemonic, form);
5015 }
5016 
VisitSVE32BitGatherLoad_VectorPlusImm(const Instruction * instr)5017 void Disassembler::VisitSVE32BitGatherLoad_VectorPlusImm(
5018     const Instruction *instr) {
5019   const char *form = "{'Zt.s}, 'Pgl/z, ['Zn.s]";
5020   const char *form_imm_b = "{'Zt.s}, 'Pgl/z, ['Zn.s, #'u2016]";
5021   const char *form_imm_h = "{'Zt.s}, 'Pgl/z, ['Zn.s, #'u2016*2]";
5022   const char *form_imm_w = "{'Zt.s}, 'Pgl/z, ['Zn.s, #'u2016*4]";
5023   const char *form_imm;
5024 
5025   const char *mnemonic = "unimplemented";
5026   switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
5027     case LD1B_z_p_ai_s:
5028       mnemonic = "ld1b";
5029       form_imm = form_imm_b;
5030       break;
5031     case LD1H_z_p_ai_s:
5032       mnemonic = "ld1h";
5033       form_imm = form_imm_h;
5034       break;
5035     case LD1SB_z_p_ai_s:
5036       mnemonic = "ld1sb";
5037       form_imm = form_imm_b;
5038       break;
5039     case LD1SH_z_p_ai_s:
5040       mnemonic = "ld1sh";
5041       form_imm = form_imm_h;
5042       break;
5043     case LD1W_z_p_ai_s:
5044       mnemonic = "ld1w";
5045       form_imm = form_imm_w;
5046       break;
5047     case LDFF1B_z_p_ai_s:
5048       mnemonic = "ldff1b";
5049       form_imm = form_imm_b;
5050       break;
5051     case LDFF1H_z_p_ai_s:
5052       mnemonic = "ldff1h";
5053       form_imm = form_imm_h;
5054       break;
5055     case LDFF1SB_z_p_ai_s:
5056       mnemonic = "ldff1sb";
5057       form_imm = form_imm_b;
5058       break;
5059     case LDFF1SH_z_p_ai_s:
5060       mnemonic = "ldff1sh";
5061       form_imm = form_imm_h;
5062       break;
5063     case LDFF1W_z_p_ai_s:
5064       mnemonic = "ldff1w";
5065       form_imm = form_imm_w;
5066       break;
5067     default:
5068       form = "(SVE32BitGatherLoad_VectorPlusImm)";
5069       form_imm = form;
5070       break;
5071   }
5072   if (instr->ExtractBits(20, 16) != 0) form = form_imm;
5073 
5074   Format(instr, mnemonic, form);
5075 }
5076 
VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(const Instruction * instr)5077 void Disassembler::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
5078     const Instruction *instr) {
5079   const char *mnemonic = "unimplemented";
5080   const char *form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.s, '?22:suxtw";
5081   const char *suffix = NULL;
5082 
5083   switch (
5084       instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
5085     case PRFB_i_p_bz_s_x32_scaled:
5086       mnemonic = "prfb";
5087       suffix = "]";
5088       break;
5089     case PRFD_i_p_bz_s_x32_scaled:
5090       mnemonic = "prfd";
5091       suffix = " #3]";
5092       break;
5093     case PRFH_i_p_bz_s_x32_scaled:
5094       mnemonic = "prfh";
5095       suffix = " #1]";
5096       break;
5097     case PRFW_i_p_bz_s_x32_scaled:
5098       mnemonic = "prfw";
5099       suffix = " #2]";
5100       break;
5101     default:
5102       form = "(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets)";
5103       break;
5104   }
5105   Format(instr, mnemonic, form, suffix);
5106 }
5107 
VisitSVE32BitGatherPrefetch_VectorPlusImm(const Instruction * instr)5108 void Disassembler::VisitSVE32BitGatherPrefetch_VectorPlusImm(
5109     const Instruction *instr) {
5110   const char *mnemonic = "unimplemented";
5111   const char *form = (instr->ExtractBits(20, 16) != 0)
5112                          ? "'prefSVEOp, 'Pgl, ['Zn.s, #'u2016]"
5113                          : "'prefSVEOp, 'Pgl, ['Zn.s]";
5114 
5115   switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
5116     case PRFB_i_p_ai_s:
5117       mnemonic = "prfb";
5118       break;
5119     case PRFD_i_p_ai_s:
5120       mnemonic = "prfd";
5121       break;
5122     case PRFH_i_p_ai_s:
5123       mnemonic = "prfh";
5124       break;
5125     case PRFW_i_p_ai_s:
5126       mnemonic = "prfw";
5127       break;
5128     default:
5129       break;
5130   }
5131   Format(instr, mnemonic, form);
5132 }
5133 
VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(const Instruction * instr)5134 void Disassembler::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
5135     const Instruction *instr) {
5136   const char *mnemonic = "unimplemented";
5137   const char *form = "{'Zt.s}, 'Pgl, ['Xns, 'Zm.s, '?14:suxtw #'u2423]";
5138 
5139   switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
5140     case ST1H_z_p_bz_s_x32_scaled:
5141       mnemonic = "st1h";
5142       break;
5143     case ST1W_z_p_bz_s_x32_scaled:
5144       mnemonic = "st1w";
5145       break;
5146     default:
5147       form = "(SVE32BitScatterStore_ScalarPlus32BitScaledOffsets)";
5148       break;
5149   }
5150   Format(instr, mnemonic, form);
5151 }
5152 
VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(const Instruction * instr)5153 void Disassembler::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
5154     const Instruction *instr) {
5155   const char *mnemonic = "unimplemented";
5156   const char *form = "{'Zt.s}, 'Pgl, ['Xns, 'Zm.s, '?14:suxtw]";
5157 
5158   switch (
5159       instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
5160     case ST1B_z_p_bz_s_x32_unscaled:
5161       mnemonic = "st1b";
5162       break;
5163     case ST1H_z_p_bz_s_x32_unscaled:
5164       mnemonic = "st1h";
5165       break;
5166     case ST1W_z_p_bz_s_x32_unscaled:
5167       mnemonic = "st1w";
5168       break;
5169     default:
5170       form = "(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets)";
5171       break;
5172   }
5173   Format(instr, mnemonic, form);
5174 }
5175 
VisitSVE32BitScatterStore_VectorPlusImm(const Instruction * instr)5176 void Disassembler::VisitSVE32BitScatterStore_VectorPlusImm(
5177     const Instruction *instr) {
5178   const char *mnemonic = "unimplemented";
5179   const char *form = "{'Zt.s}, 'Pgl, ['Zn.s";
5180   const char *suffix = NULL;
5181 
5182   bool is_zero = instr->ExtractBits(20, 16) == 0;
5183 
5184   switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
5185     case ST1B_z_p_ai_s:
5186       mnemonic = "st1b";
5187       suffix = is_zero ? "]" : ", #'u2016]";
5188       break;
5189     case ST1H_z_p_ai_s:
5190       mnemonic = "st1h";
5191       suffix = is_zero ? "]" : ", #'u2016*2]";
5192       break;
5193     case ST1W_z_p_ai_s:
5194       mnemonic = "st1w";
5195       suffix = is_zero ? "]" : ", #'u2016*4]";
5196       break;
5197     default:
5198       form = "(SVE32BitScatterStore_VectorPlusImm)";
5199       break;
5200   }
5201   Format(instr, mnemonic, form, suffix);
5202 }
5203 
VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(const Instruction * instr)5204 void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
5205     const Instruction *instr) {
5206   const char *mnemonic = "unimplemented";
5207   const char *form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, '?22:suxtw #'u2423]";
5208 
5209   switch (instr->Mask(
5210       SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
5211     case LD1D_z_p_bz_d_x32_scaled:
5212       mnemonic = "ld1d";
5213       break;
5214     case LD1H_z_p_bz_d_x32_scaled:
5215       mnemonic = "ld1h";
5216       break;
5217     case LD1SH_z_p_bz_d_x32_scaled:
5218       mnemonic = "ld1sh";
5219       break;
5220     case LD1SW_z_p_bz_d_x32_scaled:
5221       mnemonic = "ld1sw";
5222       break;
5223     case LD1W_z_p_bz_d_x32_scaled:
5224       mnemonic = "ld1w";
5225       break;
5226     case LDFF1D_z_p_bz_d_x32_scaled:
5227       mnemonic = "ldff1d";
5228       break;
5229     case LDFF1H_z_p_bz_d_x32_scaled:
5230       mnemonic = "ldff1h";
5231       break;
5232     case LDFF1SH_z_p_bz_d_x32_scaled:
5233       mnemonic = "ldff1sh";
5234       break;
5235     case LDFF1SW_z_p_bz_d_x32_scaled:
5236       mnemonic = "ldff1sw";
5237       break;
5238     case LDFF1W_z_p_bz_d_x32_scaled:
5239       mnemonic = "ldff1w";
5240       break;
5241     default:
5242       form = "(SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)";
5243       break;
5244   }
5245   Format(instr, mnemonic, form);
5246 }
5247 
VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(const Instruction * instr)5248 void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
5249     const Instruction *instr) {
5250   const char *mnemonic = "unimplemented";
5251   const char *form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, lsl #'u2423]";
5252 
5253   switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
5254     case LD1D_z_p_bz_d_64_scaled:
5255       mnemonic = "ld1d";
5256       break;
5257     case LD1H_z_p_bz_d_64_scaled:
5258       mnemonic = "ld1h";
5259       break;
5260     case LD1SH_z_p_bz_d_64_scaled:
5261       mnemonic = "ld1sh";
5262       break;
5263     case LD1SW_z_p_bz_d_64_scaled:
5264       mnemonic = "ld1sw";
5265       break;
5266     case LD1W_z_p_bz_d_64_scaled:
5267       mnemonic = "ld1w";
5268       break;
5269     case LDFF1D_z_p_bz_d_64_scaled:
5270       mnemonic = "ldff1d";
5271       break;
5272     case LDFF1H_z_p_bz_d_64_scaled:
5273       mnemonic = "ldff1h";
5274       break;
5275     case LDFF1SH_z_p_bz_d_64_scaled:
5276       mnemonic = "ldff1sh";
5277       break;
5278     case LDFF1SW_z_p_bz_d_64_scaled:
5279       mnemonic = "ldff1sw";
5280       break;
5281     case LDFF1W_z_p_bz_d_64_scaled:
5282       mnemonic = "ldff1w";
5283       break;
5284     default:
5285       form = "(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)";
5286       break;
5287   }
5288   Format(instr, mnemonic, form);
5289 }
5290 
VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(const Instruction * instr)5291 void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
5292     const Instruction *instr) {
5293   const char *mnemonic = "unimplemented";
5294   const char *form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d]";
5295 
5296   switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
5297     case LD1B_z_p_bz_d_64_unscaled:
5298       mnemonic = "ld1b";
5299       break;
5300     case LD1D_z_p_bz_d_64_unscaled:
5301       mnemonic = "ld1d";
5302       break;
5303     case LD1H_z_p_bz_d_64_unscaled:
5304       mnemonic = "ld1h";
5305       break;
5306     case LD1SB_z_p_bz_d_64_unscaled:
5307       mnemonic = "ld1sb";
5308       break;
5309     case LD1SH_z_p_bz_d_64_unscaled:
5310       mnemonic = "ld1sh";
5311       break;
5312     case LD1SW_z_p_bz_d_64_unscaled:
5313       mnemonic = "ld1sw";
5314       break;
5315     case LD1W_z_p_bz_d_64_unscaled:
5316       mnemonic = "ld1w";
5317       break;
5318     case LDFF1B_z_p_bz_d_64_unscaled:
5319       mnemonic = "ldff1b";
5320       break;
5321     case LDFF1D_z_p_bz_d_64_unscaled:
5322       mnemonic = "ldff1d";
5323       break;
5324     case LDFF1H_z_p_bz_d_64_unscaled:
5325       mnemonic = "ldff1h";
5326       break;
5327     case LDFF1SB_z_p_bz_d_64_unscaled:
5328       mnemonic = "ldff1sb";
5329       break;
5330     case LDFF1SH_z_p_bz_d_64_unscaled:
5331       mnemonic = "ldff1sh";
5332       break;
5333     case LDFF1SW_z_p_bz_d_64_unscaled:
5334       mnemonic = "ldff1sw";
5335       break;
5336     case LDFF1W_z_p_bz_d_64_unscaled:
5337       mnemonic = "ldff1w";
5338       break;
5339     default:
5340       break;
5341   }
5342   Format(instr, mnemonic, form);
5343 }
5344 
5345 void Disassembler::
VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(const Instruction * instr)5346     VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
5347         const Instruction *instr) {
5348   const char *mnemonic = "unimplemented";
5349   const char *form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, '?22:suxtw]";
5350 
5351   switch (instr->Mask(
5352       SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
5353     case LD1B_z_p_bz_d_x32_unscaled:
5354       mnemonic = "ld1b";
5355       break;
5356     case LD1D_z_p_bz_d_x32_unscaled:
5357       mnemonic = "ld1d";
5358       break;
5359     case LD1H_z_p_bz_d_x32_unscaled:
5360       mnemonic = "ld1h";
5361       break;
5362     case LD1SB_z_p_bz_d_x32_unscaled:
5363       mnemonic = "ld1sb";
5364       break;
5365     case LD1SH_z_p_bz_d_x32_unscaled:
5366       mnemonic = "ld1sh";
5367       break;
5368     case LD1SW_z_p_bz_d_x32_unscaled:
5369       mnemonic = "ld1sw";
5370       break;
5371     case LD1W_z_p_bz_d_x32_unscaled:
5372       mnemonic = "ld1w";
5373       break;
5374     case LDFF1B_z_p_bz_d_x32_unscaled:
5375       mnemonic = "ldff1b";
5376       break;
5377     case LDFF1D_z_p_bz_d_x32_unscaled:
5378       mnemonic = "ldff1d";
5379       break;
5380     case LDFF1H_z_p_bz_d_x32_unscaled:
5381       mnemonic = "ldff1h";
5382       break;
5383     case LDFF1SB_z_p_bz_d_x32_unscaled:
5384       mnemonic = "ldff1sb";
5385       break;
5386     case LDFF1SH_z_p_bz_d_x32_unscaled:
5387       mnemonic = "ldff1sh";
5388       break;
5389     case LDFF1SW_z_p_bz_d_x32_unscaled:
5390       mnemonic = "ldff1sw";
5391       break;
5392     case LDFF1W_z_p_bz_d_x32_unscaled:
5393       mnemonic = "ldff1w";
5394       break;
5395     default:
5396       form = "(SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)";
5397       break;
5398   }
5399   Format(instr, mnemonic, form);
5400 }
5401 
VisitSVE64BitGatherLoad_VectorPlusImm(const Instruction * instr)5402 void Disassembler::VisitSVE64BitGatherLoad_VectorPlusImm(
5403     const Instruction *instr) {
5404   const char *form = "{'Zt.d}, 'Pgl/z, ['Zn.d]";
5405   const char *form_imm[4] = {"{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016]",
5406                              "{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016*2]",
5407                              "{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016*4]",
5408                              "{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016*8]"};
5409 
5410   if (instr->ExtractBits(20, 16) != 0) {
5411     unsigned msz = instr->ExtractBits(24, 23);
5412     bool sign_extend = instr->ExtractBit(14) == 0;
5413     if ((msz == kDRegSizeInBytesLog2) && sign_extend) {
5414       form = "(SVE64BitGatherLoad_VectorPlusImm)";
5415     } else {
5416       VIXL_ASSERT(msz < ArrayLength(form_imm));
5417       form = form_imm[msz];
5418     }
5419   }
5420 
5421   const char *mnemonic = "unimplemented";
5422   switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
5423     case LD1B_z_p_ai_d:
5424       mnemonic = "ld1b";
5425       break;
5426     case LD1D_z_p_ai_d:
5427       mnemonic = "ld1d";
5428       break;
5429     case LD1H_z_p_ai_d:
5430       mnemonic = "ld1h";
5431       break;
5432     case LD1SB_z_p_ai_d:
5433       mnemonic = "ld1sb";
5434       break;
5435     case LD1SH_z_p_ai_d:
5436       mnemonic = "ld1sh";
5437       break;
5438     case LD1SW_z_p_ai_d:
5439       mnemonic = "ld1sw";
5440       break;
5441     case LD1W_z_p_ai_d:
5442       mnemonic = "ld1w";
5443       break;
5444     case LDFF1B_z_p_ai_d:
5445       mnemonic = "ldff1b";
5446       break;
5447     case LDFF1D_z_p_ai_d:
5448       mnemonic = "ldff1d";
5449       break;
5450     case LDFF1H_z_p_ai_d:
5451       mnemonic = "ldff1h";
5452       break;
5453     case LDFF1SB_z_p_ai_d:
5454       mnemonic = "ldff1sb";
5455       break;
5456     case LDFF1SH_z_p_ai_d:
5457       mnemonic = "ldff1sh";
5458       break;
5459     case LDFF1SW_z_p_ai_d:
5460       mnemonic = "ldff1sw";
5461       break;
5462     case LDFF1W_z_p_ai_d:
5463       mnemonic = "ldff1w";
5464       break;
5465     default:
5466       break;
5467   }
5468   Format(instr, mnemonic, form);
5469 }
5470 
VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(const Instruction * instr)5471 void Disassembler::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
5472     const Instruction *instr) {
5473   const char *mnemonic = "unimplemented";
5474   const char *form = "(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets)";
5475 
5476   switch (
5477       instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
5478     case PRFB_i_p_bz_d_64_scaled:
5479       mnemonic = "prfb";
5480       form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d]";
5481       break;
5482     case PRFD_i_p_bz_d_64_scaled:
5483       mnemonic = "prfd";
5484       form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, lsl #3]";
5485       break;
5486     case PRFH_i_p_bz_d_64_scaled:
5487       mnemonic = "prfh";
5488       form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, lsl #1]";
5489       break;
5490     case PRFW_i_p_bz_d_64_scaled:
5491       mnemonic = "prfw";
5492       form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, lsl #2]";
5493       break;
5494     default:
5495       break;
5496   }
5497   Format(instr, mnemonic, form);
5498 }
5499 
5500 void Disassembler::
VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(const Instruction * instr)5501     VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
5502         const Instruction *instr) {
5503   const char *mnemonic = "unimplemented";
5504   const char *form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, '?22:suxtw";
5505   const char *suffix = NULL;
5506 
5507   switch (instr->Mask(
5508       SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
5509     case PRFB_i_p_bz_d_x32_scaled:
5510       mnemonic = "prfb";
5511       suffix = " ]";
5512       break;
5513     case PRFD_i_p_bz_d_x32_scaled:
5514       mnemonic = "prfd";
5515       suffix = " #3]";
5516       break;
5517     case PRFH_i_p_bz_d_x32_scaled:
5518       mnemonic = "prfh";
5519       suffix = " #1]";
5520       break;
5521     case PRFW_i_p_bz_d_x32_scaled:
5522       mnemonic = "prfw";
5523       suffix = " #2]";
5524       break;
5525     default:
5526       form = "(SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets)";
5527       break;
5528   }
5529   Format(instr, mnemonic, form, suffix);
5530 }
5531 
VisitSVE64BitGatherPrefetch_VectorPlusImm(const Instruction * instr)5532 void Disassembler::VisitSVE64BitGatherPrefetch_VectorPlusImm(
5533     const Instruction *instr) {
5534   const char *mnemonic = "unimplemented";
5535   const char *form = (instr->ExtractBits(20, 16) != 0)
5536                          ? "'prefSVEOp, 'Pgl, ['Zn.d, #'u2016]"
5537                          : "'prefSVEOp, 'Pgl, ['Zn.d]";
5538 
5539   switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
5540     case PRFB_i_p_ai_d:
5541       mnemonic = "prfb";
5542       break;
5543     case PRFD_i_p_ai_d:
5544       mnemonic = "prfd";
5545       break;
5546     case PRFH_i_p_ai_d:
5547       mnemonic = "prfh";
5548       break;
5549     case PRFW_i_p_ai_d:
5550       mnemonic = "prfw";
5551       break;
5552     default:
5553       break;
5554   }
5555   Format(instr, mnemonic, form);
5556 }
5557 
VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(const Instruction * instr)5558 void Disassembler::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
5559     const Instruction *instr) {
5560   const char *mnemonic = "unimplemented";
5561   const char *form = "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, lsl #'u2423]";
5562 
5563   switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
5564     case ST1D_z_p_bz_d_64_scaled:
5565       mnemonic = "st1d";
5566       break;
5567     case ST1H_z_p_bz_d_64_scaled:
5568       mnemonic = "st1h";
5569       break;
5570     case ST1W_z_p_bz_d_64_scaled:
5571       mnemonic = "st1w";
5572       break;
5573     default:
5574       form = "(SVE64BitScatterStore_ScalarPlus64BitScaledOffsets)";
5575       break;
5576   }
5577   Format(instr, mnemonic, form);
5578 }
5579 
VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(const Instruction * instr)5580 void Disassembler::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
5581     const Instruction *instr) {
5582   const char *mnemonic = "unimplemented";
5583   const char *form = "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d]";
5584 
5585   switch (
5586       instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
5587     case ST1B_z_p_bz_d_64_unscaled:
5588       mnemonic = "st1b";
5589       break;
5590     case ST1D_z_p_bz_d_64_unscaled:
5591       mnemonic = "st1d";
5592       break;
5593     case ST1H_z_p_bz_d_64_unscaled:
5594       mnemonic = "st1h";
5595       break;
5596     case ST1W_z_p_bz_d_64_unscaled:
5597       mnemonic = "st1w";
5598       break;
5599     default:
5600       form = "(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffset)";
5601       break;
5602   }
5603   Format(instr, mnemonic, form);
5604 }
5605 
5606 void Disassembler::
VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(const Instruction * instr)5607     VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
5608         const Instruction *instr) {
5609   const char *mnemonic = "unimplemented";
5610   const char *form = "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, '?14:suxtw #'u2423]";
5611 
5612   switch (instr->Mask(
5613       SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
5614     case ST1D_z_p_bz_d_x32_scaled:
5615       mnemonic = "st1d";
5616       break;
5617     case ST1H_z_p_bz_d_x32_scaled:
5618       mnemonic = "st1h";
5619       break;
5620     case ST1W_z_p_bz_d_x32_scaled:
5621       mnemonic = "st1w";
5622       break;
5623     default:
5624       form = "(SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets)";
5625       break;
5626   }
5627   Format(instr, mnemonic, form);
5628 }
5629 
5630 void Disassembler::
VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(const Instruction * instr)5631     VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
5632         const Instruction *instr) {
5633   const char *mnemonic = "unimplemented";
5634   const char *form = "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, '?14:suxtw]";
5635 
5636   switch (instr->Mask(
5637       SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
5638     case ST1B_z_p_bz_d_x32_unscaled:
5639       mnemonic = "st1b";
5640       break;
5641     case ST1D_z_p_bz_d_x32_unscaled:
5642       mnemonic = "st1d";
5643       break;
5644     case ST1H_z_p_bz_d_x32_unscaled:
5645       mnemonic = "st1h";
5646       break;
5647     case ST1W_z_p_bz_d_x32_unscaled:
5648       mnemonic = "st1w";
5649       break;
5650     default:
5651       form = "(SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets)";
5652       break;
5653   }
5654   Format(instr, mnemonic, form);
5655 }
5656 
VisitSVE64BitScatterStore_VectorPlusImm(const Instruction * instr)5657 void Disassembler::VisitSVE64BitScatterStore_VectorPlusImm(
5658     const Instruction *instr) {
5659   const char *mnemonic = "unimplemented";
5660   const char *form = "{'Zt.d}, 'Pgl, ['Zn.d";
5661   const char *suffix = NULL;
5662 
5663   bool is_zero = instr->ExtractBits(20, 16) == 0;
5664 
5665   switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
5666     case ST1B_z_p_ai_d:
5667       mnemonic = "st1b";
5668       suffix = is_zero ? "]" : ", #'u2016]";
5669       break;
5670     case ST1D_z_p_ai_d:
5671       mnemonic = "st1d";
5672       suffix = is_zero ? "]" : ", #'u2016*8]";
5673       break;
5674     case ST1H_z_p_ai_d:
5675       mnemonic = "st1h";
5676       suffix = is_zero ? "]" : ", #'u2016*2]";
5677       break;
5678     case ST1W_z_p_ai_d:
5679       mnemonic = "st1w";
5680       suffix = is_zero ? "]" : ", #'u2016*4]";
5681       break;
5682     default:
5683       form = "(SVE64BitScatterStore_VectorPlusImm)";
5684       break;
5685   }
5686   Format(instr, mnemonic, form, suffix);
5687 }
5688 
VisitSVEBitwiseLogicalWithImm_Unpredicated(const Instruction * instr)5689 void Disassembler::VisitSVEBitwiseLogicalWithImm_Unpredicated(
5690     const Instruction *instr) {
5691   const char *mnemonic = "unimplemented";
5692   const char *form = "'Zd.'tl, 'Zd.'tl, 'ITriSvel";
5693 
5694   if (instr->GetSVEImmLogical() == 0) {
5695     // The immediate encoded in the instruction is not in the expected format.
5696     Format(instr, "unallocated", "(SVEBitwiseImm)");
5697     return;
5698   }
5699 
5700   switch (instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask)) {
5701     case AND_z_zi:
5702       mnemonic = "and";
5703       break;
5704     case EOR_z_zi:
5705       mnemonic = "eor";
5706       break;
5707     case ORR_z_zi:
5708       mnemonic = "orr";
5709       break;
5710     default:
5711       break;
5712   }
5713   Format(instr, mnemonic, form);
5714 }
5715 
VisitSVEBitwiseLogical_Predicated(const Instruction * instr)5716 void Disassembler::VisitSVEBitwiseLogical_Predicated(const Instruction *instr) {
5717   const char *mnemonic = "unimplemented";
5718   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
5719 
5720   switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
5721     case AND_z_p_zz:
5722       mnemonic = "and";
5723       break;
5724     case BIC_z_p_zz:
5725       mnemonic = "bic";
5726       break;
5727     case EOR_z_p_zz:
5728       mnemonic = "eor";
5729       break;
5730     case ORR_z_p_zz:
5731       mnemonic = "orr";
5732       break;
5733     default:
5734       break;
5735   }
5736   Format(instr, mnemonic, form);
5737 }
5738 
VisitSVEBitwiseShiftByImm_Predicated(const Instruction * instr)5739 void Disassembler::VisitSVEBitwiseShiftByImm_Predicated(
5740     const Instruction *instr) {
5741   const char *mnemonic = "unimplemented";
5742   const char *form = "'Zd.'tszp, 'Pgl/m, 'Zd.'tszp, 'ITriSveq";
5743   unsigned tsize = (instr->ExtractBits(23, 22) << 2) | instr->ExtractBits(9, 8);
5744 
5745   if (tsize == 0) {
5746     form = "(SVEBitwiseShiftByImm_Predicated)";
5747   } else {
5748     switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) {
5749       case ASRD_z_p_zi:
5750         mnemonic = "asrd";
5751         break;
5752       case ASR_z_p_zi:
5753         mnemonic = "asr";
5754         break;
5755       case LSL_z_p_zi:
5756         mnemonic = "lsl";
5757         form = "'Zd.'tszp, p'u1210/m, 'Zd.'tszp, 'ITriSvep";
5758         break;
5759       case LSR_z_p_zi:
5760         mnemonic = "lsr";
5761         break;
5762       default:
5763         break;
5764     }
5765   }
5766   Format(instr, mnemonic, form);
5767 }
5768 
VisitSVEBitwiseShiftByVector_Predicated(const Instruction * instr)5769 void Disassembler::VisitSVEBitwiseShiftByVector_Predicated(
5770     const Instruction *instr) {
5771   const char *mnemonic = "unimplemented";
5772   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
5773 
5774   switch (instr->Mask(SVEBitwiseShiftByVector_PredicatedMask)) {
5775     case ASRR_z_p_zz:
5776       mnemonic = "asrr";
5777       break;
5778     case ASR_z_p_zz:
5779       mnemonic = "asr";
5780       break;
5781     case LSLR_z_p_zz:
5782       mnemonic = "lslr";
5783       break;
5784     case LSL_z_p_zz:
5785       mnemonic = "lsl";
5786       break;
5787     case LSRR_z_p_zz:
5788       mnemonic = "lsrr";
5789       break;
5790     case LSR_z_p_zz:
5791       mnemonic = "lsr";
5792       break;
5793     default:
5794       form = "(SVEBitwiseShiftByVector_Predicated)";
5795       break;
5796   }
5797   Format(instr, mnemonic, form);
5798 }
5799 
VisitSVEBitwiseShiftByWideElements_Predicated(const Instruction * instr)5800 void Disassembler::VisitSVEBitwiseShiftByWideElements_Predicated(
5801     const Instruction *instr) {
5802   const char *mnemonic = "unimplemented";
5803   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.d";
5804 
5805   if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
5806     form = "(SVEBitwiseShiftByWideElements_Predicated)";
5807   } else {
5808     switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
5809       case ASR_z_p_zw:
5810         mnemonic = "asr";
5811         break;
5812       case LSL_z_p_zw:
5813         mnemonic = "lsl";
5814         break;
5815       case LSR_z_p_zw:
5816         mnemonic = "lsr";
5817         break;
5818       default:
5819         form = "(SVEBitwiseShiftByWideElements_Predicated)";
5820         break;
5821     }
5822   }
5823   Format(instr, mnemonic, form);
5824 }
5825 
SVEMoveMaskPreferred(uint64_t value,int lane_bytes_log2)5826 static bool SVEMoveMaskPreferred(uint64_t value, int lane_bytes_log2) {
5827   VIXL_ASSERT(IsUintN(8 << lane_bytes_log2, value));
5828 
5829   // Duplicate lane-sized value across double word.
5830   switch (lane_bytes_log2) {
5831     case 0:
5832       value *= 0x0101010101010101;
5833       break;
5834     case 1:
5835       value *= 0x0001000100010001;
5836       break;
5837     case 2:
5838       value *= 0x0000000100000001;
5839       break;
5840     case 3:  // Nothing to do
5841       break;
5842     default:
5843       VIXL_UNREACHABLE();
5844   }
5845 
5846   if ((value & 0xff) == 0) {
5847     // Check for 16-bit patterns. Set least-significant 16 bits, to make tests
5848     // easier; we already checked least-significant byte is zero above.
5849     uint64_t generic_value = value | 0xffff;
5850 
5851     // Check 0x00000000_0000pq00 or 0xffffffff_ffffpq00.
5852     if ((generic_value == 0xffff) || (generic_value == UINT64_MAX)) {
5853       return false;
5854     }
5855 
5856     // Check 0x0000pq00_0000pq00 or 0xffffpq00_ffffpq00.
5857     uint64_t rotvalue = RotateRight(value, 32, 64);
5858     if (value == rotvalue) {
5859       generic_value &= 0xffffffff;
5860       if ((generic_value == 0xffff) || (generic_value == UINT32_MAX)) {
5861         return false;
5862       }
5863     }
5864 
5865     // Check 0xpq00pq00_pq00pq00.
5866     rotvalue = RotateRight(value, 16, 64);
5867     if (value == rotvalue) {
5868       return false;
5869     }
5870   } else {
5871     // Check for 8-bit patterns. Set least-significant byte, to make tests
5872     // easier.
5873     uint64_t generic_value = value | 0xff;
5874 
5875     // Check 0x00000000_000000pq or 0xffffffff_ffffffpq.
5876     if ((generic_value == 0xff) || (generic_value == UINT64_MAX)) {
5877       return false;
5878     }
5879 
5880     // Check 0x000000pq_000000pq or 0xffffffpq_ffffffpq.
5881     uint64_t rotvalue = RotateRight(value, 32, 64);
5882     if (value == rotvalue) {
5883       generic_value &= 0xffffffff;
5884       if ((generic_value == 0xff) || (generic_value == UINT32_MAX)) {
5885         return false;
5886       }
5887     }
5888 
5889     // Check 0x00pq00pq_00pq00pq or 0xffpqffpq_ffpqffpq.
5890     rotvalue = RotateRight(value, 16, 64);
5891     if (value == rotvalue) {
5892       generic_value &= 0xffff;
5893       if ((generic_value == 0xff) || (generic_value == UINT16_MAX)) {
5894         return false;
5895       }
5896     }
5897 
5898     // Check 0xpqpqpqpq_pqpqpqpq.
5899     rotvalue = RotateRight(value, 8, 64);
5900     if (value == rotvalue) {
5901       return false;
5902     }
5903   }
5904   return true;
5905 }
5906 
VisitSVEBroadcastBitmaskImm(const Instruction * instr)5907 void Disassembler::VisitSVEBroadcastBitmaskImm(const Instruction *instr) {
5908   const char *mnemonic = "unimplemented";
5909   const char *form = "(SVEBroadcastBitmaskImm)";
5910 
5911   switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
5912     case DUPM_z_i: {
5913       uint64_t imm = instr->GetSVEImmLogical();
5914       if (imm != 0) {
5915         int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
5916         mnemonic = SVEMoveMaskPreferred(imm, lane_size) ? "mov" : "dupm";
5917         form = "'Zd.'tl, 'ITriSvel";
5918       }
5919       break;
5920     }
5921     default:
5922       break;
5923   }
5924   Format(instr, mnemonic, form);
5925 }
5926 
VisitSVEBroadcastFPImm_Unpredicated(const Instruction * instr)5927 void Disassembler::VisitSVEBroadcastFPImm_Unpredicated(
5928     const Instruction *instr) {
5929   const char *mnemonic = "unimplemented";
5930   const char *form = "(SVEBroadcastFPImm_Unpredicated)";
5931 
5932   switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
5933     case FDUP_z_i:
5934       // The preferred disassembly for fdup is "fmov".
5935       mnemonic = "fmov";
5936       form = "'Zd.'t, 'IFPSve";
5937       break;
5938     default:
5939       break;
5940   }
5941   Format(instr, mnemonic, form);
5942 }
5943 
VisitSVEBroadcastGeneralRegister(const Instruction * instr)5944 void Disassembler::VisitSVEBroadcastGeneralRegister(const Instruction *instr) {
5945   const char *mnemonic = "unimplemented";
5946   const char *form = "(SVEBroadcastGeneralRegister)";
5947 
5948   switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
5949     case DUP_z_r:
5950       // The preferred disassembly for dup is "mov".
5951       mnemonic = "mov";
5952       if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
5953         form = "'Zd.'t, 'Xns";
5954       } else {
5955         form = "'Zd.'t, 'Wns";
5956       }
5957       break;
5958     default:
5959       break;
5960   }
5961   Format(instr, mnemonic, form);
5962 }
5963 
VisitSVEBroadcastIndexElement(const Instruction * instr)5964 void Disassembler::VisitSVEBroadcastIndexElement(const Instruction *instr) {
5965   const char *mnemonic = "unimplemented";
5966   const char *form = "(SVEBroadcastIndexElement)";
5967 
5968   switch (instr->Mask(SVEBroadcastIndexElementMask)) {
5969     case DUP_z_zi: {
5970       // The tsz field must not be zero.
5971       int tsz = instr->ExtractBits(20, 16);
5972       if (tsz != 0) {
5973         // The preferred disassembly for dup is "mov".
5974         mnemonic = "mov";
5975         int imm2 = instr->ExtractBits(23, 22);
5976         if ((CountSetBits(imm2) + CountSetBits(tsz)) == 1) {
5977           // If imm2:tsz has one set bit, the index is zero. This is
5978           // disassembled as a mov from a b/h/s/d/q scalar register.
5979           form = "'Zd.'tszx, 'tszx'u0905";
5980         } else {
5981           form = "'Zd.'tszx, 'Zn.'tszx['IVInsSVEIndex]";
5982         }
5983       }
5984       break;
5985     }
5986     default:
5987       break;
5988   }
5989   Format(instr, mnemonic, form);
5990 }
5991 
VisitSVEBroadcastIntImm_Unpredicated(const Instruction * instr)5992 void Disassembler::VisitSVEBroadcastIntImm_Unpredicated(
5993     const Instruction *instr) {
5994   const char *mnemonic = "unimplemented";
5995   const char *form = "(SVEBroadcastIntImm_Unpredicated)";
5996 
5997   switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
5998     case DUP_z_i:
5999       // The encoding of byte-sized lanes with lsl #8 is undefined.
6000       if ((instr->GetSVEVectorFormat() == kFormatVnB) &&
6001           (instr->ExtractBit(13) == 1))
6002         break;
6003 
6004       // The preferred disassembly for dup is "mov".
6005       mnemonic = "mov";
6006       form = (instr->ExtractBit(13) == 0) ? "'Zd.'t, #'s1205"
6007                                           : "'Zd.'t, #'s1205, lsl #8";
6008       break;
6009     default:
6010       break;
6011   }
6012   Format(instr, mnemonic, form);
6013 }
6014 
VisitSVECompressActiveElements(const Instruction * instr)6015 void Disassembler::VisitSVECompressActiveElements(const Instruction *instr) {
6016   const char *mnemonic = "unimplemented";
6017   const char *form = "(SVECompressActiveElements)";
6018 
6019   switch (instr->Mask(SVECompressActiveElementsMask)) {
6020     case COMPACT_z_p_z:
6021       // The top bit of size is always set for compact, so 't can only be
6022       // substituted with types S and D.
6023       VIXL_ASSERT(instr->ExtractBit(23) == 1);
6024       mnemonic = "compact";
6025       form = "'Zd.'t, 'Pgl, 'Zn.'t";
6026       break;
6027     default:
6028       break;
6029   }
6030   Format(instr, mnemonic, form);
6031 }
6032 
VisitSVEConditionallyBroadcastElementToVector(const Instruction * instr)6033 void Disassembler::VisitSVEConditionallyBroadcastElementToVector(
6034     const Instruction *instr) {
6035   const char *mnemonic = "unimplemented";
6036   const char *form = "'Zd.'t, 'Pgl, 'Zd.'t, 'Zn.'t";
6037 
6038   switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
6039     case CLASTA_z_p_zz:
6040       mnemonic = "clasta";
6041       break;
6042     case CLASTB_z_p_zz:
6043       mnemonic = "clastb";
6044       break;
6045     default:
6046       break;
6047   }
6048   Format(instr, mnemonic, form);
6049 }
6050 
VisitSVEConditionallyExtractElementToGeneralRegister(const Instruction * instr)6051 void Disassembler::VisitSVEConditionallyExtractElementToGeneralRegister(
6052     const Instruction *instr) {
6053   const char *mnemonic = "unimplemented";
6054   const char *form = "'Wd, 'Pgl, 'Wd, 'Zn.'t";
6055 
6056   if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
6057     form = "'Xd, p'u1210, 'Xd, 'Zn.'t";
6058   }
6059 
6060   switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
6061     case CLASTA_r_p_z:
6062       mnemonic = "clasta";
6063       break;
6064     case CLASTB_r_p_z:
6065       mnemonic = "clastb";
6066       break;
6067     default:
6068       break;
6069   }
6070   Format(instr, mnemonic, form);
6071 }
6072 
VisitSVEConditionallyExtractElementToSIMDFPScalar(const Instruction * instr)6073 void Disassembler::VisitSVEConditionallyExtractElementToSIMDFPScalar(
6074     const Instruction *instr) {
6075   const char *mnemonic = "unimplemented";
6076   const char *form = "'t'u0400, 'Pgl, 't'u0400, 'Zn.'t";
6077 
6078   switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
6079     case CLASTA_v_p_z:
6080       mnemonic = "clasta";
6081       break;
6082     case CLASTB_v_p_z:
6083       mnemonic = "clastb";
6084       break;
6085     default:
6086       break;
6087   }
6088   Format(instr, mnemonic, form);
6089 }
6090 
VisitSVEConditionallyTerminateScalars(const Instruction * instr)6091 void Disassembler::VisitSVEConditionallyTerminateScalars(
6092     const Instruction *instr) {
6093   const char *mnemonic = "unimplemented";
6094   const char *form = (instr->ExtractBit(22) == 0) ? "'Wn, 'Wm" : "'Xn, 'Xm";
6095 
6096   switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
6097     case CTERMEQ_rr:
6098       mnemonic = "ctermeq";
6099       break;
6100     case CTERMNE_rr:
6101       mnemonic = "ctermne";
6102       break;
6103     default:
6104       break;
6105   }
6106   Format(instr, mnemonic, form);
6107 }
6108 
VisitSVEConstructivePrefix_Unpredicated(const Instruction * instr)6109 void Disassembler::VisitSVEConstructivePrefix_Unpredicated(
6110     const Instruction *instr) {
6111   const char *mnemonic = "unimplemented";
6112   const char *form = "(SVEConstructivePrefix_Unpredicated)";
6113 
6114   switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
6115     case MOVPRFX_z_z:
6116       mnemonic = "movprfx";
6117       form = "'Zd, 'Zn";
6118       break;
6119     default:
6120       break;
6121   }
6122   Format(instr, mnemonic, form);
6123 }
6124 
VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(const Instruction * instr)6125 void Disassembler::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
6126     const Instruction *instr) {
6127   const char *mnemonic = "unimplemented";
6128 
6129   bool rm_is_zr = instr->GetRm() == kZeroRegCode;
6130 
6131   const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns";
6132   const char *suffix = NULL;
6133 
6134   switch (instr->Mask(SVEContiguousFirstFaultLoad_ScalarPlusScalarMask)) {
6135     case LDFF1B_z_p_br_u16:
6136     case LDFF1B_z_p_br_u32:
6137     case LDFF1B_z_p_br_u64:
6138     case LDFF1B_z_p_br_u8:
6139       mnemonic = "ldff1b";
6140       suffix = rm_is_zr ? "]" : ", 'Xm]";
6141       break;
6142     case LDFF1D_z_p_br_u64:
6143       mnemonic = "ldff1d";
6144       suffix = rm_is_zr ? "]" : ", 'Xm, lsl #3]";
6145       break;
6146     case LDFF1H_z_p_br_u16:
6147     case LDFF1H_z_p_br_u32:
6148     case LDFF1H_z_p_br_u64:
6149       mnemonic = "ldff1h";
6150       suffix = rm_is_zr ? "]" : ", 'Xm, lsl #1]";
6151       break;
6152     case LDFF1SB_z_p_br_s16:
6153     case LDFF1SB_z_p_br_s32:
6154     case LDFF1SB_z_p_br_s64:
6155       mnemonic = "ldff1sb";
6156       suffix = rm_is_zr ? "]" : ", 'Xm]";
6157       break;
6158     case LDFF1SH_z_p_br_s32:
6159     case LDFF1SH_z_p_br_s64:
6160       mnemonic = "ldff1sh";
6161       suffix = rm_is_zr ? "]" : ", 'Xm, lsl #1]";
6162       break;
6163     case LDFF1SW_z_p_br_s64:
6164       mnemonic = "ldff1sw";
6165       suffix = rm_is_zr ? "]" : ", 'Xm, lsl #2]";
6166       break;
6167     case LDFF1W_z_p_br_u32:
6168     case LDFF1W_z_p_br_u64:
6169       mnemonic = "ldff1w";
6170       suffix = rm_is_zr ? "]" : ", 'Xm, lsl #2]";
6171       break;
6172     default:
6173       form = "(SVEContiguousFirstFaultLoad_ScalarPlusScalar)";
6174       break;
6175   }
6176 
6177   Format(instr, mnemonic, form, suffix);
6178 }
6179 
VisitSVEContiguousNonFaultLoad_ScalarPlusImm(const Instruction * instr)6180 void Disassembler::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
6181     const Instruction *instr) {
6182   const char *mnemonic = "unimplemented";
6183   const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns";
6184   const char *suffix =
6185       (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]";
6186 
6187   switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
6188     case LDNF1B_z_p_bi_u16:
6189     case LDNF1B_z_p_bi_u32:
6190     case LDNF1B_z_p_bi_u64:
6191     case LDNF1B_z_p_bi_u8:
6192       mnemonic = "ldnf1b";
6193       break;
6194     case LDNF1D_z_p_bi_u64:
6195       mnemonic = "ldnf1d";
6196       break;
6197     case LDNF1H_z_p_bi_u16:
6198     case LDNF1H_z_p_bi_u32:
6199     case LDNF1H_z_p_bi_u64:
6200       mnemonic = "ldnf1h";
6201       break;
6202     case LDNF1SB_z_p_bi_s16:
6203     case LDNF1SB_z_p_bi_s32:
6204     case LDNF1SB_z_p_bi_s64:
6205       mnemonic = "ldnf1sb";
6206       break;
6207     case LDNF1SH_z_p_bi_s32:
6208     case LDNF1SH_z_p_bi_s64:
6209       mnemonic = "ldnf1sh";
6210       break;
6211     case LDNF1SW_z_p_bi_s64:
6212       mnemonic = "ldnf1sw";
6213       break;
6214     case LDNF1W_z_p_bi_u32:
6215     case LDNF1W_z_p_bi_u64:
6216       mnemonic = "ldnf1w";
6217       break;
6218     default:
6219       form = "(SVEContiguousNonFaultLoad_ScalarPlusImm)";
6220       suffix = NULL;
6221       break;
6222   }
6223   Format(instr, mnemonic, form, suffix);
6224 }
6225 
VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(const Instruction * instr)6226 void Disassembler::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
6227     const Instruction *instr) {
6228   const char *mnemonic = "unimplemented";
6229   const char *form = "(SVEContiguousNonTemporalLoad_ScalarPlusImm)";
6230 
6231   const char *suffix =
6232       (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]";
6233   switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
6234     case LDNT1B_z_p_bi_contiguous:
6235       mnemonic = "ldnt1b";
6236       form = "{'Zt.b}, 'Pgl/z, ['Xns";
6237       break;
6238     case LDNT1D_z_p_bi_contiguous:
6239       mnemonic = "ldnt1d";
6240       form = "{'Zt.d}, 'Pgl/z, ['Xns";
6241       break;
6242     case LDNT1H_z_p_bi_contiguous:
6243       mnemonic = "ldnt1h";
6244       form = "{'Zt.h}, 'Pgl/z, ['Xns";
6245       break;
6246     case LDNT1W_z_p_bi_contiguous:
6247       mnemonic = "ldnt1w";
6248       form = "{'Zt.s}, 'Pgl/z, ['Xns";
6249       break;
6250     default:
6251       suffix = NULL;
6252       break;
6253   }
6254   Format(instr, mnemonic, form, suffix);
6255 }
6256 
VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(const Instruction * instr)6257 void Disassembler::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
6258     const Instruction *instr) {
6259   const char *mnemonic = "unimplemented";
6260   const char *form = "(SVEContiguousNonTemporalLoad_ScalarPlusScalar)";
6261 
6262   switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
6263     case LDNT1B_z_p_br_contiguous:
6264       mnemonic = "ldnt1b";
6265       form = "{'Zt.b}, 'Pgl/z, ['Xns, 'Rm]";
6266       break;
6267     case LDNT1D_z_p_br_contiguous:
6268       mnemonic = "ldnt1d";
6269       form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Rm, lsl #3]";
6270       break;
6271     case LDNT1H_z_p_br_contiguous:
6272       mnemonic = "ldnt1h";
6273       form = "{'Zt.h}, 'Pgl/z, ['Xns, 'Rm, lsl #1]";
6274       break;
6275     case LDNT1W_z_p_br_contiguous:
6276       mnemonic = "ldnt1w";
6277       form = "{'Zt.s}, 'Pgl/z, ['Xns, 'Rm, lsl #2]";
6278       break;
6279     default:
6280       break;
6281   }
6282   Format(instr, mnemonic, form);
6283 }
6284 
VisitSVEContiguousNonTemporalStore_ScalarPlusImm(const Instruction * instr)6285 void Disassembler::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
6286     const Instruction *instr) {
6287   const char *mnemonic = "unimplemented";
6288   const char *form = "(SVEContiguousNonTemporalStore_ScalarPlusImm)";
6289 
6290   const char *suffix =
6291       (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]";
6292   switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
6293     case STNT1B_z_p_bi_contiguous:
6294       mnemonic = "stnt1b";
6295       form = "{'Zt.b}, 'Pgl, ['Xns";
6296       break;
6297     case STNT1D_z_p_bi_contiguous:
6298       mnemonic = "stnt1d";
6299       form = "{'Zt.d}, 'Pgl, ['Xns";
6300       break;
6301     case STNT1H_z_p_bi_contiguous:
6302       mnemonic = "stnt1h";
6303       form = "{'Zt.h}, 'Pgl, ['Xns";
6304       break;
6305     case STNT1W_z_p_bi_contiguous:
6306       mnemonic = "stnt1w";
6307       form = "{'Zt.s}, 'Pgl, ['Xns";
6308       break;
6309     default:
6310       suffix = NULL;
6311       break;
6312   }
6313   Format(instr, mnemonic, form, suffix);
6314 }
6315 
VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(const Instruction * instr)6316 void Disassembler::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
6317     const Instruction *instr) {
6318   const char *mnemonic = "unimplemented";
6319   const char *form = "(SVEContiguousNonTemporalStore_ScalarPlusScalar)";
6320 
6321   switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
6322     case STNT1B_z_p_br_contiguous:
6323       mnemonic = "stnt1b";
6324       form = "{'Zt.b}, 'Pgl, ['Xns, 'Rm]";
6325       break;
6326     case STNT1D_z_p_br_contiguous:
6327       mnemonic = "stnt1d";
6328       form = "{'Zt.d}, 'Pgl, ['Xns, 'Rm, lsl #3]";
6329       break;
6330     case STNT1H_z_p_br_contiguous:
6331       mnemonic = "stnt1h";
6332       form = "{'Zt.h}, 'Pgl, ['Xns, 'Rm, lsl #1]";
6333       break;
6334     case STNT1W_z_p_br_contiguous:
6335       mnemonic = "stnt1w";
6336       form = "{'Zt.s}, 'Pgl, ['Xns, 'Rm, lsl #2]";
6337       break;
6338     default:
6339       break;
6340   }
6341   Format(instr, mnemonic, form);
6342 }
6343 
VisitSVEContiguousPrefetch_ScalarPlusImm(const Instruction * instr)6344 void Disassembler::VisitSVEContiguousPrefetch_ScalarPlusImm(
6345     const Instruction *instr) {
6346   const char *mnemonic = "unimplemented";
6347   const char *form = (instr->ExtractBits(21, 16) != 0)
6348                          ? "'prefSVEOp, 'Pgl, ['Xns, #'s2116, mul vl]"
6349                          : "'prefSVEOp, 'Pgl, ['Xns]";
6350 
6351   switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
6352     case PRFB_i_p_bi_s:
6353       mnemonic = "prfb";
6354       break;
6355     case PRFD_i_p_bi_s:
6356       mnemonic = "prfd";
6357       break;
6358     case PRFH_i_p_bi_s:
6359       mnemonic = "prfh";
6360       break;
6361     case PRFW_i_p_bi_s:
6362       mnemonic = "prfw";
6363       break;
6364     default:
6365       break;
6366   }
6367   Format(instr, mnemonic, form);
6368 }
6369 
VisitSVEContiguousPrefetch_ScalarPlusScalar(const Instruction * instr)6370 void Disassembler::VisitSVEContiguousPrefetch_ScalarPlusScalar(
6371     const Instruction *instr) {
6372   const char *mnemonic = "unimplemented";
6373   const char *form = "(SVEContiguousPrefetch_ScalarPlusScalar)";
6374 
6375   if (instr->GetRm() != kZeroRegCode) {
6376     switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
6377       case PRFB_i_p_br_s:
6378         mnemonic = "prfb";
6379         form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm]";
6380         break;
6381       case PRFD_i_p_br_s:
6382         mnemonic = "prfd";
6383         form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm, lsl #3]";
6384         break;
6385       case PRFH_i_p_br_s:
6386         mnemonic = "prfh";
6387         form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm, lsl #1]";
6388         break;
6389       case PRFW_i_p_br_s:
6390         mnemonic = "prfw";
6391         form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm, lsl #2]";
6392         break;
6393       default:
6394         break;
6395     }
6396   }
6397   Format(instr, mnemonic, form);
6398 }
6399 
VisitSVEContiguousStore_ScalarPlusImm(const Instruction * instr)6400 void Disassembler::VisitSVEContiguousStore_ScalarPlusImm(
6401     const Instruction *instr) {
6402   const char *mnemonic = "unimplemented";
6403 
6404   // The 'size' field isn't in the usual place here.
6405   const char *form = "{'Zt.'tls}, 'Pgl, ['Xns, #'s1916, mul vl]";
6406   if (instr->ExtractBits(19, 16) == 0) {
6407     form = "{'Zt.'tls}, 'Pgl, ['Xns]";
6408   }
6409 
6410   switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
6411     case ST1B_z_p_bi:
6412       mnemonic = "st1b";
6413       break;
6414     case ST1D_z_p_bi:
6415       mnemonic = "st1d";
6416       break;
6417     case ST1H_z_p_bi:
6418       mnemonic = "st1h";
6419       break;
6420     case ST1W_z_p_bi:
6421       mnemonic = "st1w";
6422       break;
6423     default:
6424       break;
6425   }
6426   Format(instr, mnemonic, form);
6427 }
6428 
VisitSVEContiguousStore_ScalarPlusScalar(const Instruction * instr)6429 void Disassembler::VisitSVEContiguousStore_ScalarPlusScalar(
6430     const Instruction *instr) {
6431   const char *mnemonic = "unimplemented";
6432 
6433   // The 'size' field isn't in the usual place here.
6434   const char *form = "{'Zt.'tls}, 'Pgl, ['Xns, 'Xm'NSveS]";
6435 
6436   switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
6437     case ST1B_z_p_br:
6438       mnemonic = "st1b";
6439       break;
6440     case ST1D_z_p_br:
6441       mnemonic = "st1d";
6442       break;
6443     case ST1H_z_p_br:
6444       mnemonic = "st1h";
6445       break;
6446     case ST1W_z_p_br:
6447       mnemonic = "st1w";
6448       break;
6449     default:
6450       break;
6451   }
6452   Format(instr, mnemonic, form);
6453 }
6454 
VisitSVECopyFPImm_Predicated(const Instruction * instr)6455 void Disassembler::VisitSVECopyFPImm_Predicated(const Instruction *instr) {
6456   const char *mnemonic = "unimplemented";
6457   const char *form = "(SVECopyFPImm_Predicated)";
6458 
6459   switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
6460     case FCPY_z_p_i:
6461       // The preferred disassembly for fcpy is "fmov".
6462       mnemonic = "fmov";
6463       form = "'Zd.'t, 'Pm/m, 'IFPSve";
6464       break;
6465     default:
6466       break;
6467   }
6468   Format(instr, mnemonic, form);
6469 }
6470 
VisitSVECopyGeneralRegisterToVector_Predicated(const Instruction * instr)6471 void Disassembler::VisitSVECopyGeneralRegisterToVector_Predicated(
6472     const Instruction *instr) {
6473   const char *mnemonic = "unimplemented";
6474   const char *form = "(SVECopyGeneralRegisterToVector_Predicated)";
6475 
6476   switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
6477     case CPY_z_p_r:
6478       // The preferred disassembly for cpy is "mov".
6479       mnemonic = "mov";
6480       form = "'Zd.'t, 'Pgl/m, 'Wns";
6481       if (instr->GetSVESize() == kXRegSizeInBytesLog2) {
6482         form = "'Zd.'t, 'Pgl/m, 'Xns";
6483       }
6484       break;
6485     default:
6486       break;
6487   }
6488   Format(instr, mnemonic, form);
6489 }
6490 
VisitSVECopyIntImm_Predicated(const Instruction * instr)6491 void Disassembler::VisitSVECopyIntImm_Predicated(const Instruction *instr) {
6492   const char *mnemonic = "unimplemented";
6493   const char *form = "(SVECopyIntImm_Predicated)";
6494   const char *suffix = NULL;
6495 
6496   switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
6497     case CPY_z_p_i: {
6498       // The preferred disassembly for cpy is "mov".
6499       mnemonic = "mov";
6500       form = "'Zd.'t, 'Pm/'?14:mz, #'s1205";
6501       if (instr->ExtractBit(13) != 0) suffix = ", lsl #8";
6502       break;
6503     }
6504     default:
6505       break;
6506   }
6507   Format(instr, mnemonic, form, suffix);
6508 }
6509 
VisitSVECopySIMDFPScalarRegisterToVector_Predicated(const Instruction * instr)6510 void Disassembler::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
6511     const Instruction *instr) {
6512   const char *mnemonic = "unimplemented";
6513   const char *form = "(SVECopySIMDFPScalarRegisterToVector_Predicated)";
6514 
6515   switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
6516     case CPY_z_p_v:
6517       // The preferred disassembly for cpy is "mov".
6518       mnemonic = "mov";
6519       form = "'Zd.'t, 'Pgl/m, 'Vnv";
6520       break;
6521     default:
6522       break;
6523   }
6524   Format(instr, mnemonic, form);
6525 }
6526 
VisitSVEExtractElementToGeneralRegister(const Instruction * instr)6527 void Disassembler::VisitSVEExtractElementToGeneralRegister(
6528     const Instruction *instr) {
6529   const char *mnemonic = "unimplemented";
6530   const char *form = "'Wd, 'Pgl, 'Zn.'t";
6531 
6532   if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
6533     form = "'Xd, p'u1210, 'Zn.'t";
6534   }
6535 
6536   switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
6537     case LASTA_r_p_z:
6538       mnemonic = "lasta";
6539       break;
6540     case LASTB_r_p_z:
6541       mnemonic = "lastb";
6542       break;
6543     default:
6544       break;
6545   }
6546   Format(instr, mnemonic, form);
6547 }
6548 
VisitSVEExtractElementToSIMDFPScalarRegister(const Instruction * instr)6549 void Disassembler::VisitSVEExtractElementToSIMDFPScalarRegister(
6550     const Instruction *instr) {
6551   const char *mnemonic = "unimplemented";
6552   const char *form = "'t'u0400, 'Pgl, 'Zn.'t";
6553 
6554   switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
6555     case LASTA_v_p_z:
6556       mnemonic = "lasta";
6557       break;
6558     case LASTB_v_p_z:
6559       mnemonic = "lastb";
6560       break;
6561     default:
6562       break;
6563   }
6564   Format(instr, mnemonic, form);
6565 }
6566 
VisitSVEFFRInitialise(const Instruction * instr)6567 void Disassembler::VisitSVEFFRInitialise(const Instruction *instr) {
6568   const char *mnemonic = "unimplemented";
6569   const char *form = "(SVEFFRInitialise)";
6570 
6571   switch (instr->Mask(SVEFFRInitialiseMask)) {
6572     case SETFFR_f:
6573       mnemonic = "setffr";
6574       form = " ";
6575       break;
6576     default:
6577       break;
6578   }
6579   Format(instr, mnemonic, form);
6580 }
6581 
VisitSVEFFRWriteFromPredicate(const Instruction * instr)6582 void Disassembler::VisitSVEFFRWriteFromPredicate(const Instruction *instr) {
6583   const char *mnemonic = "unimplemented";
6584   const char *form = "(SVEFFRWriteFromPredicate)";
6585 
6586   switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
6587     case WRFFR_f_p:
6588       mnemonic = "wrffr";
6589       form = "'Pn.b";
6590       break;
6591     default:
6592       break;
6593   }
6594   Format(instr, mnemonic, form);
6595 }
6596 
VisitSVEFPArithmeticWithImm_Predicated(const Instruction * instr)6597 void Disassembler::VisitSVEFPArithmeticWithImm_Predicated(
6598     const Instruction *instr) {
6599   const char *mnemonic = "unimplemented";
6600   const char *form00 = "'Zd.'t, 'Pgl/m, 'Zd.'t, #0.0";
6601   const char *form05 = "'Zd.'t, 'Pgl/m, 'Zd.'t, #0.5";
6602   const char *form10 = "'Zd.'t, 'Pgl/m, 'Zd.'t, #1.0";
6603   const char *form20 = "'Zd.'t, 'Pgl/m, 'Zd.'t, #2.0";
6604   int i1 = instr->ExtractBit(5);
6605   const char *form = i1 ? form10 : form00;
6606 
6607   switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
6608     case FADD_z_p_zs:
6609       mnemonic = "fadd";
6610       form = i1 ? form10 : form05;
6611       break;
6612     case FMAXNM_z_p_zs:
6613       mnemonic = "fmaxnm";
6614       break;
6615     case FMAX_z_p_zs:
6616       mnemonic = "fmax";
6617       break;
6618     case FMINNM_z_p_zs:
6619       mnemonic = "fminnm";
6620       break;
6621     case FMIN_z_p_zs:
6622       mnemonic = "fmin";
6623       break;
6624     case FMUL_z_p_zs:
6625       mnemonic = "fmul";
6626       form = i1 ? form20 : form05;
6627       break;
6628     case FSUBR_z_p_zs:
6629       mnemonic = "fsubr";
6630       form = i1 ? form10 : form05;
6631       break;
6632     case FSUB_z_p_zs:
6633       mnemonic = "fsub";
6634       form = i1 ? form10 : form05;
6635       break;
6636     default:
6637       form = "(SVEFPArithmeticWithImm_Predicated)";
6638       break;
6639   }
6640   Format(instr, mnemonic, form);
6641 }
6642 
VisitSVEFPArithmetic_Predicated(const Instruction * instr)6643 void Disassembler::VisitSVEFPArithmetic_Predicated(const Instruction *instr) {
6644   const char *mnemonic = "unimplemented";
6645   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
6646 
6647   switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {
6648     case FABD_z_p_zz:
6649       mnemonic = "fabd";
6650       break;
6651     case FADD_z_p_zz:
6652       mnemonic = "fadd";
6653       break;
6654     case FDIVR_z_p_zz:
6655       mnemonic = "fdivr";
6656       break;
6657     case FDIV_z_p_zz:
6658       mnemonic = "fdiv";
6659       break;
6660     case FMAXNM_z_p_zz:
6661       mnemonic = "fmaxnm";
6662       break;
6663     case FMAX_z_p_zz:
6664       mnemonic = "fmax";
6665       break;
6666     case FMINNM_z_p_zz:
6667       mnemonic = "fminnm";
6668       break;
6669     case FMIN_z_p_zz:
6670       mnemonic = "fmin";
6671       break;
6672     case FMULX_z_p_zz:
6673       mnemonic = "fmulx";
6674       break;
6675     case FMUL_z_p_zz:
6676       mnemonic = "fmul";
6677       break;
6678     case FSCALE_z_p_zz:
6679       mnemonic = "fscale";
6680       break;
6681     case FSUBR_z_p_zz:
6682       mnemonic = "fsubr";
6683       break;
6684     case FSUB_z_p_zz:
6685       mnemonic = "fsub";
6686       break;
6687     default:
6688       break;
6689   }
6690   Format(instr, mnemonic, form);
6691 }
6692 
VisitSVEFPConvertPrecision(const Instruction * instr)6693 void Disassembler::VisitSVEFPConvertPrecision(const Instruction *instr) {
6694   const char *mnemonic = "unimplemented";
6695   const char *form = "(SVEFPConvertPrecision)";
6696 
6697   switch (instr->Mask(SVEFPConvertPrecisionMask)) {
6698     case FCVT_z_p_z_d2h:
6699       mnemonic = "fcvt";
6700       form = "'Zd.h, 'Pgl/m, 'Zn.d";
6701       break;
6702     case FCVT_z_p_z_d2s:
6703       mnemonic = "fcvt";
6704       form = "'Zd.s, 'Pgl/m, 'Zn.d";
6705       break;
6706     case FCVT_z_p_z_h2d:
6707       mnemonic = "fcvt";
6708       form = "'Zd.d, 'Pgl/m, 'Zn.h";
6709       break;
6710     case FCVT_z_p_z_h2s:
6711       mnemonic = "fcvt";
6712       form = "'Zd.s, 'Pgl/m, 'Zn.h";
6713       break;
6714     case FCVT_z_p_z_s2d:
6715       mnemonic = "fcvt";
6716       form = "'Zd.d, 'Pgl/m, 'Zn.s";
6717       break;
6718     case FCVT_z_p_z_s2h:
6719       mnemonic = "fcvt";
6720       form = "'Zd.h, 'Pgl/m, 'Zn.s";
6721       break;
6722     default:
6723       break;
6724   }
6725   Format(instr, mnemonic, form);
6726 }
6727 
VisitSVEFPConvertToInt(const Instruction * instr)6728 void Disassembler::VisitSVEFPConvertToInt(const Instruction *instr) {
6729   const char *mnemonic = "unimplemented";
6730   const char *form = "(SVEFPConvertToInt)";
6731 
6732   switch (instr->Mask(SVEFPConvertToIntMask)) {
6733     case FCVTZS_z_p_z_d2w:
6734       mnemonic = "fcvtzs";
6735       form = "'Zd.s, 'Pgl/m, 'Zn.d";
6736       break;
6737     case FCVTZS_z_p_z_d2x:
6738       mnemonic = "fcvtzs";
6739       form = "'Zd.d, 'Pgl/m, 'Zn.d";
6740       break;
6741     case FCVTZS_z_p_z_fp162h:
6742       mnemonic = "fcvtzs";
6743       form = "'Zd.h, 'Pgl/m, 'Zn.h";
6744       break;
6745     case FCVTZS_z_p_z_fp162w:
6746       mnemonic = "fcvtzs";
6747       form = "'Zd.s, 'Pgl/m, 'Zn.h";
6748       break;
6749     case FCVTZS_z_p_z_fp162x:
6750       mnemonic = "fcvtzs";
6751       form = "'Zd.d, 'Pgl/m, 'Zn.h";
6752       break;
6753     case FCVTZS_z_p_z_s2w:
6754       mnemonic = "fcvtzs";
6755       form = "'Zd.s, 'Pgl/m, 'Zn.s";
6756       break;
6757     case FCVTZS_z_p_z_s2x:
6758       mnemonic = "fcvtzs";
6759       form = "'Zd.d, 'Pgl/m, 'Zn.s";
6760       break;
6761     case FCVTZU_z_p_z_d2w:
6762       mnemonic = "fcvtzu";
6763       form = "'Zd.s, 'Pgl/m, 'Zn.d";
6764       break;
6765     case FCVTZU_z_p_z_d2x:
6766       mnemonic = "fcvtzu";
6767       form = "'Zd.d, 'Pgl/m, 'Zn.d";
6768       break;
6769     case FCVTZU_z_p_z_fp162h:
6770       mnemonic = "fcvtzu";
6771       form = "'Zd.h, 'Pgl/m, 'Zn.h";
6772       break;
6773     case FCVTZU_z_p_z_fp162w:
6774       mnemonic = "fcvtzu";
6775       form = "'Zd.s, 'Pgl/m, 'Zn.h";
6776       break;
6777     case FCVTZU_z_p_z_fp162x:
6778       mnemonic = "fcvtzu";
6779       form = "'Zd.d, 'Pgl/m, 'Zn.h";
6780       break;
6781     case FCVTZU_z_p_z_s2w:
6782       mnemonic = "fcvtzu";
6783       form = "'Zd.s, 'Pgl/m, 'Zn.s";
6784       break;
6785     case FCVTZU_z_p_z_s2x:
6786       mnemonic = "fcvtzu";
6787       form = "'Zd.d, 'Pgl/m, 'Zn.s";
6788       break;
6789     default:
6790       break;
6791   }
6792   Format(instr, mnemonic, form);
6793 }
6794 
VisitSVEFPExponentialAccelerator(const Instruction * instr)6795 void Disassembler::VisitSVEFPExponentialAccelerator(const Instruction *instr) {
6796   const char *mnemonic = "unimplemented";
6797   const char *form = "(SVEFPExponentialAccelerator)";
6798 
6799   unsigned size = instr->GetSVESize();
6800   switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
6801     case FEXPA_z_z:
6802       if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) ||
6803           (size == kDRegSizeInBytesLog2)) {
6804         mnemonic = "fexpa";
6805         form = "'Zd.'t, 'Zn.'t";
6806       }
6807       break;
6808     default:
6809       break;
6810   }
6811   Format(instr, mnemonic, form);
6812 }
6813 
VisitSVEFPRoundToIntegralValue(const Instruction * instr)6814 void Disassembler::VisitSVEFPRoundToIntegralValue(const Instruction *instr) {
6815   const char *mnemonic = "unimplemented";
6816   const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t";
6817 
6818   switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
6819     case FRINTA_z_p_z:
6820       mnemonic = "frinta";
6821       break;
6822     case FRINTI_z_p_z:
6823       mnemonic = "frinti";
6824       break;
6825     case FRINTM_z_p_z:
6826       mnemonic = "frintm";
6827       break;
6828     case FRINTN_z_p_z:
6829       mnemonic = "frintn";
6830       break;
6831     case FRINTP_z_p_z:
6832       mnemonic = "frintp";
6833       break;
6834     case FRINTX_z_p_z:
6835       mnemonic = "frintx";
6836       break;
6837     case FRINTZ_z_p_z:
6838       mnemonic = "frintz";
6839       break;
6840     default:
6841       break;
6842   }
6843   Format(instr, mnemonic, form);
6844 }
6845 
VisitSVEFPTrigMulAddCoefficient(const Instruction * instr)6846 void Disassembler::VisitSVEFPTrigMulAddCoefficient(const Instruction *instr) {
6847   const char *mnemonic = "unimplemented";
6848   const char *form = "(SVEFPTrigMulAddCoefficient)";
6849 
6850   unsigned size = instr->GetSVESize();
6851   switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {
6852     case FTMAD_z_zzi:
6853       if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) ||
6854           (size == kDRegSizeInBytesLog2)) {
6855         mnemonic = "ftmad";
6856         form = "'Zd.'t, 'Zd.'t, 'Zn.'t, #'u1816";
6857       }
6858       break;
6859     default:
6860       break;
6861   }
6862   Format(instr, mnemonic, form);
6863 }
6864 
VisitSVEFPTrigSelectCoefficient(const Instruction * instr)6865 void Disassembler::VisitSVEFPTrigSelectCoefficient(const Instruction *instr) {
6866   const char *mnemonic = "unimplemented";
6867   const char *form = "(SVEFPTrigSelectCoefficient)";
6868 
6869   unsigned size = instr->GetSVESize();
6870   switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
6871     case FTSSEL_z_zz:
6872       if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) ||
6873           (size == kDRegSizeInBytesLog2)) {
6874         mnemonic = "ftssel";
6875         form = "'Zd.'t, 'Zn.'t, 'Zm.'t";
6876       }
6877       break;
6878     default:
6879       break;
6880   }
6881   Format(instr, mnemonic, form);
6882 }
6883 
VisitSVEFPUnaryOp(const Instruction * instr)6884 void Disassembler::VisitSVEFPUnaryOp(const Instruction *instr) {
6885   const char *mnemonic = "unimplemented";
6886   const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t";
6887 
6888   if (instr->GetSVESize() == kBRegSizeInBytesLog2) {
6889     form = "(SVEFPUnaryOp)";
6890   } else {
6891     switch (instr->Mask(SVEFPUnaryOpMask)) {
6892       case FRECPX_z_p_z:
6893         mnemonic = "frecpx";
6894         break;
6895       case FSQRT_z_p_z:
6896         mnemonic = "fsqrt";
6897         break;
6898       default:
6899         form = "(SVEFPUnaryOp)";
6900         break;
6901     }
6902   }
6903   Format(instr, mnemonic, form);
6904 }
6905 
IncDecFormHelper(const Instruction * instr,const char * reg_pat_mul_form,const char * reg_pat_form,const char * reg_form)6906 static const char *IncDecFormHelper(const Instruction *instr,
6907                                     const char *reg_pat_mul_form,
6908                                     const char *reg_pat_form,
6909                                     const char *reg_form) {
6910   if (instr->ExtractBits(19, 16) == 0) {
6911     if (instr->ExtractBits(9, 5) == SVE_ALL) {
6912       // Use the register only form if the multiplier is one (encoded as zero)
6913       // and the pattern is SVE_ALL.
6914       return reg_form;
6915     }
6916     // Use the register and pattern form if the multiplier is one.
6917     return reg_pat_form;
6918   }
6919   return reg_pat_mul_form;
6920 }
6921 
VisitSVEIncDecRegisterByElementCount(const Instruction * instr)6922 void Disassembler::VisitSVEIncDecRegisterByElementCount(
6923     const Instruction *instr) {
6924   const char *mnemonic = "unimplemented";
6925   const char *form =
6926       IncDecFormHelper(instr, "'Xd, 'Ipc, mul #'u1916+1", "'Xd, 'Ipc", "'Xd");
6927 
6928   switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {
6929     case DECB_r_rs:
6930       mnemonic = "decb";
6931       break;
6932     case DECD_r_rs:
6933       mnemonic = "decd";
6934       break;
6935     case DECH_r_rs:
6936       mnemonic = "dech";
6937       break;
6938     case DECW_r_rs:
6939       mnemonic = "decw";
6940       break;
6941     case INCB_r_rs:
6942       mnemonic = "incb";
6943       break;
6944     case INCD_r_rs:
6945       mnemonic = "incd";
6946       break;
6947     case INCH_r_rs:
6948       mnemonic = "inch";
6949       break;
6950     case INCW_r_rs:
6951       mnemonic = "incw";
6952       break;
6953     default:
6954       form = "(SVEIncDecRegisterByElementCount)";
6955       break;
6956   }
6957   Format(instr, mnemonic, form);
6958 }
6959 
VisitSVEIncDecVectorByElementCount(const Instruction * instr)6960 void Disassembler::VisitSVEIncDecVectorByElementCount(
6961     const Instruction *instr) {
6962   const char *mnemonic = "unimplemented";
6963   const char *form = IncDecFormHelper(instr,
6964                                       "'Zd.'t, 'Ipc, mul #'u1916+1",
6965                                       "'Zd.'t, 'Ipc",
6966                                       "'Zd.'t");
6967 
6968   switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {
6969     case DECD_z_zs:
6970       mnemonic = "decd";
6971       break;
6972     case DECH_z_zs:
6973       mnemonic = "dech";
6974       break;
6975     case DECW_z_zs:
6976       mnemonic = "decw";
6977       break;
6978     case INCD_z_zs:
6979       mnemonic = "incd";
6980       break;
6981     case INCH_z_zs:
6982       mnemonic = "inch";
6983       break;
6984     case INCW_z_zs:
6985       mnemonic = "incw";
6986       break;
6987     default:
6988       form = "(SVEIncDecVectorByElementCount)";
6989       break;
6990   }
6991   Format(instr, mnemonic, form);
6992 }
6993 
VisitSVEInsertGeneralRegister(const Instruction * instr)6994 void Disassembler::VisitSVEInsertGeneralRegister(const Instruction *instr) {
6995   const char *mnemonic = "unimplemented";
6996   const char *form = "(SVEInsertGeneralRegister)";
6997 
6998   switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
6999     case INSR_z_r:
7000       mnemonic = "insr";
7001       if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
7002         form = "'Zd.'t, 'Xn";
7003       } else {
7004         form = "'Zd.'t, 'Wn";
7005       }
7006       break;
7007     default:
7008       break;
7009   }
7010   Format(instr, mnemonic, form);
7011 }
7012 
VisitSVEInsertSIMDFPScalarRegister(const Instruction * instr)7013 void Disassembler::VisitSVEInsertSIMDFPScalarRegister(
7014     const Instruction *instr) {
7015   const char *mnemonic = "unimplemented";
7016   const char *form = "(SVEInsertSIMDFPScalarRegister)";
7017 
7018   switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
7019     case INSR_z_v:
7020       mnemonic = "insr";
7021       form = "'Zd.'t, 'Vnv";
7022       break;
7023     default:
7024       break;
7025   }
7026   Format(instr, mnemonic, form);
7027 }
7028 
VisitSVEIntAddSubtractImm_Unpredicated(const Instruction * instr)7029 void Disassembler::VisitSVEIntAddSubtractImm_Unpredicated(
7030     const Instruction *instr) {
7031   const char *mnemonic = "unimplemented";
7032   const char *form = (instr->ExtractBit(13) == 0)
7033                          ? "'Zd.'t, 'Zd.'t, #'u1205"
7034                          : "'Zd.'t, 'Zd.'t, #'u1205, lsl #8";
7035 
7036   switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
7037     case ADD_z_zi:
7038       mnemonic = "add";
7039       break;
7040     case SQADD_z_zi:
7041       mnemonic = "sqadd";
7042       break;
7043     case SQSUB_z_zi:
7044       mnemonic = "sqsub";
7045       break;
7046     case SUBR_z_zi:
7047       mnemonic = "subr";
7048       break;
7049     case SUB_z_zi:
7050       mnemonic = "sub";
7051       break;
7052     case UQADD_z_zi:
7053       mnemonic = "uqadd";
7054       break;
7055     case UQSUB_z_zi:
7056       mnemonic = "uqsub";
7057       break;
7058     default:
7059       form = "(SVEIntAddSubtractImm_Unpredicated)";
7060       break;
7061   }
7062   Format(instr, mnemonic, form);
7063 }
7064 
VisitSVEIntAddSubtractVectors_Predicated(const Instruction * instr)7065 void Disassembler::VisitSVEIntAddSubtractVectors_Predicated(
7066     const Instruction *instr) {
7067   const char *mnemonic = "unimplemented";
7068   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
7069 
7070   switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
7071     case ADD_z_p_zz:
7072       mnemonic = "add";
7073       break;
7074     case SUBR_z_p_zz:
7075       mnemonic = "subr";
7076       break;
7077     case SUB_z_p_zz:
7078       mnemonic = "sub";
7079       break;
7080     default:
7081       break;
7082   }
7083   Format(instr, mnemonic, form);
7084 }
7085 
VisitSVEIntCompareScalarCountAndLimit(const Instruction * instr)7086 void Disassembler::VisitSVEIntCompareScalarCountAndLimit(
7087     const Instruction *instr) {
7088   const char *mnemonic = "unimplemented";
7089   const char *form =
7090       (instr->ExtractBit(12) == 0) ? "'Pd.'t, 'Wn, 'Wm" : "'Pd.'t, 'Xn, 'Xm";
7091 
7092   switch (instr->Mask(SVEIntCompareScalarCountAndLimitMask)) {
7093     case WHILELE_p_p_rr:
7094       mnemonic = "whilele";
7095       break;
7096     case WHILELO_p_p_rr:
7097       mnemonic = "whilelo";
7098       break;
7099     case WHILELS_p_p_rr:
7100       mnemonic = "whilels";
7101       break;
7102     case WHILELT_p_p_rr:
7103       mnemonic = "whilelt";
7104       break;
7105     default:
7106       break;
7107   }
7108   Format(instr, mnemonic, form);
7109 }
7110 
VisitSVEIntConvertToFP(const Instruction * instr)7111 void Disassembler::VisitSVEIntConvertToFP(const Instruction *instr) {
7112   const char *mnemonic = "unimplemented";
7113   const char *form = "(SVEIntConvertToFP)";
7114 
7115   switch (instr->Mask(SVEIntConvertToFPMask)) {
7116     case SCVTF_z_p_z_h2fp16:
7117       mnemonic = "scvtf";
7118       form = "'Zd.h, 'Pgl/m, 'Zn.h";
7119       break;
7120     case SCVTF_z_p_z_w2d:
7121       mnemonic = "scvtf";
7122       form = "'Zd.d, 'Pgl/m, 'Zn.s";
7123       break;
7124     case SCVTF_z_p_z_w2fp16:
7125       mnemonic = "scvtf";
7126       form = "'Zd.h, 'Pgl/m, 'Zn.s";
7127       break;
7128     case SCVTF_z_p_z_w2s:
7129       mnemonic = "scvtf";
7130       form = "'Zd.s, 'Pgl/m, 'Zn.s";
7131       break;
7132     case SCVTF_z_p_z_x2d:
7133       mnemonic = "scvtf";
7134       form = "'Zd.d, 'Pgl/m, 'Zn.d";
7135       break;
7136     case SCVTF_z_p_z_x2fp16:
7137       mnemonic = "scvtf";
7138       form = "'Zd.h, 'Pgl/m, 'Zn.d";
7139       break;
7140     case SCVTF_z_p_z_x2s:
7141       mnemonic = "scvtf";
7142       form = "'Zd.s, 'Pgl/m, 'Zn.d";
7143       break;
7144     case UCVTF_z_p_z_h2fp16:
7145       mnemonic = "ucvtf";
7146       form = "'Zd.h, 'Pgl/m, 'Zn.h";
7147       break;
7148     case UCVTF_z_p_z_w2d:
7149       mnemonic = "ucvtf";
7150       form = "'Zd.d, 'Pgl/m, 'Zn.s";
7151       break;
7152     case UCVTF_z_p_z_w2fp16:
7153       mnemonic = "ucvtf";
7154       form = "'Zd.h, 'Pgl/m, 'Zn.s";
7155       break;
7156     case UCVTF_z_p_z_w2s:
7157       mnemonic = "ucvtf";
7158       form = "'Zd.s, 'Pgl/m, 'Zn.s";
7159       break;
7160     case UCVTF_z_p_z_x2d:
7161       mnemonic = "ucvtf";
7162       form = "'Zd.d, 'Pgl/m, 'Zn.d";
7163       break;
7164     case UCVTF_z_p_z_x2fp16:
7165       mnemonic = "ucvtf";
7166       form = "'Zd.h, 'Pgl/m, 'Zn.d";
7167       break;
7168     case UCVTF_z_p_z_x2s:
7169       mnemonic = "ucvtf";
7170       form = "'Zd.s, 'Pgl/m, 'Zn.d";
7171       break;
7172     default:
7173       break;
7174   }
7175   Format(instr, mnemonic, form);
7176 }
7177 
VisitSVEIntDivideVectors_Predicated(const Instruction * instr)7178 void Disassembler::VisitSVEIntDivideVectors_Predicated(
7179     const Instruction *instr) {
7180   const char *mnemonic = "unimplemented";
7181   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
7182 
7183   switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
7184     case SDIVR_z_p_zz:
7185       mnemonic = "sdivr";
7186       break;
7187     case SDIV_z_p_zz:
7188       mnemonic = "sdiv";
7189       break;
7190     case UDIVR_z_p_zz:
7191       mnemonic = "udivr";
7192       break;
7193     case UDIV_z_p_zz:
7194       mnemonic = "udiv";
7195       break;
7196     default:
7197       break;
7198   }
7199 
7200   switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
7201     case SDIVR_z_p_zz:
7202     case SDIV_z_p_zz:
7203     case UDIVR_z_p_zz:
7204     case UDIV_z_p_zz:
7205       switch (instr->GetSVESize()) {
7206         case kBRegSizeInBytesLog2:
7207         case kHRegSizeInBytesLog2:
7208           mnemonic = "unimplemented";
7209           form = "(SVEIntBinaryArithmeticPredicated)";
7210           break;
7211         case kSRegSizeInBytesLog2:
7212         case kDRegSizeInBytesLog2:
7213           // The default form works for these instructions.
7214           break;
7215         default:
7216           // GetSVESize() should never return other values.
7217           VIXL_UNREACHABLE();
7218           break;
7219       }
7220   }
7221 
7222   Format(instr, mnemonic, form);
7223 }
7224 
VisitSVEIntMinMaxDifference_Predicated(const Instruction * instr)7225 void Disassembler::VisitSVEIntMinMaxDifference_Predicated(
7226     const Instruction *instr) {
7227   const char *mnemonic = "unimplemented";
7228   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
7229 
7230   switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
7231     case SABD_z_p_zz:
7232       mnemonic = "sabd";
7233       break;
7234     case SMAX_z_p_zz:
7235       mnemonic = "smax";
7236       break;
7237     case SMIN_z_p_zz:
7238       mnemonic = "smin";
7239       break;
7240     case UABD_z_p_zz:
7241       mnemonic = "uabd";
7242       break;
7243     case UMAX_z_p_zz:
7244       mnemonic = "umax";
7245       break;
7246     case UMIN_z_p_zz:
7247       mnemonic = "umin";
7248       break;
7249     default:
7250       break;
7251   }
7252   Format(instr, mnemonic, form);
7253 }
7254 
VisitSVEIntMinMaxImm_Unpredicated(const Instruction * instr)7255 void Disassembler::VisitSVEIntMinMaxImm_Unpredicated(const Instruction *instr) {
7256   const char *mnemonic = "unimplemented";
7257   const char *form = "'Zd.'t, 'Zd.'t, #'u1205";
7258 
7259   switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
7260     case SMAX_z_zi:
7261       mnemonic = "smax";
7262       form = "'Zd.'t, 'Zd.'t, #'s1205";
7263       break;
7264     case SMIN_z_zi:
7265       mnemonic = "smin";
7266       form = "'Zd.'t, 'Zd.'t, #'s1205";
7267       break;
7268     case UMAX_z_zi:
7269       mnemonic = "umax";
7270       break;
7271     case UMIN_z_zi:
7272       mnemonic = "umin";
7273       break;
7274     default:
7275       break;
7276   }
7277   Format(instr, mnemonic, form);
7278 }
7279 
VisitSVEIntMulImm_Unpredicated(const Instruction * instr)7280 void Disassembler::VisitSVEIntMulImm_Unpredicated(const Instruction *instr) {
7281   const char *mnemonic = "unimplemented";
7282   const char *form = "(SVEIntMulImm_Unpredicated)";
7283 
7284   switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
7285     case MUL_z_zi:
7286       mnemonic = "mul";
7287       form = "'Zd.'t, 'Zd.'t, #'s1205";
7288       break;
7289     default:
7290       break;
7291   }
7292   Format(instr, mnemonic, form);
7293 }
7294 
VisitSVEIntMulVectors_Predicated(const Instruction * instr)7295 void Disassembler::VisitSVEIntMulVectors_Predicated(const Instruction *instr) {
7296   const char *mnemonic = "unimplemented";
7297   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
7298 
7299   switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
7300     case MUL_z_p_zz:
7301       mnemonic = "mul";
7302       break;
7303     case SMULH_z_p_zz:
7304       mnemonic = "smulh";
7305       break;
7306     case UMULH_z_p_zz:
7307       mnemonic = "umulh";
7308       break;
7309     default:
7310       break;
7311   }
7312   Format(instr, mnemonic, form);
7313 }
7314 
VisitSVELoadAndBroadcastElement(const Instruction * instr)7315 void Disassembler::VisitSVELoadAndBroadcastElement(const Instruction *instr) {
7316   const char *mnemonic = "unimplemented";
7317   const char *form = "(SVELoadAndBroadcastElement)";
7318   const char *suffix_b = ", #'u2116]";
7319   const char *suffix_h = ", #'u2116*2]";
7320   const char *suffix_w = ", #'u2116*4]";
7321   const char *suffix_d = ", #'u2116*8]";
7322   const char *suffix = NULL;
7323 
7324   switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
7325     case LD1RB_z_p_bi_u16:
7326       mnemonic = "ld1rb";
7327       form = "{'Zt.h}, 'Pgl/z, ['Xns";
7328       suffix = suffix_b;
7329       break;
7330     case LD1RB_z_p_bi_u32:
7331       mnemonic = "ld1rb";
7332       form = "{'Zt.s}, 'Pgl/z, ['Xns";
7333       suffix = suffix_b;
7334       break;
7335     case LD1RB_z_p_bi_u64:
7336       mnemonic = "ld1rb";
7337       form = "{'Zt.d}, 'Pgl/z, ['Xns";
7338       suffix = suffix_b;
7339       break;
7340     case LD1RB_z_p_bi_u8:
7341       mnemonic = "ld1rb";
7342       form = "{'Zt.b}, 'Pgl/z, ['Xns";
7343       suffix = suffix_b;
7344       break;
7345     case LD1RD_z_p_bi_u64:
7346       mnemonic = "ld1rd";
7347       form = "{'Zt.d}, 'Pgl/z, ['Xns";
7348       suffix = suffix_d;
7349       break;
7350     case LD1RH_z_p_bi_u16:
7351       mnemonic = "ld1rh";
7352       form = "{'Zt.h}, 'Pgl/z, ['Xns";
7353       suffix = suffix_h;
7354       break;
7355     case LD1RH_z_p_bi_u32:
7356       mnemonic = "ld1rh";
7357       form = "{'Zt.s}, 'Pgl/z, ['Xns";
7358       suffix = suffix_h;
7359       break;
7360     case LD1RH_z_p_bi_u64:
7361       mnemonic = "ld1rh";
7362       form = "{'Zt.d}, 'Pgl/z, ['Xns";
7363       suffix = suffix_h;
7364       break;
7365     case LD1RSB_z_p_bi_s16:
7366       mnemonic = "ld1rsb";
7367       form = "{'Zt.h}, 'Pgl/z, ['Xns";
7368       suffix = suffix_b;
7369       break;
7370     case LD1RSB_z_p_bi_s32:
7371       mnemonic = "ld1rsb";
7372       form = "{'Zt.s}, 'Pgl/z, ['Xns";
7373       suffix = suffix_b;
7374       break;
7375     case LD1RSB_z_p_bi_s64:
7376       mnemonic = "ld1rsb";
7377       form = "{'Zt.d}, 'Pgl/z, ['Xns";
7378       suffix = suffix_b;
7379       break;
7380     case LD1RSH_z_p_bi_s32:
7381       mnemonic = "ld1rsh";
7382       form = "{'Zt.s}, 'Pgl/z, ['Xns";
7383       suffix = suffix_h;
7384       break;
7385     case LD1RSH_z_p_bi_s64:
7386       mnemonic = "ld1rsh";
7387       form = "{'Zt.d}, 'Pgl/z, ['Xns";
7388       suffix = suffix_h;
7389       break;
7390     case LD1RSW_z_p_bi_s64:
7391       mnemonic = "ld1rsw";
7392       form = "{'Zt.d}, 'Pgl/z, ['Xns";
7393       suffix = suffix_w;
7394       break;
7395     case LD1RW_z_p_bi_u32:
7396       mnemonic = "ld1rw";
7397       form = "{'Zt.s}, 'Pgl/z, ['Xns";
7398       suffix = suffix_w;
7399       break;
7400     case LD1RW_z_p_bi_u64:
7401       mnemonic = "ld1rw";
7402       form = "{'Zt.d}, 'Pgl/z, ['Xns";
7403       suffix = suffix_w;
7404       break;
7405     default:
7406       break;
7407   }
7408 
7409   // Hide curly brackets if immediate is zero.
7410   if (instr->ExtractBits(21, 16) == 0) {
7411     suffix = "]";
7412   }
7413 
7414   Format(instr, mnemonic, form, suffix);
7415 }
7416 
VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(const Instruction * instr)7417 void Disassembler::VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(
7418     const Instruction *instr) {
7419   const char *mnemonic = "unimplemented";
7420   const char *form = "(SVELoadAndBroadcastQuadword_ScalarPlusImm)";
7421 
7422   const char *suffix =
7423       (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916*16]";
7424 
7425   switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusImmMask)) {
7426     case LD1RQB_z_p_bi_u8:
7427       mnemonic = "ld1rqb";
7428       form = "{'Zt.b}, 'Pgl/z, ['Xns";
7429       break;
7430     case LD1RQD_z_p_bi_u64:
7431       mnemonic = "ld1rqd";
7432       form = "{'Zt.d}, 'Pgl/z, ['Xns";
7433       break;
7434     case LD1RQH_z_p_bi_u16:
7435       mnemonic = "ld1rqh";
7436       form = "{'Zt.h}, 'Pgl/z, ['Xns";
7437       break;
7438     case LD1RQW_z_p_bi_u32:
7439       mnemonic = "ld1rqw";
7440       form = "{'Zt.s}, 'Pgl/z, ['Xns";
7441       break;
7442     default:
7443       suffix = NULL;
7444       break;
7445   }
7446   Format(instr, mnemonic, form, suffix);
7447 }
7448 
VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(const Instruction * instr)7449 void Disassembler::VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(
7450     const Instruction *instr) {
7451   const char *mnemonic = "unimplemented";
7452   const char *form = "(SVELoadAndBroadcastQuadword_ScalarPlusScalar)";
7453 
7454   switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusScalarMask)) {
7455     case LD1RQB_z_p_br_contiguous:
7456       mnemonic = "ld1rqb";
7457       form = "{'Zt.b}, 'Pgl/z, ['Xns, 'Rm]";
7458       break;
7459     case LD1RQD_z_p_br_contiguous:
7460       mnemonic = "ld1rqd";
7461       form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Rm, lsl #3]";
7462       break;
7463     case LD1RQH_z_p_br_contiguous:
7464       mnemonic = "ld1rqh";
7465       form = "{'Zt.h}, 'Pgl/z, ['Xns, 'Rm, lsl #1]";
7466       break;
7467     case LD1RQW_z_p_br_contiguous:
7468       mnemonic = "ld1rqw";
7469       form = "{'Zt.s}, 'Pgl/z, ['Xns, 'Rm, lsl #2]";
7470       break;
7471     default:
7472       break;
7473   }
7474   Format(instr, mnemonic, form);
7475 }
7476 
VisitSVELoadMultipleStructures_ScalarPlusImm(const Instruction * instr)7477 void Disassembler::VisitSVELoadMultipleStructures_ScalarPlusImm(
7478     const Instruction *instr) {
7479   const char *mnemonic = "unimplemented";
7480   const char *form = "(SVELoadMultipleStructures_ScalarPlusImm)";
7481 
7482   const char *form_2 = "{'Zt.'tmsz, 'Zt2.'tmsz}, 'Pgl/z, ['Xns'ISveSvl]";
7483   const char *form_3 =
7484       "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}, 'Pgl/z, ['Xns'ISveSvl]";
7485   const char *form_4 =
7486       "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}, "
7487       "'Pgl/z, ['Xns'ISveSvl]";
7488 
7489   switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
7490     case LD2B_z_p_bi_contiguous:
7491       mnemonic = "ld2b";
7492       form = form_2;
7493       break;
7494     case LD2D_z_p_bi_contiguous:
7495       mnemonic = "ld2d";
7496       form = form_2;
7497       break;
7498     case LD2H_z_p_bi_contiguous:
7499       mnemonic = "ld2h";
7500       form = form_2;
7501       break;
7502     case LD2W_z_p_bi_contiguous:
7503       mnemonic = "ld2w";
7504       form = form_2;
7505       break;
7506     case LD3B_z_p_bi_contiguous:
7507       mnemonic = "ld3b";
7508       form = form_3;
7509       break;
7510     case LD3D_z_p_bi_contiguous:
7511       mnemonic = "ld3d";
7512       form = form_3;
7513       break;
7514     case LD3H_z_p_bi_contiguous:
7515       mnemonic = "ld3h";
7516       form = form_3;
7517       break;
7518     case LD3W_z_p_bi_contiguous:
7519       mnemonic = "ld3w";
7520       form = form_3;
7521       break;
7522     case LD4B_z_p_bi_contiguous:
7523       mnemonic = "ld4b";
7524       form = form_4;
7525       break;
7526     case LD4D_z_p_bi_contiguous:
7527       mnemonic = "ld4d";
7528       form = form_4;
7529       break;
7530     case LD4H_z_p_bi_contiguous:
7531       mnemonic = "ld4h";
7532       form = form_4;
7533       break;
7534     case LD4W_z_p_bi_contiguous:
7535       mnemonic = "ld4w";
7536       form = form_4;
7537       break;
7538     default:
7539       break;
7540   }
7541   Format(instr, mnemonic, form);
7542 }
7543 
VisitSVELoadMultipleStructures_ScalarPlusScalar(const Instruction * instr)7544 void Disassembler::VisitSVELoadMultipleStructures_ScalarPlusScalar(
7545     const Instruction *instr) {
7546   const char *mnemonic = "unimplemented";
7547   const char *form = "(SVELoadMultipleStructures_ScalarPlusScalar)";
7548 
7549   const char *form_2 = "{'Zt.'tmsz, 'Zt2.'tmsz}, 'Pgl/z, ['Xns, 'Xm'NSveS]";
7550   const char *form_3 =
7551       "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}, 'Pgl/z, ['Xns, 'Xm'NSveS]";
7552   const char *form_4 =
7553       "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}, "
7554       "'Pgl/z, ['Xns, 'Xm'NSveS]";
7555 
7556   switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
7557     case LD2B_z_p_br_contiguous:
7558       mnemonic = "ld2b";
7559       form = form_2;
7560       break;
7561     case LD2D_z_p_br_contiguous:
7562       mnemonic = "ld2d";
7563       form = form_2;
7564       break;
7565     case LD2H_z_p_br_contiguous:
7566       mnemonic = "ld2h";
7567       form = form_2;
7568       break;
7569     case LD2W_z_p_br_contiguous:
7570       mnemonic = "ld2w";
7571       form = form_2;
7572       break;
7573     case LD3B_z_p_br_contiguous:
7574       mnemonic = "ld3b";
7575       form = form_3;
7576       break;
7577     case LD3D_z_p_br_contiguous:
7578       mnemonic = "ld3d";
7579       form = form_3;
7580       break;
7581     case LD3H_z_p_br_contiguous:
7582       mnemonic = "ld3h";
7583       form = form_3;
7584       break;
7585     case LD3W_z_p_br_contiguous:
7586       mnemonic = "ld3w";
7587       form = form_3;
7588       break;
7589     case LD4B_z_p_br_contiguous:
7590       mnemonic = "ld4b";
7591       form = form_4;
7592       break;
7593     case LD4D_z_p_br_contiguous:
7594       mnemonic = "ld4d";
7595       form = form_4;
7596       break;
7597     case LD4H_z_p_br_contiguous:
7598       mnemonic = "ld4h";
7599       form = form_4;
7600       break;
7601     case LD4W_z_p_br_contiguous:
7602       mnemonic = "ld4w";
7603       form = form_4;
7604       break;
7605     default:
7606       break;
7607   }
7608   Format(instr, mnemonic, form);
7609 }
7610 
VisitSVELoadPredicateRegister(const Instruction * instr)7611 void Disassembler::VisitSVELoadPredicateRegister(const Instruction *instr) {
7612   const char *mnemonic = "unimplemented";
7613   const char *form = "(SVELoadPredicateRegister)";
7614 
7615   switch (instr->Mask(SVELoadPredicateRegisterMask)) {
7616     case LDR_p_bi:
7617       mnemonic = "ldr";
7618       if (instr->Mask(0x003f1c00) == 0) {
7619         form = "'Pd, ['Xns]";
7620       } else {
7621         form = "'Pd, ['Xns, #'s2116:1210, mul vl]";
7622       }
7623       break;
7624     default:
7625       break;
7626   }
7627   Format(instr, mnemonic, form);
7628 }
7629 
VisitSVELoadVectorRegister(const Instruction * instr)7630 void Disassembler::VisitSVELoadVectorRegister(const Instruction *instr) {
7631   const char *mnemonic = "unimplemented";
7632   const char *form = "(SVELoadVectorRegister)";
7633 
7634   switch (instr->Mask(SVELoadVectorRegisterMask)) {
7635     case LDR_z_bi:
7636       mnemonic = "ldr";
7637       if (instr->Mask(0x003f1c00) == 0) {
7638         form = "'Zd, ['Xns]";
7639       } else {
7640         form = "'Zt, ['Xns, #'s2116:1210, mul vl]";
7641       }
7642       break;
7643     default:
7644       break;
7645   }
7646   Format(instr, mnemonic, form);
7647 }
7648 
VisitSVEPartitionBreakCondition(const Instruction * instr)7649 void Disassembler::VisitSVEPartitionBreakCondition(const Instruction *instr) {
7650   const char *mnemonic = "unimplemented";
7651   const char *form = "'Pd.b, p'u1310/'?04:mz, 'Pn.b";
7652 
7653   switch (instr->Mask(SVEPartitionBreakConditionMask)) {
7654     case BRKAS_p_p_p_z:
7655       mnemonic = "brkas";
7656       break;
7657     case BRKA_p_p_p:
7658       mnemonic = "brka";
7659       break;
7660     case BRKBS_p_p_p_z:
7661       mnemonic = "brkbs";
7662       break;
7663     case BRKB_p_p_p:
7664       mnemonic = "brkb";
7665       break;
7666     default:
7667       form = "(SVEPartitionBreakCondition)";
7668       break;
7669   }
7670   Format(instr, mnemonic, form);
7671 }
7672 
VisitSVEPermutePredicateElements(const Instruction * instr)7673 void Disassembler::VisitSVEPermutePredicateElements(const Instruction *instr) {
7674   const char *mnemonic = "unimplemented";
7675   const char *form = "'Pd.'t, 'Pn.'t, 'Pm.'t";
7676 
7677   switch (instr->Mask(SVEPermutePredicateElementsMask)) {
7678     case TRN1_p_pp:
7679       mnemonic = "trn1";
7680       break;
7681     case TRN2_p_pp:
7682       mnemonic = "trn2";
7683       break;
7684     case UZP1_p_pp:
7685       mnemonic = "uzp1";
7686       break;
7687     case UZP2_p_pp:
7688       mnemonic = "uzp2";
7689       break;
7690     case ZIP1_p_pp:
7691       mnemonic = "zip1";
7692       break;
7693     case ZIP2_p_pp:
7694       mnemonic = "zip2";
7695       break;
7696     default:
7697       break;
7698   }
7699   Format(instr, mnemonic, form);
7700 }
7701 
VisitSVEPredicateFirstActive(const Instruction * instr)7702 void Disassembler::VisitSVEPredicateFirstActive(const Instruction *instr) {
7703   const char *mnemonic = "unimplemented";
7704   const char *form = "(SVEPredicateFirstActive)";
7705 
7706   switch (instr->Mask(SVEPredicateFirstActiveMask)) {
7707     case PFIRST_p_p_p:
7708       mnemonic = "pfirst";
7709       form = "'Pd.b, 'Pn, 'Pd.b";
7710       break;
7711     default:
7712       break;
7713   }
7714   Format(instr, mnemonic, form);
7715 }
7716 
VisitSVEPredicateReadFromFFR_Unpredicated(const Instruction * instr)7717 void Disassembler::VisitSVEPredicateReadFromFFR_Unpredicated(
7718     const Instruction *instr) {
7719   const char *mnemonic = "unimplemented";
7720   const char *form = "(SVEPredicateReadFromFFR_Unpredicated)";
7721 
7722   switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
7723     case RDFFR_p_f:
7724       mnemonic = "rdffr";
7725       form = "'Pd.b";
7726       break;
7727     default:
7728       break;
7729   }
7730   Format(instr, mnemonic, form);
7731 }
7732 
VisitSVEPredicateTest(const Instruction * instr)7733 void Disassembler::VisitSVEPredicateTest(const Instruction *instr) {
7734   const char *mnemonic = "unimplemented";
7735   const char *form = "(SVEPredicateTest)";
7736 
7737   switch (instr->Mask(SVEPredicateTestMask)) {
7738     case PTEST_p_p:
7739       mnemonic = "ptest";
7740       form = "p'u1310, 'Pn.b";
7741       break;
7742     default:
7743       break;
7744   }
7745   Format(instr, mnemonic, form);
7746 }
7747 
VisitSVEPredicateZero(const Instruction * instr)7748 void Disassembler::VisitSVEPredicateZero(const Instruction *instr) {
7749   const char *mnemonic = "unimplemented";
7750   const char *form = "(SVEPredicateZero)";
7751 
7752   switch (instr->Mask(SVEPredicateZeroMask)) {
7753     case PFALSE_p:
7754       mnemonic = "pfalse";
7755       form = "'Pd.b";
7756       break;
7757     default:
7758       break;
7759   }
7760   Format(instr, mnemonic, form);
7761 }
7762 
VisitSVEPropagateBreakToNextPartition(const Instruction * instr)7763 void Disassembler::VisitSVEPropagateBreakToNextPartition(
7764     const Instruction *instr) {
7765   const char *mnemonic = "unimplemented";
7766   const char *form = "'Pd.b, p'u1310/z, 'Pn.b, 'Pd.b";
7767 
7768   switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
7769     case BRKNS_p_p_pp:
7770       mnemonic = "brkns";
7771       break;
7772     case BRKN_p_p_pp:
7773       mnemonic = "brkn";
7774       break;
7775     default:
7776       break;
7777   }
7778   Format(instr, mnemonic, form);
7779 }
7780 
VisitSVEReversePredicateElements(const Instruction * instr)7781 void Disassembler::VisitSVEReversePredicateElements(const Instruction *instr) {
7782   const char *mnemonic = "unimplemented";
7783   const char *form = "(SVEReversePredicateElements)";
7784 
7785   switch (instr->Mask(SVEReversePredicateElementsMask)) {
7786     case REV_p_p:
7787       mnemonic = "rev";
7788       form = "'Pd.'t, 'Pn.'t";
7789       break;
7790     default:
7791       break;
7792   }
7793   Format(instr, mnemonic, form);
7794 }
7795 
VisitSVEReverseVectorElements(const Instruction * instr)7796 void Disassembler::VisitSVEReverseVectorElements(const Instruction *instr) {
7797   const char *mnemonic = "unimplemented";
7798   const char *form = "(SVEReverseVectorElements)";
7799 
7800   switch (instr->Mask(SVEReverseVectorElementsMask)) {
7801     case REV_z_z:
7802       mnemonic = "rev";
7803       form = "'Zd.'t, 'Zn.'t";
7804       break;
7805     default:
7806       break;
7807   }
7808   Format(instr, mnemonic, form);
7809 }
7810 
VisitSVEReverseWithinElements(const Instruction * instr)7811 void Disassembler::VisitSVEReverseWithinElements(const Instruction *instr) {
7812   const char *mnemonic = "unimplemented";
7813   const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t";
7814 
7815   unsigned size = instr->GetSVESize();
7816   switch (instr->Mask(SVEReverseWithinElementsMask)) {
7817     case RBIT_z_p_z:
7818       mnemonic = "rbit";
7819       break;
7820     case REVB_z_z:
7821       if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) ||
7822           (size == kDRegSizeInBytesLog2)) {
7823         mnemonic = "revb";
7824       } else {
7825         form = "(SVEReverseWithinElements)";
7826       }
7827       break;
7828     case REVH_z_z:
7829       if ((size == kSRegSizeInBytesLog2) || (size == kDRegSizeInBytesLog2)) {
7830         mnemonic = "revh";
7831       } else {
7832         form = "(SVEReverseWithinElements)";
7833       }
7834       break;
7835     case REVW_z_z:
7836       if (size == kDRegSizeInBytesLog2) {
7837         mnemonic = "revw";
7838       } else {
7839         form = "(SVEReverseWithinElements)";
7840       }
7841       break;
7842     default:
7843       break;
7844   }
7845   Format(instr, mnemonic, form);
7846 }
7847 
VisitSVESaturatingIncDecRegisterByElementCount(const Instruction * instr)7848 void Disassembler::VisitSVESaturatingIncDecRegisterByElementCount(
7849     const Instruction *instr) {
7850   const char *mnemonic = "unimplemented";
7851   const char *form = IncDecFormHelper(instr,
7852                                       "'R20d, 'Ipc, mul #'u1916+1",
7853                                       "'R20d, 'Ipc",
7854                                       "'R20d");
7855   const char *form_sx = IncDecFormHelper(instr,
7856                                          "'Xd, 'Wd, 'Ipc, mul #'u1916+1",
7857                                          "'Xd, 'Wd, 'Ipc",
7858                                          "'Xd, 'Wd");
7859 
7860   switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {
7861     case SQDECB_r_rs_sx:
7862       mnemonic = "sqdecb";
7863       form = form_sx;
7864       break;
7865     case SQDECD_r_rs_sx:
7866       mnemonic = "sqdecd";
7867       form = form_sx;
7868       break;
7869     case SQDECH_r_rs_sx:
7870       mnemonic = "sqdech";
7871       form = form_sx;
7872       break;
7873     case SQDECW_r_rs_sx:
7874       mnemonic = "sqdecw";
7875       form = form_sx;
7876       break;
7877     case SQINCB_r_rs_sx:
7878       mnemonic = "sqincb";
7879       form = form_sx;
7880       break;
7881     case SQINCD_r_rs_sx:
7882       mnemonic = "sqincd";
7883       form = form_sx;
7884       break;
7885     case SQINCH_r_rs_sx:
7886       mnemonic = "sqinch";
7887       form = form_sx;
7888       break;
7889     case SQINCW_r_rs_sx:
7890       mnemonic = "sqincw";
7891       form = form_sx;
7892       break;
7893     case SQDECB_r_rs_x:
7894       mnemonic = "sqdecb";
7895       break;
7896     case SQDECD_r_rs_x:
7897       mnemonic = "sqdecd";
7898       break;
7899     case SQDECH_r_rs_x:
7900       mnemonic = "sqdech";
7901       break;
7902     case SQDECW_r_rs_x:
7903       mnemonic = "sqdecw";
7904       break;
7905     case SQINCB_r_rs_x:
7906       mnemonic = "sqincb";
7907       break;
7908     case SQINCD_r_rs_x:
7909       mnemonic = "sqincd";
7910       break;
7911     case SQINCH_r_rs_x:
7912       mnemonic = "sqinch";
7913       break;
7914     case SQINCW_r_rs_x:
7915       mnemonic = "sqincw";
7916       break;
7917     case UQDECB_r_rs_uw:
7918     case UQDECB_r_rs_x:
7919       mnemonic = "uqdecb";
7920       break;
7921     case UQDECD_r_rs_uw:
7922     case UQDECD_r_rs_x:
7923       mnemonic = "uqdecd";
7924       break;
7925     case UQDECH_r_rs_uw:
7926     case UQDECH_r_rs_x:
7927       mnemonic = "uqdech";
7928       break;
7929     case UQDECW_r_rs_uw:
7930     case UQDECW_r_rs_x:
7931       mnemonic = "uqdecw";
7932       break;
7933     case UQINCB_r_rs_uw:
7934     case UQINCB_r_rs_x:
7935       mnemonic = "uqincb";
7936       break;
7937     case UQINCD_r_rs_uw:
7938     case UQINCD_r_rs_x:
7939       mnemonic = "uqincd";
7940       break;
7941     case UQINCH_r_rs_uw:
7942     case UQINCH_r_rs_x:
7943       mnemonic = "uqinch";
7944       break;
7945     case UQINCW_r_rs_uw:
7946     case UQINCW_r_rs_x:
7947       mnemonic = "uqincw";
7948       break;
7949     default:
7950       break;
7951   }
7952   Format(instr, mnemonic, form);
7953 }
7954 
VisitSVESaturatingIncDecVectorByElementCount(const Instruction * instr)7955 void Disassembler::VisitSVESaturatingIncDecVectorByElementCount(
7956     const Instruction *instr) {
7957   const char *mnemonic = "unimplemented";
7958   const char *form = IncDecFormHelper(instr,
7959                                       "'Zd.'t, 'Ipc, mul #'u1916+1",
7960                                       "'Zd.'t, 'Ipc",
7961                                       "'Zd.'t");
7962 
7963   switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {
7964     case SQDECD_z_zs:
7965       mnemonic = "sqdecd";
7966       break;
7967     case SQDECH_z_zs:
7968       mnemonic = "sqdech";
7969       break;
7970     case SQDECW_z_zs:
7971       mnemonic = "sqdecw";
7972       break;
7973     case SQINCD_z_zs:
7974       mnemonic = "sqincd";
7975       break;
7976     case SQINCH_z_zs:
7977       mnemonic = "sqinch";
7978       break;
7979     case SQINCW_z_zs:
7980       mnemonic = "sqincw";
7981       break;
7982     case UQDECD_z_zs:
7983       mnemonic = "uqdecd";
7984       break;
7985     case UQDECH_z_zs:
7986       mnemonic = "uqdech";
7987       break;
7988     case UQDECW_z_zs:
7989       mnemonic = "uqdecw";
7990       break;
7991     case UQINCD_z_zs:
7992       mnemonic = "uqincd";
7993       break;
7994     case UQINCH_z_zs:
7995       mnemonic = "uqinch";
7996       break;
7997     case UQINCW_z_zs:
7998       mnemonic = "uqincw";
7999       break;
8000     default:
8001       form = "(SVEElementCount)";
8002       break;
8003   }
8004   Format(instr, mnemonic, form);
8005 }
8006 
VisitSVEStoreMultipleStructures_ScalarPlusImm(const Instruction * instr)8007 void Disassembler::VisitSVEStoreMultipleStructures_ScalarPlusImm(
8008     const Instruction *instr) {
8009   const char *mnemonic = "unimplemented";
8010   const char *form = "(SVEStoreMultipleStructures_ScalarPlusImm)";
8011 
8012   const char *form_2 = "{'Zt.'tmsz, 'Zt2.'tmsz}, 'Pgl, ['Xns'ISveSvl]";
8013   const char *form_3 =
8014       "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}, 'Pgl, ['Xns'ISveSvl]";
8015   const char *form_4 =
8016       "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}, "
8017       "'Pgl, ['Xns'ISveSvl]";
8018 
8019   switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
8020     case ST2B_z_p_bi_contiguous:
8021       mnemonic = "st2b";
8022       form = form_2;
8023       break;
8024     case ST2H_z_p_bi_contiguous:
8025       mnemonic = "st2h";
8026       form = form_2;
8027       break;
8028     case ST2W_z_p_bi_contiguous:
8029       mnemonic = "st2w";
8030       form = form_2;
8031       break;
8032     case ST2D_z_p_bi_contiguous:
8033       mnemonic = "st2d";
8034       form = form_2;
8035       break;
8036     case ST3B_z_p_bi_contiguous:
8037       mnemonic = "st3b";
8038       form = form_3;
8039       break;
8040     case ST3H_z_p_bi_contiguous:
8041       mnemonic = "st3h";
8042       form = form_3;
8043       break;
8044     case ST3W_z_p_bi_contiguous:
8045       mnemonic = "st3w";
8046       form = form_3;
8047       break;
8048     case ST3D_z_p_bi_contiguous:
8049       mnemonic = "st3d";
8050       form = form_3;
8051       break;
8052     case ST4B_z_p_bi_contiguous:
8053       mnemonic = "st4b";
8054       form = form_4;
8055       break;
8056     case ST4H_z_p_bi_contiguous:
8057       mnemonic = "st4h";
8058       form = form_4;
8059       break;
8060     case ST4W_z_p_bi_contiguous:
8061       mnemonic = "st4w";
8062       form = form_4;
8063       break;
8064     case ST4D_z_p_bi_contiguous:
8065       mnemonic = "st4d";
8066       form = form_4;
8067       break;
8068     default:
8069       break;
8070   }
8071   Format(instr, mnemonic, form);
8072 }
8073 
VisitSVEStoreMultipleStructures_ScalarPlusScalar(const Instruction * instr)8074 void Disassembler::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
8075     const Instruction *instr) {
8076   const char *mnemonic = "unimplemented";
8077   const char *form = "(SVEStoreMultipleStructures_ScalarPlusScalar)";
8078 
8079   const char *form_2 = "{'Zt.'tmsz, 'Zt2.'tmsz}, 'Pgl, ['Xns, 'Xm'NSveS]";
8080   const char *form_3 =
8081       "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}, 'Pgl, ['Xns, 'Xm'NSveS]";
8082   const char *form_4 =
8083       "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}, "
8084       "'Pgl, ['Xns, 'Xm'NSveS]";
8085 
8086   switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
8087     case ST2B_z_p_br_contiguous:
8088       mnemonic = "st2b";
8089       form = form_2;
8090       break;
8091     case ST2D_z_p_br_contiguous:
8092       mnemonic = "st2d";
8093       form = form_2;
8094       break;
8095     case ST2H_z_p_br_contiguous:
8096       mnemonic = "st2h";
8097       form = form_2;
8098       break;
8099     case ST2W_z_p_br_contiguous:
8100       mnemonic = "st2w";
8101       form = form_2;
8102       break;
8103     case ST3B_z_p_br_contiguous:
8104       mnemonic = "st3b";
8105       form = form_3;
8106       break;
8107     case ST3D_z_p_br_contiguous:
8108       mnemonic = "st3d";
8109       form = form_3;
8110       break;
8111     case ST3H_z_p_br_contiguous:
8112       mnemonic = "st3h";
8113       form = form_3;
8114       break;
8115     case ST3W_z_p_br_contiguous:
8116       mnemonic = "st3w";
8117       form = form_3;
8118       break;
8119     case ST4B_z_p_br_contiguous:
8120       mnemonic = "st4b";
8121       form = form_4;
8122       break;
8123     case ST4D_z_p_br_contiguous:
8124       mnemonic = "st4d";
8125       form = form_4;
8126       break;
8127     case ST4H_z_p_br_contiguous:
8128       mnemonic = "st4h";
8129       form = form_4;
8130       break;
8131     case ST4W_z_p_br_contiguous:
8132       mnemonic = "st4w";
8133       form = form_4;
8134       break;
8135     default:
8136       break;
8137   }
8138   Format(instr, mnemonic, form);
8139 }
8140 
VisitSVEStorePredicateRegister(const Instruction * instr)8141 void Disassembler::VisitSVEStorePredicateRegister(const Instruction *instr) {
8142   const char *mnemonic = "unimplemented";
8143   const char *form = "(SVEStorePredicateRegister)";
8144 
8145   switch (instr->Mask(SVEStorePredicateRegisterMask)) {
8146     case STR_p_bi:
8147       mnemonic = "str";
8148       if (instr->Mask(0x003f1c00) == 0) {
8149         form = "'Pd, ['Xns]";
8150       } else {
8151         form = "'Pd, ['Xns, #'s2116:1210, mul vl]";
8152       }
8153       break;
8154     default:
8155       break;
8156   }
8157   Format(instr, mnemonic, form);
8158 }
8159 
VisitSVEStoreVectorRegister(const Instruction * instr)8160 void Disassembler::VisitSVEStoreVectorRegister(const Instruction *instr) {
8161   const char *mnemonic = "unimplemented";
8162   const char *form = "(SVEStoreVectorRegister)";
8163 
8164   switch (instr->Mask(SVEStoreVectorRegisterMask)) {
8165     case STR_z_bi:
8166       mnemonic = "str";
8167       if (instr->Mask(0x003f1c00) == 0) {
8168         form = "'Zd, ['Xns]";
8169       } else {
8170         form = "'Zt, ['Xns, #'s2116:1210, mul vl]";
8171       }
8172       break;
8173     default:
8174       break;
8175   }
8176   Format(instr, mnemonic, form);
8177 }
8178 
VisitSVETableLookup(const Instruction * instr)8179 void Disassembler::VisitSVETableLookup(const Instruction *instr) {
8180   const char *mnemonic = "unimplemented";
8181   const char *form = "(SVETableLookup)";
8182 
8183   switch (instr->Mask(SVETableLookupMask)) {
8184     case TBL_z_zz_1:
8185       mnemonic = "tbl";
8186       form = "'Zd.'t, {'Zn.'t}, 'Zm.'t";
8187       break;
8188     default:
8189       break;
8190   }
8191   Format(instr, mnemonic, form);
8192 }
8193 
VisitSVEUnpackPredicateElements(const Instruction * instr)8194 void Disassembler::VisitSVEUnpackPredicateElements(const Instruction *instr) {
8195   const char *mnemonic = "unimplemented";
8196   const char *form = "'Pd.h, 'Pn.b";
8197 
8198   switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
8199     case PUNPKHI_p_p:
8200       mnemonic = "punpkhi";
8201       break;
8202     case PUNPKLO_p_p:
8203       mnemonic = "punpklo";
8204       break;
8205     default:
8206       break;
8207   }
8208   Format(instr, mnemonic, form);
8209 }
8210 
VisitSVEUnpackVectorElements(const Instruction * instr)8211 void Disassembler::VisitSVEUnpackVectorElements(const Instruction *instr) {
8212   const char *mnemonic = "unimplemented";
8213   const char *form = "'Zd.'t, 'Zn.'th";
8214 
8215   if (instr->GetSVESize() == 0) {
8216     // The lowest lane size of the destination vector is H-sized lane.
8217     Format(instr, "unallocated", "(SVEUnpackVectorElements)");
8218     return;
8219   }
8220 
8221   switch (instr->Mask(SVEUnpackVectorElementsMask)) {
8222     case SUNPKHI_z_z:
8223       mnemonic = "sunpkhi";
8224       break;
8225     case SUNPKLO_z_z:
8226       mnemonic = "sunpklo";
8227       break;
8228     case UUNPKHI_z_z:
8229       mnemonic = "uunpkhi";
8230       break;
8231     case UUNPKLO_z_z:
8232       mnemonic = "uunpklo";
8233       break;
8234     default:
8235       break;
8236   }
8237   Format(instr, mnemonic, form);
8238 }
8239 
VisitSVEVectorSplice_Destructive(const Instruction * instr)8240 void Disassembler::VisitSVEVectorSplice_Destructive(const Instruction *instr) {
8241   const char *mnemonic = "unimplemented";
8242   const char *form = "(SVEVectorSplice_Destructive)";
8243 
8244   switch (instr->Mask(SVEVectorSplice_DestructiveMask)) {
8245     case SPLICE_z_p_zz_des:
8246       mnemonic = "splice";
8247       form = "'Zd.'t, 'Pgl, 'Zd.'t, 'Zn.'t";
8248       break;
8249     default:
8250       break;
8251   }
8252   Format(instr, mnemonic, form);
8253 }
8254 
VisitSVEAddressGeneration(const Instruction * instr)8255 void Disassembler::VisitSVEAddressGeneration(const Instruction *instr) {
8256   const char *mnemonic = "adr";
8257   const char *form = "'Zd.d, ['Zn.d, 'Zm.d";
8258   const char *suffix = NULL;
8259 
8260   bool msz_is_zero = (instr->ExtractBits(11, 10) == 0);
8261 
8262   switch (instr->Mask(SVEAddressGenerationMask)) {
8263     case ADR_z_az_d_s32_scaled:
8264       suffix = msz_is_zero ? ", sxtw]" : ", sxtw #'u1110]";
8265       break;
8266     case ADR_z_az_d_u32_scaled:
8267       suffix = msz_is_zero ? ", uxtw]" : ", uxtw #'u1110]";
8268       break;
8269     case ADR_z_az_s_same_scaled:
8270     case ADR_z_az_d_same_scaled:
8271       form = "'Zd.'t, ['Zn.'t, 'Zm.'t";
8272       suffix = msz_is_zero ? "]" : ", lsl #'u1110]";
8273       break;
8274     default:
8275       mnemonic = "unimplemented";
8276       form = "(SVEAddressGeneration)";
8277       break;
8278   }
8279   Format(instr, mnemonic, form, suffix);
8280 }
8281 
VisitSVEBitwiseLogicalUnpredicated(const Instruction * instr)8282 void Disassembler::VisitSVEBitwiseLogicalUnpredicated(
8283     const Instruction *instr) {
8284   const char *mnemonic = "unimplemented";
8285   const char *form = "'Zd.d, 'Zn.d, 'Zm.d";
8286 
8287   switch (instr->Mask(SVEBitwiseLogicalUnpredicatedMask)) {
8288     case AND_z_zz:
8289       mnemonic = "and";
8290       break;
8291     case BIC_z_zz:
8292       mnemonic = "bic";
8293       break;
8294     case EOR_z_zz:
8295       mnemonic = "eor";
8296       break;
8297     case ORR_z_zz:
8298       mnemonic = "orr";
8299       if (instr->GetRn() == instr->GetRm()) {
8300         mnemonic = "mov";
8301         form = "'Zd.d, 'Zn.d";
8302       }
8303       break;
8304     default:
8305       break;
8306   }
8307   Format(instr, mnemonic, form);
8308 }
8309 
VisitSVEBitwiseShiftUnpredicated(const Instruction * instr)8310 void Disassembler::VisitSVEBitwiseShiftUnpredicated(const Instruction *instr) {
8311   const char *mnemonic = "unimplemented";
8312   const char *form = "(SVEBitwiseShiftUnpredicated)";
8313   unsigned tsize =
8314       (instr->ExtractBits(23, 22) << 2) | instr->ExtractBits(20, 19);
8315   unsigned lane_size = instr->GetSVESize();
8316 
8317   switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
8318     case ASR_z_zi:
8319       if (tsize != 0) {
8320         // The tsz field must not be zero.
8321         mnemonic = "asr";
8322         form = "'Zd.'tszs, 'Zn.'tszs, 'ITriSves";
8323       }
8324       break;
8325     case ASR_z_zw:
8326       if (lane_size <= kSRegSizeInBytesLog2) {
8327         mnemonic = "asr";
8328         form = "'Zd.'t, 'Zn.'t, 'Zm.d";
8329       }
8330       break;
8331     case LSL_z_zi:
8332       if (tsize != 0) {
8333         // The tsz field must not be zero.
8334         mnemonic = "lsl";
8335         form = "'Zd.'tszs, 'Zn.'tszs, 'ITriSver";
8336       }
8337       break;
8338     case LSL_z_zw:
8339       if (lane_size <= kSRegSizeInBytesLog2) {
8340         mnemonic = "lsl";
8341         form = "'Zd.'t, 'Zn.'t, 'Zm.d";
8342       }
8343       break;
8344     case LSR_z_zi:
8345       if (tsize != 0) {
8346         // The tsz field must not be zero.
8347         mnemonic = "lsr";
8348         form = "'Zd.'tszs, 'Zn.'tszs, 'ITriSves";
8349       }
8350       break;
8351     case LSR_z_zw:
8352       if (lane_size <= kSRegSizeInBytesLog2) {
8353         mnemonic = "lsr";
8354         form = "'Zd.'t, 'Zn.'t, 'Zm.d";
8355       }
8356       break;
8357     default:
8358       break;
8359   }
8360 
8361   Format(instr, mnemonic, form);
8362 }
8363 
VisitSVEElementCount(const Instruction * instr)8364 void Disassembler::VisitSVEElementCount(const Instruction *instr) {
8365   const char *mnemonic = "unimplemented";
8366   const char *form =
8367       IncDecFormHelper(instr, "'Xd, 'Ipc, mul #'u1916+1", "'Xd, 'Ipc", "'Xd");
8368 
8369   switch (instr->Mask(SVEElementCountMask)) {
8370     case CNTB_r_s:
8371       mnemonic = "cntb";
8372       break;
8373     case CNTD_r_s:
8374       mnemonic = "cntd";
8375       break;
8376     case CNTH_r_s:
8377       mnemonic = "cnth";
8378       break;
8379     case CNTW_r_s:
8380       mnemonic = "cntw";
8381       break;
8382     default:
8383       break;
8384   }
8385   Format(instr, mnemonic, form);
8386 }
8387 
VisitSVEFPAccumulatingReduction(const Instruction * instr)8388 void Disassembler::VisitSVEFPAccumulatingReduction(const Instruction *instr) {
8389   const char *mnemonic = "unimplemented";
8390   const char *form = "(SVEFPAccumulatingReduction)";
8391 
8392   switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
8393     case FADDA_v_p_z:
8394       mnemonic = "fadda";
8395       form = "'t'u0400, 'Pgl, 't'u0400, 'Zn.'t";
8396       break;
8397     default:
8398       break;
8399   }
8400   Format(instr, mnemonic, form);
8401 }
8402 
VisitSVEFPArithmeticUnpredicated(const Instruction * instr)8403 void Disassembler::VisitSVEFPArithmeticUnpredicated(const Instruction *instr) {
8404   const char *mnemonic = "unimplemented";
8405   const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t";
8406 
8407   switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
8408     case FADD_z_zz:
8409       mnemonic = "fadd";
8410       break;
8411     case FMUL_z_zz:
8412       mnemonic = "fmul";
8413       break;
8414     case FRECPS_z_zz:
8415       mnemonic = "frecps";
8416       break;
8417     case FRSQRTS_z_zz:
8418       mnemonic = "frsqrts";
8419       break;
8420     case FSUB_z_zz:
8421       mnemonic = "fsub";
8422       break;
8423     case FTSMUL_z_zz:
8424       mnemonic = "ftsmul";
8425       break;
8426     default:
8427       break;
8428   }
8429   Format(instr, mnemonic, form);
8430 }
8431 
VisitSVEFPCompareVectors(const Instruction * instr)8432 void Disassembler::VisitSVEFPCompareVectors(const Instruction *instr) {
8433   const char *mnemonic = "unimplemented";
8434   const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8435 
8436   switch (instr->Mask(SVEFPCompareVectorsMask)) {
8437     case FACGE_p_p_zz:
8438       mnemonic = "facge";
8439       break;
8440     case FACGT_p_p_zz:
8441       mnemonic = "facgt";
8442       break;
8443     case FCMEQ_p_p_zz:
8444       mnemonic = "fcmeq";
8445       break;
8446     case FCMGE_p_p_zz:
8447       mnemonic = "fcmge";
8448       break;
8449     case FCMGT_p_p_zz:
8450       mnemonic = "fcmgt";
8451       break;
8452     case FCMNE_p_p_zz:
8453       mnemonic = "fcmne";
8454       break;
8455     case FCMUO_p_p_zz:
8456       mnemonic = "fcmuo";
8457       break;
8458     default:
8459       break;
8460   }
8461   Format(instr, mnemonic, form);
8462 }
8463 
VisitSVEFPCompareWithZero(const Instruction * instr)8464 void Disassembler::VisitSVEFPCompareWithZero(const Instruction *instr) {
8465   const char *mnemonic = "unimplemented";
8466   const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, #0.0";
8467 
8468   switch (instr->Mask(SVEFPCompareWithZeroMask)) {
8469     case FCMEQ_p_p_z0:
8470       mnemonic = "fcmeq";
8471       break;
8472     case FCMGE_p_p_z0:
8473       mnemonic = "fcmge";
8474       break;
8475     case FCMGT_p_p_z0:
8476       mnemonic = "fcmgt";
8477       break;
8478     case FCMLE_p_p_z0:
8479       mnemonic = "fcmle";
8480       break;
8481     case FCMLT_p_p_z0:
8482       mnemonic = "fcmlt";
8483       break;
8484     case FCMNE_p_p_z0:
8485       mnemonic = "fcmne";
8486       break;
8487     default:
8488       break;
8489   }
8490   Format(instr, mnemonic, form);
8491 }
8492 
VisitSVEFPComplexAddition(const Instruction * instr)8493 void Disassembler::VisitSVEFPComplexAddition(const Instruction *instr) {
8494   const char *mnemonic = "unimplemented";
8495   const char *form = "(SVEFPComplexAddition)";
8496 
8497   switch (instr->Mask(SVEFPComplexAdditionMask)) {
8498     case FCADD_z_p_zz:
8499       mnemonic = "fcadd";
8500       if (instr->ExtractBit(16) == 0) {
8501         form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t, #90";
8502       } else {
8503         form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t, #270";
8504       }
8505       break;
8506     default:
8507       break;
8508   }
8509   Format(instr, mnemonic, form);
8510 }
8511 
VisitSVEFPComplexMulAdd(const Instruction * instr)8512 void Disassembler::VisitSVEFPComplexMulAdd(const Instruction *instr) {
8513   const char *mnemonic = "unimplemented";
8514   const char *form = "(SVEFPComplexMulAdd)";
8515   const char *suffix = NULL;
8516 
8517   const char *fcmla_constants[] = {"0", "90", "180", "270"};
8518 
8519   switch (instr->Mask(SVEFPComplexMulAddMask)) {
8520     case FCMLA_z_p_zzz:
8521       mnemonic = "fcmla";
8522       form = "'Zd.'t, 'Pgl/m, 'Zn.'t, 'Zm.'t, #";
8523       suffix = fcmla_constants[instr->ExtractBits(14, 13)];
8524       break;
8525     default:
8526       break;
8527   }
8528   Format(instr, mnemonic, form, suffix);
8529 }
8530 
VisitSVEFPComplexMulAddIndex(const Instruction * instr)8531 void Disassembler::VisitSVEFPComplexMulAddIndex(const Instruction *instr) {
8532   const char *mnemonic = "unimplemented";
8533   const char *form = "(SVEFPComplexMulAddIndex)";
8534 
8535   const char *fcmla_constants[] = {"0", "90", "180", "270"};
8536   const char *suffix = fcmla_constants[instr->ExtractBits(11, 10)];
8537 
8538   switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
8539     case FCMLA_z_zzzi_h:
8540       mnemonic = "fcmla";
8541       form = "'Zd.h, 'Zn.h, z'u1816.h['u2019], #";
8542       break;
8543     case FCMLA_z_zzzi_s:
8544       mnemonic = "fcmla";
8545       form = "'Zd.s, 'Zn.s, z'u1916.s['u2020], #";
8546       break;
8547     default:
8548       suffix = NULL;
8549       break;
8550   }
8551   Format(instr, mnemonic, form, suffix);
8552 }
8553 
VisitSVEFPFastReduction(const Instruction * instr)8554 void Disassembler::VisitSVEFPFastReduction(const Instruction *instr) {
8555   const char *mnemonic = "unimplemented";
8556   const char *form = "'t'u0400, 'Pgl, 'Zn.'t";
8557 
8558   switch (instr->Mask(SVEFPFastReductionMask)) {
8559     case FADDV_v_p_z:
8560       mnemonic = "faddv";
8561       break;
8562     case FMAXNMV_v_p_z:
8563       mnemonic = "fmaxnmv";
8564       break;
8565     case FMAXV_v_p_z:
8566       mnemonic = "fmaxv";
8567       break;
8568     case FMINNMV_v_p_z:
8569       mnemonic = "fminnmv";
8570       break;
8571     case FMINV_v_p_z:
8572       mnemonic = "fminv";
8573       break;
8574     default:
8575       break;
8576   }
8577   Format(instr, mnemonic, form);
8578 }
8579 
VisitSVEFPMulIndex(const Instruction * instr)8580 void Disassembler::VisitSVEFPMulIndex(const Instruction *instr) {
8581   const char *mnemonic = "unimplemented";
8582   const char *form = "(SVEFPMulIndex)";
8583 
8584   switch (instr->Mask(SVEFPMulIndexMask)) {
8585     case FMUL_z_zzi_d:
8586       mnemonic = "fmul";
8587       form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]";
8588       break;
8589     case FMUL_z_zzi_h:
8590     case FMUL_z_zzi_h_i3h:
8591       mnemonic = "fmul";
8592       form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]";
8593       break;
8594     case FMUL_z_zzi_s:
8595       mnemonic = "fmul";
8596       form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]";
8597       break;
8598     default:
8599       break;
8600   }
8601   Format(instr, mnemonic, form);
8602 }
8603 
VisitSVEFPMulAdd(const Instruction * instr)8604 void Disassembler::VisitSVEFPMulAdd(const Instruction *instr) {
8605   const char *mnemonic = "unimplemented";
8606   const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t, 'Zm.'t";
8607 
8608   switch (instr->Mask(SVEFPMulAddMask)) {
8609     case FMAD_z_p_zzz:
8610       mnemonic = "fmad";
8611       break;
8612     case FMLA_z_p_zzz:
8613       mnemonic = "fmla";
8614       break;
8615     case FMLS_z_p_zzz:
8616       mnemonic = "fmls";
8617       break;
8618     case FMSB_z_p_zzz:
8619       mnemonic = "fmsb";
8620       break;
8621     case FNMAD_z_p_zzz:
8622       mnemonic = "fnmad";
8623       break;
8624     case FNMLA_z_p_zzz:
8625       mnemonic = "fnmla";
8626       break;
8627     case FNMLS_z_p_zzz:
8628       mnemonic = "fnmls";
8629       break;
8630     case FNMSB_z_p_zzz:
8631       mnemonic = "fnmsb";
8632       break;
8633     default:
8634       break;
8635   }
8636   Format(instr, mnemonic, form);
8637 }
8638 
VisitSVEFPMulAddIndex(const Instruction * instr)8639 void Disassembler::VisitSVEFPMulAddIndex(const Instruction *instr) {
8640   const char *mnemonic = "unimplemented";
8641   const char *form = "(SVEFPMulAddIndex)";
8642 
8643   switch (instr->Mask(SVEFPMulAddIndexMask)) {
8644     case FMLA_z_zzzi_d:
8645       mnemonic = "fmla";
8646       form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]";
8647       break;
8648     case FMLA_z_zzzi_s:
8649       mnemonic = "fmla";
8650       form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]";
8651       break;
8652     case FMLS_z_zzzi_d:
8653       mnemonic = "fmls";
8654       form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]";
8655       break;
8656     case FMLS_z_zzzi_s:
8657       mnemonic = "fmls";
8658       form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]";
8659       break;
8660     case FMLA_z_zzzi_h:
8661     case FMLA_z_zzzi_h_i3h:
8662       mnemonic = "fmla";
8663       form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]";
8664       break;
8665     case FMLS_z_zzzi_h:
8666     case FMLS_z_zzzi_h_i3h:
8667       mnemonic = "fmls";
8668       form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]";
8669       break;
8670     default:
8671       break;
8672   }
8673 
8674   Format(instr, mnemonic, form);
8675 }
8676 
VisitSVEFPUnaryOpUnpredicated(const Instruction * instr)8677 void Disassembler::VisitSVEFPUnaryOpUnpredicated(const Instruction *instr) {
8678   const char *mnemonic = "unimplemented";
8679   const char *form = "'Zd.'t, 'Zn.'t";
8680 
8681   switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
8682     case FRECPE_z_z:
8683       mnemonic = "frecpe";
8684       break;
8685     case FRSQRTE_z_z:
8686       mnemonic = "frsqrte";
8687       break;
8688     default:
8689       break;
8690   }
8691   Format(instr, mnemonic, form);
8692 }
8693 
VisitSVEIncDecByPredicateCount(const Instruction * instr)8694 void Disassembler::VisitSVEIncDecByPredicateCount(const Instruction *instr) {
8695   const char *mnemonic = "unimplemented";
8696   const char *form = "(SVEIncDecByPredicateCount)";
8697 
8698   switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8699     case DECP_r_p_r:
8700     case DECP_z_p_z:
8701       mnemonic = "decp";
8702       break;
8703     case INCP_r_p_r:
8704     case INCP_z_p_z:
8705       mnemonic = "incp";
8706       break;
8707     case SQDECP_r_p_r_sx:
8708     case SQDECP_r_p_r_x:
8709     case SQDECP_z_p_z:
8710       mnemonic = "sqdecp";
8711       break;
8712     case SQINCP_r_p_r_sx:
8713     case SQINCP_r_p_r_x:
8714     case SQINCP_z_p_z:
8715       mnemonic = "sqincp";
8716       break;
8717     case UQDECP_r_p_r_uw:
8718     case UQDECP_r_p_r_x:
8719     case UQDECP_z_p_z:
8720       mnemonic = "uqdecp";
8721       break;
8722     case UQINCP_r_p_r_uw:
8723     case UQINCP_r_p_r_x:
8724     case UQINCP_z_p_z:
8725       mnemonic = "uqincp";
8726       break;
8727     default:
8728       break;
8729   }
8730 
8731   switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8732     // <Xdn>, <Pg>.<T>
8733     case DECP_r_p_r:
8734     case INCP_r_p_r:
8735       form = "'Xd, 'Pn.'t";
8736       break;
8737     // <Zdn>.<T>, <Pg>
8738     case DECP_z_p_z:
8739     case INCP_z_p_z:
8740     case SQDECP_z_p_z:
8741     case SQINCP_z_p_z:
8742     case UQDECP_z_p_z:
8743     case UQINCP_z_p_z:
8744       form = "'Zd.'t, 'Pn";
8745       break;
8746     // <Xdn>, <Pg>.<T>, <Wdn>
8747     case SQDECP_r_p_r_sx:
8748     case SQINCP_r_p_r_sx:
8749       form = "'Xd, 'Pn.'t, 'Wd";
8750       break;
8751     // <Xdn>, <Pg>.<T>
8752     case SQDECP_r_p_r_x:
8753     case SQINCP_r_p_r_x:
8754     case UQDECP_r_p_r_x:
8755     case UQINCP_r_p_r_x:
8756       form = "'Xd, 'Pn.'t";
8757       break;
8758     // <Wdn>, <Pg>.<T>
8759     case UQDECP_r_p_r_uw:
8760     case UQINCP_r_p_r_uw:
8761       form = "'Wd, 'Pn.'t";
8762       break;
8763     default:
8764       break;
8765   }
8766   Format(instr, mnemonic, form);
8767 }
8768 
VisitSVEIndexGeneration(const Instruction * instr)8769 void Disassembler::VisitSVEIndexGeneration(const Instruction *instr) {
8770   const char *mnemonic = "unimplemented";
8771   const char *form = "(SVEIndexGeneration)";
8772 
8773   bool w_inputs =
8774       static_cast<unsigned>(instr->GetSVESize()) <= kWRegSizeInBytesLog2;
8775 
8776   switch (instr->Mask(SVEIndexGenerationMask)) {
8777     case INDEX_z_ii:
8778       mnemonic = "index";
8779       form = "'Zd.'t, #'s0905, #'s2016";
8780       break;
8781     case INDEX_z_ir:
8782       mnemonic = "index";
8783       form = w_inputs ? "'Zd.'t, #'s0905, 'Wm" : "'Zd.'t, #'s0905, 'Xm";
8784       break;
8785     case INDEX_z_ri:
8786       mnemonic = "index";
8787       form = w_inputs ? "'Zd.'t, 'Wn, #'s2016" : "'Zd.'t, 'Xn, #'s2016";
8788       break;
8789     case INDEX_z_rr:
8790       mnemonic = "index";
8791       form = w_inputs ? "'Zd.'t, 'Wn, 'Wm" : "'Zd.'t, 'Xn, 'Xm";
8792       break;
8793     default:
8794       break;
8795   }
8796   Format(instr, mnemonic, form);
8797 }
8798 
VisitSVEIntArithmeticUnpredicated(const Instruction * instr)8799 void Disassembler::VisitSVEIntArithmeticUnpredicated(const Instruction *instr) {
8800   const char *mnemonic = "unimplemented";
8801   const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t";
8802 
8803   switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
8804     case ADD_z_zz:
8805       mnemonic = "add";
8806       break;
8807     case SQADD_z_zz:
8808       mnemonic = "sqadd";
8809       break;
8810     case SQSUB_z_zz:
8811       mnemonic = "sqsub";
8812       break;
8813     case SUB_z_zz:
8814       mnemonic = "sub";
8815       break;
8816     case UQADD_z_zz:
8817       mnemonic = "uqadd";
8818       break;
8819     case UQSUB_z_zz:
8820       mnemonic = "uqsub";
8821       break;
8822     default:
8823       break;
8824   }
8825   Format(instr, mnemonic, form);
8826 }
8827 
VisitSVEIntCompareSignedImm(const Instruction * instr)8828 void Disassembler::VisitSVEIntCompareSignedImm(const Instruction *instr) {
8829   const char *mnemonic = "unimplemented";
8830   const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, #'s2016";
8831 
8832   switch (instr->Mask(SVEIntCompareSignedImmMask)) {
8833     case CMPEQ_p_p_zi:
8834       mnemonic = "cmpeq";
8835       break;
8836     case CMPGE_p_p_zi:
8837       mnemonic = "cmpge";
8838       break;
8839     case CMPGT_p_p_zi:
8840       mnemonic = "cmpgt";
8841       break;
8842     case CMPLE_p_p_zi:
8843       mnemonic = "cmple";
8844       break;
8845     case CMPLT_p_p_zi:
8846       mnemonic = "cmplt";
8847       break;
8848     case CMPNE_p_p_zi:
8849       mnemonic = "cmpne";
8850       break;
8851     default:
8852       break;
8853   }
8854   Format(instr, mnemonic, form);
8855 }
8856 
VisitSVEIntCompareUnsignedImm(const Instruction * instr)8857 void Disassembler::VisitSVEIntCompareUnsignedImm(const Instruction *instr) {
8858   const char *mnemonic = "unimplemented";
8859   const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, #'u2014";
8860 
8861   switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
8862     case CMPHI_p_p_zi:
8863       mnemonic = "cmphi";
8864       break;
8865     case CMPHS_p_p_zi:
8866       mnemonic = "cmphs";
8867       break;
8868     case CMPLO_p_p_zi:
8869       mnemonic = "cmplo";
8870       break;
8871     case CMPLS_p_p_zi:
8872       mnemonic = "cmpls";
8873       break;
8874     default:
8875       break;
8876   }
8877   Format(instr, mnemonic, form);
8878 }
8879 
VisitSVEIntCompareVectors(const Instruction * instr)8880 void Disassembler::VisitSVEIntCompareVectors(const Instruction *instr) {
8881   const char *mnemonic = "unimplemented";
8882   const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.d";
8883 
8884   switch (instr->Mask(SVEIntCompareVectorsMask)) {
8885     case CMPEQ_p_p_zw:
8886       mnemonic = "cmpeq";
8887       break;
8888     case CMPEQ_p_p_zz:
8889       mnemonic = "cmpeq";
8890       form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8891       break;
8892     case CMPGE_p_p_zw:
8893       mnemonic = "cmpge";
8894       break;
8895     case CMPGE_p_p_zz:
8896       mnemonic = "cmpge";
8897       form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8898       break;
8899     case CMPGT_p_p_zw:
8900       mnemonic = "cmpgt";
8901       break;
8902     case CMPGT_p_p_zz:
8903       mnemonic = "cmpgt";
8904       form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8905       break;
8906     case CMPHI_p_p_zw:
8907       mnemonic = "cmphi";
8908       break;
8909     case CMPHI_p_p_zz:
8910       mnemonic = "cmphi";
8911       form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8912       break;
8913     case CMPHS_p_p_zw:
8914       mnemonic = "cmphs";
8915       break;
8916     case CMPHS_p_p_zz:
8917       mnemonic = "cmphs";
8918       form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8919       break;
8920     case CMPLE_p_p_zw:
8921       mnemonic = "cmple";
8922       break;
8923     case CMPLO_p_p_zw:
8924       mnemonic = "cmplo";
8925       break;
8926     case CMPLS_p_p_zw:
8927       mnemonic = "cmpls";
8928       break;
8929     case CMPLT_p_p_zw:
8930       mnemonic = "cmplt";
8931       break;
8932     case CMPNE_p_p_zw:
8933       mnemonic = "cmpne";
8934       break;
8935     case CMPNE_p_p_zz:
8936       mnemonic = "cmpne";
8937       form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8938       break;
8939     default:
8940       break;
8941   }
8942   Format(instr, mnemonic, form);
8943 }
8944 
VisitSVEIntMulAddPredicated(const Instruction * instr)8945 void Disassembler::VisitSVEIntMulAddPredicated(const Instruction *instr) {
8946   const char *mnemonic = "unimplemented";
8947   const char *form = "(SVEIntMulAddPredicated)";
8948 
8949   switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
8950     case MAD_z_p_zzz:
8951       mnemonic = "mad";
8952       form = "'Zd.'t, 'Pgl/m, 'Zm.'t, 'Zn.'t";
8953       break;
8954     case MLA_z_p_zzz:
8955       mnemonic = "mla";
8956       form = "'Zd.'t, 'Pgl/m, 'Zn.'t, 'Zm.'t";
8957       break;
8958     case MLS_z_p_zzz:
8959       mnemonic = "mls";
8960       form = "'Zd.'t, 'Pgl/m, 'Zn.'t, 'Zm.'t";
8961       break;
8962     case MSB_z_p_zzz:
8963       mnemonic = "msb";
8964       form = "'Zd.'t, 'Pgl/m, 'Zm.'t, 'Zn.'t";
8965       break;
8966     default:
8967       break;
8968   }
8969   Format(instr, mnemonic, form);
8970 }
8971 
VisitSVEIntMulAddUnpredicated(const Instruction * instr)8972 void Disassembler::VisitSVEIntMulAddUnpredicated(const Instruction *instr) {
8973   const char *mnemonic = "unimplemented";
8974   const char *form = "(SVEIntMulAddUnpredicated)";
8975 
8976   if (static_cast<unsigned>(instr->GetSVESize()) >= kSRegSizeInBytesLog2) {
8977     form = "'Zd.'t, 'Zn.'tq, 'Zm.'tq";
8978     switch (instr->Mask(SVEIntMulAddUnpredicatedMask)) {
8979       case SDOT_z_zzz:
8980         mnemonic = "sdot";
8981         break;
8982       case UDOT_z_zzz:
8983         mnemonic = "udot";
8984         break;
8985       default:
8986         break;
8987     }
8988   }
8989 
8990   Format(instr, mnemonic, form);
8991 }
8992 
VisitSVEMovprfx(const Instruction * instr)8993 void Disassembler::VisitSVEMovprfx(const Instruction *instr) {
8994   const char *mnemonic = "unimplemented";
8995   const char *form = "(SVEMovprfx)";
8996 
8997   if (instr->Mask(SVEMovprfxMask) == MOVPRFX_z_p_z) {
8998     mnemonic = "movprfx";
8999     form = "'Zd.'t, 'Pgl/'?16:mz, 'Zn.'t";
9000   }
9001 
9002   Format(instr, mnemonic, form);
9003 }
9004 
VisitSVEIntReduction(const Instruction * instr)9005 void Disassembler::VisitSVEIntReduction(const Instruction *instr) {
9006   const char *mnemonic = "unimplemented";
9007   const char *form = "'Vdv, 'Pgl, 'Zn.'t";
9008 
9009   if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
9010     switch (instr->Mask(SVEIntReductionLogicalMask)) {
9011       case ANDV_r_p_z:
9012         mnemonic = "andv";
9013         break;
9014       case EORV_r_p_z:
9015         mnemonic = "eorv";
9016         break;
9017       case ORV_r_p_z:
9018         mnemonic = "orv";
9019         break;
9020       default:
9021         break;
9022     }
9023   } else {
9024     switch (instr->Mask(SVEIntReductionMask)) {
9025       case SADDV_r_p_z:
9026         mnemonic = "saddv";
9027         form = "'Dd, 'Pgl, 'Zn.'t";
9028         break;
9029       case SMAXV_r_p_z:
9030         mnemonic = "smaxv";
9031         break;
9032       case SMINV_r_p_z:
9033         mnemonic = "sminv";
9034         break;
9035       case UADDV_r_p_z:
9036         mnemonic = "uaddv";
9037         form = "'Dd, 'Pgl, 'Zn.'t";
9038         break;
9039       case UMAXV_r_p_z:
9040         mnemonic = "umaxv";
9041         break;
9042       case UMINV_r_p_z:
9043         mnemonic = "uminv";
9044         break;
9045       default:
9046         break;
9047     }
9048   }
9049   Format(instr, mnemonic, form);
9050 }
9051 
VisitSVEIntUnaryArithmeticPredicated(const Instruction * instr)9052 void Disassembler::VisitSVEIntUnaryArithmeticPredicated(
9053     const Instruction *instr) {
9054   const char *mnemonic = "unimplemented";
9055   const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t";
9056 
9057   switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
9058     case ABS_z_p_z:
9059       mnemonic = "abs";
9060       break;
9061     case CLS_z_p_z:
9062       mnemonic = "cls";
9063       break;
9064     case CLZ_z_p_z:
9065       mnemonic = "clz";
9066       break;
9067     case CNOT_z_p_z:
9068       mnemonic = "cnot";
9069       break;
9070     case CNT_z_p_z:
9071       mnemonic = "cnt";
9072       break;
9073     case FABS_z_p_z:
9074       mnemonic = "fabs";
9075       break;
9076     case FNEG_z_p_z:
9077       mnemonic = "fneg";
9078       break;
9079     case NEG_z_p_z:
9080       mnemonic = "neg";
9081       break;
9082     case NOT_z_p_z:
9083       mnemonic = "not";
9084       break;
9085     case SXTB_z_p_z:
9086       mnemonic = "sxtb";
9087       break;
9088     case SXTH_z_p_z:
9089       mnemonic = "sxth";
9090       break;
9091     case SXTW_z_p_z:
9092       mnemonic = "sxtw";
9093       break;
9094     case UXTB_z_p_z:
9095       mnemonic = "uxtb";
9096       break;
9097     case UXTH_z_p_z:
9098       mnemonic = "uxth";
9099       break;
9100     case UXTW_z_p_z:
9101       mnemonic = "uxtw";
9102       break;
9103     default:
9104       break;
9105   }
9106   Format(instr, mnemonic, form);
9107 }
9108 
VisitSVEMulIndex(const Instruction * instr)9109 void Disassembler::VisitSVEMulIndex(const Instruction *instr) {
9110   const char *mnemonic = "unimplemented";
9111   const char *form = "(SVEMulIndex)";
9112 
9113   switch (instr->Mask(SVEMulIndexMask)) {
9114     case SDOT_z_zzzi_d:
9115       mnemonic = "sdot";
9116       form = "'Zd.d, 'Zn.h, z'u1916.h['u2020]";
9117       break;
9118     case SDOT_z_zzzi_s:
9119       mnemonic = "sdot";
9120       form = "'Zd.s, 'Zn.b, z'u1816.b['u2019]";
9121       break;
9122     case UDOT_z_zzzi_d:
9123       mnemonic = "udot";
9124       form = "'Zd.d, 'Zn.h, z'u1916.h['u2020]";
9125       break;
9126     case UDOT_z_zzzi_s:
9127       mnemonic = "udot";
9128       form = "'Zd.s, 'Zn.b, z'u1816.b['u2019]";
9129       break;
9130     default:
9131       break;
9132   }
9133   Format(instr, mnemonic, form);
9134 }
9135 
VisitSVEPermuteVectorExtract(const Instruction * instr)9136 void Disassembler::VisitSVEPermuteVectorExtract(const Instruction *instr) {
9137   const char *mnemonic = "unimplemented";
9138   const char *form = "(SVEPermuteVectorExtract)";
9139 
9140   switch (instr->Mask(SVEPermuteVectorExtractMask)) {
9141     case EXT_z_zi_des:
9142       mnemonic = "ext";
9143       form = "'Zd.b, 'Zd.b, 'Zn.b, #'u2016:1210";
9144       break;
9145     default:
9146       break;
9147   }
9148   Format(instr, mnemonic, form);
9149 }
9150 
VisitSVEPermuteVectorInterleaving(const Instruction * instr)9151 void Disassembler::VisitSVEPermuteVectorInterleaving(const Instruction *instr) {
9152   const char *mnemonic = "unimplemented";
9153   const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t";
9154 
9155   switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
9156     case TRN1_z_zz:
9157       mnemonic = "trn1";
9158       break;
9159     case TRN2_z_zz:
9160       mnemonic = "trn2";
9161       break;
9162     case UZP1_z_zz:
9163       mnemonic = "uzp1";
9164       break;
9165     case UZP2_z_zz:
9166       mnemonic = "uzp2";
9167       break;
9168     case ZIP1_z_zz:
9169       mnemonic = "zip1";
9170       break;
9171     case ZIP2_z_zz:
9172       mnemonic = "zip2";
9173       break;
9174     default:
9175       break;
9176   }
9177   Format(instr, mnemonic, form);
9178 }
9179 
VisitSVEPredicateCount(const Instruction * instr)9180 void Disassembler::VisitSVEPredicateCount(const Instruction *instr) {
9181   const char *mnemonic = "unimplemented";
9182   const char *form = "(SVEPredicateCount)";
9183 
9184   switch (instr->Mask(SVEPredicateCountMask)) {
9185     case CNTP_r_p_p:
9186       mnemonic = "cntp";
9187       form = "'Xd, p'u1310, 'Pn.'t";
9188       break;
9189     default:
9190       break;
9191   }
9192   Format(instr, mnemonic, form);
9193 }
9194 
VisitSVEPredicateLogical(const Instruction * instr)9195 void Disassembler::VisitSVEPredicateLogical(const Instruction *instr) {
9196   const char *mnemonic = "unimplemented";
9197   const char *form = "'Pd.b, p'u1310/z, 'Pn.b, 'Pm.b";
9198 
9199   int pd = instr->GetPd();
9200   int pn = instr->GetPn();
9201   int pm = instr->GetPm();
9202   int pg = instr->ExtractBits(13, 10);
9203 
9204   switch (instr->Mask(SVEPredicateLogicalMask)) {
9205     case ANDS_p_p_pp_z:
9206       mnemonic = "ands";
9207       if (pn == pm) {
9208         mnemonic = "movs";
9209         form = "'Pd.b, p'u1310/z, 'Pn.b";
9210       }
9211       break;
9212     case AND_p_p_pp_z:
9213       mnemonic = "and";
9214       if (pn == pm) {
9215         mnemonic = "mov";
9216         form = "'Pd.b, p'u1310/z, 'Pn.b";
9217       }
9218       break;
9219     case BICS_p_p_pp_z:
9220       mnemonic = "bics";
9221       break;
9222     case BIC_p_p_pp_z:
9223       mnemonic = "bic";
9224       break;
9225     case EORS_p_p_pp_z:
9226       mnemonic = "eors";
9227       if (pm == pg) {
9228         mnemonic = "nots";
9229         form = "'Pd.b, 'Pm/z, 'Pn.b";
9230       }
9231       break;
9232     case EOR_p_p_pp_z:
9233       mnemonic = "eor";
9234       if (pm == pg) {
9235         mnemonic = "not";
9236         form = "'Pd.b, 'Pm/z, 'Pn.b";
9237       }
9238       break;
9239     case NANDS_p_p_pp_z:
9240       mnemonic = "nands";
9241       break;
9242     case NAND_p_p_pp_z:
9243       mnemonic = "nand";
9244       break;
9245     case NORS_p_p_pp_z:
9246       mnemonic = "nors";
9247       break;
9248     case NOR_p_p_pp_z:
9249       mnemonic = "nor";
9250       break;
9251     case ORNS_p_p_pp_z:
9252       mnemonic = "orns";
9253       break;
9254     case ORN_p_p_pp_z:
9255       mnemonic = "orn";
9256       break;
9257     case ORRS_p_p_pp_z:
9258       mnemonic = "orrs";
9259       if ((pn == pm) && (pn == pg)) {
9260         mnemonic = "movs";
9261         form = "'Pd.b, 'Pn.b";
9262       }
9263       break;
9264     case ORR_p_p_pp_z:
9265       mnemonic = "orr";
9266       if ((pn == pm) && (pn == pg)) {
9267         mnemonic = "mov";
9268         form = "'Pd.b, 'Pn.b";
9269       }
9270       break;
9271     case SEL_p_p_pp:
9272       if (pd == pm) {
9273         mnemonic = "mov";
9274         form = "'Pd.b, p'u1310/m, 'Pn.b";
9275       } else {
9276         mnemonic = "sel";
9277         form = "'Pd.b, p'u1310, 'Pn.b, 'Pm.b";
9278       }
9279       break;
9280     default:
9281       form = "(SVEPredicateLogical)";
9282       break;
9283   }
9284   Format(instr, mnemonic, form);
9285 }
9286 
VisitSVEPredicateInitialize(const Instruction * instr)9287 void Disassembler::VisitSVEPredicateInitialize(const Instruction *instr) {
9288   // This group only contains PTRUE{S}, and there are no unallocated encodings.
9289   VIXL_STATIC_ASSERT(
9290       SVEPredicateInitializeMask ==
9291       (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
9292   VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
9293               (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
9294 
9295   const char *mnemonic = instr->ExtractBit(16) ? "ptrues" : "ptrue";
9296   const char *form = "'Pd.'t, 'Ipc";
9297   // Omit the pattern if it is the default ('ALL').
9298   if (instr->ExtractBits(9, 5) == SVE_ALL) form = "'Pd.'t";
9299   Format(instr, mnemonic, form);
9300 }
9301 
VisitSVEPredicateNextActive(const Instruction * instr)9302 void Disassembler::VisitSVEPredicateNextActive(const Instruction *instr) {
9303   // This group only contains PNEXT, and there are no unallocated encodings.
9304   VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
9305   VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
9306 
9307   Format(instr, "pnext", "'Pd.'t, 'Pn, 'Pd.'t");
9308 }
9309 
VisitSVEPredicateReadFromFFR_Predicated(const Instruction * instr)9310 void Disassembler::VisitSVEPredicateReadFromFFR_Predicated(
9311     const Instruction *instr) {
9312   const char *mnemonic = "unimplemented";
9313   const char *form = "(SVEPredicateReadFromFFR_Predicated)";
9314   switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
9315     case RDFFR_p_p_f:
9316     case RDFFRS_p_p_f:
9317       mnemonic = instr->ExtractBit(22) ? "rdffrs" : "rdffr";
9318       form = "'Pd.b, 'Pn/z";
9319       break;
9320     default:
9321       break;
9322   }
9323   Format(instr, mnemonic, form);
9324 }
9325 
VisitSVEPropagateBreak(const Instruction * instr)9326 void Disassembler::VisitSVEPropagateBreak(const Instruction *instr) {
9327   const char *mnemonic = "unimplemented";
9328   const char *form = "'Pd.b, p'u1310/z, 'Pn.b, 'Pm.b";
9329 
9330   switch (instr->Mask(SVEPropagateBreakMask)) {
9331     case BRKPAS_p_p_pp:
9332       mnemonic = "brkpas";
9333       break;
9334     case BRKPA_p_p_pp:
9335       mnemonic = "brkpa";
9336       break;
9337     case BRKPBS_p_p_pp:
9338       mnemonic = "brkpbs";
9339       break;
9340     case BRKPB_p_p_pp:
9341       mnemonic = "brkpb";
9342       break;
9343     default:
9344       break;
9345   }
9346   Format(instr, mnemonic, form);
9347 }
9348 
VisitSVEStackFrameAdjustment(const Instruction * instr)9349 void Disassembler::VisitSVEStackFrameAdjustment(const Instruction *instr) {
9350   const char *mnemonic = "unimplemented";
9351   const char *form = "'Xds, 'Xms, #'s1005";
9352 
9353   switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
9354     case ADDPL_r_ri:
9355       mnemonic = "addpl";
9356       break;
9357     case ADDVL_r_ri:
9358       mnemonic = "addvl";
9359       break;
9360     default:
9361       form = "(SVEStackFrameAdjustment)";
9362       break;
9363   }
9364 
9365   Format(instr, mnemonic, form);
9366 }
9367 
VisitSVEStackFrameSize(const Instruction * instr)9368 void Disassembler::VisitSVEStackFrameSize(const Instruction *instr) {
9369   const char *mnemonic = "unimplemented";
9370   const char *form = "(SVEStackFrameSize)";
9371 
9372   switch (instr->Mask(SVEStackFrameSizeMask)) {
9373     case RDVL_r_i:
9374       mnemonic = "rdvl";
9375       form = "'Xd, #'s1005";
9376       break;
9377     default:
9378       break;
9379   }
9380 
9381   Format(instr, mnemonic, form);
9382 }
9383 
VisitSVEVectorSelect(const Instruction * instr)9384 void Disassembler::VisitSVEVectorSelect(const Instruction *instr) {
9385   const char *mnemonic = "unimplemented";
9386   const char *form = "(SVEVectorSelect)";
9387 
9388   switch (instr->Mask(SVEVectorSelectMask)) {
9389     case SEL_z_p_zz:
9390       if (instr->GetRd() == instr->GetRm()) {
9391         mnemonic = "mov";
9392         form = "'Zd.'t, p'u1310/m, 'Zn.'t";
9393       } else {
9394         mnemonic = "sel";
9395         form = "'Zd.'t, p'u1310, 'Zn.'t, 'Zm.'t";
9396       }
9397       break;
9398     default:
9399       break;
9400   }
9401   Format(instr, mnemonic, form);
9402 }
9403 
VisitSVEContiguousLoad_ScalarPlusImm(const Instruction * instr)9404 void Disassembler::VisitSVEContiguousLoad_ScalarPlusImm(
9405     const Instruction *instr) {
9406   const char *mnemonic = "unimplemented";
9407   const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns";
9408   const char *suffix =
9409       (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]";
9410 
9411   switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
9412     case LD1B_z_p_bi_u16:
9413     case LD1B_z_p_bi_u32:
9414     case LD1B_z_p_bi_u64:
9415     case LD1B_z_p_bi_u8:
9416       mnemonic = "ld1b";
9417       break;
9418     case LD1D_z_p_bi_u64:
9419       mnemonic = "ld1d";
9420       break;
9421     case LD1H_z_p_bi_u16:
9422     case LD1H_z_p_bi_u32:
9423     case LD1H_z_p_bi_u64:
9424       mnemonic = "ld1h";
9425       break;
9426     case LD1SB_z_p_bi_s16:
9427     case LD1SB_z_p_bi_s32:
9428     case LD1SB_z_p_bi_s64:
9429       mnemonic = "ld1sb";
9430       break;
9431     case LD1SH_z_p_bi_s32:
9432     case LD1SH_z_p_bi_s64:
9433       mnemonic = "ld1sh";
9434       break;
9435     case LD1SW_z_p_bi_s64:
9436       mnemonic = "ld1sw";
9437       break;
9438     case LD1W_z_p_bi_u32:
9439     case LD1W_z_p_bi_u64:
9440       mnemonic = "ld1w";
9441       break;
9442     default:
9443       form = "(SVEContiguousLoad_ScalarPlusImm)";
9444       suffix = NULL;
9445       break;
9446   }
9447 
9448   Format(instr, mnemonic, form, suffix);
9449 }
9450 
VisitSVEContiguousLoad_ScalarPlusScalar(const Instruction * instr)9451 void Disassembler::VisitSVEContiguousLoad_ScalarPlusScalar(
9452     const Instruction *instr) {
9453   const char *mnemonic = "unimplemented";
9454   const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns, 'Xm";
9455   const char *suffix = NULL;
9456 
9457   switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
9458     case LD1B_z_p_br_u16:
9459     case LD1B_z_p_br_u32:
9460     case LD1B_z_p_br_u64:
9461     case LD1B_z_p_br_u8:
9462       mnemonic = "ld1b";
9463       suffix = "]";
9464       break;
9465     case LD1D_z_p_br_u64:
9466       mnemonic = "ld1d";
9467       suffix = ", lsl #'u2423]";
9468       break;
9469     case LD1H_z_p_br_u16:
9470     case LD1H_z_p_br_u32:
9471     case LD1H_z_p_br_u64:
9472       mnemonic = "ld1h";
9473       suffix = ", lsl #'u2423]";
9474       break;
9475     case LD1SB_z_p_br_s16:
9476     case LD1SB_z_p_br_s32:
9477     case LD1SB_z_p_br_s64:
9478       mnemonic = "ld1sb";
9479       suffix = "]";
9480       break;
9481     case LD1SH_z_p_br_s32:
9482     case LD1SH_z_p_br_s64:
9483       mnemonic = "ld1sh";
9484       suffix = ", lsl #1]";
9485       break;
9486     case LD1SW_z_p_br_s64:
9487       mnemonic = "ld1sw";
9488       suffix = ", lsl #2]";
9489       break;
9490     case LD1W_z_p_br_u32:
9491     case LD1W_z_p_br_u64:
9492       mnemonic = "ld1w";
9493       suffix = ", lsl #'u2423]";
9494       break;
9495     default:
9496       form = "(SVEContiguousLoad_ScalarPlusScalar)";
9497       suffix = NULL;
9498       break;
9499   }
9500 
9501   Format(instr, mnemonic, form, suffix);
9502 }
9503 
VisitReserved(const Instruction * instr)9504 void Disassembler::VisitReserved(const Instruction *instr) {
9505   // UDF is the only instruction in this group, and the Decoder is precise.
9506   VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
9507   Format(instr, "udf", "'IUdf");
9508 }
9509 
9510 
VisitUnimplemented(const Instruction * instr)9511 void Disassembler::VisitUnimplemented(const Instruction *instr) {
9512   Format(instr, "unimplemented", "(Unimplemented)");
9513 }
9514 
9515 
VisitUnallocated(const Instruction * instr)9516 void Disassembler::VisitUnallocated(const Instruction *instr) {
9517   Format(instr, "unallocated", "(Unallocated)");
9518 }
9519 
9520 
ProcessOutput(const Instruction *)9521 void Disassembler::ProcessOutput(const Instruction * /*instr*/) {
9522   // The base disasm does nothing more than disassembling into a buffer.
9523 }
9524 
9525 
AppendRegisterNameToOutput(const Instruction * instr,const CPURegister & reg)9526 void Disassembler::AppendRegisterNameToOutput(const Instruction *instr,
9527                                               const CPURegister &reg) {
9528   USE(instr);
9529   VIXL_ASSERT(reg.IsValid());
9530   char reg_char;
9531 
9532   if (reg.IsRegister()) {
9533     reg_char = reg.Is64Bits() ? 'x' : 'w';
9534   } else {
9535     VIXL_ASSERT(reg.IsVRegister());
9536     switch (reg.GetSizeInBits()) {
9537       case kBRegSize:
9538         reg_char = 'b';
9539         break;
9540       case kHRegSize:
9541         reg_char = 'h';
9542         break;
9543       case kSRegSize:
9544         reg_char = 's';
9545         break;
9546       case kDRegSize:
9547         reg_char = 'd';
9548         break;
9549       default:
9550         VIXL_ASSERT(reg.Is128Bits());
9551         reg_char = 'q';
9552     }
9553   }
9554 
9555   if (reg.IsVRegister() || !(reg.Aliases(sp) || reg.Aliases(xzr))) {
9556     // A core or scalar/vector register: [wx]0 - 30, [bhsdq]0 - 31.
9557     AppendToOutput("%c%d", reg_char, reg.GetCode());
9558   } else if (reg.Aliases(sp)) {
9559     // Disassemble w31/x31 as stack pointer wsp/sp.
9560     AppendToOutput("%s", reg.Is64Bits() ? "sp" : "wsp");
9561   } else {
9562     // Disassemble w31/x31 as zero register wzr/xzr.
9563     AppendToOutput("%czr", reg_char);
9564   }
9565 }
9566 
9567 
AppendPCRelativeOffsetToOutput(const Instruction * instr,int64_t offset)9568 void Disassembler::AppendPCRelativeOffsetToOutput(const Instruction *instr,
9569                                                   int64_t offset) {
9570   USE(instr);
9571   if (offset < 0) {
9572     // Cast to uint64_t so that INT64_MIN is handled in a well-defined way.
9573     uint64_t abs_offset = -static_cast<uint64_t>(offset);
9574     AppendToOutput("#-0x%" PRIx64, abs_offset);
9575   } else {
9576     AppendToOutput("#+0x%" PRIx64, offset);
9577   }
9578 }
9579 
9580 
AppendAddressToOutput(const Instruction * instr,const void * addr)9581 void Disassembler::AppendAddressToOutput(const Instruction *instr,
9582                                          const void *addr) {
9583   USE(instr);
9584   AppendToOutput("(addr 0x%" PRIxPTR ")", reinterpret_cast<uintptr_t>(addr));
9585 }
9586 
9587 
AppendCodeAddressToOutput(const Instruction * instr,const void * addr)9588 void Disassembler::AppendCodeAddressToOutput(const Instruction *instr,
9589                                              const void *addr) {
9590   AppendAddressToOutput(instr, addr);
9591 }
9592 
9593 
AppendDataAddressToOutput(const Instruction * instr,const void * addr)9594 void Disassembler::AppendDataAddressToOutput(const Instruction *instr,
9595                                              const void *addr) {
9596   AppendAddressToOutput(instr, addr);
9597 }
9598 
9599 
AppendCodeRelativeAddressToOutput(const Instruction * instr,const void * addr)9600 void Disassembler::AppendCodeRelativeAddressToOutput(const Instruction *instr,
9601                                                      const void *addr) {
9602   USE(instr);
9603   int64_t rel_addr = CodeRelativeAddress(addr);
9604   if (rel_addr >= 0) {
9605     AppendToOutput("(addr 0x%" PRIx64 ")", rel_addr);
9606   } else {
9607     AppendToOutput("(addr -0x%" PRIx64 ")", -rel_addr);
9608   }
9609 }
9610 
9611 
AppendCodeRelativeCodeAddressToOutput(const Instruction * instr,const void * addr)9612 void Disassembler::AppendCodeRelativeCodeAddressToOutput(
9613     const Instruction *instr, const void *addr) {
9614   AppendCodeRelativeAddressToOutput(instr, addr);
9615 }
9616 
9617 
AppendCodeRelativeDataAddressToOutput(const Instruction * instr,const void * addr)9618 void Disassembler::AppendCodeRelativeDataAddressToOutput(
9619     const Instruction *instr, const void *addr) {
9620   AppendCodeRelativeAddressToOutput(instr, addr);
9621 }
9622 
9623 
MapCodeAddress(int64_t base_address,const Instruction * instr_address)9624 void Disassembler::MapCodeAddress(int64_t base_address,
9625                                   const Instruction *instr_address) {
9626   set_code_address_offset(base_address -
9627                           reinterpret_cast<intptr_t>(instr_address));
9628 }
CodeRelativeAddress(const void * addr)9629 int64_t Disassembler::CodeRelativeAddress(const void *addr) {
9630   return reinterpret_cast<intptr_t>(addr) + code_address_offset();
9631 }
9632 
9633 
Format(const Instruction * instr,const char * mnemonic,const char * format0,const char * format1)9634 void Disassembler::Format(const Instruction *instr,
9635                           const char *mnemonic,
9636                           const char *format0,
9637                           const char *format1) {
9638   VIXL_ASSERT(mnemonic != NULL);
9639   ResetOutput();
9640   Substitute(instr, mnemonic);
9641   if (format0 != NULL) {
9642     VIXL_ASSERT(buffer_pos_ < buffer_size_);
9643     buffer_[buffer_pos_++] = ' ';
9644     Substitute(instr, format0);
9645     if (format1 != NULL) {
9646       Substitute(instr, format1);
9647     }
9648   }
9649   VIXL_ASSERT(buffer_pos_ < buffer_size_);
9650   buffer_[buffer_pos_] = 0;
9651   ProcessOutput(instr);
9652 }
9653 
9654 
Substitute(const Instruction * instr,const char * string)9655 void Disassembler::Substitute(const Instruction *instr, const char *string) {
9656   char chr = *string++;
9657   while (chr != '\0') {
9658     if (chr == '\'') {
9659       string += SubstituteField(instr, string);
9660     } else {
9661       VIXL_ASSERT(buffer_pos_ < buffer_size_);
9662       buffer_[buffer_pos_++] = chr;
9663     }
9664     chr = *string++;
9665   }
9666 }
9667 
9668 
SubstituteField(const Instruction * instr,const char * format)9669 int Disassembler::SubstituteField(const Instruction *instr,
9670                                   const char *format) {
9671   switch (format[0]) {
9672     // NB. The remaining substitution prefix upper-case characters are: JU.
9673     case 'R':  // Register. X or W, selected by sf (or alternative) bit.
9674     case 'F':  // FP register. S or D, selected by type field.
9675     case 'V':  // Vector register, V, vector format.
9676     case 'Z':  // Scalable vector register.
9677     case 'W':
9678     case 'X':
9679     case 'B':
9680     case 'H':
9681     case 'S':
9682     case 'D':
9683     case 'Q':
9684       return SubstituteRegisterField(instr, format);
9685     case 'P':
9686       return SubstitutePredicateRegisterField(instr, format);
9687     case 'I':
9688       return SubstituteImmediateField(instr, format);
9689     case 'L':
9690       return SubstituteLiteralField(instr, format);
9691     case 'N':
9692       return SubstituteShiftField(instr, format);
9693     case 'C':
9694       return SubstituteConditionField(instr, format);
9695     case 'E':
9696       return SubstituteExtendField(instr, format);
9697     case 'A':
9698       return SubstitutePCRelAddressField(instr, format);
9699     case 'T':
9700       return SubstituteBranchTargetField(instr, format);
9701     case 'O':
9702       return SubstituteLSRegOffsetField(instr, format);
9703     case 'M':
9704       return SubstituteBarrierField(instr, format);
9705     case 'K':
9706       return SubstituteCrField(instr, format);
9707     case 'G':
9708       return SubstituteSysOpField(instr, format);
9709     case 'p':
9710       return SubstitutePrefetchField(instr, format);
9711     case 'u':
9712     case 's':
9713       return SubstituteIntField(instr, format);
9714     case 't':
9715       return SubstituteSVESize(instr, format);
9716     case '?':
9717       return SubstituteTernary(instr, format);
9718     default: {
9719       VIXL_UNREACHABLE();
9720       return 1;
9721     }
9722   }
9723 }
9724 
GetRegNumForField(const Instruction * instr,char reg_prefix,const char * field)9725 std::pair<unsigned, unsigned> Disassembler::GetRegNumForField(
9726     const Instruction *instr, char reg_prefix, const char *field) {
9727   unsigned reg_num = UINT_MAX;
9728   unsigned field_len = 1;
9729 
9730   switch (field[0]) {
9731     case 'd':
9732       reg_num = instr->GetRd();
9733       break;
9734     case 'n':
9735       reg_num = instr->GetRn();
9736       break;
9737     case 'm':
9738       reg_num = instr->GetRm();
9739       break;
9740     case 'e':
9741       // This is register Rm, but using a 4-bit specifier. Used in NEON
9742       // by-element instructions.
9743       reg_num = instr->GetRmLow16();
9744       break;
9745     case 'a':
9746       reg_num = instr->GetRa();
9747       break;
9748     case 's':
9749       reg_num = instr->GetRs();
9750       break;
9751     case 't':
9752       reg_num = instr->GetRt();
9753       break;
9754     default:
9755       VIXL_UNREACHABLE();
9756   }
9757 
9758   switch (field[1]) {
9759     case '2':
9760     case '3':
9761     case '4':
9762       if ((reg_prefix == 'V') || (reg_prefix == 'Z')) {  // Vt2/3/4, Zt2/3/4
9763         VIXL_ASSERT(field[0] == 't');
9764         reg_num = (reg_num + field[1] - '1') % 32;
9765         field_len++;
9766       } else {
9767         VIXL_ASSERT((field[0] == 't') && (field[1] == '2'));
9768         reg_num = instr->GetRt2();
9769         field_len++;
9770       }
9771       break;
9772     case '+':  // Rt+, Rs+ (ie. Rt + 1, Rs + 1)
9773       VIXL_ASSERT((reg_prefix == 'W') || (reg_prefix == 'X'));
9774       VIXL_ASSERT((field[0] == 's') || (field[0] == 't'));
9775       reg_num++;
9776       field_len++;
9777       break;
9778     case 's':  // Core registers that are (w)sp rather than zr.
9779       VIXL_ASSERT((reg_prefix == 'W') || (reg_prefix == 'X'));
9780       reg_num = (reg_num == kZeroRegCode) ? kSPRegInternalCode : reg_num;
9781       field_len++;
9782       break;
9783   }
9784 
9785   VIXL_ASSERT(reg_num != UINT_MAX);
9786   return std::make_pair(reg_num, field_len);
9787 }
9788 
SubstituteRegisterField(const Instruction * instr,const char * format)9789 int Disassembler::SubstituteRegisterField(const Instruction *instr,
9790                                           const char *format) {
9791   unsigned field_len = 1;  // Initially, count only the first character.
9792 
9793   // The first character of the register format field, eg R, X, S, etc.
9794   char reg_prefix = format[0];
9795 
9796   // Pointer to the character after the prefix. This may be one of the standard
9797   // symbols representing a register encoding, or a two digit bit position,
9798   // handled by the following code.
9799   const char *reg_field = &format[1];
9800 
9801   if (reg_prefix == 'R') {
9802     bool is_x = instr->GetSixtyFourBits();
9803     if (strspn(reg_field, "0123456789") == 2) {  // r20d, r31n, etc.
9804       // Core W or X registers where the type is determined by a specified bit
9805       // position, eg. 'R20d, 'R05n. This is like the 'Rd syntax, where bit 31
9806       // is implicitly used to select between W and X.
9807       int bitpos = ((reg_field[0] - '0') * 10) + (reg_field[1] - '0');
9808       VIXL_ASSERT(bitpos <= 31);
9809       is_x = (instr->ExtractBit(bitpos) == 1);
9810       reg_field = &format[3];
9811       field_len += 2;
9812     }
9813     reg_prefix = is_x ? 'X' : 'W';
9814   }
9815 
9816   std::pair<unsigned, unsigned> rn =
9817       GetRegNumForField(instr, reg_prefix, reg_field);
9818   unsigned reg_num = rn.first;
9819   field_len += rn.second;
9820 
9821   if (reg_field[0] == 'm') {
9822     switch (reg_field[1]) {
9823       // Handle registers tagged with b (bytes), z (instruction), or
9824       // r (registers), used for address updates in NEON load/store
9825       // instructions.
9826       case 'r':
9827       case 'b':
9828       case 'z': {
9829         VIXL_ASSERT(reg_prefix == 'X');
9830         field_len = 3;
9831         char *eimm;
9832         int imm = static_cast<int>(strtol(&reg_field[2], &eimm, 10));
9833         field_len += eimm - &reg_field[2];
9834         if (reg_num == 31) {
9835           switch (reg_field[1]) {
9836             case 'z':
9837               imm *= (1 << instr->GetNEONLSSize());
9838               break;
9839             case 'r':
9840               imm *= (instr->GetNEONQ() == 0) ? kDRegSizeInBytes
9841                                               : kQRegSizeInBytes;
9842               break;
9843             case 'b':
9844               break;
9845           }
9846           AppendToOutput("#%d", imm);
9847           return field_len;
9848         }
9849         break;
9850       }
9851     }
9852   }
9853 
9854   CPURegister::RegisterType reg_type = CPURegister::kRegister;
9855   unsigned reg_size = kXRegSize;
9856 
9857   if (reg_prefix == 'F') {
9858     switch (instr->GetFPType()) {
9859       case 3:
9860         reg_prefix = 'H';
9861         break;
9862       case 0:
9863         reg_prefix = 'S';
9864         break;
9865       default:
9866         reg_prefix = 'D';
9867     }
9868   }
9869 
9870   switch (reg_prefix) {
9871     case 'W':
9872       reg_type = CPURegister::kRegister;
9873       reg_size = kWRegSize;
9874       break;
9875     case 'X':
9876       reg_type = CPURegister::kRegister;
9877       reg_size = kXRegSize;
9878       break;
9879     case 'B':
9880       reg_type = CPURegister::kVRegister;
9881       reg_size = kBRegSize;
9882       break;
9883     case 'H':
9884       reg_type = CPURegister::kVRegister;
9885       reg_size = kHRegSize;
9886       break;
9887     case 'S':
9888       reg_type = CPURegister::kVRegister;
9889       reg_size = kSRegSize;
9890       break;
9891     case 'D':
9892       reg_type = CPURegister::kVRegister;
9893       reg_size = kDRegSize;
9894       break;
9895     case 'Q':
9896       reg_type = CPURegister::kVRegister;
9897       reg_size = kQRegSize;
9898       break;
9899     case 'V':
9900       if (reg_field[1] == 'v') {
9901         reg_type = CPURegister::kVRegister;
9902         reg_size = 1 << (instr->GetSVESize() + 3);
9903         field_len++;
9904         break;
9905       }
9906       AppendToOutput("v%d", reg_num);
9907       return field_len;
9908     case 'Z':
9909       AppendToOutput("z%d", reg_num);
9910       return field_len;
9911     default:
9912       VIXL_UNREACHABLE();
9913   }
9914 
9915   AppendRegisterNameToOutput(instr, CPURegister(reg_num, reg_size, reg_type));
9916 
9917   return field_len;
9918 }
9919 
SubstitutePredicateRegisterField(const Instruction * instr,const char * format)9920 int Disassembler::SubstitutePredicateRegisterField(const Instruction *instr,
9921                                                    const char *format) {
9922   VIXL_ASSERT(format[0] == 'P');
9923   switch (format[1]) {
9924     // This field only supports P register that are always encoded in the same
9925     // position.
9926     case 'd':
9927     case 't':
9928       AppendToOutput("p%u", instr->GetPt());
9929       break;
9930     case 'n':
9931       AppendToOutput("p%u", instr->GetPn());
9932       break;
9933     case 'm':
9934       AppendToOutput("p%u", instr->GetPm());
9935       break;
9936     case 'g':
9937       VIXL_ASSERT(format[2] == 'l');
9938       AppendToOutput("p%u", instr->GetPgLow8());
9939       return 3;
9940     default:
9941       VIXL_UNREACHABLE();
9942   }
9943   return 2;
9944 }
9945 
SubstituteImmediateField(const Instruction * instr,const char * format)9946 int Disassembler::SubstituteImmediateField(const Instruction *instr,
9947                                            const char *format) {
9948   VIXL_ASSERT(format[0] == 'I');
9949 
9950   switch (format[1]) {
9951     case 'M': {  // IMoveImm, IMoveNeg or IMoveLSL.
9952       if (format[5] == 'L') {
9953         AppendToOutput("#0x%" PRIx32, instr->GetImmMoveWide());
9954         if (instr->GetShiftMoveWide() > 0) {
9955           AppendToOutput(", lsl #%" PRId32, 16 * instr->GetShiftMoveWide());
9956         }
9957       } else {
9958         VIXL_ASSERT((format[5] == 'I') || (format[5] == 'N'));
9959         uint64_t imm = static_cast<uint64_t>(instr->GetImmMoveWide())
9960                        << (16 * instr->GetShiftMoveWide());
9961         if (format[5] == 'N') imm = ~imm;
9962         if (!instr->GetSixtyFourBits()) imm &= UINT64_C(0xffffffff);
9963         AppendToOutput("#0x%" PRIx64, imm);
9964       }
9965       return 8;
9966     }
9967     case 'L': {
9968       switch (format[2]) {
9969         case 'L': {  // ILLiteral - Immediate Load Literal.
9970           AppendToOutput("pc%+" PRId32,
9971                          instr->GetImmLLiteral() *
9972                              static_cast<int>(kLiteralEntrySize));
9973           return 9;
9974         }
9975         case 'S': {  // ILS - Immediate Load/Store.
9976                      // ILSi - As above, but an index field which must not be
9977                      // omitted even if it is zero.
9978           bool is_index = format[3] == 'i';
9979           if (is_index || (instr->GetImmLS() != 0)) {
9980             AppendToOutput(", #%" PRId32, instr->GetImmLS());
9981           }
9982           return is_index ? 4 : 3;
9983         }
9984         case 'P': {  // ILPx - Immediate Load/Store Pair, x = access size.
9985                      // ILPxi - As above, but an index field which must not be
9986                      // omitted even if it is zero.
9987           VIXL_ASSERT((format[3] >= '0') && (format[3] <= '9'));
9988           bool is_index = format[4] == 'i';
9989           if (is_index || (instr->GetImmLSPair() != 0)) {
9990             // format[3] is the scale value. Convert to a number.
9991             int scale = 1 << (format[3] - '0');
9992             AppendToOutput(", #%" PRId32, instr->GetImmLSPair() * scale);
9993           }
9994           return is_index ? 5 : 4;
9995         }
9996         case 'U': {  // ILU - Immediate Load/Store Unsigned.
9997           if (instr->GetImmLSUnsigned() != 0) {
9998             int shift = instr->GetSizeLS();
9999             AppendToOutput(", #%" PRId32, instr->GetImmLSUnsigned() << shift);
10000           }
10001           return 3;
10002         }
10003         case 'F': {  // ILF(CNR) - Immediate Rotation Value for Complex Numbers
10004           AppendToOutput("#%" PRId32, instr->GetImmRotFcmlaSca() * 90);
10005           return strlen("ILFCNR");
10006         }
10007         case 'A': {  // ILA - Immediate Load with pointer authentication.
10008           if (instr->GetImmLSPAC() != 0) {
10009             AppendToOutput(", #%" PRId32, instr->GetImmLSPAC());
10010           }
10011           return 3;
10012         }
10013         default: {
10014           VIXL_UNIMPLEMENTED();
10015           return 0;
10016         }
10017       }
10018     }
10019     case 'C': {  // ICondB - Immediate Conditional Branch.
10020       int64_t offset = instr->GetImmCondBranch() << 2;
10021       AppendPCRelativeOffsetToOutput(instr, offset);
10022       return 6;
10023     }
10024     case 'A': {  // IAddSub.
10025       int64_t imm = instr->GetImmAddSub() << (12 * instr->GetImmAddSubShift());
10026       AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm);
10027       return 7;
10028     }
10029     case 'F': {  // IFP, IFPNeon, IFPSve or IFPFBits.
10030       int imm8 = 0;
10031       int len = strlen("IFP");
10032       switch (format[3]) {
10033         case 'F':
10034           VIXL_ASSERT(strncmp(format, "IFPFBits", strlen("IFPFBits")) == 0);
10035           AppendToOutput("#%" PRId32, 64 - instr->GetFPScale());
10036           return strlen("IFPFBits");
10037         case 'N':
10038           VIXL_ASSERT(strncmp(format, "IFPNeon", strlen("IFPNeon")) == 0);
10039           imm8 = instr->GetImmNEONabcdefgh();
10040           len += strlen("Neon");
10041           break;
10042         case 'S':
10043           VIXL_ASSERT(strncmp(format, "IFPSve", strlen("IFPSve")) == 0);
10044           imm8 = instr->ExtractBits(12, 5);
10045           len += strlen("Sve");
10046           break;
10047         default:
10048           VIXL_ASSERT(strncmp(format, "IFP", strlen("IFP")) == 0);
10049           imm8 = instr->GetImmFP();
10050           break;
10051       }
10052       AppendToOutput("#0x%" PRIx32 " (%.4f)",
10053                      imm8,
10054                      Instruction::Imm8ToFP32(imm8));
10055       return len;
10056     }
10057     case 'H': {  // IH - ImmHint
10058       AppendToOutput("#%" PRId32, instr->GetImmHint());
10059       return 2;
10060     }
10061     case 'T': {  // ITri - Immediate Triangular Encoded.
10062       if (format[4] == 'S') {
10063         VIXL_ASSERT((format[5] == 'v') && (format[6] == 'e'));
10064         switch (format[7]) {
10065           case 'l':
10066             // SVE logical immediate encoding.
10067             AppendToOutput("#0x%" PRIx64, instr->GetSVEImmLogical());
10068             return 8;
10069           case 'p': {
10070             // SVE predicated shift immediate encoding, lsl.
10071             std::pair<int, int> shift_and_lane_size =
10072                 instr->GetSVEImmShiftAndLaneSizeLog2(
10073                     /* is_predicated = */ true);
10074             int lane_bits = 8 << shift_and_lane_size.second;
10075             AppendToOutput("#%" PRId32, lane_bits - shift_and_lane_size.first);
10076             return 8;
10077           }
10078           case 'q': {
10079             // SVE predicated shift immediate encoding, asr and lsr.
10080             std::pair<int, int> shift_and_lane_size =
10081                 instr->GetSVEImmShiftAndLaneSizeLog2(
10082                     /* is_predicated = */ true);
10083             AppendToOutput("#%" PRId32, shift_and_lane_size.first);
10084             return 8;
10085           }
10086           case 'r': {
10087             // SVE unpredicated shift immediate encoding, lsl.
10088             std::pair<int, int> shift_and_lane_size =
10089                 instr->GetSVEImmShiftAndLaneSizeLog2(
10090                     /* is_predicated = */ false);
10091             int lane_bits = 8 << shift_and_lane_size.second;
10092             AppendToOutput("#%" PRId32, lane_bits - shift_and_lane_size.first);
10093             return 8;
10094           }
10095           case 's': {
10096             // SVE unpredicated shift immediate encoding, asr and lsr.
10097             std::pair<int, int> shift_and_lane_size =
10098                 instr->GetSVEImmShiftAndLaneSizeLog2(
10099                     /* is_predicated = */ false);
10100             AppendToOutput("#%" PRId32, shift_and_lane_size.first);
10101             return 8;
10102           }
10103           default:
10104             VIXL_UNREACHABLE();
10105             return 0;
10106         }
10107       } else {
10108         AppendToOutput("#0x%" PRIx64, instr->GetImmLogical());
10109         return 4;
10110       }
10111     }
10112     case 'N': {  // INzcv.
10113       int nzcv = (instr->GetNzcv() << Flags_offset);
10114       AppendToOutput("#%c%c%c%c",
10115                      ((nzcv & NFlag) == 0) ? 'n' : 'N',
10116                      ((nzcv & ZFlag) == 0) ? 'z' : 'Z',
10117                      ((nzcv & CFlag) == 0) ? 'c' : 'C',
10118                      ((nzcv & VFlag) == 0) ? 'v' : 'V');
10119       return 5;
10120     }
10121     case 'P': {  // IP - Conditional compare.
10122       AppendToOutput("#%" PRId32, instr->GetImmCondCmp());
10123       return 2;
10124     }
10125     case 'B': {  // Bitfields.
10126       return SubstituteBitfieldImmediateField(instr, format);
10127     }
10128     case 'E': {  // IExtract.
10129       AppendToOutput("#%" PRId32, instr->GetImmS());
10130       return 8;
10131     }
10132     case 't': {  // It - Test and branch bit.
10133       AppendToOutput("#%" PRId32,
10134                      (instr->GetImmTestBranchBit5() << 5) |
10135                          instr->GetImmTestBranchBit40());
10136       return 2;
10137     }
10138     case 'S': {  // ISveSvl - SVE 'mul vl' immediate for structured ld/st.
10139       VIXL_ASSERT(strncmp(format, "ISveSvl", 7) == 0);
10140       int imm = instr->ExtractSignedBits(19, 16);
10141       if (imm != 0) {
10142         int reg_count = instr->ExtractBits(22, 21) + 1;
10143         AppendToOutput(", #%d, mul vl", imm * reg_count);
10144       }
10145       return 7;
10146     }
10147     case 's': {  // Is - Shift (immediate).
10148       switch (format[2]) {
10149         case '1': {  // Is1 - SSHR.
10150           int shift = 16 << HighestSetBitPosition(instr->GetImmNEONImmh());
10151           shift -= instr->GetImmNEONImmhImmb();
10152           AppendToOutput("#%d", shift);
10153           return 3;
10154         }
10155         case '2': {  // Is2 - SLI.
10156           int shift = instr->GetImmNEONImmhImmb();
10157           shift -= 8 << HighestSetBitPosition(instr->GetImmNEONImmh());
10158           AppendToOutput("#%d", shift);
10159           return 3;
10160         }
10161         default: {
10162           VIXL_UNIMPLEMENTED();
10163           return 0;
10164         }
10165       }
10166     }
10167     case 'D': {  // IDebug - HLT and BRK instructions.
10168       AppendToOutput("#0x%" PRIx32, instr->GetImmException());
10169       return 6;
10170     }
10171     case 'U': {  // IUdf - UDF immediate.
10172       AppendToOutput("#0x%" PRIx32, instr->GetImmUdf());
10173       return 4;
10174     }
10175     case 'V': {  // Immediate Vector.
10176       switch (format[2]) {
10177         case 'F': {
10178           switch (format[5]) {
10179             // Convert 'rot' bit encodings into equivalent angle rotation
10180             case 'A':
10181               AppendToOutput("#%" PRId32,
10182                              instr->GetImmRotFcadd() == 1 ? 270 : 90);
10183               break;
10184             case 'M':
10185               AppendToOutput("#%" PRId32, instr->GetImmRotFcmlaVec() * 90);
10186               break;
10187           }
10188           return strlen("IVFCN") + 1;
10189         }
10190         case 'E': {  // IVExtract.
10191           AppendToOutput("#%" PRId32, instr->GetImmNEONExt());
10192           return 9;
10193         }
10194         case 'B': {  // IVByElemIndex.
10195           int ret = strlen("IVByElemIndex");
10196           int vm_index = (instr->GetNEONH() << 1) | instr->GetNEONL();
10197           static const char *format_rot = "IVByElemIndexRot";
10198           static const char *format_fhm = "IVByElemIndexFHM";
10199           bool is_fhm = strncmp(format, format_fhm, strlen(format_fhm)) == 0;
10200           if (strncmp(format, format_rot, strlen(format_rot)) == 0) {
10201             // FCMLA uses 'H' bit index when SIZE is 2, else H:L
10202             if (instr->GetNEONSize() == 2) {
10203               vm_index = instr->GetNEONH();
10204             }
10205             ret = static_cast<int>(strlen(format_rot));
10206           } else if (is_fhm || (instr->GetNEONSize() == 0)) {
10207             // Half-precision FP ops use H:L:M bit index
10208             // Widening operations with H-sized operands also use H:L:M.
10209             vm_index = (instr->GetNEONH() << 2) | (instr->GetNEONL() << 1) |
10210                        instr->GetNEONM();
10211             if (is_fhm) ret = static_cast<int>(strlen(format_fhm));
10212           } else if (instr->GetNEONSize() == 1) {
10213             vm_index = (vm_index << 1) | instr->GetNEONM();
10214           }
10215           AppendToOutput("%d", vm_index);
10216           return ret;
10217         }
10218         case 'I': {  // INS element.
10219           if (strncmp(format, "IVInsIndex", strlen("IVInsIndex")) == 0) {
10220             unsigned rd_index, rn_index;
10221             unsigned imm5 = instr->GetImmNEON5();
10222             unsigned imm4 = instr->GetImmNEON4();
10223             int tz = CountTrailingZeros(imm5, 32);
10224             if (tz <= 3) {  // Defined for tz = 0 to 3 only.
10225               rd_index = imm5 >> (tz + 1);
10226               rn_index = imm4 >> tz;
10227               if (strncmp(format, "IVInsIndex1", strlen("IVInsIndex1")) == 0) {
10228                 AppendToOutput("%d", rd_index);
10229                 return strlen("IVInsIndex1");
10230               } else if (strncmp(format,
10231                                  "IVInsIndex2",
10232                                  strlen("IVInsIndex2")) == 0) {
10233                 AppendToOutput("%d", rn_index);
10234                 return strlen("IVInsIndex2");
10235               }
10236             }
10237             return 0;
10238           } else if (strncmp(format,
10239                              "IVInsSVEIndex",
10240                              strlen("IVInsSVEIndex")) == 0) {
10241             std::pair<int, int> index_and_lane_size =
10242                 instr->GetSVEPermuteIndexAndLaneSizeLog2();
10243             AppendToOutput("%d", index_and_lane_size.first);
10244             return strlen("IVInsSVEIndex");
10245           }
10246           VIXL_FALLTHROUGH();
10247         }
10248         case 'L': {  // IVLSLane[0123] - suffix indicates access size shift.
10249           AppendToOutput("%d", instr->GetNEONLSIndex(format[8] - '0'));
10250           return 9;
10251         }
10252         case 'M': {  // Modified Immediate cases.
10253           if (strncmp(format, "IVMIImm8", strlen("IVMIImm8")) == 0) {
10254             uint64_t imm8 = instr->GetImmNEONabcdefgh();
10255             AppendToOutput("#0x%" PRIx64, imm8);
10256             return strlen("IVMIImm8");
10257           } else if (strncmp(format, "IVMIImm", strlen("IVMIImm")) == 0) {
10258             uint64_t imm8 = instr->GetImmNEONabcdefgh();
10259             uint64_t imm = 0;
10260             for (int i = 0; i < 8; ++i) {
10261               if (imm8 & (1 << i)) {
10262                 imm |= (UINT64_C(0xff) << (8 * i));
10263               }
10264             }
10265             AppendToOutput("#0x%" PRIx64, imm);
10266             return strlen("IVMIImm");
10267           } else if (strncmp(format,
10268                              "IVMIShiftAmt1",
10269                              strlen("IVMIShiftAmt1")) == 0) {
10270             int cmode = instr->GetNEONCmode();
10271             int shift_amount = 8 * ((cmode >> 1) & 3);
10272             AppendToOutput("#%d", shift_amount);
10273             return strlen("IVMIShiftAmt1");
10274           } else if (strncmp(format,
10275                              "IVMIShiftAmt2",
10276                              strlen("IVMIShiftAmt2")) == 0) {
10277             int cmode = instr->GetNEONCmode();
10278             int shift_amount = 8 << (cmode & 1);
10279             AppendToOutput("#%d", shift_amount);
10280             return strlen("IVMIShiftAmt2");
10281           } else {
10282             VIXL_UNIMPLEMENTED();
10283             return 0;
10284           }
10285         }
10286         default: {
10287           VIXL_UNIMPLEMENTED();
10288           return 0;
10289         }
10290       }
10291     }
10292     case 'X': {  // IX - CLREX instruction.
10293       AppendToOutput("#0x%" PRIx32, instr->GetCRm());
10294       return 2;
10295     }
10296     case 'Y': {  // IY - system register immediate.
10297       switch (instr->GetImmSystemRegister()) {
10298         case NZCV:
10299           AppendToOutput("nzcv");
10300           break;
10301         case FPCR:
10302           AppendToOutput("fpcr");
10303           break;
10304         case RNDR:
10305           AppendToOutput("rndr");
10306           break;
10307         case RNDRRS:
10308           AppendToOutput("rndrrs");
10309           break;
10310         default:
10311           AppendToOutput("S%d_%d_c%d_c%d_%d",
10312                          instr->GetSysOp0(),
10313                          instr->GetSysOp1(),
10314                          instr->GetCRn(),
10315                          instr->GetCRm(),
10316                          instr->GetSysOp2());
10317           break;
10318       }
10319       return 2;
10320     }
10321     case 'R': {  // IR - Rotate right into flags.
10322       switch (format[2]) {
10323         case 'r': {  // IRr - Rotate amount.
10324           AppendToOutput("#%d", instr->GetImmRMIFRotation());
10325           return 3;
10326         }
10327         default: {
10328           VIXL_UNIMPLEMENTED();
10329           return 0;
10330         }
10331       }
10332     }
10333     case 'p': {  // Ipc - SVE predicate constraint specifier.
10334       VIXL_ASSERT(format[2] == 'c');
10335       unsigned pattern = instr->GetImmSVEPredicateConstraint();
10336       switch (pattern) {
10337         // VL1-VL8 are encoded directly.
10338         case SVE_VL1:
10339         case SVE_VL2:
10340         case SVE_VL3:
10341         case SVE_VL4:
10342         case SVE_VL5:
10343         case SVE_VL6:
10344         case SVE_VL7:
10345         case SVE_VL8:
10346           AppendToOutput("vl%u", pattern);
10347           break;
10348         // VL16-VL256 are encoded as log2(N) + c.
10349         case SVE_VL16:
10350         case SVE_VL32:
10351         case SVE_VL64:
10352         case SVE_VL128:
10353         case SVE_VL256:
10354           AppendToOutput("vl%u", 16 << (pattern - SVE_VL16));
10355           break;
10356         // Special cases.
10357         case SVE_POW2:
10358           AppendToOutput("pow2");
10359           break;
10360         case SVE_MUL4:
10361           AppendToOutput("mul4");
10362           break;
10363         case SVE_MUL3:
10364           AppendToOutput("mul3");
10365           break;
10366         case SVE_ALL:
10367           AppendToOutput("all");
10368           break;
10369         default:
10370           AppendToOutput("#0x%x", pattern);
10371           break;
10372       }
10373       return 3;
10374     }
10375     default: {
10376       VIXL_UNIMPLEMENTED();
10377       return 0;
10378     }
10379   }
10380 }
10381 
10382 
SubstituteBitfieldImmediateField(const Instruction * instr,const char * format)10383 int Disassembler::SubstituteBitfieldImmediateField(const Instruction *instr,
10384                                                    const char *format) {
10385   VIXL_ASSERT((format[0] == 'I') && (format[1] == 'B'));
10386   unsigned r = instr->GetImmR();
10387   unsigned s = instr->GetImmS();
10388 
10389   switch (format[2]) {
10390     case 'r': {  // IBr.
10391       AppendToOutput("#%d", r);
10392       return 3;
10393     }
10394     case 's': {  // IBs+1 or IBs-r+1.
10395       if (format[3] == '+') {
10396         AppendToOutput("#%d", s + 1);
10397         return 5;
10398       } else {
10399         VIXL_ASSERT(format[3] == '-');
10400         AppendToOutput("#%d", s - r + 1);
10401         return 7;
10402       }
10403     }
10404     case 'Z': {  // IBZ-r.
10405       VIXL_ASSERT((format[3] == '-') && (format[4] == 'r'));
10406       unsigned reg_size =
10407           (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
10408       AppendToOutput("#%d", reg_size - r);
10409       return 5;
10410     }
10411     default: {
10412       VIXL_UNREACHABLE();
10413       return 0;
10414     }
10415   }
10416 }
10417 
10418 
SubstituteLiteralField(const Instruction * instr,const char * format)10419 int Disassembler::SubstituteLiteralField(const Instruction *instr,
10420                                          const char *format) {
10421   VIXL_ASSERT(strncmp(format, "LValue", 6) == 0);
10422   USE(format);
10423 
10424   const void *address = instr->GetLiteralAddress<const void *>();
10425   switch (instr->Mask(LoadLiteralMask)) {
10426     case LDR_w_lit:
10427     case LDR_x_lit:
10428     case LDRSW_x_lit:
10429     case LDR_s_lit:
10430     case LDR_d_lit:
10431     case LDR_q_lit:
10432       AppendCodeRelativeDataAddressToOutput(instr, address);
10433       break;
10434     case PRFM_lit: {
10435       // Use the prefetch hint to decide how to print the address.
10436       switch (instr->GetPrefetchHint()) {
10437         case 0x0:  // PLD: prefetch for load.
10438         case 0x2:  // PST: prepare for store.
10439           AppendCodeRelativeDataAddressToOutput(instr, address);
10440           break;
10441         case 0x1:  // PLI: preload instructions.
10442           AppendCodeRelativeCodeAddressToOutput(instr, address);
10443           break;
10444         case 0x3:  // Unallocated hint.
10445           AppendCodeRelativeAddressToOutput(instr, address);
10446           break;
10447       }
10448       break;
10449     }
10450     default:
10451       VIXL_UNREACHABLE();
10452   }
10453 
10454   return 6;
10455 }
10456 
10457 
SubstituteShiftField(const Instruction * instr,const char * format)10458 int Disassembler::SubstituteShiftField(const Instruction *instr,
10459                                        const char *format) {
10460   VIXL_ASSERT(format[0] == 'N');
10461   VIXL_ASSERT(instr->GetShiftDP() <= 0x3);
10462 
10463   switch (format[1]) {
10464     case 'D': {  // NDP.
10465       VIXL_ASSERT(instr->GetShiftDP() != ROR);
10466       VIXL_FALLTHROUGH();
10467     }
10468     case 'L': {  // NLo.
10469       if (instr->GetImmDPShift() != 0) {
10470         const char *shift_type[] = {"lsl", "lsr", "asr", "ror"};
10471         AppendToOutput(", %s #%" PRId32,
10472                        shift_type[instr->GetShiftDP()],
10473                        instr->GetImmDPShift());
10474       }
10475       return 3;
10476     }
10477     case 'S': {  // NSveS (SVE structured load/store indexing shift).
10478       VIXL_ASSERT(strncmp(format, "NSveS", 5) == 0);
10479       int msz = instr->ExtractBits(24, 23);
10480       if (msz > 0) {
10481         AppendToOutput(", lsl #%d", msz);
10482       }
10483       return 5;
10484     }
10485     default:
10486       VIXL_UNIMPLEMENTED();
10487       return 0;
10488   }
10489 }
10490 
10491 
SubstituteConditionField(const Instruction * instr,const char * format)10492 int Disassembler::SubstituteConditionField(const Instruction *instr,
10493                                            const char *format) {
10494   VIXL_ASSERT(format[0] == 'C');
10495   const char *condition_code[] = {"eq",
10496                                   "ne",
10497                                   "hs",
10498                                   "lo",
10499                                   "mi",
10500                                   "pl",
10501                                   "vs",
10502                                   "vc",
10503                                   "hi",
10504                                   "ls",
10505                                   "ge",
10506                                   "lt",
10507                                   "gt",
10508                                   "le",
10509                                   "al",
10510                                   "nv"};
10511   int cond;
10512   switch (format[1]) {
10513     case 'B':
10514       cond = instr->GetConditionBranch();
10515       break;
10516     case 'I': {
10517       cond = InvertCondition(static_cast<Condition>(instr->GetCondition()));
10518       break;
10519     }
10520     default:
10521       cond = instr->GetCondition();
10522   }
10523   AppendToOutput("%s", condition_code[cond]);
10524   return 4;
10525 }
10526 
10527 
SubstitutePCRelAddressField(const Instruction * instr,const char * format)10528 int Disassembler::SubstitutePCRelAddressField(const Instruction *instr,
10529                                               const char *format) {
10530   VIXL_ASSERT((strcmp(format, "AddrPCRelByte") == 0) ||  // Used by `adr`.
10531               (strcmp(format, "AddrPCRelPage") == 0));   // Used by `adrp`.
10532 
10533   int64_t offset = instr->GetImmPCRel();
10534 
10535   // Compute the target address based on the effective address (after applying
10536   // code_address_offset). This is required for correct behaviour of adrp.
10537   const Instruction *base = instr + code_address_offset();
10538   if (format[9] == 'P') {
10539     offset *= kPageSize;
10540     base = AlignDown(base, kPageSize);
10541   }
10542   // Strip code_address_offset before printing, so we can use the
10543   // semantically-correct AppendCodeRelativeAddressToOutput.
10544   const void *target =
10545       reinterpret_cast<const void *>(base + offset - code_address_offset());
10546 
10547   AppendPCRelativeOffsetToOutput(instr, offset);
10548   AppendToOutput(" ");
10549   AppendCodeRelativeAddressToOutput(instr, target);
10550   return 13;
10551 }
10552 
10553 
SubstituteBranchTargetField(const Instruction * instr,const char * format)10554 int Disassembler::SubstituteBranchTargetField(const Instruction *instr,
10555                                               const char *format) {
10556   VIXL_ASSERT(strncmp(format, "TImm", 4) == 0);
10557 
10558   int64_t offset = 0;
10559   switch (format[5]) {
10560     // BImmUncn - unconditional branch immediate.
10561     case 'n':
10562       offset = instr->GetImmUncondBranch();
10563       break;
10564     // BImmCond - conditional branch immediate.
10565     case 'o':
10566       offset = instr->GetImmCondBranch();
10567       break;
10568     // BImmCmpa - compare and branch immediate.
10569     case 'm':
10570       offset = instr->GetImmCmpBranch();
10571       break;
10572     // BImmTest - test and branch immediate.
10573     case 'e':
10574       offset = instr->GetImmTestBranch();
10575       break;
10576     default:
10577       VIXL_UNIMPLEMENTED();
10578   }
10579   offset *= static_cast<int>(kInstructionSize);
10580   const void *target_address = reinterpret_cast<const void *>(instr + offset);
10581   VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
10582 
10583   AppendPCRelativeOffsetToOutput(instr, offset);
10584   AppendToOutput(" ");
10585   AppendCodeRelativeCodeAddressToOutput(instr, target_address);
10586 
10587   return 8;
10588 }
10589 
10590 
SubstituteExtendField(const Instruction * instr,const char * format)10591 int Disassembler::SubstituteExtendField(const Instruction *instr,
10592                                         const char *format) {
10593   VIXL_ASSERT(strncmp(format, "Ext", 3) == 0);
10594   VIXL_ASSERT(instr->GetExtendMode() <= 7);
10595   USE(format);
10596 
10597   const char *extend_mode[] =
10598       {"uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx"};
10599 
10600   // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit
10601   // registers becomes lsl.
10602   if (((instr->GetRd() == kZeroRegCode) || (instr->GetRn() == kZeroRegCode)) &&
10603       (((instr->GetExtendMode() == UXTW) && (instr->GetSixtyFourBits() == 0)) ||
10604        (instr->GetExtendMode() == UXTX))) {
10605     if (instr->GetImmExtendShift() > 0) {
10606       AppendToOutput(", lsl #%" PRId32, instr->GetImmExtendShift());
10607     }
10608   } else {
10609     AppendToOutput(", %s", extend_mode[instr->GetExtendMode()]);
10610     if (instr->GetImmExtendShift() > 0) {
10611       AppendToOutput(" #%" PRId32, instr->GetImmExtendShift());
10612     }
10613   }
10614   return 3;
10615 }
10616 
10617 
SubstituteLSRegOffsetField(const Instruction * instr,const char * format)10618 int Disassembler::SubstituteLSRegOffsetField(const Instruction *instr,
10619                                              const char *format) {
10620   VIXL_ASSERT(strncmp(format, "Offsetreg", 9) == 0);
10621   const char *extend_mode[] = {"undefined",
10622                                "undefined",
10623                                "uxtw",
10624                                "lsl",
10625                                "undefined",
10626                                "undefined",
10627                                "sxtw",
10628                                "sxtx"};
10629   USE(format);
10630 
10631   unsigned shift = instr->GetImmShiftLS();
10632   Extend ext = static_cast<Extend>(instr->GetExtendMode());
10633   char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x';
10634 
10635   unsigned rm = instr->GetRm();
10636   if (rm == kZeroRegCode) {
10637     AppendToOutput("%czr", reg_type);
10638   } else {
10639     AppendToOutput("%c%d", reg_type, rm);
10640   }
10641 
10642   // Extend mode UXTX is an alias for shift mode LSL here.
10643   if (!((ext == UXTX) && (shift == 0))) {
10644     AppendToOutput(", %s", extend_mode[ext]);
10645     if (shift != 0) {
10646       AppendToOutput(" #%d", instr->GetSizeLS());
10647     }
10648   }
10649   return 9;
10650 }
10651 
10652 
SubstitutePrefetchField(const Instruction * instr,const char * format)10653 int Disassembler::SubstitutePrefetchField(const Instruction *instr,
10654                                           const char *format) {
10655   VIXL_ASSERT(format[0] == 'p');
10656   USE(format);
10657 
10658   bool is_sve =
10659       (strncmp(format, "prefSVEOp", strlen("prefSVEOp")) == 0) ? true : false;
10660   int placeholder_length = is_sve ? 9 : 6;
10661   static const char *stream_options[] = {"keep", "strm"};
10662 
10663   auto get_hints = [](bool is_sve) -> std::vector<std::string> {
10664     static const std::vector<std::string> sve_hints = {"ld", "st"};
10665     static const std::vector<std::string> core_hints = {"ld", "li", "st"};
10666     return (is_sve) ? sve_hints : core_hints;
10667   };
10668 
10669   std::vector<std::string> hints = get_hints(is_sve);
10670   unsigned hint =
10671       is_sve ? instr->GetSVEPrefetchHint() : instr->GetPrefetchHint();
10672   unsigned target = instr->GetPrefetchTarget() + 1;
10673   unsigned stream = instr->GetPrefetchStream();
10674 
10675   if ((hint >= hints.size()) || (target > 3)) {
10676     // Unallocated prefetch operations.
10677     if (is_sve) {
10678       std::bitset<4> prefetch_mode(instr->GetSVEImmPrefetchOperation());
10679       AppendToOutput("#0b%s", prefetch_mode.to_string().c_str());
10680     } else {
10681       std::bitset<5> prefetch_mode(instr->GetImmPrefetchOperation());
10682       AppendToOutput("#0b%s", prefetch_mode.to_string().c_str());
10683     }
10684   } else {
10685     VIXL_ASSERT(stream < ArrayLength(stream_options));
10686     AppendToOutput("p%sl%d%s",
10687                    hints[hint].c_str(),
10688                    target,
10689                    stream_options[stream]);
10690   }
10691   return placeholder_length;
10692 }
10693 
SubstituteBarrierField(const Instruction * instr,const char * format)10694 int Disassembler::SubstituteBarrierField(const Instruction *instr,
10695                                          const char *format) {
10696   VIXL_ASSERT(format[0] == 'M');
10697   USE(format);
10698 
10699   static const char *options[4][4] = {{"sy (0b0000)", "oshld", "oshst", "osh"},
10700                                       {"sy (0b0100)", "nshld", "nshst", "nsh"},
10701                                       {"sy (0b1000)", "ishld", "ishst", "ish"},
10702                                       {"sy (0b1100)", "ld", "st", "sy"}};
10703   int domain = instr->GetImmBarrierDomain();
10704   int type = instr->GetImmBarrierType();
10705 
10706   AppendToOutput("%s", options[domain][type]);
10707   return 1;
10708 }
10709 
SubstituteSysOpField(const Instruction * instr,const char * format)10710 int Disassembler::SubstituteSysOpField(const Instruction *instr,
10711                                        const char *format) {
10712   VIXL_ASSERT(format[0] == 'G');
10713   int op = -1;
10714   switch (format[1]) {
10715     case '1':
10716       op = instr->GetSysOp1();
10717       break;
10718     case '2':
10719       op = instr->GetSysOp2();
10720       break;
10721     default:
10722       VIXL_UNREACHABLE();
10723   }
10724   AppendToOutput("#%d", op);
10725   return 2;
10726 }
10727 
SubstituteCrField(const Instruction * instr,const char * format)10728 int Disassembler::SubstituteCrField(const Instruction *instr,
10729                                     const char *format) {
10730   VIXL_ASSERT(format[0] == 'K');
10731   int cr = -1;
10732   switch (format[1]) {
10733     case 'n':
10734       cr = instr->GetCRn();
10735       break;
10736     case 'm':
10737       cr = instr->GetCRm();
10738       break;
10739     default:
10740       VIXL_UNREACHABLE();
10741   }
10742   AppendToOutput("C%d", cr);
10743   return 2;
10744 }
10745 
SubstituteIntField(const Instruction * instr,const char * format)10746 int Disassembler::SubstituteIntField(const Instruction *instr,
10747                                      const char *format) {
10748   VIXL_ASSERT((format[0] == 'u') || (format[0] == 's'));
10749 
10750   // A generic signed or unsigned int field uses a placeholder of the form
10751   // 'sAABB and 'uAABB respectively where AA and BB are two digit bit positions
10752   // between 00 and 31, and AA >= BB. The placeholder is substituted with the
10753   // decimal integer represented by the bits in the instruction between
10754   // positions AA and BB inclusive.
10755   //
10756   // In addition, split fields can be represented using 'sAABB:CCDD, where CCDD
10757   // become the least-significant bits of the result, and bit AA is the sign bit
10758   // (if 's is used).
10759   int32_t bits = 0;
10760   int width = 0;
10761   const char *c = format;
10762   do {
10763     c++;  // Skip the 'u', 's' or ':'.
10764     VIXL_ASSERT(strspn(c, "0123456789") == 4);
10765     int msb = ((c[0] - '0') * 10) + (c[1] - '0');
10766     int lsb = ((c[2] - '0') * 10) + (c[3] - '0');
10767     c += 4;  // Skip the characters we just read.
10768     int chunk_width = msb - lsb + 1;
10769     VIXL_ASSERT((chunk_width > 0) && (chunk_width < 32));
10770     bits = (bits << chunk_width) | (instr->ExtractBits(msb, lsb));
10771     width += chunk_width;
10772   } while (*c == ':');
10773   VIXL_ASSERT(IsUintN(width, bits));
10774 
10775   if (format[0] == 's') {
10776     bits = ExtractSignedBitfield32(width - 1, 0, bits);
10777   }
10778 
10779   if (*c == '+') {
10780     // A "+n" trailing the format specifier indicates the extracted value should
10781     // be incremented by n. This is for cases where the encoding is zero-based,
10782     // but range of values is not, eg. values [1, 16] encoded as [0, 15]
10783     char *new_c;
10784     uint64_t value = strtoul(c + 1, &new_c, 10);
10785     c = new_c;
10786     VIXL_ASSERT(IsInt32(value));
10787     bits += value;
10788   } else if (*c == '*') {
10789     // Similarly, a "*n" trailing the format specifier indicates the extracted
10790     // value should be multiplied by n. This is for cases where the encoded
10791     // immediate is scaled, for example by access size.
10792     char *new_c;
10793     uint64_t value = strtoul(c + 1, &new_c, 10);
10794     c = new_c;
10795     VIXL_ASSERT(IsInt32(value));
10796     bits *= value;
10797   }
10798 
10799   AppendToOutput("%d", bits);
10800 
10801   return static_cast<int>(c - format);
10802 }
10803 
SubstituteSVESize(const Instruction * instr,const char * format)10804 int Disassembler::SubstituteSVESize(const Instruction *instr,
10805                                     const char *format) {
10806   USE(format);
10807   VIXL_ASSERT(format[0] == 't');
10808 
10809   static const char sizes[] = {'b', 'h', 's', 'd', 'q'};
10810   // TODO: only the most common case for <size> is supported at the moment,
10811   // and even then, the RESERVED values are handled as if they're not
10812   // reserved.
10813   unsigned size_in_bytes_log2 = instr->GetSVESize();
10814   int placeholder_length = 1;
10815   switch (format[1]) {
10816     case 'l':
10817       placeholder_length++;
10818       if (format[2] == 's') {
10819         // 'tls: Loads and stores
10820         size_in_bytes_log2 = instr->ExtractBits(22, 21);
10821         placeholder_length++;
10822         if (format[3] == 's') {
10823           // Sign extension load.
10824           unsigned msize = instr->ExtractBits(24, 23);
10825           if (msize > size_in_bytes_log2) size_in_bytes_log2 ^= 0x3;
10826           placeholder_length++;
10827         }
10828       } else {
10829         // 'tl: Logical operations
10830         size_in_bytes_log2 = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
10831       }
10832       break;
10833     case 'm':  // 'tmsz
10834       VIXL_ASSERT(strncmp(format, "tmsz", 4) == 0);
10835       placeholder_length += 3;
10836       size_in_bytes_log2 = instr->ExtractBits(24, 23);
10837       break;
10838     case 's':
10839       if (format[2] == 'z') {
10840         VIXL_ASSERT((format[3] == 'x') || (format[3] == 's') ||
10841                     (format[3] == 'p'));
10842         if (format[3] == 'x') {
10843           // 'tszx: Indexes.
10844           std::pair<int, int> index_and_lane_size =
10845               instr->GetSVEPermuteIndexAndLaneSizeLog2();
10846           size_in_bytes_log2 = index_and_lane_size.second;
10847         } else if (format[3] == 'p') {
10848           // 'tszp: Predicated shifts.
10849           std::pair<int, int> shift_and_lane_size =
10850               instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
10851           size_in_bytes_log2 = shift_and_lane_size.second;
10852         } else {
10853           // 'tszs: Unpredicated shifts.
10854           std::pair<int, int> shift_and_lane_size =
10855               instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
10856           size_in_bytes_log2 = shift_and_lane_size.second;
10857         }
10858         placeholder_length += 3;  // skip `sz[x|s]`
10859       }
10860       break;
10861     case 'h':
10862       // Half size of the lane size field.
10863       size_in_bytes_log2 -= 1;
10864       placeholder_length++;
10865       break;
10866     case 'q':
10867       // Quarter size of the lane size field.
10868       size_in_bytes_log2 -= 2;
10869       placeholder_length++;
10870       break;
10871     default:
10872       break;
10873   }
10874 
10875   VIXL_ASSERT(size_in_bytes_log2 < ArrayLength(sizes));
10876   AppendToOutput("%c", sizes[size_in_bytes_log2]);
10877 
10878   return placeholder_length;
10879 }
10880 
SubstituteTernary(const Instruction * instr,const char * format)10881 int Disassembler::SubstituteTernary(const Instruction *instr,
10882                                     const char *format) {
10883   VIXL_ASSERT((format[0] == '?') && (format[3] == ':'));
10884 
10885   // The ternary substitution of the format "'?bb:TF" is replaced by a single
10886   // character, either T or F, depending on the value of the bit at position
10887   // bb in the instruction. For example, "'?31:xw" is substituted with "x" if
10888   // bit 31 is true, and "w" otherwise.
10889   VIXL_ASSERT(strspn(&format[1], "0123456789") == 2);
10890   char *c;
10891   uint64_t value = strtoul(&format[1], &c, 10);
10892   VIXL_ASSERT(value < (kInstructionSize * kBitsPerByte));
10893   VIXL_ASSERT((*c == ':') && (strlen(c) >= 3));  // Minimum of ":TF"
10894   c++;
10895   AppendToOutput("%c", c[1 - instr->ExtractBit(static_cast<int>(value))]);
10896   return 6;
10897 }
10898 
ResetOutput()10899 void Disassembler::ResetOutput() {
10900   buffer_pos_ = 0;
10901   buffer_[buffer_pos_] = 0;
10902 }
10903 
10904 
AppendToOutput(const char * format,...)10905 void Disassembler::AppendToOutput(const char *format, ...) {
10906   va_list args;
10907   va_start(args, format);
10908   buffer_pos_ += vsnprintf(&buffer_[buffer_pos_],
10909                            buffer_size_ - buffer_pos_,
10910                            format,
10911                            args);
10912   va_end(args);
10913 }
10914 
10915 
Disassemble(const Instruction * instr)10916 void PrintDisassembler::Disassemble(const Instruction *instr) {
10917   Decoder decoder;
10918   if (cpu_features_auditor_ != NULL) {
10919     decoder.AppendVisitor(cpu_features_auditor_);
10920   }
10921   decoder.AppendVisitor(this);
10922   decoder.Decode(instr);
10923 }
10924 
DisassembleBuffer(const Instruction * start,const Instruction * end)10925 void PrintDisassembler::DisassembleBuffer(const Instruction *start,
10926                                           const Instruction *end) {
10927   Decoder decoder;
10928   if (cpu_features_auditor_ != NULL) {
10929     decoder.AppendVisitor(cpu_features_auditor_);
10930   }
10931   decoder.AppendVisitor(this);
10932   decoder.Decode(start, end);
10933 }
10934 
DisassembleBuffer(const Instruction * start,uint64_t size)10935 void PrintDisassembler::DisassembleBuffer(const Instruction *start,
10936                                           uint64_t size) {
10937   DisassembleBuffer(start, start + size);
10938 }
10939 
10940 
ProcessOutput(const Instruction * instr)10941 void PrintDisassembler::ProcessOutput(const Instruction *instr) {
10942   int64_t address = CodeRelativeAddress(instr);
10943 
10944   uint64_t abs_address;
10945   const char *sign;
10946   if (signed_addresses_) {
10947     if (address < 0) {
10948       sign = "-";
10949       abs_address = -static_cast<uint64_t>(address);
10950     } else {
10951       // Leave a leading space, to maintain alignment.
10952       sign = " ";
10953       abs_address = address;
10954     }
10955   } else {
10956     sign = "";
10957     abs_address = address;
10958   }
10959 
10960   int bytes_printed = fprintf(stream_,
10961                               "%s0x%016" PRIx64 "  %08" PRIx32 "\t\t%s",
10962                               sign,
10963                               abs_address,
10964                               instr->GetInstructionBits(),
10965                               GetOutput());
10966   if (cpu_features_auditor_ != NULL) {
10967     CPUFeatures needs = cpu_features_auditor_->GetInstructionFeatures();
10968     needs.Remove(cpu_features_auditor_->GetAvailableFeatures());
10969     if (needs != CPUFeatures::None()) {
10970       // Try to align annotations. This value is arbitrary, but based on looking
10971       // good with most instructions. Note that, for historical reasons, the
10972       // disassembly itself is printed with tab characters, so bytes_printed is
10973       // _not_ equivalent to the number of occupied screen columns. However, the
10974       // prefix before the tabs is always the same length, so the annotation
10975       // indentation does not change from one line to the next.
10976       const int indent_to = 70;
10977       // Always allow some space between the instruction and the annotation.
10978       const int min_pad = 2;
10979 
10980       int pad = std::max(min_pad, (indent_to - bytes_printed));
10981       fprintf(stream_, "%*s", pad, "");
10982 
10983       std::stringstream features;
10984       features << needs;
10985       fprintf(stream_,
10986               "%s%s%s",
10987               cpu_features_prefix_,
10988               features.str().c_str(),
10989               cpu_features_suffix_);
10990     }
10991   }
10992   fprintf(stream_, "\n");
10993 }
10994 
10995 }  // namespace aarch64
10996 }  // namespace vixl
10997