From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1L8V0W-0003ge-Hb for qemu-devel@nongnu.org; Fri, 05 Dec 2008 02:21:48 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1L8V0V-0003g8-Er for qemu-devel@nongnu.org; Fri, 05 Dec 2008 02:21:48 -0500 Received: from [199.232.76.173] (port=46029 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1L8V0V-0003g2-Ae for qemu-devel@nongnu.org; Fri, 05 Dec 2008 02:21:47 -0500 Received: from savannah.gnu.org ([199.232.41.3]:44033 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 1L8V0U-0007qQ-Jy for qemu-devel@nongnu.org; Fri, 05 Dec 2008 02:21:46 -0500 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.63) (envelope-from ) id 1L8V0U-0003wj-07 for qemu-devel@nongnu.org; Fri, 05 Dec 2008 07:21:46 +0000 Received: from aurel32 by cvs.savannah.gnu.org with local (Exim 4.63) (envelope-from ) id 1L8V0T-0003wf-Da for qemu-devel@nongnu.org; Fri, 05 Dec 2008 07:21:45 +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: Fri, 05 Dec 2008 07:21:45 +0000 Subject: [Qemu-devel] [5882] target-ppc: convert POWER shift 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: 5882 http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=5882 Author: aurel32 Date: 2008-12-05 07:21:44 +0000 (Fri, 05 Dec 2008) Log Message: ----------- target-ppc: convert POWER shift instructions to TCG Signed-off-by: Aurelien Jarno Modified Paths: -------------- trunk/target-ppc/exec.h trunk/target-ppc/op.c trunk/target-ppc/translate.c Modified: trunk/target-ppc/exec.h =================================================================== --- trunk/target-ppc/exec.h 2008-12-05 07:21:31 UTC (rev 5881) +++ trunk/target-ppc/exec.h 2008-12-05 07:21:44 UTC (rev 5882) @@ -51,28 +51,6 @@ # define RETURN() __asm__ __volatile__("" : : : "memory"); #endif -static always_inline target_ulong rotl8 (target_ulong i, int n) -{ - return (((uint8_t)i << n) | ((uint8_t)i >> (8 - n))); -} - -static always_inline target_ulong rotl16 (target_ulong i, int n) -{ - return (((uint16_t)i << n) | ((uint16_t)i >> (16 - n))); -} - -static always_inline target_ulong rotl32 (target_ulong i, int n) -{ - return (((uint32_t)i << n) | ((uint32_t)i >> (32 - n))); -} - -#if defined(TARGET_PPC64) -static always_inline target_ulong rotl64 (target_ulong i, int n) -{ - return (((uint64_t)i << n) | ((uint64_t)i >> (64 - n))); -} -#endif - #if !defined(CONFIG_USER_ONLY) #include "softmmu_exec.h" #endif /* !defined(CONFIG_USER_ONLY) */ Modified: trunk/target-ppc/op.c =================================================================== --- trunk/target-ppc/op.c 2008-12-05 07:21:31 UTC (rev 5881) +++ trunk/target-ppc/op.c 2008-12-05 07:21:44 UTC (rev 5882) @@ -476,133 +476,6 @@ RETURN(); } -/* XXX: factorise POWER rotates... */ -void OPPROTO op_POWER_rlmi (void) -{ - T0 = rotl32(T0, T2) & PARAM1; - T0 |= T1 & (uint32_t)PARAM2; - RETURN(); -} - -void OPPROTO op_POWER_rrib (void) -{ - T2 &= 0x1FUL; - T0 = rotl32(T0 & INT32_MIN, T2); - T0 |= T1 & ~rotl32(INT32_MIN, T2); - RETURN(); -} - -void OPPROTO op_POWER_sle (void) -{ - T1 &= 0x1FUL; - env->spr[SPR_MQ] = rotl32(T0, T1); - T0 = T0 << T1; - RETURN(); -} - -void OPPROTO op_POWER_sleq (void) -{ - uint32_t tmp = env->spr[SPR_MQ]; - - T1 &= 0x1FUL; - env->spr[SPR_MQ] = rotl32(T0, T1); - T0 = T0 << T1; - T0 |= tmp >> (32 - T1); - RETURN(); -} - -void OPPROTO op_POWER_sllq (void) -{ - uint32_t msk = UINT32_MAX; - - msk = msk << (T1 & 0x1FUL); - if (T1 & 0x20UL) - msk = ~msk; - T1 &= 0x1FUL; - T0 = (T0 << T1) & msk; - T0 |= env->spr[SPR_MQ] & ~msk; - RETURN(); -} - -void OPPROTO op_POWER_slq (void) -{ - uint32_t msk = UINT32_MAX, tmp; - - msk = msk << (T1 & 0x1FUL); - if (T1 & 0x20UL) - msk = ~msk; - T1 &= 0x1FUL; - tmp = rotl32(T0, T1); - T0 = tmp & msk; - env->spr[SPR_MQ] = tmp; - RETURN(); -} - -void OPPROTO op_POWER_sraq (void) -{ - env->spr[SPR_MQ] = rotl32(T0, 32 - (T1 & 0x1FUL)); - if (T1 & 0x20UL) - T0 = UINT32_MAX; - else - T0 = (int32_t)T0 >> T1; - RETURN(); -} - -void OPPROTO op_POWER_sre (void) -{ - T1 &= 0x1FUL; - env->spr[SPR_MQ] = rotl32(T0, 32 - T1); - T0 = (int32_t)T0 >> T1; - RETURN(); -} - -void OPPROTO op_POWER_srea (void) -{ - T1 &= 0x1FUL; - env->spr[SPR_MQ] = T0 >> T1; - T0 = (int32_t)T0 >> T1; - RETURN(); -} - -void OPPROTO op_POWER_sreq (void) -{ - uint32_t tmp; - int32_t msk; - - T1 &= 0x1FUL; - msk = INT32_MIN >> T1; - tmp = env->spr[SPR_MQ]; - env->spr[SPR_MQ] = rotl32(T0, 32 - T1); - T0 = T0 >> T1; - T0 |= tmp & msk; - RETURN(); -} - -void OPPROTO op_POWER_srlq (void) -{ - uint32_t tmp; - int32_t msk; - - msk = INT32_MIN >> (T1 & 0x1FUL); - if (T1 & 0x20UL) - msk = ~msk; - T1 &= 0x1FUL; - tmp = env->spr[SPR_MQ]; - env->spr[SPR_MQ] = rotl32(T0, 32 - T1); - T0 = T0 >> T1; - T0 &= msk; - T0 |= tmp & ~msk; - RETURN(); -} - -void OPPROTO op_POWER_srq (void) -{ - T1 &= 0x1FUL; - env->spr[SPR_MQ] = rotl32(T0, 32 - T1); - T0 = T0 >> T1; - RETURN(); -} - /* POWER instructions not implemented in PowerPC 601 */ #if !defined(CONFIG_USER_ONLY) void OPPROTO op_POWER_mfsri (void) Modified: trunk/target-ppc/translate.c =================================================================== --- trunk/target-ppc/translate.c 2008-12-05 07:21:31 UTC (rev 5881) +++ trunk/target-ppc/translate.c 2008-12-05 07:21:44 UTC (rev 5882) @@ -4626,195 +4626,361 @@ /* rlmi - rlmi. */ GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR) { - uint32_t mb, me; - - mb = MB(ctx->opcode); - me = ME(ctx->opcode); - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]); - gen_op_POWER_rlmi(MASK(mb, me), ~MASK(mb, me)); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + uint32_t mb = MB(ctx->opcode); + uint32_t me = ME(ctx->opcode); + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F); + tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0); + tcg_gen_andi_tl(t0, t0, MASK(mb, me)); + tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me)); + tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0); + tcg_temp_free(t0); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* rrib - rrib. */ GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]); - gen_op_POWER_rrib(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F); + tcg_gen_movi_tl(t1, 0x80000000); + tcg_gen_shr_tl(t1, t1, t0); + tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0); + tcg_gen_and_tl(t0, t0, t1); + tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1); + tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); + tcg_temp_free(t0); + tcg_temp_free(t1); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* sle - sle. */ GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); - gen_op_POWER_sle(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F); + tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1); + tcg_gen_subfi_tl(t1, 32, t1); + tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1); + tcg_gen_or_tl(t1, t0, t1); + tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0); + gen_store_spr(SPR_MQ, t1); + tcg_temp_free(t0); + tcg_temp_free(t1); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* sleq - sleq. */ GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); - gen_op_POWER_sleq(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_temp_new(); + tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F); + tcg_gen_movi_tl(t2, 0xFFFFFFFF); + tcg_gen_shl_tl(t2, t2, t0); + tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0); + gen_load_spr(t1, SPR_MQ); + gen_store_spr(SPR_MQ, t0); + tcg_gen_and_tl(t0, t0, t2); + tcg_gen_andc_tl(t1, t1, t2); + tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* sliq - sliq. */ GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode)); - gen_op_POWER_sle(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + int sh = SH(ctx->opcode); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh); + tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh); + tcg_gen_or_tl(t1, t0, t1); + tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0); + gen_store_spr(SPR_MQ, t1); + tcg_temp_free(t0); + tcg_temp_free(t1); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* slliq - slliq. */ GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode)); - gen_op_POWER_sleq(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + int sh = SH(ctx->opcode); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh); + gen_load_spr(t1, SPR_MQ); + gen_store_spr(SPR_MQ, t0); + tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU << sh)); + tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh)); + tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); + tcg_temp_free(t0); + tcg_temp_free(t1); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* sllq - sllq. */ GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); - gen_op_POWER_sllq(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + int l1 = gen_new_label(); + int l2 = gen_new_label(); + TCGv t0 = tcg_temp_local_new(); + TCGv t1 = tcg_temp_local_new(); + TCGv t2 = tcg_temp_local_new(); + tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F); + tcg_gen_movi_tl(t1, 0xFFFFFFFF); + tcg_gen_shl_tl(t1, t1, t2); + tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20); + tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); + gen_load_spr(t0, SPR_MQ); + tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); + tcg_gen_br(l2); + gen_set_label(l1); + tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2); + gen_load_spr(t2, SPR_MQ); + tcg_gen_andc_tl(t1, t2, t1); + tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); + gen_set_label(l2); + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* slq - slq. */ GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); - gen_op_POWER_slq(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + int l1 = gen_new_label(); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F); + tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1); + tcg_gen_subfi_tl(t1, 32, t1); + tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1); + tcg_gen_or_tl(t1, t0, t1); + gen_store_spr(SPR_MQ, t1); + tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20); + tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0); + tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); + tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0); + gen_set_label(l1); + tcg_temp_free(t0); + tcg_temp_free(t1); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* sraiq - sraiq. */ GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode)); - gen_op_POWER_sraq(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + int sh = SH(ctx->opcode); + int l1 = gen_new_label(); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh); + tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh); + tcg_gen_or_tl(t0, t0, t1); + gen_store_spr(SPR_MQ, t0); + tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA)); + tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); + tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1); + tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA)); + gen_set_label(l1); + tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh); + tcg_temp_free(t0); + tcg_temp_free(t1); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* sraq - sraq. */ GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); - gen_op_POWER_sraq(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + int l1 = gen_new_label(); + int l2 = gen_new_label(); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_local_new(); + TCGv t2 = tcg_temp_local_new(); + tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F); + tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2); + tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2); + tcg_gen_subfi_tl(t2, 32, t2); + tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2); + tcg_gen_or_tl(t0, t0, t2); + gen_store_spr(SPR_MQ, t0); + tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20); + tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1); + tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]); + tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31); + gen_set_label(l1); + tcg_temp_free(t0); + tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1); + tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA)); + tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2); + tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2); + tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA)); + gen_set_label(l2); + tcg_temp_free(t1); + tcg_temp_free(t2); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* sre - sre. */ GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); - gen_op_POWER_sre(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F); + tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1); + tcg_gen_subfi_tl(t1, 32, t1); + tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1); + tcg_gen_or_tl(t1, t0, t1); + tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0); + gen_store_spr(SPR_MQ, t1); + tcg_temp_free(t0); + tcg_temp_free(t1); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* srea - srea. */ GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); - gen_op_POWER_srea(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F); + tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1); + gen_store_spr(SPR_MQ, t0); + tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1); + tcg_temp_free(t0); + tcg_temp_free(t1); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* sreq */ GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); - gen_op_POWER_sreq(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_temp_new(); + tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F); + tcg_gen_movi_tl(t1, 0xFFFFFFFF); + tcg_gen_shr_tl(t1, t1, t0); + tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0); + gen_load_spr(t2, SPR_MQ); + gen_store_spr(SPR_MQ, t0); + tcg_gen_and_tl(t0, t0, t1); + tcg_gen_andc_tl(t2, t2, t1); + tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2); + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* sriq */ GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode)); - gen_op_POWER_srq(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + int sh = SH(ctx->opcode); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh); + tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh); + tcg_gen_or_tl(t1, t0, t1); + tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0); + gen_store_spr(SPR_MQ, t1); + tcg_temp_free(t0); + tcg_temp_free(t1); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* srliq */ GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); - tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode)); - gen_op_POWER_srlq(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + int sh = SH(ctx->opcode); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh); + gen_load_spr(t1, SPR_MQ); + gen_store_spr(SPR_MQ, t0); + tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU >> sh)); + tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh)); + tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); + tcg_temp_free(t0); + tcg_temp_free(t1); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* srlq */ GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); - gen_op_POWER_srlq(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + int l1 = gen_new_label(); + int l2 = gen_new_label(); + TCGv t0 = tcg_temp_local_new(); + TCGv t1 = tcg_temp_local_new(); + TCGv t2 = tcg_temp_local_new(); + tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F); + tcg_gen_movi_tl(t1, 0xFFFFFFFF); + tcg_gen_shr_tl(t2, t1, t2); + tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20); + tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); + gen_load_spr(t0, SPR_MQ); + tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2); + tcg_gen_br(l2); + gen_set_label(l1); + tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2); + tcg_gen_and_tl(t0, t0, t2); + gen_load_spr(t1, SPR_MQ); + tcg_gen_andc_tl(t1, t1, t2); + tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1); + gen_set_label(l2); + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* srq */ GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); - gen_op_POWER_srq(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + int l1 = gen_new_label(); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F); + tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1); + tcg_gen_subfi_tl(t1, 32, t1); + tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1); + tcg_gen_or_tl(t1, t0, t1); + gen_store_spr(SPR_MQ, t1); + tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20); + tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0); + tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); + tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0); + gen_set_label(l1); + tcg_temp_free(t0); + tcg_temp_free(t1); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* PowerPC 602 specific instructions */