From: Florian Krohm Date: Sat, 28 Jul 2012 22:18:32 +0000 (+0000) Subject: Add support for the CU42 insn. Part of fixing bugzilla #289839. X-Git-Tag: svn/VALGRIND_3_8_1^2~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9bb80e9ac76c3d820ed67361339af9c3dd8c3b3e;p=thirdparty%2Fvalgrind.git Add support for the CU42 insn. Part of fixing bugzilla #289839. git-svn-id: svn://svn.valgrind.org/vex/trunk@2452 --- diff --git a/VEX/priv/guest_s390_defs.h b/VEX/priv/guest_s390_defs.h index d237a4ebe5..bcb2ad3fe4 100644 --- a/VEX/priv/guest_s390_defs.h +++ b/VEX/priv/guest_s390_defs.h @@ -83,6 +83,7 @@ void s390x_dirtyhelper_CUxy(UChar *addr, ULong data, ULong num_bytes); ULong s390_do_cu21(UInt srcvalue, UInt low_surrogate); ULong s390_do_cu24(UInt srcvalue, UInt low_surrogate); +ULong s390_do_cu42(UInt srcvalue); UInt s390_do_cvb(ULong decimal); ULong s390_do_cvd(ULong binary); diff --git a/VEX/priv/guest_s390_helpers.c b/VEX/priv/guest_s390_helpers.c index e1f7811f23..dd080b0c4c 100644 --- a/VEX/priv/guest_s390_helpers.c +++ b/VEX/priv/guest_s390_helpers.c @@ -483,6 +483,53 @@ s390_do_cu24(UInt srcval, UInt low_surrogate) } +/*------------------------------------------------------------*/ +/*--- Clean helper for CU42. ---*/ +/*------------------------------------------------------------*/ + +/* The function performs a CU42 operation. It returns three things + encoded in an ULong value: + - the converted bytes (at most 4) + - the number of converted bytes (2 or 4; 0 if invalid character) + - an indication whether the UTF-32 character is invalid + + 64 48 16 8 0 + +-------+-----------------+-----------+-------------------+ + | 0x0 | converted bytes | num_bytes | invalid_character | + +-------+-----------------+-----------+-------------------+ +*/ +ULong +s390_do_cu42(UInt srcval) +{ + ULong retval; + UInt num_bytes, invalid_character = 0; + + if ((srcval >= 0x0000 && srcval <= 0xd7ff) || + (srcval >= 0xdc00 && srcval <= 0xffff)) { + retval = srcval; + num_bytes = 2; + } else if (srcval >= 0x00010000 && srcval <= 0x0010FFFF) { + UInt uvwxy = srcval >> 16; + UInt abcd = (uvwxy - 1) & 0xf; + UInt efghij = (srcval >> 10) & 0x3f; + + UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | efghij; + UInt low_surrogate = (0xdc << 8) | (srcval & 0x3ff); + + retval = (high_surrogate << 16) | low_surrogate; + num_bytes = 4; + } else { + /* D800 - DBFF or 00110000 - FFFFFFFF */ + invalid_character = 1; + retval = num_bytes = 0; /* does not matter; not used */ + } + + /* At this point RETVAL contains the converted bytes. + Build up the final return value. */ + return (retval << 16) | (num_bytes << 8) | invalid_character; +} + + /*------------------------------------------------------------*/ /*--- Clean helper for "convert to binary". ---*/ /*------------------------------------------------------------*/ diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c index 9c158649cc..1b12254d49 100644 --- a/VEX/priv/guest_s390_toIR.c +++ b/VEX/priv/guest_s390_toIR.c @@ -11353,6 +11353,100 @@ s390_irgen_CU24(UChar m3, UChar r1, UChar r2) return "cu24"; } +static IRExpr * +s390_call_cu42(IRExpr *srcval) +{ + IRExpr **args, *call; + args = mkIRExprVec_1(srcval); + call = mkIRExprCCall(Ity_I64, 0 /*regparm*/, + "s390_do_cu42", &s390_do_cu42, args); + + /* Nothing is excluded from definedness checking. */ + call->Iex.CCall.cee->mcx_mask = 0; + + return call; +} + +static HChar * +s390_irgen_CU42(UChar r1, UChar r2) +{ + IRTemp addr1 = newTemp(Ity_I64); + IRTemp addr2 = newTemp(Ity_I64); + IRTemp len1 = newTemp(Ity_I64); + IRTemp len2 = newTemp(Ity_I64); + + assign(addr1, get_gpr_dw0(r1)); + assign(addr2, get_gpr_dw0(r2)); + assign(len1, get_gpr_dw0(r1 + 1)); + assign(len2, get_gpr_dw0(r2 + 1)); + + /* We're processing the 2nd operand 4 bytes at a time. Therefore, if + there are less than 4 bytes left, then the 2nd operand is exhausted + and we're done here. cc = 0 */ + s390_cc_set(0); + next_insn_if(binop(Iop_CmpLT64U, mkexpr(len2), mkU64(4))); + + /* Read the 2nd operand. */ + IRTemp srcval = newTemp(Ity_I32); + assign(srcval, load(Ity_I32, mkexpr(addr2))); + + /* Call the helper */ + IRTemp retval = newTemp(Ity_I64); + assign(retval, s390_call_cu42(mkexpr(srcval))); + + /* If the UTF-32 character was invalid, set cc=2 and we're done. + cc=2 outranks cc=1 (1st operand exhausted) */ + IRExpr *invalid_character = binop(Iop_And64, mkexpr(retval), mkU64(0xff)); + + s390_cc_set(2); + next_insn_if(binop(Iop_CmpEQ64, invalid_character, mkU64(1))); + + /* Now test whether the 1st operand is exhausted */ + IRTemp num_bytes = newTemp(Ity_I64); + assign(num_bytes, binop(Iop_And64, + binop(Iop_Shr64, mkexpr(retval), mkU8(8)), + mkU64(0xff))); + s390_cc_set(1); + next_insn_if(binop(Iop_CmpLT64U, mkexpr(len1), mkexpr(num_bytes))); + + /* Extract the bytes to be stored at addr1 */ + IRTemp data = newTemp(Ity_I64); + assign(data, binop(Iop_Shr64, mkexpr(retval), 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)); + } + + /* Update source address and length */ + put_gpr_dw0(r2, binop(Iop_Add64, mkexpr(addr2), mkU64(4))); + put_gpr_dw0(r2 + 1, binop(Iop_Sub64, mkexpr(len2), mkU64(4))); + + /* Update destination address and length */ + put_gpr_dw0(r1, binop(Iop_Add64, mkexpr(addr1), mkexpr(num_bytes))); + put_gpr_dw0(r1 + 1, binop(Iop_Sub64, mkexpr(len1), mkexpr(num_bytes))); + + iterate(); + + return "cu42"; +} + /*------------------------------------------------------------*/ /*--- Build IR for special instructions ---*/ /*------------------------------------------------------------*/ @@ -12190,7 +12284,8 @@ s390_decode_4byte_and_irgen(UChar *bytes) ovl.fmt.RRF3.r1, ovl.fmt.RRF3.r2); goto ok; case 0xb9b2: /* CU41 */ goto unimplemented; - case 0xb9b3: /* CU42 */ goto unimplemented; + case 0xb9b3: s390_format_RRE_RR(s390_irgen_CU42, ovl.fmt.RRE.r1, + ovl.fmt.RRE.r2); goto ok; case 0xb9bd: /* TRTRE */ goto unimplemented; case 0xb9be: /* SRSTU */ goto unimplemented; case 0xb9bf: /* TRTE */ goto unimplemented;