diff options
-rw-r--r-- | target-ppc/cpu.h | 9 | ||||
-rw-r--r-- | target-ppc/op.c | 14 | ||||
-rw-r--r-- | target-ppc/translate.c | 106 |
3 files changed, 104 insertions, 25 deletions
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index e2294134d4..55b98bf5bf 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -23,13 +23,18 @@ #include "config.h" #include <stdint.h> +#if defined(TARGET_PPC64) || (HOST_LONG_BITS >= 64) +/* When using 64 bits temporary registers, + * we can use 64 bits GPR with no extra cost + */ +#define TARGET_PPCSPE +#endif + #if defined (TARGET_PPC64) typedef uint64_t ppc_gpr_t; #define TARGET_LONG_BITS 64 #define TARGET_GPR_BITS 64 #define REGX "%016" PRIx64 -/* We can safely use PowerPC SPE extension when compiling PowerPC 64 */ -#define TARGET_PPCSPE #elif defined(TARGET_PPCSPE) /* GPR are 64 bits: used by vector extension */ typedef uint64_t ppc_gpr_t; diff --git a/target-ppc/op.c b/target-ppc/op.c index 068ccb53b2..1e0584209e 100644 --- a/target-ppc/op.c +++ b/target-ppc/op.c @@ -1444,6 +1444,20 @@ void OPPROTO op_rotli32_T0 (void) RETURN(); } +#if defined(TARGET_PPC64) +void OPPROTO op_rotl64_T0_T1 (void) +{ + T0 = rotl64(T0, T1 & 0x3F); + RETURN(); +} + +void OPPROTO op_rotli64_T0 (void) +{ + T0 = rotl64(T0, PARAM1); + RETURN(); +} +#endif + /*** Integer shift ***/ /* shift left word */ void OPPROTO op_slw (void) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index fb9b07591a..cd5cdf6fa5 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -1109,12 +1109,10 @@ GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) { target_ulong mask; uint32_t mb, me, sh; - int n; mb = MB(ctx->opcode); me = ME(ctx->opcode); sh = SH(ctx->opcode); - n = me + 1 - mb; if (likely(sh == 0)) { if (likely(mb == 0 && me == 31)) { gen_op_load_gpr_T0(rS(ctx->opcode)); @@ -1231,68 +1229,130 @@ GEN_HANDLER(name##3, opc1, opc2 | 0x11, 0xFF, 0x00000000, PPC_64B) \ { \ gen_##name(ctx, 1, 1); \ } + +static inline void gen_rldinm (DisasContext *ctx, uint32_t mb, uint32_t me, + uint32_t sh) +{ + gen_op_load_gpr_T0(rS(ctx->opcode)); + if (likely(sh == 0)) { + goto do_mask; + } + if (likely(mb == 0)) { + if (likely(me == 63)) { + gen_op_rotli32_T0(sh); + goto do_store; + } else if (likely(me == (63 - sh))) { + gen_op_sli_T0(sh); + goto do_store; + } + } else if (likely(me == 63)) { + if (likely(sh == (64 - mb))) { + gen_op_srli_T0(mb); + goto do_store; + } + } + gen_op_rotli64_T0(sh); + do_mask: + gen_op_andi_T0(MASK(mb, me)); + do_store: + gen_op_store_T0_gpr(rA(ctx->opcode)); + if (unlikely(Rc(ctx->opcode) != 0)) + gen_set_Rc0(ctx); +} /* rldicl - rldicl. */ static inline void gen_rldicl (DisasContext *ctx, int mbn, int shn) { - int sh, mb; + uint32_t sh, mb; sh = SH(ctx->opcode) | (1 << shn); mb = (MB(ctx->opcode) << 1) | mbn; - /* XXX: TODO */ - RET_INVAL(ctx); + gen_rldinm(ctx, mb, 63, sh); } -GEN_PPC64_R4(rldicl, 0x1E, 0x00) +GEN_PPC64_R4(rldicl, 0x1E, 0x00); /* rldicr - rldicr. */ static inline void gen_rldicr (DisasContext *ctx, int men, int shn) { - int sh, me; + uint32_t sh, me; sh = SH(ctx->opcode) | (1 << shn); me = (MB(ctx->opcode) << 1) | men; - /* XXX: TODO */ - RET_INVAL(ctx); + gen_rldinm(ctx, 0, me, sh); } -GEN_PPC64_R4(rldicr, 0x1E, 0x02) +GEN_PPC64_R4(rldicr, 0x1E, 0x02); /* rldic - rldic. */ static inline void gen_rldic (DisasContext *ctx, int mbn, int shn) { - int sh, mb; + uint32_t sh, mb; sh = SH(ctx->opcode) | (1 << shn); mb = (MB(ctx->opcode) << 1) | mbn; - /* XXX: TODO */ - RET_INVAL(ctx); + gen_rldinm(ctx, mb, 63 - sh, sh); } -GEN_PPC64_R4(rldic, 0x1E, 0x04) +GEN_PPC64_R4(rldic, 0x1E, 0x04); + +static inline void gen_rldnm (DisasContext *ctx, uint32_t mb, uint32_t me) +{ + gen_op_load_gpr_T0(rS(ctx->opcode)); + gen_op_load_gpr_T1(rB(ctx->opcode)); + gen_op_rotl64_T0_T1(); + if (unlikely(mb != 0 || me != 63)) { + gen_op_andi_T0(MASK(mb, me)); + } + gen_op_store_T0_gpr(rA(ctx->opcode)); + if (unlikely(Rc(ctx->opcode) != 0)) + gen_set_Rc0(ctx); +} + /* rldcl - rldcl. */ static inline void gen_rldcl (DisasContext *ctx, int mbn) { - int mb; + uint32_t mb; mb = (MB(ctx->opcode) << 1) | mbn; - /* XXX: TODO */ - RET_INVAL(ctx); + gen_rldnm(ctx, mb, 63); } GEN_PPC64_R2(rldcl, 0x1E, 0x08) /* rldcr - rldcr. */ static inline void gen_rldcr (DisasContext *ctx, int men) { - int me; + uint32_t me; me = (MB(ctx->opcode) << 1) | men; - /* XXX: TODO */ - RET_INVAL(ctx); + gen_rldnm(ctx, 0, me); } GEN_PPC64_R2(rldcr, 0x1E, 0x09) /* rldimi - rldimi. */ static inline void gen_rldimi (DisasContext *ctx, int mbn, int shn) { - int sh, mb; + uint64_t mask; + uint32_t sh, mb; sh = SH(ctx->opcode) | (1 << shn); mb = (MB(ctx->opcode) << 1) | mbn; - /* XXX: TODO */ - RET_INVAL(ctx); + if (likely(sh == 0)) { + if (likely(mb == 0)) { + gen_op_load_gpr_T0(rS(ctx->opcode)); + goto do_store; + } else if (likely(mb == 63)) { + gen_op_load_gpr_T0(rA(ctx->opcode)); + goto do_store; + } + gen_op_load_gpr_T0(rS(ctx->opcode)); + gen_op_load_gpr_T1(rA(ctx->opcode)); + goto do_mask; + } + gen_op_load_gpr_T0(rS(ctx->opcode)); + gen_op_load_gpr_T1(rA(ctx->opcode)); + gen_op_rotli64_T0(SH(ctx->opcode)); + do_mask: + mask = MASK(mb, 63 - sh); + gen_op_andi_T0(mask); + gen_op_andi_T1(~mask); + gen_op_or(); + do_store: + gen_op_store_T0_gpr(rA(ctx->opcode)); + if (unlikely(Rc(ctx->opcode) != 0)) + gen_set_Rc0(ctx); } GEN_PPC64_R4(rldimi, 0x1E, 0x06) #endif |