Add neon target
authorDavid Schleef <ds@schleef.org>
Wed, 18 Mar 2009 01:47:06 +0000 (18:47 -0700)
committerDavid Schleef <ds@schleef.org>
Tue, 26 May 2009 23:55:40 +0000 (16:55 -0700)
orc/Makefile.am
orc/orc.c
orc/orcprogram-neon.c [new file with mode: 0644]
orc/orcprogram.h
orc/orcrules-neon.c [new file with mode: 0644]
testsuite/Makefile.am
testsuite/test6.c [new file with mode: 0644]

index c90e83b..6e85300 100644 (file)
@@ -26,6 +26,8 @@ liborc_@ORC_MAJORMINOR@_la_SOURCES = \
        orcrules-mmx.c \
        orcrules-sse.c \
        orcrules-arm.c \
+       orcprogram-neon.c \
+       orcrules-neon.c \
        orcdebug.c \
        orccpu.c \
        orcutils.c \
index e55515a..c930a03 100644 (file)
--- a/orc/orc.c
+++ b/orc/orc.c
@@ -23,6 +23,7 @@ orc_init (void)
   orc_mmx_init();
   orc_sse_init();
   orc_powerpc_init();
+  orc_neon_init();
   orc_arm_init();
 }
 
diff --git a/orc/orcprogram-neon.c b/orc/orcprogram-neon.c
new file mode 100644 (file)
index 0000000..9e4c6e8
--- /dev/null
@@ -0,0 +1,358 @@
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <orc/orcprogram.h>
+#include <orc/arm.h>
+#include <orc/orcutils.h>
+#include <orc/orcdebug.h>
+
+#define SIZE 65536
+
+int neon_exec_ptr = ARM_V1;
+
+void neon_emit_loop (OrcCompiler *compiler);
+
+void orc_compiler_neon_register_rules (OrcTarget *target);
+
+void orc_compiler_neon_init (OrcCompiler *compiler);
+void orc_compiler_neon_assemble (OrcCompiler *compiler);
+
+void orc_compiler_rewrite_vars (OrcCompiler *compiler);
+void orc_compiler_dump (OrcCompiler *compiler);
+
+void neon_loadw (OrcCompiler *compiler, int dest, int src1, int offset);
+void neon_storew (OrcCompiler *compiler, int dest, int offset, int src1);
+
+void
+neon_emit_prologue (OrcCompiler *compiler)
+{
+  unsigned int regs = 0;
+  int i;
+
+  orc_compiler_append_code(compiler,".global %s\n", compiler->program->name);
+  orc_compiler_append_code(compiler,"%s:\n", compiler->program->name);
+
+  for(i=0;i<16;i++){
+    if (compiler->used_regs[ORC_GP_REG_BASE + i] &&
+        compiler->save_regs[ORC_GP_REG_BASE + i]) {
+      regs |= (1<<i);
+    }
+  }
+  if (regs) arm_emit_push (compiler, regs);
+
+}
+
+void
+neon_dump_insns (OrcCompiler *compiler)
+{
+
+  arm_emit_label (compiler, 0);
+
+  arm_emit_add (compiler, ARM_A2, ARM_A3, ARM_A4);
+  arm_emit_sub (compiler, ARM_A2, ARM_A3, ARM_A4);
+  arm_emit_push (compiler, 0x06);
+  arm_emit_mov (compiler, ARM_A2, ARM_A3);
+
+  arm_emit_branch (compiler, ARM_COND_LE, 0);
+  arm_emit_branch (compiler, ARM_COND_AL, 0);
+
+  arm_emit_loadimm (compiler, ARM_A3, 0xa500);
+  arm_loadw (compiler, ARM_A3, ARM_A4, 0xa5);
+  arm_emit_load_reg (compiler, ARM_A3, ARM_A4, 0x5a5);
+}
+
+void
+neon_emit_epilogue (OrcCompiler *compiler)
+{
+  int i;
+  unsigned int regs = 0;
+
+  for(i=0;i<16;i++){
+    if (compiler->used_regs[ORC_GP_REG_BASE + i] &&
+        compiler->save_regs[ORC_GP_REG_BASE + i]) {
+      regs |= (1<<i);
+    }
+  }
+  if (regs) arm_emit_pop (compiler, regs);
+  arm_emit_bx_lr (compiler);
+
+  //arm_dump_insns (compiler);
+}
+
+static OrcTarget neon_target = {
+  "neon",
+#ifdef HAVE_ARM
+  TRUE,
+#else
+  FALSE,
+#endif
+  ORC_VEC_REG_BASE,
+  orc_compiler_neon_init,
+  orc_compiler_neon_assemble
+};
+
+void
+orc_neon_init (void)
+{
+  orc_target_register (&neon_target);
+
+  orc_compiler_neon_register_rules (&neon_target);
+}
+
+void
+orc_compiler_neon_init (OrcCompiler *compiler)
+{
+  int i;
+
+  for(i=ORC_GP_REG_BASE;i<ORC_GP_REG_BASE+16;i++){
+    compiler->valid_regs[i] = 1;
+  }
+  for(i=ORC_VEC_REG_BASE+3;i<ORC_VEC_REG_BASE+16;i++){
+    compiler->valid_regs[i] = 1;
+  }
+  compiler->valid_regs[ARM_V1] = 0;
+  //compiler->valid_regs[ARM_SB] = 0;
+  compiler->valid_regs[ARM_IP] = 0;
+  compiler->valid_regs[ARM_SP] = 0;
+  compiler->valid_regs[ARM_LR] = 0;
+  compiler->valid_regs[ARM_PC] = 0;
+  for(i=4;i<11;i++) {
+    compiler->save_regs[ORC_GP_REG_BASE+i] = 1;
+  }
+  
+  for(i=0;i<ORC_N_REGS;i++){
+    compiler->alloc_regs[i] = 0;
+    compiler->used_regs[i] = 0;
+  }
+
+  compiler->loop_shift = 0;
+}
+
+void
+neon_load_constants (OrcCompiler *compiler)
+{
+  int i;
+  for(i=0;i<compiler->n_vars;i++){
+    switch (compiler->vars[i].vartype) {
+      case ORC_VAR_TYPE_CONST:
+        //arm_emit_loadiw (compiler, compiler->vars[i].alloc,
+        //    (int)compiler->vars[i].value);
+        break;
+      case ORC_VAR_TYPE_PARAM:
+        //arm_emit_loadw (compiler, compiler->vars[i].alloc,
+        //    (int)ORC_STRUCT_OFFSET(OrcExecutor, params[i]), neon_exec_ptr);
+        break;
+      case ORC_VAR_TYPE_SRC:
+      case ORC_VAR_TYPE_DEST:
+        arm_emit_load_reg (compiler, 
+            compiler->vars[i].ptr_register,
+            neon_exec_ptr, ORC_STRUCT_OFFSET(OrcExecutor, arrays[i]));
+        break;
+      default:
+        break;
+    }
+  }
+}
+
+void
+neon_emit_load_src (OrcCompiler *compiler, OrcVariable *var)
+{
+  int ptr_reg;
+  if (var->ptr_register == 0) {
+    int i;
+    i = var - compiler->vars;
+    //arm_emit_mov_memoffset_reg (compiler, arm_ptr_size,
+    //    (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[i]),
+    //    neon_exec_ptr, X86_ECX);
+    ptr_reg = ARM_PC;
+  } else {
+    ptr_reg = var->ptr_register;
+  }
+  switch (var->size << compiler->loop_shift) {
+    //case 1:
+      //arm_emit_mov_memoffset_reg (compiler, 1, 0, ptr_reg, X86_ECX);
+      //arm_emit_mov_reg_arm (compiler, X86_ECX, var->alloc);
+      break;
+    case 2:
+      neon_loadw (compiler, var->alloc, ptr_reg, 0);
+      //arm_emit_mov_memoffset_reg (compiler, 2, 0, ptr_reg, X86_ECX);
+      //arm_emit_mov_reg_arm (compiler, X86_ECX, var->alloc);
+      break;
+    //case 4:
+      //arm_emit_mov_memoffset_arm (compiler, 4, 0, ptr_reg, var->alloc);
+      break;
+    //case 8:
+      //arm_emit_mov_memoffset_arm (compiler, 8, 0, ptr_reg, var->alloc);
+      break;
+    //case 16:
+      //arm_emit_mov_memoffset_arm (compiler, 16, 0, ptr_reg, var->alloc);
+      break;
+    default:
+      ORC_PROGRAM_ERROR(compiler, "bad size %d\n", var->size << compiler->loop_shift);
+  }
+}
+
+void
+neon_emit_store_dest (OrcCompiler *compiler, OrcVariable *var)
+{
+  int ptr_reg;
+  if (var->ptr_register == 0) {
+    //arm_emit_mov_memoffset_reg (compiler, arm_ptr_size,
+    //    var->ptr_offset, neon_exec_ptr, X86_ECX);
+    ptr_reg = ARM_PC;
+  } else {
+    ptr_reg = var->ptr_register;
+  }
+  switch (var->size << compiler->loop_shift) {
+    case 1:
+      //arm_emit_mov_arm_reg (compiler, var->alloc, X86_ECX);
+      //arm_emit_mov_reg_memoffset (compiler, 1, X86_ECX, 0, ptr_reg);
+      break;
+    case 2:
+      neon_storew (compiler, ptr_reg, 0, var->alloc);
+      //arm_emit_mov_arm_reg (compiler, var->alloc, X86_ECX);
+      //arm_emit_mov_reg_memoffset (compiler, 2, X86_ECX, 0, ptr_reg);
+      break;
+    case 4:
+      //arm_emit_mov_arm_memoffset (compiler, 4, var->alloc, 0, ptr_reg,
+      //    var->is_aligned, var->is_uncached);
+      break;
+    case 8:
+      //arm_emit_mov_arm_memoffset (compiler, 8, var->alloc, 0, ptr_reg,
+      //    var->is_aligned, var->is_uncached);
+      break;
+    case 16:
+      //arm_emit_mov_arm_memoffset (compiler, 16, var->alloc, 0, ptr_reg,
+      //    var->is_aligned, var->is_uncached);
+      break;
+    default:
+      ORC_PROGRAM_ERROR(compiler, "bad size %d\n", var->size << compiler->loop_shift);
+  }
+}
+
+void
+orc_compiler_neon_assemble (OrcCompiler *compiler)
+{
+  int dest_var = orc_compiler_get_dest (compiler);
+
+  compiler->vars[dest_var].is_aligned = FALSE;
+
+  neon_emit_prologue (compiler);
+
+  arm_emit_load_reg (compiler, ARM_IP, neon_exec_ptr,
+      (int)ORC_STRUCT_OFFSET(OrcExecutor,n));
+  neon_load_constants (compiler);
+
+  arm_emit_label (compiler, 1);
+
+  arm_emit_cmp_imm (compiler, ARM_IP, 0);
+  arm_emit_branch (compiler, ARM_COND_EQ, 3);
+
+  arm_emit_label (compiler, 2);
+  neon_emit_loop (compiler);
+  arm_emit_sub_imm (compiler, ARM_IP, ARM_IP, 1);
+  arm_emit_cmp_imm (compiler, ARM_IP, 0);
+  arm_emit_branch (compiler, ARM_COND_NE, 2);
+  arm_emit_label (compiler, 3);
+
+  neon_emit_epilogue (compiler);
+
+  arm_do_fixups (compiler);
+}
+
+void
+neon_emit_loop (OrcCompiler *compiler)
+{
+  int j;
+  int k;
+  OrcInstruction *insn;
+  OrcStaticOpcode *opcode;
+  OrcRule *rule;
+
+  for(j=0;j<compiler->n_insns;j++){
+    insn = compiler->insns + j;
+    opcode = insn->opcode;
+
+    orc_compiler_append_code(compiler,"# %d: %s", j, insn->opcode->name);
+
+    /* set up args */
+#if 0
+    for(k=0;k<opcode->n_src + opcode->n_dest;k++){
+      args[k] = compiler->vars + insn->args[k];
+      orc_compiler_append_code(compiler," %d", args[k]->alloc);
+      if (args[k]->is_chained) {
+        orc_compiler_append_code(compiler," (chained)");
+      }
+    }
+#endif
+    orc_compiler_append_code(compiler,"\n");
+
+    for(k=0;k<ORC_STATIC_OPCODE_N_SRC;k++){
+      if (opcode->src_size[k] == 0) continue;
+
+      switch (compiler->vars[insn->src_args[k]].vartype) {
+        case ORC_VAR_TYPE_SRC:
+          neon_emit_load_src (compiler, &compiler->vars[insn->src_args[k]]);
+          break;
+        case ORC_VAR_TYPE_CONST:
+          break;
+        case ORC_VAR_TYPE_PARAM:
+          break;
+        case ORC_VAR_TYPE_TEMP:
+          break;
+        default:
+          break;
+      }
+    }
+
+    rule = insn->rule;
+    if (rule && rule->emit) {
+      if (compiler->vars[insn->dest_args[0]].alloc !=
+          compiler->vars[insn->src_args[0]].alloc) {
+        arm_emit_mov (compiler, compiler->vars[insn->src_args[0]].alloc,
+            compiler->vars[insn->dest_args[0]].alloc);
+      }
+      rule->emit (compiler, rule->emit_user, insn);
+    } else {
+      orc_compiler_append_code(compiler,"No rule for: %s\n", opcode->name);
+    }
+
+    for(k=0;k<ORC_STATIC_OPCODE_N_DEST;k++){
+      if (opcode->dest_size[k] == 0) continue;
+
+      switch (compiler->vars[insn->dest_args[k]].vartype) {
+        case ORC_VAR_TYPE_DEST:
+          neon_emit_store_dest (compiler, &compiler->vars[insn->dest_args[k]]);
+          break;
+        case ORC_VAR_TYPE_TEMP:
+          break;
+        default:
+          break;
+      }
+    }
+  }
+
+  for(k=0;k<compiler->n_vars;k++){
+    if (compiler->vars[k].vartype == ORC_VAR_TYPE_SRC ||
+        compiler->vars[k].vartype == ORC_VAR_TYPE_DEST) {
+      if (compiler->vars[k].ptr_register) {
+        //arm_emit_add_imm_reg (compiler, arm_ptr_size,
+        //    compiler->vars[k].size << compiler->loop_shift,
+        //    compiler->vars[k].ptr_register);
+      } else {
+        //arm_emit_add_imm_memoffset (compiler, arm_ptr_size,
+        //    compiler->vars[k].size << compiler->loop_shift,
+        //    (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[k]),
+        //    neon_exec_ptr);
+      }
+    }
+  }
+}
+
index 7bc33a9..86b4084 100644 (file)
@@ -382,6 +382,7 @@ void orc_sse_init (void);
 void orc_arm_init (void);
 void orc_powerpc_init (void);
 void orc_c_init (void);
+void orc_neon_init (void);
 
 OrcCompileResult orc_program_compile (OrcProgram *p);
 OrcCompileResult orc_program_compile_for_target (OrcProgram *p, OrcTarget *target);
diff --git a/orc/orcrules-neon.c b/orc/orcrules-neon.c
new file mode 100644 (file)
index 0000000..cb316e5
--- /dev/null
@@ -0,0 +1,266 @@
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <orc/orcprogram.h>
+#include <orc/arm.h>
+
+
+const char *neon_reg_name (int reg)
+{
+  static const char *vec_regs[] = {
+    "d0", "d1", "d2", "d3",
+    "d4", "d5", "d6", "d7",
+    "d8", "d9", "d10", "d11",
+    "d12", "d13", "d14", "d15" };
+
+  if (reg < ORC_VEC_REG_BASE || reg >= ORC_VEC_REG_BASE+16) {
+    return "ERROR";
+  }
+
+  return vec_regs[reg&0xf];
+}
+
+void
+neon_loadw (OrcCompiler *compiler, int dest, int src1, int offset)
+{
+  uint32_t code;
+
+  code = 0xed900b00;
+  code |= (src1&0xf) << 16;
+  code |= (dest&0xf) << 12;
+  code |= (offset&0xf0) << 4;
+  code |= offset&0x0f;
+
+  ORC_ASM_CODE(compiler,"  vldr.64 %s, [%s, #%d]\n",
+      neon_reg_name (dest),
+      arm_reg_name (src1), offset);
+  arm_emit (compiler, code);
+}
+
+void
+neon_storew (OrcCompiler *compiler, int dest, int offset, int src1)
+{
+  uint32_t code;
+
+  code = 0xed800b00;
+  code |= (dest&0xf) << 16;
+  code |= (src1&0xf) << 12;
+  code |= (offset&0xf0) << 4;
+  code |= offset&0x0f;
+
+  ORC_ASM_CODE(compiler,"  vstr.64 %s, [%s, #%d]\n",
+      neon_reg_name (src1),
+      arm_reg_name (dest), offset);
+  arm_emit (compiler, code);
+}
+
+#define UNARY(opcode,insn_name,code) \
+static void \
+neon_rule_ ## opcode (OrcCompiler *p, void *user, OrcInstruction *insn) \
+{ \
+  uint32_t x = code; \
+  ORC_ASM_CODE(p,"  " insn_name " %s, %s\n", \
+      neon_reg_name (p->vars[insn->dest_args[0]].alloc), \
+      neon_reg_name (p->vars[insn->src_args[0]].alloc)); \
+  x |= (p->vars[insn->dest_args[0]].alloc&0xf)<<12; \
+  x |= (p->vars[insn->src_args[0]].alloc&0xf)<<0; \
+  arm_emit (p, x); \
+}
+
+#define BINARY(opcode,insn_name,code) \
+static void \
+neon_rule_ ## opcode (OrcCompiler *p, void *user, OrcInstruction *insn) \
+{ \
+  uint32_t x = code; \
+  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)<<16; \
+  x |= (p->vars[insn->src_args[0]].alloc&0xf)<<12; \
+  x |= (p->vars[insn->src_args[1]].alloc&0xf)<<0; \
+  arm_emit (p, x); \
+}
+
+#define MOVE(opcode,insn_name,code) \
+static void \
+neon_rule_ ## opcode (OrcCompiler *p, void *user, OrcInstruction *insn) \
+{ \
+  uint32_t x = code; \
+  ORC_ASM_CODE(p,"  " insn_name " %s, %s\n", \
+      neon_reg_name (p->vars[insn->dest_args[0]].alloc), \
+      neon_reg_name (p->vars[insn->src_args[0]].alloc)); \
+  x |= (p->vars[insn->dest_args[0]].alloc&0xf)<<16; \
+  x |= (p->vars[insn->src_args[0]].alloc&0xf)<<12; \
+  x |= (p->vars[insn->src_args[0]].alloc&0xf)<<0; \
+  arm_emit (p, x); \
+}
+
+#define SHIFT(opcode,insn_name,code) \
+static void \
+neon_rule_ ## opcode (OrcCompiler *p, void *user, OrcInstruction *insn) \
+{ \
+  uint32_t x = code; \
+  ORC_ASM_CODE(p,"  " insn_name " %s, %s, #2\n", \
+      neon_reg_name (p->vars[insn->dest_args[0]].alloc), \
+      neon_reg_name (p->vars[insn->src_args[0]].alloc)); \
+  x |= (p->vars[insn->dest_args[0]].alloc&0xf)<<12; \
+  x |= (p->vars[insn->src_args[0]].alloc&0xf)<<0; \
+  arm_emit (p, x); \
+}
+
+
+
+UNARY(absb,"vabs.s8",0xf3b10300)
+BINARY(addb,"vadd.i8",0xf2000800)
+BINARY(addssb,"vqadd.s8",0xf2000010)
+BINARY(addusb,"vqadd.u8",0xf3000010)
+BINARY(andb,"vand",0xf2000110)
+BINARY(cmpeqb,"vceq.i8",0xf3000810)
+BINARY(cmpgtsb,"vcgt.s8",0xf2000300)
+MOVE(copyb,"vmov",0xf2200110)
+BINARY(maxsb,"vmax.s8",0xf2000600)
+BINARY(maxub,"vmax.u8",0xf3000600)
+BINARY(minsb,"vmin.s8",0xf2000610)
+BINARY(minub,"vmin.u8",0xf3000610)
+BINARY(mullb,"vmul.i8",0xf2000910)
+BINARY(orb,"vorn",0xf2300110)
+SHIFT(shlb,"vshl.i8",0xf2890510)
+SHIFT(shrsb,"vshr.s8",0xf28f0010)
+SHIFT(shrub,"vshr.u8",0xf38f0010)
+BINARY(subb,"vsub.i8",0xf3000800)
+BINARY(subssb,"vqsub.s8",0xf2000210)
+BINARY(subusb,"vqsub.u8",0xf3000210)
+BINARY(xorb,"veor",0xf3000110)
+
+UNARY(absw,"vabs.s16",0xf3b50300)
+BINARY(addw,"vadd.i16",0xf2100800)
+BINARY(addssw,"vqadd.s16",0xf2100010)
+BINARY(addusw,"vqadd.u16",0xf3100010)
+BINARY(andw,"vand",0xf2000110)
+BINARY(cmpeqw,"vceq.i16",0xf3100810)
+BINARY(cmpgtsw,"vcgt.s16",0xf2100300)
+MOVE(copyw,"vmov",0xf2200110)
+BINARY(maxsw,"vmax.s16",0xf2100600)
+BINARY(maxuw,"vmax.u16",0xf3100600)
+BINARY(minsw,"vmin.s16",0xf2100610)
+BINARY(minuw,"vmin.u16",0xf3100610)
+BINARY(mullw,"vmul.i16",0xf2100910)
+BINARY(orw,"vorn",0xf2300110)
+SHIFT(shlw,"vshl.i16",0xf2910510)
+SHIFT(shrsw,"vshr.s16",0xf29f0010)
+SHIFT(shruw,"vshr.u16",0xf39f0010)
+BINARY(subw,"vsub.i16",0xf3100800)
+BINARY(subssw,"vqsub.s16",0xf2100210)
+BINARY(subusw,"vqsub.u16",0xf3100210)
+BINARY(xorw,"veor",0xf3000110)
+
+UNARY(absl,"vabs.s32",0xf3b90300)
+BINARY(addl,"vadd.i32",0xf2200800)
+BINARY(addssl,"vqadd.s32",0xf2200010)
+BINARY(addusl,"vqadd.u32",0xf3200010)
+BINARY(andl,"vand",0xf2000110)
+BINARY(cmpeql,"vceq.i32",0xf3200810)
+BINARY(cmpgtsl,"vcgt.s32",0xf2200300)
+MOVE(copyl,"vmov",0xf2200110)
+BINARY(maxsl,"vmax.s32",0xf2200600)
+BINARY(maxul,"vmax.u32",0xf3200600)
+BINARY(minsl,"vmin.s32",0xf2200610)
+BINARY(minul,"vmin.u32",0xf3200610)
+BINARY(mulll,"vmul.i32",0xf2200910)
+BINARY(orl,"vorn",0xf2300110)
+SHIFT(shll,"vshl.i32",0xf2a10510)
+SHIFT(shrsl,"vshr.s32",0xf2bf0010)
+SHIFT(shrul,"vshr.u32",0xf3bf0010)
+BINARY(subl,"vsub.i32",0xf3200800)
+BINARY(subssl,"vqsub.s32",0xf2200210)
+BINARY(subusl,"vqsub.u32",0xf3200210)
+BINARY(xorl,"veor",0xf3000110)
+
+
+
+void
+orc_compiler_neon_register_rules (OrcTarget *target)
+{
+  OrcRuleSet *rule_set;
+
+  rule_set = orc_rule_set_new (orc_opcode_set_get("sys"), target);
+
+#define REG(x) \
+    orc_rule_register (rule_set, #x , neon_rule_ ## x, NULL)
+
+  REG(absb);
+  REG(addb);
+  REG(addssb);
+  REG(addusb);
+  REG(andb);
+  REG(cmpeqb);
+  REG(cmpgtsb);
+  REG(copyb);
+  REG(maxsb);
+  REG(maxub);
+  REG(minsb);
+  REG(minub);
+  REG(mullb);
+  REG(orb);
+  REG(shlb);
+  REG(shrsb);
+  REG(shrub);
+  REG(subb);
+  REG(subssb);
+  REG(subusb);
+  REG(xorb);
+
+  REG(absw);
+  REG(addw);
+  REG(addssw);
+  REG(addusw);
+  REG(andw);
+  REG(cmpeqw);
+  REG(cmpgtsw);
+  REG(copyw);
+  REG(maxsw);
+  REG(maxuw);
+  REG(minsw);
+  REG(minuw);
+  REG(mullw);
+  REG(orw);
+  REG(shlw);
+  REG(shrsw);
+  REG(shruw);
+  REG(subw);
+  REG(subssw);
+  REG(subusw);
+  REG(xorw);
+
+  REG(absl);
+  REG(addl);
+  REG(addssl);
+  REG(addusl);
+  REG(andl);
+  REG(cmpeql);
+  REG(cmpgtsl);
+  REG(copyl);
+  REG(maxsl);
+  REG(maxul);
+  REG(minsl);
+  REG(minul);
+  REG(mulll);
+  REG(orl);
+  REG(shll);
+  REG(shrsl);
+  REG(shrul);
+  REG(subl);
+  REG(subssl);
+  REG(subusl);
+  REG(xorl);
+
+}
+
index ee30e71..4a65851 100644 (file)
@@ -18,6 +18,9 @@ orcbin_PROGRAMS = $(TESTS)
 
 CLEANFILES = temp-orc-test-*
 
+TESTS += test6
+noinst_PROGRAMS += test6
+
 AM_CFLAGS = $(ORC_CFLAGS)
 LIBS = $(ORC_LIBS) $(top_builddir)/orc-test/liborc-test-0.3.la
 
diff --git a/testsuite/test6.c b/testsuite/test6.c
new file mode 100644 (file)
index 0000000..c143bbc
--- /dev/null
@@ -0,0 +1,115 @@
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <orc/orc.h>
+
+#define PREFIX "/opt/arm-2008q3/bin/arm-none-linux-gnueabi-"
+
+int error = FALSE;
+
+void test_opcode (const char *name);
+
+int
+main (int argc, char *argv[])
+{
+  int i;
+  OrcOpcodeSet *opcode_set;
+
+  orc_init();
+
+  opcode_set = orc_opcode_set_get ("sys");
+
+  for(i=0;i<opcode_set->n_opcodes;i++){
+    printf("/* %s %d,%d,%d %p */\n",
+        opcode_set->opcodes[i].name,
+        opcode_set->opcodes[i].dest_size[0],
+        opcode_set->opcodes[i].src_size[0],
+        opcode_set->opcodes[i].src_size[1],
+        opcode_set->opcodes[i].emulate);
+    test_opcode (opcode_set->opcodes[i].name);
+  }
+
+  if (error) return 1;
+  return 0;
+}
+
+void
+test_opcode (const char *name)
+{
+  OrcProgram *p;
+  char s[40];
+  char cmd[200];
+  int ret;
+  FILE *file;
+
+  p = orc_program_new_dss (2,2,2);
+
+  sprintf(s, "test_%s", name);
+  orc_program_set_name (p, s);
+  orc_program_add_constant (p, 2, 1, "c1");
+
+  orc_program_append_str (p, name, "d1", "s1", "c1");
+
+  ret = orc_program_compile_for_target (p, orc_target_get_by_name("neon"));
+  if (!ret) {
+    error = TRUE;
+    goto out;
+  }
+
+  fflush (stdout);
+
+  file = fopen ("tmp-test6.s", "w");
+  fprintf(file, "%s", orc_program_get_asm_code (p));
+  fclose (file);
+
+  file = fopen ("dump", "w");
+  ret = fwrite(p->code, p->code_size, 1, file);
+  fclose (file);
+
+  ret = system (PREFIX "gcc -mcpu=cortex-a8 -mfpu=neon -Wall -c tmp-test6.s");
+  if (ret != 0) {
+    printf("gcc failed\n");
+    error = TRUE;
+    goto out;
+  }
+
+  ret = system (PREFIX "objdump -dr tmp-test6.o >tmp-test6.dis");
+  if (ret != 0) {
+    printf("objdump failed\n");
+    error = TRUE;
+    goto out;
+  }
+
+  sprintf (cmd, PREFIX "objcopy -I binary -O elf32-littlearm -B arm "
+      "--rename-section .data=.text "
+      "--redefine-sym _binary_dump_start=%s "
+      "dump tmp-test6.o", s);
+  ret = system (cmd);
+  if (ret != 0) {
+    printf("objcopy failed\n");
+    error = TRUE;
+    goto out;
+  }
+
+  ret = system (PREFIX "objdump -Dr tmp-test6.o >tmp-test6-dump.dis");
+  if (ret != 0) {
+    printf("objdump failed\n");
+    error = TRUE;
+    goto out;
+  }
+
+  ret = system ("diff -u tmp-test6.dis tmp-test6-dump.dis");
+  if (ret != 0) {
+    printf("diff failed\n");
+    error = TRUE;
+    goto out;
+  }
+
+out:
+  orc_program_free (p);
+}
+
+