Module: wine Branch: master Commit: 192fcc5bb31e6921c3eb6a700f30892dd24c62d4 URL: http://source.winehq.org/git/wine.git/?a=commit;h=192fcc5bb31e6921c3eb6a700f...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Sep 1 12:39:17 2009 +0200
libport: Added an interlocked_cmpxchg128 function for 64-bit.
---
include/wine/port.h | 20 ++++++++++++++++++++ libs/port/interlocked.c | 23 +++++++++++++++++------ 2 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/include/wine/port.h b/include/wine/port.h index 0fc877c..61c8399 100644 --- a/include/wine/port.h +++ b/include/wine/port.h @@ -412,6 +412,22 @@ extern inline int interlocked_xchg_add( int *dest, int incr ) return ret; }
+#ifdef __x86_64__ +extern inline unsigned char interlocked_cmpxchg128( __int64 *dest, __int64 xchg_high, + __int64 xchg_low, __int64 *compare ); +extern inline unsigned char interlocked_cmpxchg128( __int64 *dest, __int64 xchg_high, + __int64 xchg_low, __int64 *compare ) +{ + unsigned char ret; + __asm__ __volatile__( "lock cmpxchg16b %0; setz %b2" + : "=m" (dest[0]), "=m" (dest[1]), "=r" (ret), + "=a" (compare[0]), "=d" (compare[1]) + : "m" (dest[0]), "m" (dest[1]), "3" (compare[0]), "4" (compare[1]), + "c" (xchg_high), "b" (xchg_low) ); + return ret; +} +#endif + #else /* __GNUC__ */
extern int interlocked_cmpxchg( int *dest, int xchg, int compare ); @@ -420,6 +436,10 @@ extern __int64 interlocked_cmpxchg64( __int64 *dest, __int64 xchg, __int64 compa extern int interlocked_xchg( int *dest, int val ); extern void *interlocked_xchg_ptr( void **dest, void *val ); extern int interlocked_xchg_add( int *dest, int incr ); +#ifdef _WIN64 +extern unsigned char interlocked_cmpxchg128( __int64 *dest, __int64 xchg_high, + __int64 xchg_low, __int64 *compare ); +#endif
#endif /* __GNUC__ */
diff --git a/libs/port/interlocked.c b/libs/port/interlocked.c index cefbb5e..c2ac3eb 100644 --- a/libs/port/interlocked.c +++ b/libs/port/interlocked.c @@ -139,8 +139,6 @@ __declspec(naked) int interlocked_xchg_add( int *dest, int incr )
#elif defined(__x86_64__)
-#ifdef __GNUC__ - __ASM_GLOBAL_FUNC(interlocked_cmpxchg, "mov %edx, %eax\n\t" "lock cmpxchgl %esi,(%rdi)\n\t" @@ -165,10 +163,23 @@ __ASM_GLOBAL_FUNC(interlocked_xchg_add, "mov %esi, %eax\n\t" "lock xaddl %eax, (%rdi)\n\t" "ret") - -#else -# error You must implement the interlocked* functions for your compiler -#endif +__ASM_GLOBAL_FUNC(interlocked_cmpxchg128, + "push %rbx\n\t" + ".cfi_adjust_cfa_offset 8\n\t" + ".cfi_rel_offset %rbx,0\n\t" + "mov %rcx,%r8\n\t" /* compare */ + "mov %rdx,%rbx\n\t" /* xchg_low */ + "mov %rsi,%rcx\n\t" /* xchg_high */ + "mov 0(%r8),%rax\n\t" + "mov 8(%r8),%rdx\n\t" + "lock cmpxchg16b (%rdi)\n\t" + "mov %rax,0(%r8)\n\t" + "mov %rdx,8(%r8)\n\t" + "setz %al\n\t" + "pop %rbx\n\t" + ".cfi_adjust_cfa_offset -8\n\t" + ".cfi_same_value %rbx\n\t" + "ret")
#elif defined(__powerpc__) void* interlocked_cmpxchg_ptr( void **dest, void* xchg, void* compare)