From: Florian Krohm Date: Sun, 5 Aug 2012 02:59:55 +0000 (+0000) Subject: Support the cu14 insn. That insn is very much like cu12 except the X-Git-Tag: svn/VALGRIND_3_8_1^2~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1aa072406b71f97677ffec2922784f64bf24f3a4;p=thirdparty%2Fvalgrind.git Support the cu14 insn. That insn is very much like cu12 except the converted value is always 4 byte wide. The only other difference is the encoding of a 4-byte UTF-8 character. Some code refactoring does the trick. Part of fixing #289839. git-svn-id: svn://svn.valgrind.org/vex/trunk@2459 --- diff --git a/VEX/priv/guest_s390_defs.h b/VEX/priv/guest_s390_defs.h index 7a05736c6b..c6e77469e4 100644 --- a/VEX/priv/guest_s390_defs.h +++ b/VEX/priv/guest_s390_defs.h @@ -81,9 +81,11 @@ ULong s390x_dirtyhelper_STCKE(ULong *addr); ULong s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr); void s390x_dirtyhelper_CUxy(UChar *addr, ULong data, ULong num_bytes); -ULong s390_do_cu12_helper1(UInt byte1, UInt etf3_and_m3_is_1); +ULong s390_do_cu12_cu14_helper1(UInt byte1, UInt etf3_and_m3_is_1); ULong s390_do_cu12_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4, ULong stuff); +ULong s390_do_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4, + ULong stuff); ULong s390_do_cu21(UInt srcvalue, UInt low_surrogate); ULong s390_do_cu24(UInt srcvalue, UInt low_surrogate); ULong s390_do_cu42(UInt srcvalue); diff --git a/VEX/priv/guest_s390_helpers.c b/VEX/priv/guest_s390_helpers.c index 7969b27215..120f69788b 100644 --- a/VEX/priv/guest_s390_helpers.c +++ b/VEX/priv/guest_s390_helpers.c @@ -546,7 +546,7 @@ s390_do_cu42(UInt srcval) +-------+-----------+-------------------+ */ ULong -s390_do_cu12_helper1(UInt byte, UInt etf3_and_m3_is_1) +s390_do_cu12_cu14_helper1(UInt byte, UInt etf3_and_m3_is_1) { vassert(byte <= 0xff); @@ -567,7 +567,7 @@ s390_do_cu12_helper1(UInt byte, UInt etf3_and_m3_is_1) return 4 << 8; // 4 bytes } -/* The function performs a CU12 operation. BYTE1, BYTE2, etc are the +/* The function performs a CU12 or CU14 operation. BYTE1, BYTE2, etc are the bytes as read from the input stream, left to right. BYTE1 is a valid byte. The function returns three things encoded in an ULong value: @@ -580,13 +580,13 @@ s390_do_cu12_helper1(UInt byte, UInt etf3_and_m3_is_1) | 0x0 | converted bytes | num_bytes | invalid_character | +-------+-----------------+-----------+-------------------+ */ -ULong -s390_do_cu12_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4, - ULong stuff) +static ULong +s390_do_cu12_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4, + ULong stuff, Bool is_cu12) { + UInt num_src_bytes = stuff >> 1, etf3_and_m3_is_1 = stuff & 0x1; UInt num_bytes = 0, invalid_character = 0; ULong retval = 0; - UInt num_src_bytes = stuff >> 1, etf3_and_m3_is_1 = stuff & 0x1; vassert(num_src_bytes <= 4); @@ -684,26 +684,50 @@ s390_do_cu12_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4, UInt uvw = byte1 & 0x7; UInt xy = (byte2 >> 4) & 0x3; UInt uvwxy = (uvw << 2) | xy; - UInt abcd = (uvwxy - 1) & 0xf; UInt efgh = byte2 & 0xf; UInt ij = (byte3 >> 4) & 0x3; UInt klmn = byte3 & 0xf; UInt opqrst = byte4 & 0x3f; - UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | (efgh << 2) | ij; - UInt low_surrogate = (0xdc << 8) | (klmn << 6) | opqrst; - - num_bytes = 4; - retval = (high_surrogate << 16) | low_surrogate; + if (is_cu12) { + UInt abcd = (uvwxy - 1) & 0xf; + UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | (efgh << 2) | ij; + UInt low_surrogate = (0xdc << 8) | (klmn << 6) | opqrst; + + num_bytes = 4; + retval = (high_surrogate << 16) | low_surrogate; + } else { + num_bytes = 4; + retval = + (uvwxy << 16) | (efgh << 12) | (ij << 10) | (klmn << 6) | opqrst; + } break; } } + if (! is_cu12) num_bytes = 4; // for CU14, by definition + /* At this point RETVAL contains the converted bytes. Build up the final return value. */ return (retval << 16) | (num_bytes << 8) | invalid_character; } +ULong +s390_do_cu12_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4, + ULong stuff) +{ + return s390_do_cu12_cu14_helper2(byte1, byte2, byte3, byte4, stuff, + /* is_cu12 = */ 1); +} + +ULong +s390_do_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4, + ULong stuff) +{ + return s390_do_cu12_cu14_helper2(byte1, byte2, byte3, byte4, stuff, + /* is_cu12 = */ 0); +} + /*------------------------------------------------------------*/ /*--- Clean helper for "convert to binary". ---*/ diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c index 10fe3b0b9c..3bc34a781a 100644 --- a/VEX/priv/guest_s390_toIR.c +++ b/VEX/priv/guest_s390_toIR.c @@ -11472,12 +11472,12 @@ s390_irgen_CU42(UChar r1, UChar r2) } static IRExpr * -s390_call_cu12_helper1(IRExpr *byte1, IRExpr *etf3_and_m3_is_1) +s390_call_cu12_cu14_helper1(IRExpr *byte1, IRExpr *etf3_and_m3_is_1) { IRExpr **args, *call; args = mkIRExprVec_2(byte1, etf3_and_m3_is_1); - call = mkIRExprCCall(Ity_I64, 0 /*regparm*/, - "s390_do_cu12_helper1", &s390_do_cu12_helper1, args); + call = mkIRExprCCall(Ity_I64, 0 /*regparm*/, "s390_do_cu12_cu14_helper1", + &s390_do_cu12_cu14_helper1, args); /* Nothing is excluded from definedness checking. */ call->Iex.CCall.cee->mcx_mask = 0; @@ -11500,8 +11500,23 @@ s390_call_cu12_helper2(IRExpr *byte1, IRExpr *byte2, IRExpr *byte3, return call; } -static HChar * -s390_irgen_CU12(UChar m3, UChar r1, UChar r2) +static IRExpr * +s390_call_cu14_helper2(IRExpr *byte1, IRExpr *byte2, IRExpr *byte3, + IRExpr *byte4, IRExpr *stuff) +{ + IRExpr **args, *call; + args = mkIRExprVec_5(byte1, byte2, byte3, byte4, stuff); + call = mkIRExprCCall(Ity_I64, 0 /*regparm*/, + "s390_do_cu14_helper2", &s390_do_cu14_helper2, args); + + /* Nothing is excluded from definedness checking. */ + call->Iex.CCall.cee->mcx_mask = 0; + + return call; +} + +static void +s390_irgen_cu12_cu14(UChar m3, UChar r1, UChar r2, Bool is_cu12) { IRTemp addr1 = newTemp(Ity_I64); IRTemp addr2 = newTemp(Ity_I64); @@ -11527,8 +11542,8 @@ s390_irgen_CU12(UChar m3, UChar r1, UChar r2) /* Call the helper to get number of bytes and invalid byte indicator */ IRTemp retval1 = newTemp(Ity_I64); - assign(retval1, s390_call_cu12_helper1(mkexpr(byte1), - mkU32(extended_checking))); + assign(retval1, s390_call_cu12_cu14_helper1(mkexpr(byte1), + mkU32(extended_checking))); /* Check for invalid 1st byte */ IRExpr *is_invalid = unop(Iop_64to1, mkexpr(retval1)); @@ -11563,8 +11578,14 @@ s390_irgen_CU12(UChar m3, UChar r1, UChar r2) binop(Iop_Shl64, mkexpr(num_src_bytes), mkU8(1)), mkU64(extended_checking)); IRTemp retval2 = newTemp(Ity_I64); - assign(retval2, s390_call_cu12_helper2(mkexpr(byte1), byte2, byte3, byte4, - stuff)); + + if (is_cu12) { + assign(retval2, s390_call_cu12_helper2(mkexpr(byte1), byte2, byte3, + byte4, stuff)); + } else { + assign(retval2, s390_call_cu14_helper2(mkexpr(byte1), byte2, byte3, + byte4, stuff)); + } /* Check for invalid character */ s390_cc_set(2); @@ -11583,25 +11604,30 @@ s390_irgen_CU12(UChar m3, UChar r1, UChar r2) IRTemp data = newTemp(Ity_I64); assign(data, binop(Iop_Shr64, mkexpr(retval2), mkU8(16))); - /* To store the bytes construct 2 dirty helper calls. The helper calls - are guarded (num_bytes == 2 and num_bytes == 4, respectively) such - that only one of them will be called at runtime. */ - - Int i; - for (i = 2; i <= 4; ++i) { - IRDirty *d; - - if (i == 3) continue; // skip this one - - d = unsafeIRDirty_0_N(0 /* regparms */, "s390x_dirtyhelper_CUxy", - &s390x_dirtyhelper_CUxy, - mkIRExprVec_3(mkexpr(addr1), mkexpr(data), - mkexpr(num_bytes))); - d->guard = binop(Iop_CmpEQ64, mkexpr(num_bytes), mkU64(i)); - d->mFx = Ifx_Write; - d->mAddr = mkexpr(addr1); - d->mSize = i; - stmt(IRStmt_Dirty(d)); + if (is_cu12) { + /* To store the bytes construct 2 dirty helper calls. The helper calls + are guarded (num_bytes == 2 and num_bytes == 4, respectively) such + that only one of them will be called at runtime. */ + + Int i; + for (i = 2; i <= 4; ++i) { + IRDirty *d; + + if (i == 3) continue; // skip this one + + d = unsafeIRDirty_0_N(0 /* regparms */, "s390x_dirtyhelper_CUxy", + &s390x_dirtyhelper_CUxy, + mkIRExprVec_3(mkexpr(addr1), mkexpr(data), + mkexpr(num_bytes))); + d->guard = binop(Iop_CmpEQ64, mkexpr(num_bytes), mkU64(i)); + d->mFx = Ifx_Write; + d->mAddr = mkexpr(addr1); + d->mSize = i; + stmt(IRStmt_Dirty(d)); + } + } else { + // cu14 + store(mkexpr(addr1), unop(Iop_64to32, mkexpr(data))); } /* Update source address and length */ @@ -11613,10 +11639,24 @@ s390_irgen_CU12(UChar m3, UChar r1, UChar r2) put_gpr_dw0(r1 + 1, binop(Iop_Sub64, mkexpr(len1), mkexpr(num_bytes))); iterate(); +} + +static HChar * +s390_irgen_CU12(UChar m3, UChar r1, UChar r2) +{ + s390_irgen_cu12_cu14(m3, r1, r2, /* is_cu12 = */ 1); return "cu12"; } +static HChar * +s390_irgen_CU14(UChar m3, UChar r1, UChar r2) +{ + s390_irgen_cu12_cu14(m3, r1, r2, /* is_cu12 = */ 0); + + return "cu14"; +} + /*------------------------------------------------------------*/ /*--- Build IR for special instructions ---*/ /*------------------------------------------------------------*/ @@ -12451,7 +12491,9 @@ s390_decode_4byte_and_irgen(UChar *bytes) case 0xb9aa: /* LPTEA */ goto unimplemented; case 0xb9ae: /* RRBM */ goto unimplemented; case 0xb9af: /* PFMF */ goto unimplemented; - case 0xb9b0: /* CU14 */ goto unimplemented; + case 0xb9b0: s390_format_RRF_M0RERE(s390_irgen_CU14, ovl.fmt.RRF3.r3, + ovl.fmt.RRF3.r1, ovl.fmt.RRF3.r2); + goto ok; case 0xb9b1: s390_format_RRF_M0RERE(s390_irgen_CU24, ovl.fmt.RRF3.r3, ovl.fmt.RRF3.r1, ovl.fmt.RRF3.r2); goto ok;