summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorIlia Mirkin <[email protected]>2017-02-04 22:29:17 -0500
committerIlia Mirkin <[email protected]>2017-02-09 12:57:48 -0500
commit22c705ea8ce6317b039b01a6f593f565eb9789e1 (patch)
treecc7694ec078c7159173dc85835e5c7ea1a165f51 /src
parent2e986fa80688b22657201d483888ddbc5d2be19b (diff)
nvc0/ir: add a "high" subop for shifts, emit shf.l/shf.r for 64-bit
Note that this is not available for SM20/SM30. Signed-off-by: Ilia Mirkin <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir.h1
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp24
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp52
3 files changed, 74 insertions, 3 deletions
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir.h b/src/gallium/drivers/nouveau/codegen/nv50_ir.h
index 56e028790cd..b7fd19d2a4c 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir.h
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir.h
@@ -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
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp
index 4b1caa48754..03286509edb 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp
@@ -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);
@@ -936,6 +937,24 @@ CodeEmitterGK110::emitShift(const Instruction *i)
}
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)
{
emitForm_C(i, 0x248, 0x2);
@@ -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:
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp
index 21b9ac42c73..8fec6a85800 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp
@@ -161,6 +161,7 @@ private:
void emitISETP();
void emitSHL();
void emitSHR();
+ void emitSHF();
void emitPOPC();
void emitBFI();
void emitBFE();
@@ -2072,6 +2073,47 @@ CodeEmitterGM107::emitSHR()
}
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()
{
switch (insn->src(0).getFile()) {
@@ -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();