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