sync with tizen_2.2
[sdk/emulator/qemu.git] / gl / mesa / src / gallium / drivers / nv50 / codegen / nv50_ir_build_util.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_BUILD_UTIL__
24 #define __NV50_IR_BUILD_UTIL__
25
26 namespace nv50_ir {
27
28 class BuildUtil
29 {
30 public:
31    BuildUtil();
32
33    inline void setProgram(Program *);
34    inline Program *getProgram() const { return prog; }
35    inline Function *getFunction() const { return func; }
36
37    // keeps inserting at head/tail of block
38    inline void setPosition(BasicBlock *, bool tail);
39    // position advances only if @after is true
40    inline void setPosition(Instruction *, bool after);
41
42    inline BasicBlock *getBB() { return bb; }
43
44    inline void insert(Instruction *);
45    inline void remove(Instruction *i) { assert(i->bb == bb); bb->remove(i); }
46
47    inline LValue *getScratch(int size = 4);
48    inline LValue *getSSA(int size = 4); // scratch value for a single assignment
49
50    inline Instruction *mkOp(operation, DataType, Value *);
51    Instruction *mkOp1(operation, DataType, Value *, Value *);
52    Instruction *mkOp2(operation, DataType, Value *, Value *, Value *);
53    Instruction *mkOp3(operation, DataType, Value *, Value *, Value *, Value *);
54
55    LValue *mkOp1v(operation, DataType, Value *, Value *);
56    LValue *mkOp2v(operation, DataType, Value *, Value *, Value *);
57    LValue *mkOp3v(operation, DataType, Value *, Value *, Value *, Value *);
58
59    LValue *mkLoad(DataType, Symbol *, Value *ptr);
60    Instruction *mkStore(operation, DataType, Symbol *, Value *ptr, Value *val);
61
62    Instruction *mkMov(Value *, Value *, DataType = TYPE_U32);
63    Instruction *mkMovToReg(int id, Value *);
64    Instruction *mkMovFromReg(Value *, int id);
65
66    Instruction *mkInterp(unsigned mode, Value *, int32_t offset, Value *rel);
67    Instruction *mkFetch(Value *, DataType, DataFile, int32_t offset,
68                         Value *attrRel, Value *primRel);
69
70    Instruction *mkCvt(operation, DataType, Value *, DataType, Value *);
71    CmpInstruction *mkCmp(operation, CondCode, DataType,
72                          Value *,
73                          Value *, Value *, Value * = NULL);
74    Instruction *mkTex(operation, TexTarget, uint8_t tic, uint8_t tsc,
75                       Value **def, Value **src);
76    Instruction *mkQuadop(uint8_t qop, Value *, uint8_t l, Value *, Value *);
77
78    FlowInstruction *mkFlow(operation, BasicBlock *target,
79                            CondCode, Value *pred);
80
81    Instruction *mkSelect(Value *pred, Value *dst, Value *trSrc, Value *flSrc);
82
83    void mkClobber(DataFile file, uint32_t regMask, int regUnitLog2);
84
85    ImmediateValue *mkImm(float);
86    ImmediateValue *mkImm(uint32_t);
87    ImmediateValue *mkImm(uint64_t);
88
89    ImmediateValue *mkImm(int i) { return mkImm((uint32_t)i); }
90
91    Value *loadImm(Value *dst, float);
92    Value *loadImm(Value *dst, uint32_t);
93    Value *loadImm(Value *dst, uint64_t);
94
95    Value *loadImm(Value *dst, int i) { return loadImm(dst, (uint32_t)i); }
96
97    class DataArray
98    {
99    public:
100       DataArray();
101       DataArray(BuildUtil *);
102       ~DataArray();
103
104       inline void setParent(BuildUtil *bld) { assert(!up); up = bld; }
105
106       void setup(uint32_t base, int len, int vecDim, int size,
107                  DataFile, int8_t fileIndex = 0);
108
109       inline bool exists(unsigned int i, unsigned int c);
110
111       Value *load(int i, int c, Value *ptr);
112       void store(int i, int c, Value *ptr, Value *value);
113       Value *acquire(int i, int c);
114
115    private:
116       Symbol *mkSymbol(int i, int c, Symbol *base);
117
118    private:
119       Value **values;
120       uint32_t baseAddr;
121       uint32_t arrayLen;
122       Symbol *baseSym;
123
124       uint8_t vecDim;
125       uint8_t eltSize; // in bytes
126
127       DataFile file;
128       bool regOnly;
129
130       BuildUtil *up;
131
132       void init();
133    };
134
135    Symbol *mkSymbol(DataFile file, int8_t fileIndex,
136                     DataType ty, uint32_t baseAddress);
137
138    Symbol *mkSysVal(SVSemantic svName, uint32_t svIndex);
139
140 private:
141    void addImmediate(ImmediateValue *);
142    inline unsigned int u32Hash(uint32_t);
143
144 protected:
145    Program *prog;
146    Function *func;
147    Instruction *pos;
148    BasicBlock *bb;
149    bool tail;
150
151 #define NV50_IR_BUILD_IMM_HT_SIZE 256
152
153    ImmediateValue *imms[NV50_IR_BUILD_IMM_HT_SIZE];
154    unsigned int immCount;
155 };
156
157 unsigned int BuildUtil::u32Hash(uint32_t u)
158 {
159    return (u % 273) % NV50_IR_BUILD_IMM_HT_SIZE;
160 }
161
162 void BuildUtil::setProgram(Program *program)
163 {
164    prog = program;
165 }
166
167 void
168 BuildUtil::setPosition(BasicBlock *block, bool atTail)
169 {
170    bb = block;
171    prog = bb->getProgram();
172    func = bb->getFunction();
173    pos = NULL;
174    tail = atTail;
175 }
176
177 void
178 BuildUtil::setPosition(Instruction *i, bool after)
179 {
180    bb = i->bb;
181    prog = bb->getProgram();
182    func = bb->getFunction();
183    pos = i;
184    tail = after;
185    assert(bb);
186 }
187
188 LValue *
189 BuildUtil::getScratch(int size)
190 {
191    LValue *lval = new_LValue(func, FILE_GPR);
192    if (size != 4)
193       lval->reg.size = size;
194    return lval;
195 }
196
197 LValue *
198 BuildUtil::getSSA(int size)
199 {
200    LValue *lval = new_LValue(func, FILE_GPR);
201    lval->ssa = 1;
202    if (size != 4)
203       lval->reg.size = size;
204    return lval;
205 }
206
207 void BuildUtil::insert(Instruction *i)
208 {
209    if (!pos) {
210       tail ? bb->insertTail(i) : bb->insertHead(i);
211    } else {
212       if (tail) {
213          bb->insertAfter(pos, i);
214          pos = i;
215       } else {
216          bb->insertBefore(pos, i);
217       }
218    }
219 }
220
221 Instruction *
222 BuildUtil::mkOp(operation op, DataType ty, Value *dst)
223 {
224    Instruction *insn = new_Instruction(func, op, ty);
225    insn->setDef(0, dst);
226    insert(insn);
227    if (op == OP_DISCARD || op == OP_EXIT ||
228        op == OP_JOIN ||
229        op == OP_QUADON || op == OP_QUADPOP ||
230        op == OP_EMIT || op == OP_RESTART)
231       insn->fixed = 1;
232    return insn;
233 }
234
235 inline LValue *
236 BuildUtil::mkOp1v(operation op, DataType ty, Value *dst, Value *src)
237 {
238    mkOp1(op, ty, dst, src);
239    return dst->asLValue();
240 }
241
242 inline LValue *
243 BuildUtil::mkOp2v(operation op, DataType ty, Value *dst,
244                   Value *src0, Value *src1)
245 {
246    mkOp2(op, ty, dst, src0, src1);
247    return dst->asLValue();
248 }
249
250 inline LValue *
251 BuildUtil::mkOp3v(operation op, DataType ty, Value *dst,
252                   Value *src0, Value *src1, Value *src2)
253 {
254    mkOp3(op, ty, dst, src0, src1, src2);
255    return dst->asLValue();
256 }
257
258 bool
259 BuildUtil::DataArray::exists(unsigned int i, unsigned int c)
260 {
261    assert(i < arrayLen && c < vecDim);
262    return !regOnly || values[i * vecDim + c];
263 }
264
265 } // namespace nv50_ir
266
267 #endif // __NV50_IR_BUILD_UTIL_H__