static boolean match_inst(const char **pcur, unsigned *saturate, unsigned *precise, const struct tgsi_opcode_info *info) { const char *cur = *pcur; const char *mnemonic = tgsi_get_opcode_name(info->opcode); /* simple case: the whole string matches the instruction name */ if (str_match_nocase_whole(&cur, mnemonic)) { *pcur = cur; *saturate = 0; *precise = 0; return TRUE; } if (str_match_no_case(&cur, mnemonic)) { /* the instruction has a suffix, figure it out */ if (str_match_no_case(&cur, "_SAT")) { *pcur = cur; *saturate = 1; } if (str_match_no_case(&cur, "_PRECISE")) { *pcur = cur; *precise = 1; } if (!is_digit_alpha_underscore(cur)) return TRUE; } return FALSE; }
static unsigned translate_opcode(unsigned opcode) { switch(opcode) { case TGSI_OPCODE_ARL: return RC_OPCODE_ARL; case TGSI_OPCODE_MOV: return RC_OPCODE_MOV; case TGSI_OPCODE_LIT: return RC_OPCODE_LIT; case TGSI_OPCODE_RCP: return RC_OPCODE_RCP; case TGSI_OPCODE_RSQ: return RC_OPCODE_RSQ; case TGSI_OPCODE_EXP: return RC_OPCODE_EXP; case TGSI_OPCODE_LOG: return RC_OPCODE_LOG; case TGSI_OPCODE_MUL: return RC_OPCODE_MUL; case TGSI_OPCODE_ADD: return RC_OPCODE_ADD; case TGSI_OPCODE_DP3: return RC_OPCODE_DP3; case TGSI_OPCODE_DP4: return RC_OPCODE_DP4; case TGSI_OPCODE_DST: return RC_OPCODE_DST; case TGSI_OPCODE_MIN: return RC_OPCODE_MIN; case TGSI_OPCODE_MAX: return RC_OPCODE_MAX; case TGSI_OPCODE_SLT: return RC_OPCODE_SLT; case TGSI_OPCODE_SGE: return RC_OPCODE_SGE; case TGSI_OPCODE_MAD: return RC_OPCODE_MAD; case TGSI_OPCODE_SUB: return RC_OPCODE_SUB; case TGSI_OPCODE_LRP: return RC_OPCODE_LRP; case TGSI_OPCODE_CND: return RC_OPCODE_CND; /* case TGSI_OPCODE_DP2A: return RC_OPCODE_DP2A; */ /* gap */ case TGSI_OPCODE_FRC: return RC_OPCODE_FRC; case TGSI_OPCODE_CLAMP: return RC_OPCODE_CLAMP; case TGSI_OPCODE_FLR: return RC_OPCODE_FLR; case TGSI_OPCODE_ROUND: return RC_OPCODE_ROUND; case TGSI_OPCODE_EX2: return RC_OPCODE_EX2; case TGSI_OPCODE_LG2: return RC_OPCODE_LG2; case TGSI_OPCODE_POW: return RC_OPCODE_POW; case TGSI_OPCODE_XPD: return RC_OPCODE_XPD; /* gap */ case TGSI_OPCODE_ABS: return RC_OPCODE_ABS; /* case TGSI_OPCODE_RCC: return RC_OPCODE_RCC; */ case TGSI_OPCODE_DPH: return RC_OPCODE_DPH; case TGSI_OPCODE_COS: return RC_OPCODE_COS; case TGSI_OPCODE_DDX: return RC_OPCODE_DDX; case TGSI_OPCODE_DDY: return RC_OPCODE_DDY; case TGSI_OPCODE_KILP: return RC_OPCODE_KILP; /* case TGSI_OPCODE_PK2H: return RC_OPCODE_PK2H; */ /* case TGSI_OPCODE_PK2US: return RC_OPCODE_PK2US; */ /* case TGSI_OPCODE_PK4B: return RC_OPCODE_PK4B; */ /* case TGSI_OPCODE_PK4UB: return RC_OPCODE_PK4UB; */ /* case TGSI_OPCODE_RFL: return RC_OPCODE_RFL; */ case TGSI_OPCODE_SEQ: return RC_OPCODE_SEQ; case TGSI_OPCODE_SFL: return RC_OPCODE_SFL; case TGSI_OPCODE_SGT: return RC_OPCODE_SGT; case TGSI_OPCODE_SIN: return RC_OPCODE_SIN; case TGSI_OPCODE_SLE: return RC_OPCODE_SLE; case TGSI_OPCODE_SNE: return RC_OPCODE_SNE; /* case TGSI_OPCODE_STR: return RC_OPCODE_STR; */ case TGSI_OPCODE_TEX: return RC_OPCODE_TEX; case TGSI_OPCODE_TXD: return RC_OPCODE_TXD; case TGSI_OPCODE_TXP: return RC_OPCODE_TXP; /* case TGSI_OPCODE_UP2H: return RC_OPCODE_UP2H; */ /* case TGSI_OPCODE_UP2US: return RC_OPCODE_UP2US; */ /* case TGSI_OPCODE_UP4B: return RC_OPCODE_UP4B; */ /* case TGSI_OPCODE_UP4UB: return RC_OPCODE_UP4UB; */ /* case TGSI_OPCODE_X2D: return RC_OPCODE_X2D; */ /* case TGSI_OPCODE_ARA: return RC_OPCODE_ARA; */ /* case TGSI_OPCODE_ARR: return RC_OPCODE_ARR; */ /* case TGSI_OPCODE_BRA: return RC_OPCODE_BRA; */ /* case TGSI_OPCODE_CAL: return RC_OPCODE_CAL; */ /* case TGSI_OPCODE_RET: return RC_OPCODE_RET; */ case TGSI_OPCODE_SSG: return RC_OPCODE_SSG; case TGSI_OPCODE_CMP: return RC_OPCODE_CMP; case TGSI_OPCODE_SCS: return RC_OPCODE_SCS; case TGSI_OPCODE_TXB: return RC_OPCODE_TXB; /* case TGSI_OPCODE_NRM: return RC_OPCODE_NRM; */ /* case TGSI_OPCODE_DIV: return RC_OPCODE_DIV; */ case TGSI_OPCODE_DP2: return RC_OPCODE_DP2; case TGSI_OPCODE_TXL: return RC_OPCODE_TXL; case TGSI_OPCODE_BRK: return RC_OPCODE_BRK; case TGSI_OPCODE_IF: return RC_OPCODE_IF; case TGSI_OPCODE_BGNLOOP: return RC_OPCODE_BGNLOOP; case TGSI_OPCODE_ELSE: return RC_OPCODE_ELSE; case TGSI_OPCODE_ENDIF: return RC_OPCODE_ENDIF; case TGSI_OPCODE_ENDLOOP: return RC_OPCODE_ENDLOOP; /* case TGSI_OPCODE_PUSHA: return RC_OPCODE_PUSHA; */ /* case TGSI_OPCODE_POPA: return RC_OPCODE_POPA; */ case TGSI_OPCODE_CEIL: return RC_OPCODE_CEIL; /* case TGSI_OPCODE_I2F: return RC_OPCODE_I2F; */ /* case TGSI_OPCODE_NOT: return RC_OPCODE_NOT; */ case TGSI_OPCODE_TRUNC: return RC_OPCODE_TRUNC; /* case TGSI_OPCODE_SHL: return RC_OPCODE_SHL; */ /* case TGSI_OPCODE_ISHR: return RC_OPCODE_SHR; */ /* case TGSI_OPCODE_AND: return RC_OPCODE_AND; */ /* case TGSI_OPCODE_OR: return RC_OPCODE_OR; */ /* case TGSI_OPCODE_MOD: return RC_OPCODE_MOD; */ /* case TGSI_OPCODE_XOR: return RC_OPCODE_XOR; */ /* case TGSI_OPCODE_SAD: return RC_OPCODE_SAD; */ /* case TGSI_OPCODE_TXF: return RC_OPCODE_TXF; */ /* case TGSI_OPCODE_TXQ: return RC_OPCODE_TXQ; */ case TGSI_OPCODE_CONT: return RC_OPCODE_CONT; /* case TGSI_OPCODE_EMIT: return RC_OPCODE_EMIT; */ /* case TGSI_OPCODE_ENDPRIM: return RC_OPCODE_ENDPRIM; */ /* case TGSI_OPCODE_BGNLOOP2: return RC_OPCODE_BGNLOOP2; */ /* case TGSI_OPCODE_BGNSUB: return RC_OPCODE_BGNSUB; */ /* case TGSI_OPCODE_ENDLOOP2: return RC_OPCODE_ENDLOOP2; */ /* case TGSI_OPCODE_ENDSUB: return RC_OPCODE_ENDSUB; */ case TGSI_OPCODE_NOP: return RC_OPCODE_NOP; /* gap */ /* case TGSI_OPCODE_NRM4: return RC_OPCODE_NRM4; */ /* case TGSI_OPCODE_CALLNZ: return RC_OPCODE_CALLNZ; */ /* case TGSI_OPCODE_IFC: return RC_OPCODE_IFC; */ /* case TGSI_OPCODE_BREAKC: return RC_OPCODE_BREAKC; */ case TGSI_OPCODE_KIL: return RC_OPCODE_KIL; } fprintf(stderr, "r300: Unknown TGSI/RC opcode: %s\n", tgsi_get_opcode_name(opcode)); return RC_OPCODE_ILLEGAL_OPCODE; }
void lp_build_tgsi_aos(struct gallivm_state *gallivm, const struct tgsi_token *tokens, struct lp_type type, const unsigned char swizzles[4], LLVMValueRef consts_ptr, const LLVMValueRef *inputs, LLVMValueRef *outputs, struct lp_build_sampler_aos *sampler, const struct tgsi_shader_info *info) { struct lp_build_tgsi_aos_context bld; struct tgsi_parse_context parse; uint num_immediates = 0; unsigned chan; int pc = 0; /* Setup build context */ memset(&bld, 0, sizeof bld); lp_build_context_init(&bld.bld_base.base, gallivm, type); lp_build_context_init(&bld.bld_base.uint_bld, gallivm, lp_uint_type(type)); lp_build_context_init(&bld.bld_base.int_bld, gallivm, lp_int_type(type)); lp_build_context_init(&bld.int_bld, gallivm, lp_int_type(type)); for (chan = 0; chan < 4; ++chan) { bld.swizzles[chan] = swizzles[chan]; bld.inv_swizzles[swizzles[chan]] = chan; } bld.inputs = inputs; bld.outputs = outputs; bld.consts_ptr = consts_ptr; bld.sampler = sampler; bld.indirect_files = info->indirect_files; bld.bld_base.emit_swizzle = swizzle_aos; bld.bld_base.info = info; bld.bld_base.emit_fetch_funcs[TGSI_FILE_CONSTANT] = emit_fetch_constant; bld.bld_base.emit_fetch_funcs[TGSI_FILE_IMMEDIATE] = emit_fetch_immediate; bld.bld_base.emit_fetch_funcs[TGSI_FILE_INPUT] = emit_fetch_input; bld.bld_base.emit_fetch_funcs[TGSI_FILE_TEMPORARY] = emit_fetch_temporary; /* Set opcode actions */ lp_set_default_actions_cpu(&bld.bld_base); if (!lp_bld_tgsi_list_init(&bld.bld_base)) { return; } tgsi_parse_init(&parse, tokens); while (!tgsi_parse_end_of_tokens(&parse)) { tgsi_parse_token(&parse); switch(parse.FullToken.Token.Type) { case TGSI_TOKEN_TYPE_DECLARATION: /* Inputs already interpolated */ lp_emit_declaration_aos(&bld, &parse.FullToken.FullDeclaration); break; case TGSI_TOKEN_TYPE_INSTRUCTION: /* save expanded instruction */ lp_bld_tgsi_add_instruction(&bld.bld_base, &parse.FullToken.FullInstruction); break; case TGSI_TOKEN_TYPE_IMMEDIATE: /* simply copy the immediate values into the next immediates[] slot */ { const uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1; float imm[4]; assert(size <= 4); assert(num_immediates < LP_MAX_INLINED_IMMEDIATES); for (chan = 0; chan < 4; ++chan) { imm[chan] = 0.0f; } for (chan = 0; chan < size; ++chan) { unsigned swizzle = bld.swizzles[chan]; imm[swizzle] = parse.FullToken.FullImmediate.u[chan].Float; } bld.immediates[num_immediates] = lp_build_const_aos(gallivm, type, imm[0], imm[1], imm[2], imm[3], NULL); num_immediates++; } break; case TGSI_TOKEN_TYPE_PROPERTY: break; default: assert(0); } } while (pc != -1) { struct tgsi_full_instruction *instr = bld.bld_base.instructions + pc; const struct tgsi_opcode_info *opcode_info = tgsi_get_opcode_info(instr->Instruction.Opcode); if (!lp_emit_instruction_aos(&bld, instr, opcode_info, &pc)) _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n", tgsi_get_opcode_name(instr->Instruction.Opcode)); } if (0) { LLVMBasicBlockRef block = LLVMGetInsertBlock(gallivm->builder); LLVMValueRef function = LLVMGetBasicBlockParent(block); debug_printf("11111111111111111111111111111 \n"); tgsi_dump(tokens, 0); lp_debug_dump_value(function); debug_printf("2222222222222222222222222222 \n"); } tgsi_parse_free(&parse); FREE(bld.bld_base.instructions); if (0) { LLVMModuleRef module = LLVMGetGlobalParent( LLVMGetBasicBlockParent(LLVMGetInsertBlock(gallivm->builder))); LLVMDumpModule(module); } }