From 22c705ea8ce6317b039b01a6f593f565eb9789e1 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sat, 4 Feb 2017 22:29:17 -0500 Subject: [PATCH] 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 --- src/gallium/drivers/nouveau/codegen/nv50_ir.h | 1 + .../drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp | 24 +++++++++- .../drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp | 52 +++++++++++++++++++++- 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 56e0287..b7fd19d 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 4b1caa4..0328650 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 21b9ac4..8fec6a8 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(); -- 2.7.4