nvc0/ir: add a "high" subop for shifts, emit shf.l/shf.r for 64-bit
authorIlia Mirkin <imirkin@alum.mit.edu>
Sun, 5 Feb 2017 03:29:17 +0000 (22:29 -0500)
committerIlia Mirkin <imirkin@alum.mit.edu>
Thu, 9 Feb 2017 17:57:48 +0000 (12:57 -0500)
Note that this is not available for SM20/SM30.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/gallium/drivers/nouveau/codegen/nv50_ir.h
src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp

index 56e028790cd330f1c2084f98a2c96a229803e366..b7fd19d2a4c0e23495260fb2d221022f3ed2092b 100644 (file)
@@ -175,6 +175,7 @@ enum operation
 #define NV50_IR_SUBOP_LDC_IS       2
 #define NV50_IR_SUBOP_LDC_ISL      3
 #define NV50_IR_SUBOP_SHIFT_WRAP   1
+#define NV50_IR_SUBOP_SHIFT_HIGH   2
 #define NV50_IR_SUBOP_EMU_PRERET   1
 #define NV50_IR_SUBOP_TEXBAR(n)    n
 #define NV50_IR_SUBOP_MOV_FINAL    1
index 4b1caa487543a6315ef075503256aa52410429b1..03286509edb0dd56f2ca3cdab70d2cae0af56b8c 100644 (file)
@@ -109,6 +109,7 @@ private:
    void emitBFIND(const Instruction *);
    void emitPERMT(const Instruction *);
    void emitShift(const Instruction *);
+   void emitShift64(const Instruction *);
 
    void emitSFnOp(const Instruction *, uint8_t subOp);
 
@@ -935,6 +936,24 @@ CodeEmitterGK110::emitShift(const Instruction *i)
       code[1] |= 1 << 10;
 }
 
+void
+CodeEmitterGK110::emitShift64(const Instruction *i)
+{
+   if (i->op == OP_SHR) {
+      emitForm_21(i, 0x27c, 0xc7c);
+      if (isSignedType(i->sType))
+         code[1] |= 0x100;
+      if (i->subOp & NV50_IR_SUBOP_SHIFT_HIGH)
+         code[1] |= 1 << 19;
+   } else {
+      emitForm_21(i, 0xdfc, 0xf7c);
+   }
+   code[1] |= 0x200;
+
+   if (i->subOp & NV50_IR_SUBOP_SHIFT_WRAP)
+      code[1] |= 1 << 21;
+}
+
 void
 CodeEmitterGK110::emitPreOp(const Instruction *i)
 {
@@ -2475,7 +2494,10 @@ CodeEmitterGK110::emitInstruction(Instruction *insn)
       break;
    case OP_SHL:
    case OP_SHR:
-      emitShift(insn);
+      if (typeSizeof(insn->sType) == 8)
+         emitShift64(insn);
+      else
+         emitShift(insn);
       break;
    case OP_SET:
    case OP_SET_AND:
index 21b9ac42c73495b9e9ffbdde110c1e767c69dc94..8fec6a85800a8e224fb45f00bc31cc55ac61ecf4 100644 (file)
@@ -161,6 +161,7 @@ private:
    void emitISETP();
    void emitSHL();
    void emitSHR();
+   void emitSHF();
    void emitPOPC();
    void emitBFI();
    void emitBFE();
@@ -2071,6 +2072,47 @@ CodeEmitterGM107::emitSHR()
    emitGPR  (0x00, insn->def(0));
 }
 
+void
+CodeEmitterGM107::emitSHF()
+{
+   unsigned type;
+
+   switch (insn->src(1).getFile()) {
+   case FILE_GPR:
+      emitInsn(insn->op == OP_SHL ? 0x5bf80000 : 0x5cf80000);
+      emitGPR(0x14, insn->src(1));
+      break;
+   case FILE_IMMEDIATE:
+      emitInsn(insn->op == OP_SHL ? 0x36f80000 : 0x38f80000);
+      emitIMMD(0x14, 19, insn->src(1));
+      break;
+   default:
+      assert(!"bad src1 file");
+      break;
+   }
+
+   switch (insn->sType) {
+   case TYPE_U64:
+      type = 2;
+      break;
+   case TYPE_S64:
+      type = 3;
+      break;
+   default:
+      type = 0;
+      break;
+   }
+
+   emitField(0x32, 1, !!(insn->subOp & NV50_IR_SUBOP_SHIFT_WRAP));
+   emitX    (0x31);
+   emitField(0x30, 1, !!(insn->subOp & NV50_IR_SUBOP_SHIFT_HIGH));
+   emitCC   (0x2f);
+   emitGPR  (0x27, insn->src(2));
+   emitField(0x25, 2, type);
+   emitGPR  (0x08, insn->src(0));
+   emitGPR  (0x00, insn->def(0));
+}
+
 void
 CodeEmitterGM107::emitPOPC()
 {
@@ -3169,10 +3211,16 @@ CodeEmitterGM107::emitInstruction(Instruction *i)
       }
       break;
    case OP_SHL:
-      emitSHL();
+      if (typeSizeof(insn->sType) == 8)
+         emitSHF();
+      else
+         emitSHL();
       break;
    case OP_SHR:
-      emitSHR();
+      if (typeSizeof(insn->sType) == 8)
+         emitSHF();
+      else
+         emitSHR();
       break;
    case OP_POPCNT:
       emitPOPC();