summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabrizio Fabbri <ffabbri4@bloomberg.net>2016-03-02 11:35:47 -0500
committerIvan Maidanski <ivmai@mail.ru>2016-03-04 21:10:59 +0300
commitf2471925f7d3c4b38f65a75bd22eca1f4fdb98a6 (patch)
tree0db05860217955a2a17b9497a39ffc58cd1f3ff9
parentc0ed77aa8ca564c7ee905dcf5dca032049a23967 (diff)
downloadlibatomic_ops-f2471925f7d3c4b38f65a75bd22eca1f4fdb98a6.tar.gz
Initial ibmc/powerpc (xlc) support
* src/atomic_ops/sysdeps/ibmc/powerpc.h: Include test_and_set_t_is_ao_t.h. * src/atomic_ops/sysdeps/ibmc/powerpc.h (AO_test_and_set, AO_fetch_compare_and_swap): Implement.
-rw-r--r--src/atomic_ops/sysdeps/ibmc/powerpc.h71
1 files changed, 63 insertions, 8 deletions
diff --git a/src/atomic_ops/sysdeps/ibmc/powerpc.h b/src/atomic_ops/sysdeps/ibmc/powerpc.h
index e2d4027..a930b16 100644
--- a/src/atomic_ops/sysdeps/ibmc/powerpc.h
+++ b/src/atomic_ops/sysdeps/ibmc/powerpc.h
@@ -1,5 +1,4 @@
-/* FIXME. This is only a placeholder for the AIX compiler. */
-/* It doesn't work. Please send a patch. */
+
/* Memory model documented at http://www-106.ibm.com/developerworks/ */
/* eserver/articles/archguide.html and (clearer) */
/* http://www-106.ibm.com/developerworks/eserver/articles/powerpc.html. */
@@ -16,6 +15,8 @@
#include "../all_aligned_atomic_load_store.h"
+#include "../test_and_set_t_is_ao_t.h"
+
void AO_sync(void);
#pragma mc_func AO_sync { "7c0004ac" }
@@ -55,11 +56,41 @@ AO_store_release(volatile AO_t *addr, AO_t value)
/* This is similar to the code in the garbage collector. Deleting */
/* this and having it synthesized from compare_and_swap would probably */
/* only cost us a load immediate instruction. */
-/*AO_INLINE AO_TS_VAL_t
+AO_INLINE AO_TS_VAL_t
AO_test_and_set(volatile AO_TS_t *addr) {
-# error FIXME Implement me
+#if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__)
+/* Completely untested. And we should be using smaller objects anyway. */
+ unsigned long oldval;
+ unsigned long temp = 1; /* locked value */
+
+ __asm__ __volatile__(
+ "1:ldarx %0,0,%1\n" /* load and reserve */
+ "cmpdi %0, 0\n" /* if load is */
+ "bne 2f\n" /* non-zero, return already set */
+ "stdcx. %2,0,%1\n" /* else store conditional */
+ "bne- 1b\n" /* retry if lost reservation */
+ "2:\n" /* oldval is zero if we set */
+ : "=&r"(oldval)
+ : "r"(addr), "r"(temp)
+ : "memory", "cr0");
+#else
+ int oldval;
+ int temp = 1; /* locked value */
+
+ __asm__ __volatile__(
+ "1:lwarx %0,0,%1\n" /* load and reserve */
+ "cmpwi %0, 0\n" /* if load is */
+ "bne 2f\n" /* non-zero, return already set */
+ "stwcx. %2,0,%1\n" /* else store conditional */
+ "bne- 1b\n" /* retry if lost reservation */
+ "2:\n" /* oldval is zero if we set */
+ : "=&r"(oldval)
+ : "r"(addr), "r"(temp)
+ : "memory", "cr0");
+#endif
+ return (AO_TS_VAL_t)oldval;
}
-#define AO_HAVE_test_and_set*/
+#define AO_HAVE_test_and_set
AO_INLINE AO_TS_VAL_t
AO_test_and_set_acquire(volatile AO_TS_t *addr) {
@@ -87,12 +118,36 @@ AO_test_and_set_full(volatile AO_TS_t *addr) {
#define AO_HAVE_test_and_set_full
#endif /* !AO_PREFER_GENERALIZED */
-/*AO_INLINE AO_t
+AO_INLINE AO_t
AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val)
{
-# error FIXME Implement me
+ AO_t fetched_val;
+# if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__)
+ __asm__ __volatile__(
+ "1:ldarx %0,0,%1\n" /* load and reserve */
+ "cmpd %0, %3\n" /* if load is not equal to */
+ "bne 2f\n" /* old_val, fail */
+ "stdcx. %2,0,%1\n" /* else store conditional */
+ "bne- 1b\n" /* retry if lost reservation */
+ "2:\n"
+ : "=&r"(fetched_val)
+ : "r"(addr), "r"(new_val), "r"(old_val)
+ : "memory", "cr0");
+# else
+ __asm__ __volatile__(
+ "1:lwarx %0,0,%1\n" /* load and reserve */
+ "cmpw %0, %3\n" /* if load is not equal to */
+ "bne 2f\n" /* old_val, fail */
+ "stwcx. %2,0,%1\n" /* else store conditional */
+ "bne- 1b\n" /* retry if lost reservation */
+ "2:\n"
+ : "=&r"(fetched_val)
+ : "r"(addr), "r"(new_val), "r"(old_val)
+ : "memory", "cr0");
+# endif
+ return fetched_val;
}
-#define AO_HAVE_fetch_compare_and_swap*/
+#define AO_HAVE_fetch_compare_and_swap
AO_INLINE AO_t
AO_fetch_compare_and_swap_acquire(volatile AO_t *addr, AO_t old_val,