Blame sysdeps/powerpc/powerpc32/atomic-machine.h

Packit 6c4009
/* Atomic operations.  PowerPC32 version.
Packit 6c4009
   Copyright (C) 2003-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
/*  POWER6 adds a "Mutex Hint" to the Load and Reserve instruction.
Packit 6c4009
    This is a hint to the hardware to expect additional updates adjacent
Packit 6c4009
    to the lock word or not.  If we are acquiring a Mutex, the hint
Packit 6c4009
    should be true. Otherwise we releasing a Mutex or doing a simple
Packit 6c4009
    atomic operation.  In that case we don't expect additional updates
Packit 6c4009
    adjacent to the lock word after the Store Conditional and the hint
Packit 6c4009
    should be false.  */
Packit 6c4009
Packit 6c4009
#if defined _ARCH_PWR6 || defined _ARCH_PWR6X
Packit 6c4009
# define MUTEX_HINT_ACQ	",1"
Packit 6c4009
# define MUTEX_HINT_REL	",0"
Packit 6c4009
#else
Packit 6c4009
# define MUTEX_HINT_ACQ
Packit 6c4009
# define MUTEX_HINT_REL
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#define __HAVE_64B_ATOMICS 0
Packit 6c4009
#define USE_ATOMIC_COMPILER_BUILTINS 0
Packit 6c4009
#define ATOMIC_EXCHANGE_USES_CAS 1
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * The 32-bit exchange_bool is different on powerpc64 because the subf
Packit 6c4009
 * does signed 64-bit arithmetic while the lwarx is 32-bit unsigned
Packit 6c4009
 * (a load word and zero (high 32) form).  So powerpc64 has a slightly
Packit 6c4009
 * different version in sysdeps/powerpc/powerpc64/atomic-machine.h.
Packit 6c4009
 */
Packit 6c4009
#define __arch_compare_and_exchange_bool_32_acq(mem, newval, oldval)         \
Packit 6c4009
({									      \
Packit 6c4009
  unsigned int __tmp;							      \
Packit 6c4009
  __asm __volatile (							      \
Packit 6c4009
		    "1:	lwarx	%0,0,%1" MUTEX_HINT_ACQ "\n"		      \
Packit 6c4009
		    "	subf.	%0,%2,%0\n"				      \
Packit 6c4009
		    "	bne	2f\n"					      \
Packit 6c4009
		    "	stwcx.	%3,0,%1\n"				      \
Packit 6c4009
		    "	bne-	1b\n"					      \
Packit 6c4009
		    "2:	" __ARCH_ACQ_INSTR				      \
Packit 6c4009
		    : "=&r" (__tmp)					      \
Packit 6c4009
		    : "b" (mem), "r" (oldval), "r" (newval)		      \
Packit 6c4009
		    : "cr0", "memory");					      \
Packit 6c4009
  __tmp != 0;								      \
Packit 6c4009
})
Packit 6c4009
Packit 6c4009
/* Powerpc32 processors don't implement the 64-bit (doubleword) forms of
Packit 6c4009
   load and reserve (ldarx) and store conditional (stdcx.) instructions.
Packit 6c4009
   So for powerpc32 we stub out the 64-bit forms.  */
Packit 6c4009
#define __arch_compare_and_exchange_bool_64_acq(mem, newval, oldval) \
Packit 6c4009
  (abort (), 0)
Packit 6c4009
Packit 6c4009
#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
Packit 6c4009
  (abort (), (__typeof (*mem)) 0)
Packit 6c4009
Packit 6c4009
#define __arch_compare_and_exchange_val_64_rel(mem, newval, oldval) \
Packit 6c4009
  (abort (), (__typeof (*mem)) 0)
Packit 6c4009
Packit 6c4009
#define __arch_atomic_exchange_64_acq(mem, value) \
Packit 6c4009
    ({ abort (); (*mem) = (value); })
Packit 6c4009
Packit 6c4009
#define __arch_atomic_exchange_64_rel(mem, value) \
Packit 6c4009
    ({ abort (); (*mem) = (value); })
Packit 6c4009
Packit 6c4009
#define __arch_atomic_exchange_and_add_64(mem, value) \
Packit 6c4009
    ({ abort (); (*mem) = (value); })
Packit 6c4009
Packit 6c4009
#define __arch_atomic_exchange_and_add_64_acq(mem, value) \
Packit 6c4009
    ({ abort (); (*mem) = (value); })
Packit 6c4009
Packit 6c4009
#define __arch_atomic_exchange_and_add_64_rel(mem, value) \
Packit 6c4009
    ({ abort (); (*mem) = (value); })
Packit 6c4009
Packit 6c4009
#define __arch_atomic_increment_val_64(mem) \
Packit 6c4009
    ({ abort (); (*mem)++; })
Packit 6c4009
Packit 6c4009
#define __arch_atomic_decrement_val_64(mem) \
Packit 6c4009
    ({ abort (); (*mem)--; })
Packit 6c4009
Packit 6c4009
#define __arch_atomic_decrement_if_positive_64(mem) \
Packit 6c4009
    ({ abort (); (*mem)--; })
Packit 6c4009
Packit 6c4009
#ifdef _ARCH_PWR4
Packit 6c4009
/*
Packit 6c4009
 * Newer powerpc64 processors support the new "light weight" sync (lwsync)
Packit 6c4009
 * So if the build is using -mcpu=[power4,power5,power5+,970] we can
Packit 6c4009
 * safely use lwsync.
Packit 6c4009
 */
Packit 6c4009
# define atomic_read_barrier()	__asm ("lwsync" ::: "memory")
Packit 6c4009
/*
Packit 6c4009
 * "light weight" sync can also be used for the release barrier.
Packit 6c4009
 */
Packit 6c4009
# ifndef UP
Packit 6c4009
#  define __ARCH_REL_INSTR	"lwsync"
Packit 6c4009
# endif
Packit 6c4009
# define atomic_write_barrier()	__asm ("lwsync" ::: "memory")
Packit 6c4009
#else
Packit 6c4009
/*
Packit 6c4009
 * Older powerpc32 processors don't support the new "light weight"
Packit 6c4009
 * sync (lwsync).  So the only safe option is to use normal sync
Packit 6c4009
 * for all powerpc32 applications.
Packit 6c4009
 */
Packit 6c4009
# define atomic_read_barrier()	__asm ("sync" ::: "memory")
Packit 6c4009
# define atomic_write_barrier()	__asm ("sync" ::: "memory")
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Include the rest of the atomic ops macros which are common to both
Packit 6c4009
 * powerpc32 and powerpc64.
Packit 6c4009
 */
Packit 6c4009
#include_next <atomic-machine.h>