Path: blob/master/dep/vixl/src/aarch64/cpu-aarch64.cc
4261 views
// Copyright 2015, VIXL authors1// All rights reserved.2//3// Redistribution and use in source and binary forms, with or without4// modification, are permitted provided that the following conditions are met:5//6// * Redistributions of source code must retain the above copyright notice,7// this list of conditions and the following disclaimer.8// * Redistributions in binary form must reproduce the above copyright notice,9// this list of conditions and the following disclaimer in the documentation10// and/or other materials provided with the distribution.11// * Neither the name of ARM Limited nor the names of its contributors may be12// used to endorse or promote products derived from this software without13// specific prior written permission.14//15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND16// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED17// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE18// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE19// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR21// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER22// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,23// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE24// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.2526#if defined(__aarch64__) && (defined(__ANDROID__) || defined(__linux__))27#include <sys/auxv.h>28#define VIXL_USE_LINUX_HWCAP 129#endif3031#include "../utils-vixl.h"3233#include "cpu-aarch64.h"3435namespace vixl {36namespace aarch64 {373839const IDRegister::Field AA64PFR0::kFP(16, Field::kSigned);40const IDRegister::Field AA64PFR0::kAdvSIMD(20, Field::kSigned);41const IDRegister::Field AA64PFR0::kRAS(28);42const IDRegister::Field AA64PFR0::kSVE(32);43const IDRegister::Field AA64PFR0::kDIT(48);44const IDRegister::Field AA64PFR0::kCSV2(56);45const IDRegister::Field AA64PFR0::kCSV3(60);4647const IDRegister::Field AA64PFR1::kBT(0);48const IDRegister::Field AA64PFR1::kSSBS(4);49const IDRegister::Field AA64PFR1::kMTE(8);50const IDRegister::Field AA64PFR1::kSME(24);5152const IDRegister::Field AA64ISAR0::kAES(4);53const IDRegister::Field AA64ISAR0::kSHA1(8);54const IDRegister::Field AA64ISAR0::kSHA2(12);55const IDRegister::Field AA64ISAR0::kCRC32(16);56const IDRegister::Field AA64ISAR0::kAtomic(20);57const IDRegister::Field AA64ISAR0::kRDM(28);58const IDRegister::Field AA64ISAR0::kSHA3(32);59const IDRegister::Field AA64ISAR0::kSM3(36);60const IDRegister::Field AA64ISAR0::kSM4(40);61const IDRegister::Field AA64ISAR0::kDP(44);62const IDRegister::Field AA64ISAR0::kFHM(48);63const IDRegister::Field AA64ISAR0::kTS(52);64const IDRegister::Field AA64ISAR0::kRNDR(60);6566const IDRegister::Field AA64ISAR1::kDPB(0);67const IDRegister::Field AA64ISAR1::kAPA(4);68const IDRegister::Field AA64ISAR1::kAPI(8);69const IDRegister::Field AA64ISAR1::kJSCVT(12);70const IDRegister::Field AA64ISAR1::kFCMA(16);71const IDRegister::Field AA64ISAR1::kLRCPC(20);72const IDRegister::Field AA64ISAR1::kGPA(24);73const IDRegister::Field AA64ISAR1::kGPI(28);74const IDRegister::Field AA64ISAR1::kFRINTTS(32);75const IDRegister::Field AA64ISAR1::kSB(36);76const IDRegister::Field AA64ISAR1::kSPECRES(40);77const IDRegister::Field AA64ISAR1::kBF16(44);78const IDRegister::Field AA64ISAR1::kDGH(48);79const IDRegister::Field AA64ISAR1::kI8MM(52);8081const IDRegister::Field AA64ISAR2::kWFXT(0);82const IDRegister::Field AA64ISAR2::kRPRES(4);83const IDRegister::Field AA64ISAR2::kMOPS(16);84const IDRegister::Field AA64ISAR2::kCSSC(52);8586const IDRegister::Field AA64MMFR0::kECV(60);8788const IDRegister::Field AA64MMFR1::kLO(16);89const IDRegister::Field AA64MMFR1::kAFP(44);9091const IDRegister::Field AA64MMFR2::kAT(32);9293const IDRegister::Field AA64ZFR0::kSVEver(0);94const IDRegister::Field AA64ZFR0::kAES(4);95const IDRegister::Field AA64ZFR0::kBitPerm(16);96const IDRegister::Field AA64ZFR0::kBF16(20);97const IDRegister::Field AA64ZFR0::kSHA3(32);98const IDRegister::Field AA64ZFR0::kSM4(40);99const IDRegister::Field AA64ZFR0::kI8MM(44);100const IDRegister::Field AA64ZFR0::kF32MM(52);101const IDRegister::Field AA64ZFR0::kF64MM(56);102103const IDRegister::Field AA64SMFR0::kSMEf32f32(32, 1);104const IDRegister::Field AA64SMFR0::kSMEb16f32(34, 1);105const IDRegister::Field AA64SMFR0::kSMEf16f32(35, 1);106const IDRegister::Field AA64SMFR0::kSMEi8i32(36);107const IDRegister::Field AA64SMFR0::kSMEf64f64(48, 1);108const IDRegister::Field AA64SMFR0::kSMEi16i64(52);109const IDRegister::Field AA64SMFR0::kSMEfa64(63, 1);110111CPUFeatures AA64PFR0::GetCPUFeatures() const {112CPUFeatures f;113if (Get(kFP) >= 0) f.Combine(CPUFeatures::kFP);114if (Get(kFP) >= 1) f.Combine(CPUFeatures::kFPHalf);115if (Get(kAdvSIMD) >= 0) f.Combine(CPUFeatures::kNEON);116if (Get(kAdvSIMD) >= 1) f.Combine(CPUFeatures::kNEONHalf);117if (Get(kRAS) >= 1) f.Combine(CPUFeatures::kRAS);118if (Get(kSVE) >= 1) f.Combine(CPUFeatures::kSVE);119if (Get(kDIT) >= 1) f.Combine(CPUFeatures::kDIT);120if (Get(kCSV2) >= 1) f.Combine(CPUFeatures::kCSV2);121if (Get(kCSV2) >= 2) f.Combine(CPUFeatures::kSCXTNUM);122if (Get(kCSV3) >= 1) f.Combine(CPUFeatures::kCSV3);123return f;124}125126CPUFeatures AA64PFR1::GetCPUFeatures() const {127CPUFeatures f;128if (Get(kBT) >= 1) f.Combine(CPUFeatures::kBTI);129if (Get(kSSBS) >= 1) f.Combine(CPUFeatures::kSSBS);130if (Get(kSSBS) >= 2) f.Combine(CPUFeatures::kSSBSControl);131if (Get(kMTE) >= 1) f.Combine(CPUFeatures::kMTEInstructions);132if (Get(kMTE) >= 2) f.Combine(CPUFeatures::kMTE);133if (Get(kMTE) >= 3) f.Combine(CPUFeatures::kMTE3);134if (Get(kSME) >= 1) f.Combine(CPUFeatures::kSME);135return f;136}137138CPUFeatures AA64ISAR0::GetCPUFeatures() const {139CPUFeatures f;140if (Get(kAES) >= 1) f.Combine(CPUFeatures::kAES);141if (Get(kAES) >= 2) f.Combine(CPUFeatures::kPmull1Q);142if (Get(kSHA1) >= 1) f.Combine(CPUFeatures::kSHA1);143if (Get(kSHA2) >= 1) f.Combine(CPUFeatures::kSHA2);144if (Get(kSHA2) >= 2) f.Combine(CPUFeatures::kSHA512);145if (Get(kCRC32) >= 1) f.Combine(CPUFeatures::kCRC32);146if (Get(kAtomic) >= 1) f.Combine(CPUFeatures::kAtomics);147if (Get(kRDM) >= 1) f.Combine(CPUFeatures::kRDM);148if (Get(kSHA3) >= 1) f.Combine(CPUFeatures::kSHA3);149if (Get(kSM3) >= 1) f.Combine(CPUFeatures::kSM3);150if (Get(kSM4) >= 1) f.Combine(CPUFeatures::kSM4);151if (Get(kDP) >= 1) f.Combine(CPUFeatures::kDotProduct);152if (Get(kFHM) >= 1) f.Combine(CPUFeatures::kFHM);153if (Get(kTS) >= 1) f.Combine(CPUFeatures::kFlagM);154if (Get(kTS) >= 2) f.Combine(CPUFeatures::kAXFlag);155if (Get(kRNDR) >= 1) f.Combine(CPUFeatures::kRNG);156return f;157}158159CPUFeatures AA64ISAR1::GetCPUFeatures() const {160CPUFeatures f;161if (Get(kDPB) >= 1) f.Combine(CPUFeatures::kDCPoP);162if (Get(kDPB) >= 2) f.Combine(CPUFeatures::kDCCVADP);163if (Get(kJSCVT) >= 1) f.Combine(CPUFeatures::kJSCVT);164if (Get(kFCMA) >= 1) f.Combine(CPUFeatures::kFcma);165if (Get(kLRCPC) >= 1) f.Combine(CPUFeatures::kRCpc);166if (Get(kLRCPC) >= 2) f.Combine(CPUFeatures::kRCpcImm);167if (Get(kFRINTTS) >= 1) f.Combine(CPUFeatures::kFrintToFixedSizedInt);168if (Get(kSB) >= 1) f.Combine(CPUFeatures::kSB);169if (Get(kSPECRES) >= 1) f.Combine(CPUFeatures::kSPECRES);170if (Get(kBF16) >= 1) f.Combine(CPUFeatures::kBF16);171if (Get(kBF16) >= 2) f.Combine(CPUFeatures::kEBF16);172if (Get(kDGH) >= 1) f.Combine(CPUFeatures::kDGH);173if (Get(kI8MM) >= 1) f.Combine(CPUFeatures::kI8MM);174175// Only one of these fields should be non-zero, but they have the same176// encodings, so merge the logic.177int apx = std::max(Get(kAPI), Get(kAPA));178if (apx >= 1) {179f.Combine(CPUFeatures::kPAuth);180// APA (rather than API) indicates QARMA.181if (Get(kAPA) >= 1) f.Combine(CPUFeatures::kPAuthQARMA);182if (apx == 0b0010) f.Combine(CPUFeatures::kPAuthEnhancedPAC);183if (apx >= 0b0011) f.Combine(CPUFeatures::kPAuthEnhancedPAC2);184if (apx >= 0b0100) f.Combine(CPUFeatures::kPAuthFPAC);185if (apx >= 0b0101) f.Combine(CPUFeatures::kPAuthFPACCombined);186}187188if (Get(kGPI) >= 1) f.Combine(CPUFeatures::kPAuthGeneric);189if (Get(kGPA) >= 1) {190f.Combine(CPUFeatures::kPAuthGeneric, CPUFeatures::kPAuthGenericQARMA);191}192return f;193}194195CPUFeatures AA64ISAR2::GetCPUFeatures() const {196CPUFeatures f;197if (Get(kWFXT) >= 2) f.Combine(CPUFeatures::kWFXT);198if (Get(kRPRES) >= 1) f.Combine(CPUFeatures::kRPRES);199if (Get(kMOPS) >= 1) f.Combine(CPUFeatures::kMOPS);200if (Get(kCSSC) >= 1) f.Combine(CPUFeatures::kCSSC);201return f;202}203204CPUFeatures AA64MMFR0::GetCPUFeatures() const {205CPUFeatures f;206if (Get(kECV) >= 1) f.Combine(CPUFeatures::kECV);207return f;208}209210CPUFeatures AA64MMFR1::GetCPUFeatures() const {211CPUFeatures f;212if (Get(kLO) >= 1) f.Combine(CPUFeatures::kLORegions);213if (Get(kAFP) >= 1) f.Combine(CPUFeatures::kAFP);214return f;215}216217CPUFeatures AA64MMFR2::GetCPUFeatures() const {218CPUFeatures f;219if (Get(kAT) >= 1) f.Combine(CPUFeatures::kUSCAT);220return f;221}222223CPUFeatures AA64ZFR0::GetCPUFeatures() const {224// This register is only available with SVE, but reads-as-zero in its absence,225// so it's always safe to read it.226CPUFeatures f;227if (Get(kF64MM) >= 1) f.Combine(CPUFeatures::kSVEF64MM);228if (Get(kF32MM) >= 1) f.Combine(CPUFeatures::kSVEF32MM);229if (Get(kI8MM) >= 1) f.Combine(CPUFeatures::kSVEI8MM);230if (Get(kSM4) >= 1) f.Combine(CPUFeatures::kSVESM4);231if (Get(kSHA3) >= 1) f.Combine(CPUFeatures::kSVESHA3);232if (Get(kBF16) >= 1) f.Combine(CPUFeatures::kSVEBF16);233if (Get(kBF16) >= 2) f.Combine(CPUFeatures::kSVE_EBF16);234if (Get(kBitPerm) >= 1) f.Combine(CPUFeatures::kSVEBitPerm);235if (Get(kAES) >= 1) f.Combine(CPUFeatures::kSVEAES);236if (Get(kAES) >= 2) f.Combine(CPUFeatures::kSVEPmull128);237if (Get(kSVEver) >= 1) f.Combine(CPUFeatures::kSVE2);238return f;239}240241CPUFeatures AA64SMFR0::GetCPUFeatures() const {242CPUFeatures f;243if (Get(kSMEf32f32) >= 1) f.Combine(CPUFeatures::kSMEf32f32);244if (Get(kSMEb16f32) >= 1) f.Combine(CPUFeatures::kSMEb16f32);245if (Get(kSMEf16f32) >= 1) f.Combine(CPUFeatures::kSMEf16f32);246if (Get(kSMEi8i32) >= 15) f.Combine(CPUFeatures::kSMEi8i32);247if (Get(kSMEf64f64) >= 1) f.Combine(CPUFeatures::kSMEf64f64);248if (Get(kSMEi16i64) >= 15) f.Combine(CPUFeatures::kSMEi16i64);249if (Get(kSMEfa64) >= 1) f.Combine(CPUFeatures::kSMEfa64);250return f;251}252253int IDRegister::Get(IDRegister::Field field) const {254int msb = field.GetMsb();255int lsb = field.GetLsb();256VIXL_STATIC_ASSERT(static_cast<size_t>(Field::kMaxWidthInBits) <257(sizeof(int) * kBitsPerByte));258switch (field.GetType()) {259case Field::kSigned:260return static_cast<int>(ExtractSignedBitfield64(msb, lsb, value_));261case Field::kUnsigned:262return static_cast<int>(ExtractUnsignedBitfield64(msb, lsb, value_));263}264VIXL_UNREACHABLE();265return 0;266}267268CPUFeatures CPU::InferCPUFeaturesFromIDRegisters() {269CPUFeatures f;270#define VIXL_COMBINE_ID_REG(NAME, MRS_ARG) \271f.Combine(Read##NAME().GetCPUFeatures());272VIXL_AARCH64_ID_REG_LIST(VIXL_COMBINE_ID_REG)273#undef VIXL_COMBINE_ID_REG274return f;275}276277CPUFeatures CPU::InferCPUFeaturesFromOS(278CPUFeatures::QueryIDRegistersOption option) {279CPUFeatures features;280281#ifdef VIXL_USE_LINUX_HWCAP282// Map each set bit onto a feature. Ideally, we'd use HWCAP_* macros rather283// than explicit bits, but explicit bits allow us to identify features that284// the toolchain doesn't know about.285static const CPUFeatures::Feature kFeatureBitsLow[] =286{// Bits 0-7287CPUFeatures::kFP,288CPUFeatures::kNEON,289CPUFeatures::kNone, // "EVTSTRM", which VIXL doesn't track.290CPUFeatures::kAES,291CPUFeatures::kPmull1Q,292CPUFeatures::kSHA1,293CPUFeatures::kSHA2,294CPUFeatures::kCRC32,295// Bits 8-15296CPUFeatures::kAtomics,297CPUFeatures::kFPHalf,298CPUFeatures::kNEONHalf,299CPUFeatures::kIDRegisterEmulation,300CPUFeatures::kRDM,301CPUFeatures::kJSCVT,302CPUFeatures::kFcma,303CPUFeatures::kRCpc,304// Bits 16-23305CPUFeatures::kDCPoP,306CPUFeatures::kSHA3,307CPUFeatures::kSM3,308CPUFeatures::kSM4,309CPUFeatures::kDotProduct,310CPUFeatures::kSHA512,311CPUFeatures::kSVE,312CPUFeatures::kFHM,313// Bits 24-31314CPUFeatures::kDIT,315CPUFeatures::kUSCAT,316CPUFeatures::kRCpcImm,317CPUFeatures::kFlagM,318CPUFeatures::kSSBSControl,319CPUFeatures::kSB,320CPUFeatures::kPAuth,321CPUFeatures::kPAuthGeneric};322VIXL_STATIC_ASSERT(ArrayLength(kFeatureBitsLow) < 64);323324static const CPUFeatures::Feature kFeatureBitsHigh[] =325{// Bits 0-7326CPUFeatures::kDCCVADP,327CPUFeatures::kSVE2,328CPUFeatures::kSVEAES,329CPUFeatures::kSVEPmull128,330CPUFeatures::kSVEBitPerm,331CPUFeatures::kSVESHA3,332CPUFeatures::kSVESM4,333CPUFeatures::kAXFlag,334// Bits 8-15335CPUFeatures::kFrintToFixedSizedInt,336CPUFeatures::kSVEI8MM,337CPUFeatures::kSVEF32MM,338CPUFeatures::kSVEF64MM,339CPUFeatures::kSVEBF16,340CPUFeatures::kI8MM,341CPUFeatures::kBF16,342CPUFeatures::kDGH,343// Bits 16-23344CPUFeatures::kRNG,345CPUFeatures::kBTI,346CPUFeatures::kMTE,347CPUFeatures::kECV,348CPUFeatures::kAFP,349CPUFeatures::kRPRES,350CPUFeatures::kMTE3,351CPUFeatures::kSME,352// Bits 24-31353CPUFeatures::kSMEi16i64,354CPUFeatures::kSMEf64f64,355CPUFeatures::kSMEi8i32,356CPUFeatures::kSMEf16f32,357CPUFeatures::kSMEb16f32,358CPUFeatures::kSMEf32f32,359CPUFeatures::kSMEfa64,360CPUFeatures::kWFXT,361// Bits 32-39362CPUFeatures::kEBF16,363CPUFeatures::kSVE_EBF16};364VIXL_STATIC_ASSERT(ArrayLength(kFeatureBitsHigh) < 64);365366auto combine_features = [&features](uint64_t hwcap,367const CPUFeatures::Feature* feature_array,368size_t features_size) {369for (size_t i = 0; i < features_size; i++) {370if (hwcap & (UINT64_C(1) << i)) features.Combine(feature_array[i]);371}372};373374uint64_t hwcap_low = getauxval(AT_HWCAP);375uint64_t hwcap_high = getauxval(AT_HWCAP2);376377combine_features(hwcap_low, kFeatureBitsLow, ArrayLength(kFeatureBitsLow));378combine_features(hwcap_high, kFeatureBitsHigh, ArrayLength(kFeatureBitsHigh));379380// MTE support from HWCAP2 signifies FEAT_MTE1 and FEAT_MTE2 support381if (features.Has(CPUFeatures::kMTE)) {382features.Combine(CPUFeatures::kMTEInstructions);383}384#endif // VIXL_USE_LINUX_HWCAP385386if ((option == CPUFeatures::kQueryIDRegistersIfAvailable) &&387(features.Has(CPUFeatures::kIDRegisterEmulation))) {388features.Combine(InferCPUFeaturesFromIDRegisters());389}390return features;391}392393394#ifdef __aarch64__395#define VIXL_READ_ID_REG(NAME, MRS_ARG) \396NAME CPU::Read##NAME() { \397uint64_t value = 0; \398__asm__("mrs %0, " MRS_ARG : "=r"(value)); \399return NAME(value); \400}401#else // __aarch64__402#define VIXL_READ_ID_REG(NAME, MRS_ARG) \403NAME CPU::Read##NAME() { \404VIXL_UNREACHABLE(); \405return NAME(0); \406}407#endif // __aarch64__408409VIXL_AARCH64_ID_REG_LIST(VIXL_READ_ID_REG)410411#undef VIXL_READ_ID_REG412413414// Initialise to smallest possible cache size.415unsigned CPU::dcache_line_size_ = 1;416unsigned CPU::icache_line_size_ = 1;417418419// Currently computes I and D cache line size.420void CPU::SetUp() {421uint32_t cache_type_register = GetCacheType();422423// The cache type register holds information about the caches, including I424// D caches line size.425static const int kDCacheLineSizeShift = 16;426static const int kICacheLineSizeShift = 0;427static const uint32_t kDCacheLineSizeMask = 0xf << kDCacheLineSizeShift;428static const uint32_t kICacheLineSizeMask = 0xf << kICacheLineSizeShift;429430// The cache type register holds the size of the I and D caches in words as431// a power of two.432uint32_t dcache_line_size_power_of_two =433(cache_type_register & kDCacheLineSizeMask) >> kDCacheLineSizeShift;434uint32_t icache_line_size_power_of_two =435(cache_type_register & kICacheLineSizeMask) >> kICacheLineSizeShift;436437dcache_line_size_ = 4 << dcache_line_size_power_of_two;438icache_line_size_ = 4 << icache_line_size_power_of_two;439}440441442uint32_t CPU::GetCacheType() {443#ifdef __aarch64__444uint64_t cache_type_register;445// Copy the content of the cache type register to a core register.446__asm__ __volatile__("mrs %[ctr], ctr_el0" // NOLINT(runtime/references)447: [ctr] "=r"(cache_type_register));448VIXL_ASSERT(IsUint32(cache_type_register));449return static_cast<uint32_t>(cache_type_register);450#else451// This will lead to a cache with 1 byte long lines, which is fine since452// neither EnsureIAndDCacheCoherency nor the simulator will need this453// information.454return 0;455#endif456}457458459// Query the SVE vector length. This requires CPUFeatures::kSVE.460int CPU::ReadSVEVectorLengthInBits() {461#ifdef __aarch64__462uint64_t vl;463// To support compilers that don't understand `rdvl`, encode the value464// directly and move it manually.465__asm__(466" .word 0x04bf5100\n" // rdvl x0, #8467" mov %[vl], x0\n"468: [vl] "=r"(vl)469:470: "x0");471VIXL_ASSERT(vl <= INT_MAX);472return static_cast<int>(vl);473#else474VIXL_UNREACHABLE();475return 0;476#endif477}478479480void CPU::EnsureIAndDCacheCoherency(void* address, size_t length) {481#ifdef __aarch64__482// Implement the cache synchronisation for all targets where AArch64 is the483// host, even if we're building the simulator for an AAarch64 host. This484// allows for cases where the user wants to simulate code as well as run it485// natively.486487if (length == 0) {488return;489}490491// The code below assumes user space cache operations are allowed.492493// Work out the line sizes for each cache, and use them to determine the494// start addresses.495uintptr_t start = reinterpret_cast<uintptr_t>(address);496uintptr_t dsize = static_cast<uintptr_t>(dcache_line_size_);497uintptr_t isize = static_cast<uintptr_t>(icache_line_size_);498uintptr_t dline = start & ~(dsize - 1);499uintptr_t iline = start & ~(isize - 1);500501// Cache line sizes are always a power of 2.502VIXL_ASSERT(IsPowerOf2(dsize));503VIXL_ASSERT(IsPowerOf2(isize));504uintptr_t end = start + length;505506do {507__asm__ __volatile__(508// Clean each line of the D cache containing the target data.509//510// dc : Data Cache maintenance511// c : Clean512// va : by (Virtual) Address513// u : to the point of Unification514// The point of unification for a processor is the point by which the515// instruction and data caches are guaranteed to see the same copy of a516// memory location. See ARM DDI 0406B page B2-12 for more information.517" dc cvau, %[dline]\n"518:519: [dline] "r"(dline)520// This code does not write to memory, but the "memory" dependency521// prevents GCC from reordering the code.522: "memory");523dline += dsize;524} while (dline < end);525526__asm__ __volatile__(527// Make sure that the data cache operations (above) complete before the528// instruction cache operations (below).529//530// dsb : Data Synchronisation Barrier531// ish : Inner SHareable domain532//533// The point of unification for an Inner Shareable shareability domain is534// the point by which the instruction and data caches of all the535// processors536// in that Inner Shareable shareability domain are guaranteed to see the537// same copy of a memory location. See ARM DDI 0406B page B2-12 for more538// information.539" dsb ish\n"540:541:542: "memory");543544do {545__asm__ __volatile__(546// Invalidate each line of the I cache containing the target data.547//548// ic : Instruction Cache maintenance549// i : Invalidate550// va : by Address551// u : to the point of Unification552" ic ivau, %[iline]\n"553:554: [iline] "r"(iline)555: "memory");556iline += isize;557} while (iline < end);558559__asm__ __volatile__(560// Make sure that the instruction cache operations (above) take effect561// before the isb (below).562" dsb ish\n"563564// Ensure that any instructions already in the pipeline are discarded and565// reloaded from the new data.566// isb : Instruction Synchronisation Barrier567" isb\n"568:569:570: "memory");571#else572// If the host isn't AArch64, we must be using the simulator, so this function573// doesn't have to do anything.574USE(address, length);575#endif576}577578579} // namespace aarch64580} // namespace vixl581582583