summaryrefslogtreecommitdiff
path: root/target-alpha/translate.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-alpha/translate.c')
-rw-r--r--target-alpha/translate.c104
1 files changed, 45 insertions, 59 deletions
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index a2e2a62098..03e47765ed 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -99,7 +99,6 @@ static TCGv cpu_std_ir[31];
static TCGv cpu_fir[31];
static TCGv cpu_pc;
static TCGv cpu_lock_addr;
-static TCGv cpu_lock_st_addr;
static TCGv cpu_lock_value;
#ifndef CONFIG_USER_ONLY
@@ -116,7 +115,6 @@ void alpha_translate_init(void)
static const GlobalVar vars[] = {
DEF_VAR(pc),
DEF_VAR(lock_addr),
- DEF_VAR(lock_st_addr),
DEF_VAR(lock_value),
};
@@ -198,6 +196,23 @@ static TCGv dest_sink(DisasContext *ctx)
return ctx->sink;
}
+static void free_context_temps(DisasContext *ctx)
+{
+ if (!TCGV_IS_UNUSED_I64(ctx->sink)) {
+ tcg_gen_discard_i64(ctx->sink);
+ tcg_temp_free(ctx->sink);
+ TCGV_UNUSED_I64(ctx->sink);
+ }
+ if (!TCGV_IS_UNUSED_I64(ctx->zero)) {
+ tcg_temp_free(ctx->zero);
+ TCGV_UNUSED_I64(ctx->zero);
+ }
+ if (!TCGV_IS_UNUSED_I64(ctx->lit)) {
+ tcg_temp_free(ctx->lit);
+ TCGV_UNUSED_I64(ctx->lit);
+ }
+}
+
static TCGv load_gpr(DisasContext *ctx, unsigned reg)
{
if (likely(reg < 31)) {
@@ -395,56 +410,37 @@ static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
int32_t disp16, int mem_idx,
TCGMemOp op)
{
- TCGv addr;
-
- if (ra == 31) {
- /* ??? Don't bother storing anything. The user can't tell
- the difference, since the zero register always reads zero. */
- return NO_EXIT;
- }
-
-#if defined(CONFIG_USER_ONLY)
- addr = cpu_lock_st_addr;
-#else
- addr = tcg_temp_local_new();
-#endif
+ TCGLabel *lab_fail, *lab_done;
+ TCGv addr, val;
+ addr = tcg_temp_new_i64();
tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
+ free_context_temps(ctx);
-#if defined(CONFIG_USER_ONLY)
- /* ??? This is handled via a complicated version of compare-and-swap
- in the cpu_loop. Hopefully one day we'll have a real CAS opcode
- in TCG so that this isn't necessary. */
- return gen_excp(ctx, (op & MO_SIZE) == MO_64 ? EXCP_STQ_C : EXCP_STL_C, ra);
-#else
- /* ??? In system mode we are never multi-threaded, so CAS can be
- implemented via a non-atomic load-compare-store sequence. */
- {
- TCGLabel *lab_fail, *lab_done;
- TCGv val;
+ lab_fail = gen_new_label();
+ lab_done = gen_new_label();
+ tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
+ tcg_temp_free_i64(addr);
- lab_fail = gen_new_label();
- lab_done = gen_new_label();
- tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
+ val = tcg_temp_new_i64();
+ tcg_gen_atomic_cmpxchg_i64(val, cpu_lock_addr, cpu_lock_value,
+ load_gpr(ctx, ra), mem_idx, op);
+ free_context_temps(ctx);
- val = tcg_temp_new();
- tcg_gen_qemu_ld_i64(val, addr, mem_idx, op);
- tcg_gen_brcond_i64(TCG_COND_NE, val, cpu_lock_value, lab_fail);
-
- tcg_gen_qemu_st_i64(ctx->ir[ra], addr, mem_idx, op);
- tcg_gen_movi_i64(ctx->ir[ra], 1);
- tcg_gen_br(lab_done);
+ if (ra != 31) {
+ tcg_gen_setcond_i64(TCG_COND_EQ, ctx->ir[ra], val, cpu_lock_value);
+ }
+ tcg_temp_free_i64(val);
+ tcg_gen_br(lab_done);
- gen_set_label(lab_fail);
+ gen_set_label(lab_fail);
+ if (ra != 31) {
tcg_gen_movi_i64(ctx->ir[ra], 0);
-
- gen_set_label(lab_done);
- tcg_gen_movi_i64(cpu_lock_addr, -1);
-
- tcg_temp_free(addr);
- return NO_EXIT;
}
-#endif
+
+ gen_set_label(lab_done);
+ tcg_gen_movi_i64(cpu_lock_addr, -1);
+ return NO_EXIT;
}
static bool in_superpage(DisasContext *ctx, int64_t addr)
@@ -2914,6 +2910,10 @@ void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
/* Similarly for flush-to-zero. */
ctx.tb_ftz = -1;
+ TCGV_UNUSED_I64(ctx.zero);
+ TCGV_UNUSED_I64(ctx.sink);
+ TCGV_UNUSED_I64(ctx.lit);
+
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0) {
@@ -2948,23 +2948,9 @@ void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
}
insn = cpu_ldl_code(env, ctx.pc);
- TCGV_UNUSED_I64(ctx.zero);
- TCGV_UNUSED_I64(ctx.sink);
- TCGV_UNUSED_I64(ctx.lit);
-
ctx.pc += 4;
ret = translate_one(ctxp, insn);
-
- if (!TCGV_IS_UNUSED_I64(ctx.sink)) {
- tcg_gen_discard_i64(ctx.sink);
- tcg_temp_free(ctx.sink);
- }
- if (!TCGV_IS_UNUSED_I64(ctx.zero)) {
- tcg_temp_free(ctx.zero);
- }
- if (!TCGV_IS_UNUSED_I64(ctx.lit)) {
- tcg_temp_free(ctx.lit);
- }
+ free_context_temps(ctxp);
/* If we reach a page boundary, are single stepping,
or exhaust instruction count, stop generation. */