1 /**********************************************************
2  * Copyright 2008-2009 VMware, Inc.  All rights reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  *
24  **********************************************************/
25 
26 /**
27  * @file
28  * SVGA Shader Dump Facilities
29  *
30  * @author Michal Krol <michal@vmware.com>
31  */
32 
33 #include "svga_shader.h"
34 #include "svga_shader_dump.h"
35 #include "svga_shader_op.h"
36 #include "util/u_debug.h"
37 
38 #include "../svga_hw_reg.h"
39 #include "svga3d_shaderdefs.h"
40 
41 struct dump_info
42 {
43    uint32 version;
44    boolean is_ps;
45    int indent;
46 };
47 
48 #define DUMP_MAX_OP_SRC 4
49 
50 struct dump_op
51 {
52    struct sh_op op;
53    struct sh_dstreg dst;
54    struct sh_srcreg dstind;
55    struct sh_srcreg src[DUMP_MAX_OP_SRC];
56    struct sh_srcreg srcind[DUMP_MAX_OP_SRC];
57    struct sh_srcreg p0;
58 };
59 
60 static void
dump_indent(int indent)61 dump_indent(int indent)
62 {
63    int i;
64 
65    for (i = 0; i < indent; ++i) {
66       _debug_printf("  ");
67    }
68 }
69 
dump_op(struct sh_op op,const char * mnemonic)70 static void dump_op( struct sh_op op, const char *mnemonic )
71 {
72    assert( op.is_reg == 0 );
73 
74    if (op.predicated) {
75       _debug_printf("(p0) ");
76    }
77    if (op.coissue)
78       _debug_printf( "+" );
79    _debug_printf( "%s", mnemonic );
80 
81    switch (op.opcode) {
82    case SVGA3DOP_TEX:
83       switch (op.control) {
84       case 0:
85          break;
86       case 1 /* PROJECT */:
87          _debug_printf("p");
88          break;
89       case 2 /* BIAS */:
90          _debug_printf("b");
91          break;
92       default:
93          assert(0);
94       }
95       break;
96 
97    case SVGA3DOP_IFC:
98    case SVGA3DOP_BREAKC:
99    case SVGA3DOP_SETP:
100       switch (op.control) {
101       case SVGA3DOPCOMP_GT:
102          _debug_printf("_gt");
103          break;
104       case SVGA3DOPCOMP_EQ:
105          _debug_printf("_eq");
106          break;
107       case SVGA3DOPCOMP_GE:
108          _debug_printf("_ge");
109          break;
110       case SVGA3DOPCOMP_LT:
111          _debug_printf("_lt");
112          break;
113       case SVGA3DOPCOMPC_NE:
114          _debug_printf("_ne");
115          break;
116       case SVGA3DOPCOMP_LE:
117          _debug_printf("_le");
118          break;
119       default:
120          assert(0);
121       }
122       break;
123 
124    default:
125       assert(op.control == 0);
126    }
127 }
128 
129 static void
format_reg(const char * name,const struct sh_reg reg,const struct sh_srcreg * indreg)130 format_reg(const char *name,
131            const struct sh_reg reg,
132            const struct sh_srcreg *indreg)
133 {
134    if (reg.relative) {
135       assert(indreg);
136 
137       if (sh_srcreg_type(*indreg) == SVGA3DREG_LOOP) {
138          _debug_printf("%s[aL+%u]", name, reg.number);
139       } else {
140          _debug_printf("%s[a%u.x+%u]", name, indreg->number, reg.number);
141       }
142    } else {
143       _debug_printf("%s%u", name, reg.number);
144    }
145 }
146 
dump_reg(struct sh_reg reg,struct sh_srcreg * indreg,const struct dump_info * di)147 static void dump_reg( struct sh_reg reg, struct sh_srcreg *indreg, const struct dump_info *di )
148 {
149    assert( reg.is_reg == 1 );
150 
151    switch (sh_reg_type( reg )) {
152    case SVGA3DREG_TEMP:
153       format_reg("r", reg, NULL);
154       break;
155 
156    case SVGA3DREG_INPUT:
157       format_reg("v", reg, indreg);
158       break;
159 
160    case SVGA3DREG_CONST:
161       format_reg("c", reg, indreg);
162       break;
163 
164    case SVGA3DREG_ADDR:    /* VS */
165    /* SVGA3DREG_TEXTURE */ /* PS */
166       assert(!reg.relative);
167       if (di->is_ps) {
168          format_reg("t", reg, NULL);
169       } else {
170          format_reg("a", reg, NULL);
171       }
172       break;
173 
174    case SVGA3DREG_RASTOUT:
175       assert(!reg.relative);
176       switch (reg.number) {
177       case 0 /*POSITION*/:
178          _debug_printf( "oPos" );
179          break;
180       case 1 /*FOG*/:
181          _debug_printf( "oFog" );
182          break;
183       case 2 /*POINT_SIZE*/:
184          _debug_printf( "oPts" );
185          break;
186       default:
187          assert( 0 );
188          _debug_printf( "???" );
189       }
190       break;
191 
192    case SVGA3DREG_ATTROUT:
193       assert( reg.number < 2 );
194       format_reg("oD", reg, NULL);
195       break;
196 
197    case SVGA3DREG_TEXCRDOUT:  /* VS */
198    /* SVGA3DREG_OUTPUT */     /* VS3.0+ */
199       if (!di->is_ps && di->version >= SVGA3D_VS_30) {
200          format_reg("o", reg, indreg);
201       } else {
202          format_reg("oT", reg, NULL);
203       }
204       break;
205 
206    case SVGA3DREG_COLOROUT:
207       format_reg("oC", reg, NULL);
208       break;
209 
210    case SVGA3DREG_DEPTHOUT:
211       assert(!reg.relative);
212       assert(reg.number == 0);
213       _debug_printf("oDepth");
214       break;
215 
216    case SVGA3DREG_SAMPLER:
217       format_reg("s", reg, NULL);
218       break;
219 
220    case SVGA3DREG_CONSTBOOL:
221       format_reg("b", reg, NULL);
222       break;
223 
224    case SVGA3DREG_CONSTINT:
225       format_reg("i", reg, NULL);
226       break;
227 
228    case SVGA3DREG_LOOP:
229       assert(!reg.relative);
230       assert( reg.number == 0 );
231       _debug_printf( "aL" );
232       break;
233 
234    case SVGA3DREG_MISCTYPE:
235       assert(!reg.relative);
236       switch (reg.number) {
237       case SVGA3DMISCREG_POSITION:
238          _debug_printf("vPos");
239          break;
240       case SVGA3DMISCREG_FACE:
241          _debug_printf("vFace");
242          break;
243       default:
244          assert(0);
245          _debug_printf("???");
246       }
247       break;
248 
249    case SVGA3DREG_LABEL:
250       format_reg("l", reg, NULL);
251       break;
252 
253    case SVGA3DREG_PREDICATE:
254       format_reg("p", reg, NULL);
255       break;
256 
257    default:
258       assert( 0 );
259       _debug_printf( "???" );
260    }
261 }
262 
dump_cdata(struct sh_cdata cdata)263 static void dump_cdata( struct sh_cdata cdata )
264 {
265    _debug_printf( "%f, %f, %f, %f", cdata.xyzw[0], cdata.xyzw[1], cdata.xyzw[2], cdata.xyzw[3] );
266 }
267 
dump_idata(struct sh_idata idata)268 static void dump_idata( struct sh_idata idata )
269 {
270    _debug_printf( "%d, %d, %d, %d", idata.xyzw[0], idata.xyzw[1], idata.xyzw[2], idata.xyzw[3] );
271 }
272 
dump_bdata(boolean bdata)273 static void dump_bdata( boolean bdata )
274 {
275    _debug_printf( bdata ? "TRUE" : "FALSE" );
276 }
277 
278 static void
dump_sampleinfo(struct sh_sampleinfo sampleinfo)279 dump_sampleinfo(struct sh_sampleinfo sampleinfo)
280 {
281    assert( sampleinfo.is_reg == 1 );
282 
283    switch (sampleinfo.texture_type) {
284    case SVGA3DSAMP_2D:
285       _debug_printf( "_2d" );
286       break;
287    case SVGA3DSAMP_CUBE:
288       _debug_printf( "_cube" );
289       break;
290    case SVGA3DSAMP_VOLUME:
291       _debug_printf( "_volume" );
292       break;
293    default:
294       assert( 0 );
295    }
296 }
297 
298 static void
dump_semantic(uint usage,uint usage_index)299 dump_semantic(uint usage,
300               uint usage_index)
301 {
302    switch (usage) {
303    case SVGA3D_DECLUSAGE_POSITION:
304       _debug_printf("_position");
305       break;
306    case SVGA3D_DECLUSAGE_BLENDWEIGHT:
307       _debug_printf("_blendweight");
308       break;
309    case SVGA3D_DECLUSAGE_BLENDINDICES:
310       _debug_printf("_blendindices");
311       break;
312    case SVGA3D_DECLUSAGE_NORMAL:
313       _debug_printf("_normal");
314       break;
315    case SVGA3D_DECLUSAGE_PSIZE:
316       _debug_printf("_psize");
317       break;
318    case SVGA3D_DECLUSAGE_TEXCOORD:
319       _debug_printf("_texcoord");
320       break;
321    case SVGA3D_DECLUSAGE_TANGENT:
322       _debug_printf("_tangent");
323       break;
324    case SVGA3D_DECLUSAGE_BINORMAL:
325       _debug_printf("_binormal");
326       break;
327    case SVGA3D_DECLUSAGE_TESSFACTOR:
328       _debug_printf("_tessfactor");
329       break;
330    case SVGA3D_DECLUSAGE_POSITIONT:
331       _debug_printf("_positiont");
332       break;
333    case SVGA3D_DECLUSAGE_COLOR:
334       _debug_printf("_color");
335       break;
336    case SVGA3D_DECLUSAGE_FOG:
337       _debug_printf("_fog");
338       break;
339    case SVGA3D_DECLUSAGE_DEPTH:
340       _debug_printf("_depth");
341       break;
342    case SVGA3D_DECLUSAGE_SAMPLE:
343       _debug_printf("_sample");
344       break;
345    default:
346       assert(!"Unknown usage");
347       _debug_printf("_???");
348    }
349 
350    if (usage_index) {
351       _debug_printf("%u", usage_index);
352    }
353 }
354 
355 static void
dump_dstreg(struct sh_dstreg dstreg,struct sh_srcreg * indreg,const struct dump_info * di)356 dump_dstreg(struct sh_dstreg dstreg,
357             struct sh_srcreg *indreg,
358             const struct dump_info *di)
359 {
360    union {
361       struct sh_reg reg;
362       struct sh_dstreg dstreg;
363    } u;
364 
365    memset(&u, 0, sizeof(u));
366 
367    assert( (dstreg.modifier & (SVGA3DDSTMOD_SATURATE | SVGA3DDSTMOD_PARTIALPRECISION)) == dstreg.modifier );
368 
369    if (dstreg.modifier & SVGA3DDSTMOD_SATURATE)
370       _debug_printf( "_sat" );
371    if (dstreg.modifier & SVGA3DDSTMOD_PARTIALPRECISION)
372       _debug_printf( "_pp" );
373    switch (dstreg.shift_scale) {
374    case 0:
375       break;
376    case 1:
377       _debug_printf( "_x2" );
378       break;
379    case 2:
380       _debug_printf( "_x4" );
381       break;
382    case 3:
383       _debug_printf( "_x8" );
384       break;
385    case 13:
386       _debug_printf( "_d8" );
387       break;
388    case 14:
389       _debug_printf( "_d4" );
390       break;
391    case 15:
392       _debug_printf( "_d2" );
393       break;
394    default:
395       assert( 0 );
396    }
397    _debug_printf( " " );
398 
399    u.dstreg = dstreg;
400    dump_reg( u.reg, indreg, di);
401    if (dstreg.write_mask != SVGA3DWRITEMASK_ALL) {
402       _debug_printf( "." );
403       if (dstreg.write_mask & SVGA3DWRITEMASK_0)
404          _debug_printf( "x" );
405       if (dstreg.write_mask & SVGA3DWRITEMASK_1)
406          _debug_printf( "y" );
407       if (dstreg.write_mask & SVGA3DWRITEMASK_2)
408          _debug_printf( "z" );
409       if (dstreg.write_mask & SVGA3DWRITEMASK_3)
410          _debug_printf( "w" );
411    }
412 }
413 
dump_srcreg(struct sh_srcreg srcreg,struct sh_srcreg * indreg,const struct dump_info * di)414 static void dump_srcreg( struct sh_srcreg srcreg, struct sh_srcreg *indreg, const struct dump_info *di )
415 {
416    switch (srcreg.modifier) {
417    case SVGA3DSRCMOD_NEG:
418    case SVGA3DSRCMOD_BIASNEG:
419    case SVGA3DSRCMOD_SIGNNEG:
420    case SVGA3DSRCMOD_X2NEG:
421    case SVGA3DSRCMOD_ABSNEG:
422       _debug_printf( "-" );
423       break;
424    case SVGA3DSRCMOD_COMP:
425       _debug_printf( "1-" );
426       break;
427    case SVGA3DSRCMOD_NOT:
428       _debug_printf( "!" );
429    }
430    dump_reg( *(struct sh_reg *) &srcreg, indreg, di );
431    switch (srcreg.modifier) {
432    case SVGA3DSRCMOD_NONE:
433    case SVGA3DSRCMOD_NEG:
434    case SVGA3DSRCMOD_COMP:
435    case SVGA3DSRCMOD_NOT:
436       break;
437    case SVGA3DSRCMOD_BIAS:
438    case SVGA3DSRCMOD_BIASNEG:
439       _debug_printf( "_bias" );
440       break;
441    case SVGA3DSRCMOD_SIGN:
442    case SVGA3DSRCMOD_SIGNNEG:
443       _debug_printf( "_bx2" );
444       break;
445    case SVGA3DSRCMOD_X2:
446    case SVGA3DSRCMOD_X2NEG:
447       _debug_printf( "_x2" );
448       break;
449    case SVGA3DSRCMOD_DZ:
450       _debug_printf( "_dz" );
451       break;
452    case SVGA3DSRCMOD_DW:
453       _debug_printf( "_dw" );
454       break;
455    case SVGA3DSRCMOD_ABS:
456    case SVGA3DSRCMOD_ABSNEG:
457       _debug_printf("_abs");
458       break;
459    default:
460       assert( 0 );
461    }
462    if (srcreg.swizzle_x != 0 || srcreg.swizzle_y != 1 || srcreg.swizzle_z != 2 || srcreg.swizzle_w != 3) {
463       _debug_printf( "." );
464       if (srcreg.swizzle_x == srcreg.swizzle_y && srcreg.swizzle_y == srcreg.swizzle_z && srcreg.swizzle_z == srcreg.swizzle_w) {
465          _debug_printf( "%c", "xyzw"[srcreg.swizzle_x] );
466       }
467       else {
468          _debug_printf( "%c", "xyzw"[srcreg.swizzle_x] );
469          _debug_printf( "%c", "xyzw"[srcreg.swizzle_y] );
470          _debug_printf( "%c", "xyzw"[srcreg.swizzle_z] );
471          _debug_printf( "%c", "xyzw"[srcreg.swizzle_w] );
472       }
473    }
474 }
475 
476 static void
parse_op(struct dump_info * di,const uint ** token,struct dump_op * op,uint num_dst,uint num_src)477 parse_op(struct dump_info *di,
478          const uint **token,
479          struct dump_op *op,
480          uint num_dst,
481          uint num_src)
482 {
483    uint i;
484 
485    assert(num_dst <= 1);
486    assert(num_src <= DUMP_MAX_OP_SRC);
487 
488    op->op = *(struct sh_op *)*token;
489    *token += sizeof(struct sh_op) / sizeof(uint);
490 
491    if (num_dst >= 1) {
492       op->dst = *(struct sh_dstreg *)*token;
493       *token += sizeof(struct sh_dstreg) / sizeof(uint);
494       if (op->dst.relative &&
495           (!di->is_ps && di->version >= SVGA3D_VS_30)) {
496          op->dstind = *(struct sh_srcreg *)*token;
497          *token += sizeof(struct sh_srcreg) / sizeof(uint);
498       }
499    }
500 
501    if (op->op.predicated) {
502       op->p0 = *(struct sh_srcreg *)*token;
503       *token += sizeof(struct sh_srcreg) / sizeof(uint);
504    }
505 
506    for (i = 0; i < num_src; ++i) {
507       op->src[i] = *(struct sh_srcreg *)*token;
508       *token += sizeof(struct sh_srcreg) / sizeof(uint);
509       if (op->src[i].relative &&
510           ((!di->is_ps && di->version >= SVGA3D_VS_20) ||
511           (di->is_ps && di->version >= SVGA3D_PS_30))) {
512          op->srcind[i] = *(struct sh_srcreg *)*token;
513          *token += sizeof(struct sh_srcreg) / sizeof(uint);
514       }
515    }
516 }
517 
518 static void
dump_inst(struct dump_info * di,const unsigned ** assem,struct sh_op op,const struct sh_opcode_info * info)519 dump_inst(struct dump_info *di,
520           const unsigned **assem,
521           struct sh_op op,
522           const struct sh_opcode_info *info)
523 {
524    struct dump_op dop;
525    boolean not_first_arg = FALSE;
526    uint i;
527 
528    assert(info->num_dst <= 1);
529 
530    di->indent -= info->pre_dedent;
531    dump_indent(di->indent);
532    di->indent += info->post_indent;
533 
534    dump_op(op, info->mnemonic);
535 
536    parse_op(di, assem, &dop, info->num_dst, info->num_src);
537    if (info->num_dst > 0) {
538       dump_dstreg(dop.dst, &dop.dstind, di);
539       not_first_arg = TRUE;
540    }
541 
542    for (i = 0; i < info->num_src; i++) {
543       if (not_first_arg) {
544          _debug_printf(", ");
545       } else {
546          _debug_printf(" ");
547       }
548       dump_srcreg(dop.src[i], &dop.srcind[i], di);
549       not_first_arg = TRUE;
550    }
551 
552    _debug_printf("\n");
553 }
554 
555 void
svga_shader_dump(const unsigned * assem,unsigned dwords,unsigned do_binary)556 svga_shader_dump(
557    const unsigned *assem,
558    unsigned dwords,
559    unsigned do_binary )
560 {
561    boolean finished = FALSE;
562    struct dump_info di;
563 
564    di.version = *assem++;
565    di.is_ps = (di.version & 0xFFFF0000) == 0xFFFF0000;
566    di.indent = 0;
567 
568    _debug_printf(
569       "%s_%u_%u\n",
570       di.is_ps ? "ps" : "vs",
571       (di.version >> 8) & 0xff,
572       di.version & 0xff );
573 
574    while (!finished) {
575       struct sh_op op = *(struct sh_op *) assem;
576 
577       switch (op.opcode) {
578       case SVGA3DOP_DCL:
579          {
580             struct sh_dcl dcl = *(struct sh_dcl *) assem;
581 
582             _debug_printf( "dcl" );
583             switch (sh_dstreg_type(dcl.reg)) {
584             case SVGA3DREG_INPUT:
585                if ((di.is_ps && di.version >= SVGA3D_PS_30) ||
586                    (!di.is_ps && di.version >= SVGA3D_VS_30)) {
587                   dump_semantic(dcl.u.semantic.usage,
588                                 dcl.u.semantic.usage_index);
589                }
590                break;
591             case SVGA3DREG_TEXCRDOUT:
592                if (!di.is_ps && di.version >= SVGA3D_VS_30) {
593                   dump_semantic(dcl.u.semantic.usage,
594                                 dcl.u.semantic.usage_index);
595                }
596                break;
597             case SVGA3DREG_SAMPLER:
598                dump_sampleinfo( dcl.u.sampleinfo );
599                break;
600             }
601             dump_dstreg(dcl.reg, NULL, &di);
602             _debug_printf( "\n" );
603             assem += sizeof( struct sh_dcl ) / sizeof( unsigned );
604          }
605          break;
606 
607       case SVGA3DOP_DEFB:
608          {
609             struct sh_defb defb = *(struct sh_defb *) assem;
610 
611             _debug_printf( "defb " );
612             dump_reg( defb.reg, NULL, &di );
613             _debug_printf( ", " );
614             dump_bdata( defb.data );
615             _debug_printf( "\n" );
616             assem += sizeof( struct sh_defb ) / sizeof( unsigned );
617          }
618          break;
619 
620       case SVGA3DOP_DEFI:
621          {
622             struct sh_defi defi = *(struct sh_defi *) assem;
623 
624             _debug_printf( "defi " );
625             dump_reg( defi.reg, NULL, &di );
626             _debug_printf( ", " );
627             dump_idata( defi.idata );
628             _debug_printf( "\n" );
629             assem += sizeof( struct sh_defi ) / sizeof( unsigned );
630          }
631          break;
632 
633       case SVGA3DOP_TEXCOORD:
634          {
635             struct sh_opcode_info info = *svga_opcode_info(op.opcode);
636 
637             assert(di.is_ps);
638             if (di.version > SVGA3D_PS_13) {
639                assert(info.num_src == 0);
640 
641                info.num_src = 1;
642             }
643 
644             dump_inst(&di, &assem, op, &info);
645          }
646          break;
647 
648       case SVGA3DOP_TEX:
649          {
650             struct sh_opcode_info info = *svga_opcode_info(op.opcode);
651 
652             assert(di.is_ps);
653             if (di.version > SVGA3D_PS_13) {
654                assert(info.num_src == 0);
655 
656                if (di.version > SVGA3D_PS_14) {
657                   info.num_src = 2;
658                   info.mnemonic = "texld";
659                } else {
660                   info.num_src = 1;
661                }
662             }
663 
664             dump_inst(&di, &assem, op, &info);
665          }
666          break;
667 
668       case SVGA3DOP_DEF:
669          {
670             struct sh_def def = *(struct sh_def *) assem;
671 
672             _debug_printf( "def " );
673             dump_reg( def.reg, NULL, &di );
674             _debug_printf( ", " );
675             dump_cdata( def.cdata );
676             _debug_printf( "\n" );
677             assem += sizeof( struct sh_def ) / sizeof( unsigned );
678          }
679          break;
680 
681       case SVGA3DOP_SINCOS:
682          {
683             struct sh_opcode_info info = *svga_opcode_info(op.opcode);
684 
685             if ((di.is_ps && di.version >= SVGA3D_PS_30) ||
686                 (!di.is_ps && di.version >= SVGA3D_VS_30)) {
687                assert(info.num_src == 3);
688 
689                info.num_src = 1;
690             }
691 
692             dump_inst(&di, &assem, op, &info);
693          }
694          break;
695 
696       case SVGA3DOP_PHASE:
697          _debug_printf( "phase\n" );
698          assem += sizeof( struct sh_op ) / sizeof( unsigned );
699          break;
700 
701       case SVGA3DOP_COMMENT:
702          {
703             struct sh_comment comment = *(struct sh_comment *)assem;
704 
705             /* Ignore comment contents. */
706             assem += sizeof(struct sh_comment) / sizeof(unsigned) + comment.size;
707          }
708          break;
709 
710       case SVGA3DOP_END:
711          finished = TRUE;
712          break;
713 
714       default:
715          {
716             const struct sh_opcode_info *info = svga_opcode_info(op.opcode);
717 
718             dump_inst(&di, &assem, op, info);
719          }
720       }
721    }
722 }
723