2 * Copyright (C) 2008-2009 Nicolai Haehnle.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a 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, sublicense, 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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include "radeon_program_pair.h"
30 #include "radeon_compiler_util.h"
35 * Return the source slot where we installed the given register access,
36 * or -1 if no slot was free anymore.
38 int rc_pair_alloc_source(struct rc_pair_instruction
*pair
,
39 unsigned int rgb
, unsigned int alpha
,
40 rc_register_file file
, unsigned int index
)
43 int candidate_quality
= -1;
44 unsigned int alpha_used
= 0;
45 unsigned int rgb_used
= 0;
48 if ((!rgb
&& !alpha
) || file
== RC_FILE_NONE
)
51 /* Make sure only one presubtract operation is used per instruction. */
52 if (file
== RC_FILE_PRESUB
) {
53 if (rgb
&& pair
->RGB
.Src
[RC_PAIR_PRESUB_SRC
].Used
54 && index
!= pair
->RGB
.Src
[RC_PAIR_PRESUB_SRC
].Index
) {
58 if (alpha
&& pair
->Alpha
.Src
[RC_PAIR_PRESUB_SRC
].Used
59 && index
!= pair
->Alpha
.Src
[RC_PAIR_PRESUB_SRC
].Index
) {
64 for(i
= 0; i
< 3; ++i
) {
67 if (pair
->RGB
.Src
[i
].Used
) {
68 if (pair
->RGB
.Src
[i
].File
!= file
||
69 pair
->RGB
.Src
[i
].Index
!= index
) {
77 if (pair
->Alpha
.Src
[i
].Used
) {
78 if (pair
->Alpha
.Src
[i
].File
!= file
||
79 pair
->Alpha
.Src
[i
].Index
!= index
) {
86 if (q
> candidate_quality
) {
87 candidate_quality
= q
;
92 if (file
== RC_FILE_PRESUB
) {
93 candidate
= RC_PAIR_PRESUB_SRC
;
94 } else if (candidate
< 0 || (rgb
&& rgb_used
> 2)
95 || (alpha
&& alpha_used
> 2)) {
102 pair
->RGB
.Src
[candidate
].Used
= 1;
103 pair
->RGB
.Src
[candidate
].File
= file
;
104 pair
->RGB
.Src
[candidate
].Index
= index
;
105 if (candidate
== RC_PAIR_PRESUB_SRC
) {
106 /* For registers with the RC_FILE_PRESUB file,
107 * the index stores the presubtract op. */
108 int src_regs
= rc_presubtract_src_reg_count(index
);
109 for(i
= 0; i
< src_regs
; i
++) {
110 pair
->RGB
.Src
[i
].Used
= 1;
115 pair
->Alpha
.Src
[candidate
].Used
= 1;
116 pair
->Alpha
.Src
[candidate
].File
= file
;
117 pair
->Alpha
.Src
[candidate
].Index
= index
;
118 if (candidate
== RC_PAIR_PRESUB_SRC
) {
119 /* For registers with the RC_FILE_PRESUB file,
120 * the index stores the presubtract op. */
121 int src_regs
= rc_presubtract_src_reg_count(index
);
122 for(i
=0; i
< src_regs
; i
++) {
123 pair
->Alpha
.Src
[i
].Used
= 1;
131 static void pair_foreach_source_callback(
132 struct rc_pair_instruction
* pair
,
134 rc_pair_foreach_src_fn cb
,
138 /* swz > 3 means that the swizzle is either not used, or a constant
139 * swizzle (e.g. 0, 1, 0.5). */
143 if(swz
== RC_SWIZZLE_W
) {
144 if (src
== RC_PAIR_PRESUB_SRC
) {
146 unsigned int src_count
= rc_presubtract_src_reg_count(
147 pair
->Alpha
.Src
[RC_PAIR_PRESUB_SRC
].Index
);
148 for(i
= 0; i
< src_count
; i
++) {
149 cb(data
, &pair
->Alpha
.Src
[i
]);
152 cb(data
, &pair
->Alpha
.Src
[src
]);
155 if (src
== RC_PAIR_PRESUB_SRC
) {
157 unsigned int src_count
= rc_presubtract_src_reg_count(
158 pair
->RGB
.Src
[RC_PAIR_PRESUB_SRC
].Index
);
159 for(i
= 0; i
< src_count
; i
++) {
160 cb(data
, &pair
->RGB
.Src
[i
]);
164 cb(data
, &pair
->RGB
.Src
[src
]);
169 void rc_pair_foreach_source_that_alpha_reads(
170 struct rc_pair_instruction
* pair
,
172 rc_pair_foreach_src_fn cb
)
175 const struct rc_opcode_info
* info
=
176 rc_get_opcode_info(pair
->Alpha
.Opcode
);
177 for(i
= 0; i
< info
->NumSrcRegs
; i
++) {
178 pair_foreach_source_callback(pair
, data
, cb
,
179 GET_SWZ(pair
->Alpha
.Arg
[i
].Swizzle
, 0),
180 pair
->Alpha
.Arg
[i
].Source
);
184 void rc_pair_foreach_source_that_rgb_reads(
185 struct rc_pair_instruction
* pair
,
187 rc_pair_foreach_src_fn cb
)
190 const struct rc_opcode_info
* info
=
191 rc_get_opcode_info(pair
->RGB
.Opcode
);
192 for(i
= 0; i
< info
->NumSrcRegs
; i
++) {
194 unsigned int swz
= RC_SWIZZLE_UNUSED
;
195 /* Find a swizzle that is either X,Y,Z,or W. We assume here
196 * that if one channel swizzles X,Y, or Z, then none of the
197 * other channels swizzle W, and vice-versa. */
198 for(chan
= 0; chan
< 4; chan
++) {
199 swz
= GET_SWZ(pair
->RGB
.Arg
[i
].Swizzle
, chan
);
200 if(swz
== RC_SWIZZLE_X
|| swz
== RC_SWIZZLE_Y
201 || swz
== RC_SWIZZLE_Z
|| swz
== RC_SWIZZLE_W
)
204 pair_foreach_source_callback(pair
, data
, cb
,
206 pair
->RGB
.Arg
[i
].Source
);
210 struct rc_pair_instruction_source
* rc_pair_get_src(
211 struct rc_pair_instruction
* pair_inst
,
212 struct rc_pair_instruction_arg
* arg
)
216 type
= rc_source_type_swz(arg
->Swizzle
);
218 if (type
& RC_SOURCE_RGB
) {
219 return &pair_inst
->RGB
.Src
[arg
->Source
];
220 } else if (type
& RC_SOURCE_ALPHA
) {
221 return &pair_inst
->Alpha
.Src
[arg
->Source
];
227 int rc_pair_get_src_index(
228 struct rc_pair_instruction
* pair_inst
,
229 struct rc_pair_instruction_source
* src
)
232 for (i
= 0; i
< 3; i
++) {
233 if (&pair_inst
->RGB
.Src
[i
] == src
234 || &pair_inst
->Alpha
.Src
[i
] == src
) {