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
);