- GLuint src[3], dest = 0;
- int ip;
-
- if (fpi->Opcode != OPCODE_KIL) {
- dest = make_dest(cs, fpi->DstReg);
- }
-
- switch (fpi->Opcode) {
- case OPCODE_ADD:
- /* Variation on MAD: 1*src0+src1 */
- ip = emit_alu(cs, R500_ALU_RGBA_OP_MAD, R500_ALPHA_OP_MAD, fpi->DstReg);
- set_src0(cs, ip, fpi->SrcReg[0]);
- set_src1(cs, ip, fpi->SrcReg[1]);
- set_argA(cs, ip, 0, R500_SWIZ_RGB_ONE, R500_SWIZZLE_ONE);
- set_argB_reg(cs, ip, 0, fpi->SrcReg[0]);
- set_argC_reg(cs, ip, 1, fpi->SrcReg[1]);
- break;
- case OPCODE_CMP:
- /* This inst's selects need to be swapped as follows:
- * 0 -> C ; 1 -> B ; 2 -> A */
- ip = emit_alu(cs, R500_ALU_RGBA_OP_CMP, R500_ALPHA_OP_CMP, fpi->DstReg);
- set_src0(cs, ip, fpi->SrcReg[0]);
- set_src1(cs, ip, fpi->SrcReg[1]);
- set_src2(cs, ip, fpi->SrcReg[2]);
- set_argA_reg(cs, ip, 2, fpi->SrcReg[2]);
- set_argB_reg(cs, ip, 1, fpi->SrcReg[1]);
- set_argC_reg(cs, ip, 0, fpi->SrcReg[0]);
- break;
- case OPCODE_COS:
- emit_trig(cs, fpi);
- break;
- case OPCODE_DP3:
- ip = emit_alu(cs, R500_ALU_RGBA_OP_DP3, R500_ALPHA_OP_DP, fpi->DstReg);
- set_src0(cs, ip, fpi->SrcReg[0]);
- set_src1(cs, ip, fpi->SrcReg[1]);
- set_argA_reg(cs, ip, 0, fpi->SrcReg[0]);
- set_argB_reg(cs, ip, 1, fpi->SrcReg[1]);
- break;
- case OPCODE_DP4:
- ip = emit_alu(cs, R500_ALU_RGBA_OP_DP4, R500_ALPHA_OP_DP, fpi->DstReg);
- set_src0(cs, ip, fpi->SrcReg[0]);
- set_src1(cs, ip, fpi->SrcReg[1]);
- set_argA_reg(cs, ip, 0, fpi->SrcReg[0]);
- set_argB_reg(cs, ip, 1, fpi->SrcReg[1]);
- break;
- case OPCODE_DST:
- /* [1, src0.y*src1.y, src0.z, src1.w]
- * So basically MUL with lotsa swizzling. */
- ip = emit_alu(cs, R500_ALU_RGBA_OP_MAD, R500_ALPHA_OP_MAD, fpi->DstReg);
- set_src0(cs, ip, fpi->SrcReg[0]);
- set_src1(cs, ip, fpi->SrcReg[1]);
- set_argA(cs, ip, 0,
- (make_rgb_swizzle(fpi->SrcReg[0]) & ~0x7) | R500_SWIZZLE_ONE,
- R500_SWIZZLE_ONE);
- set_argB(cs, ip, 1,
- (make_rgb_swizzle(fpi->SrcReg[0]) & ~0x1c7) | R500_SWIZZLE_ONE | (R500_SWIZZLE_ONE << 6),
- make_alpha_swizzle(fpi->SrcReg[1]));
- set_argC(cs, ip, 0, R500_SWIZ_RGB_ZERO, R500_SWIZZLE_ZERO);
- break;
- case OPCODE_EX2:
- src[0] = make_src(cs, fpi->SrcReg[0]);
- emit_sop(cs, R500_ALPHA_OP_EX2, fpi->DstReg, src[0], make_sop_swizzle(fpi->SrcReg[0]));
- break;
- case OPCODE_FLR:
- dest = get_temp(cs, 0);
- ip = emit_alu_temp(cs, R500_ALU_RGBA_OP_FRC, R500_ALPHA_OP_FRC, dest, WRITEMASK_XYZW);
- set_src0(cs, ip, fpi->SrcReg[0]);
- set_argA_reg(cs, ip, 0, fpi->SrcReg[0]);
-
- ip = emit_alu(cs, R500_ALU_RGBA_OP_MAD, R500_ALPHA_OP_MAD, fpi->DstReg);
- set_src0(cs, ip, fpi->SrcReg[0]);
- set_src1_direct(cs, ip, dest);
- set_argA_reg(cs, ip, 0, fpi->SrcReg[1]);
- set_argB(cs, ip, 0, R500_SWIZ_RGB_ONE, R500_SWIZZLE_ONE);
- set_argC(cs, ip, 1,
- R500_SWIZ_RGB_RGB|(R500_SWIZ_MOD_NEG<<9),
- SWIZZLE_W|(R500_SWIZ_MOD_NEG<<3));
- break;
- case OPCODE_FRC:
- ip = emit_alu(cs, R500_ALU_RGBA_OP_FRC, R500_ALPHA_OP_FRC, fpi->DstReg);
- set_src0(cs, ip, fpi->SrcReg[0]);
- set_argA_reg(cs, ip, 0, fpi->SrcReg[0]);
- break;
- case OPCODE_LG2:
- src[0] = make_src(cs, fpi->SrcReg[0]);
- emit_sop(cs, R500_ALPHA_OP_LN2, fpi->DstReg, src[0], make_sop_swizzle(fpi->SrcReg[0]));
- break;
- case OPCODE_LIT:
- emit_lit(cs, fpi);
- break;
- case OPCODE_LRP:
- /* result = src0*src1 + (1-src0)*src2
- * = src0*src1 + src2 + (-src0)*src2
- *
- * Note: LRP without swizzling (or with only limited
- * swizzling) could be done more efficiently using the
- * presubtract hardware.
- */
- dest = get_temp(cs, 0);
- ip = emit_alu_temp(cs, R500_ALU_RGBA_OP_MAD, R500_ALPHA_OP_MAD, dest, WRITEMASK_XYZW);
- set_src0(cs, ip, fpi->SrcReg[0]);
- set_src1(cs, ip, fpi->SrcReg[1]);
- set_src2(cs, ip, fpi->SrcReg[2]);
- set_argA_reg(cs, ip, 0, fpi->SrcReg[0]);
- set_argB_reg(cs, ip, 1, fpi->SrcReg[1]);
- set_argC_reg(cs, ip, 2, fpi->SrcReg[2]);
-
- ip = emit_alu(cs, R500_ALU_RGBA_OP_MAD, R500_ALPHA_OP_MAD, fpi->DstReg);
- set_src0(cs, ip, fpi->SrcReg[0]);
- set_src1(cs, ip, fpi->SrcReg[2]);
- set_src2_direct(cs, ip, dest);
- set_argA(cs, ip, 0,
- make_rgb_swizzle(fpi->SrcReg[0]) ^ (R500_SWIZ_MOD_NEG<<9),
- make_alpha_swizzle(fpi->SrcReg[0]) ^ (R500_SWIZ_MOD_NEG<<3));
- set_argB_reg(cs, ip, 1, fpi->SrcReg[2]);
- set_argC(cs, ip, 2, R500_SWIZ_RGB_RGB, SWIZZLE_W);
- break;
- case OPCODE_MAD:
- ip = emit_alu(cs, R500_ALU_RGBA_OP_MAD, R500_ALPHA_OP_MAD, fpi->DstReg);
- set_src0(cs, ip, fpi->SrcReg[0]);
- set_src1(cs, ip, fpi->SrcReg[1]);
- set_src2(cs, ip, fpi->SrcReg[2]);
- set_argA_reg(cs, ip, 0, fpi->SrcReg[0]);
- set_argB_reg(cs, ip, 1, fpi->SrcReg[1]);
- set_argC_reg(cs, ip, 2, fpi->SrcReg[2]);
- break;
- case OPCODE_MAX:
- ip = emit_alu(cs, R500_ALU_RGBA_OP_MAX, R500_ALPHA_OP_MAX, fpi->DstReg);
- set_src0(cs, ip, fpi->SrcReg[0]);
- set_src1(cs, ip, fpi->SrcReg[1]);
- set_argA_reg(cs, ip, 0, fpi->SrcReg[0]);
- set_argB_reg(cs, ip, 1, fpi->SrcReg[1]);
- break;
- case OPCODE_MIN:
- ip = emit_alu(cs, R500_ALU_RGBA_OP_MIN, R500_ALPHA_OP_MIN, fpi->DstReg);
- set_src0(cs, ip, fpi->SrcReg[0]);
- set_src1(cs, ip, fpi->SrcReg[1]);
- set_argA_reg(cs, ip, 0, fpi->SrcReg[0]);
- set_argB_reg(cs, ip, 1, fpi->SrcReg[1]);
- break;
- case OPCODE_MOV:
- ip = emit_alu(cs, R500_ALU_RGBA_OP_CMP, R500_ALPHA_OP_CMP, fpi->DstReg);
- set_src0(cs, ip, fpi->SrcReg[0]);
- set_argA_reg(cs, ip, 0, fpi->SrcReg[0]);
- set_argB_reg(cs, ip, 0, fpi->SrcReg[0]);
- set_argC(cs, ip, 0, R500_SWIZ_RGB_ZERO, R500_SWIZZLE_ZERO);
- code->inst[ip].inst3 |= R500_ALU_RGB_OMOD_DISABLE;
- code->inst[ip].inst4 |= R500_ALPHA_OMOD_DISABLE;
- break;
- case OPCODE_MUL:
- /* Variation on MAD: src0*src1+0 */
- ip = emit_alu(cs, R500_ALU_RGBA_OP_MAD, R500_ALPHA_OP_MAD, fpi->DstReg);
- set_src0(cs, ip, fpi->SrcReg[0]);
- set_src1(cs, ip, fpi->SrcReg[1]);
- set_argA_reg(cs, ip, 0, fpi->SrcReg[0]);
- set_argB_reg(cs, ip, 1, fpi->SrcReg[1]);
- set_argC(cs, ip, 0, R500_SWIZ_RGB_ZERO, R500_SWIZZLE_ZERO);
- break;
- case OPCODE_RCP:
- src[0] = make_src(cs, fpi->SrcReg[0]);
- emit_sop(cs, R500_ALPHA_OP_RCP, fpi->DstReg, src[0], make_sop_swizzle(fpi->SrcReg[0]));
- break;
- case OPCODE_RSQ:
- src[0] = make_src(cs, fpi->SrcReg[0]);
- emit_sop(cs, R500_ALPHA_OP_RSQ, fpi->DstReg, src[0], make_sop_swizzle(fpi->SrcReg[0]));
- break;
- case OPCODE_SCS:
- emit_trig(cs, fpi);
- break;
- case OPCODE_SIN:
- emit_trig(cs, fpi);
- break;
- case OPCODE_KIL:
- case OPCODE_TEX:
- case OPCODE_TXB:
- case OPCODE_TXP:
- emit_tex(cs, fpi, dest);
- break;
- default:
- ERROR("unknown fpi->Opcode %s\n", _mesa_opcode_string(fpi->Opcode));
- break;
- }