altivec: implement load/store opcodes
authorDavid Schleef <ds@schleef.org>
Tue, 3 Aug 2010 02:30:52 +0000 (19:30 -0700)
committerDavid Schleef <ds@schleef.org>
Tue, 3 Aug 2010 02:30:52 +0000 (19:30 -0700)
orc/orcprogram-altivec.c
orc/orcrules-altivec.c

index cbbf850..b2c2cc2 100644 (file)
@@ -94,6 +94,7 @@ orc_compiler_powerpc_init (OrcCompiler *compiler)
   compiler->valid_regs[POWERPC_R13] = 0; /* reserved */
 
   compiler->tmpreg = POWERPC_V0;
+  compiler->gp_tmpreg = POWERPC_R0;
   compiler->valid_regs[compiler->tmpreg] = 0;
 
   for(i=14;i<32;i++){
@@ -106,6 +107,7 @@ orc_compiler_powerpc_init (OrcCompiler *compiler)
   compiler->loop_shift = 0;
 }
 
+#if 0
 static void
 powerpc_load_constant (OrcCompiler *p, int i, int reg)
 {
@@ -436,6 +438,36 @@ powerpc_emit_store_dest (OrcCompiler *compiler, OrcVariable *var)
       ORC_ASM_CODE(compiler,"ERROR\n");
   }
 }
+#endif
+
+void
+powerpc_load_inner_constants (OrcCompiler *compiler)
+{
+  OrcVariable *var;
+  int i;
+
+  for(i=0;i<ORC_N_VARIABLES;i++){
+    var = compiler->vars + i;
+
+    if (compiler->vars[i].name == NULL) continue;
+    switch (compiler->vars[i].vartype) {
+      case ORC_VAR_TYPE_SRC:
+      case ORC_VAR_TYPE_DEST:
+        if (compiler->vars[i].ptr_register) {
+          powerpc_emit_lwz (compiler,
+              compiler->vars[i].ptr_register,
+              POWERPC_R3,
+              (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[i]));
+        } else {
+          /* FIXME */
+          ORC_ASM_CODE(compiler,"ERROR");
+        }
+        break;
+      default:
+        break;
+    }
+  }
+}
 
 void
 orc_compiler_powerpc_assemble (OrcCompiler *compiler)
@@ -466,7 +498,8 @@ orc_compiler_powerpc_assemble (OrcCompiler *compiler)
         (int)ORC_STRUCT_OFFSET(OrcExecutorAlt, m_index));
   }
 
-  powerpc_load_constants (compiler);
+  //powerpc_load_constants (compiler);
+  powerpc_load_inner_constants (compiler);
 
   for(k=0;k<4;k++){
     OrcVariable *var = &compiler->vars[ORC_VAR_A1 + k];
@@ -517,7 +550,7 @@ orc_compiler_powerpc_assemble (OrcCompiler *compiler)
       switch (var->vartype) {
         case ORC_VAR_TYPE_SRC:
         case ORC_VAR_TYPE_DEST:
-          powerpc_emit_load_src (compiler, var);
+          //powerpc_emit_load_src (compiler, var);
           break;
         case ORC_VAR_TYPE_CONST:
           break;
@@ -542,7 +575,7 @@ orc_compiler_powerpc_assemble (OrcCompiler *compiler)
 
       switch (var->vartype) {
         case ORC_VAR_TYPE_DEST:
-          powerpc_emit_store_dest (compiler, var);
+          //powerpc_emit_store_dest (compiler, var);
           break;
         case ORC_VAR_TYPE_TEMP:
           break;
index 83ca6b3..4f76c12 100644 (file)
 
 /* rules */
 
+static void
+powerpc_rule_loadpX (OrcCompiler *compiler, void *user, OrcInstruction *insn)
+{
+  OrcVariable *src = compiler->vars + insn->src_args[0];
+  OrcVariable *dest = compiler->vars + insn->dest_args[0];
+
+  if (src->vartype == ORC_VAR_TYPE_PARAM) {
+    int greg = compiler->gp_tmpreg;
+
+    powerpc_emit_addi (compiler,
+        greg, POWERPC_R3,
+        (int)ORC_STRUCT_OFFSET(OrcExecutor, params[insn->src_args[0]]));
+    ORC_ASM_CODE(compiler,"  lvewx %s, 0, %s\n",
+        powerpc_get_regname (dest->alloc),
+        powerpc_get_regname (greg));
+    powerpc_emit_X (compiler, 0x7c00008e, powerpc_regnum(dest->alloc),
+        0, powerpc_regnum(greg));
+
+    ORC_ASM_CODE(compiler,"  lvsl %s, 0, %s\n",
+        powerpc_get_regname (POWERPC_V0),
+        powerpc_get_regname (greg));
+    powerpc_emit_X (compiler, 0x7c00000c, powerpc_regnum(POWERPC_V0),
+        0, powerpc_regnum(greg));
+
+    ORC_ASM_CODE(compiler,"  vperm %s, %s, %s, %s\n",
+        powerpc_get_regname (dest->alloc),
+        powerpc_get_regname (dest->alloc),
+        powerpc_get_regname (dest->alloc),
+        powerpc_get_regname (POWERPC_V0));
+    powerpc_emit_VA (compiler, 4,
+        powerpc_regnum(dest->alloc),
+        powerpc_regnum(dest->alloc),
+        powerpc_regnum(dest->alloc),
+        powerpc_regnum(POWERPC_V0), 43);
+    switch (src->size) {
+      case 1:
+        ORC_ASM_CODE(compiler,"  vspltb %s, %s, 3\n",
+            powerpc_get_regname (dest->alloc),
+            powerpc_get_regname (dest->alloc));
+        powerpc_emit_VX (compiler, 0x1000020c,
+            powerpc_regnum(dest->alloc), 3, powerpc_regnum(dest->alloc));
+        break;
+      case 2:
+        ORC_ASM_CODE(compiler,"  vsplth %s, %s, 1\n",
+            powerpc_get_regname (dest->alloc),
+            powerpc_get_regname (dest->alloc));
+        powerpc_emit_VX (compiler, 0x1000024c,
+            powerpc_regnum(dest->alloc), 1, powerpc_regnum(dest->alloc));
+        break;
+      case 4:
+        ORC_ASM_CODE(compiler,"  vspltw %s, %s, 0\n",
+            powerpc_get_regname (dest->alloc),
+            powerpc_get_regname (dest->alloc));
+        powerpc_emit_VX (compiler, 0x1000028c,
+            powerpc_regnum(dest->alloc), 0, powerpc_regnum(dest->alloc));
+        break;
+    }
+  } else {
+    int value = src->value;
+
+    switch (src->size) {
+      case 1:
+        if (value < 16 && value >= -16) {
+          ORC_ASM_CODE(compiler,"  vspltisb %s, %d\n",
+              powerpc_get_regname(dest->alloc), value&0x1f);
+          powerpc_emit_VX(compiler, 0x1000030c,
+              powerpc_regnum(dest->alloc), value & 0x1f, 0);
+        } else {
+          ORC_COMPILER_ERROR(compiler,"can't load constant");
+        }
+        break;
+      case 2:
+        if (value < 16 && value >= -16) {
+          ORC_ASM_CODE(compiler,"  vspltish %s, %d\n",
+              powerpc_get_regname(dest->alloc), value&0x1f);
+          powerpc_emit_VX(compiler, 0x1000034c,
+              powerpc_regnum(dest->alloc), value & 0x1f, 0);
+        } else {
+          ORC_COMPILER_ERROR(compiler,"can't load constant");
+        }
+        break;
+      case 4:
+        if (value < 16 && value >= -16) {
+          ORC_ASM_CODE(compiler,"  vspltisw %s, %d\n",
+              powerpc_get_regname(dest->alloc), value&0x1f);
+          powerpc_emit_VX(compiler, 0x1000038c,
+              powerpc_regnum(dest->alloc), value & 0x1f, 0);
+        } else {
+          ORC_COMPILER_ERROR(compiler,"can't load constant");
+        }
+        break;
+    }
+  }
+
+}
+
+static void
+powerpc_rule_loadX (OrcCompiler *compiler, void *user, OrcInstruction *insn)
+{
+  OrcVariable *src = compiler->vars + insn->src_args[0];
+  OrcVariable *dest = compiler->vars + insn->dest_args[0];
+  int size = src->size << compiler->loop_shift;
+
+  switch (size) {
+    case 1:
+      ORC_ASM_CODE(compiler,"  lvebx %s, 0, %s\n",
+          powerpc_get_regname (dest->alloc),
+          powerpc_get_regname (src->ptr_register));
+      powerpc_emit_X (compiler, 0x7c00000e, powerpc_regnum(dest->alloc),
+          0, powerpc_regnum(src->ptr_register));
+      break;
+    case 2:
+      ORC_ASM_CODE(compiler,"  lvehx %s, 0, %s\n",
+          powerpc_get_regname (dest->alloc),
+          powerpc_get_regname (src->ptr_register));
+      powerpc_emit_X (compiler, 0x7c00004e, powerpc_regnum(dest->alloc),
+          0, powerpc_regnum(src->ptr_register));
+      break;
+    case 4:
+      ORC_ASM_CODE(compiler,"  lvewx %s, 0, %s\n",
+          powerpc_get_regname (dest->alloc),
+          powerpc_get_regname (src->ptr_register));
+      powerpc_emit_X (compiler, 0x7c00008e, powerpc_regnum(dest->alloc),
+          0, powerpc_regnum(src->ptr_register));
+      break;
+  }
+  ORC_ASM_CODE(compiler,"  lvsl %s, 0, %s\n",
+      powerpc_get_regname (POWERPC_V0),
+      powerpc_get_regname (src->ptr_register));
+  powerpc_emit_X (compiler, 0x7c00000c, powerpc_regnum(POWERPC_V0),
+      0, powerpc_regnum(src->ptr_register));
+  ORC_ASM_CODE(compiler,"  vperm %s, %s, %s, %s\n",
+  powerpc_get_regname (dest->alloc),
+  powerpc_get_regname (dest->alloc),
+      powerpc_get_regname (dest->alloc),
+      powerpc_get_regname (POWERPC_V0));
+  powerpc_emit_VA (compiler, 4,
+      powerpc_regnum(dest->alloc),
+      powerpc_regnum(dest->alloc),
+      powerpc_regnum(dest->alloc),
+      powerpc_regnum(POWERPC_V0), 43);
+}
+
+static void
+powerpc_rule_storeX (OrcCompiler *compiler, void *user, OrcInstruction *insn)
+{
+  OrcVariable *src = compiler->vars + insn->src_args[0];
+  OrcVariable *dest = compiler->vars + insn->dest_args[0];
+  int size = dest->size << compiler->loop_shift;
+
+  ORC_ASM_CODE(compiler,"  lvsr %s, 0, %s\n",
+      powerpc_get_regname (POWERPC_V0),
+      powerpc_get_regname (dest->ptr_register));
+  powerpc_emit_X (compiler, 0x7c00004c, powerpc_regnum(POWERPC_V0),
+      0, powerpc_regnum(dest->ptr_register));
+  ORC_ASM_CODE(compiler,"  vperm %s, %s, %s, %s\n",
+      powerpc_get_regname (src->alloc),
+      powerpc_get_regname (src->alloc),
+      powerpc_get_regname (src->alloc),
+      powerpc_get_regname (POWERPC_V0));
+  powerpc_emit_VA (compiler, 4,
+      powerpc_regnum(src->alloc),
+      powerpc_regnum(src->alloc),
+      powerpc_regnum(src->alloc),
+      powerpc_regnum(POWERPC_V0), 43);
+
+  switch (size) {
+    case 1:
+      ORC_ASM_CODE(compiler,"  stvebx %s, 0, %s\n",
+          powerpc_get_regname (src->alloc),
+          powerpc_get_regname (dest->ptr_register));
+      powerpc_emit_X (compiler, 0x7c00010e,
+          powerpc_regnum(src->alloc),
+          0, powerpc_regnum(dest->ptr_register));
+      break;
+    case 2:
+      ORC_ASM_CODE(compiler,"  stvehx %s, 0, %s\n",
+          powerpc_get_regname (src->alloc),
+          powerpc_get_regname (dest->ptr_register));
+      powerpc_emit_X (compiler, 0x7c00014e,
+          powerpc_regnum(src->alloc),
+          0, powerpc_regnum(dest->ptr_register));
+      break;
+    case 4:
+      ORC_ASM_CODE(compiler,"  stvewx %s, 0, %s\n",
+          powerpc_get_regname (src->alloc),
+          powerpc_get_regname (dest->ptr_register));
+      powerpc_emit_X (compiler, 0x7c00018e,
+          powerpc_regnum(src->alloc),
+          0, powerpc_regnum(dest->ptr_register));
+      break;
+  }
+}
+
+
+
 #define RULE(name, opcode, code) \
 static void \
 powerpc_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \
@@ -32,11 +228,18 @@ powerpc_rule_ ## name (OrcCompiler *p, void *user, OrcInstruction *insn) \
   int src1 = ORC_SRC_ARG (p, insn, 0); \
   int src2 = ORC_SRC_ARG (p, insn, 1); \
   int dest = ORC_DEST_ARG (p, insn, 0); \
-  if (p->vars[insn->src_args[1]].vartype != ORC_VAR_TYPE_CONST && \
-      p->vars[insn->src_args[1]].vartype != ORC_VAR_TYPE_PARAM) { \
+  if (p->vars[insn->src_args[1]].vartype == ORC_VAR_TYPE_CONST) { \
+    ORC_ASM_CODE(p,"  vspltisb %s, %d\n", \
+        powerpc_get_regname(p->tmpreg), p->vars[insn->src_args[1]].value); \
+    powerpc_emit_VX(p, 0x1000030c, \
+        powerpc_regnum(p->tmpreg), p->vars[insn->src_args[1]].value, 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);\
 }
 
 RULE(addb, "vaddubm", 0x10000000)
@@ -599,12 +802,22 @@ orc_compiler_powerpc_register_rules (OrcTarget *target)
   REG(signw);
   REG(signl);
 
-  REG(select0wb);
-  REG(select1wb);
-  REG(select0lw);
-  REG(select1lw);
-  REG(mergebw);
-  REG(mergewl);
+  if (0) REG(select0wb);
+  if (0) REG(select1wb);
+  if (0) REG(select0lw);
+  if (0) REG(select1lw);
+  if (0) REG(mergebw);
+  if (0) REG(mergewl);
+
+  orc_rule_register (rule_set, "loadpb", powerpc_rule_loadpX, NULL);
+  orc_rule_register (rule_set, "loadpw", powerpc_rule_loadpX, NULL);
+  orc_rule_register (rule_set, "loadpl", powerpc_rule_loadpX, NULL);
+  orc_rule_register (rule_set, "loadb", powerpc_rule_loadX, NULL);
+  orc_rule_register (rule_set, "loadw", powerpc_rule_loadX, NULL);
+  orc_rule_register (rule_set, "loadl", powerpc_rule_loadX, NULL);
+  orc_rule_register (rule_set, "storeb", powerpc_rule_storeX, NULL);
+  orc_rule_register (rule_set, "storew", powerpc_rule_storeX, NULL);
+  orc_rule_register (rule_set, "storel", powerpc_rule_storeX, NULL);
 
   orc_rule_register (rule_set, "andnb", powerpc_rule_andnX, NULL);
   orc_rule_register (rule_set, "andnw", powerpc_rule_andnX, NULL);