From cf92c727979e434d148b23d20f2e4e0f4bc4de61 Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 5 Feb 2007 15:00:07 -0700 Subject: Initial implementation of high-level flow-control instructions. IF/ELSE/ENDIF and BEGIN_LOOP/END_LOOP/BREAK instructions seem to work. Disabled by default though until better tested. Implemented IR_NOT, but needs optimization. --- src/mesa/shader/slang/slang_emit.c | 72 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) (limited to 'src/mesa/shader/slang/slang_emit.c') diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 756bbe9587..311eea1e6a 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -1005,6 +1005,42 @@ emit_cond(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) } +/** + * Logical-NOT + */ +static struct prog_instruction * +emit_not(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) +{ + GLfloat zero = 0.0; + slang_ir_storage st; + struct prog_instruction *inst; + + /* need zero constant */ + st.File = PROGRAM_CONSTANT; + st.Size = 1; + st.Index = _mesa_add_unnamed_constant(prog->Parameters, &zero, + 1, &st.Swizzle); + + /* child expr */ + (void) emit(vt, n->Children[0], prog); + /* XXXX if child instr is SGT convert to SLE, if SEQ, SNE, etc */ + + if (!n->Store) + if (!alloc_temp_storage(vt, n, n->Children[0]->Store->Size)) + return NULL; + + inst = new_instruction(prog, OPCODE_SEQ); + storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); + storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store); + storage_to_src_reg(&inst->SrcReg[1], &st); + + free_temp_storage(vt, n->Children[0]); + + return inst; +} + + + /** * Remove any SWIZZLE_NIL terms from given swizzle mask (smear prev term). * Ex: fix_swizzle("zyNN") -> "zyyy" @@ -1202,6 +1238,9 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) case IR_COND: return emit_cond(vt, n, prog); + case IR_NOT: + return emit_not(vt, n, prog); + case IR_LABEL: return emit_label(n->Target, prog); case IR_JUMP: @@ -1235,6 +1274,39 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) return inst; } + case IR_BEGIN_LOOP: + { + /* save location of this instruction, used by OPCODE_ENDLOOP */ + n->InstLocation = prog->NumInstructions; + (void) new_instruction(prog, OPCODE_BGNLOOP); + } + break; + case IR_END_LOOP: + { + struct prog_instruction *inst; + inst = new_instruction(prog, OPCODE_ENDLOOP); + assert(n->BranchNode); + assert(n->BranchNode->InstLocation >= 0); + /* The instruction BranchTarget points to top of loop */ + inst->BranchTarget = n->BranchNode->InstLocation; + return inst; + } + case IR_CONT: + return new_instruction(prog, OPCODE_CONT); + case IR_BREAK: + { + struct prog_instruction *inst; + inst = new_instruction(prog, OPCODE_BRK); + inst->DstReg.CondMask = COND_TR; /* always true */ + return inst; + } + case IR_BEGIN_SUB: + return new_instruction(prog, OPCODE_BGNSUB); + case IR_END_SUB: + return new_instruction(prog, OPCODE_ENDSUB); + case IR_RETURN: + return new_instruction(prog, OPCODE_RET); + default: _mesa_problem(NULL, "Unexpected IR opcode in emit()\n"); abort(); -- cgit v1.2.3