summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristoph Bumiller <[email protected]>2013-02-22 20:08:57 +0100
committerChristoph Bumiller <[email protected]>2013-03-12 12:55:34 +0100
commitc893b9406060d3735b2c9e307ae89f6d83a4be40 (patch)
tree0c344d15703274584863ece29a68e36d221df63f /src
parentefe55075b505e9d96ccde12f789ec8991273aef4 (diff)
nv50/ir: add support for indirect BRA,CALL
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/nv50/codegen/nv50_ir.cpp2
-rw-r--r--src/gallium/drivers/nv50/codegen/nv50_ir.h1
-rw-r--r--src/gallium/drivers/nv50/codegen/nv50_ir_print.cpp4
-rw-r--r--src/gallium/drivers/nv50/codegen/nv50_ir_ra.cpp9
-rw-r--r--src/gallium/drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp19
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);