void emitF2I();
void emitI2F();
void emitI2I();
+ void emitSEL();
void emitSHFL();
void emitDADD();
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;
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));
}
CodeEmitterGM107::emitATOM()
{
unsigned dType, subOp;
- 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;
- assert(insn->subOp != NV50_IR_SUBOP_ATOM_CAS); /* XXX */
- emitInsn (0xed000000);
+ 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 (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()
{
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
******************************************************************************/
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:
- emitATOM();
+ if (insn->src(0).getFile() == FILE_MEMORY_SHARED)
+ emitATOMS();
+ else
+ emitATOM();
break;
case OP_CCTL:
emitCCTL();
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();