diff options
-rw-r--r-- | target/s390x/fpu_helper.c | 22 | ||||
-rw-r--r-- | target/s390x/helper.h | 2 |
2 files changed, 19 insertions, 5 deletions
diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c index 7508c0748e..4dc70ec60f 100644 --- a/target/s390x/fpu_helper.c +++ b/target/s390x/fpu_helper.c @@ -753,21 +753,30 @@ uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al) return RET128(ret); } -static const int fpc_to_rnd[4] = { +static const int fpc_to_rnd[8] = { float_round_nearest_even, float_round_to_zero, float_round_up, - float_round_down + float_round_down, + -1, + -1, + -1, + float_round_to_odd, }; /* set fpc */ void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc) { + if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u || + (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) { + s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC()); + } + /* Install everything in the main FPC. */ env->fpc = fpc; /* Install the rounding mode in the shadow fpu_status. */ - set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status); + set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status); } /* set fpc and signal */ @@ -776,12 +785,17 @@ void HELPER(sfas)(CPUS390XState *env, uint64_t fpc) uint32_t signalling = env->fpc; uint32_t s390_exc; + if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u || + (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) { + s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC()); + } + /* * FPC is set to the FPC operand with a bitwise OR of the signalling * flags. */ env->fpc = fpc | (signalling & 0x00ff0000); - set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status); + set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status); /* * If any signaling flag is enabled in the new FPC mask, a diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 6260b50496..a99b067c9c 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -104,7 +104,7 @@ DEF_HELPER_4(trtr, i32, env, i32, i64, i64) DEF_HELPER_5(trXX, i32, env, i32, i32, i32, i32) DEF_HELPER_4(cksm, i64, env, i64, i64, i64) DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64) -DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64) +DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_WG, void, env, i64) DEF_HELPER_FLAGS_2(sfas, TCG_CALL_NO_WG, void, env, i64) DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_2(stfle, i32, env, i64) |