i965: Mostly fix glsl-max-varyings.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_eu_emit.c
index b832c7165d21b02bec9b51d5b0db2bfe68914e83..10e9ebc3b0ecddaaec24717ba107bc0b6071d4c9 100644 (file)
@@ -102,8 +102,6 @@ static void brw_set_dest( struct brw_instruction *insn,
 static void brw_set_src0( struct brw_instruction *insn,
                           struct brw_reg reg )
 {
-   assert(reg.file != BRW_MESSAGE_REGISTER_FILE);
-
    if (reg.type != BRW_ARCHITECTURE_REGISTER_FILE)
       assert(reg.nr < 128);
 
@@ -255,19 +253,19 @@ static void brw_set_math_message( struct brw_context *brw,
    struct intel_context *intel = &brw->intel;
    brw_set_src1(insn, brw_imm_d(0));
 
-   if (intel->is_ironlake) {
-       insn->bits3.math_igdng.function = function;
-       insn->bits3.math_igdng.int_type = integer_type;
-       insn->bits3.math_igdng.precision = low_precision;
-       insn->bits3.math_igdng.saturate = saturate;
-       insn->bits3.math_igdng.data_type = dataType;
-       insn->bits3.math_igdng.snapshot = 0;
-       insn->bits3.math_igdng.header_present = 0;
-       insn->bits3.math_igdng.response_length = response_length;
-       insn->bits3.math_igdng.msg_length = msg_length;
-       insn->bits3.math_igdng.end_of_thread = 0;
-       insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_MATH;
-       insn->bits2.send_igdng.end_of_thread = 0;
+   if (intel->gen == 5) {
+       insn->bits3.math_gen5.function = function;
+       insn->bits3.math_gen5.int_type = integer_type;
+       insn->bits3.math_gen5.precision = low_precision;
+       insn->bits3.math_gen5.saturate = saturate;
+       insn->bits3.math_gen5.data_type = dataType;
+       insn->bits3.math_gen5.snapshot = 0;
+       insn->bits3.math_gen5.header_present = 0;
+       insn->bits3.math_gen5.response_length = response_length;
+       insn->bits3.math_gen5.msg_length = msg_length;
+       insn->bits3.math_gen5.end_of_thread = 0;
+       insn->bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_MATH;
+       insn->bits2.send_gen5.end_of_thread = 0;
    } else {
        insn->bits3.math.function = function;
        insn->bits3.math.int_type = integer_type;
@@ -282,31 +280,31 @@ static void brw_set_math_message( struct brw_context *brw,
 }
 
 
-static void brw_set_ff_sync_message( struct brw_context *brw,
-                                struct brw_instruction *insn,
-                                GLboolean allocate,
-                                GLboolean used,
-                                GLuint msg_length,
-                                GLuint response_length,
-                                GLboolean end_of_thread,
-                                GLboolean complete,
-                                GLuint offset,
-                                GLuint swizzle_control )
+static void brw_set_ff_sync_message(struct brw_context *brw,
+                                   struct brw_instruction *insn,
+                                   GLboolean allocate,
+                                   GLuint response_length,
+                                   GLboolean end_of_thread)
 {
+       struct intel_context *intel = &brw->intel;
        brw_set_src1(insn, brw_imm_d(0));
 
-       insn->bits3.urb_igdng.opcode = 1;
-       insn->bits3.urb_igdng.offset = offset;
-       insn->bits3.urb_igdng.swizzle_control = swizzle_control;
-       insn->bits3.urb_igdng.allocate = allocate;
-       insn->bits3.urb_igdng.used = used;
-       insn->bits3.urb_igdng.complete = complete;
-       insn->bits3.urb_igdng.header_present = 1;
-       insn->bits3.urb_igdng.response_length = response_length;
-       insn->bits3.urb_igdng.msg_length = msg_length;
-       insn->bits3.urb_igdng.end_of_thread = end_of_thread;
-       insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_URB;
-       insn->bits2.send_igdng.end_of_thread = end_of_thread;
+       insn->bits3.urb_gen5.opcode = 1; /* FF_SYNC */
+       insn->bits3.urb_gen5.offset = 0; /* Not used by FF_SYNC */
+       insn->bits3.urb_gen5.swizzle_control = 0; /* Not used by FF_SYNC */
+       insn->bits3.urb_gen5.allocate = allocate;
+       insn->bits3.urb_gen5.used = 0; /* Not used by FF_SYNC */
+       insn->bits3.urb_gen5.complete = 0; /* Not used by FF_SYNC */
+       insn->bits3.urb_gen5.header_present = 1;
+       insn->bits3.urb_gen5.response_length = response_length; /* may be 1 or 0 */
+       insn->bits3.urb_gen5.msg_length = 1;
+       insn->bits3.urb_gen5.end_of_thread = end_of_thread;
+       if (intel->gen >= 6) {
+          insn->header.destreg__conditionalmod = BRW_MESSAGE_TARGET_URB;
+       } else {
+          insn->bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_URB;
+          insn->bits2.send_gen5.end_of_thread = end_of_thread;
+       }
 }
 
 static void brw_set_urb_message( struct brw_context *brw,
@@ -323,19 +321,27 @@ static void brw_set_urb_message( struct brw_context *brw,
     struct intel_context *intel = &brw->intel;
     brw_set_src1(insn, brw_imm_d(0));
 
-    if (intel->is_ironlake) {
-        insn->bits3.urb_igdng.opcode = 0;      /* ? */
-        insn->bits3.urb_igdng.offset = offset;
-        insn->bits3.urb_igdng.swizzle_control = swizzle_control;
-        insn->bits3.urb_igdng.allocate = allocate;
-        insn->bits3.urb_igdng.used = used;     /* ? */
-        insn->bits3.urb_igdng.complete = complete;
-        insn->bits3.urb_igdng.header_present = 1;
-        insn->bits3.urb_igdng.response_length = response_length;
-        insn->bits3.urb_igdng.msg_length = msg_length;
-        insn->bits3.urb_igdng.end_of_thread = end_of_thread;
-        insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_URB;
-        insn->bits2.send_igdng.end_of_thread = end_of_thread;
+    if (intel->gen >= 5) {
+        insn->bits3.urb_gen5.opcode = 0;       /* ? */
+        insn->bits3.urb_gen5.offset = offset;
+        insn->bits3.urb_gen5.swizzle_control = swizzle_control;
+        insn->bits3.urb_gen5.allocate = allocate;
+        insn->bits3.urb_gen5.used = used;      /* ? */
+        insn->bits3.urb_gen5.complete = complete;
+        insn->bits3.urb_gen5.header_present = 1;
+        insn->bits3.urb_gen5.response_length = response_length;
+        insn->bits3.urb_gen5.msg_length = msg_length;
+        insn->bits3.urb_gen5.end_of_thread = end_of_thread;
+       if (intel->gen >= 6) {
+          /* For SNB, the SFID bits moved to the condmod bits, and
+           * EOT stayed in bits3 above.  Does the EOT bit setting
+           * below on Ironlake even do anything?
+           */
+          insn->header.destreg__conditionalmod = BRW_MESSAGE_TARGET_URB;
+       } else {
+          insn->bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_URB;
+          insn->bits2.send_gen5.end_of_thread = end_of_thread;
+       }
     } else {
         insn->bits3.urb.opcode = 0;    /* ? */
         insn->bits3.urb.offset = offset;
@@ -363,18 +369,18 @@ static void brw_set_dp_write_message( struct brw_context *brw,
    struct intel_context *intel = &brw->intel;
    brw_set_src1(insn, brw_imm_d(0));
 
-   if (intel->is_ironlake) {
-       insn->bits3.dp_write_igdng.binding_table_index = binding_table_index;
-       insn->bits3.dp_write_igdng.msg_control = msg_control;
-       insn->bits3.dp_write_igdng.pixel_scoreboard_clear = pixel_scoreboard_clear;
-       insn->bits3.dp_write_igdng.msg_type = msg_type;
-       insn->bits3.dp_write_igdng.send_commit_msg = 0;
-       insn->bits3.dp_write_igdng.header_present = 1;
-       insn->bits3.dp_write_igdng.response_length = response_length;
-       insn->bits3.dp_write_igdng.msg_length = msg_length;
-       insn->bits3.dp_write_igdng.end_of_thread = end_of_thread;
-       insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_DATAPORT_WRITE;
-       insn->bits2.send_igdng.end_of_thread = end_of_thread;
+   if (intel->gen == 5) {
+       insn->bits3.dp_write_gen5.binding_table_index = binding_table_index;
+       insn->bits3.dp_write_gen5.msg_control = msg_control;
+       insn->bits3.dp_write_gen5.pixel_scoreboard_clear = pixel_scoreboard_clear;
+       insn->bits3.dp_write_gen5.msg_type = msg_type;
+       insn->bits3.dp_write_gen5.send_commit_msg = 0;
+       insn->bits3.dp_write_gen5.header_present = 1;
+       insn->bits3.dp_write_gen5.response_length = response_length;
+       insn->bits3.dp_write_gen5.msg_length = msg_length;
+       insn->bits3.dp_write_gen5.end_of_thread = end_of_thread;
+       insn->bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_DATAPORT_WRITE;
+       insn->bits2.send_gen5.end_of_thread = end_of_thread;
    } else {
        insn->bits3.dp_write.binding_table_index = binding_table_index;
        insn->bits3.dp_write.msg_control = msg_control;
@@ -401,18 +407,18 @@ static void brw_set_dp_read_message( struct brw_context *brw,
    struct intel_context *intel = &brw->intel;
    brw_set_src1(insn, brw_imm_d(0));
 
-   if (intel->is_ironlake) {
-       insn->bits3.dp_read_igdng.binding_table_index = binding_table_index;
-       insn->bits3.dp_read_igdng.msg_control = msg_control;
-       insn->bits3.dp_read_igdng.msg_type = msg_type;
-       insn->bits3.dp_read_igdng.target_cache = target_cache;
-       insn->bits3.dp_read_igdng.header_present = 1;
-       insn->bits3.dp_read_igdng.response_length = response_length;
-       insn->bits3.dp_read_igdng.msg_length = msg_length;
-       insn->bits3.dp_read_igdng.pad1 = 0;
-       insn->bits3.dp_read_igdng.end_of_thread = end_of_thread;
-       insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_DATAPORT_READ;
-       insn->bits2.send_igdng.end_of_thread = end_of_thread;
+   if (intel->gen == 5) {
+       insn->bits3.dp_read_gen5.binding_table_index = binding_table_index;
+       insn->bits3.dp_read_gen5.msg_control = msg_control;
+       insn->bits3.dp_read_gen5.msg_type = msg_type;
+       insn->bits3.dp_read_gen5.target_cache = target_cache;
+       insn->bits3.dp_read_gen5.header_present = 1;
+       insn->bits3.dp_read_gen5.response_length = response_length;
+       insn->bits3.dp_read_gen5.msg_length = msg_length;
+       insn->bits3.dp_read_gen5.pad1 = 0;
+       insn->bits3.dp_read_gen5.end_of_thread = end_of_thread;
+       insn->bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_DATAPORT_READ;
+       insn->bits2.send_gen5.end_of_thread = end_of_thread;
    } else {
        insn->bits3.dp_read.binding_table_index = binding_table_index; /*0:7*/
        insn->bits3.dp_read.msg_control = msg_control;  /*8:11*/
@@ -441,17 +447,17 @@ static void brw_set_sampler_message(struct brw_context *brw,
    assert(eot == 0);
    brw_set_src1(insn, brw_imm_d(0));
 
-   if (intel->is_ironlake) {
-      insn->bits3.sampler_igdng.binding_table_index = binding_table_index;
-      insn->bits3.sampler_igdng.sampler = sampler;
-      insn->bits3.sampler_igdng.msg_type = msg_type;
-      insn->bits3.sampler_igdng.simd_mode = simd_mode;
-      insn->bits3.sampler_igdng.header_present = header_present;
-      insn->bits3.sampler_igdng.response_length = response_length;
-      insn->bits3.sampler_igdng.msg_length = msg_length;
-      insn->bits3.sampler_igdng.end_of_thread = eot;
-      insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_SAMPLER;
-      insn->bits2.send_igdng.end_of_thread = eot;
+   if (intel->gen == 5) {
+      insn->bits3.sampler_gen5.binding_table_index = binding_table_index;
+      insn->bits3.sampler_gen5.sampler = sampler;
+      insn->bits3.sampler_gen5.msg_type = msg_type;
+      insn->bits3.sampler_gen5.simd_mode = simd_mode;
+      insn->bits3.sampler_gen5.header_present = header_present;
+      insn->bits3.sampler_gen5.response_length = response_length;
+      insn->bits3.sampler_gen5.msg_length = msg_length;
+      insn->bits3.sampler_gen5.end_of_thread = eot;
+      insn->bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_SAMPLER;
+      insn->bits2.send_gen5.end_of_thread = eot;
    } else if (intel->is_g4x) {
       insn->bits3.sampler_g4x.binding_table_index = binding_table_index;
       insn->bits3.sampler_g4x.sampler = sampler;
@@ -567,7 +573,7 @@ ALU2(DPH)
 ALU2(DP3)
 ALU2(DP2)
 ALU2(LINE)
-
+ALU2(PLN)
 
 
 
@@ -657,7 +663,7 @@ struct brw_instruction *brw_ELSE(struct brw_compile *p,
    struct brw_instruction *insn;
    GLuint br = 1;
 
-   if (intel->is_ironlake)
+   if (intel->gen == 5)
       br = 2;
 
    if (p->single_program_flow) {
@@ -699,7 +705,7 @@ void brw_ENDIF(struct brw_compile *p,
    struct intel_context *intel = &p->brw->intel;
    GLuint br = 1;
 
-   if (intel->is_ironlake)
+   if (intel->gen == 5)
       br = 2; 
  
    if (p->single_program_flow) {
@@ -814,7 +820,7 @@ struct brw_instruction *brw_WHILE(struct brw_compile *p,
    struct brw_instruction *insn;
    GLuint br = 1;
 
-   if (intel->is_ironlake)
+   if (intel->gen == 5)
       br = 2;
 
    if (p->single_program_flow)
@@ -858,7 +864,7 @@ void brw_land_fwd_jump(struct brw_compile *p,
    struct brw_instruction *landing = &p->store[p->nr_insn];
    GLuint jmpi = 1;
 
-   if (intel->is_ironlake)
+   if (intel->gen == 5)
        jmpi = 2;
 
    assert(jmp_insn->header.opcode == BRW_OPCODE_JMPI);
@@ -900,6 +906,20 @@ void brw_CMP(struct brw_compile *p,
    }
 }
 
+/* Issue 'wait' instruction for n1, host could program MMIO
+   to wake up thread. */
+void brw_WAIT (struct brw_compile *p)
+{
+   struct brw_instruction *insn = next_insn(p, BRW_OPCODE_WAIT);
+   struct brw_reg src = brw_notification_1_reg();
+
+   brw_set_dest(insn, src);
+   brw_set_src0(insn, src);
+   brw_set_src1(insn, brw_null_reg());
+   insn->header.execution_size = 0; /* must */
+   insn->header.predicate_control = 0;
+   insn->header.compression_control = 0;
+}
 
 
 /***********************************************************************
@@ -917,26 +937,40 @@ void brw_math( struct brw_compile *p,
               GLuint data_type,
               GLuint precision )
 {
-   struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
-   GLuint msg_length = (function == BRW_MATH_FUNCTION_POW) ? 2 : 1; 
-   GLuint response_length = (function == BRW_MATH_FUNCTION_SINCOS) ? 2 : 1; 
+   struct intel_context *intel = &p->brw->intel;
 
-   /* Example code doesn't set predicate_control for send
-    * instructions.
-    */
-   insn->header.predicate_control = 0; 
-   insn->header.destreg__conditionalmod = msg_reg_nr;
+   if (intel->gen >= 6) {
+      struct brw_instruction *insn = next_insn(p, BRW_OPCODE_MATH);
 
-   brw_set_dest(insn, dest);
-   brw_set_src0(insn, src);
-   brw_set_math_message(p->brw,
-                       insn, 
-                       msg_length, response_length, 
-                       function,
-                       BRW_MATH_INTEGER_UNSIGNED,
-                       precision,
-                       saturate,
-                       data_type);
+      /* Math is the same ISA format as other opcodes, except that CondModifier
+       * becomes FC[3:0] and ThreadCtrl becomes FC[5:4].
+       */
+      insn->header.destreg__conditionalmod = function;
+
+      brw_set_dest(insn, dest);
+      brw_set_src0(insn, src);
+      brw_set_src1(insn, brw_null_reg());
+   } else {
+      struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
+      GLuint msg_length = (function == BRW_MATH_FUNCTION_POW) ? 2 : 1;
+      GLuint response_length = (function == BRW_MATH_FUNCTION_SINCOS) ? 2 : 1;
+      /* Example code doesn't set predicate_control for send
+       * instructions.
+       */
+      insn->header.predicate_control = 0;
+      insn->header.destreg__conditionalmod = msg_reg_nr;
+
+      brw_set_dest(insn, dest);
+      brw_set_src0(insn, src);
+      brw_set_math_message(p->brw,
+                          insn,
+                          msg_length, response_length,
+                          function,
+                          BRW_MATH_INTEGER_UNSIGNED,
+                          precision,
+                          saturate,
+                          data_type);
+   }
 }
 
 /**
@@ -951,10 +985,25 @@ void brw_math_16( struct brw_compile *p,
                  struct brw_reg src,
                  GLuint precision )
 {
+   struct intel_context *intel = &p->brw->intel;
    struct brw_instruction *insn;
    GLuint msg_length = (function == BRW_MATH_FUNCTION_POW) ? 2 : 1; 
    GLuint response_length = (function == BRW_MATH_FUNCTION_SINCOS) ? 2 : 1; 
 
+   if (intel->gen >= 6) {
+      insn = next_insn(p, BRW_OPCODE_MATH);
+
+      /* Math is the same ISA format as other opcodes, except that CondModifier
+       * becomes FC[3:0] and ThreadCtrl becomes FC[5:4].
+       */
+      insn->header.destreg__conditionalmod = function;
+
+      brw_set_dest(insn, dest);
+      brw_set_src0(insn, src);
+      brw_set_src1(insn, brw_null_reg());
+      return;
+   }
+
    /* First instruction:
     */
    brw_push_insn_state(p);
@@ -1270,7 +1319,7 @@ void brw_SAMPLE(struct brw_compile *p,
                GLuint simd_mode)
 {
    GLboolean need_stall = 0;
-   
+
    if (writemask == 0) {
       /*printf("%s: zero writemask??\n", __FUNCTION__); */
       return;
@@ -1307,8 +1356,14 @@ void brw_SAMPLE(struct brw_compile *p,
          /* printf("need stall %x %x\n", newmask , writemask); */
       }
       else {
+        GLboolean dispatch_16 = GL_FALSE;
+
         struct brw_reg m1 = brw_message_reg(msg_reg_nr);
-        
+
+        guess_execution_size(p->current, dest);
+        if (p->current->header.execution_size == BRW_EXECUTE_16)
+           dispatch_16 = GL_TRUE;
+
         newmask = ~newmask & WRITEMASK_XYZW;
 
         brw_push_insn_state(p);
@@ -1323,7 +1378,13 @@ void brw_SAMPLE(struct brw_compile *p,
 
         src0 = retype(brw_null_reg(), BRW_REGISTER_TYPE_UW); 
         dest = offset(dest, dst_offset);
-        response_length = len * 2;
+
+        /* For 16-wide dispatch, masked channels are skipped in the
+         * response.  For 8-wide, masked channels still take up slots,
+         * and are just not written to.
+         */
+        if (dispatch_16)
+           response_length = len * 2;
       }
    }
 
@@ -1377,7 +1438,21 @@ void brw_urb_WRITE(struct brw_compile *p,
                   GLuint offset,
                   GLuint swizzle)
 {
-   struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
+   struct intel_context *intel = &p->brw->intel;
+   struct brw_instruction *insn;
+
+   /* Sandybridge doesn't have the implied move for SENDs,
+    * and the first message register index comes from src0.
+    */
+   if (intel->gen >= 6) {
+      brw_push_insn_state(p);
+      brw_set_mask_control( p, BRW_MASK_DISABLE );
+      brw_MOV(p, brw_message_reg(msg_reg_nr), src0);
+      brw_pop_insn_state(p);
+      src0 = brw_message_reg(msg_reg_nr);
+   }
+
+   insn = next_insn(p, BRW_OPCODE_SEND);
 
    assert(msg_length < BRW_MAX_MRF);
 
@@ -1385,7 +1460,8 @@ void brw_urb_WRITE(struct brw_compile *p,
    brw_set_src0(insn, src0);
    brw_set_src1(insn, brw_imm_d(0));
 
-   insn->header.destreg__conditionalmod = msg_reg_nr;
+   if (intel->gen < 6)
+      insn->header.destreg__conditionalmod = msg_reg_nr;
 
    brw_set_urb_message(p->brw,
                       insn,
@@ -1404,18 +1480,11 @@ void brw_ff_sync(struct brw_compile *p,
                   GLuint msg_reg_nr,
                   struct brw_reg src0,
                   GLboolean allocate,
-                  GLboolean used,
-                  GLuint msg_length,
                   GLuint response_length,
-                  GLboolean eot,
-                  GLboolean writes_complete,
-                  GLuint offset,
-                  GLuint swizzle)
+                  GLboolean eot)
 {
    struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
 
-   assert(msg_length < 16);
-
    brw_set_dest(insn, dest);
    brw_set_src0(insn, src0);
    brw_set_src1(insn, brw_imm_d(0));
@@ -1423,13 +1492,8 @@ void brw_ff_sync(struct brw_compile *p,
    insn->header.destreg__conditionalmod = msg_reg_nr;
 
    brw_set_ff_sync_message(p->brw,
-                      insn,
-                      allocate,
-                      used,
-                      msg_length,
-                      response_length, 
-                      eot, 
-                      writes_complete, 
-                      offset,
-                      swizzle);
+                          insn,
+                          allocate,
+                          response_length,
+                          eot);
 }