All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 00/24] target-sparc improvements
@ 2016-06-28  0:38 Richard Henderson
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 01/24] target-sparc: Mark more flags for helpers Richard Henderson
                   ` (24 more replies)
  0 siblings, 25 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:38 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

The primary focus of this patch set is to reduce the number of
helpers that modify TCG globals, and thus increase the lifetime
of those globals within each TB, and thus decrease the number
of times that tcg must spill and fill them from backing store.

As a byproduct, I also implement the bulk of the interesting v9 ASIs
inline, thus exposing e.g. the little-endian loads and stores as
simple tcg operations.

The patch set is relative to my outstanding tcg pull request.
For reference, the complete tree can be found at

  git://github.com/rth7680/qemu.git tgt-sparc-2

Changes from v3 to v4:
  * Re-do the UA2005 commit change, which apparently got lost in v3.
  * Rebased on aa8151b7df, which contains fix for the ldstub issue.

Changes from v2 to v3:
  * Add ASI_BLK_COMMIT_[PS] to patch 19.
    This fixes the illegal instruction that Artyom reported.
  * Add gen_address_mask calls to all direct accesses.
    This fixes a follow-on segv that affected the debian install.

Changes from v1 to v2:
  * Commit message refers to UA2005 instead of UA2011 when
    introducing new asi.h defines. (Artyom)
  * Drop MMU_REAL_IDX, and inline handling of ASI_REAL_*.
    This appears to be the source of the regression that Artyom
    identified wrt ss5 emulation.


r~


Richard Henderson (24):
  target-sparc: Mark more flags for helpers
  target-sparc: Remove softint as a TCG global
  target-sparc: Store mmu index in TB flags
  target-sparc: Create gen_exception
  target-sparc: Unify asi handling between 32 and 64-bit
  target-sparc: Store %asi in TB flags
  target-sparc: Introduce get_asi
  target-sparc: Pass TCGMemOp to gen_ld/st_asi
  target-sparc: Import linux/arch/sparc/include/uapi/asm/asi.h
  target-sparc: Add UA2005 defines to asi.h
  target-sparc: Use defines from asi.h
  target-sparc: Directly implement easy ld/st asis
  target-sparc: Use QT0 to return results from ldda
  target-sparc: Introduce gen_check_align
  target-sparc: Directly implement easy ldd/std asis
  target-sparc: Fix obvious error in ASI_M_BFILL
  target-sparc: Pass TCGMemOp constants to helper_ld/st_asi
  target-sparc: Directly implement easy ldf/stf asis
  target-sparc: Directly implement block and short ldf/stf asis
  target-sparc: Remove helper_ldf_asi, helper_stf_asi
  target-sparc: Use explicit writes to cpu_fsr
  target-sparc: Use cpu_fsr in stfsr
  target-sparc: Use cpu_loop_exit_restore from
    helper_check_ieee_exceptions
  target-sparc: Elide duplicate updates to fprs

 target-sparc/asi.h         |  311 +++++++++++
 target-sparc/cpu.h         |   28 +-
 target-sparc/fop_helper.c  |  230 +++-----
 target-sparc/helper.h      |  168 +++---
 target-sparc/ldst_helper.c |  696 +++++++++++-------------
 target-sparc/translate.c   | 1273 ++++++++++++++++++++++++++++----------------
 6 files changed, 1607 insertions(+), 1099 deletions(-)
 create mode 100644 target-sparc/asi.h

-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 01/24] target-sparc: Mark more flags for helpers
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
@ 2016-06-28  0:38 ` Richard Henderson
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 02/24] target-sparc: Remove softint as a TCG global Richard Henderson
                   ` (23 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:38 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Quite a few helpers do not modify tcg globals but did not so indicate.

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/helper.h | 48 ++++++++++++++++++++++++------------------------
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 4374f0d..366d4d1 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -4,34 +4,34 @@ DEF_HELPER_2(wrpsr, void, env, tl)
 DEF_HELPER_1(rdpsr, tl, env)
 DEF_HELPER_1(power_down, void, env)
 #else
-DEF_HELPER_2(wrpil, void, env, tl)
+DEF_HELPER_FLAGS_2(wrpil, TCG_CALL_NO_RWG, void, env, tl)
 DEF_HELPER_2(wrpstate, void, env, tl)
 DEF_HELPER_1(done, void, env)
 DEF_HELPER_1(retry, void, env)
-DEF_HELPER_1(flushw, void, env)
-DEF_HELPER_1(saved, void, env)
-DEF_HELPER_1(restored, void, env)
+DEF_HELPER_FLAGS_1(flushw, TCG_CALL_NO_WG, void, env)
+DEF_HELPER_FLAGS_1(saved, TCG_CALL_NO_RWG, void, env)
+DEF_HELPER_FLAGS_1(restored, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_1(rdccr, tl, env)
 DEF_HELPER_2(wrccr, void, env, tl)
 DEF_HELPER_1(rdcwp, tl, env)
 DEF_HELPER_2(wrcwp, void, env, tl)
 DEF_HELPER_FLAGS_2(array8, TCG_CALL_NO_RWG_SE, tl, tl, tl)
-DEF_HELPER_1(popc, tl, tl)
+DEF_HELPER_FLAGS_1(popc, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_4(ldda_asi, void, env, tl, int, int)
 DEF_HELPER_5(ldf_asi, void, env, tl, int, int, int)
-DEF_HELPER_5(stf_asi, void, env, tl, int, int, int)
-DEF_HELPER_5(casx_asi, tl, env, tl, tl, tl, i32)
+DEF_HELPER_FLAGS_5(stf_asi, TCG_CALL_NO_WG, void, env, tl, int, int, int)
+DEF_HELPER_FLAGS_5(casx_asi, TCG_CALL_NO_WG, tl, env, tl, tl, tl, i32)
 DEF_HELPER_2(set_softint, void, env, i64)
 DEF_HELPER_2(clear_softint, void, env, i64)
 DEF_HELPER_2(write_softint, void, env, i64)
-DEF_HELPER_2(tick_set_count, void, ptr, i64)
-DEF_HELPER_3(tick_get_count, i64, env, ptr, int)
-DEF_HELPER_2(tick_set_limit, void, ptr, i64)
+DEF_HELPER_FLAGS_2(tick_set_count, TCG_CALL_NO_RWG, void, ptr, i64)
+DEF_HELPER_FLAGS_3(tick_get_count, TCG_CALL_NO_WG, i64, env, ptr, int)
+DEF_HELPER_FLAGS_2(tick_set_limit, TCG_CALL_NO_RWG, void, ptr, i64)
 #endif
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
-DEF_HELPER_5(cas_asi, tl, env, tl, tl, tl, i32)
+DEF_HELPER_FLAGS_5(cas_asi, TCG_CALL_NO_WG, tl, env, tl, tl, tl, i32)
 #endif
-DEF_HELPER_3(check_align, void, env, tl, i32)
+DEF_HELPER_FLAGS_3(check_align, TCG_CALL_NO_WG, void, env, tl, i32)
 DEF_HELPER_1(debug, void, env)
 DEF_HELPER_1(save, void, env)
 DEF_HELPER_1(restore, void, env)
@@ -42,14 +42,14 @@ DEF_HELPER_3(sdiv_cc, tl, env, tl, tl)
 DEF_HELPER_3(taddcctv, tl, env, tl, tl)
 DEF_HELPER_3(tsubcctv, tl, env, tl, tl)
 #ifdef TARGET_SPARC64
-DEF_HELPER_3(sdivx, s64, env, s64, s64)
-DEF_HELPER_3(udivx, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(sdivx, TCG_CALL_NO_WG, s64, env, s64, s64)
+DEF_HELPER_FLAGS_3(udivx, TCG_CALL_NO_WG, i64, env, i64, i64)
 #endif
-DEF_HELPER_3(ldqf, void, env, tl, int)
-DEF_HELPER_3(stqf, void, env, tl, int)
+DEF_HELPER_FLAGS_3(ldqf, TCG_CALL_NO_WG, void, env, tl, int)
+DEF_HELPER_FLAGS_3(stqf, TCG_CALL_NO_WG, void, env, tl, int)
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
-DEF_HELPER_5(ld_asi, i64, env, tl, int, int, int)
-DEF_HELPER_5(st_asi, void, env, tl, i64, int, int)
+DEF_HELPER_FLAGS_5(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, int, int)
+DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, int)
 #endif
 DEF_HELPER_2(ldfsr, void, env, i32)
 DEF_HELPER_FLAGS_1(fabss, TCG_CALL_NO_RWG_SE, f32, f32)
@@ -77,7 +77,7 @@ DEF_HELPER_3(fcmpes_fcc3, void, env, f32, f32)
 DEF_HELPER_3(fcmped_fcc1, void, env, f64, f64)
 DEF_HELPER_3(fcmped_fcc2, void, env, f64, f64)
 DEF_HELPER_3(fcmped_fcc3, void, env, f64, f64)
-DEF_HELPER_1(fabsq, void, env)
+DEF_HELPER_FLAGS_1(fabsq, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_1(fcmpq_fcc1, void, env)
 DEF_HELPER_1(fcmpq_fcc2, void, env)
 DEF_HELPER_1(fcmpq_fcc3, void, env)
@@ -106,17 +106,17 @@ DEF_HELPER_3(fsmuld, f64, env, f32, f32)
 DEF_HELPER_3(fdmulq, void, env, f64, f64)
 
 DEF_HELPER_FLAGS_1(fnegs, TCG_CALL_NO_RWG_SE, f32, f32)
-DEF_HELPER_2(fitod, f64, env, s32)
-DEF_HELPER_2(fitoq, void, env, s32)
+DEF_HELPER_FLAGS_2(fitod, TCG_CALL_NO_RWG_SE, f64, env, s32)
+DEF_HELPER_FLAGS_2(fitoq, TCG_CALL_NO_RWG, void, env, s32)
 
 DEF_HELPER_2(fitos, f32, env, s32)
 
 #ifdef TARGET_SPARC64
 DEF_HELPER_FLAGS_1(fnegd, TCG_CALL_NO_RWG_SE, f64, f64)
-DEF_HELPER_1(fnegq, void, env)
+DEF_HELPER_FLAGS_1(fnegq, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_2(fxtos, f32, env, s64)
 DEF_HELPER_2(fxtod, f64, env, s64)
-DEF_HELPER_2(fxtoq, void, env, s64)
+DEF_HELPER_FLAGS_2(fxtoq, TCG_CALL_NO_RWG, void, env, s64)
 #endif
 DEF_HELPER_2(fdtos, f32, env, f64)
 DEF_HELPER_2(fstod, f64, env, f32)
@@ -172,4 +172,4 @@ VIS_CMPHELPER(cmpne)
 #undef VIS_HELPER
 #undef VIS_CMPHELPER
 DEF_HELPER_1(compute_psr, void, env)
-DEF_HELPER_1(compute_C_icc, i32, env)
+DEF_HELPER_FLAGS_1(compute_C_icc, TCG_CALL_NO_WG_SE, i32, env)
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 02/24] target-sparc: Remove softint as a TCG global
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 01/24] target-sparc: Mark more flags for helpers Richard Henderson
@ 2016-06-28  0:38 ` Richard Henderson
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 03/24] target-sparc: Store mmu index in TB flags Richard Henderson
                   ` (22 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:38 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

The global is only ever read for one insn; we can just as well
use a load from env instead and generate the same code.  This
also allows us to indicate the the associated helpers do not
touch TCG globals.

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/helper.h    | 6 +++---
 target-sparc/translate.c | 5 ++---
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 366d4d1..14712cc 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -21,9 +21,9 @@ DEF_HELPER_4(ldda_asi, void, env, tl, int, int)
 DEF_HELPER_5(ldf_asi, void, env, tl, int, int, int)
 DEF_HELPER_FLAGS_5(stf_asi, TCG_CALL_NO_WG, void, env, tl, int, int, int)
 DEF_HELPER_FLAGS_5(casx_asi, TCG_CALL_NO_WG, tl, env, tl, tl, tl, i32)
-DEF_HELPER_2(set_softint, void, env, i64)
-DEF_HELPER_2(clear_softint, void, env, i64)
-DEF_HELPER_2(write_softint, void, env, i64)
+DEF_HELPER_FLAGS_2(set_softint, TCG_CALL_NO_RWG, void, env, i64)
+DEF_HELPER_FLAGS_2(clear_softint, TCG_CALL_NO_RWG, void, env, i64)
+DEF_HELPER_FLAGS_2(write_softint, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_2(tick_set_count, TCG_CALL_NO_RWG, void, ptr, i64)
 DEF_HELPER_FLAGS_3(tick_get_count, TCG_CALL_NO_WG, i64, env, ptr, int)
 DEF_HELPER_FLAGS_2(tick_set_limit, TCG_CALL_NO_RWG, void, ptr, i64)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 0f4faf7..fc220ed 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -57,7 +57,6 @@ static TCGv_i32 cpu_xcc, cpu_asi, cpu_fprs;
 static TCGv cpu_gsr;
 static TCGv cpu_tick_cmpr, cpu_stick_cmpr, cpu_hstick_cmpr;
 static TCGv cpu_hintp, cpu_htba, cpu_hver, cpu_ssr, cpu_ver;
-static TCGv_i32 cpu_softint;
 #else
 static TCGv cpu_wim;
 #endif
@@ -2754,7 +2753,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     gen_store_gpr(dc, rd, cpu_gsr);
                     break;
                 case 0x16: /* Softint */
-                    tcg_gen_ext_i32_tl(cpu_dst, cpu_softint);
+                    tcg_gen_ld32s_tl(cpu_dst, cpu_env,
+                                     offsetof(CPUSPARCState, softint));
                     gen_store_gpr(dc, rd, cpu_dst);
                     break;
                 case 0x17: /* Tick compare */
@@ -5364,7 +5364,6 @@ void gen_intermediate_code_init(CPUSPARCState *env)
         { &cpu_xcc, offsetof(CPUSPARCState, xcc), "xcc" },
         { &cpu_asi, offsetof(CPUSPARCState, asi), "asi" },
         { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" },
-        { &cpu_softint, offsetof(CPUSPARCState, softint), "softint" },
 #else
         { &cpu_wim, offsetof(CPUSPARCState, wim), "wim" },
 #endif
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 03/24] target-sparc: Store mmu index in TB flags
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 01/24] target-sparc: Mark more flags for helpers Richard Henderson
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 02/24] target-sparc: Remove softint as a TCG global Richard Henderson
@ 2016-06-28  0:38 ` Richard Henderson
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 04/24] target-sparc: Create gen_exception Richard Henderson
                   ` (21 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:38 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Doing this instead of saving the raw PS_PRIV and TL.  This means
that all nucleus mode TBs (TL > 0) can be shared.  This fixes a
bug in that we didn't include HS_PRIV in the TB flags, and so could
produce incorrect TB matches for hypervisor state.

The LSU and DMMU states were unused by the translator.  Including
them in TB flags meant unnecessary mismatches from tb_find_fast.

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/cpu.h       | 26 ++++++++++++--------------
 target-sparc/translate.c |  2 +-
 2 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index ba37f4b..31ea65b 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -720,34 +720,32 @@ void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit);
 trap_state* cpu_tsptr(CPUSPARCState* env);
 #endif
 
-#define TB_FLAG_FPU_ENABLED (1 << 4)
-#define TB_FLAG_AM_ENABLED (1 << 5)
+#define TB_FLAG_MMU_MASK     7
+#define TB_FLAG_FPU_ENABLED  (1 << 4)
+#define TB_FLAG_AM_ENABLED   (1 << 5)
 
 static inline void cpu_get_tb_cpu_state(CPUSPARCState *env, target_ulong *pc,
-                                        target_ulong *cs_base, uint32_t *flags)
+                                        target_ulong *cs_base, uint32_t *pflags)
 {
+    uint32_t flags;
     *pc = env->pc;
     *cs_base = env->npc;
+    flags = cpu_mmu_index(env, false);
 #ifdef TARGET_SPARC64
-    // AM . Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
-    *flags = (env->pstate & PS_PRIV)               /* 2 */
-        | ((env->lsu & (DMMU_E | IMMU_E)) >> 2)    /* 1, 0 */
-        | ((env->tl & 0xff) << 8)
-        | (env->dmmu.mmu_primary_context << 16);   /* 16... */
     if (env->pstate & PS_AM) {
-        *flags |= TB_FLAG_AM_ENABLED;
+        flags |= TB_FLAG_AM_ENABLED;
     }
-    if ((env->def->features & CPU_FEATURE_FLOAT) && (env->pstate & PS_PEF)
+    if ((env->def->features & CPU_FEATURE_FLOAT)
+        && (env->pstate & PS_PEF)
         && (env->fprs & FPRS_FEF)) {
-        *flags |= TB_FLAG_FPU_ENABLED;
+        flags |= TB_FLAG_FPU_ENABLED;
     }
 #else
-    // FPU enable . Supervisor
-    *flags = env->psrs;
     if ((env->def->features & CPU_FEATURE_FLOAT) && env->psref) {
-        *flags |= TB_FLAG_FPU_ENABLED;
+        flags |= TB_FLAG_FPU_ENABLED;
     }
 #endif
+    *pflags = flags;
 }
 
 static inline bool tb_fpu_enabled(int tb_flags)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index fc220ed..9000e9b 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5248,7 +5248,7 @@ void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
     last_pc = dc->pc;
     dc->npc = (target_ulong) tb->cs_base;
     dc->cc_op = CC_OP_DYNAMIC;
-    dc->mem_idx = cpu_mmu_index(env, false);
+    dc->mem_idx = tb->flags & TB_FLAG_MMU_MASK;
     dc->def = env->def;
     dc->fpu_enabled = tb_fpu_enabled(tb->flags);
     dc->address_mask_32bit = tb_am_enabled(tb->flags);
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 04/24] target-sparc: Create gen_exception
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (2 preceding siblings ...)
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 03/24] target-sparc: Store mmu index in TB flags Richard Henderson
@ 2016-06-28  0:38 ` Richard Henderson
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 05/24] target-sparc: Unify asi handling between 32 and 64-bit Richard Henderson
                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:38 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

This unifies quite a few duplicate code fragments.

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/translate.c | 75 +++++++++++++-----------------------------------
 1 file changed, 20 insertions(+), 55 deletions(-)

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 9000e9b..4fb26e7 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1043,6 +1043,17 @@ static inline void save_state(DisasContext *dc)
     save_npc(dc);
 }
 
+static void gen_exception(DisasContext *dc, int which)
+{
+    TCGv_i32 t;
+
+    save_state(dc);
+    t = tcg_const_i32(which);
+    gen_helper_raise_exception(cpu_env, t);
+    tcg_temp_free_i32(t);
+    dc->is_br = 1;
+}
+
 static inline void gen_mov_pc_npc(DisasContext *dc)
 {
     if (dc->npc == JUMP_PC) {
@@ -1633,28 +1644,18 @@ static inline void gen_op_fcmpeq(int fccno)
 }
 #endif
 
-static inline void gen_op_fpexception_im(int fsr_flags)
+static void gen_op_fpexception_im(DisasContext *dc, int fsr_flags)
 {
-    TCGv_i32 r_const;
-
     tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_NMASK);
     tcg_gen_ori_tl(cpu_fsr, cpu_fsr, fsr_flags);
-    r_const = tcg_const_i32(TT_FP_EXCP);
-    gen_helper_raise_exception(cpu_env, r_const);
-    tcg_temp_free_i32(r_const);
+    gen_exception(dc, TT_FP_EXCP);
 }
 
 static int gen_trap_ifnofpu(DisasContext *dc)
 {
 #if !defined(CONFIG_USER_ONLY)
     if (!dc->fpu_enabled) {
-        TCGv_i32 r_const;
-
-        save_state(dc);
-        r_const = tcg_const_i32(TT_NFPU_INSN);
-        gen_helper_raise_exception(cpu_env, r_const);
-        tcg_temp_free_i32(r_const);
-        dc->is_br = 1;
+        gen_exception(dc, TT_NFPU_INSN);
         return 1;
     }
 #endif
@@ -5155,63 +5156,27 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
  jmp_insn:
     goto egress;
  illegal_insn:
-    {
-        TCGv_i32 r_const;
-
-        save_state(dc);
-        r_const = tcg_const_i32(TT_ILL_INSN);
-        gen_helper_raise_exception(cpu_env, r_const);
-        tcg_temp_free_i32(r_const);
-        dc->is_br = 1;
-    }
+    gen_exception(dc, TT_ILL_INSN);
     goto egress;
  unimp_flush:
-    {
-        TCGv_i32 r_const;
-
-        save_state(dc);
-        r_const = tcg_const_i32(TT_UNIMP_FLUSH);
-        gen_helper_raise_exception(cpu_env, r_const);
-        tcg_temp_free_i32(r_const);
-        dc->is_br = 1;
-    }
+    gen_exception(dc, TT_UNIMP_FLUSH);
     goto egress;
 #if !defined(CONFIG_USER_ONLY)
  priv_insn:
-    {
-        TCGv_i32 r_const;
-
-        save_state(dc);
-        r_const = tcg_const_i32(TT_PRIV_INSN);
-        gen_helper_raise_exception(cpu_env, r_const);
-        tcg_temp_free_i32(r_const);
-        dc->is_br = 1;
-    }
+    gen_exception(dc, TT_PRIV_INSN);
     goto egress;
 #endif
  nfpu_insn:
-    save_state(dc);
-    gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
-    dc->is_br = 1;
+    gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP);
     goto egress;
 #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
  nfq_insn:
-    save_state(dc);
-    gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
-    dc->is_br = 1;
+    gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR);
     goto egress;
 #endif
 #ifndef TARGET_SPARC64
  ncp_insn:
-    {
-        TCGv r_const;
-
-        save_state(dc);
-        r_const = tcg_const_i32(TT_NCP_INSN);
-        gen_helper_raise_exception(cpu_env, r_const);
-        tcg_temp_free(r_const);
-        dc->is_br = 1;
-    }
+    gen_exception(dc, TT_NCP_INSN);
     goto egress;
 #endif
  egress:
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 05/24] target-sparc: Unify asi handling between 32 and 64-bit
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (3 preceding siblings ...)
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 04/24] target-sparc: Create gen_exception Richard Henderson
@ 2016-06-28  0:38 ` Richard Henderson
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 06/24] target-sparc: Store %asi in TB flags Richard Henderson
                   ` (19 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:38 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

We now have a single copy of gen_ld_asi, gen_st_asi,
gen_swap_asi, and everything uses gen_get_asi.

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/translate.c | 285 ++++++++++++++++++++++-------------------------
 1 file changed, 131 insertions(+), 154 deletions(-)

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 4fb26e7..90c46df 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1972,111 +1972,175 @@ static inline void gen_ne_fop_QD(DisasContext *dc, int rd, int rs,
 }
 
 /* asi moves */
-#ifdef TARGET_SPARC64
-static inline TCGv_i32 gen_get_asi(int insn, TCGv r_addr)
+#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
+static TCGv_i32 gen_get_asi(DisasContext *dc, int insn)
 {
-    int asi;
-    TCGv_i32 r_asi;
+    TCGv_i32 r_asi = tcg_temp_new_i32();
 
     if (IS_IMM) {
-        r_asi = tcg_temp_new_i32();
+#ifdef TARGET_SPARC64
         tcg_gen_mov_i32(r_asi, cpu_asi);
+#else
+        gen_exception(dc, TT_ILL_INSN);
+        tcg_gen_movi_i32(r_asi, 0);
+#endif
     } else {
-        asi = GET_FIELD(insn, 19, 26);
-        r_asi = tcg_const_i32(asi);
+        tcg_gen_movi_i32(r_asi, GET_FIELD(insn, 19, 26));
     }
     return r_asi;
 }
 
-static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
-                              int sign)
+static void gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr,
+                       int insn, int size, int sign)
 {
     TCGv_i32 r_asi, r_size, r_sign;
 
-    r_asi = gen_get_asi(insn, addr);
+    r_asi = gen_get_asi(dc, insn);
     r_size = tcg_const_i32(size);
     r_sign = tcg_const_i32(sign);
+#ifdef TARGET_SPARC64
     gen_helper_ld_asi(dst, cpu_env, addr, r_asi, r_size, r_sign);
+#else
+    {
+        TCGv_i64 t64 = tcg_temp_new_i64();
+        gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
+        tcg_gen_trunc_i64_tl(dst, t64);
+        tcg_temp_free_i64(t64);
+    }
+#endif
     tcg_temp_free_i32(r_sign);
     tcg_temp_free_i32(r_size);
     tcg_temp_free_i32(r_asi);
 }
 
-static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
+static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr,
+                       int insn, int size)
 {
     TCGv_i32 r_asi, r_size;
 
-    r_asi = gen_get_asi(insn, addr);
+    r_asi = gen_get_asi(dc, insn);
     r_size = tcg_const_i32(size);
+#ifdef TARGET_SPARC64
     gen_helper_st_asi(cpu_env, addr, src, r_asi, r_size);
+#else
+    {
+        TCGv_i64 t64 = tcg_temp_new_i64();
+        tcg_gen_extu_tl_i64(t64, src);
+        gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
+        tcg_temp_free_i64(t64);
+    }
+#endif
     tcg_temp_free_i32(r_size);
     tcg_temp_free_i32(r_asi);
 }
 
-static inline void gen_ldf_asi(TCGv addr, int insn, int size, int rd)
+static void gen_swap_asi(DisasContext *dc, TCGv dst, TCGv src,
+                         TCGv addr, int insn)
 {
-    TCGv_i32 r_asi, r_size, r_rd;
+    TCGv_i32 r_asi, r_size, r_sign;
+    TCGv_i64 s64, t64 = tcg_temp_new_i64();
 
-    r_asi = gen_get_asi(insn, addr);
-    r_size = tcg_const_i32(size);
-    r_rd = tcg_const_i32(rd);
-    gen_helper_ldf_asi(cpu_env, addr, r_asi, r_size, r_rd);
-    tcg_temp_free_i32(r_rd);
+    r_asi = gen_get_asi(dc, insn);
+    r_size = tcg_const_i32(4);
+    r_sign = tcg_const_i32(0);
+    gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
+    tcg_temp_free_i32(r_sign);
+
+    s64 = tcg_temp_new_i64();
+    tcg_gen_extu_tl_i64(s64, src);
+    gen_helper_st_asi(cpu_env, addr, s64, r_asi, r_size);
+    tcg_temp_free_i64(s64);
     tcg_temp_free_i32(r_size);
     tcg_temp_free_i32(r_asi);
+
+    tcg_gen_trunc_i64_tl(dst, t64);
+    tcg_temp_free_i64(t64);
 }
 
-static inline void gen_stf_asi(TCGv addr, int insn, int size, int rd)
+static void gen_cas_asi(DisasContext *dc, TCGv addr, TCGv val2,
+                        int insn, int rd)
+{
+    TCGv val1 = gen_load_gpr(dc, rd);
+    TCGv dst = gen_dest_gpr(dc, rd);
+    TCGv_i32 r_asi = gen_get_asi(dc, insn);
+
+    gen_helper_cas_asi(dst, cpu_env, addr, val1, val2, r_asi);
+    tcg_temp_free_i32(r_asi);
+    gen_store_gpr(dc, rd, dst);
+}
+
+static void gen_ldstub_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn)
+{
+    TCGv_i32 r_asi, r_size, r_sign;
+    TCGv_i64 s64, d64 = tcg_temp_new_i64();
+
+    r_asi = gen_get_asi(dc, insn);
+    r_size = tcg_const_i32(1);
+    r_sign = tcg_const_i32(0);
+    gen_helper_ld_asi(d64, cpu_env, addr, r_asi, r_size, r_sign);
+    tcg_temp_free_i32(r_sign);
+
+    s64 = tcg_const_i64(0xff);
+    gen_helper_st_asi(cpu_env, addr, s64, r_asi, r_size);
+    tcg_temp_free_i64(s64);
+    tcg_temp_free_i32(r_size);
+    tcg_temp_free_i32(r_asi);
+
+    tcg_gen_trunc_i64_tl(dst, d64);
+    tcg_temp_free_i64(d64);
+}
+#endif
+
+#ifdef TARGET_SPARC64
+static void gen_ldf_asi(DisasContext *dc, TCGv addr,
+                        int insn, int size, int rd)
 {
     TCGv_i32 r_asi, r_size, r_rd;
 
-    r_asi = gen_get_asi(insn, addr);
+    r_asi = gen_get_asi(dc, insn);
     r_size = tcg_const_i32(size);
     r_rd = tcg_const_i32(rd);
-    gen_helper_stf_asi(cpu_env, addr, r_asi, r_size, r_rd);
+    gen_helper_ldf_asi(cpu_env, addr, r_asi, r_size, r_rd);
     tcg_temp_free_i32(r_rd);
     tcg_temp_free_i32(r_size);
     tcg_temp_free_i32(r_asi);
 }
 
-static inline void gen_swap_asi(TCGv dst, TCGv src, TCGv addr, int insn)
+static void gen_stf_asi(DisasContext *dc, TCGv addr,
+                        int insn, int size, int rd)
 {
-    TCGv_i32 r_asi, r_size, r_sign;
-    TCGv_i64 t64 = tcg_temp_new_i64();
+    TCGv_i32 r_asi, r_size, r_rd;
 
-    r_asi = gen_get_asi(insn, addr);
-    r_size = tcg_const_i32(4);
-    r_sign = tcg_const_i32(0);
-    gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
-    tcg_temp_free_i32(r_sign);
-    gen_helper_st_asi(cpu_env, addr, src, r_asi, r_size);
+    r_asi = gen_get_asi(dc, insn);
+    r_size = tcg_const_i32(size);
+    r_rd = tcg_const_i32(rd);
+    gen_helper_stf_asi(cpu_env, addr, r_asi, r_size, r_rd);
+    tcg_temp_free_i32(r_rd);
     tcg_temp_free_i32(r_size);
     tcg_temp_free_i32(r_asi);
-    tcg_gen_trunc_i64_tl(dst, t64);
-    tcg_temp_free_i64(t64);
 }
 
-static inline void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
-                                int insn, int rd)
+static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
+                         int insn, int rd)
 {
     TCGv_i32 r_asi, r_rd;
 
-    r_asi = gen_get_asi(insn, addr);
+    r_asi = gen_get_asi(dc, insn);
     r_rd = tcg_const_i32(rd);
     gen_helper_ldda_asi(cpu_env, addr, r_asi, r_rd);
     tcg_temp_free_i32(r_rd);
     tcg_temp_free_i32(r_asi);
 }
 
-static inline void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
-                                int insn, int rd)
+static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
+                         int insn, int rd)
 {
     TCGv_i32 r_asi, r_size;
     TCGv lo = gen_load_gpr(dc, rd + 1);
     TCGv_i64 t64 = tcg_temp_new_i64();
 
     tcg_gen_concat_tl_i64(t64, lo, hi);
-    r_asi = gen_get_asi(insn, addr);
+    r_asi = gen_get_asi(dc, insn);
     r_size = tcg_const_i32(8);
     gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
     tcg_temp_free_i32(r_size);
@@ -2084,12 +2148,12 @@ static inline void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
     tcg_temp_free_i64(t64);
 }
 
-static inline void gen_casx_asi(DisasContext *dc, TCGv addr,
-                                TCGv val2, int insn, int rd)
+static void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv val2,
+                         int insn, int rd)
 {
     TCGv val1 = gen_load_gpr(dc, rd);
     TCGv dst = gen_dest_gpr(dc, rd);
-    TCGv_i32 r_asi = gen_get_asi(insn, addr);
+    TCGv_i32 r_asi = gen_get_asi(dc, insn);
 
     gen_helper_casx_asi(dst, cpu_env, addr, val1, val2, r_asi);
     tcg_temp_free_i32(r_asi);
@@ -2097,67 +2161,14 @@ static inline void gen_casx_asi(DisasContext *dc, TCGv addr,
 }
 
 #elif !defined(CONFIG_USER_ONLY)
-
-static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
-                              int sign)
-{
-    TCGv_i32 r_asi, r_size, r_sign;
-    TCGv_i64 t64 = tcg_temp_new_i64();
-
-    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
-    r_size = tcg_const_i32(size);
-    r_sign = tcg_const_i32(sign);
-    gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
-    tcg_temp_free_i32(r_sign);
-    tcg_temp_free_i32(r_size);
-    tcg_temp_free_i32(r_asi);
-    tcg_gen_trunc_i64_tl(dst, t64);
-    tcg_temp_free_i64(t64);
-}
-
-static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
-{
-    TCGv_i32 r_asi, r_size;
-    TCGv_i64 t64 = tcg_temp_new_i64();
-
-    tcg_gen_extu_tl_i64(t64, src);
-    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
-    r_size = tcg_const_i32(size);
-    gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
-    tcg_temp_free_i32(r_size);
-    tcg_temp_free_i32(r_asi);
-    tcg_temp_free_i64(t64);
-}
-
-static inline void gen_swap_asi(TCGv dst, TCGv src, TCGv addr, int insn)
-{
-    TCGv_i32 r_asi, r_size, r_sign;
-    TCGv_i64 r_val, t64;
-
-    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
-    r_size = tcg_const_i32(4);
-    r_sign = tcg_const_i32(0);
-    t64 = tcg_temp_new_i64();
-    gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
-    tcg_temp_free(r_sign);
-    r_val = tcg_temp_new_i64();
-    tcg_gen_extu_tl_i64(r_val, src);
-    gen_helper_st_asi(cpu_env, addr, r_val, r_asi, r_size);
-    tcg_temp_free_i64(r_val);
-    tcg_temp_free_i32(r_size);
-    tcg_temp_free_i32(r_asi);
-    tcg_gen_trunc_i64_tl(dst, t64);
-    tcg_temp_free_i64(t64);
-}
-
-static inline void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
-                                int insn, int rd)
+static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
+                         int insn, int rd)
 {
     TCGv_i32 r_asi, r_size, r_sign;
     TCGv t;
     TCGv_i64 t64;
 
-    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
+    r_asi = gen_get_asi(dc, insn);
     r_size = tcg_const_i32(8);
     r_sign = tcg_const_i32(0);
     t64 = tcg_temp_new_i64();
@@ -2180,15 +2191,15 @@ static inline void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
     gen_store_gpr(dc, rd, hi);
 }
 
-static inline void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
-                                int insn, int rd)
+static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
+                         int insn, int rd)
 {
     TCGv_i32 r_asi, r_size;
     TCGv lo = gen_load_gpr(dc, rd + 1);
     TCGv_i64 t64 = tcg_temp_new_i64();
 
     tcg_gen_concat_tl_i64(t64, lo, hi);
-    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
+    r_asi = gen_get_asi(dc, insn);
     r_size = tcg_const_i32(8);
     gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
     tcg_temp_free_i32(r_size);
@@ -2197,40 +2208,6 @@ static inline void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
 }
 #endif
 
-#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
-static inline void gen_cas_asi(DisasContext *dc, TCGv addr,
-                               TCGv val2, int insn, int rd)
-{
-    TCGv val1 = gen_load_gpr(dc, rd);
-    TCGv dst = gen_dest_gpr(dc, rd);
-#ifdef TARGET_SPARC64
-    TCGv_i32 r_asi = gen_get_asi(insn, addr);
-#else
-    TCGv_i32 r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
-#endif
-
-    gen_helper_cas_asi(dst, cpu_env, addr, val1, val2, r_asi);
-    tcg_temp_free_i32(r_asi);
-    gen_store_gpr(dc, rd, dst);
-}
-
-static inline void gen_ldstub_asi(TCGv dst, TCGv addr, int insn)
-{
-    TCGv_i64 r_val;
-    TCGv_i32 r_asi, r_size;
-
-    gen_ld_asi(dst, addr, insn, 1, 0);
-
-    r_val = tcg_const_i64(0xffULL);
-    r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
-    r_size = tcg_const_i32(1);
-    gen_helper_st_asi(cpu_env, addr, r_val, r_asi, r_size);
-    tcg_temp_free_i32(r_size);
-    tcg_temp_free_i32(r_asi);
-    tcg_temp_free_i64(r_val);
-}
-#endif
-
 static TCGv get_src1(DisasContext *dc, unsigned int insn)
 {
     unsigned int rs1 = GET_FIELD(insn, 13, 17);
@@ -4712,7 +4689,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                         goto priv_insn;
 #endif
                     save_state(dc);
-                    gen_ld_asi(cpu_val, cpu_addr, insn, 4, 0);
+                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, 4, 0);
                     break;
                 case 0x11:      /* lduba, load unsigned byte alternate */
 #ifndef TARGET_SPARC64
@@ -4722,7 +4699,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                         goto priv_insn;
 #endif
                     save_state(dc);
-                    gen_ld_asi(cpu_val, cpu_addr, insn, 1, 0);
+                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, 1, 0);
                     break;
                 case 0x12:      /* lduha, load unsigned halfword alternate */
 #ifndef TARGET_SPARC64
@@ -4732,7 +4709,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                         goto priv_insn;
 #endif
                     save_state(dc);
-                    gen_ld_asi(cpu_val, cpu_addr, insn, 2, 0);
+                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, 2, 0);
                     break;
                 case 0x13:      /* ldda, load double word alternate */
 #ifndef TARGET_SPARC64
@@ -4754,7 +4731,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                         goto priv_insn;
 #endif
                     save_state(dc);
-                    gen_ld_asi(cpu_val, cpu_addr, insn, 1, 1);
+                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, 1, 1);
                     break;
                 case 0x1a:      /* ldsha, load signed halfword alternate */
 #ifndef TARGET_SPARC64
@@ -4764,7 +4741,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                         goto priv_insn;
 #endif
                     save_state(dc);
-                    gen_ld_asi(cpu_val, cpu_addr, insn, 2, 1);
+                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, 2, 1);
                     break;
                 case 0x1d:      /* ldstuba -- XXX: should be atomically */
 #ifndef TARGET_SPARC64
@@ -4774,7 +4751,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                         goto priv_insn;
 #endif
                     save_state(dc);
-                    gen_ldstub_asi(cpu_val, cpu_addr, insn);
+                    gen_ldstub_asi(dc, cpu_val, cpu_addr, insn);
                     break;
                 case 0x1f:      /* swapa, swap reg with alt. memory. Also
                                    atomically */
@@ -4787,7 +4764,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
 #endif
                     save_state(dc);
                     cpu_src1 = gen_load_gpr(dc, rd);
-                    gen_swap_asi(cpu_val, cpu_src1, cpu_addr, insn);
+                    gen_swap_asi(dc, cpu_val, cpu_src1, cpu_addr, insn);
                     break;
 
 #ifndef TARGET_SPARC64
@@ -4808,11 +4785,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     break;
                 case 0x18: /* V9 ldswa */
                     save_state(dc);
-                    gen_ld_asi(cpu_val, cpu_addr, insn, 4, 1);
+                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, 4, 1);
                     break;
                 case 0x1b: /* V9 ldxa */
                     save_state(dc);
-                    gen_ld_asi(cpu_val, cpu_addr, insn, 8, 0);
+                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, 8, 0);
                     break;
                 case 0x2d: /* V9 prefetch, no effect */
                     goto skip_move;
@@ -4821,7 +4798,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                         goto jmp_insn;
                     }
                     save_state(dc);
-                    gen_ldf_asi(cpu_addr, insn, 4, rd);
+                    gen_ldf_asi(dc, cpu_addr, insn, 4, rd);
                     gen_update_fprs_dirty(rd);
                     goto skip_move;
                 case 0x33: /* V9 lddfa */
@@ -4829,7 +4806,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                         goto jmp_insn;
                     }
                     save_state(dc);
-                    gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd));
+                    gen_ldf_asi(dc, cpu_addr, insn, 8, DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     goto skip_move;
                 case 0x3d: /* V9 prefetcha, no effect */
@@ -4840,7 +4817,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                         goto jmp_insn;
                     }
                     save_state(dc);
-                    gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd));
+                    gen_ldf_asi(dc, cpu_addr, insn, 16, QFPREG(rd));
                     gen_update_fprs_dirty(QFPREG(rd));
                     goto skip_move;
 #endif
@@ -4954,7 +4931,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                         goto priv_insn;
 #endif
                     save_state(dc);
-                    gen_st_asi(cpu_val, cpu_addr, insn, 4);
+                    gen_st_asi(dc, cpu_val, cpu_addr, insn, 4);
                     dc->npc = DYNAMIC_PC;
                     break;
                 case 0x15: /* stba, store byte alternate */
@@ -4965,7 +4942,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                         goto priv_insn;
 #endif
                     save_state(dc);
-                    gen_st_asi(cpu_val, cpu_addr, insn, 1);
+                    gen_st_asi(dc, cpu_val, cpu_addr, insn, 1);
                     dc->npc = DYNAMIC_PC;
                     break;
                 case 0x16: /* stha, store halfword alternate */
@@ -4976,7 +4953,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                         goto priv_insn;
 #endif
                     save_state(dc);
-                    gen_st_asi(cpu_val, cpu_addr, insn, 2);
+                    gen_st_asi(dc, cpu_val, cpu_addr, insn, 2);
                     dc->npc = DYNAMIC_PC;
                     break;
                 case 0x17: /* stda, store double word alternate */
@@ -5001,7 +4978,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     break;
                 case 0x1e: /* V9 stxa */
                     save_state(dc);
-                    gen_st_asi(cpu_val, cpu_addr, insn, 8);
+                    gen_st_asi(dc, cpu_val, cpu_addr, insn, 8);
                     dc->npc = DYNAMIC_PC;
                     break;
 #endif
@@ -5081,7 +5058,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     if (gen_trap_ifnofpu(dc)) {
                         goto jmp_insn;
                     }
-                    gen_stf_asi(cpu_addr, insn, 4, rd);
+                    gen_stf_asi(dc, cpu_addr, insn, 4, rd);
                     break;
                 case 0x36: /* V9 stqfa */
                     {
@@ -5094,14 +5071,14 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                         r_const = tcg_const_i32(7);
                         gen_helper_check_align(cpu_env, cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
-                        gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd));
+                        gen_stf_asi(dc, cpu_addr, insn, 16, QFPREG(rd));
                     }
                     break;
                 case 0x37: /* V9 stdfa */
                     if (gen_trap_ifnofpu(dc)) {
                         goto jmp_insn;
                     }
-                    gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd));
+                    gen_stf_asi(dc, cpu_addr, insn, 8, DFPREG(rd));
                     break;
                 case 0x3e: /* V9 casxa */
                     rs2 = GET_FIELD(insn, 27, 31);
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 06/24] target-sparc: Store %asi in TB flags
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (4 preceding siblings ...)
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 05/24] target-sparc: Unify asi handling between 32 and 64-bit Richard Henderson
@ 2016-06-28  0:38 ` Richard Henderson
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 07/24] target-sparc: Introduce get_asi Richard Henderson
                   ` (18 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:38 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Knowing the value of %asi at translation time means that we
can handle the common settings without a function call.

The steady state appears to be %asi == ASI_P, so that sparcv9
code can use offset forms of lda/sta.  The %asi register gets
pushed and popped on entry to certain functions, but it rarely
takes on values other than ASI_P or ASI_AIUP.  Therefore we're
unlikely to be expanding the set of TBs created.

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/cpu.h       |  2 ++
 target-sparc/translate.c | 29 ++++++++++++++++++++---------
 2 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 31ea65b..653517b 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -723,6 +723,7 @@ trap_state* cpu_tsptr(CPUSPARCState* env);
 #define TB_FLAG_MMU_MASK     7
 #define TB_FLAG_FPU_ENABLED  (1 << 4)
 #define TB_FLAG_AM_ENABLED   (1 << 5)
+#define TB_FLAG_ASI_SHIFT    24
 
 static inline void cpu_get_tb_cpu_state(CPUSPARCState *env, target_ulong *pc,
                                         target_ulong *cs_base, uint32_t *pflags)
@@ -740,6 +741,7 @@ static inline void cpu_get_tb_cpu_state(CPUSPARCState *env, target_ulong *pc,
         && (env->fprs & FPRS_FEF)) {
         flags |= TB_FLAG_FPU_ENABLED;
     }
+    flags |= env->asi << TB_FLAG_ASI_SHIFT;
 #else
     if ((env->def->features & CPU_FEATURE_FLOAT) && env->psref) {
         flags |= TB_FLAG_FPU_ENABLED;
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 90c46df..0b056e5 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -53,7 +53,7 @@ static TCGv cpu_tbr;
 #endif
 static TCGv cpu_cond;
 #ifdef TARGET_SPARC64
-static TCGv_i32 cpu_xcc, cpu_asi, cpu_fprs;
+static TCGv_i32 cpu_xcc, cpu_fprs;
 static TCGv cpu_gsr;
 static TCGv cpu_tick_cmpr, cpu_stick_cmpr, cpu_hstick_cmpr;
 static TCGv cpu_hintp, cpu_htba, cpu_hver, cpu_ssr, cpu_ver;
@@ -81,6 +81,9 @@ typedef struct DisasContext {
     TCGv ttl[5];
     int n_t32;
     int n_ttl;
+#ifdef TARGET_SPARC64
+    int asi;
+#endif
 } DisasContext;
 
 typedef struct {
@@ -1975,19 +1978,19 @@ static inline void gen_ne_fop_QD(DisasContext *dc, int rd, int rs,
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
 static TCGv_i32 gen_get_asi(DisasContext *dc, int insn)
 {
-    TCGv_i32 r_asi = tcg_temp_new_i32();
+    int asi;
 
     if (IS_IMM) {
 #ifdef TARGET_SPARC64
-        tcg_gen_mov_i32(r_asi, cpu_asi);
+        asi = dc->asi;
 #else
         gen_exception(dc, TT_ILL_INSN);
-        tcg_gen_movi_i32(r_asi, 0);
+        asi = 0;
 #endif
     } else {
-        tcg_gen_movi_i32(r_asi, GET_FIELD(insn, 19, 26));
+        asi = GET_FIELD(insn, 19, 26);
     }
-    return r_asi;
+    return tcg_const_i32(asi);
 }
 
 static void gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr,
@@ -2688,7 +2691,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     gen_store_gpr(dc, rd, cpu_dst);
                     break;
                 case 0x3: /* V9 rdasi */
-                    tcg_gen_ext_i32_tl(cpu_dst, cpu_asi);
+                    tcg_gen_movi_tl(cpu_dst, dc->asi);
                     gen_store_gpr(dc, rd, cpu_dst);
                     break;
                 case 0x4: /* V9 rdtick */
@@ -3614,7 +3617,13 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                             case 0x3: /* V9 wrasi */
                                 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
                                 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xff);
-                                tcg_gen_trunc_tl_i32(cpu_asi, cpu_tmp0);
+                                tcg_gen_st32_tl(cpu_tmp0, cpu_env,
+                                                offsetof(CPUSPARCState, asi));
+                                /* End TB to notice changed ASI.  */
+                                save_state(dc);
+                                gen_op_next_insn();
+                                tcg_gen_exit_tb(0);
+                                dc->is_br = 1;
                                 break;
                             case 0x6: /* V9 wrfprs */
                                 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
@@ -5195,6 +5204,9 @@ void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
     dc->fpu_enabled = tb_fpu_enabled(tb->flags);
     dc->address_mask_32bit = tb_am_enabled(tb->flags);
     dc->singlestep = (cs->singlestep_enabled || singlestep);
+#ifdef TARGET_SPARC64
+    dc->asi = (tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff;
+#endif
 
     num_insns = 0;
     max_insns = tb->cflags & CF_COUNT_MASK;
@@ -5304,7 +5316,6 @@ void gen_intermediate_code_init(CPUSPARCState *env)
     static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = {
 #ifdef TARGET_SPARC64
         { &cpu_xcc, offsetof(CPUSPARCState, xcc), "xcc" },
-        { &cpu_asi, offsetof(CPUSPARCState, asi), "asi" },
         { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" },
 #else
         { &cpu_wim, offsetof(CPUSPARCState, wim), "wim" },
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 07/24] target-sparc: Introduce get_asi
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (5 preceding siblings ...)
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 06/24] target-sparc: Store %asi in TB flags Richard Henderson
@ 2016-06-28  0:38 ` Richard Henderson
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 08/24] target-sparc: Pass TCGMemOp to gen_ld/st_asi Richard Henderson
                   ` (17 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:38 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Replace gen_get_asi, and use it for both 32-bit and 64-bit.
For v8, do supervisor and immediate checks here.

Also, move save_state and TB ending into the respective
subroutines, out of disas_sparc_insn.

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/translate.c | 505 +++++++++++++++++++++++++----------------------
 1 file changed, 273 insertions(+), 232 deletions(-)

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 0b056e5..532ad3e 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1976,97 +1976,161 @@ static inline void gen_ne_fop_QD(DisasContext *dc, int rd, int rs,
 
 /* asi moves */
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
-static TCGv_i32 gen_get_asi(DisasContext *dc, int insn)
-{
+typedef enum {
+    GET_ASI_HELPER,
+    GET_ASI_EXCP,
+} ASIType;
+
+typedef struct {
+    ASIType type;
     int asi;
+} DisasASI;
 
+static DisasASI get_asi(DisasContext *dc, int insn)
+{
+    int asi = GET_FIELD(insn, 19, 26);
+    ASIType type = GET_ASI_HELPER;
+
+#ifndef TARGET_SPARC64
+    /* Before v9, all asis are immediate and privileged.  */
     if (IS_IMM) {
-#ifdef TARGET_SPARC64
-        asi = dc->asi;
-#else
         gen_exception(dc, TT_ILL_INSN);
-        asi = 0;
-#endif
+        type = GET_ASI_EXCP;
+    } else if (supervisor(dc)
+               /* Note that LEON accepts ASI_USERDATA in user mode, for
+                  use with CASA.  Also note that previous versions of
+                  QEMU allowed ASI_P for LEON, which is incorrect.  */
+               || (asi == 0xa
+                   && (dc->def->features & CPU_FEATURE_CASA))) {
     } else {
-        asi = GET_FIELD(insn, 19, 26);
+        gen_exception(dc, TT_PRIV_INSN);
+        type = GET_ASI_EXCP;
+    }
+#else
+    if (IS_IMM) {
+        asi = dc->asi;
     }
-    return tcg_const_i32(asi);
+#endif
+
+    return (DisasASI){ type, asi };
 }
 
 static void gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr,
                        int insn, int size, int sign)
 {
-    TCGv_i32 r_asi, r_size, r_sign;
+    DisasASI da = get_asi(dc, insn);
 
-    r_asi = gen_get_asi(dc, insn);
-    r_size = tcg_const_i32(size);
-    r_sign = tcg_const_i32(sign);
+    switch (da.type) {
+    case GET_ASI_EXCP:
+        break;
+    default:
+        {
+            TCGv_i32 r_asi = tcg_const_i32(da.asi);
+            TCGv_i32 r_size = tcg_const_i32(size);
+            TCGv_i32 r_sign = tcg_const_i32(sign);
+
+            save_state(dc);
 #ifdef TARGET_SPARC64
-    gen_helper_ld_asi(dst, cpu_env, addr, r_asi, r_size, r_sign);
+            gen_helper_ld_asi(dst, cpu_env, addr, r_asi, r_size, r_sign);
 #else
-    {
-        TCGv_i64 t64 = tcg_temp_new_i64();
-        gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
-        tcg_gen_trunc_i64_tl(dst, t64);
-        tcg_temp_free_i64(t64);
-    }
+            {
+                TCGv_i64 t64 = tcg_temp_new_i64();
+                gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
+                tcg_gen_trunc_i64_tl(dst, t64);
+                tcg_temp_free_i64(t64);
+            }
 #endif
-    tcg_temp_free_i32(r_sign);
-    tcg_temp_free_i32(r_size);
-    tcg_temp_free_i32(r_asi);
+            tcg_temp_free_i32(r_sign);
+            tcg_temp_free_i32(r_size);
+            tcg_temp_free_i32(r_asi);
+        }
+        break;
+    }
 }
 
 static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr,
                        int insn, int size)
 {
-    TCGv_i32 r_asi, r_size;
+    DisasASI da = get_asi(dc, insn);
 
-    r_asi = gen_get_asi(dc, insn);
-    r_size = tcg_const_i32(size);
+    switch (da.type) {
+    case GET_ASI_EXCP:
+        break;
+    default:
+        {
+            TCGv_i32 r_asi = tcg_const_i32(da.asi);
+            TCGv_i32 r_size = tcg_const_i32(size);
+
+            save_state(dc);
 #ifdef TARGET_SPARC64
-    gen_helper_st_asi(cpu_env, addr, src, r_asi, r_size);
+            gen_helper_st_asi(cpu_env, addr, src, r_asi, r_size);
 #else
-    {
-        TCGv_i64 t64 = tcg_temp_new_i64();
-        tcg_gen_extu_tl_i64(t64, src);
-        gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
-        tcg_temp_free_i64(t64);
-    }
+            {
+                TCGv_i64 t64 = tcg_temp_new_i64();
+                tcg_gen_extu_tl_i64(t64, src);
+                gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
+                tcg_temp_free_i64(t64);
+            }
 #endif
-    tcg_temp_free_i32(r_size);
-    tcg_temp_free_i32(r_asi);
+            tcg_temp_free_i32(r_size);
+            tcg_temp_free_i32(r_asi);
+
+            /* A write to a TLB register may alter page maps.  End the TB. */
+            dc->npc = DYNAMIC_PC;
+        }
+        break;
+    }
 }
 
 static void gen_swap_asi(DisasContext *dc, TCGv dst, TCGv src,
                          TCGv addr, int insn)
 {
-    TCGv_i32 r_asi, r_size, r_sign;
-    TCGv_i64 s64, t64 = tcg_temp_new_i64();
-
-    r_asi = gen_get_asi(dc, insn);
-    r_size = tcg_const_i32(4);
-    r_sign = tcg_const_i32(0);
-    gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
-    tcg_temp_free_i32(r_sign);
-
-    s64 = tcg_temp_new_i64();
-    tcg_gen_extu_tl_i64(s64, src);
-    gen_helper_st_asi(cpu_env, addr, s64, r_asi, r_size);
-    tcg_temp_free_i64(s64);
-    tcg_temp_free_i32(r_size);
-    tcg_temp_free_i32(r_asi);
+    DisasASI da = get_asi(dc, insn);
 
-    tcg_gen_trunc_i64_tl(dst, t64);
-    tcg_temp_free_i64(t64);
+    switch (da.type) {
+    case GET_ASI_EXCP:
+        break;
+    default:
+        {
+            TCGv_i32 r_asi = tcg_const_i32(da.asi);
+            TCGv_i32 r_size = tcg_const_i32(4);
+            TCGv_i32 r_sign = tcg_const_i32(0);
+            TCGv_i64 s64, t64;
+
+            save_state(dc);
+            t64 = tcg_temp_new_i64();
+            gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
+            tcg_temp_free_i32(r_sign);
+
+            s64 = tcg_temp_new_i64();
+            tcg_gen_extu_tl_i64(s64, src);
+            gen_helper_st_asi(cpu_env, addr, s64, r_asi, r_size);
+            tcg_temp_free_i64(s64);
+            tcg_temp_free_i32(r_size);
+            tcg_temp_free_i32(r_asi);
+
+            tcg_gen_trunc_i64_tl(dst, t64);
+            tcg_temp_free_i64(t64);
+        }
+        break;
+    }
 }
 
 static void gen_cas_asi(DisasContext *dc, TCGv addr, TCGv val2,
                         int insn, int rd)
 {
-    TCGv val1 = gen_load_gpr(dc, rd);
-    TCGv dst = gen_dest_gpr(dc, rd);
-    TCGv_i32 r_asi = gen_get_asi(dc, insn);
+    DisasASI da = get_asi(dc, insn);
+    TCGv val1, dst;
+    TCGv_i32 r_asi;
 
+    if (da.type == GET_ASI_EXCP) {
+        return;
+    }
+
+    save_state(dc);
+    val1 = gen_load_gpr(dc, rd);
+    dst = gen_dest_gpr(dc, rd);
+    r_asi = tcg_const_i32(da.asi);
     gen_helper_cas_asi(dst, cpu_env, addr, val1, val2, r_asi);
     tcg_temp_free_i32(r_asi);
     gen_store_gpr(dc, rd, dst);
@@ -2074,23 +2138,34 @@ static void gen_cas_asi(DisasContext *dc, TCGv addr, TCGv val2,
 
 static void gen_ldstub_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn)
 {
-    TCGv_i32 r_asi, r_size, r_sign;
-    TCGv_i64 s64, d64 = tcg_temp_new_i64();
-
-    r_asi = gen_get_asi(dc, insn);
-    r_size = tcg_const_i32(1);
-    r_sign = tcg_const_i32(0);
-    gen_helper_ld_asi(d64, cpu_env, addr, r_asi, r_size, r_sign);
-    tcg_temp_free_i32(r_sign);
-
-    s64 = tcg_const_i64(0xff);
-    gen_helper_st_asi(cpu_env, addr, s64, r_asi, r_size);
-    tcg_temp_free_i64(s64);
-    tcg_temp_free_i32(r_size);
-    tcg_temp_free_i32(r_asi);
+    DisasASI da = get_asi(dc, insn);
 
-    tcg_gen_trunc_i64_tl(dst, d64);
-    tcg_temp_free_i64(d64);
+    switch (da.type) {
+    case GET_ASI_EXCP:
+        break;
+    default:
+        {
+            TCGv_i32 r_asi = tcg_const_i32(da.asi);
+            TCGv_i32 r_size = tcg_const_i32(1);
+            TCGv_i32 r_sign = tcg_const_i32(0);
+            TCGv_i64 s64, t64;
+
+            save_state(dc);
+            t64 = tcg_temp_new_i64();
+            gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
+            tcg_temp_free_i32(r_sign);
+
+            s64 = tcg_const_i64(0xff);
+            gen_helper_st_asi(cpu_env, addr, s64, r_asi, r_size);
+            tcg_temp_free_i64(s64);
+            tcg_temp_free_i32(r_size);
+            tcg_temp_free_i32(r_asi);
+
+            tcg_gen_trunc_i64_tl(dst, t64);
+            tcg_temp_free_i64(t64);
+        }
+        break;
+    }
 }
 #endif
 
@@ -2098,66 +2173,115 @@ static void gen_ldstub_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn)
 static void gen_ldf_asi(DisasContext *dc, TCGv addr,
                         int insn, int size, int rd)
 {
-    TCGv_i32 r_asi, r_size, r_rd;
+    DisasASI da = get_asi(dc, insn);
 
-    r_asi = gen_get_asi(dc, insn);
-    r_size = tcg_const_i32(size);
-    r_rd = tcg_const_i32(rd);
-    gen_helper_ldf_asi(cpu_env, addr, r_asi, r_size, r_rd);
-    tcg_temp_free_i32(r_rd);
-    tcg_temp_free_i32(r_size);
-    tcg_temp_free_i32(r_asi);
+    switch (da.type) {
+    case GET_ASI_EXCP:
+        break;
+    default:
+        {
+            TCGv_i32 r_asi = tcg_const_i32(da.asi);
+            TCGv_i32 r_size = tcg_const_i32(size);
+            TCGv_i32 r_rd = tcg_const_i32(rd);
+
+            save_state(dc);
+            gen_helper_ldf_asi(cpu_env, addr, r_asi, r_size, r_rd);
+            tcg_temp_free_i32(r_rd);
+            tcg_temp_free_i32(r_size);
+            tcg_temp_free_i32(r_asi);
+        }
+        break;
+    }
 }
 
 static void gen_stf_asi(DisasContext *dc, TCGv addr,
                         int insn, int size, int rd)
 {
-    TCGv_i32 r_asi, r_size, r_rd;
+    DisasASI da = get_asi(dc, insn);
 
-    r_asi = gen_get_asi(dc, insn);
-    r_size = tcg_const_i32(size);
-    r_rd = tcg_const_i32(rd);
-    gen_helper_stf_asi(cpu_env, addr, r_asi, r_size, r_rd);
-    tcg_temp_free_i32(r_rd);
-    tcg_temp_free_i32(r_size);
-    tcg_temp_free_i32(r_asi);
+    switch (da.type) {
+    case GET_ASI_EXCP:
+        break;
+    default:
+        {
+            TCGv_i32 r_asi = tcg_const_i32(da.asi);
+            TCGv_i32 r_size = tcg_const_i32(size);
+            TCGv_i32 r_rd = tcg_const_i32(rd);
+
+            save_state(dc);
+            gen_helper_stf_asi(cpu_env, addr, r_asi, r_size, r_rd);
+            tcg_temp_free_i32(r_rd);
+            tcg_temp_free_i32(r_size);
+            tcg_temp_free_i32(r_asi);
+        }
+        break;
+    }
 }
 
 static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
                          int insn, int rd)
 {
-    TCGv_i32 r_asi, r_rd;
+    DisasASI da = get_asi(dc, insn);
 
-    r_asi = gen_get_asi(dc, insn);
-    r_rd = tcg_const_i32(rd);
-    gen_helper_ldda_asi(cpu_env, addr, r_asi, r_rd);
-    tcg_temp_free_i32(r_rd);
-    tcg_temp_free_i32(r_asi);
+    switch (da.type) {
+    case GET_ASI_EXCP:
+        break;
+    default:
+        {
+            TCGv_i32 r_asi = tcg_const_i32(da.asi);
+            TCGv_i32 r_rd = tcg_const_i32(rd);
+
+            save_state(dc);
+            gen_helper_ldda_asi(cpu_env, addr, r_asi, r_rd);
+            tcg_temp_free_i32(r_rd);
+            tcg_temp_free_i32(r_asi);
+        }
+        break;
+    }
 }
 
 static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
                          int insn, int rd)
 {
-    TCGv_i32 r_asi, r_size;
+    DisasASI da = get_asi(dc, insn);
     TCGv lo = gen_load_gpr(dc, rd + 1);
-    TCGv_i64 t64 = tcg_temp_new_i64();
 
-    tcg_gen_concat_tl_i64(t64, lo, hi);
-    r_asi = gen_get_asi(dc, insn);
-    r_size = tcg_const_i32(8);
-    gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
-    tcg_temp_free_i32(r_size);
-    tcg_temp_free_i32(r_asi);
-    tcg_temp_free_i64(t64);
+    switch (da.type) {
+    case GET_ASI_EXCP:
+        break;
+    default:
+        {
+            TCGv_i32 r_asi = tcg_const_i32(da.asi);
+            TCGv_i32 r_size = tcg_const_i32(8);
+            TCGv_i64 t64;
+
+            save_state(dc);
+
+            t64 = tcg_temp_new_i64();
+            tcg_gen_concat_tl_i64(t64, lo, hi);
+            gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
+            tcg_temp_free_i32(r_size);
+            tcg_temp_free_i32(r_asi);
+            tcg_temp_free_i64(t64);
+        }
+        break;
+    }
 }
 
 static void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv val2,
                          int insn, int rd)
 {
+    DisasASI da = get_asi(dc, insn);
     TCGv val1 = gen_load_gpr(dc, rd);
     TCGv dst = gen_dest_gpr(dc, rd);
-    TCGv_i32 r_asi = gen_get_asi(dc, insn);
+    TCGv_i32 r_asi;
 
+    if (da.type == GET_ASI_EXCP) {
+        return;
+    }
+
+    save_state(dc);
+    r_asi = tcg_const_i32(da.asi);
     gen_helper_casx_asi(dst, cpu_env, addr, val1, val2, r_asi);
     tcg_temp_free_i32(r_asi);
     gen_store_gpr(dc, rd, dst);
@@ -2167,46 +2291,64 @@ static void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv val2,
 static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
                          int insn, int rd)
 {
-    TCGv_i32 r_asi, r_size, r_sign;
-    TCGv t;
-    TCGv_i64 t64;
-
-    r_asi = gen_get_asi(dc, insn);
-    r_size = tcg_const_i32(8);
-    r_sign = tcg_const_i32(0);
-    t64 = tcg_temp_new_i64();
-    gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
-    tcg_temp_free_i32(r_sign);
-    tcg_temp_free_i32(r_size);
-    tcg_temp_free_i32(r_asi);
-
     /* ??? Work around an apparent bug in Ubuntu gcc 4.8.2-10ubuntu2+12,
        whereby "rd + 1" elicits "error: array subscript is above array".
        Since we have already asserted that rd is even, the semantics
        are unchanged.  */
-    t = gen_dest_gpr(dc, rd | 1);
-    tcg_gen_trunc_i64_tl(t, t64);
-    gen_store_gpr(dc, rd | 1, t);
+    DisasASI da = get_asi(dc, insn);
+    TCGv lo = gen_dest_gpr(dc, rd | 1);
+    TCGv_i64 t64 = tcg_temp_new_i64();
+
+    switch (da.type) {
+    case GET_ASI_EXCP:
+        tcg_temp_free_i64(t64);
+        return;
+    default:
+        {
+            TCGv_i32 r_asi = tcg_const_i32(da.asi);
+            TCGv_i32 r_size = tcg_const_i32(8);
+            TCGv_i32 r_sign = tcg_const_i32(0);
+
+            save_state(dc);
+            gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
+            tcg_temp_free_i32(r_sign);
+            tcg_temp_free_i32(r_size);
+            tcg_temp_free_i32(r_asi);
+        }
+        break;
+    }
 
-    tcg_gen_shri_i64(t64, t64, 32);
-    tcg_gen_trunc_i64_tl(hi, t64);
+    tcg_gen_extr_i64_i32(lo, hi, t64);
     tcg_temp_free_i64(t64);
+    gen_store_gpr(dc, rd | 1, lo);
     gen_store_gpr(dc, rd, hi);
 }
 
 static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
                          int insn, int rd)
 {
-    TCGv_i32 r_asi, r_size;
+    DisasASI da = get_asi(dc, insn);
     TCGv lo = gen_load_gpr(dc, rd + 1);
     TCGv_i64 t64 = tcg_temp_new_i64();
 
     tcg_gen_concat_tl_i64(t64, lo, hi);
-    r_asi = gen_get_asi(dc, insn);
-    r_size = tcg_const_i32(8);
-    gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
-    tcg_temp_free_i32(r_size);
-    tcg_temp_free_i32(r_asi);
+
+    switch (da.type) {
+    case GET_ASI_EXCP:
+        break;
+    default:
+        {
+            TCGv_i32 r_asi = tcg_const_i32(da.asi);
+            TCGv_i32 r_size = tcg_const_i32(8);
+
+            save_state(dc);
+            gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
+            tcg_temp_free_i32(r_size);
+            tcg_temp_free_i32(r_asi);
+        }
+        break;
+    }
+
     tcg_temp_free_i64(t64);
 }
 #endif
@@ -4691,87 +4833,32 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     break;
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
                 case 0x10:      /* lda, V9 lduwa, load word alternate */
-#ifndef TARGET_SPARC64
-                    if (IS_IMM)
-                        goto illegal_insn;
-                    if (!supervisor(dc))
-                        goto priv_insn;
-#endif
-                    save_state(dc);
                     gen_ld_asi(dc, cpu_val, cpu_addr, insn, 4, 0);
                     break;
                 case 0x11:      /* lduba, load unsigned byte alternate */
-#ifndef TARGET_SPARC64
-                    if (IS_IMM)
-                        goto illegal_insn;
-                    if (!supervisor(dc))
-                        goto priv_insn;
-#endif
-                    save_state(dc);
                     gen_ld_asi(dc, cpu_val, cpu_addr, insn, 1, 0);
                     break;
                 case 0x12:      /* lduha, load unsigned halfword alternate */
-#ifndef TARGET_SPARC64
-                    if (IS_IMM)
-                        goto illegal_insn;
-                    if (!supervisor(dc))
-                        goto priv_insn;
-#endif
-                    save_state(dc);
                     gen_ld_asi(dc, cpu_val, cpu_addr, insn, 2, 0);
                     break;
                 case 0x13:      /* ldda, load double word alternate */
-#ifndef TARGET_SPARC64
-                    if (IS_IMM)
-                        goto illegal_insn;
-                    if (!supervisor(dc))
-                        goto priv_insn;
-#endif
-                    if (rd & 1)
+                    if (rd & 1) {
                         goto illegal_insn;
-                    save_state(dc);
+                    }
                     gen_ldda_asi(dc, cpu_val, cpu_addr, insn, rd);
                     goto skip_move;
                 case 0x19:      /* ldsba, load signed byte alternate */
-#ifndef TARGET_SPARC64
-                    if (IS_IMM)
-                        goto illegal_insn;
-                    if (!supervisor(dc))
-                        goto priv_insn;
-#endif
-                    save_state(dc);
                     gen_ld_asi(dc, cpu_val, cpu_addr, insn, 1, 1);
                     break;
                 case 0x1a:      /* ldsha, load signed halfword alternate */
-#ifndef TARGET_SPARC64
-                    if (IS_IMM)
-                        goto illegal_insn;
-                    if (!supervisor(dc))
-                        goto priv_insn;
-#endif
-                    save_state(dc);
                     gen_ld_asi(dc, cpu_val, cpu_addr, insn, 2, 1);
                     break;
                 case 0x1d:      /* ldstuba -- XXX: should be atomically */
-#ifndef TARGET_SPARC64
-                    if (IS_IMM)
-                        goto illegal_insn;
-                    if (!supervisor(dc))
-                        goto priv_insn;
-#endif
-                    save_state(dc);
                     gen_ldstub_asi(dc, cpu_val, cpu_addr, insn);
                     break;
                 case 0x1f:      /* swapa, swap reg with alt. memory. Also
                                    atomically */
                     CHECK_IU_FEATURE(dc, SWAP);
-#ifndef TARGET_SPARC64
-                    if (IS_IMM)
-                        goto illegal_insn;
-                    if (!supervisor(dc))
-                        goto priv_insn;
-#endif
-                    save_state(dc);
                     cpu_src1 = gen_load_gpr(dc, rd);
                     gen_swap_asi(dc, cpu_val, cpu_src1, cpu_addr, insn);
                     break;
@@ -4793,11 +4880,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx);
                     break;
                 case 0x18: /* V9 ldswa */
-                    save_state(dc);
                     gen_ld_asi(dc, cpu_val, cpu_addr, insn, 4, 1);
                     break;
                 case 0x1b: /* V9 ldxa */
-                    save_state(dc);
                     gen_ld_asi(dc, cpu_val, cpu_addr, insn, 8, 0);
                     break;
                 case 0x2d: /* V9 prefetch, no effect */
@@ -4806,7 +4891,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     if (gen_trap_ifnofpu(dc)) {
                         goto jmp_insn;
                     }
-                    save_state(dc);
                     gen_ldf_asi(dc, cpu_addr, insn, 4, rd);
                     gen_update_fprs_dirty(rd);
                     goto skip_move;
@@ -4814,7 +4898,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     if (gen_trap_ifnofpu(dc)) {
                         goto jmp_insn;
                     }
-                    save_state(dc);
                     gen_ldf_asi(dc, cpu_addr, insn, 8, DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     goto skip_move;
@@ -4825,7 +4908,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     if (gen_trap_ifnofpu(dc)) {
                         goto jmp_insn;
                     }
-                    save_state(dc);
                     gen_ldf_asi(dc, cpu_addr, insn, 16, QFPREG(rd));
                     gen_update_fprs_dirty(QFPREG(rd));
                     goto skip_move;
@@ -4933,51 +5015,19 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     break;
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
                 case 0x14: /* sta, V9 stwa, store word alternate */
-#ifndef TARGET_SPARC64
-                    if (IS_IMM)
-                        goto illegal_insn;
-                    if (!supervisor(dc))
-                        goto priv_insn;
-#endif
-                    save_state(dc);
                     gen_st_asi(dc, cpu_val, cpu_addr, insn, 4);
-                    dc->npc = DYNAMIC_PC;
                     break;
                 case 0x15: /* stba, store byte alternate */
-#ifndef TARGET_SPARC64
-                    if (IS_IMM)
-                        goto illegal_insn;
-                    if (!supervisor(dc))
-                        goto priv_insn;
-#endif
-                    save_state(dc);
                     gen_st_asi(dc, cpu_val, cpu_addr, insn, 1);
-                    dc->npc = DYNAMIC_PC;
                     break;
                 case 0x16: /* stha, store halfword alternate */
-#ifndef TARGET_SPARC64
-                    if (IS_IMM)
-                        goto illegal_insn;
-                    if (!supervisor(dc))
-                        goto priv_insn;
-#endif
-                    save_state(dc);
                     gen_st_asi(dc, cpu_val, cpu_addr, insn, 2);
-                    dc->npc = DYNAMIC_PC;
                     break;
                 case 0x17: /* stda, store double word alternate */
-#ifndef TARGET_SPARC64
-                    if (IS_IMM)
+                    if (rd & 1) {
                         goto illegal_insn;
-                    if (!supervisor(dc))
-                        goto priv_insn;
-#endif
-                    if (rd & 1)
-                        goto illegal_insn;
-                    else {
-                        save_state(dc);
-                        gen_stda_asi(dc, cpu_val, cpu_addr, insn, rd);
                     }
+                    gen_stda_asi(dc, cpu_val, cpu_addr, insn, rd);
                     break;
 #endif
 #ifdef TARGET_SPARC64
@@ -4986,9 +5036,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx);
                     break;
                 case 0x1e: /* V9 stxa */
-                    save_state(dc);
                     gen_st_asi(dc, cpu_val, cpu_addr, insn, 8);
-                    dc->npc = DYNAMIC_PC;
                     break;
 #endif
                 default:
@@ -5105,13 +5153,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                 case 0x3c: /* V9 or LEON3 casa */
 #ifndef TARGET_SPARC64
                     CHECK_IU_FEATURE(dc, CASA);
-                    if (IS_IMM) {
-                        goto illegal_insn;
-                    }
-                    /* LEON3 allows CASA from user space with ASI 0xa */
-                    if ((GET_FIELD(insn, 19, 26) != 0xa) && !supervisor(dc)) {
-                        goto priv_insn;
-                    }
 #endif
                     rs2 = GET_FIELD(insn, 27, 31);
                     cpu_src2 = gen_load_gpr(dc, rs2);
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 08/24] target-sparc: Pass TCGMemOp to gen_ld/st_asi
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (6 preceding siblings ...)
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 07/24] target-sparc: Introduce get_asi Richard Henderson
@ 2016-06-28  0:38 ` Richard Henderson
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 09/24] target-sparc: Import linux/arch/sparc/include/uapi/asm/asi.h Richard Henderson
                   ` (16 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:38 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/translate.c | 32 ++++++++++++++++----------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 532ad3e..886e132 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2016,7 +2016,7 @@ static DisasASI get_asi(DisasContext *dc, int insn)
 }
 
 static void gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr,
-                       int insn, int size, int sign)
+                       int insn, TCGMemOp memop)
 {
     DisasASI da = get_asi(dc, insn);
 
@@ -2026,8 +2026,8 @@ static void gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr,
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
-            TCGv_i32 r_size = tcg_const_i32(size);
-            TCGv_i32 r_sign = tcg_const_i32(sign);
+            TCGv_i32 r_size = tcg_const_i32(1 << (memop & MO_SIZE));
+            TCGv_i32 r_sign = tcg_const_i32(!!(memop & MO_SIGN));
 
             save_state(dc);
 #ifdef TARGET_SPARC64
@@ -2049,7 +2049,7 @@ static void gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr,
 }
 
 static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr,
-                       int insn, int size)
+                       int insn, TCGMemOp memop)
 {
     DisasASI da = get_asi(dc, insn);
 
@@ -2059,7 +2059,7 @@ static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr,
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
-            TCGv_i32 r_size = tcg_const_i32(size);
+            TCGv_i32 r_size = tcg_const_i32(1 << (memop & MO_SIZE));
 
             save_state(dc);
 #ifdef TARGET_SPARC64
@@ -4833,13 +4833,13 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     break;
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
                 case 0x10:      /* lda, V9 lduwa, load word alternate */
-                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, 4, 0);
+                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEUL);
                     break;
                 case 0x11:      /* lduba, load unsigned byte alternate */
-                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, 1, 0);
+                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_UB);
                     break;
                 case 0x12:      /* lduha, load unsigned halfword alternate */
-                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, 2, 0);
+                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEUW);
                     break;
                 case 0x13:      /* ldda, load double word alternate */
                     if (rd & 1) {
@@ -4848,10 +4848,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     gen_ldda_asi(dc, cpu_val, cpu_addr, insn, rd);
                     goto skip_move;
                 case 0x19:      /* ldsba, load signed byte alternate */
-                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, 1, 1);
+                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_SB);
                     break;
                 case 0x1a:      /* ldsha, load signed halfword alternate */
-                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, 2, 1);
+                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TESW);
                     break;
                 case 0x1d:      /* ldstuba -- XXX: should be atomically */
                     gen_ldstub_asi(dc, cpu_val, cpu_addr, insn);
@@ -4880,10 +4880,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx);
                     break;
                 case 0x18: /* V9 ldswa */
-                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, 4, 1);
+                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TESL);
                     break;
                 case 0x1b: /* V9 ldxa */
-                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, 8, 0);
+                    gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEQ);
                     break;
                 case 0x2d: /* V9 prefetch, no effect */
                     goto skip_move;
@@ -5015,13 +5015,13 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     break;
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
                 case 0x14: /* sta, V9 stwa, store word alternate */
-                    gen_st_asi(dc, cpu_val, cpu_addr, insn, 4);
+                    gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUL);
                     break;
                 case 0x15: /* stba, store byte alternate */
-                    gen_st_asi(dc, cpu_val, cpu_addr, insn, 1);
+                    gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_UB);
                     break;
                 case 0x16: /* stha, store halfword alternate */
-                    gen_st_asi(dc, cpu_val, cpu_addr, insn, 2);
+                    gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUW);
                     break;
                 case 0x17: /* stda, store double word alternate */
                     if (rd & 1) {
@@ -5036,7 +5036,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx);
                     break;
                 case 0x1e: /* V9 stxa */
-                    gen_st_asi(dc, cpu_val, cpu_addr, insn, 8);
+                    gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEQ);
                     break;
 #endif
                 default:
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 09/24] target-sparc: Import linux/arch/sparc/include/uapi/asm/asi.h
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (7 preceding siblings ...)
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 08/24] target-sparc: Pass TCGMemOp to gen_ld/st_asi Richard Henderson
@ 2016-06-28  0:38 ` Richard Henderson
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 10/24] target-sparc: Add UA2005 defines to asi.h Richard Henderson
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:38 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Copied from tag v4.2, 64291f7db5bd8150a74ad2036f1037e6a0428df2.

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/asi.h | 297 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 297 insertions(+)
 create mode 100644 target-sparc/asi.h

diff --git a/target-sparc/asi.h b/target-sparc/asi.h
new file mode 100644
index 0000000..aace6f3
--- /dev/null
+++ b/target-sparc/asi.h
@@ -0,0 +1,297 @@
+#ifndef _SPARC_ASI_H
+#define _SPARC_ASI_H
+
+/* asi.h:  Address Space Identifier values for the sparc.
+ *
+ * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * Pioneer work for sun4m: Paul Hatchman (paul@sfe.com.au)
+ * Joint edition for sun4c+sun4m: Pete A. Zaitcev <zaitcev@ipmce.su>
+ */
+
+/* The first batch are for the sun4c. */
+
+#define ASI_NULL1           0x00
+#define ASI_NULL2           0x01
+
+/* sun4c and sun4 control registers and mmu/vac ops */
+#define ASI_CONTROL         0x02
+#define ASI_SEGMAP          0x03
+#define ASI_PTE             0x04
+#define ASI_HWFLUSHSEG      0x05
+#define ASI_HWFLUSHPAGE     0x06
+#define ASI_REGMAP          0x06
+#define ASI_HWFLUSHCONTEXT  0x07
+
+#define ASI_USERTXT         0x08
+#define ASI_KERNELTXT       0x09
+#define ASI_USERDATA        0x0a
+#define ASI_KERNELDATA      0x0b
+
+/* VAC Cache flushing on sun4c and sun4 */
+#define ASI_FLUSHSEG        0x0c
+#define ASI_FLUSHPG         0x0d
+#define ASI_FLUSHCTX        0x0e
+
+/* SPARCstation-5: only 6 bits are decoded. */
+/* wo = Write Only, rw = Read Write;        */
+/* ss = Single Size, as = All Sizes;        */
+#define ASI_M_RES00         0x00   /* Don't touch... */
+#define ASI_M_UNA01         0x01   /* Same here... */
+#define ASI_M_MXCC          0x02   /* Access to TI VIKING MXCC registers */
+#define ASI_M_FLUSH_PROBE   0x03   /* Reference MMU Flush/Probe; rw, ss */
+#define ASI_M_MMUREGS       0x04   /* MMU Registers; rw, ss */
+#define ASI_M_TLBDIAG       0x05   /* MMU TLB only Diagnostics */
+#define ASI_M_DIAGS         0x06   /* Reference MMU Diagnostics */
+#define ASI_M_IODIAG        0x07   /* MMU I/O TLB only Diagnostics */
+#define ASI_M_USERTXT       0x08   /* Same as ASI_USERTXT; rw, as */
+#define ASI_M_KERNELTXT     0x09   /* Same as ASI_KERNELTXT; rw, as */
+#define ASI_M_USERDATA      0x0A   /* Same as ASI_USERDATA; rw, as */
+#define ASI_M_KERNELDATA    0x0B   /* Same as ASI_KERNELDATA; rw, as */
+#define ASI_M_TXTC_TAG      0x0C   /* Instruction Cache Tag; rw, ss */
+#define ASI_M_TXTC_DATA     0x0D   /* Instruction Cache Data; rw, ss */
+#define ASI_M_DATAC_TAG     0x0E   /* Data Cache Tag; rw, ss */
+#define ASI_M_DATAC_DATA    0x0F   /* Data Cache Data; rw, ss */
+
+/* The following cache flushing ASIs work only with the 'sta'
+ * instruction. Results are unpredictable for 'swap' and 'ldstuba',
+ * so don't do it.
+ */
+
+/* These ASI flushes affect external caches too. */
+#define ASI_M_FLUSH_PAGE    0x10   /* Flush I&D Cache Line (page); wo, ss */
+#define ASI_M_FLUSH_SEG     0x11   /* Flush I&D Cache Line (seg); wo, ss */
+#define ASI_M_FLUSH_REGION  0x12   /* Flush I&D Cache Line (region); wo, ss */
+#define ASI_M_FLUSH_CTX     0x13   /* Flush I&D Cache Line (context); wo, ss */
+#define ASI_M_FLUSH_USER    0x14   /* Flush I&D Cache Line (user); wo, ss */
+
+/* Block-copy operations are available only on certain V8 cpus. */
+#define ASI_M_BCOPY         0x17   /* Block copy */
+
+/* These affect only the ICACHE and are Ross HyperSparc and TurboSparc specific. */
+#define ASI_M_IFLUSH_PAGE   0x18   /* Flush I Cache Line (page); wo, ss */
+#define ASI_M_IFLUSH_SEG    0x19   /* Flush I Cache Line (seg); wo, ss */
+#define ASI_M_IFLUSH_REGION 0x1A   /* Flush I Cache Line (region); wo, ss */
+#define ASI_M_IFLUSH_CTX    0x1B   /* Flush I Cache Line (context); wo, ss */
+#define ASI_M_IFLUSH_USER   0x1C   /* Flush I Cache Line (user); wo, ss */
+
+/* Block-fill operations are available on certain V8 cpus */
+#define ASI_M_BFILL         0x1F
+
+/* This allows direct access to main memory, actually 0x20 to 0x2f are
+ * the available ASI's for physical ram pass-through, but I don't have
+ * any idea what the other ones do....
+ */
+
+#define ASI_M_BYPASS       0x20   /* Reference MMU bypass; rw, as */
+#define ASI_M_FBMEM        0x29   /* Graphics card frame buffer access */
+#define ASI_M_VMEUS        0x2A   /* VME user 16-bit access */
+#define ASI_M_VMEPS        0x2B   /* VME priv 16-bit access */
+#define ASI_M_VMEUT        0x2C   /* VME user 32-bit access */
+#define ASI_M_VMEPT        0x2D   /* VME priv 32-bit access */
+#define ASI_M_SBUS         0x2E   /* Direct SBus access */
+#define ASI_M_CTL          0x2F   /* Control Space (ECC and MXCC are here) */
+
+
+/* This is ROSS HyperSparc only. */
+#define ASI_M_FLUSH_IWHOLE 0x31   /* Flush entire ICACHE; wo, ss */
+
+/* Tsunami/Viking/TurboSparc i/d cache flash clear. */
+#define ASI_M_IC_FLCLEAR   0x36
+#define ASI_M_DC_FLCLEAR   0x37
+
+#define ASI_M_DCDR         0x39   /* Data Cache Diagnostics Register rw, ss */
+
+#define ASI_M_VIKING_TMP1  0x40	  /* Emulation temporary 1 on Viking */
+/* only available on SuperSparc I */
+/* #define ASI_M_VIKING_TMP2  0x41 */  /* Emulation temporary 2 on Viking */
+
+#define ASI_M_ACTION       0x4c   /* Breakpoint Action Register (GNU/Viking) */
+
+/* LEON ASI */
+#define ASI_LEON_NOCACHE        0x01
+
+#define ASI_LEON_DCACHE_MISS    0x01
+
+#define ASI_LEON_CACHEREGS      0x02
+#define ASI_LEON_IFLUSH         0x10
+#define ASI_LEON_DFLUSH         0x11
+
+#define ASI_LEON_MMUFLUSH       0x18
+#define ASI_LEON_MMUREGS        0x19
+#define ASI_LEON_BYPASS         0x1c
+#define ASI_LEON_FLUSH_PAGE     0x10
+
+/* V9 Architecture mandary ASIs. */
+#define ASI_N			0x04 /* Nucleus				*/
+#define ASI_NL			0x0c /* Nucleus, little endian		*/
+#define ASI_AIUP		0x10 /* Primary, user			*/
+#define ASI_AIUS		0x11 /* Secondary, user			*/
+#define ASI_AIUPL		0x18 /* Primary, user, little endian	*/
+#define ASI_AIUSL		0x19 /* Secondary, user, little endian	*/
+#define ASI_P			0x80 /* Primary, implicit		*/
+#define ASI_S			0x81 /* Secondary, implicit		*/
+#define ASI_PNF			0x82 /* Primary, no fault		*/
+#define ASI_SNF			0x83 /* Secondary, no fault		*/
+#define ASI_PL			0x88 /* Primary, implicit, l-endian	*/
+#define ASI_SL			0x89 /* Secondary, implicit, l-endian	*/
+#define ASI_PNFL		0x8a /* Primary, no fault, l-endian	*/
+#define ASI_SNFL		0x8b /* Secondary, no fault, l-endian	*/
+
+/* SpitFire and later extended ASIs.  The "(III)" marker designates
+ * UltraSparc-III and later specific ASIs.  The "(CMT)" marker designates
+ * Chip Multi Threading specific ASIs.  "(NG)" designates Niagara specific
+ * ASIs, "(4V)" designates SUN4V specific ASIs.  "(NG4)" designates SPARC-T4
+ * and later ASIs.
+ */
+#define ASI_PHYS_USE_EC		0x14 /* PADDR, E-cachable		*/
+#define ASI_PHYS_BYPASS_EC_E	0x15 /* PADDR, E-bit			*/
+#define ASI_BLK_AIUP_4V		0x16 /* (4V) Prim, user, block ld/st	*/
+#define ASI_BLK_AIUS_4V		0x17 /* (4V) Sec, user, block ld/st	*/
+#define ASI_PHYS_USE_EC_L	0x1c /* PADDR, E-cachable, little endian*/
+#define ASI_PHYS_BYPASS_EC_E_L	0x1d /* PADDR, E-bit, little endian	*/
+#define ASI_BLK_AIUP_L_4V	0x1e /* (4V) Prim, user, block, l-endian*/
+#define ASI_BLK_AIUS_L_4V	0x1f /* (4V) Sec, user, block, l-endian	*/
+#define ASI_SCRATCHPAD		0x20 /* (4V) Scratch Pad Registers	*/
+#define ASI_MMU			0x21 /* (4V) MMU Context Registers	*/
+#define ASI_BLK_INIT_QUAD_LDD_AIUS 0x23 /* (NG) init-store, twin load,
+					 * secondary, user
+					 */
+#define ASI_NUCLEUS_QUAD_LDD	0x24 /* Cachable, qword load		*/
+#define ASI_QUEUE		0x25 /* (4V) Interrupt Queue Registers	*/
+#define ASI_QUAD_LDD_PHYS_4V	0x26 /* (4V) Physical, qword load	*/
+#define ASI_NUCLEUS_QUAD_LDD_L	0x2c /* Cachable, qword load, l-endian 	*/
+#define ASI_QUAD_LDD_PHYS_L_4V	0x2e /* (4V) Phys, qword load, l-endian	*/
+#define ASI_PCACHE_DATA_STATUS	0x30 /* (III) PCache data stat RAM diag	*/
+#define ASI_PCACHE_DATA		0x31 /* (III) PCache data RAM diag	*/
+#define ASI_PCACHE_TAG		0x32 /* (III) PCache tag RAM diag	*/
+#define ASI_PCACHE_SNOOP_TAG	0x33 /* (III) PCache snoop tag RAM diag	*/
+#define ASI_QUAD_LDD_PHYS	0x34 /* (III+) PADDR, qword load	*/
+#define ASI_WCACHE_VALID_BITS	0x38 /* (III) WCache Valid Bits diag	*/
+#define ASI_WCACHE_DATA		0x39 /* (III) WCache data RAM diag	*/
+#define ASI_WCACHE_TAG		0x3a /* (III) WCache tag RAM diag	*/
+#define ASI_WCACHE_SNOOP_TAG	0x3b /* (III) WCache snoop tag RAM diag	*/
+#define ASI_QUAD_LDD_PHYS_L	0x3c /* (III+) PADDR, qw-load, l-endian	*/
+#define ASI_SRAM_FAST_INIT	0x40 /* (III+) Fast SRAM init		*/
+#define ASI_CORE_AVAILABLE	0x41 /* (CMT) LP Available		*/
+#define ASI_CORE_ENABLE_STAT	0x41 /* (CMT) LP Enable Status		*/
+#define ASI_CORE_ENABLE		0x41 /* (CMT) LP Enable RW		*/
+#define ASI_XIR_STEERING	0x41 /* (CMT) XIR Steering RW		*/
+#define ASI_CORE_RUNNING_RW	0x41 /* (CMT) LP Running RW		*/
+#define ASI_CORE_RUNNING_W1S	0x41 /* (CMT) LP Running Write-One Set	*/
+#define ASI_CORE_RUNNING_W1C	0x41 /* (CMT) LP Running Write-One Clr	*/
+#define ASI_CORE_RUNNING_STAT	0x41 /* (CMT) LP Running Status		*/
+#define ASI_CMT_ERROR_STEERING	0x41 /* (CMT) Error Steering RW		*/
+#define ASI_DCACHE_INVALIDATE	0x42 /* (III) DCache Invalidate diag	*/
+#define ASI_DCACHE_UTAG		0x43 /* (III) DCache uTag diag		*/
+#define ASI_DCACHE_SNOOP_TAG	0x44 /* (III) DCache snoop tag RAM diag	*/
+#define ASI_LSU_CONTROL		0x45 /* Load-store control unit		*/
+#define ASI_DCU_CONTROL_REG	0x45 /* (III) DCache Unit Control reg	*/
+#define ASI_DCACHE_DATA		0x46 /* DCache data-ram diag access	*/
+#define ASI_DCACHE_TAG		0x47 /* Dcache tag/valid ram diag access*/
+#define ASI_INTR_DISPATCH_STAT	0x48 /* IRQ vector dispatch status	*/
+#define ASI_INTR_RECEIVE	0x49 /* IRQ vector receive status	*/
+#define ASI_UPA_CONFIG		0x4a /* UPA config space		*/
+#define ASI_JBUS_CONFIG		0x4a /* (IIIi) JBUS Config Register	*/
+#define ASI_SAFARI_CONFIG	0x4a /* (III) Safari Config Register	*/
+#define ASI_SAFARI_ADDRESS	0x4a /* (III) Safari Address Register	*/
+#define ASI_ESTATE_ERROR_EN	0x4b /* E-cache error enable space	*/
+#define ASI_AFSR		0x4c /* Async fault status register	*/
+#define ASI_AFAR		0x4d /* Async fault address register	*/
+#define ASI_EC_TAG_DATA		0x4e /* E-cache tag/valid ram diag acc	*/
+#define ASI_IMMU		0x50 /* Insn-MMU main register space	*/
+#define ASI_IMMU_TSB_8KB_PTR	0x51 /* Insn-MMU 8KB TSB pointer reg	*/
+#define ASI_IMMU_TSB_64KB_PTR	0x52 /* Insn-MMU 64KB TSB pointer reg	*/
+#define ASI_ITLB_DATA_IN	0x54 /* Insn-MMU TLB data in reg	*/
+#define ASI_ITLB_DATA_ACCESS	0x55 /* Insn-MMU TLB data access reg	*/
+#define ASI_ITLB_TAG_READ	0x56 /* Insn-MMU TLB tag read reg	*/
+#define ASI_IMMU_DEMAP		0x57 /* Insn-MMU TLB demap		*/
+#define ASI_DMMU		0x58 /* Data-MMU main register space	*/
+#define ASI_DMMU_TSB_8KB_PTR	0x59 /* Data-MMU 8KB TSB pointer reg	*/
+#define ASI_DMMU_TSB_64KB_PTR	0x5a /* Data-MMU 16KB TSB pointer reg	*/
+#define ASI_DMMU_TSB_DIRECT_PTR	0x5b /* Data-MMU TSB direct pointer reg	*/
+#define ASI_DTLB_DATA_IN	0x5c /* Data-MMU TLB data in reg	*/
+#define ASI_DTLB_DATA_ACCESS	0x5d /* Data-MMU TLB data access reg	*/
+#define ASI_DTLB_TAG_READ	0x5e /* Data-MMU TLB tag read reg	*/
+#define ASI_DMMU_DEMAP		0x5f /* Data-MMU TLB demap		*/
+#define ASI_IIU_INST_TRAP	0x60 /* (III) Instruction Breakpoint	*/
+#define ASI_INTR_ID		0x63 /* (CMT) Interrupt ID register	*/
+#define ASI_CORE_ID		0x63 /* (CMT) LP ID register		*/
+#define ASI_CESR_ID		0x63 /* (CMT) CESR ID register		*/
+#define ASI_IC_INSTR		0x66 /* Insn cache instrucion ram diag	*/
+#define ASI_IC_TAG		0x67 /* Insn cache tag/valid ram diag 	*/
+#define ASI_IC_STAG		0x68 /* (III) Insn cache snoop tag ram	*/
+#define ASI_IC_PRE_DECODE	0x6e /* Insn cache pre-decode ram diag	*/
+#define ASI_IC_NEXT_FIELD	0x6f /* Insn cache next-field ram diag	*/
+#define ASI_BRPRED_ARRAY	0x6f /* (III) Branch Prediction RAM diag*/
+#define ASI_BLK_AIUP		0x70 /* Primary, user, block load/store	*/
+#define ASI_BLK_AIUS		0x71 /* Secondary, user, block ld/st	*/
+#define ASI_MCU_CTRL_REG	0x72 /* (III) Memory controller regs	*/
+#define ASI_EC_DATA		0x74 /* (III) E-cache data staging reg	*/
+#define ASI_EC_CTRL		0x75 /* (III) E-cache control reg	*/
+#define ASI_EC_W		0x76 /* E-cache diag write access	*/
+#define ASI_UDB_ERROR_W		0x77 /* External UDB error regs W	*/
+#define ASI_UDB_CONTROL_W	0x77 /* External UDB control regs W	*/
+#define ASI_INTR_W		0x77 /* IRQ vector dispatch write	*/
+#define ASI_INTR_DATAN_W	0x77 /* (III) Out irq vector data reg N	*/
+#define ASI_INTR_DISPATCH_W	0x77 /* (III) Interrupt vector dispatch	*/
+#define ASI_BLK_AIUPL		0x78 /* Primary, user, little, blk ld/st*/
+#define ASI_BLK_AIUSL		0x79 /* Secondary, user, little, blk ld/st*/
+#define ASI_EC_R		0x7e /* E-cache diag read access	*/
+#define ASI_UDBH_ERROR_R	0x7f /* External UDB error regs rd hi	*/
+#define ASI_UDBL_ERROR_R	0x7f /* External UDB error regs rd low	*/
+#define ASI_UDBH_CONTROL_R	0x7f /* External UDB control regs rd hi	*/
+#define ASI_UDBL_CONTROL_R	0x7f /* External UDB control regs rd low*/
+#define ASI_INTR_R		0x7f /* IRQ vector dispatch read	*/
+#define ASI_INTR_DATAN_R	0x7f /* (III) In irq vector data reg N	*/
+#define ASI_PIC			0xb0 /* (NG4) PIC registers		*/
+#define ASI_PST8_P		0xc0 /* Primary, 8 8-bit, partial	*/
+#define ASI_PST8_S		0xc1 /* Secondary, 8 8-bit, partial	*/
+#define ASI_PST16_P		0xc2 /* Primary, 4 16-bit, partial	*/
+#define ASI_PST16_S		0xc3 /* Secondary, 4 16-bit, partial	*/
+#define ASI_PST32_P		0xc4 /* Primary, 2 32-bit, partial	*/
+#define ASI_PST32_S		0xc5 /* Secondary, 2 32-bit, partial	*/
+#define ASI_PST8_PL		0xc8 /* Primary, 8 8-bit, partial, L	*/
+#define ASI_PST8_SL		0xc9 /* Secondary, 8 8-bit, partial, L	*/
+#define ASI_PST16_PL		0xca /* Primary, 4 16-bit, partial, L	*/
+#define ASI_PST16_SL		0xcb /* Secondary, 4 16-bit, partial, L	*/
+#define ASI_PST32_PL		0xcc /* Primary, 2 32-bit, partial, L	*/
+#define ASI_PST32_SL		0xcd /* Secondary, 2 32-bit, partial, L	*/
+#define ASI_FL8_P		0xd0 /* Primary, 1 8-bit, fpu ld/st	*/
+#define ASI_FL8_S		0xd1 /* Secondary, 1 8-bit, fpu ld/st	*/
+#define ASI_FL16_P		0xd2 /* Primary, 1 16-bit, fpu ld/st	*/
+#define ASI_FL16_S		0xd3 /* Secondary, 1 16-bit, fpu ld/st	*/
+#define ASI_FL8_PL		0xd8 /* Primary, 1 8-bit, fpu ld/st, L	*/
+#define ASI_FL8_SL		0xd9 /* Secondary, 1 8-bit, fpu ld/st, L*/
+#define ASI_FL16_PL		0xda /* Primary, 1 16-bit, fpu ld/st, L	*/
+#define ASI_FL16_SL		0xdb /* Secondary, 1 16-bit, fpu ld/st,L*/
+#define ASI_BLK_COMMIT_P	0xe0 /* Primary, blk store commit	*/
+#define ASI_BLK_COMMIT_S	0xe1 /* Secondary, blk store commit	*/
+#define ASI_BLK_INIT_QUAD_LDD_P	0xe2 /* (NG) init-store, twin load,
+				      * primary, implicit
+				      */
+#define ASI_BLK_INIT_QUAD_LDD_S	0xe3 /* (NG) init-store, twin load,
+				      * secondary, implicit
+				      */
+#define ASI_BLK_P		0xf0 /* Primary, blk ld/st		*/
+#define ASI_BLK_S		0xf1 /* Secondary, blk ld/st		*/
+#define ASI_ST_BLKINIT_MRU_P	0xf2 /* (NG4) init-store, twin load,
+				      * Most-Recently-Used, primary,
+				      * implicit
+				      */
+#define ASI_ST_BLKINIT_MRU_S	0xf2 /* (NG4) init-store, twin load,
+				      * Most-Recently-Used, secondary,
+				      * implicit
+				      */
+#define ASI_BLK_PL		0xf8 /* Primary, blk ld/st, little	*/
+#define ASI_BLK_SL		0xf9 /* Secondary, blk ld/st, little	*/
+#define ASI_ST_BLKINIT_MRU_PL	0xfa /* (NG4) init-store, twin load,
+				      * Most-Recently-Used, primary,
+				      * implicit, little-endian
+				      */
+#define ASI_ST_BLKINIT_MRU_SL	0xfb /* (NG4) init-store, twin load,
+				      * Most-Recently-Used, secondary,
+				      * implicit, little-endian
+				      */
+
+#endif /* _SPARC_ASI_H */
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 10/24] target-sparc: Add UA2005 defines to asi.h
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (8 preceding siblings ...)
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 09/24] target-sparc: Import linux/arch/sparc/include/uapi/asm/asi.h Richard Henderson
@ 2016-06-28  0:38 ` Richard Henderson
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 11/24] target-sparc: Use defines from asi.h Richard Henderson
                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:38 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/asi.h | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/target-sparc/asi.h b/target-sparc/asi.h
index aace6f3..c9a1849 100644
--- a/target-sparc/asi.h
+++ b/target-sparc/asi.h
@@ -144,24 +144,36 @@
  * ASIs, "(4V)" designates SUN4V specific ASIs.  "(NG4)" designates SPARC-T4
  * and later ASIs.
  */
+#define ASI_REAL                0x14 /* Real address, cachable          */
 #define ASI_PHYS_USE_EC		0x14 /* PADDR, E-cachable		*/
+#define ASI_REAL_IO             0x15 /* Real address, non-cachable      */
 #define ASI_PHYS_BYPASS_EC_E	0x15 /* PADDR, E-bit			*/
 #define ASI_BLK_AIUP_4V		0x16 /* (4V) Prim, user, block ld/st	*/
 #define ASI_BLK_AIUS_4V		0x17 /* (4V) Sec, user, block ld/st	*/
+#define ASI_REAL_L              0x1c /* Real address, cachable, LE      */
 #define ASI_PHYS_USE_EC_L	0x1c /* PADDR, E-cachable, little endian*/
+#define ASI_REAL_IO_L           0x1d /* Real address, non-cachable, LE  */
 #define ASI_PHYS_BYPASS_EC_E_L	0x1d /* PADDR, E-bit, little endian	*/
 #define ASI_BLK_AIUP_L_4V	0x1e /* (4V) Prim, user, block, l-endian*/
 #define ASI_BLK_AIUS_L_4V	0x1f /* (4V) Sec, user, block, l-endian	*/
 #define ASI_SCRATCHPAD		0x20 /* (4V) Scratch Pad Registers	*/
 #define ASI_MMU			0x21 /* (4V) MMU Context Registers	*/
+#define ASI_TWINX_AIUP          0x22 /* twin load, primary user         */
+#define ASI_TWINX_AIUS          0x23 /* twin load, secondary user       */
 #define ASI_BLK_INIT_QUAD_LDD_AIUS 0x23 /* (NG) init-store, twin load,
 					 * secondary, user
 					 */
 #define ASI_NUCLEUS_QUAD_LDD	0x24 /* Cachable, qword load		*/
 #define ASI_QUEUE		0x25 /* (4V) Interrupt Queue Registers	*/
+#define ASI_TWINX_REAL          0x26 /* twin load, real, cachable       */
 #define ASI_QUAD_LDD_PHYS_4V	0x26 /* (4V) Physical, qword load	*/
+#define ASI_TWINX_N             0x27 /* twin load, nucleus              */
+#define ASI_TWINX_AIUP_L        0x2a /* twin load, primary user, LE     */
+#define ASI_TWINX_AIUS_L        0x2b /* twin load, secondary user, LE   */
 #define ASI_NUCLEUS_QUAD_LDD_L	0x2c /* Cachable, qword load, l-endian 	*/
+#define ASI_TWINX_REAL_L        0x2e /* twin load, real, cachable, LE   */
 #define ASI_QUAD_LDD_PHYS_L_4V	0x2e /* (4V) Phys, qword load, l-endian	*/
+#define ASI_TWINX_NL            0x2f /* twin load, nucleus, LE          */
 #define ASI_PCACHE_DATA_STATUS	0x30 /* (III) PCache data stat RAM diag	*/
 #define ASI_PCACHE_DATA		0x31 /* (III) PCache data RAM diag	*/
 #define ASI_PCACHE_TAG		0x32 /* (III) PCache tag RAM diag	*/
@@ -267,12 +279,14 @@
 #define ASI_FL16_SL		0xdb /* Secondary, 1 16-bit, fpu ld/st,L*/
 #define ASI_BLK_COMMIT_P	0xe0 /* Primary, blk store commit	*/
 #define ASI_BLK_COMMIT_S	0xe1 /* Secondary, blk store commit	*/
+#define ASI_TWINX_P             0xe2 /* twin load, primary implicit     */
 #define ASI_BLK_INIT_QUAD_LDD_P	0xe2 /* (NG) init-store, twin load,
-				      * primary, implicit
-				      */
+				      * primary, implicit */
+#define ASI_TWINX_S             0xe3 /* twin load, secondary implicit   */
 #define ASI_BLK_INIT_QUAD_LDD_S	0xe3 /* (NG) init-store, twin load,
-				      * secondary, implicit
-				      */
+				      * secondary, implicit */
+#define ASI_TWINX_PL            0xea /* twin load, primary implicit, LE */
+#define ASI_TWINX_SL            0xeb /* twin load, secondary implicit, LE */
 #define ASI_BLK_P		0xf0 /* Primary, blk ld/st		*/
 #define ASI_BLK_S		0xf1 /* Secondary, blk ld/st		*/
 #define ASI_ST_BLKINIT_MRU_P	0xf2 /* (NG4) init-store, twin load,
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 11/24] target-sparc: Use defines from asi.h
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (9 preceding siblings ...)
  2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 10/24] target-sparc: Add UA2005 defines to asi.h Richard Henderson
@ 2016-06-28  0:39 ` Richard Henderson
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 12/24] target-sparc: Directly implement easy ld/st asis Richard Henderson
                   ` (13 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/ldst_helper.c | 459 +++++++++++++++++++++++----------------------
 target-sparc/translate.c   |   6 +-
 2 files changed, 235 insertions(+), 230 deletions(-)

diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index f73cf6d..a6c4d0c 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -22,6 +22,7 @@
 #include "exec/helper-proto.h"
 #include "exec/exec-all.h"
 #include "exec/cpu_ldst.h"
+#include "asi.h"
 
 //#define DEBUG_MMU
 //#define DEBUG_MXCC
@@ -438,7 +439,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
 
     helper_check_align(env, addr, size - 1);
     switch (asi) {
-    case 2: /* SuperSparc MXCC registers and Leon3 cache control */
+    case ASI_M_MXCC: /* SuperSparc MXCC registers, or... */
+    /* case ASI_LEON_CACHEREGS:  Leon3 cache control */
         switch (addr) {
         case 0x00:          /* Leon3 Cache Control */
         case 0x08:          /* Leon3 Instruction Cache config */
@@ -497,8 +499,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
         dump_mxcc(env);
 #endif
         break;
-    case 3: /* MMU probe */
-    case 0x18: /* LEON3 MMU probe */
+    case ASI_M_FLUSH_PROBE: /* SuperSparc MMU probe */
+    case ASI_LEON_MMUFLUSH: /* LEON3 MMU probe */
         {
             int mmulev;
 
@@ -512,8 +514,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
                         addr, mmulev, ret);
         }
         break;
-    case 4: /* read MMU regs */
-    case 0x19: /* LEON3 read MMU regs */
+    case ASI_M_MMUREGS: /* SuperSparc MMU regs */
+    case ASI_LEON_MMUREGS: /* LEON3 MMU regs */
         {
             int reg = (addr >> 8) & 0x1f;
 
@@ -528,11 +530,11 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
             DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
         }
         break;
-    case 5: /* Turbosparc ITLB Diagnostic */
-    case 6: /* Turbosparc DTLB Diagnostic */
-    case 7: /* Turbosparc IOTLB Diagnostic */
+    case ASI_M_TLBDIAG: /* Turbosparc ITLB Diagnostic */
+    case ASI_M_DIAGS:   /* Turbosparc DTLB Diagnostic */
+    case ASI_M_IODIAG:  /* Turbosparc IOTLB Diagnostic */
         break;
-    case 9: /* Supervisor code access */
+    case ASI_KERNELTXT: /* Supervisor code access */
         switch (size) {
         case 1:
             ret = cpu_ldub_code(env, addr);
@@ -549,7 +551,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
             break;
         }
         break;
-    case 0xa: /* User data access */
+    case ASI_USERDATA: /* User data access */
         switch (size) {
         case 1:
             ret = cpu_ldub_user(env, addr);
@@ -566,8 +568,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
             break;
         }
         break;
-    case 0xb: /* Supervisor data access */
-    case 0x80:
+    case ASI_KERNELDATA: /* Supervisor data access */
+    case ASI_P: /* Implicit primary context data access (v9 only?) */
         switch (size) {
         case 1:
             ret = cpu_ldub_kernel(env, addr);
@@ -584,13 +586,13 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
             break;
         }
         break;
-    case 0xc: /* I-cache tag */
-    case 0xd: /* I-cache data */
-    case 0xe: /* D-cache tag */
-    case 0xf: /* D-cache data */
+    case ASI_M_TXTC_TAG:   /* SparcStation 5 I-cache tag */
+    case ASI_M_TXTC_DATA:  /* SparcStation 5 I-cache data */
+    case ASI_M_DATAC_TAG:  /* SparcStation 5 D-cache tag */
+    case ASI_M_DATAC_DATA: /* SparcStation 5 D-cache data */
         break;
-    case 0x20: /* MMU passthrough */
-    case 0x1c: /* LEON MMU passthrough */
+    case ASI_M_BYPASS:    /* MMU passthrough */
+    case ASI_LEON_BYPASS: /* LEON MMU passthrough */
         switch (size) {
         case 1:
             ret = ldub_phys(cs->as, addr);
@@ -669,7 +671,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
     case 0x4c: /* SuperSPARC MMU Breakpoint Action */
         ret = env->mmubpaction;
         break;
-    case 8: /* User code access, XXX */
+    case ASI_USERTXT: /* User code access, XXX */
     default:
         cpu_unassigned_access(cs, addr, false, false, asi, size);
         ret = 0;
@@ -704,7 +706,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
 
     helper_check_align(env, addr, size - 1);
     switch (asi) {
-    case 2: /* SuperSparc MXCC registers and Leon3 cache control */
+    case ASI_M_MXCC: /* SuperSparc MXCC registers, or... */
+    /* case ASI_LEON_CACHEREGS:  Leon3 cache control */
         switch (addr) {
         case 0x00:          /* Leon3 Cache Control */
         case 0x08:          /* Leon3 Instruction Cache config */
@@ -838,8 +841,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
         dump_mxcc(env);
 #endif
         break;
-    case 3: /* MMU flush */
-    case 0x18: /* LEON3 MMU flush */
+    case ASI_M_FLUSH_PROBE: /* SuperSparc MMU flush */
+    case ASI_LEON_MMUFLUSH: /* LEON3 MMU flush */
         {
             int mmulev;
 
@@ -863,8 +866,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
 #endif
         }
         break;
-    case 4: /* write MMU regs */
-    case 0x19: /* LEON3 write MMU regs */
+    case ASI_M_MMUREGS: /* write MMU regs */
+    case ASI_LEON_MMUREGS: /* LEON3 write MMU regs */
         {
             int reg = (addr >> 8) & 0x1f;
             uint32_t oldreg;
@@ -918,11 +921,11 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
 #endif
         }
         break;
-    case 5: /* Turbosparc ITLB Diagnostic */
-    case 6: /* Turbosparc DTLB Diagnostic */
-    case 7: /* Turbosparc IOTLB Diagnostic */
+    case ASI_M_TLBDIAG: /* Turbosparc ITLB Diagnostic */
+    case ASI_M_DIAGS:   /* Turbosparc DTLB Diagnostic */
+    case ASI_M_IODIAG:  /* Turbosparc IOTLB Diagnostic */
         break;
-    case 0xa: /* User data access */
+    case ASI_USERDATA: /* User data access */
         switch (size) {
         case 1:
             cpu_stb_user(env, addr, val);
@@ -939,8 +942,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
             break;
         }
         break;
-    case 0xb: /* Supervisor data access */
-    case 0x80:
+    case ASI_KERNELDATA: /* Supervisor data access */
+    case ASI_P:
         switch (size) {
         case 1:
             cpu_stb_kernel(env, addr, val);
@@ -957,17 +960,17 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
             break;
         }
         break;
-    case 0xc: /* I-cache tag */
-    case 0xd: /* I-cache data */
-    case 0xe: /* D-cache tag */
-    case 0xf: /* D-cache data */
-    case 0x10: /* I/D-cache flush page */
-    case 0x11: /* I/D-cache flush segment */
-    case 0x12: /* I/D-cache flush region */
-    case 0x13: /* I/D-cache flush context */
-    case 0x14: /* I/D-cache flush user */
+    case ASI_M_TXTC_TAG:   /* I-cache tag */
+    case ASI_M_TXTC_DATA:  /* I-cache data */
+    case ASI_M_DATAC_TAG:  /* D-cache tag */
+    case ASI_M_DATAC_DATA: /* D-cache data */
+    case ASI_M_FLUSH_PAGE:   /* I/D-cache flush page */
+    case ASI_M_FLUSH_SEG:    /* I/D-cache flush segment */
+    case ASI_M_FLUSH_REGION: /* I/D-cache flush region */
+    case ASI_M_FLUSH_CTX:    /* I/D-cache flush context */
+    case ASI_M_FLUSH_USER:   /* I/D-cache flush user */
         break;
-    case 0x17: /* Block copy, sta access */
+    case ASI_M_BCOPY: /* Block copy, sta access */
         {
             /* val = src
                addr = dst
@@ -981,7 +984,7 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
             }
         }
         break;
-    case 0x1f: /* Block fill, stda access */
+    case ASI_M_BFILL: /* Block fill, stda access */
         {
             /* addr = dst
                fill 32 bytes with val */
@@ -993,8 +996,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
             }
         }
         break;
-    case 0x20: /* MMU passthrough */
-    case 0x1c: /* LEON MMU passthrough */
+    case ASI_M_BYPASS:    /* MMU passthrough */
+    case ASI_LEON_BYPASS: /* LEON MMU passthrough */
         {
             switch (size) {
             case 1:
@@ -1078,8 +1081,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
     case 0x4c: /* SuperSPARC MMU Breakpoint Action */
         env->mmubpaction = val & 0x1fff;
         break;
-    case 8: /* User code access, XXX */
-    case 9: /* Supervisor code access, XXX */
+    case ASI_USERTXT: /* User code access, XXX */
+    case ASI_KERNELTXT: /* Supervisor code access, XXX */
     default:
         cpu_unassigned_access(CPU(sparc_env_get_cpu(env)),
                               addr, true, false, asi, size);
@@ -1110,8 +1113,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
     addr = asi_address_mask(env, asi, addr);
 
     switch (asi) {
-    case 0x82: /* Primary no-fault */
-    case 0x8a: /* Primary no-fault LE */
+    case ASI_PNF:  /* Primary no-fault */
+    case ASI_PNFL: /* Primary no-fault LE */
         if (page_check_range(addr, size, PAGE_READ) == -1) {
 #ifdef DEBUG_ASI
             dump_asi("read ", last_addr, asi, size, ret);
@@ -1119,8 +1122,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
             return 0;
         }
         /* Fall through */
-    case 0x80: /* Primary */
-    case 0x88: /* Primary LE */
+    case ASI_P: /* Primary */
+    case ASI_PL: /* Primary LE */
         {
             switch (size) {
             case 1:
@@ -1139,8 +1142,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
             }
         }
         break;
-    case 0x83: /* Secondary no-fault */
-    case 0x8b: /* Secondary no-fault LE */
+    case ASI_SNF:  /* Secondary no-fault */
+    case ASI_SNFL: /* Secondary no-fault LE */
         if (page_check_range(addr, size, PAGE_READ) == -1) {
 #ifdef DEBUG_ASI
             dump_asi("read ", last_addr, asi, size, ret);
@@ -1148,8 +1151,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
             return 0;
         }
         /* Fall through */
-    case 0x81: /* Secondary */
-    case 0x89: /* Secondary LE */
+    case ASI_S:  /* Secondary */
+    case ASI_SL: /* Secondary LE */
         /* XXX */
         break;
     default:
@@ -1158,10 +1161,10 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
 
     /* Convert from little endian */
     switch (asi) {
-    case 0x88: /* Primary LE */
-    case 0x89: /* Secondary LE */
-    case 0x8a: /* Primary no-fault LE */
-    case 0x8b: /* Secondary no-fault LE */
+    case ASI_PL:   /* Primary LE */
+    case ASI_SL:   /* Secondary LE */
+    case ASI_PNFL: /* Primary no-fault LE */
+    case ASI_SNFL: /* Secondary no-fault LE */
         switch (size) {
         case 2:
             ret = bswap16(ret);
@@ -1216,8 +1219,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
 
     /* Convert to little endian */
     switch (asi) {
-    case 0x88: /* Primary LE */
-    case 0x89: /* Secondary LE */
+    case ASI_PL: /* Primary LE */
+    case ASI_SL: /* Secondary LE */
         switch (size) {
         case 2:
             val = bswap16(val);
@@ -1236,8 +1239,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
     }
 
     switch (asi) {
-    case 0x80: /* Primary */
-    case 0x88: /* Primary LE */
+    case ASI_P:  /* Primary */
+    case ASI_PL: /* Primary LE */
         {
             switch (size) {
             case 1:
@@ -1256,15 +1259,15 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
             }
         }
         break;
-    case 0x81: /* Secondary */
-    case 0x89: /* Secondary LE */
+    case ASI_S:  /* Secondary */
+    case ASI_SL: /* Secondary LE */
         /* XXX */
         return;
 
-    case 0x82: /* Primary no-fault, RO */
-    case 0x83: /* Secondary no-fault, RO */
-    case 0x8a: /* Primary no-fault LE, RO */
-    case 0x8b: /* Secondary no-fault LE, RO */
+    case ASI_PNF:  /* Primary no-fault, RO */
+    case ASI_SNF:  /* Secondary no-fault, RO */
+    case ASI_PNFL: /* Primary no-fault LE, RO */
+    case ASI_SNFL: /* Secondary no-fault LE, RO */
     default:
         helper_raise_exception(env, TT_DATA_ACCESS);
         return;
@@ -1318,16 +1321,16 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
     }
 
     switch (asi) {
-    case 0x10: /* As if user primary */
-    case 0x11: /* As if user secondary */
-    case 0x18: /* As if user primary LE */
-    case 0x19: /* As if user secondary LE */
-    case 0x80: /* Primary */
-    case 0x81: /* Secondary */
-    case 0x88: /* Primary LE */
-    case 0x89: /* Secondary LE */
-    case 0xe2: /* UA2007 Primary block init */
-    case 0xe3: /* UA2007 Secondary block init */
+    case ASI_AIUP:  /* As if user primary */
+    case ASI_AIUS:  /* As if user secondary */
+    case ASI_AIUPL: /* As if user primary LE */
+    case ASI_AIUSL: /* As if user secondary LE */
+    case ASI_P:  /* Primary */
+    case ASI_S:  /* Secondary */
+    case ASI_PL: /* Primary LE */
+    case ASI_SL: /* Secondary LE */
+    case ASI_BLK_INIT_QUAD_LDD_P: /* UA2007 Primary block init */
+    case ASI_BLK_INIT_QUAD_LDD_S: /* UA2007 Secondary block init */
         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
             if (cpu_hypervisor_mode(env)) {
                 switch (size) {
@@ -1418,10 +1421,10 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
             }
         }
         break;
-    case 0x14: /* Bypass */
-    case 0x15: /* Bypass, non-cacheable */
-    case 0x1c: /* Bypass LE */
-    case 0x1d: /* Bypass, non-cacheable LE */
+    case ASI_REAL:        /* Bypass */
+    case ASI_REAL_IO:   /* Bypass, non-cacheable */
+    case ASI_REAL_L:      /* Bypass LE */
+    case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
         {
             switch (size) {
             case 1:
@@ -1440,13 +1443,13 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
             }
             break;
         }
-    case 0x24: /* Nucleus quad LDD 128 bit atomic */
-    case 0x2c: /* Nucleus quad LDD 128 bit atomic LE
-                  Only ldda allowed */
+    case ASI_NUCLEUS_QUAD_LDD:   /* Nucleus quad LDD 128 bit atomic */
+    case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */
+        /* Only ldda allowed */
         helper_raise_exception(env, TT_ILL_INSN);
         return 0;
-    case 0x04: /* Nucleus */
-    case 0x0c: /* Nucleus Little Endian (LE) */
+    case ASI_N:  /* Nucleus */
+    case ASI_NL: /* Nucleus Little Endian (LE) */
         {
             switch (size) {
             case 1:
@@ -1465,13 +1468,13 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
             }
             break;
         }
-    case 0x4a: /* UPA config */
+    case ASI_UPA_CONFIG: /* UPA config */
         /* XXX */
         break;
-    case 0x45: /* LSU */
+    case ASI_LSU_CONTROL: /* LSU */
         ret = env->lsu;
         break;
-    case 0x50: /* I-MMU regs */
+    case ASI_IMMU: /* I-MMU regs */
         {
             int reg = (addr >> 3) & 0xf;
 
@@ -1484,7 +1487,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
 
             break;
         }
-    case 0x51: /* I-MMU 8k TSB pointer */
+    case ASI_IMMU_TSB_8KB_PTR: /* I-MMU 8k TSB pointer */
         {
             /* env->immuregs[5] holds I-MMU TSB register value
                env->immuregs[6] holds I-MMU Tag Access register value */
@@ -1492,7 +1495,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
                                          8*1024);
             break;
         }
-    case 0x52: /* I-MMU 64k TSB pointer */
+    case ASI_IMMU_TSB_64KB_PTR: /* I-MMU 64k TSB pointer */
         {
             /* env->immuregs[5] holds I-MMU TSB register value
                env->immuregs[6] holds I-MMU Tag Access register value */
@@ -1500,21 +1503,21 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
                                          64*1024);
             break;
         }
-    case 0x55: /* I-MMU data access */
+    case ASI_ITLB_DATA_ACCESS: /* I-MMU data access */
         {
             int reg = (addr >> 3) & 0x3f;
 
             ret = env->itlb[reg].tte;
             break;
         }
-    case 0x56: /* I-MMU tag read */
+    case ASI_ITLB_TAG_READ: /* I-MMU tag read */
         {
             int reg = (addr >> 3) & 0x3f;
 
             ret = env->itlb[reg].tag;
             break;
         }
-    case 0x58: /* D-MMU regs */
+    case ASI_DMMU: /* D-MMU regs */
         {
             int reg = (addr >> 3) & 0xf;
 
@@ -1526,7 +1529,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
             }
             break;
         }
-    case 0x59: /* D-MMU 8k TSB pointer */
+    case ASI_DMMU_TSB_8KB_PTR: /* D-MMU 8k TSB pointer */
         {
             /* env->dmmuregs[5] holds D-MMU TSB register value
                env->dmmuregs[6] holds D-MMU Tag Access register value */
@@ -1534,7 +1537,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
                                          8*1024);
             break;
         }
-    case 0x5a: /* D-MMU 64k TSB pointer */
+    case ASI_DMMU_TSB_64KB_PTR: /* D-MMU 64k TSB pointer */
         {
             /* env->dmmuregs[5] holds D-MMU TSB register value
                env->dmmuregs[6] holds D-MMU Tag Access register value */
@@ -1542,26 +1545,26 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
                                          64*1024);
             break;
         }
-    case 0x5d: /* D-MMU data access */
+    case ASI_DTLB_DATA_ACCESS: /* D-MMU data access */
         {
             int reg = (addr >> 3) & 0x3f;
 
             ret = env->dtlb[reg].tte;
             break;
         }
-    case 0x5e: /* D-MMU tag read */
+    case ASI_DTLB_TAG_READ: /* D-MMU tag read */
         {
             int reg = (addr >> 3) & 0x3f;
 
             ret = env->dtlb[reg].tag;
             break;
         }
-    case 0x48: /* Interrupt dispatch, RO */
+    case ASI_INTR_DISPATCH_STAT: /* Interrupt dispatch, RO */
         break;
-    case 0x49: /* Interrupt data receive */
+    case ASI_INTR_RECEIVE: /* Interrupt data receive */
         ret = env->ivec_status;
         break;
-    case 0x7f: /* Incoming interrupt vector, RO */
+    case ASI_INTR_R: /* Incoming interrupt vector, RO */
         {
             int reg = (addr >> 4) & 0x3;
             if (reg < 3) {
@@ -1569,25 +1572,25 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
             }
             break;
         }
-    case 0x46: /* D-cache data */
-    case 0x47: /* D-cache tag access */
-    case 0x4b: /* E-cache error enable */
-    case 0x4c: /* E-cache asynchronous fault status */
-    case 0x4d: /* E-cache asynchronous fault address */
-    case 0x4e: /* E-cache tag data */
-    case 0x66: /* I-cache instruction access */
-    case 0x67: /* I-cache tag access */
-    case 0x6e: /* I-cache predecode */
-    case 0x6f: /* I-cache LRU etc. */
-    case 0x76: /* E-cache tag */
-    case 0x7e: /* E-cache tag */
-        break;
-    case 0x5b: /* D-MMU data pointer */
-    case 0x54: /* I-MMU data in, WO */
-    case 0x57: /* I-MMU demap, WO */
-    case 0x5c: /* D-MMU data in, WO */
-    case 0x5f: /* D-MMU demap, WO */
-    case 0x77: /* Interrupt vector, WO */
+    case ASI_DCACHE_DATA:     /* D-cache data */
+    case ASI_DCACHE_TAG:      /* D-cache tag access */
+    case ASI_ESTATE_ERROR_EN: /* E-cache error enable */
+    case ASI_AFSR:            /* E-cache asynchronous fault status */
+    case ASI_AFAR:            /* E-cache asynchronous fault address */
+    case ASI_EC_TAG_DATA:     /* E-cache tag data */
+    case ASI_IC_INSTR:        /* I-cache instruction access */
+    case ASI_IC_TAG:          /* I-cache tag access */
+    case ASI_IC_PRE_DECODE:   /* I-cache predecode */
+    case ASI_IC_NEXT_FIELD:   /* I-cache LRU etc. */
+    case ASI_EC_W:            /* E-cache tag */
+    case ASI_EC_R:            /* E-cache tag */
+        break;
+    case ASI_DMMU_TSB_DIRECT_PTR: /* D-MMU data pointer */
+    case ASI_ITLB_DATA_IN:        /* I-MMU data in, WO */
+    case ASI_IMMU_DEMAP:          /* I-MMU demap, WO */
+    case ASI_DTLB_DATA_IN:        /* D-MMU data in, WO */
+    case ASI_DMMU_DEMAP:          /* D-MMU demap, WO */
+    case ASI_INTR_W:              /* Interrupt vector, WO */
     default:
         cpu_unassigned_access(cs, addr, false, false, 1, size);
         ret = 0;
@@ -1596,13 +1599,13 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
 
     /* Convert from little endian */
     switch (asi) {
-    case 0x0c: /* Nucleus Little Endian (LE) */
-    case 0x18: /* As if user primary LE */
-    case 0x19: /* As if user secondary LE */
-    case 0x1c: /* Bypass LE */
-    case 0x1d: /* Bypass, non-cacheable LE */
-    case 0x88: /* Primary LE */
-    case 0x89: /* Secondary LE */
+    case ASI_NL: /* Nucleus Little Endian (LE) */
+    case ASI_AIUPL: /* As if user primary LE */
+    case ASI_AIUSL: /* As if user secondary LE */
+    case ASI_REAL_L:      /* Bypass LE */
+    case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
+    case ASI_PL: /* Primary LE */
+    case ASI_SL: /* Secondary LE */
         switch(size) {
         case 2:
             ret = bswap16(ret);
@@ -1666,13 +1669,13 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
 
     /* Convert to little endian */
     switch (asi) {
-    case 0x0c: /* Nucleus Little Endian (LE) */
-    case 0x18: /* As if user primary LE */
-    case 0x19: /* As if user secondary LE */
-    case 0x1c: /* Bypass LE */
-    case 0x1d: /* Bypass, non-cacheable LE */
-    case 0x88: /* Primary LE */
-    case 0x89: /* Secondary LE */
+    case ASI_NL: /* Nucleus Little Endian (LE) */
+    case ASI_AIUPL: /* As if user primary LE */
+    case ASI_AIUSL: /* As if user secondary LE */
+    case ASI_REAL_L: /* Bypass LE */
+    case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
+    case ASI_PL: /* Primary LE */
+    case ASI_SL: /* Secondary LE */
         switch (size) {
         case 2:
             val = bswap16(val);
@@ -1691,16 +1694,16 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
     }
 
     switch (asi) {
-    case 0x10: /* As if user primary */
-    case 0x11: /* As if user secondary */
-    case 0x18: /* As if user primary LE */
-    case 0x19: /* As if user secondary LE */
-    case 0x80: /* Primary */
-    case 0x81: /* Secondary */
-    case 0x88: /* Primary LE */
-    case 0x89: /* Secondary LE */
-    case 0xe2: /* UA2007 Primary block init */
-    case 0xe3: /* UA2007 Secondary block init */
+    case ASI_AIUP:  /* As if user primary */
+    case ASI_AIUS:  /* As if user secondary */
+    case ASI_AIUPL: /* As if user primary LE */
+    case ASI_AIUSL: /* As if user secondary LE */
+    case ASI_P:  /* Primary */
+    case ASI_S:  /* Secondary */
+    case ASI_PL: /* Primary LE */
+    case ASI_SL: /* Secondary LE */
+    case ASI_BLK_INIT_QUAD_LDD_P: /* UA2007 Primary block init */
+    case ASI_BLK_INIT_QUAD_LDD_S: /* UA2007 Secondary block init */
         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
             if (cpu_hypervisor_mode(env)) {
                 switch (size) {
@@ -1791,10 +1794,10 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
             }
         }
         break;
-    case 0x14: /* Bypass */
-    case 0x15: /* Bypass, non-cacheable */
-    case 0x1c: /* Bypass LE */
-    case 0x1d: /* Bypass, non-cacheable LE */
+    case ASI_REAL:      /* Bypass */
+    case ASI_REAL_IO:   /* Bypass, non-cacheable */
+    case ASI_REAL_L:    /* Bypass LE */
+    case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
         {
             switch (size) {
             case 1:
@@ -1813,13 +1816,13 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
             }
         }
         return;
-    case 0x24: /* Nucleus quad LDD 128 bit atomic */
-    case 0x2c: /* Nucleus quad LDD 128 bit atomic LE
-                  Only ldda allowed */
+    case ASI_NUCLEUS_QUAD_LDD:   /* Nucleus quad LDD 128 bit atomic */
+    case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */
+        /* Only ldda allowed */
         helper_raise_exception(env, TT_ILL_INSN);
         return;
-    case 0x04: /* Nucleus */
-    case 0x0c: /* Nucleus Little Endian (LE) */
+    case ASI_N:  /* Nucleus */
+    case ASI_NL: /* Nucleus Little Endian (LE) */
         {
             switch (size) {
             case 1:
@@ -1839,10 +1842,10 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
             break;
         }
 
-    case 0x4a: /* UPA config */
+    case ASI_UPA_CONFIG: /* UPA config */
         /* XXX */
         return;
-    case 0x45: /* LSU */
+    case ASI_LSU_CONTROL: /* LSU */
         {
             uint64_t oldreg;
 
@@ -1860,7 +1863,7 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
             }
             return;
         }
-    case 0x50: /* I-MMU regs */
+    case ASI_IMMU: /* I-MMU regs */
         {
             int reg = (addr >> 3) & 0xf;
             uint64_t oldreg;
@@ -1904,10 +1907,10 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
 #endif
             return;
         }
-    case 0x54: /* I-MMU data in */
+    case ASI_ITLB_DATA_IN: /* I-MMU data in */
         replace_tlb_1bit_lru(env->itlb, env->immu.tag_access, val, "immu", env);
         return;
-    case 0x55: /* I-MMU data access */
+    case ASI_ITLB_DATA_ACCESS: /* I-MMU data access */
         {
             /* TODO: auto demap */
 
@@ -1921,10 +1924,10 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
 #endif
             return;
         }
-    case 0x57: /* I-MMU demap */
+    case ASI_IMMU_DEMAP: /* I-MMU demap */
         demap_tlb(env->itlb, addr, "immu", env);
         return;
-    case 0x58: /* D-MMU regs */
+    case ASI_DMMU: /* D-MMU regs */
         {
             int reg = (addr >> 3) & 0xf;
             uint64_t oldreg;
@@ -1977,10 +1980,10 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
 #endif
             return;
         }
-    case 0x5c: /* D-MMU data in */
+    case ASI_DTLB_DATA_IN: /* D-MMU data in */
         replace_tlb_1bit_lru(env->dtlb, env->dmmu.tag_access, val, "dmmu", env);
         return;
-    case 0x5d: /* D-MMU data access */
+    case ASI_DTLB_DATA_ACCESS: /* D-MMU data access */
         {
             unsigned int i = (addr >> 3) & 0x3f;
 
@@ -1992,38 +1995,38 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
 #endif
             return;
         }
-    case 0x5f: /* D-MMU demap */
+    case ASI_DMMU_DEMAP: /* D-MMU demap */
         demap_tlb(env->dtlb, addr, "dmmu", env);
         return;
-    case 0x49: /* Interrupt data receive */
+    case ASI_INTR_RECEIVE: /* Interrupt data receive */
         env->ivec_status = val & 0x20;
         return;
-    case 0x46: /* D-cache data */
-    case 0x47: /* D-cache tag access */
-    case 0x4b: /* E-cache error enable */
-    case 0x4c: /* E-cache asynchronous fault status */
-    case 0x4d: /* E-cache asynchronous fault address */
-    case 0x4e: /* E-cache tag data */
-    case 0x66: /* I-cache instruction access */
-    case 0x67: /* I-cache tag access */
-    case 0x6e: /* I-cache predecode */
-    case 0x6f: /* I-cache LRU etc. */
-    case 0x76: /* E-cache tag */
-    case 0x7e: /* E-cache tag */
+    case ASI_DCACHE_DATA: /* D-cache data */
+    case ASI_DCACHE_TAG: /* D-cache tag access */
+    case ASI_ESTATE_ERROR_EN: /* E-cache error enable */
+    case ASI_AFSR: /* E-cache asynchronous fault status */
+    case ASI_AFAR: /* E-cache asynchronous fault address */
+    case ASI_EC_TAG_DATA: /* E-cache tag data */
+    case ASI_IC_INSTR: /* I-cache instruction access */
+    case ASI_IC_TAG: /* I-cache tag access */
+    case ASI_IC_PRE_DECODE: /* I-cache predecode */
+    case ASI_IC_NEXT_FIELD: /* I-cache LRU etc. */
+    case ASI_EC_W: /* E-cache tag */
+    case ASI_EC_R: /* E-cache tag */
         return;
-    case 0x51: /* I-MMU 8k TSB pointer, RO */
-    case 0x52: /* I-MMU 64k TSB pointer, RO */
-    case 0x56: /* I-MMU tag read, RO */
-    case 0x59: /* D-MMU 8k TSB pointer, RO */
-    case 0x5a: /* D-MMU 64k TSB pointer, RO */
-    case 0x5b: /* D-MMU data pointer, RO */
-    case 0x5e: /* D-MMU tag read, RO */
-    case 0x48: /* Interrupt dispatch, RO */
-    case 0x7f: /* Incoming interrupt vector, RO */
-    case 0x82: /* Primary no-fault, RO */
-    case 0x83: /* Secondary no-fault, RO */
-    case 0x8a: /* Primary no-fault LE, RO */
-    case 0x8b: /* Secondary no-fault LE, RO */
+    case ASI_IMMU_TSB_8KB_PTR: /* I-MMU 8k TSB pointer, RO */
+    case ASI_IMMU_TSB_64KB_PTR: /* I-MMU 64k TSB pointer, RO */
+    case ASI_ITLB_TAG_READ: /* I-MMU tag read, RO */
+    case ASI_DMMU_TSB_8KB_PTR: /* D-MMU 8k TSB pointer, RO */
+    case ASI_DMMU_TSB_64KB_PTR: /* D-MMU 64k TSB pointer, RO */
+    case ASI_DMMU_TSB_DIRECT_PTR: /* D-MMU data pointer, RO */
+    case ASI_DTLB_TAG_READ: /* D-MMU tag read, RO */
+    case ASI_INTR_DISPATCH_STAT: /* Interrupt dispatch, RO */
+    case ASI_INTR_R: /* Incoming interrupt vector, RO */
+    case ASI_PNF: /* Primary no-fault, RO */
+    case ASI_SNF: /* Secondary no-fault, RO */
+    case ASI_PNFL: /* Primary no-fault LE, RO */
+    case ASI_SNFL: /* Secondary no-fault LE, RO */
     default:
         cpu_unassigned_access(cs, addr, true, false, 1, size);
         return;
@@ -2044,25 +2047,25 @@ void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi, int rd)
 
     switch (asi) {
 #if !defined(CONFIG_USER_ONLY)
-    case 0x24: /* Nucleus quad LDD 128 bit atomic */
-    case 0x2c: /* Nucleus quad LDD 128 bit atomic LE */
+    case ASI_NUCLEUS_QUAD_LDD: /* Nucleus quad LDD 128 bit atomic */
+    case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */
         helper_check_align(env, addr, 0xf);
         if (rd == 0) {
             env->gregs[1] = cpu_ldq_nucleus(env, addr + 8);
-            if (asi == 0x2c) {
+            if (asi == ASI_NUCLEUS_QUAD_LDD_L) {
                 bswap64s(&env->gregs[1]);
             }
         } else if (rd < 8) {
             env->gregs[rd] = cpu_ldq_nucleus(env, addr);
             env->gregs[rd + 1] = cpu_ldq_nucleus(env, addr + 8);
-            if (asi == 0x2c) {
+            if (asi == ASI_NUCLEUS_QUAD_LDD_L) {
                 bswap64s(&env->gregs[rd]);
                 bswap64s(&env->gregs[rd + 1]);
             }
         } else {
             env->regwptr[rd - 8] = cpu_ldq_nucleus(env, addr);
             env->regwptr[rd + 1 - 8] = cpu_ldq_nucleus(env, addr + 8);
-            if (asi == 0x2c) {
+            if (asi == ASI_NUCLEUS_QUAD_LDD_L) {
                 bswap64s(&env->regwptr[rd - 8]);
                 bswap64s(&env->regwptr[rd + 1 - 8]);
             }
@@ -2094,10 +2097,10 @@ void helper_ldf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
     addr = asi_address_mask(env, asi, addr);
 
     switch (asi) {
-    case 0xf0: /* UA2007/JPS1 Block load primary */
-    case 0xf1: /* UA2007/JPS1 Block load secondary */
-    case 0xf8: /* UA2007/JPS1 Block load primary LE */
-    case 0xf9: /* UA2007/JPS1 Block load secondary LE */
+    case ASI_BLK_P:  /* UA2007/JPS1 Block load primary */
+    case ASI_BLK_S:  /* UA2007/JPS1 Block load secondary */
+    case ASI_BLK_PL: /* UA2007/JPS1 Block load primary LE */
+    case ASI_BLK_SL: /* UA2007/JPS1 Block load secondary LE */
         if (rd & 7) {
             helper_raise_exception(env, TT_ILL_INSN);
             return;
@@ -2108,14 +2111,14 @@ void helper_ldf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
         }
         return;
 
-    case 0x16: /* UA2007 Block load primary, user privilege */
-    case 0x17: /* UA2007 Block load secondary, user privilege */
-    case 0x1e: /* UA2007 Block load primary LE, user privilege */
-    case 0x1f: /* UA2007 Block load secondary LE, user privilege */
-    case 0x70: /* JPS1 Block load primary, user privilege */
-    case 0x71: /* JPS1 Block load secondary, user privilege */
-    case 0x78: /* JPS1 Block load primary LE, user privilege */
-    case 0x79: /* JPS1 Block load secondary LE, user privilege */
+    case ASI_BLK_AIUP_4V:   /* UA2007 Block load primary, user privilege */
+    case ASI_BLK_AIUS_4V:   /* UA2007 Block load secondary, user privilege */
+    case ASI_BLK_AIUP_L_4V: /* UA2007 Block load primary LE, user privilege */
+    case ASI_BLK_AIUS_L_4V: /* UA2007 Block load secondary LE, user privilege */
+    case ASI_BLK_AIUP:  /* JPS1 Block load primary, user privilege */
+    case ASI_BLK_AIUS:  /* JPS1 Block load secondary, user privilege */
+    case ASI_BLK_AIUPL: /* JPS1 Block load primary LE, user privilege */
+    case ASI_BLK_AIUSL: /* JPS1 Block load secondary LE, user privilege */
         if (rd & 7) {
             helper_raise_exception(env, TT_ILL_INSN);
             return;
@@ -2159,12 +2162,12 @@ void helper_stf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
     addr = asi_address_mask(env, asi, addr);
 
     switch (asi) {
-    case 0xe0: /* UA2007/JPS1 Block commit store primary (cache flush) */
-    case 0xe1: /* UA2007/JPS1 Block commit store secondary (cache flush) */
-    case 0xf0: /* UA2007/JPS1 Block store primary */
-    case 0xf1: /* UA2007/JPS1 Block store secondary */
-    case 0xf8: /* UA2007/JPS1 Block store primary LE */
-    case 0xf9: /* UA2007/JPS1 Block store secondary LE */
+    case ASI_BLK_COMMIT_P: /* UA2007/JPS1 Block store primary (cache flush) */
+    case ASI_BLK_COMMIT_S: /* UA2007/JPS1 Block store secondary (cache flush) */
+    case ASI_BLK_P: /* UA2007/JPS1 Block store primary */
+    case ASI_BLK_S: /* UA2007/JPS1 Block store secondary */
+    case ASI_BLK_PL: /* UA2007/JPS1 Block store primary LE */
+    case ASI_BLK_SL: /* UA2007/JPS1 Block store secondary LE */
         if (rd & 7) {
             helper_raise_exception(env, TT_ILL_INSN);
             return;
@@ -2175,14 +2178,14 @@ void helper_stf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
         }
 
         return;
-    case 0x16: /* UA2007 Block load primary, user privilege */
-    case 0x17: /* UA2007 Block load secondary, user privilege */
-    case 0x1e: /* UA2007 Block load primary LE, user privilege */
-    case 0x1f: /* UA2007 Block load secondary LE, user privilege */
-    case 0x70: /* JPS1 Block store primary, user privilege */
-    case 0x71: /* JPS1 Block store secondary, user privilege */
-    case 0x78: /* JPS1 Block load primary LE, user privilege */
-    case 0x79: /* JPS1 Block load secondary LE, user privilege */
+    case ASI_BLK_AIUP_4V: /* UA2007 Block load primary, user privilege */
+    case ASI_BLK_AIUS_4V: /* UA2007 Block load secondary, user privilege */
+    case ASI_BLK_AIUP_L_4V: /* UA2007 Block load primary LE, user privilege */
+    case ASI_BLK_AIUS_L_4V: /* UA2007 Block load secondary LE, user privilege */
+    case ASI_BLK_AIUP: /* JPS1 Block store primary, user privilege */
+    case ASI_BLK_AIUS: /* JPS1 Block store secondary, user privilege */
+    case ASI_BLK_AIUPL: /* JPS1 Block load primary LE, user privilege */
+    case ASI_BLK_AIUSL: /* JPS1 Block load secondary LE, user privilege */
         if (rd & 7) {
             helper_raise_exception(env, TT_ILL_INSN);
             return;
@@ -2193,16 +2196,16 @@ void helper_stf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
         }
 
         return;
-    case 0xd2: /* 16-bit floating point load primary */
-    case 0xd3: /* 16-bit floating point load secondary */
-    case 0xda: /* 16-bit floating point load primary, LE */
-    case 0xdb: /* 16-bit floating point load secondary, LE */
+    case ASI_FL16_P: /* 16-bit floating point load primary */
+    case ASI_FL16_S: /* 16-bit floating point load secondary */
+    case ASI_FL16_PL: /* 16-bit floating point load primary, LE */
+    case ASI_FL16_SL: /* 16-bit floating point load secondary, LE */
         helper_check_align(env, addr, 1);
         /* Fall through */
-    case 0xd0: /* 8-bit floating point load primary */
-    case 0xd1: /* 8-bit floating point load secondary */
-    case 0xd8: /* 8-bit floating point load primary, LE */
-    case 0xd9: /* 8-bit floating point load secondary, LE */
+    case ASI_FL8_P: /* 8-bit floating point load primary */
+    case ASI_FL8_S: /* 8-bit floating point load secondary */
+    case ASI_FL8_PL: /* 8-bit floating point load primary, LE */
+    case ASI_FL8_SL: /* 8-bit floating point load secondary, LE */
         val = env->fpr[rd / 2].l.lower;
         helper_st_asi(env, addr, val, asi & 0x8d, ((asi & 2) >> 1) + 1);
         return;
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 886e132..8865864 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -31,6 +31,7 @@
 
 #include "trace-tcg.h"
 #include "exec/log.h"
+#include "asi.h"
 
 
 #define DEBUG_DISAS
@@ -1999,8 +2000,9 @@ static DisasASI get_asi(DisasContext *dc, int insn)
     } else if (supervisor(dc)
                /* Note that LEON accepts ASI_USERDATA in user mode, for
                   use with CASA.  Also note that previous versions of
-                  QEMU allowed ASI_P for LEON, which is incorrect.  */
-               || (asi == 0xa
+                  QEMU allowed (and old versions of gcc emitted) ASI_P
+                  for LEON, which is incorrect.  */
+               || (asi == ASI_USERDATA
                    && (dc->def->features & CPU_FEATURE_CASA))) {
     } else {
         gen_exception(dc, TT_PRIV_INSN);
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 12/24] target-sparc: Directly implement easy ld/st asis
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (10 preceding siblings ...)
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 11/24] target-sparc: Use defines from asi.h Richard Henderson
@ 2016-06-28  0:39 ` Richard Henderson
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 13/24] target-sparc: Use QT0 to return results from ldda Richard Henderson
                   ` (12 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/translate.c | 104 ++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 90 insertions(+), 14 deletions(-)

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 8865864..55364ad 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1980,17 +1980,21 @@ static inline void gen_ne_fop_QD(DisasContext *dc, int rd, int rs,
 typedef enum {
     GET_ASI_HELPER,
     GET_ASI_EXCP,
+    GET_ASI_DIRECT,
 } ASIType;
 
 typedef struct {
     ASIType type;
     int asi;
+    int mem_idx;
+    TCGMemOp memop;
 } DisasASI;
 
-static DisasASI get_asi(DisasContext *dc, int insn)
+static DisasASI get_asi(DisasContext *dc, int insn, TCGMemOp memop)
 {
     int asi = GET_FIELD(insn, 19, 26);
     ASIType type = GET_ASI_HELPER;
+    int mem_idx = dc->mem_idx;
 
 #ifndef TARGET_SPARC64
     /* Before v9, all asis are immediate and privileged.  */
@@ -2004,6 +2008,16 @@ static DisasASI get_asi(DisasContext *dc, int insn)
                   for LEON, which is incorrect.  */
                || (asi == ASI_USERDATA
                    && (dc->def->features & CPU_FEATURE_CASA))) {
+        switch (asi) {
+        case ASI_USERDATA:   /* User data access */
+            mem_idx = MMU_USER_IDX;
+            type = GET_ASI_DIRECT;
+            break;
+        case ASI_KERNELDATA: /* Supervisor data access */
+            mem_idx = MMU_KERNEL_IDX;
+            type = GET_ASI_DIRECT;
+            break;
+        }
     } else {
         gen_exception(dc, TT_PRIV_INSN);
         type = GET_ASI_EXCP;
@@ -2012,19 +2026,77 @@ static DisasASI get_asi(DisasContext *dc, int insn)
     if (IS_IMM) {
         asi = dc->asi;
     }
+    /* With v9, all asis below 0x80 are privileged.  */
+    /* ??? We ought to check cpu_has_hypervisor, but we didn't copy
+       down that bit into DisasContext.  For the moment that's ok,
+       since the direct implementations below doesn't have any ASIs
+       in the restricted [0x30, 0x7f] range, and the check will be
+       done properly in the helper.  */
+    if (!supervisor(dc) && asi < 0x80) {
+        gen_exception(dc, TT_PRIV_ACT);
+        type = GET_ASI_EXCP;
+    } else {
+        switch (asi) {
+        case ASI_N:  /* Nucleus */
+        case ASI_NL: /* Nucleus LE */
+            mem_idx = MMU_NUCLEUS_IDX;
+            break;
+        case ASI_AIUP:  /* As if user primary */
+        case ASI_AIUPL: /* As if user primary LE */
+            mem_idx = MMU_USER_IDX;
+            break;
+        case ASI_AIUS:  /* As if user secondary */
+        case ASI_AIUSL: /* As if user secondary LE */
+            mem_idx = MMU_USER_SECONDARY_IDX;
+            break;
+        case ASI_S:  /* Secondary */
+        case ASI_SL: /* Secondary LE */
+            if (mem_idx == MMU_USER_IDX) {
+                mem_idx = MMU_USER_SECONDARY_IDX;
+            } else if (mem_idx == MMU_KERNEL_IDX) {
+                mem_idx = MMU_KERNEL_SECONDARY_IDX;
+            }
+            break;
+        case ASI_P:  /* Primary */
+        case ASI_PL: /* Primary LE */
+            break;
+        }
+        switch (asi) {
+        case ASI_N:
+        case ASI_NL:
+        case ASI_AIUP:
+        case ASI_AIUPL:
+        case ASI_AIUS:
+        case ASI_AIUSL:
+        case ASI_S:
+        case ASI_SL:
+        case ASI_P:
+        case ASI_PL:
+            type = GET_ASI_DIRECT;
+            break;
+        }
+        /* The little-endian asis all have bit 3 set.  */
+        if (asi & 8) {
+            memop ^= MO_BSWAP;
+        }
+    }
 #endif
 
-    return (DisasASI){ type, asi };
+    return (DisasASI){ type, asi, mem_idx, memop };
 }
 
 static void gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr,
                        int insn, TCGMemOp memop)
 {
-    DisasASI da = get_asi(dc, insn);
+    DisasASI da = get_asi(dc, insn, memop);
 
     switch (da.type) {
     case GET_ASI_EXCP:
         break;
+    case GET_ASI_DIRECT:
+        gen_address_mask(dc, addr);
+        tcg_gen_qemu_ld_tl(dst, addr, da.mem_idx, da.memop);
+        break;
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
@@ -2053,11 +2125,15 @@ static void gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr,
 static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr,
                        int insn, TCGMemOp memop)
 {
-    DisasASI da = get_asi(dc, insn);
+    DisasASI da = get_asi(dc, insn, memop);
 
     switch (da.type) {
     case GET_ASI_EXCP:
         break;
+    case GET_ASI_DIRECT:
+        gen_address_mask(dc, addr);
+        tcg_gen_qemu_st_tl(src, addr, da.mem_idx, da.memop);
+        break;
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
@@ -2087,7 +2163,7 @@ static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr,
 static void gen_swap_asi(DisasContext *dc, TCGv dst, TCGv src,
                          TCGv addr, int insn)
 {
-    DisasASI da = get_asi(dc, insn);
+    DisasASI da = get_asi(dc, insn, MO_TEUL);
 
     switch (da.type) {
     case GET_ASI_EXCP:
@@ -2121,7 +2197,7 @@ static void gen_swap_asi(DisasContext *dc, TCGv dst, TCGv src,
 static void gen_cas_asi(DisasContext *dc, TCGv addr, TCGv val2,
                         int insn, int rd)
 {
-    DisasASI da = get_asi(dc, insn);
+    DisasASI da = get_asi(dc, insn, MO_TEUL);
     TCGv val1, dst;
     TCGv_i32 r_asi;
 
@@ -2140,7 +2216,7 @@ static void gen_cas_asi(DisasContext *dc, TCGv addr, TCGv val2,
 
 static void gen_ldstub_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn)
 {
-    DisasASI da = get_asi(dc, insn);
+    DisasASI da = get_asi(dc, insn, MO_UB);
 
     switch (da.type) {
     case GET_ASI_EXCP:
@@ -2175,7 +2251,7 @@ static void gen_ldstub_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn)
 static void gen_ldf_asi(DisasContext *dc, TCGv addr,
                         int insn, int size, int rd)
 {
-    DisasASI da = get_asi(dc, insn);
+    DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEQ));
 
     switch (da.type) {
     case GET_ASI_EXCP:
@@ -2199,7 +2275,7 @@ static void gen_ldf_asi(DisasContext *dc, TCGv addr,
 static void gen_stf_asi(DisasContext *dc, TCGv addr,
                         int insn, int size, int rd)
 {
-    DisasASI da = get_asi(dc, insn);
+    DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEQ));
 
     switch (da.type) {
     case GET_ASI_EXCP:
@@ -2223,7 +2299,7 @@ static void gen_stf_asi(DisasContext *dc, TCGv addr,
 static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
                          int insn, int rd)
 {
-    DisasASI da = get_asi(dc, insn);
+    DisasASI da = get_asi(dc, insn, MO_TEQ);
 
     switch (da.type) {
     case GET_ASI_EXCP:
@@ -2245,7 +2321,7 @@ static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
 static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
                          int insn, int rd)
 {
-    DisasASI da = get_asi(dc, insn);
+    DisasASI da = get_asi(dc, insn, MO_TEQ);
     TCGv lo = gen_load_gpr(dc, rd + 1);
 
     switch (da.type) {
@@ -2273,7 +2349,7 @@ static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
 static void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv val2,
                          int insn, int rd)
 {
-    DisasASI da = get_asi(dc, insn);
+    DisasASI da = get_asi(dc, insn, MO_TEQ);
     TCGv val1 = gen_load_gpr(dc, rd);
     TCGv dst = gen_dest_gpr(dc, rd);
     TCGv_i32 r_asi;
@@ -2297,9 +2373,9 @@ static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
        whereby "rd + 1" elicits "error: array subscript is above array".
        Since we have already asserted that rd is even, the semantics
        are unchanged.  */
-    DisasASI da = get_asi(dc, insn);
     TCGv lo = gen_dest_gpr(dc, rd | 1);
     TCGv_i64 t64 = tcg_temp_new_i64();
+    DisasASI da = get_asi(dc, insn, MO_TEQ);
 
     switch (da.type) {
     case GET_ASI_EXCP:
@@ -2329,7 +2405,7 @@ static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
 static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
                          int insn, int rd)
 {
-    DisasASI da = get_asi(dc, insn);
+    DisasASI da = get_asi(dc, insn, MO_TEQ);
     TCGv lo = gen_load_gpr(dc, rd + 1);
     TCGv_i64 t64 = tcg_temp_new_i64();
 
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 13/24] target-sparc: Use QT0 to return results from ldda
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (11 preceding siblings ...)
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 12/24] target-sparc: Directly implement easy ld/st asis Richard Henderson
@ 2016-06-28  0:39 ` Richard Henderson
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 14/24] target-sparc: Introduce gen_check_align Richard Henderson
                   ` (11 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Also implement a few more twinx asis.

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/helper.h      |   2 +-
 target-sparc/ldst_helper.c | 156 ++++++++++++++++++++++++++++++++-------------
 target-sparc/translate.c   |  12 +++-
 3 files changed, 120 insertions(+), 50 deletions(-)

diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 14712cc..66abf83 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -17,7 +17,7 @@ DEF_HELPER_1(rdcwp, tl, env)
 DEF_HELPER_2(wrcwp, void, env, tl)
 DEF_HELPER_FLAGS_2(array8, TCG_CALL_NO_RWG_SE, tl, tl, tl)
 DEF_HELPER_FLAGS_1(popc, TCG_CALL_NO_RWG_SE, tl, tl)
-DEF_HELPER_4(ldda_asi, void, env, tl, int, int)
+DEF_HELPER_FLAGS_3(ldda_asi, TCG_CALL_NO_WG, void, env, tl, int)
 DEF_HELPER_5(ldf_asi, void, env, tl, int, int, int)
 DEF_HELPER_FLAGS_5(stf_asi, TCG_CALL_NO_WG, void, env, tl, int, int, int)
 DEF_HELPER_FLAGS_5(casx_asi, TCG_CALL_NO_WG, tl, env, tl, tl, tl, i32)
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index a6c4d0c..23840db 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -1329,8 +1329,6 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
     case ASI_S:  /* Secondary */
     case ASI_PL: /* Primary LE */
     case ASI_SL: /* Secondary LE */
-    case ASI_BLK_INIT_QUAD_LDD_P: /* UA2007 Primary block init */
-    case ASI_BLK_INIT_QUAD_LDD_S: /* UA2007 Secondary block init */
         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
             if (cpu_hypervisor_mode(env)) {
                 switch (size) {
@@ -1443,11 +1441,6 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
             }
             break;
         }
-    case ASI_NUCLEUS_QUAD_LDD:   /* Nucleus quad LDD 128 bit atomic */
-    case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */
-        /* Only ldda allowed */
-        helper_raise_exception(env, TT_ILL_INSN);
-        return 0;
     case ASI_N:  /* Nucleus */
     case ASI_NL: /* Nucleus Little Endian (LE) */
         {
@@ -1595,6 +1588,25 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
         cpu_unassigned_access(cs, addr, false, false, 1, size);
         ret = 0;
         break;
+
+    case ASI_NUCLEUS_QUAD_LDD:   /* Nucleus quad LDD 128 bit atomic */
+    case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */
+    case ASI_TWINX_AIUP:   /* As if user primary, twinx */
+    case ASI_TWINX_AIUS:   /* As if user secondary, twinx */
+    case ASI_TWINX_REAL:   /* Real address, twinx */
+    case ASI_TWINX_AIUP_L: /* As if user primary, twinx, LE */
+    case ASI_TWINX_AIUS_L: /* As if user secondary, twinx, LE */
+    case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
+    case ASI_TWINX_N:  /* Nucleus, twinx */
+    case ASI_TWINX_NL: /* Nucleus, twinx, LE */
+    /* ??? From the UA2011 document; overlaps BLK_INIT_QUAD_LDD_* */
+    case ASI_TWINX_P:  /* Primary, twinx */
+    case ASI_TWINX_PL: /* Primary, twinx, LE */
+    case ASI_TWINX_S:  /* Secondary, twinx */
+    case ASI_TWINX_SL: /* Secondary, twinx, LE */
+        /* These are all 128-bit atomic; only ldda (now ldtxa) allowed */
+        helper_raise_exception(env, TT_ILL_INSN);
+        return 0;
     }
 
     /* Convert from little endian */
@@ -1702,8 +1714,6 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
     case ASI_S:  /* Secondary */
     case ASI_PL: /* Primary LE */
     case ASI_SL: /* Secondary LE */
-    case ASI_BLK_INIT_QUAD_LDD_P: /* UA2007 Primary block init */
-    case ASI_BLK_INIT_QUAD_LDD_S: /* UA2007 Secondary block init */
         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
             if (cpu_hypervisor_mode(env)) {
                 switch (size) {
@@ -1816,11 +1826,6 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
             }
         }
         return;
-    case ASI_NUCLEUS_QUAD_LDD:   /* Nucleus quad LDD 128 bit atomic */
-    case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */
-        /* Only ldda allowed */
-        helper_raise_exception(env, TT_ILL_INSN);
-        return;
     case ASI_N:  /* Nucleus */
     case ASI_NL: /* Nucleus Little Endian (LE) */
         {
@@ -2001,6 +2006,24 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
     case ASI_INTR_RECEIVE: /* Interrupt data receive */
         env->ivec_status = val & 0x20;
         return;
+    case ASI_NUCLEUS_QUAD_LDD:   /* Nucleus quad LDD 128 bit atomic */
+    case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */
+    case ASI_TWINX_AIUP:   /* As if user primary, twinx */
+    case ASI_TWINX_AIUS:   /* As if user secondary, twinx */
+    case ASI_TWINX_REAL:   /* Real address, twinx */
+    case ASI_TWINX_AIUP_L: /* As if user primary, twinx, LE */
+    case ASI_TWINX_AIUS_L: /* As if user secondary, twinx, LE */
+    case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
+    case ASI_TWINX_N:  /* Nucleus, twinx */
+    case ASI_TWINX_NL: /* Nucleus, twinx, LE */
+    /* ??? From the UA2011 document; overlaps BLK_INIT_QUAD_LDD_* */
+    case ASI_TWINX_P:  /* Primary, twinx */
+    case ASI_TWINX_PL: /* Primary, twinx, LE */
+    case ASI_TWINX_S:  /* Secondary, twinx */
+    case ASI_TWINX_SL: /* Secondary, twinx, LE */
+        /* Only stda allowed */
+        helper_raise_exception(env, TT_ILL_INSN);
+        return;
     case ASI_DCACHE_DATA: /* D-cache data */
     case ASI_DCACHE_TAG: /* D-cache tag access */
     case ASI_ESTATE_ERROR_EN: /* E-cache error enable */
@@ -2034,8 +2057,11 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
 }
 #endif /* CONFIG_USER_ONLY */
 
-void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi, int rd)
+/* 128-bit LDDA; result returned in QT0.  */
+void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi)
 {
+    uint64_t h, l;
+
     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
         || (cpu_has_hypervisor(env)
             && asi >= 0x30 && asi < 0x80
@@ -2047,44 +2073,82 @@ void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi, int rd)
 
     switch (asi) {
 #if !defined(CONFIG_USER_ONLY)
-    case ASI_NUCLEUS_QUAD_LDD: /* Nucleus quad LDD 128 bit atomic */
-    case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */
+    case ASI_TWINX_AIUP:   /* As if user primary, twinx */
+    case ASI_TWINX_AIUP_L: /* As if user primary, twinx, LE */
         helper_check_align(env, addr, 0xf);
-        if (rd == 0) {
-            env->gregs[1] = cpu_ldq_nucleus(env, addr + 8);
-            if (asi == ASI_NUCLEUS_QUAD_LDD_L) {
-                bswap64s(&env->gregs[1]);
-            }
-        } else if (rd < 8) {
-            env->gregs[rd] = cpu_ldq_nucleus(env, addr);
-            env->gregs[rd + 1] = cpu_ldq_nucleus(env, addr + 8);
-            if (asi == ASI_NUCLEUS_QUAD_LDD_L) {
-                bswap64s(&env->gregs[rd]);
-                bswap64s(&env->gregs[rd + 1]);
-            }
-        } else {
-            env->regwptr[rd - 8] = cpu_ldq_nucleus(env, addr);
-            env->regwptr[rd + 1 - 8] = cpu_ldq_nucleus(env, addr + 8);
-            if (asi == ASI_NUCLEUS_QUAD_LDD_L) {
-                bswap64s(&env->regwptr[rd - 8]);
-                bswap64s(&env->regwptr[rd + 1 - 8]);
+        h = cpu_ldq_user(env, addr);
+        l = cpu_ldq_user(env, addr + 8);
+        break;
+    case ASI_TWINX_AIUS:   /* As if user secondary, twinx */
+    case ASI_TWINX_AIUS_L: /* As if user secondary, twinx, LE */
+        helper_check_align(env, addr, 0xf);
+        h = cpu_ldq_user_secondary(env, addr);
+        l = cpu_ldq_user_secondary(env, addr + 8);
+        break;
+    case ASI_TWINX_REAL:   /* Real address, twinx */
+    case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
+        helper_check_align(env, addr, 0xf);
+        {
+            CPUState *cs = CPU(sparc_env_get_cpu(env));
+            h = ldq_phys(cs->as, addr);
+            l = ldq_phys(cs->as, addr + 8);
+        }
+        break;
+    case ASI_NUCLEUS_QUAD_LDD:
+    case ASI_NUCLEUS_QUAD_LDD_L:
+    case ASI_TWINX_N:  /* Nucleus, twinx */
+    case ASI_TWINX_NL: /* Nucleus, twinx, LE */
+        helper_check_align(env, addr, 0xf);
+        h = cpu_ldq_nucleus(env, addr);
+        l = cpu_ldq_nucleus(env, addr + 8);
+        break;
+    case ASI_TWINX_S: /* Secondary, twinx */
+    case ASI_TWINX_SL: /* Secondary, twinx, LE */
+        if (!cpu_hypervisor_mode(env)) {
+            helper_check_align(env, addr, 0xf);
+            if (env->pstate & PS_PRIV) {
+                h = cpu_ldq_kernel_secondary(env, addr);
+                l = cpu_ldq_kernel_secondary(env, addr + 8);
+            } else {
+                h = cpu_ldq_user_secondary(env, addr);
+                l = cpu_ldq_user_secondary(env, addr + 8);
             }
+            break;
         }
+        /* fallthru */
+    case ASI_TWINX_P:  /* Primary, twinx */
+    case ASI_TWINX_PL: /* Primary, twinx, LE */
+        helper_check_align(env, addr, 0xf);
+        h = cpu_ldq_data(env, addr);
+        l = cpu_ldq_data(env, addr + 8);
         break;
+#else
+    case ASI_TWINX_P:  /* Primary, twinx */
+    case ASI_TWINX_PL: /* Primary, twinx, LE */
+    case ASI_TWINX_S:  /* Primary, twinx */
+    case ASI_TWINX_SL: /* Primary, twinx, LE */
+        /* ??? Should be available, but we need to implement
+           an atomic 128-bit load.  */
+        helper_raise_exception(env, TT_PRIV_ACT);
 #endif
     default:
-        helper_check_align(env, addr, 0x3);
-        if (rd == 0) {
-            env->gregs[1] = helper_ld_asi(env, addr + 4, asi, 4, 0);
-        } else if (rd < 8) {
-            env->gregs[rd] = helper_ld_asi(env, addr, asi, 4, 0);
-            env->gregs[rd + 1] = helper_ld_asi(env, addr + 4, asi, 4, 0);
-        } else {
-            env->regwptr[rd - 8] = helper_ld_asi(env, addr, asi, 4, 0);
-            env->regwptr[rd + 1 - 8] = helper_ld_asi(env, addr + 4, asi, 4, 0);
-        }
-        break;
+        /* Non-twinx asi, so this is the legacy ldda insn, which
+           performs two word sized operations.  */
+        /* ??? The UA2011 manual recommends emulating this with
+           a single 64-bit load.  However, LE asis *are* treated
+           as two 32-bit loads individually byte swapped.  */
+        helper_check_align(env, addr, 0x7);
+        QT0.high = (uint32_t)helper_ld_asi(env, addr, asi, 4, 0);
+        QT0.low = (uint32_t)helper_ld_asi(env, addr + 4, asi, 4, 0);
+        return;
+    }
+
+    if (asi & 8) {
+        h = bswap64(h);
+        l = bswap64(l);
     }
+    QT0.high = h;
+    QT0.low = l;
 }
 
 void helper_ldf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 55364ad..885fa58 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2307,12 +2307,18 @@ static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
-            TCGv_i32 r_rd = tcg_const_i32(rd);
+            TCGv_i64 tmp;
 
             save_state(dc);
-            gen_helper_ldda_asi(cpu_env, addr, r_asi, r_rd);
-            tcg_temp_free_i32(r_rd);
+            gen_helper_ldda_asi(cpu_env, addr, r_asi);
             tcg_temp_free_i32(r_asi);
+
+            tmp = gen_dest_gpr(dc, rd);
+            tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUSPARCState, qt0.high));
+            gen_store_gpr(dc, rd, tmp);
+            tmp = gen_dest_gpr(dc, rd + 1);
+            tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUSPARCState, qt0.low));
+            gen_store_gpr(dc, rd + 1, tmp);
         }
         break;
     }
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 14/24] target-sparc: Introduce gen_check_align
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (12 preceding siblings ...)
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 13/24] target-sparc: Use QT0 to return results from ldda Richard Henderson
@ 2016-06-28  0:39 ` Richard Henderson
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 15/24] target-sparc: Directly implement easy ldd/std asis Richard Henderson
                   ` (10 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/translate.c | 48 +++++++++++++-----------------------------------
 1 file changed, 13 insertions(+), 35 deletions(-)

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 885fa58..e7120f8 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1058,6 +1058,13 @@ static void gen_exception(DisasContext *dc, int which)
     dc->is_br = 1;
 }
 
+static void gen_check_align(TCGv addr, int mask)
+{
+    TCGv_i32 r_mask = tcg_const_i32(mask);
+    gen_helper_check_align(cpu_env, addr, r_mask);
+    tcg_temp_free_i32(r_mask);
+}
+
 static inline void gen_mov_pc_npc(DisasContext *dc)
 {
     if (dc->npc == JUMP_PC) {
@@ -4696,8 +4703,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
 #endif
 #ifdef TARGET_SPARC64
             } else if (xop == 0x39) { /* V9 return */
-                TCGv_i32 r_const;
-
                 save_state(dc);
                 cpu_src1 = get_src1(dc, insn);
                 cpu_tmp0 = get_temp_tl(dc);
@@ -4715,9 +4720,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                 }
                 gen_helper_restore(cpu_env);
                 gen_mov_pc_npc(dc);
-                r_const = tcg_const_i32(3);
-                gen_helper_check_align(cpu_env, cpu_tmp0, r_const);
-                tcg_temp_free_i32(r_const);
+                gen_check_align(cpu_tmp0, 3);
                 tcg_gen_mov_tl(cpu_npc, cpu_tmp0);
                 dc->npc = DYNAMIC_PC;
                 goto jmp_insn;
@@ -4740,16 +4743,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                 switch (xop) {
                 case 0x38:      /* jmpl */
                     {
-                        TCGv t;
-                        TCGv_i32 r_const;
-
-                        t = gen_dest_gpr(dc, rd);
+                        TCGv t = gen_dest_gpr(dc, rd);
                         tcg_gen_movi_tl(t, dc->pc);
                         gen_store_gpr(dc, rd, t);
+
                         gen_mov_pc_npc(dc);
-                        r_const = tcg_const_i32(3);
-                        gen_helper_check_align(cpu_env, cpu_tmp0, r_const);
-                        tcg_temp_free_i32(r_const);
+                        gen_check_align(cpu_tmp0, 3);
                         gen_address_mask(dc, cpu_tmp0);
                         tcg_gen_mov_tl(cpu_npc, cpu_tmp0);
                         dc->npc = DYNAMIC_PC;
@@ -4758,14 +4757,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
 #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
                 case 0x39:      /* rett, V9 return */
                     {
-                        TCGv_i32 r_const;
-
                         if (!supervisor(dc))
                             goto priv_insn;
                         gen_mov_pc_npc(dc);
-                        r_const = tcg_const_i32(3);
-                        gen_helper_check_align(cpu_env, cpu_tmp0, r_const);
-                        tcg_temp_free_i32(r_const);
+                        gen_check_align(cpu_tmp0, 3);
                         tcg_gen_mov_tl(cpu_npc, cpu_tmp0);
                         dc->npc = DYNAMIC_PC;
                         gen_helper_rett(cpu_env);
@@ -4861,14 +4856,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     if (rd & 1)
                         goto illegal_insn;
                     else {
-                        TCGv_i32 r_const;
                         TCGv_i64 t64;
 
-                        save_state(dc);
-                        r_const = tcg_const_i32(7);
-                        /* XXX remove alignment check */
-                        gen_helper_check_align(cpu_env, cpu_addr, r_const);
-                        tcg_temp_free_i32(r_const);
                         gen_address_mask(dc, cpu_addr);
                         t64 = tcg_temp_new_i64();
                         tcg_gen_qemu_ld64(t64, cpu_addr, dc->mem_idx);
@@ -5079,18 +5068,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     if (rd & 1)
                         goto illegal_insn;
                     else {
-                        TCGv_i32 r_const;
                         TCGv_i64 t64;
                         TCGv lo;
 
-                        save_state(dc);
                         gen_address_mask(dc, cpu_addr);
-                        r_const = tcg_const_i32(7);
-                        /* XXX remove alignment check */
-                        gen_helper_check_align(cpu_env, cpu_addr, r_const);
-                        tcg_temp_free_i32(r_const);
                         lo = gen_load_gpr(dc, rd + 1);
-
                         t64 = tcg_temp_new_i64();
                         tcg_gen_concat_tl_i64(t64, lo, cpu_val);
                         tcg_gen_qemu_st64(t64, cpu_addr, dc->mem_idx);
@@ -5203,15 +5185,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     break;
                 case 0x36: /* V9 stqfa */
                     {
-                        TCGv_i32 r_const;
-
                         CHECK_FPU_FEATURE(dc, FLOAT128);
                         if (gen_trap_ifnofpu(dc)) {
                             goto jmp_insn;
                         }
-                        r_const = tcg_const_i32(7);
-                        gen_helper_check_align(cpu_env, cpu_addr, r_const);
-                        tcg_temp_free_i32(r_const);
+                        gen_check_align(cpu_addr, 7);
                         gen_stf_asi(dc, cpu_addr, insn, 16, QFPREG(rd));
                     }
                     break;
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 15/24] target-sparc: Directly implement easy ldd/std asis
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (13 preceding siblings ...)
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 14/24] target-sparc: Introduce gen_check_align Richard Henderson
@ 2016-06-28  0:39 ` Richard Henderson
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 16/24] target-sparc: Fix obvious error in ASI_M_BFILL Richard Henderson
                   ` (9 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/translate.c | 115 ++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 103 insertions(+), 12 deletions(-)

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index e7120f8..0d5149d 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1988,6 +1988,7 @@ typedef enum {
     GET_ASI_HELPER,
     GET_ASI_EXCP,
     GET_ASI_DIRECT,
+    GET_ASI_DTWINX,
 } ASIType;
 
 typedef struct {
@@ -2046,18 +2047,26 @@ static DisasASI get_asi(DisasContext *dc, int insn, TCGMemOp memop)
         switch (asi) {
         case ASI_N:  /* Nucleus */
         case ASI_NL: /* Nucleus LE */
+        case ASI_TWINX_N:
+        case ASI_TWINX_NL:
             mem_idx = MMU_NUCLEUS_IDX;
             break;
         case ASI_AIUP:  /* As if user primary */
         case ASI_AIUPL: /* As if user primary LE */
+        case ASI_TWINX_AIUP:
+        case ASI_TWINX_AIUP_L:
             mem_idx = MMU_USER_IDX;
             break;
         case ASI_AIUS:  /* As if user secondary */
         case ASI_AIUSL: /* As if user secondary LE */
+        case ASI_TWINX_AIUS:
+        case ASI_TWINX_AIUS_L:
             mem_idx = MMU_USER_SECONDARY_IDX;
             break;
         case ASI_S:  /* Secondary */
         case ASI_SL: /* Secondary LE */
+        case ASI_TWINX_S:
+        case ASI_TWINX_SL:
             if (mem_idx == MMU_USER_IDX) {
                 mem_idx = MMU_USER_SECONDARY_IDX;
             } else if (mem_idx == MMU_KERNEL_IDX) {
@@ -2066,6 +2075,8 @@ static DisasASI get_asi(DisasContext *dc, int insn, TCGMemOp memop)
             break;
         case ASI_P:  /* Primary */
         case ASI_PL: /* Primary LE */
+        case ASI_TWINX_P:
+        case ASI_TWINX_PL:
             break;
         }
         switch (asi) {
@@ -2081,6 +2092,18 @@ static DisasASI get_asi(DisasContext *dc, int insn, TCGMemOp memop)
         case ASI_PL:
             type = GET_ASI_DIRECT;
             break;
+        case ASI_TWINX_N:
+        case ASI_TWINX_NL:
+        case ASI_TWINX_AIUP:
+        case ASI_TWINX_AIUP_L:
+        case ASI_TWINX_AIUS:
+        case ASI_TWINX_AIUS_L:
+        case ASI_TWINX_P:
+        case ASI_TWINX_PL:
+        case ASI_TWINX_S:
+        case ASI_TWINX_SL:
+            type = GET_ASI_DTWINX;
+            break;
         }
         /* The little-endian asis all have bit 3 set.  */
         if (asi & 8) {
@@ -2100,6 +2123,9 @@ static void gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr,
     switch (da.type) {
     case GET_ASI_EXCP:
         break;
+    case GET_ASI_DTWINX: /* Reserved for ldda.  */
+        gen_exception(dc, TT_ILL_INSN);
+        break;
     case GET_ASI_DIRECT:
         gen_address_mask(dc, addr);
         tcg_gen_qemu_ld_tl(dst, addr, da.mem_idx, da.memop);
@@ -2137,6 +2163,9 @@ static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr,
     switch (da.type) {
     case GET_ASI_EXCP:
         break;
+    case GET_ASI_DTWINX: /* Reserved for stda.  */
+        gen_exception(dc, TT_ILL_INSN);
+        break;
     case GET_ASI_DIRECT:
         gen_address_mask(dc, addr);
         tcg_gen_qemu_st_tl(src, addr, da.mem_idx, da.memop);
@@ -2303,32 +2332,59 @@ static void gen_stf_asi(DisasContext *dc, TCGv addr,
     }
 }
 
-static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
-                         int insn, int rd)
+static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd)
 {
     DisasASI da = get_asi(dc, insn, MO_TEQ);
+    TCGv_i64 hi = gen_dest_gpr(dc, rd);
+    TCGv_i64 lo = gen_dest_gpr(dc, rd + 1);
 
     switch (da.type) {
     case GET_ASI_EXCP:
+        return;
+
+    case GET_ASI_DTWINX:
+        gen_check_align(addr, 15);
+        gen_address_mask(dc, addr);
+        tcg_gen_qemu_ld_i64(hi, addr, da.mem_idx, da.memop);
+        tcg_gen_addi_tl(addr, addr, 8);
+        tcg_gen_qemu_ld_i64(lo, addr, da.mem_idx, da.memop);
         break;
+
+    case GET_ASI_DIRECT:
+        {
+            TCGv_i64 tmp = tcg_temp_new_i64();
+
+            gen_address_mask(dc, addr);
+            tcg_gen_qemu_ld_i64(tmp, addr, da.mem_idx, da.memop);
+
+            /* Note that LE ldda acts as if each 32-bit register
+               result is byte swapped.  Having just performed one
+               64-bit bswap, we need now to swap the writebacks.  */
+            if ((da.memop & MO_BSWAP) == MO_TE) {
+                tcg_gen_extr32_i64(lo, hi, tmp);
+            } else {
+                tcg_gen_extr32_i64(hi, lo, tmp);
+            }
+            tcg_temp_free_i64(tmp);
+        }
+        break;
+
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
-            TCGv_i64 tmp;
 
             save_state(dc);
             gen_helper_ldda_asi(cpu_env, addr, r_asi);
             tcg_temp_free_i32(r_asi);
 
-            tmp = gen_dest_gpr(dc, rd);
-            tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUSPARCState, qt0.high));
-            gen_store_gpr(dc, rd, tmp);
-            tmp = gen_dest_gpr(dc, rd + 1);
-            tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUSPARCState, qt0.low));
-            gen_store_gpr(dc, rd + 1, tmp);
+            tcg_gen_ld_i64(hi, cpu_env, offsetof(CPUSPARCState, qt0.high));
+            tcg_gen_ld_i64(lo, cpu_env, offsetof(CPUSPARCState, qt0.low));
         }
         break;
     }
+
+    gen_store_gpr(dc, rd, hi);
+    gen_store_gpr(dc, rd + 1, lo);
 }
 
 static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
@@ -2340,6 +2396,33 @@ static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
     switch (da.type) {
     case GET_ASI_EXCP:
         break;
+
+    case GET_ASI_DTWINX:
+        gen_check_align(addr, 15);
+        gen_address_mask(dc, addr);
+        tcg_gen_qemu_st_i64(hi, addr, da.mem_idx, da.memop);
+        tcg_gen_addi_tl(addr, addr, 8);
+        tcg_gen_qemu_st_i64(lo, addr, da.mem_idx, da.memop);
+        break;
+
+    case GET_ASI_DIRECT:
+        {
+            TCGv_i64 t64 = tcg_temp_new_i64();
+
+            /* Note that LE stda acts as if each 32-bit register result is
+               byte swapped.  We will perform one 64-bit LE store, so now
+               we must swap the order of the construction.  */
+            if ((da.memop & MO_BSWAP) == MO_TE) {
+                tcg_gen_concat32_i64(t64, lo, hi);
+            } else {
+                tcg_gen_concat32_i64(t64, hi, lo);
+            }
+            gen_address_mask(dc, addr);
+            tcg_gen_qemu_st_i64(t64, addr, da.mem_idx, da.memop);
+            tcg_temp_free_i64(t64);
+        }
+        break;
+
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
@@ -2379,14 +2462,14 @@ static void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv val2,
 }
 
 #elif !defined(CONFIG_USER_ONLY)
-static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
-                         int insn, int rd)
+static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd)
 {
     /* ??? Work around an apparent bug in Ubuntu gcc 4.8.2-10ubuntu2+12,
        whereby "rd + 1" elicits "error: array subscript is above array".
        Since we have already asserted that rd is even, the semantics
        are unchanged.  */
     TCGv lo = gen_dest_gpr(dc, rd | 1);
+    TCGv hi = gen_dest_gpr(dc, rd);
     TCGv_i64 t64 = tcg_temp_new_i64();
     DisasASI da = get_asi(dc, insn, MO_TEQ);
 
@@ -2394,6 +2477,10 @@ static void gen_ldda_asi(DisasContext *dc, TCGv hi, TCGv addr,
     case GET_ASI_EXCP:
         tcg_temp_free_i64(t64);
         return;
+    case GET_ASI_DIRECT:
+        gen_address_mask(dc, addr);
+        tcg_gen_qemu_ld_i64(t64, addr, da.mem_idx, da.memop);
+        break;
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
@@ -2427,6 +2514,10 @@ static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
     switch (da.type) {
     case GET_ASI_EXCP:
         break;
+    case GET_ASI_DIRECT:
+        gen_address_mask(dc, addr);
+        tcg_gen_qemu_st_i64(t64, addr, da.mem_idx, da.memop);
+        break;
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
@@ -4918,7 +5009,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     if (rd & 1) {
                         goto illegal_insn;
                     }
-                    gen_ldda_asi(dc, cpu_val, cpu_addr, insn, rd);
+                    gen_ldda_asi(dc, cpu_addr, insn, rd);
                     goto skip_move;
                 case 0x19:      /* ldsba, load signed byte alternate */
                     gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_SB);
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 16/24] target-sparc: Fix obvious error in ASI_M_BFILL
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (14 preceding siblings ...)
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 15/24] target-sparc: Directly implement easy ldd/std asis Richard Henderson
@ 2016-06-28  0:39 ` Richard Henderson
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 17/24] target-sparc: Pass TCGMemOp constants to helper_ld/st_asi Richard Henderson
                   ` (8 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/ldst_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 23840db..3700ca1 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -989,7 +989,7 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
             /* addr = dst
                fill 32 bytes with val */
             unsigned int i;
-            uint32_t dst = addr & 7;
+            uint32_t dst = addr & ~7;
 
             for (i = 0; i < 32; i += 8, dst += 8) {
                 cpu_stq_kernel(env, dst, val);
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 17/24] target-sparc: Pass TCGMemOp constants to helper_ld/st_asi
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (15 preceding siblings ...)
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 16/24] target-sparc: Fix obvious error in ASI_M_BFILL Richard Henderson
@ 2016-06-28  0:39 ` Richard Henderson
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 18/24] target-sparc: Directly implement easy ldf/stf asis Richard Henderson
                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Reduces the argument count for helper_ld_asi; do helper_st_asi
for consistency.

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/helper.h      |  4 +--
 target-sparc/ldst_helper.c | 73 ++++++++++++++++++++++++++--------------------
 target-sparc/translate.c   | 58 ++++++++++++++++--------------------
 3 files changed, 69 insertions(+), 66 deletions(-)

diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 66abf83..f5afc8d 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -48,8 +48,8 @@ DEF_HELPER_FLAGS_3(udivx, TCG_CALL_NO_WG, i64, env, i64, i64)
 DEF_HELPER_FLAGS_3(ldqf, TCG_CALL_NO_WG, void, env, tl, int)
 DEF_HELPER_FLAGS_3(stqf, TCG_CALL_NO_WG, void, env, tl, int)
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
-DEF_HELPER_FLAGS_5(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, int, int)
-DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, int)
+DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, i32)
+DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32)
 #endif
 DEF_HELPER_2(ldfsr, void, env, i32)
 DEF_HELPER_FLAGS_1(fabss, TCG_CALL_NO_RWG_SE, f32, f32)
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 3700ca1..240c1bc 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -19,6 +19,7 @@
 
 #include "qemu/osdep.h"
 #include "cpu.h"
+#include "tcg.h"
 #include "exec/helper-proto.h"
 #include "exec/exec-all.h"
 #include "exec/cpu_ldst.h"
@@ -428,9 +429,11 @@ static uint64_t leon3_cache_control_ld(CPUSPARCState *env, target_ulong addr,
     return ret;
 }
 
-uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
-                       int sign)
+uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr,
+                       int asi, uint32_t memop)
 {
+    int size = 1 << (memop & MO_SIZE);
+    int sign = memop & MO_SIGN;
     CPUState *cs = CPU(sparc_env_get_cpu(env));
     uint64_t ret = 0;
 #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
@@ -698,9 +701,10 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
     return ret;
 }
 
-void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
-                   int size)
+void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val,
+                   int asi, uint32_t memop)
 {
+    int size = 1 << (memop & MO_SIZE);
     SPARCCPU *cpu = sparc_env_get_cpu(env);
     CPUState *cs = CPU(cpu);
 
@@ -1097,9 +1101,11 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
 #else /* TARGET_SPARC64 */
 
 #ifdef CONFIG_USER_ONLY
-uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
-                       int sign)
+uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr,
+                       int asi, uint32_t memop)
 {
+    int size = 1 << (memop & MO_SIZE);
+    int sign = memop & MO_SIGN;
     uint64_t ret = 0;
 #if defined(DEBUG_ASI)
     target_ulong last_addr = addr;
@@ -1205,8 +1211,9 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
 }
 
 void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
-                   int asi, int size)
+                   int asi, uint32_t memop)
 {
+    int size = 1 << (memop & MO_SIZE);
 #ifdef DEBUG_ASI
     dump_asi("write", addr, asi, size, val);
 #endif
@@ -1276,9 +1283,11 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
 
 #else /* CONFIG_USER_ONLY */
 
-uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
-                       int sign)
+uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr,
+                       int asi, uint32_t memop)
 {
+    int size = 1 << (memop & MO_SIZE);
+    int sign = memop & MO_SIGN;
     CPUState *cs = CPU(sparc_env_get_cpu(env));
     uint64_t ret = 0;
 #if defined(DEBUG_ASI)
@@ -1658,8 +1667,9 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
 }
 
 void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
-                   int asi, int size)
+                   int asi, uint32_t memop)
 {
+    int size = 1 << (memop & MO_SIZE);
     SPARCCPU *cpu = sparc_env_get_cpu(env);
     CPUState *cs = CPU(cpu);
 
@@ -2138,8 +2148,8 @@ void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi)
            a single 64-bit load.  However, LE asis *are* treated
            as two 32-bit loads individually byte swapped.  */
         helper_check_align(env, addr, 0x7);
-        QT0.high = (uint32_t)helper_ld_asi(env, addr, asi, 4, 0);
-        QT0.low = (uint32_t)helper_ld_asi(env, addr + 4, asi, 4, 0);
+        QT0.high = (uint32_t)helper_ld_asi(env, addr, asi, MO_UL);
+        QT0.low = (uint32_t)helper_ld_asi(env, addr + 4, asi, MO_UL);
         return;
     }
 
@@ -2171,7 +2181,7 @@ void helper_ldf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
         }
         helper_check_align(env, addr, 0x3f);
         for (i = 0; i < 8; i++, rd += 2, addr += 8) {
-            env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi & 0x8f, 8, 0);
+            env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi & 0x8f, MO_Q);
         }
         return;
 
@@ -2189,7 +2199,7 @@ void helper_ldf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
         }
         helper_check_align(env, addr, 0x3f);
         for (i = 0; i < 8; i++, rd += 2, addr += 8) {
-            env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi & 0x19, 8, 0);
+            env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi & 0x19, MO_Q);
         }
         return;
 
@@ -2200,7 +2210,7 @@ void helper_ldf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
     switch (size) {
     default:
     case 4:
-        val = helper_ld_asi(env, addr, asi, size, 0);
+        val = helper_ld_asi(env, addr, asi, MO_UL);
         if (rd & 1) {
             env->fpr[rd / 2].l.lower = val;
         } else {
@@ -2208,11 +2218,11 @@ void helper_ldf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
         }
         break;
     case 8:
-        env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi, size, 0);
+        env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi, MO_Q);
         break;
     case 16:
-        env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi, 8, 0);
-        env->fpr[rd / 2 + 1].ll = helper_ld_asi(env, addr + 8, asi, 8, 0);
+        env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi, MO_Q);
+        env->fpr[rd / 2 + 1].ll = helper_ld_asi(env, addr + 8, asi, MO_Q);
         break;
     }
 }
@@ -2238,7 +2248,7 @@ void helper_stf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
         }
         helper_check_align(env, addr, 0x3f);
         for (i = 0; i < 8; i++, rd += 2, addr += 8) {
-            helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi & 0x8f, 8);
+            helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi & 0x8f, MO_Q);
         }
 
         return;
@@ -2256,7 +2266,7 @@ void helper_stf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
         }
         helper_check_align(env, addr, 0x3f);
         for (i = 0; i < 8; i++, rd += 2, addr += 8) {
-            helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi & 0x19, 8);
+            helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi & 0x19, MO_Q);
         }
 
         return;
@@ -2264,14 +2274,15 @@ void helper_stf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
     case ASI_FL16_S: /* 16-bit floating point load secondary */
     case ASI_FL16_PL: /* 16-bit floating point load primary, LE */
     case ASI_FL16_SL: /* 16-bit floating point load secondary, LE */
-        helper_check_align(env, addr, 1);
-        /* Fall through */
+        val = env->fpr[rd / 2].l.lower;
+        helper_st_asi(env, addr, val, asi & 0x8d, MO_UW);
+        return;
     case ASI_FL8_P: /* 8-bit floating point load primary */
     case ASI_FL8_S: /* 8-bit floating point load secondary */
     case ASI_FL8_PL: /* 8-bit floating point load primary, LE */
     case ASI_FL8_SL: /* 8-bit floating point load secondary, LE */
         val = env->fpr[rd / 2].l.lower;
-        helper_st_asi(env, addr, val, asi & 0x8d, ((asi & 2) >> 1) + 1);
+        helper_st_asi(env, addr, val, asi & 0x8d, MO_UB);
         return;
     default:
         helper_check_align(env, addr, 3);
@@ -2286,14 +2297,14 @@ void helper_stf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
         } else {
             val = env->fpr[rd / 2].l.upper;
         }
-        helper_st_asi(env, addr, val, asi, size);
+        helper_st_asi(env, addr, val, asi, MO_UL);
         break;
     case 8:
-        helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi, size);
+        helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi, MO_Q);
         break;
     case 16:
-        helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi, 8);
-        helper_st_asi(env, addr + 8, env->fpr[rd / 2 + 1].ll, asi, 8);
+        helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi, MO_Q);
+        helper_st_asi(env, addr + 8, env->fpr[rd / 2 + 1].ll, asi, MO_Q);
         break;
     }
 }
@@ -2304,9 +2315,9 @@ target_ulong helper_casx_asi(CPUSPARCState *env, target_ulong addr,
 {
     target_ulong ret;
 
-    ret = helper_ld_asi(env, addr, asi, 8, 0);
+    ret = helper_ld_asi(env, addr, asi, MO_Q);
     if (val2 == ret) {
-        helper_st_asi(env, addr, val1, asi, 8);
+        helper_st_asi(env, addr, val1, asi, MO_Q);
     }
     return ret;
 }
@@ -2319,10 +2330,10 @@ target_ulong helper_cas_asi(CPUSPARCState *env, target_ulong addr,
     target_ulong ret;
 
     val2 &= 0xffffffffUL;
-    ret = helper_ld_asi(env, addr, asi, 4, 0);
+    ret = helper_ld_asi(env, addr, asi, MO_UL);
     ret &= 0xffffffffUL;
     if (val2 == ret) {
-        helper_st_asi(env, addr, val1 & 0xffffffffUL, asi, 4);
+        helper_st_asi(env, addr, val1 & 0xffffffffUL, asi, MO_UL);
     }
     return ret;
 }
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 0d5149d..0b29aff 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2133,22 +2133,20 @@ static void gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr,
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
-            TCGv_i32 r_size = tcg_const_i32(1 << (memop & MO_SIZE));
-            TCGv_i32 r_sign = tcg_const_i32(!!(memop & MO_SIGN));
+            TCGv_i32 r_mop = tcg_const_i32(memop);
 
             save_state(dc);
 #ifdef TARGET_SPARC64
-            gen_helper_ld_asi(dst, cpu_env, addr, r_asi, r_size, r_sign);
+            gen_helper_ld_asi(dst, cpu_env, addr, r_asi, r_mop);
 #else
             {
                 TCGv_i64 t64 = tcg_temp_new_i64();
-                gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
+                gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_mop);
                 tcg_gen_trunc_i64_tl(dst, t64);
                 tcg_temp_free_i64(t64);
             }
 #endif
-            tcg_temp_free_i32(r_sign);
-            tcg_temp_free_i32(r_size);
+            tcg_temp_free_i32(r_mop);
             tcg_temp_free_i32(r_asi);
         }
         break;
@@ -2173,20 +2171,20 @@ static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr,
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
-            TCGv_i32 r_size = tcg_const_i32(1 << (memop & MO_SIZE));
+            TCGv_i32 r_mop = tcg_const_i32(memop & MO_SIZE);
 
             save_state(dc);
 #ifdef TARGET_SPARC64
-            gen_helper_st_asi(cpu_env, addr, src, r_asi, r_size);
+            gen_helper_st_asi(cpu_env, addr, src, r_asi, r_mop);
 #else
             {
                 TCGv_i64 t64 = tcg_temp_new_i64();
                 tcg_gen_extu_tl_i64(t64, src);
-                gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
+                gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_mop);
                 tcg_temp_free_i64(t64);
             }
 #endif
-            tcg_temp_free_i32(r_size);
+            tcg_temp_free_i32(r_mop);
             tcg_temp_free_i32(r_asi);
 
             /* A write to a TLB register may alter page maps.  End the TB. */
@@ -2207,20 +2205,18 @@ static void gen_swap_asi(DisasContext *dc, TCGv dst, TCGv src,
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
-            TCGv_i32 r_size = tcg_const_i32(4);
-            TCGv_i32 r_sign = tcg_const_i32(0);
+            TCGv_i32 r_mop = tcg_const_i32(MO_UL);
             TCGv_i64 s64, t64;
 
             save_state(dc);
             t64 = tcg_temp_new_i64();
-            gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
-            tcg_temp_free_i32(r_sign);
+            gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_mop);
 
             s64 = tcg_temp_new_i64();
             tcg_gen_extu_tl_i64(s64, src);
-            gen_helper_st_asi(cpu_env, addr, s64, r_asi, r_size);
+            gen_helper_st_asi(cpu_env, addr, s64, r_asi, r_mop);
             tcg_temp_free_i64(s64);
-            tcg_temp_free_i32(r_size);
+            tcg_temp_free_i32(r_mop);
             tcg_temp_free_i32(r_asi);
 
             tcg_gen_trunc_i64_tl(dst, t64);
@@ -2260,19 +2256,17 @@ static void gen_ldstub_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn)
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
-            TCGv_i32 r_size = tcg_const_i32(1);
-            TCGv_i32 r_sign = tcg_const_i32(0);
+            TCGv_i32 r_mop = tcg_const_i32(MO_UB);
             TCGv_i64 s64, t64;
 
             save_state(dc);
             t64 = tcg_temp_new_i64();
-            gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
-            tcg_temp_free_i32(r_sign);
+            gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_mop);
 
             s64 = tcg_const_i64(0xff);
-            gen_helper_st_asi(cpu_env, addr, s64, r_asi, r_size);
+            gen_helper_st_asi(cpu_env, addr, s64, r_asi, r_mop);
             tcg_temp_free_i64(s64);
-            tcg_temp_free_i32(r_size);
+            tcg_temp_free_i32(r_mop);
             tcg_temp_free_i32(r_asi);
 
             tcg_gen_trunc_i64_tl(dst, t64);
@@ -2426,15 +2420,15 @@ static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
-            TCGv_i32 r_size = tcg_const_i32(8);
+            TCGv_i32 r_mop = tcg_const_i32(MO_Q);
             TCGv_i64 t64;
 
             save_state(dc);
 
             t64 = tcg_temp_new_i64();
             tcg_gen_concat_tl_i64(t64, lo, hi);
-            gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
-            tcg_temp_free_i32(r_size);
+            gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_mop);
+            tcg_temp_free_i32(r_mop);
             tcg_temp_free_i32(r_asi);
             tcg_temp_free_i64(t64);
         }
@@ -2484,13 +2478,11 @@ static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd)
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
-            TCGv_i32 r_size = tcg_const_i32(8);
-            TCGv_i32 r_sign = tcg_const_i32(0);
+            TCGv_i32 r_mop = tcg_const_i32(MO_Q);
 
             save_state(dc);
-            gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_size, r_sign);
-            tcg_temp_free_i32(r_sign);
-            tcg_temp_free_i32(r_size);
+            gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_mop);
+            tcg_temp_free_i32(r_mop);
             tcg_temp_free_i32(r_asi);
         }
         break;
@@ -2521,11 +2513,11 @@ static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
-            TCGv_i32 r_size = tcg_const_i32(8);
+            TCGv_i32 r_mop = tcg_const_i32(MO_Q);
 
             save_state(dc);
-            gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_size);
-            tcg_temp_free_i32(r_size);
+            gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_mop);
+            tcg_temp_free_i32(r_mop);
             tcg_temp_free_i32(r_asi);
         }
         break;
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 18/24] target-sparc: Directly implement easy ldf/stf asis
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (16 preceding siblings ...)
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 17/24] target-sparc: Pass TCGMemOp constants to helper_ld/st_asi Richard Henderson
@ 2016-06-28  0:39 ` Richard Henderson
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 19/24] target-sparc: Directly implement block and short " Richard Henderson
                   ` (6 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/translate.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 0b29aff..2ea6964 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2282,10 +2282,33 @@ static void gen_ldf_asi(DisasContext *dc, TCGv addr,
                         int insn, int size, int rd)
 {
     DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEQ));
+    TCGv_i32 d32;
 
     switch (da.type) {
     case GET_ASI_EXCP:
         break;
+
+    case GET_ASI_DIRECT:
+        gen_address_mask(dc, addr);
+        switch (size) {
+        case 4:
+            d32 = gen_dest_fpr_F(dc);
+            tcg_gen_qemu_ld_i32(d32, addr, da.mem_idx, da.memop);
+            gen_store_fpr_F(dc, rd, d32);
+            break;
+        case 8:
+            tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
+            break;
+        case 16:
+            tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
+            tcg_gen_addi_tl(addr, addr, 8);
+            tcg_gen_qemu_ld_i64(cpu_fpr[rd/2+1], addr, da.mem_idx, da.memop);
+            break;
+        default:
+            g_assert_not_reached();
+        }
+        break;
+
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
@@ -2306,10 +2329,32 @@ static void gen_stf_asi(DisasContext *dc, TCGv addr,
                         int insn, int size, int rd)
 {
     DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEQ));
+    TCGv_i32 d32;
 
     switch (da.type) {
     case GET_ASI_EXCP:
         break;
+
+    case GET_ASI_DIRECT:
+        gen_address_mask(dc, addr);
+        switch (size) {
+        case 4:
+            d32 = gen_load_fpr_F(dc, rd);
+            tcg_gen_qemu_st_i32(d32, addr, da.mem_idx, da.memop);
+            break;
+        case 8:
+            tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
+            break;
+        case 16:
+            tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
+            tcg_gen_addi_tl(addr, addr, 8);
+            tcg_gen_qemu_st_i64(cpu_fpr[rd/2+1], addr, da.mem_idx, da.memop);
+            break;
+        default:
+            g_assert_not_reached();
+        }
+        break;
+
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 19/24] target-sparc: Directly implement block and short ldf/stf asis
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (17 preceding siblings ...)
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 18/24] target-sparc: Directly implement easy ldf/stf asis Richard Henderson
@ 2016-06-28  0:39 ` Richard Henderson
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 20/24] target-sparc: Remove helper_ldf_asi, helper_stf_asi Richard Henderson
                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/translate.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 122 insertions(+)

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 2ea6964..cee1e5c 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1989,6 +1989,8 @@ typedef enum {
     GET_ASI_EXCP,
     GET_ASI_DIRECT,
     GET_ASI_DTWINX,
+    GET_ASI_BLOCK,
+    GET_ASI_SHORT,
 } ASIType;
 
 typedef struct {
@@ -2055,18 +2057,33 @@ static DisasASI get_asi(DisasContext *dc, int insn, TCGMemOp memop)
         case ASI_AIUPL: /* As if user primary LE */
         case ASI_TWINX_AIUP:
         case ASI_TWINX_AIUP_L:
+        case ASI_BLK_AIUP_4V:
+        case ASI_BLK_AIUP_L_4V:
+        case ASI_BLK_AIUP:
+        case ASI_BLK_AIUPL:
             mem_idx = MMU_USER_IDX;
             break;
         case ASI_AIUS:  /* As if user secondary */
         case ASI_AIUSL: /* As if user secondary LE */
         case ASI_TWINX_AIUS:
         case ASI_TWINX_AIUS_L:
+        case ASI_BLK_AIUS_4V:
+        case ASI_BLK_AIUS_L_4V:
+        case ASI_BLK_AIUS:
+        case ASI_BLK_AIUSL:
             mem_idx = MMU_USER_SECONDARY_IDX;
             break;
         case ASI_S:  /* Secondary */
         case ASI_SL: /* Secondary LE */
         case ASI_TWINX_S:
         case ASI_TWINX_SL:
+        case ASI_BLK_COMMIT_S:
+        case ASI_BLK_S:
+        case ASI_BLK_SL:
+        case ASI_FL8_S:
+        case ASI_FL8_SL:
+        case ASI_FL16_S:
+        case ASI_FL16_SL:
             if (mem_idx == MMU_USER_IDX) {
                 mem_idx = MMU_USER_SECONDARY_IDX;
             } else if (mem_idx == MMU_KERNEL_IDX) {
@@ -2077,6 +2094,13 @@ static DisasASI get_asi(DisasContext *dc, int insn, TCGMemOp memop)
         case ASI_PL: /* Primary LE */
         case ASI_TWINX_P:
         case ASI_TWINX_PL:
+        case ASI_BLK_COMMIT_P:
+        case ASI_BLK_P:
+        case ASI_BLK_PL:
+        case ASI_FL8_P:
+        case ASI_FL8_PL:
+        case ASI_FL16_P:
+        case ASI_FL16_PL:
             break;
         }
         switch (asi) {
@@ -2104,6 +2128,36 @@ static DisasASI get_asi(DisasContext *dc, int insn, TCGMemOp memop)
         case ASI_TWINX_SL:
             type = GET_ASI_DTWINX;
             break;
+        case ASI_BLK_COMMIT_P:
+        case ASI_BLK_COMMIT_S:
+        case ASI_BLK_AIUP_4V:
+        case ASI_BLK_AIUP_L_4V:
+        case ASI_BLK_AIUP:
+        case ASI_BLK_AIUPL:
+        case ASI_BLK_AIUS_4V:
+        case ASI_BLK_AIUS_L_4V:
+        case ASI_BLK_AIUS:
+        case ASI_BLK_AIUSL:
+        case ASI_BLK_S:
+        case ASI_BLK_SL:
+        case ASI_BLK_P:
+        case ASI_BLK_PL:
+            type = GET_ASI_BLOCK;
+            break;
+        case ASI_FL8_S:
+        case ASI_FL8_SL:
+        case ASI_FL8_P:
+        case ASI_FL8_PL:
+            memop = MO_UB;
+            type = GET_ASI_SHORT;
+            break;
+        case ASI_FL16_S:
+        case ASI_FL16_SL:
+        case ASI_FL16_P:
+        case ASI_FL16_PL:
+            memop = MO_TEUW;
+            type = GET_ASI_SHORT;
+            break;
         }
         /* The little-endian asis all have bit 3 set.  */
         if (asi & 8) {
@@ -2309,6 +2363,40 @@ static void gen_ldf_asi(DisasContext *dc, TCGv addr,
         }
         break;
 
+    case GET_ASI_BLOCK:
+        /* Valid for lddfa on aligned registers only.  */
+        if (size == 8 && (rd & 7) == 0) {
+            TCGv eight;
+            int i;
+
+            gen_check_align(addr, 0x3f);
+            gen_address_mask(dc, addr);
+
+            eight = tcg_const_tl(8);
+            for (i = 0; ; ++i) {
+                tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + i], addr,
+                                    da.mem_idx, da.memop);
+                if (i == 7) {
+                    break;
+                }
+                tcg_gen_add_tl(addr, addr, eight);
+            }
+            tcg_temp_free(eight);
+        } else {
+            gen_exception(dc, TT_ILL_INSN);
+        }
+        break;
+
+    case GET_ASI_SHORT:
+        /* Valid for lddfa only.  */
+        if (size == 8) {
+            gen_address_mask(dc, addr);
+            tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
+        } else {
+            gen_exception(dc, TT_ILL_INSN);
+        }
+        break;
+
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
@@ -2355,6 +2443,40 @@ static void gen_stf_asi(DisasContext *dc, TCGv addr,
         }
         break;
 
+    case GET_ASI_BLOCK:
+        /* Valid for stdfa on aligned registers only.  */
+        if (size == 8 && (rd & 7) == 0) {
+            TCGv eight;
+            int i;
+
+            gen_check_align(addr, 0x3f);
+            gen_address_mask(dc, addr);
+
+            eight = tcg_const_tl(8);
+            for (i = 0; ; ++i) {
+                tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + i], addr,
+                                    da.mem_idx, da.memop);
+                if (i == 7) {
+                    break;
+                }
+                tcg_gen_add_tl(addr, addr, eight);
+            }
+            tcg_temp_free(eight);
+        } else {
+            gen_exception(dc, TT_ILL_INSN);
+        }
+        break;
+
+    case GET_ASI_SHORT:
+        /* Valid for stdfa only.  */
+        if (size == 8) {
+            gen_address_mask(dc, addr);
+            tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx, da.memop);
+        } else {
+            gen_exception(dc, TT_ILL_INSN);
+        }
+        break;
+
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 20/24] target-sparc: Remove helper_ldf_asi, helper_stf_asi
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (18 preceding siblings ...)
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 19/24] target-sparc: Directly implement block and short " Richard Henderson
@ 2016-06-28  0:39 ` Richard Henderson
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 21/24] target-sparc: Use explicit writes to cpu_fsr Richard Henderson
                   ` (4 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

We've now implemented all fp asis inline, except for the no-fault
memory reads.  The latter can be passed directly to helper_ld_asi.

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/helper.h      |   2 -
 target-sparc/ldst_helper.c | 148 ---------------------------------------------
 target-sparc/translate.c   |  48 ++++++++++-----
 3 files changed, 32 insertions(+), 166 deletions(-)

diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index f5afc8d..b506706 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -18,8 +18,6 @@ DEF_HELPER_2(wrcwp, void, env, tl)
 DEF_HELPER_FLAGS_2(array8, TCG_CALL_NO_RWG_SE, tl, tl, tl)
 DEF_HELPER_FLAGS_1(popc, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_3(ldda_asi, TCG_CALL_NO_WG, void, env, tl, int)
-DEF_HELPER_5(ldf_asi, void, env, tl, int, int, int)
-DEF_HELPER_FLAGS_5(stf_asi, TCG_CALL_NO_WG, void, env, tl, int, int, int)
 DEF_HELPER_FLAGS_5(casx_asi, TCG_CALL_NO_WG, tl, env, tl, tl, tl, i32)
 DEF_HELPER_FLAGS_2(set_softint, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_2(clear_softint, TCG_CALL_NO_RWG, void, env, i64)
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 240c1bc..28cc82d 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -2161,154 +2161,6 @@ void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi)
     QT0.low = l;
 }
 
-void helper_ldf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
-                    int rd)
-{
-    unsigned int i;
-    target_ulong val;
-
-    helper_check_align(env, addr, 3);
-    addr = asi_address_mask(env, asi, addr);
-
-    switch (asi) {
-    case ASI_BLK_P:  /* UA2007/JPS1 Block load primary */
-    case ASI_BLK_S:  /* UA2007/JPS1 Block load secondary */
-    case ASI_BLK_PL: /* UA2007/JPS1 Block load primary LE */
-    case ASI_BLK_SL: /* UA2007/JPS1 Block load secondary LE */
-        if (rd & 7) {
-            helper_raise_exception(env, TT_ILL_INSN);
-            return;
-        }
-        helper_check_align(env, addr, 0x3f);
-        for (i = 0; i < 8; i++, rd += 2, addr += 8) {
-            env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi & 0x8f, MO_Q);
-        }
-        return;
-
-    case ASI_BLK_AIUP_4V:   /* UA2007 Block load primary, user privilege */
-    case ASI_BLK_AIUS_4V:   /* UA2007 Block load secondary, user privilege */
-    case ASI_BLK_AIUP_L_4V: /* UA2007 Block load primary LE, user privilege */
-    case ASI_BLK_AIUS_L_4V: /* UA2007 Block load secondary LE, user privilege */
-    case ASI_BLK_AIUP:  /* JPS1 Block load primary, user privilege */
-    case ASI_BLK_AIUS:  /* JPS1 Block load secondary, user privilege */
-    case ASI_BLK_AIUPL: /* JPS1 Block load primary LE, user privilege */
-    case ASI_BLK_AIUSL: /* JPS1 Block load secondary LE, user privilege */
-        if (rd & 7) {
-            helper_raise_exception(env, TT_ILL_INSN);
-            return;
-        }
-        helper_check_align(env, addr, 0x3f);
-        for (i = 0; i < 8; i++, rd += 2, addr += 8) {
-            env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi & 0x19, MO_Q);
-        }
-        return;
-
-    default:
-        break;
-    }
-
-    switch (size) {
-    default:
-    case 4:
-        val = helper_ld_asi(env, addr, asi, MO_UL);
-        if (rd & 1) {
-            env->fpr[rd / 2].l.lower = val;
-        } else {
-            env->fpr[rd / 2].l.upper = val;
-        }
-        break;
-    case 8:
-        env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi, MO_Q);
-        break;
-    case 16:
-        env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi, MO_Q);
-        env->fpr[rd / 2 + 1].ll = helper_ld_asi(env, addr + 8, asi, MO_Q);
-        break;
-    }
-}
-
-void helper_stf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
-                    int rd)
-{
-    unsigned int i;
-    target_ulong val;
-
-    addr = asi_address_mask(env, asi, addr);
-
-    switch (asi) {
-    case ASI_BLK_COMMIT_P: /* UA2007/JPS1 Block store primary (cache flush) */
-    case ASI_BLK_COMMIT_S: /* UA2007/JPS1 Block store secondary (cache flush) */
-    case ASI_BLK_P: /* UA2007/JPS1 Block store primary */
-    case ASI_BLK_S: /* UA2007/JPS1 Block store secondary */
-    case ASI_BLK_PL: /* UA2007/JPS1 Block store primary LE */
-    case ASI_BLK_SL: /* UA2007/JPS1 Block store secondary LE */
-        if (rd & 7) {
-            helper_raise_exception(env, TT_ILL_INSN);
-            return;
-        }
-        helper_check_align(env, addr, 0x3f);
-        for (i = 0; i < 8; i++, rd += 2, addr += 8) {
-            helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi & 0x8f, MO_Q);
-        }
-
-        return;
-    case ASI_BLK_AIUP_4V: /* UA2007 Block load primary, user privilege */
-    case ASI_BLK_AIUS_4V: /* UA2007 Block load secondary, user privilege */
-    case ASI_BLK_AIUP_L_4V: /* UA2007 Block load primary LE, user privilege */
-    case ASI_BLK_AIUS_L_4V: /* UA2007 Block load secondary LE, user privilege */
-    case ASI_BLK_AIUP: /* JPS1 Block store primary, user privilege */
-    case ASI_BLK_AIUS: /* JPS1 Block store secondary, user privilege */
-    case ASI_BLK_AIUPL: /* JPS1 Block load primary LE, user privilege */
-    case ASI_BLK_AIUSL: /* JPS1 Block load secondary LE, user privilege */
-        if (rd & 7) {
-            helper_raise_exception(env, TT_ILL_INSN);
-            return;
-        }
-        helper_check_align(env, addr, 0x3f);
-        for (i = 0; i < 8; i++, rd += 2, addr += 8) {
-            helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi & 0x19, MO_Q);
-        }
-
-        return;
-    case ASI_FL16_P: /* 16-bit floating point load primary */
-    case ASI_FL16_S: /* 16-bit floating point load secondary */
-    case ASI_FL16_PL: /* 16-bit floating point load primary, LE */
-    case ASI_FL16_SL: /* 16-bit floating point load secondary, LE */
-        val = env->fpr[rd / 2].l.lower;
-        helper_st_asi(env, addr, val, asi & 0x8d, MO_UW);
-        return;
-    case ASI_FL8_P: /* 8-bit floating point load primary */
-    case ASI_FL8_S: /* 8-bit floating point load secondary */
-    case ASI_FL8_PL: /* 8-bit floating point load primary, LE */
-    case ASI_FL8_SL: /* 8-bit floating point load secondary, LE */
-        val = env->fpr[rd / 2].l.lower;
-        helper_st_asi(env, addr, val, asi & 0x8d, MO_UB);
-        return;
-    default:
-        helper_check_align(env, addr, 3);
-        break;
-    }
-
-    switch (size) {
-    default:
-    case 4:
-        if (rd & 1) {
-            val = env->fpr[rd / 2].l.lower;
-        } else {
-            val = env->fpr[rd / 2].l.upper;
-        }
-        helper_st_asi(env, addr, val, asi, MO_UL);
-        break;
-    case 8:
-        helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi, MO_Q);
-        break;
-    case 16:
-        helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi, MO_Q);
-        helper_st_asi(env, addr + 8, env->fpr[rd / 2 + 1].ll, asi, MO_Q);
-        break;
-    }
-}
-
 target_ulong helper_casx_asi(CPUSPARCState *env, target_ulong addr,
                              target_ulong val1, target_ulong val2,
                              uint32_t asi)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index cee1e5c..2cf9f83 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2400,13 +2400,36 @@ static void gen_ldf_asi(DisasContext *dc, TCGv addr,
     default:
         {
             TCGv_i32 r_asi = tcg_const_i32(da.asi);
-            TCGv_i32 r_size = tcg_const_i32(size);
-            TCGv_i32 r_rd = tcg_const_i32(rd);
+            TCGv_i32 r_mop = tcg_const_i32(da.memop);
 
             save_state(dc);
-            gen_helper_ldf_asi(cpu_env, addr, r_asi, r_size, r_rd);
-            tcg_temp_free_i32(r_rd);
-            tcg_temp_free_i32(r_size);
+            /* According to the table in the UA2011 manual, the only
+               other asis that are valid for ldfa/lddfa/ldqfa are
+               the NO_FAULT asis.  We still need a helper for these,
+               but we can just use the integer asi helper for them.  */
+            switch (size) {
+            case 4:
+                {
+                    TCGv d64 = tcg_temp_new_i64();
+                    gen_helper_ld_asi(d64, cpu_env, addr, r_asi, r_mop);
+                    d32 = gen_dest_fpr_F(dc);
+                    tcg_gen_extrl_i64_i32(d32, d64);
+                    tcg_temp_free_i64(d64);
+                    gen_store_fpr_F(dc, rd, d32);
+                }
+                break;
+            case 8:
+                gen_helper_ld_asi(cpu_fpr[rd / 2], cpu_env, addr, r_asi, r_mop);
+                break;
+            case 16:
+                gen_helper_ld_asi(cpu_fpr[rd / 2], cpu_env, addr, r_asi, r_mop);
+                tcg_gen_addi_tl(addr, addr, 8);
+                gen_helper_ld_asi(cpu_fpr[rd/2+1], cpu_env, addr, r_asi, r_mop);
+                break;
+            default:
+                g_assert_not_reached();
+            }
+            tcg_temp_free_i32(r_mop);
             tcg_temp_free_i32(r_asi);
         }
         break;
@@ -2478,17 +2501,10 @@ static void gen_stf_asi(DisasContext *dc, TCGv addr,
         break;
 
     default:
-        {
-            TCGv_i32 r_asi = tcg_const_i32(da.asi);
-            TCGv_i32 r_size = tcg_const_i32(size);
-            TCGv_i32 r_rd = tcg_const_i32(rd);
-
-            save_state(dc);
-            gen_helper_stf_asi(cpu_env, addr, r_asi, r_size, r_rd);
-            tcg_temp_free_i32(r_rd);
-            tcg_temp_free_i32(r_size);
-            tcg_temp_free_i32(r_asi);
-        }
+        /* According to the table in the UA2011 manual, the only
+           other asis that are valid for ldfa/lddfa/ldqfa are
+           the PST* asis, which aren't currently handled.  */
+        gen_exception(dc, TT_ILL_INSN);
         break;
     }
 }
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 21/24] target-sparc: Use explicit writes to cpu_fsr
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (19 preceding siblings ...)
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 20/24] target-sparc: Remove helper_ldf_asi, helper_stf_asi Richard Henderson
@ 2016-06-28  0:39 ` Richard Henderson
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 22/24] target-sparc: Use cpu_fsr in stfsr Richard Henderson
                   ` (3 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

By arranging for explicit writes to cpu_fsr after floating point
operations, we are able to mark the helpers as not writing to
tcg globals, which means that we don't need to invalidate the
integer register set across said calls.

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/fop_helper.c | 223 +++++++++++++++-------------------------------
 target-sparc/helper.h     | 112 +++++++++++------------
 target-sparc/translate.c  |  76 +++++++++-------
 3 files changed, 174 insertions(+), 237 deletions(-)

diff --git a/target-sparc/fop_helper.c b/target-sparc/fop_helper.c
index 0830643..cdc58ea 100644
--- a/target-sparc/fop_helper.c
+++ b/target-sparc/fop_helper.c
@@ -24,43 +24,46 @@
 #define QT0 (env->qt0)
 #define QT1 (env->qt1)
 
-static void check_ieee_exceptions(CPUSPARCState *env)
+target_ulong helper_check_ieee_exceptions(CPUSPARCState *env)
 {
-    target_ulong status;
+    target_ulong status = get_float_exception_flags(&env->fp_status);
+    target_ulong fsr = env->fsr;
+
+    if (unlikely(status)) {
+        /* Keep exception flags clear for next time.  */
+        set_float_exception_flags(0, &env->fp_status);
 
-    status = get_float_exception_flags(&env->fp_status);
-    if (status) {
         /* Copy IEEE 754 flags into FSR */
         if (status & float_flag_invalid) {
-            env->fsr |= FSR_NVC;
+            fsr |= FSR_NVC;
         }
         if (status & float_flag_overflow) {
-            env->fsr |= FSR_OFC;
+            fsr |= FSR_OFC;
         }
         if (status & float_flag_underflow) {
-            env->fsr |= FSR_UFC;
+            fsr |= FSR_UFC;
         }
         if (status & float_flag_divbyzero) {
-            env->fsr |= FSR_DZC;
+            fsr |= FSR_DZC;
         }
         if (status & float_flag_inexact) {
-            env->fsr |= FSR_NXC;
+            fsr |= FSR_NXC;
         }
 
-        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
-            /* Unmasked exception, generate a trap */
-            env->fsr |= FSR_FTT_IEEE_EXCP;
+        if ((fsr & FSR_CEXC_MASK) & ((fsr & FSR_TEM_MASK) >> 23)) {
+            /* Unmasked exception, generate a trap.  Note that while
+               the helper is marked as NO_WG, we can get away with
+               writing to cpu state along the exception path, since
+               TCG generated code will never see the write.  */
+            env->fsr = fsr | FSR_FTT_IEEE_EXCP;
             helper_raise_exception(env, TT_FP_EXCP);
         } else {
             /* Accumulate exceptions */
-            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
+            fsr |= (fsr & FSR_CEXC_MASK) << 5;
         }
     }
-}
 
-static inline void clear_float_exceptions(CPUSPARCState *env)
-{
-    set_float_exception_flags(0, &env->fp_status);
+    return fsr;
 }
 
 #define F_HELPER(name, p) void helper_f##name##p(CPUSPARCState *env)
@@ -69,26 +72,16 @@ static inline void clear_float_exceptions(CPUSPARCState *env)
     float32 helper_f ## name ## s (CPUSPARCState *env, float32 src1, \
                                    float32 src2)                \
     {                                                           \
-        float32 ret;                                            \
-        clear_float_exceptions(env);                            \
-        ret = float32_ ## name (src1, src2, &env->fp_status);   \
-        check_ieee_exceptions(env);                             \
-        return ret;                                             \
+        return float32_ ## name (src1, src2, &env->fp_status);  \
     }                                                           \
     float64 helper_f ## name ## d (CPUSPARCState * env, float64 src1,\
                                    float64 src2)                \
     {                                                           \
-        float64 ret;                                            \
-        clear_float_exceptions(env);                            \
-        ret = float64_ ## name (src1, src2, &env->fp_status);   \
-        check_ieee_exceptions(env);                             \
-        return ret;                                             \
+        return float64_ ## name (src1, src2, &env->fp_status);  \
     }                                                           \
     F_HELPER(name, q)                                           \
     {                                                           \
-        clear_float_exceptions(env);                            \
         QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
-        check_ieee_exceptions(env);                             \
     }
 
 F_BINOP(add);
@@ -99,22 +92,16 @@ F_BINOP(div);
 
 float64 helper_fsmuld(CPUSPARCState *env, float32 src1, float32 src2)
 {
-    float64 ret;
-    clear_float_exceptions(env);
-    ret = float64_mul(float32_to_float64(src1, &env->fp_status),
-                      float32_to_float64(src2, &env->fp_status),
-                      &env->fp_status);
-    check_ieee_exceptions(env);
-    return ret;
+    return float64_mul(float32_to_float64(src1, &env->fp_status),
+                       float32_to_float64(src2, &env->fp_status),
+                       &env->fp_status);
 }
 
 void helper_fdmulq(CPUSPARCState *env, float64 src1, float64 src2)
 {
-    clear_float_exceptions(env);
     QT0 = float128_mul(float64_to_float128(src1, &env->fp_status),
                        float64_to_float128(src2, &env->fp_status),
                        &env->fp_status);
-    check_ieee_exceptions(env);
 }
 
 float32 helper_fnegs(float32 src)
@@ -137,48 +124,32 @@ F_HELPER(neg, q)
 /* Integer to float conversion.  */
 float32 helper_fitos(CPUSPARCState *env, int32_t src)
 {
-    /* Inexact error possible converting int to float.  */
-    float32 ret;
-    clear_float_exceptions(env);
-    ret = int32_to_float32(src, &env->fp_status);
-    check_ieee_exceptions(env);
-    return ret;
+    return int32_to_float32(src, &env->fp_status);
 }
 
 float64 helper_fitod(CPUSPARCState *env, int32_t src)
 {
-    /* No possible exceptions converting int to double.  */
     return int32_to_float64(src, &env->fp_status);
 }
 
 void helper_fitoq(CPUSPARCState *env, int32_t src)
 {
-    /* No possible exceptions converting int to long double.  */
     QT0 = int32_to_float128(src, &env->fp_status);
 }
 
 #ifdef TARGET_SPARC64
 float32 helper_fxtos(CPUSPARCState *env, int64_t src)
 {
-    float32 ret;
-    clear_float_exceptions(env);
-    ret = int64_to_float32(src, &env->fp_status);
-    check_ieee_exceptions(env);
-    return ret;
+    return int64_to_float32(src, &env->fp_status);
 }
 
 float64 helper_fxtod(CPUSPARCState *env, int64_t src)
 {
-    float64 ret;
-    clear_float_exceptions(env);
-    ret = int64_to_float64(src, &env->fp_status);
-    check_ieee_exceptions(env);
-    return ret;
+    return int64_to_float64(src, &env->fp_status);
 }
 
 void helper_fxtoq(CPUSPARCState *env, int64_t src)
 {
-    /* No possible exceptions converting long long to long double.  */
     QT0 = int64_to_float128(src, &env->fp_status);
 }
 #endif
@@ -187,108 +158,64 @@ void helper_fxtoq(CPUSPARCState *env, int64_t src)
 /* floating point conversion */
 float32 helper_fdtos(CPUSPARCState *env, float64 src)
 {
-    float32 ret;
-    clear_float_exceptions(env);
-    ret = float64_to_float32(src, &env->fp_status);
-    check_ieee_exceptions(env);
-    return ret;
+    return float64_to_float32(src, &env->fp_status);
 }
 
 float64 helper_fstod(CPUSPARCState *env, float32 src)
 {
-    float64 ret;
-    clear_float_exceptions(env);
-    ret = float32_to_float64(src, &env->fp_status);
-    check_ieee_exceptions(env);
-    return ret;
+    return float32_to_float64(src, &env->fp_status);
 }
 
 float32 helper_fqtos(CPUSPARCState *env)
 {
-    float32 ret;
-    clear_float_exceptions(env);
-    ret = float128_to_float32(QT1, &env->fp_status);
-    check_ieee_exceptions(env);
-    return ret;
+    return float128_to_float32(QT1, &env->fp_status);
 }
 
 void helper_fstoq(CPUSPARCState *env, float32 src)
 {
-    clear_float_exceptions(env);
     QT0 = float32_to_float128(src, &env->fp_status);
-    check_ieee_exceptions(env);
 }
 
 float64 helper_fqtod(CPUSPARCState *env)
 {
-    float64 ret;
-    clear_float_exceptions(env);
-    ret = float128_to_float64(QT1, &env->fp_status);
-    check_ieee_exceptions(env);
-    return ret;
+    return float128_to_float64(QT1, &env->fp_status);
 }
 
 void helper_fdtoq(CPUSPARCState *env, float64 src)
 {
-    clear_float_exceptions(env);
     QT0 = float64_to_float128(src, &env->fp_status);
-    check_ieee_exceptions(env);
 }
 
 /* Float to integer conversion.  */
 int32_t helper_fstoi(CPUSPARCState *env, float32 src)
 {
-    int32_t ret;
-    clear_float_exceptions(env);
-    ret = float32_to_int32_round_to_zero(src, &env->fp_status);
-    check_ieee_exceptions(env);
-    return ret;
+    return float32_to_int32_round_to_zero(src, &env->fp_status);
 }
 
 int32_t helper_fdtoi(CPUSPARCState *env, float64 src)
 {
-    int32_t ret;
-    clear_float_exceptions(env);
-    ret = float64_to_int32_round_to_zero(src, &env->fp_status);
-    check_ieee_exceptions(env);
-    return ret;
+    return float64_to_int32_round_to_zero(src, &env->fp_status);
 }
 
 int32_t helper_fqtoi(CPUSPARCState *env)
 {
-    int32_t ret;
-    clear_float_exceptions(env);
-    ret = float128_to_int32_round_to_zero(QT1, &env->fp_status);
-    check_ieee_exceptions(env);
-    return ret;
+    return float128_to_int32_round_to_zero(QT1, &env->fp_status);
 }
 
 #ifdef TARGET_SPARC64
 int64_t helper_fstox(CPUSPARCState *env, float32 src)
 {
-    int64_t ret;
-    clear_float_exceptions(env);
-    ret = float32_to_int64_round_to_zero(src, &env->fp_status);
-    check_ieee_exceptions(env);
-    return ret;
+    return float32_to_int64_round_to_zero(src, &env->fp_status);
 }
 
 int64_t helper_fdtox(CPUSPARCState *env, float64 src)
 {
-    int64_t ret;
-    clear_float_exceptions(env);
-    ret = float64_to_int64_round_to_zero(src, &env->fp_status);
-    check_ieee_exceptions(env);
-    return ret;
+    return float64_to_int64_round_to_zero(src, &env->fp_status);
 }
 
 int64_t helper_fqtox(CPUSPARCState *env)
 {
-    int64_t ret;
-    clear_float_exceptions(env);
-    ret = float128_to_int64_round_to_zero(QT1, &env->fp_status);
-    check_ieee_exceptions(env);
-    return ret;
+    return float128_to_int64_round_to_zero(QT1, &env->fp_status);
 }
 #endif
 
@@ -311,87 +238,79 @@ void helper_fabsq(CPUSPARCState *env)
 
 float32 helper_fsqrts(CPUSPARCState *env, float32 src)
 {
-    float32 ret;
-    clear_float_exceptions(env);
-    ret = float32_sqrt(src, &env->fp_status);
-    check_ieee_exceptions(env);
-    return ret;
+    return float32_sqrt(src, &env->fp_status);
 }
 
 float64 helper_fsqrtd(CPUSPARCState *env, float64 src)
 {
-    float64 ret;
-    clear_float_exceptions(env);
-    ret = float64_sqrt(src, &env->fp_status);
-    check_ieee_exceptions(env);
-    return ret;
+    return float64_sqrt(src, &env->fp_status);
 }
 
 void helper_fsqrtq(CPUSPARCState *env)
 {
-    clear_float_exceptions(env);
     QT0 = float128_sqrt(QT1, &env->fp_status);
-    check_ieee_exceptions(env);
 }
 
 #define GEN_FCMP(name, size, reg1, reg2, FS, E)                         \
-    void glue(helper_, name) (CPUSPARCState *env)                       \
+    target_ulong glue(helper_, name) (CPUSPARCState *env)               \
     {                                                                   \
         int ret;                                                        \
-        clear_float_exceptions(env);                                    \
+        target_ulong fsr;                                               \
         if (E) {                                                        \
             ret = glue(size, _compare)(reg1, reg2, &env->fp_status);    \
         } else {                                                        \
             ret = glue(size, _compare_quiet)(reg1, reg2,                \
                                              &env->fp_status);          \
         }                                                               \
-        check_ieee_exceptions(env);                                     \
+        fsr = helper_check_ieee_exceptions(env);                        \
         switch (ret) {                                                  \
         case float_relation_unordered:                                  \
-            env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                    \
-            env->fsr |= FSR_NVA;                                        \
+            fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                         \
+            fsr |= FSR_NVA;                                             \
             break;                                                      \
         case float_relation_less:                                       \
-            env->fsr &= ~(FSR_FCC1) << FS;                              \
-            env->fsr |= FSR_FCC0 << FS;                                 \
+            fsr &= ~(FSR_FCC1) << FS;                                   \
+            fsr |= FSR_FCC0 << FS;                                      \
             break;                                                      \
         case float_relation_greater:                                    \
-            env->fsr &= ~(FSR_FCC0) << FS;                              \
-            env->fsr |= FSR_FCC1 << FS;                                 \
+            fsr &= ~(FSR_FCC0) << FS;                                   \
+            fsr |= FSR_FCC1 << FS;                                      \
             break;                                                      \
         default:                                                        \
-            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
+            fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                      \
             break;                                                      \
         }                                                               \
+        return fsr;                                                     \
     }
 #define GEN_FCMP_T(name, size, FS, E)                                   \
-    void glue(helper_, name)(CPUSPARCState *env, size src1, size src2)  \
+    target_ulong glue(helper_, name)(CPUSPARCState *env, size src1, size src2)\
     {                                                                   \
         int ret;                                                        \
-        clear_float_exceptions(env);                                    \
+        target_ulong fsr;                                               \
         if (E) {                                                        \
             ret = glue(size, _compare)(src1, src2, &env->fp_status);    \
         } else {                                                        \
             ret = glue(size, _compare_quiet)(src1, src2,                \
                                              &env->fp_status);          \
         }                                                               \
-        check_ieee_exceptions(env);                                     \
+        fsr = helper_check_ieee_exceptions(env);                        \
         switch (ret) {                                                  \
         case float_relation_unordered:                                  \
-            env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                    \
+            fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                         \
             break;                                                      \
         case float_relation_less:                                       \
-            env->fsr &= ~(FSR_FCC1 << FS);                              \
-            env->fsr |= FSR_FCC0 << FS;                                 \
+            fsr &= ~(FSR_FCC1 << FS);                                   \
+            fsr |= FSR_FCC0 << FS;                                      \
             break;                                                      \
         case float_relation_greater:                                    \
-            env->fsr &= ~(FSR_FCC0 << FS);                              \
-            env->fsr |= FSR_FCC1 << FS;                                 \
+            fsr &= ~(FSR_FCC0 << FS);                                   \
+            fsr |= FSR_FCC1 << FS;                                      \
             break;                                                      \
         default:                                                        \
-            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
+            fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                      \
             break;                                                      \
         }                                                               \
+        return fsr;                                                     \
     }
 
 GEN_FCMP_T(fcmps, float32, 0, 0);
@@ -431,11 +350,11 @@ GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
 #undef GEN_FCMP_T
 #undef GEN_FCMP
 
-static inline void set_fsr(CPUSPARCState *env)
+static void set_fsr(CPUSPARCState *env, target_ulong fsr)
 {
     int rnd_mode;
 
-    switch (env->fsr & FSR_RD_MASK) {
+    switch (fsr & FSR_RD_MASK) {
     case FSR_RD_NEAREST:
         rnd_mode = float_round_nearest_even;
         break;
@@ -453,16 +372,20 @@ static inline void set_fsr(CPUSPARCState *env)
     set_float_rounding_mode(rnd_mode, &env->fp_status);
 }
 
-void helper_ldfsr(CPUSPARCState *env, uint32_t new_fsr)
+target_ulong helper_ldfsr(CPUSPARCState *env, target_ulong old_fsr,
+                          uint32_t new_fsr)
 {
-    env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
-    set_fsr(env);
+    old_fsr = (new_fsr & FSR_LDFSR_MASK) | (old_fsr & FSR_LDFSR_OLDMASK);
+    set_fsr(env, old_fsr);
+    return old_fsr;
 }
 
 #ifdef TARGET_SPARC64
-void helper_ldxfsr(CPUSPARCState *env, uint64_t new_fsr)
+target_ulong helper_ldxfsr(CPUSPARCState *env, target_ulong old_fsr,
+                           uint64_t new_fsr)
 {
-    env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
-    set_fsr(env);
+    old_fsr = (new_fsr & FSR_LDXFSR_MASK) | (old_fsr & FSR_LDXFSR_OLDMASK);
+    set_fsr(env, old_fsr);
+    return old_fsr;
 }
 #endif
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index b506706..caa2a89 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -49,86 +49,88 @@ DEF_HELPER_FLAGS_3(stqf, TCG_CALL_NO_WG, void, env, tl, int)
 DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, i32)
 DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32)
 #endif
-DEF_HELPER_2(ldfsr, void, env, i32)
+DEF_HELPER_FLAGS_1(check_ieee_exceptions, TCG_CALL_NO_WG, tl, env)
+DEF_HELPER_FLAGS_3(ldfsr, TCG_CALL_NO_RWG, tl, env, tl, i32)
 DEF_HELPER_FLAGS_1(fabss, TCG_CALL_NO_RWG_SE, f32, f32)
-DEF_HELPER_2(fsqrts, f32, env, f32)
-DEF_HELPER_2(fsqrtd, f64, env, f64)
-DEF_HELPER_3(fcmps, void, env, f32, f32)
-DEF_HELPER_3(fcmpd, void, env, f64, f64)
-DEF_HELPER_3(fcmpes, void, env, f32, f32)
-DEF_HELPER_3(fcmped, void, env, f64, f64)
-DEF_HELPER_1(fsqrtq, void, env)
-DEF_HELPER_1(fcmpq, void, env)
-DEF_HELPER_1(fcmpeq, void, env)
+DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_RWG, f32, env, f32)
+DEF_HELPER_FLAGS_2(fsqrtd, TCG_CALL_NO_RWG, f64, env, f64)
+DEF_HELPER_FLAGS_3(fcmps, TCG_CALL_NO_WG, tl, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, tl, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmpes, TCG_CALL_NO_WG, tl, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, tl, env, f64, f64)
+DEF_HELPER_FLAGS_1(fsqrtq, TCG_CALL_NO_RWG, void, env)
+DEF_HELPER_FLAGS_1(fcmpq, TCG_CALL_NO_WG, tl, env)
+DEF_HELPER_FLAGS_1(fcmpeq, TCG_CALL_NO_WG, tl, env)
 #ifdef TARGET_SPARC64
-DEF_HELPER_2(ldxfsr, void, env, i64)
+DEF_HELPER_FLAGS_3(ldxfsr, TCG_CALL_NO_RWG, tl, env, tl, i64)
 DEF_HELPER_FLAGS_1(fabsd, TCG_CALL_NO_RWG_SE, f64, f64)
-DEF_HELPER_3(fcmps_fcc1, void, env, f32, f32)
-DEF_HELPER_3(fcmps_fcc2, void, env, f32, f32)
-DEF_HELPER_3(fcmps_fcc3, void, env, f32, f32)
-DEF_HELPER_3(fcmpd_fcc1, void, env, f64, f64)
-DEF_HELPER_3(fcmpd_fcc2, void, env, f64, f64)
-DEF_HELPER_3(fcmpd_fcc3, void, env, f64, f64)
-DEF_HELPER_3(fcmpes_fcc1, void, env, f32, f32)
-DEF_HELPER_3(fcmpes_fcc2, void, env, f32, f32)
-DEF_HELPER_3(fcmpes_fcc3, void, env, f32, f32)
-DEF_HELPER_3(fcmped_fcc1, void, env, f64, f64)
-DEF_HELPER_3(fcmped_fcc2, void, env, f64, f64)
-DEF_HELPER_3(fcmped_fcc3, void, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmps_fcc1, TCG_CALL_NO_WG, tl, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmps_fcc2, TCG_CALL_NO_WG, tl, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmps_fcc3, TCG_CALL_NO_WG, tl, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmpd_fcc1, TCG_CALL_NO_WG, tl, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmpd_fcc2, TCG_CALL_NO_WG, tl, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmpd_fcc3, TCG_CALL_NO_WG, tl, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmpes_fcc1, TCG_CALL_NO_WG, tl, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmpes_fcc2, TCG_CALL_NO_WG, tl, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmpes_fcc3, TCG_CALL_NO_WG, tl, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmped_fcc1, TCG_CALL_NO_WG, tl, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmped_fcc2, TCG_CALL_NO_WG, tl, env, f64, f64)
+DEF_HELPER_FLAGS_3(fcmped_fcc3, TCG_CALL_NO_WG, tl, env, f64, f64)
 DEF_HELPER_FLAGS_1(fabsq, TCG_CALL_NO_RWG, void, env)
-DEF_HELPER_1(fcmpq_fcc1, void, env)
-DEF_HELPER_1(fcmpq_fcc2, void, env)
-DEF_HELPER_1(fcmpq_fcc3, void, env)
-DEF_HELPER_1(fcmpeq_fcc1, void, env)
-DEF_HELPER_1(fcmpeq_fcc2, void, env)
-DEF_HELPER_1(fcmpeq_fcc3, void, env)
+DEF_HELPER_FLAGS_1(fcmpq_fcc1, TCG_CALL_NO_WG, tl, env)
+DEF_HELPER_FLAGS_1(fcmpq_fcc2, TCG_CALL_NO_WG, tl, env)
+DEF_HELPER_FLAGS_1(fcmpq_fcc3, TCG_CALL_NO_WG, tl, env)
+DEF_HELPER_FLAGS_1(fcmpeq_fcc1, TCG_CALL_NO_WG, tl, env)
+DEF_HELPER_FLAGS_1(fcmpeq_fcc2, TCG_CALL_NO_WG, tl, env)
+DEF_HELPER_FLAGS_1(fcmpeq_fcc3, TCG_CALL_NO_WG, tl, env)
 #endif
 DEF_HELPER_2(raise_exception, noreturn, env, int)
-#define F_HELPER_0_1(name) DEF_HELPER_1(f ## name, void, env)
+#define F_HELPER_0_1(name) \
+  DEF_HELPER_FLAGS_1(f ## name, TCG_CALL_NO_RWG, void, env)
 
-DEF_HELPER_3(faddd, f64, env, f64, f64)
-DEF_HELPER_3(fsubd, f64, env, f64, f64)
-DEF_HELPER_3(fmuld, f64, env, f64, f64)
-DEF_HELPER_3(fdivd, f64, env, f64, f64)
+DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_RWG, f64, env, f64, f64)
+DEF_HELPER_FLAGS_3(fsubd, TCG_CALL_NO_RWG, f64, env, f64, f64)
+DEF_HELPER_FLAGS_3(fmuld, TCG_CALL_NO_RWG, f64, env, f64, f64)
+DEF_HELPER_FLAGS_3(fdivd, TCG_CALL_NO_RWG, f64, env, f64, f64)
 F_HELPER_0_1(addq)
 F_HELPER_0_1(subq)
 F_HELPER_0_1(mulq)
 F_HELPER_0_1(divq)
 
-DEF_HELPER_3(fadds, f32, env, f32, f32)
-DEF_HELPER_3(fsubs, f32, env, f32, f32)
-DEF_HELPER_3(fmuls, f32, env, f32, f32)
-DEF_HELPER_3(fdivs, f32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fadds, TCG_CALL_NO_RWG, f32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fsubs, TCG_CALL_NO_RWG, f32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fmuls, TCG_CALL_NO_RWG, f32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fdivs, TCG_CALL_NO_RWG, f32, env, f32, f32)
 
-DEF_HELPER_3(fsmuld, f64, env, f32, f32)
-DEF_HELPER_3(fdmulq, void, env, f64, f64)
+DEF_HELPER_FLAGS_3(fsmuld, TCG_CALL_NO_RWG, f64, env, f32, f32)
+DEF_HELPER_FLAGS_3(fdmulq, TCG_CALL_NO_RWG, void, env, f64, f64)
 
 DEF_HELPER_FLAGS_1(fnegs, TCG_CALL_NO_RWG_SE, f32, f32)
 DEF_HELPER_FLAGS_2(fitod, TCG_CALL_NO_RWG_SE, f64, env, s32)
 DEF_HELPER_FLAGS_2(fitoq, TCG_CALL_NO_RWG, void, env, s32)
 
-DEF_HELPER_2(fitos, f32, env, s32)
+DEF_HELPER_FLAGS_2(fitos, TCG_CALL_NO_RWG, f32, env, s32)
 
 #ifdef TARGET_SPARC64
 DEF_HELPER_FLAGS_1(fnegd, TCG_CALL_NO_RWG_SE, f64, f64)
 DEF_HELPER_FLAGS_1(fnegq, TCG_CALL_NO_RWG, void, env)
-DEF_HELPER_2(fxtos, f32, env, s64)
-DEF_HELPER_2(fxtod, f64, env, s64)
+DEF_HELPER_FLAGS_2(fxtos, TCG_CALL_NO_RWG, f32, env, s64)
+DEF_HELPER_FLAGS_2(fxtod, TCG_CALL_NO_RWG, f64, env, s64)
 DEF_HELPER_FLAGS_2(fxtoq, TCG_CALL_NO_RWG, void, env, s64)
 #endif
-DEF_HELPER_2(fdtos, f32, env, f64)
-DEF_HELPER_2(fstod, f64, env, f32)
-DEF_HELPER_1(fqtos, f32, env)
-DEF_HELPER_2(fstoq, void, env, f32)
-DEF_HELPER_1(fqtod, f64, env)
-DEF_HELPER_2(fdtoq, void, env, f64)
-DEF_HELPER_2(fstoi, s32, env, f32)
-DEF_HELPER_2(fdtoi, s32, env, f64)
-DEF_HELPER_1(fqtoi, s32, env)
+DEF_HELPER_FLAGS_2(fdtos, TCG_CALL_NO_RWG, f32, env, f64)
+DEF_HELPER_FLAGS_2(fstod, TCG_CALL_NO_RWG, f64, env, f32)
+DEF_HELPER_FLAGS_1(fqtos, TCG_CALL_NO_RWG, f32, env)
+DEF_HELPER_FLAGS_2(fstoq, TCG_CALL_NO_RWG, void, env, f32)
+DEF_HELPER_FLAGS_1(fqtod, TCG_CALL_NO_RWG, f64, env)
+DEF_HELPER_FLAGS_2(fdtoq, TCG_CALL_NO_RWG, void, env, f64)
+DEF_HELPER_FLAGS_2(fstoi, TCG_CALL_NO_RWG, s32, env, f32)
+DEF_HELPER_FLAGS_2(fdtoi, TCG_CALL_NO_RWG, s32, env, f64)
+DEF_HELPER_FLAGS_1(fqtoi, TCG_CALL_NO_RWG, s32, env)
 #ifdef TARGET_SPARC64
-DEF_HELPER_2(fstox, s64, env, f32)
-DEF_HELPER_2(fdtox, s64, env, f64)
-DEF_HELPER_1(fqtox, s64, env)
+DEF_HELPER_FLAGS_2(fstox, TCG_CALL_NO_RWG, s64, env, f32)
+DEF_HELPER_FLAGS_2(fdtox, TCG_CALL_NO_RWG, s64, env, f64)
+DEF_HELPER_FLAGS_1(fqtox, TCG_CALL_NO_RWG, s64, env)
 
 DEF_HELPER_FLAGS_2(fpmerge, TCG_CALL_NO_RWG_SE, i64, i64, i64)
 DEF_HELPER_FLAGS_2(fmul8x16, TCG_CALL_NO_RWG_SE, i64, i64, i64)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 2cf9f83..ed0853a 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1518,16 +1518,16 @@ static inline void gen_op_fcmps(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
 {
     switch (fccno) {
     case 0:
-        gen_helper_fcmps(cpu_env, r_rs1, r_rs2);
+        gen_helper_fcmps(cpu_fsr, cpu_env, r_rs1, r_rs2);
         break;
     case 1:
-        gen_helper_fcmps_fcc1(cpu_env, r_rs1, r_rs2);
+        gen_helper_fcmps_fcc1(cpu_fsr, cpu_env, r_rs1, r_rs2);
         break;
     case 2:
-        gen_helper_fcmps_fcc2(cpu_env, r_rs1, r_rs2);
+        gen_helper_fcmps_fcc2(cpu_fsr, cpu_env, r_rs1, r_rs2);
         break;
     case 3:
-        gen_helper_fcmps_fcc3(cpu_env, r_rs1, r_rs2);
+        gen_helper_fcmps_fcc3(cpu_fsr, cpu_env, r_rs1, r_rs2);
         break;
     }
 }
@@ -1536,16 +1536,16 @@ static inline void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
 {
     switch (fccno) {
     case 0:
-        gen_helper_fcmpd(cpu_env, r_rs1, r_rs2);
+        gen_helper_fcmpd(cpu_fsr, cpu_env, r_rs1, r_rs2);
         break;
     case 1:
-        gen_helper_fcmpd_fcc1(cpu_env, r_rs1, r_rs2);
+        gen_helper_fcmpd_fcc1(cpu_fsr, cpu_env, r_rs1, r_rs2);
         break;
     case 2:
-        gen_helper_fcmpd_fcc2(cpu_env, r_rs1, r_rs2);
+        gen_helper_fcmpd_fcc2(cpu_fsr, cpu_env, r_rs1, r_rs2);
         break;
     case 3:
-        gen_helper_fcmpd_fcc3(cpu_env, r_rs1, r_rs2);
+        gen_helper_fcmpd_fcc3(cpu_fsr, cpu_env, r_rs1, r_rs2);
         break;
     }
 }
@@ -1554,16 +1554,16 @@ static inline void gen_op_fcmpq(int fccno)
 {
     switch (fccno) {
     case 0:
-        gen_helper_fcmpq(cpu_env);
+        gen_helper_fcmpq(cpu_fsr, cpu_env);
         break;
     case 1:
-        gen_helper_fcmpq_fcc1(cpu_env);
+        gen_helper_fcmpq_fcc1(cpu_fsr, cpu_env);
         break;
     case 2:
-        gen_helper_fcmpq_fcc2(cpu_env);
+        gen_helper_fcmpq_fcc2(cpu_fsr, cpu_env);
         break;
     case 3:
-        gen_helper_fcmpq_fcc3(cpu_env);
+        gen_helper_fcmpq_fcc3(cpu_fsr, cpu_env);
         break;
     }
 }
@@ -1572,16 +1572,16 @@ static inline void gen_op_fcmpes(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
 {
     switch (fccno) {
     case 0:
-        gen_helper_fcmpes(cpu_env, r_rs1, r_rs2);
+        gen_helper_fcmpes(cpu_fsr, cpu_env, r_rs1, r_rs2);
         break;
     case 1:
-        gen_helper_fcmpes_fcc1(cpu_env, r_rs1, r_rs2);
+        gen_helper_fcmpes_fcc1(cpu_fsr, cpu_env, r_rs1, r_rs2);
         break;
     case 2:
-        gen_helper_fcmpes_fcc2(cpu_env, r_rs1, r_rs2);
+        gen_helper_fcmpes_fcc2(cpu_fsr, cpu_env, r_rs1, r_rs2);
         break;
     case 3:
-        gen_helper_fcmpes_fcc3(cpu_env, r_rs1, r_rs2);
+        gen_helper_fcmpes_fcc3(cpu_fsr, cpu_env, r_rs1, r_rs2);
         break;
     }
 }
@@ -1590,16 +1590,16 @@ static inline void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
 {
     switch (fccno) {
     case 0:
-        gen_helper_fcmped(cpu_env, r_rs1, r_rs2);
+        gen_helper_fcmped(cpu_fsr, cpu_env, r_rs1, r_rs2);
         break;
     case 1:
-        gen_helper_fcmped_fcc1(cpu_env, r_rs1, r_rs2);
+        gen_helper_fcmped_fcc1(cpu_fsr, cpu_env, r_rs1, r_rs2);
         break;
     case 2:
-        gen_helper_fcmped_fcc2(cpu_env, r_rs1, r_rs2);
+        gen_helper_fcmped_fcc2(cpu_fsr, cpu_env, r_rs1, r_rs2);
         break;
     case 3:
-        gen_helper_fcmped_fcc3(cpu_env, r_rs1, r_rs2);
+        gen_helper_fcmped_fcc3(cpu_fsr, cpu_env, r_rs1, r_rs2);
         break;
     }
 }
@@ -1608,16 +1608,16 @@ static inline void gen_op_fcmpeq(int fccno)
 {
     switch (fccno) {
     case 0:
-        gen_helper_fcmpeq(cpu_env);
+        gen_helper_fcmpeq(cpu_fsr, cpu_env);
         break;
     case 1:
-        gen_helper_fcmpeq_fcc1(cpu_env);
+        gen_helper_fcmpeq_fcc1(cpu_fsr, cpu_env);
         break;
     case 2:
-        gen_helper_fcmpeq_fcc2(cpu_env);
+        gen_helper_fcmpeq_fcc2(cpu_fsr, cpu_env);
         break;
     case 3:
-        gen_helper_fcmpeq_fcc3(cpu_env);
+        gen_helper_fcmpeq_fcc3(cpu_fsr, cpu_env);
         break;
     }
 }
@@ -1626,32 +1626,32 @@ static inline void gen_op_fcmpeq(int fccno)
 
 static inline void gen_op_fcmps(int fccno, TCGv r_rs1, TCGv r_rs2)
 {
-    gen_helper_fcmps(cpu_env, r_rs1, r_rs2);
+    gen_helper_fcmps(cpu_fsr, cpu_env, r_rs1, r_rs2);
 }
 
 static inline void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
 {
-    gen_helper_fcmpd(cpu_env, r_rs1, r_rs2);
+    gen_helper_fcmpd(cpu_fsr, cpu_env, r_rs1, r_rs2);
 }
 
 static inline void gen_op_fcmpq(int fccno)
 {
-    gen_helper_fcmpq(cpu_env);
+    gen_helper_fcmpq(cpu_fsr, cpu_env);
 }
 
 static inline void gen_op_fcmpes(int fccno, TCGv r_rs1, TCGv r_rs2)
 {
-    gen_helper_fcmpes(cpu_env, r_rs1, r_rs2);
+    gen_helper_fcmpes(cpu_fsr, cpu_env, r_rs1, r_rs2);
 }
 
 static inline void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2)
 {
-    gen_helper_fcmped(cpu_env, r_rs1, r_rs2);
+    gen_helper_fcmped(cpu_fsr, cpu_env, r_rs1, r_rs2);
 }
 
 static inline void gen_op_fcmpeq(int fccno)
 {
-    gen_helper_fcmpeq(cpu_env);
+    gen_helper_fcmpeq(cpu_fsr, cpu_env);
 }
 #endif
 
@@ -1687,6 +1687,7 @@ static inline void gen_fop_FF(DisasContext *dc, int rd, int rs,
     dst = gen_dest_fpr_F(dc);
 
     gen(dst, cpu_env, src);
+    gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
 
     gen_store_fpr_F(dc, rd, dst);
 }
@@ -1714,6 +1715,7 @@ static inline void gen_fop_FFF(DisasContext *dc, int rd, int rs1, int rs2,
     dst = gen_dest_fpr_F(dc);
 
     gen(dst, cpu_env, src1, src2);
+    gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
 
     gen_store_fpr_F(dc, rd, dst);
 }
@@ -1743,6 +1745,7 @@ static inline void gen_fop_DD(DisasContext *dc, int rd, int rs,
     dst = gen_dest_fpr_D(dc, rd);
 
     gen(dst, cpu_env, src);
+    gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
 
     gen_store_fpr_D(dc, rd, dst);
 }
@@ -1772,6 +1775,7 @@ static inline void gen_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2,
     dst = gen_dest_fpr_D(dc, rd);
 
     gen(dst, cpu_env, src1, src2);
+    gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
 
     gen_store_fpr_D(dc, rd, dst);
 }
@@ -1827,6 +1831,7 @@ static inline void gen_fop_QQ(DisasContext *dc, int rd, int rs,
     gen_op_load_fpr_QT1(QFPREG(rs));
 
     gen(cpu_env);
+    gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
 
     gen_op_store_QT0_fpr(QFPREG(rd));
     gen_update_fprs_dirty(QFPREG(rd));
@@ -1852,6 +1857,7 @@ static inline void gen_fop_QQQ(DisasContext *dc, int rd, int rs1, int rs2,
     gen_op_load_fpr_QT1(QFPREG(rs2));
 
     gen(cpu_env);
+    gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
 
     gen_op_store_QT0_fpr(QFPREG(rd));
     gen_update_fprs_dirty(QFPREG(rd));
@@ -1868,6 +1874,7 @@ static inline void gen_fop_DFF(DisasContext *dc, int rd, int rs1, int rs2,
     dst = gen_dest_fpr_D(dc, rd);
 
     gen(dst, cpu_env, src1, src2);
+    gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
 
     gen_store_fpr_D(dc, rd, dst);
 }
@@ -1881,6 +1888,7 @@ static inline void gen_fop_QDD(DisasContext *dc, int rd, int rs1, int rs2,
     src2 = gen_load_fpr_D(dc, rs2);
 
     gen(cpu_env, src1, src2);
+    gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
 
     gen_op_store_QT0_fpr(QFPREG(rd));
     gen_update_fprs_dirty(QFPREG(rd));
@@ -1897,6 +1905,7 @@ static inline void gen_fop_DF(DisasContext *dc, int rd, int rs,
     dst = gen_dest_fpr_D(dc, rd);
 
     gen(dst, cpu_env, src);
+    gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
 
     gen_store_fpr_D(dc, rd, dst);
 }
@@ -1926,6 +1935,7 @@ static inline void gen_fop_FD(DisasContext *dc, int rd, int rs,
     dst = gen_dest_fpr_F(dc);
 
     gen(dst, cpu_env, src);
+    gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
 
     gen_store_fpr_F(dc, rd, dst);
 }
@@ -1939,6 +1949,7 @@ static inline void gen_fop_FQ(DisasContext *dc, int rd, int rs,
     dst = gen_dest_fpr_F(dc);
 
     gen(dst, cpu_env);
+    gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
 
     gen_store_fpr_F(dc, rd, dst);
 }
@@ -1952,6 +1963,7 @@ static inline void gen_fop_DQ(DisasContext *dc, int rd, int rs,
     dst = gen_dest_fpr_D(dc, rd);
 
     gen(dst, cpu_env);
+    gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
 
     gen_store_fpr_D(dc, rd, dst);
 }
@@ -5280,7 +5292,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     if (rd == 1) {
                         TCGv_i64 t64 = tcg_temp_new_i64();
                         tcg_gen_qemu_ld64(t64, cpu_addr, dc->mem_idx);
-                        gen_helper_ldxfsr(cpu_env, t64);
+                        gen_helper_ldxfsr(cpu_fsr, cpu_env, cpu_fsr, t64);
                         tcg_temp_free_i64(t64);
                         break;
                     }
@@ -5289,7 +5301,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     t0 = get_temp_tl(dc);
                     tcg_gen_qemu_ld32u(t0, cpu_addr, dc->mem_idx);
                     tcg_gen_trunc_tl_i32(cpu_dst_32, t0);
-                    gen_helper_ldfsr(cpu_env, cpu_dst_32);
+                    gen_helper_ldfsr(cpu_fsr, cpu_env, cpu_fsr, cpu_dst_32);
                     break;
                 case 0x22:      /* ldqf, load quad fpreg */
                     {
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 22/24] target-sparc: Use cpu_fsr in stfsr
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (20 preceding siblings ...)
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 21/24] target-sparc: Use explicit writes to cpu_fsr Richard Henderson
@ 2016-06-28  0:39 ` Richard Henderson
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 23/24] target-sparc: Use cpu_loop_exit_restore from helper_check_ieee_exceptions Richard Henderson
                   ` (2 subsequent siblings)
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/translate.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index ed0853a..dea1b5f 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5403,17 +5403,14 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     break;
                 case 0x25: /* stfsr, V9 stxfsr */
                     {
-                        TCGv t = get_temp_tl(dc);
-
-                        tcg_gen_ld_tl(t, cpu_env, offsetof(CPUSPARCState, fsr));
 #ifdef TARGET_SPARC64
                         gen_address_mask(dc, cpu_addr);
                         if (rd == 1) {
-                            tcg_gen_qemu_st64(t, cpu_addr, dc->mem_idx);
+                            tcg_gen_qemu_st64(cpu_fsr, cpu_addr, dc->mem_idx);
                             break;
                         }
 #endif
-                        tcg_gen_qemu_st32(t, cpu_addr, dc->mem_idx);
+                        tcg_gen_qemu_st32(cpu_fsr, cpu_addr, dc->mem_idx);
                     }
                     break;
                 case 0x26:
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 23/24] target-sparc: Use cpu_loop_exit_restore from helper_check_ieee_exceptions
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (21 preceding siblings ...)
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 22/24] target-sparc: Use cpu_fsr in stfsr Richard Henderson
@ 2016-06-28  0:39 ` Richard Henderson
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 24/24] target-sparc: Elide duplicate updates to fprs Richard Henderson
  2016-06-28 22:44 ` [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Mark Cave-Ayland
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

This avoids needing to save state before every FP operation.

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/fop_helper.c | 17 +++++++++++++----
 target-sparc/translate.c  |  6 +-----
 2 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/target-sparc/fop_helper.c b/target-sparc/fop_helper.c
index cdc58ea..c7fb176 100644
--- a/target-sparc/fop_helper.c
+++ b/target-sparc/fop_helper.c
@@ -19,12 +19,13 @@
 
 #include "qemu/osdep.h"
 #include "cpu.h"
+#include "exec/exec-all.h"
 #include "exec/helper-proto.h"
 
 #define QT0 (env->qt0)
 #define QT1 (env->qt1)
 
-target_ulong helper_check_ieee_exceptions(CPUSPARCState *env)
+static target_ulong do_check_ieee_exceptions(CPUSPARCState *env, uintptr_t ra)
 {
     target_ulong status = get_float_exception_flags(&env->fp_status);
     target_ulong fsr = env->fsr;
@@ -51,12 +52,15 @@ target_ulong helper_check_ieee_exceptions(CPUSPARCState *env)
         }
 
         if ((fsr & FSR_CEXC_MASK) & ((fsr & FSR_TEM_MASK) >> 23)) {
+            CPUState *cs = CPU(sparc_env_get_cpu(env));
+
             /* Unmasked exception, generate a trap.  Note that while
                the helper is marked as NO_WG, we can get away with
                writing to cpu state along the exception path, since
                TCG generated code will never see the write.  */
             env->fsr = fsr | FSR_FTT_IEEE_EXCP;
-            helper_raise_exception(env, TT_FP_EXCP);
+            cs->exception_index = TT_FP_EXCP;
+            cpu_loop_exit_restore(cs, ra);
         } else {
             /* Accumulate exceptions */
             fsr |= (fsr & FSR_CEXC_MASK) << 5;
@@ -66,6 +70,11 @@ target_ulong helper_check_ieee_exceptions(CPUSPARCState *env)
     return fsr;
 }
 
+target_ulong helper_check_ieee_exceptions(CPUSPARCState *env)
+{
+    return do_check_ieee_exceptions(env, GETPC());
+}
+
 #define F_HELPER(name, p) void helper_f##name##p(CPUSPARCState *env)
 
 #define F_BINOP(name)                                           \
@@ -262,7 +271,7 @@ void helper_fsqrtq(CPUSPARCState *env)
             ret = glue(size, _compare_quiet)(reg1, reg2,                \
                                              &env->fp_status);          \
         }                                                               \
-        fsr = helper_check_ieee_exceptions(env);                        \
+        fsr = do_check_ieee_exceptions(env, GETPC());                   \
         switch (ret) {                                                  \
         case float_relation_unordered:                                  \
             fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                         \
@@ -293,7 +302,7 @@ void helper_fsqrtq(CPUSPARCState *env)
             ret = glue(size, _compare_quiet)(src1, src2,                \
                                              &env->fp_status);          \
         }                                                               \
-        fsr = helper_check_ieee_exceptions(env);                        \
+        fsr = do_check_ieee_exceptions(env, GETPC());                   \
         switch (ret) {                                                  \
         case float_relation_unordered:                                  \
             fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                         \
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index dea1b5f..590a58d 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -3464,7 +3464,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                 rs1 = GET_FIELD(insn, 13, 17);
                 rs2 = GET_FIELD(insn, 27, 31);
                 xop = GET_FIELD(insn, 18, 26);
-                save_state(dc);
+
                 switch (xop) {
                 case 0x1: /* fmovs */
                     cpu_src1_32 = gen_load_fpr_F(dc, rs2);
@@ -3639,7 +3639,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                 rs1 = GET_FIELD(insn, 13, 17);
                 rs2 = GET_FIELD(insn, 27, 31);
                 xop = GET_FIELD(insn, 18, 26);
-                save_state(dc);
 
 #ifdef TARGET_SPARC64
 #define FMOVR(sz)                                                  \
@@ -5276,7 +5275,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                 if (gen_trap_ifnofpu(dc)) {
                     goto jmp_insn;
                 }
-                save_state(dc);
                 switch (xop) {
                 case 0x20:      /* ldf, load fpreg */
                     gen_address_mask(dc, cpu_addr);
@@ -5390,7 +5388,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                 if (gen_trap_ifnofpu(dc)) {
                     goto jmp_insn;
                 }
-                save_state(dc);
                 switch (xop) {
                 case 0x24: /* stf, store fpreg */
                     {
@@ -5449,7 +5446,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     goto illegal_insn;
                 }
             } else if (xop > 0x33 && xop < 0x3f) {
-                save_state(dc);
                 switch (xop) {
 #ifdef TARGET_SPARC64
                 case 0x34: /* V9 stfa */
-- 
2.5.5

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

* [Qemu-devel] [PATCH v4 24/24] target-sparc: Elide duplicate updates to fprs
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (22 preceding siblings ...)
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 23/24] target-sparc: Use cpu_loop_exit_restore from helper_check_ieee_exceptions Richard Henderson
@ 2016-06-28  0:39 ` Richard Henderson
  2016-06-28 22:44 ` [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Mark Cave-Ayland
  24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-28  0:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland

Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/translate.c | 45 +++++++++++++++++++++++++++------------------
 1 file changed, 27 insertions(+), 18 deletions(-)

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 590a58d..e7691e4 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -83,6 +83,7 @@ typedef struct DisasContext {
     int n_t32;
     int n_ttl;
 #ifdef TARGET_SPARC64
+    int fprs_dirty;
     int asi;
 #endif
 } DisasContext;
@@ -140,10 +141,16 @@ static inline TCGv get_temp_tl(DisasContext *dc)
     return t;
 }
 
-static inline void gen_update_fprs_dirty(int rd)
+static inline void gen_update_fprs_dirty(DisasContext *dc, int rd)
 {
 #if defined(TARGET_SPARC64)
-    tcg_gen_ori_i32(cpu_fprs, cpu_fprs, (rd < 32) ? 1 : 2);
+    int bit = (rd < 32) ? 1 : 2;
+    /* If we know we've already set this bit within the TB,
+       we can avoid setting it again.  */
+    if (!(dc->fprs_dirty & bit)) {
+        dc->fprs_dirty |= bit;
+        tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit);
+    }
 #endif
 }
 
@@ -185,7 +192,7 @@ static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v)
     tcg_gen_deposit_i64(cpu_fpr[dst / 2], cpu_fpr[dst / 2], t,
                         (dst & 1 ? 0 : 32), 32);
 #endif
-    gen_update_fprs_dirty(dst);
+    gen_update_fprs_dirty(dc, dst);
 }
 
 static TCGv_i32 gen_dest_fpr_F(DisasContext *dc)
@@ -203,7 +210,7 @@ static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v)
 {
     dst = DFPREG(dst);
     tcg_gen_mov_i64(cpu_fpr[dst / 2], v);
-    gen_update_fprs_dirty(dst);
+    gen_update_fprs_dirty(dc, dst);
 }
 
 static TCGv_i64 gen_dest_fpr_D(DisasContext *dc, unsigned int dst)
@@ -236,14 +243,14 @@ static void gen_op_store_QT0_fpr(unsigned int dst)
 }
 
 #ifdef TARGET_SPARC64
-static void gen_move_Q(unsigned int rd, unsigned int rs)
+static void gen_move_Q(DisasContext *dc, unsigned int rd, unsigned int rs)
 {
     rd = QFPREG(rd);
     rs = QFPREG(rs);
 
     tcg_gen_mov_i64(cpu_fpr[rd / 2], cpu_fpr[rs / 2]);
     tcg_gen_mov_i64(cpu_fpr[rd / 2 + 1], cpu_fpr[rs / 2 + 1]);
-    gen_update_fprs_dirty(rd);
+    gen_update_fprs_dirty(dc, rd);
 }
 #endif
 
@@ -1834,7 +1841,7 @@ static inline void gen_fop_QQ(DisasContext *dc, int rd, int rs,
     gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
 
     gen_op_store_QT0_fpr(QFPREG(rd));
-    gen_update_fprs_dirty(QFPREG(rd));
+    gen_update_fprs_dirty(dc, QFPREG(rd));
 }
 
 #ifdef TARGET_SPARC64
@@ -1846,7 +1853,7 @@ static inline void gen_ne_fop_QQ(DisasContext *dc, int rd, int rs,
     gen(cpu_env);
 
     gen_op_store_QT0_fpr(QFPREG(rd));
-    gen_update_fprs_dirty(QFPREG(rd));
+    gen_update_fprs_dirty(dc, QFPREG(rd));
 }
 #endif
 
@@ -1860,7 +1867,7 @@ static inline void gen_fop_QQQ(DisasContext *dc, int rd, int rs1, int rs2,
     gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
 
     gen_op_store_QT0_fpr(QFPREG(rd));
-    gen_update_fprs_dirty(QFPREG(rd));
+    gen_update_fprs_dirty(dc, QFPREG(rd));
 }
 
 static inline void gen_fop_DFF(DisasContext *dc, int rd, int rs1, int rs2,
@@ -1891,7 +1898,7 @@ static inline void gen_fop_QDD(DisasContext *dc, int rd, int rs1, int rs2,
     gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env);
 
     gen_op_store_QT0_fpr(QFPREG(rd));
-    gen_update_fprs_dirty(QFPREG(rd));
+    gen_update_fprs_dirty(dc, QFPREG(rd));
 }
 
 #ifdef TARGET_SPARC64
@@ -1978,7 +1985,7 @@ static inline void gen_ne_fop_QF(DisasContext *dc, int rd, int rs,
     gen(cpu_env, src);
 
     gen_op_store_QT0_fpr(QFPREG(rd));
-    gen_update_fprs_dirty(QFPREG(rd));
+    gen_update_fprs_dirty(dc, QFPREG(rd));
 }
 
 static inline void gen_ne_fop_QD(DisasContext *dc, int rd, int rs,
@@ -1991,7 +1998,7 @@ static inline void gen_ne_fop_QD(DisasContext *dc, int rd, int rs,
     gen(cpu_env, src);
 
     gen_op_store_QT0_fpr(QFPREG(rd));
-    gen_update_fprs_dirty(QFPREG(rd));
+    gen_update_fprs_dirty(dc, QFPREG(rd));
 }
 
 /* asi moves */
@@ -2790,7 +2797,7 @@ static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
     tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, cmp->c2,
                         cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]);
 
-    gen_update_fprs_dirty(qd);
+    gen_update_fprs_dirty(dc, qd);
 }
 
 #ifndef CONFIG_USER_ONLY
@@ -3588,7 +3595,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                     break;
                 case 0x3: /* V9 fmovq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
-                    gen_move_Q(rd, rs2);
+                    gen_move_Q(dc, rd, rs2);
                     break;
                 case 0x6: /* V9 fnegd */
                     gen_ne_fop_DD(dc, rd, rs2, gen_helper_fnegd);
@@ -4138,6 +4145,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                             case 0x6: /* V9 wrfprs */
                                 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
                                 tcg_gen_trunc_tl_i32(cpu_fprs, cpu_tmp0);
+                                dc->fprs_dirty = 0;
                                 save_state(dc);
                                 gen_op_next_insn();
                                 tcg_gen_exit_tb(0);
@@ -5242,14 +5250,14 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                         goto jmp_insn;
                     }
                     gen_ldf_asi(dc, cpu_addr, insn, 4, rd);
-                    gen_update_fprs_dirty(rd);
+                    gen_update_fprs_dirty(dc, rd);
                     goto skip_move;
                 case 0x33: /* V9 lddfa */
                     if (gen_trap_ifnofpu(dc)) {
                         goto jmp_insn;
                     }
                     gen_ldf_asi(dc, cpu_addr, insn, 8, DFPREG(rd));
-                    gen_update_fprs_dirty(DFPREG(rd));
+                    gen_update_fprs_dirty(dc, DFPREG(rd));
                     goto skip_move;
                 case 0x3d: /* V9 prefetcha, no effect */
                     goto skip_move;
@@ -5259,7 +5267,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                         goto jmp_insn;
                     }
                     gen_ldf_asi(dc, cpu_addr, insn, 16, QFPREG(rd));
-                    gen_update_fprs_dirty(QFPREG(rd));
+                    gen_update_fprs_dirty(dc, QFPREG(rd));
                     goto skip_move;
 #endif
                 default:
@@ -5311,7 +5319,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                         gen_helper_ldqf(cpu_env, cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
                         gen_op_store_QT0_fpr(QFPREG(rd));
-                        gen_update_fprs_dirty(QFPREG(rd));
+                        gen_update_fprs_dirty(dc, QFPREG(rd));
                     }
                     break;
                 case 0x23:      /* lddf, load double fpreg */
@@ -5579,6 +5587,7 @@ void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
     dc->address_mask_32bit = tb_am_enabled(tb->flags);
     dc->singlestep = (cs->singlestep_enabled || singlestep);
 #ifdef TARGET_SPARC64
+    dc->fprs_dirty = 0;
     dc->asi = (tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff;
 #endif
 
-- 
2.5.5

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

* Re: [Qemu-devel] [PATCH v4 00/24] target-sparc improvements
  2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
                   ` (23 preceding siblings ...)
  2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 24/24] target-sparc: Elide duplicate updates to fprs Richard Henderson
@ 2016-06-28 22:44 ` Mark Cave-Ayland
  2016-06-29  4:14   ` Richard Henderson
  24 siblings, 1 reply; 27+ messages in thread
From: Mark Cave-Ayland @ 2016-06-28 22:44 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

On 28/06/16 01:38, Richard Henderson wrote:

> The primary focus of this patch set is to reduce the number of
> helpers that modify TCG globals, and thus increase the lifetime
> of those globals within each TB, and thus decrease the number
> of times that tcg must spill and fill them from backing store.
> 
> As a byproduct, I also implement the bulk of the interesting v9 ASIs
> inline, thus exposing e.g. the little-endian loads and stores as
> simple tcg operations.
> 
> The patch set is relative to my outstanding tcg pull request.
> For reference, the complete tree can be found at
> 
>   git://github.com/rth7680/qemu.git tgt-sparc-2
> 
> Changes from v3 to v4:
>   * Re-do the UA2005 commit change, which apparently got lost in v3.
>   * Rebased on aa8151b7df, which contains fix for the ldstub issue.
> 
> Changes from v2 to v3:
>   * Add ASI_BLK_COMMIT_[PS] to patch 19.
>     This fixes the illegal instruction that Artyom reported.
>   * Add gen_address_mask calls to all direct accesses.
>     This fixes a follow-on segv that affected the debian install.
> 
> Changes from v1 to v2:
>   * Commit message refers to UA2005 instead of UA2011 when
>     introducing new asi.h defines. (Artyom)
>   * Drop MMU_REAL_IDX, and inline handling of ASI_REAL_*.
>     This appears to be the source of the regression that Artyom
>     identified wrt ss5 emulation.
> 
> 
> r~
> 
> 
> Richard Henderson (24):
>   target-sparc: Mark more flags for helpers
>   target-sparc: Remove softint as a TCG global
>   target-sparc: Store mmu index in TB flags
>   target-sparc: Create gen_exception
>   target-sparc: Unify asi handling between 32 and 64-bit
>   target-sparc: Store %asi in TB flags
>   target-sparc: Introduce get_asi
>   target-sparc: Pass TCGMemOp to gen_ld/st_asi
>   target-sparc: Import linux/arch/sparc/include/uapi/asm/asi.h
>   target-sparc: Add UA2005 defines to asi.h
>   target-sparc: Use defines from asi.h
>   target-sparc: Directly implement easy ld/st asis
>   target-sparc: Use QT0 to return results from ldda
>   target-sparc: Introduce gen_check_align
>   target-sparc: Directly implement easy ldd/std asis
>   target-sparc: Fix obvious error in ASI_M_BFILL
>   target-sparc: Pass TCGMemOp constants to helper_ld/st_asi
>   target-sparc: Directly implement easy ldf/stf asis
>   target-sparc: Directly implement block and short ldf/stf asis
>   target-sparc: Remove helper_ldf_asi, helper_stf_asi
>   target-sparc: Use explicit writes to cpu_fsr
>   target-sparc: Use cpu_fsr in stfsr
>   target-sparc: Use cpu_loop_exit_restore from
>     helper_check_ieee_exceptions
>   target-sparc: Elide duplicate updates to fprs
> 
>  target-sparc/asi.h         |  311 +++++++++++
>  target-sparc/cpu.h         |   28 +-
>  target-sparc/fop_helper.c  |  230 +++-----
>  target-sparc/helper.h      |  168 +++---
>  target-sparc/ldst_helper.c |  696 +++++++++++-------------
>  target-sparc/translate.c   | 1273 ++++++++++++++++++++++++++++----------------
>  6 files changed, 1607 insertions(+), 1099 deletions(-)
>  create mode 100644 target-sparc/asi.h

Hi Richard,

I didn't see the branch rebase onto aa8151b7df here, although I was able
to manually rebase the tgt-sparc-2 branch onto git master and build
without issues.

With that, I ran through all my OpenBIOS boot tests for SPARC32/SPARC64
and all my images booted fine without any regressions.

Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>


ATB,

Mark.

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

* Re: [Qemu-devel] [PATCH v4 00/24] target-sparc improvements
  2016-06-28 22:44 ` [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Mark Cave-Ayland
@ 2016-06-29  4:14   ` Richard Henderson
  0 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-29  4:14 UTC (permalink / raw)
  To: Mark Cave-Ayland, qemu-devel

On 06/28/2016 03:44 PM, Mark Cave-Ayland wrote:
> I didn't see the branch rebase onto aa8151b7df here, although I was able
> to manually rebase the tgt-sparc-2 branch onto git master and build
> without issues.

I pushed it to tcg-sparc if you wanted to see my branch.


r~

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

end of thread, other threads:[~2016-06-29  4:14 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-28  0:38 [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Richard Henderson
2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 01/24] target-sparc: Mark more flags for helpers Richard Henderson
2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 02/24] target-sparc: Remove softint as a TCG global Richard Henderson
2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 03/24] target-sparc: Store mmu index in TB flags Richard Henderson
2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 04/24] target-sparc: Create gen_exception Richard Henderson
2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 05/24] target-sparc: Unify asi handling between 32 and 64-bit Richard Henderson
2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 06/24] target-sparc: Store %asi in TB flags Richard Henderson
2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 07/24] target-sparc: Introduce get_asi Richard Henderson
2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 08/24] target-sparc: Pass TCGMemOp to gen_ld/st_asi Richard Henderson
2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 09/24] target-sparc: Import linux/arch/sparc/include/uapi/asm/asi.h Richard Henderson
2016-06-28  0:38 ` [Qemu-devel] [PATCH v4 10/24] target-sparc: Add UA2005 defines to asi.h Richard Henderson
2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 11/24] target-sparc: Use defines from asi.h Richard Henderson
2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 12/24] target-sparc: Directly implement easy ld/st asis Richard Henderson
2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 13/24] target-sparc: Use QT0 to return results from ldda Richard Henderson
2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 14/24] target-sparc: Introduce gen_check_align Richard Henderson
2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 15/24] target-sparc: Directly implement easy ldd/std asis Richard Henderson
2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 16/24] target-sparc: Fix obvious error in ASI_M_BFILL Richard Henderson
2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 17/24] target-sparc: Pass TCGMemOp constants to helper_ld/st_asi Richard Henderson
2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 18/24] target-sparc: Directly implement easy ldf/stf asis Richard Henderson
2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 19/24] target-sparc: Directly implement block and short " Richard Henderson
2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 20/24] target-sparc: Remove helper_ldf_asi, helper_stf_asi Richard Henderson
2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 21/24] target-sparc: Use explicit writes to cpu_fsr Richard Henderson
2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 22/24] target-sparc: Use cpu_fsr in stfsr Richard Henderson
2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 23/24] target-sparc: Use cpu_loop_exit_restore from helper_check_ieee_exceptions Richard Henderson
2016-06-28  0:39 ` [Qemu-devel] [PATCH v4 24/24] target-sparc: Elide duplicate updates to fprs Richard Henderson
2016-06-28 22:44 ` [Qemu-devel] [PATCH v4 00/24] target-sparc improvements Mark Cave-Ayland
2016-06-29  4:14   ` Richard Henderson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.