Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / r300 / compiler / radeon_program_print.c
1 /*
2  * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * on the rights to use, copy, modify, merge, publish, distribute, sub
8  * license, and/or sell copies of the Software, and to permit persons to whom
9  * the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22
23 #include "radeon_program.h"
24
25 #include <stdio.h>
26
27 static const char * textarget_to_string(rc_texture_target target)
28 {
29         switch(target) {
30         case RC_TEXTURE_2D_ARRAY: return "2D_ARRAY";
31         case RC_TEXTURE_1D_ARRAY: return "1D_ARRAY";
32         case RC_TEXTURE_CUBE: return "CUBE";
33         case RC_TEXTURE_3D: return "3D";
34         case RC_TEXTURE_RECT: return "RECT";
35         case RC_TEXTURE_2D: return "2D";
36         case RC_TEXTURE_1D: return "1D";
37         default: return "BAD_TEXTURE_TARGET";
38         }
39 }
40
41 static const char * presubtract_op_to_string(rc_presubtract_op op)
42 {
43         switch(op) {
44         case RC_PRESUB_NONE:
45                 return "NONE";
46         case RC_PRESUB_BIAS:
47                 return "(1 - 2 * src0)";
48         case RC_PRESUB_SUB:
49                 return "(src1 - src0)";
50         case RC_PRESUB_ADD:
51                 return "(src1 + src0)";
52         case RC_PRESUB_INV:
53                 return "(1 - src0)";
54         default:
55                 return "BAD_PRESUBTRACT_OP";
56         }
57 }
58
59 static void rc_print_comparefunc(FILE * f, const char * lhs, rc_compare_func func, const char * rhs)
60 {
61         if (func == RC_COMPARE_FUNC_NEVER) {
62                 fprintf(f, "false");
63         } else if (func == RC_COMPARE_FUNC_ALWAYS) {
64                 fprintf(f, "true");
65         } else {
66                 const char * op;
67                 switch(func) {
68                 case RC_COMPARE_FUNC_LESS: op = "<"; break;
69                 case RC_COMPARE_FUNC_EQUAL: op = "=="; break;
70                 case RC_COMPARE_FUNC_LEQUAL: op = "<="; break;
71                 case RC_COMPARE_FUNC_GREATER: op = ">"; break;
72                 case RC_COMPARE_FUNC_NOTEQUAL: op = "!="; break;
73                 case RC_COMPARE_FUNC_GEQUAL: op = ">="; break;
74                 default: op = "???"; break;
75                 }
76                 fprintf(f, "%s %s %s", lhs, op, rhs);
77         }
78 }
79
80 static void rc_print_register(FILE * f, rc_register_file file, int index, unsigned int reladdr)
81 {
82         if (file == RC_FILE_NONE) {
83                 fprintf(f, "none");
84         } else if (file == RC_FILE_SPECIAL) {
85                 switch(index) {
86                 case RC_SPECIAL_ALU_RESULT: fprintf(f, "aluresult"); break;
87                 default: fprintf(f, "special[%i]", index); break;
88                 }
89         } else {
90                 const char * filename;
91                 switch(file) {
92                 case RC_FILE_TEMPORARY: filename = "temp"; break;
93                 case RC_FILE_INPUT: filename = "input"; break;
94                 case RC_FILE_OUTPUT: filename = "output"; break;
95                 case RC_FILE_ADDRESS: filename = "addr"; break;
96                 case RC_FILE_CONSTANT: filename = "const"; break;
97                 default: filename = "BAD FILE"; break;
98                 }
99                 fprintf(f, "%s[%i%s]", filename, index, reladdr ? " + addr[0]" : "");
100         }
101 }
102
103 static void rc_print_mask(FILE * f, unsigned int mask)
104 {
105         if (mask & RC_MASK_X) fprintf(f, "x");
106         if (mask & RC_MASK_Y) fprintf(f, "y");
107         if (mask & RC_MASK_Z) fprintf(f, "z");
108         if (mask & RC_MASK_W) fprintf(f, "w");
109 }
110
111 static void rc_print_dst_register(FILE * f, struct rc_dst_register dst)
112 {
113         rc_print_register(f, dst.File, dst.Index, 0);
114         if (dst.WriteMask != RC_MASK_XYZW) {
115                 fprintf(f, ".");
116                 rc_print_mask(f, dst.WriteMask);
117         }
118 }
119
120 static char rc_swizzle_char(unsigned int swz)
121 {
122         switch(swz) {
123         case RC_SWIZZLE_X: return 'x';
124         case RC_SWIZZLE_Y: return 'y';
125         case RC_SWIZZLE_Z: return 'z';
126         case RC_SWIZZLE_W: return 'w';
127         case RC_SWIZZLE_ZERO: return '0';
128         case RC_SWIZZLE_ONE: return '1';
129         case RC_SWIZZLE_HALF: return 'H';
130         case RC_SWIZZLE_UNUSED: return '_';
131         }
132         fprintf(stderr, "bad swz: %u\n", swz);
133         return '?';
134 }
135
136 static void rc_print_swizzle(FILE * f, unsigned int swizzle, unsigned int negate)
137 {
138         unsigned int comp;
139         for(comp = 0; comp < 4; ++comp) {
140                 rc_swizzle swz = GET_SWZ(swizzle, comp);
141                 if (GET_BIT(negate, comp))
142                         fprintf(f, "-");
143                 fprintf(f, "%c", rc_swizzle_char(swz));
144         }
145 }
146
147 static void rc_print_presub_instruction(FILE * f,
148                                         struct rc_presub_instruction inst)
149 {
150         fprintf(f,"(");
151         switch(inst.Opcode){
152         case RC_PRESUB_BIAS:
153                 fprintf(f, "1 - 2 * ");
154                 rc_print_register(f, inst.SrcReg[0].File,
155                                 inst.SrcReg[0].Index,inst.SrcReg[0].RelAddr);
156                 break;
157         case RC_PRESUB_SUB:
158                 rc_print_register(f, inst.SrcReg[1].File,
159                                 inst.SrcReg[1].Index,inst.SrcReg[1].RelAddr);
160                 fprintf(f, " - ");
161                 rc_print_register(f, inst.SrcReg[0].File,
162                                 inst.SrcReg[0].Index,inst.SrcReg[0].RelAddr);
163                 break;
164         case RC_PRESUB_ADD:
165                 rc_print_register(f, inst.SrcReg[1].File,
166                                 inst.SrcReg[1].Index,inst.SrcReg[1].RelAddr);
167                 fprintf(f, " + ");
168                 rc_print_register(f, inst.SrcReg[0].File,
169                                 inst.SrcReg[0].Index,inst.SrcReg[0].RelAddr);
170                 break;
171         case RC_PRESUB_INV:
172                 fprintf(f, "1 - ");
173                 rc_print_register(f, inst.SrcReg[0].File,
174                                 inst.SrcReg[0].Index,inst.SrcReg[0].RelAddr);
175                 break;
176         default:
177                 break;
178         }
179         fprintf(f, ")");
180 }
181
182 static void rc_print_src_register(FILE * f, struct rc_instruction * inst,
183                                                 struct rc_src_register src)
184 {
185         int trivial_negate = (src.Negate == RC_MASK_NONE || src.Negate == RC_MASK_XYZW);
186
187         if (src.Negate == RC_MASK_XYZW)
188                 fprintf(f, "-");
189         if (src.Abs)
190                 fprintf(f, "|");
191
192         if(src.File == RC_FILE_PRESUB)
193                 rc_print_presub_instruction(f, inst->U.I.PreSub);
194         else
195                 rc_print_register(f, src.File, src.Index, src.RelAddr);
196
197         if (src.Abs && !trivial_negate)
198                 fprintf(f, "|");
199
200         if (src.Swizzle != RC_SWIZZLE_XYZW || !trivial_negate) {
201                 fprintf(f, ".");
202                 rc_print_swizzle(f, src.Swizzle, trivial_negate ? 0 : src.Negate);
203         }
204
205         if (src.Abs && trivial_negate)
206                 fprintf(f, "|");
207 }
208
209 static unsigned update_branch_depth(rc_opcode opcode, unsigned *branch_depth)
210 {
211         switch (opcode) {
212         case RC_OPCODE_IF:
213         case RC_OPCODE_BGNLOOP:
214                 return (*branch_depth)++ * 2;
215
216         case RC_OPCODE_ENDIF:
217         case RC_OPCODE_ENDLOOP:
218                 assert(*branch_depth > 0);
219                 return --(*branch_depth) * 2;
220
221         case RC_OPCODE_ELSE:
222                 assert(*branch_depth > 0);
223                 return (*branch_depth - 1) * 2;
224
225         default:
226                 return *branch_depth * 2;
227         }
228 }
229
230 static void rc_print_normal_instruction(FILE * f, struct rc_instruction * inst, unsigned *branch_depth)
231 {
232         const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
233         unsigned int reg;
234         unsigned spaces = update_branch_depth(inst->U.I.Opcode, branch_depth);
235
236         for (unsigned i = 0; i < spaces; i++)
237                 fprintf(f, " ");
238
239         fprintf(f, "%s", opcode->Name);
240
241         switch(inst->U.I.SaturateMode) {
242         case RC_SATURATE_NONE: break;
243         case RC_SATURATE_ZERO_ONE: fprintf(f, "_SAT"); break;
244         case RC_SATURATE_MINUS_PLUS_ONE: fprintf(f, "_SAT2"); break;
245         default: fprintf(f, "_BAD_SAT"); break;
246         }
247
248         if (opcode->HasDstReg) {
249                 fprintf(f, " ");
250                 rc_print_dst_register(f, inst->U.I.DstReg);
251                 if (opcode->NumSrcRegs)
252                         fprintf(f, ",");
253         }
254
255         for(reg = 0; reg < opcode->NumSrcRegs; ++reg) {
256                 if (reg > 0)
257                         fprintf(f, ",");
258                 fprintf(f, " ");
259                 rc_print_src_register(f, inst, inst->U.I.SrcReg[reg]);
260         }
261
262         if (opcode->HasTexture) {
263                 fprintf(f, ", %s%s[%u]",
264                         textarget_to_string(inst->U.I.TexSrcTarget),
265                         inst->U.I.TexShadow ? "SHADOW" : "",
266                         inst->U.I.TexSrcUnit);
267         }
268
269         fprintf(f, ";");
270
271         if (inst->U.I.WriteALUResult) {
272                 fprintf(f, " [aluresult = (");
273                 rc_print_comparefunc(f,
274                         (inst->U.I.WriteALUResult == RC_ALURESULT_X) ? "x" : "w",
275                         inst->U.I.ALUResultCompare, "0");
276                 fprintf(f, ")]");
277         }
278
279         fprintf(f, "\n");
280 }
281
282 static void rc_print_pair_instruction(FILE * f, struct rc_instruction * fullinst, unsigned *branch_depth)
283 {
284         struct rc_pair_instruction * inst = &fullinst->U.P;
285         int printedsrc = 0;
286         unsigned spaces = update_branch_depth(inst->RGB.Opcode != RC_OPCODE_NOP ?
287                                               inst->RGB.Opcode : inst->Alpha.Opcode, branch_depth);
288
289         for (unsigned i = 0; i < spaces; i++)
290                 fprintf(f, " ");
291
292         for(unsigned int src = 0; src < 3; ++src) {
293                 if (inst->RGB.Src[src].Used) {
294                         if (printedsrc)
295                                 fprintf(f, ", ");
296                         fprintf(f, "src%i.xyz = ", src);
297                         rc_print_register(f, inst->RGB.Src[src].File, inst->RGB.Src[src].Index, 0);
298                         printedsrc = 1;
299                 }
300                 if (inst->Alpha.Src[src].Used) {
301                         if (printedsrc)
302                                 fprintf(f, ", ");
303                         fprintf(f, "src%i.w = ", src);
304                         rc_print_register(f, inst->Alpha.Src[src].File, inst->Alpha.Src[src].Index, 0);
305                         printedsrc = 1;
306                 }
307         }
308         if(inst->RGB.Src[RC_PAIR_PRESUB_SRC].Used) {
309                 fprintf(f, ", srcp.xyz = %s",
310                         presubtract_op_to_string(
311                                         inst->RGB.Src[RC_PAIR_PRESUB_SRC].Index));
312         }
313         if(inst->Alpha.Src[RC_PAIR_PRESUB_SRC].Used) {
314                 fprintf(f, ", srcp.w = %s",
315                         presubtract_op_to_string(
316                                         inst->Alpha.Src[RC_PAIR_PRESUB_SRC].Index));
317         }
318         fprintf(f, "\n");
319
320         if (inst->RGB.Opcode != RC_OPCODE_NOP) {
321                 const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->RGB.Opcode);
322
323                 for (unsigned i = 0; i < spaces; i++)
324                         fprintf(f, " ");
325
326                 fprintf(f, "     %s%s", opcode->Name, inst->RGB.Saturate ? "_SAT" : "");
327                 if (inst->RGB.WriteMask)
328                         fprintf(f, " temp[%i].%s%s%s", inst->RGB.DestIndex,
329                                 (inst->RGB.WriteMask & 1) ? "x" : "",
330                                 (inst->RGB.WriteMask & 2) ? "y" : "",
331                                 (inst->RGB.WriteMask & 4) ? "z" : "");
332                 if (inst->RGB.OutputWriteMask)
333                         fprintf(f, " color[%i].%s%s%s", inst->RGB.Target,
334                                 (inst->RGB.OutputWriteMask & 1) ? "x" : "",
335                                 (inst->RGB.OutputWriteMask & 2) ? "y" : "",
336                                 (inst->RGB.OutputWriteMask & 4) ? "z" : "");
337                 if (inst->WriteALUResult == RC_ALURESULT_X)
338                         fprintf(f, " aluresult");
339
340                 for(unsigned int arg = 0; arg < opcode->NumSrcRegs; ++arg) {
341                         const char* abs = inst->RGB.Arg[arg].Abs ? "|" : "";
342                         const char* neg = inst->RGB.Arg[arg].Negate ? "-" : "";
343                         fprintf(f, ", %s%ssrc", neg, abs);
344                         if(inst->RGB.Arg[arg].Source == RC_PAIR_PRESUB_SRC)
345                                 fprintf(f,"p");
346                         else
347                                 fprintf(f,"%d", inst->RGB.Arg[arg].Source);
348                         fprintf(f,".%c%c%c%s",
349                                 rc_swizzle_char(GET_SWZ(inst->RGB.Arg[arg].Swizzle, 0)),
350                                 rc_swizzle_char(GET_SWZ(inst->RGB.Arg[arg].Swizzle, 1)),
351                                 rc_swizzle_char(GET_SWZ(inst->RGB.Arg[arg].Swizzle, 2)),
352                                 abs);
353                 }
354                 fprintf(f, "\n");
355         }
356
357         if (inst->Alpha.Opcode != RC_OPCODE_NOP) {
358                 const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Alpha.Opcode);
359
360                 for (unsigned i = 0; i < spaces; i++)
361                         fprintf(f, " ");
362
363                 fprintf(f, "     %s%s", opcode->Name, inst->Alpha.Saturate ? "_SAT" : "");
364                 if (inst->Alpha.WriteMask)
365                         fprintf(f, " temp[%i].w", inst->Alpha.DestIndex);
366                 if (inst->Alpha.OutputWriteMask)
367                         fprintf(f, " color[%i].w", inst->Alpha.Target);
368                 if (inst->Alpha.DepthWriteMask)
369                         fprintf(f, " depth.w");
370                 if (inst->WriteALUResult == RC_ALURESULT_W)
371                         fprintf(f, " aluresult");
372
373                 for(unsigned int arg = 0; arg < opcode->NumSrcRegs; ++arg) {
374                         const char* abs = inst->Alpha.Arg[arg].Abs ? "|" : "";
375                         const char* neg = inst->Alpha.Arg[arg].Negate ? "-" : "";
376                         fprintf(f, ", %s%ssrc", neg, abs);
377                         if(inst->Alpha.Arg[arg].Source == RC_PAIR_PRESUB_SRC)
378                                 fprintf(f,"p");
379                         else
380                                 fprintf(f,"%d", inst->Alpha.Arg[arg].Source);
381                         fprintf(f,".%c%s",
382                                 rc_swizzle_char(GET_SWZ(inst->Alpha.Arg[arg].Swizzle, 0)), abs);
383                 }
384                 fprintf(f, "\n");
385         }
386
387         if (inst->WriteALUResult) {
388                 for (unsigned i = 0; i < spaces; i++)
389                         fprintf(f, " ");
390
391                 fprintf(f, "      [aluresult = (");
392                 rc_print_comparefunc(f, "result", inst->ALUResultCompare, "0");
393                 fprintf(f, ")]\n");
394         }
395 }
396
397 /**
398  * Print program to stderr, default options.
399  */
400 void rc_print_program(const struct rc_program *prog)
401 {
402         unsigned int linenum = 0;
403         unsigned branch_depth = 0;
404         struct rc_instruction *inst;
405
406         fprintf(stderr, "# Radeon Compiler Program\n");
407
408         for(inst = prog->Instructions.Next; inst != &prog->Instructions; inst = inst->Next) {
409                 fprintf(stderr, "%3d: ", linenum);
410
411                 if (inst->Type == RC_INSTRUCTION_PAIR)
412                         rc_print_pair_instruction(stderr, inst, &branch_depth);
413                 else
414                         rc_print_normal_instruction(stderr, inst, &branch_depth);
415
416                 linenum++;
417         }
418 }