duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

disasm-aarch64.cc (256772B)


      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 "disasm-aarch64.h"
     28 
     29 #include <bitset>
     30 #include <cstdlib>
     31 #include <sstream>
     32 
     33 namespace vixl {
     34 namespace aarch64 {
     35 
     36 const Disassembler::FormToVisitorFnMap *Disassembler::GetFormToVisitorFnMap() {
     37   static const FormToVisitorFnMap form_to_visitor = {
     38       DEFAULT_FORM_TO_VISITOR_MAP(Disassembler),
     39       {"autia1716_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     40       {"autiasp_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     41       {"autiaz_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     42       {"autib1716_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     43       {"autibsp_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     44       {"autibz_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     45       {"axflag_m_pstate"_h, &Disassembler::DisassembleNoArgs},
     46       {"cfinv_m_pstate"_h, &Disassembler::DisassembleNoArgs},
     47       {"csdb_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     48       {"dgh_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     49       {"ssbb_only_barriers"_h, &Disassembler::DisassembleNoArgs},
     50       {"esb_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     51       {"isb_bi_barriers"_h, &Disassembler::DisassembleNoArgs},
     52       {"nop_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     53       {"pacia1716_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     54       {"paciasp_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     55       {"paciaz_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     56       {"pacib1716_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     57       {"pacibsp_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     58       {"pacibz_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     59       {"sev_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     60       {"sevl_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     61       {"wfe_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     62       {"wfi_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     63       {"xaflag_m_pstate"_h, &Disassembler::DisassembleNoArgs},
     64       {"xpaclri_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     65       {"yield_hi_hints"_h, &Disassembler::DisassembleNoArgs},
     66       {"abs_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc},
     67       {"cls_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc},
     68       {"clz_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc},
     69       {"cnt_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc},
     70       {"neg_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc},
     71       {"rev16_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc},
     72       {"rev32_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc},
     73       {"rev64_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc},
     74       {"sqabs_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc},
     75       {"sqneg_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc},
     76       {"suqadd_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc},
     77       {"urecpe_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc},
     78       {"ursqrte_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc},
     79       {"usqadd_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc},
     80       {"not_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegLogical},
     81       {"rbit_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegLogical},
     82       {"xtn_asimdmisc_n"_h, &Disassembler::DisassembleNEON2RegExtract},
     83       {"sqxtn_asimdmisc_n"_h, &Disassembler::DisassembleNEON2RegExtract},
     84       {"uqxtn_asimdmisc_n"_h, &Disassembler::DisassembleNEON2RegExtract},
     85       {"sqxtun_asimdmisc_n"_h, &Disassembler::DisassembleNEON2RegExtract},
     86       {"shll_asimdmisc_s"_h, &Disassembler::DisassembleNEON2RegExtract},
     87       {"sadalp_asimdmisc_p"_h, &Disassembler::DisassembleNEON2RegAddlp},
     88       {"saddlp_asimdmisc_p"_h, &Disassembler::DisassembleNEON2RegAddlp},
     89       {"uadalp_asimdmisc_p"_h, &Disassembler::DisassembleNEON2RegAddlp},
     90       {"uaddlp_asimdmisc_p"_h, &Disassembler::DisassembleNEON2RegAddlp},
     91       {"cmeq_asimdmisc_z"_h, &Disassembler::DisassembleNEON2RegCompare},
     92       {"cmge_asimdmisc_z"_h, &Disassembler::DisassembleNEON2RegCompare},
     93       {"cmgt_asimdmisc_z"_h, &Disassembler::DisassembleNEON2RegCompare},
     94       {"cmle_asimdmisc_z"_h, &Disassembler::DisassembleNEON2RegCompare},
     95       {"cmlt_asimdmisc_z"_h, &Disassembler::DisassembleNEON2RegCompare},
     96       {"fcmeq_asimdmisc_fz"_h, &Disassembler::DisassembleNEON2RegFPCompare},
     97       {"fcmge_asimdmisc_fz"_h, &Disassembler::DisassembleNEON2RegFPCompare},
     98       {"fcmgt_asimdmisc_fz"_h, &Disassembler::DisassembleNEON2RegFPCompare},
     99       {"fcmle_asimdmisc_fz"_h, &Disassembler::DisassembleNEON2RegFPCompare},
    100       {"fcmlt_asimdmisc_fz"_h, &Disassembler::DisassembleNEON2RegFPCompare},
    101       {"fcvtl_asimdmisc_l"_h, &Disassembler::DisassembleNEON2RegFPConvert},
    102       {"fcvtn_asimdmisc_n"_h, &Disassembler::DisassembleNEON2RegFPConvert},
    103       {"fcvtxn_asimdmisc_n"_h, &Disassembler::DisassembleNEON2RegFPConvert},
    104       {"fabs_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    105       {"fcvtas_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    106       {"fcvtau_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    107       {"fcvtms_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    108       {"fcvtmu_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    109       {"fcvtns_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    110       {"fcvtnu_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    111       {"fcvtps_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    112       {"fcvtpu_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    113       {"fcvtzs_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    114       {"fcvtzu_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    115       {"fneg_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    116       {"frecpe_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    117       {"frint32x_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    118       {"frint32z_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    119       {"frint64x_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    120       {"frint64z_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    121       {"frinta_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    122       {"frinti_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    123       {"frintm_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    124       {"frintn_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    125       {"frintp_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    126       {"frintx_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    127       {"frintz_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    128       {"frsqrte_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    129       {"fsqrt_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    130       {"scvtf_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    131       {"ucvtf_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP},
    132       {"smlal_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong},
    133       {"smlsl_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong},
    134       {"smull_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong},
    135       {"umlal_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong},
    136       {"umlsl_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong},
    137       {"umull_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong},
    138       {"sqdmull_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong},
    139       {"sqdmlal_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong},
    140       {"sqdmlsl_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong},
    141       {"sdot_asimdelem_d"_h, &Disassembler::DisassembleNEONDotProdByElement},
    142       {"udot_asimdelem_d"_h, &Disassembler::DisassembleNEONDotProdByElement},
    143       {"usdot_asimdelem_d"_h, &Disassembler::DisassembleNEONDotProdByElement},
    144       {"sudot_asimdelem_d"_h, &Disassembler::DisassembleNEONDotProdByElement},
    145       {"fmlal2_asimdelem_lh"_h,
    146        &Disassembler::DisassembleNEONFPMulByElementLong},
    147       {"fmlal_asimdelem_lh"_h,
    148        &Disassembler::DisassembleNEONFPMulByElementLong},
    149       {"fmlsl2_asimdelem_lh"_h,
    150        &Disassembler::DisassembleNEONFPMulByElementLong},
    151       {"fmlsl_asimdelem_lh"_h,
    152        &Disassembler::DisassembleNEONFPMulByElementLong},
    153       {"fcmla_asimdelem_c_h"_h,
    154        &Disassembler::DisassembleNEONComplexMulByElement},
    155       {"fcmla_asimdelem_c_s"_h,
    156        &Disassembler::DisassembleNEONComplexMulByElement},
    157       {"fmla_asimdelem_rh_h"_h,
    158        &Disassembler::DisassembleNEONHalfFPMulByElement},
    159       {"fmls_asimdelem_rh_h"_h,
    160        &Disassembler::DisassembleNEONHalfFPMulByElement},
    161       {"fmulx_asimdelem_rh_h"_h,
    162        &Disassembler::DisassembleNEONHalfFPMulByElement},
    163       {"fmul_asimdelem_rh_h"_h,
    164        &Disassembler::DisassembleNEONHalfFPMulByElement},
    165       {"fmla_asimdelem_r_sd"_h, &Disassembler::DisassembleNEONFPMulByElement},
    166       {"fmls_asimdelem_r_sd"_h, &Disassembler::DisassembleNEONFPMulByElement},
    167       {"fmulx_asimdelem_r_sd"_h, &Disassembler::DisassembleNEONFPMulByElement},
    168       {"fmul_asimdelem_r_sd"_h, &Disassembler::DisassembleNEONFPMulByElement},
    169       {"mla_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    170       {"mls_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    171       {"mul_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    172       {"saba_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    173       {"sabd_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    174       {"shadd_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    175       {"shsub_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    176       {"smaxp_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    177       {"smax_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    178       {"sminp_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    179       {"smin_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    180       {"srhadd_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    181       {"uaba_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    182       {"uabd_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    183       {"uhadd_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    184       {"uhsub_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    185       {"umaxp_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    186       {"umax_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    187       {"uminp_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    188       {"umin_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    189       {"urhadd_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD},
    190       {"and_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical},
    191       {"bic_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical},
    192       {"bif_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical},
    193       {"bit_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical},
    194       {"bsl_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical},
    195       {"eor_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical},
    196       {"orr_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical},
    197       {"orn_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical},
    198       {"pmul_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical},
    199       {"fmlal2_asimdsame_f"_h, &Disassembler::DisassembleNEON3SameFHM},
    200       {"fmlal_asimdsame_f"_h, &Disassembler::DisassembleNEON3SameFHM},
    201       {"fmlsl2_asimdsame_f"_h, &Disassembler::DisassembleNEON3SameFHM},
    202       {"fmlsl_asimdsame_f"_h, &Disassembler::DisassembleNEON3SameFHM},
    203       {"sri_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm},
    204       {"srshr_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm},
    205       {"srsra_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm},
    206       {"sshr_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm},
    207       {"ssra_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm},
    208       {"urshr_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm},
    209       {"ursra_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm},
    210       {"ushr_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm},
    211       {"usra_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm},
    212       {"scvtf_asimdshf_c"_h, &Disassembler::DisassembleNEONShiftRightImm},
    213       {"ucvtf_asimdshf_c"_h, &Disassembler::DisassembleNEONShiftRightImm},
    214       {"fcvtzs_asimdshf_c"_h, &Disassembler::DisassembleNEONShiftRightImm},
    215       {"fcvtzu_asimdshf_c"_h, &Disassembler::DisassembleNEONShiftRightImm},
    216       {"ushll_asimdshf_l"_h, &Disassembler::DisassembleNEONShiftLeftLongImm},
    217       {"sshll_asimdshf_l"_h, &Disassembler::DisassembleNEONShiftLeftLongImm},
    218       {"shrn_asimdshf_n"_h, &Disassembler::DisassembleNEONShiftRightNarrowImm},
    219       {"rshrn_asimdshf_n"_h, &Disassembler::DisassembleNEONShiftRightNarrowImm},
    220       {"sqshrn_asimdshf_n"_h,
    221        &Disassembler::DisassembleNEONShiftRightNarrowImm},
    222       {"sqrshrn_asimdshf_n"_h,
    223        &Disassembler::DisassembleNEONShiftRightNarrowImm},
    224       {"sqshrun_asimdshf_n"_h,
    225        &Disassembler::DisassembleNEONShiftRightNarrowImm},
    226       {"sqrshrun_asimdshf_n"_h,
    227        &Disassembler::DisassembleNEONShiftRightNarrowImm},
    228       {"uqshrn_asimdshf_n"_h,
    229        &Disassembler::DisassembleNEONShiftRightNarrowImm},
    230       {"uqrshrn_asimdshf_n"_h,
    231        &Disassembler::DisassembleNEONShiftRightNarrowImm},
    232       {"sqdmlal_asisdelem_l"_h,
    233        &Disassembler::DisassembleNEONScalarSatMulLongIndex},
    234       {"sqdmlsl_asisdelem_l"_h,
    235        &Disassembler::DisassembleNEONScalarSatMulLongIndex},
    236       {"sqdmull_asisdelem_l"_h,
    237        &Disassembler::DisassembleNEONScalarSatMulLongIndex},
    238       {"fmla_asisdelem_rh_h"_h, &Disassembler::DisassembleNEONFPScalarMulIndex},
    239       {"fmla_asisdelem_r_sd"_h, &Disassembler::DisassembleNEONFPScalarMulIndex},
    240       {"fmls_asisdelem_rh_h"_h, &Disassembler::DisassembleNEONFPScalarMulIndex},
    241       {"fmls_asisdelem_r_sd"_h, &Disassembler::DisassembleNEONFPScalarMulIndex},
    242       {"fmulx_asisdelem_rh_h"_h,
    243        &Disassembler::DisassembleNEONFPScalarMulIndex},
    244       {"fmulx_asisdelem_r_sd"_h,
    245        &Disassembler::DisassembleNEONFPScalarMulIndex},
    246       {"fmul_asisdelem_rh_h"_h, &Disassembler::DisassembleNEONFPScalarMulIndex},
    247       {"fmul_asisdelem_r_sd"_h, &Disassembler::DisassembleNEONFPScalarMulIndex},
    248       {"fabd_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same},
    249       {"facge_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same},
    250       {"facgt_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same},
    251       {"fcmeq_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same},
    252       {"fcmge_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same},
    253       {"fcmgt_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same},
    254       {"fmulx_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same},
    255       {"frecps_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same},
    256       {"frsqrts_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same},
    257       {"sqrdmlah_asisdsame2_only"_h, &Disassembler::VisitNEONScalar3Same},
    258       {"sqrdmlsh_asisdsame2_only"_h, &Disassembler::VisitNEONScalar3Same},
    259       {"cmeq_asisdsame_only"_h, &Disassembler::DisassembleNEONScalar3SameOnlyD},
    260       {"cmge_asisdsame_only"_h, &Disassembler::DisassembleNEONScalar3SameOnlyD},
    261       {"cmgt_asisdsame_only"_h, &Disassembler::DisassembleNEONScalar3SameOnlyD},
    262       {"cmhi_asisdsame_only"_h, &Disassembler::DisassembleNEONScalar3SameOnlyD},
    263       {"cmhs_asisdsame_only"_h, &Disassembler::DisassembleNEONScalar3SameOnlyD},
    264       {"cmtst_asisdsame_only"_h,
    265        &Disassembler::DisassembleNEONScalar3SameOnlyD},
    266       {"add_asisdsame_only"_h, &Disassembler::DisassembleNEONScalar3SameOnlyD},
    267       {"sub_asisdsame_only"_h, &Disassembler::DisassembleNEONScalar3SameOnlyD},
    268       {"fmaxnmv_asimdall_only_h"_h,
    269        &Disassembler::DisassembleNEONFP16AcrossLanes},
    270       {"fmaxv_asimdall_only_h"_h,
    271        &Disassembler::DisassembleNEONFP16AcrossLanes},
    272       {"fminnmv_asimdall_only_h"_h,
    273        &Disassembler::DisassembleNEONFP16AcrossLanes},
    274       {"fminv_asimdall_only_h"_h,
    275        &Disassembler::DisassembleNEONFP16AcrossLanes},
    276       {"fmaxnmv_asimdall_only_sd"_h,
    277        &Disassembler::DisassembleNEONFPAcrossLanes},
    278       {"fminnmv_asimdall_only_sd"_h,
    279        &Disassembler::DisassembleNEONFPAcrossLanes},
    280       {"fmaxv_asimdall_only_sd"_h, &Disassembler::DisassembleNEONFPAcrossLanes},
    281       {"fminv_asimdall_only_sd"_h, &Disassembler::DisassembleNEONFPAcrossLanes},
    282       {"shl_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
    283       {"sli_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
    284       {"sri_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
    285       {"srshr_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
    286       {"srsra_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
    287       {"sshr_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
    288       {"ssra_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
    289       {"urshr_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
    290       {"ursra_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
    291       {"ushr_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
    292       {"usra_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
    293       {"sqrshrn_asisdshf_n"_h,
    294        &Disassembler::DisassembleNEONScalarShiftRightNarrowImm},
    295       {"sqrshrun_asisdshf_n"_h,
    296        &Disassembler::DisassembleNEONScalarShiftRightNarrowImm},
    297       {"sqshrn_asisdshf_n"_h,
    298        &Disassembler::DisassembleNEONScalarShiftRightNarrowImm},
    299       {"sqshrun_asisdshf_n"_h,
    300        &Disassembler::DisassembleNEONScalarShiftRightNarrowImm},
    301       {"uqrshrn_asisdshf_n"_h,
    302        &Disassembler::DisassembleNEONScalarShiftRightNarrowImm},
    303       {"uqshrn_asisdshf_n"_h,
    304        &Disassembler::DisassembleNEONScalarShiftRightNarrowImm},
    305       {"cmeq_asisdmisc_z"_h, &Disassembler::DisassembleNEONScalar2RegMiscOnlyD},
    306       {"cmge_asisdmisc_z"_h, &Disassembler::DisassembleNEONScalar2RegMiscOnlyD},
    307       {"cmgt_asisdmisc_z"_h, &Disassembler::DisassembleNEONScalar2RegMiscOnlyD},
    308       {"cmle_asisdmisc_z"_h, &Disassembler::DisassembleNEONScalar2RegMiscOnlyD},
    309       {"cmlt_asisdmisc_z"_h, &Disassembler::DisassembleNEONScalar2RegMiscOnlyD},
    310       {"abs_asisdmisc_r"_h, &Disassembler::DisassembleNEONScalar2RegMiscOnlyD},
    311       {"neg_asisdmisc_r"_h, &Disassembler::DisassembleNEONScalar2RegMiscOnlyD},
    312       {"fcmeq_asisdmisc_fz"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    313       {"fcmge_asisdmisc_fz"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    314       {"fcmgt_asisdmisc_fz"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    315       {"fcmle_asisdmisc_fz"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    316       {"fcmlt_asisdmisc_fz"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    317       {"fcvtas_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    318       {"fcvtau_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    319       {"fcvtms_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    320       {"fcvtmu_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    321       {"fcvtns_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    322       {"fcvtnu_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    323       {"fcvtps_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    324       {"fcvtpu_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    325       {"fcvtxn_asisdmisc_n"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    326       {"fcvtzs_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    327       {"fcvtzu_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    328       {"frecpe_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    329       {"frecpx_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    330       {"frsqrte_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    331       {"scvtf_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    332       {"ucvtf_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc},
    333       {"pmull_asimddiff_l"_h, &Disassembler::DisassembleNEONPolynomialMul},
    334       {"adclb_z_zzz"_h, &Disassembler::DisassembleSVEAddSubCarry},
    335       {"adclt_z_zzz"_h, &Disassembler::DisassembleSVEAddSubCarry},
    336       {"addhnb_z_zz"_h, &Disassembler::DisassembleSVEAddSubHigh},
    337       {"addhnt_z_zz"_h, &Disassembler::DisassembleSVEAddSubHigh},
    338       {"addp_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    339       {"aesd_z_zz"_h, &Disassembler::Disassemble_ZdnB_ZdnB_ZmB},
    340       {"aese_z_zz"_h, &Disassembler::Disassemble_ZdnB_ZdnB_ZmB},
    341       {"aesimc_z_z"_h, &Disassembler::Disassemble_ZdnB_ZdnB},
    342       {"aesmc_z_z"_h, &Disassembler::Disassemble_ZdnB_ZdnB},
    343       {"bcax_z_zzz"_h, &Disassembler::DisassembleSVEBitwiseTernary},
    344       {"bdep_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT},
    345       {"bext_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT},
    346       {"bgrp_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT},
    347       {"bsl1n_z_zzz"_h, &Disassembler::DisassembleSVEBitwiseTernary},
    348       {"bsl2n_z_zzz"_h, &Disassembler::DisassembleSVEBitwiseTernary},
    349       {"bsl_z_zzz"_h, &Disassembler::DisassembleSVEBitwiseTernary},
    350       {"cadd_z_zz"_h, &Disassembler::DisassembleSVEComplexIntAddition},
    351       {"cdot_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb_const},
    352       {"cdot_z_zzzi_d"_h, &Disassembler::Disassemble_ZdaD_ZnH_ZmH_imm_const},
    353       {"cdot_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnB_ZmB_imm_const},
    354       {"cmla_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnT_ZmT_const},
    355       {"cmla_z_zzzi_h"_h, &Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm_const},
    356       {"cmla_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm_const},
    357       {"eor3_z_zzz"_h, &Disassembler::DisassembleSVEBitwiseTernary},
    358       {"eorbt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT},
    359       {"eortb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT},
    360       {"ext_z_zi_con"_h, &Disassembler::Disassemble_ZdB_Zn1B_Zn2B_imm},
    361       {"faddp_z_p_zz"_h, &Disassembler::DisassembleSVEFPPair},
    362       {"fcvtlt_z_p_z_h2s"_h, &Disassembler::Disassemble_ZdS_PgM_ZnH},
    363       {"fcvtlt_z_p_z_s2d"_h, &Disassembler::Disassemble_ZdD_PgM_ZnS},
    364       {"fcvtnt_z_p_z_d2s"_h, &Disassembler::Disassemble_ZdS_PgM_ZnD},
    365       {"fcvtnt_z_p_z_s2h"_h, &Disassembler::Disassemble_ZdH_PgM_ZnS},
    366       {"fcvtx_z_p_z_d2s"_h, &Disassembler::Disassemble_ZdS_PgM_ZnD},
    367       {"fcvtxnt_z_p_z_d2s"_h, &Disassembler::Disassemble_ZdS_PgM_ZnD},
    368       {"flogb_z_p_z"_h, &Disassembler::DisassembleSVEFlogb},
    369       {"fmaxnmp_z_p_zz"_h, &Disassembler::DisassembleSVEFPPair},
    370       {"fmaxp_z_p_zz"_h, &Disassembler::DisassembleSVEFPPair},
    371       {"fminnmp_z_p_zz"_h, &Disassembler::DisassembleSVEFPPair},
    372       {"fminp_z_p_zz"_h, &Disassembler::DisassembleSVEFPPair},
    373       {"fmlalb_z_zzz"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH},
    374       {"fmlalb_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm},
    375       {"fmlalt_z_zzz"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH},
    376       {"fmlalt_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm},
    377       {"fmlslb_z_zzz"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH},
    378       {"fmlslb_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm},
    379       {"fmlslt_z_zzz"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH},
    380       {"fmlslt_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm},
    381       {"histcnt_z_p_zz"_h, &Disassembler::Disassemble_ZdT_PgZ_ZnT_ZmT},
    382       {"histseg_z_zz"_h, &Disassembler::Disassemble_ZdB_ZnB_ZmB},
    383       {"ldnt1b_z_p_ar_d_64_unscaled"_h,
    384        &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm},
    385       {"ldnt1b_z_p_ar_s_x32_unscaled"_h,
    386        &Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm},
    387       {"ldnt1d_z_p_ar_d_64_unscaled"_h,
    388        &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm},
    389       {"ldnt1h_z_p_ar_d_64_unscaled"_h,
    390        &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm},
    391       {"ldnt1h_z_p_ar_s_x32_unscaled"_h,
    392        &Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm},
    393       {"ldnt1sb_z_p_ar_d_64_unscaled"_h,
    394        &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm},
    395       {"ldnt1sb_z_p_ar_s_x32_unscaled"_h,
    396        &Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm},
    397       {"ldnt1sh_z_p_ar_d_64_unscaled"_h,
    398        &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm},
    399       {"ldnt1sh_z_p_ar_s_x32_unscaled"_h,
    400        &Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm},
    401       {"ldnt1sw_z_p_ar_d_64_unscaled"_h,
    402        &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm},
    403       {"ldnt1w_z_p_ar_d_64_unscaled"_h,
    404        &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm},
    405       {"ldnt1w_z_p_ar_s_x32_unscaled"_h,
    406        &Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm},
    407       {"match_p_p_zz"_h, &Disassembler::Disassemble_PdT_PgZ_ZnT_ZmT},
    408       {"mla_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnD_ZmD_imm},
    409       {"mla_z_zzzi_h"_h, &Disassembler::Disassemble_ZdH_ZnH_ZmH_imm},
    410       {"mla_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnS_ZmS_imm},
    411       {"mls_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnD_ZmD_imm},
    412       {"mls_z_zzzi_h"_h, &Disassembler::Disassemble_ZdH_ZnH_ZmH_imm},
    413       {"mls_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnS_ZmS_imm},
    414       {"mul_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT},
    415       {"mul_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnD_ZmD_imm},
    416       {"mul_z_zzi_h"_h, &Disassembler::Disassemble_ZdH_ZnH_ZmH_imm},
    417       {"mul_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnS_ZmS_imm},
    418       {"nbsl_z_zzz"_h, &Disassembler::DisassembleSVEBitwiseTernary},
    419       {"nmatch_p_p_zz"_h, &Disassembler::Disassemble_PdT_PgZ_ZnT_ZmT},
    420       {"pmul_z_zz"_h, &Disassembler::Disassemble_ZdB_ZnB_ZmB},
    421       {"pmullb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    422       {"pmullt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    423       {"raddhnb_z_zz"_h, &Disassembler::DisassembleSVEAddSubHigh},
    424       {"raddhnt_z_zz"_h, &Disassembler::DisassembleSVEAddSubHigh},
    425       {"rax1_z_zz"_h, &Disassembler::Disassemble_ZdD_ZnD_ZmD},
    426       {"rshrnb_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm},
    427       {"rshrnt_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm},
    428       {"rsubhnb_z_zz"_h, &Disassembler::DisassembleSVEAddSubHigh},
    429       {"rsubhnt_z_zz"_h, &Disassembler::DisassembleSVEAddSubHigh},
    430       {"saba_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnT_ZmT},
    431       {"sabalb_z_zzz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    432       {"sabalt_z_zzz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    433       {"sabdlb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    434       {"sabdlt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    435       {"sadalp_z_p_z"_h, &Disassembler::Disassemble_ZdaT_PgM_ZnTb},
    436       {"saddlb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    437       {"saddlbt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    438       {"saddlt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    439       {"saddwb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmTb},
    440       {"saddwt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmTb},
    441       {"sbclb_z_zzz"_h, &Disassembler::DisassembleSVEAddSubCarry},
    442       {"sbclt_z_zzz"_h, &Disassembler::DisassembleSVEAddSubCarry},
    443       {"shadd_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    444       {"shrnb_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm},
    445       {"shrnt_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm},
    446       {"shsub_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    447       {"shsubr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    448       {"sli_z_zzi"_h, &Disassembler::VisitSVEBitwiseShiftUnpredicated},
    449       {"sm4e_z_zz"_h, &Disassembler::Disassemble_ZdnS_ZdnS_ZmS},
    450       {"sm4ekey_z_zz"_h, &Disassembler::Disassemble_ZdS_ZnS_ZmS},
    451       {"smaxp_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    452       {"sminp_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    453       {"smlalb_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
    454       {"smlalb_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
    455       {"smlalb_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
    456       {"smlalt_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
    457       {"smlalt_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
    458       {"smlalt_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
    459       {"smlslb_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
    460       {"smlslb_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
    461       {"smlslb_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
    462       {"smlslt_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
    463       {"smlslt_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
    464       {"smlslt_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
    465       {"smulh_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT},
    466       {"smullb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    467       {"smullb_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
    468       {"smullb_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
    469       {"smullt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    470       {"smullt_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
    471       {"smullt_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
    472       {"splice_z_p_zz_con"_h, &Disassembler::Disassemble_ZdT_Pg_Zn1T_Zn2T},
    473       {"sqabs_z_p_z"_h, &Disassembler::Disassemble_ZdT_PgM_ZnT},
    474       {"sqadd_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    475       {"sqcadd_z_zz"_h, &Disassembler::DisassembleSVEComplexIntAddition},
    476       {"sqdmlalb_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
    477       {"sqdmlalb_z_zzzi_d"_h, &Disassembler::Disassemble_ZdaD_ZnS_ZmS_imm},
    478       {"sqdmlalb_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm},
    479       {"sqdmlalbt_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
    480       {"sqdmlalt_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
    481       {"sqdmlalt_z_zzzi_d"_h, &Disassembler::Disassemble_ZdaD_ZnS_ZmS_imm},
    482       {"sqdmlalt_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm},
    483       {"sqdmlslb_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
    484       {"sqdmlslb_z_zzzi_d"_h, &Disassembler::Disassemble_ZdaD_ZnS_ZmS_imm},
    485       {"sqdmlslb_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm},
    486       {"sqdmlslbt_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
    487       {"sqdmlslt_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
    488       {"sqdmlslt_z_zzzi_d"_h, &Disassembler::Disassemble_ZdaD_ZnS_ZmS_imm},
    489       {"sqdmlslt_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm},
    490       {"sqdmulh_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT},
    491       {"sqdmulh_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnD_ZmD_imm},
    492       {"sqdmulh_z_zzi_h"_h, &Disassembler::Disassemble_ZdH_ZnH_ZmH_imm},
    493       {"sqdmulh_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnS_ZmS_imm},
    494       {"sqdmullb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    495       {"sqdmullb_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
    496       {"sqdmullb_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
    497       {"sqdmullt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    498       {"sqdmullt_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
    499       {"sqdmullt_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
    500       {"sqneg_z_p_z"_h, &Disassembler::Disassemble_ZdT_PgM_ZnT},
    501       {"sqrdcmlah_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnT_ZmT_const},
    502       {"sqrdcmlah_z_zzzi_h"_h,
    503        &Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm_const},
    504       {"sqrdcmlah_z_zzzi_s"_h,
    505        &Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm_const},
    506       {"sqrdmlah_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnT_ZmT},
    507       {"sqrdmlah_z_zzzi_d"_h, &Disassembler::Disassemble_ZdaD_ZnD_ZmD_imm},
    508       {"sqrdmlah_z_zzzi_h"_h, &Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm},
    509       {"sqrdmlah_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm},
    510       {"sqrdmlsh_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnT_ZmT},
    511       {"sqrdmlsh_z_zzzi_d"_h, &Disassembler::Disassemble_ZdaD_ZnD_ZmD_imm},
    512       {"sqrdmlsh_z_zzzi_h"_h, &Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm},
    513       {"sqrdmlsh_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm},
    514       {"sqrdmulh_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT},
    515       {"sqrdmulh_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnD_ZmD_imm},
    516       {"sqrdmulh_z_zzi_h"_h, &Disassembler::Disassemble_ZdH_ZnH_ZmH_imm},
    517       {"sqrdmulh_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnS_ZmS_imm},
    518       {"sqrshl_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    519       {"sqrshlr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    520       {"sqrshrnb_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm},
    521       {"sqrshrnt_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm},
    522       {"sqrshrunb_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm},
    523       {"sqrshrunt_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm},
    524       {"sqshl_z_p_zi"_h, &Disassembler::VisitSVEBitwiseShiftByImm_Predicated},
    525       {"sqshl_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    526       {"sqshlr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    527       {"sqshlu_z_p_zi"_h, &Disassembler::VisitSVEBitwiseShiftByImm_Predicated},
    528       {"sqshrnb_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm},
    529       {"sqshrnt_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm},
    530       {"sqshrunb_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm},
    531       {"sqshrunt_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm},
    532       {"sqsub_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    533       {"sqsubr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    534       {"sqxtnb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb},
    535       {"sqxtnt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb},
    536       {"sqxtunb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb},
    537       {"sqxtunt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb},
    538       {"srhadd_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    539       {"sri_z_zzi"_h, &Disassembler::VisitSVEBitwiseShiftUnpredicated},
    540       {"srshl_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    541       {"srshlr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    542       {"srshr_z_p_zi"_h, &Disassembler::VisitSVEBitwiseShiftByImm_Predicated},
    543       {"srsra_z_zi"_h, &Disassembler::VisitSVEBitwiseShiftUnpredicated},
    544       {"sshllb_z_zi"_h, &Disassembler::DisassembleSVEShiftLeftImm},
    545       {"sshllt_z_zi"_h, &Disassembler::DisassembleSVEShiftLeftImm},
    546       {"ssra_z_zi"_h, &Disassembler::VisitSVEBitwiseShiftUnpredicated},
    547       {"ssublb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    548       {"ssublbt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    549       {"ssublt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    550       {"ssubltb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    551       {"ssubwb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmTb},
    552       {"ssubwt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmTb},
    553       {"stnt1b_z_p_ar_d_64_unscaled"_h,
    554        &Disassembler::Disassemble_ZtD_Pg_ZnD_Xm},
    555       {"stnt1b_z_p_ar_s_x32_unscaled"_h,
    556        &Disassembler::Disassemble_ZtS_Pg_ZnS_Xm},
    557       {"stnt1d_z_p_ar_d_64_unscaled"_h,
    558        &Disassembler::Disassemble_ZtD_Pg_ZnD_Xm},
    559       {"stnt1h_z_p_ar_d_64_unscaled"_h,
    560        &Disassembler::Disassemble_ZtD_Pg_ZnD_Xm},
    561       {"stnt1h_z_p_ar_s_x32_unscaled"_h,
    562        &Disassembler::Disassemble_ZtS_Pg_ZnS_Xm},
    563       {"stnt1w_z_p_ar_d_64_unscaled"_h,
    564        &Disassembler::Disassemble_ZtD_Pg_ZnD_Xm},
    565       {"stnt1w_z_p_ar_s_x32_unscaled"_h,
    566        &Disassembler::Disassemble_ZtS_Pg_ZnS_Xm},
    567       {"subhnb_z_zz"_h, &Disassembler::DisassembleSVEAddSubHigh},
    568       {"subhnt_z_zz"_h, &Disassembler::DisassembleSVEAddSubHigh},
    569       {"suqadd_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    570       {"tbl_z_zz_2"_h, &Disassembler::Disassemble_ZdT_Zn1T_Zn2T_ZmT},
    571       {"tbx_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT},
    572       {"uaba_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnT_ZmT},
    573       {"uabalb_z_zzz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    574       {"uabalt_z_zzz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    575       {"uabdlb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    576       {"uabdlt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    577       {"uadalp_z_p_z"_h, &Disassembler::Disassemble_ZdaT_PgM_ZnTb},
    578       {"uaddlb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    579       {"uaddlt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    580       {"uaddwb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmTb},
    581       {"uaddwt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmTb},
    582       {"uhadd_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    583       {"uhsub_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    584       {"uhsubr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    585       {"umaxp_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    586       {"uminp_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    587       {"umlalb_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
    588       {"umlalb_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
    589       {"umlalb_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
    590       {"umlalt_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
    591       {"umlalt_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
    592       {"umlalt_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
    593       {"umlslb_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
    594       {"umlslb_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
    595       {"umlslb_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
    596       {"umlslt_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
    597       {"umlslt_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
    598       {"umlslt_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
    599       {"umulh_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT},
    600       {"umullb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    601       {"umullb_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
    602       {"umullb_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
    603       {"umullt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    604       {"umullt_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
    605       {"umullt_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
    606       {"uqadd_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    607       {"uqrshl_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    608       {"uqrshlr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    609       {"uqrshrnb_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm},
    610       {"uqrshrnt_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm},
    611       {"uqshl_z_p_zi"_h, &Disassembler::VisitSVEBitwiseShiftByImm_Predicated},
    612       {"uqshl_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    613       {"uqshlr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    614       {"uqshrnb_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm},
    615       {"uqshrnt_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm},
    616       {"uqsub_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    617       {"uqsubr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    618       {"uqxtnb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb},
    619       {"uqxtnt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb},
    620       {"urecpe_z_p_z"_h, &Disassembler::Disassemble_ZdS_PgM_ZnS},
    621       {"urhadd_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    622       {"urshl_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    623       {"urshlr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    624       {"urshr_z_p_zi"_h, &Disassembler::VisitSVEBitwiseShiftByImm_Predicated},
    625       {"ursqrte_z_p_z"_h, &Disassembler::Disassemble_ZdS_PgM_ZnS},
    626       {"ursra_z_zi"_h, &Disassembler::VisitSVEBitwiseShiftUnpredicated},
    627       {"ushllb_z_zi"_h, &Disassembler::DisassembleSVEShiftLeftImm},
    628       {"ushllt_z_zi"_h, &Disassembler::DisassembleSVEShiftLeftImm},
    629       {"usqadd_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
    630       {"usra_z_zi"_h, &Disassembler::VisitSVEBitwiseShiftUnpredicated},
    631       {"usublb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    632       {"usublt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
    633       {"usubwb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmTb},
    634       {"usubwt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmTb},
    635       {"whilege_p_p_rr"_h,
    636        &Disassembler::VisitSVEIntCompareScalarCountAndLimit},
    637       {"whilegt_p_p_rr"_h,
    638        &Disassembler::VisitSVEIntCompareScalarCountAndLimit},
    639       {"whilehi_p_p_rr"_h,
    640        &Disassembler::VisitSVEIntCompareScalarCountAndLimit},
    641       {"whilehs_p_p_rr"_h,
    642        &Disassembler::VisitSVEIntCompareScalarCountAndLimit},
    643       {"whilerw_p_rr"_h, &Disassembler::VisitSVEIntCompareScalarCountAndLimit},
    644       {"whilewr_p_rr"_h, &Disassembler::VisitSVEIntCompareScalarCountAndLimit},
    645       {"xar_z_zzi"_h, &Disassembler::Disassemble_ZdnT_ZdnT_ZmT_const},
    646       {"fmmla_z_zzz_s"_h, &Disassembler::Disassemble_ZdaT_ZnT_ZmT},
    647       {"fmmla_z_zzz_d"_h, &Disassembler::Disassemble_ZdaT_ZnT_ZmT},
    648       {"smmla_z_zzz"_h, &Disassembler::Disassemble_ZdaS_ZnB_ZmB},
    649       {"ummla_z_zzz"_h, &Disassembler::Disassemble_ZdaS_ZnB_ZmB},
    650       {"usmmla_z_zzz"_h, &Disassembler::Disassemble_ZdaS_ZnB_ZmB},
    651       {"usdot_z_zzz_s"_h, &Disassembler::Disassemble_ZdaS_ZnB_ZmB},
    652       {"smmla_asimdsame2_g"_h, &Disassembler::Disassemble_Vd4S_Vn16B_Vm16B},
    653       {"ummla_asimdsame2_g"_h, &Disassembler::Disassemble_Vd4S_Vn16B_Vm16B},
    654       {"usmmla_asimdsame2_g"_h, &Disassembler::Disassemble_Vd4S_Vn16B_Vm16B},
    655       {"ld1row_z_p_bi_u32"_h,
    656        &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},
    657       {"ld1row_z_p_br_contiguous"_h,
    658        &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},
    659       {"ld1rod_z_p_bi_u64"_h,
    660        &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},
    661       {"ld1rod_z_p_br_contiguous"_h,
    662        &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},
    663       {"ld1rob_z_p_bi_u8"_h,
    664        &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},
    665       {"ld1rob_z_p_br_contiguous"_h,
    666        &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},
    667       {"ld1roh_z_p_bi_u16"_h,
    668        &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},
    669       {"ld1roh_z_p_br_contiguous"_h,
    670        &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},
    671       {"usdot_z_zzzi_s"_h, &Disassembler::VisitSVEMulIndex},
    672       {"sudot_z_zzzi_s"_h, &Disassembler::VisitSVEMulIndex},
    673       {"usdot_asimdsame2_d"_h, &Disassembler::VisitNEON3SameExtra},
    674       {"addg_64_addsub_immtags"_h,
    675        &Disassembler::Disassemble_XdSP_XnSP_uimm6_uimm4},
    676       {"gmi_64g_dp_2src"_h, &Disassembler::Disassemble_Xd_XnSP_Xm},
    677       {"irg_64i_dp_2src"_h, &Disassembler::Disassemble_XdSP_XnSP_Xm},
    678       {"ldg_64loffset_ldsttags"_h, &Disassembler::DisassembleMTELoadTag},
    679       {"st2g_64soffset_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag},
    680       {"st2g_64spost_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag},
    681       {"st2g_64spre_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag},
    682       {"stgp_64_ldstpair_off"_h, &Disassembler::DisassembleMTEStoreTagPair},
    683       {"stgp_64_ldstpair_post"_h, &Disassembler::DisassembleMTEStoreTagPair},
    684       {"stgp_64_ldstpair_pre"_h, &Disassembler::DisassembleMTEStoreTagPair},
    685       {"stg_64soffset_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag},
    686       {"stg_64spost_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag},
    687       {"stg_64spre_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag},
    688       {"stz2g_64soffset_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag},
    689       {"stz2g_64spost_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag},
    690       {"stz2g_64spre_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag},
    691       {"stzg_64soffset_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag},
    692       {"stzg_64spost_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag},
    693       {"stzg_64spre_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag},
    694       {"subg_64_addsub_immtags"_h,
    695        &Disassembler::Disassemble_XdSP_XnSP_uimm6_uimm4},
    696       {"subps_64s_dp_2src"_h, &Disassembler::Disassemble_Xd_XnSP_XmSP},
    697       {"subp_64s_dp_2src"_h, &Disassembler::Disassemble_Xd_XnSP_XmSP},
    698       {"cpyen_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    699       {"cpyern_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    700       {"cpyewn_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    701       {"cpye_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    702       {"cpyfen_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    703       {"cpyfern_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    704       {"cpyfewn_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    705       {"cpyfe_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    706       {"cpyfmn_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    707       {"cpyfmrn_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    708       {"cpyfmwn_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    709       {"cpyfm_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    710       {"cpyfpn_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    711       {"cpyfprn_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    712       {"cpyfpwn_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    713       {"cpyfp_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    714       {"cpymn_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    715       {"cpymrn_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    716       {"cpymwn_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    717       {"cpym_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    718       {"cpypn_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    719       {"cpyprn_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    720       {"cpypwn_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    721       {"cpyp_cpy_memcms"_h, &Disassembler::DisassembleCpy},
    722       {"seten_set_memcms"_h, &Disassembler::DisassembleSet},
    723       {"sete_set_memcms"_h, &Disassembler::DisassembleSet},
    724       {"setgen_set_memcms"_h, &Disassembler::DisassembleSet},
    725       {"setge_set_memcms"_h, &Disassembler::DisassembleSet},
    726       {"setgmn_set_memcms"_h, &Disassembler::DisassembleSet},
    727       {"setgm_set_memcms"_h, &Disassembler::DisassembleSet},
    728       {"setgpn_set_memcms"_h, &Disassembler::DisassembleSet},
    729       {"setgp_set_memcms"_h, &Disassembler::DisassembleSet},
    730       {"setmn_set_memcms"_h, &Disassembler::DisassembleSet},
    731       {"setm_set_memcms"_h, &Disassembler::DisassembleSet},
    732       {"setpn_set_memcms"_h, &Disassembler::DisassembleSet},
    733       {"setp_set_memcms"_h, &Disassembler::DisassembleSet},
    734       {"abs_32_dp_1src"_h, &Disassembler::VisitDataProcessing1Source},
    735       {"abs_64_dp_1src"_h, &Disassembler::VisitDataProcessing1Source},
    736       {"cnt_32_dp_1src"_h, &Disassembler::VisitDataProcessing1Source},
    737       {"cnt_64_dp_1src"_h, &Disassembler::VisitDataProcessing1Source},
    738       {"ctz_32_dp_1src"_h, &Disassembler::VisitDataProcessing1Source},
    739       {"ctz_64_dp_1src"_h, &Disassembler::VisitDataProcessing1Source},
    740       {"smax_32_dp_2src"_h, &Disassembler::VisitDataProcessing2Source},
    741       {"smax_64_dp_2src"_h, &Disassembler::VisitDataProcessing2Source},
    742       {"smin_32_dp_2src"_h, &Disassembler::VisitDataProcessing2Source},
    743       {"smin_64_dp_2src"_h, &Disassembler::VisitDataProcessing2Source},
    744       {"umax_32_dp_2src"_h, &Disassembler::VisitDataProcessing2Source},
    745       {"umax_64_dp_2src"_h, &Disassembler::VisitDataProcessing2Source},
    746       {"umin_32_dp_2src"_h, &Disassembler::VisitDataProcessing2Source},
    747       {"umin_64_dp_2src"_h, &Disassembler::VisitDataProcessing2Source},
    748       {"smax_32_minmax_imm"_h, &Disassembler::DisassembleMinMaxImm},
    749       {"smax_64_minmax_imm"_h, &Disassembler::DisassembleMinMaxImm},
    750       {"smin_32_minmax_imm"_h, &Disassembler::DisassembleMinMaxImm},
    751       {"smin_64_minmax_imm"_h, &Disassembler::DisassembleMinMaxImm},
    752       {"umax_32u_minmax_imm"_h, &Disassembler::DisassembleMinMaxImm},
    753       {"umax_64u_minmax_imm"_h, &Disassembler::DisassembleMinMaxImm},
    754       {"umin_32u_minmax_imm"_h, &Disassembler::DisassembleMinMaxImm},
    755       {"umin_64u_minmax_imm"_h, &Disassembler::DisassembleMinMaxImm},
    756   };
    757   return &form_to_visitor;
    758 }  // NOLINT(readability/fn_size)
    759 
    760 Disassembler::Disassembler() {
    761   buffer_size_ = 256;
    762   buffer_ = reinterpret_cast<char *>(malloc(buffer_size_));
    763   buffer_pos_ = 0;
    764   own_buffer_ = true;
    765   code_address_offset_ = 0;
    766 }
    767 
    768 Disassembler::Disassembler(char *text_buffer, int buffer_size) {
    769   buffer_size_ = buffer_size;
    770   buffer_ = text_buffer;
    771   buffer_pos_ = 0;
    772   own_buffer_ = false;
    773   code_address_offset_ = 0;
    774 }
    775 
    776 Disassembler::~Disassembler() {
    777   if (own_buffer_) {
    778     free(buffer_);
    779   }
    780 }
    781 
    782 char *Disassembler::GetOutput() { return buffer_; }
    783 
    784 void Disassembler::VisitAddSubImmediate(const Instruction *instr) {
    785   bool rd_is_zr = RdIsZROrSP(instr);
    786   bool stack_op =
    787       (rd_is_zr || RnIsZROrSP(instr)) && (instr->GetImmAddSub() == 0) ? true
    788                                                                       : false;
    789   const char *mnemonic = mnemonic_.c_str();
    790   const char *form = "'Rds, 'Rns, 'IAddSub";
    791   const char *form_cmp = "'Rns, 'IAddSub";
    792   const char *form_mov = "'Rds, 'Rns";
    793 
    794   switch (form_hash_) {
    795     case "add_32_addsub_imm"_h:
    796     case "add_64_addsub_imm"_h:
    797       if (stack_op) {
    798         mnemonic = "mov";
    799         form = form_mov;
    800       }
    801       break;
    802     case "adds_32s_addsub_imm"_h:
    803     case "adds_64s_addsub_imm"_h:
    804       if (rd_is_zr) {
    805         mnemonic = "cmn";
    806         form = form_cmp;
    807       }
    808       break;
    809     case "subs_32s_addsub_imm"_h:
    810     case "subs_64s_addsub_imm"_h:
    811       if (rd_is_zr) {
    812         mnemonic = "cmp";
    813         form = form_cmp;
    814       }
    815       break;
    816   }
    817   Format(instr, mnemonic, form);
    818 }
    819 
    820 
    821 void Disassembler::VisitAddSubShifted(const Instruction *instr) {
    822   bool rd_is_zr = RdIsZROrSP(instr);
    823   bool rn_is_zr = RnIsZROrSP(instr);
    824   const char *mnemonic = mnemonic_.c_str();
    825   const char *form = "'Rd, 'Rn, 'Rm'NDP";
    826   const char *form_cmp = "'Rn, 'Rm'NDP";
    827   const char *form_neg = "'Rd, 'Rm'NDP";
    828 
    829   if (instr->GetShiftDP() == ROR) {
    830     // Add/sub/adds/subs don't allow ROR as a shift mode.
    831     VisitUnallocated(instr);
    832     return;
    833   }
    834 
    835   switch (form_hash_) {
    836     case "adds_32_addsub_shift"_h:
    837     case "adds_64_addsub_shift"_h:
    838       if (rd_is_zr) {
    839         mnemonic = "cmn";
    840         form = form_cmp;
    841       }
    842       break;
    843     case "sub_32_addsub_shift"_h:
    844     case "sub_64_addsub_shift"_h:
    845       if (rn_is_zr) {
    846         mnemonic = "neg";
    847         form = form_neg;
    848       }
    849       break;
    850     case "subs_32_addsub_shift"_h:
    851     case "subs_64_addsub_shift"_h:
    852       if (rd_is_zr) {
    853         mnemonic = "cmp";
    854         form = form_cmp;
    855       } else if (rn_is_zr) {
    856         mnemonic = "negs";
    857         form = form_neg;
    858       }
    859   }
    860   Format(instr, mnemonic, form);
    861 }
    862 
    863 
    864 void Disassembler::VisitAddSubExtended(const Instruction *instr) {
    865   bool rd_is_zr = RdIsZROrSP(instr);
    866   const char *mnemonic = "";
    867   Extend mode = static_cast<Extend>(instr->GetExtendMode());
    868   const char *form = ((mode == UXTX) || (mode == SXTX)) ? "'Rds, 'Rns, 'Xm'Ext"
    869                                                         : "'Rds, 'Rns, 'Wm'Ext";
    870   const char *form_cmp =
    871       ((mode == UXTX) || (mode == SXTX)) ? "'Rns, 'Xm'Ext" : "'Rns, 'Wm'Ext";
    872 
    873   switch (instr->Mask(AddSubExtendedMask)) {
    874     case ADD_w_ext:
    875     case ADD_x_ext:
    876       mnemonic = "add";
    877       break;
    878     case ADDS_w_ext:
    879     case ADDS_x_ext: {
    880       mnemonic = "adds";
    881       if (rd_is_zr) {
    882         mnemonic = "cmn";
    883         form = form_cmp;
    884       }
    885       break;
    886     }
    887     case SUB_w_ext:
    888     case SUB_x_ext:
    889       mnemonic = "sub";
    890       break;
    891     case SUBS_w_ext:
    892     case SUBS_x_ext: {
    893       mnemonic = "subs";
    894       if (rd_is_zr) {
    895         mnemonic = "cmp";
    896         form = form_cmp;
    897       }
    898       break;
    899     }
    900     default:
    901       VIXL_UNREACHABLE();
    902   }
    903   Format(instr, mnemonic, form);
    904 }
    905 
    906 
    907 void Disassembler::VisitAddSubWithCarry(const Instruction *instr) {
    908   bool rn_is_zr = RnIsZROrSP(instr);
    909   const char *mnemonic = "";
    910   const char *form = "'Rd, 'Rn, 'Rm";
    911   const char *form_neg = "'Rd, 'Rm";
    912 
    913   switch (instr->Mask(AddSubWithCarryMask)) {
    914     case ADC_w:
    915     case ADC_x:
    916       mnemonic = "adc";
    917       break;
    918     case ADCS_w:
    919     case ADCS_x:
    920       mnemonic = "adcs";
    921       break;
    922     case SBC_w:
    923     case SBC_x: {
    924       mnemonic = "sbc";
    925       if (rn_is_zr) {
    926         mnemonic = "ngc";
    927         form = form_neg;
    928       }
    929       break;
    930     }
    931     case SBCS_w:
    932     case SBCS_x: {
    933       mnemonic = "sbcs";
    934       if (rn_is_zr) {
    935         mnemonic = "ngcs";
    936         form = form_neg;
    937       }
    938       break;
    939     }
    940     default:
    941       VIXL_UNREACHABLE();
    942   }
    943   Format(instr, mnemonic, form);
    944 }
    945 
    946 
    947 void Disassembler::VisitRotateRightIntoFlags(const Instruction *instr) {
    948   FormatWithDecodedMnemonic(instr, "'Xn, 'IRr, 'INzcv");
    949 }
    950 
    951 
    952 void Disassembler::VisitEvaluateIntoFlags(const Instruction *instr) {
    953   FormatWithDecodedMnemonic(instr, "'Wn");
    954 }
    955 
    956 
    957 void Disassembler::VisitLogicalImmediate(const Instruction *instr) {
    958   bool rd_is_zr = RdIsZROrSP(instr);
    959   bool rn_is_zr = RnIsZROrSP(instr);
    960   const char *mnemonic = "";
    961   const char *form = "'Rds, 'Rn, 'ITri";
    962 
    963   if (instr->GetImmLogical() == 0) {
    964     // The immediate encoded in the instruction is not in the expected format.
    965     Format(instr, "unallocated", "(LogicalImmediate)");
    966     return;
    967   }
    968 
    969   switch (instr->Mask(LogicalImmediateMask)) {
    970     case AND_w_imm:
    971     case AND_x_imm:
    972       mnemonic = "and";
    973       break;
    974     case ORR_w_imm:
    975     case ORR_x_imm: {
    976       mnemonic = "orr";
    977       unsigned reg_size =
    978           (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
    979       if (rn_is_zr && !IsMovzMovnImm(reg_size, instr->GetImmLogical())) {
    980         mnemonic = "mov";
    981         form = "'Rds, 'ITri";
    982       }
    983       break;
    984     }
    985     case EOR_w_imm:
    986     case EOR_x_imm:
    987       mnemonic = "eor";
    988       break;
    989     case ANDS_w_imm:
    990     case ANDS_x_imm: {
    991       mnemonic = "ands";
    992       if (rd_is_zr) {
    993         mnemonic = "tst";
    994         form = "'Rn, 'ITri";
    995       }
    996       break;
    997     }
    998     default:
    999       VIXL_UNREACHABLE();
   1000   }
   1001   Format(instr, mnemonic, form);
   1002 }
   1003 
   1004 
   1005 bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
   1006   VIXL_ASSERT((reg_size == kXRegSize) ||
   1007               ((reg_size == kWRegSize) && (value <= 0xffffffff)));
   1008 
   1009   // Test for movz: 16 bits set at positions 0, 16, 32 or 48.
   1010   if (((value & UINT64_C(0xffffffffffff0000)) == 0) ||
   1011       ((value & UINT64_C(0xffffffff0000ffff)) == 0) ||
   1012       ((value & UINT64_C(0xffff0000ffffffff)) == 0) ||
   1013       ((value & UINT64_C(0x0000ffffffffffff)) == 0)) {
   1014     return true;
   1015   }
   1016 
   1017   // Test for movn: NOT(16 bits set at positions 0, 16, 32 or 48).
   1018   if ((reg_size == kXRegSize) &&
   1019       (((~value & UINT64_C(0xffffffffffff0000)) == 0) ||
   1020        ((~value & UINT64_C(0xffffffff0000ffff)) == 0) ||
   1021        ((~value & UINT64_C(0xffff0000ffffffff)) == 0) ||
   1022        ((~value & UINT64_C(0x0000ffffffffffff)) == 0))) {
   1023     return true;
   1024   }
   1025   if ((reg_size == kWRegSize) && (((value & 0xffff0000) == 0xffff0000) ||
   1026                                   ((value & 0x0000ffff) == 0x0000ffff))) {
   1027     return true;
   1028   }
   1029   return false;
   1030 }
   1031 
   1032 
   1033 void Disassembler::VisitLogicalShifted(const Instruction *instr) {
   1034   bool rd_is_zr = RdIsZROrSP(instr);
   1035   bool rn_is_zr = RnIsZROrSP(instr);
   1036   const char *mnemonic = mnemonic_.c_str();
   1037   const char *form = "'Rd, 'Rn, 'Rm'NLo";
   1038 
   1039   switch (form_hash_) {
   1040     case "ands_32_log_shift"_h:
   1041     case "ands_64_log_shift"_h:
   1042       if (rd_is_zr) {
   1043         mnemonic = "tst";
   1044         form = "'Rn, 'Rm'NLo";
   1045       }
   1046       break;
   1047     case "orr_32_log_shift"_h:
   1048     case "orr_64_log_shift"_h:
   1049       if (rn_is_zr && (instr->GetImmDPShift() == 0) &&
   1050           (instr->GetShiftDP() == LSL)) {
   1051         mnemonic = "mov";
   1052         form = "'Rd, 'Rm";
   1053       }
   1054       break;
   1055     case "orn_32_log_shift"_h:
   1056     case "orn_64_log_shift"_h:
   1057       if (rn_is_zr) {
   1058         mnemonic = "mvn";
   1059         form = "'Rd, 'Rm'NLo";
   1060       }
   1061       break;
   1062   }
   1063 
   1064   Format(instr, mnemonic, form);
   1065 }
   1066 
   1067 
   1068 void Disassembler::VisitConditionalCompareRegister(const Instruction *instr) {
   1069   FormatWithDecodedMnemonic(instr, "'Rn, 'Rm, 'INzcv, 'Cond");
   1070 }
   1071 
   1072 
   1073 void Disassembler::VisitConditionalCompareImmediate(const Instruction *instr) {
   1074   FormatWithDecodedMnemonic(instr, "'Rn, 'IP, 'INzcv, 'Cond");
   1075 }
   1076 
   1077 
   1078 void Disassembler::VisitConditionalSelect(const Instruction *instr) {
   1079   bool rnm_is_zr = (RnIsZROrSP(instr) && RmIsZROrSP(instr));
   1080   bool rn_is_rm = (instr->GetRn() == instr->GetRm());
   1081   const char *mnemonic = "";
   1082   const char *form = "'Rd, 'Rn, 'Rm, 'Cond";
   1083   const char *form_test = "'Rd, 'CInv";
   1084   const char *form_update = "'Rd, 'Rn, 'CInv";
   1085 
   1086   Condition cond = static_cast<Condition>(instr->GetCondition());
   1087   bool invertible_cond = (cond != al) && (cond != nv);
   1088 
   1089   switch (instr->Mask(ConditionalSelectMask)) {
   1090     case CSEL_w:
   1091     case CSEL_x:
   1092       mnemonic = "csel";
   1093       break;
   1094     case CSINC_w:
   1095     case CSINC_x: {
   1096       mnemonic = "csinc";
   1097       if (rnm_is_zr && invertible_cond) {
   1098         mnemonic = "cset";
   1099         form = form_test;
   1100       } else if (rn_is_rm && invertible_cond) {
   1101         mnemonic = "cinc";
   1102         form = form_update;
   1103       }
   1104       break;
   1105     }
   1106     case CSINV_w:
   1107     case CSINV_x: {
   1108       mnemonic = "csinv";
   1109       if (rnm_is_zr && invertible_cond) {
   1110         mnemonic = "csetm";
   1111         form = form_test;
   1112       } else if (rn_is_rm && invertible_cond) {
   1113         mnemonic = "cinv";
   1114         form = form_update;
   1115       }
   1116       break;
   1117     }
   1118     case CSNEG_w:
   1119     case CSNEG_x: {
   1120       mnemonic = "csneg";
   1121       if (rn_is_rm && invertible_cond) {
   1122         mnemonic = "cneg";
   1123         form = form_update;
   1124       }
   1125       break;
   1126     }
   1127     default:
   1128       VIXL_UNREACHABLE();
   1129   }
   1130   Format(instr, mnemonic, form);
   1131 }
   1132 
   1133 
   1134 void Disassembler::VisitBitfield(const Instruction *instr) {
   1135   unsigned s = instr->GetImmS();
   1136   unsigned r = instr->GetImmR();
   1137   unsigned rd_size_minus_1 =
   1138       ((instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize) - 1;
   1139   const char *mnemonic = "";
   1140   const char *form = "";
   1141   const char *form_shift_right = "'Rd, 'Rn, 'IBr";
   1142   const char *form_extend = "'Rd, 'Wn";
   1143   const char *form_bfiz = "'Rd, 'Rn, 'IBZ-r, 'IBs+1";
   1144   const char *form_bfc = "'Rd, 'IBZ-r, 'IBs+1";
   1145   const char *form_bfx = "'Rd, 'Rn, 'IBr, 'IBs-r+1";
   1146   const char *form_lsl = "'Rd, 'Rn, 'IBZ-r";
   1147 
   1148   if (instr->GetSixtyFourBits() != instr->GetBitN()) {
   1149     VisitUnallocated(instr);
   1150     return;
   1151   }
   1152 
   1153   if ((instr->GetSixtyFourBits() == 0) && ((s > 31) || (r > 31))) {
   1154     VisitUnallocated(instr);
   1155     return;
   1156   }
   1157 
   1158   switch (instr->Mask(BitfieldMask)) {
   1159     case SBFM_w:
   1160     case SBFM_x: {
   1161       mnemonic = "sbfx";
   1162       form = form_bfx;
   1163       if (r == 0) {
   1164         form = form_extend;
   1165         if (s == 7) {
   1166           mnemonic = "sxtb";
   1167         } else if (s == 15) {
   1168           mnemonic = "sxth";
   1169         } else if ((s == 31) && (instr->GetSixtyFourBits() == 1)) {
   1170           mnemonic = "sxtw";
   1171         } else {
   1172           form = form_bfx;
   1173         }
   1174       } else if (s == rd_size_minus_1) {
   1175         mnemonic = "asr";
   1176         form = form_shift_right;
   1177       } else if (s < r) {
   1178         mnemonic = "sbfiz";
   1179         form = form_bfiz;
   1180       }
   1181       break;
   1182     }
   1183     case UBFM_w:
   1184     case UBFM_x: {
   1185       mnemonic = "ubfx";
   1186       form = form_bfx;
   1187       if (r == 0) {
   1188         form = form_extend;
   1189         if (s == 7) {
   1190           mnemonic = "uxtb";
   1191         } else if (s == 15) {
   1192           mnemonic = "uxth";
   1193         } else {
   1194           form = form_bfx;
   1195         }
   1196       }
   1197       if (s == rd_size_minus_1) {
   1198         mnemonic = "lsr";
   1199         form = form_shift_right;
   1200       } else if (r == s + 1) {
   1201         mnemonic = "lsl";
   1202         form = form_lsl;
   1203       } else if (s < r) {
   1204         mnemonic = "ubfiz";
   1205         form = form_bfiz;
   1206       }
   1207       break;
   1208     }
   1209     case BFM_w:
   1210     case BFM_x: {
   1211       mnemonic = "bfxil";
   1212       form = form_bfx;
   1213       if (s < r) {
   1214         if (instr->GetRn() == kZeroRegCode) {
   1215           mnemonic = "bfc";
   1216           form = form_bfc;
   1217         } else {
   1218           mnemonic = "bfi";
   1219           form = form_bfiz;
   1220         }
   1221       }
   1222     }
   1223   }
   1224   Format(instr, mnemonic, form);
   1225 }
   1226 
   1227 
   1228 void Disassembler::VisitExtract(const Instruction *instr) {
   1229   const char *mnemonic = "";
   1230   const char *form = "'Rd, 'Rn, 'Rm, 'IExtract";
   1231 
   1232   switch (instr->Mask(ExtractMask)) {
   1233     case EXTR_w:
   1234     case EXTR_x: {
   1235       if (instr->GetRn() == instr->GetRm()) {
   1236         mnemonic = "ror";
   1237         form = "'Rd, 'Rn, 'IExtract";
   1238       } else {
   1239         mnemonic = "extr";
   1240       }
   1241       break;
   1242     }
   1243     default:
   1244       VIXL_UNREACHABLE();
   1245   }
   1246   Format(instr, mnemonic, form);
   1247 }
   1248 
   1249 
   1250 void Disassembler::VisitPCRelAddressing(const Instruction *instr) {
   1251   switch (instr->Mask(PCRelAddressingMask)) {
   1252     case ADR:
   1253       Format(instr, "adr", "'Xd, 'AddrPCRelByte");
   1254       break;
   1255     case ADRP:
   1256       Format(instr, "adrp", "'Xd, 'AddrPCRelPage");
   1257       break;
   1258     default:
   1259       Format(instr, "unimplemented", "(PCRelAddressing)");
   1260   }
   1261 }
   1262 
   1263 
   1264 void Disassembler::VisitConditionalBranch(const Instruction *instr) {
   1265   // We can't use the mnemonic directly here, as there's no space between it and
   1266   // the condition. Assert that we have the correct mnemonic, then use "b"
   1267   // explicitly for formatting the output.
   1268   VIXL_ASSERT(form_hash_ == "b_only_condbranch"_h);
   1269   Format(instr, "b.'CBrn", "'TImmCond");
   1270 }
   1271 
   1272 
   1273 void Disassembler::VisitUnconditionalBranchToRegister(
   1274     const Instruction *instr) {
   1275   const char *form = "'Xn";
   1276 
   1277   switch (form_hash_) {
   1278     case "ret_64r_branch_reg"_h:
   1279       if (instr->GetRn() == kLinkRegCode) {
   1280         form = "";
   1281       }
   1282       break;
   1283     case "retaa_64e_branch_reg"_h:
   1284     case "retab_64e_branch_reg"_h:
   1285       form = "";
   1286       break;
   1287     case "braa_64p_branch_reg"_h:
   1288     case "brab_64p_branch_reg"_h:
   1289     case "blraa_64p_branch_reg"_h:
   1290     case "blrab_64p_branch_reg"_h:
   1291       form = "'Xn, 'Xds";
   1292       break;
   1293   }
   1294 
   1295   FormatWithDecodedMnemonic(instr, form);
   1296 }
   1297 
   1298 
   1299 void Disassembler::VisitUnconditionalBranch(const Instruction *instr) {
   1300   FormatWithDecodedMnemonic(instr, "'TImmUncn");
   1301 }
   1302 
   1303 
   1304 void Disassembler::VisitDataProcessing1Source(const Instruction *instr) {
   1305   const char *form = "'Rd, 'Rn";
   1306 
   1307   switch (form_hash_) {
   1308     case "pacia_64p_dp_1src"_h:
   1309     case "pacda_64p_dp_1src"_h:
   1310     case "autia_64p_dp_1src"_h:
   1311     case "autda_64p_dp_1src"_h:
   1312     case "pacib_64p_dp_1src"_h:
   1313     case "pacdb_64p_dp_1src"_h:
   1314     case "autib_64p_dp_1src"_h:
   1315     case "autdb_64p_dp_1src"_h:
   1316       form = "'Xd, 'Xns";
   1317       break;
   1318     case "paciza_64z_dp_1src"_h:
   1319     case "pacdza_64z_dp_1src"_h:
   1320     case "autiza_64z_dp_1src"_h:
   1321     case "autdza_64z_dp_1src"_h:
   1322     case "pacizb_64z_dp_1src"_h:
   1323     case "pacdzb_64z_dp_1src"_h:
   1324     case "autizb_64z_dp_1src"_h:
   1325     case "autdzb_64z_dp_1src"_h:
   1326     case "xpacd_64z_dp_1src"_h:
   1327     case "xpaci_64z_dp_1src"_h:
   1328       form = "'Xd";
   1329       break;
   1330   }
   1331   FormatWithDecodedMnemonic(instr, form);
   1332 }
   1333 
   1334 
   1335 void Disassembler::VisitDataProcessing2Source(const Instruction *instr) {
   1336   std::string mnemonic = mnemonic_;
   1337   const char *form = "'Rd, 'Rn, 'Rm";
   1338 
   1339   switch (form_hash_) {
   1340     case "asrv_32_dp_2src"_h:
   1341     case "asrv_64_dp_2src"_h:
   1342     case "lslv_32_dp_2src"_h:
   1343     case "lslv_64_dp_2src"_h:
   1344     case "lsrv_32_dp_2src"_h:
   1345     case "lsrv_64_dp_2src"_h:
   1346     case "rorv_32_dp_2src"_h:
   1347     case "rorv_64_dp_2src"_h:
   1348       // Drop the last 'v' character.
   1349       VIXL_ASSERT(mnemonic[3] == 'v');
   1350       mnemonic.pop_back();
   1351       break;
   1352     case "pacga_64p_dp_2src"_h:
   1353       form = "'Xd, 'Xn, 'Xms";
   1354       break;
   1355     case "crc32x_64c_dp_2src"_h:
   1356     case "crc32cx_64c_dp_2src"_h:
   1357       form = "'Wd, 'Wn, 'Xm";
   1358       break;
   1359   }
   1360   Format(instr, mnemonic.c_str(), form);
   1361 }
   1362 
   1363 
   1364 void Disassembler::VisitDataProcessing3Source(const Instruction *instr) {
   1365   bool ra_is_zr = RaIsZROrSP(instr);
   1366   const char *mnemonic = "";
   1367   const char *form = "'Xd, 'Wn, 'Wm, 'Xa";
   1368   const char *form_rrr = "'Rd, 'Rn, 'Rm";
   1369   const char *form_rrrr = "'Rd, 'Rn, 'Rm, 'Ra";
   1370   const char *form_xww = "'Xd, 'Wn, 'Wm";
   1371   const char *form_xxx = "'Xd, 'Xn, 'Xm";
   1372 
   1373   switch (instr->Mask(DataProcessing3SourceMask)) {
   1374     case MADD_w:
   1375     case MADD_x: {
   1376       mnemonic = "madd";
   1377       form = form_rrrr;
   1378       if (ra_is_zr) {
   1379         mnemonic = "mul";
   1380         form = form_rrr;
   1381       }
   1382       break;
   1383     }
   1384     case MSUB_w:
   1385     case MSUB_x: {
   1386       mnemonic = "msub";
   1387       form = form_rrrr;
   1388       if (ra_is_zr) {
   1389         mnemonic = "mneg";
   1390         form = form_rrr;
   1391       }
   1392       break;
   1393     }
   1394     case SMADDL_x: {
   1395       mnemonic = "smaddl";
   1396       if (ra_is_zr) {
   1397         mnemonic = "smull";
   1398         form = form_xww;
   1399       }
   1400       break;
   1401     }
   1402     case SMSUBL_x: {
   1403       mnemonic = "smsubl";
   1404       if (ra_is_zr) {
   1405         mnemonic = "smnegl";
   1406         form = form_xww;
   1407       }
   1408       break;
   1409     }
   1410     case UMADDL_x: {
   1411       mnemonic = "umaddl";
   1412       if (ra_is_zr) {
   1413         mnemonic = "umull";
   1414         form = form_xww;
   1415       }
   1416       break;
   1417     }
   1418     case UMSUBL_x: {
   1419       mnemonic = "umsubl";
   1420       if (ra_is_zr) {
   1421         mnemonic = "umnegl";
   1422         form = form_xww;
   1423       }
   1424       break;
   1425     }
   1426     case SMULH_x: {
   1427       mnemonic = "smulh";
   1428       form = form_xxx;
   1429       break;
   1430     }
   1431     case UMULH_x: {
   1432       mnemonic = "umulh";
   1433       form = form_xxx;
   1434       break;
   1435     }
   1436     default:
   1437       VIXL_UNREACHABLE();
   1438   }
   1439   Format(instr, mnemonic, form);
   1440 }
   1441 
   1442 void Disassembler::DisassembleMinMaxImm(const Instruction *instr) {
   1443   const char *suffix = (instr->ExtractBit(18) == 0) ? "'s1710" : "'u1710";
   1444   FormatWithDecodedMnemonic(instr, "'Rd, 'Rn, #", suffix);
   1445 }
   1446 
   1447 void Disassembler::VisitCompareBranch(const Instruction *instr) {
   1448   FormatWithDecodedMnemonic(instr, "'Rt, 'TImmCmpa");
   1449 }
   1450 
   1451 
   1452 void Disassembler::VisitTestBranch(const Instruction *instr) {
   1453   // If the top bit of the immediate is clear, the tested register is
   1454   // disassembled as Wt, otherwise Xt. As the top bit of the immediate is
   1455   // encoded in bit 31 of the instruction, we can reuse the Rt form, which
   1456   // uses bit 31 (normally "sf") to choose the register size.
   1457   FormatWithDecodedMnemonic(instr, "'Rt, 'It, 'TImmTest");
   1458 }
   1459 
   1460 
   1461 void Disassembler::VisitMoveWideImmediate(const Instruction *instr) {
   1462   const char *mnemonic = "";
   1463   const char *form = "'Rd, 'IMoveImm";
   1464 
   1465   // Print the shift separately for movk, to make it clear which half word will
   1466   // be overwritten. Movn and movz print the computed immediate, which includes
   1467   // shift calculation.
   1468   switch (instr->Mask(MoveWideImmediateMask)) {
   1469     case MOVN_w:
   1470     case MOVN_x:
   1471       if ((instr->GetImmMoveWide()) || (instr->GetShiftMoveWide() == 0)) {
   1472         if ((instr->GetSixtyFourBits() == 0) &&
   1473             (instr->GetImmMoveWide() == 0xffff)) {
   1474           mnemonic = "movn";
   1475         } else {
   1476           mnemonic = "mov";
   1477           form = "'Rd, 'IMoveNeg";
   1478         }
   1479       } else {
   1480         mnemonic = "movn";
   1481       }
   1482       break;
   1483     case MOVZ_w:
   1484     case MOVZ_x:
   1485       if ((instr->GetImmMoveWide()) || (instr->GetShiftMoveWide() == 0))
   1486         mnemonic = "mov";
   1487       else
   1488         mnemonic = "movz";
   1489       break;
   1490     case MOVK_w:
   1491     case MOVK_x:
   1492       mnemonic = "movk";
   1493       form = "'Rd, 'IMoveLSL";
   1494       break;
   1495     default:
   1496       VIXL_UNREACHABLE();
   1497   }
   1498   Format(instr, mnemonic, form);
   1499 }
   1500 
   1501 
   1502 #define LOAD_STORE_LIST(V) \
   1503   V(STRB_w, "'Wt")         \
   1504   V(STRH_w, "'Wt")         \
   1505   V(STR_w, "'Wt")          \
   1506   V(STR_x, "'Xt")          \
   1507   V(LDRB_w, "'Wt")         \
   1508   V(LDRH_w, "'Wt")         \
   1509   V(LDR_w, "'Wt")          \
   1510   V(LDR_x, "'Xt")          \
   1511   V(LDRSB_x, "'Xt")        \
   1512   V(LDRSH_x, "'Xt")        \
   1513   V(LDRSW_x, "'Xt")        \
   1514   V(LDRSB_w, "'Wt")        \
   1515   V(LDRSH_w, "'Wt")        \
   1516   V(STR_b, "'Bt")          \
   1517   V(STR_h, "'Ht")          \
   1518   V(STR_s, "'St")          \
   1519   V(STR_d, "'Dt")          \
   1520   V(LDR_b, "'Bt")          \
   1521   V(LDR_h, "'Ht")          \
   1522   V(LDR_s, "'St")          \
   1523   V(LDR_d, "'Dt")          \
   1524   V(STR_q, "'Qt")          \
   1525   V(LDR_q, "'Qt")
   1526 
   1527 void Disassembler::VisitLoadStorePreIndex(const Instruction *instr) {
   1528   const char *form = "(LoadStorePreIndex)";
   1529   const char *suffix = ", ['Xns'ILSi]!";
   1530 
   1531   switch (instr->Mask(LoadStorePreIndexMask)) {
   1532 #define LS_PREINDEX(A, B) \
   1533   case A##_pre:           \
   1534     form = B;             \
   1535     break;
   1536     LOAD_STORE_LIST(LS_PREINDEX)
   1537 #undef LS_PREINDEX
   1538   }
   1539   FormatWithDecodedMnemonic(instr, form, suffix);
   1540 }
   1541 
   1542 
   1543 void Disassembler::VisitLoadStorePostIndex(const Instruction *instr) {
   1544   const char *form = "(LoadStorePostIndex)";
   1545   const char *suffix = ", ['Xns]'ILSi";
   1546 
   1547   switch (instr->Mask(LoadStorePostIndexMask)) {
   1548 #define LS_POSTINDEX(A, B) \
   1549   case A##_post:           \
   1550     form = B;              \
   1551     break;
   1552     LOAD_STORE_LIST(LS_POSTINDEX)
   1553 #undef LS_POSTINDEX
   1554   }
   1555   FormatWithDecodedMnemonic(instr, form, suffix);
   1556 }
   1557 
   1558 
   1559 void Disassembler::VisitLoadStoreUnsignedOffset(const Instruction *instr) {
   1560   const char *form = "(LoadStoreUnsignedOffset)";
   1561   const char *suffix = ", ['Xns'ILU]";
   1562 
   1563   switch (instr->Mask(LoadStoreUnsignedOffsetMask)) {
   1564 #define LS_UNSIGNEDOFFSET(A, B) \
   1565   case A##_unsigned:            \
   1566     form = B;                   \
   1567     break;
   1568     LOAD_STORE_LIST(LS_UNSIGNEDOFFSET)
   1569 #undef LS_UNSIGNEDOFFSET
   1570     case PRFM_unsigned:
   1571       form = "'prefOp";
   1572   }
   1573   FormatWithDecodedMnemonic(instr, form, suffix);
   1574 }
   1575 
   1576 
   1577 void Disassembler::VisitLoadStoreRCpcUnscaledOffset(const Instruction *instr) {
   1578   const char *mnemonic = mnemonic_.c_str();
   1579   const char *form = "'Wt, ['Xns'ILS]";
   1580   const char *form_x = "'Xt, ['Xns'ILS]";
   1581 
   1582   switch (form_hash_) {
   1583     case "ldapursb_64_ldapstl_unscaled"_h:
   1584     case "ldapursh_64_ldapstl_unscaled"_h:
   1585     case "ldapursw_64_ldapstl_unscaled"_h:
   1586     case "ldapur_64_ldapstl_unscaled"_h:
   1587     case "stlur_64_ldapstl_unscaled"_h:
   1588       form = form_x;
   1589       break;
   1590   }
   1591 
   1592   Format(instr, mnemonic, form);
   1593 }
   1594 
   1595 
   1596 void Disassembler::VisitLoadStoreRegisterOffset(const Instruction *instr) {
   1597   const char *form = "(LoadStoreRegisterOffset)";
   1598   const char *suffix = ", ['Xns, 'Offsetreg]";
   1599 
   1600   switch (instr->Mask(LoadStoreRegisterOffsetMask)) {
   1601 #define LS_REGISTEROFFSET(A, B) \
   1602   case A##_reg:                 \
   1603     form = B;                   \
   1604     break;
   1605     LOAD_STORE_LIST(LS_REGISTEROFFSET)
   1606 #undef LS_REGISTEROFFSET
   1607     case PRFM_reg:
   1608       form = "'prefOp";
   1609   }
   1610   FormatWithDecodedMnemonic(instr, form, suffix);
   1611 }
   1612 
   1613 
   1614 void Disassembler::VisitLoadStoreUnscaledOffset(const Instruction *instr) {
   1615   const char *form = "'Wt";
   1616   const char *suffix = ", ['Xns'ILS]";
   1617 
   1618   switch (form_hash_) {
   1619     case "ldur_64_ldst_unscaled"_h:
   1620     case "ldursb_64_ldst_unscaled"_h:
   1621     case "ldursh_64_ldst_unscaled"_h:
   1622     case "ldursw_64_ldst_unscaled"_h:
   1623     case "stur_64_ldst_unscaled"_h:
   1624       form = "'Xt";
   1625       break;
   1626     case "ldur_b_ldst_unscaled"_h:
   1627     case "stur_b_ldst_unscaled"_h:
   1628       form = "'Bt";
   1629       break;
   1630     case "ldur_h_ldst_unscaled"_h:
   1631     case "stur_h_ldst_unscaled"_h:
   1632       form = "'Ht";
   1633       break;
   1634     case "ldur_s_ldst_unscaled"_h:
   1635     case "stur_s_ldst_unscaled"_h:
   1636       form = "'St";
   1637       break;
   1638     case "ldur_d_ldst_unscaled"_h:
   1639     case "stur_d_ldst_unscaled"_h:
   1640       form = "'Dt";
   1641       break;
   1642     case "ldur_q_ldst_unscaled"_h:
   1643     case "stur_q_ldst_unscaled"_h:
   1644       form = "'Qt";
   1645       break;
   1646     case "prfum_p_ldst_unscaled"_h:
   1647       form = "'prefOp";
   1648       break;
   1649   }
   1650   FormatWithDecodedMnemonic(instr, form, suffix);
   1651 }
   1652 
   1653 
   1654 void Disassembler::VisitLoadLiteral(const Instruction *instr) {
   1655   const char *form = "'Wt";
   1656   const char *suffix = ", 'ILLiteral 'LValue";
   1657 
   1658   switch (form_hash_) {
   1659     case "ldr_64_loadlit"_h:
   1660     case "ldrsw_64_loadlit"_h:
   1661       form = "'Xt";
   1662       break;
   1663     case "ldr_s_loadlit"_h:
   1664       form = "'St";
   1665       break;
   1666     case "ldr_d_loadlit"_h:
   1667       form = "'Dt";
   1668       break;
   1669     case "ldr_q_loadlit"_h:
   1670       form = "'Qt";
   1671       break;
   1672     case "prfm_p_loadlit"_h:
   1673       form = "'prefOp";
   1674       break;
   1675   }
   1676   FormatWithDecodedMnemonic(instr, form, suffix);
   1677 }
   1678 
   1679 
   1680 #define LOAD_STORE_PAIR_LIST(V) \
   1681   V(STP_w, "'Wt, 'Wt2", "2")    \
   1682   V(LDP_w, "'Wt, 'Wt2", "2")    \
   1683   V(LDPSW_x, "'Xt, 'Xt2", "2")  \
   1684   V(STP_x, "'Xt, 'Xt2", "3")    \
   1685   V(LDP_x, "'Xt, 'Xt2", "3")    \
   1686   V(STP_s, "'St, 'St2", "2")    \
   1687   V(LDP_s, "'St, 'St2", "2")    \
   1688   V(STP_d, "'Dt, 'Dt2", "3")    \
   1689   V(LDP_d, "'Dt, 'Dt2", "3")    \
   1690   V(LDP_q, "'Qt, 'Qt2", "4")    \
   1691   V(STP_q, "'Qt, 'Qt2", "4")
   1692 
   1693 void Disassembler::VisitLoadStorePairPostIndex(const Instruction *instr) {
   1694   const char *form = "(LoadStorePairPostIndex)";
   1695 
   1696   switch (instr->Mask(LoadStorePairPostIndexMask)) {
   1697 #define LSP_POSTINDEX(A, B, C)     \
   1698   case A##_post:                   \
   1699     form = B ", ['Xns]'ILP" C "i"; \
   1700     break;
   1701     LOAD_STORE_PAIR_LIST(LSP_POSTINDEX)
   1702 #undef LSP_POSTINDEX
   1703   }
   1704   FormatWithDecodedMnemonic(instr, form);
   1705 }
   1706 
   1707 
   1708 void Disassembler::VisitLoadStorePairPreIndex(const Instruction *instr) {
   1709   const char *form = "(LoadStorePairPreIndex)";
   1710 
   1711   switch (instr->Mask(LoadStorePairPreIndexMask)) {
   1712 #define LSP_PREINDEX(A, B, C)       \
   1713   case A##_pre:                     \
   1714     form = B ", ['Xns'ILP" C "i]!"; \
   1715     break;
   1716     LOAD_STORE_PAIR_LIST(LSP_PREINDEX)
   1717 #undef LSP_PREINDEX
   1718   }
   1719   FormatWithDecodedMnemonic(instr, form);
   1720 }
   1721 
   1722 
   1723 void Disassembler::VisitLoadStorePairOffset(const Instruction *instr) {
   1724   const char *form = "(LoadStorePairOffset)";
   1725 
   1726   switch (instr->Mask(LoadStorePairOffsetMask)) {
   1727 #define LSP_OFFSET(A, B, C)       \
   1728   case A##_off:                   \
   1729     form = B ", ['Xns'ILP" C "]"; \
   1730     break;
   1731     LOAD_STORE_PAIR_LIST(LSP_OFFSET)
   1732 #undef LSP_OFFSET
   1733   }
   1734   FormatWithDecodedMnemonic(instr, form);
   1735 }
   1736 
   1737 
   1738 void Disassembler::VisitLoadStorePairNonTemporal(const Instruction *instr) {
   1739   const char *form = "'Wt, 'Wt2, ['Xns'ILP2]";
   1740 
   1741   switch (form_hash_) {
   1742     case "ldnp_64_ldstnapair_offs"_h:
   1743     case "stnp_64_ldstnapair_offs"_h:
   1744       form = "'Xt, 'Xt2, ['Xns'ILP3]";
   1745       break;
   1746     case "ldnp_s_ldstnapair_offs"_h:
   1747     case "stnp_s_ldstnapair_offs"_h:
   1748       form = "'St, 'St2, ['Xns'ILP2]";
   1749       break;
   1750     case "ldnp_d_ldstnapair_offs"_h:
   1751     case "stnp_d_ldstnapair_offs"_h:
   1752       form = "'Dt, 'Dt2, ['Xns'ILP3]";
   1753       break;
   1754     case "ldnp_q_ldstnapair_offs"_h:
   1755     case "stnp_q_ldstnapair_offs"_h:
   1756       form = "'Qt, 'Qt2, ['Xns'ILP4]";
   1757       break;
   1758   }
   1759   FormatWithDecodedMnemonic(instr, form);
   1760 }
   1761 
   1762 // clang-format off
   1763 #define LOAD_STORE_EXCLUSIVE_LIST(V)   \
   1764   V(STXRB_w,  "'Ws, 'Wt")              \
   1765   V(STXRH_w,  "'Ws, 'Wt")              \
   1766   V(STXR_w,   "'Ws, 'Wt")              \
   1767   V(STXR_x,   "'Ws, 'Xt")              \
   1768   V(LDXR_x,   "'Xt")                   \
   1769   V(STXP_w,   "'Ws, 'Wt, 'Wt2")        \
   1770   V(STXP_x,   "'Ws, 'Xt, 'Xt2")        \
   1771   V(LDXP_w,   "'Wt, 'Wt2")             \
   1772   V(LDXP_x,   "'Xt, 'Xt2")             \
   1773   V(STLXRB_w, "'Ws, 'Wt")              \
   1774   V(STLXRH_w, "'Ws, 'Wt")              \
   1775   V(STLXR_w,  "'Ws, 'Wt")              \
   1776   V(STLXR_x,  "'Ws, 'Xt")              \
   1777   V(LDAXR_x,  "'Xt")                   \
   1778   V(STLXP_w,  "'Ws, 'Wt, 'Wt2")        \
   1779   V(STLXP_x,  "'Ws, 'Xt, 'Xt2")        \
   1780   V(LDAXP_w,  "'Wt, 'Wt2")             \
   1781   V(LDAXP_x,  "'Xt, 'Xt2")             \
   1782   V(STLR_x,   "'Xt")                   \
   1783   V(LDAR_x,   "'Xt")                   \
   1784   V(STLLR_x,  "'Xt")                   \
   1785   V(LDLAR_x,  "'Xt")                   \
   1786   V(CAS_w,    "'Ws, 'Wt")              \
   1787   V(CAS_x,    "'Xs, 'Xt")              \
   1788   V(CASA_w,   "'Ws, 'Wt")              \
   1789   V(CASA_x,   "'Xs, 'Xt")              \
   1790   V(CASL_w,   "'Ws, 'Wt")              \
   1791   V(CASL_x,   "'Xs, 'Xt")              \
   1792   V(CASAL_w,  "'Ws, 'Wt")              \
   1793   V(CASAL_x,  "'Xs, 'Xt")              \
   1794   V(CASB,     "'Ws, 'Wt")              \
   1795   V(CASAB,    "'Ws, 'Wt")              \
   1796   V(CASLB,    "'Ws, 'Wt")              \
   1797   V(CASALB,   "'Ws, 'Wt")              \
   1798   V(CASH,     "'Ws, 'Wt")              \
   1799   V(CASAH,    "'Ws, 'Wt")              \
   1800   V(CASLH,    "'Ws, 'Wt")              \
   1801   V(CASALH,   "'Ws, 'Wt")              \
   1802   V(CASP_w,   "'Ws, 'Ws+, 'Wt, 'Wt+")  \
   1803   V(CASP_x,   "'Xs, 'Xs+, 'Xt, 'Xt+")  \
   1804   V(CASPA_w,  "'Ws, 'Ws+, 'Wt, 'Wt+")  \
   1805   V(CASPA_x,  "'Xs, 'Xs+, 'Xt, 'Xt+")  \
   1806   V(CASPL_w,  "'Ws, 'Ws+, 'Wt, 'Wt+")  \
   1807   V(CASPL_x,  "'Xs, 'Xs+, 'Xt, 'Xt+")  \
   1808   V(CASPAL_w, "'Ws, 'Ws+, 'Wt, 'Wt+")  \
   1809   V(CASPAL_x, "'Xs, 'Xs+, 'Xt, 'Xt+")
   1810 // clang-format on
   1811 
   1812 
   1813 void Disassembler::VisitLoadStoreExclusive(const Instruction *instr) {
   1814   const char *form = "'Wt";
   1815   const char *suffix = ", ['Xns]";
   1816 
   1817   switch (instr->Mask(LoadStoreExclusiveMask)) {
   1818 #define LSX(A, B) \
   1819   case A:         \
   1820     form = B;     \
   1821     break;
   1822     LOAD_STORE_EXCLUSIVE_LIST(LSX)
   1823 #undef LSX
   1824   }
   1825 
   1826   switch (instr->Mask(LoadStoreExclusiveMask)) {
   1827     case CASP_w:
   1828     case CASP_x:
   1829     case CASPA_w:
   1830     case CASPA_x:
   1831     case CASPL_w:
   1832     case CASPL_x:
   1833     case CASPAL_w:
   1834     case CASPAL_x:
   1835       if ((instr->GetRs() % 2 == 1) || (instr->GetRt() % 2 == 1)) {
   1836         VisitUnallocated(instr);
   1837         return;
   1838       }
   1839       break;
   1840   }
   1841 
   1842   FormatWithDecodedMnemonic(instr, form, suffix);
   1843 }
   1844 
   1845 void Disassembler::VisitLoadStorePAC(const Instruction *instr) {
   1846   const char *form = "'Xt, ['Xns'ILA]";
   1847   const char *suffix = "";
   1848   switch (form_hash_) {
   1849     case "ldraa_64w_ldst_pac"_h:
   1850     case "ldrab_64w_ldst_pac"_h:
   1851       suffix = "!";
   1852       break;
   1853   }
   1854   FormatWithDecodedMnemonic(instr, form, suffix);
   1855 }
   1856 
   1857 void Disassembler::VisitAtomicMemory(const Instruction *instr) {
   1858   bool is_x = (instr->ExtractBits(31, 30) == 3);
   1859   const char *form = is_x ? "'Xs, 'Xt" : "'Ws, 'Wt";
   1860   const char *suffix = ", ['Xns]";
   1861 
   1862   std::string mnemonic = mnemonic_;
   1863 
   1864   switch (form_hash_) {
   1865     case "ldaprb_32l_memop"_h:
   1866     case "ldaprh_32l_memop"_h:
   1867     case "ldapr_32l_memop"_h:
   1868       form = "'Wt";
   1869       break;
   1870     case "ldapr_64l_memop"_h:
   1871       form = "'Xt";
   1872       break;
   1873     default:
   1874       // Zero register implies a store instruction.
   1875       if (instr->GetRt() == kZeroRegCode) {
   1876         mnemonic.replace(0, 2, "st");
   1877         form = is_x ? "'Xs" : "'Ws";
   1878       }
   1879   }
   1880   Format(instr, mnemonic.c_str(), form, suffix);
   1881 }
   1882 
   1883 
   1884 void Disassembler::VisitFPCompare(const Instruction *instr) {
   1885   const char *form = "'Fn, 'Fm";
   1886   switch (form_hash_) {
   1887     case "fcmpe_dz_floatcmp"_h:
   1888     case "fcmpe_hz_floatcmp"_h:
   1889     case "fcmpe_sz_floatcmp"_h:
   1890     case "fcmp_dz_floatcmp"_h:
   1891     case "fcmp_hz_floatcmp"_h:
   1892     case "fcmp_sz_floatcmp"_h:
   1893       form = "'Fn, #0.0";
   1894   }
   1895   FormatWithDecodedMnemonic(instr, form);
   1896 }
   1897 
   1898 
   1899 void Disassembler::VisitFPConditionalCompare(const Instruction *instr) {
   1900   FormatWithDecodedMnemonic(instr, "'Fn, 'Fm, 'INzcv, 'Cond");
   1901 }
   1902 
   1903 
   1904 void Disassembler::VisitFPConditionalSelect(const Instruction *instr) {
   1905   FormatWithDecodedMnemonic(instr, "'Fd, 'Fn, 'Fm, 'Cond");
   1906 }
   1907 
   1908 
   1909 void Disassembler::VisitFPDataProcessing1Source(const Instruction *instr) {
   1910   const char *form = "'Fd, 'Fn";
   1911   switch (form_hash_) {
   1912     case "fcvt_ds_floatdp1"_h:
   1913       form = "'Dd, 'Sn";
   1914       break;
   1915     case "fcvt_sd_floatdp1"_h:
   1916       form = "'Sd, 'Dn";
   1917       break;
   1918     case "fcvt_hs_floatdp1"_h:
   1919       form = "'Hd, 'Sn";
   1920       break;
   1921     case "fcvt_sh_floatdp1"_h:
   1922       form = "'Sd, 'Hn";
   1923       break;
   1924     case "fcvt_dh_floatdp1"_h:
   1925       form = "'Dd, 'Hn";
   1926       break;
   1927     case "fcvt_hd_floatdp1"_h:
   1928       form = "'Hd, 'Dn";
   1929       break;
   1930   }
   1931   FormatWithDecodedMnemonic(instr, form);
   1932 }
   1933 
   1934 
   1935 void Disassembler::VisitFPDataProcessing2Source(const Instruction *instr) {
   1936   FormatWithDecodedMnemonic(instr, "'Fd, 'Fn, 'Fm");
   1937 }
   1938 
   1939 
   1940 void Disassembler::VisitFPDataProcessing3Source(const Instruction *instr) {
   1941   FormatWithDecodedMnemonic(instr, "'Fd, 'Fn, 'Fm, 'Fa");
   1942 }
   1943 
   1944 
   1945 void Disassembler::VisitFPImmediate(const Instruction *instr) {
   1946   const char *form = "'Hd";
   1947   const char *suffix = ", 'IFP";
   1948   switch (form_hash_) {
   1949     case "fmov_s_floatimm"_h:
   1950       form = "'Sd";
   1951       break;
   1952     case "fmov_d_floatimm"_h:
   1953       form = "'Dd";
   1954       break;
   1955   }
   1956   FormatWithDecodedMnemonic(instr, form, suffix);
   1957 }
   1958 
   1959 
   1960 void Disassembler::VisitFPIntegerConvert(const Instruction *instr) {
   1961   const char *form = "'Rd, 'Fn";
   1962   switch (form_hash_) {
   1963     case "fmov_h32_float2int"_h:
   1964     case "fmov_h64_float2int"_h:
   1965     case "fmov_s32_float2int"_h:
   1966     case "fmov_d64_float2int"_h:
   1967     case "scvtf_d32_float2int"_h:
   1968     case "scvtf_d64_float2int"_h:
   1969     case "scvtf_h32_float2int"_h:
   1970     case "scvtf_h64_float2int"_h:
   1971     case "scvtf_s32_float2int"_h:
   1972     case "scvtf_s64_float2int"_h:
   1973     case "ucvtf_d32_float2int"_h:
   1974     case "ucvtf_d64_float2int"_h:
   1975     case "ucvtf_h32_float2int"_h:
   1976     case "ucvtf_h64_float2int"_h:
   1977     case "ucvtf_s32_float2int"_h:
   1978     case "ucvtf_s64_float2int"_h:
   1979       form = "'Fd, 'Rn";
   1980       break;
   1981     case "fmov_v64i_float2int"_h:
   1982       form = "'Vd.D[1], 'Rn";
   1983       break;
   1984     case "fmov_64vx_float2int"_h:
   1985       form = "'Rd, 'Vn.D[1]";
   1986       break;
   1987   }
   1988   FormatWithDecodedMnemonic(instr, form);
   1989 }
   1990 
   1991 
   1992 void Disassembler::VisitFPFixedPointConvert(const Instruction *instr) {
   1993   const char *form = "'Rd, 'Fn";
   1994   const char *suffix = ", 'IFPFBits";
   1995 
   1996   switch (form_hash_) {
   1997     case "scvtf_d32_float2fix"_h:
   1998     case "scvtf_d64_float2fix"_h:
   1999     case "scvtf_h32_float2fix"_h:
   2000     case "scvtf_h64_float2fix"_h:
   2001     case "scvtf_s32_float2fix"_h:
   2002     case "scvtf_s64_float2fix"_h:
   2003     case "ucvtf_d32_float2fix"_h:
   2004     case "ucvtf_d64_float2fix"_h:
   2005     case "ucvtf_h32_float2fix"_h:
   2006     case "ucvtf_h64_float2fix"_h:
   2007     case "ucvtf_s32_float2fix"_h:
   2008     case "ucvtf_s64_float2fix"_h:
   2009       form = "'Fd, 'Rn";
   2010       break;
   2011   }
   2012   FormatWithDecodedMnemonic(instr, form, suffix);
   2013 }
   2014 
   2015 void Disassembler::DisassembleNoArgs(const Instruction *instr) {
   2016   Format(instr, mnemonic_.c_str(), "");
   2017 }
   2018 
   2019 void Disassembler::VisitSystem(const Instruction *instr) {
   2020   const char *mnemonic = mnemonic_.c_str();
   2021   const char *form = "(System)";
   2022   const char *suffix = NULL;
   2023 
   2024   switch (form_hash_) {
   2025     case "clrex_bn_barriers"_h:
   2026       form = (instr->GetCRm() == 0xf) ? "" : "'IX";
   2027       break;
   2028     case "mrs_rs_systemmove"_h:
   2029       form = "'Xt, 'IY";
   2030       break;
   2031     case "msr_sr_systemmove"_h:
   2032       form = "'IY, 'Xt";
   2033       break;
   2034     case "bti_hb_hints"_h:
   2035       switch (instr->ExtractBits(7, 6)) {
   2036         case 0:
   2037           form = "";
   2038           break;
   2039         case 1:
   2040           form = "c";
   2041           break;
   2042         case 2:
   2043           form = "j";
   2044           break;
   2045         case 3:
   2046           form = "jc";
   2047           break;
   2048       }
   2049       break;
   2050     case "hint_hm_hints"_h:
   2051       form = "'IH";
   2052       break;
   2053     case Hash("dmb_bo_barriers"):
   2054       form = "'M";
   2055       break;
   2056     case Hash("dsb_bo_barriers"): {
   2057       int crm = instr->GetCRm();
   2058       if (crm == 0) {
   2059         mnemonic = "ssbb";
   2060         form = "";
   2061       } else if (crm == 4) {
   2062         mnemonic = "pssbb";
   2063         form = "";
   2064       } else {
   2065         form = "'M";
   2066       }
   2067       break;
   2068     }
   2069     case Hash("sys_cr_systeminstrs"): {
   2070       mnemonic = "dc";
   2071       suffix = ", 'Xt";
   2072 
   2073       const std::map<uint32_t, const char *> dcop = {
   2074           {IVAU, "ivau"},
   2075           {CVAC, "cvac"},
   2076           {CVAU, "cvau"},
   2077           {CVAP, "cvap"},
   2078           {CVADP, "cvadp"},
   2079           {CIVAC, "civac"},
   2080           {ZVA, "zva"},
   2081           {GVA, "gva"},
   2082           {GZVA, "gzva"},
   2083           {CGVAC, "cgvac"},
   2084           {CGDVAC, "cgdvac"},
   2085           {CGVAP, "cgvap"},
   2086           {CGDVAP, "cgdvap"},
   2087           {CIGVAC, "cigvac"},
   2088           {CIGDVAC, "cigdvac"},
   2089       };
   2090 
   2091       uint32_t sysop = instr->GetSysOp();
   2092       if (dcop.count(sysop)) {
   2093         if (sysop == IVAU) {
   2094           mnemonic = "ic";
   2095         }
   2096         form = dcop.at(sysop);
   2097       } else {
   2098         mnemonic = "sys";
   2099         form = "'G1, 'Kn, 'Km, 'G2";
   2100         if (instr->GetRt() == 31) {
   2101           suffix = NULL;
   2102         }
   2103         break;
   2104       }
   2105     }
   2106   }
   2107   Format(instr, mnemonic, form, suffix);
   2108 }
   2109 
   2110 
   2111 void Disassembler::VisitException(const Instruction *instr) {
   2112   const char *mnemonic = "unimplemented";
   2113   const char *form = "'IDebug";
   2114 
   2115   switch (instr->Mask(ExceptionMask)) {
   2116     case HLT:
   2117       mnemonic = "hlt";
   2118       break;
   2119     case BRK:
   2120       mnemonic = "brk";
   2121       break;
   2122     case SVC:
   2123       mnemonic = "svc";
   2124       break;
   2125     case HVC:
   2126       mnemonic = "hvc";
   2127       break;
   2128     case SMC:
   2129       mnemonic = "smc";
   2130       break;
   2131     case DCPS1:
   2132       mnemonic = "dcps1";
   2133       form = "{'IDebug}";
   2134       break;
   2135     case DCPS2:
   2136       mnemonic = "dcps2";
   2137       form = "{'IDebug}";
   2138       break;
   2139     case DCPS3:
   2140       mnemonic = "dcps3";
   2141       form = "{'IDebug}";
   2142       break;
   2143     default:
   2144       form = "(Exception)";
   2145   }
   2146   Format(instr, mnemonic, form);
   2147 }
   2148 
   2149 
   2150 void Disassembler::VisitCrypto2RegSHA(const Instruction *instr) {
   2151   VisitUnimplemented(instr);
   2152 }
   2153 
   2154 
   2155 void Disassembler::VisitCrypto3RegSHA(const Instruction *instr) {
   2156   VisitUnimplemented(instr);
   2157 }
   2158 
   2159 
   2160 void Disassembler::VisitCryptoAES(const Instruction *instr) {
   2161   VisitUnimplemented(instr);
   2162 }
   2163 
   2164 void Disassembler::DisassembleNEON2RegAddlp(const Instruction *instr) {
   2165   const char *mnemonic = mnemonic_.c_str();
   2166   const char *form = "'Vd.%s, 'Vn.%s";
   2167 
   2168   static const NEONFormatMap map_lp_ta =
   2169       {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
   2170   NEONFormatDecoder nfd(instr);
   2171   nfd.SetFormatMap(0, &map_lp_ta);
   2172   Format(instr, mnemonic, nfd.Substitute(form));
   2173 }
   2174 
   2175 void Disassembler::DisassembleNEON2RegCompare(const Instruction *instr) {
   2176   const char *mnemonic = mnemonic_.c_str();
   2177   const char *form = "'Vd.%s, 'Vn.%s, #0";
   2178   NEONFormatDecoder nfd(instr);
   2179   Format(instr, mnemonic, nfd.Substitute(form));
   2180 }
   2181 
   2182 void Disassembler::DisassembleNEON2RegFPCompare(const Instruction *instr) {
   2183   const char *mnemonic = mnemonic_.c_str();
   2184   const char *form = "'Vd.%s, 'Vn.%s, #0.0";
   2185   NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPFormatMap());
   2186   Format(instr, mnemonic, nfd.Substitute(form));
   2187 }
   2188 
   2189 void Disassembler::DisassembleNEON2RegFPConvert(const Instruction *instr) {
   2190   const char *mnemonic = mnemonic_.c_str();
   2191   const char *form = "'Vd.%s, 'Vn.%s";
   2192   static const NEONFormatMap map_cvt_ta = {{22}, {NF_4S, NF_2D}};
   2193 
   2194   static const NEONFormatMap map_cvt_tb = {{22, 30},
   2195                                            {NF_4H, NF_8H, NF_2S, NF_4S}};
   2196   NEONFormatDecoder nfd(instr, &map_cvt_tb, &map_cvt_ta);
   2197 
   2198   VectorFormat vform_dst = nfd.GetVectorFormat(0);
   2199   switch (form_hash_) {
   2200     case "fcvtl_asimdmisc_l"_h:
   2201       nfd.SetFormatMaps(&map_cvt_ta, &map_cvt_tb);
   2202       break;
   2203     case "fcvtxn_asimdmisc_n"_h:
   2204       if ((vform_dst != kFormat2S) && (vform_dst != kFormat4S)) {
   2205         mnemonic = NULL;
   2206       }
   2207       break;
   2208   }
   2209   Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
   2210 }
   2211 
   2212 void Disassembler::DisassembleNEON2RegFP(const Instruction *instr) {
   2213   const char *mnemonic = mnemonic_.c_str();
   2214   const char *form = "'Vd.%s, 'Vn.%s";
   2215   NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPFormatMap());
   2216   Format(instr, mnemonic, nfd.Substitute(form));
   2217 }
   2218 
   2219 void Disassembler::DisassembleNEON2RegLogical(const Instruction *instr) {
   2220   const char *mnemonic = mnemonic_.c_str();
   2221   const char *form = "'Vd.%s, 'Vn.%s";
   2222   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
   2223   if (form_hash_ == "not_asimdmisc_r"_h) {
   2224     mnemonic = "mvn";
   2225   }
   2226   Format(instr, mnemonic, nfd.Substitute(form));
   2227 }
   2228 
   2229 void Disassembler::DisassembleNEON2RegExtract(const Instruction *instr) {
   2230   const char *mnemonic = mnemonic_.c_str();
   2231   const char *form = "'Vd.%s, 'Vn.%s";
   2232   const char *suffix = NULL;
   2233   NEONFormatDecoder nfd(instr,
   2234                         NEONFormatDecoder::IntegerFormatMap(),
   2235                         NEONFormatDecoder::LongIntegerFormatMap());
   2236 
   2237   if (form_hash_ == "shll_asimdmisc_s"_h) {
   2238     nfd.SetFormatMaps(nfd.LongIntegerFormatMap(), nfd.IntegerFormatMap());
   2239     switch (instr->GetNEONSize()) {
   2240       case 0:
   2241         suffix = ", #8";
   2242         break;
   2243       case 1:
   2244         suffix = ", #16";
   2245         break;
   2246       case 2:
   2247         suffix = ", #32";
   2248         break;
   2249     }
   2250   }
   2251   Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form), suffix);
   2252 }
   2253 
   2254 void Disassembler::VisitNEON2RegMisc(const Instruction *instr) {
   2255   const char *mnemonic = mnemonic_.c_str();
   2256   const char *form = "'Vd.%s, 'Vn.%s";
   2257   NEONFormatDecoder nfd(instr);
   2258 
   2259   VectorFormat vform_dst = nfd.GetVectorFormat(0);
   2260   if (vform_dst != kFormatUndefined) {
   2261     uint32_t ls_dst = LaneSizeInBitsFromFormat(vform_dst);
   2262     switch (form_hash_) {
   2263       case "cnt_asimdmisc_r"_h:
   2264       case "rev16_asimdmisc_r"_h:
   2265         if (ls_dst != kBRegSize) {
   2266           mnemonic = NULL;
   2267         }
   2268         break;
   2269       case "rev32_asimdmisc_r"_h:
   2270         if ((ls_dst == kDRegSize) || (ls_dst == kSRegSize)) {
   2271           mnemonic = NULL;
   2272         }
   2273         break;
   2274       case "urecpe_asimdmisc_r"_h:
   2275       case "ursqrte_asimdmisc_r"_h:
   2276         // For urecpe and ursqrte, only S-sized elements are supported. The MSB
   2277         // of the size field is always set by the instruction (0b1x) so we need
   2278         // only check and discard D-sized elements here.
   2279         VIXL_ASSERT((ls_dst == kSRegSize) || (ls_dst == kDRegSize));
   2280         VIXL_FALLTHROUGH();
   2281       case "clz_asimdmisc_r"_h:
   2282       case "cls_asimdmisc_r"_h:
   2283       case "rev64_asimdmisc_r"_h:
   2284         if (ls_dst == kDRegSize) {
   2285           mnemonic = NULL;
   2286         }
   2287         break;
   2288     }
   2289   }
   2290 
   2291   Format(instr, mnemonic, nfd.Substitute(form));
   2292 }
   2293 
   2294 void Disassembler::VisitNEON2RegMiscFP16(const Instruction *instr) {
   2295   const char *mnemonic = mnemonic_.c_str();
   2296   const char *form = "'Vd.'?30:84h, 'Vn.'?30:84h";
   2297   const char *suffix = NULL;
   2298 
   2299   switch (form_hash_) {
   2300     case "fcmeq_asimdmiscfp16_fz"_h:
   2301     case "fcmge_asimdmiscfp16_fz"_h:
   2302     case "fcmgt_asimdmiscfp16_fz"_h:
   2303     case "fcmle_asimdmiscfp16_fz"_h:
   2304     case "fcmlt_asimdmiscfp16_fz"_h:
   2305       suffix = ", #0.0";
   2306   }
   2307   Format(instr, mnemonic, form, suffix);
   2308 }
   2309 
   2310 void Disassembler::DisassembleNEON3SameLogical(const Instruction *instr) {
   2311   const char *mnemonic = mnemonic_.c_str();
   2312   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
   2313   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
   2314 
   2315   switch (form_hash_) {
   2316     case "orr_asimdsame_only"_h:
   2317       if (instr->GetRm() == instr->GetRn()) {
   2318         mnemonic = "mov";
   2319         form = "'Vd.%s, 'Vn.%s";
   2320       }
   2321       break;
   2322     case "pmul_asimdsame_only"_h:
   2323       if (instr->GetNEONSize() != 0) {
   2324         mnemonic = NULL;
   2325       }
   2326   }
   2327   Format(instr, mnemonic, nfd.Substitute(form));
   2328 }
   2329 
   2330 void Disassembler::DisassembleNEON3SameFHM(const Instruction *instr) {
   2331   FormatWithDecodedMnemonic(instr, "'Vd.'?30:42s, 'Vn.'?30:42h, 'Vm.'?30:42h");
   2332 }
   2333 
   2334 void Disassembler::DisassembleNEON3SameNoD(const Instruction *instr) {
   2335   const char *mnemonic = mnemonic_.c_str();
   2336   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
   2337   static const NEONFormatMap map =
   2338       {{23, 22, 30},
   2339        {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_UNDEF}};
   2340   NEONFormatDecoder nfd(instr, &map);
   2341   Format(instr, mnemonic, nfd.Substitute(form));
   2342 }
   2343 
   2344 void Disassembler::VisitNEON3Same(const Instruction *instr) {
   2345   const char *mnemonic = mnemonic_.c_str();
   2346   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
   2347   NEONFormatDecoder nfd(instr);
   2348 
   2349   if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
   2350     nfd.SetFormatMaps(nfd.FPFormatMap());
   2351   }
   2352 
   2353   VectorFormat vform_dst = nfd.GetVectorFormat(0);
   2354   if (vform_dst != kFormatUndefined) {
   2355     uint32_t ls_dst = LaneSizeInBitsFromFormat(vform_dst);
   2356     switch (form_hash_) {
   2357       case "sqdmulh_asimdsame_only"_h:
   2358       case "sqrdmulh_asimdsame_only"_h:
   2359         if ((ls_dst == kBRegSize) || (ls_dst == kDRegSize)) {
   2360           mnemonic = NULL;
   2361         }
   2362         break;
   2363     }
   2364   }
   2365   Format(instr, mnemonic, nfd.Substitute(form));
   2366 }
   2367 
   2368 void Disassembler::VisitNEON3SameFP16(const Instruction *instr) {
   2369   const char *mnemonic = mnemonic_.c_str();
   2370   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
   2371   NEONFormatDecoder nfd(instr);
   2372   nfd.SetFormatMaps(nfd.FP16FormatMap());
   2373   Format(instr, mnemonic, nfd.Substitute(form));
   2374 }
   2375 
   2376 void Disassembler::VisitNEON3SameExtra(const Instruction *instr) {
   2377   static const NEONFormatMap map_dot =
   2378       {{23, 22, 30}, {NF_UNDEF, NF_UNDEF, NF_UNDEF, NF_UNDEF, NF_2S, NF_4S}};
   2379   static const NEONFormatMap map_fc =
   2380       {{23, 22, 30},
   2381        {NF_UNDEF, NF_UNDEF, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_2D}};
   2382   static const NEONFormatMap map_rdm =
   2383       {{23, 22, 30}, {NF_UNDEF, NF_UNDEF, NF_4H, NF_8H, NF_2S, NF_4S}};
   2384 
   2385   const char *mnemonic = mnemonic_.c_str();
   2386   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
   2387   const char *suffix = NULL;
   2388 
   2389   NEONFormatDecoder nfd(instr, &map_fc);
   2390 
   2391   switch (form_hash_) {
   2392     case "fcmla_asimdsame2_c"_h:
   2393       suffix = ", #'u1211*90";
   2394       break;
   2395     case "fcadd_asimdsame2_c"_h:
   2396       // Bit 10 is always set, so this gives 90 * 1 or 3.
   2397       suffix = ", #'u1212:1010*90";
   2398       break;
   2399     case "sdot_asimdsame2_d"_h:
   2400     case "udot_asimdsame2_d"_h:
   2401     case "usdot_asimdsame2_d"_h:
   2402       nfd.SetFormatMaps(nfd.LogicalFormatMap());
   2403       nfd.SetFormatMap(0, &map_dot);
   2404       break;
   2405     default:
   2406       nfd.SetFormatMaps(&map_rdm);
   2407       break;
   2408   }
   2409 
   2410   Format(instr, mnemonic, nfd.Substitute(form), suffix);
   2411 }
   2412 
   2413 
   2414 void Disassembler::VisitNEON3Different(const Instruction *instr) {
   2415   const char *mnemonic = mnemonic_.c_str();
   2416   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
   2417 
   2418   NEONFormatDecoder nfd(instr);
   2419   nfd.SetFormatMap(0, nfd.LongIntegerFormatMap());
   2420 
   2421   switch (form_hash_) {
   2422     case "saddw_asimddiff_w"_h:
   2423     case "ssubw_asimddiff_w"_h:
   2424     case "uaddw_asimddiff_w"_h:
   2425     case "usubw_asimddiff_w"_h:
   2426       nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
   2427       break;
   2428     case "addhn_asimddiff_n"_h:
   2429     case "raddhn_asimddiff_n"_h:
   2430     case "rsubhn_asimddiff_n"_h:
   2431     case "subhn_asimddiff_n"_h:
   2432       nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
   2433       nfd.SetFormatMap(0, nfd.IntegerFormatMap());
   2434       break;
   2435     case "sqdmlal_asimddiff_l"_h:
   2436     case "sqdmlsl_asimddiff_l"_h:
   2437     case "sqdmull_asimddiff_l"_h:
   2438       if (nfd.GetVectorFormat(0) == kFormat8H) {
   2439         mnemonic = NULL;
   2440       }
   2441       break;
   2442   }
   2443   Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
   2444 }
   2445 
   2446 void Disassembler::DisassembleNEONPolynomialMul(const Instruction *instr) {
   2447   const char *mnemonic = instr->ExtractBit(30) ? "pmull2" : "pmull";
   2448   const char *form = NULL;
   2449   int size = instr->ExtractBits(23, 22);
   2450   if (size == 0) {
   2451     // Bits 30:27 of the instruction are x001, where x is the Q bit. Map
   2452     // this to "8" and "16" by adding 7.
   2453     form = "'Vd.8h, 'Vn.'u3127+7b, 'Vm.'u3127+7b";
   2454   } else if (size == 3) {
   2455     form = "'Vd.1q, 'Vn.'?30:21d, 'Vm.'?30:21d";
   2456   } else {
   2457     mnemonic = NULL;
   2458   }
   2459   Format(instr, mnemonic, form);
   2460 }
   2461 
   2462 void Disassembler::DisassembleNEONFPAcrossLanes(const Instruction *instr) {
   2463   const char *mnemonic = mnemonic_.c_str();
   2464   const char *form = "'Sd, 'Vn.4s";
   2465   if ((instr->GetNEONQ() == 0) || (instr->ExtractBit(22) == 1)) {
   2466     mnemonic = NULL;
   2467   }
   2468   Format(instr, mnemonic, form);
   2469 }
   2470 
   2471 void Disassembler::DisassembleNEONFP16AcrossLanes(const Instruction *instr) {
   2472   FormatWithDecodedMnemonic(instr, "'Hd, 'Vn.'?30:84h");
   2473 }
   2474 
   2475 void Disassembler::VisitNEONAcrossLanes(const Instruction *instr) {
   2476   const char *mnemonic = mnemonic_.c_str();
   2477   const char *form = "%sd, 'Vn.%s";
   2478 
   2479   NEONFormatDecoder nfd(instr,
   2480                         NEONFormatDecoder::ScalarFormatMap(),
   2481                         NEONFormatDecoder::IntegerFormatMap());
   2482 
   2483   switch (form_hash_) {
   2484     case "saddlv_asimdall_only"_h:
   2485     case "uaddlv_asimdall_only"_h:
   2486       nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
   2487   }
   2488 
   2489   VectorFormat vform_src = nfd.GetVectorFormat(1);
   2490   if ((vform_src == kFormat2S) || (vform_src == kFormat2D)) {
   2491     mnemonic = NULL;
   2492   }
   2493 
   2494   Format(instr,
   2495          mnemonic,
   2496          nfd.Substitute(form,
   2497                         NEONFormatDecoder::kPlaceholder,
   2498                         NEONFormatDecoder::kFormat));
   2499 }
   2500 
   2501 void Disassembler::VisitNEONByIndexedElement(const Instruction *instr) {
   2502   const char *form = "'Vd.%s, 'Vn.%s, 'Vf.%s['IVByElemIndex]";
   2503   static const NEONFormatMap map_v =
   2504       {{23, 22, 30},
   2505        {NF_UNDEF, NF_UNDEF, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_UNDEF}};
   2506   static const NEONFormatMap map_s = {{23, 22},
   2507                                       {NF_UNDEF, NF_H, NF_S, NF_UNDEF}};
   2508   NEONFormatDecoder nfd(instr, &map_v, &map_v, &map_s);
   2509   Format(instr, mnemonic_.c_str(), nfd.Substitute(form));
   2510 }
   2511 
   2512 void Disassembler::DisassembleNEONMulByElementLong(const Instruction *instr) {
   2513   const char *form = "'Vd.%s, 'Vn.%s, 'Vf.%s['IVByElemIndex]";
   2514   // TODO: Disallow undefined element types for this instruction.
   2515   static const NEONFormatMap map_ta = {{23, 22}, {NF_UNDEF, NF_4S, NF_2D}};
   2516   NEONFormatDecoder nfd(instr,
   2517                         &map_ta,
   2518                         NEONFormatDecoder::IntegerFormatMap(),
   2519                         NEONFormatDecoder::ScalarFormatMap());
   2520   Format(instr, nfd.Mnemonic(mnemonic_.c_str()), nfd.Substitute(form));
   2521 }
   2522 
   2523 void Disassembler::DisassembleNEONDotProdByElement(const Instruction *instr) {
   2524   const char *form = instr->ExtractBit(30) ? "'Vd.4s, 'Vn.16" : "'Vd.2s, 'Vn.8";
   2525   const char *suffix = "b, 'Vm.4b['u1111:2121]";
   2526   Format(instr, mnemonic_.c_str(), form, suffix);
   2527 }
   2528 
   2529 void Disassembler::DisassembleNEONFPMulByElement(const Instruction *instr) {
   2530   const char *form = "'Vd.%s, 'Vn.%s, 'Vf.%s['IVByElemIndex]";
   2531   NEONFormatDecoder nfd(instr,
   2532                         NEONFormatDecoder::FPFormatMap(),
   2533                         NEONFormatDecoder::FPFormatMap(),
   2534                         NEONFormatDecoder::FPScalarFormatMap());
   2535   Format(instr, mnemonic_.c_str(), nfd.Substitute(form));
   2536 }
   2537 
   2538 void Disassembler::DisassembleNEONHalfFPMulByElement(const Instruction *instr) {
   2539   FormatWithDecodedMnemonic(instr,
   2540                             "'Vd.'?30:84h, 'Vn.'?30:84h, "
   2541                             "'Ve.h['IVByElemIndex]");
   2542 }
   2543 
   2544 void Disassembler::DisassembleNEONFPMulByElementLong(const Instruction *instr) {
   2545   FormatWithDecodedMnemonic(instr,
   2546                             "'Vd.'?30:42s, 'Vn.'?30:42h, "
   2547                             "'Ve.h['IVByElemIndexFHM]");
   2548 }
   2549 
   2550 void Disassembler::DisassembleNEONComplexMulByElement(
   2551     const Instruction *instr) {
   2552   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s['IVByElemIndexRot], #'u1413*90";
   2553   // TODO: Disallow undefined element types for this instruction.
   2554   static const NEONFormatMap map_cn =
   2555       {{23, 22, 30},
   2556        {NF_UNDEF, NF_UNDEF, NF_4H, NF_8H, NF_UNDEF, NF_4S, NF_UNDEF, NF_UNDEF}};
   2557   NEONFormatDecoder nfd(instr,
   2558                         &map_cn,
   2559                         &map_cn,
   2560                         NEONFormatDecoder::ScalarFormatMap());
   2561   Format(instr, mnemonic_.c_str(), nfd.Substitute(form));
   2562 }
   2563 
   2564 void Disassembler::VisitNEONCopy(const Instruction *instr) {
   2565   const char *mnemonic = mnemonic_.c_str();
   2566   const char *form = "(NEONCopy)";
   2567 
   2568   NEONFormatDecoder nfd(instr,
   2569                         NEONFormatDecoder::TriangularFormatMap(),
   2570                         NEONFormatDecoder::TriangularScalarFormatMap());
   2571 
   2572   switch (form_hash_) {
   2573     case "ins_asimdins_iv_v"_h:
   2574       mnemonic = "mov";
   2575       nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
   2576       form = "'Vd.%s['IVInsIndex1], 'Vn.%s['IVInsIndex2]";
   2577       break;
   2578     case "ins_asimdins_ir_r"_h:
   2579       mnemonic = "mov";
   2580       nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
   2581       if (nfd.GetVectorFormat() == kFormatD) {
   2582         form = "'Vd.%s['IVInsIndex1], 'Xn";
   2583       } else {
   2584         form = "'Vd.%s['IVInsIndex1], 'Wn";
   2585       }
   2586       break;
   2587     case "umov_asimdins_w_w"_h:
   2588     case "umov_asimdins_x_x"_h:
   2589       if (instr->Mask(NEON_Q) || ((instr->GetImmNEON5() & 7) == 4)) {
   2590         mnemonic = "mov";
   2591       }
   2592       nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
   2593       if (nfd.GetVectorFormat() == kFormatD) {
   2594         form = "'Xd, 'Vn.%s['IVInsIndex1]";
   2595       } else {
   2596         form = "'Wd, 'Vn.%s['IVInsIndex1]";
   2597       }
   2598       break;
   2599     case "smov_asimdins_w_w"_h:
   2600     case "smov_asimdins_x_x"_h: {
   2601       nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
   2602       VectorFormat vform = nfd.GetVectorFormat();
   2603       if ((vform == kFormatD) ||
   2604           ((vform == kFormatS) && (instr->ExtractBit(30) == 0))) {
   2605         mnemonic = NULL;
   2606       }
   2607       form = "'R30d, 'Vn.%s['IVInsIndex1]";
   2608       break;
   2609     }
   2610     case "dup_asimdins_dv_v"_h:
   2611       form = "'Vd.%s, 'Vn.%s['IVInsIndex1]";
   2612       break;
   2613     case "dup_asimdins_dr_r"_h:
   2614       if (nfd.GetVectorFormat() == kFormat2D) {
   2615         form = "'Vd.%s, 'Xn";
   2616       } else {
   2617         form = "'Vd.%s, 'Wn";
   2618       }
   2619   }
   2620   Format(instr, mnemonic, nfd.Substitute(form));
   2621 }
   2622 
   2623 
   2624 void Disassembler::VisitNEONExtract(const Instruction *instr) {
   2625   const char *mnemonic = mnemonic_.c_str();
   2626   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVExtract";
   2627   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
   2628   if ((instr->GetImmNEONExt() > 7) && (instr->GetNEONQ() == 0)) {
   2629     mnemonic = NULL;
   2630   }
   2631   Format(instr, mnemonic, nfd.Substitute(form));
   2632 }
   2633 
   2634 
   2635 void Disassembler::VisitNEONLoadStoreMultiStruct(const Instruction *instr) {
   2636   const char *mnemonic = NULL;
   2637   const char *form = NULL;
   2638   const char *form_1v = "{'Vt.%1$s}, ['Xns]";
   2639   const char *form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns]";
   2640   const char *form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns]";
   2641   const char *form_4v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]";
   2642   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
   2643 
   2644   switch (instr->Mask(NEONLoadStoreMultiStructMask)) {
   2645     case NEON_LD1_1v:
   2646       mnemonic = "ld1";
   2647       form = form_1v;
   2648       break;
   2649     case NEON_LD1_2v:
   2650       mnemonic = "ld1";
   2651       form = form_2v;
   2652       break;
   2653     case NEON_LD1_3v:
   2654       mnemonic = "ld1";
   2655       form = form_3v;
   2656       break;
   2657     case NEON_LD1_4v:
   2658       mnemonic = "ld1";
   2659       form = form_4v;
   2660       break;
   2661     case NEON_LD2:
   2662       mnemonic = "ld2";
   2663       form = form_2v;
   2664       break;
   2665     case NEON_LD3:
   2666       mnemonic = "ld3";
   2667       form = form_3v;
   2668       break;
   2669     case NEON_LD4:
   2670       mnemonic = "ld4";
   2671       form = form_4v;
   2672       break;
   2673     case NEON_ST1_1v:
   2674       mnemonic = "st1";
   2675       form = form_1v;
   2676       break;
   2677     case NEON_ST1_2v:
   2678       mnemonic = "st1";
   2679       form = form_2v;
   2680       break;
   2681     case NEON_ST1_3v:
   2682       mnemonic = "st1";
   2683       form = form_3v;
   2684       break;
   2685     case NEON_ST1_4v:
   2686       mnemonic = "st1";
   2687       form = form_4v;
   2688       break;
   2689     case NEON_ST2:
   2690       mnemonic = "st2";
   2691       form = form_2v;
   2692       break;
   2693     case NEON_ST3:
   2694       mnemonic = "st3";
   2695       form = form_3v;
   2696       break;
   2697     case NEON_ST4:
   2698       mnemonic = "st4";
   2699       form = form_4v;
   2700       break;
   2701     default:
   2702       break;
   2703   }
   2704 
   2705   // Work out unallocated encodings.
   2706   bool allocated = (mnemonic != NULL);
   2707   switch (instr->Mask(NEONLoadStoreMultiStructMask)) {
   2708     case NEON_LD2:
   2709     case NEON_LD3:
   2710     case NEON_LD4:
   2711     case NEON_ST2:
   2712     case NEON_ST3:
   2713     case NEON_ST4:
   2714       // LD[2-4] and ST[2-4] cannot use .1d format.
   2715       allocated = (instr->GetNEONQ() != 0) || (instr->GetNEONLSSize() != 3);
   2716       break;
   2717     default:
   2718       break;
   2719   }
   2720   if (allocated) {
   2721     VIXL_ASSERT(mnemonic != NULL);
   2722     VIXL_ASSERT(form != NULL);
   2723   } else {
   2724     mnemonic = "unallocated";
   2725     form = "(NEONLoadStoreMultiStruct)";
   2726   }
   2727 
   2728   Format(instr, mnemonic, nfd.Substitute(form));
   2729 }
   2730 
   2731 
   2732 void Disassembler::VisitNEONLoadStoreMultiStructPostIndex(
   2733     const Instruction *instr) {
   2734   const char *mnemonic = NULL;
   2735   const char *form = NULL;
   2736   const char *form_1v = "{'Vt.%1$s}, ['Xns], 'Xmr1";
   2737   const char *form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns], 'Xmr2";
   2738   const char *form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns], 'Xmr3";
   2739   const char *form_4v =
   2740       "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmr4";
   2741   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
   2742 
   2743   switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
   2744     case NEON_LD1_1v_post:
   2745       mnemonic = "ld1";
   2746       form = form_1v;
   2747       break;
   2748     case NEON_LD1_2v_post:
   2749       mnemonic = "ld1";
   2750       form = form_2v;
   2751       break;
   2752     case NEON_LD1_3v_post:
   2753       mnemonic = "ld1";
   2754       form = form_3v;
   2755       break;
   2756     case NEON_LD1_4v_post:
   2757       mnemonic = "ld1";
   2758       form = form_4v;
   2759       break;
   2760     case NEON_LD2_post:
   2761       mnemonic = "ld2";
   2762       form = form_2v;
   2763       break;
   2764     case NEON_LD3_post:
   2765       mnemonic = "ld3";
   2766       form = form_3v;
   2767       break;
   2768     case NEON_LD4_post:
   2769       mnemonic = "ld4";
   2770       form = form_4v;
   2771       break;
   2772     case NEON_ST1_1v_post:
   2773       mnemonic = "st1";
   2774       form = form_1v;
   2775       break;
   2776     case NEON_ST1_2v_post:
   2777       mnemonic = "st1";
   2778       form = form_2v;
   2779       break;
   2780     case NEON_ST1_3v_post:
   2781       mnemonic = "st1";
   2782       form = form_3v;
   2783       break;
   2784     case NEON_ST1_4v_post:
   2785       mnemonic = "st1";
   2786       form = form_4v;
   2787       break;
   2788     case NEON_ST2_post:
   2789       mnemonic = "st2";
   2790       form = form_2v;
   2791       break;
   2792     case NEON_ST3_post:
   2793       mnemonic = "st3";
   2794       form = form_3v;
   2795       break;
   2796     case NEON_ST4_post:
   2797       mnemonic = "st4";
   2798       form = form_4v;
   2799       break;
   2800     default:
   2801       break;
   2802   }
   2803 
   2804   // Work out unallocated encodings.
   2805   bool allocated = (mnemonic != NULL);
   2806   switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
   2807     case NEON_LD2_post:
   2808     case NEON_LD3_post:
   2809     case NEON_LD4_post:
   2810     case NEON_ST2_post:
   2811     case NEON_ST3_post:
   2812     case NEON_ST4_post:
   2813       // LD[2-4] and ST[2-4] cannot use .1d format.
   2814       allocated = (instr->GetNEONQ() != 0) || (instr->GetNEONLSSize() != 3);
   2815       break;
   2816     default:
   2817       break;
   2818   }
   2819   if (allocated) {
   2820     VIXL_ASSERT(mnemonic != NULL);
   2821     VIXL_ASSERT(form != NULL);
   2822   } else {
   2823     mnemonic = "unallocated";
   2824     form = "(NEONLoadStoreMultiStructPostIndex)";
   2825   }
   2826 
   2827   Format(instr, mnemonic, nfd.Substitute(form));
   2828 }
   2829 
   2830 
   2831 void Disassembler::VisitNEONLoadStoreSingleStruct(const Instruction *instr) {
   2832   const char *mnemonic = NULL;
   2833   const char *form = NULL;
   2834 
   2835   const char *form_1b = "{'Vt.b}['IVLSLane0], ['Xns]";
   2836   const char *form_1h = "{'Vt.h}['IVLSLane1], ['Xns]";
   2837   const char *form_1s = "{'Vt.s}['IVLSLane2], ['Xns]";
   2838   const char *form_1d = "{'Vt.d}['IVLSLane3], ['Xns]";
   2839   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
   2840 
   2841   switch (instr->Mask(NEONLoadStoreSingleStructMask)) {
   2842     case NEON_LD1_b:
   2843       mnemonic = "ld1";
   2844       form = form_1b;
   2845       break;
   2846     case NEON_LD1_h:
   2847       mnemonic = "ld1";
   2848       form = form_1h;
   2849       break;
   2850     case NEON_LD1_s:
   2851       mnemonic = "ld1";
   2852       VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
   2853       form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
   2854       break;
   2855     case NEON_ST1_b:
   2856       mnemonic = "st1";
   2857       form = form_1b;
   2858       break;
   2859     case NEON_ST1_h:
   2860       mnemonic = "st1";
   2861       form = form_1h;
   2862       break;
   2863     case NEON_ST1_s:
   2864       mnemonic = "st1";
   2865       VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
   2866       form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
   2867       break;
   2868     case NEON_LD1R:
   2869       mnemonic = "ld1r";
   2870       form = "{'Vt.%s}, ['Xns]";
   2871       break;
   2872     case NEON_LD2_b:
   2873     case NEON_ST2_b:
   2874       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
   2875       form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns]";
   2876       break;
   2877     case NEON_LD2_h:
   2878     case NEON_ST2_h:
   2879       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
   2880       form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns]";
   2881       break;
   2882     case NEON_LD2_s:
   2883     case NEON_ST2_s:
   2884       VIXL_STATIC_ASSERT((NEON_ST2_s | (1 << NEONLSSize_offset)) == NEON_ST2_d);
   2885       VIXL_STATIC_ASSERT((NEON_LD2_s | (1 << NEONLSSize_offset)) == NEON_LD2_d);
   2886       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
   2887       if ((instr->GetNEONLSSize() & 1) == 0) {
   2888         form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns]";
   2889       } else {
   2890         form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns]";
   2891       }
   2892       break;
   2893     case NEON_LD2R:
   2894       mnemonic = "ld2r";
   2895       form = "{'Vt.%s, 'Vt2.%s}, ['Xns]";
   2896       break;
   2897     case NEON_LD3_b:
   2898     case NEON_ST3_b:
   2899       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
   2900       form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns]";
   2901       break;
   2902     case NEON_LD3_h:
   2903     case NEON_ST3_h:
   2904       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
   2905       form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns]";
   2906       break;
   2907     case NEON_LD3_s:
   2908     case NEON_ST3_s:
   2909       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
   2910       if ((instr->GetNEONLSSize() & 1) == 0) {
   2911         form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns]";
   2912       } else {
   2913         form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns]";
   2914       }
   2915       break;
   2916     case NEON_LD3R:
   2917       mnemonic = "ld3r";
   2918       form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns]";
   2919       break;
   2920     case NEON_LD4_b:
   2921     case NEON_ST4_b:
   2922       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
   2923       form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns]";
   2924       break;
   2925     case NEON_LD4_h:
   2926     case NEON_ST4_h:
   2927       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
   2928       form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns]";
   2929       break;
   2930     case NEON_LD4_s:
   2931     case NEON_ST4_s:
   2932       VIXL_STATIC_ASSERT((NEON_LD4_s | (1 << NEONLSSize_offset)) == NEON_LD4_d);
   2933       VIXL_STATIC_ASSERT((NEON_ST4_s | (1 << NEONLSSize_offset)) == NEON_ST4_d);
   2934       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
   2935       if ((instr->GetNEONLSSize() & 1) == 0) {
   2936         form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns]";
   2937       } else {
   2938         form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns]";
   2939       }
   2940       break;
   2941     case NEON_LD4R:
   2942       mnemonic = "ld4r";
   2943       form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]";
   2944       break;
   2945     default:
   2946       break;
   2947   }
   2948 
   2949   // Work out unallocated encodings.
   2950   bool allocated = (mnemonic != NULL);
   2951   switch (instr->Mask(NEONLoadStoreSingleStructMask)) {
   2952     case NEON_LD1_h:
   2953     case NEON_LD2_h:
   2954     case NEON_LD3_h:
   2955     case NEON_LD4_h:
   2956     case NEON_ST1_h:
   2957     case NEON_ST2_h:
   2958     case NEON_ST3_h:
   2959     case NEON_ST4_h:
   2960       VIXL_ASSERT(allocated);
   2961       allocated = ((instr->GetNEONLSSize() & 1) == 0);
   2962       break;
   2963     case NEON_LD1_s:
   2964     case NEON_LD2_s:
   2965     case NEON_LD3_s:
   2966     case NEON_LD4_s:
   2967     case NEON_ST1_s:
   2968     case NEON_ST2_s:
   2969     case NEON_ST3_s:
   2970     case NEON_ST4_s:
   2971       VIXL_ASSERT(allocated);
   2972       allocated = (instr->GetNEONLSSize() <= 1) &&
   2973                   ((instr->GetNEONLSSize() == 0) || (instr->GetNEONS() == 0));
   2974       break;
   2975     case NEON_LD1R:
   2976     case NEON_LD2R:
   2977     case NEON_LD3R:
   2978     case NEON_LD4R:
   2979       VIXL_ASSERT(allocated);
   2980       allocated = (instr->GetNEONS() == 0);
   2981       break;
   2982     default:
   2983       break;
   2984   }
   2985   if (allocated) {
   2986     VIXL_ASSERT(mnemonic != NULL);
   2987     VIXL_ASSERT(form != NULL);
   2988   } else {
   2989     mnemonic = "unallocated";
   2990     form = "(NEONLoadStoreSingleStruct)";
   2991   }
   2992 
   2993   Format(instr, mnemonic, nfd.Substitute(form));
   2994 }
   2995 
   2996 
   2997 void Disassembler::VisitNEONLoadStoreSingleStructPostIndex(
   2998     const Instruction *instr) {
   2999   const char *mnemonic = NULL;
   3000   const char *form = NULL;
   3001 
   3002   const char *form_1b = "{'Vt.b}['IVLSLane0], ['Xns], 'Xmb1";
   3003   const char *form_1h = "{'Vt.h}['IVLSLane1], ['Xns], 'Xmb2";
   3004   const char *form_1s = "{'Vt.s}['IVLSLane2], ['Xns], 'Xmb4";
   3005   const char *form_1d = "{'Vt.d}['IVLSLane3], ['Xns], 'Xmb8";
   3006   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
   3007 
   3008   switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
   3009     case NEON_LD1_b_post:
   3010       mnemonic = "ld1";
   3011       form = form_1b;
   3012       break;
   3013     case NEON_LD1_h_post:
   3014       mnemonic = "ld1";
   3015       form = form_1h;
   3016       break;
   3017     case NEON_LD1_s_post:
   3018       mnemonic = "ld1";
   3019       VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
   3020       form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
   3021       break;
   3022     case NEON_ST1_b_post:
   3023       mnemonic = "st1";
   3024       form = form_1b;
   3025       break;
   3026     case NEON_ST1_h_post:
   3027       mnemonic = "st1";
   3028       form = form_1h;
   3029       break;
   3030     case NEON_ST1_s_post:
   3031       mnemonic = "st1";
   3032       VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
   3033       form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
   3034       break;
   3035     case NEON_LD1R_post:
   3036       mnemonic = "ld1r";
   3037       form = "{'Vt.%s}, ['Xns], 'Xmz1";
   3038       break;
   3039     case NEON_LD2_b_post:
   3040     case NEON_ST2_b_post:
   3041       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
   3042       form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns], 'Xmb2";
   3043       break;
   3044     case NEON_ST2_h_post:
   3045     case NEON_LD2_h_post:
   3046       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
   3047       form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns], 'Xmb4";
   3048       break;
   3049     case NEON_LD2_s_post:
   3050     case NEON_ST2_s_post:
   3051       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
   3052       if ((instr->GetNEONLSSize() & 1) == 0)
   3053         form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns], 'Xmb8";
   3054       else
   3055         form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns], 'Xmb16";
   3056       break;
   3057     case NEON_LD2R_post:
   3058       mnemonic = "ld2r";
   3059       form = "{'Vt.%s, 'Vt2.%s}, ['Xns], 'Xmz2";
   3060       break;
   3061     case NEON_LD3_b_post:
   3062     case NEON_ST3_b_post:
   3063       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
   3064       form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns], 'Xmb3";
   3065       break;
   3066     case NEON_LD3_h_post:
   3067     case NEON_ST3_h_post:
   3068       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
   3069       form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns], 'Xmb6";
   3070       break;
   3071     case NEON_LD3_s_post:
   3072     case NEON_ST3_s_post:
   3073       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
   3074       if ((instr->GetNEONLSSize() & 1) == 0)
   3075         form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns], 'Xmb12";
   3076       else
   3077         form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns], 'Xmb24";
   3078       break;
   3079     case NEON_LD3R_post:
   3080       mnemonic = "ld3r";
   3081       form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns], 'Xmz3";
   3082       break;
   3083     case NEON_LD4_b_post:
   3084     case NEON_ST4_b_post:
   3085       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
   3086       form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns], 'Xmb4";
   3087       break;
   3088     case NEON_LD4_h_post:
   3089     case NEON_ST4_h_post:
   3090       mnemonic = (instr->GetLdStXLoad()) == 1 ? "ld4" : "st4";
   3091       form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns], 'Xmb8";
   3092       break;
   3093     case NEON_LD4_s_post:
   3094     case NEON_ST4_s_post:
   3095       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
   3096       if ((instr->GetNEONLSSize() & 1) == 0)
   3097         form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns], 'Xmb16";
   3098       else
   3099         form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns], 'Xmb32";
   3100       break;
   3101     case NEON_LD4R_post:
   3102       mnemonic = "ld4r";
   3103       form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmz4";
   3104       break;
   3105     default:
   3106       break;
   3107   }
   3108 
   3109   // Work out unallocated encodings.
   3110   bool allocated = (mnemonic != NULL);
   3111   switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
   3112     case NEON_LD1_h_post:
   3113     case NEON_LD2_h_post:
   3114     case NEON_LD3_h_post:
   3115     case NEON_LD4_h_post:
   3116     case NEON_ST1_h_post:
   3117     case NEON_ST2_h_post:
   3118     case NEON_ST3_h_post:
   3119     case NEON_ST4_h_post:
   3120       VIXL_ASSERT(allocated);
   3121       allocated = ((instr->GetNEONLSSize() & 1) == 0);
   3122       break;
   3123     case NEON_LD1_s_post:
   3124     case NEON_LD2_s_post:
   3125     case NEON_LD3_s_post:
   3126     case NEON_LD4_s_post:
   3127     case NEON_ST1_s_post:
   3128     case NEON_ST2_s_post:
   3129     case NEON_ST3_s_post:
   3130     case NEON_ST4_s_post:
   3131       VIXL_ASSERT(allocated);
   3132       allocated = (instr->GetNEONLSSize() <= 1) &&
   3133                   ((instr->GetNEONLSSize() == 0) || (instr->GetNEONS() == 0));
   3134       break;
   3135     case NEON_LD1R_post:
   3136     case NEON_LD2R_post:
   3137     case NEON_LD3R_post:
   3138     case NEON_LD4R_post:
   3139       VIXL_ASSERT(allocated);
   3140       allocated = (instr->GetNEONS() == 0);
   3141       break;
   3142     default:
   3143       break;
   3144   }
   3145   if (allocated) {
   3146     VIXL_ASSERT(mnemonic != NULL);
   3147     VIXL_ASSERT(form != NULL);
   3148   } else {
   3149     mnemonic = "unallocated";
   3150     form = "(NEONLoadStoreSingleStructPostIndex)";
   3151   }
   3152 
   3153   Format(instr, mnemonic, nfd.Substitute(form));
   3154 }
   3155 
   3156 
   3157 void Disassembler::VisitNEONModifiedImmediate(const Instruction *instr) {
   3158   const char *mnemonic = mnemonic_.c_str();
   3159   const char *form = "'Vt.%s, 'IVMIImm8, lsl 'IVMIShiftAmt1";
   3160 
   3161   static const NEONFormatMap map_h = {{30}, {NF_4H, NF_8H}};
   3162   static const NEONFormatMap map_s = {{30}, {NF_2S, NF_4S}};
   3163   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
   3164 
   3165   switch (form_hash_) {
   3166     case "movi_asimdimm_n_b"_h:
   3167       form = "'Vt.%s, 'IVMIImm8";
   3168       break;
   3169     case "bic_asimdimm_l_hl"_h:
   3170     case "movi_asimdimm_l_hl"_h:
   3171     case "mvni_asimdimm_l_hl"_h:
   3172     case "orr_asimdimm_l_hl"_h:
   3173       nfd.SetFormatMap(0, &map_h);
   3174       break;
   3175     case "movi_asimdimm_m_sm"_h:
   3176     case "mvni_asimdimm_m_sm"_h:
   3177       form = "'Vt.%s, 'IVMIImm8, msl 'IVMIShiftAmt2";
   3178       VIXL_FALLTHROUGH();
   3179     case "bic_asimdimm_l_sl"_h:
   3180     case "movi_asimdimm_l_sl"_h:
   3181     case "mvni_asimdimm_l_sl"_h:
   3182     case "orr_asimdimm_l_sl"_h:
   3183       nfd.SetFormatMap(0, &map_s);
   3184       break;
   3185     case "movi_asimdimm_d_ds"_h:
   3186       form = "'Dd, 'IVMIImm";
   3187       break;
   3188     case "movi_asimdimm_d2_d"_h:
   3189       form = "'Vt.2d, 'IVMIImm";
   3190       break;
   3191     case "fmov_asimdimm_h_h"_h:
   3192       form = "'Vt.%s, 'IFPNeon";
   3193       nfd.SetFormatMap(0, &map_h);
   3194       break;
   3195     case "fmov_asimdimm_s_s"_h:
   3196       form = "'Vt.%s, 'IFPNeon";
   3197       nfd.SetFormatMap(0, &map_s);
   3198       break;
   3199     case "fmov_asimdimm_d2_d"_h:
   3200       form = "'Vt.2d, 'IFPNeon";
   3201       break;
   3202   }
   3203 
   3204   Format(instr, mnemonic, nfd.Substitute(form));
   3205 }
   3206 
   3207 void Disassembler::DisassembleNEONScalar2RegMiscOnlyD(
   3208     const Instruction *instr) {
   3209   const char *mnemonic = mnemonic_.c_str();
   3210   const char *form = "'Dd, 'Dn";
   3211   const char *suffix = ", #0";
   3212   if (instr->GetNEONSize() != 3) {
   3213     mnemonic = NULL;
   3214   }
   3215   switch (form_hash_) {
   3216     case "abs_asisdmisc_r"_h:
   3217     case "neg_asisdmisc_r"_h:
   3218       suffix = NULL;
   3219   }
   3220   Format(instr, mnemonic, form, suffix);
   3221 }
   3222 
   3223 void Disassembler::DisassembleNEONFPScalar2RegMisc(const Instruction *instr) {
   3224   const char *mnemonic = mnemonic_.c_str();
   3225   const char *form = "%sd, %sn";
   3226   const char *suffix = NULL;
   3227   NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap());
   3228   switch (form_hash_) {
   3229     case "fcmeq_asisdmisc_fz"_h:
   3230     case "fcmge_asisdmisc_fz"_h:
   3231     case "fcmgt_asisdmisc_fz"_h:
   3232     case "fcmle_asisdmisc_fz"_h:
   3233     case "fcmlt_asisdmisc_fz"_h:
   3234       suffix = ", #0.0";
   3235       break;
   3236     case "fcvtxn_asisdmisc_n"_h:
   3237       if (nfd.GetVectorFormat(0) == kFormatS) {  // Source format.
   3238         mnemonic = NULL;
   3239       }
   3240       form = "'Sd, 'Dn";
   3241   }
   3242   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form), suffix);
   3243 }
   3244 
   3245 void Disassembler::VisitNEONScalar2RegMisc(const Instruction *instr) {
   3246   const char *mnemonic = mnemonic_.c_str();
   3247   const char *form = "%sd, %sn";
   3248   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
   3249   switch (form_hash_) {
   3250     case "sqxtn_asisdmisc_n"_h:
   3251     case "sqxtun_asisdmisc_n"_h:
   3252     case "uqxtn_asisdmisc_n"_h:
   3253       nfd.SetFormatMap(1, nfd.LongScalarFormatMap());
   3254   }
   3255   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
   3256 }
   3257 
   3258 void Disassembler::VisitNEONScalar2RegMiscFP16(const Instruction *instr) {
   3259   const char *mnemonic = mnemonic_.c_str();
   3260   const char *form = "'Hd, 'Hn";
   3261   const char *suffix = NULL;
   3262 
   3263   switch (form_hash_) {
   3264     case "fcmeq_asisdmiscfp16_fz"_h:
   3265     case "fcmge_asisdmiscfp16_fz"_h:
   3266     case "fcmgt_asisdmiscfp16_fz"_h:
   3267     case "fcmle_asisdmiscfp16_fz"_h:
   3268     case "fcmlt_asisdmiscfp16_fz"_h:
   3269       suffix = ", #0.0";
   3270   }
   3271   Format(instr, mnemonic, form, suffix);
   3272 }
   3273 
   3274 
   3275 void Disassembler::VisitNEONScalar3Diff(const Instruction *instr) {
   3276   const char *mnemonic = mnemonic_.c_str();
   3277   const char *form = "%sd, %sn, %sm";
   3278   NEONFormatDecoder nfd(instr,
   3279                         NEONFormatDecoder::LongScalarFormatMap(),
   3280                         NEONFormatDecoder::ScalarFormatMap());
   3281   if (nfd.GetVectorFormat(0) == kFormatH) {
   3282     mnemonic = NULL;
   3283   }
   3284   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
   3285 }
   3286 
   3287 void Disassembler::DisassembleNEONFPScalar3Same(const Instruction *instr) {
   3288   const char *mnemonic = mnemonic_.c_str();
   3289   const char *form = "%sd, %sn, %sm";
   3290   NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap());
   3291   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
   3292 }
   3293 
   3294 void Disassembler::DisassembleNEONScalar3SameOnlyD(const Instruction *instr) {
   3295   const char *mnemonic = mnemonic_.c_str();
   3296   const char *form = "'Dd, 'Dn, 'Dm";
   3297   if (instr->GetNEONSize() != 3) {
   3298     mnemonic = NULL;
   3299   }
   3300   Format(instr, mnemonic, form);
   3301 }
   3302 
   3303 void Disassembler::VisitNEONScalar3Same(const Instruction *instr) {
   3304   const char *mnemonic = mnemonic_.c_str();
   3305   const char *form = "%sd, %sn, %sm";
   3306   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
   3307   VectorFormat vform = nfd.GetVectorFormat(0);
   3308   switch (form_hash_) {
   3309     case "srshl_asisdsame_only"_h:
   3310     case "urshl_asisdsame_only"_h:
   3311     case "sshl_asisdsame_only"_h:
   3312     case "ushl_asisdsame_only"_h:
   3313       if (vform != kFormatD) {
   3314         mnemonic = NULL;
   3315       }
   3316       break;
   3317     case "sqdmulh_asisdsame_only"_h:
   3318     case "sqrdmulh_asisdsame_only"_h:
   3319       if ((vform == kFormatB) || (vform == kFormatD)) {
   3320         mnemonic = NULL;
   3321       }
   3322   }
   3323   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
   3324 }
   3325 
   3326 void Disassembler::VisitNEONScalar3SameFP16(const Instruction *instr) {
   3327   FormatWithDecodedMnemonic(instr, "'Hd, 'Hn, 'Hm");
   3328 }
   3329 
   3330 void Disassembler::VisitNEONScalar3SameExtra(const Instruction *instr) {
   3331   USE(instr);
   3332   // Nothing to do - handled by VisitNEONScalar3Same.
   3333   VIXL_UNREACHABLE();
   3334 }
   3335 
   3336 void Disassembler::DisassembleNEONScalarSatMulLongIndex(
   3337     const Instruction *instr) {
   3338   const char *mnemonic = mnemonic_.c_str();
   3339   const char *form = "%sd, %sn, 'Vf.%s['IVByElemIndex]";
   3340   NEONFormatDecoder nfd(instr,
   3341                         NEONFormatDecoder::LongScalarFormatMap(),
   3342                         NEONFormatDecoder::ScalarFormatMap());
   3343   if (nfd.GetVectorFormat(0) == kFormatH) {
   3344     mnemonic = NULL;
   3345   }
   3346   Format(instr,
   3347          mnemonic,
   3348          nfd.Substitute(form, nfd.kPlaceholder, nfd.kPlaceholder, nfd.kFormat));
   3349 }
   3350 
   3351 void Disassembler::DisassembleNEONFPScalarMulIndex(const Instruction *instr) {
   3352   const char *mnemonic = mnemonic_.c_str();
   3353   const char *form = "%sd, %sn, 'Vf.%s['IVByElemIndex]";
   3354   static const NEONFormatMap map = {{23, 22}, {NF_H, NF_UNDEF, NF_S, NF_D}};
   3355   NEONFormatDecoder nfd(instr, &map);
   3356   Format(instr,
   3357          mnemonic,
   3358          nfd.Substitute(form, nfd.kPlaceholder, nfd.kPlaceholder, nfd.kFormat));
   3359 }
   3360 
   3361 void Disassembler::VisitNEONScalarByIndexedElement(const Instruction *instr) {
   3362   const char *mnemonic = mnemonic_.c_str();
   3363   const char *form = "%sd, %sn, 'Vf.%s['IVByElemIndex]";
   3364   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
   3365   VectorFormat vform_dst = nfd.GetVectorFormat(0);
   3366   if ((vform_dst == kFormatB) || (vform_dst == kFormatD)) {
   3367     mnemonic = NULL;
   3368   }
   3369   Format(instr,
   3370          mnemonic,
   3371          nfd.Substitute(form, nfd.kPlaceholder, nfd.kPlaceholder, nfd.kFormat));
   3372 }
   3373 
   3374 
   3375 void Disassembler::VisitNEONScalarCopy(const Instruction *instr) {
   3376   const char *mnemonic = "unimplemented";
   3377   const char *form = "(NEONScalarCopy)";
   3378 
   3379   NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
   3380 
   3381   if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
   3382     mnemonic = "mov";
   3383     form = "%sd, 'Vn.%s['IVInsIndex1]";
   3384   }
   3385 
   3386   Format(instr, mnemonic, nfd.Substitute(form, nfd.kPlaceholder, nfd.kFormat));
   3387 }
   3388 
   3389 
   3390 void Disassembler::VisitNEONScalarPairwise(const Instruction *instr) {
   3391   const char *mnemonic = mnemonic_.c_str();
   3392   if (form_hash_ == "addp_asisdpair_only"_h) {
   3393     // All pairwise operations except ADDP use bit U to differentiate FP16
   3394     // from FP32/FP64 variations.
   3395     if (instr->GetNEONSize() != 3) {
   3396       mnemonic = NULL;
   3397     }
   3398     Format(instr, mnemonic, "'Dd, 'Vn.2d");
   3399   } else {
   3400     const char *form = "%sd, 'Vn.2%s";
   3401     NEONFormatDecoder nfd(instr,
   3402                           NEONFormatDecoder::FPScalarPairwiseFormatMap());
   3403 
   3404     Format(instr,
   3405            mnemonic,
   3406            nfd.Substitute(form,
   3407                           NEONFormatDecoder::kPlaceholder,
   3408                           NEONFormatDecoder::kFormat));
   3409   }
   3410 }
   3411 
   3412 void Disassembler::DisassembleNEONScalarShiftImmOnlyD(
   3413     const Instruction *instr) {
   3414   const char *mnemonic = mnemonic_.c_str();
   3415   const char *form = "'Dd, 'Dn, ";
   3416   const char *suffix = "'IsR";
   3417 
   3418   if (instr->ExtractBit(22) == 0) {
   3419     // Only D registers are supported.
   3420     mnemonic = NULL;
   3421   }
   3422 
   3423   switch (form_hash_) {
   3424     case "shl_asisdshf_r"_h:
   3425     case "sli_asisdshf_r"_h:
   3426       suffix = "'IsL";
   3427   }
   3428 
   3429   Format(instr, mnemonic, form, suffix);
   3430 }
   3431 
   3432 void Disassembler::DisassembleNEONScalarShiftRightNarrowImm(
   3433     const Instruction *instr) {
   3434   const char *mnemonic = mnemonic_.c_str();
   3435   const char *form = "%sd, %sn, 'IsR";
   3436   static const NEONFormatMap map_dst =
   3437       {{22, 21, 20, 19}, {NF_UNDEF, NF_B, NF_H, NF_H, NF_S, NF_S, NF_S, NF_S}};
   3438   static const NEONFormatMap map_src =
   3439       {{22, 21, 20, 19}, {NF_UNDEF, NF_H, NF_S, NF_S, NF_D, NF_D, NF_D, NF_D}};
   3440   NEONFormatDecoder nfd(instr, &map_dst, &map_src);
   3441   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
   3442 }
   3443 
   3444 void Disassembler::VisitNEONScalarShiftImmediate(const Instruction *instr) {
   3445   const char *mnemonic = mnemonic_.c_str();
   3446   const char *form = "%sd, %sn, ";
   3447   const char *suffix = "'IsR";
   3448 
   3449   // clang-format off
   3450   static const NEONFormatMap map = {{22, 21, 20, 19},
   3451                                     {NF_UNDEF, NF_B, NF_H, NF_H,
   3452                                      NF_S,     NF_S, NF_S, NF_S,
   3453                                      NF_D,     NF_D, NF_D, NF_D,
   3454                                      NF_D,     NF_D, NF_D, NF_D}};
   3455   // clang-format on
   3456   NEONFormatDecoder nfd(instr, &map);
   3457   switch (form_hash_) {
   3458     case "sqshlu_asisdshf_r"_h:
   3459     case "sqshl_asisdshf_r"_h:
   3460     case "uqshl_asisdshf_r"_h:
   3461       suffix = "'IsL";
   3462       break;
   3463     default:
   3464       if (nfd.GetVectorFormat(0) == kFormatB) {
   3465         mnemonic = NULL;
   3466       }
   3467   }
   3468   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form), suffix);
   3469 }
   3470 
   3471 void Disassembler::DisassembleNEONShiftLeftLongImm(const Instruction *instr) {
   3472   const char *mnemonic = mnemonic_.c_str();
   3473   const char *form = "'Vd.%s, 'Vn.%s";
   3474   const char *suffix = ", 'IsL";
   3475 
   3476   NEONFormatDecoder nfd(instr,
   3477                         NEONFormatDecoder::ShiftLongNarrowImmFormatMap(),
   3478                         NEONFormatDecoder::ShiftImmFormatMap());
   3479 
   3480   if (instr->GetImmNEONImmb() == 0 &&
   3481       CountSetBits(instr->GetImmNEONImmh(), 32) == 1) {  // xtl variant.
   3482     VIXL_ASSERT((form_hash_ == "sshll_asimdshf_l"_h) ||
   3483                 (form_hash_ == "ushll_asimdshf_l"_h));
   3484     mnemonic = (form_hash_ == "sshll_asimdshf_l"_h) ? "sxtl" : "uxtl";
   3485     suffix = NULL;
   3486   }
   3487   Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form), suffix);
   3488 }
   3489 
   3490 void Disassembler::DisassembleNEONShiftRightImm(const Instruction *instr) {
   3491   const char *mnemonic = mnemonic_.c_str();
   3492   const char *form = "'Vd.%s, 'Vn.%s, 'IsR";
   3493   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ShiftImmFormatMap());
   3494 
   3495   VectorFormat vform_dst = nfd.GetVectorFormat(0);
   3496   if (vform_dst != kFormatUndefined) {
   3497     uint32_t ls_dst = LaneSizeInBitsFromFormat(vform_dst);
   3498     switch (form_hash_) {
   3499       case "scvtf_asimdshf_c"_h:
   3500       case "ucvtf_asimdshf_c"_h:
   3501       case "fcvtzs_asimdshf_c"_h:
   3502       case "fcvtzu_asimdshf_c"_h:
   3503         if (ls_dst == kBRegSize) {
   3504           mnemonic = NULL;
   3505         }
   3506         break;
   3507     }
   3508   }
   3509   Format(instr, mnemonic, nfd.Substitute(form));
   3510 }
   3511 
   3512 void Disassembler::DisassembleNEONShiftRightNarrowImm(
   3513     const Instruction *instr) {
   3514   const char *mnemonic = mnemonic_.c_str();
   3515   const char *form = "'Vd.%s, 'Vn.%s, 'IsR";
   3516 
   3517   NEONFormatDecoder nfd(instr,
   3518                         NEONFormatDecoder::ShiftImmFormatMap(),
   3519                         NEONFormatDecoder::ShiftLongNarrowImmFormatMap());
   3520   Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
   3521 }
   3522 
   3523 void Disassembler::VisitNEONShiftImmediate(const Instruction *instr) {
   3524   const char *mnemonic = mnemonic_.c_str();
   3525   const char *form = "'Vd.%s, 'Vn.%s, 'IsL";
   3526   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ShiftImmFormatMap());
   3527   Format(instr, mnemonic, nfd.Substitute(form));
   3528 }
   3529 
   3530 
   3531 void Disassembler::VisitNEONTable(const Instruction *instr) {
   3532   const char *mnemonic = mnemonic_.c_str();
   3533   const char form_1v[] = "'Vd.%%s, {'Vn.16b}, 'Vm.%%s";
   3534   const char form_2v[] = "'Vd.%%s, {'Vn.16b, v%d.16b}, 'Vm.%%s";
   3535   const char form_3v[] = "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b}, 'Vm.%%s";
   3536   const char form_4v[] =
   3537       "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b, v%d.16b}, 'Vm.%%s";
   3538   const char *form = form_1v;
   3539 
   3540   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
   3541 
   3542   switch (form_hash_) {
   3543     case "tbl_asimdtbl_l2_2"_h:
   3544     case "tbx_asimdtbl_l2_2"_h:
   3545       form = form_2v;
   3546       break;
   3547     case "tbl_asimdtbl_l3_3"_h:
   3548     case "tbx_asimdtbl_l3_3"_h:
   3549       form = form_3v;
   3550       break;
   3551     case "tbl_asimdtbl_l4_4"_h:
   3552     case "tbx_asimdtbl_l4_4"_h:
   3553       form = form_4v;
   3554       break;
   3555   }
   3556   VIXL_ASSERT(form != NULL);
   3557 
   3558   char re_form[sizeof(form_4v) + 6];  // 3 * two-digit substitutions => 6
   3559   int reg_num = instr->GetRn();
   3560   snprintf(re_form,
   3561            sizeof(re_form),
   3562            form,
   3563            (reg_num + 1) % kNumberOfVRegisters,
   3564            (reg_num + 2) % kNumberOfVRegisters,
   3565            (reg_num + 3) % kNumberOfVRegisters);
   3566 
   3567   Format(instr, mnemonic, nfd.Substitute(re_form));
   3568 }
   3569 
   3570 
   3571 void Disassembler::VisitNEONPerm(const Instruction *instr) {
   3572   NEONFormatDecoder nfd(instr);
   3573   FormatWithDecodedMnemonic(instr, nfd.Substitute("'Vd.%s, 'Vn.%s, 'Vm.%s"));
   3574 }
   3575 
   3576 void Disassembler::Disassemble_Vd4S_Vn16B_Vm16B(const Instruction *instr) {
   3577   FormatWithDecodedMnemonic(instr, "'Vd.4s, 'Vn.16b, 'Vm.16b");
   3578 }
   3579 
   3580 void Disassembler::
   3581     VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
   3582         const Instruction *instr) {
   3583   FormatWithDecodedMnemonic(instr,
   3584                             "{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw #1]");
   3585 }
   3586 
   3587 void Disassembler::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
   3588     const Instruction *instr) {
   3589   FormatWithDecodedMnemonic(instr,
   3590                             "{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw #2]");
   3591 }
   3592 
   3593 void Disassembler::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
   3594     const Instruction *instr) {
   3595   FormatWithDecodedMnemonic(instr,
   3596                             "{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw]");
   3597 }
   3598 
   3599 void Disassembler::VisitSVE32BitGatherLoad_VectorPlusImm(
   3600     const Instruction *instr) {
   3601   const char *form = "{'Zt.s}, 'Pgl/z, ['Zn.s]";
   3602   const char *form_imm = "{'Zt.s}, 'Pgl/z, ['Zn.s, #'u2016]";
   3603   const char *form_imm_h = "{'Zt.s}, 'Pgl/z, ['Zn.s, #'u2016*2]";
   3604   const char *form_imm_w = "{'Zt.s}, 'Pgl/z, ['Zn.s, #'u2016*4]";
   3605 
   3606   const char *mnemonic = mnemonic_.c_str();
   3607   switch (form_hash_) {
   3608     case "ld1h_z_p_ai_s"_h:
   3609     case "ld1sh_z_p_ai_s"_h:
   3610     case "ldff1h_z_p_ai_s"_h:
   3611     case "ldff1sh_z_p_ai_s"_h:
   3612       form_imm = form_imm_h;
   3613       break;
   3614     case "ld1w_z_p_ai_s"_h:
   3615     case "ldff1w_z_p_ai_s"_h:
   3616       form_imm = form_imm_w;
   3617       break;
   3618   }
   3619   if (instr->ExtractBits(20, 16) != 0) form = form_imm;
   3620 
   3621   Format(instr, mnemonic, form);
   3622 }
   3623 
   3624 void Disassembler::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
   3625     const Instruction *instr) {
   3626   const char *mnemonic = "unimplemented";
   3627   const char *form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.s, '?22:suxtw";
   3628   const char *suffix = NULL;
   3629 
   3630   switch (
   3631       instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
   3632     case PRFB_i_p_bz_s_x32_scaled:
   3633       mnemonic = "prfb";
   3634       suffix = "]";
   3635       break;
   3636     case PRFD_i_p_bz_s_x32_scaled:
   3637       mnemonic = "prfd";
   3638       suffix = " #3]";
   3639       break;
   3640     case PRFH_i_p_bz_s_x32_scaled:
   3641       mnemonic = "prfh";
   3642       suffix = " #1]";
   3643       break;
   3644     case PRFW_i_p_bz_s_x32_scaled:
   3645       mnemonic = "prfw";
   3646       suffix = " #2]";
   3647       break;
   3648     default:
   3649       form = "(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets)";
   3650       break;
   3651   }
   3652   Format(instr, mnemonic, form, suffix);
   3653 }
   3654 
   3655 void Disassembler::VisitSVE32BitGatherPrefetch_VectorPlusImm(
   3656     const Instruction *instr) {
   3657   const char *form = (instr->ExtractBits(20, 16) != 0)
   3658                          ? "'prefSVEOp, 'Pgl, ['Zn.s, #'u2016]"
   3659                          : "'prefSVEOp, 'Pgl, ['Zn.s]";
   3660   FormatWithDecodedMnemonic(instr, form);
   3661 }
   3662 
   3663 void Disassembler::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
   3664     const Instruction *instr) {
   3665   FormatWithDecodedMnemonic(instr,
   3666                             "{'Zt.s}, 'Pgl, ['Xns, 'Zm.s, '?14:suxtw #'u2423]");
   3667 }
   3668 
   3669 void Disassembler::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
   3670     const Instruction *instr) {
   3671   FormatWithDecodedMnemonic(instr, "{'Zt.s}, 'Pgl, ['Xns, 'Zm.s, '?14:suxtw]");
   3672 }
   3673 
   3674 void Disassembler::VisitSVE32BitScatterStore_VectorPlusImm(
   3675     const Instruction *instr) {
   3676   const char *mnemonic = "unimplemented";
   3677   const char *form = "{'Zt.s}, 'Pgl, ['Zn.s";
   3678   const char *suffix = NULL;
   3679 
   3680   bool is_zero = instr->ExtractBits(20, 16) == 0;
   3681 
   3682   switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
   3683     case ST1B_z_p_ai_s:
   3684       mnemonic = "st1b";
   3685       suffix = is_zero ? "]" : ", #'u2016]";
   3686       break;
   3687     case ST1H_z_p_ai_s:
   3688       mnemonic = "st1h";
   3689       suffix = is_zero ? "]" : ", #'u2016*2]";
   3690       break;
   3691     case ST1W_z_p_ai_s:
   3692       mnemonic = "st1w";
   3693       suffix = is_zero ? "]" : ", #'u2016*4]";
   3694       break;
   3695     default:
   3696       form = "(SVE32BitScatterStore_VectorPlusImm)";
   3697       break;
   3698   }
   3699   Format(instr, mnemonic, form, suffix);
   3700 }
   3701 
   3702 void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
   3703     const Instruction *instr) {
   3704   FormatWithDecodedMnemonic(instr,
   3705                             "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, '?22:suxtw "
   3706                             "#'u2423]");
   3707 }
   3708 
   3709 void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
   3710     const Instruction *instr) {
   3711   FormatWithDecodedMnemonic(instr,
   3712                             "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, lsl #'u2423]");
   3713 }
   3714 
   3715 void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
   3716     const Instruction *instr) {
   3717   FormatWithDecodedMnemonic(instr, "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d]");
   3718 }
   3719 
   3720 void Disassembler::
   3721     VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
   3722         const Instruction *instr) {
   3723   FormatWithDecodedMnemonic(instr,
   3724                             "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, '?22:suxtw]");
   3725 }
   3726 
   3727 void Disassembler::VisitSVE64BitGatherLoad_VectorPlusImm(
   3728     const Instruction *instr) {
   3729   const char *form = "{'Zt.d}, 'Pgl/z, ['Zn.d]";
   3730   const char *form_imm[4] = {"{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016]",
   3731                              "{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016*2]",
   3732                              "{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016*4]",
   3733                              "{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016*8]"};
   3734 
   3735   if (instr->ExtractBits(20, 16) != 0) {
   3736     unsigned msz = instr->ExtractBits(24, 23);
   3737     bool sign_extend = instr->ExtractBit(14) == 0;
   3738     if ((msz == kDRegSizeInBytesLog2) && sign_extend) {
   3739       form = "(SVE64BitGatherLoad_VectorPlusImm)";
   3740     } else {
   3741       VIXL_ASSERT(msz < ArrayLength(form_imm));
   3742       form = form_imm[msz];
   3743     }
   3744   }
   3745 
   3746   FormatWithDecodedMnemonic(instr, form);
   3747 }
   3748 
   3749 void Disassembler::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
   3750     const Instruction *instr) {
   3751   const char *form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d";
   3752   const char *suffix = "]";
   3753 
   3754   switch (form_hash_) {
   3755     case "prfh_i_p_bz_d_64_scaled"_h:
   3756       suffix = ", lsl #1]";
   3757       break;
   3758     case "prfs_i_p_bz_d_64_scaled"_h:
   3759       suffix = ", lsl #2]";
   3760       break;
   3761     case "prfd_i_p_bz_d_64_scaled"_h:
   3762       suffix = ", lsl #3]";
   3763       break;
   3764   }
   3765   FormatWithDecodedMnemonic(instr, form, suffix);
   3766 }
   3767 
   3768 void Disassembler::
   3769     VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
   3770         const Instruction *instr) {
   3771   const char *form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, '?22:suxtw ";
   3772   const char *suffix = "]";
   3773 
   3774   switch (form_hash_) {
   3775     case "prfh_i_p_bz_d_x32_scaled"_h:
   3776       suffix = "#1]";
   3777       break;
   3778     case "prfs_i_p_bz_d_x32_scaled"_h:
   3779       suffix = "#2]";
   3780       break;
   3781     case "prfd_i_p_bz_d_x32_scaled"_h:
   3782       suffix = "#3]";
   3783       break;
   3784   }
   3785   FormatWithDecodedMnemonic(instr, form, suffix);
   3786 }
   3787 
   3788 void Disassembler::VisitSVE64BitGatherPrefetch_VectorPlusImm(
   3789     const Instruction *instr) {
   3790   const char *form = (instr->ExtractBits(20, 16) != 0)
   3791                          ? "'prefSVEOp, 'Pgl, ['Zn.d, #'u2016]"
   3792                          : "'prefSVEOp, 'Pgl, ['Zn.d]";
   3793 
   3794   FormatWithDecodedMnemonic(instr, form);
   3795 }
   3796 
   3797 void Disassembler::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
   3798     const Instruction *instr) {
   3799   FormatWithDecodedMnemonic(instr, "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, lsl #'u2423]");
   3800 }
   3801 
   3802 void Disassembler::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
   3803     const Instruction *instr) {
   3804   FormatWithDecodedMnemonic(instr, "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d]");
   3805 }
   3806 
   3807 void Disassembler::
   3808     VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
   3809         const Instruction *instr) {
   3810   FormatWithDecodedMnemonic(instr,
   3811                             "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, '?14:suxtw #'u2423]");
   3812 }
   3813 
   3814 void Disassembler::
   3815     VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
   3816         const Instruction *instr) {
   3817   FormatWithDecodedMnemonic(instr, "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, '?14:suxtw]");
   3818 }
   3819 
   3820 void Disassembler::VisitSVE64BitScatterStore_VectorPlusImm(
   3821     const Instruction *instr) {
   3822   const char *form = "{'Zt.d}, 'Pgl, ['Zn.d";
   3823   const char *suffix = "]";
   3824 
   3825   if (instr->ExtractBits(20, 16) != 0) {
   3826     switch (form_hash_) {
   3827       case "st1b_z_p_ai_d"_h:
   3828         suffix = ", #'u2016]";
   3829         break;
   3830       case "st1h_z_p_ai_d"_h:
   3831         suffix = ", #'u2016*2]";
   3832         break;
   3833       case "st1w_z_p_ai_d"_h:
   3834         suffix = ", #'u2016*4]";
   3835         break;
   3836       case "st1d_z_p_ai_d"_h:
   3837         suffix = ", #'u2016*8]";
   3838         break;
   3839     }
   3840   }
   3841   FormatWithDecodedMnemonic(instr, form, suffix);
   3842 }
   3843 
   3844 void Disassembler::VisitSVEBitwiseLogicalWithImm_Unpredicated(
   3845     const Instruction *instr) {
   3846   if (instr->GetSVEImmLogical() == 0) {
   3847     // The immediate encoded in the instruction is not in the expected format.
   3848     Format(instr, "unallocated", "(SVEBitwiseImm)");
   3849   } else {
   3850     FormatWithDecodedMnemonic(instr, "'Zd.'tl, 'Zd.'tl, 'ITriSvel");
   3851   }
   3852 }
   3853 
   3854 void Disassembler::VisitSVEBitwiseLogical_Predicated(const Instruction *instr) {
   3855   FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t");
   3856 }
   3857 
   3858 void Disassembler::VisitSVEBitwiseShiftByImm_Predicated(
   3859     const Instruction *instr) {
   3860   const char *mnemonic = mnemonic_.c_str();
   3861   const char *form = "'Zd.'tszp, 'Pgl/m, 'Zd.'tszp, ";
   3862   const char *suffix = NULL;
   3863   unsigned tsize = (instr->ExtractBits(23, 22) << 2) | instr->ExtractBits(9, 8);
   3864 
   3865   if (tsize == 0) {
   3866     mnemonic = "unimplemented";
   3867     form = "(SVEBitwiseShiftByImm_Predicated)";
   3868   } else {
   3869     switch (form_hash_) {
   3870       case "lsl_z_p_zi"_h:
   3871       case "sqshl_z_p_zi"_h:
   3872       case "sqshlu_z_p_zi"_h:
   3873       case "uqshl_z_p_zi"_h:
   3874         suffix = "'ITriSvep";
   3875         break;
   3876       case "asrd_z_p_zi"_h:
   3877       case "asr_z_p_zi"_h:
   3878       case "lsr_z_p_zi"_h:
   3879       case "srshr_z_p_zi"_h:
   3880       case "urshr_z_p_zi"_h:
   3881         suffix = "'ITriSveq";
   3882         break;
   3883       default:
   3884         mnemonic = "unimplemented";
   3885         form = "(SVEBitwiseShiftByImm_Predicated)";
   3886         break;
   3887     }
   3888   }
   3889   Format(instr, mnemonic, form, suffix);
   3890 }
   3891 
   3892 void Disassembler::VisitSVEBitwiseShiftByVector_Predicated(
   3893     const Instruction *instr) {
   3894   FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t");
   3895 }
   3896 
   3897 void Disassembler::VisitSVEBitwiseShiftByWideElements_Predicated(
   3898     const Instruction *instr) {
   3899   if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
   3900     Format(instr, "unallocated", "(SVEBitwiseShiftByWideElements_Predicated)");
   3901   } else {
   3902     FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.d");
   3903   }
   3904 }
   3905 
   3906 static bool SVEMoveMaskPreferred(uint64_t value, int lane_bytes_log2) {
   3907   VIXL_ASSERT(IsUintN(8 << lane_bytes_log2, value));
   3908 
   3909   // Duplicate lane-sized value across double word.
   3910   switch (lane_bytes_log2) {
   3911     case 0:
   3912       value *= 0x0101010101010101;
   3913       break;
   3914     case 1:
   3915       value *= 0x0001000100010001;
   3916       break;
   3917     case 2:
   3918       value *= 0x0000000100000001;
   3919       break;
   3920     case 3:  // Nothing to do
   3921       break;
   3922     default:
   3923       VIXL_UNREACHABLE();
   3924   }
   3925 
   3926   if ((value & 0xff) == 0) {
   3927     // Check for 16-bit patterns. Set least-significant 16 bits, to make tests
   3928     // easier; we already checked least-significant byte is zero above.
   3929     uint64_t generic_value = value | 0xffff;
   3930 
   3931     // Check 0x00000000_0000pq00 or 0xffffffff_ffffpq00.
   3932     if ((generic_value == 0xffff) || (generic_value == UINT64_MAX)) {
   3933       return false;
   3934     }
   3935 
   3936     // Check 0x0000pq00_0000pq00 or 0xffffpq00_ffffpq00.
   3937     uint64_t rotvalue = RotateRight(value, 32, 64);
   3938     if (value == rotvalue) {
   3939       generic_value &= 0xffffffff;
   3940       if ((generic_value == 0xffff) || (generic_value == UINT32_MAX)) {
   3941         return false;
   3942       }
   3943     }
   3944 
   3945     // Check 0xpq00pq00_pq00pq00.
   3946     rotvalue = RotateRight(value, 16, 64);
   3947     if (value == rotvalue) {
   3948       return false;
   3949     }
   3950   } else {
   3951     // Check for 8-bit patterns. Set least-significant byte, to make tests
   3952     // easier.
   3953     uint64_t generic_value = value | 0xff;
   3954 
   3955     // Check 0x00000000_000000pq or 0xffffffff_ffffffpq.
   3956     if ((generic_value == 0xff) || (generic_value == UINT64_MAX)) {
   3957       return false;
   3958     }
   3959 
   3960     // Check 0x000000pq_000000pq or 0xffffffpq_ffffffpq.
   3961     uint64_t rotvalue = RotateRight(value, 32, 64);
   3962     if (value == rotvalue) {
   3963       generic_value &= 0xffffffff;
   3964       if ((generic_value == 0xff) || (generic_value == UINT32_MAX)) {
   3965         return false;
   3966       }
   3967     }
   3968 
   3969     // Check 0x00pq00pq_00pq00pq or 0xffpqffpq_ffpqffpq.
   3970     rotvalue = RotateRight(value, 16, 64);
   3971     if (value == rotvalue) {
   3972       generic_value &= 0xffff;
   3973       if ((generic_value == 0xff) || (generic_value == UINT16_MAX)) {
   3974         return false;
   3975       }
   3976     }
   3977 
   3978     // Check 0xpqpqpqpq_pqpqpqpq.
   3979     rotvalue = RotateRight(value, 8, 64);
   3980     if (value == rotvalue) {
   3981       return false;
   3982     }
   3983   }
   3984   return true;
   3985 }
   3986 
   3987 void Disassembler::VisitSVEBroadcastBitmaskImm(const Instruction *instr) {
   3988   const char *mnemonic = "unimplemented";
   3989   const char *form = "(SVEBroadcastBitmaskImm)";
   3990 
   3991   switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
   3992     case DUPM_z_i: {
   3993       uint64_t imm = instr->GetSVEImmLogical();
   3994       if (imm != 0) {
   3995         int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
   3996         mnemonic = SVEMoveMaskPreferred(imm, lane_size) ? "mov" : "dupm";
   3997         form = "'Zd.'tl, 'ITriSvel";
   3998       }
   3999       break;
   4000     }
   4001     default:
   4002       break;
   4003   }
   4004   Format(instr, mnemonic, form);
   4005 }
   4006 
   4007 void Disassembler::VisitSVEBroadcastFPImm_Unpredicated(
   4008     const Instruction *instr) {
   4009   const char *mnemonic = "unimplemented";
   4010   const char *form = "(SVEBroadcastFPImm_Unpredicated)";
   4011 
   4012   if (instr->GetSVEVectorFormat() != kFormatVnB) {
   4013     switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
   4014       case FDUP_z_i:
   4015         // The preferred disassembly for fdup is "fmov".
   4016         mnemonic = "fmov";
   4017         form = "'Zd.'t, 'IFPSve";
   4018         break;
   4019       default:
   4020         break;
   4021     }
   4022   }
   4023   Format(instr, mnemonic, form);
   4024 }
   4025 
   4026 void Disassembler::VisitSVEBroadcastGeneralRegister(const Instruction *instr) {
   4027   const char *mnemonic = "unimplemented";
   4028   const char *form = "(SVEBroadcastGeneralRegister)";
   4029 
   4030   switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
   4031     case DUP_z_r:
   4032       // The preferred disassembly for dup is "mov".
   4033       mnemonic = "mov";
   4034       if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
   4035         form = "'Zd.'t, 'Xns";
   4036       } else {
   4037         form = "'Zd.'t, 'Wns";
   4038       }
   4039       break;
   4040     default:
   4041       break;
   4042   }
   4043   Format(instr, mnemonic, form);
   4044 }
   4045 
   4046 void Disassembler::VisitSVEBroadcastIndexElement(const Instruction *instr) {
   4047   const char *mnemonic = "unimplemented";
   4048   const char *form = "(SVEBroadcastIndexElement)";
   4049 
   4050   switch (instr->Mask(SVEBroadcastIndexElementMask)) {
   4051     case DUP_z_zi: {
   4052       // The tsz field must not be zero.
   4053       int tsz = instr->ExtractBits(20, 16);
   4054       if (tsz != 0) {
   4055         // The preferred disassembly for dup is "mov".
   4056         mnemonic = "mov";
   4057         int imm2 = instr->ExtractBits(23, 22);
   4058         if ((CountSetBits(imm2) + CountSetBits(tsz)) == 1) {
   4059           // If imm2:tsz has one set bit, the index is zero. This is
   4060           // disassembled as a mov from a b/h/s/d/q scalar register.
   4061           form = "'Zd.'ti, 'ti'u0905";
   4062         } else {
   4063           form = "'Zd.'ti, 'Zn.'ti['IVInsSVEIndex]";
   4064         }
   4065       }
   4066       break;
   4067     }
   4068     default:
   4069       break;
   4070   }
   4071   Format(instr, mnemonic, form);
   4072 }
   4073 
   4074 void Disassembler::VisitSVEBroadcastIntImm_Unpredicated(
   4075     const Instruction *instr) {
   4076   const char *mnemonic = "unimplemented";
   4077   const char *form = "(SVEBroadcastIntImm_Unpredicated)";
   4078 
   4079   switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
   4080     case DUP_z_i:
   4081       // The encoding of byte-sized lanes with lsl #8 is undefined.
   4082       if ((instr->GetSVEVectorFormat() == kFormatVnB) &&
   4083           (instr->ExtractBit(13) == 1))
   4084         break;
   4085 
   4086       // The preferred disassembly for dup is "mov".
   4087       mnemonic = "mov";
   4088       form = (instr->ExtractBit(13) == 0) ? "'Zd.'t, #'s1205"
   4089                                           : "'Zd.'t, #'s1205, lsl #8";
   4090       break;
   4091     default:
   4092       break;
   4093   }
   4094   Format(instr, mnemonic, form);
   4095 }
   4096 
   4097 void Disassembler::VisitSVECompressActiveElements(const Instruction *instr) {
   4098   // The top bit of size is always set for compact, so 't can only be
   4099   // substituted with types S and D.
   4100   if (instr->ExtractBit(23) == 1) {
   4101     FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl, 'Zn.'t");
   4102   } else {
   4103     VisitUnallocated(instr);
   4104   }
   4105 }
   4106 
   4107 void Disassembler::VisitSVEConditionallyBroadcastElementToVector(
   4108     const Instruction *instr) {
   4109   FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl, 'Zd.'t, 'Zn.'t");
   4110 }
   4111 
   4112 void Disassembler::VisitSVEConditionallyExtractElementToGeneralRegister(
   4113     const Instruction *instr) {
   4114   const char *form = "'Wd, 'Pgl, 'Wd, 'Zn.'t";
   4115 
   4116   if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
   4117     form = "'Xd, p'u1210, 'Xd, 'Zn.'t";
   4118   }
   4119   FormatWithDecodedMnemonic(instr, form);
   4120 }
   4121 
   4122 void Disassembler::VisitSVEConditionallyExtractElementToSIMDFPScalar(
   4123     const Instruction *instr) {
   4124   FormatWithDecodedMnemonic(instr, "'t'u0400, 'Pgl, 't'u0400, 'Zn.'t");
   4125 }
   4126 
   4127 void Disassembler::VisitSVEConditionallyTerminateScalars(
   4128     const Instruction *instr) {
   4129   const char *form = (instr->ExtractBit(22) == 0) ? "'Wn, 'Wm" : "'Xn, 'Xm";
   4130   FormatWithDecodedMnemonic(instr, form);
   4131 }
   4132 
   4133 void Disassembler::VisitSVEConstructivePrefix_Unpredicated(
   4134     const Instruction *instr) {
   4135   FormatWithDecodedMnemonic(instr, "'Zd, 'Zn");
   4136 }
   4137 
   4138 void Disassembler::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
   4139     const Instruction *instr) {
   4140   const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns";
   4141   const char *suffix = "]";
   4142 
   4143   if (instr->GetRm() != kZeroRegCode) {
   4144     switch (form_hash_) {
   4145       case "ldff1b_z_p_br_u8"_h:
   4146       case "ldff1b_z_p_br_u16"_h:
   4147       case "ldff1b_z_p_br_u32"_h:
   4148       case "ldff1b_z_p_br_u64"_h:
   4149       case "ldff1sb_z_p_br_s16"_h:
   4150       case "ldff1sb_z_p_br_s32"_h:
   4151       case "ldff1sb_z_p_br_s64"_h:
   4152         suffix = ", 'Xm]";
   4153         break;
   4154       case "ldff1h_z_p_br_u16"_h:
   4155       case "ldff1h_z_p_br_u32"_h:
   4156       case "ldff1h_z_p_br_u64"_h:
   4157       case "ldff1sh_z_p_br_s32"_h:
   4158       case "ldff1sh_z_p_br_s64"_h:
   4159         suffix = ", 'Xm, lsl #1]";
   4160         break;
   4161       case "ldff1w_z_p_br_u32"_h:
   4162       case "ldff1w_z_p_br_u64"_h:
   4163       case "ldff1sw_z_p_br_s64"_h:
   4164         suffix = ", 'Xm, lsl #2]";
   4165         break;
   4166       case "ldff1d_z_p_br_u64"_h:
   4167         suffix = ", 'Xm, lsl #3]";
   4168         break;
   4169     }
   4170   }
   4171 
   4172   FormatWithDecodedMnemonic(instr, form, suffix);
   4173 }
   4174 
   4175 void Disassembler::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
   4176     const Instruction *instr) {
   4177   const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns";
   4178   const char *suffix =
   4179       (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]";
   4180   FormatWithDecodedMnemonic(instr, form, suffix);
   4181 }
   4182 
   4183 void Disassembler::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
   4184     const Instruction *instr) {
   4185   const char *form = "{'Zt.b}, 'Pgl/z, ['Xns";
   4186   const char *suffix =
   4187       (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]";
   4188   switch (form_hash_) {
   4189     case "ldnt1d_z_p_bi_contiguous"_h:
   4190       form = "{'Zt.d}, 'Pgl/z, ['Xns";
   4191       break;
   4192     case "ldnt1h_z_p_bi_contiguous"_h:
   4193       form = "{'Zt.h}, 'Pgl/z, ['Xns";
   4194       break;
   4195     case "ldnt1w_z_p_bi_contiguous"_h:
   4196       form = "{'Zt.s}, 'Pgl/z, ['Xns";
   4197       break;
   4198   }
   4199   FormatWithDecodedMnemonic(instr, form, suffix);
   4200 }
   4201 
   4202 void Disassembler::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
   4203     const Instruction *instr) {
   4204   const char *form = "{'Zt.b}, 'Pgl/z, ['Xns, 'Rm]";
   4205   switch (form_hash_) {
   4206     case "ldnt1d_z_p_br_contiguous"_h:
   4207       form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Rm, lsl #3]";
   4208       break;
   4209     case "ldnt1h_z_p_br_contiguous"_h:
   4210       form = "{'Zt.h}, 'Pgl/z, ['Xns, 'Rm, lsl #1]";
   4211       break;
   4212     case "ldnt1w_z_p_br_contiguous"_h:
   4213       form = "{'Zt.s}, 'Pgl/z, ['Xns, 'Rm, lsl #2]";
   4214       break;
   4215   }
   4216   FormatWithDecodedMnemonic(instr, form);
   4217 }
   4218 
   4219 void Disassembler::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
   4220     const Instruction *instr) {
   4221   const char *form = "{'Zt.b}, 'Pgl, ['Xns";
   4222   const char *suffix =
   4223       (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]";
   4224 
   4225   switch (form_hash_) {
   4226     case "stnt1d_z_p_bi_contiguous"_h:
   4227       form = "{'Zt.d}, 'Pgl, ['Xns";
   4228       break;
   4229     case "stnt1h_z_p_bi_contiguous"_h:
   4230       form = "{'Zt.h}, 'Pgl, ['Xns";
   4231       break;
   4232     case "stnt1w_z_p_bi_contiguous"_h:
   4233       form = "{'Zt.s}, 'Pgl, ['Xns";
   4234       break;
   4235   }
   4236   FormatWithDecodedMnemonic(instr, form, suffix);
   4237 }
   4238 
   4239 void Disassembler::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
   4240     const Instruction *instr) {
   4241   const char *mnemonic = "unimplemented";
   4242   const char *form = "(SVEContiguousNonTemporalStore_ScalarPlusScalar)";
   4243 
   4244   switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
   4245     case STNT1B_z_p_br_contiguous:
   4246       mnemonic = "stnt1b";
   4247       form = "{'Zt.b}, 'Pgl, ['Xns, 'Rm]";
   4248       break;
   4249     case STNT1D_z_p_br_contiguous:
   4250       mnemonic = "stnt1d";
   4251       form = "{'Zt.d}, 'Pgl, ['Xns, 'Rm, lsl #3]";
   4252       break;
   4253     case STNT1H_z_p_br_contiguous:
   4254       mnemonic = "stnt1h";
   4255       form = "{'Zt.h}, 'Pgl, ['Xns, 'Rm, lsl #1]";
   4256       break;
   4257     case STNT1W_z_p_br_contiguous:
   4258       mnemonic = "stnt1w";
   4259       form = "{'Zt.s}, 'Pgl, ['Xns, 'Rm, lsl #2]";
   4260       break;
   4261     default:
   4262       break;
   4263   }
   4264   Format(instr, mnemonic, form);
   4265 }
   4266 
   4267 void Disassembler::VisitSVEContiguousPrefetch_ScalarPlusImm(
   4268     const Instruction *instr) {
   4269   const char *form = (instr->ExtractBits(21, 16) != 0)
   4270                          ? "'prefSVEOp, 'Pgl, ['Xns, #'s2116, mul vl]"
   4271                          : "'prefSVEOp, 'Pgl, ['Xns]";
   4272   FormatWithDecodedMnemonic(instr, form);
   4273 }
   4274 
   4275 void Disassembler::VisitSVEContiguousPrefetch_ScalarPlusScalar(
   4276     const Instruction *instr) {
   4277   const char *mnemonic = "unimplemented";
   4278   const char *form = "(SVEContiguousPrefetch_ScalarPlusScalar)";
   4279 
   4280   if (instr->GetRm() != kZeroRegCode) {
   4281     switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
   4282       case PRFB_i_p_br_s:
   4283         mnemonic = "prfb";
   4284         form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm]";
   4285         break;
   4286       case PRFD_i_p_br_s:
   4287         mnemonic = "prfd";
   4288         form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm, lsl #3]";
   4289         break;
   4290       case PRFH_i_p_br_s:
   4291         mnemonic = "prfh";
   4292         form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm, lsl #1]";
   4293         break;
   4294       case PRFW_i_p_br_s:
   4295         mnemonic = "prfw";
   4296         form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm, lsl #2]";
   4297         break;
   4298       default:
   4299         break;
   4300     }
   4301   }
   4302   Format(instr, mnemonic, form);
   4303 }
   4304 
   4305 void Disassembler::VisitSVEContiguousStore_ScalarPlusImm(
   4306     const Instruction *instr) {
   4307   // The 'size' field isn't in the usual place here.
   4308   const char *form = "{'Zt.'tls}, 'Pgl, ['Xns, #'s1916, mul vl]";
   4309   if (instr->ExtractBits(19, 16) == 0) {
   4310     form = "{'Zt.'tls}, 'Pgl, ['Xns]";
   4311   }
   4312   FormatWithDecodedMnemonic(instr, form);
   4313 }
   4314 
   4315 void Disassembler::VisitSVEContiguousStore_ScalarPlusScalar(
   4316     const Instruction *instr) {
   4317   // The 'size' field isn't in the usual place here.
   4318   FormatWithDecodedMnemonic(instr, "{'Zt.'tls}, 'Pgl, ['Xns, 'Xm'NSveS]");
   4319 }
   4320 
   4321 void Disassembler::VisitSVECopyFPImm_Predicated(const Instruction *instr) {
   4322   const char *mnemonic = "unimplemented";
   4323   const char *form = "(SVECopyFPImm_Predicated)";
   4324 
   4325   if (instr->GetSVEVectorFormat() != kFormatVnB) {
   4326     switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
   4327       case FCPY_z_p_i:
   4328         // The preferred disassembly for fcpy is "fmov".
   4329         mnemonic = "fmov";
   4330         form = "'Zd.'t, 'Pm/m, 'IFPSve";
   4331         break;
   4332       default:
   4333         break;
   4334     }
   4335   }
   4336   Format(instr, mnemonic, form);
   4337 }
   4338 
   4339 void Disassembler::VisitSVECopyGeneralRegisterToVector_Predicated(
   4340     const Instruction *instr) {
   4341   const char *mnemonic = "unimplemented";
   4342   const char *form = "(SVECopyGeneralRegisterToVector_Predicated)";
   4343 
   4344   switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
   4345     case CPY_z_p_r:
   4346       // The preferred disassembly for cpy is "mov".
   4347       mnemonic = "mov";
   4348       form = "'Zd.'t, 'Pgl/m, 'Wns";
   4349       if (instr->GetSVESize() == kXRegSizeInBytesLog2) {
   4350         form = "'Zd.'t, 'Pgl/m, 'Xns";
   4351       }
   4352       break;
   4353     default:
   4354       break;
   4355   }
   4356   Format(instr, mnemonic, form);
   4357 }
   4358 
   4359 void Disassembler::VisitSVECopyIntImm_Predicated(const Instruction *instr) {
   4360   const char *mnemonic = "unimplemented";
   4361   const char *form = "(SVECopyIntImm_Predicated)";
   4362   const char *suffix = NULL;
   4363 
   4364   switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
   4365     case CPY_z_p_i: {
   4366       // The preferred disassembly for cpy is "mov".
   4367       mnemonic = "mov";
   4368       form = "'Zd.'t, 'Pm/'?14:mz, #'s1205";
   4369       if (instr->ExtractBit(13) != 0) suffix = ", lsl #8";
   4370       break;
   4371     }
   4372     default:
   4373       break;
   4374   }
   4375   Format(instr, mnemonic, form, suffix);
   4376 }
   4377 
   4378 void Disassembler::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
   4379     const Instruction *instr) {
   4380   const char *mnemonic = "unimplemented";
   4381   const char *form = "(SVECopySIMDFPScalarRegisterToVector_Predicated)";
   4382 
   4383   switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
   4384     case CPY_z_p_v:
   4385       // The preferred disassembly for cpy is "mov".
   4386       mnemonic = "mov";
   4387       form = "'Zd.'t, 'Pgl/m, 'Vnv";
   4388       break;
   4389     default:
   4390       break;
   4391   }
   4392   Format(instr, mnemonic, form);
   4393 }
   4394 
   4395 void Disassembler::VisitSVEExtractElementToGeneralRegister(
   4396     const Instruction *instr) {
   4397   const char *form = "'Wd, 'Pgl, 'Zn.'t";
   4398   if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
   4399     form = "'Xd, p'u1210, 'Zn.'t";
   4400   }
   4401   FormatWithDecodedMnemonic(instr, form);
   4402 }
   4403 
   4404 void Disassembler::VisitSVEExtractElementToSIMDFPScalarRegister(
   4405     const Instruction *instr) {
   4406   FormatWithDecodedMnemonic(instr, "'t'u0400, 'Pgl, 'Zn.'t");
   4407 }
   4408 
   4409 void Disassembler::VisitSVEFFRInitialise(const Instruction *instr) {
   4410   DisassembleNoArgs(instr);
   4411 }
   4412 
   4413 void Disassembler::VisitSVEFFRWriteFromPredicate(const Instruction *instr) {
   4414   FormatWithDecodedMnemonic(instr, "'Pn.b");
   4415 }
   4416 
   4417 void Disassembler::VisitSVEFPArithmeticWithImm_Predicated(
   4418     const Instruction *instr) {
   4419   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, #";
   4420   const char *suffix00 = "0.0";
   4421   const char *suffix05 = "0.5";
   4422   const char *suffix10 = "1.0";
   4423   const char *suffix20 = "2.0";
   4424   int i1 = instr->ExtractBit(5);
   4425   const char *suffix = i1 ? suffix10 : suffix00;
   4426 
   4427   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   4428     VisitUnallocated(instr);
   4429     return;
   4430   }
   4431 
   4432   switch (form_hash_) {
   4433     case "fadd_z_p_zs"_h:
   4434     case "fsubr_z_p_zs"_h:
   4435     case "fsub_z_p_zs"_h:
   4436       suffix = i1 ? suffix10 : suffix05;
   4437       break;
   4438     case "fmul_z_p_zs"_h:
   4439       suffix = i1 ? suffix20 : suffix05;
   4440       break;
   4441   }
   4442   FormatWithDecodedMnemonic(instr, form, suffix);
   4443 }
   4444 
   4445 void Disassembler::VisitSVEFPArithmetic_Predicated(const Instruction *instr) {
   4446   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   4447     VisitUnallocated(instr);
   4448   } else {
   4449     FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t");
   4450   }
   4451 }
   4452 
   4453 void Disassembler::VisitSVEFPConvertPrecision(const Instruction *instr) {
   4454   const char *form = NULL;
   4455 
   4456   switch (form_hash_) {
   4457     case "fcvt_z_p_z_d2h"_h:
   4458       form = "'Zd.h, 'Pgl/m, 'Zn.d";
   4459       break;
   4460     case "fcvt_z_p_z_d2s"_h:
   4461       form = "'Zd.s, 'Pgl/m, 'Zn.d";
   4462       break;
   4463     case "fcvt_z_p_z_h2d"_h:
   4464       form = "'Zd.d, 'Pgl/m, 'Zn.h";
   4465       break;
   4466     case "fcvt_z_p_z_h2s"_h:
   4467       form = "'Zd.s, 'Pgl/m, 'Zn.h";
   4468       break;
   4469     case "fcvt_z_p_z_s2d"_h:
   4470       form = "'Zd.d, 'Pgl/m, 'Zn.s";
   4471       break;
   4472     case "fcvt_z_p_z_s2h"_h:
   4473       form = "'Zd.h, 'Pgl/m, 'Zn.s";
   4474       break;
   4475   }
   4476   FormatWithDecodedMnemonic(instr, form);
   4477 }
   4478 
   4479 void Disassembler::VisitSVEFPConvertToInt(const Instruction *instr) {
   4480   const char *form = NULL;
   4481 
   4482   switch (form_hash_) {
   4483     case "fcvtzs_z_p_z_d2w"_h:
   4484     case "fcvtzu_z_p_z_d2w"_h:
   4485       form = "'Zd.s, 'Pgl/m, 'Zn.d";
   4486       break;
   4487     case "fcvtzs_z_p_z_d2x"_h:
   4488     case "fcvtzu_z_p_z_d2x"_h:
   4489       form = "'Zd.d, 'Pgl/m, 'Zn.d";
   4490       break;
   4491     case "fcvtzs_z_p_z_fp162h"_h:
   4492     case "fcvtzu_z_p_z_fp162h"_h:
   4493       form = "'Zd.h, 'Pgl/m, 'Zn.h";
   4494       break;
   4495     case "fcvtzs_z_p_z_fp162w"_h:
   4496     case "fcvtzu_z_p_z_fp162w"_h:
   4497       form = "'Zd.s, 'Pgl/m, 'Zn.h";
   4498       break;
   4499     case "fcvtzs_z_p_z_fp162x"_h:
   4500     case "fcvtzu_z_p_z_fp162x"_h:
   4501       form = "'Zd.d, 'Pgl/m, 'Zn.h";
   4502       break;
   4503     case "fcvtzs_z_p_z_s2w"_h:
   4504     case "fcvtzu_z_p_z_s2w"_h:
   4505       form = "'Zd.s, 'Pgl/m, 'Zn.s";
   4506       break;
   4507     case "fcvtzs_z_p_z_s2x"_h:
   4508     case "fcvtzu_z_p_z_s2x"_h:
   4509       form = "'Zd.d, 'Pgl/m, 'Zn.s";
   4510       break;
   4511   }
   4512   FormatWithDecodedMnemonic(instr, form);
   4513 }
   4514 
   4515 void Disassembler::VisitSVEFPExponentialAccelerator(const Instruction *instr) {
   4516   unsigned size = instr->GetSVESize();
   4517   if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) ||
   4518       (size == kDRegSizeInBytesLog2)) {
   4519     FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'t");
   4520   } else {
   4521     VisitUnallocated(instr);
   4522   }
   4523 }
   4524 
   4525 void Disassembler::VisitSVEFPRoundToIntegralValue(const Instruction *instr) {
   4526   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   4527     VisitUnallocated(instr);
   4528   } else {
   4529     FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zn.'t");
   4530   }
   4531 }
   4532 
   4533 void Disassembler::VisitSVEFPTrigMulAddCoefficient(const Instruction *instr) {
   4534   unsigned size = instr->GetSVESize();
   4535   if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) ||
   4536       (size == kDRegSizeInBytesLog2)) {
   4537     FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zd.'t, 'Zn.'t, #'u1816");
   4538   } else {
   4539     VisitUnallocated(instr);
   4540   }
   4541 }
   4542 
   4543 void Disassembler::VisitSVEFPTrigSelectCoefficient(const Instruction *instr) {
   4544   unsigned size = instr->GetSVESize();
   4545   if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) ||
   4546       (size == kDRegSizeInBytesLog2)) {
   4547     FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'t, 'Zm.'t");
   4548   } else {
   4549     VisitUnallocated(instr);
   4550   }
   4551 }
   4552 
   4553 void Disassembler::VisitSVEFPUnaryOp(const Instruction *instr) {
   4554   if (instr->GetSVESize() == kBRegSizeInBytesLog2) {
   4555     VisitUnallocated(instr);
   4556   } else {
   4557     FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zn.'t");
   4558   }
   4559 }
   4560 
   4561 static const char *IncDecFormHelper(const Instruction *instr,
   4562                                     const char *reg_pat_mul_form,
   4563                                     const char *reg_pat_form,
   4564                                     const char *reg_form) {
   4565   if (instr->ExtractBits(19, 16) == 0) {
   4566     if (instr->ExtractBits(9, 5) == SVE_ALL) {
   4567       // Use the register only form if the multiplier is one (encoded as zero)
   4568       // and the pattern is SVE_ALL.
   4569       return reg_form;
   4570     }
   4571     // Use the register and pattern form if the multiplier is one.
   4572     return reg_pat_form;
   4573   }
   4574   return reg_pat_mul_form;
   4575 }
   4576 
   4577 void Disassembler::VisitSVEIncDecRegisterByElementCount(
   4578     const Instruction *instr) {
   4579   const char *form =
   4580       IncDecFormHelper(instr, "'Xd, 'Ipc, mul #'u1916+1", "'Xd, 'Ipc", "'Xd");
   4581   FormatWithDecodedMnemonic(instr, form);
   4582 }
   4583 
   4584 void Disassembler::VisitSVEIncDecVectorByElementCount(
   4585     const Instruction *instr) {
   4586   const char *form = IncDecFormHelper(instr,
   4587                                       "'Zd.'t, 'Ipc, mul #'u1916+1",
   4588                                       "'Zd.'t, 'Ipc",
   4589                                       "'Zd.'t");
   4590   FormatWithDecodedMnemonic(instr, form);
   4591 }
   4592 
   4593 void Disassembler::VisitSVEInsertGeneralRegister(const Instruction *instr) {
   4594   const char *form = "'Zd.'t, 'Wn";
   4595   if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
   4596     form = "'Zd.'t, 'Xn";
   4597   }
   4598   FormatWithDecodedMnemonic(instr, form);
   4599 }
   4600 
   4601 void Disassembler::VisitSVEInsertSIMDFPScalarRegister(
   4602     const Instruction *instr) {
   4603   FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Vnv");
   4604 }
   4605 
   4606 void Disassembler::VisitSVEIntAddSubtractImm_Unpredicated(
   4607     const Instruction *instr) {
   4608   const char *form = (instr->ExtractBit(13) == 0)
   4609                          ? "'Zd.'t, 'Zd.'t, #'u1205"
   4610                          : "'Zd.'t, 'Zd.'t, #'u1205, lsl #8";
   4611   FormatWithDecodedMnemonic(instr, form);
   4612 }
   4613 
   4614 void Disassembler::VisitSVEIntAddSubtractVectors_Predicated(
   4615     const Instruction *instr) {
   4616   FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t");
   4617 }
   4618 
   4619 void Disassembler::VisitSVEIntCompareScalarCountAndLimit(
   4620     const Instruction *instr) {
   4621   const char *form =
   4622       (instr->ExtractBit(12) == 0) ? "'Pd.'t, 'Wn, 'Wm" : "'Pd.'t, 'Xn, 'Xm";
   4623   FormatWithDecodedMnemonic(instr, form);
   4624 }
   4625 
   4626 void Disassembler::VisitSVEIntConvertToFP(const Instruction *instr) {
   4627   const char *form = NULL;
   4628   switch (form_hash_) {
   4629     case "scvtf_z_p_z_h2fp16"_h:
   4630     case "ucvtf_z_p_z_h2fp16"_h:
   4631       form = "'Zd.h, 'Pgl/m, 'Zn.h";
   4632       break;
   4633     case "scvtf_z_p_z_w2d"_h:
   4634     case "ucvtf_z_p_z_w2d"_h:
   4635       form = "'Zd.d, 'Pgl/m, 'Zn.s";
   4636       break;
   4637     case "scvtf_z_p_z_w2fp16"_h:
   4638     case "ucvtf_z_p_z_w2fp16"_h:
   4639       form = "'Zd.h, 'Pgl/m, 'Zn.s";
   4640       break;
   4641     case "scvtf_z_p_z_w2s"_h:
   4642     case "ucvtf_z_p_z_w2s"_h:
   4643       form = "'Zd.s, 'Pgl/m, 'Zn.s";
   4644       break;
   4645     case "scvtf_z_p_z_x2d"_h:
   4646     case "ucvtf_z_p_z_x2d"_h:
   4647       form = "'Zd.d, 'Pgl/m, 'Zn.d";
   4648       break;
   4649     case "scvtf_z_p_z_x2fp16"_h:
   4650     case "ucvtf_z_p_z_x2fp16"_h:
   4651       form = "'Zd.h, 'Pgl/m, 'Zn.d";
   4652       break;
   4653     case "scvtf_z_p_z_x2s"_h:
   4654     case "ucvtf_z_p_z_x2s"_h:
   4655       form = "'Zd.s, 'Pgl/m, 'Zn.d";
   4656       break;
   4657   }
   4658   FormatWithDecodedMnemonic(instr, form);
   4659 }
   4660 
   4661 void Disassembler::VisitSVEIntDivideVectors_Predicated(
   4662     const Instruction *instr) {
   4663   unsigned size = instr->GetSVESize();
   4664   if ((size == kSRegSizeInBytesLog2) || (size == kDRegSizeInBytesLog2)) {
   4665     FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t");
   4666   } else {
   4667     VisitUnallocated(instr);
   4668   }
   4669 }
   4670 
   4671 void Disassembler::VisitSVEIntMinMaxDifference_Predicated(
   4672     const Instruction *instr) {
   4673   FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t");
   4674 }
   4675 
   4676 void Disassembler::VisitSVEIntMinMaxImm_Unpredicated(const Instruction *instr) {
   4677   const char *form = "'Zd.'t, 'Zd.'t, #";
   4678   const char *suffix = "'u1205";
   4679 
   4680   switch (form_hash_) {
   4681     case "smax_z_zi"_h:
   4682     case "smin_z_zi"_h:
   4683       suffix = "'s1205";
   4684       break;
   4685   }
   4686   FormatWithDecodedMnemonic(instr, form, suffix);
   4687 }
   4688 
   4689 void Disassembler::VisitSVEIntMulImm_Unpredicated(const Instruction *instr) {
   4690   FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zd.'t, #'s1205");
   4691 }
   4692 
   4693 void Disassembler::VisitSVEIntMulVectors_Predicated(const Instruction *instr) {
   4694   FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t");
   4695 }
   4696 
   4697 void Disassembler::VisitSVELoadAndBroadcastElement(const Instruction *instr) {
   4698   const char *form = "(SVELoadAndBroadcastElement)";
   4699   const char *suffix_b = ", #'u2116]";
   4700   const char *suffix_h = ", #'u2116*2]";
   4701   const char *suffix_w = ", #'u2116*4]";
   4702   const char *suffix_d = ", #'u2116*8]";
   4703   const char *suffix = NULL;
   4704 
   4705   switch (form_hash_) {
   4706     case "ld1rb_z_p_bi_u8"_h:
   4707       form = "{'Zt.b}, 'Pgl/z, ['Xns";
   4708       suffix = suffix_b;
   4709       break;
   4710     case "ld1rb_z_p_bi_u16"_h:
   4711     case "ld1rsb_z_p_bi_s16"_h:
   4712       form = "{'Zt.h}, 'Pgl/z, ['Xns";
   4713       suffix = suffix_b;
   4714       break;
   4715     case "ld1rb_z_p_bi_u32"_h:
   4716     case "ld1rsb_z_p_bi_s32"_h:
   4717       form = "{'Zt.s}, 'Pgl/z, ['Xns";
   4718       suffix = suffix_b;
   4719       break;
   4720     case "ld1rb_z_p_bi_u64"_h:
   4721     case "ld1rsb_z_p_bi_s64"_h:
   4722       form = "{'Zt.d}, 'Pgl/z, ['Xns";
   4723       suffix = suffix_b;
   4724       break;
   4725     case "ld1rh_z_p_bi_u16"_h:
   4726       form = "{'Zt.h}, 'Pgl/z, ['Xns";
   4727       suffix = suffix_h;
   4728       break;
   4729     case "ld1rh_z_p_bi_u32"_h:
   4730     case "ld1rsh_z_p_bi_s32"_h:
   4731       form = "{'Zt.s}, 'Pgl/z, ['Xns";
   4732       suffix = suffix_h;
   4733       break;
   4734     case "ld1rh_z_p_bi_u64"_h:
   4735     case "ld1rsh_z_p_bi_s64"_h:
   4736       form = "{'Zt.d}, 'Pgl/z, ['Xns";
   4737       suffix = suffix_h;
   4738       break;
   4739     case "ld1rw_z_p_bi_u32"_h:
   4740       form = "{'Zt.s}, 'Pgl/z, ['Xns";
   4741       suffix = suffix_w;
   4742       break;
   4743     case "ld1rsw_z_p_bi_s64"_h:
   4744     case "ld1rw_z_p_bi_u64"_h:
   4745       form = "{'Zt.d}, 'Pgl/z, ['Xns";
   4746       suffix = suffix_w;
   4747       break;
   4748     case "ld1rd_z_p_bi_u64"_h:
   4749       form = "{'Zt.d}, 'Pgl/z, ['Xns";
   4750       suffix = suffix_d;
   4751       break;
   4752   }
   4753 
   4754   // Hide curly brackets if immediate is zero.
   4755   if (instr->ExtractBits(21, 16) == 0) {
   4756     suffix = "]";
   4757   }
   4758 
   4759   FormatWithDecodedMnemonic(instr, form, suffix);
   4760 }
   4761 
   4762 void Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm(
   4763     const Instruction *instr) {
   4764   const char *form = "{'Zt.'tmsz}, 'Pgl/z, ['Xns";
   4765   const char *suffix = ", #'s1916*16]";
   4766 
   4767   switch (form_hash_) {
   4768     case "ld1rob_z_p_bi_u8"_h:
   4769     case "ld1rod_z_p_bi_u64"_h:
   4770     case "ld1roh_z_p_bi_u16"_h:
   4771     case "ld1row_z_p_bi_u32"_h:
   4772       suffix = ", #'s1916*32]";
   4773       break;
   4774   }
   4775   if (instr->ExtractBits(19, 16) == 0) suffix = "]";
   4776 
   4777   FormatWithDecodedMnemonic(instr, form, suffix);
   4778 }
   4779 
   4780 void Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar(
   4781     const Instruction *instr) {
   4782   const char *form = "{'Zt.'tmsz}, 'Pgl/z, ['Xns, ";
   4783   const char *suffix = "'Rm, lsl #'u2423]";
   4784 
   4785   switch (form_hash_) {
   4786     case "ld1rqb_z_p_br_contiguous"_h:
   4787     case "ld1rob_z_p_br_contiguous"_h:
   4788       suffix = "'Rm]";
   4789       break;
   4790   }
   4791   FormatWithDecodedMnemonic(instr, form, suffix);
   4792 }
   4793 
   4794 void Disassembler::VisitSVELoadMultipleStructures_ScalarPlusImm(
   4795     const Instruction *instr) {
   4796   const char *form = "{'Zt.'tmsz, 'Zt2.'tmsz}";
   4797   const char *form_3 = "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}";
   4798   const char *form_4 = "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}";
   4799   const char *suffix = ", 'Pgl/z, ['Xns'ISveSvl]";
   4800 
   4801   switch (form_hash_) {
   4802     case "ld3b_z_p_bi_contiguous"_h:
   4803     case "ld3d_z_p_bi_contiguous"_h:
   4804     case "ld3h_z_p_bi_contiguous"_h:
   4805     case "ld3w_z_p_bi_contiguous"_h:
   4806       form = form_3;
   4807       break;
   4808     case "ld4b_z_p_bi_contiguous"_h:
   4809     case "ld4d_z_p_bi_contiguous"_h:
   4810     case "ld4h_z_p_bi_contiguous"_h:
   4811     case "ld4w_z_p_bi_contiguous"_h:
   4812       form = form_4;
   4813       break;
   4814   }
   4815   FormatWithDecodedMnemonic(instr, form, suffix);
   4816 }
   4817 
   4818 void Disassembler::VisitSVELoadMultipleStructures_ScalarPlusScalar(
   4819     const Instruction *instr) {
   4820   const char *form = "{'Zt.'tmsz, 'Zt2.'tmsz}";
   4821   const char *form_3 = "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}";
   4822   const char *form_4 = "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}";
   4823   const char *suffix = ", 'Pgl/z, ['Xns, 'Xm'NSveS]";
   4824 
   4825   switch (form_hash_) {
   4826     case "ld3b_z_p_br_contiguous"_h:
   4827     case "ld3d_z_p_br_contiguous"_h:
   4828     case "ld3h_z_p_br_contiguous"_h:
   4829     case "ld3w_z_p_br_contiguous"_h:
   4830       form = form_3;
   4831       break;
   4832     case "ld4b_z_p_br_contiguous"_h:
   4833     case "ld4d_z_p_br_contiguous"_h:
   4834     case "ld4h_z_p_br_contiguous"_h:
   4835     case "ld4w_z_p_br_contiguous"_h:
   4836       form = form_4;
   4837       break;
   4838   }
   4839   FormatWithDecodedMnemonic(instr, form, suffix);
   4840 }
   4841 
   4842 void Disassembler::VisitSVELoadPredicateRegister(const Instruction *instr) {
   4843   const char *form = "'Pd, ['Xns, #'s2116:1210, mul vl]";
   4844   if (instr->Mask(0x003f1c00) == 0) {
   4845     form = "'Pd, ['Xns]";
   4846   }
   4847   FormatWithDecodedMnemonic(instr, form);
   4848 }
   4849 
   4850 void Disassembler::VisitSVELoadVectorRegister(const Instruction *instr) {
   4851   const char *form = "'Zt, ['Xns, #'s2116:1210, mul vl]";
   4852   if (instr->Mask(0x003f1c00) == 0) {
   4853     form = "'Zd, ['Xns]";
   4854   }
   4855   FormatWithDecodedMnemonic(instr, form);
   4856 }
   4857 
   4858 void Disassembler::VisitSVEPartitionBreakCondition(const Instruction *instr) {
   4859   FormatWithDecodedMnemonic(instr, "'Pd.b, p'u1310/'?04:mz, 'Pn.b");
   4860 }
   4861 
   4862 void Disassembler::VisitSVEPermutePredicateElements(const Instruction *instr) {
   4863   FormatWithDecodedMnemonic(instr, "'Pd.'t, 'Pn.'t, 'Pm.'t");
   4864 }
   4865 
   4866 void Disassembler::VisitSVEPredicateFirstActive(const Instruction *instr) {
   4867   FormatWithDecodedMnemonic(instr, "'Pd.b, 'Pn, 'Pd.b");
   4868 }
   4869 
   4870 void Disassembler::VisitSVEPredicateReadFromFFR_Unpredicated(
   4871     const Instruction *instr) {
   4872   FormatWithDecodedMnemonic(instr, "'Pd.b");
   4873 }
   4874 
   4875 void Disassembler::VisitSVEPredicateTest(const Instruction *instr) {
   4876   FormatWithDecodedMnemonic(instr, "p'u1310, 'Pn.b");
   4877 }
   4878 
   4879 void Disassembler::VisitSVEPredicateZero(const Instruction *instr) {
   4880   FormatWithDecodedMnemonic(instr, "'Pd.b");
   4881 }
   4882 
   4883 void Disassembler::VisitSVEPropagateBreakToNextPartition(
   4884     const Instruction *instr) {
   4885   FormatWithDecodedMnemonic(instr, "'Pd.b, p'u1310/z, 'Pn.b, 'Pd.b");
   4886 }
   4887 
   4888 void Disassembler::VisitSVEReversePredicateElements(const Instruction *instr) {
   4889   FormatWithDecodedMnemonic(instr, "'Pd.'t, 'Pn.'t");
   4890 }
   4891 
   4892 void Disassembler::VisitSVEReverseVectorElements(const Instruction *instr) {
   4893   FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'t");
   4894 }
   4895 
   4896 void Disassembler::VisitSVEReverseWithinElements(const Instruction *instr) {
   4897   const char *mnemonic = "unimplemented";
   4898   const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t";
   4899 
   4900   unsigned size = instr->GetSVESize();
   4901   switch (instr->Mask(SVEReverseWithinElementsMask)) {
   4902     case RBIT_z_p_z:
   4903       mnemonic = "rbit";
   4904       break;
   4905     case REVB_z_z:
   4906       if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) ||
   4907           (size == kDRegSizeInBytesLog2)) {
   4908         mnemonic = "revb";
   4909       } else {
   4910         form = "(SVEReverseWithinElements)";
   4911       }
   4912       break;
   4913     case REVH_z_z:
   4914       if ((size == kSRegSizeInBytesLog2) || (size == kDRegSizeInBytesLog2)) {
   4915         mnemonic = "revh";
   4916       } else {
   4917         form = "(SVEReverseWithinElements)";
   4918       }
   4919       break;
   4920     case REVW_z_z:
   4921       if (size == kDRegSizeInBytesLog2) {
   4922         mnemonic = "revw";
   4923       } else {
   4924         form = "(SVEReverseWithinElements)";
   4925       }
   4926       break;
   4927     default:
   4928       break;
   4929   }
   4930   Format(instr, mnemonic, form);
   4931 }
   4932 
   4933 void Disassembler::VisitSVESaturatingIncDecRegisterByElementCount(
   4934     const Instruction *instr) {
   4935   const char *form = IncDecFormHelper(instr,
   4936                                       "'R20d, 'Ipc, mul #'u1916+1",
   4937                                       "'R20d, 'Ipc",
   4938                                       "'R20d");
   4939   const char *form_sx = IncDecFormHelper(instr,
   4940                                          "'Xd, 'Wd, 'Ipc, mul #'u1916+1",
   4941                                          "'Xd, 'Wd, 'Ipc",
   4942                                          "'Xd, 'Wd");
   4943 
   4944   switch (form_hash_) {
   4945     case "sqdecb_r_rs_sx"_h:
   4946     case "sqdecd_r_rs_sx"_h:
   4947     case "sqdech_r_rs_sx"_h:
   4948     case "sqdecw_r_rs_sx"_h:
   4949     case "sqincb_r_rs_sx"_h:
   4950     case "sqincd_r_rs_sx"_h:
   4951     case "sqinch_r_rs_sx"_h:
   4952     case "sqincw_r_rs_sx"_h:
   4953       form = form_sx;
   4954       break;
   4955   }
   4956   FormatWithDecodedMnemonic(instr, form);
   4957 }
   4958 
   4959 void Disassembler::VisitSVESaturatingIncDecVectorByElementCount(
   4960     const Instruction *instr) {
   4961   const char *form = IncDecFormHelper(instr,
   4962                                       "'Zd.'t, 'Ipc, mul #'u1916+1",
   4963                                       "'Zd.'t, 'Ipc",
   4964                                       "'Zd.'t");
   4965   FormatWithDecodedMnemonic(instr, form);
   4966 }
   4967 
   4968 void Disassembler::VisitSVEStoreMultipleStructures_ScalarPlusImm(
   4969     const Instruction *instr) {
   4970   const char *form = "{'Zt.'tmsz, 'Zt2.'tmsz}";
   4971   const char *form_3 = "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}";
   4972   const char *form_4 = "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}";
   4973   const char *suffix = ", 'Pgl, ['Xns'ISveSvl]";
   4974 
   4975   switch (form_hash_) {
   4976     case "st3b_z_p_bi_contiguous"_h:
   4977     case "st3h_z_p_bi_contiguous"_h:
   4978     case "st3w_z_p_bi_contiguous"_h:
   4979     case "st3d_z_p_bi_contiguous"_h:
   4980       form = form_3;
   4981       break;
   4982     case "st4b_z_p_bi_contiguous"_h:
   4983     case "st4h_z_p_bi_contiguous"_h:
   4984     case "st4w_z_p_bi_contiguous"_h:
   4985     case "st4d_z_p_bi_contiguous"_h:
   4986       form = form_4;
   4987       break;
   4988   }
   4989   FormatWithDecodedMnemonic(instr, form, suffix);
   4990 }
   4991 
   4992 void Disassembler::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
   4993     const Instruction *instr) {
   4994   const char *form = "{'Zt.'tmsz, 'Zt2.'tmsz}";
   4995   const char *form_3 = "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}";
   4996   const char *form_4 = "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}";
   4997   const char *suffix = ", 'Pgl, ['Xns, 'Xm'NSveS]";
   4998 
   4999   switch (form_hash_) {
   5000     case "st3b_z_p_br_contiguous"_h:
   5001     case "st3d_z_p_br_contiguous"_h:
   5002     case "st3h_z_p_br_contiguous"_h:
   5003     case "st3w_z_p_br_contiguous"_h:
   5004       form = form_3;
   5005       break;
   5006     case "st4b_z_p_br_contiguous"_h:
   5007     case "st4d_z_p_br_contiguous"_h:
   5008     case "st4h_z_p_br_contiguous"_h:
   5009     case "st4w_z_p_br_contiguous"_h:
   5010       form = form_4;
   5011       break;
   5012   }
   5013   FormatWithDecodedMnemonic(instr, form, suffix);
   5014 }
   5015 
   5016 void Disassembler::VisitSVEStorePredicateRegister(const Instruction *instr) {
   5017   const char *form = "'Pd, ['Xns, #'s2116:1210, mul vl]";
   5018   if (instr->Mask(0x003f1c00) == 0) {
   5019     form = "'Pd, ['Xns]";
   5020   }
   5021   FormatWithDecodedMnemonic(instr, form);
   5022 }
   5023 
   5024 void Disassembler::VisitSVEStoreVectorRegister(const Instruction *instr) {
   5025   const char *form = "'Zt, ['Xns, #'s2116:1210, mul vl]";
   5026   if (instr->Mask(0x003f1c00) == 0) {
   5027     form = "'Zd, ['Xns]";
   5028   }
   5029   FormatWithDecodedMnemonic(instr, form);
   5030 }
   5031 
   5032 void Disassembler::VisitSVETableLookup(const Instruction *instr) {
   5033   FormatWithDecodedMnemonic(instr, "'Zd.'t, {'Zn.'t}, 'Zm.'t");
   5034 }
   5035 
   5036 void Disassembler::VisitSVEUnpackPredicateElements(const Instruction *instr) {
   5037   FormatWithDecodedMnemonic(instr, "'Pd.h, 'Pn.b");
   5038 }
   5039 
   5040 void Disassembler::VisitSVEUnpackVectorElements(const Instruction *instr) {
   5041   if (instr->GetSVESize() == 0) {
   5042     // The lowest lane size of the destination vector is H-sized lane.
   5043     VisitUnallocated(instr);
   5044   } else {
   5045     FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'th");
   5046   }
   5047 }
   5048 
   5049 void Disassembler::VisitSVEVectorSplice(const Instruction *instr) {
   5050   FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl, 'Zd.'t, 'Zn.'t");
   5051 }
   5052 
   5053 void Disassembler::VisitSVEAddressGeneration(const Instruction *instr) {
   5054   const char *mnemonic = "adr";
   5055   const char *form = "'Zd.d, ['Zn.d, 'Zm.d";
   5056   const char *suffix = NULL;
   5057 
   5058   bool msz_is_zero = (instr->ExtractBits(11, 10) == 0);
   5059 
   5060   switch (instr->Mask(SVEAddressGenerationMask)) {
   5061     case ADR_z_az_d_s32_scaled:
   5062       suffix = msz_is_zero ? ", sxtw]" : ", sxtw #'u1110]";
   5063       break;
   5064     case ADR_z_az_d_u32_scaled:
   5065       suffix = msz_is_zero ? ", uxtw]" : ", uxtw #'u1110]";
   5066       break;
   5067     case ADR_z_az_s_same_scaled:
   5068     case ADR_z_az_d_same_scaled:
   5069       form = "'Zd.'t, ['Zn.'t, 'Zm.'t";
   5070       suffix = msz_is_zero ? "]" : ", lsl #'u1110]";
   5071       break;
   5072     default:
   5073       mnemonic = "unimplemented";
   5074       form = "(SVEAddressGeneration)";
   5075       break;
   5076   }
   5077   Format(instr, mnemonic, form, suffix);
   5078 }
   5079 
   5080 void Disassembler::VisitSVEBitwiseLogicalUnpredicated(
   5081     const Instruction *instr) {
   5082   const char *mnemonic = "unimplemented";
   5083   const char *form = "'Zd.d, 'Zn.d, 'Zm.d";
   5084 
   5085   switch (instr->Mask(SVEBitwiseLogicalUnpredicatedMask)) {
   5086     case AND_z_zz:
   5087       mnemonic = "and";
   5088       break;
   5089     case BIC_z_zz:
   5090       mnemonic = "bic";
   5091       break;
   5092     case EOR_z_zz:
   5093       mnemonic = "eor";
   5094       break;
   5095     case ORR_z_zz:
   5096       mnemonic = "orr";
   5097       if (instr->GetRn() == instr->GetRm()) {
   5098         mnemonic = "mov";
   5099         form = "'Zd.d, 'Zn.d";
   5100       }
   5101       break;
   5102     default:
   5103       break;
   5104   }
   5105   Format(instr, mnemonic, form);
   5106 }
   5107 
   5108 void Disassembler::VisitSVEBitwiseShiftUnpredicated(const Instruction *instr) {
   5109   const char *mnemonic = "unimplemented";
   5110   const char *form = "(SVEBitwiseShiftUnpredicated)";
   5111   unsigned tsize =
   5112       (instr->ExtractBits(23, 22) << 2) | instr->ExtractBits(20, 19);
   5113   unsigned lane_size = instr->GetSVESize();
   5114 
   5115   const char *suffix = NULL;
   5116   const char *form_i = "'Zd.'tszs, 'Zn.'tszs, ";
   5117 
   5118   switch (form_hash_) {
   5119     case "asr_z_zi"_h:
   5120     case "lsr_z_zi"_h:
   5121     case "sri_z_zzi"_h:
   5122     case "srsra_z_zi"_h:
   5123     case "ssra_z_zi"_h:
   5124     case "ursra_z_zi"_h:
   5125     case "usra_z_zi"_h:
   5126       if (tsize != 0) {
   5127         // The tsz field must not be zero.
   5128         mnemonic = mnemonic_.c_str();
   5129         form = form_i;
   5130         suffix = "'ITriSves";
   5131       }
   5132       break;
   5133     case "lsl_z_zi"_h:
   5134     case "sli_z_zzi"_h:
   5135       if (tsize != 0) {
   5136         // The tsz field must not be zero.
   5137         mnemonic = mnemonic_.c_str();
   5138         form = form_i;
   5139         suffix = "'ITriSver";
   5140       }
   5141       break;
   5142     case "asr_z_zw"_h:
   5143     case "lsl_z_zw"_h:
   5144     case "lsr_z_zw"_h:
   5145       if (lane_size <= kSRegSizeInBytesLog2) {
   5146         mnemonic = mnemonic_.c_str();
   5147         form = "'Zd.'t, 'Zn.'t, 'Zm.d";
   5148       }
   5149       break;
   5150     default:
   5151       break;
   5152   }
   5153 
   5154   Format(instr, mnemonic, form, suffix);
   5155 }
   5156 
   5157 void Disassembler::VisitSVEElementCount(const Instruction *instr) {
   5158   const char *form =
   5159       IncDecFormHelper(instr, "'Xd, 'Ipc, mul #'u1916+1", "'Xd, 'Ipc", "'Xd");
   5160   FormatWithDecodedMnemonic(instr, form);
   5161 }
   5162 
   5163 void Disassembler::VisitSVEFPAccumulatingReduction(const Instruction *instr) {
   5164   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   5165     VisitUnallocated(instr);
   5166   } else {
   5167     FormatWithDecodedMnemonic(instr, "'t'u0400, 'Pgl, 't'u0400, 'Zn.'t");
   5168   }
   5169 }
   5170 
   5171 void Disassembler::VisitSVEFPArithmeticUnpredicated(const Instruction *instr) {
   5172   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   5173     VisitUnallocated(instr);
   5174   } else {
   5175     FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'t, 'Zm.'t");
   5176   }
   5177 }
   5178 
   5179 void Disassembler::VisitSVEFPCompareVectors(const Instruction *instr) {
   5180   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   5181     VisitUnallocated(instr);
   5182   } else {
   5183     FormatWithDecodedMnemonic(instr, "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t");
   5184   }
   5185 }
   5186 
   5187 void Disassembler::VisitSVEFPCompareWithZero(const Instruction *instr) {
   5188   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   5189     VisitUnallocated(instr);
   5190   } else {
   5191     FormatWithDecodedMnemonic(instr, "'Pd.'t, 'Pgl/z, 'Zn.'t, #0.0");
   5192   }
   5193 }
   5194 
   5195 void Disassembler::VisitSVEFPComplexAddition(const Instruction *instr) {
   5196   // Bit 15 is always set, so this gives 90 * 1 or 3.
   5197   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t, #'u1615*90";
   5198   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   5199     VisitUnallocated(instr);
   5200   } else {
   5201     FormatWithDecodedMnemonic(instr, form);
   5202   }
   5203 }
   5204 
   5205 void Disassembler::VisitSVEFPComplexMulAdd(const Instruction *instr) {
   5206   const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t, 'Zm.'t, #'u1413*90";
   5207   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   5208     VisitUnallocated(instr);
   5209   } else {
   5210     FormatWithDecodedMnemonic(instr, form);
   5211   }
   5212 }
   5213 
   5214 void Disassembler::VisitSVEFPComplexMulAddIndex(const Instruction *instr) {
   5215   const char *form = "'Zd.h, 'Zn.h, z'u1816.h['u2019]";
   5216   const char *suffix = ", #'u1110*90";
   5217   switch (form_hash_) {
   5218     case "fcmla_z_zzzi_s"_h:
   5219       form = "'Zd.s, 'Zn.s, z'u1916.s['u2020]";
   5220       break;
   5221   }
   5222   FormatWithDecodedMnemonic(instr, form, suffix);
   5223 }
   5224 
   5225 void Disassembler::VisitSVEFPFastReduction(const Instruction *instr) {
   5226   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   5227     VisitUnallocated(instr);
   5228   } else {
   5229     FormatWithDecodedMnemonic(instr, "'t'u0400, 'Pgl, 'Zn.'t");
   5230   }
   5231 }
   5232 
   5233 void Disassembler::VisitSVEFPMulIndex(const Instruction *instr) {
   5234   const char *form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]";
   5235   switch (form_hash_) {
   5236     case "fmul_z_zzi_d"_h:
   5237       form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]";
   5238       break;
   5239     case "fmul_z_zzi_s"_h:
   5240       form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]";
   5241       break;
   5242   }
   5243   FormatWithDecodedMnemonic(instr, form);
   5244 }
   5245 
   5246 void Disassembler::VisitSVEFPMulAdd(const Instruction *instr) {
   5247   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   5248     VisitUnallocated(instr);
   5249   } else {
   5250     FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zn.'t, 'Zm.'t");
   5251   }
   5252 }
   5253 
   5254 void Disassembler::VisitSVEFPMulAddIndex(const Instruction *instr) {
   5255   const char *form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]";
   5256   switch (form_hash_) {
   5257     case "fmla_z_zzzi_s"_h:
   5258     case "fmls_z_zzzi_s"_h:
   5259       form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]";
   5260       break;
   5261     case "fmla_z_zzzi_d"_h:
   5262     case "fmls_z_zzzi_d"_h:
   5263       form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]";
   5264       break;
   5265   }
   5266   FormatWithDecodedMnemonic(instr, form);
   5267 }
   5268 
   5269 void Disassembler::VisitSVEFPUnaryOpUnpredicated(const Instruction *instr) {
   5270   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   5271     VisitUnallocated(instr);
   5272   } else {
   5273     FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'t");
   5274   }
   5275 }
   5276 
   5277 void Disassembler::VisitSVEIncDecByPredicateCount(const Instruction *instr) {
   5278   const char *form = "'Zd.'t, 'Pn";
   5279   switch (form_hash_) {
   5280     // <Xdn>, <Pg>.<T>
   5281     case "decp_r_p_r"_h:
   5282     case "incp_r_p_r"_h:
   5283       form = "'Xd, 'Pn.'t";
   5284       break;
   5285     // <Xdn>, <Pg>.<T>, <Wdn>
   5286     case "sqdecp_r_p_r_sx"_h:
   5287     case "sqincp_r_p_r_sx"_h:
   5288       form = "'Xd, 'Pn.'t, 'Wd";
   5289       break;
   5290     // <Xdn>, <Pg>.<T>
   5291     case "sqdecp_r_p_r_x"_h:
   5292     case "sqincp_r_p_r_x"_h:
   5293     case "uqdecp_r_p_r_x"_h:
   5294     case "uqincp_r_p_r_x"_h:
   5295       form = "'Xd, 'Pn.'t";
   5296       break;
   5297     // <Wdn>, <Pg>.<T>
   5298     case "uqdecp_r_p_r_uw"_h:
   5299     case "uqincp_r_p_r_uw"_h:
   5300       form = "'Wd, 'Pn.'t";
   5301       break;
   5302   }
   5303   FormatWithDecodedMnemonic(instr, form);
   5304 }
   5305 
   5306 void Disassembler::VisitSVEIndexGeneration(const Instruction *instr) {
   5307   const char *form = "'Zd.'t, #'s0905, #'s2016";
   5308   bool w_inputs =
   5309       static_cast<unsigned>(instr->GetSVESize()) <= kWRegSizeInBytesLog2;
   5310 
   5311   switch (form_hash_) {
   5312     case "index_z_ir"_h:
   5313       form = w_inputs ? "'Zd.'t, #'s0905, 'Wm" : "'Zd.'t, #'s0905, 'Xm";
   5314       break;
   5315     case "index_z_ri"_h:
   5316       form = w_inputs ? "'Zd.'t, 'Wn, #'s2016" : "'Zd.'t, 'Xn, #'s2016";
   5317       break;
   5318     case "index_z_rr"_h:
   5319       form = w_inputs ? "'Zd.'t, 'Wn, 'Wm" : "'Zd.'t, 'Xn, 'Xm";
   5320       break;
   5321   }
   5322   FormatWithDecodedMnemonic(instr, form);
   5323 }
   5324 
   5325 void Disassembler::VisitSVEIntArithmeticUnpredicated(const Instruction *instr) {
   5326   FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'t, 'Zm.'t");
   5327 }
   5328 
   5329 void Disassembler::VisitSVEIntCompareSignedImm(const Instruction *instr) {
   5330   FormatWithDecodedMnemonic(instr, "'Pd.'t, 'Pgl/z, 'Zn.'t, #'s2016");
   5331 }
   5332 
   5333 void Disassembler::VisitSVEIntCompareUnsignedImm(const Instruction *instr) {
   5334   FormatWithDecodedMnemonic(instr, "'Pd.'t, 'Pgl/z, 'Zn.'t, #'u2014");
   5335 }
   5336 
   5337 void Disassembler::VisitSVEIntCompareVectors(const Instruction *instr) {
   5338   const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.";
   5339   const char *suffix = "d";
   5340   switch (form_hash_) {
   5341     case "cmpeq_p_p_zz"_h:
   5342     case "cmpge_p_p_zz"_h:
   5343     case "cmpgt_p_p_zz"_h:
   5344     case "cmphi_p_p_zz"_h:
   5345     case "cmphs_p_p_zz"_h:
   5346     case "cmpne_p_p_zz"_h:
   5347       suffix = "'t";
   5348       break;
   5349   }
   5350   FormatWithDecodedMnemonic(instr, form, suffix);
   5351 }
   5352 
   5353 void Disassembler::VisitSVEIntMulAddPredicated(const Instruction *instr) {
   5354   const char *form = "'Zd.'t, 'Pgl/m, ";
   5355   const char *suffix = "'Zn.'t, 'Zm.'t";
   5356   switch (form_hash_) {
   5357     case "mad_z_p_zzz"_h:
   5358     case "msb_z_p_zzz"_h:
   5359       suffix = "'Zm.'t, 'Zn.'t";
   5360       break;
   5361   }
   5362   FormatWithDecodedMnemonic(instr, form, suffix);
   5363 }
   5364 
   5365 void Disassembler::VisitSVEIntMulAddUnpredicated(const Instruction *instr) {
   5366   if (static_cast<unsigned>(instr->GetSVESize()) >= kSRegSizeInBytesLog2) {
   5367     FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'tq, 'Zm.'tq");
   5368   } else {
   5369     VisitUnallocated(instr);
   5370   }
   5371 }
   5372 
   5373 void Disassembler::VisitSVEMovprfx(const Instruction *instr) {
   5374   FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/'?16:mz, 'Zn.'t");
   5375 }
   5376 
   5377 void Disassembler::VisitSVEIntReduction(const Instruction *instr) {
   5378   const char *form = "'Vdv, 'Pgl, 'Zn.'t";
   5379   switch (form_hash_) {
   5380     case "saddv_r_p_z"_h:
   5381     case "uaddv_r_p_z"_h:
   5382       form = "'Dd, 'Pgl, 'Zn.'t";
   5383       break;
   5384   }
   5385   FormatWithDecodedMnemonic(instr, form);
   5386 }
   5387 
   5388 void Disassembler::VisitSVEIntUnaryArithmeticPredicated(
   5389     const Instruction *instr) {
   5390   VectorFormat vform = instr->GetSVEVectorFormat();
   5391 
   5392   switch (form_hash_) {
   5393     case "sxtw_z_p_z"_h:
   5394     case "uxtw_z_p_z"_h:
   5395       if (vform == kFormatVnS) {
   5396         VisitUnallocated(instr);
   5397         return;
   5398       }
   5399       VIXL_FALLTHROUGH();
   5400     case "sxth_z_p_z"_h:
   5401     case "uxth_z_p_z"_h:
   5402       if (vform == kFormatVnH) {
   5403         VisitUnallocated(instr);
   5404         return;
   5405       }
   5406       VIXL_FALLTHROUGH();
   5407     case "sxtb_z_p_z"_h:
   5408     case "uxtb_z_p_z"_h:
   5409     case "fabs_z_p_z"_h:
   5410     case "fneg_z_p_z"_h:
   5411       if (vform == kFormatVnB) {
   5412         VisitUnallocated(instr);
   5413         return;
   5414       }
   5415       break;
   5416   }
   5417 
   5418   FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zn.'t");
   5419 }
   5420 
   5421 void Disassembler::VisitSVEMulIndex(const Instruction *instr) {
   5422   const char *form = "'Zd.s, 'Zn.b, z'u1816.b['u2019]";
   5423 
   5424   switch (form_hash_) {
   5425     case "sdot_z_zzzi_d"_h:
   5426     case "udot_z_zzzi_d"_h:
   5427       form = "'Zd.d, 'Zn.h, z'u1916.h['u2020]";
   5428       break;
   5429   }
   5430 
   5431   FormatWithDecodedMnemonic(instr, form);
   5432 }
   5433 
   5434 void Disassembler::VisitSVEPermuteVectorExtract(const Instruction *instr) {
   5435   FormatWithDecodedMnemonic(instr, "'Zd.b, 'Zd.b, 'Zn.b, #'u2016:1210");
   5436 }
   5437 
   5438 void Disassembler::VisitSVEPermuteVectorInterleaving(const Instruction *instr) {
   5439   FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'t, 'Zm.'t");
   5440 }
   5441 
   5442 void Disassembler::VisitSVEPredicateCount(const Instruction *instr) {
   5443   FormatWithDecodedMnemonic(instr, "'Xd, p'u1310, 'Pn.'t");
   5444 }
   5445 
   5446 void Disassembler::VisitSVEPredicateLogical(const Instruction *instr) {
   5447   const char *mnemonic = mnemonic_.c_str();
   5448   const char *form = "'Pd.b, p'u1310/z, 'Pn.b, 'Pm.b";
   5449 
   5450   int pd = instr->GetPd();
   5451   int pn = instr->GetPn();
   5452   int pm = instr->GetPm();
   5453   int pg = instr->ExtractBits(13, 10);
   5454 
   5455   switch (form_hash_) {
   5456     case "ands_p_p_pp_z"_h:
   5457       if (pn == pm) {
   5458         mnemonic = "movs";
   5459         form = "'Pd.b, p'u1310/z, 'Pn.b";
   5460       }
   5461       break;
   5462     case "and_p_p_pp_z"_h:
   5463       if (pn == pm) {
   5464         mnemonic = "mov";
   5465         form = "'Pd.b, p'u1310/z, 'Pn.b";
   5466       }
   5467       break;
   5468     case "eors_p_p_pp_z"_h:
   5469       if (pm == pg) {
   5470         mnemonic = "nots";
   5471         form = "'Pd.b, 'Pm/z, 'Pn.b";
   5472       }
   5473       break;
   5474     case "eor_p_p_pp_z"_h:
   5475       if (pm == pg) {
   5476         mnemonic = "not";
   5477         form = "'Pd.b, 'Pm/z, 'Pn.b";
   5478       }
   5479       break;
   5480     case "orrs_p_p_pp_z"_h:
   5481       if ((pn == pm) && (pn == pg)) {
   5482         mnemonic = "movs";
   5483         form = "'Pd.b, 'Pn.b";
   5484       }
   5485       break;
   5486     case "orr_p_p_pp_z"_h:
   5487       if ((pn == pm) && (pn == pg)) {
   5488         mnemonic = "mov";
   5489         form = "'Pd.b, 'Pn.b";
   5490       }
   5491       break;
   5492     case "sel_p_p_pp"_h:
   5493       if (pd == pm) {
   5494         mnemonic = "mov";
   5495         form = "'Pd.b, p'u1310/m, 'Pn.b";
   5496       } else {
   5497         form = "'Pd.b, p'u1310, 'Pn.b, 'Pm.b";
   5498       }
   5499       break;
   5500   }
   5501   Format(instr, mnemonic, form);
   5502 }
   5503 
   5504 void Disassembler::VisitSVEPredicateInitialize(const Instruction *instr) {
   5505   const char *form = "'Pd.'t, 'Ipc";
   5506   // Omit the pattern if it is the default ('ALL').
   5507   if (instr->ExtractBits(9, 5) == SVE_ALL) form = "'Pd.'t";
   5508   FormatWithDecodedMnemonic(instr, form);
   5509 }
   5510 
   5511 void Disassembler::VisitSVEPredicateNextActive(const Instruction *instr) {
   5512   FormatWithDecodedMnemonic(instr, "'Pd.'t, 'Pn, 'Pd.'t");
   5513 }
   5514 
   5515 void Disassembler::VisitSVEPredicateReadFromFFR_Predicated(
   5516     const Instruction *instr) {
   5517   FormatWithDecodedMnemonic(instr, "'Pd.b, 'Pn/z");
   5518 }
   5519 
   5520 void Disassembler::VisitSVEPropagateBreak(const Instruction *instr) {
   5521   FormatWithDecodedMnemonic(instr, "'Pd.b, p'u1310/z, 'Pn.b, 'Pm.b");
   5522 }
   5523 
   5524 void Disassembler::VisitSVEStackFrameAdjustment(const Instruction *instr) {
   5525   FormatWithDecodedMnemonic(instr, "'Xds, 'Xms, #'s1005");
   5526 }
   5527 
   5528 void Disassembler::VisitSVEStackFrameSize(const Instruction *instr) {
   5529   FormatWithDecodedMnemonic(instr, "'Xd, #'s1005");
   5530 }
   5531 
   5532 void Disassembler::VisitSVEVectorSelect(const Instruction *instr) {
   5533   const char *mnemonic = mnemonic_.c_str();
   5534   const char *form = "'Zd.'t, p'u1310, 'Zn.'t, 'Zm.'t";
   5535 
   5536   if (instr->GetRd() == instr->GetRm()) {
   5537     mnemonic = "mov";
   5538     form = "'Zd.'t, p'u1310/m, 'Zn.'t";
   5539   }
   5540 
   5541   Format(instr, mnemonic, form);
   5542 }
   5543 
   5544 void Disassembler::VisitSVEContiguousLoad_ScalarPlusImm(
   5545     const Instruction *instr) {
   5546   const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns";
   5547   const char *suffix =
   5548       (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]";
   5549   FormatWithDecodedMnemonic(instr, form, suffix);
   5550 }
   5551 
   5552 void Disassembler::VisitSVEContiguousLoad_ScalarPlusScalar(
   5553     const Instruction *instr) {
   5554   const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns, 'Xm";
   5555   const char *suffix = "]";
   5556 
   5557   switch (form_hash_) {
   5558     case "ld1h_z_p_br_u16"_h:
   5559     case "ld1h_z_p_br_u32"_h:
   5560     case "ld1h_z_p_br_u64"_h:
   5561     case "ld1w_z_p_br_u32"_h:
   5562     case "ld1w_z_p_br_u64"_h:
   5563     case "ld1d_z_p_br_u64"_h:
   5564       suffix = ", lsl #'u2423]";
   5565       break;
   5566     case "ld1sh_z_p_br_s32"_h:
   5567     case "ld1sh_z_p_br_s64"_h:
   5568       suffix = ", lsl #1]";
   5569       break;
   5570     case "ld1sw_z_p_br_s64"_h:
   5571       suffix = ", lsl #2]";
   5572       break;
   5573   }
   5574 
   5575   FormatWithDecodedMnemonic(instr, form, suffix);
   5576 }
   5577 
   5578 void Disassembler::VisitReserved(const Instruction *instr) {
   5579   // UDF is the only instruction in this group, and the Decoder is precise.
   5580   VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
   5581   Format(instr, "udf", "'IUdf");
   5582 }
   5583 
   5584 void Disassembler::VisitUnimplemented(const Instruction *instr) {
   5585   Format(instr, "unimplemented", "(Unimplemented)");
   5586 }
   5587 
   5588 
   5589 void Disassembler::VisitUnallocated(const Instruction *instr) {
   5590   Format(instr, "unallocated", "(Unallocated)");
   5591 }
   5592 
   5593 void Disassembler::Visit(Metadata *metadata, const Instruction *instr) {
   5594   VIXL_ASSERT(metadata->count("form") > 0);
   5595   const std::string &form = (*metadata)["form"];
   5596   form_hash_ = Hash(form.c_str());
   5597   const FormToVisitorFnMap *fv = Disassembler::GetFormToVisitorFnMap();
   5598   FormToVisitorFnMap::const_iterator it = fv->find(form_hash_);
   5599   if (it == fv->end()) {
   5600     VisitUnimplemented(instr);
   5601   } else {
   5602     SetMnemonicFromForm(form);
   5603     (it->second)(this, instr);
   5604   }
   5605 }
   5606 
   5607 void Disassembler::Disassemble_PdT_PgZ_ZnT_ZmT(const Instruction *instr) {
   5608   const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
   5609   VectorFormat vform = instr->GetSVEVectorFormat();
   5610 
   5611   if ((vform == kFormatVnS) || (vform == kFormatVnD)) {
   5612     Format(instr, "unimplemented", "(PdT_PgZ_ZnT_ZmT)");
   5613   } else {
   5614     Format(instr, mnemonic_.c_str(), form);
   5615   }
   5616 }
   5617 
   5618 void Disassembler::Disassemble_ZdB_Zn1B_Zn2B_imm(const Instruction *instr) {
   5619   const char *form = "'Zd.b, {'Zn.b, 'Zn2.b}, #'u2016:1210";
   5620   Format(instr, mnemonic_.c_str(), form);
   5621 }
   5622 
   5623 void Disassembler::Disassemble_ZdB_ZnB_ZmB(const Instruction *instr) {
   5624   const char *form = "'Zd.b, 'Zn.b, 'Zm.b";
   5625   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   5626     Format(instr, mnemonic_.c_str(), form);
   5627   } else {
   5628     Format(instr, "unimplemented", "(ZdB_ZnB_ZmB)");
   5629   }
   5630 }
   5631 
   5632 void Disassembler::Disassemble_ZdD_PgM_ZnS(const Instruction *instr) {
   5633   const char *form = "'Zd.d, 'Pgl/m, 'Zn.s";
   5634   Format(instr, mnemonic_.c_str(), form);
   5635 }
   5636 
   5637 void Disassembler::Disassemble_ZdD_ZnD_ZmD(const Instruction *instr) {
   5638   const char *form = "'Zd.d, 'Zn.d, 'Zm.d";
   5639   Format(instr, mnemonic_.c_str(), form);
   5640 }
   5641 
   5642 void Disassembler::Disassemble_ZdD_ZnD_ZmD_imm(const Instruction *instr) {
   5643   const char *form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]";
   5644   Format(instr, mnemonic_.c_str(), form);
   5645 }
   5646 
   5647 void Disassembler::Disassemble_ZdD_ZnS_ZmS_imm(const Instruction *instr) {
   5648   const char *form = "'Zd.d, 'Zn.s, z'u1916.s['u2020:1111]";
   5649   Format(instr, mnemonic_.c_str(), form);
   5650 }
   5651 
   5652 void Disassembler::Disassemble_ZdH_PgM_ZnS(const Instruction *instr) {
   5653   const char *form = "'Zd.h, 'Pgl/m, 'Zn.s";
   5654   Format(instr, mnemonic_.c_str(), form);
   5655 }
   5656 
   5657 void Disassembler::Disassemble_ZdH_ZnH_ZmH_imm(const Instruction *instr) {
   5658   const char *form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]";
   5659   Format(instr, mnemonic_.c_str(), form);
   5660 }
   5661 
   5662 void Disassembler::Disassemble_ZdS_PgM_ZnD(const Instruction *instr) {
   5663   const char *form = "'Zd.s, 'Pgl/m, 'Zn.d";
   5664   Format(instr, mnemonic_.c_str(), form);
   5665 }
   5666 
   5667 void Disassembler::Disassemble_ZdS_PgM_ZnH(const Instruction *instr) {
   5668   const char *form = "'Zd.s, 'Pgl/m, 'Zn.h";
   5669   Format(instr, mnemonic_.c_str(), form);
   5670 }
   5671 
   5672 void Disassembler::Disassemble_ZdS_PgM_ZnS(const Instruction *instr) {
   5673   const char *form = "'Zd.s, 'Pgl/m, 'Zn.s";
   5674   if (instr->GetSVEVectorFormat() == kFormatVnS) {
   5675     Format(instr, mnemonic_.c_str(), form);
   5676   } else {
   5677     Format(instr, "unimplemented", "(ZdS_PgM_ZnS)");
   5678   }
   5679 }
   5680 
   5681 void Disassembler::Disassemble_ZdS_ZnH_ZmH_imm(const Instruction *instr) {
   5682   const char *form = "'Zd.s, 'Zn.h, z'u1816.h['u2019:1111]";
   5683   Format(instr, mnemonic_.c_str(), form);
   5684 }
   5685 
   5686 void Disassembler::Disassemble_ZdS_ZnS_ZmS(const Instruction *instr) {
   5687   const char *form = "'Zd.s, 'Zn.s, 'Zm.s";
   5688   Format(instr, mnemonic_.c_str(), form);
   5689 }
   5690 
   5691 void Disassembler::Disassemble_ZdS_ZnS_ZmS_imm(const Instruction *instr) {
   5692   const char *form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]";
   5693   Format(instr, mnemonic_.c_str(), form);
   5694 }
   5695 
   5696 void Disassembler::DisassembleSVEFlogb(const Instruction *instr) {
   5697   const char *form = "'Zd.'tf, 'Pgl/m, 'Zn.'tf";
   5698   if (instr->GetSVEVectorFormat(17) == kFormatVnB) {
   5699     Format(instr, "unimplemented", "(SVEFlogb)");
   5700   } else {
   5701     Format(instr, mnemonic_.c_str(), form);
   5702   }
   5703 }
   5704 
   5705 void Disassembler::Disassemble_ZdT_PgM_ZnT(const Instruction *instr) {
   5706   const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t";
   5707   Format(instr, mnemonic_.c_str(), form);
   5708 }
   5709 
   5710 void Disassembler::Disassemble_ZdT_PgZ_ZnT_ZmT(const Instruction *instr) {
   5711   const char *form = "'Zd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
   5712   VectorFormat vform = instr->GetSVEVectorFormat();
   5713   if ((vform == kFormatVnS) || (vform == kFormatVnD)) {
   5714     Format(instr, mnemonic_.c_str(), form);
   5715   } else {
   5716     Format(instr, "unimplemented", "(ZdT_PgZ_ZnT_ZmT)");
   5717   }
   5718 }
   5719 
   5720 void Disassembler::Disassemble_ZdT_Pg_Zn1T_Zn2T(const Instruction *instr) {
   5721   const char *form = "'Zd.'t, 'Pgl, {'Zn.'t, 'Zn2.'t}";
   5722   Format(instr, mnemonic_.c_str(), form);
   5723 }
   5724 
   5725 void Disassembler::Disassemble_ZdT_Zn1T_Zn2T_ZmT(const Instruction *instr) {
   5726   const char *form = "'Zd.'t, {'Zn.'t, 'Zn2.'t}, 'Zm.'t";
   5727   Format(instr, mnemonic_.c_str(), form);
   5728 }
   5729 
   5730 void Disassembler::Disassemble_ZdT_ZnT_ZmT(const Instruction *instr) {
   5731   const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t";
   5732   Format(instr, mnemonic_.c_str(), form);
   5733 }
   5734 
   5735 void Disassembler::Disassemble_ZdT_ZnT_ZmTb(const Instruction *instr) {
   5736   const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'th";
   5737   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   5738     Format(instr, "unimplemented", "(ZdT_ZnT_ZmTb)");
   5739   } else {
   5740     Format(instr, mnemonic_.c_str(), form);
   5741   }
   5742 }
   5743 
   5744 void Disassembler::Disassemble_ZdT_ZnTb(const Instruction *instr) {
   5745   const char *form = "'Zd.'tszs, 'Zn.'tszd";
   5746   std::pair<int, int> shift_and_lane_size =
   5747       instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
   5748   int shift_dist = shift_and_lane_size.first;
   5749   int lane_size = shift_and_lane_size.second;
   5750   // Convert shift_dist from a right to left shift. Valid xtn instructions
   5751   // must have a left shift_dist equivalent of zero.
   5752   shift_dist = (8 << lane_size) - shift_dist;
   5753   if ((lane_size >= static_cast<int>(kBRegSizeInBytesLog2)) &&
   5754       (lane_size <= static_cast<int>(kSRegSizeInBytesLog2)) &&
   5755       (shift_dist == 0)) {
   5756     Format(instr, mnemonic_.c_str(), form);
   5757   } else {
   5758     Format(instr, "unimplemented", "(ZdT_ZnTb)");
   5759   }
   5760 }
   5761 
   5762 void Disassembler::Disassemble_ZdT_ZnTb_ZmTb(const Instruction *instr) {
   5763   const char *form = "'Zd.'t, 'Zn.'th, 'Zm.'th";
   5764   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   5765     // TODO: This is correct for saddlbt, ssublbt, subltb, which don't have
   5766     // b-lane sized form, and for pmull[b|t] as feature `SVEPmull128` isn't
   5767     // supported, but may need changes for other instructions reaching here.
   5768     Format(instr, "unimplemented", "(ZdT_ZnTb_ZmTb)");
   5769   } else {
   5770     Format(instr, mnemonic_.c_str(), form);
   5771   }
   5772 }
   5773 
   5774 void Disassembler::DisassembleSVEAddSubHigh(const Instruction *instr) {
   5775   const char *form = "'Zd.'th, 'Zn.'t, 'Zm.'t";
   5776   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   5777     Format(instr, "unimplemented", "(SVEAddSubHigh)");
   5778   } else {
   5779     Format(instr, mnemonic_.c_str(), form);
   5780   }
   5781 }
   5782 
   5783 void Disassembler::DisassembleSVEShiftLeftImm(const Instruction *instr) {
   5784   const char *form = "'Zd.'tszd, 'Zn.'tszs, 'ITriSver";
   5785   std::pair<int, int> shift_and_lane_size =
   5786       instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
   5787   int lane_size = shift_and_lane_size.second;
   5788   if ((lane_size >= static_cast<int>(kBRegSizeInBytesLog2)) &&
   5789       (lane_size <= static_cast<int>(kSRegSizeInBytesLog2))) {
   5790     Format(instr, mnemonic_.c_str(), form);
   5791   } else {
   5792     Format(instr, "unimplemented", "(SVEShiftLeftImm)");
   5793   }
   5794 }
   5795 
   5796 void Disassembler::DisassembleSVEShiftRightImm(const Instruction *instr) {
   5797   const char *form = "'Zd.'tszs, 'Zn.'tszd, 'ITriSves";
   5798   std::pair<int, int> shift_and_lane_size =
   5799       instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
   5800   int lane_size = shift_and_lane_size.second;
   5801   if ((lane_size >= static_cast<int>(kBRegSizeInBytesLog2)) &&
   5802       (lane_size <= static_cast<int>(kSRegSizeInBytesLog2))) {
   5803     Format(instr, mnemonic_.c_str(), form);
   5804   } else {
   5805     Format(instr, "unimplemented", "(SVEShiftRightImm)");
   5806   }
   5807 }
   5808 
   5809 void Disassembler::Disassemble_ZdaD_ZnD_ZmD_imm(const Instruction *instr) {
   5810   const char *form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]";
   5811   Format(instr, mnemonic_.c_str(), form);
   5812 }
   5813 
   5814 void Disassembler::Disassemble_ZdaD_ZnH_ZmH_imm_const(
   5815     const Instruction *instr) {
   5816   const char *form = "'Zd.d, 'Zn.h, z'u1916.h['u2020], #'u1110*90";
   5817   Format(instr, mnemonic_.c_str(), form);
   5818 }
   5819 
   5820 void Disassembler::Disassemble_ZdaD_ZnS_ZmS_imm(const Instruction *instr) {
   5821   const char *form = "'Zd.d, 'Zn.s, z'u1916.s['u2020:1111]";
   5822   Format(instr, mnemonic_.c_str(), form);
   5823 }
   5824 
   5825 void Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm(const Instruction *instr) {
   5826   const char *form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]";
   5827   Format(instr, mnemonic_.c_str(), form);
   5828 }
   5829 
   5830 void Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm_const(
   5831     const Instruction *instr) {
   5832   const char *form = "'Zd.h, 'Zn.h, z'u1816.h['u2019], #'u1110*90";
   5833   Format(instr, mnemonic_.c_str(), form);
   5834 }
   5835 
   5836 void Disassembler::Disassemble_ZdaS_ZnB_ZmB(const Instruction *instr) {
   5837   const char *form = "'Zd.s, 'Zn.b, 'Zm.b";
   5838   Format(instr, mnemonic_.c_str(), form);
   5839 }
   5840 
   5841 void Disassembler::Disassemble_ZdaS_ZnB_ZmB_imm_const(
   5842     const Instruction *instr) {
   5843   const char *form = "'Zd.s, 'Zn.b, z'u1816.b['u2019], #'u1110*90";
   5844   Format(instr, mnemonic_.c_str(), form);
   5845 }
   5846 
   5847 void Disassembler::Disassemble_ZdaS_ZnH_ZmH(const Instruction *instr) {
   5848   const char *form = "'Zd.s, 'Zn.h, 'Zm.h";
   5849   Format(instr, mnemonic_.c_str(), form);
   5850 }
   5851 
   5852 void Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm(const Instruction *instr) {
   5853   const char *form = "'Zd.s, 'Zn.h, z'u1816.h['u2019:1111]";
   5854   Format(instr, mnemonic_.c_str(), form);
   5855 }
   5856 
   5857 void Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm(const Instruction *instr) {
   5858   const char *form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]";
   5859   Format(instr, mnemonic_.c_str(), form);
   5860 }
   5861 
   5862 void Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm_const(
   5863     const Instruction *instr) {
   5864   const char *form = "'Zd.s, 'Zn.s, z'u1916.s['u2020], #'u1110*90";
   5865   Format(instr, mnemonic_.c_str(), form);
   5866 }
   5867 
   5868 void Disassembler::Disassemble_ZdaT_PgM_ZnTb(const Instruction *instr) {
   5869   const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'th";
   5870 
   5871   if (instr->GetSVESize() == 0) {
   5872     // The lowest lane size of the destination vector is H-sized lane.
   5873     Format(instr, "unimplemented", "(Disassemble_ZdaT_PgM_ZnTb)");
   5874     return;
   5875   }
   5876 
   5877   Format(instr, mnemonic_.c_str(), form);
   5878 }
   5879 
   5880 void Disassembler::DisassembleSVEAddSubCarry(const Instruction *instr) {
   5881   const char *form = "'Zd.'?22:ds, 'Zn.'?22:ds, 'Zm.'?22:ds";
   5882   Format(instr, mnemonic_.c_str(), form);
   5883 }
   5884 
   5885 void Disassembler::Disassemble_ZdaT_ZnT_ZmT(const Instruction *instr) {
   5886   const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t";
   5887   Format(instr, mnemonic_.c_str(), form);
   5888 }
   5889 
   5890 void Disassembler::Disassemble_ZdaT_ZnT_ZmT_const(const Instruction *instr) {
   5891   const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t, #'u1110*90";
   5892   Format(instr, mnemonic_.c_str(), form);
   5893 }
   5894 
   5895 void Disassembler::Disassemble_ZdaT_ZnTb_ZmTb(const Instruction *instr) {
   5896   const char *form = "'Zd.'t, 'Zn.'th, 'Zm.'th";
   5897   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   5898     Format(instr, "unimplemented", "(ZdaT_ZnTb_ZmTb)");
   5899   } else {
   5900     Format(instr, mnemonic_.c_str(), form);
   5901   }
   5902 }
   5903 
   5904 void Disassembler::Disassemble_ZdaT_ZnTb_ZmTb_const(const Instruction *instr) {
   5905   const char *form = "'Zd.'t, 'Zn.'tq, 'Zm.'tq, #'u1110*90";
   5906   VectorFormat vform = instr->GetSVEVectorFormat();
   5907 
   5908   if ((vform == kFormatVnB) || (vform == kFormatVnH)) {
   5909     Format(instr, "unimplemented", "(ZdaT_ZnTb_ZmTb_const)");
   5910   } else {
   5911     Format(instr, mnemonic_.c_str(), form);
   5912   }
   5913 }
   5914 
   5915 void Disassembler::Disassemble_ZdnB_ZdnB(const Instruction *instr) {
   5916   const char *form = "'Zd.b, 'Zd.b";
   5917   Format(instr, mnemonic_.c_str(), form);
   5918 }
   5919 
   5920 void Disassembler::Disassemble_ZdnB_ZdnB_ZmB(const Instruction *instr) {
   5921   const char *form = "'Zd.b, 'Zd.b, 'Zn.b";
   5922   Format(instr, mnemonic_.c_str(), form);
   5923 }
   5924 
   5925 void Disassembler::DisassembleSVEBitwiseTernary(const Instruction *instr) {
   5926   const char *form = "'Zd.d, 'Zd.d, 'Zm.d, 'Zn.d";
   5927   Format(instr, mnemonic_.c_str(), form);
   5928 }
   5929 
   5930 void Disassembler::Disassemble_ZdnS_ZdnS_ZmS(const Instruction *instr) {
   5931   const char *form = "'Zd.s, 'Zd.s, 'Zn.s";
   5932   Format(instr, mnemonic_.c_str(), form);
   5933 }
   5934 
   5935 void Disassembler::DisassembleSVEFPPair(const Instruction *instr) {
   5936   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
   5937   if (instr->GetSVEVectorFormat() == kFormatVnB) {
   5938     Format(instr, "unimplemented", "(SVEFPPair)");
   5939   } else {
   5940     Format(instr, mnemonic_.c_str(), form);
   5941   }
   5942 }
   5943 
   5944 void Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT(const Instruction *instr) {
   5945   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
   5946   Format(instr, mnemonic_.c_str(), form);
   5947 }
   5948 
   5949 void Disassembler::DisassembleSVEComplexIntAddition(const Instruction *instr) {
   5950   const char *form = "'Zd.'t, 'Zd.'t, 'Zn.'t, #";
   5951   const char *suffix = (instr->ExtractBit(10) == 0) ? "90" : "270";
   5952   Format(instr, mnemonic_.c_str(), form, suffix);
   5953 }
   5954 
   5955 void Disassembler::Disassemble_ZdnT_ZdnT_ZmT_const(const Instruction *instr) {
   5956   const char *form = "'Zd.'tszs, 'Zd.'tszs, 'Zn.'tszs, 'ITriSves";
   5957   unsigned tsize =
   5958       (instr->ExtractBits(23, 22) << 2) | instr->ExtractBits(20, 19);
   5959 
   5960   if (tsize == 0) {
   5961     Format(instr, "unimplemented", "(ZdnT_ZdnT_ZmT_const)");
   5962   } else {
   5963     Format(instr, mnemonic_.c_str(), form);
   5964   }
   5965 }
   5966 
   5967 void Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm(const Instruction *instr) {
   5968   const char *form = "{'Zt.d}, 'Pgl/z, ['Zn.d";
   5969   const char *suffix = instr->GetRm() == 31 ? "]" : ", 'Xm]";
   5970   Format(instr, mnemonic_.c_str(), form, suffix);
   5971 }
   5972 
   5973 void Disassembler::Disassemble_ZtD_Pg_ZnD_Xm(const Instruction *instr) {
   5974   const char *form = "{'Zt.d}, 'Pgl, ['Zn.d";
   5975   const char *suffix = instr->GetRm() == 31 ? "]" : ", 'Xm]";
   5976   Format(instr, mnemonic_.c_str(), form, suffix);
   5977 }
   5978 
   5979 void Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm(const Instruction *instr) {
   5980   const char *form = "{'Zt.s}, 'Pgl/z, ['Zn.s";
   5981   const char *suffix = instr->GetRm() == 31 ? "]" : ", 'Xm]";
   5982   Format(instr, mnemonic_.c_str(), form, suffix);
   5983 }
   5984 
   5985 void Disassembler::Disassemble_ZtS_Pg_ZnS_Xm(const Instruction *instr) {
   5986   const char *form = "{'Zt.s}, 'Pgl, ['Zn.s";
   5987   const char *suffix = instr->GetRm() == 31 ? "]" : ", 'Xm]";
   5988   Format(instr, mnemonic_.c_str(), form, suffix);
   5989 }
   5990 
   5991 void Disassembler::Disassemble_XdSP_XnSP_Xm(const Instruction *instr) {
   5992   const char *form = "'Xds, 'Xns";
   5993   const char *suffix = instr->GetRm() == 31 ? "" : ", 'Xm";
   5994   Format(instr, mnemonic_.c_str(), form, suffix);
   5995 }
   5996 
   5997 void Disassembler::Disassemble_XdSP_XnSP_uimm6_uimm4(const Instruction *instr) {
   5998   VIXL_STATIC_ASSERT(kMTETagGranuleInBytes == 16);
   5999   const char *form = "'Xds, 'Xns, #'u2116*16, #'u1310";
   6000   Format(instr, mnemonic_.c_str(), form);
   6001 }
   6002 
   6003 void Disassembler::Disassemble_Xd_XnSP_Xm(const Instruction *instr) {
   6004   const char *form = "'Rd, 'Xns, 'Rm";
   6005   Format(instr, mnemonic_.c_str(), form);
   6006 }
   6007 
   6008 void Disassembler::Disassemble_Xd_XnSP_XmSP(const Instruction *instr) {
   6009   if ((form_hash_ == Hash("subps_64s_dp_2src")) && (instr->GetRd() == 31)) {
   6010     Format(instr, "cmpp", "'Xns, 'Xms");
   6011   } else {
   6012     const char *form = "'Xd, 'Xns, 'Xms";
   6013     Format(instr, mnemonic_.c_str(), form);
   6014   }
   6015 }
   6016 
   6017 void Disassembler::DisassembleMTEStoreTagPair(const Instruction *instr) {
   6018   const char *form = "'Xt, 'Xt2, ['Xns";
   6019   const char *suffix = NULL;
   6020   switch (form_hash_) {
   6021     case Hash("stgp_64_ldstpair_off"):
   6022       suffix = ", #'s2115*16]";
   6023       break;
   6024     case Hash("stgp_64_ldstpair_post"):
   6025       suffix = "], #'s2115*16";
   6026       break;
   6027     case Hash("stgp_64_ldstpair_pre"):
   6028       suffix = ", #'s2115*16]!";
   6029       break;
   6030     default:
   6031       mnemonic_ = "unimplemented";
   6032       break;
   6033   }
   6034 
   6035   if (instr->GetImmLSPair() == 0) {
   6036     suffix = "]";
   6037   }
   6038 
   6039   Format(instr, mnemonic_.c_str(), form, suffix);
   6040 }
   6041 
   6042 void Disassembler::DisassembleMTEStoreTag(const Instruction *instr) {
   6043   const char *form = "'Xds, ['Xns";
   6044   const char *suffix = NULL;
   6045   switch (form_hash_) {
   6046     case Hash("st2g_64soffset_ldsttags"):
   6047     case Hash("stg_64soffset_ldsttags"):
   6048     case Hash("stz2g_64soffset_ldsttags"):
   6049     case Hash("stzg_64soffset_ldsttags"):
   6050       suffix = ", #'s2012*16]";
   6051       break;
   6052     case Hash("st2g_64spost_ldsttags"):
   6053     case Hash("stg_64spost_ldsttags"):
   6054     case Hash("stz2g_64spost_ldsttags"):
   6055     case Hash("stzg_64spost_ldsttags"):
   6056       suffix = "], #'s2012*16";
   6057       break;
   6058     case Hash("st2g_64spre_ldsttags"):
   6059     case Hash("stg_64spre_ldsttags"):
   6060     case Hash("stz2g_64spre_ldsttags"):
   6061     case Hash("stzg_64spre_ldsttags"):
   6062       suffix = ", #'s2012*16]!";
   6063       break;
   6064     default:
   6065       mnemonic_ = "unimplemented";
   6066       break;
   6067   }
   6068 
   6069   if (instr->GetImmLS() == 0) {
   6070     suffix = "]";
   6071   }
   6072 
   6073   Format(instr, mnemonic_.c_str(), form, suffix);
   6074 }
   6075 
   6076 void Disassembler::DisassembleMTELoadTag(const Instruction *instr) {
   6077   const char *form =
   6078       (instr->GetImmLS() == 0) ? "'Xt, ['Xns]" : "'Xt, ['Xns, #'s2012*16]";
   6079   Format(instr, mnemonic_.c_str(), form);
   6080 }
   6081 
   6082 void Disassembler::DisassembleCpy(const Instruction *instr) {
   6083   const char *form = "['Xd]!, ['Xs]!, 'Xn!";
   6084 
   6085   int d = instr->GetRd();
   6086   int n = instr->GetRn();
   6087   int s = instr->GetRs();
   6088 
   6089   // Aliased registers and sp/zr are disallowed.
   6090   if ((d == n) || (d == s) || (n == s) || (d == 31) || (n == 31) || (s == 31)) {
   6091     form = NULL;
   6092   }
   6093 
   6094   // Bits 31 and 30 must be zero.
   6095   if (instr->ExtractBits(31, 30)) {
   6096     form = NULL;
   6097   }
   6098 
   6099   Format(instr, mnemonic_.c_str(), form);
   6100 }
   6101 
   6102 void Disassembler::DisassembleSet(const Instruction *instr) {
   6103   const char *form = "['Xd]!, 'Xn!, 'Xs";
   6104 
   6105   int d = instr->GetRd();
   6106   int n = instr->GetRn();
   6107   int s = instr->GetRs();
   6108 
   6109   // Aliased registers are disallowed. Only Xs may be xzr.
   6110   if ((d == n) || (d == s) || (n == s) || (d == 31) || (n == 31)) {
   6111     form = NULL;
   6112   }
   6113 
   6114   // Bits 31 and 30 must be zero.
   6115   if (instr->ExtractBits(31, 30)) {
   6116     form = NULL;
   6117   }
   6118 
   6119   Format(instr, mnemonic_.c_str(), form);
   6120 }
   6121 
   6122 void Disassembler::ProcessOutput(const Instruction * /*instr*/) {
   6123   // The base disasm does nothing more than disassembling into a buffer.
   6124 }
   6125 
   6126 
   6127 void Disassembler::AppendRegisterNameToOutput(const Instruction *instr,
   6128                                               const CPURegister &reg) {
   6129   USE(instr);
   6130   VIXL_ASSERT(reg.IsValid());
   6131   char reg_char;
   6132 
   6133   if (reg.IsRegister()) {
   6134     reg_char = reg.Is64Bits() ? 'x' : 'w';
   6135   } else {
   6136     VIXL_ASSERT(reg.IsVRegister());
   6137     switch (reg.GetSizeInBits()) {
   6138       case kBRegSize:
   6139         reg_char = 'b';
   6140         break;
   6141       case kHRegSize:
   6142         reg_char = 'h';
   6143         break;
   6144       case kSRegSize:
   6145         reg_char = 's';
   6146         break;
   6147       case kDRegSize:
   6148         reg_char = 'd';
   6149         break;
   6150       default:
   6151         VIXL_ASSERT(reg.Is128Bits());
   6152         reg_char = 'q';
   6153     }
   6154   }
   6155 
   6156   if (reg.IsVRegister() || !(reg.Aliases(sp) || reg.Aliases(xzr))) {
   6157     // A core or scalar/vector register: [wx]0 - 30, [bhsdq]0 - 31.
   6158     AppendToOutput("%c%d", reg_char, reg.GetCode());
   6159   } else if (reg.Aliases(sp)) {
   6160     // Disassemble w31/x31 as stack pointer wsp/sp.
   6161     AppendToOutput("%s", reg.Is64Bits() ? "sp" : "wsp");
   6162   } else {
   6163     // Disassemble w31/x31 as zero register wzr/xzr.
   6164     AppendToOutput("%czr", reg_char);
   6165   }
   6166 }
   6167 
   6168 
   6169 void Disassembler::AppendPCRelativeOffsetToOutput(const Instruction *instr,
   6170                                                   int64_t offset) {
   6171   USE(instr);
   6172   if (offset < 0) {
   6173     // Cast to uint64_t so that INT64_MIN is handled in a well-defined way.
   6174     uint64_t abs_offset = UnsignedNegate(static_cast<uint64_t>(offset));
   6175     AppendToOutput("#-0x%" PRIx64, abs_offset);
   6176   } else {
   6177     AppendToOutput("#+0x%" PRIx64, offset);
   6178   }
   6179 }
   6180 
   6181 
   6182 void Disassembler::AppendAddressToOutput(const Instruction *instr,
   6183                                          const void *addr) {
   6184   USE(instr);
   6185   AppendToOutput("(addr 0x%" PRIxPTR ")", reinterpret_cast<uintptr_t>(addr));
   6186 }
   6187 
   6188 
   6189 void Disassembler::AppendCodeAddressToOutput(const Instruction *instr,
   6190                                              const void *addr) {
   6191   AppendAddressToOutput(instr, addr);
   6192 }
   6193 
   6194 
   6195 void Disassembler::AppendDataAddressToOutput(const Instruction *instr,
   6196                                              const void *addr) {
   6197   AppendAddressToOutput(instr, addr);
   6198 }
   6199 
   6200 
   6201 void Disassembler::AppendCodeRelativeAddressToOutput(const Instruction *instr,
   6202                                                      const void *addr) {
   6203   USE(instr);
   6204   int64_t rel_addr = CodeRelativeAddress(addr);
   6205   if (rel_addr >= 0) {
   6206     AppendToOutput("(addr 0x%" PRIx64 ")", rel_addr);
   6207   } else {
   6208     AppendToOutput("(addr -0x%" PRIx64 ")", -rel_addr);
   6209   }
   6210 }
   6211 
   6212 
   6213 void Disassembler::AppendCodeRelativeCodeAddressToOutput(
   6214     const Instruction *instr, const void *addr) {
   6215   AppendCodeRelativeAddressToOutput(instr, addr);
   6216 }
   6217 
   6218 
   6219 void Disassembler::AppendCodeRelativeDataAddressToOutput(
   6220     const Instruction *instr, const void *addr) {
   6221   AppendCodeRelativeAddressToOutput(instr, addr);
   6222 }
   6223 
   6224 
   6225 void Disassembler::MapCodeAddress(int64_t base_address,
   6226                                   const Instruction *instr_address) {
   6227   set_code_address_offset(base_address -
   6228                           reinterpret_cast<intptr_t>(instr_address));
   6229 }
   6230 int64_t Disassembler::CodeRelativeAddress(const void *addr) {
   6231   return reinterpret_cast<intptr_t>(addr) + code_address_offset();
   6232 }
   6233 
   6234 
   6235 void Disassembler::Format(const Instruction *instr,
   6236                           const char *mnemonic,
   6237                           const char *format0,
   6238                           const char *format1) {
   6239   if ((mnemonic == NULL) || (format0 == NULL)) {
   6240     VisitUnallocated(instr);
   6241   } else {
   6242     ResetOutput();
   6243     Substitute(instr, mnemonic);
   6244     if (format0[0] != 0) {  // Not a zero-length string.
   6245       VIXL_ASSERT(buffer_pos_ < buffer_size_);
   6246       buffer_[buffer_pos_++] = ' ';
   6247       Substitute(instr, format0);
   6248       // TODO: consider using a zero-length string here, too.
   6249       if (format1 != NULL) {
   6250         Substitute(instr, format1);
   6251       }
   6252     }
   6253     VIXL_ASSERT(buffer_pos_ < buffer_size_);
   6254     buffer_[buffer_pos_] = 0;
   6255     ProcessOutput(instr);
   6256   }
   6257 }
   6258 
   6259 void Disassembler::FormatWithDecodedMnemonic(const Instruction *instr,
   6260                                              const char *format0,
   6261                                              const char *format1) {
   6262   Format(instr, mnemonic_.c_str(), format0, format1);
   6263 }
   6264 
   6265 void Disassembler::Substitute(const Instruction *instr, const char *string) {
   6266   char chr = *string++;
   6267   while (chr != '\0') {
   6268     if (chr == '\'') {
   6269       string += SubstituteField(instr, string);
   6270     } else {
   6271       VIXL_ASSERT(buffer_pos_ < buffer_size_);
   6272       buffer_[buffer_pos_++] = chr;
   6273     }
   6274     chr = *string++;
   6275   }
   6276 }
   6277 
   6278 
   6279 int Disassembler::SubstituteField(const Instruction *instr,
   6280                                   const char *format) {
   6281   switch (format[0]) {
   6282     // NB. The remaining substitution prefix upper-case characters are: JU.
   6283     case 'R':  // Register. X or W, selected by sf (or alternative) bit.
   6284     case 'F':  // FP register. S or D, selected by type field.
   6285     case 'V':  // Vector register, V, vector format.
   6286     case 'Z':  // Scalable vector register.
   6287     case 'W':
   6288     case 'X':
   6289     case 'B':
   6290     case 'H':
   6291     case 'S':
   6292     case 'D':
   6293     case 'Q':
   6294       return SubstituteRegisterField(instr, format);
   6295     case 'P':
   6296       return SubstitutePredicateRegisterField(instr, format);
   6297     case 'I':
   6298       return SubstituteImmediateField(instr, format);
   6299     case 'L':
   6300       return SubstituteLiteralField(instr, format);
   6301     case 'N':
   6302       return SubstituteShiftField(instr, format);
   6303     case 'C':
   6304       return SubstituteConditionField(instr, format);
   6305     case 'E':
   6306       return SubstituteExtendField(instr, format);
   6307     case 'A':
   6308       return SubstitutePCRelAddressField(instr, format);
   6309     case 'T':
   6310       return SubstituteBranchTargetField(instr, format);
   6311     case 'O':
   6312       return SubstituteLSRegOffsetField(instr, format);
   6313     case 'M':
   6314       return SubstituteBarrierField(instr, format);
   6315     case 'K':
   6316       return SubstituteCrField(instr, format);
   6317     case 'G':
   6318       return SubstituteSysOpField(instr, format);
   6319     case 'p':
   6320       return SubstitutePrefetchField(instr, format);
   6321     case 'u':
   6322     case 's':
   6323       return SubstituteIntField(instr, format);
   6324     case 't':
   6325       return SubstituteSVESize(instr, format);
   6326     case '?':
   6327       return SubstituteTernary(instr, format);
   6328     default: {
   6329       VIXL_UNREACHABLE();
   6330       return 1;
   6331     }
   6332   }
   6333 }
   6334 
   6335 std::pair<unsigned, unsigned> Disassembler::GetRegNumForField(
   6336     const Instruction *instr, char reg_prefix, const char *field) {
   6337   unsigned reg_num = UINT_MAX;
   6338   unsigned field_len = 1;
   6339 
   6340   switch (field[0]) {
   6341     case 'd':
   6342       reg_num = instr->GetRd();
   6343       break;
   6344     case 'n':
   6345       reg_num = instr->GetRn();
   6346       break;
   6347     case 'm':
   6348       reg_num = instr->GetRm();
   6349       break;
   6350     case 'e':
   6351       // This is register Rm, but using a 4-bit specifier. Used in NEON
   6352       // by-element instructions.
   6353       reg_num = instr->GetRmLow16();
   6354       break;
   6355     case 'f':
   6356       // This is register Rm, but using an element size dependent number of bits
   6357       // in the register specifier.
   6358       reg_num =
   6359           (instr->GetNEONSize() < 2) ? instr->GetRmLow16() : instr->GetRm();
   6360       break;
   6361     case 'a':
   6362       reg_num = instr->GetRa();
   6363       break;
   6364     case 's':
   6365       reg_num = instr->GetRs();
   6366       break;
   6367     case 't':
   6368       reg_num = instr->GetRt();
   6369       break;
   6370     default:
   6371       VIXL_UNREACHABLE();
   6372   }
   6373 
   6374   switch (field[1]) {
   6375     case '2':
   6376     case '3':
   6377     case '4':
   6378       if ((reg_prefix == 'V') || (reg_prefix == 'Z')) {  // t2/3/4, n2/3/4
   6379         VIXL_ASSERT((field[0] == 't') || (field[0] == 'n'));
   6380         reg_num = (reg_num + field[1] - '1') % 32;
   6381         field_len++;
   6382       } else {
   6383         VIXL_ASSERT((field[0] == 't') && (field[1] == '2'));
   6384         reg_num = instr->GetRt2();
   6385         field_len++;
   6386       }
   6387       break;
   6388     case '+':  // Rt+, Rs+ (ie. Rt + 1, Rs + 1)
   6389       VIXL_ASSERT((reg_prefix == 'W') || (reg_prefix == 'X'));
   6390       VIXL_ASSERT((field[0] == 's') || (field[0] == 't'));
   6391       reg_num++;
   6392       field_len++;
   6393       break;
   6394     case 's':  // Core registers that are (w)sp rather than zr.
   6395       VIXL_ASSERT((reg_prefix == 'W') || (reg_prefix == 'X'));
   6396       reg_num = (reg_num == kZeroRegCode) ? kSPRegInternalCode : reg_num;
   6397       field_len++;
   6398       break;
   6399   }
   6400 
   6401   VIXL_ASSERT(reg_num != UINT_MAX);
   6402   return std::make_pair(reg_num, field_len);
   6403 }
   6404 
   6405 int Disassembler::SubstituteRegisterField(const Instruction *instr,
   6406                                           const char *format) {
   6407   unsigned field_len = 1;  // Initially, count only the first character.
   6408 
   6409   // The first character of the register format field, eg R, X, S, etc.
   6410   char reg_prefix = format[0];
   6411 
   6412   // Pointer to the character after the prefix. This may be one of the standard
   6413   // symbols representing a register encoding, or a two digit bit position,
   6414   // handled by the following code.
   6415   const char *reg_field = &format[1];
   6416 
   6417   if (reg_prefix == 'R') {
   6418     bool is_x = instr->GetSixtyFourBits() == 1;
   6419     if (strspn(reg_field, "0123456789") == 2) {  // r20d, r31n, etc.
   6420       // Core W or X registers where the type is determined by a specified bit
   6421       // position, eg. 'R20d, 'R05n. This is like the 'Rd syntax, where bit 31
   6422       // is implicitly used to select between W and X.
   6423       int bitpos = ((reg_field[0] - '0') * 10) + (reg_field[1] - '0');
   6424       VIXL_ASSERT(bitpos <= 31);
   6425       is_x = (instr->ExtractBit(bitpos) == 1);
   6426       reg_field = &format[3];
   6427       field_len += 2;
   6428     }
   6429     reg_prefix = is_x ? 'X' : 'W';
   6430   }
   6431 
   6432   std::pair<unsigned, unsigned> rn =
   6433       GetRegNumForField(instr, reg_prefix, reg_field);
   6434   unsigned reg_num = rn.first;
   6435   field_len += rn.second;
   6436 
   6437   if (reg_field[0] == 'm') {
   6438     switch (reg_field[1]) {
   6439       // Handle registers tagged with b (bytes), z (instruction), or
   6440       // r (registers), used for address updates in NEON load/store
   6441       // instructions.
   6442       case 'r':
   6443       case 'b':
   6444       case 'z': {
   6445         VIXL_ASSERT(reg_prefix == 'X');
   6446         field_len = 3;
   6447         char *eimm;
   6448         int imm = static_cast<int>(strtol(&reg_field[2], &eimm, 10));
   6449         field_len += static_cast<unsigned>(eimm - &reg_field[2]);
   6450         if (reg_num == 31) {
   6451           switch (reg_field[1]) {
   6452             case 'z':
   6453               imm *= (1 << instr->GetNEONLSSize());
   6454               break;
   6455             case 'r':
   6456               imm *= (instr->GetNEONQ() == 0) ? kDRegSizeInBytes
   6457                                               : kQRegSizeInBytes;
   6458               break;
   6459             case 'b':
   6460               break;
   6461           }
   6462           AppendToOutput("#%d", imm);
   6463           return field_len;
   6464         }
   6465         break;
   6466       }
   6467     }
   6468   }
   6469 
   6470   CPURegister::RegisterType reg_type = CPURegister::kRegister;
   6471   unsigned reg_size = kXRegSize;
   6472 
   6473   if (reg_prefix == 'F') {
   6474     switch (instr->GetFPType()) {
   6475       case 3:
   6476         reg_prefix = 'H';
   6477         break;
   6478       case 0:
   6479         reg_prefix = 'S';
   6480         break;
   6481       default:
   6482         reg_prefix = 'D';
   6483     }
   6484   }
   6485 
   6486   switch (reg_prefix) {
   6487     case 'W':
   6488       reg_type = CPURegister::kRegister;
   6489       reg_size = kWRegSize;
   6490       break;
   6491     case 'X':
   6492       reg_type = CPURegister::kRegister;
   6493       reg_size = kXRegSize;
   6494       break;
   6495     case 'B':
   6496       reg_type = CPURegister::kVRegister;
   6497       reg_size = kBRegSize;
   6498       break;
   6499     case 'H':
   6500       reg_type = CPURegister::kVRegister;
   6501       reg_size = kHRegSize;
   6502       break;
   6503     case 'S':
   6504       reg_type = CPURegister::kVRegister;
   6505       reg_size = kSRegSize;
   6506       break;
   6507     case 'D':
   6508       reg_type = CPURegister::kVRegister;
   6509       reg_size = kDRegSize;
   6510       break;
   6511     case 'Q':
   6512       reg_type = CPURegister::kVRegister;
   6513       reg_size = kQRegSize;
   6514       break;
   6515     case 'V':
   6516       if (reg_field[1] == 'v') {
   6517         reg_type = CPURegister::kVRegister;
   6518         reg_size = 1 << (instr->GetSVESize() + 3);
   6519         field_len++;
   6520         break;
   6521       }
   6522       AppendToOutput("v%d", reg_num);
   6523       return field_len;
   6524     case 'Z':
   6525       AppendToOutput("z%d", reg_num);
   6526       return field_len;
   6527     default:
   6528       VIXL_UNREACHABLE();
   6529   }
   6530 
   6531   AppendRegisterNameToOutput(instr, CPURegister(reg_num, reg_size, reg_type));
   6532 
   6533   return field_len;
   6534 }
   6535 
   6536 int Disassembler::SubstitutePredicateRegisterField(const Instruction *instr,
   6537                                                    const char *format) {
   6538   VIXL_ASSERT(format[0] == 'P');
   6539   switch (format[1]) {
   6540     // This field only supports P register that are always encoded in the same
   6541     // position.
   6542     case 'd':
   6543     case 't':
   6544       AppendToOutput("p%u", instr->GetPt());
   6545       break;
   6546     case 'n':
   6547       AppendToOutput("p%u", instr->GetPn());
   6548       break;
   6549     case 'm':
   6550       AppendToOutput("p%u", instr->GetPm());
   6551       break;
   6552     case 'g':
   6553       VIXL_ASSERT(format[2] == 'l');
   6554       AppendToOutput("p%u", instr->GetPgLow8());
   6555       return 3;
   6556     default:
   6557       VIXL_UNREACHABLE();
   6558   }
   6559   return 2;
   6560 }
   6561 
   6562 int Disassembler::SubstituteImmediateField(const Instruction *instr,
   6563                                            const char *format) {
   6564   VIXL_ASSERT(format[0] == 'I');
   6565 
   6566   switch (format[1]) {
   6567     case 'M': {  // IMoveImm, IMoveNeg or IMoveLSL.
   6568       if (format[5] == 'L') {
   6569         AppendToOutput("#0x%" PRIx32, instr->GetImmMoveWide());
   6570         if (instr->GetShiftMoveWide() > 0) {
   6571           AppendToOutput(", lsl #%" PRId32, 16 * instr->GetShiftMoveWide());
   6572         }
   6573       } else {
   6574         VIXL_ASSERT((format[5] == 'I') || (format[5] == 'N'));
   6575         uint64_t imm = static_cast<uint64_t>(instr->GetImmMoveWide())
   6576                        << (16 * instr->GetShiftMoveWide());
   6577         if (format[5] == 'N') imm = ~imm;
   6578         if (!instr->GetSixtyFourBits()) imm &= UINT64_C(0xffffffff);
   6579         AppendToOutput("#0x%" PRIx64, imm);
   6580       }
   6581       return 8;
   6582     }
   6583     case 'L': {
   6584       switch (format[2]) {
   6585         case 'L': {  // ILLiteral - Immediate Load Literal.
   6586           AppendToOutput("pc%+" PRId32,
   6587                          instr->GetImmLLiteral() *
   6588                              static_cast<int>(kLiteralEntrySize));
   6589           return 9;
   6590         }
   6591         case 'S': {  // ILS - Immediate Load/Store.
   6592                      // ILSi - As above, but an index field which must not be
   6593                      // omitted even if it is zero.
   6594           bool is_index = format[3] == 'i';
   6595           if (is_index || (instr->GetImmLS() != 0)) {
   6596             AppendToOutput(", #%" PRId32, instr->GetImmLS());
   6597           }
   6598           return is_index ? 4 : 3;
   6599         }
   6600         case 'P': {  // ILPx - Immediate Load/Store Pair, x = access size.
   6601                      // ILPxi - As above, but an index field which must not be
   6602                      // omitted even if it is zero.
   6603           VIXL_ASSERT((format[3] >= '0') && (format[3] <= '9'));
   6604           bool is_index = format[4] == 'i';
   6605           if (is_index || (instr->GetImmLSPair() != 0)) {
   6606             // format[3] is the scale value. Convert to a number.
   6607             int scale = 1 << (format[3] - '0');
   6608             AppendToOutput(", #%" PRId32, instr->GetImmLSPair() * scale);
   6609           }
   6610           return is_index ? 5 : 4;
   6611         }
   6612         case 'U': {  // ILU - Immediate Load/Store Unsigned.
   6613           if (instr->GetImmLSUnsigned() != 0) {
   6614             int shift = instr->GetSizeLS();
   6615             AppendToOutput(", #%" PRId32, instr->GetImmLSUnsigned() << shift);
   6616           }
   6617           return 3;
   6618         }
   6619         case 'A': {  // ILA - Immediate Load with pointer authentication.
   6620           if (instr->GetImmLSPAC() != 0) {
   6621             AppendToOutput(", #%" PRId32, instr->GetImmLSPAC());
   6622           }
   6623           return 3;
   6624         }
   6625         default: {
   6626           VIXL_UNIMPLEMENTED();
   6627           return 0;
   6628         }
   6629       }
   6630     }
   6631     case 'C': {  // ICondB - Immediate Conditional Branch.
   6632       int64_t offset = instr->GetImmCondBranch() << 2;
   6633       AppendPCRelativeOffsetToOutput(instr, offset);
   6634       return 6;
   6635     }
   6636     case 'A': {  // IAddSub.
   6637       int64_t imm = instr->GetImmAddSub() << (12 * instr->GetImmAddSubShift());
   6638       AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm);
   6639       return 7;
   6640     }
   6641     case 'F': {  // IFP, IFPNeon, IFPSve or IFPFBits.
   6642       int imm8 = 0;
   6643       size_t len = strlen("IFP");
   6644       switch (format[3]) {
   6645         case 'F':
   6646           VIXL_ASSERT(strncmp(format, "IFPFBits", strlen("IFPFBits")) == 0);
   6647           AppendToOutput("#%" PRId32, 64 - instr->GetFPScale());
   6648           return static_cast<int>(strlen("IFPFBits"));
   6649         case 'N':
   6650           VIXL_ASSERT(strncmp(format, "IFPNeon", strlen("IFPNeon")) == 0);
   6651           imm8 = instr->GetImmNEONabcdefgh();
   6652           len += strlen("Neon");
   6653           break;
   6654         case 'S':
   6655           VIXL_ASSERT(strncmp(format, "IFPSve", strlen("IFPSve")) == 0);
   6656           imm8 = instr->ExtractBits(12, 5);
   6657           len += strlen("Sve");
   6658           break;
   6659         default:
   6660           VIXL_ASSERT(strncmp(format, "IFP", strlen("IFP")) == 0);
   6661           imm8 = instr->GetImmFP();
   6662           break;
   6663       }
   6664       AppendToOutput("#0x%" PRIx32 " (%.4f)",
   6665                      imm8,
   6666                      Instruction::Imm8ToFP32(imm8));
   6667       return static_cast<int>(len);
   6668     }
   6669     case 'H': {  // IH - ImmHint
   6670       AppendToOutput("#%" PRId32, instr->GetImmHint());
   6671       return 2;
   6672     }
   6673     case 'T': {  // ITri - Immediate Triangular Encoded.
   6674       if (format[4] == 'S') {
   6675         VIXL_ASSERT((format[5] == 'v') && (format[6] == 'e'));
   6676         switch (format[7]) {
   6677           case 'l':
   6678             // SVE logical immediate encoding.
   6679             AppendToOutput("#0x%" PRIx64, instr->GetSVEImmLogical());
   6680             return 8;
   6681           case 'p': {
   6682             // SVE predicated shift immediate encoding, lsl.
   6683             std::pair<int, int> shift_and_lane_size =
   6684                 instr->GetSVEImmShiftAndLaneSizeLog2(
   6685                     /* is_predicated = */ true);
   6686             int lane_bits = 8 << shift_and_lane_size.second;
   6687             AppendToOutput("#%" PRId32, lane_bits - shift_and_lane_size.first);
   6688             return 8;
   6689           }
   6690           case 'q': {
   6691             // SVE predicated shift immediate encoding, asr and lsr.
   6692             std::pair<int, int> shift_and_lane_size =
   6693                 instr->GetSVEImmShiftAndLaneSizeLog2(
   6694                     /* is_predicated = */ true);
   6695             AppendToOutput("#%" PRId32, shift_and_lane_size.first);
   6696             return 8;
   6697           }
   6698           case 'r': {
   6699             // SVE unpredicated shift immediate encoding, left shifts.
   6700             std::pair<int, int> shift_and_lane_size =
   6701                 instr->GetSVEImmShiftAndLaneSizeLog2(
   6702                     /* is_predicated = */ false);
   6703             int lane_bits = 8 << shift_and_lane_size.second;
   6704             AppendToOutput("#%" PRId32, lane_bits - shift_and_lane_size.first);
   6705             return 8;
   6706           }
   6707           case 's': {
   6708             // SVE unpredicated shift immediate encoding, right shifts.
   6709             std::pair<int, int> shift_and_lane_size =
   6710                 instr->GetSVEImmShiftAndLaneSizeLog2(
   6711                     /* is_predicated = */ false);
   6712             AppendToOutput("#%" PRId32, shift_and_lane_size.first);
   6713             return 8;
   6714           }
   6715           default:
   6716             VIXL_UNREACHABLE();
   6717             return 0;
   6718         }
   6719       } else {
   6720         AppendToOutput("#0x%" PRIx64, instr->GetImmLogical());
   6721         return 4;
   6722       }
   6723     }
   6724     case 'N': {  // INzcv.
   6725       int nzcv = (instr->GetNzcv() << Flags_offset);
   6726       AppendToOutput("#%c%c%c%c",
   6727                      ((nzcv & NFlag) == 0) ? 'n' : 'N',
   6728                      ((nzcv & ZFlag) == 0) ? 'z' : 'Z',
   6729                      ((nzcv & CFlag) == 0) ? 'c' : 'C',
   6730                      ((nzcv & VFlag) == 0) ? 'v' : 'V');
   6731       return 5;
   6732     }
   6733     case 'P': {  // IP - Conditional compare.
   6734       AppendToOutput("#%" PRId32, instr->GetImmCondCmp());
   6735       return 2;
   6736     }
   6737     case 'B': {  // Bitfields.
   6738       return SubstituteBitfieldImmediateField(instr, format);
   6739     }
   6740     case 'E': {  // IExtract.
   6741       AppendToOutput("#%" PRId32, instr->GetImmS());
   6742       return 8;
   6743     }
   6744     case 't': {  // It - Test and branch bit.
   6745       AppendToOutput("#%" PRId32,
   6746                      (instr->GetImmTestBranchBit5() << 5) |
   6747                          instr->GetImmTestBranchBit40());
   6748       return 2;
   6749     }
   6750     case 'S': {  // ISveSvl - SVE 'mul vl' immediate for structured ld/st.
   6751       VIXL_ASSERT(strncmp(format, "ISveSvl", 7) == 0);
   6752       int imm = instr->ExtractSignedBits(19, 16);
   6753       if (imm != 0) {
   6754         int reg_count = instr->ExtractBits(22, 21) + 1;
   6755         AppendToOutput(", #%d, mul vl", imm * reg_count);
   6756       }
   6757       return 7;
   6758     }
   6759     case 's': {  // Is - Shift (immediate).
   6760       switch (format[2]) {
   6761         case 'R': {  // IsR - right shifts.
   6762           int shift = 16 << HighestSetBitPosition(instr->GetImmNEONImmh());
   6763           shift -= instr->GetImmNEONImmhImmb();
   6764           AppendToOutput("#%d", shift);
   6765           return 3;
   6766         }
   6767         case 'L': {  // IsL - left shifts.
   6768           int shift = instr->GetImmNEONImmhImmb();
   6769           shift -= 8 << HighestSetBitPosition(instr->GetImmNEONImmh());
   6770           AppendToOutput("#%d", shift);
   6771           return 3;
   6772         }
   6773         default: {
   6774           VIXL_UNIMPLEMENTED();
   6775           return 0;
   6776         }
   6777       }
   6778     }
   6779     case 'D': {  // IDebug - HLT and BRK instructions.
   6780       AppendToOutput("#0x%" PRIx32, instr->GetImmException());
   6781       return 6;
   6782     }
   6783     case 'U': {  // IUdf - UDF immediate.
   6784       AppendToOutput("#0x%" PRIx32, instr->GetImmUdf());
   6785       return 4;
   6786     }
   6787     case 'V': {  // Immediate Vector.
   6788       switch (format[2]) {
   6789         case 'E': {  // IVExtract.
   6790           AppendToOutput("#%" PRId32, instr->GetImmNEONExt());
   6791           return 9;
   6792         }
   6793         case 'B': {  // IVByElemIndex.
   6794           int ret = static_cast<int>(strlen("IVByElemIndex"));
   6795           uint32_t vm_index = instr->GetNEONH() << 2;
   6796           vm_index |= instr->GetNEONL() << 1;
   6797           vm_index |= instr->GetNEONM();
   6798 
   6799           static const char *format_rot = "IVByElemIndexRot";
   6800           static const char *format_fhm = "IVByElemIndexFHM";
   6801           if (strncmp(format, format_rot, strlen(format_rot)) == 0) {
   6802             // FCMLA uses 'H' bit index when SIZE is 2, else H:L
   6803             VIXL_ASSERT((instr->GetNEONSize() == 1) ||
   6804                         (instr->GetNEONSize() == 2));
   6805             vm_index >>= instr->GetNEONSize();
   6806             ret = static_cast<int>(strlen(format_rot));
   6807           } else if (strncmp(format, format_fhm, strlen(format_fhm)) == 0) {
   6808             // Nothing to do - FMLAL and FMLSL use H:L:M.
   6809             ret = static_cast<int>(strlen(format_fhm));
   6810           } else {
   6811             if (instr->GetNEONSize() == 2) {
   6812               // S-sized elements use H:L.
   6813               vm_index >>= 1;
   6814             } else if (instr->GetNEONSize() == 3) {
   6815               // D-sized elements use H.
   6816               vm_index >>= 2;
   6817             }
   6818           }
   6819           AppendToOutput("%d", vm_index);
   6820           return ret;
   6821         }
   6822         case 'I': {  // INS element.
   6823           if (strncmp(format, "IVInsIndex", strlen("IVInsIndex")) == 0) {
   6824             unsigned rd_index, rn_index;
   6825             unsigned imm5 = instr->GetImmNEON5();
   6826             unsigned imm4 = instr->GetImmNEON4();
   6827             int tz = CountTrailingZeros(imm5, 32);
   6828             if (tz <= 3) {  // Defined for tz = 0 to 3 only.
   6829               rd_index = imm5 >> (tz + 1);
   6830               rn_index = imm4 >> tz;
   6831               if (strncmp(format, "IVInsIndex1", strlen("IVInsIndex1")) == 0) {
   6832                 AppendToOutput("%d", rd_index);
   6833                 return static_cast<int>(strlen("IVInsIndex1"));
   6834               } else if (strncmp(format,
   6835                                  "IVInsIndex2",
   6836                                  strlen("IVInsIndex2")) == 0) {
   6837                 AppendToOutput("%d", rn_index);
   6838                 return static_cast<int>(strlen("IVInsIndex2"));
   6839               }
   6840             }
   6841             return 0;
   6842           } else if (strncmp(format,
   6843                              "IVInsSVEIndex",
   6844                              strlen("IVInsSVEIndex")) == 0) {
   6845             std::pair<int, int> index_and_lane_size =
   6846                 instr->GetSVEPermuteIndexAndLaneSizeLog2();
   6847             AppendToOutput("%d", index_and_lane_size.first);
   6848             return static_cast<int>(strlen("IVInsSVEIndex"));
   6849           }
   6850           VIXL_FALLTHROUGH();
   6851         }
   6852         case 'L': {  // IVLSLane[0123] - suffix indicates access size shift.
   6853           AppendToOutput("%d", instr->GetNEONLSIndex(format[8] - '0'));
   6854           return 9;
   6855         }
   6856         case 'M': {  // Modified Immediate cases.
   6857           if (strncmp(format, "IVMIImm8", strlen("IVMIImm8")) == 0) {
   6858             uint64_t imm8 = instr->GetImmNEONabcdefgh();
   6859             AppendToOutput("#0x%" PRIx64, imm8);
   6860             return static_cast<int>(strlen("IVMIImm8"));
   6861           } else if (strncmp(format, "IVMIImm", strlen("IVMIImm")) == 0) {
   6862             uint64_t imm8 = instr->GetImmNEONabcdefgh();
   6863             uint64_t imm = 0;
   6864             for (int i = 0; i < 8; ++i) {
   6865               if (imm8 & (UINT64_C(1) << i)) {
   6866                 imm |= (UINT64_C(0xff) << (8 * i));
   6867               }
   6868             }
   6869             AppendToOutput("#0x%" PRIx64, imm);
   6870             return static_cast<int>(strlen("IVMIImm"));
   6871           } else if (strncmp(format,
   6872                              "IVMIShiftAmt1",
   6873                              strlen("IVMIShiftAmt1")) == 0) {
   6874             int cmode = instr->GetNEONCmode();
   6875             int shift_amount = 8 * ((cmode >> 1) & 3);
   6876             AppendToOutput("#%d", shift_amount);
   6877             return static_cast<int>(strlen("IVMIShiftAmt1"));
   6878           } else if (strncmp(format,
   6879                              "IVMIShiftAmt2",
   6880                              strlen("IVMIShiftAmt2")) == 0) {
   6881             int cmode = instr->GetNEONCmode();
   6882             int shift_amount = 8 << (cmode & 1);
   6883             AppendToOutput("#%d", shift_amount);
   6884             return static_cast<int>(strlen("IVMIShiftAmt2"));
   6885           } else {
   6886             VIXL_UNIMPLEMENTED();
   6887             return 0;
   6888           }
   6889         }
   6890         default: {
   6891           VIXL_UNIMPLEMENTED();
   6892           return 0;
   6893         }
   6894       }
   6895     }
   6896     case 'X': {  // IX - CLREX instruction.
   6897       AppendToOutput("#0x%" PRIx32, instr->GetCRm());
   6898       return 2;
   6899     }
   6900     case 'Y': {  // IY - system register immediate.
   6901       switch (instr->GetImmSystemRegister()) {
   6902         case NZCV:
   6903           AppendToOutput("nzcv");
   6904           break;
   6905         case FPCR:
   6906           AppendToOutput("fpcr");
   6907           break;
   6908         case RNDR:
   6909           AppendToOutput("rndr");
   6910           break;
   6911         case RNDRRS:
   6912           AppendToOutput("rndrrs");
   6913           break;
   6914         default:
   6915           AppendToOutput("S%d_%d_c%d_c%d_%d",
   6916                          instr->GetSysOp0(),
   6917                          instr->GetSysOp1(),
   6918                          instr->GetCRn(),
   6919                          instr->GetCRm(),
   6920                          instr->GetSysOp2());
   6921           break;
   6922       }
   6923       return 2;
   6924     }
   6925     case 'R': {  // IR - Rotate right into flags.
   6926       switch (format[2]) {
   6927         case 'r': {  // IRr - Rotate amount.
   6928           AppendToOutput("#%d", instr->GetImmRMIFRotation());
   6929           return 3;
   6930         }
   6931         default: {
   6932           VIXL_UNIMPLEMENTED();
   6933           return 0;
   6934         }
   6935       }
   6936     }
   6937     case 'p': {  // Ipc - SVE predicate constraint specifier.
   6938       VIXL_ASSERT(format[2] == 'c');
   6939       unsigned pattern = instr->GetImmSVEPredicateConstraint();
   6940       switch (pattern) {
   6941         // VL1-VL8 are encoded directly.
   6942         case SVE_VL1:
   6943         case SVE_VL2:
   6944         case SVE_VL3:
   6945         case SVE_VL4:
   6946         case SVE_VL5:
   6947         case SVE_VL6:
   6948         case SVE_VL7:
   6949         case SVE_VL8:
   6950           AppendToOutput("vl%u", pattern);
   6951           break;
   6952         // VL16-VL256 are encoded as log2(N) + c.
   6953         case SVE_VL16:
   6954         case SVE_VL32:
   6955         case SVE_VL64:
   6956         case SVE_VL128:
   6957         case SVE_VL256:
   6958           AppendToOutput("vl%u", 16 << (pattern - SVE_VL16));
   6959           break;
   6960         // Special cases.
   6961         case SVE_POW2:
   6962           AppendToOutput("pow2");
   6963           break;
   6964         case SVE_MUL4:
   6965           AppendToOutput("mul4");
   6966           break;
   6967         case SVE_MUL3:
   6968           AppendToOutput("mul3");
   6969           break;
   6970         case SVE_ALL:
   6971           AppendToOutput("all");
   6972           break;
   6973         default:
   6974           AppendToOutput("#0x%x", pattern);
   6975           break;
   6976       }
   6977       return 3;
   6978     }
   6979     default: {
   6980       VIXL_UNIMPLEMENTED();
   6981       return 0;
   6982     }
   6983   }
   6984 }
   6985 
   6986 
   6987 int Disassembler::SubstituteBitfieldImmediateField(const Instruction *instr,
   6988                                                    const char *format) {
   6989   VIXL_ASSERT((format[0] == 'I') && (format[1] == 'B'));
   6990   unsigned r = instr->GetImmR();
   6991   unsigned s = instr->GetImmS();
   6992 
   6993   switch (format[2]) {
   6994     case 'r': {  // IBr.
   6995       AppendToOutput("#%d", r);
   6996       return 3;
   6997     }
   6998     case 's': {  // IBs+1 or IBs-r+1.
   6999       if (format[3] == '+') {
   7000         AppendToOutput("#%d", s + 1);
   7001         return 5;
   7002       } else {
   7003         VIXL_ASSERT(format[3] == '-');
   7004         AppendToOutput("#%d", s - r + 1);
   7005         return 7;
   7006       }
   7007     }
   7008     case 'Z': {  // IBZ-r.
   7009       VIXL_ASSERT((format[3] == '-') && (format[4] == 'r'));
   7010       unsigned reg_size =
   7011           (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
   7012       AppendToOutput("#%d", reg_size - r);
   7013       return 5;
   7014     }
   7015     default: {
   7016       VIXL_UNREACHABLE();
   7017       return 0;
   7018     }
   7019   }
   7020 }
   7021 
   7022 
   7023 int Disassembler::SubstituteLiteralField(const Instruction *instr,
   7024                                          const char *format) {
   7025   VIXL_ASSERT(strncmp(format, "LValue", 6) == 0);
   7026   USE(format);
   7027 
   7028   const void *address = instr->GetLiteralAddress<const void *>();
   7029   switch (instr->Mask(LoadLiteralMask)) {
   7030     case LDR_w_lit:
   7031     case LDR_x_lit:
   7032     case LDRSW_x_lit:
   7033     case LDR_s_lit:
   7034     case LDR_d_lit:
   7035     case LDR_q_lit:
   7036       AppendCodeRelativeDataAddressToOutput(instr, address);
   7037       break;
   7038     case PRFM_lit: {
   7039       // Use the prefetch hint to decide how to print the address.
   7040       switch (instr->GetPrefetchHint()) {
   7041         case 0x0:  // PLD: prefetch for load.
   7042         case 0x2:  // PST: prepare for store.
   7043           AppendCodeRelativeDataAddressToOutput(instr, address);
   7044           break;
   7045         case 0x1:  // PLI: preload instructions.
   7046           AppendCodeRelativeCodeAddressToOutput(instr, address);
   7047           break;
   7048         case 0x3:  // Unallocated hint.
   7049           AppendCodeRelativeAddressToOutput(instr, address);
   7050           break;
   7051       }
   7052       break;
   7053     }
   7054     default:
   7055       VIXL_UNREACHABLE();
   7056   }
   7057 
   7058   return 6;
   7059 }
   7060 
   7061 
   7062 int Disassembler::SubstituteShiftField(const Instruction *instr,
   7063                                        const char *format) {
   7064   VIXL_ASSERT(format[0] == 'N');
   7065   VIXL_ASSERT(instr->GetShiftDP() <= 0x3);
   7066 
   7067   switch (format[1]) {
   7068     case 'D': {  // NDP.
   7069       VIXL_ASSERT(instr->GetShiftDP() != ROR);
   7070       VIXL_FALLTHROUGH();
   7071     }
   7072     case 'L': {  // NLo.
   7073       if (instr->GetImmDPShift() != 0) {
   7074         const char *shift_type[] = {"lsl", "lsr", "asr", "ror"};
   7075         AppendToOutput(", %s #%" PRId32,
   7076                        shift_type[instr->GetShiftDP()],
   7077                        instr->GetImmDPShift());
   7078       }
   7079       return 3;
   7080     }
   7081     case 'S': {  // NSveS (SVE structured load/store indexing shift).
   7082       VIXL_ASSERT(strncmp(format, "NSveS", 5) == 0);
   7083       int msz = instr->ExtractBits(24, 23);
   7084       if (msz > 0) {
   7085         AppendToOutput(", lsl #%d", msz);
   7086       }
   7087       return 5;
   7088     }
   7089     default:
   7090       VIXL_UNIMPLEMENTED();
   7091       return 0;
   7092   }
   7093 }
   7094 
   7095 
   7096 int Disassembler::SubstituteConditionField(const Instruction *instr,
   7097                                            const char *format) {
   7098   VIXL_ASSERT(format[0] == 'C');
   7099   const char *condition_code[] = {"eq",
   7100                                   "ne",
   7101                                   "hs",
   7102                                   "lo",
   7103                                   "mi",
   7104                                   "pl",
   7105                                   "vs",
   7106                                   "vc",
   7107                                   "hi",
   7108                                   "ls",
   7109                                   "ge",
   7110                                   "lt",
   7111                                   "gt",
   7112                                   "le",
   7113                                   "al",
   7114                                   "nv"};
   7115   int cond;
   7116   switch (format[1]) {
   7117     case 'B':
   7118       cond = instr->GetConditionBranch();
   7119       break;
   7120     case 'I': {
   7121       cond = InvertCondition(static_cast<Condition>(instr->GetCondition()));
   7122       break;
   7123     }
   7124     default:
   7125       cond = instr->GetCondition();
   7126   }
   7127   AppendToOutput("%s", condition_code[cond]);
   7128   return 4;
   7129 }
   7130 
   7131 
   7132 int Disassembler::SubstitutePCRelAddressField(const Instruction *instr,
   7133                                               const char *format) {
   7134   VIXL_ASSERT((strcmp(format, "AddrPCRelByte") == 0) ||  // Used by `adr`.
   7135               (strcmp(format, "AddrPCRelPage") == 0));   // Used by `adrp`.
   7136 
   7137   int64_t offset = instr->GetImmPCRel();
   7138 
   7139   // Compute the target address based on the effective address (after applying
   7140   // code_address_offset). This is required for correct behaviour of adrp.
   7141   const Instruction *base = instr + code_address_offset();
   7142   if (format[9] == 'P') {
   7143     offset *= kPageSize;
   7144     base = AlignDown(base, kPageSize);
   7145   }
   7146   // Strip code_address_offset before printing, so we can use the
   7147   // semantically-correct AppendCodeRelativeAddressToOutput.
   7148   const void *target =
   7149       reinterpret_cast<const void *>(base + offset - code_address_offset());
   7150 
   7151   AppendPCRelativeOffsetToOutput(instr, offset);
   7152   AppendToOutput(" ");
   7153   AppendCodeRelativeAddressToOutput(instr, target);
   7154   return 13;
   7155 }
   7156 
   7157 
   7158 int Disassembler::SubstituteBranchTargetField(const Instruction *instr,
   7159                                               const char *format) {
   7160   VIXL_ASSERT(strncmp(format, "TImm", 4) == 0);
   7161 
   7162   int64_t offset = 0;
   7163   switch (format[5]) {
   7164     // BImmUncn - unconditional branch immediate.
   7165     case 'n':
   7166       offset = instr->GetImmUncondBranch();
   7167       break;
   7168     // BImmCond - conditional branch immediate.
   7169     case 'o':
   7170       offset = instr->GetImmCondBranch();
   7171       break;
   7172     // BImmCmpa - compare and branch immediate.
   7173     case 'm':
   7174       offset = instr->GetImmCmpBranch();
   7175       break;
   7176     // BImmTest - test and branch immediate.
   7177     case 'e':
   7178       offset = instr->GetImmTestBranch();
   7179       break;
   7180     default:
   7181       VIXL_UNIMPLEMENTED();
   7182   }
   7183   offset *= static_cast<int>(kInstructionSize);
   7184   const void *target_address = reinterpret_cast<const void *>(instr + offset);
   7185   VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
   7186 
   7187   AppendPCRelativeOffsetToOutput(instr, offset);
   7188   AppendToOutput(" ");
   7189   AppendCodeRelativeCodeAddressToOutput(instr, target_address);
   7190 
   7191   return 8;
   7192 }
   7193 
   7194 
   7195 int Disassembler::SubstituteExtendField(const Instruction *instr,
   7196                                         const char *format) {
   7197   VIXL_ASSERT(strncmp(format, "Ext", 3) == 0);
   7198   VIXL_ASSERT(instr->GetExtendMode() <= 7);
   7199   USE(format);
   7200 
   7201   const char *extend_mode[] =
   7202       {"uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx"};
   7203 
   7204   // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit
   7205   // registers becomes lsl.
   7206   if (((instr->GetRd() == kZeroRegCode) || (instr->GetRn() == kZeroRegCode)) &&
   7207       (((instr->GetExtendMode() == UXTW) && (instr->GetSixtyFourBits() == 0)) ||
   7208        (instr->GetExtendMode() == UXTX))) {
   7209     if (instr->GetImmExtendShift() > 0) {
   7210       AppendToOutput(", lsl #%" PRId32, instr->GetImmExtendShift());
   7211     }
   7212   } else {
   7213     AppendToOutput(", %s", extend_mode[instr->GetExtendMode()]);
   7214     if (instr->GetImmExtendShift() > 0) {
   7215       AppendToOutput(" #%" PRId32, instr->GetImmExtendShift());
   7216     }
   7217   }
   7218   return 3;
   7219 }
   7220 
   7221 
   7222 int Disassembler::SubstituteLSRegOffsetField(const Instruction *instr,
   7223                                              const char *format) {
   7224   VIXL_ASSERT(strncmp(format, "Offsetreg", 9) == 0);
   7225   const char *extend_mode[] = {"undefined",
   7226                                "undefined",
   7227                                "uxtw",
   7228                                "lsl",
   7229                                "undefined",
   7230                                "undefined",
   7231                                "sxtw",
   7232                                "sxtx"};
   7233   USE(format);
   7234 
   7235   unsigned shift = instr->GetImmShiftLS();
   7236   Extend ext = static_cast<Extend>(instr->GetExtendMode());
   7237   char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x';
   7238 
   7239   unsigned rm = instr->GetRm();
   7240   if (rm == kZeroRegCode) {
   7241     AppendToOutput("%czr", reg_type);
   7242   } else {
   7243     AppendToOutput("%c%d", reg_type, rm);
   7244   }
   7245 
   7246   // Extend mode UXTX is an alias for shift mode LSL here.
   7247   if (!((ext == UXTX) && (shift == 0))) {
   7248     AppendToOutput(", %s", extend_mode[ext]);
   7249     if (shift != 0) {
   7250       AppendToOutput(" #%d", instr->GetSizeLS());
   7251     }
   7252   }
   7253   return 9;
   7254 }
   7255 
   7256 
   7257 int Disassembler::SubstitutePrefetchField(const Instruction *instr,
   7258                                           const char *format) {
   7259   VIXL_ASSERT(format[0] == 'p');
   7260   USE(format);
   7261 
   7262   bool is_sve =
   7263       (strncmp(format, "prefSVEOp", strlen("prefSVEOp")) == 0) ? true : false;
   7264   int placeholder_length = is_sve ? 9 : 6;
   7265   static const char *stream_options[] = {"keep", "strm"};
   7266 
   7267   auto get_hints = [](bool want_sve_hint) -> std::vector<std::string> {
   7268     static const std::vector<std::string> sve_hints = {"ld", "st"};
   7269     static const std::vector<std::string> core_hints = {"ld", "li", "st"};
   7270     return (want_sve_hint) ? sve_hints : core_hints;
   7271   };
   7272 
   7273   std::vector<std::string> hints = get_hints(is_sve);
   7274   unsigned hint =
   7275       is_sve ? instr->GetSVEPrefetchHint() : instr->GetPrefetchHint();
   7276   unsigned target = instr->GetPrefetchTarget() + 1;
   7277   unsigned stream = instr->GetPrefetchStream();
   7278 
   7279   if ((hint >= hints.size()) || (target > 3)) {
   7280     // Unallocated prefetch operations.
   7281     if (is_sve) {
   7282       std::bitset<4> prefetch_mode(instr->GetSVEImmPrefetchOperation());
   7283       AppendToOutput("#0b%s", prefetch_mode.to_string().c_str());
   7284     } else {
   7285       std::bitset<5> prefetch_mode(instr->GetImmPrefetchOperation());
   7286       AppendToOutput("#0b%s", prefetch_mode.to_string().c_str());
   7287     }
   7288   } else {
   7289     VIXL_ASSERT(stream < ArrayLength(stream_options));
   7290     AppendToOutput("p%sl%d%s",
   7291                    hints[hint].c_str(),
   7292                    target,
   7293                    stream_options[stream]);
   7294   }
   7295   return placeholder_length;
   7296 }
   7297 
   7298 int Disassembler::SubstituteBarrierField(const Instruction *instr,
   7299                                          const char *format) {
   7300   VIXL_ASSERT(format[0] == 'M');
   7301   USE(format);
   7302 
   7303   static const char *options[4][4] = {{"sy (0b0000)", "oshld", "oshst", "osh"},
   7304                                       {"sy (0b0100)", "nshld", "nshst", "nsh"},
   7305                                       {"sy (0b1000)", "ishld", "ishst", "ish"},
   7306                                       {"sy (0b1100)", "ld", "st", "sy"}};
   7307   int domain = instr->GetImmBarrierDomain();
   7308   int type = instr->GetImmBarrierType();
   7309 
   7310   AppendToOutput("%s", options[domain][type]);
   7311   return 1;
   7312 }
   7313 
   7314 int Disassembler::SubstituteSysOpField(const Instruction *instr,
   7315                                        const char *format) {
   7316   VIXL_ASSERT(format[0] == 'G');
   7317   int op = -1;
   7318   switch (format[1]) {
   7319     case '1':
   7320       op = instr->GetSysOp1();
   7321       break;
   7322     case '2':
   7323       op = instr->GetSysOp2();
   7324       break;
   7325     default:
   7326       VIXL_UNREACHABLE();
   7327   }
   7328   AppendToOutput("#%d", op);
   7329   return 2;
   7330 }
   7331 
   7332 int Disassembler::SubstituteCrField(const Instruction *instr,
   7333                                     const char *format) {
   7334   VIXL_ASSERT(format[0] == 'K');
   7335   int cr = -1;
   7336   switch (format[1]) {
   7337     case 'n':
   7338       cr = instr->GetCRn();
   7339       break;
   7340     case 'm':
   7341       cr = instr->GetCRm();
   7342       break;
   7343     default:
   7344       VIXL_UNREACHABLE();
   7345   }
   7346   AppendToOutput("C%d", cr);
   7347   return 2;
   7348 }
   7349 
   7350 int Disassembler::SubstituteIntField(const Instruction *instr,
   7351                                      const char *format) {
   7352   VIXL_ASSERT((format[0] == 'u') || (format[0] == 's'));
   7353 
   7354   // A generic signed or unsigned int field uses a placeholder of the form
   7355   // 'sAABB and 'uAABB respectively where AA and BB are two digit bit positions
   7356   // between 00 and 31, and AA >= BB. The placeholder is substituted with the
   7357   // decimal integer represented by the bits in the instruction between
   7358   // positions AA and BB inclusive.
   7359   //
   7360   // In addition, split fields can be represented using 'sAABB:CCDD, where CCDD
   7361   // become the least-significant bits of the result, and bit AA is the sign bit
   7362   // (if 's is used).
   7363   int32_t bits = 0;
   7364   int width = 0;
   7365   const char *c = format;
   7366   do {
   7367     c++;  // Skip the 'u', 's' or ':'.
   7368     VIXL_ASSERT(strspn(c, "0123456789") == 4);
   7369     int msb = ((c[0] - '0') * 10) + (c[1] - '0');
   7370     int lsb = ((c[2] - '0') * 10) + (c[3] - '0');
   7371     c += 4;  // Skip the characters we just read.
   7372     int chunk_width = msb - lsb + 1;
   7373     VIXL_ASSERT((chunk_width > 0) && (chunk_width < 32));
   7374     bits = (bits << chunk_width) | (instr->ExtractBits(msb, lsb));
   7375     width += chunk_width;
   7376   } while (*c == ':');
   7377   VIXL_ASSERT(IsUintN(width, bits));
   7378 
   7379   if (format[0] == 's') {
   7380     bits = ExtractSignedBitfield32(width - 1, 0, bits);
   7381   }
   7382 
   7383   if (*c == '+') {
   7384     // A "+n" trailing the format specifier indicates the extracted value should
   7385     // be incremented by n. This is for cases where the encoding is zero-based,
   7386     // but range of values is not, eg. values [1, 16] encoded as [0, 15]
   7387     char *new_c;
   7388     uint64_t value = strtoul(c + 1, &new_c, 10);
   7389     c = new_c;
   7390     VIXL_ASSERT(IsInt32(value));
   7391     bits = static_cast<int32_t>(bits + value);
   7392   } else if (*c == '*') {
   7393     // Similarly, a "*n" trailing the format specifier indicates the extracted
   7394     // value should be multiplied by n. This is for cases where the encoded
   7395     // immediate is scaled, for example by access size.
   7396     char *new_c;
   7397     uint64_t value = strtoul(c + 1, &new_c, 10);
   7398     c = new_c;
   7399     VIXL_ASSERT(IsInt32(value));
   7400     bits = static_cast<int32_t>(bits * value);
   7401   }
   7402 
   7403   AppendToOutput("%d", bits);
   7404 
   7405   return static_cast<int>(c - format);
   7406 }
   7407 
   7408 int Disassembler::SubstituteSVESize(const Instruction *instr,
   7409                                     const char *format) {
   7410   USE(format);
   7411   VIXL_ASSERT(format[0] == 't');
   7412 
   7413   static const char sizes[] = {'b', 'h', 's', 'd', 'q'};
   7414   unsigned size_in_bytes_log2 = instr->GetSVESize();
   7415   int placeholder_length = 1;
   7416   switch (format[1]) {
   7417     case 'f':  // 'tf - FP size encoded in <18:17>
   7418       placeholder_length++;
   7419       size_in_bytes_log2 = instr->ExtractBits(18, 17);
   7420       break;
   7421     case 'l':
   7422       placeholder_length++;
   7423       if (format[2] == 's') {
   7424         // 'tls: Loads and stores
   7425         size_in_bytes_log2 = instr->ExtractBits(22, 21);
   7426         placeholder_length++;
   7427         if (format[3] == 's') {
   7428           // Sign extension load.
   7429           unsigned msize = instr->ExtractBits(24, 23);
   7430           if (msize > size_in_bytes_log2) size_in_bytes_log2 ^= 0x3;
   7431           placeholder_length++;
   7432         }
   7433       } else {
   7434         // 'tl: Logical operations
   7435         size_in_bytes_log2 = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
   7436       }
   7437       break;
   7438     case 'm':  // 'tmsz
   7439       VIXL_ASSERT(strncmp(format, "tmsz", 4) == 0);
   7440       placeholder_length += 3;
   7441       size_in_bytes_log2 = instr->ExtractBits(24, 23);
   7442       break;
   7443     case 'i': {  // 'ti: indices.
   7444       std::pair<int, int> index_and_lane_size =
   7445           instr->GetSVEPermuteIndexAndLaneSizeLog2();
   7446       placeholder_length++;
   7447       size_in_bytes_log2 = index_and_lane_size.second;
   7448       break;
   7449     }
   7450     case 's':
   7451       if (format[2] == 'z') {
   7452         VIXL_ASSERT((format[3] == 'p') || (format[3] == 's') ||
   7453                     (format[3] == 'd'));
   7454         bool is_predicated = (format[3] == 'p');
   7455         std::pair<int, int> shift_and_lane_size =
   7456             instr->GetSVEImmShiftAndLaneSizeLog2(is_predicated);
   7457         size_in_bytes_log2 = shift_and_lane_size.second;
   7458         if (format[3] == 'd') {  // Double size lanes.
   7459           size_in_bytes_log2++;
   7460         }
   7461         placeholder_length += 3;  // skip "sz(p|s|d)"
   7462       }
   7463       break;
   7464     case 'h':
   7465       // Half size of the lane size field.
   7466       size_in_bytes_log2 -= 1;
   7467       placeholder_length++;
   7468       break;
   7469     case 'q':
   7470       // Quarter size of the lane size field.
   7471       size_in_bytes_log2 -= 2;
   7472       placeholder_length++;
   7473       break;
   7474     default:
   7475       break;
   7476   }
   7477 
   7478   VIXL_ASSERT(size_in_bytes_log2 < ArrayLength(sizes));
   7479   AppendToOutput("%c", sizes[size_in_bytes_log2]);
   7480 
   7481   return placeholder_length;
   7482 }
   7483 
   7484 int Disassembler::SubstituteTernary(const Instruction *instr,
   7485                                     const char *format) {
   7486   VIXL_ASSERT((format[0] == '?') && (format[3] == ':'));
   7487 
   7488   // The ternary substitution of the format "'?bb:TF" is replaced by a single
   7489   // character, either T or F, depending on the value of the bit at position
   7490   // bb in the instruction. For example, "'?31:xw" is substituted with "x" if
   7491   // bit 31 is true, and "w" otherwise.
   7492   VIXL_ASSERT(strspn(&format[1], "0123456789") == 2);
   7493   char *c;
   7494   uint64_t value = strtoul(&format[1], &c, 10);
   7495   VIXL_ASSERT(value < (kInstructionSize * kBitsPerByte));
   7496   VIXL_ASSERT((*c == ':') && (strlen(c) >= 3));  // Minimum of ":TF"
   7497   c++;
   7498   AppendToOutput("%c", c[1 - instr->ExtractBit(static_cast<int>(value))]);
   7499   return 6;
   7500 }
   7501 
   7502 void Disassembler::ResetOutput() {
   7503   buffer_pos_ = 0;
   7504   buffer_[buffer_pos_] = 0;
   7505 }
   7506 
   7507 
   7508 void Disassembler::AppendToOutput(const char *format, ...) {
   7509   va_list args;
   7510   va_start(args, format);
   7511   buffer_pos_ += vsnprintf(&buffer_[buffer_pos_],
   7512                            buffer_size_ - buffer_pos_,
   7513                            format,
   7514                            args);
   7515   va_end(args);
   7516 }
   7517 
   7518 
   7519 void PrintDisassembler::Disassemble(const Instruction *instr) {
   7520   Decoder decoder;
   7521   if (cpu_features_auditor_ != NULL) {
   7522     decoder.AppendVisitor(cpu_features_auditor_);
   7523   }
   7524   decoder.AppendVisitor(this);
   7525   decoder.Decode(instr);
   7526 }
   7527 
   7528 void PrintDisassembler::DisassembleBuffer(const Instruction *start,
   7529                                           const Instruction *end) {
   7530   Decoder decoder;
   7531   if (cpu_features_auditor_ != NULL) {
   7532     decoder.AppendVisitor(cpu_features_auditor_);
   7533   }
   7534   decoder.AppendVisitor(this);
   7535   decoder.Decode(start, end);
   7536 }
   7537 
   7538 void PrintDisassembler::DisassembleBuffer(const Instruction *start,
   7539                                           uint64_t size) {
   7540   DisassembleBuffer(start, start + size);
   7541 }
   7542 
   7543 
   7544 void PrintDisassembler::ProcessOutput(const Instruction *instr) {
   7545   int64_t address = CodeRelativeAddress(instr);
   7546 
   7547   uint64_t abs_address;
   7548   const char *sign;
   7549   if (signed_addresses_) {
   7550     if (address < 0) {
   7551       sign = "-";
   7552       abs_address = UnsignedNegate(static_cast<uint64_t>(address));
   7553     } else {
   7554       // Leave a leading space, to maintain alignment.
   7555       sign = " ";
   7556       abs_address = address;
   7557     }
   7558   } else {
   7559     sign = "";
   7560     abs_address = address;
   7561   }
   7562 
   7563   int bytes_printed = fprintf(stream_,
   7564                               "%s0x%016" PRIx64 "  %08" PRIx32 "\t\t%s",
   7565                               sign,
   7566                               abs_address,
   7567                               instr->GetInstructionBits(),
   7568                               GetOutput());
   7569   if (cpu_features_auditor_ != NULL) {
   7570     CPUFeatures needs = cpu_features_auditor_->GetInstructionFeatures();
   7571     needs.Remove(cpu_features_auditor_->GetAvailableFeatures());
   7572     if (needs != CPUFeatures::None()) {
   7573       // Try to align annotations. This value is arbitrary, but based on looking
   7574       // good with most instructions. Note that, for historical reasons, the
   7575       // disassembly itself is printed with tab characters, so bytes_printed is
   7576       // _not_ equivalent to the number of occupied screen columns. However, the
   7577       // prefix before the tabs is always the same length, so the annotation
   7578       // indentation does not change from one line to the next.
   7579       const int indent_to = 70;
   7580       // Always allow some space between the instruction and the annotation.
   7581       const int min_pad = 2;
   7582 
   7583       int pad = std::max(min_pad, (indent_to - bytes_printed));
   7584       fprintf(stream_, "%*s", pad, "");
   7585 
   7586       std::stringstream features;
   7587       features << needs;
   7588       fprintf(stream_,
   7589               "%s%s%s",
   7590               cpu_features_prefix_,
   7591               features.str().c_str(),
   7592               cpu_features_suffix_);
   7593     }
   7594   }
   7595   fprintf(stream_, "\n");
   7596 }
   7597 
   7598 }  // namespace aarch64
   7599 }  // namespace vixl