altivec: Fix rules for shift ops with parameters
authorDavid Schleef <ds@schleef.org>
Thu, 28 Apr 2011 07:27:44 +0000 (00:27 -0700)
committerDavid Schleef <ds@schleef.org>
Thu, 28 Apr 2011 07:27:44 +0000 (00:27 -0700)
orc/orccompiler.c
orc/orcpowerpc.c
orc/orcpowerpc.h
orc/orcprogram-altivec.c
orc/orcprogram.h
orc/orcrules-altivec.c

index a3b6cbf..d65fe40 100644 (file)
@@ -528,9 +528,12 @@ orc_compiler_rewrite_insns (OrcCompiler *compiler)
         OrcVariable *var;
 
         if (opcode->src_size[i] == 0) continue;
-        if (i > 0 && (opcode->flags & ORC_STATIC_OPCODE_SCALAR)) continue;
-
         var = compiler->vars + insn.src_args[i];
+
+        if (i > 0 && (opcode->flags & ORC_STATIC_OPCODE_SCALAR) &&
+            (!compiler->load_params || var->vartype != ORC_VAR_TYPE_PARAM))
+          continue;
+
         if (var->vartype == ORC_VAR_TYPE_SRC ||
             var->vartype == ORC_VAR_TYPE_DEST) {
           OrcInstruction *cinsn;
index 982020d..1d9c6c8 100644 (file)
@@ -399,8 +399,6 @@ powerpc_load_constant (OrcCompiler *p, int i, int reg)
 {
   int j;
   int value = p->constants[i].value;
-  int greg = p->gp_tmpreg;
-  int label_skip, label_data;
 
   switch (p->constants[i].type) {
     case ORC_CONST_ZERO:
@@ -467,6 +465,20 @@ powerpc_load_constant (OrcCompiler *p, int i, int reg)
       break;
   }
 
+  powerpc_load_long_constant (p, reg,
+    p->constants[i].full_value[0],
+    p->constants[i].full_value[1],
+    p->constants[i].full_value[2],
+    p->constants[i].full_value[3]);
+}
+
+void
+powerpc_load_long_constant (OrcCompiler *p, int reg, orc_uint32 a,
+    orc_uint32 b, orc_uint32 c, orc_uint32 d)
+{
+  int label_skip, label_data;
+  int greg = p->gp_tmpreg;
+
   label_skip = orc_compiler_label_new (p);
   label_data = orc_compiler_label_new (p);
 
@@ -478,10 +490,14 @@ powerpc_load_constant (OrcCompiler *p, int i, int reg)
   }
 
   powerpc_emit_label (p, label_data);
-  for(j=0;j<4;j++){
-    ORC_ASM_CODE(p,"  .long 0x%08x\n", p->constants[i].full_value[j]);
-    powerpc_emit (p, p->constants[i].full_value[j]);
-  }
+  ORC_ASM_CODE(p,"  .long 0x%08x\n", a);
+  powerpc_emit (p, a);
+  ORC_ASM_CODE(p,"  .long 0x%08x\n", b);
+  powerpc_emit (p, b);
+  ORC_ASM_CODE(p,"  .long 0x%08x\n", c);
+  powerpc_emit (p, c);
+  ORC_ASM_CODE(p,"  .long 0x%08x\n", d);
+  powerpc_emit (p, d);
 
   powerpc_emit_label (p, label_skip);
   powerpc_emit_lwz (p,
index 285f8ca..947a833 100644 (file)
@@ -125,6 +125,8 @@ void powerpc_emit_VX_4 (OrcCompiler *p, const char *name, unsigned int insn,
     int d, int a);
 int powerpc_get_constant (OrcCompiler *p, int type, int value);
 int powerpc_get_constant_full (OrcCompiler *p, int value0, int value1, int value2, int value3);
+void powerpc_load_long_constant (OrcCompiler *p, int reg, orc_uint32 a,
+    orc_uint32 b, orc_uint32 c, orc_uint32 d);
 
 /* instructions */
 #define powerpc_emit_vand(p,a,b,c)         powerpc_emit_VX_2 (p, "vand", 0x10000404, a, b, c)
index 903c6f5..84f46b9 100644 (file)
@@ -113,6 +113,7 @@ orc_compiler_powerpc_init (OrcCompiler *compiler)
   }
 
   compiler->loop_shift = 0;
+  compiler->load_params = TRUE;
 }
 
 void
index 8aebccb..23f275b 100644 (file)
@@ -483,6 +483,7 @@ struct _OrcCompiler {
 
   int insn_shift; /* used when emitting rules */
   int max_var_size; /* size of largest var */
+  int load_params;
 };
 
 #define ORC_SRC_ARG(p,i,n) ((p)->vars[(i)->src_args[(n)]].alloc)
index a405bed..69876e3 100644 (file)
@@ -76,7 +76,11 @@ powerpc_rule_loadpX (OrcCompiler *compiler, void *user, OrcInstruction *insn)
           powerpc_emit_VX(compiler, 0x1000030c,
               powerpc_regnum(dest->alloc), value & 0x1f, 0);
         } else {
-          ORC_COMPILER_ERROR(compiler,"can't load constant");
+          value &= 0xff;
+          value |= value << 8;
+          value |= value << 16;
+          powerpc_load_long_constant (compiler, dest->alloc, value, value,
+              value, value);
         }
         break;
       case 2:
@@ -86,7 +90,10 @@ powerpc_rule_loadpX (OrcCompiler *compiler, void *user, OrcInstruction *insn)
           powerpc_emit_VX(compiler, 0x1000034c,
               powerpc_regnum(dest->alloc), value & 0x1f, 0);
         } else {
-          ORC_COMPILER_ERROR(compiler,"can't load constant");
+          value &= 0xffff;
+          value |= value << 16;
+          powerpc_load_long_constant (compiler, dest->alloc, value, value,
+              value, value);
         }
         break;
       case 4:
@@ -96,7 +103,8 @@ powerpc_rule_loadpX (OrcCompiler *compiler, void *user, OrcInstruction *insn)
           powerpc_emit_VX(compiler, 0x1000038c,
               powerpc_regnum(dest->alloc), value & 0x1f, 0);
         } else {
-          ORC_COMPILER_ERROR(compiler,"can't load constant");
+          powerpc_load_long_constant (compiler, dest->alloc, value, value,
+              value, value);
         }
         break;
     }
@@ -326,11 +334,8 @@ powerpc_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \
     powerpc_emit_VX(p, 0x1000030c, \
         powerpc_regnum(p->tmpreg), (int)p->vars[insn->src_args[1]].value.i, 0); \
     powerpc_emit_VX_2 (p, opcode, code , dest, src1, p->tmpreg);\
-  } else if (p->vars[insn->src_args[1]].vartype == ORC_VAR_TYPE_PARAM) { \
-    ORC_COMPILER_ERROR(p,"rule only works with constants"); \
-    powerpc_emit_VX_2 (p, opcode, code , dest, src1, src2);\
   } else { \
-    ORC_COMPILER_ERROR(p,"rule only works with constants or params"); \
+    powerpc_emit_VX_2 (p, opcode, code , dest, src1, src2);\
   } \
 }