Merge branch 'llvm-cliptest-viewport'
[mesa.git] / src / gallium / drivers / r600 / r600_asm.c
index 0ed177c66bdf09fbf6c5dc23801068348417c142..d13da0ef6381f9960dce766c903e17625dc8533b 100644 (file)
  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
-#include "r600_asm.h"
-#include "r600_context.h"
+#include <stdio.h>
+#include <errno.h>
 #include "util/u_memory.h"
+#include "r600_pipe.h"
 #include "r600_sq.h"
 #include "r600_opcodes.h"
-#include <stdio.h>
-#include <errno.h>
+#include "r600_asm.h"
 
 static inline unsigned int r600_bc_get_num_operands(struct r600_bc_alu *alu)
 {
@@ -71,7 +71,6 @@ static inline unsigned int r600_bc_get_num_operands(struct r600_bc_alu *alu)
        case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SIN:
        case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_COS:
                return 1;
-        
        default: R600_ERR(
                "Need instruction operand number for 0x%x.\n", alu->inst); 
        };
@@ -146,6 +145,13 @@ int r600_bc_init(struct r600_bc *bc, enum radeon_family family)
        case CHIP_RV740:
                bc->chiprev = 1;
                break;
+       case CHIP_CEDAR:
+       case CHIP_REDWOOD:
+       case CHIP_JUNIPER:
+       case CHIP_CYPRESS:
+       case CHIP_HEMLOCK:
+               bc->chiprev = 2;
+               break;
        default:
                R600_ERR("unknown family %d\n", bc->family);
                return -EINVAL;
@@ -213,6 +219,7 @@ static int init_gpr(struct r600_bc_alu *alu)
        return 0;
 }
 
+#if 0
 static int reserve_gpr(struct r600_bc_alu *alu, unsigned sel, unsigned chan, unsigned cycle)
 {
        if (alu->hw_gpr[cycle][chan] < 0)
@@ -292,14 +299,7 @@ static int cycle_for_vector_bank_swizzle(const int swiz, const int sel, unsigned
        return ret;
 }
 
-static int is_const(int sel)
-{
-       if (sel > 255 && sel < 512)
-               return 1;
-       if (sel >= V_SQ_ALU_SRC_0 && sel <= V_SQ_ALU_SRC_LITERAL)
-               return 1;
-       return 0;
-}
+
 
 static void update_chan_counter(struct r600_bc_alu *alu, int *chan_counter)
 {
@@ -316,7 +316,6 @@ static void update_chan_counter(struct r600_bc_alu *alu, int *chan_counter)
        }
 }
 
-#if 0
 /* we need something like this I think - but this is bogus */
 int check_read_slots(struct r600_bc *bc, struct r600_bc_alu *alu_first)
 {
@@ -341,10 +340,23 @@ int check_read_slots(struct r600_bc *bc, struct r600_bc_alu *alu_first)
 }
 #endif
 
+static int is_const(int sel)
+{
+       if (sel > 255 && sel < 512)
+               return 1;
+       if (sel >= V_SQ_ALU_SRC_0 && sel <= V_SQ_ALU_SRC_LITERAL)
+               return 1;
+       return 0;
+}
+
 static int check_scalar(struct r600_bc *bc, struct r600_bc_alu *alu)
 {
        unsigned swizzle_key;
 
+       if (alu->bank_swizzle_force) {
+               alu->bank_swizzle = alu->bank_swizzle_force;
+               return 0;
+       }
        swizzle_key = (is_const(alu->src[0].sel) ? 4 : 0 ) + 
                (is_const(alu->src[1].sel) ? 2 : 0 ) + 
                (is_const(alu->src[2].sel) ? 1 : 0 );
@@ -357,6 +369,10 @@ static int check_vector(struct r600_bc *bc, struct r600_bc_alu *alu)
 {
        unsigned swizzle_key;
 
+       if (alu->bank_swizzle_force) {
+               alu->bank_swizzle = alu->bank_swizzle_force;
+               return 0;
+       }
        swizzle_key = (is_const(alu->src[0].sel) ? 4 : 0 ) + 
                (is_const(alu->src[1].sel) ? 2 : 0 ) + 
                (is_const(alu->src[2].sel) ? 1 : 0 );
@@ -367,7 +383,7 @@ static int check_vector(struct r600_bc *bc, struct r600_bc_alu *alu)
 
 static int check_and_set_bank_swizzle(struct r600_bc *bc, struct r600_bc_alu *alu_first)
 {
-       struct r600_bc_alu *alu;
+       struct r600_bc_alu *alu = NULL;
        int num_instr = 1;
 
        init_gpr(alu_first);
@@ -393,7 +409,6 @@ int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int
 {
        struct r600_bc_alu *nalu = r600_bc_alu();
        struct r600_bc_alu *lalu;
-       struct r600_bc_alu *curr_bs_head;
        int i, r;
 
        if (nalu == NULL)
@@ -404,7 +419,6 @@ int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int
        /* cf can contains only alu or only vtx or only tex */
        if (bc->cf_last == NULL || bc->cf_last->inst != (type << 3) ||
                bc->force_add_cf) {
-               /* at most 128 slots, one add alu can add 4 slots + 4 constant worst case */
                r = r600_bc_add_cf(bc);
                if (r) {
                        free(nalu);
@@ -418,7 +432,9 @@ int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int
        } else {
                LIST_ADDTAIL(&nalu->bs_list, &bc->cf_last->curr_bs_head->bs_list);
        }
-       if (alu->last && (bc->cf_last->ndw >> 1) >= 124) {
+       /* at most 128 slots, one add alu can add 4 slots + 4 constants(2 slots)
+        * worst case */
+       if (alu->last && (bc->cf_last->ndw >> 1) >= 120) {
                bc->force_add_cf = 1;
        }
        /* number of gpr == the last gpr used in any alu */
@@ -449,8 +465,7 @@ int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int
        bc->cf_last->ndw += 2;
        bc->ndw += 2;
 
-       if (bc->use_mem_constant)
-               bc->cf_last->kcache0_mode = 2;
+       bc->cf_last->kcache0_mode = 2;
 
        /* process cur ALU instructions for bank swizzle */
        if (alu->last) {
@@ -462,7 +477,7 @@ int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int
 
 int r600_bc_add_alu(struct r600_bc *bc, const struct r600_bc_alu *alu)
 {
-       return r600_bc_add_alu_type(bc, alu, V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU);
+       return r600_bc_add_alu_type(bc, alu, BC_INST(bc, V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU));
 }
 
 int r600_bc_add_literal(struct r600_bc *bc, const u32 *value)
@@ -475,6 +490,7 @@ int r600_bc_add_literal(struct r600_bc *bc, const u32 *value)
        if (bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_TEX) {
                return 0;
        }
+       /* all same on EG */
        if (bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_JUMP ||
            bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_ELSE ||
            bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_LOOP_START_NO_AL ||
@@ -484,6 +500,7 @@ int r600_bc_add_literal(struct r600_bc *bc, const u32 *value)
            bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_POP) {
                return 0;
        }
+       /* same on EG */
        if (((bc->cf_last->inst != (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3)) &&
             (bc->cf_last->inst != (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3))) ||
                LIST_IS_EMPTY(&bc->cf_last->alu)) {
@@ -513,7 +530,8 @@ int r600_bc_add_vtx(struct r600_bc *bc, const struct r600_bc_vtx *vtx)
        /* cf can contains only alu or only vtx or only tex */
        if (bc->cf_last == NULL ||
                (bc->cf_last->inst != V_SQ_CF_WORD1_SQ_CF_INST_VTX &&
-                bc->cf_last->inst != V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC)) {
+                bc->cf_last->inst != V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC) ||
+                bc->force_add_cf) {
                r = r600_bc_add_cf(bc);
                if (r) {
                        free(nvtx);
@@ -525,6 +543,8 @@ int r600_bc_add_vtx(struct r600_bc *bc, const struct r600_bc_vtx *vtx)
        /* each fetch use 4 dwords */
        bc->cf_last->ndw += 4;
        bc->ndw += 4;
+       if ((bc->ndw / 4) > 7)
+               bc->force_add_cf = 1;
        return 0;
 }
 
@@ -539,7 +559,8 @@ int r600_bc_add_tex(struct r600_bc *bc, const struct r600_bc_tex *tex)
 
        /* cf can contains only alu or only vtx or only tex */
        if (bc->cf_last == NULL ||
-               bc->cf_last->inst != V_SQ_CF_WORD1_SQ_CF_INST_TEX) {
+               bc->cf_last->inst != V_SQ_CF_WORD1_SQ_CF_INST_TEX ||
+               bc->force_add_cf) {
                r = r600_bc_add_cf(bc);
                if (r) {
                        free(ntex);
@@ -551,6 +572,8 @@ int r600_bc_add_tex(struct r600_bc *bc, const struct r600_bc_tex *tex)
        /* each texture fetch use 4 dwords */
        bc->cf_last->ndw += 4;
        bc->ndw += 4;
+       if ((bc->ndw / 4) > 7)
+               bc->force_add_cf = 1;
        return 0;
 }
 
@@ -566,6 +589,7 @@ int r600_bc_add_cfinst(struct r600_bc *bc, int inst)
        return 0;
 }
 
+/* common to all 3 families */
 static int r600_bc_vtx_build(struct r600_bc *bc, struct r600_bc_vtx *vtx, unsigned id)
 {
        bc->bytecode[id++] = S_SQ_VTX_WORD0_BUFFER_ID(vtx->buffer_id) |
@@ -576,13 +600,18 @@ static int r600_bc_vtx_build(struct r600_bc *bc, struct r600_bc_vtx *vtx, unsign
                                S_SQ_VTX_WORD1_DST_SEL_Y(vtx->dst_sel_y) |
                                S_SQ_VTX_WORD1_DST_SEL_Z(vtx->dst_sel_z) |
                                S_SQ_VTX_WORD1_DST_SEL_W(vtx->dst_sel_w) |
-                               S_SQ_VTX_WORD1_USE_CONST_FIELDS(1) |
+                               S_SQ_VTX_WORD1_USE_CONST_FIELDS(vtx->use_const_fields) |
+                               S_SQ_VTX_WORD1_DATA_FORMAT(vtx->data_format) |
+                               S_SQ_VTX_WORD1_NUM_FORMAT_ALL(vtx->num_format_all) |
+                               S_SQ_VTX_WORD1_FORMAT_COMP_ALL(vtx->format_comp_all) |
+                               S_SQ_VTX_WORD1_SRF_MODE_ALL(vtx->srf_mode_all) |
                                S_SQ_VTX_WORD1_GPR_DST_GPR(vtx->dst_gpr);
        bc->bytecode[id++] = S_SQ_VTX_WORD2_MEGA_FETCH(1);
        bc->bytecode[id++] = 0;
        return 0;
 }
 
+/* common to all 3 families */
 static int r600_bc_tex_build(struct r600_bc *bc, struct r600_bc_tex *tex, unsigned id)
 {
        bc->bytecode[id++] = S_SQ_TEX_WORD0_TEX_INST(tex->inst) |
@@ -612,6 +641,7 @@ static int r600_bc_tex_build(struct r600_bc *bc, struct r600_bc_tex *tex, unsign
        return 0;
 }
 
+/* r600 only, r700/eg bits in r700_asm.c */
 static int r600_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsigned id)
 {
        unsigned i;
@@ -662,6 +692,7 @@ static int r600_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsign
        return 0;
 }
 
+/* common for r600/r700 - eg in eg_asm.c */
 static int r600_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf)
 {
        unsigned id = cf->id;
@@ -674,6 +705,7 @@ static int r600_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf)
 
                bc->bytecode[id++] = S_SQ_CF_ALU_WORD1_CF_INST(cf->inst >> 3) |
                                        S_SQ_CF_ALU_WORD1_BARRIER(1) |
+                                       S_SQ_CF_ALU_WORD1_USES_WATERFALL(bc->chiprev == 0 ? cf->r6xx_uses_waterfall : 0) |
                                        S_SQ_CF_ALU_WORD1_COUNT((cf->ndw / 2) - 1);
                break;
        case V_SQ_CF_WORD1_SQ_CF_INST_TEX:
@@ -748,6 +780,8 @@ int r600_bc_build(struct r600_bc *bc)
                        break;
                case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT:
                case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE:
+               case EG_V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT:
+               case EG_V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE:
                        break;
                case V_SQ_CF_WORD1_SQ_CF_INST_JUMP:
                case V_SQ_CF_WORD1_SQ_CF_INST_ELSE:
@@ -771,7 +805,10 @@ int r600_bc_build(struct r600_bc *bc)
                return -ENOMEM;
        LIST_FOR_EACH_ENTRY(cf, &bc->cf, list) {
                addr = cf->addr;
-               r = r600_bc_cf_build(bc, cf);
+               if (bc->chiprev == 2)
+                       r = eg_bc_cf_build(bc, cf);
+               else
+                       r = r600_bc_cf_build(bc, cf);
                if (r)
                        return r;
                switch (cf->inst) {
@@ -783,6 +820,7 @@ int r600_bc_build(struct r600_bc *bc)
                                        r = r600_bc_alu_build(bc, alu, addr);
                                        break;
                                case 1:
+                               case 2: /* eg alu is same encoding as r700 */
                                        r = r700_bc_alu_build(bc, alu, addr);
                                        break;
                                default:
@@ -816,6 +854,8 @@ int r600_bc_build(struct r600_bc *bc)
                        break;
                case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT:
                case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE:
+               case EG_V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT:
+               case EG_V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE:
                case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_START_NO_AL:
                case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_END:
                case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_CONTINUE: