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
30namespace vixl {
31
32Disassembler::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
41Disassembler::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
50Disassembler::~Disassembler() {
51  if (own_buffer_) {
52    free(buffer_);
53  }
54}
55
56
57char* Disassembler::GetOutput() {
58  return buffer_;
59}
60
61
62void 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
107void 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
154void 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
192void 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
227void 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
270bool 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
299void 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
350void 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
365void 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
380void 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
433void 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
511void 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
532void 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
541void 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
549void 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
570void 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
583void 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
604void 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
634void 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
712void 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
727void 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
744void 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
805void 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
819void 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
833void 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
848void 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
863void 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
905void 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
944void 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
958void 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
972void 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
986void 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
1007void 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
1050void 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
1070void 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
1085void 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
1098void 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
1130void 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
1154void 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
1173void 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
1186void 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
1252void 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
1280void 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
1378void 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
1397void Disassembler::VisitCrypto2RegSHA(const Instruction* instr) {
1398  VisitUnimplemented(instr);
1399}
1400
1401
1402void Disassembler::VisitCrypto3RegSHA(const Instruction* instr) {
1403  VisitUnimplemented(instr);
1404}
1405
1406
1407void Disassembler::VisitCryptoAES(const Instruction* instr) {
1408  VisitUnimplemented(instr);
1409}
1410
1411
1412void 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
1561void 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
1638void 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
1707void 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
1747void 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
1797void 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
1847void 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
1859void 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
1890void 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
1923void 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
2029void 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
2132void 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
2195void 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
2264void 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
2280void 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
2330void 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
2375void 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
2390void 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
2410void 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
2480void 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
2587void 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
2621void 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
2639void Disassembler::VisitUnimplemented(const Instruction* instr) {
2640  Format(instr, "unimplemented", "(Unimplemented)");
2641}
2642
2643
2644void Disassembler::VisitUnallocated(const Instruction* instr) {
2645  Format(instr, "unallocated", "(Unallocated)");
2646}
2647
2648
2649void Disassembler::ProcessOutput(const Instruction* /*instr*/) {
2650  // The base disasm does nothing more than disassembling into a buffer.
2651}
2652
2653
2654void 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
2688void Disassembler::AppendPCRelativeOffsetToOutput(const Instruction* instr,
2689                                                  int64_t offset) {
2690  USE(instr);
2691  char sign = (offset < 0) ? '-' : '+';
2692  AppendToOutput("#%c0x%" PRIx64, sign, std::abs(offset));
2693}
2694
2695
2696void Disassembler::AppendAddressToOutput(const Instruction* instr,
2697                                         const void* addr) {
2698  USE(instr);
2699  AppendToOutput("(addr 0x%" PRIxPTR ")", reinterpret_cast<uintptr_t>(addr));
2700}
2701
2702
2703void Disassembler::AppendCodeAddressToOutput(const Instruction* instr,
2704                                             const void* addr) {
2705  AppendAddressToOutput(instr, addr);
2706}
2707
2708
2709void Disassembler::AppendDataAddressToOutput(const Instruction* instr,
2710                                             const void* addr) {
2711  AppendAddressToOutput(instr, addr);
2712}
2713
2714
2715void Disassembler::AppendCodeRelativeAddressToOutput(const Instruction* instr,
2716                                                     const void* addr) {
2717  USE(instr);
2718  int64_t rel_addr = CodeRelativeAddress(addr);
2719  if (rel_addr >= 0) {
2720    AppendToOutput("(addr 0x%" PRIx64 ")", rel_addr);
2721  } else {
2722    AppendToOutput("(addr -0x%" PRIx64 ")", -rel_addr);
2723  }
2724}
2725
2726
2727void Disassembler::AppendCodeRelativeCodeAddressToOutput(
2728    const Instruction* instr, const void* addr) {
2729  AppendCodeRelativeAddressToOutput(instr, addr);
2730}
2731
2732
2733void Disassembler::AppendCodeRelativeDataAddressToOutput(
2734    const Instruction* instr, const void* addr) {
2735  AppendCodeRelativeAddressToOutput(instr, addr);
2736}
2737
2738
2739void Disassembler::MapCodeAddress(int64_t base_address,
2740                                  const Instruction* instr_address) {
2741  set_code_address_offset(
2742      base_address - reinterpret_cast<intptr_t>(instr_address));
2743}
2744int64_t Disassembler::CodeRelativeAddress(const void* addr) {
2745  return reinterpret_cast<intptr_t>(addr) + code_address_offset();
2746}
2747
2748
2749void Disassembler::Format(const Instruction* instr, const char* mnemonic,
2750                          const char* format) {
2751  VIXL_ASSERT(mnemonic != NULL);
2752  ResetOutput();
2753  Substitute(instr, mnemonic);
2754  if (format != NULL) {
2755    VIXL_ASSERT(buffer_pos_ < buffer_size_);
2756    buffer_[buffer_pos_++] = ' ';
2757    Substitute(instr, format);
2758  }
2759  VIXL_ASSERT(buffer_pos_ < buffer_size_);
2760  buffer_[buffer_pos_] = 0;
2761  ProcessOutput(instr);
2762}
2763
2764
2765void Disassembler::Substitute(const Instruction* instr, const char* string) {
2766  char chr = *string++;
2767  while (chr != '\0') {
2768    if (chr == '\'') {
2769      string += SubstituteField(instr, string);
2770    } else {
2771      VIXL_ASSERT(buffer_pos_ < buffer_size_);
2772      buffer_[buffer_pos_++] = chr;
2773    }
2774    chr = *string++;
2775  }
2776}
2777
2778
2779int Disassembler::SubstituteField(const Instruction* instr,
2780                                  const char* format) {
2781  switch (format[0]) {
2782    // NB. The remaining substitution prefix characters are: GJKUZ.
2783    case 'R':  // Register. X or W, selected by sf bit.
2784    case 'F':  // FP register. S or D, selected by type field.
2785    case 'V':  // Vector register, V, vector format.
2786    case 'W':
2787    case 'X':
2788    case 'B':
2789    case 'H':
2790    case 'S':
2791    case 'D':
2792    case 'Q': return SubstituteRegisterField(instr, format);
2793    case 'I': return SubstituteImmediateField(instr, format);
2794    case 'L': return SubstituteLiteralField(instr, format);
2795    case 'N': return SubstituteShiftField(instr, format);
2796    case 'P': return SubstitutePrefetchField(instr, format);
2797    case 'C': return SubstituteConditionField(instr, format);
2798    case 'E': return SubstituteExtendField(instr, format);
2799    case 'A': return SubstitutePCRelAddressField(instr, format);
2800    case 'T': return SubstituteBranchTargetField(instr, format);
2801    case 'O': return SubstituteLSRegOffsetField(instr, format);
2802    case 'M': return SubstituteBarrierField(instr, format);
2803    case 'K': return SubstituteCrField(instr, format);
2804    case 'G': return SubstituteSysOpField(instr, format);
2805    default: {
2806      VIXL_UNREACHABLE();
2807      return 1;
2808    }
2809  }
2810}
2811
2812
2813int Disassembler::SubstituteRegisterField(const Instruction* instr,
2814                                          const char* format) {
2815  char reg_prefix = format[0];
2816  unsigned reg_num = 0;
2817  unsigned field_len = 2;
2818
2819  switch (format[1]) {
2820    case 'd':
2821      reg_num = instr->Rd();
2822      if (format[2] == 'q') {
2823        reg_prefix = instr->NEONQ() ? 'X' : 'W';
2824        field_len = 3;
2825      }
2826      break;
2827    case 'n': reg_num = instr->Rn(); break;
2828    case 'm':
2829      reg_num = instr->Rm();
2830      switch (format[2]) {
2831          // Handle registers tagged with b (bytes), z (instruction), or
2832          // r (registers), used for address updates in
2833          // NEON load/store instructions.
2834        case 'r':
2835        case 'b':
2836        case 'z': {
2837          field_len = 3;
2838          char* eimm;
2839          int imm = static_cast<int>(strtol(&format[3], &eimm, 10));
2840          field_len += eimm - &format[3];
2841          if (reg_num == 31) {
2842            switch (format[2]) {
2843              case 'z':
2844                imm *= (1 << instr->NEONLSSize());
2845                break;
2846              case 'r':
2847                imm *= (instr->NEONQ() == 0) ? kDRegSizeInBytes
2848                                             : kQRegSizeInBytes;
2849                break;
2850              case 'b':
2851                break;
2852            }
2853            AppendToOutput("#%d", imm);
2854            return field_len;
2855          }
2856          break;
2857        }
2858      }
2859      break;
2860    case 'e':
2861      // This is register Rm, but using a 4-bit specifier. Used in NEON
2862      // by-element instructions.
2863      reg_num = (instr->Rm() & 0xf);
2864      break;
2865    case 'a': reg_num = instr->Ra(); break;
2866    case 's': reg_num = instr->Rs(); break;
2867    case 't':
2868      reg_num = instr->Rt();
2869      if (format[0] == 'V') {
2870        if ((format[2] >= '2') && (format[2] <= '4')) {
2871          // Handle consecutive vector register specifiers Vt2, Vt3 and Vt4.
2872          reg_num = (reg_num + format[2] - '1') % 32;
2873          field_len = 3;
2874        }
2875      } else {
2876        if (format[2] == '2') {
2877        // Handle register specifier Rt2.
2878          reg_num = instr->Rt2();
2879          field_len = 3;
2880        }
2881      }
2882      break;
2883    default: VIXL_UNREACHABLE();
2884  }
2885
2886  // Increase field length for registers tagged as stack.
2887  if (format[2] == 's') {
2888    field_len = 3;
2889  }
2890
2891  CPURegister::RegisterType reg_type = CPURegister::kRegister;
2892  unsigned reg_size = kXRegSize;
2893
2894  if (reg_prefix == 'R') {
2895    reg_prefix = instr->SixtyFourBits() ? 'X' : 'W';
2896  } else if (reg_prefix == 'F') {
2897    reg_prefix = ((instr->FPType() & 1) == 0) ? 'S' : 'D';
2898  }
2899
2900  switch (reg_prefix) {
2901    case 'W':
2902      reg_type = CPURegister::kRegister; reg_size = kWRegSize; break;
2903    case 'X':
2904      reg_type = CPURegister::kRegister; reg_size = kXRegSize; break;
2905    case 'B':
2906      reg_type = CPURegister::kVRegister; reg_size = kBRegSize; break;
2907    case 'H':
2908      reg_type = CPURegister::kVRegister; reg_size = kHRegSize; break;
2909    case 'S':
2910      reg_type = CPURegister::kVRegister; reg_size = kSRegSize; break;
2911    case 'D':
2912      reg_type = CPURegister::kVRegister; reg_size = kDRegSize; break;
2913    case 'Q':
2914      reg_type = CPURegister::kVRegister; reg_size = kQRegSize; break;
2915    case 'V':
2916      AppendToOutput("v%d", reg_num);
2917      return field_len;
2918    default:
2919      VIXL_UNREACHABLE();
2920  }
2921
2922  if ((reg_type == CPURegister::kRegister) &&
2923      (reg_num == kZeroRegCode) && (format[2] == 's')) {
2924    reg_num = kSPRegInternalCode;
2925  }
2926
2927  AppendRegisterNameToOutput(instr, CPURegister(reg_num, reg_size, reg_type));
2928
2929  return field_len;
2930}
2931
2932
2933int Disassembler::SubstituteImmediateField(const Instruction* instr,
2934                                           const char* format) {
2935  VIXL_ASSERT(format[0] == 'I');
2936
2937  switch (format[1]) {
2938    case 'M': {  // IMoveImm, IMoveNeg or IMoveLSL.
2939      if (format[5] == 'L') {
2940        AppendToOutput("#0x%" PRIx32, instr->ImmMoveWide());
2941        if (instr->ShiftMoveWide() > 0) {
2942          AppendToOutput(", lsl #%" PRId32, 16 * instr->ShiftMoveWide());
2943        }
2944      } else {
2945        VIXL_ASSERT((format[5] == 'I') || (format[5] == 'N'));
2946        uint64_t imm = static_cast<uint64_t>(instr->ImmMoveWide()) <<
2947            (16 * instr->ShiftMoveWide());
2948        if (format[5] == 'N')
2949          imm = ~imm;
2950        if (!instr->SixtyFourBits())
2951          imm &= UINT64_C(0xffffffff);
2952        AppendToOutput("#0x%" PRIx64, imm);
2953      }
2954      return 8;
2955    }
2956    case 'L': {
2957      switch (format[2]) {
2958        case 'L': {  // ILLiteral - Immediate Load Literal.
2959          AppendToOutput("pc%+" PRId32,
2960                         instr->ImmLLiteral() << kLiteralEntrySizeLog2);
2961          return 9;
2962        }
2963        case 'S': {  // ILS - Immediate Load/Store.
2964          if (instr->ImmLS() != 0) {
2965            AppendToOutput(", #%" PRId32, instr->ImmLS());
2966          }
2967          return 3;
2968        }
2969        case 'P': {  // ILPx - Immediate Load/Store Pair, x = access size.
2970          if (instr->ImmLSPair() != 0) {
2971            // format[3] is the scale value. Convert to a number.
2972            int scale = 1 << (format[3] - '0');
2973            AppendToOutput(", #%" PRId32, instr->ImmLSPair() * scale);
2974          }
2975          return 4;
2976        }
2977        case 'U': {  // ILU - Immediate Load/Store Unsigned.
2978          if (instr->ImmLSUnsigned() != 0) {
2979            int shift = instr->SizeLS();
2980            AppendToOutput(", #%" PRId32, instr->ImmLSUnsigned() << shift);
2981          }
2982          return 3;
2983        }
2984      }
2985    }
2986    case 'C': {  // ICondB - Immediate Conditional Branch.
2987      int64_t offset = instr->ImmCondBranch() << 2;
2988      AppendPCRelativeOffsetToOutput(instr, offset);
2989      return 6;
2990    }
2991    case 'A': {  // IAddSub.
2992      VIXL_ASSERT(instr->ShiftAddSub() <= 1);
2993      int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub());
2994      AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm);
2995      return 7;
2996    }
2997    case 'F': {  // IFPSingle, IFPDouble or IFPFBits.
2998      if (format[3] == 'F') {  // IFPFbits.
2999        AppendToOutput("#%" PRId32, 64 - instr->FPScale());
3000        return 8;
3001      } else {
3002        AppendToOutput("#0x%" PRIx32 " (%.4f)", instr->ImmFP(),
3003                       format[3] == 'S' ? instr->ImmFP32() : instr->ImmFP64());
3004        return 9;
3005      }
3006    }
3007    case 'T': {  // ITri - Immediate Triangular Encoded.
3008      AppendToOutput("#0x%" PRIx64, instr->ImmLogical());
3009      return 4;
3010    }
3011    case 'N': {  // INzcv.
3012      int nzcv = (instr->Nzcv() << Flags_offset);
3013      AppendToOutput("#%c%c%c%c", ((nzcv & NFlag) == 0) ? 'n' : 'N',
3014                                  ((nzcv & ZFlag) == 0) ? 'z' : 'Z',
3015                                  ((nzcv & CFlag) == 0) ? 'c' : 'C',
3016                                  ((nzcv & VFlag) == 0) ? 'v' : 'V');
3017      return 5;
3018    }
3019    case 'P': {  // IP - Conditional compare.
3020      AppendToOutput("#%" PRId32, instr->ImmCondCmp());
3021      return 2;
3022    }
3023    case 'B': {  // Bitfields.
3024      return SubstituteBitfieldImmediateField(instr, format);
3025    }
3026    case 'E': {  // IExtract.
3027      AppendToOutput("#%" PRId32, instr->ImmS());
3028      return 8;
3029    }
3030    case 'S': {  // IS - Test and branch bit.
3031      AppendToOutput("#%" PRId32, (instr->ImmTestBranchBit5() << 5) |
3032                                  instr->ImmTestBranchBit40());
3033      return 2;
3034    }
3035    case 's': {  // Is - Shift (immediate).
3036      switch (format[2]) {
3037        case '1': {  // Is1 - SSHR.
3038          int shift = 16 << HighestSetBitPosition(instr->ImmNEONImmh());
3039          shift -= instr->ImmNEONImmhImmb();
3040          AppendToOutput("#%d", shift);
3041          return 3;
3042        }
3043        case '2': {  // Is2 - SLI.
3044          int shift = instr->ImmNEONImmhImmb();
3045          shift -= 8 << HighestSetBitPosition(instr->ImmNEONImmh());
3046          AppendToOutput("#%d", shift);
3047          return 3;
3048        }
3049        default: {
3050          VIXL_UNIMPLEMENTED();
3051          return 0;
3052        }
3053      }
3054    }
3055    case 'D': {  // IDebug - HLT and BRK instructions.
3056      AppendToOutput("#0x%" PRIx32, instr->ImmException());
3057      return 6;
3058    }
3059    case 'V': {  // Immediate Vector.
3060      switch (format[2]) {
3061        case 'E': {  // IVExtract.
3062          AppendToOutput("#%" PRId32, instr->ImmNEONExt());
3063          return 9;
3064        }
3065        case 'B': {  // IVByElemIndex.
3066          int vm_index = (instr->NEONH() << 1) | instr->NEONL();
3067          if (instr->NEONSize() == 1) {
3068            vm_index = (vm_index << 1) | instr->NEONM();
3069          }
3070          AppendToOutput("%d", vm_index);
3071          return strlen("IVByElemIndex");
3072        }
3073        case 'I': {  // INS element.
3074          if (strncmp(format, "IVInsIndex", strlen("IVInsIndex")) == 0) {
3075            int rd_index, rn_index;
3076            int imm5 = instr->ImmNEON5();
3077            int imm4 = instr->ImmNEON4();
3078            int tz = CountTrailingZeros(imm5, 32);
3079            rd_index = imm5 >> (tz + 1);
3080            rn_index = imm4 >> tz;
3081            if (strncmp(format, "IVInsIndex1", strlen("IVInsIndex1")) == 0) {
3082              AppendToOutput("%d", rd_index);
3083              return strlen("IVInsIndex1");
3084            } else if (strncmp(format, "IVInsIndex2",
3085                       strlen("IVInsIndex2")) == 0) {
3086              AppendToOutput("%d", rn_index);
3087              return strlen("IVInsIndex2");
3088            } else {
3089              VIXL_UNIMPLEMENTED();
3090              return 0;
3091            }
3092          }
3093          VIXL_FALLTHROUGH();
3094        }
3095        case 'L': {  // IVLSLane[0123] - suffix indicates access size shift.
3096          AppendToOutput("%d", instr->NEONLSIndex(format[8] - '0'));
3097          return 9;
3098        }
3099        case 'M': {  // Modified Immediate cases.
3100          if (strncmp(format,
3101                      "IVMIImmFPSingle",
3102                      strlen("IVMIImmFPSingle")) == 0) {
3103            AppendToOutput("#0x%" PRIx32 " (%.4f)", instr->ImmNEONabcdefgh(),
3104                           instr->ImmNEONFP32());
3105            return strlen("IVMIImmFPSingle");
3106          } else if (strncmp(format,
3107                             "IVMIImmFPDouble",
3108                             strlen("IVMIImmFPDouble")) == 0) {
3109            AppendToOutput("#0x%" PRIx32 " (%.4f)", instr->ImmNEONabcdefgh(),
3110                           instr->ImmNEONFP64());
3111            return strlen("IVMIImmFPDouble");
3112          } else if (strncmp(format, "IVMIImm8", strlen("IVMIImm8")) == 0) {
3113            uint64_t imm8 = instr->ImmNEONabcdefgh();
3114            AppendToOutput("#0x%" PRIx64, imm8);
3115            return strlen("IVMIImm8");
3116          } else if (strncmp(format, "IVMIImm", strlen("IVMIImm")) == 0) {
3117            uint64_t imm8 = instr->ImmNEONabcdefgh();
3118            uint64_t imm = 0;
3119            for (int i = 0; i < 8; ++i) {
3120              if (imm8 & (1 << i)) {
3121                imm |= (UINT64_C(0xff) << (8 * i));
3122              }
3123            }
3124            AppendToOutput("#0x%" PRIx64, imm);
3125            return strlen("IVMIImm");
3126          } else if (strncmp(format, "IVMIShiftAmt1",
3127                             strlen("IVMIShiftAmt1")) == 0) {
3128            int cmode = instr->NEONCmode();
3129            int shift_amount = 8 * ((cmode >> 1) & 3);
3130            AppendToOutput("#%d", shift_amount);
3131            return strlen("IVMIShiftAmt1");
3132          } else if (strncmp(format, "IVMIShiftAmt2",
3133                             strlen("IVMIShiftAmt2")) == 0) {
3134            int cmode = instr->NEONCmode();
3135            int shift_amount = 8 << (cmode & 1);
3136            AppendToOutput("#%d", shift_amount);
3137            return strlen("IVMIShiftAmt2");
3138          } else {
3139            VIXL_UNIMPLEMENTED();
3140            return 0;
3141          }
3142        }
3143        default: {
3144          VIXL_UNIMPLEMENTED();
3145          return 0;
3146        }
3147      }
3148    }
3149    case 'X': {  // IX - CLREX instruction.
3150      AppendToOutput("#0x%" PRIx32, instr->CRm());
3151      return 2;
3152    }
3153    default: {
3154      VIXL_UNIMPLEMENTED();
3155      return 0;
3156    }
3157  }
3158}
3159
3160
3161int Disassembler::SubstituteBitfieldImmediateField(const Instruction* instr,
3162                                                   const char* format) {
3163  VIXL_ASSERT((format[0] == 'I') && (format[1] == 'B'));
3164  unsigned r = instr->ImmR();
3165  unsigned s = instr->ImmS();
3166
3167  switch (format[2]) {
3168    case 'r': {  // IBr.
3169      AppendToOutput("#%d", r);
3170      return 3;
3171    }
3172    case 's': {  // IBs+1 or IBs-r+1.
3173      if (format[3] == '+') {
3174        AppendToOutput("#%d", s + 1);
3175        return 5;
3176      } else {
3177        VIXL_ASSERT(format[3] == '-');
3178        AppendToOutput("#%d", s - r + 1);
3179        return 7;
3180      }
3181    }
3182    case 'Z': {  // IBZ-r.
3183      VIXL_ASSERT((format[3] == '-') && (format[4] == 'r'));
3184      unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSize : kWRegSize;
3185      AppendToOutput("#%d", reg_size - r);
3186      return 5;
3187    }
3188    default: {
3189      VIXL_UNREACHABLE();
3190      return 0;
3191    }
3192  }
3193}
3194
3195
3196int Disassembler::SubstituteLiteralField(const Instruction* instr,
3197                                         const char* format) {
3198  VIXL_ASSERT(strncmp(format, "LValue", 6) == 0);
3199  USE(format);
3200
3201  const void * address = instr->LiteralAddress<const void *>();
3202  switch (instr->Mask(LoadLiteralMask)) {
3203    case LDR_w_lit:
3204    case LDR_x_lit:
3205    case LDRSW_x_lit:
3206    case LDR_s_lit:
3207    case LDR_d_lit:
3208    case LDR_q_lit:
3209      AppendCodeRelativeDataAddressToOutput(instr, address);
3210      break;
3211    case PRFM_lit: {
3212      // Use the prefetch hint to decide how to print the address.
3213      switch (instr->PrefetchHint()) {
3214        case 0x0:     // PLD: prefetch for load.
3215        case 0x2:     // PST: prepare for store.
3216          AppendCodeRelativeDataAddressToOutput(instr, address);
3217          break;
3218        case 0x1:     // PLI: preload instructions.
3219          AppendCodeRelativeCodeAddressToOutput(instr, address);
3220          break;
3221        case 0x3:     // Unallocated hint.
3222          AppendCodeRelativeAddressToOutput(instr, address);
3223          break;
3224      }
3225      break;
3226    }
3227    default:
3228      VIXL_UNREACHABLE();
3229  }
3230
3231  return 6;
3232}
3233
3234
3235int Disassembler::SubstituteShiftField(const Instruction* instr,
3236                                       const char* format) {
3237  VIXL_ASSERT(format[0] == 'N');
3238  VIXL_ASSERT(instr->ShiftDP() <= 0x3);
3239
3240  switch (format[1]) {
3241    case 'D': {  // HDP.
3242      VIXL_ASSERT(instr->ShiftDP() != ROR);
3243      VIXL_FALLTHROUGH();
3244    }
3245    case 'L': {  // HLo.
3246      if (instr->ImmDPShift() != 0) {
3247        const char* shift_type[] = {"lsl", "lsr", "asr", "ror"};
3248        AppendToOutput(", %s #%" PRId32, shift_type[instr->ShiftDP()],
3249                       instr->ImmDPShift());
3250      }
3251      return 3;
3252    }
3253    default:
3254      VIXL_UNIMPLEMENTED();
3255      return 0;
3256  }
3257}
3258
3259
3260int Disassembler::SubstituteConditionField(const Instruction* instr,
3261                                           const char* format) {
3262  VIXL_ASSERT(format[0] == 'C');
3263  const char* condition_code[] = { "eq", "ne", "hs", "lo",
3264                                   "mi", "pl", "vs", "vc",
3265                                   "hi", "ls", "ge", "lt",
3266                                   "gt", "le", "al", "nv" };
3267  int cond;
3268  switch (format[1]) {
3269    case 'B': cond = instr->ConditionBranch(); break;
3270    case 'I': {
3271      cond = InvertCondition(static_cast<Condition>(instr->Condition()));
3272      break;
3273    }
3274    default: cond = instr->Condition();
3275  }
3276  AppendToOutput("%s", condition_code[cond]);
3277  return 4;
3278}
3279
3280
3281int Disassembler::SubstitutePCRelAddressField(const Instruction* instr,
3282                                              const char* format) {
3283  VIXL_ASSERT((strcmp(format, "AddrPCRelByte") == 0) ||   // Used by `adr`.
3284              (strcmp(format, "AddrPCRelPage") == 0));    // Used by `adrp`.
3285
3286  int64_t offset = instr->ImmPCRel();
3287
3288  // Compute the target address based on the effective address (after applying
3289  // code_address_offset). This is required for correct behaviour of adrp.
3290  const Instruction* base = instr + code_address_offset();
3291  if (format[9] == 'P') {
3292    offset *= kPageSize;
3293    base = AlignDown(base, kPageSize);
3294  }
3295  // Strip code_address_offset before printing, so we can use the
3296  // semantically-correct AppendCodeRelativeAddressToOutput.
3297  const void* target =
3298      reinterpret_cast<const void*>(base + offset - code_address_offset());
3299
3300  AppendPCRelativeOffsetToOutput(instr, offset);
3301  AppendToOutput(" ");
3302  AppendCodeRelativeAddressToOutput(instr, target);
3303  return 13;
3304}
3305
3306
3307int Disassembler::SubstituteBranchTargetField(const Instruction* instr,
3308                                              const char* format) {
3309  VIXL_ASSERT(strncmp(format, "TImm", 4) == 0);
3310
3311  int64_t offset = 0;
3312  switch (format[5]) {
3313    // BImmUncn - unconditional branch immediate.
3314    case 'n': offset = instr->ImmUncondBranch(); break;
3315    // BImmCond - conditional branch immediate.
3316    case 'o': offset = instr->ImmCondBranch(); break;
3317    // BImmCmpa - compare and branch immediate.
3318    case 'm': offset = instr->ImmCmpBranch(); break;
3319    // BImmTest - test and branch immediate.
3320    case 'e': offset = instr->ImmTestBranch(); break;
3321    default: VIXL_UNIMPLEMENTED();
3322  }
3323  offset <<= kInstructionSizeLog2;
3324  const void* target_address = reinterpret_cast<const void*>(instr + offset);
3325  VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
3326
3327  AppendPCRelativeOffsetToOutput(instr, offset);
3328  AppendToOutput(" ");
3329  AppendCodeRelativeCodeAddressToOutput(instr, target_address);
3330
3331  return 8;
3332}
3333
3334
3335int Disassembler::SubstituteExtendField(const Instruction* instr,
3336                                        const char* format) {
3337  VIXL_ASSERT(strncmp(format, "Ext", 3) == 0);
3338  VIXL_ASSERT(instr->ExtendMode() <= 7);
3339  USE(format);
3340
3341  const char* extend_mode[] = { "uxtb", "uxth", "uxtw", "uxtx",
3342                                "sxtb", "sxth", "sxtw", "sxtx" };
3343
3344  // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit
3345  // registers becomes lsl.
3346  if (((instr->Rd() == kZeroRegCode) || (instr->Rn() == kZeroRegCode)) &&
3347      (((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
3348       (instr->ExtendMode() == UXTX))) {
3349    if (instr->ImmExtendShift() > 0) {
3350      AppendToOutput(", lsl #%" PRId32, instr->ImmExtendShift());
3351    }
3352  } else {
3353    AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
3354    if (instr->ImmExtendShift() > 0) {
3355      AppendToOutput(" #%" PRId32, instr->ImmExtendShift());
3356    }
3357  }
3358  return 3;
3359}
3360
3361
3362int Disassembler::SubstituteLSRegOffsetField(const Instruction* instr,
3363                                             const char* format) {
3364  VIXL_ASSERT(strncmp(format, "Offsetreg", 9) == 0);
3365  const char* extend_mode[] = { "undefined", "undefined", "uxtw", "lsl",
3366                                "undefined", "undefined", "sxtw", "sxtx" };
3367  USE(format);
3368
3369  unsigned shift = instr->ImmShiftLS();
3370  Extend ext = static_cast<Extend>(instr->ExtendMode());
3371  char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x';
3372
3373  unsigned rm = instr->Rm();
3374  if (rm == kZeroRegCode) {
3375    AppendToOutput("%czr", reg_type);
3376  } else {
3377    AppendToOutput("%c%d", reg_type, rm);
3378  }
3379
3380  // Extend mode UXTX is an alias for shift mode LSL here.
3381  if (!((ext == UXTX) && (shift == 0))) {
3382    AppendToOutput(", %s", extend_mode[ext]);
3383    if (shift != 0) {
3384      AppendToOutput(" #%d", instr->SizeLS());
3385    }
3386  }
3387  return 9;
3388}
3389
3390
3391int Disassembler::SubstitutePrefetchField(const Instruction* instr,
3392                                          const char* format) {
3393  VIXL_ASSERT(format[0] == 'P');
3394  USE(format);
3395
3396  static const char* hints[] = {"ld", "li", "st"};
3397  static const char* stream_options[] = {"keep", "strm"};
3398
3399  unsigned hint = instr->PrefetchHint();
3400  unsigned target = instr->PrefetchTarget() + 1;
3401  unsigned stream = instr->PrefetchStream();
3402
3403  if ((hint >= (sizeof(hints) / sizeof(hints[0]))) || (target > 3)) {
3404    // Unallocated prefetch operations.
3405    int prefetch_mode = instr->ImmPrefetchOperation();
3406    AppendToOutput("#0b%c%c%c%c%c",
3407                   (prefetch_mode & (1 << 4)) ? '1' : '0',
3408                   (prefetch_mode & (1 << 3)) ? '1' : '0',
3409                   (prefetch_mode & (1 << 2)) ? '1' : '0',
3410                   (prefetch_mode & (1 << 1)) ? '1' : '0',
3411                   (prefetch_mode & (1 << 0)) ? '1' : '0');
3412  } else {
3413    VIXL_ASSERT(stream < (sizeof(stream_options) / sizeof(stream_options[0])));
3414    AppendToOutput("p%sl%d%s", hints[hint], target, stream_options[stream]);
3415  }
3416  return 6;
3417}
3418
3419int Disassembler::SubstituteBarrierField(const Instruction* instr,
3420                                         const char* format) {
3421  VIXL_ASSERT(format[0] == 'M');
3422  USE(format);
3423
3424  static const char* options[4][4] = {
3425    { "sy (0b0000)", "oshld", "oshst", "osh" },
3426    { "sy (0b0100)", "nshld", "nshst", "nsh" },
3427    { "sy (0b1000)", "ishld", "ishst", "ish" },
3428    { "sy (0b1100)", "ld", "st", "sy" }
3429  };
3430  int domain = instr->ImmBarrierDomain();
3431  int type = instr->ImmBarrierType();
3432
3433  AppendToOutput("%s", options[domain][type]);
3434  return 1;
3435}
3436
3437int Disassembler::SubstituteSysOpField(const Instruction* instr,
3438                                       const char* format) {
3439  VIXL_ASSERT(format[0] == 'G');
3440  int op = -1;
3441  switch (format[1]) {
3442    case '1': op = instr->SysOp1(); break;
3443    case '2': op = instr->SysOp2(); break;
3444    default:
3445      VIXL_UNREACHABLE();
3446  }
3447  AppendToOutput("#%d", op);
3448  return 2;
3449}
3450
3451int Disassembler::SubstituteCrField(const Instruction* instr,
3452                                    const char* format) {
3453  VIXL_ASSERT(format[0] == 'K');
3454  int cr = -1;
3455  switch (format[1]) {
3456    case 'n': cr = instr->CRn(); break;
3457    case 'm': cr = instr->CRm(); break;
3458    default:
3459      VIXL_UNREACHABLE();
3460  }
3461  AppendToOutput("C%d", cr);
3462  return 2;
3463}
3464
3465void Disassembler::ResetOutput() {
3466  buffer_pos_ = 0;
3467  buffer_[buffer_pos_] = 0;
3468}
3469
3470
3471void Disassembler::AppendToOutput(const char* format, ...) {
3472  va_list args;
3473  va_start(args, format);
3474  buffer_pos_ += vsnprintf(&buffer_[buffer_pos_], buffer_size_ - buffer_pos_,
3475          format, args);
3476  va_end(args);
3477}
3478
3479
3480void PrintDisassembler::ProcessOutput(const Instruction* instr) {
3481  fprintf(stream_, "0x%016" PRIx64 "  %08" PRIx32 "\t\t%s\n",
3482          reinterpret_cast<uint64_t>(instr),
3483          instr->InstructionBits(),
3484          GetOutput());
3485}
3486
3487}  // namespace vixl
3488