From 216163b44d2285705d1af1db405be94d69a27fef Mon Sep 17 00:00:00 2001 From: "Xiang, Haihao" Date: Fri, 22 Feb 2013 11:14:06 +0800 Subject: assembler/bdw: Set jip/uip offsets used by flow control instructions Signed-off-by: Xiang, Haihao Signed-off-by: Ben Widawsky --- assembler/gram.y | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ assembler/main.c | 52 ++++------------------------------- 2 files changed, 88 insertions(+), 47 deletions(-) (limited to 'assembler') 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); } } -- cgit v1.2.3