+static void
+emit_store_output(struct lp_build_tgsi_context *bld_base,
+ enum tgsi_opcode_type dtype,
+ const struct tgsi_full_dst_register *reg,
+ unsigned index,
+ unsigned chan_index,
+ LLVMValueRef indirect_index,
+ LLVMValueRef value)
+{
+ struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
+ struct gallivm_state *gallivm = bld_base->base.gallivm;
+ LLVMBuilderRef builder = gallivm->builder;
+ struct lp_build_context *float_bld = &bld_base->base;
+
+ /* Outputs are always stored as floats */
+ value = LLVMBuildBitCast(builder, value, float_bld->vec_type, "");
+
+ if (reg->Register.Indirect) {
+ LLVMValueRef index_vec; /* indexes into the output registers */
+ LLVMValueRef outputs_array;
+ LLVMTypeRef fptr_type;
+
+ index_vec = get_soa_array_offsets(&bld_base->uint_bld,
+ indirect_index,
+ chan_index,
+ TRUE);
+
+ fptr_type = LLVMPointerType(LLVMFloatTypeInContext(gallivm->context), 0);
+ outputs_array = LLVMBuildBitCast(builder, bld->outputs_array, fptr_type, "");
+
+ /* Scatter store values into output registers */
+ emit_mask_scatter(bld, outputs_array, index_vec, value,
+ &bld->exec_mask);
+ }
+ else {
+ assert(LLVMTypeOf(value) == float_bld->vec_type);
+ LLVMValueRef out_ptr = lp_get_output_ptr(bld, reg->Register.Index,
+ chan_index);
+
+ if (tgsi_type_is_64bit(dtype)) {
+ LLVMValueRef out_ptr2 = lp_get_output_ptr(bld, reg->Register.Index,
+ chan_index + 1);
+ emit_store_64bit_chan(bld_base, out_ptr, out_ptr2,
+ value);
+ } else
+ lp_exec_mask_store(&bld->exec_mask, float_bld, value, out_ptr);
+ }
+}
+
+static void
+emit_store_tcs_output(struct lp_build_tgsi_context *bld_base,
+ enum tgsi_opcode_type dtype,
+ const struct tgsi_full_dst_register *reg,
+ unsigned index,
+ unsigned chan_index,
+ LLVMValueRef indirect_index,
+ LLVMValueRef value)
+{
+ struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
+ struct gallivm_state *gallivm = bld->bld_base.base.gallivm;
+ const struct tgsi_shader_info *info = bld->bld_base.info;
+ LLVMValueRef attrib_index = NULL;
+ LLVMValueRef vertex_index = NULL;
+ LLVMValueRef channel_index = NULL;
+
+ if (reg->Register.Indirect) {
+ /*
+ * XXX: this is possibly not quite the right value, since file_max may be
+ * larger than the max attrib index, due to it being the max of declared
+ * inputs AND the max vertices per prim (which is 6 for tri adj).
+ * It should however be safe to use (since we always allocate
+ * PIPE_MAX_SHADER_INPUTS (80) for it, which is overallocated quite a bit).
+ */
+ int index_limit = info->file_max[reg->Register.File];
+ attrib_index = get_indirect_index(bld,
+ reg->Register.File,
+ reg->Register.Index,
+ ®->Indirect,
+ index_limit);
+ } else {
+ attrib_index = lp_build_const_int32(gallivm, reg->Register.Index);
+ }
+
+ if (reg->Dimension.Indirect) {
+ vertex_index = get_indirect_index(bld,
+ reg->Register.File,
+ reg->Dimension.Index,
+ ®->DimIndirect,
+ PIPE_MAX_SHADER_OUTPUTS);
+ } else {
+ vertex_index = lp_build_const_int32(gallivm, reg->Dimension.Index);
+ }
+
+ channel_index = lp_build_const_int32(gallivm, chan_index);
+
+ assert(bld->tcs_iface->emit_store_output);
+ bld->tcs_iface->emit_store_output(bld->tcs_iface, (struct lp_build_context*)bld_base,
+ bld_base->info->output_semantic_name[reg->Register.Index],
+ reg->Dimension.Indirect,
+ vertex_index,
+ reg->Register.Indirect,
+ attrib_index,
+ channel_index,
+ value,
+ mask_vec(bld_base));
+}
+
+static void
+emit_store_temp(struct lp_build_tgsi_context *bld_base,
+ enum tgsi_opcode_type dtype,
+ const struct tgsi_full_dst_register *reg,
+ unsigned index,
+ unsigned chan_index,
+ LLVMValueRef indirect_index,
+ LLVMValueRef value)
+{
+ struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
+ struct gallivm_state *gallivm = bld_base->base.gallivm;
+ LLVMBuilderRef builder = gallivm->builder;
+ struct lp_build_context *float_bld = &bld_base->base;
+
+ /* Temporaries are always stored as floats */
+ if (!tgsi_type_is_64bit(dtype))
+ value = LLVMBuildBitCast(builder, value, float_bld->vec_type, "");
+ else
+ value = LLVMBuildBitCast(builder, value, LLVMVectorType(LLVMFloatTypeInContext(gallivm->context), bld_base->base.type.length * 2), "");
+
+ if (reg->Register.Indirect) {
+ LLVMValueRef index_vec; /* indexes into the temp registers */
+ LLVMValueRef temps_array;
+ LLVMTypeRef fptr_type;
+
+ index_vec = get_soa_array_offsets(&bld_base->uint_bld,
+ indirect_index,
+ chan_index,
+ TRUE);
+
+ fptr_type = LLVMPointerType(LLVMFloatTypeInContext(gallivm->context), 0);
+ temps_array = LLVMBuildBitCast(builder, bld->temps_array, fptr_type, "");
+
+ /* Scatter store values into temp registers */
+ emit_mask_scatter(bld, temps_array, index_vec, value,
+ &bld->exec_mask);
+ }
+ else {
+ LLVMValueRef temp_ptr;
+ temp_ptr = lp_get_temp_ptr_soa(bld, reg->Register.Index, chan_index);
+
+ if (tgsi_type_is_64bit(dtype)) {
+ LLVMValueRef temp_ptr2 = lp_get_temp_ptr_soa(bld,
+ reg->Register.Index,
+ chan_index + 1);
+ emit_store_64bit_chan(bld_base, temp_ptr, temp_ptr2,
+ value);
+ }
+ else
+ lp_exec_mask_store(&bld->exec_mask, float_bld, value, temp_ptr);
+ }
+}
+
+static void
+emit_store_address(struct lp_build_tgsi_context *bld_base,
+ enum tgsi_opcode_type dtype,
+ const struct tgsi_full_dst_register *reg,
+ unsigned index,
+ unsigned chan_index,
+ LLVMValueRef indirect_index,
+ LLVMValueRef value)
+{
+ struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
+ struct gallivm_state *gallivm = bld_base->base.gallivm;
+ LLVMBuilderRef builder = gallivm->builder;
+ struct lp_build_context *int_bld = &bld_base->int_bld;
+
+ assert(dtype == TGSI_TYPE_SIGNED);
+ assert(LLVMTypeOf(value) == int_bld->vec_type);
+ value = LLVMBuildBitCast(builder, value, int_bld->vec_type, "");
+ lp_exec_mask_store(&bld->exec_mask, int_bld, value,
+ bld->addr[reg->Register.Index][chan_index]);
+}
+