diff --git a/target-ppc/helper.h b/target-ppc/helper.h index c366b74f8c..050fec52b0 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -7,3 +7,13 @@ DEF_HELPER(uint32_t, helper_fcmpu, (void)) DEF_HELPER(uint32_t, helper_load_cr, (void)) DEF_HELPER(void, helper_store_cr, (target_ulong, uint32_t)) + +DEF_HELPER(target_ulong, helper_cntlzw, (target_ulong t)) +DEF_HELPER(target_ulong, helper_popcntb, (target_ulong val)) +DEF_HELPER(target_ulong, helper_sraw, (target_ulong, target_ulong)) +#if defined(TARGET_PPC64) +DEF_HELPER(target_ulong, helper_cntlzd, (target_ulong t)) +DEF_HELPER(target_ulong, helper_popcntb_64, (target_ulong val)) +DEF_HELPER(target_ulong, helper_srad, (target_ulong, target_ulong)) +#endif + diff --git a/target-ppc/op.c b/target-ppc/op.c index d9676ba81e..9a1ec8209d 100644 --- a/target-ppc/op.c +++ b/target-ppc/op.c @@ -37,15 +37,6 @@ void OPPROTO op_debug (void) do_raise_exception(EXCP_DEBUG); } -/* Load/store special registers */ -#if defined(TARGET_PPC64) -void OPPROTO op_store_pri (void) -{ - do_store_pri(PARAM1); - RETURN(); -} -#endif - #if !defined(CONFIG_USER_ONLY) /* Segment registers load and store */ void OPPROTO op_load_sr (void) @@ -921,101 +912,7 @@ void OPPROTO op_subfzeo_64 (void) } #endif -void OPPROTO op_popcntb (void) -{ - do_popcntb(); - RETURN(); -} - -#if defined(TARGET_PPC64) -void OPPROTO op_popcntb_64 (void) -{ - do_popcntb_64(); - RETURN(); -} -#endif - /*** Integer logical ***/ -/* and */ -void OPPROTO op_and (void) -{ - T0 &= T1; - RETURN(); -} - -/* andc */ -void OPPROTO op_andc (void) -{ - T0 &= ~T1; - RETURN(); -} - -/* count leading zero */ -void OPPROTO op_cntlzw (void) -{ - do_cntlzw(); - RETURN(); -} - -#if defined(TARGET_PPC64) -void OPPROTO op_cntlzd (void) -{ - do_cntlzd(); - RETURN(); -} -#endif - -/* eqv */ -void OPPROTO op_eqv (void) -{ - T0 = ~(T0 ^ T1); - RETURN(); -} - -/* extend sign byte */ -void OPPROTO op_extsb (void) -{ -#if defined (TARGET_PPC64) - T0 = (int64_t)((int8_t)T0); -#else - T0 = (int32_t)((int8_t)T0); -#endif - RETURN(); -} - -/* extend sign half word */ -void OPPROTO op_extsh (void) -{ -#if defined (TARGET_PPC64) - T0 = (int64_t)((int16_t)T0); -#else - T0 = (int32_t)((int16_t)T0); -#endif - RETURN(); -} - -#if defined (TARGET_PPC64) -void OPPROTO op_extsw (void) -{ - T0 = (int64_t)((int32_t)T0); - RETURN(); -} -#endif - -/* nand */ -void OPPROTO op_nand (void) -{ - T0 = ~(T0 & T1); - RETURN(); -} - -/* nor */ -void OPPROTO op_nor (void) -{ - T0 = ~(T0 | T1); - RETURN(); -} - /* or */ void OPPROTO op_or (void) { @@ -1023,34 +920,6 @@ void OPPROTO op_or (void) RETURN(); } -/* orc */ -void OPPROTO op_orc (void) -{ - T0 |= ~T1; - RETURN(); -} - -/* ori */ -void OPPROTO op_ori (void) -{ - T0 |= (uint32_t)PARAM1; - RETURN(); -} - -/* xor */ -void OPPROTO op_xor (void) -{ - T0 ^= T1; - RETURN(); -} - -/* xori */ -void OPPROTO op_xori (void) -{ - T0 ^= (uint32_t)PARAM1; - RETURN(); -} - /*** Integer rotate ***/ void OPPROTO op_rotl32_T0_T1 (void) { @@ -1079,122 +948,13 @@ void OPPROTO op_rotli64_T0 (void) #endif /*** Integer shift ***/ -/* shift left word */ -void OPPROTO op_slw (void) -{ - if (T1 & 0x20) { - T0 = 0; - } else { - T0 = (uint32_t)(T0 << T1); - } - RETURN(); -} - -#if defined(TARGET_PPC64) -void OPPROTO op_sld (void) -{ - if (T1 & 0x40) { - T0 = 0; - } else { - T0 = T0 << T1; - } - RETURN(); -} -#endif - -/* shift right algebraic word */ -void OPPROTO op_sraw (void) -{ - do_sraw(); - RETURN(); -} - -#if defined(TARGET_PPC64) -void OPPROTO op_srad (void) -{ - do_srad(); - RETURN(); -} -#endif - -/* shift right algebraic word immediate */ -void OPPROTO op_srawi (void) -{ - uint32_t mask = (uint32_t)PARAM2; - - T0 = (int32_t)T0 >> PARAM1; - if ((int32_t)T1 < 0 && (T1 & mask) != 0) { - env->xer |= (1 << XER_CA); - } else { - env->xer &= ~(1 << XER_CA); - } - RETURN(); -} - -#if defined(TARGET_PPC64) -void OPPROTO op_sradi (void) -{ - uint64_t mask = ((uint64_t)PARAM2 << 32) | (uint64_t)PARAM3; - - T0 = (int64_t)T0 >> PARAM1; - if ((int64_t)T1 < 0 && ((uint64_t)T1 & mask) != 0) { - env->xer |= (1 << XER_CA); - } else { - env->xer &= ~(1 << XER_CA); - } - RETURN(); -} -#endif - /* shift right word */ -void OPPROTO op_srw (void) -{ - if (T1 & 0x20) { - T0 = 0; - } else { - T0 = (uint32_t)T0 >> T1; - } - RETURN(); -} - -#if defined(TARGET_PPC64) -void OPPROTO op_srd (void) -{ - if (T1 & 0x40) { - T0 = 0; - } else { - T0 = (uint64_t)T0 >> T1; - } - RETURN(); -} -#endif - -void OPPROTO op_sl_T0_T1 (void) -{ - T0 = T0 << T1; - RETURN(); -} - void OPPROTO op_sli_T0 (void) { T0 = T0 << PARAM1; RETURN(); } -void OPPROTO op_srl_T0_T1 (void) -{ - T0 = (uint32_t)T0 >> T1; - RETURN(); -} - -#if defined(TARGET_PPC64) -void OPPROTO op_srl_T0_T1_64 (void) -{ - T0 = (uint32_t)T0 >> T1; - RETURN(); -} -#endif - void OPPROTO op_srli_T0 (void) { T0 = (uint32_t)T0 >> PARAM1; @@ -1215,14 +975,6 @@ void OPPROTO op_srli_T1 (void) RETURN(); } -#if defined(TARGET_PPC64) -void OPPROTO op_srli_T1_64 (void) -{ - T1 = (uint64_t)T1 >> PARAM1; - RETURN(); -} -#endif - /*** Floating-Point arithmetic ***/ /* fadd - fadd. */ void OPPROTO op_fadd (void) diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index e0b6f4efdb..32b347100d 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -368,96 +368,98 @@ void do_subfzeo_64 (void) } #endif -void do_cntlzw (void) +target_ulong helper_cntlzw (target_ulong t) { - T0 = clz32(T0); + return clz32(t); } #if defined(TARGET_PPC64) -void do_cntlzd (void) +target_ulong helper_cntlzd (target_ulong t) { - T0 = clz64(T0); + return clz64(t); } #endif /* shift right arithmetic helper */ -void do_sraw (void) +target_ulong helper_sraw (target_ulong value, target_ulong shift) { int32_t ret; - if (likely(!(T1 & 0x20UL))) { - if (likely((uint32_t)T1 != 0)) { - ret = (int32_t)T0 >> (T1 & 0x1fUL); - if (likely(ret >= 0 || ((int32_t)T0 & ((1 << T1) - 1)) == 0)) { + if (likely(!(shift & 0x20))) { + if (likely((uint32_t)shift != 0)) { + shift &= 0x1f; + ret = (int32_t)value >> shift; + if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) { env->xer &= ~(1 << XER_CA); } else { env->xer |= (1 << XER_CA); } } else { - ret = T0; + ret = (int32_t)value; env->xer &= ~(1 << XER_CA); } } else { - ret = UINT32_MAX * ((uint32_t)T0 >> 31); - if (likely(ret >= 0 || ((uint32_t)T0 & ~0x80000000UL) == 0)) { - env->xer &= ~(1 << XER_CA); - } else { + ret = (int32_t)value >> 31; + if (ret) { env->xer |= (1 << XER_CA); + } else { + env->xer &= ~(1 << XER_CA); } } - T0 = ret; + return (target_long)ret; } #if defined(TARGET_PPC64) -void do_srad (void) +target_ulong helper_srad (target_ulong value, target_ulong shift) { int64_t ret; - if (likely(!(T1 & 0x40UL))) { - if (likely((uint64_t)T1 != 0)) { - ret = (int64_t)T0 >> (T1 & 0x3FUL); - if (likely(ret >= 0 || ((int64_t)T0 & ((1 << T1) - 1)) == 0)) { + if (likely(!(shift & 0x40))) { + if (likely((uint64_t)shift != 0)) { + shift &= 0x3f; + ret = (int64_t)value >> shift; + if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) { env->xer &= ~(1 << XER_CA); } else { env->xer |= (1 << XER_CA); } } else { - ret = T0; + ret = (int64_t)value; env->xer &= ~(1 << XER_CA); } } else { - ret = UINT64_MAX * ((uint64_t)T0 >> 63); - if (likely(ret >= 0 || ((uint64_t)T0 & ~0x8000000000000000ULL) == 0)) { - env->xer &= ~(1 << XER_CA); - } else { + ret = (int64_t)value >> 63; + if (ret) { env->xer |= (1 << XER_CA); + } else { + env->xer &= ~(1 << XER_CA); } } - T0 = ret; + return ret; } #endif -void do_popcntb (void) +target_ulong helper_popcntb (target_ulong val) { uint32_t ret; int i; ret = 0; for (i = 0; i < 32; i += 8) - ret |= ctpop8((T0 >> i) & 0xFF) << i; - T0 = ret; + ret |= ctpop8((val >> i) & 0xFF) << i; + return ret; } #if defined(TARGET_PPC64) -void do_popcntb_64 (void) +target_ulong helper_popcntb_64 (target_ulong val) { uint64_t ret; int i; ret = 0; for (i = 0; i < 64; i += 8) - ret |= ctpop8((T0 >> i) & 0xFF) << i; - T0 = ret; + ret |= ctpop8((val >> i) & 0xFF) << i; + return ret; } #endif diff --git a/target-ppc/translate.c b/target-ppc/translate.c index e2cb190fac..e40cae917a 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -1277,63 +1277,56 @@ GEN_INT_ARITH2 (divdu, 0x1F, 0x09, 0x0E, PPC_64B); #endif /*** Integer logical ***/ -#define __GEN_LOGICAL2(name, opc2, opc3, type) \ -GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, type) \ +#define GEN_LOGICAL2(name, tcg_op, opc, type) \ +GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type) \ { \ - 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_##name(); \ - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \ + tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], \ + cpu_gpr[rB(ctx->opcode)]); \ if (unlikely(Rc(ctx->opcode) != 0)) \ - gen_set_Rc0(ctx, cpu_T[0]); \ + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \ } -#define GEN_LOGICAL2(name, opc, type) \ -__GEN_LOGICAL2(name, 0x1C, opc, type) -#define GEN_LOGICAL1(name, opc, type) \ +#define GEN_LOGICAL1(name, tcg_op, opc, type) \ GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type) \ { \ - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); \ - gen_op_##name(); \ - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \ + tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); \ if (unlikely(Rc(ctx->opcode) != 0)) \ - gen_set_Rc0(ctx, cpu_T[0]); \ + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \ } /* and & and. */ -GEN_LOGICAL2(and, 0x00, PPC_INTEGER); +GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER); /* andc & andc. */ -GEN_LOGICAL2(andc, 0x01, PPC_INTEGER); +GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER); /* andi. */ GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_andi_tl(cpu_T[0], cpu_T[0], UIMM(ctx->opcode)); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); - gen_set_Rc0(ctx, cpu_T[0]); + tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode)); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* andis. */ GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_andi_tl(cpu_T[0], cpu_T[0], UIMM(ctx->opcode) << 16); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); - gen_set_Rc0(ctx, cpu_T[0]); + tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode) << 16); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } - /* cntlzw */ -GEN_LOGICAL1(cntlzw, 0x00, PPC_INTEGER); +GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER) +{ + tcg_gen_helper_1_1(helper_cntlzw, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); + if (unlikely(Rc(ctx->opcode) != 0)) + gen_set_Rc0(ctx, cpu_gpr[rS(ctx->opcode)]); +} /* eqv & eqv. */ -GEN_LOGICAL2(eqv, 0x08, PPC_INTEGER); +GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER); /* extsb & extsb. */ -GEN_LOGICAL1(extsb, 0x1D, PPC_INTEGER); +GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER); /* extsh & extsh. */ -GEN_LOGICAL1(extsh, 0x1C, PPC_INTEGER); +GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER); /* nand & nand. */ -GEN_LOGICAL2(nand, 0x0E, PPC_INTEGER); +GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER); /* nor & nor. */ -GEN_LOGICAL2(nor, 0x03, PPC_INTEGER); - +GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER); /* or & or. */ GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER) { @@ -1344,55 +1337,54 @@ GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER) rb = rB(ctx->opcode); /* Optimisation for mr. ri case */ if (rs != ra || rs != rb) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rs]); - if (rs != rb) { - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rb]); - gen_op_or(); - } - tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]); + if (rs != rb) + tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]); + else + tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[ra]); } else if (unlikely(Rc(ctx->opcode) != 0)) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rs]); - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rs]); #if defined(TARGET_PPC64) } else { + int prio = 0; + switch (rs) { case 1: /* Set process priority to low */ - gen_op_store_pri(2); + prio = 2; break; case 6: /* Set process priority to medium-low */ - gen_op_store_pri(3); + prio = 3; break; case 2: /* Set process priority to normal */ - gen_op_store_pri(4); + prio = 4; break; #if !defined(CONFIG_USER_ONLY) case 31: if (ctx->supervisor > 0) { /* Set process priority to very low */ - gen_op_store_pri(1); + prio = 1; } break; case 5: if (ctx->supervisor > 0) { /* Set process priority to medium-hight */ - gen_op_store_pri(5); + prio = 5; } break; case 3: if (ctx->supervisor > 0) { /* Set process priority to high */ - gen_op_store_pri(6); + prio = 6; } break; case 7: if (ctx->supervisor > 1) { /* Set process priority to very high */ - gen_op_store_pri(7); + prio = 7; } break; #endif @@ -1400,26 +1392,29 @@ GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER) /* nop */ break; } + if (prio) { + TCGv temp = tcg_temp_new(TCG_TYPE_TL); + tcg_gen_ld_tl(temp, cpu_env, offsetof(CPUState, spr[SPR_PPR])); + tcg_gen_andi_tl(temp, temp, ~0x001C000000000000ULL); + tcg_gen_ori_tl(temp, temp, ((uint64_t)prio) << 50); + tcg_gen_st_tl(temp, cpu_env, offsetof(CPUState, spr[SPR_PPR])); + tcg_temp_free(temp); + } #endif } } - /* orc & orc. */ -GEN_LOGICAL2(orc, 0x0C, PPC_INTEGER); +GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER); /* xor & xor. */ GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); /* Optimisation for "set to zero" case */ - if (rS(ctx->opcode) != rB(ctx->opcode)) { - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); - gen_op_xor(); - } else { - tcg_gen_movi_tl(cpu_T[0], 0); - } - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + if (rS(ctx->opcode) != rB(ctx->opcode)) + tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); + else + tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* ori */ GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) @@ -1431,10 +1426,7 @@ GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) /* XXX: should handle special NOPs for POWER series */ return; } - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - if (likely(uimm != 0)) - gen_op_ori(uimm); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm); } /* oris */ GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) @@ -1445,10 +1437,7 @@ GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) /* NOP */ return; } - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - if (likely(uimm != 0)) - gen_op_ori(uimm << 16); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16); } /* xori */ GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) @@ -1459,12 +1448,8 @@ GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) /* NOP */ return; } - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - if (likely(uimm != 0)) - gen_op_xori(uimm); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm); } - /* xoris */ GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) { @@ -1474,30 +1459,29 @@ GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) /* NOP */ return; } - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - if (likely(uimm != 0)) - gen_op_xori(uimm << 16); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16); } - /* popcntb : PowerPC 2.03 specification */ GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB) { - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); #if defined(TARGET_PPC64) if (ctx->sf_mode) - gen_op_popcntb_64(); + tcg_gen_helper_1_1(helper_popcntb_64, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); else #endif - gen_op_popcntb(); - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); + tcg_gen_helper_1_1(helper_popcntb, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); } #if defined(TARGET_PPC64) /* extsw & extsw. */ -GEN_LOGICAL1(extsw, 0x1E, PPC_64B); +GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B); /* cntlzd */ -GEN_LOGICAL1(cntlzd, 0x01, PPC_64B); +GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B) +{ + tcg_gen_helper_1_1(helper_cntlzd, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); + if (unlikely(Rc(ctx->opcode) != 0)) + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); +} #endif /*** Integer rotate ***/ @@ -1759,54 +1743,141 @@ GEN_PPC64_R4(rldimi, 0x1E, 0x06); /*** Integer shift ***/ /* slw & slw. */ -__GEN_LOGICAL2(slw, 0x18, 0x00, PPC_INTEGER); +GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER) +{ + TCGv temp; + int l1, l2; + l1 = gen_new_label(); + l2 = gen_new_label(); + + temp = tcg_temp_local_new(TCG_TYPE_TL); + tcg_gen_andi_tl(temp, cpu_gpr[rB(ctx->opcode)], 0x20); + tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1); + tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0); + tcg_gen_br(l2); + gen_set_label(l1); + tcg_gen_andi_tl(temp, cpu_gpr[rB(ctx->opcode)], 0x3f); + tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], temp); + tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); + gen_set_label(l2); + tcg_temp_free(temp); + if (unlikely(Rc(ctx->opcode) != 0)) + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); +} /* sraw & sraw. */ -__GEN_LOGICAL2(sraw, 0x18, 0x18, PPC_INTEGER); +GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER) +{ + tcg_gen_helper_1_2(helper_sraw, cpu_gpr[rA(ctx->opcode)], + cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); + if (unlikely(Rc(ctx->opcode) != 0)) + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); +} /* srawi & srawi. */ GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER) { - int mb, me; - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - if (SH(ctx->opcode) != 0) { - tcg_gen_mov_tl(cpu_T[1], cpu_T[0]); - mb = 32 - SH(ctx->opcode); - me = 31; -#if defined(TARGET_PPC64) - mb += 32; - me += 32; -#endif - gen_op_srawi(SH(ctx->opcode), MASK(mb, me)); + int sh = SH(ctx->opcode); + if (sh != 0) { + int l1, l2; + TCGv temp; + l1 = gen_new_label(); + l2 = gen_new_label(); + temp = tcg_temp_local_new(TCG_TYPE_TL); + tcg_gen_ext32s_tl(temp, cpu_gpr[rS(ctx->opcode)]); + tcg_gen_brcondi_tl(TCG_COND_GE, temp, 0, l1); + tcg_gen_andi_tl(temp, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1); + tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1); + tcg_gen_ori_i32(cpu_xer, cpu_xer, 1 << XER_CA); + tcg_gen_br(l2); + gen_set_label(l1); + tcg_gen_andi_i32(cpu_xer, cpu_xer, ~(1 << XER_CA)); + gen_set_label(l2); + tcg_gen_ext32s_tl(temp, cpu_gpr[rS(ctx->opcode)]); + tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], temp, sh); + tcg_temp_free(temp); + } else { + tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); + tcg_gen_andi_i32(cpu_xer, cpu_xer, ~(1 << XER_CA)); } - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } /* srw & srw. */ -__GEN_LOGICAL2(srw, 0x18, 0x10, PPC_INTEGER); +GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER) +{ + TCGv temp; + int l1, l2; + l1 = gen_new_label(); + l2 = gen_new_label(); + temp = tcg_temp_local_new(TCG_TYPE_TL); + tcg_gen_andi_tl(temp, cpu_gpr[rB(ctx->opcode)], 0x20); + tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1); + tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0); + tcg_gen_br(l2); + gen_set_label(l1); + tcg_gen_andi_tl(temp, cpu_gpr[rB(ctx->opcode)], 0x3f); + tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], temp); + tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); + gen_set_label(l2); + tcg_temp_free(temp); + if (unlikely(Rc(ctx->opcode) != 0)) + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); +} #if defined(TARGET_PPC64) /* sld & sld. */ -__GEN_LOGICAL2(sld, 0x1B, 0x00, PPC_64B); +GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B) +{ + TCGv temp; + int l1, l2; + l1 = gen_new_label(); + l2 = gen_new_label(); + + temp = tcg_temp_local_new(TCG_TYPE_TL); + tcg_gen_andi_tl(temp, cpu_gpr[rB(ctx->opcode)], 0x40); + tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1); + tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0); + tcg_gen_br(l2); + gen_set_label(l1); + tcg_gen_andi_tl(temp, cpu_gpr[rB(ctx->opcode)], 0x7f); + tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], temp); + gen_set_label(l2); + tcg_temp_free(temp); + if (unlikely(Rc(ctx->opcode) != 0)) + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); +} /* srad & srad. */ -__GEN_LOGICAL2(srad, 0x1A, 0x18, PPC_64B); +GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B) +{ + tcg_gen_helper_1_2(helper_srad, cpu_gpr[rA(ctx->opcode)], + cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); + if (unlikely(Rc(ctx->opcode) != 0)) + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); +} /* sradi & sradi. */ static always_inline void gen_sradi (DisasContext *ctx, int n) { - uint64_t mask; - int sh, mb, me; - - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - sh = SH(ctx->opcode) + (n << 5); + int sh = SH(ctx->opcode) + (n << 5); if (sh != 0) { - tcg_gen_mov_tl(cpu_T[1], cpu_T[0]); - mb = 64 - SH(ctx->opcode); - me = 63; - mask = MASK(mb, me); - gen_op_sradi(sh, mask >> 32, mask); + int l1, l2; + TCGv temp; + l1 = gen_new_label(); + l2 = gen_new_label(); + tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1); + temp = tcg_temp_new(TCG_TYPE_TL); + tcg_gen_andi_tl(temp, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1); + tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1); + tcg_gen_ori_i32(cpu_xer, cpu_xer, 1 << XER_CA); + tcg_gen_br(l2); + gen_set_label(l1); + tcg_gen_andi_i32(cpu_xer, cpu_xer, ~(1 << XER_CA)); + gen_set_label(l2); + tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh); + } else { + tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); + tcg_gen_andi_i32(cpu_xer, cpu_xer, ~(1 << XER_CA)); } - tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); if (unlikely(Rc(ctx->opcode) != 0)) - gen_set_Rc0(ctx, cpu_T[0]); + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); } GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B) { @@ -1817,7 +1888,26 @@ GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B) gen_sradi(ctx, 1); } /* srd & srd. */ -__GEN_LOGICAL2(srd, 0x1B, 0x10, PPC_64B); +GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B) +{ + TCGv temp; + int l1, l2; + l1 = gen_new_label(); + l2 = gen_new_label(); + + temp = tcg_temp_local_new(TCG_TYPE_TL); + tcg_gen_andi_tl(temp, cpu_gpr[rB(ctx->opcode)], 0x40); + tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1); + tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0); + tcg_gen_br(l2); + gen_set_label(l1); + tcg_gen_andi_tl(temp, cpu_gpr[rB(ctx->opcode)], 0x7f); + tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], temp); + gen_set_label(l2); + tcg_temp_free(temp); + if (unlikely(Rc(ctx->opcode) != 0)) + gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); +} #endif /*** Floating-Point arithmetic ***/