Add NC and OC to the list of insns that get special treatment under EX.
Refactored code such that s390_irgen_xonc can be reused thereby avoiding
code duplication.


git-svn-id: svn://svn.valgrind.org/vex/trunk@2320 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/guest_s390_toIR.c b/priv/guest_s390_toIR.c
index fd54316..a741c64 100644
--- a/priv/guest_s390_toIR.c
+++ b/priv/guest_s390_toIR.c
@@ -48,6 +48,7 @@
 /*--- Forward declarations                                 ---*/
 /*------------------------------------------------------------*/
 static UInt s390_decode_and_irgen(UChar *, UInt, DisResult *);
+static void s390_irgen_xonc(IROp, IRTemp, IRTemp, IRTemp);
 
 
 /*------------------------------------------------------------*/
@@ -8784,38 +8785,25 @@
    return "clcle";
 }
 
+
 static void
 s390_irgen_XC_EX(IRTemp length, IRTemp start1, IRTemp start2)
 {
-   IRTemp old1 = newTemp(Ity_I8);
-   IRTemp old2 = newTemp(Ity_I8);
-   IRTemp new1 = newTemp(Ity_I8);
-   IRTemp counter = newTemp(Ity_I32);
-   IRTemp addr1 = newTemp(Ity_I64);
+   s390_irgen_xonc(Iop_Xor8, length, start1, start2);
+}
 
-   assign(counter, get_counter_w0());
 
-   assign(addr1, binop(Iop_Add64, mkexpr(start1),
-                       unop(Iop_32Uto64, mkexpr(counter))));
+static void
+s390_irgen_NC_EX(IRTemp length, IRTemp start1, IRTemp start2)
+{
+   s390_irgen_xonc(Iop_And8, length, start1, start2);
+}
 
-   assign(old1, load(Ity_I8, mkexpr(addr1)));
-   assign(old2, load(Ity_I8, binop(Iop_Add64, mkexpr(start2),
-                                   unop(Iop_32Uto64,mkexpr(counter)))));
-   assign(new1, binop(Iop_Xor8, mkexpr(old1), mkexpr(old2)));
 
-   store(mkexpr(addr1),
-         mkite(binop(Iop_CmpEQ64, mkexpr(start1), mkexpr(start2)),
-               mkU8(0), mkexpr(new1)));
-   put_counter_w1(binop(Iop_Or32, unop(Iop_8Uto32, mkexpr(new1)),
-                        get_counter_w1()));
-
-   /* Check for end of field */
-   put_counter_w0(binop(Iop_Add32, mkexpr(counter), mkU32(1)));
-   if_condition_goto(binop(Iop_CmpNE32, mkexpr(counter), mkexpr(length)),
-                     guest_IA_curr_instr);
-   s390_cc_thunk_put1(S390_CC_OP_BITWISE, mktemp(Ity_I32, get_counter_w1()),
-                      False);
-   put_counter_dw0(mkU64(0));
+static void
+s390_irgen_OC_EX(IRTemp length, IRTemp start1, IRTemp start2)
+{
+   s390_irgen_xonc(Iop_Or8, length, start1, start2);
 }
 
 
@@ -8963,6 +8951,15 @@
       s390_irgen_EX_SS(r1, addr2, s390_irgen_XC_EX, 32);
       return "xc via ex";
 
+   case 0xd600000000000000ULL:
+      /* special case OC */
+      s390_irgen_EX_SS(r1, addr2, s390_irgen_OC_EX, 32);
+      return "oc via ex";
+
+   case 0xd400000000000000ULL:
+      /* special case NC */
+      s390_irgen_EX_SS(r1, addr2, s390_irgen_NC_EX, 32);
+      return "nc via ex";
 
    default:
    {
@@ -9308,7 +9305,7 @@
 }
 
 static void
-s390_irgen_xonc(IROp op, UChar length, IRTemp start1, IRTemp start2)
+s390_irgen_xonc(IROp op, IRTemp length, IRTemp start1, IRTemp start2)
 {
    IRTemp old1 = newTemp(Ity_I8);
    IRTemp old2 = newTemp(Ity_I8);
@@ -9338,7 +9335,7 @@
 
    /* Check for end of field */
    put_counter_w0(binop(Iop_Add32, mkexpr(counter), mkU32(1)));
-   if_condition_goto(binop(Iop_CmpNE32, mkexpr(counter), mkU32(length)),
+   if_condition_goto(binop(Iop_CmpNE32, mkexpr(counter), mkexpr(length)),
                      guest_IA_curr_instr);
    s390_cc_thunk_put1(S390_CC_OP_BITWISE, mktemp(Ity_I32, get_counter_w1()),
                       False);
@@ -9349,7 +9346,10 @@
 static HChar *
 s390_irgen_XC(UChar length, IRTemp start1, IRTemp start2)
 {
-   s390_irgen_xonc(Iop_Xor8, length, start1, start2);
+   IRTemp len = newTemp(Ity_I32);
+
+   assign(len, mkU32(length));
+   s390_irgen_xonc(Iop_Xor8, len, start1, start2);
 
    return "xc";
 }
@@ -9397,7 +9397,10 @@
 static HChar *
 s390_irgen_NC(UChar length, IRTemp start1, IRTemp start2)
 {
-   s390_irgen_xonc(Iop_And8, length, start1, start2);
+   IRTemp len = newTemp(Ity_I32);
+
+   assign(len, mkU32(length));
+   s390_irgen_xonc(Iop_And8, len, start1, start2);
 
    return "nc";
 }
@@ -9405,7 +9408,10 @@
 static HChar *
 s390_irgen_OC(UChar length, IRTemp start1, IRTemp start2)
 {
-   s390_irgen_xonc(Iop_Or8, length, start1, start2);
+   IRTemp len = newTemp(Ity_I32);
+
+   assign(len, mkU32(length));
+   s390_irgen_xonc(Iop_Or8, len, start1, start2);
 
    return "oc";
 }