-/*
- * bytestream -> r600 shader
- *
- * These functions are used to transform the output of the LLVM backend into
- * struct r600_bytecode.
- */
-
-static void r600_bytecode_from_byte_stream(struct r600_shader_ctx *ctx,
- unsigned char * bytes, unsigned num_bytes);
-
-#ifdef HAVE_OPENCL
-int r600_compute_shader_create(struct pipe_context * ctx,
- LLVMModuleRef mod, struct r600_bytecode * bytecode)
-{
- struct r600_context *r600_ctx = (struct r600_context *)ctx;
- unsigned char * bytes;
- unsigned byte_count;
- struct r600_shader_ctx shader_ctx;
- unsigned dump = 0;
-
- if (debug_get_bool_option("R600_DUMP_SHADERS", FALSE)) {
- dump = 1;
- }
-
- r600_llvm_compile(mod, &bytes, &byte_count, r600_ctx->family , dump);
- shader_ctx.bc = bytecode;
- r600_bytecode_init(shader_ctx.bc, r600_ctx->chip_class, r600_ctx->family);
- shader_ctx.bc->type = TGSI_PROCESSOR_COMPUTE;
- r600_bytecode_from_byte_stream(&shader_ctx, bytes, byte_count);
- if (shader_ctx.bc->chip_class == CAYMAN) {
- cm_bytecode_add_cf_end(shader_ctx.bc);
- }
- r600_bytecode_build(shader_ctx.bc);
- if (dump) {
- r600_bytecode_dump(shader_ctx.bc);
- }
- return 1;
-}
-
-#endif /* HAVE_OPENCL */
-
-static unsigned r600_src_from_byte_stream(unsigned char * bytes,
- unsigned bytes_read, struct r600_bytecode_alu * alu, unsigned src_idx)
-{
- unsigned i;
- unsigned sel0, sel1;
- sel0 = bytes[bytes_read++];
- sel1 = bytes[bytes_read++];
- alu->src[src_idx].sel = sel0 | (sel1 << 8);
- alu->src[src_idx].chan = bytes[bytes_read++];
- alu->src[src_idx].neg = bytes[bytes_read++];
- alu->src[src_idx].abs = bytes[bytes_read++];
- alu->src[src_idx].rel = bytes[bytes_read++];
- alu->src[src_idx].kc_bank = bytes[bytes_read++];
- for (i = 0; i < 4; i++) {
- alu->src[src_idx].value |= bytes[bytes_read++] << (i * 8);
- }
- return bytes_read;
-}
-
-static unsigned r600_alu_from_byte_stream(struct r600_shader_ctx *ctx,
- unsigned char * bytes, unsigned bytes_read)
-{
- unsigned src_idx;
- unsigned inst0, inst1;
- struct r600_bytecode_alu alu;
- memset(&alu, 0, sizeof(alu));
- for(src_idx = 0; src_idx < 3; src_idx++) {
- bytes_read = r600_src_from_byte_stream(bytes, bytes_read,
- &alu, src_idx);
- }
-
- alu.dst.sel = bytes[bytes_read++];
- alu.dst.chan = bytes[bytes_read++];
- alu.dst.clamp = bytes[bytes_read++];
- alu.dst.write = bytes[bytes_read++];
- alu.dst.rel = bytes[bytes_read++];
- inst0 = bytes[bytes_read++];
- inst1 = bytes[bytes_read++];
- alu.inst = inst0 | (inst1 << 8);
- alu.last = bytes[bytes_read++];
- alu.is_op3 = bytes[bytes_read++];
- alu.predicate = bytes[bytes_read++];
- alu.bank_swizzle = bytes[bytes_read++];
- alu.bank_swizzle_force = bytes[bytes_read++];
- alu.omod = bytes[bytes_read++];
- alu.index_mode = bytes[bytes_read++];
- r600_bytecode_add_alu(ctx->bc, &alu);
-
- /* XXX: Handle other KILL instructions */
- if (alu.inst == CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT)) {
- ctx->shader->uses_kill = 1;
- /* XXX: This should be enforced in the LLVM backend. */
- ctx->bc->force_add_cf = 1;
- }
- return bytes_read;
-}
-
-static void llvm_if(struct r600_shader_ctx *ctx, struct r600_bytecode_alu * alu,
- unsigned pred_inst)
-{
- alu->inst = pred_inst;
- alu->predicate = 1;
- alu->dst.write = 0;
- alu->src[1].sel = V_SQ_ALU_SRC_0;
- alu->src[1].chan = 0;
- alu->last = 1;
- r600_bytecode_add_alu_type(ctx->bc, alu,
- CTX_INST(V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE));
-
- r600_bytecode_add_cfinst(ctx->bc, CTX_INST(V_SQ_CF_WORD1_SQ_CF_INST_JUMP));
- fc_pushlevel(ctx, FC_IF);
- callstack_check_depth(ctx, FC_PUSH_VPM, 0);
-}
-
-static void r600_break_from_byte_stream(struct r600_shader_ctx *ctx,
- struct r600_bytecode_alu *alu, unsigned compare_opcode)
-{
- unsigned opcode = TGSI_OPCODE_BRK;
- if (ctx->bc->chip_class == CAYMAN)
- ctx->inst_info = &cm_shader_tgsi_instruction[opcode];
- else if (ctx->bc->chip_class >= EVERGREEN)
- ctx->inst_info = &eg_shader_tgsi_instruction[opcode];
- else
- ctx->inst_info = &r600_shader_tgsi_instruction[opcode];
- llvm_if(ctx, alu, compare_opcode);
- tgsi_loop_brk_cont(ctx);
- tgsi_endif(ctx);
-}
-
-static unsigned r600_fc_from_byte_stream(struct r600_shader_ctx *ctx,
- unsigned char * bytes, unsigned bytes_read)
-{
- struct r600_bytecode_alu alu;
- unsigned inst;
- memset(&alu, 0, sizeof(alu));
- bytes_read = r600_src_from_byte_stream(bytes, bytes_read, &alu, 0);
- inst = bytes[bytes_read++];
- switch (inst) {
- case 0:
- llvm_if(ctx, &alu,
- CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE));
- break;
- case 1:
- tgsi_else(ctx);
- break;
- case 2:
- tgsi_endif(ctx);
- break;
- case 3:
- tgsi_bgnloop(ctx);
- break;
- case 4:
- tgsi_endloop(ctx);
- break;
- case 5:
- r600_break_from_byte_stream(ctx, &alu,
- CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE));
- break;
- case 6:
- r600_break_from_byte_stream(ctx, &alu,
- CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE_INT));
- break;
- case 7:
- {
- unsigned opcode = TGSI_OPCODE_CONT;
- if (ctx->bc->chip_class == CAYMAN) {
- ctx->inst_info =
- &cm_shader_tgsi_instruction[opcode];
- } else if (ctx->bc->chip_class >= EVERGREEN) {
- ctx->inst_info =
- &eg_shader_tgsi_instruction[opcode];
- } else {
- ctx->inst_info =
- &r600_shader_tgsi_instruction[opcode];
- }
- tgsi_loop_brk_cont(ctx);
- }
- break;
- case 8:
- r600_break_from_byte_stream(ctx, &alu,
- CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE_INT));
- break;
- }
-
- return bytes_read;
-}
-
-static unsigned r600_tex_from_byte_stream(struct r600_shader_ctx *ctx,
- unsigned char * bytes, unsigned bytes_read)
-{
- struct r600_bytecode_tex tex;
-
- tex.inst = bytes[bytes_read++];
- tex.resource_id = bytes[bytes_read++];
- tex.src_gpr = bytes[bytes_read++];
- tex.src_rel = bytes[bytes_read++];
- tex.dst_gpr = bytes[bytes_read++];
- tex.dst_rel = bytes[bytes_read++];
- tex.dst_sel_x = bytes[bytes_read++];
- tex.dst_sel_y = bytes[bytes_read++];
- tex.dst_sel_z = bytes[bytes_read++];
- tex.dst_sel_w = bytes[bytes_read++];
- tex.lod_bias = bytes[bytes_read++];
- tex.coord_type_x = bytes[bytes_read++];
- tex.coord_type_y = bytes[bytes_read++];
- tex.coord_type_z = bytes[bytes_read++];
- tex.coord_type_w = bytes[bytes_read++];
- tex.offset_x = bytes[bytes_read++];
- tex.offset_y = bytes[bytes_read++];
- tex.offset_z = bytes[bytes_read++];
- tex.sampler_id = bytes[bytes_read++];
- tex.src_sel_x = bytes[bytes_read++];
- tex.src_sel_y = bytes[bytes_read++];
- tex.src_sel_z = bytes[bytes_read++];
- tex.src_sel_w = bytes[bytes_read++];
-
- r600_bytecode_add_tex(ctx->bc, &tex);
-
- return bytes_read;
-}
-
-static int r600_vtx_from_byte_stream(struct r600_shader_ctx *ctx,
- unsigned char * bytes, unsigned bytes_read)
-{
- struct r600_bytecode_vtx vtx;
- memset(&vtx, 0, sizeof(vtx));
- vtx.inst = bytes[bytes_read++];
- vtx.fetch_type = bytes[bytes_read++];
- vtx.buffer_id = bytes[bytes_read++];
- vtx.src_gpr = bytes[bytes_read++];
- vtx.src_sel_x = bytes[bytes_read++];
- vtx.mega_fetch_count = bytes[bytes_read++];
- vtx.dst_gpr = bytes[bytes_read++];
- vtx.dst_sel_x = bytes[bytes_read++];
- vtx.dst_sel_y = bytes[bytes_read++];
- vtx.dst_sel_z = bytes[bytes_read++];
- vtx.dst_sel_w = bytes[bytes_read++];
- vtx.use_const_fields = bytes[bytes_read++];
- vtx.data_format = bytes[bytes_read++];
- vtx.num_format_all = bytes[bytes_read++];
- vtx.format_comp_all = bytes[bytes_read++];
- vtx.srf_mode_all = bytes[bytes_read++];
- /* offset is 2 bytes wide */
- vtx.offset = bytes[bytes_read++];
- vtx.offset |= (bytes[bytes_read++] << 8);
- vtx.endian = bytes[bytes_read++];
-
- if (r600_bytecode_add_vtx(ctx->bc, &vtx)) {
- fprintf(stderr, "Error adding vtx\n");
- }
- /* Use the Texture Cache */
- ctx->bc->cf_last->inst = EG_V_SQ_CF_WORD1_SQ_CF_INST_TEX;
- return bytes_read;
-}
-
-static void r600_bytecode_from_byte_stream(struct r600_shader_ctx *ctx,
- unsigned char * bytes, unsigned num_bytes)
-{
- unsigned bytes_read = 0;
- unsigned i, byte;
- while (bytes_read < num_bytes) {
- char inst_type = bytes[bytes_read++];
- switch (inst_type) {
- case 0:
- bytes_read = r600_alu_from_byte_stream(ctx, bytes,
- bytes_read);
- break;
- case 1:
- bytes_read = r600_tex_from_byte_stream(ctx, bytes,
- bytes_read);
- break;
- case 2:
- bytes_read = r600_fc_from_byte_stream(ctx, bytes,
- bytes_read);
- break;
- case 3:
- r600_bytecode_add_cfinst(ctx->bc, CF_NATIVE);
- for (i = 0; i < 2; i++) {
- for (byte = 0 ; byte < 4; byte++) {
- ctx->bc->cf_last->isa[i] |=
- (bytes[bytes_read++] << (byte * 8));
- }
- }
- break;
-
- case 4:
- bytes_read = r600_vtx_from_byte_stream(ctx, bytes,
- bytes_read);
- break;
- default:
- /* XXX: Error here */
- break;
- }
- }
-}
-
-/* End bytestream -> r600 shader functions*/
-