diff options
author | Ilia Mirkin <imirkin@alum.mit.edu> | 2016-02-04 22:58:48 -0500 |
---|---|---|
committer | Ilia Mirkin <imirkin@alum.mit.edu> | 2016-02-05 00:41:33 -0500 |
commit | 1a0fde1f52c59e0dbada03f387c8e25d9475ebbe (patch) | |
tree | d038162846770c289cecf0ab7f17200fc6282658 /src | |
parent | 2fed18b8a54319f22888e3761a6ed5cd85f9688c (diff) |
nvc0/ir: fix converting between predicate and gpr
The spill logic will insert convert ops when moving between files. It
seems like the emission logic wasn't quite ready for these converts.
Tested on fermi, and visually looked at nvdisasm output for maxwell.
Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Cc: mesa-stable@lists.freedesktop.org
Diffstat (limited to 'src')
3 files changed, 41 insertions, 11 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 17cb484d2b..0c7cd1d813 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp @@ -1947,10 +1947,16 @@ CodeEmitterGK110::emitInstruction(Instruction *insn) case OP_CEIL: case OP_FLOOR: case OP_TRUNC: - case OP_CVT: case OP_SAT: emitCVT(insn); break; + case OP_CVT: + if (insn->def(0).getFile() == FILE_PREDICATE || + insn->src(0).getFile() == FILE_PREDICATE) + emitMOV(insn); + else + emitCVT(insn); + break; case OP_RSQ: emitSFnOp(insn, 5 + 2 * insn->subOp); break; 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 1fa0eb6da6..dee26225b7 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp @@ -673,7 +673,12 @@ CodeEmitterGM107::emitMOV() (insn->sType != TYPE_F32 && !longIMMD(insn->src(0)))) { switch (insn->src(0).getFile()) { case FILE_GPR: - emitInsn(0x5c980000); + if (insn->def(0).getFile() == FILE_PREDICATE) { + emitInsn(0x5b6a0000); + emitGPR (0x08); + } else { + emitInsn(0x5c980000); + } emitGPR (0x14, insn->src(0)); break; case FILE_MEMORY_CONST: @@ -684,18 +689,32 @@ CodeEmitterGM107::emitMOV() emitInsn(0x38980000); emitIMMD(0x14, 19, insn->src(0)); break; + case FILE_PREDICATE: + emitInsn(0x50880000); + emitPRED(0x0c, insn->src(0)); + emitPRED(0x1d); + emitPRED(0x27); + break; default: assert(!"bad src file"); break; } - emitField(0x27, 4, insn->lanes); + if (insn->def(0).getFile() != FILE_PREDICATE && + insn->src(0).getFile() != FILE_PREDICATE) + emitField(0x27, 4, insn->lanes); } else { emitInsn (0x01000000); emitIMMD (0x14, 32, insn->src(0)); emitField(0x0c, 4, insn->lanes); } - emitGPR(0x00, insn->def(0)); + if (insn->def(0).getFile() == FILE_PREDICATE) { + emitPRED(0x27); + emitPRED(0x03, insn->def(0)); + emitPRED(0x00); + } else { + emitGPR(0x00, insn->def(0)); + } } void @@ -2684,11 +2703,7 @@ CodeEmitterGM107::emitInstruction(Instruction *i) emitRAM(); break; case OP_MOV: - if (insn->def(0).getFile() == FILE_GPR && - insn->src(0).getFile() != FILE_PREDICATE) - emitMOV(); - else - assert(!"R2P/P2R"); + emitMOV(); break; case OP_RDSV: emitS2R(); @@ -2700,7 +2715,10 @@ CodeEmitterGM107::emitInstruction(Instruction *i) case OP_CEIL: case OP_TRUNC: case OP_CVT: - if (isFloatType(insn->dType)) { + if (insn->op == OP_CVT && (insn->def(0).getFile() == FILE_PREDICATE || + insn->src(0).getFile() == FILE_PREDICATE)) { + emitMOV(); + } else if (isFloatType(insn->dType)) { if (isFloatType(insn->sType)) emitF2F(); else 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 6cf69e5339..8637db9152 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp @@ -2435,10 +2435,16 @@ CodeEmitterNVC0::emitInstruction(Instruction *insn) case OP_CEIL: case OP_FLOOR: case OP_TRUNC: - case OP_CVT: case OP_SAT: emitCVT(insn); break; + case OP_CVT: + if (insn->def(0).getFile() == FILE_PREDICATE || + insn->src(0).getFile() == FILE_PREDICATE) + emitMOV(insn); + else + emitCVT(insn); + break; case OP_RSQ: emitSFnOp(insn, 5 + 2 * insn->subOp); break; |