orcrules-mmx.c \
orcrules-sse.c \
orcrules-arm.c \
+ orcprogram-neon.c \
+ orcrules-neon.c \
orcdebug.c \
orccpu.c \
orcutils.c \
orc_mmx_init();
orc_sse_init();
orc_powerpc_init();
+ orc_neon_init();
orc_arm_init();
}
--- /dev/null
+
+#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);
+ }
+ }
+ }
+}
+
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);
--- /dev/null
+
+#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);
+
+}
+
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
--- /dev/null
+
+#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);
+}
+
+