server/dep/acelite/ace/Atomic_Op_Sparc.c
2023-01-01 00:55:45 +00:00

187 lines
4.7 KiB
C

/* $Id: Atomic_Op_Sparc.c 80826 2008-03-04 14:51:23Z wotte $
*
* 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 */