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