nv50,nvc0: hold references to the framebuffer surfaces
[mesa.git] / src / gallium / drivers / nv50 / codegen / nv50_ir_inlines.h
1 /*
2 * Copyright 2011 Christoph Bumiller
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #ifndef __NV50_IR_INLINES_H__
24 #define __NV50_IR_INLINES_H__
25
26 static inline CondCode reverseCondCode(CondCode cc)
27 {
28 static const uint8_t ccRev[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
29
30 return static_cast<CondCode>(ccRev[cc & 7] | (cc & ~7));
31 }
32
33 static inline CondCode inverseCondCode(CondCode cc)
34 {
35 return static_cast<CondCode>(cc ^ 7);
36 }
37
38 static inline bool isMemoryFile(DataFile f)
39 {
40 return (f >= FILE_MEMORY_CONST && f <= FILE_MEMORY_LOCAL);
41 }
42
43 static inline bool isTextureOp(operation op)
44 {
45 return (op >= OP_TEX && op <= OP_TEXCSAA);
46 }
47
48 static inline unsigned int typeSizeof(DataType ty)
49 {
50 switch (ty) {
51 case TYPE_U8:
52 case TYPE_S8:
53 return 1;
54 case TYPE_F16:
55 case TYPE_U16:
56 case TYPE_S16:
57 return 2;
58 case TYPE_F32:
59 case TYPE_U32:
60 case TYPE_S32:
61 return 4;
62 case TYPE_F64:
63 case TYPE_U64:
64 case TYPE_S64:
65 return 8;
66 case TYPE_B96:
67 return 12;
68 case TYPE_B128:
69 return 16;
70 default:
71 return 0;
72 }
73 }
74
75 static inline DataType typeOfSize(unsigned int size,
76 bool flt = false, bool sgn = false)
77 {
78 switch (size) {
79 case 1: return sgn ? TYPE_S8 : TYPE_U8;
80 case 2: return flt ? TYPE_F16 : (sgn ? TYPE_S16 : TYPE_U16);
81 case 8: return flt ? TYPE_F64 : (sgn ? TYPE_S64 : TYPE_U64);
82 case 12: return TYPE_B96;
83 case 16: return TYPE_B128;
84 case 4:
85 default:
86 return flt ? TYPE_F32 : (sgn ? TYPE_S32 : TYPE_U32);
87 }
88 }
89
90 static inline bool isFloatType(DataType ty)
91 {
92 return (ty >= TYPE_F16 && ty <= TYPE_F64);
93 }
94
95 static inline bool isSignedIntType(DataType ty)
96 {
97 return (ty == TYPE_S8 || ty == TYPE_S16 || ty == TYPE_S32);
98 }
99
100 static inline bool isSignedType(DataType ty)
101 {
102 switch (ty) {
103 case TYPE_NONE:
104 case TYPE_U8:
105 case TYPE_U16:
106 case TYPE_U32:
107 case TYPE_B96:
108 case TYPE_B128:
109 return false;
110 default:
111 return true;
112 }
113 }
114
115 const ValueRef *ValueRef::getIndirect(int dim) const
116 {
117 return isIndirect(dim) ? &insn->src[indirect[dim]] : NULL;
118 }
119
120 DataFile ValueRef::getFile() const
121 {
122 return value ? value->reg.file : FILE_NULL;
123 }
124
125 unsigned int ValueRef::getSize() const
126 {
127 return value ? value->reg.size : 0;
128 }
129
130 Value *ValueRef::rep() const
131 {
132 assert(value);
133 return value->join;
134 }
135
136 Value *ValueDef::rep() const
137 {
138 assert(value);
139 return value->join;
140 }
141
142 DataFile ValueDef::getFile() const
143 {
144 return value ? value->reg.file : FILE_NULL;
145 }
146
147 unsigned int ValueDef::getSize() const
148 {
149 return value ? value->reg.size : 0;
150 }
151
152 void ValueDef::setSSA(LValue *lval)
153 {
154 Value *save = value;
155
156 this->set(NULL);
157 prev = reinterpret_cast<ValueDef *>(save);
158 value = lval;
159 lval->defs = this;
160 }
161
162 void ValueDef::restoreDefList()
163 {
164 if (next == this)
165 prev = this;
166 }
167
168 const LValue *ValueDef::preSSA() const
169 {
170 return reinterpret_cast<LValue *>(prev);
171 }
172
173 Instruction *Value::getInsn() const
174 {
175 assert(!defs || getUniqueInsn());
176 return defs ? defs->getInsn() : NULL;
177 }
178
179 Instruction *Value::getUniqueInsn() const
180 {
181 if (defs) {
182 if (join != this) {
183 ValueDef::Iterator it = defs->iterator();
184 while (!it.end() && it.get()->get() != this)
185 it.next();
186 assert(it.get()->get() == this);
187 return it.get()->getInsn();
188 }
189
190 // after regalloc, the definitions of coalesced values are linked
191 if (reg.data.id < 0) {
192 ValueDef::Iterator it = defs->iterator();
193 int nDef;
194 for (nDef = 0; !it.end() && nDef < 2; it.next())
195 if (it.get()->get() == this) // don't count joined values
196 ++nDef;
197 if (nDef > 1)
198 WARN("value %%%i not uniquely defined\n", id); // return NULL ?
199 }
200
201 assert(defs->get() == this);
202 return defs->getInsn();
203 }
204 return NULL;
205 }
206
207 Value *Instruction::getIndirect(int s, int dim) const
208 {
209 return src[s].isIndirect(dim) ? getSrc(src[s].indirect[dim]) : NULL;
210 }
211
212 Value *Instruction::getPredicate() const
213 {
214 return (predSrc >= 0) ? getSrc(predSrc) : NULL;
215 }
216
217 Value *TexInstruction::getIndirectR() const
218 {
219 return tex.rIndirectSrc >= 0 ? getSrc(tex.rIndirectSrc) : NULL;
220 }
221
222 Value *TexInstruction::getIndirectS() const
223 {
224 return tex.rIndirectSrc >= 0 ? getSrc(tex.rIndirectSrc) : NULL;
225 }
226
227 CmpInstruction *Instruction::asCmp()
228 {
229 if (op >= OP_SET_AND && op <= OP_SLCT && op != OP_SELP)
230 return static_cast<CmpInstruction *>(this);
231 return NULL;
232 }
233
234 const CmpInstruction *Instruction::asCmp() const
235 {
236 if (op >= OP_SET_AND && op <= OP_SLCT && op != OP_SELP)
237 return static_cast<const CmpInstruction *>(this);
238 return NULL;
239 }
240
241 FlowInstruction *Instruction::asFlow()
242 {
243 if (op >= OP_BRA && op <= OP_JOIN)
244 return static_cast<FlowInstruction *>(this);
245 return NULL;
246 }
247
248 const FlowInstruction *Instruction::asFlow() const
249 {
250 if (op >= OP_BRA && op <= OP_JOINAT)
251 return static_cast<const FlowInstruction *>(this);
252 return NULL;
253 }
254
255 TexInstruction *Instruction::asTex()
256 {
257 if (op >= OP_TEX && op <= OP_TEXCSAA)
258 return static_cast<TexInstruction *>(this);
259 return NULL;
260 }
261
262 const TexInstruction *Instruction::asTex() const
263 {
264 if (op >= OP_TEX && op <= OP_TEXCSAA)
265 return static_cast<const TexInstruction *>(this);
266 return NULL;
267 }
268
269 // XXX: use a virtual function so we're really really safe ?
270 LValue *Value::asLValue()
271 {
272 if (reg.file >= FILE_GPR && reg.file <= FILE_ADDRESS)
273 return static_cast<LValue *>(this);
274 return NULL;
275 }
276
277 Symbol *Value::asSym()
278 {
279 if (reg.file >= FILE_MEMORY_CONST)
280 return static_cast<Symbol *>(this);
281 return NULL;
282 }
283
284 const Symbol *Value::asSym() const
285 {
286 if (reg.file >= FILE_MEMORY_CONST)
287 return static_cast<const Symbol *>(this);
288 return NULL;
289 }
290
291 void Symbol::setOffset(int32_t offset)
292 {
293 reg.data.offset = offset;
294 }
295
296 void Symbol::setAddress(Symbol *base, int32_t offset)
297 {
298 baseSym = base;
299 reg.data.offset = offset;
300 }
301
302 void Symbol::setSV(SVSemantic sv, uint32_t index)
303 {
304 reg.data.sv.sv = sv;
305 reg.data.sv.index = index;
306 }
307
308 ImmediateValue *Value::asImm()
309 {
310 if (reg.file == FILE_IMMEDIATE)
311 return static_cast<ImmediateValue *>(this);
312 return NULL;
313 }
314
315 const ImmediateValue *Value::asImm() const
316 {
317 if (reg.file == FILE_IMMEDIATE)
318 return static_cast<const ImmediateValue *>(this);
319 return NULL;
320 }
321
322 Value *Value::get(Iterator &it)
323 {
324 return reinterpret_cast<Value *>(it.get());
325 }
326
327 bool BasicBlock::reachableBy(BasicBlock *by, BasicBlock *term)
328 {
329 return cfg.reachableBy(&by->cfg, &term->cfg);
330 }
331
332 BasicBlock *BasicBlock::get(Iterator &iter)
333 {
334 return reinterpret_cast<BasicBlock *>(iter.get());
335 }
336
337 BasicBlock *BasicBlock::get(Graph::Node *node)
338 {
339 assert(node);
340 return reinterpret_cast<BasicBlock *>(node->data);
341 }
342
343 LValue *Function::getLValue(int id)
344 {
345 assert((unsigned int)id < (unsigned int)allLValues.getSize());
346 return reinterpret_cast<LValue *>(allLValues.get(id));
347 }
348
349 #endif // __NV50_IR_INLINES_H__