summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhboehm <hboehm>2009-02-25 05:30:41 +0000
committerIvan Maidanski <ivmai@mail.ru>2011-07-25 16:03:24 +0400
commitdefad3052dd3d70c768c9ffb8ff266c50158749f (patch)
tree183eddb238b2f331ef406c2bc1d65d7483a83e5a
parentc69538936623d2a41f71c88b50e5ce6c8ba2d5e1 (diff)
downloadlibatomic_ops-defad3052dd3d70c768c9ffb8ff266c50158749f.tar.gz
2009-02-24 Hans Boehm <Hans.Boehm@hp.com> (Really primarily Earl Chew)
* src/atomic_ops/sysdeps/gcc/powerpc.h: Add index, update modifiers to asms, refine clobbers to "cr0", use cr0 instead of cr7, add explicit AO_fetch_and_add, add UNTESTED 64 bit support.
-rw-r--r--ChangeLog6
-rw-r--r--src/atomic_ops/sysdeps/gcc/powerpc.h107
2 files changed, 96 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index 3f6aa7c..68d7d9f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2009-02-24 Hans Boehm <Hans.Boehm@hp.com> (Really primarily Earl Chew)
+ * src/atomic_ops/sysdeps/gcc/powerpc.h: Add index,
+ update modifiers to asms, refine clobbers to "cr0", use
+ cr0 instead of cr7, add explicit AO_fetch_and_add,
+ add UNTESTED 64 bit support.
+
2008-11-10 Hans Boehm <Hans.Boehm@hp.com> (Really Joerg Wagner)
* src/atomic_ops/sysdeps/armcc/arm_v6.h: Compute
AO_compare_and_swap value differently, add
diff --git a/src/atomic_ops/sysdeps/gcc/powerpc.h b/src/atomic_ops/sysdeps/gcc/powerpc.h
index db63c7a..28d8986 100644
--- a/src/atomic_ops/sysdeps/gcc/powerpc.h
+++ b/src/atomic_ops/sysdeps/gcc/powerpc.h
@@ -15,7 +15,6 @@
*
*/
-/* FIXME. Incomplete. No support for 64 bits. */
/* 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. */
@@ -29,6 +28,7 @@
/* from cached memory. */
/* Thanks to Maged Michael, Doug Lea, and Roger Hoover for helping to */
/* track some of this down and correcting my misunderstandings. -HB */
+/* Earl Chew subsequently contributed further fixes & additions. */
#include "../all_aligned_atomic_load_store.h"
@@ -74,16 +74,13 @@ AO_load_acquire(const volatile AO_t *addr)
{
AO_t result;
- /* FIXME: We should get gcc to allocate one of the condition */
- /* registers. I always got "impossible constraint" when I */
- /* tried the "y" constraint. */
- __asm__ __volatile__ (
- "ld %0,%1\n"
- "cmpw cr7,%0,%0\n"
- "bne- cr7,1f\n"
+ __asm__ __volatile__ (
+ "ld%U1%X1 %0,%1\n"
+ "cmpw %0,%0\n"
+ "bne- 1f\n"
"1: isync\n"
: "=r" (result)
- : "m"(*addr) : "memory", "cc");
+ : "m"(*addr) : "memory", "cr0");
return result;
}
#else
@@ -97,8 +94,8 @@ AO_load_acquire(const volatile AO_t *addr)
/* tried the "y" constraint. */
__asm__ __volatile__ (
"lwz%U1%X1 %0,%1\n"
- "cmpw cr7,%0,%0\n"
- "bne- cr7,1f\n"
+ "cmpw %0,%0\n"
+ "bne- 1f\n"
"1: isync\n"
: "=r" (result)
: "m"(*addr) : "memory", "cc");
@@ -137,7 +134,7 @@ AO_test_and_set(volatile AO_TS_t *addr) {
"2:\n" /* oldval is zero if we set */
: "=&r"(oldval)
: "r"(addr), "r"(temp)
- : "memory", "cc");
+ : "memory", "cr0");
return (AO_TS_VAL_t)oldval;
}
@@ -158,7 +155,7 @@ AO_test_and_set(volatile AO_TS_t *addr) {
"2:\n" /* oldval is zero if we set */
: "=&r"(oldval)
: "r"(addr), "r"(temp)
- : "memory", "cc");
+ : "memory", "cr0");
return (AO_TS_VAL_t)oldval;
}
@@ -212,7 +209,7 @@ AO_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val) {
"2:\n"
: "=&r"(oldval), "=&r"(result)
: "r"(addr), "r"(new_val), "r"(old), "1"(result)
- : "memory", "cc");
+ : "memory", "cr0");
return result;
}
@@ -234,7 +231,7 @@ AO_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val) {
"2:\n"
: "=&r"(oldval), "=&r"(result)
: "r"(addr), "r"(new_val), "r"(old), "1"(result)
- : "memory", "cc");
+ : "memory", "cr0");
return result;
}
@@ -270,5 +267,81 @@ AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) {
#define AO_HAVE_compare_and_swap_full
-/* FIXME: We should also implement fetch_and_add and or primitives */
-/* directly. */
+#if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__)
+/* FIXME: Completely untested. */
+
+AO_INLINE AO_t
+AO_fetch_and_add(volatile AO_t *addr, AO_t incr) {
+ AO_t oldval;
+ AO_t newval;
+
+ __asm__ __volatile__(
+ "1:ldarx %0,0,%2\n" /* load and reserve */
+ "add %1,%0,%3\n" /* increment */
+ "stdcx. %1,0,%2\n" /* store conditional */
+ "bne- 1b\n" /* retry if lost reservation */
+ : "=&r"(oldval), "=&r"(newval)
+ : "r"(addr), "r"(incr)
+ : "memory", "cr0");
+
+ return oldval;
+}
+
+#define AO_HAVE_fetch_and_add
+
+#else
+
+AO_INLINE AO_t
+AO_fetch_and_add(volatile AO_t *addr, AO_t incr) {
+ AO_t oldval;
+ AO_t newval;
+
+ __asm__ __volatile__(
+ "1:lwarx %0,0,%2\n" /* load and reserve */
+ "add %1,%0,%3\n" /* increment */
+ "stwcx. %1,0,%2\n" /* store conditional */
+ "bne- 1b\n" /* retry if lost reservation */
+ : "=&r"(oldval), "=&r"(newval)
+ : "r"(addr), "r"(incr)
+ : "memory", "cr0");
+
+ return oldval;
+}
+
+#define AO_HAVE_fetch_and_add
+
+#endif
+
+AO_INLINE AO_t
+AO_fetch_and_add_acquire(volatile AO_t *addr, AO_t incr) {
+ AO_t result = AO_fetch_and_add(addr, incr);
+ AO_lwsync();
+ return result;
+}
+
+#define AO_HAVE_fetch_and_add_acquire
+
+AO_INLINE AO_t
+AO_fetch_and_add_release(volatile AO_t *addr, AO_t incr) {
+ AO_lwsync();
+ return AO_fetch_and_add(addr, incr);
+}
+
+#define AO_HAVE_fetch_and_add_release
+
+AO_INLINE AO_t
+AO_fetch_and_add_full(volatile AO_t *addr, AO_t incr) {
+ AO_t result;
+ AO_lwsync();
+ result = AO_fetch_and_add(addr, incr);
+ AO_lwsync();
+ return result;
+}
+
+#define AO_HAVE_fetch_and_add_full
+
+#if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__)
+#else
+# include "../ao_t_is_int.h"
+#endif
+