• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 //   * Redistributions of source code must retain the above copyright notice,
8 //     this list of conditions and the following disclaimer.
9 //   * Redistributions in binary form must reproduce the above copyright notice,
10 //     this list of conditions and the following disclaimer in the documentation
11 //     and/or other materials provided with the distribution.
12 //   * Neither the name of ARM Limited nor the names of its contributors may be
13 //     used to endorse or promote products derived from this software without
14 //     specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #include <array>
28 #include <bitset>
29 #include <cstdlib>
30 #include <sstream>
31 
32 #include "disasm-aarch64.h"
33 
34 namespace vixl {
35 namespace aarch64 {
36 
37 const Disassembler::FormToVisitorFnMap Disassembler::FORM_TO_VISITOR = {
38     DEFAULT_FORM_TO_VISITOR_MAP(Disassembler),
39     {"autia1716_hi_hints", &Disassembler::DisassembleNoArgs},
40     {"autiasp_hi_hints", &Disassembler::DisassembleNoArgs},
41     {"autiaz_hi_hints", &Disassembler::DisassembleNoArgs},
42     {"autib1716_hi_hints", &Disassembler::DisassembleNoArgs},
43     {"autibsp_hi_hints", &Disassembler::DisassembleNoArgs},
44     {"autibz_hi_hints", &Disassembler::DisassembleNoArgs},
45     {"axflag_m_pstate", &Disassembler::DisassembleNoArgs},
46     {"cfinv_m_pstate", &Disassembler::DisassembleNoArgs},
47     {"csdb_hi_hints", &Disassembler::DisassembleNoArgs},
48     {"dgh_hi_hints", &Disassembler::DisassembleNoArgs},
49     {"ssbb_only_barriers", &Disassembler::DisassembleNoArgs},
50     {"pssbb_only_barriers", &Disassembler::DisassembleNoArgs},
51     {"esb_hi_hints", &Disassembler::DisassembleNoArgs},
52     {"isb_bi_barriers", &Disassembler::DisassembleNoArgs},
53     {"nop_hi_hints", &Disassembler::DisassembleNoArgs},
54     {"pacia1716_hi_hints", &Disassembler::DisassembleNoArgs},
55     {"paciasp_hi_hints", &Disassembler::DisassembleNoArgs},
56     {"paciaz_hi_hints", &Disassembler::DisassembleNoArgs},
57     {"pacib1716_hi_hints", &Disassembler::DisassembleNoArgs},
58     {"pacibsp_hi_hints", &Disassembler::DisassembleNoArgs},
59     {"pacibz_hi_hints", &Disassembler::DisassembleNoArgs},
60     {"sev_hi_hints", &Disassembler::DisassembleNoArgs},
61     {"sevl_hi_hints", &Disassembler::DisassembleNoArgs},
62     {"wfe_hi_hints", &Disassembler::DisassembleNoArgs},
63     {"wfi_hi_hints", &Disassembler::DisassembleNoArgs},
64     {"xaflag_m_pstate", &Disassembler::DisassembleNoArgs},
65     {"xpaclri_hi_hints", &Disassembler::DisassembleNoArgs},
66     {"yield_hi_hints", &Disassembler::DisassembleNoArgs},
67     {"abs_asimdmisc_r", &Disassembler::VisitNEON2RegMisc},
68     {"cls_asimdmisc_r", &Disassembler::VisitNEON2RegMisc},
69     {"clz_asimdmisc_r", &Disassembler::VisitNEON2RegMisc},
70     {"cnt_asimdmisc_r", &Disassembler::VisitNEON2RegMisc},
71     {"neg_asimdmisc_r", &Disassembler::VisitNEON2RegMisc},
72     {"rev16_asimdmisc_r", &Disassembler::VisitNEON2RegMisc},
73     {"rev32_asimdmisc_r", &Disassembler::VisitNEON2RegMisc},
74     {"rev64_asimdmisc_r", &Disassembler::VisitNEON2RegMisc},
75     {"sqabs_asimdmisc_r", &Disassembler::VisitNEON2RegMisc},
76     {"sqneg_asimdmisc_r", &Disassembler::VisitNEON2RegMisc},
77     {"suqadd_asimdmisc_r", &Disassembler::VisitNEON2RegMisc},
78     {"urecpe_asimdmisc_r", &Disassembler::VisitNEON2RegMisc},
79     {"ursqrte_asimdmisc_r", &Disassembler::VisitNEON2RegMisc},
80     {"usqadd_asimdmisc_r", &Disassembler::VisitNEON2RegMisc},
81     {"not_asimdmisc_r", &Disassembler::DisassembleNEON2RegLogical},
82     {"rbit_asimdmisc_r", &Disassembler::DisassembleNEON2RegLogical},
83     {"xtn_asimdmisc_n", &Disassembler::DisassembleNEON2RegExtract},
84     {"sqxtn_asimdmisc_n", &Disassembler::DisassembleNEON2RegExtract},
85     {"uqxtn_asimdmisc_n", &Disassembler::DisassembleNEON2RegExtract},
86     {"sqxtun_asimdmisc_n", &Disassembler::DisassembleNEON2RegExtract},
87     {"shll_asimdmisc_s", &Disassembler::DisassembleNEON2RegExtract},
88     {"sadalp_asimdmisc_p", &Disassembler::DisassembleNEON2RegAddlp},
89     {"saddlp_asimdmisc_p", &Disassembler::DisassembleNEON2RegAddlp},
90     {"uadalp_asimdmisc_p", &Disassembler::DisassembleNEON2RegAddlp},
91     {"uaddlp_asimdmisc_p", &Disassembler::DisassembleNEON2RegAddlp},
92     {"cmeq_asimdmisc_z", &Disassembler::DisassembleNEON2RegCompare},
93     {"cmge_asimdmisc_z", &Disassembler::DisassembleNEON2RegCompare},
94     {"cmgt_asimdmisc_z", &Disassembler::DisassembleNEON2RegCompare},
95     {"cmle_asimdmisc_z", &Disassembler::DisassembleNEON2RegCompare},
96     {"cmlt_asimdmisc_z", &Disassembler::DisassembleNEON2RegCompare},
97     {"fcmeq_asimdmisc_fz", &Disassembler::DisassembleNEON2RegFPCompare},
98     {"fcmge_asimdmisc_fz", &Disassembler::DisassembleNEON2RegFPCompare},
99     {"fcmgt_asimdmisc_fz", &Disassembler::DisassembleNEON2RegFPCompare},
100     {"fcmle_asimdmisc_fz", &Disassembler::DisassembleNEON2RegFPCompare},
101     {"fcmlt_asimdmisc_fz", &Disassembler::DisassembleNEON2RegFPCompare},
102     {"fcvtl_asimdmisc_l", &Disassembler::DisassembleNEON2RegFPConvert},
103     {"fcvtn_asimdmisc_n", &Disassembler::DisassembleNEON2RegFPConvert},
104     {"fcvtxn_asimdmisc_n", &Disassembler::DisassembleNEON2RegFPConvert},
105     {"fabs_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
106     {"fcvtas_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
107     {"fcvtau_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
108     {"fcvtms_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
109     {"fcvtmu_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
110     {"fcvtns_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
111     {"fcvtnu_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
112     {"fcvtps_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
113     {"fcvtpu_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
114     {"fcvtzs_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
115     {"fcvtzu_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
116     {"fneg_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
117     {"frecpe_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
118     {"frint32x_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
119     {"frint32z_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
120     {"frint64x_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
121     {"frint64z_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
122     {"frinta_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
123     {"frinti_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
124     {"frintm_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
125     {"frintn_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
126     {"frintp_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
127     {"frintx_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
128     {"frintz_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
129     {"frsqrte_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
130     {"fsqrt_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
131     {"scvtf_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
132     {"ucvtf_asimdmisc_r", &Disassembler::DisassembleNEON2RegFP},
133     {"smlal_asimdelem_l", &Disassembler::DisassembleNEONMulByElementLong},
134     {"smlsl_asimdelem_l", &Disassembler::DisassembleNEONMulByElementLong},
135     {"smull_asimdelem_l", &Disassembler::DisassembleNEONMulByElementLong},
136     {"umlal_asimdelem_l", &Disassembler::DisassembleNEONMulByElementLong},
137     {"umlsl_asimdelem_l", &Disassembler::DisassembleNEONMulByElementLong},
138     {"umull_asimdelem_l", &Disassembler::DisassembleNEONMulByElementLong},
139     {"sqdmull_asimdelem_l", &Disassembler::DisassembleNEONMulByElementLong},
140     {"sqdmlal_asimdelem_l", &Disassembler::DisassembleNEONMulByElementLong},
141     {"sqdmlsl_asimdelem_l", &Disassembler::DisassembleNEONMulByElementLong},
142     {"sdot_asimdelem_d", &Disassembler::DisassembleNEONDotProdByElement},
143     {"udot_asimdelem_d", &Disassembler::DisassembleNEONDotProdByElement},
144     {"usdot_asimdelem_d", &Disassembler::DisassembleNEONDotProdByElement},
145     {"sudot_asimdelem_d", &Disassembler::DisassembleNEONDotProdByElement},
146     {"fmlal2_asimdelem_lh", &Disassembler::DisassembleNEONFPMulByElementLong},
147     {"fmlal_asimdelem_lh", &Disassembler::DisassembleNEONFPMulByElementLong},
148     {"fmlsl2_asimdelem_lh", &Disassembler::DisassembleNEONFPMulByElementLong},
149     {"fmlsl_asimdelem_lh", &Disassembler::DisassembleNEONFPMulByElementLong},
150     {"fcmla_asimdelem_c_h",
151       &Disassembler::DisassembleNEONComplexMulByElement},
152     {"fcmla_asimdelem_c_s",
153       &Disassembler::DisassembleNEONComplexMulByElement},
154     {"fmla_asimdelem_rh_h", &Disassembler::DisassembleNEONHalfFPMulByElement},
155     {"fmls_asimdelem_rh_h", &Disassembler::DisassembleNEONHalfFPMulByElement},
156     {"fmulx_asimdelem_rh_h",
157       &Disassembler::DisassembleNEONHalfFPMulByElement},
158     {"fmul_asimdelem_rh_h", &Disassembler::DisassembleNEONHalfFPMulByElement},
159     {"fmla_asimdelem_r_sd", &Disassembler::DisassembleNEONFPMulByElement},
160     {"fmls_asimdelem_r_sd", &Disassembler::DisassembleNEONFPMulByElement},
161     {"fmulx_asimdelem_r_sd", &Disassembler::DisassembleNEONFPMulByElement},
162     {"fmul_asimdelem_r_sd", &Disassembler::DisassembleNEONFPMulByElement},
163     {"mla_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
164     {"mls_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
165     {"mul_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
166     {"saba_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
167     {"sabd_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
168     {"shadd_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
169     {"shsub_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
170     {"smaxp_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
171     {"smax_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
172     {"sminp_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
173     {"smin_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
174     {"srhadd_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
175     {"uaba_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
176     {"uabd_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
177     {"uhadd_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
178     {"uhsub_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
179     {"umaxp_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
180     {"umax_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
181     {"uminp_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
182     {"umin_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
183     {"urhadd_asimdsame_only", &Disassembler::DisassembleNEON3SameNoD},
184     {"and_asimdsame_only", &Disassembler::DisassembleNEON3SameLogical},
185     {"bic_asimdsame_only", &Disassembler::DisassembleNEON3SameLogical},
186     {"bif_asimdsame_only", &Disassembler::DisassembleNEON3SameLogical},
187     {"bit_asimdsame_only", &Disassembler::DisassembleNEON3SameLogical},
188     {"bsl_asimdsame_only", &Disassembler::DisassembleNEON3SameLogical},
189     {"eor_asimdsame_only", &Disassembler::DisassembleNEON3SameLogical},
190     {"orr_asimdsame_only", &Disassembler::DisassembleNEON3SameLogical},
191     {"orn_asimdsame_only", &Disassembler::DisassembleNEON3SameLogical},
192     {"pmul_asimdsame_only", &Disassembler::DisassembleNEON3SameLogical},
193     {"fmlal2_asimdsame_f", &Disassembler::DisassembleNEON3SameFHM},
194     {"fmlal_asimdsame_f", &Disassembler::DisassembleNEON3SameFHM},
195     {"fmlsl2_asimdsame_f", &Disassembler::DisassembleNEON3SameFHM},
196     {"fmlsl_asimdsame_f", &Disassembler::DisassembleNEON3SameFHM},
197     {"sri_asimdshf_r", &Disassembler::DisassembleNEONShiftRightImm},
198     {"srshr_asimdshf_r", &Disassembler::DisassembleNEONShiftRightImm},
199     {"srsra_asimdshf_r", &Disassembler::DisassembleNEONShiftRightImm},
200     {"sshr_asimdshf_r", &Disassembler::DisassembleNEONShiftRightImm},
201     {"ssra_asimdshf_r", &Disassembler::DisassembleNEONShiftRightImm},
202     {"urshr_asimdshf_r", &Disassembler::DisassembleNEONShiftRightImm},
203     {"ursra_asimdshf_r", &Disassembler::DisassembleNEONShiftRightImm},
204     {"ushr_asimdshf_r", &Disassembler::DisassembleNEONShiftRightImm},
205     {"usra_asimdshf_r", &Disassembler::DisassembleNEONShiftRightImm},
206     {"scvtf_asimdshf_c", &Disassembler::DisassembleNEONShiftRightImm},
207     {"ucvtf_asimdshf_c", &Disassembler::DisassembleNEONShiftRightImm},
208     {"fcvtzs_asimdshf_c", &Disassembler::DisassembleNEONShiftRightImm},
209     {"fcvtzu_asimdshf_c", &Disassembler::DisassembleNEONShiftRightImm},
210     {"ushll_asimdshf_l", &Disassembler::DisassembleNEONShiftLeftLongImm},
211     {"sshll_asimdshf_l", &Disassembler::DisassembleNEONShiftLeftLongImm},
212     {"shrn_asimdshf_n", &Disassembler::DisassembleNEONShiftRightNarrowImm},
213     {"rshrn_asimdshf_n", &Disassembler::DisassembleNEONShiftRightNarrowImm},
214     {"sqshrn_asimdshf_n", &Disassembler::DisassembleNEONShiftRightNarrowImm},
215     {"sqrshrn_asimdshf_n", &Disassembler::DisassembleNEONShiftRightNarrowImm},
216     {"sqshrun_asimdshf_n", &Disassembler::DisassembleNEONShiftRightNarrowImm},
217     {"sqrshrun_asimdshf_n",
218       &Disassembler::DisassembleNEONShiftRightNarrowImm},
219     {"uqshrn_asimdshf_n", &Disassembler::DisassembleNEONShiftRightNarrowImm},
220     {"uqrshrn_asimdshf_n", &Disassembler::DisassembleNEONShiftRightNarrowImm},
221     {"sqdmlal_asisdelem_l",
222       &Disassembler::DisassembleNEONScalarSatMulLongIndex},
223     {"sqdmlsl_asisdelem_l",
224       &Disassembler::DisassembleNEONScalarSatMulLongIndex},
225     {"sqdmull_asisdelem_l",
226       &Disassembler::DisassembleNEONScalarSatMulLongIndex},
227     {"fmla_asisdelem_rh_h", &Disassembler::DisassembleNEONFPScalarMulIndex},
228     {"fmla_asisdelem_r_sd", &Disassembler::DisassembleNEONFPScalarMulIndex},
229     {"fmls_asisdelem_rh_h", &Disassembler::DisassembleNEONFPScalarMulIndex},
230     {"fmls_asisdelem_r_sd", &Disassembler::DisassembleNEONFPScalarMulIndex},
231     {"fmulx_asisdelem_rh_h", &Disassembler::DisassembleNEONFPScalarMulIndex},
232     {"fmulx_asisdelem_r_sd", &Disassembler::DisassembleNEONFPScalarMulIndex},
233     {"fmul_asisdelem_rh_h", &Disassembler::DisassembleNEONFPScalarMulIndex},
234     {"fmul_asisdelem_r_sd", &Disassembler::DisassembleNEONFPScalarMulIndex},
235     {"fabd_asisdsame_only", &Disassembler::DisassembleNEONFPScalar3Same},
236     {"facge_asisdsame_only", &Disassembler::DisassembleNEONFPScalar3Same},
237     {"facgt_asisdsame_only", &Disassembler::DisassembleNEONFPScalar3Same},
238     {"fcmeq_asisdsame_only", &Disassembler::DisassembleNEONFPScalar3Same},
239     {"fcmge_asisdsame_only", &Disassembler::DisassembleNEONFPScalar3Same},
240     {"fcmgt_asisdsame_only", &Disassembler::DisassembleNEONFPScalar3Same},
241     {"fmulx_asisdsame_only", &Disassembler::DisassembleNEONFPScalar3Same},
242     {"frecps_asisdsame_only", &Disassembler::DisassembleNEONFPScalar3Same},
243     {"frsqrts_asisdsame_only", &Disassembler::DisassembleNEONFPScalar3Same},
244     {"sqrdmlah_asisdsame2_only", &Disassembler::VisitNEONScalar3Same},
245     {"sqrdmlsh_asisdsame2_only", &Disassembler::VisitNEONScalar3Same},
246     {"cmeq_asisdsame_only", &Disassembler::DisassembleNEONScalar3SameOnlyD},
247     {"cmge_asisdsame_only", &Disassembler::DisassembleNEONScalar3SameOnlyD},
248     {"cmgt_asisdsame_only", &Disassembler::DisassembleNEONScalar3SameOnlyD},
249     {"cmhi_asisdsame_only", &Disassembler::DisassembleNEONScalar3SameOnlyD},
250     {"cmhs_asisdsame_only", &Disassembler::DisassembleNEONScalar3SameOnlyD},
251     {"cmtst_asisdsame_only", &Disassembler::DisassembleNEONScalar3SameOnlyD},
252     {"add_asisdsame_only", &Disassembler::DisassembleNEONScalar3SameOnlyD},
253     {"sub_asisdsame_only", &Disassembler::DisassembleNEONScalar3SameOnlyD},
254     {"fmaxnmv_asimdall_only_h",
255       &Disassembler::DisassembleNEONFP16AcrossLanes},
256     {"fmaxv_asimdall_only_h", &Disassembler::DisassembleNEONFP16AcrossLanes},
257     {"fminnmv_asimdall_only_h",
258       &Disassembler::DisassembleNEONFP16AcrossLanes},
259     {"fminv_asimdall_only_h", &Disassembler::DisassembleNEONFP16AcrossLanes},
260     {"fmaxnmv_asimdall_only_sd", &Disassembler::DisassembleNEONFPAcrossLanes},
261     {"fminnmv_asimdall_only_sd", &Disassembler::DisassembleNEONFPAcrossLanes},
262     {"fmaxv_asimdall_only_sd", &Disassembler::DisassembleNEONFPAcrossLanes},
263     {"fminv_asimdall_only_sd", &Disassembler::DisassembleNEONFPAcrossLanes},
264     {"shl_asisdshf_r", &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
265     {"sli_asisdshf_r", &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
266     {"sri_asisdshf_r", &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
267     {"srshr_asisdshf_r", &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
268     {"srsra_asisdshf_r", &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
269     {"sshr_asisdshf_r", &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
270     {"ssra_asisdshf_r", &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
271     {"urshr_asisdshf_r", &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
272     {"ursra_asisdshf_r", &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
273     {"ushr_asisdshf_r", &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
274     {"usra_asisdshf_r", &Disassembler::DisassembleNEONScalarShiftImmOnlyD},
275     {"sqrshrn_asisdshf_n",
276       &Disassembler::DisassembleNEONScalarShiftRightNarrowImm},
277     {"sqrshrun_asisdshf_n",
278       &Disassembler::DisassembleNEONScalarShiftRightNarrowImm},
279     {"sqshrn_asisdshf_n",
280       &Disassembler::DisassembleNEONScalarShiftRightNarrowImm},
281     {"sqshrun_asisdshf_n",
282       &Disassembler::DisassembleNEONScalarShiftRightNarrowImm},
283     {"uqrshrn_asisdshf_n",
284       &Disassembler::DisassembleNEONScalarShiftRightNarrowImm},
285     {"uqshrn_asisdshf_n",
286       &Disassembler::DisassembleNEONScalarShiftRightNarrowImm},
287     {"cmeq_asisdmisc_z", &Disassembler::DisassembleNEONScalar2RegMiscOnlyD},
288     {"cmge_asisdmisc_z", &Disassembler::DisassembleNEONScalar2RegMiscOnlyD},
289     {"cmgt_asisdmisc_z", &Disassembler::DisassembleNEONScalar2RegMiscOnlyD},
290     {"cmle_asisdmisc_z", &Disassembler::DisassembleNEONScalar2RegMiscOnlyD},
291     {"cmlt_asisdmisc_z", &Disassembler::DisassembleNEONScalar2RegMiscOnlyD},
292     {"abs_asisdmisc_r", &Disassembler::DisassembleNEONScalar2RegMiscOnlyD},
293     {"neg_asisdmisc_r", &Disassembler::DisassembleNEONScalar2RegMiscOnlyD},
294     {"fcmeq_asisdmisc_fz", &Disassembler::DisassembleNEONFPScalar2RegMisc},
295     {"fcmge_asisdmisc_fz", &Disassembler::DisassembleNEONFPScalar2RegMisc},
296     {"fcmgt_asisdmisc_fz", &Disassembler::DisassembleNEONFPScalar2RegMisc},
297     {"fcmle_asisdmisc_fz", &Disassembler::DisassembleNEONFPScalar2RegMisc},
298     {"fcmlt_asisdmisc_fz", &Disassembler::DisassembleNEONFPScalar2RegMisc},
299     {"fcvtas_asisdmisc_r", &Disassembler::DisassembleNEONFPScalar2RegMisc},
300     {"fcvtau_asisdmisc_r", &Disassembler::DisassembleNEONFPScalar2RegMisc},
301     {"fcvtms_asisdmisc_r", &Disassembler::DisassembleNEONFPScalar2RegMisc},
302     {"fcvtmu_asisdmisc_r", &Disassembler::DisassembleNEONFPScalar2RegMisc},
303     {"fcvtns_asisdmisc_r", &Disassembler::DisassembleNEONFPScalar2RegMisc},
304     {"fcvtnu_asisdmisc_r", &Disassembler::DisassembleNEONFPScalar2RegMisc},
305     {"fcvtps_asisdmisc_r", &Disassembler::DisassembleNEONFPScalar2RegMisc},
306     {"fcvtpu_asisdmisc_r", &Disassembler::DisassembleNEONFPScalar2RegMisc},
307     {"fcvtxn_asisdmisc_n", &Disassembler::DisassembleNEONFPScalar2RegMisc},
308     {"fcvtzs_asisdmisc_r", &Disassembler::DisassembleNEONFPScalar2RegMisc},
309     {"fcvtzu_asisdmisc_r", &Disassembler::DisassembleNEONFPScalar2RegMisc},
310     {"frecpe_asisdmisc_r", &Disassembler::DisassembleNEONFPScalar2RegMisc},
311     {"frecpx_asisdmisc_r", &Disassembler::DisassembleNEONFPScalar2RegMisc},
312     {"frsqrte_asisdmisc_r", &Disassembler::DisassembleNEONFPScalar2RegMisc},
313     {"scvtf_asisdmisc_r", &Disassembler::DisassembleNEONFPScalar2RegMisc},
314     {"ucvtf_asisdmisc_r", &Disassembler::DisassembleNEONFPScalar2RegMisc},
315     {"adclb_z_zzz", &Disassembler::DisassembleSVEAddSubCarry},
316     {"adclt_z_zzz", &Disassembler::DisassembleSVEAddSubCarry},
317     {"addhnb_z_zz", &Disassembler::DisassembleSVEAddSubHigh},
318     {"addhnt_z_zz", &Disassembler::DisassembleSVEAddSubHigh},
319     {"addp_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
320     {"aesd_z_zz", &Disassembler::Disassemble_ZdnB_ZdnB_ZmB},
321     {"aese_z_zz", &Disassembler::Disassemble_ZdnB_ZdnB_ZmB},
322     {"aesimc_z_z", &Disassembler::Disassemble_ZdnB_ZdnB},
323     {"aesmc_z_z", &Disassembler::Disassemble_ZdnB_ZdnB},
324     {"bcax_z_zzz", &Disassembler::DisassembleSVEBitwiseTernary},
325     {"bdep_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmT},
326     {"bext_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmT},
327     {"bgrp_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmT},
328     {"bsl1n_z_zzz", &Disassembler::DisassembleSVEBitwiseTernary},
329     {"bsl2n_z_zzz", &Disassembler::DisassembleSVEBitwiseTernary},
330     {"bsl_z_zzz", &Disassembler::DisassembleSVEBitwiseTernary},
331     {"cadd_z_zz", &Disassembler::DisassembleSVEComplexIntAddition},
332     {"cdot_z_zzz", &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb_const},
333     {"cdot_z_zzzi_d", &Disassembler::Disassemble_ZdaD_ZnH_ZmH_imm_const},
334     {"cdot_z_zzzi_s", &Disassembler::Disassemble_ZdaS_ZnB_ZmB_imm_const},
335     {"cmla_z_zzz", &Disassembler::Disassemble_ZdaT_ZnT_ZmT_const},
336     {"cmla_z_zzzi_h", &Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm_const},
337     {"cmla_z_zzzi_s", &Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm_const},
338     {"eor3_z_zzz", &Disassembler::DisassembleSVEBitwiseTernary},
339     {"eorbt_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmT},
340     {"eortb_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmT},
341     {"ext_z_zi_con", &Disassembler::Disassemble_ZdB_Zn1B_Zn2B_imm},
342     {"faddp_z_p_zz", &Disassembler::DisassembleSVEFPPair},
343     {"fcvtlt_z_p_z_h2s", &Disassembler::Disassemble_ZdS_PgM_ZnH},
344     {"fcvtlt_z_p_z_s2d", &Disassembler::Disassemble_ZdD_PgM_ZnS},
345     {"fcvtnt_z_p_z_d2s", &Disassembler::Disassemble_ZdS_PgM_ZnD},
346     {"fcvtnt_z_p_z_s2h", &Disassembler::Disassemble_ZdH_PgM_ZnS},
347     {"fcvtx_z_p_z_d2s", &Disassembler::Disassemble_ZdS_PgM_ZnD},
348     {"fcvtxnt_z_p_z_d2s", &Disassembler::Disassemble_ZdS_PgM_ZnD},
349     {"flogb_z_p_z", &Disassembler::DisassembleSVEFlogb},
350     {"fmaxnmp_z_p_zz", &Disassembler::DisassembleSVEFPPair},
351     {"fmaxp_z_p_zz", &Disassembler::DisassembleSVEFPPair},
352     {"fminnmp_z_p_zz", &Disassembler::DisassembleSVEFPPair},
353     {"fminp_z_p_zz", &Disassembler::DisassembleSVEFPPair},
354     {"fmlalb_z_zzz", &Disassembler::Disassemble_ZdaS_ZnH_ZmH},
355     {"fmlalb_z_zzzi_s", &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm},
356     {"fmlalt_z_zzz", &Disassembler::Disassemble_ZdaS_ZnH_ZmH},
357     {"fmlalt_z_zzzi_s", &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm},
358     {"fmlslb_z_zzz", &Disassembler::Disassemble_ZdaS_ZnH_ZmH},
359     {"fmlslb_z_zzzi_s", &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm},
360     {"fmlslt_z_zzz", &Disassembler::Disassemble_ZdaS_ZnH_ZmH},
361     {"fmlslt_z_zzzi_s", &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm},
362     {"histcnt_z_p_zz", &Disassembler::Disassemble_ZdT_PgZ_ZnT_ZmT},
363     {"histseg_z_zz", &Disassembler::Disassemble_ZdB_ZnB_ZmB},
364     {"ldnt1b_z_p_ar_d_64_unscaled",
365       &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm},
366     {"ldnt1b_z_p_ar_s_x32_unscaled",
367       &Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm},
368     {"ldnt1d_z_p_ar_d_64_unscaled",
369       &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm},
370     {"ldnt1h_z_p_ar_d_64_unscaled",
371       &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm},
372     {"ldnt1h_z_p_ar_s_x32_unscaled",
373       &Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm},
374     {"ldnt1sb_z_p_ar_d_64_unscaled",
375       &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm},
376     {"ldnt1sb_z_p_ar_s_x32_unscaled",
377       &Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm},
378     {"ldnt1sh_z_p_ar_d_64_unscaled",
379       &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm},
380     {"ldnt1sh_z_p_ar_s_x32_unscaled",
381       &Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm},
382     {"ldnt1sw_z_p_ar_d_64_unscaled",
383       &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm},
384     {"ldnt1w_z_p_ar_d_64_unscaled",
385       &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm},
386     {"ldnt1w_z_p_ar_s_x32_unscaled",
387       &Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm},
388     {"match_p_p_zz", &Disassembler::Disassemble_PdT_PgZ_ZnT_ZmT},
389     {"mla_z_zzzi_d", &Disassembler::Disassemble_ZdD_ZnD_ZmD_imm},
390     {"mla_z_zzzi_h", &Disassembler::Disassemble_ZdH_ZnH_ZmH_imm},
391     {"mla_z_zzzi_s", &Disassembler::Disassemble_ZdS_ZnS_ZmS_imm},
392     {"mls_z_zzzi_d", &Disassembler::Disassemble_ZdD_ZnD_ZmD_imm},
393     {"mls_z_zzzi_h", &Disassembler::Disassemble_ZdH_ZnH_ZmH_imm},
394     {"mls_z_zzzi_s", &Disassembler::Disassemble_ZdS_ZnS_ZmS_imm},
395     {"mul_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmT},
396     {"mul_z_zzi_d", &Disassembler::Disassemble_ZdD_ZnD_ZmD_imm},
397     {"mul_z_zzi_h", &Disassembler::Disassemble_ZdH_ZnH_ZmH_imm},
398     {"mul_z_zzi_s", &Disassembler::Disassemble_ZdS_ZnS_ZmS_imm},
399     {"nbsl_z_zzz", &Disassembler::DisassembleSVEBitwiseTernary},
400     {"nmatch_p_p_zz", &Disassembler::Disassemble_PdT_PgZ_ZnT_ZmT},
401     {"pmul_z_zz", &Disassembler::Disassemble_ZdB_ZnB_ZmB},
402     {"pmullb_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
403     {"pmullt_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
404     {"raddhnb_z_zz", &Disassembler::DisassembleSVEAddSubHigh},
405     {"raddhnt_z_zz", &Disassembler::DisassembleSVEAddSubHigh},
406     {"rax1_z_zz", &Disassembler::Disassemble_ZdD_ZnD_ZmD},
407     {"rshrnb_z_zi", &Disassembler::DisassembleSVEShiftRightImm},
408     {"rshrnt_z_zi", &Disassembler::DisassembleSVEShiftRightImm},
409     {"rsubhnb_z_zz", &Disassembler::DisassembleSVEAddSubHigh},
410     {"rsubhnt_z_zz", &Disassembler::DisassembleSVEAddSubHigh},
411     {"saba_z_zzz", &Disassembler::Disassemble_ZdaT_ZnT_ZmT},
412     {"sabalb_z_zzz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
413     {"sabalt_z_zzz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
414     {"sabdlb_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
415     {"sabdlt_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
416     {"sadalp_z_p_z", &Disassembler::Disassemble_ZdaT_PgM_ZnTb},
417     {"saddlb_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
418     {"saddlbt_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
419     {"saddlt_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
420     {"saddwb_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmTb},
421     {"saddwt_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmTb},
422     {"sbclb_z_zzz", &Disassembler::DisassembleSVEAddSubCarry},
423     {"sbclt_z_zzz", &Disassembler::DisassembleSVEAddSubCarry},
424     {"shadd_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
425     {"shrnb_z_zi", &Disassembler::DisassembleSVEShiftRightImm},
426     {"shrnt_z_zi", &Disassembler::DisassembleSVEShiftRightImm},
427     {"shsub_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
428     {"shsubr_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
429     {"sli_z_zzi", &Disassembler::VisitSVEBitwiseShiftUnpredicated},
430     {"sm4e_z_zz", &Disassembler::Disassemble_ZdnS_ZdnS_ZmS},
431     {"sm4ekey_z_zz", &Disassembler::Disassemble_ZdS_ZnS_ZmS},
432     {"smaxp_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
433     {"sminp_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
434     {"smlalb_z_zzz", &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
435     {"smlalb_z_zzzi_d", &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
436     {"smlalb_z_zzzi_s", &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
437     {"smlalt_z_zzz", &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
438     {"smlalt_z_zzzi_d", &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
439     {"smlalt_z_zzzi_s", &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
440     {"smlslb_z_zzz", &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
441     {"smlslb_z_zzzi_d", &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
442     {"smlslb_z_zzzi_s", &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
443     {"smlslt_z_zzz", &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
444     {"smlslt_z_zzzi_d", &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
445     {"smlslt_z_zzzi_s", &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
446     {"smulh_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmT},
447     {"smullb_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
448     {"smullb_z_zzi_d", &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
449     {"smullb_z_zzi_s", &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
450     {"smullt_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
451     {"smullt_z_zzi_d", &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
452     {"smullt_z_zzi_s", &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
453     {"splice_z_p_zz_con", &Disassembler::Disassemble_ZdT_Pg_Zn1T_Zn2T},
454     {"sqabs_z_p_z", &Disassembler::Disassemble_ZdT_PgM_ZnT},
455     {"sqadd_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
456     {"sqcadd_z_zz", &Disassembler::DisassembleSVEComplexIntAddition},
457     {"sqdmlalb_z_zzz", &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
458     {"sqdmlalb_z_zzzi_d", &Disassembler::Disassemble_ZdaD_ZnS_ZmS_imm},
459     {"sqdmlalb_z_zzzi_s", &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm},
460     {"sqdmlalbt_z_zzz", &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
461     {"sqdmlalt_z_zzz", &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
462     {"sqdmlalt_z_zzzi_d", &Disassembler::Disassemble_ZdaD_ZnS_ZmS_imm},
463     {"sqdmlalt_z_zzzi_s", &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm},
464     {"sqdmlslb_z_zzz", &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
465     {"sqdmlslb_z_zzzi_d", &Disassembler::Disassemble_ZdaD_ZnS_ZmS_imm},
466     {"sqdmlslb_z_zzzi_s", &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm},
467     {"sqdmlslbt_z_zzz", &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
468     {"sqdmlslt_z_zzz", &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
469     {"sqdmlslt_z_zzzi_d", &Disassembler::Disassemble_ZdaD_ZnS_ZmS_imm},
470     {"sqdmlslt_z_zzzi_s", &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm},
471     {"sqdmulh_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmT},
472     {"sqdmulh_z_zzi_d", &Disassembler::Disassemble_ZdD_ZnD_ZmD_imm},
473     {"sqdmulh_z_zzi_h", &Disassembler::Disassemble_ZdH_ZnH_ZmH_imm},
474     {"sqdmulh_z_zzi_s", &Disassembler::Disassemble_ZdS_ZnS_ZmS_imm},
475     {"sqdmullb_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
476     {"sqdmullb_z_zzi_d", &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
477     {"sqdmullb_z_zzi_s", &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
478     {"sqdmullt_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
479     {"sqdmullt_z_zzi_d", &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
480     {"sqdmullt_z_zzi_s", &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
481     {"sqneg_z_p_z", &Disassembler::Disassemble_ZdT_PgM_ZnT},
482     {"sqrdcmlah_z_zzz", &Disassembler::Disassemble_ZdaT_ZnT_ZmT_const},
483     {"sqrdcmlah_z_zzzi_h", &Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm_const},
484     {"sqrdcmlah_z_zzzi_s", &Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm_const},
485     {"sqrdmlah_z_zzz", &Disassembler::Disassemble_ZdaT_ZnT_ZmT},
486     {"sqrdmlah_z_zzzi_d", &Disassembler::Disassemble_ZdaD_ZnD_ZmD_imm},
487     {"sqrdmlah_z_zzzi_h", &Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm},
488     {"sqrdmlah_z_zzzi_s", &Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm},
489     {"sqrdmlsh_z_zzz", &Disassembler::Disassemble_ZdaT_ZnT_ZmT},
490     {"sqrdmlsh_z_zzzi_d", &Disassembler::Disassemble_ZdaD_ZnD_ZmD_imm},
491     {"sqrdmlsh_z_zzzi_h", &Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm},
492     {"sqrdmlsh_z_zzzi_s", &Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm},
493     {"sqrdmulh_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmT},
494     {"sqrdmulh_z_zzi_d", &Disassembler::Disassemble_ZdD_ZnD_ZmD_imm},
495     {"sqrdmulh_z_zzi_h", &Disassembler::Disassemble_ZdH_ZnH_ZmH_imm},
496     {"sqrdmulh_z_zzi_s", &Disassembler::Disassemble_ZdS_ZnS_ZmS_imm},
497     {"sqrshl_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
498     {"sqrshlr_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
499     {"sqrshrnb_z_zi", &Disassembler::DisassembleSVEShiftRightImm},
500     {"sqrshrnt_z_zi", &Disassembler::DisassembleSVEShiftRightImm},
501     {"sqrshrunb_z_zi", &Disassembler::DisassembleSVEShiftRightImm},
502     {"sqrshrunt_z_zi", &Disassembler::DisassembleSVEShiftRightImm},
503     {"sqshl_z_p_zi", &Disassembler::VisitSVEBitwiseShiftByImm_Predicated},
504     {"sqshl_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
505     {"sqshlr_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
506     {"sqshlu_z_p_zi", &Disassembler::VisitSVEBitwiseShiftByImm_Predicated},
507     {"sqshrnb_z_zi", &Disassembler::DisassembleSVEShiftRightImm},
508     {"sqshrnt_z_zi", &Disassembler::DisassembleSVEShiftRightImm},
509     {"sqshrunb_z_zi", &Disassembler::DisassembleSVEShiftRightImm},
510     {"sqshrunt_z_zi", &Disassembler::DisassembleSVEShiftRightImm},
511     {"sqsub_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
512     {"sqsubr_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
513     {"sqxtnb_z_zz", &Disassembler::Disassemble_ZdT_ZnTb},
514     {"sqxtnt_z_zz", &Disassembler::Disassemble_ZdT_ZnTb},
515     {"sqxtunb_z_zz", &Disassembler::Disassemble_ZdT_ZnTb},
516     {"sqxtunt_z_zz", &Disassembler::Disassemble_ZdT_ZnTb},
517     {"srhadd_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
518     {"sri_z_zzi", &Disassembler::VisitSVEBitwiseShiftUnpredicated},
519     {"srshl_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
520     {"srshlr_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
521     {"srshr_z_p_zi", &Disassembler::VisitSVEBitwiseShiftByImm_Predicated},
522     {"srsra_z_zi", &Disassembler::VisitSVEBitwiseShiftUnpredicated},
523     {"sshllb_z_zi", &Disassembler::DisassembleSVEShiftLeftImm},
524     {"sshllt_z_zi", &Disassembler::DisassembleSVEShiftLeftImm},
525     {"ssra_z_zi", &Disassembler::VisitSVEBitwiseShiftUnpredicated},
526     {"ssublb_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
527     {"ssublbt_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
528     {"ssublt_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
529     {"ssubltb_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
530     {"ssubwb_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmTb},
531     {"ssubwt_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmTb},
532     {"stnt1b_z_p_ar_d_64_unscaled", &Disassembler::Disassemble_ZtD_Pg_ZnD_Xm},
533     {"stnt1b_z_p_ar_s_x32_unscaled",
534       &Disassembler::Disassemble_ZtS_Pg_ZnS_Xm},
535     {"stnt1d_z_p_ar_d_64_unscaled", &Disassembler::Disassemble_ZtD_Pg_ZnD_Xm},
536     {"stnt1h_z_p_ar_d_64_unscaled", &Disassembler::Disassemble_ZtD_Pg_ZnD_Xm},
537     {"stnt1h_z_p_ar_s_x32_unscaled",
538       &Disassembler::Disassemble_ZtS_Pg_ZnS_Xm},
539     {"stnt1w_z_p_ar_d_64_unscaled", &Disassembler::Disassemble_ZtD_Pg_ZnD_Xm},
540     {"stnt1w_z_p_ar_s_x32_unscaled",
541       &Disassembler::Disassemble_ZtS_Pg_ZnS_Xm},
542     {"subhnb_z_zz", &Disassembler::DisassembleSVEAddSubHigh},
543     {"subhnt_z_zz", &Disassembler::DisassembleSVEAddSubHigh},
544     {"suqadd_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
545     {"tbl_z_zz_2", &Disassembler::Disassemble_ZdT_Zn1T_Zn2T_ZmT},
546     {"tbx_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmT},
547     {"uaba_z_zzz", &Disassembler::Disassemble_ZdaT_ZnT_ZmT},
548     {"uabalb_z_zzz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
549     {"uabalt_z_zzz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
550     {"uabdlb_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
551     {"uabdlt_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
552     {"uadalp_z_p_z", &Disassembler::Disassemble_ZdaT_PgM_ZnTb},
553     {"uaddlb_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
554     {"uaddlt_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
555     {"uaddwb_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmTb},
556     {"uaddwt_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmTb},
557     {"uhadd_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
558     {"uhsub_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
559     {"uhsubr_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
560     {"umaxp_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
561     {"uminp_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
562     {"umlalb_z_zzz", &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
563     {"umlalb_z_zzzi_d", &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
564     {"umlalb_z_zzzi_s", &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
565     {"umlalt_z_zzz", &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
566     {"umlalt_z_zzzi_d", &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
567     {"umlalt_z_zzzi_s", &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
568     {"umlslb_z_zzz", &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
569     {"umlslb_z_zzzi_d", &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
570     {"umlslb_z_zzzi_s", &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
571     {"umlslt_z_zzz", &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb},
572     {"umlslt_z_zzzi_d", &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
573     {"umlslt_z_zzzi_s", &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
574     {"umulh_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmT},
575     {"umullb_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
576     {"umullb_z_zzi_d", &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
577     {"umullb_z_zzi_s", &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
578     {"umullt_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
579     {"umullt_z_zzi_d", &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm},
580     {"umullt_z_zzi_s", &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm},
581     {"uqadd_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
582     {"uqrshl_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
583     {"uqrshlr_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
584     {"uqrshrnb_z_zi", &Disassembler::DisassembleSVEShiftRightImm},
585     {"uqrshrnt_z_zi", &Disassembler::DisassembleSVEShiftRightImm},
586     {"uqshl_z_p_zi", &Disassembler::VisitSVEBitwiseShiftByImm_Predicated},
587     {"uqshl_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
588     {"uqshlr_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
589     {"uqshrnb_z_zi", &Disassembler::DisassembleSVEShiftRightImm},
590     {"uqshrnt_z_zi", &Disassembler::DisassembleSVEShiftRightImm},
591     {"uqsub_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
592     {"uqsubr_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
593     {"uqxtnb_z_zz", &Disassembler::Disassemble_ZdT_ZnTb},
594     {"uqxtnt_z_zz", &Disassembler::Disassemble_ZdT_ZnTb},
595     {"urecpe_z_p_z", &Disassembler::Disassemble_ZdS_PgM_ZnS},
596     {"urhadd_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
597     {"urshl_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
598     {"urshlr_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
599     {"urshr_z_p_zi", &Disassembler::VisitSVEBitwiseShiftByImm_Predicated},
600     {"ursqrte_z_p_z", &Disassembler::Disassemble_ZdS_PgM_ZnS},
601     {"ursra_z_zi", &Disassembler::VisitSVEBitwiseShiftUnpredicated},
602     {"ushllb_z_zi", &Disassembler::DisassembleSVEShiftLeftImm},
603     {"ushllt_z_zi", &Disassembler::DisassembleSVEShiftLeftImm},
604     {"usqadd_z_p_zz", &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT},
605     {"usra_z_zi", &Disassembler::VisitSVEBitwiseShiftUnpredicated},
606     {"usublb_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
607     {"usublt_z_zz", &Disassembler::Disassemble_ZdT_ZnTb_ZmTb},
608     {"usubwb_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmTb},
609     {"usubwt_z_zz", &Disassembler::Disassemble_ZdT_ZnT_ZmTb},
610     {"whilege_p_p_rr", &Disassembler::VisitSVEIntCompareScalarCountAndLimit},
611     {"whilegt_p_p_rr", &Disassembler::VisitSVEIntCompareScalarCountAndLimit},
612     {"whilehi_p_p_rr", &Disassembler::VisitSVEIntCompareScalarCountAndLimit},
613     {"whilehs_p_p_rr", &Disassembler::VisitSVEIntCompareScalarCountAndLimit},
614     {"whilerw_p_rr", &Disassembler::VisitSVEIntCompareScalarCountAndLimit},
615     {"whilewr_p_rr", &Disassembler::VisitSVEIntCompareScalarCountAndLimit},
616     {"xar_z_zzi", &Disassembler::Disassemble_ZdnT_ZdnT_ZmT_const},
617     {"fmmla_z_zzz_s", &Disassembler::Disassemble_ZdaT_ZnT_ZmT},
618     {"fmmla_z_zzz_d", &Disassembler::Disassemble_ZdaT_ZnT_ZmT},
619     {"smmla_z_zzz", &Disassembler::Disassemble_ZdaS_ZnB_ZmB},
620     {"ummla_z_zzz", &Disassembler::Disassemble_ZdaS_ZnB_ZmB},
621     {"usmmla_z_zzz", &Disassembler::Disassemble_ZdaS_ZnB_ZmB},
622     {"usdot_z_zzz_s", &Disassembler::Disassemble_ZdaS_ZnB_ZmB},
623     {"smmla_asimdsame2_g", &Disassembler::Disassemble_Vd4S_Vn16B_Vm16B},
624     {"ummla_asimdsame2_g", &Disassembler::Disassemble_Vd4S_Vn16B_Vm16B},
625     {"usmmla_asimdsame2_g", &Disassembler::Disassemble_Vd4S_Vn16B_Vm16B},
626     {"ld1row_z_p_bi_u32",
627       &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},
628     {"ld1row_z_p_br_contiguous",
629       &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},
630     {"ld1rod_z_p_bi_u64",
631       &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},
632     {"ld1rod_z_p_br_contiguous",
633       &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},
634     {"ld1rob_z_p_bi_u8",
635       &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},
636     {"ld1rob_z_p_br_contiguous",
637       &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},
638     {"ld1roh_z_p_bi_u16",
639       &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},
640     {"ld1roh_z_p_br_contiguous",
641       &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},
642     {"usdot_z_zzzi_s", &Disassembler::VisitSVEMulIndex},
643     {"sudot_z_zzzi_s", &Disassembler::VisitSVEMulIndex},
644     {"usdot_asimdsame2_d", &Disassembler::VisitNEON3SameExtra},
645 };
646 
GetFormToVisitorFnMap()647 const Disassembler::FormToVisitorFnMap *Disassembler::GetFormToVisitorFnMap() {
648   return &FORM_TO_VISITOR;
649 }  // NOLINT(readability/fn_size)
650 
651 #ifndef PANDA_BUILD
Disassembler()652 Disassembler::Disassembler() : allocator_(std::make_optional<AllocatorWrapper>()) {
653 #else
654 Disassembler::Disassembler(PandaAllocator* allocator) : allocator_(std::make_optional<AllocatorWrapper>(allocator)) {
655 #endif
656   buffer_size_ = static_cast<uint32_t>(kDefaultBufferSize);
657   buffer_ = static_cast<char *>(allocator_->Alloc(buffer_size_));
658   own_buffer_ = true;
659   buffer_pos_ = 0;
660   code_address_offset_ = 0;
661 }
662 
663 Disassembler::Disassembler(char *text_buffer, int buffer_size) {
664   buffer_size_ = buffer_size;
665   buffer_ = text_buffer;
666   buffer_pos_ = 0;
667   own_buffer_ = false;
668   code_address_offset_ = 0;
669 }
670 
671 Disassembler::~Disassembler() {
672   if (own_buffer_) {
673     allocator_->Free(buffer_);
674   }
675 }
676 
677 char *Disassembler::GetOutput() { return buffer_; }
678 
679 void Disassembler::VisitAddSubImmediate(const Instruction *instr) {
680   bool rd_is_zr = RdIsZROrSP(instr);
681   bool stack_op =
682       (rd_is_zr || RnIsZROrSP(instr)) && (instr->GetImmAddSub() == 0) ? true
683                                                                       : false;
684   const char *mnemonic = "";
685   const char *form = "'Rds, 'Rns, 'IAddSub";
686   const char *form_cmp = "'Rns, 'IAddSub";
687   const char *form_mov = "'Rds, 'Rns";
688 
689   switch (instr->Mask(AddSubImmediateMask)) {
690     case ADD_w_imm:
691     case ADD_x_imm: {
692       mnemonic = "add";
693       if (stack_op) {
694         mnemonic = "mov";
695         form = form_mov;
696       }
697       break;
698     }
699     case ADDS_w_imm:
700     case ADDS_x_imm: {
701       mnemonic = "adds";
702       if (rd_is_zr) {
703         mnemonic = "cmn";
704         form = form_cmp;
705       }
706       break;
707     }
708     case SUB_w_imm:
709     case SUB_x_imm:
710       mnemonic = "sub";
711       break;
712     case SUBS_w_imm:
713     case SUBS_x_imm: {
714       mnemonic = "subs";
715       if (rd_is_zr) {
716         mnemonic = "cmp";
717         form = form_cmp;
718       }
719       break;
720     }
721     default:
722       VIXL_UNREACHABLE();
723   }
724   Format(instr, mnemonic, form);
725 }
726 
727 
728 void Disassembler::VisitAddSubShifted(const Instruction *instr) {
729   bool rd_is_zr = RdIsZROrSP(instr);
730   bool rn_is_zr = RnIsZROrSP(instr);
731   const char *mnemonic = "";
732   const char *form = "'Rd, 'Rn, 'Rm'NDP";
733   const char *form_cmp = "'Rn, 'Rm'NDP";
734   const char *form_neg = "'Rd, 'Rm'NDP";
735 
736   switch (instr->Mask(AddSubShiftedMask)) {
737     case ADD_w_shift:
738     case ADD_x_shift:
739       mnemonic = "add";
740       break;
741     case ADDS_w_shift:
742     case ADDS_x_shift: {
743       mnemonic = "adds";
744       if (rd_is_zr) {
745         mnemonic = "cmn";
746         form = form_cmp;
747       }
748       break;
749     }
750     case SUB_w_shift:
751     case SUB_x_shift: {
752       mnemonic = "sub";
753       if (rn_is_zr) {
754         mnemonic = "neg";
755         form = form_neg;
756       }
757       break;
758     }
759     case SUBS_w_shift:
760     case SUBS_x_shift: {
761       mnemonic = "subs";
762       if (rd_is_zr) {
763         mnemonic = "cmp";
764         form = form_cmp;
765       } else if (rn_is_zr) {
766         mnemonic = "negs";
767         form = form_neg;
768       }
769       break;
770     }
771     default:
772       VIXL_UNREACHABLE();
773   }
774   Format(instr, mnemonic, form);
775 }
776 
777 
778 void Disassembler::VisitAddSubExtended(const Instruction *instr) {
779   bool rd_is_zr = RdIsZROrSP(instr);
780   const char *mnemonic = "";
781   Extend mode = static_cast<Extend>(instr->GetExtendMode());
782   const char *form = ((mode == UXTX) || (mode == SXTX)) ? "'Rds, 'Rns, 'Xm'Ext"
783                                                         : "'Rds, 'Rns, 'Wm'Ext";
784   const char *form_cmp =
785       ((mode == UXTX) || (mode == SXTX)) ? "'Rns, 'Xm'Ext" : "'Rns, 'Wm'Ext";
786 
787   switch (instr->Mask(AddSubExtendedMask)) {
788     case ADD_w_ext:
789     case ADD_x_ext:
790       mnemonic = "add";
791       break;
792     case ADDS_w_ext:
793     case ADDS_x_ext: {
794       mnemonic = "adds";
795       if (rd_is_zr) {
796         mnemonic = "cmn";
797         form = form_cmp;
798       }
799       break;
800     }
801     case SUB_w_ext:
802     case SUB_x_ext:
803       mnemonic = "sub";
804       break;
805     case SUBS_w_ext:
806     case SUBS_x_ext: {
807       mnemonic = "subs";
808       if (rd_is_zr) {
809         mnemonic = "cmp";
810         form = form_cmp;
811       }
812       break;
813     }
814     default:
815       VIXL_UNREACHABLE();
816   }
817   Format(instr, mnemonic, form);
818 }
819 
820 
821 void Disassembler::VisitAddSubWithCarry(const Instruction *instr) {
822   bool rn_is_zr = RnIsZROrSP(instr);
823   const char *mnemonic = "";
824   const char *form = "'Rd, 'Rn, 'Rm";
825   const char *form_neg = "'Rd, 'Rm";
826 
827   switch (instr->Mask(AddSubWithCarryMask)) {
828     case ADC_w:
829     case ADC_x:
830       mnemonic = "adc";
831       break;
832     case ADCS_w:
833     case ADCS_x:
834       mnemonic = "adcs";
835       break;
836     case SBC_w:
837     case SBC_x: {
838       mnemonic = "sbc";
839       if (rn_is_zr) {
840         mnemonic = "ngc";
841         form = form_neg;
842       }
843       break;
844     }
845     case SBCS_w:
846     case SBCS_x: {
847       mnemonic = "sbcs";
848       if (rn_is_zr) {
849         mnemonic = "ngcs";
850         form = form_neg;
851       }
852       break;
853     }
854     default:
855       VIXL_UNREACHABLE();
856   }
857   Format(instr, mnemonic, form);
858 }
859 
860 
861 void Disassembler::VisitRotateRightIntoFlags(const Instruction *instr) {
862   const char *mnemonic = "unimplemented";
863   const char *form = "(RotateRightIntoFlags)";
864 
865   switch (instr->Mask(RotateRightIntoFlagsMask)) {
866     case RMIF:
867       mnemonic = "rmif";
868       form = "'Xn, 'IRr, 'INzcv";
869       break;
870     default:
871       VIXL_UNREACHABLE();
872   }
873 
874   Format(instr, mnemonic, form);
875 }
876 
877 
878 void Disassembler::VisitEvaluateIntoFlags(const Instruction *instr) {
879   const char *mnemonic = "unimplemented";
880   const char *form = "(EvaluateIntoFlags)";
881 
882   switch (instr->Mask(EvaluateIntoFlagsMask)) {
883     case SETF8:
884       mnemonic = "setf8";
885       form = "'Wn";
886       break;
887     case SETF16:
888       mnemonic = "setf16";
889       form = "'Wn";
890       break;
891     default:
892       VIXL_UNREACHABLE();
893   }
894 
895   Format(instr, mnemonic, form);
896 }
897 
898 
899 void Disassembler::VisitLogicalImmediate(const Instruction *instr) {
900   bool rd_is_zr = RdIsZROrSP(instr);
901   bool rn_is_zr = RnIsZROrSP(instr);
902   const char *mnemonic = "";
903   const char *form = "'Rds, 'Rn, 'ITri";
904 
905   if (instr->GetImmLogical() == 0) {
906     // The immediate encoded in the instruction is not in the expected format.
907     Format(instr, "unallocated", "(LogicalImmediate)");
908     return;
909   }
910 
911   switch (instr->Mask(LogicalImmediateMask)) {
912     case AND_w_imm:
913     case AND_x_imm:
914       mnemonic = "and";
915       break;
916     case ORR_w_imm:
917     case ORR_x_imm: {
918       mnemonic = "orr";
919       unsigned reg_size =
920           (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
921       if (rn_is_zr && !IsMovzMovnImm(reg_size, instr->GetImmLogical())) {
922         mnemonic = "mov";
923         form = "'Rds, 'ITri";
924       }
925       break;
926     }
927     case EOR_w_imm:
928     case EOR_x_imm:
929       mnemonic = "eor";
930       break;
931     case ANDS_w_imm:
932     case ANDS_x_imm: {
933       mnemonic = "ands";
934       if (rd_is_zr) {
935         mnemonic = "tst";
936         form = "'Rn, 'ITri";
937       }
938       break;
939     }
940     default:
941       VIXL_UNREACHABLE();
942   }
943   Format(instr, mnemonic, form);
944 }
945 
946 
947 bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
948   VIXL_ASSERT((reg_size == kXRegSize) ||
949               ((reg_size == kWRegSize) && (value <= 0xffffffff)));
950 
951   // Test for movz: 16 bits set at positions 0, 16, 32 or 48.
952   if (((value & UINT64_C(0xffffffffffff0000)) == 0) ||
953       ((value & UINT64_C(0xffffffff0000ffff)) == 0) ||
954       ((value & UINT64_C(0xffff0000ffffffff)) == 0) ||
955       ((value & UINT64_C(0x0000ffffffffffff)) == 0)) {
956     return true;
957   }
958 
959   // Test for movn: NOT(16 bits set at positions 0, 16, 32 or 48).
960   if ((reg_size == kXRegSize) &&
961       (((~value & UINT64_C(0xffffffffffff0000)) == 0) ||
962        ((~value & UINT64_C(0xffffffff0000ffff)) == 0) ||
963        ((~value & UINT64_C(0xffff0000ffffffff)) == 0) ||
964        ((~value & UINT64_C(0x0000ffffffffffff)) == 0))) {
965     return true;
966   }
967   if ((reg_size == kWRegSize) && (((value & 0xffff0000) == 0xffff0000) ||
968                                   ((value & 0x0000ffff) == 0x0000ffff))) {
969     return true;
970   }
971   return false;
972 }
973 
974 
975 void Disassembler::VisitLogicalShifted(const Instruction *instr) {
976   bool rd_is_zr = RdIsZROrSP(instr);
977   bool rn_is_zr = RnIsZROrSP(instr);
978   const char *mnemonic = "";
979   const char *form = "'Rd, 'Rn, 'Rm'NLo";
980 
981   switch (instr->Mask(LogicalShiftedMask)) {
982     case AND_w:
983     case AND_x:
984       mnemonic = "and";
985       break;
986     case BIC_w:
987     case BIC_x:
988       mnemonic = "bic";
989       break;
990     case EOR_w:
991     case EOR_x:
992       mnemonic = "eor";
993       break;
994     case EON_w:
995     case EON_x:
996       mnemonic = "eon";
997       break;
998     case BICS_w:
999     case BICS_x:
1000       mnemonic = "bics";
1001       break;
1002     case ANDS_w:
1003     case ANDS_x: {
1004       mnemonic = "ands";
1005       if (rd_is_zr) {
1006         mnemonic = "tst";
1007         form = "'Rn, 'Rm'NLo";
1008       }
1009       break;
1010     }
1011     case ORR_w:
1012     case ORR_x: {
1013       mnemonic = "orr";
1014       if (rn_is_zr && (instr->GetImmDPShift() == 0) &&
1015           (instr->GetShiftDP() == LSL)) {
1016         mnemonic = "mov";
1017         form = "'Rd, 'Rm";
1018       }
1019       break;
1020     }
1021     case ORN_w:
1022     case ORN_x: {
1023       mnemonic = "orn";
1024       if (rn_is_zr) {
1025         mnemonic = "mvn";
1026         form = "'Rd, 'Rm'NLo";
1027       }
1028       break;
1029     }
1030     default:
1031       VIXL_UNREACHABLE();
1032   }
1033 
1034   Format(instr, mnemonic, form);
1035 }
1036 
1037 
1038 void Disassembler::VisitConditionalCompareRegister(const Instruction *instr) {
1039   const char *mnemonic = "";
1040   const char *form = "'Rn, 'Rm, 'INzcv, 'Cond";
1041 
1042   switch (instr->Mask(ConditionalCompareRegisterMask)) {
1043     case CCMN_w:
1044     case CCMN_x:
1045       mnemonic = "ccmn";
1046       break;
1047     case CCMP_w:
1048     case CCMP_x:
1049       mnemonic = "ccmp";
1050       break;
1051     default:
1052       VIXL_UNREACHABLE();
1053   }
1054   Format(instr, mnemonic, form);
1055 }
1056 
1057 
1058 void Disassembler::VisitConditionalCompareImmediate(const Instruction *instr) {
1059   const char *mnemonic = "";
1060   const char *form = "'Rn, 'IP, 'INzcv, 'Cond";
1061 
1062   switch (instr->Mask(ConditionalCompareImmediateMask)) {
1063     case CCMN_w_imm:
1064     case CCMN_x_imm:
1065       mnemonic = "ccmn";
1066       break;
1067     case CCMP_w_imm:
1068     case CCMP_x_imm:
1069       mnemonic = "ccmp";
1070       break;
1071     default:
1072       VIXL_UNREACHABLE();
1073   }
1074   Format(instr, mnemonic, form);
1075 }
1076 
1077 
1078 void Disassembler::VisitConditionalSelect(const Instruction *instr) {
1079   bool rnm_is_zr = (RnIsZROrSP(instr) && RmIsZROrSP(instr));
1080   bool rn_is_rm = (instr->GetRn() == instr->GetRm());
1081   const char *mnemonic = "";
1082   const char *form = "'Rd, 'Rn, 'Rm, 'Cond";
1083   const char *form_test = "'Rd, 'CInv";
1084   const char *form_update = "'Rd, 'Rn, 'CInv";
1085 
1086   Condition cond = static_cast<Condition>(instr->GetCondition());
1087   bool invertible_cond = (cond != al) && (cond != nv);
1088 
1089   switch (instr->Mask(ConditionalSelectMask)) {
1090     case CSEL_w:
1091     case CSEL_x:
1092       mnemonic = "csel";
1093       break;
1094     case CSINC_w:
1095     case CSINC_x: {
1096       mnemonic = "csinc";
1097       if (rnm_is_zr && invertible_cond) {
1098         mnemonic = "cset";
1099         form = form_test;
1100       } else if (rn_is_rm && invertible_cond) {
1101         mnemonic = "cinc";
1102         form = form_update;
1103       }
1104       break;
1105     }
1106     case CSINV_w:
1107     case CSINV_x: {
1108       mnemonic = "csinv";
1109       if (rnm_is_zr && invertible_cond) {
1110         mnemonic = "csetm";
1111         form = form_test;
1112       } else if (rn_is_rm && invertible_cond) {
1113         mnemonic = "cinv";
1114         form = form_update;
1115       }
1116       break;
1117     }
1118     case CSNEG_w:
1119     case CSNEG_x: {
1120       mnemonic = "csneg";
1121       if (rn_is_rm && invertible_cond) {
1122         mnemonic = "cneg";
1123         form = form_update;
1124       }
1125       break;
1126     }
1127     default:
1128       VIXL_UNREACHABLE();
1129   }
1130   Format(instr, mnemonic, form);
1131 }
1132 
1133 
1134 void Disassembler::VisitBitfield(const Instruction *instr) {
1135   unsigned s = instr->GetImmS();
1136   unsigned r = instr->GetImmR();
1137   unsigned rd_size_minus_1 =
1138       ((instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize) - 1;
1139   const char *mnemonic = "";
1140   const char *form = "";
1141   const char *form_shift_right = "'Rd, 'Rn, 'IBr";
1142   const char *form_extend = "'Rd, 'Wn";
1143   const char *form_bfiz = "'Rd, 'Rn, 'IBZ-r, 'IBs+1";
1144   const char *form_bfc = "'Rd, 'IBZ-r, 'IBs+1";
1145   const char *form_bfx = "'Rd, 'Rn, 'IBr, 'IBs-r+1";
1146   const char *form_lsl = "'Rd, 'Rn, 'IBZ-r";
1147 
1148   if (instr->GetSixtyFourBits() != instr->GetBitN()) {
1149     VisitUnallocated(instr);
1150     return;
1151   }
1152 
1153   if ((instr->GetSixtyFourBits() == 0) && ((s > 31) || (r > 31))) {
1154     VisitUnallocated(instr);
1155     return;
1156   }
1157 
1158   switch (instr->Mask(BitfieldMask)) {
1159     case SBFM_w:
1160     case SBFM_x: {
1161       mnemonic = "sbfx";
1162       form = form_bfx;
1163       if (r == 0) {
1164         form = form_extend;
1165         if (s == 7) {
1166           mnemonic = "sxtb";
1167         } else if (s == 15) {
1168           mnemonic = "sxth";
1169         } else if ((s == 31) && (instr->GetSixtyFourBits() == 1)) {
1170           mnemonic = "sxtw";
1171         } else {
1172           form = form_bfx;
1173         }
1174       } else if (s == rd_size_minus_1) {
1175         mnemonic = "asr";
1176         form = form_shift_right;
1177       } else if (s < r) {
1178         mnemonic = "sbfiz";
1179         form = form_bfiz;
1180       }
1181       break;
1182     }
1183     case UBFM_w:
1184     case UBFM_x: {
1185       mnemonic = "ubfx";
1186       form = form_bfx;
1187       if (r == 0) {
1188         form = form_extend;
1189         if (s == 7) {
1190           mnemonic = "uxtb";
1191         } else if (s == 15) {
1192           mnemonic = "uxth";
1193         } else {
1194           form = form_bfx;
1195         }
1196       }
1197       if (s == rd_size_minus_1) {
1198         mnemonic = "lsr";
1199         form = form_shift_right;
1200       } else if (r == s + 1) {
1201         mnemonic = "lsl";
1202         form = form_lsl;
1203       } else if (s < r) {
1204         mnemonic = "ubfiz";
1205         form = form_bfiz;
1206       }
1207       break;
1208     }
1209     case BFM_w:
1210     case BFM_x: {
1211       mnemonic = "bfxil";
1212       form = form_bfx;
1213       if (s < r) {
1214         if (instr->GetRn() == kZeroRegCode) {
1215           mnemonic = "bfc";
1216           form = form_bfc;
1217         } else {
1218           mnemonic = "bfi";
1219           form = form_bfiz;
1220         }
1221       }
1222     }
1223   }
1224   Format(instr, mnemonic, form);
1225 }
1226 
1227 
1228 void Disassembler::VisitExtract(const Instruction *instr) {
1229   const char *mnemonic = "";
1230   const char *form = "'Rd, 'Rn, 'Rm, 'IExtract";
1231 
1232   switch (instr->Mask(ExtractMask)) {
1233     case EXTR_w:
1234     case EXTR_x: {
1235       if (instr->GetRn() == instr->GetRm()) {
1236         mnemonic = "ror";
1237         form = "'Rd, 'Rn, 'IExtract";
1238       } else {
1239         mnemonic = "extr";
1240       }
1241       break;
1242     }
1243     default:
1244       VIXL_UNREACHABLE();
1245   }
1246   Format(instr, mnemonic, form);
1247 }
1248 
1249 
1250 void Disassembler::VisitPCRelAddressing(const Instruction *instr) {
1251   switch (instr->Mask(PCRelAddressingMask)) {
1252     case ADR:
1253       Format(instr, "adr", "'Xd, 'AddrPCRelByte");
1254       break;
1255     case ADRP:
1256       Format(instr, "adrp", "'Xd, 'AddrPCRelPage");
1257       break;
1258     default:
1259       Format(instr, "unimplemented", "(PCRelAddressing)");
1260   }
1261 }
1262 
1263 
1264 void Disassembler::VisitConditionalBranch(const Instruction *instr) {
1265   switch (instr->Mask(ConditionalBranchMask)) {
1266     case B_cond:
1267       Format(instr, "b.'CBrn", "'TImmCond");
1268       break;
1269     default:
1270       VIXL_UNREACHABLE();
1271   }
1272 }
1273 
1274 
1275 void Disassembler::VisitUnconditionalBranchToRegister(
1276     const Instruction *instr) {
1277   const char *mnemonic = mnemonic_.c_str();
1278   const char *form = "'Xn";
1279 
1280   switch (form_hash_) {
1281     case Hash("ret_64r_branch_reg"):
1282       if (instr->GetRn() == kLinkRegCode) {
1283         form = "";
1284       }
1285       break;
1286     case Hash("retaa_64e_branch_reg"):
1287     case Hash("retab_64e_branch_reg"):
1288       form = "";
1289       break;
1290     case Hash("braa_64p_branch_reg"):
1291     case Hash("brab_64p_branch_reg"):
1292     case Hash("blraa_64p_branch_reg"):
1293     case Hash("blrab_64p_branch_reg"):
1294       form = "'Xn, 'Xds";
1295       break;
1296   }
1297 
1298   Format(instr, mnemonic, form);
1299 }
1300 
1301 
1302 void Disassembler::VisitUnconditionalBranch(const Instruction *instr) {
1303   const char *mnemonic = "";
1304   const char *form = "'TImmUncn";
1305 
1306   switch (instr->Mask(UnconditionalBranchMask)) {
1307     case B:
1308       mnemonic = "b";
1309       break;
1310     case BL:
1311       mnemonic = "bl";
1312       break;
1313     default:
1314       VIXL_UNREACHABLE();
1315   }
1316   Format(instr, mnemonic, form);
1317 }
1318 
1319 
1320 void Disassembler::VisitDataProcessing1Source(const Instruction *instr) {
1321   const char *mnemonic = "";
1322   const char *form = "'Rd, 'Rn";
1323 
1324   switch (instr->Mask(DataProcessing1SourceMask)) {
1325 #define FORMAT(A, B) \
1326   case A##_w:        \
1327   case A##_x:        \
1328     mnemonic = B;    \
1329     break;
1330     FORMAT(RBIT, "rbit");
1331     FORMAT(REV16, "rev16");
1332     FORMAT(REV, "rev");
1333     FORMAT(CLZ, "clz");
1334     FORMAT(CLS, "cls");
1335 #undef FORMAT
1336 
1337 #define PAUTH_VARIATIONS(V) \
1338   V(PACI, "paci")           \
1339   V(PACD, "pacd")           \
1340   V(AUTI, "auti")           \
1341   V(AUTD, "autd")
1342 #define PAUTH_CASE(NAME, MN) \
1343   case NAME##A:              \
1344     mnemonic = MN "a";       \
1345     form = "'Xd, 'Xns";      \
1346     break;                   \
1347   case NAME##ZA:             \
1348     mnemonic = MN "za";      \
1349     form = "'Xd";            \
1350     break;                   \
1351   case NAME##B:              \
1352     mnemonic = MN "b";       \
1353     form = "'Xd, 'Xns";      \
1354     break;                   \
1355   case NAME##ZB:             \
1356     mnemonic = MN "zb";      \
1357     form = "'Xd";            \
1358     break;
1359 
1360     PAUTH_VARIATIONS(PAUTH_CASE)
1361 #undef PAUTH_CASE
1362 
1363     case XPACI:
1364       mnemonic = "xpaci";
1365       form = "'Xd";
1366       break;
1367     case XPACD:
1368       mnemonic = "xpacd";
1369       form = "'Xd";
1370       break;
1371     case REV32_x:
1372       mnemonic = "rev32";
1373       break;
1374     default:
1375       VIXL_UNREACHABLE();
1376   }
1377   Format(instr, mnemonic, form);
1378 }
1379 
1380 
1381 void Disassembler::VisitDataProcessing2Source(const Instruction *instr) {
1382   const char *mnemonic = "unimplemented";
1383   const char *form = "'Rd, 'Rn, 'Rm";
1384   const char *form_wwx = "'Wd, 'Wn, 'Xm";
1385 
1386   switch (instr->Mask(DataProcessing2SourceMask)) {
1387 #define FORMAT(A, B) \
1388   case A##_w:        \
1389   case A##_x:        \
1390     mnemonic = B;    \
1391     break;
1392     FORMAT(UDIV, "udiv");
1393     FORMAT(SDIV, "sdiv");
1394     FORMAT(LSLV, "lsl");
1395     FORMAT(LSRV, "lsr");
1396     FORMAT(ASRV, "asr");
1397     FORMAT(RORV, "ror");
1398 #undef FORMAT
1399     case PACGA:
1400       mnemonic = "pacga";
1401       form = "'Xd, 'Xn, 'Xms";
1402       break;
1403     case CRC32B:
1404       mnemonic = "crc32b";
1405       break;
1406     case CRC32H:
1407       mnemonic = "crc32h";
1408       break;
1409     case CRC32W:
1410       mnemonic = "crc32w";
1411       break;
1412     case CRC32X:
1413       mnemonic = "crc32x";
1414       form = form_wwx;
1415       break;
1416     case CRC32CB:
1417       mnemonic = "crc32cb";
1418       break;
1419     case CRC32CH:
1420       mnemonic = "crc32ch";
1421       break;
1422     case CRC32CW:
1423       mnemonic = "crc32cw";
1424       break;
1425     case CRC32CX:
1426       mnemonic = "crc32cx";
1427       form = form_wwx;
1428       break;
1429     default:
1430       form = "(DataProcessing2Source)";
1431   }
1432   Format(instr, mnemonic, form);
1433 }
1434 
1435 
1436 void Disassembler::VisitDataProcessing3Source(const Instruction *instr) {
1437   bool ra_is_zr = RaIsZROrSP(instr);
1438   const char *mnemonic = "";
1439   const char *form = "'Xd, 'Wn, 'Wm, 'Xa";
1440   const char *form_rrr = "'Rd, 'Rn, 'Rm";
1441   const char *form_rrrr = "'Rd, 'Rn, 'Rm, 'Ra";
1442   const char *form_xww = "'Xd, 'Wn, 'Wm";
1443   const char *form_xxx = "'Xd, 'Xn, 'Xm";
1444 
1445   switch (instr->Mask(DataProcessing3SourceMask)) {
1446     case MADD_w:
1447     case MADD_x: {
1448       mnemonic = "madd";
1449       form = form_rrrr;
1450       if (ra_is_zr) {
1451         mnemonic = "mul";
1452         form = form_rrr;
1453       }
1454       break;
1455     }
1456     case MSUB_w:
1457     case MSUB_x: {
1458       mnemonic = "msub";
1459       form = form_rrrr;
1460       if (ra_is_zr) {
1461         mnemonic = "mneg";
1462         form = form_rrr;
1463       }
1464       break;
1465     }
1466     case SMADDL_x: {
1467       mnemonic = "smaddl";
1468       if (ra_is_zr) {
1469         mnemonic = "smull";
1470         form = form_xww;
1471       }
1472       break;
1473     }
1474     case SMSUBL_x: {
1475       mnemonic = "smsubl";
1476       if (ra_is_zr) {
1477         mnemonic = "smnegl";
1478         form = form_xww;
1479       }
1480       break;
1481     }
1482     case UMADDL_x: {
1483       mnemonic = "umaddl";
1484       if (ra_is_zr) {
1485         mnemonic = "umull";
1486         form = form_xww;
1487       }
1488       break;
1489     }
1490     case UMSUBL_x: {
1491       mnemonic = "umsubl";
1492       if (ra_is_zr) {
1493         mnemonic = "umnegl";
1494         form = form_xww;
1495       }
1496       break;
1497     }
1498     case SMULH_x: {
1499       mnemonic = "smulh";
1500       form = form_xxx;
1501       break;
1502     }
1503     case UMULH_x: {
1504       mnemonic = "umulh";
1505       form = form_xxx;
1506       break;
1507     }
1508     default:
1509       VIXL_UNREACHABLE();
1510   }
1511   Format(instr, mnemonic, form);
1512 }
1513 
1514 
1515 void Disassembler::VisitCompareBranch(const Instruction *instr) {
1516   const char *mnemonic = "";
1517   const char *form = "'Rt, 'TImmCmpa";
1518 
1519   switch (instr->Mask(CompareBranchMask)) {
1520     case CBZ_w:
1521     case CBZ_x:
1522       mnemonic = "cbz";
1523       break;
1524     case CBNZ_w:
1525     case CBNZ_x:
1526       mnemonic = "cbnz";
1527       break;
1528     default:
1529       VIXL_UNREACHABLE();
1530   }
1531   Format(instr, mnemonic, form);
1532 }
1533 
1534 
1535 void Disassembler::VisitTestBranch(const Instruction *instr) {
1536   const char *mnemonic = "";
1537   // If the top bit of the immediate is clear, the tested register is
1538   // disassembled as Wt, otherwise Xt. As the top bit of the immediate is
1539   // encoded in bit 31 of the instruction, we can reuse the Rt form, which
1540   // uses bit 31 (normally "sf") to choose the register size.
1541   const char *form = "'Rt, 'It, 'TImmTest";
1542 
1543   switch (instr->Mask(TestBranchMask)) {
1544     case TBZ:
1545       mnemonic = "tbz";
1546       break;
1547     case TBNZ:
1548       mnemonic = "tbnz";
1549       break;
1550     default:
1551       VIXL_UNREACHABLE();
1552   }
1553   Format(instr, mnemonic, form);
1554 }
1555 
1556 
1557 void Disassembler::VisitMoveWideImmediate(const Instruction *instr) {
1558   const char *mnemonic = "";
1559   const char *form = "'Rd, 'IMoveImm";
1560 
1561   // Print the shift separately for movk, to make it clear which half word will
1562   // be overwritten. Movn and movz print the computed immediate, which includes
1563   // shift calculation.
1564   switch (instr->Mask(MoveWideImmediateMask)) {
1565     case MOVN_w:
1566     case MOVN_x:
1567       if ((instr->GetImmMoveWide()) || (instr->GetShiftMoveWide() == 0)) {
1568         if ((instr->GetSixtyFourBits() == 0) &&
1569             (instr->GetImmMoveWide() == 0xffff)) {
1570           mnemonic = "movn";
1571         } else {
1572           mnemonic = "mov";
1573           form = "'Rd, 'IMoveNeg";
1574         }
1575       } else {
1576         mnemonic = "movn";
1577       }
1578       break;
1579     case MOVZ_w:
1580     case MOVZ_x:
1581       if ((instr->GetImmMoveWide()) || (instr->GetShiftMoveWide() == 0))
1582         mnemonic = "mov";
1583       else
1584         mnemonic = "movz";
1585       break;
1586     case MOVK_w:
1587     case MOVK_x:
1588       mnemonic = "movk";
1589       form = "'Rd, 'IMoveLSL";
1590       break;
1591     default:
1592       VIXL_UNREACHABLE();
1593   }
1594   Format(instr, mnemonic, form);
1595 }
1596 
1597 
1598 #define LOAD_STORE_LIST(V)   \
1599   V(STRB_w, "strb", "'Wt")   \
1600   V(STRH_w, "strh", "'Wt")   \
1601   V(STR_w, "str", "'Wt")     \
1602   V(STR_x, "str", "'Xt")     \
1603   V(LDRB_w, "ldrb", "'Wt")   \
1604   V(LDRH_w, "ldrh", "'Wt")   \
1605   V(LDR_w, "ldr", "'Wt")     \
1606   V(LDR_x, "ldr", "'Xt")     \
1607   V(LDRSB_x, "ldrsb", "'Xt") \
1608   V(LDRSH_x, "ldrsh", "'Xt") \
1609   V(LDRSW_x, "ldrsw", "'Xt") \
1610   V(LDRSB_w, "ldrsb", "'Wt") \
1611   V(LDRSH_w, "ldrsh", "'Wt") \
1612   V(STR_b, "str", "'Bt")     \
1613   V(STR_h, "str", "'Ht")     \
1614   V(STR_s, "str", "'St")     \
1615   V(STR_d, "str", "'Dt")     \
1616   V(LDR_b, "ldr", "'Bt")     \
1617   V(LDR_h, "ldr", "'Ht")     \
1618   V(LDR_s, "ldr", "'St")     \
1619   V(LDR_d, "ldr", "'Dt")     \
1620   V(STR_q, "str", "'Qt")     \
1621   V(LDR_q, "ldr", "'Qt")
1622 
1623 void Disassembler::VisitLoadStorePreIndex(const Instruction *instr) {
1624   const char *mnemonic = "unimplemented";
1625   const char *form = "(LoadStorePreIndex)";
1626 
1627   switch (instr->Mask(LoadStorePreIndexMask)) {
1628 #define LS_PREINDEX(A, B, C)   \
1629   case A##_pre:                \
1630     mnemonic = B;              \
1631     form = C ", ['Xns'ILSi]!"; \
1632     break;
1633     LOAD_STORE_LIST(LS_PREINDEX)
1634 #undef LS_PREINDEX
1635   }
1636   Format(instr, mnemonic, form);
1637 }
1638 
1639 
1640 void Disassembler::VisitLoadStorePostIndex(const Instruction *instr) {
1641   const char *mnemonic = "unimplemented";
1642   const char *form = "(LoadStorePostIndex)";
1643 
1644   switch (instr->Mask(LoadStorePostIndexMask)) {
1645 #define LS_POSTINDEX(A, B, C) \
1646   case A##_post:              \
1647     mnemonic = B;             \
1648     form = C ", ['Xns]'ILSi"; \
1649     break;
1650     LOAD_STORE_LIST(LS_POSTINDEX)
1651 #undef LS_POSTINDEX
1652   }
1653   Format(instr, mnemonic, form);
1654 }
1655 
1656 
1657 void Disassembler::VisitLoadStoreUnsignedOffset(const Instruction *instr) {
1658   const char *mnemonic = "unimplemented";
1659   const char *form = "(LoadStoreUnsignedOffset)";
1660 
1661   switch (instr->Mask(LoadStoreUnsignedOffsetMask)) {
1662 #define LS_UNSIGNEDOFFSET(A, B, C) \
1663   case A##_unsigned:               \
1664     mnemonic = B;                  \
1665     form = C ", ['Xns'ILU]";       \
1666     break;
1667     LOAD_STORE_LIST(LS_UNSIGNEDOFFSET)
1668 #undef LS_UNSIGNEDOFFSET
1669     case PRFM_unsigned:
1670       mnemonic = "prfm";
1671       form = "'prefOp, ['Xns'ILU]";
1672   }
1673   Format(instr, mnemonic, form);
1674 }
1675 
1676 
1677 void Disassembler::VisitLoadStoreRCpcUnscaledOffset(const Instruction *instr) {
1678   const char *mnemonic;
1679   const char *form = "'Wt, ['Xns'ILS]";
1680   const char *form_x = "'Xt, ['Xns'ILS]";
1681 
1682   switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
1683     case STLURB:
1684       mnemonic = "stlurb";
1685       break;
1686     case LDAPURB:
1687       mnemonic = "ldapurb";
1688       break;
1689     case LDAPURSB_w:
1690       mnemonic = "ldapursb";
1691       break;
1692     case LDAPURSB_x:
1693       mnemonic = "ldapursb";
1694       form = form_x;
1695       break;
1696     case STLURH:
1697       mnemonic = "stlurh";
1698       break;
1699     case LDAPURH:
1700       mnemonic = "ldapurh";
1701       break;
1702     case LDAPURSH_w:
1703       mnemonic = "ldapursh";
1704       break;
1705     case LDAPURSH_x:
1706       mnemonic = "ldapursh";
1707       form = form_x;
1708       break;
1709     case STLUR_w:
1710       mnemonic = "stlur";
1711       break;
1712     case LDAPUR_w:
1713       mnemonic = "ldapur";
1714       break;
1715     case LDAPURSW:
1716       mnemonic = "ldapursw";
1717       form = form_x;
1718       break;
1719     case STLUR_x:
1720       mnemonic = "stlur";
1721       form = form_x;
1722       break;
1723     case LDAPUR_x:
1724       mnemonic = "ldapur";
1725       form = form_x;
1726       break;
1727     default:
1728       mnemonic = "unimplemented";
1729       form = "(LoadStoreRCpcUnscaledOffset)";
1730   }
1731 
1732   Format(instr, mnemonic, form);
1733 }
1734 
1735 
1736 void Disassembler::VisitLoadStoreRegisterOffset(const Instruction *instr) {
1737   const char *mnemonic = "unimplemented";
1738   const char *form = "(LoadStoreRegisterOffset)";
1739 
1740   switch (instr->Mask(LoadStoreRegisterOffsetMask)) {
1741 #define LS_REGISTEROFFSET(A, B, C)   \
1742   case A##_reg:                      \
1743     mnemonic = B;                    \
1744     form = C ", ['Xns, 'Offsetreg]"; \
1745     break;
1746     LOAD_STORE_LIST(LS_REGISTEROFFSET)
1747 #undef LS_REGISTEROFFSET
1748     case PRFM_reg:
1749       mnemonic = "prfm";
1750       form = "'prefOp, ['Xns, 'Offsetreg]";
1751   }
1752   Format(instr, mnemonic, form);
1753 }
1754 
1755 
1756 void Disassembler::VisitLoadStoreUnscaledOffset(const Instruction *instr) {
1757   const char *mnemonic = "unimplemented";
1758   const char *form = "'Wt, ['Xns'ILS]";
1759   const char *form_x = "'Xt, ['Xns'ILS]";
1760   const char *form_b = "'Bt, ['Xns'ILS]";
1761   const char *form_h = "'Ht, ['Xns'ILS]";
1762   const char *form_s = "'St, ['Xns'ILS]";
1763   const char *form_d = "'Dt, ['Xns'ILS]";
1764   const char *form_q = "'Qt, ['Xns'ILS]";
1765   const char *form_prefetch = "'prefOp, ['Xns'ILS]";
1766 
1767   switch (instr->Mask(LoadStoreUnscaledOffsetMask)) {
1768     case STURB_w:
1769       mnemonic = "sturb";
1770       break;
1771     case STURH_w:
1772       mnemonic = "sturh";
1773       break;
1774     case STUR_w:
1775       mnemonic = "stur";
1776       break;
1777     case STUR_x:
1778       mnemonic = "stur";
1779       form = form_x;
1780       break;
1781     case STUR_b:
1782       mnemonic = "stur";
1783       form = form_b;
1784       break;
1785     case STUR_h:
1786       mnemonic = "stur";
1787       form = form_h;
1788       break;
1789     case STUR_s:
1790       mnemonic = "stur";
1791       form = form_s;
1792       break;
1793     case STUR_d:
1794       mnemonic = "stur";
1795       form = form_d;
1796       break;
1797     case STUR_q:
1798       mnemonic = "stur";
1799       form = form_q;
1800       break;
1801     case LDURB_w:
1802       mnemonic = "ldurb";
1803       break;
1804     case LDURH_w:
1805       mnemonic = "ldurh";
1806       break;
1807     case LDUR_w:
1808       mnemonic = "ldur";
1809       break;
1810     case LDUR_x:
1811       mnemonic = "ldur";
1812       form = form_x;
1813       break;
1814     case LDUR_b:
1815       mnemonic = "ldur";
1816       form = form_b;
1817       break;
1818     case LDUR_h:
1819       mnemonic = "ldur";
1820       form = form_h;
1821       break;
1822     case LDUR_s:
1823       mnemonic = "ldur";
1824       form = form_s;
1825       break;
1826     case LDUR_d:
1827       mnemonic = "ldur";
1828       form = form_d;
1829       break;
1830     case LDUR_q:
1831       mnemonic = "ldur";
1832       form = form_q;
1833       break;
1834     case LDURSB_x:
1835       form = form_x;
1836       VIXL_FALLTHROUGH();
1837     case LDURSB_w:
1838       mnemonic = "ldursb";
1839       break;
1840     case LDURSH_x:
1841       form = form_x;
1842       VIXL_FALLTHROUGH();
1843     case LDURSH_w:
1844       mnemonic = "ldursh";
1845       break;
1846     case LDURSW_x:
1847       mnemonic = "ldursw";
1848       form = form_x;
1849       break;
1850     case PRFUM:
1851       mnemonic = "prfum";
1852       form = form_prefetch;
1853       break;
1854     default:
1855       form = "(LoadStoreUnscaledOffset)";
1856   }
1857   Format(instr, mnemonic, form);
1858 }
1859 
1860 
1861 void Disassembler::VisitLoadLiteral(const Instruction *instr) {
1862   const char *mnemonic = "ldr";
1863   const char *form = "(LoadLiteral)";
1864 
1865   switch (instr->Mask(LoadLiteralMask)) {
1866     case LDR_w_lit:
1867       form = "'Wt, 'ILLiteral 'LValue";
1868       break;
1869     case LDR_x_lit:
1870       form = "'Xt, 'ILLiteral 'LValue";
1871       break;
1872     case LDR_s_lit:
1873       form = "'St, 'ILLiteral 'LValue";
1874       break;
1875     case LDR_d_lit:
1876       form = "'Dt, 'ILLiteral 'LValue";
1877       break;
1878     case LDR_q_lit:
1879       form = "'Qt, 'ILLiteral 'LValue";
1880       break;
1881     case LDRSW_x_lit: {
1882       mnemonic = "ldrsw";
1883       form = "'Xt, 'ILLiteral 'LValue";
1884       break;
1885     }
1886     case PRFM_lit: {
1887       mnemonic = "prfm";
1888       form = "'prefOp, 'ILLiteral 'LValue";
1889       break;
1890     }
1891     default:
1892       mnemonic = "unimplemented";
1893   }
1894   Format(instr, mnemonic, form);
1895 }
1896 
1897 
1898 #define LOAD_STORE_PAIR_LIST(V)         \
1899   V(STP_w, "stp", "'Wt, 'Wt2", "2")     \
1900   V(LDP_w, "ldp", "'Wt, 'Wt2", "2")     \
1901   V(LDPSW_x, "ldpsw", "'Xt, 'Xt2", "2") \
1902   V(STP_x, "stp", "'Xt, 'Xt2", "3")     \
1903   V(LDP_x, "ldp", "'Xt, 'Xt2", "3")     \
1904   V(STP_s, "stp", "'St, 'St2", "2")     \
1905   V(LDP_s, "ldp", "'St, 'St2", "2")     \
1906   V(STP_d, "stp", "'Dt, 'Dt2", "3")     \
1907   V(LDP_d, "ldp", "'Dt, 'Dt2", "3")     \
1908   V(LDP_q, "ldp", "'Qt, 'Qt2", "4")     \
1909   V(STP_q, "stp", "'Qt, 'Qt2", "4")
1910 
1911 void Disassembler::VisitLoadStorePairPostIndex(const Instruction *instr) {
1912   const char *mnemonic = "unimplemented";
1913   const char *form = "(LoadStorePairPostIndex)";
1914 
1915   switch (instr->Mask(LoadStorePairPostIndexMask)) {
1916 #define LSP_POSTINDEX(A, B, C, D)  \
1917   case A##_post:                   \
1918     mnemonic = B;                  \
1919     form = C ", ['Xns]'ILP" D "i"; \
1920     break;
1921     LOAD_STORE_PAIR_LIST(LSP_POSTINDEX)
1922 #undef LSP_POSTINDEX
1923   }
1924   Format(instr, mnemonic, form);
1925 }
1926 
1927 
1928 void Disassembler::VisitLoadStorePairPreIndex(const Instruction *instr) {
1929   const char *mnemonic = "unimplemented";
1930   const char *form = "(LoadStorePairPreIndex)";
1931 
1932   switch (instr->Mask(LoadStorePairPreIndexMask)) {
1933 #define LSP_PREINDEX(A, B, C, D)    \
1934   case A##_pre:                     \
1935     mnemonic = B;                   \
1936     form = C ", ['Xns'ILP" D "i]!"; \
1937     break;
1938     LOAD_STORE_PAIR_LIST(LSP_PREINDEX)
1939 #undef LSP_PREINDEX
1940   }
1941   Format(instr, mnemonic, form);
1942 }
1943 
1944 
1945 void Disassembler::VisitLoadStorePairOffset(const Instruction *instr) {
1946   const char *mnemonic = "unimplemented";
1947   const char *form = "(LoadStorePairOffset)";
1948 
1949   switch (instr->Mask(LoadStorePairOffsetMask)) {
1950 #define LSP_OFFSET(A, B, C, D)    \
1951   case A##_off:                   \
1952     mnemonic = B;                 \
1953     form = C ", ['Xns'ILP" D "]"; \
1954     break;
1955     LOAD_STORE_PAIR_LIST(LSP_OFFSET)
1956 #undef LSP_OFFSET
1957   }
1958   Format(instr, mnemonic, form);
1959 }
1960 
1961 
1962 void Disassembler::VisitLoadStorePairNonTemporal(const Instruction *instr) {
1963   const char *mnemonic = "unimplemented";
1964   const char *form;
1965 
1966   switch (instr->Mask(LoadStorePairNonTemporalMask)) {
1967     case STNP_w:
1968       mnemonic = "stnp";
1969       form = "'Wt, 'Wt2, ['Xns'ILP2]";
1970       break;
1971     case LDNP_w:
1972       mnemonic = "ldnp";
1973       form = "'Wt, 'Wt2, ['Xns'ILP2]";
1974       break;
1975     case STNP_x:
1976       mnemonic = "stnp";
1977       form = "'Xt, 'Xt2, ['Xns'ILP3]";
1978       break;
1979     case LDNP_x:
1980       mnemonic = "ldnp";
1981       form = "'Xt, 'Xt2, ['Xns'ILP3]";
1982       break;
1983     case STNP_s:
1984       mnemonic = "stnp";
1985       form = "'St, 'St2, ['Xns'ILP2]";
1986       break;
1987     case LDNP_s:
1988       mnemonic = "ldnp";
1989       form = "'St, 'St2, ['Xns'ILP2]";
1990       break;
1991     case STNP_d:
1992       mnemonic = "stnp";
1993       form = "'Dt, 'Dt2, ['Xns'ILP3]";
1994       break;
1995     case LDNP_d:
1996       mnemonic = "ldnp";
1997       form = "'Dt, 'Dt2, ['Xns'ILP3]";
1998       break;
1999     case STNP_q:
2000       mnemonic = "stnp";
2001       form = "'Qt, 'Qt2, ['Xns'ILP4]";
2002       break;
2003     case LDNP_q:
2004       mnemonic = "ldnp";
2005       form = "'Qt, 'Qt2, ['Xns'ILP4]";
2006       break;
2007     default:
2008       form = "(LoadStorePairNonTemporal)";
2009   }
2010   Format(instr, mnemonic, form);
2011 }
2012 
2013 // clang-format off
2014 #define LOAD_STORE_EXCLUSIVE_LIST(V)                  \
2015   V(STXRB_w,  "stxrb",  "'Ws, 'Wt")                   \
2016   V(STXRH_w,  "stxrh",  "'Ws, 'Wt")                   \
2017   V(STXR_w,   "stxr",   "'Ws, 'Wt")                   \
2018   V(STXR_x,   "stxr",   "'Ws, 'Xt")                   \
2019   V(LDXRB_w,  "ldxrb",  "'Wt")                        \
2020   V(LDXRH_w,  "ldxrh",  "'Wt")                        \
2021   V(LDXR_w,   "ldxr",   "'Wt")                        \
2022   V(LDXR_x,   "ldxr",   "'Xt")                        \
2023   V(STXP_w,   "stxp",   "'Ws, 'Wt, 'Wt2")             \
2024   V(STXP_x,   "stxp",   "'Ws, 'Xt, 'Xt2")             \
2025   V(LDXP_w,   "ldxp",   "'Wt, 'Wt2")                  \
2026   V(LDXP_x,   "ldxp",   "'Xt, 'Xt2")                  \
2027   V(STLXRB_w, "stlxrb", "'Ws, 'Wt")                   \
2028   V(STLXRH_w, "stlxrh", "'Ws, 'Wt")                   \
2029   V(STLXR_w,  "stlxr",  "'Ws, 'Wt")                   \
2030   V(STLXR_x,  "stlxr",  "'Ws, 'Xt")                   \
2031   V(LDAXRB_w, "ldaxrb", "'Wt")                        \
2032   V(LDAXRH_w, "ldaxrh", "'Wt")                        \
2033   V(LDAXR_w,  "ldaxr",  "'Wt")                        \
2034   V(LDAXR_x,  "ldaxr",  "'Xt")                        \
2035   V(STLXP_w,  "stlxp",  "'Ws, 'Wt, 'Wt2")             \
2036   V(STLXP_x,  "stlxp",  "'Ws, 'Xt, 'Xt2")             \
2037   V(LDAXP_w,  "ldaxp",  "'Wt, 'Wt2")                  \
2038   V(LDAXP_x,  "ldaxp",  "'Xt, 'Xt2")                  \
2039   V(STLRB_w,  "stlrb",  "'Wt")                        \
2040   V(STLRH_w,  "stlrh",  "'Wt")                        \
2041   V(STLR_w,   "stlr",   "'Wt")                        \
2042   V(STLR_x,   "stlr",   "'Xt")                        \
2043   V(LDARB_w,  "ldarb",  "'Wt")                        \
2044   V(LDARH_w,  "ldarh",  "'Wt")                        \
2045   V(LDAR_w,   "ldar",   "'Wt")                        \
2046   V(LDAR_x,   "ldar",   "'Xt")                        \
2047   V(STLLRB,   "stllrb", "'Wt")                        \
2048   V(STLLRH,   "stllrh", "'Wt")                        \
2049   V(STLLR_w,  "stllr",  "'Wt")                        \
2050   V(STLLR_x,  "stllr",  "'Xt")                        \
2051   V(LDLARB,   "ldlarb", "'Wt")                        \
2052   V(LDLARH,   "ldlarh", "'Wt")                        \
2053   V(LDLAR_w,  "ldlar",  "'Wt")                        \
2054   V(LDLAR_x,  "ldlar",  "'Xt")                        \
2055   V(CAS_w,    "cas",    "'Ws, 'Wt")                   \
2056   V(CAS_x,    "cas",    "'Xs, 'Xt")                   \
2057   V(CASA_w,   "casa",   "'Ws, 'Wt")                   \
2058   V(CASA_x,   "casa",   "'Xs, 'Xt")                   \
2059   V(CASL_w,   "casl",   "'Ws, 'Wt")                   \
2060   V(CASL_x,   "casl",   "'Xs, 'Xt")                   \
2061   V(CASAL_w,  "casal",  "'Ws, 'Wt")                   \
2062   V(CASAL_x,  "casal",  "'Xs, 'Xt")                   \
2063   V(CASB,     "casb",   "'Ws, 'Wt")                   \
2064   V(CASAB,    "casab",  "'Ws, 'Wt")                   \
2065   V(CASLB,    "caslb",  "'Ws, 'Wt")                   \
2066   V(CASALB,   "casalb", "'Ws, 'Wt")                   \
2067   V(CASH,     "cash",   "'Ws, 'Wt")                   \
2068   V(CASAH,    "casah",  "'Ws, 'Wt")                   \
2069   V(CASLH,    "caslh",  "'Ws, 'Wt")                   \
2070   V(CASALH,   "casalh", "'Ws, 'Wt")                   \
2071   V(CASP_w,   "casp",   "'Ws, 'Ws+, 'Wt, 'Wt+")       \
2072   V(CASP_x,   "casp",   "'Xs, 'Xs+, 'Xt, 'Xt+")       \
2073   V(CASPA_w,  "caspa",  "'Ws, 'Ws+, 'Wt, 'Wt+")       \
2074   V(CASPA_x,  "caspa",  "'Xs, 'Xs+, 'Xt, 'Xt+")       \
2075   V(CASPL_w,  "caspl",  "'Ws, 'Ws+, 'Wt, 'Wt+")       \
2076   V(CASPL_x,  "caspl",  "'Xs, 'Xs+, 'Xt, 'Xt+")       \
2077   V(CASPAL_w, "caspal", "'Ws, 'Ws+, 'Wt, 'Wt+")       \
2078   V(CASPAL_x, "caspal", "'Xs, 'Xs+, 'Xt, 'Xt+")
2079 // clang-format on
2080 
2081 
2082 void Disassembler::VisitLoadStoreExclusive(const Instruction *instr) {
2083   const char *mnemonic = "unimplemented";
2084   const char *form;
2085 
2086   switch (instr->Mask(LoadStoreExclusiveMask)) {
2087 #define LSX(A, B, C)     \
2088   case A:                \
2089     mnemonic = B;        \
2090     form = C ", ['Xns]"; \
2091     break;
2092     LOAD_STORE_EXCLUSIVE_LIST(LSX)
2093 #undef LSX
2094     default:
2095       form = "(LoadStoreExclusive)";
2096   }
2097 
2098   switch (instr->Mask(LoadStoreExclusiveMask)) {
2099     case CASP_w:
2100     case CASP_x:
2101     case CASPA_w:
2102     case CASPA_x:
2103     case CASPL_w:
2104     case CASPL_x:
2105     case CASPAL_w:
2106     case CASPAL_x:
2107       if ((instr->GetRs() % 2 == 1) || (instr->GetRt() % 2 == 1)) {
2108         mnemonic = "unallocated";
2109         form = "(LoadStoreExclusive)";
2110       }
2111       break;
2112   }
2113 
2114   Format(instr, mnemonic, form);
2115 }
2116 
2117 void Disassembler::VisitLoadStorePAC(const Instruction *instr) {
2118   const char *mnemonic = "unimplemented";
2119   const char *form = "(LoadStorePAC)";
2120 
2121   switch (instr->Mask(LoadStorePACMask)) {
2122     case LDRAA:
2123       mnemonic = "ldraa";
2124       form = "'Xt, ['Xns'ILA]";
2125       break;
2126     case LDRAB:
2127       mnemonic = "ldrab";
2128       form = "'Xt, ['Xns'ILA]";
2129       break;
2130     case LDRAA_pre:
2131       mnemonic = "ldraa";
2132       form = "'Xt, ['Xns'ILA]!";
2133       break;
2134     case LDRAB_pre:
2135       mnemonic = "ldrab";
2136       form = "'Xt, ['Xns'ILA]!";
2137       break;
2138   }
2139 
2140   Format(instr, mnemonic, form);
2141 }
2142 
2143 #define ATOMIC_MEMORY_SIMPLE_LIST(V) \
2144   V(LDADD, "add")                    \
2145   V(LDCLR, "clr")                    \
2146   V(LDEOR, "eor")                    \
2147   V(LDSET, "set")                    \
2148   V(LDSMAX, "smax")                  \
2149   V(LDSMIN, "smin")                  \
2150   V(LDUMAX, "umax")                  \
2151   V(LDUMIN, "umin")
2152 
2153 void Disassembler::VisitAtomicMemory(const Instruction *instr) {
2154   const int kMaxAtomicOpMnemonicLength = 16;
2155   const char *mnemonic;
2156   const char *form = "'Ws, 'Wt, ['Xns]";
2157 
2158   switch (instr->Mask(AtomicMemoryMask)) {
2159 #define AMS(A, MN)             \
2160   case A##B:                   \
2161     mnemonic = MN "b";         \
2162     break;                     \
2163   case A##AB:                  \
2164     mnemonic = MN "ab";        \
2165     break;                     \
2166   case A##LB:                  \
2167     mnemonic = MN "lb";        \
2168     break;                     \
2169   case A##ALB:                 \
2170     mnemonic = MN "alb";       \
2171     break;                     \
2172   case A##H:                   \
2173     mnemonic = MN "h";         \
2174     break;                     \
2175   case A##AH:                  \
2176     mnemonic = MN "ah";        \
2177     break;                     \
2178   case A##LH:                  \
2179     mnemonic = MN "lh";        \
2180     break;                     \
2181   case A##ALH:                 \
2182     mnemonic = MN "alh";       \
2183     break;                     \
2184   case A##_w:                  \
2185     mnemonic = MN;             \
2186     break;                     \
2187   case A##A_w:                 \
2188     mnemonic = MN "a";         \
2189     break;                     \
2190   case A##L_w:                 \
2191     mnemonic = MN "l";         \
2192     break;                     \
2193   case A##AL_w:                \
2194     mnemonic = MN "al";        \
2195     break;                     \
2196   case A##_x:                  \
2197     mnemonic = MN;             \
2198     form = "'Xs, 'Xt, ['Xns]"; \
2199     break;                     \
2200   case A##A_x:                 \
2201     mnemonic = MN "a";         \
2202     form = "'Xs, 'Xt, ['Xns]"; \
2203     break;                     \
2204   case A##L_x:                 \
2205     mnemonic = MN "l";         \
2206     form = "'Xs, 'Xt, ['Xns]"; \
2207     break;                     \
2208   case A##AL_x:                \
2209     mnemonic = MN "al";        \
2210     form = "'Xs, 'Xt, ['Xns]"; \
2211     break;
2212     ATOMIC_MEMORY_SIMPLE_LIST(AMS)
2213 
2214     // SWP has the same semantics as ldadd etc but without the store aliases.
2215     AMS(SWP, "swp")
2216 #undef AMS
2217 
2218     case LDAPRB:
2219       mnemonic = "ldaprb";
2220       form = "'Wt, ['Xns]";
2221       break;
2222     case LDAPRH:
2223       mnemonic = "ldaprh";
2224       form = "'Wt, ['Xns]";
2225       break;
2226     case LDAPR_w:
2227       mnemonic = "ldapr";
2228       form = "'Wt, ['Xns]";
2229       break;
2230     case LDAPR_x:
2231       mnemonic = "ldapr";
2232       form = "'Xt, ['Xns]";
2233       break;
2234     default:
2235       mnemonic = "unimplemented";
2236       form = "(AtomicMemory)";
2237   }
2238 
2239   const char *prefix = "";
2240   switch (instr->Mask(AtomicMemoryMask)) {
2241 #define AMS(A, MN)                   \
2242   case A##AB:                        \
2243   case A##ALB:                       \
2244   case A##AH:                        \
2245   case A##ALH:                       \
2246   case A##A_w:                       \
2247   case A##AL_w:                      \
2248   case A##A_x:                       \
2249   case A##AL_x:                      \
2250     prefix = "ld";                   \
2251     break;                           \
2252   case A##B:                         \
2253   case A##LB:                        \
2254   case A##H:                         \
2255   case A##LH:                        \
2256   case A##_w:                        \
2257   case A##L_w: {                     \
2258     prefix = "ld";                   \
2259     unsigned rt = instr->GetRt();    \
2260     if (Register(rt, 32).IsZero()) { \
2261       prefix = "st";                 \
2262       form = "'Ws, ['Xns]";          \
2263     }                                \
2264     break;                           \
2265   }                                  \
2266   case A##_x:                        \
2267   case A##L_x: {                     \
2268     prefix = "ld";                   \
2269     unsigned rt = instr->GetRt();    \
2270     if (Register(rt, 64).IsZero()) { \
2271       prefix = "st";                 \
2272       form = "'Xs, ['Xns]";          \
2273     }                                \
2274     break;                           \
2275   }
2276     ATOMIC_MEMORY_SIMPLE_LIST(AMS)
2277 #undef AMS
2278   }
2279 
2280   char buffer[kMaxAtomicOpMnemonicLength];
2281   if (strlen(prefix) > 0) {
2282     snprintf(buffer, kMaxAtomicOpMnemonicLength, "%s%s", prefix, mnemonic);
2283     mnemonic = buffer;
2284   }
2285 
2286   Format(instr, mnemonic, form);
2287 }
2288 
2289 
2290 void Disassembler::VisitFPCompare(const Instruction *instr) {
2291   const char *mnemonic = "unimplemented";
2292   const char *form = "'Fn, 'Fm";
2293   const char *form_zero = "'Fn, #0.0";
2294 
2295   switch (instr->Mask(FPCompareMask)) {
2296     case FCMP_h_zero:
2297     case FCMP_s_zero:
2298     case FCMP_d_zero:
2299       form = form_zero;
2300       VIXL_FALLTHROUGH();
2301     case FCMP_h:
2302     case FCMP_s:
2303     case FCMP_d:
2304       mnemonic = "fcmp";
2305       break;
2306     case FCMPE_h_zero:
2307     case FCMPE_s_zero:
2308     case FCMPE_d_zero:
2309       form = form_zero;
2310       VIXL_FALLTHROUGH();
2311     case FCMPE_h:
2312     case FCMPE_s:
2313     case FCMPE_d:
2314       mnemonic = "fcmpe";
2315       break;
2316     default:
2317       form = "(FPCompare)";
2318   }
2319   Format(instr, mnemonic, form);
2320 }
2321 
2322 
2323 void Disassembler::VisitFPConditionalCompare(const Instruction *instr) {
2324   const char *mnemonic = "unmplemented";
2325   const char *form = "'Fn, 'Fm, 'INzcv, 'Cond";
2326 
2327   switch (instr->Mask(FPConditionalCompareMask)) {
2328     case FCCMP_h:
2329     case FCCMP_s:
2330     case FCCMP_d:
2331       mnemonic = "fccmp";
2332       break;
2333     case FCCMPE_h:
2334     case FCCMPE_s:
2335     case FCCMPE_d:
2336       mnemonic = "fccmpe";
2337       break;
2338     default:
2339       form = "(FPConditionalCompare)";
2340   }
2341   Format(instr, mnemonic, form);
2342 }
2343 
2344 
2345 void Disassembler::VisitFPConditionalSelect(const Instruction *instr) {
2346   const char *mnemonic = "";
2347   const char *form = "'Fd, 'Fn, 'Fm, 'Cond";
2348 
2349   switch (instr->Mask(FPConditionalSelectMask)) {
2350     case FCSEL_h:
2351     case FCSEL_s:
2352     case FCSEL_d:
2353       mnemonic = "fcsel";
2354       break;
2355     default:
2356       VIXL_UNREACHABLE();
2357   }
2358   Format(instr, mnemonic, form);
2359 }
2360 
2361 
2362 void Disassembler::VisitFPDataProcessing1Source(const Instruction *instr) {
2363   const char *mnemonic = "unimplemented";
2364   const char *form = "'Fd, 'Fn";
2365 
2366   switch (instr->Mask(FPDataProcessing1SourceMask)) {
2367 #define FORMAT(A, B) \
2368   case A##_h:        \
2369   case A##_s:        \
2370   case A##_d:        \
2371     mnemonic = B;    \
2372     break;
2373     FORMAT(FMOV, "fmov");
2374     FORMAT(FABS, "fabs");
2375     FORMAT(FNEG, "fneg");
2376     FORMAT(FSQRT, "fsqrt");
2377     FORMAT(FRINTN, "frintn");
2378     FORMAT(FRINTP, "frintp");
2379     FORMAT(FRINTM, "frintm");
2380     FORMAT(FRINTZ, "frintz");
2381     FORMAT(FRINTA, "frinta");
2382     FORMAT(FRINTX, "frintx");
2383     FORMAT(FRINTI, "frinti");
2384 #undef FORMAT
2385 #define FORMAT(A, B) \
2386   case A##_s:        \
2387   case A##_d:        \
2388     mnemonic = B;    \
2389     break;
2390     FORMAT(FRINT32X, "frint32x");
2391     FORMAT(FRINT32Z, "frint32z");
2392     FORMAT(FRINT64X, "frint64x");
2393     FORMAT(FRINT64Z, "frint64z");
2394 #undef FORMAT
2395     case FCVT_ds:
2396       mnemonic = "fcvt";
2397       form = "'Dd, 'Sn";
2398       break;
2399     case FCVT_sd:
2400       mnemonic = "fcvt";
2401       form = "'Sd, 'Dn";
2402       break;
2403     case FCVT_hs:
2404       mnemonic = "fcvt";
2405       form = "'Hd, 'Sn";
2406       break;
2407     case FCVT_sh:
2408       mnemonic = "fcvt";
2409       form = "'Sd, 'Hn";
2410       break;
2411     case FCVT_dh:
2412       mnemonic = "fcvt";
2413       form = "'Dd, 'Hn";
2414       break;
2415     case FCVT_hd:
2416       mnemonic = "fcvt";
2417       form = "'Hd, 'Dn";
2418       break;
2419     default:
2420       form = "(FPDataProcessing1Source)";
2421   }
2422   Format(instr, mnemonic, form);
2423 }
2424 
2425 
2426 void Disassembler::VisitFPDataProcessing2Source(const Instruction *instr) {
2427   const char *mnemonic = "";
2428   const char *form = "'Fd, 'Fn, 'Fm";
2429 
2430   switch (instr->Mask(FPDataProcessing2SourceMask)) {
2431 #define FORMAT(A, B) \
2432   case A##_h:        \
2433   case A##_s:        \
2434   case A##_d:        \
2435     mnemonic = B;    \
2436     break;
2437     FORMAT(FADD, "fadd");
2438     FORMAT(FSUB, "fsub");
2439     FORMAT(FMUL, "fmul");
2440     FORMAT(FDIV, "fdiv");
2441     FORMAT(FMAX, "fmax");
2442     FORMAT(FMIN, "fmin");
2443     FORMAT(FMAXNM, "fmaxnm");
2444     FORMAT(FMINNM, "fminnm");
2445     FORMAT(FNMUL, "fnmul");
2446 #undef FORMAT
2447     default:
2448       VIXL_UNREACHABLE();
2449   }
2450   Format(instr, mnemonic, form);
2451 }
2452 
2453 
2454 void Disassembler::VisitFPDataProcessing3Source(const Instruction *instr) {
2455   const char *mnemonic = "";
2456   const char *form = "'Fd, 'Fn, 'Fm, 'Fa";
2457 
2458   switch (instr->Mask(FPDataProcessing3SourceMask)) {
2459 #define FORMAT(A, B) \
2460   case A##_h:        \
2461   case A##_s:        \
2462   case A##_d:        \
2463     mnemonic = B;    \
2464     break;
2465     FORMAT(FMADD, "fmadd");
2466     FORMAT(FMSUB, "fmsub");
2467     FORMAT(FNMADD, "fnmadd");
2468     FORMAT(FNMSUB, "fnmsub");
2469 #undef FORMAT
2470     default:
2471       VIXL_UNREACHABLE();
2472   }
2473   Format(instr, mnemonic, form);
2474 }
2475 
2476 
2477 void Disassembler::VisitFPImmediate(const Instruction *instr) {
2478   const char *mnemonic = "";
2479   const char *form = "(FPImmediate)";
2480   switch (instr->Mask(FPImmediateMask)) {
2481     case FMOV_h_imm:
2482       mnemonic = "fmov";
2483       form = "'Hd, 'IFP";
2484       break;
2485     case FMOV_s_imm:
2486       mnemonic = "fmov";
2487       form = "'Sd, 'IFP";
2488       break;
2489     case FMOV_d_imm:
2490       mnemonic = "fmov";
2491       form = "'Dd, 'IFP";
2492       break;
2493     default:
2494       VIXL_UNREACHABLE();
2495   }
2496   Format(instr, mnemonic, form);
2497 }
2498 
2499 
2500 void Disassembler::VisitFPIntegerConvert(const Instruction *instr) {
2501   const char *mnemonic = "unimplemented";
2502   const char *form = "(FPIntegerConvert)";
2503   const char *form_rf = "'Rd, 'Fn";
2504   const char *form_fr = "'Fd, 'Rn";
2505 
2506   switch (instr->Mask(FPIntegerConvertMask)) {
2507     case FMOV_wh:
2508     case FMOV_xh:
2509     case FMOV_ws:
2510     case FMOV_xd:
2511       mnemonic = "fmov";
2512       form = form_rf;
2513       break;
2514     case FMOV_hw:
2515     case FMOV_hx:
2516     case FMOV_sw:
2517     case FMOV_dx:
2518       mnemonic = "fmov";
2519       form = form_fr;
2520       break;
2521     case FMOV_d1_x:
2522       mnemonic = "fmov";
2523       form = "'Vd.D[1], 'Rn";
2524       break;
2525     case FMOV_x_d1:
2526       mnemonic = "fmov";
2527       form = "'Rd, 'Vn.D[1]";
2528       break;
2529     case FCVTAS_wh:
2530     case FCVTAS_xh:
2531     case FCVTAS_ws:
2532     case FCVTAS_xs:
2533     case FCVTAS_wd:
2534     case FCVTAS_xd:
2535       mnemonic = "fcvtas";
2536       form = form_rf;
2537       break;
2538     case FCVTAU_wh:
2539     case FCVTAU_xh:
2540     case FCVTAU_ws:
2541     case FCVTAU_xs:
2542     case FCVTAU_wd:
2543     case FCVTAU_xd:
2544       mnemonic = "fcvtau";
2545       form = form_rf;
2546       break;
2547     case FCVTMS_wh:
2548     case FCVTMS_xh:
2549     case FCVTMS_ws:
2550     case FCVTMS_xs:
2551     case FCVTMS_wd:
2552     case FCVTMS_xd:
2553       mnemonic = "fcvtms";
2554       form = form_rf;
2555       break;
2556     case FCVTMU_wh:
2557     case FCVTMU_xh:
2558     case FCVTMU_ws:
2559     case FCVTMU_xs:
2560     case FCVTMU_wd:
2561     case FCVTMU_xd:
2562       mnemonic = "fcvtmu";
2563       form = form_rf;
2564       break;
2565     case FCVTNS_wh:
2566     case FCVTNS_xh:
2567     case FCVTNS_ws:
2568     case FCVTNS_xs:
2569     case FCVTNS_wd:
2570     case FCVTNS_xd:
2571       mnemonic = "fcvtns";
2572       form = form_rf;
2573       break;
2574     case FCVTNU_wh:
2575     case FCVTNU_xh:
2576     case FCVTNU_ws:
2577     case FCVTNU_xs:
2578     case FCVTNU_wd:
2579     case FCVTNU_xd:
2580       mnemonic = "fcvtnu";
2581       form = form_rf;
2582       break;
2583     case FCVTZU_wh:
2584     case FCVTZU_xh:
2585     case FCVTZU_ws:
2586     case FCVTZU_xs:
2587     case FCVTZU_wd:
2588     case FCVTZU_xd:
2589       mnemonic = "fcvtzu";
2590       form = form_rf;
2591       break;
2592     case FCVTZS_wh:
2593     case FCVTZS_xh:
2594     case FCVTZS_ws:
2595     case FCVTZS_xs:
2596     case FCVTZS_wd:
2597     case FCVTZS_xd:
2598       mnemonic = "fcvtzs";
2599       form = form_rf;
2600       break;
2601     case FCVTPU_wh:
2602     case FCVTPU_xh:
2603     case FCVTPU_xs:
2604     case FCVTPU_wd:
2605     case FCVTPU_ws:
2606     case FCVTPU_xd:
2607       mnemonic = "fcvtpu";
2608       form = form_rf;
2609       break;
2610     case FCVTPS_wh:
2611     case FCVTPS_xh:
2612     case FCVTPS_ws:
2613     case FCVTPS_xs:
2614     case FCVTPS_wd:
2615     case FCVTPS_xd:
2616       mnemonic = "fcvtps";
2617       form = form_rf;
2618       break;
2619     case SCVTF_hw:
2620     case SCVTF_hx:
2621     case SCVTF_sw:
2622     case SCVTF_sx:
2623     case SCVTF_dw:
2624     case SCVTF_dx:
2625       mnemonic = "scvtf";
2626       form = form_fr;
2627       break;
2628     case UCVTF_hw:
2629     case UCVTF_hx:
2630     case UCVTF_sw:
2631     case UCVTF_sx:
2632     case UCVTF_dw:
2633     case UCVTF_dx:
2634       mnemonic = "ucvtf";
2635       form = form_fr;
2636       break;
2637     case FJCVTZS:
2638       mnemonic = "fjcvtzs";
2639       form = form_rf;
2640       break;
2641   }
2642   Format(instr, mnemonic, form);
2643 }
2644 
2645 
2646 void Disassembler::VisitFPFixedPointConvert(const Instruction *instr) {
2647   const char *mnemonic = "";
2648   const char *form = "'Rd, 'Fn, 'IFPFBits";
2649   const char *form_fr = "'Fd, 'Rn, 'IFPFBits";
2650 
2651   switch (instr->Mask(FPFixedPointConvertMask)) {
2652     case FCVTZS_wh_fixed:
2653     case FCVTZS_xh_fixed:
2654     case FCVTZS_ws_fixed:
2655     case FCVTZS_xs_fixed:
2656     case FCVTZS_wd_fixed:
2657     case FCVTZS_xd_fixed:
2658       mnemonic = "fcvtzs";
2659       break;
2660     case FCVTZU_wh_fixed:
2661     case FCVTZU_xh_fixed:
2662     case FCVTZU_ws_fixed:
2663     case FCVTZU_xs_fixed:
2664     case FCVTZU_wd_fixed:
2665     case FCVTZU_xd_fixed:
2666       mnemonic = "fcvtzu";
2667       break;
2668     case SCVTF_hw_fixed:
2669     case SCVTF_hx_fixed:
2670     case SCVTF_sw_fixed:
2671     case SCVTF_sx_fixed:
2672     case SCVTF_dw_fixed:
2673     case SCVTF_dx_fixed:
2674       mnemonic = "scvtf";
2675       form = form_fr;
2676       break;
2677     case UCVTF_hw_fixed:
2678     case UCVTF_hx_fixed:
2679     case UCVTF_sw_fixed:
2680     case UCVTF_sx_fixed:
2681     case UCVTF_dw_fixed:
2682     case UCVTF_dx_fixed:
2683       mnemonic = "ucvtf";
2684       form = form_fr;
2685       break;
2686     default:
2687       VIXL_UNREACHABLE();
2688   }
2689   Format(instr, mnemonic, form);
2690 }
2691 
2692 void Disassembler::DisassembleNoArgs(const Instruction *instr) {
2693   Format(instr, mnemonic_.c_str(), "");
2694 }
2695 
2696 void Disassembler::VisitSystem(const Instruction *instr) {
2697   const char *mnemonic = mnemonic_.c_str();
2698   const char *form = "(System)";
2699   const char *suffix = NULL;
2700 
2701   switch (form_hash_) {
2702     case Hash("clrex_bn_barriers"):
2703       form = (instr->GetCRm() == 0xf) ? "" : "'IX";
2704       break;
2705     case Hash("mrs_rs_systemmove"):
2706       form = "'Xt, 'IY";
2707       break;
2708     case Hash("msr_si_pstate"):
2709     case Hash("msr_sr_systemmove"):
2710       form = "'IY, 'Xt";
2711       break;
2712     case Hash("bti_hb_hints"):
2713       switch (instr->ExtractBits(7, 6)) {
2714         case 0:
2715           form = "";
2716           break;
2717         case 1:
2718           form = "c";
2719           break;
2720         case 2:
2721           form = "j";
2722           break;
2723         case 3:
2724           form = "jc";
2725           break;
2726       }
2727       break;
2728     case Hash("hint_hm_hints"):
2729       form = "'IH";
2730       break;
2731     case Hash("dmb_bo_barriers"):
2732     case Hash("dsb_bo_barriers"):
2733       form = "'M";
2734       break;
2735     case Hash("sys_cr_systeminstrs"):
2736       mnemonic = "dc";
2737       suffix = ", 'Xt";
2738       switch (instr->GetSysOp()) {
2739         case IVAU:
2740           mnemonic = "ic";
2741           form = "ivau";
2742           break;
2743         case CVAC:
2744           form = "cvac";
2745           break;
2746         case CVAU:
2747           form = "cvau";
2748           break;
2749         case CVAP:
2750           form = "cvap";
2751           break;
2752         case CVADP:
2753           form = "cvadp";
2754           break;
2755         case CIVAC:
2756           form = "civac";
2757           break;
2758         case ZVA:
2759           form = "zva";
2760           break;
2761         default:
2762           mnemonic = "sys";
2763           form = "'G1, 'Kn, 'Km, 'G2";
2764           if (instr->GetRt() == 31) {
2765             suffix = NULL;
2766           }
2767           break;
2768       }
2769   }
2770   Format(instr, mnemonic, form, suffix);
2771 }
2772 
2773 
2774 void Disassembler::VisitException(const Instruction *instr) {
2775   const char *mnemonic = "unimplemented";
2776   const char *form = "'IDebug";
2777 
2778   switch (instr->Mask(ExceptionMask)) {
2779     case HLT:
2780       mnemonic = "hlt";
2781       break;
2782     case BRK:
2783       mnemonic = "brk";
2784       break;
2785     case SVC:
2786       mnemonic = "svc";
2787       break;
2788     case HVC:
2789       mnemonic = "hvc";
2790       break;
2791     case SMC:
2792       mnemonic = "smc";
2793       break;
2794     case DCPS1:
2795       mnemonic = "dcps1";
2796       form = "{'IDebug}";
2797       break;
2798     case DCPS2:
2799       mnemonic = "dcps2";
2800       form = "{'IDebug}";
2801       break;
2802     case DCPS3:
2803       mnemonic = "dcps3";
2804       form = "{'IDebug}";
2805       break;
2806     default:
2807       form = "(Exception)";
2808   }
2809   Format(instr, mnemonic, form);
2810 }
2811 
2812 
2813 void Disassembler::VisitCrypto2RegSHA(const Instruction *instr) {
2814   VisitUnimplemented(instr);
2815 }
2816 
2817 
2818 void Disassembler::VisitCrypto3RegSHA(const Instruction *instr) {
2819   VisitUnimplemented(instr);
2820 }
2821 
2822 
2823 void Disassembler::VisitCryptoAES(const Instruction *instr) {
2824   VisitUnimplemented(instr);
2825 }
2826 
2827 void Disassembler::DisassembleNEON2RegAddlp(const Instruction *instr) {
2828   const char *mnemonic = mnemonic_.c_str();
2829   const char *form = "'Vd.%s, 'Vn.%s";
2830 
2831   static const NEONFormatMap map_lp_ta =
2832       {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
2833   NEONFormatDecoder nfd(instr);
2834   nfd.SetFormatMap(0, &map_lp_ta);
2835   Format(instr, mnemonic, nfd.Substitute(form));
2836 }
2837 
2838 void Disassembler::DisassembleNEON2RegCompare(const Instruction *instr) {
2839   const char *mnemonic = mnemonic_.c_str();
2840   const char *form = "'Vd.%s, 'Vn.%s, #0";
2841   NEONFormatDecoder nfd(instr);
2842   Format(instr, mnemonic, nfd.Substitute(form));
2843 }
2844 
2845 void Disassembler::DisassembleNEON2RegFPCompare(const Instruction *instr) {
2846   const char *mnemonic = mnemonic_.c_str();
2847   const char *form = "'Vd.%s, 'Vn.%s, #0.0";
2848   NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPFormatMap());
2849   Format(instr, mnemonic, nfd.Substitute(form));
2850 }
2851 
2852 void Disassembler::DisassembleNEON2RegFPConvert(const Instruction *instr) {
2853   const char *mnemonic = mnemonic_.c_str();
2854   const char *form = "'Vd.%s, 'Vn.%s";
2855   static const NEONFormatMap map_cvt_ta = {{22}, {NF_4S, NF_2D}};
2856 
2857   static const NEONFormatMap map_cvt_tb = {{22, 30},
2858                                            {NF_4H, NF_8H, NF_2S, NF_4S}};
2859   NEONFormatDecoder nfd(instr, &map_cvt_tb, &map_cvt_ta);
2860 
2861   VectorFormat vform_dst = nfd.GetVectorFormat(0);
2862   switch (form_hash_) {
2863     case Hash("fcvtl_asimdmisc_l"):
2864       nfd.SetFormatMaps(&map_cvt_ta, &map_cvt_tb);
2865       break;
2866     case Hash("fcvtxn_asimdmisc_n"):
2867       if ((vform_dst != kFormat2S) && (vform_dst != kFormat4S)) {
2868         mnemonic = NULL;
2869       }
2870       break;
2871   }
2872   Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
2873 }
2874 
2875 void Disassembler::DisassembleNEON2RegFP(const Instruction *instr) {
2876   const char *mnemonic = mnemonic_.c_str();
2877   const char *form = "'Vd.%s, 'Vn.%s";
2878   NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPFormatMap());
2879   Format(instr, mnemonic, nfd.Substitute(form));
2880 }
2881 
2882 void Disassembler::DisassembleNEON2RegLogical(const Instruction *instr) {
2883   const char *mnemonic = mnemonic_.c_str();
2884   const char *form = "'Vd.%s, 'Vn.%s";
2885   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
2886   if (form_hash_ == Hash("not_asimdmisc_r")) {
2887     mnemonic = "mvn";
2888   }
2889   Format(instr, mnemonic, nfd.Substitute(form));
2890 }
2891 
2892 void Disassembler::DisassembleNEON2RegExtract(const Instruction *instr) {
2893   const char *mnemonic = mnemonic_.c_str();
2894   const char *form = "'Vd.%s, 'Vn.%s";
2895   const char *suffix = NULL;
2896   NEONFormatDecoder nfd(instr,
2897                         NEONFormatDecoder::IntegerFormatMap(),
2898                         NEONFormatDecoder::LongIntegerFormatMap());
2899 
2900   if (form_hash_ == Hash("shll_asimdmisc_s")) {
2901     nfd.SetFormatMaps(nfd.LongIntegerFormatMap(), nfd.IntegerFormatMap());
2902     switch (instr->GetNEONSize()) {
2903       case 0:
2904         suffix = ", #8";
2905         break;
2906       case 1:
2907         suffix = ", #16";
2908         break;
2909       case 2:
2910         suffix = ", #32";
2911         break;
2912     }
2913   }
2914   Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form), suffix);
2915 }
2916 
2917 void Disassembler::VisitNEON2RegMisc(const Instruction *instr) {
2918   const char *mnemonic = mnemonic_.c_str();
2919   const char *form = "'Vd.%s, 'Vn.%s";
2920   NEONFormatDecoder nfd(instr);
2921 
2922   VectorFormat vform_dst = nfd.GetVectorFormat(0);
2923   if (vform_dst != kFormatUndefined) {
2924     uint32_t ls_dst = LaneSizeInBitsFromFormat(vform_dst);
2925     switch (form_hash_) {
2926       case Hash("cnt_asimdmisc_r"):
2927       case Hash("rev16_asimdmisc_r"):
2928         if (ls_dst != kBRegSize) {
2929           mnemonic = NULL;
2930         }
2931         break;
2932       case Hash("rev32_asimdmisc_r"):
2933         if ((ls_dst == kDRegSize) || (ls_dst == kSRegSize)) {
2934           mnemonic = NULL;
2935         }
2936         break;
2937       case Hash("urecpe_asimdmisc_r"):
2938       case Hash("ursqrte_asimdmisc_r"):
2939         // For urecpe and ursqrte, only S-sized elements are supported. The MSB
2940         // of the size field is always set by the instruction (0b1x) so we need
2941         // only check and discard D-sized elements here.
2942         VIXL_ASSERT((ls_dst == kSRegSize) || (ls_dst == kDRegSize));
2943         VIXL_FALLTHROUGH();
2944       case Hash("clz_asimdmisc_r"):
2945       case Hash("cls_asimdmisc_r"):
2946       case Hash("rev64_asimdmisc_r"):
2947         if (ls_dst == kDRegSize) {
2948           mnemonic = NULL;
2949         }
2950         break;
2951     }
2952   }
2953 
2954   Format(instr, mnemonic, nfd.Substitute(form));
2955 }
2956 
2957 void Disassembler::VisitNEON2RegMiscFP16(const Instruction *instr) {
2958   const char *mnemonic = mnemonic_.c_str();
2959   const char *form = "'Vd.'?30:84h, 'Vn.'?30:84h";
2960   const char *suffix = NULL;
2961 
2962   switch (form_hash_) {
2963     case Hash("fcmeq_asimdmiscfp16_fz"):
2964     case Hash("fcmge_asimdmiscfp16_fz"):
2965     case Hash("fcmgt_asimdmiscfp16_fz"):
2966     case Hash("fcmle_asimdmiscfp16_fz"):
2967     case Hash("fcmlt_asimdmiscfp16_fz"):
2968       suffix = ", #0.0";
2969   }
2970   Format(instr, mnemonic, form, suffix);
2971 }
2972 
2973 void Disassembler::DisassembleNEON3SameLogical(const Instruction *instr) {
2974   const char *mnemonic = mnemonic_.c_str();
2975   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
2976   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
2977 
2978   switch (form_hash_) {
2979     case Hash("orr_asimdsame_only"):
2980       if (instr->GetRm() == instr->GetRn()) {
2981         mnemonic = "mov";
2982         form = "'Vd.%s, 'Vn.%s";
2983       }
2984       break;
2985     case Hash("pmul_asimdsame_only"):
2986       if (instr->GetNEONSize() != 0) {
2987         mnemonic = NULL;
2988       }
2989   }
2990   Format(instr, mnemonic, nfd.Substitute(form));
2991 }
2992 
2993 void Disassembler::DisassembleNEON3SameFHM(const Instruction *instr) {
2994   const char *mnemonic = mnemonic_.c_str();
2995   const char *form = "'Vd.'?30:42s, 'Vn.'?30:42h, 'Vm.'?30:42h";
2996   Format(instr, mnemonic, form);
2997 }
2998 
2999 void Disassembler::DisassembleNEON3SameNoD(const Instruction *instr) {
3000   const char *mnemonic = mnemonic_.c_str();
3001   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
3002   static const NEONFormatMap map =
3003       {{23, 22, 30},
3004        {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_UNDEF}};
3005   NEONFormatDecoder nfd(instr, &map);
3006   Format(instr, mnemonic, nfd.Substitute(form));
3007 }
3008 
3009 void Disassembler::VisitNEON3Same(const Instruction *instr) {
3010   const char *mnemonic = mnemonic_.c_str();
3011   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
3012   NEONFormatDecoder nfd(instr);
3013 
3014   if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
3015     nfd.SetFormatMaps(nfd.FPFormatMap());
3016   }
3017 
3018   VectorFormat vform_dst = nfd.GetVectorFormat(0);
3019   if (vform_dst != kFormatUndefined) {
3020     uint32_t ls_dst = LaneSizeInBitsFromFormat(vform_dst);
3021     switch (form_hash_) {
3022       case Hash("sqdmulh_asimdsame_only"):
3023       case Hash("sqrdmulh_asimdsame_only"):
3024         if ((ls_dst == kBRegSize) || (ls_dst == kDRegSize)) {
3025           mnemonic = NULL;
3026         }
3027         break;
3028     }
3029   }
3030   Format(instr, mnemonic, nfd.Substitute(form));
3031 }
3032 
3033 void Disassembler::VisitNEON3SameFP16(const Instruction *instr) {
3034   const char *mnemonic = mnemonic_.c_str();
3035   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
3036   NEONFormatDecoder nfd(instr);
3037   nfd.SetFormatMaps(nfd.FP16FormatMap());
3038   Format(instr, mnemonic, nfd.Substitute(form));
3039 }
3040 
3041 void Disassembler::VisitNEON3SameExtra(const Instruction *instr) {
3042   static const NEONFormatMap map_usdot = {{30}, {NF_8B, NF_16B}};
3043 
3044   const char *mnemonic = mnemonic_.c_str();
3045   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
3046   const char *suffix = NULL;
3047 
3048   NEONFormatDecoder nfd(instr);
3049 
3050   switch (form_hash_) {
3051     case Hash("fcmla_asimdsame2_c"):
3052       suffix = ", #'u1211*90";
3053       break;
3054     case Hash("fcadd_asimdsame2_c"):
3055       // Bit 10 is always set, so this gives 90 * 1 or 3.
3056       suffix = ", #'u1212:1010*90";
3057       break;
3058     case Hash("sdot_asimdsame2_d"):
3059     case Hash("udot_asimdsame2_d"):
3060     case Hash("usdot_asimdsame2_d"):
3061       nfd.SetFormatMap(1, &map_usdot);
3062       nfd.SetFormatMap(2, &map_usdot);
3063       break;
3064     default:
3065       // sqrdml[as]h - nothing to do.
3066       break;
3067   }
3068 
3069   Format(instr, mnemonic, nfd.Substitute(form), suffix);
3070 }
3071 
3072 
3073 void Disassembler::VisitNEON3Different(const Instruction *instr) {
3074   const char *mnemonic = mnemonic_.c_str();
3075   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
3076 
3077   NEONFormatDecoder nfd(instr);
3078   nfd.SetFormatMap(0, nfd.LongIntegerFormatMap());
3079 
3080   switch (form_hash_) {
3081     case Hash("saddw_asimddiff_w"):
3082     case Hash("ssubw_asimddiff_w"):
3083     case Hash("uaddw_asimddiff_w"):
3084     case Hash("usubw_asimddiff_w"):
3085       nfd.SetFormatMap(1, nfd.LongIntegerFormatMap());
3086       break;
3087     case Hash("addhn_asimddiff_n"):
3088     case Hash("raddhn_asimddiff_n"):
3089     case Hash("rsubhn_asimddiff_n"):
3090     case Hash("subhn_asimddiff_n"):
3091       nfd.SetFormatMaps(nfd.LongIntegerFormatMap());
3092       nfd.SetFormatMap(0, nfd.IntegerFormatMap());
3093       break;
3094     case Hash("pmull_asimddiff_l"):
3095       if (nfd.GetVectorFormat(0) != kFormat8H) {
3096         mnemonic = NULL;
3097       }
3098       break;
3099     case Hash("sqdmlal_asimddiff_l"):
3100     case Hash("sqdmlsl_asimddiff_l"):
3101     case Hash("sqdmull_asimddiff_l"):
3102       if (nfd.GetVectorFormat(0) == kFormat8H) {
3103         mnemonic = NULL;
3104       }
3105       break;
3106   }
3107   Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
3108 }
3109 
3110 void Disassembler::DisassembleNEONFPAcrossLanes(const Instruction *instr) {
3111   const char *mnemonic = mnemonic_.c_str();
3112   const char *form = "'Sd, 'Vn.4s";
3113   if ((instr->GetNEONQ() == 0) || (instr->ExtractBit(22) == 1)) {
3114     mnemonic = NULL;
3115   }
3116   Format(instr, mnemonic, form);
3117 }
3118 
3119 void Disassembler::DisassembleNEONFP16AcrossLanes(const Instruction *instr) {
3120   const char *mnemonic = mnemonic_.c_str();
3121   const char *form = "'Hd, 'Vn.'?30:84h";
3122   Format(instr, mnemonic, form);
3123 }
3124 
3125 void Disassembler::VisitNEONAcrossLanes(const Instruction *instr) {
3126   const char *mnemonic = mnemonic_.c_str();
3127   const char *form = "%sd, 'Vn.%s";
3128 
3129   NEONFormatDecoder nfd(instr,
3130                         NEONFormatDecoder::ScalarFormatMap(),
3131                         NEONFormatDecoder::IntegerFormatMap());
3132 
3133   switch (form_hash_) {
3134     case Hash("saddlv_asimdall_only"):
3135     case Hash("uaddlv_asimdall_only"):
3136       nfd.SetFormatMap(0, nfd.LongScalarFormatMap());
3137   }
3138 
3139   VectorFormat vform_src = nfd.GetVectorFormat(1);
3140   if ((vform_src == kFormat2S) || (vform_src == kFormat2D)) {
3141     mnemonic = NULL;
3142   }
3143 
3144   Format(instr,
3145          mnemonic,
3146          nfd.Substitute(form,
3147                         NEONFormatDecoder::kPlaceholder,
3148                         NEONFormatDecoder::kFormat));
3149 }
3150 
3151 void Disassembler::VisitNEONByIndexedElement(const Instruction *instr) {
3152   const char *form = "'Vd.%s, 'Vn.%s, 'Ve.%s['IVByElemIndex]";
3153   static const NEONFormatMap map_v =
3154       {{23, 22, 30},
3155        {NF_UNDEF, NF_UNDEF, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_UNDEF}};
3156   static const NEONFormatMap map_s = {{23, 22},
3157                                       {NF_UNDEF, NF_H, NF_S, NF_UNDEF}};
3158   NEONFormatDecoder nfd(instr, &map_v, &map_v, &map_s);
3159   Format(instr, mnemonic_.c_str(), nfd.Substitute(form));
3160 }
3161 
3162 void Disassembler::DisassembleNEONMulByElementLong(const Instruction *instr) {
3163   const char *form = "'Vd.%s, 'Vn.%s, 'Ve.%s['IVByElemIndex]";
3164   // TODO: Disallow undefined element types for this instruction.
3165   static const NEONFormatMap map_ta = {{23, 22}, {NF_UNDEF, NF_4S, NF_2D}};
3166   NEONFormatDecoder nfd(instr,
3167                         &map_ta,
3168                         NEONFormatDecoder::IntegerFormatMap(),
3169                         NEONFormatDecoder::ScalarFormatMap());
3170   Format(instr, nfd.Mnemonic(mnemonic_.c_str()), nfd.Substitute(form));
3171 }
3172 
3173 void Disassembler::DisassembleNEONDotProdByElement(const Instruction *instr) {
3174   const char *form = instr->ExtractBit(30) ? "'Vd.4s, 'Vn.16" : "'Vd.2s, 'Vn.8";
3175   const char *suffix = "b, 'Vm.4b['u1111:2121]";
3176   Format(instr, mnemonic_.c_str(), form, suffix);
3177 }
3178 
3179 void Disassembler::DisassembleNEONFPMulByElement(const Instruction *instr) {
3180   const char *form = "'Vd.%s, 'Vn.%s, 'Ve.%s['IVByElemIndex]";
3181   NEONFormatDecoder nfd(instr,
3182                         NEONFormatDecoder::FPFormatMap(),
3183                         NEONFormatDecoder::FPFormatMap(),
3184                         NEONFormatDecoder::FPScalarFormatMap());
3185   Format(instr, mnemonic_.c_str(), nfd.Substitute(form));
3186 }
3187 
3188 void Disassembler::DisassembleNEONHalfFPMulByElement(const Instruction *instr) {
3189   const char *form = "'Vd.'?30:84h, 'Vn.'?30:84h, 'Ve.h['IVByElemIndex]";
3190   Format(instr, mnemonic_.c_str(), form);
3191 }
3192 
3193 void Disassembler::DisassembleNEONFPMulByElementLong(const Instruction *instr) {
3194   const char *form = "'Vd.'?30:42s, 'Vn.'?30:42h, 'Ve.h['IVByElemIndexFHM]";
3195   Format(instr, mnemonic_.c_str(), form);
3196 }
3197 
3198 void Disassembler::DisassembleNEONComplexMulByElement(
3199     const Instruction *instr) {
3200   const char *form = "'Vd.%s, 'Vn.%s, 'Ve.%s['IVByElemIndexRot], #'u1413*90";
3201   // TODO: Disallow undefined element types for this instruction.
3202   static const NEONFormatMap map_cn =
3203       {{23, 22, 30},
3204        {NF_UNDEF, NF_UNDEF, NF_4H, NF_8H, NF_UNDEF, NF_4S, NF_UNDEF, NF_UNDEF}};
3205   NEONFormatDecoder nfd(instr,
3206                         &map_cn,
3207                         &map_cn,
3208                         NEONFormatDecoder::ScalarFormatMap());
3209   Format(instr, mnemonic_.c_str(), nfd.Substitute(form));
3210 }
3211 
3212 void Disassembler::VisitNEONCopy(const Instruction *instr) {
3213   const char *mnemonic = mnemonic_.c_str();
3214   const char *form = "(NEONCopy)";
3215 
3216   NEONFormatDecoder nfd(instr,
3217                         NEONFormatDecoder::TriangularFormatMap(),
3218                         NEONFormatDecoder::TriangularScalarFormatMap());
3219 
3220   switch (form_hash_) {
3221     case Hash("ins_asimdins_iv_v"):
3222       mnemonic = "mov";
3223       nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
3224       form = "'Vd.%s['IVInsIndex1], 'Vn.%s['IVInsIndex2]";
3225       break;
3226     case Hash("ins_asimdins_ir_r"):
3227       mnemonic = "mov";
3228       nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
3229       if (nfd.GetVectorFormat() == kFormatD) {
3230         form = "'Vd.%s['IVInsIndex1], 'Xn";
3231       } else {
3232         form = "'Vd.%s['IVInsIndex1], 'Wn";
3233       }
3234       break;
3235     case Hash("umov_asimdins_w_w"):
3236     case Hash("umov_asimdins_x_x"):
3237       if (instr->Mask(NEON_Q) || ((instr->GetImmNEON5() & 7) == 4)) {
3238         mnemonic = "mov";
3239       }
3240       nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
3241       if (nfd.GetVectorFormat() == kFormatD) {
3242         form = "'Xd, 'Vn.%s['IVInsIndex1]";
3243       } else {
3244         form = "'Wd, 'Vn.%s['IVInsIndex1]";
3245       }
3246       break;
3247     case Hash("smov_asimdins_w_w"):
3248     case Hash("smov_asimdins_x_x"): {
3249       nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap());
3250       VectorFormat vform = nfd.GetVectorFormat();
3251       if ((vform == kFormatD) ||
3252           ((vform == kFormatS) && (instr->ExtractBit(30) == 0))) {
3253         mnemonic = NULL;
3254       }
3255       form = "'R30d, 'Vn.%s['IVInsIndex1]";
3256       break;
3257     }
3258     case Hash("dup_asimdins_dv_v"):
3259       form = "'Vd.%s, 'Vn.%s['IVInsIndex1]";
3260       break;
3261     case Hash("dup_asimdins_dr_r"):
3262       if (nfd.GetVectorFormat() == kFormat2D) {
3263         form = "'Vd.%s, 'Xn";
3264       } else {
3265         form = "'Vd.%s, 'Wn";
3266       }
3267   }
3268   Format(instr, mnemonic, nfd.Substitute(form));
3269 }
3270 
3271 
3272 void Disassembler::VisitNEONExtract(const Instruction *instr) {
3273   const char *mnemonic = mnemonic_.c_str();
3274   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVExtract";
3275   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
3276   if ((instr->GetImmNEONExt() > 7) && (instr->GetNEONQ() == 0)) {
3277     mnemonic = NULL;
3278   }
3279   Format(instr, mnemonic, nfd.Substitute(form));
3280 }
3281 
3282 
3283 void Disassembler::VisitNEONLoadStoreMultiStruct(const Instruction *instr) {
3284   const char *mnemonic = NULL;
3285   const char *form = NULL;
3286   const char *form_1v = "{'Vt.%1$s}, ['Xns]";
3287   const char *form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns]";
3288   const char *form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns]";
3289   const char *form_4v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]";
3290   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3291 
3292   switch (instr->Mask(NEONLoadStoreMultiStructMask)) {
3293     case NEON_LD1_1v:
3294       mnemonic = "ld1";
3295       form = form_1v;
3296       break;
3297     case NEON_LD1_2v:
3298       mnemonic = "ld1";
3299       form = form_2v;
3300       break;
3301     case NEON_LD1_3v:
3302       mnemonic = "ld1";
3303       form = form_3v;
3304       break;
3305     case NEON_LD1_4v:
3306       mnemonic = "ld1";
3307       form = form_4v;
3308       break;
3309     case NEON_LD2:
3310       mnemonic = "ld2";
3311       form = form_2v;
3312       break;
3313     case NEON_LD3:
3314       mnemonic = "ld3";
3315       form = form_3v;
3316       break;
3317     case NEON_LD4:
3318       mnemonic = "ld4";
3319       form = form_4v;
3320       break;
3321     case NEON_ST1_1v:
3322       mnemonic = "st1";
3323       form = form_1v;
3324       break;
3325     case NEON_ST1_2v:
3326       mnemonic = "st1";
3327       form = form_2v;
3328       break;
3329     case NEON_ST1_3v:
3330       mnemonic = "st1";
3331       form = form_3v;
3332       break;
3333     case NEON_ST1_4v:
3334       mnemonic = "st1";
3335       form = form_4v;
3336       break;
3337     case NEON_ST2:
3338       mnemonic = "st2";
3339       form = form_2v;
3340       break;
3341     case NEON_ST3:
3342       mnemonic = "st3";
3343       form = form_3v;
3344       break;
3345     case NEON_ST4:
3346       mnemonic = "st4";
3347       form = form_4v;
3348       break;
3349     default:
3350       break;
3351   }
3352 
3353   // Work out unallocated encodings.
3354   bool allocated = (mnemonic != NULL);
3355   switch (instr->Mask(NEONLoadStoreMultiStructMask)) {
3356     case NEON_LD2:
3357     case NEON_LD3:
3358     case NEON_LD4:
3359     case NEON_ST2:
3360     case NEON_ST3:
3361     case NEON_ST4:
3362       // LD[2-4] and ST[2-4] cannot use .1d format.
3363       allocated = (instr->GetNEONQ() != 0) || (instr->GetNEONLSSize() != 3);
3364       break;
3365     default:
3366       break;
3367   }
3368   if (allocated) {
3369     VIXL_ASSERT(mnemonic != NULL);
3370     VIXL_ASSERT(form != NULL);
3371   } else {
3372     mnemonic = "unallocated";
3373     form = "(NEONLoadStoreMultiStruct)";
3374   }
3375 
3376   Format(instr, mnemonic, nfd.Substitute(form));
3377 }
3378 
3379 
3380 void Disassembler::VisitNEONLoadStoreMultiStructPostIndex(
3381     const Instruction *instr) {
3382   const char *mnemonic = NULL;
3383   const char *form = NULL;
3384   const char *form_1v = "{'Vt.%1$s}, ['Xns], 'Xmr1";
3385   const char *form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns], 'Xmr2";
3386   const char *form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns], 'Xmr3";
3387   const char *form_4v =
3388       "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmr4";
3389   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3390 
3391   switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
3392     case NEON_LD1_1v_post:
3393       mnemonic = "ld1";
3394       form = form_1v;
3395       break;
3396     case NEON_LD1_2v_post:
3397       mnemonic = "ld1";
3398       form = form_2v;
3399       break;
3400     case NEON_LD1_3v_post:
3401       mnemonic = "ld1";
3402       form = form_3v;
3403       break;
3404     case NEON_LD1_4v_post:
3405       mnemonic = "ld1";
3406       form = form_4v;
3407       break;
3408     case NEON_LD2_post:
3409       mnemonic = "ld2";
3410       form = form_2v;
3411       break;
3412     case NEON_LD3_post:
3413       mnemonic = "ld3";
3414       form = form_3v;
3415       break;
3416     case NEON_LD4_post:
3417       mnemonic = "ld4";
3418       form = form_4v;
3419       break;
3420     case NEON_ST1_1v_post:
3421       mnemonic = "st1";
3422       form = form_1v;
3423       break;
3424     case NEON_ST1_2v_post:
3425       mnemonic = "st1";
3426       form = form_2v;
3427       break;
3428     case NEON_ST1_3v_post:
3429       mnemonic = "st1";
3430       form = form_3v;
3431       break;
3432     case NEON_ST1_4v_post:
3433       mnemonic = "st1";
3434       form = form_4v;
3435       break;
3436     case NEON_ST2_post:
3437       mnemonic = "st2";
3438       form = form_2v;
3439       break;
3440     case NEON_ST3_post:
3441       mnemonic = "st3";
3442       form = form_3v;
3443       break;
3444     case NEON_ST4_post:
3445       mnemonic = "st4";
3446       form = form_4v;
3447       break;
3448     default:
3449       break;
3450   }
3451 
3452   // Work out unallocated encodings.
3453   bool allocated = (mnemonic != NULL);
3454   switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
3455     case NEON_LD2_post:
3456     case NEON_LD3_post:
3457     case NEON_LD4_post:
3458     case NEON_ST2_post:
3459     case NEON_ST3_post:
3460     case NEON_ST4_post:
3461       // LD[2-4] and ST[2-4] cannot use .1d format.
3462       allocated = (instr->GetNEONQ() != 0) || (instr->GetNEONLSSize() != 3);
3463       break;
3464     default:
3465       break;
3466   }
3467   if (allocated) {
3468     VIXL_ASSERT(mnemonic != NULL);
3469     VIXL_ASSERT(form != NULL);
3470   } else {
3471     mnemonic = "unallocated";
3472     form = "(NEONLoadStoreMultiStructPostIndex)";
3473   }
3474 
3475   Format(instr, mnemonic, nfd.Substitute(form));
3476 }
3477 
3478 
3479 void Disassembler::VisitNEONLoadStoreSingleStruct(const Instruction *instr) {
3480   const char *mnemonic = NULL;
3481   const char *form = NULL;
3482 
3483   const char *form_1b = "{'Vt.b}['IVLSLane0], ['Xns]";
3484   const char *form_1h = "{'Vt.h}['IVLSLane1], ['Xns]";
3485   const char *form_1s = "{'Vt.s}['IVLSLane2], ['Xns]";
3486   const char *form_1d = "{'Vt.d}['IVLSLane3], ['Xns]";
3487   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3488 
3489   switch (instr->Mask(NEONLoadStoreSingleStructMask)) {
3490     case NEON_LD1_b:
3491       mnemonic = "ld1";
3492       form = form_1b;
3493       break;
3494     case NEON_LD1_h:
3495       mnemonic = "ld1";
3496       form = form_1h;
3497       break;
3498     case NEON_LD1_s:
3499       mnemonic = "ld1";
3500       VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
3501       form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
3502       break;
3503     case NEON_ST1_b:
3504       mnemonic = "st1";
3505       form = form_1b;
3506       break;
3507     case NEON_ST1_h:
3508       mnemonic = "st1";
3509       form = form_1h;
3510       break;
3511     case NEON_ST1_s:
3512       mnemonic = "st1";
3513       VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
3514       form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
3515       break;
3516     case NEON_LD1R:
3517       mnemonic = "ld1r";
3518       form = "{'Vt.%s}, ['Xns]";
3519       break;
3520     case NEON_LD2_b:
3521     case NEON_ST2_b:
3522       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3523       form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns]";
3524       break;
3525     case NEON_LD2_h:
3526     case NEON_ST2_h:
3527       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3528       form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns]";
3529       break;
3530     case NEON_LD2_s:
3531     case NEON_ST2_s:
3532       VIXL_STATIC_ASSERT((NEON_ST2_s | (1 << NEONLSSize_offset)) == NEON_ST2_d);
3533       VIXL_STATIC_ASSERT((NEON_LD2_s | (1 << NEONLSSize_offset)) == NEON_LD2_d);
3534       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3535       if ((instr->GetNEONLSSize() & 1) == 0) {
3536         form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns]";
3537       } else {
3538         form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns]";
3539       }
3540       break;
3541     case NEON_LD2R:
3542       mnemonic = "ld2r";
3543       form = "{'Vt.%s, 'Vt2.%s}, ['Xns]";
3544       break;
3545     case NEON_LD3_b:
3546     case NEON_ST3_b:
3547       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3548       form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns]";
3549       break;
3550     case NEON_LD3_h:
3551     case NEON_ST3_h:
3552       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3553       form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns]";
3554       break;
3555     case NEON_LD3_s:
3556     case NEON_ST3_s:
3557       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3558       if ((instr->GetNEONLSSize() & 1) == 0) {
3559         form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns]";
3560       } else {
3561         form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns]";
3562       }
3563       break;
3564     case NEON_LD3R:
3565       mnemonic = "ld3r";
3566       form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns]";
3567       break;
3568     case NEON_LD4_b:
3569     case NEON_ST4_b:
3570       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3571       form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns]";
3572       break;
3573     case NEON_LD4_h:
3574     case NEON_ST4_h:
3575       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3576       form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns]";
3577       break;
3578     case NEON_LD4_s:
3579     case NEON_ST4_s:
3580       VIXL_STATIC_ASSERT((NEON_LD4_s | (1 << NEONLSSize_offset)) == NEON_LD4_d);
3581       VIXL_STATIC_ASSERT((NEON_ST4_s | (1 << NEONLSSize_offset)) == NEON_ST4_d);
3582       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3583       if ((instr->GetNEONLSSize() & 1) == 0) {
3584         form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns]";
3585       } else {
3586         form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns]";
3587       }
3588       break;
3589     case NEON_LD4R:
3590       mnemonic = "ld4r";
3591       form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]";
3592       break;
3593     default:
3594       break;
3595   }
3596 
3597   // Work out unallocated encodings.
3598   bool allocated = (mnemonic != NULL);
3599   switch (instr->Mask(NEONLoadStoreSingleStructMask)) {
3600     case NEON_LD1_h:
3601     case NEON_LD2_h:
3602     case NEON_LD3_h:
3603     case NEON_LD4_h:
3604     case NEON_ST1_h:
3605     case NEON_ST2_h:
3606     case NEON_ST3_h:
3607     case NEON_ST4_h:
3608       VIXL_ASSERT(allocated);
3609       allocated = ((instr->GetNEONLSSize() & 1) == 0);
3610       break;
3611     case NEON_LD1_s:
3612     case NEON_LD2_s:
3613     case NEON_LD3_s:
3614     case NEON_LD4_s:
3615     case NEON_ST1_s:
3616     case NEON_ST2_s:
3617     case NEON_ST3_s:
3618     case NEON_ST4_s:
3619       VIXL_ASSERT(allocated);
3620       allocated = (instr->GetNEONLSSize() <= 1) &&
3621                   ((instr->GetNEONLSSize() == 0) || (instr->GetNEONS() == 0));
3622       break;
3623     case NEON_LD1R:
3624     case NEON_LD2R:
3625     case NEON_LD3R:
3626     case NEON_LD4R:
3627       VIXL_ASSERT(allocated);
3628       allocated = (instr->GetNEONS() == 0);
3629       break;
3630     default:
3631       break;
3632   }
3633   if (allocated) {
3634     VIXL_ASSERT(mnemonic != NULL);
3635     VIXL_ASSERT(form != NULL);
3636   } else {
3637     mnemonic = "unallocated";
3638     form = "(NEONLoadStoreSingleStruct)";
3639   }
3640 
3641   Format(instr, mnemonic, nfd.Substitute(form));
3642 }
3643 
3644 
3645 void Disassembler::VisitNEONLoadStoreSingleStructPostIndex(
3646     const Instruction *instr) {
3647   const char *mnemonic = NULL;
3648   const char *form = NULL;
3649 
3650   const char *form_1b = "{'Vt.b}['IVLSLane0], ['Xns], 'Xmb1";
3651   const char *form_1h = "{'Vt.h}['IVLSLane1], ['Xns], 'Xmb2";
3652   const char *form_1s = "{'Vt.s}['IVLSLane2], ['Xns], 'Xmb4";
3653   const char *form_1d = "{'Vt.d}['IVLSLane3], ['Xns], 'Xmb8";
3654   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3655 
3656   switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
3657     case NEON_LD1_b_post:
3658       mnemonic = "ld1";
3659       form = form_1b;
3660       break;
3661     case NEON_LD1_h_post:
3662       mnemonic = "ld1";
3663       form = form_1h;
3664       break;
3665     case NEON_LD1_s_post:
3666       mnemonic = "ld1";
3667       VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
3668       form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
3669       break;
3670     case NEON_ST1_b_post:
3671       mnemonic = "st1";
3672       form = form_1b;
3673       break;
3674     case NEON_ST1_h_post:
3675       mnemonic = "st1";
3676       form = form_1h;
3677       break;
3678     case NEON_ST1_s_post:
3679       mnemonic = "st1";
3680       VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
3681       form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d;
3682       break;
3683     case NEON_LD1R_post:
3684       mnemonic = "ld1r";
3685       form = "{'Vt.%s}, ['Xns], 'Xmz1";
3686       break;
3687     case NEON_LD2_b_post:
3688     case NEON_ST2_b_post:
3689       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3690       form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns], 'Xmb2";
3691       break;
3692     case NEON_ST2_h_post:
3693     case NEON_LD2_h_post:
3694       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3695       form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns], 'Xmb4";
3696       break;
3697     case NEON_LD2_s_post:
3698     case NEON_ST2_s_post:
3699       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2";
3700       if ((instr->GetNEONLSSize() & 1) == 0)
3701         form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns], 'Xmb8";
3702       else
3703         form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns], 'Xmb16";
3704       break;
3705     case NEON_LD2R_post:
3706       mnemonic = "ld2r";
3707       form = "{'Vt.%s, 'Vt2.%s}, ['Xns], 'Xmz2";
3708       break;
3709     case NEON_LD3_b_post:
3710     case NEON_ST3_b_post:
3711       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3712       form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns], 'Xmb3";
3713       break;
3714     case NEON_LD3_h_post:
3715     case NEON_ST3_h_post:
3716       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3717       form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns], 'Xmb6";
3718       break;
3719     case NEON_LD3_s_post:
3720     case NEON_ST3_s_post:
3721       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3";
3722       if ((instr->GetNEONLSSize() & 1) == 0)
3723         form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns], 'Xmb12";
3724       else
3725         form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns], 'Xmb24";
3726       break;
3727     case NEON_LD3R_post:
3728       mnemonic = "ld3r";
3729       form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns], 'Xmz3";
3730       break;
3731     case NEON_LD4_b_post:
3732     case NEON_ST4_b_post:
3733       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3734       form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns], 'Xmb4";
3735       break;
3736     case NEON_LD4_h_post:
3737     case NEON_ST4_h_post:
3738       mnemonic = (instr->GetLdStXLoad()) == 1 ? "ld4" : "st4";
3739       form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns], 'Xmb8";
3740       break;
3741     case NEON_LD4_s_post:
3742     case NEON_ST4_s_post:
3743       mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4";
3744       if ((instr->GetNEONLSSize() & 1) == 0)
3745         form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns], 'Xmb16";
3746       else
3747         form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns], 'Xmb32";
3748       break;
3749     case NEON_LD4R_post:
3750       mnemonic = "ld4r";
3751       form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmz4";
3752       break;
3753     default:
3754       break;
3755   }
3756 
3757   // Work out unallocated encodings.
3758   bool allocated = (mnemonic != NULL);
3759   switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
3760     case NEON_LD1_h_post:
3761     case NEON_LD2_h_post:
3762     case NEON_LD3_h_post:
3763     case NEON_LD4_h_post:
3764     case NEON_ST1_h_post:
3765     case NEON_ST2_h_post:
3766     case NEON_ST3_h_post:
3767     case NEON_ST4_h_post:
3768       VIXL_ASSERT(allocated);
3769       allocated = ((instr->GetNEONLSSize() & 1) == 0);
3770       break;
3771     case NEON_LD1_s_post:
3772     case NEON_LD2_s_post:
3773     case NEON_LD3_s_post:
3774     case NEON_LD4_s_post:
3775     case NEON_ST1_s_post:
3776     case NEON_ST2_s_post:
3777     case NEON_ST3_s_post:
3778     case NEON_ST4_s_post:
3779       VIXL_ASSERT(allocated);
3780       allocated = (instr->GetNEONLSSize() <= 1) &&
3781                   ((instr->GetNEONLSSize() == 0) || (instr->GetNEONS() == 0));
3782       break;
3783     case NEON_LD1R_post:
3784     case NEON_LD2R_post:
3785     case NEON_LD3R_post:
3786     case NEON_LD4R_post:
3787       VIXL_ASSERT(allocated);
3788       allocated = (instr->GetNEONS() == 0);
3789       break;
3790     default:
3791       break;
3792   }
3793   if (allocated) {
3794     VIXL_ASSERT(mnemonic != NULL);
3795     VIXL_ASSERT(form != NULL);
3796   } else {
3797     mnemonic = "unallocated";
3798     form = "(NEONLoadStoreSingleStructPostIndex)";
3799   }
3800 
3801   Format(instr, mnemonic, nfd.Substitute(form));
3802 }
3803 
3804 
3805 void Disassembler::VisitNEONModifiedImmediate(const Instruction *instr) {
3806   const char *mnemonic = mnemonic_.c_str();
3807   const char *form = "'Vt.%s, 'IVMIImm8, lsl 'IVMIShiftAmt1";
3808 
3809   static const NEONFormatMap map_h = {{30}, {NF_4H, NF_8H}};
3810   static const NEONFormatMap map_s = {{30}, {NF_2S, NF_4S}};
3811   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
3812 
3813   switch (form_hash_) {
3814     case Hash("movi_asimdimm_n_b"):
3815       form = "'Vt.%s, 'IVMIImm8";
3816       break;
3817     case Hash("bic_asimdimm_l_hl"):
3818     case Hash("movi_asimdimm_l_hl"):
3819     case Hash("mvni_asimdimm_l_hl"):
3820     case Hash("orr_asimdimm_l_hl"):
3821       nfd.SetFormatMap(0, &map_h);
3822       break;
3823     case Hash("movi_asimdimm_m_sm"):
3824     case Hash("mvni_asimdimm_m_sm"):
3825       form = "'Vt.%s, 'IVMIImm8, msl 'IVMIShiftAmt2";
3826       VIXL_FALLTHROUGH();
3827     case Hash("bic_asimdimm_l_sl"):
3828     case Hash("movi_asimdimm_l_sl"):
3829     case Hash("mvni_asimdimm_l_sl"):
3830     case Hash("orr_asimdimm_l_sl"):
3831       nfd.SetFormatMap(0, &map_s);
3832       break;
3833     case Hash("movi_asimdimm_d_ds"):
3834       form = "'Dd, 'IVMIImm";
3835       break;
3836     case Hash("movi_asimdimm_d2_d"):
3837       form = "'Vt.2d, 'IVMIImm";
3838       break;
3839     case Hash("fmov_asimdimm_h_h"):
3840       form = "'Vt.%s, 'IFPNeon";
3841       nfd.SetFormatMap(0, &map_h);
3842       break;
3843     case Hash("fmov_asimdimm_s_s"):
3844       form = "'Vt.%s, 'IFPNeon";
3845       nfd.SetFormatMap(0, &map_s);
3846       break;
3847     case Hash("fmov_asimdimm_d2_d"):
3848       form = "'Vt.2d, 'IFPNeon";
3849       break;
3850   }
3851 
3852   Format(instr, mnemonic, nfd.Substitute(form));
3853 }
3854 
3855 void Disassembler::DisassembleNEONScalar2RegMiscOnlyD(
3856     const Instruction *instr) {
3857   const char *mnemonic = mnemonic_.c_str();
3858   const char *form = "'Dd, 'Dn";
3859   const char *suffix = ", #0";
3860   if (instr->GetNEONSize() != 3) {
3861     mnemonic = NULL;
3862   }
3863   switch (form_hash_) {
3864     case Hash("abs_asisdmisc_r"):
3865     case Hash("neg_asisdmisc_r"):
3866       suffix = NULL;
3867   }
3868   Format(instr, mnemonic, form, suffix);
3869 }
3870 
3871 void Disassembler::DisassembleNEONFPScalar2RegMisc(const Instruction *instr) {
3872   const char *mnemonic = mnemonic_.c_str();
3873   const char *form = "%sd, %sn";
3874   const char *suffix = NULL;
3875   NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap());
3876   switch (form_hash_) {
3877     case Hash("fcmeq_asisdmisc_fz"):
3878     case Hash("fcmge_asisdmisc_fz"):
3879     case Hash("fcmgt_asisdmisc_fz"):
3880     case Hash("fcmle_asisdmisc_fz"):
3881     case Hash("fcmlt_asisdmisc_fz"):
3882       suffix = ", #0.0";
3883       break;
3884     case Hash("fcvtxn_asisdmisc_n"):
3885       if (nfd.GetVectorFormat(0) == kFormatS) {  // Source format.
3886         mnemonic = NULL;
3887       }
3888       form = "'Sd, 'Dn";
3889   }
3890   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form), suffix);
3891 }
3892 
3893 void Disassembler::VisitNEONScalar2RegMisc(const Instruction *instr) {
3894   const char *mnemonic = mnemonic_.c_str();
3895   const char *form = "%sd, %sn";
3896   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
3897   switch (form_hash_) {
3898     case Hash("sqxtn_asisdmisc_n"):
3899     case Hash("sqxtun_asisdmisc_n"):
3900     case Hash("uqxtn_asisdmisc_n"):
3901       nfd.SetFormatMap(1, nfd.LongScalarFormatMap());
3902   }
3903   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
3904 }
3905 
3906 void Disassembler::VisitNEONScalar2RegMiscFP16(const Instruction *instr) {
3907   const char *mnemonic = mnemonic_.c_str();
3908   const char *form = "'Hd, 'Hn";
3909   const char *suffix = NULL;
3910 
3911   switch (form_hash_) {
3912     case Hash("fcmeq_asisdmiscfp16_fz"):
3913     case Hash("fcmge_asisdmiscfp16_fz"):
3914     case Hash("fcmgt_asisdmiscfp16_fz"):
3915     case Hash("fcmle_asisdmiscfp16_fz"):
3916     case Hash("fcmlt_asisdmiscfp16_fz"):
3917       suffix = ", #0.0";
3918   }
3919   Format(instr, mnemonic, form, suffix);
3920 }
3921 
3922 
3923 void Disassembler::VisitNEONScalar3Diff(const Instruction *instr) {
3924   const char *mnemonic = mnemonic_.c_str();
3925   const char *form = "%sd, %sn, %sm";
3926   NEONFormatDecoder nfd(instr,
3927                         NEONFormatDecoder::LongScalarFormatMap(),
3928                         NEONFormatDecoder::ScalarFormatMap());
3929   if (nfd.GetVectorFormat(0) == kFormatH) {
3930     mnemonic = NULL;
3931   }
3932   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
3933 }
3934 
3935 void Disassembler::DisassembleNEONFPScalar3Same(const Instruction *instr) {
3936   const char *mnemonic = mnemonic_.c_str();
3937   const char *form = "%sd, %sn, %sm";
3938   NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap());
3939   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
3940 }
3941 
3942 void Disassembler::DisassembleNEONScalar3SameOnlyD(const Instruction *instr) {
3943   const char *mnemonic = mnemonic_.c_str();
3944   const char *form = "'Dd, 'Dn, 'Dm";
3945   if (instr->GetNEONSize() != 3) {
3946     mnemonic = NULL;
3947   }
3948   Format(instr, mnemonic, form);
3949 }
3950 
3951 void Disassembler::VisitNEONScalar3Same(const Instruction *instr) {
3952   const char *mnemonic = mnemonic_.c_str();
3953   const char *form = "%sd, %sn, %sm";
3954   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
3955   VectorFormat vform = nfd.GetVectorFormat(0);
3956   switch (form_hash_) {
3957     case Hash("srshl_asisdsame_only"):
3958     case Hash("urshl_asisdsame_only"):
3959     case Hash("sshl_asisdsame_only"):
3960     case Hash("ushl_asisdsame_only"):
3961       if (vform != kFormatD) {
3962         mnemonic = NULL;
3963       }
3964       break;
3965     case Hash("sqdmulh_asisdsame_only"):
3966     case Hash("sqrdmulh_asisdsame_only"):
3967       if ((vform == kFormatB) || (vform == kFormatD)) {
3968         mnemonic = NULL;
3969       }
3970   }
3971   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
3972 }
3973 
3974 void Disassembler::VisitNEONScalar3SameFP16(const Instruction *instr) {
3975   const char *mnemonic = mnemonic_.c_str();
3976   const char *form = "'Hd, 'Hn, 'Hm";
3977   Format(instr, mnemonic, form);
3978 }
3979 
3980 void Disassembler::VisitNEONScalar3SameExtra(const Instruction *instr) {
3981   USE(instr);
3982   // Nothing to do - handled by VisitNEONScalar3Same.
3983   VIXL_UNREACHABLE();
3984 }
3985 
3986 void Disassembler::DisassembleNEONScalarSatMulLongIndex(
3987     const Instruction *instr) {
3988   const char *mnemonic = mnemonic_.c_str();
3989   const char *form = "%sd, %sn, 'Ve.%s['IVByElemIndex]";
3990   NEONFormatDecoder nfd(instr,
3991                         NEONFormatDecoder::LongScalarFormatMap(),
3992                         NEONFormatDecoder::ScalarFormatMap());
3993   if (nfd.GetVectorFormat(0) == kFormatH) {
3994     mnemonic = NULL;
3995   }
3996   Format(instr,
3997          mnemonic,
3998          nfd.Substitute(form, nfd.kPlaceholder, nfd.kPlaceholder, nfd.kFormat));
3999 }
4000 
4001 void Disassembler::DisassembleNEONFPScalarMulIndex(const Instruction *instr) {
4002   const char *mnemonic = mnemonic_.c_str();
4003   const char *form = "%sd, %sn, 'Ve.%s['IVByElemIndex]";
4004   static const NEONFormatMap map = {{23, 22}, {NF_H, NF_UNDEF, NF_S, NF_D}};
4005   NEONFormatDecoder nfd(instr, &map);
4006   Format(instr,
4007          mnemonic,
4008          nfd.Substitute(form, nfd.kPlaceholder, nfd.kPlaceholder, nfd.kFormat));
4009 }
4010 
4011 void Disassembler::VisitNEONScalarByIndexedElement(const Instruction *instr) {
4012   const char *mnemonic = mnemonic_.c_str();
4013   const char *form = "%sd, %sn, 'Ve.%s['IVByElemIndex]";
4014   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4015   VectorFormat vform_dst = nfd.GetVectorFormat(0);
4016   if ((vform_dst == kFormatB) || (vform_dst == kFormatD)) {
4017     mnemonic = NULL;
4018   }
4019   Format(instr,
4020          mnemonic,
4021          nfd.Substitute(form, nfd.kPlaceholder, nfd.kPlaceholder, nfd.kFormat));
4022 }
4023 
4024 
4025 void Disassembler::VisitNEONScalarCopy(const Instruction *instr) {
4026   const char *mnemonic = "unimplemented";
4027   const char *form = "(NEONScalarCopy)";
4028 
4029   NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
4030 
4031   if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
4032     mnemonic = "mov";
4033     form = "%sd, 'Vn.%s['IVInsIndex1]";
4034   }
4035 
4036   Format(instr, mnemonic, nfd.Substitute(form, nfd.kPlaceholder, nfd.kFormat));
4037 }
4038 
4039 
4040 void Disassembler::VisitNEONScalarPairwise(const Instruction *instr) {
4041   const char *mnemonic = mnemonic_.c_str();
4042   if (form_hash_ == Hash("addp_asisdpair_only")) {
4043     // All pairwise operations except ADDP use bit U to differentiate FP16
4044     // from FP32/FP64 variations.
4045     if (instr->GetNEONSize() != 3) {
4046       mnemonic = NULL;
4047     }
4048     Format(instr, mnemonic, "'Dd, 'Vn.2d");
4049   } else {
4050     const char *form = "%sd, 'Vn.2%s";
4051     NEONFormatDecoder nfd(instr,
4052                           NEONFormatDecoder::FPScalarPairwiseFormatMap());
4053 
4054     Format(instr,
4055            mnemonic,
4056            nfd.Substitute(form,
4057                           NEONFormatDecoder::kPlaceholder,
4058                           NEONFormatDecoder::kFormat));
4059   }
4060 }
4061 
4062 void Disassembler::DisassembleNEONScalarShiftImmOnlyD(
4063     const Instruction *instr) {
4064   const char *mnemonic = mnemonic_.c_str();
4065   const char *form = "'Dd, 'Dn, ";
4066   const char *suffix = "'IsR";
4067 
4068   if (instr->ExtractBit(22) == 0) {
4069     // Only D registers are supported.
4070     mnemonic = NULL;
4071   }
4072 
4073   switch (form_hash_) {
4074     case Hash("shl_asisdshf_r"):
4075     case Hash("sli_asisdshf_r"):
4076       suffix = "'IsL";
4077   }
4078 
4079   Format(instr, mnemonic, form, suffix);
4080 }
4081 
4082 void Disassembler::DisassembleNEONScalarShiftRightNarrowImm(
4083     const Instruction *instr) {
4084   const char *mnemonic = mnemonic_.c_str();
4085   const char *form = "%sd, %sn, 'IsR";
4086   static const NEONFormatMap map_dst =
4087       {{22, 21, 20, 19}, {NF_UNDEF, NF_B, NF_H, NF_H, NF_S, NF_S, NF_S, NF_S}};
4088   static const NEONFormatMap map_src =
4089       {{22, 21, 20, 19}, {NF_UNDEF, NF_H, NF_S, NF_S, NF_D, NF_D, NF_D, NF_D}};
4090   NEONFormatDecoder nfd(instr, &map_dst, &map_src);
4091   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form));
4092 }
4093 
4094 void Disassembler::VisitNEONScalarShiftImmediate(const Instruction *instr) {
4095   const char *mnemonic = mnemonic_.c_str();
4096   const char *form = "%sd, %sn, ";
4097   const char *suffix = "'IsR";
4098 
4099   // clang-format off
4100   static const NEONFormatMap map = {{22, 21, 20, 19},
4101                                     {NF_UNDEF, NF_B, NF_H, NF_H,
4102                                      NF_S,     NF_S, NF_S, NF_S,
4103                                      NF_D,     NF_D, NF_D, NF_D,
4104                                      NF_D,     NF_D, NF_D, NF_D}};
4105   // clang-format on
4106   NEONFormatDecoder nfd(instr, &map);
4107   switch (form_hash_) {
4108     case Hash("sqshlu_asisdshf_r"):
4109     case Hash("sqshl_asisdshf_r"):
4110     case Hash("uqshl_asisdshf_r"):
4111       suffix = "'IsL";
4112       break;
4113     default:
4114       if (nfd.GetVectorFormat(0) == kFormatB) {
4115         mnemonic = NULL;
4116       }
4117   }
4118   Format(instr, mnemonic, nfd.SubstitutePlaceholders(form), suffix);
4119 }
4120 
4121 void Disassembler::DisassembleNEONShiftLeftLongImm(const Instruction *instr) {
4122   const char *mnemonic = mnemonic_.c_str();
4123   const char *form = "'Vd.%s, 'Vn.%s";
4124   const char *suffix = ", 'IsL";
4125 
4126   NEONFormatDecoder nfd(instr,
4127                         NEONFormatDecoder::ShiftLongNarrowImmFormatMap(),
4128                         NEONFormatDecoder::ShiftImmFormatMap());
4129 
4130   if (instr->GetImmNEONImmb() == 0 &&
4131       CountSetBits(instr->GetImmNEONImmh(), 32) == 1) {  // xtl variant.
4132     VIXL_ASSERT((form_hash_ == Hash("sshll_asimdshf_l")) ||
4133                 (form_hash_ == Hash("ushll_asimdshf_l")));
4134     mnemonic = (form_hash_ == Hash("sshll_asimdshf_l")) ? "sxtl" : "uxtl";
4135     suffix = NULL;
4136   }
4137   Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form), suffix);
4138 }
4139 
4140 void Disassembler::DisassembleNEONShiftRightImm(const Instruction *instr) {
4141   const char *mnemonic = mnemonic_.c_str();
4142   const char *form = "'Vd.%s, 'Vn.%s, 'IsR";
4143   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ShiftImmFormatMap());
4144 
4145   VectorFormat vform_dst = nfd.GetVectorFormat(0);
4146   if (vform_dst != kFormatUndefined) {
4147     uint32_t ls_dst = LaneSizeInBitsFromFormat(vform_dst);
4148     switch (form_hash_) {
4149       case Hash("scvtf_asimdshf_c"):
4150       case Hash("ucvtf_asimdshf_c"):
4151       case Hash("fcvtzs_asimdshf_c"):
4152       case Hash("fcvtzu_asimdshf_c"):
4153         if (ls_dst == kBRegSize) {
4154           mnemonic = NULL;
4155         }
4156         break;
4157     }
4158   }
4159   Format(instr, mnemonic, nfd.Substitute(form));
4160 }
4161 
4162 void Disassembler::DisassembleNEONShiftRightNarrowImm(
4163     const Instruction *instr) {
4164   const char *mnemonic = mnemonic_.c_str();
4165   const char *form = "'Vd.%s, 'Vn.%s, 'IsR";
4166 
4167   NEONFormatDecoder nfd(instr,
4168                         NEONFormatDecoder::ShiftImmFormatMap(),
4169                         NEONFormatDecoder::ShiftLongNarrowImmFormatMap());
4170   Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form));
4171 }
4172 
4173 void Disassembler::VisitNEONShiftImmediate(const Instruction *instr) {
4174   const char *mnemonic = mnemonic_.c_str();
4175   const char *form = "'Vd.%s, 'Vn.%s, 'IsL";
4176   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ShiftImmFormatMap());
4177   Format(instr, mnemonic, nfd.Substitute(form));
4178 }
4179 
4180 
4181 void Disassembler::VisitNEONTable(const Instruction *instr) {
4182   const char *mnemonic = mnemonic_.c_str();
4183   const char form_1v[] = "'Vd.%%s, {'Vn.16b}, 'Vm.%%s";
4184   const char form_2v[] = "'Vd.%%s, {'Vn.16b, v%d.16b}, 'Vm.%%s";
4185   const char form_3v[] = "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b}, 'Vm.%%s";
4186   const char form_4v[] =
4187       "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b, v%d.16b}, 'Vm.%%s";
4188   const char *form = form_1v;
4189 
4190   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
4191 
4192   switch (form_hash_) {
4193     case Hash("tbl_asimdtbl_l2_2"):
4194     case Hash("tbx_asimdtbl_l2_2"):
4195       form = form_2v;
4196       break;
4197     case Hash("tbl_asimdtbl_l3_3"):
4198     case Hash("tbx_asimdtbl_l3_3"):
4199       form = form_3v;
4200       break;
4201     case Hash("tbl_asimdtbl_l4_4"):
4202     case Hash("tbx_asimdtbl_l4_4"):
4203       form = form_4v;
4204       break;
4205   }
4206   VIXL_ASSERT(form != NULL);
4207 
4208   char re_form[sizeof(form_4v) + 6];  // 3 * two-digit substitutions => 6
4209   int reg_num = instr->GetRn();
4210   snprintf(re_form,
4211            sizeof(re_form),
4212            form,
4213            (reg_num + 1) % kNumberOfVRegisters,
4214            (reg_num + 2) % kNumberOfVRegisters,
4215            (reg_num + 3) % kNumberOfVRegisters);
4216 
4217   Format(instr, mnemonic, nfd.Substitute(re_form));
4218 }
4219 
4220 
4221 void Disassembler::VisitNEONPerm(const Instruction *instr) {
4222   const char *mnemonic = mnemonic_.c_str();
4223   const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s";
4224   NEONFormatDecoder nfd(instr);
4225   Format(instr, mnemonic, nfd.Substitute(form));
4226 }
4227 
4228 void Disassembler::Disassemble_Vd4S_Vn16B_Vm16B(const Instruction *instr) {
4229   const char *form = "'Vd.4s, 'Vn.16b, 'Vm.16b";
4230   Format(instr, mnemonic_.c_str(), form);
4231 }
4232 
4233 void Disassembler::
4234     VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
4235         const Instruction *instr) {
4236   const char *mnemonic = "unimplemented";
4237   const char *form = "{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw #1]";
4238 
4239   switch (instr->Mask(
4240       SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
4241     case LD1H_z_p_bz_s_x32_scaled:
4242       mnemonic = "ld1h";
4243       break;
4244     case LD1SH_z_p_bz_s_x32_scaled:
4245       mnemonic = "ld1sh";
4246       break;
4247     case LDFF1H_z_p_bz_s_x32_scaled:
4248       mnemonic = "ldff1h";
4249       break;
4250     case LDFF1SH_z_p_bz_s_x32_scaled:
4251       mnemonic = "ldff1sh";
4252       break;
4253     default:
4254       form = "(SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets)";
4255       break;
4256   }
4257   Format(instr, mnemonic, form);
4258 }
4259 
4260 void Disassembler::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
4261     const Instruction *instr) {
4262   const char *mnemonic = "unimplemented";
4263   const char *form = "{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw #2]";
4264 
4265   switch (
4266       instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
4267     case LD1W_z_p_bz_s_x32_scaled:
4268       mnemonic = "ld1w";
4269       break;
4270     case LDFF1W_z_p_bz_s_x32_scaled:
4271       mnemonic = "ldff1w";
4272       break;
4273     default:
4274       form = "(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets)";
4275       break;
4276   }
4277   Format(instr, mnemonic, form);
4278 }
4279 
4280 void Disassembler::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
4281     const Instruction *instr) {
4282   const char *form = "{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw]";
4283 
4284   const char *mnemonic = "unimplemented";
4285   switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
4286     case LD1B_z_p_bz_s_x32_unscaled:
4287       mnemonic = "ld1b";
4288       break;
4289     case LD1H_z_p_bz_s_x32_unscaled:
4290       mnemonic = "ld1h";
4291       break;
4292     case LD1SB_z_p_bz_s_x32_unscaled:
4293       mnemonic = "ld1sb";
4294       break;
4295     case LD1SH_z_p_bz_s_x32_unscaled:
4296       mnemonic = "ld1sh";
4297       break;
4298     case LD1W_z_p_bz_s_x32_unscaled:
4299       mnemonic = "ld1w";
4300       break;
4301     case LDFF1B_z_p_bz_s_x32_unscaled:
4302       mnemonic = "ldff1b";
4303       break;
4304     case LDFF1H_z_p_bz_s_x32_unscaled:
4305       mnemonic = "ldff1h";
4306       break;
4307     case LDFF1SB_z_p_bz_s_x32_unscaled:
4308       mnemonic = "ldff1sb";
4309       break;
4310     case LDFF1SH_z_p_bz_s_x32_unscaled:
4311       mnemonic = "ldff1sh";
4312       break;
4313     case LDFF1W_z_p_bz_s_x32_unscaled:
4314       mnemonic = "ldff1w";
4315       break;
4316     default:
4317       form = "(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets)";
4318       break;
4319   }
4320   Format(instr, mnemonic, form);
4321 }
4322 
4323 void Disassembler::VisitSVE32BitGatherLoad_VectorPlusImm(
4324     const Instruction *instr) {
4325   const char *form = "{'Zt.s}, 'Pgl/z, ['Zn.s]";
4326   const char *form_imm_b = "{'Zt.s}, 'Pgl/z, ['Zn.s, #'u2016]";
4327   const char *form_imm_h = "{'Zt.s}, 'Pgl/z, ['Zn.s, #'u2016*2]";
4328   const char *form_imm_w = "{'Zt.s}, 'Pgl/z, ['Zn.s, #'u2016*4]";
4329   const char *form_imm;
4330 
4331   const char *mnemonic = "unimplemented";
4332   switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
4333     case LD1B_z_p_ai_s:
4334       mnemonic = "ld1b";
4335       form_imm = form_imm_b;
4336       break;
4337     case LD1H_z_p_ai_s:
4338       mnemonic = "ld1h";
4339       form_imm = form_imm_h;
4340       break;
4341     case LD1SB_z_p_ai_s:
4342       mnemonic = "ld1sb";
4343       form_imm = form_imm_b;
4344       break;
4345     case LD1SH_z_p_ai_s:
4346       mnemonic = "ld1sh";
4347       form_imm = form_imm_h;
4348       break;
4349     case LD1W_z_p_ai_s:
4350       mnemonic = "ld1w";
4351       form_imm = form_imm_w;
4352       break;
4353     case LDFF1B_z_p_ai_s:
4354       mnemonic = "ldff1b";
4355       form_imm = form_imm_b;
4356       break;
4357     case LDFF1H_z_p_ai_s:
4358       mnemonic = "ldff1h";
4359       form_imm = form_imm_h;
4360       break;
4361     case LDFF1SB_z_p_ai_s:
4362       mnemonic = "ldff1sb";
4363       form_imm = form_imm_b;
4364       break;
4365     case LDFF1SH_z_p_ai_s:
4366       mnemonic = "ldff1sh";
4367       form_imm = form_imm_h;
4368       break;
4369     case LDFF1W_z_p_ai_s:
4370       mnemonic = "ldff1w";
4371       form_imm = form_imm_w;
4372       break;
4373     default:
4374       form = "(SVE32BitGatherLoad_VectorPlusImm)";
4375       form_imm = form;
4376       break;
4377   }
4378   if (instr->ExtractBits(20, 16) != 0) form = form_imm;
4379 
4380   Format(instr, mnemonic, form);
4381 }
4382 
4383 void Disassembler::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
4384     const Instruction *instr) {
4385   const char *mnemonic = "unimplemented";
4386   const char *form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.s, '?22:suxtw";
4387   const char *suffix = NULL;
4388 
4389   switch (
4390       instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
4391     case PRFB_i_p_bz_s_x32_scaled:
4392       mnemonic = "prfb";
4393       suffix = "]";
4394       break;
4395     case PRFD_i_p_bz_s_x32_scaled:
4396       mnemonic = "prfd";
4397       suffix = " #3]";
4398       break;
4399     case PRFH_i_p_bz_s_x32_scaled:
4400       mnemonic = "prfh";
4401       suffix = " #1]";
4402       break;
4403     case PRFW_i_p_bz_s_x32_scaled:
4404       mnemonic = "prfw";
4405       suffix = " #2]";
4406       break;
4407     default:
4408       form = "(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets)";
4409       break;
4410   }
4411   Format(instr, mnemonic, form, suffix);
4412 }
4413 
4414 void Disassembler::VisitSVE32BitGatherPrefetch_VectorPlusImm(
4415     const Instruction *instr) {
4416   const char *mnemonic = "unimplemented";
4417   const char *form = (instr->ExtractBits(20, 16) != 0)
4418                          ? "'prefSVEOp, 'Pgl, ['Zn.s, #'u2016]"
4419                          : "'prefSVEOp, 'Pgl, ['Zn.s]";
4420 
4421   switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
4422     case PRFB_i_p_ai_s:
4423       mnemonic = "prfb";
4424       break;
4425     case PRFD_i_p_ai_s:
4426       mnemonic = "prfd";
4427       break;
4428     case PRFH_i_p_ai_s:
4429       mnemonic = "prfh";
4430       break;
4431     case PRFW_i_p_ai_s:
4432       mnemonic = "prfw";
4433       break;
4434     default:
4435       break;
4436   }
4437   Format(instr, mnemonic, form);
4438 }
4439 
4440 void Disassembler::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
4441     const Instruction *instr) {
4442   const char *mnemonic = "unimplemented";
4443   const char *form = "{'Zt.s}, 'Pgl, ['Xns, 'Zm.s, '?14:suxtw #'u2423]";
4444 
4445   switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
4446     case ST1H_z_p_bz_s_x32_scaled:
4447       mnemonic = "st1h";
4448       break;
4449     case ST1W_z_p_bz_s_x32_scaled:
4450       mnemonic = "st1w";
4451       break;
4452     default:
4453       form = "(SVE32BitScatterStore_ScalarPlus32BitScaledOffsets)";
4454       break;
4455   }
4456   Format(instr, mnemonic, form);
4457 }
4458 
4459 void Disassembler::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
4460     const Instruction *instr) {
4461   const char *mnemonic = "unimplemented";
4462   const char *form = "{'Zt.s}, 'Pgl, ['Xns, 'Zm.s, '?14:suxtw]";
4463 
4464   switch (
4465       instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
4466     case ST1B_z_p_bz_s_x32_unscaled:
4467       mnemonic = "st1b";
4468       break;
4469     case ST1H_z_p_bz_s_x32_unscaled:
4470       mnemonic = "st1h";
4471       break;
4472     case ST1W_z_p_bz_s_x32_unscaled:
4473       mnemonic = "st1w";
4474       break;
4475     default:
4476       form = "(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets)";
4477       break;
4478   }
4479   Format(instr, mnemonic, form);
4480 }
4481 
4482 void Disassembler::VisitSVE32BitScatterStore_VectorPlusImm(
4483     const Instruction *instr) {
4484   const char *mnemonic = "unimplemented";
4485   const char *form = "{'Zt.s}, 'Pgl, ['Zn.s";
4486   const char *suffix = NULL;
4487 
4488   bool is_zero = instr->ExtractBits(20, 16) == 0;
4489 
4490   switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
4491     case ST1B_z_p_ai_s:
4492       mnemonic = "st1b";
4493       suffix = is_zero ? "]" : ", #'u2016]";
4494       break;
4495     case ST1H_z_p_ai_s:
4496       mnemonic = "st1h";
4497       suffix = is_zero ? "]" : ", #'u2016*2]";
4498       break;
4499     case ST1W_z_p_ai_s:
4500       mnemonic = "st1w";
4501       suffix = is_zero ? "]" : ", #'u2016*4]";
4502       break;
4503     default:
4504       form = "(SVE32BitScatterStore_VectorPlusImm)";
4505       break;
4506   }
4507   Format(instr, mnemonic, form, suffix);
4508 }
4509 
4510 void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
4511     const Instruction *instr) {
4512   const char *mnemonic = "unimplemented";
4513   const char *form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, '?22:suxtw #'u2423]";
4514 
4515   switch (instr->Mask(
4516       SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
4517     case LD1D_z_p_bz_d_x32_scaled:
4518       mnemonic = "ld1d";
4519       break;
4520     case LD1H_z_p_bz_d_x32_scaled:
4521       mnemonic = "ld1h";
4522       break;
4523     case LD1SH_z_p_bz_d_x32_scaled:
4524       mnemonic = "ld1sh";
4525       break;
4526     case LD1SW_z_p_bz_d_x32_scaled:
4527       mnemonic = "ld1sw";
4528       break;
4529     case LD1W_z_p_bz_d_x32_scaled:
4530       mnemonic = "ld1w";
4531       break;
4532     case LDFF1D_z_p_bz_d_x32_scaled:
4533       mnemonic = "ldff1d";
4534       break;
4535     case LDFF1H_z_p_bz_d_x32_scaled:
4536       mnemonic = "ldff1h";
4537       break;
4538     case LDFF1SH_z_p_bz_d_x32_scaled:
4539       mnemonic = "ldff1sh";
4540       break;
4541     case LDFF1SW_z_p_bz_d_x32_scaled:
4542       mnemonic = "ldff1sw";
4543       break;
4544     case LDFF1W_z_p_bz_d_x32_scaled:
4545       mnemonic = "ldff1w";
4546       break;
4547     default:
4548       form = "(SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)";
4549       break;
4550   }
4551   Format(instr, mnemonic, form);
4552 }
4553 
4554 void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
4555     const Instruction *instr) {
4556   const char *mnemonic = "unimplemented";
4557   const char *form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, lsl #'u2423]";
4558 
4559   switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
4560     case LD1D_z_p_bz_d_64_scaled:
4561       mnemonic = "ld1d";
4562       break;
4563     case LD1H_z_p_bz_d_64_scaled:
4564       mnemonic = "ld1h";
4565       break;
4566     case LD1SH_z_p_bz_d_64_scaled:
4567       mnemonic = "ld1sh";
4568       break;
4569     case LD1SW_z_p_bz_d_64_scaled:
4570       mnemonic = "ld1sw";
4571       break;
4572     case LD1W_z_p_bz_d_64_scaled:
4573       mnemonic = "ld1w";
4574       break;
4575     case LDFF1D_z_p_bz_d_64_scaled:
4576       mnemonic = "ldff1d";
4577       break;
4578     case LDFF1H_z_p_bz_d_64_scaled:
4579       mnemonic = "ldff1h";
4580       break;
4581     case LDFF1SH_z_p_bz_d_64_scaled:
4582       mnemonic = "ldff1sh";
4583       break;
4584     case LDFF1SW_z_p_bz_d_64_scaled:
4585       mnemonic = "ldff1sw";
4586       break;
4587     case LDFF1W_z_p_bz_d_64_scaled:
4588       mnemonic = "ldff1w";
4589       break;
4590     default:
4591       form = "(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)";
4592       break;
4593   }
4594   Format(instr, mnemonic, form);
4595 }
4596 
4597 void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
4598     const Instruction *instr) {
4599   const char *mnemonic = "unimplemented";
4600   const char *form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d]";
4601 
4602   switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
4603     case LD1B_z_p_bz_d_64_unscaled:
4604       mnemonic = "ld1b";
4605       break;
4606     case LD1D_z_p_bz_d_64_unscaled:
4607       mnemonic = "ld1d";
4608       break;
4609     case LD1H_z_p_bz_d_64_unscaled:
4610       mnemonic = "ld1h";
4611       break;
4612     case LD1SB_z_p_bz_d_64_unscaled:
4613       mnemonic = "ld1sb";
4614       break;
4615     case LD1SH_z_p_bz_d_64_unscaled:
4616       mnemonic = "ld1sh";
4617       break;
4618     case LD1SW_z_p_bz_d_64_unscaled:
4619       mnemonic = "ld1sw";
4620       break;
4621     case LD1W_z_p_bz_d_64_unscaled:
4622       mnemonic = "ld1w";
4623       break;
4624     case LDFF1B_z_p_bz_d_64_unscaled:
4625       mnemonic = "ldff1b";
4626       break;
4627     case LDFF1D_z_p_bz_d_64_unscaled:
4628       mnemonic = "ldff1d";
4629       break;
4630     case LDFF1H_z_p_bz_d_64_unscaled:
4631       mnemonic = "ldff1h";
4632       break;
4633     case LDFF1SB_z_p_bz_d_64_unscaled:
4634       mnemonic = "ldff1sb";
4635       break;
4636     case LDFF1SH_z_p_bz_d_64_unscaled:
4637       mnemonic = "ldff1sh";
4638       break;
4639     case LDFF1SW_z_p_bz_d_64_unscaled:
4640       mnemonic = "ldff1sw";
4641       break;
4642     case LDFF1W_z_p_bz_d_64_unscaled:
4643       mnemonic = "ldff1w";
4644       break;
4645     default:
4646       break;
4647   }
4648   Format(instr, mnemonic, form);
4649 }
4650 
4651 void Disassembler::
4652     VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
4653         const Instruction *instr) {
4654   const char *mnemonic = "unimplemented";
4655   const char *form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, '?22:suxtw]";
4656 
4657   switch (instr->Mask(
4658       SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
4659     case LD1B_z_p_bz_d_x32_unscaled:
4660       mnemonic = "ld1b";
4661       break;
4662     case LD1D_z_p_bz_d_x32_unscaled:
4663       mnemonic = "ld1d";
4664       break;
4665     case LD1H_z_p_bz_d_x32_unscaled:
4666       mnemonic = "ld1h";
4667       break;
4668     case LD1SB_z_p_bz_d_x32_unscaled:
4669       mnemonic = "ld1sb";
4670       break;
4671     case LD1SH_z_p_bz_d_x32_unscaled:
4672       mnemonic = "ld1sh";
4673       break;
4674     case LD1SW_z_p_bz_d_x32_unscaled:
4675       mnemonic = "ld1sw";
4676       break;
4677     case LD1W_z_p_bz_d_x32_unscaled:
4678       mnemonic = "ld1w";
4679       break;
4680     case LDFF1B_z_p_bz_d_x32_unscaled:
4681       mnemonic = "ldff1b";
4682       break;
4683     case LDFF1D_z_p_bz_d_x32_unscaled:
4684       mnemonic = "ldff1d";
4685       break;
4686     case LDFF1H_z_p_bz_d_x32_unscaled:
4687       mnemonic = "ldff1h";
4688       break;
4689     case LDFF1SB_z_p_bz_d_x32_unscaled:
4690       mnemonic = "ldff1sb";
4691       break;
4692     case LDFF1SH_z_p_bz_d_x32_unscaled:
4693       mnemonic = "ldff1sh";
4694       break;
4695     case LDFF1SW_z_p_bz_d_x32_unscaled:
4696       mnemonic = "ldff1sw";
4697       break;
4698     case LDFF1W_z_p_bz_d_x32_unscaled:
4699       mnemonic = "ldff1w";
4700       break;
4701     default:
4702       form = "(SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)";
4703       break;
4704   }
4705   Format(instr, mnemonic, form);
4706 }
4707 
4708 void Disassembler::VisitSVE64BitGatherLoad_VectorPlusImm(
4709     const Instruction *instr) {
4710   const char *form = "{'Zt.d}, 'Pgl/z, ['Zn.d]";
4711   const char *form_imm[4] = {"{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016]",
4712                              "{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016*2]",
4713                              "{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016*4]",
4714                              "{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016*8]"};
4715 
4716   if (instr->ExtractBits(20, 16) != 0) {
4717     unsigned msz = instr->ExtractBits(24, 23);
4718     bool sign_extend = instr->ExtractBit(14) == 0;
4719     if ((msz == kDRegSizeInBytesLog2) && sign_extend) {
4720       form = "(SVE64BitGatherLoad_VectorPlusImm)";
4721     } else {
4722       VIXL_ASSERT(msz < ArrayLength(form_imm));
4723       form = form_imm[msz];
4724     }
4725   }
4726 
4727   const char *mnemonic = "unimplemented";
4728   switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
4729     case LD1B_z_p_ai_d:
4730       mnemonic = "ld1b";
4731       break;
4732     case LD1D_z_p_ai_d:
4733       mnemonic = "ld1d";
4734       break;
4735     case LD1H_z_p_ai_d:
4736       mnemonic = "ld1h";
4737       break;
4738     case LD1SB_z_p_ai_d:
4739       mnemonic = "ld1sb";
4740       break;
4741     case LD1SH_z_p_ai_d:
4742       mnemonic = "ld1sh";
4743       break;
4744     case LD1SW_z_p_ai_d:
4745       mnemonic = "ld1sw";
4746       break;
4747     case LD1W_z_p_ai_d:
4748       mnemonic = "ld1w";
4749       break;
4750     case LDFF1B_z_p_ai_d:
4751       mnemonic = "ldff1b";
4752       break;
4753     case LDFF1D_z_p_ai_d:
4754       mnemonic = "ldff1d";
4755       break;
4756     case LDFF1H_z_p_ai_d:
4757       mnemonic = "ldff1h";
4758       break;
4759     case LDFF1SB_z_p_ai_d:
4760       mnemonic = "ldff1sb";
4761       break;
4762     case LDFF1SH_z_p_ai_d:
4763       mnemonic = "ldff1sh";
4764       break;
4765     case LDFF1SW_z_p_ai_d:
4766       mnemonic = "ldff1sw";
4767       break;
4768     case LDFF1W_z_p_ai_d:
4769       mnemonic = "ldff1w";
4770       break;
4771     default:
4772       break;
4773   }
4774   Format(instr, mnemonic, form);
4775 }
4776 
4777 void Disassembler::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
4778     const Instruction *instr) {
4779   const char *mnemonic = "unimplemented";
4780   const char *form = "(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets)";
4781 
4782   switch (
4783       instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
4784     case PRFB_i_p_bz_d_64_scaled:
4785       mnemonic = "prfb";
4786       form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d]";
4787       break;
4788     case PRFD_i_p_bz_d_64_scaled:
4789       mnemonic = "prfd";
4790       form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, lsl #3]";
4791       break;
4792     case PRFH_i_p_bz_d_64_scaled:
4793       mnemonic = "prfh";
4794       form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, lsl #1]";
4795       break;
4796     case PRFW_i_p_bz_d_64_scaled:
4797       mnemonic = "prfw";
4798       form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, lsl #2]";
4799       break;
4800     default:
4801       break;
4802   }
4803   Format(instr, mnemonic, form);
4804 }
4805 
4806 void Disassembler::
4807     VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
4808         const Instruction *instr) {
4809   const char *mnemonic = "unimplemented";
4810   const char *form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, '?22:suxtw";
4811   const char *suffix = NULL;
4812 
4813   switch (instr->Mask(
4814       SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
4815     case PRFB_i_p_bz_d_x32_scaled:
4816       mnemonic = "prfb";
4817       suffix = " ]";
4818       break;
4819     case PRFD_i_p_bz_d_x32_scaled:
4820       mnemonic = "prfd";
4821       suffix = " #3]";
4822       break;
4823     case PRFH_i_p_bz_d_x32_scaled:
4824       mnemonic = "prfh";
4825       suffix = " #1]";
4826       break;
4827     case PRFW_i_p_bz_d_x32_scaled:
4828       mnemonic = "prfw";
4829       suffix = " #2]";
4830       break;
4831     default:
4832       form = "(SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets)";
4833       break;
4834   }
4835   Format(instr, mnemonic, form, suffix);
4836 }
4837 
4838 void Disassembler::VisitSVE64BitGatherPrefetch_VectorPlusImm(
4839     const Instruction *instr) {
4840   const char *mnemonic = "unimplemented";
4841   const char *form = (instr->ExtractBits(20, 16) != 0)
4842                          ? "'prefSVEOp, 'Pgl, ['Zn.d, #'u2016]"
4843                          : "'prefSVEOp, 'Pgl, ['Zn.d]";
4844 
4845   switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
4846     case PRFB_i_p_ai_d:
4847       mnemonic = "prfb";
4848       break;
4849     case PRFD_i_p_ai_d:
4850       mnemonic = "prfd";
4851       break;
4852     case PRFH_i_p_ai_d:
4853       mnemonic = "prfh";
4854       break;
4855     case PRFW_i_p_ai_d:
4856       mnemonic = "prfw";
4857       break;
4858     default:
4859       break;
4860   }
4861   Format(instr, mnemonic, form);
4862 }
4863 
4864 void Disassembler::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
4865     const Instruction *instr) {
4866   const char *mnemonic = "unimplemented";
4867   const char *form = "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, lsl #'u2423]";
4868 
4869   switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
4870     case ST1D_z_p_bz_d_64_scaled:
4871       mnemonic = "st1d";
4872       break;
4873     case ST1H_z_p_bz_d_64_scaled:
4874       mnemonic = "st1h";
4875       break;
4876     case ST1W_z_p_bz_d_64_scaled:
4877       mnemonic = "st1w";
4878       break;
4879     default:
4880       form = "(SVE64BitScatterStore_ScalarPlus64BitScaledOffsets)";
4881       break;
4882   }
4883   Format(instr, mnemonic, form);
4884 }
4885 
4886 void Disassembler::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
4887     const Instruction *instr) {
4888   const char *mnemonic = "unimplemented";
4889   const char *form = "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d]";
4890 
4891   switch (
4892       instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
4893     case ST1B_z_p_bz_d_64_unscaled:
4894       mnemonic = "st1b";
4895       break;
4896     case ST1D_z_p_bz_d_64_unscaled:
4897       mnemonic = "st1d";
4898       break;
4899     case ST1H_z_p_bz_d_64_unscaled:
4900       mnemonic = "st1h";
4901       break;
4902     case ST1W_z_p_bz_d_64_unscaled:
4903       mnemonic = "st1w";
4904       break;
4905     default:
4906       form = "(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffset)";
4907       break;
4908   }
4909   Format(instr, mnemonic, form);
4910 }
4911 
4912 void Disassembler::
4913     VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
4914         const Instruction *instr) {
4915   const char *mnemonic = "unimplemented";
4916   const char *form = "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, '?14:suxtw #'u2423]";
4917 
4918   switch (instr->Mask(
4919       SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
4920     case ST1D_z_p_bz_d_x32_scaled:
4921       mnemonic = "st1d";
4922       break;
4923     case ST1H_z_p_bz_d_x32_scaled:
4924       mnemonic = "st1h";
4925       break;
4926     case ST1W_z_p_bz_d_x32_scaled:
4927       mnemonic = "st1w";
4928       break;
4929     default:
4930       form = "(SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets)";
4931       break;
4932   }
4933   Format(instr, mnemonic, form);
4934 }
4935 
4936 void Disassembler::
4937     VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
4938         const Instruction *instr) {
4939   const char *mnemonic = "unimplemented";
4940   const char *form = "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, '?14:suxtw]";
4941 
4942   switch (instr->Mask(
4943       SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
4944     case ST1B_z_p_bz_d_x32_unscaled:
4945       mnemonic = "st1b";
4946       break;
4947     case ST1D_z_p_bz_d_x32_unscaled:
4948       mnemonic = "st1d";
4949       break;
4950     case ST1H_z_p_bz_d_x32_unscaled:
4951       mnemonic = "st1h";
4952       break;
4953     case ST1W_z_p_bz_d_x32_unscaled:
4954       mnemonic = "st1w";
4955       break;
4956     default:
4957       form = "(SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets)";
4958       break;
4959   }
4960   Format(instr, mnemonic, form);
4961 }
4962 
4963 void Disassembler::VisitSVE64BitScatterStore_VectorPlusImm(
4964     const Instruction *instr) {
4965   const char *mnemonic = "unimplemented";
4966   const char *form = "{'Zt.d}, 'Pgl, ['Zn.d";
4967   const char *suffix = NULL;
4968 
4969   bool is_zero = instr->ExtractBits(20, 16) == 0;
4970 
4971   switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
4972     case ST1B_z_p_ai_d:
4973       mnemonic = "st1b";
4974       suffix = is_zero ? "]" : ", #'u2016]";
4975       break;
4976     case ST1D_z_p_ai_d:
4977       mnemonic = "st1d";
4978       suffix = is_zero ? "]" : ", #'u2016*8]";
4979       break;
4980     case ST1H_z_p_ai_d:
4981       mnemonic = "st1h";
4982       suffix = is_zero ? "]" : ", #'u2016*2]";
4983       break;
4984     case ST1W_z_p_ai_d:
4985       mnemonic = "st1w";
4986       suffix = is_zero ? "]" : ", #'u2016*4]";
4987       break;
4988     default:
4989       form = "(SVE64BitScatterStore_VectorPlusImm)";
4990       break;
4991   }
4992   Format(instr, mnemonic, form, suffix);
4993 }
4994 
4995 void Disassembler::VisitSVEBitwiseLogicalWithImm_Unpredicated(
4996     const Instruction *instr) {
4997   const char *mnemonic = "unimplemented";
4998   const char *form = "'Zd.'tl, 'Zd.'tl, 'ITriSvel";
4999 
5000   if (instr->GetSVEImmLogical() == 0) {
5001     // The immediate encoded in the instruction is not in the expected format.
5002     Format(instr, "unallocated", "(SVEBitwiseImm)");
5003     return;
5004   }
5005 
5006   switch (instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask)) {
5007     case AND_z_zi:
5008       mnemonic = "and";
5009       break;
5010     case EOR_z_zi:
5011       mnemonic = "eor";
5012       break;
5013     case ORR_z_zi:
5014       mnemonic = "orr";
5015       break;
5016     default:
5017       break;
5018   }
5019   Format(instr, mnemonic, form);
5020 }
5021 
5022 void Disassembler::VisitSVEBitwiseLogical_Predicated(const Instruction *instr) {
5023   const char *mnemonic = "unimplemented";
5024   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
5025 
5026   switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
5027     case AND_z_p_zz:
5028       mnemonic = "and";
5029       break;
5030     case BIC_z_p_zz:
5031       mnemonic = "bic";
5032       break;
5033     case EOR_z_p_zz:
5034       mnemonic = "eor";
5035       break;
5036     case ORR_z_p_zz:
5037       mnemonic = "orr";
5038       break;
5039     default:
5040       break;
5041   }
5042   Format(instr, mnemonic, form);
5043 }
5044 
5045 void Disassembler::VisitSVEBitwiseShiftByImm_Predicated(
5046     const Instruction *instr) {
5047   const char *mnemonic = mnemonic_.c_str();
5048   const char *form = "'Zd.'tszp, 'Pgl/m, 'Zd.'tszp, ";
5049   const char *suffix = NULL;
5050   unsigned tsize = (instr->ExtractBits(23, 22) << 2) | instr->ExtractBits(9, 8);
5051 
5052   if (tsize == 0) {
5053     mnemonic = "unimplemented";
5054     form = "(SVEBitwiseShiftByImm_Predicated)";
5055   } else {
5056     switch (form_hash_) {
5057       case Hash("lsl_z_p_zi"):
5058       case Hash("sqshl_z_p_zi"):
5059       case Hash("sqshlu_z_p_zi"):
5060       case Hash("uqshl_z_p_zi"):
5061         suffix = "'ITriSvep";
5062         break;
5063       case Hash("asrd_z_p_zi"):
5064       case Hash("asr_z_p_zi"):
5065       case Hash("lsr_z_p_zi"):
5066       case Hash("srshr_z_p_zi"):
5067       case Hash("urshr_z_p_zi"):
5068         suffix = "'ITriSveq";
5069         break;
5070       default:
5071         mnemonic = "unimplemented";
5072         form = "(SVEBitwiseShiftByImm_Predicated)";
5073         break;
5074     }
5075   }
5076   Format(instr, mnemonic, form, suffix);
5077 }
5078 
5079 void Disassembler::VisitSVEBitwiseShiftByVector_Predicated(
5080     const Instruction *instr) {
5081   const char *mnemonic = "unimplemented";
5082   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
5083 
5084   switch (instr->Mask(SVEBitwiseShiftByVector_PredicatedMask)) {
5085     case ASRR_z_p_zz:
5086       mnemonic = "asrr";
5087       break;
5088     case ASR_z_p_zz:
5089       mnemonic = "asr";
5090       break;
5091     case LSLR_z_p_zz:
5092       mnemonic = "lslr";
5093       break;
5094     case LSL_z_p_zz:
5095       mnemonic = "lsl";
5096       break;
5097     case LSRR_z_p_zz:
5098       mnemonic = "lsrr";
5099       break;
5100     case LSR_z_p_zz:
5101       mnemonic = "lsr";
5102       break;
5103     default:
5104       form = "(SVEBitwiseShiftByVector_Predicated)";
5105       break;
5106   }
5107   Format(instr, mnemonic, form);
5108 }
5109 
5110 void Disassembler::VisitSVEBitwiseShiftByWideElements_Predicated(
5111     const Instruction *instr) {
5112   const char *mnemonic = "unimplemented";
5113   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.d";
5114 
5115   if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
5116     form = "(SVEBitwiseShiftByWideElements_Predicated)";
5117   } else {
5118     switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
5119       case ASR_z_p_zw:
5120         mnemonic = "asr";
5121         break;
5122       case LSL_z_p_zw:
5123         mnemonic = "lsl";
5124         break;
5125       case LSR_z_p_zw:
5126         mnemonic = "lsr";
5127         break;
5128       default:
5129         form = "(SVEBitwiseShiftByWideElements_Predicated)";
5130         break;
5131     }
5132   }
5133   Format(instr, mnemonic, form);
5134 }
5135 
5136 static bool SVEMoveMaskPreferred(uint64_t value, int lane_bytes_log2) {
5137   VIXL_ASSERT(IsUintN(8 << lane_bytes_log2, value));
5138 
5139   // Duplicate lane-sized value across double word.
5140   switch (lane_bytes_log2) {
5141     case 0:
5142       value *= 0x0101010101010101;
5143       break;
5144     case 1:
5145       value *= 0x0001000100010001;
5146       break;
5147     case 2:
5148       value *= 0x0000000100000001;
5149       break;
5150     case 3:  // Nothing to do
5151       break;
5152     default:
5153       VIXL_UNREACHABLE();
5154   }
5155 
5156   if ((value & 0xff) == 0) {
5157     // Check for 16-bit patterns. Set least-significant 16 bits, to make tests
5158     // easier; we already checked least-significant byte is zero above.
5159     uint64_t generic_value = value | 0xffff;
5160 
5161     // Check 0x00000000_0000pq00 or 0xffffffff_ffffpq00.
5162     if ((generic_value == 0xffff) || (generic_value == UINT64_MAX)) {
5163       return false;
5164     }
5165 
5166     // Check 0x0000pq00_0000pq00 or 0xffffpq00_ffffpq00.
5167     uint64_t rotvalue = RotateRight(value, 32, 64);
5168     if (value == rotvalue) {
5169       generic_value &= 0xffffffff;
5170       if ((generic_value == 0xffff) || (generic_value == UINT32_MAX)) {
5171         return false;
5172       }
5173     }
5174 
5175     // Check 0xpq00pq00_pq00pq00.
5176     rotvalue = RotateRight(value, 16, 64);
5177     if (value == rotvalue) {
5178       return false;
5179     }
5180   } else {
5181     // Check for 8-bit patterns. Set least-significant byte, to make tests
5182     // easier.
5183     uint64_t generic_value = value | 0xff;
5184 
5185     // Check 0x00000000_000000pq or 0xffffffff_ffffffpq.
5186     if ((generic_value == 0xff) || (generic_value == UINT64_MAX)) {
5187       return false;
5188     }
5189 
5190     // Check 0x000000pq_000000pq or 0xffffffpq_ffffffpq.
5191     uint64_t rotvalue = RotateRight(value, 32, 64);
5192     if (value == rotvalue) {
5193       generic_value &= 0xffffffff;
5194       if ((generic_value == 0xff) || (generic_value == UINT32_MAX)) {
5195         return false;
5196       }
5197     }
5198 
5199     // Check 0x00pq00pq_00pq00pq or 0xffpqffpq_ffpqffpq.
5200     rotvalue = RotateRight(value, 16, 64);
5201     if (value == rotvalue) {
5202       generic_value &= 0xffff;
5203       if ((generic_value == 0xff) || (generic_value == UINT16_MAX)) {
5204         return false;
5205       }
5206     }
5207 
5208     // Check 0xpqpqpqpq_pqpqpqpq.
5209     rotvalue = RotateRight(value, 8, 64);
5210     if (value == rotvalue) {
5211       return false;
5212     }
5213   }
5214   return true;
5215 }
5216 
5217 void Disassembler::VisitSVEBroadcastBitmaskImm(const Instruction *instr) {
5218   const char *mnemonic = "unimplemented";
5219   const char *form = "(SVEBroadcastBitmaskImm)";
5220 
5221   switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
5222     case DUPM_z_i: {
5223       uint64_t imm = instr->GetSVEImmLogical();
5224       if (imm != 0) {
5225         int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
5226         mnemonic = SVEMoveMaskPreferred(imm, lane_size) ? "mov" : "dupm";
5227         form = "'Zd.'tl, 'ITriSvel";
5228       }
5229       break;
5230     }
5231     default:
5232       break;
5233   }
5234   Format(instr, mnemonic, form);
5235 }
5236 
5237 void Disassembler::VisitSVEBroadcastFPImm_Unpredicated(
5238     const Instruction *instr) {
5239   const char *mnemonic = "unimplemented";
5240   const char *form = "(SVEBroadcastFPImm_Unpredicated)";
5241 
5242   if (instr->GetSVEVectorFormat() != kFormatVnB) {
5243     switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
5244       case FDUP_z_i:
5245         // The preferred disassembly for fdup is "fmov".
5246         mnemonic = "fmov";
5247         form = "'Zd.'t, 'IFPSve";
5248         break;
5249       default:
5250         break;
5251     }
5252   }
5253   Format(instr, mnemonic, form);
5254 }
5255 
5256 void Disassembler::VisitSVEBroadcastGeneralRegister(const Instruction *instr) {
5257   const char *mnemonic = "unimplemented";
5258   const char *form = "(SVEBroadcastGeneralRegister)";
5259 
5260   switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
5261     case DUP_z_r:
5262       // The preferred disassembly for dup is "mov".
5263       mnemonic = "mov";
5264       if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
5265         form = "'Zd.'t, 'Xns";
5266       } else {
5267         form = "'Zd.'t, 'Wns";
5268       }
5269       break;
5270     default:
5271       break;
5272   }
5273   Format(instr, mnemonic, form);
5274 }
5275 
5276 void Disassembler::VisitSVEBroadcastIndexElement(const Instruction *instr) {
5277   const char *mnemonic = "unimplemented";
5278   const char *form = "(SVEBroadcastIndexElement)";
5279 
5280   switch (instr->Mask(SVEBroadcastIndexElementMask)) {
5281     case DUP_z_zi: {
5282       // The tsz field must not be zero.
5283       int tsz = instr->ExtractBits(20, 16);
5284       if (tsz != 0) {
5285         // The preferred disassembly for dup is "mov".
5286         mnemonic = "mov";
5287         int imm2 = instr->ExtractBits(23, 22);
5288         if ((CountSetBits(imm2) + CountSetBits(tsz)) == 1) {
5289           // If imm2:tsz has one set bit, the index is zero. This is
5290           // disassembled as a mov from a b/h/s/d/q scalar register.
5291           form = "'Zd.'ti, 'ti'u0905";
5292         } else {
5293           form = "'Zd.'ti, 'Zn.'ti['IVInsSVEIndex]";
5294         }
5295       }
5296       break;
5297     }
5298     default:
5299       break;
5300   }
5301   Format(instr, mnemonic, form);
5302 }
5303 
5304 void Disassembler::VisitSVEBroadcastIntImm_Unpredicated(
5305     const Instruction *instr) {
5306   const char *mnemonic = "unimplemented";
5307   const char *form = "(SVEBroadcastIntImm_Unpredicated)";
5308 
5309   switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
5310     case DUP_z_i:
5311       // The encoding of byte-sized lanes with lsl #8 is undefined.
5312       if ((instr->GetSVEVectorFormat() == kFormatVnB) &&
5313           (instr->ExtractBit(13) == 1))
5314         break;
5315 
5316       // The preferred disassembly for dup is "mov".
5317       mnemonic = "mov";
5318       form = (instr->ExtractBit(13) == 0) ? "'Zd.'t, #'s1205"
5319                                           : "'Zd.'t, #'s1205, lsl #8";
5320       break;
5321     default:
5322       break;
5323   }
5324   Format(instr, mnemonic, form);
5325 }
5326 
5327 void Disassembler::VisitSVECompressActiveElements(const Instruction *instr) {
5328   const char *mnemonic = "unimplemented";
5329   const char *form = "(SVECompressActiveElements)";
5330 
5331   switch (instr->Mask(SVECompressActiveElementsMask)) {
5332     case COMPACT_z_p_z:
5333       // The top bit of size is always set for compact, so 't can only be
5334       // substituted with types S and D.
5335       VIXL_ASSERT(instr->ExtractBit(23) == 1);
5336       mnemonic = "compact";
5337       form = "'Zd.'t, 'Pgl, 'Zn.'t";
5338       break;
5339     default:
5340       break;
5341   }
5342   Format(instr, mnemonic, form);
5343 }
5344 
5345 void Disassembler::VisitSVEConditionallyBroadcastElementToVector(
5346     const Instruction *instr) {
5347   const char *mnemonic = "unimplemented";
5348   const char *form = "'Zd.'t, 'Pgl, 'Zd.'t, 'Zn.'t";
5349 
5350   switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
5351     case CLASTA_z_p_zz:
5352       mnemonic = "clasta";
5353       break;
5354     case CLASTB_z_p_zz:
5355       mnemonic = "clastb";
5356       break;
5357     default:
5358       break;
5359   }
5360   Format(instr, mnemonic, form);
5361 }
5362 
5363 void Disassembler::VisitSVEConditionallyExtractElementToGeneralRegister(
5364     const Instruction *instr) {
5365   const char *mnemonic = "unimplemented";
5366   const char *form = "'Wd, 'Pgl, 'Wd, 'Zn.'t";
5367 
5368   if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
5369     form = "'Xd, p'u1210, 'Xd, 'Zn.'t";
5370   }
5371 
5372   switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
5373     case CLASTA_r_p_z:
5374       mnemonic = "clasta";
5375       break;
5376     case CLASTB_r_p_z:
5377       mnemonic = "clastb";
5378       break;
5379     default:
5380       break;
5381   }
5382   Format(instr, mnemonic, form);
5383 }
5384 
5385 void Disassembler::VisitSVEConditionallyExtractElementToSIMDFPScalar(
5386     const Instruction *instr) {
5387   const char *mnemonic = "unimplemented";
5388   const char *form = "'t'u0400, 'Pgl, 't'u0400, 'Zn.'t";
5389 
5390   switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
5391     case CLASTA_v_p_z:
5392       mnemonic = "clasta";
5393       break;
5394     case CLASTB_v_p_z:
5395       mnemonic = "clastb";
5396       break;
5397     default:
5398       break;
5399   }
5400   Format(instr, mnemonic, form);
5401 }
5402 
5403 void Disassembler::VisitSVEConditionallyTerminateScalars(
5404     const Instruction *instr) {
5405   const char *mnemonic = "unimplemented";
5406   const char *form = (instr->ExtractBit(22) == 0) ? "'Wn, 'Wm" : "'Xn, 'Xm";
5407 
5408   switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
5409     case CTERMEQ_rr:
5410       mnemonic = "ctermeq";
5411       break;
5412     case CTERMNE_rr:
5413       mnemonic = "ctermne";
5414       break;
5415     default:
5416       break;
5417   }
5418   Format(instr, mnemonic, form);
5419 }
5420 
5421 void Disassembler::VisitSVEConstructivePrefix_Unpredicated(
5422     const Instruction *instr) {
5423   const char *mnemonic = "unimplemented";
5424   const char *form = "(SVEConstructivePrefix_Unpredicated)";
5425 
5426   switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
5427     case MOVPRFX_z_z:
5428       mnemonic = "movprfx";
5429       form = "'Zd, 'Zn";
5430       break;
5431     default:
5432       break;
5433   }
5434   Format(instr, mnemonic, form);
5435 }
5436 
5437 void Disassembler::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
5438     const Instruction *instr) {
5439   const char *mnemonic = "unimplemented";
5440 
5441   bool rm_is_zr = instr->GetRm() == kZeroRegCode;
5442 
5443   const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns";
5444   const char *suffix = NULL;
5445 
5446   switch (instr->Mask(SVEContiguousFirstFaultLoad_ScalarPlusScalarMask)) {
5447     case LDFF1B_z_p_br_u16:
5448     case LDFF1B_z_p_br_u32:
5449     case LDFF1B_z_p_br_u64:
5450     case LDFF1B_z_p_br_u8:
5451       mnemonic = "ldff1b";
5452       suffix = rm_is_zr ? "]" : ", 'Xm]";
5453       break;
5454     case LDFF1D_z_p_br_u64:
5455       mnemonic = "ldff1d";
5456       suffix = rm_is_zr ? "]" : ", 'Xm, lsl #3]";
5457       break;
5458     case LDFF1H_z_p_br_u16:
5459     case LDFF1H_z_p_br_u32:
5460     case LDFF1H_z_p_br_u64:
5461       mnemonic = "ldff1h";
5462       suffix = rm_is_zr ? "]" : ", 'Xm, lsl #1]";
5463       break;
5464     case LDFF1SB_z_p_br_s16:
5465     case LDFF1SB_z_p_br_s32:
5466     case LDFF1SB_z_p_br_s64:
5467       mnemonic = "ldff1sb";
5468       suffix = rm_is_zr ? "]" : ", 'Xm]";
5469       break;
5470     case LDFF1SH_z_p_br_s32:
5471     case LDFF1SH_z_p_br_s64:
5472       mnemonic = "ldff1sh";
5473       suffix = rm_is_zr ? "]" : ", 'Xm, lsl #1]";
5474       break;
5475     case LDFF1SW_z_p_br_s64:
5476       mnemonic = "ldff1sw";
5477       suffix = rm_is_zr ? "]" : ", 'Xm, lsl #2]";
5478       break;
5479     case LDFF1W_z_p_br_u32:
5480     case LDFF1W_z_p_br_u64:
5481       mnemonic = "ldff1w";
5482       suffix = rm_is_zr ? "]" : ", 'Xm, lsl #2]";
5483       break;
5484     default:
5485       form = "(SVEContiguousFirstFaultLoad_ScalarPlusScalar)";
5486       break;
5487   }
5488 
5489   Format(instr, mnemonic, form, suffix);
5490 }
5491 
5492 void Disassembler::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
5493     const Instruction *instr) {
5494   const char *mnemonic = "unimplemented";
5495   const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns";
5496   const char *suffix =
5497       (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]";
5498 
5499   switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
5500     case LDNF1B_z_p_bi_u16:
5501     case LDNF1B_z_p_bi_u32:
5502     case LDNF1B_z_p_bi_u64:
5503     case LDNF1B_z_p_bi_u8:
5504       mnemonic = "ldnf1b";
5505       break;
5506     case LDNF1D_z_p_bi_u64:
5507       mnemonic = "ldnf1d";
5508       break;
5509     case LDNF1H_z_p_bi_u16:
5510     case LDNF1H_z_p_bi_u32:
5511     case LDNF1H_z_p_bi_u64:
5512       mnemonic = "ldnf1h";
5513       break;
5514     case LDNF1SB_z_p_bi_s16:
5515     case LDNF1SB_z_p_bi_s32:
5516     case LDNF1SB_z_p_bi_s64:
5517       mnemonic = "ldnf1sb";
5518       break;
5519     case LDNF1SH_z_p_bi_s32:
5520     case LDNF1SH_z_p_bi_s64:
5521       mnemonic = "ldnf1sh";
5522       break;
5523     case LDNF1SW_z_p_bi_s64:
5524       mnemonic = "ldnf1sw";
5525       break;
5526     case LDNF1W_z_p_bi_u32:
5527     case LDNF1W_z_p_bi_u64:
5528       mnemonic = "ldnf1w";
5529       break;
5530     default:
5531       form = "(SVEContiguousNonFaultLoad_ScalarPlusImm)";
5532       suffix = NULL;
5533       break;
5534   }
5535   Format(instr, mnemonic, form, suffix);
5536 }
5537 
5538 void Disassembler::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
5539     const Instruction *instr) {
5540   const char *mnemonic = "unimplemented";
5541   const char *form = "(SVEContiguousNonTemporalLoad_ScalarPlusImm)";
5542 
5543   const char *suffix =
5544       (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]";
5545   switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
5546     case LDNT1B_z_p_bi_contiguous:
5547       mnemonic = "ldnt1b";
5548       form = "{'Zt.b}, 'Pgl/z, ['Xns";
5549       break;
5550     case LDNT1D_z_p_bi_contiguous:
5551       mnemonic = "ldnt1d";
5552       form = "{'Zt.d}, 'Pgl/z, ['Xns";
5553       break;
5554     case LDNT1H_z_p_bi_contiguous:
5555       mnemonic = "ldnt1h";
5556       form = "{'Zt.h}, 'Pgl/z, ['Xns";
5557       break;
5558     case LDNT1W_z_p_bi_contiguous:
5559       mnemonic = "ldnt1w";
5560       form = "{'Zt.s}, 'Pgl/z, ['Xns";
5561       break;
5562     default:
5563       suffix = NULL;
5564       break;
5565   }
5566   Format(instr, mnemonic, form, suffix);
5567 }
5568 
5569 void Disassembler::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
5570     const Instruction *instr) {
5571   const char *mnemonic = "unimplemented";
5572   const char *form = "(SVEContiguousNonTemporalLoad_ScalarPlusScalar)";
5573 
5574   switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
5575     case LDNT1B_z_p_br_contiguous:
5576       mnemonic = "ldnt1b";
5577       form = "{'Zt.b}, 'Pgl/z, ['Xns, 'Rm]";
5578       break;
5579     case LDNT1D_z_p_br_contiguous:
5580       mnemonic = "ldnt1d";
5581       form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Rm, lsl #3]";
5582       break;
5583     case LDNT1H_z_p_br_contiguous:
5584       mnemonic = "ldnt1h";
5585       form = "{'Zt.h}, 'Pgl/z, ['Xns, 'Rm, lsl #1]";
5586       break;
5587     case LDNT1W_z_p_br_contiguous:
5588       mnemonic = "ldnt1w";
5589       form = "{'Zt.s}, 'Pgl/z, ['Xns, 'Rm, lsl #2]";
5590       break;
5591     default:
5592       break;
5593   }
5594   Format(instr, mnemonic, form);
5595 }
5596 
5597 void Disassembler::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
5598     const Instruction *instr) {
5599   const char *mnemonic = "unimplemented";
5600   const char *form = "(SVEContiguousNonTemporalStore_ScalarPlusImm)";
5601 
5602   const char *suffix =
5603       (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]";
5604   switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
5605     case STNT1B_z_p_bi_contiguous:
5606       mnemonic = "stnt1b";
5607       form = "{'Zt.b}, 'Pgl, ['Xns";
5608       break;
5609     case STNT1D_z_p_bi_contiguous:
5610       mnemonic = "stnt1d";
5611       form = "{'Zt.d}, 'Pgl, ['Xns";
5612       break;
5613     case STNT1H_z_p_bi_contiguous:
5614       mnemonic = "stnt1h";
5615       form = "{'Zt.h}, 'Pgl, ['Xns";
5616       break;
5617     case STNT1W_z_p_bi_contiguous:
5618       mnemonic = "stnt1w";
5619       form = "{'Zt.s}, 'Pgl, ['Xns";
5620       break;
5621     default:
5622       suffix = NULL;
5623       break;
5624   }
5625   Format(instr, mnemonic, form, suffix);
5626 }
5627 
5628 void Disassembler::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
5629     const Instruction *instr) {
5630   const char *mnemonic = "unimplemented";
5631   const char *form = "(SVEContiguousNonTemporalStore_ScalarPlusScalar)";
5632 
5633   switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
5634     case STNT1B_z_p_br_contiguous:
5635       mnemonic = "stnt1b";
5636       form = "{'Zt.b}, 'Pgl, ['Xns, 'Rm]";
5637       break;
5638     case STNT1D_z_p_br_contiguous:
5639       mnemonic = "stnt1d";
5640       form = "{'Zt.d}, 'Pgl, ['Xns, 'Rm, lsl #3]";
5641       break;
5642     case STNT1H_z_p_br_contiguous:
5643       mnemonic = "stnt1h";
5644       form = "{'Zt.h}, 'Pgl, ['Xns, 'Rm, lsl #1]";
5645       break;
5646     case STNT1W_z_p_br_contiguous:
5647       mnemonic = "stnt1w";
5648       form = "{'Zt.s}, 'Pgl, ['Xns, 'Rm, lsl #2]";
5649       break;
5650     default:
5651       break;
5652   }
5653   Format(instr, mnemonic, form);
5654 }
5655 
5656 void Disassembler::VisitSVEContiguousPrefetch_ScalarPlusImm(
5657     const Instruction *instr) {
5658   const char *mnemonic = "unimplemented";
5659   const char *form = (instr->ExtractBits(21, 16) != 0)
5660                          ? "'prefSVEOp, 'Pgl, ['Xns, #'s2116, mul vl]"
5661                          : "'prefSVEOp, 'Pgl, ['Xns]";
5662 
5663   switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
5664     case PRFB_i_p_bi_s:
5665       mnemonic = "prfb";
5666       break;
5667     case PRFD_i_p_bi_s:
5668       mnemonic = "prfd";
5669       break;
5670     case PRFH_i_p_bi_s:
5671       mnemonic = "prfh";
5672       break;
5673     case PRFW_i_p_bi_s:
5674       mnemonic = "prfw";
5675       break;
5676     default:
5677       break;
5678   }
5679   Format(instr, mnemonic, form);
5680 }
5681 
5682 void Disassembler::VisitSVEContiguousPrefetch_ScalarPlusScalar(
5683     const Instruction *instr) {
5684   const char *mnemonic = "unimplemented";
5685   const char *form = "(SVEContiguousPrefetch_ScalarPlusScalar)";
5686 
5687   if (instr->GetRm() != kZeroRegCode) {
5688     switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
5689       case PRFB_i_p_br_s:
5690         mnemonic = "prfb";
5691         form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm]";
5692         break;
5693       case PRFD_i_p_br_s:
5694         mnemonic = "prfd";
5695         form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm, lsl #3]";
5696         break;
5697       case PRFH_i_p_br_s:
5698         mnemonic = "prfh";
5699         form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm, lsl #1]";
5700         break;
5701       case PRFW_i_p_br_s:
5702         mnemonic = "prfw";
5703         form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm, lsl #2]";
5704         break;
5705       default:
5706         break;
5707     }
5708   }
5709   Format(instr, mnemonic, form);
5710 }
5711 
5712 void Disassembler::VisitSVEContiguousStore_ScalarPlusImm(
5713     const Instruction *instr) {
5714   const char *mnemonic = "unimplemented";
5715 
5716   // The 'size' field isn't in the usual place here.
5717   const char *form = "{'Zt.'tls}, 'Pgl, ['Xns, #'s1916, mul vl]";
5718   if (instr->ExtractBits(19, 16) == 0) {
5719     form = "{'Zt.'tls}, 'Pgl, ['Xns]";
5720   }
5721 
5722   switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
5723     case ST1B_z_p_bi:
5724       mnemonic = "st1b";
5725       break;
5726     case ST1D_z_p_bi:
5727       mnemonic = "st1d";
5728       break;
5729     case ST1H_z_p_bi:
5730       mnemonic = "st1h";
5731       break;
5732     case ST1W_z_p_bi:
5733       mnemonic = "st1w";
5734       break;
5735     default:
5736       break;
5737   }
5738   Format(instr, mnemonic, form);
5739 }
5740 
5741 void Disassembler::VisitSVEContiguousStore_ScalarPlusScalar(
5742     const Instruction *instr) {
5743   const char *mnemonic = "unimplemented";
5744 
5745   // The 'size' field isn't in the usual place here.
5746   const char *form = "{'Zt.'tls}, 'Pgl, ['Xns, 'Xm'NSveS]";
5747 
5748   switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
5749     case ST1B_z_p_br:
5750       mnemonic = "st1b";
5751       break;
5752     case ST1D_z_p_br:
5753       mnemonic = "st1d";
5754       break;
5755     case ST1H_z_p_br:
5756       mnemonic = "st1h";
5757       break;
5758     case ST1W_z_p_br:
5759       mnemonic = "st1w";
5760       break;
5761     default:
5762       break;
5763   }
5764   Format(instr, mnemonic, form);
5765 }
5766 
5767 void Disassembler::VisitSVECopyFPImm_Predicated(const Instruction *instr) {
5768   const char *mnemonic = "unimplemented";
5769   const char *form = "(SVECopyFPImm_Predicated)";
5770 
5771   if (instr->GetSVEVectorFormat() != kFormatVnB) {
5772     switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
5773       case FCPY_z_p_i:
5774         // The preferred disassembly for fcpy is "fmov".
5775         mnemonic = "fmov";
5776         form = "'Zd.'t, 'Pm/m, 'IFPSve";
5777         break;
5778       default:
5779         break;
5780     }
5781   }
5782   Format(instr, mnemonic, form);
5783 }
5784 
5785 void Disassembler::VisitSVECopyGeneralRegisterToVector_Predicated(
5786     const Instruction *instr) {
5787   const char *mnemonic = "unimplemented";
5788   const char *form = "(SVECopyGeneralRegisterToVector_Predicated)";
5789 
5790   switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
5791     case CPY_z_p_r:
5792       // The preferred disassembly for cpy is "mov".
5793       mnemonic = "mov";
5794       form = "'Zd.'t, 'Pgl/m, 'Wns";
5795       if (instr->GetSVESize() == kXRegSizeInBytesLog2) {
5796         form = "'Zd.'t, 'Pgl/m, 'Xns";
5797       }
5798       break;
5799     default:
5800       break;
5801   }
5802   Format(instr, mnemonic, form);
5803 }
5804 
5805 void Disassembler::VisitSVECopyIntImm_Predicated(const Instruction *instr) {
5806   const char *mnemonic = "unimplemented";
5807   const char *form = "(SVECopyIntImm_Predicated)";
5808   const char *suffix = NULL;
5809 
5810   switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
5811     case CPY_z_p_i: {
5812       // The preferred disassembly for cpy is "mov".
5813       mnemonic = "mov";
5814       form = "'Zd.'t, 'Pm/'?14:mz, #'s1205";
5815       if (instr->ExtractBit(13) != 0) suffix = ", lsl #8";
5816       break;
5817     }
5818     default:
5819       break;
5820   }
5821   Format(instr, mnemonic, form, suffix);
5822 }
5823 
5824 void Disassembler::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
5825     const Instruction *instr) {
5826   const char *mnemonic = "unimplemented";
5827   const char *form = "(SVECopySIMDFPScalarRegisterToVector_Predicated)";
5828 
5829   switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
5830     case CPY_z_p_v:
5831       // The preferred disassembly for cpy is "mov".
5832       mnemonic = "mov";
5833       form = "'Zd.'t, 'Pgl/m, 'Vnv";
5834       break;
5835     default:
5836       break;
5837   }
5838   Format(instr, mnemonic, form);
5839 }
5840 
5841 void Disassembler::VisitSVEExtractElementToGeneralRegister(
5842     const Instruction *instr) {
5843   const char *mnemonic = "unimplemented";
5844   const char *form = "'Wd, 'Pgl, 'Zn.'t";
5845 
5846   if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
5847     form = "'Xd, p'u1210, 'Zn.'t";
5848   }
5849 
5850   switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
5851     case LASTA_r_p_z:
5852       mnemonic = "lasta";
5853       break;
5854     case LASTB_r_p_z:
5855       mnemonic = "lastb";
5856       break;
5857     default:
5858       break;
5859   }
5860   Format(instr, mnemonic, form);
5861 }
5862 
5863 void Disassembler::VisitSVEExtractElementToSIMDFPScalarRegister(
5864     const Instruction *instr) {
5865   const char *mnemonic = "unimplemented";
5866   const char *form = "'t'u0400, 'Pgl, 'Zn.'t";
5867 
5868   switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
5869     case LASTA_v_p_z:
5870       mnemonic = "lasta";
5871       break;
5872     case LASTB_v_p_z:
5873       mnemonic = "lastb";
5874       break;
5875     default:
5876       break;
5877   }
5878   Format(instr, mnemonic, form);
5879 }
5880 
5881 void Disassembler::VisitSVEFFRInitialise(const Instruction *instr) {
5882   const char *mnemonic = "unimplemented";
5883   const char *form = "(SVEFFRInitialise)";
5884 
5885   switch (instr->Mask(SVEFFRInitialiseMask)) {
5886     case SETFFR_f:
5887       mnemonic = "setffr";
5888       form = " ";
5889       break;
5890     default:
5891       break;
5892   }
5893   Format(instr, mnemonic, form);
5894 }
5895 
5896 void Disassembler::VisitSVEFFRWriteFromPredicate(const Instruction *instr) {
5897   const char *mnemonic = "unimplemented";
5898   const char *form = "(SVEFFRWriteFromPredicate)";
5899 
5900   switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
5901     case WRFFR_f_p:
5902       mnemonic = "wrffr";
5903       form = "'Pn.b";
5904       break;
5905     default:
5906       break;
5907   }
5908   Format(instr, mnemonic, form);
5909 }
5910 
5911 void Disassembler::VisitSVEFPArithmeticWithImm_Predicated(
5912     const Instruction *instr) {
5913   const char *mnemonic = "unimplemented";
5914   const char *form00 = "'Zd.'t, 'Pgl/m, 'Zd.'t, #0.0";
5915   const char *form05 = "'Zd.'t, 'Pgl/m, 'Zd.'t, #0.5";
5916   const char *form10 = "'Zd.'t, 'Pgl/m, 'Zd.'t, #1.0";
5917   const char *form20 = "'Zd.'t, 'Pgl/m, 'Zd.'t, #2.0";
5918   int i1 = instr->ExtractBit(5);
5919   const char *form = i1 ? form10 : form00;
5920 
5921   if (instr->GetSVEVectorFormat() == kFormatVnB) {
5922     form = "(SVEFPArithmeticWithImm_Predicated)";
5923   } else {
5924     switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
5925       case FADD_z_p_zs:
5926         mnemonic = "fadd";
5927         form = i1 ? form10 : form05;
5928         break;
5929       case FMAXNM_z_p_zs:
5930         mnemonic = "fmaxnm";
5931         break;
5932       case FMAX_z_p_zs:
5933         mnemonic = "fmax";
5934         break;
5935       case FMINNM_z_p_zs:
5936         mnemonic = "fminnm";
5937         break;
5938       case FMIN_z_p_zs:
5939         mnemonic = "fmin";
5940         break;
5941       case FMUL_z_p_zs:
5942         mnemonic = "fmul";
5943         form = i1 ? form20 : form05;
5944         break;
5945       case FSUBR_z_p_zs:
5946         mnemonic = "fsubr";
5947         form = i1 ? form10 : form05;
5948         break;
5949       case FSUB_z_p_zs:
5950         mnemonic = "fsub";
5951         form = i1 ? form10 : form05;
5952         break;
5953       default:
5954         form = "(SVEFPArithmeticWithImm_Predicated)";
5955         break;
5956     }
5957   }
5958   Format(instr, mnemonic, form);
5959 }
5960 
5961 void Disassembler::VisitSVEFPArithmetic_Predicated(const Instruction *instr) {
5962   const char *mnemonic = "unimplemented";
5963   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
5964 
5965   if (instr->GetSVEVectorFormat() == kFormatVnB) {
5966     form = "(SVEFPArithmetic_Predicated)";
5967   } else {
5968     switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {
5969       case FABD_z_p_zz:
5970         mnemonic = "fabd";
5971         break;
5972       case FADD_z_p_zz:
5973         mnemonic = "fadd";
5974         break;
5975       case FDIVR_z_p_zz:
5976         mnemonic = "fdivr";
5977         break;
5978       case FDIV_z_p_zz:
5979         mnemonic = "fdiv";
5980         break;
5981       case FMAXNM_z_p_zz:
5982         mnemonic = "fmaxnm";
5983         break;
5984       case FMAX_z_p_zz:
5985         mnemonic = "fmax";
5986         break;
5987       case FMINNM_z_p_zz:
5988         mnemonic = "fminnm";
5989         break;
5990       case FMIN_z_p_zz:
5991         mnemonic = "fmin";
5992         break;
5993       case FMULX_z_p_zz:
5994         mnemonic = "fmulx";
5995         break;
5996       case FMUL_z_p_zz:
5997         mnemonic = "fmul";
5998         break;
5999       case FSCALE_z_p_zz:
6000         mnemonic = "fscale";
6001         break;
6002       case FSUBR_z_p_zz:
6003         mnemonic = "fsubr";
6004         break;
6005       case FSUB_z_p_zz:
6006         mnemonic = "fsub";
6007         break;
6008       default:
6009         break;
6010     }
6011   }
6012   Format(instr, mnemonic, form);
6013 }
6014 
6015 void Disassembler::VisitSVEFPConvertPrecision(const Instruction *instr) {
6016   const char *mnemonic = "unimplemented";
6017   const char *form = "(SVEFPConvertPrecision)";
6018 
6019   switch (instr->Mask(SVEFPConvertPrecisionMask)) {
6020     case FCVT_z_p_z_d2h:
6021       mnemonic = "fcvt";
6022       form = "'Zd.h, 'Pgl/m, 'Zn.d";
6023       break;
6024     case FCVT_z_p_z_d2s:
6025       mnemonic = "fcvt";
6026       form = "'Zd.s, 'Pgl/m, 'Zn.d";
6027       break;
6028     case FCVT_z_p_z_h2d:
6029       mnemonic = "fcvt";
6030       form = "'Zd.d, 'Pgl/m, 'Zn.h";
6031       break;
6032     case FCVT_z_p_z_h2s:
6033       mnemonic = "fcvt";
6034       form = "'Zd.s, 'Pgl/m, 'Zn.h";
6035       break;
6036     case FCVT_z_p_z_s2d:
6037       mnemonic = "fcvt";
6038       form = "'Zd.d, 'Pgl/m, 'Zn.s";
6039       break;
6040     case FCVT_z_p_z_s2h:
6041       mnemonic = "fcvt";
6042       form = "'Zd.h, 'Pgl/m, 'Zn.s";
6043       break;
6044     default:
6045       break;
6046   }
6047   Format(instr, mnemonic, form);
6048 }
6049 
6050 void Disassembler::VisitSVEFPConvertToInt(const Instruction *instr) {
6051   const char *mnemonic = "unimplemented";
6052   const char *form = "(SVEFPConvertToInt)";
6053 
6054   switch (instr->Mask(SVEFPConvertToIntMask)) {
6055     case FCVTZS_z_p_z_d2w:
6056       mnemonic = "fcvtzs";
6057       form = "'Zd.s, 'Pgl/m, 'Zn.d";
6058       break;
6059     case FCVTZS_z_p_z_d2x:
6060       mnemonic = "fcvtzs";
6061       form = "'Zd.d, 'Pgl/m, 'Zn.d";
6062       break;
6063     case FCVTZS_z_p_z_fp162h:
6064       mnemonic = "fcvtzs";
6065       form = "'Zd.h, 'Pgl/m, 'Zn.h";
6066       break;
6067     case FCVTZS_z_p_z_fp162w:
6068       mnemonic = "fcvtzs";
6069       form = "'Zd.s, 'Pgl/m, 'Zn.h";
6070       break;
6071     case FCVTZS_z_p_z_fp162x:
6072       mnemonic = "fcvtzs";
6073       form = "'Zd.d, 'Pgl/m, 'Zn.h";
6074       break;
6075     case FCVTZS_z_p_z_s2w:
6076       mnemonic = "fcvtzs";
6077       form = "'Zd.s, 'Pgl/m, 'Zn.s";
6078       break;
6079     case FCVTZS_z_p_z_s2x:
6080       mnemonic = "fcvtzs";
6081       form = "'Zd.d, 'Pgl/m, 'Zn.s";
6082       break;
6083     case FCVTZU_z_p_z_d2w:
6084       mnemonic = "fcvtzu";
6085       form = "'Zd.s, 'Pgl/m, 'Zn.d";
6086       break;
6087     case FCVTZU_z_p_z_d2x:
6088       mnemonic = "fcvtzu";
6089       form = "'Zd.d, 'Pgl/m, 'Zn.d";
6090       break;
6091     case FCVTZU_z_p_z_fp162h:
6092       mnemonic = "fcvtzu";
6093       form = "'Zd.h, 'Pgl/m, 'Zn.h";
6094       break;
6095     case FCVTZU_z_p_z_fp162w:
6096       mnemonic = "fcvtzu";
6097       form = "'Zd.s, 'Pgl/m, 'Zn.h";
6098       break;
6099     case FCVTZU_z_p_z_fp162x:
6100       mnemonic = "fcvtzu";
6101       form = "'Zd.d, 'Pgl/m, 'Zn.h";
6102       break;
6103     case FCVTZU_z_p_z_s2w:
6104       mnemonic = "fcvtzu";
6105       form = "'Zd.s, 'Pgl/m, 'Zn.s";
6106       break;
6107     case FCVTZU_z_p_z_s2x:
6108       mnemonic = "fcvtzu";
6109       form = "'Zd.d, 'Pgl/m, 'Zn.s";
6110       break;
6111     default:
6112       break;
6113   }
6114   Format(instr, mnemonic, form);
6115 }
6116 
6117 void Disassembler::VisitSVEFPExponentialAccelerator(const Instruction *instr) {
6118   const char *mnemonic = "unimplemented";
6119   const char *form = "(SVEFPExponentialAccelerator)";
6120 
6121   unsigned size = instr->GetSVESize();
6122   switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
6123     case FEXPA_z_z:
6124       if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) ||
6125           (size == kDRegSizeInBytesLog2)) {
6126         mnemonic = "fexpa";
6127         form = "'Zd.'t, 'Zn.'t";
6128       }
6129       break;
6130     default:
6131       break;
6132   }
6133   Format(instr, mnemonic, form);
6134 }
6135 
6136 void Disassembler::VisitSVEFPRoundToIntegralValue(const Instruction *instr) {
6137   const char *mnemonic = "unimplemented";
6138   const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t";
6139 
6140   if (instr->GetSVEVectorFormat() == kFormatVnB) {
6141     form = "(SVEFPRoundToIntegralValue)";
6142   } else {
6143     switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
6144       case FRINTA_z_p_z:
6145         mnemonic = "frinta";
6146         break;
6147       case FRINTI_z_p_z:
6148         mnemonic = "frinti";
6149         break;
6150       case FRINTM_z_p_z:
6151         mnemonic = "frintm";
6152         break;
6153       case FRINTN_z_p_z:
6154         mnemonic = "frintn";
6155         break;
6156       case FRINTP_z_p_z:
6157         mnemonic = "frintp";
6158         break;
6159       case FRINTX_z_p_z:
6160         mnemonic = "frintx";
6161         break;
6162       case FRINTZ_z_p_z:
6163         mnemonic = "frintz";
6164         break;
6165       default:
6166         break;
6167     }
6168   }
6169   Format(instr, mnemonic, form);
6170 }
6171 
6172 void Disassembler::VisitSVEFPTrigMulAddCoefficient(const Instruction *instr) {
6173   const char *mnemonic = "unimplemented";
6174   const char *form = "(SVEFPTrigMulAddCoefficient)";
6175 
6176   unsigned size = instr->GetSVESize();
6177   switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {
6178     case FTMAD_z_zzi:
6179       if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) ||
6180           (size == kDRegSizeInBytesLog2)) {
6181         mnemonic = "ftmad";
6182         form = "'Zd.'t, 'Zd.'t, 'Zn.'t, #'u1816";
6183       }
6184       break;
6185     default:
6186       break;
6187   }
6188   Format(instr, mnemonic, form);
6189 }
6190 
6191 void Disassembler::VisitSVEFPTrigSelectCoefficient(const Instruction *instr) {
6192   const char *mnemonic = "unimplemented";
6193   const char *form = "(SVEFPTrigSelectCoefficient)";
6194 
6195   unsigned size = instr->GetSVESize();
6196   switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
6197     case FTSSEL_z_zz:
6198       if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) ||
6199           (size == kDRegSizeInBytesLog2)) {
6200         mnemonic = "ftssel";
6201         form = "'Zd.'t, 'Zn.'t, 'Zm.'t";
6202       }
6203       break;
6204     default:
6205       break;
6206   }
6207   Format(instr, mnemonic, form);
6208 }
6209 
6210 void Disassembler::VisitSVEFPUnaryOp(const Instruction *instr) {
6211   const char *mnemonic = "unimplemented";
6212   const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t";
6213 
6214   if (instr->GetSVESize() == kBRegSizeInBytesLog2) {
6215     form = "(SVEFPUnaryOp)";
6216   } else {
6217     switch (instr->Mask(SVEFPUnaryOpMask)) {
6218       case FRECPX_z_p_z:
6219         mnemonic = "frecpx";
6220         break;
6221       case FSQRT_z_p_z:
6222         mnemonic = "fsqrt";
6223         break;
6224       default:
6225         form = "(SVEFPUnaryOp)";
6226         break;
6227     }
6228   }
6229   Format(instr, mnemonic, form);
6230 }
6231 
6232 static const char *IncDecFormHelper(const Instruction *instr,
6233                                     const char *reg_pat_mul_form,
6234                                     const char *reg_pat_form,
6235                                     const char *reg_form) {
6236   if (instr->ExtractBits(19, 16) == 0) {
6237     if (instr->ExtractBits(9, 5) == SVE_ALL) {
6238       // Use the register only form if the multiplier is one (encoded as zero)
6239       // and the pattern is SVE_ALL.
6240       return reg_form;
6241     }
6242     // Use the register and pattern form if the multiplier is one.
6243     return reg_pat_form;
6244   }
6245   return reg_pat_mul_form;
6246 }
6247 
6248 void Disassembler::VisitSVEIncDecRegisterByElementCount(
6249     const Instruction *instr) {
6250   const char *mnemonic = "unimplemented";
6251   const char *form =
6252       IncDecFormHelper(instr, "'Xd, 'Ipc, mul #'u1916+1", "'Xd, 'Ipc", "'Xd");
6253 
6254   switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {
6255     case DECB_r_rs:
6256       mnemonic = "decb";
6257       break;
6258     case DECD_r_rs:
6259       mnemonic = "decd";
6260       break;
6261     case DECH_r_rs:
6262       mnemonic = "dech";
6263       break;
6264     case DECW_r_rs:
6265       mnemonic = "decw";
6266       break;
6267     case INCB_r_rs:
6268       mnemonic = "incb";
6269       break;
6270     case INCD_r_rs:
6271       mnemonic = "incd";
6272       break;
6273     case INCH_r_rs:
6274       mnemonic = "inch";
6275       break;
6276     case INCW_r_rs:
6277       mnemonic = "incw";
6278       break;
6279     default:
6280       form = "(SVEIncDecRegisterByElementCount)";
6281       break;
6282   }
6283   Format(instr, mnemonic, form);
6284 }
6285 
6286 void Disassembler::VisitSVEIncDecVectorByElementCount(
6287     const Instruction *instr) {
6288   const char *mnemonic = "unimplemented";
6289   const char *form = IncDecFormHelper(instr,
6290                                       "'Zd.'t, 'Ipc, mul #'u1916+1",
6291                                       "'Zd.'t, 'Ipc",
6292                                       "'Zd.'t");
6293 
6294   switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {
6295     case DECD_z_zs:
6296       mnemonic = "decd";
6297       break;
6298     case DECH_z_zs:
6299       mnemonic = "dech";
6300       break;
6301     case DECW_z_zs:
6302       mnemonic = "decw";
6303       break;
6304     case INCD_z_zs:
6305       mnemonic = "incd";
6306       break;
6307     case INCH_z_zs:
6308       mnemonic = "inch";
6309       break;
6310     case INCW_z_zs:
6311       mnemonic = "incw";
6312       break;
6313     default:
6314       form = "(SVEIncDecVectorByElementCount)";
6315       break;
6316   }
6317   Format(instr, mnemonic, form);
6318 }
6319 
6320 void Disassembler::VisitSVEInsertGeneralRegister(const Instruction *instr) {
6321   const char *mnemonic = "unimplemented";
6322   const char *form = "(SVEInsertGeneralRegister)";
6323 
6324   switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
6325     case INSR_z_r:
6326       mnemonic = "insr";
6327       if (instr->GetSVESize() == kDRegSizeInBytesLog2) {
6328         form = "'Zd.'t, 'Xn";
6329       } else {
6330         form = "'Zd.'t, 'Wn";
6331       }
6332       break;
6333     default:
6334       break;
6335   }
6336   Format(instr, mnemonic, form);
6337 }
6338 
6339 void Disassembler::VisitSVEInsertSIMDFPScalarRegister(
6340     const Instruction *instr) {
6341   const char *mnemonic = "unimplemented";
6342   const char *form = "(SVEInsertSIMDFPScalarRegister)";
6343 
6344   switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
6345     case INSR_z_v:
6346       mnemonic = "insr";
6347       form = "'Zd.'t, 'Vnv";
6348       break;
6349     default:
6350       break;
6351   }
6352   Format(instr, mnemonic, form);
6353 }
6354 
6355 void Disassembler::VisitSVEIntAddSubtractImm_Unpredicated(
6356     const Instruction *instr) {
6357   const char *mnemonic = "unimplemented";
6358   const char *form = (instr->ExtractBit(13) == 0)
6359                          ? "'Zd.'t, 'Zd.'t, #'u1205"
6360                          : "'Zd.'t, 'Zd.'t, #'u1205, lsl #8";
6361 
6362   switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
6363     case ADD_z_zi:
6364       mnemonic = "add";
6365       break;
6366     case SQADD_z_zi:
6367       mnemonic = "sqadd";
6368       break;
6369     case SQSUB_z_zi:
6370       mnemonic = "sqsub";
6371       break;
6372     case SUBR_z_zi:
6373       mnemonic = "subr";
6374       break;
6375     case SUB_z_zi:
6376       mnemonic = "sub";
6377       break;
6378     case UQADD_z_zi:
6379       mnemonic = "uqadd";
6380       break;
6381     case UQSUB_z_zi:
6382       mnemonic = "uqsub";
6383       break;
6384     default:
6385       form = "(SVEIntAddSubtractImm_Unpredicated)";
6386       break;
6387   }
6388   Format(instr, mnemonic, form);
6389 }
6390 
6391 void Disassembler::VisitSVEIntAddSubtractVectors_Predicated(
6392     const Instruction *instr) {
6393   const char *mnemonic = "unimplemented";
6394   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
6395 
6396   switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
6397     case ADD_z_p_zz:
6398       mnemonic = "add";
6399       break;
6400     case SUBR_z_p_zz:
6401       mnemonic = "subr";
6402       break;
6403     case SUB_z_p_zz:
6404       mnemonic = "sub";
6405       break;
6406     default:
6407       break;
6408   }
6409   Format(instr, mnemonic, form);
6410 }
6411 
6412 void Disassembler::VisitSVEIntCompareScalarCountAndLimit(
6413     const Instruction *instr) {
6414   const char *form =
6415       (instr->ExtractBit(12) == 0) ? "'Pd.'t, 'Wn, 'Wm" : "'Pd.'t, 'Xn, 'Xm";
6416   Format(instr, mnemonic_.c_str(), form);
6417 }
6418 
6419 void Disassembler::VisitSVEIntConvertToFP(const Instruction *instr) {
6420   const char *mnemonic = "unimplemented";
6421   const char *form = "(SVEIntConvertToFP)";
6422 
6423   switch (instr->Mask(SVEIntConvertToFPMask)) {
6424     case SCVTF_z_p_z_h2fp16:
6425       mnemonic = "scvtf";
6426       form = "'Zd.h, 'Pgl/m, 'Zn.h";
6427       break;
6428     case SCVTF_z_p_z_w2d:
6429       mnemonic = "scvtf";
6430       form = "'Zd.d, 'Pgl/m, 'Zn.s";
6431       break;
6432     case SCVTF_z_p_z_w2fp16:
6433       mnemonic = "scvtf";
6434       form = "'Zd.h, 'Pgl/m, 'Zn.s";
6435       break;
6436     case SCVTF_z_p_z_w2s:
6437       mnemonic = "scvtf";
6438       form = "'Zd.s, 'Pgl/m, 'Zn.s";
6439       break;
6440     case SCVTF_z_p_z_x2d:
6441       mnemonic = "scvtf";
6442       form = "'Zd.d, 'Pgl/m, 'Zn.d";
6443       break;
6444     case SCVTF_z_p_z_x2fp16:
6445       mnemonic = "scvtf";
6446       form = "'Zd.h, 'Pgl/m, 'Zn.d";
6447       break;
6448     case SCVTF_z_p_z_x2s:
6449       mnemonic = "scvtf";
6450       form = "'Zd.s, 'Pgl/m, 'Zn.d";
6451       break;
6452     case UCVTF_z_p_z_h2fp16:
6453       mnemonic = "ucvtf";
6454       form = "'Zd.h, 'Pgl/m, 'Zn.h";
6455       break;
6456     case UCVTF_z_p_z_w2d:
6457       mnemonic = "ucvtf";
6458       form = "'Zd.d, 'Pgl/m, 'Zn.s";
6459       break;
6460     case UCVTF_z_p_z_w2fp16:
6461       mnemonic = "ucvtf";
6462       form = "'Zd.h, 'Pgl/m, 'Zn.s";
6463       break;
6464     case UCVTF_z_p_z_w2s:
6465       mnemonic = "ucvtf";
6466       form = "'Zd.s, 'Pgl/m, 'Zn.s";
6467       break;
6468     case UCVTF_z_p_z_x2d:
6469       mnemonic = "ucvtf";
6470       form = "'Zd.d, 'Pgl/m, 'Zn.d";
6471       break;
6472     case UCVTF_z_p_z_x2fp16:
6473       mnemonic = "ucvtf";
6474       form = "'Zd.h, 'Pgl/m, 'Zn.d";
6475       break;
6476     case UCVTF_z_p_z_x2s:
6477       mnemonic = "ucvtf";
6478       form = "'Zd.s, 'Pgl/m, 'Zn.d";
6479       break;
6480     default:
6481       break;
6482   }
6483   Format(instr, mnemonic, form);
6484 }
6485 
6486 void Disassembler::VisitSVEIntDivideVectors_Predicated(
6487     const Instruction *instr) {
6488   const char *mnemonic = "unimplemented";
6489   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
6490 
6491   switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
6492     case SDIVR_z_p_zz:
6493       mnemonic = "sdivr";
6494       break;
6495     case SDIV_z_p_zz:
6496       mnemonic = "sdiv";
6497       break;
6498     case UDIVR_z_p_zz:
6499       mnemonic = "udivr";
6500       break;
6501     case UDIV_z_p_zz:
6502       mnemonic = "udiv";
6503       break;
6504     default:
6505       break;
6506   }
6507 
6508   switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
6509     case SDIVR_z_p_zz:
6510     case SDIV_z_p_zz:
6511     case UDIVR_z_p_zz:
6512     case UDIV_z_p_zz:
6513       switch (instr->GetSVESize()) {
6514         case kBRegSizeInBytesLog2:
6515         case kHRegSizeInBytesLog2:
6516           mnemonic = "unimplemented";
6517           form = "(SVEIntBinaryArithmeticPredicated)";
6518           break;
6519         case kSRegSizeInBytesLog2:
6520         case kDRegSizeInBytesLog2:
6521           // The default form works for these instructions.
6522           break;
6523         default:
6524           // GetSVESize() should never return other values.
6525           VIXL_UNREACHABLE();
6526           break;
6527       }
6528   }
6529 
6530   Format(instr, mnemonic, form);
6531 }
6532 
6533 void Disassembler::VisitSVEIntMinMaxDifference_Predicated(
6534     const Instruction *instr) {
6535   const char *mnemonic = "unimplemented";
6536   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
6537 
6538   switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
6539     case SABD_z_p_zz:
6540       mnemonic = "sabd";
6541       break;
6542     case SMAX_z_p_zz:
6543       mnemonic = "smax";
6544       break;
6545     case SMIN_z_p_zz:
6546       mnemonic = "smin";
6547       break;
6548     case UABD_z_p_zz:
6549       mnemonic = "uabd";
6550       break;
6551     case UMAX_z_p_zz:
6552       mnemonic = "umax";
6553       break;
6554     case UMIN_z_p_zz:
6555       mnemonic = "umin";
6556       break;
6557     default:
6558       break;
6559   }
6560   Format(instr, mnemonic, form);
6561 }
6562 
6563 void Disassembler::VisitSVEIntMinMaxImm_Unpredicated(const Instruction *instr) {
6564   const char *mnemonic = "unimplemented";
6565   const char *form = "'Zd.'t, 'Zd.'t, #'u1205";
6566 
6567   switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
6568     case SMAX_z_zi:
6569       mnemonic = "smax";
6570       form = "'Zd.'t, 'Zd.'t, #'s1205";
6571       break;
6572     case SMIN_z_zi:
6573       mnemonic = "smin";
6574       form = "'Zd.'t, 'Zd.'t, #'s1205";
6575       break;
6576     case UMAX_z_zi:
6577       mnemonic = "umax";
6578       break;
6579     case UMIN_z_zi:
6580       mnemonic = "umin";
6581       break;
6582     default:
6583       break;
6584   }
6585   Format(instr, mnemonic, form);
6586 }
6587 
6588 void Disassembler::VisitSVEIntMulImm_Unpredicated(const Instruction *instr) {
6589   const char *mnemonic = "unimplemented";
6590   const char *form = "(SVEIntMulImm_Unpredicated)";
6591 
6592   switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
6593     case MUL_z_zi:
6594       mnemonic = "mul";
6595       form = "'Zd.'t, 'Zd.'t, #'s1205";
6596       break;
6597     default:
6598       break;
6599   }
6600   Format(instr, mnemonic, form);
6601 }
6602 
6603 void Disassembler::VisitSVEIntMulVectors_Predicated(const Instruction *instr) {
6604   const char *mnemonic = "unimplemented";
6605   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
6606 
6607   switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
6608     case MUL_z_p_zz:
6609       mnemonic = "mul";
6610       break;
6611     case SMULH_z_p_zz:
6612       mnemonic = "smulh";
6613       break;
6614     case UMULH_z_p_zz:
6615       mnemonic = "umulh";
6616       break;
6617     default:
6618       break;
6619   }
6620   Format(instr, mnemonic, form);
6621 }
6622 
6623 void Disassembler::VisitSVELoadAndBroadcastElement(const Instruction *instr) {
6624   const char *mnemonic = "unimplemented";
6625   const char *form = "(SVELoadAndBroadcastElement)";
6626   const char *suffix_b = ", #'u2116]";
6627   const char *suffix_h = ", #'u2116*2]";
6628   const char *suffix_w = ", #'u2116*4]";
6629   const char *suffix_d = ", #'u2116*8]";
6630   const char *suffix = NULL;
6631 
6632   switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
6633     case LD1RB_z_p_bi_u16:
6634       mnemonic = "ld1rb";
6635       form = "{'Zt.h}, 'Pgl/z, ['Xns";
6636       suffix = suffix_b;
6637       break;
6638     case LD1RB_z_p_bi_u32:
6639       mnemonic = "ld1rb";
6640       form = "{'Zt.s}, 'Pgl/z, ['Xns";
6641       suffix = suffix_b;
6642       break;
6643     case LD1RB_z_p_bi_u64:
6644       mnemonic = "ld1rb";
6645       form = "{'Zt.d}, 'Pgl/z, ['Xns";
6646       suffix = suffix_b;
6647       break;
6648     case LD1RB_z_p_bi_u8:
6649       mnemonic = "ld1rb";
6650       form = "{'Zt.b}, 'Pgl/z, ['Xns";
6651       suffix = suffix_b;
6652       break;
6653     case LD1RD_z_p_bi_u64:
6654       mnemonic = "ld1rd";
6655       form = "{'Zt.d}, 'Pgl/z, ['Xns";
6656       suffix = suffix_d;
6657       break;
6658     case LD1RH_z_p_bi_u16:
6659       mnemonic = "ld1rh";
6660       form = "{'Zt.h}, 'Pgl/z, ['Xns";
6661       suffix = suffix_h;
6662       break;
6663     case LD1RH_z_p_bi_u32:
6664       mnemonic = "ld1rh";
6665       form = "{'Zt.s}, 'Pgl/z, ['Xns";
6666       suffix = suffix_h;
6667       break;
6668     case LD1RH_z_p_bi_u64:
6669       mnemonic = "ld1rh";
6670       form = "{'Zt.d}, 'Pgl/z, ['Xns";
6671       suffix = suffix_h;
6672       break;
6673     case LD1RSB_z_p_bi_s16:
6674       mnemonic = "ld1rsb";
6675       form = "{'Zt.h}, 'Pgl/z, ['Xns";
6676       suffix = suffix_b;
6677       break;
6678     case LD1RSB_z_p_bi_s32:
6679       mnemonic = "ld1rsb";
6680       form = "{'Zt.s}, 'Pgl/z, ['Xns";
6681       suffix = suffix_b;
6682       break;
6683     case LD1RSB_z_p_bi_s64:
6684       mnemonic = "ld1rsb";
6685       form = "{'Zt.d}, 'Pgl/z, ['Xns";
6686       suffix = suffix_b;
6687       break;
6688     case LD1RSH_z_p_bi_s32:
6689       mnemonic = "ld1rsh";
6690       form = "{'Zt.s}, 'Pgl/z, ['Xns";
6691       suffix = suffix_h;
6692       break;
6693     case LD1RSH_z_p_bi_s64:
6694       mnemonic = "ld1rsh";
6695       form = "{'Zt.d}, 'Pgl/z, ['Xns";
6696       suffix = suffix_h;
6697       break;
6698     case LD1RSW_z_p_bi_s64:
6699       mnemonic = "ld1rsw";
6700       form = "{'Zt.d}, 'Pgl/z, ['Xns";
6701       suffix = suffix_w;
6702       break;
6703     case LD1RW_z_p_bi_u32:
6704       mnemonic = "ld1rw";
6705       form = "{'Zt.s}, 'Pgl/z, ['Xns";
6706       suffix = suffix_w;
6707       break;
6708     case LD1RW_z_p_bi_u64:
6709       mnemonic = "ld1rw";
6710       form = "{'Zt.d}, 'Pgl/z, ['Xns";
6711       suffix = suffix_w;
6712       break;
6713     default:
6714       break;
6715   }
6716 
6717   // Hide curly brackets if immediate is zero.
6718   if (instr->ExtractBits(21, 16) == 0) {
6719     suffix = "]";
6720   }
6721 
6722   Format(instr, mnemonic, form, suffix);
6723 }
6724 
6725 void Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm(
6726     const Instruction *instr) {
6727   const char *mnemonic = mnemonic_.c_str();
6728   const char *form = "{'Zt.'tmsz}, 'Pgl/z, ['Xns";
6729   const char *suffix = ", #'s1916*16]";
6730 
6731   switch (form_hash_) {
6732     case Hash("ld1rqb_z_p_bi_u8"):
6733     case Hash("ld1rqd_z_p_bi_u64"):
6734     case Hash("ld1rqh_z_p_bi_u16"):
6735     case Hash("ld1rqw_z_p_bi_u32"):
6736       // Nothing to do.
6737       break;
6738     case Hash("ld1rob_z_p_bi_u8"):
6739     case Hash("ld1rod_z_p_bi_u64"):
6740     case Hash("ld1roh_z_p_bi_u16"):
6741     case Hash("ld1row_z_p_bi_u32"):
6742       suffix = ", #'s1916*32]";
6743       break;
6744     default:
6745       VIXL_UNREACHABLE();
6746       break;
6747   }
6748   if (instr->ExtractBits(19, 16) == 0) suffix = "]";
6749 
6750   Format(instr, mnemonic, form, suffix);
6751 }
6752 
6753 void Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar(
6754     const Instruction *instr) {
6755   const char *mnemonic = mnemonic_.c_str();
6756   const char *form = "{'Zt.'tmsz}, 'Pgl/z, ['Xns, ";
6757   const char *suffix = "'Rm, lsl #'u2423]";
6758 
6759   switch (form_hash_) {
6760     case Hash("ld1rqb_z_p_br_contiguous"):
6761     case Hash("ld1rob_z_p_br_contiguous"):
6762       suffix = "'Rm]";
6763       break;
6764     case Hash("ld1rqd_z_p_br_contiguous"):
6765     case Hash("ld1rod_z_p_br_contiguous"):
6766     case Hash("ld1rqh_z_p_br_contiguous"):
6767     case Hash("ld1roh_z_p_br_contiguous"):
6768     case Hash("ld1rqw_z_p_br_contiguous"):
6769     case Hash("ld1row_z_p_br_contiguous"):
6770       // Nothing to do.
6771       break;
6772     default:
6773       VIXL_UNREACHABLE();
6774       break;
6775   }
6776   Format(instr, mnemonic, form, suffix);
6777 }
6778 
6779 void Disassembler::VisitSVELoadMultipleStructures_ScalarPlusImm(
6780     const Instruction *instr) {
6781   const char *mnemonic = "unimplemented";
6782   const char *form = "(SVELoadMultipleStructures_ScalarPlusImm)";
6783 
6784   const char *form_2 = "{'Zt.'tmsz, 'Zt2.'tmsz}, 'Pgl/z, ['Xns'ISveSvl]";
6785   const char *form_3 =
6786       "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}, 'Pgl/z, ['Xns'ISveSvl]";
6787   const char *form_4 =
6788       "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}, "
6789       "'Pgl/z, ['Xns'ISveSvl]";
6790 
6791   switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
6792     case LD2B_z_p_bi_contiguous:
6793       mnemonic = "ld2b";
6794       form = form_2;
6795       break;
6796     case LD2D_z_p_bi_contiguous:
6797       mnemonic = "ld2d";
6798       form = form_2;
6799       break;
6800     case LD2H_z_p_bi_contiguous:
6801       mnemonic = "ld2h";
6802       form = form_2;
6803       break;
6804     case LD2W_z_p_bi_contiguous:
6805       mnemonic = "ld2w";
6806       form = form_2;
6807       break;
6808     case LD3B_z_p_bi_contiguous:
6809       mnemonic = "ld3b";
6810       form = form_3;
6811       break;
6812     case LD3D_z_p_bi_contiguous:
6813       mnemonic = "ld3d";
6814       form = form_3;
6815       break;
6816     case LD3H_z_p_bi_contiguous:
6817       mnemonic = "ld3h";
6818       form = form_3;
6819       break;
6820     case LD3W_z_p_bi_contiguous:
6821       mnemonic = "ld3w";
6822       form = form_3;
6823       break;
6824     case LD4B_z_p_bi_contiguous:
6825       mnemonic = "ld4b";
6826       form = form_4;
6827       break;
6828     case LD4D_z_p_bi_contiguous:
6829       mnemonic = "ld4d";
6830       form = form_4;
6831       break;
6832     case LD4H_z_p_bi_contiguous:
6833       mnemonic = "ld4h";
6834       form = form_4;
6835       break;
6836     case LD4W_z_p_bi_contiguous:
6837       mnemonic = "ld4w";
6838       form = form_4;
6839       break;
6840     default:
6841       break;
6842   }
6843   Format(instr, mnemonic, form);
6844 }
6845 
6846 void Disassembler::VisitSVELoadMultipleStructures_ScalarPlusScalar(
6847     const Instruction *instr) {
6848   const char *mnemonic = "unimplemented";
6849   const char *form = "(SVELoadMultipleStructures_ScalarPlusScalar)";
6850 
6851   const char *form_2 = "{'Zt.'tmsz, 'Zt2.'tmsz}, 'Pgl/z, ['Xns, 'Xm'NSveS]";
6852   const char *form_3 =
6853       "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}, 'Pgl/z, ['Xns, 'Xm'NSveS]";
6854   const char *form_4 =
6855       "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}, "
6856       "'Pgl/z, ['Xns, 'Xm'NSveS]";
6857 
6858   switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
6859     case LD2B_z_p_br_contiguous:
6860       mnemonic = "ld2b";
6861       form = form_2;
6862       break;
6863     case LD2D_z_p_br_contiguous:
6864       mnemonic = "ld2d";
6865       form = form_2;
6866       break;
6867     case LD2H_z_p_br_contiguous:
6868       mnemonic = "ld2h";
6869       form = form_2;
6870       break;
6871     case LD2W_z_p_br_contiguous:
6872       mnemonic = "ld2w";
6873       form = form_2;
6874       break;
6875     case LD3B_z_p_br_contiguous:
6876       mnemonic = "ld3b";
6877       form = form_3;
6878       break;
6879     case LD3D_z_p_br_contiguous:
6880       mnemonic = "ld3d";
6881       form = form_3;
6882       break;
6883     case LD3H_z_p_br_contiguous:
6884       mnemonic = "ld3h";
6885       form = form_3;
6886       break;
6887     case LD3W_z_p_br_contiguous:
6888       mnemonic = "ld3w";
6889       form = form_3;
6890       break;
6891     case LD4B_z_p_br_contiguous:
6892       mnemonic = "ld4b";
6893       form = form_4;
6894       break;
6895     case LD4D_z_p_br_contiguous:
6896       mnemonic = "ld4d";
6897       form = form_4;
6898       break;
6899     case LD4H_z_p_br_contiguous:
6900       mnemonic = "ld4h";
6901       form = form_4;
6902       break;
6903     case LD4W_z_p_br_contiguous:
6904       mnemonic = "ld4w";
6905       form = form_4;
6906       break;
6907     default:
6908       break;
6909   }
6910   Format(instr, mnemonic, form);
6911 }
6912 
6913 void Disassembler::VisitSVELoadPredicateRegister(const Instruction *instr) {
6914   const char *mnemonic = "unimplemented";
6915   const char *form = "(SVELoadPredicateRegister)";
6916 
6917   switch (instr->Mask(SVELoadPredicateRegisterMask)) {
6918     case LDR_p_bi:
6919       mnemonic = "ldr";
6920       if (instr->Mask(0x003f1c00) == 0) {
6921         form = "'Pd, ['Xns]";
6922       } else {
6923         form = "'Pd, ['Xns, #'s2116:1210, mul vl]";
6924       }
6925       break;
6926     default:
6927       break;
6928   }
6929   Format(instr, mnemonic, form);
6930 }
6931 
6932 void Disassembler::VisitSVELoadVectorRegister(const Instruction *instr) {
6933   const char *mnemonic = "unimplemented";
6934   const char *form = "(SVELoadVectorRegister)";
6935 
6936   switch (instr->Mask(SVELoadVectorRegisterMask)) {
6937     case LDR_z_bi:
6938       mnemonic = "ldr";
6939       if (instr->Mask(0x003f1c00) == 0) {
6940         form = "'Zd, ['Xns]";
6941       } else {
6942         form = "'Zt, ['Xns, #'s2116:1210, mul vl]";
6943       }
6944       break;
6945     default:
6946       break;
6947   }
6948   Format(instr, mnemonic, form);
6949 }
6950 
6951 void Disassembler::VisitSVEPartitionBreakCondition(const Instruction *instr) {
6952   const char *mnemonic = "unimplemented";
6953   const char *form = "'Pd.b, p'u1310/'?04:mz, 'Pn.b";
6954 
6955   switch (instr->Mask(SVEPartitionBreakConditionMask)) {
6956     case BRKAS_p_p_p_z:
6957       mnemonic = "brkas";
6958       break;
6959     case BRKA_p_p_p:
6960       mnemonic = "brka";
6961       break;
6962     case BRKBS_p_p_p_z:
6963       mnemonic = "brkbs";
6964       break;
6965     case BRKB_p_p_p:
6966       mnemonic = "brkb";
6967       break;
6968     default:
6969       form = "(SVEPartitionBreakCondition)";
6970       break;
6971   }
6972   Format(instr, mnemonic, form);
6973 }
6974 
6975 void Disassembler::VisitSVEPermutePredicateElements(const Instruction *instr) {
6976   const char *mnemonic = "unimplemented";
6977   const char *form = "'Pd.'t, 'Pn.'t, 'Pm.'t";
6978 
6979   switch (instr->Mask(SVEPermutePredicateElementsMask)) {
6980     case TRN1_p_pp:
6981       mnemonic = "trn1";
6982       break;
6983     case TRN2_p_pp:
6984       mnemonic = "trn2";
6985       break;
6986     case UZP1_p_pp:
6987       mnemonic = "uzp1";
6988       break;
6989     case UZP2_p_pp:
6990       mnemonic = "uzp2";
6991       break;
6992     case ZIP1_p_pp:
6993       mnemonic = "zip1";
6994       break;
6995     case ZIP2_p_pp:
6996       mnemonic = "zip2";
6997       break;
6998     default:
6999       break;
7000   }
7001   Format(instr, mnemonic, form);
7002 }
7003 
7004 void Disassembler::VisitSVEPredicateFirstActive(const Instruction *instr) {
7005   const char *mnemonic = "unimplemented";
7006   const char *form = "(SVEPredicateFirstActive)";
7007 
7008   switch (instr->Mask(SVEPredicateFirstActiveMask)) {
7009     case PFIRST_p_p_p:
7010       mnemonic = "pfirst";
7011       form = "'Pd.b, 'Pn, 'Pd.b";
7012       break;
7013     default:
7014       break;
7015   }
7016   Format(instr, mnemonic, form);
7017 }
7018 
7019 void Disassembler::VisitSVEPredicateReadFromFFR_Unpredicated(
7020     const Instruction *instr) {
7021   const char *mnemonic = "unimplemented";
7022   const char *form = "(SVEPredicateReadFromFFR_Unpredicated)";
7023 
7024   switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
7025     case RDFFR_p_f:
7026       mnemonic = "rdffr";
7027       form = "'Pd.b";
7028       break;
7029     default:
7030       break;
7031   }
7032   Format(instr, mnemonic, form);
7033 }
7034 
7035 void Disassembler::VisitSVEPredicateTest(const Instruction *instr) {
7036   const char *mnemonic = "unimplemented";
7037   const char *form = "(SVEPredicateTest)";
7038 
7039   switch (instr->Mask(SVEPredicateTestMask)) {
7040     case PTEST_p_p:
7041       mnemonic = "ptest";
7042       form = "p'u1310, 'Pn.b";
7043       break;
7044     default:
7045       break;
7046   }
7047   Format(instr, mnemonic, form);
7048 }
7049 
7050 void Disassembler::VisitSVEPredicateZero(const Instruction *instr) {
7051   const char *mnemonic = "unimplemented";
7052   const char *form = "(SVEPredicateZero)";
7053 
7054   switch (instr->Mask(SVEPredicateZeroMask)) {
7055     case PFALSE_p:
7056       mnemonic = "pfalse";
7057       form = "'Pd.b";
7058       break;
7059     default:
7060       break;
7061   }
7062   Format(instr, mnemonic, form);
7063 }
7064 
7065 void Disassembler::VisitSVEPropagateBreakToNextPartition(
7066     const Instruction *instr) {
7067   const char *mnemonic = "unimplemented";
7068   const char *form = "'Pd.b, p'u1310/z, 'Pn.b, 'Pd.b";
7069 
7070   switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
7071     case BRKNS_p_p_pp:
7072       mnemonic = "brkns";
7073       break;
7074     case BRKN_p_p_pp:
7075       mnemonic = "brkn";
7076       break;
7077     default:
7078       break;
7079   }
7080   Format(instr, mnemonic, form);
7081 }
7082 
7083 void Disassembler::VisitSVEReversePredicateElements(const Instruction *instr) {
7084   const char *mnemonic = "unimplemented";
7085   const char *form = "(SVEReversePredicateElements)";
7086 
7087   switch (instr->Mask(SVEReversePredicateElementsMask)) {
7088     case REV_p_p:
7089       mnemonic = "rev";
7090       form = "'Pd.'t, 'Pn.'t";
7091       break;
7092     default:
7093       break;
7094   }
7095   Format(instr, mnemonic, form);
7096 }
7097 
7098 void Disassembler::VisitSVEReverseVectorElements(const Instruction *instr) {
7099   const char *mnemonic = "unimplemented";
7100   const char *form = "(SVEReverseVectorElements)";
7101 
7102   switch (instr->Mask(SVEReverseVectorElementsMask)) {
7103     case REV_z_z:
7104       mnemonic = "rev";
7105       form = "'Zd.'t, 'Zn.'t";
7106       break;
7107     default:
7108       break;
7109   }
7110   Format(instr, mnemonic, form);
7111 }
7112 
7113 void Disassembler::VisitSVEReverseWithinElements(const Instruction *instr) {
7114   const char *mnemonic = "unimplemented";
7115   const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t";
7116 
7117   unsigned size = instr->GetSVESize();
7118   switch (instr->Mask(SVEReverseWithinElementsMask)) {
7119     case RBIT_z_p_z:
7120       mnemonic = "rbit";
7121       break;
7122     case REVB_z_z:
7123       if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) ||
7124           (size == kDRegSizeInBytesLog2)) {
7125         mnemonic = "revb";
7126       } else {
7127         form = "(SVEReverseWithinElements)";
7128       }
7129       break;
7130     case REVH_z_z:
7131       if ((size == kSRegSizeInBytesLog2) || (size == kDRegSizeInBytesLog2)) {
7132         mnemonic = "revh";
7133       } else {
7134         form = "(SVEReverseWithinElements)";
7135       }
7136       break;
7137     case REVW_z_z:
7138       if (size == kDRegSizeInBytesLog2) {
7139         mnemonic = "revw";
7140       } else {
7141         form = "(SVEReverseWithinElements)";
7142       }
7143       break;
7144     default:
7145       break;
7146   }
7147   Format(instr, mnemonic, form);
7148 }
7149 
7150 void Disassembler::VisitSVESaturatingIncDecRegisterByElementCount(
7151     const Instruction *instr) {
7152   const char *mnemonic = "unimplemented";
7153   const char *form = IncDecFormHelper(instr,
7154                                       "'R20d, 'Ipc, mul #'u1916+1",
7155                                       "'R20d, 'Ipc",
7156                                       "'R20d");
7157   const char *form_sx = IncDecFormHelper(instr,
7158                                          "'Xd, 'Wd, 'Ipc, mul #'u1916+1",
7159                                          "'Xd, 'Wd, 'Ipc",
7160                                          "'Xd, 'Wd");
7161 
7162   switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {
7163     case SQDECB_r_rs_sx:
7164       mnemonic = "sqdecb";
7165       form = form_sx;
7166       break;
7167     case SQDECD_r_rs_sx:
7168       mnemonic = "sqdecd";
7169       form = form_sx;
7170       break;
7171     case SQDECH_r_rs_sx:
7172       mnemonic = "sqdech";
7173       form = form_sx;
7174       break;
7175     case SQDECW_r_rs_sx:
7176       mnemonic = "sqdecw";
7177       form = form_sx;
7178       break;
7179     case SQINCB_r_rs_sx:
7180       mnemonic = "sqincb";
7181       form = form_sx;
7182       break;
7183     case SQINCD_r_rs_sx:
7184       mnemonic = "sqincd";
7185       form = form_sx;
7186       break;
7187     case SQINCH_r_rs_sx:
7188       mnemonic = "sqinch";
7189       form = form_sx;
7190       break;
7191     case SQINCW_r_rs_sx:
7192       mnemonic = "sqincw";
7193       form = form_sx;
7194       break;
7195     case SQDECB_r_rs_x:
7196       mnemonic = "sqdecb";
7197       break;
7198     case SQDECD_r_rs_x:
7199       mnemonic = "sqdecd";
7200       break;
7201     case SQDECH_r_rs_x:
7202       mnemonic = "sqdech";
7203       break;
7204     case SQDECW_r_rs_x:
7205       mnemonic = "sqdecw";
7206       break;
7207     case SQINCB_r_rs_x:
7208       mnemonic = "sqincb";
7209       break;
7210     case SQINCD_r_rs_x:
7211       mnemonic = "sqincd";
7212       break;
7213     case SQINCH_r_rs_x:
7214       mnemonic = "sqinch";
7215       break;
7216     case SQINCW_r_rs_x:
7217       mnemonic = "sqincw";
7218       break;
7219     case UQDECB_r_rs_uw:
7220     case UQDECB_r_rs_x:
7221       mnemonic = "uqdecb";
7222       break;
7223     case UQDECD_r_rs_uw:
7224     case UQDECD_r_rs_x:
7225       mnemonic = "uqdecd";
7226       break;
7227     case UQDECH_r_rs_uw:
7228     case UQDECH_r_rs_x:
7229       mnemonic = "uqdech";
7230       break;
7231     case UQDECW_r_rs_uw:
7232     case UQDECW_r_rs_x:
7233       mnemonic = "uqdecw";
7234       break;
7235     case UQINCB_r_rs_uw:
7236     case UQINCB_r_rs_x:
7237       mnemonic = "uqincb";
7238       break;
7239     case UQINCD_r_rs_uw:
7240     case UQINCD_r_rs_x:
7241       mnemonic = "uqincd";
7242       break;
7243     case UQINCH_r_rs_uw:
7244     case UQINCH_r_rs_x:
7245       mnemonic = "uqinch";
7246       break;
7247     case UQINCW_r_rs_uw:
7248     case UQINCW_r_rs_x:
7249       mnemonic = "uqincw";
7250       break;
7251     default:
7252       break;
7253   }
7254   Format(instr, mnemonic, form);
7255 }
7256 
7257 void Disassembler::VisitSVESaturatingIncDecVectorByElementCount(
7258     const Instruction *instr) {
7259   const char *mnemonic = "unimplemented";
7260   const char *form = IncDecFormHelper(instr,
7261                                       "'Zd.'t, 'Ipc, mul #'u1916+1",
7262                                       "'Zd.'t, 'Ipc",
7263                                       "'Zd.'t");
7264 
7265   switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {
7266     case SQDECD_z_zs:
7267       mnemonic = "sqdecd";
7268       break;
7269     case SQDECH_z_zs:
7270       mnemonic = "sqdech";
7271       break;
7272     case SQDECW_z_zs:
7273       mnemonic = "sqdecw";
7274       break;
7275     case SQINCD_z_zs:
7276       mnemonic = "sqincd";
7277       break;
7278     case SQINCH_z_zs:
7279       mnemonic = "sqinch";
7280       break;
7281     case SQINCW_z_zs:
7282       mnemonic = "sqincw";
7283       break;
7284     case UQDECD_z_zs:
7285       mnemonic = "uqdecd";
7286       break;
7287     case UQDECH_z_zs:
7288       mnemonic = "uqdech";
7289       break;
7290     case UQDECW_z_zs:
7291       mnemonic = "uqdecw";
7292       break;
7293     case UQINCD_z_zs:
7294       mnemonic = "uqincd";
7295       break;
7296     case UQINCH_z_zs:
7297       mnemonic = "uqinch";
7298       break;
7299     case UQINCW_z_zs:
7300       mnemonic = "uqincw";
7301       break;
7302     default:
7303       form = "(SVEElementCount)";
7304       break;
7305   }
7306   Format(instr, mnemonic, form);
7307 }
7308 
7309 void Disassembler::VisitSVEStoreMultipleStructures_ScalarPlusImm(
7310     const Instruction *instr) {
7311   const char *mnemonic = "unimplemented";
7312   const char *form = "(SVEStoreMultipleStructures_ScalarPlusImm)";
7313 
7314   const char *form_2 = "{'Zt.'tmsz, 'Zt2.'tmsz}, 'Pgl, ['Xns'ISveSvl]";
7315   const char *form_3 =
7316       "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}, 'Pgl, ['Xns'ISveSvl]";
7317   const char *form_4 =
7318       "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}, "
7319       "'Pgl, ['Xns'ISveSvl]";
7320 
7321   switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
7322     case ST2B_z_p_bi_contiguous:
7323       mnemonic = "st2b";
7324       form = form_2;
7325       break;
7326     case ST2H_z_p_bi_contiguous:
7327       mnemonic = "st2h";
7328       form = form_2;
7329       break;
7330     case ST2W_z_p_bi_contiguous:
7331       mnemonic = "st2w";
7332       form = form_2;
7333       break;
7334     case ST2D_z_p_bi_contiguous:
7335       mnemonic = "st2d";
7336       form = form_2;
7337       break;
7338     case ST3B_z_p_bi_contiguous:
7339       mnemonic = "st3b";
7340       form = form_3;
7341       break;
7342     case ST3H_z_p_bi_contiguous:
7343       mnemonic = "st3h";
7344       form = form_3;
7345       break;
7346     case ST3W_z_p_bi_contiguous:
7347       mnemonic = "st3w";
7348       form = form_3;
7349       break;
7350     case ST3D_z_p_bi_contiguous:
7351       mnemonic = "st3d";
7352       form = form_3;
7353       break;
7354     case ST4B_z_p_bi_contiguous:
7355       mnemonic = "st4b";
7356       form = form_4;
7357       break;
7358     case ST4H_z_p_bi_contiguous:
7359       mnemonic = "st4h";
7360       form = form_4;
7361       break;
7362     case ST4W_z_p_bi_contiguous:
7363       mnemonic = "st4w";
7364       form = form_4;
7365       break;
7366     case ST4D_z_p_bi_contiguous:
7367       mnemonic = "st4d";
7368       form = form_4;
7369       break;
7370     default:
7371       break;
7372   }
7373   Format(instr, mnemonic, form);
7374 }
7375 
7376 void Disassembler::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
7377     const Instruction *instr) {
7378   const char *mnemonic = "unimplemented";
7379   const char *form = "(SVEStoreMultipleStructures_ScalarPlusScalar)";
7380 
7381   const char *form_2 = "{'Zt.'tmsz, 'Zt2.'tmsz}, 'Pgl, ['Xns, 'Xm'NSveS]";
7382   const char *form_3 =
7383       "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}, 'Pgl, ['Xns, 'Xm'NSveS]";
7384   const char *form_4 =
7385       "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}, "
7386       "'Pgl, ['Xns, 'Xm'NSveS]";
7387 
7388   switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
7389     case ST2B_z_p_br_contiguous:
7390       mnemonic = "st2b";
7391       form = form_2;
7392       break;
7393     case ST2D_z_p_br_contiguous:
7394       mnemonic = "st2d";
7395       form = form_2;
7396       break;
7397     case ST2H_z_p_br_contiguous:
7398       mnemonic = "st2h";
7399       form = form_2;
7400       break;
7401     case ST2W_z_p_br_contiguous:
7402       mnemonic = "st2w";
7403       form = form_2;
7404       break;
7405     case ST3B_z_p_br_contiguous:
7406       mnemonic = "st3b";
7407       form = form_3;
7408       break;
7409     case ST3D_z_p_br_contiguous:
7410       mnemonic = "st3d";
7411       form = form_3;
7412       break;
7413     case ST3H_z_p_br_contiguous:
7414       mnemonic = "st3h";
7415       form = form_3;
7416       break;
7417     case ST3W_z_p_br_contiguous:
7418       mnemonic = "st3w";
7419       form = form_3;
7420       break;
7421     case ST4B_z_p_br_contiguous:
7422       mnemonic = "st4b";
7423       form = form_4;
7424       break;
7425     case ST4D_z_p_br_contiguous:
7426       mnemonic = "st4d";
7427       form = form_4;
7428       break;
7429     case ST4H_z_p_br_contiguous:
7430       mnemonic = "st4h";
7431       form = form_4;
7432       break;
7433     case ST4W_z_p_br_contiguous:
7434       mnemonic = "st4w";
7435       form = form_4;
7436       break;
7437     default:
7438       break;
7439   }
7440   Format(instr, mnemonic, form);
7441 }
7442 
7443 void Disassembler::VisitSVEStorePredicateRegister(const Instruction *instr) {
7444   const char *mnemonic = "unimplemented";
7445   const char *form = "(SVEStorePredicateRegister)";
7446 
7447   switch (instr->Mask(SVEStorePredicateRegisterMask)) {
7448     case STR_p_bi:
7449       mnemonic = "str";
7450       if (instr->Mask(0x003f1c00) == 0) {
7451         form = "'Pd, ['Xns]";
7452       } else {
7453         form = "'Pd, ['Xns, #'s2116:1210, mul vl]";
7454       }
7455       break;
7456     default:
7457       break;
7458   }
7459   Format(instr, mnemonic, form);
7460 }
7461 
7462 void Disassembler::VisitSVEStoreVectorRegister(const Instruction *instr) {
7463   const char *mnemonic = "unimplemented";
7464   const char *form = "(SVEStoreVectorRegister)";
7465 
7466   switch (instr->Mask(SVEStoreVectorRegisterMask)) {
7467     case STR_z_bi:
7468       mnemonic = "str";
7469       if (instr->Mask(0x003f1c00) == 0) {
7470         form = "'Zd, ['Xns]";
7471       } else {
7472         form = "'Zt, ['Xns, #'s2116:1210, mul vl]";
7473       }
7474       break;
7475     default:
7476       break;
7477   }
7478   Format(instr, mnemonic, form);
7479 }
7480 
7481 void Disassembler::VisitSVETableLookup(const Instruction *instr) {
7482   const char *mnemonic = "unimplemented";
7483   const char *form = "(SVETableLookup)";
7484 
7485   switch (instr->Mask(SVETableLookupMask)) {
7486     case TBL_z_zz_1:
7487       mnemonic = "tbl";
7488       form = "'Zd.'t, {'Zn.'t}, 'Zm.'t";
7489       break;
7490     default:
7491       break;
7492   }
7493   Format(instr, mnemonic, form);
7494 }
7495 
7496 void Disassembler::VisitSVEUnpackPredicateElements(const Instruction *instr) {
7497   const char *mnemonic = "unimplemented";
7498   const char *form = "'Pd.h, 'Pn.b";
7499 
7500   switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
7501     case PUNPKHI_p_p:
7502       mnemonic = "punpkhi";
7503       break;
7504     case PUNPKLO_p_p:
7505       mnemonic = "punpklo";
7506       break;
7507     default:
7508       break;
7509   }
7510   Format(instr, mnemonic, form);
7511 }
7512 
7513 void Disassembler::VisitSVEUnpackVectorElements(const Instruction *instr) {
7514   const char *mnemonic = "unimplemented";
7515   const char *form = "'Zd.'t, 'Zn.'th";
7516 
7517   if (instr->GetSVESize() == 0) {
7518     // The lowest lane size of the destination vector is H-sized lane.
7519     Format(instr, "unallocated", "(SVEUnpackVectorElements)");
7520     return;
7521   }
7522 
7523   switch (instr->Mask(SVEUnpackVectorElementsMask)) {
7524     case SUNPKHI_z_z:
7525       mnemonic = "sunpkhi";
7526       break;
7527     case SUNPKLO_z_z:
7528       mnemonic = "sunpklo";
7529       break;
7530     case UUNPKHI_z_z:
7531       mnemonic = "uunpkhi";
7532       break;
7533     case UUNPKLO_z_z:
7534       mnemonic = "uunpklo";
7535       break;
7536     default:
7537       break;
7538   }
7539   Format(instr, mnemonic, form);
7540 }
7541 
7542 void Disassembler::VisitSVEVectorSplice(const Instruction *instr) {
7543   const char *mnemonic = "unimplemented";
7544   const char *form = "(SVEVectorSplice)";
7545 
7546   switch (instr->Mask(SVEVectorSpliceMask)) {
7547     case SPLICE_z_p_zz_des:
7548       mnemonic = "splice";
7549       form = "'Zd.'t, 'Pgl, 'Zd.'t, 'Zn.'t";
7550       break;
7551     default:
7552       break;
7553   }
7554   Format(instr, mnemonic, form);
7555 }
7556 
7557 void Disassembler::VisitSVEAddressGeneration(const Instruction *instr) {
7558   const char *mnemonic = "adr";
7559   const char *form = "'Zd.d, ['Zn.d, 'Zm.d";
7560   const char *suffix = NULL;
7561 
7562   bool msz_is_zero = (instr->ExtractBits(11, 10) == 0);
7563 
7564   switch (instr->Mask(SVEAddressGenerationMask)) {
7565     case ADR_z_az_d_s32_scaled:
7566       suffix = msz_is_zero ? ", sxtw]" : ", sxtw #'u1110]";
7567       break;
7568     case ADR_z_az_d_u32_scaled:
7569       suffix = msz_is_zero ? ", uxtw]" : ", uxtw #'u1110]";
7570       break;
7571     case ADR_z_az_s_same_scaled:
7572     case ADR_z_az_d_same_scaled:
7573       form = "'Zd.'t, ['Zn.'t, 'Zm.'t";
7574       suffix = msz_is_zero ? "]" : ", lsl #'u1110]";
7575       break;
7576     default:
7577       mnemonic = "unimplemented";
7578       form = "(SVEAddressGeneration)";
7579       break;
7580   }
7581   Format(instr, mnemonic, form, suffix);
7582 }
7583 
7584 void Disassembler::VisitSVEBitwiseLogicalUnpredicated(
7585     const Instruction *instr) {
7586   const char *mnemonic = "unimplemented";
7587   const char *form = "'Zd.d, 'Zn.d, 'Zm.d";
7588 
7589   switch (instr->Mask(SVEBitwiseLogicalUnpredicatedMask)) {
7590     case AND_z_zz:
7591       mnemonic = "and";
7592       break;
7593     case BIC_z_zz:
7594       mnemonic = "bic";
7595       break;
7596     case EOR_z_zz:
7597       mnemonic = "eor";
7598       break;
7599     case ORR_z_zz:
7600       mnemonic = "orr";
7601       if (instr->GetRn() == instr->GetRm()) {
7602         mnemonic = "mov";
7603         form = "'Zd.d, 'Zn.d";
7604       }
7605       break;
7606     default:
7607       break;
7608   }
7609   Format(instr, mnemonic, form);
7610 }
7611 
7612 void Disassembler::VisitSVEBitwiseShiftUnpredicated(const Instruction *instr) {
7613   const char *mnemonic = "unimplemented";
7614   const char *form = "(SVEBitwiseShiftUnpredicated)";
7615   unsigned tsize =
7616       (instr->ExtractBits(23, 22) << 2) | instr->ExtractBits(20, 19);
7617   unsigned lane_size = instr->GetSVESize();
7618 
7619   const char *suffix = NULL;
7620   const char *form_i = "'Zd.'tszs, 'Zn.'tszs, ";
7621 
7622   switch (form_hash_) {
7623     case Hash("asr_z_zi"):
7624     case Hash("lsr_z_zi"):
7625     case Hash("sri_z_zzi"):
7626     case Hash("srsra_z_zi"):
7627     case Hash("ssra_z_zi"):
7628     case Hash("ursra_z_zi"):
7629     case Hash("usra_z_zi"):
7630       if (tsize != 0) {
7631         // The tsz field must not be zero.
7632         mnemonic = mnemonic_.c_str();
7633         form = form_i;
7634         suffix = "'ITriSves";
7635       }
7636       break;
7637     case Hash("lsl_z_zi"):
7638     case Hash("sli_z_zzi"):
7639       if (tsize != 0) {
7640         // The tsz field must not be zero.
7641         mnemonic = mnemonic_.c_str();
7642         form = form_i;
7643         suffix = "'ITriSver";
7644       }
7645       break;
7646     case Hash("asr_z_zw"):
7647     case Hash("lsl_z_zw"):
7648     case Hash("lsr_z_zw"):
7649       if (lane_size <= kSRegSizeInBytesLog2) {
7650         mnemonic = mnemonic_.c_str();
7651         form = "'Zd.'t, 'Zn.'t, 'Zm.d";
7652       }
7653       break;
7654     default:
7655       break;
7656   }
7657 
7658   Format(instr, mnemonic, form, suffix);
7659 }
7660 
7661 void Disassembler::VisitSVEElementCount(const Instruction *instr) {
7662   const char *mnemonic = "unimplemented";
7663   const char *form =
7664       IncDecFormHelper(instr, "'Xd, 'Ipc, mul #'u1916+1", "'Xd, 'Ipc", "'Xd");
7665 
7666   switch (instr->Mask(SVEElementCountMask)) {
7667     case CNTB_r_s:
7668       mnemonic = "cntb";
7669       break;
7670     case CNTD_r_s:
7671       mnemonic = "cntd";
7672       break;
7673     case CNTH_r_s:
7674       mnemonic = "cnth";
7675       break;
7676     case CNTW_r_s:
7677       mnemonic = "cntw";
7678       break;
7679     default:
7680       break;
7681   }
7682   Format(instr, mnemonic, form);
7683 }
7684 
7685 void Disassembler::VisitSVEFPAccumulatingReduction(const Instruction *instr) {
7686   const char *mnemonic = "unimplemented";
7687   const char *form = "(SVEFPAccumulatingReduction)";
7688 
7689   if (instr->GetSVEVectorFormat() != kFormatVnB) {
7690     switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
7691       case FADDA_v_p_z:
7692         mnemonic = "fadda";
7693         form = "'t'u0400, 'Pgl, 't'u0400, 'Zn.'t";
7694         break;
7695       default:
7696         break;
7697     }
7698   }
7699   Format(instr, mnemonic, form);
7700 }
7701 
7702 void Disassembler::VisitSVEFPArithmeticUnpredicated(const Instruction *instr) {
7703   const char *mnemonic = "unimplemented";
7704   const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t";
7705 
7706   if (instr->GetSVEVectorFormat() == kFormatVnB) {
7707     form = ("(SVEFPArithmeticUnpredicated)");
7708   } else {
7709     switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
7710       case FADD_z_zz:
7711         mnemonic = "fadd";
7712         break;
7713       case FMUL_z_zz:
7714         mnemonic = "fmul";
7715         break;
7716       case FRECPS_z_zz:
7717         mnemonic = "frecps";
7718         break;
7719       case FRSQRTS_z_zz:
7720         mnemonic = "frsqrts";
7721         break;
7722       case FSUB_z_zz:
7723         mnemonic = "fsub";
7724         break;
7725       case FTSMUL_z_zz:
7726         mnemonic = "ftsmul";
7727         break;
7728       default:
7729         break;
7730     }
7731   }
7732   Format(instr, mnemonic, form);
7733 }
7734 
7735 void Disassembler::VisitSVEFPCompareVectors(const Instruction *instr) {
7736   const char *mnemonic = "unimplemented";
7737   const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
7738 
7739   if (instr->GetSVEVectorFormat() == kFormatVnB) {
7740     form = "(SVEFPCompareVectors)";
7741   } else {
7742     switch (instr->Mask(SVEFPCompareVectorsMask)) {
7743       case FACGE_p_p_zz:
7744         mnemonic = "facge";
7745         break;
7746       case FACGT_p_p_zz:
7747         mnemonic = "facgt";
7748         break;
7749       case FCMEQ_p_p_zz:
7750         mnemonic = "fcmeq";
7751         break;
7752       case FCMGE_p_p_zz:
7753         mnemonic = "fcmge";
7754         break;
7755       case FCMGT_p_p_zz:
7756         mnemonic = "fcmgt";
7757         break;
7758       case FCMNE_p_p_zz:
7759         mnemonic = "fcmne";
7760         break;
7761       case FCMUO_p_p_zz:
7762         mnemonic = "fcmuo";
7763         break;
7764       default:
7765         break;
7766     }
7767   }
7768   Format(instr, mnemonic, form);
7769 }
7770 
7771 void Disassembler::VisitSVEFPCompareWithZero(const Instruction *instr) {
7772   const char *mnemonic = "unimplemented";
7773   const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, #0.0";
7774 
7775   if (instr->GetSVEVectorFormat() == kFormatVnB) {
7776     form = "(SVEFPCompareWithZero)";
7777   } else {
7778     switch (instr->Mask(SVEFPCompareWithZeroMask)) {
7779       case FCMEQ_p_p_z0:
7780         mnemonic = "fcmeq";
7781         break;
7782       case FCMGE_p_p_z0:
7783         mnemonic = "fcmge";
7784         break;
7785       case FCMGT_p_p_z0:
7786         mnemonic = "fcmgt";
7787         break;
7788       case FCMLE_p_p_z0:
7789         mnemonic = "fcmle";
7790         break;
7791       case FCMLT_p_p_z0:
7792         mnemonic = "fcmlt";
7793         break;
7794       case FCMNE_p_p_z0:
7795         mnemonic = "fcmne";
7796         break;
7797       default:
7798         break;
7799     }
7800   }
7801   Format(instr, mnemonic, form);
7802 }
7803 
7804 void Disassembler::VisitSVEFPComplexAddition(const Instruction *instr) {
7805   const char *mnemonic = "unimplemented";
7806   const char *form = "(SVEFPComplexAddition)";
7807 
7808   if (instr->GetSVEVectorFormat() != kFormatVnB) {
7809     switch (instr->Mask(SVEFPComplexAdditionMask)) {
7810       case FCADD_z_p_zz:
7811         mnemonic = "fcadd";
7812         if (instr->ExtractBit(16) == 0) {
7813           form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t, #90";
7814         } else {
7815           form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t, #270";
7816         }
7817         break;
7818       default:
7819         break;
7820     }
7821   }
7822   Format(instr, mnemonic, form);
7823 }
7824 
7825 void Disassembler::VisitSVEFPComplexMulAdd(const Instruction *instr) {
7826   const char *mnemonic = "unimplemented";
7827   const char *form = "(SVEFPComplexMulAdd)";
7828   const char *suffix = NULL;
7829 
7830   const char *fcmla_constants[] = {"0", "90", "180", "270"};
7831 
7832   if (instr->GetSVEVectorFormat() != kFormatVnB) {
7833     switch (instr->Mask(SVEFPComplexMulAddMask)) {
7834       case FCMLA_z_p_zzz:
7835         mnemonic = "fcmla";
7836         form = "'Zd.'t, 'Pgl/m, 'Zn.'t, 'Zm.'t, #";
7837         suffix = fcmla_constants[instr->ExtractBits(14, 13)];
7838         break;
7839       default:
7840         break;
7841     }
7842   }
7843   Format(instr, mnemonic, form, suffix);
7844 }
7845 
7846 void Disassembler::VisitSVEFPComplexMulAddIndex(const Instruction *instr) {
7847   const char *mnemonic = "unimplemented";
7848   const char *form = "(SVEFPComplexMulAddIndex)";
7849 
7850   const char *fcmla_constants[] = {"0", "90", "180", "270"};
7851   const char *suffix = fcmla_constants[instr->ExtractBits(11, 10)];
7852 
7853   switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
7854     case FCMLA_z_zzzi_h:
7855       mnemonic = "fcmla";
7856       form = "'Zd.h, 'Zn.h, z'u1816.h['u2019], #";
7857       break;
7858     case FCMLA_z_zzzi_s:
7859       mnemonic = "fcmla";
7860       form = "'Zd.s, 'Zn.s, z'u1916.s['u2020], #";
7861       break;
7862     default:
7863       suffix = NULL;
7864       break;
7865   }
7866   Format(instr, mnemonic, form, suffix);
7867 }
7868 
7869 void Disassembler::VisitSVEFPFastReduction(const Instruction *instr) {
7870   const char *mnemonic = "unimplemented";
7871   const char *form = "'t'u0400, 'Pgl, 'Zn.'t";
7872 
7873   if (instr->GetSVEVectorFormat() == kFormatVnB) {
7874     form = "(SVEFPFastReduction)";
7875   } else {
7876     switch (instr->Mask(SVEFPFastReductionMask)) {
7877       case FADDV_v_p_z:
7878         mnemonic = "faddv";
7879         break;
7880       case FMAXNMV_v_p_z:
7881         mnemonic = "fmaxnmv";
7882         break;
7883       case FMAXV_v_p_z:
7884         mnemonic = "fmaxv";
7885         break;
7886       case FMINNMV_v_p_z:
7887         mnemonic = "fminnmv";
7888         break;
7889       case FMINV_v_p_z:
7890         mnemonic = "fminv";
7891         break;
7892       default:
7893         break;
7894     }
7895   }
7896   Format(instr, mnemonic, form);
7897 }
7898 
7899 void Disassembler::VisitSVEFPMulIndex(const Instruction *instr) {
7900   const char *mnemonic = "unimplemented";
7901   const char *form = "(SVEFPMulIndex)";
7902 
7903   switch (instr->Mask(SVEFPMulIndexMask)) {
7904     case FMUL_z_zzi_d:
7905       mnemonic = "fmul";
7906       form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]";
7907       break;
7908     case FMUL_z_zzi_h:
7909     case FMUL_z_zzi_h_i3h:
7910       mnemonic = "fmul";
7911       form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]";
7912       break;
7913     case FMUL_z_zzi_s:
7914       mnemonic = "fmul";
7915       form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]";
7916       break;
7917     default:
7918       break;
7919   }
7920   Format(instr, mnemonic, form);
7921 }
7922 
7923 void Disassembler::VisitSVEFPMulAdd(const Instruction *instr) {
7924   const char *mnemonic = "unimplemented";
7925   const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t, 'Zm.'t";
7926 
7927   if (instr->GetSVEVectorFormat() == kFormatVnB) {
7928     form = "(SVEFPMulAdd)";
7929   } else {
7930     switch (instr->Mask(SVEFPMulAddMask)) {
7931       case FMAD_z_p_zzz:
7932         mnemonic = "fmad";
7933         break;
7934       case FMLA_z_p_zzz:
7935         mnemonic = "fmla";
7936         break;
7937       case FMLS_z_p_zzz:
7938         mnemonic = "fmls";
7939         break;
7940       case FMSB_z_p_zzz:
7941         mnemonic = "fmsb";
7942         break;
7943       case FNMAD_z_p_zzz:
7944         mnemonic = "fnmad";
7945         break;
7946       case FNMLA_z_p_zzz:
7947         mnemonic = "fnmla";
7948         break;
7949       case FNMLS_z_p_zzz:
7950         mnemonic = "fnmls";
7951         break;
7952       case FNMSB_z_p_zzz:
7953         mnemonic = "fnmsb";
7954         break;
7955       default:
7956         break;
7957     }
7958   }
7959   Format(instr, mnemonic, form);
7960 }
7961 
7962 void Disassembler::VisitSVEFPMulAddIndex(const Instruction *instr) {
7963   const char *mnemonic = "unimplemented";
7964   const char *form = "(SVEFPMulAddIndex)";
7965 
7966   switch (instr->Mask(SVEFPMulAddIndexMask)) {
7967     case FMLA_z_zzzi_d:
7968       mnemonic = "fmla";
7969       form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]";
7970       break;
7971     case FMLA_z_zzzi_s:
7972       mnemonic = "fmla";
7973       form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]";
7974       break;
7975     case FMLS_z_zzzi_d:
7976       mnemonic = "fmls";
7977       form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]";
7978       break;
7979     case FMLS_z_zzzi_s:
7980       mnemonic = "fmls";
7981       form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]";
7982       break;
7983     case FMLA_z_zzzi_h:
7984     case FMLA_z_zzzi_h_i3h:
7985       mnemonic = "fmla";
7986       form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]";
7987       break;
7988     case FMLS_z_zzzi_h:
7989     case FMLS_z_zzzi_h_i3h:
7990       mnemonic = "fmls";
7991       form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]";
7992       break;
7993     default:
7994       break;
7995   }
7996 
7997   Format(instr, mnemonic, form);
7998 }
7999 
8000 void Disassembler::VisitSVEFPUnaryOpUnpredicated(const Instruction *instr) {
8001   const char *mnemonic = "unimplemented";
8002   const char *form = "'Zd.'t, 'Zn.'t";
8003 
8004   if (instr->GetSVEVectorFormat() == kFormatVnB) {
8005     form = "(SVEFPUnaryOpUnpredicated)";
8006   } else {
8007     switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
8008       case FRECPE_z_z:
8009         mnemonic = "frecpe";
8010         break;
8011       case FRSQRTE_z_z:
8012         mnemonic = "frsqrte";
8013         break;
8014       default:
8015         break;
8016     }
8017   }
8018   Format(instr, mnemonic, form);
8019 }
8020 
8021 void Disassembler::VisitSVEIncDecByPredicateCount(const Instruction *instr) {
8022   const char *mnemonic = "unimplemented";
8023   const char *form = "(SVEIncDecByPredicateCount)";
8024 
8025   switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8026     case DECP_r_p_r:
8027     case DECP_z_p_z:
8028       mnemonic = "decp";
8029       break;
8030     case INCP_r_p_r:
8031     case INCP_z_p_z:
8032       mnemonic = "incp";
8033       break;
8034     case SQDECP_r_p_r_sx:
8035     case SQDECP_r_p_r_x:
8036     case SQDECP_z_p_z:
8037       mnemonic = "sqdecp";
8038       break;
8039     case SQINCP_r_p_r_sx:
8040     case SQINCP_r_p_r_x:
8041     case SQINCP_z_p_z:
8042       mnemonic = "sqincp";
8043       break;
8044     case UQDECP_r_p_r_uw:
8045     case UQDECP_r_p_r_x:
8046     case UQDECP_z_p_z:
8047       mnemonic = "uqdecp";
8048       break;
8049     case UQINCP_r_p_r_uw:
8050     case UQINCP_r_p_r_x:
8051     case UQINCP_z_p_z:
8052       mnemonic = "uqincp";
8053       break;
8054     default:
8055       break;
8056   }
8057 
8058   switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8059     // <Xdn>, <Pg>.<T>
8060     case DECP_r_p_r:
8061     case INCP_r_p_r:
8062       form = "'Xd, 'Pn.'t";
8063       break;
8064     // <Zdn>.<T>, <Pg>
8065     case DECP_z_p_z:
8066     case INCP_z_p_z:
8067     case SQDECP_z_p_z:
8068     case SQINCP_z_p_z:
8069     case UQDECP_z_p_z:
8070     case UQINCP_z_p_z:
8071       form = "'Zd.'t, 'Pn";
8072       break;
8073     // <Xdn>, <Pg>.<T>, <Wdn>
8074     case SQDECP_r_p_r_sx:
8075     case SQINCP_r_p_r_sx:
8076       form = "'Xd, 'Pn.'t, 'Wd";
8077       break;
8078     // <Xdn>, <Pg>.<T>
8079     case SQDECP_r_p_r_x:
8080     case SQINCP_r_p_r_x:
8081     case UQDECP_r_p_r_x:
8082     case UQINCP_r_p_r_x:
8083       form = "'Xd, 'Pn.'t";
8084       break;
8085     // <Wdn>, <Pg>.<T>
8086     case UQDECP_r_p_r_uw:
8087     case UQINCP_r_p_r_uw:
8088       form = "'Wd, 'Pn.'t";
8089       break;
8090     default:
8091       break;
8092   }
8093   Format(instr, mnemonic, form);
8094 }
8095 
8096 void Disassembler::VisitSVEIndexGeneration(const Instruction *instr) {
8097   const char *mnemonic = "unimplemented";
8098   const char *form = "(SVEIndexGeneration)";
8099 
8100   bool w_inputs =
8101       static_cast<unsigned>(instr->GetSVESize()) <= kWRegSizeInBytesLog2;
8102 
8103   switch (instr->Mask(SVEIndexGenerationMask)) {
8104     case INDEX_z_ii:
8105       mnemonic = "index";
8106       form = "'Zd.'t, #'s0905, #'s2016";
8107       break;
8108     case INDEX_z_ir:
8109       mnemonic = "index";
8110       form = w_inputs ? "'Zd.'t, #'s0905, 'Wm" : "'Zd.'t, #'s0905, 'Xm";
8111       break;
8112     case INDEX_z_ri:
8113       mnemonic = "index";
8114       form = w_inputs ? "'Zd.'t, 'Wn, #'s2016" : "'Zd.'t, 'Xn, #'s2016";
8115       break;
8116     case INDEX_z_rr:
8117       mnemonic = "index";
8118       form = w_inputs ? "'Zd.'t, 'Wn, 'Wm" : "'Zd.'t, 'Xn, 'Xm";
8119       break;
8120     default:
8121       break;
8122   }
8123   Format(instr, mnemonic, form);
8124 }
8125 
8126 void Disassembler::VisitSVEIntArithmeticUnpredicated(const Instruction *instr) {
8127   const char *mnemonic = "unimplemented";
8128   const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t";
8129 
8130   switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
8131     case ADD_z_zz:
8132       mnemonic = "add";
8133       break;
8134     case SQADD_z_zz:
8135       mnemonic = "sqadd";
8136       break;
8137     case SQSUB_z_zz:
8138       mnemonic = "sqsub";
8139       break;
8140     case SUB_z_zz:
8141       mnemonic = "sub";
8142       break;
8143     case UQADD_z_zz:
8144       mnemonic = "uqadd";
8145       break;
8146     case UQSUB_z_zz:
8147       mnemonic = "uqsub";
8148       break;
8149     default:
8150       break;
8151   }
8152   Format(instr, mnemonic, form);
8153 }
8154 
8155 void Disassembler::VisitSVEIntCompareSignedImm(const Instruction *instr) {
8156   const char *mnemonic = "unimplemented";
8157   const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, #'s2016";
8158 
8159   switch (instr->Mask(SVEIntCompareSignedImmMask)) {
8160     case CMPEQ_p_p_zi:
8161       mnemonic = "cmpeq";
8162       break;
8163     case CMPGE_p_p_zi:
8164       mnemonic = "cmpge";
8165       break;
8166     case CMPGT_p_p_zi:
8167       mnemonic = "cmpgt";
8168       break;
8169     case CMPLE_p_p_zi:
8170       mnemonic = "cmple";
8171       break;
8172     case CMPLT_p_p_zi:
8173       mnemonic = "cmplt";
8174       break;
8175     case CMPNE_p_p_zi:
8176       mnemonic = "cmpne";
8177       break;
8178     default:
8179       break;
8180   }
8181   Format(instr, mnemonic, form);
8182 }
8183 
8184 void Disassembler::VisitSVEIntCompareUnsignedImm(const Instruction *instr) {
8185   const char *mnemonic = "unimplemented";
8186   const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, #'u2014";
8187 
8188   switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
8189     case CMPHI_p_p_zi:
8190       mnemonic = "cmphi";
8191       break;
8192     case CMPHS_p_p_zi:
8193       mnemonic = "cmphs";
8194       break;
8195     case CMPLO_p_p_zi:
8196       mnemonic = "cmplo";
8197       break;
8198     case CMPLS_p_p_zi:
8199       mnemonic = "cmpls";
8200       break;
8201     default:
8202       break;
8203   }
8204   Format(instr, mnemonic, form);
8205 }
8206 
8207 void Disassembler::VisitSVEIntCompareVectors(const Instruction *instr) {
8208   const char *mnemonic = "unimplemented";
8209   const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.d";
8210 
8211   switch (instr->Mask(SVEIntCompareVectorsMask)) {
8212     case CMPEQ_p_p_zw:
8213       mnemonic = "cmpeq";
8214       break;
8215     case CMPEQ_p_p_zz:
8216       mnemonic = "cmpeq";
8217       form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8218       break;
8219     case CMPGE_p_p_zw:
8220       mnemonic = "cmpge";
8221       break;
8222     case CMPGE_p_p_zz:
8223       mnemonic = "cmpge";
8224       form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8225       break;
8226     case CMPGT_p_p_zw:
8227       mnemonic = "cmpgt";
8228       break;
8229     case CMPGT_p_p_zz:
8230       mnemonic = "cmpgt";
8231       form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8232       break;
8233     case CMPHI_p_p_zw:
8234       mnemonic = "cmphi";
8235       break;
8236     case CMPHI_p_p_zz:
8237       mnemonic = "cmphi";
8238       form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8239       break;
8240     case CMPHS_p_p_zw:
8241       mnemonic = "cmphs";
8242       break;
8243     case CMPHS_p_p_zz:
8244       mnemonic = "cmphs";
8245       form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8246       break;
8247     case CMPLE_p_p_zw:
8248       mnemonic = "cmple";
8249       break;
8250     case CMPLO_p_p_zw:
8251       mnemonic = "cmplo";
8252       break;
8253     case CMPLS_p_p_zw:
8254       mnemonic = "cmpls";
8255       break;
8256     case CMPLT_p_p_zw:
8257       mnemonic = "cmplt";
8258       break;
8259     case CMPNE_p_p_zw:
8260       mnemonic = "cmpne";
8261       break;
8262     case CMPNE_p_p_zz:
8263       mnemonic = "cmpne";
8264       form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8265       break;
8266     default:
8267       break;
8268   }
8269   Format(instr, mnemonic, form);
8270 }
8271 
8272 void Disassembler::VisitSVEIntMulAddPredicated(const Instruction *instr) {
8273   const char *mnemonic = "unimplemented";
8274   const char *form = "(SVEIntMulAddPredicated)";
8275 
8276   switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
8277     case MAD_z_p_zzz:
8278       mnemonic = "mad";
8279       form = "'Zd.'t, 'Pgl/m, 'Zm.'t, 'Zn.'t";
8280       break;
8281     case MLA_z_p_zzz:
8282       mnemonic = "mla";
8283       form = "'Zd.'t, 'Pgl/m, 'Zn.'t, 'Zm.'t";
8284       break;
8285     case MLS_z_p_zzz:
8286       mnemonic = "mls";
8287       form = "'Zd.'t, 'Pgl/m, 'Zn.'t, 'Zm.'t";
8288       break;
8289     case MSB_z_p_zzz:
8290       mnemonic = "msb";
8291       form = "'Zd.'t, 'Pgl/m, 'Zm.'t, 'Zn.'t";
8292       break;
8293     default:
8294       break;
8295   }
8296   Format(instr, mnemonic, form);
8297 }
8298 
8299 void Disassembler::VisitSVEIntMulAddUnpredicated(const Instruction *instr) {
8300   const char *mnemonic = "unimplemented";
8301   const char *form = "(SVEIntMulAddUnpredicated)";
8302 
8303   if (static_cast<unsigned>(instr->GetSVESize()) >= kSRegSizeInBytesLog2) {
8304     form = "'Zd.'t, 'Zn.'tq, 'Zm.'tq";
8305     switch (instr->Mask(SVEIntMulAddUnpredicatedMask)) {
8306       case SDOT_z_zzz:
8307         mnemonic = "sdot";
8308         break;
8309       case UDOT_z_zzz:
8310         mnemonic = "udot";
8311         break;
8312       default:
8313         break;
8314     }
8315   }
8316 
8317   Format(instr, mnemonic, form);
8318 }
8319 
8320 void Disassembler::VisitSVEMovprfx(const Instruction *instr) {
8321   const char *mnemonic = "unimplemented";
8322   const char *form = "(SVEMovprfx)";
8323 
8324   if (instr->Mask(SVEMovprfxMask) == MOVPRFX_z_p_z) {
8325     mnemonic = "movprfx";
8326     form = "'Zd.'t, 'Pgl/'?16:mz, 'Zn.'t";
8327   }
8328 
8329   Format(instr, mnemonic, form);
8330 }
8331 
8332 void Disassembler::VisitSVEIntReduction(const Instruction *instr) {
8333   const char *mnemonic = "unimplemented";
8334   const char *form = "'Vdv, 'Pgl, 'Zn.'t";
8335 
8336   if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
8337     switch (instr->Mask(SVEIntReductionLogicalMask)) {
8338       case ANDV_r_p_z:
8339         mnemonic = "andv";
8340         break;
8341       case EORV_r_p_z:
8342         mnemonic = "eorv";
8343         break;
8344       case ORV_r_p_z:
8345         mnemonic = "orv";
8346         break;
8347       default:
8348         break;
8349     }
8350   } else {
8351     switch (instr->Mask(SVEIntReductionMask)) {
8352       case SADDV_r_p_z:
8353         mnemonic = "saddv";
8354         form = "'Dd, 'Pgl, 'Zn.'t";
8355         break;
8356       case SMAXV_r_p_z:
8357         mnemonic = "smaxv";
8358         break;
8359       case SMINV_r_p_z:
8360         mnemonic = "sminv";
8361         break;
8362       case UADDV_r_p_z:
8363         mnemonic = "uaddv";
8364         form = "'Dd, 'Pgl, 'Zn.'t";
8365         break;
8366       case UMAXV_r_p_z:
8367         mnemonic = "umaxv";
8368         break;
8369       case UMINV_r_p_z:
8370         mnemonic = "uminv";
8371         break;
8372       default:
8373         break;
8374     }
8375   }
8376   Format(instr, mnemonic, form);
8377 }
8378 
8379 void Disassembler::VisitSVEIntUnaryArithmeticPredicated(
8380     const Instruction *instr) {
8381   const char *mnemonic = mnemonic_.c_str();
8382   const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t";
8383   VectorFormat vform = instr->GetSVEVectorFormat();
8384 
8385   switch (form_hash_) {
8386     case Hash("sxtw_z_p_z"):
8387     case Hash("uxtw_z_p_z"):
8388       if (vform == kFormatVnS) {
8389         VisitUnallocated(instr);
8390         return;
8391       }
8392       VIXL_FALLTHROUGH();
8393     case Hash("sxth_z_p_z"):
8394     case Hash("uxth_z_p_z"):
8395       if (vform == kFormatVnH) {
8396         VisitUnallocated(instr);
8397         return;
8398       }
8399       VIXL_FALLTHROUGH();
8400     case Hash("sxtb_z_p_z"):
8401     case Hash("uxtb_z_p_z"):
8402     case Hash("fabs_z_p_z"):
8403     case Hash("fneg_z_p_z"):
8404       if (vform == kFormatVnB) {
8405         VisitUnallocated(instr);
8406         return;
8407       }
8408       break;
8409   }
8410 
8411   Format(instr, mnemonic, form);
8412 }
8413 
8414 void Disassembler::VisitSVEMulIndex(const Instruction *instr) {
8415   const char *mnemonic = mnemonic_.c_str();
8416   const char *form = "(SVEMulIndex)";
8417 
8418   switch (form_hash_) {
8419     case Hash("sdot_z_zzzi_d"):
8420     case Hash("udot_z_zzzi_d"):
8421       form = "'Zd.d, 'Zn.h, z'u1916.h['u2020]";
8422       break;
8423     case Hash("sdot_z_zzzi_s"):
8424     case Hash("sudot_z_zzzi_s"):
8425     case Hash("udot_z_zzzi_s"):
8426     case Hash("usdot_z_zzzi_s"):
8427       form = "'Zd.s, 'Zn.b, z'u1816.b['u2019]";
8428       break;
8429     default:
8430       break;
8431   }
8432   Format(instr, mnemonic, form);
8433 }
8434 
8435 void Disassembler::VisitSVEPermuteVectorExtract(const Instruction *instr) {
8436   const char *mnemonic = "unimplemented";
8437   const char *form = "(SVEPermuteVectorExtract)";
8438 
8439   switch (instr->Mask(SVEPermuteVectorExtractMask)) {
8440     case EXT_z_zi_des:
8441       mnemonic = "ext";
8442       form = "'Zd.b, 'Zd.b, 'Zn.b, #'u2016:1210";
8443       break;
8444     default:
8445       break;
8446   }
8447   Format(instr, mnemonic, form);
8448 }
8449 
8450 void Disassembler::VisitSVEPermuteVectorInterleaving(const Instruction *instr) {
8451   const char *mnemonic = "unimplemented";
8452   const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t";
8453 
8454   switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
8455     case TRN1_z_zz:
8456       mnemonic = "trn1";
8457       break;
8458     case TRN2_z_zz:
8459       mnemonic = "trn2";
8460       break;
8461     case UZP1_z_zz:
8462       mnemonic = "uzp1";
8463       break;
8464     case UZP2_z_zz:
8465       mnemonic = "uzp2";
8466       break;
8467     case ZIP1_z_zz:
8468       mnemonic = "zip1";
8469       break;
8470     case ZIP2_z_zz:
8471       mnemonic = "zip2";
8472       break;
8473     default:
8474       break;
8475   }
8476   Format(instr, mnemonic, form);
8477 }
8478 
8479 void Disassembler::VisitSVEPredicateCount(const Instruction *instr) {
8480   const char *mnemonic = "unimplemented";
8481   const char *form = "(SVEPredicateCount)";
8482 
8483   switch (instr->Mask(SVEPredicateCountMask)) {
8484     case CNTP_r_p_p:
8485       mnemonic = "cntp";
8486       form = "'Xd, p'u1310, 'Pn.'t";
8487       break;
8488     default:
8489       break;
8490   }
8491   Format(instr, mnemonic, form);
8492 }
8493 
8494 void Disassembler::VisitSVEPredicateLogical(const Instruction *instr) {
8495   const char *mnemonic = "unimplemented";
8496   const char *form = "'Pd.b, p'u1310/z, 'Pn.b, 'Pm.b";
8497 
8498   int pd = instr->GetPd();
8499   int pn = instr->GetPn();
8500   int pm = instr->GetPm();
8501   int pg = instr->ExtractBits(13, 10);
8502 
8503   switch (instr->Mask(SVEPredicateLogicalMask)) {
8504     case ANDS_p_p_pp_z:
8505       mnemonic = "ands";
8506       if (pn == pm) {
8507         mnemonic = "movs";
8508         form = "'Pd.b, p'u1310/z, 'Pn.b";
8509       }
8510       break;
8511     case AND_p_p_pp_z:
8512       mnemonic = "and";
8513       if (pn == pm) {
8514         mnemonic = "mov";
8515         form = "'Pd.b, p'u1310/z, 'Pn.b";
8516       }
8517       break;
8518     case BICS_p_p_pp_z:
8519       mnemonic = "bics";
8520       break;
8521     case BIC_p_p_pp_z:
8522       mnemonic = "bic";
8523       break;
8524     case EORS_p_p_pp_z:
8525       mnemonic = "eors";
8526       if (pm == pg) {
8527         mnemonic = "nots";
8528         form = "'Pd.b, 'Pm/z, 'Pn.b";
8529       }
8530       break;
8531     case EOR_p_p_pp_z:
8532       mnemonic = "eor";
8533       if (pm == pg) {
8534         mnemonic = "not";
8535         form = "'Pd.b, 'Pm/z, 'Pn.b";
8536       }
8537       break;
8538     case NANDS_p_p_pp_z:
8539       mnemonic = "nands";
8540       break;
8541     case NAND_p_p_pp_z:
8542       mnemonic = "nand";
8543       break;
8544     case NORS_p_p_pp_z:
8545       mnemonic = "nors";
8546       break;
8547     case NOR_p_p_pp_z:
8548       mnemonic = "nor";
8549       break;
8550     case ORNS_p_p_pp_z:
8551       mnemonic = "orns";
8552       break;
8553     case ORN_p_p_pp_z:
8554       mnemonic = "orn";
8555       break;
8556     case ORRS_p_p_pp_z:
8557       mnemonic = "orrs";
8558       if ((pn == pm) && (pn == pg)) {
8559         mnemonic = "movs";
8560         form = "'Pd.b, 'Pn.b";
8561       }
8562       break;
8563     case ORR_p_p_pp_z:
8564       mnemonic = "orr";
8565       if ((pn == pm) && (pn == pg)) {
8566         mnemonic = "mov";
8567         form = "'Pd.b, 'Pn.b";
8568       }
8569       break;
8570     case SEL_p_p_pp:
8571       if (pd == pm) {
8572         mnemonic = "mov";
8573         form = "'Pd.b, p'u1310/m, 'Pn.b";
8574       } else {
8575         mnemonic = "sel";
8576         form = "'Pd.b, p'u1310, 'Pn.b, 'Pm.b";
8577       }
8578       break;
8579     default:
8580       form = "(SVEPredicateLogical)";
8581       break;
8582   }
8583   Format(instr, mnemonic, form);
8584 }
8585 
8586 void Disassembler::VisitSVEPredicateInitialize(const Instruction *instr) {
8587   // This group only contains PTRUE{S}, and there are no unallocated encodings.
8588   VIXL_STATIC_ASSERT(
8589       SVEPredicateInitializeMask ==
8590       (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
8591   VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
8592               (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
8593 
8594   const char *mnemonic = instr->ExtractBit(16) ? "ptrues" : "ptrue";
8595   const char *form = "'Pd.'t, 'Ipc";
8596   // Omit the pattern if it is the default ('ALL').
8597   if (instr->ExtractBits(9, 5) == SVE_ALL) form = "'Pd.'t";
8598   Format(instr, mnemonic, form);
8599 }
8600 
8601 void Disassembler::VisitSVEPredicateNextActive(const Instruction *instr) {
8602   // This group only contains PNEXT, and there are no unallocated encodings.
8603   VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
8604   VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
8605 
8606   Format(instr, "pnext", "'Pd.'t, 'Pn, 'Pd.'t");
8607 }
8608 
8609 void Disassembler::VisitSVEPredicateReadFromFFR_Predicated(
8610     const Instruction *instr) {
8611   const char *mnemonic = "unimplemented";
8612   const char *form = "(SVEPredicateReadFromFFR_Predicated)";
8613   switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
8614     case RDFFR_p_p_f:
8615     case RDFFRS_p_p_f:
8616       mnemonic = instr->ExtractBit(22) ? "rdffrs" : "rdffr";
8617       form = "'Pd.b, 'Pn/z";
8618       break;
8619     default:
8620       break;
8621   }
8622   Format(instr, mnemonic, form);
8623 }
8624 
8625 void Disassembler::VisitSVEPropagateBreak(const Instruction *instr) {
8626   const char *mnemonic = "unimplemented";
8627   const char *form = "'Pd.b, p'u1310/z, 'Pn.b, 'Pm.b";
8628 
8629   switch (instr->Mask(SVEPropagateBreakMask)) {
8630     case BRKPAS_p_p_pp:
8631       mnemonic = "brkpas";
8632       break;
8633     case BRKPA_p_p_pp:
8634       mnemonic = "brkpa";
8635       break;
8636     case BRKPBS_p_p_pp:
8637       mnemonic = "brkpbs";
8638       break;
8639     case BRKPB_p_p_pp:
8640       mnemonic = "brkpb";
8641       break;
8642     default:
8643       break;
8644   }
8645   Format(instr, mnemonic, form);
8646 }
8647 
8648 void Disassembler::VisitSVEStackFrameAdjustment(const Instruction *instr) {
8649   const char *mnemonic = "unimplemented";
8650   const char *form = "'Xds, 'Xms, #'s1005";
8651 
8652   switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
8653     case ADDPL_r_ri:
8654       mnemonic = "addpl";
8655       break;
8656     case ADDVL_r_ri:
8657       mnemonic = "addvl";
8658       break;
8659     default:
8660       form = "(SVEStackFrameAdjustment)";
8661       break;
8662   }
8663 
8664   Format(instr, mnemonic, form);
8665 }
8666 
8667 void Disassembler::VisitSVEStackFrameSize(const Instruction *instr) {
8668   const char *mnemonic = "unimplemented";
8669   const char *form = "(SVEStackFrameSize)";
8670 
8671   switch (instr->Mask(SVEStackFrameSizeMask)) {
8672     case RDVL_r_i:
8673       mnemonic = "rdvl";
8674       form = "'Xd, #'s1005";
8675       break;
8676     default:
8677       break;
8678   }
8679 
8680   Format(instr, mnemonic, form);
8681 }
8682 
8683 void Disassembler::VisitSVEVectorSelect(const Instruction *instr) {
8684   const char *mnemonic = "unimplemented";
8685   const char *form = "(SVEVectorSelect)";
8686 
8687   switch (instr->Mask(SVEVectorSelectMask)) {
8688     case SEL_z_p_zz:
8689       if (instr->GetRd() == instr->GetRm()) {
8690         mnemonic = "mov";
8691         form = "'Zd.'t, p'u1310/m, 'Zn.'t";
8692       } else {
8693         mnemonic = "sel";
8694         form = "'Zd.'t, p'u1310, 'Zn.'t, 'Zm.'t";
8695       }
8696       break;
8697     default:
8698       break;
8699   }
8700   Format(instr, mnemonic, form);
8701 }
8702 
8703 void Disassembler::VisitSVEContiguousLoad_ScalarPlusImm(
8704     const Instruction *instr) {
8705   const char *mnemonic = "unimplemented";
8706   const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns";
8707   const char *suffix =
8708       (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]";
8709 
8710   switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
8711     case LD1B_z_p_bi_u16:
8712     case LD1B_z_p_bi_u32:
8713     case LD1B_z_p_bi_u64:
8714     case LD1B_z_p_bi_u8:
8715       mnemonic = "ld1b";
8716       break;
8717     case LD1D_z_p_bi_u64:
8718       mnemonic = "ld1d";
8719       break;
8720     case LD1H_z_p_bi_u16:
8721     case LD1H_z_p_bi_u32:
8722     case LD1H_z_p_bi_u64:
8723       mnemonic = "ld1h";
8724       break;
8725     case LD1SB_z_p_bi_s16:
8726     case LD1SB_z_p_bi_s32:
8727     case LD1SB_z_p_bi_s64:
8728       mnemonic = "ld1sb";
8729       break;
8730     case LD1SH_z_p_bi_s32:
8731     case LD1SH_z_p_bi_s64:
8732       mnemonic = "ld1sh";
8733       break;
8734     case LD1SW_z_p_bi_s64:
8735       mnemonic = "ld1sw";
8736       break;
8737     case LD1W_z_p_bi_u32:
8738     case LD1W_z_p_bi_u64:
8739       mnemonic = "ld1w";
8740       break;
8741     default:
8742       form = "(SVEContiguousLoad_ScalarPlusImm)";
8743       suffix = NULL;
8744       break;
8745   }
8746 
8747   Format(instr, mnemonic, form, suffix);
8748 }
8749 
8750 void Disassembler::VisitSVEContiguousLoad_ScalarPlusScalar(
8751     const Instruction *instr) {
8752   const char *mnemonic = "unimplemented";
8753   const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns, 'Xm";
8754   const char *suffix = NULL;
8755 
8756   switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
8757     case LD1B_z_p_br_u16:
8758     case LD1B_z_p_br_u32:
8759     case LD1B_z_p_br_u64:
8760     case LD1B_z_p_br_u8:
8761       mnemonic = "ld1b";
8762       suffix = "]";
8763       break;
8764     case LD1D_z_p_br_u64:
8765       mnemonic = "ld1d";
8766       suffix = ", lsl #'u2423]";
8767       break;
8768     case LD1H_z_p_br_u16:
8769     case LD1H_z_p_br_u32:
8770     case LD1H_z_p_br_u64:
8771       mnemonic = "ld1h";
8772       suffix = ", lsl #'u2423]";
8773       break;
8774     case LD1SB_z_p_br_s16:
8775     case LD1SB_z_p_br_s32:
8776     case LD1SB_z_p_br_s64:
8777       mnemonic = "ld1sb";
8778       suffix = "]";
8779       break;
8780     case LD1SH_z_p_br_s32:
8781     case LD1SH_z_p_br_s64:
8782       mnemonic = "ld1sh";
8783       suffix = ", lsl #1]";
8784       break;
8785     case LD1SW_z_p_br_s64:
8786       mnemonic = "ld1sw";
8787       suffix = ", lsl #2]";
8788       break;
8789     case LD1W_z_p_br_u32:
8790     case LD1W_z_p_br_u64:
8791       mnemonic = "ld1w";
8792       suffix = ", lsl #'u2423]";
8793       break;
8794     default:
8795       form = "(SVEContiguousLoad_ScalarPlusScalar)";
8796       suffix = NULL;
8797       break;
8798   }
8799 
8800   Format(instr, mnemonic, form, suffix);
8801 }
8802 
8803 void Disassembler::VisitReserved(const Instruction *instr) {
8804   // UDF is the only instruction in this group, and the Decoder is precise.
8805   VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
8806   Format(instr, "udf", "'IUdf");
8807 }
8808 
8809 void Disassembler::VisitUnimplemented(const Instruction *instr) {
8810   Format(instr, "unimplemented", "(Unimplemented)");
8811 }
8812 
8813 
8814 void Disassembler::VisitUnallocated(const Instruction *instr) {
8815   Format(instr, "unallocated", "(Unallocated)");
8816 }
8817 
8818 void Disassembler::Visit(Metadata *metadata, const Instruction *instr) {
8819   VIXL_ASSERT(metadata->count("form") > 0);
8820   const std::string &form = (*metadata)["form"];
8821   const FormToVisitorFnMap *fv = Disassembler::GetFormToVisitorFnMap();
8822   if ((fv->count(form) > 0) && fv->at(form)) {
8823     form_hash_ = Hash(form.c_str());
8824     SetMnemonicFromForm(form);
8825     fv->at(form)(this, instr);
8826   } else {
8827     VisitUnimplemented(instr);
8828   }
8829 }
8830 
8831 void Disassembler::Disassemble_PdT_PgZ_ZnT_ZmT(const Instruction *instr) {
8832   const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8833   VectorFormat vform = instr->GetSVEVectorFormat();
8834 
8835   if ((vform == kFormatVnS) || (vform == kFormatVnD)) {
8836     Format(instr, "unimplemented", "(PdT_PgZ_ZnT_ZmT)");
8837   } else {
8838     Format(instr, mnemonic_.c_str(), form);
8839   }
8840 }
8841 
8842 void Disassembler::Disassemble_ZdB_Zn1B_Zn2B_imm(const Instruction *instr) {
8843   const char *form = "'Zd.b, {'Zn.b, 'Zn2.b}, #'u2016:1210";
8844   Format(instr, mnemonic_.c_str(), form);
8845 }
8846 
8847 void Disassembler::Disassemble_ZdB_ZnB_ZmB(const Instruction *instr) {
8848   const char *form = "'Zd.b, 'Zn.b, 'Zm.b";
8849   if (instr->GetSVEVectorFormat() == kFormatVnB) {
8850     Format(instr, mnemonic_.c_str(), form);
8851   } else {
8852     Format(instr, "unimplemented", "(ZdB_ZnB_ZmB)");
8853   }
8854 }
8855 
8856 void Disassembler::Disassemble_ZdD_PgM_ZnS(const Instruction *instr) {
8857   const char *form = "'Zd.d, 'Pgl/m, 'Zn.s";
8858   Format(instr, mnemonic_.c_str(), form);
8859 }
8860 
8861 void Disassembler::Disassemble_ZdD_ZnD_ZmD(const Instruction *instr) {
8862   const char *form = "'Zd.d, 'Zn.d, 'Zm.d";
8863   Format(instr, mnemonic_.c_str(), form);
8864 }
8865 
8866 void Disassembler::Disassemble_ZdD_ZnD_ZmD_imm(const Instruction *instr) {
8867   const char *form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]";
8868   Format(instr, mnemonic_.c_str(), form);
8869 }
8870 
8871 void Disassembler::Disassemble_ZdD_ZnS_ZmS_imm(const Instruction *instr) {
8872   const char *form = "'Zd.d, 'Zn.s, z'u1916.s['u2020:1111]";
8873   Format(instr, mnemonic_.c_str(), form);
8874 }
8875 
8876 void Disassembler::Disassemble_ZdH_PgM_ZnS(const Instruction *instr) {
8877   const char *form = "'Zd.h, 'Pgl/m, 'Zn.s";
8878   Format(instr, mnemonic_.c_str(), form);
8879 }
8880 
8881 void Disassembler::Disassemble_ZdH_ZnH_ZmH_imm(const Instruction *instr) {
8882   const char *form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]";
8883   Format(instr, mnemonic_.c_str(), form);
8884 }
8885 
8886 void Disassembler::Disassemble_ZdS_PgM_ZnD(const Instruction *instr) {
8887   const char *form = "'Zd.s, 'Pgl/m, 'Zn.d";
8888   Format(instr, mnemonic_.c_str(), form);
8889 }
8890 
8891 void Disassembler::Disassemble_ZdS_PgM_ZnH(const Instruction *instr) {
8892   const char *form = "'Zd.s, 'Pgl/m, 'Zn.h";
8893   Format(instr, mnemonic_.c_str(), form);
8894 }
8895 
8896 void Disassembler::Disassemble_ZdS_PgM_ZnS(const Instruction *instr) {
8897   const char *form = "'Zd.s, 'Pgl/m, 'Zn.s";
8898   if (instr->GetSVEVectorFormat() == kFormatVnS) {
8899     Format(instr, mnemonic_.c_str(), form);
8900   } else {
8901     Format(instr, "unimplemented", "(ZdS_PgM_ZnS)");
8902   }
8903 }
8904 
8905 void Disassembler::Disassemble_ZdS_ZnH_ZmH_imm(const Instruction *instr) {
8906   const char *form = "'Zd.s, 'Zn.h, z'u1816.h['u2019:1111]";
8907   Format(instr, mnemonic_.c_str(), form);
8908 }
8909 
8910 void Disassembler::Disassemble_ZdS_ZnS_ZmS(const Instruction *instr) {
8911   const char *form = "'Zd.s, 'Zn.s, 'Zm.s";
8912   Format(instr, mnemonic_.c_str(), form);
8913 }
8914 
8915 void Disassembler::Disassemble_ZdS_ZnS_ZmS_imm(const Instruction *instr) {
8916   const char *form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]";
8917   Format(instr, mnemonic_.c_str(), form);
8918 }
8919 
8920 void Disassembler::DisassembleSVEFlogb(const Instruction *instr) {
8921   const char *form = "'Zd.'tf, 'Pgl/m, 'Zn.'tf";
8922   if (instr->GetSVEVectorFormat(17) == kFormatVnB) {
8923     Format(instr, "unimplemented", "(SVEFlogb)");
8924   } else {
8925     Format(instr, mnemonic_.c_str(), form);
8926   }
8927 }
8928 
8929 void Disassembler::Disassemble_ZdT_PgM_ZnT(const Instruction *instr) {
8930   const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t";
8931   Format(instr, mnemonic_.c_str(), form);
8932 }
8933 
8934 void Disassembler::Disassemble_ZdT_PgZ_ZnT_ZmT(const Instruction *instr) {
8935   const char *form = "'Zd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t";
8936   VectorFormat vform = instr->GetSVEVectorFormat();
8937   if ((vform == kFormatVnS) || (vform == kFormatVnD)) {
8938     Format(instr, mnemonic_.c_str(), form);
8939   } else {
8940     Format(instr, "unimplemented", "(ZdT_PgZ_ZnT_ZmT)");
8941   }
8942 }
8943 
8944 void Disassembler::Disassemble_ZdT_Pg_Zn1T_Zn2T(const Instruction *instr) {
8945   const char *form = "'Zd.'t, 'Pgl, {'Zn.'t, 'Zn2.'t}";
8946   Format(instr, mnemonic_.c_str(), form);
8947 }
8948 
8949 void Disassembler::Disassemble_ZdT_Zn1T_Zn2T_ZmT(const Instruction *instr) {
8950   const char *form = "'Zd.'t, {'Zn.'t, 'Zn2.'t}, 'Zm.'t";
8951   Format(instr, mnemonic_.c_str(), form);
8952 }
8953 
8954 void Disassembler::Disassemble_ZdT_ZnT_ZmT(const Instruction *instr) {
8955   const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t";
8956   Format(instr, mnemonic_.c_str(), form);
8957 }
8958 
8959 void Disassembler::Disassemble_ZdT_ZnT_ZmTb(const Instruction *instr) {
8960   const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'th";
8961   if (instr->GetSVEVectorFormat() == kFormatVnB) {
8962     Format(instr, "unimplemented", "(ZdT_ZnT_ZmTb)");
8963   } else {
8964     Format(instr, mnemonic_.c_str(), form);
8965   }
8966 }
8967 
8968 void Disassembler::Disassemble_ZdT_ZnTb(const Instruction *instr) {
8969   const char *form = "'Zd.'tszs, 'Zn.'tszd";
8970   std::pair<int, int> shift_and_lane_size =
8971       instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
8972   int shift_dist = shift_and_lane_size.first;
8973   int lane_size = shift_and_lane_size.second;
8974   // Convert shift_dist from a right to left shift. Valid xtn instructions
8975   // must have a left shift_dist equivalent of zero.
8976   shift_dist = (8 << lane_size) - shift_dist;
8977   if ((lane_size >= static_cast<int>(kBRegSizeInBytesLog2)) &&
8978       (lane_size <= static_cast<int>(kSRegSizeInBytesLog2)) &&
8979       (shift_dist == 0)) {
8980     Format(instr, mnemonic_.c_str(), form);
8981   } else {
8982     Format(instr, "unimplemented", "(ZdT_ZnTb)");
8983   }
8984 }
8985 
8986 void Disassembler::Disassemble_ZdT_ZnTb_ZmTb(const Instruction *instr) {
8987   const char *form = "'Zd.'t, 'Zn.'th, 'Zm.'th";
8988   if (instr->GetSVEVectorFormat() == kFormatVnB) {
8989     // TODO: This is correct for saddlbt, ssublbt, subltb, which don't have
8990     // b-lane sized form, and for pmull[b|t] as feature `SVEPmull128` isn't
8991     // supported, but may need changes for other instructions reaching here.
8992     Format(instr, "unimplemented", "(ZdT_ZnTb_ZmTb)");
8993   } else {
8994     Format(instr, mnemonic_.c_str(), form);
8995   }
8996 }
8997 
8998 void Disassembler::DisassembleSVEAddSubHigh(const Instruction *instr) {
8999   const char *form = "'Zd.'th, 'Zn.'t, 'Zm.'t";
9000   if (instr->GetSVEVectorFormat() == kFormatVnB) {
9001     Format(instr, "unimplemented", "(SVEAddSubHigh)");
9002   } else {
9003     Format(instr, mnemonic_.c_str(), form);
9004   }
9005 }
9006 
9007 void Disassembler::DisassembleSVEShiftLeftImm(const Instruction *instr) {
9008   const char *form = "'Zd.'tszd, 'Zn.'tszs, 'ITriSver";
9009   std::pair<int, int> shift_and_lane_size =
9010       instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
9011   int lane_size = shift_and_lane_size.second;
9012   if ((lane_size >= static_cast<int>(kBRegSizeInBytesLog2)) &&
9013       (lane_size <= static_cast<int>(kSRegSizeInBytesLog2))) {
9014     Format(instr, mnemonic_.c_str(), form);
9015   } else {
9016     Format(instr, "unimplemented", "(SVEShiftLeftImm)");
9017   }
9018 }
9019 
9020 void Disassembler::DisassembleSVEShiftRightImm(const Instruction *instr) {
9021   const char *form = "'Zd.'tszs, 'Zn.'tszd, 'ITriSves";
9022   std::pair<int, int> shift_and_lane_size =
9023       instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
9024   int lane_size = shift_and_lane_size.second;
9025   if ((lane_size >= static_cast<int>(kBRegSizeInBytesLog2)) &&
9026       (lane_size <= static_cast<int>(kSRegSizeInBytesLog2))) {
9027     Format(instr, mnemonic_.c_str(), form);
9028   } else {
9029     Format(instr, "unimplemented", "(SVEShiftRightImm)");
9030   }
9031 }
9032 
9033 void Disassembler::Disassemble_ZdaD_ZnD_ZmD_imm(const Instruction *instr) {
9034   const char *form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]";
9035   Format(instr, mnemonic_.c_str(), form);
9036 }
9037 
9038 void Disassembler::Disassemble_ZdaD_ZnH_ZmH_imm_const(
9039     const Instruction *instr) {
9040   const char *form = "'Zd.d, 'Zn.h, z'u1916.h['u2020], #'u1110*90";
9041   Format(instr, mnemonic_.c_str(), form);
9042 }
9043 
9044 void Disassembler::Disassemble_ZdaD_ZnS_ZmS_imm(const Instruction *instr) {
9045   const char *form = "'Zd.d, 'Zn.s, z'u1916.s['u2020:1111]";
9046   Format(instr, mnemonic_.c_str(), form);
9047 }
9048 
9049 void Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm(const Instruction *instr) {
9050   const char *form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]";
9051   Format(instr, mnemonic_.c_str(), form);
9052 }
9053 
9054 void Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm_const(
9055     const Instruction *instr) {
9056   const char *form = "'Zd.h, 'Zn.h, z'u1816.h['u2019], #'u1110*90";
9057   Format(instr, mnemonic_.c_str(), form);
9058 }
9059 
9060 void Disassembler::Disassemble_ZdaS_ZnB_ZmB(const Instruction *instr) {
9061   const char *form = "'Zd.s, 'Zn.b, 'Zm.b";
9062   Format(instr, mnemonic_.c_str(), form);
9063 }
9064 
9065 void Disassembler::Disassemble_ZdaS_ZnB_ZmB_imm_const(
9066     const Instruction *instr) {
9067   const char *form = "'Zd.s, 'Zn.b, z'u1816.b['u2019], #'u1110*90";
9068   Format(instr, mnemonic_.c_str(), form);
9069 }
9070 
9071 void Disassembler::Disassemble_ZdaS_ZnH_ZmH(const Instruction *instr) {
9072   const char *form = "'Zd.s, 'Zn.h, 'Zm.h";
9073   Format(instr, mnemonic_.c_str(), form);
9074 }
9075 
9076 void Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm(const Instruction *instr) {
9077   const char *form = "'Zd.s, 'Zn.h, z'u1816.h['u2019:1111]";
9078   Format(instr, mnemonic_.c_str(), form);
9079 }
9080 
9081 void Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm(const Instruction *instr) {
9082   const char *form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]";
9083   Format(instr, mnemonic_.c_str(), form);
9084 }
9085 
9086 void Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm_const(
9087     const Instruction *instr) {
9088   const char *form = "'Zd.s, 'Zn.s, z'u1916.s['u2020], #'u1110*90";
9089   Format(instr, mnemonic_.c_str(), form);
9090 }
9091 
9092 void Disassembler::Disassemble_ZdaT_PgM_ZnTb(const Instruction *instr) {
9093   const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'th";
9094 
9095   if (instr->GetSVESize() == 0) {
9096     // The lowest lane size of the destination vector is H-sized lane.
9097     Format(instr, "unimplemented", "(Disassemble_ZdaT_PgM_ZnTb)");
9098     return;
9099   }
9100 
9101   Format(instr, mnemonic_.c_str(), form);
9102 }
9103 
9104 void Disassembler::DisassembleSVEAddSubCarry(const Instruction *instr) {
9105   const char *form = "'Zd.'?22:ds, 'Zn.'?22:ds, 'Zm.'?22:ds";
9106   Format(instr, mnemonic_.c_str(), form);
9107 }
9108 
9109 void Disassembler::Disassemble_ZdaT_ZnT_ZmT(const Instruction *instr) {
9110   const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t";
9111   Format(instr, mnemonic_.c_str(), form);
9112 }
9113 
9114 void Disassembler::Disassemble_ZdaT_ZnT_ZmT_const(const Instruction *instr) {
9115   const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t, #'u1110*90";
9116   Format(instr, mnemonic_.c_str(), form);
9117 }
9118 
9119 void Disassembler::Disassemble_ZdaT_ZnTb_ZmTb(const Instruction *instr) {
9120   const char *form = "'Zd.'t, 'Zn.'th, 'Zm.'th";
9121   if (instr->GetSVEVectorFormat() == kFormatVnB) {
9122     Format(instr, "unimplemented", "(ZdaT_ZnTb_ZmTb)");
9123   } else {
9124     Format(instr, mnemonic_.c_str(), form);
9125   }
9126 }
9127 
9128 void Disassembler::Disassemble_ZdaT_ZnTb_ZmTb_const(const Instruction *instr) {
9129   const char *form = "'Zd.'t, 'Zn.'tq, 'Zm.'tq, #'u1110*90";
9130   VectorFormat vform = instr->GetSVEVectorFormat();
9131 
9132   if ((vform == kFormatVnB) || (vform == kFormatVnH)) {
9133     Format(instr, "unimplemented", "(ZdaT_ZnTb_ZmTb_const)");
9134   } else {
9135     Format(instr, mnemonic_.c_str(), form);
9136   }
9137 }
9138 
9139 void Disassembler::Disassemble_ZdnB_ZdnB(const Instruction *instr) {
9140   const char *form = "'Zd.b, 'Zd.b";
9141   Format(instr, mnemonic_.c_str(), form);
9142 }
9143 
9144 void Disassembler::Disassemble_ZdnB_ZdnB_ZmB(const Instruction *instr) {
9145   const char *form = "'Zd.b, 'Zd.b, 'Zn.b";
9146   Format(instr, mnemonic_.c_str(), form);
9147 }
9148 
9149 void Disassembler::DisassembleSVEBitwiseTernary(const Instruction *instr) {
9150   const char *form = "'Zd.d, 'Zd.d, 'Zm.d, 'Zn.d";
9151   Format(instr, mnemonic_.c_str(), form);
9152 }
9153 
9154 void Disassembler::Disassemble_ZdnS_ZdnS_ZmS(const Instruction *instr) {
9155   const char *form = "'Zd.s, 'Zd.s, 'Zn.s";
9156   Format(instr, mnemonic_.c_str(), form);
9157 }
9158 
9159 void Disassembler::DisassembleSVEFPPair(const Instruction *instr) {
9160   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
9161   if (instr->GetSVEVectorFormat() == kFormatVnB) {
9162     Format(instr, "unimplemented", "(SVEFPPair)");
9163   } else {
9164     Format(instr, mnemonic_.c_str(), form);
9165   }
9166 }
9167 
9168 void Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT(const Instruction *instr) {
9169   const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t";
9170   Format(instr, mnemonic_.c_str(), form);
9171 }
9172 
9173 void Disassembler::DisassembleSVEComplexIntAddition(const Instruction *instr) {
9174   const char *form = "'Zd.'t, 'Zd.'t, 'Zn.'t, #";
9175   const char *suffix = (instr->ExtractBit(10) == 0) ? "90" : "270";
9176   Format(instr, mnemonic_.c_str(), form, suffix);
9177 }
9178 
9179 void Disassembler::Disassemble_ZdnT_ZdnT_ZmT_const(const Instruction *instr) {
9180   const char *form = "'Zd.'tszs, 'Zd.'tszs, 'Zn.'tszs, 'ITriSves";
9181   unsigned tsize =
9182       (instr->ExtractBits(23, 22) << 2) | instr->ExtractBits(20, 19);
9183 
9184   if (tsize == 0) {
9185     Format(instr, "unimplemented", "(ZdnT_ZdnT_ZmT_const)");
9186   } else {
9187     Format(instr, mnemonic_.c_str(), form);
9188   }
9189 }
9190 
9191 void Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm(const Instruction *instr) {
9192   const char *form = "{'Zt.d}, 'Pgl/z, ['Zn.d";
9193   const char *suffix = instr->GetRm() == 31 ? "]" : ", 'Xm]";
9194   Format(instr, mnemonic_.c_str(), form, suffix);
9195 }
9196 
9197 void Disassembler::Disassemble_ZtD_Pg_ZnD_Xm(const Instruction *instr) {
9198   const char *form = "{'Zt.d}, 'Pgl, ['Zn.d";
9199   const char *suffix = instr->GetRm() == 31 ? "]" : ", 'Xm]";
9200   Format(instr, mnemonic_.c_str(), form, suffix);
9201 }
9202 
9203 void Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm(const Instruction *instr) {
9204   const char *form = "{'Zt.s}, 'Pgl/z, ['Zn.s";
9205   const char *suffix = instr->GetRm() == 31 ? "]" : ", 'Xm]";
9206   Format(instr, mnemonic_.c_str(), form, suffix);
9207 }
9208 
9209 void Disassembler::Disassemble_ZtS_Pg_ZnS_Xm(const Instruction *instr) {
9210   const char *form = "{'Zt.s}, 'Pgl, ['Zn.s";
9211   const char *suffix = instr->GetRm() == 31 ? "]" : ", 'Xm]";
9212   Format(instr, mnemonic_.c_str(), form, suffix);
9213 }
9214 
9215 void Disassembler::ProcessOutput(const Instruction * /*instr*/) {
9216   // The base disasm does nothing more than disassembling into a buffer.
9217 }
9218 
9219 
9220 void Disassembler::AppendRegisterNameToOutput(const Instruction *instr,
9221                                               const CPURegister &reg) {
9222   USE(instr);
9223   VIXL_ASSERT(reg.IsValid());
9224   char reg_char;
9225 
9226   if (reg.IsRegister()) {
9227     reg_char = reg.Is64Bits() ? 'x' : 'w';
9228   } else {
9229     VIXL_ASSERT(reg.IsVRegister());
9230     switch (reg.GetSizeInBits()) {
9231       case kBRegSize:
9232         reg_char = 'b';
9233         break;
9234       case kHRegSize:
9235         reg_char = 'h';
9236         break;
9237       case kSRegSize:
9238         reg_char = 's';
9239         break;
9240       case kDRegSize:
9241         reg_char = 'd';
9242         break;
9243       default:
9244         VIXL_ASSERT(reg.Is128Bits());
9245         reg_char = 'q';
9246     }
9247   }
9248 
9249   if (reg.IsVRegister() || !(reg.Aliases(sp) || reg.Aliases(xzr))) {
9250     // A core or scalar/vector register: [wx]0 - 30, [bhsdq]0 - 31.
9251     AppendToOutput("%c%d", reg_char, reg.GetCode());
9252   } else if (reg.Aliases(sp)) {
9253     // Disassemble w31/x31 as stack pointer wsp/sp.
9254     AppendToOutput("%s", reg.Is64Bits() ? "sp" : "wsp");
9255   } else {
9256     // Disassemble w31/x31 as zero register wzr/xzr.
9257     AppendToOutput("%czr", reg_char);
9258   }
9259 }
9260 
9261 
9262 void Disassembler::AppendPCRelativeOffsetToOutput(const Instruction *instr,
9263                                                   int64_t offset) {
9264   USE(instr);
9265   if (offset < 0) {
9266     // Cast to uint64_t so that INT64_MIN is handled in a well-defined way.
9267     uint64_t abs_offset = -static_cast<uint64_t>(offset);
9268     AppendToOutput("#-0x%" PRIx64, abs_offset);
9269   } else {
9270     AppendToOutput("#+0x%" PRIx64, offset);
9271   }
9272 }
9273 
9274 
9275 void Disassembler::AppendAddressToOutput(const Instruction *instr,
9276                                          const void *addr) {
9277   USE(instr);
9278   AppendToOutput("(addr 0x%" PRIxPTR ")", reinterpret_cast<uintptr_t>(addr));
9279 }
9280 
9281 
9282 void Disassembler::AppendCodeAddressToOutput(const Instruction *instr,
9283                                              const void *addr) {
9284   AppendAddressToOutput(instr, addr);
9285 }
9286 
9287 
9288 void Disassembler::AppendDataAddressToOutput(const Instruction *instr,
9289                                              const void *addr) {
9290   AppendAddressToOutput(instr, addr);
9291 }
9292 
9293 
9294 void Disassembler::AppendCodeRelativeAddressToOutput(const Instruction *instr,
9295                                                      const void *addr) {
9296   USE(instr);
9297   int64_t rel_addr = CodeRelativeAddress(addr);
9298   if (rel_addr >= 0) {
9299     AppendToOutput("(addr 0x%" PRIx64 ")", rel_addr);
9300   } else {
9301     AppendToOutput("(addr -0x%" PRIx64 ")", -rel_addr);
9302   }
9303 }
9304 
9305 
9306 void Disassembler::AppendCodeRelativeCodeAddressToOutput(
9307     const Instruction *instr, const void *addr) {
9308   AppendCodeRelativeAddressToOutput(instr, addr);
9309 }
9310 
9311 
9312 void Disassembler::AppendCodeRelativeDataAddressToOutput(
9313     const Instruction *instr, const void *addr) {
9314   AppendCodeRelativeAddressToOutput(instr, addr);
9315 }
9316 
9317 
9318 void Disassembler::MapCodeAddress(int64_t base_address,
9319                                   const Instruction *instr_address) {
9320   set_code_address_offset(base_address -
9321                           reinterpret_cast<intptr_t>(instr_address));
9322 }
9323 int64_t Disassembler::CodeRelativeAddress(const void *addr) {
9324   return reinterpret_cast<intptr_t>(addr) + code_address_offset();
9325 }
9326 
9327 
9328 void Disassembler::Format(const Instruction *instr,
9329                           const char *mnemonic,
9330                           const char *format0,
9331                           const char *format1) {
9332   if ((mnemonic == NULL) || (format0 == NULL)) {
9333     VisitUnallocated(instr);
9334   } else {
9335     ResetOutput();
9336     Substitute(instr, mnemonic);
9337     if (format0[0] != 0) {  // Not a zero-length string.
9338       VIXL_ASSERT(buffer_pos_ < buffer_size_);
9339       buffer_[buffer_pos_++] = ' ';
9340       Substitute(instr, format0);
9341       // TODO: consider using a zero-length string here, too.
9342       if (format1 != NULL) {
9343         Substitute(instr, format1);
9344       }
9345     }
9346     VIXL_ASSERT(buffer_pos_ < buffer_size_);
9347     buffer_[buffer_pos_] = 0;
9348     ProcessOutput(instr);
9349   }
9350 }
9351 
9352 
9353 void Disassembler::Substitute(const Instruction *instr, const char *string) {
9354   char chr = *string++;
9355   while (chr != '\0') {
9356     if (chr == '\'') {
9357       string += SubstituteField(instr, string);
9358     } else {
9359       VIXL_ASSERT(buffer_pos_ < buffer_size_);
9360       buffer_[buffer_pos_++] = chr;
9361     }
9362     chr = *string++;
9363   }
9364 }
9365 
9366 
9367 int Disassembler::SubstituteField(const Instruction *instr,
9368                                   const char *format) {
9369   switch (format[0]) {
9370     // NB. The remaining substitution prefix upper-case characters are: JU.
9371     case 'R':  // Register. X or W, selected by sf (or alternative) bit.
9372     case 'F':  // FP register. S or D, selected by type field.
9373     case 'V':  // Vector register, V, vector format.
9374     case 'Z':  // Scalable vector register.
9375     case 'W':
9376     case 'X':
9377     case 'B':
9378     case 'H':
9379     case 'S':
9380     case 'D':
9381     case 'Q':
9382       return SubstituteRegisterField(instr, format);
9383     case 'P':
9384       return SubstitutePredicateRegisterField(instr, format);
9385     case 'I':
9386       return SubstituteImmediateField(instr, format);
9387     case 'L':
9388       return SubstituteLiteralField(instr, format);
9389     case 'N':
9390       return SubstituteShiftField(instr, format);
9391     case 'C':
9392       return SubstituteConditionField(instr, format);
9393     case 'E':
9394       return SubstituteExtendField(instr, format);
9395     case 'A':
9396       return SubstitutePCRelAddressField(instr, format);
9397     case 'T':
9398       return SubstituteBranchTargetField(instr, format);
9399     case 'O':
9400       return SubstituteLSRegOffsetField(instr, format);
9401     case 'M':
9402       return SubstituteBarrierField(instr, format);
9403     case 'K':
9404       return SubstituteCrField(instr, format);
9405     case 'G':
9406       return SubstituteSysOpField(instr, format);
9407     case 'p':
9408       return SubstitutePrefetchField(instr, format);
9409     case 'u':
9410     case 's':
9411       return SubstituteIntField(instr, format);
9412     case 't':
9413       return SubstituteSVESize(instr, format);
9414     case '?':
9415       return SubstituteTernary(instr, format);
9416     default: {
9417       VIXL_UNREACHABLE();
9418       return 1;
9419     }
9420   }
9421 }
9422 
9423 std::pair<unsigned, unsigned> Disassembler::GetRegNumForField(
9424     const Instruction *instr, char reg_prefix, const char *field) {
9425   unsigned reg_num = UINT_MAX;
9426   unsigned field_len = 1;
9427 
9428   switch (field[0]) {
9429     case 'd':
9430       reg_num = instr->GetRd();
9431       break;
9432     case 'n':
9433       reg_num = instr->GetRn();
9434       break;
9435     case 'm':
9436       reg_num = instr->GetRm();
9437       break;
9438     case 'e':
9439       // This is register Rm, but using a 4-bit specifier. Used in NEON
9440       // by-element instructions.
9441       reg_num = instr->GetRmLow16();
9442       break;
9443     case 'a':
9444       reg_num = instr->GetRa();
9445       break;
9446     case 's':
9447       reg_num = instr->GetRs();
9448       break;
9449     case 't':
9450       reg_num = instr->GetRt();
9451       break;
9452     default:
9453       VIXL_UNREACHABLE();
9454   }
9455 
9456   switch (field[1]) {
9457     case '2':
9458     case '3':
9459     case '4':
9460       if ((reg_prefix == 'V') || (reg_prefix == 'Z')) {  // t2/3/4, n2/3/4
9461         VIXL_ASSERT((field[0] == 't') || (field[0] == 'n'));
9462         reg_num = (reg_num + field[1] - '1') % 32;
9463         field_len++;
9464       } else {
9465         VIXL_ASSERT((field[0] == 't') && (field[1] == '2'));
9466         reg_num = instr->GetRt2();
9467         field_len++;
9468       }
9469       break;
9470     case '+':  // Rt+, Rs+ (ie. Rt + 1, Rs + 1)
9471       VIXL_ASSERT((reg_prefix == 'W') || (reg_prefix == 'X'));
9472       VIXL_ASSERT((field[0] == 's') || (field[0] == 't'));
9473       reg_num++;
9474       field_len++;
9475       break;
9476     case 's':  // Core registers that are (w)sp rather than zr.
9477       VIXL_ASSERT((reg_prefix == 'W') || (reg_prefix == 'X'));
9478       reg_num = (reg_num == kZeroRegCode) ? kSPRegInternalCode : reg_num;
9479       field_len++;
9480       break;
9481   }
9482 
9483   VIXL_ASSERT(reg_num != UINT_MAX);
9484   return std::make_pair(reg_num, field_len);
9485 }
9486 
9487 int Disassembler::SubstituteRegisterField(const Instruction *instr,
9488                                           const char *format) {
9489   unsigned field_len = 1;  // Initially, count only the first character.
9490 
9491   // The first character of the register format field, eg R, X, S, etc.
9492   char reg_prefix = format[0];
9493 
9494   // Pointer to the character after the prefix. This may be one of the standard
9495   // symbols representing a register encoding, or a two digit bit position,
9496   // handled by the following code.
9497   const char *reg_field = &format[1];
9498 
9499   if (reg_prefix == 'R') {
9500     bool is_x = instr->GetSixtyFourBits();
9501     if (strspn(reg_field, "0123456789") == 2) {  // r20d, r31n, etc.
9502       // Core W or X registers where the type is determined by a specified bit
9503       // position, eg. 'R20d, 'R05n. This is like the 'Rd syntax, where bit 31
9504       // is implicitly used to select between W and X.
9505       int bitpos = ((reg_field[0] - '0') * 10) + (reg_field[1] - '0');
9506       VIXL_ASSERT(bitpos <= 31);
9507       is_x = (instr->ExtractBit(bitpos) == 1);
9508       reg_field = &format[3];
9509       field_len += 2;
9510     }
9511     reg_prefix = is_x ? 'X' : 'W';
9512   }
9513 
9514   std::pair<unsigned, unsigned> rn =
9515       GetRegNumForField(instr, reg_prefix, reg_field);
9516   unsigned reg_num = rn.first;
9517   field_len += rn.second;
9518 
9519   if (reg_field[0] == 'm') {
9520     switch (reg_field[1]) {
9521       // Handle registers tagged with b (bytes), z (instruction), or
9522       // r (registers), used for address updates in NEON load/store
9523       // instructions.
9524       case 'r':
9525       case 'b':
9526       case 'z': {
9527         VIXL_ASSERT(reg_prefix == 'X');
9528         field_len = 3;
9529         char *eimm;
9530         int imm = static_cast<int>(strtol(&reg_field[2], &eimm, 10));
9531         field_len += eimm - &reg_field[2];
9532         if (reg_num == 31) {
9533           switch (reg_field[1]) {
9534             case 'z':
9535               imm *= (1 << instr->GetNEONLSSize());
9536               break;
9537             case 'r':
9538               imm *= (instr->GetNEONQ() == 0) ? kDRegSizeInBytes
9539                                               : kQRegSizeInBytes;
9540               break;
9541             case 'b':
9542               break;
9543           }
9544           AppendToOutput("#%d", imm);
9545           return field_len;
9546         }
9547         break;
9548       }
9549     }
9550   }
9551 
9552   CPURegister::RegisterType reg_type = CPURegister::kRegister;
9553   unsigned reg_size = kXRegSize;
9554 
9555   if (reg_prefix == 'F') {
9556     switch (instr->GetFPType()) {
9557       case 3:
9558         reg_prefix = 'H';
9559         break;
9560       case 0:
9561         reg_prefix = 'S';
9562         break;
9563       default:
9564         reg_prefix = 'D';
9565     }
9566   }
9567 
9568   switch (reg_prefix) {
9569     case 'W':
9570       reg_type = CPURegister::kRegister;
9571       reg_size = kWRegSize;
9572       break;
9573     case 'X':
9574       reg_type = CPURegister::kRegister;
9575       reg_size = kXRegSize;
9576       break;
9577     case 'B':
9578       reg_type = CPURegister::kVRegister;
9579       reg_size = kBRegSize;
9580       break;
9581     case 'H':
9582       reg_type = CPURegister::kVRegister;
9583       reg_size = kHRegSize;
9584       break;
9585     case 'S':
9586       reg_type = CPURegister::kVRegister;
9587       reg_size = kSRegSize;
9588       break;
9589     case 'D':
9590       reg_type = CPURegister::kVRegister;
9591       reg_size = kDRegSize;
9592       break;
9593     case 'Q':
9594       reg_type = CPURegister::kVRegister;
9595       reg_size = kQRegSize;
9596       break;
9597     case 'V':
9598       if (reg_field[1] == 'v') {
9599         reg_type = CPURegister::kVRegister;
9600         reg_size = 1 << (instr->GetSVESize() + 3);
9601         field_len++;
9602         break;
9603       }
9604       AppendToOutput("v%d", reg_num);
9605       return field_len;
9606     case 'Z':
9607       AppendToOutput("z%d", reg_num);
9608       return field_len;
9609     default:
9610       VIXL_UNREACHABLE();
9611   }
9612 
9613   AppendRegisterNameToOutput(instr, CPURegister(reg_num, reg_size, reg_type));
9614 
9615   return field_len;
9616 }
9617 
9618 int Disassembler::SubstitutePredicateRegisterField(const Instruction *instr,
9619                                                    const char *format) {
9620   VIXL_ASSERT(format[0] == 'P');
9621   switch (format[1]) {
9622     // This field only supports P register that are always encoded in the same
9623     // position.
9624     case 'd':
9625     case 't':
9626       AppendToOutput("p%u", instr->GetPt());
9627       break;
9628     case 'n':
9629       AppendToOutput("p%u", instr->GetPn());
9630       break;
9631     case 'm':
9632       AppendToOutput("p%u", instr->GetPm());
9633       break;
9634     case 'g':
9635       VIXL_ASSERT(format[2] == 'l');
9636       AppendToOutput("p%u", instr->GetPgLow8());
9637       return 3;
9638     default:
9639       VIXL_UNREACHABLE();
9640   }
9641   return 2;
9642 }
9643 
9644 int Disassembler::SubstituteImmediateField(const Instruction *instr,
9645                                            const char *format) {
9646   VIXL_ASSERT(format[0] == 'I');
9647 
9648   switch (format[1]) {
9649     case 'M': {  // IMoveImm, IMoveNeg or IMoveLSL.
9650       if (format[5] == 'L') {
9651         AppendToOutput("#0x%" PRIx32, instr->GetImmMoveWide());
9652         if (instr->GetShiftMoveWide() > 0) {
9653           AppendToOutput(", lsl #%" PRId32, 16 * instr->GetShiftMoveWide());
9654         }
9655       } else {
9656         VIXL_ASSERT((format[5] == 'I') || (format[5] == 'N'));
9657         uint64_t imm = static_cast<uint64_t>(instr->GetImmMoveWide())
9658                        << (16 * instr->GetShiftMoveWide());
9659         if (format[5] == 'N') imm = ~imm;
9660         if (!instr->GetSixtyFourBits()) imm &= UINT64_C(0xffffffff);
9661         AppendToOutput("#0x%" PRIx64, imm);
9662       }
9663       return 8;
9664     }
9665     case 'L': {
9666       switch (format[2]) {
9667         case 'L': {  // ILLiteral - Immediate Load Literal.
9668           AppendToOutput("pc%+" PRId32,
9669                          instr->GetImmLLiteral() *
9670                              static_cast<int>(kLiteralEntrySize));
9671           return 9;
9672         }
9673         case 'S': {  // ILS - Immediate Load/Store.
9674                      // ILSi - As above, but an index field which must not be
9675                      // omitted even if it is zero.
9676           bool is_index = format[3] == 'i';
9677           if (is_index || (instr->GetImmLS() != 0)) {
9678             AppendToOutput(", #%" PRId32, instr->GetImmLS());
9679           }
9680           return is_index ? 4 : 3;
9681         }
9682         case 'P': {  // ILPx - Immediate Load/Store Pair, x = access size.
9683                      // ILPxi - As above, but an index field which must not be
9684                      // omitted even if it is zero.
9685           VIXL_ASSERT((format[3] >= '0') && (format[3] <= '9'));
9686           bool is_index = format[4] == 'i';
9687           if (is_index || (instr->GetImmLSPair() != 0)) {
9688             // format[3] is the scale value. Convert to a number.
9689             int scale = 1 << (format[3] - '0');
9690             AppendToOutput(", #%" PRId32, instr->GetImmLSPair() * scale);
9691           }
9692           return is_index ? 5 : 4;
9693         }
9694         case 'U': {  // ILU - Immediate Load/Store Unsigned.
9695           if (instr->GetImmLSUnsigned() != 0) {
9696             int shift = instr->GetSizeLS();
9697             AppendToOutput(", #%" PRId32, instr->GetImmLSUnsigned() << shift);
9698           }
9699           return 3;
9700         }
9701         case 'A': {  // ILA - Immediate Load with pointer authentication.
9702           if (instr->GetImmLSPAC() != 0) {
9703             AppendToOutput(", #%" PRId32, instr->GetImmLSPAC());
9704           }
9705           return 3;
9706         }
9707         default: {
9708           VIXL_UNIMPLEMENTED();
9709           return 0;
9710         }
9711       }
9712     }
9713     case 'C': {  // ICondB - Immediate Conditional Branch.
9714       int64_t offset = instr->GetImmCondBranch() << 2;
9715       AppendPCRelativeOffsetToOutput(instr, offset);
9716       return 6;
9717     }
9718     case 'A': {  // IAddSub.
9719       int64_t imm = instr->GetImmAddSub() << (12 * instr->GetImmAddSubShift());
9720 #ifndef PANDA_BUILD
9721       AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm);
9722 #else
9723       AppendToOutput("#0x%" PRIx64 " // (%" PRId64 ")", imm, imm);
9724 #endif
9725       return 7;
9726     }
9727     case 'F': {  // IFP, IFPNeon, IFPSve or IFPFBits.
9728       int imm8 = 0;
9729       int len = strlen("IFP");
9730       switch (format[3]) {
9731         case 'F':
9732           VIXL_ASSERT(strncmp(format, "IFPFBits", strlen("IFPFBits")) == 0);
9733           AppendToOutput("#%" PRId32, 64 - instr->GetFPScale());
9734           return strlen("IFPFBits");
9735         case 'N':
9736           VIXL_ASSERT(strncmp(format, "IFPNeon", strlen("IFPNeon")) == 0);
9737           imm8 = instr->GetImmNEONabcdefgh();
9738           len += strlen("Neon");
9739           break;
9740         case 'S':
9741           VIXL_ASSERT(strncmp(format, "IFPSve", strlen("IFPSve")) == 0);
9742           imm8 = instr->ExtractBits(12, 5);
9743           len += strlen("Sve");
9744           break;
9745         default:
9746           VIXL_ASSERT(strncmp(format, "IFP", strlen("IFP")) == 0);
9747           imm8 = instr->GetImmFP();
9748           break;
9749       }
9750 #ifndef PANDA_BUILD
9751       AppendToOutput("#0x%" PRIx32 " (%.4f)",
9752 #else
9753       AppendToOutput("#0x%" PRIx32 " // (%.4f)",
9754 #endif
9755                      imm8,
9756                      Instruction::Imm8ToFP32(imm8));
9757       return len;
9758     }
9759     case 'H': {  // IH - ImmHint
9760       AppendToOutput("#%" PRId32, instr->GetImmHint());
9761       return 2;
9762     }
9763     case 'T': {  // ITri - Immediate Triangular Encoded.
9764       if (format[4] == 'S') {
9765         VIXL_ASSERT((format[5] == 'v') && (format[6] == 'e'));
9766         switch (format[7]) {
9767           case 'l':
9768             // SVE logical immediate encoding.
9769             AppendToOutput("#0x%" PRIx64, instr->GetSVEImmLogical());
9770             return 8;
9771           case 'p': {
9772             // SVE predicated shift immediate encoding, lsl.
9773             std::pair<int, int> shift_and_lane_size =
9774                 instr->GetSVEImmShiftAndLaneSizeLog2(
9775                     /* is_predicated = */ true);
9776             int lane_bits = 8 << shift_and_lane_size.second;
9777             AppendToOutput("#%" PRId32, lane_bits - shift_and_lane_size.first);
9778             return 8;
9779           }
9780           case 'q': {
9781             // SVE predicated shift immediate encoding, asr and lsr.
9782             std::pair<int, int> shift_and_lane_size =
9783                 instr->GetSVEImmShiftAndLaneSizeLog2(
9784                     /* is_predicated = */ true);
9785             AppendToOutput("#%" PRId32, shift_and_lane_size.first);
9786             return 8;
9787           }
9788           case 'r': {
9789             // SVE unpredicated shift immediate encoding, left shifts.
9790             std::pair<int, int> shift_and_lane_size =
9791                 instr->GetSVEImmShiftAndLaneSizeLog2(
9792                     /* is_predicated = */ false);
9793             int lane_bits = 8 << shift_and_lane_size.second;
9794             AppendToOutput("#%" PRId32, lane_bits - shift_and_lane_size.first);
9795             return 8;
9796           }
9797           case 's': {
9798             // SVE unpredicated shift immediate encoding, right shifts.
9799             std::pair<int, int> shift_and_lane_size =
9800                 instr->GetSVEImmShiftAndLaneSizeLog2(
9801                     /* is_predicated = */ false);
9802             AppendToOutput("#%" PRId32, shift_and_lane_size.first);
9803             return 8;
9804           }
9805           default:
9806             VIXL_UNREACHABLE();
9807             return 0;
9808         }
9809       } else {
9810         AppendToOutput("#0x%" PRIx64, instr->GetImmLogical());
9811         return 4;
9812       }
9813     }
9814     case 'N': {  // INzcv.
9815       int nzcv = (instr->GetNzcv() << Flags_offset);
9816       AppendToOutput("#%c%c%c%c",
9817                      ((nzcv & NFlag) == 0) ? 'n' : 'N',
9818                      ((nzcv & ZFlag) == 0) ? 'z' : 'Z',
9819                      ((nzcv & CFlag) == 0) ? 'c' : 'C',
9820                      ((nzcv & VFlag) == 0) ? 'v' : 'V');
9821       return 5;
9822     }
9823     case 'P': {  // IP - Conditional compare.
9824       AppendToOutput("#%" PRId32, instr->GetImmCondCmp());
9825       return 2;
9826     }
9827     case 'B': {  // Bitfields.
9828       return SubstituteBitfieldImmediateField(instr, format);
9829     }
9830     case 'E': {  // IExtract.
9831       AppendToOutput("#%" PRId32, instr->GetImmS());
9832       return 8;
9833     }
9834     case 't': {  // It - Test and branch bit.
9835       AppendToOutput("#%" PRId32,
9836                      (instr->GetImmTestBranchBit5() << 5) |
9837                          instr->GetImmTestBranchBit40());
9838       return 2;
9839     }
9840     case 'S': {  // ISveSvl - SVE 'mul vl' immediate for structured ld/st.
9841       VIXL_ASSERT(strncmp(format, "ISveSvl", 7) == 0);
9842       int imm = instr->ExtractSignedBits(19, 16);
9843       if (imm != 0) {
9844         int reg_count = instr->ExtractBits(22, 21) + 1;
9845         AppendToOutput(", #%d, mul vl", imm * reg_count);
9846       }
9847       return 7;
9848     }
9849     case 's': {  // Is - Shift (immediate).
9850       switch (format[2]) {
9851         case 'R': {  // IsR - right shifts.
9852           int shift = 16 << HighestSetBitPosition(instr->GetImmNEONImmh());
9853           shift -= instr->GetImmNEONImmhImmb();
9854           AppendToOutput("#%d", shift);
9855           return 3;
9856         }
9857         case 'L': {  // IsL - left shifts.
9858           int shift = instr->GetImmNEONImmhImmb();
9859           shift -= 8 << HighestSetBitPosition(instr->GetImmNEONImmh());
9860           AppendToOutput("#%d", shift);
9861           return 3;
9862         }
9863         default: {
9864           VIXL_UNIMPLEMENTED();
9865           return 0;
9866         }
9867       }
9868     }
9869     case 'D': {  // IDebug - HLT and BRK instructions.
9870       AppendToOutput("#0x%" PRIx32, instr->GetImmException());
9871       return 6;
9872     }
9873     case 'U': {  // IUdf - UDF immediate.
9874       AppendToOutput("#0x%" PRIx32, instr->GetImmUdf());
9875       return 4;
9876     }
9877     case 'V': {  // Immediate Vector.
9878       switch (format[2]) {
9879         case 'E': {  // IVExtract.
9880           AppendToOutput("#%" PRId32, instr->GetImmNEONExt());
9881           return 9;
9882         }
9883         case 'B': {  // IVByElemIndex.
9884           int ret = strlen("IVByElemIndex");
9885           uint32_t vm_index = instr->GetNEONH() << 2;
9886           vm_index |= instr->GetNEONL() << 1;
9887           vm_index |= instr->GetNEONM();
9888 
9889           static const char *format_rot = "IVByElemIndexRot";
9890           static const char *format_fhm = "IVByElemIndexFHM";
9891           if (strncmp(format, format_rot, strlen(format_rot)) == 0) {
9892             // FCMLA uses 'H' bit index when SIZE is 2, else H:L
9893             VIXL_ASSERT((instr->GetNEONSize() == 1) ||
9894                         (instr->GetNEONSize() == 2));
9895             vm_index >>= instr->GetNEONSize();
9896             ret = static_cast<int>(strlen(format_rot));
9897           } else if (strncmp(format, format_fhm, strlen(format_fhm)) == 0) {
9898             // Nothing to do - FMLAL and FMLSL use H:L:M.
9899             ret = static_cast<int>(strlen(format_fhm));
9900           } else {
9901             if (instr->GetNEONSize() == 2) {
9902               // S-sized elements use H:L.
9903               vm_index >>= 1;
9904             } else if (instr->GetNEONSize() == 3) {
9905               // D-sized elements use H.
9906               vm_index >>= 2;
9907             }
9908           }
9909           AppendToOutput("%d", vm_index);
9910           return ret;
9911         }
9912         case 'I': {  // INS element.
9913           if (strncmp(format, "IVInsIndex", strlen("IVInsIndex")) == 0) {
9914             unsigned rd_index, rn_index;
9915             unsigned imm5 = instr->GetImmNEON5();
9916             unsigned imm4 = instr->GetImmNEON4();
9917             int tz = CountTrailingZeros(imm5, 32);
9918             if (tz <= 3) {  // Defined for tz = 0 to 3 only.
9919               rd_index = imm5 >> (tz + 1);
9920               rn_index = imm4 >> tz;
9921               if (strncmp(format, "IVInsIndex1", strlen("IVInsIndex1")) == 0) {
9922                 AppendToOutput("%d", rd_index);
9923                 return strlen("IVInsIndex1");
9924               } else if (strncmp(format,
9925                                  "IVInsIndex2",
9926                                  strlen("IVInsIndex2")) == 0) {
9927                 AppendToOutput("%d", rn_index);
9928                 return strlen("IVInsIndex2");
9929               }
9930             }
9931             return 0;
9932           } else if (strncmp(format,
9933                              "IVInsSVEIndex",
9934                              strlen("IVInsSVEIndex")) == 0) {
9935             std::pair<int, int> index_and_lane_size =
9936                 instr->GetSVEPermuteIndexAndLaneSizeLog2();
9937             AppendToOutput("%d", index_and_lane_size.first);
9938             return strlen("IVInsSVEIndex");
9939           }
9940           VIXL_FALLTHROUGH();
9941         }
9942         case 'L': {  // IVLSLane[0123] - suffix indicates access size shift.
9943           AppendToOutput("%d", instr->GetNEONLSIndex(format[8] - '0'));
9944           return 9;
9945         }
9946         case 'M': {  // Modified Immediate cases.
9947           if (strncmp(format, "IVMIImm8", strlen("IVMIImm8")) == 0) {
9948             uint64_t imm8 = instr->GetImmNEONabcdefgh();
9949             AppendToOutput("#0x%" PRIx64, imm8);
9950             return strlen("IVMIImm8");
9951           } else if (strncmp(format, "IVMIImm", strlen("IVMIImm")) == 0) {
9952             uint64_t imm8 = instr->GetImmNEONabcdefgh();
9953             uint64_t imm = 0;
9954             for (int i = 0; i < 8; ++i) {
9955               if (imm8 & (1 << i)) {
9956                 imm |= (UINT64_C(0xff) << (8 * i));
9957               }
9958             }
9959             AppendToOutput("#0x%" PRIx64, imm);
9960             return strlen("IVMIImm");
9961           } else if (strncmp(format,
9962                              "IVMIShiftAmt1",
9963                              strlen("IVMIShiftAmt1")) == 0) {
9964             int cmode = instr->GetNEONCmode();
9965             int shift_amount = 8 * ((cmode >> 1) & 3);
9966             AppendToOutput("#%d", shift_amount);
9967             return strlen("IVMIShiftAmt1");
9968           } else if (strncmp(format,
9969                              "IVMIShiftAmt2",
9970                              strlen("IVMIShiftAmt2")) == 0) {
9971             int cmode = instr->GetNEONCmode();
9972             int shift_amount = 8 << (cmode & 1);
9973             AppendToOutput("#%d", shift_amount);
9974             return strlen("IVMIShiftAmt2");
9975           } else {
9976             VIXL_UNIMPLEMENTED();
9977             return 0;
9978           }
9979         }
9980         default: {
9981           VIXL_UNIMPLEMENTED();
9982           return 0;
9983         }
9984       }
9985     }
9986     case 'X': {  // IX - CLREX instruction.
9987       AppendToOutput("#0x%" PRIx32, instr->GetCRm());
9988       return 2;
9989     }
9990     case 'Y': {  // IY - system register immediate.
9991       switch (instr->GetImmSystemRegister()) {
9992         case NZCV:
9993           AppendToOutput("nzcv");
9994           break;
9995         case FPCR:
9996           AppendToOutput("fpcr");
9997           break;
9998         case RNDR:
9999           AppendToOutput("rndr");
10000           break;
10001         case RNDRRS:
10002           AppendToOutput("rndrrs");
10003           break;
10004         default:
10005           AppendToOutput("S%d_%d_c%d_c%d_%d",
10006                          instr->GetSysOp0(),
10007                          instr->GetSysOp1(),
10008                          instr->GetCRn(),
10009                          instr->GetCRm(),
10010                          instr->GetSysOp2());
10011           break;
10012       }
10013       return 2;
10014     }
10015     case 'R': {  // IR - Rotate right into flags.
10016       switch (format[2]) {
10017         case 'r': {  // IRr - Rotate amount.
10018           AppendToOutput("#%d", instr->GetImmRMIFRotation());
10019           return 3;
10020         }
10021         default: {
10022           VIXL_UNIMPLEMENTED();
10023           return 0;
10024         }
10025       }
10026     }
10027     case 'p': {  // Ipc - SVE predicate constraint specifier.
10028       VIXL_ASSERT(format[2] == 'c');
10029       unsigned pattern = instr->GetImmSVEPredicateConstraint();
10030       switch (pattern) {
10031         // VL1-VL8 are encoded directly.
10032         case SVE_VL1:
10033         case SVE_VL2:
10034         case SVE_VL3:
10035         case SVE_VL4:
10036         case SVE_VL5:
10037         case SVE_VL6:
10038         case SVE_VL7:
10039         case SVE_VL8:
10040           AppendToOutput("vl%u", pattern);
10041           break;
10042         // VL16-VL256 are encoded as log2(N) + c.
10043         case SVE_VL16:
10044         case SVE_VL32:
10045         case SVE_VL64:
10046         case SVE_VL128:
10047         case SVE_VL256:
10048           AppendToOutput("vl%u", 16 << (pattern - SVE_VL16));
10049           break;
10050         // Special cases.
10051         case SVE_POW2:
10052           AppendToOutput("pow2");
10053           break;
10054         case SVE_MUL4:
10055           AppendToOutput("mul4");
10056           break;
10057         case SVE_MUL3:
10058           AppendToOutput("mul3");
10059           break;
10060         case SVE_ALL:
10061           AppendToOutput("all");
10062           break;
10063         default:
10064           AppendToOutput("#0x%x", pattern);
10065           break;
10066       }
10067       return 3;
10068     }
10069     default: {
10070       VIXL_UNIMPLEMENTED();
10071       return 0;
10072     }
10073   }
10074 }
10075 
10076 
10077 int Disassembler::SubstituteBitfieldImmediateField(const Instruction *instr,
10078                                                    const char *format) {
10079   VIXL_ASSERT((format[0] == 'I') && (format[1] == 'B'));
10080   unsigned r = instr->GetImmR();
10081   unsigned s = instr->GetImmS();
10082 
10083   switch (format[2]) {
10084     case 'r': {  // IBr.
10085       AppendToOutput("#%d", r);
10086       return 3;
10087     }
10088     case 's': {  // IBs+1 or IBs-r+1.
10089       if (format[3] == '+') {
10090         AppendToOutput("#%d", s + 1);
10091         return 5;
10092       } else {
10093         VIXL_ASSERT(format[3] == '-');
10094         AppendToOutput("#%d", s - r + 1);
10095         return 7;
10096       }
10097     }
10098     case 'Z': {  // IBZ-r.
10099       VIXL_ASSERT((format[3] == '-') && (format[4] == 'r'));
10100       unsigned reg_size =
10101           (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
10102       AppendToOutput("#%d", reg_size - r);
10103       return 5;
10104     }
10105     default: {
10106       VIXL_UNREACHABLE();
10107       return 0;
10108     }
10109   }
10110 }
10111 
10112 
10113 int Disassembler::SubstituteLiteralField(const Instruction *instr,
10114                                          const char *format) {
10115   VIXL_ASSERT(strncmp(format, "LValue", 6) == 0);
10116   USE(format);
10117 
10118   const void *address = instr->GetLiteralAddress<const void *>();
10119   switch (instr->Mask(LoadLiteralMask)) {
10120     case LDR_w_lit:
10121     case LDR_x_lit:
10122     case LDRSW_x_lit:
10123     case LDR_s_lit:
10124     case LDR_d_lit:
10125     case LDR_q_lit:
10126       AppendCodeRelativeDataAddressToOutput(instr, address);
10127       break;
10128     case PRFM_lit: {
10129       // Use the prefetch hint to decide how to print the address.
10130       switch (instr->GetPrefetchHint()) {
10131         case 0x0:  // PLD: prefetch for load.
10132         case 0x2:  // PST: prepare for store.
10133           AppendCodeRelativeDataAddressToOutput(instr, address);
10134           break;
10135         case 0x1:  // PLI: preload instructions.
10136           AppendCodeRelativeCodeAddressToOutput(instr, address);
10137           break;
10138         case 0x3:  // Unallocated hint.
10139           AppendCodeRelativeAddressToOutput(instr, address);
10140           break;
10141       }
10142       break;
10143     }
10144     default:
10145       VIXL_UNREACHABLE();
10146   }
10147 
10148   return 6;
10149 }
10150 
10151 
10152 int Disassembler::SubstituteShiftField(const Instruction *instr,
10153                                        const char *format) {
10154   VIXL_ASSERT(format[0] == 'N');
10155   VIXL_ASSERT(instr->GetShiftDP() <= 0x3);
10156 
10157   switch (format[1]) {
10158     case 'D': {  // NDP.
10159       VIXL_ASSERT(instr->GetShiftDP() != ROR);
10160       VIXL_FALLTHROUGH();
10161     }
10162     case 'L': {  // NLo.
10163       if (instr->GetImmDPShift() != 0) {
10164         const char *shift_type[] = {"lsl", "lsr", "asr", "ror"};
10165         AppendToOutput(", %s #%" PRId32,
10166                        shift_type[instr->GetShiftDP()],
10167                        instr->GetImmDPShift());
10168       }
10169       return 3;
10170     }
10171     case 'S': {  // NSveS (SVE structured load/store indexing shift).
10172       VIXL_ASSERT(strncmp(format, "NSveS", 5) == 0);
10173       int msz = instr->ExtractBits(24, 23);
10174       if (msz > 0) {
10175         AppendToOutput(", lsl #%d", msz);
10176       }
10177       return 5;
10178     }
10179     default:
10180       VIXL_UNIMPLEMENTED();
10181       return 0;
10182   }
10183 }
10184 
10185 
10186 int Disassembler::SubstituteConditionField(const Instruction *instr,
10187                                            const char *format) {
10188   VIXL_ASSERT(format[0] == 'C');
10189   const char *condition_code[] = {"eq",
10190                                   "ne",
10191                                   "hs",
10192                                   "lo",
10193                                   "mi",
10194                                   "pl",
10195                                   "vs",
10196                                   "vc",
10197                                   "hi",
10198                                   "ls",
10199                                   "ge",
10200                                   "lt",
10201                                   "gt",
10202                                   "le",
10203                                   "al",
10204                                   "nv"};
10205   int cond;
10206   switch (format[1]) {
10207     case 'B':
10208       cond = instr->GetConditionBranch();
10209       break;
10210     case 'I': {
10211       cond = InvertCondition(static_cast<Condition>(instr->GetCondition()));
10212       break;
10213     }
10214     default:
10215       cond = instr->GetCondition();
10216   }
10217   AppendToOutput("%s", condition_code[cond]);
10218   return 4;
10219 }
10220 
10221 
10222 int Disassembler::SubstitutePCRelAddressField(const Instruction *instr,
10223                                               const char *format) {
10224   VIXL_ASSERT((strcmp(format, "AddrPCRelByte") == 0) ||  // Used by `adr`.
10225               (strcmp(format, "AddrPCRelPage") == 0));   // Used by `adrp`.
10226 
10227   int64_t offset = instr->GetImmPCRel();
10228 
10229   // Compute the target address based on the effective address (after applying
10230   // code_address_offset). This is required for correct behaviour of adrp.
10231   const Instruction *base = instr + code_address_offset();
10232   if (format[9] == 'P') {
10233     offset *= kPageSize;
10234     base = AlignDown(base, kPageSize);
10235   }
10236   // Strip code_address_offset before printing, so we can use the
10237   // semantically-correct AppendCodeRelativeAddressToOutput.
10238   const void *target =
10239       reinterpret_cast<const void *>(base + offset - code_address_offset());
10240 
10241   AppendPCRelativeOffsetToOutput(instr, offset);
10242   AppendToOutput(" ");
10243   AppendCodeRelativeAddressToOutput(instr, target);
10244   return 13;
10245 }
10246 
10247 
10248 int Disassembler::SubstituteBranchTargetField(const Instruction *instr,
10249                                               const char *format) {
10250   VIXL_ASSERT(strncmp(format, "TImm", 4) == 0);
10251 
10252   int64_t offset = 0;
10253   switch (format[5]) {
10254     // BImmUncn - unconditional branch immediate.
10255     case 'n':
10256       offset = instr->GetImmUncondBranch();
10257       break;
10258     // BImmCond - conditional branch immediate.
10259     case 'o':
10260       offset = instr->GetImmCondBranch();
10261       break;
10262     // BImmCmpa - compare and branch immediate.
10263     case 'm':
10264       offset = instr->GetImmCmpBranch();
10265       break;
10266     // BImmTest - test and branch immediate.
10267     case 'e':
10268       offset = instr->GetImmTestBranch();
10269       break;
10270     default:
10271       VIXL_UNIMPLEMENTED();
10272   }
10273   offset *= static_cast<int>(kInstructionSize);
10274   const void *target_address = reinterpret_cast<const void *>(instr + offset);
10275   VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
10276 
10277   AppendPCRelativeOffsetToOutput(instr, offset);
10278   AppendToOutput(" ");
10279   AppendCodeRelativeCodeAddressToOutput(instr, target_address);
10280 
10281   return 8;
10282 }
10283 
10284 
10285 int Disassembler::SubstituteExtendField(const Instruction *instr,
10286                                         const char *format) {
10287   VIXL_ASSERT(strncmp(format, "Ext", 3) == 0);
10288   VIXL_ASSERT(instr->GetExtendMode() <= 7);
10289   USE(format);
10290 
10291   const char *extend_mode[] =
10292       {"uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx"};
10293 
10294   // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit
10295   // registers becomes lsl.
10296   if (((instr->GetRd() == kZeroRegCode) || (instr->GetRn() == kZeroRegCode)) &&
10297       (((instr->GetExtendMode() == UXTW) && (instr->GetSixtyFourBits() == 0)) ||
10298        (instr->GetExtendMode() == UXTX))) {
10299     if (instr->GetImmExtendShift() > 0) {
10300       AppendToOutput(", lsl #%" PRId32, instr->GetImmExtendShift());
10301     }
10302   } else {
10303     AppendToOutput(", %s", extend_mode[instr->GetExtendMode()]);
10304     if (instr->GetImmExtendShift() > 0) {
10305       AppendToOutput(" #%" PRId32, instr->GetImmExtendShift());
10306     }
10307   }
10308   return 3;
10309 }
10310 
10311 
10312 int Disassembler::SubstituteLSRegOffsetField(const Instruction *instr,
10313                                              const char *format) {
10314   VIXL_ASSERT(strncmp(format, "Offsetreg", 9) == 0);
10315   const char *extend_mode[] = {"undefined",
10316                                "undefined",
10317                                "uxtw",
10318                                "lsl",
10319                                "undefined",
10320                                "undefined",
10321                                "sxtw",
10322                                "sxtx"};
10323   USE(format);
10324 
10325   unsigned shift = instr->GetImmShiftLS();
10326   Extend ext = static_cast<Extend>(instr->GetExtendMode());
10327   char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x';
10328 
10329   unsigned rm = instr->GetRm();
10330   if (rm == kZeroRegCode) {
10331     AppendToOutput("%czr", reg_type);
10332   } else {
10333     AppendToOutput("%c%d", reg_type, rm);
10334   }
10335 
10336   // Extend mode UXTX is an alias for shift mode LSL here.
10337   if (!((ext == UXTX) && (shift == 0))) {
10338     AppendToOutput(", %s", extend_mode[ext]);
10339     if (shift != 0) {
10340       AppendToOutput(" #%d", instr->GetSizeLS());
10341     }
10342   }
10343   return 9;
10344 }
10345 
10346 
10347 int Disassembler::SubstitutePrefetchField(const Instruction *instr,
10348                                           const char *format) {
10349   VIXL_ASSERT(format[0] == 'p');
10350   USE(format);
10351 
10352   bool is_sve =
10353       (strncmp(format, "prefSVEOp", strlen("prefSVEOp")) == 0) ? true : false;
10354   int placeholder_length = is_sve ? 9 : 6;
10355   static const char *stream_options[] = {"keep", "strm"};
10356 
10357   auto get_hints = [](bool want_sve_hint) {
10358     static std::vector<std::string> sve_hints = {"ld", "st"};
10359     static std::vector<std::string> core_hints = {"ld", "li", "st"};
10360     return (want_sve_hint) ? sve_hints : core_hints;
10361   };
10362 
10363   const auto& hints = get_hints(is_sve);
10364   unsigned hint =
10365       is_sve ? instr->GetSVEPrefetchHint() : instr->GetPrefetchHint();
10366   unsigned target = instr->GetPrefetchTarget() + 1;
10367   unsigned stream = instr->GetPrefetchStream();
10368 
10369   if ((hint >= hints.size()) || (target > 3)) {
10370     // Unallocated prefetch operations.
10371     if (is_sve) {
10372       std::bitset<4> prefetch_mode(instr->GetSVEImmPrefetchOperation());
10373       AppendToOutput("#0b%s", prefetch_mode.to_string().c_str());
10374     } else {
10375       std::bitset<5> prefetch_mode(instr->GetImmPrefetchOperation());
10376       AppendToOutput("#0b%s", prefetch_mode.to_string().c_str());
10377     }
10378   } else {
10379     VIXL_ASSERT(stream < ArrayLength(stream_options));
10380     AppendToOutput("p%sl%d%s",
10381                    hints[hint].c_str(),
10382                    target,
10383                    stream_options[stream]);
10384   }
10385   return placeholder_length;
10386 }
10387 
10388 int Disassembler::SubstituteBarrierField(const Instruction *instr,
10389                                          const char *format) {
10390   VIXL_ASSERT(format[0] == 'M');
10391   USE(format);
10392 
10393   static const char *options[4][4] = {{"sy (0b0000)", "oshld", "oshst", "osh"},
10394                                       {"sy (0b0100)", "nshld", "nshst", "nsh"},
10395                                       {"sy (0b1000)", "ishld", "ishst", "ish"},
10396                                       {"sy (0b1100)", "ld", "st", "sy"}};
10397   int domain = instr->GetImmBarrierDomain();
10398   int type = instr->GetImmBarrierType();
10399 
10400   AppendToOutput("%s", options[domain][type]);
10401   return 1;
10402 }
10403 
10404 int Disassembler::SubstituteSysOpField(const Instruction *instr,
10405                                        const char *format) {
10406   VIXL_ASSERT(format[0] == 'G');
10407   int op = -1;
10408   switch (format[1]) {
10409     case '1':
10410       op = instr->GetSysOp1();
10411       break;
10412     case '2':
10413       op = instr->GetSysOp2();
10414       break;
10415     default:
10416       VIXL_UNREACHABLE();
10417   }
10418   AppendToOutput("#%d", op);
10419   return 2;
10420 }
10421 
10422 int Disassembler::SubstituteCrField(const Instruction *instr,
10423                                     const char *format) {
10424   VIXL_ASSERT(format[0] == 'K');
10425   int cr = -1;
10426   switch (format[1]) {
10427     case 'n':
10428       cr = instr->GetCRn();
10429       break;
10430     case 'm':
10431       cr = instr->GetCRm();
10432       break;
10433     default:
10434       VIXL_UNREACHABLE();
10435   }
10436   AppendToOutput("C%d", cr);
10437   return 2;
10438 }
10439 
10440 int Disassembler::SubstituteIntField(const Instruction *instr,
10441                                      const char *format) {
10442   VIXL_ASSERT((format[0] == 'u') || (format[0] == 's'));
10443 
10444   // A generic signed or unsigned int field uses a placeholder of the form
10445   // 'sAABB and 'uAABB respectively where AA and BB are two digit bit positions
10446   // between 00 and 31, and AA >= BB. The placeholder is substituted with the
10447   // decimal integer represented by the bits in the instruction between
10448   // positions AA and BB inclusive.
10449   //
10450   // In addition, split fields can be represented using 'sAABB:CCDD, where CCDD
10451   // become the least-significant bits of the result, and bit AA is the sign bit
10452   // (if 's is used).
10453   int32_t bits = 0;
10454   int width = 0;
10455   const char *c = format;
10456   do {
10457     c++;  // Skip the 'u', 's' or ':'.
10458     VIXL_ASSERT(strspn(c, "0123456789") == 4);
10459     int msb = ((c[0] - '0') * 10) + (c[1] - '0');
10460     int lsb = ((c[2] - '0') * 10) + (c[3] - '0');
10461     c += 4;  // Skip the characters we just read.
10462     int chunk_width = msb - lsb + 1;
10463     VIXL_ASSERT((chunk_width > 0) && (chunk_width < 32));
10464     bits = (bits << chunk_width) | (instr->ExtractBits(msb, lsb));
10465     width += chunk_width;
10466   } while (*c == ':');
10467   VIXL_ASSERT(IsUintN(width, bits));
10468 
10469   if (format[0] == 's') {
10470     bits = ExtractSignedBitfield32(width - 1, 0, bits);
10471   }
10472 
10473   if (*c == '+') {
10474     // A "+n" trailing the format specifier indicates the extracted value should
10475     // be incremented by n. This is for cases where the encoding is zero-based,
10476     // but range of values is not, eg. values [1, 16] encoded as [0, 15]
10477     char *new_c;
10478     uint64_t value = strtoul(c + 1, &new_c, 10);
10479     c = new_c;
10480     VIXL_ASSERT(IsInt32(value));
10481     bits += value;
10482   } else if (*c == '*') {
10483     // Similarly, a "*n" trailing the format specifier indicates the extracted
10484     // value should be multiplied by n. This is for cases where the encoded
10485     // immediate is scaled, for example by access size.
10486     char *new_c;
10487     uint64_t value = strtoul(c + 1, &new_c, 10);
10488     c = new_c;
10489     VIXL_ASSERT(IsInt32(value));
10490     bits *= value;
10491   }
10492 
10493   AppendToOutput("%d", bits);
10494 
10495   return static_cast<int>(c - format);
10496 }
10497 
10498 int Disassembler::SubstituteSVESize(const Instruction *instr,
10499                                     const char *format) {
10500   USE(format);
10501   VIXL_ASSERT(format[0] == 't');
10502 
10503   static const char sizes[] = {'b', 'h', 's', 'd', 'q'};
10504   unsigned size_in_bytes_log2 = instr->GetSVESize();
10505   int placeholder_length = 1;
10506   switch (format[1]) {
10507     case 'f':  // 'tf - FP size encoded in <18:17>
10508       placeholder_length++;
10509       size_in_bytes_log2 = instr->ExtractBits(18, 17);
10510       break;
10511     case 'l':
10512       placeholder_length++;
10513       if (format[2] == 's') {
10514         // 'tls: Loads and stores
10515         size_in_bytes_log2 = instr->ExtractBits(22, 21);
10516         placeholder_length++;
10517         if (format[3] == 's') {
10518           // Sign extension load.
10519           unsigned msize = instr->ExtractBits(24, 23);
10520           if (msize > size_in_bytes_log2) size_in_bytes_log2 ^= 0x3;
10521           placeholder_length++;
10522         }
10523       } else {
10524         // 'tl: Logical operations
10525         size_in_bytes_log2 = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
10526       }
10527       break;
10528     case 'm':  // 'tmsz
10529       VIXL_ASSERT(strncmp(format, "tmsz", 4) == 0);
10530       placeholder_length += 3;
10531       size_in_bytes_log2 = instr->ExtractBits(24, 23);
10532       break;
10533     case 'i': {  // 'ti: indices.
10534       std::pair<int, int> index_and_lane_size =
10535           instr->GetSVEPermuteIndexAndLaneSizeLog2();
10536       placeholder_length++;
10537       size_in_bytes_log2 = index_and_lane_size.second;
10538       break;
10539     }
10540     case 's':
10541       if (format[2] == 'z') {
10542         VIXL_ASSERT((format[3] == 'p') || (format[3] == 's') ||
10543                     (format[3] == 'd'));
10544         bool is_predicated = (format[3] == 'p');
10545         std::pair<int, int> shift_and_lane_size =
10546             instr->GetSVEImmShiftAndLaneSizeLog2(is_predicated);
10547         size_in_bytes_log2 = shift_and_lane_size.second;
10548         if (format[3] == 'd') {  // Double size lanes.
10549           size_in_bytes_log2++;
10550         }
10551         placeholder_length += 3;  // skip "sz(p|s|d)"
10552       }
10553       break;
10554     case 'h':
10555       // Half size of the lane size field.
10556       size_in_bytes_log2 -= 1;
10557       placeholder_length++;
10558       break;
10559     case 'q':
10560       // Quarter size of the lane size field.
10561       size_in_bytes_log2 -= 2;
10562       placeholder_length++;
10563       break;
10564     default:
10565       break;
10566   }
10567 
10568   VIXL_ASSERT(size_in_bytes_log2 < ArrayLength(sizes));
10569   AppendToOutput("%c", sizes[size_in_bytes_log2]);
10570 
10571   return placeholder_length;
10572 }
10573 
10574 int Disassembler::SubstituteTernary(const Instruction *instr,
10575                                     const char *format) {
10576   VIXL_ASSERT((format[0] == '?') && (format[3] == ':'));
10577 
10578   // The ternary substitution of the format "'?bb:TF" is replaced by a single
10579   // character, either T or F, depending on the value of the bit at position
10580   // bb in the instruction. For example, "'?31:xw" is substituted with "x" if
10581   // bit 31 is true, and "w" otherwise.
10582   VIXL_ASSERT(strspn(&format[1], "0123456789") == 2);
10583   char *c;
10584   uint64_t value = strtoul(&format[1], &c, 10);
10585   VIXL_ASSERT(value < (kInstructionSize * kBitsPerByte));
10586   VIXL_ASSERT((*c == ':') && (strlen(c) >= 3));  // Minimum of ":TF"
10587   c++;
10588   AppendToOutput("%c", c[1 - instr->ExtractBit(static_cast<int>(value))]);
10589   return 6;
10590 }
10591 
10592 void Disassembler::ResetOutput() {
10593   buffer_pos_ = 0;
10594   buffer_[buffer_pos_] = 0;
10595 }
10596 
10597 
10598 void Disassembler::AppendToOutput(const char *format, ...) {
10599   va_list args;
10600   va_start(args, format);
10601   buffer_pos_ += vsnprintf(&buffer_[buffer_pos_],
10602                            buffer_size_ - buffer_pos_,
10603                            format,
10604                            args);
10605   va_end(args);
10606 }
10607 
10608 
10609 void PrintDisassembler::Disassemble(const Instruction *instr) {
10610 #ifndef PANDA_BUILD
10611   Decoder decoder;
10612 #else
10613   Decoder decoder(allocator_);
10614 #endif
10615   if (cpu_features_auditor_ != NULL) {
10616     decoder.AppendVisitor(cpu_features_auditor_);
10617   }
10618   decoder.AppendVisitor(this);
10619   decoder.Decode(instr);
10620 }
10621 
10622 void PrintDisassembler::DisassembleBuffer(const Instruction *start,
10623                                           const Instruction *end) {
10624 #ifndef PANDA_BUILD
10625   Decoder decoder;
10626 #else
10627   Decoder decoder(allocator_);
10628 #endif
10629 
10630   if (cpu_features_auditor_ != NULL) {
10631     decoder.AppendVisitor(cpu_features_auditor_);
10632   }
10633   decoder.AppendVisitor(this);
10634   decoder.Decode(start, end);
10635 }
10636 
10637 void PrintDisassembler::DisassembleBuffer(const Instruction *start,
10638                                           uint64_t size) {
10639   DisassembleBuffer(start, start + size);
10640 }
10641 
10642 
10643 void PrintDisassembler::ProcessOutput(const Instruction *instr) {
10644   int64_t address = CodeRelativeAddress(instr);
10645 
10646   uint64_t abs_address;
10647   const char *sign;
10648   if (signed_addresses_) {
10649     if (address < 0) {
10650       sign = "-";
10651       abs_address = -static_cast<uint64_t>(address);
10652     } else {
10653       // Leave a leading space, to maintain alignment.
10654       sign = " ";
10655       abs_address = address;
10656     }
10657   } else {
10658     sign = "";
10659     abs_address = address;
10660   }
10661 
10662   int bytes_printed = fprintf(stream_,
10663                               "%s0x%016" PRIx64 "  %08" PRIx32 "\t\t%s",
10664                               sign,
10665                               abs_address,
10666                               instr->GetInstructionBits(),
10667                               GetOutput());
10668   if (cpu_features_auditor_ != NULL) {
10669     CPUFeatures needs = cpu_features_auditor_->GetInstructionFeatures();
10670     needs.Remove(cpu_features_auditor_->GetAvailableFeatures());
10671     if (needs != CPUFeatures::None()) {
10672       // Try to align annotations. This value is arbitrary, but based on looking
10673       // good with most instructions. Note that, for historical reasons, the
10674       // disassembly itself is printed with tab characters, so bytes_printed is
10675       // _not_ equivalent to the number of occupied screen columns. However, the
10676       // prefix before the tabs is always the same length, so the annotation
10677       // indentation does not change from one line to the next.
10678       const int indent_to = 70;
10679       // Always allow some space between the instruction and the annotation.
10680       const int min_pad = 2;
10681 
10682       int pad = std::max(min_pad, (indent_to - bytes_printed));
10683       fprintf(stream_, "%*s", pad, "");
10684 
10685       std::stringstream features;
10686       features << needs;
10687       fprintf(stream_,
10688               "%s%s%s",
10689               cpu_features_prefix_,
10690               features.str().c_str(),
10691               cpu_features_suffix_);
10692     }
10693   }
10694   fprintf(stream_, "\n");
10695 }
10696 
10697 }  // namespace aarch64
10698 }  // namespace vixl
10699