freedreno/ir3: fix valgrind complaint with STLW
[mesa.git] / src / freedreno / ir3 / ir3.c
index feec723abd0af65d61095ca05e2dc4ce14504d6b..76ee44d80f5c58bd394898c4375d12e8f1ed2f2a 100644 (file)
@@ -154,6 +154,9 @@ static int emit_cat0(struct ir3_instruction *instr, void *ptr,
        cat0->sync     = !!(instr->flags & IR3_INSTR_SY);
        cat0->opc_cat  = 0;
 
+       if (instr->opc == OPC_CONDEND || instr->opc == OPC_ENDPATCH)
+               cat0->dummy4 = 16;
+
        return 0;
 }
 
@@ -235,7 +238,8 @@ static int emit_cat2(struct ir3_instruction *instr, void *ptr,
        } else if (src1->flags & IR3_REG_CONST) {
                iassert(src1->num < (1 << 12));
                cat2->c1.src1   = reg(src1, info, instr->repeat,
-                               IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF);
+                               IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF |
+                               absneg);
                cat2->c1.src1_c = 1;
        } else {
                iassert(src1->num < (1 << 11));
@@ -261,7 +265,8 @@ static int emit_cat2(struct ir3_instruction *instr, void *ptr,
                } else if (src2->flags & IR3_REG_CONST) {
                        iassert(src2->num < (1 << 12));
                        cat2->c2.src2   = reg(src2, info, instr->repeat,
-                                       IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF);
+                                       IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF |
+                                       absneg);
                        cat2->c2.src2_c = 1;
                } else {
                        iassert(src2->num < (1 << 11));
@@ -345,7 +350,7 @@ static int emit_cat3(struct ir3_instruction *instr, void *ptr,
        } else if (src1->flags & IR3_REG_CONST) {
                iassert(src1->num < (1 << 12));
                cat3->c1.src1   = reg(src1, info, instr->repeat,
-                               IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF);
+                               IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF | absneg);
                cat3->c1.src1_c = 1;
        } else {
                iassert(src1->num < (1 << 11));
@@ -370,7 +375,7 @@ static int emit_cat3(struct ir3_instruction *instr, void *ptr,
        } else if (src3->flags & IR3_REG_CONST) {
                iassert(src3->num < (1 << 12));
                cat3->c2.src3   = reg(src3, info, instr->repeat,
-                               IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF);
+                               IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF | absneg);
                cat3->c2.src3_c = 1;
        } else {
                iassert(src3->num < (1 << 11));
@@ -793,18 +798,30 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr,
 
                return 0;
        } else if (instr->cat6.src_offset || (instr->opc == OPC_LDG) ||
-                       (instr->opc == OPC_LDL)) {
+                       (instr->opc == OPC_LDL) || (instr->opc == OPC_LDLW)) {
+               struct ir3_register *src3 = instr->regs[3];
                instr_cat6a_t *cat6a = ptr;
 
                cat6->src_off = true;
 
-               cat6a->src1 = reg(src1, info, instr->repeat, IR3_REG_IMMED);
-               cat6a->src1_im = !!(src1->flags & IR3_REG_IMMED);
-               if (src2) {
-                       cat6a->src2 = reg(src2, info, instr->repeat, IR3_REG_IMMED);
-                       cat6a->src2_im = !!(src2->flags & IR3_REG_IMMED);
+               if (instr->opc == OPC_LDG) {
+                       /* For LDG src1 can not be immediate, so src1_imm is redundant and
+                        * instead used to signal whether (when true) 'off' is a 32 bit
+                        * register or an immediate offset.
+                        */
+                       cat6a->src1 = reg(src1, info, instr->repeat, 0);
+                       cat6a->src1_im = !(src3->flags & IR3_REG_IMMED);
+                       cat6a->off = reg(src3, info, instr->repeat, IR3_REG_IMMED);
+               } else {
+                       cat6a->src1 = reg(src1, info, instr->repeat, IR3_REG_IMMED);
+                       cat6a->src1_im = !!(src1->flags & IR3_REG_IMMED);
+                       cat6a->off = reg(src3, info, instr->repeat, IR3_REG_IMMED);
+                       iassert(src3->flags & IR3_REG_IMMED);
                }
-               cat6a->off = instr->cat6.src_offset;
+
+               /* Num components */
+               cat6a->src2 = reg(src2, info, instr->repeat, IR3_REG_IMMED);
+               cat6a->src2_im = true;
        } else {
                instr_cat6b_t *cat6b = ptr;
 
@@ -819,11 +836,22 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr,
        }
 
        if (instr->cat6.dst_offset || (instr->opc == OPC_STG) ||
-                       (instr->opc == OPC_STL)) {
+                       (instr->opc == OPC_STL) || (instr->opc == OPC_STLW)) {
                instr_cat6c_t *cat6c = ptr;
                cat6->dst_off = true;
                cat6c->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
-               cat6c->off = instr->cat6.dst_offset;
+
+               if (instr->flags & IR3_INSTR_G) {
+                       struct ir3_register *src3 = instr->regs[4];
+                       cat6c->off = reg(src3, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
+                       if (src3->flags & IR3_REG_IMMED) {
+                               /* Immediate offsets are in bytes... */
+                               cat6->g = false;
+                               cat6c->off *= 4;
+                       }
+               } else {
+                       cat6c->off = instr->cat6.dst_offset;
+               }
        } else {
                instr_cat6d_t *cat6d = ptr;
                cat6->dst_off = false;
@@ -894,6 +922,9 @@ void * ir3_assemble(struct ir3 *shader, struct ir3_info *info,
                        if (ret)
                                goto fail;
                        info->instrs_count += 1 + instr->repeat + instr->nop;
+                       info->nops_count += instr->nop;
+                       if (instr->opc == OPC_NOP)
+                               info->nops_count += 1 + instr->repeat;
                        dwords += 2;
 
                        if (instr->flags & IR3_INSTR_SS)
@@ -1071,11 +1102,12 @@ ir3_count_instructions(struct ir3 *ir)
 {
        unsigned cnt = 0;
        list_for_each_entry (struct ir3_block, block, &ir->block_list, node) {
+               block->start_ip = cnt;
+               block->end_ip = cnt;
                list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node) {
                        instr->ip = cnt++;
+                       block->end_ip = instr->ip;
                }
-               block->start_ip = list_first_entry(&block->instr_list, struct ir3_instruction, node)->ip;
-               block->end_ip = list_last_entry(&block->instr_list, struct ir3_instruction, node)->ip;
        }
        return cnt;
 }