1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2011 Christoph Bumiller
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
12bf215546Sopenharmony_ci * all copies or substantial portions of the Software.
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
21bf215546Sopenharmony_ci */
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ci#include "nv50_ir.h"
24bf215546Sopenharmony_ci#include "nv50_ir_build_util.h"
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_cinamespace nv50_ir {
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ciBuildUtil::BuildUtil()
29bf215546Sopenharmony_ci{
30bf215546Sopenharmony_ci   init(NULL);
31bf215546Sopenharmony_ci}
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ciBuildUtil::BuildUtil(Program *prog)
34bf215546Sopenharmony_ci{
35bf215546Sopenharmony_ci   init(prog);
36bf215546Sopenharmony_ci}
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_civoid
39bf215546Sopenharmony_ciBuildUtil::init(Program *prog)
40bf215546Sopenharmony_ci{
41bf215546Sopenharmony_ci   this->prog = prog;
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_ci   func = NULL;
44bf215546Sopenharmony_ci   bb = NULL;
45bf215546Sopenharmony_ci   pos = NULL;
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci   tail = false;
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci   memset(imms, 0, sizeof(imms));
50bf215546Sopenharmony_ci   immCount = 0;
51bf215546Sopenharmony_ci}
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_civoid
54bf215546Sopenharmony_ciBuildUtil::addImmediate(ImmediateValue *imm)
55bf215546Sopenharmony_ci{
56bf215546Sopenharmony_ci   if (immCount > (NV50_IR_BUILD_IMM_HT_SIZE * 3) / 4)
57bf215546Sopenharmony_ci      return;
58bf215546Sopenharmony_ci
59bf215546Sopenharmony_ci   unsigned int pos = u32Hash(imm->reg.data.u32);
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci   while (imms[pos])
62bf215546Sopenharmony_ci      pos = (pos + 1) % NV50_IR_BUILD_IMM_HT_SIZE;
63bf215546Sopenharmony_ci   imms[pos] = imm;
64bf215546Sopenharmony_ci   immCount++;
65bf215546Sopenharmony_ci}
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ciInstruction *
68bf215546Sopenharmony_ciBuildUtil::mkOp1(operation op, DataType ty, Value *dst, Value *src)
69bf215546Sopenharmony_ci{
70bf215546Sopenharmony_ci   Instruction *insn = new_Instruction(func, op, ty);
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci   insn->setDef(0, dst);
73bf215546Sopenharmony_ci   insn->setSrc(0, src);
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci   insert(insn);
76bf215546Sopenharmony_ci   return insn;
77bf215546Sopenharmony_ci}
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ciInstruction *
80bf215546Sopenharmony_ciBuildUtil::mkOp2(operation op, DataType ty, Value *dst,
81bf215546Sopenharmony_ci                 Value *src0, Value *src1)
82bf215546Sopenharmony_ci{
83bf215546Sopenharmony_ci   Instruction *insn = new_Instruction(func, op, ty);
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_ci   insn->setDef(0, dst);
86bf215546Sopenharmony_ci   insn->setSrc(0, src0);
87bf215546Sopenharmony_ci   insn->setSrc(1, src1);
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci   insert(insn);
90bf215546Sopenharmony_ci   return insn;
91bf215546Sopenharmony_ci}
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ciInstruction *
94bf215546Sopenharmony_ciBuildUtil::mkOp3(operation op, DataType ty, Value *dst,
95bf215546Sopenharmony_ci                 Value *src0, Value *src1, Value *src2)
96bf215546Sopenharmony_ci{
97bf215546Sopenharmony_ci   Instruction *insn = new_Instruction(func, op, ty);
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci   insn->setDef(0, dst);
100bf215546Sopenharmony_ci   insn->setSrc(0, src0);
101bf215546Sopenharmony_ci   insn->setSrc(1, src1);
102bf215546Sopenharmony_ci   insn->setSrc(2, src2);
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci   insert(insn);
105bf215546Sopenharmony_ci   return insn;
106bf215546Sopenharmony_ci}
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ciInstruction *
109bf215546Sopenharmony_ciBuildUtil::mkLoad(DataType ty, Value *dst, Symbol *mem, Value *ptr)
110bf215546Sopenharmony_ci{
111bf215546Sopenharmony_ci   Instruction *insn = new_Instruction(func, OP_LOAD, ty);
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci   insn->setDef(0, dst);
114bf215546Sopenharmony_ci   insn->setSrc(0, mem);
115bf215546Sopenharmony_ci   if (ptr)
116bf215546Sopenharmony_ci      insn->setIndirect(0, 0, ptr);
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci   insert(insn);
119bf215546Sopenharmony_ci   return insn;
120bf215546Sopenharmony_ci}
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ciInstruction *
123bf215546Sopenharmony_ciBuildUtil::mkStore(operation op, DataType ty, Symbol *mem, Value *ptr,
124bf215546Sopenharmony_ci                   Value *stVal)
125bf215546Sopenharmony_ci{
126bf215546Sopenharmony_ci   Instruction *insn = new_Instruction(func, op, ty);
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   insn->setSrc(0, mem);
129bf215546Sopenharmony_ci   insn->setSrc(1, stVal);
130bf215546Sopenharmony_ci   if (ptr)
131bf215546Sopenharmony_ci      insn->setIndirect(0, 0, ptr);
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci   insert(insn);
134bf215546Sopenharmony_ci   return insn;
135bf215546Sopenharmony_ci}
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ciInstruction *
138bf215546Sopenharmony_ciBuildUtil::mkFetch(Value *dst, DataType ty, DataFile file, int32_t offset,
139bf215546Sopenharmony_ci                   Value *attrRel, Value *primRel)
140bf215546Sopenharmony_ci{
141bf215546Sopenharmony_ci   Symbol *sym = mkSymbol(file, 0, ty, offset);
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci   Instruction *insn = mkOp1(OP_VFETCH, ty, dst, sym);
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci   insn->setIndirect(0, 0, attrRel);
146bf215546Sopenharmony_ci   insn->setIndirect(0, 1, primRel);
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci   // already inserted
149bf215546Sopenharmony_ci   return insn;
150bf215546Sopenharmony_ci}
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ciInstruction *
153bf215546Sopenharmony_ciBuildUtil::mkInterp(unsigned mode, Value *dst, int32_t offset, Value *rel)
154bf215546Sopenharmony_ci{
155bf215546Sopenharmony_ci   operation op = OP_LINTERP;
156bf215546Sopenharmony_ci   DataType ty = TYPE_F32;
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci   if ((mode & NV50_IR_INTERP_MODE_MASK) == NV50_IR_INTERP_FLAT)
159bf215546Sopenharmony_ci      ty = TYPE_U32;
160bf215546Sopenharmony_ci   else
161bf215546Sopenharmony_ci   if ((mode & NV50_IR_INTERP_MODE_MASK) == NV50_IR_INTERP_PERSPECTIVE)
162bf215546Sopenharmony_ci      op = OP_PINTERP;
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci   Symbol *sym = mkSymbol(FILE_SHADER_INPUT, 0, ty, offset);
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci   Instruction *insn = mkOp1(op, ty, dst, sym);
167bf215546Sopenharmony_ci   insn->setIndirect(0, 0, rel);
168bf215546Sopenharmony_ci   insn->setInterpolate(mode);
169bf215546Sopenharmony_ci   return insn;
170bf215546Sopenharmony_ci}
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ciInstruction *
173bf215546Sopenharmony_ciBuildUtil::mkMov(Value *dst, Value *src, DataType ty)
174bf215546Sopenharmony_ci{
175bf215546Sopenharmony_ci   Instruction *insn = new_Instruction(func, OP_MOV, ty);
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_ci   insn->setDef(0, dst);
178bf215546Sopenharmony_ci   insn->setSrc(0, src);
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci   insert(insn);
181bf215546Sopenharmony_ci   return insn;
182bf215546Sopenharmony_ci}
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ciInstruction *
185bf215546Sopenharmony_ciBuildUtil::mkMovToReg(int id, Value *src)
186bf215546Sopenharmony_ci{
187bf215546Sopenharmony_ci   Instruction *insn = new_Instruction(func, OP_MOV, typeOfSize(src->reg.size));
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci   insn->setDef(0, new_LValue(func, FILE_GPR));
190bf215546Sopenharmony_ci   insn->getDef(0)->reg.data.id = id;
191bf215546Sopenharmony_ci   insn->setSrc(0, src);
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci   insert(insn);
194bf215546Sopenharmony_ci   return insn;
195bf215546Sopenharmony_ci}
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ciInstruction *
198bf215546Sopenharmony_ciBuildUtil::mkMovFromReg(Value *dst, int id)
199bf215546Sopenharmony_ci{
200bf215546Sopenharmony_ci   Instruction *insn = new_Instruction(func, OP_MOV, typeOfSize(dst->reg.size));
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci   insn->setDef(0, dst);
203bf215546Sopenharmony_ci   insn->setSrc(0, new_LValue(func, FILE_GPR));
204bf215546Sopenharmony_ci   insn->getSrc(0)->reg.data.id = id;
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci   insert(insn);
207bf215546Sopenharmony_ci   return insn;
208bf215546Sopenharmony_ci}
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ciInstruction *
211bf215546Sopenharmony_ciBuildUtil::mkCvt(operation op,
212bf215546Sopenharmony_ci                 DataType dstTy, Value *dst, DataType srcTy, Value *src)
213bf215546Sopenharmony_ci{
214bf215546Sopenharmony_ci   Instruction *insn = new_Instruction(func, op, dstTy);
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci   insn->setType(dstTy, srcTy);
217bf215546Sopenharmony_ci   insn->setDef(0, dst);
218bf215546Sopenharmony_ci   insn->setSrc(0, src);
219bf215546Sopenharmony_ci
220bf215546Sopenharmony_ci   insert(insn);
221bf215546Sopenharmony_ci   return insn;
222bf215546Sopenharmony_ci}
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ciCmpInstruction *
225bf215546Sopenharmony_ciBuildUtil::mkCmp(operation op, CondCode cc, DataType dstTy, Value *dst,
226bf215546Sopenharmony_ci                 DataType srcTy, Value *src0, Value *src1, Value *src2)
227bf215546Sopenharmony_ci{
228bf215546Sopenharmony_ci   CmpInstruction *insn = new_CmpInstruction(func, op);
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci   insn->setType((dst->reg.file == FILE_PREDICATE ||
231bf215546Sopenharmony_ci                  dst->reg.file == FILE_FLAGS) ? TYPE_U8 : dstTy, srcTy);
232bf215546Sopenharmony_ci   insn->setCondition(cc);
233bf215546Sopenharmony_ci   insn->setDef(0, dst);
234bf215546Sopenharmony_ci   insn->setSrc(0, src0);
235bf215546Sopenharmony_ci   insn->setSrc(1, src1);
236bf215546Sopenharmony_ci   if (src2)
237bf215546Sopenharmony_ci      insn->setSrc(2, src2);
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci   if (dst->reg.file == FILE_FLAGS)
240bf215546Sopenharmony_ci      insn->flagsDef = 0;
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_ci   insert(insn);
243bf215546Sopenharmony_ci   return insn;
244bf215546Sopenharmony_ci}
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ciTexInstruction *
247bf215546Sopenharmony_ciBuildUtil::mkTex(operation op, TexTarget targ,
248bf215546Sopenharmony_ci                 uint16_t tic, uint16_t tsc,
249bf215546Sopenharmony_ci                 const std::vector<Value *> &def,
250bf215546Sopenharmony_ci                 const std::vector<Value *> &src)
251bf215546Sopenharmony_ci{
252bf215546Sopenharmony_ci   TexInstruction *tex = new_TexInstruction(func, op);
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci   for (size_t d = 0; d < def.size() && def[d]; ++d)
255bf215546Sopenharmony_ci      tex->setDef(d, def[d]);
256bf215546Sopenharmony_ci   for (size_t s = 0; s < src.size() && src[s]; ++s)
257bf215546Sopenharmony_ci      tex->setSrc(s, src[s]);
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci   tex->setTexture(targ, tic, tsc);
260bf215546Sopenharmony_ci
261bf215546Sopenharmony_ci   insert(tex);
262bf215546Sopenharmony_ci   return tex;
263bf215546Sopenharmony_ci}
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_ciInstruction *
266bf215546Sopenharmony_ciBuildUtil::mkQuadop(uint8_t q, Value *def, uint8_t l, Value *src0, Value *src1)
267bf215546Sopenharmony_ci{
268bf215546Sopenharmony_ci   Instruction *quadop = mkOp2(OP_QUADOP, TYPE_F32, def, src0, src1);
269bf215546Sopenharmony_ci   quadop->subOp = q;
270bf215546Sopenharmony_ci   quadop->lanes = l;
271bf215546Sopenharmony_ci   return quadop;
272bf215546Sopenharmony_ci}
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ciInstruction *
275bf215546Sopenharmony_ciBuildUtil::mkSelect(Value *pred, Value *dst, Value *trSrc, Value *flSrc)
276bf215546Sopenharmony_ci{
277bf215546Sopenharmony_ci   LValue *def0 = getSSA();
278bf215546Sopenharmony_ci   LValue *def1 = getSSA();
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci   mkMov(def0, trSrc)->setPredicate(CC_P, pred);
281bf215546Sopenharmony_ci   mkMov(def1, flSrc)->setPredicate(CC_NOT_P, pred);
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci   return mkOp2(OP_UNION, typeOfSize(dst->reg.size), dst, def0, def1);
284bf215546Sopenharmony_ci}
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_ciInstruction *
287bf215546Sopenharmony_ciBuildUtil::mkSplit(Value *h[2], uint8_t halfSize, Value *val)
288bf215546Sopenharmony_ci{
289bf215546Sopenharmony_ci   Instruction *insn = NULL;
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci   const DataType fTy = typeOfSize(halfSize * 2);
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci   if (val->reg.file == FILE_IMMEDIATE)
294bf215546Sopenharmony_ci      val = mkMov(getSSA(halfSize * 2), val, fTy)->getDef(0);
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci   if (isMemoryFile(val->reg.file)) {
297bf215546Sopenharmony_ci      h[0] = cloneShallow(getFunction(), val);
298bf215546Sopenharmony_ci      h[1] = cloneShallow(getFunction(), val);
299bf215546Sopenharmony_ci      h[0]->reg.size = halfSize;
300bf215546Sopenharmony_ci      h[1]->reg.size = halfSize;
301bf215546Sopenharmony_ci      h[1]->reg.data.offset += halfSize;
302bf215546Sopenharmony_ci   } else {
303bf215546Sopenharmony_ci      h[0] = getSSA(halfSize, val->reg.file);
304bf215546Sopenharmony_ci      h[1] = getSSA(halfSize, val->reg.file);
305bf215546Sopenharmony_ci      insn = mkOp1(OP_SPLIT, fTy, h[0], val);
306bf215546Sopenharmony_ci      insn->setDef(1, h[1]);
307bf215546Sopenharmony_ci   }
308bf215546Sopenharmony_ci   return insn;
309bf215546Sopenharmony_ci}
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ciFlowInstruction *
312bf215546Sopenharmony_ciBuildUtil::mkFlow(operation op, void *targ, CondCode cc, Value *pred)
313bf215546Sopenharmony_ci{
314bf215546Sopenharmony_ci   FlowInstruction *insn = new_FlowInstruction(func, op, targ);
315bf215546Sopenharmony_ci
316bf215546Sopenharmony_ci   if (pred)
317bf215546Sopenharmony_ci      insn->setPredicate(cc, pred);
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci   insert(insn);
320bf215546Sopenharmony_ci   return insn;
321bf215546Sopenharmony_ci}
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_civoid
324bf215546Sopenharmony_ciBuildUtil::mkClobber(DataFile f, uint32_t rMask, int unit)
325bf215546Sopenharmony_ci{
326bf215546Sopenharmony_ci   static const uint16_t baseSize2[16] =
327bf215546Sopenharmony_ci   {
328bf215546Sopenharmony_ci      0x0000, 0x0010, 0x0011, 0x0020, 0x0012, 0x1210, 0x1211, 0x1220,
329bf215546Sopenharmony_ci      0x0013, 0x1310, 0x1311, 0x1320, 0x0022, 0x2210, 0x2211, 0x0040,
330bf215546Sopenharmony_ci   };
331bf215546Sopenharmony_ci
332bf215546Sopenharmony_ci   int base = 0;
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci   for (; rMask; rMask >>= 4, base += 4) {
335bf215546Sopenharmony_ci      const uint32_t mask = rMask & 0xf;
336bf215546Sopenharmony_ci      if (!mask)
337bf215546Sopenharmony_ci         continue;
338bf215546Sopenharmony_ci      int base1 = (baseSize2[mask] >>  0) & 0xf;
339bf215546Sopenharmony_ci      int size1 = (baseSize2[mask] >>  4) & 0xf;
340bf215546Sopenharmony_ci      int base2 = (baseSize2[mask] >>  8) & 0xf;
341bf215546Sopenharmony_ci      int size2 = (baseSize2[mask] >> 12) & 0xf;
342bf215546Sopenharmony_ci      Instruction *insn = mkOp(OP_NOP, TYPE_NONE, NULL);
343bf215546Sopenharmony_ci      if (true) { // size1 can't be 0
344bf215546Sopenharmony_ci         LValue *reg = new_LValue(func, f);
345bf215546Sopenharmony_ci         reg->reg.size = size1 << unit;
346bf215546Sopenharmony_ci         reg->reg.data.id = base + base1;
347bf215546Sopenharmony_ci         insn->setDef(0, reg);
348bf215546Sopenharmony_ci      }
349bf215546Sopenharmony_ci      if (size2) {
350bf215546Sopenharmony_ci         LValue *reg = new_LValue(func, f);
351bf215546Sopenharmony_ci         reg->reg.size = size2 << unit;
352bf215546Sopenharmony_ci         reg->reg.data.id = base + base2;
353bf215546Sopenharmony_ci         insn->setDef(1, reg);
354bf215546Sopenharmony_ci      }
355bf215546Sopenharmony_ci   }
356bf215546Sopenharmony_ci}
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ciImmediateValue *
359bf215546Sopenharmony_ciBuildUtil::mkImm(uint16_t u)
360bf215546Sopenharmony_ci{
361bf215546Sopenharmony_ci   ImmediateValue *imm = new_ImmediateValue(prog, (uint32_t)0);
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_ci   imm->reg.size = 2;
364bf215546Sopenharmony_ci   imm->reg.type = TYPE_U16;
365bf215546Sopenharmony_ci   imm->reg.data.u32 = u;
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci   return imm;
368bf215546Sopenharmony_ci}
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ciImmediateValue *
371bf215546Sopenharmony_ciBuildUtil::mkImm(uint32_t u)
372bf215546Sopenharmony_ci{
373bf215546Sopenharmony_ci   unsigned int pos = u32Hash(u);
374bf215546Sopenharmony_ci
375bf215546Sopenharmony_ci   while (imms[pos] && imms[pos]->reg.data.u32 != u)
376bf215546Sopenharmony_ci      pos = (pos + 1) % NV50_IR_BUILD_IMM_HT_SIZE;
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci   ImmediateValue *imm = imms[pos];
379bf215546Sopenharmony_ci   if (!imm) {
380bf215546Sopenharmony_ci      imm = new_ImmediateValue(prog, u);
381bf215546Sopenharmony_ci      addImmediate(imm);
382bf215546Sopenharmony_ci   }
383bf215546Sopenharmony_ci   return imm;
384bf215546Sopenharmony_ci}
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_ciImmediateValue *
387bf215546Sopenharmony_ciBuildUtil::mkImm(uint64_t u)
388bf215546Sopenharmony_ci{
389bf215546Sopenharmony_ci   ImmediateValue *imm = new_ImmediateValue(prog, (uint32_t)0);
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci   imm->reg.size = 8;
392bf215546Sopenharmony_ci   imm->reg.type = TYPE_U64;
393bf215546Sopenharmony_ci   imm->reg.data.u64 = u;
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci   return imm;
396bf215546Sopenharmony_ci}
397bf215546Sopenharmony_ci
398bf215546Sopenharmony_ciImmediateValue *
399bf215546Sopenharmony_ciBuildUtil::mkImm(float f)
400bf215546Sopenharmony_ci{
401bf215546Sopenharmony_ci   union {
402bf215546Sopenharmony_ci      float f32;
403bf215546Sopenharmony_ci      uint32_t u32;
404bf215546Sopenharmony_ci   } u;
405bf215546Sopenharmony_ci   u.f32 = f;
406bf215546Sopenharmony_ci   return mkImm(u.u32);
407bf215546Sopenharmony_ci}
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ciImmediateValue *
410bf215546Sopenharmony_ciBuildUtil::mkImm(double d)
411bf215546Sopenharmony_ci{
412bf215546Sopenharmony_ci   return new_ImmediateValue(prog, d);
413bf215546Sopenharmony_ci}
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_ciValue *
416bf215546Sopenharmony_ciBuildUtil::loadImm(Value *dst, float f)
417bf215546Sopenharmony_ci{
418bf215546Sopenharmony_ci   return mkOp1v(OP_MOV, TYPE_F32, dst ? dst : getScratch(), mkImm(f));
419bf215546Sopenharmony_ci}
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_ciValue *
422bf215546Sopenharmony_ciBuildUtil::loadImm(Value *dst, double d)
423bf215546Sopenharmony_ci{
424bf215546Sopenharmony_ci   return mkOp1v(OP_MOV, TYPE_F64, dst ? dst : getScratch(8), mkImm(d));
425bf215546Sopenharmony_ci}
426bf215546Sopenharmony_ci
427bf215546Sopenharmony_ciValue *
428bf215546Sopenharmony_ciBuildUtil::loadImm(Value *dst, uint16_t u)
429bf215546Sopenharmony_ci{
430bf215546Sopenharmony_ci   return mkOp1v(OP_MOV, TYPE_U16, dst ? dst : getScratch(2), mkImm(u));
431bf215546Sopenharmony_ci}
432bf215546Sopenharmony_ci
433bf215546Sopenharmony_ciValue *
434bf215546Sopenharmony_ciBuildUtil::loadImm(Value *dst, uint32_t u)
435bf215546Sopenharmony_ci{
436bf215546Sopenharmony_ci   return mkOp1v(OP_MOV, TYPE_U32, dst ? dst : getScratch(), mkImm(u));
437bf215546Sopenharmony_ci}
438bf215546Sopenharmony_ci
439bf215546Sopenharmony_ciValue *
440bf215546Sopenharmony_ciBuildUtil::loadImm(Value *dst, uint64_t u)
441bf215546Sopenharmony_ci{
442bf215546Sopenharmony_ci   return mkOp1v(OP_MOV, TYPE_U64, dst ? dst : getScratch(8), mkImm(u));
443bf215546Sopenharmony_ci}
444bf215546Sopenharmony_ci
445bf215546Sopenharmony_ciSymbol *
446bf215546Sopenharmony_ciBuildUtil::mkSymbol(DataFile file, int8_t fileIndex, DataType ty,
447bf215546Sopenharmony_ci                    uint32_t baseAddr)
448bf215546Sopenharmony_ci{
449bf215546Sopenharmony_ci   Symbol *sym = new_Symbol(prog, file, fileIndex);
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci   sym->setOffset(baseAddr);
452bf215546Sopenharmony_ci   sym->reg.type = ty;
453bf215546Sopenharmony_ci   sym->reg.size = typeSizeof(ty);
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_ci   return sym;
456bf215546Sopenharmony_ci}
457bf215546Sopenharmony_ci
458bf215546Sopenharmony_ciSymbol *
459bf215546Sopenharmony_ciBuildUtil::mkSysVal(SVSemantic svName, uint32_t svIndex)
460bf215546Sopenharmony_ci{
461bf215546Sopenharmony_ci   Symbol *sym = new_Symbol(prog, FILE_SYSTEM_VALUE, 0);
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_ci   assert(svIndex < 4 || svName == SV_CLIP_DISTANCE);
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci   switch (svName) {
466bf215546Sopenharmony_ci   case SV_POSITION:
467bf215546Sopenharmony_ci   case SV_FACE:
468bf215546Sopenharmony_ci   case SV_YDIR:
469bf215546Sopenharmony_ci   case SV_POINT_SIZE:
470bf215546Sopenharmony_ci   case SV_POINT_COORD:
471bf215546Sopenharmony_ci   case SV_CLIP_DISTANCE:
472bf215546Sopenharmony_ci   case SV_TESS_OUTER:
473bf215546Sopenharmony_ci   case SV_TESS_INNER:
474bf215546Sopenharmony_ci   case SV_TESS_COORD:
475bf215546Sopenharmony_ci      sym->reg.type = TYPE_F32;
476bf215546Sopenharmony_ci      break;
477bf215546Sopenharmony_ci   default:
478bf215546Sopenharmony_ci      sym->reg.type = TYPE_U32;
479bf215546Sopenharmony_ci      break;
480bf215546Sopenharmony_ci   }
481bf215546Sopenharmony_ci   sym->reg.size = typeSizeof(sym->reg.type);
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci   sym->reg.data.sv.sv = svName;
484bf215546Sopenharmony_ci   sym->reg.data.sv.index = svIndex;
485bf215546Sopenharmony_ci
486bf215546Sopenharmony_ci   return sym;
487bf215546Sopenharmony_ci}
488bf215546Sopenharmony_ci
489bf215546Sopenharmony_ciSymbol *
490bf215546Sopenharmony_ciBuildUtil::mkTSVal(TSSemantic tsName)
491bf215546Sopenharmony_ci{
492bf215546Sopenharmony_ci   Symbol *sym = new_Symbol(prog, FILE_THREAD_STATE, 0);
493bf215546Sopenharmony_ci   sym->reg.type = TYPE_U32;
494bf215546Sopenharmony_ci   sym->reg.size = typeSizeof(sym->reg.type);
495bf215546Sopenharmony_ci   sym->reg.data.ts = tsName;
496bf215546Sopenharmony_ci   return sym;
497bf215546Sopenharmony_ci}
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_civoid
500bf215546Sopenharmony_ciBuildUtil::DataArray::setup(unsigned array, unsigned arrayIdx,
501bf215546Sopenharmony_ci                            uint32_t base, int len, int vecDim, int eltSize,
502bf215546Sopenharmony_ci                            DataFile file, int8_t fileIdx)
503bf215546Sopenharmony_ci{
504bf215546Sopenharmony_ci   this->array = array;
505bf215546Sopenharmony_ci   this->arrayIdx = arrayIdx;
506bf215546Sopenharmony_ci   this->baseAddr = base;
507bf215546Sopenharmony_ci   this->arrayLen = len;
508bf215546Sopenharmony_ci   this->vecDim = vecDim;
509bf215546Sopenharmony_ci   this->eltSize = eltSize;
510bf215546Sopenharmony_ci   this->file = file;
511bf215546Sopenharmony_ci   this->regOnly = !isMemoryFile(file);
512bf215546Sopenharmony_ci
513bf215546Sopenharmony_ci   if (!regOnly) {
514bf215546Sopenharmony_ci      baseSym = new_Symbol(up->getProgram(), file, fileIdx);
515bf215546Sopenharmony_ci      baseSym->setOffset(baseAddr);
516bf215546Sopenharmony_ci      baseSym->reg.size = eltSize;
517bf215546Sopenharmony_ci   } else {
518bf215546Sopenharmony_ci      baseSym = NULL;
519bf215546Sopenharmony_ci   }
520bf215546Sopenharmony_ci}
521bf215546Sopenharmony_ci
522bf215546Sopenharmony_ciValue *
523bf215546Sopenharmony_ciBuildUtil::DataArray::acquire(ValueMap &m, int i, int c)
524bf215546Sopenharmony_ci{
525bf215546Sopenharmony_ci   if (regOnly) {
526bf215546Sopenharmony_ci      Value *v = lookup(m, i, c);
527bf215546Sopenharmony_ci      if (!v)
528bf215546Sopenharmony_ci         v = insert(m, i, c, new_LValue(up->getFunction(), file));
529bf215546Sopenharmony_ci
530bf215546Sopenharmony_ci      return v;
531bf215546Sopenharmony_ci   } else {
532bf215546Sopenharmony_ci      return up->getScratch(eltSize);
533bf215546Sopenharmony_ci   }
534bf215546Sopenharmony_ci}
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ciValue *
537bf215546Sopenharmony_ciBuildUtil::DataArray::load(ValueMap &m, int i, int c, Value *ptr)
538bf215546Sopenharmony_ci{
539bf215546Sopenharmony_ci   if (regOnly) {
540bf215546Sopenharmony_ci      Value *v = lookup(m, i, c);
541bf215546Sopenharmony_ci      if (!v)
542bf215546Sopenharmony_ci         v = insert(m, i, c, new_LValue(up->getFunction(), file));
543bf215546Sopenharmony_ci
544bf215546Sopenharmony_ci      return v;
545bf215546Sopenharmony_ci   } else {
546bf215546Sopenharmony_ci      Value *sym = lookup(m, i, c);
547bf215546Sopenharmony_ci      if (!sym)
548bf215546Sopenharmony_ci         sym = insert(m, i, c, mkSymbol(i, c));
549bf215546Sopenharmony_ci
550bf215546Sopenharmony_ci      return up->mkLoadv(typeOfSize(eltSize), static_cast<Symbol *>(sym), ptr);
551bf215546Sopenharmony_ci   }
552bf215546Sopenharmony_ci}
553bf215546Sopenharmony_ci
554bf215546Sopenharmony_civoid
555bf215546Sopenharmony_ciBuildUtil::DataArray::store(ValueMap &m, int i, int c, Value *ptr, Value *value)
556bf215546Sopenharmony_ci{
557bf215546Sopenharmony_ci   if (regOnly) {
558bf215546Sopenharmony_ci      assert(!ptr);
559bf215546Sopenharmony_ci      if (!lookup(m, i, c))
560bf215546Sopenharmony_ci         insert(m, i, c, value);
561bf215546Sopenharmony_ci
562bf215546Sopenharmony_ci      assert(lookup(m, i, c) == value);
563bf215546Sopenharmony_ci   } else {
564bf215546Sopenharmony_ci      Value *sym = lookup(m, i, c);
565bf215546Sopenharmony_ci      if (!sym)
566bf215546Sopenharmony_ci         sym = insert(m, i, c, mkSymbol(i, c));
567bf215546Sopenharmony_ci
568bf215546Sopenharmony_ci      const DataType stTy = typeOfSize(value->reg.size);
569bf215546Sopenharmony_ci
570bf215546Sopenharmony_ci      up->mkStore(OP_STORE, stTy, static_cast<Symbol *>(sym), ptr, value);
571bf215546Sopenharmony_ci   }
572bf215546Sopenharmony_ci}
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_ciSymbol *
575bf215546Sopenharmony_ciBuildUtil::DataArray::mkSymbol(int i, int c)
576bf215546Sopenharmony_ci{
577bf215546Sopenharmony_ci   const unsigned int idx = i * vecDim + c;
578bf215546Sopenharmony_ci   Symbol *sym = new_Symbol(up->getProgram(), file, 0);
579bf215546Sopenharmony_ci
580bf215546Sopenharmony_ci   assert(baseSym || (idx < arrayLen && c < vecDim));
581bf215546Sopenharmony_ci
582bf215546Sopenharmony_ci   sym->reg.size = eltSize;
583bf215546Sopenharmony_ci   sym->reg.type = typeOfSize(eltSize);
584bf215546Sopenharmony_ci   sym->setAddress(baseSym, baseAddr + idx * eltSize);
585bf215546Sopenharmony_ci   return sym;
586bf215546Sopenharmony_ci}
587bf215546Sopenharmony_ci
588bf215546Sopenharmony_ci
589bf215546Sopenharmony_ciInstruction *
590bf215546Sopenharmony_ciBuildUtil::split64BitOpPostRA(Function *fn, Instruction *i,
591bf215546Sopenharmony_ci                              Value *zero,
592bf215546Sopenharmony_ci                              Value *carry)
593bf215546Sopenharmony_ci{
594bf215546Sopenharmony_ci   DataType hTy;
595bf215546Sopenharmony_ci   int srcNr;
596bf215546Sopenharmony_ci
597bf215546Sopenharmony_ci   switch (i->dType) {
598bf215546Sopenharmony_ci   case TYPE_U64: hTy = TYPE_U32; break;
599bf215546Sopenharmony_ci   case TYPE_S64: hTy = TYPE_S32; break;
600bf215546Sopenharmony_ci   case TYPE_F64:
601bf215546Sopenharmony_ci      if (i->op == OP_MOV) {
602bf215546Sopenharmony_ci         hTy = TYPE_U32;
603bf215546Sopenharmony_ci         break;
604bf215546Sopenharmony_ci      }
605bf215546Sopenharmony_ci      FALLTHROUGH;
606bf215546Sopenharmony_ci   default:
607bf215546Sopenharmony_ci      return NULL;
608bf215546Sopenharmony_ci   }
609bf215546Sopenharmony_ci
610bf215546Sopenharmony_ci   switch (i->op) {
611bf215546Sopenharmony_ci   case OP_MOV: srcNr = 1; break;
612bf215546Sopenharmony_ci   case OP_ADD:
613bf215546Sopenharmony_ci   case OP_SUB:
614bf215546Sopenharmony_ci      if (!carry)
615bf215546Sopenharmony_ci         return NULL;
616bf215546Sopenharmony_ci      srcNr = 2;
617bf215546Sopenharmony_ci      break;
618bf215546Sopenharmony_ci   case OP_SELP: srcNr = 3; break;
619bf215546Sopenharmony_ci   default:
620bf215546Sopenharmony_ci      // TODO when needed
621bf215546Sopenharmony_ci      return NULL;
622bf215546Sopenharmony_ci   }
623bf215546Sopenharmony_ci
624bf215546Sopenharmony_ci   i->setType(hTy);
625bf215546Sopenharmony_ci   i->setDef(0, cloneShallow(fn, i->getDef(0)));
626bf215546Sopenharmony_ci   i->getDef(0)->reg.size = 4;
627bf215546Sopenharmony_ci   Instruction *lo = i;
628bf215546Sopenharmony_ci   Instruction *hi = cloneForward(fn, i);
629bf215546Sopenharmony_ci   lo->bb->insertAfter(lo, hi);
630bf215546Sopenharmony_ci
631bf215546Sopenharmony_ci   hi->getDef(0)->reg.data.id++;
632bf215546Sopenharmony_ci
633bf215546Sopenharmony_ci   for (int s = 0; s < srcNr; ++s) {
634bf215546Sopenharmony_ci      if (lo->getSrc(s)->reg.size < 8) {
635bf215546Sopenharmony_ci         if (s == 2)
636bf215546Sopenharmony_ci            hi->setSrc(s, lo->getSrc(s));
637bf215546Sopenharmony_ci         else
638bf215546Sopenharmony_ci            hi->setSrc(s, zero);
639bf215546Sopenharmony_ci      } else {
640bf215546Sopenharmony_ci         if (lo->getSrc(s)->refCount() > 1)
641bf215546Sopenharmony_ci            lo->setSrc(s, cloneShallow(fn, lo->getSrc(s)));
642bf215546Sopenharmony_ci         lo->getSrc(s)->reg.size /= 2;
643bf215546Sopenharmony_ci         hi->setSrc(s, cloneShallow(fn, lo->getSrc(s)));
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_ci         switch (hi->src(s).getFile()) {
646bf215546Sopenharmony_ci         case FILE_IMMEDIATE:
647bf215546Sopenharmony_ci            hi->getSrc(s)->reg.data.u64 >>= 32;
648bf215546Sopenharmony_ci            break;
649bf215546Sopenharmony_ci         case FILE_MEMORY_CONST:
650bf215546Sopenharmony_ci         case FILE_MEMORY_SHARED:
651bf215546Sopenharmony_ci         case FILE_SHADER_INPUT:
652bf215546Sopenharmony_ci         case FILE_SHADER_OUTPUT:
653bf215546Sopenharmony_ci            hi->getSrc(s)->reg.data.offset += 4;
654bf215546Sopenharmony_ci            break;
655bf215546Sopenharmony_ci         default:
656bf215546Sopenharmony_ci            assert(hi->src(s).getFile() == FILE_GPR);
657bf215546Sopenharmony_ci            hi->getSrc(s)->reg.data.id++;
658bf215546Sopenharmony_ci            break;
659bf215546Sopenharmony_ci         }
660bf215546Sopenharmony_ci      }
661bf215546Sopenharmony_ci   }
662bf215546Sopenharmony_ci   if (srcNr == 2) {
663bf215546Sopenharmony_ci      lo->setFlagsDef(1, carry);
664bf215546Sopenharmony_ci      hi->setFlagsSrc(hi->srcCount(), carry);
665bf215546Sopenharmony_ci   }
666bf215546Sopenharmony_ci   return hi;
667bf215546Sopenharmony_ci}
668bf215546Sopenharmony_ci
669bf215546Sopenharmony_ci} // namespace nv50_ir
670