Complicated because we may now require a runtime jump. Reviewed-by: Ilya Leoshkevich <i...@linux.ibm.com> Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- target/s390x/tcg/translate.c | 40 +++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 12 deletions(-)
diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index b317767a7d..96bd37426f 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -3922,7 +3922,7 @@ static DisasJumpType op_sacf(DisasContext *s, DisasOps *o) static DisasJumpType op_sam(DisasContext *s, DisasOps *o) { int sam = s->insn->data; - TCGv_i64 tsam; + TCGLabel *fault = NULL; uint64_t mask; switch (sam) { @@ -3937,20 +3937,36 @@ static DisasJumpType op_sam(DisasContext *s, DisasOps *o) break; } - /* Bizarre but true, we check the address of the current insn for the - specification exception, not the next to be executed. Thus the PoO - documents that Bad Things Happen two bytes before the end. */ - if (s->base.pc_next & ~mask) { - gen_program_exception(s, PGM_SPECIFICATION); - return DISAS_NORETURN; - } - s->pc_tmp &= mask; + /* + * Bizarre but true, we check the address of the current insn for the + * specification exception, not the next to be executed. Thus the PoO + * documents that Bad Things Happen two bytes before the end. + */ + if (mask != -1) { + TCGv_i64 t = tcg_temp_new_i64(); + fault = gen_new_label(); - tsam = tcg_constant_i64(sam); - tcg_gen_deposit_i64(psw_mask, psw_mask, tsam, 31, 2); + gen_psw_addr_disp(s, t, 0); + tcg_gen_andi_i64(t, t, ~mask); + tcg_gen_brcondi_i64(TCG_COND_NE, t, 0, fault); + tcg_temp_free_i64(t); + } + + update_cc_op(s); + + tcg_gen_deposit_i64(psw_mask, psw_mask, tcg_constant_i64(sam), 31, 2); + + gen_psw_addr_disp(s, psw_addr, s->ilen); + tcg_gen_andi_i64(psw_addr, psw_addr, mask); /* Always exit the TB, since we (may have) changed execution mode. */ - return DISAS_TOO_MANY; + tcg_gen_lookup_and_goto_ptr(); + + if (mask != -1) { + gen_set_label(fault); + gen_program_exception(s, PGM_SPECIFICATION); + } + return DISAS_NORETURN; } static DisasJumpType op_sar(DisasContext *s, DisasOps *o) -- 2.34.1