{REG_GPR, X10_IDX, REG_GPR, "x10", "x10", "xreg", 2, 1},
{REG_GPR, X11_IDX, REG_GPR, "x11", "x11", "xreg", 3, 1},
{REG_GPR, X12_IDX, REG_GPR, "x12", "x12", "xreg", 4, 1},
- {REG_CND, CND_IDX, REG_CND, "C", "C", "xreg", 0, 1},
+ {REG_CND, CND_IDX, REG_CND, "C", "psw", "0xd0", 0, 1},
+ {0, DPL_IDX, 0, "dpl", "dpl", "0x82", 0, 0},
+ {0, DPH_IDX, 0, "dph", "dph", "0x83", 0, 0},
+ {0, B_IDX, 0, "b", "b", "0xf0", 0, 0},
+ {0, A_IDX, 0, "a", "acc", "0xe0", 0, 0},
};
-int mcs51_nRegs = 13;
+int mcs51_nRegs = 17;
static void spillThis (symbol *);
static void freeAllRegs ();
return NULL;
}
+/*-----------------------------------------------------------------*/
+/* allocThisReg - allocates a particular register (if free) */
+/*-----------------------------------------------------------------*/
+static regs *
+allocThisReg (regs * reg)
+{
+ if (!reg->isFree)
+ return NULL;
+
+ reg->isFree = 0;
+ if (currFunc)
+ currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, reg->rIdx);
+
+ return reg;
+}
+
+
/*-----------------------------------------------------------------*/
/* mcs51_regWithIdx - returns pointer to register wit index number */
/*-----------------------------------------------------------------*/
{
int i;
- for (i = 0; i < mcs51_nRegs; i++)
+ for (i = 0; i < sizeof(regs8051)/sizeof(regs); i++)
if (regs8051[i].rIdx == idx)
return ®s8051[i];
}
- setToNull ((void **) &sset);
+ setToNull ((void *) &sset);
sym->blockSpil = 0;
return sym;
}
getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym)
{
regs *reg;
+ int j;
tryAgain:
/* try for a ptr type */
if (!spilSomething (ic, ebp, sym))
return NULL;
+ /* make sure partially assigned registers aren't reused */
+ for (j=0; j<=sym->nRegs; j++)
+ if (sym->regs[j])
+ sym->regs[j]->isFree = 0;
+
/* this looks like an infinite loop but
in really selectSpil will abort */
goto tryAgain;
getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
{
regs *reg;
-
+ int j;
+
tryAgain:
/* try for gpr type */
if ((reg = allocReg (REG_GPR)))
if (!spilSomething (ic, ebp, sym))
return NULL;
+ /* make sure partially assigned registers aren't reused */
+ for (j=0; j<=sym->nRegs; j++)
+ if (sym->regs[j])
+ sym->regs[j]->isFree = 0;
+
/* this looks like an infinite loop but
in really selectSpil will abort */
goto tryAgain;
(result = OP_SYMBOL (IC_RESULT (ic))) && /* has a result */
result->liveTo > ic->seq && /* and will live beyond this */
result->liveTo <= ebp->lSeq && /* does not go beyond this block */
+ result->liveFrom == ic->seq && /* does not start before here */
result->regType == sym->regType && /* same register types */
result->nRegs && /* which needs registers */
!result->isspilt && /* and does not already have them */
return change;
}
+
+/*------------------------------------------------------------------*/
+/* verifyRegsAssigned - make sure an iTemp is properly initialized; */
+/* it should either have registers or have beed spilled. Otherwise, */
+/* there was an uninitialized variable, so just spill this to get */
+/* the operand in a valid state. */
+/*------------------------------------------------------------------*/
+static void
+verifyRegsAssigned (operand *op, iCode * ic)
+{
+ symbol * sym;
+
+ if (!op) return;
+ if (!IS_ITEMP (op)) return;
+
+ sym = OP_SYMBOL (op);
+ if (sym->isspilt) return;
+ if (!sym->nRegs) return;
+ if (sym->regs[0]) return;
+
+ werrorfl (ic->filename, ic->lineno, W_LOCAL_NOINIT,
+ sym->prereqv ? sym->prereqv->name : sym->name);
+ spillThis (sym);
+}
+
+
+
/*-----------------------------------------------------------------*/
/* serialRegAssign - serially allocate registers to the variables */
/*-----------------------------------------------------------------*/
}
}
#endif
-
/* if this is an ipop that means some live
range will have to be assigned again */
if (ic->op == IPOP)
spillThis (sym);
continue;
}
+
+ /* If the live range preceeds the point of definition
+ then ideally we must take into account registers that
+ have been allocated after sym->liveFrom but freed
+ before ic->seq. This is complicated, so spill this
+ symbol instead and let fillGaps handle the allocation. */
+ if (sym->liveFrom < ic->seq) {
+ spillThis (sym);
+ continue;
+ }
/* if it has a spillocation & is used less than
all other live ranges then spill this */
mcs51_ptrRegReq++;
ptrRegSet = 1;
}
+ if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic))
+ && SPEC_OCLS(OP_SYMBOL (IC_LEFT (ic))->etype) == idata) {
+ mcs51_ptrRegReq++;
+ ptrRegSet = 1;
+ }
+ if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic))
+ && SPEC_OCLS(OP_SYMBOL (IC_RIGHT (ic))->etype) == idata) {
+ mcs51_ptrRegReq++;
+ ptrRegSet = 1;
+ }
+
/* else we assign registers to it */
_G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
_G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key);
for (j = 0; j < sym->nRegs; j++) {
+ sym->regs[j] = NULL;
if (sym->regType == REG_PTR)
sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
else
- sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
+ {
+ if (ic->op == CAST && IS_SYMOP (IC_RIGHT (ic)))
+ {
+ symbol * right = OP_SYMBOL (IC_RIGHT (ic));
+
+ if (right->regs[j])
+ sym->regs[j] = allocThisReg (right->regs[j]);
+ }
+ if (!sym->regs[j])
+ sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
+ }
/* if the allocation failed which means
this was spilt then break */
- if (!sym->regs[j]) {
- break;
- }
+ if (!sym->regs[j])
+ {
+ for (i=0; i < sym->nRegs ; i++ )
+ sym->regs[i] = NULL;
+ break;
+ }
}
-
+
if (!POINTER_SET(ic) && !POINTER_GET(ic)) {
/* if it shares registers with operands make sure
that they are in the same position */
}
}
}
+
+ /* Check for and fix any problems with uninitialized operands */
+ for (i = 0; i < count; i++)
+ {
+ iCode *ic;
+
+ if (ebbs[i]->noPath &&
+ (ebbs[i]->entryLabel != entryLabel &&
+ ebbs[i]->entryLabel != returnLabel))
+ continue;
+
+ for (ic = ebbs[i]->sch; ic; ic = ic->next)
+ {
+ if (SKIP_IC2 (ic))
+ continue;
+
+ if (ic->op == IFX)
+ {
+ verifyRegsAssigned (IC_COND (ic), ic);
+ continue;
+ }
+
+ if (ic->op == JUMPTABLE)
+ {
+ verifyRegsAssigned (IC_JTCOND (ic), ic);
+ continue;
+ }
+
+ verifyRegsAssigned (IC_RESULT (ic), ic);
+ verifyRegsAssigned (IC_LEFT (ic), ic);
+ verifyRegsAssigned (IC_RIGHT (ic), ic);
+ }
+ }
}
/*-----------------------------------------------------------------*/
symbol *sym =NULL;
int key =0;
int pass;
+ iCode *ic = NULL;
if (getenv("DISABLE_FILL_GAPS")) return;
bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */
continue ;
- clr = hTabItemWithKey(liveRanges,i);
+ clr = hTabItemWithKey(liveRanges,i);
assert(clr);
-
+
/* mark these registers as used */
for (k = 0 ; k < clr->nRegs ; k++ )
useReg(clr->regs[k]);
continue ;
}
+ ic = NULL;
+ for (i = 0 ; i < sym->defs->size ; i++ )
+ {
+ if (bitVectBitValue(sym->defs,i))
+ {
+ if (!(ic = hTabItemWithKey(iCodehTab,i)))
+ continue;
+ if (ic->op == CAST)
+ break;
+ }
+ }
+
D(printf("Atemping fillGaps on %s: [",sym->name));
/* THERE IS HOPE !!!! */
for (i=0; i < sym->nRegs ; i++ ) {
if (sym->regType == REG_PTR)
sym->regs[i] = getRegPtrNoSpil ();
else
- sym->regs[i] = getRegGprNoSpil ();
+ {
+ sym->regs[i] = NULL;
+ if (ic && ic->op == CAST && IS_SYMOP (IC_RIGHT (ic)))
+ {
+ symbol * right = OP_SYMBOL (IC_RIGHT (ic));
+
+ if (right->regs[i])
+ sym->regs[i] = allocThisReg (right->regs[i]);
+ }
+ if (!sym->regs[i])
+ sym->regs[i] = getRegGprNoSpil ();
+ }
D(printf("%s ", sym->regs[i]->name));
}
D(printf("]\n"));
D(printf(" checking definitions\n"));
for (i = 0 ; i < sym->defs->size ; i++ ) {
if (bitVectBitValue(sym->defs,i)) {
- iCode *ic;
if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ;
D(printf(" ic->seq = %d\n", ic->seq));
if (SKIP_IC(ic)) continue;
continue ;
}
D(printf ("FILLED GAP for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN"));
+
_G.totRegAssigned = bitVectSetBit(_G.totRegAssigned,sym->key);
sym->isspilt = sym->spillA = 0 ;
sym->usl.spillLoc->allocreq--;
for (j = 0; j < sym->nRegs; j++)
{
+ if (sym->regs[j]) /* EEP - debug */
rumask = bitVectSetBit (rumask,
sym->regs[j]->rIdx);
}
(ic = hTabItemWithKey (iCodehTab,
bitVectFirstBit (sym->defs))) &&
POINTER_GET (ic) &&
- !sym->noSpilLoc &&
- !IS_BITVAR (sym->etype))
+ !IS_BITVAR (sym->etype) &&
+ (aggrToPtrDclType (operandType (IC_LEFT (ic)), FALSE) == POINTER))
{
-
- /* and that pointer is remat in data space */
- if (IS_SYMOP (IC_LEFT (ic)) &&
- OP_SYMBOL (IC_LEFT (ic))->remat &&
- !IS_CAST_ICODE(OP_SYMBOL (IC_LEFT (ic))->rematiCode) &&
- DCL_TYPE (aggrToPtr (operandType(IC_LEFT(ic)), FALSE)) == POINTER)
+ if (ptrPseudoSymSafe (sym, ic))
{
- /* create a psuedo symbol & force a spil */
- symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
- psym->type = sym->type;
- psym->etype = sym->etype;
-
- strcpy (psym->rname, psym->name);
- sym->isspilt = 1;
- sym->usl.spillLoc = psym;
-#if 0 // an alternative fix for bug #480076
- /* now this is a useless assignment to itself */
- remiCodeFromeBBlock (ebbs, ic);
-#else
- /* now this really is an assignment to itself, make it so;
- it will be optimized out later */
- ic->op='=';
- ReplaceOpWithCheaperOp(&IC_RIGHT(ic), IC_RESULT(ic));
- IC_LEFT(ic)=NULL;
-#endif
+ ptrPseudoSymConvert (sym, ic, rematStr (OP_SYMBOL (IC_LEFT (ic))));
continue;
}
return 0;
}
-
/* if the true symbol is defined in far space or on stack
then we should not since this will increase register pressure */
if (isOperandInFarSpace(IC_RESULT(ic)) && !farSpacePackable(ic)) {
we cannot */
for (dic = ic->prev; dic; dic = dic->prev)
{
-
-#if 0 /* jwk: This collides with 1.43 but I really see no need for
- this anymore. It fixes bug #716790 and substantially improves
- redundant register usage around function calls.
- */
-
- /* if there is a function call then don't pack it */
+ int crossedCall = 0;
+
+ /* We can pack across a function call only if it's a local */
+ /* variable or our parameter. Never pack global variables */
+ /* or parameters to a function we call. */
if ((dic->op == CALL || dic->op == PCALL))
{
- dic = NULL;
- break;
+ if (!OP_SYMBOL (IC_RESULT (ic))->ismyparm
+ && !OP_SYMBOL (IC_RESULT (ic))->islocal)
+ {
+ crossedCall = 1;
+ }
}
-#endif
if (SKIP_IC2 (dic))
continue;
break;
}
- if (POINTER_SET (dic) &&
+ if (IS_SYMOP (IC_RESULT (dic)) &&
IC_RESULT (dic)->key == IC_RESULT (ic)->key)
{
dic = NULL;
break;
}
+
+ if (crossedCall)
+ {
+ dic = NULL;
+ break;
+ }
+
}
}
if (!dic)
return 0; /* did not find */
+ /* if assignment then check that right is not a bit */
+ if (ASSIGNMENT (ic) && !POINTER_SET (ic))
+ {
+ sym_link *etype = operandType (IC_RESULT (dic));
+ if (IS_BITFIELD (etype))
+ {
+ /* if result is a bit too then it's ok */
+ etype = operandType (IC_RESULT (ic));
+ if (!IS_BITFIELD (etype))
+ {
+ return 0;
+ }
+ }
+ }
+#if 0
/* if assignment then check that right is not a bit */
if (ASSIGNMENT (dic) && !POINTER_SET (dic))
{
if (IS_BITFIELD (etype))
{
/* if result is a bit too then it's ok */
- etype = operandType (IC_RESULT (dic));
+ etype = operandType (IC_RESULT (dic));
if (!IS_BITFIELD (etype))
- return 0;
- }
+ return 0;
+ }
}
+#endif
/* if the result is on stack or iaccess then it must be
the same atleast one of the operands */
if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
other uses.
*/
-
for (dic = ic->prev; dic; dic = dic->prev)
{
/* update the sym of the used operand */
OP_SYMBOL(op) = OP_SYMBOL(IC_RIGHT(assignment));
op->key = OP_SYMBOL(op)->key;
-
+ OP_SYMBOL(op)->accuse = 0;
+
/* update the sym's liverange */
if ( OP_LIVETO(op) < ic->seq )
setToRange(op, ic->seq, FALSE);
{
/* if we are using a symbol on the stack
then we should say mcs51_ptrRegReq */
+ if (options.useXstack && ic->parmPush
+ && (ic->op == IPUSH || ic->op == IPOP))
+ mcs51_ptrRegReq++;
if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
mcs51_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ||
- OP_SYMBOL (IC_COND (ic))->iaccess) ? 1 : 0);
+ OP_SYMBOL (IC_COND (ic))->iaccess ||
+ SPEC_OCLS(OP_SYMBOL (IC_COND (ic))->etype) == idata) ? 1 : 0);
else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic)))
mcs51_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ||
- OP_SYMBOL (IC_JTCOND (ic))->iaccess) ? 1 : 0);
+ OP_SYMBOL (IC_JTCOND (ic))->iaccess ||
+ SPEC_OCLS(OP_SYMBOL (IC_JTCOND (ic))->etype) == idata) ? 1 : 0);
else
{
if (IS_SYMOP (IC_LEFT (ic)))
mcs51_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ||
- OP_SYMBOL (IC_LEFT (ic))->iaccess) ? 1 : 0);
+ OP_SYMBOL (IC_LEFT (ic))->iaccess ||
+ SPEC_OCLS(OP_SYMBOL (IC_LEFT (ic))->etype) == idata) ? 1 : 0);
if (IS_SYMOP (IC_RIGHT (ic)))
mcs51_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ||
- OP_SYMBOL (IC_RIGHT (ic))->iaccess) ? 1 : 0);
+ OP_SYMBOL (IC_RIGHT (ic))->iaccess ||
+ SPEC_OCLS(OP_SYMBOL (IC_RIGHT (ic))->etype) == idata) ? 1 : 0);
if (IS_SYMOP (IC_RESULT (ic)))
mcs51_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ||
- OP_SYMBOL (IC_RESULT (ic))->iaccess) ? 1 : 0);
+ OP_SYMBOL (IC_RESULT (ic))->iaccess ||
+ SPEC_OCLS(OP_SYMBOL (IC_RESULT (ic))->etype) == idata) ? 1 : 0);
+ if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic))
+ && getSize (OP_SYMBOL (IC_LEFT (ic))->type) <= (unsigned int) PTRSIZE)
+ mcs51_ptrRegReq ++;
+ if (POINTER_SET (ic) && IS_SYMOP (IC_RESULT (ic))
+ && getSize (OP_SYMBOL (IC_RESULT (ic))->type) <= (unsigned int) PTRSIZE)
+ mcs51_ptrRegReq ++;
}
}
for (i = 0; i < count; i++)
packRegisters (ebbs, i);
-
+
+ /* liveranges probably changed by register packing
+ so we compute them again */
+ recomputeLiveRanges (ebbs, count);
if (options.dump_pack)
dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
redoStackOffsets ();
}
+ /* make sure r0 & r1 are flagged as used if they might be used */
+ /* as pointers */
+ if (currFunc && mcs51_ptrRegReq)
+ {
+ currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, R0_IDX);
+ currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, R1_IDX);
+ }
+
if (options.dump_rassgn)
{
dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
/* free up any _G.stackSpil locations allocated */
applyToSet (_G.stackSpil, deallocStackSpil);
_G.slocNum = 0;
- setToNull ((void **) &_G.stackSpil);
- setToNull ((void **) &_G.spiltSet);
+ setToNull ((void *) &_G.stackSpil);
+ setToNull ((void *) &_G.spiltSet);
/* mark all registers as free */
freeAllRegs ();