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