From e0371e63df173be38a086a5d816eeaf0e8cbe7eb Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Fri, 5 Feb 2016 15:09:07 +0100 Subject: [PATCH] nv50/ir: make OP_SELP a compare instruction This OP_SELP insn will be used to handle compare and swap subops. Changes from v2: - fix logic for GK110+ Signed-off-by: Samuel Pitoiset Reviewed-by: Ilia Mirkin --- .../drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp | 12 ++++++++---- .../drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp | 13 +++++++++---- .../drivers/nouveau/codegen/nv50_ir_inlines.h | 4 ++-- 3 files changed, 19 insertions(+), 10 deletions(-) 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 4bb4e5240e6..8268e08b118 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp @@ -112,7 +112,7 @@ private: void emitSET(const CmpInstruction *); void emitSLCT(const CmpInstruction *); - void emitSELP(const Instruction *); + void emitSELP(const CmpInstruction *); void emitTEXBAR(const Instruction *); void emitTEX(const TexInstruction *); @@ -433,6 +433,10 @@ CodeEmitterGK110::emitForm_21(const Instruction *i, uint32_t opc2, srcId(i->src(s), s ? ((s == 2) ? 42 : s1) : 10); break; default: + if (i->op == OP_SELP) { + assert(s == 2 && i->src(s).getFile() == FILE_PREDICATE); + srcId(i->src(s), 42); + } // ignore here, can be predicate or flags, but must not be address break; } @@ -1041,11 +1045,11 @@ CodeEmitterGK110::emitSLCT(const CmpInstruction *i) } } -void CodeEmitterGK110::emitSELP(const Instruction *i) +void CodeEmitterGK110::emitSELP(const CmpInstruction *i) { emitForm_21(i, 0x250, 0x050); - if ((i->cc == CC_NOT_P) ^ (bool)(i->src(2).mod & Modifier(NV50_IR_MOD_NOT))) + if ((i->setCond == CC_NOT_P) ^ (bool)(i->src(2).mod & Modifier(NV50_IR_MOD_NOT))) code[1] |= 1 << 13; } @@ -1933,7 +1937,7 @@ CodeEmitterGK110::emitInstruction(Instruction *insn) emitSET(insn->asCmp()); break; case OP_SELP: - emitSELP(insn); + emitSELP(insn->asCmp()); break; case OP_SLCT: emitSLCT(insn->asCmp()); diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp index a7c49a24efb..d588d7e8845 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp @@ -120,7 +120,7 @@ private: void emitSET(const CmpInstruction *); void emitSLCT(const CmpInstruction *); - void emitSELP(const Instruction *); + void emitSELP(const CmpInstruction *); void emitTEXBAR(const Instruction *); void emitTEX(const TexInstruction *); @@ -398,6 +398,11 @@ CodeEmitterNVC0::emitForm_A(const Instruction *i, uint64_t opc) srcId(i->src(s), s ? ((s == 2) ? 49 : s1) : 20); break; default: + if (i->op == OP_SELP) { + // OP_SELP is used to implement shared+atomics on Fermi. + assert(s == 2 && i->src(s).getFile() == FILE_PREDICATE); + srcId(i->src(s), 49); + } // ignore here, can be predicate or flags, but must not be address break; } @@ -1170,11 +1175,11 @@ CodeEmitterNVC0::emitSLCT(const CmpInstruction *i) code[0] |= 1 << 5; } -void CodeEmitterNVC0::emitSELP(const Instruction *i) +void CodeEmitterNVC0::emitSELP(const CmpInstruction *i) { emitForm_A(i, HEX64(20000000, 00000004)); - if (i->cc == CC_NOT_P || i->src(2).mod & Modifier(NV50_IR_MOD_NOT)) + if (i->setCond == CC_NOT_P || i->src(2).mod & Modifier(NV50_IR_MOD_NOT)) code[1] |= 1 << 20; } @@ -2433,7 +2438,7 @@ CodeEmitterNVC0::emitInstruction(Instruction *insn) emitSET(insn->asCmp()); break; case OP_SELP: - emitSELP(insn); + emitSELP(insn->asCmp()); break; case OP_SLCT: emitSLCT(insn->asCmp()); diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h b/src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h index e465f24845b..02e6157e65b 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h @@ -281,14 +281,14 @@ Value *TexInstruction::getIndirectS() const CmpInstruction *Instruction::asCmp() { - if (op >= OP_SET_AND && op <= OP_SLCT && op != OP_SELP) + if (op >= OP_SET_AND && op <= OP_SLCT) return static_cast(this); return NULL; } const CmpInstruction *Instruction::asCmp() const { - if (op >= OP_SET_AND && op <= OP_SLCT && op != OP_SELP) + if (op >= OP_SET_AND && op <= OP_SLCT) return static_cast(this); return NULL; } -- 2.30.2