summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Schleef <ds@ginger.bigkitten.com>2008-05-20 12:35:14 -0700
committerDavid Schleef <ds@ginger.bigkitten.com>2008-05-20 12:35:14 -0700
commitb1b8fdccc0981ef32a17030d19d3d153509c20db (patch)
tree236b810067d8b8fc4ba89b0c6e98c88f73a0afac
parentf35e4adb51a0347ca28c766e9b62d4600882ab23 (diff)
downloadliboil-b1b8fdccc0981ef32a17030d19d3d153509c20db.tar.gz
[orc] rewrite register handling, add mmx rules
-rw-r--r--orc/orcopcodes.c8
-rw-r--r--orc/orcprogram-x86.c169
-rw-r--r--orc/orcprogram.c13
-rw-r--r--orc/orcprogram.h49
-rw-r--r--orc/orcrule.c52
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;
-}
-
-