diff options
author | Nathan Froyd <froydnj@codesourcery.com> | 2009-08-03 08:43:26 -0700 |
---|---|---|
committer | malc <av1474@comtv.ru> | 2009-08-03 20:33:41 +0400 |
commit | 4425265beb8503b82dc3de0388b504e15825d06e (patch) | |
tree | 25ad23be765cec59d5ac80d2397523d894dd370f /target-ppc/translate.c | |
parent | 18b21a2f83a26c3d6a9e7f0bdc4e8eb2b177e8f6 (diff) |
target-ppc: add exceptions for conditional stores
Signed-off-by: Nathan Froyd <froydnj@codesourcery.com>
Signed-off-by: malc <av1474@comtv.ru>
Diffstat (limited to 'target-ppc/translate.c')
-rw-r--r-- | target-ppc/translate.c | 71 |
1 files changed, 51 insertions, 20 deletions
diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 06282b6aea..f82c6e5bae 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -3018,24 +3018,49 @@ static void gen_lwarx(DisasContext *ctx) tcg_temp_free(t0); } +#if defined(CONFIG_USER_ONLY) +static void gen_conditional_store (DisasContext *ctx, TCGv EA, + int reg, int size) +{ + TCGv t0 = tcg_temp_new(); + uint32_t save_exception = ctx->exception; + + tcg_gen_st_tl(EA, cpu_env, offsetof(CPUState, reserve_ea)); + tcg_gen_movi_tl(t0, (size << 5) | reg); + tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, reserve_info)); + tcg_temp_free(t0); + gen_update_nip(ctx, ctx->nip-4); + ctx->exception = POWERPC_EXCP_BRANCH; + gen_exception(ctx, POWERPC_EXCP_STCX); + ctx->exception = save_exception; +} +#endif + /* stwcx. */ static void gen_stwcx_(DisasContext *ctx) { - int l1; TCGv t0; gen_set_access_type(ctx, ACCESS_RES); t0 = tcg_temp_local_new(); gen_addr_reg_index(ctx, t0); gen_check_align(ctx, t0, 0x03); - tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer); - tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO); - tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1); - l1 = gen_new_label(); - tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1); - tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ); - gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], t0); - gen_set_label(l1); - tcg_gen_movi_tl(cpu_reserve, -1); +#if defined(CONFIG_USER_ONLY) + gen_conditional_store(ctx, t0, rS(ctx->opcode), 4); +#else + { + int l1; + + tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer); + tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO); + tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1); + l1 = gen_new_label(); + tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1); + tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ); + gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], t0); + gen_set_label(l1); + tcg_gen_movi_tl(cpu_reserve, -1); + } +#endif tcg_temp_free(t0); } @@ -3058,21 +3083,27 @@ static void gen_ldarx(DisasContext *ctx) /* stdcx. */ static void gen_stdcx_(DisasContext *ctx) { - int l1; TCGv t0; gen_set_access_type(ctx, ACCESS_RES); t0 = tcg_temp_local_new(); gen_addr_reg_index(ctx, t0); gen_check_align(ctx, t0, 0x07); - tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer); - tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO); - tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1); - l1 = gen_new_label(); - tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1); - tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ); - gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], t0); - gen_set_label(l1); - tcg_gen_movi_tl(cpu_reserve, -1); +#if defined(CONFIG_USER_ONLY) + gen_conditional_store(ctx, t0, rS(ctx->opcode), 8); +#else + { + int l1; + tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer); + tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO); + tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1); + l1 = gen_new_label(); + tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1); + tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ); + gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], t0); + gen_set_label(l1); + tcg_gen_movi_tl(cpu_reserve, -1); + } +#endif tcg_temp_free(t0); } #endif /* defined(TARGET_PPC64) */ |