From: Florian Krohm Date: Sat, 1 Sep 2012 17:54:09 +0000 (+0000) Subject: s390: Generate an emulation failure if an insn is encountered that X-Git-Tag: svn/VALGRIND_3_9_0^2~264 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=74314ae4fb5ef0b510c6b7b203dfb61e1158e0a1;p=thirdparty%2Fvalgrind.git s390: Generate an emulation failure if an insn is encountered that requires the floating point extension facility but the host does not have it. Factored out function emulation_failure. git-svn-id: svn://svn.valgrind.org/vex/trunk@2497 --- diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c index 0aece5b282..e1c82e1143 100644 --- a/VEX/priv/guest_s390_toIR.c +++ b/VEX/priv/guest_s390_toIR.c @@ -464,6 +464,15 @@ put_fpr_pair(UInt archreg, IRExpr *expr) put_fpr_dw0(archreg + 2, low); } +/* Terminate the current IRSB with an emulation failure. */ +static void +emulation_failure(VexEmNote fail_kind) +{ + stmt(IRStmt_Put(S390X_GUEST_OFFSET(guest_EMNOTE), mkU32(fail_kind))); + put_IA(mkaddr_expr(guest_IA_next_instr)); + dis_res->whatNext = Dis_StopHere; + dis_res->jk_StopHere = Ijk_EmFail; +} /*------------------------------------------------------------*/ /*--- IR Debugging aids. ---*/ @@ -8275,12 +8284,15 @@ static HChar * s390_irgen_CELFBR(UChar m3, UChar m4 __attribute__((unused)), UChar r1, UChar r2) { - IRTemp op2 = newTemp(Ity_I32); - - assign(op2, get_gpr_w1(r2)); - put_fpr_w0(r1, binop(Iop_I32UtoF32, mkU32(encode_rounding_mode(m3)), - mkexpr(op2))); + if (! s390_host_has_fpext) { + emulation_failure(EmFail_S390X_fpext); + } else { + IRTemp op2 = newTemp(Ity_I32); + assign(op2, get_gpr_w1(r2)); + put_fpr_w0(r1, binop(Iop_I32UtoF32, mkU32(encode_rounding_mode(m3)), + mkexpr(op2))); + } return "celfbr"; } @@ -8288,11 +8300,14 @@ static HChar * s390_irgen_CDLFBR(UChar m3, UChar m4 __attribute__((unused)), UChar r1, UChar r2) { - IRTemp op2 = newTemp(Ity_I32); - - assign(op2, get_gpr_w1(r2)); - put_fpr_dw0(r1, unop(Iop_I32UtoF64, mkexpr(op2))); + if (! s390_host_has_fpext) { + emulation_failure(EmFail_S390X_fpext); + } else { + IRTemp op2 = newTemp(Ity_I32); + assign(op2, get_gpr_w1(r2)); + put_fpr_dw0(r1, unop(Iop_I32UtoF64, mkexpr(op2))); + } return "cdlfbr"; } @@ -8300,12 +8315,15 @@ static HChar * s390_irgen_CELGBR(UChar m3, UChar m4 __attribute__((unused)), UChar r1, UChar r2) { - IRTemp op2 = newTemp(Ity_I64); - - assign(op2, get_gpr_dw0(r2)); - put_fpr_w0(r1, binop(Iop_I64UtoF32, mkU32(encode_rounding_mode(m3)), - mkexpr(op2))); + if (! s390_host_has_fpext) { + emulation_failure(EmFail_S390X_fpext); + } else { + IRTemp op2 = newTemp(Ity_I64); + assign(op2, get_gpr_dw0(r2)); + put_fpr_w0(r1, binop(Iop_I64UtoF32, mkU32(encode_rounding_mode(m3)), + mkexpr(op2))); + } return "celgbr"; } @@ -8313,12 +8331,15 @@ static HChar * s390_irgen_CDLGBR(UChar m3, UChar m4 __attribute__((unused)), UChar r1, UChar r2) { - IRTemp op2 = newTemp(Ity_I64); - - assign(op2, get_gpr_dw0(r2)); - put_fpr_dw0(r1, binop(Iop_I64UtoF64, mkU32(encode_rounding_mode(m3)), - mkexpr(op2))); + if (! s390_host_has_fpext) { + emulation_failure(EmFail_S390X_fpext); + } else { + IRTemp op2 = newTemp(Ity_I64); + assign(op2, get_gpr_dw0(r2)); + put_fpr_dw0(r1, binop(Iop_I64UtoF64, mkU32(encode_rounding_mode(m3)), + mkexpr(op2))); + } return "cdlgbr"; } @@ -8326,15 +8347,18 @@ static HChar * s390_irgen_CLFEBR(UChar m3, UChar m4 __attribute__((unused)), UChar r1, UChar r2) { - IRTemp op = newTemp(Ity_F32); - IRTemp result = newTemp(Ity_I32); - - assign(op, get_fpr_w0(r2)); - assign(result, binop(Iop_F32toI32U, mkU32(encode_rounding_mode(m3)), - mkexpr(op))); - put_gpr_w1(r1, mkexpr(result)); - s390_cc_thunk_putF(S390_CC_OP_BFP_32_TO_UINT_32, op); - + if (! s390_host_has_fpext) { + emulation_failure(EmFail_S390X_fpext); + } else { + IRTemp op = newTemp(Ity_F32); + IRTemp result = newTemp(Ity_I32); + + assign(op, get_fpr_w0(r2)); + assign(result, binop(Iop_F32toI32U, mkU32(encode_rounding_mode(m3)), + mkexpr(op))); + put_gpr_w1(r1, mkexpr(result)); + s390_cc_thunk_putF(S390_CC_OP_BFP_32_TO_UINT_32, op); + } return "clfebr"; } @@ -8342,15 +8366,18 @@ static HChar * s390_irgen_CLFDBR(UChar m3, UChar m4 __attribute__((unused)), UChar r1, UChar r2) { - IRTemp op = newTemp(Ity_F64); - IRTemp result = newTemp(Ity_I32); - - assign(op, get_fpr_dw0(r2)); - assign(result, binop(Iop_F64toI32U, mkU32(encode_rounding_mode(m3)), - mkexpr(op))); - put_gpr_w1(r1, mkexpr(result)); - s390_cc_thunk_putF(S390_CC_OP_BFP_64_TO_UINT_32, op); - + if (! s390_host_has_fpext) { + emulation_failure(EmFail_S390X_fpext); + } else { + IRTemp op = newTemp(Ity_F64); + IRTemp result = newTemp(Ity_I32); + + assign(op, get_fpr_dw0(r2)); + assign(result, binop(Iop_F64toI32U, mkU32(encode_rounding_mode(m3)), + mkexpr(op))); + put_gpr_w1(r1, mkexpr(result)); + s390_cc_thunk_putF(S390_CC_OP_BFP_64_TO_UINT_32, op); + } return "clfdbr"; } @@ -8358,15 +8385,18 @@ static HChar * s390_irgen_CLGEBR(UChar m3, UChar m4 __attribute__((unused)), UChar r1, UChar r2) { - IRTemp op = newTemp(Ity_F32); - IRTemp result = newTemp(Ity_I64); - - assign(op, get_fpr_w0(r2)); - assign(result, binop(Iop_F32toI64U, mkU32(encode_rounding_mode(m3)), - mkexpr(op))); - put_gpr_dw0(r1, mkexpr(result)); - s390_cc_thunk_putF(S390_CC_OP_BFP_32_TO_UINT_64, op); - + if (! s390_host_has_fpext) { + emulation_failure(EmFail_S390X_fpext); + } else { + IRTemp op = newTemp(Ity_F32); + IRTemp result = newTemp(Ity_I64); + + assign(op, get_fpr_w0(r2)); + assign(result, binop(Iop_F32toI64U, mkU32(encode_rounding_mode(m3)), + mkexpr(op))); + put_gpr_dw0(r1, mkexpr(result)); + s390_cc_thunk_putF(S390_CC_OP_BFP_32_TO_UINT_64, op); + } return "clgebr"; } @@ -8374,15 +8404,18 @@ static HChar * s390_irgen_CLGDBR(UChar m3, UChar m4 __attribute__((unused)), UChar r1, UChar r2) { - IRTemp op = newTemp(Ity_F64); - IRTemp result = newTemp(Ity_I64); - - assign(op, get_fpr_dw0(r2)); - assign(result, binop(Iop_F64toI64U, mkU32(encode_rounding_mode(m3)), - mkexpr(op))); - put_gpr_dw0(r1, mkexpr(result)); - s390_cc_thunk_putF(S390_CC_OP_BFP_64_TO_UINT_64, op); - + if (! s390_host_has_fpext) { + emulation_failure(EmFail_S390X_fpext); + } else { + IRTemp op = newTemp(Ity_F64); + IRTemp result = newTemp(Ity_I64); + + assign(op, get_fpr_dw0(r2)); + assign(result, binop(Iop_F64toI64U, mkU32(encode_rounding_mode(m3)), + mkexpr(op))); + put_gpr_dw0(r1, mkexpr(result)); + s390_cc_thunk_putF(S390_CC_OP_BFP_64_TO_UINT_64, op); + } return "clgdbr"; } @@ -10285,11 +10318,14 @@ static HChar * s390_irgen_CXLFBR(UChar m3, UChar m4 __attribute__((unused)), UChar r1, UChar r2) { - IRTemp op2 = newTemp(Ity_I32); - - assign(op2, get_gpr_w1(r2)); - put_fpr_pair(r1, unop(Iop_I32UtoF128, mkexpr(op2))); + if (! s390_host_has_fpext) { + emulation_failure(EmFail_S390X_fpext); + } else { + IRTemp op2 = newTemp(Ity_I32); + assign(op2, get_gpr_w1(r2)); + put_fpr_pair(r1, unop(Iop_I32UtoF128, mkexpr(op2))); + } return "cxlfbr"; } @@ -10309,11 +10345,14 @@ static HChar * s390_irgen_CXLGBR(UChar m3, UChar m4 __attribute__((unused)), UChar r1, UChar r2) { - IRTemp op2 = newTemp(Ity_I64); - - assign(op2, get_gpr_dw0(r2)); - put_fpr_pair(r1, unop(Iop_I64UtoF128, mkexpr(op2))); + if (! s390_host_has_fpext) { + emulation_failure(EmFail_S390X_fpext); + } else { + IRTemp op2 = newTemp(Ity_I64); + assign(op2, get_gpr_dw0(r2)); + put_fpr_pair(r1, unop(Iop_I64UtoF128, mkexpr(op2))); + } return "cxlgbr"; } @@ -10336,15 +10375,18 @@ static HChar * s390_irgen_CLFXBR(UChar m3, UChar m4 __attribute__((unused)), UChar r1, UChar r2) { - IRTemp op = newTemp(Ity_F128); - IRTemp result = newTemp(Ity_I32); - - assign(op, get_fpr_pair(r2)); - assign(result, binop(Iop_F128toI32U, mkU32(encode_rounding_mode(m3)), - mkexpr(op))); - put_gpr_w1(r1, mkexpr(result)); - s390_cc_thunk_put1f128(S390_CC_OP_BFP_128_TO_UINT_32, op); - + if (! s390_host_has_fpext) { + emulation_failure(EmFail_S390X_fpext); + } else { + IRTemp op = newTemp(Ity_F128); + IRTemp result = newTemp(Ity_I32); + + assign(op, get_fpr_pair(r2)); + assign(result, binop(Iop_F128toI32U, mkU32(encode_rounding_mode(m3)), + mkexpr(op))); + put_gpr_w1(r1, mkexpr(result)); + s390_cc_thunk_put1f128(S390_CC_OP_BFP_128_TO_UINT_32, op); + } return "clfxbr"; } @@ -10368,15 +10410,18 @@ static HChar * s390_irgen_CLGXBR(UChar m3, UChar m4 __attribute__((unused)), UChar r1, UChar r2) { - IRTemp op = newTemp(Ity_F128); - IRTemp result = newTemp(Ity_I64); - - assign(op, get_fpr_pair(r2)); - assign(result, binop(Iop_F128toI64U, mkU32(encode_rounding_mode(m3)), - mkexpr(op))); - put_gpr_dw0(r1, mkexpr(result)); - s390_cc_thunk_put1f128(S390_CC_OP_BFP_128_TO_UINT_64, op); - + if (! s390_host_has_fpext) { + emulation_failure(EmFail_S390X_fpext); + } else { + IRTemp op = newTemp(Ity_F128); + IRTemp result = newTemp(Ity_I64); + + assign(op, get_fpr_pair(r2)); + assign(result, binop(Iop_F128toI64U, mkU32(encode_rounding_mode(m3)), + mkexpr(op))); + put_gpr_dw0(r1, mkexpr(result)); + s390_cc_thunk_put1f128(S390_CC_OP_BFP_128_TO_UINT_64, op); + } return "clgxbr"; } @@ -10969,11 +11014,7 @@ static HChar * s390_irgen_STCKF(IRTemp op2addr) { if (! s390_host_has_stckf) { - stmt(IRStmt_Put(S390X_GUEST_OFFSET(guest_EMNOTE), - mkU32(EmFail_S390X_stckf))); - put_IA(mkaddr_expr(guest_IA_next_instr)); - dis_res->whatNext = Dis_StopHere; - dis_res->jk_StopHere = Ijk_EmFail; + emulation_failure(EmFail_S390X_stckf); } else { IRTemp cc = newTemp(Ity_I64); @@ -11012,11 +11053,7 @@ static HChar * s390_irgen_STFLE(IRTemp op2addr) { if (! s390_host_has_stfle) { - stmt(IRStmt_Put(S390X_GUEST_OFFSET(guest_EMNOTE), - mkU32(EmFail_S390X_stfle))); - put_IA(mkaddr_expr(guest_IA_next_instr)); - dis_res->whatNext = Dis_StopHere; - dis_res->jk_StopHere = Ijk_EmFail; + emulation_failure(EmFail_S390X_stfle); return "stfle"; } @@ -11979,11 +12016,7 @@ static HChar * s390_irgen_ECAG(UChar r1, UChar r3, IRTemp op2addr) { if (! s390_host_has_gie) { - stmt(IRStmt_Put(S390X_GUEST_OFFSET(guest_EMNOTE), - mkU32(EmFail_S390X_ecag))); - put_IA(mkaddr_expr(guest_IA_next_instr)); - dis_res->whatNext = Dis_StopHere; - dis_res->jk_StopHere = Ijk_EmFail; + emulation_failure(EmFail_S390X_ecag); } else { put_gpr_dw0(r1, s390_call_ecag(mkexpr(op2addr))); } diff --git a/VEX/priv/main_main.c b/VEX/priv/main_main.c index ef2c121c67..29b971d5e5 100644 --- a/VEX/priv/main_main.c +++ b/VEX/priv/main_main.c @@ -1026,12 +1026,16 @@ HChar* LibVEX_EmNote_string ( VexEmNote ew ) return "PPC64 function redirection stack overflow"; case EmWarn_PPC64_redir_underflow: return "PPC64 function redirection stack underflow"; - case EmFail_S390X_stfle: + case EmFail_S390X_stfle: return "Instruction stfle is not supported on this host"; - case EmFail_S390X_stckf: + case EmFail_S390X_stckf: return "Instruction stckf is not supported on this host"; - case EmFail_S390X_ecag: + case EmFail_S390X_ecag: return "Instruction ecag is not supported on this host"; + case EmFail_S390X_fpext: + return "Encountered an instruction that requires the floating " + "point extension facility.\n" + " That facility is not available on this host"; default: vpanic("LibVEX_EmNote_string: unknown warning"); } diff --git a/VEX/pub/libvex_emnote.h b/VEX/pub/libvex_emnote.h index f5cf943918..bb9cab776a 100644 --- a/VEX/pub/libvex_emnote.h +++ b/VEX/pub/libvex_emnote.h @@ -94,6 +94,10 @@ typedef /* ecag insn is not supported on this host */ EmFail_S390X_ecag, + /* insn needs floating point extension facility which is not + available on this host */ + EmFail_S390X_fpext, + EmNote_NUMBER } VexEmNote;