nv50/ir: add support for indirect BRA,CALL
This commit is contained in:
parent
efe55075b5
commit
c893b94060
|
@ -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 *
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue