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