void gen8_vec4_generator::generate_pull_constant_load(vec4_instruction *inst, struct brw_reg dst, struct brw_reg index, struct brw_reg offset) { assert(index.file == BRW_IMMEDIATE_VALUE && index.type == BRW_REGISTER_TYPE_UD); uint32_t surf_index = index.dw1.ud; assert(offset.file == BRW_GENERAL_REGISTER_FILE); /* Each of the 8 channel enables is considered for whether each * dword is written. */ gen8_instruction *send = next_inst(BRW_OPCODE_SEND); gen8_set_dst(brw, send, dst); gen8_set_src0(brw, send, offset); gen8_set_dp_message(brw, send, GEN7_SFID_DATAPORT_DATA_CACHE, surf_index, GEN6_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ, 0, /* message control */ 1, /* mlen */ 1, /* rlen */ false, /* no header */ false); /* EOT */ mark_surface_used(surf_index); }
void gen8_vec4_generator::generate_scratch_write(vec4_instruction *ir, struct brw_reg dst, struct brw_reg src, struct brw_reg index) { struct brw_reg header = brw_vec8_grf(GEN7_MRF_HACK_START + ir->base_mrf, 0); MOV_RAW(header, brw_vec8_grf(0, 0)); generate_oword_dual_block_offsets(brw_message_reg(ir->base_mrf + 1), index); MOV(retype(brw_message_reg(ir->base_mrf + 2), BRW_REGISTER_TYPE_D), retype(src, BRW_REGISTER_TYPE_D)); /* Each of the 8 channel enables is considered for whether each * dword is written. */ gen8_instruction *send = next_inst(BRW_OPCODE_SEND); gen8_set_dst(brw, send, dst); gen8_set_src0(brw, send, header); gen8_set_pred_control(send, ir->predicate); gen8_set_dp_message(brw, send, GEN7_SFID_DATAPORT_DATA_CACHE, 255, /* binding table index: stateless access */ GEN7_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE, BRW_DATAPORT_OWORD_DUAL_BLOCK_1OWORD, 3, /* mlen */ 0, /* rlen */ true, /* header present */ false); /* EOT */ }
void gen8_vec4_generator::generate_urb_write(vec4_instruction *ir, bool vs) { struct brw_reg header = brw_vec8_grf(GEN7_MRF_HACK_START + ir->base_mrf, 0); /* Copy g0. */ if (vs) MOV_RAW(header, brw_vec8_grf(0, 0)); gen8_instruction *inst; if (!(ir->urb_write_flags & BRW_URB_WRITE_USE_CHANNEL_MASKS)) { /* Enable Channel Masks in the URB_WRITE_OWORD message header */ default_state.access_mode = BRW_ALIGN_1; inst = OR(retype(brw_vec1_grf(GEN7_MRF_HACK_START + ir->base_mrf, 5), BRW_REGISTER_TYPE_UD), retype(brw_vec1_grf(0, 5), BRW_REGISTER_TYPE_UD), brw_imm_ud(0xff00)); gen8_set_mask_control(inst, BRW_MASK_DISABLE); default_state.access_mode = BRW_ALIGN_16; } inst = next_inst(BRW_OPCODE_SEND); gen8_set_urb_message(brw, inst, ir->urb_write_flags, ir->mlen, 0, ir->offset, true); gen8_set_dst(brw, inst, brw_null_reg()); gen8_set_src0(brw, inst, header); }
void gen8_vec4_generator::generate_untyped_atomic(vec4_instruction *ir, struct brw_reg dst, struct brw_reg atomic_op, struct brw_reg surf_index) { assert(atomic_op.file == BRW_IMMEDIATE_VALUE && atomic_op.type == BRW_REGISTER_TYPE_UD && surf_index.file == BRW_IMMEDIATE_VALUE && surf_index.type == BRW_REGISTER_TYPE_UD); assert((atomic_op.dw1.ud & ~0xf) == 0); unsigned msg_control = atomic_op.dw1.ud | /* Atomic Operation Type: BRW_AOP_* */ (1 << 5); /* Return data expected */ gen8_instruction *inst = next_inst(BRW_OPCODE_SEND); gen8_set_dst(brw, inst, retype(dst, BRW_REGISTER_TYPE_UD)); gen8_set_src0(brw, inst, brw_message_reg(ir->base_mrf)); gen8_set_dp_message(brw, inst, HSW_SFID_DATAPORT_DATA_CACHE_1, surf_index.dw1.ud, HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP_SIMD4X2, msg_control, ir->mlen, 1, ir->header_present, false); brw_mark_surface_used(&prog_data->base, surf_index.dw1.ud); }
gen8_instruction * gen8_generator::MOV_RAW(struct brw_reg dst, struct brw_reg src0) { gen8_instruction *inst = next_inst(BRW_OPCODE_MOV); gen8_set_dst(brw, inst, retype(dst, BRW_REGISTER_TYPE_UD)); gen8_set_src0(brw, inst, retype(src0, BRW_REGISTER_TYPE_UD)); gen8_set_mask_control(inst, BRW_MASK_DISABLE); return inst; }
gen8_instruction * gen8_generator::math(unsigned math_function, struct brw_reg dst, struct brw_reg src0) { gen8_instruction *inst = next_inst(BRW_OPCODE_MATH); assert(src0.hstride == 0 || src0.hstride == dst.hstride); gen8_set_math_function(inst, math_function); gen8_set_dst(brw, inst, dst); gen8_set_src0(brw, inst, src0); return inst; }
gen8_instruction * gen8_generator::CMP(struct brw_reg dst, unsigned conditional, struct brw_reg src0, struct brw_reg src1) { gen8_instruction *inst = next_inst(BRW_OPCODE_CMP); gen8_set_cond_modifier(inst, conditional); /* The CMP instruction appears to behave erratically for floating point * sources unless the destination type is also float. Overriding it to * match src0 makes it work in all cases. */ dst.type = src0.type; gen8_set_dst(brw, inst, dst); gen8_set_src0(brw, inst, src0); gen8_set_src1(brw, inst, src1); return inst; }
static int arch_xap_disasm(char *str, const unsigned char *buf, ut64 seek) { struct state *s = get_state(); struct directive *d; memset(s, 0, sizeof(*s)); s->s_buf = buf; s->s_off = seek; s->s_out = NULL; d = next_inst(s); if (d != NULL) { xap_decode(s, d); strcpy(str, d->d_asm); free(d); } else *str = '\0'; #if 0 if (s->s_ff_quirk) { sprintf(d->d_asm, "DC\t0x%x", i2u16(&d->d_inst)); s->s_ff_quirk = 0; } #endif return 0; }
void gen8_vec4_generator::generate_gs_thread_end(vec4_instruction *ir) { struct brw_reg src = brw_vec8_grf(GEN7_MRF_HACK_START + ir->base_mrf, 0); gen8_instruction *inst; /* Enable Channel Masks in the URB_WRITE_HWORD message header */ default_state.access_mode = BRW_ALIGN_1; inst = OR(retype(brw_vec1_grf(GEN7_MRF_HACK_START + ir->base_mrf, 5), BRW_REGISTER_TYPE_UD), retype(brw_vec1_grf(0, 5), BRW_REGISTER_TYPE_UD), brw_imm_ud(0xff00)); /* could be 0x1100 but shouldn't matter */ gen8_set_mask_control(inst, BRW_MASK_DISABLE); default_state.access_mode = BRW_ALIGN_16; /* mlen = 2: g0 header + vertex count */ inst = next_inst(BRW_OPCODE_SEND); gen8_set_urb_message(brw, inst, BRW_URB_WRITE_EOT, 2, 0, 0, true); gen8_set_dst(brw, inst, brw_null_reg()); gen8_set_src0(brw, inst, src); }
void gen8_vec4_generator::generate_untyped_surface_read(vec4_instruction *ir, struct brw_reg dst, struct brw_reg surf_index) { assert(surf_index.file == BRW_IMMEDIATE_VALUE && surf_index.type == BRW_REGISTER_TYPE_UD); gen8_instruction *inst = next_inst(BRW_OPCODE_SEND); gen8_set_dst(brw, inst, retype(dst, BRW_REGISTER_TYPE_UD)); gen8_set_src0(brw, inst, brw_message_reg(ir->base_mrf)); gen8_set_dp_message(brw, inst, HSW_SFID_DATAPORT_DATA_CACHE_1, surf_index.dw1.ud, HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_READ, 0xe, /* enable only the R channel */ ir->mlen, 1, ir->header_present, false); brw_mark_surface_used(&prog_data->base, surf_index.dw1.ud); }
gen8_instruction * gen8_generator::NOP() { return next_inst(BRW_OPCODE_NOP); }
gen8_instruction * gen8_generator::alu3(unsigned opcode, struct brw_reg dst, struct brw_reg src0, struct brw_reg src1, struct brw_reg src2) { /* MRFs haven't existed since Gen7, so we better not be using them. */ if (dst.file == BRW_MESSAGE_REGISTER_FILE) { dst.file = BRW_GENERAL_REGISTER_FILE; dst.nr += GEN7_MRF_HACK_START; } gen8_instruction *inst = next_inst(opcode); assert(gen8_access_mode(inst) == BRW_ALIGN_16); assert(dst.file == BRW_GENERAL_REGISTER_FILE); assert(dst.nr < 128); assert(dst.address_mode == BRW_ADDRESS_DIRECT); assert(dst.type == BRW_REGISTER_TYPE_F || dst.type == BRW_REGISTER_TYPE_D || dst.type == BRW_REGISTER_TYPE_UD); gen8_set_dst_3src_reg_nr(inst, dst.nr); gen8_set_dst_3src_subreg_nr(inst, dst.subnr / 16); gen8_set_dst_3src_writemask(inst, dst.dw1.bits.writemask); assert(src0.file == BRW_GENERAL_REGISTER_FILE); assert(src0.address_mode == BRW_ADDRESS_DIRECT); assert(src0.nr < 128); gen8_set_src0_3src_swizzle(inst, src0.dw1.bits.swizzle); gen8_set_src0_3src_subreg_nr(inst, get_3src_subreg_nr(src0)); gen8_set_src0_3src_rep_ctrl(inst, src0.vstride == BRW_VERTICAL_STRIDE_0); gen8_set_src0_3src_reg_nr(inst, src0.nr); gen8_set_src0_3src_abs(inst, src0.abs); gen8_set_src0_3src_negate(inst, src0.negate); assert(src1.file == BRW_GENERAL_REGISTER_FILE); assert(src1.address_mode == BRW_ADDRESS_DIRECT); assert(src1.nr < 128); gen8_set_src1_3src_swizzle(inst, src1.dw1.bits.swizzle); gen8_set_src1_3src_subreg_nr(inst, get_3src_subreg_nr(src1)); gen8_set_src1_3src_rep_ctrl(inst, src1.vstride == BRW_VERTICAL_STRIDE_0); gen8_set_src1_3src_reg_nr(inst, src1.nr); gen8_set_src1_3src_abs(inst, src1.abs); gen8_set_src1_3src_negate(inst, src1.negate); assert(src2.file == BRW_GENERAL_REGISTER_FILE); assert(src2.address_mode == BRW_ADDRESS_DIRECT); assert(src2.nr < 128); gen8_set_src2_3src_swizzle(inst, src2.dw1.bits.swizzle); gen8_set_src2_3src_subreg_nr(inst, get_3src_subreg_nr(src2)); gen8_set_src2_3src_rep_ctrl(inst, src2.vstride == BRW_VERTICAL_STRIDE_0); gen8_set_src2_3src_reg_nr(inst, src2.nr); gen8_set_src2_3src_abs(inst, src2.abs); gen8_set_src2_3src_negate(inst, src2.negate); /* Set both the source and destination types based on dst.type, ignoring * the source register types. The MAD and LRP emitters both ensure that * all register types are float. The BFE and BFI2 emitters, however, may * send us mixed D and UD source types and want us to ignore that. */ switch (dst.type) { case BRW_REGISTER_TYPE_F: gen8_set_src_3src_type(inst, BRW_3SRC_TYPE_F); gen8_set_dst_3src_type(inst, BRW_3SRC_TYPE_F); break; case BRW_REGISTER_TYPE_D: gen8_set_src_3src_type(inst, BRW_3SRC_TYPE_D); gen8_set_dst_3src_type(inst, BRW_3SRC_TYPE_D); break; case BRW_REGISTER_TYPE_UD: gen8_set_src_3src_type(inst, BRW_3SRC_TYPE_UD); gen8_set_dst_3src_type(inst, BRW_3SRC_TYPE_UD); break; } return inst; }
void gen8_vec4_generator::generate_tex(vec4_instruction *ir, struct brw_reg dst) { int msg_type = 0; switch (ir->opcode) { case SHADER_OPCODE_TEX: case SHADER_OPCODE_TXL: if (ir->shadow_compare) { msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_LOD_COMPARE; } else { msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_LOD; } break; case SHADER_OPCODE_TXD: if (ir->shadow_compare) { msg_type = HSW_SAMPLER_MESSAGE_SAMPLE_DERIV_COMPARE; } else { msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_DERIVS; } break; case SHADER_OPCODE_TXF: msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_LD; break; case SHADER_OPCODE_TXF_CMS: msg_type = GEN7_SAMPLER_MESSAGE_SAMPLE_LD2DMS; break; case SHADER_OPCODE_TXF_MCS: msg_type = GEN7_SAMPLER_MESSAGE_SAMPLE_LD_MCS; break; case SHADER_OPCODE_TXS: msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_RESINFO; break; case SHADER_OPCODE_TG4: if (ir->shadow_compare) { msg_type = GEN7_SAMPLER_MESSAGE_SAMPLE_GATHER4_C; } else { msg_type = GEN7_SAMPLER_MESSAGE_SAMPLE_GATHER4; } break; case SHADER_OPCODE_TG4_OFFSET: if (ir->shadow_compare) { msg_type = GEN7_SAMPLER_MESSAGE_SAMPLE_GATHER4_PO_C; } else { msg_type = GEN7_SAMPLER_MESSAGE_SAMPLE_GATHER4_PO; } break; default: assert(!"should not get here: invalid VS texture opcode"); break; } if (ir->header_present) { MOV_RAW(retype(brw_message_reg(ir->base_mrf), BRW_REGISTER_TYPE_UD), retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD)); default_state.access_mode = BRW_ALIGN_1; if (ir->texture_offset) { /* Set the offset bits in DWord 2. */ MOV_RAW(retype(brw_vec1_reg(MRF, ir->base_mrf, 2), BRW_REGISTER_TYPE_UD), brw_imm_ud(ir->texture_offset)); } if (ir->sampler >= 16) { /* The "Sampler Index" field can only store values between 0 and 15. * However, we can add an offset to the "Sampler State Pointer" * field, effectively selecting a different set of 16 samplers. * * The "Sampler State Pointer" needs to be aligned to a 32-byte * offset, and each sampler state is only 16-bytes, so we can't * exclusively use the offset - we have to use both. */ gen8_instruction *add = ADD(get_element_ud(brw_message_reg(ir->base_mrf), 3), get_element_ud(brw_vec8_grf(0, 0), 3), brw_imm_ud(16 * (ir->sampler / 16) * sizeof(gen7_sampler_state))); gen8_set_mask_control(add, BRW_MASK_DISABLE); } default_state.access_mode = BRW_ALIGN_16; } uint32_t surf_index = prog_data->base.binding_table.texture_start + ir->sampler; gen8_instruction *inst = next_inst(BRW_OPCODE_SEND); gen8_set_dst(brw, inst, dst); gen8_set_src0(brw, inst, brw_message_reg(ir->base_mrf)); gen8_set_sampler_message(brw, inst, surf_index, ir->sampler % 16, msg_type, 1, ir->mlen, ir->header_present, BRW_SAMPLER_SIMD_MODE_SIMD4X2); mark_surface_used(surf_index); }