Path: blob/21.2-virgl/src/gallium/frontends/d3d10umd/ShaderParse.c
4565 views
/**************************************************************************1*2* Copyright 2012-2021 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL16* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,17* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR18* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE19* USE OR OTHER DEALINGS IN THE SOFTWARE.20*21* The above copyright notice and this permission notice (including the22* next paragraph) shall be included in all copies or substantial portions23* of the Software.24*25**************************************************************************/2627/*28* ShaderParse.c --29* Functions for parsing shader tokens.30*/3132#include "Debug.h"33#include "ShaderParse.h"3435#include "util/u_memory.h"363738void39Shader_parse_init(struct Shader_parser *parser,40const unsigned *code)41{42parser->curr = parser->code = code;4344parser->header.type = DECODE_D3D10_SB_TOKENIZED_PROGRAM_TYPE(*parser->curr);45parser->header.major_version = DECODE_D3D10_SB_TOKENIZED_PROGRAM_MAJOR_VERSION(*parser->curr);46parser->header.minor_version = DECODE_D3D10_SB_TOKENIZED_PROGRAM_MINOR_VERSION(*parser->curr);47parser->curr++;4849parser->header.size = DECODE_D3D10_SB_TOKENIZED_PROGRAM_LENGTH(*parser->curr);50parser->curr++;51}5253#define OP_NOT_DONE (1 << 0) /* not implemented yet */54#define OP_SATURATE (1 << 1) /* saturate in opcode specific control */55#define OP_TEST_BOOLEAN (1 << 2) /* test boolean in opcode specific control */56#define OP_DCL (1 << 3) /* custom opcode specific control */57#define OP_RESINFO_RET_TYPE (1 << 4) /* return type for resinfo */5859struct dx10_opcode_info {60D3D10_SB_OPCODE_TYPE type;61const char *name;62unsigned num_dst;63unsigned num_src;64unsigned flags;65};6667#define _(_opcode) _opcode, #_opcode6869static const struct dx10_opcode_info70opcode_info[D3D10_SB_NUM_OPCODES] = {71{_(D3D10_SB_OPCODE_ADD), 1, 2, OP_SATURATE},72{_(D3D10_SB_OPCODE_AND), 1, 2, 0},73{_(D3D10_SB_OPCODE_BREAK), 0, 0, 0},74{_(D3D10_SB_OPCODE_BREAKC), 0, 1, OP_TEST_BOOLEAN},75{_(D3D10_SB_OPCODE_CALL), 0, 1, 0},76{_(D3D10_SB_OPCODE_CALLC), 0, 2, OP_TEST_BOOLEAN},77{_(D3D10_SB_OPCODE_CASE), 0, 1, 0},78{_(D3D10_SB_OPCODE_CONTINUE), 0, 0, 0},79{_(D3D10_SB_OPCODE_CONTINUEC), 0, 1, OP_TEST_BOOLEAN},80{_(D3D10_SB_OPCODE_CUT), 0, 0, 0},81{_(D3D10_SB_OPCODE_DEFAULT), 0, 0, 0},82{_(D3D10_SB_OPCODE_DERIV_RTX), 1, 1, OP_SATURATE},83{_(D3D10_SB_OPCODE_DERIV_RTY), 1, 1, OP_SATURATE},84{_(D3D10_SB_OPCODE_DISCARD), 0, 1, OP_TEST_BOOLEAN},85{_(D3D10_SB_OPCODE_DIV), 1, 2, OP_SATURATE},86{_(D3D10_SB_OPCODE_DP2), 1, 2, OP_SATURATE},87{_(D3D10_SB_OPCODE_DP3), 1, 2, OP_SATURATE},88{_(D3D10_SB_OPCODE_DP4), 1, 2, OP_SATURATE},89{_(D3D10_SB_OPCODE_ELSE), 0, 0, 0},90{_(D3D10_SB_OPCODE_EMIT), 0, 0, 0},91{_(D3D10_SB_OPCODE_EMITTHENCUT), 0, 0, 0},92{_(D3D10_SB_OPCODE_ENDIF), 0, 0, 0},93{_(D3D10_SB_OPCODE_ENDLOOP), 0, 0, 0},94{_(D3D10_SB_OPCODE_ENDSWITCH), 0, 0, 0},95{_(D3D10_SB_OPCODE_EQ), 1, 2, 0},96{_(D3D10_SB_OPCODE_EXP), 1, 1, OP_SATURATE},97{_(D3D10_SB_OPCODE_FRC), 1, 1, OP_SATURATE},98{_(D3D10_SB_OPCODE_FTOI), 1, 1, 0},99{_(D3D10_SB_OPCODE_FTOU), 1, 1, 0},100{_(D3D10_SB_OPCODE_GE), 1, 2, 0},101{_(D3D10_SB_OPCODE_IADD), 1, 2, 0},102{_(D3D10_SB_OPCODE_IF), 0, 1, OP_TEST_BOOLEAN},103{_(D3D10_SB_OPCODE_IEQ), 1, 2, 0},104{_(D3D10_SB_OPCODE_IGE), 1, 2, 0},105{_(D3D10_SB_OPCODE_ILT), 1, 2, 0},106{_(D3D10_SB_OPCODE_IMAD), 1, 3, 0},107{_(D3D10_SB_OPCODE_IMAX), 1, 2, 0},108{_(D3D10_SB_OPCODE_IMIN), 1, 2, 0},109{_(D3D10_SB_OPCODE_IMUL), 2, 2, 0},110{_(D3D10_SB_OPCODE_INE), 1, 2, 0},111{_(D3D10_SB_OPCODE_INEG), 1, 1, 0},112{_(D3D10_SB_OPCODE_ISHL), 1, 2, 0},113{_(D3D10_SB_OPCODE_ISHR), 1, 2, 0},114{_(D3D10_SB_OPCODE_ITOF), 1, 1, 0},115{_(D3D10_SB_OPCODE_LABEL), 0, 1, 0},116{_(D3D10_SB_OPCODE_LD), 1, 2, 0},117{_(D3D10_SB_OPCODE_LD_MS), 1, 3, 0},118{_(D3D10_SB_OPCODE_LOG), 1, 1, OP_SATURATE},119{_(D3D10_SB_OPCODE_LOOP), 0, 0, 0},120{_(D3D10_SB_OPCODE_LT), 1, 2, 0},121{_(D3D10_SB_OPCODE_MAD), 1, 3, OP_SATURATE},122{_(D3D10_SB_OPCODE_MIN), 1, 2, OP_SATURATE},123{_(D3D10_SB_OPCODE_MAX), 1, 2, OP_SATURATE},124{_(D3D10_SB_OPCODE_CUSTOMDATA), 0, 0, 0},125{_(D3D10_SB_OPCODE_MOV), 1, 1, OP_SATURATE},126{_(D3D10_SB_OPCODE_MOVC), 1, 3, OP_SATURATE},127{_(D3D10_SB_OPCODE_MUL), 1, 2, OP_SATURATE},128{_(D3D10_SB_OPCODE_NE), 1, 2, 0},129{_(D3D10_SB_OPCODE_NOP), 0, 0, 0},130{_(D3D10_SB_OPCODE_NOT), 1, 1, 0},131{_(D3D10_SB_OPCODE_OR), 1, 2, 0},132{_(D3D10_SB_OPCODE_RESINFO), 1, 2, OP_RESINFO_RET_TYPE},133{_(D3D10_SB_OPCODE_RET), 0, 0, 0},134{_(D3D10_SB_OPCODE_RETC), 0, 1, OP_TEST_BOOLEAN},135{_(D3D10_SB_OPCODE_ROUND_NE), 1, 1, OP_SATURATE},136{_(D3D10_SB_OPCODE_ROUND_NI), 1, 1, OP_SATURATE},137{_(D3D10_SB_OPCODE_ROUND_PI), 1, 1, OP_SATURATE},138{_(D3D10_SB_OPCODE_ROUND_Z), 1, 1, OP_SATURATE},139{_(D3D10_SB_OPCODE_RSQ), 1, 1, OP_SATURATE},140{_(D3D10_SB_OPCODE_SAMPLE), 1, 3, 0},141{_(D3D10_SB_OPCODE_SAMPLE_C), 1, 4, 0},142{_(D3D10_SB_OPCODE_SAMPLE_C_LZ), 1, 4, 0},143{_(D3D10_SB_OPCODE_SAMPLE_L), 1, 4, 0},144{_(D3D10_SB_OPCODE_SAMPLE_D), 1, 5, 0},145{_(D3D10_SB_OPCODE_SAMPLE_B), 1, 4, 0},146{_(D3D10_SB_OPCODE_SQRT), 1, 1, OP_SATURATE},147{_(D3D10_SB_OPCODE_SWITCH), 0, 1, 0},148{_(D3D10_SB_OPCODE_SINCOS), 2, 1, OP_SATURATE},149{_(D3D10_SB_OPCODE_UDIV), 2, 2, 0},150{_(D3D10_SB_OPCODE_ULT), 1, 2, 0},151{_(D3D10_SB_OPCODE_UGE), 1, 2, 0},152{_(D3D10_SB_OPCODE_UMUL), 2, 2, 0},153{_(D3D10_SB_OPCODE_UMAD), 1, 3, 0},154{_(D3D10_SB_OPCODE_UMAX), 1, 2, 0},155{_(D3D10_SB_OPCODE_UMIN), 1, 2, 0},156{_(D3D10_SB_OPCODE_USHR), 1, 2, 0},157{_(D3D10_SB_OPCODE_UTOF), 1, 1, 0},158{_(D3D10_SB_OPCODE_XOR), 1, 2, 0},159{_(D3D10_SB_OPCODE_DCL_RESOURCE), 1, 0, OP_DCL},160{_(D3D10_SB_OPCODE_DCL_CONSTANT_BUFFER), 0, 1, OP_DCL},161{_(D3D10_SB_OPCODE_DCL_SAMPLER), 1, 0, OP_DCL},162{_(D3D10_SB_OPCODE_DCL_INDEX_RANGE), 1, 0, OP_DCL},163{_(D3D10_SB_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY), 0, 0, OP_DCL},164{_(D3D10_SB_OPCODE_DCL_GS_INPUT_PRIMITIVE), 0, 0, OP_DCL},165{_(D3D10_SB_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT), 0, 0, OP_DCL},166{_(D3D10_SB_OPCODE_DCL_INPUT), 1, 0, OP_DCL},167{_(D3D10_SB_OPCODE_DCL_INPUT_SGV), 1, 0, OP_DCL},168{_(D3D10_SB_OPCODE_DCL_INPUT_SIV), 1, 0, OP_DCL},169{_(D3D10_SB_OPCODE_DCL_INPUT_PS), 1, 0, OP_DCL},170{_(D3D10_SB_OPCODE_DCL_INPUT_PS_SGV), 1, 0, OP_DCL},171{_(D3D10_SB_OPCODE_DCL_INPUT_PS_SIV), 1, 0, OP_DCL},172{_(D3D10_SB_OPCODE_DCL_OUTPUT), 1, 0, OP_DCL},173{_(D3D10_SB_OPCODE_DCL_OUTPUT_SGV), 1, 0, OP_DCL},174{_(D3D10_SB_OPCODE_DCL_OUTPUT_SIV), 1, 0, OP_DCL},175{_(D3D10_SB_OPCODE_DCL_TEMPS), 0, 0, OP_DCL},176{_(D3D10_SB_OPCODE_DCL_INDEXABLE_TEMP), 0, 0, OP_DCL},177{_(D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS), 0, 0, OP_DCL},178{_(D3D10_SB_OPCODE_RESERVED0), 0, 0, OP_NOT_DONE},179{_(D3D10_1_SB_OPCODE_LOD), 0, 0, OP_NOT_DONE},180{_(D3D10_1_SB_OPCODE_GATHER4), 0, 0, OP_NOT_DONE},181{_(D3D10_1_SB_OPCODE_SAMPLE_POS), 0, 0, OP_NOT_DONE},182{_(D3D10_1_SB_OPCODE_SAMPLE_INFO), 0, 0, OP_NOT_DONE}183};184185#undef _186187static void188parse_operand(const unsigned **curr,189struct Shader_operand *operand)190{191operand->type = DECODE_D3D10_SB_OPERAND_TYPE(**curr);192193/* Index dimension. */194switch (DECODE_D3D10_SB_OPERAND_INDEX_DIMENSION(**curr)) {195case D3D10_SB_OPERAND_INDEX_0D:196operand->index_dim = 0;197break;198case D3D10_SB_OPERAND_INDEX_1D:199operand->index_dim = 1;200break;201case D3D10_SB_OPERAND_INDEX_2D:202operand->index_dim = 2;203break;204default:205assert(0);206}207208if (operand->index_dim >= 1) {209operand->index[0].index_rep = DECODE_D3D10_SB_OPERAND_INDEX_REPRESENTATION(0, **curr);210if (operand->index_dim >= 2) {211operand->index[1].index_rep = DECODE_D3D10_SB_OPERAND_INDEX_REPRESENTATION(1, **curr);212}213}214215(*curr)++;216}217218static void219parse_relative_operand(const unsigned **curr,220struct Shader_relative_operand *operand)221{222assert(!DECODE_IS_D3D10_SB_OPERAND_EXTENDED(**curr));223assert(DECODE_D3D10_SB_OPERAND_NUM_COMPONENTS(**curr) == D3D10_SB_OPERAND_4_COMPONENT);224assert(DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE(**curr) == D3D10_SB_OPERAND_4_COMPONENT_SELECT_1_MODE);225226operand->comp = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECT_1(**curr);227228operand->type = DECODE_D3D10_SB_OPERAND_TYPE(**curr);229assert(operand->type != D3D10_SB_OPERAND_TYPE_IMMEDIATE32);230231/* Index dimension. */232assert(DECODE_D3D10_SB_OPERAND_INDEX_REPRESENTATION(0, **curr) == D3D10_SB_OPERAND_INDEX_IMMEDIATE32);233234if (DECODE_D3D10_SB_OPERAND_INDEX_DIMENSION(**curr) == D3D10_SB_OPERAND_INDEX_1D) {235(*curr)++;236operand->index[0].imm = **curr;237} else {238assert(DECODE_D3D10_SB_OPERAND_INDEX_DIMENSION(**curr) == D3D10_SB_OPERAND_INDEX_2D);239(*curr)++;240operand->index[0].imm = **curr;241(*curr)++;242operand->index[1].imm = **curr;243244}245(*curr)++;246}247248static void249parse_index(const unsigned **curr,250struct Shader_index *index)251{252switch (index->index_rep) {253case D3D10_SB_OPERAND_INDEX_IMMEDIATE32:254index->imm = *(*curr)++;255break;256case D3D10_SB_OPERAND_INDEX_RELATIVE:257index->imm = 0;258parse_relative_operand(curr, &index->rel);259break;260case D3D10_SB_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE:261index->imm = *(*curr)++;262parse_relative_operand(curr, &index->rel);263break;264default:265/* XXX: Support other index representations.266*/267assert(0);268}269}270271static void272parse_operand_index(const unsigned **curr,273struct Shader_operand *operand)274{275if (operand->index_dim >= 1) {276parse_index(curr, &operand->index[0]);277if (operand->index_dim >= 2) {278parse_index(curr, &operand->index[1]);279}280}281}282283boolean284Shader_parse_opcode(struct Shader_parser *parser,285struct Shader_opcode *opcode)286{287const unsigned *curr = parser->curr;288const struct dx10_opcode_info *info;289unsigned length;290boolean opcode_is_extended;291unsigned i;292293if (curr >= parser->code + parser->header.size) {294return FALSE;295}296297memset(opcode, 0, sizeof *opcode);298299/* Opcode type. */300opcode->type = DECODE_D3D10_SB_OPCODE_TYPE(*curr);301302if (opcode->type == D3D10_SB_OPCODE_CUSTOMDATA) {303opcode->customdata._class = DECODE_D3D10_SB_CUSTOMDATA_CLASS(*curr);304curr++;305306assert(opcode->customdata._class == D3D10_SB_CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER);307308opcode->customdata.u.constbuf.count = *curr - 2;309curr++;310311opcode->customdata.u.constbuf.data = MALLOC(opcode->customdata.u.constbuf.count * sizeof(unsigned));312assert(opcode->customdata.u.constbuf.data);313314memcpy(opcode->customdata.u.constbuf.data,315curr,316opcode->customdata.u.constbuf.count * sizeof(unsigned));317curr += opcode->customdata.u.constbuf.count;318319parser->curr = curr;320return TRUE;321}322323opcode->dcl_siv_name = D3D10_SB_NAME_UNDEFINED;324325/* Lookup extra information based on opcode type. */326assert(opcode->type < D3D10_SB_NUM_OPCODES);327info = &opcode_info[opcode->type];328329/* Opcode specific. */330switch (opcode->type) {331case D3D10_SB_OPCODE_DCL_RESOURCE:332opcode->specific.dcl_resource_dimension = DECODE_D3D10_SB_RESOURCE_DIMENSION(*curr);333break;334case D3D10_SB_OPCODE_DCL_SAMPLER:335opcode->specific.dcl_sampler_mode = DECODE_D3D10_SB_SAMPLER_MODE(*curr);336break;337case D3D10_SB_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY:338opcode->specific.dcl_gs_output_primitive_topology = DECODE_D3D10_SB_GS_OUTPUT_PRIMITIVE_TOPOLOGY(*curr);339break;340case D3D10_SB_OPCODE_DCL_GS_INPUT_PRIMITIVE:341opcode->specific.dcl_gs_input_primitive = DECODE_D3D10_SB_GS_INPUT_PRIMITIVE(*curr);342break;343case D3D10_SB_OPCODE_DCL_INPUT_PS:344case D3D10_SB_OPCODE_DCL_INPUT_PS_SIV:345opcode->specific.dcl_in_ps_interp = DECODE_D3D10_SB_INPUT_INTERPOLATION_MODE(*curr);346break;347case D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS:348opcode->specific.global_flags.refactoring_allowed = DECODE_D3D10_SB_GLOBAL_FLAGS(*curr) ? 1 : 0;349break;350default:351/* Parse opcode-specific control bits */352if (info->flags & OP_DCL) {353/* no-op */354} else if (info->flags & OP_SATURATE) {355opcode->saturate =356!!DECODE_IS_D3D10_SB_INSTRUCTION_SATURATE_ENABLED(*curr);357} else if (info->flags & OP_TEST_BOOLEAN) {358opcode->specific.test_boolean =359DECODE_D3D10_SB_INSTRUCTION_TEST_BOOLEAN(*curr);360} else if (info->flags & OP_RESINFO_RET_TYPE) {361opcode->specific.resinfo_ret_type =362DECODE_D3D10_SB_RESINFO_INSTRUCTION_RETURN_TYPE(*curr);363} else {364/* Warn if there are bits set in the opcode-specific controls (bits 23:11 inclusive)*/365if (*curr & ((1 << 24) - (1 << 11))) {366debug_printf("warning: unexpected opcode-specific control in opcode %s\n",367info->name);368}369}370break;371}372373/* Opcode length in DWORDs. */374length = DECODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(*curr);375assert(curr + length <= parser->code + parser->header.size);376377/* Opcode specific fields in token0. */378switch (opcode->type) {379case D3D10_SB_OPCODE_DCL_CONSTANT_BUFFER:380opcode->specific.dcl_cb_access_pattern =381DECODE_D3D10_SB_CONSTANT_BUFFER_ACCESS_PATTERN(*curr);382break;383default:384break;385}386387opcode_is_extended = DECODE_IS_D3D10_SB_OPCODE_EXTENDED(*curr);388389curr++;390391if (opcode_is_extended) {392/* NOTE: DECODE_IS_D3D10_SB_OPCODE_DOUBLE_EXTENDED is broken.393*/394assert(!((*curr & D3D10_SB_OPCODE_DOUBLE_EXTENDED_MASK) >> D3D10_SB_OPERAND_DOUBLE_EXTENDED_SHIFT));395396switch (DECODE_D3D10_SB_EXTENDED_OPCODE_TYPE(*curr)) {397case D3D10_SB_EXTENDED_OPCODE_EMPTY:398break;399case D3D10_SB_EXTENDED_OPCODE_SAMPLE_CONTROLS:400opcode->imm_texel_offset.u = DECODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET(D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_U, *curr);401opcode->imm_texel_offset.v = DECODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET(D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_V, *curr);402opcode->imm_texel_offset.w = DECODE_IMMEDIATE_D3D10_SB_ADDRESS_OFFSET(D3D10_SB_IMMEDIATE_ADDRESS_OFFSET_W, *curr);403break;404default:405assert(0);406}407408curr++;409}410411if (info->flags & OP_NOT_DONE) {412/* XXX: Need to figure out the number of operands for this opcode.413* Should be okay to continue execution -- we have enough info414* to skip to the next instruction.415*/416LOG_UNSUPPORTED(TRUE);417opcode->num_dst = 0;418opcode->num_src = 0;419goto skip;420}421422opcode->num_dst = info->num_dst;423opcode->num_src = info->num_src;424425/* Destination operands. */426for (i = 0; i < info->num_dst; i++) {427D3D10_SB_OPERAND_NUM_COMPONENTS num_components;428429assert(!DECODE_IS_D3D10_SB_OPERAND_EXTENDED(*curr));430431num_components = DECODE_D3D10_SB_OPERAND_NUM_COMPONENTS(*curr);432if (num_components == D3D10_SB_OPERAND_4_COMPONENT) {433D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE selection_mode;434435selection_mode = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE(*curr);436assert(selection_mode == D3D10_SB_OPERAND_4_COMPONENT_MASK_MODE);437438opcode->dst[i].mask = DECODE_D3D10_SB_OPERAND_4_COMPONENT_MASK(*curr);439} else {440assert(num_components == D3D10_SB_OPERAND_0_COMPONENT ||441num_components == D3D10_SB_OPERAND_1_COMPONENT);442443opcode->dst[i].mask = D3D10_SB_OPERAND_4_COMPONENT_MASK_X;444}445446parse_operand(&curr, &opcode->dst[i].base);447parse_operand_index(&curr, &opcode->dst[i].base);448}449450/* Source operands. */451for (i = 0; i < info->num_src; i++) {452boolean extended;453D3D10_SB_OPERAND_NUM_COMPONENTS num_components;454455extended = DECODE_IS_D3D10_SB_OPERAND_EXTENDED(*curr);456457num_components = DECODE_D3D10_SB_OPERAND_NUM_COMPONENTS(*curr);458if (num_components == D3D10_SB_OPERAND_4_COMPONENT) {459D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE selection_mode;460461selection_mode = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE(*curr);462463if (selection_mode == D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_MODE) {464opcode->src[i].swizzle[0] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SOURCE(*curr, 0);465opcode->src[i].swizzle[1] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SOURCE(*curr, 1);466opcode->src[i].swizzle[2] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SOURCE(*curr, 2);467opcode->src[i].swizzle[3] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_SOURCE(*curr, 3);468} else if (selection_mode == D3D10_SB_OPERAND_4_COMPONENT_SELECT_1_MODE) {469opcode->src[i].swizzle[0] =470opcode->src[i].swizzle[1] =471opcode->src[i].swizzle[2] =472opcode->src[i].swizzle[3] = DECODE_D3D10_SB_OPERAND_4_COMPONENT_SELECT_1(*curr);473} else {474/* This case apparently happens only for 4-component 32-bit475* immediate operands.476*/477assert(selection_mode == D3D10_SB_OPERAND_4_COMPONENT_MASK_MODE);478assert(DECODE_D3D10_SB_OPERAND_4_COMPONENT_MASK(*curr) == 0);479assert(DECODE_D3D10_SB_OPERAND_TYPE(*curr) == D3D10_SB_OPERAND_TYPE_IMMEDIATE32);480481482opcode->src[i].swizzle[0] = D3D10_SB_4_COMPONENT_X;483opcode->src[i].swizzle[1] = D3D10_SB_4_COMPONENT_Y;484opcode->src[i].swizzle[2] = D3D10_SB_4_COMPONENT_Z;485opcode->src[i].swizzle[3] = D3D10_SB_4_COMPONENT_W;486}487} else if (num_components == D3D10_SB_OPERAND_1_COMPONENT) {488opcode->src[i].swizzle[0] =489opcode->src[i].swizzle[1] =490opcode->src[i].swizzle[2] =491opcode->src[i].swizzle[3] = D3D10_SB_4_COMPONENT_X;492} else {493/* Samplers only?494*/495assert(num_components == D3D10_SB_OPERAND_0_COMPONENT);496assert(DECODE_D3D10_SB_OPERAND_TYPE(*curr) == D3D10_SB_OPERAND_TYPE_SAMPLER ||497DECODE_D3D10_SB_OPERAND_TYPE(*curr) == D3D10_SB_OPERAND_TYPE_LABEL);498499opcode->src[i].swizzle[0] = D3D10_SB_4_COMPONENT_X;500opcode->src[i].swizzle[1] = D3D10_SB_4_COMPONENT_Y;501opcode->src[i].swizzle[2] = D3D10_SB_4_COMPONENT_Z;502opcode->src[i].swizzle[3] = D3D10_SB_4_COMPONENT_W;503}504505parse_operand(&curr, &opcode->src[i].base);506507opcode->src[i].modifier = D3D10_SB_OPERAND_MODIFIER_NONE;508if (extended) {509/* NOTE: DECODE_IS_D3D10_SB_OPERAND_DOUBLE_EXTENDED is broken.510*/511assert(!((*curr & D3D10_SB_OPERAND_DOUBLE_EXTENDED_MASK) >> D3D10_SB_OPERAND_DOUBLE_EXTENDED_SHIFT));512513switch (DECODE_D3D10_SB_EXTENDED_OPERAND_TYPE(*curr)) {514case D3D10_SB_EXTENDED_OPERAND_EMPTY:515break;516517case D3D10_SB_EXTENDED_OPERAND_MODIFIER:518opcode->src[i].modifier = DECODE_D3D10_SB_OPERAND_MODIFIER(*curr);519break;520521default:522assert(0);523}524525curr++;526}527528parse_operand_index(&curr, &opcode->src[i].base);529530if (opcode->src[i].base.type == D3D10_SB_OPERAND_TYPE_IMMEDIATE32) {531switch (num_components) {532case D3D10_SB_OPERAND_1_COMPONENT:533opcode->src[i].imm[0].u32 =534opcode->src[i].imm[1].u32 =535opcode->src[i].imm[2].u32 =536opcode->src[i].imm[3].u32 = *curr++;537break;538539case D3D10_SB_OPERAND_4_COMPONENT:540opcode->src[i].imm[0].u32 = *curr++;541opcode->src[i].imm[1].u32 = *curr++;542opcode->src[i].imm[2].u32 = *curr++;543opcode->src[i].imm[3].u32 = *curr++;544break;545546default:547/* XXX: Support other component sizes.548*/549assert(0);550}551}552}553554/* Opcode specific trailing operands. */555switch (opcode->type) {556case D3D10_SB_OPCODE_DCL_RESOURCE:557opcode->dcl_resource_ret_type[0] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*curr, 0);558opcode->dcl_resource_ret_type[1] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*curr, 1);559opcode->dcl_resource_ret_type[2] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*curr, 2);560opcode->dcl_resource_ret_type[3] = DECODE_D3D10_SB_RESOURCE_RETURN_TYPE(*curr, 3);561curr++;562break;563case D3D10_SB_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT:564opcode->specific.dcl_max_output_vertex_count = *curr;565curr++;566break;567case D3D10_SB_OPCODE_DCL_INPUT_SGV:568case D3D10_SB_OPCODE_DCL_INPUT_SIV:569case D3D10_SB_OPCODE_DCL_INPUT_PS_SGV:570case D3D10_SB_OPCODE_DCL_INPUT_PS_SIV:571case D3D10_SB_OPCODE_DCL_OUTPUT_SIV:572case D3D10_SB_OPCODE_DCL_OUTPUT_SGV:573opcode->dcl_siv_name = DECODE_D3D10_SB_NAME(*curr);574curr++;575break;576case D3D10_SB_OPCODE_DCL_TEMPS:577opcode->specific.dcl_num_temps = *curr;578curr++;579break;580case D3D10_SB_OPCODE_DCL_INDEXABLE_TEMP:581opcode->specific.dcl_indexable_temp.index = *curr++;582opcode->specific.dcl_indexable_temp.count = *curr++;583opcode->specific.dcl_indexable_temp.components = *curr++;584break;585case D3D10_SB_OPCODE_DCL_INDEX_RANGE:586opcode->specific.index_range_count = *curr++;587break;588default:589break;590}591592assert(curr == parser->curr + length);593594skip:595/* Advance to the next opcode. */596parser->curr += length;597598return TRUE;599}600601void602Shader_opcode_free(struct Shader_opcode *opcode)603{604if (opcode->type == D3D10_SB_OPCODE_CUSTOMDATA) {605if (opcode->customdata._class == D3D10_SB_CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER) {606FREE(opcode->customdata.u.constbuf.data);607}608}609}610611612