summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp133
-rw-r--r--src/gallium/drivers/nvc0/codegen/nv50_ir_target_nvc0.cpp1
2 files changed, 133 insertions, 1 deletions
diff --git a/src/gallium/drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp b/src/gallium/drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp
index 763d07f759a..66e971558ee 100644
--- a/src/gallium/drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp
+++ b/src/gallium/drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp
@@ -78,6 +78,7 @@ private:
void emitLOAD(const Instruction *);
void emitSTORE(const Instruction *);
void emitMOV(const Instruction *);
+ void emitATOM(const Instruction *);
void emitINTERP(const Instruction *);
void emitPFETCH(const Instruction *);
@@ -98,6 +99,8 @@ private:
void emitLogicOp(const Instruction *, uint8_t subOp);
void emitPOPC(const Instruction *);
void emitINSBF(const Instruction *);
+ void emitEXTBF(const Instruction *);
+ void emitPERMT(const Instruction *);
void emitShift(const Instruction *);
void emitSFnOp(const Instruction *, uint8_t subOp);
@@ -739,7 +742,26 @@ CodeEmitterNVC0::emitPOPC(const Instruction *i)
void
CodeEmitterNVC0::emitINSBF(const Instruction *i)
{
- emitForm_A(i, HEX64(28000000, 30000000));
+ emitForm_A(i, HEX64(28000000, 00000003));
+}
+
+void
+CodeEmitterNVC0::emitEXTBF(const Instruction *i)
+{
+ emitForm_A(i, HEX64(70000000, 00000003));
+
+ if (i->dType == TYPE_S32)
+ code[0] |= 1 << 5;
+ if (i->subOp == NV50_IR_SUBOP_EXTBF_REV)
+ code[0] |= 1 << 8;
+}
+
+void
+CodeEmitterNVC0::emitPERMT(const Instruction *i)
+{
+ emitForm_A(i, HEX64(24000000, 00000004));
+
+ code[0] |= i->subOp << 5;
}
void
@@ -1635,6 +1657,103 @@ CodeEmitterNVC0::emitMOV(const Instruction *i)
}
void
+CodeEmitterNVC0::emitATOM(const Instruction *i)
+{
+ const bool hasDst = i->defExists(0);
+ const bool casOrExch =
+ i->subOp == NV50_IR_SUBOP_ATOM_EXCH ||
+ i->subOp == NV50_IR_SUBOP_ATOM_CAS;
+
+ if (i->dType == TYPE_U64) {
+ switch (i->subOp) {
+ case NV50_IR_SUBOP_ATOM_ADD:
+ code[0] = 0x205;
+ if (hasDst)
+ code[1] = 0x507e0000;
+ else
+ code[1] = 0x10000000;
+ break;
+ case NV50_IR_SUBOP_ATOM_EXCH:
+ code[0] = 0x305;
+ code[1] = 0x507e0000;
+ break;
+ case NV50_IR_SUBOP_ATOM_CAS:
+ code[0] = 0x325;
+ code[1] = 0x50000000;
+ break;
+ default:
+ assert(!"invalid u64 red op");
+ break;
+ }
+ } else
+ if (i->dType == TYPE_U32) {
+ switch (i->subOp) {
+ case NV50_IR_SUBOP_ATOM_EXCH:
+ code[0] = 0x105;
+ code[1] = 0x507e0000;
+ break;
+ case NV50_IR_SUBOP_ATOM_CAS:
+ code[0] = 0x125;
+ code[1] = 0x50000000;
+ break;
+ default:
+ code[0] = 0x5 | (i->subOp << 5);
+ if (hasDst)
+ code[1] = 0x507e0000;
+ else
+ code[1] = 0x10000000;
+ break;
+ }
+ } else
+ if (i->dType == TYPE_S32) {
+ assert(i->subOp <= 2);
+ code[0] = 0x205 | (i->subOp << 5);
+ if (hasDst)
+ code[1] = 0x587e0000;
+ else
+ code[1] = 0x18000000;
+ } else
+ if (i->dType == TYPE_F32) {
+ assert(i->subOp == NV50_IR_SUBOP_ATOM_ADD);
+ code[0] = 0x205;
+ if (hasDst)
+ code[1] = 0x687e0000;
+ else
+ code[1] = 0x28000000;
+ }
+
+ emitPredicate(i);
+
+ srcId(i->src(1), 14);
+
+ if (hasDst)
+ defId(i->def(0), 32 + 11);
+ else
+ if (casOrExch)
+ code[1] |= 63 << 11;
+
+ if (hasDst || casOrExch) {
+ const int32_t offset = SDATA(i->src(0)).offset;
+ assert(offset < 0x80000 && offset >= -0x80000);
+ code[0] |= offset << 26;
+ code[1] |= (offset & 0x1ffc0) >> 6;
+ code[1] |= (offset & 0xe0000) << 6;
+ } else {
+ srcAddr32(i->src(0), 26);
+ }
+ if (i->getIndirect(0, 0)) {
+ srcId(i->getIndirect(0, 0), 20);
+ if (i->getIndirect(0, 0)->reg.size == 8)
+ code[1] |= 1 << 26;
+ } else {
+ code[0] |= 63 << 20;
+ }
+
+ if (i->subOp == NV50_IR_SUBOP_ATOM_CAS)
+ srcId(i->src(2), 32 + 17);
+}
+
+void
CodeEmitterNVC0::emitSUCLAMPMode(uint16_t subOp)
{
uint8_t m;
@@ -2047,6 +2166,9 @@ CodeEmitterNVC0::emitInstruction(Instruction *insn)
else
ERROR("SUSTx not yet supported on < nve4\n");
break;
+ case OP_ATOM:
+ emitATOM(insn);
+ break;
case OP_BRA:
case OP_CALL:
case OP_PRERET:
@@ -2075,6 +2197,15 @@ CodeEmitterNVC0::emitInstruction(Instruction *insn)
case OP_POPCNT:
emitPOPC(insn);
break;
+ case OP_INSBF:
+ emitINSBF(insn);
+ break;
+ case OP_EXTBF:
+ emitEXTBF(insn);
+ break;
+ case OP_PERMT:
+ emitPERMT(insn);
+ break;
case OP_JOIN:
emitNOP(insn);
insn->join = 1;
diff --git a/src/gallium/drivers/nvc0/codegen/nv50_ir_target_nvc0.cpp b/src/gallium/drivers/nvc0/codegen/nv50_ir_target_nvc0.cpp
index a37e4ef35dd..802bd2556c8 100644
--- a/src/gallium/drivers/nvc0/codegen/nv50_ir_target_nvc0.cpp
+++ b/src/gallium/drivers/nvc0/codegen/nv50_ir_target_nvc0.cpp
@@ -246,6 +246,7 @@ static const struct opProperties _initProps[] =
{ OP_DFDY, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0 },
{ OP_CALL, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0 },
{ OP_INSBF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4 },
+ { OP_PERMT, 0x0, 0x0, 0x0, 0x0, 0x6, 0x2 },
{ OP_SET_AND, 0x3, 0x3, 0x0, 0x0, 0x2, 0x2 },
{ OP_SET_OR, 0x3, 0x3, 0x0, 0x0, 0x2, 0x2 },
{ OP_SET_XOR, 0x3, 0x3, 0x0, 0x0, 0x2, 0x2 },