r300/compiler: Move declaration before code.
[mesa.git] / src / mesa / drivers / dri / r300 / compiler / radeon_program.c
1 /*
2 * Copyright (C) 2008 Nicolai Haehnle.
3 *
4 * All Rights Reserved.
5 *
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:
13 *
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.
17 *
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.
25 *
26 */
27
28 #include "radeon_program.h"
29
30 #include <stdio.h>
31
32 #include "radeon_compiler.h"
33 #include "radeon_dataflow.h"
34
35
36 /**
37 * Transform the given clause in the following way:
38 * 1. Replace it with an empty clause
39 * 2. For every instruction in the original clause, try the given
40 * transformations in order.
41 * 3. If one of the transformations returns GL_TRUE, assume that it
42 * has emitted the appropriate instruction(s) into the new clause;
43 * otherwise, copy the instruction verbatim.
44 *
45 * \note The transformation is currently not recursive; in other words,
46 * instructions emitted by transformations are not transformed.
47 *
48 * \note The transform is called 'local' because it can only look at
49 * one instruction at a time.
50 */
51 void rc_local_transform(
52 struct radeon_compiler * c,
53 void *user)
54 {
55 struct radeon_program_transformation *transformations =
56 (struct radeon_program_transformation*)user;
57 struct rc_instruction * inst = c->Program.Instructions.Next;
58
59 while(inst != &c->Program.Instructions) {
60 struct rc_instruction * current = inst;
61 int i;
62
63 inst = inst->Next;
64
65 for(i = 0; transformations[i].function; ++i) {
66 struct radeon_program_transformation* t = transformations + i;
67
68 if (t->function(c, current, t->userData))
69 break;
70 }
71 }
72 }
73
74 /**
75 * Left multiplication of a register with a swizzle
76 */
77 struct rc_src_register lmul_swizzle(unsigned int swizzle, struct rc_src_register srcreg)
78 {
79 struct rc_src_register tmp = srcreg;
80 int i;
81 tmp.Swizzle = 0;
82 tmp.Negate = 0;
83 for(i = 0; i < 4; ++i) {
84 rc_swizzle swz = GET_SWZ(swizzle, i);
85 if (swz < 4) {
86 tmp.Swizzle |= GET_SWZ(srcreg.Swizzle, swz) << (i*3);
87 tmp.Negate |= GET_BIT(srcreg.Negate, swz) << i;
88 } else {
89 tmp.Swizzle |= swz << (i*3);
90 }
91 }
92 return tmp;
93 }
94
95 struct get_used_temporaries_data {
96 unsigned char * Used;
97 unsigned int UsedLength;
98 };
99
100 static void get_used_temporaries_cb(
101 void * userdata,
102 struct rc_instruction * inst,
103 rc_register_file file,
104 unsigned int index,
105 unsigned int mask)
106 {
107 struct get_used_temporaries_data * d = userdata;
108
109 if (file != RC_FILE_TEMPORARY)
110 return;
111
112 if (index >= d->UsedLength)
113 return;
114
115 d->Used[index] |= mask;
116 }
117
118 /**
119 * This function fills in the parameter 'used' with a writemask that
120 * represent which components of each temporary register are used by the
121 * program. This is meant to be combined with rc_find_free_temporary_list as a
122 * more efficient version of rc_find_free_temporary.
123 * @param used The function does not initialize this parameter.
124 */
125 void rc_get_used_temporaries(
126 struct radeon_compiler * c,
127 unsigned char * used,
128 unsigned int used_length)
129 {
130 struct rc_instruction * inst;
131 struct get_used_temporaries_data d;
132 d.Used = used;
133 d.UsedLength = used_length;
134
135 for(inst = c->Program.Instructions.Next;
136 inst != &c->Program.Instructions; inst = inst->Next) {
137
138 rc_for_all_reads_mask(inst, get_used_temporaries_cb, &d);
139 rc_for_all_writes_mask(inst, get_used_temporaries_cb, &d);
140 }
141 }
142
143 /* Search a list of used temporaries for a free one
144 * \sa rc_get_used_temporaries
145 * @note If this functions finds a free temporary, it will mark it as used
146 * in the used temporary list (param 'used')
147 * @param used list of used temporaries
148 * @param used_length number of items in param 'used'
149 * @param mask which components must be free in the temporary index that is
150 * returned.
151 * @return -1 If there are no more free temporaries, otherwise the index of
152 * a temporary register where the components specified in param 'mask' are
153 * not being used.
154 */
155 int rc_find_free_temporary_list(
156 struct radeon_compiler * c,
157 unsigned char * used,
158 unsigned int used_length,
159 unsigned int mask)
160 {
161 int i;
162 for(i = 0; i < used_length; i++) {
163 if ((~used[i] & mask) == mask) {
164 used[i] |= mask;
165 return i;
166 }
167 }
168 return -1;
169 }
170
171 unsigned int rc_find_free_temporary(struct radeon_compiler * c)
172 {
173 unsigned char used[RC_REGISTER_MAX_INDEX];
174 int free;
175
176 memset(used, 0, sizeof(used));
177
178 rc_get_used_temporaries(c, used, RC_REGISTER_MAX_INDEX);
179
180 free = rc_find_free_temporary_list(c, used, RC_REGISTER_MAX_INDEX,
181 RC_MASK_XYZW);
182 if (free < 0) {
183 rc_error(c, "Ran out of temporary registers\n");
184 return 0;
185 }
186 return free;
187 }
188
189
190 struct rc_instruction *rc_alloc_instruction(struct radeon_compiler * c)
191 {
192 struct rc_instruction * inst = memory_pool_malloc(&c->Pool, sizeof(struct rc_instruction));
193
194 memset(inst, 0, sizeof(struct rc_instruction));
195
196 inst->U.I.Opcode = RC_OPCODE_ILLEGAL_OPCODE;
197 inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
198 inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
199 inst->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_XYZW;
200 inst->U.I.SrcReg[2].Swizzle = RC_SWIZZLE_XYZW;
201
202 return inst;
203 }
204
205 void rc_insert_instruction(struct rc_instruction * after, struct rc_instruction * inst)
206 {
207 inst->Prev = after;
208 inst->Next = after->Next;
209
210 inst->Prev->Next = inst;
211 inst->Next->Prev = inst;
212 }
213
214 struct rc_instruction *rc_insert_new_instruction(struct radeon_compiler * c, struct rc_instruction * after)
215 {
216 struct rc_instruction * inst = rc_alloc_instruction(c);
217
218 rc_insert_instruction(after, inst);
219
220 return inst;
221 }
222
223 void rc_remove_instruction(struct rc_instruction * inst)
224 {
225 inst->Prev->Next = inst->Next;
226 inst->Next->Prev = inst->Prev;
227 }
228
229 /**
230 * Return the number of instructions in the program.
231 */
232 unsigned int rc_recompute_ips(struct radeon_compiler * c)
233 {
234 unsigned int ip = 0;
235 struct rc_instruction * inst;
236
237 for(inst = c->Program.Instructions.Next;
238 inst != &c->Program.Instructions;
239 inst = inst->Next) {
240 inst->IP = ip++;
241 }
242
243 c->Program.Instructions.IP = 0xcafedead;
244
245 return ip;
246 }
247
248 rc_swizzle rc_mask_to_swizzle(unsigned int mask)
249 {
250 switch(mask) {
251 case RC_MASK_X: return RC_SWIZZLE_X;
252 case RC_MASK_Y: return RC_SWIZZLE_Y;
253 case RC_MASK_Z: return RC_SWIZZLE_Z;
254 case RC_MASK_W: return RC_SWIZZLE_W;
255 default: return RC_SWIZZLE_UNUSED;
256 }
257 }