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