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