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