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