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 #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    GLint i;
303 
304    printf("\t\tBEGIN\n");
305 
306    assert((program[0] & 0x1ff) + 2 == sz);
307 
308    program++;
309    for (i = 1; i < sz; i += 3, program += 3) {
310       GLuint opcode = program[0] & (0x1f << 24);
311 
312       printf("\t\t");
313 
314       if ((GLint) opcode >= A0_NOP && opcode <= A0_SLT)
315          print_arith_op(opcode >> 24, program);
316       else if (opcode >= T0_TEXLD && opcode <= T0_TEXKILL)
317          print_tex_op(opcode >> 24, program);
318       else if (opcode == D0_DCL)
319          print_dcl_op(opcode >> 24, program);
320       else
321          printf("Unknown opcode 0x%x\n", opcode);
322    }
323 
324    printf("\t\tEND\n\n");
325 }
326 
327 
328