r600g: fix up vs export handling
[mesa.git] / src / gallium / drivers / r600 / r600_shader.c
index 0995dd5a99bda690065d51813c486b5f2c6ebedd..fc56656f55d034340315824f3eacac0e3810e584 100644 (file)
@@ -99,14 +99,14 @@ static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *s
        /* build state */
        switch (rshader->processor_type) {
        case TGSI_PROCESSOR_VERTEX:
-               if (rshader->family >= CHIP_CEDAR) {
+               if (rctx->chip_class >= EVERGREEN) {
                        evergreen_pipe_shader_vs(ctx, shader);
                } else {
                        r600_pipe_shader_vs(ctx, shader);
                }
                break;
        case TGSI_PROCESSOR_FRAGMENT:
-               if (rshader->family >= CHIP_CEDAR) {
+               if (rctx->chip_class >= EVERGREEN) {
                        evergreen_pipe_shader_ps(ctx, shader);
                } else {
                        r600_pipe_shader_ps(ctx, shader);
@@ -118,9 +118,9 @@ static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *s
        return 0;
 }
 
-static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader);
+static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct r600_pipe_shader *pipeshader);
 
-int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *shader, const struct tgsi_token *tokens)
+int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *shader)
 {
        static int dump_shaders = -1;
        struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
@@ -133,10 +133,9 @@ int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *s
 
        if (dump_shaders) {
                fprintf(stderr, "--------------------------------------------------------------\n");
-               tgsi_dump(tokens, 0);
+               tgsi_dump(shader->tokens, 0);
        }
-       shader->shader.family = r600_get_family(rctx->radeon);
-       r = r600_shader_from_tgsi(tokens, &shader->shader);
+       r = r600_shader_from_tgsi(rctx, shader);
        if (r) {
                R600_ERR("translation from TGSI failed !\n");
                return r;
@@ -159,6 +158,8 @@ void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader
 
        r600_bo_reference(rctx->radeon, &shader->bo, NULL);
        r600_bc_clear(&shader->shader.bc);
+
+       memset(&shader->shader,0,sizeof(struct r600_shader));
 }
 
 /*
@@ -315,7 +316,7 @@ static int tgsi_declaration(struct r600_shader_ctx *ctx)
                ctx->shader->input[i].interpolate = d->Declaration.Interpolate;
                ctx->shader->input[i].centroid = d->Declaration.Centroid;
                ctx->shader->input[i].gpr = ctx->file_offset[TGSI_FILE_INPUT] + i;
-               if (ctx->type == TGSI_PROCESSOR_FRAGMENT && ctx->bc->chiprev >= CHIPREV_EVERGREEN) {
+               if (ctx->type == TGSI_PROCESSOR_FRAGMENT && ctx->bc->chip_class >= EVERGREEN) {
                        /* turn input into interpolate on EG */
                        if (ctx->shader->input[i].name != TGSI_SEMANTIC_POSITION) {
                                if (ctx->shader->input[i].interpolate > 0) {
@@ -331,6 +332,12 @@ static int tgsi_declaration(struct r600_shader_ctx *ctx)
                ctx->shader->output[i].sid = d->Semantic.Index;
                ctx->shader->output[i].gpr = ctx->file_offset[TGSI_FILE_OUTPUT] + i;
                ctx->shader->output[i].interpolate = d->Declaration.Interpolate;
+               if (ctx->type == TGSI_PROCESSOR_VERTEX) {
+                       /* these don't count as vertex param exports */
+                       if ((ctx->shader->output[i].name == TGSI_SEMANTIC_POSITION) ||
+                           (ctx->shader->output[i].name == TGSI_SEMANTIC_PSIZE))
+                               ctx->shader->npos++;
+               }
                break;
        case TGSI_FILE_CONSTANT:
        case TGSI_FILE_TEMPORARY:
@@ -594,21 +601,21 @@ static int tgsi_split_literal_constant(struct r600_shader_ctx *ctx)
        return 0;
 }
 
-static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader)
+static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct r600_pipe_shader *pipeshader)
 {
+       struct r600_shader *shader = &pipeshader->shader;
+       struct tgsi_token *tokens = pipeshader->tokens;
        struct tgsi_full_immediate *immediate;
        struct tgsi_full_property *property;
        struct r600_shader_ctx ctx;
        struct r600_bc_output output[32];
        unsigned output_done, noutput;
        unsigned opcode;
-       int i, r = 0, pos0;
+       int i, j, r = 0, pos0;
 
        ctx.bc = &shader->bc;
        ctx.shader = shader;
-       r = r600_bc_init(ctx.bc, shader->family);
-       if (r)
-               return r;
+       r600_bc_init(ctx.bc, rctx->chip_class);
        ctx.tokens = tokens;
        tgsi_scan_shader(tokens, &ctx.info);
        tgsi_parse_init(&ctx.parse, tokens);
@@ -616,6 +623,11 @@ static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_sh
        shader->processor_type = ctx.type;
        ctx.bc->type = shader->processor_type;
 
+       shader->clamp_color = (((ctx.type == TGSI_PROCESSOR_FRAGMENT) && rctx->clamp_fragment_color) ||
+               ((ctx.type == TGSI_PROCESSOR_VERTEX) && rctx->clamp_vertex_color));
+
+       shader->nr_cbufs = rctx->nr_cbufs;
+
        /* register allocations */
        /* Values [0,127] correspond to GPR[0..127].
         * Values [128,159] correspond to constant buffer bank 0
@@ -642,19 +654,19 @@ static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_sh
        }
        if (ctx.type == TGSI_PROCESSOR_VERTEX) {
                ctx.file_offset[TGSI_FILE_INPUT] = 1;
-               if (ctx.bc->chiprev >= CHIPREV_EVERGREEN) {
+               if (ctx.bc->chip_class >= EVERGREEN) {
                        r600_bc_add_cfinst(ctx.bc, EG_V_SQ_CF_WORD1_SQ_CF_INST_CALL_FS);
                } else {
                        r600_bc_add_cfinst(ctx.bc, V_SQ_CF_WORD1_SQ_CF_INST_CALL_FS);
                }
        }
-       if (ctx.type == TGSI_PROCESSOR_FRAGMENT && ctx.bc->chiprev >= CHIPREV_EVERGREEN) {
+       if (ctx.type == TGSI_PROCESSOR_FRAGMENT && ctx.bc->chip_class >= EVERGREEN) {
                ctx.file_offset[TGSI_FILE_INPUT] = evergreen_gpr_count(&ctx);
        }
        ctx.file_offset[TGSI_FILE_OUTPUT] = ctx.file_offset[TGSI_FILE_INPUT] +
-                                               ctx.info.file_count[TGSI_FILE_INPUT];
+                                               ctx.info.file_max[TGSI_FILE_INPUT] + 1;
        ctx.file_offset[TGSI_FILE_TEMPORARY] = ctx.file_offset[TGSI_FILE_OUTPUT] +
-                                               ctx.info.file_count[TGSI_FILE_OUTPUT];
+                                               ctx.info.file_max[TGSI_FILE_OUTPUT] + 1;
 
        /* Outside the GPR range. This will be translated to one of the
         * kcache banks later. */
@@ -662,7 +674,7 @@ static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_sh
 
        ctx.file_offset[TGSI_FILE_IMMEDIATE] = V_SQ_ALU_SRC_LITERAL;
        ctx.ar_reg = ctx.file_offset[TGSI_FILE_TEMPORARY] +
-                       ctx.info.file_count[TGSI_FILE_TEMPORARY];
+                       ctx.info.file_max[TGSI_FILE_TEMPORARY] + 1;
        ctx.temp_reg = ctx.ar_reg + 1;
 
        ctx.nliterals = 0;
@@ -702,9 +714,9 @@ static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_sh
                                goto out_err;
                        if ((r = tgsi_split_literal_constant(&ctx)))
                                goto out_err;
-                       if (ctx.bc->chiprev == CHIPREV_CAYMAN)
+                       if (ctx.bc->chip_class == CAYMAN)
                                ctx.inst_info = &cm_shader_tgsi_instruction[opcode];
-                       else if (ctx.bc->chiprev >= CHIPREV_EVERGREEN)
+                       else if (ctx.bc->chip_class >= EVERGREEN)
                                ctx.inst_info = &eg_shader_tgsi_instruction[opcode];
                        else
                                ctx.inst_info = &r600_shader_tgsi_instruction[opcode];
@@ -725,52 +737,103 @@ static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_sh
                        goto out_err;
                }
        }
-       /* export output */
+
        noutput = shader->noutput;
+
+       /* clamp color outputs */
+       if (shader->clamp_color) {
+               for (i = 0; i < noutput; i++) {
+                       if (shader->output[i].name == TGSI_SEMANTIC_COLOR ||
+                               shader->output[i].name == TGSI_SEMANTIC_BCOLOR) {
+
+                               int j;
+                               for (j = 0; j < 4; j++) {
+                                       struct r600_bc_alu alu;
+                                       memset(&alu, 0, sizeof(struct r600_bc_alu));
+
+                                       /* MOV_SAT R, R */
+                                       alu.inst = BC_INST(ctx.bc, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV);
+                                       alu.dst.sel = shader->output[i].gpr;
+                                       alu.dst.chan = j;
+                                       alu.dst.write = 1;
+                                       alu.dst.clamp = 1;
+                                       alu.src[0].sel = alu.dst.sel;
+                                       alu.src[0].chan = j;
+
+                                       if (j == 3) {
+                                               alu.last = 1;
+                                       }
+                                       r = r600_bc_add_alu(ctx.bc, &alu);
+                                       if (r)
+                                               return r;
+                               }
+                       }
+               }
+       }
+
+       /* export output */
+       j = 0;
        for (i = 0, pos0 = 0; i < noutput; i++) {
                memset(&output[i], 0, sizeof(struct r600_bc_output));
-               output[i].gpr = shader->output[i].gpr;
-               output[i].elem_size = 3;
-               output[i].swizzle_x = 0;
-               output[i].swizzle_y = 1;
-               output[i].swizzle_z = 2;
-               output[i].swizzle_w = 3;
-               output[i].burst_count = 1;
-               output[i].barrier = 1;
-               output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM;
-               output[i].array_base = i - pos0;
-               output[i].inst = BC_INST(ctx.bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT);
+               output[i + j].gpr = shader->output[i].gpr;
+               output[i + j].elem_size = 3;
+               output[i + j].swizzle_x = 0;
+               output[i + j].swizzle_y = 1;
+               output[i + j].swizzle_z = 2;
+               output[i + j].swizzle_w = 3;
+               output[i + j].burst_count = 1;
+               output[i + j].barrier = 1;
+               output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM;
+               output[i + j].array_base = i - pos0;
+               output[i + j].inst = BC_INST(ctx.bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT);
                switch (ctx.type) {
                case TGSI_PROCESSOR_VERTEX:
                        if (shader->output[i].name == TGSI_SEMANTIC_POSITION) {
-                               output[i].array_base = 60;
-                               output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS;
+                               output[i + j].array_base = 60;
+                               output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS;
                                /* position doesn't count in array_base */
                                pos0++;
                        }
                        if (shader->output[i].name == TGSI_SEMANTIC_PSIZE) {
-                               output[i].array_base = 61;
-                               output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS;
+                               output[i + j].array_base = 61;
+                               output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_POS;
                                /* position doesn't count in array_base */
                                pos0++;
                        }
                        break;
                case TGSI_PROCESSOR_FRAGMENT:
                        if (shader->output[i].name == TGSI_SEMANTIC_COLOR) {
-                               output[i].array_base = shader->output[i].sid;
-                               output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+                               output[i + j].array_base = shader->output[i].sid;
+                               output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+                               if (shader->fs_write_all && (rctx->chip_class >= EVERGREEN)) {
+                                       for (j = 1; j < shader->nr_cbufs; j++) {
+                                               memset(&output[i + j], 0, sizeof(struct r600_bc_output));
+                                               output[i + j].gpr = shader->output[i].gpr;
+                                               output[i + j].elem_size = 3;
+                                               output[i + j].swizzle_x = 0;
+                                               output[i + j].swizzle_y = 1;
+                                               output[i + j].swizzle_z = 2;
+                                               output[i + j].swizzle_w = 3;
+                                               output[i + j].burst_count = 1;
+                                               output[i + j].barrier = 1;
+                                               output[i + j].array_base = shader->output[i].sid + j;
+                                               output[i + j].inst = BC_INST(ctx.bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT);
+                                               output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+                                       }
+                                       j--;
+                               }
                        } else if (shader->output[i].name == TGSI_SEMANTIC_POSITION) {
-                               output[i].array_base = 61;
-                               output[i].swizzle_x = 2;
-                               output[i].swizzle_y = 7;
-                               output[i].swizzle_z = output[i].swizzle_w = 7;
-                               output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+                               output[i + j].array_base = 61;
+                               output[i + j].swizzle_x = 2;
+                               output[i + j].swizzle_y = 7;
+                               output[i + j].swizzle_z = output[i + j].swizzle_w = 7;
+                               output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
                        } else if (shader->output[i].name == TGSI_SEMANTIC_STENCIL) {
-                               output[i].array_base = 61;
-                               output[i].swizzle_x = 7;
-                               output[i].swizzle_y = 1;
-                               output[i].swizzle_z = output[i].swizzle_w = 7;
-                               output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+                               output[i + j].array_base = 61;
+                               output[i + j].swizzle_x = 7;
+                               output[i + j].swizzle_y = 1;
+                               output[i + j].swizzle_z = output[i + j].swizzle_w = 7;
+                               output[i + j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
                        } else {
                                R600_ERR("unsupported fragment output name %d\n", shader->output[i].name);
                                r = -EINVAL;
@@ -783,6 +846,7 @@ static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_sh
                        goto out_err;
                }
        }
+       noutput += j;
        /* add fake param output for vertex shader if no param is exported */
        if (ctx.type == TGSI_PROCESSOR_VERTEX) {
                for (i = 0, pos0 = 0; i < noutput; i++) {
@@ -825,7 +889,7 @@ static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_sh
        }
        /* set export done on last export of each type */
        for (i = noutput - 1, output_done = 0; i >= 0; i--) {
-               if (ctx.bc->chiprev < CHIPREV_CAYMAN) {
+               if (ctx.bc->chip_class < CAYMAN) {
                        if (i == (noutput - 1)) {
                                output[i].end_of_program = 1;
                        }
@@ -842,7 +906,7 @@ static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_sh
                        goto out_err;
        }
        /* add program end */
-       if (ctx.bc->chiprev == CHIPREV_CAYMAN)
+       if (ctx.bc->chip_class == CAYMAN)
                cm_bc_add_cf_end(ctx.bc);
 
        free(ctx.literals);
@@ -878,6 +942,17 @@ static void r600_bc_src(struct r600_bc_alu_src *bc_src,
        bc_src->value = shader_src->value[bc_src->chan];
 }
 
+static void r600_bc_src_set_abs(struct r600_bc_alu_src *bc_src)
+{
+       bc_src->abs = 1;
+       bc_src->neg = 0;
+}
+
+static void r600_bc_src_toggle_neg(struct r600_bc_alu_src *bc_src)
+{
+       bc_src->neg = !bc_src->neg;
+}
+
 static void tgsi_dst(struct r600_shader_ctx *ctx,
                     const struct tgsi_full_dst_register *tgsi_dst,
                     unsigned swizzle,
@@ -934,12 +1009,10 @@ static int tgsi_op2_s(struct r600_shader_ctx *ctx, int swap)
                /* handle some special cases */
                switch (ctx->inst_info->tgsi_opcode) {
                case TGSI_OPCODE_SUB:
-                       alu.src[1].neg = 1;
+                       r600_bc_src_toggle_neg(&alu.src[1]);
                        break;
                case TGSI_OPCODE_ABS:
-                       alu.src[0].abs = 1;
-                       if (alu.src[0].neg)
-                         alu.src[0].neg = 0;
+                       r600_bc_src_set_abs(&alu.src[0]);
                        break;
                default:
                        break;
@@ -1053,7 +1126,7 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx)
        alu.src[2].sel = V_SQ_ALU_SRC_LITERAL;
        alu.src[2].chan = 0;
 
-       if (ctx->bc->chiprev == CHIPREV_R600) {
+       if (ctx->bc->chip_class == R600) {
                alu.src[1].value = *(uint32_t *)&double_pi;
                alu.src[2].value = *(uint32_t *)&neg_pi;
        } else {
@@ -1160,7 +1233,7 @@ static int tgsi_scs(struct r600_shader_ctx *ctx)
 
        /* dst.x = COS */
        if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
-               if (ctx->bc->chiprev == CHIPREV_CAYMAN) {
+               if (ctx->bc->chip_class == CAYMAN) {
                        for (i = 0 ; i < 3; i++) {
                                memset(&alu, 0, sizeof(struct r600_bc_alu));
                                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_COS);
@@ -1194,7 +1267,7 @@ static int tgsi_scs(struct r600_shader_ctx *ctx)
 
        /* dst.y = SIN */
        if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
-               if (ctx->bc->chiprev == CHIPREV_CAYMAN) {
+               if (ctx->bc->chip_class == CAYMAN) {
                        for (i = 0 ; i < 3; i++) {
                                memset(&alu, 0, sizeof(struct r600_bc_alu));
                                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SIN);
@@ -1303,36 +1376,17 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
        struct r600_bc_alu alu;
        int r;
 
-       /* dst.x, <- 1.0  */
-       memset(&alu, 0, sizeof(struct r600_bc_alu));
-       alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV);
-       alu.src[0].sel  = V_SQ_ALU_SRC_1; /*1.0*/
-       alu.src[0].chan = 0;
-       tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst);
-       alu.dst.write = (inst->Dst[0].Register.WriteMask >> 0) & 1;
-       r = r600_bc_add_alu(ctx->bc, &alu);
-       if (r)
-               return r;
-
-       /* dst.y = max(src.x, 0.0) */
+       /* tmp.x = max(src.y, 0.0) */
        memset(&alu, 0, sizeof(struct r600_bc_alu));
        alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX);
-       r600_bc_src(&alu.src[0], &ctx->src[0], 0);
+       r600_bc_src(&alu.src[0], &ctx->src[0], 1);
        alu.src[1].sel  = V_SQ_ALU_SRC_0; /*0.0*/
-       alu.src[1].chan = 0;
-       tgsi_dst(ctx, &inst->Dst[0], 1, &alu.dst);
-       alu.dst.write = (inst->Dst[0].Register.WriteMask >> 1) & 1;
-       r = r600_bc_add_alu(ctx->bc, &alu);
-       if (r)
-               return r;
+       alu.src[1].chan = 1;
+
+       alu.dst.sel = ctx->temp_reg;
+       alu.dst.chan = 0;
+       alu.dst.write = 1;
 
-       /* dst.w, <- 1.0  */
-       memset(&alu, 0, sizeof(struct r600_bc_alu));
-       alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV);
-       alu.src[0].sel  = V_SQ_ALU_SRC_1;
-       alu.src[0].chan = 0;
-       tgsi_dst(ctx, &inst->Dst[0], 3, &alu.dst);
-       alu.dst.write = (inst->Dst[0].Register.WriteMask >> 3) & 1;
        alu.last = 1;
        r = r600_bc_add_alu(ctx->bc, &alu);
        if (r)
@@ -1344,13 +1398,15 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
                int sel;
                int i;
 
-               if (ctx->bc->chiprev == CHIPREV_CAYMAN) {
+               if (ctx->bc->chip_class == CAYMAN) {
                        for (i = 0; i < 3; i++) {
-                               /* dst.z = log(src.y) */
+                               /* tmp.z = log(tmp.x) */
                                memset(&alu, 0, sizeof(struct r600_bc_alu));
                                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_CLAMPED);
-                               r600_bc_src(&alu.src[0], &ctx->src[0], 1);
-                               tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
+                               alu.src[0].sel = ctx->temp_reg;
+                               alu.src[0].chan = 0;
+                               alu.dst.sel = ctx->temp_reg;
+                               alu.dst.chan = i;
                                if (i == 2) {
                                        alu.dst.write = 1;
                                        alu.last = 1;
@@ -1362,11 +1418,14 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
                                        return r;
                        }
                } else {
-                       /* dst.z = log(src.y) */
+                       /* tmp.z = log(tmp.x) */
                        memset(&alu, 0, sizeof(struct r600_bc_alu));
                        alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_CLAMPED);
-                       r600_bc_src(&alu.src[0], &ctx->src[0], 1);
-                       tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst);
+                       alu.src[0].sel = ctx->temp_reg;
+                       alu.src[0].chan = 0;
+                       alu.dst.sel = ctx->temp_reg;
+                       alu.dst.chan = 2;
+                       alu.dst.write = 1;
                        alu.last = 1;
                        r = r600_bc_add_alu(ctx->bc, &alu);
                        if (r)
@@ -1376,13 +1435,12 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
                chan = alu.dst.chan;
                sel = alu.dst.sel;
 
-               /* tmp.x = amd MUL_LIT(src.w, dst.z, src.x ) */
+               /* tmp.x = amd MUL_LIT(tmp.z, src.w, src.x ) */
                memset(&alu, 0, sizeof(struct r600_bc_alu));
                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT);
-               r600_bc_src(&alu.src[0], &ctx->src[0], 3);
-               alu.src[1].sel  = sel;
-               alu.src[1].chan = chan;
-
+               alu.src[0].sel  = sel;
+               alu.src[0].chan = chan;
+               r600_bc_src(&alu.src[1], &ctx->src[0], 3);
                r600_bc_src(&alu.src[2], &ctx->src[0], 0);
                alu.dst.sel = ctx->temp_reg;
                alu.dst.chan = 0;
@@ -1393,7 +1451,7 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
                if (r)
                        return r;
 
-               if (ctx->bc->chiprev == CHIPREV_CAYMAN) {
+               if (ctx->bc->chip_class == CAYMAN) {
                        for (i = 0; i < 3; i++) {
                                /* dst.z = exp(tmp.x) */
                                memset(&alu, 0, sizeof(struct r600_bc_alu));
@@ -1423,6 +1481,42 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
                                return r;
                }
        }
+
+       /* dst.x, <- 1.0  */
+       memset(&alu, 0, sizeof(struct r600_bc_alu));
+       alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV);
+       alu.src[0].sel  = V_SQ_ALU_SRC_1; /*1.0*/
+       alu.src[0].chan = 0;
+       tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst);
+       alu.dst.write = (inst->Dst[0].Register.WriteMask >> 0) & 1;
+       r = r600_bc_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       /* dst.y = max(src.x, 0.0) */
+       memset(&alu, 0, sizeof(struct r600_bc_alu));
+       alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX);
+       r600_bc_src(&alu.src[0], &ctx->src[0], 0);
+       alu.src[1].sel  = V_SQ_ALU_SRC_0; /*0.0*/
+       alu.src[1].chan = 0;
+       tgsi_dst(ctx, &inst->Dst[0], 1, &alu.dst);
+       alu.dst.write = (inst->Dst[0].Register.WriteMask >> 1) & 1;
+       r = r600_bc_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       /* dst.w, <- 1.0  */
+       memset(&alu, 0, sizeof(struct r600_bc_alu));
+       alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV);
+       alu.src[0].sel  = V_SQ_ALU_SRC_1;
+       alu.src[0].chan = 0;
+       tgsi_dst(ctx, &inst->Dst[0], 3, &alu.dst);
+       alu.dst.write = (inst->Dst[0].Register.WriteMask >> 3) & 1;
+       alu.last = 1;
+       r = r600_bc_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
        return 0;
 }
 
@@ -1442,7 +1536,7 @@ static int tgsi_rsq(struct r600_shader_ctx *ctx)
 
        for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
                r600_bc_src(&alu.src[i], &ctx->src[i], 0);
-               alu.src[i].abs = 1;
+               r600_bc_src_set_abs(&alu.src[i]);
        }
        alu.dst.sel = ctx->temp_reg;
        alu.dst.write = 1;
@@ -1834,7 +1928,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx)
        } else if (inst->Instruction.Opcode == TGSI_OPCODE_TXP) {
                int out_chan;
                /* Add perspective divide */
-               if (ctx->bc->chiprev == CHIPREV_CAYMAN) {
+               if (ctx->bc->chip_class == CAYMAN) {
                        out_chan = 2;
                        for (i = 0; i < 3; i++) {
                                memset(&alu, 0, sizeof(struct r600_bc_alu));
@@ -1916,7 +2010,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx)
                }
 
                /* tmp1.z = RCP_e(|tmp1.z|) */
-               if (ctx->bc->chiprev == CHIPREV_CAYMAN) {
+               if (ctx->bc->chip_class == CAYMAN) {
                        for (i = 0; i < 3; i++) {
                                memset(&alu, 0, sizeof(struct r600_bc_alu));
                                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE);
@@ -2128,7 +2222,7 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx)
                alu.src[0].sel = V_SQ_ALU_SRC_1;
                alu.src[0].chan = 0;
                r600_bc_src(&alu.src[1], &ctx->src[0], i);
-               alu.src[1].neg = 1;
+               r600_bc_src_toggle_neg(&alu.src[1]);
                alu.dst.sel = ctx->temp_reg;
                alu.dst.chan = i;
                if (i == lasti) {
@@ -2309,7 +2403,7 @@ static int tgsi_exp(struct r600_shader_ctx *ctx)
                if (r)
                        return r;
 
-               if (ctx->bc->chiprev == CHIPREV_CAYMAN) {
+               if (ctx->bc->chip_class == CAYMAN) {
                        for (i = 0; i < 3; i++) {
                                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE);
                                alu.src[0].sel = ctx->temp_reg;
@@ -2365,7 +2459,7 @@ static int tgsi_exp(struct r600_shader_ctx *ctx)
 
        /* result.z = RoughApprox2ToX(tmp);*/
        if ((inst->Dst[0].Register.WriteMask >> 2) & 0x1) {
-               if (ctx->bc->chiprev == CHIPREV_CAYMAN) {
+               if (ctx->bc->chip_class == CAYMAN) {
                        for (i = 0; i < 3; i++) {
                                memset(&alu, 0, sizeof(struct r600_bc_alu));
                                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE);
@@ -2425,14 +2519,15 @@ static int tgsi_log(struct r600_shader_ctx *ctx)
        int r;
        int i;
 
-       /* result.x = floor(log2(src)); */
+       /* result.x = floor(log2(|src|)); */
        if (inst->Dst[0].Register.WriteMask & 1) {
-               if (ctx->bc->chiprev == CHIPREV_CAYMAN) {
+               if (ctx->bc->chip_class == CAYMAN) {
                        for (i = 0; i < 3; i++) {
                                memset(&alu, 0, sizeof(struct r600_bc_alu));
 
                                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_IEEE);
                                r600_bc_src(&alu.src[0], &ctx->src[0], 0);
+                               r600_bc_src_set_abs(&alu.src[0]);
                        
                                alu.dst.sel = ctx->temp_reg;
                                alu.dst.chan = i;
@@ -2450,6 +2545,7 @@ static int tgsi_log(struct r600_shader_ctx *ctx)
 
                        alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_IEEE);
                        r600_bc_src(&alu.src[0], &ctx->src[0], 0);
+                       r600_bc_src_set_abs(&alu.src[0]);
                        
                        alu.dst.sel = ctx->temp_reg;
                        alu.dst.chan = 0;
@@ -2474,15 +2570,16 @@ static int tgsi_log(struct r600_shader_ctx *ctx)
                        return r;
        }
 
-       /* result.y = src.x / (2 ^ floor(log2(src.x))); */
+       /* result.y = |src.x| / (2 ^ floor(log2(|src.x|))); */
        if ((inst->Dst[0].Register.WriteMask >> 1) & 1) {
 
-               if (ctx->bc->chiprev == CHIPREV_CAYMAN) {
+               if (ctx->bc->chip_class == CAYMAN) {
                        for (i = 0; i < 3; i++) {
                                memset(&alu, 0, sizeof(struct r600_bc_alu));
 
                                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_IEEE);
                                r600_bc_src(&alu.src[0], &ctx->src[0], 0);
+                               r600_bc_src_set_abs(&alu.src[0]);
 
                                alu.dst.sel = ctx->temp_reg;
                                alu.dst.chan = i;
@@ -2500,6 +2597,7 @@ static int tgsi_log(struct r600_shader_ctx *ctx)
 
                        alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_IEEE);
                        r600_bc_src(&alu.src[0], &ctx->src[0], 0);
+                       r600_bc_src_set_abs(&alu.src[0]);
 
                        alu.dst.sel = ctx->temp_reg;
                        alu.dst.chan = 1;
@@ -2526,7 +2624,7 @@ static int tgsi_log(struct r600_shader_ctx *ctx)
                if (r)
                        return r;
 
-               if (ctx->bc->chiprev == CHIPREV_CAYMAN) {
+               if (ctx->bc->chip_class == CAYMAN) {
                        for (i = 0; i < 3; i++) {
                                memset(&alu, 0, sizeof(struct r600_bc_alu));
                                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE);
@@ -2560,7 +2658,7 @@ static int tgsi_log(struct r600_shader_ctx *ctx)
                                return r;
                }
 
-               if (ctx->bc->chiprev == CHIPREV_CAYMAN) {
+               if (ctx->bc->chip_class == CAYMAN) {
                        for (i = 0; i < 3; i++) {
                                memset(&alu, 0, sizeof(struct r600_bc_alu));
                                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE);
@@ -2599,6 +2697,7 @@ static int tgsi_log(struct r600_shader_ctx *ctx)
                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL);
 
                r600_bc_src(&alu.src[0], &ctx->src[0], 0);
+               r600_bc_src_set_abs(&alu.src[0]);
 
                alu.src[1].sel = ctx->temp_reg;
                alu.src[1].chan = 1;
@@ -2613,14 +2712,15 @@ static int tgsi_log(struct r600_shader_ctx *ctx)
                        return r;
        }
 
-       /* result.z = log2(src);*/
+       /* result.z = log2(|src|);*/
        if ((inst->Dst[0].Register.WriteMask >> 2) & 1) {
-               if (ctx->bc->chiprev == CHIPREV_CAYMAN) {
+               if (ctx->bc->chip_class == CAYMAN) {
                        for (i = 0; i < 3; i++) {
                                memset(&alu, 0, sizeof(struct r600_bc_alu));
 
                                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_IEEE);
                                r600_bc_src(&alu.src[0], &ctx->src[0], 0);
+                               r600_bc_src_set_abs(&alu.src[0]);
 
                                alu.dst.sel = ctx->temp_reg;
                                if (i == 2)
@@ -2638,6 +2738,7 @@ static int tgsi_log(struct r600_shader_ctx *ctx)
 
                        alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_IEEE);
                        r600_bc_src(&alu.src[0], &ctx->src[0], 0);
+                       r600_bc_src_set_abs(&alu.src[0]);
 
                        alu.dst.sel = ctx->temp_reg;
                        alu.dst.write = 1;