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