1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright 2007 VMware, Inc. 4848b8605Smrg * All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the 8848b8605Smrg * "Software"), to deal in the Software without restriction, including 9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 12848b8605Smrg * the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice (including the 15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 16848b8605Smrg * of the Software. 17848b8605Smrg * 18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25848b8605Smrg * 26848b8605Smrg **************************************************************************/ 27848b8605Smrg 28848b8605Smrg#include "util/u_debug.h" 29848b8605Smrg#include "pipe/p_shader_tokens.h" 30848b8605Smrg#include "tgsi_parse.h" 31848b8605Smrg#include "util/u_memory.h" 32848b8605Smrg 33848b8605Smrgunsigned 34848b8605Smrgtgsi_parse_init( 35848b8605Smrg struct tgsi_parse_context *ctx, 36848b8605Smrg const struct tgsi_token *tokens ) 37848b8605Smrg{ 38848b8605Smrg ctx->FullHeader.Header = *(struct tgsi_header *) &tokens[0]; 39b8e80941Smrg if (ctx->FullHeader.Header.HeaderSize >= 2) { 40848b8605Smrg ctx->FullHeader.Processor = *(struct tgsi_processor *) &tokens[1]; 41848b8605Smrg } 42848b8605Smrg else { 43848b8605Smrg return TGSI_PARSE_ERROR; 44848b8605Smrg } 45848b8605Smrg 46848b8605Smrg ctx->Tokens = tokens; 47848b8605Smrg ctx->Position = ctx->FullHeader.Header.HeaderSize; 48848b8605Smrg 49848b8605Smrg return TGSI_PARSE_OK; 50848b8605Smrg} 51848b8605Smrg 52848b8605Smrgvoid 53848b8605Smrgtgsi_parse_free( 54b8e80941Smrg UNUSED struct tgsi_parse_context *ctx ) 55848b8605Smrg{ 56848b8605Smrg} 57848b8605Smrg 58848b8605Smrgboolean 59848b8605Smrgtgsi_parse_end_of_tokens( 60848b8605Smrg struct tgsi_parse_context *ctx ) 61848b8605Smrg{ 62b8e80941Smrg /* All values involved are unsigned, but the sum will be promoted to 63b8e80941Smrg * a signed value (at least on 64 bit). To capture a possible overflow 64b8e80941Smrg * make it a signed comparison. 65b8e80941Smrg */ 66b8e80941Smrg return (int)ctx->Position >= 67b8e80941Smrg ctx->FullHeader.Header.HeaderSize + ctx->FullHeader.Header.BodySize; 68848b8605Smrg} 69848b8605Smrg 70848b8605Smrg 71848b8605Smrg/** 72848b8605Smrg * This function is used to avoid and work-around type punning/aliasing 73848b8605Smrg * warnings. The warnings seem harmless on x86 but on PPC they cause 74848b8605Smrg * real failures. 75848b8605Smrg */ 76b8e80941Smrgstatic inline void 77848b8605Smrgcopy_token(void *dst, const void *src) 78848b8605Smrg{ 79848b8605Smrg memcpy(dst, src, 4); 80848b8605Smrg} 81848b8605Smrg 82848b8605Smrg 83848b8605Smrg/** 84848b8605Smrg * Get next 4-byte token, return it at address specified by 'token' 85848b8605Smrg */ 86848b8605Smrgstatic void 87848b8605Smrgnext_token( 88848b8605Smrg struct tgsi_parse_context *ctx, 89848b8605Smrg void *token ) 90848b8605Smrg{ 91848b8605Smrg assert( !tgsi_parse_end_of_tokens( ctx ) ); 92848b8605Smrg copy_token(token, &ctx->Tokens[ctx->Position]); 93848b8605Smrg ctx->Position++; 94848b8605Smrg} 95848b8605Smrg 96848b8605Smrg 97848b8605Smrgvoid 98848b8605Smrgtgsi_parse_token( 99848b8605Smrg struct tgsi_parse_context *ctx ) 100848b8605Smrg{ 101848b8605Smrg struct tgsi_token token; 102848b8605Smrg unsigned i; 103848b8605Smrg 104848b8605Smrg next_token( ctx, &token ); 105848b8605Smrg 106848b8605Smrg switch( token.Type ) { 107848b8605Smrg case TGSI_TOKEN_TYPE_DECLARATION: 108848b8605Smrg { 109848b8605Smrg struct tgsi_full_declaration *decl = &ctx->FullToken.FullDeclaration; 110848b8605Smrg 111848b8605Smrg memset(decl, 0, sizeof *decl); 112848b8605Smrg copy_token(&decl->Declaration, &token); 113848b8605Smrg 114848b8605Smrg next_token( ctx, &decl->Range ); 115848b8605Smrg 116848b8605Smrg if (decl->Declaration.Dimension) { 117848b8605Smrg next_token(ctx, &decl->Dim); 118848b8605Smrg } 119848b8605Smrg 120b8e80941Smrg if (decl->Declaration.Interpolate) { 121848b8605Smrg next_token( ctx, &decl->Interp ); 122848b8605Smrg } 123848b8605Smrg 124b8e80941Smrg if (decl->Declaration.Semantic) { 125848b8605Smrg next_token( ctx, &decl->Semantic ); 126848b8605Smrg } 127848b8605Smrg 128b8e80941Smrg if (decl->Declaration.File == TGSI_FILE_IMAGE) { 129b8e80941Smrg next_token(ctx, &decl->Image); 130848b8605Smrg } 131848b8605Smrg 132848b8605Smrg if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) { 133848b8605Smrg next_token(ctx, &decl->SamplerView); 134848b8605Smrg } 135848b8605Smrg 136b8e80941Smrg if (decl->Declaration.Array) { 137848b8605Smrg next_token(ctx, &decl->Array); 138848b8605Smrg } 139848b8605Smrg 140848b8605Smrg break; 141848b8605Smrg } 142848b8605Smrg 143848b8605Smrg case TGSI_TOKEN_TYPE_IMMEDIATE: 144848b8605Smrg { 145848b8605Smrg struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate; 146848b8605Smrg uint imm_count; 147848b8605Smrg 148848b8605Smrg memset(imm, 0, sizeof *imm); 149848b8605Smrg copy_token(&imm->Immediate, &token); 150848b8605Smrg 151848b8605Smrg imm_count = imm->Immediate.NrTokens - 1; 152848b8605Smrg 153848b8605Smrg switch (imm->Immediate.DataType) { 154848b8605Smrg case TGSI_IMM_FLOAT32: 155b8e80941Smrg case TGSI_IMM_FLOAT64: 156848b8605Smrg for (i = 0; i < imm_count; i++) { 157848b8605Smrg next_token(ctx, &imm->u[i].Float); 158848b8605Smrg } 159848b8605Smrg break; 160848b8605Smrg 161848b8605Smrg case TGSI_IMM_UINT32: 162b8e80941Smrg case TGSI_IMM_UINT64: 163848b8605Smrg for (i = 0; i < imm_count; i++) { 164848b8605Smrg next_token(ctx, &imm->u[i].Uint); 165848b8605Smrg } 166848b8605Smrg break; 167848b8605Smrg 168848b8605Smrg case TGSI_IMM_INT32: 169b8e80941Smrg case TGSI_IMM_INT64: 170848b8605Smrg for (i = 0; i < imm_count; i++) { 171848b8605Smrg next_token(ctx, &imm->u[i].Int); 172848b8605Smrg } 173848b8605Smrg break; 174848b8605Smrg 175848b8605Smrg default: 176848b8605Smrg assert( 0 ); 177848b8605Smrg } 178848b8605Smrg 179848b8605Smrg break; 180848b8605Smrg } 181848b8605Smrg 182848b8605Smrg case TGSI_TOKEN_TYPE_INSTRUCTION: 183848b8605Smrg { 184848b8605Smrg struct tgsi_full_instruction *inst = &ctx->FullToken.FullInstruction; 185848b8605Smrg 186848b8605Smrg memset(inst, 0, sizeof *inst); 187848b8605Smrg copy_token(&inst->Instruction, &token); 188848b8605Smrg 189848b8605Smrg if (inst->Instruction.Label) { 190848b8605Smrg next_token( ctx, &inst->Label); 191848b8605Smrg } 192848b8605Smrg 193848b8605Smrg if (inst->Instruction.Texture) { 194848b8605Smrg next_token( ctx, &inst->Texture); 195b8e80941Smrg for (i = 0; i < inst->Texture.NumOffsets; i++) { 196848b8605Smrg next_token( ctx, &inst->TexOffsets[i] ); 197848b8605Smrg } 198848b8605Smrg } 199848b8605Smrg 200b8e80941Smrg if (inst->Instruction.Memory) { 201b8e80941Smrg next_token(ctx, &inst->Memory); 202b8e80941Smrg } 203b8e80941Smrg 204848b8605Smrg assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS ); 205848b8605Smrg 206b8e80941Smrg for (i = 0; i < inst->Instruction.NumDstRegs; i++) { 207848b8605Smrg 208848b8605Smrg next_token( ctx, &inst->Dst[i].Register ); 209848b8605Smrg 210b8e80941Smrg if (inst->Dst[i].Register.Indirect) 211848b8605Smrg next_token( ctx, &inst->Dst[i].Indirect ); 212848b8605Smrg 213b8e80941Smrg if (inst->Dst[i].Register.Dimension) { 214848b8605Smrg next_token( ctx, &inst->Dst[i].Dimension ); 215848b8605Smrg 216848b8605Smrg /* 217848b8605Smrg * No support for multi-dimensional addressing. 218848b8605Smrg */ 219848b8605Smrg assert( !inst->Dst[i].Dimension.Dimension ); 220848b8605Smrg 221b8e80941Smrg if (inst->Dst[i].Dimension.Indirect) 222848b8605Smrg next_token( ctx, &inst->Dst[i].DimIndirect ); 223848b8605Smrg } 224848b8605Smrg } 225848b8605Smrg 226848b8605Smrg assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS ); 227848b8605Smrg 228b8e80941Smrg for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { 229848b8605Smrg 230848b8605Smrg next_token( ctx, &inst->Src[i].Register ); 231848b8605Smrg 232b8e80941Smrg if (inst->Src[i].Register.Indirect) 233848b8605Smrg next_token( ctx, &inst->Src[i].Indirect ); 234848b8605Smrg 235b8e80941Smrg if (inst->Src[i].Register.Dimension) { 236848b8605Smrg next_token( ctx, &inst->Src[i].Dimension ); 237848b8605Smrg 238848b8605Smrg /* 239848b8605Smrg * No support for multi-dimensional addressing. 240848b8605Smrg */ 241848b8605Smrg assert( !inst->Src[i].Dimension.Dimension ); 242848b8605Smrg 243b8e80941Smrg if (inst->Src[i].Dimension.Indirect) 244848b8605Smrg next_token( ctx, &inst->Src[i].DimIndirect ); 245848b8605Smrg } 246848b8605Smrg } 247848b8605Smrg 248848b8605Smrg break; 249848b8605Smrg } 250848b8605Smrg 251848b8605Smrg case TGSI_TOKEN_TYPE_PROPERTY: 252848b8605Smrg { 253848b8605Smrg struct tgsi_full_property *prop = &ctx->FullToken.FullProperty; 254848b8605Smrg uint prop_count; 255848b8605Smrg 256848b8605Smrg memset(prop, 0, sizeof *prop); 257848b8605Smrg copy_token(&prop->Property, &token); 258848b8605Smrg 259848b8605Smrg prop_count = prop->Property.NrTokens - 1; 260848b8605Smrg for (i = 0; i < prop_count; i++) { 261848b8605Smrg next_token(ctx, &prop->u[i]); 262848b8605Smrg } 263848b8605Smrg 264848b8605Smrg break; 265848b8605Smrg } 266848b8605Smrg 267848b8605Smrg default: 268848b8605Smrg assert( 0 ); 269848b8605Smrg } 270848b8605Smrg} 271848b8605Smrg 272848b8605Smrg 273848b8605Smrg 274848b8605Smrg 275848b8605Smrg/** 276848b8605Smrg * Make a new copy of a token array. 277848b8605Smrg */ 278848b8605Smrgstruct tgsi_token * 279848b8605Smrgtgsi_dup_tokens(const struct tgsi_token *tokens) 280848b8605Smrg{ 281848b8605Smrg unsigned n = tgsi_num_tokens(tokens); 282848b8605Smrg unsigned bytes = n * sizeof(struct tgsi_token); 283848b8605Smrg struct tgsi_token *new_tokens = (struct tgsi_token *) MALLOC(bytes); 284848b8605Smrg if (new_tokens) 285848b8605Smrg memcpy(new_tokens, tokens, bytes); 286848b8605Smrg return new_tokens; 287848b8605Smrg} 288848b8605Smrg 289848b8605Smrg 290848b8605Smrg/** 291848b8605Smrg * Allocate memory for num_tokens tokens. 292848b8605Smrg */ 293848b8605Smrgstruct tgsi_token * 294848b8605Smrgtgsi_alloc_tokens(unsigned num_tokens) 295848b8605Smrg{ 296848b8605Smrg unsigned bytes = num_tokens * sizeof(struct tgsi_token); 297848b8605Smrg return (struct tgsi_token *) MALLOC(bytes); 298848b8605Smrg} 299848b8605Smrg 300848b8605Smrg 301b8e80941Smrg/** 302b8e80941Smrg * Free tokens allocated by tgsi_alloc_tokens() or tgsi_dup_tokens() 303b8e80941Smrg */ 304b8e80941Smrgvoid 305b8e80941Smrgtgsi_free_tokens(const struct tgsi_token *tokens) 306b8e80941Smrg{ 307b8e80941Smrg FREE((void *) tokens); 308b8e80941Smrg} 309b8e80941Smrg 310b8e80941Smrg 311848b8605Smrgvoid 312848b8605Smrgtgsi_dump_tokens(const struct tgsi_token *tokens) 313848b8605Smrg{ 314848b8605Smrg const unsigned *dwords = (const unsigned *)tokens; 315848b8605Smrg int nr = tgsi_num_tokens(tokens); 316848b8605Smrg int i; 317848b8605Smrg 318b8e80941Smrg STATIC_ASSERT(sizeof(*tokens) == sizeof(unsigned)); 319848b8605Smrg 320848b8605Smrg debug_printf("const unsigned tokens[%d] = {\n", nr); 321848b8605Smrg for (i = 0; i < nr; i++) 322848b8605Smrg debug_printf("0x%08x,\n", dwords[i]); 323848b8605Smrg debug_printf("};\n"); 324848b8605Smrg} 325b8e80941Smrg 326b8e80941Smrgunsigned 327b8e80941Smrgtgsi_get_processor_type(const struct tgsi_token *tokens) 328b8e80941Smrg{ 329b8e80941Smrg struct tgsi_parse_context parse; 330b8e80941Smrg 331b8e80941Smrg if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) { 332b8e80941Smrg debug_printf("tgsi_parse_init() failed in %s:%i!\n", __func__, __LINE__); 333b8e80941Smrg return ~0; 334b8e80941Smrg } 335b8e80941Smrg return parse.FullHeader.Processor.Processor; 336b8e80941Smrg} 337