if (op == OP_JOIN)
terminator = targ ? 1 : 0;
- allWarp = absolute = limit = builtin = 0;
+ allWarp = absolute = limit = builtin = indirect = 0;
}
FlowInstruction *
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;
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
// 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));
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;
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);