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