Home | History | Annotate | Download | only in sb
      1 /*
      2  * Copyright 2013 Vadim Girlin <vadimgirlin (at) gmail.com>
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * on the rights to use, copy, modify, merge, publish, distribute, sub
      8  * license, and/or sell copies of the Software, and to permit persons to whom
      9  * the Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     18  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
     19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     21  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     22  *
     23  * Authors:
     24  *      Vadim Girlin
     25  */
     26 
     27 #include "sb_bc.h"
     28 #include "sb_shader.h"
     29 #include "sb_pass.h"
     30 
     31 namespace r600_sb {
     32 
     33 bc_builder::bc_builder(shader &s)
     34 	: sh(s), ctx(s.get_ctx()), bb(ctx.hw_class_bit()), error(0) {}
     35 
     36 int bc_builder::build() {
     37 
     38 	container_node *root = sh.root;
     39 	int cf_cnt = 0;
     40 
     41 	// FIXME reserve total size to avoid reallocs
     42 
     43 	for (node_iterator it = root->begin(), end = root->end();
     44 			it != end; ++it) {
     45 
     46 		cf_node *cf = static_cast<cf_node*>(*it);
     47 		assert(cf->is_cf_inst() || cf->is_alu_clause() || cf->is_fetch_clause());
     48 
     49 		cf_op_flags flags = (cf_op_flags)cf->bc.op_ptr->flags;
     50 
     51 		cf->bc.id = cf_cnt++;
     52 
     53 		if (flags & CF_ALU) {
     54 			if (cf->bc.is_alu_extended())
     55 				cf_cnt++;
     56 		}
     57 	}
     58 
     59 	bb.set_size(cf_cnt << 1);
     60 	bb.seek(cf_cnt << 1);
     61 
     62 	unsigned cf_pos = 0;
     63 
     64 	for (node_iterator I = root->begin(), end = root->end();
     65 			I != end; ++I) {
     66 
     67 		cf_node *cf = static_cast<cf_node*>(*I);
     68 		cf_op_flags flags = (cf_op_flags)cf->bc.op_ptr->flags;
     69 
     70 		if (flags & CF_ALU) {
     71 			bb.seek(bb.ndw());
     72 			cf->bc.addr = bb.ndw() >> 1;
     73 			build_alu_clause(cf);
     74 			cf->bc.count = (bb.ndw() >> 1) - cf->bc.addr - 1;
     75 		} else if (flags & CF_FETCH) {
     76 			bb.align(4);
     77 			bb.seek(bb.ndw());
     78 			cf->bc.addr = bb.ndw() >> 1;
     79 			build_fetch_clause(cf);
     80 			cf->bc.count = (((bb.ndw() >> 1) - cf->bc.addr) >> 1) - 1;
     81 		} else if (cf->jump_target) {
     82 			cf->bc.addr = cf->jump_target->bc.id;
     83 			if (cf->jump_after_target)
     84 				cf->bc.addr += 1;
     85 		}
     86 
     87 		bb.seek(cf_pos);
     88 		build_cf(cf);
     89 		cf_pos = bb.get_pos();
     90 	}
     91 
     92 	return 0;
     93 }
     94 
     95 int bc_builder::build_alu_clause(cf_node* n) {
     96 	for (node_iterator I = n->begin(),	E = n->end();
     97 			I != E; ++I) {
     98 
     99 		alu_group_node *g = static_cast<alu_group_node*>(*I);
    100 		assert(g->is_valid());
    101 
    102 		build_alu_group(g);
    103 	}
    104 	return 0;
    105 }
    106 
    107 int bc_builder::build_alu_group(alu_group_node* n) {
    108 
    109 	for (node_iterator I = n->begin(),	E = n->end();
    110 			I != E; ++I) {
    111 
    112 		alu_node *a = static_cast<alu_node*>(*I);
    113 		assert(a->is_valid());
    114 		build_alu(a);
    115 	}
    116 
    117 	for(int i = 0, ls = n->literals.size(); i < ls; ++i) {
    118 		bb << n->literals.at(i).u;
    119 	}
    120 
    121 	bb.align(2);
    122 	bb.seek(bb.ndw());
    123 
    124 	return 0;
    125 }
    126 
    127 int bc_builder::build_fetch_clause(cf_node* n) {
    128 	for (node_iterator I = n->begin(), E = n->end();
    129 			I != E; ++I) {
    130 		fetch_node *f = static_cast<fetch_node*>(*I);
    131 
    132 		if (f->bc.op_ptr->flags & FF_GDS)
    133 			build_fetch_gds(f);
    134 		else if (f->bc.op_ptr->flags & FF_VTX)
    135 			build_fetch_vtx(f);
    136 		else
    137 			build_fetch_tex(f);
    138 	}
    139 	return 0;
    140 }
    141 
    142 
    143 int bc_builder::build_cf(cf_node* n) {
    144 	const bc_cf &bc = n->bc;
    145 	const cf_op_info *cfop = bc.op_ptr;
    146 
    147 	if (cfop->flags & CF_ALU)
    148 		return build_cf_alu(n);
    149 	if (cfop->flags & (CF_EXP | CF_MEM))
    150 		return build_cf_exp(n);
    151 
    152 	if (ctx.is_egcm()) {
    153 		bb << CF_WORD0_EGCM()
    154 				.ADDR(bc.addr)
    155 				.JUMPTABLE_SEL(bc.jumptable_sel);
    156 
    157 		if (ctx.is_evergreen())
    158 
    159 			bb << CF_WORD1_EG()
    160 					.BARRIER(bc.barrier)
    161 					.CF_CONST(bc.cf_const)
    162 					.CF_INST(ctx.cf_opcode(bc.op))
    163 					.COND(bc.cond)
    164 					.COUNT(bc.count)
    165 					.END_OF_PROGRAM(bc.end_of_program)
    166 					.POP_COUNT(bc.pop_count)
    167 					.VALID_PIXEL_MODE(bc.valid_pixel_mode)
    168 					.WHOLE_QUAD_MODE(bc.whole_quad_mode);
    169 
    170 		else //cayman
    171 
    172 			bb << CF_WORD1_CM()
    173 					.BARRIER(bc.barrier)
    174 					.CF_CONST(bc.cf_const)
    175 					.CF_INST(ctx.cf_opcode(bc.op))
    176 					.COND(bc.cond)
    177 					.COUNT(bc.count)
    178 					.POP_COUNT(bc.pop_count)
    179 					.VALID_PIXEL_MODE(bc.valid_pixel_mode);
    180 	} else {
    181 		bb << CF_WORD0_R6R7()
    182 				.ADDR(bc.addr);
    183 
    184 		assert(bc.count < ctx.max_fetch);
    185 
    186 		bb << CF_WORD1_R6R7()
    187 				.BARRIER(bc.barrier)
    188 				.CALL_COUNT(bc.call_count)
    189 				.CF_CONST(bc.cf_const)
    190 				.CF_INST(ctx.cf_opcode(bc.op))
    191 				.COND(bc.cond)
    192 				.COUNT(bc.count & 7)
    193 				.COUNT_3(bc.count >> 3)
    194 				.END_OF_PROGRAM(bc.end_of_program)
    195 				.POP_COUNT(bc.pop_count)
    196 				.VALID_PIXEL_MODE(bc.valid_pixel_mode)
    197 				.WHOLE_QUAD_MODE(bc.whole_quad_mode);
    198 	}
    199 
    200 	return 0;
    201 }
    202 
    203 int bc_builder::build_cf_alu(cf_node* n) {
    204 	const bc_cf &bc = n->bc;
    205 
    206 	assert(bc.count < 128);
    207 
    208 	if (n->bc.is_alu_extended()) {
    209 		assert(ctx.is_egcm());
    210 
    211 		bb << CF_ALU_WORD0_EXT_EGCM()
    212 				.KCACHE_BANK2(bc.kc[2].bank)
    213 				.KCACHE_BANK3(bc.kc[3].bank)
    214 				.KCACHE_BANK_INDEX_MODE0(bc.kc[0].index_mode)
    215 				.KCACHE_BANK_INDEX_MODE1(bc.kc[1].index_mode)
    216 				.KCACHE_BANK_INDEX_MODE2(bc.kc[2].index_mode)
    217 				.KCACHE_BANK_INDEX_MODE3(bc.kc[3].index_mode)
    218 				.KCACHE_MODE2(bc.kc[2].mode);
    219 
    220 		bb << CF_ALU_WORD1_EXT_EGCM()
    221 				.BARRIER(bc.barrier)
    222 				.CF_INST(ctx.cf_opcode(CF_OP_ALU_EXT))
    223 				.KCACHE_ADDR2(bc.kc[2].addr)
    224 				.KCACHE_ADDR3(bc.kc[3].addr)
    225 				.KCACHE_MODE3(bc.kc[3].mode);
    226 	}
    227 
    228 	bb << CF_ALU_WORD0_ALL()
    229 			.ADDR(bc.addr)
    230 			.KCACHE_BANK0(bc.kc[0].bank)
    231 			.KCACHE_BANK1(bc.kc[1].bank)
    232 			.KCACHE_MODE0(bc.kc[0].mode);
    233 
    234 	assert(bc.count < 128);
    235 
    236 	if (ctx.is_r600())
    237 		bb << CF_ALU_WORD1_R6()
    238 				.BARRIER(bc.barrier)
    239 				.CF_INST(ctx.cf_opcode(bc.op))
    240 				.COUNT(bc.count)
    241 				.KCACHE_ADDR0(bc.kc[0].addr)
    242 				.KCACHE_ADDR1(bc.kc[1].addr)
    243 				.KCACHE_MODE1(bc.kc[1].mode)
    244 				.USES_WATERFALL(bc.uses_waterfall)
    245 				.WHOLE_QUAD_MODE(bc.whole_quad_mode);
    246 	else
    247 		bb << CF_ALU_WORD1_R7EGCM()
    248 				.ALT_CONST(bc.alt_const)
    249 				.BARRIER(bc.barrier)
    250 				.CF_INST(ctx.cf_opcode(bc.op))
    251 				.COUNT(bc.count)
    252 				.KCACHE_ADDR0(bc.kc[0].addr)
    253 				.KCACHE_ADDR1(bc.kc[1].addr)
    254 				.KCACHE_MODE1(bc.kc[1].mode)
    255 				.WHOLE_QUAD_MODE(bc.whole_quad_mode);
    256 
    257 	return 0;
    258 }
    259 
    260 int bc_builder::build_cf_exp(cf_node* n) {
    261 	const bc_cf &bc = n->bc;
    262 	const cf_op_info *cfop = bc.op_ptr;
    263 
    264 	if (cfop->flags & CF_RAT) {
    265 		assert(ctx.is_egcm());
    266 
    267 		bb << CF_ALLOC_EXPORT_WORD0_RAT_EGCM()
    268 				.ELEM_SIZE(bc.elem_size)
    269 				.INDEX_GPR(bc.index_gpr)
    270 				.RAT_ID(bc.rat_id)
    271 				.RAT_INDEX_MODE(bc.rat_index_mode)
    272 				.RAT_INST(bc.rat_inst)
    273 				.RW_GPR(bc.rw_gpr)
    274 				.RW_REL(bc.rw_rel)
    275 				.TYPE(bc.type);
    276 	} else {
    277 
    278 		bb << CF_ALLOC_EXPORT_WORD0_ALL()
    279 					.ARRAY_BASE(bc.array_base)
    280 					.ELEM_SIZE(bc.elem_size)
    281 					.INDEX_GPR(bc.index_gpr)
    282 					.RW_GPR(bc.rw_gpr)
    283 					.RW_REL(bc.rw_rel)
    284 					.TYPE(bc.type);
    285 	}
    286 
    287 	if (cfop->flags & CF_EXP) {
    288 
    289 		if (!ctx.is_egcm())
    290 			bb << CF_ALLOC_EXPORT_WORD1_SWIZ_R6R7()
    291 					.BARRIER(bc.barrier)
    292 					.BURST_COUNT(bc.burst_count)
    293 					.CF_INST(ctx.cf_opcode(bc.op))
    294 					.END_OF_PROGRAM(bc.end_of_program)
    295 					.SEL_X(bc.sel[0])
    296 					.SEL_Y(bc.sel[1])
    297 					.SEL_Z(bc.sel[2])
    298 					.SEL_W(bc.sel[3])
    299 					.VALID_PIXEL_MODE(bc.valid_pixel_mode)
    300 					.WHOLE_QUAD_MODE(bc.whole_quad_mode);
    301 
    302 		else if (ctx.is_evergreen())
    303 			bb << CF_ALLOC_EXPORT_WORD1_SWIZ_EG()
    304 					.BARRIER(bc.barrier)
    305 					.BURST_COUNT(bc.burst_count)
    306 					.CF_INST(ctx.cf_opcode(bc.op))
    307 					.END_OF_PROGRAM(bc.end_of_program)
    308 					.MARK(bc.mark)
    309 					.SEL_X(bc.sel[0])
    310 					.SEL_Y(bc.sel[1])
    311 					.SEL_Z(bc.sel[2])
    312 					.SEL_W(bc.sel[3])
    313 					.VALID_PIXEL_MODE(bc.valid_pixel_mode);
    314 
    315 		else // cayman
    316 			bb << CF_ALLOC_EXPORT_WORD1_SWIZ_CM()
    317 					.BARRIER(bc.barrier)
    318 					.BURST_COUNT(bc.burst_count)
    319 					.CF_INST(ctx.cf_opcode(bc.op))
    320 					.MARK(bc.mark)
    321 					.SEL_X(bc.sel[0])
    322 					.SEL_Y(bc.sel[1])
    323 					.SEL_Z(bc.sel[2])
    324 					.SEL_W(bc.sel[3])
    325 					.VALID_PIXEL_MODE(bc.valid_pixel_mode);
    326 
    327 	} else if (cfop->flags & CF_MEM) {
    328 		return build_cf_mem(n);
    329 	}
    330 
    331 	return 0;
    332 }
    333 
    334 int bc_builder::build_cf_mem(cf_node* n) {
    335 	const bc_cf &bc = n->bc;
    336 
    337 	if (!ctx.is_egcm())
    338 		bb << CF_ALLOC_EXPORT_WORD1_BUF_R6R7()
    339 				.ARR_SIZE(bc.array_size)
    340 				.BARRIER(bc.barrier)
    341 				.BURST_COUNT(bc.burst_count)
    342 				.CF_INST(ctx.cf_opcode(bc.op))
    343 				.COMP_MASK(bc.comp_mask)
    344 				.END_OF_PROGRAM(bc.end_of_program)
    345 				.VALID_PIXEL_MODE(bc.valid_pixel_mode)
    346 				.WHOLE_QUAD_MODE(bc.whole_quad_mode);
    347 
    348 	else if (ctx.is_evergreen())
    349 		bb << CF_ALLOC_EXPORT_WORD1_BUF_EG()
    350 				.ARR_SIZE(bc.array_size)
    351 				.BARRIER(bc.barrier)
    352 				.BURST_COUNT(bc.burst_count)
    353 				.CF_INST(ctx.cf_opcode(bc.op))
    354 				.COMP_MASK(bc.comp_mask)
    355 				.END_OF_PROGRAM(bc.end_of_program)
    356 				.MARK(bc.mark)
    357 				.VALID_PIXEL_MODE(bc.valid_pixel_mode);
    358 
    359 	else // cayman
    360 		bb << CF_ALLOC_EXPORT_WORD1_BUF_CM()
    361 		.ARR_SIZE(bc.array_size)
    362 		.BARRIER(bc.barrier)
    363 		.BURST_COUNT(bc.burst_count)
    364 		.CF_INST(ctx.cf_opcode(bc.op))
    365 		.COMP_MASK(bc.comp_mask)
    366 		.MARK(bc.mark)
    367 		.VALID_PIXEL_MODE(bc.valid_pixel_mode);
    368 
    369 	return 0;
    370 }
    371 
    372 int bc_builder::build_alu(alu_node* n) {
    373 	const bc_alu &bc = n->bc;
    374 	const alu_op_info *aop = bc.op_ptr;
    375 
    376 	if (n->bc.op_ptr->flags & AF_LDS) {
    377 		assert(ctx.is_egcm());
    378 		bb << ALU_WORD0_LDS_IDX_OP_EGCM()
    379 			.SRC0_SEL(bc.src[0].sel)
    380 			.SRC0_REL(bc.src[0].rel)
    381 			.SRC0_CHAN(bc.src[0].chan)
    382 			.IDX_OFFSET_4((bc.lds_idx_offset >> 4) & 1)
    383 			.SRC1_SEL(bc.src[1].sel)
    384 			.SRC1_REL(bc.src[1].rel)
    385 			.SRC1_CHAN(bc.src[1].chan)
    386 			.IDX_OFFSET_5((bc.lds_idx_offset >> 5) & 1)
    387 			.INDEX_MODE(bc.index_mode)
    388 			.PRED_SEL(bc.pred_sel)
    389 			.LAST(bc.last);
    390 
    391 		bb << ALU_WORD1_LDS_IDX_OP_EGCM()
    392 			.SRC2_SEL(bc.src[2].sel)
    393 			.SRC2_REL(bc.src[2].rel)
    394 			.SRC2_CHAN(bc.src[2].chan)
    395 			.IDX_OFFSET_1((bc.lds_idx_offset >> 1) & 1)
    396 			.ALU_INST(ctx.alu_opcode(ALU_OP3_LDS_IDX_OP))
    397 			.BANK_SWIZZLE(bc.bank_swizzle)
    398 			.LDS_OP((bc.op_ptr->opcode[1] >> 8) & 0xff)
    399 			.IDX_OFFSET_0((bc.lds_idx_offset >> 0) & 1)
    400 			.IDX_OFFSET_2((bc.lds_idx_offset >> 2) & 1)
    401 			.DST_CHAN(bc.dst_chan)
    402 			.IDX_OFFSET_3((bc.lds_idx_offset >> 3) & 1);
    403 
    404 		return 0;
    405 	}
    406 
    407 	bb << ALU_WORD0_ALL()
    408 			.INDEX_MODE(bc.index_mode)
    409 			.LAST(bc.last)
    410 			.PRED_SEL(bc.pred_sel)
    411 			.SRC0_SEL(bc.src[0].sel)
    412 			.SRC0_CHAN(bc.src[0].chan)
    413 			.SRC0_NEG(bc.src[0].neg)
    414 			.SRC0_REL(bc.src[0].rel)
    415 			.SRC1_SEL(bc.src[1].sel)
    416 			.SRC1_CHAN(bc.src[1].chan)
    417 			.SRC1_NEG(bc.src[1].neg)
    418 			.SRC1_REL(bc.src[1].rel);
    419 
    420 	if (aop->src_count<3) {
    421 		if (ctx.is_r600())
    422 			bb << ALU_WORD1_OP2_R6()
    423 					.ALU_INST(ctx.alu_opcode(bc.op))
    424 					.BANK_SWIZZLE(bc.bank_swizzle)
    425 					.CLAMP(bc.clamp)
    426 					.DST_GPR(bc.dst_gpr)
    427 					.DST_CHAN(bc.dst_chan)
    428 					.DST_REL(bc.dst_rel)
    429 					.FOG_MERGE(bc.fog_merge)
    430 					.OMOD(bc.omod)
    431 					.SRC0_ABS(bc.src[0].abs)
    432 					.SRC1_ABS(bc.src[1].abs)
    433 					.UPDATE_EXEC_MASK(bc.update_exec_mask)
    434 					.UPDATE_PRED(bc.update_pred)
    435 					.WRITE_MASK(bc.write_mask);
    436 		else {
    437 
    438 			if (ctx.is_cayman() && (aop->flags & AF_MOVA)) {
    439 
    440 				bb << ALU_WORD1_OP2_MOVA_CM()
    441 						.ALU_INST(ctx.alu_opcode(bc.op))
    442 						.BANK_SWIZZLE(bc.bank_swizzle)
    443 						.CLAMP(bc.clamp)
    444 						.MOVA_DST(bc.dst_gpr)
    445 						.DST_CHAN(bc.dst_chan)
    446 						.DST_REL(bc.dst_rel)
    447 						.OMOD(bc.omod)
    448 						.UPDATE_EXEC_MASK(bc.update_exec_mask)
    449 						.UPDATE_PRED(bc.update_pred)
    450 						.WRITE_MASK(bc.write_mask)
    451 						.SRC0_ABS(bc.src[0].abs)
    452 						.SRC1_ABS(bc.src[1].abs);
    453 
    454 			} else if (ctx.is_cayman() && (aop->flags & (AF_PRED|AF_KILL))) {
    455 				bb << ALU_WORD1_OP2_EXEC_MASK_CM()
    456 						.ALU_INST(ctx.alu_opcode(bc.op))
    457 						.BANK_SWIZZLE(bc.bank_swizzle)
    458 						.CLAMP(bc.clamp)
    459 						.DST_CHAN(bc.dst_chan)
    460 						.DST_REL(bc.dst_rel)
    461 						.EXECUTE_MASK_OP(bc.omod)
    462 						.UPDATE_EXEC_MASK(bc.update_exec_mask)
    463 						.UPDATE_PRED(bc.update_pred)
    464 						.WRITE_MASK(bc.write_mask)
    465 						.SRC0_ABS(bc.src[0].abs)
    466 						.SRC1_ABS(bc.src[1].abs);
    467 
    468 			} else
    469 				bb << ALU_WORD1_OP2_R7EGCM()
    470 						.ALU_INST(ctx.alu_opcode(bc.op))
    471 						.BANK_SWIZZLE(bc.bank_swizzle)
    472 						.CLAMP(bc.clamp)
    473 						.DST_GPR(bc.dst_gpr)
    474 						.DST_CHAN(bc.dst_chan)
    475 						.DST_REL(bc.dst_rel)
    476 						.OMOD(bc.omod)
    477 						.UPDATE_EXEC_MASK(bc.update_exec_mask)
    478 						.UPDATE_PRED(bc.update_pred)
    479 						.WRITE_MASK(bc.write_mask)
    480 						.SRC0_ABS(bc.src[0].abs)
    481 						.SRC1_ABS(bc.src[1].abs);
    482 
    483 		}
    484 	} else
    485 		bb << ALU_WORD1_OP3_ALL()
    486 				.ALU_INST(ctx.alu_opcode(bc.op))
    487 				.BANK_SWIZZLE(bc.bank_swizzle)
    488 				.CLAMP(bc.clamp)
    489 				.DST_GPR(bc.dst_gpr)
    490 				.DST_CHAN(bc.dst_chan)
    491 				.DST_REL(bc.dst_rel)
    492 				.SRC2_SEL(bc.src[2].sel)
    493 				.SRC2_CHAN(bc.src[2].chan)
    494 				.SRC2_NEG(bc.src[2].neg)
    495 				.SRC2_REL(bc.src[2].rel);
    496 	return 0;
    497 }
    498 
    499 int bc_builder::build_fetch_tex(fetch_node* n) {
    500 	const bc_fetch &bc = n->bc;
    501 	const fetch_op_info *fop = bc.op_ptr;
    502 
    503 	assert(!(fop->flags & FF_VTX));
    504 
    505 	if (ctx.is_r600())
    506 		bb << TEX_WORD0_R6()
    507 				.BC_FRAC_MODE(bc.bc_frac_mode)
    508 				.FETCH_WHOLE_QUAD(bc.fetch_whole_quad)
    509 				.RESOURCE_ID(bc.resource_id)
    510 				.SRC_GPR(bc.src_gpr)
    511 				.SRC_REL(bc.src_rel)
    512 				.TEX_INST(ctx.fetch_opcode(bc.op));
    513 
    514 	else if (ctx.is_r700())
    515 		bb << TEX_WORD0_R7()
    516 				.ALT_CONST(bc.alt_const)
    517 				.BC_FRAC_MODE(bc.bc_frac_mode)
    518 				.FETCH_WHOLE_QUAD(bc.fetch_whole_quad)
    519 				.RESOURCE_ID(bc.resource_id)
    520 				.SRC_GPR(bc.src_gpr)
    521 				.SRC_REL(bc.src_rel)
    522 				.TEX_INST(ctx.fetch_opcode(bc.op));
    523 
    524 	else
    525 		bb << TEX_WORD0_EGCM()
    526 				.ALT_CONST(bc.alt_const)
    527 				.FETCH_WHOLE_QUAD(bc.fetch_whole_quad)
    528 				.INST_MOD(bc.inst_mod)
    529 				.RESOURCE_ID(bc.resource_id)
    530 				.RESOURCE_INDEX_MODE(bc.resource_index_mode)
    531 				.SAMPLER_INDEX_MODE(bc.sampler_index_mode)
    532 				.SRC_GPR(bc.src_gpr)
    533 				.SRC_REL(bc.src_rel)
    534 				.TEX_INST(ctx.fetch_opcode(bc.op));
    535 
    536 	bb << TEX_WORD1_ALL()
    537 			.COORD_TYPE_X(bc.coord_type[0])
    538 			.COORD_TYPE_Y(bc.coord_type[1])
    539 			.COORD_TYPE_Z(bc.coord_type[2])
    540 			.COORD_TYPE_W(bc.coord_type[3])
    541 			.DST_GPR(bc.dst_gpr)
    542 			.DST_REL(bc.dst_rel)
    543 			.DST_SEL_X(bc.dst_sel[0])
    544 			.DST_SEL_Y(bc.dst_sel[1])
    545 			.DST_SEL_Z(bc.dst_sel[2])
    546 			.DST_SEL_W(bc.dst_sel[3])
    547 			.LOD_BIAS(bc.lod_bias);
    548 
    549 	bb << TEX_WORD2_ALL()
    550 			.OFFSET_X(bc.offset[0])
    551 			.OFFSET_Y(bc.offset[1])
    552 			.OFFSET_Z(bc.offset[2])
    553 			.SAMPLER_ID(bc.sampler_id)
    554 			.SRC_SEL_X(bc.src_sel[0])
    555 			.SRC_SEL_Y(bc.src_sel[1])
    556 			.SRC_SEL_Z(bc.src_sel[2])
    557 			.SRC_SEL_W(bc.src_sel[3]);
    558 
    559 	bb << 0;
    560 	return 0;
    561 }
    562 
    563 int bc_builder::build_fetch_gds(fetch_node *n) {
    564 	const bc_fetch &bc = n->bc;
    565 	const fetch_op_info *fop = bc.op_ptr;
    566 	unsigned gds_op = (ctx.fetch_opcode(bc.op) >> 8) & 0x3f;
    567 	unsigned mem_op = 4;
    568 	assert(fop->flags && FF_GDS);
    569 
    570 	if (bc.op == FETCH_OP_TF_WRITE) {
    571 		mem_op = 5;
    572 		gds_op = 0;
    573 	}
    574 
    575 	bb << MEM_GDS_WORD0_EGCM()
    576 		.MEM_INST(2)
    577 		.MEM_OP(mem_op)
    578 		.SRC_GPR(bc.src_gpr)
    579 		.SRC_SEL_X(bc.src_sel[0])
    580 		.SRC_SEL_Y(bc.src_sel[1])
    581 		.SRC_SEL_Z(bc.src_sel[2]);
    582 
    583 	bb << MEM_GDS_WORD1_EGCM()
    584 		.DST_GPR(bc.dst_gpr)
    585 		.DST_REL_MODE(bc.dst_rel)
    586 		.GDS_OP(gds_op)
    587 		.SRC_GPR(bc.src2_gpr)
    588 		.UAV_INDEX_MODE(bc.uav_index_mode)
    589 		.UAV_ID(bc.uav_id)
    590 		.ALLOC_CONSUME(bc.alloc_consume)
    591 		.BCAST_FIRST_REQ(bc.bcast_first_req);
    592 
    593 	bb << MEM_GDS_WORD2_EGCM()
    594 		.DST_SEL_X(bc.dst_sel[0])
    595 		.DST_SEL_Y(bc.dst_sel[1])
    596 		.DST_SEL_Z(bc.dst_sel[2])
    597 		.DST_SEL_W(bc.dst_sel[3]);
    598 
    599 	bb << 0;
    600 	return 0;
    601 }
    602 
    603 int bc_builder::build_fetch_vtx(fetch_node* n) {
    604 	const bc_fetch &bc = n->bc;
    605 	const fetch_op_info *fop = bc.op_ptr;
    606 
    607 	assert(fop->flags & FF_VTX);
    608 
    609 	if (!ctx.is_cayman())
    610 		bb << VTX_WORD0_R6R7EG()
    611 				.BUFFER_ID(bc.resource_id)
    612 				.FETCH_TYPE(bc.fetch_type)
    613 				.FETCH_WHOLE_QUAD(bc.fetch_whole_quad)
    614 				.MEGA_FETCH_COUNT(bc.mega_fetch_count)
    615 				.SRC_GPR(bc.src_gpr)
    616 				.SRC_REL(bc.src_rel)
    617 				.SRC_SEL_X(bc.src_sel[0])
    618 				.VC_INST(ctx.fetch_opcode(bc.op));
    619 
    620 	else
    621 		bb << VTX_WORD0_CM()
    622 				.BUFFER_ID(bc.resource_id)
    623 				.COALESCED_READ(bc.coalesced_read)
    624 				.FETCH_TYPE(bc.fetch_type)
    625 				.FETCH_WHOLE_QUAD(bc.fetch_whole_quad)
    626 				.LDS_REQ(bc.lds_req)
    627 				.SRC_GPR(bc.src_gpr)
    628 				.SRC_REL(bc.src_rel)
    629 				.SRC_SEL_X(bc.src_sel[0])
    630 				.SRC_SEL_Y(bc.src_sel[1])
    631 				.STRUCTURED_READ(bc.structured_read)
    632 				.VC_INST(ctx.fetch_opcode(bc.op));
    633 
    634 	if (bc.op == FETCH_OP_SEMFETCH)
    635 		bb << VTX_WORD1_SEM_ALL()
    636 				.DATA_FORMAT(bc.data_format)
    637 				.DST_SEL_X(bc.dst_sel[0])
    638 				.DST_SEL_Y(bc.dst_sel[1])
    639 				.DST_SEL_Z(bc.dst_sel[2])
    640 				.DST_SEL_W(bc.dst_sel[3])
    641 				.FORMAT_COMP_ALL(bc.format_comp_all)
    642 				.NUM_FORMAT_ALL(bc.num_format_all)
    643 				.SEMANTIC_ID(bc.semantic_id)
    644 				.SRF_MODE_ALL(bc.srf_mode_all)
    645 				.USE_CONST_FIELDS(bc.use_const_fields);
    646 	else
    647 		bb << VTX_WORD1_GPR_ALL()
    648 				.DATA_FORMAT(bc.data_format)
    649 				.DST_GPR(bc.dst_gpr)
    650 				.DST_REL(bc.dst_rel)
    651 				.DST_SEL_X(bc.dst_sel[0])
    652 				.DST_SEL_Y(bc.dst_sel[1])
    653 				.DST_SEL_Z(bc.dst_sel[2])
    654 				.DST_SEL_W(bc.dst_sel[3])
    655 				.FORMAT_COMP_ALL(bc.format_comp_all)
    656 				.NUM_FORMAT_ALL(bc.num_format_all)
    657 				.SRF_MODE_ALL(bc.srf_mode_all)
    658 				.USE_CONST_FIELDS(bc.use_const_fields);
    659 
    660 	switch (ctx.hw_class) {
    661 	case HW_CLASS_R600:
    662 		bb << VTX_WORD2_R6()
    663 				.CONST_BUF_NO_STRIDE(bc.const_buf_no_stride)
    664 				.ENDIAN_SWAP(bc.endian_swap)
    665 				.MEGA_FETCH(bc.mega_fetch)
    666 				.OFFSET(bc.offset[0]);
    667 		break;
    668 	case HW_CLASS_R700:
    669 		bb << VTX_WORD2_R7()
    670 				.ALT_CONST(bc.alt_const)
    671 				.CONST_BUF_NO_STRIDE(bc.const_buf_no_stride)
    672 				.ENDIAN_SWAP(bc.endian_swap)
    673 				.MEGA_FETCH(bc.mega_fetch)
    674 				.OFFSET(bc.offset[0]);
    675 		break;
    676 	case HW_CLASS_EVERGREEN:
    677 		bb << VTX_WORD2_EG()
    678 				.ALT_CONST(bc.alt_const)
    679 				.BUFFER_INDEX_MODE(bc.resource_index_mode)
    680 				.CONST_BUF_NO_STRIDE(bc.const_buf_no_stride)
    681 				.ENDIAN_SWAP(bc.endian_swap)
    682 				.MEGA_FETCH(bc.mega_fetch)
    683 				.OFFSET(bc.offset[0]);
    684 		break;
    685 	case HW_CLASS_CAYMAN:
    686 		bb << VTX_WORD2_CM()
    687 				.ALT_CONST(bc.alt_const)
    688 				.BUFFER_INDEX_MODE(bc.resource_index_mode)
    689 				.CONST_BUF_NO_STRIDE(bc.const_buf_no_stride)
    690 				.ENDIAN_SWAP(bc.endian_swap)
    691 				.OFFSET(bc.offset[0]);
    692 		break;
    693 	default:
    694 		assert(!"unknown hw class");
    695 		return -1;
    696 	}
    697 
    698 	bb << 0;
    699 	return 0;
    700 }
    701 
    702 }
    703