xref: /src/contrib/llvm-project/compiler-rt/lib/builtins/aarch64/sme-abi-vg.c (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2 // See https://llvm.org/LICENSE.txt for license information.
3 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4 
5 #include "../cpu_model/aarch64.h"
6 
7 struct FEATURES {
8   unsigned long long features;
9 };
10 
11 extern struct FEATURES __aarch64_cpu_features;
12 
13 struct SME_STATE {
14   long PSTATE;
15   long TPIDR2_EL0;
16 };
17 
18 extern struct SME_STATE __arm_sme_state(void) __arm_streaming_compatible;
19 
20 extern bool __aarch64_has_sme_and_tpidr2_el0;
21 
22 #if __GNUC__ >= 9
23 #pragma GCC diagnostic ignored "-Wprio-ctor-dtor"
24 #endif
25 __attribute__((constructor(90))) static void get_aarch64_cpu_features(void) {
26   if (__atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED))
27     return;
28 
29   __init_cpu_features();
30 }
31 
32 __attribute__((target("sve"))) long
33 __arm_get_current_vg(void) __arm_streaming_compatible {
34   struct SME_STATE State = __arm_sme_state();
35   unsigned long long features =
36       __atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED);
37   bool HasSVE = features & (1ULL << FEAT_SVE);
38 
39   if (!HasSVE && !__aarch64_has_sme_and_tpidr2_el0)
40     return 0;
41 
42   if (HasSVE || (State.PSTATE & 1)) {
43     long vl;
44     __asm__ __volatile__("cntd %0" : "=r"(vl));
45     return vl;
46   }
47 
48   return 0;
49 }
50