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