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 ®) {
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(®_field[2], &eimm, 10));
6190 field_len += eimm - ®_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