2 * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
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:
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
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. */
23 #include "radeon_program.h"
27 static const char * textarget_to_string(rc_texture_target 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";
41 static const char * presubtract_op_to_string(rc_presubtract_op op
)
47 return "(1 - 2 * src0)";
49 return "(src1 - src0)";
51 return "(src1 + src0)";
55 return "BAD_PRESUBTRACT_OP";
59 static void print_omod_op(FILE * f
, rc_omod_op op
)
61 const char * omod_str
;
88 fprintf(f
, " %s", omod_str
);
91 static void rc_print_comparefunc(FILE * f
, const char * lhs
, rc_compare_func func
, const char * rhs
)
93 if (func
== RC_COMPARE_FUNC_NEVER
) {
95 } else if (func
== RC_COMPARE_FUNC_ALWAYS
) {
100 case RC_COMPARE_FUNC_LESS
: op
= "<"; break;
101 case RC_COMPARE_FUNC_EQUAL
: op
= "=="; break;
102 case RC_COMPARE_FUNC_LEQUAL
: op
= "<="; break;
103 case RC_COMPARE_FUNC_GREATER
: op
= ">"; break;
104 case RC_COMPARE_FUNC_NOTEQUAL
: op
= "!="; break;
105 case RC_COMPARE_FUNC_GEQUAL
: op
= ">="; break;
106 default: op
= "???"; break;
108 fprintf(f
, "%s %s %s", lhs
, op
, rhs
);
112 static void rc_print_inline_float(FILE * f
, int index
)
114 int r300_exponent
= (index
>> 3) & 0xf;
115 unsigned r300_mantissa
= index
& 0x7;
116 unsigned float_exponent
;
118 float * print_float
= (float*) &real_float
;
121 float_exponent
= r300_exponent
+ 127;
122 real_float
= (r300_mantissa
<< 20) | (float_exponent
<< 23);
124 fprintf(f
, "%f (0x%x)", *print_float
, index
);
128 static void rc_print_register(FILE * f
, rc_register_file file
, int index
, unsigned int reladdr
)
130 if (file
== RC_FILE_NONE
) {
132 } else if (file
== RC_FILE_SPECIAL
) {
134 case RC_SPECIAL_ALU_RESULT
: fprintf(f
, "aluresult"); break;
135 default: fprintf(f
, "special[%i]", index
); break;
137 } else if (file
== RC_FILE_INLINE
) {
138 rc_print_inline_float(f
, index
);
140 const char * filename
;
142 case RC_FILE_TEMPORARY
: filename
= "temp"; break;
143 case RC_FILE_INPUT
: filename
= "input"; break;
144 case RC_FILE_OUTPUT
: filename
= "output"; break;
145 case RC_FILE_ADDRESS
: filename
= "addr"; break;
146 case RC_FILE_CONSTANT
: filename
= "const"; break;
147 default: filename
= "BAD FILE"; break;
149 fprintf(f
, "%s[%i%s]", filename
, index
, reladdr
? " + addr[0]" : "");
153 static void rc_print_mask(FILE * f
, unsigned int mask
)
155 if (mask
& RC_MASK_X
) fprintf(f
, "x");
156 if (mask
& RC_MASK_Y
) fprintf(f
, "y");
157 if (mask
& RC_MASK_Z
) fprintf(f
, "z");
158 if (mask
& RC_MASK_W
) fprintf(f
, "w");
161 static void rc_print_dst_register(FILE * f
, struct rc_dst_register dst
)
163 rc_print_register(f
, dst
.File
, dst
.Index
, 0);
164 if (dst
.WriteMask
!= RC_MASK_XYZW
) {
166 rc_print_mask(f
, dst
.WriteMask
);
170 static char rc_swizzle_char(unsigned int swz
)
173 case RC_SWIZZLE_X
: return 'x';
174 case RC_SWIZZLE_Y
: return 'y';
175 case RC_SWIZZLE_Z
: return 'z';
176 case RC_SWIZZLE_W
: return 'w';
177 case RC_SWIZZLE_ZERO
: return '0';
178 case RC_SWIZZLE_ONE
: return '1';
179 case RC_SWIZZLE_HALF
: return 'H';
180 case RC_SWIZZLE_UNUSED
: return '_';
182 fprintf(stderr
, "bad swz: %u\n", swz
);
186 static void rc_print_swizzle(FILE * f
, unsigned int swizzle
, unsigned int negate
)
189 for(comp
= 0; comp
< 4; ++comp
) {
190 rc_swizzle swz
= GET_SWZ(swizzle
, comp
);
191 if (GET_BIT(negate
, comp
))
193 fprintf(f
, "%c", rc_swizzle_char(swz
));
197 static void rc_print_presub_instruction(FILE * f
,
198 struct rc_presub_instruction inst
)
203 fprintf(f
, "1 - 2 * ");
204 rc_print_register(f
, inst
.SrcReg
[0].File
,
205 inst
.SrcReg
[0].Index
,inst
.SrcReg
[0].RelAddr
);
208 rc_print_register(f
, inst
.SrcReg
[1].File
,
209 inst
.SrcReg
[1].Index
,inst
.SrcReg
[1].RelAddr
);
211 rc_print_register(f
, inst
.SrcReg
[0].File
,
212 inst
.SrcReg
[0].Index
,inst
.SrcReg
[0].RelAddr
);
215 rc_print_register(f
, inst
.SrcReg
[1].File
,
216 inst
.SrcReg
[1].Index
,inst
.SrcReg
[1].RelAddr
);
218 rc_print_register(f
, inst
.SrcReg
[0].File
,
219 inst
.SrcReg
[0].Index
,inst
.SrcReg
[0].RelAddr
);
223 rc_print_register(f
, inst
.SrcReg
[0].File
,
224 inst
.SrcReg
[0].Index
,inst
.SrcReg
[0].RelAddr
);
232 static void rc_print_src_register(FILE * f
, struct rc_instruction
* inst
,
233 struct rc_src_register src
)
235 int trivial_negate
= (src
.Negate
== RC_MASK_NONE
|| src
.Negate
== RC_MASK_XYZW
);
237 if (src
.Negate
== RC_MASK_XYZW
)
242 if(src
.File
== RC_FILE_PRESUB
)
243 rc_print_presub_instruction(f
, inst
->U
.I
.PreSub
);
245 rc_print_register(f
, src
.File
, src
.Index
, src
.RelAddr
);
247 if (src
.Abs
&& !trivial_negate
)
250 if (src
.Swizzle
!= RC_SWIZZLE_XYZW
|| !trivial_negate
) {
252 rc_print_swizzle(f
, src
.Swizzle
, trivial_negate
? 0 : src
.Negate
);
255 if (src
.Abs
&& trivial_negate
)
259 static unsigned update_branch_depth(rc_opcode opcode
, unsigned *branch_depth
)
263 case RC_OPCODE_BGNLOOP
:
264 return (*branch_depth
)++ * 2;
266 case RC_OPCODE_ENDIF
:
267 case RC_OPCODE_ENDLOOP
:
268 assert(*branch_depth
> 0);
269 return --(*branch_depth
) * 2;
272 assert(*branch_depth
> 0);
273 return (*branch_depth
- 1) * 2;
276 return *branch_depth
* 2;
280 static void rc_print_normal_instruction(FILE * f
, struct rc_instruction
* inst
, unsigned *branch_depth
)
282 const struct rc_opcode_info
* opcode
= rc_get_opcode_info(inst
->U
.I
.Opcode
);
284 unsigned spaces
= update_branch_depth(inst
->U
.I
.Opcode
, branch_depth
);
286 for (unsigned i
= 0; i
< spaces
; i
++)
289 fprintf(f
, "%s", opcode
->Name
);
291 switch(inst
->U
.I
.SaturateMode
) {
292 case RC_SATURATE_NONE
: break;
293 case RC_SATURATE_ZERO_ONE
: fprintf(f
, "_SAT"); break;
294 case RC_SATURATE_MINUS_PLUS_ONE
: fprintf(f
, "_SAT2"); break;
295 default: fprintf(f
, "_BAD_SAT"); break;
298 if (opcode
->HasDstReg
) {
300 rc_print_dst_register(f
, inst
->U
.I
.DstReg
);
301 print_omod_op(f
, inst
->U
.I
.Omod
);
302 if (opcode
->NumSrcRegs
)
306 for(reg
= 0; reg
< opcode
->NumSrcRegs
; ++reg
) {
310 rc_print_src_register(f
, inst
, inst
->U
.I
.SrcReg
[reg
]);
313 if (opcode
->HasTexture
) {
314 fprintf(f
, ", %s%s[%u]%s%s",
315 textarget_to_string(inst
->U
.I
.TexSrcTarget
),
316 inst
->U
.I
.TexShadow
? "SHADOW" : "",
317 inst
->U
.I
.TexSrcUnit
,
318 inst
->U
.I
.TexSemWait
? " SEM_WAIT" : "",
319 inst
->U
.I
.TexSemAcquire
? " SEM_ACQUIRE" : "");
324 if (inst
->U
.I
.WriteALUResult
) {
325 fprintf(f
, " [aluresult = (");
326 rc_print_comparefunc(f
,
327 (inst
->U
.I
.WriteALUResult
== RC_ALURESULT_X
) ? "x" : "w",
328 inst
->U
.I
.ALUResultCompare
, "0");
332 if (inst
->U
.I
.DstReg
.Pred
== RC_PRED_SET
) {
333 fprintf(f
, " PRED_SET");
334 } else if (inst
->U
.I
.DstReg
.Pred
== RC_PRED_INV
) {
335 fprintf(f
, " PRED_INV");
341 static void rc_print_pair_instruction(FILE * f
, struct rc_instruction
* fullinst
, unsigned *branch_depth
)
343 struct rc_pair_instruction
* inst
= &fullinst
->U
.P
;
345 unsigned spaces
= update_branch_depth(inst
->RGB
.Opcode
!= RC_OPCODE_NOP
?
346 inst
->RGB
.Opcode
: inst
->Alpha
.Opcode
, branch_depth
);
348 for (unsigned i
= 0; i
< spaces
; i
++)
351 for(unsigned int src
= 0; src
< 3; ++src
) {
352 if (inst
->RGB
.Src
[src
].Used
) {
355 fprintf(f
, "src%i.xyz = ", src
);
356 rc_print_register(f
, inst
->RGB
.Src
[src
].File
, inst
->RGB
.Src
[src
].Index
, 0);
359 if (inst
->Alpha
.Src
[src
].Used
) {
362 fprintf(f
, "src%i.w = ", src
);
363 rc_print_register(f
, inst
->Alpha
.Src
[src
].File
, inst
->Alpha
.Src
[src
].Index
, 0);
367 if(inst
->RGB
.Src
[RC_PAIR_PRESUB_SRC
].Used
) {
368 fprintf(f
, ", srcp.xyz = %s",
369 presubtract_op_to_string(
370 inst
->RGB
.Src
[RC_PAIR_PRESUB_SRC
].Index
));
372 if(inst
->Alpha
.Src
[RC_PAIR_PRESUB_SRC
].Used
) {
373 fprintf(f
, ", srcp.w = %s",
374 presubtract_op_to_string(
375 inst
->Alpha
.Src
[RC_PAIR_PRESUB_SRC
].Index
));
378 fprintf(f
, " SEM_WAIT");
382 if (inst
->RGB
.Opcode
!= RC_OPCODE_NOP
) {
383 const struct rc_opcode_info
* opcode
= rc_get_opcode_info(inst
->RGB
.Opcode
);
385 for (unsigned i
= 0; i
< spaces
; i
++)
388 fprintf(f
, " %s%s", opcode
->Name
, inst
->RGB
.Saturate
? "_SAT" : "");
389 if (inst
->RGB
.WriteMask
)
390 fprintf(f
, " temp[%i].%s%s%s", inst
->RGB
.DestIndex
,
391 (inst
->RGB
.WriteMask
& 1) ? "x" : "",
392 (inst
->RGB
.WriteMask
& 2) ? "y" : "",
393 (inst
->RGB
.WriteMask
& 4) ? "z" : "");
394 if (inst
->RGB
.OutputWriteMask
)
395 fprintf(f
, " color[%i].%s%s%s", inst
->RGB
.Target
,
396 (inst
->RGB
.OutputWriteMask
& 1) ? "x" : "",
397 (inst
->RGB
.OutputWriteMask
& 2) ? "y" : "",
398 (inst
->RGB
.OutputWriteMask
& 4) ? "z" : "");
399 if (inst
->WriteALUResult
== RC_ALURESULT_X
)
400 fprintf(f
, " aluresult");
402 print_omod_op(f
, inst
->RGB
.Omod
);
404 for(unsigned int arg
= 0; arg
< opcode
->NumSrcRegs
; ++arg
) {
405 const char* abs
= inst
->RGB
.Arg
[arg
].Abs
? "|" : "";
406 const char* neg
= inst
->RGB
.Arg
[arg
].Negate
? "-" : "";
407 fprintf(f
, ", %s%ssrc", neg
, abs
);
408 if(inst
->RGB
.Arg
[arg
].Source
== RC_PAIR_PRESUB_SRC
)
411 fprintf(f
,"%d", inst
->RGB
.Arg
[arg
].Source
);
412 fprintf(f
,".%c%c%c%s",
413 rc_swizzle_char(GET_SWZ(inst
->RGB
.Arg
[arg
].Swizzle
, 0)),
414 rc_swizzle_char(GET_SWZ(inst
->RGB
.Arg
[arg
].Swizzle
, 1)),
415 rc_swizzle_char(GET_SWZ(inst
->RGB
.Arg
[arg
].Swizzle
, 2)),
421 if (inst
->Alpha
.Opcode
!= RC_OPCODE_NOP
) {
422 const struct rc_opcode_info
* opcode
= rc_get_opcode_info(inst
->Alpha
.Opcode
);
424 for (unsigned i
= 0; i
< spaces
; i
++)
427 fprintf(f
, " %s%s", opcode
->Name
, inst
->Alpha
.Saturate
? "_SAT" : "");
428 if (inst
->Alpha
.WriteMask
)
429 fprintf(f
, " temp[%i].w", inst
->Alpha
.DestIndex
);
430 if (inst
->Alpha
.OutputWriteMask
)
431 fprintf(f
, " color[%i].w", inst
->Alpha
.Target
);
432 if (inst
->Alpha
.DepthWriteMask
)
433 fprintf(f
, " depth.w");
434 if (inst
->WriteALUResult
== RC_ALURESULT_W
)
435 fprintf(f
, " aluresult");
437 print_omod_op(f
, inst
->Alpha
.Omod
);
439 for(unsigned int arg
= 0; arg
< opcode
->NumSrcRegs
; ++arg
) {
440 const char* abs
= inst
->Alpha
.Arg
[arg
].Abs
? "|" : "";
441 const char* neg
= inst
->Alpha
.Arg
[arg
].Negate
? "-" : "";
442 fprintf(f
, ", %s%ssrc", neg
, abs
);
443 if(inst
->Alpha
.Arg
[arg
].Source
== RC_PAIR_PRESUB_SRC
)
446 fprintf(f
,"%d", inst
->Alpha
.Arg
[arg
].Source
);
448 rc_swizzle_char(GET_SWZ(inst
->Alpha
.Arg
[arg
].Swizzle
, 0)), abs
);
453 if (inst
->WriteALUResult
) {
454 for (unsigned i
= 0; i
< spaces
; i
++)
457 fprintf(f
, " [aluresult = (");
458 rc_print_comparefunc(f
, "result", inst
->ALUResultCompare
, "0");
464 * Print program to stderr, default options.
466 void rc_print_program(const struct rc_program
*prog
)
468 unsigned int linenum
= 0;
469 unsigned branch_depth
= 0;
470 struct rc_instruction
*inst
;
472 fprintf(stderr
, "# Radeon Compiler Program\n");
474 for(inst
= prog
->Instructions
.Next
; inst
!= &prog
->Instructions
; inst
= inst
->Next
) {
475 fprintf(stderr
, "%3d: ", linenum
);
477 if (inst
->Type
== RC_INSTRUCTION_PAIR
)
478 rc_print_pair_instruction(stderr
, inst
, &branch_depth
);
480 rc_print_normal_instruction(stderr
, inst
, &branch_depth
);