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