assembler/bdw: Set jip/uip offsets used by flow control instructions
authorXiang, Haihao <haihao.xiang@intel.com>
Fri, 22 Feb 2013 03:14:06 +0000 (11:14 +0800)
committerBen Widawsky <benjamin.widawsky@intel.com>
Wed, 6 Nov 2013 17:39:41 +0000 (09:39 -0800)
Signed-off-by: Xiang, Haihao <haihao.xiang@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
assembler/gram.y
assembler/main.c

index a603c2c..f8483d3 100644 (file)
@@ -117,6 +117,9 @@ static void set_direct_dst_operand(struct brw_reg *dst, struct brw_reg *reg,
 static void set_direct_src_operand(struct src_operand *src, struct brw_reg *reg,
                                   int type);
 
+void set_branch_two_offsets(struct brw_program_instruction *insn, int jip_offset, int uip_offset);
+void set_branch_one_offset(struct brw_program_instruction *insn, int jip_offset);
+
 enum message_level {
     WARN,
     ERROR,
@@ -3152,3 +3155,83 @@ static void set_direct_src_operand(struct src_operand *src, struct brw_reg *reg,
        src->reg.abs = 0;
        SWIZZLE(src->reg) = BRW_SWIZZLE_NOOP;
 }
+
+static inline int instruction_opcode(struct brw_program_instruction *insn)
+{
+    if (IS_GENp(8))
+       return gen8_opcode(GEN8(insn));
+    else
+       return GEN(insn)->header.opcode;
+}
+
+/*
+ * return the offset used in native flow control (branch) instructions
+ */
+static inline int branch_offset(struct brw_program_instruction *insn, int 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 (instruction_opcode(insn) == BRW_OPCODE_JMPI)
+        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
+     * Gen7.5+: the offset is in unit of 8bits for JMPI, 64bits for other flow
+     * control instructions
+     */
+    if (gen_level >= 75 &&
+        (instruction_opcode(insn) == BRW_OPCODE_JMPI))
+        offset *= 16;
+    else if (gen_level >= 50)
+        offset *= 2;
+
+    return offset;
+}
+
+void set_branch_two_offsets(struct brw_program_instruction *insn, int jip_offset, int uip_offset)
+{
+    int jip = branch_offset(insn, jip_offset);
+    int uip = branch_offset(insn, uip_offset);
+
+    assert(instruction_opcode(insn) != BRW_OPCODE_JMPI);
+
+    if (IS_GENp(8)) {
+        gen8_set_jip(GEN8(insn), jip);
+       gen8_set_uip(GEN8(insn), uip);
+    } else {
+        GEN(insn)->bits3.break_cont.jip = jip;
+        GEN(insn)->bits3.break_cont.uip = uip;
+    }
+}
+
+void set_branch_one_offset(struct brw_program_instruction *insn, int jip_offset)
+{
+    int jip = branch_offset(insn, jip_offset);
+
+    if (IS_GENp(8)) {
+        gen8_set_jip(GEN8(insn), jip);
+    } else if (IS_GENx(7)) {
+        /* Gen7 JMPI Restrictions in bspec:
+         * The JIP data type must be Signed DWord
+         */
+        if (instruction_opcode(insn) == BRW_OPCODE_JMPI)
+            GEN(insn)->bits3.JIP = jip;
+        else
+            GEN(insn)->bits3.break_cont.jip = jip;
+    } else if (IS_GENx(6)) {
+        if ((instruction_opcode(insn) == BRW_OPCODE_CALL) ||
+            (instruction_opcode(insn) == BRW_OPCODE_JMPI))
+            GEN(insn)->bits3.JIP = jip;
+        else
+            GEN(insn)->bits1.branch_gen6.jump_count = jip; // for CASE,ELSE,FORK,IF,WHILE
+    } else {
+        GEN(insn)->bits3.JIP = jip;
+
+        if (instruction_opcode(insn) == BRW_OPCODE_ELSE)
+            GEN(insn)->bits3.break_cont.uip = 1; // Set the istack pop count, which must always be 1.
+    }
+}
index 809977b..469406a 100644 (file)
@@ -38,6 +38,8 @@
 #include "brw_eu.h"
 
 extern FILE *yyin;
+extern void set_branch_two_offsets(struct brw_program_instruction *insn, int jip_offset, int uip_offset);
+extern void set_branch_one_offset(struct brw_program_instruction *insn, int jip_offset);
 
 long int gen_level = 40;
 int advanced_flag = 0; /* 0: in unit of byte, 1: in unit of data element size */
@@ -86,16 +88,6 @@ 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(IS_GENp(5))
-        offset *= 2;
-    return offset;
-}
-
 static void usage(void)
 {
        fprintf(stderr, "usage: intel-gen4asm [options] inputfile\n");
@@ -438,7 +430,6 @@ int main(int argc, char **argv)
 
        for (entry = compiled_program.first; entry; entry = entry->next) {
            struct relocation *reloc = &entry->reloc;
-           struct brw_instruction *inst = &entry->insn.gen;
 
            if (!is_relocatable(entry))
                continue;
@@ -449,43 +440,10 @@ int main(int argc, char **argv)
            if (reloc->second_reloc_target)
                reloc->second_reloc_offset = label_to_addr(reloc->second_reloc_target, entry->inst_offset) - entry->inst_offset;
 
-           if (reloc->second_reloc_offset) {
-               // this is a branch instruction with two offset arguments
-               inst->bits3.break_cont.jip = jump_distance(reloc->first_reloc_offset);
-               inst->bits3.break_cont.uip = jump_distance(reloc->second_reloc_offset);
+           if (reloc->second_reloc_offset) { // this is a branch instruction with two offset arguments
+                set_branch_two_offsets(entry, reloc->first_reloc_offset, reloc->second_reloc_offset);
            } else if (reloc->first_reloc_offset) {
-               // this is a branch instruction with one offset argument
-               int offset = reloc->first_reloc_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. */
-
-               int is_jmpi = inst->header.opcode == BRW_OPCODE_JMPI; // target relative to the post-incremented IP, so delta == 1 if JMPI
-               if(is_jmpi)
-                   offset --;
-               offset = jump_distance(offset);
-               if (is_jmpi && (gen_level == 75))
-                       offset = offset * 8;
-
-               if(!IS_GENp(6)) {
-                   inst->bits3.JIP = offset;
-                   if(inst->header.opcode == BRW_OPCODE_ELSE)
-                       inst->bits3.break_cont.uip = 1; /* Set the istack pop count, which must always be 1. */
-               } else if(IS_GENx(6)) {
-                   /* TODO: endif JIP pos is not in Gen6 spec. may be bits1 */
-                   int opcode = inst->header.opcode;
-                   if(opcode == BRW_OPCODE_CALL || opcode == BRW_OPCODE_JMPI)
-                       inst->bits3.JIP = offset; // for CALL, JMPI
-                   else
-                       inst->bits1.branch_gen6.jump_count = offset; // for CASE,ELSE,FORK,IF,WHILE
-               } else if(IS_GENp(7)) {
-                   int opcode = inst->header.opcode;
-                   /* Gen7 JMPI Restrictions in bspec:
-                    * The JIP data type must be Signed DWord
-                    */
-                   if(opcode == BRW_OPCODE_JMPI)
-                       inst->bits3.JIP = offset;
-                   else
-                       inst->bits3.break_cont.jip = offset;
-               }
+                set_branch_one_offset(entry, reloc->first_reloc_offset);
            }
        }