gallium: added PPC support for SWZ, XPD, POW

That's the last of the ARB_v_p opcodes, except for ARL.
This commit is contained in:
Brian Paul 2008-10-29 11:05:34 -06:00
parent 75b92764a7
commit 4e1c33700d

View file

@ -610,6 +610,7 @@ emit_unaryop(struct gen_context *gen, struct tgsi_full_instruction *inst)
ppc_vlogefp(gen->f, v1, v0); /* v1 = log2(v0) */
break;
case TGSI_OPCODE_MOV:
case TGSI_OPCODE_SWZ:
if (v0 != v1)
ppc_vmove(gen->f, v1, v0);
break;
@ -1000,12 +1001,91 @@ emit_log(struct gen_context *gen, struct tgsi_full_instruction *inst)
}
static void
emit_pow(struct gen_context *gen, struct tgsi_full_instruction *inst)
{
int s0_vec = get_src_vec(gen, inst, 0, CHAN_X);
int s1_vec = get_src_vec(gen, inst, 1, CHAN_X);
int pow_vec = ppc_allocate_vec_register(gen->f);
int chan;
ppc_vec_pow(gen->f, pow_vec, s0_vec, s1_vec);
FOR_EACH_DST0_ENABLED_CHANNEL(*inst, chan) {
emit_store(gen, pow_vec, inst, chan, FALSE);
}
ppc_release_vec_register(gen->f, pow_vec);
release_src_vecs(gen);
}
static void
emit_xpd(struct gen_context *gen, struct tgsi_full_instruction *inst)
{
int x0_vec, y0_vec, z0_vec;
int x1_vec, y1_vec, z1_vec;
int zero_vec, tmp_vec;
int tmp2_vec;
zero_vec = ppc_allocate_vec_register(gen->f);
ppc_vzero(gen->f, zero_vec);
tmp_vec = ppc_allocate_vec_register(gen->f);
tmp2_vec = ppc_allocate_vec_register(gen->f);
if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Y) ||
IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Z)) {
x0_vec = get_src_vec(gen, inst, 0, CHAN_X);
x1_vec = get_src_vec(gen, inst, 1, CHAN_X);
}
if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_X) ||
IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Z)) {
y0_vec = get_src_vec(gen, inst, 0, CHAN_Y);
y1_vec = get_src_vec(gen, inst, 1, CHAN_Y);
}
if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_X) ||
IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Y)) {
z0_vec = get_src_vec(gen, inst, 0, CHAN_Z);
z1_vec = get_src_vec(gen, inst, 1, CHAN_Z);
}
IF_IS_DST0_CHANNEL_ENABLED(*inst, CHAN_X) {
/* tmp = y0 * z1 */
ppc_vmaddfp(gen->f, tmp_vec, y0_vec, z1_vec, zero_vec);
/* tmp = tmp - z0 * y1*/
ppc_vnmsubfp(gen->f, tmp_vec, tmp_vec, z0_vec, y1_vec);
emit_store(gen, tmp_vec, inst, CHAN_X, FALSE);
}
IF_IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Y) {
/* tmp = z0 * x1 */
ppc_vmaddfp(gen->f, tmp_vec, z0_vec, x1_vec, zero_vec);
/* tmp = tmp - x0 * z1 */
ppc_vnmsubfp(gen->f, tmp_vec, tmp_vec, x0_vec, z1_vec);
emit_store(gen, tmp_vec, inst, CHAN_Y, FALSE);
}
IF_IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Z) {
/* tmp = x0 * y1 */
ppc_vmaddfp(gen->f, tmp_vec, x0_vec, y1_vec, zero_vec);
/* tmp = tmp - y0 * x1 */
ppc_vnmsubfp(gen->f, tmp_vec, tmp_vec, y0_vec, x1_vec);
emit_store(gen, tmp_vec, inst, CHAN_Z, FALSE);
}
/* W is undefined */
ppc_release_vec_register(gen->f, tmp_vec);
ppc_release_vec_register(gen->f, zero_vec);
release_src_vecs(gen);
}
static int
emit_instruction(struct gen_context *gen,
struct tgsi_full_instruction *inst)
{
switch (inst->Instruction.Opcode) {
case TGSI_OPCODE_MOV:
case TGSI_OPCODE_SWZ:
case TGSI_OPCODE_ABS:
case TGSI_OPCODE_FLOOR:
case TGSI_OPCODE_FRAC:
@ -1050,6 +1130,12 @@ emit_instruction(struct gen_context *gen,
case TGSI_OPCODE_EXP:
emit_exp(gen, inst);
break;
case TGSI_OPCODE_POW:
emit_pow(gen, inst);
break;
case TGSI_OPCODE_XPD:
emit_xpd(gen, inst);
break;
case TGSI_OPCODE_END:
/* normal end */
return 1;