tgsi: Add support for indirect addressing in dump, sanity and text modules.
[mesa.git] / src / gallium / auxiliary / tgsi / util / tgsi_dump.c
1 /**************************************************************************
2 *
3 * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "pipe/p_debug.h"
29 #include "tgsi_dump.h"
30 #include "tgsi_iterate.h"
31
32 struct dump_ctx
33 {
34 struct tgsi_iterate_context iter;
35
36 uint instno;
37 };
38
39 static void
40 dump_enum(
41 uint e,
42 const char **enums,
43 uint enum_count )
44 {
45 if (e >= enum_count)
46 debug_printf( "%u", e );
47 else
48 debug_printf( "%s", enums[e] );
49 }
50
51 #define EOL() debug_printf( "\n" )
52 #define TXT(S) debug_printf( "%s", S )
53 #define CHR(C) debug_printf( "%c", C )
54 #define UIX(I) debug_printf( "0x%x", I )
55 #define UID(I) debug_printf( "%u", I )
56 #define SID(I) debug_printf( "%d", I )
57 #define FLT(F) debug_printf( "%10.4f", F )
58 #define ENM(E,ENUMS) dump_enum( E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
59
60 static const char *processor_type_names[] =
61 {
62 "FRAG",
63 "VERT",
64 "GEOM"
65 };
66
67 static const char *file_names[] =
68 {
69 "NULL",
70 "CONST",
71 "IN",
72 "OUT",
73 "TEMP",
74 "SAMP",
75 "ADDR",
76 "IMM"
77 };
78
79 static const char *interpolate_names[] =
80 {
81 "CONSTANT",
82 "LINEAR",
83 "PERSPECTIVE"
84 };
85
86 static const char *semantic_names[] =
87 {
88 "POSITION",
89 "COLOR",
90 "BCOLOR",
91 "FOG",
92 "PSIZE",
93 "GENERIC",
94 "NORMAL"
95 };
96
97 static const char *immediate_type_names[] =
98 {
99 "FLT32"
100 };
101
102 static const char *opcode_names[TGSI_OPCODE_LAST] =
103 {
104 "ARL",
105 "MOV",
106 "LIT",
107 "RCP",
108 "RSQ",
109 "EXP",
110 "LOG",
111 "MUL",
112 "ADD",
113 "DP3",
114 "DP4",
115 "DST",
116 "MIN",
117 "MAX",
118 "SLT",
119 "SGE",
120 "MAD",
121 "SUB",
122 "LERP",
123 "CND",
124 "CND0",
125 "DOT2ADD",
126 "INDEX",
127 "NEGATE",
128 "FRAC",
129 "CLAMP",
130 "FLOOR",
131 "ROUND",
132 "EXPBASE2",
133 "LOGBASE2",
134 "POWER",
135 "CROSSPRODUCT",
136 "MULTIPLYMATRIX",
137 "ABS",
138 "RCC",
139 "DPH",
140 "COS",
141 "DDX",
142 "DDY",
143 "KILP",
144 "PK2H",
145 "PK2US",
146 "PK4B",
147 "PK4UB",
148 "RFL",
149 "SEQ",
150 "SFL",
151 "SGT",
152 "SIN",
153 "SLE",
154 "SNE",
155 "STR",
156 "TEX",
157 "TXD",
158 "TXP",
159 "UP2H",
160 "UP2US",
161 "UP4B",
162 "UP4UB",
163 "X2D",
164 "ARA",
165 "ARR",
166 "BRA",
167 "CAL",
168 "RET",
169 "SSG",
170 "CMP",
171 "SCS",
172 "TXB",
173 "NRM",
174 "DIV",
175 "DP2",
176 "TXL",
177 "BRK",
178 "IF",
179 "LOOP",
180 "REP",
181 "ELSE",
182 "ENDIF",
183 "ENDLOOP",
184 "ENDREP",
185 "PUSHA",
186 "POPA",
187 "CEIL",
188 "I2F",
189 "NOT",
190 "TRUNC",
191 "SHL",
192 "SHR",
193 "AND",
194 "OR",
195 "MOD",
196 "XOR",
197 "SAD",
198 "TXF",
199 "TXQ",
200 "CONT",
201 "EMIT",
202 "ENDPRIM",
203 "BGNLOOP2",
204 "BGNSUB",
205 "ENDLOOP2",
206 "ENDSUB",
207 "NOISE1",
208 "NOISE2",
209 "NOISE3",
210 "NOISE4",
211 "NOP",
212 "M4X3",
213 "M3X4",
214 "M3X3",
215 "M3X2",
216 "NRM4",
217 "CALLNZ",
218 "IFC",
219 "BREAKC",
220 "KIL",
221 "END",
222 "SWZ"
223 };
224
225 static const char *swizzle_names[] =
226 {
227 "x",
228 "y",
229 "z",
230 "w"
231 };
232
233 static const char *texture_names[] =
234 {
235 "UNKNOWN",
236 "1D",
237 "2D",
238 "3D",
239 "CUBE",
240 "RECT",
241 "SHADOW1D",
242 "SHADOW2D",
243 "SHADOWRECT"
244 };
245
246 static const char *extswizzle_names[] =
247 {
248 "x",
249 "y",
250 "z",
251 "w",
252 "0",
253 "1"
254 };
255
256 static const char *modulate_names[TGSI_MODULATE_COUNT] =
257 {
258 "",
259 "_2X",
260 "_4X",
261 "_8X",
262 "_D2",
263 "_D4",
264 "_D8"
265 };
266
267 static void
268 _dump_register_prefix(
269 uint file,
270 uint first,
271 uint last )
272 {
273
274
275 }
276
277 static void
278 _dump_register(
279 uint file,
280 int first,
281 int last )
282 {
283 ENM( file, file_names );
284 CHR( '[' );
285 SID( first );
286 if (first != last) {
287 TXT( ".." );
288 SID( last );
289 }
290 CHR( ']' );
291 }
292
293 static void
294 _dump_register_ind(
295 uint file,
296 int index,
297 uint ind_file,
298 int ind_index )
299 {
300 ENM( file, file_names );
301 CHR( '[' );
302 ENM( ind_file, file_names );
303 CHR( '[' );
304 SID( ind_index );
305 CHR( ']' );
306 if (index != 0) {
307 if (index > 0)
308 CHR( '+' );
309 SID( index );
310 }
311 CHR( ']' );
312 }
313
314 static void
315 _dump_writemask(
316 uint writemask )
317 {
318 if (writemask != TGSI_WRITEMASK_XYZW) {
319 CHR( '.' );
320 if (writemask & TGSI_WRITEMASK_X)
321 CHR( 'x' );
322 if (writemask & TGSI_WRITEMASK_Y)
323 CHR( 'y' );
324 if (writemask & TGSI_WRITEMASK_Z)
325 CHR( 'z' );
326 if (writemask & TGSI_WRITEMASK_W)
327 CHR( 'w' );
328 }
329 }
330
331 void
332 tgsi_dump_declaration(
333 const struct tgsi_full_declaration *decl )
334 {
335 TXT( "\nDCL " );
336
337 _dump_register(
338 decl->Declaration.File,
339 decl->DeclarationRange.First,
340 decl->DeclarationRange.Last );
341 _dump_writemask(
342 decl->Declaration.UsageMask );
343
344 if (decl->Declaration.Semantic) {
345 TXT( ", " );
346 ENM( decl->Semantic.SemanticName, semantic_names );
347 if (decl->Semantic.SemanticIndex != 0 ||
348 decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC) {
349 CHR( '[' );
350 UID( decl->Semantic.SemanticIndex );
351 CHR( ']' );
352 }
353 }
354
355 TXT( ", " );
356 ENM( decl->Declaration.Interpolate, interpolate_names );
357 }
358
359 static boolean
360 iter_declaration(
361 struct tgsi_iterate_context *iter,
362 struct tgsi_full_declaration *decl )
363 {
364 tgsi_dump_declaration( decl );
365 return TRUE;
366 }
367
368 void
369 tgsi_dump_immediate(
370 const struct tgsi_full_immediate *imm )
371 {
372 uint i;
373
374 TXT( "\nIMM " );
375 ENM( imm->Immediate.DataType, immediate_type_names );
376
377 TXT( " { " );
378 for (i = 0; i < imm->Immediate.Size - 1; i++) {
379 switch (imm->Immediate.DataType) {
380 case TGSI_IMM_FLOAT32:
381 FLT( imm->u.ImmediateFloat32[i].Float );
382 break;
383 default:
384 assert( 0 );
385 }
386
387 if (i < imm->Immediate.Size - 2)
388 TXT( ", " );
389 }
390 TXT( " }" );
391 }
392
393 static boolean
394 iter_immediate(
395 struct tgsi_iterate_context *iter,
396 struct tgsi_full_immediate *imm )
397 {
398 tgsi_dump_immediate( imm );
399 return TRUE;
400 }
401
402 void
403 tgsi_dump_instruction(
404 const struct tgsi_full_instruction *inst,
405 uint instno )
406 {
407 uint i;
408 boolean first_reg = TRUE;
409
410 EOL();
411 UID( instno );
412 CHR( ':' );
413 ENM( inst->Instruction.Opcode, opcode_names );
414
415 switch (inst->Instruction.Saturate) {
416 case TGSI_SAT_NONE:
417 break;
418 case TGSI_SAT_ZERO_ONE:
419 TXT( "_SAT" );
420 break;
421 case TGSI_SAT_MINUS_PLUS_ONE:
422 TXT( "_SATNV" );
423 break;
424 default:
425 assert( 0 );
426 }
427
428 for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
429 const struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
430
431 if (!first_reg)
432 CHR( ',' );
433 CHR( ' ' );
434
435 _dump_register(
436 dst->DstRegister.File,
437 dst->DstRegister.Index,
438 dst->DstRegister.Index );
439 ENM( dst->DstRegisterExtModulate.Modulate, modulate_names );
440 _dump_writemask( dst->DstRegister.WriteMask );
441
442 first_reg = FALSE;
443 }
444
445 for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
446 const struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i];
447
448 if (!first_reg)
449 CHR( ',' );
450 CHR( ' ' );
451
452 if (src->SrcRegisterExtMod.Negate)
453 TXT( "-(" );
454 if (src->SrcRegisterExtMod.Absolute)
455 CHR( '|' );
456 if (src->SrcRegisterExtMod.Scale2X)
457 TXT( "2*(" );
458 if (src->SrcRegisterExtMod.Bias)
459 CHR( '(' );
460 if (src->SrcRegisterExtMod.Complement)
461 TXT( "1-(" );
462 if (src->SrcRegister.Negate)
463 CHR( '-' );
464
465 if (src->SrcRegister.Indirect) {
466 _dump_register_ind(
467 src->SrcRegister.File,
468 src->SrcRegister.Index,
469 src->SrcRegisterInd.File,
470 src->SrcRegisterInd.Index );
471 }
472 else {
473 _dump_register(
474 src->SrcRegister.File,
475 src->SrcRegister.Index,
476 src->SrcRegister.Index );
477 }
478
479 if (src->SrcRegister.SwizzleX != TGSI_SWIZZLE_X ||
480 src->SrcRegister.SwizzleY != TGSI_SWIZZLE_Y ||
481 src->SrcRegister.SwizzleZ != TGSI_SWIZZLE_Z ||
482 src->SrcRegister.SwizzleW != TGSI_SWIZZLE_W) {
483 CHR( '.' );
484 ENM( src->SrcRegister.SwizzleX, swizzle_names );
485 ENM( src->SrcRegister.SwizzleY, swizzle_names );
486 ENM( src->SrcRegister.SwizzleZ, swizzle_names );
487 ENM( src->SrcRegister.SwizzleW, swizzle_names );
488 }
489 if (src->SrcRegisterExtSwz.ExtSwizzleX != TGSI_EXTSWIZZLE_X ||
490 src->SrcRegisterExtSwz.ExtSwizzleY != TGSI_EXTSWIZZLE_Y ||
491 src->SrcRegisterExtSwz.ExtSwizzleZ != TGSI_EXTSWIZZLE_Z ||
492 src->SrcRegisterExtSwz.ExtSwizzleW != TGSI_EXTSWIZZLE_W) {
493 CHR( '.' );
494 ENM( src->SrcRegisterExtSwz.ExtSwizzleX, extswizzle_names );
495 ENM( src->SrcRegisterExtSwz.ExtSwizzleY, extswizzle_names );
496 ENM( src->SrcRegisterExtSwz.ExtSwizzleZ, extswizzle_names );
497 ENM( src->SrcRegisterExtSwz.ExtSwizzleW, extswizzle_names );
498 }
499
500 if (src->SrcRegisterExtMod.Complement)
501 CHR( ')' );
502 if (src->SrcRegisterExtMod.Bias)
503 TXT( ")-.5" );
504 if (src->SrcRegisterExtMod.Scale2X)
505 CHR( ')' );
506 if (src->SrcRegisterExtMod.Absolute)
507 CHR( '|' );
508 if (src->SrcRegisterExtMod.Negate)
509 CHR( ')' );
510
511 first_reg = FALSE;
512 }
513
514 if (inst->InstructionExtTexture.Texture != TGSI_TEXTURE_UNKNOWN) {
515 TXT( ", " );
516 ENM( inst->InstructionExtTexture.Texture, texture_names );
517 }
518
519 switch (inst->Instruction.Opcode) {
520 case TGSI_OPCODE_IF:
521 case TGSI_OPCODE_ELSE:
522 case TGSI_OPCODE_BGNLOOP2:
523 case TGSI_OPCODE_ENDLOOP2:
524 case TGSI_OPCODE_CAL:
525 TXT( " :" );
526 UID( inst->InstructionExtLabel.Label );
527 break;
528 }
529 }
530
531 static boolean
532 iter_instruction(
533 struct tgsi_iterate_context *iter,
534 struct tgsi_full_instruction *inst )
535 {
536 struct dump_ctx *ctx = (struct dump_ctx *) iter;
537
538 tgsi_dump_instruction( inst, ctx->instno++ );
539 return TRUE;
540 }
541
542 static boolean
543 prolog(
544 struct tgsi_iterate_context *ctx )
545 {
546 EOL();
547 ENM( ctx->processor.Processor, processor_type_names );
548 UID( ctx->version.MajorVersion );
549 CHR( '.' );
550 UID( ctx->version.MinorVersion );
551 return TRUE;
552 }
553
554 void
555 tgsi_dump(
556 const struct tgsi_token *tokens,
557 uint flags )
558 {
559 struct dump_ctx ctx;
560
561 /* sanity checks */
562 assert( strcmp( opcode_names[TGSI_OPCODE_CONT], "CONT" ) == 0 );
563 assert( strcmp( opcode_names[TGSI_OPCODE_END], "END" ) == 0 );
564
565 ctx.iter.prolog = prolog;
566 ctx.iter.iterate_instruction = iter_instruction;
567 ctx.iter.iterate_declaration = iter_declaration;
568 ctx.iter.iterate_immediate = iter_immediate;
569 ctx.iter.epilog = NULL;
570
571 ctx.instno = 0;
572
573 tgsi_iterate_shader( tokens, &ctx.iter );
574 }