Add loop alignment code to neon
authorDavid Schleef <ds@schleef.org>
Sun, 29 Mar 2009 19:13:44 +0000 (12:13 -0700)
committerDavid Schleef <ds@schleef.org>
Tue, 26 May 2009 23:55:42 +0000 (16:55 -0700)
orc/arm.c
orc/arm.h
orc/orcprogram-arm.c
orc/orcprogram-neon.c

index c0cd385..346c7a1 100644 (file)
--- a/orc/arm.c
+++ b/orc/arm.c
@@ -13,6 +13,7 @@
 #include <orc/orcprogram.h>
 #include <orc/arm.h>
 #include <orc/orcutils.h>
+#include <orc/orcdebug.h>
 
 
 const char *
@@ -161,16 +162,25 @@ arm_emit_branch (OrcCompiler *compiler, int cond, int label)
 }
 
 void
-arm_emit_loadimm (OrcCompiler *compiler, int dest, int imm)
+arm_emit_load_imm (OrcCompiler *compiler, int dest, int imm)
 {
   uint32_t code;
   int shift2;
 
   shift2 = 0;
+#if 0
   while (imm && ((imm&3)==0)) {
     imm >>= 2;
     shift2++;
   }
+#endif
+  while (imm && imm > 0xffff) {
+    if ((imm&3) != 0) {
+      ORC_ERROR("bad immediate value");
+    }
+    imm >>= 2;
+    shift2++;
+  }
 
   code = 0xe3a00000;
   code |= (dest&0xf) << 12;
@@ -233,6 +243,23 @@ arm_emit_add_imm (OrcCompiler *compiler, int dest, int src1, int value)
 }
 
 void
+arm_emit_and_imm (OrcCompiler *compiler, int dest, int src1, int value)
+{
+  uint32_t code;
+
+  code = 0xe2000000;
+  code |= (src1&0xf) << 16;
+  code |= (dest&0xf) << 12;
+  code |= (value) << 0;
+
+  ORC_ASM_CODE(compiler,"  and %s, %s, #%d\n",
+      arm_reg_name (dest),
+      arm_reg_name (src1),
+      value);
+  arm_emit (compiler, code);
+}
+
+void
 arm_emit_sub_imm (OrcCompiler *compiler, int dest, int src1, int value)
 {
   uint32_t code;
@@ -265,10 +292,28 @@ arm_emit_cmp_imm (OrcCompiler *compiler, int src1, int value)
 }
 
 void
+arm_emit_cmp (OrcCompiler *compiler, int src1, int src2)
+{
+  uint32_t code;
+
+  code = 0xe1500000;
+  code |= (src1&0xf) << 16;
+  code |= (src2&0xf) << 0;
+
+  ORC_ASM_CODE(compiler,"  cmp %s, %s\n",
+      arm_reg_name (src1),
+      arm_reg_name (src2));
+  arm_emit (compiler, code);
+}
+
+void
 arm_emit_asr_imm (OrcCompiler *compiler, int dest, int src1, int value)
 {
   uint32_t code;
 
+  if (value == 0) {
+    ORC_ERROR("bad immediate value");
+  }
   code = 0xe1a00040;
   code |= (src1&0xf) << 0;
   code |= (dest&0xf) << 12;
@@ -297,6 +342,21 @@ arm_emit_load_reg (OrcCompiler *compiler, int dest, int src1, int offset)
   arm_emit (compiler, code);
 }
 
+void
+arm_emit_store_reg (OrcCompiler *compiler, int dest, int src1, int offset)
+{
+  uint32_t code;
+
+  code = 0xe5800000;
+  code |= (dest&0xf) << 16;
+  code |= (src1&0xf) << 12;
+  code |= offset&0xfff;
+
+  ORC_ASM_CODE(compiler,"  str %s, [%s, #%d]\n",
+      arm_reg_name (src1),
+      arm_reg_name (dest), offset);
+  arm_emit (compiler, code);
+}
 
 
 void
index 36cc1d2..f804297 100644 (file)
--- a/orc/arm.h
+++ b/orc/arm.h
@@ -65,14 +65,16 @@ enum {
 void arm_emit (OrcCompiler *compiler, uint32_t insn);
 void arm_emit_bx_lr (OrcCompiler *compiler);
 const char * arm_reg_name (int reg);
-void arm_emit_loadimm (OrcCompiler *compiler, int dest, int imm);
+void arm_emit_load_imm (OrcCompiler *compiler, int dest, int imm);
 
 void arm_emit_add (OrcCompiler *compiler, int dest, int src1, int src2);
 void arm_emit_sub (OrcCompiler *compiler, int dest, int src1, int src2);
 void arm_emit_add_imm (OrcCompiler *compiler, int dest, int src1, int value);
+void arm_emit_and_imm (OrcCompiler *compiler, int dest, int src1, int value);
 void arm_emit_sub_imm (OrcCompiler *compiler, int dest, int src1, int value);
 void arm_emit_asr_imm (OrcCompiler *compiler, int dest, int src1, int value);
 void arm_emit_cmp_imm (OrcCompiler *compiler, int src1, int value);
+void arm_emit_cmp (OrcCompiler *compiler, int src1, int src2);
 
 void arm_emit_label (OrcCompiler *compiler, int label);
 void arm_emit_push (OrcCompiler *compiler, int regs);
@@ -87,6 +89,7 @@ void arm_loadw (OrcCompiler *compiler, int dest, int src1, int offset);
 void arm_storew (OrcCompiler *compiler, int dest, int offset, int src1);
 
 void arm_emit_load_reg (OrcCompiler *compiler, int dest, int src1, int offset);
+void arm_emit_store_reg (OrcCompiler *compiler, int src, int dest, int offset);
 
 void arm_do_fixups (OrcCompiler *compiler);
 
index 798450b..a2d1af0 100644 (file)
@@ -61,7 +61,7 @@ arm_dump_insns (OrcCompiler *compiler)
   arm_emit_branch (compiler, ARM_COND_LE, 0);
   arm_emit_branch (compiler, ARM_COND_AL, 0);
 
-  arm_emit_loadimm (compiler, ARM_A3, 0xa500);
+  arm_emit_load_imm (compiler, ARM_A3, 0xa500);
   arm_loadw (compiler, ARM_A3, ARM_A4, 0xa5);
   arm_emit_load_reg (compiler, ARM_A3, ARM_A4, 0x5a5);
 }
index 6d0fcbd..ed000c0 100644 (file)
@@ -65,7 +65,7 @@ neon_dump_insns (OrcCompiler *compiler)
   arm_emit_branch (compiler, ARM_COND_LE, 0);
   arm_emit_branch (compiler, ARM_COND_AL, 0);
 
-  arm_emit_loadimm (compiler, ARM_A3, 0xa500);
+  arm_emit_load_imm (compiler, ARM_A3, 0xa500);
   arm_loadw (compiler, ARM_A3, ARM_A4, 0xa5);
   arm_emit_load_reg (compiler, ARM_A3, ARM_A4, 0x5a5);
 }
@@ -211,15 +211,79 @@ neon_emit_store_dest (OrcCompiler *compiler, OrcVariable *var)
       var->size << compiler->loop_shift);
 }
 
+static int
+get_shift (int size)
+{
+  switch (size) {
+    case 1:
+      return 0;
+    case 2:
+      return 1;
+    case 4:
+      return 2;
+    default:
+      ORC_ERROR("bad size %d", size);
+  }
+  return -1;
+}
+
 void
 orc_compiler_neon_assemble (OrcCompiler *compiler)
 {
-  int dest_var = orc_compiler_get_dest (compiler);
+  int dest_var;
+  int dest_shift;
+  
+  dest_var = orc_compiler_get_dest (compiler);
+  dest_shift = get_shift (compiler->vars[dest_var].size);
 
   compiler->vars[dest_var].is_aligned = FALSE;
 
   neon_emit_prologue (compiler);
 
+  if (compiler->loop_shift > 0) {
+    arm_emit_load_imm (compiler, ARM_IP, 16);
+
+    arm_emit_load_reg (compiler, ARM_A3, neon_exec_ptr,
+        (int)ORC_STRUCT_OFFSET(OrcExecutor,n));
+    arm_emit_load_reg (compiler, ARM_A2, neon_exec_ptr,
+        (int)ORC_STRUCT_OFFSET(OrcExecutor,arrays[dest_var]));
+    arm_emit_sub (compiler, ARM_IP, ARM_IP, ARM_A2);
+    arm_emit_and_imm (compiler, ARM_IP, ARM_IP, 0xf);
+    if (dest_shift > 0) {
+      arm_emit_asr_imm (compiler, ARM_IP, ARM_IP, dest_shift);
+    }
+
+    arm_emit_cmp (compiler, ARM_IP, ARM_A3);
+    arm_emit_branch (compiler, ARM_COND_LE, 6);
+
+    arm_emit_store_reg (compiler, ARM_IP, neon_exec_ptr,
+        (int)ORC_STRUCT_OFFSET(OrcExecutor,counter1));
+    arm_emit_sub (compiler, ARM_A2, ARM_A3, ARM_IP);
+
+    arm_emit_asr_imm (compiler, ARM_A3, ARM_A2, compiler->loop_shift);
+    arm_emit_store_reg (compiler, ARM_A3, neon_exec_ptr,
+        (int)ORC_STRUCT_OFFSET(OrcExecutor,counter2));
+
+    arm_emit_and_imm (compiler, ARM_A3, ARM_A2, (1<<compiler->loop_shift)-1);
+    arm_emit_store_reg (compiler, ARM_A3, neon_exec_ptr,
+        (int)ORC_STRUCT_OFFSET(OrcExecutor,counter3));
+
+    arm_emit_branch (compiler, ARM_COND_AL, 7);
+    arm_emit_label (compiler, 6);
+
+    arm_emit_store_reg (compiler, ARM_A3, neon_exec_ptr,
+        (int)ORC_STRUCT_OFFSET(OrcExecutor,counter1));
+
+    arm_emit_load_imm (compiler, ARM_A3, 0);
+    arm_emit_store_reg (compiler, ARM_A3, neon_exec_ptr,
+        (int)ORC_STRUCT_OFFSET(OrcExecutor,counter2));
+    arm_emit_store_reg (compiler, ARM_A3, neon_exec_ptr,
+        (int)ORC_STRUCT_OFFSET(OrcExecutor,counter3));
+
+    arm_emit_label (compiler, 7);
+  }
+
+
   arm_emit_load_reg (compiler, ARM_IP, neon_exec_ptr,
       (int)ORC_STRUCT_OFFSET(OrcExecutor,n));
   if (compiler->loop_shift > 0) {