diff options
author | David Schleef <ds@ginger.bigkitten.com> | 2008-05-21 00:24:52 -0700 |
---|---|---|
committer | David Schleef <ds@ginger.bigkitten.com> | 2008-05-21 00:24:52 -0700 |
commit | b0cbfea4324309b3b14f66b562087f0b79f61edd (patch) | |
tree | 28c38a95a9949f53cb4d0ff08f20d64e56ebbddd | |
parent | 4477508ae5af09e741f530abf0bf73ed8f396513 (diff) | |
download | liboil-b0cbfea4324309b3b14f66b562087f0b79f61edd.tar.gz |
[orc] add beginnings of powerpc support
-rw-r--r-- | orc/Makefile.am | 1 | ||||
-rw-r--r-- | orc/orc.c | 1 | ||||
-rw-r--r-- | orc/orcprogram-powerpc.c | 784 | ||||
-rw-r--r-- | orc/orcprogram-x86.c | 31 | ||||
-rw-r--r-- | orc/orcprogram.c | 34 | ||||
-rw-r--r-- | orc/orcprogram.h | 12 |
6 files changed, 834 insertions, 29 deletions
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_@LIBOIL_MAJORMINOR@_la_SOURCES = \ orcprogram.c \ orcprogram-c.c \ orcprogram-x86.c \ + orcprogram-powerpc.c \ orcprogram.h \ orcopcodes.c \ orcprogram-linux.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); |