------------------------------------------------------------------------
r15792 | florian | 2016-02-17 21:00:59 +0100 (Mi, 17. Feb 2016) | 4 Zeilen

s390: Fix BZ #359289, adding support for popcnt insn.
Companion patch is VEX r3210.
Patch by Andreas Arnez (arnez@linux.vnet.ibm.com).

------------------------------------------------------------------------
Index: tests/s390x_features.c
===================================================================
--- tests/s390x_features.c.orig
+++ tests/s390x_features.c
@@ -231,6 +231,8 @@ static int go(char *feature, char *cpu)
       match = facilities & FAC_BIT(42);
    } else if (strcmp(feature, "s390x-pfpo") == 0 ) {
       match = facilities & FAC_BIT(44);
+   } else if (strcmp(feature, "s390x-highw") == 0 ) {
+      match = facilities & FAC_BIT(45);
    } else {
       return 2;          // Unrecognised feature.
    }
Index: none/tests/s390x/popcnt.stderr.exp
===================================================================
--- /dev/null
+++ none/tests/s390x/popcnt.stderr.exp
@@ -0,0 +1,2 @@
+
+
Index: none/tests/s390x/Makefile.am
===================================================================
--- none/tests/s390x/Makefile.am.orig
+++ none/tests/s390x/Makefile.am
@@ -11,7 +11,7 @@ INSN_TESTS = clc clcle cvb cvd icm lpr t
              ex_sig ex_clone cu14 cu14_1 cu41 fpconv ecag fpext_warn \
              rounding-1 rounding-2 rounding-3 rounding-4 rounding-5 bfp-1 \
              bfp-2 bfp-3 bfp-4 srnm srnmb comp-1 comp-2 exrl tmll tm stmg \
-	     ex clst mvc test_fork test_sig rounding-6 rxsbg\
+	     ex clst mvc test_fork test_sig rounding-6 rxsbg popcnt \
 	     spechelper-alr spechelper-algr \
 	     spechelper-slr spechelper-slgr \
 	     spechelper-cr  spechelper-clr  \
Index: none/tests/s390x/opcodes.h
===================================================================
--- none/tests/s390x/opcodes.h.orig
+++ none/tests/s390x/opcodes.h
@@ -324,6 +324,7 @@
 #define OY(r1,x2,b2,dl2,dh2)            RXY_RRRD(e3,r1,x2,b2,dl2,dh2,56)
 #define PFD(r1,x2,b2,dl2,dh2)           RXY_URRD(e3,r1,x2,b2,dl2,dh2,36)
 #define PFDRL(r1,i2)                    RIL_UP(c6,r1,2,i2)
+#define POPCNT(r1,r2)                   RRE_RR(b9e1,00,r1,r2)
 #define RISBG(r1,r2,i3,i4,i5)           RIE_RRUUU(ec,r1,r2,i3,i4,i5,55)
 #define RNSBG(r1,r2,i3,i4,i5)           RIE_RRUUU(ec,r1,r2,i3,i4,i5,54)
 #define ROSBG(r1,r2,i3,i4,i5)           RIE_RRUUU(ec,r1,r2,i3,i4,i5,56)
Index: none/tests/s390x/popcnt.stdout.exp
===================================================================
--- /dev/null
+++ none/tests/s390x/popcnt.stdout.exp
@@ -0,0 +1,5 @@
+popcnt                0 ->                0      cc=0    
+popcnt                1 ->                1      cc=1    
+popcnt 8000000000000000 ->  100000000000000      cc=1    
+popcnt ffffffffffffffff ->  808080808080808      cc=1    
+popcnt ff427e3800556bcd ->  802060300040505      cc=1    
Index: none/tests/s390x/popcnt.vgtest
===================================================================
--- /dev/null
+++ none/tests/s390x/popcnt.vgtest
@@ -0,0 +1 @@
+prog: popcnt
Index: none/tests/s390x/popcnt.c
===================================================================
--- /dev/null
+++ none/tests/s390x/popcnt.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <stdint.h>
+
+
+static void check_popcnt(uint64_t in, uint64_t expected_result,
+                         int expected_cc)
+{
+   uint64_t out = ~expected_result;
+   int cc = ~expected_cc;
+
+   asm volatile(".insn rre, 0xb9e10000, %[out], %[in]\n\t"
+                "ipm     %[cc]\n\t"
+                "srl     %[cc],28\n\t"
+                : [cc]"=d" (cc), [out]"=d" (out)
+                : [in]"d" (in)
+                : "cc");
+   printf("popcnt %16lx -> %16lx %s  cc=%d %s\n",
+          in, out, (out == expected_result ? "   " : "ERR"),
+          cc, (cc == expected_cc ? "   " : "ERR"));
+}
+
+int main()
+{
+   check_popcnt(0, 0, 0);
+   check_popcnt(1, 1, 1);
+   check_popcnt(0x8000000000000000ULL, 0x0100000000000000ULL, 1);
+   check_popcnt(0xffffffffffffffffULL, 0x0808080808080808ULL, 1);
+   check_popcnt(0xff427e3800556bcdULL, 0x0802060300040505ULL, 1);
+   return 0;
+}
