summaryrefslogtreecommitdiff
path: root/ACE/ace/Atomic_Op_Sparc.c
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/ace/Atomic_Op_Sparc.c')
-rw-r--r--ACE/ace/Atomic_Op_Sparc.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/ACE/ace/Atomic_Op_Sparc.c b/ACE/ace/Atomic_Op_Sparc.c
new file mode 100644
index 00000000000..75d64eb6ac5
--- /dev/null
+++ b/ACE/ace/Atomic_Op_Sparc.c
@@ -0,0 +1,187 @@
+/* $Id$
+ *
+ * This is a C file for a reason. The Sun C++ compiler does not accept
+ * inline assembler.
+ *
+ * Portions of this code are based on atomic operations found in the
+ * linux kernel source code.
+ */
+
+#if defined (ACE_INCLUDE_ATOMIC_OP_SPARC)
+
+#if defined(__i386) && defined(__SUNPRO_C)
+static void
+__sunpro_asm_code() {
+ __asm("\n\
+ .globl ace_atomic_add_long \n\
+ .type ace_atomic_add_long,@function \n\
+ .align 4 \n\
+ace_atomic_add_long: \n\
+ movl 0x00000004(%esp), %edx \n\
+ movl 0x00000008(%esp), %eax \n\
+ lock; xadd %eax, (%edx) \n\
+ addl 0x00000008(%esp), %eax \n\
+ ret \n\
+ ");
+
+ __asm("\n\
+ .globl ace_atomic_swap_long \n\
+ .type ace_atomic_swap_long,@function \n\
+ .align 4 \n\
+ace_atomic_swap_long: \n\
+ movl 0x00000004(%esp), %edx \n\
+ movl 0x00000008(%esp), %eax \n\
+ xchg %eax, (%edx) \n\
+ ret \n\
+ ");
+
+ __asm("\n\
+ .globl ace_atomic_swap_add_long \n\
+ .type ace_atomic_swap_add_long,@function \n\
+ .align 4 \n\
+ace_atomic_swap_add_long: \n\
+ movl 0x00000004(%esp), %edx \n\
+ movl 0x00000008(%esp), %eax \n\
+ lock; xadd %eax, (%edx) \n\
+ ret \n\
+ ");
+}
+
+#elif defined(__x86_64) && defined(__SUNPRO_C)
+
+static void
+__sunpro_asm_code() {
+ __asm("\n\
+ .globl ace_atomic_add_long \n\
+ .type ace_atomic_add_long,@function \n\
+ .align 16 \n\
+ace_atomic_add_long: \n\
+ movq %rsi, %rax \n\
+ lock; xaddq %rax, (%rdi) \n\
+ addq %rsi, %rax \n\
+ ret \n\
+ ");
+
+ __asm("\n\
+ .globl ace_atomic_swap_long \n\
+ .type ace_atomic_swap_long,@function \n\
+ .align 16 \n\
+ace_atomic_swap_long: \n\
+ xchgq %rsi, (%rdi) \n\
+ movq %rsi, %rax \n\
+ ret \n\
+ ");
+
+ __asm("\n\
+ .globl ace_atomic_swap_add_long \n\
+ .type ace_atomic_swap_add_long,@function \n\
+ .align 16 \n\
+ace_atomic_swap_add_long: \n\
+ lock; xaddq %rsi, (%rdi) \n\
+ movq %rsi, %rax \n\
+ ret \n\
+ ");
+}
+
+#elif defined (__sparcv9)
+
+unsigned long
+ace_atomic_add_long (volatile unsigned long *dest, long rhs)
+{
+ __asm ("restore\n"
+ "ldx [%o0], %o2\n"
+ ".again_add:\n"
+ "add %o2, %o1, %o3\n"
+ "casx [%o0], %o2, %o3\n"
+ "cmp %o2, %o3\n"
+ "bne,pn %xcc, .again_add\n"
+ "mov %o3, %o2\n"
+ "retl\n"
+ "add %o2, %o1, %o0\n");
+}
+
+unsigned long
+ace_atomic_swap_long (volatile unsigned long *dest, unsigned long rhs)
+{
+ __asm ("restore\n"
+ "ldx [%o0], %o2\n"
+ ".again_swap:\n"
+ "mov %o1, %o3\n"
+ "casx [%o0], %o2, %o3\n"
+ "cmp %o2, %o3\n"
+ "bne,pn %xcc, .again_swap\n"
+ "mov %o3, %o2\n"
+ "retl\n"
+ "mov %o3, %o0\n");
+}
+
+unsigned long
+ace_atomic_swap_add_long (volatile unsigned long *dest, long rhs)
+{
+ __asm ("restore\n"
+ "ldx [%o0], %o2\n"
+ ".again_swap_add:\n"
+ "mov %o2, %o4\n"
+ "add %o2, %o1, %o3\n"
+ "casx [%o0], %o2, %o3\n"
+ "cmp %o2, %o3\n"
+ "bne,pn %xcc, .again_swap_add\n"
+ "mov %o3, %o2\n"
+ "retl\n"
+ "mov %o4, %o0\n");
+}
+
+#else
+
+unsigned long
+ace_atomic_add_long (volatile unsigned long *dest, long rhs)
+{
+ __asm ("restore\n"
+ "ld [%o0], %o2\n"
+ ".again_add:\n"
+ "add %o2, %o1, %o3\n"
+ "cas [%o0], %o2, %o3\n"
+ "cmp %o2, %o3\n"
+ "bne,pn %icc, .again_add\n"
+ "mov %o3, %o2\n"
+ "retl\n"
+ "add %o2, %o1, %o0\n");
+}
+
+unsigned long
+ace_atomic_swap_long (volatile unsigned long *dest, unsigned long rhs)
+{
+ __asm ("restore\n"
+ "ld [%o0], %o2\n"
+ ".again_swap:\n"
+ "mov %o1, %o3\n"
+ "cas [%o0], %o2, %o3\n"
+ "cmp %o2, %o3\n"
+ "bne,pn %icc, .again_swap\n"
+ "mov %o3, %o2\n"
+ "retl\n"
+ "mov %o3, %o0\n");
+}
+
+unsigned long
+ace_atomic_swap_add_long (volatile unsigned long *dest, long rhs)
+{
+ __asm ("restore\n"
+ "ld [%o0], %o2\n"
+ ".again_swap_add:\n"
+ "mov %o2, %o4\n"
+ "add %o2, %o1, %o3\n"
+ "cas [%o0], %o2, %o3\n"
+ "cmp %o2, %o3\n"
+ "bne,pn %icc, .again_swap_add\n"
+ "mov %o3, %o2\n"
+ "retl\n"
+ "mov %o4, %o0\n");
+}
+
+# endif /* __sparcv9 */
+
+#elif !defined (__GNUC__) && !defined (__INTEL_COMPILER)
+/* Make compilers stop complaining about an empty translation unit */
+static int shut_up_compiler = 0;
+#endif /* ACE_INCLUDE_ATOMIC_OP_SPARC */