* as/hc08/lkaomf51.c (OutputName),
[fw/sdcc] / src / hc08 / ralloc.c
index ee599f19353b95df7c0a021a1dfa297b7062ab6e..995b78763b3f8a0353d4d2b566ee7da231868015 100644 (file)
@@ -1,6 +1,6 @@
 /*------------------------------------------------------------------------
 
-  SDCCralloc.c - source file for register allocation. (8051) specific
+  SDCCralloc.c - source file for register allocation. 68HC08 specific
 
                 Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
 
@@ -8,19 +8,19 @@
    under the terms of the GNU General Public License as published by the
    Free Software Foundation; either version 2, or (at your option) any
    later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-   
+
    In other words, you are welcome to use, share and improve this program.
    You are forbidden to forbid anyone else to use, share and improve
-   what you give them.   Help stamp out software-hoarding!  
+   what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 
 #include "common.h"
@@ -61,21 +61,23 @@ int hc08_ptrRegReq;         /* one byte pointer register required */
 regs regshc08[] =
 {
 
-  {REG_GPR, A_IDX, REG_GPR, "a", "a", "0", 1, NULL, 0, 1},
-  {REG_GPR, X_IDX, REG_GPR, "x", "x", "0", 2, NULL, 0, 1},
-  {REG_GPR, H_IDX, REG_GPR, "h", "h", "0", 4, NULL, 0, 1},
-  {REG_PTR, HX_IDX, REG_PTR, "hx", "hx", "0", 6, NULL, 0, 1},
-  {REG_GPR, XA_IDX, REG_GPR, "xa", "xa", "0", 3, NULL, 0, 1},
+  {REG_GPR, A_IDX,   "a",  1, NULL, 0, 1},
+  {REG_GPR, X_IDX,   "x",  2, NULL, 0, 1},
+  {REG_GPR, H_IDX,   "h",  4, NULL, 0, 1},
+  {REG_PTR, HX_IDX,  "hx", 6, NULL, 0, 1},
+  {REG_GPR, XA_IDX,  "xa", 3, NULL, 0, 1},
 
-  {REG_CND, CND_IDX, REG_CND, "C", "C", "xreg", 0, NULL, 0, 1},
+  {REG_CND, CND_IDX, "C",  0, NULL, 0, 1},
+  {0,       SP_IDX,  "sp", 0, NULL, 0, 1},
 };
-int hc08_nRegs = 6;
+int hc08_nRegs = 7;
 
 regs *hc08_reg_a;
 regs *hc08_reg_x;
 regs *hc08_reg_h;
 regs *hc08_reg_hx;
 regs *hc08_reg_xa;
+regs *hc08_reg_sp;
 
 static void spillThis (symbol *);
 static void freeAllRegs ();
@@ -87,7 +89,7 @@ static regs *
 allocReg (short type)
 {
   return NULL;
-  
+
   if ((type==REG_PTR) && (regshc08[HX_IDX].isFree))
     {
       regshc08[HX_IDX].isFree = 0;
@@ -130,7 +132,7 @@ hc08_freeReg (regs * reg)
     }
 
   reg->isFree = 1;
-  
+
   switch (reg->rIdx)
     {
       case A_IDX:
@@ -283,9 +285,9 @@ computeSpillable (iCode * ic)
 {
   bitVect *spillable;
 
-  /* spillable live ranges are those that are live at this 
+  /* spillable live ranges are those that are live at this
      point . the following categories need to be subtracted
-     from this set. 
+     from this set.
      a) - those that are already spilt
      b) - if being used by this one
      c) - defined by this one */
@@ -389,7 +391,7 @@ liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
       if (!bitVectBitValue (lrs, i))
        continue;
 
-      /* if we don't find it in the live range 
+      /* if we don't find it in the live range
          hash table we are in serious trouble */
       if (!(sym = hTabItemWithKey (liveRanges, i)))
        {
@@ -509,7 +511,7 @@ spillLRWithPtrReg (symbol * forSym)
       int j;
 
       /* if no registers assigned to it or spilt */
-      /* if it does not overlap with this then 
+      /* if it does not overlap with this then
          not need to spill it */
 
       if (lrsym->isspilt || !lrsym->nRegs ||
@@ -539,7 +541,7 @@ createStackSpil (symbol * sym)
 
   char slocBuffer[30];
 
-  /* first go try and find a free one that is already 
+  /* first go try and find a free one that is already
      existing on the stack */
   if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
     {
@@ -607,7 +609,7 @@ createStackSpil (symbol * sym)
   sym->usl.spillLoc = sloc;
   sym->stackSpil = 1;
 
-  /* add it to the set of itempStack set 
+  /* add it to the set of itempStack set
      of the spill location */
   addSetHead (&sloc->usl.itmpStack, sym);
   return sym;
@@ -653,7 +655,7 @@ spillThis (symbol * sym)
   if (!(sym->remat || sym->usl.spillLoc))
     createStackSpil (sym);
 
-  /* mark it has spilt & put it in the spilt set */
+  /* mark it as spilt & put it in the spilt set */
   sym->isspilt = sym->spillA = 1;
   _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
 
@@ -668,7 +670,7 @@ spillThis (symbol * sym)
        sym->regs[i] = NULL;
       }
 
-  /* if spilt on stack then free up r0 & r1 
+  /* if spilt on stack then free up r0 & r1
      if they could have been assigned to some
      LIVE ranges */
 //  if (!hc08_ptrRegReq && isSpiltOnStack (sym))
@@ -736,7 +738,9 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
 
       /* check if there are any live ranges that not
          used in the remainder of the block */
-      if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
+      if (!_G.blockSpil &&
+          !isiCodeInFunctionCall (ic) &&       
+          (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
        {
          sym = leastUsedLR (selectS);
          if (sym != forSym)
@@ -823,7 +827,7 @@ spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
       spillLRWithPtrReg (ssym);
     }
 
-  /* if this was a block level spil then insert push & pop 
+  /* if this was a block level spil then insert push & pop
      at the start & end of block respectively */
   if (ssym->blockSpil)
     {
@@ -878,7 +882,7 @@ tryAgain:
   if (!spilSomething (ic, ebp, sym))
     return NULL;
 
-  /* this looks like an infinite loop but 
+  /* this looks like an infinite loop but
      in really selectSpil will abort  */
   goto tryAgain;
 }
@@ -904,7 +908,7 @@ tryAgain:
   if (!spilSomething (ic, ebp, sym))
     return NULL;
 
-  /* this looks like an infinite loop but 
+  /* this looks like an infinite loop but
      in really selectSpil will abort  */
   goto tryAgain;
 }
@@ -985,7 +989,7 @@ deassignLRs (iCode * ic, eBBlock * ebp)
       if (sym->liveTo > ic->seq)
        continue;
 
-      /* if it was spilt on stack then we can 
+      /* if it was spilt on stack then we can
          mark the stack spil location as free */
       if (sym->isspilt)
        {
@@ -1001,7 +1005,7 @@ deassignLRs (iCode * ic, eBBlock * ebp)
        continue;
 
       /* special case check if this is an IFX &
-         the privious one was a pop and the 
+         the privious one was a pop and the
          previous one was not spilt then keep track
          of the symbol */
       if (ic->op == IFX && ic->prev &&
@@ -1030,6 +1034,7 @@ deassignLRs (iCode * ic, eBBlock * ebp)
              (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 */
@@ -1101,8 +1106,8 @@ willCauseSpill (int nr, int rt)
      of te type required */
   if (rt == REG_PTR)
     {
-      /* special case for pointer type 
-         if pointer type not avlb then 
+      /* special case for pointer type
+         if pointer type not avlb then
          check for type gpr */
       if (nFreeRegs (rt) >= nr)
        return 0;
@@ -1179,16 +1184,16 @@ 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, 
+
+  werrorfl (ic->filename, ic->lineno, W_LOCAL_NOINIT,
            sym->prereqv ? sym->prereqv->name : sym->name);
   spillThis (sym);
 }
@@ -1260,7 +1265,13 @@ serialRegAssign (eBBlock ** ebbs, int count)
                int j;
                int ptrRegSet = 0;
 
-               /* if it does not need or is spilt 
+               /* Make sure any spill location is definately allocated */
+               if (sym->isspilt && !sym->remat && sym->usl.spillLoc &&
+                   !sym->usl.spillLoc->allocreq) {
+                   sym->usl.spillLoc->allocreq++;
+               }
+
+                /* if it does not need or is spilt
                   or is already assigned to registers
                   or will not live beyond this instructions */
                if (!sym->nRegs ||
@@ -1277,14 +1288,24 @@ serialRegAssign (eBBlock ** ebbs, int count)
                    continue;
                }
                /* if trying to allocate this will cause
-                  a spill and there is nothing to spill 
+                  a spill and there is nothing to spill
                   or this one is rematerializable then
                   spill this one */
                willCS = willCauseSpill (sym->nRegs, sym->regType);
                spillable = computeSpillable (ic);
-               if (sym->remat || (willCS && bitVectIsZero (spillable))) {                    
+               if (sym->remat || (willCS && bitVectIsZero (spillable))) {
+                   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;                 
+                   continue;
                }
 
                /* if it has a spillocation & is used less than
@@ -1387,7 +1408,7 @@ serialRegAssign (eBBlock ** ebbs, int count)
            verifyRegsAssigned (IC_LEFT (ic), ic);
            verifyRegsAssigned (IC_RIGHT (ic), ic);
           }
-      }    
+      }
 
 }
 
@@ -1397,12 +1418,12 @@ serialRegAssign (eBBlock ** ebbs, int count)
 static void fillGaps()
 {
     symbol *sym =NULL;
-    int key =0;    
-    
+    int key =0;
+
     if (getenv("DISABLE_FILL_GAPS")) return;
-    
-    /* look for livernages that was spilt by the allocator */
-    for (sym = hTabFirstItem(liveRanges,&key) ; sym ; 
+
+    /* look for liveranges that were spilt by the allocator */
+    for (sym = hTabFirstItem(liveRanges,&key) ; sym ;
         sym = hTabNextItem(liveRanges,&key)) {
 
        int i;
@@ -1422,9 +1443,9 @@ static void fillGaps()
 
                clr = hTabItemWithKey(liveRanges,i);
            assert(clr);
-        
+
            /* mark these registers as used */
-           for (k = 0 ; k < clr->nRegs ; k++ ) 
+           for (k = 0 ; k < clr->nRegs ; k++ )
                hc08_useReg(clr->regs[k]);
        }
 
@@ -1439,12 +1460,12 @@ static void fillGaps()
            if (sym->regType == REG_PTR)
                sym->regs[i] = getRegPtrNoSpil ();
            else
-               sym->regs[i] = getRegGprNoSpil ();                
+               sym->regs[i] = getRegGprNoSpil ();
        }
 
        /* for all its definitions check if the registers
           allocated needs positioning NOTE: we can position
-          only ONCE if more than One positioning required 
+          only ONCE if more than One positioning required
           then give up */
        sym->isspilt = 0;
        for (i = 0 ; i < sym->defs->size ; i++ ) {
@@ -1454,11 +1475,11 @@ static void fillGaps()
                if (SKIP_IC(ic)) continue;
                assert(isSymbolEqual(sym,OP_SYMBOL(IC_RESULT(ic)))); /* just making sure */
                /* if left is assigned to registers */
-               if (IS_SYMOP(IC_LEFT(ic)) && 
+               if (IS_SYMOP(IC_LEFT(ic)) &&
                    bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_LEFT(ic))->key)) {
                    pdone += positionRegs(sym,OP_SYMBOL(IC_LEFT(ic)));
                }
-               if (IS_SYMOP(IC_RIGHT(ic)) && 
+               if (IS_SYMOP(IC_RIGHT(ic)) &&
                    bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) {
                    pdone += positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic)));
                }
@@ -1473,7 +1494,7 @@ static void fillGaps()
                if (!IS_ASSIGN_ICODE(ic)) continue ;
 
                /* if result is assigned to registers */
-               if (IS_SYMOP(IC_RESULT(ic)) && 
+               if (IS_SYMOP(IC_RESULT(ic)) &&
                    bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) {
                    pdone += positionRegs(sym,OP_SYMBOL(IC_RESULT(ic)));
                }
@@ -1489,7 +1510,7 @@ static void fillGaps()
            }
            freeAllRegs();
            D(printf ("Fill Gap gave up due to positioning for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN"));
-           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);
@@ -1606,7 +1627,7 @@ createRegMask (eBBlock ** ebbs, int count)
          ic->rUsed = regsUsedIniCode (ic);
          _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
 
-         /* now create the register mask for those 
+         /* now create the register mask for those
             registers that are in use : this is a
             super set of ic->rUsed */
          ic->rMask = newBitVect (hc08_nRegs + 1);
@@ -1653,7 +1674,7 @@ rematStr (symbol * sym)
   char *s = buffer;
   iCode *ic = sym->rematiCode;
 //  int offset = 0;
-  
+
   while (1)
     {
       /* if plus or minus print the right hand side */
@@ -1666,7 +1687,7 @@ rematStr (symbol * sym)
          continue;
        }
 
-/*      
+/*
       if (ic->op == '+')
         {
           offset += operandLitValue (IC_RIGHT (ic));
@@ -1724,7 +1745,7 @@ regTypeNum (eBBlock *ebbs)
          if (sym->regType == REG_CND)
            continue;
 
-         /* if used in return only then we don't 
+         /* if used in return only then we don't
             need registers */
          if (sym->ruonly || sym->accuse)
            {
@@ -1739,34 +1760,13 @@ regTypeNum (eBBlock *ebbs)
              (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;
                }
 
@@ -1907,7 +1907,7 @@ packRegsForLiteral (iCode * ic)
 {
   int k;
   iCode *uic;
-  
+
   if (ic->op != '=')
     return;
   if (POINTER_SET (ic))
@@ -1922,7 +1922,7 @@ packRegsForLiteral (iCode * ic)
       {
         uic = hTabItemWithKey (iCodehTab, k);
         if (!uic) continue;
-        
+
         if (uic->op != IFX && uic->op != JUMPTABLE)
          {
            if (IC_LEFT (uic) && IC_LEFT (uic)->key == IC_RESULT (ic)->key)
@@ -1953,7 +1953,6 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
       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 0
@@ -1962,14 +1961,14 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
   }
 #endif
 
-  /* find the definition of iTempNN scanning backwards if we find a 
-     a use of the true symbol in before we find the definition then 
+  /* find the definition of iTempNN scanning backwards if we find a
+     a use of the true symbol in before we find the definition then
      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 
+        this anymore. It fixes bug #716790 and substantially improves
         redundant register usage around function calls.
       */
 
@@ -2028,16 +2027,18 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
     return 0;                  /* did not find */
 
   /* if assignment then check that right is not a bit */
-  if (ASSIGNMENT (dic) && !POINTER_SET (dic))
+  if (ASSIGNMENT (ic) && !POINTER_SET (ic))
     {
-      sym_link *etype = operandType (IC_RIGHT (dic));
+      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 (dic));
+          etype = operandType (IC_RESULT (ic));
           if (!IS_BITFIELD (etype))
-           return 0;
-       }
+            {
+              return 0;
+            }
+       }
     }
   /* if the result is on stack or iaccess then it must be
      the same atleast one of the operands */
@@ -2070,7 +2071,7 @@ pack:
     }
   // TODO: and the otherway around?
 
-  /* delete from liverange table also 
+  /* delete from liverange table also
      delete from all the points inbetween and the new
      one */
   for (sic = dic; sic != ic; sic = sic->next)
@@ -2104,7 +2105,7 @@ findAssignToSym (operand * op, iCode * ic)
      and eliminate the use of iTempAA, freeing up its register for
      other uses.
   */
-     
+
 
   for (dic = ic->prev; dic; dic = dic->prev)
     {
@@ -2113,7 +2114,7 @@ findAssignToSym (operand * op, iCode * ic)
       if (dic->op == '=' &&
          !POINTER_SET (dic) &&
          IC_RESULT (dic)->key == op->key
-          &&  IS_TRUE_SYMOP(IC_RIGHT(dic)) 
+          &&  IS_TRUE_SYMOP(IC_RIGHT(dic))
        )
        break;  /* found where this temp was defined */
 
@@ -2133,11 +2134,11 @@ findAssignToSym (operand * op, iCode * ic)
 
   /* we are interested only if defined in far space */
   /* or in stack space in case of + & - */
-  
+
   /* if assigned to a non-symbol then don't repack regs */
   if (!IS_SYMOP (IC_RIGHT (dic)))
     return NULL;
-  
+
   /* if the symbol is volatile then we should not */
   if (isOperandVolatile (IC_RIGHT (dic), TRUE))
     return NULL;
@@ -2148,7 +2149,7 @@ findAssignToSym (operand * op, iCode * ic)
   /* if the symbol is in far space then we should not */
   /* if (isOperandInFarSpace (IC_RIGHT (dic)))
     return NULL; */
-  
+
   /* for + & - operations make sure that
      if it is on the stack it is the same
      as one of the three operands */
@@ -2156,14 +2157,14 @@ findAssignToSym (operand * op, iCode * ic)
   if ((ic->op == '+' || ic->op == '-') &&
       OP_SYMBOL (IC_RIGHT (dic))->onStack)
     {
-      
+
       if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
          IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
          IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
        return NULL;
     }
 #endif
-  
+
   /* now make sure that the right side of dic
      is not defined between ic & dic */
   if (dic)
@@ -2216,7 +2217,7 @@ reassignAliasedSym (eBBlock *ebp, iCode *assignment, iCode *use, operand *op)
   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(assignment))->defs, assignment->key);
   hTabDeleteItem (&iCodehTab, assignment->key, assignment, DELETE_ITEM, NULL);
 }
-  
+
 
 /*-----------------------------------------------------------------*/
 /* packRegsForSupport :- reduce some registers for support calls   */
@@ -2226,7 +2227,7 @@ packRegsForSupport (iCode * ic, eBBlock * ebp)
 {
   iCode *dic;
   int changes = 0;
-  
+
   /* for the left & right operand :- look to see if the
      left was assigned a true symbol in far space in that
      case replace them */
@@ -2283,19 +2284,19 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
     return NULL;
 
   return NULL;
-  
+
   if (ic->op != SEND //RETURN
       && ic->op != SEND
       && !POINTER_SET (ic)
       && !POINTER_GET (ic) )
     return NULL;
-  
+
   if (ic->op == SEND && ic->argreg != 1) return NULL;
 
-  /* this routine will mark the a symbol as used in one 
-     instruction use only && if the defintion is local 
+  /* this routine will mark the a symbol as used in one
+     instruction use only && if the defintion is local
      (ie. within the basic block) && has only one definition &&
-     that definiion is either a return value from a 
+     that definiion is either a return value from a
      function or does not contain any variables in
      far space */
   uses = bitVectCopy (OP_USES (op));
@@ -2316,7 +2317,7 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
   /* if that only usage is a cast */
   if (dic->op == CAST) {
     /* to a bigger type */
-    if (getSize(OP_SYM_TYPE(IC_RESULT(dic))) > 
+    if (getSize(OP_SYM_TYPE(IC_RESULT(dic))) >
        getSize(OP_SYM_TYPE(IC_RIGHT(dic)))) {
       /* than we can not, since we cannot predict the usage of b & acc */
       return NULL;
@@ -2362,7 +2363,7 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
   if (POINTER_GET (dic) &&
       !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
     return NULL;
-#endif 
+#endif
 
   sic = dic;
 
@@ -2432,7 +2433,7 @@ isBitwiseOptimizable (iCode * ic)
   sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
 
   /* bitwise operations are considered optimizable
-     under the following conditions (Jean-Louis VERN) 
+     under the following conditions (Jean-Louis VERN)
 
      x & lit
      bit & bit
@@ -2497,11 +2498,11 @@ bool operandUsesAcc2(operand *op)
 
 //    if (sym->iaccess && symspace->paged)
 //      return TRUE;  /* must fetch paged indirect sym via accumulator */
-    
+
     if (IN_BITSPACE(symspace))
       return TRUE;  /* fetching bit vars uses the accumulator */
-    
-    if (IN_FARSPACE(symspace) || IN_CODESPACE(symspace)) 
+
+    if (IN_FARSPACE(symspace) || IN_CODESPACE(symspace))
       return TRUE;  /* fetched via accumulator and dptr */
   }
 
@@ -2509,168 +2510,165 @@ bool operandUsesAcc2(operand *op)
 }
 
 /*-----------------------------------------------------------------*/
-/* packRegsForAccUse - pack registers for acc use                  */
+/* canDefAccResult - return 1 if the iCode can generate a result   */
+/*                   in A or XA                                    */
 /*-----------------------------------------------------------------*/
-static void
-packRegsForAccUse (iCode * ic)
+static int
+canDefAccResult (iCode * ic)
 {
-  iCode *uic;
-
-  /* if this is an aggregate, e.g. a one byte char array */
-  if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
-    return;
-  }
+  int size;
 
-  /* if we are calling a reentrant function that has stack parameters */
-  #if 0
-  if (ic->op == CALL &&
-       IFFUNC_ISREENT(operandType(IC_LEFT(ic))) &&
-       FUNC_HASSTACKPARM(operandType(IC_LEFT(ic))))
-      return;
-
-  if (ic->op == PCALL &&
-       IFFUNC_ISREENT(operandType(IC_LEFT(ic))->next) &&
-       FUNC_HASSTACKPARM(operandType(IC_LEFT(ic))->next))
-      return;
-  #endif
+  if (ic->op == IFX || ic->op == JUMPTABLE)    /* these iCodes have no result */
+    return 0;
 
-  /* if + or - then it has to be one byte result */
-  if ((ic->op == '+' || ic->op == '-')
-      && getSize (operandType (IC_RESULT (ic))) > 1)
-    return;
+  if (POINTER_SET (ic))
+    return 0;
 
+  if (!IC_RESULT (ic))
+    return 0;
 
-  /* if shift operation make sure right side is a literal */
-  if (ic->op == RIGHT_OP &&
-      (!isOperandLiteral (IC_RIGHT (ic)) ||
-       (getSize (operandType (IC_RESULT (ic) )) > 1)))
-    return;
+  if (!IS_ITEMP (IC_RESULT (ic)))
+    return 0;
 
-  if (ic->op == LEFT_OP &&
-      (!isOperandLiteral (IC_RIGHT (ic)) ||
-       (getSize (operandType (IC_RESULT (ic) )) > 1)))
-    return;
+  /* I don't think an iTemp can be an aggregate, but just in case */
+  if (IS_AGGREGATE(operandType(IC_RESULT(ic))))
+    return 0;
 
-  if (IS_BITWISE_OP (ic) &&
-      getSize (operandType (IC_RESULT (ic))) > 1)
-    return;
+  size = getSize (operandType (IC_RESULT (ic)));
 
+  if (size == 1)
+    {
+      /* All 1 byte operations should safely generate an accumulator result */
+      return 1;
+    }
+  else if (size == 2)
+    {
+      switch (ic->op)
+        {
+        case LEFT_OP:
+        case RIGHT_OP:
+          return isOperandLiteral (IC_RIGHT (ic))
+                  && SPEC_USIGN (operandType (IC_RESULT (ic)));
+        case CALL:
+        case PCALL:
+        case '*':
+        case RECEIVE:
+        case '=': /* assignment, since POINTER_SET is already ruled out */
+          return 1;
+
+        default:
+          return 0;
+        }
+    }
 
-  /* has only one definition */
-  if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
-    return;
+  return 0;
+}
 
-  /* has only one use */
-  if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
-    return;
+/*-----------------------------------------------------------------*/
+/* canUseAccOperand - return 1 if the iCode can use the operand    */
+/*                    when passed in A or XA                       */
+/*-----------------------------------------------------------------*/
+static int
+canUseAccOperand (iCode * ic, operand * op)
+{
+  int size;
+  operand * otherOp;
 
-  /* and the usage immediately follows this iCode */
-  if (!(uic = hTabItemWithKey (iCodehTab,
-                              bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
-    return;
+  if (ic->op == IFX)
+    {
+      if (isOperandEqual (op, IC_COND (ic)))
+        return 1;
+      else
+        return 0;
+    }
 
-  if (ic->next != uic)
-    return;
+  if (ic->op == JUMPTABLE)
+    {
+      if (isOperandEqual (op, IC_JTCOND (ic)))
+        return 1;
+      else
+        return 0;
+    }
 
-  /* if it is a conditional branch then we definitely can */
-  if (uic->op == IFX)
-    goto accuse;
+  if (POINTER_SET (ic) && isOperandEqual (op, IC_RESULT (ic)))
+    return 1;
 
-  if (uic->op == JUMPTABLE)
-    return;
+  if (isOperandEqual (op, IC_LEFT (ic)))
+    otherOp = IC_RIGHT (ic);
+  else if (isOperandEqual (op, IC_RIGHT (ic)))
+    otherOp = IC_LEFT (ic);
+  else
+    return 0;
 
-#if 0
-  if (POINTER_SET (uic) &&
-      getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1)
-    return;
-#endif
+  /* Generation of SEND is deferred until CALL; not safe */
+  /* if there are intermediate iCodes */
+  if (ic->op == SEND && ic->next && ic->next->op != CALL)
+    return 0;
 
-  /* if the usage is not is an assignment
-     or an arithmetic / bitwise / shift operation then not */
-  if (uic->op != '=' &&
-      !IS_ARITHMETIC_OP (uic) &&
-      !IS_BITWISE_OP (uic) &&
-      (uic->op != LEFT_OP) &&
-      (uic->op != RIGHT_OP) &&
-      (uic->op != GETHBIT) &&
-      (uic->op != RETURN) &&
-      (uic->op != '~') &&
-      (uic->op != '!'))
-    return;
+  size = getSize (operandType (op));
+  if (size == 1)
+    {
+      /* All 1 byte operations should safely use an accumulator operand */
+      return 1;
+    }
+  else if (size == 2)
+    {
+      switch (ic->op)
+        {
+        case LEFT_OP:
+        case RIGHT_OP:
+          return isOperandLiteral (IC_RIGHT (ic));
+        case SEND:
+          return 1;
+        default:
+          return 0;
+        }
+    }
 
-#if 0
-  /* if used in ^ operation then make sure right is not a 
-     literal (WIML: Why is this?) */
-  if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
-    return;
+  return 0;
+}
 
-  /* if shift operation make sure right side is not a literal */
-  /* WIML: Why is this? */
-  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;
-#endif
 
-  /* make sure that the result of this icode is not on the
-     stack, since acc is used to compute stack offset */
-#if 0
-  if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
-      OP_SYMBOL (IC_RESULT (uic))->onStack)
-    return;
-#else
-//  if (isOperandOnStack(IC_RESULT(uic)))
-//    return;
-#endif
+/*-----------------------------------------------------------------*/
+/* packRegsForAccUse - pack registers for acc use                  */
+/*-----------------------------------------------------------------*/
+static int
+packRegsForAccUse (iCode * ic)
+{
+  iCode * uic;
+  operand * op;
 
-  /* if the usage has only one operand then we can */
-  if (IC_LEFT (uic) == NULL ||
-      IC_RIGHT (uic) == NULL)
-    goto accuse;
+  if (!canDefAccResult (ic))
+    return 0;
 
-#if 0
-  /* if the other operand uses the accumulator then we cannot */
-  if ( (IC_LEFT(uic)->key == IC_RESULT(ic)->key &&
-       operandUsesAcc2(IC_RIGHT(uic))) ||
-       (IC_RIGHT(uic)->key == IC_RESULT(ic)->key &&
-       operandUsesAcc2(IC_LEFT(uic))) ) 
-    return;
+  op = IC_RESULT (ic);
 
-  /* make sure this is on the left side if not commutative */
-  /* except for '-', which has been written to be able to
-     handle reversed operands */
-  if (!(isCommutativeOp2(ic->op) || ic->op == '-') &&
-       IC_LEFT (uic)->key != IC_RESULT (ic)->key)
-    return;
-#endif
+  /* has only one definition */
+  if (bitVectnBitsOn (OP_DEFS (op)) > 1)
+    return 0;
 
-#if 0
-  // this is too dangerous and need further restrictions
-  // see bug #447547
+  /* has only one use */
+  if (bitVectnBitsOn (OP_USES (op)) > 1)
+    return 0;
 
-  /* 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;
-    }
-#endif
+  uic = ic->next;
+  if (!uic)
+    return 0;
 
-accuse:
+  if (!canUseAccOperand (uic, op))
+    return 0;
 
+  #if 0
   if ((POINTER_GET(uic))
       || (ic->op == ADDRESS_OF && uic->op == '+' && IS_OP_LITERAL (IC_RIGHT (uic))))
     {
       OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_HX;
       return;
     }
-  
+  #endif
+
   OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_XA;
+  return 1;
 }
 
 /*-----------------------------------------------------------------*/
@@ -2715,7 +2713,7 @@ packForPush (iCode * ic, eBBlock ** ebpp, int blockno)
        inbetween */
     dbv = OP_DEFS(IC_RIGHT(dic));
     for (lic = ic; lic && lic != dic ; lic = lic->prev) {
-      if (bitVectBitValue(dbv,lic->key)) 
+      if (bitVectBitValue(dbv,lic->key))
        return ;
     }
     /* make sure they have the same type */
@@ -2723,7 +2721,7 @@ packForPush (iCode * ic, eBBlock ** ebpp, int blockno)
     {
       sym_link *itype=operandType(IC_LEFT(ic));
       sym_link *ditype=operandType(IC_RIGHT(dic));
-      
+
       if (SPEC_USIGN(itype)!=SPEC_USIGN(ditype) ||
          SPEC_LONG(itype)!=SPEC_LONG(ditype))
        return;
@@ -2733,7 +2731,7 @@ packForPush (iCode * ic, eBBlock ** ebpp, int blockno)
       OP_SYMBOL(IC_RIGHT(dic))->liveTo = ic->seq;
     }
     bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
-  } 
+  }
 
   /* we now we know that it has one & only one def & use
      and the that the definition is an assignment */
@@ -2776,11 +2774,11 @@ packRegisters (eBBlock ** ebpp, int blockno)
   for (ic = ebp->sch; ic; ic = ic->next)
     {
       //packRegsForLiteral (ic);
-      
-      /* if this is an itemp & result of an address of a true sym 
+
+      /* if this is an itemp & result of an address of a true sym
          then mark this as rematerialisable   */
       if (ic->op == ADDRESS_OF &&
-         IS_ITEMP (IC_RESULT (ic)) && 
+         IS_ITEMP (IC_RESULT (ic)) &&
          IS_TRUE_SYMOP (IC_LEFT (ic)) &&
          bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
          !OP_SYMBOL (IC_LEFT (ic))->onStack )
@@ -2823,20 +2821,20 @@ packRegisters (eBBlock ** ebpp, int blockno)
 
       /* if cast to a generic pointer & the pointer being
         cast is remat, then we can remat this cast as well */
-      if (ic->op == CAST && 
+      if (ic->op == CAST &&
          IS_SYMOP(IC_RIGHT(ic)) &&
          OP_SYMBOL(IC_RIGHT(ic))->remat &&
          bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1) {
              sym_link *to_type = operandType(IC_LEFT(ic));
              sym_link *from_type = operandType(IC_RIGHT(ic));
-             if (IS_GENPTR(to_type) && IS_PTR(from_type)) {                  
+             if (IS_GENPTR(to_type) && IS_PTR(from_type)) {
                      OP_SYMBOL (IC_RESULT (ic))->remat = 1;
                      OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
                      OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
              }
       }
 
-      /* if this is a +/- operation with a rematerizable 
+      /* if this is a +/- operation with a rematerizable
          then mark this as rematerializable as well */
       if ((ic->op == '+' || ic->op == '-') &&
          (IS_SYMOP (IC_LEFT (ic)) &&
@@ -2900,6 +2898,57 @@ packRegisters (eBBlock ** ebpp, int blockno)
          continue;
        }
 
+      #if 0
+      /* if the condition of an if instruction
+         is defined in the previous GET_POINTER instruction and
+        this is the only usage then
+         mark the itemp as accumulator use */
+      if ((POINTER_GET (ic) && getSize (operandType (IC_RESULT (ic))) <=1) &&
+          ic->next && ic->next->op == IFX &&
+          bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 &&
+          isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
+          OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
+        {
+          OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
+          continue;
+        }
+
+      if (ic->op != IFX && ic->op !=JUMPTABLE && !POINTER_SET (ic)
+          && IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))
+          && getSize (operandType (IC_RESULT (ic))) == 1
+          && bitVectnBitsOn (OP_USES (IC_RESULT (ic))) == 1
+          && ic->next
+          && OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
+        {
+          int accuse = 0;
+
+          if (ic->next->op == IFX)
+            {
+              if (isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)))
+                accuse = 1;
+            }
+          else if (ic->next->op == JUMPTABLE)
+            {
+               if (isOperandEqual (IC_RESULT (ic), IC_JTCOND (ic->next)))
+                 accuse = 1;
+            }
+          else
+            {
+               if (isOperandEqual (IC_RESULT (ic), IC_LEFT (ic->next)))
+                 accuse = 1;
+               if (isOperandEqual (IC_RESULT (ic), IC_RIGHT (ic->next)))
+                 accuse = 1;
+            }
+
+          if (accuse)
+            {
+              OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
+              continue;
+            }
+
+        }
+      #endif
+
       /* reduce for support function calls */
       if (ic->supportRtn || (ic->op != IFX && ic->op != JUMPTABLE))
        packRegsForSupport (ic, ebp);
@@ -2918,7 +2967,7 @@ packRegisters (eBBlock ** ebpp, int blockno)
       if (POINTER_SET (ic) &&
          /* !isOperandInFarSpace (IC_RIGHT (ic)) && */
          !OP_SYMBOL (IC_RESULT (ic))->remat &&
-         !IS_OP_RUONLY (IC_RIGHT (ic)) 
+         !IS_OP_RUONLY (IC_RIGHT (ic))
          /* && getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1 */ )
        packRegsForOneuse (ic, IC_RESULT (ic), ebp);
 
@@ -2927,15 +2976,15 @@ packRegisters (eBBlock ** ebpp, int blockno)
          IS_SYMOP (IC_LEFT (ic)) &&
          /* !isOperandInFarSpace (IC_RESULT (ic)) && */
          !OP_SYMBOL (IC_LEFT (ic))->remat &&
-         !IS_OP_RUONLY (IC_RESULT (ic)) 
+         !IS_OP_RUONLY (IC_RESULT (ic))
           /* && getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1 */)
        packRegsForOneuse (ic, IC_LEFT (ic), ebp);
 
 
       /* if this is cast for intergral promotion then
-         check if only use of  the definition of the 
+         check if only use of  the definition of the
          operand being casted/ if yes then replace
-         the result of that arithmetic operation with 
+         the result of that arithmetic operation with
          this result and get rid of the cast */
       if (ic->op == CAST)
        {
@@ -2951,7 +3000,7 @@ packRegisters (eBBlock ** ebpp, int blockno)
              if (dic)
                {
                  if (IS_ARITHMETIC_OP (dic))
-                   {                  
+                   {
                      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
                      ReplaceOpWithCheaperOp(&IC_RESULT (dic), IC_RESULT (ic));
                      remiCodeFromeBBlock (ebp, ic);
@@ -2987,8 +3036,8 @@ packRegisters (eBBlock ** ebpp, int blockno)
            }
        }
       #endif
-      
-      /* pack for PUSH 
+
+      /* pack for PUSH
          iTempNN := (some variable in farspace) V1
          push iTempNN ;
          -------------
@@ -2999,32 +3048,7 @@ packRegisters (eBBlock ** ebpp, int blockno)
          packForPush (ic, ebpp, blockno);
        }
 
-
-      #if 1
-      /* 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 x:a
-         combination */
-      if ((IS_ARITHMETIC_OP (ic)
-          || IS_CONDITIONAL(ic)
-          || IS_BITWISE_OP (ic)
-          || ic->op == '='
-           || ic->op == '!'
-           || ic->op == '~'
-          || ic->op == GETHBIT
-          || ic->op == LEFT_OP || ic->op == RIGHT_OP || ic->op == CALL
-          || (ic->op == ADDRESS_OF && isOperandOnStack (IC_LEFT (ic)))
-           || ic->op == RECEIVE
-         ) &&
-         IS_ITEMP (IC_RESULT (ic)) &&
-         getSize (operandType (IC_RESULT (ic))) <= 1)
-
-       packRegsForAccUse (ic);
-      #endif
+      packRegsForAccUse (ic);
     }
 }
 
@@ -3032,8 +3056,10 @@ packRegisters (eBBlock ** ebpp, int blockno)
 /* assignRegisters - assigns registers to each live range as need  */
 /*-----------------------------------------------------------------*/
 void
-hc08_assignRegisters (eBBlock ** ebbs, int count)
+hc08_assignRegisters (ebbIndex * ebbi)
 {
+  eBBlock ** ebbs = ebbi->bbOrder;
+  int count = ebbi->count;
   iCode *ic;
   int i;
 
@@ -3041,12 +3067,14 @@ hc08_assignRegisters (eBBlock ** ebbs, int count)
   setToNull ((void *) &_G.regAssigned);
   setToNull ((void *) &_G.totRegAssigned);
   hc08_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
-  hc08_nRegs = 5;
+  hc08_nRegs = 7;
   hc08_reg_a = hc08_regWithIdx(A_IDX);
   hc08_reg_x = hc08_regWithIdx(X_IDX);
   hc08_reg_h = hc08_regWithIdx(H_IDX);
   hc08_reg_hx = hc08_regWithIdx(HX_IDX);
   hc08_reg_xa = hc08_regWithIdx(XA_IDX);
+  hc08_reg_sp = hc08_regWithIdx(SP_IDX);
+  hc08_nRegs = 5;
 
   /* change assignments this will remove some
      live ranges reducing some register pressure */
@@ -3056,11 +3084,11 @@ hc08_assignRegisters (eBBlock ** ebbs, int count)
   /* liveranges probably changed by register packing
      so we compute them again */
   recomputeLiveRanges (ebbs, count);
-  
+
   if (options.dump_pack)
-    dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
+    dumpEbbsToFileExt (DUMP_PACK, ebbi);
 
-  /* first determine for each live range the number of 
+  /* first determine for each live range the number of
      registers & the type of registers required for each */
   regTypeNum (*ebbs);
 
@@ -3098,7 +3126,7 @@ hc08_assignRegisters (eBBlock ** ebbs, int count)
 
   if (options.dump_rassgn)
     {
-      dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
+      dumpEbbsToFileExt (DUMP_RASSGN, ebbi);
       dumpLiveRanges (DUMP_LRANGE, liveRanges);
     }
 
@@ -3113,8 +3141,8 @@ hc08_assignRegisters (eBBlock ** ebbs, int 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 ();