static boolean iter_instruction( struct tgsi_iterate_context *iter, struct tgsi_full_instruction *inst ) { struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter; const struct tgsi_opcode_info *info; uint i; if (inst->Instruction.Opcode == TGSI_OPCODE_END) { if (ctx->index_of_END != ~0) { report_error( ctx, "Too many END instructions" ); } ctx->index_of_END = ctx->num_instructions; } info = tgsi_get_opcode_info( inst->Instruction.Opcode ); if (info == NULL) { report_error( ctx, "(%u): Invalid instruction opcode", inst->Instruction.Opcode ); return TRUE; } if (info->num_dst != inst->Instruction.NumDstRegs) { report_error( ctx, "Invalid number of destination operands, should be %u", info->num_dst ); } if (info->num_src != inst->Instruction.NumSrcRegs) { report_error( ctx, "Invalid number of source operands, should be %u", info->num_src ); } /* Check destination and source registers' validity. * Mark the registers as used. */ for (i = 0; i < inst->Instruction.NumDstRegs; i++) { check_register_usage( ctx, inst->FullDstRegisters[i].DstRegister.File, inst->FullDstRegisters[i].DstRegister.Index, "destination", FALSE ); } for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { check_register_usage( ctx, inst->FullSrcRegisters[i].SrcRegister.File, inst->FullSrcRegisters[i].SrcRegister.Index, "source", (boolean)inst->FullSrcRegisters[i].SrcRegister.Indirect ); if (inst->FullSrcRegisters[i].SrcRegister.Indirect) { uint file; int index; file = inst->FullSrcRegisters[i].SrcRegisterInd.File; index = inst->FullSrcRegisters[i].SrcRegisterInd.Index; check_register_usage( ctx, file, index, "indirect", FALSE ); if (file != TGSI_FILE_ADDRESS || index != 0) report_warning( ctx, "Indirect register not ADDR[0]" ); } } ctx->num_instructions++; return TRUE; }
static boolean iter_instruction( struct tgsi_iterate_context *iter, struct tgsi_full_instruction *inst ) { struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter; const struct tgsi_opcode_info *info; uint i; if (inst->Instruction.Opcode == TGSI_OPCODE_END) { if (ctx->index_of_END != ~0) { report_error( ctx, "Too many END instructions" ); } ctx->index_of_END = ctx->num_instructions; } info = tgsi_get_opcode_info( inst->Instruction.Opcode ); if (!info) { report_error( ctx, "(%u): Invalid instruction opcode", inst->Instruction.Opcode ); return TRUE; } if (info->num_dst != inst->Instruction.NumDstRegs) { report_error( ctx, "%s: Invalid number of destination operands, should be %u", info->mnemonic, info->num_dst ); } if (info->num_src != inst->Instruction.NumSrcRegs) { report_error( ctx, "%s: Invalid number of source operands, should be %u", info->mnemonic, info->num_src ); } /* Check destination and source registers' validity. * Mark the registers as used. */ for (i = 0; i < inst->Instruction.NumDstRegs; i++) { scan_register *reg = create_scan_register_dst(&inst->Dst[i]); check_register_usage( ctx, reg, "destination", FALSE ); if (!inst->Dst[i].Register.WriteMask) { report_error(ctx, "Destination register has empty writemask"); } } for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { scan_register *reg = create_scan_register_src(&inst->Src[i]); check_register_usage( ctx, reg, "source", (boolean)inst->Src[i].Register.Indirect ); if (inst->Src[i].Register.Indirect) { scan_register *ind_reg = MALLOC(sizeof(scan_register)); fill_scan_register1d(ind_reg, inst->Src[i].Indirect.File, inst->Src[i].Indirect.Index); check_register_usage( ctx, ind_reg, "indirect", FALSE ); } } ctx->num_instructions++; return TRUE; }