PowerPC improvments:
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Thu, 22 Mar 2007 22:41:50 +0000 (22:41 +0000)
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Thu, 22 Mar 2007 22:41:50 +0000 (22:41 +0000)
- 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

target-ppc/cpu.h
target-ppc/op.c
target-ppc/translate.c

index e229413..55b98bf 100644 (file)
 #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;
index 068ccb5..1e05842 100644 (file)
@@ -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)
index fb9b075..cd5cdf6 100644 (file)
@@ -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