2 * Copyright (C) 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_dataflow.h"
30 #include "radeon_program.h"
33 static void reads_normal(struct rc_instruction
* fullinst
, rc_read_write_fn cb
, void * userdata
)
35 struct rc_sub_instruction
* inst
= &fullinst
->U
.I
;
36 const struct rc_opcode_info
* opcode
= rc_get_opcode_info(inst
->Opcode
);
38 for(unsigned int src
= 0; src
< opcode
->NumSrcRegs
; ++src
) {
39 unsigned int refmask
= 0;
41 if (inst
->SrcReg
[src
].File
== RC_FILE_NONE
)
44 for(unsigned int chan
= 0; chan
< 4; ++chan
)
45 refmask
|= 1 << GET_SWZ(inst
->SrcReg
[src
].Swizzle
, chan
);
47 refmask
&= RC_MASK_XYZW
;
49 for(unsigned int chan
= 0; chan
< 4; ++chan
) {
50 if (GET_BIT(refmask
, chan
)) {
51 cb(userdata
, fullinst
, inst
->SrcReg
[src
].File
, inst
->SrcReg
[src
].Index
, chan
);
55 if (refmask
&& inst
->SrcReg
[src
].RelAddr
)
56 cb(userdata
, fullinst
, RC_FILE_ADDRESS
, 0, RC_MASK_X
);
60 static void reads_pair(struct rc_instruction
* fullinst
, rc_read_write_fn cb
, void * userdata
)
62 struct rc_pair_instruction
* inst
= &fullinst
->U
.P
;
63 unsigned int refmasks
[3] = { 0, 0, 0 };
65 if (inst
->RGB
.Opcode
!= RC_OPCODE_NOP
) {
66 const struct rc_opcode_info
* opcode
= rc_get_opcode_info(inst
->RGB
.Opcode
);
68 for(unsigned int arg
= 0; arg
< opcode
->NumSrcRegs
; ++arg
) {
69 for(unsigned int chan
= 0; chan
< 3; ++chan
) {
70 unsigned int swz
= GET_SWZ(inst
->RGB
.Arg
[arg
].Swizzle
, chan
);
72 refmasks
[inst
->RGB
.Arg
[arg
].Source
] |= 1 << swz
;
77 if (inst
->Alpha
.Opcode
!= RC_OPCODE_NOP
) {
78 const struct rc_opcode_info
* opcode
= rc_get_opcode_info(inst
->Alpha
.Opcode
);
80 for(unsigned int arg
= 0; arg
< opcode
->NumSrcRegs
; ++arg
) {
81 if (inst
->Alpha
.Arg
[arg
].Swizzle
< 4)
82 refmasks
[inst
->Alpha
.Arg
[arg
].Source
] |= 1 << inst
->Alpha
.Arg
[arg
].Swizzle
;
86 for(unsigned int src
= 0; src
< 3; ++src
) {
87 if (inst
->RGB
.Src
[src
].Used
) {
88 for(unsigned int chan
= 0; chan
< 3; ++chan
) {
89 if (GET_BIT(refmasks
[src
], chan
))
90 cb(userdata
, fullinst
, inst
->RGB
.Src
[src
].File
, inst
->RGB
.Src
[src
].Index
, chan
);
94 if (inst
->Alpha
.Src
[src
].Used
) {
95 if (GET_BIT(refmasks
[src
], 3))
96 cb(userdata
, fullinst
, inst
->Alpha
.Src
[src
].File
, inst
->Alpha
.Src
[src
].Index
, 3);
102 * Calls a callback function for all sourced register channels.
104 * This is conservative, i.e. channels may be called multiple times,
105 * and the writemask of the instruction is not taken into account.
107 void rc_for_all_reads(struct rc_instruction
* inst
, rc_read_write_fn cb
, void * userdata
)
109 if (inst
->Type
== RC_INSTRUCTION_NORMAL
) {
110 reads_normal(inst
, cb
, userdata
);
112 reads_pair(inst
, cb
, userdata
);
118 static void writes_normal(struct rc_instruction
* fullinst
, rc_read_write_fn cb
, void * userdata
)
120 struct rc_sub_instruction
* inst
= &fullinst
->U
.I
;
121 const struct rc_opcode_info
* opcode
= rc_get_opcode_info(inst
->Opcode
);
123 if (opcode
->HasDstReg
) {
124 for(unsigned int chan
= 0; chan
< 4; ++chan
) {
125 if (GET_BIT(inst
->DstReg
.WriteMask
, chan
))
126 cb(userdata
, fullinst
, inst
->DstReg
.File
, inst
->DstReg
.Index
, chan
);
130 if (inst
->WriteALUResult
)
131 cb(userdata
, fullinst
, RC_FILE_SPECIAL
, RC_SPECIAL_ALU_RESULT
, 0);
134 static void writes_pair(struct rc_instruction
* fullinst
, rc_read_write_fn cb
, void * userdata
)
136 struct rc_pair_instruction
* inst
= &fullinst
->U
.P
;
138 for(unsigned int chan
= 0; chan
< 3; ++chan
) {
139 if (GET_BIT(inst
->RGB
.WriteMask
, chan
))
140 cb(userdata
, fullinst
, RC_FILE_TEMPORARY
, inst
->RGB
.DestIndex
, chan
);
143 if (inst
->Alpha
.WriteMask
)
144 cb(userdata
, fullinst
, RC_FILE_TEMPORARY
, inst
->Alpha
.DestIndex
, 3);
146 if (inst
->WriteALUResult
)
147 cb(userdata
, fullinst
, RC_FILE_SPECIAL
, RC_SPECIAL_ALU_RESULT
, 0);
151 * Calls a callback function for all written register channels.
153 * \warning Does not report output registers for paired instructions!
155 void rc_for_all_writes(struct rc_instruction
* inst
, rc_read_write_fn cb
, void * userdata
)
157 if (inst
->Type
== RC_INSTRUCTION_NORMAL
) {
158 writes_normal(inst
, cb
, userdata
);
160 writes_pair(inst
, cb
, userdata
);
165 static void remap_normal_instruction(struct rc_instruction
* fullinst
,
166 rc_remap_register_fn cb
, void * userdata
)
168 struct rc_sub_instruction
* inst
= &fullinst
->U
.I
;
169 const struct rc_opcode_info
* opcode
= rc_get_opcode_info(inst
->Opcode
);
171 if (opcode
->HasDstReg
) {
172 rc_register_file file
= inst
->DstReg
.File
;
173 unsigned int index
= inst
->DstReg
.Index
;
175 cb(userdata
, fullinst
, &file
, &index
);
177 inst
->DstReg
.File
= file
;
178 inst
->DstReg
.Index
= index
;
181 for(unsigned int src
= 0; src
< opcode
->NumSrcRegs
; ++src
) {
182 rc_register_file file
= inst
->SrcReg
[src
].File
;
183 unsigned int index
= inst
->SrcReg
[src
].Index
;
185 cb(userdata
, fullinst
, &file
, &index
);
187 inst
->SrcReg
[src
].File
= file
;
188 inst
->SrcReg
[src
].Index
= index
;
192 static void remap_pair_instruction(struct rc_instruction
* fullinst
,
193 rc_remap_register_fn cb
, void * userdata
)
195 struct rc_pair_instruction
* inst
= &fullinst
->U
.P
;
197 if (inst
->RGB
.WriteMask
) {
198 rc_register_file file
= RC_FILE_TEMPORARY
;
199 unsigned int index
= inst
->RGB
.DestIndex
;
201 cb(userdata
, fullinst
, &file
, &index
);
203 inst
->RGB
.DestIndex
= index
;
206 if (inst
->Alpha
.WriteMask
) {
207 rc_register_file file
= RC_FILE_TEMPORARY
;
208 unsigned int index
= inst
->Alpha
.DestIndex
;
210 cb(userdata
, fullinst
, &file
, &index
);
212 inst
->Alpha
.DestIndex
= index
;
215 for(unsigned int src
= 0; src
< 3; ++src
) {
216 if (inst
->RGB
.Src
[src
].Used
) {
217 rc_register_file file
= inst
->RGB
.Src
[src
].File
;
218 unsigned int index
= inst
->RGB
.Src
[src
].Index
;
220 cb(userdata
, fullinst
, &file
, &index
);
222 inst
->RGB
.Src
[src
].File
= file
;
223 inst
->RGB
.Src
[src
].Index
= index
;
226 if (inst
->Alpha
.Src
[src
].Used
) {
227 rc_register_file file
= inst
->Alpha
.Src
[src
].File
;
228 unsigned int index
= inst
->Alpha
.Src
[src
].Index
;
230 cb(userdata
, fullinst
, &file
, &index
);
232 inst
->Alpha
.Src
[src
].File
= file
;
233 inst
->Alpha
.Src
[src
].Index
= index
;
240 * Remap all register accesses according to the given function.
241 * That is, call the function \p cb for each referenced register (both read and written)
242 * and update the given instruction \p inst accordingly
243 * if it modifies its \ref pfile and \ref pindex contents.
245 void rc_remap_registers(struct rc_instruction
* inst
, rc_remap_register_fn cb
, void * userdata
)
247 if (inst
->Type
== RC_INSTRUCTION_NORMAL
)
248 remap_normal_instruction(inst
, cb
, userdata
);
250 remap_pair_instruction(inst
, cb
, userdata
);