When targeting PPU use rlwinm instead of andi. if possible
authormalc <av1474@comtv.ru>
Sun, 6 Sep 2009 02:31:09 +0000 (06:31 +0400)
committermalc <av1474@comtv.ru>
Sun, 6 Sep 2009 03:24:37 +0000 (07:24 +0400)
andi. is microcoded and slow there.

Signed-off-by: malc <av1474@comtv.ru>
tcg/ppc/tcg-target.c

index 2409288..0739515 100644 (file)
@@ -1253,14 +1253,60 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
 
     case INDEX_op_and_i32:
         if (const_args[2]) {
-            if ((args[2] & 0xffff) == args[2])
-                tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | args[2]);
-            else if ((args[2] & 0xffff0000) == args[2])
-                tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0])
-                           | ((args[2] >> 16) & 0xffff));
-            else {
-                tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
-                tcg_out32 (s, AND | SAB (args[1], args[0], 0));
+            uint32_t c;
+
+            c = args[2];
+
+            if (!c) {
+                tcg_out_movi (s, TCG_TYPE_I32, args[0], 0);
+                break;
+            }
+#ifdef __PPU__
+            uint32_t t, n;
+            int mb, me;
+
+            n = c ^ -(c & 1);
+            t = n + (n & -n);
+
+            if ((t & (t - 1)) == 0) {
+                int lzc, tzc;
+
+                if ((c & 0x80000001) == 0x80000001) {
+                    lzc = clz32 (n);
+                    tzc = ctz32 (n);
+
+                    mb = 32 - tzc;
+                    me = lzc - 1;
+                }
+                else {
+                    lzc = clz32 (c);
+                    tzc = ctz32 (c);
+
+                    mb = lzc;
+                    me = 31 - tzc;
+                }
+
+                tcg_out32 (s, (RLWINM
+                               | RA (args[0])
+                               | RS (args[1])
+                               | SH (0)
+                               | MB (mb)
+                               | ME (me)
+                               )
+                    );
+            }
+            else
+#endif /* !__PPU__ */
+            {
+                if ((c & 0xffff) == c)
+                    tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | c);
+                else if ((c & 0xffff0000) == c)
+                    tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0])
+                               | ((c >> 16) & 0xffff));
+                else {
+                    tcg_out_movi (s, TCG_TYPE_I32, 0, c);
+                    tcg_out32 (s, AND | SAB (args[1], args[0], 0));
+                }
             }
         }
         else