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