On 11/26/2013 03:04 PM, Sebastian Huber wrote: > The LEON3 processor has support for the CASA instruction which is > normally only available for SPARC V9 processors. Binutils 2.24 > and GCC 4.9 will support this instruction for LEON3. GCC uses it to > generate C11 atomic operations.
The patch looks good. I can't really test it but I assume you did. Thank you Sebastian. Reviewed-by: Fabien Chouteau <chout...@adacore.com> > --- > target-sparc/cpu.c | 3 +- > target-sparc/cpu.h | 4 ++- > target-sparc/helper.h | 4 ++- > target-sparc/ldst_helper.c | 26 +++++++++++++----------- > target-sparc/translate.c | 47 ++++++++++++++++++++++++++++--------------- > 5 files changed, 52 insertions(+), 32 deletions(-) > > diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c > index e7f878e..5806e59 100644 > --- a/target-sparc/cpu.c > +++ b/target-sparc/cpu.c > @@ -458,7 +458,8 @@ static const sparc_def_t sparc_defs[] = { > .mmu_trcr_mask = 0xffffffff, > .nwindows = 8, > .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN | > - CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN, > + CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN | > + CPU_FEATURE_CASA, > }, > #endif > }; > diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h > index 41194ec..f87d7fb 100644 > --- a/target-sparc/cpu.h > +++ b/target-sparc/cpu.h > @@ -271,12 +271,14 @@ typedef struct sparc_def_t { > #define CPU_FEATURE_ASR17 (1 << 15) > #define CPU_FEATURE_CACHE_CTRL (1 << 16) > #define CPU_FEATURE_POWERDOWN (1 << 17) > +#define CPU_FEATURE_CASA (1 << 18) > > #ifndef TARGET_SPARC64 > #define CPU_DEFAULT_FEATURES (CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | \ > CPU_FEATURE_MUL | CPU_FEATURE_DIV | \ > CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT | \ > - CPU_FEATURE_FMUL | CPU_FEATURE_FSMULD) > + CPU_FEATURE_FMUL | CPU_FEATURE_FSMULD | \ > + CPU_FEATURE_CASA) > #else > #define CPU_DEFAULT_FEATURES (CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | \ > CPU_FEATURE_MUL | CPU_FEATURE_DIV | \ > diff --git a/target-sparc/helper.h b/target-sparc/helper.h > index 5e0eea1..9c4fd56 100644 > --- a/target-sparc/helper.h > +++ b/target-sparc/helper.h > @@ -22,7 +22,6 @@ DEF_HELPER_1(popc, 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(cas_asi, tl, env, tl, tl, tl, i32) > DEF_HELPER_5(casx_asi, tl, env, tl, tl, tl, i32) > DEF_HELPER_2(set_softint, void, env, i64) > DEF_HELPER_2(clear_softint, void, env, i64) > @@ -31,6 +30,9 @@ DEF_HELPER_2(tick_set_count, void, ptr, i64) > DEF_HELPER_1(tick_get_count, i64, ptr) > DEF_HELPER_2(tick_set_limit, void, ptr, i64) > #endif > +#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) > +DEF_HELPER_5(cas_asi, tl, env, tl, tl, tl, i32) > +#endif > DEF_HELPER_3(check_align, void, env, tl, i32) > DEF_HELPER_1(debug, void, env) > DEF_HELPER_1(save, void, env) > diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c > index 2936b58..c51b9b0 100644 > --- a/target-sparc/ldst_helper.c > +++ b/target-sparc/ldst_helper.c > @@ -2224,33 +2224,35 @@ void helper_stf_asi(CPUSPARCState *env, target_ulong > addr, int asi, int size, > } > } > > -target_ulong helper_cas_asi(CPUSPARCState *env, target_ulong addr, > - target_ulong val1, target_ulong val2, uint32_t > asi) > +target_ulong helper_casx_asi(CPUSPARCState *env, target_ulong addr, > + target_ulong val1, target_ulong val2, > + uint32_t asi) > { > target_ulong ret; > > - val2 &= 0xffffffffUL; > - ret = helper_ld_asi(env, addr, asi, 4, 0); > - ret &= 0xffffffffUL; > + ret = helper_ld_asi(env, addr, asi, 8, 0); > if (val2 == ret) { > - helper_st_asi(env, addr, val1 & 0xffffffffUL, asi, 4); > + helper_st_asi(env, addr, val1, asi, 8); > } > return ret; > } > +#endif /* TARGET_SPARC64 */ > > -target_ulong helper_casx_asi(CPUSPARCState *env, target_ulong addr, > - target_ulong val1, target_ulong val2, > - uint32_t asi) > +#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) > +target_ulong helper_cas_asi(CPUSPARCState *env, target_ulong addr, > + target_ulong val1, target_ulong val2, uint32_t > asi) > { > target_ulong ret; > > - ret = helper_ld_asi(env, addr, asi, 8, 0); > + val2 &= 0xffffffffUL; > + ret = helper_ld_asi(env, addr, asi, 4, 0); > + ret &= 0xffffffffUL; > if (val2 == ret) { > - helper_st_asi(env, addr, val1, asi, 8); > + helper_st_asi(env, addr, val1 & 0xffffffffUL, asi, 4); > } > return ret; > } > -#endif /* TARGET_SPARC64 */ > +#endif /* !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) */ > > void helper_ldqf(CPUSPARCState *env, target_ulong addr, int mem_idx) > { > diff --git a/target-sparc/translate.c b/target-sparc/translate.c > index 38b4519..86743dc 100644 > --- a/target-sparc/translate.c > +++ b/target-sparc/translate.c > @@ -2107,18 +2107,6 @@ static inline void gen_stda_asi(DisasContext *dc, TCGv > hi, TCGv addr, > tcg_temp_free_i64(t64); > } > > -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); > - TCGv_i32 r_asi = gen_get_asi(insn, addr); > - > - 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_casx_asi(DisasContext *dc, TCGv addr, > TCGv val2, int insn, int rd) > { > @@ -2229,6 +2217,22 @@ 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; > @@ -5103,11 +5107,6 @@ static void disas_sparc_insn(DisasContext * dc, > unsigned int insn) > } > gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd)); > break; > - case 0x3c: /* V9 casa */ > - rs2 = GET_FIELD(insn, 27, 31); > - cpu_src2 = gen_load_gpr(dc, rs2); > - gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd); > - break; > case 0x3e: /* V9 casxa */ > rs2 = GET_FIELD(insn, 27, 31); > cpu_src2 = gen_load_gpr(dc, rs2); > @@ -5120,6 +5119,20 @@ static void disas_sparc_insn(DisasContext * dc, > unsigned int insn) > case 0x37: /* stdc */ > goto ncp_insn; > #endif > +#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) > + case 0x3c: /* V9 or LEON3 casa */ > + CHECK_FPU_FEATURE(dc, CASA); > +#ifndef TARGET_SPARC64 > + if (IS_IMM) > + goto illegal_insn; > + if (!supervisor(dc)) > + goto priv_insn; > +#endif > + rs2 = GET_FIELD(insn, 27, 31); > + cpu_src2 = gen_load_gpr(dc, rs2); > + gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd); > + break; > +#endif > default: > goto illegal_insn; > } >