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