summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorDavid Schleef <ds@ginger.bigkitten.com>2008-05-14 17:09:18 -0700
committerDavid Schleef <ds@ginger.bigkitten.com>2008-05-14 17:09:18 -0700
commit497b00cade96e3d5e247f6e74bd171152a9e86b4 (patch)
treea52cd3cb28376fc8094f269eded94058cc7791a9 /examples
parentcde19e3ea598fc816ca88700d356b0f940e0eb1f (diff)
downloadliboil-497b00cade96e3d5e247f6e74bd171152a9e86b4.tar.gz
more jit hacking. creates code that assembles and works
Diffstat (limited to 'examples')
-rw-r--r--examples/jit/jit.c26
-rw-r--r--examples/jit/ojprogram-x86.c203
-rw-r--r--examples/jit/ojprogram.c52
-rw-r--r--examples/jit/ojprogram.h40
4 files changed, 278 insertions, 43 deletions
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<N;i++){
src1[i] = rand()&0xf;
src2[i] = rand()&0xf;
}
- oj_executor_emulate (ex);
+ test (ex);
+ //oj_executor_emulate (ex);
for(i=0;i<N;i++){
printf(" %4d %4d %4d %4d\n", src1[i], src2[i], dest[i],
(src1[i] + src2[i] + 1)>>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<n;i++){
+ dest[i] = (src1[i] + src2[i] + 1)>>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 + 8) return x86_regs[i - X86_REG_BASE];
+ switch (i) {
+ case 0:
+ return "UNALLOCATED";
+ case 1:
+ return "direct";
+ default:
+ return "ERROR";
+ }
+}
+
+static const char *
+x86_get_regname_16(int i)
+{
+ static const char *x86_regs[] = { "ax", "cx", "dx", "bx",
+ "sp", "bp", "si", "di" };
+
+ if (i>=X86_REG_BASE && i<X86_REG_BASE + 8) return x86_regs[i - X86_REG_BASE];
+ switch (i) {
+ case 0:
+ return "UNALLOCATED";
+ case 1:
+ return "direct";
+ default:
+ return "ERROR";
+ }
+}
+
void oj_program_rewrite_vars (OJProgram *program);
void oj_program_allocate_regs (OJProgram *program);
@@ -134,6 +168,11 @@ oj_program_compile_x86 (OJProgram *program)
OJInstruction *insn;
OJOpcode *opcode;
OJVariable *args[10];
+ OJRuleList *list;
+ OJRule *rule;
+
+ list = oj_rule_list_new();
+ oj_program_x86_register_rules (list);
oj_program_rewrite_vars (program);
oj_program_dump (program);
@@ -141,11 +180,14 @@ oj_program_compile_x86 (OJProgram *program)
printf("# n_insns %d\n", program->n_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;j<program->n_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;k<opcode->n_src + opcode->n_dest;k++){
+ for(k=0;k<opcode->n_src + opcode->n_dest;k++){
args[k] = program->vars + insn->args[k];
+ }
+ for(k=opcode->n_dest;k<opcode->n_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;k<opcode->n_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;k<program->n_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;i<program->n_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;j<program->n_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;k<opcode->n_dest;k++){
@@ -379,13 +456,12 @@ oj_program_rewrite_vars (OJProgram *program)
}
}
-#if 0
for(j=0;j<program->n_insns;j++){
- for(i=0;i<program->n_regs;i++){
- if (program->regs[i].first_use == j) {
+ for(i=0;i<program->n_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;i<program->n_regs;i++){
- if (program->regs[i].last_use == j) {
- alloc[program->regs[i].alloc] = 0;
+ for(i=0;i<program->n_vars;i++){
+ if (program->vars[i].last_use == j) {
+ alloc[program->vars[i].alloc - X86_REG_BASE] = 0;
}
}
}
- for(i=0;i<program->n_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;i<program->n_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;i<rule_list->n_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