Implement TR, TRE, TRTT, TROT, TRTO insns.
These are the VEX bits for fixing #273114. 
Patch by Divya Vyas (divyvyas@linux.vnet.ibm.com).


git-svn-id: svn://svn.valgrind.org/vex/trunk@2245 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/guest_s390_toIR.c b/priv/guest_s390_toIR.c
index e7b64b4..7319781 100644
--- a/priv/guest_s390_toIR.c
+++ b/priv/guest_s390_toIR.c
@@ -10894,6 +10894,225 @@
    return "troo";
 }
 
+static HChar *
+s390_irgen_TRTO(UChar m3, UChar r1, UChar r2)
+{
+   IRTemp src_addr, des_addr, tab_addr, src_len, test_byte;
+   src_addr = newTemp(Ity_I64);
+   des_addr = newTemp(Ity_I64);
+   tab_addr = newTemp(Ity_I64);
+   test_byte = newTemp(Ity_I8);
+   src_len = newTemp(Ity_I64);
+
+   assign(src_addr, get_gpr_dw0(r2));
+   assign(des_addr, get_gpr_dw0(r1));
+   assign(tab_addr, get_gpr_dw0(1));
+   assign(src_len, get_gpr_dw0(r1+1));
+   assign(test_byte, get_gpr_b7(0));
+
+   IRTemp op = newTemp(Ity_I16);
+   IRTemp op1 = newTemp(Ity_I8);
+   IRTemp result = newTemp(Ity_I64);
+
+   /* End of source string? We're done; proceed to next insn */
+   s390_cc_set(0);
+   if_condition_goto(binop(Iop_CmpEQ64, mkexpr(src_len), mkU64(0)),
+                     guest_IA_next_instr);
+
+   /* Load character from source string, index translation table and
+      store translated character in op1. */
+   assign(op, load(Ity_I16, mkexpr(src_addr)));
+
+   assign(result, binop(Iop_Add64, unop(Iop_16Uto64, mkexpr(op)),
+                        mkexpr(tab_addr)));
+
+   assign(op1, load(Ity_I8, mkexpr(result)));
+
+   if (! s390_host_has_etf2 || (m3 & 0x1) == 0) {
+      s390_cc_set(1);
+      if_condition_goto(binop(Iop_CmpEQ8, mkexpr(op1), mkexpr(test_byte)),
+                        guest_IA_next_instr);
+   }
+   store(get_gpr_dw0(r1), mkexpr(op1));
+
+   put_gpr_dw0(r2, binop(Iop_Add64, mkexpr(src_addr), mkU64(2)));
+   put_gpr_dw0(r1, binop(Iop_Add64, mkexpr(des_addr), mkU64(1)));
+   put_gpr_dw0(r1+1, binop(Iop_Sub64, mkexpr(src_len), mkU64(2)));
+
+   always_goto_and_chase(guest_IA_curr_instr);
+
+   return "trto";
+}
+
+static HChar *
+s390_irgen_TROT(UChar m3, UChar r1, UChar r2)
+{
+   IRTemp src_addr, des_addr, tab_addr, src_len, test_byte;
+   src_addr = newTemp(Ity_I64);
+   des_addr = newTemp(Ity_I64);
+   tab_addr = newTemp(Ity_I64);
+   test_byte = newTemp(Ity_I16);
+   src_len = newTemp(Ity_I64);
+
+   assign(src_addr, get_gpr_dw0(r2));
+   assign(des_addr, get_gpr_dw0(r1));
+   assign(tab_addr, get_gpr_dw0(1));
+   assign(src_len, get_gpr_dw0(r1+1));
+   assign(test_byte, get_gpr_hw3(0));
+
+   IRTemp op = newTemp(Ity_I8);
+   IRTemp op1 = newTemp(Ity_I16);
+   IRTemp result = newTemp(Ity_I64);
+
+   /* End of source string? We're done; proceed to next insn */
+   s390_cc_set(0);
+   if_condition_goto(binop(Iop_CmpEQ64, mkexpr(src_len), mkU64(0)),
+                     guest_IA_next_instr);
+
+   /* Load character from source string, index translation table and
+      store translated character in op1. */
+   assign(op, binop(Iop_Shl8, load(Ity_I8, mkexpr(src_addr)), mkU8(1)));
+
+   assign(result, binop(Iop_Add64, unop(Iop_8Uto64, mkexpr(op)), 
+                        mkexpr(tab_addr)));
+   assign(op1, load(Ity_I16, mkexpr(result)));
+
+   if (! s390_host_has_etf2 || (m3 & 0x1) == 0) {
+      s390_cc_set(1);
+      if_condition_goto(binop(Iop_CmpEQ16, mkexpr(op1), mkexpr(test_byte)),
+                        guest_IA_next_instr);
+   }
+   store(get_gpr_dw0(r1), mkexpr(op1));
+
+   put_gpr_dw0(r2, binop(Iop_Add64, mkexpr(src_addr), mkU64(1)));
+   put_gpr_dw0(r1, binop(Iop_Add64, mkexpr(des_addr), mkU64(2)));
+   put_gpr_dw0(r1+1, binop(Iop_Sub64, mkexpr(src_len), mkU64(1)));
+
+   always_goto_and_chase(guest_IA_curr_instr);
+
+   return "trot";
+}
+
+static HChar *
+s390_irgen_TRTT(UChar m3, UChar r1, UChar r2)
+{
+   IRTemp src_addr, des_addr, tab_addr, src_len, test_byte;
+   src_addr = newTemp(Ity_I64);
+   des_addr = newTemp(Ity_I64);
+   tab_addr = newTemp(Ity_I64);
+   test_byte = newTemp(Ity_I16);
+   src_len = newTemp(Ity_I64);
+
+   assign(src_addr, get_gpr_dw0(r2));
+   assign(des_addr, get_gpr_dw0(r1));
+   assign(tab_addr, get_gpr_dw0(1));
+   assign(src_len, get_gpr_dw0(r1+1));
+   assign(test_byte, get_gpr_hw3(0));
+
+   IRTemp op = newTemp(Ity_I16);
+   IRTemp op1 = newTemp(Ity_I16);
+   IRTemp result = newTemp(Ity_I64);
+
+   /* End of source string? We're done; proceed to next insn */
+   s390_cc_set(0);
+   if_condition_goto(binop(Iop_CmpEQ64, mkexpr(src_len), mkU64(0)),
+                     guest_IA_next_instr);
+
+   /* Load character from source string, index translation table and
+      store translated character in op1. */
+   assign(op, binop(Iop_Shl16, load(Ity_I16, mkexpr(src_addr)), mkU8(1)));
+
+   assign(result, binop(Iop_Add64, unop(Iop_16Uto64, mkexpr(op)),
+                        mkexpr(tab_addr)));
+   assign(op1, load(Ity_I16, mkexpr(result)));
+
+   if (! s390_host_has_etf2 || (m3 & 0x1) == 0) {
+      s390_cc_set(1);
+      if_condition_goto(binop(Iop_CmpEQ16, mkexpr(op1), mkexpr(test_byte)),
+                        guest_IA_next_instr);
+   }
+
+   store(get_gpr_dw0(r1), mkexpr(op1));
+
+   put_gpr_dw0(r2, binop(Iop_Add64, mkexpr(src_addr), mkU64(2)));
+   put_gpr_dw0(r1, binop(Iop_Add64, mkexpr(des_addr), mkU64(2)));
+   put_gpr_dw0(r1+1, binop(Iop_Sub64, mkexpr(src_len), mkU64(2)));
+
+   always_goto_and_chase(guest_IA_curr_instr);
+
+   return "trtt";
+}
+
+static HChar *
+s390_irgen_TR(UChar length, IRTemp start1, IRTemp start2)
+{
+   IRTemp op = newTemp(Ity_I8);
+   IRTemp op1 = newTemp(Ity_I8);
+   IRTemp result = newTemp(Ity_I64);
+   IRTemp counter = newTemp(Ity_I64);
+
+   assign(counter, get_counter_dw0());
+
+   assign(op, load(Ity_I8, binop(Iop_Add64, mkexpr(start1), mkexpr(counter))));
+
+   assign(result, binop(Iop_Add64, unop(Iop_8Uto64, mkexpr(op)), mkexpr(start2)));
+
+   assign(op1, load(Ity_I8, mkexpr(result)));
+   store(binop(Iop_Add64, mkexpr(start1), mkexpr(counter)), mkexpr(op1));
+
+   put_counter_dw0(binop(Iop_Add64, mkexpr(counter), mkU64(1)));
+   if_condition_goto(binop(Iop_CmpNE64, mkexpr(counter), mkU64(length)),
+                     guest_IA_curr_instr);
+
+   put_counter_dw0(mkU64(0));
+
+   return "tr";
+}
+
+static HChar *
+s390_irgen_TRE(UChar r1,UChar r2)
+{
+   IRTemp src_addr, tab_addr, src_len, test_byte;
+   src_addr = newTemp(Ity_I64);
+   tab_addr = newTemp(Ity_I64);
+   src_len = newTemp(Ity_I64);
+   test_byte = newTemp(Ity_I8);
+
+   assign(src_addr, get_gpr_dw0(r1));
+   assign(src_len, get_gpr_dw0(r1+1));
+   assign(tab_addr, get_gpr_dw0(r2));
+   assign(test_byte, get_gpr_b7(0));
+
+   IRTemp op = newTemp(Ity_I8);
+   IRTemp op1 = newTemp(Ity_I8);
+   IRTemp result = newTemp(Ity_I64);
+
+   /* End of source string? We're done; proceed to next insn */   
+   s390_cc_set(0);
+   if_condition_goto(binop(Iop_CmpEQ64, mkexpr(src_len), mkU64(0)),
+                     guest_IA_next_instr);
+
+   /* Load character from source string and compare with test byte */
+   assign(op, load(Ity_I8, mkexpr(src_addr)));
+   
+   s390_cc_set(1);
+   if_condition_goto(binop(Iop_CmpEQ8, mkexpr(op), mkexpr(test_byte)),
+                     guest_IA_next_instr);
+
+   assign(result, binop(Iop_Add64, unop(Iop_8Uto64, mkexpr(op)), 
+			mkexpr(tab_addr)));
+
+   assign(op1, load(Ity_I8, mkexpr(result)));
+
+   store(get_gpr_dw0(r1), mkexpr(op1));
+   put_gpr_dw0(r1, binop(Iop_Add64, mkexpr(src_addr), mkU64(1)));
+   put_gpr_dw0(r1+1, binop(Iop_Sub64, mkexpr(src_len), mkU64(1)));
+
+   always_goto(mkU64(guest_IA_curr_instr));
+
+   return "tre";
+}
+
 
 /*------------------------------------------------------------*/
 /*--- Build IR for special instructions                    ---*/
@@ -11333,7 +11552,7 @@
                                  goto ok;
    case 0xb29d: s390_format_S_RD(s390_irgen_LFPC, ovl.fmt.S.b2, ovl.fmt.S.d2);
                                  goto ok;
-   case 0xb2a5: /* TRE */ goto unimplemented;
+   case 0xb2a5: s390_format_RRE_FF(s390_irgen_TRE, ovl.fmt.RRE.r1, ovl.fmt.RRE.r2);  goto ok;
    case 0xb2a6: /* CU21 */ goto unimplemented;
    case 0xb2a7: /* CU12 */ goto unimplemented;
    case 0xb2b0: s390_format_S_RD(s390_irgen_STFLE, ovl.fmt.S.b2, ovl.fmt.S.d2);
@@ -11696,9 +11915,12 @@
    case 0xb98a: /* CSPG */ goto unimplemented;
    case 0xb98d: /* EPSW */ goto unimplemented;
    case 0xb98e: /* IDTE */ goto unimplemented;
-   case 0xb990: /* TRTT */ goto unimplemented;
-   case 0xb991: /* TRTO */ goto unimplemented;
-   case 0xb992: /* TROT */ goto unimplemented;
+   case 0xb990: s390_format_RRF_M0RERE(s390_irgen_TRTT, ovl.fmt.RRF3.r3,
+                                   ovl.fmt.RRF3.r1, ovl.fmt.RRF3.r2);  goto ok;
+   case 0xb991: s390_format_RRF_M0RERE(s390_irgen_TRTO, ovl.fmt.RRF3.r3,
+                                   ovl.fmt.RRF3.r1, ovl.fmt.RRF3.r2);  goto ok;
+   case 0xb992: s390_format_RRF_M0RERE(s390_irgen_TROT, ovl.fmt.RRF3.r3,
+                                   ovl.fmt.RRF3.r1, ovl.fmt.RRF3.r2);  goto ok;
    case 0xb993: s390_format_RRF_M0RERE(s390_irgen_TROO, ovl.fmt.RRF3.r3,
                                    ovl.fmt.RRF3.r1, ovl.fmt.RRF3.r2);  goto ok;
    case 0xb994: s390_format_RRE_RR(s390_irgen_LLCR, ovl.fmt.RRE.r1,
@@ -13121,7 +13343,9 @@
    case 0xd9ULL: /* MVCK */ goto unimplemented;
    case 0xdaULL: /* MVCP */ goto unimplemented;
    case 0xdbULL: /* MVCS */ goto unimplemented;
-   case 0xdcULL: /* TR */ goto unimplemented;
+   case 0xdcULL: s390_format_SS_L0RDRD(s390_irgen_TR, ovl.fmt.SS.l,
+                                       ovl.fmt.SS.b1, ovl.fmt.SS.d1,
+                                       ovl.fmt.SS.b2, ovl.fmt.SS.d2);  goto ok;
    case 0xddULL: /* TRT */ goto unimplemented;
    case 0xdeULL: /* ED */ goto unimplemented;
    case 0xdfULL: /* EDMK */ goto unimplemented;