tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Disasm-vixl.cpp (129636B)


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