cpu-features-auditor-aarch64.cc (68668B)
1 // Copyright 2018, 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 "cpu-features-auditor-aarch64.h" 28 29 #include "cpu-features.h" 30 #include "globals-vixl.h" 31 #include "utils-vixl.h" 32 33 #include "decoder-aarch64.h" 34 35 namespace vixl { 36 namespace aarch64 { 37 38 39 const CPUFeaturesAuditor::FormToVisitorFnMap* 40 CPUFeaturesAuditor::GetFormToVisitorFnMap() { 41 static const FormToVisitorFnMap form_to_visitor = { 42 DEFAULT_FORM_TO_VISITOR_MAP(CPUFeaturesAuditor), 43 SIM_AUD_VISITOR_MAP(CPUFeaturesAuditor), 44 {"fcmla_asimdelem_c_h"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 45 {"fcmla_asimdelem_c_s"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 46 {"fmlal2_asimdelem_lh"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 47 {"fmlal_asimdelem_lh"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 48 {"fmla_asimdelem_rh_h"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 49 {"fmla_asimdelem_r_sd"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 50 {"fmlsl2_asimdelem_lh"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 51 {"fmlsl_asimdelem_lh"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 52 {"fmls_asimdelem_rh_h"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 53 {"fmls_asimdelem_r_sd"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 54 {"fmulx_asimdelem_rh_h"_h, 55 &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 56 {"fmulx_asimdelem_r_sd"_h, 57 &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 58 {"fmul_asimdelem_rh_h"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 59 {"fmul_asimdelem_r_sd"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 60 {"sdot_asimdelem_d"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 61 {"smlal_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 62 {"smlsl_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 63 {"smull_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 64 {"sqdmlal_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 65 {"sqdmlsl_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 66 {"sqdmull_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 67 {"udot_asimdelem_d"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 68 {"umlal_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 69 {"umlsl_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 70 {"umull_asimdelem_l"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, 71 }; 72 return &form_to_visitor; 73 } 74 75 // Every instruction must update last_instruction_, even if only to clear it, 76 // and every instruction must also update seen_ once it has been fully handled. 77 // This scope makes that simple, and allows early returns in the decode logic. 78 class CPUFeaturesAuditor::RecordInstructionFeaturesScope { 79 public: 80 explicit RecordInstructionFeaturesScope(CPUFeaturesAuditor* auditor) 81 : auditor_(auditor) { 82 auditor_->last_instruction_ = CPUFeatures::None(); 83 } 84 ~RecordInstructionFeaturesScope() { 85 auditor_->seen_.Combine(auditor_->last_instruction_); 86 } 87 88 void Record(const CPUFeatures& features) { 89 auditor_->last_instruction_.Combine(features); 90 } 91 92 void Record(CPUFeatures::Feature feature0, 93 CPUFeatures::Feature feature1 = CPUFeatures::kNone, 94 CPUFeatures::Feature feature2 = CPUFeatures::kNone, 95 CPUFeatures::Feature feature3 = CPUFeatures::kNone) { 96 auditor_->last_instruction_.Combine(feature0, feature1, feature2, feature3); 97 } 98 99 // If exactly one of a or b is known to be available, record it. Otherwise, 100 // record both. This is intended for encodings that can be provided by two 101 // different features. 102 void RecordOneOrBothOf(CPUFeatures::Feature a, CPUFeatures::Feature b) { 103 bool hint_a = auditor_->available_.Has(a); 104 bool hint_b = auditor_->available_.Has(b); 105 if (hint_a && !hint_b) { 106 Record(a); 107 } else if (hint_b && !hint_a) { 108 Record(b); 109 } else { 110 Record(a, b); 111 } 112 } 113 114 private: 115 CPUFeaturesAuditor* auditor_; 116 }; 117 118 void CPUFeaturesAuditor::LoadStoreHelper(const Instruction* instr) { 119 RecordInstructionFeaturesScope scope(this); 120 switch (instr->Mask(LoadStoreMask)) { 121 case LDR_b: 122 case LDR_q: 123 case STR_b: 124 case STR_q: 125 scope.Record(CPUFeatures::kNEON); 126 return; 127 case LDR_h: 128 case LDR_s: 129 case LDR_d: 130 case STR_h: 131 case STR_s: 132 case STR_d: 133 scope.RecordOneOrBothOf(CPUFeatures::kFP, CPUFeatures::kNEON); 134 return; 135 default: 136 // No special CPU features. 137 return; 138 } 139 } 140 141 void CPUFeaturesAuditor::LoadStorePairHelper(const Instruction* instr) { 142 RecordInstructionFeaturesScope scope(this); 143 switch (instr->Mask(LoadStorePairMask)) { 144 case LDP_q: 145 case STP_q: 146 scope.Record(CPUFeatures::kNEON); 147 return; 148 case LDP_s: 149 case LDP_d: 150 case STP_s: 151 case STP_d: { 152 scope.RecordOneOrBothOf(CPUFeatures::kFP, CPUFeatures::kNEON); 153 return; 154 } 155 default: 156 // No special CPU features. 157 return; 158 } 159 } 160 161 void CPUFeaturesAuditor::VisitAddSubExtended(const Instruction* instr) { 162 RecordInstructionFeaturesScope scope(this); 163 USE(instr); 164 } 165 166 void CPUFeaturesAuditor::VisitAddSubImmediate(const Instruction* instr) { 167 RecordInstructionFeaturesScope scope(this); 168 USE(instr); 169 } 170 171 void CPUFeaturesAuditor::VisitAddSubShifted(const Instruction* instr) { 172 RecordInstructionFeaturesScope scope(this); 173 USE(instr); 174 } 175 176 void CPUFeaturesAuditor::VisitAddSubWithCarry(const Instruction* instr) { 177 RecordInstructionFeaturesScope scope(this); 178 USE(instr); 179 } 180 181 void CPUFeaturesAuditor::VisitRotateRightIntoFlags(const Instruction* instr) { 182 RecordInstructionFeaturesScope scope(this); 183 switch (instr->Mask(RotateRightIntoFlagsMask)) { 184 case RMIF: 185 scope.Record(CPUFeatures::kFlagM); 186 return; 187 } 188 } 189 190 void CPUFeaturesAuditor::VisitEvaluateIntoFlags(const Instruction* instr) { 191 RecordInstructionFeaturesScope scope(this); 192 switch (instr->Mask(EvaluateIntoFlagsMask)) { 193 case SETF8: 194 case SETF16: 195 scope.Record(CPUFeatures::kFlagM); 196 return; 197 } 198 } 199 200 void CPUFeaturesAuditor::VisitAtomicMemory(const Instruction* instr) { 201 RecordInstructionFeaturesScope scope(this); 202 switch (instr->Mask(AtomicMemoryMask)) { 203 case LDAPRB: 204 case LDAPRH: 205 case LDAPR_w: 206 case LDAPR_x: 207 scope.Record(CPUFeatures::kRCpc); 208 return; 209 default: 210 // Everything else belongs to the Atomics extension. 211 scope.Record(CPUFeatures::kAtomics); 212 return; 213 } 214 } 215 216 void CPUFeaturesAuditor::VisitBitfield(const Instruction* instr) { 217 RecordInstructionFeaturesScope scope(this); 218 USE(instr); 219 } 220 221 void CPUFeaturesAuditor::VisitCompareBranch(const Instruction* instr) { 222 RecordInstructionFeaturesScope scope(this); 223 USE(instr); 224 } 225 226 void CPUFeaturesAuditor::VisitConditionalBranch(const Instruction* instr) { 227 RecordInstructionFeaturesScope scope(this); 228 USE(instr); 229 } 230 231 void CPUFeaturesAuditor::VisitConditionalCompareImmediate( 232 const Instruction* instr) { 233 RecordInstructionFeaturesScope scope(this); 234 USE(instr); 235 } 236 237 void CPUFeaturesAuditor::VisitConditionalCompareRegister( 238 const Instruction* instr) { 239 RecordInstructionFeaturesScope scope(this); 240 USE(instr); 241 } 242 243 void CPUFeaturesAuditor::VisitConditionalSelect(const Instruction* instr) { 244 RecordInstructionFeaturesScope scope(this); 245 USE(instr); 246 } 247 248 void CPUFeaturesAuditor::VisitCrypto2RegSHA(const Instruction* instr) { 249 RecordInstructionFeaturesScope scope(this); 250 USE(instr); 251 } 252 253 void CPUFeaturesAuditor::VisitCrypto3RegSHA(const Instruction* instr) { 254 RecordInstructionFeaturesScope scope(this); 255 USE(instr); 256 } 257 258 void CPUFeaturesAuditor::VisitCryptoAES(const Instruction* instr) { 259 RecordInstructionFeaturesScope scope(this); 260 USE(instr); 261 } 262 263 void CPUFeaturesAuditor::VisitDataProcessing1Source(const Instruction* instr) { 264 RecordInstructionFeaturesScope scope(this); 265 switch (instr->Mask(DataProcessing1SourceMask)) { 266 case PACIA: 267 case PACIB: 268 case PACDA: 269 case PACDB: 270 case AUTIA: 271 case AUTIB: 272 case AUTDA: 273 case AUTDB: 274 case PACIZA: 275 case PACIZB: 276 case PACDZA: 277 case PACDZB: 278 case AUTIZA: 279 case AUTIZB: 280 case AUTDZA: 281 case AUTDZB: 282 case XPACI: 283 case XPACD: 284 scope.Record(CPUFeatures::kPAuth); 285 return; 286 default: 287 // No special CPU features. 288 return; 289 } 290 } 291 292 void CPUFeaturesAuditor::VisitDataProcessing2Source(const Instruction* instr) { 293 RecordInstructionFeaturesScope scope(this); 294 switch (instr->Mask(DataProcessing2SourceMask)) { 295 case CRC32B: 296 case CRC32H: 297 case CRC32W: 298 case CRC32X: 299 case CRC32CB: 300 case CRC32CH: 301 case CRC32CW: 302 case CRC32CX: 303 scope.Record(CPUFeatures::kCRC32); 304 return; 305 case PACGA: 306 scope.Record(CPUFeatures::kPAuth, CPUFeatures::kPAuthGeneric); 307 return; 308 default: 309 // No special CPU features. 310 return; 311 } 312 } 313 314 void CPUFeaturesAuditor::VisitLoadStoreRCpcUnscaledOffset( 315 const Instruction* instr) { 316 RecordInstructionFeaturesScope scope(this); 317 switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) { 318 case LDAPURB: 319 case LDAPURSB_w: 320 case LDAPURSB_x: 321 case LDAPURH: 322 case LDAPURSH_w: 323 case LDAPURSH_x: 324 case LDAPUR_w: 325 case LDAPURSW: 326 case LDAPUR_x: 327 328 // These stores don't actually have RCpc semantics but they're included with 329 // the RCpc extensions. 330 case STLURB: 331 case STLURH: 332 case STLUR_w: 333 case STLUR_x: 334 scope.Record(CPUFeatures::kRCpc, CPUFeatures::kRCpcImm); 335 return; 336 } 337 } 338 339 void CPUFeaturesAuditor::VisitLoadStorePAC(const Instruction* instr) { 340 RecordInstructionFeaturesScope scope(this); 341 USE(instr); 342 scope.Record(CPUFeatures::kPAuth); 343 } 344 345 void CPUFeaturesAuditor::VisitDataProcessing3Source(const Instruction* instr) { 346 RecordInstructionFeaturesScope scope(this); 347 USE(instr); 348 } 349 350 void CPUFeaturesAuditor::VisitException(const Instruction* instr) { 351 RecordInstructionFeaturesScope scope(this); 352 USE(instr); 353 } 354 355 void CPUFeaturesAuditor::VisitExtract(const Instruction* instr) { 356 RecordInstructionFeaturesScope scope(this); 357 USE(instr); 358 } 359 360 void CPUFeaturesAuditor::VisitFPCompare(const Instruction* instr) { 361 RecordInstructionFeaturesScope scope(this); 362 // All of these instructions require FP. 363 scope.Record(CPUFeatures::kFP); 364 switch (instr->Mask(FPCompareMask)) { 365 case FCMP_h: 366 case FCMP_h_zero: 367 case FCMPE_h: 368 case FCMPE_h_zero: 369 scope.Record(CPUFeatures::kFPHalf); 370 return; 371 default: 372 // No special CPU features. 373 return; 374 } 375 } 376 377 void CPUFeaturesAuditor::VisitFPConditionalCompare(const Instruction* instr) { 378 RecordInstructionFeaturesScope scope(this); 379 // All of these instructions require FP. 380 scope.Record(CPUFeatures::kFP); 381 switch (instr->Mask(FPConditionalCompareMask)) { 382 case FCCMP_h: 383 case FCCMPE_h: 384 scope.Record(CPUFeatures::kFPHalf); 385 return; 386 default: 387 // No special CPU features. 388 return; 389 } 390 } 391 392 void CPUFeaturesAuditor::VisitFPConditionalSelect(const Instruction* instr) { 393 RecordInstructionFeaturesScope scope(this); 394 // All of these instructions require FP. 395 scope.Record(CPUFeatures::kFP); 396 if (instr->Mask(FPConditionalSelectMask) == FCSEL_h) { 397 scope.Record(CPUFeatures::kFPHalf); 398 } 399 } 400 401 void CPUFeaturesAuditor::VisitFPDataProcessing1Source( 402 const Instruction* instr) { 403 RecordInstructionFeaturesScope scope(this); 404 // All of these instructions require FP. 405 scope.Record(CPUFeatures::kFP); 406 switch (instr->Mask(FPDataProcessing1SourceMask)) { 407 case FMOV_h: 408 case FABS_h: 409 case FNEG_h: 410 case FSQRT_h: 411 case FRINTN_h: 412 case FRINTP_h: 413 case FRINTM_h: 414 case FRINTZ_h: 415 case FRINTA_h: 416 case FRINTX_h: 417 case FRINTI_h: 418 scope.Record(CPUFeatures::kFPHalf); 419 return; 420 case FRINT32X_s: 421 case FRINT32X_d: 422 case FRINT32Z_s: 423 case FRINT32Z_d: 424 case FRINT64X_s: 425 case FRINT64X_d: 426 case FRINT64Z_s: 427 case FRINT64Z_d: 428 scope.Record(CPUFeatures::kFrintToFixedSizedInt); 429 return; 430 default: 431 // No special CPU features. 432 // This category includes some half-precision FCVT instructions that do 433 // not require FPHalf. 434 return; 435 } 436 } 437 438 void CPUFeaturesAuditor::VisitFPDataProcessing2Source( 439 const Instruction* instr) { 440 RecordInstructionFeaturesScope scope(this); 441 // All of these instructions require FP. 442 scope.Record(CPUFeatures::kFP); 443 switch (instr->Mask(FPDataProcessing2SourceMask)) { 444 case FMUL_h: 445 case FDIV_h: 446 case FADD_h: 447 case FSUB_h: 448 case FMAX_h: 449 case FMIN_h: 450 case FMAXNM_h: 451 case FMINNM_h: 452 case FNMUL_h: 453 scope.Record(CPUFeatures::kFPHalf); 454 return; 455 default: 456 // No special CPU features. 457 return; 458 } 459 } 460 461 void CPUFeaturesAuditor::VisitFPDataProcessing3Source( 462 const Instruction* instr) { 463 RecordInstructionFeaturesScope scope(this); 464 // All of these instructions require FP. 465 scope.Record(CPUFeatures::kFP); 466 switch (instr->Mask(FPDataProcessing3SourceMask)) { 467 case FMADD_h: 468 case FMSUB_h: 469 case FNMADD_h: 470 case FNMSUB_h: 471 scope.Record(CPUFeatures::kFPHalf); 472 return; 473 default: 474 // No special CPU features. 475 return; 476 } 477 } 478 479 void CPUFeaturesAuditor::VisitFPFixedPointConvert(const Instruction* instr) { 480 RecordInstructionFeaturesScope scope(this); 481 // All of these instructions require FP. 482 scope.Record(CPUFeatures::kFP); 483 switch (instr->Mask(FPFixedPointConvertMask)) { 484 case FCVTZS_wh_fixed: 485 case FCVTZS_xh_fixed: 486 case FCVTZU_wh_fixed: 487 case FCVTZU_xh_fixed: 488 case SCVTF_hw_fixed: 489 case SCVTF_hx_fixed: 490 case UCVTF_hw_fixed: 491 case UCVTF_hx_fixed: 492 scope.Record(CPUFeatures::kFPHalf); 493 return; 494 default: 495 // No special CPU features. 496 return; 497 } 498 } 499 500 void CPUFeaturesAuditor::VisitFPImmediate(const Instruction* instr) { 501 RecordInstructionFeaturesScope scope(this); 502 // All of these instructions require FP. 503 scope.Record(CPUFeatures::kFP); 504 if (instr->Mask(FPImmediateMask) == FMOV_h_imm) { 505 scope.Record(CPUFeatures::kFPHalf); 506 } 507 } 508 509 void CPUFeaturesAuditor::VisitFPIntegerConvert(const Instruction* instr) { 510 RecordInstructionFeaturesScope scope(this); 511 switch (instr->Mask(FPIntegerConvertMask)) { 512 case FCVTAS_wh: 513 case FCVTAS_xh: 514 case FCVTAU_wh: 515 case FCVTAU_xh: 516 case FCVTMS_wh: 517 case FCVTMS_xh: 518 case FCVTMU_wh: 519 case FCVTMU_xh: 520 case FCVTNS_wh: 521 case FCVTNS_xh: 522 case FCVTNU_wh: 523 case FCVTNU_xh: 524 case FCVTPS_wh: 525 case FCVTPS_xh: 526 case FCVTPU_wh: 527 case FCVTPU_xh: 528 case FCVTZS_wh: 529 case FCVTZS_xh: 530 case FCVTZU_wh: 531 case FCVTZU_xh: 532 case FMOV_hw: 533 case FMOV_hx: 534 case FMOV_wh: 535 case FMOV_xh: 536 case SCVTF_hw: 537 case SCVTF_hx: 538 case UCVTF_hw: 539 case UCVTF_hx: 540 scope.Record(CPUFeatures::kFP); 541 scope.Record(CPUFeatures::kFPHalf); 542 return; 543 case FMOV_dx: 544 scope.RecordOneOrBothOf(CPUFeatures::kFP, CPUFeatures::kNEON); 545 return; 546 case FMOV_d1_x: 547 case FMOV_x_d1: 548 scope.Record(CPUFeatures::kFP); 549 scope.Record(CPUFeatures::kNEON); 550 return; 551 case FJCVTZS: 552 scope.Record(CPUFeatures::kFP); 553 scope.Record(CPUFeatures::kJSCVT); 554 return; 555 default: 556 scope.Record(CPUFeatures::kFP); 557 return; 558 } 559 } 560 561 void CPUFeaturesAuditor::VisitLoadLiteral(const Instruction* instr) { 562 RecordInstructionFeaturesScope scope(this); 563 switch (instr->Mask(LoadLiteralMask)) { 564 case LDR_s_lit: 565 case LDR_d_lit: 566 scope.RecordOneOrBothOf(CPUFeatures::kFP, CPUFeatures::kNEON); 567 return; 568 case LDR_q_lit: 569 scope.Record(CPUFeatures::kNEON); 570 return; 571 default: 572 // No special CPU features. 573 return; 574 } 575 } 576 577 void CPUFeaturesAuditor::VisitLoadStoreExclusive(const Instruction* instr) { 578 RecordInstructionFeaturesScope scope(this); 579 switch (instr->Mask(LoadStoreExclusiveMask)) { 580 case CAS_w: 581 case CASA_w: 582 case CASL_w: 583 case CASAL_w: 584 case CAS_x: 585 case CASA_x: 586 case CASL_x: 587 case CASAL_x: 588 case CASB: 589 case CASAB: 590 case CASLB: 591 case CASALB: 592 case CASH: 593 case CASAH: 594 case CASLH: 595 case CASALH: 596 case CASP_w: 597 case CASPA_w: 598 case CASPL_w: 599 case CASPAL_w: 600 case CASP_x: 601 case CASPA_x: 602 case CASPL_x: 603 case CASPAL_x: 604 scope.Record(CPUFeatures::kAtomics); 605 return; 606 case STLLRB: 607 case LDLARB: 608 case STLLRH: 609 case LDLARH: 610 case STLLR_w: 611 case LDLAR_w: 612 case STLLR_x: 613 case LDLAR_x: 614 scope.Record(CPUFeatures::kLORegions); 615 return; 616 default: 617 // No special CPU features. 618 return; 619 } 620 } 621 622 void CPUFeaturesAuditor::VisitLoadStorePairNonTemporal( 623 const Instruction* instr) { 624 LoadStorePairHelper(instr); 625 } 626 627 void CPUFeaturesAuditor::VisitLoadStorePairOffset(const Instruction* instr) { 628 LoadStorePairHelper(instr); 629 } 630 631 void CPUFeaturesAuditor::VisitLoadStorePairPostIndex(const Instruction* instr) { 632 LoadStorePairHelper(instr); 633 } 634 635 void CPUFeaturesAuditor::VisitLoadStorePairPreIndex(const Instruction* instr) { 636 LoadStorePairHelper(instr); 637 } 638 639 void CPUFeaturesAuditor::VisitLoadStorePostIndex(const Instruction* instr) { 640 LoadStoreHelper(instr); 641 } 642 643 void CPUFeaturesAuditor::VisitLoadStorePreIndex(const Instruction* instr) { 644 LoadStoreHelper(instr); 645 } 646 647 void CPUFeaturesAuditor::VisitLoadStoreRegisterOffset( 648 const Instruction* instr) { 649 LoadStoreHelper(instr); 650 } 651 652 void CPUFeaturesAuditor::VisitLoadStoreUnscaledOffset( 653 const Instruction* instr) { 654 LoadStoreHelper(instr); 655 } 656 657 void CPUFeaturesAuditor::VisitLoadStoreUnsignedOffset( 658 const Instruction* instr) { 659 LoadStoreHelper(instr); 660 } 661 662 void CPUFeaturesAuditor::VisitLogicalImmediate(const Instruction* instr) { 663 RecordInstructionFeaturesScope scope(this); 664 USE(instr); 665 } 666 667 void CPUFeaturesAuditor::VisitLogicalShifted(const Instruction* instr) { 668 RecordInstructionFeaturesScope scope(this); 669 USE(instr); 670 } 671 672 void CPUFeaturesAuditor::VisitMoveWideImmediate(const Instruction* instr) { 673 RecordInstructionFeaturesScope scope(this); 674 USE(instr); 675 } 676 677 void CPUFeaturesAuditor::VisitNEON2RegMisc(const Instruction* instr) { 678 RecordInstructionFeaturesScope scope(this); 679 // All of these instructions require NEON. 680 scope.Record(CPUFeatures::kNEON); 681 switch (instr->Mask(NEON2RegMiscFPMask)) { 682 case NEON_FABS: 683 case NEON_FNEG: 684 case NEON_FSQRT: 685 case NEON_FCVTL: 686 case NEON_FCVTN: 687 case NEON_FCVTXN: 688 case NEON_FRINTI: 689 case NEON_FRINTX: 690 case NEON_FRINTA: 691 case NEON_FRINTM: 692 case NEON_FRINTN: 693 case NEON_FRINTP: 694 case NEON_FRINTZ: 695 case NEON_FCVTNS: 696 case NEON_FCVTNU: 697 case NEON_FCVTPS: 698 case NEON_FCVTPU: 699 case NEON_FCVTMS: 700 case NEON_FCVTMU: 701 case NEON_FCVTZS: 702 case NEON_FCVTZU: 703 case NEON_FCVTAS: 704 case NEON_FCVTAU: 705 case NEON_SCVTF: 706 case NEON_UCVTF: 707 case NEON_FRSQRTE: 708 case NEON_FRECPE: 709 case NEON_FCMGT_zero: 710 case NEON_FCMGE_zero: 711 case NEON_FCMEQ_zero: 712 case NEON_FCMLE_zero: 713 case NEON_FCMLT_zero: 714 scope.Record(CPUFeatures::kFP); 715 return; 716 case NEON_FRINT32X: 717 case NEON_FRINT32Z: 718 case NEON_FRINT64X: 719 case NEON_FRINT64Z: 720 scope.Record(CPUFeatures::kFP, CPUFeatures::kFrintToFixedSizedInt); 721 return; 722 default: 723 // No additional features. 724 return; 725 } 726 } 727 728 void CPUFeaturesAuditor::VisitNEON2RegMiscFP16(const Instruction* instr) { 729 RecordInstructionFeaturesScope scope(this); 730 // All of these instructions require NEONHalf. 731 scope.Record(CPUFeatures::kFP, CPUFeatures::kNEON, CPUFeatures::kNEONHalf); 732 USE(instr); 733 } 734 735 void CPUFeaturesAuditor::VisitNEON3Different(const Instruction* instr) { 736 RecordInstructionFeaturesScope scope(this); 737 // All of these instructions require NEON. 738 scope.Record(CPUFeatures::kNEON); 739 if (form_hash_ == "pmull_asimddiff_l"_h) { 740 if (instr->GetNEONSize() == 3) { 741 // Source is 1D or 2D, destination is 1Q. 742 scope.Record(CPUFeatures::kPmull1Q); 743 } 744 } 745 USE(instr); 746 } 747 748 void CPUFeaturesAuditor::VisitNEON3Same(const Instruction* instr) { 749 RecordInstructionFeaturesScope scope(this); 750 // All of these instructions require NEON. 751 scope.Record(CPUFeatures::kNEON); 752 if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) { 753 scope.Record(CPUFeatures::kFP); 754 } 755 switch (instr->Mask(NEON3SameFHMMask)) { 756 case NEON_FMLAL: 757 case NEON_FMLAL2: 758 case NEON_FMLSL: 759 case NEON_FMLSL2: 760 scope.Record(CPUFeatures::kFP, CPUFeatures::kNEONHalf, CPUFeatures::kFHM); 761 return; 762 default: 763 // No additional features. 764 return; 765 } 766 } 767 768 void CPUFeaturesAuditor::VisitNEON3SameExtra(const Instruction* instr) { 769 RecordInstructionFeaturesScope scope(this); 770 // All of these instructions require NEON. 771 scope.Record(CPUFeatures::kNEON); 772 if ((instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) || 773 (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD)) { 774 scope.Record(CPUFeatures::kFP, CPUFeatures::kFcma); 775 if (instr->GetNEONSize() == 1) scope.Record(CPUFeatures::kNEONHalf); 776 } else { 777 switch (instr->Mask(NEON3SameExtraMask)) { 778 case NEON_SDOT: 779 case NEON_UDOT: 780 scope.Record(CPUFeatures::kDotProduct); 781 return; 782 case NEON_SQRDMLAH: 783 case NEON_SQRDMLSH: 784 scope.Record(CPUFeatures::kRDM); 785 return; 786 default: 787 // No additional features. 788 return; 789 } 790 } 791 } 792 793 void CPUFeaturesAuditor::VisitNEON3SameFP16(const Instruction* instr) { 794 RecordInstructionFeaturesScope scope(this); 795 // All of these instructions require NEON FP16 support. 796 scope.Record(CPUFeatures::kFP, CPUFeatures::kNEON, CPUFeatures::kNEONHalf); 797 USE(instr); 798 } 799 800 void CPUFeaturesAuditor::VisitNEONAcrossLanes(const Instruction* instr) { 801 RecordInstructionFeaturesScope scope(this); 802 // All of these instructions require NEON. 803 scope.Record(CPUFeatures::kNEON); 804 if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) { 805 // FMAXV_H, FMINV_H, FMAXNMV_H, FMINNMV_H 806 scope.Record(CPUFeatures::kFP, CPUFeatures::kNEONHalf); 807 } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) { 808 // FMAXV, FMINV, FMAXNMV, FMINNMV 809 scope.Record(CPUFeatures::kFP); 810 } 811 } 812 813 void CPUFeaturesAuditor::VisitNEONByIndexedElement(const Instruction* instr) { 814 RecordInstructionFeaturesScope scope(this); 815 // All of these instructions require NEON. 816 scope.Record(CPUFeatures::kNEON); 817 switch (instr->Mask(NEONByIndexedElementMask)) { 818 case NEON_SDOT_byelement: 819 case NEON_UDOT_byelement: 820 scope.Record(CPUFeatures::kDotProduct); 821 return; 822 case NEON_SQRDMLAH_byelement: 823 case NEON_SQRDMLSH_byelement: 824 scope.Record(CPUFeatures::kRDM); 825 return; 826 default: 827 // Fall through to check other instructions. 828 break; 829 } 830 switch (instr->Mask(NEONByIndexedElementFPLongMask)) { 831 case NEON_FMLAL_H_byelement: 832 case NEON_FMLAL2_H_byelement: 833 case NEON_FMLSL_H_byelement: 834 case NEON_FMLSL2_H_byelement: 835 scope.Record(CPUFeatures::kFP, CPUFeatures::kNEONHalf, CPUFeatures::kFHM); 836 return; 837 default: 838 // Fall through to check other instructions. 839 break; 840 } 841 switch (instr->Mask(NEONByIndexedElementFPMask)) { 842 case NEON_FMLA_H_byelement: 843 case NEON_FMLS_H_byelement: 844 case NEON_FMUL_H_byelement: 845 case NEON_FMULX_H_byelement: 846 scope.Record(CPUFeatures::kNEONHalf); 847 VIXL_FALLTHROUGH(); 848 case NEON_FMLA_byelement: 849 case NEON_FMLS_byelement: 850 case NEON_FMUL_byelement: 851 case NEON_FMULX_byelement: 852 scope.Record(CPUFeatures::kFP); 853 return; 854 default: 855 switch (instr->Mask(NEONByIndexedElementFPComplexMask)) { 856 case NEON_FCMLA_byelement: 857 scope.Record(CPUFeatures::kFP, CPUFeatures::kFcma); 858 if (instr->GetNEONSize() == 1) scope.Record(CPUFeatures::kNEONHalf); 859 return; 860 } 861 // No additional features. 862 return; 863 } 864 } 865 866 void CPUFeaturesAuditor::VisitNEONCopy(const Instruction* instr) { 867 RecordInstructionFeaturesScope scope(this); 868 // All of these instructions require NEON. 869 scope.Record(CPUFeatures::kNEON); 870 USE(instr); 871 } 872 873 void CPUFeaturesAuditor::VisitNEONExtract(const Instruction* instr) { 874 RecordInstructionFeaturesScope scope(this); 875 // All of these instructions require NEON. 876 scope.Record(CPUFeatures::kNEON); 877 USE(instr); 878 } 879 880 void CPUFeaturesAuditor::VisitNEONLoadStoreMultiStruct( 881 const Instruction* instr) { 882 RecordInstructionFeaturesScope scope(this); 883 // All of these instructions require NEON. 884 scope.Record(CPUFeatures::kNEON); 885 USE(instr); 886 } 887 888 void CPUFeaturesAuditor::VisitNEONLoadStoreMultiStructPostIndex( 889 const Instruction* instr) { 890 RecordInstructionFeaturesScope scope(this); 891 // All of these instructions require NEON. 892 scope.Record(CPUFeatures::kNEON); 893 USE(instr); 894 } 895 896 void CPUFeaturesAuditor::VisitNEONLoadStoreSingleStruct( 897 const Instruction* instr) { 898 RecordInstructionFeaturesScope scope(this); 899 // All of these instructions require NEON. 900 scope.Record(CPUFeatures::kNEON); 901 USE(instr); 902 } 903 904 void CPUFeaturesAuditor::VisitNEONLoadStoreSingleStructPostIndex( 905 const Instruction* instr) { 906 RecordInstructionFeaturesScope scope(this); 907 // All of these instructions require NEON. 908 scope.Record(CPUFeatures::kNEON); 909 USE(instr); 910 } 911 912 void CPUFeaturesAuditor::VisitNEONModifiedImmediate(const Instruction* instr) { 913 RecordInstructionFeaturesScope scope(this); 914 // All of these instructions require NEON. 915 scope.Record(CPUFeatures::kNEON); 916 if (instr->GetNEONCmode() == 0xf) { 917 // FMOV (vector, immediate), double-, single- or half-precision. 918 scope.Record(CPUFeatures::kFP); 919 if (instr->ExtractBit(11)) scope.Record(CPUFeatures::kNEONHalf); 920 } 921 } 922 923 void CPUFeaturesAuditor::VisitNEONPerm(const Instruction* instr) { 924 RecordInstructionFeaturesScope scope(this); 925 // All of these instructions require NEON. 926 scope.Record(CPUFeatures::kNEON); 927 USE(instr); 928 } 929 930 void CPUFeaturesAuditor::VisitNEONScalar2RegMisc(const Instruction* instr) { 931 RecordInstructionFeaturesScope scope(this); 932 // All of these instructions require NEON. 933 scope.Record(CPUFeatures::kNEON); 934 switch (instr->Mask(NEONScalar2RegMiscFPMask)) { 935 case NEON_FRECPE_scalar: 936 case NEON_FRECPX_scalar: 937 case NEON_FRSQRTE_scalar: 938 case NEON_FCMGT_zero_scalar: 939 case NEON_FCMGE_zero_scalar: 940 case NEON_FCMEQ_zero_scalar: 941 case NEON_FCMLE_zero_scalar: 942 case NEON_FCMLT_zero_scalar: 943 case NEON_SCVTF_scalar: 944 case NEON_UCVTF_scalar: 945 case NEON_FCVTNS_scalar: 946 case NEON_FCVTNU_scalar: 947 case NEON_FCVTPS_scalar: 948 case NEON_FCVTPU_scalar: 949 case NEON_FCVTMS_scalar: 950 case NEON_FCVTMU_scalar: 951 case NEON_FCVTZS_scalar: 952 case NEON_FCVTZU_scalar: 953 case NEON_FCVTAS_scalar: 954 case NEON_FCVTAU_scalar: 955 case NEON_FCVTXN_scalar: 956 scope.Record(CPUFeatures::kFP); 957 return; 958 default: 959 // No additional features. 960 return; 961 } 962 } 963 964 void CPUFeaturesAuditor::VisitNEONScalar2RegMiscFP16(const Instruction* instr) { 965 RecordInstructionFeaturesScope scope(this); 966 // All of these instructions require NEONHalf. 967 scope.Record(CPUFeatures::kFP, CPUFeatures::kNEON, CPUFeatures::kNEONHalf); 968 USE(instr); 969 } 970 971 void CPUFeaturesAuditor::VisitNEONScalar3Diff(const Instruction* instr) { 972 RecordInstructionFeaturesScope scope(this); 973 // All of these instructions require NEON. 974 scope.Record(CPUFeatures::kNEON); 975 USE(instr); 976 } 977 978 void CPUFeaturesAuditor::VisitNEONScalar3Same(const Instruction* instr) { 979 RecordInstructionFeaturesScope scope(this); 980 // All of these instructions require NEON. 981 scope.Record(CPUFeatures::kNEON); 982 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) { 983 scope.Record(CPUFeatures::kFP); 984 } 985 } 986 987 void CPUFeaturesAuditor::VisitNEONScalar3SameExtra(const Instruction* instr) { 988 RecordInstructionFeaturesScope scope(this); 989 // All of these instructions require NEON and RDM. 990 scope.Record(CPUFeatures::kNEON, CPUFeatures::kRDM); 991 USE(instr); 992 } 993 994 void CPUFeaturesAuditor::VisitNEONScalar3SameFP16(const Instruction* instr) { 995 RecordInstructionFeaturesScope scope(this); 996 // All of these instructions require NEONHalf. 997 scope.Record(CPUFeatures::kFP, CPUFeatures::kNEON, CPUFeatures::kNEONHalf); 998 USE(instr); 999 } 1000 1001 void CPUFeaturesAuditor::VisitNEONScalarByIndexedElement( 1002 const Instruction* instr) { 1003 RecordInstructionFeaturesScope scope(this); 1004 // All of these instructions require NEON. 1005 scope.Record(CPUFeatures::kNEON); 1006 switch (instr->Mask(NEONScalarByIndexedElementMask)) { 1007 case NEON_SQRDMLAH_byelement_scalar: 1008 case NEON_SQRDMLSH_byelement_scalar: 1009 scope.Record(CPUFeatures::kRDM); 1010 return; 1011 default: 1012 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) { 1013 case NEON_FMLA_H_byelement_scalar: 1014 case NEON_FMLS_H_byelement_scalar: 1015 case NEON_FMUL_H_byelement_scalar: 1016 case NEON_FMULX_H_byelement_scalar: 1017 scope.Record(CPUFeatures::kNEONHalf); 1018 VIXL_FALLTHROUGH(); 1019 case NEON_FMLA_byelement_scalar: 1020 case NEON_FMLS_byelement_scalar: 1021 case NEON_FMUL_byelement_scalar: 1022 case NEON_FMULX_byelement_scalar: 1023 scope.Record(CPUFeatures::kFP); 1024 return; 1025 } 1026 // No additional features. 1027 return; 1028 } 1029 } 1030 1031 void CPUFeaturesAuditor::VisitNEONScalarCopy(const Instruction* instr) { 1032 RecordInstructionFeaturesScope scope(this); 1033 // All of these instructions require NEON. 1034 scope.Record(CPUFeatures::kNEON); 1035 USE(instr); 1036 } 1037 1038 void CPUFeaturesAuditor::VisitNEONScalarPairwise(const Instruction* instr) { 1039 RecordInstructionFeaturesScope scope(this); 1040 // All of these instructions require NEON. 1041 scope.Record(CPUFeatures::kNEON); 1042 switch (instr->Mask(NEONScalarPairwiseMask)) { 1043 case NEON_FMAXNMP_h_scalar: 1044 case NEON_FADDP_h_scalar: 1045 case NEON_FMAXP_h_scalar: 1046 case NEON_FMINNMP_h_scalar: 1047 case NEON_FMINP_h_scalar: 1048 scope.Record(CPUFeatures::kNEONHalf); 1049 VIXL_FALLTHROUGH(); 1050 case NEON_FADDP_scalar: 1051 case NEON_FMAXP_scalar: 1052 case NEON_FMAXNMP_scalar: 1053 case NEON_FMINP_scalar: 1054 case NEON_FMINNMP_scalar: 1055 scope.Record(CPUFeatures::kFP); 1056 return; 1057 default: 1058 // No additional features. 1059 return; 1060 } 1061 } 1062 1063 void CPUFeaturesAuditor::VisitNEONScalarShiftImmediate( 1064 const Instruction* instr) { 1065 RecordInstructionFeaturesScope scope(this); 1066 // All of these instructions require NEON. 1067 scope.Record(CPUFeatures::kNEON); 1068 switch (instr->Mask(NEONScalarShiftImmediateMask)) { 1069 case NEON_FCVTZS_imm_scalar: 1070 case NEON_FCVTZU_imm_scalar: 1071 case NEON_SCVTF_imm_scalar: 1072 case NEON_UCVTF_imm_scalar: 1073 scope.Record(CPUFeatures::kFP); 1074 // If immh is 0b001x then the data type is FP16, and requires kNEONHalf. 1075 if ((instr->GetImmNEONImmh() & 0xe) == 0x2) { 1076 scope.Record(CPUFeatures::kNEONHalf); 1077 } 1078 return; 1079 default: 1080 // No additional features. 1081 return; 1082 } 1083 } 1084 1085 void CPUFeaturesAuditor::VisitNEONShiftImmediate(const Instruction* instr) { 1086 RecordInstructionFeaturesScope scope(this); 1087 // All of these instructions require NEON. 1088 scope.Record(CPUFeatures::kNEON); 1089 switch (instr->Mask(NEONShiftImmediateMask)) { 1090 case NEON_SCVTF_imm: 1091 case NEON_UCVTF_imm: 1092 case NEON_FCVTZS_imm: 1093 case NEON_FCVTZU_imm: 1094 scope.Record(CPUFeatures::kFP); 1095 // If immh is 0b001x then the data type is FP16, and requires kNEONHalf. 1096 if ((instr->GetImmNEONImmh() & 0xe) == 0x2) { 1097 scope.Record(CPUFeatures::kNEONHalf); 1098 } 1099 return; 1100 default: 1101 // No additional features. 1102 return; 1103 } 1104 } 1105 1106 void CPUFeaturesAuditor::VisitNEONTable(const Instruction* instr) { 1107 RecordInstructionFeaturesScope scope(this); 1108 // All of these instructions require NEON. 1109 scope.Record(CPUFeatures::kNEON); 1110 USE(instr); 1111 } 1112 1113 void CPUFeaturesAuditor::VisitPCRelAddressing(const Instruction* instr) { 1114 RecordInstructionFeaturesScope scope(this); 1115 USE(instr); 1116 } 1117 1118 // Most SVE visitors require only SVE. 1119 #define VIXL_SIMPLE_SVE_VISITOR_LIST(V) \ 1120 V(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets) \ 1121 V(SVE32BitGatherLoad_VectorPlusImm) \ 1122 V(SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets) \ 1123 V(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets) \ 1124 V(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets) \ 1125 V(SVE32BitGatherPrefetch_VectorPlusImm) \ 1126 V(SVE32BitScatterStore_ScalarPlus32BitScaledOffsets) \ 1127 V(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets) \ 1128 V(SVE32BitScatterStore_VectorPlusImm) \ 1129 V(SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets) \ 1130 V(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsets) \ 1131 V(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets) \ 1132 V(SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets) \ 1133 V(SVE64BitGatherLoad_VectorPlusImm) \ 1134 V(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets) \ 1135 V(SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets) \ 1136 V(SVE64BitGatherPrefetch_VectorPlusImm) \ 1137 V(SVE64BitScatterStore_ScalarPlus64BitScaledOffsets) \ 1138 V(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets) \ 1139 V(SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets) \ 1140 V(SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets) \ 1141 V(SVE64BitScatterStore_VectorPlusImm) \ 1142 V(SVEAddressGeneration) \ 1143 V(SVEBitwiseLogicalUnpredicated) \ 1144 V(SVEBitwiseShiftUnpredicated) \ 1145 V(SVEFFRInitialise) \ 1146 V(SVEFFRWriteFromPredicate) \ 1147 V(SVEFPAccumulatingReduction) \ 1148 V(SVEFPArithmeticUnpredicated) \ 1149 V(SVEFPCompareVectors) \ 1150 V(SVEFPCompareWithZero) \ 1151 V(SVEFPComplexAddition) \ 1152 V(SVEFPComplexMulAdd) \ 1153 V(SVEFPComplexMulAddIndex) \ 1154 V(SVEFPFastReduction) \ 1155 V(SVEFPMulIndex) \ 1156 V(SVEFPMulAdd) \ 1157 V(SVEFPMulAddIndex) \ 1158 V(SVEFPUnaryOpUnpredicated) \ 1159 V(SVEIncDecByPredicateCount) \ 1160 V(SVEIndexGeneration) \ 1161 V(SVEIntArithmeticUnpredicated) \ 1162 V(SVEIntCompareSignedImm) \ 1163 V(SVEIntCompareUnsignedImm) \ 1164 V(SVEIntCompareVectors) \ 1165 V(SVEIntMulAddPredicated) \ 1166 V(SVEIntMulAddUnpredicated) \ 1167 V(SVEIntReduction) \ 1168 V(SVEIntUnaryArithmeticPredicated) \ 1169 V(SVEMovprfx) \ 1170 V(SVEMulIndex) \ 1171 V(SVEPermuteVectorExtract) \ 1172 V(SVEPermuteVectorInterleaving) \ 1173 V(SVEPredicateCount) \ 1174 V(SVEPredicateLogical) \ 1175 V(SVEPropagateBreak) \ 1176 V(SVEStackFrameAdjustment) \ 1177 V(SVEStackFrameSize) \ 1178 V(SVEVectorSelect) \ 1179 V(SVEBitwiseLogical_Predicated) \ 1180 V(SVEBitwiseLogicalWithImm_Unpredicated) \ 1181 V(SVEBitwiseShiftByImm_Predicated) \ 1182 V(SVEBitwiseShiftByVector_Predicated) \ 1183 V(SVEBitwiseShiftByWideElements_Predicated) \ 1184 V(SVEBroadcastBitmaskImm) \ 1185 V(SVEBroadcastFPImm_Unpredicated) \ 1186 V(SVEBroadcastGeneralRegister) \ 1187 V(SVEBroadcastIndexElement) \ 1188 V(SVEBroadcastIntImm_Unpredicated) \ 1189 V(SVECompressActiveElements) \ 1190 V(SVEConditionallyBroadcastElementToVector) \ 1191 V(SVEConditionallyExtractElementToSIMDFPScalar) \ 1192 V(SVEConditionallyExtractElementToGeneralRegister) \ 1193 V(SVEConditionallyTerminateScalars) \ 1194 V(SVEConstructivePrefix_Unpredicated) \ 1195 V(SVEContiguousFirstFaultLoad_ScalarPlusScalar) \ 1196 V(SVEContiguousLoad_ScalarPlusImm) \ 1197 V(SVEContiguousLoad_ScalarPlusScalar) \ 1198 V(SVEContiguousNonFaultLoad_ScalarPlusImm) \ 1199 V(SVEContiguousNonTemporalLoad_ScalarPlusImm) \ 1200 V(SVEContiguousNonTemporalLoad_ScalarPlusScalar) \ 1201 V(SVEContiguousNonTemporalStore_ScalarPlusImm) \ 1202 V(SVEContiguousNonTemporalStore_ScalarPlusScalar) \ 1203 V(SVEContiguousPrefetch_ScalarPlusImm) \ 1204 V(SVEContiguousPrefetch_ScalarPlusScalar) \ 1205 V(SVEContiguousStore_ScalarPlusImm) \ 1206 V(SVEContiguousStore_ScalarPlusScalar) \ 1207 V(SVECopySIMDFPScalarRegisterToVector_Predicated) \ 1208 V(SVECopyFPImm_Predicated) \ 1209 V(SVECopyGeneralRegisterToVector_Predicated) \ 1210 V(SVECopyIntImm_Predicated) \ 1211 V(SVEElementCount) \ 1212 V(SVEExtractElementToSIMDFPScalarRegister) \ 1213 V(SVEExtractElementToGeneralRegister) \ 1214 V(SVEFPArithmetic_Predicated) \ 1215 V(SVEFPArithmeticWithImm_Predicated) \ 1216 V(SVEFPConvertPrecision) \ 1217 V(SVEFPConvertToInt) \ 1218 V(SVEFPExponentialAccelerator) \ 1219 V(SVEFPRoundToIntegralValue) \ 1220 V(SVEFPTrigMulAddCoefficient) \ 1221 V(SVEFPTrigSelectCoefficient) \ 1222 V(SVEFPUnaryOp) \ 1223 V(SVEIncDecRegisterByElementCount) \ 1224 V(SVEIncDecVectorByElementCount) \ 1225 V(SVEInsertSIMDFPScalarRegister) \ 1226 V(SVEInsertGeneralRegister) \ 1227 V(SVEIntAddSubtractImm_Unpredicated) \ 1228 V(SVEIntAddSubtractVectors_Predicated) \ 1229 V(SVEIntCompareScalarCountAndLimit) \ 1230 V(SVEIntConvertToFP) \ 1231 V(SVEIntDivideVectors_Predicated) \ 1232 V(SVEIntMinMaxImm_Unpredicated) \ 1233 V(SVEIntMinMaxDifference_Predicated) \ 1234 V(SVEIntMulImm_Unpredicated) \ 1235 V(SVEIntMulVectors_Predicated) \ 1236 V(SVELoadAndBroadcastElement) \ 1237 V(SVELoadAndBroadcastQOWord_ScalarPlusImm) \ 1238 V(SVELoadAndBroadcastQOWord_ScalarPlusScalar) \ 1239 V(SVELoadMultipleStructures_ScalarPlusImm) \ 1240 V(SVELoadMultipleStructures_ScalarPlusScalar) \ 1241 V(SVELoadPredicateRegister) \ 1242 V(SVELoadVectorRegister) \ 1243 V(SVEPartitionBreakCondition) \ 1244 V(SVEPermutePredicateElements) \ 1245 V(SVEPredicateFirstActive) \ 1246 V(SVEPredicateInitialize) \ 1247 V(SVEPredicateNextActive) \ 1248 V(SVEPredicateReadFromFFR_Predicated) \ 1249 V(SVEPredicateReadFromFFR_Unpredicated) \ 1250 V(SVEPredicateTest) \ 1251 V(SVEPredicateZero) \ 1252 V(SVEPropagateBreakToNextPartition) \ 1253 V(SVEReversePredicateElements) \ 1254 V(SVEReverseVectorElements) \ 1255 V(SVEReverseWithinElements) \ 1256 V(SVESaturatingIncDecRegisterByElementCount) \ 1257 V(SVESaturatingIncDecVectorByElementCount) \ 1258 V(SVEStoreMultipleStructures_ScalarPlusImm) \ 1259 V(SVEStoreMultipleStructures_ScalarPlusScalar) \ 1260 V(SVEStorePredicateRegister) \ 1261 V(SVEStoreVectorRegister) \ 1262 V(SVETableLookup) \ 1263 V(SVEUnpackPredicateElements) \ 1264 V(SVEUnpackVectorElements) \ 1265 V(SVEVectorSplice) 1266 1267 #define VIXL_DEFINE_SIMPLE_SVE_VISITOR(NAME) \ 1268 void CPUFeaturesAuditor::Visit##NAME(const Instruction* instr) { \ 1269 RecordInstructionFeaturesScope scope(this); \ 1270 scope.Record(CPUFeatures::kSVE); \ 1271 USE(instr); \ 1272 } 1273 VIXL_SIMPLE_SVE_VISITOR_LIST(VIXL_DEFINE_SIMPLE_SVE_VISITOR) 1274 #undef VIXL_DEFINE_SIMPLE_SVE_VISITOR 1275 #undef VIXL_SIMPLE_SVE_VISITOR_LIST 1276 1277 void CPUFeaturesAuditor::VisitSystem(const Instruction* instr) { 1278 RecordInstructionFeaturesScope scope(this); 1279 if (instr->Mask(SystemHintFMask) == SystemHintFixed) { 1280 CPUFeatures required; 1281 switch (instr->GetInstructionBits()) { 1282 case PACIA1716: 1283 case PACIB1716: 1284 case AUTIA1716: 1285 case AUTIB1716: 1286 case PACIAZ: 1287 case PACIASP: 1288 case PACIBZ: 1289 case PACIBSP: 1290 case AUTIAZ: 1291 case AUTIASP: 1292 case AUTIBZ: 1293 case AUTIBSP: 1294 case XPACLRI: 1295 required.Combine(CPUFeatures::kPAuth); 1296 break; 1297 default: 1298 switch (instr->GetImmHint()) { 1299 case ESB: 1300 required.Combine(CPUFeatures::kRAS); 1301 break; 1302 case BTI: 1303 case BTI_j: 1304 case BTI_c: 1305 case BTI_jc: 1306 required.Combine(CPUFeatures::kBTI); 1307 break; 1308 default: 1309 break; 1310 } 1311 break; 1312 } 1313 1314 // These are all HINT instructions, and behave as NOPs if the corresponding 1315 // features are not implemented, so we record the corresponding features 1316 // only if they are available. 1317 if (available_.Has(required)) scope.Record(required); 1318 } else if (instr->Mask(SystemSysMask) == SYS) { 1319 switch (instr->GetSysOp()) { 1320 // DC instruction variants. 1321 case CGVAC: 1322 case CGDVAC: 1323 case CGVAP: 1324 case CGDVAP: 1325 case CIGVAC: 1326 case CIGDVAC: 1327 case GVA: 1328 case GZVA: 1329 scope.Record(CPUFeatures::kMTE); 1330 break; 1331 case CVAP: 1332 scope.Record(CPUFeatures::kDCPoP); 1333 break; 1334 case CVADP: 1335 scope.Record(CPUFeatures::kDCCVADP); 1336 break; 1337 case IVAU: 1338 case CVAC: 1339 case CVAU: 1340 case CIVAC: 1341 case ZVA: 1342 // No special CPU features. 1343 break; 1344 } 1345 } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) { 1346 switch (instr->Mask(SystemPStateMask)) { 1347 case CFINV: 1348 scope.Record(CPUFeatures::kFlagM); 1349 break; 1350 case AXFLAG: 1351 case XAFLAG: 1352 scope.Record(CPUFeatures::kAXFlag); 1353 break; 1354 } 1355 } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) { 1356 if (instr->Mask(SystemSysRegMask) == MRS) { 1357 switch (instr->GetImmSystemRegister()) { 1358 case RNDR: 1359 case RNDRRS: 1360 scope.Record(CPUFeatures::kRNG); 1361 break; 1362 } 1363 } 1364 } 1365 } 1366 1367 void CPUFeaturesAuditor::VisitTestBranch(const Instruction* instr) { 1368 RecordInstructionFeaturesScope scope(this); 1369 USE(instr); 1370 } 1371 1372 void CPUFeaturesAuditor::VisitUnallocated(const Instruction* instr) { 1373 RecordInstructionFeaturesScope scope(this); 1374 USE(instr); 1375 } 1376 1377 void CPUFeaturesAuditor::VisitUnconditionalBranch(const Instruction* instr) { 1378 RecordInstructionFeaturesScope scope(this); 1379 USE(instr); 1380 } 1381 1382 void CPUFeaturesAuditor::VisitUnconditionalBranchToRegister( 1383 const Instruction* instr) { 1384 RecordInstructionFeaturesScope scope(this); 1385 switch (instr->Mask(UnconditionalBranchToRegisterMask)) { 1386 case BRAAZ: 1387 case BRABZ: 1388 case BLRAAZ: 1389 case BLRABZ: 1390 case RETAA: 1391 case RETAB: 1392 case BRAA: 1393 case BRAB: 1394 case BLRAA: 1395 case BLRAB: 1396 scope.Record(CPUFeatures::kPAuth); 1397 return; 1398 default: 1399 // No additional features. 1400 return; 1401 } 1402 } 1403 1404 void CPUFeaturesAuditor::VisitReserved(const Instruction* instr) { 1405 RecordInstructionFeaturesScope scope(this); 1406 USE(instr); 1407 } 1408 1409 void CPUFeaturesAuditor::VisitUnimplemented(const Instruction* instr) { 1410 RecordInstructionFeaturesScope scope(this); 1411 USE(instr); 1412 } 1413 1414 void CPUFeaturesAuditor::Visit(Metadata* metadata, const Instruction* instr) { 1415 VIXL_ASSERT(metadata->count("form") > 0); 1416 const std::string& form = (*metadata)["form"]; 1417 form_hash_ = Hash(form.c_str()); 1418 const FormToVisitorFnMap* fv = CPUFeaturesAuditor::GetFormToVisitorFnMap(); 1419 FormToVisitorFnMap::const_iterator it = fv->find(form_hash_); 1420 if (it == fv->end()) { 1421 RecordInstructionFeaturesScope scope(this); 1422 std::map<uint32_t, const CPUFeatures> features = { 1423 {"adclb_z_zzz"_h, CPUFeatures::kSVE2}, 1424 {"adclt_z_zzz"_h, CPUFeatures::kSVE2}, 1425 {"addhnb_z_zz"_h, CPUFeatures::kSVE2}, 1426 {"addhnt_z_zz"_h, CPUFeatures::kSVE2}, 1427 {"addp_z_p_zz"_h, CPUFeatures::kSVE2}, 1428 {"bcax_z_zzz"_h, CPUFeatures::kSVE2}, 1429 {"bdep_z_zz"_h, 1430 CPUFeatures(CPUFeatures::kSVE2, CPUFeatures::kSVEBitPerm)}, 1431 {"bext_z_zz"_h, 1432 CPUFeatures(CPUFeatures::kSVE2, CPUFeatures::kSVEBitPerm)}, 1433 {"bgrp_z_zz"_h, 1434 CPUFeatures(CPUFeatures::kSVE2, CPUFeatures::kSVEBitPerm)}, 1435 {"bsl1n_z_zzz"_h, CPUFeatures::kSVE2}, 1436 {"bsl2n_z_zzz"_h, CPUFeatures::kSVE2}, 1437 {"bsl_z_zzz"_h, CPUFeatures::kSVE2}, 1438 {"cadd_z_zz"_h, CPUFeatures::kSVE2}, 1439 {"cdot_z_zzz"_h, CPUFeatures::kSVE2}, 1440 {"cdot_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1441 {"cdot_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1442 {"cmla_z_zzz"_h, CPUFeatures::kSVE2}, 1443 {"cmla_z_zzzi_h"_h, CPUFeatures::kSVE2}, 1444 {"cmla_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1445 {"eor3_z_zzz"_h, CPUFeatures::kSVE2}, 1446 {"eorbt_z_zz"_h, CPUFeatures::kSVE2}, 1447 {"eortb_z_zz"_h, CPUFeatures::kSVE2}, 1448 {"ext_z_zi_con"_h, CPUFeatures::kSVE2}, 1449 {"faddp_z_p_zz"_h, CPUFeatures::kSVE2}, 1450 {"fcvtlt_z_p_z_h2s"_h, CPUFeatures::kSVE2}, 1451 {"fcvtlt_z_p_z_s2d"_h, CPUFeatures::kSVE2}, 1452 {"fcvtnt_z_p_z_d2s"_h, CPUFeatures::kSVE2}, 1453 {"fcvtnt_z_p_z_s2h"_h, CPUFeatures::kSVE2}, 1454 {"fcvtx_z_p_z_d2s"_h, CPUFeatures::kSVE2}, 1455 {"fcvtxnt_z_p_z_d2s"_h, CPUFeatures::kSVE2}, 1456 {"flogb_z_p_z"_h, CPUFeatures::kSVE2}, 1457 {"fmaxnmp_z_p_zz"_h, CPUFeatures::kSVE2}, 1458 {"fmaxp_z_p_zz"_h, CPUFeatures::kSVE2}, 1459 {"fminnmp_z_p_zz"_h, CPUFeatures::kSVE2}, 1460 {"fminp_z_p_zz"_h, CPUFeatures::kSVE2}, 1461 {"fmlalb_z_zzz"_h, CPUFeatures::kSVE2}, 1462 {"fmlalb_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1463 {"fmlalt_z_zzz"_h, CPUFeatures::kSVE2}, 1464 {"fmlalt_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1465 {"fmlslb_z_zzz"_h, CPUFeatures::kSVE2}, 1466 {"fmlslb_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1467 {"fmlslt_z_zzz"_h, CPUFeatures::kSVE2}, 1468 {"fmlslt_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1469 {"histcnt_z_p_zz"_h, CPUFeatures::kSVE2}, 1470 {"histseg_z_zz"_h, CPUFeatures::kSVE2}, 1471 {"ldnt1b_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2}, 1472 {"ldnt1b_z_p_ar_s_x32_unscaled"_h, CPUFeatures::kSVE2}, 1473 {"ldnt1d_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2}, 1474 {"ldnt1h_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2}, 1475 {"ldnt1h_z_p_ar_s_x32_unscaled"_h, CPUFeatures::kSVE2}, 1476 {"ldnt1sb_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2}, 1477 {"ldnt1sb_z_p_ar_s_x32_unscaled"_h, CPUFeatures::kSVE2}, 1478 {"ldnt1sh_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2}, 1479 {"ldnt1sh_z_p_ar_s_x32_unscaled"_h, CPUFeatures::kSVE2}, 1480 {"ldnt1sw_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2}, 1481 {"ldnt1w_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2}, 1482 {"ldnt1w_z_p_ar_s_x32_unscaled"_h, CPUFeatures::kSVE2}, 1483 {"match_p_p_zz"_h, CPUFeatures::kSVE2}, 1484 {"mla_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1485 {"mla_z_zzzi_h"_h, CPUFeatures::kSVE2}, 1486 {"mla_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1487 {"mls_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1488 {"mls_z_zzzi_h"_h, CPUFeatures::kSVE2}, 1489 {"mls_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1490 {"mul_z_zz"_h, CPUFeatures::kSVE2}, 1491 {"mul_z_zzi_d"_h, CPUFeatures::kSVE2}, 1492 {"mul_z_zzi_h"_h, CPUFeatures::kSVE2}, 1493 {"mul_z_zzi_s"_h, CPUFeatures::kSVE2}, 1494 {"nbsl_z_zzz"_h, CPUFeatures::kSVE2}, 1495 {"nmatch_p_p_zz"_h, CPUFeatures::kSVE2}, 1496 {"pmul_z_zz"_h, CPUFeatures::kSVE2}, 1497 {"pmullb_z_zz"_h, CPUFeatures::kSVE2}, 1498 {"pmullt_z_zz"_h, CPUFeatures::kSVE2}, 1499 {"raddhnb_z_zz"_h, CPUFeatures::kSVE2}, 1500 {"raddhnt_z_zz"_h, CPUFeatures::kSVE2}, 1501 {"rshrnb_z_zi"_h, CPUFeatures::kSVE2}, 1502 {"rshrnt_z_zi"_h, CPUFeatures::kSVE2}, 1503 {"rsubhnb_z_zz"_h, CPUFeatures::kSVE2}, 1504 {"rsubhnt_z_zz"_h, CPUFeatures::kSVE2}, 1505 {"saba_z_zzz"_h, CPUFeatures::kSVE2}, 1506 {"sabalb_z_zzz"_h, CPUFeatures::kSVE2}, 1507 {"sabalt_z_zzz"_h, CPUFeatures::kSVE2}, 1508 {"sabdlb_z_zz"_h, CPUFeatures::kSVE2}, 1509 {"sabdlt_z_zz"_h, CPUFeatures::kSVE2}, 1510 {"sadalp_z_p_z"_h, CPUFeatures::kSVE2}, 1511 {"saddlb_z_zz"_h, CPUFeatures::kSVE2}, 1512 {"saddlbt_z_zz"_h, CPUFeatures::kSVE2}, 1513 {"saddlt_z_zz"_h, CPUFeatures::kSVE2}, 1514 {"saddwb_z_zz"_h, CPUFeatures::kSVE2}, 1515 {"saddwt_z_zz"_h, CPUFeatures::kSVE2}, 1516 {"sbclb_z_zzz"_h, CPUFeatures::kSVE2}, 1517 {"sbclt_z_zzz"_h, CPUFeatures::kSVE2}, 1518 {"shadd_z_p_zz"_h, CPUFeatures::kSVE2}, 1519 {"shrnb_z_zi"_h, CPUFeatures::kSVE2}, 1520 {"shrnt_z_zi"_h, CPUFeatures::kSVE2}, 1521 {"shsub_z_p_zz"_h, CPUFeatures::kSVE2}, 1522 {"shsubr_z_p_zz"_h, CPUFeatures::kSVE2}, 1523 {"sli_z_zzi"_h, CPUFeatures::kSVE2}, 1524 {"smaxp_z_p_zz"_h, CPUFeatures::kSVE2}, 1525 {"sminp_z_p_zz"_h, CPUFeatures::kSVE2}, 1526 {"smlalb_z_zzz"_h, CPUFeatures::kSVE2}, 1527 {"smlalb_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1528 {"smlalb_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1529 {"smlalt_z_zzz"_h, CPUFeatures::kSVE2}, 1530 {"smlalt_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1531 {"smlalt_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1532 {"smlslb_z_zzz"_h, CPUFeatures::kSVE2}, 1533 {"smlslb_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1534 {"smlslb_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1535 {"smlslt_z_zzz"_h, CPUFeatures::kSVE2}, 1536 {"smlslt_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1537 {"smlslt_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1538 {"smulh_z_zz"_h, CPUFeatures::kSVE2}, 1539 {"smullb_z_zz"_h, CPUFeatures::kSVE2}, 1540 {"smullb_z_zzi_d"_h, CPUFeatures::kSVE2}, 1541 {"smullb_z_zzi_s"_h, CPUFeatures::kSVE2}, 1542 {"smullt_z_zz"_h, CPUFeatures::kSVE2}, 1543 {"smullt_z_zzi_d"_h, CPUFeatures::kSVE2}, 1544 {"smullt_z_zzi_s"_h, CPUFeatures::kSVE2}, 1545 {"splice_z_p_zz_con"_h, CPUFeatures::kSVE2}, 1546 {"sqabs_z_p_z"_h, CPUFeatures::kSVE2}, 1547 {"sqadd_z_p_zz"_h, CPUFeatures::kSVE2}, 1548 {"sqcadd_z_zz"_h, CPUFeatures::kSVE2}, 1549 {"sqdmlalb_z_zzz"_h, CPUFeatures::kSVE2}, 1550 {"sqdmlalb_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1551 {"sqdmlalb_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1552 {"sqdmlalbt_z_zzz"_h, CPUFeatures::kSVE2}, 1553 {"sqdmlalt_z_zzz"_h, CPUFeatures::kSVE2}, 1554 {"sqdmlalt_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1555 {"sqdmlalt_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1556 {"sqdmlslb_z_zzz"_h, CPUFeatures::kSVE2}, 1557 {"sqdmlslb_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1558 {"sqdmlslb_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1559 {"sqdmlslbt_z_zzz"_h, CPUFeatures::kSVE2}, 1560 {"sqdmlslt_z_zzz"_h, CPUFeatures::kSVE2}, 1561 {"sqdmlslt_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1562 {"sqdmlslt_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1563 {"sqdmulh_z_zz"_h, CPUFeatures::kSVE2}, 1564 {"sqdmulh_z_zzi_d"_h, CPUFeatures::kSVE2}, 1565 {"sqdmulh_z_zzi_h"_h, CPUFeatures::kSVE2}, 1566 {"sqdmulh_z_zzi_s"_h, CPUFeatures::kSVE2}, 1567 {"sqdmullb_z_zz"_h, CPUFeatures::kSVE2}, 1568 {"sqdmullb_z_zzi_d"_h, CPUFeatures::kSVE2}, 1569 {"sqdmullb_z_zzi_s"_h, CPUFeatures::kSVE2}, 1570 {"sqdmullt_z_zz"_h, CPUFeatures::kSVE2}, 1571 {"sqdmullt_z_zzi_d"_h, CPUFeatures::kSVE2}, 1572 {"sqdmullt_z_zzi_s"_h, CPUFeatures::kSVE2}, 1573 {"sqneg_z_p_z"_h, CPUFeatures::kSVE2}, 1574 {"sqrdcmlah_z_zzz"_h, CPUFeatures::kSVE2}, 1575 {"sqrdcmlah_z_zzzi_h"_h, CPUFeatures::kSVE2}, 1576 {"sqrdcmlah_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1577 {"sqrdmlah_z_zzz"_h, CPUFeatures::kSVE2}, 1578 {"sqrdmlah_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1579 {"sqrdmlah_z_zzzi_h"_h, CPUFeatures::kSVE2}, 1580 {"sqrdmlah_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1581 {"sqrdmlsh_z_zzz"_h, CPUFeatures::kSVE2}, 1582 {"sqrdmlsh_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1583 {"sqrdmlsh_z_zzzi_h"_h, CPUFeatures::kSVE2}, 1584 {"sqrdmlsh_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1585 {"sqrdmulh_z_zz"_h, CPUFeatures::kSVE2}, 1586 {"sqrdmulh_z_zzi_d"_h, CPUFeatures::kSVE2}, 1587 {"sqrdmulh_z_zzi_h"_h, CPUFeatures::kSVE2}, 1588 {"sqrdmulh_z_zzi_s"_h, CPUFeatures::kSVE2}, 1589 {"sqrshl_z_p_zz"_h, CPUFeatures::kSVE2}, 1590 {"sqrshlr_z_p_zz"_h, CPUFeatures::kSVE2}, 1591 {"sqrshrnb_z_zi"_h, CPUFeatures::kSVE2}, 1592 {"sqrshrnt_z_zi"_h, CPUFeatures::kSVE2}, 1593 {"sqrshrunb_z_zi"_h, CPUFeatures::kSVE2}, 1594 {"sqrshrunt_z_zi"_h, CPUFeatures::kSVE2}, 1595 {"sqshl_z_p_zi"_h, CPUFeatures::kSVE2}, 1596 {"sqshl_z_p_zz"_h, CPUFeatures::kSVE2}, 1597 {"sqshlr_z_p_zz"_h, CPUFeatures::kSVE2}, 1598 {"sqshlu_z_p_zi"_h, CPUFeatures::kSVE2}, 1599 {"sqshrnb_z_zi"_h, CPUFeatures::kSVE2}, 1600 {"sqshrnt_z_zi"_h, CPUFeatures::kSVE2}, 1601 {"sqshrunb_z_zi"_h, CPUFeatures::kSVE2}, 1602 {"sqshrunt_z_zi"_h, CPUFeatures::kSVE2}, 1603 {"sqsub_z_p_zz"_h, CPUFeatures::kSVE2}, 1604 {"sqsubr_z_p_zz"_h, CPUFeatures::kSVE2}, 1605 {"sqxtnb_z_zz"_h, CPUFeatures::kSVE2}, 1606 {"sqxtnt_z_zz"_h, CPUFeatures::kSVE2}, 1607 {"sqxtunb_z_zz"_h, CPUFeatures::kSVE2}, 1608 {"sqxtunt_z_zz"_h, CPUFeatures::kSVE2}, 1609 {"srhadd_z_p_zz"_h, CPUFeatures::kSVE2}, 1610 {"sri_z_zzi"_h, CPUFeatures::kSVE2}, 1611 {"srshl_z_p_zz"_h, CPUFeatures::kSVE2}, 1612 {"srshlr_z_p_zz"_h, CPUFeatures::kSVE2}, 1613 {"srshr_z_p_zi"_h, CPUFeatures::kSVE2}, 1614 {"srsra_z_zi"_h, CPUFeatures::kSVE2}, 1615 {"sshllb_z_zi"_h, CPUFeatures::kSVE2}, 1616 {"sshllt_z_zi"_h, CPUFeatures::kSVE2}, 1617 {"ssra_z_zi"_h, CPUFeatures::kSVE2}, 1618 {"ssublb_z_zz"_h, CPUFeatures::kSVE2}, 1619 {"ssublbt_z_zz"_h, CPUFeatures::kSVE2}, 1620 {"ssublt_z_zz"_h, CPUFeatures::kSVE2}, 1621 {"ssubltb_z_zz"_h, CPUFeatures::kSVE2}, 1622 {"ssubwb_z_zz"_h, CPUFeatures::kSVE2}, 1623 {"ssubwt_z_zz"_h, CPUFeatures::kSVE2}, 1624 {"stnt1b_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2}, 1625 {"stnt1b_z_p_ar_s_x32_unscaled"_h, CPUFeatures::kSVE2}, 1626 {"stnt1d_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2}, 1627 {"stnt1h_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2}, 1628 {"stnt1h_z_p_ar_s_x32_unscaled"_h, CPUFeatures::kSVE2}, 1629 {"stnt1w_z_p_ar_d_64_unscaled"_h, CPUFeatures::kSVE2}, 1630 {"stnt1w_z_p_ar_s_x32_unscaled"_h, CPUFeatures::kSVE2}, 1631 {"subhnb_z_zz"_h, CPUFeatures::kSVE2}, 1632 {"subhnt_z_zz"_h, CPUFeatures::kSVE2}, 1633 {"suqadd_z_p_zz"_h, CPUFeatures::kSVE2}, 1634 {"tbl_z_zz_2"_h, CPUFeatures::kSVE2}, 1635 {"tbx_z_zz"_h, CPUFeatures::kSVE2}, 1636 {"uaba_z_zzz"_h, CPUFeatures::kSVE2}, 1637 {"uabalb_z_zzz"_h, CPUFeatures::kSVE2}, 1638 {"uabalt_z_zzz"_h, CPUFeatures::kSVE2}, 1639 {"uabdlb_z_zz"_h, CPUFeatures::kSVE2}, 1640 {"uabdlt_z_zz"_h, CPUFeatures::kSVE2}, 1641 {"uadalp_z_p_z"_h, CPUFeatures::kSVE2}, 1642 {"uaddlb_z_zz"_h, CPUFeatures::kSVE2}, 1643 {"uaddlt_z_zz"_h, CPUFeatures::kSVE2}, 1644 {"uaddwb_z_zz"_h, CPUFeatures::kSVE2}, 1645 {"uaddwt_z_zz"_h, CPUFeatures::kSVE2}, 1646 {"uhadd_z_p_zz"_h, CPUFeatures::kSVE2}, 1647 {"uhsub_z_p_zz"_h, CPUFeatures::kSVE2}, 1648 {"uhsubr_z_p_zz"_h, CPUFeatures::kSVE2}, 1649 {"umaxp_z_p_zz"_h, CPUFeatures::kSVE2}, 1650 {"uminp_z_p_zz"_h, CPUFeatures::kSVE2}, 1651 {"umlalb_z_zzz"_h, CPUFeatures::kSVE2}, 1652 {"umlalb_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1653 {"umlalb_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1654 {"umlalt_z_zzz"_h, CPUFeatures::kSVE2}, 1655 {"umlalt_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1656 {"umlalt_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1657 {"umlslb_z_zzz"_h, CPUFeatures::kSVE2}, 1658 {"umlslb_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1659 {"umlslb_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1660 {"umlslt_z_zzz"_h, CPUFeatures::kSVE2}, 1661 {"umlslt_z_zzzi_d"_h, CPUFeatures::kSVE2}, 1662 {"umlslt_z_zzzi_s"_h, CPUFeatures::kSVE2}, 1663 {"umulh_z_zz"_h, CPUFeatures::kSVE2}, 1664 {"umullb_z_zz"_h, CPUFeatures::kSVE2}, 1665 {"umullb_z_zzi_d"_h, CPUFeatures::kSVE2}, 1666 {"umullb_z_zzi_s"_h, CPUFeatures::kSVE2}, 1667 {"umullt_z_zz"_h, CPUFeatures::kSVE2}, 1668 {"umullt_z_zzi_d"_h, CPUFeatures::kSVE2}, 1669 {"umullt_z_zzi_s"_h, CPUFeatures::kSVE2}, 1670 {"uqadd_z_p_zz"_h, CPUFeatures::kSVE2}, 1671 {"uqrshl_z_p_zz"_h, CPUFeatures::kSVE2}, 1672 {"uqrshlr_z_p_zz"_h, CPUFeatures::kSVE2}, 1673 {"uqrshrnb_z_zi"_h, CPUFeatures::kSVE2}, 1674 {"uqrshrnt_z_zi"_h, CPUFeatures::kSVE2}, 1675 {"uqshl_z_p_zi"_h, CPUFeatures::kSVE2}, 1676 {"uqshl_z_p_zz"_h, CPUFeatures::kSVE2}, 1677 {"uqshlr_z_p_zz"_h, CPUFeatures::kSVE2}, 1678 {"uqshrnb_z_zi"_h, CPUFeatures::kSVE2}, 1679 {"uqshrnt_z_zi"_h, CPUFeatures::kSVE2}, 1680 {"uqsub_z_p_zz"_h, CPUFeatures::kSVE2}, 1681 {"uqsubr_z_p_zz"_h, CPUFeatures::kSVE2}, 1682 {"uqxtnb_z_zz"_h, CPUFeatures::kSVE2}, 1683 {"uqxtnt_z_zz"_h, CPUFeatures::kSVE2}, 1684 {"urecpe_z_p_z"_h, CPUFeatures::kSVE2}, 1685 {"urhadd_z_p_zz"_h, CPUFeatures::kSVE2}, 1686 {"urshl_z_p_zz"_h, CPUFeatures::kSVE2}, 1687 {"urshlr_z_p_zz"_h, CPUFeatures::kSVE2}, 1688 {"urshr_z_p_zi"_h, CPUFeatures::kSVE2}, 1689 {"ursqrte_z_p_z"_h, CPUFeatures::kSVE2}, 1690 {"ursra_z_zi"_h, CPUFeatures::kSVE2}, 1691 {"ushllb_z_zi"_h, CPUFeatures::kSVE2}, 1692 {"ushllt_z_zi"_h, CPUFeatures::kSVE2}, 1693 {"usqadd_z_p_zz"_h, CPUFeatures::kSVE2}, 1694 {"usra_z_zi"_h, CPUFeatures::kSVE2}, 1695 {"usublb_z_zz"_h, CPUFeatures::kSVE2}, 1696 {"usublt_z_zz"_h, CPUFeatures::kSVE2}, 1697 {"usubwb_z_zz"_h, CPUFeatures::kSVE2}, 1698 {"usubwt_z_zz"_h, CPUFeatures::kSVE2}, 1699 {"whilege_p_p_rr"_h, CPUFeatures::kSVE2}, 1700 {"whilegt_p_p_rr"_h, CPUFeatures::kSVE2}, 1701 {"whilehi_p_p_rr"_h, CPUFeatures::kSVE2}, 1702 {"whilehs_p_p_rr"_h, CPUFeatures::kSVE2}, 1703 {"whilerw_p_rr"_h, CPUFeatures::kSVE2}, 1704 {"whilewr_p_rr"_h, CPUFeatures::kSVE2}, 1705 {"xar_z_zzi"_h, CPUFeatures::kSVE2}, 1706 {"smmla_z_zzz"_h, 1707 CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEI8MM)}, 1708 {"ummla_z_zzz"_h, 1709 CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEI8MM)}, 1710 {"usmmla_z_zzz"_h, 1711 CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEI8MM)}, 1712 {"fmmla_z_zzz_s"_h, 1713 CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF32MM)}, 1714 {"fmmla_z_zzz_d"_h, 1715 CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)}, 1716 {"smmla_asimdsame2_g"_h, 1717 CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kI8MM)}, 1718 {"ummla_asimdsame2_g"_h, 1719 CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kI8MM)}, 1720 {"usmmla_asimdsame2_g"_h, 1721 CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kI8MM)}, 1722 {"ld1row_z_p_bi_u32"_h, 1723 CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)}, 1724 {"ld1row_z_p_br_contiguous"_h, 1725 CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)}, 1726 {"ld1rod_z_p_bi_u64"_h, 1727 CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)}, 1728 {"ld1rod_z_p_br_contiguous"_h, 1729 CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)}, 1730 {"ld1rob_z_p_bi_u8"_h, 1731 CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)}, 1732 {"ld1rob_z_p_br_contiguous"_h, 1733 CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)}, 1734 {"ld1roh_z_p_bi_u16"_h, 1735 CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)}, 1736 {"ld1roh_z_p_br_contiguous"_h, 1737 CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEF64MM)}, 1738 {"usdot_asimdsame2_d"_h, 1739 CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kI8MM)}, 1740 {"sudot_asimdelem_d"_h, 1741 CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kI8MM)}, 1742 {"usdot_asimdelem_d"_h, 1743 CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kI8MM)}, 1744 {"usdot_z_zzz_s"_h, 1745 CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEI8MM)}, 1746 {"usdot_z_zzzi_s"_h, 1747 CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEI8MM)}, 1748 {"sudot_z_zzzi_s"_h, 1749 CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kSVEI8MM)}, 1750 {"addg_64_addsub_immtags"_h, CPUFeatures::kMTE}, 1751 {"gmi_64g_dp_2src"_h, CPUFeatures::kMTE}, 1752 {"irg_64i_dp_2src"_h, CPUFeatures::kMTE}, 1753 {"ldg_64loffset_ldsttags"_h, CPUFeatures::kMTE}, 1754 {"st2g_64soffset_ldsttags"_h, CPUFeatures::kMTE}, 1755 {"st2g_64spost_ldsttags"_h, CPUFeatures::kMTE}, 1756 {"st2g_64spre_ldsttags"_h, CPUFeatures::kMTE}, 1757 {"stgp_64_ldstpair_off"_h, CPUFeatures::kMTE}, 1758 {"stgp_64_ldstpair_post"_h, CPUFeatures::kMTE}, 1759 {"stgp_64_ldstpair_pre"_h, CPUFeatures::kMTE}, 1760 {"stg_64soffset_ldsttags"_h, CPUFeatures::kMTE}, 1761 {"stg_64spost_ldsttags"_h, CPUFeatures::kMTE}, 1762 {"stg_64spre_ldsttags"_h, CPUFeatures::kMTE}, 1763 {"stz2g_64soffset_ldsttags"_h, CPUFeatures::kMTE}, 1764 {"stz2g_64spost_ldsttags"_h, CPUFeatures::kMTE}, 1765 {"stz2g_64spre_ldsttags"_h, CPUFeatures::kMTE}, 1766 {"stzg_64soffset_ldsttags"_h, CPUFeatures::kMTE}, 1767 {"stzg_64spost_ldsttags"_h, CPUFeatures::kMTE}, 1768 {"stzg_64spre_ldsttags"_h, CPUFeatures::kMTE}, 1769 {"subg_64_addsub_immtags"_h, CPUFeatures::kMTE}, 1770 {"subps_64s_dp_2src"_h, CPUFeatures::kMTE}, 1771 {"subp_64s_dp_2src"_h, CPUFeatures::kMTE}, 1772 {"cpyen_cpy_memcms"_h, CPUFeatures::kMOPS}, 1773 {"cpyern_cpy_memcms"_h, CPUFeatures::kMOPS}, 1774 {"cpyewn_cpy_memcms"_h, CPUFeatures::kMOPS}, 1775 {"cpye_cpy_memcms"_h, CPUFeatures::kMOPS}, 1776 {"cpyfen_cpy_memcms"_h, CPUFeatures::kMOPS}, 1777 {"cpyfern_cpy_memcms"_h, CPUFeatures::kMOPS}, 1778 {"cpyfewn_cpy_memcms"_h, CPUFeatures::kMOPS}, 1779 {"cpyfe_cpy_memcms"_h, CPUFeatures::kMOPS}, 1780 {"cpyfmn_cpy_memcms"_h, CPUFeatures::kMOPS}, 1781 {"cpyfmrn_cpy_memcms"_h, CPUFeatures::kMOPS}, 1782 {"cpyfmwn_cpy_memcms"_h, CPUFeatures::kMOPS}, 1783 {"cpyfm_cpy_memcms"_h, CPUFeatures::kMOPS}, 1784 {"cpyfpn_cpy_memcms"_h, CPUFeatures::kMOPS}, 1785 {"cpyfprn_cpy_memcms"_h, CPUFeatures::kMOPS}, 1786 {"cpyfpwn_cpy_memcms"_h, CPUFeatures::kMOPS}, 1787 {"cpyfp_cpy_memcms"_h, CPUFeatures::kMOPS}, 1788 {"cpymn_cpy_memcms"_h, CPUFeatures::kMOPS}, 1789 {"cpymrn_cpy_memcms"_h, CPUFeatures::kMOPS}, 1790 {"cpymwn_cpy_memcms"_h, CPUFeatures::kMOPS}, 1791 {"cpym_cpy_memcms"_h, CPUFeatures::kMOPS}, 1792 {"cpypn_cpy_memcms"_h, CPUFeatures::kMOPS}, 1793 {"cpyprn_cpy_memcms"_h, CPUFeatures::kMOPS}, 1794 {"cpypwn_cpy_memcms"_h, CPUFeatures::kMOPS}, 1795 {"cpyp_cpy_memcms"_h, CPUFeatures::kMOPS}, 1796 {"seten_set_memcms"_h, CPUFeatures::kMOPS}, 1797 {"sete_set_memcms"_h, CPUFeatures::kMOPS}, 1798 {"setgen_set_memcms"_h, 1799 CPUFeatures(CPUFeatures::kMOPS, CPUFeatures::kMTE)}, 1800 {"setge_set_memcms"_h, 1801 CPUFeatures(CPUFeatures::kMOPS, CPUFeatures::kMTE)}, 1802 {"setgmn_set_memcms"_h, 1803 CPUFeatures(CPUFeatures::kMOPS, CPUFeatures::kMTE)}, 1804 {"setgm_set_memcms"_h, 1805 CPUFeatures(CPUFeatures::kMOPS, CPUFeatures::kMTE)}, 1806 {"setgpn_set_memcms"_h, 1807 CPUFeatures(CPUFeatures::kMOPS, CPUFeatures::kMTE)}, 1808 {"setgp_set_memcms"_h, 1809 CPUFeatures(CPUFeatures::kMOPS, CPUFeatures::kMTE)}, 1810 {"setmn_set_memcms"_h, CPUFeatures::kMOPS}, 1811 {"setm_set_memcms"_h, CPUFeatures::kMOPS}, 1812 {"setpn_set_memcms"_h, CPUFeatures::kMOPS}, 1813 {"setp_set_memcms"_h, CPUFeatures::kMOPS}, 1814 {"abs_32_dp_1src"_h, CPUFeatures::kCSSC}, 1815 {"abs_64_dp_1src"_h, CPUFeatures::kCSSC}, 1816 {"cnt_32_dp_1src"_h, CPUFeatures::kCSSC}, 1817 {"cnt_64_dp_1src"_h, CPUFeatures::kCSSC}, 1818 {"ctz_32_dp_1src"_h, CPUFeatures::kCSSC}, 1819 {"ctz_64_dp_1src"_h, CPUFeatures::kCSSC}, 1820 {"smax_32_dp_2src"_h, CPUFeatures::kCSSC}, 1821 {"smax_64_dp_2src"_h, CPUFeatures::kCSSC}, 1822 {"smin_32_dp_2src"_h, CPUFeatures::kCSSC}, 1823 {"smin_64_dp_2src"_h, CPUFeatures::kCSSC}, 1824 {"umax_32_dp_2src"_h, CPUFeatures::kCSSC}, 1825 {"umax_64_dp_2src"_h, CPUFeatures::kCSSC}, 1826 {"umin_32_dp_2src"_h, CPUFeatures::kCSSC}, 1827 {"umin_64_dp_2src"_h, CPUFeatures::kCSSC}, 1828 {"smax_32_minmax_imm"_h, CPUFeatures::kCSSC}, 1829 {"smax_64_minmax_imm"_h, CPUFeatures::kCSSC}, 1830 {"smin_32_minmax_imm"_h, CPUFeatures::kCSSC}, 1831 {"smin_64_minmax_imm"_h, CPUFeatures::kCSSC}, 1832 {"umax_32u_minmax_imm"_h, CPUFeatures::kCSSC}, 1833 {"umax_64u_minmax_imm"_h, CPUFeatures::kCSSC}, 1834 {"umin_32u_minmax_imm"_h, CPUFeatures::kCSSC}, 1835 {"umin_64u_minmax_imm"_h, CPUFeatures::kCSSC}, 1836 }; 1837 1838 if (features.count(form_hash_) > 0) { 1839 scope.Record(features[form_hash_]); 1840 } 1841 } else { 1842 (it->second)(this, instr); 1843 } 1844 } 1845 1846 } // namespace aarch64 1847 } // namespace vixl