summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Schleef <ds@ginger.bigkitten.com>2008-05-14 21:40:23 -0700
committerDavid Schleef <ds@ginger.bigkitten.com>2008-05-14 21:40:23 -0700
commit6971030867c9aae22531dd39ecf6ba9d862e4818 (patch)
treebc0c6e2411f4609f27230560e80b0465b4ba2745
parent497b00cade96e3d5e247f6e74bd171152a9e86b4 (diff)
downloadliboil-6971030867c9aae22531dd39ecf6ba9d862e4818.tar.gz
more jit hacking. compiler creates runnable code
-rw-r--r--examples/jit/jit.c8
-rw-r--r--examples/jit/ojprogram-x86.c694
-rw-r--r--examples/jit/ojprogram.h26
3 files changed, 466 insertions, 262 deletions
diff --git a/examples/jit/jit.c b/examples/jit/jit.c
index bbb1152..44fdddc 100644
--- a/examples/jit/jit.c
+++ b/examples/jit/jit.c
@@ -48,24 +48,24 @@ main (int argc, char *argv[])
oj_program_compile_x86 (p);
-#if 0
if (1) {
int i;
+ void (*func) (OJExecutor *);
for(i=0;i<N;i++){
src1[i] = rand()&0xf;
src2[i] = rand()&0xf;
}
- test (ex);
+ func = p->code_exec;
+ func (ex);
//oj_executor_emulate (ex);
for(i=0;i<N;i++){
- printf(" %4d %4d %4d %4d\n", src1[i], src2[i], dest[i],
+ printf("# %4d %4d %4d %4d\n", src1[i], src2[i], dest[i],
(src1[i] + src2[i] + 1)>>1);
}
}
-#endif
return 0;
}
diff --git a/examples/jit/ojprogram-x86.c b/examples/jit/ojprogram-x86.c
index de23aca..1da8694 100644
--- a/examples/jit/ojprogram-x86.c
+++ b/examples/jit/ojprogram-x86.c
@@ -6,121 +6,45 @@
#include <string.h>
#include <stdlib.h>
-#include "ojprogram.h"
-
-
-#if 0
-void
-emit (unsigned int x)
-{
- g_print ("%02x ", x);
-}
-
-void
-emit_modrm (OJArgument *reg, OJArgument *regmem)
-{
- int bits_mod;
- int bits_rm;
- int bits_reg;
-
- if (regmem->is_indirect) {
- if (regmem->offset == 0) {
- bits_mod = 0;
- bits_rm = regmem->index;
- bits_reg = reg->index;
- emit ((bits_reg << 5) | (bits_mod << 3) | (bits_rm));
- } else {
- if (regmem->offset <= 127 && regmem->offset >= -128) {
- bits_mod = 1;
- bits_rm = regmem->index;
- bits_reg = reg->index;
- emit ((bits_reg << 5) | (bits_mod << 3) | (bits_rm));
- emit (regmem->offset);
- } else {
- bits_mod = 2;
- bits_rm = regmem->index;
- bits_reg = reg->index;
- emit ((bits_reg << 5) | (bits_mod << 3) | (bits_rm));
- emit ((regmem->offset>>0) & 0xff);
- emit ((regmem->offset>>8) & 0xff);
- emit ((regmem->offset>>16) & 0xff);
- emit ((regmem->offset>>24) & 0xff);
- }
- }
- } else {
- bits_mod = 3;
- bits_rm = regmem->index;
- bits_reg = reg->index;
- emit ((bits_reg << 5) | (bits_mod << 3) | (bits_rm));
- }
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/mman.h>
-}
-
-void
-oj_program_output_mmx (OJProgram *program)
-{
- int i;
- char *dest_regs[] = { "error", "eax", "error", "error" };
- char *src_regs[] = { "error", "ecx", "edx", "error" };
- char *r_regs[] = { "mm0", "mm1", "mm2", "mm3" };
- OJInstruction *insn;
-
- g_print(" push %%ebp\n");
- g_print(" movl %%esp, %%ebp\n");
- g_print(" movl 0x8(%%ebp), %%%s\n", dest_regs[1]);
- g_print(" movl 0xc(%%ebp), %%%s\n", src_regs[1]);
- g_print(" movl 0x10(%%ebp), %%%s\n", src_regs[2]);
-
- for(i=0;i<program->n_insns;i++){
- insn = program->insns + i;
- switch (insn->opcode) {
- case 0:
- g_print (" movq %d(%%%s), %%%s\n",
- insn->args[1].offset,
- src_regs[insn->args[1].index],
- r_regs[insn->args[0].index]);
- emit (0x0f);
- emit (0x6f);
- emit_modrm (insn->args + 0, insn->args + 1);
- g_print ("\n");
- break;
- case 1:
- g_print (" movq %%%s, %d(%%%s)\n",
- r_regs[insn->args[1].index],
- insn->args[0].offset,
- dest_regs[insn->args[0].index]);
- emit (0x0f);
- emit (0x7f);
- emit_modrm (insn->args + 1, insn->args + 0);
- g_print ("\n");
- break;
- case 2:
- g_print (" movq %%%s, %%%s\n",
- r_regs[insn->args[2].index],
- r_regs[insn->args[0].index]);
- emit (0x0f);
- emit (0x6f);
- emit_modrm (insn->args + 0, insn->args + 1);
- g_print ("\n");
- g_print (" paddw %%%s, %%%s\n",
- r_regs[insn->args[1].index],
- r_regs[insn->args[0].index]);
- emit (0x0f);
- emit (0xfd);
- emit_modrm (insn->args + 0, insn->args + 1);
- g_print ("\n");
- break;
- }
- }
+#include "ojprogram.h"
- g_print(" emms\n");
- g_print(" pop %%ebp\n");
- g_print(" ret\n");
-}
-#endif
#define X86_REG_BASE 8
+void x86_emit_push (OJProgram *program, int size, int reg);
+void x86_emit_pop (OJProgram *program, int size, int reg);
+void x86_emit_mov_memoffset_reg (OJProgram *program, int size, int offset, int reg1, int reg2);
+void x86_emit_mov_reg_memoffset (OJProgram *program, int size, int reg1, int offset, int reg2);
+void x86_emit_mov_imm_reg (OJProgram *program, int size, int value, int reg1);
+void x86_emit_mov_reg_reg (OJProgram *program, int size, int reg1, int reg2);
+void x86_emit_test_reg_reg (OJProgram *program, int size, int reg1, int reg2);
+void x86_emit_dec_memoffset (OJProgram *program, int size, int offset, int reg);
+void x86_emit_add_imm_memoffset (OJProgram *program, int size, int value, int offset, int reg);
+void x86_emit_ret (OJProgram *program);
+void x86_emit_je (OJProgram *program, int label);
+void x86_emit_jne (OJProgram *program, int label);
+void x86_emit_label (OJProgram *program, int label);
+
+void x86_emit_modrm_memoffset (OJProgram *program, int reg1, int offset, int reg2);
+void x86_emit_modrm_reg (OJProgram *program, int reg1, int reg2);
+
+void oj_program_dump_code (OJProgram *program);
+
+enum {
+ X86_EAX = X86_REG_BASE,
+ X86_ECX,
+ X86_EDX,
+ X86_EBX,
+ X86_ESP,
+ X86_EBP,
+ X86_ESI,
+ X86_EDI
+};
+
static const char *
x86_get_regname(int i)
{
@@ -138,6 +62,12 @@ x86_get_regname(int i)
}
}
+static int
+x86_get_regnum(int i)
+{
+ return i - X86_REG_BASE;
+}
+
static const char *
x86_get_regname_16(int i)
{
@@ -171,24 +101,37 @@ oj_program_compile_x86 (OJProgram *program)
OJRuleList *list;
OJRule *rule;
+ oj_program_allocate_codemem (program);
+
list = oj_rule_list_new();
oj_program_x86_register_rules (list);
oj_program_rewrite_vars (program);
- oj_program_dump (program);
+ //oj_program_dump (program);
+ printf(".global test\n");
+ printf("test:\n");
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(" je 2f\n");
- g_print("1:\n");
+ x86_emit_push (program, 4, X86_EBP);
+ x86_emit_mov_memoffset_reg (program, 4, 8, X86_ESP, X86_EBP);
+ x86_emit_push (program, 4, X86_EDI);
+ x86_emit_push (program, 4, X86_ESI);
+ x86_emit_push (program, 4, X86_EBX);
+
+ //g_print(" movl 0x%02x(%%ebp), %%ecx\n", (int)G_STRUCT_OFFSET(OJExecutor,n));
+ x86_emit_mov_memoffset_reg (program, 4, (int)G_STRUCT_OFFSET(OJExecutor,n),
+ X86_EBP, X86_ECX);
+
+ //g_print(" movl %%ecx, 0x%02x(%%ebp)\n", (int)G_STRUCT_OFFSET(OJExecutor,counter));
+ x86_emit_mov_reg_memoffset (program, 4, X86_ECX,
+ (int)G_STRUCT_OFFSET(OJExecutor,counter), X86_EBP);
+
+ //g_print(" testl %%ecx, %%ecx\n");
+ x86_emit_test_reg_reg (program, 4, X86_ECX, X86_ECX);
+
+ //g_print(" je 2f\n");
+ x86_emit_je (program, 1);
+ x86_emit_label (program, 0);
for(j=0;j<program->n_insns;j++){
insn = program->insns + j;
@@ -204,14 +147,19 @@ oj_program_compile_x86 (OJProgram *program)
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), %%ecx\n",
- (int)G_STRUCT_OFFSET(OJExecutor, arrays[k]));
- g_print(" movw 0(%%ecx), %%%s\n",
- x86_get_regname_16(args[k]->alloc));
+ //g_print(" movl 0x%02x(%%ebp), %%ecx\n",
+ // (int)G_STRUCT_OFFSET(OJExecutor, arrays[k]));
+ x86_emit_mov_memoffset_reg (program, 4,
+ (int)G_STRUCT_OFFSET(OJExecutor, arrays[k]),
+ X86_EBP, X86_ECX);
+ //g_print(" movw 0(%%ecx), %%%s\n",
+ // x86_get_regname_16(args[k]->alloc));
+ x86_emit_mov_memoffset_reg (program, 2, 0, X86_ECX, args[k]->alloc);
break;
case OJ_VAR_TYPE_CONST:
- g_print(" movl $%d, %%%s\n", args[k]->s16,
- x86_get_regname(args[k]->alloc));
+ //g_print(" movl $%d, %%%s\n", args[k]->s16,
+ // x86_get_regname(args[k]->alloc));
+ x86_emit_mov_imm_reg (program, 2, args[k]->s16, args[k]->alloc);
break;
case OJ_VAR_TYPE_TEMP:
#if 0
@@ -228,9 +176,10 @@ oj_program_compile_x86 (OJProgram *program)
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));
+ //g_print (" movw %%%s, %%%s\n",
+ // x86_get_regname_16(args[1]->alloc),
+ // x86_get_regname_16(args[0]->alloc));
+ x86_emit_mov_reg_reg (program, 2, args[1]->alloc, args[0]->alloc);
}
rule->emit (program, rule->emit_user, insn);
} else {
@@ -240,10 +189,14 @@ oj_program_compile_x86 (OJProgram *program)
for(k=0;k<opcode->n_dest;k++){
switch (args[k]->vartype) {
case OJ_VAR_TYPE_DEST:
- g_print(" movl 0x%02x(%%ebp), %%ecx\n",
- (int)G_STRUCT_OFFSET(OJExecutor, arrays[k]));
- g_print(" movw %%%s, 0(%%ecx)\n",
- x86_get_regname_16(args[k]->alloc));
+ //g_print(" movl 0x%02x(%%ebp), %%ecx\n",
+ // (int)G_STRUCT_OFFSET(OJExecutor, arrays[k]));
+ x86_emit_mov_memoffset_reg (program, 4,
+ (int)G_STRUCT_OFFSET(OJExecutor, arrays[k]),
+ X86_EBP, X86_ECX);
+ //g_print(" movw %%%s, 0(%%ecx)\n",
+ // x86_get_regname_16(args[k]->alloc));
+ x86_emit_mov_reg_memoffset (program, 2, args[k]->alloc, 0, X86_ECX);
break;
case OJ_VAR_TYPE_TEMP:
#if 0
@@ -260,122 +213,40 @@ 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(" addl $2, 0x%02x(%%ebp)\n",
+ // (int)G_STRUCT_OFFSET(OJExecutor, arrays[k]));
+ x86_emit_add_imm_memoffset (program, 4, 2,
+ (int)G_STRUCT_OFFSET(OJExecutor, arrays[k]),
+ X86_EBP);
}
}
- 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)
-{
- int i;
-
- for(i=0;i<program->n_regs;i++) {
- if (program->regs[i].var == var && !program->regs[i].retired) {
- program->regs[i].last_use = insn;
- return i;
- }
- }
-
- program->regs[i].var = var;
- program->regs[i].first_use = insn;
- program->regs[i].last_use = insn;
-
- program->n_regs++;
-
- return i;
-}
-
-static void
-oj_program_retire_reg (OJProgram *program, int var)
-{
- int i;
-
- for(i=0;i<program->n_regs;i++) {
- if (program->regs[i].var == var && !program->regs[i].retired) {
- program->regs[i].retired = TRUE;
- return;
- }
- }
-}
-#endif
-
-#if 0
-void
-oj_program_allocate_regs (OJProgram *program)
-{
- int i;
- int j;
- int k;
- OJInstruction *insn;
- OJOpcode *opcode;
- OJVariable *args[10];
- int alloc[8] = { 0, 0, 0, 0, 1, 1, 1, 0 };
-
- for(j=0;j<program->n_insns;j++){
- insn = program->insns + j;
- opcode = insn->opcode;
-
- /* set up args */
- for(k=opcode->n_dest;k<opcode->n_src + opcode->n_dest;k++){
- args[k] = program->vars + insn->args[k];
-
- oj_program_get_reg (program, j, insn->args[k]);
- }
-
- for(k=0;k<opcode->n_dest;k++){
- args[k] = program->vars + insn->args[k];
-
- oj_program_retire_reg (program, insn->args[k]);
- oj_program_get_reg (program, j, insn->args[k]);
- }
- }
-
- for(j=0;j<program->n_insns;j++){
- for(i=0;i<program->n_regs;i++){
- if (program->regs[i].first_use == j) {
- for(k=0;k<8;k++){
- if (!alloc[k]) {
- program->regs[i].alloc = X86_REG_BASE + k;
- alloc[k] = 1;
- break;
- }
- }
- if (k==8) {
- g_print("register overflow\n");
- }
+ //g_print(" decl 0x%02x(%%ebp)\n", (int)G_STRUCT_OFFSET(OJExecutor,counter));
+ x86_emit_dec_memoffset (program, 4, (int)G_STRUCT_OFFSET(OJExecutor,counter),
+ X86_EBP);
+ //g_print(" jne 1b\n");
+ x86_emit_jne (program, 0);
+ x86_emit_label (program, 1);
+
+ x86_emit_pop (program, 4, X86_EBX);
+ x86_emit_pop (program, 4, X86_ESI);
+ x86_emit_pop (program, 4, X86_EDI);
+ x86_emit_pop (program, 4, X86_EBP);
+ x86_emit_ret (program);
+
+ {
+ int i;
+ for(i=0;i<program->n_fixups;i++){
+ if (program->fixups[i].type == 0) {
+ unsigned char *label = program->labels[program->fixups[i].label];
+ unsigned char *ptr = program->fixups[i].ptr;
+
+ ptr[0] += label - ptr;
}
}
- for(i=0;i<program->n_regs;i++){
- if (program->regs[i].last_use == j) {
- alloc[program->regs[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_get_regname(program->regs[i].alloc));
}
+ oj_program_dump_code (program);
}
-#endif
void
@@ -478,6 +349,7 @@ oj_program_rewrite_vars (OJProgram *program)
}
}
+#if 0
for(i=0;i<program->n_vars;i++){
g_print("%2d: %2d %2d %s\n",
i,
@@ -485,6 +357,7 @@ oj_program_rewrite_vars (OJProgram *program)
program->vars[i].last_use,
x86_get_regname(program->vars[i].alloc));
}
+#endif
}
@@ -534,6 +407,12 @@ 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));
+
+ *p->codeptr++ = 0x66;
+ *p->codeptr++ = 0x01;
+ x86_emit_modrm_reg (p, p->vars[insn->args[0]].alloc,
+ p->vars[insn->args[2]].alloc);
+
}
static void
@@ -542,6 +421,11 @@ 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));
+
+ *p->codeptr++ = 0x66;
+ *p->codeptr++ = 0x29;
+ x86_emit_modrm_reg (p, p->vars[insn->args[0]].alloc,
+ p->vars[insn->args[2]].alloc);
}
static void
@@ -550,23 +434,38 @@ 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));
+
+ *p->codeptr++ = 0x66;
+ *p->codeptr++ = 0x0f;
+ *p->codeptr++ = 0xaf;
+ x86_emit_modrm_reg (p, p->vars[insn->args[0]].alloc,
+ p->vars[insn->args[2]].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_emit_mov_reg_reg(p, 4, p->vars[insn->args[2]].alloc, X86_ECX);
+
+ g_print(" shlw %%cl, %%%s\n",
x86_get_regname_16(p->vars[insn->args[0]].alloc));
+
+ *p->codeptr++ = 0x66;
+ *p->codeptr++ = 0xd3;
+ x86_emit_modrm_reg (p, p->vars[insn->args[0]].alloc, 4);
}
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));
+ x86_emit_mov_reg_reg(p, 4, p->vars[insn->args[2]].alloc, X86_ECX);
+
g_print(" sarw %%cl, %%%s\n",
x86_get_regname_16(p->vars[insn->args[0]].alloc));
+
+ *p->codeptr++ = 0x66;
+ *p->codeptr++ = 0xd3;
+ x86_emit_modrm_reg (p, p->vars[insn->args[0]].alloc, 7);
}
@@ -586,3 +485,302 @@ oj_program_x86_register_rules (OJRuleList *list)
}
+void
+oj_program_allocate_codemem (OJProgram *program)
+{
+ char *filename;
+ int fd;
+ GError *error = NULL;
+
+ fd = g_file_open_tmp ("liboilexecXXXXXX", &filename, &error);
+ if (fd == -1) {
+ /* FIXME oh crap */
+ g_print("failed to create temp file\n");
+ return;
+ }
+ unlink (filename);
+ g_free (filename);
+
+ ftruncate (fd, 4096);
+
+ program->code = mmap (NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (program->code == MAP_FAILED) {
+ /* FIXME oh crap */
+ g_print("failed to create write map\n");
+ return;
+ }
+ program->code_exec = mmap (NULL, 4096, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0);
+ if (program->code_exec == MAP_FAILED) {
+ /* FIXME oh crap */
+ g_print("failed to create exec map\n");
+ return;
+ }
+
+ close (fd);
+
+ program->codeptr = program->code;
+}
+
+
+/* code generation */
+
+void
+oj_program_dump_code (OJProgram *program)
+{
+ //unsigned char *ptr;
+ FILE *file;
+
+ file = fopen("dump","w");
+
+ fwrite (program->code, 1, program->codeptr - program->code, file);
+ fclose (file);
+
+#if 0
+ ptr = program->code;
+ while(ptr < program->codeptr) {
+ g_print("# %02x\n", ptr[0]);
+ ptr++;
+ }
+#endif
+}
+
+void
+x86_emit_push (OJProgram *program, int size, int reg)
+{
+
+ if (size == 1) {
+ program->error = 1;
+ } else if (size == 2) {
+ g_print(" pushw %%%s\n", x86_get_regname_16(reg));
+ *program->codeptr++ = 0x66;
+ *program->codeptr++ = 0x50 + x86_get_regnum(reg);
+ } else {
+ g_print(" pushl %%%s\n", x86_get_regname(reg));
+ *program->codeptr++ = 0x50 + x86_get_regnum(reg);
+ }
+}
+
+void
+x86_emit_pop (OJProgram *program, int size, int reg)
+{
+
+ if (size == 1) {
+ program->error = 1;
+ } else if (size == 2) {
+ g_print(" popw %%%s\n", x86_get_regname_16(reg));
+ *program->codeptr++ = 0x66;
+ *program->codeptr++ = 0x58 + x86_get_regnum(reg);
+ } else {
+ g_print(" popl %%%s\n", x86_get_regname(reg));
+ *program->codeptr++ = 0x58 + x86_get_regnum(reg);
+ }
+}
+
+#define X86_MODRM(mod, rm, reg) ((((mod)&3)<<6)|(((rm)&7)<<0)|(((reg)&7)<<3))
+#define X86_SIB(ss, ind, reg) ((((ss)&3)<<6)|(((ind)&7)<<3)|((reg)&7))
+
+void
+x86_emit_modrm_memoffset (OJProgram *program, int reg1, int offset, int reg2)
+{
+ if (offset == 0 && reg2 != X86_EBP) {
+ if (reg2 == X86_ESP) {
+ *program->codeptr++ = X86_MODRM(1, 4, reg1);
+ *program->codeptr++ = X86_SIB(0, 4, reg2);
+ } else {
+ *program->codeptr++ = X86_MODRM(0, reg2, reg1);
+ }
+ } else if (offset >= -128 && offset < 128) {
+ *program->codeptr++ = X86_MODRM(1, reg2, reg1);
+ if (reg2 == X86_ESP) {
+ *program->codeptr++ = X86_SIB(0, 4, reg2);
+ }
+ *program->codeptr++ = (offset & 0xff);
+ } else {
+ *program->codeptr++ = X86_MODRM(1, reg2, reg1);
+ if (reg2 == X86_ESP) {
+ *program->codeptr++ = X86_SIB(0, 4, reg2);
+ }
+ *program->codeptr++ = (offset & 0xff);
+ *program->codeptr++ = ((offset>>8) & 0xff);
+ *program->codeptr++ = ((offset>>16) & 0xff);
+ *program->codeptr++ = ((offset>>24) & 0xff);
+ }
+}
+
+void
+x86_emit_modrm_reg (OJProgram *program, int reg1, int reg2)
+{
+ *program->codeptr++ = X86_MODRM(3, reg1, reg2);
+}
+
+void
+x86_emit_mov_memoffset_reg (OJProgram *program, int size, int offset,
+ int reg1, int reg2)
+{
+ if (size == 2) {
+ g_print(" movw %d(%%%s), %%%s\n", offset, x86_get_regname(reg1),
+ x86_get_regname_16(reg2));
+ *program->codeptr++ = 0x66;
+ } else {
+ g_print(" movl %d(%%%s), %%%s\n", offset, x86_get_regname(reg1),
+ x86_get_regname(reg2));
+ }
+
+ *program->codeptr++ = 0x8b;
+ x86_emit_modrm_memoffset (program, reg2, offset, reg1);
+}
+
+void
+x86_emit_mov_reg_memoffset (OJProgram *program, int size, int reg1, int offset,
+ int reg2)
+{
+ if (size == 2) {
+ g_print(" movw %%%s, %d(%%%s)\n", x86_get_regname_16(reg1), offset,
+ x86_get_regname(reg2));
+ *program->codeptr++ = 0x66;
+ } else {
+ g_print(" movl %%%s, %d(%%%s)\n", x86_get_regname(reg1), offset,
+ x86_get_regname(reg2));
+ }
+
+ *program->codeptr++ = 0x89;
+ x86_emit_modrm_memoffset (program, reg1, offset, reg2);
+}
+
+void
+x86_emit_mov_imm_reg (OJProgram *program, int size, int value, int reg1)
+{
+ if (size == 2) {
+ g_print(" movw $%d, %%%s\n", value, x86_get_regname_16(reg1));
+ *program->codeptr++ = 0x66;
+ *program->codeptr++ = 0xb8 + x86_get_regnum(reg1);
+ *program->codeptr++ = (value & 0xff);
+ *program->codeptr++ = ((value>>8) & 0xff);
+ } else {
+ g_print(" movl $%d, %%%s\n", value, x86_get_regname(reg1));
+ *program->codeptr++ = 0xb8;
+ *program->codeptr++ = (value & 0xff);
+ *program->codeptr++ = ((value>>8) & 0xff);
+ *program->codeptr++ = ((value>>16) & 0xff);
+ *program->codeptr++ = ((value>>24) & 0xff);
+ }
+
+}
+
+void x86_emit_mov_reg_reg (OJProgram *program, int size, int reg1, int reg2)
+{
+ if (size == 2) {
+ g_print(" movw %%%s, %%%s\n", x86_get_regname_16(reg1),
+ x86_get_regname_16(reg2));
+ *program->codeptr++ = 0x66;
+ } else {
+ g_print(" movl %%%s, %%%s\n", x86_get_regname(reg1),
+ x86_get_regname(reg2));
+ }
+
+ *program->codeptr++ = 0x89;
+ x86_emit_modrm_reg (program, reg2, reg1);
+}
+
+
+void
+x86_emit_test_reg_reg (OJProgram *program, int size, int reg1, int reg2)
+{
+ if (size == 2) {
+ g_print(" testw %%%s, %%%s\n", x86_get_regname_16(reg1),
+ x86_get_regname_16(reg2));
+ *program->codeptr++ = 0x66;
+ } else {
+ g_print(" testl %%%s, %%%s\n", x86_get_regname(reg1),
+ x86_get_regname(reg2));
+ }
+
+ *program->codeptr++ = 0x85;
+ x86_emit_modrm_reg (program, reg2, reg1);
+}
+
+void
+x86_emit_add_imm_memoffset (OJProgram *program, int size, int value,
+ int offset, int reg)
+{
+ if (size == 2) {
+ g_print(" addw $%d, %d(%%%s)\n", value, offset,
+ x86_get_regname(reg));
+ *program->codeptr++ = 0x66;
+ } else {
+ g_print(" addl $%d, %d(%%%s)\n", value, offset,
+ x86_get_regname(reg));
+ }
+
+ if (value >= -128 && value < 128) {
+ *program->codeptr++ = 0x83;
+ x86_emit_modrm_memoffset (program, 0, offset, reg);
+ *program->codeptr++ = (value & 0xff);
+ } else {
+ *program->codeptr++ = 0x81;
+ x86_emit_modrm_memoffset (program, 0, offset, reg);
+ *program->codeptr++ = (value & 0xff);
+ *program->codeptr++ = ((value>>8) & 0xff);
+ }
+}
+
+void
+x86_emit_dec_memoffset (OJProgram *program, int size,
+ int offset, int reg)
+{
+ if (size == 2) {
+ g_print(" decw %d(%%%s)\n", offset, x86_get_regname(reg));
+ *program->codeptr++ = 0x66;
+ } else {
+ g_print(" decl %d(%%%s)\n", offset, x86_get_regname(reg));
+ }
+
+ *program->codeptr++ = 0xff;
+ x86_emit_modrm_memoffset (program, 1, offset, reg);
+}
+
+void x86_emit_ret (OJProgram *program)
+{
+ g_print(" ret\n");
+ *program->codeptr++ = 0xc3;
+}
+
+void
+x86_add_fixup (OJProgram *program, unsigned char *ptr, int label)
+{
+ program->fixups[program->n_fixups].ptr = ptr;
+ program->fixups[program->n_fixups].label = label;
+ program->fixups[program->n_fixups].type = 0;
+ program->n_fixups++;
+}
+
+void
+x86_add_label (OJProgram *program, unsigned char *ptr, int label)
+{
+ program->labels[label] = ptr;
+}
+
+void x86_emit_je (OJProgram *program, int label)
+{
+ g_print(" je .L%d\n", label);
+
+ *program->codeptr++ = 0x74;
+ x86_add_fixup (program, program->codeptr, label);
+ *program->codeptr++ = -1;
+}
+
+void x86_emit_jne (OJProgram *program, int label)
+{
+ g_print(" jne .L%d\n", label);
+ *program->codeptr++ = 0x75;
+ x86_add_fixup (program, program->codeptr, label);
+ *program->codeptr++ = -1;
+}
+
+void x86_emit_label (OJProgram *program, int label)
+{
+ g_print(".L%d:\n", label);
+
+ x86_add_label (program, program->codeptr, label);
+}
+
diff --git a/examples/jit/ojprogram.h b/examples/jit/ojprogram.h
index dd41350..0dbf4eb 100644
--- a/examples/jit/ojprogram.h
+++ b/examples/jit/ojprogram.h
@@ -13,6 +13,7 @@ typedef struct _OJInstruction OJInstruction;
typedef struct _OJProgram OJProgram;
typedef struct _OJRule OJRule;
typedef struct _OJRuleList OJRuleList;
+typedef struct _OJFixup OJFixup;
typedef void (*OJOpcodeEmulateFunc)(OJExecutor *ex, void *user);
typedef void (*OJRuleEmitFunc)(OJProgram *p, void *user, OJInstruction *insn);
@@ -76,17 +77,11 @@ struct _OJInstruction {
OJRule *rule;
};
-#if 0
-struct _OJRegister {
- int var;
-
- int first_use;
- int last_use;
- int retired;
-
- int alloc;
+struct _OJFixup {
+ unsigned char *ptr;
+ int type;
+ int label;
};
-#endif
struct _OJProgram {
OJInstruction insns[100];
@@ -96,6 +91,16 @@ struct _OJProgram {
int n_vars;
OJInstruction *insn;
+
+ unsigned char *code;
+ void *code_exec;
+ unsigned char *codeptr;
+
+ OJFixup fixups[100];
+ int n_fixups;
+ unsigned char *labels[100];
+
+ int error;
};
struct _OJExecutor {
@@ -165,6 +170,7 @@ 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);
+void oj_program_allocate_codemem (OJProgram *program);
#endif