}
}
+static uint16_t opcodeToSubOp(uint opcode)
+{
+ switch (opcode) {
+ case TGSI_OPCODE_LFENCE: return NV50_IR_SUBOP_MEMBAR(L, GL);
+ case TGSI_OPCODE_SFENCE: return NV50_IR_SUBOP_MEMBAR(S, GL);
+ case TGSI_OPCODE_MFENCE: return NV50_IR_SUBOP_MEMBAR(M, GL);
+ case TGSI_OPCODE_ATOMUADD: return NV50_IR_SUBOP_ATOM_ADD;
+ case TGSI_OPCODE_ATOMXCHG: return NV50_IR_SUBOP_ATOM_EXCH;
+ case TGSI_OPCODE_ATOMCAS: return NV50_IR_SUBOP_ATOM_CAS;
+ case TGSI_OPCODE_ATOMAND: return NV50_IR_SUBOP_ATOM_AND;
+ case TGSI_OPCODE_ATOMOR: return NV50_IR_SUBOP_ATOM_OR;
+ case TGSI_OPCODE_ATOMXOR: return NV50_IR_SUBOP_ATOM_XOR;
+ case TGSI_OPCODE_ATOMUMIN: return NV50_IR_SUBOP_ATOM_MIN;
+ case TGSI_OPCODE_ATOMIMIN: return NV50_IR_SUBOP_ATOM_MIN;
+ case TGSI_OPCODE_ATOMUMAX: return NV50_IR_SUBOP_ATOM_MAX;
+ case TGSI_OPCODE_ATOMIMAX: return NV50_IR_SUBOP_ATOM_MAX;
+ default:
+ return 0;
+ }
+}
+
bool Instruction::checkDstSrcAliasing() const
{
if (insn->Dst[0].Register.Indirect) // no danger if indirect, using memory
{
Instruction insn(inst);
+ if (insn.getOpcode() == TGSI_OPCODE_BARRIER)
+ info->numBarriers = 1;
+
if (insn.dstCount()) {
if (insn.getDst(0).getFile() == TGSI_FILE_OUTPUT) {
Instruction::DstRegister dst = insn.getDst(0);
bool
Converter::handleInstruction(const struct tgsi_full_instruction *insn)
{
+ Instruction *geni;
+
Value *dst0[4], *rDst0[4];
Value *src0, *src1, *src2;
Value *val0, *val1;
case TGSI_OPCODE_STORE:
handleSTORE();
break;
- case TGSI_OPCODE_ATOMUADD:
- handleATOM(dst0, dstTy, NV50_IR_SUBOP_ATOM_ADD);
+ case TGSI_OPCODE_BARRIER:
+ geni = mkOp2(OP_BAR, TYPE_U32, NULL, mkImm(0), mkImm(0));
+ geni->fixed = 1;
+ geni->subOp = NV50_IR_SUBOP_BAR_SYNC;
break;
- case TGSI_OPCODE_ATOMXCHG:
- handleATOM(dst0, dstTy, NV50_IR_SUBOP_ATOM_EXCH);
+ case TGSI_OPCODE_MFENCE:
+ case TGSI_OPCODE_LFENCE:
+ case TGSI_OPCODE_SFENCE:
+ geni = mkOp(OP_MEMBAR, TYPE_NONE, NULL);
+ geni->fixed = 1;
+ geni->subOp = tgsi::opcodeToSubOp(tgsi.getOpcode());
break;
+ case TGSI_OPCODE_ATOMUADD:
+ case TGSI_OPCODE_ATOMXCHG:
case TGSI_OPCODE_ATOMCAS:
- handleATOM(dst0, dstTy, NV50_IR_SUBOP_ATOM_CAS);
- break;
case TGSI_OPCODE_ATOMAND:
- handleATOM(dst0, dstTy, NV50_IR_SUBOP_ATOM_AND);
- break;
case TGSI_OPCODE_ATOMOR:
- handleATOM(dst0, dstTy, NV50_IR_SUBOP_ATOM_OR);
- break;
case TGSI_OPCODE_ATOMXOR:
- handleATOM(dst0, dstTy, NV50_IR_SUBOP_ATOM_XOR);
- break;
case TGSI_OPCODE_ATOMUMIN:
case TGSI_OPCODE_ATOMIMIN:
- handleATOM(dst0, dstTy, NV50_IR_SUBOP_ATOM_MIN);
- break;
case TGSI_OPCODE_ATOMUMAX:
case TGSI_OPCODE_ATOMIMAX:
- handleATOM(dst0, dstTy, NV50_IR_SUBOP_ATOM_MAX);
+ handleATOM(dst0, dstTy, tgsi::opcodeToSubOp(tgsi.getOpcode()));
break;
default:
ERROR("unhandled TGSI opcode: %u\n", tgsi.getOpcode());
void emitSTORE(const Instruction *);
void emitMOV(const Instruction *);
void emitATOM(const Instruction *);
+ void emitMEMBAR(const Instruction *);
void emitINTERP(const Instruction *);
void emitPFETCH(const Instruction *);
void emitQUADOP(const Instruction *, uint8_t qOp, uint8_t laneMask);
void emitFlow(const Instruction *);
+ void emitBAR(const Instruction *);
void emitSUCLAMPMode(uint16_t);
void emitSUCalc(Instruction *);
}
}
+void
+CodeEmitterNVC0::emitBAR(const Instruction *i)
+{
+ Value *rDef = NULL, *pDef = NULL;
+
+ switch (i->subOp) {
+ case NV50_IR_SUBOP_BAR_ARRIVE: code[0] = 0x84; break;
+ case NV50_IR_SUBOP_BAR_RED_AND: code[0] = 0x24; break;
+ case NV50_IR_SUBOP_BAR_RED_OR: code[0] = 0x44; break;
+ case NV50_IR_SUBOP_BAR_RED_POPC: code[0] = 0x04; break;
+ default:
+ code[0] = 0x04;
+ assert(i->subOp == NV50_IR_SUBOP_BAR_SYNC);
+ break;
+ }
+ code[1] = 0x50000000;
+
+ code[0] |= 63 << 14;
+ code[1] |= 7 << 21;
+
+ emitPredicate(i);
+
+ // barrier id
+ if (i->src(0).getFile() == FILE_GPR) {
+ srcId(i->src(0), 20);
+ } else {
+ ImmediateValue *imm = i->getSrc(0)->asImm();
+ assert(imm);
+ code[0] |= imm->reg.data.u32 << 20;
+ }
+
+ // thread count
+ if (i->src(1).getFile() == FILE_GPR) {
+ srcId(i->src(1), 26);
+ } else {
+ ImmediateValue *imm = i->getSrc(1)->asImm();
+ assert(imm);
+ code[0] |= imm->reg.data.u32 << 26;
+ code[1] |= imm->reg.data.u32 >> 6;
+ }
+
+ if (i->srcExists(2) && (i->predSrc != 2)) {
+ srcId(i->src(2), 32 + 17);
+ if (i->src(2).mod == Modifier(NV50_IR_MOD_NOT))
+ code[1] |= 1 << 20;
+ } else {
+ code[1] |= 7 << 17;
+ }
+
+ if (i->defExists(0)) {
+ if (i->def(0).getFile() == FILE_GPR)
+ rDef = i->getDef(0);
+ else
+ pDef = i->getDef(0);
+
+ if (i->defExists(1)) {
+ if (i->def(1).getFile() == FILE_GPR)
+ rDef = i->getDef(1);
+ else
+ pDef = i->getDef(1);
+ }
+ }
+ if (rDef) {
+ code[0] &= ~(63 << 14);
+ defId(rDef, 14);
+ }
+ if (pDef) {
+ code[1] &= ~(7 << 21);
+ defId(pDef, 32 + 21);
+ }
+}
+
void
CodeEmitterNVC0::emitPFETCH(const Instruction *i)
{
srcId(i->src(2), 32 + 17);
}
+void
+CodeEmitterNVC0::emitMEMBAR(const Instruction *i)
+{
+ switch (NV50_IR_SUBOP_MEMBAR_SCOPE(i->subOp)) {
+ case NV50_IR_SUBOP_MEMBAR_CTA: code[0] = 0x05; break;
+ case NV50_IR_SUBOP_MEMBAR_GL: code[0] = 0x25; break;
+ default:
+ code[0] = 0x45;
+ assert(NV50_IR_SUBOP_MEMBAR_SCOPE(i->subOp) == NV50_IR_SUBOP_MEMBAR_SYS);
+ break;
+ }
+ code[1] = 0xe0000000;
+
+ emitPredicate(i);
+}
+
void
CodeEmitterNVC0::emitSUCLAMPMode(uint16_t subOp)
{
emitNOP(insn);
insn->join = 1;
break;
+ case OP_BAR:
+ emitBAR(insn);
+ break;
+ case OP_MEMBAR:
+ emitMEMBAR(insn);
+ break;
case OP_VSHL:
emitVSHL(insn);
break;