nv50/ir/emit: handle OP_ATOM
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Wed, 20 Feb 2013 19:54:14 +0000 (20:54 +0100)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Tue, 12 Mar 2013 11:55:35 +0000 (12:55 +0100)
src/gallium/drivers/nv50/codegen/nv50_ir_emit_nv50.cpp

index 90f861590e14fdaf621b0ad142d084d02b4f0426..796c1957eb5f8b9e9f46ae7516088e52dc64dc32 100644 (file)
@@ -122,6 +122,8 @@ private:
 
    void emitFlow(const Instruction *, uint8_t flowOp);
    void emitPRERETEmu(const FlowInstruction *);
+
+   void emitATOM(const Instruction *);
 };
 
 #define SDATA(a) ((a).rep()->reg.data)
@@ -1532,6 +1534,42 @@ CodeEmitterNV50::emitFlow(const Instruction *i, uint8_t flowOp)
    }
 }
 
+void
+CodeEmitterNV50::emitATOM(const Instruction *i)
+{
+   uint8_t subOp;
+   switch (i->subOp) {
+   case NV50_IR_SUBOP_ATOM_ADD:  subOp = 0x0; break;
+   case NV50_IR_SUBOP_ATOM_MIN:  subOp = 0x7; break;
+   case NV50_IR_SUBOP_ATOM_MAX:  subOp = 0x6; break;
+   case NV50_IR_SUBOP_ATOM_INC:  subOp = 0x4; break;
+   case NV50_IR_SUBOP_ATOM_DEC:  subOp = 0x5; break;
+   case NV50_IR_SUBOP_ATOM_AND:  subOp = 0xa; break;
+   case NV50_IR_SUBOP_ATOM_OR:   subOp = 0xb; break;
+   case NV50_IR_SUBOP_ATOM_XOR:  subOp = 0xc; break;
+   case NV50_IR_SUBOP_ATOM_CAS:  subOp = 0x2; break;
+   case NV50_IR_SUBOP_ATOM_EXCH: subOp = 0x1; break;
+   default:
+      assert(!"invalid subop");
+      break;
+   }
+   code[0] = 0xd0000001;
+   code[1] = 0xe0c00000 | (subOp << 2);
+   if (isSignedType(i->dType))
+      code[1] |= 1 << 21;
+
+   // args
+   emitFlagsRd(i);
+   setDst(i, 0);
+   setSrc(i, 1, 1);
+   if (i->subOp == NV50_IR_SUBOP_ATOM_CAS)
+      setSrc(i, 2, 2);
+
+   // g[] pointer
+   code[0] |= i->getSrc(0)->reg.fileIndex << 23;
+   srcId(i->getIndirect(0, 0), 9);
+}
+
 bool
 CodeEmitterNV50::emitInstruction(Instruction *insn)
 {
@@ -1712,6 +1750,9 @@ CodeEmitterNV50::emitInstruction(Instruction *insn)
    case OP_DFDY:
       emitQUADOP(insn, 5, insn->src(0).mod.neg() ? 0x5a : 0xa5);
       break;
+   case OP_ATOM:
+      emitATOM(insn);
+      break;
    case OP_PHI:
    case OP_UNION:
    case OP_CONSTRAINT: