void emitLOAD(const Instruction *);
void emitSTORE(const Instruction *);
void emitMOV(const Instruction *);
+ void emitMEMBAR(const Instruction *);
void emitINTERP(const Instruction *);
+ void emitAFETCH(const Instruction *);
void emitPFETCH(const Instruction *);
void emitVFETCH(const Instruction *);
void emitEXPORT(const Instruction *);
void emitPIXLD(const Instruction *);
+ void emitBAR(const Instruction *);
+
void emitFlow(const Instruction *);
inline void defId(const ValueDef&, const int pos);
if (isLIMM(i->src(1), TYPE_S32)) {
emitForm_L(i, 0x280, 2, Modifier(0));
- assert(i->subOp != NV50_IR_SUBOP_MUL_HIGH);
-
+ if (i->subOp == NV50_IR_SUBOP_MUL_HIGH)
+ code[1] |= 1 << 24;
if (i->sType == TYPE_S32)
code[1] |= 3 << 25;
} else {
if (i->sType == TYPE_S32)
code[1] |= (1 << 19) | (1 << 24);
- if (code[0] & 0x1) {
- assert(!i->subOp);
- SAT_(39);
- } else {
- if (i->subOp == NV50_IR_SUBOP_MUL_HIGH)
- code[1] |= 1 << 25;
- SAT_(35);
- }
+ if (i->subOp == NV50_IR_SUBOP_MUL_HIGH)
+ code[1] |= 1 << 25;
+ SAT_(35);
}
void
code[0] |= typeSizeofLog2(dType) << 10;
code[0] |= typeSizeofLog2(i->sType) << 12;
+ code[1] |= i->subOp << 12;
if (isSignedIntType(dType))
code[0] |= 0x4000;
code[0] = (code[0] & ~0xfc) | ((code[0] << 3) & 0xe0);
if (i->defExists(1))
defId(i->def(1), 2);
- else
- code[0] |= 0x1c;
+ else
+ code[0] |= 0x1c;
} else {
switch (i->sType) {
case TYPE_F32: op2 = 0x000; op1 = 0x800; break;
}
FTZ_(3a);
- if (i->dType == TYPE_F32)
- code[1] |= 1 << 23;
+ if (i->dType == TYPE_F32) {
+ if (isFloatType(i->sType))
+ code[1] |= 1 << 23;
+ else
+ code[1] |= 1 << 15;
+ }
}
if (i->sType == TYPE_S32)
code[1] |= 1 << 19;
code[1] |= 0x00070000;
}
+void
+CodeEmitterGK110::emitBAR(const Instruction *i)
+{
+ /* TODO */
+ emitNOP(i);
+}
+
void
CodeEmitterGK110::emitFlow(const Instruction *i)
{
} else
if (mask & 2) {
int32_t pcRel = f->target.bb->binPos - (codeSize + 8);
+ if (writeIssueDelays && !(f->target.bb->binPos & 0x3f))
+ pcRel += 8;
// currently we don't want absolute branches
assert(!f->absolute);
code[0] |= (pcRel & 0x1ff) << 23;
}
}
+void
+CodeEmitterGK110::emitAFETCH(const Instruction *i)
+{
+ uint32_t offset = i->src(0).get()->reg.data.offset & 0x7ff;
+
+ code[0] = 0x00000002 | (offset << 23);
+ code[1] = 0x7d000000 | (offset >> 9);
+
+ if (i->getSrc(0)->reg.file == FILE_SHADER_OUTPUT)
+ code[1] |= 0x8;
+
+ emitPredicate(i);
+
+ defId(i->def(0), 2);
+ srcId(i->src(0).getIndirect(0), 10);
+}
+
void
CodeEmitterGK110::emitPFETCH(const Instruction *i)
{
const int src1 = (i->predSrc == 1) ? 2 : 1; // if predSrc == 1, !srcExists(2)
defId(i->def(0), 2);
- srcId(i, 1, 10);
+ srcId(i, src1, 10);
}
void
code[1] |= (i->ipa & 0xc) << (19 - 2);
}
+static void
+interpApply(const InterpEntry *entry, uint32_t *code,
+ bool force_persample_interp, bool flatshade)
+{
+ int ipa = entry->ipa;
+ int reg = entry->reg;
+ int loc = entry->loc;
+
+ if (flatshade &&
+ (ipa & NV50_IR_INTERP_MODE_MASK) == NV50_IR_INTERP_SC) {
+ ipa = NV50_IR_INTERP_FLAT;
+ reg = 0xff;
+ } else if (force_persample_interp &&
+ (ipa & NV50_IR_INTERP_SAMPLE_MASK) == NV50_IR_INTERP_DEFAULT &&
+ (ipa & NV50_IR_INTERP_MODE_MASK) != NV50_IR_INTERP_FLAT) {
+ ipa |= NV50_IR_INTERP_CENTROID;
+ }
+ code[loc + 1] &= ~(0xf << 19);
+ code[loc + 1] |= (ipa & 0x3) << 21;
+ code[loc + 1] |= (ipa & 0xc) << (19 - 2);
+ code[loc + 0] &= ~(0xff << 23);
+ code[loc + 0] |= reg << 23;
+}
+
void
CodeEmitterGK110::emitINTERP(const Instruction *i)
{
if (i->saturate)
code[1] |= 1 << 18;
- if (i->op == OP_PINTERP)
+ if (i->op == OP_PINTERP) {
srcId(i->src(1), 23);
- else
+ addInterp(i->ipa, SDATA(i->src(1)).id, interpApply);
+ } else {
code[0] |= 0xff << 23;
+ addInterp(i->ipa, 0xff, interpApply);
+ }
srcId(i->src(0).getIndirect(0), 10);
emitInterpMode(i);
case SV_VERTEX_COUNT: return 0x10;
case SV_INVOCATION_ID: return 0x11;
case SV_YDIR: return 0x12;
+ case SV_THREAD_KILL: return 0x13;
case SV_TID: return 0x21 + SDATA(ref).sv.index;
case SV_CTAID: return 0x25 + SDATA(ref).sv.index;
case SV_NTID: return 0x29 + SDATA(ref).sv.index;
}
}
+void CodeEmitterGK110::emitMEMBAR(const Instruction *i)
+{
+ code[0] = 0x00000002 | NV50_IR_SUBOP_MEMBAR_SCOPE(i->subOp) << 8;
+ code[1] = 0x7cc00000;
+
+ emitPredicate(i);
+}
+
bool
CodeEmitterGK110::emitInstruction(Instruction *insn)
{
case OP_EXPORT:
emitEXPORT(insn);
break;
+ case OP_AFETCH:
+ emitAFETCH(insn);
+ break;
case OP_PFETCH:
emitPFETCH(insn);
break;
emitNOP(insn);
insn->join = 1;
break;
+ case OP_BAR:
+ emitBAR(insn);
+ break;
+ case OP_MEMBAR:
+ emitMEMBAR(insn);
+ break;
case OP_PHI:
case OP_UNION:
case OP_CONSTRAINT:
ERROR("operation should have been lowered\n");
return false;
default:
- ERROR("unknow op\n");
+ ERROR("unknown op: %u\n", insn->op);
return false;
}