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