diff options
author | Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> | 2016-09-12 12:11:37 +0530 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2016-09-23 10:29:40 +1000 |
commit | aa2008af0c1cd26f6a7c522825438f8d1d3de272 (patch) | |
tree | 78205043242182d466cdc8646d0f50525cbe9647 /target-ppc | |
parent | 48793c95c963c3def3b6f3ecdbf89ec098d5e494 (diff) |
target-ppc: move out stqcx impementation
Being a 16byte operation, qemu_ld/st still does not support this. Move
this out so other store operation can use qemu_ld/st in the following
patch. Also, convert it to two MO_Q operations for stqcx.
Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'target-ppc')
-rw-r--r-- | target-ppc/translate.c | 69 |
1 files changed, 47 insertions, 22 deletions
diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 72e78ff8ef..618fe43da7 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -3105,22 +3105,6 @@ static void gen_conditional_store(DisasContext *ctx, TCGv EA, gen_qemu_st32(ctx, cpu_gpr[reg], EA); } else if (size == 2) { gen_qemu_st16(ctx, cpu_gpr[reg], EA); -#if defined(TARGET_PPC64) - } else if (size == 16) { - TCGv gpr1, gpr2 , EA8; - if (unlikely(ctx->le_mode)) { - gpr1 = cpu_gpr[reg+1]; - gpr2 = cpu_gpr[reg]; - } else { - gpr1 = cpu_gpr[reg]; - gpr2 = cpu_gpr[reg+1]; - } - gen_qemu_st64_i64(ctx, gpr1, EA); - EA8 = tcg_temp_local_new(); - gen_addr_add(ctx, EA8, EA, 8); - gen_qemu_st64_i64(ctx, gpr2, EA8); - tcg_temp_free(EA8); -#endif } else { gen_qemu_st8(ctx, cpu_gpr[reg], EA); } @@ -3133,11 +3117,6 @@ static void gen_conditional_store(DisasContext *ctx, TCGv EA, static void gen_##name(DisasContext *ctx) \ { \ TCGv t0; \ - if (unlikely((len == 16) && (rD(ctx->opcode) & 1))) { \ - gen_inval_exception(ctx, \ - POWERPC_EXCP_INVAL_INVAL); \ - return; \ - } \ gen_set_access_type(ctx, ACCESS_RES); \ t0 = tcg_temp_local_new(); \ gen_addr_reg_index(ctx, t0); \ @@ -3190,9 +3169,55 @@ static void gen_lqarx(DisasContext *ctx) tcg_temp_free(EA); } +/* stqcx. */ +static void gen_stqcx_(DisasContext *ctx) +{ + TCGv EA; + int reg = rS(ctx->opcode); + int len = 16; +#if !defined(CONFIG_USER_ONLY) + TCGLabel *l1; + TCGv gpr1, gpr2; +#endif + + if (unlikely((rD(ctx->opcode) & 1))) { + gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); + return; + } + gen_set_access_type(ctx, ACCESS_RES); + EA = tcg_temp_local_new(); + gen_addr_reg_index(ctx, EA); + if (len > 1) { + gen_check_align(ctx, EA, (len) - 1); + } + +#if defined(CONFIG_USER_ONLY) + gen_conditional_store(ctx, EA, reg, 16); +#else + tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so); + l1 = gen_new_label(); + tcg_gen_brcond_tl(TCG_COND_NE, EA, cpu_reserve, l1); + tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ); + + if (unlikely(ctx->le_mode)) { + gpr1 = cpu_gpr[reg + 1]; + gpr2 = cpu_gpr[reg]; + } else { + gpr1 = cpu_gpr[reg]; + gpr2 = cpu_gpr[reg + 1]; + } + tcg_gen_qemu_st_tl(gpr1, EA, ctx->mem_idx, DEF_MEMOP(MO_Q)); + gen_addr_add(ctx, EA, EA, 8); + tcg_gen_qemu_st_tl(gpr2, EA, ctx->mem_idx, DEF_MEMOP(MO_Q)); + + gen_set_label(l1); + tcg_gen_movi_tl(cpu_reserve, -1); +#endif + tcg_temp_free(EA); +} + /* stdcx. */ STCX(stdcx_, 8); -STCX(stqcx_, 16); #endif /* defined(TARGET_PPC64) */ /* sync */ |