/* * Copyright © 2012 Intel Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * */ #ifndef __GBE_INTRINSICS_HPP__ #define __GBE_INTRINSICS_HPP__ #include "sys/platform.hpp" #include #include #if defined(__MSVC__) #include #define GBE_COMPILER_WRITE_BARRIER _WriteBarrier() #define GBE_COMPILER_READ_WRITE_BARRIER _ReadWriteBarrier() #if _MSC_VER >= 1400 #pragma intrinsic(_ReadBarrier) #define GBE_COMPILER_READ_BARRIER _ReadBarrier() #else #define GBE_COMPILER_READ_BARRIER _ReadWriteBarrier() #endif /* _MSC_VER >= 1400 */ INLINE int __bsf(int v) { unsigned long r = 0; _BitScanForward(&r,v); return r; } INLINE int __bsr(int v) { unsigned long r = 0; _BitScanReverse(&r,v); return r; } INLINE int __btc(int v, int i) { long r = v; _bittestandcomplement(&r,i); return r; } INLINE int __bts(int v, int i) { long r = v; _bittestandset(&r,i); return r; } INLINE int __btr(int v, int i) { long r = v; _bittestandreset(&r,i); return r; } INLINE void memoryFence(void) { _mm_mfence(); } #if defined(__X86_64__) && !defined(__INTEL_COMPILER) INLINE size_t __bsf(size_t v) { unsigned long r = 0; _BitScanForward64(&r,v); return r; } INLINE size_t __bsr(size_t v) { unsigned long r = 0; _BitScanReverse64(&r,v); return r; } INLINE size_t __btc(size_t v, size_t i) { __int64_t r = v; _bittestandcomplement64(&r,i); return r; } INLINE size_t __bts(size_t v, size_t i) { __int64_t r = v; _bittestandset64(&r,i); return r; } INLINE size_t __btr(size_t v, size_t i) { __int64_t r = v; _bittestandreset64(&r,i); return r; } #endif /* defined(__X86_64__) && !defined(__INTEL_COMPILER) */ typedef int32_t atomic32_t; INLINE int32_t atomic_add(volatile int32_t* m, const int32_t v) { return _InterlockedExchangeAdd((volatile long*)m,v); } INLINE int32_t atomic_cmpxchg(volatile int32_t* m, const int32_t v, const int32_t c) { return _InterlockedCompareExchange((volatile long*)m,v,c); } #if defined(__X86_64__) typedef int64_t atomic_t; INLINE int64_t atomic_add(volatile int64_t* m, const int64_t v) { return _InterlockedExchangeAdd64(m,v); } INLINE int64_t atomic_cmpxchg(volatile int64_t* m, const int64_t v, const int64_t c) { return _InterlockedCompareExchange64(m,v,c); } #else typedef int32_t atomic_t; #endif /* defined(__X86_64__) */ #else INLINE unsigned int __popcnt(unsigned int in) { int r = 0; asm ("popcnt %1,%0" : "=r"(r) : "r"(in)); return r; } INLINE int __bsf(int v) { int r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r; } INLINE int __bsr(int v) { int r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r; } INLINE int __btc(int v, int i) { int r = 0; asm ("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r; } INLINE int __bts(int v, int i) { int r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r; } INLINE int __btr(int v, int i) { int r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r; } INLINE size_t __bsf(size_t v) { size_t r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r; } INLINE size_t __bsr(size_t v) { size_t r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r; } INLINE size_t __btc(size_t v, size_t i) { size_t r = 0; asm ("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r; } INLINE size_t __bts(size_t v, size_t i) { size_t r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r; } INLINE size_t __btr(size_t v, size_t i) { size_t r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r; } INLINE void memoryFence(void) { _mm_mfence(); } typedef int32_t atomic32_t; INLINE int32_t atomic_add(int32_t volatile* value, int32_t input) { asm volatile("lock xadd %0,%1" : "+r" (input), "+m" (*value) : "r" (input), "m" (*value)); return input; } INLINE int32_t atomic_cmpxchg(int32_t volatile* value, const int32_t input, int32_t comparand) { asm volatile("lock cmpxchg %2,%0" : "=m" (*value), "=a" (comparand) : "r" (input), "m" (*value), "a" (comparand) : "flags"); return comparand; } #if defined(__X86_64__) typedef int64_t atomic_t; INLINE int64_t atomic_add(int64_t volatile* value, int64_t input) { asm volatile("lock xaddq %0,%1" : "+r" (input), "+m" (*value) : "r" (input), "m" (*value)); return input; } INLINE int64_t atomic_cmpxchg(int64_t volatile* value, const int64_t input, int64_t comparand) { asm volatile("lock cmpxchgq %2,%0" : "+m" (*value), "+a" (comparand) : "r" (input), "m" (*value), "r" (comparand) : "flags"); return comparand; } #else typedef int32_t atomic_t; #endif /* defined(__X86_64__) */ #define GBE_COMPILER_READ_WRITE_BARRIER asm volatile("" ::: "memory"); #define GBE_COMPILER_WRITE_BARRIER GBE_COMPILER_READ_WRITE_BARRIER #define GBE_COMPILER_READ_BARRIER GBE_COMPILER_READ_WRITE_BARRIER #endif /* __MSVC__ */ template INLINE T __load_acquire(volatile T *ptr) { GBE_COMPILER_READ_WRITE_BARRIER; T x = *ptr; // for x86, load == load_acquire GBE_COMPILER_READ_WRITE_BARRIER; return x; } template INLINE void __store_release(volatile T *ptr, T x) { GBE_COMPILER_READ_WRITE_BARRIER; *ptr = x; // for x86, store == store_release GBE_COMPILER_READ_WRITE_BARRIER; } #endif /* __GBE_INTRINSICS_HPP__ */