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.        */ \