[Liboil-commit] orc/Makefile.am orc/orc.c orc/orcprogram-powerpc.c orc/orcprogram-x86.c orc/orcprogram.c orc/orcprogram.h

David Schleef ds at kemper.freedesktop.org
Wed May 21 00:25:10 PDT 2008


 orc/Makefile.am          |    1 
 orc/orc.c                |    1 
 orc/orcprogram-powerpc.c |  784 +++++++++++++++++++++++++++++++++++++++++++++++
 orc/orcprogram-x86.c     |   31 +
 orc/orcprogram.c         |   34 --
 orc/orcprogram.h         |   12 
 6 files changed, 834 insertions(+), 29 deletions(-)

New commits:
commit b0cbfea4324309b3b14f66b562087f0b79f61edd
Author: David Schleef <ds at ginger.bigkitten.com>
Date:   Wed May 21 00:24:52 2008 -0700

    [orc] add beginnings of powerpc support

diff --git a/orc/Makefile.am b/orc/Makefile.am
index 9388c8b..4d63801 100644
--- a/orc/Makefile.am
+++ b/orc/Makefile.am
@@ -14,6 +14,7 @@ liborc_ at LIBOIL_MAJORMINOR@_la_SOURCES = \
 	orcprogram.c \
 	orcprogram-c.c \
 	orcprogram-x86.c \
+	orcprogram-powerpc.c \
 	orcprogram.h \
 	orcopcodes.c \
 	orcprogram-linux.c
diff --git a/orc/orc.c b/orc/orc.c
index a1dfce8..9d009e1 100644
--- a/orc/orc.c
+++ b/orc/orc.c
@@ -16,6 +16,7 @@ orc_init (void)
   oil_init ();
   orc_opcode_init();
   orc_x86_init();
+  orc_powerpc_init();
   orc_c_init();
 }
 
diff --git a/orc/orcprogram-powerpc.c b/orc/orcprogram-powerpc.c
new file mode 100644
index 0000000..618937f
--- /dev/null
+++ b/orc/orcprogram-powerpc.c
@@ -0,0 +1,784 @@
+
+#include "config.h"
+
+#include <glib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <orc/orcprogram.h>
+
+#define SIZE 65536
+
+#if 0
+void x86_emit_push (OrcProgram *program, int size, int reg);
+void x86_emit_pop (OrcProgram *program, int size, int reg);
+void x86_emit_mov_memoffset_reg (OrcProgram *program, int size, int offset, int reg1, int reg2);
+void x86_emit_mov_memoffset_mmx (OrcProgram *program, int size, int offset,
+    int reg1, int reg2);
+void x86_emit_mov_reg_memoffset (OrcProgram *program, int size, int reg1, int offset, int reg2);
+void x86_emit_mov_mmx_memoffset (OrcProgram *program, int size, int reg1, int offset,
+    int reg2);
+void x86_emit_mov_imm_reg (OrcProgram *program, int size, int value, int reg1);
+void x86_emit_mov_reg_reg (OrcProgram *program, int size, int reg1, int reg2);
+void x86_emit_mov_reg_mmx (OrcProgram *program, int reg1, int reg2);
+void x86_emit_mov_mmx_reg (OrcProgram *program, int reg1, int reg2);
+void x86_emit_test_reg_reg (OrcProgram *program, int size, int reg1, int reg2);
+void x86_emit_sar_imm_reg (OrcProgram *program, int size, int value, int reg);
+void x86_emit_dec_memoffset (OrcProgram *program, int size, int offset, int reg);
+void x86_emit_add_imm_memoffset (OrcProgram *program, int size, int value, int offset, int reg);
+void x86_emit_add_imm_reg (OrcProgram *program, int size, int value, int reg);
+void x86_emit_emms (OrcProgram *program);
+#endif
+void powerpc_emit_ret (OrcProgram *program);
+void powerpc_emit_beq (OrcProgram *program, int label);
+void powerpc_emit_bne (OrcProgram *program, int label);
+void powerpc_emit_label (OrcProgram *program, int label);
+
+#if 0
+static void mmx_emit_loadi_s16 (OrcProgram *p, int reg, int value);
+
+void x86_emit_modrm_memoffset (OrcProgram *program, int reg1, int offset, int reg2);
+void x86_emit_modrm_reg (OrcProgram *program, int reg1, int reg2);
+void x86_test (OrcProgram *program);
+#endif
+
+void orc_program_powerpc_register_rules (void);
+
+enum {
+  POWERPC_R0 = ORC_GP_REG_BASE,
+  POWERPC_R1,
+  POWERPC_R2,
+  POWERPC_R3,
+  POWERPC_R4,
+  POWERPC_R5,
+  POWERPC_R6,
+  POWERPC_R7,
+  POWERPC_R8,
+  POWERPC_R9,
+  POWERPC_R30 = POWERPC_R0+30,
+  POWERPC_R31 = POWERPC_R0+31
+};
+
+const char *
+powerpc_get_regname(int i)
+{
+  static const char *powerpc_regs[] = {
+    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
+    "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19",
+    "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29",
+    "r30", "r31",
+    "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
+    "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
+    "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29",
+    "v30", "v31",
+  };
+
+  if (i>=ORC_GP_REG_BASE && i<ORC_GP_REG_BASE + 64) {
+    return powerpc_regs[i - ORC_GP_REG_BASE];
+  }
+  switch (i) {
+    case 0:
+      return "UNALLOCATED";
+    case 1:
+      return "direct";
+    default:
+      return "ERROR";
+  }
+}
+
+int
+orc_program_powerpc_allocate_register (OrcProgram *program, int data_reg)
+{
+  int i;
+
+  if (!data_reg) {
+    for(i=ORC_GP_REG_BASE;i<ORC_GP_REG_BASE+32;i++){
+      if (program->alloc_regs[i] == 0) {
+        program->alloc_regs[i]++;
+        program->used_regs[i] = 1;
+        return i;
+      }
+    }
+  } else {
+    for(i=ORC_GP_REG_BASE+32;i<ORC_GP_REG_BASE+64;i++){
+      if (program->alloc_regs[i] == 0) {
+        program->alloc_regs[i]++;
+        program->used_regs[i] = 1;
+        return i;
+      }
+    }
+  }
+  g_print("register overflow\n");
+  return 0;
+}
+
+
+void orc_program_rewrite_vars (OrcProgram *program);
+void orc_program_dump (OrcProgram *program);
+
+void
+powerpc_emit_prologue (OrcProgram *program)
+{
+  printf (".global test\n");
+  printf ("test:\n");
+
+  printf ("  mr %s, %s", powerpc_get_regname(POWERPC_R30),
+      powerpc_get_regname(POWERPC_R3));
+#if 0
+  if (program->used_regs[X86_EDI]) {
+    x86_emit_push (program, 4, X86_EDI);
+  }
+  if (program->used_regs[X86_ESI]) {
+    x86_emit_push (program, 4, X86_ESI);
+  }
+  if (program->used_regs[X86_EBX]) {
+    x86_emit_push (program, 4, X86_EBX);
+  }
+#endif
+}
+
+void
+powerpc_emit_epilogue (OrcProgram *program)
+{
+#if 0
+  if (program->used_regs[X86_EBX]) {
+    x86_emit_pop (program, 4, X86_EBX);
+  }
+  if (program->used_regs[X86_ESI]) {
+    x86_emit_pop (program, 4, X86_ESI);
+  }
+  if (program->used_regs[X86_EDI]) {
+    x86_emit_pop (program, 4, X86_EDI);
+  }
+#endif
+  powerpc_emit_ret (program);
+}
+
+void
+powerpc_do_fixups (OrcProgram *program)
+{
+#if 0
+  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;
+    }
+  }
+#endif
+}
+
+void
+orc_powerpc_init (void)
+{
+  orc_program_powerpc_register_rules ();
+}
+
+void
+orc_program_powerpc_reset_alloc (OrcProgram *program)
+{
+  int i;
+
+  for(i=ORC_GP_REG_BASE;i<ORC_GP_REG_BASE+64;i++){
+    program->alloc_regs[i] = 0;
+  }
+  program->alloc_regs[POWERPC_R0] = 1;
+  program->alloc_regs[POWERPC_R31] = 1;
+}
+
+void
+powerpc_load_constants (OrcProgram *program)
+{
+  int i;
+  for(i=0;i<program->n_vars;i++){
+    switch (program->vars[i].vartype) {
+      case ORC_VAR_TYPE_CONST:
+        printf("  vspltish %s, %d\n",
+            powerpc_get_regname(program->vars[i].alloc),
+            program->vars[i].s16);
+        break;
+      case ORC_VAR_TYPE_SRC:
+      case ORC_VAR_TYPE_DEST:
+        if (program->vars[i].ptr_register) {
+          printf("  ldw %s, %s, %d\n",
+              powerpc_get_regname(program->vars[i].ptr_register),
+              powerpc_get_regname(POWERPC_R30),
+              (int)G_STRUCT_OFFSET(OrcExecutor, arrays[i]));
+        } else {
+          /* FIXME */
+          printf("ERROR");
+        }
+        break;
+      default:
+        break;
+    }
+  }
+}
+
+void
+powerpc_emit_load_src (OrcProgram *program, OrcVariable *var)
+{
+  int ptr_reg;
+  ptr_reg = var->ptr_register;
+
+  switch (program->rule_set) {
+    case ORC_RULE_ALTIVEC_1:
+      printf("  lvehx %s, 0, %s\n", 
+          powerpc_get_regname (var->alloc),
+          powerpc_get_regname (ptr_reg));
+      break;
+    default:
+      printf("ERROR\n");
+  }
+}
+
+void
+powerpc_emit_store_dest (OrcProgram *program, OrcVariable *var)
+{
+  int ptr_reg;
+  ptr_reg = var->ptr_register;
+
+  switch (program->rule_set) {
+    case ORC_RULE_ALTIVEC_1:
+      printf("  stvehx %s, 0, %s\n", 
+          powerpc_get_regname (var->alloc),
+          powerpc_get_regname (ptr_reg));
+      break;
+    default:
+      printf("ERROR\n");
+  }
+}
+
+void
+orc_program_assemble_powerpc (OrcProgram *program)
+{
+  int j;
+  int k;
+  OrcInstruction *insn;
+  OrcOpcode *opcode;
+  OrcVariable *args[10];
+  OrcRule *rule;
+
+  powerpc_emit_prologue (program);
+
+#if 0
+  powerpc_emit_mov_memoffset_reg (program, 4, (int)G_STRUCT_OFFSET(OrcExecutor,n),
+      X86_EBP, X86_ECX);
+
+  powerpc_emit_sar_imm_reg (program, 4, program->loop_shift, X86_ECX);
+  powerpc_emit_mov_reg_memoffset (program, 4, X86_ECX,
+      (int)G_STRUCT_OFFSET(OrcExecutor,counter), X86_EBP);
+
+  powerpc_emit_test_reg_reg (program, 4, X86_ECX, X86_ECX);
+#endif
+
+  powerpc_emit_beq (program, 1);
+
+  powerpc_load_constants (program);
+
+  powerpc_emit_label (program, 0);
+
+  for(j=0;j<program->n_insns;j++){
+    insn = program->insns + j;
+    opcode = insn->opcode;
+
+    printf("# %d: %s", j, insn->opcode->name);
+
+    /* set up args */
+    for(k=0;k<opcode->n_src + opcode->n_dest;k++){
+      args[k] = program->vars + insn->args[k];
+      printf(" %d", args[k]->alloc);
+      if (args[k]->is_chained) {
+        printf(" (chained)");
+      }
+    }
+    printf(" rule_flag=%d", insn->rule_flag);
+    printf("\n");
+
+    for(k=opcode->n_dest;k<opcode->n_src + opcode->n_dest;k++){
+      switch (args[k]->vartype) {
+        case ORC_VAR_TYPE_SRC:
+          powerpc_emit_load_src (program, args[k]);
+          break;
+        case ORC_VAR_TYPE_CONST:
+          break;
+        case ORC_VAR_TYPE_TEMP:
+          break;
+        default:
+          break;
+      }
+    }
+
+    rule = insn->rule;
+    if (rule) {
+      rule->emit (program, rule->emit_user, insn);
+    } else {
+      printf("No rule for: %s\n", opcode->name);
+    }
+
+    for(k=0;k<opcode->n_dest;k++){
+      switch (args[k]->vartype) {
+        case ORC_VAR_TYPE_DEST:
+          powerpc_emit_store_dest (program, args[k]);
+          break;
+        case ORC_VAR_TYPE_TEMP:
+          break;
+        default:
+          break;
+      }
+    }
+  }
+
+  for(k=0;k<program->n_vars;k++){
+    if (program->vars[k].vartype == ORC_VAR_TYPE_SRC ||
+        program->vars[k].vartype == ORC_VAR_TYPE_DEST) {
+#if 0
+      if (program->vars[k].ptr_register) {
+        powerpc_emit_add_imm_reg (program, 4,
+            orc_variable_get_size(program->vars + k) * program->n_per_loop,
+            program->vars[k].ptr_register);
+      } else {
+        powerpc_emit_add_imm_memoffset (program, 4,
+            orc_variable_get_size(program->vars + k) * program->n_per_loop,
+            (int)G_STRUCT_OFFSET(OrcExecutor, arrays[k]),
+            X86_EBP);
+      }
+#endif
+    }
+  }
+
+#if 0
+  powerpc_emit_dec_memoffset (program, 4,
+      (int)G_STRUCT_OFFSET(OrcExecutor,counter),
+      X86_EBP);
+#endif
+  powerpc_emit_bne (program, 0);
+  powerpc_emit_label (program, 1);
+
+  powerpc_emit_epilogue (program);
+
+  powerpc_do_fixups (program);
+}
+
+
+/* rules */
+
+static void
+powerpc_rule_add_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
+{
+  printf("  vadduhm %s, %s, %s\n",
+      powerpc_get_regname(p->vars[insn->args[0]].alloc),
+      powerpc_get_regname(p->vars[insn->args[1]].alloc),
+      powerpc_get_regname(p->vars[insn->args[2]].alloc));
+}
+
+static void
+powerpc_rule_sub_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
+{
+  printf("  vsubuhm %s, %s, %s\n",
+      powerpc_get_regname(p->vars[insn->args[0]].alloc),
+      powerpc_get_regname(p->vars[insn->args[1]].alloc),
+      powerpc_get_regname(p->vars[insn->args[2]].alloc));
+}
+
+static void
+powerpc_rule_mul_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
+{
+  printf("  vmladduhm %s, %s, %s, vzero\n",
+      powerpc_get_regname(p->vars[insn->args[0]].alloc),
+      powerpc_get_regname(p->vars[insn->args[1]].alloc),
+      powerpc_get_regname(p->vars[insn->args[2]].alloc));
+}
+
+static void
+powerpc_rule_lshift_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
+{
+  printf("  vrlh %s, %s, %s\n",
+      powerpc_get_regname(p->vars[insn->args[0]].alloc),
+      powerpc_get_regname(p->vars[insn->args[1]].alloc),
+      powerpc_get_regname(p->vars[insn->args[2]].alloc));
+}
+
+static void
+powerpc_rule_rshift_s16 (OrcProgram *p, void *user, OrcInstruction *insn)
+{
+  printf("  vsrah %s, %s, %s\n",
+      powerpc_get_regname(p->vars[insn->args[0]].alloc),
+      powerpc_get_regname(p->vars[insn->args[1]].alloc),
+      powerpc_get_regname(p->vars[insn->args[2]].alloc));
+}
+
+
+void
+orc_program_powerpc_register_rules (void)
+{
+  orc_rule_register ("add_s16", ORC_RULE_ALTIVEC_1, powerpc_rule_add_s16, NULL,
+      ORC_RULE_REG_REG);
+  orc_rule_register ("sub_s16", ORC_RULE_ALTIVEC_1, powerpc_rule_sub_s16, NULL,
+      ORC_RULE_REG_REG);
+  orc_rule_register ("mul_s16", ORC_RULE_ALTIVEC_1, powerpc_rule_mul_s16, NULL,
+      ORC_RULE_REG_REG);
+  orc_rule_register ("lshift_s16", ORC_RULE_ALTIVEC_1, powerpc_rule_lshift_s16, NULL,
+      ORC_RULE_REG_REG);
+  orc_rule_register ("rshift_s16", ORC_RULE_ALTIVEC_1, powerpc_rule_rshift_s16, NULL,
+      ORC_RULE_REG_REG);
+}
+
+/* code generation */
+
+#if 0
+void
+x86_emit_push (OrcProgram *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 (OrcProgram *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 (OrcProgram *program, int reg1, int offset, int reg2)
+{
+  if (offset == 0 && reg2 != X86_EBP) {
+    if (reg2 == X86_ESP) {
+      *program->codeptr++ = X86_MODRM(0, 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(2, 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 (OrcProgram *program, int reg1, int reg2)
+{
+  *program->codeptr++ = X86_MODRM(3, reg1, reg2);
+}
+
+void
+x86_emit_mov_memoffset_reg (OrcProgram *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_memoffset_mmx (OrcProgram *program, int size, int offset,
+    int reg1, int reg2)
+{
+  if (size == 4) {
+    g_print("  movd %d(%%%s), %%%s\n", offset, x86_get_regname(reg1),
+        x86_get_regname_mmx(reg2));
+    *program->codeptr++ = 0x0f;
+    *program->codeptr++ = 0x6e;
+  } else {
+    g_print("  movq %d(%%%s), %%%s\n", offset, x86_get_regname(reg1),
+        x86_get_regname_mmx(reg2));
+    *program->codeptr++ = 0x0f;
+    *program->codeptr++ = 0x6f;
+  }
+  x86_emit_modrm_memoffset (program, reg2, offset, reg1);
+}
+
+void
+x86_emit_mov_reg_memoffset (OrcProgram *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_mmx_memoffset (OrcProgram *program, int size, int reg1, int offset,
+    int reg2)
+{
+  if (size == 4) {
+    g_print("  movd %%%s, %d(%%%s)\n", x86_get_regname_mmx(reg1), offset,
+        x86_get_regname(reg2));
+    *program->codeptr++ = 0x0f;
+    *program->codeptr++ = 0x7e;
+  } else {
+    g_print("  movq %%%s, %d(%%%s)\n", x86_get_regname_mmx(reg1), offset,
+        x86_get_regname(reg2));
+    *program->codeptr++ = 0x0f;
+    *program->codeptr++ = 0x7f;
+  }
+
+  x86_emit_modrm_memoffset (program, reg1, offset, reg2);
+}
+
+void
+x86_emit_mov_imm_reg (OrcProgram *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 + x86_get_regnum(reg1);
+    *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 (OrcProgram *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_mov_reg_mmx (OrcProgram *program, int reg1, int reg2)
+{
+  /* FIXME */
+  g_print("  movd %%%s, %%%s\n", x86_get_regname(reg1),
+      x86_get_regname_mmx(reg2));
+  *program->codeptr++ = 0x0f;
+  *program->codeptr++ = 0x6e;
+  x86_emit_modrm_reg (program, reg1, reg2);
+}
+
+void x86_emit_mov_mmx_reg (OrcProgram *program, int reg1, int reg2)
+{
+  /* FIXME */
+  g_print("  movd %%%s, %%%s\n", x86_get_regname_mmx(reg1),
+      x86_get_regname(reg2));
+  *program->codeptr++ = 0x0f;
+  *program->codeptr++ = 0x7e;
+  x86_emit_modrm_reg (program, reg2, reg1);
+}
+
+void
+x86_emit_test_reg_reg (OrcProgram *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_sar_imm_reg (OrcProgram *program, int size, int value, int reg)
+{
+  g_print("  sarl $%d, %%%s\n", value, x86_get_regname(reg));
+
+  if (value == 1) {
+    *program->codeptr++ = 0xd1;
+    x86_emit_modrm_reg (program, reg, 7);
+  } else {
+    *program->codeptr++ = 0xc1;
+    x86_emit_modrm_reg (program, reg, 7);
+    *program->codeptr++ = value;
+  }
+}
+
+void
+x86_emit_add_imm_memoffset (OrcProgram *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);
+    if (size == 4) {
+      *program->codeptr++ = ((value>>16) & 0xff);
+      *program->codeptr++ = ((value>>24) & 0xff);
+    }
+  }
+}
+
+void
+x86_emit_add_imm_reg (OrcProgram *program, int size, int value, int reg)
+{
+  if (size == 2) {
+    g_print("  addw $%d, %%%s\n", value, x86_get_regname_16(reg));
+    *program->codeptr++ = 0x66;
+  } else {
+    g_print("  addl $%d, %%%s\n", value, x86_get_regname(reg));
+  }
+
+  if (value >= -128 && value < 128) {
+    *program->codeptr++ = 0x83;
+    x86_emit_modrm_reg (program, reg, 0);
+    *program->codeptr++ = (value & 0xff);
+  } else {
+    *program->codeptr++ = 0x81;
+    x86_emit_modrm_reg (program, reg, 0);
+    *program->codeptr++ = (value & 0xff);
+    *program->codeptr++ = ((value>>8) & 0xff);
+    if (size == 4) {
+      *program->codeptr++ = ((value>>16) & 0xff);
+      *program->codeptr++ = ((value>>24) & 0xff);
+    }
+  }
+}
+
+void
+x86_emit_dec_memoffset (OrcProgram *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);
+}
+#endif
+
+void powerpc_emit_ret (OrcProgram *program)
+{
+  g_print("  ret\n");
+  //*program->codeptr++ = 0xc3;
+}
+
+#if 0
+void
+x86_add_fixup (OrcProgram *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++;
+}
+#endif
+
+void
+powerpc_add_label (OrcProgram *program, unsigned char *ptr, int label)
+{
+  program->labels[label] = ptr;
+}
+
+void powerpc_emit_beq (OrcProgram *program, int label)
+{
+  g_print("  beq .L%d\n", label);
+
+#if 0
+  *program->codeptr++ = 0x74;
+  x86_add_fixup (program, program->codeptr, label);
+  *program->codeptr++ = -1;
+#endif
+}
+
+void powerpc_emit_bne (OrcProgram *program, int label)
+{
+  g_print("  bne .L%d\n", label);
+#if 0
+  *program->codeptr++ = 0x75;
+  x86_add_fixup (program, program->codeptr, label);
+  *program->codeptr++ = -1;
+#endif
+}
+
+void powerpc_emit_label (OrcProgram *program, int label)
+{
+  g_print(".L%d:\n", label);
+
+  powerpc_add_label (program, program->codeptr, label);
+}
+
diff --git a/orc/orcprogram-x86.c b/orc/orcprogram-x86.c
index abb8470..273d07a 100644
--- a/orc/orcprogram-x86.c
+++ b/orc/orcprogram-x86.c
@@ -123,9 +123,38 @@ x86_get_regname_mmx(int i)
   }
 }
 
+int
+orc_program_x86_allocate_register (OrcProgram *program, int data_reg)
+{
+  int i;
+
+  if (program->rule_set == ORC_RULE_SCALAR_1) {
+    data_reg = FALSE;
+  }
+
+  if (!data_reg) {
+    for(i=ORC_GP_REG_BASE;i<ORC_GP_REG_BASE+8;i++){
+      if (program->alloc_regs[i] == 0) {
+        program->alloc_regs[i]++;
+        program->used_regs[i] = 1;
+        return i;
+      }
+    }
+  } else {
+    for(i=ORC_GP_REG_BASE+8;i<ORC_GP_REG_BASE+16;i++){
+      if (program->alloc_regs[i] == 0) {
+        program->alloc_regs[i]++;
+        program->used_regs[i] = 1;
+        return i;
+      }
+    }
+  }
+  g_print("register overflow\n");
+  return 0;
+}
+
 
 void orc_program_rewrite_vars (OrcProgram *program);
-void orc_program_allocate_regs (OrcProgram *program);
 void orc_program_dump (OrcProgram *program);
 
 void
diff --git a/orc/orcprogram.c b/orc/orcprogram.c
index be1b591..2c46264 100644
--- a/orc/orcprogram.c
+++ b/orc/orcprogram.c
@@ -22,7 +22,7 @@ orc_program_new (void)
   p = malloc(sizeof(OrcProgram));
   memset (p, 0, sizeof(OrcProgram));
 
-  p->rule_set = ORC_RULE_MMX_1;
+  p->rule_set = ORC_RULE_ALTIVEC_1;
   p->n_per_loop = 1;
   p->loop_shift = 0;
 
@@ -135,31 +135,11 @@ orc_program_append (OrcProgram *program, const char *name, int arg0,
 int
 orc_program_allocate_register (OrcProgram *program, int data_reg)
 {
-  int i;
-
-  if (program->rule_set == ORC_RULE_SCALAR_1) {
-    data_reg = FALSE;
-  }
-
-  if (!data_reg) {
-    for(i=ORC_GP_REG_BASE;i<ORC_GP_REG_BASE+8;i++){
-      if (program->alloc_regs[i] == 0) {
-        program->alloc_regs[i]++;
-        program->used_regs[i] = 1;
-        return i;
-      }
-    }
+  if (program->rule_set == ORC_RULE_ALTIVEC_1) {
+    return orc_program_powerpc_allocate_register (program, data_reg);
   } else {
-    for(i=ORC_GP_REG_BASE+8;i<ORC_GP_REG_BASE+16;i++){
-      if (program->alloc_regs[i] == 0) {
-        program->alloc_regs[i]++;
-        program->used_regs[i] = 1;
-        return i;
-      }
-    }
+    return orc_program_x86_allocate_register (program, data_reg);
   }
-  g_print("register overflow\n");
-  return 0;
 }
 
 void
@@ -168,7 +148,8 @@ orc_program_compile (OrcProgram *program)
   orc_program_assign_rules (program);
   orc_program_rewrite_vars (program);
 
-  orc_program_reset_alloc (program);
+  //orc_program_x86_reset_alloc (program);
+  orc_program_powerpc_reset_alloc (program);
   orc_program_global_reg_alloc (program);
 
   orc_program_do_regs (program);
@@ -176,7 +157,8 @@ orc_program_compile (OrcProgram *program)
   orc_program_rewrite_vars2 (program);
 
   orc_program_allocate_codemem (program);
-  orc_program_assemble_x86 (program);
+  //orc_program_assemble_x86 (program);
+  orc_program_assemble_powerpc (program);
   //orc_program_assemble_c (program);
 
   orc_program_dump_code (program);
diff --git a/orc/orcprogram.h b/orc/orcprogram.h
index 29a6a4f..684cc11 100644
--- a/orc/orcprogram.h
+++ b/orc/orcprogram.h
@@ -30,7 +30,8 @@ enum {
   ORC_RULE_MMX_1,
   ORC_RULE_MMX_2,
   ORC_RULE_MMX_4,
-  ORC_RULE_MMX_8
+  ORC_RULE_MMX_8,
+  ORC_RULE_ALTIVEC_1
 };
 
 struct _OrcType {
@@ -184,10 +185,12 @@ void orc_opcode_init (void);
 void orc_program_append (OrcProgram *p, const char *opcode, int arg0, int arg1, int arg2);
 
 void orc_x86_init (void);
+void orc_powerpc_init (void);
 void orc_c_init (void);
 
 void orc_program_compile (OrcProgram *p);
 void orc_program_assemble_x86 (OrcProgram *p);
+void orc_program_assemble_powerpc (OrcProgram *p);
 void orc_program_assemble_c (OrcProgram *p);
 void orc_program_free (OrcProgram *program);
 
@@ -199,7 +202,8 @@ int orc_program_add_constant (OrcProgram *program, const char *type, int value,
 void orc_program_append (OrcProgram *program, const char *opcode, int arg0,
     int arg1, int arg2);
 
-void orc_program_reset_alloc (OrcProgram *program);
+void orc_program_x86_reset_alloc (OrcProgram *program);
+void orc_program_powerpc_reset_alloc (OrcProgram *program);
 
 
 OrcType * orc_type_get (const char *name);
@@ -215,6 +219,10 @@ void orc_executor_run (OrcExecutor *ex);
 void orc_rule_register (const char *opcode_name, unsigned int mode,
     OrcRuleEmitFunc emit, void *emit_user, unsigned int flags);
 
+int orc_program_allocate_register (OrcProgram *program, int is_data);
+int orc_program_x86_allocate_register (OrcProgram *program, int is_data);
+int orc_program_powerpc_allocate_register (OrcProgram *program, int is_data);
+
 void orc_program_x86_register_rules (void);
 void orc_program_allocate_codemem (OrcProgram *program);
 void orc_program_dump_code (OrcProgram *program);


More information about the Liboil-commit mailing list