r300/compiler: Add a more efficient version of rc_find_free_temporary()
[mesa.git] / src / mesa / drivers / dri / r300 / compiler / radeon_program.h
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 #ifndef __RADEON_PROGRAM_H_
29 #define __RADEON_PROGRAM_H_
30
31 #include <stdint.h>
32 #include <string.h>
33
34 #include "radeon_opcodes.h"
35 #include "radeon_code.h"
36 #include "radeon_program_constants.h"
37 #include "radeon_program_pair.h"
38
39 struct radeon_compiler;
40
41 struct rc_src_register {
42 unsigned int File:4;
43
44 /** Negative values may be used for relative addressing. */
45 signed int Index:(RC_REGISTER_INDEX_BITS+1);
46 unsigned int RelAddr:1;
47
48 unsigned int Swizzle:12;
49
50 /** Take the component-wise absolute value */
51 unsigned int Abs:1;
52
53 /** Post-Abs negation. */
54 unsigned int Negate:4;
55 };
56
57 struct rc_dst_register {
58 unsigned int File:3;
59
60 /** Negative values may be used for relative addressing. */
61 signed int Index:(RC_REGISTER_INDEX_BITS+1);
62 unsigned int RelAddr:1;
63
64 unsigned int WriteMask:4;
65 };
66
67 struct rc_presub_instruction {
68 rc_presubtract_op Opcode;
69 struct rc_src_register SrcReg[2];
70 };
71
72 /**
73 * Instructions are maintained by the compiler in a doubly linked list
74 * of these structures.
75 *
76 * This instruction format is intended to be expanded for hardware-specific
77 * trickery. At different stages of compilation, a different set of
78 * instruction types may be valid.
79 */
80 struct rc_sub_instruction {
81 struct rc_src_register SrcReg[3];
82 struct rc_dst_register DstReg;
83
84 /**
85 * Opcode of this instruction, according to \ref rc_opcode enums.
86 */
87 unsigned int Opcode:8;
88
89 /**
90 * Saturate each value of the result to the range [0,1] or [-1,1],
91 * according to \ref rc_saturate_mode enums.
92 */
93 unsigned int SaturateMode:2;
94
95 /**
96 * Writing to the special register RC_SPECIAL_ALU_RESULT
97 */
98 /*@{*/
99 unsigned int WriteALUResult:2;
100 unsigned int ALUResultCompare:3;
101 /*@}*/
102
103 /**
104 * \name Extra fields for TEX, TXB, TXD, TXL, TXP instructions.
105 */
106 /*@{*/
107 /** Source texture unit. */
108 unsigned int TexSrcUnit:5;
109
110 /** Source texture target, one of the \ref rc_texture_target enums */
111 unsigned int TexSrcTarget:3;
112
113 /** True if tex instruction should do shadow comparison */
114 unsigned int TexShadow:1;
115 /*@}*/
116
117 /** This holds information about the presubtract operation used by
118 * this instruction. */
119 struct rc_presub_instruction PreSub;
120 };
121
122 typedef enum {
123 RC_INSTRUCTION_NORMAL = 0,
124 RC_INSTRUCTION_PAIR
125 } rc_instruction_type;
126
127 struct rc_instruction {
128 struct rc_instruction * Prev;
129 struct rc_instruction * Next;
130
131 rc_instruction_type Type;
132 union {
133 struct rc_sub_instruction I;
134 struct rc_pair_instruction P;
135 } U;
136
137 /**
138 * Warning: IPs are not stable. If you want to use them,
139 * you need to recompute them at the beginning of each pass
140 * using \ref rc_recompute_ips
141 */
142 unsigned int IP;
143 };
144
145 struct rc_program {
146 /**
147 * Instructions.Next points to the first instruction,
148 * Instructions.Prev points to the last instruction.
149 */
150 struct rc_instruction Instructions;
151
152 /* Long term, we should probably remove InputsRead & OutputsWritten,
153 * since updating dependent state can be fragile, and they aren't
154 * actually used very often. */
155 uint32_t InputsRead;
156 uint32_t OutputsWritten;
157 uint32_t ShadowSamplers; /**< Texture units used for shadow sampling. */
158
159 struct rc_constant_list Constants;
160 };
161
162 static inline rc_swizzle get_swz(unsigned int swz, rc_swizzle idx)
163 {
164 if (idx & 0x4)
165 return idx;
166 return GET_SWZ(swz, idx);
167 }
168
169 static inline unsigned int combine_swizzles4(unsigned int src,
170 rc_swizzle swz_x, rc_swizzle swz_y, rc_swizzle swz_z, rc_swizzle swz_w)
171 {
172 unsigned int ret = 0;
173
174 ret |= get_swz(src, swz_x);
175 ret |= get_swz(src, swz_y) << 3;
176 ret |= get_swz(src, swz_z) << 6;
177 ret |= get_swz(src, swz_w) << 9;
178
179 return ret;
180 }
181
182 static inline unsigned int combine_swizzles(unsigned int src, unsigned int swz)
183 {
184 unsigned int ret = 0;
185
186 ret |= get_swz(src, GET_SWZ(swz, RC_SWIZZLE_X));
187 ret |= get_swz(src, GET_SWZ(swz, RC_SWIZZLE_Y)) << 3;
188 ret |= get_swz(src, GET_SWZ(swz, RC_SWIZZLE_Z)) << 6;
189 ret |= get_swz(src, GET_SWZ(swz, RC_SWIZZLE_W)) << 9;
190
191 return ret;
192 }
193
194 /**
195 * @param mask Must be either RC_MASK_X, RC_MASK_Y, RC_MASK_Z, or RC_MASK_W
196 */
197 static inline rc_swizzle rc_mask_to_swz(unsigned int mask)
198 {
199 switch (mask) {
200 case RC_MASK_X: return RC_SWIZZLE_X;
201 case RC_MASK_Y: return RC_SWIZZLE_Y;
202 case RC_MASK_Z: return RC_SWIZZLE_Z;
203 case RC_MASK_W: return RC_SWIZZLE_W;
204 default: assert(0);
205 }
206 return RC_SWIZZLE_UNUSED;
207 }
208 struct rc_src_register lmul_swizzle(unsigned int swizzle, struct rc_src_register srcreg);
209
210 static inline void reset_srcreg(struct rc_src_register* reg)
211 {
212 memset(reg, 0, sizeof(struct rc_src_register));
213 reg->Swizzle = RC_SWIZZLE_XYZW;
214 }
215
216
217 /**
218 * A transformation that can be passed to \ref rc_local_transform.
219 *
220 * The function will be called once for each instruction.
221 * It has to either emit the appropriate transformed code for the instruction
222 * and return true, or return false if it doesn't understand the
223 * instruction.
224 *
225 * The function gets passed the userData as last parameter.
226 */
227 struct radeon_program_transformation {
228 int (*function)(
229 struct radeon_compiler*,
230 struct rc_instruction*,
231 void*);
232 void *userData;
233 };
234
235 void rc_local_transform(
236 struct radeon_compiler *c,
237 void *user);
238
239 void rc_get_used_temporaries(
240 struct radeon_compiler * c,
241 unsigned char * used,
242 unsigned int used_length);
243
244 int rc_find_free_temporary_list(
245 struct radeon_compiler * c,
246 unsigned char * used,
247 unsigned int used_length,
248 unsigned int mask);
249
250 unsigned int rc_find_free_temporary(struct radeon_compiler * c);
251
252 struct rc_instruction *rc_alloc_instruction(struct radeon_compiler * c);
253 struct rc_instruction *rc_insert_new_instruction(struct radeon_compiler * c, struct rc_instruction * after);
254 void rc_insert_instruction(struct rc_instruction * after, struct rc_instruction * inst);
255 void rc_remove_instruction(struct rc_instruction * inst);
256
257 unsigned int rc_recompute_ips(struct radeon_compiler * c);
258
259 void rc_print_program(const struct rc_program *prog);
260
261 rc_swizzle rc_mask_to_swizzle(unsigned int mask);
262 #endif