summaryrefslogtreecommitdiff
path: root/assembler
diff options
context:
space:
mode:
authorXiang, Haihao <haihao.xiang@intel.com>2013-02-22 11:14:06 +0800
committerBen Widawsky <benjamin.widawsky@intel.com>2013-11-06 09:39:41 -0800
commit216163b44d2285705d1af1db405be94d69a27fef (patch)
tree9ea5fe7edc6692527be6f86f28291a3136cb915d /assembler
parent2df4d3115af706c9e01b2d7ddb7b957239bfdc85 (diff)
assembler/bdw: Set jip/uip offsets used by flow control instructions
Signed-off-by: Xiang, Haihao <haihao.xiang@intel.com> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Diffstat (limited to 'assembler')
-rw-r--r--assembler/gram.y83
-rw-r--r--assembler/main.c52
2 files changed, 88 insertions, 47 deletions
diff --git a/assembler/gram.y b/assembler/gram.y
index a603c2c2..f8483d3d 100644
--- a/assembler/gram.y
+++ b/assembler/gram.y
@@ -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.
+ }
+}
diff --git a/assembler/main.c b/assembler/main.c
index 809977bc..469406ae 100644
--- a/assembler/main.c
+++ b/assembler/main.c
@@ -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);
}
}