From 62215c01acc30e34bd7af07f2f1987ee71cb19d2 Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Sat, 4 Jul 2009 14:33:53 +0000 Subject: [PATCH] Make this test work on PowerPC too. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10412 --- memcheck/tests/Makefile.am | 5 +- memcheck/tests/atomic_incs.c | 158 ++++++++++++++++++++++++++++++++--- 2 files changed, 148 insertions(+), 15 deletions(-) diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am index b7e6a8fd64..212ca0f432 100644 --- a/memcheck/tests/Makefile.am +++ b/memcheck/tests/Makefile.am @@ -185,6 +185,7 @@ EXTRA_DIST = \ check_PROGRAMS = \ addressable \ + atomic_incs \ badaddrvalue badfree badjump badjump2 \ badloop badpoll badrw brk2 buflen_check \ clientperm custom_alloc \ @@ -230,10 +231,6 @@ check_PROGRAMS = \ wrap1 wrap2 wrap3 wrap4 wrap5 wrap6 wrap7 wrap7so.so wrap8 \ writev -if VGCONF_ARCHS_INCLUDE_X86 -check_PROGRAMS += atomic_incs -endif - AM_CFLAGS += $(AM_FLAG_M3264_PRI) AM_CXXFLAGS += $(AM_FLAG_M3264_PRI) diff --git a/memcheck/tests/atomic_incs.c b/memcheck/tests/atomic_incs.c index 07d6a06684..a9b71e8375 100644 --- a/memcheck/tests/atomic_incs.c +++ b/memcheck/tests/atomic_incs.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -14,12 +15,15 @@ #define NNN 3456987 +#define IS_8_ALIGNED(_ptr) (0 == (((unsigned long)(_ptr)) & 7)) + + __attribute__((noinline)) void atomic_add_8bit ( char* p, int n ) { +#if defined(VGA_x86) unsigned long block[2]; block[0] = (unsigned long)p; block[1] = n; -#if defined(VGA_x86) __asm__ __volatile__( "movl 0(%%esi),%%eax" "\n\t" "movl 4(%%esi),%%ebx" "\n\t" @@ -27,23 +31,61 @@ __attribute__((noinline)) void atomic_add_8bit ( char* p, int n ) : : "S"(&block[0])/* S means "esi only" */ : "memory","cc","eax","ebx" ); #elif defined(VGA_amd64) + unsigned long block[2]; + block[0] = (unsigned long)p; + block[1] = n; __asm__ __volatile__( "movq 0(%%rsi),%%rax" "\n\t" "movq 8(%%rsi),%%rbx" "\n\t" "lock; addb %%bl,(%%rax)" "\n" : : "S"(&block[0])/* S means "rsi only" */ : "memory","cc","rax","rbx" ); +#elif defined(VGA_ppc32) + /* Nasty hack. Does correctly atomically do *p += n, but only if p + is 8-aligned -- guaranteed by caller. */ + unsigned long success; + do { + __asm__ __volatile__( + "lwarx 15,0,%1" "\n\t" + "add 15,15,%2" "\n\t" + "stwcx. 15,0,%1" "\n\t" + "mfcr %0" "\n\t" + "srwi %0,%0,29" "\n\t" + "andi. %0,%0,1" "\n" + : /*out*/"=b"(success) + : /*in*/ "b"(p), "b"(((unsigned long)n) << 24) + : /*trash*/ "memory", "cc", "r15" + ); + } while (success != 1); +#elif defined(VGA_ppc64) + /* Nasty hack. Does correctly atomically do *p += n, but only if p + is 8-aligned -- guaranteed by caller. */ + unsigned long success; + do { + __asm__ __volatile__( + "ldarx 15,0,%1" "\n\t" + "add 15,15,%2" "\n\t" + "stdcx. 15,0,%1" "\n\t" + "mfcr %0" "\n\t" + "srwi %0,%0,29" "\n\t" + "andi. %0,%0,1" "\n" + : /*out*/"=b"(success) + : /*in*/ "b"(p), "b"(((unsigned long)n) << 56) + : /*trash*/ "memory", "cc", "r15" + ); + } while (success != 1); #else # error "Unsupported arch" #endif } + __attribute__((noinline)) void atomic_add_16bit ( short* p, int n ) { +#if defined(VGA_x86) unsigned long block[2]; block[0] = (unsigned long)p; block[1] = n; -#if defined(VGA_x86) __asm__ __volatile__( "movl 0(%%esi),%%eax" "\n\t" "movl 4(%%esi),%%ebx" "\n\t" @@ -51,12 +93,49 @@ __attribute__((noinline)) void atomic_add_16bit ( short* p, int n ) : : "S"(&block[0])/* S means "esi only" */ : "memory","cc","eax","ebx" ); #elif defined(VGA_amd64) + unsigned long block[2]; + block[0] = (unsigned long)p; + block[1] = n; __asm__ __volatile__( "movq 0(%%rsi),%%rax" "\n\t" "movq 8(%%rsi),%%rbx" "\n\t" "lock; addw %%bx,(%%rax)" "\n" : : "S"(&block[0])/* S means "rsi only" */ : "memory","cc","rax","rbx" ); +#elif defined(VGA_ppc32) + /* Nasty hack. Does correctly atomically do *p += n, but only if p + is 8-aligned -- guaranteed by caller. */ + unsigned long success; + do { + __asm__ __volatile__( + "lwarx 15,0,%1" "\n\t" + "add 15,15,%2" "\n\t" + "stwcx. 15,0,%1" "\n\t" + "mfcr %0" "\n\t" + "srwi %0,%0,29" "\n\t" + "andi. %0,%0,1" "\n" + : /*out*/"=b"(success) + : /*in*/ "b"(p), "b"(((unsigned long)n) << 16) + : /*trash*/ "memory", "cc", "r15" + ); + } while (success != 1); +#elif defined(VGA_ppc64) + /* Nasty hack. Does correctly atomically do *p += n, but only if p + is 8-aligned -- guaranteed by caller. */ + unsigned long success; + do { + __asm__ __volatile__( + "ldarx 15,0,%1" "\n\t" + "add 15,15,%2" "\n\t" + "stdcx. 15,0,%1" "\n\t" + "mfcr %0" "\n\t" + "srwi %0,%0,29" "\n\t" + "andi. %0,%0,1" "\n" + : /*out*/"=b"(success) + : /*in*/ "b"(p), "b"(((unsigned long)n) << 48) + : /*trash*/ "memory", "cc", "r15" + ); + } while (success != 1); #else # error "Unsupported arch" #endif @@ -64,10 +143,10 @@ __attribute__((noinline)) void atomic_add_16bit ( short* p, int n ) __attribute__((noinline)) void atomic_add_32bit ( int* p, int n ) { +#if defined(VGA_x86) unsigned long block[2]; block[0] = (unsigned long)p; block[1] = n; -#if defined(VGA_x86) __asm__ __volatile__( "movl 0(%%esi),%%eax" "\n\t" "movl 4(%%esi),%%ebx" "\n\t" @@ -75,12 +154,47 @@ __attribute__((noinline)) void atomic_add_32bit ( int* p, int n ) : : "S"(&block[0])/* S means "esi only" */ : "memory","cc","eax","ebx" ); #elif defined(VGA_amd64) + unsigned long block[2]; + block[0] = (unsigned long)p; + block[1] = n; __asm__ __volatile__( "movq 0(%%rsi),%%rax" "\n\t" "movq 8(%%rsi),%%rbx" "\n\t" "lock; addl %%ebx,(%%rax)" "\n" : : "S"(&block[0])/* S means "rsi only" */ : "memory","cc","rax","rbx" ); +#elif defined(VGA_ppc32) + unsigned long success; + do { + __asm__ __volatile__( + "lwarx 15,0,%1" "\n\t" + "add 15,15,%2" "\n\t" + "stwcx. 15,0,%1" "\n\t" + "mfcr %0" "\n\t" + "srwi %0,%0,29" "\n\t" + "andi. %0,%0,1" "\n" + : /*out*/"=b"(success) + : /*in*/ "b"(p), "b"(n) + : /*trash*/ "memory", "cc", "r15" + ); + } while (success != 1); +#elif defined(VGA_ppc64) + /* Nasty hack. Does correctly atomically do *p += n, but only if p + is 8-aligned -- guaranteed by caller. */ + unsigned long success; + do { + __asm__ __volatile__( + "ldarx 15,0,%1" "\n\t" + "add 15,15,%2" "\n\t" + "stdcx. 15,0,%1" "\n\t" + "mfcr %0" "\n\t" + "srwi %0,%0,29" "\n\t" + "andi. %0,%0,1" "\n" + : /*out*/"=b"(success) + : /*in*/ "b"(p), "b"(((unsigned long)n) << 32) + : /*trash*/ "memory", "cc", "r15" + ); + } while (success != 1); #else # error "Unsupported arch" #endif @@ -88,20 +202,35 @@ __attribute__((noinline)) void atomic_add_32bit ( int* p, int n ) __attribute__((noinline)) void atomic_add_64bit ( long long int* p, int n ) { - // this is a bit subtle. It relies on the fact that, on a 64-bit platform, - // sizeof(unsigned long long int) == sizeof(unsigned long) == sizeof(void*) +#if defined(VGA_x86) || defined(VGA_ppc32) + /* do nothing; is not supported */ +#elif defined(VGA_amd64) + // this is a bit subtle. It relies on the fact that, on a 64-bit platform, + // sizeof(unsigned long long int) == sizeof(unsigned long) == sizeof(void*) unsigned long long int block[2]; block[0] = (unsigned long long int)(unsigned long)p; block[1] = n; -#if defined(VGA_x86) - /* do nothing; is not supported */ -#elif defined(VGA_amd64) __asm__ __volatile__( "movq 0(%%rsi),%%rax" "\n\t" "movq 8(%%rsi),%%rbx" "\n\t" "lock; addq %%rbx,(%%rax)" "\n" : : "S"(&block[0])/* S means "rsi only" */ : "memory","cc","rax","rbx" ); +#elif defined(VGA_ppc64) + unsigned long success; + do { + __asm__ __volatile__( + "ldarx 15,0,%1" "\n\t" + "add 15,15,%2" "\n\t" + "stdcx. 15,0,%1" "\n\t" + "mfcr %0" "\n\t" + "srwi %0,%0,29" "\n\t" + "andi. %0,%0,1" "\n" + : /*out*/"=b"(success) + : /*in*/ "b"(p), "b"(n) + : /*trash*/ "memory", "cc", "r15" + ); + } while (success != 1); #else # error "Unsupported arch" #endif @@ -132,6 +261,13 @@ int main ( int argc, char** argv ) p32 = (int*)(page+512); p64 = (long long int*)(page+768); + assert( IS_8_ALIGNED(p8) ); + assert( IS_8_ALIGNED(p16) ); + assert( IS_8_ALIGNED(p32) ); + assert( IS_8_ALIGNED(p64) ); + + memset(page, 0, 1024); + *p8 = 0; *p16 = 0; *p32 = 0; @@ -175,12 +311,12 @@ int main ( int argc, char** argv ) assert(WIFEXITED(status)); printf("FINAL VALUES: 8 bit %d, 16 bit %d, 32 bit %d, 64 bit %lld\n", - (int)(*p8), (int)(*p16), *p32, *p64 ); + (int)(*(signed char*)p8), (int)(*p16), *p32, *p64 ); - if (-74 == (int)(*p8) + if (-74 == (int)(*(signed char*)p8) && 32694 == (int)(*p16) && 6913974 == *p32 - && (0LL == *p64 || 682858642110 == *p64)) { + && (0LL == *p64 || 682858642110LL == *p64)) { printf("PASS\n"); } else { printf("FAIL -- see source code for expected values\n"); -- 2.47.3