Refactor the code based on s390_irgen_LAA.
New functions: s390_irgen_load_and_add32/64 and 
s390_irgen_load_and_bitwise32/64.

Part of fixing BZ #306035.


git-svn-id: svn://svn.valgrind.org/vex/trunk@2577 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/guest_s390_toIR.c b/priv/guest_s390_toIR.c
index 566ad88..68b108f 100644
--- a/priv/guest_s390_toIR.c
+++ b/priv/guest_s390_toIR.c
@@ -5430,8 +5430,8 @@
    constructed which will iterate until the CAS succeeds. As a consequence,
    instrumenters may see more memory accesses than happen natively. See also
    discussion here: https://bugs.kde.org/show_bug.cgi?id=306035 */
-static const HChar *
-s390_irgen_LAA(UChar r1, UChar r3, IRTemp op2addr)
+static void
+s390_irgen_load_and_add32(UChar r1, UChar r3, IRTemp op2addr, Bool is_signed)
 {
    IRCAS *cas;
    IRTemp old_mem = newTemp(Ity_I32);
@@ -5451,13 +5451,117 @@
                  NULL, mkexpr(result)  /* new value */);
    stmt(IRStmt_CAS(cas));
 
-   /* Set CC according to 32-bit signed addition */
-   s390_cc_thunk_putSS(S390_CC_OP_SIGNED_ADD_32, op2, op3);
+   /* Set CC according to 32-bit addition */
+   if (is_signed) {
+      s390_cc_thunk_putSS(S390_CC_OP_SIGNED_ADD_32, op2, op3);
+   } else {
+      s390_cc_thunk_putZZ(S390_CC_OP_UNSIGNED_ADD_32, op2, op3);
+   }
 
    /* If old_mem contains the expected value, then the CAS succeeded.
       Otherwise, it did not */
    yield_if(binop(Iop_CmpNE32, mkexpr(old_mem), mkexpr(op2)));
    put_gpr_w1(r1, mkexpr(old_mem));
+}
+
+static void
+s390_irgen_load_and_add64(UChar r1, UChar r3, IRTemp op2addr, Bool is_signed)
+{
+   IRCAS *cas;
+   IRTemp old_mem = newTemp(Ity_I64);
+   IRTemp op2 = newTemp(Ity_I64);
+   IRTemp op3 = newTemp(Ity_I64);
+   IRTemp result = newTemp(Ity_I64);
+
+   assign(op2, load(Ity_I64, mkexpr(op2addr)));
+   assign(op3, get_gpr_dw0(r3));
+   assign(result, binop(Iop_Add64, mkexpr(op2), mkexpr(op3)));
+
+   /* Place the addition of second operand and third operand at the
+      second-operand location everytime */
+   cas = mkIRCAS(IRTemp_INVALID, old_mem,
+                 Iend_BE, mkexpr(op2addr),
+                 NULL, mkexpr(op2), /* expected value */
+                 NULL, mkexpr(result)  /* new value */);
+   stmt(IRStmt_CAS(cas));
+
+   /* Set CC according to 64-bit addition */
+   if (is_signed) {
+      s390_cc_thunk_putSS(S390_CC_OP_SIGNED_ADD_64, op2, op3);
+   } else {
+      s390_cc_thunk_putZZ(S390_CC_OP_UNSIGNED_ADD_64, op2, op3);
+   }
+
+   /* If old_mem contains the expected value, then the CAS succeeded.
+      Otherwise, it did not */
+   yield_if(binop(Iop_CmpNE64, mkexpr(old_mem), mkexpr(op2)));
+   put_gpr_dw0(r1, mkexpr(old_mem));
+}
+
+static void
+s390_irgen_load_and_bitwise32(UChar r1, UChar r3, IRTemp op2addr, IROp op)
+{
+   IRCAS *cas;
+   IRTemp old_mem = newTemp(Ity_I32);
+   IRTemp op2 = newTemp(Ity_I32);
+   IRTemp op3 = newTemp(Ity_I32);
+   IRTemp result = newTemp(Ity_I32);
+
+   assign(op2, load(Ity_I32, mkexpr(op2addr)));
+   assign(op3, get_gpr_w1(r3));
+   assign(result, binop(op, mkexpr(op2), mkexpr(op3)));
+
+   /* Place the addition of second operand and third operand at the
+      second-operand location everytime */
+   cas = mkIRCAS(IRTemp_INVALID, old_mem,
+                 Iend_BE, mkexpr(op2addr),
+                 NULL, mkexpr(op2), /* expected value */
+                 NULL, mkexpr(result)  /* new value */);
+   stmt(IRStmt_CAS(cas));
+
+   /* Set CC according to bitwise operation */
+   s390_cc_thunk_putZ(S390_CC_OP_BITWISE, result);
+
+   /* If old_mem contains the expected value, then the CAS succeeded.
+      Otherwise, it did not */
+   yield_if(binop(Iop_CmpNE32, mkexpr(old_mem), mkexpr(op2)));
+   put_gpr_w1(r1, mkexpr(old_mem));
+}
+
+static void
+s390_irgen_load_and_bitwise64(UChar r1, UChar r3, IRTemp op2addr, IROp op)
+{
+   IRCAS *cas;
+   IRTemp old_mem = newTemp(Ity_I64);
+   IRTemp op2 = newTemp(Ity_I64);
+   IRTemp op3 = newTemp(Ity_I64);
+   IRTemp result = newTemp(Ity_I64);
+
+   assign(op2, load(Ity_I64, mkexpr(op2addr)));
+   assign(op3, get_gpr_dw0(r3));
+   assign(result, binop(op, mkexpr(op2), mkexpr(op3)));
+
+   /* Place the addition of second operand and third operand at the
+      second-operand location everytime */
+   cas = mkIRCAS(IRTemp_INVALID, old_mem,
+                 Iend_BE, mkexpr(op2addr),
+                 NULL, mkexpr(op2), /* expected value */
+                 NULL, mkexpr(result)  /* new value */);
+   stmt(IRStmt_CAS(cas));
+
+   /* Set CC according to bitwise operation */
+   s390_cc_thunk_putZ(S390_CC_OP_BITWISE, result);
+
+   /* If old_mem contains the expected value, then the CAS succeeded.
+      Otherwise, it did not */
+   yield_if(binop(Iop_CmpNE64, mkexpr(old_mem), mkexpr(op2)));
+   put_gpr_dw0(r1, mkexpr(old_mem));
+}
+
+static const HChar *
+s390_irgen_LAA(UChar r1, UChar r3, IRTemp op2addr)
+{
+   s390_irgen_load_and_add32(r1, r3, op2addr, True /* is_signed */);
 
    return "laa";
 }
@@ -5465,16 +5569,7 @@
 static const HChar *
 s390_irgen_LAAG(UChar r1, UChar r3, IRTemp op2addr)
 {
-   IRTemp op2 = newTemp(Ity_I64);
-   IRTemp op3 = newTemp(Ity_I64);
-   IRTemp result = newTemp(Ity_I64);
-
-   assign(op2, load(Ity_I64, mkexpr(op2addr)));
-   assign(op3, get_gpr_dw0(r3));
-   assign(result, binop(Iop_Add64, mkexpr(op2), mkexpr(op3)));
-   s390_cc_thunk_putSS(S390_CC_OP_SIGNED_ADD_64, op2, op3);
-   store(mkexpr(op2addr), mkexpr(result));
-   put_gpr_dw0(r1, mkexpr(op2));
+   s390_irgen_load_and_add64(r1, r3, op2addr, True /* is_signed */);
 
    return "laag";
 }
@@ -5482,16 +5577,7 @@
 static const HChar *
 s390_irgen_LAAL(UChar r1, UChar r3, IRTemp op2addr)
 {
-   IRTemp op2 = newTemp(Ity_I32);
-   IRTemp op3 = newTemp(Ity_I32);
-   IRTemp result = newTemp(Ity_I32);
-
-   assign(op2, load(Ity_I32, mkexpr(op2addr)));
-   assign(op3, get_gpr_w1(r3));
-   assign(result, binop(Iop_Add32, mkexpr(op2), mkexpr(op3)));
-   s390_cc_thunk_putZZ(S390_CC_OP_UNSIGNED_ADD_32, op2, op3);
-   store(mkexpr(op2addr), mkexpr(result));
-   put_gpr_w1(r1, mkexpr(op2));
+   s390_irgen_load_and_add32(r1, r3, op2addr, False /* is_signed */);
 
    return "laal";
 }
@@ -5499,16 +5585,7 @@
 static const HChar *
 s390_irgen_LAALG(UChar r1, UChar r3, IRTemp op2addr)
 {
-   IRTemp op2 = newTemp(Ity_I64);
-   IRTemp op3 = newTemp(Ity_I64);
-   IRTemp result = newTemp(Ity_I64);
-
-   assign(op2, load(Ity_I64, mkexpr(op2addr)));
-   assign(op3, get_gpr_dw0(r3));
-   assign(result, binop(Iop_Add64, mkexpr(op2), mkexpr(op3)));
-   s390_cc_thunk_putZZ(S390_CC_OP_UNSIGNED_ADD_64, op2, op3);
-   store(mkexpr(op2addr), mkexpr(result));
-   put_gpr_dw0(r1, mkexpr(op2));
+   s390_irgen_load_and_add64(r1, r3, op2addr, False /* is_signed */);
 
    return "laalg";
 }
@@ -5516,16 +5593,7 @@
 static const HChar *
 s390_irgen_LAN(UChar r1, UChar r3, IRTemp op2addr)
 {
-   IRTemp op2 = newTemp(Ity_I32);
-   IRTemp op3 = newTemp(Ity_I32);
-   IRTemp result = newTemp(Ity_I32);
-
-   assign(op2, load(Ity_I32, mkexpr(op2addr)));
-   assign(op3, get_gpr_w1(r3));
-   assign(result, binop(Iop_And32, mkexpr(op2), mkexpr(op3)));
-   s390_cc_thunk_putZ(S390_CC_OP_BITWISE, result);
-   store(mkexpr(op2addr), mkexpr(result));
-   put_gpr_w1(r1, mkexpr(op2));
+   s390_irgen_load_and_bitwise32(r1, r3, op2addr, Iop_And32);
 
    return "lan";
 }
@@ -5533,16 +5601,7 @@
 static const HChar *
 s390_irgen_LANG(UChar r1, UChar r3, IRTemp op2addr)
 {
-   IRTemp op2 = newTemp(Ity_I64);
-   IRTemp op3 = newTemp(Ity_I64);
-   IRTemp result = newTemp(Ity_I64);
-
-   assign(op2, load(Ity_I64, mkexpr(op2addr)));
-   assign(op3, get_gpr_dw0(r3));
-   assign(result, binop(Iop_And64, mkexpr(op2), mkexpr(op3)));
-   s390_cc_thunk_putZ(S390_CC_OP_BITWISE, result);
-   store(mkexpr(op2addr), mkexpr(result));
-   put_gpr_dw0(r1, mkexpr(op2));
+   s390_irgen_load_and_bitwise64(r1, r3, op2addr, Iop_And64);
 
    return "lang";
 }
@@ -5550,16 +5609,7 @@
 static const HChar *
 s390_irgen_LAX(UChar r1, UChar r3, IRTemp op2addr)
 {
-   IRTemp op2 = newTemp(Ity_I32);
-   IRTemp op3 = newTemp(Ity_I32);
-   IRTemp result = newTemp(Ity_I32);
-
-   assign(op2, load(Ity_I32, mkexpr(op2addr)));
-   assign(op3, get_gpr_w1(r3));
-   assign(result, binop(Iop_Xor32, mkexpr(op2), mkexpr(op3)));
-   s390_cc_thunk_putZ(S390_CC_OP_BITWISE, result);
-   store(mkexpr(op2addr), mkexpr(result));
-   put_gpr_w1(r1, mkexpr(op2));
+   s390_irgen_load_and_bitwise32(r1, r3, op2addr, Iop_Xor32);
 
    return "lax";
 }
@@ -5567,16 +5617,7 @@
 static const HChar *
 s390_irgen_LAXG(UChar r1, UChar r3, IRTemp op2addr)
 {
-   IRTemp op2 = newTemp(Ity_I64);
-   IRTemp op3 = newTemp(Ity_I64);
-   IRTemp result = newTemp(Ity_I64);
-
-   assign(op2, load(Ity_I64, mkexpr(op2addr)));
-   assign(op3, get_gpr_dw0(r3));
-   assign(result, binop(Iop_Xor64, mkexpr(op2), mkexpr(op3)));
-   s390_cc_thunk_putZ(S390_CC_OP_BITWISE, result);
-   store(mkexpr(op2addr), mkexpr(result));
-   put_gpr_dw0(r1, mkexpr(op2));
+   s390_irgen_load_and_bitwise64(r1, r3, op2addr, Iop_Xor64);
 
    return "laxg";
 }
@@ -5584,16 +5625,7 @@
 static const HChar *
 s390_irgen_LAO(UChar r1, UChar r3, IRTemp op2addr)
 {
-   IRTemp op2 = newTemp(Ity_I32);
-   IRTemp op3 = newTemp(Ity_I32);
-   IRTemp result = newTemp(Ity_I32);
-
-   assign(op2, load(Ity_I32, mkexpr(op2addr)));
-   assign(op3, get_gpr_w1(r3));
-   assign(result, binop(Iop_Or32, mkexpr(op2), mkexpr(op3)));
-   s390_cc_thunk_putZ(S390_CC_OP_BITWISE, result);
-   store(mkexpr(op2addr), mkexpr(result));
-   put_gpr_w1(r1, mkexpr(op2));
+   s390_irgen_load_and_bitwise32(r1, r3, op2addr, Iop_Or32);
 
    return "lao";
 }
@@ -5601,16 +5633,7 @@
 static const HChar *
 s390_irgen_LAOG(UChar r1, UChar r3, IRTemp op2addr)
 {
-   IRTemp op2 = newTemp(Ity_I64);
-   IRTemp op3 = newTemp(Ity_I64);
-   IRTemp result = newTemp(Ity_I64);
-
-   assign(op2, load(Ity_I64, mkexpr(op2addr)));
-   assign(op3, get_gpr_dw0(r3));
-   assign(result, binop(Iop_Or64, mkexpr(op2), mkexpr(op3)));
-   s390_cc_thunk_putZ(S390_CC_OP_BITWISE, result);
-   store(mkexpr(op2addr), mkexpr(result));
-   put_gpr_dw0(r1, mkexpr(op2));
+   s390_irgen_load_and_bitwise64(r1, r3, op2addr, Iop_Or64);
 
    return "laog";
 }