[CRT/INTRIN] Leverage __has_builtin() with the intrinsics. Dedicated to Thomas. CORE-11799 (#94)

This commit is contained in:
Amine Khaldi 2017-11-19 15:09:06 +01:00
parent 3a68bebf87
commit b439381523
2 changed files with 126 additions and 64 deletions

View file

@ -32,7 +32,9 @@
#ifdef __clang__ #ifdef __clang__
#define __INTRIN_INLINE __forceinline #define __INTRIN_INLINE __forceinline
#define HAS_BUILTIN(x) __has_builtin(x)
#else #else
#define HAS_BUILTIN(x) 0
#define __ATTRIBUTE_ARTIFICIAL __attribute__((artificial)) #define __ATTRIBUTE_ARTIFICIAL __attribute__((artificial))
#define __INTRIN_INLINE extern __inline__ __attribute__((__always_inline__,__gnu_inline__)) __ATTRIBUTE_ARTIFICIAL #define __INTRIN_INLINE extern __inline__ __attribute__((__always_inline__,__gnu_inline__)) __ATTRIBUTE_ARTIFICIAL
#endif #endif

View file

@ -89,35 +89,41 @@ __INTRIN_INLINE void* __cdecl memcpy(void* dest, const void* source, size_t num)
/*** Memory barriers ***/ /*** Memory barriers ***/
#ifndef __clang__ #if !HAS_BUILTIN(_ReadWriteBarrier)
__INTRIN_INLINE void _ReadWriteBarrier(void) __INTRIN_INLINE void _ReadWriteBarrier(void)
{ {
__asm__ __volatile__("" : : : "memory"); __asm__ __volatile__("" : : : "memory");
} }
#endif
/* GCC only supports full barriers */ /* GCC only supports full barriers */
#define _ReadBarrier _ReadWriteBarrier #define _ReadBarrier _ReadWriteBarrier
#define _WriteBarrier _ReadWriteBarrier #define _WriteBarrier _ReadWriteBarrier
#if !HAS_BUILTIN(_mm_mfence)
__INTRIN_INLINE void _mm_mfence(void) __INTRIN_INLINE void _mm_mfence(void)
{ {
__asm__ __volatile__("mfence" : : : "memory"); __asm__ __volatile__("mfence" : : : "memory");
} }
#endif
#if !HAS_BUILTIN(_mm_lfence)
__INTRIN_INLINE void _mm_lfence(void) __INTRIN_INLINE void _mm_lfence(void)
{ {
_ReadBarrier(); _ReadBarrier();
__asm__ __volatile__("lfence"); __asm__ __volatile__("lfence");
_ReadBarrier(); _ReadBarrier();
} }
#endif
#if !HAS_BUILTIN(_mm_sfence)
__INTRIN_INLINE void _mm_sfence(void) __INTRIN_INLINE void _mm_sfence(void)
{ {
_WriteBarrier(); _WriteBarrier();
__asm__ __volatile__("sfence"); __asm__ __volatile__("sfence");
_WriteBarrier(); _WriteBarrier();
} }
#endif /* !__clang__ */ #endif
#ifdef __x86_64__ #ifdef __x86_64__
__INTRIN_INLINE void __faststorefence(void) __INTRIN_INLINE void __faststorefence(void)
@ -142,18 +148,18 @@ __INTRIN_INLINE short _InterlockedCompareExchange16(volatile short * Destination
return __sync_val_compare_and_swap(Destination, Comperand, Exchange); return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
} }
#ifndef __clang__ #if !HAS_BUILTIN(_InterlockedCompareExchange)
__INTRIN_INLINE long __cdecl _InterlockedCompareExchange(volatile long * Destination, long Exchange, long Comperand) __INTRIN_INLINE long __cdecl _InterlockedCompareExchange(volatile long * Destination, long Exchange, long Comperand)
{ {
return __sync_val_compare_and_swap(Destination, Comperand, Exchange); return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
} }
#endif
#if !HAS_BUILTIN(_InterlockedCompareExchangePointer)
__INTRIN_INLINE void * _InterlockedCompareExchangePointer(void * volatile * Destination, void * Exchange, void * Comperand) __INTRIN_INLINE void * _InterlockedCompareExchangePointer(void * volatile * Destination, void * Exchange, void * Comperand)
{ {
return (void *)__sync_val_compare_and_swap(Destination, Comperand, Exchange); return (void *)__sync_val_compare_and_swap(Destination, Comperand, Exchange);
} }
#endif #endif
__INTRIN_INLINE char _InterlockedExchange8(volatile char * Target, char Value) __INTRIN_INLINE char _InterlockedExchange8(volatile char * Target, char Value)
@ -170,22 +176,22 @@ __INTRIN_INLINE short _InterlockedExchange16(volatile short * Target, short Valu
return __sync_lock_test_and_set(Target, Value); return __sync_lock_test_and_set(Target, Value);
} }
#ifndef __clang__ #if !HAS_BUILTIN(_InterlockedExchange)
__INTRIN_INLINE long __cdecl _InterlockedExchange(volatile long * Target, long Value) __INTRIN_INLINE long __cdecl _InterlockedExchange(volatile long * Target, long Value)
{ {
/* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */ /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */
__sync_synchronize(); __sync_synchronize();
return __sync_lock_test_and_set(Target, Value); return __sync_lock_test_and_set(Target, Value);
} }
#endif
#if !HAS_BUILTIN(_InterlockedExchangePointer)
__INTRIN_INLINE void * _InterlockedExchangePointer(void * volatile * Target, void * Value) __INTRIN_INLINE void * _InterlockedExchangePointer(void * volatile * Target, void * Value)
{ {
/* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */ /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */
__sync_synchronize(); __sync_synchronize();
return (void *)__sync_lock_test_and_set(Target, Value); return (void *)__sync_lock_test_and_set(Target, Value);
} }
#endif #endif
#if defined(__x86_64__) #if defined(__x86_64__)
@ -207,7 +213,7 @@ __INTRIN_INLINE short _InterlockedExchangeAdd16(volatile short * Addend, short V
return __sync_fetch_and_add(Addend, Value); return __sync_fetch_and_add(Addend, Value);
} }
#ifndef __clang__ #if !HAS_BUILTIN(_InterlockedExchangeAdd)
__INTRIN_INLINE long __cdecl _InterlockedExchangeAdd(volatile long * Addend, long Value) __INTRIN_INLINE long __cdecl _InterlockedExchangeAdd(volatile long * Addend, long Value)
{ {
return __sync_fetch_and_add(Addend, Value); return __sync_fetch_and_add(Addend, Value);
@ -287,12 +293,14 @@ __INTRIN_INLINE long long _InterlockedXor64(volatile long long * value, long lon
} }
#endif #endif
#ifndef __clang__ #if !HAS_BUILTIN(_InterlockedDecrement)
__INTRIN_INLINE long __cdecl _InterlockedDecrement(volatile long * lpAddend) __INTRIN_INLINE long __cdecl _InterlockedDecrement(volatile long * lpAddend)
{ {
return __sync_sub_and_fetch(lpAddend, 1); return __sync_sub_and_fetch(lpAddend, 1);
} }
#endif
#if !HAS_BUILTIN(_InterlockedIncrement)
__INTRIN_INLINE long __cdecl _InterlockedIncrement(volatile long * lpAddend) __INTRIN_INLINE long __cdecl _InterlockedIncrement(volatile long * lpAddend)
{ {
return __sync_add_and_fetch(lpAddend, 1); return __sync_add_and_fetch(lpAddend, 1);
@ -323,85 +331,106 @@ __INTRIN_INLINE long long _InterlockedIncrement64(volatile long long * lpAddend)
#else /* (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 */ #else /* (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 */
#ifndef __clang__ #if !HAS_BUILTIN(_InterlockedCompareExchange8)
__INTRIN_INLINE char _InterlockedCompareExchange8(volatile char * Destination, char Exchange, char Comperand) __INTRIN_INLINE char _InterlockedCompareExchange8(volatile char * Destination, char Exchange, char Comperand)
{ {
char retval = Comperand; char retval = Comperand;
__asm__("lock; cmpxchgb %b[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange) : "memory"); __asm__("lock; cmpxchgb %b[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange) : "memory");
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(_InterlockedCompareExchange16)
__INTRIN_INLINE short _InterlockedCompareExchange16(volatile short * Destination, short Exchange, short Comperand) __INTRIN_INLINE short _InterlockedCompareExchange16(volatile short * Destination, short Exchange, short Comperand)
{ {
short retval = Comperand; short retval = Comperand;
__asm__("lock; cmpxchgw %w[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange): "memory"); __asm__("lock; cmpxchgw %w[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange): "memory");
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(_InterlockedCompareExchange)
__INTRIN_INLINE long _InterlockedCompareExchange(volatile long * Destination, long Exchange, long Comperand) __INTRIN_INLINE long _InterlockedCompareExchange(volatile long * Destination, long Exchange, long Comperand)
{ {
long retval = Comperand; long retval = Comperand;
__asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange): "memory"); __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange): "memory");
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(_InterlockedCompareExchangePointer)
__INTRIN_INLINE void * _InterlockedCompareExchangePointer(void * volatile * Destination, void * Exchange, void * Comperand) __INTRIN_INLINE void * _InterlockedCompareExchangePointer(void * volatile * Destination, void * Exchange, void * Comperand)
{ {
void * retval = (void *)Comperand; void * retval = (void *)Comperand;
__asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval] "=a" (retval) : "[retval]" (retval), [Destination] "m" (*Destination), [Exchange] "q" (Exchange) : "memory"); __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval] "=a" (retval) : "[retval]" (retval), [Destination] "m" (*Destination), [Exchange] "q" (Exchange) : "memory");
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(_InterlockedExchange8)
__INTRIN_INLINE char _InterlockedExchange8(volatile char * Target, char Value) __INTRIN_INLINE char _InterlockedExchange8(volatile char * Target, char Value)
{ {
char retval = Value; char retval = Value;
__asm__("xchgb %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory"); __asm__("xchgb %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory");
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(_InterlockedExchange16)
__INTRIN_INLINE short _InterlockedExchange16(volatile short * Target, short Value) __INTRIN_INLINE short _InterlockedExchange16(volatile short * Target, short Value)
{ {
short retval = Value; short retval = Value;
__asm__("xchgw %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory"); __asm__("xchgw %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory");
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(_InterlockedExchange)
__INTRIN_INLINE long _InterlockedExchange(volatile long * Target, long Value) __INTRIN_INLINE long _InterlockedExchange(volatile long * Target, long Value)
{ {
long retval = Value; long retval = Value;
__asm__("xchgl %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory"); __asm__("xchgl %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory");
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(_InterlockedExchangePointer)
__INTRIN_INLINE void * _InterlockedExchangePointer(void * volatile * Target, void * Value) __INTRIN_INLINE void * _InterlockedExchangePointer(void * volatile * Target, void * Value)
{ {
void * retval = Value; void * retval = Value;
__asm__("xchgl %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory"); __asm__("xchgl %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory");
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(_InterlockedExchangeAdd8)
__INTRIN_INLINE char _InterlockedExchangeAdd8(char volatile * Addend, char Value) __INTRIN_INLINE char _InterlockedExchangeAdd8(char volatile * Addend, char Value)
{ {
char retval = Value; char retval = Value;
__asm__("lock; xaddb %[retval], %[Addend]" : [retval] "+r" (retval) : [Addend] "m" (*Addend) : "memory"); __asm__("lock; xaddb %[retval], %[Addend]" : [retval] "+r" (retval) : [Addend] "m" (*Addend) : "memory");
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(_InterlockedExchangeAdd16)
__INTRIN_INLINE short _InterlockedExchangeAdd16(volatile short * Addend, short Value) __INTRIN_INLINE short _InterlockedExchangeAdd16(volatile short * Addend, short Value)
{ {
short retval = Value; short retval = Value;
__asm__("lock; xaddw %[retval], %[Addend]" : [retval] "+r" (retval) : [Addend] "m" (*Addend) : "memory"); __asm__("lock; xaddw %[retval], %[Addend]" : [retval] "+r" (retval) : [Addend] "m" (*Addend) : "memory");
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(_InterlockedExchangeAdd)
__INTRIN_INLINE long _InterlockedExchangeAdd(volatile long * Addend, long Value) __INTRIN_INLINE long _InterlockedExchangeAdd(volatile long * Addend, long Value)
{ {
long retval = Value; long retval = Value;
__asm__("lock; xaddl %[retval], %[Addend]" : [retval] "+r" (retval) : [Addend] "m" (*Addend) : "memory"); __asm__("lock; xaddl %[retval], %[Addend]" : [retval] "+r" (retval) : [Addend] "m" (*Addend) : "memory");
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(_InterlockedAnd8)
__INTRIN_INLINE char _InterlockedAnd8(volatile char * value, char mask) __INTRIN_INLINE char _InterlockedAnd8(volatile char * value, char mask)
{ {
char x; char x;
@ -418,7 +447,9 @@ __INTRIN_INLINE char _InterlockedAnd8(volatile char * value, char mask)
return y; return y;
} }
#endif
#if !HAS_BUILTIN(_InterlockedAnd16)
__INTRIN_INLINE short _InterlockedAnd16(volatile short * value, short mask) __INTRIN_INLINE short _InterlockedAnd16(volatile short * value, short mask)
{ {
short x; short x;
@ -435,7 +466,9 @@ __INTRIN_INLINE short _InterlockedAnd16(volatile short * value, short mask)
return y; return y;
} }
#endif
#if !HAS_BUILTIN(_InterlockedAnd)
__INTRIN_INLINE long _InterlockedAnd(volatile long * value, long mask) __INTRIN_INLINE long _InterlockedAnd(volatile long * value, long mask)
{ {
long x; long x;
@ -452,7 +485,9 @@ __INTRIN_INLINE long _InterlockedAnd(volatile long * value, long mask)
return y; return y;
} }
#endif
#if !HAS_BUILTIN(_InterlockedOr8)
__INTRIN_INLINE char _InterlockedOr8(volatile char * value, char mask) __INTRIN_INLINE char _InterlockedOr8(volatile char * value, char mask)
{ {
char x; char x;
@ -469,7 +504,9 @@ __INTRIN_INLINE char _InterlockedOr8(volatile char * value, char mask)
return y; return y;
} }
#endif
#if !HAS_BUILTIN(_InterlockedOr16)
__INTRIN_INLINE short _InterlockedOr16(volatile short * value, short mask) __INTRIN_INLINE short _InterlockedOr16(volatile short * value, short mask)
{ {
short x; short x;
@ -486,7 +523,9 @@ __INTRIN_INLINE short _InterlockedOr16(volatile short * value, short mask)
return y; return y;
} }
#endif
#if !HAS_BUILTIN(_InterlockedOr)
__INTRIN_INLINE long _InterlockedOr(volatile long * value, long mask) __INTRIN_INLINE long _InterlockedOr(volatile long * value, long mask)
{ {
long x; long x;
@ -503,7 +542,9 @@ __INTRIN_INLINE long _InterlockedOr(volatile long * value, long mask)
return y; return y;
} }
#endif
#if !HAS_BUILTIN(_InterlockedXor8)
__INTRIN_INLINE char _InterlockedXor8(volatile char * value, char mask) __INTRIN_INLINE char _InterlockedXor8(volatile char * value, char mask)
{ {
char x; char x;
@ -520,7 +561,9 @@ __INTRIN_INLINE char _InterlockedXor8(volatile char * value, char mask)
return y; return y;
} }
#endif
#if !HAS_BUILTIN(_InterlockedXor16)
__INTRIN_INLINE short _InterlockedXor16(volatile short * value, short mask) __INTRIN_INLINE short _InterlockedXor16(volatile short * value, short mask)
{ {
short x; short x;
@ -537,7 +580,9 @@ __INTRIN_INLINE short _InterlockedXor16(volatile short * value, short mask)
return y; return y;
} }
#endif
#if !HAS_BUILTIN(_InterlockedXor)
__INTRIN_INLINE long _InterlockedXor(volatile long * value, long mask) __INTRIN_INLINE long _InterlockedXor(volatile long * value, long mask)
{ {
long x; long x;
@ -554,28 +599,35 @@ __INTRIN_INLINE long _InterlockedXor(volatile long * value, long mask)
return y; return y;
} }
#endif
#if !HAS_BUILTIN(_InterlockedDecrement)
__INTRIN_INLINE long _InterlockedDecrement(volatile long * lpAddend) __INTRIN_INLINE long _InterlockedDecrement(volatile long * lpAddend)
{ {
return _InterlockedExchangeAdd(lpAddend, -1) - 1; return _InterlockedExchangeAdd(lpAddend, -1) - 1;
} }
#endif
#if !HAS_BUILTIN(_InterlockedIncrement)
__INTRIN_INLINE long _InterlockedIncrement(volatile long * lpAddend) __INTRIN_INLINE long _InterlockedIncrement(volatile long * lpAddend)
{ {
return _InterlockedExchangeAdd(lpAddend, 1) + 1; return _InterlockedExchangeAdd(lpAddend, 1) + 1;
} }
#endif
#if !HAS_BUILTIN(_InterlockedDecrement16)
__INTRIN_INLINE short _InterlockedDecrement16(volatile short * lpAddend) __INTRIN_INLINE short _InterlockedDecrement16(volatile short * lpAddend)
{ {
return _InterlockedExchangeAdd16(lpAddend, -1) - 1; return _InterlockedExchangeAdd16(lpAddend, -1) - 1;
} }
#endif
#if !HAS_BUILTIN(_InterlockedIncrement16)
__INTRIN_INLINE short _InterlockedIncrement16(volatile short * lpAddend) __INTRIN_INLINE short _InterlockedIncrement16(volatile short * lpAddend)
{ {
return _InterlockedExchangeAdd16(lpAddend, 1) + 1; return _InterlockedExchangeAdd16(lpAddend, 1) + 1;
} }
#endif
#endif /* !__clang__ */
#if defined(__x86_64__) #if defined(__x86_64__)
__INTRIN_INLINE long long _InterlockedDecrement64(volatile long long * lpAddend) __INTRIN_INLINE long long _InterlockedDecrement64(volatile long long * lpAddend)
@ -598,9 +650,9 @@ __INTRIN_INLINE long long _InterlockedCompareExchange64(volatile long long * Des
return __sync_val_compare_and_swap(Destination, Comperand, Exchange); return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
} }
#else #else /* (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 && defined(__x86_64__) */
#ifndef __clang__ #if !HAS_BUILTIN(_InterlockedCompareExchange64)
__INTRIN_INLINE long long _InterlockedCompareExchange64(volatile long long * Destination, long long Exchange, long long Comperand) __INTRIN_INLINE long long _InterlockedCompareExchange64(volatile long long * Destination, long long Exchange, long long Comperand)
{ {
long long retval = Comperand; long long retval = Comperand;
@ -617,10 +669,10 @@ __INTRIN_INLINE long long _InterlockedCompareExchange64(volatile long long * Des
return retval; return retval;
} }
#endif /* !__clang__ */
#endif #endif
#endif /* (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 && defined(__x86_64__) */
#ifdef __i386__ #ifdef __i386__
__INTRIN_INLINE long _InterlockedAddLargeStatistic(volatile long long * Addend, long Value) __INTRIN_INLINE long _InterlockedAddLargeStatistic(volatile long long * Addend, long Value)
{ {
@ -655,14 +707,14 @@ __INTRIN_INLINE unsigned char _interlockedbittestandreset64(volatile long long *
} }
#endif #endif
#ifndef __clang__ #if !HAS_BUILTIN(_interlockedbittestandset)
__INTRIN_INLINE unsigned char _interlockedbittestandset(volatile long * a, long b) __INTRIN_INLINE unsigned char _interlockedbittestandset(volatile long * a, long b)
{ {
unsigned char retval; unsigned char retval;
__asm__("lock; btsl %[b], %[a]; setc %b[retval]" : [retval] "=q" (retval), [a] "+m" (*a) : [b] "Ir" (b) : "memory"); __asm__("lock; btsl %[b], %[a]; setc %b[retval]" : [retval] "=q" (retval), [a] "+m" (*a) : [b] "Ir" (b) : "memory");
return retval; return retval;
} }
#endif /* !__clang__ */ #endif
#if defined(__x86_64__) #if defined(__x86_64__)
__INTRIN_INLINE unsigned char _interlockedbittestandset64(volatile long long * a, long long b) __INTRIN_INLINE unsigned char _interlockedbittestandset64(volatile long long * a, long long b)
@ -675,7 +727,7 @@ __INTRIN_INLINE unsigned char _interlockedbittestandset64(volatile long long * a
/*** String operations ***/ /*** String operations ***/
#ifndef __clang__ #if !HAS_BUILTIN(__stosb)
/* NOTE: we don't set a memory clobber in the __stosX functions because Visual C++ doesn't */ /* NOTE: we don't set a memory clobber in the __stosX functions because Visual C++ doesn't */
__INTRIN_INLINE void __stosb(unsigned char * Dest, unsigned char Data, size_t Count) __INTRIN_INLINE void __stosb(unsigned char * Dest, unsigned char Data, size_t Count)
{ {
@ -873,30 +925,32 @@ __INTRIN_INLINE void __writefsdword(unsigned long Offset, unsigned long Data)
__asm__ __volatile__("movl %k[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory"); __asm__ __volatile__("movl %k[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
} }
#ifndef __clang__ #if !HAS_BUILTIN(__readfsbyte)
__INTRIN_INLINE unsigned char __readfsbyte(unsigned long Offset) __INTRIN_INLINE unsigned char __readfsbyte(unsigned long Offset)
{ {
unsigned char value; unsigned char value;
__asm__ __volatile__("movb %%fs:%a[Offset], %b[value]" : [value] "=q" (value) : [Offset] "ir" (Offset)); __asm__ __volatile__("movb %%fs:%a[Offset], %b[value]" : [value] "=q" (value) : [Offset] "ir" (Offset));
return value; return value;
} }
#endif
#if !HAS_BUILTIN(__readfsword)
__INTRIN_INLINE unsigned short __readfsword(unsigned long Offset) __INTRIN_INLINE unsigned short __readfsword(unsigned long Offset)
{ {
unsigned short value; unsigned short value;
__asm__ __volatile__("movw %%fs:%a[Offset], %w[value]" : [value] "=r" (value) : [Offset] "ir" (Offset)); __asm__ __volatile__("movw %%fs:%a[Offset], %w[value]" : [value] "=r" (value) : [Offset] "ir" (Offset));
return value; return value;
} }
#endif
#if !HAS_BUILTIN(__readfsdword)
__INTRIN_INLINE unsigned long __readfsdword(unsigned long Offset) __INTRIN_INLINE unsigned long __readfsdword(unsigned long Offset)
{ {
unsigned long value; unsigned long value;
__asm__ __volatile__("movl %%fs:%a[Offset], %k[value]" : [value] "=r" (value) : [Offset] "ir" (Offset)); __asm__ __volatile__("movl %%fs:%a[Offset], %k[value]" : [value] "=r" (value) : [Offset] "ir" (Offset));
return value; return value;
} }
#endif
#endif /* !__clang__ */
__INTRIN_INLINE void __incfsbyte(unsigned long Offset) __INTRIN_INLINE void __incfsbyte(unsigned long Offset)
{ {
@ -943,21 +997,21 @@ __INTRIN_INLINE void __addfsdword(unsigned long Offset, unsigned long Data)
/*** Bit manipulation ***/ /*** Bit manipulation ***/
#ifndef __clang__ #if !HAS_BUILTIN(_BitScanForward)
__INTRIN_INLINE unsigned char _BitScanForward(unsigned long * Index, unsigned long Mask) __INTRIN_INLINE unsigned char _BitScanForward(unsigned long * Index, unsigned long Mask)
{ {
__asm__("bsfl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask)); __asm__("bsfl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask));
return Mask ? 1 : 0; return Mask ? 1 : 0;
} }
#endif
#if !HAS_BUILTIN(_BitScanReverse)
__INTRIN_INLINE unsigned char _BitScanReverse(unsigned long * Index, unsigned long Mask) __INTRIN_INLINE unsigned char _BitScanReverse(unsigned long * Index, unsigned long Mask)
{ {
__asm__("bsrl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask)); __asm__("bsrl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask));
return Mask ? 1 : 0; return Mask ? 1 : 0;
} }
#endif
#endif /* !__clang__ */
/* NOTE: again, the bizarre implementation follows Visual C++ */ /* NOTE: again, the bizarre implementation follows Visual C++ */
__INTRIN_INLINE unsigned char _bittest(const long * a, long b) __INTRIN_INLINE unsigned char _bittest(const long * a, long b)
@ -1076,32 +1130,34 @@ __INTRIN_INLINE unsigned char _bittestandcomplement64(long long * a, long long b
return retval; return retval;
} }
#endif #endif /* __x86_64__ */
#ifndef __clang__
#if !HAS_BUILTIN(_rotl8)
__INTRIN_INLINE unsigned char __cdecl _rotl8(unsigned char value, unsigned char shift) __INTRIN_INLINE unsigned char __cdecl _rotl8(unsigned char value, unsigned char shift)
{ {
unsigned char retval; unsigned char retval;
__asm__("rolb %b[shift], %b[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift)); __asm__("rolb %b[shift], %b[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(_rotl16)
__INTRIN_INLINE unsigned short __cdecl _rotl16(unsigned short value, unsigned char shift) __INTRIN_INLINE unsigned short __cdecl _rotl16(unsigned short value, unsigned char shift)
{ {
unsigned short retval; unsigned short retval;
__asm__("rolw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift)); __asm__("rolw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(_rotl)
__INTRIN_INLINE unsigned int __cdecl _rotl(unsigned int value, int shift) __INTRIN_INLINE unsigned int __cdecl _rotl(unsigned int value, int shift)
{ {
unsigned int retval; unsigned int retval;
__asm__("roll %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift)); __asm__("roll %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
return retval; return retval;
} }
#endif
#endif /* !__clang__ */
#ifdef __x86_64__ #ifdef __x86_64__
__INTRIN_INLINE unsigned long long _rotl64(unsigned long long value, int shift) __INTRIN_INLINE unsigned long long _rotl64(unsigned long long value, int shift)
@ -1111,39 +1167,41 @@ __INTRIN_INLINE unsigned long long _rotl64(unsigned long long value, int shift)
return retval; return retval;
} }
#else /* __x86_64__ */ #else /* __x86_64__ */
#ifndef __clang__ #if !HAS_BUILTIN(_rotl64)
__INTRIN_INLINE unsigned long long __cdecl _rotl64(unsigned long long value, int shift) __INTRIN_INLINE unsigned long long __cdecl _rotl64(unsigned long long value, int shift)
{ {
/* FIXME: this is probably not optimal */ /* FIXME: this is probably not optimal */
return (value << shift) | (value >> (64 - shift)); return (value << shift) | (value >> (64 - shift));
} }
#endif /* !__clang__ */ #endif /* !HAS_BUILTIN(_rotl64) */
#endif /* __x86_64__ */ #endif /* __x86_64__ */
#ifndef __clang__ #if !HAS_BUILTIN(_rotr)
__INTRIN_INLINE unsigned int __cdecl _rotr(unsigned int value, int shift) __INTRIN_INLINE unsigned int __cdecl _rotr(unsigned int value, int shift)
{ {
unsigned int retval; unsigned int retval;
__asm__("rorl %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift)); __asm__("rorl %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(_rotr8)
__INTRIN_INLINE unsigned char __cdecl _rotr8(unsigned char value, unsigned char shift) __INTRIN_INLINE unsigned char __cdecl _rotr8(unsigned char value, unsigned char shift)
{ {
unsigned char retval; unsigned char retval;
__asm__("rorb %b[shift], %b[retval]" : [retval] "=qm" (retval) : "[retval]" (value), [shift] "Nc" (shift)); __asm__("rorb %b[shift], %b[retval]" : [retval] "=qm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(_rotr16)
__INTRIN_INLINE unsigned short __cdecl _rotr16(unsigned short value, unsigned char shift) __INTRIN_INLINE unsigned short __cdecl _rotr16(unsigned short value, unsigned char shift)
{ {
unsigned short retval; unsigned short retval;
__asm__("rorw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift)); __asm__("rorw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
return retval; return retval;
} }
#endif
#endif /* !__clang__ */
#ifdef __x86_64__ #ifdef __x86_64__
__INTRIN_INLINE unsigned long long _rotr64(unsigned long long value, int shift) __INTRIN_INLINE unsigned long long _rotr64(unsigned long long value, int shift)
@ -1153,32 +1211,32 @@ __INTRIN_INLINE unsigned long long _rotr64(unsigned long long value, int shift)
return retval; return retval;
} }
#else /* __x86_64__ */ #else /* __x86_64__ */
#ifndef __clang__ #if !HAS_BUILTIN(_rotr64)
__INTRIN_INLINE unsigned long long __cdecl _rotr64(unsigned long long value, int shift) __INTRIN_INLINE unsigned long long __cdecl _rotr64(unsigned long long value, int shift)
{ {
/* FIXME: this is probably not optimal */ /* FIXME: this is probably not optimal */
return (value >> shift) | (value << (64 - shift)); return (value >> shift) | (value << (64 - shift));
} }
#endif /* !__clang__ */ #endif /* !HAS_BUILTIN(_rotr64) */
#endif /* __x86_64__ */ #endif /* __x86_64__ */
#ifndef __clang__ #if !HAS_BUILTIN(_lrotl)
__INTRIN_INLINE unsigned long __cdecl _lrotl(unsigned long value, int shift) __INTRIN_INLINE unsigned long __cdecl _lrotl(unsigned long value, int shift)
{ {
unsigned long retval; unsigned long retval;
__asm__("roll %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift)); __asm__("roll %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(_lrotr)
__INTRIN_INLINE unsigned long __cdecl _lrotr(unsigned long value, int shift) __INTRIN_INLINE unsigned long __cdecl _lrotr(unsigned long value, int shift)
{ {
unsigned long retval; unsigned long retval;
__asm__("rorl %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift)); __asm__("rorl %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
return retval; return retval;
} }
#endif
#endif /* !__clang__ */
/* /*
NOTE: in __ll_lshift, __ll_rshift and __ull_rshift we use the "A" NOTE: in __ll_lshift, __ll_rshift and __ull_rshift we use the "A"
@ -1278,19 +1336,19 @@ __INTRIN_INLINE unsigned short __lzcnt16(unsigned short value)
return __builtin_clz(value); return __builtin_clz(value);
} }
#ifndef __clang__ #if !HAS_BUILTIN(__popcnt)
__INTRIN_INLINE unsigned int __popcnt(unsigned int value) __INTRIN_INLINE unsigned int __popcnt(unsigned int value)
{ {
return __builtin_popcount(value); return __builtin_popcount(value);
} }
#endif
#if !HAS_BUILTIN(__popcnt16)
__INTRIN_INLINE unsigned short __popcnt16(unsigned short value) __INTRIN_INLINE unsigned short __popcnt16(unsigned short value)
{ {
return __builtin_popcount(value); return __builtin_popcount(value);
} }
#endif
#endif /* !__clang__ */
#ifdef __x86_64__ #ifdef __x86_64__
__INTRIN_INLINE unsigned long long __lzcnt64(unsigned long long value) __INTRIN_INLINE unsigned long long __lzcnt64(unsigned long long value)
@ -1306,23 +1364,23 @@ __INTRIN_INLINE unsigned long long __popcnt64(unsigned long long value)
/*** 64-bit math ***/ /*** 64-bit math ***/
#ifndef __clang__ #if !HAS_BUILTIN(__emul)
__INTRIN_INLINE long long __emul(int a, int b) __INTRIN_INLINE long long __emul(int a, int b)
{ {
long long retval; long long retval;
__asm__("imull %[b]" : "=A" (retval) : [a] "a" (a), [b] "rm" (b)); __asm__("imull %[b]" : "=A" (retval) : [a] "a" (a), [b] "rm" (b));
return retval; return retval;
} }
#endif
#if !HAS_BUILTIN(__emulu)
__INTRIN_INLINE unsigned long long __emulu(unsigned int a, unsigned int b) __INTRIN_INLINE unsigned long long __emulu(unsigned int a, unsigned int b)
{ {
unsigned long long retval; unsigned long long retval;
__asm__("mull %[b]" : "=A" (retval) : [a] "a" (a), [b] "rm" (b)); __asm__("mull %[b]" : "=A" (retval) : [a] "a" (a), [b] "rm" (b));
return retval; return retval;
} }
#endif
#endif /* !__clang__ */
__INTRIN_INLINE long long __cdecl _abs64(long long value) __INTRIN_INLINE long long __cdecl _abs64(long long value)
{ {
@ -1479,7 +1537,7 @@ __INTRIN_INLINE void __cpuidex(int CPUInfo[4], int InfoType, int ECXValue)
__asm__ __volatile__("cpuid" : "=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3]) : "a" (InfoType), "c" (ECXValue)); __asm__ __volatile__("cpuid" : "=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3]) : "a" (InfoType), "c" (ECXValue));
} }
#ifndef __clang__ #if !HAS_BUILTIN(__rdtsc)
__INTRIN_INLINE unsigned long long __rdtsc(void) __INTRIN_INLINE unsigned long long __rdtsc(void)
{ {
#ifdef __x86_64__ #ifdef __x86_64__
@ -1492,7 +1550,7 @@ __INTRIN_INLINE unsigned long long __rdtsc(void)
return retval; return retval;
#endif #endif
} }
#endif /* !__clang__ */ #endif /* !HAS_BUILTIN(__rdtsc) */
__INTRIN_INLINE void __writeeflags(uintptr_t Value) __INTRIN_INLINE void __writeeflags(uintptr_t Value)
{ {
@ -1508,24 +1566,26 @@ __INTRIN_INLINE uintptr_t __readeflags(void)
/*** Interrupts ***/ /*** Interrupts ***/
#ifndef __clang__ #if !HAS_BUILTIN(__debugbreak)
__INTRIN_INLINE void __cdecl __debugbreak(void) __INTRIN_INLINE void __cdecl __debugbreak(void)
{ {
__asm__("int $3"); __asm__("int $3");
} }
#endif
#if !HAS_BUILTIN(__ud2)
__INTRIN_INLINE void __ud2(void) __INTRIN_INLINE void __ud2(void)
{ {
__asm__("ud2"); __asm__("ud2");
} }
#endif
#if !HAS_BUILTIN(__int2c)
__INTRIN_INLINE void __int2c(void) __INTRIN_INLINE void __int2c(void)
{ {
__asm__("int $0x2c"); __asm__("int $0x2c");
} }
#endif
#endif /* !__clang__ */
__INTRIN_INLINE void __cdecl _disable(void) __INTRIN_INLINE void __cdecl _disable(void)
{ {
@ -1542,7 +1602,7 @@ __INTRIN_INLINE void __halt(void)
__asm__("hlt" : : : "memory"); __asm__("hlt" : : : "memory");
} }
#ifndef __clang__ #if !HAS_BUILTIN(__fastfail)
__declspec(noreturn) __declspec(noreturn)
__INTRIN_INLINE void __fastfail(unsigned int Code) __INTRIN_INLINE void __fastfail(unsigned int Code)
{ {
@ -1627,7 +1687,7 @@ __INTRIN_INLINE void __writecr4(unsigned int Data)
__asm__("mov %[Data], %%cr4" : : [Data] "r" (Data) : "memory"); __asm__("mov %[Data], %%cr4" : : [Data] "r" (Data) : "memory");
} }
#ifndef __clang__ #if !HAS_BUILTIN(__writecr8)
__INTRIN_INLINE void __writecr8(unsigned int Data) __INTRIN_INLINE void __writecr8(unsigned int Data)
{ {
__asm__("mov %[Data], %%cr8" : : [Data] "r" (Data) : "memory"); __asm__("mov %[Data], %%cr8" : : [Data] "r" (Data) : "memory");
@ -1662,7 +1722,7 @@ __INTRIN_INLINE unsigned long __readcr4(void)
return value; return value;
} }
#ifndef __clang__ #if !HAS_BUILTIN(__readcr8)
__INTRIN_INLINE unsigned long __readcr8(void) __INTRIN_INLINE unsigned long __readcr8(void)
{ {
unsigned long value; unsigned long value;
@ -1874,7 +1934,7 @@ __INTRIN_INLINE void _sgdt(void *Destination)
/*** Misc operations ***/ /*** Misc operations ***/
#ifndef __clang__ #if !HAS_BUILTIN(_mm_pause)
__INTRIN_INLINE void _mm_pause(void) __INTRIN_INLINE void _mm_pause(void)
{ {
__asm__ __volatile__("pause" : : : "memory"); __asm__ __volatile__("pause" : : : "memory");