AARCH64_NUM_FEATURES
};
+typedef uint64_t aarch64_feature_word;
+#define AARCH64_BITS_PER_FEATURE_WORD 64
+
+#define AA64_REPLICATE(SEP, BODY, ...) \
+ BODY (0, __VA_ARGS__) SEP \
+ BODY (1, __VA_ARGS__)
+
+/* Some useful SEP operators for use with replication. */
+#define REP_COMMA ,
+#define REP_SEMICOLON ;
+#define REP_OR_OR ||
+#define REP_AND_AND &&
+#define REP_PLUS +
+
+/* Not currently needed, but if an empty SEP is required define:
+ #define REP_NO_SEP
+ Then use REP_NO_SEP in the SEP field. */
+
+/* Used to generate one instance of VAL for each value of ELT (ELT is
+ not otherwise used). */
+#define AA64_REPVAL(ELT, VAL) VAL
+
+/* static_assert requires C11 (or C++11) or later. Support older
+ versions by disabling this check since compilers without this are
+ pretty uncommon these days. */
+#if ((defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L) \
+ || (defined __cplusplus && __cplusplus >= 201103L))
+static_assert ((AA64_REPLICATE (REP_PLUS, AA64_REPVAL,
+ AARCH64_BITS_PER_FEATURE_WORD))
+ >= AARCH64_NUM_FEATURES,
+ "Insufficient repetitions in AA64_REPLICATE()");
+#endif
+
/* These macros take an initial argument X that gives the index into
an aarch64_feature_set. The macros then return the bitmask for
that array index. */
/* A mask in which feature bit BIT is set and all other bits are clear. */
-#define AARCH64_UINT64_BIT(X, BIT) \
- ((X) == (BIT) / 64 ? 1ULL << (BIT) % 64 : 0)
+#define AARCH64_UINT64_BIT(X, BIT) \
+ ((X) == (BIT) / AARCH64_BITS_PER_FEATURE_WORD \
+ ? 1ULL << (BIT) % AARCH64_BITS_PER_FEATURE_WORD \
+ : 0)
/* A mask that includes only AARCH64_FEATURE_<NAME>. */
#define AARCH64_FEATBIT(X, NAME) \
/* CPU-specific features. */
typedef struct {
- uint64_t flags[(AARCH64_NUM_FEATURES + 63) / 64];
+ aarch64_feature_word flags[AA64_REPLICATE (REP_PLUS, AA64_REPVAL, 1)];
} aarch64_feature_set;
-#define AARCH64_CPU_HAS_FEATURE(CPU,FEAT) \
- ((~(CPU).flags[0] & AARCH64_FEATBIT (0, FEAT)) == 0 \
- && (~(CPU).flags[1] & AARCH64_FEATBIT (1, FEAT)) == 0)
+#define AARCH64_CPU_HAS_FEATURE_BODY(ELT, CPU, FEAT) \
+ ((~(CPU).flags[ELT] & AARCH64_FEATBIT (ELT, FEAT)) == 0)
+#define AARCH64_CPU_HAS_FEATURE(CPU, FEAT) \
+ (AA64_REPLICATE (REP_AND_AND, AARCH64_CPU_HAS_FEATURE_BODY, CPU, FEAT))
-#define AARCH64_CPU_HAS_ALL_FEATURES(CPU,FEAT) \
- ((~(CPU).flags[0] & (FEAT).flags[0]) == 0 \
- && (~(CPU).flags[1] & (FEAT).flags[1]) == 0)
+#define AARCH64_CPU_HAS_ALL_FEATURES_BODY(ELT, CPU, FEAT) \
+ ((~(CPU).flags[ELT] & (FEAT).flags[ELT]) == 0)
+#define AARCH64_CPU_HAS_ALL_FEATURES(CPU, FEAT) \
+ (AA64_REPLICATE (REP_AND_AND, AARCH64_CPU_HAS_ALL_FEATURES_BODY, CPU, FEAT))
+#define AARCH64_CPU_HAS_ANY_FEATURES_BODY(ELT, CPU, FEAT) \
+ (((CPU).flags[ELT] & (FEAT).flags[ELT]) != 0)
#define AARCH64_CPU_HAS_ANY_FEATURES(CPU,FEAT) \
- (((CPU).flags[0] & (FEAT).flags[0]) != 0 \
- || ((CPU).flags[1] & (FEAT).flags[1]) != 0)
+ (AA64_REPLICATE (REP_OR_OR, AARCH64_CPU_HAS_ANY_FEATURES_BODY, CPU, FEAT))
+#define AARCH64_SET_FEATURE_BODY(ELT, DEST, FEAT) \
+ (DEST).flags[ELT] = FEAT (ELT)
#define AARCH64_SET_FEATURE(DEST, FEAT) \
- ((DEST).flags[0] = FEAT (0), \
- (DEST).flags[1] = FEAT (1))
+ (AA64_REPLICATE (REP_COMMA, AARCH64_SET_FEATURE_BODY, DEST, FEAT))
+#define AARCH64_CLEAR_FEATURE_BODY(ELT, DEST, SRC, FEAT) \
+ (DEST).flags[ELT] = ((SRC).flags[ELT] \
+ & ~AARCH64_FEATBIT (ELT, FEAT))
#define AARCH64_CLEAR_FEATURE(DEST, SRC, FEAT) \
- ((DEST).flags[0] = (SRC).flags[0] & ~AARCH64_FEATBIT (0, FEAT), \
- (DEST).flags[1] = (SRC).flags[1] & ~AARCH64_FEATBIT (1, FEAT))
-
-#define AARCH64_MERGE_FEATURE_SETS(TARG,F1,F2) \
- do \
- { \
- (TARG).flags[0] = (F1).flags[0] | (F2).flags[0]; \
- (TARG).flags[1] = (F1).flags[1] | (F2).flags[1]; \
- } \
+ (AA64_REPLICATE (REP_COMMA, AARCH64_CLEAR_FEATURE_BODY, DEST, SRC, FEAT))
+
+#define AARCH64_MERGE_FEATURE_SETS_BODY(ELT, TARG, F1, F2) \
+ (TARG).flags[ELT] = (F1).flags[ELT] | (F2).flags[ELT];
+#define AARCH64_MERGE_FEATURE_SETS(TARG, F1, F2) \
+ do \
+ { \
+ AA64_REPLICATE (REP_SEMICOLON, \
+ AARCH64_MERGE_FEATURE_SETS_BODY, TARG, F1, F2); \
+ } \
while (0)
-#define AARCH64_CLEAR_FEATURES(TARG,F1,F2) \
- do \
- { \
- (TARG).flags[0] = (F1).flags[0] &~ (F2).flags[0]; \
- (TARG).flags[1] = (F1).flags[1] &~ (F2).flags[1]; \
- } \
+#define AARCH64_CLEAR_FEATURES_BODY(ELT, TARG, F1, F2) \
+ (TARG).flags[ELT] = (F1).flags[ELT] &~ (F2).flags[ELT];
+#define AARCH64_CLEAR_FEATURES(TARG,F1,F2) \
+ do \
+ { \
+ AA64_REPLICATE (REP_SEMICOLON, \
+ AARCH64_CLEAR_FEATURES_BODY, TARG, F1, F2); \
+ } \
while (0)
/* aarch64_feature_set initializers for no features and all features,
respectively. */
-#define AARCH64_NO_FEATURES { { 0, 0 } }
-#define AARCH64_ALL_FEATURES { { -1, -1 } }
+#define AARCH64_NO_FEATURES { { AA64_REPLICATE (REP_COMMA, AA64_REPVAL, 0) } }
+#define AARCH64_ALL_FEATURES { { AA64_REPLICATE (REP_COMMA, AA64_REPVAL, -1) } }
/* An aarch64_feature_set initializer for a single feature,
AARCH64_FEATURE_<FEAT>. */
-#define AARCH64_FEATURE(FEAT) \
- { { AARCH64_FEATBIT (0, FEAT), AARCH64_FEATBIT (1, FEAT) } }
+#define AARCH64_FEATURE_BODY(ELT, FEAT) \
+ AARCH64_FEATBIT (ELT, FEAT)
+#define AARCH64_FEATURE(FEAT) \
+ { { AA64_REPLICATE (REP_COMMA, AARCH64_FEATURE_BODY, FEAT) } }
/* An aarch64_feature_set initializer for a specific architecture version,
including all the features that are enabled by default for that architecture
version. */
-#define AARCH64_ARCH_FEATURES(ARCH) \
- { { AARCH64_ARCH_##ARCH (0), AARCH64_ARCH_##ARCH (1) } }
+#define AARCH64_ARCH_FEATURES_BODY(ELT, ARCH) \
+ AARCH64_ARCH_##ARCH (ELT)
+#define AARCH64_ARCH_FEATURES(ARCH) \
+ { { AA64_REPLICATE (REP_COMMA, AARCH64_ARCH_FEATURES_BODY, ARCH) } }
/* Used by AARCH64_CPU_FEATURES. */
#define AARCH64_OR_FEATURES_1(X, ARCH, F1) \
/* An aarch64_feature_set initializer for a CPU that implements architecture
version ARCH, and additionally provides the N features listed in "...". */
+#define AARCH64_CPU_FEATURES_BODY(ELT, ARCH, N, ...) \
+ AARCH64_OR_FEATURES_##N (ELT, ARCH, __VA_ARGS__)
#define AARCH64_CPU_FEATURES(ARCH, N, ...) \
- { { AARCH64_OR_FEATURES_##N (0, ARCH, __VA_ARGS__), \
- AARCH64_OR_FEATURES_##N (1, ARCH, __VA_ARGS__) } }
+ { { AA64_REPLICATE (REP_COMMA, AARCH64_CPU_FEATURES_BODY, \
+ ARCH, N, __VA_ARGS__) } }
/* An aarch64_feature_set initializer for the N features listed in "...". */
#define AARCH64_FEATURES(N, ...) \