14a49301eSmrg/************************************************************************** 24a49301eSmrg * 3af69d88dSmrg * Copyright 2007 VMware, Inc. 44a49301eSmrg * All Rights Reserved. 54a49301eSmrg * 64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 74a49301eSmrg * copy of this software and associated documentation files (the 84a49301eSmrg * "Software"), to deal in the Software without restriction, including 94a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish, 104a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to 114a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to 124a49301eSmrg * the following conditions: 134a49301eSmrg * 144a49301eSmrg * The above copyright notice and this permission notice (including the 154a49301eSmrg * next paragraph) shall be included in all copies or substantial portions 164a49301eSmrg * of the Software. 174a49301eSmrg * 184a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 194a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 204a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 224a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 234a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 244a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 254a49301eSmrg * 264a49301eSmrg **************************************************************************/ 274a49301eSmrg 284a49301eSmrg#include "util/u_debug.h" 294a49301eSmrg#include "pipe/p_shader_tokens.h" 304a49301eSmrg#include "tgsi_parse.h" 314a49301eSmrg#include "util/u_memory.h" 324a49301eSmrg 334a49301eSmrgunsigned 344a49301eSmrgtgsi_parse_init( 354a49301eSmrg struct tgsi_parse_context *ctx, 364a49301eSmrg const struct tgsi_token *tokens ) 374a49301eSmrg{ 38cdc920a0Smrg ctx->FullHeader.Header = *(struct tgsi_header *) &tokens[0]; 3901e04c3fSmrg if (ctx->FullHeader.Header.HeaderSize >= 2) { 40cdc920a0Smrg ctx->FullHeader.Processor = *(struct tgsi_processor *) &tokens[1]; 414a49301eSmrg } 424a49301eSmrg else { 43cdc920a0Smrg return TGSI_PARSE_ERROR; 444a49301eSmrg } 454a49301eSmrg 464a49301eSmrg ctx->Tokens = tokens; 47cdc920a0Smrg ctx->Position = ctx->FullHeader.Header.HeaderSize; 484a49301eSmrg 494a49301eSmrg return TGSI_PARSE_OK; 504a49301eSmrg} 514a49301eSmrg 524a49301eSmrgvoid 534a49301eSmrgtgsi_parse_free( 5401e04c3fSmrg UNUSED struct tgsi_parse_context *ctx ) 554a49301eSmrg{ 564a49301eSmrg} 574a49301eSmrg 584a49301eSmrgboolean 594a49301eSmrgtgsi_parse_end_of_tokens( 604a49301eSmrg struct tgsi_parse_context *ctx ) 614a49301eSmrg{ 6201e04c3fSmrg /* All values involved are unsigned, but the sum will be promoted to 6301e04c3fSmrg * a signed value (at least on 64 bit). To capture a possible overflow 6401e04c3fSmrg * make it a signed comparison. 6501e04c3fSmrg */ 6601e04c3fSmrg return (int)ctx->Position >= 6701e04c3fSmrg ctx->FullHeader.Header.HeaderSize + ctx->FullHeader.Header.BodySize; 684a49301eSmrg} 694a49301eSmrg 704a49301eSmrg 714a49301eSmrg/** 724a49301eSmrg * This function is used to avoid and work-around type punning/aliasing 734a49301eSmrg * warnings. The warnings seem harmless on x86 but on PPC they cause 744a49301eSmrg * real failures. 754a49301eSmrg */ 7601e04c3fSmrgstatic inline void 774a49301eSmrgcopy_token(void *dst, const void *src) 784a49301eSmrg{ 794a49301eSmrg memcpy(dst, src, 4); 804a49301eSmrg} 814a49301eSmrg 824a49301eSmrg 834a49301eSmrg/** 844a49301eSmrg * Get next 4-byte token, return it at address specified by 'token' 854a49301eSmrg */ 864a49301eSmrgstatic void 874a49301eSmrgnext_token( 884a49301eSmrg struct tgsi_parse_context *ctx, 894a49301eSmrg void *token ) 904a49301eSmrg{ 914a49301eSmrg assert( !tgsi_parse_end_of_tokens( ctx ) ); 924a49301eSmrg copy_token(token, &ctx->Tokens[ctx->Position]); 934a49301eSmrg ctx->Position++; 944a49301eSmrg} 954a49301eSmrg 964a49301eSmrg 974a49301eSmrgvoid 984a49301eSmrgtgsi_parse_token( 994a49301eSmrg struct tgsi_parse_context *ctx ) 1004a49301eSmrg{ 1014a49301eSmrg struct tgsi_token token; 1024a49301eSmrg unsigned i; 1034a49301eSmrg 1044a49301eSmrg next_token( ctx, &token ); 1054a49301eSmrg 1064a49301eSmrg switch( token.Type ) { 1074a49301eSmrg case TGSI_TOKEN_TYPE_DECLARATION: 1084a49301eSmrg { 1094a49301eSmrg struct tgsi_full_declaration *decl = &ctx->FullToken.FullDeclaration; 1104a49301eSmrg 111cdc920a0Smrg memset(decl, 0, sizeof *decl); 1124a49301eSmrg copy_token(&decl->Declaration, &token); 1134a49301eSmrg 114cdc920a0Smrg next_token( ctx, &decl->Range ); 115cdc920a0Smrg 116cdc920a0Smrg if (decl->Declaration.Dimension) { 117cdc920a0Smrg next_token(ctx, &decl->Dim); 118cdc920a0Smrg } 1194a49301eSmrg 12001e04c3fSmrg if (decl->Declaration.Interpolate) { 121af69d88dSmrg next_token( ctx, &decl->Interp ); 1224a49301eSmrg } 1234a49301eSmrg 12401e04c3fSmrg if (decl->Declaration.Semantic) { 125af69d88dSmrg next_token( ctx, &decl->Semantic ); 1263464ebd5Sriastradh } 1273464ebd5Sriastradh 12801e04c3fSmrg if (decl->Declaration.File == TGSI_FILE_IMAGE) { 12901e04c3fSmrg next_token(ctx, &decl->Image); 1303464ebd5Sriastradh } 1313464ebd5Sriastradh 132af69d88dSmrg if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) { 133af69d88dSmrg next_token(ctx, &decl->SamplerView); 134af69d88dSmrg } 135af69d88dSmrg 13601e04c3fSmrg if (decl->Declaration.Array) { 137af69d88dSmrg next_token(ctx, &decl->Array); 138af69d88dSmrg } 139af69d88dSmrg 1404a49301eSmrg break; 1414a49301eSmrg } 1424a49301eSmrg 1434a49301eSmrg case TGSI_TOKEN_TYPE_IMMEDIATE: 1444a49301eSmrg { 1454a49301eSmrg struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate; 146cdc920a0Smrg uint imm_count; 1474a49301eSmrg 148cdc920a0Smrg memset(imm, 0, sizeof *imm); 1494a49301eSmrg copy_token(&imm->Immediate, &token); 150cdc920a0Smrg 151cdc920a0Smrg imm_count = imm->Immediate.NrTokens - 1; 1524a49301eSmrg 1534a49301eSmrg switch (imm->Immediate.DataType) { 1544a49301eSmrg case TGSI_IMM_FLOAT32: 15501e04c3fSmrg case TGSI_IMM_FLOAT64: 156cdc920a0Smrg for (i = 0; i < imm_count; i++) { 157cdc920a0Smrg next_token(ctx, &imm->u[i].Float); 158cdc920a0Smrg } 159cdc920a0Smrg break; 160cdc920a0Smrg 161cdc920a0Smrg case TGSI_IMM_UINT32: 16201e04c3fSmrg case TGSI_IMM_UINT64: 163cdc920a0Smrg for (i = 0; i < imm_count; i++) { 164cdc920a0Smrg next_token(ctx, &imm->u[i].Uint); 165cdc920a0Smrg } 166cdc920a0Smrg break; 167cdc920a0Smrg 168cdc920a0Smrg case TGSI_IMM_INT32: 16901e04c3fSmrg case TGSI_IMM_INT64: 170cdc920a0Smrg for (i = 0; i < imm_count; i++) { 171cdc920a0Smrg next_token(ctx, &imm->u[i].Int); 1724a49301eSmrg } 1734a49301eSmrg break; 1744a49301eSmrg 1754a49301eSmrg default: 1764a49301eSmrg assert( 0 ); 1774a49301eSmrg } 1784a49301eSmrg 1794a49301eSmrg break; 1804a49301eSmrg } 1814a49301eSmrg 1824a49301eSmrg case TGSI_TOKEN_TYPE_INSTRUCTION: 1834a49301eSmrg { 1844a49301eSmrg struct tgsi_full_instruction *inst = &ctx->FullToken.FullInstruction; 1854a49301eSmrg 186cdc920a0Smrg memset(inst, 0, sizeof *inst); 1874a49301eSmrg copy_token(&inst->Instruction, &token); 1884a49301eSmrg 189cdc920a0Smrg if (inst->Instruction.Label) { 190cdc920a0Smrg next_token( ctx, &inst->Label); 191cdc920a0Smrg } 1924a49301eSmrg 193cdc920a0Smrg if (inst->Instruction.Texture) { 194cdc920a0Smrg next_token( ctx, &inst->Texture); 19501e04c3fSmrg for (i = 0; i < inst->Texture.NumOffsets; i++) { 196af69d88dSmrg next_token( ctx, &inst->TexOffsets[i] ); 197af69d88dSmrg } 1984a49301eSmrg } 1994a49301eSmrg 20001e04c3fSmrg if (inst->Instruction.Memory) { 20101e04c3fSmrg next_token(ctx, &inst->Memory); 20201e04c3fSmrg } 20301e04c3fSmrg 2044a49301eSmrg assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS ); 2054a49301eSmrg 20601e04c3fSmrg for (i = 0; i < inst->Instruction.NumDstRegs; i++) { 2074a49301eSmrg 208cdc920a0Smrg next_token( ctx, &inst->Dst[i].Register ); 2094a49301eSmrg 21001e04c3fSmrg if (inst->Dst[i].Register.Indirect) 211cdc920a0Smrg next_token( ctx, &inst->Dst[i].Indirect ); 2124a49301eSmrg 21301e04c3fSmrg if (inst->Dst[i].Register.Dimension) { 2143464ebd5Sriastradh next_token( ctx, &inst->Dst[i].Dimension ); 2153464ebd5Sriastradh 2163464ebd5Sriastradh /* 2173464ebd5Sriastradh * No support for multi-dimensional addressing. 2183464ebd5Sriastradh */ 2193464ebd5Sriastradh assert( !inst->Dst[i].Dimension.Dimension ); 2203464ebd5Sriastradh 22101e04c3fSmrg if (inst->Dst[i].Dimension.Indirect) 2223464ebd5Sriastradh next_token( ctx, &inst->Dst[i].DimIndirect ); 2233464ebd5Sriastradh } 2244a49301eSmrg } 2254a49301eSmrg 2264a49301eSmrg assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS ); 2274a49301eSmrg 22801e04c3fSmrg for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { 2294a49301eSmrg 230cdc920a0Smrg next_token( ctx, &inst->Src[i].Register ); 2314a49301eSmrg 23201e04c3fSmrg if (inst->Src[i].Register.Indirect) 233cdc920a0Smrg next_token( ctx, &inst->Src[i].Indirect ); 2344a49301eSmrg 23501e04c3fSmrg if (inst->Src[i].Register.Dimension) { 236cdc920a0Smrg next_token( ctx, &inst->Src[i].Dimension ); 2374a49301eSmrg 2384a49301eSmrg /* 2394a49301eSmrg * No support for multi-dimensional addressing. 2404a49301eSmrg */ 241cdc920a0Smrg assert( !inst->Src[i].Dimension.Dimension ); 2424a49301eSmrg 24301e04c3fSmrg if (inst->Src[i].Dimension.Indirect) 244cdc920a0Smrg next_token( ctx, &inst->Src[i].DimIndirect ); 2454a49301eSmrg } 2464a49301eSmrg } 2474a49301eSmrg 2484a49301eSmrg break; 2494a49301eSmrg } 2504a49301eSmrg 251cdc920a0Smrg case TGSI_TOKEN_TYPE_PROPERTY: 252cdc920a0Smrg { 253cdc920a0Smrg struct tgsi_full_property *prop = &ctx->FullToken.FullProperty; 254cdc920a0Smrg uint prop_count; 255cdc920a0Smrg 256cdc920a0Smrg memset(prop, 0, sizeof *prop); 257cdc920a0Smrg copy_token(&prop->Property, &token); 258cdc920a0Smrg 259cdc920a0Smrg prop_count = prop->Property.NrTokens - 1; 260cdc920a0Smrg for (i = 0; i < prop_count; i++) { 261cdc920a0Smrg next_token(ctx, &prop->u[i]); 262cdc920a0Smrg } 263cdc920a0Smrg 264cdc920a0Smrg break; 265cdc920a0Smrg } 266cdc920a0Smrg 2674a49301eSmrg default: 2684a49301eSmrg assert( 0 ); 2694a49301eSmrg } 2704a49301eSmrg} 2714a49301eSmrg 2724a49301eSmrg 2734a49301eSmrg 2744a49301eSmrg 2754a49301eSmrg/** 2764a49301eSmrg * Make a new copy of a token array. 2774a49301eSmrg */ 2784a49301eSmrgstruct tgsi_token * 2794a49301eSmrgtgsi_dup_tokens(const struct tgsi_token *tokens) 2804a49301eSmrg{ 2814a49301eSmrg unsigned n = tgsi_num_tokens(tokens); 2824a49301eSmrg unsigned bytes = n * sizeof(struct tgsi_token); 2834a49301eSmrg struct tgsi_token *new_tokens = (struct tgsi_token *) MALLOC(bytes); 2844a49301eSmrg if (new_tokens) 2854a49301eSmrg memcpy(new_tokens, tokens, bytes); 2864a49301eSmrg return new_tokens; 2874a49301eSmrg} 288cdc920a0Smrg 289cdc920a0Smrg 290cdc920a0Smrg/** 291cdc920a0Smrg * Allocate memory for num_tokens tokens. 292cdc920a0Smrg */ 293cdc920a0Smrgstruct tgsi_token * 294cdc920a0Smrgtgsi_alloc_tokens(unsigned num_tokens) 295cdc920a0Smrg{ 296cdc920a0Smrg unsigned bytes = num_tokens * sizeof(struct tgsi_token); 297cdc920a0Smrg return (struct tgsi_token *) MALLOC(bytes); 298cdc920a0Smrg} 2993464ebd5Sriastradh 3003464ebd5Sriastradh 30101e04c3fSmrg/** 30201e04c3fSmrg * Free tokens allocated by tgsi_alloc_tokens() or tgsi_dup_tokens() 30301e04c3fSmrg */ 30401e04c3fSmrgvoid 30501e04c3fSmrgtgsi_free_tokens(const struct tgsi_token *tokens) 30601e04c3fSmrg{ 30701e04c3fSmrg FREE((void *) tokens); 30801e04c3fSmrg} 30901e04c3fSmrg 31001e04c3fSmrg 3113464ebd5Sriastradhvoid 3123464ebd5Sriastradhtgsi_dump_tokens(const struct tgsi_token *tokens) 3133464ebd5Sriastradh{ 3143464ebd5Sriastradh const unsigned *dwords = (const unsigned *)tokens; 3153464ebd5Sriastradh int nr = tgsi_num_tokens(tokens); 3163464ebd5Sriastradh int i; 3173464ebd5Sriastradh 31801e04c3fSmrg STATIC_ASSERT(sizeof(*tokens) == sizeof(unsigned)); 3193464ebd5Sriastradh 3203464ebd5Sriastradh debug_printf("const unsigned tokens[%d] = {\n", nr); 3213464ebd5Sriastradh for (i = 0; i < nr; i++) 3223464ebd5Sriastradh debug_printf("0x%08x,\n", dwords[i]); 3233464ebd5Sriastradh debug_printf("};\n"); 3243464ebd5Sriastradh} 32501e04c3fSmrg 32601e04c3fSmrgunsigned 32701e04c3fSmrgtgsi_get_processor_type(const struct tgsi_token *tokens) 32801e04c3fSmrg{ 32901e04c3fSmrg struct tgsi_parse_context parse; 33001e04c3fSmrg 33101e04c3fSmrg if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) { 33201e04c3fSmrg debug_printf("tgsi_parse_init() failed in %s:%i!\n", __func__, __LINE__); 33301e04c3fSmrg return ~0; 33401e04c3fSmrg } 33501e04c3fSmrg return parse.FullHeader.Processor.Processor; 33601e04c3fSmrg} 337