qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PULL 00/43] target/hppa: Misc improvements
@ 2024-05-15  9:40 Richard Henderson
  2024-05-15  9:40 ` [PULL 01/43] target/hppa: Move cpu_get_tb_cpu_state out of line Richard Henderson
                   ` (43 more replies)
  0 siblings, 44 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel

The following changes since commit 3d48b6b687c558a042d91370633b91c6e29e0e05:

  Merge tag 'pull-request-2024-05-14' of https://gitlab.com/thuth/qemu into staging (2024-05-14 17:24:04 +0200)

are available in the Git repository at:

  https://gitlab.com/rth7680/qemu.git tags/pull-hppa-20240515

for you to fetch changes up to 9e035f00788c52a6f51529c54371a611d9f8b089:

  target/hppa: Log cpu state on return-from-interrupt (2024-05-15 10:03:45 +0200)

----------------------------------------------------------------
target/hppa:
  - Use TCG_COND_TST where applicable.
  - Use CF_BP_PAGE instead of a local breakpoint search.
  - Clean up IAOQ handling during translation.
  - Implement CF_PCREL.
  - Implement PSW.B.
  - Implement PSW.X.
  - Log cpu state on interrupt and rfi.

----------------------------------------------------------------
Richard Henderson (43):
      target/hppa: Move cpu_get_tb_cpu_state out of line
      target/hppa: Use hppa_form_gva_psw in hppa_cpu_get_pc
      target/hppa: Move constant destination check into use_goto_tb
      target/hppa: Pass displacement to do_dbranch
      target/hppa: Allow prior nullification in do_ibranch
      target/hppa: Use CF_BP_PAGE instead of cpu_breakpoint_test
      target/hppa: Add install_iaq_entries
      target/hppa: Add install_link
      target/hppa: Delay computation of IAQ_Next
      target/hppa: Skip nullified insns in unconditional dbranch path
      target/hppa: Simplify TB end
      target/hppa: Add IASQ entries to DisasContext
      target/hppa: Add space arguments to install_iaq_entries
      target/hppa: Add space argument to do_ibranch
      target/hppa: Use umax in do_ibranch_priv
      target/hppa: Always make a copy in do_ibranch_priv
      target/hppa: Introduce and use DisasIAQE for branch management
      target/hppa: Use displacements in DisasIAQE
      target/hppa: Rename cond_make_* helpers
      target/hppa: Use TCG_COND_TST* in do_cond
      target/hppa: Use TCG_COND_TST* in do_log_cond
      target/hppa: Use TCG_COND_TST* in do_unit_zero_cond
      target/hppa: Use TCG_COND_TST* in do_unit_addsub
      target/hppa: Use TCG_COND_TST* in trans_bb_imm
      target/hppa: Use registerfields.h for FPSR
      target/hppa: Use TCG_COND_TST* in trans_ftest
      target/hppa: Remove cond_free
      target/hppa: Introduce DisasDelayException
      target/hppa: Use delay_excp for conditional traps
      target/hppa: Use delay_excp for conditional trap on overflow
      linux-user/hppa: Force all code addresses to PRIV_USER
      target/hppa: Store full iaoq_f and page offset of iaoq_b in TB
      target/hppa: Do not mask in copy_iaoq_entry
      target/hppa: Improve hppa_cpu_dump_state
      target/hppa: Split PSW X and B into their own field
      target/hppa: Manage PSW_X and PSW_B in translator
      target/hppa: Implement PSW_B
      target/hppa: Implement PSW_X
      target/hppa: Drop tlb_entry return from hppa_get_physical_address
      target/hppa: Adjust priv for B,GATE at runtime
      target/hppa: Implement CF_PCREL
      target/hppa: Log cpu state at interrupt
      target/hppa: Log cpu state on return-from-interrupt

 linux-user/hppa/target_cpu.h |    4 +-
 target/hppa/cpu.h            |   80 ++-
 target/hppa/helper.h         |    3 +-
 linux-user/elfload.c         |    4 +-
 linux-user/hppa/cpu_loop.c   |   14 +-
 linux-user/hppa/signal.c     |    6 +-
 target/hppa/cpu.c            |   92 +++-
 target/hppa/fpu_helper.c     |   26 +-
 target/hppa/gdbstub.c        |    6 +
 target/hppa/helper.c         |   66 ++-
 target/hppa/int_helper.c     |   33 +-
 target/hppa/mem_helper.c     |   99 ++--
 target/hppa/op_helper.c      |   17 +-
 target/hppa/sys_helper.c     |   12 +
 target/hppa/translate.c      | 1158 +++++++++++++++++++++---------------------
 15 files changed, 868 insertions(+), 752 deletions(-)


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PULL 01/43] target/hppa: Move cpu_get_tb_cpu_state out of line
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 02/43] target/hppa: Use hppa_form_gva_psw in hppa_cpu_get_pc Richard Henderson
                   ` (42 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/cpu.h | 43 ++-----------------------------------------
 target/hppa/cpu.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 41 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index fb2e4c4a98..61f1353133 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -314,47 +314,8 @@ hwaddr hppa_abs_to_phys_pa2_w1(vaddr addr);
 #define TB_FLAG_PRIV_SHIFT  8
 #define TB_FLAG_UNALIGN     0x400
 
-static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
-                                        uint64_t *cs_base, uint32_t *pflags)
-{
-    uint32_t flags = env->psw_n * PSW_N;
-
-    /* TB lookup assumes that PC contains the complete virtual address.
-       If we leave space+offset separate, we'll get ITLB misses to an
-       incomplete virtual address.  This also means that we must separate
-       out current cpu privilege from the low bits of IAOQ_F.  */
-#ifdef CONFIG_USER_ONLY
-    *pc = env->iaoq_f & -4;
-    *cs_base = env->iaoq_b & -4;
-    flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
-#else
-    /* ??? E, T, H, L, B bits need to be here, when implemented.  */
-    flags |= env->psw & (PSW_W | PSW_C | PSW_D | PSW_P);
-    flags |= (env->iaoq_f & 3) << TB_FLAG_PRIV_SHIFT;
-
-    *pc = hppa_form_gva_psw(env->psw, (env->psw & PSW_C ? env->iasq_f : 0),
-                            env->iaoq_f & -4);
-    *cs_base = env->iasq_f;
-
-    /* Insert a difference between IAOQ_B and IAOQ_F within the otherwise zero
-       low 32-bits of CS_BASE.  This will succeed for all direct branches,
-       which is the primary case we care about -- using goto_tb within a page.
-       Failure is indicated by a zero difference.  */
-    if (env->iasq_f == env->iasq_b) {
-        target_long diff = env->iaoq_b - env->iaoq_f;
-        if (diff == (int32_t)diff) {
-            *cs_base |= (uint32_t)diff;
-        }
-    }
-    if ((env->sr[4] == env->sr[5])
-        & (env->sr[4] == env->sr[6])
-        & (env->sr[4] == env->sr[7])) {
-        flags |= TB_FLAG_SR_SAME;
-    }
-#endif
-
-    *pflags = flags;
-}
+void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
+                          uint64_t *cs_base, uint32_t *pflags);
 
 target_ulong cpu_hppa_get_psw(CPUHPPAState *env);
 void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong);
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index 393a81988d..582036b31e 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -43,6 +43,48 @@ static vaddr hppa_cpu_get_pc(CPUState *cs)
     return cpu->env.iaoq_f;
 }
 
+void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
+                          uint64_t *cs_base, uint32_t *pflags)
+{
+    uint32_t flags = env->psw_n * PSW_N;
+
+    /* TB lookup assumes that PC contains the complete virtual address.
+       If we leave space+offset separate, we'll get ITLB misses to an
+       incomplete virtual address.  This also means that we must separate
+       out current cpu privilege from the low bits of IAOQ_F.  */
+#ifdef CONFIG_USER_ONLY
+    *pc = env->iaoq_f & -4;
+    *cs_base = env->iaoq_b & -4;
+    flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
+#else
+    /* ??? E, T, H, L, B bits need to be here, when implemented.  */
+    flags |= env->psw & (PSW_W | PSW_C | PSW_D | PSW_P);
+    flags |= (env->iaoq_f & 3) << TB_FLAG_PRIV_SHIFT;
+
+    *pc = hppa_form_gva_psw(env->psw, (env->psw & PSW_C ? env->iasq_f : 0),
+                            env->iaoq_f & -4);
+    *cs_base = env->iasq_f;
+
+    /* Insert a difference between IAOQ_B and IAOQ_F within the otherwise zero
+       low 32-bits of CS_BASE.  This will succeed for all direct branches,
+       which is the primary case we care about -- using goto_tb within a page.
+       Failure is indicated by a zero difference.  */
+    if (env->iasq_f == env->iasq_b) {
+        target_long diff = env->iaoq_b - env->iaoq_f;
+        if (diff == (int32_t)diff) {
+            *cs_base |= (uint32_t)diff;
+        }
+    }
+    if ((env->sr[4] == env->sr[5])
+        & (env->sr[4] == env->sr[6])
+        & (env->sr[4] == env->sr[7])) {
+        flags |= TB_FLAG_SR_SAME;
+    }
+#endif
+
+    *pflags = flags;
+}
+
 static void hppa_cpu_synchronize_from_tb(CPUState *cs,
                                          const TranslationBlock *tb)
 {
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 02/43] target/hppa: Use hppa_form_gva_psw in hppa_cpu_get_pc
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
  2024-05-15  9:40 ` [PULL 01/43] target/hppa: Move cpu_get_tb_cpu_state out of line Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 03/43] target/hppa: Move constant destination check into use_goto_tb Richard Henderson
                   ` (41 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

This function is for log_pc(), which needs to produce a
similar result to cpu_get_tb_cpu_state().

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/cpu.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index 582036b31e..be8c558014 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -38,9 +38,10 @@ static void hppa_cpu_set_pc(CPUState *cs, vaddr value)
 
 static vaddr hppa_cpu_get_pc(CPUState *cs)
 {
-    HPPACPU *cpu = HPPA_CPU(cs);
+    CPUHPPAState *env = cpu_env(cs);
 
-    return cpu->env.iaoq_f;
+    return hppa_form_gva_psw(env->psw, (env->psw & PSW_C ? env->iasq_f : 0),
+                             env->iaoq_f & -4);
 }
 
 void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
@@ -61,8 +62,7 @@ void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
     flags |= env->psw & (PSW_W | PSW_C | PSW_D | PSW_P);
     flags |= (env->iaoq_f & 3) << TB_FLAG_PRIV_SHIFT;
 
-    *pc = hppa_form_gva_psw(env->psw, (env->psw & PSW_C ? env->iasq_f : 0),
-                            env->iaoq_f & -4);
+    *pc = hppa_cpu_get_pc(env_cpu(env));
     *cs_base = env->iasq_f;
 
     /* Insert a difference between IAOQ_B and IAOQ_F within the otherwise zero
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 03/43] target/hppa: Move constant destination check into use_goto_tb
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
  2024-05-15  9:40 ` [PULL 01/43] target/hppa: Move cpu_get_tb_cpu_state out of line Richard Henderson
  2024-05-15  9:40 ` [PULL 02/43] target/hppa: Use hppa_form_gva_psw in hppa_cpu_get_pc Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 04/43] target/hppa: Pass displacement to do_dbranch Richard Henderson
                   ` (40 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Share this check between gen_goto_tb and hppa_tr_translate_insn.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 6d45611888..398803981c 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -662,9 +662,10 @@ static bool gen_illegal(DisasContext *ctx)
     } while (0)
 #endif
 
-static bool use_goto_tb(DisasContext *ctx, uint64_t dest)
+static bool use_goto_tb(DisasContext *ctx, uint64_t bofs, uint64_t nofs)
 {
-    return translator_use_goto_tb(&ctx->base, dest);
+    return (bofs != -1 && nofs != -1 &&
+            translator_use_goto_tb(&ctx->base, bofs));
 }
 
 /* If the next insn is to be nullified, and it's on the same page,
@@ -678,16 +679,16 @@ static bool use_nullify_skip(DisasContext *ctx)
 }
 
 static void gen_goto_tb(DisasContext *ctx, int which,
-                        uint64_t f, uint64_t b)
+                        uint64_t b, uint64_t n)
 {
-    if (f != -1 && b != -1 && use_goto_tb(ctx, f)) {
+    if (use_goto_tb(ctx, b, n)) {
         tcg_gen_goto_tb(which);
-        copy_iaoq_entry(ctx, cpu_iaoq_f, f, NULL);
-        copy_iaoq_entry(ctx, cpu_iaoq_b, b, NULL);
+        copy_iaoq_entry(ctx, cpu_iaoq_f, b, NULL);
+        copy_iaoq_entry(ctx, cpu_iaoq_b, n, NULL);
         tcg_gen_exit_tb(ctx->base.tb, which);
     } else {
-        copy_iaoq_entry(ctx, cpu_iaoq_f, f, cpu_iaoq_b);
-        copy_iaoq_entry(ctx, cpu_iaoq_b, b, ctx->iaoq_n_var);
+        copy_iaoq_entry(ctx, cpu_iaoq_f, b, cpu_iaoq_b);
+        copy_iaoq_entry(ctx, cpu_iaoq_b, n, ctx->iaoq_n_var);
         tcg_gen_lookup_and_goto_ptr();
     }
 }
@@ -4744,8 +4745,7 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
     /* Advance the insn queue.  Note that this check also detects
        a priority change within the instruction queue.  */
     if (ret == DISAS_NEXT && ctx->iaoq_b != ctx->iaoq_f + 4) {
-        if (ctx->iaoq_b != -1 && ctx->iaoq_n != -1
-            && use_goto_tb(ctx, ctx->iaoq_b)
+        if (use_goto_tb(ctx, ctx->iaoq_b, ctx->iaoq_n)
             && (ctx->null_cond.c == TCG_COND_NEVER
                 || ctx->null_cond.c == TCG_COND_ALWAYS)) {
             nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS);
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 04/43] target/hppa: Pass displacement to do_dbranch
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (2 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 03/43] target/hppa: Move constant destination check into use_goto_tb Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 05/43] target/hppa: Allow prior nullification in do_ibranch Richard Henderson
                   ` (39 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller, Philippe Mathieu-Daudé

Pass a displacement instead of an absolute value.

In trans_be, remove the user-only do_dbranch case.  The branch we are
attempting to optimize is to the zero page, which is perforce on a
different page than the code currently executing, which means that
we will *not* use a goto_tb.  Use a plain indirect branch instead,
which is what we got out of the attempted direct branch anyway.

Reviewed-by: Helge Deller <deller@gmx.de>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 33 +++++++++------------------------
 1 file changed, 9 insertions(+), 24 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 398803981c..4c42b518c5 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -1766,9 +1766,11 @@ static bool do_fop_dedd(DisasContext *ctx, unsigned rt,
 
 /* Emit an unconditional branch to a direct target, which may or may not
    have already had nullification handled.  */
-static bool do_dbranch(DisasContext *ctx, uint64_t dest,
+static bool do_dbranch(DisasContext *ctx, int64_t disp,
                        unsigned link, bool is_n)
 {
+    uint64_t dest = iaoq_dest(ctx, disp);
+
     if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
         if (link != 0) {
             copy_iaoq_entry(ctx, cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
@@ -1815,10 +1817,7 @@ static bool do_cbranch(DisasContext *ctx, int64_t disp, bool is_n,
 
     /* Handle TRUE and NEVER as direct branches.  */
     if (c == TCG_COND_ALWAYS) {
-        return do_dbranch(ctx, dest, 0, is_n && disp >= 0);
-    }
-    if (c == TCG_COND_NEVER) {
-        return do_dbranch(ctx, ctx->iaoq_n, 0, is_n && disp < 0);
+        return do_dbranch(ctx, disp, 0, is_n && disp >= 0);
     }
 
     taken = gen_new_label();
@@ -3914,22 +3913,6 @@ static bool trans_be(DisasContext *ctx, arg_be *a)
 {
     TCGv_i64 tmp;
 
-#ifdef CONFIG_USER_ONLY
-    /* ??? It seems like there should be a good way of using
-       "be disp(sr2, r0)", the canonical gateway entry mechanism
-       to our advantage.  But that appears to be inconvenient to
-       manage along side branch delay slots.  Therefore we handle
-       entry into the gateway page via absolute address.  */
-    /* Since we don't implement spaces, just branch.  Do notice the special
-       case of "be disp(*,r0)" using a direct branch to disp, so that we can
-       goto_tb to the TB containing the syscall.  */
-    if (a->b == 0) {
-        return do_dbranch(ctx, a->disp, a->l, a->n);
-    }
-#else
-    nullify_over(ctx);
-#endif
-
     tmp = tcg_temp_new_i64();
     tcg_gen_addi_i64(tmp, load_gpr(ctx, a->b), a->disp);
     tmp = do_ibranch_priv(ctx, tmp);
@@ -3939,6 +3922,8 @@ static bool trans_be(DisasContext *ctx, arg_be *a)
 #else
     TCGv_i64 new_spc = tcg_temp_new_i64();
 
+    nullify_over(ctx);
+
     load_spr(ctx, new_spc, a->sp);
     if (a->l) {
         copy_iaoq_entry(ctx, cpu_gr[31], ctx->iaoq_n, ctx->iaoq_n_var);
@@ -3968,7 +3953,7 @@ static bool trans_be(DisasContext *ctx, arg_be *a)
 
 static bool trans_bl(DisasContext *ctx, arg_bl *a)
 {
-    return do_dbranch(ctx, iaoq_dest(ctx, a->disp), a->l, a->n);
+    return do_dbranch(ctx, a->disp, a->l, a->n);
 }
 
 static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
@@ -4022,7 +4007,7 @@ static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
         save_gpr(ctx, a->l, tmp);
     }
 
-    return do_dbranch(ctx, dest, 0, a->n);
+    return do_dbranch(ctx, dest - iaoq_dest(ctx, 0), 0, a->n);
 }
 
 static bool trans_blr(DisasContext *ctx, arg_blr *a)
@@ -4035,7 +4020,7 @@ static bool trans_blr(DisasContext *ctx, arg_blr *a)
         return do_ibranch(ctx, tmp, a->l, a->n);
     } else {
         /* BLR R0,RX is a good way to load PC+8 into RX.  */
-        return do_dbranch(ctx, ctx->iaoq_f + 8, a->l, a->n);
+        return do_dbranch(ctx, 0, a->l, a->n);
     }
 }
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 05/43] target/hppa: Allow prior nullification in do_ibranch
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (3 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 04/43] target/hppa: Pass displacement to do_dbranch Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 06/43] target/hppa: Use CF_BP_PAGE instead of cpu_breakpoint_test Richard Henderson
                   ` (38 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Simplify the function by not attempting a conditional move
on the branch destination -- just use nullify_over normally.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 73 +++++++++++------------------------------
 1 file changed, 20 insertions(+), 53 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 4c42b518c5..140dfb747a 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -1871,17 +1871,15 @@ static bool do_cbranch(DisasContext *ctx, int64_t disp, bool is_n,
 static bool do_ibranch(DisasContext *ctx, TCGv_i64 dest,
                        unsigned link, bool is_n)
 {
-    TCGv_i64 a0, a1, next, tmp;
-    TCGCond c;
+    TCGv_i64 next;
 
-    assert(ctx->null_lab == NULL);
+    if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
+        next = tcg_temp_new_i64();
+        tcg_gen_mov_i64(next, dest);
 
-    if (ctx->null_cond.c == TCG_COND_NEVER) {
         if (link != 0) {
             copy_iaoq_entry(ctx, cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
         }
-        next = tcg_temp_new_i64();
-        tcg_gen_mov_i64(next, dest);
         if (is_n) {
             if (use_nullify_skip(ctx)) {
                 copy_iaoq_entry(ctx, cpu_iaoq_f, -1, next);
@@ -1895,60 +1893,29 @@ static bool do_ibranch(DisasContext *ctx, TCGv_i64 dest,
         }
         ctx->iaoq_n = -1;
         ctx->iaoq_n_var = next;
-    } else if (is_n && use_nullify_skip(ctx)) {
-        /* The (conditional) branch, B, nullifies the next insn, N,
-           and we're allowed to skip execution N (no single-step or
-           tracepoint in effect).  Since the goto_ptr that we must use
-           for the indirect branch consumes no special resources, we
-           can (conditionally) skip B and continue execution.  */
-        /* The use_nullify_skip test implies we have a known control path.  */
-        tcg_debug_assert(ctx->iaoq_b != -1);
-        tcg_debug_assert(ctx->iaoq_n != -1);
+        return true;
+    }
 
-        /* We do have to handle the non-local temporary, DEST, before
-           branching.  Since IOAQ_F is not really live at this point, we
-           can simply store DEST optimistically.  Similarly with IAOQ_B.  */
+    nullify_over(ctx);
+
+    if (is_n && use_nullify_skip(ctx)) {
         copy_iaoq_entry(ctx, cpu_iaoq_f, -1, dest);
         next = tcg_temp_new_i64();
         tcg_gen_addi_i64(next, dest, 4);
         copy_iaoq_entry(ctx, cpu_iaoq_b, -1, next);
-
-        nullify_over(ctx);
-        if (link != 0) {
-            copy_iaoq_entry(ctx, cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
-        }
-        tcg_gen_lookup_and_goto_ptr();
-        return nullify_end(ctx);
+        nullify_set(ctx, 0);
     } else {
-        c = ctx->null_cond.c;
-        a0 = ctx->null_cond.a0;
-        a1 = ctx->null_cond.a1;
-
-        tmp = tcg_temp_new_i64();
-        next = tcg_temp_new_i64();
-
-        copy_iaoq_entry(ctx, tmp, ctx->iaoq_n, ctx->iaoq_n_var);
-        tcg_gen_movcond_i64(c, next, a0, a1, tmp, dest);
-        ctx->iaoq_n = -1;
-        ctx->iaoq_n_var = next;
-
-        if (link != 0) {
-            tcg_gen_movcond_i64(c, cpu_gr[link], a0, a1, cpu_gr[link], tmp);
-        }
-
-        if (is_n) {
-            /* The branch nullifies the next insn, which means the state of N
-               after the branch is the inverse of the state of N that applied
-               to the branch.  */
-            tcg_gen_setcond_i64(tcg_invert_cond(c), cpu_psw_n, a0, a1);
-            cond_free(&ctx->null_cond);
-            ctx->null_cond = cond_make_n();
-            ctx->psw_n_nonzero = true;
-        } else {
-            cond_free(&ctx->null_cond);
-        }
+        copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
+        copy_iaoq_entry(ctx, cpu_iaoq_b, -1, dest);
+        nullify_set(ctx, is_n);
     }
-    return true;
+    if (link != 0) {
+        copy_iaoq_entry(ctx, cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
+    }
+
+    tcg_gen_lookup_and_goto_ptr();
+    ctx->base.is_jmp = DISAS_NORETURN;
+    return nullify_end(ctx);
 }
 
 /* Implement
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 06/43] target/hppa: Use CF_BP_PAGE instead of cpu_breakpoint_test
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (4 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 05/43] target/hppa: Allow prior nullification in do_ibranch Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 07/43] target/hppa: Add install_iaq_entries Richard Henderson
                   ` (37 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

The generic tcg driver will have already checked for breakpoints.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 140dfb747a..d272be0e6e 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -674,8 +674,9 @@ static bool use_goto_tb(DisasContext *ctx, uint64_t bofs, uint64_t nofs)
    executing a TB that merely branches to the next TB.  */
 static bool use_nullify_skip(DisasContext *ctx)
 {
-    return (((ctx->iaoq_b ^ ctx->iaoq_f) & TARGET_PAGE_MASK) == 0
-            && !cpu_breakpoint_test(ctx->cs, ctx->iaoq_b, BP_ANY));
+    return (!(tb_cflags(ctx->base.tb) & CF_BP_PAGE)
+            && ctx->iaoq_b != -1
+            && is_same_page(&ctx->base, ctx->iaoq_b));
 }
 
 static void gen_goto_tb(DisasContext *ctx, int which,
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 07/43] target/hppa: Add install_iaq_entries
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (5 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 06/43] target/hppa: Use CF_BP_PAGE instead of cpu_breakpoint_test Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 08/43] target/hppa: Add install_link Richard Henderson
                   ` (36 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Instead of two separate cpu_iaoq_entry calls, use one call to update
both IAQ_Front and IAQ_Back.  Simplify with an argument combination
that automatically handles a simple increment from Front to Back.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 64 +++++++++++++++++++++--------------------
 1 file changed, 33 insertions(+), 31 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index d272be0e6e..08d5e2a4bc 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -617,6 +617,23 @@ static void copy_iaoq_entry(DisasContext *ctx, TCGv_i64 dest,
     }
 }
 
+static void install_iaq_entries(DisasContext *ctx, uint64_t bi, TCGv_i64 bv,
+                                uint64_t ni, TCGv_i64 nv)
+{
+    copy_iaoq_entry(ctx, cpu_iaoq_f, bi, bv);
+
+    /* Allow ni variable, with nv null, to indicate a trivial advance. */
+    if (ni != -1 || nv) {
+        copy_iaoq_entry(ctx, cpu_iaoq_b, ni, nv);
+    } else if (bi != -1) {
+        copy_iaoq_entry(ctx, cpu_iaoq_b, bi + 4, NULL);
+    } else {
+        tcg_gen_addi_i64(cpu_iaoq_b, cpu_iaoq_f, 4);
+        tcg_gen_andi_i64(cpu_iaoq_b, cpu_iaoq_b,
+                         gva_offset_mask(ctx->tb_flags));
+    }
+}
+
 static inline uint64_t iaoq_dest(DisasContext *ctx, int64_t disp)
 {
     return ctx->iaoq_f + disp + 8;
@@ -629,8 +646,7 @@ static void gen_excp_1(int exception)
 
 static void gen_excp(DisasContext *ctx, int exception)
 {
-    copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
-    copy_iaoq_entry(ctx, cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
+    install_iaq_entries(ctx, ctx->iaoq_f, cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
     nullify_save(ctx);
     gen_excp_1(exception);
     ctx->base.is_jmp = DISAS_NORETURN;
@@ -684,12 +700,10 @@ static void gen_goto_tb(DisasContext *ctx, int which,
 {
     if (use_goto_tb(ctx, b, n)) {
         tcg_gen_goto_tb(which);
-        copy_iaoq_entry(ctx, cpu_iaoq_f, b, NULL);
-        copy_iaoq_entry(ctx, cpu_iaoq_b, n, NULL);
+        install_iaq_entries(ctx, b, NULL, n, NULL);
         tcg_gen_exit_tb(ctx->base.tb, which);
     } else {
-        copy_iaoq_entry(ctx, cpu_iaoq_f, b, cpu_iaoq_b);
-        copy_iaoq_entry(ctx, cpu_iaoq_b, n, ctx->iaoq_n_var);
+        install_iaq_entries(ctx, b, cpu_iaoq_b, n, ctx->iaoq_n_var);
         tcg_gen_lookup_and_goto_ptr();
     }
 }
@@ -1883,9 +1897,7 @@ static bool do_ibranch(DisasContext *ctx, TCGv_i64 dest,
         }
         if (is_n) {
             if (use_nullify_skip(ctx)) {
-                copy_iaoq_entry(ctx, cpu_iaoq_f, -1, next);
-                tcg_gen_addi_i64(next, next, 4);
-                copy_iaoq_entry(ctx, cpu_iaoq_b, -1, next);
+                install_iaq_entries(ctx, -1, next, -1, NULL);
                 nullify_set(ctx, 0);
                 ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
                 return true;
@@ -1900,14 +1912,10 @@ static bool do_ibranch(DisasContext *ctx, TCGv_i64 dest,
     nullify_over(ctx);
 
     if (is_n && use_nullify_skip(ctx)) {
-        copy_iaoq_entry(ctx, cpu_iaoq_f, -1, dest);
-        next = tcg_temp_new_i64();
-        tcg_gen_addi_i64(next, dest, 4);
-        copy_iaoq_entry(ctx, cpu_iaoq_b, -1, next);
+        install_iaq_entries(ctx, -1, dest, -1, NULL);
         nullify_set(ctx, 0);
     } else {
-        copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
-        copy_iaoq_entry(ctx, cpu_iaoq_b, -1, dest);
+        install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, -1, dest);
         nullify_set(ctx, is_n);
     }
     if (link != 0) {
@@ -1998,9 +2006,7 @@ static void do_page_zero(DisasContext *ctx)
         tcg_gen_st_i64(cpu_gr[26], tcg_env, offsetof(CPUHPPAState, cr[27]));
         tmp = tcg_temp_new_i64();
         tcg_gen_ori_i64(tmp, cpu_gr[31], 3);
-        copy_iaoq_entry(ctx, cpu_iaoq_f, -1, tmp);
-        tcg_gen_addi_i64(tmp, tmp, 4);
-        copy_iaoq_entry(ctx, cpu_iaoq_b, -1, tmp);
+        install_iaq_entries(ctx, -1, tmp, -1, NULL);
         ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
         break;
 
@@ -2744,8 +2750,8 @@ static bool trans_or(DisasContext *ctx, arg_rrr_cf_d *a)
             nullify_over(ctx);
 
             /* Advance the instruction queue.  */
-            copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
-            copy_iaoq_entry(ctx, cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
+            install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b,
+                                ctx->iaoq_n, ctx->iaoq_n_var);
             nullify_set(ctx, 0);
 
             /* Tell the qemu main loop to halt until this cpu has work.  */
@@ -3898,18 +3904,15 @@ static bool trans_be(DisasContext *ctx, arg_be *a)
         tcg_gen_mov_i64(cpu_sr[0], cpu_iasq_b);
     }
     if (a->n && use_nullify_skip(ctx)) {
-        copy_iaoq_entry(ctx, cpu_iaoq_f, -1, tmp);
-        tcg_gen_addi_i64(tmp, tmp, 4);
-        copy_iaoq_entry(ctx, cpu_iaoq_b, -1, tmp);
+        install_iaq_entries(ctx, -1, tmp, -1, NULL);
         tcg_gen_mov_i64(cpu_iasq_f, new_spc);
         tcg_gen_mov_i64(cpu_iasq_b, cpu_iasq_f);
         nullify_set(ctx, 0);
     } else {
-        copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
+        install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, -1, tmp);
         if (ctx->iaoq_b == -1) {
             tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
         }
-        copy_iaoq_entry(ctx, cpu_iaoq_b, -1, tmp);
         tcg_gen_mov_i64(cpu_iasq_b, new_spc);
         nullify_set(ctx, a->n);
     }
@@ -4018,11 +4021,10 @@ static bool trans_bve(DisasContext *ctx, arg_bve *a)
     nullify_over(ctx);
     dest = do_ibranch_priv(ctx, load_gpr(ctx, a->b));
 
-    copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
+    install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, -1, dest);
     if (ctx->iaoq_b == -1) {
         tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
     }
-    copy_iaoq_entry(ctx, cpu_iaoq_b, -1, dest);
     tcg_gen_mov_i64(cpu_iasq_b, space_select(ctx, 0, dest));
     if (a->l) {
         copy_iaoq_entry(ctx, cpu_gr[a->l], ctx->iaoq_n, ctx->iaoq_n_var);
@@ -4721,8 +4723,8 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
     case DISAS_IAQ_N_STALE:
     case DISAS_IAQ_N_STALE_EXIT:
         if (ctx->iaoq_f == -1) {
-            copy_iaoq_entry(ctx, cpu_iaoq_f, -1, cpu_iaoq_b);
-            copy_iaoq_entry(ctx, cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
+            install_iaq_entries(ctx, -1, cpu_iaoq_b,
+                                ctx->iaoq_n, ctx->iaoq_n_var);
 #ifndef CONFIG_USER_ONLY
             tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
 #endif
@@ -4751,8 +4753,8 @@ static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
     case DISAS_TOO_MANY:
     case DISAS_IAQ_N_STALE:
     case DISAS_IAQ_N_STALE_EXIT:
-        copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
-        copy_iaoq_entry(ctx, cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
+        install_iaq_entries(ctx, ctx->iaoq_f, cpu_iaoq_f,
+                            ctx->iaoq_b, cpu_iaoq_b);
         nullify_save(ctx);
         /* FALLTHRU */
     case DISAS_IAQ_N_UPDATED:
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 08/43] target/hppa: Add install_link
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (6 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 07/43] target/hppa: Add install_iaq_entries Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 09/43] target/hppa: Delay computation of IAQ_Next Richard Henderson
                   ` (35 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Add a common routine for writing the return address.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 55 ++++++++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 23 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 08d5e2a4bc..220665d98e 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -634,6 +634,24 @@ static void install_iaq_entries(DisasContext *ctx, uint64_t bi, TCGv_i64 bv,
     }
 }
 
+static void install_link(DisasContext *ctx, unsigned link, bool with_sr0)
+{
+    tcg_debug_assert(ctx->null_cond.c == TCG_COND_NEVER);
+    if (!link) {
+        return;
+    }
+    if (ctx->iaoq_b == -1) {
+        tcg_gen_addi_i64(cpu_gr[link], cpu_iaoq_b, 4);
+    } else {
+        tcg_gen_movi_i64(cpu_gr[link], ctx->iaoq_b + 4);
+    }
+#ifndef CONFIG_USER_ONLY
+    if (with_sr0) {
+        tcg_gen_mov_i64(cpu_sr[0], cpu_iasq_b);
+    }
+#endif
+}
+
 static inline uint64_t iaoq_dest(DisasContext *ctx, int64_t disp)
 {
     return ctx->iaoq_f + disp + 8;
@@ -1787,9 +1805,7 @@ static bool do_dbranch(DisasContext *ctx, int64_t disp,
     uint64_t dest = iaoq_dest(ctx, disp);
 
     if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
-        if (link != 0) {
-            copy_iaoq_entry(ctx, cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
-        }
+        install_link(ctx, link, false);
         ctx->iaoq_n = dest;
         if (is_n) {
             ctx->null_cond.c = TCG_COND_ALWAYS;
@@ -1797,10 +1813,7 @@ static bool do_dbranch(DisasContext *ctx, int64_t disp,
     } else {
         nullify_over(ctx);
 
-        if (link != 0) {
-            copy_iaoq_entry(ctx, cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
-        }
-
+        install_link(ctx, link, false);
         if (is_n && use_nullify_skip(ctx)) {
             nullify_set(ctx, 0);
             gen_goto_tb(ctx, 0, dest, dest + 4);
@@ -1892,9 +1905,7 @@ static bool do_ibranch(DisasContext *ctx, TCGv_i64 dest,
         next = tcg_temp_new_i64();
         tcg_gen_mov_i64(next, dest);
 
-        if (link != 0) {
-            copy_iaoq_entry(ctx, cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
-        }
+        install_link(ctx, link, false);
         if (is_n) {
             if (use_nullify_skip(ctx)) {
                 install_iaq_entries(ctx, -1, next, -1, NULL);
@@ -1911,16 +1922,17 @@ static bool do_ibranch(DisasContext *ctx, TCGv_i64 dest,
 
     nullify_over(ctx);
 
+    next = tcg_temp_new_i64();
+    tcg_gen_mov_i64(next, dest);
+
+    install_link(ctx, link, false);
     if (is_n && use_nullify_skip(ctx)) {
-        install_iaq_entries(ctx, -1, dest, -1, NULL);
+        install_iaq_entries(ctx, -1, next, -1, NULL);
         nullify_set(ctx, 0);
     } else {
-        install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, -1, dest);
+        install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, -1, next);
         nullify_set(ctx, is_n);
     }
-    if (link != 0) {
-        copy_iaoq_entry(ctx, cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
-    }
 
     tcg_gen_lookup_and_goto_ptr();
     ctx->base.is_jmp = DISAS_NORETURN;
@@ -3899,10 +3911,7 @@ static bool trans_be(DisasContext *ctx, arg_be *a)
     nullify_over(ctx);
 
     load_spr(ctx, new_spc, a->sp);
-    if (a->l) {
-        copy_iaoq_entry(ctx, cpu_gr[31], ctx->iaoq_n, ctx->iaoq_n_var);
-        tcg_gen_mov_i64(cpu_sr[0], cpu_iasq_b);
-    }
+    install_link(ctx, a->l, true);
     if (a->n && use_nullify_skip(ctx)) {
         install_iaq_entries(ctx, -1, tmp, -1, NULL);
         tcg_gen_mov_i64(cpu_iasq_f, new_spc);
@@ -4019,16 +4028,16 @@ static bool trans_bve(DisasContext *ctx, arg_bve *a)
     return do_ibranch(ctx, dest, a->l, a->n);
 #else
     nullify_over(ctx);
-    dest = do_ibranch_priv(ctx, load_gpr(ctx, a->b));
+    dest = tcg_temp_new_i64();
+    tcg_gen_mov_i64(dest, load_gpr(ctx, a->b));
+    dest = do_ibranch_priv(ctx, dest);
 
+    install_link(ctx, a->l, false);
     install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, -1, dest);
     if (ctx->iaoq_b == -1) {
         tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
     }
     tcg_gen_mov_i64(cpu_iasq_b, space_select(ctx, 0, dest));
-    if (a->l) {
-        copy_iaoq_entry(ctx, cpu_gr[a->l], ctx->iaoq_n, ctx->iaoq_n_var);
-    }
     nullify_set(ctx, a->n);
     tcg_gen_lookup_and_goto_ptr();
     ctx->base.is_jmp = DISAS_NORETURN;
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 09/43] target/hppa: Delay computation of IAQ_Next
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (7 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 08/43] target/hppa: Add install_link Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 10/43] target/hppa: Skip nullified insns in unconditional dbranch path Richard Henderson
                   ` (34 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

We no longer have to allocate a temp and perform an
addition before translation of the rest of the insn.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 26 ++++++++++----------------
 1 file changed, 10 insertions(+), 16 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 220665d98e..9189e0350b 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -1807,6 +1807,7 @@ static bool do_dbranch(DisasContext *ctx, int64_t disp,
     if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
         install_link(ctx, link, false);
         ctx->iaoq_n = dest;
+        ctx->iaoq_n_var = NULL;
         if (is_n) {
             ctx->null_cond.c = TCG_COND_ALWAYS;
         }
@@ -1863,11 +1864,6 @@ static bool do_cbranch(DisasContext *ctx, int64_t disp, bool is_n,
             ctx->null_lab = NULL;
         }
         nullify_set(ctx, n);
-        if (ctx->iaoq_n == -1) {
-            /* The temporary iaoq_n_var died at the branch above.
-               Regenerate it here instead of saving it.  */
-            tcg_gen_addi_i64(ctx->iaoq_n_var, cpu_iaoq_b, 4);
-        }
         gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
     }
 
@@ -4631,8 +4627,6 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     ctx->iaoq_f = (ctx->base.pc_first & ~iasq_f) + ctx->privilege;
     ctx->iaoq_b = (diff ? ctx->iaoq_f + diff : -1);
 #endif
-    ctx->iaoq_n = -1;
-    ctx->iaoq_n_var = NULL;
 
     ctx->zero = tcg_constant_i64(0);
 
@@ -4684,14 +4678,8 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 
         /* Set up the IA queue for the next insn.
            This will be overwritten by a branch.  */
-        if (ctx->iaoq_b == -1) {
-            ctx->iaoq_n = -1;
-            ctx->iaoq_n_var = tcg_temp_new_i64();
-            tcg_gen_addi_i64(ctx->iaoq_n_var, cpu_iaoq_b, 4);
-        } else {
-            ctx->iaoq_n = ctx->iaoq_b + 4;
-            ctx->iaoq_n_var = NULL;
-        }
+        ctx->iaoq_n_var = NULL;
+        ctx->iaoq_n = ctx->iaoq_b == -1 ? -1 : ctx->iaoq_b + 4;
 
         if (unlikely(ctx->null_cond.c == TCG_COND_ALWAYS)) {
             ctx->null_cond.c = TCG_COND_NEVER;
@@ -4742,7 +4730,13 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
                                 ? DISAS_EXIT
                                 : DISAS_IAQ_N_UPDATED);
         } else if (ctx->iaoq_b == -1) {
-            copy_iaoq_entry(ctx, cpu_iaoq_b, -1, ctx->iaoq_n_var);
+            if (ctx->iaoq_n_var) {
+                copy_iaoq_entry(ctx, cpu_iaoq_b, -1, ctx->iaoq_n_var);
+            } else {
+                tcg_gen_addi_i64(cpu_iaoq_b, cpu_iaoq_b, 4);
+                tcg_gen_andi_i64(cpu_iaoq_b, cpu_iaoq_b,
+                                 gva_offset_mask(ctx->tb_flags));
+            }
         }
         break;
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 10/43] target/hppa: Skip nullified insns in unconditional dbranch path
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (8 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 09/43] target/hppa: Delay computation of IAQ_Next Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 11/43] target/hppa: Simplify TB end Richard Henderson
                   ` (33 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 9189e0350b..6c5efb0023 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -1806,11 +1806,17 @@ static bool do_dbranch(DisasContext *ctx, int64_t disp,
 
     if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
         install_link(ctx, link, false);
-        ctx->iaoq_n = dest;
-        ctx->iaoq_n_var = NULL;
         if (is_n) {
+            if (use_nullify_skip(ctx)) {
+                nullify_set(ctx, 0);
+                gen_goto_tb(ctx, 0, dest, dest + 4);
+                ctx->base.is_jmp = DISAS_NORETURN;
+                return true;
+            }
             ctx->null_cond.c = TCG_COND_ALWAYS;
         }
+        ctx->iaoq_n = dest;
+        ctx->iaoq_n_var = NULL;
     } else {
         nullify_over(ctx);
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 11/43] target/hppa: Simplify TB end
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (9 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 10/43] target/hppa: Skip nullified insns in unconditional dbranch path Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 12/43] target/hppa: Add IASQ entries to DisasContext Richard Henderson
                   ` (32 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Minimize the amount of code in hppa_tr_translate_insn advancing the
insn queue for the next insn.  Move the goto_tb path to hppa_tr_tb_stop.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 109 +++++++++++++++++++++-------------------
 1 file changed, 57 insertions(+), 52 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 6c5efb0023..b79c44bd49 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -4700,54 +4700,31 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
         }
     }
 
-    /* Advance the insn queue.  Note that this check also detects
-       a priority change within the instruction queue.  */
-    if (ret == DISAS_NEXT && ctx->iaoq_b != ctx->iaoq_f + 4) {
-        if (use_goto_tb(ctx, ctx->iaoq_b, ctx->iaoq_n)
-            && (ctx->null_cond.c == TCG_COND_NEVER
-                || ctx->null_cond.c == TCG_COND_ALWAYS)) {
-            nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS);
-            gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
-            ctx->base.is_jmp = ret = DISAS_NORETURN;
-        } else {
-            ctx->base.is_jmp = ret = DISAS_IAQ_N_STALE;
-        }
+    /* If the TranslationBlock must end, do so. */
+    ctx->base.pc_next += 4;
+    if (ret != DISAS_NEXT) {
+        return;
     }
+    /* Note this also detects a priority change. */
+    if (ctx->iaoq_b != ctx->iaoq_f + 4) {
+        ctx->base.is_jmp = DISAS_IAQ_N_STALE;
+        return;
+    }
+
+    /*
+     * Advance the insn queue.
+     * The only exit now is DISAS_TOO_MANY from the translator loop.
+     */
     ctx->iaoq_f = ctx->iaoq_b;
     ctx->iaoq_b = ctx->iaoq_n;
-    ctx->base.pc_next += 4;
-
-    switch (ret) {
-    case DISAS_NORETURN:
-    case DISAS_IAQ_N_UPDATED:
-        break;
-
-    case DISAS_NEXT:
-    case DISAS_IAQ_N_STALE:
-    case DISAS_IAQ_N_STALE_EXIT:
-        if (ctx->iaoq_f == -1) {
-            install_iaq_entries(ctx, -1, cpu_iaoq_b,
-                                ctx->iaoq_n, ctx->iaoq_n_var);
-#ifndef CONFIG_USER_ONLY
-            tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
-#endif
-            nullify_save(ctx);
-            ctx->base.is_jmp = (ret == DISAS_IAQ_N_STALE_EXIT
-                                ? DISAS_EXIT
-                                : DISAS_IAQ_N_UPDATED);
-        } else if (ctx->iaoq_b == -1) {
-            if (ctx->iaoq_n_var) {
-                copy_iaoq_entry(ctx, cpu_iaoq_b, -1, ctx->iaoq_n_var);
-            } else {
-                tcg_gen_addi_i64(cpu_iaoq_b, cpu_iaoq_b, 4);
-                tcg_gen_andi_i64(cpu_iaoq_b, cpu_iaoq_b,
-                                 gva_offset_mask(ctx->tb_flags));
-            }
+    if (ctx->iaoq_b == -1) {
+        if (ctx->iaoq_n_var) {
+            copy_iaoq_entry(ctx, cpu_iaoq_b, -1, ctx->iaoq_n_var);
+        } else {
+            tcg_gen_addi_i64(cpu_iaoq_b, cpu_iaoq_b, 4);
+            tcg_gen_andi_i64(cpu_iaoq_b, cpu_iaoq_b,
+                             gva_offset_mask(ctx->tb_flags));
         }
-        break;
-
-    default:
-        g_assert_not_reached();
     }
 }
 
@@ -4755,23 +4732,51 @@ static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
 {
     DisasContext *ctx = container_of(dcbase, DisasContext, base);
     DisasJumpType is_jmp = ctx->base.is_jmp;
+    uint64_t fi, bi;
+    TCGv_i64 fv, bv;
+    TCGv_i64 fs;
+
+    /* Assume the insn queue has not been advanced. */
+    fi = ctx->iaoq_b;
+    fv = cpu_iaoq_b;
+    fs = fi == -1 ? cpu_iasq_b : NULL;
+    bi = ctx->iaoq_n;
+    bv = ctx->iaoq_n_var;
 
     switch (is_jmp) {
     case DISAS_NORETURN:
         break;
     case DISAS_TOO_MANY:
-    case DISAS_IAQ_N_STALE:
-    case DISAS_IAQ_N_STALE_EXIT:
-        install_iaq_entries(ctx, ctx->iaoq_f, cpu_iaoq_f,
-                            ctx->iaoq_b, cpu_iaoq_b);
-        nullify_save(ctx);
+        /* The insn queue has not been advanced. */
+        bi = fi;
+        bv = fv;
+        fi = ctx->iaoq_f;
+        fv = NULL;
+        fs = NULL;
         /* FALLTHRU */
-    case DISAS_IAQ_N_UPDATED:
-        if (is_jmp != DISAS_IAQ_N_STALE_EXIT) {
-            tcg_gen_lookup_and_goto_ptr();
+    case DISAS_IAQ_N_STALE:
+        if (use_goto_tb(ctx, fi, bi)
+            && (ctx->null_cond.c == TCG_COND_NEVER
+                || ctx->null_cond.c == TCG_COND_ALWAYS)) {
+            nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS);
+            gen_goto_tb(ctx, 0, fi, bi);
             break;
         }
         /* FALLTHRU */
+    case DISAS_IAQ_N_STALE_EXIT:
+        install_iaq_entries(ctx, fi, fv, bi, bv);
+        if (fs) {
+            tcg_gen_mov_i64(cpu_iasq_f, fs);
+        }
+        nullify_save(ctx);
+        if (is_jmp == DISAS_IAQ_N_STALE_EXIT) {
+            tcg_gen_exit_tb(NULL, 0);
+            break;
+        }
+        /* FALLTHRU */
+    case DISAS_IAQ_N_UPDATED:
+        tcg_gen_lookup_and_goto_ptr();
+        break;
     case DISAS_EXIT:
         tcg_gen_exit_tb(NULL, 0);
         break;
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 12/43] target/hppa: Add IASQ entries to DisasContext
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (10 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 11/43] target/hppa: Simplify TB end Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 13/43] target/hppa: Add space arguments to install_iaq_entries Richard Henderson
                   ` (31 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Add variable to track space changes to IAQ.  So far, no such changes
are introduced, but the new checks vs ctx->iasq_b may eliminate an
unnecessary copy to cpu_iasq_f with e.g. BLR.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 39 ++++++++++++++++++++++++++++++---------
 1 file changed, 30 insertions(+), 9 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index b79c44bd49..b4e384baa3 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -50,6 +50,13 @@ typedef struct DisasContext {
     uint64_t iaoq_b;
     uint64_t iaoq_n;
     TCGv_i64 iaoq_n_var;
+    /*
+     * Null when IASQ_Back unchanged from IASQ_Front,
+     * or cpu_iasq_b, when IASQ_Back has been changed.
+     */
+    TCGv_i64 iasq_b;
+    /* Null when IASQ_Next unchanged from IASQ_Back, or set by branch. */
+    TCGv_i64 iasq_n;
 
     DisasCond null_cond;
     TCGLabel *null_lab;
@@ -3917,12 +3924,12 @@ static bool trans_be(DisasContext *ctx, arg_be *a)
     if (a->n && use_nullify_skip(ctx)) {
         install_iaq_entries(ctx, -1, tmp, -1, NULL);
         tcg_gen_mov_i64(cpu_iasq_f, new_spc);
-        tcg_gen_mov_i64(cpu_iasq_b, cpu_iasq_f);
+        tcg_gen_mov_i64(cpu_iasq_b, new_spc);
         nullify_set(ctx, 0);
     } else {
         install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, -1, tmp);
-        if (ctx->iaoq_b == -1) {
-            tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
+        if (ctx->iasq_b) {
+            tcg_gen_mov_i64(cpu_iasq_f, ctx->iasq_b);
         }
         tcg_gen_mov_i64(cpu_iasq_b, new_spc);
         nullify_set(ctx, a->n);
@@ -4036,8 +4043,8 @@ static bool trans_bve(DisasContext *ctx, arg_bve *a)
 
     install_link(ctx, a->l, false);
     install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, -1, dest);
-    if (ctx->iaoq_b == -1) {
-        tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
+    if (ctx->iasq_b) {
+        tcg_gen_mov_i64(cpu_iasq_f, ctx->iasq_b);
     }
     tcg_gen_mov_i64(cpu_iasq_b, space_select(ctx, 0, dest));
     nullify_set(ctx, a->n);
@@ -4618,6 +4625,7 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     ctx->mmu_idx = MMU_USER_IDX;
     ctx->iaoq_f = ctx->base.pc_first | ctx->privilege;
     ctx->iaoq_b = ctx->base.tb->cs_base | ctx->privilege;
+    ctx->iasq_b = NULL;
     ctx->unalign = (ctx->tb_flags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN);
 #else
     ctx->privilege = (ctx->tb_flags >> TB_FLAG_PRIV_SHIFT) & 3;
@@ -4632,6 +4640,7 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
 
     ctx->iaoq_f = (ctx->base.pc_first & ~iasq_f) + ctx->privilege;
     ctx->iaoq_b = (diff ? ctx->iaoq_f + diff : -1);
+    ctx->iasq_b = (diff ? NULL : cpu_iasq_b);
 #endif
 
     ctx->zero = tcg_constant_i64(0);
@@ -4684,6 +4693,7 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 
         /* Set up the IA queue for the next insn.
            This will be overwritten by a branch.  */
+        ctx->iasq_n = NULL;
         ctx->iaoq_n_var = NULL;
         ctx->iaoq_n = ctx->iaoq_b == -1 ? -1 : ctx->iaoq_b + 4;
 
@@ -4706,7 +4716,7 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
         return;
     }
     /* Note this also detects a priority change. */
-    if (ctx->iaoq_b != ctx->iaoq_f + 4) {
+    if (ctx->iaoq_b != ctx->iaoq_f + 4 || ctx->iasq_b) {
         ctx->base.is_jmp = DISAS_IAQ_N_STALE;
         return;
     }
@@ -4726,6 +4736,10 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
                              gva_offset_mask(ctx->tb_flags));
         }
     }
+    if (ctx->iasq_n) {
+        tcg_gen_mov_i64(cpu_iasq_b, ctx->iasq_n);
+        ctx->iasq_b = cpu_iasq_b;
+    }
 }
 
 static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
@@ -4734,14 +4748,15 @@ static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
     DisasJumpType is_jmp = ctx->base.is_jmp;
     uint64_t fi, bi;
     TCGv_i64 fv, bv;
-    TCGv_i64 fs;
+    TCGv_i64 fs, bs;
 
     /* Assume the insn queue has not been advanced. */
     fi = ctx->iaoq_b;
     fv = cpu_iaoq_b;
-    fs = fi == -1 ? cpu_iasq_b : NULL;
+    fs = ctx->iasq_b;
     bi = ctx->iaoq_n;
     bv = ctx->iaoq_n_var;
+    bs = ctx->iasq_n;
 
     switch (is_jmp) {
     case DISAS_NORETURN:
@@ -4750,12 +4765,15 @@ static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
         /* The insn queue has not been advanced. */
         bi = fi;
         bv = fv;
+        bs = fs;
         fi = ctx->iaoq_f;
         fv = NULL;
         fs = NULL;
         /* FALLTHRU */
     case DISAS_IAQ_N_STALE:
-        if (use_goto_tb(ctx, fi, bi)
+        if (fs == NULL
+            && bs == NULL
+            && use_goto_tb(ctx, fi, bi)
             && (ctx->null_cond.c == TCG_COND_NEVER
                 || ctx->null_cond.c == TCG_COND_ALWAYS)) {
             nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS);
@@ -4768,6 +4786,9 @@ static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
         if (fs) {
             tcg_gen_mov_i64(cpu_iasq_f, fs);
         }
+        if (bs) {
+            tcg_gen_mov_i64(cpu_iasq_b, bs);
+        }
         nullify_save(ctx);
         if (is_jmp == DISAS_IAQ_N_STALE_EXIT) {
             tcg_gen_exit_tb(NULL, 0);
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 13/43] target/hppa: Add space arguments to install_iaq_entries
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (11 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 12/43] target/hppa: Add IASQ entries to DisasContext Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 14/43] target/hppa: Add space argument to do_ibranch Richard Henderson
                   ` (30 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Move space assighments to a central location.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 58 +++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 31 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index b4e384baa3..eed0f92db4 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -624,8 +624,9 @@ static void copy_iaoq_entry(DisasContext *ctx, TCGv_i64 dest,
     }
 }
 
-static void install_iaq_entries(DisasContext *ctx, uint64_t bi, TCGv_i64 bv,
-                                uint64_t ni, TCGv_i64 nv)
+static void install_iaq_entries(DisasContext *ctx,
+                                uint64_t bi, TCGv_i64 bv, TCGv_i64 bs,
+                                uint64_t ni, TCGv_i64 nv, TCGv_i64 ns)
 {
     copy_iaoq_entry(ctx, cpu_iaoq_f, bi, bv);
 
@@ -639,6 +640,12 @@ static void install_iaq_entries(DisasContext *ctx, uint64_t bi, TCGv_i64 bv,
         tcg_gen_andi_i64(cpu_iaoq_b, cpu_iaoq_b,
                          gva_offset_mask(ctx->tb_flags));
     }
+    if (bs) {
+        tcg_gen_mov_i64(cpu_iasq_f, bs);
+    }
+    if (ns || bs) {
+        tcg_gen_mov_i64(cpu_iasq_b, ns ? ns : bs);
+    }
 }
 
 static void install_link(DisasContext *ctx, unsigned link, bool with_sr0)
@@ -671,7 +678,8 @@ static void gen_excp_1(int exception)
 
 static void gen_excp(DisasContext *ctx, int exception)
 {
-    install_iaq_entries(ctx, ctx->iaoq_f, cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
+    install_iaq_entries(ctx, ctx->iaoq_f, cpu_iaoq_f, NULL,
+                        ctx->iaoq_b, cpu_iaoq_b, NULL);
     nullify_save(ctx);
     gen_excp_1(exception);
     ctx->base.is_jmp = DISAS_NORETURN;
@@ -725,10 +733,11 @@ static void gen_goto_tb(DisasContext *ctx, int which,
 {
     if (use_goto_tb(ctx, b, n)) {
         tcg_gen_goto_tb(which);
-        install_iaq_entries(ctx, b, NULL, n, NULL);
+        install_iaq_entries(ctx, b, NULL, NULL, n, NULL, NULL);
         tcg_gen_exit_tb(ctx->base.tb, which);
     } else {
-        install_iaq_entries(ctx, b, cpu_iaoq_b, n, ctx->iaoq_n_var);
+        install_iaq_entries(ctx, b, cpu_iaoq_b, ctx->iasq_b,
+                            n, ctx->iaoq_n_var, ctx->iasq_n);
         tcg_gen_lookup_and_goto_ptr();
     }
 }
@@ -1917,7 +1926,7 @@ static bool do_ibranch(DisasContext *ctx, TCGv_i64 dest,
         install_link(ctx, link, false);
         if (is_n) {
             if (use_nullify_skip(ctx)) {
-                install_iaq_entries(ctx, -1, next, -1, NULL);
+                install_iaq_entries(ctx, -1, next, NULL, -1, NULL, NULL);
                 nullify_set(ctx, 0);
                 ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
                 return true;
@@ -1936,10 +1945,11 @@ static bool do_ibranch(DisasContext *ctx, TCGv_i64 dest,
 
     install_link(ctx, link, false);
     if (is_n && use_nullify_skip(ctx)) {
-        install_iaq_entries(ctx, -1, next, -1, NULL);
+        install_iaq_entries(ctx, -1, next, NULL, -1, NULL, NULL);
         nullify_set(ctx, 0);
     } else {
-        install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, -1, next);
+        install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, ctx->iasq_b,
+                            -1, next, NULL);
         nullify_set(ctx, is_n);
     }
 
@@ -2027,7 +2037,7 @@ static void do_page_zero(DisasContext *ctx)
         tcg_gen_st_i64(cpu_gr[26], tcg_env, offsetof(CPUHPPAState, cr[27]));
         tmp = tcg_temp_new_i64();
         tcg_gen_ori_i64(tmp, cpu_gr[31], 3);
-        install_iaq_entries(ctx, -1, tmp, -1, NULL);
+        install_iaq_entries(ctx, -1, tmp, NULL, -1, NULL, NULL);
         ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
         break;
 
@@ -2771,8 +2781,8 @@ static bool trans_or(DisasContext *ctx, arg_rrr_cf_d *a)
             nullify_over(ctx);
 
             /* Advance the instruction queue.  */
-            install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b,
-                                ctx->iaoq_n, ctx->iaoq_n_var);
+            install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, ctx->iasq_b,
+                                ctx->iaoq_n, ctx->iaoq_n_var, ctx->iasq_n);
             nullify_set(ctx, 0);
 
             /* Tell the qemu main loop to halt until this cpu has work.  */
@@ -3922,16 +3932,11 @@ static bool trans_be(DisasContext *ctx, arg_be *a)
     load_spr(ctx, new_spc, a->sp);
     install_link(ctx, a->l, true);
     if (a->n && use_nullify_skip(ctx)) {
-        install_iaq_entries(ctx, -1, tmp, -1, NULL);
-        tcg_gen_mov_i64(cpu_iasq_f, new_spc);
-        tcg_gen_mov_i64(cpu_iasq_b, new_spc);
+        install_iaq_entries(ctx, -1, tmp, new_spc, -1, NULL, new_spc);
         nullify_set(ctx, 0);
     } else {
-        install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, -1, tmp);
-        if (ctx->iasq_b) {
-            tcg_gen_mov_i64(cpu_iasq_f, ctx->iasq_b);
-        }
-        tcg_gen_mov_i64(cpu_iasq_b, new_spc);
+        install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, ctx->iasq_b,
+                            -1, tmp, new_spc);
         nullify_set(ctx, a->n);
     }
     tcg_gen_lookup_and_goto_ptr();
@@ -4042,11 +4047,8 @@ static bool trans_bve(DisasContext *ctx, arg_bve *a)
     dest = do_ibranch_priv(ctx, dest);
 
     install_link(ctx, a->l, false);
-    install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, -1, dest);
-    if (ctx->iasq_b) {
-        tcg_gen_mov_i64(cpu_iasq_f, ctx->iasq_b);
-    }
-    tcg_gen_mov_i64(cpu_iasq_b, space_select(ctx, 0, dest));
+    install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, ctx->iasq_b,
+                        -1, dest, space_select(ctx, 0, dest));
     nullify_set(ctx, a->n);
     tcg_gen_lookup_and_goto_ptr();
     ctx->base.is_jmp = DISAS_NORETURN;
@@ -4782,13 +4784,7 @@ static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
         }
         /* FALLTHRU */
     case DISAS_IAQ_N_STALE_EXIT:
-        install_iaq_entries(ctx, fi, fv, bi, bv);
-        if (fs) {
-            tcg_gen_mov_i64(cpu_iasq_f, fs);
-        }
-        if (bs) {
-            tcg_gen_mov_i64(cpu_iasq_b, bs);
-        }
+        install_iaq_entries(ctx, fi, fv, fs, bi, bv, bs);
         nullify_save(ctx);
         if (is_jmp == DISAS_IAQ_N_STALE_EXIT) {
             tcg_gen_exit_tb(NULL, 0);
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 14/43] target/hppa: Add space argument to do_ibranch
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (12 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 13/43] target/hppa: Add space arguments to install_iaq_entries Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 15/43] target/hppa: Use umax in do_ibranch_priv Richard Henderson
                   ` (29 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

This allows unification of BE, BLR, BV, BVE with a common helper.
Since we can now track space with IAQ_Next, we can now let the
TranslationBlock continue across the delay slot with BE, BVE.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 76 ++++++++++++++---------------------------
 1 file changed, 26 insertions(+), 50 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index eed0f92db4..1758c6e1d4 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -1914,8 +1914,8 @@ static bool do_cbranch(DisasContext *ctx, int64_t disp, bool is_n,
 
 /* Emit an unconditional branch to an indirect target.  This handles
    nullification of the branch itself.  */
-static bool do_ibranch(DisasContext *ctx, TCGv_i64 dest,
-                       unsigned link, bool is_n)
+static bool do_ibranch(DisasContext *ctx, TCGv_i64 dest, TCGv_i64 dspc,
+                       unsigned link, bool with_sr0, bool is_n)
 {
     TCGv_i64 next;
 
@@ -1923,10 +1923,10 @@ static bool do_ibranch(DisasContext *ctx, TCGv_i64 dest,
         next = tcg_temp_new_i64();
         tcg_gen_mov_i64(next, dest);
 
-        install_link(ctx, link, false);
+        install_link(ctx, link, with_sr0);
         if (is_n) {
             if (use_nullify_skip(ctx)) {
-                install_iaq_entries(ctx, -1, next, NULL, -1, NULL, NULL);
+                install_iaq_entries(ctx, -1, next, dspc, -1, NULL, NULL);
                 nullify_set(ctx, 0);
                 ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
                 return true;
@@ -1935,6 +1935,7 @@ static bool do_ibranch(DisasContext *ctx, TCGv_i64 dest,
         }
         ctx->iaoq_n = -1;
         ctx->iaoq_n_var = next;
+        ctx->iasq_n = dspc;
         return true;
     }
 
@@ -1943,13 +1944,13 @@ static bool do_ibranch(DisasContext *ctx, TCGv_i64 dest,
     next = tcg_temp_new_i64();
     tcg_gen_mov_i64(next, dest);
 
-    install_link(ctx, link, false);
+    install_link(ctx, link, with_sr0);
     if (is_n && use_nullify_skip(ctx)) {
-        install_iaq_entries(ctx, -1, next, NULL, -1, NULL, NULL);
+        install_iaq_entries(ctx, -1, next, dspc, -1, NULL, NULL);
         nullify_set(ctx, 0);
     } else {
         install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, ctx->iasq_b,
-                            -1, next, NULL);
+                            -1, next, dspc);
         nullify_set(ctx, is_n);
     }
 
@@ -3916,33 +3917,18 @@ static bool trans_depi_sar(DisasContext *ctx, arg_depi_sar *a)
 
 static bool trans_be(DisasContext *ctx, arg_be *a)
 {
-    TCGv_i64 tmp;
+    TCGv_i64 dest = tcg_temp_new_i64();
+    TCGv_i64 space = NULL;
 
-    tmp = tcg_temp_new_i64();
-    tcg_gen_addi_i64(tmp, load_gpr(ctx, a->b), a->disp);
-    tmp = do_ibranch_priv(ctx, tmp);
+    tcg_gen_addi_i64(dest, load_gpr(ctx, a->b), a->disp);
+    dest = do_ibranch_priv(ctx, dest);
 
-#ifdef CONFIG_USER_ONLY
-    return do_ibranch(ctx, tmp, a->l, a->n);
-#else
-    TCGv_i64 new_spc = tcg_temp_new_i64();
-
-    nullify_over(ctx);
-
-    load_spr(ctx, new_spc, a->sp);
-    install_link(ctx, a->l, true);
-    if (a->n && use_nullify_skip(ctx)) {
-        install_iaq_entries(ctx, -1, tmp, new_spc, -1, NULL, new_spc);
-        nullify_set(ctx, 0);
-    } else {
-        install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, ctx->iasq_b,
-                            -1, tmp, new_spc);
-        nullify_set(ctx, a->n);
-    }
-    tcg_gen_lookup_and_goto_ptr();
-    ctx->base.is_jmp = DISAS_NORETURN;
-    return nullify_end(ctx);
+#ifndef CONFIG_USER_ONLY
+    space = tcg_temp_new_i64();
+    load_spr(ctx, space, a->sp);
 #endif
+
+    return do_ibranch(ctx, dest, space, a->l, true, a->n);
 }
 
 static bool trans_bl(DisasContext *ctx, arg_bl *a)
@@ -4011,7 +3997,7 @@ static bool trans_blr(DisasContext *ctx, arg_blr *a)
         tcg_gen_shli_i64(tmp, load_gpr(ctx, a->x), 3);
         tcg_gen_addi_i64(tmp, tmp, ctx->iaoq_f + 8);
         /* The computation here never changes privilege level.  */
-        return do_ibranch(ctx, tmp, a->l, a->n);
+        return do_ibranch(ctx, tmp, NULL, a->l, false, a->n);
     } else {
         /* BLR R0,RX is a good way to load PC+8 into RX.  */
         return do_dbranch(ctx, 0, a->l, a->n);
@@ -4030,30 +4016,20 @@ static bool trans_bv(DisasContext *ctx, arg_bv *a)
         tcg_gen_add_i64(dest, dest, load_gpr(ctx, a->b));
     }
     dest = do_ibranch_priv(ctx, dest);
-    return do_ibranch(ctx, dest, 0, a->n);
+    return do_ibranch(ctx, dest, NULL, 0, false, a->n);
 }
 
 static bool trans_bve(DisasContext *ctx, arg_bve *a)
 {
-    TCGv_i64 dest;
+    TCGv_i64 b = load_gpr(ctx, a->b);
+    TCGv_i64 dest = do_ibranch_priv(ctx, b);
+    TCGv_i64 space = NULL;
 
-#ifdef CONFIG_USER_ONLY
-    dest = do_ibranch_priv(ctx, load_gpr(ctx, a->b));
-    return do_ibranch(ctx, dest, a->l, a->n);
-#else
-    nullify_over(ctx);
-    dest = tcg_temp_new_i64();
-    tcg_gen_mov_i64(dest, load_gpr(ctx, a->b));
-    dest = do_ibranch_priv(ctx, dest);
-
-    install_link(ctx, a->l, false);
-    install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, ctx->iasq_b,
-                        -1, dest, space_select(ctx, 0, dest));
-    nullify_set(ctx, a->n);
-    tcg_gen_lookup_and_goto_ptr();
-    ctx->base.is_jmp = DISAS_NORETURN;
-    return nullify_end(ctx);
+#ifndef CONFIG_USER_ONLY
+    space = space_select(ctx, 0, b);
 #endif
+
+    return do_ibranch(ctx, dest, space, a->l, false, a->n);
 }
 
 static bool trans_nopbts(DisasContext *ctx, arg_nopbts *a)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 15/43] target/hppa: Use umax in do_ibranch_priv
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (13 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 14/43] target/hppa: Add space argument to do_ibranch Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 16/43] target/hppa: Always make a copy " Richard Henderson
                   ` (28 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé

Using umax is clearer than the same operation using movcond.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 1758c6e1d4..e9ba792065 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -1982,7 +1982,7 @@ static TCGv_i64 do_ibranch_priv(DisasContext *ctx, TCGv_i64 offset)
         dest = tcg_temp_new_i64();
         tcg_gen_andi_i64(dest, offset, -4);
         tcg_gen_ori_i64(dest, dest, ctx->privilege);
-        tcg_gen_movcond_i64(TCG_COND_GTU, dest, dest, offset, dest, offset);
+        tcg_gen_umax_i64(dest, dest, offset);
         break;
     }
     return dest;
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 16/43] target/hppa: Always make a copy in do_ibranch_priv
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (14 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 15/43] target/hppa: Use umax in do_ibranch_priv Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 17/43] target/hppa: Introduce and use DisasIAQE for branch management Richard Henderson
                   ` (27 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé

This simplifies callers, which might otherwise have
to make another copy.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index e9ba792065..1ede4bd725 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -1968,18 +1968,17 @@ static bool do_ibranch(DisasContext *ctx, TCGv_i64 dest, TCGv_i64 dspc,
  */
 static TCGv_i64 do_ibranch_priv(DisasContext *ctx, TCGv_i64 offset)
 {
-    TCGv_i64 dest;
+    TCGv_i64 dest = tcg_temp_new_i64();
     switch (ctx->privilege) {
     case 0:
         /* Privilege 0 is maximum and is allowed to decrease.  */
-        return offset;
+        tcg_gen_mov_i64(dest, offset);
+        break;
     case 3:
         /* Privilege 3 is minimum and is never allowed to increase.  */
-        dest = tcg_temp_new_i64();
         tcg_gen_ori_i64(dest, offset, 3);
         break;
     default:
-        dest = tcg_temp_new_i64();
         tcg_gen_andi_i64(dest, offset, -4);
         tcg_gen_ori_i64(dest, dest, ctx->privilege);
         tcg_gen_umax_i64(dest, dest, offset);
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 17/43] target/hppa: Introduce and use DisasIAQE for branch management
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (15 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 16/43] target/hppa: Always make a copy " Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 18/43] target/hppa: Use displacements in DisasIAQE Richard Henderson
                   ` (26 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Wrap offset and space together in one structure, ensuring
that they're copied together as required.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 378 +++++++++++++++++++++-------------------
 1 file changed, 198 insertions(+), 180 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 1ede4bd725..e0e4db75ee 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -42,21 +42,23 @@ typedef struct DisasCond {
     TCGv_i64 a0, a1;
 } DisasCond;
 
+typedef struct DisasIAQE {
+    /* IASQ; may be null for no change from TB. */
+    TCGv_i64 space;
+    /* IAOQ base; may be null for immediate absolute address. */
+    TCGv_i64 base;
+    /* IAOQ addend; absolute immedate address if base is null. */
+    int64_t disp;
+} DisasIAQE;
+
 typedef struct DisasContext {
     DisasContextBase base;
     CPUState *cs;
 
-    uint64_t iaoq_f;
-    uint64_t iaoq_b;
-    uint64_t iaoq_n;
-    TCGv_i64 iaoq_n_var;
-    /*
-     * Null when IASQ_Back unchanged from IASQ_Front,
-     * or cpu_iasq_b, when IASQ_Back has been changed.
-     */
-    TCGv_i64 iasq_b;
-    /* Null when IASQ_Next unchanged from IASQ_Back, or set by branch. */
-    TCGv_i64 iasq_n;
+    /* IAQ_Front, IAQ_Back. */
+    DisasIAQE iaq_f, iaq_b;
+    /* IAQ_Next, for jumps, otherwise null for simple advance. */
+    DisasIAQE iaq_j, *iaq_n;
 
     DisasCond null_cond;
     TCGLabel *null_lab;
@@ -602,49 +604,67 @@ static bool nullify_end(DisasContext *ctx)
     return true;
 }
 
+static bool iaqe_variable(const DisasIAQE *e)
+{
+    return e->base || e->space;
+}
+
+static DisasIAQE iaqe_incr(const DisasIAQE *e, int64_t disp)
+{
+    return (DisasIAQE){
+        .space = e->space,
+        .base = e->base,
+        .disp = e->disp + disp,
+    };
+}
+
+static DisasIAQE iaqe_branchi(DisasContext *ctx, int64_t disp)
+{
+    return (DisasIAQE){
+        .space = ctx->iaq_b.space,
+        .disp = ctx->iaq_f.disp + 8 + disp,
+    };
+}
+
+static DisasIAQE iaqe_next_absv(DisasContext *ctx, TCGv_i64 var)
+{
+    return (DisasIAQE){
+        .space = ctx->iaq_b.space,
+        .base = var,
+    };
+}
+
 static void copy_iaoq_entry(DisasContext *ctx, TCGv_i64 dest,
-                            uint64_t ival, TCGv_i64 vval)
+                            const DisasIAQE *src)
 {
     uint64_t mask = gva_offset_mask(ctx->tb_flags);
 
-    if (ival != -1) {
-        tcg_gen_movi_i64(dest, ival & mask);
-        return;
-    }
-    tcg_debug_assert(vval != NULL);
-
-    /*
-     * We know that the IAOQ is already properly masked.
-     * This optimization is primarily for "iaoq_f = iaoq_b".
-     */
-    if (vval == cpu_iaoq_f || vval == cpu_iaoq_b) {
-        tcg_gen_mov_i64(dest, vval);
+    if (src->base == NULL) {
+        tcg_gen_movi_i64(dest, src->disp & mask);
+    } else if (src->disp == 0) {
+        tcg_gen_andi_i64(dest, src->base, mask);
     } else {
-        tcg_gen_andi_i64(dest, vval, mask);
+        tcg_gen_addi_i64(dest, src->base, src->disp);
+        tcg_gen_andi_i64(dest, dest, mask);
     }
 }
 
-static void install_iaq_entries(DisasContext *ctx,
-                                uint64_t bi, TCGv_i64 bv, TCGv_i64 bs,
-                                uint64_t ni, TCGv_i64 nv, TCGv_i64 ns)
+static void install_iaq_entries(DisasContext *ctx, const DisasIAQE *f,
+                                const DisasIAQE *b)
 {
-    copy_iaoq_entry(ctx, cpu_iaoq_f, bi, bv);
+    DisasIAQE b_next;
 
-    /* Allow ni variable, with nv null, to indicate a trivial advance. */
-    if (ni != -1 || nv) {
-        copy_iaoq_entry(ctx, cpu_iaoq_b, ni, nv);
-    } else if (bi != -1) {
-        copy_iaoq_entry(ctx, cpu_iaoq_b, bi + 4, NULL);
-    } else {
-        tcg_gen_addi_i64(cpu_iaoq_b, cpu_iaoq_f, 4);
-        tcg_gen_andi_i64(cpu_iaoq_b, cpu_iaoq_b,
-                         gva_offset_mask(ctx->tb_flags));
+    if (b == NULL) {
+        b_next = iaqe_incr(f, 4);
+        b = &b_next;
     }
-    if (bs) {
-        tcg_gen_mov_i64(cpu_iasq_f, bs);
+    copy_iaoq_entry(ctx, cpu_iaoq_f, f);
+    copy_iaoq_entry(ctx, cpu_iaoq_b, b);
+    if (f->space) {
+        tcg_gen_mov_i64(cpu_iasq_f, f->space);
     }
-    if (ns || bs) {
-        tcg_gen_mov_i64(cpu_iasq_b, ns ? ns : bs);
+    if (b->space || f->space) {
+        tcg_gen_mov_i64(cpu_iasq_b, b->space ? : f->space);
     }
 }
 
@@ -654,10 +674,11 @@ static void install_link(DisasContext *ctx, unsigned link, bool with_sr0)
     if (!link) {
         return;
     }
-    if (ctx->iaoq_b == -1) {
-        tcg_gen_addi_i64(cpu_gr[link], cpu_iaoq_b, 4);
+    if (ctx->iaq_b.base) {
+        tcg_gen_addi_i64(cpu_gr[link], ctx->iaq_b.base,
+                         ctx->iaq_b.disp + 4);
     } else {
-        tcg_gen_movi_i64(cpu_gr[link], ctx->iaoq_b + 4);
+        tcg_gen_movi_i64(cpu_gr[link], ctx->iaq_b.disp + 4);
     }
 #ifndef CONFIG_USER_ONLY
     if (with_sr0) {
@@ -666,11 +687,6 @@ static void install_link(DisasContext *ctx, unsigned link, bool with_sr0)
 #endif
 }
 
-static inline uint64_t iaoq_dest(DisasContext *ctx, int64_t disp)
-{
-    return ctx->iaoq_f + disp + 8;
-}
-
 static void gen_excp_1(int exception)
 {
     gen_helper_excp(tcg_env, tcg_constant_i32(exception));
@@ -678,8 +694,7 @@ static void gen_excp_1(int exception)
 
 static void gen_excp(DisasContext *ctx, int exception)
 {
-    install_iaq_entries(ctx, ctx->iaoq_f, cpu_iaoq_f, NULL,
-                        ctx->iaoq_b, cpu_iaoq_b, NULL);
+    install_iaq_entries(ctx, &ctx->iaq_f, &ctx->iaq_b);
     nullify_save(ctx);
     gen_excp_1(exception);
     ctx->base.is_jmp = DISAS_NORETURN;
@@ -711,10 +726,12 @@ static bool gen_illegal(DisasContext *ctx)
     } while (0)
 #endif
 
-static bool use_goto_tb(DisasContext *ctx, uint64_t bofs, uint64_t nofs)
+static bool use_goto_tb(DisasContext *ctx, const DisasIAQE *f,
+                        const DisasIAQE *b)
 {
-    return (bofs != -1 && nofs != -1 &&
-            translator_use_goto_tb(&ctx->base, bofs));
+    return (!iaqe_variable(f) &&
+            (b == NULL || !iaqe_variable(b)) &&
+            translator_use_goto_tb(&ctx->base, f->disp));
 }
 
 /* If the next insn is to be nullified, and it's on the same page,
@@ -724,20 +741,19 @@ static bool use_goto_tb(DisasContext *ctx, uint64_t bofs, uint64_t nofs)
 static bool use_nullify_skip(DisasContext *ctx)
 {
     return (!(tb_cflags(ctx->base.tb) & CF_BP_PAGE)
-            && ctx->iaoq_b != -1
-            && is_same_page(&ctx->base, ctx->iaoq_b));
+            && !iaqe_variable(&ctx->iaq_b)
+            && is_same_page(&ctx->base, ctx->iaq_b.disp));
 }
 
 static void gen_goto_tb(DisasContext *ctx, int which,
-                        uint64_t b, uint64_t n)
+                        const DisasIAQE *f, const DisasIAQE *b)
 {
-    if (use_goto_tb(ctx, b, n)) {
+    if (use_goto_tb(ctx, f, b)) {
         tcg_gen_goto_tb(which);
-        install_iaq_entries(ctx, b, NULL, NULL, n, NULL, NULL);
+        install_iaq_entries(ctx, f, b);
         tcg_gen_exit_tb(ctx->base.tb, which);
     } else {
-        install_iaq_entries(ctx, b, cpu_iaoq_b, ctx->iasq_b,
-                            n, ctx->iaoq_n_var, ctx->iasq_n);
+        install_iaq_entries(ctx, f, b);
         tcg_gen_lookup_and_goto_ptr();
     }
 }
@@ -1818,37 +1834,35 @@ static bool do_fop_dedd(DisasContext *ctx, unsigned rt,
 static bool do_dbranch(DisasContext *ctx, int64_t disp,
                        unsigned link, bool is_n)
 {
-    uint64_t dest = iaoq_dest(ctx, disp);
+    ctx->iaq_j = iaqe_branchi(ctx, disp);
 
     if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
         install_link(ctx, link, false);
         if (is_n) {
             if (use_nullify_skip(ctx)) {
                 nullify_set(ctx, 0);
-                gen_goto_tb(ctx, 0, dest, dest + 4);
+                gen_goto_tb(ctx, 0, &ctx->iaq_j, NULL);
                 ctx->base.is_jmp = DISAS_NORETURN;
                 return true;
             }
             ctx->null_cond.c = TCG_COND_ALWAYS;
         }
-        ctx->iaoq_n = dest;
-        ctx->iaoq_n_var = NULL;
+        ctx->iaq_n = &ctx->iaq_j;
     } else {
         nullify_over(ctx);
 
         install_link(ctx, link, false);
         if (is_n && use_nullify_skip(ctx)) {
             nullify_set(ctx, 0);
-            gen_goto_tb(ctx, 0, dest, dest + 4);
+            gen_goto_tb(ctx, 0, &ctx->iaq_j, NULL);
         } else {
             nullify_set(ctx, is_n);
-            gen_goto_tb(ctx, 0, ctx->iaoq_b, dest);
+            gen_goto_tb(ctx, 0, &ctx->iaq_b, &ctx->iaq_j);
         }
-
         nullify_end(ctx);
 
         nullify_set(ctx, 0);
-        gen_goto_tb(ctx, 1, ctx->iaoq_b, ctx->iaoq_n);
+        gen_goto_tb(ctx, 1, &ctx->iaq_b, NULL);
         ctx->base.is_jmp = DISAS_NORETURN;
     }
     return true;
@@ -1859,7 +1873,7 @@ static bool do_dbranch(DisasContext *ctx, int64_t disp,
 static bool do_cbranch(DisasContext *ctx, int64_t disp, bool is_n,
                        DisasCond *cond)
 {
-    uint64_t dest = iaoq_dest(ctx, disp);
+    DisasIAQE next;
     TCGLabel *taken = NULL;
     TCGCond c = cond->c;
     bool n;
@@ -1879,26 +1893,29 @@ static bool do_cbranch(DisasContext *ctx, int64_t disp, bool is_n,
     n = is_n && disp < 0;
     if (n && use_nullify_skip(ctx)) {
         nullify_set(ctx, 0);
-        gen_goto_tb(ctx, 0, ctx->iaoq_n, ctx->iaoq_n + 4);
+        next = iaqe_incr(&ctx->iaq_b, 4);
+        gen_goto_tb(ctx, 0, &next, NULL);
     } else {
         if (!n && ctx->null_lab) {
             gen_set_label(ctx->null_lab);
             ctx->null_lab = NULL;
         }
         nullify_set(ctx, n);
-        gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
+        gen_goto_tb(ctx, 0, &ctx->iaq_b, NULL);
     }
 
     gen_set_label(taken);
 
     /* Taken: Condition satisfied; nullify on forward branches.  */
     n = is_n && disp >= 0;
+
+    next = iaqe_branchi(ctx, disp);
     if (n && use_nullify_skip(ctx)) {
         nullify_set(ctx, 0);
-        gen_goto_tb(ctx, 1, dest, dest + 4);
+        gen_goto_tb(ctx, 1, &next, NULL);
     } else {
         nullify_set(ctx, n);
-        gen_goto_tb(ctx, 1, ctx->iaoq_b, dest);
+        gen_goto_tb(ctx, 1, &ctx->iaq_b, &next);
     }
 
     /* Not taken: the branch itself was nullified.  */
@@ -1912,45 +1929,36 @@ static bool do_cbranch(DisasContext *ctx, int64_t disp, bool is_n,
     return true;
 }
 
-/* Emit an unconditional branch to an indirect target.  This handles
-   nullification of the branch itself.  */
-static bool do_ibranch(DisasContext *ctx, TCGv_i64 dest, TCGv_i64 dspc,
-                       unsigned link, bool with_sr0, bool is_n)
+/*
+ * Emit an unconditional branch to an indirect target, in ctx->iaq_j.
+ * This handles nullification of the branch itself.
+ */
+static bool do_ibranch(DisasContext *ctx, unsigned link,
+                       bool with_sr0, bool is_n)
 {
-    TCGv_i64 next;
-
     if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
-        next = tcg_temp_new_i64();
-        tcg_gen_mov_i64(next, dest);
-
         install_link(ctx, link, with_sr0);
         if (is_n) {
             if (use_nullify_skip(ctx)) {
-                install_iaq_entries(ctx, -1, next, dspc, -1, NULL, NULL);
+                install_iaq_entries(ctx, &ctx->iaq_j, NULL);
                 nullify_set(ctx, 0);
                 ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
                 return true;
             }
             ctx->null_cond.c = TCG_COND_ALWAYS;
         }
-        ctx->iaoq_n = -1;
-        ctx->iaoq_n_var = next;
-        ctx->iasq_n = dspc;
+        ctx->iaq_n = &ctx->iaq_j;
         return true;
     }
 
     nullify_over(ctx);
 
-    next = tcg_temp_new_i64();
-    tcg_gen_mov_i64(next, dest);
-
     install_link(ctx, link, with_sr0);
     if (is_n && use_nullify_skip(ctx)) {
-        install_iaq_entries(ctx, -1, next, dspc, -1, NULL, NULL);
+        install_iaq_entries(ctx, &ctx->iaq_j, NULL);
         nullify_set(ctx, 0);
     } else {
-        install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, ctx->iasq_b,
-                            -1, next, dspc);
+        install_iaq_entries(ctx, &ctx->iaq_b, &ctx->iaq_j);
         nullify_set(ctx, is_n);
     }
 
@@ -1997,8 +2005,6 @@ static TCGv_i64 do_ibranch_priv(DisasContext *ctx, TCGv_i64 offset)
    aforementioned BE.  */
 static void do_page_zero(DisasContext *ctx)
 {
-    TCGv_i64 tmp;
-
     /* If by some means we get here with PSW[N]=1, that implies that
        the B,GATE instruction would be skipped, and we'd fault on the
        next insn within the privileged page.  */
@@ -2018,11 +2024,11 @@ static void do_page_zero(DisasContext *ctx)
        non-sequential instruction execution.  Normally the PSW[B] bit
        detects this by disallowing the B,GATE instruction to execute
        under such conditions.  */
-    if (ctx->iaoq_b != ctx->iaoq_f + 4) {
+    if (iaqe_variable(&ctx->iaq_b) || ctx->iaq_b.disp != ctx->iaq_f.disp + 4) {
         goto do_sigill;
     }
 
-    switch (ctx->iaoq_f & -4) {
+    switch (ctx->iaq_f.disp & -4) {
     case 0x00: /* Null pointer call */
         gen_excp_1(EXCP_IMP);
         ctx->base.is_jmp = DISAS_NORETURN;
@@ -2034,11 +2040,15 @@ static void do_page_zero(DisasContext *ctx)
         break;
 
     case 0xe0: /* SET_THREAD_POINTER */
-        tcg_gen_st_i64(cpu_gr[26], tcg_env, offsetof(CPUHPPAState, cr[27]));
-        tmp = tcg_temp_new_i64();
-        tcg_gen_ori_i64(tmp, cpu_gr[31], 3);
-        install_iaq_entries(ctx, -1, tmp, NULL, -1, NULL, NULL);
-        ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
+        {
+            DisasIAQE next = { .base = tcg_temp_new_i64() };
+
+            tcg_gen_st_i64(cpu_gr[26], tcg_env,
+                           offsetof(CPUHPPAState, cr[27]));
+            tcg_gen_ori_i64(next.base, cpu_gr[31], 3);
+            install_iaq_entries(ctx, &next, NULL);
+            ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
+        }
         break;
 
     case 0x100: /* SYSCALL */
@@ -2077,11 +2087,12 @@ static bool trans_sync(DisasContext *ctx, arg_sync *a)
 
 static bool trans_mfia(DisasContext *ctx, arg_mfia *a)
 {
-    unsigned rt = a->t;
-    TCGv_i64 tmp = dest_gpr(ctx, rt);
-    tcg_gen_movi_i64(tmp, ctx->iaoq_f & ~3ULL);
-    save_gpr(ctx, rt, tmp);
+    TCGv_i64 dest = dest_gpr(ctx, a->t);
 
+    copy_iaoq_entry(ctx, dest, &ctx->iaq_f);
+    tcg_gen_andi_i64(dest, dest, -4);
+
+    save_gpr(ctx, a->t, dest);
     cond_free(&ctx->null_cond);
     return true;
 }
@@ -2781,8 +2792,7 @@ static bool trans_or(DisasContext *ctx, arg_rrr_cf_d *a)
             nullify_over(ctx);
 
             /* Advance the instruction queue.  */
-            install_iaq_entries(ctx, ctx->iaoq_b, cpu_iaoq_b, ctx->iasq_b,
-                                ctx->iaoq_n, ctx->iaoq_n_var, ctx->iasq_n);
+            install_iaq_entries(ctx, &ctx->iaq_b, NULL);
             nullify_set(ctx, 0);
 
             /* Tell the qemu main loop to halt until this cpu has work.  */
@@ -3916,18 +3926,18 @@ static bool trans_depi_sar(DisasContext *ctx, arg_depi_sar *a)
 
 static bool trans_be(DisasContext *ctx, arg_be *a)
 {
-    TCGv_i64 dest = tcg_temp_new_i64();
-    TCGv_i64 space = NULL;
-
-    tcg_gen_addi_i64(dest, load_gpr(ctx, a->b), a->disp);
-    dest = do_ibranch_priv(ctx, dest);
-
 #ifndef CONFIG_USER_ONLY
-    space = tcg_temp_new_i64();
-    load_spr(ctx, space, a->sp);
+    ctx->iaq_j.space = tcg_temp_new_i64();
+    load_spr(ctx, ctx->iaq_j.space, a->sp);
 #endif
 
-    return do_ibranch(ctx, dest, space, a->l, true, a->n);
+    ctx->iaq_j.base = tcg_temp_new_i64();
+    ctx->iaq_j.disp = 0;
+
+    tcg_gen_addi_i64(ctx->iaq_j.base, load_gpr(ctx, a->b), a->disp);
+    ctx->iaq_j.base = do_ibranch_priv(ctx, ctx->iaq_j.base);
+
+    return do_ibranch(ctx, a->l, true, a->n);
 }
 
 static bool trans_bl(DisasContext *ctx, arg_bl *a)
@@ -3937,7 +3947,7 @@ static bool trans_bl(DisasContext *ctx, arg_bl *a)
 
 static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
 {
-    uint64_t dest = iaoq_dest(ctx, a->disp);
+    int64_t disp = a->disp;
 
     nullify_over(ctx);
 
@@ -3952,7 +3962,7 @@ static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
      *    b  evil
      * in which instructions at evil would run with increased privs.
      */
-    if (ctx->iaoq_b == -1 || ctx->iaoq_b != ctx->iaoq_f + 4) {
+    if (iaqe_variable(&ctx->iaq_b) || ctx->iaq_b.disp != ctx->iaq_f.disp + 4) {
         return gen_illegal(ctx);
     }
 
@@ -3970,10 +3980,11 @@ static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
         }
         /* No change for non-gateway pages or for priv decrease.  */
         if (type >= 4 && type - 4 < ctx->privilege) {
-            dest = deposit64(dest, 0, 2, type - 4);
+            disp -= ctx->privilege;
+            disp += type - 4;
         }
     } else {
-        dest &= -4;  /* priv = 0 */
+        disp -= ctx->privilege;  /* priv = 0 */
     }
 #endif
 
@@ -3986,17 +3997,23 @@ static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
         save_gpr(ctx, a->l, tmp);
     }
 
-    return do_dbranch(ctx, dest - iaoq_dest(ctx, 0), 0, a->n);
+    return do_dbranch(ctx, disp, 0, a->n);
 }
 
 static bool trans_blr(DisasContext *ctx, arg_blr *a)
 {
     if (a->x) {
-        TCGv_i64 tmp = tcg_temp_new_i64();
-        tcg_gen_shli_i64(tmp, load_gpr(ctx, a->x), 3);
-        tcg_gen_addi_i64(tmp, tmp, ctx->iaoq_f + 8);
+        DisasIAQE next = iaqe_incr(&ctx->iaq_f, 8);
+        TCGv_i64 t0 = tcg_temp_new_i64();
+        TCGv_i64 t1 = tcg_temp_new_i64();
+
         /* The computation here never changes privilege level.  */
-        return do_ibranch(ctx, tmp, NULL, a->l, false, a->n);
+        copy_iaoq_entry(ctx, t0, &next);
+        tcg_gen_shli_i64(t1, load_gpr(ctx, a->x), 3);
+        tcg_gen_add_i64(t0, t0, t1);
+
+        ctx->iaq_j = iaqe_next_absv(ctx, t0);
+        return do_ibranch(ctx, a->l, false, a->n);
     } else {
         /* BLR R0,RX is a good way to load PC+8 into RX.  */
         return do_dbranch(ctx, 0, a->l, a->n);
@@ -4015,20 +4032,22 @@ static bool trans_bv(DisasContext *ctx, arg_bv *a)
         tcg_gen_add_i64(dest, dest, load_gpr(ctx, a->b));
     }
     dest = do_ibranch_priv(ctx, dest);
-    return do_ibranch(ctx, dest, NULL, 0, false, a->n);
+    ctx->iaq_j = iaqe_next_absv(ctx, dest);
+
+    return do_ibranch(ctx, 0, false, a->n);
 }
 
 static bool trans_bve(DisasContext *ctx, arg_bve *a)
 {
     TCGv_i64 b = load_gpr(ctx, a->b);
-    TCGv_i64 dest = do_ibranch_priv(ctx, b);
-    TCGv_i64 space = NULL;
 
 #ifndef CONFIG_USER_ONLY
-    space = space_select(ctx, 0, b);
+    ctx->iaq_j.space = space_select(ctx, 0, b);
 #endif
+    ctx->iaq_j.base = do_ibranch_priv(ctx, b);
+    ctx->iaq_j.disp = 0;
 
-    return do_ibranch(ctx, dest, space, a->l, false, a->n);
+    return do_ibranch(ctx, a->l, false, a->n);
 }
 
 static bool trans_nopbts(DisasContext *ctx, arg_nopbts *a)
@@ -4600,9 +4619,8 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
 #ifdef CONFIG_USER_ONLY
     ctx->privilege = MMU_IDX_TO_PRIV(MMU_USER_IDX);
     ctx->mmu_idx = MMU_USER_IDX;
-    ctx->iaoq_f = ctx->base.pc_first | ctx->privilege;
-    ctx->iaoq_b = ctx->base.tb->cs_base | ctx->privilege;
-    ctx->iasq_b = NULL;
+    ctx->iaq_f.disp = ctx->base.pc_first | ctx->privilege;
+    ctx->iaq_b.disp = ctx->base.tb->cs_base | ctx->privilege;
     ctx->unalign = (ctx->tb_flags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN);
 #else
     ctx->privilege = (ctx->tb_flags >> TB_FLAG_PRIV_SHIFT) & 3;
@@ -4615,9 +4633,13 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     uint64_t iasq_f = cs_base & ~0xffffffffull;
     int32_t diff = cs_base;
 
-    ctx->iaoq_f = (ctx->base.pc_first & ~iasq_f) + ctx->privilege;
-    ctx->iaoq_b = (diff ? ctx->iaoq_f + diff : -1);
-    ctx->iasq_b = (diff ? NULL : cpu_iasq_b);
+    ctx->iaq_f.disp = (ctx->base.pc_first & ~iasq_f) + ctx->privilege;
+    if (diff) {
+        ctx->iaq_b.disp = ctx->iaq_f.disp + diff;
+    } else {
+        ctx->iaq_b.base = cpu_iaoq_b;
+        ctx->iaq_b.space = cpu_iasq_b;
+    }
 #endif
 
     ctx->zero = tcg_constant_i64(0);
@@ -4645,7 +4667,10 @@ static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
 {
     DisasContext *ctx = container_of(dcbase, DisasContext, base);
 
-    tcg_gen_insn_start(ctx->iaoq_f, ctx->iaoq_b, 0);
+    tcg_debug_assert(!iaqe_variable(&ctx->iaq_f));
+    tcg_gen_insn_start(ctx->iaq_f.disp,
+                       iaqe_variable(&ctx->iaq_b) ? -1 : ctx->iaq_b.disp,
+                       0);
     ctx->insn_start_updated = false;
 }
 
@@ -4668,11 +4693,12 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
            the page permissions for execute.  */
         uint32_t insn = translator_ldl(env, &ctx->base, ctx->base.pc_next);
 
-        /* Set up the IA queue for the next insn.
-           This will be overwritten by a branch.  */
-        ctx->iasq_n = NULL;
-        ctx->iaoq_n_var = NULL;
-        ctx->iaoq_n = ctx->iaoq_b == -1 ? -1 : ctx->iaoq_b + 4;
+        /*
+         * Set up the IA queue for the next insn.
+         * This will be overwritten by a branch.
+         */
+        ctx->iaq_n = NULL;
+        memset(&ctx->iaq_j, 0, sizeof(ctx->iaq_j));
 
         if (unlikely(ctx->null_cond.c == TCG_COND_ALWAYS)) {
             ctx->null_cond.c = TCG_COND_NEVER;
@@ -4693,7 +4719,8 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
         return;
     }
     /* Note this also detects a priority change. */
-    if (ctx->iaoq_b != ctx->iaoq_f + 4 || ctx->iasq_b) {
+    if (iaqe_variable(&ctx->iaq_b)
+        || ctx->iaq_b.disp != ctx->iaq_f.disp + 4) {
         ctx->base.is_jmp = DISAS_IAQ_N_STALE;
         return;
     }
@@ -4702,20 +4729,25 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
      * Advance the insn queue.
      * The only exit now is DISAS_TOO_MANY from the translator loop.
      */
-    ctx->iaoq_f = ctx->iaoq_b;
-    ctx->iaoq_b = ctx->iaoq_n;
-    if (ctx->iaoq_b == -1) {
-        if (ctx->iaoq_n_var) {
-            copy_iaoq_entry(ctx, cpu_iaoq_b, -1, ctx->iaoq_n_var);
-        } else {
-            tcg_gen_addi_i64(cpu_iaoq_b, cpu_iaoq_b, 4);
-            tcg_gen_andi_i64(cpu_iaoq_b, cpu_iaoq_b,
-                             gva_offset_mask(ctx->tb_flags));
-        }
+    ctx->iaq_f.disp = ctx->iaq_b.disp;
+    if (!ctx->iaq_n) {
+        ctx->iaq_b.disp += 4;
+        return;
     }
-    if (ctx->iasq_n) {
-        tcg_gen_mov_i64(cpu_iasq_b, ctx->iasq_n);
-        ctx->iasq_b = cpu_iasq_b;
+    /*
+     * If IAQ_Next is variable in any way, we need to copy into the
+     * IAQ_Back globals, in case the next insn raises an exception.
+     */
+    if (ctx->iaq_n->base) {
+        copy_iaoq_entry(ctx, cpu_iaoq_b, ctx->iaq_n);
+        ctx->iaq_b.base = cpu_iaoq_b;
+        ctx->iaq_b.disp = 0;
+    } else {
+        ctx->iaq_b.disp = ctx->iaq_n->disp;
+    }
+    if (ctx->iaq_n->space) {
+        tcg_gen_mov_i64(cpu_iasq_b, ctx->iaq_n->space);
+        ctx->iaq_b.space = cpu_iasq_b;
     }
 }
 
@@ -4723,43 +4755,29 @@ static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
 {
     DisasContext *ctx = container_of(dcbase, DisasContext, base);
     DisasJumpType is_jmp = ctx->base.is_jmp;
-    uint64_t fi, bi;
-    TCGv_i64 fv, bv;
-    TCGv_i64 fs, bs;
-
     /* Assume the insn queue has not been advanced. */
-    fi = ctx->iaoq_b;
-    fv = cpu_iaoq_b;
-    fs = ctx->iasq_b;
-    bi = ctx->iaoq_n;
-    bv = ctx->iaoq_n_var;
-    bs = ctx->iasq_n;
+    DisasIAQE *f = &ctx->iaq_b;
+    DisasIAQE *b = ctx->iaq_n;
 
     switch (is_jmp) {
     case DISAS_NORETURN:
         break;
     case DISAS_TOO_MANY:
         /* The insn queue has not been advanced. */
-        bi = fi;
-        bv = fv;
-        bs = fs;
-        fi = ctx->iaoq_f;
-        fv = NULL;
-        fs = NULL;
+        f = &ctx->iaq_f;
+        b = &ctx->iaq_b;
         /* FALLTHRU */
     case DISAS_IAQ_N_STALE:
-        if (fs == NULL
-            && bs == NULL
-            && use_goto_tb(ctx, fi, bi)
+        if (use_goto_tb(ctx, f, b)
             && (ctx->null_cond.c == TCG_COND_NEVER
                 || ctx->null_cond.c == TCG_COND_ALWAYS)) {
             nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS);
-            gen_goto_tb(ctx, 0, fi, bi);
+            gen_goto_tb(ctx, 0, f, b);
             break;
         }
         /* FALLTHRU */
     case DISAS_IAQ_N_STALE_EXIT:
-        install_iaq_entries(ctx, fi, fv, fs, bi, bv, bs);
+        install_iaq_entries(ctx, f, b);
         nullify_save(ctx);
         if (is_jmp == DISAS_IAQ_N_STALE_EXIT) {
             tcg_gen_exit_tb(NULL, 0);
@@ -4815,6 +4833,6 @@ static const TranslatorOps hppa_tr_ops = {
 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
                            vaddr pc, void *host_pc)
 {
-    DisasContext ctx;
+    DisasContext ctx = { };
     translator_loop(cs, tb, max_insns, pc, host_pc, &hppa_tr_ops, &ctx.base);
 }
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 18/43] target/hppa: Use displacements in DisasIAQE
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (16 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 17/43] target/hppa: Introduce and use DisasIAQE for branch management Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 19/43] target/hppa: Rename cond_make_* helpers Richard Henderson
                   ` (25 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

This is a first step in enabling CF_PCREL, but for now
we regenerate the absolute address before writeback.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 43 ++++++++++++++++++++++-------------------
 1 file changed, 23 insertions(+), 20 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index e0e4db75ee..de077e7a57 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -45,9 +45,9 @@ typedef struct DisasCond {
 typedef struct DisasIAQE {
     /* IASQ; may be null for no change from TB. */
     TCGv_i64 space;
-    /* IAOQ base; may be null for immediate absolute address. */
+    /* IAOQ base; may be null for relative address. */
     TCGv_i64 base;
-    /* IAOQ addend; absolute immedate address if base is null. */
+    /* IAOQ addend; if base is null, relative to ctx->iaoq_first. */
     int64_t disp;
 } DisasIAQE;
 
@@ -60,6 +60,9 @@ typedef struct DisasContext {
     /* IAQ_Next, for jumps, otherwise null for simple advance. */
     DisasIAQE iaq_j, *iaq_n;
 
+    /* IAOQ_Front at entry to TB. */
+    uint64_t iaoq_first;
+
     DisasCond null_cond;
     TCGLabel *null_lab;
 
@@ -640,7 +643,7 @@ static void copy_iaoq_entry(DisasContext *ctx, TCGv_i64 dest,
     uint64_t mask = gva_offset_mask(ctx->tb_flags);
 
     if (src->base == NULL) {
-        tcg_gen_movi_i64(dest, src->disp & mask);
+        tcg_gen_movi_i64(dest, (ctx->iaoq_first + src->disp) & mask);
     } else if (src->disp == 0) {
         tcg_gen_andi_i64(dest, src->base, mask);
     } else {
@@ -674,12 +677,8 @@ static void install_link(DisasContext *ctx, unsigned link, bool with_sr0)
     if (!link) {
         return;
     }
-    if (ctx->iaq_b.base) {
-        tcg_gen_addi_i64(cpu_gr[link], ctx->iaq_b.base,
-                         ctx->iaq_b.disp + 4);
-    } else {
-        tcg_gen_movi_i64(cpu_gr[link], ctx->iaq_b.disp + 4);
-    }
+    DisasIAQE next = iaqe_incr(&ctx->iaq_b, 4);
+    copy_iaoq_entry(ctx, cpu_gr[link], &next);
 #ifndef CONFIG_USER_ONLY
     if (with_sr0) {
         tcg_gen_mov_i64(cpu_sr[0], cpu_iasq_b);
@@ -731,7 +730,7 @@ static bool use_goto_tb(DisasContext *ctx, const DisasIAQE *f,
 {
     return (!iaqe_variable(f) &&
             (b == NULL || !iaqe_variable(b)) &&
-            translator_use_goto_tb(&ctx->base, f->disp));
+            translator_use_goto_tb(&ctx->base, ctx->iaoq_first + f->disp));
 }
 
 /* If the next insn is to be nullified, and it's on the same page,
@@ -742,7 +741,8 @@ static bool use_nullify_skip(DisasContext *ctx)
 {
     return (!(tb_cflags(ctx->base.tb) & CF_BP_PAGE)
             && !iaqe_variable(&ctx->iaq_b)
-            && is_same_page(&ctx->base, ctx->iaq_b.disp));
+            && (((ctx->iaoq_first + ctx->iaq_b.disp) ^ ctx->iaoq_first)
+                & TARGET_PAGE_MASK) == 0);
 }
 
 static void gen_goto_tb(DisasContext *ctx, int which,
@@ -2005,6 +2005,8 @@ static TCGv_i64 do_ibranch_priv(DisasContext *ctx, TCGv_i64 offset)
    aforementioned BE.  */
 static void do_page_zero(DisasContext *ctx)
 {
+    assert(ctx->iaq_f.disp == 0);
+
     /* If by some means we get here with PSW[N]=1, that implies that
        the B,GATE instruction would be skipped, and we'd fault on the
        next insn within the privileged page.  */
@@ -2024,11 +2026,11 @@ static void do_page_zero(DisasContext *ctx)
        non-sequential instruction execution.  Normally the PSW[B] bit
        detects this by disallowing the B,GATE instruction to execute
        under such conditions.  */
-    if (iaqe_variable(&ctx->iaq_b) || ctx->iaq_b.disp != ctx->iaq_f.disp + 4) {
+    if (iaqe_variable(&ctx->iaq_b) || ctx->iaq_b.disp != 4) {
         goto do_sigill;
     }
 
-    switch (ctx->iaq_f.disp & -4) {
+    switch (ctx->base.pc_first) {
     case 0x00: /* Null pointer call */
         gen_excp_1(EXCP_IMP);
         ctx->base.is_jmp = DISAS_NORETURN;
@@ -4619,8 +4621,8 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
 #ifdef CONFIG_USER_ONLY
     ctx->privilege = MMU_IDX_TO_PRIV(MMU_USER_IDX);
     ctx->mmu_idx = MMU_USER_IDX;
-    ctx->iaq_f.disp = ctx->base.pc_first | ctx->privilege;
-    ctx->iaq_b.disp = ctx->base.tb->cs_base | ctx->privilege;
+    ctx->iaoq_first = ctx->base.pc_first | ctx->privilege;
+    ctx->iaq_b.disp = ctx->base.tb->cs_base - ctx->base.pc_first;
     ctx->unalign = (ctx->tb_flags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN);
 #else
     ctx->privilege = (ctx->tb_flags >> TB_FLAG_PRIV_SHIFT) & 3;
@@ -4633,9 +4635,10 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     uint64_t iasq_f = cs_base & ~0xffffffffull;
     int32_t diff = cs_base;
 
-    ctx->iaq_f.disp = (ctx->base.pc_first & ~iasq_f) + ctx->privilege;
+    ctx->iaoq_first = (ctx->base.pc_first & ~iasq_f) + ctx->privilege;
+
     if (diff) {
-        ctx->iaq_b.disp = ctx->iaq_f.disp + diff;
+        ctx->iaq_b.disp = diff;
     } else {
         ctx->iaq_b.base = cpu_iaoq_b;
         ctx->iaq_b.space = cpu_iasq_b;
@@ -4668,9 +4671,9 @@ static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
     DisasContext *ctx = container_of(dcbase, DisasContext, base);
 
     tcg_debug_assert(!iaqe_variable(&ctx->iaq_f));
-    tcg_gen_insn_start(ctx->iaq_f.disp,
-                       iaqe_variable(&ctx->iaq_b) ? -1 : ctx->iaq_b.disp,
-                       0);
+    tcg_gen_insn_start(ctx->iaoq_first + ctx->iaq_f.disp,
+                       (iaqe_variable(&ctx->iaq_b) ? -1 :
+                        ctx->iaoq_first + ctx->iaq_b.disp), 0);
     ctx->insn_start_updated = false;
 }
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 19/43] target/hppa: Rename cond_make_* helpers
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (17 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 18/43] target/hppa: Use displacements in DisasIAQE Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 20/43] target/hppa: Use TCG_COND_TST* in do_cond Richard Henderson
                   ` (24 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller, Philippe Mathieu-Daudé

Use 'v' for a variable that needs copying, 't' for a temp that
doesn't need copying, and 'i' for an immediate, and use this
naming for both arguments of the comparison.  So:

   cond_make_tmp -> cond_make_tt
   cond_make_0_tmp -> cond_make_ti
   cond_make_0 -> cond_make_vi
   cond_make -> cond_make_vv

Pass 0 explictly, rather than implicitly in the function name.

Reviewed-by: Helge Deller <deller@gmx.de>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 52 ++++++++++++++++++++---------------------
 1 file changed, 26 insertions(+), 26 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index de077e7a57..07ba35001b 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -345,32 +345,32 @@ static DisasCond cond_make_n(void)
     };
 }
 
-static DisasCond cond_make_tmp(TCGCond c, TCGv_i64 a0, TCGv_i64 a1)
+static DisasCond cond_make_tt(TCGCond c, TCGv_i64 a0, TCGv_i64 a1)
 {
     assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
     return (DisasCond){ .c = c, .a0 = a0, .a1 = a1 };
 }
 
-static DisasCond cond_make_0_tmp(TCGCond c, TCGv_i64 a0)
+static DisasCond cond_make_ti(TCGCond c, TCGv_i64 a0, uint64_t imm)
 {
-    return cond_make_tmp(c, a0, tcg_constant_i64(0));
+    return cond_make_tt(c, a0, tcg_constant_i64(imm));
 }
 
-static DisasCond cond_make_0(TCGCond c, TCGv_i64 a0)
+static DisasCond cond_make_vi(TCGCond c, TCGv_i64 a0, uint64_t imm)
 {
     TCGv_i64 tmp = tcg_temp_new_i64();
     tcg_gen_mov_i64(tmp, a0);
-    return cond_make_0_tmp(c, tmp);
+    return cond_make_ti(c, tmp, imm);
 }
 
-static DisasCond cond_make(TCGCond c, TCGv_i64 a0, TCGv_i64 a1)
+static DisasCond cond_make_vv(TCGCond c, TCGv_i64 a0, TCGv_i64 a1)
 {
     TCGv_i64 t0 = tcg_temp_new_i64();
     TCGv_i64 t1 = tcg_temp_new_i64();
 
     tcg_gen_mov_i64(t0, a0);
     tcg_gen_mov_i64(t1, a1);
-    return cond_make_tmp(c, t0, t1);
+    return cond_make_tt(c, t0, t1);
 }
 
 static void cond_free(DisasCond *cond)
@@ -789,7 +789,7 @@ static DisasCond do_cond(DisasContext *ctx, unsigned cf, bool d,
             tcg_gen_ext32u_i64(tmp, res);
             res = tmp;
         }
-        cond = cond_make_0(TCG_COND_EQ, res);
+        cond = cond_make_vi(TCG_COND_EQ, res, 0);
         break;
     case 2: /* < / >=        (N ^ V / !(N ^ V) */
         tmp = tcg_temp_new_i64();
@@ -797,7 +797,7 @@ static DisasCond do_cond(DisasContext *ctx, unsigned cf, bool d,
         if (!d) {
             tcg_gen_ext32s_i64(tmp, tmp);
         }
-        cond = cond_make_0_tmp(TCG_COND_LT, tmp);
+        cond = cond_make_ti(TCG_COND_LT, tmp, 0);
         break;
     case 3: /* <= / >        (N ^ V) | Z / !((N ^ V) | Z) */
         /*
@@ -819,10 +819,10 @@ static DisasCond do_cond(DisasContext *ctx, unsigned cf, bool d,
             tcg_gen_sari_i64(tmp, tmp, 63);
             tcg_gen_and_i64(tmp, tmp, res);
         }
-        cond = cond_make_0_tmp(TCG_COND_EQ, tmp);
+        cond = cond_make_ti(TCG_COND_EQ, tmp, 0);
         break;
     case 4: /* NUV / UV      (!UV / UV) */
-        cond = cond_make_0(TCG_COND_EQ, uv);
+        cond = cond_make_vi(TCG_COND_EQ, uv, 0);
         break;
     case 5: /* ZNV / VNZ     (!UV | Z / UV & !Z) */
         tmp = tcg_temp_new_i64();
@@ -830,7 +830,7 @@ static DisasCond do_cond(DisasContext *ctx, unsigned cf, bool d,
         if (!d) {
             tcg_gen_ext32u_i64(tmp, tmp);
         }
-        cond = cond_make_0_tmp(TCG_COND_EQ, tmp);
+        cond = cond_make_ti(TCG_COND_EQ, tmp, 0);
         break;
     case 6: /* SV / NSV      (V / !V) */
         if (!d) {
@@ -838,12 +838,12 @@ static DisasCond do_cond(DisasContext *ctx, unsigned cf, bool d,
             tcg_gen_ext32s_i64(tmp, sv);
             sv = tmp;
         }
-        cond = cond_make_0(TCG_COND_LT, sv);
+        cond = cond_make_ti(TCG_COND_LT, sv, 0);
         break;
     case 7: /* OD / EV */
         tmp = tcg_temp_new_i64();
         tcg_gen_andi_i64(tmp, res, 1);
-        cond = cond_make_0_tmp(TCG_COND_NE, tmp);
+        cond = cond_make_ti(TCG_COND_NE, tmp, 0);
         break;
     default:
         g_assert_not_reached();
@@ -905,9 +905,9 @@ static DisasCond do_sub_cond(DisasContext *ctx, unsigned cf, bool d,
             tcg_gen_ext32s_i64(t1, in1);
             tcg_gen_ext32s_i64(t2, in2);
         }
-        return cond_make_tmp(tc, t1, t2);
+        return cond_make_tt(tc, t1, t2);
     }
-    return cond_make(tc, in1, in2);
+    return cond_make_vv(tc, in1, in2);
 }
 
 /*
@@ -979,9 +979,9 @@ static DisasCond do_log_cond(DisasContext *ctx, unsigned cf, bool d,
         } else {
             tcg_gen_ext32s_i64(tmp, res);
         }
-        return cond_make_0_tmp(tc, tmp);
+        return cond_make_ti(tc, tmp, 0);
     }
-    return cond_make_0(tc, res);
+    return cond_make_vi(tc, res, 0);
 }
 
 /* Similar, but for shift/extract/deposit conditions.  */
@@ -1040,7 +1040,7 @@ static DisasCond do_unit_zero_cond(unsigned cf, bool d, TCGv_i64 res)
     tcg_gen_andc_i64(tmp, tmp, res);
     tcg_gen_andi_i64(tmp, tmp, sgns);
 
-    return cond_make_0_tmp(cf & 1 ? TCG_COND_EQ : TCG_COND_NE, tmp);
+    return cond_make_ti(cf & 1 ? TCG_COND_EQ : TCG_COND_NE, tmp, 0);
 }
 
 static TCGv_i64 get_carry(DisasContext *ctx, bool d,
@@ -1454,7 +1454,7 @@ static void do_unit_addsub(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
         }
 
         tcg_gen_andi_i64(cb, cb, test_cb);
-        cond = cond_make_0_tmp(cf & 1 ? TCG_COND_EQ : TCG_COND_NE, cb);
+        cond = cond_make_ti(cf & 1 ? TCG_COND_EQ : TCG_COND_NE, cb, 0);
     }
 
     if (is_tc) {
@@ -3543,7 +3543,7 @@ static bool trans_bb_sar(DisasContext *ctx, arg_bb_sar *a)
         tcg_gen_shl_i64(tmp, tcg_r, tmp);
     }
 
-    cond = cond_make_0_tmp(a->c ? TCG_COND_GE : TCG_COND_LT, tmp);
+    cond = cond_make_ti(a->c ? TCG_COND_GE : TCG_COND_LT, tmp, 0);
     return do_cbranch(ctx, a->disp, a->n, &cond);
 }
 
@@ -3560,7 +3560,7 @@ static bool trans_bb_imm(DisasContext *ctx, arg_bb_imm *a)
     p = a->p | (a->d ? 0 : 32);
     tcg_gen_shli_i64(tmp, tcg_r, p);
 
-    cond = cond_make_0(a->c ? TCG_COND_GE : TCG_COND_LT, tmp);
+    cond = cond_make_ti(a->c ? TCG_COND_GE : TCG_COND_LT, tmp, 0);
     return do_cbranch(ctx, a->disp, a->n, &cond);
 }
 
@@ -4364,7 +4364,7 @@ static bool trans_ftest(DisasContext *ctx, arg_ftest *a)
         switch (a->c) {
         case 0: /* simple */
             tcg_gen_andi_i64(t, t, 0x4000000);
-            ctx->null_cond = cond_make_0(TCG_COND_NE, t);
+            ctx->null_cond = cond_make_ti(TCG_COND_NE, t, 0);
             goto done;
         case 2: /* rej */
             inv = true;
@@ -4394,16 +4394,16 @@ static bool trans_ftest(DisasContext *ctx, arg_ftest *a)
         if (inv) {
             TCGv_i64 c = tcg_constant_i64(mask);
             tcg_gen_or_i64(t, t, c);
-            ctx->null_cond = cond_make(TCG_COND_EQ, t, c);
+            ctx->null_cond = cond_make_tt(TCG_COND_EQ, t, c);
         } else {
             tcg_gen_andi_i64(t, t, mask);
-            ctx->null_cond = cond_make_0(TCG_COND_EQ, t);
+            ctx->null_cond = cond_make_ti(TCG_COND_EQ, t, 0);
         }
     } else {
         unsigned cbit = (a->y ^ 1) - 1;
 
         tcg_gen_extract_i64(t, t, 21 - cbit, 1);
-        ctx->null_cond = cond_make_0(TCG_COND_NE, t);
+        ctx->null_cond = cond_make_ti(TCG_COND_NE, t, 0);
     }
 
  done:
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 20/43] target/hppa: Use TCG_COND_TST* in do_cond
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (18 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 19/43] target/hppa: Rename cond_make_* helpers Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 21/43] target/hppa: Use TCG_COND_TST* in do_log_cond Richard Henderson
                   ` (23 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

We can directly test bits of a 32-bit comparison without
zero or sign-extending an intermediate result.
We can directly test bit 0 for odd/even.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 64 ++++++++++++++++++-----------------------
 1 file changed, 28 insertions(+), 36 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 07ba35001b..813f1571e9 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -776,28 +776,36 @@ static bool cond_need_cb(int c)
 static DisasCond do_cond(DisasContext *ctx, unsigned cf, bool d,
                          TCGv_i64 res, TCGv_i64 uv, TCGv_i64 sv)
 {
+    TCGCond sign_cond, zero_cond;
+    uint64_t sign_imm, zero_imm;
     DisasCond cond;
     TCGv_i64 tmp;
 
+    if (d) {
+        /* 64-bit condition. */
+        sign_imm = 0;
+        sign_cond = TCG_COND_LT;
+        zero_imm = 0;
+        zero_cond = TCG_COND_EQ;
+    } else {
+        /* 32-bit condition. */
+        sign_imm = 1ull << 31;
+        sign_cond = TCG_COND_TSTNE;
+        zero_imm = UINT32_MAX;
+        zero_cond = TCG_COND_TSTEQ;
+    }
+
     switch (cf >> 1) {
     case 0: /* Never / TR    (0 / 1) */
         cond = cond_make_f();
         break;
     case 1: /* = / <>        (Z / !Z) */
-        if (!d) {
-            tmp = tcg_temp_new_i64();
-            tcg_gen_ext32u_i64(tmp, res);
-            res = tmp;
-        }
-        cond = cond_make_vi(TCG_COND_EQ, res, 0);
+        cond = cond_make_vi(zero_cond, res, zero_imm);
         break;
     case 2: /* < / >=        (N ^ V / !(N ^ V) */
         tmp = tcg_temp_new_i64();
         tcg_gen_xor_i64(tmp, res, sv);
-        if (!d) {
-            tcg_gen_ext32s_i64(tmp, tmp);
-        }
-        cond = cond_make_ti(TCG_COND_LT, tmp, 0);
+        cond = cond_make_ti(sign_cond, tmp, sign_imm);
         break;
     case 3: /* <= / >        (N ^ V) | Z / !((N ^ V) | Z) */
         /*
@@ -805,21 +813,15 @@ static DisasCond do_cond(DisasContext *ctx, unsigned cf, bool d,
          *   (N ^ V) | Z
          *   ((res < 0) ^ (sv < 0)) | !res
          *   ((res ^ sv) < 0) | !res
-         *   (~(res ^ sv) >= 0) | !res
-         *   !(~(res ^ sv) >> 31) | !res
-         *   !(~(res ^ sv) >> 31 & res)
+         *   ((res ^ sv) < 0 ? 1 : !res)
+         *   !((res ^ sv) < 0 ? 0 : res)
          */
         tmp = tcg_temp_new_i64();
-        tcg_gen_eqv_i64(tmp, res, sv);
-        if (!d) {
-            tcg_gen_sextract_i64(tmp, tmp, 31, 1);
-            tcg_gen_and_i64(tmp, tmp, res);
-            tcg_gen_ext32u_i64(tmp, tmp);
-        } else {
-            tcg_gen_sari_i64(tmp, tmp, 63);
-            tcg_gen_and_i64(tmp, tmp, res);
-        }
-        cond = cond_make_ti(TCG_COND_EQ, tmp, 0);
+        tcg_gen_xor_i64(tmp, res, sv);
+        tcg_gen_movcond_i64(sign_cond, tmp,
+                            tmp, tcg_constant_i64(sign_imm),
+                            ctx->zero, res);
+        cond = cond_make_ti(zero_cond, tmp, zero_imm);
         break;
     case 4: /* NUV / UV      (!UV / UV) */
         cond = cond_make_vi(TCG_COND_EQ, uv, 0);
@@ -827,23 +829,13 @@ static DisasCond do_cond(DisasContext *ctx, unsigned cf, bool d,
     case 5: /* ZNV / VNZ     (!UV | Z / UV & !Z) */
         tmp = tcg_temp_new_i64();
         tcg_gen_movcond_i64(TCG_COND_EQ, tmp, uv, ctx->zero, ctx->zero, res);
-        if (!d) {
-            tcg_gen_ext32u_i64(tmp, tmp);
-        }
-        cond = cond_make_ti(TCG_COND_EQ, tmp, 0);
+        cond = cond_make_ti(zero_cond, tmp, zero_imm);
         break;
     case 6: /* SV / NSV      (V / !V) */
-        if (!d) {
-            tmp = tcg_temp_new_i64();
-            tcg_gen_ext32s_i64(tmp, sv);
-            sv = tmp;
-        }
-        cond = cond_make_ti(TCG_COND_LT, sv, 0);
+        cond = cond_make_vi(sign_cond, sv, sign_imm);
         break;
     case 7: /* OD / EV */
-        tmp = tcg_temp_new_i64();
-        tcg_gen_andi_i64(tmp, res, 1);
-        cond = cond_make_ti(TCG_COND_NE, tmp, 0);
+        cond = cond_make_vi(TCG_COND_TSTNE, res, 1);
         break;
     default:
         g_assert_not_reached();
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 21/43] target/hppa: Use TCG_COND_TST* in do_log_cond
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (19 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 20/43] target/hppa: Use TCG_COND_TST* in do_cond Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 22/43] target/hppa: Use TCG_COND_TST* in do_unit_zero_cond Richard Henderson
                   ` (22 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

We can directly test bits of a 32-bit comparison without
zero or sign-extending an intermediate result.
We can directly test bit 0 for odd/even.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 78 ++++++++++++++---------------------------
 1 file changed, 27 insertions(+), 51 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 813f1571e9..62cc3c3117 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -915,65 +915,41 @@ static DisasCond do_log_cond(DisasContext *ctx, unsigned cf, bool d,
                              TCGv_i64 res)
 {
     TCGCond tc;
-    bool ext_uns;
+    uint64_t imm;
 
-    switch (cf) {
-    case 0:  /* never */
-    case 9:  /* undef, C */
-    case 11: /* undef, C & !Z */
-    case 12: /* undef, V */
-        return cond_make_f();
-
-    case 1:  /* true */
-    case 8:  /* undef, !C */
-    case 10: /* undef, !C | Z */
-    case 13: /* undef, !V */
-        return cond_make_t();
-
-    case 2:  /* == */
-        tc = TCG_COND_EQ;
-        ext_uns = true;
+    switch (cf >> 1) {
+    case 0:  /* never / always */
+    case 4:  /* undef, C */
+    case 5:  /* undef, C & !Z */
+    case 6:  /* undef, V */
+        return cf & 1 ? cond_make_t() : cond_make_f();
+    case 1:  /* == / <> */
+        tc = d ? TCG_COND_EQ : TCG_COND_TSTEQ;
+        imm = d ? 0 : UINT32_MAX;
         break;
-    case 3:  /* <> */
-        tc = TCG_COND_NE;
-        ext_uns = true;
+    case 2:  /* < / >= */
+        tc = d ? TCG_COND_LT : TCG_COND_TSTNE;
+        imm = d ? 0 : 1ull << 31;
         break;
-    case 4:  /* < */
-        tc = TCG_COND_LT;
-        ext_uns = false;
+    case 3:  /* <= / > */
+        tc = cf & 1 ? TCG_COND_GT : TCG_COND_LE;
+        if (!d) {
+            TCGv_i64 tmp = tcg_temp_new_i64();
+            tcg_gen_ext32s_i64(tmp, res);
+            return cond_make_ti(tc, tmp, 0);
+        }
+        return cond_make_vi(tc, res, 0);
+    case 7: /* OD / EV */
+        tc = TCG_COND_TSTNE;
+        imm = 1;
         break;
-    case 5:  /* >= */
-        tc = TCG_COND_GE;
-        ext_uns = false;
-        break;
-    case 6:  /* <= */
-        tc = TCG_COND_LE;
-        ext_uns = false;
-        break;
-    case 7:  /* > */
-        tc = TCG_COND_GT;
-        ext_uns = false;
-        break;
-
-    case 14: /* OD */
-    case 15: /* EV */
-        return do_cond(ctx, cf, d, res, NULL, NULL);
-
     default:
         g_assert_not_reached();
     }
-
-    if (!d) {
-        TCGv_i64 tmp = tcg_temp_new_i64();
-
-        if (ext_uns) {
-            tcg_gen_ext32u_i64(tmp, res);
-        } else {
-            tcg_gen_ext32s_i64(tmp, res);
-        }
-        return cond_make_ti(tc, tmp, 0);
+    if (cf & 1) {
+        tc = tcg_invert_cond(tc);
     }
-    return cond_make_vi(tc, res, 0);
+    return cond_make_vi(tc, res, imm);
 }
 
 /* Similar, but for shift/extract/deposit conditions.  */
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 22/43] target/hppa: Use TCG_COND_TST* in do_unit_zero_cond
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (20 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 21/43] target/hppa: Use TCG_COND_TST* in do_log_cond Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 23/43] target/hppa: Use TCG_COND_TST* in do_unit_addsub Richard Henderson
                   ` (21 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 62cc3c3117..b19d7c64fe 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -1006,9 +1006,8 @@ static DisasCond do_unit_zero_cond(unsigned cf, bool d, TCGv_i64 res)
     tmp = tcg_temp_new_i64();
     tcg_gen_subi_i64(tmp, res, ones);
     tcg_gen_andc_i64(tmp, tmp, res);
-    tcg_gen_andi_i64(tmp, tmp, sgns);
 
-    return cond_make_ti(cf & 1 ? TCG_COND_EQ : TCG_COND_NE, tmp, 0);
+    return cond_make_ti(cf & 1 ? TCG_COND_TSTEQ : TCG_COND_TSTNE, tmp, sgns);
 }
 
 static TCGv_i64 get_carry(DisasContext *ctx, bool d,
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 23/43] target/hppa: Use TCG_COND_TST* in do_unit_addsub
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (21 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 22/43] target/hppa: Use TCG_COND_TST* in do_unit_zero_cond Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 24/43] target/hppa: Use TCG_COND_TST* in trans_bb_imm Richard Henderson
                   ` (20 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller, Philippe Mathieu-Daudé

Reviewed-by: Helge Deller <deller@gmx.de>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index b19d7c64fe..4e49bd2b67 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -1420,8 +1420,8 @@ static void do_unit_addsub(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
             tcg_gen_shri_i64(cb, cb, 1);
         }
 
-        tcg_gen_andi_i64(cb, cb, test_cb);
-        cond = cond_make_ti(cf & 1 ? TCG_COND_EQ : TCG_COND_NE, cb, 0);
+        cond = cond_make_ti(cf & 1 ? TCG_COND_TSTEQ : TCG_COND_TSTNE,
+                            cb, test_cb);
     }
 
     if (is_tc) {
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 24/43] target/hppa: Use TCG_COND_TST* in trans_bb_imm
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (22 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 23/43] target/hppa: Use TCG_COND_TST* in do_unit_addsub Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 25/43] target/hppa: Use registerfields.h for FPSR Richard Henderson
                   ` (19 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller, Philippe Mathieu-Daudé

Reviewed-by: Helge Deller <deller@gmx.de>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 4e49bd2b67..af6be5100c 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -3516,18 +3516,12 @@ static bool trans_bb_sar(DisasContext *ctx, arg_bb_sar *a)
 
 static bool trans_bb_imm(DisasContext *ctx, arg_bb_imm *a)
 {
-    TCGv_i64 tmp, tcg_r;
     DisasCond cond;
-    int p;
+    int p = a->p | (a->d ? 0 : 32);
 
     nullify_over(ctx);
-
-    tmp = tcg_temp_new_i64();
-    tcg_r = load_gpr(ctx, a->r);
-    p = a->p | (a->d ? 0 : 32);
-    tcg_gen_shli_i64(tmp, tcg_r, p);
-
-    cond = cond_make_ti(a->c ? TCG_COND_GE : TCG_COND_LT, tmp, 0);
+    cond = cond_make_vi(a->c ? TCG_COND_TSTEQ : TCG_COND_TSTNE,
+                        load_gpr(ctx, a->r), 1ull << (63 - p));
     return do_cbranch(ctx, a->disp, a->n, &cond);
 }
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 25/43] target/hppa: Use registerfields.h for FPSR
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (23 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 24/43] target/hppa: Use TCG_COND_TST* in trans_bb_imm Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 26/43] target/hppa: Use TCG_COND_TST* in trans_ftest Richard Henderson
                   ` (18 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Define all of the context dependent field definitions.
Use FIELD_EX32 and FIELD_DP32 with named fields instead
of extract32 and deposit32 with raw constants.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/cpu.h        | 25 +++++++++++++++++++++++++
 target/hppa/fpu_helper.c | 26 +++++++++++++-------------
 target/hppa/translate.c  | 18 ++++++++----------
 3 files changed, 46 insertions(+), 23 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 61f1353133..c37b4e12fb 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -24,6 +24,7 @@
 #include "exec/cpu-defs.h"
 #include "qemu/cpu-float.h"
 #include "qemu/interval-tree.h"
+#include "hw/registerfields.h"
 
 #define MMU_ABS_W_IDX     6
 #define MMU_ABS_IDX       7
@@ -152,6 +153,30 @@
 #define CR_IPSW          22
 #define CR_EIRR          23
 
+FIELD(FPSR, ENA_I, 0, 1)
+FIELD(FPSR, ENA_U, 1, 1)
+FIELD(FPSR, ENA_O, 2, 1)
+FIELD(FPSR, ENA_Z, 3, 1)
+FIELD(FPSR, ENA_V, 4, 1)
+FIELD(FPSR, ENABLES, 0, 5)
+FIELD(FPSR, D, 5, 1)
+FIELD(FPSR, T, 6, 1)
+FIELD(FPSR, RM, 9, 2)
+FIELD(FPSR, CQ, 11, 11)
+FIELD(FPSR, CQ0_6, 15, 7)
+FIELD(FPSR, CQ0_4, 17, 5)
+FIELD(FPSR, CQ0_2, 19, 3)
+FIELD(FPSR, CQ0, 21, 1)
+FIELD(FPSR, CA, 15, 7)
+FIELD(FPSR, CA0, 21, 1)
+FIELD(FPSR, C, 26, 1)
+FIELD(FPSR, FLG_I, 27, 1)
+FIELD(FPSR, FLG_U, 28, 1)
+FIELD(FPSR, FLG_O, 29, 1)
+FIELD(FPSR, FLG_Z, 30, 1)
+FIELD(FPSR, FLG_V, 31, 1)
+FIELD(FPSR, FLAGS, 27, 5)
+
 typedef struct HPPATLBEntry {
     union {
         IntervalTreeNode itree;
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
index 576f283b04..deaed2b65d 100644
--- a/target/hppa/fpu_helper.c
+++ b/target/hppa/fpu_helper.c
@@ -30,7 +30,7 @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
 
     env->fr0_shadow = shadow;
 
-    switch (extract32(shadow, 9, 2)) {
+    switch (FIELD_EX32(shadow, FPSR, RM)) {
     default:
         rm = float_round_nearest_even;
         break;
@@ -46,7 +46,7 @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
     }
     set_float_rounding_mode(rm, &env->fp_status);
 
-    d = extract32(shadow, 5, 1);
+    d = FIELD_EX32(shadow, FPSR, D);
     set_flush_to_zero(d, &env->fp_status);
     set_flush_inputs_to_zero(d, &env->fp_status);
 }
@@ -57,7 +57,7 @@ void cpu_hppa_loaded_fr0(CPUHPPAState *env)
 }
 
 #define CONVERT_BIT(X, SRC, DST)        \
-    ((SRC) > (DST)                      \
+    ((unsigned)(SRC) > (unsigned)(DST)  \
      ? (X) / ((SRC) / (DST)) & (DST)    \
      : ((X) & (SRC)) * ((DST) / (SRC)))
 
@@ -73,12 +73,12 @@ static void update_fr0_op(CPUHPPAState *env, uintptr_t ra)
     }
     set_float_exception_flags(0, &env->fp_status);
 
-    hard_exp |= CONVERT_BIT(soft_exp, float_flag_inexact,   1u << 0);
-    hard_exp |= CONVERT_BIT(soft_exp, float_flag_underflow, 1u << 1);
-    hard_exp |= CONVERT_BIT(soft_exp, float_flag_overflow,  1u << 2);
-    hard_exp |= CONVERT_BIT(soft_exp, float_flag_divbyzero, 1u << 3);
-    hard_exp |= CONVERT_BIT(soft_exp, float_flag_invalid,   1u << 4);
-    shadow |= hard_exp << (32 - 5);
+    hard_exp |= CONVERT_BIT(soft_exp, float_flag_inexact,   R_FPSR_ENA_I_MASK);
+    hard_exp |= CONVERT_BIT(soft_exp, float_flag_underflow, R_FPSR_ENA_U_MASK);
+    hard_exp |= CONVERT_BIT(soft_exp, float_flag_overflow,  R_FPSR_ENA_O_MASK);
+    hard_exp |= CONVERT_BIT(soft_exp, float_flag_divbyzero, R_FPSR_ENA_Z_MASK);
+    hard_exp |= CONVERT_BIT(soft_exp, float_flag_invalid,   R_FPSR_ENA_V_MASK);
+    shadow |= hard_exp << (R_FPSR_FLAGS_SHIFT - R_FPSR_ENABLES_SHIFT);
     env->fr0_shadow = shadow;
     env->fr[0] = (uint64_t)shadow << 32;
 
@@ -378,15 +378,15 @@ static void update_fr0_cmp(CPUHPPAState *env, uint32_t y,
     if (y) {
         /* targeted comparison */
         /* set fpsr[ca[y - 1]] to current compare */
-        shadow = deposit32(shadow, 21 - (y - 1), 1, c);
+        shadow = deposit32(shadow, R_FPSR_CA0_SHIFT - (y - 1), 1, c);
     } else {
         /* queued comparison */
         /* shift cq right by one place */
-        shadow = deposit32(shadow, 11, 10, extract32(shadow, 12, 10));
+        shadow = (shadow & ~R_FPSR_CQ_MASK) | ((shadow >> 1) & R_FPSR_CQ_MASK);
         /* move fpsr[c] to fpsr[cq[0]] */
-        shadow = deposit32(shadow, 21, 1, extract32(shadow, 26, 1));
+        shadow = FIELD_DP32(shadow, FPSR, CQ0, FIELD_EX32(shadow, FPSR, C));
         /* set fpsr[c] to current compare */
-        shadow = deposit32(shadow, 26, 1, c);
+        shadow = FIELD_DP32(shadow, FPSR, C, c);
     }
 
     env->fr0_shadow = shadow;
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index af6be5100c..efd4398437 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -4324,29 +4324,28 @@ static bool trans_ftest(DisasContext *ctx, arg_ftest *a)
 
         switch (a->c) {
         case 0: /* simple */
-            tcg_gen_andi_i64(t, t, 0x4000000);
-            ctx->null_cond = cond_make_ti(TCG_COND_NE, t, 0);
-            goto done;
+            mask = R_FPSR_C_MASK;
+            break;
         case 2: /* rej */
             inv = true;
             /* fallthru */
         case 1: /* acc */
-            mask = 0x43ff800;
+            mask = R_FPSR_C_MASK | R_FPSR_CQ_MASK;
             break;
         case 6: /* rej8 */
             inv = true;
             /* fallthru */
         case 5: /* acc8 */
-            mask = 0x43f8000;
+            mask = R_FPSR_C_MASK | R_FPSR_CQ0_6_MASK;
             break;
         case 9: /* acc6 */
-            mask = 0x43e0000;
+            mask = R_FPSR_C_MASK | R_FPSR_CQ0_4_MASK;
             break;
         case 13: /* acc4 */
-            mask = 0x4380000;
+            mask = R_FPSR_C_MASK | R_FPSR_CQ0_2_MASK;
             break;
         case 17: /* acc2 */
-            mask = 0x4200000;
+            mask = R_FPSR_C_MASK | R_FPSR_CQ0_MASK;
             break;
         default:
             gen_illegal(ctx);
@@ -4363,11 +4362,10 @@ static bool trans_ftest(DisasContext *ctx, arg_ftest *a)
     } else {
         unsigned cbit = (a->y ^ 1) - 1;
 
-        tcg_gen_extract_i64(t, t, 21 - cbit, 1);
+        tcg_gen_extract_i64(t, t, R_FPSR_CA0_SHIFT - cbit, 1);
         ctx->null_cond = cond_make_ti(TCG_COND_NE, t, 0);
     }
 
- done:
     return nullify_end(ctx);
 }
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 26/43] target/hppa: Use TCG_COND_TST* in trans_ftest
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (24 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 25/43] target/hppa: Use registerfields.h for FPSR Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 27/43] target/hppa: Remove cond_free Richard Henderson
                   ` (17 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller, Philippe Mathieu-Daudé

Reviewed-by: Helge Deller <deller@gmx.de>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 22 ++++++----------------
 1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index efd4398437..11d74bb2aa 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -4311,6 +4311,8 @@ static bool trans_fcmp_d(DisasContext *ctx, arg_fclass2 *a)
 
 static bool trans_ftest(DisasContext *ctx, arg_ftest *a)
 {
+    TCGCond tc = TCG_COND_TSTNE;
+    uint32_t mask;
     TCGv_i64 t;
 
     nullify_over(ctx);
@@ -4319,21 +4321,18 @@ static bool trans_ftest(DisasContext *ctx, arg_ftest *a)
     tcg_gen_ld32u_i64(t, tcg_env, offsetof(CPUHPPAState, fr0_shadow));
 
     if (a->y == 1) {
-        int mask;
-        bool inv = false;
-
         switch (a->c) {
         case 0: /* simple */
             mask = R_FPSR_C_MASK;
             break;
         case 2: /* rej */
-            inv = true;
+            tc = TCG_COND_TSTEQ;
             /* fallthru */
         case 1: /* acc */
             mask = R_FPSR_C_MASK | R_FPSR_CQ_MASK;
             break;
         case 6: /* rej8 */
-            inv = true;
+            tc = TCG_COND_TSTEQ;
             /* fallthru */
         case 5: /* acc8 */
             mask = R_FPSR_C_MASK | R_FPSR_CQ0_6_MASK;
@@ -4351,21 +4350,12 @@ static bool trans_ftest(DisasContext *ctx, arg_ftest *a)
             gen_illegal(ctx);
             return true;
         }
-        if (inv) {
-            TCGv_i64 c = tcg_constant_i64(mask);
-            tcg_gen_or_i64(t, t, c);
-            ctx->null_cond = cond_make_tt(TCG_COND_EQ, t, c);
-        } else {
-            tcg_gen_andi_i64(t, t, mask);
-            ctx->null_cond = cond_make_ti(TCG_COND_EQ, t, 0);
-        }
     } else {
         unsigned cbit = (a->y ^ 1) - 1;
-
-        tcg_gen_extract_i64(t, t, R_FPSR_CA0_SHIFT - cbit, 1);
-        ctx->null_cond = cond_make_ti(TCG_COND_NE, t, 0);
+        mask = R_FPSR_CA0_MASK >> cbit;
     }
 
+    ctx->null_cond = cond_make_ti(tc, t, mask);
     return nullify_end(ctx);
 }
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 27/43] target/hppa: Remove cond_free
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (25 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 26/43] target/hppa: Use TCG_COND_TST* in trans_ftest Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 28/43] target/hppa: Introduce DisasDelayException Richard Henderson
                   ` (16 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller, Philippe Mathieu-Daudé

Now that we do not need to free tcg temporaries, the only
thing cond_free does is reset the condition to never.
Instead, simply write a new condition over the old, which
may be simply cond_make_f() for the never condition.

The do_*_cond functions do the right thing with c or cf == 0,
so there's no need for a special case anymore.

Reviewed-by: Helge Deller <deller@gmx.de>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 102 +++++++++++-----------------------------
 1 file changed, 27 insertions(+), 75 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 11d74bb2aa..81a75ddf95 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -373,21 +373,6 @@ static DisasCond cond_make_vv(TCGCond c, TCGv_i64 a0, TCGv_i64 a1)
     return cond_make_tt(c, t0, t1);
 }
 
-static void cond_free(DisasCond *cond)
-{
-    switch (cond->c) {
-    default:
-        cond->a0 = NULL;
-        cond->a1 = NULL;
-        /* fallthru */
-    case TCG_COND_ALWAYS:
-        cond->c = TCG_COND_NEVER;
-        break;
-    case TCG_COND_NEVER:
-        break;
-    }
-}
-
 static TCGv_i64 load_gpr(DisasContext *ctx, unsigned reg)
 {
     if (reg == 0) {
@@ -537,7 +522,7 @@ static void nullify_over(DisasContext *ctx)
 
         tcg_gen_brcond_i64(ctx->null_cond.c, ctx->null_cond.a0,
                            ctx->null_cond.a1, ctx->null_lab);
-        cond_free(&ctx->null_cond);
+        ctx->null_cond = cond_make_f();
     }
 }
 
@@ -555,7 +540,7 @@ static void nullify_save(DisasContext *ctx)
                             ctx->null_cond.a0, ctx->null_cond.a1);
         ctx->psw_n_nonzero = true;
     }
-    cond_free(&ctx->null_cond);
+    ctx->null_cond = cond_make_f();
 }
 
 /* Set a PSW[N] to X.  The intention is that this is used immediately
@@ -1166,7 +1151,6 @@ static void do_add(DisasContext *ctx, unsigned rt, TCGv_i64 orig_in1,
     save_gpr(ctx, rt, dest);
 
     /* Install the new nullification.  */
-    cond_free(&ctx->null_cond);
     ctx->null_cond = cond;
 }
 
@@ -1263,7 +1247,6 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
     save_gpr(ctx, rt, dest);
 
     /* Install the new nullification.  */
-    cond_free(&ctx->null_cond);
     ctx->null_cond = cond;
 }
 
@@ -1318,7 +1301,6 @@ static void do_cmpclr(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
     save_gpr(ctx, rt, dest);
 
     /* Install the new nullification.  */
-    cond_free(&ctx->null_cond);
     ctx->null_cond = cond;
 }
 
@@ -1333,10 +1315,7 @@ static void do_log(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
     save_gpr(ctx, rt, dest);
 
     /* Install the new nullification.  */
-    cond_free(&ctx->null_cond);
-    if (cf) {
-        ctx->null_cond = do_log_cond(ctx, cf, d, dest);
-    }
+    ctx->null_cond = do_log_cond(ctx, cf, d, dest);
 }
 
 static bool do_log_reg(DisasContext *ctx, arg_rrr_cf_d *a,
@@ -1431,7 +1410,6 @@ static void do_unit_addsub(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
     }
     save_gpr(ctx, rt, dest);
 
-    cond_free(&ctx->null_cond);
     ctx->null_cond = cond;
 }
 
@@ -1854,7 +1832,6 @@ static bool do_cbranch(DisasContext *ctx, int64_t disp, bool is_n,
 
     taken = gen_new_label();
     tcg_gen_brcond_i64(c, cond->a0, cond->a1, taken);
-    cond_free(cond);
 
     /* Not taken: Condition not satisfied; nullify on backward branches. */
     n = is_n && disp < 0;
@@ -2036,7 +2013,7 @@ static void do_page_zero(DisasContext *ctx)
 
 static bool trans_nop(DisasContext *ctx, arg_nop *a)
 {
-    cond_free(&ctx->null_cond);
+    ctx->null_cond = cond_make_f();
     return true;
 }
 
@@ -2050,7 +2027,7 @@ static bool trans_sync(DisasContext *ctx, arg_sync *a)
     /* No point in nullifying the memory barrier.  */
     tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
 
-    cond_free(&ctx->null_cond);
+    ctx->null_cond = cond_make_f();
     return true;
 }
 
@@ -2062,7 +2039,7 @@ static bool trans_mfia(DisasContext *ctx, arg_mfia *a)
     tcg_gen_andi_i64(dest, dest, -4);
 
     save_gpr(ctx, a->t, dest);
-    cond_free(&ctx->null_cond);
+    ctx->null_cond = cond_make_f();
     return true;
 }
 
@@ -2077,7 +2054,7 @@ static bool trans_mfsp(DisasContext *ctx, arg_mfsp *a)
 
     save_gpr(ctx, rt, t0);
 
-    cond_free(&ctx->null_cond);
+    ctx->null_cond = cond_make_f();
     return true;
 }
 
@@ -2122,7 +2099,7 @@ static bool trans_mfctl(DisasContext *ctx, arg_mfctl *a)
     save_gpr(ctx, rt, tmp);
 
  done:
-    cond_free(&ctx->null_cond);
+    ctx->null_cond = cond_make_f();
     return true;
 }
 
@@ -2162,7 +2139,7 @@ static bool trans_mtctl(DisasContext *ctx, arg_mtctl *a)
         tcg_gen_andi_i64(tmp, reg, ctx->is_pa20 ? 63 : 31);
         save_or_nullify(ctx, cpu_sar, tmp);
 
-        cond_free(&ctx->null_cond);
+        ctx->null_cond = cond_make_f();
         return true;
     }
 
@@ -2236,7 +2213,7 @@ static bool trans_mtsarcm(DisasContext *ctx, arg_mtsarcm *a)
     tcg_gen_andi_i64(tmp, tmp, ctx->is_pa20 ? 63 : 31);
     save_or_nullify(ctx, cpu_sar, tmp);
 
-    cond_free(&ctx->null_cond);
+    ctx->null_cond = cond_make_f();
     return true;
 }
 
@@ -2253,7 +2230,7 @@ static bool trans_ldsid(DisasContext *ctx, arg_ldsid *a)
 #endif
     save_gpr(ctx, a->t, dest);
 
-    cond_free(&ctx->null_cond);
+    ctx->null_cond = cond_make_f();
     return true;
 }
 
@@ -2415,7 +2392,7 @@ static bool trans_nop_addrx(DisasContext *ctx, arg_ldst *a)
         tcg_gen_add_i64(dest, src1, src2);
         save_gpr(ctx, a->b, dest);
     }
-    cond_free(&ctx->null_cond);
+    ctx->null_cond = cond_make_f();
     return true;
 }
 
@@ -2657,7 +2634,7 @@ static bool trans_lci(DisasContext *ctx, arg_lci *a)
        since the entire address space is coherent.  */
     save_gpr(ctx, a->t, ctx->zero);
 
-    cond_free(&ctx->null_cond);
+    ctx->null_cond = cond_make_f();
     return true;
 }
 
@@ -2734,7 +2711,7 @@ static bool trans_or(DisasContext *ctx, arg_rrr_cf_d *a)
         unsigned rt = a->t;
 
         if (rt == 0) { /* NOP */
-            cond_free(&ctx->null_cond);
+            ctx->null_cond = cond_make_f();
             return true;
         }
         if (r2 == 0) { /* COPY */
@@ -2745,7 +2722,7 @@ static bool trans_or(DisasContext *ctx, arg_rrr_cf_d *a)
             } else {
                 save_gpr(ctx, rt, cpu_gr[r1]);
             }
-            cond_free(&ctx->null_cond);
+            ctx->null_cond = cond_make_f();
             return true;
         }
 #ifndef CONFIG_USER_ONLY
@@ -2810,11 +2787,7 @@ static bool trans_uxor(DisasContext *ctx, arg_rrr_cf_d *a)
     tcg_gen_xor_i64(dest, tcg_r1, tcg_r2);
     save_gpr(ctx, a->t, dest);
 
-    cond_free(&ctx->null_cond);
-    if (a->cf) {
-        ctx->null_cond = do_unit_zero_cond(a->cf, a->d, dest);
-    }
-
+    ctx->null_cond = do_unit_zero_cond(a->cf, a->d, dest);
     return nullify_end(ctx);
 }
 
@@ -2840,7 +2813,7 @@ static bool do_uaddcm(DisasContext *ctx, arg_rrr_cf_d *a, bool is_tc)
             tcg_gen_subi_i64(tmp, tmp, 1);
         }
         save_gpr(ctx, a->t, tmp);
-        cond_free(&ctx->null_cond);
+        ctx->null_cond = cond_make_f();
         return true;
     }
 
@@ -3366,7 +3339,7 @@ static bool trans_ldil(DisasContext *ctx, arg_ldil *a)
 
     tcg_gen_movi_i64(tcg_rt, a->i);
     save_gpr(ctx, a->t, tcg_rt);
-    cond_free(&ctx->null_cond);
+    ctx->null_cond = cond_make_f();
     return true;
 }
 
@@ -3377,7 +3350,7 @@ static bool trans_addil(DisasContext *ctx, arg_addil *a)
 
     tcg_gen_addi_i64(tcg_r1, tcg_rt, a->i);
     save_gpr(ctx, 1, tcg_r1);
-    cond_free(&ctx->null_cond);
+    ctx->null_cond = cond_make_f();
     return true;
 }
 
@@ -3393,7 +3366,7 @@ static bool trans_ldo(DisasContext *ctx, arg_ldo *a)
         tcg_gen_addi_i64(tcg_rt, cpu_gr[a->b], a->i);
     }
     save_gpr(ctx, a->t, tcg_rt);
-    cond_free(&ctx->null_cond);
+    ctx->null_cond = cond_make_f();
     return true;
 }
 
@@ -3619,10 +3592,7 @@ static bool trans_shrp_sar(DisasContext *ctx, arg_shrp_sar *a)
     save_gpr(ctx, a->t, dest);
 
     /* Install the new nullification.  */
-    cond_free(&ctx->null_cond);
-    if (a->c) {
-        ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
-    }
+    ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
     return nullify_end(ctx);
 }
 
@@ -3662,10 +3632,7 @@ static bool trans_shrp_imm(DisasContext *ctx, arg_shrp_imm *a)
     save_gpr(ctx, a->t, dest);
 
     /* Install the new nullification.  */
-    cond_free(&ctx->null_cond);
-    if (a->c) {
-        ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
-    }
+    ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
     return nullify_end(ctx);
 }
 
@@ -3707,10 +3674,7 @@ static bool trans_extr_sar(DisasContext *ctx, arg_extr_sar *a)
     save_gpr(ctx, a->t, dest);
 
     /* Install the new nullification.  */
-    cond_free(&ctx->null_cond);
-    if (a->c) {
-        ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
-    }
+    ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
     return nullify_end(ctx);
 }
 
@@ -3743,10 +3707,7 @@ static bool trans_extr_imm(DisasContext *ctx, arg_extr_imm *a)
     save_gpr(ctx, a->t, dest);
 
     /* Install the new nullification.  */
-    cond_free(&ctx->null_cond);
-    if (a->c) {
-        ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
-    }
+    ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
     return nullify_end(ctx);
 }
 
@@ -3783,10 +3744,7 @@ static bool trans_depi_imm(DisasContext *ctx, arg_depi_imm *a)
     save_gpr(ctx, a->t, dest);
 
     /* Install the new nullification.  */
-    cond_free(&ctx->null_cond);
-    if (a->c) {
-        ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
-    }
+    ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
     return nullify_end(ctx);
 }
 
@@ -3819,10 +3777,7 @@ static bool trans_dep_imm(DisasContext *ctx, arg_dep_imm *a)
     save_gpr(ctx, a->t, dest);
 
     /* Install the new nullification.  */
-    cond_free(&ctx->null_cond);
-    if (a->c) {
-        ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
-    }
+    ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
     return nullify_end(ctx);
 }
 
@@ -3856,10 +3811,7 @@ static bool do_dep_sar(DisasContext *ctx, unsigned rt, unsigned c,
     save_gpr(ctx, rt, dest);
 
     /* Install the new nullification.  */
-    cond_free(&ctx->null_cond);
-    if (c) {
-        ctx->null_cond = do_sed_cond(ctx, c, d, dest);
-    }
+    ctx->null_cond = do_sed_cond(ctx, c, d, dest);
     return nullify_end(ctx);
 }
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 28/43] target/hppa: Introduce DisasDelayException
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (26 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 27/43] target/hppa: Remove cond_free Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 29/43] target/hppa: Use delay_excp for conditional traps Richard Henderson
                   ` (15 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Allow an exception to be emitted at the end of the TranslationBlock,
leaving only the conditional branch inline.  Use it for simple
exception instructions like break, which happen to be nullified.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 60 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 55 insertions(+), 5 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 81a75ddf95..706537ea59 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -51,6 +51,17 @@ typedef struct DisasIAQE {
     int64_t disp;
 } DisasIAQE;
 
+typedef struct DisasDelayException {
+    struct DisasDelayException *next;
+    TCGLabel *lab;
+    uint32_t insn;
+    bool set_iir;
+    int8_t set_n;
+    uint8_t excp;
+    /* Saved state at parent insn. */
+    DisasIAQE iaq_f, iaq_b;
+} DisasDelayException;
+
 typedef struct DisasContext {
     DisasContextBase base;
     CPUState *cs;
@@ -66,6 +77,7 @@ typedef struct DisasContext {
     DisasCond null_cond;
     TCGLabel *null_lab;
 
+    DisasDelayException *delay_excp_list;
     TCGv_i64 zero;
 
     uint32_t insn;
@@ -684,13 +696,38 @@ static void gen_excp(DisasContext *ctx, int exception)
     ctx->base.is_jmp = DISAS_NORETURN;
 }
 
+static DisasDelayException *delay_excp(DisasContext *ctx, uint8_t excp)
+{
+    DisasDelayException *e = tcg_malloc(sizeof(DisasDelayException));
+
+    memset(e, 0, sizeof(*e));
+    e->next = ctx->delay_excp_list;
+    ctx->delay_excp_list = e;
+
+    e->lab = gen_new_label();
+    e->insn = ctx->insn;
+    e->set_iir = true;
+    e->set_n = ctx->psw_n_nonzero ? 0 : -1;
+    e->excp = excp;
+    e->iaq_f = ctx->iaq_f;
+    e->iaq_b = ctx->iaq_b;
+
+    return e;
+}
+
 static bool gen_excp_iir(DisasContext *ctx, int exc)
 {
-    nullify_over(ctx);
-    tcg_gen_st_i64(tcg_constant_i64(ctx->insn),
-                   tcg_env, offsetof(CPUHPPAState, cr[CR_IIR]));
-    gen_excp(ctx, exc);
-    return nullify_end(ctx);
+    if (ctx->null_cond.c == TCG_COND_NEVER) {
+        tcg_gen_st_i64(tcg_constant_i64(ctx->insn),
+                       tcg_env, offsetof(CPUHPPAState, cr[CR_IIR]));
+        gen_excp(ctx, exc);
+    } else {
+        DisasDelayException *e = delay_excp(ctx, exc);
+        tcg_gen_brcond_i64(tcg_invert_cond(ctx->null_cond.c),
+                           ctx->null_cond.a0, ctx->null_cond.a1, e->lab);
+        ctx->null_cond = cond_make_f();
+    }
+    return true;
 }
 
 static bool gen_illegal(DisasContext *ctx)
@@ -4697,6 +4734,19 @@ static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
     default:
         g_assert_not_reached();
     }
+
+    for (DisasDelayException *e = ctx->delay_excp_list; e ; e = e->next) {
+        gen_set_label(e->lab);
+        if (e->set_n >= 0) {
+            tcg_gen_movi_i64(cpu_psw_n, e->set_n);
+        }
+        if (e->set_iir) {
+            tcg_gen_st_i64(tcg_constant_i64(e->insn), tcg_env,
+                           offsetof(CPUHPPAState, cr[CR_IIR]));
+        }
+        install_iaq_entries(ctx, &e->iaq_f, &e->iaq_b);
+        gen_excp_1(e->excp);
+    }
 }
 
 static void hppa_tr_disas_log(const DisasContextBase *dcbase,
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 29/43] target/hppa: Use delay_excp for conditional traps
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (27 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 28/43] target/hppa: Introduce DisasDelayException Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 30/43] target/hppa: Use delay_excp for conditional trap on overflow Richard Henderson
                   ` (14 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/helper.h     |  1 -
 target/hppa/int_helper.c |  2 +-
 target/hppa/op_helper.c  |  7 -------
 target/hppa/translate.c  | 41 ++++++++++++++++++++++++++++++----------
 4 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index 5900fd70bc..3d0d143aed 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -1,6 +1,5 @@
 DEF_HELPER_2(excp, noreturn, env, int)
 DEF_HELPER_FLAGS_2(tsv, TCG_CALL_NO_WG, void, env, tl)
-DEF_HELPER_FLAGS_2(tcond, TCG_CALL_NO_WG, void, env, tl)
 
 DEF_HELPER_FLAGS_3(stby_b, TCG_CALL_NO_WG, void, env, tl, tl)
 DEF_HELPER_FLAGS_3(stby_b_parallel, TCG_CALL_NO_WG, void, env, tl, tl)
diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
index a667ee380d..1aa3e88ef1 100644
--- a/target/hppa/int_helper.c
+++ b/target/hppa/int_helper.c
@@ -134,13 +134,13 @@ void hppa_cpu_do_interrupt(CPUState *cs)
         switch (i) {
         case EXCP_ILL:
         case EXCP_BREAK:
+        case EXCP_COND:
         case EXCP_PRIV_REG:
         case EXCP_PRIV_OPR:
             /* IIR set via translate.c.  */
             break;
 
         case EXCP_OVERFLOW:
-        case EXCP_COND:
         case EXCP_ASSIST:
         case EXCP_DTLB_MISS:
         case EXCP_NA_ITLB_MISS:
diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index 6cf49f33b7..a8b69fd481 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -49,13 +49,6 @@ void HELPER(tsv)(CPUHPPAState *env, target_ulong cond)
     }
 }
 
-void HELPER(tcond)(CPUHPPAState *env, target_ulong cond)
-{
-    if (unlikely(cond)) {
-        hppa_dynamic_excp(env, EXCP_COND, GETPC());
-    }
-}
-
 static void atomic_store_mask32(CPUHPPAState *env, target_ulong addr,
                                 uint32_t val, uint32_t mask, uintptr_t ra)
 {
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 706537ea59..ae291124f2 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -1117,6 +1117,25 @@ static TCGv_i64 do_sub_sv(DisasContext *ctx, TCGv_i64 res,
     return sv;
 }
 
+static void gen_tc(DisasContext *ctx, DisasCond *cond)
+{
+    DisasDelayException *e;
+
+    switch (cond->c) {
+    case TCG_COND_NEVER:
+        break;
+    case TCG_COND_ALWAYS:
+        gen_excp_iir(ctx, EXCP_COND);
+        break;
+    default:
+        e = delay_excp(ctx, EXCP_COND);
+        tcg_gen_brcond_i64(cond->c, cond->a0, cond->a1, e->lab);
+        /* In the non-trap path, the condition is known false. */
+        *cond = cond_make_f();
+        break;
+    }
+}
+
 static void do_add(DisasContext *ctx, unsigned rt, TCGv_i64 orig_in1,
                    TCGv_i64 in2, unsigned shift, bool is_l,
                    bool is_tsv, bool is_tc, bool is_c, unsigned cf, bool d)
@@ -1175,9 +1194,7 @@ static void do_add(DisasContext *ctx, unsigned rt, TCGv_i64 orig_in1,
     /* Emit any conditional trap before any writeback.  */
     cond = do_cond(ctx, cf, d, dest, uv, sv);
     if (is_tc) {
-        tmp = tcg_temp_new_i64();
-        tcg_gen_setcond_i64(cond.c, tmp, cond.a0, cond.a1);
-        gen_helper_tcond(tcg_env, tmp);
+        gen_tc(ctx, &cond);
     }
 
     /* Write back the result.  */
@@ -1196,6 +1213,10 @@ static bool do_add_reg(DisasContext *ctx, arg_rrr_cf_d_sh *a,
 {
     TCGv_i64 tcg_r1, tcg_r2;
 
+    if (unlikely(is_tc && a->cf == 1)) {
+        /* Unconditional trap on condition. */
+        return gen_excp_iir(ctx, EXCP_COND);
+    }
     if (a->cf) {
         nullify_over(ctx);
     }
@@ -1211,6 +1232,10 @@ static bool do_add_imm(DisasContext *ctx, arg_rri_cf *a,
 {
     TCGv_i64 tcg_im, tcg_r2;
 
+    if (unlikely(is_tc && a->cf == 1)) {
+        /* Unconditional trap on condition. */
+        return gen_excp_iir(ctx, EXCP_COND);
+    }
     if (a->cf) {
         nullify_over(ctx);
     }
@@ -1225,7 +1250,7 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
                    TCGv_i64 in2, bool is_tsv, bool is_b,
                    bool is_tc, unsigned cf, bool d)
 {
-    TCGv_i64 dest, sv, cb, cb_msb, tmp;
+    TCGv_i64 dest, sv, cb, cb_msb;
     unsigned c = cf >> 1;
     DisasCond cond;
 
@@ -1273,9 +1298,7 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
 
     /* Emit any conditional trap before any writeback.  */
     if (is_tc) {
-        tmp = tcg_temp_new_i64();
-        tcg_gen_setcond_i64(cond.c, tmp, cond.a0, cond.a1);
-        gen_helper_tcond(tcg_env, tmp);
+        gen_tc(ctx, &cond);
     }
 
     /* Write back the result.  */
@@ -1441,9 +1464,7 @@ static void do_unit_addsub(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
     }
 
     if (is_tc) {
-        TCGv_i64 tmp = tcg_temp_new_i64();
-        tcg_gen_setcond_i64(cond.c, tmp, cond.a0, cond.a1);
-        gen_helper_tcond(tcg_env, tmp);
+        gen_tc(ctx, &cond);
     }
     save_gpr(ctx, rt, dest);
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 30/43] target/hppa: Use delay_excp for conditional trap on overflow
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (28 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 29/43] target/hppa: Use delay_excp for conditional traps Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 31/43] linux-user/hppa: Force all code addresses to PRIV_USER Richard Henderson
                   ` (13 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/helper.h     |  1 -
 target/hppa/int_helper.c |  2 +-
 target/hppa/op_helper.c  |  7 -------
 target/hppa/translate.c  | 21 +++++++++++++--------
 4 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index 3d0d143aed..c12b48a04a 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -1,5 +1,4 @@
 DEF_HELPER_2(excp, noreturn, env, int)
-DEF_HELPER_FLAGS_2(tsv, TCG_CALL_NO_WG, void, env, tl)
 
 DEF_HELPER_FLAGS_3(stby_b, TCG_CALL_NO_WG, void, env, tl, tl)
 DEF_HELPER_FLAGS_3(stby_b_parallel, TCG_CALL_NO_WG, void, env, tl, tl)
diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
index 1aa3e88ef1..97e5f0b9a7 100644
--- a/target/hppa/int_helper.c
+++ b/target/hppa/int_helper.c
@@ -134,13 +134,13 @@ void hppa_cpu_do_interrupt(CPUState *cs)
         switch (i) {
         case EXCP_ILL:
         case EXCP_BREAK:
+        case EXCP_OVERFLOW:
         case EXCP_COND:
         case EXCP_PRIV_REG:
         case EXCP_PRIV_OPR:
             /* IIR set via translate.c.  */
             break;
 
-        case EXCP_OVERFLOW:
         case EXCP_ASSIST:
         case EXCP_DTLB_MISS:
         case EXCP_NA_ITLB_MISS:
diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index a8b69fd481..66cad78a57 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -42,13 +42,6 @@ G_NORETURN void hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra)
     cpu_loop_exit_restore(cs, ra);
 }
 
-void HELPER(tsv)(CPUHPPAState *env, target_ulong cond)
-{
-    if (unlikely((target_long)cond < 0)) {
-        hppa_dynamic_excp(env, EXCP_OVERFLOW, GETPC());
-    }
-}
-
 static void atomic_store_mask32(CPUHPPAState *env, target_ulong addr,
                                 uint32_t val, uint32_t mask, uintptr_t ra)
 {
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index ae291124f2..16b25a9ede 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -1136,6 +1136,17 @@ static void gen_tc(DisasContext *ctx, DisasCond *cond)
     }
 }
 
+static void gen_tsv(DisasContext *ctx, TCGv_i64 *sv, bool d)
+{
+    DisasCond cond = do_cond(ctx, /* SV */ 12, d, NULL, NULL, *sv);
+    DisasDelayException *e = delay_excp(ctx, EXCP_OVERFLOW);
+
+    tcg_gen_brcond_i64(cond.c, cond.a0, cond.a1, e->lab);
+
+    /* In the non-trap path, V is known zero. */
+    *sv = tcg_constant_i64(0);
+}
+
 static void do_add(DisasContext *ctx, unsigned rt, TCGv_i64 orig_in1,
                    TCGv_i64 in2, unsigned shift, bool is_l,
                    bool is_tsv, bool is_tc, bool is_c, unsigned cf, bool d)
@@ -1178,10 +1189,7 @@ static void do_add(DisasContext *ctx, unsigned rt, TCGv_i64 orig_in1,
     if (is_tsv || cond_need_sv(c)) {
         sv = do_add_sv(ctx, dest, in1, in2, orig_in1, shift, d);
         if (is_tsv) {
-            if (!d) {
-                tcg_gen_ext32s_i64(sv, sv);
-            }
-            gen_helper_tsv(tcg_env, sv);
+            gen_tsv(ctx, &sv, d);
         }
     }
 
@@ -1282,10 +1290,7 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
     if (is_tsv || cond_need_sv(c)) {
         sv = do_sub_sv(ctx, dest, in1, in2);
         if (is_tsv) {
-            if (!d) {
-                tcg_gen_ext32s_i64(sv, sv);
-            }
-            gen_helper_tsv(tcg_env, sv);
+            gen_tsv(ctx, &sv, d);
         }
     }
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 31/43] linux-user/hppa: Force all code addresses to PRIV_USER
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (29 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 30/43] target/hppa: Use delay_excp for conditional trap on overflow Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 32/43] target/hppa: Store full iaoq_f and page offset of iaoq_b in TB Richard Henderson
                   ` (12 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

The kernel does this along the return path to user mode.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/hppa/target_cpu.h |  4 ++--
 target/hppa/cpu.h            |  3 +++
 linux-user/elfload.c         |  4 ++--
 linux-user/hppa/cpu_loop.c   | 14 +++++++-------
 linux-user/hppa/signal.c     |  6 ++++--
 target/hppa/cpu.c            |  7 +++++--
 target/hppa/gdbstub.c        |  6 ++++++
 target/hppa/translate.c      |  4 ++--
 8 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/linux-user/hppa/target_cpu.h b/linux-user/hppa/target_cpu.h
index aacf3e9e02..4b84422a90 100644
--- a/linux-user/hppa/target_cpu.h
+++ b/linux-user/hppa/target_cpu.h
@@ -28,8 +28,8 @@ static inline void cpu_clone_regs_child(CPUHPPAState *env, target_ulong newsp,
     /* Indicate child in return value.  */
     env->gr[28] = 0;
     /* Return from the syscall.  */
-    env->iaoq_f = env->gr[31];
-    env->iaoq_b = env->gr[31] + 4;
+    env->iaoq_f = env->gr[31] | PRIV_USER;
+    env->iaoq_b = env->iaoq_f + 4;
 }
 
 static inline void cpu_clone_regs_parent(CPUHPPAState *env, unsigned flags)
diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index c37b4e12fb..5a1e720bb6 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -42,6 +42,9 @@
 #define MMU_IDX_TO_P(MIDX)          (((MIDX) - MMU_KERNEL_IDX) & 1)
 #define PRIV_P_TO_MMU_IDX(PRIV, P)  ((PRIV) * 2 + !!(P) + MMU_KERNEL_IDX)
 
+#define PRIV_KERNEL       0
+#define PRIV_USER         3
+
 #define TARGET_INSN_START_EXTRA_WORDS 2
 
 /* No need to flush MMU_ABS*_IDX  */
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index b473cda6b4..c1e1511ff2 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1887,8 +1887,8 @@ static inline void init_thread(struct target_pt_regs *regs,
 static inline void init_thread(struct target_pt_regs *regs,
                                struct image_info *infop)
 {
-    regs->iaoq[0] = infop->entry;
-    regs->iaoq[1] = infop->entry + 4;
+    regs->iaoq[0] = infop->entry | PRIV_USER;
+    regs->iaoq[1] = regs->iaoq[0] + 4;
     regs->gr[23] = 0;
     regs->gr[24] = infop->argv;
     regs->gr[25] = infop->argc;
diff --git a/linux-user/hppa/cpu_loop.c b/linux-user/hppa/cpu_loop.c
index d5232f37fe..bc093b8fe8 100644
--- a/linux-user/hppa/cpu_loop.c
+++ b/linux-user/hppa/cpu_loop.c
@@ -129,8 +129,8 @@ void cpu_loop(CPUHPPAState *env)
             default:
                 env->gr[28] = ret;
                 /* We arrived here by faking the gateway page.  Return.  */
-                env->iaoq_f = env->gr[31];
-                env->iaoq_b = env->gr[31] + 4;
+                env->iaoq_f = env->gr[31] | PRIV_USER;
+                env->iaoq_b = env->iaoq_f + 4;
                 break;
             case -QEMU_ERESTARTSYS:
             case -QEMU_ESIGRETURN:
@@ -140,8 +140,8 @@ void cpu_loop(CPUHPPAState *env)
         case EXCP_SYSCALL_LWS:
             env->gr[21] = hppa_lws(env);
             /* We arrived here by faking the gateway page.  Return.  */
-            env->iaoq_f = env->gr[31];
-            env->iaoq_b = env->gr[31] + 4;
+            env->iaoq_f = env->gr[31] | PRIV_USER;
+            env->iaoq_b = env->iaoq_f + 4;
             break;
         case EXCP_IMP:
             force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->iaoq_f);
@@ -152,9 +152,9 @@ void cpu_loop(CPUHPPAState *env)
         case EXCP_PRIV_OPR:
             /* check for glibc ABORT_INSTRUCTION "iitlbp %r0,(%sr0, %r0)" */
             if (env->cr[CR_IIR] == 0x04000000) {
-		    force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->iaoq_f);
+                force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->iaoq_f);
             } else {
-		    force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->iaoq_f);
+                force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->iaoq_f);
             }
             break;
         case EXCP_PRIV_REG:
@@ -170,7 +170,7 @@ void cpu_loop(CPUHPPAState *env)
             force_sig_fault(TARGET_SIGFPE, 0, env->iaoq_f);
             break;
         case EXCP_BREAK:
-            force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f & ~3);
+            force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f);
             break;
         case EXCP_DEBUG:
             force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f);
diff --git a/linux-user/hppa/signal.c b/linux-user/hppa/signal.c
index 682ba25922..f6f094c960 100644
--- a/linux-user/hppa/signal.c
+++ b/linux-user/hppa/signal.c
@@ -101,7 +101,9 @@ static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
     cpu_hppa_loaded_fr0(env);
 
     __get_user(env->iaoq_f, &sc->sc_iaoq[0]);
+    env->iaoq_f |= PRIV_USER;
     __get_user(env->iaoq_b, &sc->sc_iaoq[1]);
+    env->iaoq_b |= PRIV_USER;
     __get_user(env->cr[CR_SAR], &sc->sc_sar);
 }
 
@@ -162,8 +164,8 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
         unlock_user(fdesc, haddr, 0);
         haddr = dest;
     }
-    env->iaoq_f = haddr;
-    env->iaoq_b = haddr + 4;
+    env->iaoq_f = haddr | PRIV_USER;
+    env->iaoq_b = env->iaoq_f + 4;
     env->psw_n = 0;
     return;
 
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index be8c558014..a007de5521 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -32,6 +32,9 @@ static void hppa_cpu_set_pc(CPUState *cs, vaddr value)
 {
     HPPACPU *cpu = HPPA_CPU(cs);
 
+#ifdef CONFIG_USER_ONLY
+    value |= PRIV_USER;
+#endif
     cpu->env.iaoq_f = value;
     cpu->env.iaoq_b = value + 4;
 }
@@ -93,8 +96,8 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs,
     tcg_debug_assert(!tcg_cflags_has(cs, CF_PCREL));
 
 #ifdef CONFIG_USER_ONLY
-    cpu->env.iaoq_f = tb->pc;
-    cpu->env.iaoq_b = tb->cs_base;
+    cpu->env.iaoq_f = tb->pc | PRIV_USER;
+    cpu->env.iaoq_b = tb->cs_base | PRIV_USER;
 #else
     /* Recover the IAOQ values from the GVA + PRIV.  */
     uint32_t priv = (tb->flags >> TB_FLAG_PRIV_SHIFT) & 3;
diff --git a/target/hppa/gdbstub.c b/target/hppa/gdbstub.c
index 4a965b38d7..0daa52f7af 100644
--- a/target/hppa/gdbstub.c
+++ b/target/hppa/gdbstub.c
@@ -163,12 +163,18 @@ int hppa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
         env->cr[CR_SAR] = val & (hppa_is_pa20(env) ? 63 : 31);
         break;
     case 33:
+#ifdef CONFIG_USER_ONLY
+        val |= PRIV_USER;
+#endif
         env->iaoq_f = val;
         break;
     case 34:
         env->iasq_f = (uint64_t)val << 32;
         break;
     case 35:
+#ifdef CONFIG_USER_ONLY
+        val |= PRIV_USER;
+#endif
         env->iaoq_b = val;
         break;
     case 36:
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 16b25a9ede..12359bafb6 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2054,7 +2054,7 @@ static void do_page_zero(DisasContext *ctx)
 
             tcg_gen_st_i64(cpu_gr[26], tcg_env,
                            offsetof(CPUHPPAState, cr[27]));
-            tcg_gen_ori_i64(next.base, cpu_gr[31], 3);
+            tcg_gen_ori_i64(next.base, cpu_gr[31], PRIV_USER);
             install_iaq_entries(ctx, &next, NULL);
             ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
         }
@@ -4583,7 +4583,7 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     ctx->is_pa20 = hppa_is_pa20(cpu_env(cs));
 
 #ifdef CONFIG_USER_ONLY
-    ctx->privilege = MMU_IDX_TO_PRIV(MMU_USER_IDX);
+    ctx->privilege = PRIV_USER;
     ctx->mmu_idx = MMU_USER_IDX;
     ctx->iaoq_first = ctx->base.pc_first | ctx->privilege;
     ctx->iaq_b.disp = ctx->base.tb->cs_base - ctx->base.pc_first;
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 32/43] target/hppa: Store full iaoq_f and page offset of iaoq_b in TB
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (30 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 31/43] linux-user/hppa: Force all code addresses to PRIV_USER Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 33/43] target/hppa: Do not mask in copy_iaoq_entry Richard Henderson
                   ` (11 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

In preparation for CF_PCREL. store the iaoq_f in 3 parts: high
bits in cs_base, middle bits in pc, and low bits in priv.
For iaoq_b, set a bit for either of space or page differing,
else the page offset.

Install iaq entries before goto_tb. The change to not record
the full direct branch difference in TB means that we have to
store at least iaoq_b before goto_tb.  But since a later change
to enable CF_PCREL will require both iaoq_f and iaoq_b to be
updated before goto_tb, go ahead and update both fields now.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/cpu.h       |  2 ++
 target/hppa/cpu.c       | 72 ++++++++++++++++++-----------------------
 target/hppa/translate.c | 29 +++++++++--------
 3 files changed, 48 insertions(+), 55 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 5a1e720bb6..1232a4cef2 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -341,6 +341,8 @@ hwaddr hppa_abs_to_phys_pa2_w1(vaddr addr);
 #define TB_FLAG_SR_SAME     PSW_I
 #define TB_FLAG_PRIV_SHIFT  8
 #define TB_FLAG_UNALIGN     0x400
+#define CS_BASE_DIFFPAGE    (1 << 12)
+#define CS_BASE_DIFFSPACE   (1 << 13)
 
 void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
                           uint64_t *cs_base, uint32_t *pflags);
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index a007de5521..003af63e20 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -48,36 +48,43 @@ static vaddr hppa_cpu_get_pc(CPUState *cs)
 }
 
 void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
-                          uint64_t *cs_base, uint32_t *pflags)
+                          uint64_t *pcsbase, uint32_t *pflags)
 {
     uint32_t flags = env->psw_n * PSW_N;
+    uint64_t cs_base = 0;
+
+    /*
+     * TB lookup assumes that PC contains the complete virtual address.
+     * If we leave space+offset separate, we'll get ITLB misses to an
+     * incomplete virtual address.  This also means that we must separate
+     * out current cpu privilege from the low bits of IAOQ_F.
+     */
+    *pc = hppa_cpu_get_pc(env_cpu(env));
+    flags |= (env->iaoq_f & 3) << TB_FLAG_PRIV_SHIFT;
+
+    if (hppa_is_pa20(env)) {
+        cs_base = env->iaoq_f & MAKE_64BIT_MASK(32, 32);
+    }
+
+    /*
+     * The only really interesting case is if IAQ_Back is on the same page
+     * as IAQ_Front, so that we can use goto_tb between the blocks.  In all
+     * other cases, we'll be ending the TranslationBlock with one insn and
+     * not linking between them.
+     */
+    if (env->iasq_f != env->iasq_b) {
+        cs_base |= CS_BASE_DIFFSPACE;
+    } else if ((env->iaoq_f ^ env->iaoq_b) & TARGET_PAGE_MASK) {
+        cs_base |= CS_BASE_DIFFPAGE;
+    } else {
+        cs_base |= env->iaoq_b & ~TARGET_PAGE_MASK;
+    }
 
-    /* TB lookup assumes that PC contains the complete virtual address.
-       If we leave space+offset separate, we'll get ITLB misses to an
-       incomplete virtual address.  This also means that we must separate
-       out current cpu privilege from the low bits of IAOQ_F.  */
 #ifdef CONFIG_USER_ONLY
-    *pc = env->iaoq_f & -4;
-    *cs_base = env->iaoq_b & -4;
     flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
 #else
     /* ??? E, T, H, L, B bits need to be here, when implemented.  */
     flags |= env->psw & (PSW_W | PSW_C | PSW_D | PSW_P);
-    flags |= (env->iaoq_f & 3) << TB_FLAG_PRIV_SHIFT;
-
-    *pc = hppa_cpu_get_pc(env_cpu(env));
-    *cs_base = env->iasq_f;
-
-    /* Insert a difference between IAOQ_B and IAOQ_F within the otherwise zero
-       low 32-bits of CS_BASE.  This will succeed for all direct branches,
-       which is the primary case we care about -- using goto_tb within a page.
-       Failure is indicated by a zero difference.  */
-    if (env->iasq_f == env->iasq_b) {
-        target_long diff = env->iaoq_b - env->iaoq_f;
-        if (diff == (int32_t)diff) {
-            *cs_base |= (uint32_t)diff;
-        }
-    }
     if ((env->sr[4] == env->sr[5])
         & (env->sr[4] == env->sr[6])
         & (env->sr[4] == env->sr[7])) {
@@ -85,6 +92,7 @@ void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
     }
 #endif
 
+    *pcsbase = cs_base;
     *pflags = flags;
 }
 
@@ -93,25 +101,7 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs,
 {
     HPPACPU *cpu = HPPA_CPU(cs);
 
-    tcg_debug_assert(!tcg_cflags_has(cs, CF_PCREL));
-
-#ifdef CONFIG_USER_ONLY
-    cpu->env.iaoq_f = tb->pc | PRIV_USER;
-    cpu->env.iaoq_b = tb->cs_base | PRIV_USER;
-#else
-    /* Recover the IAOQ values from the GVA + PRIV.  */
-    uint32_t priv = (tb->flags >> TB_FLAG_PRIV_SHIFT) & 3;
-    target_ulong cs_base = tb->cs_base;
-    target_ulong iasq_f = cs_base & ~0xffffffffull;
-    int32_t diff = cs_base;
-
-    cpu->env.iasq_f = iasq_f;
-    cpu->env.iaoq_f = (tb->pc & ~iasq_f) + priv;
-    if (diff) {
-        cpu->env.iaoq_b = cpu->env.iaoq_f + diff;
-    }
-#endif
-
+    /* IAQ is always up-to-date before goto_tb. */
     cpu->env.psw_n = (tb->flags & PSW_N) != 0;
 }
 
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 12359bafb6..70df42f558 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -770,12 +770,11 @@ static bool use_nullify_skip(DisasContext *ctx)
 static void gen_goto_tb(DisasContext *ctx, int which,
                         const DisasIAQE *f, const DisasIAQE *b)
 {
+    install_iaq_entries(ctx, f, b);
     if (use_goto_tb(ctx, f, b)) {
         tcg_gen_goto_tb(which);
-        install_iaq_entries(ctx, f, b);
         tcg_gen_exit_tb(ctx->base.tb, which);
     } else {
-        install_iaq_entries(ctx, f, b);
         tcg_gen_lookup_and_goto_ptr();
     }
 }
@@ -4576,6 +4575,7 @@ static bool trans_diag_unimp(DisasContext *ctx, arg_diag_unimp *a)
 static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
 {
     DisasContext *ctx = container_of(dcbase, DisasContext, base);
+    uint64_t cs_base, iaoq_f, iaoq_b;
     int bound;
 
     ctx->cs = cs;
@@ -4585,29 +4585,30 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
 #ifdef CONFIG_USER_ONLY
     ctx->privilege = PRIV_USER;
     ctx->mmu_idx = MMU_USER_IDX;
-    ctx->iaoq_first = ctx->base.pc_first | ctx->privilege;
-    ctx->iaq_b.disp = ctx->base.tb->cs_base - ctx->base.pc_first;
     ctx->unalign = (ctx->tb_flags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN);
 #else
     ctx->privilege = (ctx->tb_flags >> TB_FLAG_PRIV_SHIFT) & 3;
     ctx->mmu_idx = (ctx->tb_flags & PSW_D
                     ? PRIV_P_TO_MMU_IDX(ctx->privilege, ctx->tb_flags & PSW_P)
                     : ctx->tb_flags & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX);
+#endif
 
     /* Recover the IAOQ values from the GVA + PRIV.  */
-    uint64_t cs_base = ctx->base.tb->cs_base;
-    uint64_t iasq_f = cs_base & ~0xffffffffull;
-    int32_t diff = cs_base;
+    cs_base = ctx->base.tb->cs_base;
+    iaoq_f = cs_base & MAKE_64BIT_MASK(32, 32);
+    iaoq_f |= ctx->base.pc_first & MAKE_64BIT_MASK(2, 30);
+    iaoq_f |= ctx->privilege;
+    ctx->iaoq_first = iaoq_f;
 
-    ctx->iaoq_first = (ctx->base.pc_first & ~iasq_f) + ctx->privilege;
-
-    if (diff) {
-        ctx->iaq_b.disp = diff;
-    } else {
-        ctx->iaq_b.base = cpu_iaoq_b;
+    if (unlikely(cs_base & CS_BASE_DIFFSPACE)) {
         ctx->iaq_b.space = cpu_iasq_b;
+        ctx->iaq_b.base = cpu_iaoq_b;
+    } else if (unlikely(cs_base & CS_BASE_DIFFPAGE)) {
+        ctx->iaq_b.base = cpu_iaoq_b;
+    } else {
+        iaoq_b = (iaoq_f & TARGET_PAGE_MASK) | (cs_base & ~TARGET_PAGE_MASK);
+        ctx->iaq_b.disp = iaoq_b - iaoq_f;
     }
-#endif
 
     ctx->zero = tcg_constant_i64(0);
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 33/43] target/hppa: Do not mask in copy_iaoq_entry
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (31 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 32/43] target/hppa: Store full iaoq_f and page offset of iaoq_b in TB Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 34/43] target/hppa: Improve hppa_cpu_dump_state Richard Henderson
                   ` (10 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

As with loads and stores, code offsets are kept intact until the
full gva is formed.  In qemu, this is in cpu_get_tb_cpu_state.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 70df42f558..ab8dd161ad 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -637,15 +637,10 @@ static DisasIAQE iaqe_next_absv(DisasContext *ctx, TCGv_i64 var)
 static void copy_iaoq_entry(DisasContext *ctx, TCGv_i64 dest,
                             const DisasIAQE *src)
 {
-    uint64_t mask = gva_offset_mask(ctx->tb_flags);
-
     if (src->base == NULL) {
-        tcg_gen_movi_i64(dest, (ctx->iaoq_first + src->disp) & mask);
-    } else if (src->disp == 0) {
-        tcg_gen_andi_i64(dest, src->base, mask);
+        tcg_gen_movi_i64(dest, ctx->iaoq_first + src->disp);
     } else {
         tcg_gen_addi_i64(dest, src->base, src->disp);
-        tcg_gen_andi_i64(dest, dest, mask);
     }
 }
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 34/43] target/hppa: Improve hppa_cpu_dump_state
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (32 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 33/43] target/hppa: Do not mask in copy_iaoq_entry Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 35/43] target/hppa: Split PSW X and B into their own field Richard Henderson
                   ` (9 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Print both raw IAQ_Front and IAQ_Back as well as the GVAs.
Print control registers in system mode.
Print floating point registers if CPU_DUMP_FPU.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/helper.c | 60 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 54 insertions(+), 6 deletions(-)

diff --git a/target/hppa/helper.c b/target/hppa/helper.c
index 9d217d051c..7d22c248fb 100644
--- a/target/hppa/helper.c
+++ b/target/hppa/helper.c
@@ -102,6 +102,19 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw)
 
 void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
 {
+#ifndef CONFIG_USER_ONLY
+    static const char cr_name[32][5] = {
+        "RC",    "CR1",   "CR2",   "CR3",
+        "CR4",   "CR5",   "CR6",   "CR7",
+        "PID1",  "PID2",  "CCR",   "SAR",
+        "PID3",  "PID4",  "IVA",   "EIEM",
+        "ITMR",  "ISQF",  "IOQF",  "IIR",
+        "ISR",   "IOR",   "IPSW",  "EIRR",
+        "TR0",   "TR1",   "TR2",   "TR3",
+        "TR4",   "TR5",   "TR6",   "TR7",
+    };
+#endif
+
     CPUHPPAState *env = cpu_env(cs);
     target_ulong psw = cpu_hppa_get_psw(env);
     target_ulong psw_cb;
@@ -117,11 +130,12 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
         m = UINT32_MAX;
     }
 
-    qemu_fprintf(f, "IA_F " TARGET_FMT_lx " IA_B " TARGET_FMT_lx
-                 " IIR %0*" PRIx64 "\n",
+    qemu_fprintf(f, "IA_F %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n"
+                    "IA_B %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n",
+                 env->iasq_f >> 32, w, m & env->iaoq_f,
                  hppa_form_gva_psw(psw, env->iasq_f, env->iaoq_f),
-                 hppa_form_gva_psw(psw, env->iasq_b, env->iaoq_b),
-                 w, m & env->cr[CR_IIR]);
+                 env->iasq_b >> 32, w, m & env->iaoq_b,
+                 hppa_form_gva_psw(psw, env->iasq_b, env->iaoq_b));
 
     psw_c[0]  = (psw & PSW_W ? 'W' : '-');
     psw_c[1]  = (psw & PSW_E ? 'E' : '-');
@@ -154,12 +168,46 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
                      (i & 3) == 3 ? '\n' : ' ');
     }
 #ifndef CONFIG_USER_ONLY
+    for (i = 0; i < 32; i++) {
+        qemu_fprintf(f, "%-4s %0*" PRIx64 "%c",
+                     cr_name[i], w, m & env->cr[i],
+                     (i & 3) == 3 ? '\n' : ' ');
+    }
+    qemu_fprintf(f, "ISQB %0*" PRIx64 " IOQB %0*" PRIx64 "\n",
+                 w, m & env->cr_back[0], w, m & env->cr_back[1]);
     for (i = 0; i < 8; i++) {
         qemu_fprintf(f, "SR%02d %08x%c", i, (uint32_t)(env->sr[i] >> 32),
                      (i & 3) == 3 ? '\n' : ' ');
     }
 #endif
-     qemu_fprintf(f, "\n");
 
-    /* ??? FR */
+    if (flags & CPU_DUMP_FPU) {
+        static const char rm[4][4] = { "RN", "RZ", "R+", "R-" };
+        char flg[6], ena[6];
+        uint32_t fpsr = env->fr0_shadow;
+
+        flg[0] = (fpsr & R_FPSR_FLG_V_MASK ? 'V' : '-');
+        flg[1] = (fpsr & R_FPSR_FLG_Z_MASK ? 'Z' : '-');
+        flg[2] = (fpsr & R_FPSR_FLG_O_MASK ? 'O' : '-');
+        flg[3] = (fpsr & R_FPSR_FLG_U_MASK ? 'U' : '-');
+        flg[4] = (fpsr & R_FPSR_FLG_I_MASK ? 'I' : '-');
+        flg[5] = '\0';
+
+        ena[0] = (fpsr & R_FPSR_ENA_V_MASK ? 'V' : '-');
+        ena[1] = (fpsr & R_FPSR_ENA_Z_MASK ? 'Z' : '-');
+        ena[2] = (fpsr & R_FPSR_ENA_O_MASK ? 'O' : '-');
+        ena[3] = (fpsr & R_FPSR_ENA_U_MASK ? 'U' : '-');
+        ena[4] = (fpsr & R_FPSR_ENA_I_MASK ? 'I' : '-');
+        ena[5] = '\0';
+
+        qemu_fprintf(f, "FPSR %08x flag    %s enable  %s %s\n",
+                     fpsr, flg, ena, rm[FIELD_EX32(fpsr, FPSR, RM)]);
+
+        for (i = 0; i < 32; i++) {
+            qemu_fprintf(f, "FR%02d %016" PRIx64 "%c",
+                     i, env->fr[i], (i & 3) == 3 ? '\n' : ' ');
+        }
+    }
+
+    qemu_fprintf(f, "\n");
 }
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 35/43] target/hppa: Split PSW X and B into their own field
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (33 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 34/43] target/hppa: Improve hppa_cpu_dump_state Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 36/43] target/hppa: Manage PSW_X and PSW_B in translator Richard Henderson
                   ` (8 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller, Philippe Mathieu-Daudé

Generally, both of these bits are cleared at the end of each
instruction.  By separating these, we will be able to clear
both with a single insn, instead of 2 or 3.

Reviewed-by: Helge Deller <deller@gmx.de>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/cpu.h    | 3 ++-
 target/hppa/helper.c | 6 +++---
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 1232a4cef2..f247ad56d7 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -208,7 +208,8 @@ typedef struct CPUArchState {
     uint64_t fr[32];
     uint64_t sr[8];          /* stored shifted into place for gva */
 
-    target_ulong psw;        /* All psw bits except the following:  */
+    uint32_t psw;            /* All psw bits except the following:  */
+    uint32_t psw_xb;         /* X and B, in their normal positions */
     target_ulong psw_n;      /* boolean */
     target_long psw_v;       /* in most significant bit */
 
diff --git a/target/hppa/helper.c b/target/hppa/helper.c
index 7d22c248fb..b79ddd8184 100644
--- a/target/hppa/helper.c
+++ b/target/hppa/helper.c
@@ -54,7 +54,7 @@ target_ulong cpu_hppa_get_psw(CPUHPPAState *env)
 
     psw |= env->psw_n * PSW_N;
     psw |= (env->psw_v < 0) * PSW_V;
-    psw |= env->psw;
+    psw |= env->psw | env->psw_xb;
 
     return psw;
 }
@@ -76,8 +76,8 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw)
     }
     psw &= ~reserved;
 
-    env->psw = psw & (uint32_t)~(PSW_N | PSW_V | PSW_CB);
-
+    env->psw = psw & (uint32_t)~(PSW_B | PSW_N | PSW_V | PSW_X | PSW_CB);
+    env->psw_xb = psw & (PSW_X | PSW_B);
     env->psw_n = (psw / PSW_N) & 1;
     env->psw_v = -((psw / PSW_V) & 1);
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 36/43] target/hppa: Manage PSW_X and PSW_B in translator
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (34 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 35/43] target/hppa: Split PSW X and B into their own field Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 37/43] target/hppa: Implement PSW_B Richard Henderson
                   ` (7 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

PSW_X is cleared after every instruction, and only set by RFI.
PSW_B is cleared after every non-branch, or branch not taken,
and only set by taken branches.  We can clear both bits with a
single store, at most once per TB.  Taken branches set PSW_B,
at most once per TB.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/cpu.c       | 10 ++++++---
 target/hppa/translate.c | 50 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index 003af63e20..5f0df0697a 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -50,7 +50,7 @@ static vaddr hppa_cpu_get_pc(CPUState *cs)
 void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
                           uint64_t *pcsbase, uint32_t *pflags)
 {
-    uint32_t flags = env->psw_n * PSW_N;
+    uint32_t flags = 0;
     uint64_t cs_base = 0;
 
     /*
@@ -80,11 +80,14 @@ void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
         cs_base |= env->iaoq_b & ~TARGET_PAGE_MASK;
     }
 
+    /* ??? E, T, H, L bits need to be here, when implemented.  */
+    flags |= env->psw_n * PSW_N;
+    flags |= env->psw_xb;
+    flags |= env->psw & (PSW_W | PSW_C | PSW_D | PSW_P);
+
 #ifdef CONFIG_USER_ONLY
     flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
 #else
-    /* ??? E, T, H, L, B bits need to be here, when implemented.  */
-    flags |= env->psw & (PSW_W | PSW_C | PSW_D | PSW_P);
     if ((env->sr[4] == env->sr[5])
         & (env->sr[4] == env->sr[6])
         & (env->sr[4] == env->sr[7])) {
@@ -103,6 +106,7 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs,
 
     /* IAQ is always up-to-date before goto_tb. */
     cpu->env.psw_n = (tb->flags & PSW_N) != 0;
+    cpu->env.psw_xb = tb->flags & (PSW_X | PSW_B);
 }
 
 static void hppa_restore_state_to_opc(CPUState *cs,
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index ab8dd161ad..f7d54f4009 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -84,7 +84,9 @@ typedef struct DisasContext {
     uint32_t tb_flags;
     int mmu_idx;
     int privilege;
+    uint32_t psw_xb;
     bool psw_n_nonzero;
+    bool psw_b_next;
     bool is_pa20;
     bool insn_start_updated;
 
@@ -263,6 +265,7 @@ static TCGv_i64 cpu_psw_n;
 static TCGv_i64 cpu_psw_v;
 static TCGv_i64 cpu_psw_cb;
 static TCGv_i64 cpu_psw_cb_msb;
+static TCGv_i32 cpu_psw_xb;
 
 void hppa_translate_init(void)
 {
@@ -315,6 +318,9 @@ void hppa_translate_init(void)
         *v->var = tcg_global_mem_new(tcg_env, v->ofs, v->name);
     }
 
+    cpu_psw_xb = tcg_global_mem_new_i32(tcg_env,
+                                        offsetof(CPUHPPAState, psw_xb),
+                                        "psw_xb");
     cpu_iasq_f = tcg_global_mem_new_i64(tcg_env,
                                         offsetof(CPUHPPAState, iasq_f),
                                         "iasq_f");
@@ -509,6 +515,25 @@ static void load_spr(DisasContext *ctx, TCGv_i64 dest, unsigned reg)
 #endif
 }
 
+/*
+ * Write a value to psw_xb, bearing in mind the known value.
+ * To be used just before exiting the TB, so do not update the known value.
+ */
+static void store_psw_xb(DisasContext *ctx, uint32_t xb)
+{
+    tcg_debug_assert(xb == 0 || xb == PSW_B);
+    if (ctx->psw_xb != xb) {
+        tcg_gen_movi_i32(cpu_psw_xb, xb);
+    }
+}
+
+/* Write a value to psw_xb, and update the known value. */
+static void set_psw_xb(DisasContext *ctx, uint32_t xb)
+{
+    store_psw_xb(ctx, xb);
+    ctx->psw_xb = xb;
+}
+
 /* Skip over the implementation of an insn that has been nullified.
    Use this when the insn is too complex for a conditional move.  */
 static void nullify_over(DisasContext *ctx)
@@ -576,6 +601,8 @@ static bool nullify_end(DisasContext *ctx)
     /* For NEXT, NORETURN, STALE, we can easily continue (or exit).
        For UPDATED, we cannot update on the nullified path.  */
     assert(status != DISAS_IAQ_N_UPDATED);
+    /* Taken branches are handled manually. */
+    assert(!ctx->psw_b_next);
 
     if (likely(null_lab == NULL)) {
         /* The current insn wasn't conditional or handled the condition
@@ -1843,6 +1870,7 @@ static bool do_dbranch(DisasContext *ctx, int64_t disp,
         if (is_n) {
             if (use_nullify_skip(ctx)) {
                 nullify_set(ctx, 0);
+                store_psw_xb(ctx, 0);
                 gen_goto_tb(ctx, 0, &ctx->iaq_j, NULL);
                 ctx->base.is_jmp = DISAS_NORETURN;
                 return true;
@@ -1850,20 +1878,24 @@ static bool do_dbranch(DisasContext *ctx, int64_t disp,
             ctx->null_cond.c = TCG_COND_ALWAYS;
         }
         ctx->iaq_n = &ctx->iaq_j;
+        ctx->psw_b_next = true;
     } else {
         nullify_over(ctx);
 
         install_link(ctx, link, false);
         if (is_n && use_nullify_skip(ctx)) {
             nullify_set(ctx, 0);
+            store_psw_xb(ctx, 0);
             gen_goto_tb(ctx, 0, &ctx->iaq_j, NULL);
         } else {
             nullify_set(ctx, is_n);
+            store_psw_xb(ctx, PSW_B);
             gen_goto_tb(ctx, 0, &ctx->iaq_b, &ctx->iaq_j);
         }
         nullify_end(ctx);
 
         nullify_set(ctx, 0);
+        store_psw_xb(ctx, 0);
         gen_goto_tb(ctx, 1, &ctx->iaq_b, NULL);
         ctx->base.is_jmp = DISAS_NORETURN;
     }
@@ -1894,6 +1926,7 @@ static bool do_cbranch(DisasContext *ctx, int64_t disp, bool is_n,
     n = is_n && disp < 0;
     if (n && use_nullify_skip(ctx)) {
         nullify_set(ctx, 0);
+        store_psw_xb(ctx, 0);
         next = iaqe_incr(&ctx->iaq_b, 4);
         gen_goto_tb(ctx, 0, &next, NULL);
     } else {
@@ -1902,6 +1935,7 @@ static bool do_cbranch(DisasContext *ctx, int64_t disp, bool is_n,
             ctx->null_lab = NULL;
         }
         nullify_set(ctx, n);
+        store_psw_xb(ctx, 0);
         gen_goto_tb(ctx, 0, &ctx->iaq_b, NULL);
     }
 
@@ -1913,9 +1947,11 @@ static bool do_cbranch(DisasContext *ctx, int64_t disp, bool is_n,
     next = iaqe_branchi(ctx, disp);
     if (n && use_nullify_skip(ctx)) {
         nullify_set(ctx, 0);
+        store_psw_xb(ctx, 0);
         gen_goto_tb(ctx, 1, &next, NULL);
     } else {
         nullify_set(ctx, n);
+        store_psw_xb(ctx, PSW_B);
         gen_goto_tb(ctx, 1, &ctx->iaq_b, &next);
     }
 
@@ -1949,6 +1985,7 @@ static bool do_ibranch(DisasContext *ctx, unsigned link,
             ctx->null_cond.c = TCG_COND_ALWAYS;
         }
         ctx->iaq_n = &ctx->iaq_j;
+        ctx->psw_b_next = true;
         return true;
     }
 
@@ -1958,9 +1995,11 @@ static bool do_ibranch(DisasContext *ctx, unsigned link,
     if (is_n && use_nullify_skip(ctx)) {
         install_iaq_entries(ctx, &ctx->iaq_j, NULL);
         nullify_set(ctx, 0);
+        store_psw_xb(ctx, 0);
     } else {
         install_iaq_entries(ctx, &ctx->iaq_b, &ctx->iaq_j);
         nullify_set(ctx, is_n);
+        store_psw_xb(ctx, PSW_B);
     }
 
     tcg_gen_lookup_and_goto_ptr();
@@ -2387,6 +2426,7 @@ static bool trans_halt(DisasContext *ctx, arg_halt *a)
 {
     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
 #ifndef CONFIG_USER_ONLY
+    set_psw_xb(ctx, 0);
     nullify_over(ctx);
     gen_helper_halt(tcg_env);
     ctx->base.is_jmp = DISAS_NORETURN;
@@ -2398,6 +2438,7 @@ static bool trans_reset(DisasContext *ctx, arg_reset *a)
 {
     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
 #ifndef CONFIG_USER_ONLY
+    set_psw_xb(ctx, 0);
     nullify_over(ctx);
     gen_helper_reset(tcg_env);
     ctx->base.is_jmp = DISAS_NORETURN;
@@ -2792,6 +2833,9 @@ static bool trans_or(DisasContext *ctx, arg_rrr_cf_d *a)
         if ((rt == 10 || rt == 31) && r1 == rt && r2 == rt) { /* PAUSE */
             /* No need to check for supervisor, as userland can only pause
                until the next timer interrupt.  */
+
+            set_psw_xb(ctx, 0);
+
             nullify_over(ctx);
 
             /* Advance the instruction queue.  */
@@ -4576,6 +4620,7 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     ctx->cs = cs;
     ctx->tb_flags = ctx->base.tb->flags;
     ctx->is_pa20 = hppa_is_pa20(cpu_env(cs));
+    ctx->psw_xb = ctx->tb_flags & (PSW_X | PSW_B);
 
 #ifdef CONFIG_USER_ONLY
     ctx->privilege = PRIV_USER;
@@ -4662,6 +4707,7 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
          */
         ctx->iaq_n = NULL;
         memset(&ctx->iaq_j, 0, sizeof(ctx->iaq_j));
+        ctx->psw_b_next = false;
 
         if (unlikely(ctx->null_cond.c == TCG_COND_ALWAYS)) {
             ctx->null_cond.c = TCG_COND_NEVER;
@@ -4674,6 +4720,10 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
             ret = ctx->base.is_jmp;
             assert(ctx->null_lab == NULL);
         }
+
+        if (ret != DISAS_NORETURN) {
+            set_psw_xb(ctx, ctx->psw_b_next ? PSW_B : 0);
+        }
     }
 
     /* If the TranslationBlock must end, do so. */
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 37/43] target/hppa: Implement PSW_B
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (35 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 36/43] target/hppa: Manage PSW_X and PSW_B in translator Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 38/43] target/hppa: Implement PSW_X Richard Henderson
                   ` (6 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

PSW_B causes B,GATE to trap as an illegal instruction, removing our
previous sequential execution test that was merely an approximation.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 25 ++++++-------------------
 1 file changed, 6 insertions(+), 19 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index f7d54f4009..f40ac92e98 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2062,11 +2062,8 @@ static void do_page_zero(DisasContext *ctx)
         g_assert_not_reached();
     }
 
-    /* Check that we didn't arrive here via some means that allowed
-       non-sequential instruction execution.  Normally the PSW[B] bit
-       detects this by disallowing the B,GATE instruction to execute
-       under such conditions.  */
-    if (iaqe_variable(&ctx->iaq_b) || ctx->iaq_b.disp != 4) {
+    /* If PSW[B] is set, the B,GATE insn would trap. */
+    if (ctx->psw_xb & PSW_B) {
         goto do_sigill;
     }
 
@@ -3965,23 +3962,13 @@ static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
 {
     int64_t disp = a->disp;
 
-    nullify_over(ctx);
-
-    /* Make sure the caller hasn't done something weird with the queue.
-     * ??? This is not quite the same as the PSW[B] bit, which would be
-     * expensive to track.  Real hardware will trap for
-     *    b  gateway
-     *    b  gateway+4  (in delay slot of first branch)
-     * However, checking for a non-sequential instruction queue *will*
-     * diagnose the security hole
-     *    b  gateway
-     *    b  evil
-     * in which instructions at evil would run with increased privs.
-     */
-    if (iaqe_variable(&ctx->iaq_b) || ctx->iaq_b.disp != ctx->iaq_f.disp + 4) {
+    /* Trap if PSW[B] is set. */
+    if (ctx->psw_xb & PSW_B) {
         return gen_illegal(ctx);
     }
 
+    nullify_over(ctx);
+
 #ifndef CONFIG_USER_ONLY
     if (ctx->tb_flags & PSW_C) {
         int type = hppa_artype_for_page(cpu_env(ctx->cs), ctx->base.pc_next);
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 38/43] target/hppa: Implement PSW_X
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (36 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 37/43] target/hppa: Implement PSW_B Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 39/43] target/hppa: Drop tlb_entry return from hppa_get_physical_address Richard Henderson
                   ` (5 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Use PAGE_WRITE_INV to temporarily enable write permission
on for a given page, driven by PSW_X being set.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/mem_helper.c | 46 +++++++++++++++++++++++-----------------
 1 file changed, 27 insertions(+), 19 deletions(-)

diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index d09877afd7..ca7bbe0a7c 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -296,30 +296,38 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
         goto egress;
     }
 
-    /* In reverse priority order, check for conditions which raise faults.
-       As we go, remove PROT bits that cover the condition we want to check.
-       In this way, the resulting PROT will force a re-check of the
-       architectural TLB entry for the next access.  */
-    if (unlikely(!ent->d)) {
-        if (type & PAGE_WRITE) {
-            /* The D bit is not set -- TLB Dirty Bit Fault.  */
-            ret = EXCP_TLB_DIRTY;
-        }
-        prot &= PAGE_READ | PAGE_EXEC;
-    }
-    if (unlikely(ent->b)) {
-        if (type & PAGE_WRITE) {
-            /* The B bit is set -- Data Memory Break Fault.  */
-            ret = EXCP_DMB;
-        }
-        prot &= PAGE_READ | PAGE_EXEC;
-    }
+    /*
+     * In priority order, check for conditions which raise faults.
+     * Remove PROT bits that cover the condition we want to check,
+     * so that the resulting PROT will force a re-check of the
+     * architectural TLB entry for the next access.
+     */
     if (unlikely(ent->t)) {
+        prot &= PAGE_EXEC;
         if (!(type & PAGE_EXEC)) {
             /* The T bit is set -- Page Reference Fault.  */
             ret = EXCP_PAGE_REF;
         }
-        prot &= PAGE_EXEC;
+    } else if (!ent->d) {
+        prot &= PAGE_READ | PAGE_EXEC;
+        if (type & PAGE_WRITE) {
+            /* The D bit is not set -- TLB Dirty Bit Fault.  */
+            ret = EXCP_TLB_DIRTY;
+        }
+    } else if (unlikely(ent->b)) {
+        prot &= PAGE_READ | PAGE_EXEC;
+        if (type & PAGE_WRITE) {
+            /*
+             * The B bit is set -- Data Memory Break Fault.
+             * Except when PSW_X is set, allow this single access to succeed.
+             * The write bit will be invalidated for subsequent accesses.
+             */
+            if (env->psw_xb & PSW_X) {
+                prot |= PAGE_WRITE_INV;
+            } else {
+                ret = EXCP_DMB;
+            }
+        }
     }
 
  egress:
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 39/43] target/hppa: Drop tlb_entry return from hppa_get_physical_address
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (37 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 38/43] target/hppa: Implement PSW_X Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 40/43] target/hppa: Adjust priv for B,GATE at runtime Richard Henderson
                   ` (4 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller, Philippe Mathieu-Daudé

The return-by-reference is never used.

Reviewed-by: Helge Deller <deller@gmx.de>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/cpu.h        |  3 +--
 target/hppa/int_helper.c |  2 +-
 target/hppa/mem_helper.c | 19 ++++---------------
 target/hppa/op_helper.c  |  3 +--
 4 files changed, 7 insertions(+), 20 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index f247ad56d7..78ab0adcd0 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -371,8 +371,7 @@ bool hppa_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 void hppa_cpu_do_interrupt(CPUState *cpu);
 bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req);
 int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
-                              int type, hwaddr *pphys, int *pprot,
-                              HPPATLBEntry **tlb_entry);
+                              int type, hwaddr *pphys, int *pprot);
 void hppa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
                                      vaddr addr, unsigned size,
                                      MMUAccessType access_type,
diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
index 97e5f0b9a7..b82f32fd12 100644
--- a/target/hppa/int_helper.c
+++ b/target/hppa/int_helper.c
@@ -167,7 +167,7 @@ void hppa_cpu_do_interrupt(CPUState *cs)
 
                     vaddr = hppa_form_gva_psw(old_psw, env->iasq_f, vaddr);
                     t = hppa_get_physical_address(env, vaddr, MMU_KERNEL_IDX,
-                                                  0, &paddr, &prot, NULL);
+                                                  0, &paddr, &prot);
                     if (t >= 0) {
                         /* We can't re-load the instruction.  */
                         env->cr[CR_IIR] = 0;
diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index ca7bbe0a7c..2929226874 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -197,18 +197,13 @@ static int match_prot_id64(CPUHPPAState *env, uint32_t access_id)
 }
 
 int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
-                              int type, hwaddr *pphys, int *pprot,
-                              HPPATLBEntry **tlb_entry)
+                              int type, hwaddr *pphys, int *pprot)
 {
     hwaddr phys;
     int prot, r_prot, w_prot, x_prot, priv;
     HPPATLBEntry *ent;
     int ret = -1;
 
-    if (tlb_entry) {
-        *tlb_entry = NULL;
-    }
-
     /* Virtual translation disabled.  Map absolute to physical.  */
     if (MMU_IDX_MMU_DISABLED(mmu_idx)) {
         switch (mmu_idx) {
@@ -238,10 +233,6 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
         goto egress;
     }
 
-    if (tlb_entry) {
-        *tlb_entry = ent;
-    }
-
     /* We now know the physical address.  */
     phys = ent->pa + (addr - ent->itree.start);
 
@@ -350,7 +341,7 @@ hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
                cpu->env.psw & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX);
 
     excp = hppa_get_physical_address(&cpu->env, addr, mmu_idx, 0,
-                                     &phys, &prot, NULL);
+                                     &phys, &prot);
 
     /* Since we're translating for debugging, the only error that is a
        hard error is no translation at all.  Otherwise, while a real cpu
@@ -432,7 +423,6 @@ bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
 {
     HPPACPU *cpu = HPPA_CPU(cs);
     CPUHPPAState *env = &cpu->env;
-    HPPATLBEntry *ent;
     int prot, excp, a_prot;
     hwaddr phys;
 
@@ -448,8 +438,7 @@ bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
         break;
     }
 
-    excp = hppa_get_physical_address(env, addr, mmu_idx,
-                                     a_prot, &phys, &prot, &ent);
+    excp = hppa_get_physical_address(env, addr, mmu_idx, a_prot, &phys, &prot);
     if (unlikely(excp >= 0)) {
         if (probe) {
             return false;
@@ -690,7 +679,7 @@ target_ulong HELPER(lpa)(CPUHPPAState *env, target_ulong addr)
     int prot, excp;
 
     excp = hppa_get_physical_address(env, addr, MMU_KERNEL_IDX, 0,
-                                     &phys, &prot, NULL);
+                                     &phys, &prot);
     if (excp >= 0) {
         if (excp == EXCP_DTLB_MISS) {
             excp = EXCP_NA_DTLB_MISS;
diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index 66cad78a57..7f79196fff 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -334,8 +334,7 @@ target_ulong HELPER(probe)(CPUHPPAState *env, target_ulong addr,
     }
 
     mmu_idx = PRIV_P_TO_MMU_IDX(level, env->psw & PSW_P);
-    excp = hppa_get_physical_address(env, addr, mmu_idx, 0, &phys,
-                                     &prot, NULL);
+    excp = hppa_get_physical_address(env, addr, mmu_idx, 0, &phys, &prot);
     if (excp >= 0) {
         cpu_restore_state(env_cpu(env), GETPC());
         hppa_set_ior_and_isr(env, addr, MMU_IDX_MMU_DISABLED(mmu_idx));
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 40/43] target/hppa: Adjust priv for B,GATE at runtime
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (38 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 39/43] target/hppa: Drop tlb_entry return from hppa_get_physical_address Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 41/43] target/hppa: Implement CF_PCREL Richard Henderson
                   ` (3 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Do not compile in the priv change based on the first translation;
look up the PTE at execution time.  This is required for CF_PCREL,
where a page may be mapped multiple times with different attributes.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/cpu.h        |  1 -
 target/hppa/helper.h     |  1 +
 target/hppa/mem_helper.c | 34 +++++++++++++++++++++++++++-------
 target/hppa/translate.c  | 36 +++++++++++++++++++-----------------
 4 files changed, 47 insertions(+), 25 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 78ab0adcd0..2bcb3b602b 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -380,7 +380,6 @@ void hppa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
 extern const MemoryRegionOps hppa_io_eir_ops;
 extern const VMStateDescription vmstate_hppa_cpu;
 void hppa_cpu_alarm_timer(void *);
-int hppa_artype_for_page(CPUHPPAState *env, target_ulong vaddr);
 #endif
 G_NORETURN void hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra);
 
diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index c12b48a04a..de411923d9 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -86,6 +86,7 @@ DEF_HELPER_1(halt, noreturn, env)
 DEF_HELPER_1(reset, noreturn, env)
 DEF_HELPER_1(rfi, void, env)
 DEF_HELPER_1(rfi_r, void, env)
+DEF_HELPER_FLAGS_2(b_gate_priv, TCG_CALL_NO_WG, i64, env, i64)
 DEF_HELPER_FLAGS_2(write_interval_timer, TCG_CALL_NO_RWG, void, env, tl)
 DEF_HELPER_FLAGS_2(write_eirr, TCG_CALL_NO_RWG, void, env, tl)
 DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tl, env, tl)
diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index 2929226874..b984f730aa 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -691,13 +691,6 @@ target_ulong HELPER(lpa)(CPUHPPAState *env, target_ulong addr)
     return phys;
 }
 
-/* Return the ar_type of the TLB at VADDR, or -1.  */
-int hppa_artype_for_page(CPUHPPAState *env, target_ulong vaddr)
-{
-    HPPATLBEntry *ent = hppa_find_tlb(env, vaddr);
-    return ent ? ent->ar_type : -1;
-}
-
 /*
  * diag_btlb() emulates the PDC PDC_BLOCK_TLB firmware call to
  * allow operating systems to modify the Block TLB (BTLB) entries.
@@ -793,3 +786,30 @@ void HELPER(diag_btlb)(CPUHPPAState *env)
         break;
     }
 }
+
+uint64_t HELPER(b_gate_priv)(CPUHPPAState *env, uint64_t iaoq_f)
+{
+    uint64_t gva = hppa_form_gva(env, env->iasq_f, iaoq_f);
+    HPPATLBEntry *ent = hppa_find_tlb(env, gva);
+
+    if (ent == NULL) {
+        raise_exception_with_ior(env, EXCP_ITLB_MISS, GETPC(), gva, false);
+    }
+
+    /*
+     * There should be no need to check page permissions, as that will
+     * already have been done by tb_lookup via get_page_addr_code.
+     * All we need at this point is to check the ar_type.
+     *
+     * No change for non-gateway pages or for priv decrease.
+     */
+    if (ent->ar_type & 4) {
+        int old_priv = iaoq_f & 3;
+        int new_priv = ent->ar_type & 3;
+
+        if (new_priv < old_priv) {
+            iaoq_f = (iaoq_f & -4) | new_priv;
+        }
+    }
+    return iaoq_f;
+}
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index f40ac92e98..c2cee89a6a 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -3961,6 +3961,7 @@ static bool trans_bl(DisasContext *ctx, arg_bl *a)
 static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
 {
     int64_t disp = a->disp;
+    bool indirect = false;
 
     /* Trap if PSW[B] is set. */
     if (ctx->psw_xb & PSW_B) {
@@ -3970,24 +3971,22 @@ static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
     nullify_over(ctx);
 
 #ifndef CONFIG_USER_ONLY
-    if (ctx->tb_flags & PSW_C) {
-        int type = hppa_artype_for_page(cpu_env(ctx->cs), ctx->base.pc_next);
-        /* If we could not find a TLB entry, then we need to generate an
-           ITLB miss exception so the kernel will provide it.
-           The resulting TLB fill operation will invalidate this TB and
-           we will re-translate, at which point we *will* be able to find
-           the TLB entry and determine if this is in fact a gateway page.  */
-        if (type < 0) {
-            gen_excp(ctx, EXCP_ITLB_MISS);
-            return true;
-        }
-        /* No change for non-gateway pages or for priv decrease.  */
-        if (type >= 4 && type - 4 < ctx->privilege) {
-            disp -= ctx->privilege;
-            disp += type - 4;
-        }
+    if (ctx->privilege == 0) {
+        /* Privilege cannot decrease. */
+    } else if (!(ctx->tb_flags & PSW_C)) {
+        /* With paging disabled, priv becomes 0. */
+        disp -= ctx->privilege;
     } else {
-        disp -= ctx->privilege;  /* priv = 0 */
+        /* Adjust the dest offset for the privilege change from the PTE. */
+        TCGv_i64 off = tcg_temp_new_i64();
+
+        gen_helper_b_gate_priv(off, tcg_env,
+                               tcg_constant_i64(ctx->iaoq_first
+                                                + ctx->iaq_f.disp));
+
+        ctx->iaq_j.base = off;
+        ctx->iaq_j.disp = disp + 8;
+        indirect = true;
     }
 #endif
 
@@ -4000,6 +3999,9 @@ static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
         save_gpr(ctx, a->l, tmp);
     }
 
+    if (indirect) {
+        return do_ibranch(ctx, 0, false, a->n);
+    }
     return do_dbranch(ctx, disp, 0, a->n);
 }
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 41/43] target/hppa: Implement CF_PCREL
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (39 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 40/43] target/hppa: Adjust priv for B,GATE at runtime Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 42/43] target/hppa: Log cpu state at interrupt Richard Henderson
                   ` (2 subsequent siblings)
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Helge Deller

Now that the groundwork has been laid, enabling CF_PCREL within the
translator proper is a simple matter of updating copy_iaoq_entry
and install_iaq_entries.

We also need to modify the unwind info, since we no longer have
absolute addresses to install.

As expected, this reduces the runtime overhead of compilation when
running a Linux kernel with address space randomization enabled.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/cpu.c       | 19 ++++++------
 target/hppa/translate.c | 68 ++++++++++++++++++++++++++++-------------
 2 files changed, 55 insertions(+), 32 deletions(-)

diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index 5f0df0697a..f0507874ce 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -62,10 +62,6 @@ void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
     *pc = hppa_cpu_get_pc(env_cpu(env));
     flags |= (env->iaoq_f & 3) << TB_FLAG_PRIV_SHIFT;
 
-    if (hppa_is_pa20(env)) {
-        cs_base = env->iaoq_f & MAKE_64BIT_MASK(32, 32);
-    }
-
     /*
      * The only really interesting case is if IAQ_Back is on the same page
      * as IAQ_Front, so that we can use goto_tb between the blocks.  In all
@@ -113,19 +109,19 @@ static void hppa_restore_state_to_opc(CPUState *cs,
                                       const TranslationBlock *tb,
                                       const uint64_t *data)
 {
-    HPPACPU *cpu = HPPA_CPU(cs);
+    CPUHPPAState *env = cpu_env(cs);
 
-    cpu->env.iaoq_f = data[0];
-    if (data[1] != (target_ulong)-1) {
-        cpu->env.iaoq_b = data[1];
+    env->iaoq_f = (env->iaoq_f & TARGET_PAGE_MASK) | data[0];
+    if (data[1] != INT32_MIN) {
+        env->iaoq_b = env->iaoq_f + data[1];
     }
-    cpu->env.unwind_breg = data[2];
+    env->unwind_breg = data[2];
     /*
      * Since we were executing the instruction at IAOQ_F, and took some
      * sort of action that provoked the cpu_restore_state, we can infer
      * that the instruction was not nullified.
      */
-    cpu->env.psw_n = 0;
+    env->psw_n = 0;
 }
 
 static bool hppa_cpu_has_work(CPUState *cs)
@@ -191,6 +187,9 @@ static void hppa_cpu_realizefn(DeviceState *dev, Error **errp)
         hppa_ptlbe(&cpu->env);
     }
 #endif
+
+    /* Use pc-relative instructions always to simplify the translator. */
+    tcg_cflags_set(cs, CF_PCREL);
 }
 
 static void hppa_cpu_initfn(Object *obj)
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index c2cee89a6a..c0920a3c29 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -47,7 +47,7 @@ typedef struct DisasIAQE {
     TCGv_i64 space;
     /* IAOQ base; may be null for relative address. */
     TCGv_i64 base;
-    /* IAOQ addend; if base is null, relative to ctx->iaoq_first. */
+    /* IAOQ addend; if base is null, relative to cpu_iaoq_f. */
     int64_t disp;
 } DisasIAQE;
 
@@ -664,11 +664,7 @@ static DisasIAQE iaqe_next_absv(DisasContext *ctx, TCGv_i64 var)
 static void copy_iaoq_entry(DisasContext *ctx, TCGv_i64 dest,
                             const DisasIAQE *src)
 {
-    if (src->base == NULL) {
-        tcg_gen_movi_i64(dest, ctx->iaoq_first + src->disp);
-    } else {
-        tcg_gen_addi_i64(dest, src->base, src->disp);
-    }
+    tcg_gen_addi_i64(dest, src->base ? : cpu_iaoq_f, src->disp);
 }
 
 static void install_iaq_entries(DisasContext *ctx, const DisasIAQE *f,
@@ -680,8 +676,28 @@ static void install_iaq_entries(DisasContext *ctx, const DisasIAQE *f,
         b_next = iaqe_incr(f, 4);
         b = &b_next;
     }
-    copy_iaoq_entry(ctx, cpu_iaoq_f, f);
-    copy_iaoq_entry(ctx, cpu_iaoq_b, b);
+
+    /*
+     * There is an edge case
+     *    bv   r0(rN)
+     *    b,l  disp,r0
+     * for which F will use cpu_iaoq_b (from the indirect branch),
+     * and B will use cpu_iaoq_f (from the direct branch).
+     * In this case we need an extra temporary.
+     */
+    if (f->base != cpu_iaoq_b) {
+        copy_iaoq_entry(ctx, cpu_iaoq_b, b);
+        copy_iaoq_entry(ctx, cpu_iaoq_f, f);
+    } else if (f->base == b->base) {
+        copy_iaoq_entry(ctx, cpu_iaoq_f, f);
+        tcg_gen_addi_i64(cpu_iaoq_b, cpu_iaoq_f, b->disp - f->disp);
+    } else {
+        TCGv_i64 tmp = tcg_temp_new_i64();
+        copy_iaoq_entry(ctx, tmp, b);
+        copy_iaoq_entry(ctx, cpu_iaoq_f, f);
+        tcg_gen_mov_i64(cpu_iaoq_b, tmp);
+    }
+
     if (f->space) {
         tcg_gen_mov_i64(cpu_iasq_f, f->space);
     }
@@ -3980,9 +3996,8 @@ static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
         /* Adjust the dest offset for the privilege change from the PTE. */
         TCGv_i64 off = tcg_temp_new_i64();
 
-        gen_helper_b_gate_priv(off, tcg_env,
-                               tcg_constant_i64(ctx->iaoq_first
-                                                + ctx->iaq_f.disp));
+        copy_iaoq_entry(ctx, off, &ctx->iaq_f);
+        gen_helper_b_gate_priv(off, tcg_env, off);
 
         ctx->iaq_j.base = off;
         ctx->iaq_j.disp = disp + 8;
@@ -4603,7 +4618,7 @@ static bool trans_diag_unimp(DisasContext *ctx, arg_diag_unimp *a)
 static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
 {
     DisasContext *ctx = container_of(dcbase, DisasContext, base);
-    uint64_t cs_base, iaoq_f, iaoq_b;
+    uint64_t cs_base;
     int bound;
 
     ctx->cs = cs;
@@ -4622,12 +4637,8 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
                     : ctx->tb_flags & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX);
 #endif
 
-    /* Recover the IAOQ values from the GVA + PRIV.  */
     cs_base = ctx->base.tb->cs_base;
-    iaoq_f = cs_base & MAKE_64BIT_MASK(32, 32);
-    iaoq_f |= ctx->base.pc_first & MAKE_64BIT_MASK(2, 30);
-    iaoq_f |= ctx->privilege;
-    ctx->iaoq_first = iaoq_f;
+    ctx->iaoq_first = ctx->base.pc_first + ctx->privilege;
 
     if (unlikely(cs_base & CS_BASE_DIFFSPACE)) {
         ctx->iaq_b.space = cpu_iasq_b;
@@ -4635,8 +4646,9 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     } else if (unlikely(cs_base & CS_BASE_DIFFPAGE)) {
         ctx->iaq_b.base = cpu_iaoq_b;
     } else {
-        iaoq_b = (iaoq_f & TARGET_PAGE_MASK) | (cs_base & ~TARGET_PAGE_MASK);
-        ctx->iaq_b.disp = iaoq_b - iaoq_f;
+        uint64_t iaoq_f_pgofs = ctx->iaoq_first & ~TARGET_PAGE_MASK;
+        uint64_t iaoq_b_pgofs = cs_base & ~TARGET_PAGE_MASK;
+        ctx->iaq_b.disp = iaoq_b_pgofs - iaoq_f_pgofs;
     }
 
     ctx->zero = tcg_constant_i64(0);
@@ -4663,11 +4675,23 @@ static void hppa_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
 static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
 {
     DisasContext *ctx = container_of(dcbase, DisasContext, base);
+    uint64_t iaoq_f, iaoq_b;
+    int64_t diff;
 
     tcg_debug_assert(!iaqe_variable(&ctx->iaq_f));
-    tcg_gen_insn_start(ctx->iaoq_first + ctx->iaq_f.disp,
-                       (iaqe_variable(&ctx->iaq_b) ? -1 :
-                        ctx->iaoq_first + ctx->iaq_b.disp), 0);
+
+    iaoq_f = ctx->iaoq_first + ctx->iaq_f.disp;
+    if (iaqe_variable(&ctx->iaq_b)) {
+        diff = INT32_MIN;
+    } else {
+        iaoq_b = ctx->iaoq_first + ctx->iaq_b.disp;
+        diff = iaoq_b - iaoq_f;
+        /* Direct branches can only produce a 24-bit displacement. */
+        tcg_debug_assert(diff == (int32_t)diff);
+        tcg_debug_assert(diff != INT32_MIN);
+    }
+
+    tcg_gen_insn_start(iaoq_f & ~TARGET_PAGE_MASK, diff, 0);
     ctx->insn_start_updated = false;
 }
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 42/43] target/hppa: Log cpu state at interrupt
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (40 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 41/43] target/hppa: Implement CF_PCREL Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15  9:40 ` [PULL 43/43] target/hppa: Log cpu state on return-from-interrupt Richard Henderson
  2024-05-15 12:59 ` [PULL 00/43] target/hppa: Misc improvements Richard Henderson
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel

This contains all of the information logged before, plus more.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/int_helper.c | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
index b82f32fd12..391f32f27d 100644
--- a/target/hppa/int_helper.c
+++ b/target/hppa/int_helper.c
@@ -241,21 +241,22 @@ void hppa_cpu_do_interrupt(CPUState *cs)
             [EXCP_SYSCALL_LWS]   = "syscall-lws",
             [EXCP_TOC]           = "TOC (transfer of control)",
         };
-        static int count;
-        const char *name = NULL;
-        char unknown[16];
 
-        if (i >= 0 && i < ARRAY_SIZE(names)) {
-            name = names[i];
+        FILE *logfile = qemu_log_trylock();
+        if (logfile) {
+            const char *name = NULL;
+
+            if (i >= 0 && i < ARRAY_SIZE(names)) {
+                name = names[i];
+            }
+            if (name) {
+                fprintf(logfile, "INT: cpu %d %s\n", cs->cpu_index, name);
+            } else {
+                fprintf(logfile, "INT: cpu %d unknown %d\n", cs->cpu_index, i);
+            }
+            hppa_cpu_dump_state(cs, logfile, 0);
+            qemu_log_unlock(logfile);
         }
-        if (!name) {
-            snprintf(unknown, sizeof(unknown), "unknown %d", i);
-            name = unknown;
-        }
-        qemu_log("INT %6d: %s @ " TARGET_FMT_lx ":" TARGET_FMT_lx
-                 " for " TARGET_FMT_lx ":" TARGET_FMT_lx "\n",
-                 ++count, name, env->cr[CR_IIASQ], env->cr[CR_IIAOQ],
-                 env->cr[CR_ISR], env->cr[CR_IOR]);
     }
     cs->exception_index = -1;
 }
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PULL 43/43] target/hppa: Log cpu state on return-from-interrupt
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (41 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 42/43] target/hppa: Log cpu state at interrupt Richard Henderson
@ 2024-05-15  9:40 ` Richard Henderson
  2024-05-15 12:59 ` [PULL 00/43] target/hppa: Misc improvements Richard Henderson
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15  9:40 UTC (permalink / raw)
  To: qemu-devel

Inverse of the logging on taking an interrupt.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/sys_helper.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/target/hppa/sys_helper.c b/target/hppa/sys_helper.c
index 22d6c89964..9b43b556fd 100644
--- a/target/hppa/sys_helper.c
+++ b/target/hppa/sys_helper.c
@@ -18,6 +18,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/log.h"
 #include "cpu.h"
 #include "exec/exec-all.h"
 #include "exec/helper-proto.h"
@@ -93,6 +94,17 @@ void HELPER(rfi)(CPUHPPAState *env)
     env->iaoq_b = env->cr_back[1];
     env->iasq_f = (env->cr[CR_IIASQ] << 32) & ~(env->iaoq_f & mask);
     env->iasq_b = (env->cr_back[0] << 32) & ~(env->iaoq_b & mask);
+
+    if (qemu_loglevel_mask(CPU_LOG_INT)) {
+        FILE *logfile = qemu_log_trylock();
+        if (logfile) {
+            CPUState *cs = env_cpu(env);
+
+            fprintf(logfile, "RFI: cpu %d\n", cs->cpu_index);
+            hppa_cpu_dump_state(cs, logfile, 0);
+            qemu_log_unlock(logfile);
+        }
+    }
 }
 
 static void getshadowregs(CPUHPPAState *env)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* Re: [PULL 00/43] target/hppa: Misc improvements
  2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
                   ` (42 preceding siblings ...)
  2024-05-15  9:40 ` [PULL 43/43] target/hppa: Log cpu state on return-from-interrupt Richard Henderson
@ 2024-05-15 12:59 ` Richard Henderson
  43 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2024-05-15 12:59 UTC (permalink / raw)
  To: qemu-devel

On 5/15/24 11:40, Richard Henderson wrote:
> The following changes since commit 3d48b6b687c558a042d91370633b91c6e29e0e05:
> 
>    Merge tag 'pull-request-2024-05-14' ofhttps://gitlab.com/thuth/qemu  into staging (2024-05-14 17:24:04 +0200)
> 
> are available in the Git repository at:
> 
>    https://gitlab.com/rth7680/qemu.git  tags/pull-hppa-20240515
> 
> for you to fetch changes up to 9e035f00788c52a6f51529c54371a611d9f8b089:
> 
>    target/hppa: Log cpu state on return-from-interrupt (2024-05-15 10:03:45 +0200)
> 
> ----------------------------------------------------------------
> target/hppa:
>    - Use TCG_COND_TST where applicable.
>    - Use CF_BP_PAGE instead of a local breakpoint search.
>    - Clean up IAOQ handling during translation.
>    - Implement CF_PCREL.
>    - Implement PSW.B.
>    - Implement PSW.X.
>    - Log cpu state on interrupt and rfi.

Applied, thanks.  Please update https://wiki.qemu.org/ChangeLog/9.1 as appropriate.


r~



^ permalink raw reply	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2024-05-15 13:00 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-15  9:40 [PULL 00/43] target/hppa: Misc improvements Richard Henderson
2024-05-15  9:40 ` [PULL 01/43] target/hppa: Move cpu_get_tb_cpu_state out of line Richard Henderson
2024-05-15  9:40 ` [PULL 02/43] target/hppa: Use hppa_form_gva_psw in hppa_cpu_get_pc Richard Henderson
2024-05-15  9:40 ` [PULL 03/43] target/hppa: Move constant destination check into use_goto_tb Richard Henderson
2024-05-15  9:40 ` [PULL 04/43] target/hppa: Pass displacement to do_dbranch Richard Henderson
2024-05-15  9:40 ` [PULL 05/43] target/hppa: Allow prior nullification in do_ibranch Richard Henderson
2024-05-15  9:40 ` [PULL 06/43] target/hppa: Use CF_BP_PAGE instead of cpu_breakpoint_test Richard Henderson
2024-05-15  9:40 ` [PULL 07/43] target/hppa: Add install_iaq_entries Richard Henderson
2024-05-15  9:40 ` [PULL 08/43] target/hppa: Add install_link Richard Henderson
2024-05-15  9:40 ` [PULL 09/43] target/hppa: Delay computation of IAQ_Next Richard Henderson
2024-05-15  9:40 ` [PULL 10/43] target/hppa: Skip nullified insns in unconditional dbranch path Richard Henderson
2024-05-15  9:40 ` [PULL 11/43] target/hppa: Simplify TB end Richard Henderson
2024-05-15  9:40 ` [PULL 12/43] target/hppa: Add IASQ entries to DisasContext Richard Henderson
2024-05-15  9:40 ` [PULL 13/43] target/hppa: Add space arguments to install_iaq_entries Richard Henderson
2024-05-15  9:40 ` [PULL 14/43] target/hppa: Add space argument to do_ibranch Richard Henderson
2024-05-15  9:40 ` [PULL 15/43] target/hppa: Use umax in do_ibranch_priv Richard Henderson
2024-05-15  9:40 ` [PULL 16/43] target/hppa: Always make a copy " Richard Henderson
2024-05-15  9:40 ` [PULL 17/43] target/hppa: Introduce and use DisasIAQE for branch management Richard Henderson
2024-05-15  9:40 ` [PULL 18/43] target/hppa: Use displacements in DisasIAQE Richard Henderson
2024-05-15  9:40 ` [PULL 19/43] target/hppa: Rename cond_make_* helpers Richard Henderson
2024-05-15  9:40 ` [PULL 20/43] target/hppa: Use TCG_COND_TST* in do_cond Richard Henderson
2024-05-15  9:40 ` [PULL 21/43] target/hppa: Use TCG_COND_TST* in do_log_cond Richard Henderson
2024-05-15  9:40 ` [PULL 22/43] target/hppa: Use TCG_COND_TST* in do_unit_zero_cond Richard Henderson
2024-05-15  9:40 ` [PULL 23/43] target/hppa: Use TCG_COND_TST* in do_unit_addsub Richard Henderson
2024-05-15  9:40 ` [PULL 24/43] target/hppa: Use TCG_COND_TST* in trans_bb_imm Richard Henderson
2024-05-15  9:40 ` [PULL 25/43] target/hppa: Use registerfields.h for FPSR Richard Henderson
2024-05-15  9:40 ` [PULL 26/43] target/hppa: Use TCG_COND_TST* in trans_ftest Richard Henderson
2024-05-15  9:40 ` [PULL 27/43] target/hppa: Remove cond_free Richard Henderson
2024-05-15  9:40 ` [PULL 28/43] target/hppa: Introduce DisasDelayException Richard Henderson
2024-05-15  9:40 ` [PULL 29/43] target/hppa: Use delay_excp for conditional traps Richard Henderson
2024-05-15  9:40 ` [PULL 30/43] target/hppa: Use delay_excp for conditional trap on overflow Richard Henderson
2024-05-15  9:40 ` [PULL 31/43] linux-user/hppa: Force all code addresses to PRIV_USER Richard Henderson
2024-05-15  9:40 ` [PULL 32/43] target/hppa: Store full iaoq_f and page offset of iaoq_b in TB Richard Henderson
2024-05-15  9:40 ` [PULL 33/43] target/hppa: Do not mask in copy_iaoq_entry Richard Henderson
2024-05-15  9:40 ` [PULL 34/43] target/hppa: Improve hppa_cpu_dump_state Richard Henderson
2024-05-15  9:40 ` [PULL 35/43] target/hppa: Split PSW X and B into their own field Richard Henderson
2024-05-15  9:40 ` [PULL 36/43] target/hppa: Manage PSW_X and PSW_B in translator Richard Henderson
2024-05-15  9:40 ` [PULL 37/43] target/hppa: Implement PSW_B Richard Henderson
2024-05-15  9:40 ` [PULL 38/43] target/hppa: Implement PSW_X Richard Henderson
2024-05-15  9:40 ` [PULL 39/43] target/hppa: Drop tlb_entry return from hppa_get_physical_address Richard Henderson
2024-05-15  9:40 ` [PULL 40/43] target/hppa: Adjust priv for B,GATE at runtime Richard Henderson
2024-05-15  9:40 ` [PULL 41/43] target/hppa: Implement CF_PCREL Richard Henderson
2024-05-15  9:40 ` [PULL 42/43] target/hppa: Log cpu state at interrupt Richard Henderson
2024-05-15  9:40 ` [PULL 43/43] target/hppa: Log cpu state on return-from-interrupt Richard Henderson
2024-05-15 12:59 ` [PULL 00/43] target/hppa: Misc improvements Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).