diff options
author | Xiang, Haihao <haihao.xiang@intel.com> | 2013-02-22 11:14:06 +0800 |
---|---|---|
committer | Ben Widawsky <benjamin.widawsky@intel.com> | 2013-11-06 09:39:41 -0800 |
commit | 216163b44d2285705d1af1db405be94d69a27fef (patch) | |
tree | 9ea5fe7edc6692527be6f86f28291a3136cb915d /assembler/gram.y | |
parent | 2df4d3115af706c9e01b2d7ddb7b957239bfdc85 (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/gram.y')
-rw-r--r-- | assembler/gram.y | 83 |
1 files changed, 83 insertions, 0 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. + } +} |