* as/hc08/lkaomf51.c (OutputName),
[fw/sdcc] / src / hc08 / ralloc.c
index f70c369b36420e7232c2d8ee5d43ac937fa667e2..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)
 
 
                 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.
    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.
    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.
    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
    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"
 -------------------------------------------------------------------------*/
 
 #include "common.h"
@@ -61,21 +61,23 @@ int hc08_ptrRegReq;         /* one byte pointer register required */
 regs regshc08[] =
 {
 
 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_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 ();
 
 static void spillThis (symbol *);
 static void freeAllRegs ();
@@ -87,7 +89,7 @@ static regs *
 allocReg (short type)
 {
   return NULL;
 allocReg (short type)
 {
   return NULL;
-  
+
   if ((type==REG_PTR) && (regshc08[HX_IDX].isFree))
     {
       regshc08[HX_IDX].isFree = 0;
   if ((type==REG_PTR) && (regshc08[HX_IDX].isFree))
     {
       regshc08[HX_IDX].isFree = 0;
@@ -130,7 +132,7 @@ hc08_freeReg (regs * reg)
     }
 
   reg->isFree = 1;
     }
 
   reg->isFree = 1;
-  
+
   switch (reg->rIdx)
     {
       case A_IDX:
   switch (reg->rIdx)
     {
       case A_IDX:
@@ -283,9 +285,9 @@ computeSpillable (iCode * ic)
 {
   bitVect *spillable;
 
 {
   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
      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 */
      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 (!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)))
        {
          hash table we are in serious trouble */
       if (!(sym = hTabItemWithKey (liveRanges, i)))
        {
@@ -434,7 +436,7 @@ leastUsedLR (set * sset)
 
     }
 
 
     }
 
-  setToNull ((void **) &sset);
+  setToNull ((void *) &sset);
   sym->blockSpil = 0;
   return sym;
 }
   sym->blockSpil = 0;
   return sym;
 }
@@ -509,7 +511,7 @@ spillLRWithPtrReg (symbol * forSym)
       int j;
 
       /* if no registers assigned to it or spilt */
       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 ||
          not need to spill it */
 
       if (lrsym->isspilt || !lrsym->nRegs ||
@@ -539,7 +541,7 @@ createStackSpil (symbol * sym)
 
   char slocBuffer[30];
 
 
   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))
     {
      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;
 
   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;
      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);
 
   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);
 
   sym->isspilt = sym->spillA = 1;
   _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
 
@@ -668,7 +670,7 @@ spillThis (symbol * sym)
        sym->regs[i] = NULL;
       }
 
        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))
      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 */
 
       /* 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)
        {
          sym = leastUsedLR (selectS);
          if (sym != forSym)
@@ -823,7 +827,7 @@ spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
       spillLRWithPtrReg (ssym);
     }
 
       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)
     {
      at the start & end of block respectively */
   if (ssym->blockSpil)
     {
@@ -878,7 +882,7 @@ tryAgain:
   if (!spilSomething (ic, ebp, sym))
     return NULL;
 
   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;
 }
      in really selectSpil will abort  */
   goto tryAgain;
 }
@@ -904,7 +908,7 @@ tryAgain:
   if (!spilSomething (ic, ebp, sym))
     return NULL;
 
   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;
 }
      in really selectSpil will abort  */
   goto tryAgain;
 }
@@ -985,7 +989,7 @@ deassignLRs (iCode * ic, eBBlock * ebp)
       if (sym->liveTo > ic->seq)
        continue;
 
       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)
        {
          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 &
        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 &&
          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 = 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 */
              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)
     {
      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;
          check for type gpr */
       if (nFreeRegs (rt) >= nr)
        return 0;
@@ -1169,6 +1174,32 @@ xchgPositions:
   return change;
 }
 
   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  */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 /* serialRegAssign - serially allocate registers to the variables  */
 /*-----------------------------------------------------------------*/
@@ -1234,7 +1265,13 @@ serialRegAssign (eBBlock ** ebbs, int count)
                int j;
                int ptrRegSet = 0;
 
                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 ||
                   or is already assigned to registers
                   or will not live beyond this instructions */
                if (!sym->nRegs ||
@@ -1251,14 +1288,24 @@ serialRegAssign (eBBlock ** ebbs, int count)
                    continue;
                }
                /* if trying to allocate this will cause
                    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);
                   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);
                    spillThis (sym);
-                   continue;                 
+                   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
                }
 
                /* if it has a spillocation & is used less than
@@ -1329,6 +1376,40 @@ serialRegAssign (eBBlock ** ebbs, int count)
            }
        }
     }
            }
        }
     }
+
+    /* 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);
+          }
+      }
+
 }
 
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
@@ -1337,12 +1418,12 @@ serialRegAssign (eBBlock ** ebbs, int count)
 static void fillGaps()
 {
     symbol *sym =NULL;
 static void fillGaps()
 {
     symbol *sym =NULL;
-    int key =0;    
-    
+    int key =0;
+
     if (getenv("DISABLE_FILL_GAPS")) return;
     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;
         sym = hTabNextItem(liveRanges,&key)) {
 
        int i;
@@ -1362,9 +1443,9 @@ static void fillGaps()
 
                clr = hTabItemWithKey(liveRanges,i);
            assert(clr);
 
                clr = hTabItemWithKey(liveRanges,i);
            assert(clr);
-        
+
            /* mark these registers as used */
            /* mark these registers as used */
-           for (k = 0 ; k < clr->nRegs ; k++ ) 
+           for (k = 0 ; k < clr->nRegs ; k++ )
                hc08_useReg(clr->regs[k]);
        }
 
                hc08_useReg(clr->regs[k]);
        }
 
@@ -1379,12 +1460,12 @@ static void fillGaps()
            if (sym->regType == REG_PTR)
                sym->regs[i] = getRegPtrNoSpil ();
            else
            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
        }
 
        /* 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++ ) {
           then give up */
        sym->isspilt = 0;
        for (i = 0 ; i < sym->defs->size ; i++ ) {
@@ -1394,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 (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)));
                }
                    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)));
                }
                    bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) {
                    pdone += positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic)));
                }
@@ -1413,7 +1494,7 @@ static void fillGaps()
                if (!IS_ASSIGN_ICODE(ic)) continue ;
 
                /* if result is assigned to registers */
                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)));
                }
                    bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) {
                    pdone += positionRegs(sym,OP_SYMBOL(IC_RESULT(ic)));
                }
@@ -1429,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"));
            }
            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);
        }
        D(printf ("FILLED GAP for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN"));
        _G.totRegAssigned = bitVectSetBit(_G.totRegAssigned,sym->key);
@@ -1546,7 +1627,7 @@ createRegMask (eBBlock ** ebbs, int count)
          ic->rUsed = regsUsedIniCode (ic);
          _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
 
          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);
             registers that are in use : this is a
             super set of ic->rUsed */
          ic->rMask = newBitVect (hc08_nRegs + 1);
@@ -1593,10 +1674,9 @@ rematStr (symbol * sym)
   char *s = buffer;
   iCode *ic = sym->rematiCode;
 //  int offset = 0;
   char *s = buffer;
   iCode *ic = sym->rematiCode;
 //  int offset = 0;
-  
+
   while (1)
     {
   while (1)
     {
-
       /* if plus or minus print the right hand side */
       if (ic->op == '+' || ic->op == '-')
        {
       /* if plus or minus print the right hand side */
       if (ic->op == '+' || ic->op == '-')
        {
@@ -1606,7 +1686,8 @@ rematStr (symbol * sym)
          ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
          continue;
        }
          ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
          continue;
        }
-/*      
+
+/*
       if (ic->op == '+')
         {
           offset += operandLitValue (IC_RIGHT (ic));
       if (ic->op == '+')
         {
           offset += operandLitValue (IC_RIGHT (ic));
@@ -1626,7 +1707,10 @@ rematStr (symbol * sym)
          continue;
       }
       /* we reached the end */
          continue;
       }
       /* we reached the end */
-      sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
+      if (ic->op == ADDRESS_OF)
+        sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
+      else if (ic->op == '=')
+        sprintf (s, "0x%04x", (int) operandLitValue (IC_RIGHT (ic)) );
       break;
     }
 
       break;
     }
 
@@ -1661,7 +1745,7 @@ regTypeNum (eBBlock *ebbs)
          if (sym->regType == REG_CND)
            continue;
 
          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)
            {
             need registers */
          if (sym->ruonly || sym->accuse)
            {
@@ -1676,34 +1760,13 @@ regTypeNum (eBBlock *ebbs)
              (ic = hTabItemWithKey (iCodehTab,
                                     bitVectFirstBit (sym->defs))) &&
              POINTER_GET (ic) &&
              (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;
                }
 
                  continue;
                }
 
@@ -1838,6 +1901,43 @@ farSpacePackable (iCode * ic)
 }
 #endif
 
 }
 #endif
 
+#if 0
+static void
+packRegsForLiteral (iCode * ic)
+{
+  int k;
+  iCode *uic;
+
+  if (ic->op != '=')
+    return;
+  if (POINTER_SET (ic))
+    return;
+  if (!IS_LITERAL (getSpec (operandType (IC_RIGHT (ic)))))
+    return;
+  if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
+    return;
+
+  for (k=0; k< OP_USES (IC_RESULT (ic))->size; k++)
+    if (bitVectBitValue (OP_USES (IC_RESULT (ic)), k))
+      {
+        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)
+             ReplaceOpWithCheaperOp(&IC_LEFT(uic), IC_RIGHT(ic));
+           if (IC_RIGHT (uic) && IC_RIGHT (uic)->key == IC_RESULT (ic)->key)
+             ReplaceOpWithCheaperOp(&IC_RIGHT(uic), IC_RIGHT(ic));
+           if (IC_RESULT (uic) && IC_RESULT (uic)->key == IC_RESULT (ic)->key)
+             ReplaceOpWithCheaperOp(&IC_RESULT(uic), IC_RIGHT(ic));
+         }
+      }
+
+}
+#endif
+
+
 /*-----------------------------------------------------------------*/
 /* packRegsForAssign - register reduction for assignment           */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 /* packRegsForAssign - register reduction for assignment           */
 /*-----------------------------------------------------------------*/
@@ -1853,7 +1953,6 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
       return 0;
     }
 
       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
   /* if the true symbol is defined in far space or on stack
      then we should not since this will increase register pressure */
 #if 0
@@ -1862,14 +1961,14 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
   }
 #endif
 
   }
 #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
      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.
       */
 
         redundant register usage around function calls.
       */
 
@@ -1928,16 +2027,18 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
     return 0;                  /* did not find */
 
   /* if assignment then check that right is not a bit */
     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 */
       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))
           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 */
     }
   /* if the result is on stack or iaccess then it must be
      the same atleast one of the operands */
@@ -1970,7 +2071,7 @@ pack:
     }
   // TODO: and the otherway around?
 
     }
   // 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)
      delete from all the points inbetween and the new
      one */
   for (sic = dic; sic != ic; sic = sic->next)
@@ -1987,6 +2088,7 @@ pack:
   return 1;
 }
 
   return 1;
 }
 
+
 /*------------------------------------------------------------------*/
 /* findAssignToSym : scanning backwards looks for first assig found */
 /*------------------------------------------------------------------*/
 /*------------------------------------------------------------------*/
 /* findAssignToSym : scanning backwards looks for first assig found */
 /*------------------------------------------------------------------*/
@@ -2003,7 +2105,7 @@ findAssignToSym (operand * op, iCode * ic)
      and eliminate the use of iTempAA, freeing up its register for
      other uses.
   */
      and eliminate the use of iTempAA, freeing up its register for
      other uses.
   */
-     
+
 
   for (dic = ic->prev; dic; dic = dic->prev)
     {
 
   for (dic = ic->prev; dic; dic = dic->prev)
     {
@@ -2012,7 +2114,7 @@ findAssignToSym (operand * op, iCode * ic)
       if (dic->op == '=' &&
          !POINTER_SET (dic) &&
          IC_RESULT (dic)->key == op->key
       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 */
 
        )
        break;  /* found where this temp was defined */
 
@@ -2032,11 +2134,11 @@ findAssignToSym (operand * op, iCode * ic)
 
   /* we are interested only if defined in far space */
   /* or in stack space in case of + & - */
 
   /* 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 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;
   /* if the symbol is volatile then we should not */
   if (isOperandVolatile (IC_RIGHT (dic), TRUE))
     return NULL;
@@ -2047,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; */
   /* 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 */
   /* for + & - operations make sure that
      if it is on the stack it is the same
      as one of the three operands */
@@ -2055,14 +2157,14 @@ findAssignToSym (operand * op, iCode * ic)
   if ((ic->op == '+' || ic->op == '-') &&
       OP_SYMBOL (IC_RIGHT (dic))->onStack)
     {
   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
       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)
   /* now make sure that the right side of dic
      is not defined between ic & dic */
   if (dic)
@@ -2115,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);
 }
   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(assignment))->defs, assignment->key);
   hTabDeleteItem (&iCodehTab, assignment->key, assignment, DELETE_ITEM, NULL);
 }
-  
+
 
 /*-----------------------------------------------------------------*/
 /* packRegsForSupport :- reduce some registers for support calls   */
 
 /*-----------------------------------------------------------------*/
 /* packRegsForSupport :- reduce some registers for support calls   */
@@ -2124,7 +2226,8 @@ static int
 packRegsForSupport (iCode * ic, eBBlock * ebp)
 {
   iCode *dic;
 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 */
   /* for the left & right operand :- look to see if the
      left was assigned a true symbol in far space in that
      case replace them */
@@ -2138,7 +2241,7 @@ packRegsForSupport (iCode * ic, eBBlock * ebp)
        {
          /* found it we need to remove it from the block */
          reassignAliasedSym (ebp, dic, ic, IC_LEFT(ic));
        {
          /* found it we need to remove it from the block */
          reassignAliasedSym (ebp, dic, ic, IC_LEFT(ic));
-         return 1;
+         changes++;
        }
     }
 
        }
     }
 
@@ -2150,25 +2253,13 @@ packRegsForSupport (iCode * ic, eBBlock * ebp)
 
       if (dic)
        {
 
       if (dic)
        {
-         /* if this is a subtraction & the result
-            is a true symbol in far space then don't pack */
-#if 0
-         if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
-           {
-             sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
-             if (IN_FARSPACE (SPEC_OCLS (etype)))
-               return 0;
-           }
-#endif
-         /* found it we need to remove it from the
-            block */
+         /* found it we need to remove it from the block */
          reassignAliasedSym (ebp, dic, ic, IC_RIGHT(ic));
          reassignAliasedSym (ebp, dic, ic, IC_RIGHT(ic));
-         
-         return 1;
+         changes++;
        }
     }
 
        }
     }
 
-  return 0;
+  return changes;
 }
 
 #define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
 }
 
 #define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
@@ -2193,19 +2284,19 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
     return NULL;
 
   return NULL;
     return NULL;
 
   return NULL;
-  
+
   if (ic->op != SEND //RETURN
       && ic->op != SEND
       && !POINTER_SET (ic)
       && !POINTER_GET (ic) )
     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;
 
   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 &&
      (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));
      function or does not contain any variables in
      far space */
   uses = bitVectCopy (OP_USES (op));
@@ -2226,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 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;
        getSize(OP_SYM_TYPE(IC_RIGHT(dic)))) {
       /* than we can not, since we cannot predict the usage of b & acc */
       return NULL;
@@ -2272,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;
   if (POINTER_GET (dic) &&
       !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
     return NULL;
-#endif 
+#endif
 
   sic = dic;
 
 
   sic = dic;
 
@@ -2342,7 +2433,7 @@ isBitwiseOptimizable (iCode * ic)
   sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
 
   /* bitwise operations are considered optimizable
   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
 
      x & lit
      bit & bit
@@ -2407,11 +2498,11 @@ bool operandUsesAcc2(operand *op)
 
 //    if (sym->iaccess && symspace->paged)
 //      return TRUE;  /* must fetch paged indirect sym via accumulator */
 
 //    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_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 */
   }
 
       return TRUE;  /* fetched via accumulator and dptr */
   }
 
@@ -2419,165 +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;
+  int size;
 
 
-  /* if this is an aggregate, e.g. a one byte char array */
-  if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
-    return;
-  }
-
-  /* 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 == IFX || ic->op == JUMPTABLE)    /* these iCodes have no result */
+    return 0;
 
 
-  if (ic->op == PCALL &&
-       IFFUNC_ISREENT(operandType(IC_LEFT(ic))->next) &&
-       FUNC_HASSTACKPARM(operandType(IC_LEFT(ic))->next))
-      return;
-  #endif
+  if (POINTER_SET (ic))
+    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 (!IC_RESULT (ic))
+    return 0;
 
 
+  if (!IS_ITEMP (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;
+  /* I don't think an iTemp can be an aggregate, but just in case */
+  if (IS_AGGREGATE(operandType(IC_RESULT(ic))))
+    return 0;
 
 
-  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;
+  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))
-    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;
     }
   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;
   OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_XA;
+  return 1;
 }
 
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
@@ -2622,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) {
        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 */
        return ;
     }
     /* make sure they have the same type */
@@ -2630,7 +2721,7 @@ packForPush (iCode * ic, eBBlock ** ebpp, int blockno)
     {
       sym_link *itype=operandType(IC_LEFT(ic));
       sym_link *ditype=operandType(IC_RIGHT(dic));
     {
       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;
       if (SPEC_USIGN(itype)!=SPEC_USIGN(ditype) ||
          SPEC_LONG(itype)!=SPEC_LONG(ditype))
        return;
@@ -2640,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);
       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 */
 
   /* we now we know that it has one & only one def & use
      and the that the definition is an assignment */
@@ -2682,7 +2773,9 @@ packRegisters (eBBlock ** ebpp, int blockno)
 
   for (ic = ebp->sch; ic; ic = ic->next)
     {
 
   for (ic = ebp->sch; ic; ic = ic->next)
     {
-      /* if this is an itemp & result of an address of a true sym 
+      //packRegsForLiteral (ic);
+
+      /* 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)) &&
          then mark this as rematerialisable   */
       if (ic->op == ADDRESS_OF &&
          IS_ITEMP (IC_RESULT (ic)) &&
@@ -2696,7 +2789,20 @@ packRegisters (eBBlock ** ebpp, int blockno)
          OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
 
        }
          OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
 
        }
+#if 1
+      if (ic->op == '=' &&
+          !POINTER_SET (ic) &&
+         IS_ITEMP (IC_RESULT (ic)) &&
+         IS_VALOP (IC_RIGHT (ic)) &&
+         bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1)
+       {
+
+         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
 
 
+       }
+#endif
       /* if straight assignment then carry remat flag if
          this is the only definition */
       if (ic->op == '=' &&
       /* if straight assignment then carry remat flag if
          this is the only definition */
       if (ic->op == '=' &&
@@ -2715,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 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));
          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;
              }
       }
 
                      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)) &&
          then mark this as rematerializable as well */
       if ((ic->op == '+' || ic->op == '-') &&
          (IS_SYMOP (IC_LEFT (ic)) &&
@@ -2792,8 +2898,59 @@ packRegisters (eBBlock ** ebpp, int blockno)
          continue;
        }
 
          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 */
       /* reduce for support function calls */
-      if (ic->supportRtn || ic->op == '+' || ic->op == '-')
+      if (ic->supportRtn || (ic->op != IFX && ic->op != JUMPTABLE))
        packRegsForSupport (ic, ebp);
 
       #if 0
        packRegsForSupport (ic, ebp);
 
       #if 0
@@ -2810,7 +2967,7 @@ packRegisters (eBBlock ** ebpp, int blockno)
       if (POINTER_SET (ic) &&
          /* !isOperandInFarSpace (IC_RIGHT (ic)) && */
          !OP_SYMBOL (IC_RESULT (ic))->remat &&
       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);
 
          /* && getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1 */ )
        packRegsForOneuse (ic, IC_RESULT (ic), ebp);
 
@@ -2819,15 +2976,15 @@ packRegisters (eBBlock ** ebpp, int blockno)
          IS_SYMOP (IC_LEFT (ic)) &&
          /* !isOperandInFarSpace (IC_RESULT (ic)) && */
          !OP_SYMBOL (IC_LEFT (ic))->remat &&
          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
           /* && 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
          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)
        {
          this result and get rid of the cast */
       if (ic->op == CAST)
        {
@@ -2843,7 +3000,7 @@ packRegisters (eBBlock ** ebpp, int blockno)
              if (dic)
                {
                  if (IS_ARITHMETIC_OP (dic))
              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);
                      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
                      ReplaceOpWithCheaperOp(&IC_RESULT (dic), IC_RESULT (ic));
                      remiCodeFromeBBlock (ebp, ic);
@@ -2879,8 +3036,8 @@ packRegisters (eBBlock ** ebpp, int blockno)
            }
        }
       #endif
            }
        }
       #endif
-      
-      /* pack for PUSH 
+
+      /* pack for PUSH
          iTempNN := (some variable in farspace) V1
          push iTempNN ;
          -------------
          iTempNN := (some variable in farspace) V1
          push iTempNN ;
          -------------
@@ -2891,29 +3048,7 @@ packRegisters (eBBlock ** ebpp, int blockno)
          packForPush (ic, ebpp, 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 == GETHBIT
-          || ic->op == LEFT_OP || ic->op == RIGHT_OP || ic->op == CALL
-          || (ic->op == ADDRESS_OF && isOperandOnStack (IC_LEFT (ic)))
-         ) &&
-         IS_ITEMP (IC_RESULT (ic)) &&
-         getSize (operandType (IC_RESULT (ic))) <= 1)
-
-       packRegsForAccUse (ic);
-      #endif
+      packRegsForAccUse (ic);
     }
 }
 
     }
 }
 
@@ -2921,8 +3056,10 @@ packRegisters (eBBlock ** ebpp, int blockno)
 /* assignRegisters - assigns registers to each live range as need  */
 /*-----------------------------------------------------------------*/
 void
 /* 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;
 
   iCode *ic;
   int i;
 
@@ -2930,22 +3067,28 @@ hc08_assignRegisters (eBBlock ** ebbs, int count)
   setToNull ((void *) &_G.regAssigned);
   setToNull ((void *) &_G.totRegAssigned);
   hc08_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
   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_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 */
   for (i = 0; i < count; i++)
     packRegisters (ebbs, i);
 
 
   /* change assignments this will remove some
      live ranges reducing some register pressure */
   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)
   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);
 
      registers & the type of registers required for each */
   regTypeNum (*ebbs);
 
@@ -2983,7 +3126,7 @@ hc08_assignRegisters (eBBlock ** ebbs, int count)
 
   if (options.dump_rassgn)
     {
 
   if (options.dump_rassgn)
     {
-      dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
+      dumpEbbsToFileExt (DUMP_RASSGN, ebbi);
       dumpLiveRanges (DUMP_LRANGE, liveRanges);
     }
 
       dumpLiveRanges (DUMP_LRANGE, liveRanges);
     }
 
@@ -2998,8 +3141,8 @@ hc08_assignRegisters (eBBlock ** ebbs, int count)
   /* free up any _G.stackSpil locations allocated */
   applyToSet (_G.stackSpil, deallocStackSpil);
   _G.slocNum = 0;
   /* 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 ();
 
   /* mark all registers as free */
   freeAllRegs ();