diff options
author | Samuel Pitoiset <[email protected]> | 2016-02-05 15:09:07 +0100 |
---|---|---|
committer | Samuel Pitoiset <[email protected]> | 2016-02-21 10:42:29 +0100 |
commit | e0371e63df173be38a086a5d816eeaf0e8cbe7eb (patch) | |
tree | 6f2127b75f65564b5105ce4f642a93039fb57e03 | |
parent | 0c930557bf96721ce50ca95b5201be09da905cb8 (diff) |
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 <[email protected]>
Reviewed-by: Ilia Mirkin <[email protected]>
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<CmpInstruction *>(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<const CmpInstruction *>(this); return NULL; } |