void emitF2I();
void emitI2F();
void emitI2I();
+ void emitSEL();
void emitSHFL();
void emitDADD();
void emitISBERD();
void emitAL2P();
void emitIPA();
+ void emitATOM();
+ void emitATOMS();
+ void emitCCTL();
void emitPIXLD();
void emitNOP();
void emitKIL();
void emitOUT();
+
+ void emitBAR();
+ void emitMEMBAR();
+
+ void emitVOTE();
};
/*******************************************************************************
case SV_INVOCATION_ID : id = 0x11; break;
case SV_THREAD_KILL : id = 0x13; break;
case SV_INVOCATION_INFO: id = 0x1d; break;
+ case SV_TID : id = 0x21 + val->reg.data.sv.index; break;
+ case SV_CTAID : id = 0x25 + val->reg.data.sv.index; break;
default:
assert(!"invalid system value");
id = 0;
(insn->sType != TYPE_F32 && !longIMMD(insn->src(0)))) {
switch (insn->src(0).getFile()) {
case FILE_GPR:
- emitInsn(0x5c980000);
+ if (insn->def(0).getFile() == FILE_PREDICATE) {
+ emitInsn(0x5b6a0000);
+ emitGPR (0x08);
+ } else {
+ emitInsn(0x5c980000);
+ }
emitGPR (0x14, insn->src(0));
break;
case FILE_MEMORY_CONST:
emitInsn(0x38980000);
emitIMMD(0x14, 19, insn->src(0));
break;
+ case FILE_PREDICATE:
+ emitInsn(0x50880000);
+ emitPRED(0x0c, insn->src(0));
+ emitPRED(0x1d);
+ emitPRED(0x27);
+ break;
default:
assert(!"bad src file");
break;
}
- emitField(0x27, 4, insn->lanes);
+ if (insn->def(0).getFile() != FILE_PREDICATE &&
+ insn->src(0).getFile() != FILE_PREDICATE)
+ emitField(0x27, 4, insn->lanes);
} else {
emitInsn (0x01000000);
emitIMMD (0x14, 32, insn->src(0));
emitField(0x0c, 4, insn->lanes);
}
- emitGPR(0x00, insn->def(0));
+ if (insn->def(0).getFile() == FILE_PREDICATE) {
+ emitPRED(0x27);
+ emitPRED(0x03, insn->def(0));
+ emitPRED(0x00);
+ } else {
+ emitGPR(0x00, insn->def(0));
+ }
}
void
emitGPR (0x00, insn->def(0));
}
+void
+CodeEmitterGM107::emitSEL()
+{
+ switch (insn->src(1).getFile()) {
+ case FILE_GPR:
+ emitInsn(0x5ca00000);
+ emitGPR (0x14, insn->src(1));
+ break;
+ case FILE_MEMORY_CONST:
+ emitInsn(0x4ca00000);
+ emitCBUF(0x22, -1, 0x14, 16, 2, insn->src(1));
+ break;
+ case FILE_IMMEDIATE:
+ emitInsn(0x38a00000);
+ emitIMMD(0x14, 19, insn->src(1));
+ break;
+ default:
+ assert(!"bad src1 file");
+ break;
+ }
+
+ emitPRED(0x27, insn->src(2));
+ emitGPR (0x08, insn->src(0));
+ emitGPR (0x00, insn->def(0));
+}
+
void
CodeEmitterGM107::emitSHFL()
{
emitRND (0x27);
emitField(0x26, 1, insn->lanes); /* abused for .ndv */
emitField(0x1c, 8, insn->subOp);
- emitGPR (0x14, insn->src(1));
+ if (insn->predSrc != 1)
+ emitGPR (0x14, insn->src(1));
+ else
+ emitGPR (0x14);
emitGPR (0x08, insn->src(0));
emitGPR (0x00, insn->def(0));
}
break;
}
emitPRED (0x30);
+ emitX (0x2b);
emitField(0x29, 2, lop);
emitINV (0x28, insn->src(1));
emitINV (0x27, insn->src(0));
} else {
emitInsn (0x04000000);
+ emitX (0x39);
emitINV (0x38, insn->src(1));
emitINV (0x37, insn->src(0));
emitField(0x35, 2, lop);
emitNEG(0x31, insn->src(0));
emitNEG(0x30, insn->src(1));
emitCC (0x2f);
+ emitX (0x2b);
} else {
emitInsn(0x1c000000);
emitSAT (0x36);
+ emitX (0x35);
emitCC (0x34);
emitIMMD(0x14, 32, insn->src(1));
}
emitGPR(0x27);
}
+void
+CodeEmitterGM107::emitATOM()
+{
+ unsigned dType, subOp;
+
+ if (insn->subOp == NV50_IR_SUBOP_ATOM_CAS) {
+ switch (insn->dType) {
+ case TYPE_U32: dType = 0; break;
+ case TYPE_U64: dType = 1; break;
+ default: assert(!"unexpected dType"); dType = 0; break;
+ }
+ subOp = 15;
+
+ emitInsn (0xee000000);
+ } else {
+ switch (insn->dType) {
+ case TYPE_U32: dType = 0; break;
+ case TYPE_S32: dType = 1; break;
+ case TYPE_U64: dType = 2; break;
+ case TYPE_F32: dType = 3; break;
+ case TYPE_B128: dType = 4; break;
+ case TYPE_S64: dType = 5; break;
+ default: assert(!"unexpected dType"); dType = 0; break;
+ }
+ if (insn->subOp == NV50_IR_SUBOP_ATOM_EXCH)
+ subOp = 8;
+ else
+ subOp = insn->subOp;
+
+ emitInsn (0xed000000);
+ }
+
+ emitField(0x34, 4, subOp);
+ emitField(0x31, 3, dType);
+ emitField(0x30, 1, insn->src(0).getIndirect(0)->getSize() == 8);
+ emitGPR (0x14, insn->src(1));
+ emitADDR (0x08, 0x1c, 20, 0, insn->src(0));
+ emitGPR (0x00, insn->def(0));
+}
+
+void
+CodeEmitterGM107::emitATOMS()
+{
+ unsigned dType, subOp;
+
+ if (insn->subOp == NV50_IR_SUBOP_ATOM_CAS) {
+ switch (insn->dType) {
+ case TYPE_U32: dType = 0; break;
+ case TYPE_U64: dType = 1; break;
+ default: assert(!"unexpected dType"); dType = 0; break;
+ }
+ subOp = 4;
+
+ emitInsn (0xee000000);
+ emitField(0x34, 1, dType);
+ } else {
+ switch (insn->dType) {
+ case TYPE_U32: dType = 0; break;
+ case TYPE_S32: dType = 1; break;
+ case TYPE_U64: dType = 2; break;
+ case TYPE_S64: dType = 3; break;
+ default: assert(!"unexpected dType"); dType = 0; break;
+ }
+
+ if (insn->subOp == NV50_IR_SUBOP_ATOM_EXCH)
+ subOp = 8;
+ else
+ subOp = insn->subOp;
+
+ emitInsn (0xec000000);
+ emitField(0x1c, 3, dType);
+ }
+
+ emitField(0x34, 4, subOp);
+ emitGPR (0x14, insn->src(1));
+ emitADDR (0x08, 0x12, 22, 0, insn->src(0));
+ emitGPR (0x00, insn->def(0));
+}
+
+void
+CodeEmitterGM107::emitCCTL()
+{
+ unsigned width;
+ if (insn->src(0).getFile() == FILE_MEMORY_GLOBAL) {
+ emitInsn(0xef600000);
+ width = 30;
+ } else {
+ emitInsn(0xef800000);
+ width = 22;
+ }
+ emitField(0x34, 1, insn->src(0).getIndirect(0)->getSize() == 8);
+ emitADDR (0x08, 0x16, width, 2, insn->src(0));
+ emitField(0x00, 4, insn->subOp);
+}
+
/*******************************************************************************
* surface
******************************************************************************/
emitGPR (0x00, insn->def(0));
}
+void
+CodeEmitterGM107::emitBAR()
+{
+ uint8_t subop;
+
+ emitInsn (0xf0a80000);
+
+ switch (insn->subOp) {
+ case NV50_IR_SUBOP_BAR_RED_POPC: subop = 0x02; break;
+ case NV50_IR_SUBOP_BAR_RED_AND: subop = 0x0a; break;
+ case NV50_IR_SUBOP_BAR_RED_OR: subop = 0x12; break;
+ case NV50_IR_SUBOP_BAR_ARRIVE: subop = 0x81; break;
+ default:
+ subop = 0x80;
+ assert(insn->subOp == NV50_IR_SUBOP_BAR_SYNC);
+ break;
+ }
+
+ emitField(0x20, 8, subop);
+
+ // barrier id
+ if (insn->src(0).getFile() == FILE_GPR) {
+ emitGPR(0x08, insn->src(0));
+ } else {
+ ImmediateValue *imm = insn->getSrc(0)->asImm();
+ assert(imm);
+ emitField(0x08, 8, imm->reg.data.u32);
+ emitField(0x2b, 1, 1);
+ }
+
+ // thread count
+ if (insn->src(1).getFile() == FILE_GPR) {
+ emitGPR(0x14, insn->src(1));
+ } else {
+ ImmediateValue *imm = insn->getSrc(0)->asImm();
+ assert(imm);
+ emitField(0x14, 12, imm->reg.data.u32);
+ emitField(0x2c, 1, 1);
+ }
+
+ if (insn->srcExists(2) && (insn->predSrc != 2)) {
+ emitPRED (0x27, insn->src(2));
+ emitField(0x2a, 1, insn->src(2).mod == Modifier(NV50_IR_MOD_NOT));
+ } else {
+ emitField(0x27, 3, 7);
+ }
+}
+
+void
+CodeEmitterGM107::emitMEMBAR()
+{
+ emitInsn (0xef980000);
+ emitField(0x08, 2, insn->subOp >> 2);
+}
+
+void
+CodeEmitterGM107::emitVOTE()
+{
+ int subOp;
+
+ assert(insn->src(0).getFile() == FILE_PREDICATE &&
+ insn->def(1).getFile() == FILE_PREDICATE);
+
+ switch (insn->subOp) {
+ case NV50_IR_SUBOP_VOTE_ANY: subOp = 1; break;
+ default:
+ assert(insn->subOp == NV50_IR_SUBOP_VOTE_ALL);
+ subOp = 0;
+ break;
+ }
+
+ emitInsn (0x50d80000);
+ emitField(0x30, 2, subOp);
+ emitGPR (0x00, insn->def(0));
+ emitPRED (0x2d, insn->def(1));
+ emitField(0x2a, 1, insn->src(0).mod == Modifier(NV50_IR_MOD_NOT));
+ emitPRED (0x27, insn->src(0));
+}
+
/*******************************************************************************
* assembler front-end
******************************************************************************/
emitRAM();
break;
case OP_MOV:
- if (insn->def(0).getFile() == FILE_GPR &&
- insn->src(0).getFile() != FILE_PREDICATE)
- emitMOV();
- else
- assert(!"R2P/P2R");
+ emitMOV();
break;
case OP_RDSV:
emitS2R();
case OP_CEIL:
case OP_TRUNC:
case OP_CVT:
- if (isFloatType(insn->dType)) {
+ if (insn->op == OP_CVT && (insn->def(0).getFile() == FILE_PREDICATE ||
+ insn->src(0).getFile() == FILE_PREDICATE)) {
+ emitMOV();
+ } else if (isFloatType(insn->dType)) {
if (isFloatType(insn->sType))
emitF2F();
else
emitISETP();
}
break;
+ case OP_SELP:
+ emitSEL();
+ break;
case OP_PRESIN:
case OP_PREEX2:
emitRRO();
case FILE_MEMORY_SHARED: emitSTS(); break;
case FILE_MEMORY_GLOBAL: emitST(); break;
default:
- assert(!"invalid load");
+ assert(!"invalid store");
emitNOP();
break;
}
break;
+ case OP_ATOM:
+ if (insn->src(0).getFile() == FILE_MEMORY_SHARED)
+ emitATOMS();
+ else
+ emitATOM();
+ break;
+ case OP_CCTL:
+ emitCCTL();
+ break;
case OP_VFETCH:
emitALD();
break;
case OP_RESTART:
emitOUT();
break;
+ case OP_BAR:
+ emitBAR();
+ break;
+ case OP_MEMBAR:
+ emitMEMBAR();
+ break;
+ case OP_VOTE:
+ emitVOTE();
+ break;
default:
assert(!"invalid opcode");
emitNOP();