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