s390x/tcg: Check for exceptions in SET BFP ROUNDING MODE
Let's split handling of BFP/DFP rounding mode configuration. Also, let's not reuse the sfpc handler, use a separate handler so we can properly check for specification exceptions for SRNMB. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: David Hildenbrand <david@redhat.com> Message-Id: <20190218122710.23639-10-david@redhat.com> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
This commit is contained in:
parent
2aea83c672
commit
b9c737f58e
@ -819,3 +819,14 @@ void HELPER(sfas)(CPUS390XState *env, uint64_t fpc)
|
||||
tcg_s390_data_exception(env, s390_exc | 3, GETPC());
|
||||
}
|
||||
}
|
||||
|
||||
/* set bfp rounding mode */
|
||||
void HELPER(srnm)(CPUS390XState *env, uint64_t rnd)
|
||||
{
|
||||
if (rnd > 0x7 || fpc_to_rnd[rnd & 0x7] == -1) {
|
||||
s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC());
|
||||
}
|
||||
|
||||
env->fpc = deposit32(env->fpc, 0, 3, rnd);
|
||||
set_float_rounding_mode(fpc_to_rnd[rnd & 0x7], &env->fpu_status);
|
||||
}
|
||||
|
@ -106,6 +106,7 @@ 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_WG, void, env, i64)
|
||||
DEF_HELPER_FLAGS_2(sfas, TCG_CALL_NO_WG, void, env, i64)
|
||||
DEF_HELPER_FLAGS_2(srnm, 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)
|
||||
DEF_HELPER_FLAGS_2(lpq, TCG_CALL_NO_WG, i64, env, i64)
|
||||
|
@ -763,10 +763,10 @@
|
||||
/* SET FPC AND SIGNAL */
|
||||
F(0xb385, SFASR, RRE, IEEEE_SIM, 0, r1_o, 0, 0, sfas, 0, IF_DFP)
|
||||
/* SET BFP ROUNDING MODE */
|
||||
F(0xb299, SRNM, S, Z, 0, 0, 0, 0, srnm, 0, IF_BFP)
|
||||
F(0xb2b8, SRNMB, S, FPE, 0, 0, 0, 0, srnm, 0, IF_BFP)
|
||||
F(0xb299, SRNM, S, Z, la2, 0, 0, 0, srnm, 0, IF_BFP)
|
||||
F(0xb2b8, SRNMB, S, FPE, la2, 0, 0, 0, srnmb, 0, IF_BFP)
|
||||
/* SET DFP ROUNDING MODE */
|
||||
F(0xb2b9, SRNMT, S, DFPR, 0, 0, 0, 0, srnm, 0, IF_DFP)
|
||||
F(0xb2b9, SRNMT, S, DFPR, la2, 0, 0, 0, srnmt, 0, IF_DFP)
|
||||
/* SET PROGRAM MASK */
|
||||
C(0x0400, SPM, RR_a, Z, r1, 0, 0, 0, spm, 0)
|
||||
|
||||
|
@ -3996,41 +3996,33 @@ static DisasJumpType op_sfas(DisasContext *s, DisasOps *o)
|
||||
|
||||
static DisasJumpType op_srnm(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int b2 = get_field(s->fields, b2);
|
||||
int d2 = get_field(s->fields, d2);
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
int mask, pos, len;
|
||||
/* Bits other than 62 and 63 are ignored. Bit 29 is set to zero. */
|
||||
tcg_gen_andi_i64(o->addr1, o->addr1, 0x3ull);
|
||||
gen_helper_srnm(cpu_env, o->addr1);
|
||||
return DISAS_NEXT;
|
||||
}
|
||||
|
||||
switch (s->fields->op2) {
|
||||
case 0x99: /* SRNM */
|
||||
pos = 0, len = 2;
|
||||
break;
|
||||
case 0xb8: /* SRNMB */
|
||||
pos = 0, len = 3;
|
||||
break;
|
||||
case 0xb9: /* SRNMT */
|
||||
pos = 4, len = 3;
|
||||
break;
|
||||
default:
|
||||
tcg_abort();
|
||||
}
|
||||
mask = (1 << len) - 1;
|
||||
static DisasJumpType op_srnmb(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
/* Bits 0-55 are are ignored. */
|
||||
tcg_gen_andi_i64(o->addr1, o->addr1, 0xffull);
|
||||
gen_helper_srnm(cpu_env, o->addr1);
|
||||
return DISAS_NEXT;
|
||||
}
|
||||
|
||||
/* Insert the value into the appropriate field of the FPC. */
|
||||
if (b2 == 0) {
|
||||
tcg_gen_movi_i64(t1, d2 & mask);
|
||||
} else {
|
||||
tcg_gen_addi_i64(t1, regs[b2], d2);
|
||||
tcg_gen_andi_i64(t1, t1, mask);
|
||||
}
|
||||
tcg_gen_ld32u_i64(t2, cpu_env, offsetof(CPUS390XState, fpc));
|
||||
tcg_gen_deposit_i64(t2, t2, t1, pos, len);
|
||||
tcg_temp_free_i64(t1);
|
||||
static DisasJumpType op_srnmt(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
TCGv_i64 tmp = tcg_temp_new_i64();
|
||||
|
||||
/* Then install the new FPC to set the rounding mode in fpu_status. */
|
||||
gen_helper_sfpc(cpu_env, t2);
|
||||
tcg_temp_free_i64(t2);
|
||||
/* Bits other than 61-63 are ignored. */
|
||||
tcg_gen_andi_i64(o->addr1, o->addr1, 0x7ull);
|
||||
|
||||
/* No need to call a helper, we don't implement dfp */
|
||||
tcg_gen_ld32u_i64(tmp, cpu_env, offsetof(CPUS390XState, fpc));
|
||||
tcg_gen_deposit_i64(tmp, tmp, o->addr1, 4, 3);
|
||||
tcg_gen_st32_i64(tmp, cpu_env, offsetof(CPUS390XState, fpc));
|
||||
|
||||
tcg_temp_free_i64(tmp);
|
||||
return DISAS_NEXT;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user