]> xenbits.xensource.com Git - qemu-xen.git/commitdiff
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)
committerMichael Tokarev <mjt@tls.msk.ru>
Thu, 30 Mar 2023 09:19:04 +0000 (12:19 +0300)
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>
(cherry picked from commit 703d03a4aaf38f285555ef5422ba5ce075416fc4)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
target/s390x/cpu.h
target/s390x/tcg/mem_helper.c
target/s390x/tcg/translate.c

index 7d6d01325b2dfa9dd4b216c3d5283dc5a5c4c424..8aaf8dd5a3bd32ed6cf25d038aedb6acf24373c9 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 3758b9e688cf641177f5b982daa1f50af6fea17e..7e7de5e2f16f72434fa09fc589588de26eee1d8f 100644 (file)
@@ -2618,6 +2618,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 ab60b51e312af43085b37bc583730e45b030b4a9..e328aa5b971a07a865ff4dd18c9baa73c468f62c 100644 (file)
@@ -5964,7 +5964,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)