neon hacking
authorDavid Schleef <ds@schleef.org>
Tue, 31 Mar 2009 05:19:39 +0000 (22:19 -0700)
committerDavid Schleef <ds@schleef.org>
Tue, 26 May 2009 23:55:43 +0000 (16:55 -0700)
orc/orcprogram-neon.c
orc/orcrules-neon.c

index 71d41f2..1b21124 100644 (file)
@@ -31,6 +31,7 @@ void orc_compiler_dump (OrcCompiler *compiler);
 void neon_loadb (OrcCompiler *compiler, int dest, int src1, int offset);
 void neon_loadw (OrcCompiler *compiler, int dest, int src1, int offset);
 void neon_loadl (OrcCompiler *compiler, int dest, int src1, int offset);
+void neon_neg (OrcCompiler *compiler, int dest);
 void neon_storeb (OrcCompiler *compiler, int dest, int offset, int src1);
 void neon_storew (OrcCompiler *compiler, int dest, int offset, int src1);
 void neon_storel (OrcCompiler *compiler, int dest, int offset, int src1);
@@ -164,12 +165,15 @@ neon_load_constants (OrcCompiler *compiler)
   for(i=0;i<compiler->n_vars;i++){
     switch (compiler->vars[i].vartype) {
       case ORC_VAR_TYPE_CONST:
+        ORC_ASSERT (compiler->vars[i].size == 2);
         neon_emit_loadiw (compiler, compiler->vars[i].alloc,
             (int)compiler->vars[i].value);
         break;
       case ORC_VAR_TYPE_PARAM:
-        //neon_emit_loadw (compiler, compiler->vars[i].alloc,
-        //    (int)ORC_STRUCT_OFFSET(OrcExecutor, params[i]), neon_exec_ptr);
+        arm_emit_add_imm (compiler, neon_tmp_reg,
+            neon_exec_ptr, ORC_STRUCT_OFFSET(OrcExecutor, arrays[i]));
+        neon_loadl (compiler, compiler->vars[i].alloc, neon_exec_ptr, 0);
+        neon_neg (compiler, compiler->vars[i].alloc);
         break;
       case ORC_VAR_TYPE_SRC:
       case ORC_VAR_TYPE_DEST:
index 8de4e85..bc46324 100644 (file)
@@ -54,6 +54,7 @@ const char *neon_reg_name_quad (int reg)
   return vec_regs[reg&0x1f];
 }
 
+#if 0
 void
 neon_emit_mov (OrcCompiler *compiler, uint32_t code, int src, int dest)
 {
@@ -63,6 +64,7 @@ neon_emit_mov (OrcCompiler *compiler, uint32_t code, int src, int dest)
   code |= ((dest>>4)&0x1) << 7;
   arm_emit (compiler, code);
 }
+#endif
 
 void
 neon_loadb (OrcCompiler *compiler, int dest, int src1, int offset)
@@ -161,6 +163,22 @@ neon_loadl (OrcCompiler *compiler, int dest, int src1, int offset)
 }
 
 void
+neon_neg (OrcCompiler *compiler, int dest)
+{
+  uint32_t code;
+
+  ORC_ASM_CODE(compiler,"  vneg.s32 %s, %s\n",
+      neon_reg_name (dest),
+      neon_reg_name (dest));
+  code = 0xf3b90380;
+  code |= (dest&0xf) << 12;
+  code |= ((dest>>4)&0x1) << 22;
+  code |= (dest&0xf) << 0;
+  code |= ((dest>>4)&0x1) << 5;
+  arm_emit (compiler, code);
+}
+
+void
 neon_storeb (OrcCompiler *compiler, int dest, int offset, int src1)
 {
   uint32_t code;
@@ -433,11 +451,57 @@ neon_rule_ ## opcode (OrcCompiler *p, void *user, OrcInstruction *insn) \
     x |= ((p->vars[insn->src_args[0]].alloc>>4)&0x1)<<5; \
     x |= ((n - p->vars[insn->src_args[1]].value)&(n-1))<<16; \
     arm_emit (p, x); \
+  } else if (p->vars[insn->src_args[1]].vartype == ORC_VAR_TYPE_PARAM) { \
+    ORC_ASM_CODE(p,"  " insn_name " %s, %s, %s\n", \
+        neon_reg_name (p->vars[insn->dest_args[0]].alloc), \
+        neon_reg_name (p->vars[insn->src_args[0]].alloc), \
+        neon_reg_name (p->vars[insn->src_args[1]].alloc)); \
+    x |= (p->vars[insn->dest_args[0]].alloc&0xf)<<12; \
+    x |= ((p->vars[insn->dest_args[0]].alloc>>4)&0x1)<<22; \
+    x |= (p->vars[insn->src_args[0]].alloc&0xf)<<0; \
+    x |= ((p->vars[insn->src_args[0]].alloc>>4)&0x1)<<5; \
+    x |= (p->vars[insn->src_args[1]].alloc)<<16; \
+    x |= ((p->vars[insn->src_args[1]].alloc>>4))<<7; \
+    arm_emit (p, x); \
   } else { \
-    ORC_PROGRAM_ERROR(p,"shift rule only works with constants"); \
+    ORC_PROGRAM_ERROR(p,"shift rule only works with constants and params"); \
   } \
 }
 
+static void
+neon_rule_shrsw (OrcCompiler *p, void *user, OrcInstruction *insn)
+{
+  uint32_t code;
+  if (p->vars[insn->src_args[1]].vartype == ORC_VAR_TYPE_CONST) {
+    code = 0xf2900010;
+    ORC_ASM_CODE(p,"  vshr.s16 %s, %s, #%d\n",
+        neon_reg_name (p->vars[insn->dest_args[0]].alloc),
+        neon_reg_name (p->vars[insn->src_args[0]].alloc),
+        p->vars[insn->src_args[1]].value);
+    code |= (p->vars[insn->dest_args[0]].alloc&0xf)<<12;
+    code |= ((p->vars[insn->dest_args[0]].alloc>>4)&0x1)<<22;
+    code |= (p->vars[insn->src_args[0]].alloc&0xf)<<0;
+    code |= ((p->vars[insn->src_args[0]].alloc>>4)&0x1)<<5;
+    code |= ((16 - p->vars[insn->src_args[1]].value)&0xf)<<16;
+    arm_emit (p, code);
+  } else if (p->vars[insn->src_args[1]].vartype == ORC_VAR_TYPE_PARAM) {
+    code = 0xf2100400;
+    ORC_ASM_CODE(p,"  vshl.s16 %s, %s, %s\n",
+        neon_reg_name (p->vars[insn->dest_args[0]].alloc),
+        neon_reg_name (p->vars[insn->src_args[0]].alloc),
+        neon_reg_name (p->vars[insn->src_args[1]].alloc));
+    code |= (p->vars[insn->dest_args[0]].alloc&0xf)<<12;
+    code |= ((p->vars[insn->dest_args[0]].alloc>>4)&0x1)<<22;
+    code |= (p->vars[insn->src_args[0]].alloc&0xf)<<0;
+    code |= ((p->vars[insn->src_args[0]].alloc>>4)&0x1)<<5;
+    code |= (p->vars[insn->src_args[1]].alloc&0xf)<<16;
+    code |= ((p->vars[insn->src_args[1]].alloc>>4)&0x1)<<7;
+    arm_emit (p, code);
+  } else {
+    ORC_PROGRAM_ERROR(p,"shift rule only works with constants and params");
+  }
+}
+
 
 static void
 neon_rule_andn (OrcCompiler *p, void *user, OrcInstruction *insn)
@@ -500,7 +564,7 @@ BINARY(minuw,"vmin.u16",0xf3100610)
 BINARY(mullw,"vmul.i16",0xf2100910)
 BINARY(orw,"vorr",0xf2200110)
 LSHIFT(shlw,"vshl.i16",0xf2900510)
-RSHIFT(shrsw,"vshr.s16",0xf2900010,16)
+//RSHIFT(shrsw,"vshr.s16",0xf2900010,16)
 RSHIFT(shruw,"vshr.u16",0xf3900010,16)
 BINARY(subw,"vsub.i16",0xf3100800)
 BINARY(subssw,"vqsub.s16",0xf2100210)