* [Qemu-devel] [PATCH v3 00/24] target-sparc improvements
@ 2016-06-02 5:56 Richard Henderson
2016-06-02 5:56 ` [Qemu-devel] [PATCH v3 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-02 5:56 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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 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 the 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 UA2011 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 v3 01/24] target-sparc: Mark more flags for helpers
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
@ 2016-06-02 5:56 ` Richard Henderson
2016-06-02 5:56 ` [Qemu-devel] [PATCH v3 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-02 5:56 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
Quite a few helpers do not modify tcg globals but did not so indicate.
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 v3 02/24] target-sparc: Remove softint as a TCG global
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
2016-06-02 5:56 ` [Qemu-devel] [PATCH v3 01/24] target-sparc: Mark more flags for helpers Richard Henderson
@ 2016-06-02 5:56 ` Richard Henderson
2016-06-02 5:56 ` [Qemu-devel] [PATCH v3 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-02 5:56 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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.
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 21760b9..bfeef35 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 */
@@ -5360,7 +5360,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 v3 03/24] target-sparc: Store mmu index in TB flags
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
2016-06-02 5:56 ` [Qemu-devel] [PATCH v3 01/24] target-sparc: Mark more flags for helpers Richard Henderson
2016-06-02 5:56 ` [Qemu-devel] [PATCH v3 02/24] target-sparc: Remove softint as a TCG global Richard Henderson
@ 2016-06-02 5:56 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:56 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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.
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 bfeef35..fb3938a 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5245,7 +5245,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 v3 04/24] target-sparc: Create gen_exception
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (2 preceding siblings ...)
2016-06-02 5:56 ` [Qemu-devel] [PATCH v3 03/24] target-sparc: Store mmu index in TB flags Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
This unifies quite a few duplicate code fragments.
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 fb3938a..e2531d2 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
@@ -5152,63 +5153,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 v3 05/24] target-sparc: Unify asi handling between 32 and 64-bit
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (3 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 04/24] target-sparc: Create gen_exception Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
We now have a single copy of gen_ld_asi, gen_st_asi,
gen_swap_asi, and everything uses gen_get_asi.
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 e2531d2..7d5d2fe 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);
@@ -4709,7 +4686,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
@@ -4719,7 +4696,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
@@ -4729,7 +4706,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
@@ -4751,7 +4728,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
@@ -4761,7 +4738,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
@@ -4771,7 +4748,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 */
@@ -4784,7 +4761,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
@@ -4805,11 +4782,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;
@@ -4818,7 +4795,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 */
@@ -4826,7 +4803,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 */
@@ -4837,7 +4814,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
@@ -4951,7 +4928,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 */
@@ -4962,7 +4939,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 */
@@ -4973,7 +4950,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 */
@@ -4998,7 +4975,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
@@ -5078,7 +5055,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 */
{
@@ -5091,14 +5068,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 v3 06/24] target-sparc: Store %asi in TB flags
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (4 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 05/24] target-sparc: Unify asi handling between 32 and 64-bit Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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.
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 7d5d2fe..cea839c 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);
@@ -5192,6 +5201,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;
@@ -5300,7 +5312,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 v3 07/24] target-sparc: Introduce get_asi
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (5 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 06/24] target-sparc: Store %asi in TB flags Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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.
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 cea839c..8917a72 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
@@ -4688,87 +4830,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;
@@ -4790,11 +4877,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 */
@@ -4803,7 +4888,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;
@@ -4811,7 +4895,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;
@@ -4822,7 +4905,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;
@@ -4930,51 +5012,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
@@ -4983,9 +5033,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:
@@ -5102,13 +5150,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 v3 08/24] target-sparc: Pass TCGMemOp to gen_ld/st_asi
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (6 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 07/24] target-sparc: Introduce get_asi Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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 8917a72..99a251c 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
@@ -4830,13 +4830,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) {
@@ -4845,10 +4845,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);
@@ -4877,10 +4877,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;
@@ -5012,13 +5012,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) {
@@ -5033,7 +5033,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 v3 09/24] target-sparc: Import linux/arch/sparc/include/uapi/asm/asi.h
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (7 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 08/24] target-sparc: Pass TCGMemOp to gen_ld/st_asi Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 10/24] target-sparc: Add UA2011 defines to asi.h Richard Henderson
` (15 subsequent siblings)
24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
Copied from tag v4.2, 64291f7db5bd8150a74ad2036f1037e6a0428df2.
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 v3 10/24] target-sparc: Add UA2011 defines to asi.h
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (8 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 09/24] target-sparc: Import linux/arch/sparc/include/uapi/asm/asi.h Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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 v3 11/24] target-sparc: Use defines from asi.h
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (9 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 10/24] target-sparc: Add UA2011 defines to asi.h Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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 99a251c..1d8c880 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 v3 12/24] target-sparc: Directly implement easy ld/st asis
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (10 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 11/24] target-sparc: Use defines from asi.h Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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 1d8c880..0e870d8 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 v3 13/24] target-sparc: Use QT0 to return results from ldda
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (11 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 12/24] target-sparc: Directly implement easy ld/st asis Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
Also implement a few more twinx asis.
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 0e870d8..0917486 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 v3 14/24] target-sparc: Introduce gen_check_align
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (12 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 13/24] target-sparc: Use QT0 to return results from ldda Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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 0917486..7d10578 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);
@@ -5076,18 +5065,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);
@@ -5200,15 +5182,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 v3 15/24] target-sparc: Directly implement easy ldd/std asis
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (13 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 14/24] target-sparc: Introduce gen_check_align Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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 7d10578..b2b3027 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);
@@ -4915,7 +5006,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 v3 16/24] target-sparc: Fix obvious error in ASI_M_BFILL
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (14 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 15/24] target-sparc: Directly implement easy ldd/std asis Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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 v3 17/24] target-sparc: Pass TCGMemOp constants to helper_ld/st_asi
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (15 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 16/24] target-sparc: Fix obvious error in ASI_M_BFILL Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
Reduces the argument count for helper_ld_asi; do helper_st_asi
for consistency.
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 b2b3027..968564e 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 v3 18/24] target-sparc: Directly implement easy ldf/stf asis
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (16 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 17/24] target-sparc: Pass TCGMemOp constants to helper_ld/st_asi Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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 968564e..948869e 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 v3 19/24] target-sparc: Directly implement block and short ldf/stf asis
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (17 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 18/24] target-sparc: Directly implement easy ldf/stf asis Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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 948869e..9151ab8 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 v3 20/24] target-sparc: Remove helper_ldf_asi, helper_stf_asi
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (18 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 19/24] target-sparc: Directly implement block and short " Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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.
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 9151ab8..02054b5 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 v3 21/24] target-sparc: Use explicit writes to cpu_fsr
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (19 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 20/24] target-sparc: Remove helper_ldf_asi, helper_stf_asi Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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.
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 02054b5..e9be680 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);
}
@@ -5277,7 +5289,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;
}
@@ -5286,7 +5298,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 v3 22/24] target-sparc: Use cpu_fsr in stfsr
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (20 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 21/24] target-sparc: Use explicit writes to cpu_fsr Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 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-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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 e9be680..a7fbbbb 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5400,17 +5400,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 v3 23/24] target-sparc: Use cpu_loop_exit_restore from helper_check_ieee_exceptions
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (21 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 22/24] target-sparc: Use cpu_fsr in stfsr Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 24/24] target-sparc: Elide duplicate updates to fprs Richard Henderson
2016-06-02 12:17 ` [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Artyom Tarasenko
24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
This avoids needing to save state before every FP operation.
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 a7fbbbb..4a6a554 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) \
@@ -5273,7 +5272,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);
@@ -5387,7 +5385,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 */
{
@@ -5446,7 +5443,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 v3 24/24] target-sparc: Elide duplicate updates to fprs
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (22 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 23/24] target-sparc: Use cpu_loop_exit_restore from helper_check_ieee_exceptions Richard Henderson
@ 2016-06-02 5:57 ` Richard Henderson
2016-06-02 12:17 ` [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Artyom Tarasenko
24 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2016-06-02 5:57 UTC (permalink / raw)
To: qemu-devel; +Cc: mark.cave-ayland, atar4qemu
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 4a6a554..2d3cda6 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);
@@ -5239,14 +5247,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;
@@ -5256,7 +5264,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:
@@ -5308,7 +5316,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 */
@@ -5576,6 +5584,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 v3 00/24] target-sparc improvements
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
` (23 preceding siblings ...)
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 24/24] target-sparc: Elide duplicate updates to fprs Richard Henderson
@ 2016-06-02 12:17 ` Artyom Tarasenko
2016-06-24 13:05 ` Artyom Tarasenko
24 siblings, 1 reply; 27+ messages in thread
From: Artyom Tarasenko @ 2016-06-02 12:17 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, Mark Cave-Ayland
On Thu, Jun 2, 2016 at 7:56 AM, Richard Henderson <rth@twiddle.net> 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 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)
Looks like this change is lost in v3.
But it is cosmetic and won't stop me from running the tests.
Thanks for the update,
Artyom
> * Drop the 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 UA2011 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
>
--
Regards,
Artyom Tarasenko
SPARC and PPC PReP under qemu blog: http://tyom.blogspot.com/search/label/qemu
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [PATCH v3 00/24] target-sparc improvements
2016-06-02 12:17 ` [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Artyom Tarasenko
@ 2016-06-24 13:05 ` Artyom Tarasenko
0 siblings, 0 replies; 27+ messages in thread
From: Artyom Tarasenko @ 2016-06-24 13:05 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, Mark Cave-Ayland
On Thu, Jun 2, 2016 at 2:17 PM, Artyom Tarasenko <atar4qemu@gmail.com> wrote:
> On Thu, Jun 2, 2016 at 7:56 AM, Richard Henderson <rth@twiddle.net> 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 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)
Once this change gets back to v4
Reviewed-By: Artyom Tarasenko <atar4qemu@gmail.com>
(Currently rebasing my sun4v branch on top of this series)
>> 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 UA2011 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
>>
>
>
>
> --
> Regards,
> Artyom Tarasenko
>
> SPARC and PPC PReP under qemu blog: http://tyom.blogspot.com/search/label/qemu
--
Regards,
Artyom Tarasenko
SPARC and PPC PReP under qemu blog: http://tyom.blogspot.com/search/label/qemu
^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2016-06-24 13:05 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-02 5:56 [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Richard Henderson
2016-06-02 5:56 ` [Qemu-devel] [PATCH v3 01/24] target-sparc: Mark more flags for helpers Richard Henderson
2016-06-02 5:56 ` [Qemu-devel] [PATCH v3 02/24] target-sparc: Remove softint as a TCG global Richard Henderson
2016-06-02 5:56 ` [Qemu-devel] [PATCH v3 03/24] target-sparc: Store mmu index in TB flags Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 04/24] target-sparc: Create gen_exception Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 05/24] target-sparc: Unify asi handling between 32 and 64-bit Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 06/24] target-sparc: Store %asi in TB flags Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 07/24] target-sparc: Introduce get_asi Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 08/24] target-sparc: Pass TCGMemOp to gen_ld/st_asi Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 09/24] target-sparc: Import linux/arch/sparc/include/uapi/asm/asi.h Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 10/24] target-sparc: Add UA2011 defines to asi.h Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 11/24] target-sparc: Use defines from asi.h Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 12/24] target-sparc: Directly implement easy ld/st asis Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 13/24] target-sparc: Use QT0 to return results from ldda Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 14/24] target-sparc: Introduce gen_check_align Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 15/24] target-sparc: Directly implement easy ldd/std asis Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 16/24] target-sparc: Fix obvious error in ASI_M_BFILL Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 17/24] target-sparc: Pass TCGMemOp constants to helper_ld/st_asi Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 18/24] target-sparc: Directly implement easy ldf/stf asis Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 19/24] target-sparc: Directly implement block and short " Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 20/24] target-sparc: Remove helper_ldf_asi, helper_stf_asi Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 21/24] target-sparc: Use explicit writes to cpu_fsr Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 22/24] target-sparc: Use cpu_fsr in stfsr Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 23/24] target-sparc: Use cpu_loop_exit_restore from helper_check_ieee_exceptions Richard Henderson
2016-06-02 5:57 ` [Qemu-devel] [PATCH v3 24/24] target-sparc: Elide duplicate updates to fprs Richard Henderson
2016-06-02 12:17 ` [Qemu-devel] [PATCH v3 00/24] target-sparc improvements Artyom Tarasenko
2016-06-24 13:05 ` Artyom Tarasenko
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.