From 807a673c1dd35d0c4903a12e4b62bebceeb3dca5 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 10 Jul 2013 20:17:20 -0700 Subject: [PATCH] Added PowerPC and ARM versions of the memory barrier functions. --- include/SDL_atomic.h | 26 +++++++++++++++++++++++--- src/atomic/SDL_atomic.c | 14 ++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/include/SDL_atomic.h b/include/SDL_atomic.h index 65c3b6dfe..7bd669d1a 100644 --- a/include/SDL_atomic.h +++ b/include/SDL_atomic.h @@ -155,11 +155,31 @@ void _ReadWriteBarrier(void); * For more information on these semantics, take a look at the blog post: * http://preshing.com/20120913/acquire-and-release-semantics */ -/* FIXME: This is correct for x86 and x64 but not other CPUs - For PPC we need the lwsync instruction, and on ARM some variant of dmb - */ +#if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__)) +#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("lwsync" : : : "memory") +#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("lwsync" : : : "memory") +#elif defined(__GNUC__) && defined(__arm__) +#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) +#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory") +#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory") +#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) +#ifdef __thumb__ +/* The mcr instruction isn't available in thumb mode, use real functions */ +extern DECLSPEC void SDLCALL SDL_MemoryBarrierRelease(); +extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquire(); +#else +#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory") +#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory") +#endif /* __thumb__ */ +#else +#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("" : : : "memory") +#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("" : : : "memory") +#endif /* __GNUC__ && __arm__ */ +#else +/* This is correct for the x86 and x64 CPUs, and we'll expand this over time. */ #define SDL_MemoryBarrierRelease() SDL_CompilerBarrier() #define SDL_MemoryBarrierAcquire() SDL_CompilerBarrier() +#endif /* Platform specific optimized versions of the atomic functions, diff --git a/src/atomic/SDL_atomic.c b/src/atomic/SDL_atomic.c index cd799dea7..c747b12aa 100644 --- a/src/atomic/SDL_atomic.c +++ b/src/atomic/SDL_atomic.c @@ -101,4 +101,18 @@ SDL_AtomicCASPtr(void **a, void *oldval, void *newval) return retval; } +#if defined(__GNUC__) && defined(__arm__) && \ + (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__)) +__asm__( +" .align 2\n" +" .globl _SDL_MemoryBarrierRelease\n" +" .globl _SDL_MemoryBarrierAcquire\n" +"_SDL_MemoryBarrierRelease:\n" +"_SDL_MemoryBarrierAcquire:\n" +" mov r0, #0\n" +" mcr p15, 0, r0, c7, c10, 5\n" +" bx lr\n" +); +#endif /* __GNUC__ && __arm__ && ARMV6 */ + /* vi: set ts=4 sw=4 expandtab: */