/* * Copyright © 2012 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ /** * @file gen8_instruction.h * * A representation of a Gen8+ EU instruction, with helper methods to get * and set various fields. This is the actual hardware format. */ #ifndef GEN8_INSTRUCTION_H #define GEN8_INSTRUCTION_H #include #include #include "brw_context.h" #include "brw_reg.h" #ifdef __cplusplus extern "C" { #endif struct gen8_instruction { uint32_t data[4]; }; static inline unsigned gen8_instruction_bits(struct gen8_instruction *inst, unsigned high, unsigned low); static inline void gen8_instruction_set_bits(struct gen8_instruction *inst, unsigned high, unsigned low, unsigned value); #define F(name, high, low) \ static inline void gen8_set_##name(struct gen8_instruction *inst, unsigned v) \ { \ gen8_instruction_set_bits(inst, high, low, v); \ } \ static inline unsigned gen8_##name(struct gen8_instruction *inst) \ { \ return gen8_instruction_bits(inst, high, low); \ } F(src1_vert_stride, 120, 117) F(src1_da1_width, 116, 114) F(src1_da16_swiz_w, 115, 114) F(src1_da16_swiz_z, 113, 112) F(src1_da1_hstride, 113, 112) F(src1_address_mode, 111, 111) /** Src1.SrcMod @{ */ F(src1_negate, 110, 110) F(src1_abs, 109, 109) /** @} */ F(src1_ia1_subreg_nr, 108, 105) F(src1_da_reg_nr, 108, 101) F(src1_da16_subreg_nr, 100, 100) F(src1_da1_subreg_nr, 100, 96) F(src1_da16_swiz_y, 99, 98) F(src1_da16_swiz_x, 97, 96) F(src1_reg_type, 94, 91) F(src1_reg_file, 90, 89) F(src0_vert_stride, 88, 85) F(src0_da1_width, 84, 82) F(src0_da16_swiz_w, 83, 82) F(src0_da16_swiz_z, 81, 80) F(src0_da1_hstride, 81, 80) F(src0_address_mode, 79, 79) /** Src0.SrcMod @{ */ F(src0_negate, 78, 78) F(src0_abs, 77, 77) /** @} */ F(src0_ia1_subreg_nr, 76, 73) F(src0_da_reg_nr, 76, 69) F(src0_da16_subreg_nr, 68, 68) F(src0_da1_subreg_nr, 68, 64) F(src0_da16_swiz_y, 67, 66) F(src0_da16_swiz_x, 65, 64) F(dst_address_mode, 63, 63) F(dst_da1_hstride, 62, 61) F(dst_ia1_subreg_nr, 60, 57) F(dst_da_reg_nr, 60, 53) F(dst_da16_subreg_nr, 52, 52) F(dst_da1_subreg_nr, 52, 48) F(da16_writemask, 51, 48) /* Dst.ChanEn */ F(src0_reg_type, 46, 43) F(src0_reg_file, 42, 41) F(dst_reg_type, 40, 37) F(dst_reg_file, 36, 35) F(mask_control, 34, 34) F(flag_reg_nr, 33, 33) F(flag_subreg_nr, 32, 32) F(saturate, 31, 31) F(branch_control, 30, 30) F(debug_control, 30, 30) F(cmpt_control, 29, 29) F(acc_wr_control, 28, 28) F(cond_modifier, 27, 24) F(exec_size, 23, 21) F(pred_inv, 20, 20) F(pred_control, 19, 16) F(thread_control, 15, 14) F(qtr_control, 13, 12) F(nib_control, 11, 11) F(no_dd_check, 10, 10) F(no_dd_clear, 9, 9) F(access_mode, 8, 8) /* Bit 7 is Reserved (for future Opcode expansion) */ F(opcode, 6, 0) /** * Three-source instructions: * @{ */ F(src2_3src_reg_nr, 125, 118) F(src2_3src_subreg_nr, 117, 115) F(src2_3src_swizzle, 114, 107) F(src2_3src_rep_ctrl, 106, 106) F(src1_3src_reg_nr, 104, 97) /* src1_3src_subreg_nr spans word boundaries and has to be handled specially */ F(src1_3src_swizzle, 93, 86) F(src1_3src_rep_ctrl, 85, 85) F(src0_3src_reg_nr, 83, 76) F(src0_3src_subreg_nr, 75, 73) F(src0_3src_swizzle, 72, 65) F(src0_3src_rep_ctrl, 64, 64) F(dst_3src_reg_nr, 63, 56) F(dst_3src_subreg_nr, 55, 53) F(dst_3src_writemask, 52, 49) F(dst_3src_type, 48, 46) F(src_3src_type, 45, 43) F(src2_3src_negate, 42, 42) F(src2_3src_abs, 41, 41) F(src1_3src_negate, 40, 40) F(src1_3src_abs, 39, 39) F(src0_3src_negate, 38, 38) F(src0_3src_abs, 37, 37) /** @} */ /** * Fields for SEND messages: * @{ */ F(eot, 127, 127) F(mlen, 124, 121) F(rlen, 120, 116) F(header_present, 115, 115) F(function_control, 114, 96) F(sfid, 27, 24) F(math_function, 27, 24) /** @} */ /** * URB message function control bits: * @{ */ F(urb_per_slot_offset, 113, 113) F(urb_interleave, 111, 111) F(urb_global_offset, 110, 100) F(urb_opcode, 99, 96) /** @} */ /* Message descriptor bits */ #define MD(name, high, low) F(name, (high + 96), (low + 96)) /** * Sampler message function control bits: * @{ */ MD(sampler_simd_mode, 18, 17) MD(sampler_msg_type, 16, 12) MD(sampler, 11, 8) MD(binding_table_index, 7, 0) /* also used by other messages */ /** @} */ /** * Data port message function control bits: * @{ */ MD(dp_category, 18, 18) MD(dp_message_type, 17, 14) MD(dp_message_control, 13, 8) /** @} */ /** * Render Target message function control bits: * @{ */ MD(rt_last, 12, 12) MD(rt_slot_group, 11, 11) MD(rt_message_type, 10, 8) /** @} */ /** * Thread Spawn message function control bits: * @{ */ MD(ts_resource_select, 4, 4) MD(ts_request_type, 1, 1) MD(ts_opcode, 0, 0) /** @} */ /** * Video Motion Estimation message function control bits: * @{ */ F(vme_message_type, 14, 13) /** @} */ /** * Check & Refinement Engine message function control bits: * @{ */ F(cre_message_type, 14, 13) /** @} */ #undef MD #undef F static inline void gen8_set_src1_3src_subreg_nr(struct gen8_instruction *inst, unsigned v) { assert((v & ~0x7) == 0); gen8_instruction_set_bits(inst, 95, 94, v & 0x3); gen8_instruction_set_bits(inst, 96, 96, v >> 2); } static inline unsigned gen8_src1_3src_subreg_nr(struct gen8_instruction *inst) { return gen8_instruction_bits(inst, 95, 94) | (gen8_instruction_bits(inst, 96, 96) << 2); } #define GEN8_IA1_ADDR_IMM(reg, nine, high, low) \ static inline void \ gen8_set_##reg##_ia1_addr_imm(struct gen8_instruction *inst, unsigned value) \ { \ assert((value & ~0x3ff) == 0); \ gen8_instruction_set_bits(inst, high, low, value & 0x1ff); \ gen8_instruction_set_bits(inst, nine, nine, value >> 9); \ } \ \ static inline unsigned \ gen8_##reg##_ia1_addr_imm(struct gen8_instruction *inst) \ { \ return gen8_instruction_bits(inst, high, low) | \ (gen8_instruction_bits(inst, nine, nine) << 9); \ } /* AddrImm[9:0] for Align1 Indirect Addressing */ GEN8_IA1_ADDR_IMM(src1, 121, 104, 96) GEN8_IA1_ADDR_IMM(src0, 95, 72, 64) GEN8_IA1_ADDR_IMM(dst, 47, 56, 48) /** * Flow control instruction bits: * @{ */ static inline unsigned gen8_uip(struct gen8_instruction *inst) { return inst->data[2]; } static inline void gen8_set_uip(struct gen8_instruction *inst, unsigned uip) { inst->data[2] = uip; } static inline unsigned gen8_jip(struct gen8_instruction *inst) { return inst->data[3]; } static inline void gen8_set_jip(struct gen8_instruction *inst, unsigned jip) { inst->data[3] = jip; } /** @} */ static inline int gen8_src1_imm_d(struct gen8_instruction *inst) { return inst->data[3]; } static inline unsigned gen8_src1_imm_ud(struct gen8_instruction *inst) { return inst->data[3]; } static inline float gen8_src1_imm_f(struct gen8_instruction *inst) { fi_type ft; ft.u = inst->data[3]; return ft.f; } void gen8_set_dst(const struct brw_context *brw, struct gen8_instruction *inst, struct brw_reg reg); void gen8_set_src0(const struct brw_context *brw, struct gen8_instruction *inst, struct brw_reg reg); void gen8_set_src1(const struct brw_context *brw, struct gen8_instruction *inst, struct brw_reg reg); void gen8_set_urb_message(const struct brw_context *brw, struct gen8_instruction *inst, enum brw_urb_write_flags flags, unsigned mlen, unsigned rlen, unsigned offset, bool interleave); void gen8_set_sampler_message(const struct brw_context *brw, struct gen8_instruction *inst, unsigned binding_table_index, unsigned sampler, unsigned msg_type, unsigned rlen, unsigned mlen, bool header_present, unsigned simd_mode); void gen8_set_dp_message(const struct brw_context *brw, struct gen8_instruction *inst, enum brw_message_target sfid, unsigned binding_table_index, unsigned msg_type, unsigned msg_control, unsigned msg_length, unsigned response_length, bool header_present, bool end_of_thread); /** Disassemble the instruction. */ int gen8_disassemble(FILE *file, struct gen8_instruction *inst, int gen); /** * Fetch a set of contiguous bits from the instruction. * * Bits indexes range from 0..127; fields may not cross 32-bit boundaries. */ static inline unsigned gen8_instruction_bits(struct gen8_instruction *inst, unsigned high, unsigned low) { /* We assume the field doesn't cross 32-bit boundaries. */ const unsigned word = high / 32; assert(word == low / 32); high %= 32; low %= 32; const unsigned mask = (((1 << (high - low + 1)) - 1) << low); return (inst->data[word] & mask) >> low; } /** * Set bits in the instruction, with proper shifting and masking. * * Bits indexes range from 0..127; fields may not cross 32-bit boundaries. */ static inline void gen8_instruction_set_bits(struct gen8_instruction *inst, unsigned high, unsigned low, unsigned value) { const unsigned word = high / 32; assert(word == low / 32); high %= 32; low %= 32; const unsigned mask = (((1 << (high - low + 1)) - 1) << low); /* Make sure the supplied value actually fits in the given bitfield. */ assert((value & (mask >> low)) == value); inst->data[word] = (inst->data[word] & ~mask) | ((value << low) & mask); } #ifdef __cplusplus } #endif #endif