target-ppc: add exceptions for conditional stores
Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> Signed-off-by: malc <av1474@comtv.ru>
This commit is contained in:
parent
18b21a2f83
commit
4425265beb
@ -218,6 +218,7 @@ enum {
|
|||||||
/* Qemu exceptions: special cases we want to stop translation */
|
/* Qemu exceptions: special cases we want to stop translation */
|
||||||
POWERPC_EXCP_SYNC = 0x202, /* context synchronizing instruction */
|
POWERPC_EXCP_SYNC = 0x202, /* context synchronizing instruction */
|
||||||
POWERPC_EXCP_SYSCALL_USER = 0x203, /* System call in user mode only */
|
POWERPC_EXCP_SYSCALL_USER = 0x203, /* System call in user mode only */
|
||||||
|
POWERPC_EXCP_STCX = 0x204 /* Conditional stores in user mode */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Exceptions error codes */
|
/* Exceptions error codes */
|
||||||
@ -564,6 +565,10 @@ struct CPUPPCState {
|
|||||||
target_ulong reserve_addr;
|
target_ulong reserve_addr;
|
||||||
/* Reservation value */
|
/* Reservation value */
|
||||||
target_ulong reserve_val;
|
target_ulong reserve_val;
|
||||||
|
/* Reservation store address */
|
||||||
|
target_ulong reserve_ea;
|
||||||
|
/* Reserved store source register and size */
|
||||||
|
target_ulong reserve_info;
|
||||||
|
|
||||||
/* Those ones are used in supervisor mode only */
|
/* Those ones are used in supervisor mode only */
|
||||||
/* machine state register */
|
/* machine state register */
|
||||||
|
@ -3018,24 +3018,49 @@ static void gen_lwarx(DisasContext *ctx)
|
|||||||
tcg_temp_free(t0);
|
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. */
|
/* stwcx. */
|
||||||
static void gen_stwcx_(DisasContext *ctx)
|
static void gen_stwcx_(DisasContext *ctx)
|
||||||
{
|
{
|
||||||
int l1;
|
|
||||||
TCGv t0;
|
TCGv t0;
|
||||||
gen_set_access_type(ctx, ACCESS_RES);
|
gen_set_access_type(ctx, ACCESS_RES);
|
||||||
t0 = tcg_temp_local_new();
|
t0 = tcg_temp_local_new();
|
||||||
gen_addr_reg_index(ctx, t0);
|
gen_addr_reg_index(ctx, t0);
|
||||||
gen_check_align(ctx, t0, 0x03);
|
gen_check_align(ctx, t0, 0x03);
|
||||||
tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
|
#if defined(CONFIG_USER_ONLY)
|
||||||
tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
|
gen_conditional_store(ctx, t0, rS(ctx->opcode), 4);
|
||||||
tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
|
#else
|
||||||
l1 = gen_new_label();
|
{
|
||||||
tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
|
int l1;
|
||||||
tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
|
|
||||||
gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], t0);
|
tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
|
||||||
gen_set_label(l1);
|
tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
|
||||||
tcg_gen_movi_tl(cpu_reserve, -1);
|
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);
|
tcg_temp_free(t0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3058,21 +3083,27 @@ static void gen_ldarx(DisasContext *ctx)
|
|||||||
/* stdcx. */
|
/* stdcx. */
|
||||||
static void gen_stdcx_(DisasContext *ctx)
|
static void gen_stdcx_(DisasContext *ctx)
|
||||||
{
|
{
|
||||||
int l1;
|
|
||||||
TCGv t0;
|
TCGv t0;
|
||||||
gen_set_access_type(ctx, ACCESS_RES);
|
gen_set_access_type(ctx, ACCESS_RES);
|
||||||
t0 = tcg_temp_local_new();
|
t0 = tcg_temp_local_new();
|
||||||
gen_addr_reg_index(ctx, t0);
|
gen_addr_reg_index(ctx, t0);
|
||||||
gen_check_align(ctx, t0, 0x07);
|
gen_check_align(ctx, t0, 0x07);
|
||||||
tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
|
#if defined(CONFIG_USER_ONLY)
|
||||||
tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
|
gen_conditional_store(ctx, t0, rS(ctx->opcode), 8);
|
||||||
tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
|
#else
|
||||||
l1 = gen_new_label();
|
{
|
||||||
tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
|
int l1;
|
||||||
tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
|
tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
|
||||||
gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], t0);
|
tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
|
||||||
gen_set_label(l1);
|
tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
|
||||||
tcg_gen_movi_tl(cpu_reserve, -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);
|
tcg_temp_free(t0);
|
||||||
}
|
}
|
||||||
#endif /* defined(TARGET_PPC64) */
|
#endif /* defined(TARGET_PPC64) */
|
||||||
|
Loading…
Reference in New Issue
Block a user