summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Schleef <ds@wendolyne.(none)>2010-08-25 03:25:14 -0700
committerDavid Schleef <ds@wendolyne.(none)>2010-08-25 03:25:14 -0700
commit5e8a6257da92f90898f8a8c553124ecda50d3171 (patch)
tree0466a700f043f737944cf4931480ea677cba3b56
parent9efe6267870dd10b7924aae8492954f190dd5273 (diff)
altivec: Implement lots more rules
-rw-r--r--orc/orcpowerpc.c118
-rw-r--r--orc/orcpowerpc.h19
-rw-r--r--orc/orcprogram-altivec.c382
-rw-r--r--orc/orcrules-altivec.c495
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;i<size;i+=cache_line_size) {
__asm__ __volatile__ ("icbi %0,%1" :: "r" (ptr), "r" (i));
}
@@ -344,46 +402,40 @@ powerpc_load_constant (OrcCompiler *p, int i, int reg)
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;
+ 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;i<p->n_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;i<ORC_N_COMPILER_VARIABLES;i++){
var = compiler->vars + 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;i<compiler->n_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;i<ORC_N_COMPILER_VARIABLES;i++){
- var = compiler->vars + 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;j<compiler->n_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);
+
}