regsAVR[i].isFree ) {
regsAVR[i].isFree = 0;
if (currFunc)
- currFunc->regsUsed =
- bitVectSetBit(currFunc->regsUsed,i);
+ currFunc->regsUsed = bitVectSetBit(currFunc->regsUsed,i);
return ®sAVR[i];
}
/* other wise look for specific type
(ic = hTabItemWithKey(iCodehTab,i)) &&
( ic->seq >= fseq && ic->seq <= toseq))
- return FALSE;
-
+ return FALSE;
}
return TRUE;
/*-----------------------------------------------------------------*/
static bool isSpiltOnStack (symbol *sym)
{
- link *etype;
+ sym_link *etype;
if (!sym)
return FALSE ;
if (!_G.blockSpil &&
(selectS = liveRangesWith(lrcs,notUsedInRemaining,ebp,ic))) {
sym = leastUsedLR (selectS);
- if (!sym->remat) {
- sym->remainSpil = 1;
- _G.blockSpil++;
+ if (sym != forSym) {
+ if (!sym->remat) {
+ sym->remainSpil = 1;
+ _G.blockSpil++;
+ }
+ return sym;
}
- return sym;
}
}
goto tryAgain ;
}
+/*-----------------------------------------------------------------*/
+/* getRegScr - will try for SCR if not a GPR type if not spil */
+/*-----------------------------------------------------------------*/
+static regs *getRegScr (iCode *ic, eBBlock *ebp, symbol *sym)
+{
+ regs *reg;
+
+ tryAgain:
+ /* try for a ptr type */
+ if ((reg = allocReg(REG_SCR)))
+ return reg;
+
+ /* try for gpr type */
+ if ((reg = allocReg(REG_GPR)))
+ return reg;
+
+ /* we have to spil */
+ if (!spilSomething (ic,ebp,sym))
+ return NULL ;
+
+ /* this looks like an infinite loop but
+ in really selectSpil will abort */
+ goto tryAgain ;
+}
+
/*-----------------------------------------------------------------*/
/* getRegGpr - will try for GPR if not spil */
/*-----------------------------------------------------------------*/
for (i = 0 ; i < result->nRegs ; i++)
if (i < sym->nRegs )
result->regs[i] = sym->regs[i] ;
+ else if (result->regType == REG_SCR)
+ result->regs[i] = getRegScr(ic,ebp,result);
else
- result->regs[i] = getRegGpr (ic,ebp,result);
+ result->regs[i] = getRegGpr (ic,ebp,result);
_G.regAssigned = bitVectSetBit(_G.regAssigned,result->key);
for (j = 0 ; j < sym->nRegs ;j++ ) {
if (sym->regType == REG_PTR)
sym->regs[j] = getRegPtr(ic,ebbs[i],sym);
+ else if (sym->regType == REG_SCR)
+ sym->regs[j] = getRegScr(ic,ebbs[i],sym);
else
sym->regs[j] = getRegGpr(ic,ebbs[i],sym);
continue ;
/* for all the registers allocated to it */
- for (k = 0 ; k < sym->nRegs ;k++)
- if (sym->regs[k])
+ for (k = 0 ; k < sym->nRegs ;k++) {
+ if (sym->regs[k]) {
ic->rMask =
bitVectSetBit(ic->rMask,sym->regs[k]->rIdx);
+ /* special case for X & Z registers */
+ if (k == R26_IDX || k == R27_IDX)
+ ic->rMask = bitVectSetBit(ic->rMask,X_IDX);
+ if (k == R30_IDX || k == R31_IDX)
+ ic->rMask = bitVectSetBit(ic->rMask,Z_IDX);
+ }
+ }
}
}
}
/* determine the type of register required */
if (sym->nRegs == 2 && /* size is two */
IS_PTR(sym->type) && /* is a pointer */
- sym->uptr) { /* has has pointer usage i.e. get/set pointer */
+ sym->uptr) { /* has pointer usage i.e. get/set pointer */
sym->regType = REG_PTR ;
avr_ptrRegReq++;
}
- else
- sym->regType = REG_GPR ;
-
+ else {
+ /* live accross a function call then gpr else scratch */
+ if (sym->isLiveFcall)
+ sym->regType = REG_GPR ;
+ else
+ sym->regType = REG_SCR ;
+ }
} else
/* for the first run we don't provide */
/* registers for true symbols we will */
/* if this is a subtraction & the result
is a true symbol in far space then don't pack */
if (ic->op == '-' && IS_TRUE_SYMOP(IC_RESULT(dic))) {
- link *etype =getSpec(operandType(IC_RESULT(dic)));
+ sym_link *etype =getSpec(operandType(IC_RESULT(dic)));
if (IN_FARSPACE(SPEC_OCLS(etype)))
return change ;
}
if (!IS_SYMOP(op))
return NULL;
- /* only upto 2 bytes since we cannot predict
- the usage of b, & acc */
- if (getSize(operandType(op)) > (fReturnSize - 2) &&
- ic->op != RETURN &&
- ic->op != SEND)
- return NULL;
+ /* returns only */
+ if (ic->op != RETURN) return NULL;
/* this routine will mark the a symbol as used in one
instruction use only && if the defintion is local
a function call */
if (dic->op == CALL || dic->op == PCALL ) {
if (ic->op != SEND && ic->op != RETURN) {
-/* OP_SYMBOL(op)->ruonly = 1; */
+ OP_SYMBOL(op)->ruonly = 1;
return dic;
}
dic = dic->next ;
/* otherwise check that the definition does
not contain any symbols in far space */
- if (isOperandInFarSpace(IC_LEFT(dic)) ||
- isOperandInFarSpace(IC_RIGHT(dic)) ||
- IS_OP_RUONLY(IC_LEFT(ic)) ||
+ if (IS_OP_RUONLY(IC_LEFT(ic)) ||
IS_OP_RUONLY(IC_RIGHT(ic)) ) {
return NULL;
}
return NULL;
/* if left or right or result is in far space */
- if (isOperandInFarSpace(IC_LEFT(dic)) ||
- isOperandInFarSpace(IC_RIGHT(dic)) ||
- isOperandInFarSpace(IC_RESULT(dic)) ||
- IS_OP_RUONLY(IC_LEFT(dic)) ||
+ if (IS_OP_RUONLY(IC_LEFT(dic)) ||
IS_OP_RUONLY(IC_RIGHT(dic)) ||
IS_OP_RUONLY(IC_RESULT(dic)) ) {
return NULL;
}
}
-/* OP_SYMBOL(op)->ruonly = 1; */
+ OP_SYMBOL(op)->ruonly = 1;
return sic;
}
/*-----------------------------------------------------------------*/
static bool isBitwiseOptimizable (iCode *ic)
{
- link *ltype = getSpec(operandType(IC_LEFT(ic)));
- link *rtype = getSpec(operandType(IC_RIGHT(ic)));
+ sym_link *ltype = getSpec(operandType(IC_LEFT(ic)));
+ sym_link *rtype = getSpec(operandType(IC_RIGHT(ic)));
/* bitwise operations are considered optimizable
under the following conditions (Jean-Louis VERN)
return FALSE ;
}
-/*-----------------------------------------------------------------*/
-/* packRegsForAccUse - pack registers for acc use */
-/*-----------------------------------------------------------------*/
-static void packRegsForAccUse (iCode *ic)
-{
- iCode *uic;
-
- /* if + or - then it has to be one byte result */
- if ((ic->op == '+' || ic->op == '-')
- && getSize(operandType(IC_RESULT(ic))) > 1)
- return ;
-
- /* if shift operation make sure right side is not a literal */
- if (ic->op == RIGHT_OP &&
- ( isOperandLiteral(IC_RIGHT(ic)) ||
- getSize(operandType(IC_RESULT(ic))) > 1))
- return ;
-
- if (ic->op == LEFT_OP &&
- ( isOperandLiteral(IC_RIGHT(ic)) ||
- getSize(operandType(IC_RESULT(ic))) > 1))
- return ;
-
- if (IS_BITWISE_OP(ic) &&
- getSize(operandType(IC_RESULT(ic))) > 1)
- return ;
-
-
- /* has only one definition */
- if (bitVectnBitsOn(OP_DEFS(IC_RESULT(ic))) > 1)
- return ;
-
- /* has only one use */
- if (bitVectnBitsOn(OP_USES(IC_RESULT(ic))) > 1)
- return ;
-
- /* and the usage immediately follows this iCode */
- if (!(uic = hTabItemWithKey(iCodehTab,
- bitVectFirstBit(OP_USES(IC_RESULT(ic))))))
- return ;
-
- if (ic->next != uic)
- return ;
-
- /* if it is a conditional branch then we definitely can */
- if (uic->op == IFX )
- goto accuse;
-
- if ( uic->op == JUMPTABLE )
- return ;
-
- /* if the usage is not is an assignment
- or an arithmetic / bitwise / shift operation then not */
- if (POINTER_SET(uic) &&
- getSize(aggrToPtr(operandType(IC_RESULT(uic)),FALSE)) > 1)
- return;
-
- if (uic->op != '=' &&
- !IS_ARITHMETIC_OP(uic) &&
- !IS_BITWISE_OP(uic) &&
- uic->op != LEFT_OP &&
- uic->op != RIGHT_OP )
- return;
-
- /* if used in ^ operation then make sure right is not a
- literl */
- if (uic->op == '^' && isOperandLiteral(IC_RIGHT(uic)))
- return ;
-
- /* if shift operation make sure right side is not a literal */
- if (uic->op == RIGHT_OP &&
- ( isOperandLiteral(IC_RIGHT(uic)) ||
- getSize(operandType(IC_RESULT(uic))) > 1))
- return ;
-
- if (uic->op == LEFT_OP &&
- ( isOperandLiteral(IC_RIGHT(uic)) ||
- getSize(operandType(IC_RESULT(uic))) > 1))
- return ;
-
- /* make sure that the result of this icode is not on the
- stack, since acc is used to compute stack offset */
- if (IS_TRUE_SYMOP(IC_RESULT(uic)) &&
- OP_SYMBOL(IC_RESULT(uic))->onStack)
- return ;
-
- /* if either one of them in far space then we cannot */
- if ((IS_TRUE_SYMOP(IC_LEFT(uic)) &&
- isOperandInFarSpace(IC_LEFT(uic))) ||
- (IS_TRUE_SYMOP(IC_RIGHT(uic)) &&
- isOperandInFarSpace(IC_RIGHT(uic))))
- return ;
-
- /* if the usage has only one operand then we can */
- if (IC_LEFT(uic) == NULL ||
- IC_RIGHT(uic) == NULL)
- goto accuse;
-
- /* make sure this is on the left side if not
- a '+' since '+' is commutative */
- if (ic->op != '+' &&
- IC_LEFT(uic)->key != IC_RESULT(ic)->key)
- return;
-
- /* if one of them is a literal then we can */
- if ((IC_LEFT(uic) && IS_OP_LITERAL(IC_LEFT(uic))) ||
- (IC_RIGHT(uic) && IS_OP_LITERAL(IC_RIGHT(uic)))) {
- OP_SYMBOL(IC_RESULT(ic))->accuse = 1;
- return ;
- }
-
- /* if the other one is not on stack then we can */
- if (IC_LEFT(uic)->key == IC_RESULT(ic)->key &&
- (IS_ITEMP(IC_RIGHT(uic)) ||
- (IS_TRUE_SYMOP(IC_RIGHT(uic)) &&
- !OP_SYMBOL(IC_RIGHT(uic))->onStack)))
- goto accuse;
-
- if (IC_RIGHT(uic)->key == IC_RESULT(ic)->key &&
- (IS_ITEMP(IC_LEFT(uic)) ||
- (IS_TRUE_SYMOP(IC_LEFT(uic)) &&
- !OP_SYMBOL(IC_LEFT(uic))->onStack)))
- goto accuse ;
-
- return ;
-
- accuse:
- OP_SYMBOL(IC_RESULT(ic))->accuse = 1;
-
-
-}
-
/*-----------------------------------------------------------------*/
/* packForPush - hueristics to reduce iCode for pushing */
/*-----------------------------------------------------------------*/
continue ;
}
- /* reduce for support function calls */
-/* if (ic->supportRtn || ic->op == '+' || ic->op == '-' ) */
-/* packRegsForSupport (ic,ebp); */
-
/* some cases the redundant moves can
can be eliminated for return statements */
-/* if ((ic->op == RETURN || ic->op == SEND) && */
-/* !isOperandInFarSpace(IC_LEFT(ic)) && */
-/* !options.model) */
-/* packRegsForOneuse (ic,IC_LEFT(ic),ebp); */
-
- /* if pointer set & left has a size more than
- one and right is not in far space */
-/* if (POINTER_SET(ic) && */
-/* !isOperandInFarSpace(IC_RIGHT(ic)) && */
-/* !OP_SYMBOL(IC_RESULT(ic))->remat && */
-/* !IS_OP_RUONLY(IC_RIGHT(ic)) && */
-/* getSize(aggrToPtr(operandType(IC_RESULT(ic)),FALSE)) > 1 ) */
-
-/* packRegsForOneuse (ic,IC_RESULT(ic),ebp); */
-
- /* if pointer get */
-/* if (POINTER_GET(ic) && */
-/* !isOperandInFarSpace(IC_RESULT(ic))&& */
-/* !OP_SYMBOL(IC_LEFT(ic))->remat && */
-/* !IS_OP_RUONLY(IC_RESULT(ic)) && */
-/* getSize(aggrToPtr(operandType(IC_LEFT(ic)),FALSE)) > 1 ) */
-
-/* packRegsForOneuse (ic,IC_LEFT(ic),ebp); */
-
+ if ((ic->op == RETURN || ic->op == SEND))
+ packRegsForOneuse (ic,IC_LEFT(ic),ebp);
/* if this is cast for intergral promotion then
check if only use of the definition of the
the result of that arithmetic operation with
this result and get rid of the cast */
if (ic->op == CAST) {
- link *fromType = operandType(IC_RIGHT(ic));
- link *toType = operandType(IC_LEFT(ic));
+ sym_link *fromType = operandType(IC_RIGHT(ic));
+ sym_link *toType = operandType(IC_LEFT(ic));
if (IS_INTEGRAL(fromType) && IS_INTEGRAL(toType) &&
- getSize(fromType) != getSize(toType) ) {
+ getSize(fromType) != getSize(toType) &&
+ SPEC_USIGN(fromType) == SPEC_USIGN(toType)) {
iCode *dic = packRegsForOneuse(ic,IC_RIGHT(ic),ebp);
if (dic) {
}
}
}
-
- /* pack for PUSH
- iTempNN := (some variable in farspace) V1
- push iTempNN ;
- -------------
- push V1
- */
-/* if (ic->op == IPUSH ) { */
-/* packForPush(ic,ebp); */
-/* } */
-
-
- /* pack registers for accumulator use, when the
- result of an arithmetic or bit wise operation
- has only one use, that use is immediately following
- the defintion and the using iCode has only one
- operand or has two operands but one is literal &
- the result of that operation is not on stack then
- we can leave the result of this operation in acc:b
- combination */
-/* if ((IS_ARITHMETIC_OP(ic) */
-
-/* || IS_BITWISE_OP(ic) */
-
-/* || ic->op == LEFT_OP || ic->op == RIGHT_OP */
-
-/* ) && */
-/* IS_ITEMP(IC_RESULT(ic)) && */
-/* getSize(operandType(IC_RESULT(ic))) <= 2) */
-
-/* packRegsForAccUse (ic); */
-
}
}
if (ic->op == RECEIVE) {
symbol *r = OP_SYMBOL(IC_RESULT(ic));
int size = getSize(r->type);
- if (r->regType == REG_GPR) {
+ if (r->regType == REG_GPR || r->regType == REG_SCR) {
int j = 0;
while (size--) {
r->regs[j++] = ®sAVR[i++];
/*-----------------------------------------------------------------*/
static void setDefaultRegs(eBBlock **ebbs,int count)
{
+ int i ;
/* if no pointer registers required in this function
then mark r26-27 & r30-r31 as GPR & free */
+ regsAVR[R26_IDX].isFree =
+ regsAVR[R27_IDX].isFree =
+ regsAVR[R30_IDX].isFree =
+ regsAVR[R31_IDX].isFree = 1;
+
if (!avr_ptrRegReq) {
- regsAVR[R26_IDX].isFree =
- regsAVR[R27_IDX].isFree =
- regsAVR[R30_IDX].isFree =
- regsAVR[R31_IDX].isFree = 1;
regsAVR[R26_IDX].type =
regsAVR[R27_IDX].type =
regsAVR[R30_IDX].type =
regsAVR[R31_IDX].type = REG_GPR ;
} else {
- regsAVR[R26_IDX].isFree =
- regsAVR[R27_IDX].isFree =
- regsAVR[R30_IDX].isFree =
- regsAVR[R31_IDX].isFree = 1;
regsAVR[R26_IDX].type =
regsAVR[R27_IDX].type =
regsAVR[R30_IDX].type =
regsAVR[R1_IDX].isFree =
regsAVR[R24_IDX].isFree =
regsAVR[R25_IDX].isFree = 0;
-
+
/* if this has no function calls then we need
to do something special
a) pre-assign registers to parameters RECEIVE
b) mark the remaining parameter regs as free */
if (!currFunc->hasFcall) {
+ /* mark the parameter regs as GPR */
+ for (i= R16_IDX ; i <= R23_IDX ;i++) {
+ regsAVR[i].type = REG_SCR;
+ regsAVR[i].isFree = 1;
+ }
preAssignParms(ebbs[0]->sch);
} else {
- int i=0;
- for (i= R16_IDX ; i <= R23_IDX ;i++)
- regsAVR[i].isFree = 0;
+
+ /* otherwise mark them as free scratch */
+ for (i= R16_IDX ; i <= R23_IDX ;i++) {
+ regsAVR[i].type = REG_SCR;
+ regsAVR[i].isFree = 1;
+ }
}
/* Y - is not allocated (it is the stack frame) */
setToNull((void *)&_G.funcrUsed);
avr_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
- /* setup other default register allocation */
/* change assignments this will remove some
live ranges reducing some register pressure */
for (i = 0 ; i < count ;i++ )
genAVRCode(ic);
-
+/* for (; ic ; ic = ic->next) */
+/* piCode(ic,stdout); */
/* free up any _G.stackSpil locations allocated */
applyToSet(_G.stackSpil,deallocStackSpil);
_G.slocNum = 0;