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