From 497b00cade96e3d5e247f6e74bd171152a9e86b4 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Wed, 14 May 2008 17:09:18 -0700 Subject: more jit hacking. creates code that assembles and works --- examples/jit/jit.c | 26 ++++-- examples/jit/ojprogram-x86.c | 203 +++++++++++++++++++++++++++++++++++-------- examples/jit/ojprogram.c | 52 +++++++++++ examples/jit/ojprogram.h | 40 ++++++++- 4 files changed, 278 insertions(+), 43 deletions(-) (limited to 'examples') diff --git a/examples/jit/jit.c b/examples/jit/jit.c index c8aa5da..bbb1152 100644 --- a/examples/jit/jit.c +++ b/examples/jit/jit.c @@ -14,6 +14,8 @@ int16_t src1[N]; int16_t src2[N]; int16_t dest[N]; +void test(OJExecutor *ex); + int main (int argc, char *argv[]) { @@ -21,7 +23,6 @@ main (int argc, char *argv[]) OJExecutor *ex; int s1, s2, d1, offset, shift; int t1; - int i; oj_opcode_init (); @@ -45,23 +46,38 @@ main (int argc, char *argv[]) oj_executor_set_array (ex, s2, src2); oj_executor_set_array (ex, d1, dest); - if (0) { + oj_program_compile_x86 (p); + +#if 0 + if (1) { + int i; + for(i=0;i>1); } - } else { - oj_program_compile_x86 (p); } +#endif return 0; } + +void +test1 (int16_t *dest, int16_t *src1, int16_t *src2, int n) +{ + int i; + for(i=0;i>1; + } +} + diff --git a/examples/jit/ojprogram-x86.c b/examples/jit/ojprogram-x86.c index 7df11b6..de23aca 100644 --- a/examples/jit/ojprogram-x86.c +++ b/examples/jit/ojprogram-x86.c @@ -119,8 +119,42 @@ oj_program_output_mmx (OJProgram *program) } #endif -static const char *x86_regs[] = { "eax", "ecx", "edx", "ebx", - "esp", "ebp", "esi", "edi" }; +#define X86_REG_BASE 8 + +static const char * +x86_get_regname(int i) +{ + static const char *x86_regs[] = { "eax", "ecx", "edx", "ebx", + "esp", "ebp", "esi", "edi" }; + + if (i>=X86_REG_BASE && i=X86_REG_BASE && in_insns); g_print(" push %%ebp\n"); g_print(" movl 0x8(%%esp), %%ebp\n"); + g_print(" push %%edi\n"); + g_print(" push %%esi\n"); + g_print(" push %%ebx\n"); g_print(" movl 0x%02x(%%ebp), %%ecx\n", (int)G_STRUCT_OFFSET(OJExecutor,n)); g_print(" movl %%ecx, 0x%02x(%%ebp)\n", (int)G_STRUCT_OFFSET(OJExecutor,counter)); g_print(" testl %%ecx, %%ecx\n"); - g_print(" jeq 2f\n"); + g_print(" je 2f\n"); g_print("1:\n"); for(j=0;jn_insns;j++){ @@ -155,40 +197,59 @@ oj_program_compile_x86 (OJProgram *program) printf("# %d: %s\n", j, insn->opcode->name); /* set up args */ - for(k=opcode->n_dest;kn_src + opcode->n_dest;k++){ + for(k=0;kn_src + opcode->n_dest;k++){ args[k] = program->vars + insn->args[k]; + } + for(k=opcode->n_dest;kn_src + opcode->n_dest;k++){ switch (args[k]->vartype) { case OJ_VAR_TYPE_SRC: - g_print(" movl 0x%02x(%%ebp), %%esi\n", + g_print(" movl 0x%02x(%%ebp), %%ecx\n", (int)G_STRUCT_OFFSET(OJExecutor, arrays[k])); - g_print(" movw 0(%%esi), %%%s\n", x86_regs[k]); + g_print(" movw 0(%%ecx), %%%s\n", + x86_get_regname_16(args[k]->alloc)); break; case OJ_VAR_TYPE_CONST: - g_print(" movl $%d, %%%s\n", args[k]->s16, x86_regs[k]); + g_print(" movl $%d, %%%s\n", args[k]->s16, + x86_get_regname(args[k]->alloc)); break; case OJ_VAR_TYPE_TEMP: - g_print(" movw temp, %%%s\n", x86_regs[k]); +#if 0 + g_print(" movw temp, %%%s\n", + x86_get_regname(args[k]->alloc)); +#endif break; default: break; } } - //opcode->emulate (ex, opcode->emulate_user); - printf("emit: %s\n", opcode->name); + rule = oj_rule_list_get (list, opcode); + if (rule) { + if (rule->flags & OJ_RULE_MUST_CHAIN_SRC1 && + insn->args[0] != insn->args[1]) { + g_print (" movw %%%s, %%%s\n", + x86_get_regname_16(args[1]->alloc), + x86_get_regname_16(args[0]->alloc)); + } + rule->emit (program, rule->emit_user, insn); + } else { + printf("No rule for: %s\n", opcode->name); + } for(k=0;kn_dest;k++){ - args[k] = program->vars + insn->args[k]; - switch (args[k]->vartype) { case OJ_VAR_TYPE_DEST: - g_print(" movl 0x%02x(%%ebp), %%esi\n", + g_print(" movl 0x%02x(%%ebp), %%ecx\n", (int)G_STRUCT_OFFSET(OJExecutor, arrays[k])); - g_print(" movw %%%s, 0(%%esi)\n", x86_regs[k]); + g_print(" movw %%%s, 0(%%ecx)\n", + x86_get_regname_16(args[k]->alloc)); break; case OJ_VAR_TYPE_TEMP: - g_print(" movw %%%s, temp\n", x86_regs[k]); +#if 0 + g_print(" movw %%%s, temp\n", + x86_get_regname(args[k]->alloc)); +#endif break; default: break; @@ -196,15 +257,26 @@ oj_program_compile_x86 (OJProgram *program) } } + for(k=0;kn_vars;k++){ + if (program->vars[k].vartype == OJ_VAR_TYPE_SRC || + program->vars[k].vartype == OJ_VAR_TYPE_DEST) { + g_print(" addl $2, 0x%02x(%%ebp)\n", + (int)G_STRUCT_OFFSET(OJExecutor, arrays[k])); + } + } g_print(" decl 0x%02x(%%ebp)\n", (int)G_STRUCT_OFFSET(OJExecutor,counter)); g_print(" jne 1b\n"); g_print("2:\n"); + g_print(" pop %%ebx\n"); + g_print(" pop %%esi\n"); + g_print(" pop %%edi\n"); g_print(" pop %%ebp\n"); g_print(" ret\n"); } +#if 0 static int oj_program_get_reg (OJProgram *program, int insn, int var) { @@ -238,7 +310,9 @@ oj_program_retire_reg (OJProgram *program, int var) } } } +#endif +#if 0 void oj_program_allocate_regs (OJProgram *program) { @@ -274,7 +348,7 @@ oj_program_allocate_regs (OJProgram *program) if (program->regs[i].first_use == j) { for(k=0;k<8;k++){ if (!alloc[k]) { - program->regs[i].alloc = k; + program->regs[i].alloc = X86_REG_BASE + k; alloc[k] = 1; break; } @@ -286,7 +360,7 @@ oj_program_allocate_regs (OJProgram *program) } for(i=0;in_regs;i++){ if (program->regs[i].last_use == j) { - alloc[program->regs[i].alloc] = 0; + alloc[program->regs[i].alloc - X86_REG_BASE] = 0; } } } @@ -297,21 +371,24 @@ oj_program_allocate_regs (OJProgram *program) program->regs[i].first_use, program->regs[i].last_use, program->regs[i].retired, - x86_regs[program->regs[i].alloc]); + x86_get_regname(program->regs[i].alloc)); } } +#endif void oj_program_rewrite_vars (OJProgram *program) { + int i; int j; int k; OJInstruction *insn; OJOpcode *opcode; int var; int actual_var; + int alloc[8] = { 0, 1, 0, 0, 1, 1, 0, 0 }; for(j=0;jn_insns;j++){ insn = program->insns + j; @@ -337,7 +414,7 @@ oj_program_rewrite_vars (OJProgram *program) program->vars[var].used = TRUE; program->vars[var].first_use = j; } - program->vars[var].last_use = j; + program->vars[actual_var].last_use = j; } for(k=0;kn_dest;k++){ @@ -379,13 +456,12 @@ oj_program_rewrite_vars (OJProgram *program) } } -#if 0 for(j=0;jn_insns;j++){ - for(i=0;in_regs;i++){ - if (program->regs[i].first_use == j) { + for(i=0;in_vars;i++){ + if (program->vars[i].first_use == j) { for(k=0;k<8;k++){ if (!alloc[k]) { - program->regs[i].alloc = k; + program->vars[i].alloc = k + X86_REG_BASE; alloc[k] = 1; break; } @@ -395,22 +471,20 @@ oj_program_rewrite_vars (OJProgram *program) } } } - for(i=0;in_regs;i++){ - if (program->regs[i].last_use == j) { - alloc[program->regs[i].alloc] = 0; + for(i=0;in_vars;i++){ + if (program->vars[i].last_use == j) { + alloc[program->vars[i].alloc - X86_REG_BASE] = 0; } } } - for(i=0;in_regs;i++){ - g_print("%2d: %2d %2d %2d %d %s\n", - i, program->regs[i].var, - program->regs[i].first_use, - program->regs[i].last_use, - program->regs[i].retired, - x86_regs[program->regs[i].alloc]); + for(i=0;in_vars;i++){ + g_print("%2d: %2d %2d %s\n", + i, + program->vars[i].first_use, + program->vars[i].last_use, + x86_get_regname(program->vars[i].alloc)); } -#endif } @@ -451,3 +525,64 @@ oj_program_dump (OJProgram *program) } + +/* rules */ + +static void +x86_rule_add_s16 (OJProgram *p, void *user, OJInstruction *insn) +{ + g_print(" addw %%%s, %%%s\n", + x86_get_regname_16(p->vars[insn->args[2]].alloc), + x86_get_regname_16(p->vars[insn->args[0]].alloc)); +} + +static void +x86_rule_sub_s16 (OJProgram *p, void *user, OJInstruction *insn) +{ + g_print(" subw %%%s, %%%s\n", + x86_get_regname_16(p->vars[insn->args[2]].alloc), + x86_get_regname_16(p->vars[insn->args[0]].alloc)); +} + +static void +x86_rule_mul_s16 (OJProgram *p, void *user, OJInstruction *insn) +{ + g_print(" imulw %%%s, %%%s\n", + x86_get_regname_16(p->vars[insn->args[2]].alloc), + x86_get_regname_16(p->vars[insn->args[0]].alloc)); +} + +static void +x86_rule_lshift_s16 (OJProgram *p, void *user, OJInstruction *insn) +{ + g_print(" shlw %%%s, %%%s\n", + x86_get_regname_16(p->vars[insn->args[2]].alloc), + x86_get_regname_16(p->vars[insn->args[0]].alloc)); +} + +static void +x86_rule_rshift_s16 (OJProgram *p, void *user, OJInstruction *insn) +{ + g_print(" movl %%%s, %%ecx\n", + x86_get_regname(p->vars[insn->args[2]].alloc)); + g_print(" sarw %%cl, %%%s\n", + x86_get_regname_16(p->vars[insn->args[0]].alloc)); +} + + +void +oj_program_x86_register_rules (OJRuleList *list) +{ + oj_rule_list_register (list, "add_s16", x86_rule_add_s16, NULL, + OJ_RULE_MUST_CHAIN_SRC1 | OJ_RULE_SYMMETRIC_SRC); + oj_rule_list_register (list, "sub_s16", x86_rule_sub_s16, NULL, + OJ_RULE_MUST_CHAIN_SRC1); + oj_rule_list_register (list, "mul_s16", x86_rule_mul_s16, NULL, + OJ_RULE_MUST_CHAIN_SRC1 | OJ_RULE_SYMMETRIC_SRC); + oj_rule_list_register (list, "lshift_s16", x86_rule_lshift_s16, NULL, + OJ_RULE_MUST_CHAIN_SRC1); + oj_rule_list_register (list, "rshift_s16", x86_rule_rshift_s16, NULL, + OJ_RULE_MUST_CHAIN_SRC1); +} + + diff --git a/examples/jit/ojprogram.c b/examples/jit/ojprogram.c index 6699c6e..340dff6 100644 --- a/examples/jit/ojprogram.c +++ b/examples/jit/ojprogram.c @@ -237,3 +237,55 @@ oj_executor_emulate (OJExecutor *ex) } } +/* rule list */ + +OJRuleList * +oj_rule_list_new (void) +{ + OJRuleList *rule_list; + + rule_list = malloc (sizeof(OJRuleList)); + memset (rule_list, 0, sizeof(OJRuleList)); + + return rule_list; +} + +void +oj_rule_list_free (OJRuleList *rule_list) +{ + free (rule_list->rules); + free (rule_list); +} + +void +oj_rule_list_register (OJRuleList *rule_list, const char *opcode_name, + OJRuleEmitFunc emit, void *emit_user, unsigned int flags) +{ + int i; + + if (rule_list->n_rules == rule_list->n_alloc) { + rule_list->n_alloc += 100; + rule_list->rules = realloc (rule_list, sizeof(OJRule) * rule_list->n_alloc); + } + + i = rule_list->n_rules; + rule_list->rules[i].opcode = oj_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++; +} + +OJRule * +oj_rule_list_get (OJRuleList *rule_list, OJOpcode *opcode) +{ + int i; + for (i=0;in_rules;i++){ + if (rule_list->rules[i].opcode == opcode) { + return rule_list->rules + i; + } + } + return NULL; +} + diff --git a/examples/jit/ojprogram.h b/examples/jit/ojprogram.h index c825563..dd41350 100644 --- a/examples/jit/ojprogram.h +++ b/examples/jit/ojprogram.h @@ -11,9 +11,11 @@ typedef struct _OJOpcode OJOpcode; typedef struct _OJArgument OJArgument; typedef struct _OJInstruction OJInstruction; typedef struct _OJProgram OJProgram; -typedef struct _OJRegister OJRegister; +typedef struct _OJRule OJRule; +typedef struct _OJRuleList OJRuleList; typedef void (*OJOpcodeEmulateFunc)(OJExecutor *ex, void *user); +typedef void (*OJRuleEmitFunc)(OJProgram *p, void *user, OJInstruction *insn); struct _OJType { char *name; @@ -40,6 +42,8 @@ struct _OJVariable { int replaced; int replacement; + int alloc; + int16_t s16; }; @@ -68,8 +72,11 @@ struct _OJArgument { struct _OJInstruction { OJOpcode *opcode; int args[3]; + + OJRule *rule; }; +#if 0 struct _OJRegister { int var; @@ -79,6 +86,7 @@ struct _OJRegister { int alloc; }; +#endif struct _OJProgram { OJInstruction insns[100]; @@ -88,9 +96,6 @@ struct _OJProgram { int n_vars; OJInstruction *insn; - - OJRegister regs[100]; - int n_regs; }; struct _OJExecutor { @@ -105,6 +110,27 @@ struct _OJExecutor { }; +#define OJ_RULE_MUST_CHAIN_SRC1 0x0001 +#define OJ_RULE_MAY_CHAIN_SRC1 0x0002 +#define OJ_RULE_SYMMETRIC_SRC 0x0004 +#define OJ_RULE_SRC2_IS_CL 0x0008 + +struct _OJRule { + OJOpcode *opcode; + + unsigned int flags; + + OJRuleEmitFunc emit; + void *emit_user; +}; + +struct _OJRuleList { + int n_alloc; + int n_rules; + OJRule *rules; +}; + + OJProgram * oj_program_new (void); OJOpcode * oj_opcode_find_by_name (const char *name); void oj_opcode_init (void); @@ -133,6 +159,12 @@ void oj_executor_set_n (OJExecutor *ex, int n); void oj_executor_emulate (OJExecutor *ex); +OJRuleList *oj_rule_list_new(void); +void oj_rule_list_free (OJRuleList *rule_list); +void oj_rule_list_register (OJRuleList *rule_list, const char *op_name, + OJRuleEmitFunc emit, void *emit_user, unsigned int flags); +OJRule * oj_rule_list_get (OJRuleList *rule_list, OJOpcode *opcode); +void oj_program_x86_register_rules (OJRuleList *rule_list); #endif -- cgit v1.2.1