nv50_ir_lowering_nvc0.cpp revision b8b3af2932039c6105d61f6922157a250ed8b79a
1d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller/*
2d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller * Copyright 2011 Christoph Bumiller
3d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller *
4d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller * Permission is hereby granted, free of charge, to any person obtaining a
5d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller * copy of this software and associated documentation files (the "Software"),
6d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller * to deal in the Software without restriction, including without limitation
7d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller * and/or sell copies of the Software, and to permit persons to whom the
9d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller * Software is furnished to do so, subject to the following conditions:
10d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller *
11d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller * The above copyright notice and this permission notice shall be included in
12d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller * all copies or substantial portions of the Software.
13d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller *
14d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
173d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
183d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
193d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
203d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * OTHER DEALINGS IN THE SOFTWARE.
21d2d19ea51fa3575a8d014a69a9b835c335728817Christoph Bumiller */
2257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
235eb7ff1175a644ffe3b0f1a75cb235400355f9fbJohannes Obermayr#include "codegen/nv50_ir.h"
245eb7ff1175a644ffe3b0f1a75cb235400355f9fbJohannes Obermayr#include "codegen/nv50_ir_build_util.h"
2557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
265eb7ff1175a644ffe3b0f1a75cb235400355f9fbJohannes Obermayr#include "codegen/nv50_ir_target_nvc0.h"
273723ff52237194995d4f9f9fb5d66fb80110889eBen Skeggs#include "codegen/nv50_ir_lowering_nvc0.h"
2857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
2900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller#include <limits>
3000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller
3157594065c30feec9376be9b2132659f7d87362eeChristoph Bumillernamespace nv50_ir {
3257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
3357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller#define QOP_ADD  0
3457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller#define QOP_SUBR 1
3557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller#define QOP_SUB  2
3657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller#define QOP_MOV2 3
3757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
38717f55d79d9709a31e0f85a87f076ac13446701dChristoph Bumiller//             UL UR LL LR
3957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller#define QUADOP(q, r, s, t)                      \
40717f55d79d9709a31e0f85a87f076ac13446701dChristoph Bumiller   ((QOP_##q << 6) | (QOP_##r << 4) |           \
41717f55d79d9709a31e0f85a87f076ac13446701dChristoph Bumiller    (QOP_##s << 2) | (QOP_##t << 0))
4257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
4357594065c30feec9376be9b2132659f7d87362eeChristoph Bumillervoid
4457594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LegalizeSSA::handleDIV(Instruction *i)
4557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
4657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   FlowInstruction *call;
4757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   int builtin;
4857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Value *def[2];
4957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
5057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   bld.setPosition(i, false);
5157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   def[0] = bld.mkMovToReg(0, i->getSrc(0))->getDef(0);
5257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   def[1] = bld.mkMovToReg(1, i->getSrc(1))->getDef(0);
5357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   switch (i->dType) {
5457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case TYPE_U32: builtin = NVC0_BUILTIN_DIV_U32; break;
5557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case TYPE_S32: builtin = NVC0_BUILTIN_DIV_S32; break;
5657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   default:
5757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return;
5857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
5957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   call = bld.mkFlow(OP_CALL, NULL, CC_ALWAYS, NULL);
6057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   bld.mkMov(i->getDef(0), def[(i->op == OP_DIV) ? 0 : 1]);
6157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   bld.mkClobber(FILE_GPR, (i->op == OP_DIV) ? 0xe : 0xd, 2);
6257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   bld.mkClobber(FILE_PREDICATE, (i->dType == TYPE_S32) ? 0xf : 0x3, 0);
6357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
6457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   call->fixed = 1;
6557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   call->absolute = call->builtin = 1;
6657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   call->target.builtin = builtin;
6757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   delete_Instruction(prog, i);
6857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
6957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
7057594065c30feec9376be9b2132659f7d87362eeChristoph Bumillervoid
7157594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LegalizeSSA::handleRCPRSQ(Instruction *i)
7257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
73b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   assert(i->dType == TYPE_F64);
74b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   // There are instructions that will compute the high 32 bits of the 64-bit
75b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   // float. We will just stick 0 in the bottom 32 bits.
76b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin
77b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   bld.setPosition(i, false);
78b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin
79b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   // 1. Take the source and it up.
80b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   Value *src[2], *dst[2], *def = i->getDef(0);
81b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   bld.mkSplit(src, 4, i->getSrc(0));
82b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin
83b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   // 2. We don't care about the low 32 bits of the destination. Stick a 0 in.
84b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   dst[0] = bld.loadImm(NULL, 0);
85b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   dst[1] = bld.getSSA();
86b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin
87b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   // 3. The new version of the instruction takes the high 32 bits of the
88b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   // source and outputs the high 32 bits of the destination.
89b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   i->setSrc(0, src[1]);
90b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   i->setDef(0, dst[1]);
91b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   i->setType(TYPE_F32);
92b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   i->subOp = NV50_IR_SUBOP_RCPRSQ_64H;
93b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin
94b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   // 4. Recombine the two dst pieces back into the original destination.
95b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   bld.setPosition(i, true);
96b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   bld.mkOp2(OP_MERGE, TYPE_U64, def, dst[0], dst[1]);
9757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
9857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
996fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkinvoid
1006fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia MirkinNVC0LegalizeSSA::handleFTZ(Instruction *i)
1016fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin{
1026fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin   // Only want to flush float inputs
103d1eea18a595a468dbc2267a8d14197a3b1a5a4b6Ilia Mirkin   assert(i->sType == TYPE_F32);
1046fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin
1056fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin   // If we're already flushing denorms (and NaN's) to zero, no need for this.
1066fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin   if (i->dnz)
1076fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin      return;
1086fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin
1096fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin   // Only certain classes of operations can flush
1106fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin   OpClass cls = prog->getTarget()->getOpClass(i->op);
1116fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin   if (cls != OPCLASS_ARITH && cls != OPCLASS_COMPARE &&
1126fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin       cls != OPCLASS_CONVERT)
1136fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin      return;
1146fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin
1156fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin   i->ftz = true;
1166fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin}
1176fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin
11857594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
11957594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LegalizeSSA::visit(Function *fn)
12057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
12157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   bld.setProgram(fn->getProgram());
12257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
12357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
12457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
12557594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
12657594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LegalizeSSA::visit(BasicBlock *bb)
12757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
12857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Instruction *next;
12957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   for (Instruction *i = bb->getEntry(); i; i = next) {
13057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      next = i->next;
131d1eea18a595a468dbc2267a8d14197a3b1a5a4b6Ilia Mirkin      if (i->sType == TYPE_F32) {
1326fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin         if (prog->getType() != Program::TYPE_COMPUTE)
1336fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin            handleFTZ(i);
13457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         continue;
1356fe0d4f0354418c6e68dd352996e9891ddd4dfd6Ilia Mirkin      }
13657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      switch (i->op) {
13757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      case OP_DIV:
13857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      case OP_MOD:
13957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         handleDIV(i);
14057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         break;
14157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      case OP_RCP:
14257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      case OP_RSQ:
14357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         if (i->dType == TYPE_F64)
14457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller            handleRCPRSQ(i);
14557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         break;
14657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      default:
14757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         break;
14857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      }
14957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
15057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
15157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
15257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
153e44089b2f79aa2dcaacf348911433d1e21235c0cChristoph BumillerNVC0LegalizePostRA::NVC0LegalizePostRA(const Program *prog)
15474be77a99e1196d07ebd941aee24313f7aa123c9Vinson Lee   : rZero(NULL),
15574be77a99e1196d07ebd941aee24313f7aa123c9Vinson Lee     carry(NULL),
15674be77a99e1196d07ebd941aee24313f7aa123c9Vinson Lee     needTexBar(prog->getTarget()->getChipset() >= 0xe0)
157e44089b2f79aa2dcaacf348911433d1e21235c0cChristoph Bumiller{
158e44089b2f79aa2dcaacf348911433d1e21235c0cChristoph Bumiller}
159e44089b2f79aa2dcaacf348911433d1e21235c0cChristoph Bumiller
16057594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
16100fe442253744c4c4e7e68da44d6983da053968bChristoph BumillerNVC0LegalizePostRA::insnDominatedBy(const Instruction *later,
16200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller                                    const Instruction *early) const
16300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller{
16400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   if (early->bb == later->bb)
16500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      return early->serial < later->serial;
16600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   return later->bb->dominatedBy(early->bb);
16700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller}
16800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller
16900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumillervoid
17040c224a573f2b763046001e622aafca90f68c693Christoph BumillerNVC0LegalizePostRA::addTexUse(std::list<TexUse> &uses,
171a2af42c1d2dc91f4c31e25ff9fff15a89a9b6eadIlia Mirkin                              Instruction *usei, const Instruction *texi)
17240c224a573f2b763046001e622aafca90f68c693Christoph Bumiller{
17340c224a573f2b763046001e622aafca90f68c693Christoph Bumiller   bool add = true;
17440c224a573f2b763046001e622aafca90f68c693Christoph Bumiller   for (std::list<TexUse>::iterator it = uses.begin();
17540c224a573f2b763046001e622aafca90f68c693Christoph Bumiller        it != uses.end();) {
17640c224a573f2b763046001e622aafca90f68c693Christoph Bumiller      if (insnDominatedBy(usei, it->insn)) {
17740c224a573f2b763046001e622aafca90f68c693Christoph Bumiller         add = false;
17840c224a573f2b763046001e622aafca90f68c693Christoph Bumiller         break;
17940c224a573f2b763046001e622aafca90f68c693Christoph Bumiller      }
18040c224a573f2b763046001e622aafca90f68c693Christoph Bumiller      if (insnDominatedBy(it->insn, usei))
18140c224a573f2b763046001e622aafca90f68c693Christoph Bumiller         it = uses.erase(it);
18240c224a573f2b763046001e622aafca90f68c693Christoph Bumiller      else
18340c224a573f2b763046001e622aafca90f68c693Christoph Bumiller         ++it;
18440c224a573f2b763046001e622aafca90f68c693Christoph Bumiller   }
18540c224a573f2b763046001e622aafca90f68c693Christoph Bumiller   if (add)
186a2af42c1d2dc91f4c31e25ff9fff15a89a9b6eadIlia Mirkin      uses.push_back(TexUse(usei, texi));
18740c224a573f2b763046001e622aafca90f68c693Christoph Bumiller}
18840c224a573f2b763046001e622aafca90f68c693Christoph Bumiller
1897752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin// While it might be tempting to use the an algorithm that just looks at tex
1907752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin// uses, not all texture results are guaranteed to be used on all paths. In
1917752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin// the case where along some control flow path a texture result is never used,
1927752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin// we might reuse that register for something else, creating a
1937752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin// write-after-write hazard. So we have to manually look through all
1947752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin// instructions looking for ones that reference the registers in question.
19540c224a573f2b763046001e622aafca90f68c693Christoph Bumillervoid
1967752bbc44e78e982de3cd4c34862adc38a338234Ilia MirkinNVC0LegalizePostRA::findFirstUses(
1977752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   Instruction *texi, std::list<TexUse> &uses)
19840c224a573f2b763046001e622aafca90f68c693Christoph Bumiller{
1997752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   int minGPR = texi->def(0).rep()->reg.data.id;
2007752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   int maxGPR = minGPR + texi->def(0).rep()->reg.size / 4 - 1;
20140c224a573f2b763046001e622aafca90f68c693Christoph Bumiller
2027752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   unordered_set<const BasicBlock *> visited;
2037752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   findFirstUsesBB(minGPR, maxGPR, texi->next, texi, uses, visited);
20440c224a573f2b763046001e622aafca90f68c693Christoph Bumiller}
20540c224a573f2b763046001e622aafca90f68c693Christoph Bumiller
20640c224a573f2b763046001e622aafca90f68c693Christoph Bumillervoid
2077752bbc44e78e982de3cd4c34862adc38a338234Ilia MirkinNVC0LegalizePostRA::findFirstUsesBB(
2087752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   int minGPR, int maxGPR, Instruction *start,
2097752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   const Instruction *texi, std::list<TexUse> &uses,
2107752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   unordered_set<const BasicBlock *> &visited)
21100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller{
2127752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   const BasicBlock *bb = start->bb;
2137752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin
2147752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   // We don't process the whole bb the first time around. This is correct,
2157752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   // however we might be in a loop and hit this BB again, and need to process
2167752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   // the full thing. So only mark a bb as visited if we processed it from the
2177752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   // beginning.
2187752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   if (start == bb->getEntry()) {
2197752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin      if (visited.find(bb) != visited.end())
2207752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin         return;
2217752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin      visited.insert(bb);
2227752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   }
2237752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin
2247752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   for (Instruction *insn = start; insn != bb->getExit(); insn = insn->next) {
2257752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin      if (insn->isNop())
2267752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin         continue;
2277752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin
2287752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin      for (int d = 0; insn->defExists(d); ++d) {
2297752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin         if (insn->def(d).getFile() != FILE_GPR ||
2307752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin             insn->def(d).rep()->reg.data.id < minGPR ||
2317752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin             insn->def(d).rep()->reg.data.id > maxGPR)
232c4bb436f7660c951cd27e52660cf825da68793e5Ilia Mirkin            continue;
2337752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin         addTexUse(uses, insn, texi);
2347752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin         return;
2357752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin      }
236c4bb436f7660c951cd27e52660cf825da68793e5Ilia Mirkin
2377752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin      for (int s = 0; insn->srcExists(s); ++s) {
2387752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin         if (insn->src(s).getFile() != FILE_GPR ||
2397752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin             insn->src(s).rep()->reg.data.id < minGPR ||
2407752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin             insn->src(s).rep()->reg.data.id > maxGPR)
2417752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin            continue;
2427752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin         addTexUse(uses, insn, texi);
2437752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin         return;
24400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      }
24500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   }
2467752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin
2477752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) {
2487752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin      findFirstUsesBB(minGPR, maxGPR, BasicBlock::get(ei.getNode())->getEntry(),
2497752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin                      texi, uses, visited);
2507752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin   }
25100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller}
25200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller
25300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller// Texture barriers:
25400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller// This pass is a bit long and ugly and can probably be optimized.
25500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller//
25600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller// 1. obtain a list of TEXes and their outputs' first use(s)
25700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller// 2. calculate the barrier level of each first use (minimal number of TEXes,
25800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller//    over all paths, between the TEX and the use in question)
25900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller// 3. for each barrier, if all paths from the source TEX to that barrier
26000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller//    contain a barrier of lesser level, it can be culled
26100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumillerbool
26200fe442253744c4c4e7e68da44d6983da053968bChristoph BumillerNVC0LegalizePostRA::insertTextureBarriers(Function *fn)
26300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller{
26400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   std::list<TexUse> *uses;
26500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   std::vector<Instruction *> texes;
26600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   std::vector<int> bbFirstTex;
26700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   std::vector<int> bbFirstUse;
26800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   std::vector<int> texCounts;
26900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   std::vector<TexUse> useVec;
27000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   ArrayList insns;
27100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller
27200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   fn->orderInstructions(insns);
27300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller
27400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   texCounts.resize(fn->allBBlocks.getSize(), 0);
27500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   bbFirstTex.resize(fn->allBBlocks.getSize(), insns.getSize());
27600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   bbFirstUse.resize(fn->allBBlocks.getSize(), insns.getSize());
27700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller
27800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   // tag BB CFG nodes by their id for later
27900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   for (ArrayList::Iterator i = fn->allBBlocks.iterator(); !i.end(); i.next()) {
28000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      BasicBlock *bb = reinterpret_cast<BasicBlock *>(i.get());
28100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      if (bb)
28200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         bb->cfg.tag = bb->getId();
28300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   }
28400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller
28500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   // gather the first uses for each TEX
28600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   for (int i = 0; i < insns.getSize(); ++i) {
28700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      Instruction *tex = reinterpret_cast<Instruction *>(insns.get(i));
28800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      if (isTextureOp(tex->op)) {
28900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         texes.push_back(tex);
29000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         if (!texCounts.at(tex->bb->getId()))
29100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            bbFirstTex[tex->bb->getId()] = texes.size() - 1;
29200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         texCounts[tex->bb->getId()]++;
29300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      }
29400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   }
29500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   insns.clear();
29600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   if (texes.empty())
29700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      return false;
29800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   uses = new std::list<TexUse>[texes.size()];
29900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   if (!uses)
30000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      return false;
301c4bb436f7660c951cd27e52660cf825da68793e5Ilia Mirkin   for (size_t i = 0; i < texes.size(); ++i) {
3027752bbc44e78e982de3cd4c34862adc38a338234Ilia Mirkin      findFirstUses(texes[i], uses[i]);
303c4bb436f7660c951cd27e52660cf825da68793e5Ilia Mirkin   }
30400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller
30500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   // determine the barrier level at each use
30600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   for (size_t i = 0; i < texes.size(); ++i) {
30700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      for (std::list<TexUse>::iterator u = uses[i].begin(); u != uses[i].end();
30800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller           ++u) {
30900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         BasicBlock *tb = texes[i]->bb;
31000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         BasicBlock *ub = u->insn->bb;
31100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         if (tb == ub) {
31200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            u->level = 0;
31300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            for (size_t j = i + 1; j < texes.size() &&
31400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller                    texes[j]->bb == tb && texes[j]->serial < u->insn->serial;
31500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller                 ++j)
31600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller               u->level++;
31700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         } else {
31800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            u->level = fn->cfg.findLightestPathWeight(&tb->cfg,
31900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller                                                      &ub->cfg, texCounts);
32000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            if (u->level < 0) {
32100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller               WARN("Failed to find path TEX -> TEXBAR\n");
32200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller               u->level = 0;
32300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller               continue;
32400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            }
32500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            // this counted all TEXes in the origin block, correct that
32600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            u->level -= i - bbFirstTex.at(tb->getId()) + 1 /* this TEX */;
32700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            // and did not count the TEXes in the destination block, add those
32800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            for (size_t j = bbFirstTex.at(ub->getId()); j < texes.size() &&
32900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller                    texes[j]->bb == ub && texes[j]->serial < u->insn->serial;
33000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller                 ++j)
33100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller               u->level++;
33200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         }
33300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         assert(u->level >= 0);
33400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         useVec.push_back(*u);
33500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      }
33600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   }
33700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   delete[] uses;
33800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller
33900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   // insert the barriers
34000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   for (size_t i = 0; i < useVec.size(); ++i) {
34100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      Instruction *prev = useVec[i].insn->prev;
34200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      if (useVec[i].level < 0)
34300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         continue;
34400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      if (prev && prev->op == OP_TEXBAR) {
34500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         if (prev->subOp > useVec[i].level)
34600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            prev->subOp = useVec[i].level;
34700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         prev->setSrc(prev->srcCount(), useVec[i].tex->getDef(0));
34800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      } else {
34900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         Instruction *bar = new_Instruction(func, OP_TEXBAR, TYPE_NONE);
35000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         bar->fixed = 1;
35100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         bar->subOp = useVec[i].level;
35200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         // make use explicit to ease latency calculation
35300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         bar->setSrc(bar->srcCount(), useVec[i].tex->getDef(0));
35400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         useVec[i].insn->bb->insertBefore(useVec[i].insn, bar);
35500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      }
35600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   }
35700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller
3585966903c28a13f13923de308c5f5116a0d5c8cbdIlia Mirkin   if (fn->getProgram()->optLevel < 3)
35900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      return true;
36000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller
36100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   std::vector<Limits> limitT, limitB, limitS; // entry, exit, single
36200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller
36300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   limitT.resize(fn->allBBlocks.getSize(), Limits(0, 0));
36400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   limitB.resize(fn->allBBlocks.getSize(), Limits(0, 0));
36500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   limitS.resize(fn->allBBlocks.getSize());
36600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller
36700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   // cull unneeded barriers (should do that earlier, but for simplicity)
36840c224a573f2b763046001e622aafca90f68c693Christoph Bumiller   IteratorRef bi = fn->cfg.iteratorCFG();
36900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   // first calculate min/max outstanding TEXes for each BB
37000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   for (bi->reset(); !bi->end(); bi->next()) {
37100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      Graph::Node *n = reinterpret_cast<Graph::Node *>(bi->get());
37200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      BasicBlock *bb = BasicBlock::get(n);
37300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      int min = 0;
37400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      int max = std::numeric_limits<int>::max();
37500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      for (Instruction *i = bb->getFirst(); i; i = i->next) {
37600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         if (isTextureOp(i->op)) {
37700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            min++;
37800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            if (max < std::numeric_limits<int>::max())
37900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller               max++;
38000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         } else
38100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         if (i->op == OP_TEXBAR) {
38200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            min = MIN2(min, i->subOp);
38300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            max = MIN2(max, i->subOp);
38400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         }
38500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      }
38600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      // limits when looking at an isolated block
38700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      limitS[bb->getId()].min = min;
38800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      limitS[bb->getId()].max = max;
38900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   }
39000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   // propagate the min/max values
39100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   for (unsigned int l = 0; l <= fn->loopNestingBound; ++l) {
39200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      for (bi->reset(); !bi->end(); bi->next()) {
39300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         Graph::Node *n = reinterpret_cast<Graph::Node *>(bi->get());
39400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         BasicBlock *bb = BasicBlock::get(n);
39500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         const int bbId = bb->getId();
39600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         for (Graph::EdgeIterator ei = n->incident(); !ei.end(); ei.next()) {
39700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            BasicBlock *in = BasicBlock::get(ei.getNode());
39800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            const int inId = in->getId();
39900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            limitT[bbId].min = MAX2(limitT[bbId].min, limitB[inId].min);
40000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            limitT[bbId].max = MAX2(limitT[bbId].max, limitB[inId].max);
40100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         }
40200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         // I just hope this is correct ...
40300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         if (limitS[bbId].max == std::numeric_limits<int>::max()) {
40400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            // no barrier
40500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            limitB[bbId].min = limitT[bbId].min + limitS[bbId].min;
40600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            limitB[bbId].max = limitT[bbId].max + limitS[bbId].min;
40700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         } else {
40800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            // block contained a barrier
40900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            limitB[bbId].min = MIN2(limitS[bbId].max,
41000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller                                    limitT[bbId].min + limitS[bbId].min);
41100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            limitB[bbId].max = MIN2(limitS[bbId].max,
41200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller                                    limitT[bbId].max + limitS[bbId].min);
41300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         }
41400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      }
41500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   }
41600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   // finally delete unnecessary barriers
41700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   for (bi->reset(); !bi->end(); bi->next()) {
41800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      Graph::Node *n = reinterpret_cast<Graph::Node *>(bi->get());
41900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      BasicBlock *bb = BasicBlock::get(n);
42000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      Instruction *prev = NULL;
42100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      Instruction *next;
42200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      int max = limitT[bb->getId()].max;
42300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      for (Instruction *i = bb->getFirst(); i; i = next) {
42400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         next = i->next;
42500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         if (i->op == OP_TEXBAR) {
42600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            if (i->subOp >= max) {
42700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller               delete_Instruction(prog, i);
4287086636358b611a2bb124253e1fe870107e1cecbTiziano Bacocco               i = NULL;
42900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            } else {
43000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller               max = i->subOp;
43100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller               if (prev && prev->op == OP_TEXBAR && prev->subOp >= max) {
43200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller                  delete_Instruction(prog, prev);
43300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller                  prev = NULL;
43400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller               }
43500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            }
43600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         } else
43700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         if (isTextureOp(i->op)) {
43800fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            max++;
43900fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller         }
4407086636358b611a2bb124253e1fe870107e1cecbTiziano Bacocco         if (i && !i->isNop())
44100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller            prev = i;
44200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      }
44300fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   }
44400fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   return true;
44500fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller}
44600fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller
44700fe442253744c4c4e7e68da44d6983da053968bChristoph Bumillerbool
44857594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LegalizePostRA::visit(Function *fn)
44957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
45000fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller   if (needTexBar)
45100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      insertTextureBarriers(fn);
45200fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller
4533433471e8b46dd9dd042a00f88ef9ad011a94aacChristoph Bumiller   rZero = new_LValue(fn, FILE_GPR);
45499e4eba669f13a0dc80880f4f91e2338377c1667Christoph Bumiller   carry = new_LValue(fn, FILE_FLAGS);
4554506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
4563433471e8b46dd9dd042a00f88ef9ad011a94aacChristoph Bumiller   rZero->reg.data.id = prog->getTarget()->getFileSize(FILE_GPR);
45799e4eba669f13a0dc80880f4f91e2338377c1667Christoph Bumiller   carry->reg.data.id = 0;
4584506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
45957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
46057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
46157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
46257594065c30feec9376be9b2132659f7d87362eeChristoph Bumillervoid
46357594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LegalizePostRA::replaceZero(Instruction *i)
46457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
46557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   for (int s = 0; i->srcExists(s); ++s) {
4664506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      if (s == 2 && i->op == OP_SUCLAMP)
4674506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         continue;
46857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      ImmediateValue *imm = i->getSrc(s)->asImm();
46957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      if (imm && imm->reg.data.u64 == 0)
4703433471e8b46dd9dd042a00f88ef9ad011a94aacChristoph Bumiller         i->setSrc(s, rZero);
47157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
47257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
47357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
47457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller// replace CONT with BRA for single unconditional continue
47557594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
47657594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LegalizePostRA::tryReplaceContWithBra(BasicBlock *bb)
47757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
47857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (bb->cfg.incidentCount() != 2 || bb->getEntry()->op != OP_PRECONT)
47957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return false;
48057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Graph::EdgeIterator ei = bb->cfg.incident();
48157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (ei.getType() != Graph::Edge::BACK)
48257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      ei.next();
48357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (ei.getType() != Graph::Edge::BACK)
48457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return false;
48557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   BasicBlock *contBB = BasicBlock::get(ei.getNode());
48657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
48757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (!contBB->getExit() || contBB->getExit()->op != OP_CONT ||
48857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller       contBB->getExit()->getPredicate())
48957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return false;
49057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   contBB->getExit()->op = OP_BRA;
49157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   bb->remove(bb->getEntry()); // delete PRECONT
49257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
49357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   ei.next();
49457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   assert(ei.end() || ei.getType() != Graph::Edge::BACK);
49557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
49657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
49757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
49857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller// replace branches to join blocks with join ops
49957594065c30feec9376be9b2132659f7d87362eeChristoph Bumillervoid
50057594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LegalizePostRA::propagateJoin(BasicBlock *bb)
50157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
50257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (bb->getEntry()->op != OP_JOIN || bb->getEntry()->asFlow()->limit)
50357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return;
50457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   for (Graph::EdgeIterator ei = bb->cfg.incident(); !ei.end(); ei.next()) {
50557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      BasicBlock *in = BasicBlock::get(ei.getNode());
50657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      Instruction *exit = in->getExit();
50757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      if (!exit) {
50857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         in->insertTail(new FlowInstruction(func, OP_JOIN, bb));
50957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         // there should always be a terminator instruction
51057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         WARN("inserted missing terminator in BB:%i\n", in->getId());
51157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      } else
51257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      if (exit->op == OP_BRA) {
51357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         exit->op = OP_JOIN;
51457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         exit->asFlow()->limit = 1; // must-not-propagate marker
51557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      }
51657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
51757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   bb->remove(bb->getEntry());
51857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
51957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
52057594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
52157594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LegalizePostRA::visit(BasicBlock *bb)
52257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
52357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Instruction *i, *next;
52457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
52557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   // remove pseudo operations and non-fixed no-ops, split 64 bit operations
52657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   for (i = bb->getFirst(); i; i = next) {
52757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      next = i->next;
52857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      if (i->op == OP_EMIT || i->op == OP_RESTART) {
52957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         if (!i->getDef(0)->refCount())
53057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller            i->setDef(0, NULL);
5319362d4bc0a03860ec386156cf499e855a9c2d2a5Christoph Bumiller         if (i->src(0).getFile() == FILE_IMMEDIATE)
5323433471e8b46dd9dd042a00f88ef9ad011a94aacChristoph Bumiller            i->setSrc(0, rZero); // initial value must be 0
53307d3972b4927841bb892af16ff0389f8a241b24cBen Skeggs         replaceZero(i);
53457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      } else
53557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      if (i->isNop()) {
53657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         bb->remove(i);
537313940b03cf7c857143b9e3ec0ab969ce4472c83Ilia Mirkin      } else
538313940b03cf7c857143b9e3ec0ab969ce4472c83Ilia Mirkin      if (i->op == OP_BAR && i->subOp == NV50_IR_SUBOP_BAR_SYNC &&
539313940b03cf7c857143b9e3ec0ab969ce4472c83Ilia Mirkin          prog->getType() != Program::TYPE_COMPUTE) {
540313940b03cf7c857143b9e3ec0ab969ce4472c83Ilia Mirkin         // It seems like barriers are never required for tessellation since
541313940b03cf7c857143b9e3ec0ab969ce4472c83Ilia Mirkin         // the warp size is 32, and there are always at most 32 tcs threads.
542313940b03cf7c857143b9e3ec0ab969ce4472c83Ilia Mirkin         bb->remove(i);
54337b67db6ae34fb6586d640a7a1b6232f091dd812Ilia Mirkin      } else
54437b67db6ae34fb6586d640a7a1b6232f091dd812Ilia Mirkin      if (i->op == OP_LOAD && i->subOp == NV50_IR_SUBOP_LDC_IS) {
54537b67db6ae34fb6586d640a7a1b6232f091dd812Ilia Mirkin         int offset = i->src(0).get()->reg.data.offset;
54637b67db6ae34fb6586d640a7a1b6232f091dd812Ilia Mirkin         if (abs(offset) > 0x10000)
54737b67db6ae34fb6586d640a7a1b6232f091dd812Ilia Mirkin            i->src(0).get()->reg.fileIndex += offset >> 16;
54837b67db6ae34fb6586d640a7a1b6232f091dd812Ilia Mirkin         i->src(0).get()->reg.data.offset = (int)(short)offset;
54957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      } else {
55099e4eba669f13a0dc80880f4f91e2338377c1667Christoph Bumiller         // TODO: Move this to before register allocation for operations that
55199e4eba669f13a0dc80880f4f91e2338377c1667Christoph Bumiller         // need the $c register !
55299e4eba669f13a0dc80880f4f91e2338377c1667Christoph Bumiller         if (typeSizeof(i->dType) == 8) {
55399e4eba669f13a0dc80880f4f91e2338377c1667Christoph Bumiller            Instruction *hi;
55499e4eba669f13a0dc80880f4f91e2338377c1667Christoph Bumiller            hi = BuildUtil::split64BitOpPostRA(func, i, rZero, carry);
55599e4eba669f13a0dc80880f4f91e2338377c1667Christoph Bumiller            if (hi)
55699e4eba669f13a0dc80880f4f91e2338377c1667Christoph Bumiller               next = hi;
55799e4eba669f13a0dc80880f4f91e2338377c1667Christoph Bumiller         }
55899e4eba669f13a0dc80880f4f91e2338377c1667Christoph Bumiller
55957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         if (i->op != OP_MOV && i->op != OP_PFETCH)
56057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller            replaceZero(i);
56157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      }
56257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
56357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (!bb->getEntry())
56457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return true;
56557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
56657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (!tryReplaceContWithBra(bb))
56757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      propagateJoin(bb);
56857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
56957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
57057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
57157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
57257594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::NVC0LoweringPass(Program *prog) : targ(prog->getTarget())
57357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
57457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   bld.setProgram(prog);
5754506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   gMemBase = NULL;
57657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
57757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
57857594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
57957594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::visit(Function *fn)
58057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
58157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (prog->getType() == Program::TYPE_GEOMETRY) {
58257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      assert(!strncmp(fn->getName(), "MAIN", 4));
58357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      // TODO: when we generate actual functions pass this value along somehow
58457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      bld.setPosition(BasicBlock::get(fn->cfg.getRoot()), false);
58557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      gpEmitAddress = bld.loadImm(NULL, 0)->asLValue();
5862ec5c8feb331af29548e98b0e78e810bbbc7009eChristoph Bumiller      if (fn->cfgExit) {
5872ec5c8feb331af29548e98b0e78e810bbbc7009eChristoph Bumiller         bld.setPosition(BasicBlock::get(fn->cfgExit)->getExit(), false);
5882ec5c8feb331af29548e98b0e78e810bbbc7009eChristoph Bumiller         bld.mkMovToReg(0, gpEmitAddress);
5892ec5c8feb331af29548e98b0e78e810bbbc7009eChristoph Bumiller      }
59057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
59157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
59257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
59357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
59457594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
59557594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::visit(BasicBlock *bb)
59657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
59757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
59857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
59957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
6007a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumillerinline Value *
6017a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph BumillerNVC0LoweringPass::loadTexHandle(Value *ptr, unsigned int slot)
6027a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumiller{
603d86933e6f42b9c2f5bb617c66c91795c560a9abdSamuel Pitoiset   uint8_t b = prog->driver->io.auxCBSlot;
6047a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumiller   uint32_t off = prog->driver->io.texBindBase + slot * 4;
6057a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumiller   return bld.
6067a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumiller      mkLoadv(TYPE_U32, bld.mkSymbol(FILE_MEMORY_CONST, b, TYPE_U32, off), ptr);
6077a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumiller}
6087a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumiller
60957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller// move array source to first slot, convert to u16, add indirections
61057594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
61157594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::handleTEX(TexInstruction *i)
61257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
61337a08ddce54d28f90dc8db8e10792d0759938590Christoph Bumiller   const int dim = i->tex.target.getDim() + i->tex.target.isCube();
61437a08ddce54d28f90dc8db8e10792d0759938590Christoph Bumiller   const int arg = i->tex.target.getArgCount();
6154da54c91d24da891c56957f29274e7821c8254f6Christoph Bumiller   const int lyr = arg - (i->tex.target.isMS() ? 2 : 1);
61619ba573a57ff6125a26ff9ae94cf43c36129645fIlia Mirkin   const int chipset = prog->getTarget()->getChipset();
61757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
6186eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin   /* Only normalize in the non-explicit derivatives case. For explicit
6196eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin    * derivatives, this is handled in handleManualTXD.
6206eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin    */
6216eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin   if (i->tex.target.isCube() && i->dPdx[0].get() == NULL) {
6226eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin      Value *src[3], *val;
6236eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin      int c;
6246eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin      for (c = 0; c < 3; ++c)
6256eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin         src[c] = bld.mkOp1v(OP_ABS, TYPE_F32, bld.getSSA(), i->getSrc(c));
6266eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin      val = bld.getScratch();
6276eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin      bld.mkOp2(OP_MAX, TYPE_F32, val, src[0], src[1]);
6286eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin      bld.mkOp2(OP_MAX, TYPE_F32, val, src[2], val);
6296eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin      bld.mkOp1(OP_RCP, TYPE_F32, val, val);
6306eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin      for (c = 0; c < 3; ++c) {
6316eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin         i->setSrc(c, bld.mkOp2v(OP_MUL, TYPE_F32, bld.getSSA(),
6326eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin                                 i->getSrc(c), val));
6336eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin      }
6346eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin   }
6356eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin
636f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   // Arguments to the TEX instruction are a little insane. Even though the
637f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   // encoding is identical between SM20 and SM30, the arguments mean
638f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   // different things between Fermi and Kepler+. A lot of arguments are
639f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   // optional based on flags passed to the instruction. This summarizes the
640f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   // order of things.
641f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //
642f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   // Fermi:
643f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //  array/indirect
644f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //  coords
645f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //  sample
646f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //  lod bias
647f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //  depth compare
648f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //  offsets:
649f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //    - tg4: 8 bits each, either 2 (1 offset reg) or 8 (2 offset reg)
650f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //    - other: 4 bits each, single reg
651f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //
652f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   // Kepler+:
653f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //  indirect handle
654f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //  array (+ offsets for txd in upper 16 bits)
655f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //  coords
656f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //  sample
657f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //  lod bias
658f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //  depth compare
659f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin   //  offsets (same as fermi, except txd which takes it with array)
6600532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin   //
6610532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin   // Maxwell (tex):
6620532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin   //  array
6630532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin   //  coords
6640532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin   //  indirect handle
6650532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin   //  sample
6660532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin   //  lod bias
6670532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin   //  depth compare
6680532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin   //  offsets
6690532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin   //
6700532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin   // Maxwell (txd):
6710532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin   //  indirect handle
6720532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin   //  coords
6730532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin   //  array + offsets
6740532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin   //  derivatives
675f525bd01d1430a5e33f57805f50fe4e89aa86ae8Ilia Mirkin
67619ba573a57ff6125a26ff9ae94cf43c36129645fIlia Mirkin   if (chipset >= NVISA_GK104_CHIPSET) {
6777a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumiller      if (i->tex.rIndirectSrc >= 0 || i->tex.sIndirectSrc >= 0) {
678b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin         // XXX this ignores tsc, and assumes a 1:1 mapping
679b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin         assert(i->tex.rIndirectSrc >= 0);
680b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin         Value *hnd = loadTexHandle(
681b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin               bld.mkOp2v(OP_SHL, TYPE_U32, bld.getSSA(),
682b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin                          i->getIndirectR(), bld.mkImm(2)),
683b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin               i->tex.r);
684b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin         i->tex.r = 0xff;
685b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin         i->tex.s = 0x1f;
686b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin         i->setIndirectR(hnd);
687b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin         i->setIndirectS(NULL);
68863b850403c90f33c295d3ad6be4ad749d4ea6274Ilia Mirkin      } else if (i->tex.r == i->tex.s || i->op == OP_TXF) {
6894506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         i->tex.r += prog->driver->io.texBindBase / 4;
690e44089b2f79aa2dcaacf348911433d1e21235c0cChristoph Bumiller         i->tex.s  = 0; // only a single cX[] value possible here
691e44089b2f79aa2dcaacf348911433d1e21235c0cChristoph Bumiller      } else {
6927a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumiller         Value *hnd = bld.getScratch();
6937a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumiller         Value *rHnd = loadTexHandle(NULL, i->tex.r);
6947a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumiller         Value *sHnd = loadTexHandle(NULL, i->tex.s);
6957a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumiller
6967a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumiller         bld.mkOp3(OP_INSBF, TYPE_U32, hnd, rHnd, bld.mkImm(0x1400), sHnd);
6977a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumiller
6987a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumiller         i->tex.r = 0; // not used for indirect tex
6997a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumiller         i->tex.s = 0;
7007a91d3a2a4c4e7851fdb46465224213ce1874c9bChristoph Bumiller         i->setIndirectR(hnd);
701e44089b2f79aa2dcaacf348911433d1e21235c0cChristoph Bumiller      }
702e44089b2f79aa2dcaacf348911433d1e21235c0cChristoph Bumiller      if (i->tex.target.isArray()) {
703e44089b2f79aa2dcaacf348911433d1e21235c0cChristoph Bumiller         LValue *layer = new_LValue(func, FILE_GPR);
7044da54c91d24da891c56957f29274e7821c8254f6Christoph Bumiller         Value *src = i->getSrc(lyr);
705e44089b2f79aa2dcaacf348911433d1e21235c0cChristoph Bumiller         const int sat = (i->op == OP_TXF) ? 1 : 0;
706e44089b2f79aa2dcaacf348911433d1e21235c0cChristoph Bumiller         DataType sTy = (i->op == OP_TXF) ? TYPE_U32 : TYPE_F32;
707e44089b2f79aa2dcaacf348911433d1e21235c0cChristoph Bumiller         bld.mkCvt(OP_CVT, TYPE_U16, layer, sTy, src)->saturate = sat;
7080532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin         if (i->op != OP_TXD || chipset < NVISA_GM107_CHIPSET) {
7090532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin            for (int s = dim; s >= 1; --s)
7100532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin               i->setSrc(s, i->getSrc(s - 1));
7110532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin            i->setSrc(0, layer);
7120532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin         } else {
7130532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin            i->setSrc(dim, layer);
7140532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin         }
715e44089b2f79aa2dcaacf348911433d1e21235c0cChristoph Bumiller      }
716b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin      // Move the indirect reference to the first place
7170532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin      if (i->tex.rIndirectSrc >= 0 && (
7180532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin                i->op == OP_TXD || chipset < NVISA_GM107_CHIPSET)) {
719b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin         Value *hnd = i->getIndirectR();
720b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin
721b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin         i->setIndirectR(NULL);
722b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin         i->moveSources(0, 1);
723b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin         i->setSrc(0, hnd);
724b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin         i->tex.rIndirectSrc = 0;
725b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin         i->tex.sIndirectSrc = -1;
726b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin      }
727e44089b2f79aa2dcaacf348911433d1e21235c0cChristoph Bumiller   } else
728e44089b2f79aa2dcaacf348911433d1e21235c0cChristoph Bumiller   // (nvc0) generate and move the tsc/tic/array source to the front
72919ba573a57ff6125a26ff9ae94cf43c36129645fIlia Mirkin   if (i->tex.target.isArray() || i->tex.rIndirectSrc >= 0 || i->tex.sIndirectSrc >= 0) {
73057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      LValue *src = new_LValue(func, FILE_GPR); // 0xttxsaaaa
73157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
7329807a8ddaf3d0b6d8bf8b3e7c0b01cc4c7db4f30Ilia Mirkin      Value *ticRel = i->getIndirectR();
7339807a8ddaf3d0b6d8bf8b3e7c0b01cc4c7db4f30Ilia Mirkin      Value *tscRel = i->getIndirectS();
7349807a8ddaf3d0b6d8bf8b3e7c0b01cc4c7db4f30Ilia Mirkin
735af3619e88043ce85560b8220dc16244f8898a926Ilia Mirkin      if (ticRel) {
7369807a8ddaf3d0b6d8bf8b3e7c0b01cc4c7db4f30Ilia Mirkin         i->setSrc(i->tex.rIndirectSrc, NULL);
737af3619e88043ce85560b8220dc16244f8898a926Ilia Mirkin         if (i->tex.r)
738af3619e88043ce85560b8220dc16244f8898a926Ilia Mirkin            ticRel = bld.mkOp2v(OP_ADD, TYPE_U32, bld.getScratch(),
739af3619e88043ce85560b8220dc16244f8898a926Ilia Mirkin                                ticRel, bld.mkImm(i->tex.r));
740af3619e88043ce85560b8220dc16244f8898a926Ilia Mirkin      }
741af3619e88043ce85560b8220dc16244f8898a926Ilia Mirkin      if (tscRel) {
7429807a8ddaf3d0b6d8bf8b3e7c0b01cc4c7db4f30Ilia Mirkin         i->setSrc(i->tex.sIndirectSrc, NULL);
743af3619e88043ce85560b8220dc16244f8898a926Ilia Mirkin         if (i->tex.s)
744af3619e88043ce85560b8220dc16244f8898a926Ilia Mirkin            tscRel = bld.mkOp2v(OP_ADD, TYPE_U32, bld.getScratch(),
745af3619e88043ce85560b8220dc16244f8898a926Ilia Mirkin                                tscRel, bld.mkImm(i->tex.s));
746af3619e88043ce85560b8220dc16244f8898a926Ilia Mirkin      }
7479807a8ddaf3d0b6d8bf8b3e7c0b01cc4c7db4f30Ilia Mirkin
7484da54c91d24da891c56957f29274e7821c8254f6Christoph Bumiller      Value *arrayIndex = i->tex.target.isArray() ? i->getSrc(lyr) : NULL;
7497d98bfedd73d632041d27ff12ccf7c7be74a2dddIlia Mirkin      if (arrayIndex) {
7507d98bfedd73d632041d27ff12ccf7c7be74a2dddIlia Mirkin         for (int s = dim; s >= 1; --s)
7517d98bfedd73d632041d27ff12ccf7c7be74a2dddIlia Mirkin            i->setSrc(s, i->getSrc(s - 1));
7527d98bfedd73d632041d27ff12ccf7c7be74a2dddIlia Mirkin         i->setSrc(0, arrayIndex);
7537d98bfedd73d632041d27ff12ccf7c7be74a2dddIlia Mirkin      } else {
7547d98bfedd73d632041d27ff12ccf7c7be74a2dddIlia Mirkin         i->moveSources(0, 1);
7557d98bfedd73d632041d27ff12ccf7c7be74a2dddIlia Mirkin      }
75657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
757e4210a42bcfdb19336faa2ad4b807818c71a2982Christoph Bumiller      if (arrayIndex) {
758e4210a42bcfdb19336faa2ad4b807818c71a2982Christoph Bumiller         int sat = (i->op == OP_TXF) ? 1 : 0;
759e4210a42bcfdb19336faa2ad4b807818c71a2982Christoph Bumiller         DataType sTy = (i->op == OP_TXF) ? TYPE_U32 : TYPE_F32;
760e4210a42bcfdb19336faa2ad4b807818c71a2982Christoph Bumiller         bld.mkCvt(OP_CVT, TYPE_U16, src, sTy, arrayIndex)->saturate = sat;
761e4210a42bcfdb19336faa2ad4b807818c71a2982Christoph Bumiller      } else {
76257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         bld.loadImm(src, 0);
763e4210a42bcfdb19336faa2ad4b807818c71a2982Christoph Bumiller      }
76457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
7659807a8ddaf3d0b6d8bf8b3e7c0b01cc4c7db4f30Ilia Mirkin      if (ticRel)
76657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         bld.mkOp3(OP_INSBF, TYPE_U32, src, ticRel, bld.mkImm(0x0917), src);
7679807a8ddaf3d0b6d8bf8b3e7c0b01cc4c7db4f30Ilia Mirkin      if (tscRel)
76857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         bld.mkOp3(OP_INSBF, TYPE_U32, src, tscRel, bld.mkImm(0x0710), src);
76957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
77057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      i->setSrc(0, src);
77157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
77257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
77319ba573a57ff6125a26ff9ae94cf43c36129645fIlia Mirkin   // For nvc0, the sample id has to be in the second operand, as the offset
77419ba573a57ff6125a26ff9ae94cf43c36129645fIlia Mirkin   // does. Right now we don't know how to pass both in, and this case can't
77519ba573a57ff6125a26ff9ae94cf43c36129645fIlia Mirkin   // happen with OpenGL. On nve0, the sample id is part of the texture
77619ba573a57ff6125a26ff9ae94cf43c36129645fIlia Mirkin   // coordinate argument.
77719ba573a57ff6125a26ff9ae94cf43c36129645fIlia Mirkin   assert(chipset >= NVISA_GK104_CHIPSET ||
77819ba573a57ff6125a26ff9ae94cf43c36129645fIlia Mirkin          !i->tex.useOffsets || !i->tex.target.isMS());
77919ba573a57ff6125a26ff9ae94cf43c36129645fIlia Mirkin
780f782d6e792db2ed7773a2d22866dbcdb1e4062eeIlia Mirkin   // offset is between lod and dc
78157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (i->tex.useOffsets) {
78257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      int n, c;
78371c1c8a9b89ca1ecca1857c53cd8c648c9c9a871Christoph Bumiller      int s = i->srcCount(0xff, true);
7848aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin      if (i->op != OP_TXD || chipset < NVISA_GK104_CHIPSET) {
7858aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin         if (i->tex.target.isShadow())
7868aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin            s--;
7878aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin         if (i->srcExists(s)) // move potential predicate out of the way
7888aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin            i->moveSources(s, 1);
7898aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin         if (i->tex.useOffsets == 4 && i->srcExists(s + 1))
7908aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin            i->moveSources(s + 1, 1);
7918aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin      }
792f6579e4b17a6010fadb464b5179dea5779c74968Ilia Mirkin      if (i->op == OP_TXG) {
793f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin         // Either there is 1 offset, which goes into the 2 low bytes of the
794f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin         // first source, or there are 4 offsets, which go into 2 sources (8
795f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin         // values, 1 byte each).
796f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin         Value *offs[2] = {NULL, NULL};
797f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin         for (n = 0; n < i->tex.useOffsets; n++) {
798f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin            for (c = 0; c < 2; ++c) {
799f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin               if ((n % 2) == 0 && c == 0)
800f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin                  offs[n / 2] = i->offset[n][c].get();
801f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin               else
802f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin                  bld.mkOp3(OP_INSBF, TYPE_U32,
803f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin                            offs[n / 2],
804f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin                            i->offset[n][c].get(),
805f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin                            bld.mkImm(0x800 | ((n * 16 + c * 8) % 32)),
806f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin                            offs[n / 2]);
807f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin            }
808f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin         }
809f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin         i->setSrc(s, offs[0]);
810f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin         if (offs[1])
811f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin            i->setSrc(s + 1, offs[1]);
812f6579e4b17a6010fadb464b5179dea5779c74968Ilia Mirkin      } else {
813f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin         unsigned imm = 0;
814f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin         assert(i->tex.useOffsets == 1);
815f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin         for (c = 0; c < 3; ++c) {
816f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin            ImmediateValue val;
817fb1afd1ea5fd25d82c75c5c3a2aba0bcb53b6d47Ilia Mirkin            if (!i->offset[0][c].getImmediate(val))
818fb1afd1ea5fd25d82c75c5c3a2aba0bcb53b6d47Ilia Mirkin               assert(!"non-immediate offset passed to non-TXG");
819f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin            imm |= (val.reg.data.u32 & 0xf) << (c * 4);
820f3aa999383074d666d6e3f3506e66b0c937904caIlia Mirkin         }
8218aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin         if (i->op == OP_TXD && chipset >= NVISA_GK104_CHIPSET) {
8228aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin            // The offset goes into the upper 16 bits of the array index. So
8238aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin            // create it if it's not already there, and INSBF it if it already
8248aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin            // is.
825b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin            s = (i->tex.rIndirectSrc >= 0) ? 1 : 0;
8260532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin            if (chipset >= NVISA_GM107_CHIPSET)
8270532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin               s += dim;
8288aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin            if (i->tex.target.isArray()) {
8290532a5fd00cdddda0fd1727fb519cb4312f47e83Ilia Mirkin               bld.mkOp3(OP_INSBF, TYPE_U32, i->getSrc(s),
8308aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin                         bld.loadImm(NULL, imm), bld.mkImm(0xc10),
831b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin                         i->getSrc(s));
8328aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin            } else {
833b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin               i->moveSources(s, 1);
834b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin               i->setSrc(s, bld.loadImm(NULL, imm << 16));
8358aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin            }
8368aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin         } else {
8378aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin            i->setSrc(s, bld.loadImm(NULL, imm));
8388aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin         }
839f6579e4b17a6010fadb464b5179dea5779c74968Ilia Mirkin      }
84057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
84157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
84219ba573a57ff6125a26ff9ae94cf43c36129645fIlia Mirkin   if (chipset >= NVISA_GK104_CHIPSET) {
84371c1c8a9b89ca1ecca1857c53cd8c648c9c9a871Christoph Bumiller      //
84471c1c8a9b89ca1ecca1857c53cd8c648c9c9a871Christoph Bumiller      // If TEX requires more than 4 sources, the 2nd register tuple must be
84571c1c8a9b89ca1ecca1857c53cd8c648c9c9a871Christoph Bumiller      // aligned to 4, even if it consists of just a single 4-byte register.
84671c1c8a9b89ca1ecca1857c53cd8c648c9c9a871Christoph Bumiller      //
84771c1c8a9b89ca1ecca1857c53cd8c648c9c9a871Christoph Bumiller      // XXX HACK: We insert 0 sources to avoid the 5 or 6 regs case.
84871c1c8a9b89ca1ecca1857c53cd8c648c9c9a871Christoph Bumiller      //
84971c1c8a9b89ca1ecca1857c53cd8c648c9c9a871Christoph Bumiller      int s = i->srcCount(0xff, true);
85071c1c8a9b89ca1ecca1857c53cd8c648c9c9a871Christoph Bumiller      if (s > 4 && s < 7) {
85171c1c8a9b89ca1ecca1857c53cd8c648c9c9a871Christoph Bumiller         if (i->srcExists(s)) // move potential predicate out of the way
85271c1c8a9b89ca1ecca1857c53cd8c648c9c9a871Christoph Bumiller            i->moveSources(s, 7 - s);
85371c1c8a9b89ca1ecca1857c53cd8c648c9c9a871Christoph Bumiller         while (s < 7)
85471c1c8a9b89ca1ecca1857c53cd8c648c9c9a871Christoph Bumiller            i->setSrc(s++, bld.loadImm(NULL, 0));
85571c1c8a9b89ca1ecca1857c53cd8c648c9c9a871Christoph Bumiller      }
85671c1c8a9b89ca1ecca1857c53cd8c648c9c9a871Christoph Bumiller   }
85771c1c8a9b89ca1ecca1857c53cd8c648c9c9a871Christoph Bumiller
85857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
85957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
86057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
86157594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
86257594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::handleManualTXD(TexInstruction *i)
86357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
86457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   static const uint8_t qOps[4][2] =
86557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   {
86657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      { QUADOP(MOV2, ADD,  MOV2, ADD),  QUADOP(MOV2, MOV2, ADD,  ADD) }, // l0
86757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      { QUADOP(SUBR, MOV2, SUBR, MOV2), QUADOP(MOV2, MOV2, ADD,  ADD) }, // l1
86857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      { QUADOP(MOV2, ADD,  MOV2, ADD),  QUADOP(SUBR, SUBR, MOV2, MOV2) }, // l2
86957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      { QUADOP(SUBR, MOV2, SUBR, MOV2), QUADOP(SUBR, SUBR, MOV2, MOV2) }, // l3
87057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   };
87157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Value *def[4][4];
87257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Value *crd[3];
87357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Instruction *tex;
87457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Value *zero = bld.loadImm(bld.getSSA(), 0);
87557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   int l, c;
87669e8b476d07544d6ef06414a1a78ce5c04761fdbIlia Mirkin   const int dim = i->tex.target.getDim() + i->tex.target.isCube();
877f667d15561820ee9dd8e836d43cce3ee52a4780eIlia Mirkin
878f667d15561820ee9dd8e836d43cce3ee52a4780eIlia Mirkin   // This function is invoked after handleTEX lowering, so we have to expect
879f667d15561820ee9dd8e836d43cce3ee52a4780eIlia Mirkin   // the arguments in the order that the hw wants them. For Fermi, array and
880f667d15561820ee9dd8e836d43cce3ee52a4780eIlia Mirkin   // indirect are both in the leading arg, while for Kepler, array and
881f667d15561820ee9dd8e836d43cce3ee52a4780eIlia Mirkin   // indirect are separate (and both precede the coordinates). Maxwell is
882f667d15561820ee9dd8e836d43cce3ee52a4780eIlia Mirkin   // handled in a separate function.
883f667d15561820ee9dd8e836d43cce3ee52a4780eIlia Mirkin   unsigned array;
884f667d15561820ee9dd8e836d43cce3ee52a4780eIlia Mirkin   if (targ->getChipset() < NVISA_GK104_CHIPSET)
885f667d15561820ee9dd8e836d43cce3ee52a4780eIlia Mirkin      array = i->tex.target.isArray() || i->tex.rIndirectSrc >= 0;
886f667d15561820ee9dd8e836d43cce3ee52a4780eIlia Mirkin   else
887f667d15561820ee9dd8e836d43cce3ee52a4780eIlia Mirkin      array = i->tex.target.isArray() + (i->tex.rIndirectSrc >= 0);
88857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
88957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   i->op = OP_TEX; // no need to clone dPdx/dPdy later
89057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
89157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   for (c = 0; c < dim; ++c)
89257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      crd[c] = bld.getScratch();
89357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
89457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   bld.mkOp(OP_QUADON, TYPE_NONE, NULL);
89557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   for (l = 0; l < 4; ++l) {
8966eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin      Value *src[3], *val;
89757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      // mov coordinates from lane l to all lanes
89857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      for (c = 0; c < dim; ++c)
899afea9bae67208cdb00b27a60c9cb013bf7d6de52Ilia Mirkin         bld.mkQuadop(0x00, crd[c], l, i->getSrc(c + array), zero);
90057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      // add dPdx from lane l to lanes dx
90157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      for (c = 0; c < dim; ++c)
90257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         bld.mkQuadop(qOps[l][0], crd[c], l, i->dPdx[c].get(), crd[c]);
90357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      // add dPdy from lane l to lanes dy
90457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      for (c = 0; c < dim; ++c)
90557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         bld.mkQuadop(qOps[l][1], crd[c], l, i->dPdy[c].get(), crd[c]);
9066eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin      // normalize cube coordinates
9076eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin      if (i->tex.target.isCube()) {
9086eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin         for (c = 0; c < 3; ++c)
9096eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin            src[c] = bld.mkOp1v(OP_ABS, TYPE_F32, bld.getSSA(), crd[c]);
9106eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin         val = bld.getScratch();
9116eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin         bld.mkOp2(OP_MAX, TYPE_F32, val, src[0], src[1]);
9126eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin         bld.mkOp2(OP_MAX, TYPE_F32, val, src[2], val);
9136eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin         bld.mkOp1(OP_RCP, TYPE_F32, val, val);
9146eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin         for (c = 0; c < 3; ++c)
9156eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin            src[c] = bld.mkOp2v(OP_MUL, TYPE_F32, bld.getSSA(), crd[c], val);
9166eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin      } else {
9176eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin         for (c = 0; c < dim; ++c)
9186eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin            src[c] = crd[c];
9196eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin      }
92057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      // texture
921a05e6a3fa28168d58a13cfb07f7a664e84b925aeFrancisco Jerez      bld.insert(tex = cloneForward(func, i));
92257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      for (c = 0; c < dim; ++c)
9236eeb284e4f74a2fe5ae6cba90f97f219935e24dfIlia Mirkin         tex->setSrc(c + array, src[c]);
92457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      // save results
92557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      for (c = 0; i->defExists(c); ++c) {
92657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         Instruction *mov;
92757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         def[c][l] = bld.getSSA();
92857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         mov = bld.mkMov(def[c][l], tex->getDef(c));
92957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         mov->fixed = 1;
93057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         mov->lanes = 1 << l;
93157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      }
93257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
93357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   bld.mkOp(OP_QUADPOP, TYPE_NONE, NULL);
93457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
93557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   for (c = 0; i->defExists(c); ++c) {
93657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      Instruction *u = bld.mkOp(OP_UNION, TYPE_U32, i->getDef(c));
93757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      for (l = 0; l < 4; ++l)
93857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         u->setSrc(l, def[c][l]);
93957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
94057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
94157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   i->bb->remove(i);
94257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
94357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
94457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
94557594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
94657594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::handleTXD(TexInstruction *txd)
94757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
94869e8b476d07544d6ef06414a1a78ce5c04761fdbIlia Mirkin   int dim = txd->tex.target.getDim() + txd->tex.target.isCube();
9498aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin   unsigned arg = txd->tex.target.getArgCount();
9508aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin   unsigned expected_args = arg;
9518aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin   const int chipset = prog->getTarget()->getChipset();
9528aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin
9538aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin   if (chipset >= NVISA_GK104_CHIPSET) {
9548aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin      if (!txd->tex.target.isArray() && txd->tex.useOffsets)
9558aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin         expected_args++;
956b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin      if (txd->tex.rIndirectSrc >= 0 || txd->tex.sIndirectSrc >= 0)
957b3cbd862242e0ff75584fef706f2b2a3da8e49f2Ilia Mirkin         expected_args++;
9588aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin   } else {
9598aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin      if (txd->tex.useOffsets)
9608aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin         expected_args++;
9617f937875c0289c2ffc2dc8306add72d5de7951efIlia Mirkin      if (!txd->tex.target.isArray() && (
9627f937875c0289c2ffc2dc8306add72d5de7951efIlia Mirkin                txd->tex.rIndirectSrc >= 0 || txd->tex.sIndirectSrc >= 0))
9637f937875c0289c2ffc2dc8306add72d5de7951efIlia Mirkin         expected_args++;
9648aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin   }
9658aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin
9668aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin   if (expected_args > 4 ||
9678aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin       dim > 2 ||
96869e8b476d07544d6ef06414a1a78ce5c04761fdbIlia Mirkin       txd->tex.target.isShadow())
9698aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin      txd->op = OP_TEX;
97057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
97157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   handleTEX(txd);
97238a20281fcc2ed244aea0aaa268035533f48a183Christoph Bumiller   while (txd->srcExists(arg))
97357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      ++arg;
97457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
9759c930639d9f6d713ccfd16b390a41a9f584f348cChristoph Bumiller   txd->tex.derivAll = true;
9768aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin   if (txd->op == OP_TEX)
97757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return handleManualTXD(txd);
97857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
9798aa34dc9cb1f4b1b17e49da98e54066832afc98eIlia Mirkin   assert(arg == expected_args);
98057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   for (int c = 0; c < dim; ++c) {
98138a20281fcc2ed244aea0aaa268035533f48a183Christoph Bumiller      txd->setSrc(arg + c * 2 + 0, txd->dPdx[c]);
98238a20281fcc2ed244aea0aaa268035533f48a183Christoph Bumiller      txd->setSrc(arg + c * 2 + 1, txd->dPdy[c]);
9839362d4bc0a03860ec386156cf499e855a9c2d2a5Christoph Bumiller      txd->dPdx[c].set(NULL);
9849362d4bc0a03860ec386156cf499e855a9c2d2a5Christoph Bumiller      txd->dPdy[c].set(NULL);
98557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
98657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
98757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
98857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
98957594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
99030cb66cd745fc793a2349f1d17046c50cd51c558Christoph BumillerNVC0LoweringPass::handleTXQ(TexInstruction *txq)
99130cb66cd745fc793a2349f1d17046c50cd51c558Christoph Bumiller{
9925877a594d54fdd2b3aa329f4d35b3491a7ee8a33Ilia Mirkin   const int chipset = prog->getTarget()->getChipset();
9935877a594d54fdd2b3aa329f4d35b3491a7ee8a33Ilia Mirkin   if (chipset >= NVISA_GK104_CHIPSET && txq->tex.rIndirectSrc < 0)
9945877a594d54fdd2b3aa329f4d35b3491a7ee8a33Ilia Mirkin      txq->tex.r += prog->driver->io.texBindBase / 4;
9955877a594d54fdd2b3aa329f4d35b3491a7ee8a33Ilia Mirkin
996346ce0b98832e33d5411200002571b3edea9e2bbIlia Mirkin   if (txq->tex.rIndirectSrc < 0)
99720e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin      return true;
99820e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin
99920e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin   Value *ticRel = txq->getIndirectR();
100020e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin
100120e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin   txq->setIndirectS(NULL);
100220e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin   txq->tex.sIndirectSrc = -1;
100320e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin
1004346ce0b98832e33d5411200002571b3edea9e2bbIlia Mirkin   assert(ticRel);
1005346ce0b98832e33d5411200002571b3edea9e2bbIlia Mirkin
100620e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin   if (chipset < NVISA_GK104_CHIPSET) {
100720e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin      LValue *src = new_LValue(func, FILE_GPR); // 0xttxsaaaa
100820e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin
1009346ce0b98832e33d5411200002571b3edea9e2bbIlia Mirkin      txq->setSrc(txq->tex.rIndirectSrc, NULL);
1010346ce0b98832e33d5411200002571b3edea9e2bbIlia Mirkin      if (txq->tex.r)
1011346ce0b98832e33d5411200002571b3edea9e2bbIlia Mirkin         ticRel = bld.mkOp2v(OP_ADD, TYPE_U32, bld.getScratch(),
1012346ce0b98832e33d5411200002571b3edea9e2bbIlia Mirkin                             ticRel, bld.mkImm(txq->tex.r));
101320e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin
1014346ce0b98832e33d5411200002571b3edea9e2bbIlia Mirkin      bld.mkOp2(OP_SHL, TYPE_U32, src, ticRel, bld.mkImm(0x17));
101520e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin
101620e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin      txq->moveSources(0, 1);
101720e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin      txq->setSrc(0, src);
101820e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin   } else {
101920e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin      Value *hnd = loadTexHandle(
102020e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin            bld.mkOp2v(OP_SHL, TYPE_U32, bld.getSSA(),
102120e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin                       txq->getIndirectR(), bld.mkImm(2)),
102220e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin            txq->tex.r);
102320e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin      txq->tex.r = 0xff;
102420e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin      txq->tex.s = 0x1f;
102520e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin
1026b346a84e270a50f0a8f1a6e474a51da04dd72f0eIlia Mirkin      txq->setIndirectR(NULL);
1027b346a84e270a50f0a8f1a6e474a51da04dd72f0eIlia Mirkin      txq->moveSources(0, 1);
1028b346a84e270a50f0a8f1a6e474a51da04dd72f0eIlia Mirkin      txq->setSrc(0, hnd);
1029b346a84e270a50f0a8f1a6e474a51da04dd72f0eIlia Mirkin      txq->tex.rIndirectSrc = 0;
103020e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin   }
103120e484afa4874e87cd18daffd66286bb893cf3fbIlia Mirkin
103230cb66cd745fc793a2349f1d17046c50cd51c558Christoph Bumiller   return true;
103330cb66cd745fc793a2349f1d17046c50cd51c558Christoph Bumiller}
103430cb66cd745fc793a2349f1d17046c50cd51c558Christoph Bumiller
103530cb66cd745fc793a2349f1d17046c50cd51c558Christoph Bumillerbool
1036423f64e83ab5b1ea7de475ae80300a8408522743Ilia MirkinNVC0LoweringPass::handleTXLQ(TexInstruction *i)
1037423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin{
1038423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin   /* The outputs are inverted compared to what the TGSI instruction
1039423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin    * expects. Take that into account in the mask.
1040423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin    */
1041423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin   assert((i->tex.mask & ~3) == 0);
1042423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin   if (i->tex.mask == 1)
1043423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin      i->tex.mask = 2;
1044423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin   else if (i->tex.mask == 2)
1045423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin      i->tex.mask = 1;
1046423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin   handleTEX(i);
1047423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin   bld.setPosition(i, true);
1048423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin
1049423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin   /* The returned values are not quite what we want:
1050423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin    * (a) convert from s16/u16 to f32
1051423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin    * (b) multiply by 1/256
1052423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin    */
1053423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin   for (int def = 0; def < 2; ++def) {
1054423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin      if (!i->defExists(def))
1055423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin         continue;
1056423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin      enum DataType type = TYPE_S16;
1057423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin      if (i->tex.mask == 2 || def > 0)
1058423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin         type = TYPE_U16;
1059423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin      bld.mkCvt(OP_CVT, TYPE_F32, i->getDef(def), type, i->getDef(def));
1060423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin      bld.mkOp2(OP_MUL, TYPE_F32, i->getDef(def),
1061423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin                i->getDef(def), bld.loadImm(NULL, 1.0f / 256));
1062423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin   }
1063423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin   if (i->tex.mask == 3) {
1064423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin      LValue *t = new_LValue(func, FILE_GPR);
1065423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin      bld.mkMov(t, i->getDef(0));
1066423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin      bld.mkMov(i->getDef(0), i->getDef(1));
1067423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin      bld.mkMov(i->getDef(1), t);
1068423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin   }
1069423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin   return true;
1070423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin}
1071423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin
1072423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkinbool
10732c4eeb0b5cf17caa06cb3fa46d4f64e6a8005d23Ilia MirkinNVC0LoweringPass::handleSUQ(Instruction *suq)
10742c4eeb0b5cf17caa06cb3fa46d4f64e6a8005d23Ilia Mirkin{
10752c4eeb0b5cf17caa06cb3fa46d4f64e6a8005d23Ilia Mirkin   suq->op = OP_MOV;
1076b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset   suq->setSrc(0, loadBufLength32(suq->getIndirect(0, 1),
10777b9a77b905bda3003dc57efb99879499ebc4ba41Ilia Mirkin                                  suq->getSrc(0)->reg.fileIndex * 16));
10787b9a77b905bda3003dc57efb99879499ebc4ba41Ilia Mirkin   suq->setIndirect(0, 0, NULL);
10797b9a77b905bda3003dc57efb99879499ebc4ba41Ilia Mirkin   suq->setIndirect(0, 1, NULL);
10802c4eeb0b5cf17caa06cb3fa46d4f64e6a8005d23Ilia Mirkin   return true;
10812c4eeb0b5cf17caa06cb3fa46d4f64e6a8005d23Ilia Mirkin}
10822c4eeb0b5cf17caa06cb3fa46d4f64e6a8005d23Ilia Mirkin
108314a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoisetvoid
108414a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel PitoisetNVC0LoweringPass::handleSharedATOM(Instruction *atom)
108514a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset{
108614a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   assert(atom->src(0).getFile() == FILE_MEMORY_SHARED);
108714a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
108814a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   BasicBlock *currBB = atom->bb;
108914a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   BasicBlock *tryLockAndSetBB = atom->bb->splitBefore(atom, false);
109014a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   BasicBlock *joinBB = atom->bb->splitAfter(atom);
109114a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
109214a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   bld.setPosition(currBB, true);
109314a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   assert(!currBB->joinAt);
109414a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   currBB->joinAt = bld.mkFlow(OP_JOINAT, joinBB, CC_ALWAYS, NULL);
109514a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
109614a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   bld.mkFlow(OP_BRA, tryLockAndSetBB, CC_ALWAYS, NULL);
109714a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   currBB->cfg.attach(&tryLockAndSetBB->cfg, Graph::Edge::TREE);
109814a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
109914a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   bld.setPosition(tryLockAndSetBB, true);
110014a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
110114a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   Instruction *ld =
110214a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      bld.mkLoad(TYPE_U32, atom->getDef(0),
110314a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset                 bld.mkSymbol(FILE_MEMORY_SHARED, 0, TYPE_U32, 0), NULL);
110414a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   ld->setDef(1, bld.getSSA(1, FILE_PREDICATE));
110514a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   ld->subOp = NV50_IR_SUBOP_LOAD_LOCKED;
110614a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
110714a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   Value *stVal;
110814a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   if (atom->subOp == NV50_IR_SUBOP_ATOM_EXCH) {
110914a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      // Read the old value, and write the new one.
111014a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      stVal = atom->getSrc(1);
111114a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   } else if (atom->subOp == NV50_IR_SUBOP_ATOM_CAS) {
111214a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      CmpInstruction *set =
111314a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset         bld.mkCmp(OP_SET, CC_EQ, TYPE_U32, bld.getSSA(1, FILE_PREDICATE),
111414a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset                   TYPE_U32, ld->getDef(0), atom->getSrc(1));
111514a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      set->setPredicate(CC_P, ld->getDef(1));
111614a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
11176526225f888a08b301e8c39ec70b4e739081e490Samuel Pitoiset      Instruction *selp =
11186526225f888a08b301e8c39ec70b4e739081e490Samuel Pitoiset         bld.mkOp3(OP_SELP, TYPE_U32, bld.getSSA(), ld->getDef(0),
11196526225f888a08b301e8c39ec70b4e739081e490Samuel Pitoiset                   atom->getSrc(2), set->getDef(0));
11206526225f888a08b301e8c39ec70b4e739081e490Samuel Pitoiset      selp->src(2).mod = Modifier(NV50_IR_MOD_NOT);
112114a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      selp->setPredicate(CC_P, ld->getDef(1));
112214a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
112314a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      stVal = selp->getDef(0);
112414a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   } else {
112514a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      operation op;
112614a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
112714a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      switch (atom->subOp) {
112814a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      case NV50_IR_SUBOP_ATOM_ADD:
112914a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset         op = OP_ADD;
113014a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset         break;
113114a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      case NV50_IR_SUBOP_ATOM_AND:
113214a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset         op = OP_AND;
113314a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset         break;
113414a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      case NV50_IR_SUBOP_ATOM_OR:
113514a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset         op = OP_OR;
113614a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset         break;
113714a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      case NV50_IR_SUBOP_ATOM_XOR:
113814a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset         op = OP_XOR;
113914a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset         break;
114014a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      case NV50_IR_SUBOP_ATOM_MIN:
114114a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset         op = OP_MIN;
114214a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset         break;
114314a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      case NV50_IR_SUBOP_ATOM_MAX:
114414a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset         op = OP_MAX;
114514a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset         break;
114614a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      default:
114714a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset         assert(0);
1148e05492fd7f0e1a9454482a9174f5870b8cb5a41eSamuel Pitoiset         return;
114914a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      }
115014a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
115114a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      Instruction *i =
115214a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset         bld.mkOp2(op, atom->dType, bld.getSSA(), ld->getDef(0),
115314a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset                   atom->getSrc(1));
115414a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      i->setPredicate(CC_P, ld->getDef(1));
115514a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
115614a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      stVal = i->getDef(0);
115714a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   }
115814a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
115914a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   Instruction *st =
116014a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      bld.mkStore(OP_STORE, TYPE_U32,
116114a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset                  bld.mkSymbol(FILE_MEMORY_SHARED, 0, TYPE_U32, 0),
116214a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset                  NULL, stVal);
116314a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   st->setPredicate(CC_P, ld->getDef(1));
116414a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   st->subOp = NV50_IR_SUBOP_STORE_UNLOCKED;
116514a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
116614a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   // Loop until the lock is acquired.
116714a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   bld.mkFlow(OP_BRA, tryLockAndSetBB, CC_NOT_P, ld->getDef(1));
116814a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   tryLockAndSetBB->cfg.attach(&tryLockAndSetBB->cfg, Graph::Edge::BACK);
116914a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   tryLockAndSetBB->cfg.attach(&joinBB->cfg, Graph::Edge::CROSS);
117014a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   bld.mkFlow(OP_BRA, joinBB, CC_ALWAYS, NULL);
117114a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
117214a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   bld.remove(atom);
117314a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
117414a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   bld.setPosition(joinBB, false);
117514a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   bld.mkFlow(OP_JOIN, NULL, CC_ALWAYS, NULL)->fixed = 1;
117614a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset}
117714a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
11782c4eeb0b5cf17caa06cb3fa46d4f64e6a8005d23Ilia Mirkinbool
1179c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph BumillerNVC0LoweringPass::handleATOM(Instruction *atom)
1180c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller{
1181c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller   SVSemantic sv;
11827b9a77b905bda3003dc57efb99879499ebc4ba41Ilia Mirkin   Value *ptr = atom->getIndirect(0, 0), *ind = atom->getIndirect(0, 1), *base;
1183c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller
1184c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller   switch (atom->src(0).getFile()) {
1185c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller   case FILE_MEMORY_LOCAL:
1186c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller      sv = SV_LBASE;
1187c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller      break;
1188c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller   case FILE_MEMORY_SHARED:
118914a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      handleSharedATOM(atom);
119014a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      return true;
1191c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller   default:
1192c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller      assert(atom->src(0).getFile() == FILE_MEMORY_GLOBAL);
1193b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset      base = loadBufInfo64(ind, atom->getSrc(0)->reg.fileIndex * 16);
1194c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin      assert(base->reg.size == 8);
1195c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin      if (ptr)
1196c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin         base = bld.mkOp2v(OP_ADD, TYPE_U64, base, base, ptr);
1197c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin      assert(base->reg.size == 8);
1198c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin      atom->setIndirect(0, 0, base);
1199c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller      return true;
1200c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller   }
1201c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin   base =
1202c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller      bld.mkOp1v(OP_RDSV, TYPE_U32, bld.getScratch(), bld.mkSysVal(sv, 0));
1203c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller
1204c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller   atom->setSrc(0, cloneShallow(func, atom->getSrc(0)));
1205c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller   atom->getSrc(0)->reg.file = FILE_MEMORY_GLOBAL;
1206c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller   if (ptr)
1207c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller      base = bld.mkOp2v(OP_ADD, TYPE_U32, base, base, ptr);
12087b9a77b905bda3003dc57efb99879499ebc4ba41Ilia Mirkin   atom->setIndirect(0, 1, NULL);
1209c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller   atom->setIndirect(0, 0, base);
1210c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller
1211c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller   return true;
1212c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller}
1213c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller
121475f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumillerbool
121575f1f852b00ad0d766684d01695322b93a2acd55Christoph BumillerNVC0LoweringPass::handleCasExch(Instruction *cas, bool needCctl)
121675f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller{
121714a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   if (cas->src(0).getFile() == FILE_MEMORY_SHARED) {
121814a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      // ATOM_CAS and ATOM_EXCH are handled in handleSharedATOM().
121914a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset      return false;
122014a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset   }
122114a810e9d0dbf52e547ae6e16a68487d7cb92004Samuel Pitoiset
122275f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller   if (cas->subOp != NV50_IR_SUBOP_ATOM_CAS &&
122375f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller       cas->subOp != NV50_IR_SUBOP_ATOM_EXCH)
122475f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      return false;
122575f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller   bld.setPosition(cas, true);
122675f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller
122775f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller   if (needCctl) {
122875f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      Instruction *cctl = bld.mkOp1(OP_CCTL, TYPE_NONE, NULL, cas->getSrc(0));
122975f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      cctl->setIndirect(0, 0, cas->getIndirect(0, 0));
123075f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      cctl->fixed = 1;
123175f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      cctl->subOp = NV50_IR_SUBOP_CCTL_IV;
123275f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      if (cas->isPredicated())
123375f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller         cctl->setPredicate(cas->cc, cas->getPredicate());
123475f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller   }
123575f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller
1236df043f076464d817a9d88c4c43757e65b6eae3f9Ilia Mirkin   if (cas->subOp == NV50_IR_SUBOP_ATOM_CAS) {
123775f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      // CAS is crazy. It's 2nd source is a double reg, and the 3rd source
123875f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      // should be set to the high part of the double reg or bad things will
123975f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      // happen elsewhere in the universe.
124075f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      // Also, it sometimes returns the new value instead of the old one
124175f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      // under mysterious circumstances.
124275f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      Value *dreg = bld.getSSA(8);
124375f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      bld.setPosition(cas, false);
124475f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      bld.mkOp2(OP_MERGE, TYPE_U64, dreg, cas->getSrc(1), cas->getSrc(2));
124575f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      cas->setSrc(1, dreg);
1246df043f076464d817a9d88c4c43757e65b6eae3f9Ilia Mirkin      cas->setSrc(2, dreg);
124775f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller   }
124875f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller
124975f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller   return true;
125075f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller}
125175f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller
12524506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumillerinline Value *
1253b8b3af2932039c6105d61f6922157a250ed8b79aSamuel PitoisetNVC0LoweringPass::loadResInfo32(Value *ptr, uint32_t off, uint16_t base)
12544506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller{
1255d86933e6f42b9c2f5bb617c66c91795c560a9abdSamuel Pitoiset   uint8_t b = prog->driver->io.auxCBSlot;
1256b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset   off += base;
1257b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset
12584506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   return bld.
12594506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      mkLoadv(TYPE_U32, bld.mkSymbol(FILE_MEMORY_CONST, b, TYPE_U32, off), ptr);
12604506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller}
12614506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
12624506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumillerinline Value *
1263b8b3af2932039c6105d61f6922157a250ed8b79aSamuel PitoisetNVC0LoweringPass::loadResInfo64(Value *ptr, uint32_t off, uint16_t base)
1264c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin{
1265d86933e6f42b9c2f5bb617c66c91795c560a9abdSamuel Pitoiset   uint8_t b = prog->driver->io.auxCBSlot;
1266b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset   off += base;
1267c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin
12687b9a77b905bda3003dc57efb99879499ebc4ba41Ilia Mirkin   if (ptr)
12697b9a77b905bda3003dc57efb99879499ebc4ba41Ilia Mirkin      ptr = bld.mkOp2v(OP_SHL, TYPE_U32, bld.getScratch(), ptr, bld.mkImm(4));
12707b9a77b905bda3003dc57efb99879499ebc4ba41Ilia Mirkin
1271c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin   return bld.
1272c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin      mkLoadv(TYPE_U64, bld.mkSymbol(FILE_MEMORY_CONST, b, TYPE_U64, off), ptr);
1273c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin}
1274c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin
1275c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkininline Value *
1276b8b3af2932039c6105d61f6922157a250ed8b79aSamuel PitoisetNVC0LoweringPass::loadResLength32(Value *ptr, uint32_t off, uint16_t base)
1277c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin{
1278d86933e6f42b9c2f5bb617c66c91795c560a9abdSamuel Pitoiset   uint8_t b = prog->driver->io.auxCBSlot;
1279b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset   off += base;
1280c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin
12817b9a77b905bda3003dc57efb99879499ebc4ba41Ilia Mirkin   if (ptr)
12827b9a77b905bda3003dc57efb99879499ebc4ba41Ilia Mirkin      ptr = bld.mkOp2v(OP_SHL, TYPE_U32, bld.getScratch(), ptr, bld.mkImm(4));
12837b9a77b905bda3003dc57efb99879499ebc4ba41Ilia Mirkin
1284c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin   return bld.
1285c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin      mkLoadv(TYPE_U32, bld.mkSymbol(FILE_MEMORY_CONST, b, TYPE_U64, off + 8), ptr);
1286c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin}
1287c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin
1288c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkininline Value *
1289b8b3af2932039c6105d61f6922157a250ed8b79aSamuel PitoisetNVC0LoweringPass::loadSuInfo32(Value *ptr, uint32_t off)
1290b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset{
1291b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset   return loadResInfo32(ptr, off, prog->driver->io.suInfoBase);
1292b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset}
1293b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset
1294b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoisetinline Value *
1295b8b3af2932039c6105d61f6922157a250ed8b79aSamuel PitoisetNVC0LoweringPass::loadSuInfo64(Value *ptr, uint32_t off)
1296b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset{
1297b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset   return loadResInfo64(ptr, off, prog->driver->io.suInfoBase);
1298b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset}
1299b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset
1300b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoisetinline Value *
1301b8b3af2932039c6105d61f6922157a250ed8b79aSamuel PitoisetNVC0LoweringPass::loadSuLength32(Value *ptr, uint32_t off)
1302b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset{
1303b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset   return loadResLength32(ptr, off, prog->driver->io.suInfoBase);
1304b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset}
1305b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset
1306b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoisetinline Value *
1307b8b3af2932039c6105d61f6922157a250ed8b79aSamuel PitoisetNVC0LoweringPass::loadBufInfo32(Value *ptr, uint32_t off)
1308b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset{
1309b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset   return loadResInfo32(ptr, off, prog->driver->io.bufInfoBase);
1310b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset}
1311b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset
1312b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoisetinline Value *
1313b8b3af2932039c6105d61f6922157a250ed8b79aSamuel PitoisetNVC0LoweringPass::loadBufInfo64(Value *ptr, uint32_t off)
1314b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset{
1315b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset   return loadResInfo64(ptr, off, prog->driver->io.bufInfoBase);
1316b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset}
1317b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset
1318b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoisetinline Value *
1319b8b3af2932039c6105d61f6922157a250ed8b79aSamuel PitoisetNVC0LoweringPass::loadBufLength32(Value *ptr, uint32_t off)
1320b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset{
1321b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset   return loadResLength32(ptr, off, prog->driver->io.bufInfoBase);
1322b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset}
1323b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset
1324b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoisetinline Value *
13254506ed28de7f9d76bbc99c0758a7891b84528729Christoph BumillerNVC0LoweringPass::loadMsInfo32(Value *ptr, uint32_t off)
13264506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller{
13274506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   uint8_t b = prog->driver->io.msInfoCBSlot;
13284506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   off += prog->driver->io.msInfoBase;
13294506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   return bld.
13304506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      mkLoadv(TYPE_U32, bld.mkSymbol(FILE_MEMORY_CONST, b, TYPE_U32, off), ptr);
13314506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller}
13324506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
13334506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller/* On nvc0, surface info is obtained via the surface binding points passed
13344506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller * to the SULD/SUST instructions.
13354506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller * On nve4, surface info is stored in c[] and is used by various special
13364506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller * instructions, e.g. for clamping coordiantes or generating an address.
13374506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller * They couldn't just have added an equivalent to TIC now, couldn't they ?
13384506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller */
13394506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_ADDR   0x00
13404506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_FMT    0x04
13414506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_DIM_X  0x08
13424506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_PITCH  0x0c
13434506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_DIM_Y  0x10
13444506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_ARRAY  0x14
13454506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_DIM_Z  0x18
13464506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_UNK1C  0x1c
13474506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_WIDTH  0x20
13484506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_HEIGHT 0x24
13494506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_DEPTH  0x28
13504506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_TARGET 0x2c
13514506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_CALL   0x30
13524506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_RAW_X  0x34
13534506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_MS_X   0x38
13544506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_MS_Y   0x3c
13554506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
13564506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO__STRIDE 0x40
13574506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
13584506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_DIM(i)  (0x08 + (i) * 8)
13594506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_SIZE(i) (0x20 + (i) * 4)
13604506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller#define NVE4_SU_INFO_MS(i)   (0x38 + (i) * 4)
13614506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
13624506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumillerstatic inline uint16_t getSuClampSubOp(const TexInstruction *su, int c)
13634506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller{
13644506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   switch (su->tex.target.getEnum()) {
13654506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case TEX_TARGET_BUFFER:      return NV50_IR_SUBOP_SUCLAMP_PL(0, 1);
13664506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case TEX_TARGET_RECT:        return NV50_IR_SUBOP_SUCLAMP_SD(0, 2);
13674506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case TEX_TARGET_1D:          return NV50_IR_SUBOP_SUCLAMP_SD(0, 2);
13684506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case TEX_TARGET_1D_ARRAY:    return (c == 1) ?
13694506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller                                   NV50_IR_SUBOP_SUCLAMP_PL(0, 2) :
13704506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller                                   NV50_IR_SUBOP_SUCLAMP_SD(0, 2);
13714506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case TEX_TARGET_2D:          return NV50_IR_SUBOP_SUCLAMP_BL(0, 2);
13724506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case TEX_TARGET_2D_MS:       return NV50_IR_SUBOP_SUCLAMP_BL(0, 2);
13734506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case TEX_TARGET_2D_ARRAY:    return NV50_IR_SUBOP_SUCLAMP_SD(0, 2);
13744506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case TEX_TARGET_2D_MS_ARRAY: return NV50_IR_SUBOP_SUCLAMP_SD(0, 2);
13754506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case TEX_TARGET_3D:          return NV50_IR_SUBOP_SUCLAMP_SD(0, 2);
13764506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case TEX_TARGET_CUBE:        return NV50_IR_SUBOP_SUCLAMP_SD(0, 2);
13774506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case TEX_TARGET_CUBE_ARRAY:  return NV50_IR_SUBOP_SUCLAMP_SD(0, 2);
13784506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   default:
13794506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      assert(0);
13804506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      return 0;
13814506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   }
13824506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller}
13834506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
13844506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumillervoid
13854506ed28de7f9d76bbc99c0758a7891b84528729Christoph BumillerNVC0LoweringPass::adjustCoordinatesMS(TexInstruction *tex)
13864506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller{
13874506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   const uint16_t base = tex->tex.r * NVE4_SU_INFO__STRIDE;
13884506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   const int arg = tex->tex.target.getArgCount();
13894506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
13904506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   if (tex->tex.target == TEX_TARGET_2D_MS)
13914506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      tex->tex.target = TEX_TARGET_2D;
13924506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   else
13934506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   if (tex->tex.target == TEX_TARGET_2D_MS_ARRAY)
13944506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      tex->tex.target = TEX_TARGET_2D_ARRAY;
13954506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   else
13964506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      return;
13974506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
13984506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   Value *x = tex->getSrc(0);
13994506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   Value *y = tex->getSrc(1);
14004506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   Value *s = tex->getSrc(arg - 1);
14014506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
14024506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   Value *tx = bld.getSSA(), *ty = bld.getSSA(), *ts = bld.getSSA();
14034506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
1404b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset   Value *ms_x = loadSuInfo32(NULL, base + NVE4_SU_INFO_MS(0));
1405b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset   Value *ms_y = loadSuInfo32(NULL, base + NVE4_SU_INFO_MS(1));
14064506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
14074506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   bld.mkOp2(OP_SHL, TYPE_U32, tx, x, ms_x);
14084506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   bld.mkOp2(OP_SHL, TYPE_U32, ty, y, ms_y);
14094506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
14104506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   s = bld.mkOp2v(OP_AND, TYPE_U32, ts, s, bld.loadImm(NULL, 0x7));
14114506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   s = bld.mkOp2v(OP_SHL, TYPE_U32, ts, ts, bld.mkImm(3));
14124506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
14134506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   Value *dx = loadMsInfo32(ts, 0x0);
14144506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   Value *dy = loadMsInfo32(ts, 0x4);
14154506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
14164506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   bld.mkOp2(OP_ADD, TYPE_U32, tx, tx, dx);
14174506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   bld.mkOp2(OP_ADD, TYPE_U32, ty, ty, dy);
14184506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
14194506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   tex->setSrc(0, tx);
14204506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   tex->setSrc(1, ty);
14214506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   tex->moveSources(arg, -1);
14224506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller}
14234506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
14244506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller// Sets 64-bit "generic address", predicate and format sources for SULD/SUST.
14254506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller// They're computed from the coordinates using the surface info in c[] space.
14264506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumillervoid
14274506ed28de7f9d76bbc99c0758a7891b84528729Christoph BumillerNVC0LoweringPass::processSurfaceCoordsNVE4(TexInstruction *su)
14284506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller{
14294506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   Instruction *insn;
14304506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   const bool atom = su->op == OP_SUREDB || su->op == OP_SUREDP;
14314506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   const bool raw =
14324506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      su->op == OP_SULDB || su->op == OP_SUSTB || su->op == OP_SUREDB;
14334506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   const int idx = su->tex.r;
14344506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   const int dim = su->tex.target.getDim();
14354506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   const int arg = dim + (su->tex.target.isArray() ? 1 : 0);
14364506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   const uint16_t base = idx * NVE4_SU_INFO__STRIDE;
14374506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   int c;
14384506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   Value *zero = bld.mkImm(0);
14394506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   Value *p1 = NULL;
14404506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   Value *v;
14414506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   Value *src[3];
14424506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   Value *bf, *eau, *off;
14434506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   Value *addr, *pred;
14444506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
14454506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   off = bld.getScratch(4);
14464506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   bf = bld.getScratch(4);
14474506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   addr = bld.getSSA(8);
14484506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   pred = bld.getScratch(1, FILE_PREDICATE);
14494506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
14504506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   bld.setPosition(su, false);
14514506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
14524506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   adjustCoordinatesMS(su);
14534506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
14544506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   // calculate clamped coordinates
14554506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   for (c = 0; c < arg; ++c) {
14564506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      src[c] = bld.getScratch();
14574506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      if (c == 0 && raw)
1458b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset         v = loadSuInfo32(NULL, base + NVE4_SU_INFO_RAW_X);
14594506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      else
1460b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset         v = loadSuInfo32(NULL, base + NVE4_SU_INFO_DIM(c));
14614506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      bld.mkOp3(OP_SUCLAMP, TYPE_S32, src[c], su->getSrc(c), v, zero)
14624506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         ->subOp = getSuClampSubOp(su, c);
14634506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   }
14644506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   for (; c < 3; ++c)
14654506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      src[c] = zero;
14664506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
14674506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   // set predicate output
14684506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   if (su->tex.target == TEX_TARGET_BUFFER) {
14694506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      src[0]->getInsn()->setFlagsDef(1, pred);
14704506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   } else
14714506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   if (su->tex.target.isArray()) {
14724506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      p1 = bld.getSSA(1, FILE_PREDICATE);
14734506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      src[dim]->getInsn()->setFlagsDef(1, p1);
14744506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   }
14754506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
14764506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   // calculate pixel offset
14774506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   if (dim == 1) {
14784506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      if (su->tex.target != TEX_TARGET_BUFFER)
14794506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         bld.mkOp2(OP_AND, TYPE_U32, off, src[0], bld.loadImm(NULL, 0xffff));
14804506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   } else
14814506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   if (dim == 3) {
1482b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset      v = loadSuInfo32(NULL, base + NVE4_SU_INFO_UNK1C);
14834506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      bld.mkOp3(OP_MADSP, TYPE_U32, off, src[2], v, src[1])
14844506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         ->subOp = NV50_IR_SUBOP_MADSP(4,2,8); // u16l u16l u16l
14854506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
1486b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset      v = loadSuInfo32(NULL, base + NVE4_SU_INFO_PITCH);
14874506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      bld.mkOp3(OP_MADSP, TYPE_U32, off, off, v, src[0])
14884506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         ->subOp = NV50_IR_SUBOP_MADSP(0,2,8); // u32 u16l u16l
14894506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   } else {
14904506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      assert(dim == 2);
1491b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset      v = loadSuInfo32(NULL, base + NVE4_SU_INFO_PITCH);
14924506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      bld.mkOp3(OP_MADSP, TYPE_U32, off, src[1], v, src[0])
14934506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         ->subOp = su->tex.target.isArray() ?
14944506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         NV50_IR_SUBOP_MADSP_SD : NV50_IR_SUBOP_MADSP(4,2,8); // u16l u16l u16l
14954506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   }
14964506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
14974506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   // calculate effective address part 1
14984506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   if (su->tex.target == TEX_TARGET_BUFFER) {
14994506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      if (raw) {
15004506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         bf = src[0];
15014506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      } else {
1502b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset         v = loadSuInfo32(NULL, base + NVE4_SU_INFO_FMT);
15034506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         bld.mkOp3(OP_VSHL, TYPE_U32, bf, src[0], v, zero)
15044506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller            ->subOp = NV50_IR_SUBOP_V1(7,6,8|2);
15054506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      }
15064506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   } else {
15074506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      Value *y = src[1];
15084506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      Value *z = src[2];
15094506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      uint16_t subOp = 0;
15104506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
15114506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      switch (dim) {
15124506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      case 1:
15134506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         y = zero;
15144506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         z = zero;
15154506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         break;
15164506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      case 2:
15174506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         z = off;
15184506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         if (!su->tex.target.isArray()) {
1519b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset            z = loadSuInfo32(NULL, base + NVE4_SU_INFO_UNK1C);
15204506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller            subOp = NV50_IR_SUBOP_SUBFM_3D;
15214506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         }
15224506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         break;
15234506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      default:
15244506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         subOp = NV50_IR_SUBOP_SUBFM_3D;
15254506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         assert(dim == 3);
15264506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         break;
15274506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      }
15284506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      insn = bld.mkOp3(OP_SUBFM, TYPE_U32, bf, src[0], y, z);
15294506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      insn->subOp = subOp;
15304506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      insn->setFlagsDef(1, pred);
15314506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   }
15324506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
15334506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   // part 2
1534b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset   v = loadSuInfo32(NULL, base + NVE4_SU_INFO_ADDR);
15354506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
15364506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   if (su->tex.target == TEX_TARGET_BUFFER) {
15374506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      eau = v;
15384506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   } else {
15394506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      eau = bld.mkOp3v(OP_SUEAU, TYPE_U32, bld.getScratch(4), off, bf, v);
15404506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   }
15414506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   // add array layer offset
15424506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   if (su->tex.target.isArray()) {
1543b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset      v = loadSuInfo32(NULL, base + NVE4_SU_INFO_ARRAY);
15444506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      if (dim == 1)
15454506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         bld.mkOp3(OP_MADSP, TYPE_U32, eau, src[1], v, eau)
15464506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller            ->subOp = NV50_IR_SUBOP_MADSP(4,0,0); // u16 u24 u32
15474506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      else
15484506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         bld.mkOp3(OP_MADSP, TYPE_U32, eau, v, src[2], eau)
15494506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller            ->subOp = NV50_IR_SUBOP_MADSP(0,0,0); // u32 u24 u32
15504506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      // combine predicates
15514506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      assert(p1);
15524506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      bld.mkOp2(OP_OR, TYPE_U8, pred, pred, p1);
15534506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   }
15544506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
15554506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   if (atom) {
15564506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      Value *lo = bf;
15574506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      if (su->tex.target == TEX_TARGET_BUFFER) {
15584506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         lo = zero;
15594506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         bld.mkMov(off, bf);
15604506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      }
15614506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      //  bf == g[] address & 0xff
15624506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      // eau == g[] address >> 8
15634506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      bld.mkOp3(OP_PERMT, TYPE_U32,  bf,   lo, bld.loadImm(NULL, 0x6540), eau);
15644506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      bld.mkOp3(OP_PERMT, TYPE_U32, eau, zero, bld.loadImm(NULL, 0x0007), eau);
15654506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   } else
15664506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   if (su->op == OP_SULDP && su->tex.target == TEX_TARGET_BUFFER) {
15674506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      // Convert from u32 to u8 address format, which is what the library code
15684506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      // doing SULDP currently uses.
15694506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      // XXX: can SUEAU do this ?
15704506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      // XXX: does it matter that we don't mask high bytes in bf ?
15714506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      // Grrr.
15724506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      bld.mkOp2(OP_SHR, TYPE_U32, off, bf, bld.mkImm(8));
15734506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      bld.mkOp2(OP_ADD, TYPE_U32, eau, eau, off);
15744506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   }
15754506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
15764506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   bld.mkOp2(OP_MERGE, TYPE_U64, addr, bf, eau);
15774506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
15784506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   if (atom && su->tex.target == TEX_TARGET_BUFFER)
15794506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      bld.mkOp2(OP_ADD, TYPE_U64, addr, addr, off);
15804506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
15814506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   // let's just set it 0 for raw access and hope it works
15824506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   v = raw ?
1583b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset      bld.mkImm(0) : loadSuInfo32(NULL, base + NVE4_SU_INFO_FMT);
15844506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
15854506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   // get rid of old coordinate sources, make space for fmt info and predicate
15864506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   su->moveSources(arg, 3 - arg);
15874506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   // set 64 bit address and 32-bit format sources
15884506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   su->setSrc(0, addr);
15894506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   su->setSrc(1, v);
15904506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   su->setSrc(2, pred);
15914506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller}
15924506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
15934506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumillervoid
15944506ed28de7f9d76bbc99c0758a7891b84528729Christoph BumillerNVC0LoweringPass::handleSurfaceOpNVE4(TexInstruction *su)
15954506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller{
15964506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   processSurfaceCoordsNVE4(su);
15974506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
15984506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   // Who do we hate more ? The person who decided that nvc0's SULD doesn't
15994506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   // have to support conversion or the person who decided that, in OpenCL,
16004506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   // you don't have to specify the format here like you do in OpenGL ?
16014506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
16024506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   if (su->op == OP_SULDP) {
16034506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      // We don't patch shaders. Ever.
16044506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      // You get an indirect call to our library blob here.
16054506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      // But at least it's uniform.
16064506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      FlowInstruction *call;
16074506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      LValue *p[3];
16084506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      LValue *r[5];
16094506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      uint16_t base = su->tex.r * NVE4_SU_INFO__STRIDE + NVE4_SU_INFO_CALL;
16104506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
16114506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      for (int i = 0; i < 4; ++i)
16124506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         (r[i] = bld.getScratch(4, FILE_GPR))->reg.data.id = i;
16134506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      for (int i = 0; i < 3; ++i)
16144506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         (p[i] = bld.getScratch(1, FILE_PREDICATE))->reg.data.id = i;
16154506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      (r[4] = bld.getScratch(8, FILE_GPR))->reg.data.id = 4;
16164506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
16174506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      bld.mkMov(p[1], bld.mkImm((su->cache == CACHE_CA) ? 1 : 0), TYPE_U8);
16184506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      bld.mkMov(p[2], bld.mkImm((su->cache == CACHE_CG) ? 1 : 0), TYPE_U8);
16194506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      bld.mkMov(p[0], su->getSrc(2), TYPE_U8);
16204506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      bld.mkMov(r[4], su->getSrc(0), TYPE_U64);
16214506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      bld.mkMov(r[2], su->getSrc(1), TYPE_U32);
16224506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
16234506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      call = bld.mkFlow(OP_CALL, NULL, su->cc, su->getPredicate());
16244506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
16254506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      call->indirect = 1;
16264506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      call->absolute = 1;
16274506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      call->setSrc(0, bld.mkSymbol(FILE_MEMORY_CONST,
1628d86933e6f42b9c2f5bb617c66c91795c560a9abdSamuel Pitoiset                                   prog->driver->io.auxCBSlot, TYPE_U32,
16294506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller                                   prog->driver->io.suInfoBase + base));
16304506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      call->setSrc(1, r[2]);
16314506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      call->setSrc(2, r[4]);
16324506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      for (int i = 0; i < 3; ++i)
16334506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         call->setSrc(3 + i, p[i]);
16344506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      for (int i = 0; i < 4; ++i) {
16354506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         call->setDef(i, r[i]);
16364506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         bld.mkMov(su->getDef(i), r[i]);
16374506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      }
16384506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      call->setDef(4, p[1]);
16394506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      delete_Instruction(bld.getProgram(), su);
16404506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   }
16414506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
16424506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   if (su->op == OP_SUREDB || su->op == OP_SUREDP) {
164375f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      // FIXME: for out of bounds access, destination value will be undefined !
16444506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      Value *pred = su->getSrc(2);
16454506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      CondCode cc = CC_NOT_P;
16464506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      if (su->getPredicate()) {
16474506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         pred = bld.getScratch(1, FILE_PREDICATE);
16484506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         cc = su->cc;
16494506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         if (cc == CC_NOT_P) {
16504506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller            bld.mkOp2(OP_OR, TYPE_U8, pred, su->getPredicate(), su->getSrc(2));
16514506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         } else {
16524506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller            bld.mkOp2(OP_AND, TYPE_U8, pred, su->getPredicate(), su->getSrc(2));
16534506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller            pred->getInsn()->src(1).mod = Modifier(NV50_IR_MOD_NOT);
16544506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         }
16554506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      }
16564506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      Instruction *red = bld.mkOp(OP_ATOM, su->dType, su->getDef(0));
16574506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      red->subOp = su->subOp;
16584506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      if (!gMemBase)
16594506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         gMemBase = bld.mkSymbol(FILE_MEMORY_GLOBAL, 0, TYPE_U32, 0);
16604506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      red->setSrc(0, gMemBase);
16614506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      red->setSrc(1, su->getSrc(3));
16624506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      if (su->subOp == NV50_IR_SUBOP_ATOM_CAS)
16634506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         red->setSrc(2, su->getSrc(4));
16644506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      red->setIndirect(0, 0, su->getSrc(0));
16654506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      red->setPredicate(cc, pred);
16664506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      delete_Instruction(bld.getProgram(), su);
166775f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      handleCasExch(red, true);
16684506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   } else {
16694506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      su->sType = (su->tex.target == TEX_TARGET_BUFFER) ? TYPE_U32 : TYPE_U8;
16704506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   }
16714506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller}
16724506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller
1673c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumillerbool
167457594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::handleWRSV(Instruction *i)
167557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
167657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Instruction *st;
167757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Symbol *sym;
167857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   uint32_t addr;
167957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
168057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   // must replace, $sreg are not writeable
168157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   addr = targ->getSVAddress(FILE_SHADER_OUTPUT, i->getSrc(0)->asSym());
168257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (addr >= 0x400)
168357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return false;
168457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   sym = bld.mkSymbol(FILE_SHADER_OUTPUT, 0, i->sType, addr);
168557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
168657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   st = bld.mkStore(OP_EXPORT, i->dType, sym, i->getIndirect(0, 0),
168757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller                    i->getSrc(1));
168857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   st->perPatch = i->perPatch;
168957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
169057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   bld.getBB()->remove(i);
169157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
169257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
169357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
169457594065c30feec9376be9b2132659f7d87362eeChristoph Bumillervoid
169557594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::readTessCoord(LValue *dst, int c)
169657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
169757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Value *laneid = bld.getSSA();
169857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Value *x, *y;
169957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
170057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   bld.mkOp1(OP_RDSV, TYPE_U32, laneid, bld.mkSysVal(SV_LANEID, 0));
170157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
170257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (c == 0) {
170357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      x = dst;
170457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      y = NULL;
170557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   } else
170657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (c == 1) {
170757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      x = NULL;
170857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      y = dst;
170957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   } else {
171057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      assert(c == 2);
171157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      x = bld.getSSA();
171257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      y = bld.getSSA();
171357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
171457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (x)
171557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      bld.mkFetch(x, TYPE_F32, FILE_SHADER_OUTPUT, 0x2f0, NULL, laneid);
171657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (y)
17173fc2818f2b9e8a19e5349442e50dcee4858452c6Christoph Bumiller      bld.mkFetch(y, TYPE_F32, FILE_SHADER_OUTPUT, 0x2f4, NULL, laneid);
171857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
171957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (c == 2) {
172057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      bld.mkOp2(OP_ADD, TYPE_F32, dst, x, y);
172157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      bld.mkOp2(OP_SUB, TYPE_F32, dst, bld.loadImm(NULL, 1.0f), dst);
172257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
172357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
172457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
172557594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
172657594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::handleRDSV(Instruction *i)
172757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
172857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Symbol *sym = i->getSrc(0)->asSym();
1729ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller   const SVSemantic sv = sym->reg.data.sv.sv;
173057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Value *vtx = NULL;
173157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Instruction *ld;
173257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   uint32_t addr = targ->getSVAddress(FILE_SHADER_INPUT, sym);
173357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
1734ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller   if (addr >= 0x400) {
1735ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller      // mov $sreg
1736ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller      if (sym->reg.data.sv.index == 3) {
1737ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller         // TGSI backend may use 4th component of TID,NTID,CTAID,NCTAID
1738ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller         i->op = OP_MOV;
1739ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller         i->setSrc(0, bld.mkImm((sv == SV_NTID || sv == SV_NCTAID) ? 1 : 0));
1740ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller      }
17417cf2bffe8254de6808202d866598ec4c9afe1a51Ilia Mirkin      if (sv == SV_VERTEX_COUNT) {
17427cf2bffe8254de6808202d866598ec4c9afe1a51Ilia Mirkin         bld.setPosition(i, true);
17437cf2bffe8254de6808202d866598ec4c9afe1a51Ilia Mirkin         bld.mkOp2(OP_EXTBF, TYPE_U32, i->getDef(0), i->getDef(0), bld.mkImm(0x808));
17447cf2bffe8254de6808202d866598ec4c9afe1a51Ilia Mirkin      }
174557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return true;
1746ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller   }
174757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
1748ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller   switch (sv) {
174957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case SV_POSITION:
175057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      assert(prog->getType() == Program::TYPE_FRAGMENT);
1751acaed8f41d3cf57092f3fe3a607b8069c72b57f1Ilia Mirkin      if (i->srcExists(1)) {
1752acaed8f41d3cf57092f3fe3a607b8069c72b57f1Ilia Mirkin         // Pass offset through to the interpolation logic
1753acaed8f41d3cf57092f3fe3a607b8069c72b57f1Ilia Mirkin         ld = bld.mkInterp(NV50_IR_INTERP_LINEAR | NV50_IR_INTERP_OFFSET,
1754acaed8f41d3cf57092f3fe3a607b8069c72b57f1Ilia Mirkin                           i->getDef(0), addr, NULL);
1755acaed8f41d3cf57092f3fe3a607b8069c72b57f1Ilia Mirkin         ld->setSrc(1, i->getSrc(1));
1756acaed8f41d3cf57092f3fe3a607b8069c72b57f1Ilia Mirkin      } else {
1757acaed8f41d3cf57092f3fe3a607b8069c72b57f1Ilia Mirkin         bld.mkInterp(NV50_IR_INTERP_LINEAR, i->getDef(0), addr, NULL);
1758acaed8f41d3cf57092f3fe3a607b8069c72b57f1Ilia Mirkin      }
175952c8c52b222e1fdb4c1f4ca3dedde9cd7b9c321fChristoph Bumiller      break;
176052c8c52b222e1fdb4c1f4ca3dedde9cd7b9c321fChristoph Bumiller   case SV_FACE:
176152c8c52b222e1fdb4c1f4ca3dedde9cd7b9c321fChristoph Bumiller   {
176252c8c52b222e1fdb4c1f4ca3dedde9cd7b9c321fChristoph Bumiller      Value *face = i->getDef(0);
176352c8c52b222e1fdb4c1f4ca3dedde9cd7b9c321fChristoph Bumiller      bld.mkInterp(NV50_IR_INTERP_FLAT, face, addr, NULL);
176452c8c52b222e1fdb4c1f4ca3dedde9cd7b9c321fChristoph Bumiller      if (i->dType == TYPE_F32) {
1765354206f407fffd5f0b553dcbcc46b178d0b22c47Ilia Mirkin         bld.mkOp2(OP_OR, TYPE_U32, face, face, bld.mkImm(0x00000001));
1766354206f407fffd5f0b553dcbcc46b178d0b22c47Ilia Mirkin         bld.mkOp1(OP_NEG, TYPE_S32, face, face);
1767354206f407fffd5f0b553dcbcc46b178d0b22c47Ilia Mirkin         bld.mkCvt(OP_CVT, TYPE_F32, face, TYPE_S32, face);
176852c8c52b222e1fdb4c1f4ca3dedde9cd7b9c321fChristoph Bumiller      }
176952c8c52b222e1fdb4c1f4ca3dedde9cd7b9c321fChristoph Bumiller   }
177057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      break;
177157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case SV_TESS_COORD:
177257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      assert(prog->getType() == Program::TYPE_TESSELLATION_EVAL);
177357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      readTessCoord(i->getDef(0)->asLValue(), i->getSrc(0)->reg.data.sv.index);
177457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      break;
1775ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller   case SV_NTID:
1776ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller   case SV_NCTAID:
1777ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller   case SV_GRIDID:
1778ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller      assert(targ->getChipset() >= NVISA_GK104_CHIPSET); // mov $sreg otherwise
1779ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller      if (sym->reg.data.sv.index == 3) {
1780ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller         i->op = OP_MOV;
1781ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller         i->setSrc(0, bld.mkImm(sv == SV_GRIDID ? 0 : 1));
1782ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller         return true;
1783ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller      }
1784ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller      addr += prog->driver->prop.cp.gridInfoBase;
1785ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller      bld.mkLoad(TYPE_U32, i->getDef(0),
178626cc411db87f924003f227874d7a047dd8b5e5a4Samuel Pitoiset                 bld.mkSymbol(FILE_MEMORY_CONST, prog->driver->io.auxCBSlot,
178726cc411db87f924003f227874d7a047dd8b5e5a4Samuel Pitoiset                              TYPE_U32, addr), NULL);
1788ae59a7d35d2b6f23634617dc91e1baf85c9d6d81Christoph Bumiller      break;
1789af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin   case SV_SAMPLE_INDEX:
1790af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin      // TODO: Properly pass source as an address in the PIX address space
1791af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin      // (which can be of the form [r0+offset]). But this is currently
1792af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin      // unnecessary.
1793af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin      ld = bld.mkOp1(OP_PIXLD, TYPE_U32, i->getDef(0), bld.mkImm(0));
1794af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin      ld->subOp = NV50_IR_SUBOP_PIXLD_SAMPLEID;
1795af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin      break;
1796af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin   case SV_SAMPLE_POS: {
1797af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin      Value *off = new_LValue(func, FILE_GPR);
1798af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin      ld = bld.mkOp1(OP_PIXLD, TYPE_U32, i->getDef(0), bld.mkImm(0));
1799af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin      ld->subOp = NV50_IR_SUBOP_PIXLD_SAMPLEID;
1800af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin      bld.mkOp2(OP_SHL, TYPE_U32, off, i->getDef(0), bld.mkImm(3));
1801af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin      bld.mkLoad(TYPE_F32,
1802af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin                 i->getDef(0),
1803af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin                 bld.mkSymbol(
1804d86933e6f42b9c2f5bb617c66c91795c560a9abdSamuel Pitoiset                       FILE_MEMORY_CONST, prog->driver->io.auxCBSlot,
1805af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin                       TYPE_U32, prog->driver->io.sampleInfoBase +
1806af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin                       4 * sym->reg.data.sv.index),
1807af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin                 off);
1808af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin      break;
1809af38ef907c89ecb1125bf258cafa0793f79a5eb7Ilia Mirkin   }
1810b3a2398aded19e25124a4a1d228eb3843827f6b2Ilia Mirkin   case SV_SAMPLE_MASK:
1811b3a2398aded19e25124a4a1d228eb3843827f6b2Ilia Mirkin      ld = bld.mkOp1(OP_PIXLD, TYPE_U32, i->getDef(0), bld.mkImm(0));
1812b3a2398aded19e25124a4a1d228eb3843827f6b2Ilia Mirkin      ld->subOp = NV50_IR_SUBOP_PIXLD_COVMASK;
1813b3a2398aded19e25124a4a1d228eb3843827f6b2Ilia Mirkin      break;
1814517a93b346e720082e22e358b63b5dbc5c42aa09Ilia Mirkin   case SV_BASEVERTEX:
1815517a93b346e720082e22e358b63b5dbc5c42aa09Ilia Mirkin   case SV_BASEINSTANCE:
1816517a93b346e720082e22e358b63b5dbc5c42aa09Ilia Mirkin   case SV_DRAWID:
1817517a93b346e720082e22e358b63b5dbc5c42aa09Ilia Mirkin      ld = bld.mkLoad(TYPE_U32, i->getDef(0),
1818517a93b346e720082e22e358b63b5dbc5c42aa09Ilia Mirkin                      bld.mkSymbol(FILE_MEMORY_CONST,
1819517a93b346e720082e22e358b63b5dbc5c42aa09Ilia Mirkin                                   prog->driver->io.auxCBSlot,
1820517a93b346e720082e22e358b63b5dbc5c42aa09Ilia Mirkin                                   TYPE_U32,
1821517a93b346e720082e22e358b63b5dbc5c42aa09Ilia Mirkin                                   prog->driver->io.drawInfoBase +
1822517a93b346e720082e22e358b63b5dbc5c42aa09Ilia Mirkin                                   4 * (sv - SV_BASEVERTEX)),
1823517a93b346e720082e22e358b63b5dbc5c42aa09Ilia Mirkin                      NULL);
1824517a93b346e720082e22e358b63b5dbc5c42aa09Ilia Mirkin      break;
182557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   default:
18267e0036a49258326cc2d875f2960d18c6b3665036Ilia Mirkin      if (prog->getType() == Program::TYPE_TESSELLATION_EVAL && !i->perPatch)
182757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         vtx = bld.mkOp1v(OP_PFETCH, TYPE_U32, bld.getSSA(), bld.mkImm(0));
182857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      ld = bld.mkFetch(i->getDef(0), i->dType,
182957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller                       FILE_SHADER_INPUT, addr, i->getIndirect(0, 0), vtx);
183057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      ld->perPatch = i->perPatch;
183157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      break;
183257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
183357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   bld.getBB()->remove(i);
183457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
183557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
183657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
183757594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
183857594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::handleDIV(Instruction *i)
183957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
184057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (!isFloatType(i->dType))
184157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return true;
1842b5f2c0505fd4f66422e034b041cdf0bc3dc46e99Christoph Bumiller   bld.setPosition(i, false);
1843b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   Instruction *rcp = bld.mkOp1(OP_RCP, i->dType, bld.getSSA(typeSizeof(i->dType)), i->getSrc(1));
184457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   i->op = OP_MUL;
184557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   i->setSrc(1, rcp->getDef(0));
184657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
184757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
184857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
184957594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
185057594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::handleMOD(Instruction *i)
185157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
1852b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   if (!isFloatType(i->dType))
185357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return true;
1854b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   LValue *value = bld.getScratch(typeSizeof(i->dType));
1855b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   bld.mkOp1(OP_RCP, i->dType, value, i->getSrc(1));
1856b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   bld.mkOp2(OP_MUL, i->dType, value, i->getSrc(0), value);
1857b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   bld.mkOp1(OP_TRUNC, i->dType, value, value);
1858b87b498b88c51fb8c80901b8f581331d3fbcd972Ilia Mirkin   bld.mkOp2(OP_MUL, i->dType, value, i->getSrc(1), value);
185957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   i->op = OP_SUB;
186057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   i->setSrc(1, value);
186157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
186257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
186357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
186457594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
186557594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::handleSQRT(Instruction *i)
186657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
1867c1e4a6bfbf015801c6a8b0ae694482421a22c2d9Ilia Mirkin   if (i->dType == TYPE_F64) {
1868c1e4a6bfbf015801c6a8b0ae694482421a22c2d9Ilia Mirkin      Value *pred = bld.getSSA(1, FILE_PREDICATE);
18699184d9a0bbe8a8b88d676a20f95d66ceee9eaf21Pierre Moreau      Value *zero = bld.loadImm(NULL, 0.0);
1870c1e4a6bfbf015801c6a8b0ae694482421a22c2d9Ilia Mirkin      Value *dst = bld.getSSA(8);
1871c1e4a6bfbf015801c6a8b0ae694482421a22c2d9Ilia Mirkin      bld.mkOp1(OP_RSQ, i->dType, dst, i->getSrc(0));
1872c1e4a6bfbf015801c6a8b0ae694482421a22c2d9Ilia Mirkin      bld.mkCmp(OP_SET, CC_LE, i->dType, pred, i->dType, i->getSrc(0), zero);
1873c1e4a6bfbf015801c6a8b0ae694482421a22c2d9Ilia Mirkin      bld.mkOp3(OP_SELP, TYPE_U64, dst, zero, dst, pred);
1874c1e4a6bfbf015801c6a8b0ae694482421a22c2d9Ilia Mirkin      i->op = OP_MUL;
1875c1e4a6bfbf015801c6a8b0ae694482421a22c2d9Ilia Mirkin      i->setSrc(1, dst);
1876c1e4a6bfbf015801c6a8b0ae694482421a22c2d9Ilia Mirkin      // TODO: Handle this properly with a library function
1877c1e4a6bfbf015801c6a8b0ae694482421a22c2d9Ilia Mirkin   } else {
1878c1e4a6bfbf015801c6a8b0ae694482421a22c2d9Ilia Mirkin      bld.setPosition(i, true);
1879c1e4a6bfbf015801c6a8b0ae694482421a22c2d9Ilia Mirkin      i->op = OP_RSQ;
1880c1e4a6bfbf015801c6a8b0ae694482421a22c2d9Ilia Mirkin      bld.mkOp1(OP_RCP, i->dType, i->getDef(0), i->getDef(0));
1881c1e4a6bfbf015801c6a8b0ae694482421a22c2d9Ilia Mirkin   }
188257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
188357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
188457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
188557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
188657594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
188757594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::handlePOW(Instruction *i)
188857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
188957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   LValue *val = bld.getScratch();
189057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
189157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   bld.mkOp1(OP_LG2, TYPE_F32, val, i->getSrc(0));
189257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   bld.mkOp2(OP_MUL, TYPE_F32, val, i->getSrc(1), val)->dnz = 1;
189357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   bld.mkOp1(OP_PREEX2, TYPE_F32, val, val);
189457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
189557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   i->op = OP_EX2;
189657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   i->setSrc(0, val);
189757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   i->setSrc(1, NULL);
189857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
189957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
190057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
190157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
190257594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
190357594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::handleEXPORT(Instruction *i)
190457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
190557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (prog->getType() == Program::TYPE_FRAGMENT) {
190657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      int id = i->getSrc(0)->reg.data.offset / 4;
190757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
19089362d4bc0a03860ec386156cf499e855a9c2d2a5Christoph Bumiller      if (i->src(0).isIndirect(0)) // TODO, ugly
190957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller         return false;
191057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      i->op = OP_MOV;
191100fe442253744c4c4e7e68da44d6983da053968bChristoph Bumiller      i->subOp = NV50_IR_SUBOP_MOV_FINAL;
19129362d4bc0a03860ec386156cf499e855a9c2d2a5Christoph Bumiller      i->src(0).set(i->src(1));
191357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      i->setSrc(1, NULL);
191457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      i->setDef(0, new_LValue(func, FILE_GPR));
191557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      i->getDef(0)->reg.data.id = id;
191657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
191757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      prog->maxGPR = MAX2(prog->maxGPR, id);
191857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   } else
191957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (prog->getType() == Program::TYPE_GEOMETRY) {
192057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      i->setIndirect(0, 1, gpEmitAddress);
192157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
192257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
192357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
192457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
192557594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
192657594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::handleOUT(Instruction *i)
192757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
19282f2467cb23ce19770c95ce1f004dc11750dffc6dIlia Mirkin   Instruction *prev = i->prev;
19292f2467cb23ce19770c95ce1f004dc11750dffc6dIlia Mirkin   ImmediateValue stream, prevStream;
19302f2467cb23ce19770c95ce1f004dc11750dffc6dIlia Mirkin
19312f2467cb23ce19770c95ce1f004dc11750dffc6dIlia Mirkin   // Only merge if the stream ids match. Also, note that the previous
19322f2467cb23ce19770c95ce1f004dc11750dffc6dIlia Mirkin   // instruction would have already been lowered, so we take arg1 from it.
19332f2467cb23ce19770c95ce1f004dc11750dffc6dIlia Mirkin   if (i->op == OP_RESTART && prev && prev->op == OP_EMIT &&
19342f2467cb23ce19770c95ce1f004dc11750dffc6dIlia Mirkin       i->src(0).getImmediate(stream) &&
19352f2467cb23ce19770c95ce1f004dc11750dffc6dIlia Mirkin       prev->src(1).getImmediate(prevStream) &&
19362f2467cb23ce19770c95ce1f004dc11750dffc6dIlia Mirkin       stream.reg.data.u32 == prevStream.reg.data.u32) {
193757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      i->prev->subOp = NV50_IR_SUBOP_EMIT_RESTART;
193857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      delete_Instruction(prog, i);
193957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   } else {
194057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      assert(gpEmitAddress);
194157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      i->setDef(0, gpEmitAddress);
19422f2467cb23ce19770c95ce1f004dc11750dffc6dIlia Mirkin      i->setSrc(1, i->getSrc(0));
194357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      i->setSrc(0, gpEmitAddress);
194457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
194557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return true;
194657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
194757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
194857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller// Generate a binary predicate if an instruction is predicated by
194957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller// e.g. an f32 value.
195057594065c30feec9376be9b2132659f7d87362eeChristoph Bumillervoid
195157594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::checkPredicate(Instruction *insn)
195257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
195357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Value *pred = insn->getPredicate();
195457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   Value *pdst;
195557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
195657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (!pred || pred->reg.file == FILE_PREDICATE)
195757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return;
195857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   pdst = new_LValue(func, FILE_PREDICATE);
195957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
196057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   // CAUTION: don't use pdst->getInsn, the definition might not be unique,
196157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   //  delay turning PSET(FSET(x,y),0) into PSET(x,y) to a later pass
196257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
1963bbe3d6dc29f218e4d790e5ea359d3c6736e94226Dave Airlie   bld.mkCmp(OP_SET, CC_NEU, insn->dType, pdst, insn->dType, bld.mkImm(0), pred);
196457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
196557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   insn->setPredicate(insn->cc, pdst);
196657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
196757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
196857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller//
196957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller// - add quadop dance for texturing
197057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller// - put FP outputs in GPRs
197157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller// - convert instruction sequences
197257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller//
197357594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
197457594065c30feec9376be9b2132659f7d87362eeChristoph BumillerNVC0LoweringPass::visit(Instruction *i)
197557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
19769d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin   bool ret = true;
1977405bd00f3c98cb78d1dda1f3bf5d74155b18cd57Christoph Bumiller   bld.setPosition(i, false);
197857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
197957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (i->cc != CC_ALWAYS)
198057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      checkPredicate(i);
198157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
198257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   switch (i->op) {
198357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_TEX:
198457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_TXB:
198557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_TXL:
198657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_TXF:
198757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_TXG:
198857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return handleTEX(i->asTex());
198957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_TXD:
199057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return handleTXD(i->asTex());
1991423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin   case OP_TXLQ:
1992423f64e83ab5b1ea7de475ae80300a8408522743Ilia Mirkin      return handleTXLQ(i->asTex());
199330cb66cd745fc793a2349f1d17046c50cd51c558Christoph Bumiller   case OP_TXQ:
199430cb66cd745fc793a2349f1d17046c50cd51c558Christoph Bumiller     return handleTXQ(i->asTex());
199557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_EX2:
199657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      bld.mkOp1(OP_PREEX2, TYPE_F32, i->getDef(0), i->getSrc(0));
199757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      i->setSrc(0, i->getDef(0));
199857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      break;
199957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_POW:
200057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return handlePOW(i);
200157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_DIV:
200257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return handleDIV(i);
200357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_MOD:
200457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return handleMOD(i);
200557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_SQRT:
200657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return handleSQRT(i);
200757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_EXPORT:
20089d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin      ret = handleEXPORT(i);
20099d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin      break;
201057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_EMIT:
201157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_RESTART:
201257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return handleOUT(i);
201357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_RDSV:
201457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return handleRDSV(i);
201557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_WRSV:
201657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return handleWRSV(i);
2017c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin   case OP_STORE:
201857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   case OP_LOAD:
20199362d4bc0a03860ec386156cf499e855a9c2d2a5Christoph Bumiller      if (i->src(0).getFile() == FILE_SHADER_INPUT) {
2020d105b3df14283a4dd80cecc1e6cab58432368ef6Christoph Bumiller         if (prog->getType() == Program::TYPE_COMPUTE) {
2021d105b3df14283a4dd80cecc1e6cab58432368ef6Christoph Bumiller            i->getSrc(0)->reg.file = FILE_MEMORY_CONST;
2022d105b3df14283a4dd80cecc1e6cab58432368ef6Christoph Bumiller            i->getSrc(0)->reg.fileIndex = 0;
2023b3f82e1a63e8a58f0e7ac297fc5e94ebe76c3339Bryan Cain         } else
2024b3f82e1a63e8a58f0e7ac297fc5e94ebe76c3339Bryan Cain         if (prog->getType() == Program::TYPE_GEOMETRY &&
2025b3f82e1a63e8a58f0e7ac297fc5e94ebe76c3339Bryan Cain             i->src(0).isIndirect(0)) {
2026b3f82e1a63e8a58f0e7ac297fc5e94ebe76c3339Bryan Cain            // XXX: this assumes vec4 units
2027b3f82e1a63e8a58f0e7ac297fc5e94ebe76c3339Bryan Cain            Value *ptr = bld.mkOp2v(OP_SHL, TYPE_U32, bld.getSSA(),
2028b3f82e1a63e8a58f0e7ac297fc5e94ebe76c3339Bryan Cain                                    i->getIndirect(0, 0), bld.mkImm(4));
2029b3f82e1a63e8a58f0e7ac297fc5e94ebe76c3339Bryan Cain            i->setIndirect(0, 0, ptr);
2030217301843aea0299ab245e260b20af7ad250e9d8Ilia Mirkin            i->op = OP_VFETCH;
2031d105b3df14283a4dd80cecc1e6cab58432368ef6Christoph Bumiller         } else {
2032d105b3df14283a4dd80cecc1e6cab58432368ef6Christoph Bumiller            i->op = OP_VFETCH;
2033d105b3df14283a4dd80cecc1e6cab58432368ef6Christoph Bumiller            assert(prog->getType() != Program::TYPE_FRAGMENT); // INTERP
2034d105b3df14283a4dd80cecc1e6cab58432368ef6Christoph Bumiller         }
20350ddc28b026688df79e54d3af1d7914ff04b12fedIlia Mirkin      } else if (i->src(0).getFile() == FILE_MEMORY_CONST) {
20360ddc28b026688df79e54d3af1d7914ff04b12fedIlia Mirkin         if (i->src(0).isIndirect(1)) {
20370ddc28b026688df79e54d3af1d7914ff04b12fedIlia Mirkin            Value *ptr;
20380ddc28b026688df79e54d3af1d7914ff04b12fedIlia Mirkin            if (i->src(0).isIndirect(0))
20390ddc28b026688df79e54d3af1d7914ff04b12fedIlia Mirkin               ptr = bld.mkOp3v(OP_INSBF, TYPE_U32, bld.getSSA(),
20400ddc28b026688df79e54d3af1d7914ff04b12fedIlia Mirkin                                i->getIndirect(0, 1), bld.mkImm(0x1010),
20410ddc28b026688df79e54d3af1d7914ff04b12fedIlia Mirkin                                i->getIndirect(0, 0));
20420ddc28b026688df79e54d3af1d7914ff04b12fedIlia Mirkin            else
20430ddc28b026688df79e54d3af1d7914ff04b12fedIlia Mirkin               ptr = bld.mkOp2v(OP_SHL, TYPE_U32, bld.getSSA(),
20440ddc28b026688df79e54d3af1d7914ff04b12fedIlia Mirkin                                i->getIndirect(0, 1), bld.mkImm(16));
20450ddc28b026688df79e54d3af1d7914ff04b12fedIlia Mirkin            i->setIndirect(0, 1, NULL);
20460ddc28b026688df79e54d3af1d7914ff04b12fedIlia Mirkin            i->setIndirect(0, 0, ptr);
20470ddc28b026688df79e54d3af1d7914ff04b12fedIlia Mirkin            i->subOp = NV50_IR_SUBOP_LDC_IS;
20480ddc28b026688df79e54d3af1d7914ff04b12fedIlia Mirkin         }
2049e3e2df01bf855f3b435e03224a762649081c6558Ilia Mirkin      } else if (i->src(0).getFile() == FILE_SHADER_OUTPUT) {
2050e3e2df01bf855f3b435e03224a762649081c6558Ilia Mirkin         assert(prog->getType() == Program::TYPE_TESSELLATION_CONTROL);
2051e3e2df01bf855f3b435e03224a762649081c6558Ilia Mirkin         i->op = OP_VFETCH;
2052c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin      } else if (i->src(0).getFile() == FILE_MEMORY_GLOBAL) {
20537b9a77b905bda3003dc57efb99879499ebc4ba41Ilia Mirkin         Value *ind = i->getIndirect(0, 1);
2054b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset         Value *ptr = loadBufInfo64(ind, i->getSrc(0)->reg.fileIndex * 16);
2055c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin         // XXX come up with a way not to do this for EVERY little access but
2056c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin         // rather to batch these up somehow. Unfortunately we've lost the
2057c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin         // information about the field width by the time we get here.
2058c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin         Value *offset = bld.loadImm(NULL, i->getSrc(0)->reg.data.offset + typeSizeof(i->sType));
2059b8b3af2932039c6105d61f6922157a250ed8b79aSamuel Pitoiset         Value *length = loadBufLength32(ind, i->getSrc(0)->reg.fileIndex * 16);
2060c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin         Value *pred = new_LValue(func, FILE_PREDICATE);
2061c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin         if (i->src(0).isIndirect(0)) {
2062c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin            bld.mkOp2(OP_ADD, TYPE_U64, ptr, ptr, i->getIndirect(0, 0));
2063c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin            bld.mkOp2(OP_ADD, TYPE_U32, offset, offset, i->getIndirect(0, 0));
2064c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin         }
20657b9a77b905bda3003dc57efb99879499ebc4ba41Ilia Mirkin         i->setIndirect(0, 1, NULL);
2066c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin         i->setIndirect(0, 0, ptr);
2067c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin         bld.mkCmp(OP_SET, CC_GT, TYPE_U32, pred, TYPE_U32, offset, length);
2068c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin         i->setPredicate(CC_NOT_P, pred);
2069c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin         if (i->defExists(0)) {
2070c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin            bld.mkMov(i->getDef(0), bld.mkImm(0));
2071c3083c70823d8f4bfdabcf38f98dfebeff0a2b2bIlia Mirkin         }
207257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      }
207357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      break;
2074c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller   case OP_ATOM:
207575f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller   {
207675f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      const bool cctl = i->src(0).getFile() == FILE_MEMORY_GLOBAL;
2077c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller      handleATOM(i);
207875f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller      handleCasExch(i, cctl);
207975f1f852b00ad0d766684d01695322b93a2acd55Christoph Bumiller   }
2080c0fc3463e9be19495ed31018fc093e726d5f4fbbChristoph Bumiller      break;
20814506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case OP_SULDB:
20824506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case OP_SULDP:
20834506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case OP_SUSTB:
20844506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case OP_SUSTP:
20854506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case OP_SUREDB:
20864506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller   case OP_SUREDP:
20874506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      if (targ->getChipset() >= NVISA_GK104_CHIPSET)
20884506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller         handleSurfaceOpNVE4(i->asTex());
20894506ed28de7f9d76bbc99c0758a7891b84528729Christoph Bumiller      break;
20902c4eeb0b5cf17caa06cb3fa46d4f64e6a8005d23Ilia Mirkin   case OP_SUQ:
20912c4eeb0b5cf17caa06cb3fa46d4f64e6a8005d23Ilia Mirkin      handleSUQ(i);
20922c4eeb0b5cf17caa06cb3fa46d4f64e6a8005d23Ilia Mirkin      break;
209357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   default:
209457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      break;
20956bca283ad5ebdd85e268c6757842b3c808c6b73dJohannes Obermayr   }
20969d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin
20979d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin   /* Kepler+ has a special opcode to compute a new base address to be used
20989d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin    * for indirect loads.
20999d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin    */
21009d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin   if (targ->getChipset() >= NVISA_GK104_CHIPSET && !i->perPatch &&
21019d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin       (i->op == OP_VFETCH || i->op == OP_EXPORT) && i->src(0).isIndirect(0)) {
21029d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin      Instruction *afetch = bld.mkOp1(OP_AFETCH, TYPE_U32, bld.getSSA(),
21039d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin                                      cloneShallow(func, i->getSrc(0)));
21049d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin      afetch->setIndirect(0, 0, i->getIndirect(0, 0));
21059d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin      i->src(0).get()->reg.data.offset = 0;
21069d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin      i->setIndirect(0, 0, afetch->getDef(0));
21079d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin   }
21089d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin
21099d60793a03e40e1d139b78fce0144cad57438741Ilia Mirkin   return ret;
211057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
211157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
211257594065c30feec9376be9b2132659f7d87362eeChristoph Bumillerbool
211357594065c30feec9376be9b2132659f7d87362eeChristoph BumillerTargetNVC0::runLegalizePass(Program *prog, CGStage stage) const
211457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller{
211557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (stage == CG_STAGE_PRE_SSA) {
211657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      NVC0LoweringPass pass(prog);
211757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return pass.run(prog, false, true);
211857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   } else
211957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (stage == CG_STAGE_POST_RA) {
2120e44089b2f79aa2dcaacf348911433d1e21235c0cChristoph Bumiller      NVC0LegalizePostRA pass(prog);
212157594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return pass.run(prog, false, true);
212257594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   } else
212357594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   if (stage == CG_STAGE_SSA) {
212457594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      NVC0LegalizeSSA pass;
212557594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller      return pass.run(prog, false, true);
212657594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   }
212757594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller   return false;
212857594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller}
212957594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller
213057594065c30feec9376be9b2132659f7d87362eeChristoph Bumiller} // namespace nv50_ir
2131