mips: add mips64le support for atomic_incs and annotate_hbefore tests
Add mips64-le implementation of:
- atomic_add_8bit
- atomic_add_16bit
- atomic_add_32bit
- atomic_add_64bit
- do_acasW
Minor fixes for mips32 implementations are included as well.
These functions are needed to execute atomic_incs and annotate_hbefore
tests on mips64le.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13357 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/helgrind/tests/annotate_hbefore.c b/helgrind/tests/annotate_hbefore.c
index cd58cef..3ddf3dc 100644
--- a/helgrind/tests/annotate_hbefore.c
+++ b/helgrind/tests/annotate_hbefore.c
@@ -188,7 +188,7 @@
#elif defined(VGA_mips32)
-// mips
+// mips32
/* return 1 if success, 0 if failure */
UWord do_acasW ( UWord* addr, UWord expected, UWord nyu )
{
@@ -202,13 +202,47 @@
"lw $t3, 4(%1)" "\n\t"
"ll $t1, 0($t0)" "\n\t"
"bne $t1, $t2, exit_0" "\n\t"
+ "nop" "\n\t"
"sc $t3, 0($t0)" "\n\t"
"move %0, $t3" "\n\t"
"b exit" "\n\t"
"nop" "\n\t"
"exit_0:" "\n\t"
- "move %0, $0" "\n\t"
- "exit:" "\n\t"
+ "move %0, $zero" "\n\t"
+ "exit:" "\n\t"
+ : /*out*/ "=r"(success)
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "t0", "t1", "t2", "t3", "memory"
+ );
+
+ assert(success == 0 || success == 1);
+ return success;
+}
+
+#elif defined(VGA_mips64)
+
+// mips64
+/* return 1 if success, 0 if failure */
+UWord do_acasW ( UWord* addr, UWord expected, UWord nyu )
+{
+ UWord old, success;
+ UWord block[3] = { (UWord)addr, nyu, expected};
+
+ __asm__ __volatile__(
+ ".set noreorder" "\n\t"
+ "ld $t0, 0(%1)" "\n\t"
+ "ld $t2, 16(%1)" "\n\t"
+ "ld $t3, 8(%1)" "\n\t"
+ "ll $t1, 0($t0)" "\n\t"
+ "bne $t1, $t2, exit_0" "\n\t"
+ "nop" "\n\t"
+ "sc $t3, 0($t0)" "\n\t"
+ "move %0, $t3" "\n\t"
+ "b exit" "\n\t"
+ "nop" "\n\t"
+ "exit_0:" "\n\t"
+ "move %0, $zero" "\n\t"
+ "exit:" "\n\t"
: /*out*/ "=r"(success)
: /*in*/ "r"(&block[0])
: /*trash*/ "t0", "t1", "t2", "t3", "memory"
diff --git a/memcheck/tests/atomic_incs.c b/memcheck/tests/atomic_incs.c
index ac1e775..ae1368c 100644
--- a/memcheck/tests/atomic_incs.c
+++ b/memcheck/tests/atomic_incs.c
@@ -111,44 +111,73 @@
: "d" (n)
: "cc", "memory", "0", "1");
#elif defined(VGA_mips32)
+ /* We rely on the fact that p is 4-aligned. Otherwise 'll' may throw an
+ exception that can cause this function to fail. */
#if defined (_MIPSEL)
unsigned int block[3]
- = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF };
+ = { (unsigned int)p, (unsigned int)n, 0x0 };
do {
__asm__ __volatile__(
- "move $t0, %0" "\n\t"
- "lw $t1, 0($t0)" "\n\t" // p
- "lw $t2, 4($t0)" "\n\t" // n
- "ll $t3, 0($t1)" "\n\t"
- "addu $t3, $t3, $t2" "\n\t"
- "andi $t3, $t3, 0xFF" "\n\t"
+ "move $t0, %0" "\n\t"
+ "lw $t1, 0($t0)" "\n\t" // p
+ "lw $t2, 4($t0)" "\n\t" // n
+ "andi $t2, $t2, 0xFF" "\n\t" // n = n and 0xFF
+ "li $t4, 0xFF" "\n\t"
+ "nor $t4, $t4, $zero" "\n\t" // $t4 = 0xFFFFFF00
+ "ll $t3, 0($t1)" "\n\t" // $t3 = old value
+ "and $t4, $t4, $t3" "\n\t" // $t4 = $t3 and 0xFFFFFF00
+ "addu $t3, $t3, $t2" "\n\t" // $t3 = $t3 + n
+ "andi $t3, $t3, 0xFF" "\n\t" // $t3 = $t3 and 0xFF
+ "or $t3, $t3, $t4" "\n\t" // $t3 = $t3 or $t4
"sc $t3, 0($t1)" "\n\t"
- "sw $t3, 8($t0)" "\n\t"
+ "sw $t3, 8($t0)" "\n\t" // save result
: /*out*/
: /*in*/ "r"(&block[0])
- : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3"
+ : /*trash*/ "memory", "t0", "t1", "t2", "t3", "t4"
);
} while (block[2] != 1);
#elif defined (_MIPSEB)
unsigned int block[3]
- = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF };
+ = { (unsigned int)p, (unsigned int)n << 24, 0x0 };
do {
__asm__ __volatile__(
- "move $t0, %0" "\n\t"
- "lw $t1, 0($t0)" "\n\t" // p
- "lw $t2, 4($t0)" "\n\t" // n
- "li $t4, 0x000000FF" "\n\t"
- "ll $t3, 0($t1)" "\n\t"
- "addu $t3, $t3, $t2" "\n\t"
- "and $t3, $t3, $t4" "\n\t"
- "wsbh $t4, $t3" "\n\t"
- "rotr $t4, $t4, 16" "\n\t"
- "or $t3, $t4, $t3" "\n\t"
- "sc $t3, 0($t1)" "\n\t"
- "sw $t3, 8($t0)" "\n\t"
+ "move $t0, %0" "\n\t"
+ "lw $t1, 0($t0)" "\n\t" // p
+ "lw $t2, 4($t0)" "\n\t" // n
+ "ll $t3, 0($t1)" "\n\t"
+ "addu $t3, $t3, $t2" "\n\t"
+ "sc $t3, 0($t1)" "\n\t"
+ "sw $t3, 8($t0)" "\n\t"
: /*out*/
: /*in*/ "r"(&block[0])
- : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3", "t4"
+ : /*trash*/ "memory", "t0", "t1", "t2", "t3"
+ );
+ } while (block[2] != 1);
+#endif
+#elif defined(VGA_mips64)
+ /* We rely on the fact that p is 4-aligned. Otherwise 'll' may throw an
+ exception that can cause this function to fail. */
+#if defined (_MIPSEL)
+ unsigned long block[3]
+ = { (unsigned long)p, (unsigned long)n, 0x0ULL };
+ do {
+ __asm__ __volatile__(
+ "move $t0, %0" "\n\t"
+ "ld $t1, 0($t0)" "\n\t" // p
+ "ld $t2, 8($t0)" "\n\t" // n
+ "andi $t2, $t2, 0xFF" "\n\t" // n = n and 0xFF
+ "li $s0, 0xFF" "\n\t"
+ "nor $s0, $s0, $zero" "\n\t" // $s0 = 0xFFFFFF00
+ "ll $t3, 0($t1)" "\n\t" // $t3 = old value
+ "and $s0, $s0, $t3" "\n\t" // $s0 = $t3 and 0xFFFFFF00
+ "addu $t3, $t3, $t2" "\n\t" // $t3 = $t3 + n
+ "andi $t3, $t3, 0xFF" "\n\t" // $t3 = $t3 and 0xFF
+ "or $t3, $t3, $s0" "\n\t" // $t3 = $t3 or $s0
+ "sc $t3, 0($t1)" "\n\t"
+ "sw $t3, 16($t0)" "\n\t" // save result
+ : /*out*/
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "memory", "t0", "t1", "t2", "t3", "s0"
);
} while (block[2] != 1);
#endif
@@ -246,39 +275,73 @@
: "d" (n)
: "cc", "memory", "0", "1");
#elif defined(VGA_mips32)
+ /* We rely on the fact that p is 4-aligned. Otherwise 'll' may throw an
+ exception that can cause this function to fail. */
#if defined (_MIPSEL)
unsigned int block[3]
- = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF };
+ = { (unsigned int)p, (unsigned int)n, 0x0 };
do {
__asm__ __volatile__(
- "move $t0, %0" "\n\t"
- "lw $t1, 0($t0)" "\n\t" // p
- "lw $t2, 4($t0)" "\n\t" // n
- "ll $t3, 0($t1)" "\n\t"
- "addu $t3, $t3, $t2" "\n\t"
- "andi $t3, $t3, 0xFFFF" "\n\t"
+ "move $t0, %0" "\n\t"
+ "lw $t1, 0($t0)" "\n\t" // p
+ "lw $t2, 4($t0)" "\n\t" // n
+ "andi $t2, $t2, 0xFFFF" "\n\t" // n = n and 0xFFFF
+ "li $t4, 0xFFFF" "\n\t"
+ "nor $t4, $t4, $zero" "\n\t" // $t4 = 0xFFFF0000
+ "ll $t3, 0($t1)" "\n\t" // $t3 = old value
+ "and $t4, $t4, $t3" "\n\t" // $t4 = $t3 and 0xFFFF0000
+ "addu $t3, $t3, $t2" "\n\t" // $t3 = $t3 + n
+ "andi $t3, $t3, 0xFFFF" "\n\t" // $t3 = $t3 and 0xFFFF
+ "or $t3, $t3, $t4" "\n\t" // $t3 = $t3 or $t4
"sc $t3, 0($t1)" "\n\t"
- "sw $t3, 8($t0)" "\n\t"
+ "sw $t3, 8($t0)" "\n\t" // save result
: /*out*/
: /*in*/ "r"(&block[0])
- : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3"
+ : /*trash*/ "memory", "t0", "t1", "t2", "t3", "t4"
);
} while (block[2] != 1);
#elif defined (_MIPSEB)
unsigned int block[3]
- = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF };
+ = { (unsigned int)p, (unsigned int)n << 16, 0x0 };
do {
__asm__ __volatile__(
- "move $t0, %0" "\n\t"
- "lw $t1, 0($t0)" "\n\t" // p
- "li $t2, 32694" "\n\t" // n
- "li $t3, 0x1" "\n\t"
- "sll $t2, $t2, 16" "\n\t"
- "sw $t2, 0($t1)" "\n\t"
- "sw $t3, 8($t0)" "\n\t"
+ "move $t0, %0" "\n\t"
+ "lw $t1, 0($t0)" "\n\t" // p
+ "lw $t2, 4($t0)" "\n\t" // n
+ "ll $t3, 0($t1)" "\n\t"
+ "addu $t3, $t3, $t2" "\n\t"
+ "sc $t3, 0($t1)" "\n\t"
+ "sw $t3, 8($t0)" "\n\t"
: /*out*/
: /*in*/ "r"(&block[0])
- : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3"
+ : /*trash*/ "memory", "t0", "t1", "t2", "t3"
+ );
+ } while (block[2] != 1);
+#endif
+#elif defined(VGA_mips64)
+ /* We rely on the fact that p is 4-aligned. Otherwise 'll' may throw an
+ exception that can cause this function to fail. */
+#if defined (_MIPSEL)
+ unsigned long block[3]
+ = { (unsigned long)p, (unsigned long)n, 0x0ULL };
+ do {
+ __asm__ __volatile__(
+ "move $t0, %0" "\n\t"
+ "ld $t1, 0($t0)" "\n\t" // p
+ "ld $t2, 8($t0)" "\n\t" // n
+ "andi $t2, $t2, 0xFFFF" "\n\t" // n = n and 0xFFFF
+ "li $s0, 0xFFFF" "\n\t"
+ "nor $s0, $s0, $zero" "\n\t" // $s0= 0xFFFF0000
+ "ll $t3, 0($t1)" "\n\t" // $t3 = old value
+ "and $s0, $s0, $t3" "\n\t" // $s0 = $t3 and 0xFFFF0000
+ "addu $t3, $t3, $t2" "\n\t" // $t3 = $t3 + n
+ "andi $t3, $t3, 0xFFFF" "\n\t" // $t3 = $t3 and 0xFFFF
+ "or $t3, $t3, $s0" "\n\t" // $t3 = $t3 or $s0
+ "sc $t3, 0($t1)" "\n\t"
+ "sw $t3, 16($t0)" "\n\t" // save result
+ : /*out*/
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "memory", "t0", "t1", "t2", "t3", "s0"
);
} while (block[2] != 1);
#endif
@@ -370,19 +433,36 @@
: "cc", "memory", "0", "1");
#elif defined(VGA_mips32)
unsigned int block[3]
- = { (unsigned int)p, (unsigned int)n, 0xFFFFFFFF };
+ = { (unsigned int)p, (unsigned int)n, 0x0 };
do {
__asm__ __volatile__(
- "move $t0, %0" "\n\t"
- "lw $t1, 0($t0)" "\n\t" // p
- "lw $t2, 4($t0)" "\n\t" // n
- "ll $t3, 0($t1)" "\n\t"
- "addu $t3, $t3, $t2" "\n\t"
- "sc $t3, 0($t1)" "\n\t"
- "sw $t3, 8($t0)" "\n\t"
+ "move $t0, %0" "\n\t"
+ "lw $t1, 0($t0)" "\n\t" // p
+ "lw $t2, 4($t0)" "\n\t" // n
+ "ll $t3, 0($t1)" "\n\t"
+ "addu $t3, $t3, $t2" "\n\t"
+ "sc $t3, 0($t1)" "\n\t"
+ "sw $t3, 8($t0)" "\n\t"
: /*out*/
: /*in*/ "r"(&block[0])
- : /*trash*/ "memory", "cc", "t0", "t1", "t2", "t3"
+ : /*trash*/ "memory", "t0", "t1", "t2", "t3"
+ );
+ } while (block[2] != 1);
+#elif defined(VGA_mips64)
+ unsigned long block[3]
+ = { (unsigned long)p, (unsigned long)n, 0x0ULL };
+ do {
+ __asm__ __volatile__(
+ "move $t0, %0" "\n\t"
+ "ld $t1, 0($t0)" "\n\t" // p
+ "ld $t2, 8($t0)" "\n\t" // n
+ "ll $t3, 0($t1)" "\n\t"
+ "addu $t3, $t3, $t2" "\n\t"
+ "sc $t3, 0($t1)" "\n\t"
+ "sd $t3, 16($t0)" "\n\t"
+ : /*out*/
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "memory", "t0", "t1", "t2", "t3"
);
} while (block[2] != 1);
#else
@@ -451,6 +531,23 @@
: "+m" (*p)
: "d" (n)
: "cc", "memory", "0", "1");
+#elif defined(VGA_mips64)
+ unsigned long block[3]
+ = { (unsigned long)p, (unsigned long)n, 0x0ULL };
+ do {
+ __asm__ __volatile__(
+ "move $t0, %0" "\n\t"
+ "ld $t1, 0($t0)" "\n\t" // p
+ "ld $t2, 8($t0)" "\n\t" // n
+ "lld $t3, 0($t1)" "\n\t"
+ "daddu $t3, $t3, $t2" "\n\t"
+ "scd $t3, 0($t1)" "\n\t"
+ "sd $t3, 16($t0)" "\n\t"
+ : /*out*/
+ : /*in*/ "r"(&block[0])
+ : /*trash*/ "memory", "t0", "t1", "t2", "t3"
+ );
+ } while (block[2] != 1);
#else
# error "Unsupported arch"
#endif