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