diff options
author | Ilia Mirkin <[email protected]> | 2017-02-04 22:29:17 -0500 |
---|---|---|
committer | Ilia Mirkin <[email protected]> | 2017-02-09 12:57:48 -0500 |
commit | 22c705ea8ce6317b039b01a6f593f565eb9789e1 (patch) | |
tree | cc7694ec078c7159173dc85835e5c7ea1a165f51 /src | |
parent | 2e986fa80688b22657201d483888ddbc5d2be19b (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.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp | 24 | ||||
-rw-r--r-- | src/gallium/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 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(); |