From c893b9406060d3735b2c9e307ae89f6d83a4be40 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Fri, 22 Feb 2013 20:08:57 +0100 Subject: nv50/ir: add support for indirect BRA,CALL --- src/gallium/drivers/nv50/codegen/nv50_ir.cpp | 2 +- src/gallium/drivers/nv50/codegen/nv50_ir.h | 1 + src/gallium/drivers/nv50/codegen/nv50_ir_print.cpp | 4 ++++ src/gallium/drivers/nv50/codegen/nv50_ir_ra.cpp | 9 ++++++--- .../drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp | 19 +++++++++++++++++-- 5 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir.cpp index 3121c5ff270..b8476665806 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir.cpp +++ b/src/gallium/drivers/nv50/codegen/nv50_ir.cpp @@ -968,7 +968,7 @@ FlowInstruction::FlowInstruction(Function *fn, operation op, void *targ) if (op == OP_JOIN) terminator = targ ? 1 : 0; - allWarp = absolute = limit = builtin = 0; + allWarp = absolute = limit = builtin = indirect = 0; } FlowInstruction * diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir.h b/src/gallium/drivers/nv50/codegen/nv50_ir.h index ae577cc4209..47562beb2fd 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir.h +++ b/src/gallium/drivers/nv50/codegen/nv50_ir.h @@ -918,6 +918,7 @@ public: unsigned absolute : 1; unsigned limit : 1; unsigned builtin : 1; // true for calls to emulation code + unsigned indirect : 1; // target in src(0) union { BasicBlock *bb; diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_print.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_print.cpp index 48ade15842d..00a80544c17 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir_print.cpp +++ b/src/gallium/drivers/nv50/codegen/nv50_ir_print.cpp @@ -500,6 +500,10 @@ void Instruction::print() const if (asFlow()) { PRINT("%s", operationStr[op]); + if (asFlow()->indirect) + PRINT(" ind"); + if (asFlow()->absolute) + PRINT(" abs"); if (op == OP_CALL && asFlow()->builtin) { PRINT(" %sBUILTIN:%i", colour[TXT_BRA], asFlow()->target.builtin); } else diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_ra.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_ra.cpp index e0fea4b9337..ed991dac30b 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir_ra.cpp +++ b/src/gallium/drivers/nv50/codegen/nv50_ir_ra.cpp @@ -409,14 +409,17 @@ RegAlloc::ArgumentMovesPass::visit(BasicBlock *bb) // conflict arises. for (Instruction *i = bb->getEntry(); i; i = i->next) { FlowInstruction *cal = i->asFlow(); - if (!cal || cal->op != OP_CALL || cal->builtin) + // TODO: Handle indirect calls. + // Right now they should only be generated for builtins. + if (!cal || cal->op != OP_CALL || cal->builtin || cal->indirect) continue; RegisterSet clobberSet(prog->getTarget()); // Bind input values. - for (int s = 0; cal->srcExists(s); ++s) { + for (int s = cal->indirect ? 1 : 0; cal->srcExists(s); ++s) { + const int t = cal->indirect ? (s - 1) : s; LValue *tmp = new_LValue(func, cal->getSrc(s)->asLValue()); - tmp->reg.data.id = cal->target.fn->ins[s].rep()->reg.data.id; + tmp->reg.data.id = cal->target.fn->ins[t].rep()->reg.data.id; Instruction *mov = new_Instruction(func, OP_MOV, typeOfSize(tmp->reg.size)); diff --git a/src/gallium/drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp b/src/gallium/drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp index dc1fe99bde6..763d07f759a 100644 --- a/src/gallium/drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp +++ b/src/gallium/drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp @@ -1192,8 +1192,8 @@ CodeEmitterNVC0::emitFlow(const Instruction *i) break; case OP_CALL: code[1] = f->absolute ? 0x10000000 : 0x50000000; - if (i->srcExists(0) && i->src(0).getFile() == FILE_MEMORY_CONST) - code[0] |= 0x4000; + if (f->indirect) + code[0] |= 0x4000; // indirect calls always use c[] source mask = 2; break; @@ -1230,7 +1230,22 @@ CodeEmitterNVC0::emitFlow(const Instruction *i) if (f->limit) code[0] |= 1 << 16; + if (f->indirect) { + if (code[0] & 0x4000) { + assert(i->srcExists(0) && i->src(0).getFile() == FILE_MEMORY_CONST); + setAddress16(i->src(0)); + code[1] |= i->getSrc(0)->reg.fileIndex << 10; + if (f->op == OP_BRA) + srcId(f->src(0).getIndirect(0), 20); + } else { + srcId(f, 0, 20); + } + } + if (f->op == OP_CALL) { + if (f->indirect) { + // nothing + } else if (f->builtin) { assert(f->absolute); uint32_t pcAbs = targNVC0->getBuiltinOffset(f->target.builtin); -- cgit v1.2.3