another AVR
[fw/sdcc] / src / avr / ralloc.c
index a2f80849b396bc5f13f46b6b6868833926aef7c1..dc2404f7277f683dbe134a44eec329b1274ed551 100644 (file)
@@ -111,8 +111,7 @@ static regs *allocReg (short type)
            regsAVR[i].isFree ) {
            regsAVR[i].isFree = 0;
            if (currFunc)
-               currFunc->regsUsed = 
-                   bitVectSetBit(currFunc->regsUsed,i);
+               currFunc->regsUsed = bitVectSetBit(currFunc->regsUsed,i);
            return &regsAVR[i];
        }
        /* other wise look for specific type
@@ -200,8 +199,7 @@ static bool allDefsOutOfRange (bitVect *defs,int fseq, int toseq)
            (ic = hTabItemWithKey(iCodehTab,i)) &&
            ( ic->seq >= fseq  && ic->seq <= toseq))
            
-           return FALSE;
-       
+           return FALSE;       
     }
     
     return TRUE;
@@ -619,11 +617,13 @@ static symbol *selectSpil (iCode *ic, eBBlock *ebp, symbol *forSym)
        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;
        }
     }   
 
@@ -743,6 +743,31 @@ static regs *getRegPtr (iCode *ic, eBBlock *ebp, symbol *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                        */
 /*-----------------------------------------------------------------*/
@@ -853,11 +878,13 @@ static void deassignLRs (iCode *ic, eBBlock *ebp)
                  sym->nRegs) >= result->nRegs)
                ) {
                
-               for (i = 0 ; i < max(sym->nRegs,result->nRegs) ; i++)
+               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);
                
@@ -1062,6 +1089,8 @@ static void serialRegAssign (eBBlock **ebbs, int count)
                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);
 
@@ -1078,7 +1107,7 @@ static void serialRegAssign (eBBlock **ebbs, int count)
                                     OP_SYMBOL(IC_LEFT(ic)),ic->lineno);
                /* do the same for the right operand */
                if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) &&
-                   OP_SYMBOL(IC_RIGHT(ic))->nRegs && ic->op != '=')
+                   OP_SYMBOL(IC_RIGHT(ic))->nRegs )
                        positionRegs(OP_SYMBOL(IC_RESULT(ic)),
                                     OP_SYMBOL(IC_RIGHT(ic)),ic->lineno);
                                                
@@ -1212,10 +1241,17 @@ static void createRegMask (eBBlock **ebbs, int count)
                    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);
+                   }
+               }
            }
        }
     }
@@ -1310,13 +1346,17 @@ static void regTypeNum ()
            /* 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 */
@@ -1666,7 +1706,7 @@ static iCode *packRegsForOneuse (iCode *ic, operand *op , eBBlock *ebp)
     
     /* only upto 2 bytes since we cannot predict
        the usage of b, & acc */
-    if (getSize(operandType(op)) >  (fReturnSize - 2) &&
+    if (getSize(operandType(op)) > fAVRReturnSize  &&
        ic->op != RETURN             &&
        ic->op != SEND)
        return NULL;
@@ -1701,7 +1741,7 @@ static iCode *packRegsForOneuse (iCode *ic, operand *op , eBBlock *ebp)
        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 ;
@@ -1710,9 +1750,7 @@ static iCode *packRegsForOneuse (iCode *ic, operand *op , eBBlock *ebp)
     
     /* 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;
     }
@@ -1759,17 +1797,14 @@ static iCode *packRegsForOneuse (iCode *ic, operand *op , eBBlock *ebp)
                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;
        
 }
@@ -2073,10 +2108,8 @@ static void packRegisters (eBBlock *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 ((ic->op == RETURN || ic->op == SEND))
+           packRegsForOneuse (ic,IC_LEFT(ic),ebp);     
 
        /* if pointer set & left has a size more than
           one and right is not in far space */
@@ -2184,7 +2217,7 @@ static void preAssignParms (iCode *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++] = &regsAVR[i++];
@@ -2211,23 +2244,21 @@ static void preAssignParms (iCode *ic)
 /*-----------------------------------------------------------------*/
 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 =
@@ -2239,17 +2270,25 @@ static void setDefaultRegs(eBBlock **ebbs,int count)
        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) */
@@ -2268,7 +2307,6 @@ void avr_assignRegisters (eBBlock **ebbs, int count)
     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++ )
@@ -2315,7 +2353,8 @@ void avr_assignRegisters (eBBlock **ebbs, int count)
 
 
     genAVRCode(ic);
-
+/*     for (; ic ; ic = ic->next) */
+/*         piCode(ic,stdout); */
     /* free up any _G.stackSpil locations allocated */   
     applyToSet(_G.stackSpil,deallocStackSpil);
     _G.slocNum = 0;