From df043f076464d817a9d88c4c43757e65b6eae3f9 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sun, 10 Jan 2016 21:47:04 -0500 Subject: [PATCH] nvc0/ir: fix atomic compare-and-swap arguments Teach the emitter that the two registers are sequential, and drop the second arg entirely, in favor of a double-wide first argument. Signed-off-by: Ilia Mirkin --- src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp | 6 ++++-- src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp | 4 ++-- .../drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) 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 0b28047e22b..6cf69e5339f 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp @@ -2021,8 +2021,10 @@ CodeEmitterNVC0::emitATOM(const Instruction *i) code[0] |= 63 << 20; } - if (i->subOp == NV50_IR_SUBOP_ATOM_CAS) - srcId(i->src(2), 32 + 17); + if (i->subOp == NV50_IR_SUBOP_ATOM_CAS) { + assert(i->src(1).getSize() == 2 * typeSizeof(i->sType)); + code[1] |= (SDATA(i->src(1)).id + 1) << 17; + } } void diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp index 735e2891cf2..947d97be7f1 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp @@ -2435,13 +2435,13 @@ Converter::handleATOM(Value *dst0[4], DataType ty, uint16_t subOp) else sym = makeSym(TGSI_FILE_BUFFER, r, -1, c, 0); insn = mkOp2(OP_ATOM, ty, dst, sym, fetchSrc(2, c)); + if (subOp == NV50_IR_SUBOP_ATOM_CAS) + insn->setSrc(2, fetchSrc(3, 0)); if (tgsi.getSrc(1).getFile() != TGSI_FILE_IMMEDIATE) insn->setIndirect(0, 0, off); if (tgsi.getSrc(0).isIndirect(0)) insn->setIndirect(0, 1, fetchSrc(tgsi.getSrc(0).getIndirect(0), 0, 0)); insn->subOp = subOp; - if (subOp == NV50_IR_SUBOP_ATOM_CAS) - insn->setSrc(2, fetchSrc(3, 0)); } for (int c = 0; c < 4; ++c) if (dst0[c]) diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp index 0a77dce85c2..e7cb54bc426 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp @@ -1086,7 +1086,7 @@ NVC0LoweringPass::handleCasExch(Instruction *cas, bool needCctl) cctl->setPredicate(cas->cc, cas->getPredicate()); } - if (cas->defExists(0) && cas->subOp == NV50_IR_SUBOP_ATOM_CAS) { + if (cas->subOp == NV50_IR_SUBOP_ATOM_CAS) { // CAS is crazy. It's 2nd source is a double reg, and the 3rd source // should be set to the high part of the double reg or bad things will // happen elsewhere in the universe. @@ -1096,6 +1096,7 @@ NVC0LoweringPass::handleCasExch(Instruction *cas, bool needCctl) bld.setPosition(cas, false); bld.mkOp2(OP_MERGE, TYPE_U64, dreg, cas->getSrc(1), cas->getSrc(2)); cas->setSrc(1, dreg); + cas->setSrc(2, dreg); } return true; -- 2.30.2