From 5e8a6257da92f90898f8a8c553124ecda50d3171 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Wed, 25 Aug 2010 03:25:14 -0700 Subject: [PATCH] altivec: Implement lots more rules --- orc/orcpowerpc.c | 118 +++++++---- orc/orcpowerpc.h | 19 +- orc/orcprogram-altivec.c | 382 ++++-------------------------------- orc/orcrules-altivec.c | 495 +++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 571 insertions(+), 443 deletions(-) diff --git a/orc/orcpowerpc.c b/orc/orcpowerpc.c index 616951f..f813109 100644 --- a/orc/orcpowerpc.c +++ b/orc/orcpowerpc.c @@ -178,6 +178,19 @@ powerpc_emit_655510 (OrcCompiler *compiler, int major, int d, int a, int b, } void +powerpc_emit_D (OrcCompiler *compiler, const char *name, + unsigned int insn, int regd, int rega, int imm) +{ + ORC_ASM_CODE(compiler," %s %s, %s, %d\n", name, + powerpc_get_regname(regd), + powerpc_get_regname(rega), imm); + insn |= (powerpc_regnum (regd)<<21) | (powerpc_regnum (rega)<<16); + insn |= imm&0xffff; + + powerpc_emit (compiler, insn); +} + +void powerpc_emit_X (OrcCompiler *compiler, unsigned int insn, int d, int a, int b) { #if 0 @@ -195,31 +208,48 @@ powerpc_emit_X (OrcCompiler *compiler, unsigned int insn, int d, int a, int b) } void -powerpc_emit_VA (OrcCompiler *compiler, int major, int d, int a, int b, - int c, int minor) +powerpc_emit_VA (OrcCompiler *compiler, const char *name, unsigned int insn, + int d, int a, int b, int c) { - unsigned int insn; + ORC_ASM_CODE(compiler," %s %s, %s, %s, %s\n", name, + powerpc_get_regname(d), + powerpc_get_regname(a), + powerpc_get_regname(b), + powerpc_get_regname(c)); - insn = (major<<26) | (d<<21) | (a<<16); - insn |= (b<<11) | (c<<6) | (minor<<0); + insn |= ((d&0x1f)<<21) | ((a&0x1f)<<16) | ((b&0x1f)<<11) | ((c&0x1f)<<6); powerpc_emit (compiler, insn); } void -powerpc_emit_VA_2 (OrcCompiler *p, const char *name, int major, int d, int a, int b, - int c, int minor) +powerpc_emit_VA_acb (OrcCompiler *compiler, const char *name, unsigned int insn, + int d, int a, int b, int c) { - ORC_ASM_CODE(p," %s %s, %s, %s, %s\n", name, + ORC_ASM_CODE(compiler," %s %s, %s, %s, %s\n", name, powerpc_get_regname(d), powerpc_get_regname(a), - powerpc_get_regname(b), - powerpc_get_regname(c)); - powerpc_emit_VA(p, major, - powerpc_regnum(d), - powerpc_regnum(a), - powerpc_regnum(b), - powerpc_regnum(c), minor); + powerpc_get_regname(c), + powerpc_get_regname(b)); + + insn |= ((d&0x1f)<<21) | ((a&0x1f)<<16) | ((b&0x1f)<<11) | ((c&0x1f)<<6); + + powerpc_emit (compiler, insn); +} + +void +powerpc_emit_VXR (OrcCompiler *compiler, const char *name, unsigned int insn, + int d, int a, int b, int record) +{ + ORC_ASM_CODE(compiler," %s %s, %s, %s\n", name, + powerpc_get_regname(d), + powerpc_get_regname(a), + powerpc_get_regname(b)); + + insn |= ((d&0x1f)<<21) | ((a&0x1f)<<16) | ((b&0x1f)<<11); + insn |= ((record&0x1)<<10); + + powerpc_emit (compiler, insn); } void @@ -246,6 +276,34 @@ powerpc_emit_VX_2 (OrcCompiler *p, const char *name, } void +powerpc_emit_VX_b (OrcCompiler *p, const char *name, + unsigned int insn, int b) +{ + ORC_ASM_CODE(p," %s %s\n", name, powerpc_get_regname(b)); + powerpc_emit_VX(p, insn, 0, 0, powerpc_regnum(b)); +} + +void +powerpc_emit_VX_db (OrcCompiler *p, const char *name, unsigned int insn, + int d, int b) +{ + ORC_ASM_CODE(p," %s %s, %s\n", name, + powerpc_get_regname(d), + powerpc_get_regname(b)); + powerpc_emit_VX(p, insn, powerpc_regnum(d), 0, powerpc_regnum(b)); +} + +void +powerpc_emit_VX_dbi (OrcCompiler *p, const char *name, unsigned int insn, + int d, int b, int imm) +{ + ORC_ASM_CODE(p," %s %s, %s, %d\n", name, + powerpc_get_regname(d), + powerpc_get_regname(b), imm); + powerpc_emit_VX(p, insn, powerpc_regnum(d), imm, powerpc_regnum(b)); +} + +void powerpc_emit_VX_3_reg (OrcCompiler *p, const char *name, unsigned int insn, int d, int a, int b, int c) { @@ -328,7 +386,7 @@ orc_powerpc_flush_cache (OrcCode *code) } __asm__ __volatile ("sync"); - ptr = code->exec; + ptr = (void *)code->exec; for (i=0;iconstants[i].type) { case ORC_CONST_ZERO: powerpc_emit_VX_2(p, "vxor", 0x100004c4, reg, reg, reg); - break; + return; case ORC_CONST_SPLAT_B: if (value < 16 && value >= -16) { ORC_ASM_CODE(p," vspltisb %s, %d\n", - powerpc_get_regname(reg), value&0x1f); - powerpc_emit_VX(p, 0x1000020c, + powerpc_get_regname(reg), value); + powerpc_emit_VX(p, 0x1000030c, powerpc_regnum(reg), value & 0x1f, 0); - } else { - ORC_COMPILER_ERROR(p,"can't load constant"); + return; } break; case ORC_CONST_SPLAT_W: if (value < 16 && value >= -16) { ORC_ASM_CODE(p," vspltish %s, %d\n", - powerpc_get_regname(reg), value&0x1f); - powerpc_emit_VX(p, 0x1000024c, + powerpc_get_regname(reg), value); + powerpc_emit_VX(p, 0x1000034c, powerpc_regnum(reg), value & 0x1f, 0); - } else { - ORC_COMPILER_ERROR(p,"can't load constant"); + return; } break; case ORC_CONST_SPLAT_L: if (value < 16 && value >= -16) { ORC_ASM_CODE(p," vspltisw %s, %d\n", - powerpc_get_regname(reg), value&0x1f); - powerpc_emit_VX(p, 0x1000028c, + powerpc_get_regname(reg), value); + powerpc_emit_VX(p, 0x1000038c, powerpc_regnum(reg), value & 0x1f, 0); - } else { - ORC_COMPILER_ERROR(p,"can't load constant"); + return; } break; default: - ORC_COMPILER_ERROR(p,"unhandled"); break; } -#endif switch (p->constants[i].type) { case ORC_CONST_ZERO: @@ -463,7 +515,7 @@ powerpc_load_constant (OrcCompiler *p, int i, int reg) int powerpc_get_constant (OrcCompiler *p, int type, int value) { - int reg = p->tmpreg; + int reg = orc_compiler_get_temp_reg (p); int i; for(i=0;in_constants;i++){ diff --git a/orc/orcpowerpc.h b/orc/orcpowerpc.h index 2075756..5a85a47 100644 --- a/orc/orcpowerpc.h +++ b/orc/orcpowerpc.h @@ -96,14 +96,21 @@ void powerpc_emit_srawi (OrcCompiler *compiler, int regd, int rega, int shift, int record); void powerpc_emit_655510 (OrcCompiler *compiler, int major, int d, int a, int b, int minor); +void powerpc_emit_D (OrcCompiler *compiler, const char *name, + unsigned int insn, int regd, int rega, int imm); void powerpc_emit_X (OrcCompiler *compiler, unsigned int insn, int d, int a, int b); -void powerpc_emit_VA (OrcCompiler *compiler, int major, int d, int a, int b, - int c, int minor); -void powerpc_emit_VA_2 (OrcCompiler *compiler, const char *name, int major, int d, - int a, int b, int c, int minor); +void powerpc_emit_VA (OrcCompiler *compiler, const char *name, unsigned int insn, int d, int a, int b, + int c); +void powerpc_emit_VA_acb (OrcCompiler *compiler, const char *name, unsigned int insn, int d, int a, int b, + int c); void powerpc_emit_VX (OrcCompiler *compiler, unsigned int insn, int d, int a, int b); +void powerpc_emit_VX_b (OrcCompiler *p, const char *name, unsigned int insn, int a); +void powerpc_emit_VX_db (OrcCompiler *p, const char *name, unsigned int insn, int d, int b); +void powerpc_emit_VX_dbi (OrcCompiler *p, const char *name, unsigned int insn, int d, int b, int imm); +void powerpc_emit_VXR (OrcCompiler *compiler, const char *name, + unsigned int insn, int d, int a, int b, int record); void powerpc_emit_VX_2 (OrcCompiler *p, const char *name, unsigned int insn, int d, int a, int b); void powerpc_emit_VX_3 (OrcCompiler *p, const char *name, unsigned int insn, @@ -154,12 +161,12 @@ int powerpc_get_constant_full (OrcCompiler *p, int value0, int value1, int value #define powerpc_emit_vminsw(p,a,b,c) powerpc_emit_VX_2 (p, "vminsw", 0x10000382, a, b, c) #define powerpc_emit_vsldoi(p,a,b,c,d) powerpc_emit_VX_3 (p, "vsldoi", 0x1000002c | (d<<6), a, b, c, d) -#define powerpc_emit_vmladduhm(p,a,b,c,d) powerpc_emit_VA_2 (p, "vmladduhm", 4, a, b, c, d, 34) +#define powerpc_emit_vmladduhm(p,a,b,c,d) powerpc_emit_VA (p, "vmladduhm", 0x10000022, a, b, c, d) #define powerpc_emit_vupkhsb(p,a,b) powerpc_emit_VX_4 (p, "vupkhsb", 0x1000020e, a, b) #define powerpc_emit_vupkhsh(p,a,b) powerpc_emit_VX_4 (p, "vupkhsh", 0x1000024e, a, b) -#define powerpc_emit_vperm(p,a,b,c,d) powerpc_emit_VX_3_reg (p, "vperm", 0x1000002b, a, b, c, d) +#define powerpc_emit_vperm(p,a,b,c,d) powerpc_emit_VA (p, "vperm", 0x1000002b, a, b, c, d) #endif diff --git a/orc/orcprogram-altivec.c b/orc/orcprogram-altivec.c index e661c11..5f1755b 100644 --- a/orc/orcprogram-altivec.c +++ b/orc/orcprogram-altivec.c @@ -101,8 +101,9 @@ orc_compiler_powerpc_init (OrcCompiler *compiler) compiler->valid_regs[POWERPC_R13] = 0; /* reserved */ compiler->tmpreg = POWERPC_V0; - compiler->gp_tmpreg = POWERPC_R0; + compiler->gp_tmpreg = POWERPC_R4; compiler->valid_regs[compiler->tmpreg] = 0; + compiler->valid_regs[compiler->gp_tmpreg] = 0; for(i=14;i<32;i++){ compiler->save_regs[POWERPC_R0 + i] = 1; @@ -114,207 +115,17 @@ orc_compiler_powerpc_init (OrcCompiler *compiler) compiler->loop_shift = 0; } -#if 0 -static void -powerpc_load_constant (OrcCompiler *p, int i, int reg) -{ - int j; - int value = p->constants[i].value; - int greg = POWERPC_R31; - int label_skip, label_data; - -#if 0 - switch (p->constants[i].type) { - case ORC_CONST_ZERO: - powerpc_emit_VX_2(p, "vxor", 0x100004c4, reg, reg, reg); - break; - case ORC_CONST_SPLAT_B: - if (value < 16 && value >= -16) { - ORC_ASM_CODE(p," vspltisb %s, %d\n", - powerpc_get_regname(reg), value&0x1f); - powerpc_emit_VX(p, 0x1000020c, - powerpc_regnum(reg), value & 0x1f, 0); - } else { - ORC_COMPILER_ERROR(p,"can't load constant"); - } - break; - case ORC_CONST_SPLAT_W: - if (value < 16 && value >= -16) { - ORC_ASM_CODE(p," vspltish %s, %d\n", - powerpc_get_regname(reg), value&0x1f); - powerpc_emit_VX(p, 0x1000024c, - powerpc_regnum(reg), value & 0x1f, 0); - } else { - ORC_COMPILER_ERROR(p,"can't load constant"); - } - break; - case ORC_CONST_SPLAT_L: - if (value < 16 && value >= -16) { - ORC_ASM_CODE(p," vspltisw %s, %d\n", - powerpc_get_regname(reg), value&0x1f); - powerpc_emit_VX(p, 0x1000028c, - powerpc_regnum(reg), value & 0x1f, 0); - } else { - ORC_COMPILER_ERROR(p,"can't load constant"); - } - break; - default: - ORC_COMPILER_ERROR(p,"unhandled"); - break; - } -#endif - - switch (p->constants[i].type) { - case ORC_CONST_ZERO: - for(j=0;j<4;j++){ - p->constants[i].full_value[j] = 0; - } - break; - case ORC_CONST_SPLAT_B: - value &= 0xff; - value |= (value<<8); - value |= (value<<16); - for(j=0;j<4;j++){ - p->constants[i].full_value[j] = value; - } - break; - case ORC_CONST_SPLAT_W: - value &= 0xffff; - value |= (value<<16); - for(j=0;j<4;j++){ - p->constants[i].full_value[j] = value; - } - break; - case ORC_CONST_SPLAT_L: - for(j=0;j<4;j++){ - p->constants[i].full_value[j] = value; - } - break; - default: - break; - } - - label_skip = orc_compiler_label_new (p); - label_data = orc_compiler_label_new (p); - - powerpc_emit_b (p, label_skip); - - while ((p->codeptr - p->program->code) & 0xf) { - ORC_ASM_CODE(p," .long 0x00000000\n"); - powerpc_emit (p, 0x00000000); - } - - powerpc_emit_label (p, label_data); - for(j=0;j<4;j++){ - ORC_ASM_CODE(p," .long 0x%08x\n", p->constants[i].full_value[j]); - powerpc_emit (p, p->constants[i].full_value[j]); - } - - powerpc_emit_label (p, label_skip); - powerpc_emit_lwz (p, - greg, - POWERPC_R3, - (int)ORC_STRUCT_OFFSET(OrcExecutor, program)); - powerpc_emit_lwz (p, - greg, greg, - (int)ORC_STRUCT_OFFSET(OrcProgram, code_exec)); - - powerpc_add_fixup (p, 1, p->codeptr, label_data); - { - unsigned int insn; - - ORC_ASM_CODE(p," addi %s, %s, %db - %s\n", - powerpc_get_regname(greg), - powerpc_get_regname(greg), label_data, p->program->name); - insn = (14<<26) | (powerpc_regnum (greg)<<21) | (powerpc_regnum (greg)<<16); - insn |= 0; - - powerpc_emit (p, insn); - } - - ORC_ASM_CODE(p," lvx %s, 0, %s\n", - powerpc_get_regname(reg), - powerpc_get_regname(greg)); - powerpc_emit_X (p, 0x7c0000ce, reg, 0, greg); - -} - void -powerpc_load_constants (OrcCompiler *compiler) +powerpc_load_inner_constants (OrcCompiler *compiler) { OrcVariable *var; int i; - int j; - int greg = POWERPC_R0; for(i=0;ivars + i; if (compiler->vars[i].name == NULL) continue; switch (compiler->vars[i].vartype) { - case ORC_VAR_TYPE_CONST: - j = compiler->n_constants; - compiler->n_constants++; - if (compiler->vars[i].size == 1) { - compiler->constants[j].type = ORC_CONST_SPLAT_B; - } else if (compiler->vars[i].size == 2) { - compiler->constants[j].type = ORC_CONST_SPLAT_W; - } else { - compiler->constants[j].type = ORC_CONST_SPLAT_L; - } - compiler->constants[j].value = compiler->vars[i].value; - compiler->constants[j].alloc_reg = compiler->vars[i].alloc; - break; - case ORC_VAR_TYPE_PARAM: - powerpc_emit_addi (compiler, - greg, POWERPC_R3, - (int)ORC_STRUCT_OFFSET(OrcExecutor, params[i])); - ORC_ASM_CODE(compiler," lvewx %s, 0, %s\n", - powerpc_get_regname (var->alloc), - powerpc_get_regname (greg)); - powerpc_emit_X (compiler, 0x7c00008e, powerpc_regnum(var->alloc), - 0, powerpc_regnum(greg)); - - ORC_ASM_CODE(compiler," lvsl %s, 0, %s\n", - powerpc_get_regname (POWERPC_V0), - powerpc_get_regname (greg)); - powerpc_emit_X (compiler, 0x7c00000c, powerpc_regnum(POWERPC_V0), - 0, powerpc_regnum(greg)); - - ORC_ASM_CODE(compiler," vperm %s, %s, %s, %s\n", - powerpc_get_regname (var->alloc), - powerpc_get_regname (var->alloc), - powerpc_get_regname (var->alloc), - powerpc_get_regname (POWERPC_V0)); - powerpc_emit_VA (compiler, 4, - powerpc_regnum(var->alloc), - powerpc_regnum(var->alloc), - powerpc_regnum(var->alloc), - powerpc_regnum(POWERPC_V0), 43); - switch (var->size) { - case 1: - ORC_ASM_CODE(compiler," vspltb %s, %s, 3\n", - powerpc_get_regname (var->alloc), - powerpc_get_regname (var->alloc)); - powerpc_emit_VX (compiler, 0x1000020c, - powerpc_regnum(var->alloc), 3, powerpc_regnum(var->alloc)); - break; - case 2: - ORC_ASM_CODE(compiler," vsplth %s, %s, 1\n", - powerpc_get_regname (var->alloc), - powerpc_get_regname (var->alloc)); - powerpc_emit_VX (compiler, 0x1000024c, - powerpc_regnum(var->alloc), 1, powerpc_regnum(var->alloc)); - break; - case 4: - ORC_ASM_CODE(compiler," vspltw %s, %s, 0\n", - powerpc_get_regname (var->alloc), - powerpc_get_regname (var->alloc)); - powerpc_emit_VX (compiler, 0x1000028c, - powerpc_regnum(var->alloc), 0, powerpc_regnum(var->alloc)); - break; - } - break; case ORC_VAR_TYPE_SRC: case ORC_VAR_TYPE_DEST: if (compiler->vars[i].ptr_register) { @@ -331,149 +142,18 @@ powerpc_load_constants (OrcCompiler *compiler) break; } } - - for(i=0;in_constants;i++){ - if (compiler->constants[i].alloc_reg > 0) { - powerpc_load_constant (compiler, i, compiler->constants[i].alloc_reg); - } - } -} - -void -powerpc_emit_load_src (OrcCompiler *compiler, OrcVariable *var) -{ - int ptr_reg; - ptr_reg = var->ptr_register; - - switch (compiler->loop_shift) { - case 0: - switch (var->size) { - case 1: - ORC_ASM_CODE(compiler," lvebx %s, 0, %s\n", - powerpc_get_regname (var->alloc), - powerpc_get_regname (ptr_reg)); - powerpc_emit_X (compiler, 0x7c00000e, powerpc_regnum(var->alloc), - 0, powerpc_regnum(ptr_reg)); - break; - case 2: - ORC_ASM_CODE(compiler," lvehx %s, 0, %s\n", - powerpc_get_regname (var->alloc), - powerpc_get_regname (ptr_reg)); - powerpc_emit_X (compiler, 0x7c00004e, powerpc_regnum(var->alloc), - 0, powerpc_regnum(ptr_reg)); - break; - case 4: - ORC_ASM_CODE(compiler," lvewx %s, 0, %s\n", - powerpc_get_regname (var->alloc), - powerpc_get_regname (ptr_reg)); - powerpc_emit_X (compiler, 0x7c00008e, powerpc_regnum(var->alloc), - 0, powerpc_regnum(ptr_reg)); - break; - } - ORC_ASM_CODE(compiler," lvsl %s, 0, %s\n", - powerpc_get_regname (POWERPC_V0), - powerpc_get_regname (ptr_reg)); - powerpc_emit_X (compiler, 0x7c00000c, powerpc_regnum(POWERPC_V0), - 0, powerpc_regnum(ptr_reg)); - ORC_ASM_CODE(compiler," vperm %s, %s, %s, %s\n", - powerpc_get_regname (var->alloc), - powerpc_get_regname (var->alloc), - powerpc_get_regname (var->alloc), - powerpc_get_regname (POWERPC_V0)); - powerpc_emit_VA (compiler, 4, - powerpc_regnum(var->alloc), - powerpc_regnum(var->alloc), - powerpc_regnum(var->alloc), - powerpc_regnum(POWERPC_V0), 43); - break; - default: - ORC_ASM_CODE(compiler,"ERROR\n"); - } -} - -void -powerpc_emit_store_dest (OrcCompiler *compiler, OrcVariable *var) -{ - int ptr_reg; - ptr_reg = var->ptr_register; - - switch (compiler->loop_shift) { - case 0: - ORC_ASM_CODE(compiler," lvsr %s, 0, %s\n", - powerpc_get_regname (POWERPC_V0), - powerpc_get_regname (ptr_reg)); - powerpc_emit_X (compiler, 0x7c00004c, powerpc_regnum(POWERPC_V0), - 0, powerpc_regnum(ptr_reg)); - ORC_ASM_CODE(compiler," vperm %s, %s, %s, %s\n", - powerpc_get_regname (var->alloc), - powerpc_get_regname (var->alloc), - powerpc_get_regname (var->alloc), - powerpc_get_regname (POWERPC_V0)); - powerpc_emit_VA (compiler, 4, - powerpc_regnum(var->alloc), - powerpc_regnum(var->alloc), - powerpc_regnum(var->alloc), - powerpc_regnum(POWERPC_V0), 43); - switch (var->size) { - case 1: - ORC_ASM_CODE(compiler," stvebx %s, 0, %s\n", - powerpc_get_regname (var->alloc), - powerpc_get_regname (ptr_reg)); - powerpc_emit_X (compiler, 0x7c00010e, - powerpc_regnum(var->alloc), - 0, powerpc_regnum(ptr_reg)); - break; - case 2: - ORC_ASM_CODE(compiler," stvehx %s, 0, %s\n", - powerpc_get_regname (var->alloc), - powerpc_get_regname (ptr_reg)); - powerpc_emit_X (compiler, 0x7c00014e, - powerpc_regnum(var->alloc), - 0, powerpc_regnum(ptr_reg)); - break; - case 4: - ORC_ASM_CODE(compiler," stvewx %s, 0, %s\n", - powerpc_get_regname (var->alloc), - powerpc_get_regname (ptr_reg)); - powerpc_emit_X (compiler, 0x7c00018e, - powerpc_regnum(var->alloc), - 0, powerpc_regnum(ptr_reg)); - break; - } - break; - default: - ORC_ASM_CODE(compiler,"ERROR\n"); - } } -#endif -void -powerpc_load_inner_constants (OrcCompiler *compiler) +static int +orc_program_has_float (OrcCompiler *compiler) { - OrcVariable *var; - int i; - - for(i=0;ivars + i; - - if (compiler->vars[i].name == NULL) continue; - switch (compiler->vars[i].vartype) { - case ORC_VAR_TYPE_SRC: - case ORC_VAR_TYPE_DEST: - if (compiler->vars[i].ptr_register) { - powerpc_emit_lwz (compiler, - compiler->vars[i].ptr_register, - POWERPC_R3, - (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[i])); - } else { - /* FIXME */ - ORC_ASM_CODE(compiler,"ERROR"); - } - break; - default: - break; - } + int j; + for(j=0;jn_insns;j++){ + OrcInstruction *insn = compiler->insns + j; + OrcStaticOpcode *opcode = insn->opcode; + if (opcode->flags & ORC_STATIC_OPCODE_FLOAT) return TRUE; } + return FALSE; } void @@ -488,6 +168,7 @@ orc_compiler_powerpc_assemble (OrcCompiler *compiler) int label_outer_loop_start; int label_loop_start; int label_leave; + int set_vscr = FALSE; label_outer_loop_start = orc_compiler_label_new (compiler); label_loop_start = orc_compiler_label_new (compiler); @@ -495,6 +176,19 @@ orc_compiler_powerpc_assemble (OrcCompiler *compiler) powerpc_emit_prologue (compiler); + if (orc_program_has_float (compiler)) { + int tmp = POWERPC_V0; + + set_vscr = TRUE; + + ORC_ASM_CODE(compiler," vspltish %s, %d\n", + powerpc_get_regname(tmp), 1); + powerpc_emit_VX(compiler, 0x1000034c, + powerpc_regnum(tmp), 1, 0); + + powerpc_emit_VX_b(compiler, "mtvscr", 0x10000644, tmp); + } + if (compiler->program->is_2d) { powerpc_emit_lwz (compiler, POWERPC_R0, POWERPC_R3, (int)ORC_STRUCT_OFFSET(OrcExecutorAlt, m)); @@ -535,6 +229,8 @@ orc_compiler_powerpc_assemble (OrcCompiler *compiler) insn = compiler->insns + j; opcode = insn->opcode; + compiler->insn_index = j; + ORC_ASM_CODE(compiler,"# %d: %s\n", j, insn->opcode->name); #if 0 @@ -568,6 +264,8 @@ orc_compiler_powerpc_assemble (OrcCompiler *compiler) } } + compiler->min_temp_reg = ORC_VEC_REG_BASE; + rule = insn->rule; if (rule) { rule->emit (compiler, rule->emit_user, insn); @@ -674,16 +372,8 @@ orc_compiler_powerpc_assemble (OrcCompiler *compiler) powerpc_emit_X (compiler, 0x7c00004c, powerpc_regnum(POWERPC_V0), 0, powerpc_regnum(POWERPC_R0)); - ORC_ASM_CODE(compiler," vperm %s, %s, %s, %s\n", - powerpc_get_regname (var->alloc), - powerpc_get_regname (var->alloc), - powerpc_get_regname (var->alloc), - powerpc_get_regname (POWERPC_V0)); - powerpc_emit_VA (compiler, 4, - powerpc_regnum(var->alloc), - powerpc_regnum(var->alloc), - powerpc_regnum(var->alloc), - powerpc_regnum(POWERPC_V0), 43); + powerpc_emit_vperm (compiler, var->alloc, var->alloc, var->alloc, + POWERPC_V0); ORC_ASM_CODE(compiler," stvewx %s, 0, %s\n", powerpc_get_regname (var->alloc), @@ -693,6 +383,16 @@ orc_compiler_powerpc_assemble (OrcCompiler *compiler) 0, powerpc_regnum(POWERPC_R0)); } + if (set_vscr) { + int tmp = POWERPC_V0; + + ORC_ASM_CODE(compiler," vspltisw %s, %d\n", + powerpc_get_regname(tmp), 0); + powerpc_emit_VX(compiler, 0x1000038c, + powerpc_regnum(tmp), 0, 0); + + powerpc_emit_VX_b(compiler, "mtvscr", 0x10000644, tmp); + } powerpc_emit_epilogue (compiler); powerpc_do_fixups (compiler); diff --git a/orc/orcrules-altivec.c b/orc/orcrules-altivec.c index 4f76c12..11a4679 100644 --- a/orc/orcrules-altivec.c +++ b/orc/orcrules-altivec.c @@ -20,6 +20,7 @@ powerpc_rule_loadpX (OrcCompiler *compiler, void *user, OrcInstruction *insn) { OrcVariable *src = compiler->vars + insn->src_args[0]; OrcVariable *dest = compiler->vars + insn->dest_args[0]; + int size = ORC_PTR_TO_INT(user); if (src->vartype == ORC_VAR_TYPE_PARAM) { int greg = compiler->gp_tmpreg; @@ -39,17 +40,9 @@ powerpc_rule_loadpX (OrcCompiler *compiler, void *user, OrcInstruction *insn) powerpc_emit_X (compiler, 0x7c00000c, powerpc_regnum(POWERPC_V0), 0, powerpc_regnum(greg)); - ORC_ASM_CODE(compiler," vperm %s, %s, %s, %s\n", - powerpc_get_regname (dest->alloc), - powerpc_get_regname (dest->alloc), - powerpc_get_regname (dest->alloc), - powerpc_get_regname (POWERPC_V0)); - powerpc_emit_VA (compiler, 4, - powerpc_regnum(dest->alloc), - powerpc_regnum(dest->alloc), - powerpc_regnum(dest->alloc), - powerpc_regnum(POWERPC_V0), 43); - switch (src->size) { + powerpc_emit_vperm (compiler, dest->alloc, dest->alloc, dest->alloc, + POWERPC_V0); + switch (size) { case 1: ORC_ASM_CODE(compiler," vspltb %s, %s, 3\n", powerpc_get_regname (dest->alloc), @@ -75,7 +68,7 @@ powerpc_rule_loadpX (OrcCompiler *compiler, void *user, OrcInstruction *insn) } else { int value = src->value; - switch (src->size) { + switch (size) { case 1: if (value < 16 && value >= -16) { ORC_ASM_CODE(compiler," vspltisb %s, %d\n", @@ -117,6 +110,7 @@ powerpc_rule_loadX (OrcCompiler *compiler, void *user, OrcInstruction *insn) OrcVariable *src = compiler->vars + insn->src_args[0]; OrcVariable *dest = compiler->vars + insn->dest_args[0]; int size = src->size << compiler->loop_shift; + int perm = orc_compiler_get_temp_reg (compiler); switch (size) { case 1: @@ -140,22 +134,25 @@ powerpc_rule_loadX (OrcCompiler *compiler, void *user, OrcInstruction *insn) powerpc_emit_X (compiler, 0x7c00008e, powerpc_regnum(dest->alloc), 0, powerpc_regnum(src->ptr_register)); break; + case 8: + case 16: + ORC_ASM_CODE(compiler," lvx %s, 0, %s\n", + powerpc_get_regname (dest->alloc), + powerpc_get_regname (src->ptr_register)); + powerpc_emit_X (compiler, 0x7c0000ce, powerpc_regnum(dest->alloc), + 0, powerpc_regnum(src->ptr_register)); + break; + default: + ORC_COMPILER_ERROR(compiler,"bad load size %d", + src->size << compiler->loop_shift); + break; } ORC_ASM_CODE(compiler," lvsl %s, 0, %s\n", - powerpc_get_regname (POWERPC_V0), + powerpc_get_regname (perm), powerpc_get_regname (src->ptr_register)); - powerpc_emit_X (compiler, 0x7c00000c, powerpc_regnum(POWERPC_V0), + powerpc_emit_X (compiler, 0x7c00000c, powerpc_regnum(perm), 0, powerpc_regnum(src->ptr_register)); - ORC_ASM_CODE(compiler," vperm %s, %s, %s, %s\n", - powerpc_get_regname (dest->alloc), - powerpc_get_regname (dest->alloc), - powerpc_get_regname (dest->alloc), - powerpc_get_regname (POWERPC_V0)); - powerpc_emit_VA (compiler, 4, - powerpc_regnum(dest->alloc), - powerpc_regnum(dest->alloc), - powerpc_regnum(dest->alloc), - powerpc_regnum(POWERPC_V0), 43); + powerpc_emit_vperm (compiler, dest->alloc, dest->alloc, dest->alloc, perm); } static void @@ -164,48 +161,74 @@ powerpc_rule_storeX (OrcCompiler *compiler, void *user, OrcInstruction *insn) OrcVariable *src = compiler->vars + insn->src_args[0]; OrcVariable *dest = compiler->vars + insn->dest_args[0]; int size = dest->size << compiler->loop_shift; + int perm = orc_compiler_get_temp_reg (compiler); + int tmp = orc_compiler_get_temp_reg (compiler); ORC_ASM_CODE(compiler," lvsr %s, 0, %s\n", - powerpc_get_regname (POWERPC_V0), + powerpc_get_regname (perm), powerpc_get_regname (dest->ptr_register)); - powerpc_emit_X (compiler, 0x7c00004c, powerpc_regnum(POWERPC_V0), + powerpc_emit_X (compiler, 0x7c00004c, powerpc_regnum(perm), 0, powerpc_regnum(dest->ptr_register)); - ORC_ASM_CODE(compiler," vperm %s, %s, %s, %s\n", - powerpc_get_regname (src->alloc), - powerpc_get_regname (src->alloc), - powerpc_get_regname (src->alloc), - powerpc_get_regname (POWERPC_V0)); - powerpc_emit_VA (compiler, 4, - powerpc_regnum(src->alloc), - powerpc_regnum(src->alloc), - powerpc_regnum(src->alloc), - powerpc_regnum(POWERPC_V0), 43); + + powerpc_emit_vperm (compiler, tmp, src->alloc, src->alloc, perm); switch (size) { case 1: ORC_ASM_CODE(compiler," stvebx %s, 0, %s\n", - powerpc_get_regname (src->alloc), + powerpc_get_regname (tmp), powerpc_get_regname (dest->ptr_register)); powerpc_emit_X (compiler, 0x7c00010e, - powerpc_regnum(src->alloc), + powerpc_regnum(tmp), 0, powerpc_regnum(dest->ptr_register)); break; case 2: ORC_ASM_CODE(compiler," stvehx %s, 0, %s\n", - powerpc_get_regname (src->alloc), + powerpc_get_regname (tmp), powerpc_get_regname (dest->ptr_register)); powerpc_emit_X (compiler, 0x7c00014e, - powerpc_regnum(src->alloc), + powerpc_regnum(tmp), 0, powerpc_regnum(dest->ptr_register)); break; case 4: ORC_ASM_CODE(compiler," stvewx %s, 0, %s\n", - powerpc_get_regname (src->alloc), + powerpc_get_regname (tmp), + powerpc_get_regname (dest->ptr_register)); + powerpc_emit_X (compiler, 0x7c00018e, + powerpc_regnum(tmp), + 0, powerpc_regnum(dest->ptr_register)); + break; + case 8: + ORC_ASM_CODE(compiler," stvewx %s, 0, %s\n", + powerpc_get_regname (tmp), + powerpc_get_regname (dest->ptr_register)); + powerpc_emit_X (compiler, 0x7c00018e, + powerpc_regnum(tmp), + 0, powerpc_regnum(dest->ptr_register)); + + powerpc_emit_D (compiler, "addi", 0x38000000, compiler->gp_tmpreg, + POWERPC_R0, 4); + + ORC_ASM_CODE(compiler," stvewx %s, %s, %s\n", + powerpc_get_regname (tmp), + powerpc_get_regname (compiler->gp_tmpreg), powerpc_get_regname (dest->ptr_register)); powerpc_emit_X (compiler, 0x7c00018e, - powerpc_regnum(src->alloc), + powerpc_regnum(tmp), + powerpc_regnum(compiler->gp_tmpreg), + powerpc_regnum(dest->ptr_register)); + break; + case 16: + ORC_ASM_CODE(compiler," stvx %s, 0, %s\n", + powerpc_get_regname (tmp), + powerpc_get_regname (dest->ptr_register)); + powerpc_emit_X (compiler, 0x7c0001ce, + powerpc_regnum(tmp), 0, powerpc_regnum(dest->ptr_register)); break; + default: + ORC_COMPILER_ERROR(compiler,"bad store size %d", + dest->size << compiler->loop_shift); + break; } } @@ -308,6 +331,12 @@ RULE(subssl, "vsubsws", 0x10000780) RULE(subusl, "vsubuws", 0x10000680) RULE(xorl, "vxor", 0x100004c4) +RULE(addf, "vaddfp", 0x1000000a) +RULE(subf, "vsubfp", 0x1000004a) +RULE(maxf, "vmaxfp", 0x1000040a) +RULE(minf, "vminfp", 0x1000044a) +RULE(cmpeqf, "vcmpeqfp", 0x100000c6) + static void powerpc_rule_andnX (OrcCompiler *p, void *user, OrcInstruction *insn) { @@ -636,11 +665,8 @@ powerpc_rule_select0wb (OrcCompiler *p, void *user, OrcInstruction *insn) { int src1 = ORC_SRC_ARG (p, insn, 0); int dest = ORC_DEST_ARG (p, insn, 0); - int perm; - perm = powerpc_get_constant_full (p, 0x00010405, 0x08090c0d, - 0x10111415, 0x18191c1d); - powerpc_emit_vperm (p, dest, src1, src1, perm); + powerpc_emit_vpkuhum (p, dest, src1, src1); } static void @@ -648,8 +674,11 @@ powerpc_rule_select1wb (OrcCompiler *p, void *user, OrcInstruction *insn) { int src1 = ORC_SRC_ARG (p, insn, 0); int dest = ORC_DEST_ARG (p, insn, 0); + int perm; - powerpc_emit_vpkuhum (p, dest, src1, src1); + perm = powerpc_get_constant_full (p, 0x00010405, 0x08090c0d, + 0x10111415, 0x18191c1d); + powerpc_emit_vperm (p, dest, src1, src1, perm); } static void @@ -657,10 +686,8 @@ powerpc_rule_select0lw (OrcCompiler *p, void *user, OrcInstruction *insn) { int src1 = ORC_SRC_ARG (p, insn, 0); int dest = ORC_DEST_ARG (p, insn, 0); - int perm; - perm = powerpc_get_constant_full (p, 0x00010405, 0x08090c0d, 0x10111415, 0x18191c1d); - powerpc_emit_vperm (p, dest, src1, src1, perm); + powerpc_emit_vpkuwum (p, dest, src1, src1); } static void @@ -668,8 +695,11 @@ powerpc_rule_select1lw (OrcCompiler *p, void *user, OrcInstruction *insn) { int src1 = ORC_SRC_ARG (p, insn, 0); int dest = ORC_DEST_ARG (p, insn, 0); + int perm; - powerpc_emit_vpkuwum (p, dest, src1, src1); + perm = powerpc_get_constant_full (p, 0x00010405, 0x08090c0d, + 0x10111415, 0x18191c1d); + powerpc_emit_vperm (p, dest, src1, src1, perm); } static void @@ -680,7 +710,8 @@ powerpc_rule_mergebw (OrcCompiler *p, void *user, OrcInstruction *insn) int dest = ORC_DEST_ARG (p, insn, 0); int perm; - perm = powerpc_get_constant_full (p, 0x00100111, 0x02120313, 0x04140515, 0x06160717); + perm = powerpc_get_constant_full (p, 0x10001101, 0x12021303, + 0x14041505, 0x16061707); powerpc_emit_vperm (p, dest, src1, src2, perm); } @@ -692,10 +723,316 @@ powerpc_rule_mergewl (OrcCompiler *p, void *user, OrcInstruction *insn) int dest = ORC_DEST_ARG (p, insn, 0); int perm; - perm = powerpc_get_constant_full (p, 0x00011011, 0x02031213, 0x04051415, 0x06071617); + perm = powerpc_get_constant_full (p, 0x10110001, 0x12130203, + 0x14150405, 0x16170607); powerpc_emit_vperm (p, dest, src1, src2, perm); } +static void +powerpc_rule_absb (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int tmpc; + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + int tmp; + + tmpc = powerpc_get_constant (p, ORC_CONST_SPLAT_B, 0); + if (src1 != dest) { + tmp = dest; + } else { + tmp = orc_compiler_get_temp_reg (p); + } + powerpc_emit_VX_2 (p, "vsububm", 0x10000400, tmp, tmpc, src1); + powerpc_emit_vminub (p, dest, tmp, src1); +} + +static void +powerpc_rule_absw (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int tmp; + int tmpc; + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + + tmpc = powerpc_get_constant (p, ORC_CONST_SPLAT_W, 0); + if (src1 != dest) { + tmp = dest; + } else { + tmp = orc_compiler_get_temp_reg (p); + } + powerpc_emit_VX_2 (p, "vsubuhm", 0x10000440, tmp, tmpc, src1); + powerpc_emit_VX_2 (p, "vminuh", 0x10000242, dest, tmp, src1); +} + +static void +powerpc_rule_absl (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int tmp; + int tmpc; + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + + tmpc = powerpc_get_constant (p, ORC_CONST_SPLAT_L, 0); + if (src1 != dest) { + tmp = dest; + } else { + tmp = orc_compiler_get_temp_reg (p); + } + powerpc_emit_VX_2 (p, "vsubuwm", 0x10000480, tmp, tmpc, src1); + powerpc_emit_VX_2 (p, "vminuw", 0x10000282, dest, tmp, src1); +} + +static void +powerpc_rule_splatw3q (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + int perm; + + perm = powerpc_get_constant_full (p, 0x00010001, 0x00010001, + 0x08090809, 0x08090809); + powerpc_emit_vperm (p, dest, src1, src1, perm); +} + +static void +powerpc_rule_splatbw (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + + powerpc_emit_VX_2 (p, "vmrghb", 0x1000000c, dest, src1, src1); +} + +static void +powerpc_rule_splatbl (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); +#if 0 + int perm; + + perm = powerpc_get_constant_full (p, 0x00000000, 0x01010101, + 0x02020202, 0x03030303); + powerpc_emit_vperm (p, dest, src1, src1, perm); +#else + powerpc_emit_VX_2 (p, "vmrghb", 0x1000000c, dest, src1, src1); + powerpc_emit_VX_2 (p, "vmrghh", 0x1000004c, dest, dest, dest); +#endif +} + +static void +powerpc_rule_convulq (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + int perm; + int zero; + + zero = powerpc_get_constant (p, ORC_CONST_SPLAT_B, 0); + perm = powerpc_get_constant_full (p, 0x10101010, 0x00010203, + 0x10101010, 0x04050607); + powerpc_emit_vperm (p, dest, src1, zero, perm); +} + +static void +powerpc_rule_convslq (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + int perm; + int tmp = orc_compiler_get_temp_reg (p); + + ORC_ASM_CODE(p," vspltisb %s, -1\n", powerpc_get_regname(tmp)); + powerpc_emit_VX(p, 0x1000030c, powerpc_regnum(tmp), 0x1f, 0); + + powerpc_emit_VX_2 (p, "vsraw", 0x10000384, tmp, src1, tmp); + + perm = powerpc_get_constant_full (p, 0x10101010, 0x00010203, + 0x10101010, 0x04050607); + powerpc_emit_vperm (p, dest, src1, tmp, perm); +} + +static void +powerpc_rule_convhwb (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + int perm; + + perm = powerpc_get_constant_full (p, 0x00020406, 0x080a0c0e, + 0x10121416, 0x181a1c1e); + powerpc_emit_vperm (p, dest, src1, src1, perm); +} + +static void +powerpc_rule_convhlw (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + int perm; + + perm = powerpc_get_constant_full (p, 0x00010405, 0x08090c0d, + 0x10111415, 0x18191c1d); + powerpc_emit_vperm (p, dest, src1, src1, perm); +} + +static void +powerpc_rule_convql (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + int perm; + + perm = powerpc_get_constant_full (p, 0x04050607, 0x0c0d0e0f, + 0x14151617, 0x1c1d1e1f); + powerpc_emit_vperm (p, dest, src1, src1, perm); +} + +static void +powerpc_rule_swapw (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + int perm; + + perm = powerpc_get_constant_full (p, 0x01000302, 0x05040706, + 0x09080b0a, 0x0d0c0f0e); + powerpc_emit_vperm (p, dest, src1, src1, perm); +} + +static void +powerpc_rule_swapl (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + int perm; + + perm = powerpc_get_constant_full (p, 0x03020100, 0x07060504, + 0x0b0a0908, 0x0f0e0d0c); + powerpc_emit_vperm (p, dest, src1, src1, perm); +} + +static void +powerpc_rule_splitlw (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest1 = ORC_DEST_ARG (p, insn, 0); + int dest2 = ORC_DEST_ARG (p, insn, 1); + int perm; + + powerpc_emit_vpkuwum (p, dest2, src1, src1); + perm = powerpc_get_constant_full (p, 0x00010405, 0x08090c0d, + 0x10111415, 0x18191c1d); + powerpc_emit_vperm (p, dest1, src1, src1, perm); +} + +static void +powerpc_rule_splitwb (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest1 = ORC_DEST_ARG (p, insn, 0); + int dest2 = ORC_DEST_ARG (p, insn, 1); + int perm; + + powerpc_emit_vpkuhum (p, dest2, src1, src1); + perm = powerpc_get_constant_full (p, 0x00020406, 0x080a0c0e, + 0x10121416, 0x181a1c1e); + powerpc_emit_vperm (p, dest1, src1, src1, perm); +} + +static void +powerpc_rule_mulf (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); + int tmp; + + tmp = powerpc_get_constant (p, ORC_CONST_SPLAT_L, 0x80000000); + powerpc_emit_VA_acb (p, "vmaddfp", 0x1000002e, dest, src1, tmp, src2); +} + +static void +powerpc_rule_divf (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); + int y = orc_compiler_get_temp_reg (p); + int t = orc_compiler_get_temp_reg (p); + int c1; + int c0; + + c1 = powerpc_get_constant (p, ORC_CONST_SPLAT_L, 0x3f800000); /* 1.0 */ + + powerpc_emit_VX_db (p, "vrefp", 0x1000010a, y, src2); + + powerpc_emit_VA_acb (p, "vnmsubfp", 0x1000002f, t, y, c1, src2); + powerpc_emit_VA_acb (p, "vmaddfp", 0x1000002e, y, y, y, t); + + c0 = powerpc_get_constant (p, ORC_CONST_SPLAT_L, 0x00000000); /* 0.0 */ + powerpc_emit_VA_acb (p, "vmaddfp", 0x1000002e, dest, y, c0, src1); +} + +static void +powerpc_rule_cmpltf (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); + + powerpc_emit_VXR (p, "vcmpgefp", 0x100001c6, dest, src2, src1, FALSE); +} + +static void +powerpc_rule_cmplef (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int src2 = ORC_SRC_ARG (p, insn, 1); + int dest = ORC_DEST_ARG (p, insn, 0); + + powerpc_emit_VXR (p, "vcmpgtfp", 0x100002c6, dest, src2, src1, FALSE); +} + +static void +powerpc_rule_convfl (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + + //powerpc_emit_VX_db (p, "vrfin", 0x1000020a, dest, src1); + powerpc_emit_VX_dbi (p, "vctsxs", 0x100003ca, dest, src1, 0); +} + +static void +powerpc_rule_convlf (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + + powerpc_emit_VX_dbi (p, "vcfsx", 0x1000034a, dest, src1, 0); +} + +static void +powerpc_rule_div255w (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + int tmp = orc_compiler_get_temp_reg (p); + int tmp2 = orc_compiler_get_temp_reg (p); + int tmpc; + + tmpc = powerpc_get_constant (p, ORC_CONST_SPLAT_W, 0x0080); + powerpc_emit_VX_2 (p, "vadduhm", 0x10000040, dest, src1, tmpc); + + ORC_ASM_CODE(p," vspltish %s, 8\n", powerpc_get_regname(tmp2)); + powerpc_emit_VX(p, 0x1000034c, powerpc_regnum(tmp2), 8, 0); + + powerpc_emit_VX_2 (p, "vsrw", 0x10000284, tmp, dest, tmp2); + powerpc_emit_VX_2 (p, "vadduhm", 0x10000040, dest, dest, tmp); + powerpc_emit_VX_2 (p, "vsrw", 0x10000284, dest, dest, tmp2); +} + void orc_compiler_powerpc_register_rules (OrcTarget *target) { @@ -802,22 +1139,53 @@ orc_compiler_powerpc_register_rules (OrcTarget *target) REG(signw); REG(signl); - if (0) REG(select0wb); - if (0) REG(select1wb); - if (0) REG(select0lw); - if (0) REG(select1lw); - if (0) REG(mergebw); - if (0) REG(mergewl); - - orc_rule_register (rule_set, "loadpb", powerpc_rule_loadpX, NULL); - orc_rule_register (rule_set, "loadpw", powerpc_rule_loadpX, NULL); - orc_rule_register (rule_set, "loadpl", powerpc_rule_loadpX, NULL); + REG(select0wb); + REG(select1wb); + REG(select0lw); + REG(select1lw); + REG(mergebw); + REG(mergewl); + + REG(absb); + REG(absw); + REG(absl); + REG(splatw3q); + REG(splatbw); + REG(splatbl); + REG(convslq); + REG(convulq); + REG(convhwb); + REG(convhlw); + REG(convql); + REG(swapw); + REG(swapl); + REG(splitlw); + REG(splitwb); + REG(div255w); + + REG(addf); + REG(subf); + REG(minf); + REG(maxf); + REG(cmpeqf); + REG(cmplef); + REG(cmpltf); + REG(mulf); + if (0) REG(divf); /* not accurate enough */ + REG(convfl); + REG(convlf); + + orc_rule_register (rule_set, "loadpb", powerpc_rule_loadpX, (void *)1); + orc_rule_register (rule_set, "loadpw", powerpc_rule_loadpX, (void *)2); + orc_rule_register (rule_set, "loadpl", powerpc_rule_loadpX, (void *)4); orc_rule_register (rule_set, "loadb", powerpc_rule_loadX, NULL); orc_rule_register (rule_set, "loadw", powerpc_rule_loadX, NULL); orc_rule_register (rule_set, "loadl", powerpc_rule_loadX, NULL); + orc_rule_register (rule_set, "loadq", powerpc_rule_loadX, NULL); orc_rule_register (rule_set, "storeb", powerpc_rule_storeX, NULL); orc_rule_register (rule_set, "storew", powerpc_rule_storeX, NULL); orc_rule_register (rule_set, "storel", powerpc_rule_storeX, NULL); + orc_rule_register (rule_set, "storeq", powerpc_rule_storeX, NULL); orc_rule_register (rule_set, "andnb", powerpc_rule_andnX, NULL); orc_rule_register (rule_set, "andnw", powerpc_rule_andnX, NULL); @@ -826,5 +1194,6 @@ orc_compiler_powerpc_register_rules (OrcTarget *target) orc_rule_register (rule_set, "copyb", powerpc_rule_copyX, NULL); orc_rule_register (rule_set, "copyw", powerpc_rule_copyX, NULL); orc_rule_register (rule_set, "copyl", powerpc_rule_copyX, NULL); + } -- 2.7.4