From 192fcc5bb31e6921c3eb6a700f30892dd24c62d4 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 1 Sep 2009 12:39:17 +0200 Subject: [PATCH] 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 0fc877cf935..61c8399f7a1 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 cefbb5e467d..c2ac3eb03f4 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) -- 2.11.4.GIT