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