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