summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Schleef <ds@ginger.bigkitten.com>2008-05-20 22:41:35 -0700
committerDavid Schleef <ds@ginger.bigkitten.com>2008-05-20 22:41:35 -0700
commit4477508ae5af09e741f530abf0bf73ed8f396513 (patch)
tree062031fd43f2acfde721f9d173cdcc9a8024016f
parent75d06203e0111752f75762ac4b0bc45cce1e55ed (diff)
downloadliboil-4477508ae5af09e741f530abf0bf73ed8f396513.tar.gz
[orc] Fix some mmx instructions. Add C backend
-rw-r--r--orc/Makefile.am1
-rw-r--r--orc/orc.c1
-rw-r--r--orc/orcprogram-c.c199
-rw-r--r--orc/orcprogram-x86.c56
-rw-r--r--orc/orcprogram.c6
-rw-r--r--orc/orcprogram.h8
-rw-r--r--orc/test.c21
7 files changed, 263 insertions, 29 deletions
diff --git a/orc/Makefile.am b/orc/Makefile.am
index 6554224..9388c8b 100644
--- a/orc/Makefile.am
+++ b/orc/Makefile.am
@@ -12,6 +12,7 @@ liborc_@LIBOIL_MAJORMINOR@_la_SOURCES = \
orcrule.c \
orctype.c \
orcprogram.c \
+ orcprogram-c.c \
orcprogram-x86.c \
orcprogram.h \
orcopcodes.c \
diff --git a/orc/orc.c b/orc/orc.c
index 1475505..a1dfce8 100644
--- a/orc/orc.c
+++ b/orc/orc.c
@@ -16,5 +16,6 @@ orc_init (void)
oil_init ();
orc_opcode_init();
orc_x86_init();
+ orc_c_init();
}
diff --git a/orc/orcprogram-c.c b/orc/orcprogram-c.c
new file mode 100644
index 0000000..a2bdd91
--- /dev/null
+++ b/orc/orcprogram-c.c
@@ -0,0 +1,199 @@
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <orc/orcprogram.h>
+
+
+void orc_c_init (void);
+
+void
+orc_program_assemble_c (OrcProgram *program)
+{
+ int i;
+ int j;
+ OrcInstruction *insn;
+ OrcOpcode *opcode;
+ OrcRule *rule;
+
+ printf("\n");
+ printf("void\n");
+ printf("test (OrcExecutor *ex)\n");
+ printf("{\n");
+ printf(" int i;\n");
+
+ for(i=0;i<program->n_vars;i++){
+ OrcVariable *var = program->vars + i;
+ switch (var->vartype) {
+ case ORC_VAR_TYPE_CONST:
+ printf(" int16_t var%d = %d;\n", i, var->s16);
+ break;
+ case ORC_VAR_TYPE_TEMP:
+ printf(" int16_t var%d;\n", i);
+ break;
+ case ORC_VAR_TYPE_SRC:
+ case ORC_VAR_TYPE_DEST:
+ printf(" int16_t *var%d = ex->var%d;\n", i, i);
+ break;
+ case ORC_VAR_TYPE_PARAM:
+ printf(" int16_t var%d = ex->var%d;\n", i, i);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ printf("\n");
+ printf(" for (i = 0; i < n; i++) {\n");
+
+ for(j=0;j<program->n_insns;j++){
+ insn = program->insns + j;
+ opcode = insn->opcode;
+
+ printf(" // %d: %s\n", j, insn->opcode->name);
+
+#if 0
+ for(k=opcode->n_dest;k<opcode->n_src + opcode->n_dest;k++){
+ switch (args[k]->vartype) {
+ case ORC_VAR_TYPE_SRC:
+ x86_emit_load_src (program, args[k]);
+ break;
+ case ORC_VAR_TYPE_CONST:
+ break;
+ case ORC_VAR_TYPE_TEMP:
+ break;
+ default:
+ break;
+ }
+ }
+#endif
+
+ rule = insn->rule;
+ if (rule) {
+ rule->emit (program, rule->emit_user, insn);
+ } else {
+ printf("No rule for: %s\n", opcode->name);
+ }
+
+#if 0
+ for(k=0;k<opcode->n_dest;k++){
+ switch (args[k]->vartype) {
+ case ORC_VAR_TYPE_DEST:
+ x86_emit_store_dest (program, args[k]);
+ break;
+ case ORC_VAR_TYPE_TEMP:
+ break;
+ default:
+ break;
+ }
+ }
+#endif
+ }
+
+ printf(" }\n");
+ printf("}\n");
+ printf("\n");
+}
+
+
+/* rules */
+
+static void
+c_get_name (char *name, OrcProgram *p, int var)
+{
+ switch (p->vars[var].vartype) {
+ case ORC_VAR_TYPE_CONST:
+ case ORC_VAR_TYPE_PARAM:
+ case ORC_VAR_TYPE_TEMP:
+ sprintf(name, "var%d", var);
+ break;
+ case ORC_VAR_TYPE_SRC:
+ case ORC_VAR_TYPE_DEST:
+ sprintf(name, "var%d[i]", var);
+ break;
+ default:
+ sprintf(name, "ERROR");
+ break;
+ }
+
+}
+
+static void
+c_rule_add_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
+{
+ char dest[20], src1[20], src2[20];
+
+ c_get_name (dest, p, insn->args[0]);
+ c_get_name (src1, p, insn->args[1]);
+ c_get_name (src2, p, insn->args[2]);
+
+ printf (" %s = %s + %s;\n", dest, src1, src2);
+}
+
+static void
+c_rule_sub_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
+{
+ char dest[20], src1[20], src2[20];
+
+ c_get_name (dest, p, insn->args[0]);
+ c_get_name (src1, p, insn->args[1]);
+ c_get_name (src2, p, insn->args[2]);
+
+ printf (" %s = %s - %s;\n", dest, src1, src2);
+}
+
+static void
+c_rule_mul_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
+{
+ char dest[20], src1[20], src2[20];
+
+ c_get_name (dest, p, insn->args[0]);
+ c_get_name (src1, p, insn->args[1]);
+ c_get_name (src2, p, insn->args[2]);
+
+ printf (" %s = %s * %s;\n", dest, src1, src2);
+}
+
+static void
+c_rule_lshift_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
+{
+ char dest[20], src1[20], src2[20];
+
+ c_get_name (dest, p, insn->args[0]);
+ c_get_name (src1, p, insn->args[1]);
+ c_get_name (src2, p, insn->args[2]);
+
+ printf (" %s = %s << %s;\n", dest, src1, src2);
+}
+
+static void
+c_rule_rshift_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
+{
+ char dest[20], src1[20], src2[20];
+
+ c_get_name (dest, p, insn->args[0]);
+ c_get_name (src1, p, insn->args[1]);
+ c_get_name (src2, p, insn->args[2]);
+
+ printf (" %s = %s >> %s;\n", dest, src1, src2);
+}
+
+
+void
+orc_c_init (void)
+{
+ orc_rule_register ("add_s16", ORC_RULE_C, c_rule_add_s16, NULL,
+ ORC_RULE_REG_REG);
+ orc_rule_register ("sub_s16", ORC_RULE_C, c_rule_sub_s16, NULL,
+ ORC_RULE_REG_REG);
+ orc_rule_register ("mul_s16", ORC_RULE_C, c_rule_mul_s16, NULL,
+ ORC_RULE_REG_REG);
+ orc_rule_register ("lshift_s16", ORC_RULE_C, c_rule_lshift_s16, NULL,
+ ORC_RULE_REG_REG);
+ orc_rule_register ("rshift_s16", ORC_RULE_C, c_rule_rshift_s16, NULL,
+ ORC_RULE_REG_REG);
+}
+
diff --git a/orc/orcprogram-x86.c b/orc/orcprogram-x86.c
index a669bb3..abb8470 100644
--- a/orc/orcprogram-x86.c
+++ b/orc/orcprogram-x86.c
@@ -274,6 +274,9 @@ x86_emit_store_dest (OrcProgram *program, OrcVariable *var)
break;
case ORC_RULE_MMX_1:
/* FIXME we might be using ecx twice here */
+ if (ptr_reg == X86_ECX) {
+ printf("ERROR\n");
+ }
x86_emit_mov_mmx_reg (program, var->alloc, X86_ECX);
x86_emit_mov_reg_memoffset (program, 2, X86_ECX, 0, ptr_reg);
break;
@@ -303,7 +306,7 @@ orc_program_assemble_x86 (OrcProgram *program)
x86_emit_mov_memoffset_reg (program, 4, (int)G_STRUCT_OFFSET(OrcExecutor,n),
X86_EBP, X86_ECX);
- x86_emit_sar_imm_reg (program, 4, 2, X86_ECX);
+ x86_emit_sar_imm_reg (program, 4, program->loop_shift, X86_ECX);
x86_emit_mov_reg_memoffset (program, 4, X86_ECX,
(int)G_STRUCT_OFFSET(OrcExecutor,counter), X86_EBP);
@@ -658,19 +661,23 @@ mmx_rule_rshift_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
void
orc_program_mmx_register_rules (void)
{
+ int i;
+
orc_rule_register ("_loadi_s16", ORC_RULE_MMX_4, mmx_rule_loadi_s16, NULL,
ORC_RULE_REG_IMM);
- orc_rule_register ("add_s16", ORC_RULE_MMX_4, mmx_rule_add_s16, NULL,
- ORC_RULE_REG_REG);
- orc_rule_register ("sub_s16", ORC_RULE_MMX_4, mmx_rule_sub_s16, NULL,
- ORC_RULE_REG_REG);
- orc_rule_register ("mul_s16", ORC_RULE_MMX_4, mmx_rule_mul_s16, NULL,
- ORC_RULE_REG_REG);
- orc_rule_register ("lshift_s16", ORC_RULE_MMX_4, mmx_rule_lshift_s16, NULL,
- ORC_RULE_REG_REG);
- orc_rule_register ("rshift_s16", ORC_RULE_MMX_4, mmx_rule_rshift_s16, NULL,
- ORC_RULE_REG_REG);
+ for(i=ORC_RULE_MMX_1; i <= ORC_RULE_MMX_4; i++) {
+ orc_rule_register ("add_s16", i, mmx_rule_add_s16, NULL,
+ ORC_RULE_REG_REG);
+ orc_rule_register ("sub_s16", i, mmx_rule_sub_s16, NULL,
+ ORC_RULE_REG_REG);
+ orc_rule_register ("mul_s16", i, mmx_rule_mul_s16, NULL,
+ ORC_RULE_REG_REG);
+ orc_rule_register ("lshift_s16", i, mmx_rule_lshift_s16, NULL,
+ ORC_RULE_REG_REG);
+ orc_rule_register ("rshift_s16", i, mmx_rule_rshift_s16, NULL,
+ ORC_RULE_REG_REG);
+ }
}
/* code generation */
@@ -765,18 +772,17 @@ void
x86_emit_mov_memoffset_mmx (OrcProgram *program, int size, int offset,
int reg1, int reg2)
{
- /* FIXME */
if (size == 4) {
g_print(" movd %d(%%%s), %%%s\n", offset, x86_get_regname(reg1),
x86_get_regname_mmx(reg2));
- *program->codeptr++ = 0x66;
+ *program->codeptr++ = 0x0f;
+ *program->codeptr++ = 0x6e;
} else {
g_print(" movq %d(%%%s), %%%s\n", offset, x86_get_regname(reg1),
x86_get_regname_mmx(reg2));
+ *program->codeptr++ = 0x0f;
+ *program->codeptr++ = 0x6f;
}
-
- *program->codeptr++ = 0x0f;
- *program->codeptr++ = 0x6f;
x86_emit_modrm_memoffset (program, reg2, offset, reg1);
}
@@ -801,18 +807,18 @@ void
x86_emit_mov_mmx_memoffset (OrcProgram *program, int size, int reg1, int offset,
int reg2)
{
- /* FIXME */
if (size == 4) {
g_print(" movd %%%s, %d(%%%s)\n", x86_get_regname_mmx(reg1), offset,
x86_get_regname(reg2));
- *program->codeptr++ = 0x66;
+ *program->codeptr++ = 0x0f;
+ *program->codeptr++ = 0x7e;
} else {
g_print(" movq %%%s, %d(%%%s)\n", x86_get_regname_mmx(reg1), offset,
x86_get_regname(reg2));
+ *program->codeptr++ = 0x0f;
+ *program->codeptr++ = 0x7f;
}
- *program->codeptr++ = 0x0f;
- *program->codeptr++ = 0x7f;
x86_emit_modrm_memoffset (program, reg1, offset, reg2);
}
@@ -856,9 +862,9 @@ void x86_emit_mov_reg_mmx (OrcProgram *program, int reg1, int reg2)
/* FIXME */
g_print(" movd %%%s, %%%s\n", x86_get_regname(reg1),
x86_get_regname_mmx(reg2));
- *program->codeptr++ = 0x66;
- *program->codeptr++ = 0x89;
- x86_emit_modrm_reg (program, reg2, reg1);
+ *program->codeptr++ = 0x0f;
+ *program->codeptr++ = 0x6e;
+ x86_emit_modrm_reg (program, reg1, reg2);
}
void x86_emit_mov_mmx_reg (OrcProgram *program, int reg1, int reg2)
@@ -866,8 +872,8 @@ void x86_emit_mov_mmx_reg (OrcProgram *program, int reg1, int reg2)
/* FIXME */
g_print(" movd %%%s, %%%s\n", x86_get_regname_mmx(reg1),
x86_get_regname(reg2));
- *program->codeptr++ = 0x66;
- *program->codeptr++ = 0x89;
+ *program->codeptr++ = 0x0f;
+ *program->codeptr++ = 0x7e;
x86_emit_modrm_reg (program, reg2, reg1);
}
diff --git a/orc/orcprogram.c b/orc/orcprogram.c
index 37402dc..be1b591 100644
--- a/orc/orcprogram.c
+++ b/orc/orcprogram.c
@@ -22,8 +22,9 @@ orc_program_new (void)
p = malloc(sizeof(OrcProgram));
memset (p, 0, sizeof(OrcProgram));
- p->rule_set = ORC_RULE_MMX_4;
- p->n_per_loop = 4;
+ p->rule_set = ORC_RULE_MMX_1;
+ p->n_per_loop = 1;
+ p->loop_shift = 0;
return p;
}
@@ -176,6 +177,7 @@ orc_program_compile (OrcProgram *program)
orc_program_allocate_codemem (program);
orc_program_assemble_x86 (program);
+ //orc_program_assemble_c (program);
orc_program_dump_code (program);
}
diff --git a/orc/orcprogram.h b/orc/orcprogram.h
index e5cb83c..29a6a4f 100644
--- a/orc/orcprogram.h
+++ b/orc/orcprogram.h
@@ -2,7 +2,7 @@
#ifndef _ORC_PROGRAM_H_
#define _ORC_PROGRAM_H_
-#include <glib.h>
+//#include <glib.h>
typedef struct _OrcType OrcType;
typedef struct _OrcExecutor OrcExecutor;
@@ -24,7 +24,8 @@ typedef void (*OrcRuleEmitFunc)(OrcProgram *p, void *user, OrcInstruction *insn)
#define ORC_OPCODE_N_RULES 8
enum {
- ORC_RULE_SCALAR_1 = 0,
+ ORC_RULE_C = 0,
+ ORC_RULE_SCALAR_1,
ORC_RULE_SCALAR_2,
ORC_RULE_MMX_1,
ORC_RULE_MMX_2,
@@ -146,6 +147,7 @@ struct _OrcProgram {
int used_regs[ORC_N_REGS];
int alloc_regs[ORC_N_REGS];
+ int loop_shift;
int n_per_loop;
};
@@ -182,9 +184,11 @@ void orc_opcode_init (void);
void orc_program_append (OrcProgram *p, const char *opcode, int arg0, int arg1, int arg2);
void orc_x86_init (void);
+void orc_c_init (void);
void orc_program_compile (OrcProgram *p);
void orc_program_assemble_x86 (OrcProgram *p);
+void orc_program_assemble_c (OrcProgram *p);
void orc_program_free (OrcProgram *program);
int orc_program_add_temporary (OrcProgram *program, const char *type, const char *name);
diff --git a/orc/test.c b/orc/test.c
new file mode 100644
index 0000000..bff0df2
--- /dev/null
+++ b/orc/test.c
@@ -0,0 +1,21 @@
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <orc/orcprogram.h>
+
+void
+test (OrcExecutor *ex)
+{
+ int i;
+ int n = ex->n;
+ int16_t *var0 = ex->arrays[0];
+ int16_t *var1 = ex->arrays[1];
+ int16_t *var2 = ex->arrays[2];
+ int16_t var3;
+ int16_t var6;
+
+ for (i = 0; i < n; i++) {
+ var0[i] = (var1[i] + var2[i] + 1) >> 1;
+ }
+}
+