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