diff mbox

[4/7] target-ppc: add exceptions for conditional stores

Message ID 1249314209-10230-5-git-send-email-froydnj@codesourcery.com
State Superseded
Headers show

Commit Message

Nathan Froyd Aug. 3, 2009, 3:43 p.m. UTC
Signed-off-by: Nathan Froyd <froydnj@codesourcery.com>
---
 target-ppc/cpu.h       |    5 +++
 target-ppc/translate.c |   71 ++++++++++++++++++++++++++++++++++-------------
 2 files changed, 56 insertions(+), 20 deletions(-)
diff mbox

Patch

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 7935fcd..8c1029e 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -218,6 +218,7 @@  enum {
     /* Qemu exceptions: special cases we want to stop translation            */
     POWERPC_EXCP_SYNC         = 0x202, /* context synchronizing instruction  */
     POWERPC_EXCP_SYSCALL_USER = 0x203, /* System call in user mode only      */
+    POWERPC_EXCP_STCX         = 0x204 /* Conditional stores in user mode     */
 };
 
 /* Exceptions error codes                                                    */
@@ -564,6 +565,10 @@  struct CPUPPCState {
     target_ulong reserve_addr;
     /* Reservation value */
     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 */
     /* machine state register */
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 06282b6..f82c6e5 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) */