Commit 59468fc9 authored by David Schleef's avatar David Schleef

altivec: Fix a bunch of bugs

parent 7e7a1e4b
......@@ -64,6 +64,35 @@ powerpc_emit(OrcCompiler *compiler, unsigned int insn)
*compiler->codeptr++ = (insn>>0);
}
void
powerpc_emit_add (OrcCompiler *compiler, int regd, int rega, int regb)
{
unsigned int insn;
ORC_ASM_CODE(compiler," add %s, %s, %s\n",
powerpc_get_regname(regd),
powerpc_get_regname(rega),
powerpc_get_regname(regb));
insn = 0x7c000214 | (powerpc_regnum (regd)<<21) | (powerpc_regnum (rega)<<16);
insn |= (powerpc_regnum (regb)<<11);
powerpc_emit (compiler, insn);
}
void
powerpc_emit_addi_rec (OrcCompiler *compiler, int regd, int rega, int imm)
{
unsigned int insn;
ORC_ASM_CODE(compiler," addic. %s, %s, %d\n",
powerpc_get_regname(regd),
powerpc_get_regname(rega), imm);
insn = 0x34000000 | (powerpc_regnum (regd)<<21) | (powerpc_regnum (rega)<<16);
insn |= imm&0xffff;
powerpc_emit (compiler, insn);
}
void
powerpc_emit_addi (OrcCompiler *compiler, int regd, int rega, int imm)
{
......@@ -92,6 +121,20 @@ powerpc_emit_lwz (OrcCompiler *compiler, int regd, int rega, int imm)
powerpc_emit (compiler, insn);
}
void
powerpc_emit_stw (OrcCompiler *compiler, int regs, int rega, int offset)
{
unsigned int insn;
ORC_ASM_CODE(compiler," stw %s, %d(%s)\n",
powerpc_get_regname(regs),
offset, powerpc_get_regname(rega));
insn = 0x90000000 | (powerpc_regnum (regs)<<21) | (powerpc_regnum (rega)<<16);
insn |= offset&0xffff;
powerpc_emit (compiler, insn);
}
void
powerpc_emit_stwu (OrcCompiler *compiler, int regs, int rega, int offset)
{
......@@ -202,6 +245,21 @@ powerpc_emit_VX_2 (OrcCompiler *p, const char *name,
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)
{
ORC_ASM_CODE(p," %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_VX(p, insn,
powerpc_regnum(d),
powerpc_regnum(a),
powerpc_regnum(b));
}
void
powerpc_emit_VX_3 (OrcCompiler *p, const char *name,
unsigned int insn, int d, int a, int b, int c)
......@@ -236,18 +294,21 @@ powerpc_do_fixups (OrcCompiler *compiler)
unsigned int insn;
for(i=0;i<compiler->n_fixups;i++){
if (compiler->fixups[i].type == 0) {
unsigned char *label = compiler->labels[compiler->fixups[i].label];
unsigned char *ptr = compiler->fixups[i].ptr;
unsigned char *label = compiler->labels[compiler->fixups[i].label];
unsigned char *ptr = compiler->fixups[i].ptr;
insn = *(unsigned int *)ptr;
*(unsigned int *)ptr = (insn&0xffff0000) | ((insn + (label-ptr))&0xffff);
} else {
unsigned char *label = compiler->labels[compiler->fixups[i].label];
unsigned char *ptr = compiler->fixups[i].ptr;
insn = *(unsigned int *)ptr;
insn = *(unsigned int *)ptr;
switch (compiler->fixups[i].type) {
case 0:
*(unsigned int *)ptr = (insn&0xffff0000) | ((insn + (label-ptr))&0xffff);
break;
case 1:
*(unsigned int *)ptr = (insn&0xffff0000) | ((insn + (label-compiler->program->code))&0xffff);
break;
case 2:
*(unsigned int *)ptr = (insn&0xfc000000) | ((insn + (label-ptr))&0x03ffffff);
break;
}
}
}
......@@ -426,6 +487,39 @@ powerpc_get_constant (OrcCompiler *p, int type, int value)
return reg;
}
int
powerpc_get_constant_full (OrcCompiler *p, int value0, int value1,
int value2, int value3)
{
int reg = p->tmpreg;
int i;
for(i=0;i<p->n_constants;i++){
#if 0
if (p->constants[i].type == type &&
p->constants[i].value == value) {
if (p->constants[i].alloc_reg != 0) {
return p->constants[i].alloc_reg;
}
break;
}
#endif
}
if (i == p->n_constants) {
p->n_constants++;
p->constants[i].type = ORC_CONST_FULL;
p->constants[i].full_value[0] = value0;
p->constants[i].full_value[1] = value1;
p->constants[i].full_value[2] = value2;
p->constants[i].full_value[3] = value3;
p->constants[i].alloc_reg = 0;
}
powerpc_load_constant (p, i, reg);
return reg;
}
void powerpc_emit_ret (OrcCompiler *compiler)
{
ORC_ASM_CODE(compiler," ret\n");
......@@ -439,6 +533,9 @@ powerpc_add_fixup (OrcCompiler *compiler, int type, unsigned char *ptr, int labe
compiler->fixups[compiler->n_fixups].label = label;
compiler->fixups[compiler->n_fixups].type = type;
compiler->n_fixups++;
if (compiler->n_fixups >= ORC_N_FIXUPS) {
ORC_ERROR("too many fixups");
}
}
void
......@@ -452,7 +549,7 @@ void powerpc_emit_b (OrcCompiler *compiler, int label)
ORC_ASM_CODE(compiler," b %d%c\n", label,
(compiler->labels[label]!=NULL) ? 'b' : 'f');
powerpc_add_fixup (compiler, 0, compiler->codeptr, label);
powerpc_add_fixup (compiler, 2, compiler->codeptr, label);
powerpc_emit (compiler, 0x48000000);
}
......
......@@ -76,8 +76,11 @@ int powerpc_regnum (int i);
void powerpc_emit(OrcCompiler *compiler, unsigned int insn);
void powerpc_emit_add (OrcCompiler *compiler, int regd, int rega, int regb);
void powerpc_emit_addi_rec (OrcCompiler *compiler, int regd, int rega, int imm);
void powerpc_emit_addi (OrcCompiler *compiler, int regd, int rega, int imm);
void powerpc_emit_lwz (OrcCompiler *compiler, int regd, int rega, int imm);
void powerpc_emit_stw (OrcCompiler *compiler, int regs, int rega, int offset);
void powerpc_emit_stwu (OrcCompiler *compiler, int regs, int rega, int offset);
void powerpc_emit_ret (OrcCompiler *compiler);
......@@ -105,9 +108,12 @@ 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,
int d, int a, int b, int c);
void powerpc_emit_VX_3_reg (OrcCompiler *p, const char *name, unsigned int insn,
int d, int a, int b, int c);
void powerpc_emit_VX_4 (OrcCompiler *p, const char *name, unsigned int insn,
int d, int a);
int powerpc_get_constant (OrcCompiler *p, int type, int value);
int powerpc_get_constant_full (OrcCompiler *p, int value0, int value1, int value2, int value3);
/* instructions */
#define powerpc_emit_vandc(p,a,b,c) powerpc_emit_VX_2 (p, "vandc", 0x10000444, a, b, c)
......@@ -153,7 +159,7 @@ int powerpc_get_constant (OrcCompiler *p, int type, int value);
#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 (p, "vperm", 0x1000002b, a, b, c, d)
#define powerpc_emit_vperm(p,a,b,c,d) powerpc_emit_VX_3_reg (p, "vperm", 0x1000002b, a, b, c, d)
#endif
......
......@@ -446,14 +446,39 @@ orc_compiler_powerpc_assemble (OrcCompiler *compiler)
OrcStaticOpcode *opcode;
//OrcVariable *args[10];
OrcRule *rule;
int label_outer_loop_start;
int label_loop_start;
int label_leave;
label_outer_loop_start = orc_compiler_label_new (compiler);
label_loop_start = orc_compiler_label_new (compiler);
label_leave = orc_compiler_label_new (compiler);
powerpc_emit_prologue (compiler);
if (compiler->program->is_2d) {
powerpc_emit_lwz (compiler, POWERPC_R0, POWERPC_R3,
(int)ORC_STRUCT_OFFSET(OrcExecutorAlt, m));
powerpc_emit_srawi (compiler, POWERPC_R0, POWERPC_R0,
compiler->loop_shift, 1);
powerpc_emit_beq (compiler, label_leave);
powerpc_emit_stw (compiler, POWERPC_R0, POWERPC_R3,
(int)ORC_STRUCT_OFFSET(OrcExecutorAlt, m_index));
}
powerpc_load_constants (compiler);
for(k=0;k<4;k++){
OrcVariable *var = &compiler->vars[ORC_VAR_A1 + k];
if (compiler->vars[ORC_VAR_A1 + k].name == NULL) continue;
//powerpc_emit_VX_2(p, "vxor", 0x100004c4, reg, reg, reg);
powerpc_emit_vxor (compiler, var->alloc, var->alloc, var->alloc);
}
powerpc_emit_label (compiler, label_outer_loop_start);
powerpc_emit_lwz (compiler, POWERPC_R0, POWERPC_R3,
(int)ORC_STRUCT_OFFSET(OrcExecutor, n));
powerpc_emit_srawi (compiler, POWERPC_R0, POWERPC_R0,
......@@ -464,8 +489,6 @@ orc_compiler_powerpc_assemble (OrcCompiler *compiler)
powerpc_emit (compiler, 0x7c0903a6);
ORC_ASM_CODE (compiler, " mtctr %s\n", powerpc_get_regname(POWERPC_R0));
powerpc_load_constants (compiler);
powerpc_emit_label (compiler, label_loop_start);
for(j=0;j<compiler->n_insns;j++){
......@@ -545,8 +568,91 @@ orc_compiler_powerpc_assemble (OrcCompiler *compiler)
}
powerpc_emit_bne (compiler, label_loop_start);
if (compiler->program->is_2d) {
powerpc_emit_lwz (compiler, POWERPC_R0, POWERPC_R3,
(int)ORC_STRUCT_OFFSET(OrcExecutorAlt, m_index));
powerpc_emit_addi_rec (compiler, POWERPC_R0, POWERPC_R0, -1);
powerpc_emit_beq (compiler, label_leave);
powerpc_emit_stw (compiler, POWERPC_R0, POWERPC_R3,
(int)ORC_STRUCT_OFFSET(OrcExecutorAlt, m_index));
for(k=0;k<ORC_N_VARIABLES;k++){
if (compiler->vars[k].name == NULL) continue;
if (compiler->vars[k].vartype == ORC_VAR_TYPE_SRC ||
compiler->vars[k].vartype == ORC_VAR_TYPE_DEST) {
if (compiler->vars[k].ptr_register) {
powerpc_emit_lwz (compiler,
compiler->vars[k].ptr_register,
POWERPC_R3,
(int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[k]));
powerpc_emit_lwz (compiler,
POWERPC_R0,
POWERPC_R3,
(int)ORC_STRUCT_OFFSET(OrcExecutorAlt, strides[k]));
powerpc_emit_add (compiler,
compiler->vars[k].ptr_register,
compiler->vars[k].ptr_register,
POWERPC_R0);
powerpc_emit_stw (compiler,
compiler->vars[k].ptr_register,
POWERPC_R3,
(int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[k]));
} else {
ORC_ASM_CODE(compiler,"ERROR\n");
}
}
}
powerpc_emit_b (compiler, label_outer_loop_start);
}
powerpc_emit_label (compiler, label_leave);
for(k=0;k<4;k++){
OrcVariable *var = &compiler->vars[ORC_VAR_A1 + k];
if (compiler->vars[ORC_VAR_A1 + k].name == NULL) continue;
powerpc_emit_addi (compiler,
POWERPC_R0,
POWERPC_R3,
(int)ORC_STRUCT_OFFSET(OrcExecutor, accumulators[k]));
if (var->size == 2) {
powerpc_emit_vxor (compiler,
POWERPC_V0, POWERPC_V0, POWERPC_V0);
powerpc_emit_VX_2 (compiler, "vsum4shs", 0x10000648,
POWERPC_V0, var->alloc, POWERPC_V0);
powerpc_emit_vor (compiler, var->alloc, POWERPC_V0, POWERPC_V0);
}
ORC_ASM_CODE(compiler," lvsr %s, 0, %s\n",
powerpc_get_regname (POWERPC_V0),
powerpc_get_regname (POWERPC_R0));
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);
ORC_ASM_CODE(compiler," stvewx %s, 0, %s\n",
powerpc_get_regname (var->alloc),
powerpc_get_regname (POWERPC_R0));
powerpc_emit_X (compiler, 0x7c00018e,
powerpc_regnum(var->alloc),
0, powerpc_regnum(POWERPC_R0));
}
powerpc_emit_epilogue (compiler);
powerpc_do_fixups (compiler);
......
......@@ -29,9 +29,9 @@ typedef void (*OrcExecutorFunc)(OrcExecutor *ex);
#define ORC_N_VARIABLES 64
#define ORC_N_ARRAYS 12
#define ORC_N_REGISTERS 20
#define ORC_N_FIXUPS 20
#define ORC_N_FIXUPS 40
#define ORC_N_CONSTANTS 20
#define ORC_N_LABELS 20
#define ORC_N_LABELS 40
#define ORC_GP_REG_BASE 32
#define ORC_VEC_REG_BASE 64
......@@ -145,6 +145,7 @@ enum {
ORC_CONST_SPLAT_B,
ORC_CONST_SPLAT_W,
ORC_CONST_SPLAT_L,
ORC_CONST_FULL
};
enum {
......
......@@ -350,6 +350,8 @@ powerpc_rule_muluwl (OrcCompiler *p, void *user, OrcInstruction *insn)
powerpc_emit_vmuleuh (p, dest, src1, src2);
}
#if 0
/* doesn't work */
static void
powerpc_rule_accw (OrcCompiler *p, void *user, OrcInstruction *insn)
{
......@@ -358,6 +360,7 @@ powerpc_rule_accw (OrcCompiler *p, void *user, OrcInstruction *insn)
powerpc_emit_vadduhm (p, dest, dest, src1);
}
#endif
static void
powerpc_rule_accl (OrcCompiler *p, void *user, OrcInstruction *insn)
......@@ -368,6 +371,8 @@ powerpc_rule_accl (OrcCompiler *p, void *user, OrcInstruction *insn)
powerpc_emit_vadduwm (p, dest, dest, src1);
}
#if 0
/* doesn't work */
static void
powerpc_rule_accsadubl (OrcCompiler *p, void *user, OrcInstruction *insn)
{
......@@ -382,6 +387,7 @@ powerpc_rule_accsadubl (OrcCompiler *p, void *user, OrcInstruction *insn)
powerpc_emit_vsububm (p, tmp1, tmp1, tmp2);
powerpc_emit_vsum4ubs (p, dest, dest, tmp1);
}
#endif
static void
powerpc_rule_signb (OrcCompiler *p, void *user, OrcInstruction *insn)
......@@ -422,12 +428,6 @@ powerpc_rule_signl (OrcCompiler *p, void *user, OrcInstruction *insn)
powerpc_emit_vmaxsw (p, dest, dest, reg);
}
static int
load_constant (OrcCompiler *compiler, int a, int b, int c, int d)
{
return 0;
}
static void
powerpc_rule_select0wb (OrcCompiler *p, void *user, OrcInstruction *insn)
{
......@@ -435,7 +435,8 @@ powerpc_rule_select0wb (OrcCompiler *p, void *user, OrcInstruction *insn)
int dest = ORC_DEST_ARG (p, insn, 0);
int perm;
perm = load_constant (p, 0x00010405, 0x08090c0d, 0x10111415, 0x18191c1d);
perm = powerpc_get_constant_full (p, 0x00010405, 0x08090c0d,
0x10111415, 0x18191c1d);
powerpc_emit_vperm (p, dest, src1, src1, perm);
}
......@@ -455,7 +456,7 @@ powerpc_rule_select0lw (OrcCompiler *p, void *user, OrcInstruction *insn)
int dest = ORC_DEST_ARG (p, insn, 0);
int perm;
perm = load_constant (p, 0x00020406, 0x080a0c0e, 0x10121416, 0x181a1c1e);
perm = powerpc_get_constant_full (p, 0x00010405, 0x08090c0d, 0x10111415, 0x18191c1d);
powerpc_emit_vperm (p, dest, src1, src1, perm);
}
......@@ -472,22 +473,24 @@ static void
powerpc_rule_mergebw (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 perm;
perm = load_constant (p, 0x00100111, 0x02120313, 0x04140515, 0x06160717);
powerpc_emit_vperm (p, dest, src1, src1, perm);
perm = powerpc_get_constant_full (p, 0x00100111, 0x02120313, 0x04140515, 0x06160717);
powerpc_emit_vperm (p, dest, src1, src2, perm);
}
static void
powerpc_rule_mergewl (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 perm;
perm = load_constant (p, 0x00011011, 0x02031213, 0x04051415, 0x06071617);
powerpc_emit_vperm (p, dest, src1, src1, perm);
perm = powerpc_get_constant_full (p, 0x00011011, 0x02031213, 0x04051415, 0x06071617);
powerpc_emit_vperm (p, dest, src1, src2, perm);
}
void
......@@ -588,9 +591,9 @@ orc_compiler_powerpc_register_rules (OrcTarget *target)
REG(mulswl);
REG(muluwl);
REG(accw);
//REG(accw);
REG(accl);
REG(accsadubl);
//REG(accsadubl);
REG(signb);
REG(signw);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment