Home | History | Annotate | Download | only in i915
      1 /**************************************************************************
      2  *
      3  * Copyright 2003 VMware, Inc.
      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 VMWARE 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 
     29 #include "i915_reg.h"
     30 #include "i915_debug.h"
     31 #include "i915_debug_private.h"
     32 #include "util/u_debug.h"
     33 
     34 
     35 static void
     36 PRINTF(
     37    struct debug_stream  *stream,
     38    const char           *fmt,
     39                         ... )
     40 {
     41    va_list  args;
     42 
     43    va_start( args, fmt );
     44    debug_vprintf( fmt, args );
     45    va_end( args );
     46 }
     47 
     48 
     49 static const char *opcodes[0x20] = {
     50    "NOP",
     51    "ADD",
     52    "MOV",
     53    "MUL",
     54    "MAD",
     55    "DP2ADD",
     56    "DP3",
     57    "DP4",
     58    "FRC",
     59    "RCP",
     60    "RSQ",
     61    "EXP",
     62    "LOG",
     63    "CMP",
     64    "MIN",
     65    "MAX",
     66    "FLR",
     67    "MOD",
     68    "TRC",
     69    "SGE",
     70    "SLT",
     71    "TEXLD",
     72    "TEXLDP",
     73    "TEXLDB",
     74    "TEXKILL",
     75    "DCL",
     76    "0x1a",
     77    "0x1b",
     78    "0x1c",
     79    "0x1d",
     80    "0x1e",
     81    "0x1f",
     82 };
     83 
     84 
     85 static const int args[0x20] = {
     86    0,                           /* 0 nop */
     87    2,                           /* 1 add */
     88    1,                           /* 2 mov */
     89    2,                           /* 3 m ul */
     90    3,                           /* 4 mad */
     91    3,                           /* 5 dp2add */
     92    2,                           /* 6 dp3 */
     93    2,                           /* 7 dp4 */
     94    1,                           /* 8 frc */
     95    1,                           /* 9 rcp */
     96    1,                           /* a rsq */
     97    1,                           /* b exp */
     98    1,                           /* c log */
     99    3,                           /* d cmp */
    100    2,                           /* e min */
    101    2,                           /* f max */
    102    1,                           /* 10 flr */
    103    1,                           /* 11 mod */
    104    1,                           /* 12 trc */
    105    2,                           /* 13 sge */
    106    2,                           /* 14 slt */
    107    1,
    108    1,
    109    1,
    110    1,
    111    0,
    112    0,
    113    0,
    114    0,
    115    0,
    116    0,
    117    0,
    118 };
    119 
    120 
    121 static const char *regname[0x8] = {
    122    "R",
    123    "T",
    124    "CONST",
    125    "S",
    126    "OC",
    127    "OD",
    128    "U",
    129    "UNKNOWN",
    130 };
    131 
    132 static void
    133 print_reg_type_nr(struct debug_stream *stream, unsigned type, unsigned nr)
    134 {
    135    switch (type) {
    136    case REG_TYPE_T:
    137       switch (nr) {
    138       case T_DIFFUSE:
    139          PRINTF(stream, "T_DIFFUSE");
    140          return;
    141       case T_SPECULAR:
    142          PRINTF(stream, "T_SPECULAR");
    143          return;
    144       case T_FOG_W:
    145          PRINTF(stream, "T_FOG_W");
    146          return;
    147       default:
    148          PRINTF(stream, "T_TEX%d", nr);
    149          return;
    150       }
    151    case REG_TYPE_OC:
    152       if (nr == 0) {
    153          PRINTF(stream, "oC");
    154          return;
    155       }
    156       break;
    157    case REG_TYPE_OD:
    158       if (nr == 0) {
    159          PRINTF(stream, "oD");
    160          return;
    161       }
    162       break;
    163    default:
    164       break;
    165    }
    166 
    167    PRINTF(stream, "%s[%d]", regname[type], nr);
    168 }
    169 
    170 #define REG_SWIZZLE_MASK 0x7777
    171 #define REG_NEGATE_MASK 0x8888
    172 
    173 #define REG_SWIZZLE_XYZW ((SRC_X << A2_SRC2_CHANNEL_X_SHIFT) |	\
    174 		      (SRC_Y << A2_SRC2_CHANNEL_Y_SHIFT) |	\
    175 		      (SRC_Z << A2_SRC2_CHANNEL_Z_SHIFT) |	\
    176 		      (SRC_W << A2_SRC2_CHANNEL_W_SHIFT))
    177 
    178 
    179 static void
    180 print_reg_neg_swizzle(struct debug_stream *stream, unsigned reg)
    181 {
    182    int i;
    183 
    184    if ((reg & REG_SWIZZLE_MASK) == REG_SWIZZLE_XYZW &&
    185        (reg & REG_NEGATE_MASK) == 0)
    186       return;
    187 
    188    PRINTF(stream, ".");
    189 
    190    for (i = 3; i >= 0; i--) {
    191       if (reg & (1 << ((i * 4) + 3)))
    192          PRINTF(stream, "-");
    193 
    194       switch ((reg >> (i * 4)) & 0x7) {
    195       case 0:
    196          PRINTF(stream, "x");
    197          break;
    198       case 1:
    199          PRINTF(stream, "y");
    200          break;
    201       case 2:
    202          PRINTF(stream, "z");
    203          break;
    204       case 3:
    205          PRINTF(stream, "w");
    206          break;
    207       case 4:
    208          PRINTF(stream, "0");
    209          break;
    210       case 5:
    211          PRINTF(stream, "1");
    212          break;
    213       default:
    214          PRINTF(stream, "?");
    215          break;
    216       }
    217    }
    218 }
    219 
    220 
    221 static void
    222 print_src_reg(struct debug_stream *stream, unsigned dword)
    223 {
    224    unsigned nr = (dword >> A2_SRC2_NR_SHIFT) & REG_NR_MASK;
    225    unsigned type = (dword >> A2_SRC2_TYPE_SHIFT) & REG_TYPE_MASK;
    226    print_reg_type_nr(stream, type, nr);
    227    print_reg_neg_swizzle(stream, dword);
    228 }
    229 
    230 
    231 static void
    232 print_dest_reg(struct debug_stream *stream, unsigned dword)
    233 {
    234    unsigned nr = (dword >> A0_DEST_NR_SHIFT) & REG_NR_MASK;
    235    unsigned type = (dword >> A0_DEST_TYPE_SHIFT) & REG_TYPE_MASK;
    236    print_reg_type_nr(stream, type, nr);
    237    if ((dword & A0_DEST_CHANNEL_ALL) == A0_DEST_CHANNEL_ALL)
    238       return;
    239    PRINTF(stream, ".");
    240    if (dword & A0_DEST_CHANNEL_X)
    241       PRINTF(stream, "x");
    242    if (dword & A0_DEST_CHANNEL_Y)
    243       PRINTF(stream, "y");
    244    if (dword & A0_DEST_CHANNEL_Z)
    245       PRINTF(stream, "z");
    246    if (dword & A0_DEST_CHANNEL_W)
    247       PRINTF(stream, "w");
    248 }
    249 
    250 
    251 #define GET_SRC0_REG(r0, r1) ((r0<<14)|(r1>>A1_SRC0_CHANNEL_W_SHIFT))
    252 #define GET_SRC1_REG(r0, r1) ((r0<<8)|(r1>>A2_SRC1_CHANNEL_W_SHIFT))
    253 #define GET_SRC2_REG(r)      (r)
    254 
    255 
    256 static void
    257 print_arith_op(struct debug_stream *stream,
    258 	       unsigned opcode, const unsigned * program)
    259 {
    260    if (opcode != A0_NOP) {
    261       print_dest_reg(stream, program[0]);
    262       if (program[0] & A0_DEST_SATURATE)
    263          PRINTF(stream, " = SATURATE ");
    264       else
    265          PRINTF(stream, " = ");
    266    }
    267 
    268    PRINTF(stream, "%s ", opcodes[opcode]);
    269 
    270    print_src_reg(stream, GET_SRC0_REG(program[0], program[1]));
    271    if (args[opcode] == 1) {
    272       PRINTF(stream, "\n");
    273       return;
    274    }
    275 
    276    PRINTF(stream, ", ");
    277    print_src_reg(stream, GET_SRC1_REG(program[1], program[2]));
    278    if (args[opcode] == 2) {
    279       PRINTF(stream, "\n");
    280       return;
    281    }
    282 
    283    PRINTF(stream, ", ");
    284    print_src_reg(stream, GET_SRC2_REG(program[2]));
    285    PRINTF(stream, "\n");
    286    return;
    287 }
    288 
    289 
    290 static void
    291 print_tex_op(struct debug_stream *stream,
    292 	     unsigned opcode, const unsigned * program)
    293 {
    294    print_dest_reg(stream, program[0] | A0_DEST_CHANNEL_ALL);
    295    PRINTF(stream, " = ");
    296 
    297    PRINTF(stream, "%s ", opcodes[opcode]);
    298 
    299    PRINTF(stream, "S[%d],", program[0] & T0_SAMPLER_NR_MASK);
    300 
    301    print_reg_type_nr(stream,
    302 		     (program[1] >> T1_ADDRESS_REG_TYPE_SHIFT) &
    303                      REG_TYPE_MASK,
    304                      (program[1] >> T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK);
    305    PRINTF(stream, "\n");
    306 }
    307 
    308 static void
    309 print_texkil_op(struct debug_stream *stream,
    310                 unsigned opcode, const unsigned * program)
    311 {
    312    PRINTF(stream, "TEXKIL ");
    313 
    314    print_reg_type_nr(stream,
    315 		     (program[1] >> T1_ADDRESS_REG_TYPE_SHIFT) &
    316                      REG_TYPE_MASK,
    317                      (program[1] >> T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK);
    318    PRINTF(stream, "\n");
    319 }
    320 
    321 static void
    322 print_dcl_op(struct debug_stream *stream,
    323 	     unsigned opcode, const unsigned * program)
    324 {
    325    PRINTF(stream, "%s ", opcodes[opcode]);
    326    print_dest_reg(stream,
    327 		  program[0] | A0_DEST_CHANNEL_ALL);
    328    PRINTF(stream, "\n");
    329 }
    330 
    331 
    332 void
    333 i915_disassemble_program(struct debug_stream *stream,
    334 			 const unsigned * program, unsigned sz)
    335 {
    336    unsigned i;
    337 
    338    PRINTF(stream, "\t\tBEGIN\n");
    339 
    340    assert((program[0] & 0x1ff) + 2 == sz);
    341 
    342    for (i = 1; i < sz; i += 3, program += 3) {
    343       unsigned opcode = program[0] & (0x1f << 24);
    344 
    345       PRINTF(stream, "\t\t");
    346 
    347       if ((int) opcode >= A0_NOP && opcode <= A0_SLT)
    348          print_arith_op(stream, opcode >> 24, program);
    349       else if (opcode >= T0_TEXLD && opcode < T0_TEXKILL)
    350          print_tex_op(stream, opcode >> 24, program);
    351       else if (opcode == T0_TEXKILL)
    352          print_texkil_op(stream, opcode >> 24, program);
    353       else if (opcode == D0_DCL)
    354          print_dcl_op(stream, opcode >> 24, program);
    355       else
    356          PRINTF(stream, "Unknown opcode 0x%x\n", opcode);
    357    }
    358 
    359    PRINTF(stream, "\t\tEND\n\n");
    360 }
    361 
    362 
    363