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