[Liboil-commit] orc/orcopcodes.c orc/orcprogram-x86.c orc/orcprogram.c orc/orcprogram.h orc/orcrule.c

David Schleef ds at kemper.freedesktop.org
Tue May 20 12:35:53 PDT 2008


 orc/orcopcodes.c     |    8 ++
 orc/orcprogram-x86.c |  169 +++++++++++++++++++++++++++++++++++++++++++++------
 orc/orcprogram.c     |   13 +++
 orc/orcprogram.h     |   49 +++++++-------
 orc/orcrule.c        |   52 +--------------
 5 files changed, 201 insertions(+), 90 deletions(-)

New commits:
commit b1b8fdccc0981ef32a17030d19d3d153509c20db
Author: David Schleef <ds at ginger.bigkitten.com>
Date:   Tue May 20 12:35:14 2008 -0700

    [orc] rewrite register handling, add mmx rules

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;
-}
-
-


More information about the Liboil-commit mailing list