nv50/ir: add support for indirect BRA,CALL

This commit is contained in:
Christoph Bumiller 2013-02-22 20:08:57 +01:00
parent efe55075b5
commit c893b94060
5 changed files with 29 additions and 6 deletions

View 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 *

View 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;

View 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

View 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));

View 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);