Add testcases for "compare and swap".


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12595 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/configure.in b/configure.in
index 5b46244..13c4a95 100644
--- a/configure.in
+++ b/configure.in
@@ -2196,6 +2196,7 @@
    memcheck/tests/x86-linux/Makefile
    memcheck/tests/ppc32/Makefile
    memcheck/tests/ppc64/Makefile
+   memcheck/tests/s390x/Makefile
    cachegrind/Makefile
    cachegrind/tests/Makefile
    cachegrind/tests/x86/Makefile
diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am
index fa76b5c..530e1f2 100644
--- a/memcheck/tests/Makefile.am
+++ b/memcheck/tests/Makefile.am
@@ -18,6 +18,10 @@
 SUBDIRS += ppc64
 endif
 
+if VGCONF_ARCHS_INCLUDE_S390X
+SUBDIRS += s390x
+endif
+
 # OS-specific tests
 if VGCONF_OS_IS_LINUX
 SUBDIRS += linux
diff --git a/memcheck/tests/s390x/Makefile.am b/memcheck/tests/s390x/Makefile.am
new file mode 100644
index 0000000..4369e5c
--- /dev/null
+++ b/memcheck/tests/s390x/Makefile.am
@@ -0,0 +1,16 @@
+include $(top_srcdir)/Makefile.tool-tests.am
+
+dist_noinst_SCRIPTS = filter_stderr
+
+INSN_TESTS = cs csg
+
+check_PROGRAMS = $(INSN_TESTS) 
+
+EXTRA_DIST = \
+	$(addsuffix .stderr.exp,$(INSN_TESTS)) \
+	$(addsuffix .stdout.exp,$(INSN_TESTS)) \
+	$(addsuffix .vgtest,$(INSN_TESTS))
+
+AM_CFLAGS    += @FLAG_M64@
+AM_CXXFLAGS  += @FLAG_M64@
+AM_CCASFLAGS += @FLAG_M64@
diff --git a/memcheck/tests/s390x/cs.c b/memcheck/tests/s390x/cs.c
new file mode 100644
index 0000000..9a298ce
--- /dev/null
+++ b/memcheck/tests/s390x/cs.c
@@ -0,0 +1,32 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+void 
+test(int32_t op1_init, int32_t op2_init, int32_t op3_init)
+{
+   register int32_t op1 asm("8") = op1_init;
+   register int32_t op3 asm("9") = op3_init;
+   
+   int32_t op2 = op2_init;
+   int cc = 1; 
+
+   __asm__ volatile (
+           "cs      8,9,%1\n\t"
+           "ipm     %0\n\t"
+           "srl     %0,28\n\t"
+           : "=d" (cc), "+Q" (op2), "+d"(op1), "+d"(op3)
+           : 
+           : "cc");
+}
+
+int main ()
+{
+   int op1, op2, op3;
+
+   test(op1, 0x10000000, 0x12345678);   // complaint
+   test(0x10000000, op2, 0x12345678);   // complaint
+   test(0x10000000, 0x01000000, op3);   // no complaint
+
+   return 0;
+}
diff --git a/memcheck/tests/s390x/cs.stderr.exp b/memcheck/tests/s390x/cs.stderr.exp
new file mode 100644
index 0000000..e45dc99
--- /dev/null
+++ b/memcheck/tests/s390x/cs.stderr.exp
@@ -0,0 +1,8 @@
+Conditional jump or move depends on uninitialised value(s)
+   at 0x........: test (cs.c:14)
+   by 0x........: main (cs.c:27)
+
+Conditional jump or move depends on uninitialised value(s)
+   at 0x........: test (cs.c:14)
+   by 0x........: main (cs.c:28)
+
diff --git a/memcheck/tests/s390x/cs.vgtest b/memcheck/tests/s390x/cs.vgtest
new file mode 100644
index 0000000..323cce8
--- /dev/null
+++ b/memcheck/tests/s390x/cs.vgtest
@@ -0,0 +1,2 @@
+prog: cs
+vgopts: -q
diff --git a/memcheck/tests/s390x/csg.c b/memcheck/tests/s390x/csg.c
new file mode 100644
index 0000000..7f9d8c8
--- /dev/null
+++ b/memcheck/tests/s390x/csg.c
@@ -0,0 +1,32 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+void 
+test(int64_t op1_init, int64_t op2_init, int64_t op3_init)
+{
+   register int64_t op1 asm("8") = op1_init;
+   register int64_t op3 asm("9") = op3_init;
+   
+   int64_t op2 = op2_init;
+   int cc = 1; 
+
+   __asm__ volatile (
+           "csg     8,9,%1\n\t"
+           "ipm     %0\n\t"
+           "srl     %0,28\n\t"
+           : "=d" (cc), "+Q" (op2), "+d"(op1), "+d"(op3)
+           : 
+           : "cc");
+}
+
+int main ()
+{
+   int64_t op1, op2, op3;
+
+   test(op1, 0x1000000000000000ull, 0x1234567887654321ull);  // complaint
+   test(0x1000000000000000ull, op2, 0x1234567887654321ull);  // complaint
+   test(0x1000000000000000ull, 0x1000000000000000ull, op3);  // no complaint
+
+   return 0;
+}
diff --git a/memcheck/tests/s390x/csg.stderr.exp b/memcheck/tests/s390x/csg.stderr.exp
new file mode 100644
index 0000000..fda2021
--- /dev/null
+++ b/memcheck/tests/s390x/csg.stderr.exp
@@ -0,0 +1,8 @@
+Conditional jump or move depends on uninitialised value(s)
+   at 0x........: test (csg.c:14)
+   by 0x........: main (csg.c:27)
+
+Conditional jump or move depends on uninitialised value(s)
+   at 0x........: test (csg.c:14)
+   by 0x........: main (csg.c:28)
+
diff --git a/memcheck/tests/s390x/csg.vgtest b/memcheck/tests/s390x/csg.vgtest
new file mode 100644
index 0000000..6de75c1
--- /dev/null
+++ b/memcheck/tests/s390x/csg.vgtest
@@ -0,0 +1,2 @@
+prog: csg
+vgopts: -q
diff --git a/memcheck/tests/s390x/filter_stderr b/memcheck/tests/s390x/filter_stderr
new file mode 100755
index 0000000..a778e97
--- /dev/null
+++ b/memcheck/tests/s390x/filter_stderr
@@ -0,0 +1,3 @@
+#! /bin/sh
+
+../filter_stderr "$@"
diff --git a/none/tests/s390x/Makefile.am b/none/tests/s390x/Makefile.am
index ddb4f4e..b52ee13 100644
--- a/none/tests/s390x/Makefile.am
+++ b/none/tests/s390x/Makefile.am
@@ -6,7 +6,8 @@
              and or xor insert div srst fold_And16 flogr sub_EI add_EI \
              and_EI or_EI xor_EI insert_EI mul_GE add_GE condloadstore \
              op_exception fgx stck stckf stcke stfle cksm mvcl clcl troo \
-             trto trot trtt tr tre cij cgij clij clgij crj cgrj clrj clgrj
+             trto trot trtt tr tre cij cgij clij clgij crj cgrj clrj clgrj \
+             cs csg
 
 check_PROGRAMS = $(INSN_TESTS) \
 		 allexec \
diff --git a/none/tests/s390x/cs.c b/none/tests/s390x/cs.c
new file mode 100644
index 0000000..72b56c2
--- /dev/null
+++ b/none/tests/s390x/cs.c
@@ -0,0 +1,51 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+void 
+test(int32_t op1_init, int32_t op2_init, int32_t op3_init, int expected_cc)
+{
+   register int32_t op1 asm("8") = op1_init;
+   register int32_t op3 asm("9") = op3_init;
+   
+   int32_t op2 = op2_init;
+   int cc = 1; 
+
+   printf("before op1 = %#x\n", op1);
+   printf("before op2 = %#x\n", op2);
+   printf("before op3 = %#x\n", op3);
+
+   __asm__ volatile (
+           "cs      8,9,%1\n\t"
+           "ipm     %0\n\t"
+           "srl     %0,28\n\t"
+           : "=d" (cc), "+Q" (op2), "+d"(op1), "+d"(op3)
+           : 
+           : "cc");
+
+   printf("after  op1 = %#x\n", op1);
+   printf("after  op2 = %#x\n", op2);
+   printf("after  op3 = %#x\n", op3);
+   printf("cc = %d\n", cc);
+
+   if (cc != expected_cc) {
+      printf("condition code is incorrect\n");
+   }
+   if (expected_cc == 0) {
+      if (op2 != op3) {
+         printf("operand #2 not updated\n");
+      }
+   } else {
+      if (op1 != op2) {
+         printf("operand #1 not updated\n");
+      }
+   }
+}
+
+int main ()
+{
+   test(0x10000000, 0x10000000, 0x12345678, 0);
+   test(0x10000000, 0x20000000, 0x12345678, 1);
+
+   return 0;
+}
diff --git a/none/tests/s390x/cs.stderr.exp b/none/tests/s390x/cs.stderr.exp
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/none/tests/s390x/cs.stderr.exp
@@ -0,0 +1,2 @@
+
+
diff --git a/none/tests/s390x/cs.stdout.exp b/none/tests/s390x/cs.stdout.exp
new file mode 100644
index 0000000..803a8b3
--- /dev/null
+++ b/none/tests/s390x/cs.stdout.exp
@@ -0,0 +1,14 @@
+before op1 = 0x10000000
+before op2 = 0x10000000
+before op3 = 0x12345678
+after  op1 = 0x10000000
+after  op2 = 0x12345678
+after  op3 = 0x12345678
+cc = 0
+before op1 = 0x10000000
+before op2 = 0x20000000
+before op3 = 0x12345678
+after  op1 = 0x20000000
+after  op2 = 0x20000000
+after  op3 = 0x12345678
+cc = 1
diff --git a/none/tests/s390x/cs.vgtest b/none/tests/s390x/cs.vgtest
new file mode 100644
index 0000000..9d9bdd9
--- /dev/null
+++ b/none/tests/s390x/cs.vgtest
@@ -0,0 +1 @@
+prog: cs
diff --git a/none/tests/s390x/csg.c b/none/tests/s390x/csg.c
new file mode 100644
index 0000000..1a5e8ff
--- /dev/null
+++ b/none/tests/s390x/csg.c
@@ -0,0 +1,51 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+void 
+test(int64_t op1_init, int64_t op2_init, int64_t op3_init, int expected_cc)
+{
+   register int64_t op1 asm("8") = op1_init;
+   register int64_t op3 asm("9") = op3_init;
+   
+   int64_t op2 = op2_init;
+   int cc = 1; 
+
+   printf("before op1 = %#lx\n", op1);
+   printf("before op2 = %#lx\n", op2);
+   printf("before op3 = %#lx\n", op3);
+
+   __asm__ volatile (
+           "csg     8,9,%1\n\t"
+           "ipm     %0\n\t"
+           "srl     %0,28\n\t"
+           : "=d" (cc), "+Q" (op2), "+d"(op1), "+d"(op3)
+           : 
+           : "cc");
+
+   printf("after  op1 = %#lx\n", op1);
+   printf("after  op2 = %#lx\n", op2);
+   printf("after  op3 = %#lx\n", op3);
+   printf("cc = %d\n", cc);
+
+   if (cc != expected_cc) {
+      printf("condition code is incorrect\n");
+   }
+   if (expected_cc == 0) {
+      if (op2 != op3) {
+         printf("operand #2 not updated\n");
+      }
+   } else {
+      if (op1 != op2) {
+         printf("operand #1 not updated\n");
+      }
+   }
+}
+
+int main ()
+{
+   test(0x1000000000000000ull, 0x1000000000000000ull, 0x1234567887654321ull, 0);
+   test(0x1000000000000000ull, 0x2000000000000000ull, 0x1234567887654321ull, 1);
+
+   return 0;
+}
diff --git a/none/tests/s390x/csg.stderr.exp b/none/tests/s390x/csg.stderr.exp
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/none/tests/s390x/csg.stderr.exp
@@ -0,0 +1,2 @@
+
+
diff --git a/none/tests/s390x/csg.stdout.exp b/none/tests/s390x/csg.stdout.exp
new file mode 100644
index 0000000..1258ece
--- /dev/null
+++ b/none/tests/s390x/csg.stdout.exp
@@ -0,0 +1,14 @@
+before op1 = 0x1000000000000000
+before op2 = 0x1000000000000000
+before op3 = 0x1234567887654321
+after  op1 = 0x1000000000000000
+after  op2 = 0x1234567887654321
+after  op3 = 0x1234567887654321
+cc = 0
+before op1 = 0x1000000000000000
+before op2 = 0x2000000000000000
+before op3 = 0x1234567887654321
+after  op1 = 0x2000000000000000
+after  op2 = 0x2000000000000000
+after  op3 = 0x1234567887654321
+cc = 1
diff --git a/none/tests/s390x/csg.vgtest b/none/tests/s390x/csg.vgtest
new file mode 100644
index 0000000..c765a1b
--- /dev/null
+++ b/none/tests/s390x/csg.vgtest
@@ -0,0 +1 @@
+prog: csg