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