MS VC6 Port
[fw/sdcc] / src / avr / ralloc.c
index 05e541a7ab0573a886dbcf2915fb2116e67254e0..3b33a9d6f055a685ff0811be7ddcb16ad979ad68 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;
@@ -529,7 +527,7 @@ static symbol *createStackSpil (symbol *sym)
 /*-----------------------------------------------------------------*/
 static bool isSpiltOnStack (symbol *sym)
 {
-    link *etype;
+    sym_link *etype;
 
     if (!sym)
        return FALSE ;
@@ -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                        */
 /*-----------------------------------------------------------------*/
@@ -856,8 +881,10 @@ static void deassignLRs (iCode *ic, eBBlock *ebp)
                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);
 
@@ -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 */
@@ -1628,7 +1668,7 @@ static int packRegsForSupport (iCode *ic, eBBlock *ebp)
        /* 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 ;
        }
@@ -1664,12 +1704,8 @@ static iCode *packRegsForOneuse (iCode *ic, operand *op , eBBlock *ebp)
     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 
@@ -1701,7 +1737,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 +1746,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 +1793,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;
        
 }
@@ -1779,8 +1810,8 @@ static iCode *packRegsForOneuse (iCode *ic, operand *op , eBBlock *ebp)
 /*-----------------------------------------------------------------*/
 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) 
@@ -1802,138 +1833,6 @@ static bool isBitwiseOptimizable (iCode *ic)
        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            */
 /*-----------------------------------------------------------------*/
@@ -2067,36 +1966,10 @@ static void packRegisters (eBBlock *ebp)
            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 
@@ -2104,11 +1977,12 @@ static void packRegisters (eBBlock *ebp)
           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) {
@@ -2136,38 +2010,6 @@ static void packRegisters (eBBlock *ebp)
                }
            }
        }
-       
-       /* 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); */
-
     }
 }
 
@@ -2184,7 +2026,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 +2053,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 +2079,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 +2116,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 +2162,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;