Test improvements for FLOGR.  Part of #268715.
(Florian Krohm, britzel@acm.org)


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11662 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/none/tests/s390x/flogr.c b/none/tests/s390x/flogr.c
index 63ed036..f3631e5 100644
--- a/none/tests/s390x/flogr.c
+++ b/none/tests/s390x/flogr.c
@@ -1,15 +1,25 @@
 #include <stdio.h>
 
+/* The FLOGR insn reads from register R2 and writes to register R1 and
+   R1 + 1. So we need to distinguish three cases:
+
+   (1) All three registers R1, R1 + 1, and R2 are distinct
+   (2) R2 == R1
+   (3) R2 == R1 + 1
+
+   These are tested by flogr1, flogr2, and flogr3, respectively. */
 
 /* Call FLOGR on INPUT. The results are returned through the parms. */
+
+/* R2 != R1 && R2 != R1 + 1 */
 void
-flogr(unsigned long input, unsigned long *bitpos, unsigned long *modval,
-      unsigned int *cc)
+flogr1(unsigned long input, unsigned long *bitpos, unsigned long *modval,
+       unsigned int *cc)
 {
    unsigned int psw;
    register unsigned long value asm("4") = input;
 
-   asm volatile ( "flogr 2, %[val]\n\t"
+   asm volatile ( ".long 0xB9830024\n\t" // "flogr 2, %[val]\n\t"
                   "ipm   %[psw]\n\t"
                   "stg   2, %[bitpos]\n\t"
                   "stg   3, %[modval]\n\t"
@@ -25,8 +35,57 @@
 #endif
 }
 
+/* R2 == R1 */
 void
-runtest(void)
+flogr2(unsigned long input, unsigned long *bitpos, unsigned long *modval,
+       unsigned int *cc)
+{
+   unsigned int psw;
+   register unsigned long value asm("2") = input;
+
+   asm volatile ( ".long 0xB9830022\n\t" // "flogr 2, %[val]\n\t"
+                  "ipm   %[psw]\n\t"
+                  "stg   2, %[bitpos]\n\t"
+                  "stg   3, %[modval]\n\t"
+                  : [bitpos]"=m"(*bitpos), [modval]"=m"(*modval),
+                    [psw]"=d"(psw), [val] "+d"(value)
+                  :
+                  : "3", "cc");
+
+   *cc = psw >> 28;
+#if 0
+   printf("value = %lx,  bitpos = %lu,  modval = %lx,  cc = %d\n",
+          value, *bitpos, *modval, *cc);
+#endif
+}
+
+/* R2 == R1 + 1 */
+void
+flogr3(unsigned long input, unsigned long *bitpos, unsigned long *modval,
+       unsigned int *cc)
+{
+   unsigned int psw;
+   register unsigned long value asm("3") = input;
+
+   asm volatile ( ".long 0xB9830023\n\t" // "flogr 2, %[val]\n\t"
+                  "ipm   %[psw]\n\t"
+                  "stg   2, %[bitpos]\n\t"
+                  "stg   3, %[modval]\n\t"
+                  : [bitpos]"=m"(*bitpos), [modval]"=m"(*modval),
+                    [psw]"=d"(psw), [val] "+d"(value)
+                  :
+                  : "2", "cc");
+
+   *cc = psw >> 28;
+#if 0
+   printf("value = %lx,  bitpos = %lu,  modval = %lx,  cc = %d\n",
+          value, *bitpos, *modval, *cc);
+#endif
+}
+
+void
+runtest(void (*func)(unsigned long, unsigned long *, unsigned long *,
+                     unsigned int *))
 {
    unsigned long bitpos, modval, value;
    unsigned int cc;
@@ -34,7 +93,7 @@
 
    /* Value 0 is special */
    value = 0;
-   flogr(value, &bitpos, &modval, &cc);
+   func(value, &bitpos, &modval, &cc);
    if (modval != 0)  fprintf(stderr, "modval is wrong for %lx\n", value);
    if (bitpos != 64) fprintf(stderr, "bitpos is wrong for %lx\n", value);
    if (cc != 0)      fprintf(stderr, "cc is wrong for %lx\n", value);
@@ -42,7 +101,7 @@
    /* Test with exactly 1 bit set */
    for (i = 0; i < 64; ++i) {
      value = 1ull << i;
-     flogr(value, &bitpos, &modval, &cc);
+     func(value, &bitpos, &modval, &cc);
      if (modval != 0) fprintf(stderr, "modval is wrong for %lx\n", value);
      if (bitpos != 63 - i) fprintf(stderr, "bitpos is wrong for %lx\n", value);
      if (cc != 2)          fprintf(stderr, "cc is wrong for %lx\n", value);
@@ -52,7 +111,7 @@
    for (i = 1; i < 64; ++i) {
      value = 1ull << i;
      value = value | (value - 1);
-     flogr(value, &bitpos, &modval, &cc);
+     func(value, &bitpos, &modval, &cc);
      if (modval != (value >> 1)) fprintf(stderr, "modval is wrong for %lx\n", value);
      if (bitpos != 63 - i) fprintf(stderr, "bitpos is wrong for %lx\n", value);
      if (cc != 2)          fprintf(stderr, "cc is wrong for %lx\n", value);
@@ -62,7 +121,9 @@
 
 int main()
 {
-   runtest();
+   runtest(flogr1);
+   runtest(flogr2);
+   runtest(flogr3);
 
    return 0;
 }