From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1L6p69-0006ql-Mg for qemu-devel@nongnu.org; Sun, 30 Nov 2008 11:24:41 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1L6p68-0006qL-Qq for qemu-devel@nongnu.org; Sun, 30 Nov 2008 11:24:41 -0500 Received: from [199.232.76.173] (port=39022 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1L6p68-0006qG-ND for qemu-devel@nongnu.org; Sun, 30 Nov 2008 11:24:40 -0500 Received: from savannah.gnu.org ([199.232.41.3]:48811 helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1L6p68-0007AP-DA for qemu-devel@nongnu.org; Sun, 30 Nov 2008 11:24:40 -0500 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.63) (envelope-from ) id 1L6p67-000603-Sl for qemu-devel@nongnu.org; Sun, 30 Nov 2008 16:24:39 +0000 Received: from aurel32 by cvs.savannah.gnu.org with local (Exim 4.63) (envelope-from ) id 1L6p67-0005zx-Gd for qemu-devel@nongnu.org; Sun, 30 Nov 2008 16:24:39 +0000 MIME-Version: 1.0 Errors-To: aurel32 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Aurelien Jarno Message-Id: Date: Sun, 30 Nov 2008 16:24:39 +0000 Subject: [Qemu-devel] [5830] target-ppc: convert load/store with reservation instructions to TCG Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Revision: 5830 http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=5830 Author: aurel32 Date: 2008-11-30 16:24:39 +0000 (Sun, 30 Nov 2008) Log Message: ----------- target-ppc: convert load/store with reservation instructions to TCG Signed-off-by: Aurelien Jarno Modified Paths: -------------- trunk/target-ppc/op_mem.h trunk/target-ppc/translate.c Modified: trunk/target-ppc/op_mem.h =================================================================== --- trunk/target-ppc/op_mem.h 2008-11-30 16:24:30 UTC (rev 5829) +++ trunk/target-ppc/op_mem.h 2008-11-30 16:24:39 UTC (rev 5830) @@ -20,232 +20,6 @@ #include "op_mem_access.h" -/* Load and set reservation */ -void OPPROTO glue(op_lwarx, MEMSUFFIX) (void) -{ - if (unlikely(T0 & 0x03)) { - raise_exception(env, POWERPC_EXCP_ALIGN); - } else { - T1 = glue(ldu32, MEMSUFFIX)((uint32_t)T0); - env->reserve = (uint32_t)T0; - } - RETURN(); -} - -#if defined(TARGET_PPC64) -void OPPROTO glue(op_lwarx_64, MEMSUFFIX) (void) -{ - if (unlikely(T0 & 0x03)) { - raise_exception(env, POWERPC_EXCP_ALIGN); - } else { - T1 = glue(ldu32, MEMSUFFIX)((uint64_t)T0); - env->reserve = (uint64_t)T0; - } - RETURN(); -} - -void OPPROTO glue(op_ldarx, MEMSUFFIX) (void) -{ - if (unlikely(T0 & 0x03)) { - raise_exception(env, POWERPC_EXCP_ALIGN); - } else { - T1 = glue(ldu64, MEMSUFFIX)((uint32_t)T0); - env->reserve = (uint32_t)T0; - } - RETURN(); -} - -void OPPROTO glue(op_ldarx_64, MEMSUFFIX) (void) -{ - if (unlikely(T0 & 0x03)) { - raise_exception(env, POWERPC_EXCP_ALIGN); - } else { - T1 = glue(ldu64, MEMSUFFIX)((uint64_t)T0); - env->reserve = (uint64_t)T0; - } - RETURN(); -} -#endif - -void OPPROTO glue(op_lwarx_le, MEMSUFFIX) (void) -{ - if (unlikely(T0 & 0x03)) { - raise_exception(env, POWERPC_EXCP_ALIGN); - } else { - T1 = glue(ldu32r, MEMSUFFIX)((uint32_t)T0); - env->reserve = (uint32_t)T0; - } - RETURN(); -} - -#if defined(TARGET_PPC64) -void OPPROTO glue(op_lwarx_le_64, MEMSUFFIX) (void) -{ - if (unlikely(T0 & 0x03)) { - raise_exception(env, POWERPC_EXCP_ALIGN); - } else { - T1 = glue(ldu32r, MEMSUFFIX)((uint64_t)T0); - env->reserve = (uint64_t)T0; - } - RETURN(); -} - -void OPPROTO glue(op_ldarx_le, MEMSUFFIX) (void) -{ - if (unlikely(T0 & 0x03)) { - raise_exception(env, POWERPC_EXCP_ALIGN); - } else { - T1 = glue(ldu64r, MEMSUFFIX)((uint32_t)T0); - env->reserve = (uint32_t)T0; - } - RETURN(); -} - -void OPPROTO glue(op_ldarx_le_64, MEMSUFFIX) (void) -{ - if (unlikely(T0 & 0x03)) { - raise_exception(env, POWERPC_EXCP_ALIGN); - } else { - T1 = glue(ldu64r, MEMSUFFIX)((uint64_t)T0); - env->reserve = (uint64_t)T0; - } - RETURN(); -} -#endif - -/* Store with reservation */ -void OPPROTO glue(op_stwcx, MEMSUFFIX) (void) -{ - if (unlikely(T0 & 0x03)) { - raise_exception(env, POWERPC_EXCP_ALIGN); - } else { - if (unlikely(env->reserve != (uint32_t)T0)) { - env->crf[0] = xer_so; - } else { - glue(st32, MEMSUFFIX)((uint32_t)T0, T1); - env->crf[0] = xer_so | 0x02; - } - } - env->reserve = (target_ulong)-1ULL; - RETURN(); -} - -#if defined(TARGET_PPC64) -void OPPROTO glue(op_stwcx_64, MEMSUFFIX) (void) -{ - if (unlikely(T0 & 0x03)) { - raise_exception(env, POWERPC_EXCP_ALIGN); - } else { - if (unlikely(env->reserve != (uint64_t)T0)) { - env->crf[0] = xer_so; - } else { - glue(st32, MEMSUFFIX)((uint64_t)T0, T1); - env->crf[0] = xer_so | 0x02; - } - } - env->reserve = (target_ulong)-1ULL; - RETURN(); -} - -void OPPROTO glue(op_stdcx, MEMSUFFIX) (void) -{ - if (unlikely(T0 & 0x03)) { - raise_exception(env, POWERPC_EXCP_ALIGN); - } else { - if (unlikely(env->reserve != (uint32_t)T0)) { - env->crf[0] = xer_so; - } else { - glue(st64, MEMSUFFIX)((uint32_t)T0, T1); - env->crf[0] = xer_so | 0x02; - } - } - env->reserve = (target_ulong)-1ULL; - RETURN(); -} - -void OPPROTO glue(op_stdcx_64, MEMSUFFIX) (void) -{ - if (unlikely(T0 & 0x03)) { - raise_exception(env, POWERPC_EXCP_ALIGN); - } else { - if (unlikely(env->reserve != (uint64_t)T0)) { - env->crf[0] = xer_so; - } else { - glue(st64, MEMSUFFIX)((uint64_t)T0, T1); - env->crf[0] = xer_so | 0x02; - } - } - env->reserve = (target_ulong)-1ULL; - RETURN(); -} -#endif - -void OPPROTO glue(op_stwcx_le, MEMSUFFIX) (void) -{ - if (unlikely(T0 & 0x03)) { - raise_exception(env, POWERPC_EXCP_ALIGN); - } else { - if (unlikely(env->reserve != (uint32_t)T0)) { - env->crf[0] = xer_so; - } else { - glue(st32r, MEMSUFFIX)((uint32_t)T0, T1); - env->crf[0] = xer_so | 0x02; - } - } - env->reserve = (target_ulong)-1ULL; - RETURN(); -} - -#if defined(TARGET_PPC64) -void OPPROTO glue(op_stwcx_le_64, MEMSUFFIX) (void) -{ - if (unlikely(T0 & 0x03)) { - raise_exception(env, POWERPC_EXCP_ALIGN); - } else { - if (unlikely(env->reserve != (uint64_t)T0)) { - env->crf[0] = xer_so; - } else { - glue(st32r, MEMSUFFIX)((uint64_t)T0, T1); - env->crf[0] = xer_so | 0x02; - } - } - env->reserve = (target_ulong)-1ULL; - RETURN(); -} - -void OPPROTO glue(op_stdcx_le, MEMSUFFIX) (void) -{ - if (unlikely(T0 & 0x03)) { - raise_exception(env, POWERPC_EXCP_ALIGN); - } else { - if (unlikely(env->reserve != (uint32_t)T0)) { - env->crf[0] = xer_so; - } else { - glue(st64r, MEMSUFFIX)((uint32_t)T0, T1); - env->crf[0] = xer_so | 0x02; - } - } - env->reserve = (target_ulong)-1ULL; - RETURN(); -} - -void OPPROTO glue(op_stdcx_le_64, MEMSUFFIX) (void) -{ - if (unlikely(T0 & 0x03)) { - raise_exception(env, POWERPC_EXCP_ALIGN); - } else { - if (unlikely(env->reserve != (uint64_t)T0)) { - env->crf[0] = xer_so; - } else { - glue(st64r, MEMSUFFIX)((uint64_t)T0, T1); - env->crf[0] = xer_so | 0x02; - } - } - env->reserve = (target_ulong)-1ULL; - RETURN(); -} -#endif - /* External access */ void OPPROTO glue(op_eciwx, MEMSUFFIX) (void) { Modified: trunk/target-ppc/translate.c =================================================================== --- trunk/target-ppc/translate.c 2008-11-30 16:24:30 UTC (rev 5829) +++ trunk/target-ppc/translate.c 2008-11-30 16:24:39 UTC (rev 5830) @@ -66,6 +66,7 @@ static TCGv cpu_ctr; static TCGv cpu_lr; static TCGv cpu_xer; +static TCGv cpu_reserve; static TCGv_i32 cpu_fpscr; static TCGv_i32 cpu_access_type; @@ -161,6 +162,9 @@ cpu_xer = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, xer), "xer"); + cpu_reserve = tcg_global_mem_new(TCG_AREG0, + offsetof(CPUState, reserve), "reserve"); + cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, fpscr), "fpscr"); @@ -2468,6 +2472,24 @@ tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]); } +static always_inline void gen_check_align (DisasContext *ctx, TCGv EA, int mask) +{ + int l1 = gen_new_label(); + TCGv t0 = tcg_temp_new(); + TCGv_i32 t1, t2; + /* NIP cannot be restored if the memory exception comes from an helper */ + gen_update_nip(ctx, ctx->nip - 4); + tcg_gen_andi_tl(t0, EA, mask); + tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); + t1 = tcg_const_i32(POWERPC_EXCP_ALIGN); + t2 = tcg_const_i32(0); + gen_helper_raise_exception_err(t1, t2); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t2); + gen_set_label(l1); + tcg_temp_free(t0); +} + #if defined(TARGET_PPC64) #define _GEN_MEM_FUNCS(name, mode) \ &gen_op_##name##_##mode, \ @@ -3220,67 +3242,79 @@ GEN_STOP(ctx); } -#define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])() -#define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])() -static GenOpFunc *gen_op_lwarx[NB_MEM_FUNCS] = { - GEN_MEM_FUNCS(lwarx), -}; -static GenOpFunc *gen_op_stwcx[NB_MEM_FUNCS] = { - GEN_MEM_FUNCS(stwcx), -}; - /* lwarx */ GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES) { - /* NIP cannot be restored if the memory exception comes from an helper */ - gen_update_nip(ctx, ctx->nip - 4); + TCGv t0 = tcg_temp_local_new(); gen_set_access_type(ACCESS_RES); - gen_addr_reg_index(cpu_T[0], ctx); - op_lwarx(); - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]); + gen_addr_reg_index(t0, ctx); + gen_check_align(ctx, t0, 0x03); +#if defined(TARGET_PPC64) + if (!ctx->sf_mode) + tcg_gen_ext32u_tl(t0, t0); +#endif + gen_qemu_ld32u(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx); + tcg_gen_mov_tl(cpu_reserve, t0); + tcg_temp_free(t0); } /* stwcx. */ GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES) { - /* NIP cannot be restored if the memory exception comes from an helper */ - gen_update_nip(ctx, ctx->nip - 4); + int l1 = gen_new_label(); + TCGv t0 = tcg_temp_local_new(); gen_set_access_type(ACCESS_RES); - gen_addr_reg_index(cpu_T[0], ctx); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); - op_stwcx(); + gen_addr_reg_index(t0, ctx); + gen_check_align(ctx, t0, 0x03); +#if defined(TARGET_PPC64) + if (!ctx->sf_mode) + tcg_gen_ext32u_tl(t0, t0); +#endif + 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); + 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(cpu_gpr[rS(ctx->opcode)], t0, ctx->mem_idx); + gen_set_label(l1); + tcg_gen_movi_tl(cpu_reserve, -1); + tcg_temp_free(t0); } #if defined(TARGET_PPC64) -#define op_ldarx() (*gen_op_ldarx[ctx->mem_idx])() -#define op_stdcx() (*gen_op_stdcx[ctx->mem_idx])() -static GenOpFunc *gen_op_ldarx[NB_MEM_FUNCS] = { - GEN_MEM_FUNCS(ldarx), -}; -static GenOpFunc *gen_op_stdcx[NB_MEM_FUNCS] = { - GEN_MEM_FUNCS(stdcx), -}; - /* ldarx */ GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B) { - /* NIP cannot be restored if the memory exception comes from an helper */ - gen_update_nip(ctx, ctx->nip - 4); + TCGv t0 = tcg_temp_local_new(); gen_set_access_type(ACCESS_RES); - gen_addr_reg_index(cpu_T[0], ctx); - op_ldarx(); - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]); + gen_addr_reg_index(t0, ctx); + gen_check_align(ctx, t0, 0x07); + if (!ctx->sf_mode) + tcg_gen_ext32u_tl(t0, t0); + gen_qemu_ld64(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx); + tcg_gen_mov_tl(cpu_reserve, t0); + tcg_temp_free(t0); } /* stdcx. */ GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B) { - /* NIP cannot be restored if the memory exception comes from an helper */ - gen_update_nip(ctx, ctx->nip - 4); + int l1 = gen_new_label(); + TCGv t0 = tcg_temp_local_new(); gen_set_access_type(ACCESS_RES); - gen_addr_reg_index(cpu_T[0], ctx); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); - op_stdcx(); + gen_addr_reg_index(t0, ctx); + gen_check_align(ctx, t0, 0x07); + if (!ctx->sf_mode) + tcg_gen_ext32u_tl(t0, t0); + 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); + 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(cpu_gpr[rS(ctx->opcode)], t0, ctx->mem_idx); + gen_set_label(l1); + tcg_gen_movi_tl(cpu_reserve, -1); + tcg_temp_free(t0); } #endif /* defined(TARGET_PPC64) */