commit 51789c410beb34423b1188a6b6e069fe8b68aebe
Author: j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Date:   Thu Mar 22 22:41:50 2007 +0000

    PowerPC improvments:
    - add missing 64 bits rotate instructions
    - safely define TARGET_PPCSPE when 64 bits registers are used
      a separate target will be needed to use it in 32 bits mode on 32 bits hosts.
    
    
    git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2527 c046a42c-6fe2-441c-8c8c-71466251a162

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index fb9b075..cd5cdf6 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
