This patch can obtain the cpucfg value at runtime and extract the
flag bits of features for function selection.

libgcc/ChangeLog:

        * config/loongarch/t-loongarch64: Add cpuinfo.c to LIB2ADD.
        * config/loongarch/cpuinfo.c: New file.

---
 libgcc/config/loongarch/cpuinfo.c     | 77 +++++++++++++++++++++++++++
 libgcc/config/loongarch/t-loongarch64 |  2 +
 2 files changed, 79 insertions(+)
 create mode 100644 libgcc/config/loongarch/cpuinfo.c

diff --git a/libgcc/config/loongarch/cpuinfo.c 
b/libgcc/config/loongarch/cpuinfo.c
new file mode 100644
index 00000000000..bec602459b1
--- /dev/null
+++ b/libgcc/config/loongarch/cpuinfo.c
@@ -0,0 +1,77 @@
+/* CPU feature detection for LoongArch architecture.
+   Copyright (C) 2025 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "common/config/loongarch/cpu-features.h"
+
+#define CPUCFG1_LA64       2ULL << 0
+#define CPUCFG1_UAL        1ULL << 20
+#define CPUCFG2_LSX        1ULL << 6
+#define CPUCFG2_LASX       1ULL << 7
+#define CPUCFG2_FRECIPE            1ULL << 25
+#define CPUCFG2_DIV32      1ULL << 26
+#define CPUCFG2_LAM_BH     1ULL << 27
+#define CPUCFG2_LAMCAS     1ULL << 28
+#define CPUCFG2_SCQ        1ULL << 30
+#define CPUCFG3_LD_SEQ_SA   1ULL << 23
+
+struct {
+    loongarch_fmv_feature_mask features;
+} __loongarch_feature_bits __attribute__ ((visibility ("hidden"), nocommon));
+
+void __init_loongarch_features_resolver (void);
+void
+__init_loongarch_features_resolver (void)
+{
+  if (__atomic_load_n (&__loongarch_feature_bits.features, __ATOMIC_RELAXED))
+    return;
+
+  loongarch_fmv_feature_mask feat = 0ULL;
+#define setCPUFeature(F) feat |= 1ULL << F;
+  unsigned int CPUCFG1 = __builtin_loongarch_cpucfg (1);
+  unsigned int CPUCFG2 = __builtin_loongarch_cpucfg (2);
+  unsigned int CPUCFG3 = __builtin_loongarch_cpucfg (3);
+
+  if (CPUCFG1 & CPUCFG1_LA64)
+    setCPUFeature (FEAT_LA64);
+  if (CPUCFG1 & CPUCFG1_UAL)
+    setCPUFeature (FEAT_UAL);
+  if (CPUCFG2 & CPUCFG2_LSX)
+    setCPUFeature (FEAT_LSX);
+  if (CPUCFG2 & CPUCFG2_LASX)
+    setCPUFeature (FEAT_LASX);
+  if (CPUCFG2 & CPUCFG2_FRECIPE)
+    setCPUFeature (FEAT_FRECIPE);
+  if (CPUCFG2 & CPUCFG2_DIV32)
+    setCPUFeature (FEAT_DIV32);
+  if (CPUCFG2 & CPUCFG2_LAM_BH)
+    setCPUFeature (FEAT_LAM_BH);
+  if (CPUCFG2 & CPUCFG2_LAMCAS)
+    setCPUFeature (FEAT_LAMCAS);
+  if (CPUCFG2 & CPUCFG2_SCQ)
+    setCPUFeature (FEAT_SCQ);
+  if (CPUCFG3 & CPUCFG3_LD_SEQ_SA)
+    setCPUFeature (FEAT_LD_SEQ_SA);
+#undef setCPUFeature
+  __atomic_store_n (&__loongarch_feature_bits.features, feat, 
__ATOMIC_RELAXED);
+}
diff --git a/libgcc/config/loongarch/t-loongarch64 
b/libgcc/config/loongarch/t-loongarch64
index a1e3513e288..20d15207515 100644
--- a/libgcc/config/loongarch/t-loongarch64
+++ b/libgcc/config/loongarch/t-loongarch64
@@ -1 +1,3 @@
+LIB2ADD += $(srcdir)/config/loongarch/cpuinfo.c
+
 softfp_int_modes += ti
-- 
2.34.1

Reply via email to