diff options
author | David Schleef <ds@ginger.bigkitten.com> | 2008-05-20 12:35:14 -0700 |
---|---|---|
committer | David Schleef <ds@ginger.bigkitten.com> | 2008-05-20 12:35:14 -0700 |
commit | b1b8fdccc0981ef32a17030d19d3d153509c20db (patch) | |
tree | 236b810067d8b8fc4ba89b0c6e98c88f73a0afac | |
parent | f35e4adb51a0347ca28c766e9b62d4600882ab23 (diff) | |
download | liboil-b1b8fdccc0981ef32a17030d19d3d153509c20db.tar.gz |
[orc] rewrite register handling, add mmx rules
-rw-r--r-- | orc/orcopcodes.c | 8 | ||||
-rw-r--r-- | orc/orcprogram-x86.c | 169 | ||||
-rw-r--r-- | orc/orcprogram.c | 13 | ||||
-rw-r--r-- | orc/orcprogram.h | 49 | ||||
-rw-r--r-- | orc/orcrule.c | 52 |
5 files changed, 201 insertions, 90 deletions
diff --git a/orc/orcopcodes.c b/orc/orcopcodes.c index b9ee821..d82757d 100644 --- a/orc/orcopcodes.c +++ b/orc/orcopcodes.c @@ -52,6 +52,12 @@ orc_opcode_find_by_name (const char *name) } static void +move_s16 (OrcExecutor *ex, void *user) +{ + ex->args[0]->s16 = ex->args[1]->s16; +} + +static void add_s16 (OrcExecutor *ex, void *user) { ex->args[0]->s16 = (int16_t)(ex->args[1]->s16 + ex->args[2]->s16); @@ -84,6 +90,8 @@ rshift_s16 (OrcExecutor *ex, void *user) void orc_opcode_init (void) { + orc_opcode_register("_loadi_s16", 1, 1, move_s16, NULL); + orc_opcode_register("add_s16", 1, 2, add_s16, NULL); orc_opcode_register("sub_s16", 1, 2, sub_s16, NULL); orc_opcode_register("mul_s16", 1, 2, mul_s16, NULL); diff --git a/orc/orcprogram-x86.c b/orc/orcprogram-x86.c index 6757d4c..1eeab2e 100644 --- a/orc/orcprogram-x86.c +++ b/orc/orcprogram-x86.c @@ -32,6 +32,9 @@ void x86_emit_modrm_memoffset (OrcProgram *program, int reg1, int offset, int re void x86_emit_modrm_reg (OrcProgram *program, int reg1, int reg2); void x86_test (OrcProgram *program); +void orc_program_x86_register_rules (void); +void orc_program_mmx_register_rules (void); + enum { X86_EAX = ORC_GP_REG_BASE, X86_ECX, @@ -83,6 +86,23 @@ x86_get_regname_16(int i) } } +static const char * +x86_get_regname_mmx(int i) +{ + static const char *x86_regs[] = { "mm0", "mm1", "mm2", "mm3", + "mm4", "mm5", "mm6", "mm7" }; + + if (i>=ORC_GP_REG_BASE && i<ORC_GP_REG_BASE + 8) return x86_regs[i - ORC_GP_REG_BASE]; + switch (i) { + case 0: + return "UNALLOCATED"; + case 1: + return "direct"; + default: + return "ERROR"; + } +} + void orc_program_rewrite_vars (OrcProgram *program); void orc_program_allocate_regs (OrcProgram *program); @@ -95,13 +115,13 @@ x86_emit_prologue (OrcProgram *program) g_print("test:\n"); x86_emit_push (program, 4, X86_EBP); x86_emit_mov_memoffset_reg (program, 4, 8, X86_ESP, X86_EBP); - if (program->used_regs[x86_get_regnum(X86_EDI)]) { + if (program->used_regs[X86_EDI]) { x86_emit_push (program, 4, X86_EDI); } - if (program->used_regs[x86_get_regnum(X86_ESI)]) { + if (program->used_regs[X86_ESI]) { x86_emit_push (program, 4, X86_ESI); } - if (program->used_regs[x86_get_regnum(X86_EBX)]) { + if (program->used_regs[X86_EBX]) { x86_emit_push (program, 4, X86_EBX); } } @@ -109,13 +129,13 @@ x86_emit_prologue (OrcProgram *program) void x86_emit_epilogue (OrcProgram *program) { - if (program->used_regs[x86_get_regnum(X86_EBX)]) { + if (program->used_regs[X86_EBX]) { x86_emit_pop (program, 4, X86_EBX); } - if (program->used_regs[x86_get_regnum(X86_ESI)]) { + if (program->used_regs[X86_ESI]) { x86_emit_pop (program, 4, X86_ESI); } - if (program->used_regs[x86_get_regnum(X86_EDI)]) { + if (program->used_regs[X86_EDI]) { x86_emit_pop (program, 4, X86_EDI); } x86_emit_pop (program, 4, X86_EBP); @@ -136,13 +156,11 @@ x86_do_fixups (OrcProgram *program) } } -OrcRuleList *orc_x86_list; - void orc_x86_init (void) { - orc_x86_list = orc_rule_list_new(); - orc_program_x86_register_rules (orc_x86_list); + orc_program_x86_register_rules (); + orc_program_mmx_register_rules (); } void @@ -199,6 +217,7 @@ orc_program_compile_x86 (OrcProgram *program) printf(" (chained)"); } } + printf(" rule_flag=%d", insn->rule_flag); printf("\n"); for(k=opcode->n_dest;k<opcode->n_src + opcode->n_dest;k++){ @@ -210,7 +229,7 @@ orc_program_compile_x86 (OrcProgram *program) x86_emit_mov_memoffset_reg (program, 2, 0, X86_ECX, args[k]->alloc); break; case ORC_VAR_TYPE_CONST: - if (args[k]->alloc != 1) { + if (insn->rule_flag != ORC_RULE_REG_IMM) { x86_emit_mov_imm_reg (program, 2, args[k]->s16, args[k]->alloc); } break; @@ -283,6 +302,13 @@ orc_program_compile_x86 (OrcProgram *program) /* rules */ static void +x86_rule_loadi_s16 (OrcProgram *p, void *user, OrcInstruction *insn) +{ + x86_emit_mov_imm_reg (p, 2, p->vars[insn->args[2]].s16, + p->vars[insn->args[0]].alloc); +} + +static void x86_rule_add_s16 (OrcProgram *p, void *user, OrcInstruction *insn) { if (insn->rule_flag == ORC_RULE_REG_IMM) { @@ -386,20 +412,129 @@ x86_rule_rshift_s16 (OrcProgram *p, void *user, OrcInstruction *insn) void -orc_program_x86_register_rules (OrcRuleList *list) +orc_program_x86_register_rules (void) { - orc_rule_list_register (list, "add_s16", x86_rule_add_s16, NULL, + orc_rule_register ("_loadi_s16", ORC_RULE_SCALAR_1, x86_rule_loadi_s16, NULL, + ORC_RULE_REG_IMM); + + orc_rule_register ("add_s16", ORC_RULE_SCALAR_1, x86_rule_add_s16, NULL, ORC_RULE_REG_REG | ORC_RULE_REG_IMM); - orc_rule_list_register (list, "sub_s16", x86_rule_sub_s16, NULL, + orc_rule_register ("sub_s16", ORC_RULE_SCALAR_1, x86_rule_sub_s16, NULL, ORC_RULE_REG_REG); - orc_rule_list_register (list, "mul_s16", x86_rule_mul_s16, NULL, + orc_rule_register ("mul_s16", ORC_RULE_SCALAR_1, x86_rule_mul_s16, NULL, ORC_RULE_REG_REG); - orc_rule_list_register (list, "lshift_s16", x86_rule_lshift_s16, NULL, + orc_rule_register ("lshift_s16", ORC_RULE_SCALAR_1, x86_rule_lshift_s16, NULL, ORC_RULE_REG_REG); - orc_rule_list_register (list, "rshift_s16", x86_rule_rshift_s16, NULL, + orc_rule_register ("rshift_s16", ORC_RULE_SCALAR_1, x86_rule_rshift_s16, NULL, ORC_RULE_REG_REG | ORC_RULE_REG_IMM); } +/* mmx rules */ + +static void +mmx_rule_loadi_s16 (OrcProgram *p, void *user, OrcInstruction *insn) +{ + x86_emit_mov_imm_reg (p, 4, p->vars[insn->args[2]].s16, X86_ECX); + + g_print(" movd %%ecx, %%%s\n", + x86_get_regname_mmx(p->vars[insn->args[0]].alloc)); + *p->codeptr++ = 0x0f; + *p->codeptr++ = 0x6e; + x86_emit_modrm_reg (p, X86_ECX, p->vars[insn->args[0]].alloc); + + g_print(" pshufw $0, %%%s, %%%s\n", + x86_get_regname_mmx(p->vars[insn->args[0]].alloc), + x86_get_regname_mmx(p->vars[insn->args[0]].alloc)); + + *p->codeptr++ = 0x0f; + *p->codeptr++ = 0x70; + x86_emit_modrm_reg (p, p->vars[insn->args[0]].alloc, + p->vars[insn->args[0]].alloc); + *p->codeptr++ = 0x00; +} + +static void +mmx_rule_add_s16 (OrcProgram *p, void *user, OrcInstruction *insn) +{ + g_print(" paddw %%%s, %%%s\n", + x86_get_regname_mmx(p->vars[insn->args[2]].alloc), + x86_get_regname_mmx(p->vars[insn->args[0]].alloc)); + + *p->codeptr++ = 0x0f; + *p->codeptr++ = 0xfd; + x86_emit_modrm_reg (p, p->vars[insn->args[2]].alloc, + p->vars[insn->args[0]].alloc); +} + +static void +mmx_rule_sub_s16 (OrcProgram *p, void *user, OrcInstruction *insn) +{ + g_print(" psubw %%%s, %%%s\n", + x86_get_regname_mmx(p->vars[insn->args[2]].alloc), + x86_get_regname_mmx(p->vars[insn->args[0]].alloc)); + + *p->codeptr++ = 0x0f; + *p->codeptr++ = 0xf9; + x86_emit_modrm_reg (p, p->vars[insn->args[2]].alloc, + p->vars[insn->args[0]].alloc); +} + +static void +mmx_rule_mul_s16 (OrcProgram *p, void *user, OrcInstruction *insn) +{ + g_print(" pmullw %%%s, %%%s\n", + x86_get_regname_mmx(p->vars[insn->args[2]].alloc), + x86_get_regname_mmx(p->vars[insn->args[0]].alloc)); + + *p->codeptr++ = 0x0f; + *p->codeptr++ = 0xd5; + x86_emit_modrm_reg (p, p->vars[insn->args[2]].alloc, + p->vars[insn->args[0]].alloc); +} + +static void +mmx_rule_lshift_s16 (OrcProgram *p, void *user, OrcInstruction *insn) +{ + g_print(" psllw %%%s, %%%s\n", + x86_get_regname_mmx(p->vars[insn->args[2]].alloc), + x86_get_regname_mmx(p->vars[insn->args[0]].alloc)); + + *p->codeptr++ = 0x0f; + *p->codeptr++ = 0xf1; + x86_emit_modrm_reg (p, p->vars[insn->args[2]].alloc, + p->vars[insn->args[0]].alloc); +} + +static void +mmx_rule_rshift_s16 (OrcProgram *p, void *user, OrcInstruction *insn) +{ + g_print(" psraw %%%s, %%%s\n", + x86_get_regname_mmx(p->vars[insn->args[2]].alloc), + x86_get_regname_mmx(p->vars[insn->args[0]].alloc)); + + *p->codeptr++ = 0x0f; + *p->codeptr++ = 0xe1; + x86_emit_modrm_reg (p, p->vars[insn->args[2]].alloc, + p->vars[insn->args[0]].alloc); +} + +void +orc_program_mmx_register_rules (void) +{ + 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); +} /* code generation */ diff --git a/orc/orcprogram.c b/orc/orcprogram.c index 6dcad07..8930127 100644 --- a/orc/orcprogram.c +++ b/orc/orcprogram.c @@ -13,8 +13,12 @@ OrcProgram * orc_program_new (void) { OrcProgram *p; + p = malloc(sizeof(OrcProgram)); memset (p, 0, sizeof(OrcProgram)); + + p->rule_set = ORC_RULE_SCALAR_1; + return p; } @@ -130,7 +134,7 @@ orc_program_assign_rules (OrcProgram *program) OrcInstruction *insn = program->insns + i; unsigned int flags; - insn->rule = orc_rule_list_get (orc_x86_list,insn->opcode); + insn->rule = insn->opcode->rules + program->rule_set; flags = insn->rule->flags; if (flags & ORC_RULE_REG_IMM && @@ -259,10 +263,15 @@ orc_program_rewrite_vars (OrcProgram *program) } #endif - /* immediate operand, don't load */ if (program->insns[j].rule_flag == ORC_RULE_REG_IMM) { + /* immediate operand, don't load */ int src2 = program->insns[j].args[2]; program->vars[src2].alloc = 1; + } else { + int src2 = program->insns[j].args[2]; + if (program->vars[src2].alloc == 1) { + program->vars[src2].alloc = 0; + } } for(i=0;i<program->n_vars;i++){ diff --git a/orc/orcprogram.h b/orc/orcprogram.h index 8381af6..99df8d1 100644 --- a/orc/orcprogram.h +++ b/orc/orcprogram.h @@ -12,7 +12,6 @@ typedef struct _OrcArgument OrcArgument; typedef struct _OrcInstruction OrcInstruction; typedef struct _OrcProgram OrcProgram; typedef struct _OrcRule OrcRule; -typedef struct _OrcRuleList OrcRuleList; typedef struct _OrcFixup OrcFixup; typedef void (*OrcOpcodeEmulateFunc)(OrcExecutor *ex, void *user); @@ -20,6 +19,18 @@ typedef void (*OrcRuleEmitFunc)(OrcProgram *p, void *user, OrcInstruction *insn) #define ORC_N_REGS 64 +#define ORC_OPCODE_N_ARGS 4 +#define ORC_OPCODE_N_RULES 8 + +enum { + ORC_RULE_SCALAR_1 = 0, + ORC_RULE_SCALAR_2, + ORC_RULE_MMX_1, + ORC_RULE_MMX_2, + ORC_RULE_MMX_4, + ORC_RULE_MMX_8 +}; + struct _OrcType { char *name; int size; @@ -51,12 +62,19 @@ struct _OrcVariable { int16_t s16; }; +struct _OrcRule { + unsigned int flags; + OrcRuleEmitFunc emit; + void *emit_user; +}; struct _OrcOpcode { char *name; int n_src; int n_dest; - OrcType *arg_types[10]; + OrcType *arg_types[ORC_OPCODE_N_ARGS]; + + OrcRule rules[ORC_OPCODE_N_RULES]; OrcOpcodeEmulateFunc emulate; void *emulate_user; @@ -95,6 +113,7 @@ struct _OrcProgram { int n_vars; OrcInstruction *insn; + int rule_set; unsigned char *code; void *code_exec; @@ -133,21 +152,6 @@ enum { ORC_RULE_REG_CL = (1<<6) }; -struct _OrcRule { - OrcOpcode *opcode; - - unsigned int flags; - - OrcRuleEmitFunc emit; - void *emit_user; -}; - -struct _OrcRuleList { - int n_alloc; - int n_rules; - OrcRule *rules; -}; - #define ORC_GP_REG_BASE 8 void orc_init (void); @@ -184,17 +188,12 @@ void orc_executor_set_n (OrcExecutor *ex, int n); void orc_executor_emulate (OrcExecutor *ex); void orc_executor_run (OrcExecutor *ex); - -OrcRuleList *orc_rule_list_new(void); -void orc_rule_list_free (OrcRuleList *rule_list); -void orc_rule_list_register (OrcRuleList *rule_list, const char *op_name, +void orc_rule_register (const char *opcode_name, unsigned int mode, OrcRuleEmitFunc emit, void *emit_user, unsigned int flags); -OrcRule * orc_rule_list_get (OrcRuleList *rule_list, OrcOpcode *opcode); -void orc_program_x86_register_rules (OrcRuleList *rule_list); + +void orc_program_x86_register_rules (void); void orc_program_allocate_codemem (OrcProgram *program); void orc_program_dump_code (OrcProgram *program); -extern OrcRuleList *orc_x86_list; - #endif diff --git a/orc/orcrule.c b/orc/orcrule.c index 3b13020..7024745 100644 --- a/orc/orcrule.c +++ b/orc/orcrule.c @@ -9,56 +9,16 @@ #include <orc/orcprogram.h> -OrcRuleList * -orc_rule_list_new (void) -{ - OrcRuleList *rule_list; - - rule_list = malloc (sizeof(OrcRuleList)); - memset (rule_list, 0, sizeof(OrcRuleList)); - - return rule_list; -} - -void -orc_rule_list_free (OrcRuleList *rule_list) -{ - if (rule_list->rules) { - free (rule_list->rules); - } - free (rule_list); -} - void -orc_rule_list_register (OrcRuleList *rule_list, const char *opcode_name, +orc_rule_register (const char *opcode_name, unsigned int mode, OrcRuleEmitFunc emit, void *emit_user, unsigned int flags) { - int i; + OrcOpcode *opcode; - if (rule_list->n_rules == rule_list->n_alloc) { - rule_list->n_alloc += 100; - rule_list->rules = realloc (rule_list->rules, sizeof(OrcRule) * rule_list->n_alloc); - } + opcode = orc_opcode_find_by_name (opcode_name); - i = rule_list->n_rules; - rule_list->rules[i].opcode = orc_opcode_find_by_name (opcode_name); - rule_list->rules[i].emit = emit; - rule_list->rules[i].emit_user = emit_user; - rule_list->rules[i].flags = flags; - - rule_list->n_rules++; + opcode->rules[mode].emit = emit; + opcode->rules[mode].emit_user = emit_user; + opcode->rules[mode].flags = flags; } -OrcRule * -orc_rule_list_get (OrcRuleList *rule_list, OrcOpcode *opcode) -{ - int i; - for (i=0;i<rule_list->n_rules;i++){ - if (rule_list->rules[i].opcode == opcode) { - return rule_list->rules + i; - } - } - return NULL; -} - - |