target/s390x: Fix EXECUTE of relative long instructions
authorIlya Leoshkevich <iii@linux.ibm.com>
Thu, 16 Mar 2023 21:07:50 +0000 (22:07 +0100)
committerThomas Huth <thuth@redhat.com>
Mon, 20 Mar 2023 08:32:50 +0000 (09:32 +0100)
The code uses the wrong base for relative addressing: it should use the
target instruction address and not the EXECUTE's address.

Fix by storing the target instruction address in the new CPUS390XState
member and loading it from the code generated by gen_ri2().

Reported-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: David Hildenbrand <david@redhat.com>
Message-Id: <20230316210751.302423-2-iii@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
target/s390x/cpu.h
target/s390x/tcg/mem_helper.c
target/s390x/tcg/translate.c

index 16f63547513027bb8ac88265edcad322e8231641..82c2f575bb39c1159f8d5fc96ce711ba2d450322 100644 (file)
@@ -87,6 +87,7 @@ struct CPUArchState {
     uint64_t cc_vr;
 
     uint64_t ex_value;
+    uint64_t ex_target;
 
     uint64_t __excp_addr;
     uint64_t psa;
index 6835c26dda479488bcdb983848b68e58e08fbeb4..00afae2b6408b1ded5bcb240e83ac403840ac498 100644 (file)
@@ -2530,6 +2530,7 @@ void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr)
        that ex_value is non-zero, which flags that we are in a state
        that requires such execution.  */
     env->ex_value = insn | ilen;
+    env->ex_target = addr;
 }
 
 uint32_t HELPER(mvcos)(CPUS390XState *env, uint64_t dest, uint64_t src,
index 6758d9f47a93d301fe8ab6d5f76c329d015665a1..a6d81ed16b5f1b83db59ad33ac1ce21c62784163 100644 (file)
@@ -5769,7 +5769,18 @@ static void in2_a2(DisasContext *s, DisasOps *o)
 
 static TCGv gen_ri2(DisasContext *s)
 {
-    return tcg_constant_i64(s->base.pc_next + (int64_t)get_field(s, i2) * 2);
+    int64_t delta = (int64_t)get_field(s, i2) * 2;
+    TCGv ri2;
+
+    if (unlikely(s->ex_value)) {
+        ri2 = tcg_temp_new_i64();
+        tcg_gen_ld_i64(ri2, cpu_env, offsetof(CPUS390XState, ex_target));
+        tcg_gen_addi_i64(ri2, ri2, delta);
+    } else {
+        ri2 = tcg_constant_i64(s->base.pc_next + delta);
+    }
+
+    return ri2;
 }
 
 static void in2_ri2(DisasContext *s, DisasOps *o)