Initial implementation of OPCODE_IF/ELSE/ENDIF instructions.
This commit is contained in:
@@ -130,11 +130,14 @@ static const struct instruction_info InstInfo[MAX_OPCODE] = {
|
||||
{ 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 },
|
||||
|
||||
@@ -143,11 +143,14 @@ typedef enum prog_opcode {
|
||||
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 */
|
||||
|
||||
@@ -295,7 +295,7 @@ _mesa_print_instruction(const struct prog_instruction *inst)
|
||||
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));
|
||||
@@ -305,6 +305,18 @@ _mesa_print_instruction(const struct prog_instruction *inst)
|
||||
_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);
|
||||
|
||||
@@ -1560,6 +1560,51 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@@ -2314,7 +2359,13 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
|
||||
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:
|
||||
|
||||
@@ -91,6 +91,9 @@ static slang_ir_info IrInfo[] = {
|
||||
{ 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 },
|
||||
@@ -271,6 +274,18 @@ slang_print_ir(const slang_ir_node *n, int indent)
|
||||
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),
|
||||
@@ -862,6 +877,28 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
|
||||
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();
|
||||
|
||||
@@ -51,6 +51,9 @@ typedef enum
|
||||
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,
|
||||
|
||||
@@ -888,6 +888,73 @@ execute_program( GLcontext *ctx,
|
||||
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];
|
||||
|
||||
@@ -746,11 +746,14 @@ static void (* const opcode_func[MAX_OPCODE+3])(struct arb_vp_machine *, union i
|
||||
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*/
|
||||
|
||||
Reference in New Issue
Block a user