Merge branch 'llvm-cliptest-viewport'
[mesa.git] / src / mesa / drivers / dri / r300 / compiler / r500_fragprog_emit.c
index 5612a4e5ccc63b50e4b4ea31cf6ea1811c7a7782..6f101c68eb68630f872a2d2b681b9cf0283b8693 100644 (file)
@@ -198,7 +198,7 @@ static void use_temporary(struct r500_fragment_program_code* code, unsigned int
                code->max_temp_idx = index;
 }
 
-static unsigned int use_source(struct r500_fragment_program_code* code, struct radeon_pair_instruction_source src)
+static unsigned int use_source(struct r500_fragment_program_code* code, struct rc_pair_instruction_source src)
 {
        if (src.File == RC_FILE_CONSTANT) {
                return src.Index | 0x100;
@@ -227,14 +227,15 @@ static void alu_nop(struct r300_fragment_program_compiler *c, int ip)
  */
 static void emit_paired(struct r300_fragment_program_compiler *c, struct rc_pair_instruction *inst)
 {
+       int ip;
        PROG_CODE;
 
-       if (code->inst_end >= 511) {
+       if (code->inst_end >= c->Base.max_alu_insts-1) {
                error("emit_alu: Too many instructions");
                return;
        }
 
-       int ip = ++code->inst_end;
+       ip = ++code->inst_end;
 
        /* Quirk: MDH/MDV (DDX/DDY) need a NOP on previous non-TEX instructions. */
        if (inst->RGB.Opcode == RC_OPCODE_DDX || inst->Alpha.Opcode == RC_OPCODE_DDX ||
@@ -250,7 +251,7 @@ static void emit_paired(struct r300_fragment_program_compiler *c, struct rc_pair
        if (inst->RGB.OutputWriteMask || inst->Alpha.OutputWriteMask || inst->Alpha.DepthWriteMask) {
                code->inst[ip].inst0 = R500_INST_TYPE_OUT;
                if (inst->WriteALUResult) {
-                       error("%s: cannot write output and ALU result at the same time");
+                       error("Cannot write output and ALU result at the same time");
                        return;
                }
        } else {
@@ -260,6 +261,9 @@ static void emit_paired(struct r300_fragment_program_compiler *c, struct rc_pair
 
        code->inst[ip].inst0 |= (inst->RGB.WriteMask << 11) | (inst->Alpha.WriteMask << 14);
        code->inst[ip].inst0 |= (inst->RGB.OutputWriteMask << 15) | (inst->Alpha.OutputWriteMask << 18);
+       if (inst->Nop) {
+               code->inst[ip].inst0 |= R500_INST_NOP;
+       }
        if (inst->Alpha.DepthWriteMask) {
                code->inst[ip].inst4 |= R500_ALPHA_W_OMASK;
                c->code->writes_depth = 1;
@@ -275,6 +279,40 @@ static void emit_paired(struct r300_fragment_program_compiler *c, struct rc_pair
        if (inst->Alpha.Saturate)
                code->inst[ip].inst0 |= R500_INST_ALPHA_CLAMP;
 
+       /* Set the presubtract operation. */
+       switch(inst->RGB.Src[RC_PAIR_PRESUB_SRC].Index) {
+               case RC_PRESUB_BIAS:
+                       code->inst[ip].inst1 |= R500_RGB_SRCP_OP_1_MINUS_2RGB0;
+                       break;
+               case RC_PRESUB_SUB:
+                       code->inst[ip].inst1 |= R500_RGB_SRCP_OP_RGB1_MINUS_RGB0;
+                       break;
+               case RC_PRESUB_ADD:
+                       code->inst[ip].inst1 |= R500_RGB_SRCP_OP_RGB1_PLUS_RGB0;
+                       break;
+               case RC_PRESUB_INV:
+                       code->inst[ip].inst1 |= R500_RGB_SRCP_OP_1_MINUS_RGB0;
+                       break;
+               default:
+                       break;
+       }
+       switch(inst->Alpha.Src[RC_PAIR_PRESUB_SRC].Index) {
+               case RC_PRESUB_BIAS:
+                       code->inst[ip].inst2 |= R500_ALPHA_SRCP_OP_1_MINUS_2A0;
+                       break;
+               case RC_PRESUB_SUB:
+                       code->inst[ip].inst2 |= R500_ALPHA_SRCP_OP_A1_MINUS_A0;
+                       break;
+               case RC_PRESUB_ADD:
+                       code->inst[ip].inst2 |= R500_ALPHA_SRCP_OP_A1_PLUS_A0;
+                       break;
+               case RC_PRESUB_INV:
+                       code->inst[ip].inst2 |= R500_ALPHA_SRCP_OP_1_MINUS_A0;
+                       break;
+               default:
+                       break;
+       }
+
        code->inst[ip].inst1 |= R500_RGB_ADDR0(use_source(code, inst->RGB.Src[0]));
        code->inst[ip].inst1 |= R500_RGB_ADDR1(use_source(code, inst->RGB.Src[1]));
        code->inst[ip].inst1 |= R500_RGB_ADDR2(use_source(code, inst->RGB.Src[2]));
@@ -320,14 +358,15 @@ static unsigned int translate_strq_swizzle(unsigned int swizzle)
  */
 static int emit_tex(struct r300_fragment_program_compiler *c, struct rc_sub_instruction *inst)
 {
+       int ip;
        PROG_CODE;
 
-       if (code->inst_end >= 511) {
+       if (code->inst_end >= c->Base.max_alu_insts-1) {
                error("emit_tex: Too many instructions");
                return 0;
        }
 
-       int ip = ++code->inst_end;
+       ip = ++code->inst_end;
 
        code->inst[ip].inst0 = R500_INST_TYPE_TEX
                | (inst->DstReg.WriteMask << 11)
@@ -370,12 +409,14 @@ static int emit_tex(struct r300_fragment_program_compiler *c, struct rc_sub_inst
 
 static void emit_flowcontrol(struct emit_state * s, struct rc_instruction * inst)
 {
-       if (s->Code->inst_end >= 511) {
+       unsigned int newip;
+
+       if (s->Code->inst_end >= s->C->max_alu_insts-1) {
                rc_error(s->C, "emit_tex: Too many instructions");
                return;
        }
 
-       unsigned int newip = ++s->Code->inst_end;
+       newip = ++s->Code->inst_end;
 
        /* Currently all loops use the same integer constant to intialize
         * the loop variables. */
@@ -546,8 +587,9 @@ static void emit_flowcontrol(struct emit_state * s, struct rc_instruction * inst
        }
 }
 
-void r500BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compiler)
+void r500BuildFragmentProgramHwCode(struct radeon_compiler *c, void *user)
 {
+       struct r300_fragment_program_compiler *compiler = (struct r300_fragment_program_compiler*)c;
        struct emit_state s;
        struct r500_fragment_program_code *code = &compiler->code->code.r500;
 
@@ -577,7 +619,7 @@ void r500BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compi
                }
        }
 
-       if (code->max_temp_idx >= 128)
+       if (code->max_temp_idx >= compiler->Base.max_temp_regs)
                rc_error(&compiler->Base, "Too many hardware temporaries used");
 
        if (compiler->Base.Error)
@@ -585,14 +627,16 @@ void r500BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compi
 
        if (code->inst_end == -1 ||
            (code->inst[code->inst_end].inst0 & R500_INST_TYPE_MASK) != R500_INST_TYPE_OUT) {
+               int ip;
+
                /* This may happen when dead-code elimination is disabled or
                 * when most of the fragment program logic is leading to a KIL */
-               if (code->inst_end >= 511) {
+               if (code->inst_end >= compiler->Base.max_alu_insts-1) {
                        rc_error(&compiler->Base, "Introducing fake OUT: Too many instructions");
                        return;
                }
 
-               int ip = ++code->inst_end;
+               ip = ++code->inst_end;
                code->inst[ip].inst0 = R500_INST_TYPE_OUT | R500_INST_TEX_SEM_WAIT;
        }