(root)/
gcc-13.2.0/
libatomic/
config/
x86/
host-config.h
       1  /* Copyright (C) 2012-2023 Free Software Foundation, Inc.
       2     Contributed by Richard Henderson <rth@redhat.com>.
       3  
       4     This file is part of the GNU Atomic Library (libatomic).
       5  
       6     Libatomic is free software; you can redistribute it and/or modify it
       7     under the terms of the GNU General Public License as published by
       8     the Free Software Foundation; either version 3 of the License, or
       9     (at your option) any later version.
      10  
      11     Libatomic is distributed in the hope that it will be useful, but WITHOUT ANY
      12     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      13     FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      14     more details.
      15  
      16     Under Section 7 of GPL version 3, you are granted additional
      17     permissions described in the GCC Runtime Library Exception, version
      18     3.1, as published by the Free Software Foundation.
      19  
      20     You should have received a copy of the GNU General Public License and
      21     a copy of the GCC Runtime Library Exception along with this program;
      22     see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      23     <http://www.gnu.org/licenses/>.  */
      24  
      25  #if HAVE_IFUNC
      26  #include <cpuid.h>
      27  
      28  #ifdef __x86_64__
      29  # define FEAT1_REGISTER ecx
      30  #else
      31  # define FEAT1_REGISTER edx
      32  #endif
      33  
      34  /* Value of the CPUID feature register FEAT1_REGISTER for the cmpxchg
      35     bit for IFUNC_COND1 below.  */
      36  extern unsigned int __libat_feat1 HIDDEN;
      37  
      38  /* Initialize libat_feat1 and return its value.  */
      39  unsigned int __libat_feat1_init (void) HIDDEN;
      40  
      41  /* Return the value of the relevant feature register for the relevant
      42     cmpxchg bit, or 0 if there is no CPUID support.  */
      43  static inline unsigned int
      44  __attribute__ ((const))
      45  load_feat1 (void)
      46  {
      47    /* See the store in __libat_feat1_init.  */
      48    unsigned int feat1 = __atomic_load_n (&__libat_feat1, __ATOMIC_RELAXED);
      49    if (feat1 == 0)
      50      /* Assume that initialization has not happened yet.  This may get
      51         called repeatedly if the CPU does not have any feature bits at
      52         all.  */
      53      feat1 = __libat_feat1_init ();
      54    return feat1;
      55  }
      56  
      57  #ifdef __x86_64__
      58  # define IFUNC_COND_1	((load_feat1 () & (bit_AVX | bit_CMPXCHG16B)) \
      59  			 == (bit_AVX | bit_CMPXCHG16B))
      60  # define IFUNC_COND_2	(load_feat1 () & bit_CMPXCHG16B)
      61  #else
      62  # define IFUNC_COND_1	(load_feat1 () & bit_CMPXCHG8B)
      63  #endif
      64  
      65  #ifdef __x86_64__
      66  # define IFUNC_NCOND(N) (2 * (N == 16))
      67  #else
      68  # define IFUNC_NCOND(N) (N == 8)
      69  #endif
      70  
      71  #ifdef __x86_64__
      72  # undef MAYBE_HAVE_ATOMIC_CAS_16
      73  # define MAYBE_HAVE_ATOMIC_CAS_16	IFUNC_COND_2
      74  # undef MAYBE_HAVE_ATOMIC_EXCHANGE_16
      75  # define MAYBE_HAVE_ATOMIC_EXCHANGE_16	IFUNC_COND_2
      76  # undef MAYBE_HAVE_ATOMIC_LDST_16
      77  # define MAYBE_HAVE_ATOMIC_LDST_16	IFUNC_COND_2
      78  /* Since load and store are implemented with CAS, they are not fast.  */
      79  # undef FAST_ATOMIC_LDST_16
      80  # define FAST_ATOMIC_LDST_16		0
      81  # if IFUNC_ALT != 0
      82  #  undef HAVE_ATOMIC_CAS_16
      83  #  define HAVE_ATOMIC_CAS_16 1
      84  # endif
      85  # if IFUNC_ALT == 1
      86  #  undef HAVE_ATOMIC_LDST_16
      87  #  define HAVE_ATOMIC_LDST_16 1
      88  # endif
      89  #else
      90  # undef MAYBE_HAVE_ATOMIC_CAS_8
      91  # define MAYBE_HAVE_ATOMIC_CAS_8	IFUNC_COND_1
      92  # undef MAYBE_HAVE_ATOMIC_EXCHANGE_8
      93  # define MAYBE_HAVE_ATOMIC_EXCHANGE_8	IFUNC_COND_1
      94  # undef MAYBE_HAVE_ATOMIC_LDST_8
      95  # define MAYBE_HAVE_ATOMIC_LDST_8	IFUNC_COND_1
      96  # if IFUNC_ALT == 1
      97  #  undef HAVE_ATOMIC_CAS_8
      98  #  define HAVE_ATOMIC_CAS_8 1
      99  # endif
     100  #endif
     101  
     102  #if defined(__x86_64__) && N == 16 && IFUNC_ALT != 0
     103  static inline bool
     104  atomic_compare_exchange_n (UTYPE *mptr, UTYPE *eptr, UTYPE newval,
     105                             bool weak_p UNUSED, int sm UNUSED, int fm UNUSED)
     106  {
     107    UTYPE cmpval = *eptr;
     108    UTYPE oldval = __sync_val_compare_and_swap_16 (mptr, cmpval, newval);
     109    if (oldval == cmpval)
     110      return true;
     111    *eptr = oldval;
     112    return false;
     113  }
     114  # define atomic_compare_exchange_n atomic_compare_exchange_n
     115  #endif /* Have CAS 16 */
     116  
     117  #if defined(__x86_64__) && N == 16 && IFUNC_ALT == 1
     118  #define __atomic_load_n(ptr, model) \
     119    (sizeof (*ptr) == 16 ? atomic_load_n (ptr, model) \
     120  		       : (__atomic_load_n) (ptr, model))
     121  #define __atomic_store_n(ptr, val, model) \
     122    (sizeof (*ptr) == 16 ? atomic_store_n (ptr, val, model) \
     123  		       : (__atomic_store_n) (ptr, val, model))
     124  
     125  static inline UTYPE
     126  atomic_load_n (UTYPE *ptr, int model UNUSED)
     127  {
     128    UTYPE ret;
     129    __asm__ ("vmovdqa\t{%1, %0|%0, %1}" : "=x" (ret) : "m" (*ptr));
     130    return ret;
     131  }
     132  
     133  static inline void
     134  atomic_store_n (UTYPE *ptr, UTYPE val, int model UNUSED)
     135  {
     136    __asm__ ("vmovdqa\t{%1, %0|%0, %1}\n\tmfence" : "=m" (*ptr) : "x" (val));
     137  }
     138  #endif
     139  
     140  #endif /* HAVE_IFUNC */
     141  
     142  #include_next <host-config.h>