Mark Wielaard eee38c2
commit 4b825ef5dcf064fd0f05323e7edd538ce02ac146
Mark Wielaard eee38c2
Author: florian <florian@8f6e269a-dfd6-0310-a8e1-e2731360e62c>
Mark Wielaard eee38c2
Date:   Wed Feb 17 19:57:01 2016 +0000
Mark Wielaard eee38c2
Mark Wielaard eee38c2
    s390: Implement popcnt insn. Part of fixing BZ #359289.
Mark Wielaard eee38c2
    Patch by Andreas Arnez (arnez@linux.vnet.ibm.com)
Mark Wielaard eee38c2
    
Mark Wielaard eee38c2
    
Mark Wielaard eee38c2
    git-svn-id: svn://svn.valgrind.org/vex/trunk@3210 8f6e269a-dfd6-0310-a8e1-e2731360e62c
Mark Wielaard eee38c2
Mark Wielaard eee38c2
diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c
Mark Wielaard eee38c2
index 116a606..5e6acd4 100644
Mark Wielaard eee38c2
--- a/VEX/priv/guest_s390_toIR.c
Mark Wielaard eee38c2
+++ b/VEX/priv/guest_s390_toIR.c
Mark Wielaard eee38c2
@@ -12938,6 +12938,38 @@ s390_irgen_FLOGR(UChar r1, UChar r2)
Mark Wielaard eee38c2
 }
Mark Wielaard eee38c2
 
Mark Wielaard eee38c2
 static const HChar *
Mark Wielaard eee38c2
+s390_irgen_POPCNT(UChar r1, UChar r2)
Mark Wielaard eee38c2
+{
Mark Wielaard eee38c2
+   Int i;
Mark Wielaard eee38c2
+   IRTemp val = newTemp(Ity_I64);
Mark Wielaard eee38c2
+   IRTemp mask[3];
Mark Wielaard eee38c2
+
Mark Wielaard eee38c2
+   assign(val, get_gpr_dw0(r2));
Mark Wielaard eee38c2
+   for (i = 0; i < 3; i++) {
Mark Wielaard eee38c2
+      mask[i] = newTemp(Ity_I64);
Mark Wielaard eee38c2
+   }
Mark Wielaard eee38c2
+   assign(mask[0], mkU64(0x5555555555555555ULL));
Mark Wielaard eee38c2
+   assign(mask[1], mkU64(0x3333333333333333ULL));
Mark Wielaard eee38c2
+   assign(mask[2], mkU64(0x0F0F0F0F0F0F0F0FULL));
Mark Wielaard eee38c2
+   for (i = 0; i < 3; i++) {
Mark Wielaard eee38c2
+      IRTemp tmp = newTemp(Ity_I64);
Mark Wielaard eee38c2
+
Mark Wielaard eee38c2
+      assign(tmp,
Mark Wielaard eee38c2
+             binop(Iop_Add64,
Mark Wielaard eee38c2
+                   binop(Iop_And64,
Mark Wielaard eee38c2
+                         mkexpr(val),
Mark Wielaard eee38c2
+                         mkexpr(mask[i])),
Mark Wielaard eee38c2
+                   binop(Iop_And64,
Mark Wielaard eee38c2
+                         binop(Iop_Shr64, mkexpr(val), mkU8(1 << i)),
Mark Wielaard eee38c2
+                         mkexpr(mask[i]))));
Mark Wielaard eee38c2
+      val = tmp;
Mark Wielaard eee38c2
+   }
Mark Wielaard eee38c2
+   s390_cc_thunk_putZ(S390_CC_OP_BITWISE, val);
Mark Wielaard eee38c2
+   put_gpr_dw0(r1, mkexpr(val));
Mark Wielaard eee38c2
+   return "popcnt";
Mark Wielaard eee38c2
+}
Mark Wielaard eee38c2
+
Mark Wielaard eee38c2
+static const HChar *
Mark Wielaard eee38c2
 s390_irgen_STCK(IRTemp op2addr)
Mark Wielaard eee38c2
 {
Mark Wielaard eee38c2
    IRDirty *d;
Mark Wielaard eee38c2
@@ -14999,7 +15031,8 @@ s390_decode_4byte_and_irgen(const UChar *bytes)
Mark Wielaard eee38c2
                                    ovl.fmt.RRE.r2);  goto ok;
Mark Wielaard eee38c2
    case 0xb9df: s390_format_RRE_RR(s390_irgen_CLHLR, ovl.fmt.RRE.r1,
Mark Wielaard eee38c2
                                    ovl.fmt.RRE.r2);  goto ok;
Mark Wielaard eee38c2
-   case 0xb9e1: /* POPCNT */ goto unimplemented;
Mark Wielaard eee38c2
+   case 0xb9e1: s390_format_RRE_RR(s390_irgen_POPCNT, ovl.fmt.RRE.r1,
Mark Wielaard eee38c2
+                                   ovl.fmt.RRE.r2);  goto ok;
Mark Wielaard eee38c2
    case 0xb9e2: s390_format_RRF_U0RR(s390_irgen_LOCGR, ovl.fmt.RRF3.r3,
Mark Wielaard eee38c2
                                      ovl.fmt.RRF3.r1, ovl.fmt.RRF3.r2,
Mark Wielaard eee38c2
                                      S390_XMNM_LOCGR);  goto ok;