diff options
author | David Schleef <ds@ginger.bigkitten.com> | 2007-12-27 17:22:14 -0800 |
---|---|---|
committer | David Schleef <ds@ginger.bigkitten.com> | 2007-12-27 17:22:14 -0800 |
commit | d90d3298c4d01e68e6ee6902785acaa2b0089044 (patch) | |
tree | ea757df8dfaefab347751e6ad0ae33ddb90b26b5 /examples | |
parent | 3a6bcdb7221129b306f41bd4b421d28030b77614 (diff) |
Add some experimental JIT code
Diffstat (limited to 'examples')
-rw-r--r-- | examples/.gitignore | 1 | ||||
-rw-r--r-- | examples/jit/Makefile.am | 2 | ||||
-rw-r--r-- | examples/jit/jit.c | 345 | ||||
-rw-r--r-- | examples/jit/ojprogram-x86.c | 119 | ||||
-rw-r--r-- | examples/jit/ojprogram.c | 196 | ||||
-rw-r--r-- | examples/jit/ojprogram.h | 57 |
6 files changed, 376 insertions, 344 deletions
diff --git a/examples/.gitignore b/examples/.gitignore index 37a77f2..bd7dfea 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1,6 +1,7 @@ audioresample/test_functable1 example1 huffman/huffman_test +jit/jit jpeg/jpeg_rgb_test jpeg/jpeg_test md5/md5sum diff --git a/examples/jit/Makefile.am b/examples/jit/Makefile.am index 56b144b..3c7dd5b 100644 --- a/examples/jit/Makefile.am +++ b/examples/jit/Makefile.am @@ -6,3 +6,5 @@ noinst_PROGRAMS = jit AM_LDFLAGS = $(LIBOIL_LIBS) $(GLIB_LIBS) AM_CFLAGS = $(LIBOIL_CFLAGS) $(GLIB_CFLAGS) +jit_SOURCES = jit.c ojprogram.c ojprogram-x86.c + diff --git a/examples/jit/jit.c b/examples/jit/jit.c index be2bc9c..6debf54 100644 --- a/examples/jit/jit.c +++ b/examples/jit/jit.c @@ -6,350 +6,7 @@ #include <string.h> #include <stdlib.h> - -void -stuff (void *d, void *s1, void *s2) -{ - - __asm__ __volatile__ ( - " movq 0(%[s1]), %%mm0 \n" - " movq 0(%[s2]), %%mm1 \n" - " paddw %%mm1, %%mm0 \n" - " movq %%mm0, 0(%[d]) \n" - " emms \n" - : [d] "+r" (d), [s1] "+r" (s1), [s2] "+r" (s2)); -} - - -typedef struct _OJArgument { - int type; - int index; - int offset; -} OJArgument; - -typedef struct _OJInstruction { - int opcode; - - OJArgument args[3]; -} OJInstruction; - -typedef struct _OJRegister { - int type; - - int index; -}OJRegister; - -typedef struct _OJProgram { - OJInstruction insns[100]; - int n_insns; - - /* parsing state */ - char *s; - char *error; - - OJInstruction *insn; - -}OJProgram; - -typedef struct _OJOpcode { - char *name; - int n_args; -} OJOpcode; - - -const OJOpcode opcode_list[] = { - { "load", 2 }, - { "store", 2 }, - { "add", 3 } -}; -#define N_OPCODES 3 - -#define ARG_REG 0 -#define ARG_SRC 1 -#define ARG_DEST 2 - - -OJProgram * -oj_program_new (void) -{ - OJProgram *p; - p = g_malloc0(sizeof(OJProgram)); - return p; -} - -int -oj_opcode_lookup (const char *s, int len) -{ - int i; - for(i=0;i<N_OPCODES;i++){ - if (strlen (opcode_list[i].name) != len) continue; - if (strncmp (opcode_list[i].name, s, len) == 0) { - return i; - } - } - - return -1; -} - -static gboolean -get_opcode (OJProgram *p) -{ - char *s; - char *opcode; - int opcode_len; - int i; - - if (p->error) return FALSE; - - g_print("looking for opcode at \"%s\"\n", p->s); - - s = p->s; - while (g_ascii_isspace (s[0])) s++; - opcode = s; - while (g_ascii_isalnum (s[0])) s++; - opcode_len = s - opcode; - - if (opcode_len == 0) { - p->error = g_strdup ("expected opcode"); - return FALSE; - } - - p->insn->opcode = oj_opcode_lookup (opcode, opcode_len); - - for(i=0;i<N_OPCODES;i++){ - if (strlen (opcode_list[i].name) != opcode_len) continue; - if (strncmp (opcode_list[i].name, opcode, opcode_len) == 0) { - break; - } - } - if (i == N_OPCODES) { - p->error = g_strdup ("unknown opcode"); - return FALSE; - } - - p->insn->opcode = i; - p->s = s; - return TRUE; -} - -static gboolean -get_arg (OJProgram *p, int i) -{ - char *s; - char *end; - - if (p->error) return FALSE; - - g_print("looking for arg at \"%s\"\n", p->s); - - s = p->s; - while (g_ascii_isspace (s[0])) s++; - - switch (s[0]) { - case 'r': - p->insn->args[i].type = ARG_REG; - break; - case 's': - p->insn->args[i].type = ARG_SRC; - break; - case 'd': - p->insn->args[i].type = ARG_DEST; - break; - default: - p->s = s; - p->error = g_strdup ("expected argument"); - return FALSE; - } - s++; - - p->insn->args[i].index = strtoul (s, &end, 10); - if (s == end) { - p->s = s; - p->error = strdup ("expected number"); - return FALSE; - } - - s = end; - - p->s = s; - return TRUE; -} - -static gboolean -skip_comma (OJProgram *p) -{ - char *s; - - if (p->error) return FALSE; - - g_print("looking for comma at \"%s\"\n", p->s); - - s = p->s; - while (g_ascii_isspace (s[0])) s++; - if (s[0] != ',') { - p->error = g_strdup ("expected comma"); - return FALSE; - } - s++; - while (g_ascii_isspace (s[0])) s++; - - p->s = s; - return TRUE; -} - -void -oj_program_parse (OJProgram *p, const char *program) -{ - char **lines; - char *line; - char *s; - int i; - - lines = g_strsplit(program, "\n", 0); - - for(i=0;lines[i];i++){ - p->insn = p->insns + p->n_insns; - line = lines[i]; - - s = line; - - g_print("looking at \"%s\"\n", s); - - while (g_ascii_isspace (s[0])) s++; - if (s[0] == 0 || s[0] == '#') continue; - - p->s = s; - get_opcode (p); - - get_arg (p, 0); - if (opcode_list[p->insn->opcode].n_args >= 2) { - skip_comma (p); - get_arg (p, 1); - if (opcode_list[p->insn->opcode].n_args >= 3) { - skip_comma (p); - get_arg (p, 2); - } - } - - if (p->error) { - g_print("error on line %d: %s at \"%s\"\n", i, p->error, p->s); - g_free(p->error); - p->error = NULL; - } - - p->n_insns++; - } - g_strfreev (lines); -} - -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->type != ARG_REG) { - 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)); - } - -} - -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; - } - } - - g_print(" emms\n"); - g_print(" pop %%ebp\n"); - g_print(" ret\n"); -} - +#include "ojprogram.h" const char *program = "load r0, s1\n" diff --git a/examples/jit/ojprogram-x86.c b/examples/jit/ojprogram-x86.c new file mode 100644 index 0000000..64083d6 --- /dev/null +++ b/examples/jit/ojprogram-x86.c @@ -0,0 +1,119 @@ + +#include "config.h" + +#include <glib.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "ojprogram.h" + + +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)); + } + +} + +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; + } + } + + g_print(" emms\n"); + g_print(" pop %%ebp\n"); + g_print(" ret\n"); +} + diff --git a/examples/jit/ojprogram.c b/examples/jit/ojprogram.c new file mode 100644 index 0000000..aac03c8 --- /dev/null +++ b/examples/jit/ojprogram.c @@ -0,0 +1,196 @@ + +#include "config.h" + +#include <glib.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "ojprogram.h" + + +const OJOpcode opcode_list[] = { + { "load", 2 }, + { "store", 2 }, + { "add", 3 } +}; +#define N_OPCODES 3 + +#define ARG_REG 0 +#define ARG_SRC 1 +#define ARG_DEST 2 + + +OJProgram * +oj_program_new (void) +{ + OJProgram *p; + p = g_malloc0(sizeof(OJProgram)); + return p; +} + +int +oj_opcode_lookup (const char *s, int len) +{ + int i; + for(i=0;i<N_OPCODES;i++){ + if (strlen (opcode_list[i].name) != len) continue; + if (strncmp (opcode_list[i].name, s, len) == 0) { + return i; + } + } + + return -1; +} + +static gboolean +get_opcode (OJProgram *p) +{ + char *s; + char *opcode; + int opcode_len; + int i; + + if (p->error) return FALSE; + + g_print("looking for opcode at \"%s\"\n", p->s); + + s = p->s; + while (g_ascii_isspace (s[0])) s++; + opcode = s; + while (g_ascii_isalnum (s[0])) s++; + opcode_len = s - opcode; + + if (opcode_len == 0) { + p->error = g_strdup ("expected opcode"); + return FALSE; + } + + p->insn->opcode = oj_opcode_lookup (opcode, opcode_len); + + for(i=0;i<N_OPCODES;i++){ + if (strlen (opcode_list[i].name) != opcode_len) continue; + if (strncmp (opcode_list[i].name, opcode, opcode_len) == 0) { + break; + } + } + if (i == N_OPCODES) { + p->error = g_strdup ("unknown opcode"); + return FALSE; + } + + p->insn->opcode = i; + p->s = s; + return TRUE; +} + +static gboolean +get_arg (OJProgram *p, int i) +{ + char *s; + char *end; + + if (p->error) return FALSE; + + g_print("looking for arg at \"%s\"\n", p->s); + + s = p->s; + while (g_ascii_isspace (s[0])) s++; + + switch (s[0]) { + case 'r': + p->insn->args[i].type = ARG_REG; + break; + case 's': + p->insn->args[i].type = ARG_SRC; + break; + case 'd': + p->insn->args[i].type = ARG_DEST; + break; + default: + p->s = s; + p->error = g_strdup ("expected argument"); + return FALSE; + } + s++; + + p->insn->args[i].index = strtoul (s, &end, 10); + if (s == end) { + p->s = s; + p->error = strdup ("expected number"); + return FALSE; + } + + s = end; + + p->s = s; + return TRUE; +} + +static gboolean +skip_comma (OJProgram *p) +{ + char *s; + + if (p->error) return FALSE; + + g_print("looking for comma at \"%s\"\n", p->s); + + s = p->s; + while (g_ascii_isspace (s[0])) s++; + if (s[0] != ',') { + p->error = g_strdup ("expected comma"); + return FALSE; + } + s++; + while (g_ascii_isspace (s[0])) s++; + + p->s = s; + return TRUE; +} + +void +oj_program_parse (OJProgram *p, const char *program) +{ + char **lines; + char *line; + char *s; + int i; + + lines = g_strsplit(program, "\n", 0); + + for(i=0;lines[i];i++){ + p->insn = p->insns + p->n_insns; + line = lines[i]; + + s = line; + + g_print("looking at \"%s\"\n", s); + + while (g_ascii_isspace (s[0])) s++; + if (s[0] == 0 || s[0] == '#') continue; + + p->s = s; + get_opcode (p); + + get_arg (p, 0); + if (opcode_list[p->insn->opcode].n_args >= 2) { + skip_comma (p); + get_arg (p, 1); + if (opcode_list[p->insn->opcode].n_args >= 3) { + skip_comma (p); + get_arg (p, 2); + } + } + + if (p->error) { + g_print("error on line %d: %s at \"%s\"\n", i, p->error, p->s); + g_free(p->error); + p->error = NULL; + } + + p->n_insns++; + } + g_strfreev (lines); +} + diff --git a/examples/jit/ojprogram.h b/examples/jit/ojprogram.h new file mode 100644 index 0000000..db87814 --- /dev/null +++ b/examples/jit/ojprogram.h @@ -0,0 +1,57 @@ + +#ifndef _OJ_PROGRAM_H_ +#define _OJ_PROGRAM_H_ + +#include <glib.h> + + +typedef struct _OJVariable { + char *name; +} OJVariable; + +typedef struct _OJArgument { + OJVariable *var; + int is_indirect; + int is_indexed; + OJVariable *index_var; + int index_scale; + int type; // remove + int index; // remove + int offset; +} OJArgument; + +typedef struct _OJInstruction { + int opcode; + + OJArgument args[3]; +} OJInstruction; + +typedef struct _OJProgram { + OJInstruction insns[100]; + int n_insns; + + OJVariable vars[100]; + int n_vars; + + /* parsing state */ + char *s; + char *error; + + OJInstruction *insn; + +}OJProgram; + +typedef struct _OJOpcode { + char *name; + int n_args; +} OJOpcode; + + +OJProgram * oj_program_new (void); +int oj_opcode_lookup (const char *s, int len); +void oj_program_parse (OJProgram *p, const char *program); +void oj_program_output_mmx (OJProgram *p); +void oj_program_free (OJProgram *program); + +#endif + |