Supporting multi-branch instructios BRD & BRC
authorHomer Hsing <homer.xing@intel.com>
Mon, 24 Sep 2012 02:06:35 +0000 (10:06 +0800)
committerDamien Lespiau <damien.lespiau@intel.com>
Mon, 4 Mar 2013 15:54:33 +0000 (15:54 +0000)
brd: redirect channels to branches
brc: let channels converging together

also rewrite code converting label to offset

assembler/src/brw_defines.h
assembler/src/gram.y
assembler/src/lex.l
assembler/src/main.c

index 6cc161f..471cef9 100644 (file)
 #define BRW_OPCODE_BFI1       25
 #define BRW_OPCODE_BFI2       26
 #define BRW_OPCODE_JMPI       32
+#define BRW_OPCODE_BRD        33
 #define BRW_OPCODE_IF         34
+#define BRW_OPCODE_BRC        35
 #define BRW_OPCODE_IFF        35
 #define BRW_OPCODE_ELSE       36
 #define BRW_OPCODE_ENDIF      37
index 30abfb0..155abfd 100644 (file)
@@ -40,6 +40,16 @@ extern long int gen_level;
 extern int advanced_flag;
 extern int yylineno;
 extern int need_export;
+static struct src_operand src_null_reg =
+{
+    .reg_file = BRW_ARCHITECTURE_REGISTER_FILE,
+    .reg_nr = BRW_ARF_NULL,
+};
+static struct dst_operand dst_null_reg =
+{
+    .reg_file = BRW_ARCHITECTURE_REGISTER_FILE,
+    .reg_nr = BRW_ARF_NULL,
+};
 
 static int get_type_size(GLuint type);
 int set_instruction_dest(struct brw_instruction *instr,
@@ -121,6 +131,7 @@ void set_direct_src_operand(struct src_operand *src, struct direct_reg *reg,
 %token <integer> MATH_INST
 %token <integer> MAD LRP BFE BFI2 SUBB
 %token <integer> CALL RET
+%token <integer> BRD BRC
 
 %token NULL_TOKEN MATH SAMPLER GATEWAY READ WRITE URB THREAD_SPAWNER VME DATA_PORT
 
@@ -162,6 +173,7 @@ void set_direct_src_operand(struct src_operand *src, struct direct_reg *reg,
 %type <instruction> instoptions instoption_list predicate
 %type <instruction> mathinstruction
 %type <instruction> subroutineinstruction
+%type <instruction> multibranchinstruction
 %type <string> label
 %type <program> instrseq
 %type <integer> instoption
@@ -385,6 +397,67 @@ instruction:       unaryinstruction
                | specialinstruction
                | mathinstruction
                | subroutineinstruction
+               | multibranchinstruction
+;
+
+multibranchinstruction:
+               predicate BRD execsize relativelocation instoptions
+               {
+                 /* Gen7 bspec: dest must be null. use Switch option */
+                 memset(&$$, 0, sizeof($$));
+                 set_instruction_predicate(&$$, &$1);
+                 $$.header.opcode = $2;
+                 $$.header.execution_size = $3;
+                 $$.header.thread_control |= BRW_THREAD_SWITCH;
+                 $$.first_reloc_target = $4.reloc_target;
+                 $$.first_reloc_offset = $4.imm32;
+                 set_instruction_dest(&$$, &dst_null_reg);
+               }
+               | predicate BRD execsize src instoptions
+               {
+                 /* Gen7 bspec: dest must be null. src must be a scalar DWord */
+                 if($4.reg_type != BRW_REGISTER_TYPE_D) {
+                   fprintf(stderr, "The dest type of BRD should be D.\n");
+                   YYERROR;
+                 }
+                 memset(&$$, 0, sizeof($$));
+                 set_instruction_predicate(&$$, &$1);
+                 $$.header.opcode = $2;
+                 $$.header.execution_size = $3;
+                 $$.header.thread_control |= BRW_THREAD_SWITCH;
+                 set_instruction_dest(&$$, &dst_null_reg);
+                 set_instruction_src0(&$$, &$4);
+               }
+               | predicate BRC execsize relativelocation relativelocation instoptions
+               {
+                 /* Gen7 bspec: dest must be null. src0 must be null. use Switch option */
+                 memset(&$$, 0, sizeof($$));
+                 set_instruction_predicate(&$$, &$1);
+                 $$.header.opcode = $2;
+                 $$.header.execution_size = $3;
+                 $$.header.thread_control |= BRW_THREAD_SWITCH;
+                 $$.first_reloc_target = $4.reloc_target;
+                 $$.first_reloc_offset = $4.imm32;
+                 $$.second_reloc_target = $5.reloc_target;
+                 $$.second_reloc_offset = $5.imm32;
+                 set_instruction_dest(&$$, &dst_null_reg);
+                 set_instruction_src0(&$$, &src_null_reg);
+               }
+               | predicate BRC execsize src instoptions
+               {
+                 /* Gen7 bspec: dest must be null. src must be DWORD. use Switch option */
+                 if($4.reg_type != BRW_REGISTER_TYPE_D) {
+                   fprintf(stderr, "The dest type of BRC should be D.\n");
+                   YYERROR;
+                 }
+                 memset(&$$, 0, sizeof($$));
+                 set_instruction_predicate(&$$, &$1);
+                 $$.header.opcode = $2;
+                 $$.header.execution_size = $3;
+                 $$.header.thread_control |= BRW_THREAD_SWITCH;
+                 set_instruction_dest(&$$, &dst_null_reg);
+                 set_instruction_src0(&$$, &$4);
+               }
 ;
 
 subroutineinstruction:
index e4492f0..02bd2c9 100644 (file)
@@ -138,6 +138,8 @@ yylval.integer = BRW_CHANNEL_W;
 "endif" { yylval.integer = BRW_OPCODE_ENDIF; return ENDIF; }
 "call" { yylval.integer = BRW_OPCODE_CALL; return CALL; }
 "ret" { yylval.integer = BRW_OPCODE_RET; return RET; }
+"brd" { yylval.integer = BRW_OPCODE_BRD; return BRD; }
+"brc" { yylval.integer = BRW_OPCODE_BRC; return BRC; }
 
 "pln" { yylval.integer = BRW_OPCODE_PLN; return PLN; }
 
index cf72b85..4dee1b3 100644 (file)
@@ -79,6 +79,16 @@ static const struct option longopts[] = {
        { NULL, 0, NULL, 0 }
 };
 
+// jump distance used in branch instructions as JIP or UIP
+static int jump_distance(int offset)
+{
+    // Gen4- bspec: the jump distance is in number of sixteen-byte units
+    // Gen5+ bspec: the jump distance is in number of eight-byte units
+    if(gen_level >= 5)
+        offset *= 2;
+    return offset;
+}
+
 static void usage(void)
 {
        fprintf(stderr, "usage: intel-gen4asm [options] inputfile\n");
@@ -169,6 +179,10 @@ int label_to_addr(char *name, int start_addr)
                 r = p->addr;
         }
     }
+    if(r == -1) {
+        fprintf(stderr, "Can't find label %s\n", name);
+        exit(1);
+    }
     return r;
 }
 
@@ -385,20 +399,25 @@ int main(int argc, char **argv)
        }
 
        for (entry = compiled_program.first; entry; entry = entry->next) {
-           if (entry->instruction.first_reloc_target) {
-               int addr = label_to_addr(entry->instruction.first_reloc_target,
-                                        entry->inst_offset);
-               if(addr == -1) {
-                   fprintf(stderr, "can not find label %s\n",
-                           entry->instruction.first_reloc_target);
-                   exit(1);
-               }
-               int offset = addr - entry->inst_offset;
+           struct brw_instruction *inst = & entry->instruction;
+
+           if (inst->first_reloc_target)
+               inst->first_reloc_offset = label_to_addr(inst->first_reloc_target, entry->inst_offset);
+
+           if (inst->second_reloc_target)
+               inst->second_reloc_offset = label_to_addr(inst->second_reloc_target, entry->inst_offset);
+
+           if (inst->second_reloc_offset) {
+               // this is a branch instruction with two offset arguments
+               entry->instruction.bits3.branch_2_offset.JIP = jump_distance(inst->first_reloc_offset - entry->inst_offset);
+               entry->instruction.bits3.branch_2_offset.UIP = jump_distance(inst->second_reloc_offset - entry->inst_offset);
+           } else if (inst->first_reloc_offset) {
+               // this is a branch instruction with one offset argument
+               int offset = inst->first_reloc_offset - entry->inst_offset;
+               /* bspec: Unlike other flow control instructions, the offset used by JMPI is relative to the incremented instruction pointer rather than the IP value for the instruction itself. */
                if(entry->instruction.header.opcode == BRW_OPCODE_JMPI)
                    offset --;
-               if(gen_level >= 5)
-                   offset *= 2; // bspec: the jump distance in number of eight-byte units
-               entry->instruction.bits3.JIP = offset;
+               entry->instruction.bits3.JIP = jump_distance(offset);
                if(entry->instruction.header.opcode == BRW_OPCODE_ELSE)
                    entry->instruction.bits3.branch_2_offset.UIP = 1;
            }