#if !defined(__TBB_machine_H) || defined(__TBB_machine_gcc_power_H)
#error Do not #include this internal file directly; use public TBB headers instead.
#endif
#define __TBB_machine_gcc_power_H
#include <stdint.h>
#include <unistd.h>
#if __powerpc64__ || __ppc64__
#define __TBB_WORDSIZE 8
#else
#define __TBB_WORDSIZE 4
#endif
#ifndef __BYTE_ORDER__
#elif __BYTE_ORDER__==__ORDER_BIG_ENDIAN__
#define __TBB_BIG_ENDIAN 1
#elif __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
#define __TBB_BIG_ENDIAN 0
#else
#define __TBB_BIG_ENDIAN -1
#endif
#if __TBB_WORDSIZE==8
#define __TBB_64BIT_ATOMICS 1
#elif __bgp__
#define __TBB_64BIT_ATOMICS 0
#else
#ifndef __TBB_64BIT_ATOMICS
#define __TBB_64BIT_ATOMICS 0
#endif
#endif
inline int32_t __TBB_machine_cmpswp4 (volatile void *ptr, int32_t value, int32_t comparand )
{
int32_t result;
__asm__ __volatile__("sync\n"
"0:\n\t"
"lwarx %[res],0,%[ptr]\n\t"
"cmpw %[res],%[cmp]\n\t"
"bne- 1f\n\t"
"stwcx. %[val],0,%[ptr]\n\t"
"bne- 0b\n"
"1:\n\t"
"isync"
: [res]"=&r"(result)
, "+m"(* (int32_t*) ptr)
: [ptr]"r"(ptr)
, [val]"r"(value)
, [cmp]"r"(comparand)
: "memory"
, "cr0"
);
return result;
}
#if __TBB_WORDSIZE==8
inline int64_t __TBB_machine_cmpswp8 (volatile void *ptr, int64_t value, int64_t comparand )
{
int64_t result;
__asm__ __volatile__("sync\n"
"0:\n\t"
"ldarx %[res],0,%[ptr]\n\t"
"cmpd %[res],%[cmp]\n\t"
"bne- 1f\n\t"
"stdcx. %[val],0,%[ptr]\n\t"
"bne- 0b\n"
"1:\n\t"
"isync"
: [res]"=&r"(result)
, "+m"(* (int64_t*) ptr)
: [ptr]"r"(ptr)
, [val]"r"(value)
, [cmp]"r"(comparand)
: "memory"
, "cr0"
);
return result;
}
#elif __TBB_64BIT_ATOMICS
inline int64_t __TBB_machine_cmpswp8 (volatile void *ptr, int64_t value, int64_t comparand )
{
int64_t result;
int64_t value_register, comparand_register, result_register;
__asm__ __volatile__("sync\n\t"
"ld %[val],%[valm]\n\t"
"ld %[cmp],%[cmpm]\n"
"0:\n\t"
"ldarx %[res],0,%[ptr]\n\t"
"cmpd %[res],%[cmp]\n\t"
"bne- 1f\n\t"
"stdcx. %[val],0,%[ptr]\n\t"
"bne- 0b\n"
"1:\n\t"
"std %[res],%[resm]\n\t"
"isync"
: [resm]"=m"(result)
, [res] "=&r"( result_register)
, [val] "=&r"( value_register)
, [cmp] "=&r"(comparand_register)
, "+m"(* (int64_t*) ptr)
: [ptr] "r"(ptr)
, [valm]"m"(value)
, [cmpm]"m"(comparand)
: "memory"
, "cr0"
);
return result;
}
#endif
#define __TBB_MACHINE_DEFINE_LOAD_STORE(S,ldx,stx,cmpx) \
template <typename T> \
struct machine_load_store<T,S> { \
static inline T load_with_acquire(const volatile T& location) { \
T result; \
__asm__ __volatile__(ldx " %[res],0(%[ptr])\n" \
"0:\n\t" \
cmpx " %[res],%[res]\n\t" \
"bne- 0b\n\t" \
"isync" \
: [res]"=r"(result) \
: [ptr]"b"(&location) \
, "m"(location) \
: "memory" \
, "cr0" ); \
return result; \
} \
static inline void store_with_release(volatile T &location, T value) { \
__asm__ __volatile__("lwsync\n\t" \
stx " %[val],0(%[ptr])" \
: "=m"(location) \
: [ptr]"b"(&location) \
, [val]"r"(value) \
: "memory" ); \
} \
}; \
\
template <typename T> \
struct machine_load_store_relaxed<T,S> { \
static inline T load (const __TBB_atomic T& location) { \
T result; \
__asm__ __volatile__(ldx " %[res],0(%[ptr])" \
: [res]"=r"(result) \
: [ptr]"b"(&location) \
, "m"(location) \
); \
return result; \
} \
static inline void store (__TBB_atomic T &location, T value) { \
__asm__ __volatile__(stx " %[val],0(%[ptr])" \
: "=m"(location) \
: [ptr]"b"(&location) \
, [val]"r"(value) \
); \
} \
};
namespace tbb {
namespace internal {
__TBB_MACHINE_DEFINE_LOAD_STORE(1,"lbz","stb","cmpw")
__TBB_MACHINE_DEFINE_LOAD_STORE(2,"lhz","sth","cmpw")
__TBB_MACHINE_DEFINE_LOAD_STORE(4,"lwz","stw","cmpw")
#if __TBB_WORDSIZE==8
__TBB_MACHINE_DEFINE_LOAD_STORE(8,"ld" ,"std","cmpd")
#elif __TBB_64BIT_ATOMICS
template <typename T>
struct machine_load_store<T,8> {
static inline T load_with_acquire(const volatile T& location) {
T result;
T result_register;
__asm__ __volatile__("ld %[res],0(%[ptr])\n\t"
"std %[res],%[resm]\n"
"0:\n\t"
"cmpd %[res],%[res]\n\t"
"bne- 0b\n\t"
"isync"
: [resm]"=m"(result)
, [res]"=&r"(result_register)
: [ptr]"b"(&location)
, "m"(location)
: "memory"
, "cr0" );
return result;
}
static inline void store_with_release(volatile T &location, T value) {
T value_register;
__asm__ __volatile__("lwsync\n\t"
"ld %[val],%[valm]\n\t"
"std %[val],0(%[ptr])"
: "=m"(location)
, [val]"=&r"(value_register)
: [ptr]"b"(&location)
, [valm]"m"(value)
: "memory" );
}
};
struct machine_load_store_relaxed<T,8> {
static inline T load (const volatile T& location) {
T result;
T result_register;
__asm__ __volatile__("ld %[res],0(%[ptr])\n\t"
"std %[res],%[resm]"
: [resm]"=m"(result)
, [res]"=&r"(result_register)
: [ptr]"b"(&location)
, "m"(location)
);
return result;
}
static inline void store (volatile T &location, T value) {
T value_register;
__asm__ __volatile__("ld %[val],%[valm]\n\t"
"std %[val],0(%[ptr])"
: "=m"(location)
, [val]"=&r"(value_register)
: [ptr]"b"(&location)
, [valm]"m"(value)
);
}
};
#define __TBB_machine_load_store_relaxed_8
#endif
}}
#undef __TBB_MACHINE_DEFINE_LOAD_STORE
#define __TBB_USE_GENERIC_PART_WORD_CAS 1
#define __TBB_USE_GENERIC_FETCH_ADD 1
#define __TBB_USE_GENERIC_FETCH_STORE 1
#define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1
#define __TBB_control_consistency_helper() __asm__ __volatile__("isync": : :"memory")
#define __TBB_full_memory_fence() __asm__ __volatile__( "sync": : :"memory")
static inline intptr_t __TBB_machine_lg( uintptr_t x ) {
__TBB_ASSERT(x, "__TBB_Log2(0) undefined");
#if __TBB_WORDSIZE==8
__asm__ __volatile__ ("cntlzd %0,%0" : "+r"(x));
return 63-static_cast<intptr_t>(x);
#else
__asm__ __volatile__ ("cntlzw %0,%0" : "+r"(x));
return 31-static_cast<intptr_t>(x);
#endif
}
#define __TBB_Log2(V) __TBB_machine_lg(V)
typedef uint32_t __TBB_Flag;
#define __TBB_Flag __TBB_Flag
inline bool __TBB_machine_trylockbyte( __TBB_atomic __TBB_Flag &flag ) {
return __TBB_machine_cmpswp4(&flag,1,0)==0;
}
#define __TBB_TryLockByte(P) __TBB_machine_trylockbyte(P)