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