{ OPCODE_DP4, "DP4", 2 },
{ OPCODE_DPH, "DPH", 2 },
{ OPCODE_DST, "DST", 2 },
+ { OPCODE_ELSE, "ELSE", 0 },
{ OPCODE_END, "END", 0 },
+ { OPCODE_ENDIF, "ENDIF", 0 },
{ OPCODE_EX2, "EX2", 1 },
{ OPCODE_EXP, "EXP", 1 },
{ OPCODE_FLR, "FLR", 1 },
{ OPCODE_FRC, "FRC", 1 },
+ { OPCODE_IF, "IF", 0 },
{ OPCODE_INT, "INT", 1 },
{ OPCODE_KIL, "KIL", 1 },
{ OPCODE_KIL_NV, "KIL", 0 },
OPCODE_DP4, /* X X X X */
OPCODE_DPH, /* X X 1.1 */
OPCODE_DST, /* X X X X */
+ OPCODE_ELSE,
OPCODE_END, /* X X X X */
+ OPCODE_ENDIF,
OPCODE_EX2, /* X X 2 X */
OPCODE_EXP, /* X X */
OPCODE_FLR, /* X X 2 X */
OPCODE_FRC, /* X X 2 X */
+ OPCODE_IF,
OPCODE_INT, /* */
OPCODE_KIL, /* X */
OPCODE_KIL_NV, /* X */
print_comment(inst);
break;
case OPCODE_BRA:
- _mesa_printf("BRA %u (%s.%s)",
+ _mesa_printf("BRA %u (%s%s)",
inst->BranchTarget,
condcode_string(inst->DstReg.CondMask),
swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE));
_mesa_printf("CAL %u", inst->BranchTarget);
print_comment(inst);
break;
+ case OPCODE_IF:
+ _mesa_printf(" IF (%s%s)",
+ condcode_string(inst->DstReg.CondMask),
+ swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE));
+ print_comment(inst);
+ break;
+ case OPCODE_ELSE:
+ _mesa_printf(" ELSE;\n");
+ break;
+ case OPCODE_ENDIF:
+ _mesa_printf(" ENDIF;\n");
+ break;
case OPCODE_END:
_mesa_printf("END");
print_comment(inst);
}
+/**
+ * Use high-level IF/ELSE/ENDIF instructions
+ */
+static slang_ir_node *
+_slang_gen_if2(slang_assemble_ctx * A, const slang_operation *oper)
+{
+ /*
+ * eval expr (child[0]), updating condcodes
+ * branch if false to _else or _endif
+ * "true" code block
+ * if haveElseClause clause:
+ * jump "__endif"
+ * label "__else"
+ * "false" code block
+ * label "__endif"
+ */
+ const GLboolean haveElseClause = !_slang_is_noop(&oper->children[2]);
+ slang_ir_node *ifNode, *cond, *trueBody, *elseNode, *falseBody, *endifNode;
+ slang_ir_node *tree;
+
+ cond = _slang_gen_operation(A, &oper->children[0]);
+ cond = _slang_gen_cond(cond);
+ /*assert(cond->Store);*/
+ ifNode = new_node(IR_IF, cond, NULL);
+
+ trueBody = _slang_gen_operation(A, &oper->children[1]);
+ tree = new_seq(ifNode, trueBody);
+
+ if (haveElseClause) {
+ /* else clause */
+ elseNode = new_node(IR_ELSE, NULL, NULL);
+ tree = new_seq(tree, elseNode);
+
+ falseBody = _slang_gen_operation(A, &oper->children[2]);
+ tree = new_seq(tree, falseBody);
+ }
+
+ endifNode = new_node(IR_ENDIF, NULL, NULL);
+ tree = new_seq(tree, endifNode);
+
+ return tree;
+}
+
+
+
/**
* Generate IR node for storage of a temporary of given size.
*/
case slang_oper_identifier:
return _slang_gen_variable(A, oper);
case slang_oper_if:
- return _slang_gen_if(A, oper);
+ if (A->program->Target == GL_FRAGMENT_PROGRAM_ARB) {
+ return _slang_gen_if(A, oper);
+ }
+ else {
+ /* XXX update tnl executor */
+ return _slang_gen_if(A, oper);
+ }
case slang_oper_field:
return _slang_gen_field(A, oper);
case slang_oper_subscript:
{ IR_JUMP, "IR_JUMP", 0, 0, 0 },
{ IR_CJUMP0, "IR_CJUMP0", 0, 0, 0 },
{ IR_CJUMP1, "IR_CJUMP1", 0, 0, 0 },
+ { IR_IF, "IR_IF", 0, 0, 0 },
+ { IR_ELSE, "IR_ELSE", 0, 0, 0 },
+ { IR_ENDIF, "IR_ENDIF", 0, 0, 0 },
{ IR_KILL, "IR_KILL", 0, 0, 0 },
{ IR_COND, "IR_COND", 0, 0, 0 },
{ IR_CALL, "IR_CALL", 0, 0, 0 },
printf("CJUMP1 %s\n", n->Target);
slang_print_ir(n->Children[0], indent+3);
break;
+
+ case IR_IF:
+ printf("IF \n");
+ slang_print_ir(n->Children[0], indent+3);
+ break;
+ case IR_ELSE:
+ printf("ELSE\n");
+ break;
+ case IR_ENDIF:
+ printf("ENDIF\n");
+ break;
+
case IR_VAR:
printf("VAR %s%s at %s store %p\n",
(char *) n->Var->a_name, swizzle_string(n->Store->Swizzle),
case IR_KILL:
return emit_kill(prog);
+ case IR_IF:
+ {
+ struct prog_instruction *inst;
+ emit(vt, n->Children[0], prog); /* the condition */
+ inst = new_instruction(prog, OPCODE_IF);
+ inst->DstReg.CondMask = COND_NE; /* if cond is non-zero */
+ inst->DstReg.CondSwizzle = SWIZZLE_X;
+ return inst;
+ }
+ case IR_ELSE:
+ {
+ struct prog_instruction *inst;
+ inst = new_instruction(prog, OPCODE_ELSE);
+ return inst;
+ }
+ case IR_ENDIF:
+ {
+ struct prog_instruction *inst;
+ inst = new_instruction(prog, OPCODE_ENDIF);
+ return inst;
+ }
+
default:
_mesa_problem(NULL, "Unexpected IR opcode in emit()\n");
abort();
IR_CJUMP0, /* conditional jump if zero */
IR_CJUMP1, /* conditional jump if one (or non-zero) */
IR_COND, /* conditional expression */
+ IR_IF, /* high-level IF */
+ IR_ELSE, /* high-level ELSE */
+ IR_ENDIF, /* high-level ENDIF */
IR_CALL, /* call subroutine */
IR_MOVE,
IR_ADD,
store_vector4( inst, machine, result );
}
break;
+ case OPCODE_IF:
+ {
+ const GLuint swizzle = inst->DstReg.CondSwizzle;
+ const GLuint condMask = inst->DstReg.CondMask;
+ if (test_cc(machine->CondCodes[GET_SWZ(swizzle, 0)], condMask) ||
+ test_cc(machine->CondCodes[GET_SWZ(swizzle, 1)], condMask) ||
+ test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
+ test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
+ /* do if-clause (just continue execution) */
+ }
+ else {
+ /* do else-clause, or go to endif */
+ GLint ifDepth = 1;
+ do {
+ pc++;
+ inst = program->Base.Instructions + pc;
+ if (inst->Opcode == OPCODE_END) {
+ /* mal-formed program! */
+ abort();
+ }
+ else if (inst->Opcode == OPCODE_IF) {
+ ifDepth++;
+ }
+ else if (inst->Opcode == OPCODE_ELSE) {
+ if (ifDepth == 0) {
+ /* ok, continue normal execution */
+ break;
+ }
+ }
+ else if (inst->Opcode == OPCODE_ENDIF) {
+ ifDepth--;
+ if (ifDepth == 0) {
+ /* ok, continue normal execution */
+ break;
+ }
+ }
+ assert(ifDepth >= 0);
+ } while (pc < maxInst);
+ }
+ }
+ break;
+ case OPCODE_ELSE:
+ {
+ /* find/goto ENDIF */
+ GLint ifDepth = 1;
+ do {
+ pc++;
+ inst = program->Base.Instructions + pc;
+ if (inst->Opcode == OPCODE_END) {
+ /* mal-formed program! */
+ abort();
+ }
+ else if (inst->Opcode == OPCODE_IF) {
+ ifDepth++;
+ }
+ else if (inst->Opcode == OPCODE_ENDIF) {
+ ifDepth--;
+ if (ifDepth == 0)
+ break;
+ }
+ assert(ifDepth >= 0);
+ } while (pc < maxInst);
+ }
+ break;
+ case OPCODE_ENDIF:
+ /* nothing */
+ break;
case OPCODE_INT: /* float to int */
{
GLfloat a[4], result[4];
do_DP4,
do_DPH,
do_DST,
- do_NOP,
+ do_NOP,/*ELSE*/
+ do_NOP,/*END*/
+ do_NOP,/*ENDIF*/
do_EX2,
do_EXP,
do_FLR,
do_FRC,
+ do_NOP,/*IF*/
do_INT,
do_NOP,/*KIL*/
do_NOP,/*KIL_NV*/