nv50/ir: add support for indirect BRA,CALL
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Fri, 22 Feb 2013 19:08:57 +0000 (20:08 +0100)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Tue, 12 Mar 2013 11:55:34 +0000 (12:55 +0100)
src/gallium/drivers/nv50/codegen/nv50_ir.cpp
src/gallium/drivers/nv50/codegen/nv50_ir.h
src/gallium/drivers/nv50/codegen/nv50_ir_print.cpp
src/gallium/drivers/nv50/codegen/nv50_ir_ra.cpp
src/gallium/drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp

index 3121c5ff270b610fc096e46df58a6593eca82234..b84766658069378eadcdf4edd8a7e123375853fe 100644 (file)
@@ -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 *
index ae577cc4209ebbdb7ad0886cd65eac5766716b44..47562beb2fd7cecf6f1d7c146cd7b7eda76739b7 100644 (file)
@@ -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;
index 48ade15842ddb7766ba42f1fd8787ed69c0f1041..00a80544c176f5470132dc52c09dfc74de0710c7 100644 (file)
@@ -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
index e0fea4b933754e6f5e8d3be5b3d47f20c35c1528..ed991dac30b463f7f310e6424b7f71f351e12405 100644 (file)
@@ -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));
index dc1fe99bde6917115d84661d74b3f91ef463608e..763d07f759ac7236915177c4f9c2cd932eac7ea8 100644 (file)
@@ -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);