Add missing ID register feature detection.
In particular, kUSCAT could appear in auxv, but would be ignored in the
ID registers, causing a test failure.
Change-Id: Id964ce4423bce4913aa4f75c077586a2e50d5caf
diff --git a/src/aarch64/cpu-aarch64.cc b/src/aarch64/cpu-aarch64.cc
index f5e4fca..277a8e6 100644
--- a/src/aarch64/cpu-aarch64.cc
+++ b/src/aarch64/cpu-aarch64.cc
@@ -66,17 +66,18 @@
const IDRegister::Field AA64ISAR1::kGPA(24);
const IDRegister::Field AA64ISAR1::kGPI(28);
const IDRegister::Field AA64ISAR1::kFRINTTS(32);
-const IDRegister::Field AA64ISAR1::kSB(36);
-const IDRegister::Field AA64ISAR1::kSPECRES(40);
const IDRegister::Field AA64MMFR1::kLO(16);
+const IDRegister::Field AA64MMFR2::kAT(32);
+
CPUFeatures AA64PFR0::GetCPUFeatures() const {
CPUFeatures f;
if (Get(kFP) >= 0) f.Combine(CPUFeatures::kFP);
if (Get(kFP) >= 1) f.Combine(CPUFeatures::kFPHalf);
if (Get(kAdvSIMD) >= 0) f.Combine(CPUFeatures::kNEON);
if (Get(kAdvSIMD) >= 1) f.Combine(CPUFeatures::kNEONHalf);
+ if (Get(kRAS) >= 1) f.Combine(CPUFeatures::kRAS);
if (Get(kSVE) >= 1) f.Combine(CPUFeatures::kSVE);
if (Get(kDIT) >= 1) f.Combine(CPUFeatures::kDIT);
return f;
@@ -111,6 +112,7 @@
CPUFeatures AA64ISAR1::GetCPUFeatures() const {
CPUFeatures f;
if (Get(kDPB) >= 1) f.Combine(CPUFeatures::kDCPoP);
+ if (Get(kDPB) >= 2) f.Combine(CPUFeatures::kDCCVADP);
if (Get(kJSCVT) >= 1) f.Combine(CPUFeatures::kJSCVT);
if (Get(kFCMA) >= 1) f.Combine(CPUFeatures::kFcma);
if (Get(kLRCPC) >= 1) f.Combine(CPUFeatures::kRCpc);
@@ -132,6 +134,12 @@
return f;
}
+CPUFeatures AA64MMFR2::GetCPUFeatures() const {
+ CPUFeatures f;
+ if (Get(kAT) >= 1) f.Combine(CPUFeatures::kUSCAT);
+ return f;
+}
+
int IDRegister::Get(IDRegister::Field field) const {
int msb = field.GetMsb();
int lsb = field.GetLsb();
@@ -163,46 +171,51 @@
// Map each set bit onto a feature. Ideally, we'd use HWCAP_* macros rather
// than explicit bits, but explicit bits allow us to identify features that
// the toolchain doesn't know about.
- static const CPUFeatures::Feature kFeatureBits[] = {
- // Bits 0-7
- CPUFeatures::kFP,
- CPUFeatures::kNEON,
- CPUFeatures::kNone, // "EVTSTRM", which VIXL doesn't track.
- CPUFeatures::kAES,
- CPUFeatures::kPmull1Q,
- CPUFeatures::kSHA1,
- CPUFeatures::kSHA2,
- CPUFeatures::kCRC32,
- // Bits 8-15
- CPUFeatures::kAtomics,
- CPUFeatures::kFPHalf,
- CPUFeatures::kNEONHalf,
- CPUFeatures::kIDRegisterEmulation,
- CPUFeatures::kRDM,
- CPUFeatures::kJSCVT,
- CPUFeatures::kFcma,
- CPUFeatures::kRCpc,
- // Bits 16-23
- CPUFeatures::kDCPoP,
- CPUFeatures::kSHA3,
- CPUFeatures::kSM3,
- CPUFeatures::kSM4,
- CPUFeatures::kDotProduct,
- CPUFeatures::kSHA512,
- CPUFeatures::kSVE,
- CPUFeatures::kFHM,
- // Bits 24-27
- CPUFeatures::kDIT,
- CPUFeatures::kUSCAT,
- CPUFeatures::kRCpcImm,
- CPUFeatures::kFlagM
- // Bits 28-31 are unassigned.
- };
+ static const CPUFeatures::Feature kFeatureBits[] =
+ {// Bits 0-7
+ CPUFeatures::kFP,
+ CPUFeatures::kNEON,
+ CPUFeatures::kNone, // "EVTSTRM", which VIXL doesn't track.
+ CPUFeatures::kAES,
+ CPUFeatures::kPmull1Q,
+ CPUFeatures::kSHA1,
+ CPUFeatures::kSHA2,
+ CPUFeatures::kCRC32,
+ // Bits 8-15
+ CPUFeatures::kAtomics,
+ CPUFeatures::kFPHalf,
+ CPUFeatures::kNEONHalf,
+ CPUFeatures::kIDRegisterEmulation,
+ CPUFeatures::kRDM,
+ CPUFeatures::kJSCVT,
+ CPUFeatures::kFcma,
+ CPUFeatures::kRCpc,
+ // Bits 16-23
+ CPUFeatures::kDCPoP,
+ CPUFeatures::kSHA3,
+ CPUFeatures::kSM3,
+ CPUFeatures::kSM4,
+ CPUFeatures::kDotProduct,
+ CPUFeatures::kSHA512,
+ CPUFeatures::kSVE,
+ CPUFeatures::kFHM,
+ // Bits 24-27
+ CPUFeatures::kDIT,
+ CPUFeatures::kUSCAT,
+ CPUFeatures::kRCpcImm,
+ CPUFeatures::kFlagM,
+ // Bits 28-31
+ CPUFeatures::kNone, // "ssbs"
+ CPUFeatures::kNone, // "sb"
+ CPUFeatures::kPAuth,
+ CPUFeatures::kPAuthGeneric};
static const size_t kFeatureBitCount =
sizeof(kFeatureBits) / sizeof(kFeatureBits[0]);
unsigned long auxv = getauxval(AT_HWCAP); // NOLINT(runtime/int)
+ // TODO: Also examine AT_HWCAP2.
+
VIXL_STATIC_ASSERT(kFeatureBitCount < (sizeof(auxv) * kBitsPerByte));
for (size_t i = 0; i < kFeatureBitCount; i++) {
if (auxv & (1UL << i)) features.Combine(kFeatureBits[i]);
@@ -225,10 +238,10 @@
return NAME(value); \
}
#else // __aarch64__
-#define VIXL_READ_ID_REG(NAME) \
- NAME CPU::Read##NAME() { \
- /* TODO: Use VIXL_UNREACHABLE once it works in release builds. */ \
- VIXL_ABORT(); \
+#define VIXL_READ_ID_REG(NAME) \
+ NAME CPU::Read##NAME() { \
+ VIXL_UNREACHABLE(); \
+ return NAME(0); \
}
#endif // __aarch64__
diff --git a/src/aarch64/cpu-aarch64.h b/src/aarch64/cpu-aarch64.h
index d2b2ee8..ec6ea9f 100644
--- a/src/aarch64/cpu-aarch64.h
+++ b/src/aarch64/cpu-aarch64.h
@@ -92,6 +92,7 @@
private:
static const Field kFP;
static const Field kAdvSIMD;
+ static const Field kRAS;
static const Field kSVE;
static const Field kDIT;
};
@@ -143,8 +144,6 @@
static const Field kGPA;
static const Field kGPI;
static const Field kFRINTTS;
- static const Field kSB;
- static const Field kSPECRES;
};
class AA64MMFR1 : public IDRegister {
@@ -157,6 +156,16 @@
static const Field kLO;
};
+class AA64MMFR2 : public IDRegister {
+ public:
+ explicit AA64MMFR2(uint64_t value) : IDRegister(value) {}
+
+ CPUFeatures GetCPUFeatures() const;
+
+ private:
+ static const Field kAT;
+};
+
class CPU {
public:
// Initialise CPU support.
@@ -216,7 +225,8 @@
V(AA64PFR1) \
V(AA64ISAR0) \
V(AA64ISAR1) \
- V(AA64MMFR1)
+ V(AA64MMFR1) \
+ V(AA64MMFR2)
#define VIXL_READ_ID_REG(NAME) static NAME Read##NAME();
// On native AArch64 platforms, read the named CPU ID registers. These require
diff --git a/src/cpu-features.h b/src/cpu-features.h
index 50ddc26..42eb4f4 100644
--- a/src/cpu-features.h
+++ b/src/cpu-features.h
@@ -68,18 +68,18 @@
/* Data cache clean to the point of persistence: DC CVAP. */ \
V(kDCPoP, "DCPoP", "dcpop") \
/* Data cache clean to the point of deep persistence: DC CVADP. */ \
- V(kDCCVADP, "DCCVADP", NULL) \
+ V(kDCCVADP, "DCCVADP", "dcpodp") \
/* Cryptographic support instructions. */ \
V(kSHA3, "SHA3", "sha3") \
V(kSHA512, "SHA512", "sha512") \
V(kSM3, "SM3", "sm3") \
V(kSM4, "SM4", "sm4") \
/* Pointer authentication for addresses. */ \
- V(kPAuth, "PAuth", NULL) \
+ V(kPAuth, "PAuth", "paca") \
/* Pointer authentication for addresses uses QARMA. */ \
V(kPAuthQARMA, "PAuthQARMA", NULL) \
/* Generic authentication (using the PACGA instruction). */ \
- V(kPAuthGeneric, "PAuthGeneric", NULL) \
+ V(kPAuthGeneric, "PAuthGeneric", "pacg") \
/* Generic authentication uses QARMA. */ \
V(kPAuthGenericQARMA, "PAuthGenericQARMA", NULL) \
/* JavaScript-style FP -> integer conversion instruction: FJCVTZS. */ \