From: Ivan Maidanski Date: Wed, 30 Nov 2011 08:30:29 +0000 (+0400) Subject: Implement AO_fetch_compare_and_swap for MIPS X-Git-Tag: libatomic_ops-7_3alpha2~41^2~4 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6b9d8e004426a45c5ffa5ef87ca82ea514fb558f;p=libatomic_ops Implement AO_fetch_compare_and_swap for MIPS * src/atomic_ops/sysdeps/gcc/mips.h (AO_compare_and_swap, AO_HAVE_compare_and_swap): Do not define if AO_GENERALIZE_ASM_BOOL_CAS. * src/atomic_ops/sysdeps/gcc/mips.h (AO_fetch_compare_and_swap, AO_HAVE_fetch_compare_and_swap): Implement (assuming 32-bit ABI); remove FIXME. --- diff --git a/src/atomic_ops/sysdeps/gcc/mips.h b/src/atomic_ops/sysdeps/gcc/mips.h index 1e1ad97..a37c6b5 100644 --- a/src/atomic_ops/sysdeps/gcc/mips.h +++ b/src/atomic_ops/sysdeps/gcc/mips.h @@ -40,38 +40,64 @@ AO_nop_full(void) } #define AO_HAVE_nop_full -AO_INLINE int -AO_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val) +#ifndef AO_GENERALIZE_ASM_BOOL_CAS + AO_INLINE int + AO_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val) + { + register int was_equal = 0; + register int temp; + + __asm__ __volatile__( + " .set push \n" + " .set mips2 \n" + " .set noreorder \n" + " .set nomacro \n" + "1: ll %0, %1 \n" + " bne %0, %4, 2f \n" + " move %0, %3 \n" + " sc %0, %1 \n" + " .set pop \n" + " beqz %0, 1b \n" + " li %2, 1 \n" + "2: " + : "=&r" (temp), "+R" (*addr), "+r" (was_equal) + : "r" (new_val), "r" (old) + : "memory"); + return was_equal; + } +# define AO_HAVE_compare_and_swap +#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */ + +AO_INLINE AO_t +AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val) { - register int was_equal = 0; + register int fetched_val; register int temp; __asm__ __volatile__( - " .set push \n" - " .set mips2 \n" - " .set noreorder \n" - " .set nomacro \n" - "1: ll %0, %1 \n" - " bne %0, %4, 2f \n" - " move %0, %3 \n" - " sc %0, %1 \n" - " .set pop \n" - " beqz %0, 1b \n" - " li %2, 1 \n" - "2: " - : "=&r" (temp), "+R" (*addr), "+r" (was_equal) - : "r" (new_val), "r" (old) + " .set push\n" + " .set mips2\n" + " .set noreorder\n" + " .set nomacro\n" + "1: ll %0, %2\n" + " bne %0, %4, 2f\n" + " move %1, %3\n" + " sc %1, %2\n" + " beqz %1, 1b\n" + " nop\n" + " .set pop\n" + "2:" + : "=&r" (fetched_val), "=&r" (temp), "=m" (*addr) + : "r" (new_val), "Jr" (old) : "memory"); - return was_equal; + return (AO_t)fetched_val; } -#define AO_HAVE_compare_and_swap +#define AO_HAVE_fetch_compare_and_swap /* CAS primitives with acquire, release and full semantics are */ /* generated automatically (and AO_int_... primitives are */ /* defined properly after the first generalization pass). */ -/* FIXME: implement AO_fetch_compare_and_swap */ - /* FIXME: We should also implement AO_fetch_and_add, AO_and, AO_or, */ /* AO_xor primitives directly. */