diff options
author | David Schleef <ds@ginger.bigkitten.com> | 2008-05-20 22:41:35 -0700 |
---|---|---|
committer | David Schleef <ds@ginger.bigkitten.com> | 2008-05-20 22:41:35 -0700 |
commit | 4477508ae5af09e741f530abf0bf73ed8f396513 (patch) | |
tree | 062031fd43f2acfde721f9d173cdcc9a8024016f | |
parent | 75d06203e0111752f75762ac4b0bc45cce1e55ed (diff) | |
download | liboil-4477508ae5af09e741f530abf0bf73ed8f396513.tar.gz |
[orc] Fix some mmx instructions. Add C backend
-rw-r--r-- | orc/Makefile.am | 1 | ||||
-rw-r--r-- | orc/orc.c | 1 | ||||
-rw-r--r-- | orc/orcprogram-c.c | 199 | ||||
-rw-r--r-- | orc/orcprogram-x86.c | 56 | ||||
-rw-r--r-- | orc/orcprogram.c | 6 | ||||
-rw-r--r-- | orc/orcprogram.h | 8 | ||||
-rw-r--r-- | orc/test.c | 21 |
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 \ @@ -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; + } +} + |