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