* src/SDCCpeeph.c: made labelHashEntry global, made pcDistance, FBYNAME static,
[fw/sdcc] / src / z80 / ralloc.c
index 93f4e37b068130e82a0db9d8b821813d7d77a205..b8ad485a655deca9ea0efc3ef4fc3a98e344b6dc 100644 (file)
@@ -7,8 +7,9 @@
     hardware.  It allocates based on usage and how long the varible
     lives into registers or temporary memory on the stack.
 
-    On the Z80 hl, ix, iy, and a are reserved for the code generator,
-    leaving bc and de for allocation.  The extra register pressure
+    On the Z80 hl and ix and a are reserved for the code generator,
+    leaving bc and de for allocation.  iy is unusable due to currently
+    as it's only adressable as a pair.  The extra register pressure
     from reserving hl is made up for by how much easier the sub
     operations become.  You could swap hl for iy if the undocumented
     iyl/iyh instructions are available.
 */
 
 #include "z80.h"
+#include "SDCCicode.h"
 
-enum {
-    DISABLE_PACK_ACC   = 0,
-    DISABLE_PACK_ASSIGN        = 0,
-    LIMITED_PACK_ACC   = 1
-};
-
-#define D_ALLOC                1
-
-#if 0
+/* Flags to turn off optimisations.
+ */
+enum
+  {
+    DISABLE_PACK_ACC = 0,
+    DISABLE_PACK_ASSIGN = 0,
+    DISABLE_PACK_ONE_USE = 0,
+    DISABLE_PACK_HL = 1,
+    DISABLE_PACK_IY = 0
+  };
+
+/* Flags to turn on debugging code.
+ */
+enum
+  {
+    D_ALLOC = 0,
+    D_ALLOC2 = 0,
+    D_ACCUSE2 = 0,
+    D_ACCUSE2_VERBOSE = 0,
+    D_HLUSE = 0,
+    D_HLUSE2 = 0,
+    D_HLUSE2_VERBOSE = 0,
+    D_FILL_GAPS = 0,
+    D_PACK_IY = 0,
+    D_PACK_HLUSE3 = 0
+  };
+
+#if 1
 #define D(_a, _s)      if (_a)  { printf _s; fflush(stdout); }
 #else
 #define D(_a, _s)
 #endif
 
-/*-----------------------------------------------------------------*/
-/* At this point we start getting processor specific although      */
-/* some routines are non-processor specific & can be reused when   */
-/* targetting other processors. The decision for this will have    */
-/* to be made on a routine by routine basis                        */
-/* routines used to pack registers are most definitely not reusable*/
-/* since the pack the registers depending strictly on the MCU      */
-/*-----------------------------------------------------------------*/
+#define DISABLE_PACKREGSFORSUPPORT     1
+#define DISABLE_PACKREGSFORACCUSE      1
 
-bitVect *spiltSet = NULL ; 
-set *stackSpil = NULL;
-bitVect *regAssigned = NULL;
-short blockSpil = 0;
-int slocNum = 0 ;
-extern void genZ80Code(iCode *);
-bitVect *funcrUsed = NULL; /* registers used in a function */
-int stackExtend = 0;
-int dataExtend  = 0;
-int _nRegs;
-
-/** Set to help debug register pressure related problems */
-#define DEBUG_FAKE_EXTRA_REGS  0
-
-static regs _gbz80_regs[] = {
-    { REG_GPR, C_IDX , "c", 1 },
-    { REG_GPR, B_IDX , "b", 1 },
-    { REG_CND, CND_IDX, "c", 1}
+extern void genZ80Code (iCode *);
+
+/** Local static variables */
+static struct
+{
+  bitVect *spiltSet;
+  set *stackSpil;
+  bitVect *regAssigned;
+  bitVect *totRegAssigned;    /* final set of LRs that got into registers */
+  short blockSpil;
+  int slocNum;
+  /* registers used in a function */
+  bitVect *funcrUsed;
+  int stackExtend;
+  int dataExtend;
+  int nRegs;
+} _G;
+
+static regs _gbz80_regs[] =
+{
+  {REG_GPR, C_IDX, "c", 1},
+  {REG_GPR, B_IDX, "b", 1},
+  {REG_CND, CND_IDX, "c", 1}
 };
 
-static regs _z80_regs[] = {
-    { REG_GPR, C_IDX , "c", 1 },
-    { REG_GPR, B_IDX , "b", 1 },
-    { REG_GPR, E_IDX , "e", 1 },
-    { REG_GPR, D_IDX , "d", 1 },
-    /*    { REG_GPR, L_IDX , "l", 1 },
-    { REG_GPR, H_IDX , "h", 1 },*/
-#if DEBUG_FAKE_EXTRA_REGS
-    { REG_GPR, M_IDX , "m", 1 },
-    { REG_GPR, N_IDX , "n", 1 },
-    { REG_GPR, O_IDX , "o", 1 },
-    { REG_GPR, P_IDX , "p", 1 },
-    { REG_GPR, Q_IDX , "q", 1 },
-    { REG_GPR, R_IDX , "r", 1 },
-    { REG_GPR, S_IDX , "s", 1 },
-    { REG_GPR, T_IDX , "t", 1 },
-#endif
-    { REG_CND, CND_IDX, "c", 1}
+static regs _z80_regs[] =
+{
+  {REG_GPR, C_IDX, "c", 1},
+  {REG_GPR, B_IDX, "b", 1},
+  {REG_GPR, E_IDX, "e", 1},
+  {REG_GPR, D_IDX, "d", 1},
+  {REG_CND, CND_IDX, "c", 1}
 };
 
 regs *regsZ80;
@@ -114,6 +123,7 @@ regs *regsZ80;
 #define GBZ80_MAX_REGS ((sizeof(_gbz80_regs)/sizeof(_gbz80_regs[0]))-1)
 
 static void spillThis (symbol *);
+static void freeAllRegs ();
 
 /** Allocates register of given type.
     'type' is not used on the z80 version.  It was used to select
@@ -121,144 +131,146 @@ static void spillThis (symbol *);
 
     @return            Pointer to the newly allocated register.
  */
-static regs *allocReg (short type)
+static regs *
+allocReg (short type)
 {
-    int i;
-
-    for ( i = 0 ; i < _nRegs ; i++ ) {
-       /* For now we allocate from any free */
-       if (regsZ80[i].isFree ) {
-           regsZ80[i].isFree = 0;
-           if (currFunc)
-               currFunc->regsUsed = 
-                   bitVectSetBit(currFunc->regsUsed,i);
-           D(D_ALLOC, ("allocReg: alloced %zr\n", &regsZ80[i]));
-           return &regsZ80[i];
+  int i;
+
+  for (i = 0; i < _G.nRegs; i++)
+    {
+      /* For now we allocate from any free */
+      if (regsZ80[i].isFree)
+       {
+         regsZ80[i].isFree = 0;
+         if (currFunc)
+            {
+              currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, i);
+            }
+         D (D_ALLOC, ("allocReg: alloced %p\n", &regsZ80[i]));
+         return &regsZ80[i];
        }
     }
-    D(D_ALLOC, ("allocReg: No free.\n"));
-    return NULL;
+  (D_ALLOC, ("allocReg: No free.\n"));
+  return NULL;
 }
 
 /** Returns pointer to register wit index number
  */
-regs *regWithIdx (int idx)
+regs *
+regWithIdx (int idx)
 {
-    int i;
-    
-    for (i=0;i < _nRegs;i++)
-       if (regsZ80[i].rIdx == idx)
-           return &regsZ80[i];
-    
-    werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-          "regWithIdx not found");
-    exit(1);
+  int i;
+
+  for (i = 0; i < _G.nRegs; i++)
+    {
+      if (regsZ80[i].rIdx == idx)
+        {
+          return &regsZ80[i];
+        }
+    }
+
+  wassertl (0, "regWithIdx not found");
+  exit (1);
 }
 
 /** Frees a register.
  */
-static void freeReg (regs *reg)
+static void 
+freeReg (regs * reg)
 {
-    wassert(!reg->isFree);
-    reg->isFree = 1;
-    D(D_ALLOC, ("freeReg: freed %zr\n", reg));
+  wassert (!reg->isFree);
+  reg->isFree = 1;
+  D (D_ALLOC, ("freeReg: freed %p\n", reg));
 }
 
 
 /** Returns number of free registers.
  */
-static int nFreeRegs (int type)
+static int 
+nFreeRegs (int type)
 {
-    int i;
-    int nfr=0;
-    
-    for (i = 0 ; i < _nRegs; i++ ) {
-       /* For now only one reg type */
-       if (regsZ80[i].isFree)
-           nfr++;
+  int i;
+  int nfr = 0;
+
+  for (i = 0; i < _G.nRegs; i++)
+    {
+      /* For now only one reg type */
+      if (regsZ80[i].isFree)
+        {
+          nfr++;
+        }
     }
-    return nfr;
+  return nfr;
 }
 
 /** Free registers with type.
  */
-static int nfreeRegsType (int type)
+static int 
+nfreeRegsType (int type)
 {
-    int nfr ;
-    if (type == REG_PTR) {
-       if ((nfr = nFreeRegs(type)) == 0)
-           return nFreeRegs(REG_GPR);
-    } 
-    
-    return nFreeRegs(type);
-}
+  int nfr;
+  if (type == REG_PTR)
+    {
+      if ((nfr = nFreeRegs (type)) == 0)
+        {
+          return nFreeRegs (REG_GPR);
+        }
+    }
 
+  return nFreeRegs (type);
+}
 
-#if 0
 /*-----------------------------------------------------------------*/
-/* allDefsOutOfRange - all definitions are out of a range          */
+/* useReg - marks a register  as used                              */
 /*-----------------------------------------------------------------*/
-static bool allDefsOutOfRange (bitVect *defs,int fseq, int toseq) 
+static void
+useReg (regs * reg)
 {
-    int i ;
-
-    if (!defs)
-       return TRUE ;
-
-    for ( i = 0 ;i < defs->size ; i++ ) {
-       iCode *ic;
-
-       if (bitVectBitValue(defs,i)             &&
-           (ic = hTabItemWithKey(iCodehTab,i)) &&
-           ( ic->seq >= fseq  && ic->seq <= toseq))
-           
-           return FALSE;
-       
-    }
-    
-    return TRUE;
+  reg->isFree = 0;
 }
-#endif
-  
+
 /*-----------------------------------------------------------------*/
 /* computeSpillable - given a point find the spillable live ranges */
 /*-----------------------------------------------------------------*/
-static bitVect *computeSpillable (iCode *ic)
+static bitVect *
+computeSpillable (iCode * ic)
 {
-    bitVect *spillable ;
-
-    /* spillable live ranges are those that are live at this 
-       point . the following categories need to be subtracted
-       from this set. 
-       a) - those that are already spilt
-       b) - if being used by this one
-       c) - defined by this one */
-    
-    spillable = bitVectCopy(ic->rlive);
-    spillable = 
-       bitVectCplAnd(spillable,spiltSet); /* those already spilt */
-    spillable = 
-       bitVectCplAnd(spillable,ic->uses); /* used in this one */    
-    bitVectUnSetBit(spillable,ic->defKey);
-    spillable = bitVectIntersect(spillable,regAssigned);
-    return spillable;
-    
+  bitVect *spillable;
+
+  /* spillable live ranges are those that are live at this 
+     point . the following categories need to be subtracted
+     from this set. 
+     a) - those that are already spilt
+     b) - if being used by this one
+     c) - defined by this one */
+
+  spillable = bitVectCopy (ic->rlive);
+  spillable =
+    bitVectCplAnd (spillable, _G.spiltSet);    /* those already spilt */
+  spillable =
+    bitVectCplAnd (spillable, ic->uses);       /* used in this one */
+  bitVectUnSetBit (spillable, ic->defKey);
+  spillable = bitVectIntersect (spillable, _G.regAssigned);
+
+  return spillable;
 }
 
 /*-----------------------------------------------------------------*/
 /* noSpilLoc - return true if a variable has no spil location      */
 /*-----------------------------------------------------------------*/
-static int noSpilLoc (symbol *sym, eBBlock *ebp,iCode *ic)
+static int 
+noSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
 {
-    return (sym->usl.spillLoc ? 0 : 1);
+  return (sym->usl.spillLoc ? 0 : 1);
 }
 
 /*-----------------------------------------------------------------*/
 /* hasSpilLoc - will return 1 if the symbol has spil location      */
 /*-----------------------------------------------------------------*/
-static int hasSpilLoc (symbol *sym, eBBlock *ebp, iCode *ic)
+static int 
+hasSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
 {
-    return (sym->usl.spillLoc ? 1 : 0);
+  return (sym->usl.spillLoc ? 1 : 0);
 }
 
 /** Will return 1 if the remat flag is set.
@@ -266,549 +278,658 @@ static int hasSpilLoc (symbol *sym, eBBlock *ebp, iCode *ic)
     into registers at creation as it can be re-created at any time -
     i.e. it's constant in some way.
 */
-static int rematable (symbol *sym, eBBlock *ebp, iCode *ic)
+static int 
+rematable (symbol * sym, eBBlock * ebp, iCode * ic)
 {
-    return sym->remat;
+  return sym->remat;
 }
 
 /*-----------------------------------------------------------------*/
 /* allLRs - return true for all                                    */
 /*-----------------------------------------------------------------*/
-static int allLRs (symbol *sym, eBBlock *ebp, iCode *ic)
+static int 
+allLRs (symbol * sym, eBBlock * ebp, iCode * ic)
 {
-    return 1;
+  return 1;
 }
 
-/*-----------------------------------------------------------------*/
-/* liveRangesWith - applies function to a given set of live range  */
-/*-----------------------------------------------------------------*/
-set *liveRangesWith (bitVect *lrs, int (func)(symbol *,eBBlock *, iCode *),
-                    eBBlock *ebp, iCode *ic)
+/** liveRangesWith - applies function to a given set of live range 
+ */
+static set *
+liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
+               eBBlock * ebp, iCode * ic)
 {
-    set *rset = NULL;
-    int i;
+  set *rset = NULL;
+  int i;
 
-    if (!lrs || !lrs->size)
-       return NULL;
-
-    for ( i = 1 ; i < lrs->size ; i++ ) {
-       symbol *sym;
-       if (!bitVectBitValue(lrs,i))
-           continue ;
+  if (!lrs || !lrs->size)
+    return NULL;
 
-       /* if we don't find it in the live range 
-          hash table we are in serious trouble */
-       if (!(sym = hTabItemWithKey(liveRanges,i))) {
-           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-                  "liveRangesWith could not find liveRange");
-           exit(1);
+  for (i = 1; i < lrs->size; i++)
+    {
+      symbol *sym;
+      if (!bitVectBitValue (lrs, i))
+       continue;
+
+      /* if we don't find it in the live range 
+         hash table we are in serious trouble */
+      if (!(sym = hTabItemWithKey (liveRanges, i)))
+       {
+          wassertl (0, "liveRangesWith could not find liveRange");
+         exit (1);
        }
-       
-       if (func(sym,ebp,ic) && bitVectBitValue(regAssigned,sym->key))
-           addSetHead(&rset,sym);
+
+      if (func (sym, ebp, ic) && bitVectBitValue (_G.regAssigned, sym->key))
+        {
+          addSetHead (&rset, sym);
+        }
     }
 
-    return rset;
+  return rset;
 }
 
 
-/*-----------------------------------------------------------------*/
-/* leastUsedLR - given a set determines which is the least used    */
-/*-----------------------------------------------------------------*/
-symbol *leastUsedLR (set *sset)
+/** leastUsedLR - given a set determines which is the least used 
+ */
+static symbol *
+leastUsedLR (set * sset)
 {
-    symbol *sym = NULL, *lsym = NULL ;
-    
-    sym = lsym = setFirstItem(sset);
+  symbol *sym = NULL, *lsym = NULL;
 
-    if (!lsym)
-       return NULL;
+  sym = lsym = setFirstItem (sset);
 
-    for (; lsym; lsym = setNextItem(sset)) {
-       
-       /* if usage is the same then prefer
-          the spill the smaller of the two */
-       if ( lsym->used == sym->used )
-           if (getSize(lsym->type) < getSize(sym->type))
-               sym = lsym;
-
-       /* if less usage */
-       if (lsym->used < sym->used )
-           sym = lsym;
-       
-   }
-
-    setToNull((void **)&sset);
-    sym->blockSpil = 0;
-    return sym;
+  if (!lsym)
+    return NULL;
+
+  for (; lsym; lsym = setNextItem (sset))
+    {
+
+      /* if usage is the same then prefer
+         the spill the smaller of the two */
+      if (lsym->used == sym->used)
+       if (getSize (lsym->type) < getSize (sym->type))
+         sym = lsym;
+
+      /* if less usage */
+      if (lsym->used < sym->used)
+       sym = lsym;
+
+    }
+
+  setToNull ((void *) &sset);
+  sym->blockSpil = 0;
+  return sym;
 }
 
-/*-----------------------------------------------------------------*/
-/* noOverLap - will iterate through the list looking for over lap  */
-/*-----------------------------------------------------------------*/
-static int noOverLap (set *itmpStack, symbol *fsym)
+/** noOverLap - will iterate through the list looking for over lap
+ */
+static int 
+noOverLap (set * itmpStack, symbol * fsym)
 {
-    symbol *sym;
-   
-    for (sym = setFirstItem(itmpStack); sym;
-        sym = setNextItem(itmpStack)) {
-       if (sym->liveTo > fsym->liveFrom )
-           return 0;
-           
+  symbol *sym;
+
+  for (sym = setFirstItem (itmpStack); sym;
+       sym = setNextItem (itmpStack))
+    {
+      if (bitVectBitValue(sym->clashes,fsym->key)) 
+        return 0;
+#if 0
+            // if sym starts before (or on) our end point
+            // and ends after (or on) our start point, 
+            // it is an overlap.
+           if (sym->liveFrom <= fsym->liveTo &&
+               sym->liveTo   >= fsym->liveFrom)
+           {
+               return 0;
+           }
+#endif
     }
-    return 1;
+  return 1;
 }
 
 /*-----------------------------------------------------------------*/
 /* isFree - will return 1 if the a free spil location is found     */
 /*-----------------------------------------------------------------*/
-DEFSETFUNC(isFree)
+DEFSETFUNC (isFree)
 {
-    symbol *sym = item;
-    V_ARG(symbol **,sloc);
-    V_ARG(symbol *,fsym);
+  symbol *sym = item;
+  V_ARG (symbol **, sloc);
+  V_ARG (symbol *, fsym);
 
-    /* if already found */
-    if (*sloc)
-       return 0;
+  /* if already found */
+  if (*sloc)
+    return 0;
 
-    /* if it is free && and the itmp assigned to
-       this does not have any overlapping live ranges
-       with the one currently being assigned and
-       the size can be accomodated  */
-    if (sym->isFree                        && 
-       noOverLap(sym->usl.itmpStack,fsym) &&
-       getSize(sym->type) >= getSize(fsym->type)) {
-       *sloc = sym;
-       return 1;
+  /* if it is free && and the itmp assigned to
+     this does not have any overlapping live ranges
+     with the one currently being assigned and
+     the size can be accomodated  */
+  if (sym->isFree &&
+      noOverLap (sym->usl.itmpStack, fsym) &&
+      getSize (sym->type) >= getSize (fsym->type))
+    {
+      *sloc = sym;
+      return 1;
     }
 
-    return 0;
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* createStackSpil - create a location on the stack to spil        */
 /*-----------------------------------------------------------------*/
-symbol *createStackSpil (symbol *sym)
+static symbol *
+createStackSpil (symbol * sym)
 {
-    symbol *sloc= NULL;
-
-    D(D_ALLOC, ("createStackSpil: for sym %zs\n", sym));
-
-    /* first go try and find a free one that is already 
-       existing on the stack */
-    if (applyToSet(stackSpil,isFree,&sloc, sym)) {
-       /* found a free one : just update & return */
-       sym->usl.spillLoc = sloc;
-       sym->stackSpil= 1;
-       sloc->isFree = 0;
-       addSetHead(&sloc->usl.itmpStack,sym);
-       D(D_ALLOC, ("createStackSpil: found existing\n"));
-       return sym;
-    }
-
-    /* could not then have to create one , this is the hard part
-       we need to allocate this on the stack : this is really a
-       hack!! but cannot think of anything better at this time */
-       
-    sprintf(buffer,"sloc%d",slocNum++);
-    sloc = newiTemp(buffer);
-
-    /* set the type to the spilling symbol */
-    sloc->type = copyLinkChain(sym->type);
-    sloc->etype = getSpec(sloc->type);
-    SPEC_SCLS(sloc->etype) = S_AUTO ;    
-
-    /* we don't allow it to be allocated`
-       onto the external stack since : so we
-       temporarily turn it off ; we also
-       turn off memory model to prevent
-       the spil from going to the external storage
-       and turn off overlaying 
-    */
-    allocLocal(sloc);
-
-    sloc->isref = 1; /* to prevent compiler warning */
-    
-    /* if it is on the stack then update the stack */
-    if (IN_STACK(sloc->etype)) {
-       currFunc->stack += getSize(sloc->type);
-       stackExtend += getSize(sloc->type);
-    } else
-       dataExtend += getSize(sloc->type);
-
-    /* add it to the stackSpil set */
-    addSetHead(&stackSpil,sloc);
-    sym->usl.spillLoc = sloc;
-    sym->stackSpil = 1;
-    
-    /* add it to the set of itempStack set 
-       of the spill location */
-    addSetHead(&sloc->usl.itmpStack,sym);
+  symbol *sloc = NULL;
+
+  D (D_ALLOC, ("createStackSpil: for sym %p\n", sym));
+
+  /* first go try and find a free one that is already 
+     existing on the stack */
+  if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
+    {
+      /* found a free one : just update & return */
+      sym->usl.spillLoc = sloc;
+      sym->stackSpil = 1;
+      sloc->isFree = 0;
+      addSetHead (&sloc->usl.itmpStack, sym);
+      D (D_ALLOC, ("createStackSpil: found existing\n"));
+      return sym;
+    }
+
+  /* could not then have to create one , this is the hard part
+     we need to allocate this on the stack : this is really a
+     hack!! but cannot think of anything better at this time */
+
+  sprintf (buffer, "sloc%d", _G.slocNum++);
+  sloc = newiTemp (buffer);
+
+  /* set the type to the spilling symbol */
+  sloc->type = copyLinkChain (sym->type);
+  sloc->etype = getSpec (sloc->type);
+  SPEC_SCLS (sloc->etype) = S_AUTO;
+  SPEC_EXTR (sloc->etype) = 0;
+  SPEC_STAT (sloc->etype) = 0;
+  SPEC_VOLATILE(sloc->etype) = 0;
+
+  allocLocal (sloc);
+
+  sloc->isref = 1;             /* to prevent compiler warning */
 
-    D(D_ALLOC, ("createStackSpil: created new\n"));
-    return sym;
+  /* if it is on the stack then update the stack */
+  if (IN_STACK (sloc->etype))
+    {
+      currFunc->stack += getSize (sloc->type);
+      _G.stackExtend += getSize (sloc->type);
+    }
+  else
+    {
+      _G.dataExtend += getSize (sloc->type);
+    }
+
+  /* add it to the stackSpil set */
+  addSetHead (&_G.stackSpil, sloc);
+  sym->usl.spillLoc = sloc;
+  sym->stackSpil = 1;
+
+  /* add it to the set of itempStack set 
+     of the spill location */
+  addSetHead (&sloc->usl.itmpStack, sym);
+
+  D (D_ALLOC, ("createStackSpil: created new\n"));
+  return sym;
 }
 
 /*-----------------------------------------------------------------*/
-/* isSpiltOnStack - returns true if the spil location is on stack  */
+/* spillThis - spils a specific operand                            */
 /*-----------------------------------------------------------------*/
-bool isSpiltOnStack (symbol *sym)
+static void 
+spillThis (symbol * sym)
 {
-    link *etype;
+  int i;
 
-    if (!sym)
-       return FALSE ;
-    
-    if (!sym->isspilt)
-       return FALSE ;
+  D (D_ALLOC, ("spillThis: spilling %p\n", sym));
 
-/*     if (sym->stackSpil) */
-/*     return TRUE; */
-    
-    if (!sym->usl.spillLoc)
-       return FALSE;
+  /* if this is rematerializable or has a spillLocation
+     we are okay, else we need to create a spillLocation
+     for it */
+  if (!(sym->remat || sym->usl.spillLoc))
+    {
+      createStackSpil (sym);
+    }
+
+  /* mark it has spilt & put it in the spilt set */
+  sym->isspilt = sym->spillA = 1;
+  _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
 
-    etype = getSpec(sym->usl.spillLoc->type);
-    if (IN_STACK(etype))
-       return TRUE;
+  bitVectUnSetBit (_G.regAssigned, sym->key);
+  bitVectUnSetBit (_G.totRegAssigned, sym->key);
+
+  for (i = 0; i < sym->nRegs; i++)
+    {
+      if (sym->regs[i])
+       {
+         freeReg (sym->regs[i]);
+         sym->regs[i] = NULL;
+       }
+    }
 
-    return FALSE ;
+  if (sym->usl.spillLoc && !sym->remat)
+    {
+      sym->usl.spillLoc->allocreq++;
+    }
+  return;
 }
 
+#if DISABLED
 /*-----------------------------------------------------------------*/
-/* spillThis - spils a specific operand                            */
+/* allDefsOutOfRange - all definitions are out of a range          */
 /*-----------------------------------------------------------------*/
-static void spillThis (symbol *sym)
+static bool
+allDefsOutOfRange (bitVect * defs, int fseq, int toseq)
 {
-    int i;
-
-    D(D_ALLOC, ("spillThis: spilling %zs\n", sym));
-
-    /* if this is rematerializable or has a spillLocation
-       we are okay, else we need to create a spillLocation
-       for it */
-    if (!(sym->remat || sym->usl.spillLoc)) 
-       createStackSpil (sym);
-
-    /* mark it has spilt & put it in the spilt set */
-    sym->isspilt = 1;
-    spiltSet = bitVectSetBit(spiltSet,sym->key);
-       
-    bitVectUnSetBit(regAssigned,sym->key);
-
-    for (i = 0 ; i < sym->nRegs ; i++) {
-       if (sym->regs[i]) {
-           freeReg(sym->regs[i]);
-           sym->regs[i] = NULL;
-       }
+  int i;
+
+  if (!defs)
+    return TRUE;
+
+  for (i = 0; i < defs->size; i++)
+    {
+      iCode *ic;
+
+      if (bitVectBitValue (defs, i) &&
+         (ic = hTabItemWithKey (iCodehTab, i)) &&
+         (ic->seq >= fseq && ic->seq <= toseq))
+
+       return FALSE;
+
     }
-    
-    /* if spilt on stack then free up r0 & r1 
-       if they could have been assigned to some
-       LIVE ranges */
-    if (sym->usl.spillLoc && !sym->remat)
-       sym->usl.spillLoc->allocreq = 1;
-    return;
+
+  return TRUE;
+}
+
+/*-----------------------------------------------------------------*/
+/* hasSpilLocnoUptr - will return 1 if the symbol has spil location */
+/*                    but is not used as a pointer                 */
+/*-----------------------------------------------------------------*/
+static int
+hasSpilLocnoUptr (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return ((sym->usl.spillLoc && !sym->uptr) ? 1 : 0);
+}
+
+/*-----------------------------------------------------------------*/
+/* notUsedInRemaining - not used or defined in remain of the block */
+/*-----------------------------------------------------------------*/
+static int
+notUsedInRemaining (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return ((usedInRemaining (operandFromSymbol (sym), ic) ? 0 : 1) &&
+         allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
 }
+#endif
 
 /** Select a iTemp to spil : rather a simple procedure.
  */
-symbol *selectSpil (iCode *ic, eBBlock *ebp, symbol *forSym)
+symbol *
+selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
 {
-    bitVect *lrcs= NULL ; 
-    set *selectS ;
-    symbol *sym;
+  bitVect *lrcs = NULL;
+  set *selectS;
+  symbol *sym;
 
-    D(D_ALLOC, ("selectSpil: finding spill for ic %zi\n", ic));
-    /* get the spillable live ranges */
-    lrcs = computeSpillable (ic);
+  D (D_ALLOC, ("selectSpil: finding spill for ic %p\n", ic));
+  /* get the spillable live ranges */
+  lrcs = computeSpillable (ic);
 
-    /* get all live ranges that are rematerizable */
-    if ((selectS = liveRangesWith(lrcs,rematable,ebp,ic))) {
-       D(D_ALLOC, ("selectSpil: using remat.\n"));
-       /* return the least used of these */
-       return leastUsedLR(selectS);
+  /* get all live ranges that are rematerizable */
+  if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
+    {
+      D (D_ALLOC, ("selectSpil: using remat.\n"));
+      /* return the least used of these */
+      return leastUsedLR (selectS);
     }
 
 #if 0
-    /* get live ranges with spillLocations in direct space */
-    if ((selectS = liveRangesWith(lrcs,directSpilLoc,ebp,ic))) {
-       sym = leastUsedLR(selectS);
-       strcpy(sym->rname,(sym->usl.spillLoc->rname[0] ? 
-                          sym->usl.spillLoc->rname : 
-                          sym->usl.spillLoc->name)); 
-       sym->spildir = 1;
-       /* mark it as allocation required */
-       sym->usl.spillLoc->allocreq = 1;
-       return sym;
-    }
-
-    /* if the symbol is local to the block then */        
-    if (forSym->liveTo < ebp->lSeq ) {       
-
-       /* check if there are any live ranges allocated
-          to registers that are not used in this block */
-       if (!blockSpil && (selectS = liveRangesWith(lrcs,notUsedInBlock,ebp,ic))) {
-           sym = leastUsedLR(selectS);
-           /* if this is not rematerializable */
-           if (!sym->remat) {
-               blockSpil++;
-               sym->blockSpil = 1;
+  /* get live ranges with spillLocations in direct space */
+  if ((selectS = liveRangesWith (lrcs, directSpilLoc, ebp, ic)))
+    {
+      sym = leastUsedLR (selectS);
+      strcpy (sym->rname, (sym->usl.spillLoc->rname[0] ?
+                          sym->usl.spillLoc->rname :
+                          sym->usl.spillLoc->name));
+      sym->spildir = 1;
+      /* mark it as allocation required */
+      sym->usl.spillLoc->allocreq++;
+      return sym;
+    }
+
+  /* if the symbol is local to the block then */
+  if (forSym->liveTo < ebp->lSeq)
+    {
+
+      /* check if there are any live ranges allocated
+         to registers that are not used in this block */
+      if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
+       {
+         sym = leastUsedLR (selectS);
+         /* if this is not rematerializable */
+         if (!sym->remat)
+           {
+             _G.blockSpil++;
+              wassertl (0, "Attempted to do an unsupported block spill");
+             sym->blockSpil = 1;
            }
-           return sym;
-       } 
-
-       /* check if there are any live ranges that not
-          used in the remainder of the block */
-       if (!blockSpil && (selectS = liveRangesWith(lrcs,notUsedInRemaining,ebp,ic))) {
-           sym = leastUsedLR (selectS);
-           if (!sym->remat) {
-               sym->remainSpil = 1;
-               blockSpil++;
+         return sym;
+       }
+
+      /* 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)))
+       {
+         sym = leastUsedLR (selectS);
+         if (sym != forSym)
+           {
+             if (!sym->remat)
+               {
+                  wassertl (0, "Attempted to do an unsupported remain spill");
+                 sym->remainSpil = 1;
+                 _G.blockSpil++;
+               }
+             return sym;
            }
-           return sym;
        }
     }
-    /* find live ranges with spillocation && not used as pointers */
-    if ((selectS = liveRangesWith(lrcs,hasSpilLocnoUptr,ebp,ic))) {
-       
-       sym =  leastUsedLR(selectS);
-       /* mark this as allocation required */
-       sym->usl.spillLoc->allocreq = 1;
-       return sym;
-    }
-#endif   
-
-    /* find live ranges with spillocation */
-    if ((selectS = liveRangesWith(lrcs,hasSpilLoc,ebp,ic))) {
-       D(D_ALLOC, ("selectSpil: using with spill.\n"));
-       sym = leastUsedLR(selectS);
-       sym->usl.spillLoc->allocreq = 1;
-       return sym;
-    }
-
-    /* couldn't find then we need to create a spil
-       location on the stack , for which one? the least
-       used ofcourse */
-    if ((selectS = liveRangesWith(lrcs,noSpilLoc,ebp,ic))) {
-       D(D_ALLOC, ("selectSpil: creating new spill.\n"));
-       /* return a created spil location */
-       sym = createStackSpil(leastUsedLR(selectS));
-       sym->usl.spillLoc->allocreq = 1;
-       return sym;
+  /* find live ranges with spillocation && not used as pointers */
+  if ((selectS = liveRangesWith (lrcs, hasSpilLocnoUptr, ebp, ic)))
+    {
+
+      sym = leastUsedLR (selectS);
+      /* mark this as allocation required */
+      sym->usl.spillLoc->allocreq++;
+      return sym;
+    }
+#endif
+
+  /* find live ranges with spillocation */
+  if ((selectS = liveRangesWith (lrcs, hasSpilLoc, ebp, ic)))
+    {
+      D (D_ALLOC, ("selectSpil: using with spill.\n"));
+      sym = leastUsedLR (selectS);
+      sym->usl.spillLoc->allocreq++;
+      return sym;
+    }
+
+  /* couldn't find then we need to create a spil
+     location on the stack , for which one? the least
+     used ofcourse */
+  if ((selectS = liveRangesWith (lrcs, noSpilLoc, ebp, ic)))
+    {
+      D (D_ALLOC, ("selectSpil: creating new spill.\n"));
+      /* return a created spil location */
+      sym = createStackSpil (leastUsedLR (selectS));
+      sym->usl.spillLoc->allocreq++;
+      return sym;
     }
-    
-    /* this is an extreme situation we will spill
-       this one : happens very rarely but it does happen */
-    D(D_ALLOC, ("selectSpil: using spillThis.\n"));
-    spillThis ( forSym );
-    return forSym;
-   
+
+  /* this is an extreme situation we will spill
+     this one : happens very rarely but it does happen */
+  (D_ALLOC, ("selectSpil: using spillThis.\n"));
+  spillThis (forSym);
+  return forSym;
+
 }
 
 /** Spil some variable & mark registers as free.
     A spill occurs when an iTemp wont fit into the available registers.
  */
-bool spilSomething (iCode *ic, eBBlock *ebp, symbol *forSym)
+bool 
+spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
 {
-    symbol *ssym;
-    int i ;
+  symbol *ssym;
+  int i;
 
-    D(D_ALLOC, ("spilSomething: spilling on ic %zi\n", ic));
+  D (D_ALLOC, ("spilSomething: spilling on ic %p\n", ic));
 
-    /* get something we can spil */
-    ssym = selectSpil(ic,ebp,forSym);
-    
-    /* mark it as spilt */
-    ssym->isspilt = 1;
-    spiltSet = bitVectSetBit(spiltSet,ssym->key);
-    
-    /* mark it as not register assigned &
-       take it away from the set */   
-    bitVectUnSetBit(regAssigned,ssym->key);
-    /* mark the registers as free */    
-    for (i = 0 ; i < ssym->nRegs ;i++ )
-       if (ssym->regs[i])
-           freeReg(ssym->regs[i]);
+  /* get something we can spil */
+  ssym = selectSpil (ic, ebp, forSym);
+
+  /* mark it as spilt */
+  ssym->isspilt = ssym->spillA = 1;
+  _G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key);
+
+  /* mark it as not register assigned &
+     take it away from the set */
+  bitVectUnSetBit (_G.regAssigned, ssym->key);
+  bitVectUnSetBit (_G.totRegAssigned, ssym->key);
+
+  /* mark the registers as free */
+  for (i = 0; i < ssym->nRegs; i++)
+    if (ssym->regs[i])
+      freeReg (ssym->regs[i]);
+
+  wassertl (ssym->blockSpil == 0, "Encountered a sym with a block spill");
+  wassertl (ssym->remainSpil == 0, "Encountered a sym with a remain spill");
 #if 0
-    /* if spilt on stack then free up r0 & r1 
-       if they could have been assigned to as gprs */
-    if (!ptrRegReq && isSpiltOnStack(ssym) ) {
-       ptrRegReq++ ;
-       spillLRWithPtrReg(ssym);
-    }
-
-    /* if this was a block level spil then insert push & pop 
-       at the start & end of block respectively */
-    if (ssym->blockSpil) {
-       iCode *nic = newiCode(IPUSH,operandFromSymbol(ssym),NULL);
-       /* add push to the start of the block */
-       addiCodeToeBBlock(ebp,nic,( ebp->sch->op == LABEL ? 
+  /* if spilt on stack then free up r0 & r1 
+     if they could have been assigned to as gprs */
+  if (!ptrRegReq && isSpiltOnStack (ssym))
+    {
+      ptrRegReq++;
+      spillLRWithPtrReg (ssym);
+    }
+
+  /* if this was a block level spil then insert push & pop 
+     at the start & end of block respectively */
+  if (ssym->blockSpil)
+    {
+      iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
+      /* add push to the start of the block */
+      addiCodeToeBBlock (ebp, nic, (ebp->sch->op == LABEL ?
                                    ebp->sch->next : ebp->sch));
-       nic = newiCode(IPOP,operandFromSymbol(ssym),NULL);
-       /* add pop to the end of the block */
-       addiCodeToeBBlock(ebp,nic,NULL);
-    }       
-
-    /* if spilt because not used in the remainder of the
-       block then add a push before this instruction and
-       a pop at the end of the block */
-    if (ssym->remainSpil) {
-
-       iCode *nic = newiCode(IPUSH,operandFromSymbol(ssym),NULL);
-       /* add push just before this instruction */
-       addiCodeToeBBlock(ebp,nic,ic);
-                                   
-       nic = newiCode(IPOP,operandFromSymbol(ssym),NULL);
-       /* add pop to the end of the block */
-       addiCodeToeBBlock(ebp,nic,NULL);    
+      nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
+      /* add pop to the end of the block */
+      addiCodeToeBBlock (ebp, nic, NULL);
+    }
+
+  /* if spilt because not used in the remainder of the
+     block then add a push before this instruction and
+     a pop at the end of the block */
+  if (ssym->remainSpil)
+    {
+
+      iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
+      /* add push just before this instruction */
+      addiCodeToeBBlock (ebp, nic, ic);
+
+      nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
+      /* add pop to the end of the block */
+      addiCodeToeBBlock (ebp, nic, NULL);
     }
 #endif
 
-    D(D_ALLOC, ("spilSomething: done.\n"));
+  (D_ALLOC, ("spilSomething: done.\n"));
 
-    if (ssym == forSym )
-       return FALSE ;
-    else
-       return TRUE ;
+  if (ssym == forSym)
+    return FALSE;
+  else
+    return TRUE;
 }
 
 /** Will try for GPR if not spil.
  */
-regs *getRegGpr (iCode *ic, eBBlock *ebp,symbol *sym)
+regs *
+getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
 {
-    regs *reg;
+  regs *reg;
+  int j;
 
-    D(D_ALLOC, ("getRegGpr: on ic %zi\n"));
- tryAgain:
-    /* try for gpr type */
-    if ((reg = allocReg(REG_GPR))) {
-       D(D_ALLOC, ("getRegGpr: got a reg.\n"));
-       return reg;    
+  D (D_ALLOC, ("getRegGpr: on ic %p\n", ic));
+tryAgain:
+  /* try for gpr type */
+  if ((reg = allocReg (REG_GPR)))
+    {
+      D (D_ALLOC, ("getRegGpr: got a reg.\n"));
+      return reg;
+    }
+
+  /* we have to spil */
+  if (!spilSomething (ic, ebp, sym))
+    {
+      D (D_ALLOC, ("getRegGpr: have to spill.\n"));
+      return NULL;
     }
+  
+  /* make sure partially assigned registers aren't reused */
+  for (j=0; j<=sym->nRegs; j++)
+    if (sym->regs[j])
+      sym->regs[j]->isFree = 0;
+
+  /* this looks like an infinite loop but 
+     in really selectSpil will abort  */
+  goto tryAgain;
+}
+
+static regs *getRegGprNoSpil()
+{
+  regs *reg;
 
-    /* we have to spil */
-    if (!spilSomething (ic,ebp,sym)) {
-       D(D_ALLOC, ("getRegGpr: have to spill.\n"));
-       return NULL ;
+  /* try for gpr type */
+  if ((reg = allocReg (REG_GPR)))
+    {
+      D (D_ALLOC, ("getRegGprNoSpil: got a reg.\n"));
+      return reg;
     }
+  assert(0);
 
-    /* this looks like an infinite loop but 
-       in really selectSpil will abort  */
-    goto tryAgain ;    
+  /* just to make the compiler happy */
+  return 0;
 }
 
 /** Symbol has a given register.
  */
-static bool symHasReg(symbol *sym,regs *reg)
+static bool 
+symHasReg (symbol * sym, regs * reg)
 {
-    int i;
+  int i;
 
-    for ( i = 0 ; i < sym->nRegs ; i++)
-       if (sym->regs[i] == reg)
-           return TRUE;
-           
-    return FALSE;
+  for (i = 0; i < sym->nRegs; i++)
+    if (sym->regs[i] == reg)
+      return TRUE;
+
+  return FALSE;
 }
 
 /** Check the live to and if they have registers & are not spilt then
     free up the registers 
 */
-static void deassignLRs (iCode *ic, eBBlock *ebp)
+static void 
+deassignLRs (iCode * ic, eBBlock * ebp)
 {
-    symbol *sym;
-    int k;
-    symbol *result;
-
-    for (sym = hTabFirstItem(liveRanges,&k); sym;
-        sym = hTabNextItem(liveRanges,&k)) {
-       
-       symbol *psym= NULL;
-       /* if it does not end here */
-       if (sym->liveTo > ic->seq )
-           continue ;
+  symbol *sym;
+  int k;
+  symbol *result;
+
+  for (sym = hTabFirstItem (liveRanges, &k); sym;
+       sym = hTabNextItem (liveRanges, &k))
+    {
 
-       /* if it was spilt on stack then we can 
-          mark the stack spil location as free */
-       if (sym->isspilt ) {
-           if (sym->stackSpil) {
-               sym->usl.spillLoc->isFree = 1;
-               sym->stackSpil = 0;
+      symbol *psym = NULL;
+      /* if it does not end here */
+      if (sym->liveTo > ic->seq)
+       continue;
+
+      /* if it was spilt on stack then we can 
+         mark the stack spil location as free */
+      if (sym->isspilt)
+       {
+         if (sym->stackSpil)
+           {
+             sym->usl.spillLoc->isFree = 1;
+             sym->stackSpil = 0;
            }
-           continue ;
+         continue;
        }
-       
-       if (!bitVectBitValue(regAssigned,sym->key))
-           continue;
-       
-       /* special case check if this is an IFX &
-          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 &&
-           ic->prev->op == IPOP && 
-           !ic->prev->parmPush  &&
-           !OP_SYMBOL(IC_LEFT(ic->prev))->isspilt) 
-           psym = OP_SYMBOL(IC_LEFT(ic->prev));
-
-       D(D_ALLOC, ("deassignLRs: in loop on sym %zs", sym));
-
-       if (sym->nRegs) {
-           int i = 0;
-           
-           bitVectUnSetBit(regAssigned,sym->key);
-
-           /* if the result of this one needs registers
-              and does not have it then assign it right
-              away */
-           if (IC_RESULT(ic) &&
-               !  (SKIP_IC2(ic) ||               /* not a special icode */
-                   ic->op == JUMPTABLE ||
-                   ic->op == IFX ||
-                   ic->op == IPUSH ||
-                   ic->op == IPOP ||
-                   ic->op == RETURN)   &&
-               (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->regType == sym->regType &&     /* same register types */
-               result->nRegs            &&            /* which needs registers */
-               ! result->isspilt        &&            /* and does not already have them */
-               ! result->remat          &&
-               ! bitVectBitValue(regAssigned,result->key) &&
-               /* the number of free regs + number of regs in this LR
-                  can accomodate the what result Needs */
-               ((nfreeRegsType(result->regType) +
-                 sym->nRegs) >= result->nRegs)
-               ) {
-               for (i = 0 ; i < max(sym->nRegs,result->nRegs) ; i++) {
-                   if (i < sym->nRegs )
-                       result->regs[i] = sym->regs[i] ;
-                   else
-                       result->regs[i] = getRegGpr (ic,ebp,result);
-                   
-                   /* if the allocation falied which means
-                      this was spilt then break */
-                   if (!result->regs[i]) {
-                       wassert(0);
-                       assert(0);
-                       break;
+
+      if (!bitVectBitValue (_G.regAssigned, sym->key))
+       continue;
+
+      /* special case check if this is an IFX &
+         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 &&
+         ic->prev->op == IPOP &&
+         !ic->prev->parmPush &&
+         !OP_SYMBOL (IC_LEFT (ic->prev))->isspilt)
+       psym = OP_SYMBOL (IC_LEFT (ic->prev));
+
+      D (D_ALLOC, ("deassignLRs: in loop on sym %p nregs %u\n", sym, sym->nRegs));
+
+      if (sym->nRegs)
+       {
+         int i = 0;
+
+         bitVectUnSetBit (_G.regAssigned, sym->key);
+
+         /* if the result of this one needs registers
+            and does not have it then assign it right
+            away */
+         if (IC_RESULT (ic) &&
+             !(SKIP_IC2 (ic) ||        /* not a special icode */
+               ic->op == JUMPTABLE ||
+               ic->op == IFX ||
+               ic->op == IPUSH ||
+               ic->op == IPOP ||
+               ic->op == RETURN) &&
+             (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->remat &&
+             !bitVectBitValue (_G.regAssigned, result->key) &&
+         /* the number of free regs + number of regs in this LR
+            can accomodate the what result Needs */
+             ((nfreeRegsType (result->regType) +
+               sym->nRegs) >= result->nRegs)
+           )
+           {
+             for (i = 0; i < result->nRegs; i++)
+               {
+                 if (i < sym->nRegs)
+                   result->regs[i] = sym->regs[i];
+                 else
+                   result->regs[i] = getRegGpr (ic, ebp, result);
+
+                 /* if the allocation falied which means
+                    this was spilt then break */
+                 if (!result->regs[i])
+                   {
+                     wassert (0);
+                     assert (0);
+                     break;
                    }
                }
 
-               regAssigned = bitVectSetBit(regAssigned,result->key);
-           }                   
-           
-           /* free the remaining */
-           for (; i < sym->nRegs ; i++) {
-               if (psym) {
-                   if (!symHasReg(psym,sym->regs[i]))
-                       freeReg(sym->regs[i]);
-               } else
-                   freeReg(sym->regs[i]);
-               //              sym->regs[i] = NULL;
+             _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
+             _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, result->key);
+           }
+
+         /* free the remaining */
+         for (; i < sym->nRegs; i++)
+           {
+             if (psym)
+               {
+                 if (!symHasReg (psym, sym->regs[i]))
+                   freeReg (sym->regs[i]);
+               }
+             else
+               freeReg (sym->regs[i]);
+             //              sym->regs[i] = NULL;
            }
        }
     }
@@ -817,848 +938,1189 @@ static void deassignLRs (iCode *ic, eBBlock *ebp)
 
 /** Reassign this to registers.
  */
-static void reassignLR (operand *op)
+static void 
+reassignLR (operand * op)
 {
-    symbol *sym = OP_SYMBOL(op);
-    int i;
+  symbol *sym = OP_SYMBOL (op);
+  int i;
 
-    D(D_ALLOC, ("reassingLR: on sym %zs\n", sym));
+  D (D_ALLOC, ("reassingLR: on sym %p\n", sym));
 
-    /* not spilt any more */     
-    sym->isspilt = sym->blockSpil  = sym->remainSpil = 0;
-    bitVectUnSetBit(spiltSet,sym->key);
-      
-    regAssigned = bitVectSetBit(regAssigned,sym->key);
+  /* not spilt any more */
+  sym->isspilt = sym->spillA = sym->blockSpil = sym->remainSpil = 0;
+  bitVectUnSetBit (_G.spiltSet, sym->key);
+
+  _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+  _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key);
 
-    blockSpil--;
+  _G.blockSpil--;
 
-    for (i=0;i<sym->nRegs;i++)
-       sym->regs[i]->isFree = 0;
+  for (i = 0; i < sym->nRegs; i++)
+    sym->regs[i]->isFree = 0;
 }
 
 /** Determines if allocating will cause a spill.
  */
-static int willCauseSpill ( int nr, int rt)
+static int 
+willCauseSpill (int nr, int rt)
 {
-    /* first check if there are any avlb registers
-       of te type required */
-    if (nFreeRegs(0) >= nr)
-       return 0;
+  /* first check if there are any avlb registers
+     of te type required */
+  if (nFreeRegs (0) >= nr)
+    return 0;
 
-    /* it will cause a spil */
-    return 1;
+  /* it will cause a spil */
+  return 1;
 }
 
 /** The allocator can allocate same registers to result and operand,
     if this happens make sure they are in the same position as the operand
     otherwise chaos results.
 */
-static void positionRegs (symbol *result, symbol *opsym, int lineno)
+static int
+positionRegs (symbol * result, symbol * opsym)
 {
-    int count = min(result->nRegs,opsym->nRegs);
-    int i , j = 0, shared = 0;
-
-    D(D_ALLOC, ("positionRegs: on result %zs opsum %zs line %u\n", result, opsym, lineno));
-
-    /* if the result has been spilt then cannot share */
-    if (opsym->isspilt)
-       return ;
- again:
-    shared = 0;
-    /* first make sure that they actually share */
-    for ( i = 0 ; i < count; i++ ) {
-       for (j = 0 ; j < count ; j++ ) {
-           if (result->regs[i] == opsym->regs[j] && i !=j) {
-               shared = 1;
-               goto xchgPositions;
+  int count = min (result->nRegs, opsym->nRegs);
+  int i, j = 0, shared = 0;
+  int change = 0;
+
+  D (D_ALLOC, ("positionRegs: on result %p opsum %p line %u\n", result, opsym, lineno));
+
+  /* if the result has been spilt then cannot share */
+  if (opsym->isspilt)
+    return 0;
+again:
+  shared = 0;
+  /* first make sure that they actually share */
+  for (i = 0; i < count; i++)
+    {
+      for (j = 0; j < count; j++)
+       {
+         if (result->regs[i] == opsym->regs[j] && i != j)
+           {
+             shared = 1;
+             goto xchgPositions;
            }
        }
     }
- xchgPositions:
-    if (shared) {
-       regs *tmp = result->regs[i];
-       result->regs[i] = result->regs[j];
-       result->regs[j] = tmp;          
-       goto again;
+xchgPositions:
+  if (shared)
+    {
+      regs *tmp = result->regs[i];
+      result->regs[i] = result->regs[j];
+      result->regs[j] = tmp;
+      change ++;
+      goto again;
     }
+  return change ;
 }
 
 /** Try to allocate a pair of registers to the symbol.
  */
-bool tryAllocatingRegPair(symbol *sym)
+bool 
+tryAllocatingRegPair (symbol * sym)
 {
-    int i;
-    wassert(sym->nRegs == 2);
-    for ( i = 0 ; i < _nRegs ; i+=2 ) {
-       if ((regsZ80[i].isFree)&&(regsZ80[i+1].isFree)) {
-           regsZ80[i].isFree = 0;
-           sym->regs[0] = &regsZ80[i];
-           regsZ80[i+1].isFree = 0;
-           sym->regs[1] = &regsZ80[i+1];
-           if (currFunc) {
-               currFunc->regsUsed = 
-                   bitVectSetBit(currFunc->regsUsed,i);
-               currFunc->regsUsed = 
-                   bitVectSetBit(currFunc->regsUsed,i+1);
+  int i;
+  wassert (sym->nRegs == 2);
+  for (i = 0; i < _G.nRegs; i += 2)
+    {
+      if ((regsZ80[i].isFree) && (regsZ80[i + 1].isFree))
+       {
+         regsZ80[i].isFree = 0;
+         sym->regs[0] = &regsZ80[i];
+         regsZ80[i + 1].isFree = 0;
+         sym->regs[1] = &regsZ80[i + 1];
+          sym->regType = REG_PAIR;
+
+         if (currFunc)
+           {
+             currFunc->regsUsed =
+               bitVectSetBit (currFunc->regsUsed, i);
+             currFunc->regsUsed =
+               bitVectSetBit (currFunc->regsUsed, i + 1);
            }
-           D(D_ALLOC, ("tryAllocRegPair: succeded for sym %zs\n", sym));
-           return TRUE;
+         D (D_ALLOC, ("tryAllocRegPair: succeded for sym %p\n", sym));
+         return TRUE;
        }
     }
-    D(D_ALLOC, ("tryAllocRegPair: failed on sym %zs\n", sym));
-    return FALSE;
+  D (D_ALLOC, ("tryAllocRegPair: failed on sym %p\n", sym));
+  return FALSE;
+}
+
+/*------------------------------------------------------------------*/
+/* 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);
 }
 
+
 /** Serially allocate registers to the variables.
     This is the main register allocation function.  It is called after
     packing.
  */
-static void serialRegAssign (eBBlock **ebbs, int count)
+static void 
+serialRegAssign (eBBlock ** ebbs, int count)
 {
-    int i;
+  int i;
 
-    /* for all blocks */
-    for (i = 0; i < count ; i++ ) {
-       
-       iCode *ic;
-       
-       if (ebbs[i]->noPath &&
-           (ebbs[i]->entryLabel != entryLabel &&
-            ebbs[i]->entryLabel != returnLabel ))
-           continue ;
+  /* for all blocks */
+  for (i = 0; i < count; i++)
+    {
 
-       /* of all instructions do */
-       for (ic = ebbs[i]->sch ; ic ; ic = ic->next) {
-        
-           /* if this is an ipop that means some live
-              range will have to be assigned again */
-           if (ic->op == IPOP) {
-               wassert(0);
-               reassignLR (IC_LEFT(ic));
+      iCode *ic;
+
+      if (ebbs[i]->noPath &&
+         (ebbs[i]->entryLabel != entryLabel &&
+          ebbs[i]->entryLabel != returnLabel))
+       continue;
+
+      /* of all instructions do */
+      for (ic = ebbs[i]->sch; ic; ic = ic->next)
+       {
+
+         /* if this is an ipop that means some live
+            range will have to be assigned again */
+         if (ic->op == IPOP)
+           {
+             wassert (0);
+             reassignLR (IC_LEFT (ic));
            }
 
-           /* if result is present && is a true symbol */
-           if (IC_RESULT(ic) && ic->op != IFX &&
-               IS_TRUE_SYMOP(IC_RESULT(ic)))
-               OP_SYMBOL(IC_RESULT(ic))->allocreq = 1;
-
-           /* take away registers from live
-              ranges that end at this instruction */      
-           deassignLRs (ic, ebbs[i]) ;         
-                   
-           /* some don't need registers */
-           /* MLH: removed RESULT and POINTER_SET condition */
-           if (SKIP_IC2(ic) ||
-               ic->op == JUMPTABLE ||
-               ic->op == IFX ||
-               ic->op == IPUSH ||
-               ic->op == IPOP)
-               continue;   
-           
-           /* now we need to allocate registers only for the result */
-           if (IC_RESULT(ic)) {
-               symbol *sym = OP_SYMBOL(IC_RESULT(ic));
-               bitVect *spillable;
-               int willCS ;
-               int j;
-
-               D(D_ALLOC, ("serialRegAssign: in loop on result %zs\n", sym));
-
-               /* if it does not need or is spilt 
-                  or is already assigned to registers
-                  or will not live beyond this instructions */
-               if (!sym->nRegs      || 
-                   sym->isspilt     || 
-                   bitVectBitValue(regAssigned,sym->key) ||
-                   sym->liveTo <= ic->seq) {
-                   D(D_ALLOC, ("serialRegAssign: wont live long enough.\n"));
-                   continue ;
+         /* if result is present && is a true symbol */
+         if (IC_RESULT (ic) && ic->op != IFX &&
+             IS_TRUE_SYMOP (IC_RESULT (ic)))
+           OP_SYMBOL (IC_RESULT (ic))->allocreq++;
+
+         /* take away registers from live
+            ranges that end at this instruction */
+         deassignLRs (ic, ebbs[i]);
+
+         /* some don't need registers */
+         /* MLH: removed RESULT and POINTER_SET condition */
+         if (SKIP_IC2 (ic) ||
+             ic->op == JUMPTABLE ||
+             ic->op == IFX ||
+             ic->op == IPUSH ||
+             ic->op == IPOP)
+           continue;
+
+         /* now we need to allocate registers only for the result */
+         if (IC_RESULT (ic))
+           {
+             symbol *sym = OP_SYMBOL (IC_RESULT (ic));
+             bitVect *spillable;
+             int willCS;
+             int j;
+
+             D (D_ALLOC, ("serialRegAssign: in loop on result %p\n", sym));
+                
+             /* 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 some liverange has been spilt at the block level
-                  and this one live beyond this block then spil this
-                  to be safe */
-               if (blockSpil && sym->liveTo > ebbs[i]->lSeq) {
-                   D(D_ALLOC, ("serialRegAssign: \"spilling to be safe.\"\n"));
-                   spillThis (sym);
-                   continue ;
+             /* if it does not need or is spilt 
+                or is already assigned to registers
+                or will not live beyond this instructions */
+             if (!sym->nRegs ||
+                 sym->isspilt ||
+                 bitVectBitValue (_G.regAssigned, sym->key) ||
+                 sym->liveTo <= ic->seq)
+               {
+                 D (D_ALLOC, ("serialRegAssign: wont live long enough.\n"));
+                 continue;
                }
-               /* if trying to allocate this will cause
-                  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) ) ) {
-
-                   D(D_ALLOC, ("serialRegAssign: \"remat spill\"\n"));
-                   spillThis (sym) ;
-                   continue ;
 
+             /* if some liverange has been spilt at the block level
+                and this one live beyond this block then spil this
+                to be safe */
+             if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
+               {
+                 D (D_ALLOC, ("serialRegAssign: \"spilling to be safe.\"\n"));
+                 spillThis (sym);
+                 continue;
                }
+             /* if trying to allocate this will cause
+                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)))
+               {
+
+                 D (D_ALLOC, ("serialRegAssign: \"remat spill\"\n"));
+                 spillThis (sym);
+                 continue;
 
-               /* if it has a spillocation & is used less than
-                  all other live ranges then spill this */
-               if ( willCS && sym->usl.spillLoc ) {
-
-                   symbol *leastUsed = 
-                       leastUsedLR(liveRangesWith (spillable ,
-                                                   allLRs,
-                                                   ebbs[i],
-                                                   ic));
-                   if (leastUsed && 
-                       leastUsed->used > sym->used) {
-                       spillThis (sym);
-                       continue;
-                   }
-               }               
+               }
 
-               /* else we assign registers to it */            
-               regAssigned = bitVectSetBit(regAssigned,sym->key);
+             /* 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;                 
+               }
 
-               /* Special case:  Try to fit into a reg pair if
-                  available */
-               D(D_ALLOC, ("serialRegAssign: actually allocing regs!\n"));
-               if ((sym->nRegs == 2)&&tryAllocatingRegPair(sym)) {
+             /* if it has a spillocation & is used less than
+                all other live ranges then spill this */
+             if (willCS) {
+                     if (sym->usl.spillLoc) {
+                             symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
+                                                                              allLRs, ebbs[i], ic));
+                             if (leastUsed && leastUsed->used > sym->used) {
+                                     spillThis (sym);
+                                     continue;
+                             }
+                     } else {
+                             /* if none of the liveRanges have a spillLocation then better
+                                to spill this one than anything else already assigned to registers */
+                             if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
+                                 /* if this is local to this block then we might find a block spil */
+                                 if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
+                                     spillThis (sym);
+                                     continue;
+                                 }
+                             }
+                     }
+             }
+
+             /* else we assign registers to it */
+             _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+             _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key);
+
+             /* Special case:  Try to fit into a reg pair if
+                available */
+             D (D_ALLOC, ("serialRegAssign: actually allocing regs!\n"));
+             if ((sym->nRegs == 2) && tryAllocatingRegPair (sym))
+               {
                }
-               else {
-                   for (j = 0 ; j < sym->nRegs ;j++ ) {
-                       sym->regs[j] = getRegGpr(ic,ebbs[i],sym);
-                       
-                       /* if the allocation falied which means
-                          this was spilt then break */
-                       if (!sym->regs[j]) {
+             else
+               {
+                 for (j = 0; j < sym->nRegs; j++)
+                   {
+                     sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
+
+                     /* if the allocation falied which means
+                        this was spilt then break */
+                     if (!sym->regs[j])
+                       {
+                         D (D_ALLOC, ("Couldnt alloc (spill)\n"))
                            break;
                        }
                    }
                }
-               /* if it shares registers with operands make sure
-                  that they are in the same position */
-               if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) &&
-                   OP_SYMBOL(IC_LEFT(ic))->nRegs  && ic->op != '=')
-                       positionRegs(OP_SYMBOL(IC_RESULT(ic)),
-                                    OP_SYMBOL(IC_LEFT(ic)),ic->lineno);
-               /* do the same for the right operand */
-               if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) &&
-                   OP_SYMBOL(IC_RIGHT(ic))->nRegs && ic->op != '=')
-                       positionRegs(OP_SYMBOL(IC_RESULT(ic)),
-                                    OP_SYMBOL(IC_RIGHT(ic)),ic->lineno);
-               
-           }       
+             /* if it shares registers with operands make sure
+                that they are in the same position */
+             if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
+                 OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=')
+               positionRegs (OP_SYMBOL (IC_RESULT (ic)),
+                             OP_SYMBOL (IC_LEFT (ic)));
+             /* do the same for the right operand */
+             if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
+                 OP_SYMBOL (IC_RIGHT (ic))->nRegs)
+               positionRegs (OP_SYMBOL (IC_RESULT (ic)),
+                             OP_SYMBOL (IC_RIGHT (ic)));
+
+           }
        }
     }
-}
 
-/*-----------------------------------------------------------------*/
-/* rUmaskForOp :- returns register mask for an operand             */
-/*-----------------------------------------------------------------*/
-bitVect *rUmaskForOp (operand *op)
+    /* 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);
+          }
+      }    
+
+}
+
+/*-----------------------------------------------------------------*/
+/* fillGaps - Try to fill in the Gaps left by Pass1                */
+/*-----------------------------------------------------------------*/
+static void fillGaps()
 {
-    bitVect *rumask;
-    symbol *sym;
-    int j;
+    symbol *sym =NULL;
+    int key =0;    
     
-    /* only temporaries are assigned registers */
-    if (!IS_ITEMP(op)) 
-       return NULL;
-
-    sym = OP_SYMBOL(op);
+    if (getenv("DISABLE_FILL_GAPS")) return;
     
-    /* if spilt or no registers assigned to it
-       then nothing */
-    if (sym->isspilt || !sym->nRegs)
-       return NULL;
+    /* look for livernages that was spilt by the allocator */
+    for (sym = hTabFirstItem(liveRanges,&key) ; sym ; 
+        sym = hTabNextItem(liveRanges,&key)) {
+
+       int i;
+       int pdone = 0;
+
+       if (!sym->spillA || !sym->clashes || sym->remat) continue ;
 
-    rumask = newBitVect(_nRegs);
+       /* find the liveRanges this one clashes with, that are
+          still assigned to registers & mark the registers as used*/
+       for ( i = 0 ; i < sym->clashes->size ; i ++) {
+           int k;
+           symbol *clr;
 
-    for (j = 0; j < sym->nRegs; j++) {
-       rumask = bitVectSetBit(rumask, sym->regs[j]->rIdx);
+           if (bitVectBitValue(sym->clashes,i) == 0 ||    /* those that clash with this */
+               bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */
+               continue ;
+
+           clr = hTabItemWithKey(liveRanges,i);
+           assert(clr);
+        
+           /* mark these registers as used */
+           for (k = 0 ; k < clr->nRegs ; k++ ) 
+               useReg(clr->regs[k]);
+       }
+
+       if (willCauseSpill(sym->nRegs,sym->regType)) {
+           /* NOPE :( clear all registers & and continue */
+           freeAllRegs();
+           continue ;
+       }
+
+       /* THERE IS HOPE !!!! */
+       for (i=0; i < sym->nRegs ; i++ ) {
+               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 
+          then give up */
+       sym->isspilt = 0;
+       for (i = 0 ; i < sym->defs->size ; i++ ) {
+           if (bitVectBitValue(sym->defs,i)) {
+               iCode *ic;
+               if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ;
+               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)) && 
+                   bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_LEFT(ic))->key)) {
+                   pdone += positionRegs(sym,OP_SYMBOL(IC_LEFT(ic)));
+               }
+               if (IS_SYMOP(IC_RIGHT(ic)) && 
+                   bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) {
+                   pdone += positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic)));
+               }
+               if (pdone > 1) break;
+           }
+       }
+       for (i = 0 ; i < sym->uses->size ; i++ ) {
+           if (bitVectBitValue(sym->uses,i)) {
+               iCode *ic;
+               if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ;
+               if (SKIP_IC(ic)) continue;
+               if (!IS_ASSIGN_ICODE(ic)) continue ;
+
+               /* if result is assigned to registers */
+               if (IS_SYMOP(IC_RESULT(ic)) && 
+                   bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) {
+                   pdone += positionRegs(sym,OP_SYMBOL(IC_RESULT(ic)));
+               }
+               if (pdone > 1) break;
+           }
+       }
+       /* had to position more than once GIVE UP */
+       if (pdone > 1) {
+           /* UNDO all the changes we made to try this */
+           sym->isspilt = 1;
+           for (i=0; i < sym->nRegs ; i++ ) {
+               sym->regs[i] = NULL;
+           }
+           freeAllRegs();
+           D(D_FILL_GAPS,("Fill Gap gave up due to positioning for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN"));
+           continue ;      
+       }
+       D(D_FILL_GAPS,("FILLED GAP for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN"));
+       _G.totRegAssigned = bitVectSetBit(_G.totRegAssigned,sym->key);
+       sym->isspilt = sym->spillA = 0 ;
+       sym->usl.spillLoc->allocreq--;
+       freeAllRegs();
     }
+}
+
+/*-----------------------------------------------------------------*/
+/* rUmaskForOp :- returns register mask for an operand             */
+/*-----------------------------------------------------------------*/
+bitVect *
+rUmaskForOp (operand * op)
+{
+  bitVect *rumask;
+  symbol *sym;
+  int j;
+
+  /* only temporaries are assigned registers */
+  if (!IS_ITEMP (op))
+    return NULL;
+
+  sym = OP_SYMBOL (op);
 
-    return rumask;
+  /* if spilt or no registers assigned to it
+     then nothing */
+  if (sym->isspilt || !sym->nRegs)
+    return NULL;
+
+  rumask = newBitVect (_G.nRegs);
+
+  for (j = 0; j < sym->nRegs; j++)
+    {
+      rumask = bitVectSetBit (rumask, sym->regs[j]->rIdx);
+    }
+
+  return rumask;
+}
+
+bitVect *
+z80_rUmaskForOp (operand * op)
+{
+  return rUmaskForOp (op);
 }
 
 /** Returns bit vector of registers used in iCode.
  */
-bitVect *regsUsedIniCode (iCode *ic)
+bitVect *
+regsUsedIniCode (iCode * ic)
 {
-    bitVect *rmask = newBitVect(_nRegs);
+  bitVect *rmask = newBitVect (_G.nRegs);
 
-    /* do the special cases first */
-    if (ic->op == IFX ) {
-       rmask = bitVectUnion(rmask,
-                            rUmaskForOp(IC_COND(ic)));
-       goto ret;
+  /* do the special cases first */
+  if (ic->op == IFX)
+    {
+      rmask = bitVectUnion (rmask,
+                           rUmaskForOp (IC_COND (ic)));
+      goto ret;
     }
 
-    /* for the jumptable */
-    if (ic->op == JUMPTABLE) {
-       rmask = bitVectUnion(rmask,
-                            rUmaskForOp(IC_JTCOND(ic)));
+  /* for the jumptable */
+  if (ic->op == JUMPTABLE)
+    {
+      rmask = bitVectUnion (rmask,
+                           rUmaskForOp (IC_JTCOND (ic)));
 
-        goto ret;
+      goto ret;
     }
 
-    /* of all other cases */
-    if (IC_LEFT(ic)) 
-       rmask = bitVectUnion(rmask,
-                            rUmaskForOp(IC_LEFT(ic)));
-       
-    
-    if (IC_RIGHT(ic))
-       rmask = bitVectUnion(rmask,
-                            rUmaskForOp(IC_RIGHT(ic)));
+  /* of all other cases */
+  if (IC_LEFT (ic))
+    rmask = bitVectUnion (rmask,
+                         rUmaskForOp (IC_LEFT (ic)));
 
-    if (IC_RESULT(ic))
-       rmask = bitVectUnion(rmask,
-                            rUmaskForOp(IC_RESULT(ic)));
 
- ret:
-    return rmask;
+  if (IC_RIGHT (ic))
+    rmask = bitVectUnion (rmask,
+                         rUmaskForOp (IC_RIGHT (ic)));
+
+  if (IC_RESULT (ic))
+    rmask = bitVectUnion (rmask,
+                         rUmaskForOp (IC_RESULT (ic)));
+
+ret:
+  return rmask;
 }
 
 /** For each instruction will determine the regsUsed.
  */
-static void createRegMask (eBBlock **ebbs, int count)
+static void 
+createRegMask (eBBlock ** ebbs, int count)
 {
-    int i;
+  int i;
 
-    /* for all blocks */
-    for (i = 0; i < count ; i++ ) {
-       iCode *ic ;
+  /* for all blocks */
+  for (i = 0; i < count; i++)
+    {
+      iCode *ic;
 
-       if ( ebbs[i]->noPath &&
-            ( ebbs[i]->entryLabel != entryLabel &&
-              ebbs[i]->entryLabel != returnLabel ))
-           continue ;
+      if (ebbs[i]->noPath &&
+         (ebbs[i]->entryLabel != entryLabel &&
+          ebbs[i]->entryLabel != returnLabel))
+       continue;
 
-       /* for all instructions */
-       for ( ic = ebbs[i]->sch ; ic ; ic = ic->next ) {
-           
-           int j;
+      /* for all instructions */
+      for (ic = ebbs[i]->sch; ic; ic = ic->next)
+       {
 
-           if (SKIP_IC2(ic) || !ic->rlive)
-               continue ;
-           
-           /* first mark the registers used in this
-              instruction */
-           ic->rUsed = regsUsedIniCode(ic);
-           funcrUsed = bitVectUnion(funcrUsed,ic->rUsed);
-
-           /* now create the register mask for those 
-              registers that are in use : this is a
-              super set of ic->rUsed */
-           ic->rMask = newBitVect(_nRegs+1);
-
-           /* for all live Ranges alive at this point */
-           for (j = 1; j < ic->rlive->size; j++ ) {
-               symbol *sym;
-               int k;
-
-               /* if not alive then continue */
-               if (!bitVectBitValue(ic->rlive,j))
-                   continue ;
-
-               /* find the live range we are interested in */
-               if (!(sym = hTabItemWithKey(liveRanges,j))) {
-                   werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
-                           "createRegMask cannot find live range");
-                   exit(0);
+         int j;
+
+         if (SKIP_IC2 (ic) || !ic->rlive)
+           continue;
+
+         /* first mark the registers used in this
+            instruction */
+         ic->rUsed = regsUsedIniCode (ic);
+         _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
+
+         /* now create the register mask for those 
+            registers that are in use : this is a
+            super set of ic->rUsed */
+         ic->rMask = newBitVect (_G.nRegs + 1);
+
+         /* for all live Ranges alive at this point */
+         for (j = 1; j < ic->rlive->size; j++)
+           {
+             symbol *sym;
+             int k;
+
+             /* if not alive then continue */
+             if (!bitVectBitValue (ic->rlive, j))
+               continue;
+
+             /* find the live range we are interested in */
+             if (!(sym = hTabItemWithKey (liveRanges, j)))
+               {
+                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                         "createRegMask cannot find live range");
+                 exit (0);
                }
 
-               /* if no register assigned to it */
-               if (!sym->nRegs || sym->isspilt)
-                   continue ;
+             /* if no register assigned to it */
+             if (!sym->nRegs || sym->isspilt)
+               continue;
 
-               /* for all the registers allocated to it */
-               for (k = 0 ; k < sym->nRegs ;k++)
-                   if (sym->regs[k])
-                       ic->rMask =
-                           bitVectSetBit(ic->rMask,sym->regs[k]->rIdx);
+             /* for all the registers allocated to it */
+             for (k = 0; k < sym->nRegs; k++)
+               if (sym->regs[k])
+                 ic->rMask =
+                   bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
            }
        }
     }
 }
 
+#if 0
 /** Returns the rematerialized string for a remat var.
  */
-char *rematStr (symbol *sym)
+static char *
+rematStr (symbol * sym)
 {
-    char *s = buffer;   
-    iCode *ic = sym->rematiCode;    
-
-    while (1) {
-
-        /* if plus or minus print the right hand side */
-        if (ic->op == '+' || ic->op == '-') {
-            sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
-                    ic->op );
-            s += strlen(s);
-            ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
-            continue ;
+  iCode *ic = sym->rematiCode;
+  int offset = 0;
+
+  while (1)
+    {
+      /* if plus adjust offset to right hand side */
+      if (ic->op == '+')
+        {
+          offset += (int) operandLitValue (IC_RIGHT (ic));
+          ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+          continue;
         }
-        /* we reached the end */
-        sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
-        break;
+
+      /* if minus adjust offset to right hand side */
+      if (ic->op == '-')
+       {
+          offset -= (int) operandLitValue (IC_RIGHT (ic));
+         ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+         continue;
+       }
+
+      /* cast then continue */
+      if (IS_CAST_ICODE(ic)) {
+          ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
+          continue;
+      }
+      /* we reached the end */
+      break;
     }
 
-    return buffer ;
+  if (offset)
+    {
+      SNPRINTF (buffer, sizeof(buffer),
+                "(%s %c 0x%04x)",
+                OP_SYMBOL (IC_LEFT (ic))->rname,
+                offset >= 0 ? '+' : '-',
+                abs (offset) & 0xffff);
+    }
+  else
+    {
+      strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
+    }
+  return buffer;
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* regTypeNum - computes the type & number of registers required   */
 /*-----------------------------------------------------------------*/
-static void regTypeNum (void)
+static void 
+regTypeNum (void)
 {
-    symbol *sym;
-    int k;
+  symbol *sym;
+  int k;
 
-    /* for each live range do */
-    for ( sym = hTabFirstItem(liveRanges,&k); sym ;
-         sym = hTabNextItem(liveRanges,&k)) {
+  /* for each live range do */
+  for (sym = hTabFirstItem (liveRanges, &k); sym;
+       sym = hTabNextItem (liveRanges, &k))
+    {
 
-       /* if used zero times then no registers needed */
-       if ((sym->liveTo - sym->liveFrom) == 0)
-           continue ;
+      /* if used zero times then no registers needed */
+      if ((sym->liveTo - sym->liveFrom) == 0)
+       continue;
 
-       D(D_ALLOC, ("regTypeNum: loop on sym %zs\n", sym));
-       
-       /* if the live range is a temporary */
-       if (sym->isitmp) {
+      D (D_ALLOC, ("regTypeNum: loop on sym %p\n", sym));
 
-           /* if the type is marked as a conditional */
-           if (sym->regType == REG_CND)
-               continue ;
+      /* if the live range is a temporary */
+      if (sym->isitmp)
+       {
 
-           /* if used in return only then we don't 
-              need registers */
-           if (sym->ruonly || sym->accuse) {
-               if (IS_AGGREGATE(sym->type) || sym->isptr)
-                   sym->type = aggrToPtr(sym->type,FALSE);
-               continue ;
+         /* if the type is marked as a conditional */
+         if (sym->regType == REG_CND)
+           continue;
+
+         /* if used in return only then we don't 
+            need registers */
+         if (sym->ruonly || sym->accuse)
+           {
+             if (IS_AGGREGATE (sym->type) || sym->isptr)
+               sym->type = aggrToPtr (sym->type, FALSE);
+             continue;
            }
 
-           /* if not then we require registers */
-           sym->nRegs = ((IS_AGGREGATE(sym->type) || sym->isptr ) ?
-                         getSize(sym->type = aggrToPtr(sym->type,FALSE)) :
-                         getSize(sym->type));
+         /* if not then we require registers */
+         D (D_ALLOC, ("regTypeNum: isagg %u nRegs %u type %p\n", IS_AGGREGATE (sym->type) || sym->isptr, sym->nRegs, sym->type));
+         sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
+                       getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
+                       getSize (sym->type));
+         D (D_ALLOC, ("regTypeNum: setting nRegs of %s (%p) to %u\n", sym->name, sym, sym->nRegs));
 
-           D(D_ALLOC, ("regTypeNum: setup to assign regs sym %zs\n", sym));
+         D (D_ALLOC, ("regTypeNum: setup to assign regs sym %p\n", sym));
 
-           if (sym->nRegs > 4) {
-               fprintf(stderr,"allocated more than 4 or 0 registers for type ");
-               printTypeChain(sym->type,stderr);fprintf(stderr,"\n");
-            }
-           
-           /* determine the type of register required */
-           /* Always general purpose */
-           sym->regType = REG_GPR ;
-           
-       } else 
-           /* for the first run we don't provide */
-           /* registers for true symbols we will */
-           /* see how things go                  */
-           sym->nRegs = 0 ;    
+         if (sym->nRegs > 4)
+           {
+             fprintf (stderr, "allocated more than 4 or 0 registers for type ");
+             printTypeChain (sym->type, stderr);
+             fprintf (stderr, "\n");
+           }
+
+         /* determine the type of register required */
+         /* Always general purpose */
+         sym->regType = REG_GPR;
+
+       }
+      else
+       {
+         /* for the first run we don't provide */
+         /* registers for true symbols we will */
+         /* see how things go                  */
+         D (D_ALLOC, ("regTypeNum: #2 setting num of %p to 0\n", sym));
+         sym->nRegs = 0;
+       }
     }
-    
+
 }
 
 /** Mark all registers as free.
  */
-static void freeAllRegs()
+static void 
+freeAllRegs ()
 {
-    int i;
+  int i;
 
-    D(D_ALLOC, ("freeAllRegs: running.\n"));
+  (D_ALLOC, ("freeAllRegs: running.\n"));
 
-    for (i=0;i< _nRegs;i++ )
-       regsZ80[i].isFree = 1;
+  for (i = 0; i < _G.nRegs; i++)
+    regsZ80[i].isFree = 1;
 }
 
 /*-----------------------------------------------------------------*/
 /* deallocStackSpil - this will set the stack pointer back         */
 /*-----------------------------------------------------------------*/
-DEFSETFUNC(deallocStackSpil)
+DEFSETFUNC (deallocStackSpil)
 {
-    symbol *sym = item;
+  symbol *sym = item;
 
-    deallocLocal(sym);
-    return 0;
+  deallocLocal (sym);
+  return 0;
 }
 
 /** Register reduction for assignment.
  */
-static int packRegsForAssign (iCode *ic,eBBlock *ebp)
+static int 
+packRegsForAssign (iCode * ic, eBBlock * ebp)
 {
-    iCode *dic, *sic;
+  iCode *dic, *sic;
 
-    D(D_ALLOC, ("packRegsForAssing: running on ic %zi\n", ic));
-    
-    if (
-       /*      !IS_TRUE_SYMOP(IC_RESULT(ic)) ||*/
-       !IS_ITEMP(IC_RIGHT(ic))       ||
-       OP_LIVETO(IC_RIGHT(ic)) > ic->seq ||
-       OP_SYMBOL(IC_RIGHT(ic))->isind)
-       return 0;
+  D (D_ALLOC, ("packRegsForAssign: running on ic %p\n", ic));
 
-#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 (isOperandInFarSpace(IC_RESULT(ic))) {
-       if ((dic = farSpacePackable(ic)))
-           goto pack;
-       else
-           return 0;
+  if (!IS_ITEMP (IC_RIGHT (ic)) ||
+      OP_SYMBOL (IC_RIGHT (ic))->isind ||
+      OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
+    {
+      return 0;
     }
-#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 
-       we cannot */    
-    for ( dic = ic->prev ; dic ; dic = dic->prev) {
-       /* if there is a function call and this is
-          a parameter & not my parameter then don't pack it */
-       if ( (dic->op == CALL || dic->op == PCALL) &&
-            (OP_SYMBOL(IC_RESULT(ic))->_isparm &&
-             !OP_SYMBOL(IC_RESULT(ic))->ismyparm)) {
-           dic = NULL;
-           break;
+  /* 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)
+    {
+      /* PENDING: Don't pack across function calls. */
+      if (dic->op == CALL || dic->op == PCALL)
+       {
+         dic = NULL;
+         break;
        }
 
-       if (SKIP_IC2(dic))
-               continue;
+      if (SKIP_IC2 (dic))
+       continue;
+
+      if (dic->op == IFX)
+        {
+          if (IS_SYMOP (IC_COND (dic)) &&
+             (IC_COND (dic)->key == IC_RESULT (ic)->key ||
+              IC_COND (dic)->key == IC_RIGHT (ic)->key))
+           {
+             dic = NULL;
+             break;
+           }
+        }
+      else
+        {
+          if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
+             IS_OP_VOLATILE (IC_RESULT (dic)))
+           {
+             dic = NULL;
+             break;
+           }
 
-       if (IS_SYMOP(IC_RESULT(dic)) &&
-           IC_RESULT(dic)->key == IC_RIGHT(ic)->key) {
-           break;          
-       }
+          if (IS_SYMOP (IC_RESULT (dic)) &&
+             IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+           {
+             if (POINTER_SET (dic))
+               dic = NULL;
 
-       if (IS_SYMOP(IC_RIGHT(dic)) && 
-           (IC_RIGHT(dic)->key == IC_RESULT(ic)->key ||
-            IC_RIGHT(dic)->key == IC_RIGHT(ic)->key)) {
-           dic = NULL;
-           break;
-       }
-       
-       if (IS_SYMOP(IC_LEFT(dic)) && 
-           (IC_LEFT(dic)->key == IC_RESULT(ic)->key ||
-            IC_LEFT(dic)->key == IC_RIGHT(ic)->key)) {
-           dic = NULL;
-           break;
-       }
-#if 0
-       if (POINTER_SET(dic) && 
-           IC_RESULT(dic)->key == IC_RESULT(ic)->key ) {
-           dic = NULL ;
-           break;
+             break;
+           }
+
+          if (IS_SYMOP (IC_RIGHT (dic)) &&
+             (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
+              IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
+           {
+             dic = NULL;
+             break;
+           }
+
+          if (IS_SYMOP (IC_LEFT (dic)) &&
+             (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
+              IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
+           {
+             dic = NULL;
+             break;
+           }
+
+          if (IS_SYMOP (IC_RESULT (dic)) &&
+             IC_RESULT (dic)->key == IC_RESULT (ic)->key)
+           {
+             dic = NULL;
+             break;
+           }
+           
        }
-#endif
     }
-    
-    if (!dic)
-       return 0 ; /* did not find */
-           
-    /* if the result is on stack or iaccess then it must be
-       the same atleast one of the operands */
-    if (OP_SYMBOL(IC_RESULT(ic))->onStack  || 
-       OP_SYMBOL(IC_RESULT(ic))->iaccess ) {
-
-       /* the operation has only one symbol
-          operator then we can pack */
-       if ((IC_LEFT(dic) && !IS_SYMOP(IC_LEFT(dic))) ||
-           (IC_RIGHT(dic) && !IS_SYMOP(IC_RIGHT(dic))))
-           goto pack;
-
-       if (!((IC_LEFT(dic) &&
-            IC_RESULT(ic)->key == IC_LEFT(dic)->key) ||
-             (IC_RIGHT(dic) &&
-              IC_RESULT(ic)->key == IC_RIGHT(dic)->key)))
-           return 0;                
+
+  if (!dic)
+    return 0;                  /* did not find */
+
+  /* if assignment then check that right is not a bit */
+  if (ASSIGNMENT (ic) && !POINTER_SET (ic))
+    {
+      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 (ic));
+          if (!IS_BITFIELD (etype))
+            {
+              return 0;
+            }
+       }
+    }
+
+  /* if the result is on stack or iaccess then it must be
+     the same atleast one of the operands */
+  if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
+      OP_SYMBOL (IC_RESULT (ic))->iaccess)
+    {
+      /* the operation has only one symbol
+         operator then we can pack */
+      if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) ||
+         (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic))))
+       goto pack;
+
+      if (!((IC_LEFT (dic) &&
+            IC_RESULT (ic)->key == IC_LEFT (dic)->key) ||
+           (IC_RIGHT (dic) &&
+            IC_RESULT (ic)->key == IC_RIGHT (dic)->key)))
+       return 0;
     }
 pack:
-    /* found the definition */
-    /* replace the result with the result of */
-    /* this assignment and remove this assignment */
-    IC_RESULT(dic) = IC_RESULT(ic) ;
-
-    if (IS_ITEMP(IC_RESULT(dic)) && OP_SYMBOL(IC_RESULT(dic))->liveFrom > dic->seq) {
-           OP_SYMBOL(IC_RESULT(dic))->liveFrom = dic->seq;
-    }
-    /* delete from liverange table also 
-       delete from all the points inbetween and the new
-       one */
-    for ( sic = dic; sic != ic ; sic = sic->next ) {   
-       bitVectUnSetBit(sic->rlive,IC_RESULT(ic)->key);
-       if (IS_ITEMP(IC_RESULT(dic)))
-           bitVectSetBit(sic->rlive,IC_RESULT(dic)->key);
-    }
-        
-    remiCodeFromeBBlock(ebp,ic);
-    return 1;
-    
+  /* found the definition */
+  /* replace the result with the result of */
+  /* this assignment and remove this assignment */
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+  IC_RESULT (dic) = IC_RESULT (ic);
+
+  if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
+    {
+      OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
+    }
+  /* delete from liverange table also 
+     delete from all the points inbetween and the new
+     one */
+  for (sic = dic; sic != ic; sic = sic->next)
+    {
+      bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
+      if (IS_ITEMP (IC_RESULT (dic)))
+       bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
+    }
+
+  remiCodeFromeBBlock (ebp, ic);
+  // PENDING: Check vs mcs51
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+  hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+  OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+  return 1;
 }
 
 /** Scanning backwards looks for first assig found.
  */
-iCode *findAssignToSym (operand *op,iCode *ic)
+iCode *
+findAssignToSym (operand * op, iCode * ic)
 {
-    iCode *dic;
-
-    for (dic = ic->prev ; dic ; dic = dic->prev) {
-       
-       /* if definition by assignment */
-       if (dic->op == '='                 && 
-           !POINTER_SET(dic)              &&
-           IC_RESULT(dic)->key == op->key)
-           /*      &&  IS_TRUE_SYMOP(IC_RIGHT(dic))*/
-           {      
-
-           /* we are interested only if defined in far space */
-           /* or in stack space in case of + & - */
-
-           /* if assigned to a non-symbol then return
-              true */
-           if (!IS_SYMOP(IC_RIGHT(dic)))
-               break ;
-
-           /* 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 */
-           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;
-           }           
-
-           break ;
-               
-       }
+  iCode *dic;
 
-       /* if we find an usage then we cannot delete it */
-       if (IC_LEFT(dic) && IC_LEFT(dic)->key == op->key)
-           return NULL;
-           
-       if (IC_RIGHT(dic) && IC_RIGHT(dic)->key == op->key)
-           return NULL;
+  for (dic = ic->prev; dic; dic = dic->prev)
+    {
 
-       if (POINTER_SET(dic) && IC_RESULT(dic)->key == op->key)
+      /* if definition by assignment */
+      if (dic->op == '=' &&
+         !POINTER_SET (dic) &&
+         IC_RESULT (dic)->key == op->key)
+       /*      &&  IS_TRUE_SYMOP(IC_RIGHT(dic)) */
+       {
+
+         /* we are interested only if defined in far space */
+         /* or in stack space in case of + & - */
+
+         /* if assigned to a non-symbol then return
+            true */
+         if (!IS_SYMOP (IC_RIGHT (dic)))
+           break;
+
+         /* if the symbol is in far space then
+            we should not */
+         if (isOperandInFarSpace (IC_RIGHT (dic)))
            return NULL;
-    }
 
-    /* now make sure that the right side of dic
-       is not defined between ic & dic */       
-    if (dic) {
-       iCode *sic = dic->next ;
+         /* for + & - operations make sure that
+            if it is on the stack it is the same
+            as one of the three operands */
+         if ((ic->op == '+' || ic->op == '-') &&
+             OP_SYMBOL (IC_RIGHT (dic))->onStack)
+           {
 
-       for (; sic != ic ; sic = sic->next)
-           if (IC_RESULT(sic) &&
-               IC_RESULT(sic)->key == IC_RIGHT(dic)->key)
+             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;
+           }
+
+         break;
+
+       }
+
+      /* if we find an usage then we cannot delete it */
+      if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
+       return NULL;
+
+      if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
+       return NULL;
+
+      if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
+       return NULL;
+    }
+
+  /* now make sure that the right side of dic
+     is not defined between ic & dic */
+  if (dic)
+    {
+      iCode *sic = dic->next;
+
+      for (; sic != ic; sic = sic->next)
+       if (IC_RESULT (sic) &&
+           IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
+         return NULL;
     }
 
-    return dic;
-       
-       
+  return dic;
+
+
 }
 
+#if !DISABLE_PACKREGSFORSUPPORT
+// PENDING
+
 /*-----------------------------------------------------------------*/
 /* packRegsForSupport :- reduce some registers for support calls   */
 /*-----------------------------------------------------------------*/
-static int packRegsForSupport (iCode *ic, eBBlock *ebp)
+static int 
+packRegsForSupport (iCode * ic, eBBlock * ebp)
 {
-    int change = 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 */
-    D(D_ALLOC, ("packRegsForSupport: running on ic %zi\n", ic));
-
-    if (IS_ITEMP(IC_LEFT(ic)) && 
-       OP_SYMBOL(IC_LEFT(ic))->liveTo <= ic->seq) {
-       iCode *dic = findAssignToSym(IC_LEFT(ic),ic);
-       iCode *sic;
-
-       if (!dic)
-           goto right ;
-
-       /* found it we need to remove it from the
-          block */
-       for ( sic = dic; sic != ic ; sic = sic->next )
-           bitVectUnSetBit(sic->rlive,IC_LEFT(ic)->key);
-
-       IC_LEFT(ic)->operand.symOperand =
-           IC_RIGHT(dic)->operand.symOperand;
-       IC_LEFT(ic)->key = IC_RIGHT(dic)->operand.symOperand->key;
-       remiCodeFromeBBlock(ebp,dic);   
-       change++;      
+  int change = 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 */
+  D (D_ALLOC, ("packRegsForSupport: running on ic %p\n", ic));
+
+  if (IS_ITEMP (IC_LEFT (ic)) &&
+      OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
+    {
+      iCode *dic = findAssignToSym (IC_LEFT (ic), ic);
+      iCode *sic;
+
+      if (!dic)
+       goto right;
+
+      /* found it we need to remove it from the
+         block */
+      for (sic = dic; sic != ic; sic = sic->next)
+       bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
+
+      IC_LEFT (ic)->operand.symOperand =
+       IC_RIGHT (dic)->operand.symOperand;
+      IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
+      remiCodeFromeBBlock (ebp, dic);
+      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+      hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+      // PENDING: Check vs mcs51
+      change++;
     }
-    
-    /* do the same for the right operand */
- right:    
-    if (!change && 
-       IS_ITEMP(IC_RIGHT(ic)) &&
-       OP_SYMBOL(IC_RIGHT(ic))->liveTo <= ic->seq) {
-       iCode *dic = findAssignToSym(IC_RIGHT(ic),ic);
-       iCode *sic;
-       
-       if (!dic)
-           return change ;
-
-       /* found it we need to remove it from the block */
-       for ( sic = dic; sic != ic ; sic = sic->next )
-           bitVectUnSetBit(sic->rlive,IC_RIGHT(ic)->key);
-       
-       IC_RIGHT(ic)->operand.symOperand =
-           IC_RIGHT(dic)->operand.symOperand;
-       IC_RIGHT(ic)->key = IC_RIGHT(dic)->operand.symOperand->key;
-       
-       remiCodeFromeBBlock(ebp,dic);
-       change ++;
-    }
-   
-    return change ;
+
+  /* do the same for the right operand */
+right:
+  if (!change &&
+      IS_ITEMP (IC_RIGHT (ic)) &&
+      OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
+    {
+      iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
+      iCode *sic;
+
+      if (!dic)
+       return change;
+
+      /* found it we need to remove it from the block */
+      for (sic = dic; sic != ic; sic = sic->next)
+       bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
+
+      IC_RIGHT (ic)->operand.symOperand =
+       IC_RIGHT (dic)->operand.symOperand;
+      IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
+
+      remiCodeFromeBBlock (ebp, dic);
+      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+      hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+      // PENDING: vs mcs51
+      change++;
+    }
+
+  return change;
 }
+#endif
 
 #define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
 
 /** Will reduce some registers for single use.
  */
-static iCode *packRegsForOneuse (iCode *ic, operand *op , eBBlock *ebp)
+static iCode *
+packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
 {
-    bitVect *uses ;
-    iCode *dic, *sic;
+  bitVect *uses;
+  iCode *dic, *sic;
 
-    D(D_ALLOC, ("packRegsForOneUse: running on ic %zi\n", ic));
+  // PENDING: Disable
+  D (D_ALLOC, ("packRegsForOneUse: running on ic %p\n", ic));
 
-    /* if returning a literal then do nothing */
-    if (!IS_SYMOP(op))
-       return NULL;
-    
-    /* only upto 2 bytes since we cannot predict
-       the usage of b, & acc */
-    if (getSize(operandType(op)) > 2 && 
-       ic->op != RETURN             &&
-       ic->op != SEND)
-       return NULL;
+  /* if returning a literal then do nothing */
+  if (!IS_SYMOP (op))
+    return NULL;
 
-    /* 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 
-       function or does not contain any variables in
-       far space */
-    uses = bitVectCopy(OP_USES(op));
-    bitVectUnSetBit(uses,ic->key); /* take away this iCode */
-    if (!bitVectIsZero(uses)) /* has other uses */
-       return NULL ;
-    
-    /* if it has only one defintion */
-    if (bitVectnBitsOn(OP_DEFS(op)) > 1)
-       return NULL ; /* has more than one definition */
-
-    /* get the that definition */
-    if (!(dic = 
-         hTabItemWithKey(iCodehTab,
-                         bitVectFirstBit(OP_DEFS(op)))))
-       return NULL ;
-
-    /* found the definition now check if it is local */
-    if (dic->seq < ebp->fSeq ||
-       dic->seq > ebp->lSeq)
-       return NULL ; /* non-local */
-
-    /* now check if it is the return from a function call */
-    if (dic->op == CALL || dic->op == PCALL ) {
-       if (ic->op != SEND && ic->op != RETURN) {
-           OP_SYMBOL(op)->ruonly = 1;
-           return dic;
+  /* only upto 2 bytes since we cannot predict
+     the usage of b, & acc */
+  if (getSize (operandType (op)) > 2)
+    return NULL;
+
+  if (ic->op != RETURN &&
+      ic->op != SEND)
+    return NULL;
+
+  /* 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 
+     function or does not contain any variables in
+     far space */
+  uses = bitVectCopy (OP_USES (op));
+  bitVectUnSetBit (uses, ic->key);     /* take away this iCode */
+  if (!bitVectIsZero (uses))   /* has other uses */
+    return NULL;
+
+  /* if it has only one defintion */
+  if (bitVectnBitsOn (OP_DEFS (op)) > 1)
+    return NULL;               /* has more than one definition */
+
+  /* get the that definition */
+  if (!(dic =
+       hTabItemWithKey (iCodehTab,
+                        bitVectFirstBit (OP_DEFS (op)))))
+    return NULL;
+
+  /* found the definition now check if it is local */
+  if (dic->seq < ebp->fSeq ||
+      dic->seq > ebp->lSeq)
+    return NULL;               /* non-local */
+
+  /* now check if it is the return from a function call */
+  if (dic->op == CALL || dic->op == PCALL)
+    {
+      if (ic->op != SEND && ic->op != RETURN &&
+         !POINTER_SET(ic) && !POINTER_GET(ic))
+       {
+         OP_SYMBOL (op)->ruonly = 1;
+         return dic;
        }
-       dic = dic->next ;
-    }
-        
-    /* otherwise check that the definition does
-       not contain any symbols in far space */
-    if (isOperandInFarSpace(IC_LEFT(dic))  ||
-       isOperandInFarSpace(IC_RIGHT(dic)) ||
-       IS_OP_RUONLY(IC_LEFT(ic))          ||
-       IS_OP_RUONLY(IC_RIGHT(ic)) )        {
-       return NULL;
+      dic = dic->next;
     }
-    
-    /* if pointer set then make sure the pointer is one byte */
-    if (POINTER_SET(dic))
-      return NULL;
 
-    if (POINTER_GET(dic))
+  /* otherwise check that the definition does
+     not contain any symbols in far space */
+  if (isOperandInFarSpace (IC_LEFT (dic)) ||
+      isOperandInFarSpace (IC_RIGHT (dic)) ||
+      IS_OP_RUONLY (IC_LEFT (ic)) ||
+      IS_OP_RUONLY (IC_RIGHT (ic)))
+    {
       return NULL;
-    
-    sic = dic;
+    }
 
-    /* also make sure the intervenening instructions
-       don't have any thing in far space */
-    for (dic = dic->next ; dic && dic != ic ; dic = dic->next) {
-       /* if there is an intervening function call then no */
-       if (dic->op == CALL || dic->op == PCALL)
-               return NULL;
-       /* if pointer set then make sure the pointer
-          is one byte */
-       if (POINTER_SET(dic))
-           return NULL ;
-       
-       if (POINTER_GET(dic))
-           return NULL ;
-
-       /* if address of & the result is remat the okay */
-       if (dic->op == ADDRESS_OF &&
-           OP_SYMBOL(IC_RESULT(dic))->remat)
-           continue ;
-          
-       /* if left or right or result is in far space */
-       if (isOperandInFarSpace(IC_LEFT(dic))   ||
-           isOperandInFarSpace(IC_RIGHT(dic))  ||
-           isOperandInFarSpace(IC_RESULT(dic)) ||
-           IS_OP_RUONLY(IC_LEFT(dic))          ||
-           IS_OP_RUONLY(IC_RIGHT(dic))         ||
-           IS_OP_RUONLY(IC_RESULT(dic))            ) {
-           return NULL;
+  /* if pointer set then make sure the pointer is one byte */
+  if (POINTER_SET (dic))
+    return NULL;
+
+  if (POINTER_GET (dic))
+    return NULL;
+
+  sic = dic;
+
+  /* also make sure the intervenening instructions
+     don't have any thing in far space */
+  for (dic = dic->next; dic && dic != ic; dic = dic->next)
+    {
+      /* if there is an intervening function call then no */
+      if (dic->op == CALL || dic->op == PCALL)
+       return NULL;
+      /* if pointer set then make sure the pointer
+         is one byte */
+      if (POINTER_SET (dic))
+       return NULL;
+
+      if (POINTER_GET (dic))
+       return NULL;
+
+      /* if address of & the result is remat the okay */
+      if (dic->op == ADDRESS_OF &&
+         OP_SYMBOL (IC_RESULT (dic))->remat)
+       continue;
+
+      /* if left or right or result is in far space */
+      if (isOperandInFarSpace (IC_LEFT (dic)) ||
+         isOperandInFarSpace (IC_RIGHT (dic)) ||
+         isOperandInFarSpace (IC_RESULT (dic)) ||
+         IS_OP_RUONLY (IC_LEFT (dic)) ||
+         IS_OP_RUONLY (IC_RIGHT (dic)) ||
+         IS_OP_RUONLY (IC_RESULT (dic)))
+       {
+         return NULL;
        }
     }
-               
-    OP_SYMBOL(op)->ruonly = 1;
-    return sic;
+
+  OP_SYMBOL (op)->ruonly = 1;
+  return sic;
 }
 
 /*-----------------------------------------------------------------*/
 /* isBitwiseOptimizable - requirements of JEAN LOUIS VERN          */
 /*-----------------------------------------------------------------*/
-static bool isBitwiseOptimizable (iCode *ic)
+static bool 
+isBitwiseOptimizable (iCode * ic)
 {
-    link *rtype = getSpec(operandType(IC_RIGHT(ic)));
-
-    /* bitwise operations are considered optimizable
-       under the following conditions (Jean-Louis VERN) 
-       
-       x & lit
-       bit & bit
-       bit & x
-       bit ^ bit
-       bit ^ x
-       x   ^ lit
-       x   | lit
-       bit | bit
-       bit | x
-    */    
-    if (IS_LITERAL(rtype))
-       return TRUE;
-    return FALSE; 
+  sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
+
+  /* bitwise operations are considered optimizable
+     under the following conditions (Jean-Louis VERN) 
+
+     x & lit
+     bit & bit
+     bit & x
+     bit ^ bit
+     bit ^ x
+     x   ^ lit
+     x   | lit
+     bit | bit
+     bit | x
+   */
+  if (IS_LITERAL (rtype))
+    return TRUE;
+  return FALSE;
 }
 
 /** Optimisations:
@@ -1673,581 +2135,1099 @@ genAssign (ptr)
     ld (iy),(hl)
 */
 
+#if !DISABLE_PACKREGSFORACCUSE
+// PENDING
+
 /** Pack registers for acc use.
     When the result of this operation is small and short lived it may
     be able to be stored in the accumelator.
  */
-static void packRegsForAccUse (iCode *ic)
+static void 
+packRegsForAccUse (iCode * ic)
 {
-    iCode *uic;
-    
-    /* if + or - then it has to be one byte result */
-    if ((ic->op == '+' || ic->op == '-')
-       && getSize(operandType(IC_RESULT(ic))) > 1)
-       return ;
-    
-    /* if shift operation make sure right side is not a literal */
-    if (ic->op == RIGHT_OP  &&
-       (isOperandLiteral(IC_RIGHT(ic)) ||
-         getSize(operandType(IC_RESULT(ic))) > 1))
-       return ;
-       
-    if (ic->op == LEFT_OP &&        
-       ( isOperandLiteral(IC_RIGHT(ic)) ||
-         getSize(operandType(IC_RESULT(ic))) > 1))
-       return ;
-       
-    /* has only one definition */
-    if (bitVectnBitsOn(OP_DEFS(IC_RESULT(ic))) > 1)
-       return ;
-
-    /* has only one use */
-    if (bitVectnBitsOn(OP_USES(IC_RESULT(ic))) > 1)
-       return ;
-
-    /* and the usage immediately follows this iCode */
-    if (!(uic = hTabItemWithKey(iCodehTab,
-                               bitVectFirstBit(OP_USES(IC_RESULT(ic))))))
-       return ;
-
-    if (ic->next != uic)
-       return ;
-    
-    /* if it is a conditional branch then we definitely can */
-    if (uic->op == IFX  ) 
-       goto accuse;
+  iCode *uic;
+
+  /* if this is an aggregate, e.g. a one byte char array */
+  if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
+    return;
+  }
+
+  /* if + or - then it has to be one byte result */
+  if ((ic->op == '+' || ic->op == '-')
+      && getSize (operandType (IC_RESULT (ic))) > 1)
+    return;
+
+  /* if shift operation make sure right side is not a literal */
+  if (ic->op == RIGHT_OP &&
+      (isOperandLiteral (IC_RIGHT (ic)) ||
+       getSize (operandType (IC_RESULT (ic))) > 1))
+    return;
+
+  if (ic->op == LEFT_OP &&
+      (isOperandLiteral (IC_RIGHT (ic)) ||
+       getSize (operandType (IC_RESULT (ic))) > 1))
+    return;
+
+  /* has only one definition */
+  if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
+    return;
 
-    if ( uic->op == JUMPTABLE )
-       return ;
+  /* has only one use */
+  if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
+    return;
+
+  /* and the usage immediately follows this iCode */
+  if (!(uic = hTabItemWithKey (iCodehTab,
+                              bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
+    return;
+
+  if (ic->next != uic)
+    return;
+
+  /* if it is a conditional branch then we definitely can */
+  if (uic->op == IFX)
+    goto accuse;
+
+  if (uic->op == JUMPTABLE)
+    return;
 
 #if 0
-    /* if the usage is not is an assignment or an 
-       arithmetic / bitwise / shift operation then not */
-    if (POINTER_SET(uic) && 
-       getSize(aggrToPtr(operandType(IC_RESULT(uic)),FALSE)) > 1)
-       return;
+  /* if the usage is not is an assignment or an 
+     arithmetic / bitwise / shift operation then not */
+  if (POINTER_SET (uic) &&
+      getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1)
+    return;
 #endif
 
-    if (uic->op != '=' && 
-       !IS_ARITHMETIC_OP(uic) &&
-       !IS_BITWISE_OP(uic)    &&
-       uic->op != LEFT_OP &&
-       uic->op != RIGHT_OP )
-       return;
-
-    /* if used in ^ operation then make sure right is not a 
-       literl */
-    if (uic->op == '^' && isOperandLiteral(IC_RIGHT(uic)))
-       return ;
-
-    /* if shift operation make sure right side is not a literal */
-    if (uic->op == RIGHT_OP  &&
-       ( isOperandLiteral(IC_RIGHT(uic)) ||
-         getSize(operandType(IC_RESULT(uic))) > 1))
-       return ;
-
-    if (uic->op == LEFT_OP &&        
-       ( isOperandLiteral(IC_RIGHT(uic)) ||
-         getSize(operandType(IC_RESULT(uic))) > 1))
-       return ;
-           
+  if (uic->op != '=' &&
+      !IS_ARITHMETIC_OP (uic) &&
+      !IS_BITWISE_OP (uic) &&
+      uic->op != LEFT_OP &&
+      uic->op != RIGHT_OP)
+    return;
+
+  /* if used in ^ operation then make sure right is not a 
+     literl */
+  if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
+    return;
+
+  /* if shift operation make sure right side is not a literal */
+  if (uic->op == RIGHT_OP &&
+      (isOperandLiteral (IC_RIGHT (uic)) ||
+       getSize (operandType (IC_RESULT (uic))) > 1))
+    return;
+
+  if (uic->op == LEFT_OP &&
+      (isOperandLiteral (IC_RIGHT (uic)) ||
+       getSize (operandType (IC_RESULT (uic))) > 1))
+    return;
+
 #if 0
-    /* make sure that the result of this icode is not on the
-       stack, since acc is used to compute stack offset */
-    if (IS_TRUE_SYMOP(IC_RESULT(uic)) &&
-       OP_SYMBOL(IC_RESULT(uic))->onStack)
-       return ;
+  /* make sure that the result of this icode is not on the
+     stack, since acc is used to compute stack offset */
+  if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
+      OP_SYMBOL (IC_RESULT (uic))->onStack)
+    return;
 #endif
 
 #if 0
-    /* if either one of them in far space then we cannot */
-    if ((IS_TRUE_SYMOP(IC_LEFT(uic)) &&
-        isOperandInFarSpace(IC_LEFT(uic))) ||
-       (IS_TRUE_SYMOP(IC_RIGHT(uic)) &&
-        isOperandInFarSpace(IC_RIGHT(uic))))
-       return ;
+  /* if either one of them in far space then we cannot */
+  if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
+       isOperandInFarSpace (IC_LEFT (uic))) ||
+      (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
+       isOperandInFarSpace (IC_RIGHT (uic))))
+    return;
 #endif
 
-    /* if the usage has only one operand then we can */
-    if (IC_LEFT(uic) == NULL ||
-       IC_RIGHT(uic) == NULL) 
-       goto accuse;
-
-    /* make sure this is on the left side if not
-       a '+' since '+' is commutative */
-    if (ic->op != '+' &&
-       IC_LEFT(uic)->key != IC_RESULT(ic)->key)
-       return;
-
-    /* if one of them is a literal then we can */
-    if ((IC_LEFT(uic) && IS_OP_LITERAL(IC_LEFT(uic))) ||
-       (IC_RIGHT(uic) && IS_OP_LITERAL(IC_RIGHT(uic)))) {
-       OP_SYMBOL(IC_RESULT(ic))->accuse = 1;
-       return ;
-    }
-
-    /** This is confusing :)  Guess for now */
-    if (IC_LEFT(uic)->key == IC_RESULT(ic)->key &&
-       (IS_ITEMP(IC_RIGHT(uic)) ||
-        (IS_TRUE_SYMOP(IC_RIGHT(uic)))))
-       goto accuse;
-    
-    if (IC_RIGHT(uic)->key == IC_RESULT(ic)->key &&
-       (IS_ITEMP(IC_LEFT(uic)) ||
-        (IS_TRUE_SYMOP(IC_LEFT(uic)))))
-       goto accuse ;
-    return ;
- accuse:
-    OP_SYMBOL(IC_RESULT(ic))->accuse = 1;
+  /* if the usage has only one operand then we can */
+  if (IC_LEFT (uic) == NULL ||
+      IC_RIGHT (uic) == NULL)
+    goto accuse;
+
+  /* make sure this is on the left side if not
+     a '+' since '+' is commutative */
+  if (ic->op != '+' &&
+      IC_LEFT (uic)->key != IC_RESULT (ic)->key)
+    return;
+
+  // See mcs51 ralloc for reasoning
+#if 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))))
+    {
+      goto accuse;
+      return;
+    }
+#endif
+
+/** This is confusing :)  Guess for now */
+  if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
+      (IS_ITEMP (IC_RIGHT (uic)) ||
+       (IS_TRUE_SYMOP (IC_RIGHT (uic)))))
+    goto accuse;
+
+  if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key &&
+      (IS_ITEMP (IC_LEFT (uic)) ||
+       (IS_TRUE_SYMOP (IC_LEFT (uic)))))
+    goto accuse;
+  return;
+accuse:
+  OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_A;
 }
+#endif
 
-bool opPreservesA(iCode *ic, iCode *uic)
+static void 
+packRegsForHLUse (iCode * ic)
 {
-    /* if it is a conditional branch then we definitely can */
-    if (uic->op == IFX  ) 
-       return FALSE;
+  iCode *uic;
 
-    if ( uic->op == JUMPTABLE )
-       return FALSE;
+  /* PENDING: Could do IFX */
+  if (ic->op == IFX)
+    {
+      return;
+    }
 
-    /* if the usage has only one operand then we can */
-    /* PENDING: check */
-    if (IC_LEFT(uic) == NULL ||
-       IC_RIGHT(uic) == NULL) 
-       return FALSE;
+  /* has only one definition */
+  if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
+    {
+      D (D_HLUSE, ("  + Dropping as has more than one def\n"));
+      return;
+    }
 
-    /* PENDING: check this rule */
-    if (getSize(operandType(IC_RESULT(uic))) > 1) {
-       return FALSE;
+  /* has only one use */
+  if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
+    {
+      D (D_HLUSE, ("  + Dropping as has more than one use\n"));
+      return;
     }
 
-    /*
-      Bad:
-       !IS_ARITHMETIC_OP(uic) (sub requires A)
-    */
-    if (
-       uic->op != '+' &&
-       !IS_BITWISE_OP(uic)    &&
-       uic->op != '=' && 
-       uic->op != EQ_OP &&
-       !POINTER_GET(uic) &&
-       /*
-       uic->op != LEFT_OP &&
-       uic->op != RIGHT_OP &&*/
-       1
-       ) {
-       return FALSE;
+  /* and the usage immediately follows this iCode */
+  if (!(uic = hTabItemWithKey (iCodehTab,
+                              bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
+    {
+      D (D_HLUSE, ("  + Dropping as usage isn't in this block\n"));
+      return;
     }
 
-    /* PENDING */
-    if (!IC_LEFT(uic) || !IC_RESULT(ic))
-       return FALSE;
+  if (ic->next != uic)
+    {
+      D (D_HLUSE, ("  + Dropping as usage doesn't follow this\n"));
+      return;
+    }
 
-    /** This is confusing :)  Guess for now */
-    if (IC_LEFT(uic)->key == IC_RESULT(ic)->key &&
-       (IS_ITEMP(IC_RIGHT(uic)) ||
-        (IS_TRUE_SYMOP(IC_RIGHT(uic)))))
-       return TRUE;
-    
-    if (IC_RIGHT(uic)->key == IC_RESULT(ic)->key &&
-       (IS_ITEMP(IC_LEFT(uic)) ||
-        (IS_TRUE_SYMOP(IC_LEFT(uic)))))
-       return TRUE;
+  if (uic->op ==IFX)
+    {
+      return;
+    }
 
-    return FALSE;
+  if (getSize (operandType (IC_RESULT (ic))) != 2 ||
+      (IC_LEFT(uic) && getSize (operandType (IC_LEFT (uic))) != 2) ||
+      (IC_RIGHT(uic) && getSize (operandType (IC_RIGHT (uic))) != 2))
+    {
+      D (D_HLUSE, ("  + Dropping as the result size is not 2\n"));
+      return;
+    }
+
+  if (IS_Z80)
+    {
+      if (ic->op == CAST && uic->op == IPUSH)
+        goto hluse;
+      if (ic->op == ADDRESS_OF && uic->op == IPUSH)
+        goto hluse;
+      if (ic->op == ADDRESS_OF && POINTER_GET (uic) && IS_ITEMP( IC_RESULT (uic)))
+        goto hluse;
+      if (ic->op == CALL && ic->parmBytes == 0 && (uic->op == '-' || uic->op == '+'))
+        goto hluse;
+    }
+  else if (IS_GB)
+    {
+      /* Case of assign a constant to offset in a static array. */
+      if (ic->op == '+' && IS_VALOP (IC_RIGHT (ic)))
+        {
+          if (uic->op == '=' && POINTER_SET (uic))
+            {
+              goto hluse;
+            }
+          else if (uic->op == IPUSH && getSize (operandType (IC_LEFT (uic))) == 2)
+            {
+              goto hluse;
+            }
+        }
+    }
+
+  D (D_HLUSE, ("  + Dropping as it's a bad op\n"));
+  return;
+hluse:
+  OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_SCRATCH;
+}
+
+static iCode *
+packRegsForHLUse3 (iCode * lic, operand * op, eBBlock * ebp)
+{
+  int i, key;
+  symbol *sym;
+  iCode *ic, *dic;
+  bool isFirst = TRUE;
+
+  D (D_PACK_HLUSE3, ("Checking HL on %p lic key %u first def %u line %u:\n", OP_SYMBOL(op), lic->key, bitVectFirstBit(OP_DEFS(op)), lic->lineno));
+  if (D_PACK_HLUSE3)
+    piCode(lic, NULL);
+
+  if ( OP_SYMBOL(op)->accuse)
+    {
+      return NULL;
+    }
+
+  if (OP_SYMBOL(op)->remat)
+    {
+      return NULL; 
+    }
+
+  /* Only defined once */
+  if (bitVectnBitsOn (OP_DEFS (op)) > 1)
+    return NULL;
+
+  if (getSize (operandType (op)) > 2)
+    return NULL;
+
+  /* And this is the definition */
+  if (bitVectFirstBit (OP_DEFS (op)) != lic->key)
+    return NULL;
+
+  /* first check if any overlapping liverange has already been
+     assigned to DPTR */
+  if (OP_SYMBOL(op)->clashes) 
+    {
+      for (i = 0 ; i < OP_SYMBOL(op)->clashes->size ; i++ ) 
+        {
+          if (bitVectBitValue(OP_SYMBOL(op)->clashes,i)) 
+            {
+              sym = hTabItemWithKey(liveRanges,i);
+              if (sym->accuse == ACCUSE_SCRATCH)
+                {
+                  return NULL;
+                }
+            }
+        }
+    }
+
+  /* Nothing else that clashes with this is using the scratch
+     register.  Scan through all of the intermediate instructions and
+     see if any of them could nuke HL.
+  */
+  dic = ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom);
+
+  for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
+       ic = hTabNextItem(iCodeSeqhTab, &key)) 
+    {
+      if (D_PACK_HLUSE3)
+        piCode(ic, NULL);
+      D (D_PACK_HLUSE3, ("(On %p: op: %u next: %p)\n", ic, ic->op, ic->next));
+
+      if (isFirst)
+        {
+          isFirst = FALSE;
+          if (ic->op == ADDRESS_OF)
+            continue;
+          if (POINTER_GET (ic))
+            continue;
+          if (ic->op == '=' && !POINTER_SET(ic))
+            continue;
+        }
+
+      if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic))
+          && isOperandInDirSpace (IC_RESULT (ic)))
+        return NULL;
+
+      if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic))
+          && isOperandInDirSpace (IC_LEFT (ic)))
+        return NULL;
+
+      if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic))
+          && isOperandInDirSpace (IC_RIGHT (ic)))
+        return NULL;
+
+      /* Handle the non left/right/result ones first */
+      if (ic->op == IFX)
+        continue;
+      if (ic->op == JUMPTABLE)
+        return NULL;
+
+      if (SKIP_IC2(ic))
+        continue;
+
+      if (ic->op == CAST)
+        continue;
+
+      if (ic->op == IPUSH && isOperandEqual (op, IC_LEFT (ic)))
+        continue;
+
+      if (ic->op == SEND && isOperandEqual (op, IC_LEFT (ic)))
+        continue;
+
+      if (ic->op == CALL && isOperandEqual (op, IC_RESULT (ic)))
+        continue;
+
+      if (ic->op == LEFT_OP && isOperandLiteral (IC_RIGHT (ic)))
+        continue;
+
+      if ((ic->op == '=' && !POINTER_SET(ic)) ||
+          ic->op == UNARYMINUS ||
+          ic->op == '+' ||
+          ic->op == '-' ||
+          ic->op == '>' ||
+          ic->op == '<' ||
+          ic->op == EQ_OP ||
+          0)
+        continue;
+
+      if (ic->op == '*' && isOperandEqual (op, IC_LEFT (ic)))
+        continue;
+
+      if (POINTER_SET (ic) && isOperandEqual (op, IC_RESULT (ic)))
+        continue;
+
+      if (POINTER_GET (ic) && isOperandEqual (op, IC_LEFT (ic)))
+        continue;
+
+      if (IS_VALOP (IC_RIGHT (ic)) &&
+          (ic->op == EQ_OP ||
+           0))
+        {
+          continue;
+        }
+
+      /* By default give up */
+      return NULL;
+    }
+
+  D (D_PACK_HLUSE3, ("Succeeded!\n"))
+
+  OP_SYMBOL (op)->accuse = ACCUSE_SCRATCH;
+  return dic;
+}
+
+static iCode *
+packRegsForIYUse (iCode * lic, operand * op, eBBlock * ebp)
+{
+  int i, key;
+  symbol *sym;
+  iCode *ic, *dic;
+  bitVect *uses;
+
+  D (D_PACK_IY, ("Checking IY on %p lic key %u first def %u line %u:\n", OP_SYMBOL(op), lic->key, bitVectFirstBit(OP_DEFS(op)), lic->lineno));
+  if (D_PACK_IY)
+    piCode(lic, NULL);
+
+  if ( OP_SYMBOL(op)->accuse)
+    {
+      return NULL;
+    }
+
+  if (OP_SYMBOL(op)->remat)
+    {
+      return NULL; 
+    }
+
+  /* Only defined once */
+  if (bitVectnBitsOn (OP_DEFS (op)) > 1)
+    return NULL;
+
+  /* And this is the definition */
+  if (bitVectFirstBit (OP_DEFS (op)) != lic->key)
+    return NULL;
+
+  /* first check if any overlapping liverange has already been
+     assigned to DPTR */
+  if (OP_SYMBOL(op)->clashes) 
+    {
+      for (i = 0 ; i < OP_SYMBOL(op)->clashes->size ; i++ ) 
+        {
+          if (bitVectBitValue(OP_SYMBOL(op)->clashes,i)) 
+            {
+              sym = hTabItemWithKey(liveRanges,i);
+              if (sym->accuse == ACCUSE_IY)
+                {
+                  return NULL;
+                }
+            }
+        }
+    }
+
+  /* Only a few instructions can load into IY */
+  if (lic->op != '=')
+    {
+      return NULL;
+    }
+
+  if (getSize (operandType (op)) != 2)
+    {
+      D (D_ACCUSE2, ("  + Dropping as operation has size is too big\n"));
+      return FALSE;
+    }
+
+  /* Nothing else that clashes with this is using the scratch
+     register.  Scan through all of the intermediate instructions and
+     see if any of them could nuke HL.
+  */
+  dic = ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom);
+  uses = OP_USES(op);
+
+  for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
+       ic = hTabNextItem(iCodeSeqhTab,&key)) 
+    {
+      if (D_PACK_IY)
+        piCode(ic, NULL);
+
+      if (ic->op == PCALL || 
+          ic->op == CALL ||
+          ic->op == JUMPTABLE
+          )
+        return NULL;
+
+      if (SKIP_IC2(ic))
+        continue;
+
+      /* Be pessamistic. */
+      if (ic->op == IFX)
+        return NULL;
+
+      D (D_PACK_IY, ("  op: %u uses %u result: %d left: %d right: %d\n", ic->op, bitVectBitValue(uses, ic->key),
+                     IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) ? isOperandInDirSpace(IC_RESULT(ic)) : -1,
+                     IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) ? isOperandInDirSpace(IC_LEFT(ic)) : -1,
+                     IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) ? isOperandInDirSpace(IC_RIGHT(ic)) : -1
+                     ));
+
+      if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) && 
+          isOperandInDirSpace(IC_RESULT(ic)))
+        return NULL;
+      
+      if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) && 
+          isOperandInDirSpace(IC_RIGHT(ic)))
+        return NULL;
+      
+      if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) && 
+          isOperandInDirSpace(IC_LEFT(ic)))
+        return NULL;
+
+      /* Only certain rules will work against IY.  Check if this iCode uses
+         this symbol. */
+      if (bitVectBitValue(uses, ic->key) != 0)
+        {
+          if (ic->op == '=' &&
+              isOperandEqual(IC_RESULT(ic), op))
+            continue;
+
+          if (ic->op == GET_VALUE_AT_ADDRESS &&
+              isOperandEqual(IC_LEFT(ic), op))
+            continue;
+
+          if (isOperandEqual(IC_RESULT(ic), IC_LEFT(ic)) == FALSE)
+            return NULL;
+
+          if (IC_RIGHT (ic) && IS_VALOP (IC_RIGHT (ic)))
+            {
+              if (ic->op == '+' ||
+                  ic->op == '-')
+                {
+                  /* Only works if the constant is small */
+                  if (operandLitValue (IC_RIGHT (ic)) < 4)
+                    continue;
+                }
+            }
+
+          return NULL;
+        }
+      else
+        {
+          /* This iCode doesn't use the sym.  See if this iCode preserves IY.
+           */
+          continue;
+        }
+
+      /* By default give up */
+      return NULL;
+    }
+
+  D (D_PACK_IY, ("Succeeded IY!\n"));
+
+  OP_SYMBOL (op)->accuse = ACCUSE_IY;
+  return dic;
+}
+
+/** Returns TRUE if this operation can use acc and if it preserves the value.
+ */
+static bool 
+opPreservesA (iCode * uic)
+{
+  if (uic->op == IFX)
+    {
+      /* If we've gotten this far then the thing to compare must be
+         small enough and must be in A.
+      */
+      return TRUE;
+    }
+
+  if (uic->op == JUMPTABLE)
+    {
+      D (D_ACCUSE2, ("  + Dropping as operation is a Jumptable\n"));
+      return FALSE;
+    }
+
+  /* A pointer assign preserves A if A is the left value. */
+  if (uic->op == '=' && POINTER_SET (uic))
+    {
+      return TRUE;
+    }
+
+  /* if the usage has only one operand then we can */
+  /* PENDING: check */
+  if (IC_LEFT (uic) == NULL ||
+      IC_RIGHT (uic) == NULL)
+    {
+      D (D_ACCUSE2, ("  + Dropping as operation has only one operand\n"));
+      return FALSE;
+    }
+
+  /* PENDING: check this rule */
+  if (getSize (operandType (IC_RESULT (uic))) > 1)
+    {
+      D (D_ACCUSE2, ("  + Dropping as operation has size is too big\n"));
+      return FALSE;
+    }
+
+
+  /* Disabled all of the old rules as they weren't verified and have
+     caused at least one problem.
+   */
+  return FALSE;
 }
 
+/** Returns true if this operand preserves the value of A.
+ */
+static bool
+opIgnoresA (iCode * ic, iCode * uic)
+{
+  /* A increment of an iTemp by a constant is OK. */
+  if ( uic->op == '+' &&
+       IS_ITEMP (IC_LEFT (uic)) &&
+       IS_ITEMP (IC_RESULT (uic)) &&
+       IS_OP_LITERAL (IC_RIGHT (uic)))
+    {
+      unsigned int icount = (unsigned int) floatFromVal (IC_RIGHT (uic)->operand.valOperand);
+
+      /* Being an ITEMP means that we're already a symbol. */
+      if (icount == 1 &&
+          IC_RESULT (uic)->operand.symOperand->key == IC_LEFT (uic)->operand.symOperand->key
+          )
+        {
+          return TRUE;
+        }
+    }
+  else if (uic->op == '=' && !POINTER_SET (uic))
+    {
+      /* If they are equal and get optimised out then things are OK. */
+      if (isOperandEqual (IC_RESULT (uic), IC_RIGHT (uic)))
+        {
+          /* Straight assign is OK. */
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
+
+/* Some optimisation cases:
+
+   1. Part of memcpy
+;      genPointerGet
+       ld      l,-4(ix)
+       ld      h,-3(ix)
+       ld      c,(hl)
+;      genPlus
+       inc     -4(ix)
+       jp      nz,00108$
+       inc     -3(ix)
+00108$:
+;      genAssign (pointer)
+       ld      a,c
+       ld      (de),a
+      want to optimise down to:
+        ld       hl,-4(ix) ...
+        ld       a,(hl)
+        inc      -4(ix).w  ...
+        ld       (de),a
+
+      So genPointer get is OK
+      genPlus where the right is constant, left is iTemp, and result is same as left
+      genAssign (pointer) is OK
+
+    2. Part of _strcpy
+;      genPointerGet
+       ld      a,(de)
+       ld      c,a
+;      genIfx
+       xor     a,a
+       or      a,c
+       jp      z,00103$
+;      _strcpy.c 40
+;      genAssign (pointer)
+;      AOP_STK for _strcpy_to_1_1
+       ld      l,-2(ix)
+       ld      h,-1(ix)
+       ld      (hl),c
+
+      want to optimise down to:
+        ld     a,(de)
+        or     a,a
+        jp     z,00103$
+        ld     (bc),a
+      
+      So genIfx where IC_COND has size of 1 and is a constant.
+*/
+
 /** Pack registers for acc use.
     When the result of this operation is small and short lived it may
-    be able to be stored in the accumelator.
+    be able to be stored in the accumulator.
 
-    Note that the 'A preserving' list is currently emperical :)e
+    Note that the 'A preserving' list is currently emperical :)
  */
-static void packRegsForAccUse2(iCode *ic)
+static void 
+packRegsForAccUse2 (iCode * ic)
 {
-    iCode *uic;
-
-    D(D_ALLOC, ("packRegsForAccUse2: running on ic %zi\n", ic));
-
-    /* Filter out all but those 'good' commands */
-    if (
-       !POINTER_GET(ic) &&
-       ic->op != '+' &&
-       !IS_BITWISE_OP(ic)    &&
-       ic->op != '=' && 
-       ic->op != EQ_OP &&
-       ic->op != CAST &&
-       1)
-       return;
-
-    /* if + or - then it has to be one byte result.
-       MLH: Ok.
-     */
-    if ((ic->op == '+' || ic->op == '-')
-       && getSize(operandType(IC_RESULT(ic))) > 1)
-       return ;
-    
-    /* if shift operation make sure right side is not a literal.
-       MLH: depends.
-     */
-#if 0
-    if (ic->op == RIGHT_OP  &&
-       (isOperandLiteral(IC_RIGHT(ic)) ||
-         getSize(operandType(IC_RESULT(ic))) > 1))
-       return ;
-       
-    if (ic->op == LEFT_OP &&        
-       ( isOperandLiteral(IC_RIGHT(ic)) ||
-         getSize(operandType(IC_RESULT(ic))) > 1))
-       return ;
-#endif
-       
-    /* has only one definition */
-    if (bitVectnBitsOn(OP_DEFS(IC_RESULT(ic))) > 1) {
-       return;
-    }
-
-    /* Right.  We may be able to propagate it through if:
-       For each in the chain of uses the intermediate is OK.
-    */
-    /* Get next with 'uses result' bit on
-       If this->next == next
-         Validate use of next
-        If OK, increase count
-    */
-    /* and the usage immediately follows this iCode */
-    if (!(uic = hTabItemWithKey(iCodehTab,
-                               bitVectFirstBit(OP_USES(IC_RESULT(ic)))))) {
-       return;
-    }
-
-    {
-       /* Create a copy of the OP_USES bit vect */
-       bitVect *uses = bitVectCopy(OP_USES(IC_RESULT(ic)));
-       int setBit;
-       iCode *scan = ic, *next;
-
-       do {
-           setBit = bitVectFirstBit(uses);
-           next = hTabItemWithKey(iCodehTab, setBit);
-           if (scan->next == next) {
-               bitVectUnSetBit(uses, setBit);
-               /* Still contigous. */
-               if (!opPreservesA(ic, next)) {
-                   return;
-               }
-               scan = next;
-           }
-           else {
-               return;
-           }
-       } while (!bitVectIsZero(uses));
-       OP_SYMBOL(IC_RESULT(ic))->accuse = 1;
-       return;
-    }
-
-    /* OLD CODE FOLLOWS */
-    /* if it is a conditional branch then we definitely can
-       MLH: Depends.
-     */
-#if 0    
-    if (uic->op == IFX ) 
-       goto accuse;
-
-    /* MLH: Depends. */
-    if ( uic->op == JUMPTABLE )
-       return ;
-#endif
+  iCode *uic;
+
+  D (D_ACCUSE2, ("packRegsForAccUse2: running on ic %p line %u\n", ic, ic->lineno));
+  if (D_ACCUSE2)
+    piCode (ic, NULL);
+
+  /* Filter out all but those 'good' commands */
+  if (
+       !POINTER_GET (ic) &&
+       ic->op != '+' &&
+       ic->op != '-' &&
+       !IS_BITWISE_OP (ic) &&
+       ic->op != '=' &&
+       ic->op != EQ_OP &&
+       ic->op != '<' &&
+       ic->op != '>' &&
+       ic->op != CAST &&
+       ic->op != GETHBIT &&
+       1)
+    {
+      D (D_ACCUSE2, ("  + Dropping as not a 'good' source command\n"));
+      return;
+    }
 
-    /* if the usage is not is an assignment or an 
-       arithmetic / bitwise / shift operation then not.
-       MLH: Pending:  Invalid.  Our pointer sets are always peechy.
- */
-#if 0
-    if (POINTER_SET(uic) && 
-       getSize(aggrToPtr(operandType(IC_RESULT(uic)),FALSE)) > 1) {
-       printf("e5 %u\n", getSize(aggrToPtr(operandType(IC_RESULT(uic)),FALSE)));
-       return;
+  /* if + or - then it has to be one byte result.
+     MLH: Ok.
+   */
+  if ((ic->op == '+' || ic->op == '-')
+      && getSize (operandType (IC_RESULT (ic))) > 1)
+    {
+      D (D_ACCUSE2, ("  + Dropping as it's a big + or -\n"));
+      return;
     }
-#endif
 
-    printf("1\n");
-    if (uic->op != '=' && 
-       !IS_ARITHMETIC_OP(uic) &&
-       !IS_BITWISE_OP(uic)    &&
-       uic->op != LEFT_OP &&
-       uic->op != RIGHT_OP ) {
-       printf("e6\n");
-       return;
-    }
-
-    /* if used in ^ operation then make sure right is not a 
-       literl */
-    if (uic->op == '^' && isOperandLiteral(IC_RIGHT(uic)))
-       return ;
-
-    /* if shift operation make sure right side is not a literal */
-    if (uic->op == RIGHT_OP  &&
-       ( isOperandLiteral(IC_RIGHT(uic)) ||
-         getSize(operandType(IC_RESULT(uic))) > 1))
-       return ;
-
-    if (uic->op == LEFT_OP &&        
-       ( isOperandLiteral(IC_RIGHT(uic)) ||
-         getSize(operandType(IC_RESULT(uic))) > 1))
-       return ;
-           
-#if 0
-    /* make sure that the result of this icode is not on the
-       stack, since acc is used to compute stack offset */
-    if (IS_TRUE_SYMOP(IC_RESULT(uic)) &&
-       OP_SYMBOL(IC_RESULT(uic))->onStack)
-       return ;
-#endif
+  /* has only one definition */
+  if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
+    {
+      D (D_ACCUSE2, ("  + Dropping as it has more than one definition\n"));
+      return;
+    }
 
-#if 0
-    /* if either one of them in far space then we cannot */
-    if ((IS_TRUE_SYMOP(IC_LEFT(uic)) &&
-        isOperandInFarSpace(IC_LEFT(uic))) ||
-       (IS_TRUE_SYMOP(IC_RIGHT(uic)) &&
-        isOperandInFarSpace(IC_RIGHT(uic))))
-       return ;
-#endif
+  /* Right.  We may be able to propagate it through if:
+     For each in the chain of uses the intermediate is OK.
+   */
+  /* Get next with 'uses result' bit on
+     If this->next == next
+     Validate use of next
+     If OK, increase count
+   */
+  /* and the usage immediately follows this iCode */
+  if (!(uic = hTabItemWithKey (iCodehTab,
+                              bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
+    {
+      D (D_ACCUSE2, ("  + Dropping as usage does not follow first\n"));
+      return;
+    }
 
-    /* if the usage has only one operand then we can */
-    if (IC_LEFT(uic) == NULL ||
-       IC_RIGHT(uic) == NULL) 
-       goto accuse;
-
-    /* make sure this is on the left side if not
-       a '+' since '+' is commutative */
-    if (ic->op != '+' &&
-       IC_LEFT(uic)->key != IC_RESULT(ic)->key)
-       return;
-
-    /* if one of them is a literal then we can */
-    if ((IC_LEFT(uic) && IS_OP_LITERAL(IC_LEFT(uic))) ||
-       (IC_RIGHT(uic) && IS_OP_LITERAL(IC_RIGHT(uic)))) {
-       OP_SYMBOL(IC_RESULT(ic))->accuse = 1;
-       return ;
-    }
-
-    /** This is confusing :)  Guess for now */
-    if (IC_LEFT(uic)->key == IC_RESULT(ic)->key &&
-       (IS_ITEMP(IC_RIGHT(uic)) ||
-        (IS_TRUE_SYMOP(IC_RIGHT(uic)))))
-       goto accuse;
-    
-    if (IC_RIGHT(uic)->key == IC_RESULT(ic)->key &&
-       (IS_ITEMP(IC_LEFT(uic)) ||
-        (IS_TRUE_SYMOP(IC_LEFT(uic)))))
-       goto accuse ;
-    return ;
- accuse:
-    printf("acc ok!\n");
-    OP_SYMBOL(IC_RESULT(ic))->accuse = 1;
+  {
+    /* Create a copy of the OP_USES bit vect */
+    bitVect *uses = bitVectCopy (OP_USES (IC_RESULT (ic)));
+    int setBit;
+    iCode *scan = ic, *next;
+
+    do
+      {
+       setBit = bitVectFirstBit (uses);
+       next = hTabItemWithKey (iCodehTab, setBit);
+       if (scan->next == next)
+         {
+            D (D_ACCUSE2_VERBOSE, ("  ! Is next in line\n"));
+
+           bitVectUnSetBit (uses, setBit);
+           /* Still contigous. */
+           if (!opPreservesA (next))
+             {
+                D (D_ACCUSE2, ("  + Dropping as operation doesn't preserve A\n"));
+               return;
+             }
+            D (D_ACCUSE2_VERBOSE, ("  ! Preserves A, so continue scanning\n"));
+           scan = next;
+         }
+        else if (scan->next == NULL && bitVectnBitsOn (uses) == 1 && next != NULL)
+          {
+            if (next->prev == NULL)
+              {
+                if (!opPreservesA (next))
+                  {
+                    D (D_ACCUSE2, ("  + Dropping as operation doesn't preserve A #2\n"));
+                    return;
+                  }
+                bitVectUnSetBit (uses, setBit);
+                scan = next;
+              }
+            else 
+              {
+                D (D_ACCUSE2, ("  + Dropping as last in list and next doesn't start a block\n"));
+                return;
+              }
+          }
+        else if (scan->next == NULL)
+          {
+            D (D_ACCUSE2, ("  + Dropping as hit the end of the list\n"));
+            D (D_ACCUSE2, ("  + Next in htab: %p\n", next));
+            return;
+          }
+       else
+         {
+            if (opIgnoresA (ic, scan->next))
+              {
+                /* Safe for now. */
+                scan = scan->next;
+                D (D_ACCUSE2_VERBOSE, ("  ! Op ignores A, so continue scanning\n"));
+              }
+            else
+              {
+                D (D_ACCUSE2, ("  + Dropping as parts are not consecuitive and intermediate might use A\n"));
+                return;
+              }
+         }
+      }
+    while (!bitVectIsZero (uses));
+
+    OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_A;
+    return;
+  }
 }
 
 /** Does some transformations to reduce register pressure.
  */
-static void packRegisters (eBBlock *ebp)
+static void 
+packRegisters (eBBlock * ebp)
 {
-    iCode *ic ;
-    int change = 0 ;
+  iCode *ic;
+  int change = 0;
 
-    D(D_ALLOC, ("packRegisters: entered.\n"));
-    
-    while (1 && !DISABLE_PACK_ASSIGN) {
-       change = 0;
-       /* look for assignments of the form */
-       /* iTempNN = TRueSym (someoperation) SomeOperand */
-       /*       ....                       */
-       /* TrueSym := iTempNN:1             */
-       for ( ic = ebp->sch ; ic ; ic = ic->next ) {
-           /* find assignment of the form TrueSym := iTempNN:1 */
-           if (ic->op == '=' && !POINTER_SET(ic))
-               change += packRegsForAssign(ic,ebp);
+  D (D_ALLOC, ("packRegisters: entered.\n"));
+
+  while (1 && !DISABLE_PACK_ASSIGN)
+    {
+      change = 0;
+      /* look for assignments of the form */
+      /* iTempNN = TRueSym (someoperation) SomeOperand */
+      /*       ....                       */
+      /* TrueSym := iTempNN:1             */
+      for (ic = ebp->sch; ic; ic = ic->next)
+       {
+         /* find assignment of the form TrueSym := iTempNN:1 */
+         if (ic->op == '=' && !POINTER_SET (ic))
+           change += packRegsForAssign (ic, ebp);
        }
-       if (!change)
-           break;
+      if (!change)
+       break;
     }
 
-    for ( ic = ebp->sch ; ic ; ic = ic->next ) {
-       /* Safe: address of a true sym is always constant. */
-       /* if this is an itemp & result of a address of a true sym 
-          then mark this as rematerialisable   */
-
-       D(D_ALLOC, ("packRegisters: looping on ic %zi\n", ic));
-    
-       if (ic->op == ADDRESS_OF && 
-           IS_ITEMP(IC_RESULT(ic)) &&
-           IS_TRUE_SYMOP(IC_LEFT(ic)) &&
-            bitVectnBitsOn(OP_DEFS(IC_RESULT(ic))) == 1 &&
-           !OP_SYMBOL(IC_LEFT(ic))->onStack ) {
-
-           OP_SYMBOL(IC_RESULT(ic))->remat = 1;
-           OP_SYMBOL(IC_RESULT(ic))->rematiCode = ic;
-           OP_SYMBOL(IC_RESULT(ic))->usl.spillLoc = NULL;
+  for (ic = ebp->sch; ic; ic = ic->next)
+    {
+      /* Safe: address of a true sym is always constant. */
+      /* if this is an itemp & result of a address of a true sym 
+         then mark this as rematerialisable   */
+      D (D_ALLOC, ("packRegisters: looping on ic %p\n", ic));
+
+      if (ic->op == ADDRESS_OF &&
+         IS_ITEMP (IC_RESULT (ic)) &&
+         IS_TRUE_SYMOP (IC_LEFT (ic)) &&
+         bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
+         !OP_SYMBOL (IC_LEFT (ic))->onStack)
+       {
+
+         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
        }
 
-       /* Safe: just propagates the remat flag */
-       /* if straight assignment then carry remat flag if this is the
-          only definition */
-       if (ic->op == '='    && 
-           !POINTER_SET(ic) &&
-           IS_SYMOP(IC_RIGHT(ic)) && 
-           OP_SYMBOL(IC_RIGHT(ic))->remat &&
-           bitVectnBitsOn(OP_SYMBOL(IC_RESULT(ic))->defs) <= 1) {
-
-           OP_SYMBOL(IC_RESULT(ic))->remat = 
-               OP_SYMBOL(IC_RIGHT(ic))->remat;
-           OP_SYMBOL(IC_RESULT(ic))->rematiCode = 
-               OP_SYMBOL(IC_RIGHT(ic))->rematiCode ;
+      /* Safe: just propagates the remat flag */
+      /* if straight assignment then carry remat flag if this is the
+         only definition */
+      if (ic->op == '=' &&
+         !POINTER_SET (ic) &&
+         IS_SYMOP (IC_RIGHT (ic)) &&
+         OP_SYMBOL (IC_RIGHT (ic))->remat &&
+         bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
+       {
+
+         OP_SYMBOL (IC_RESULT (ic))->remat =
+           OP_SYMBOL (IC_RIGHT (ic))->remat;
+         OP_SYMBOL (IC_RESULT (ic))->rematiCode =
+           OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
        }
 
-       /* if the condition of an if instruction is defined in the
-          previous instruction then mark the itemp as a conditional */
-       if ((IS_CONDITIONAL(ic) ||
-            ( ( ic->op == BITWISEAND      ||
-                ic->op == '|'             ||
-                ic->op == '^' ) &&
-              isBitwiseOptimizable(ic))) &&        
-           ic->next && ic->next->op == IFX &&
-           isOperandEqual(IC_RESULT(ic),IC_COND(ic->next)) &&
-           OP_SYMBOL(IC_RESULT(ic))->liveTo <= ic->next->seq) {
-           
-           OP_SYMBOL(IC_RESULT(ic))->regType = REG_CND;            
-           continue ;
+      /* if the condition of an if instruction is defined in the
+         previous instruction then mark the itemp as a conditional */
+      if ((IS_CONDITIONAL (ic) ||
+          ((ic->op == BITWISEAND ||
+            ic->op == '|' ||
+            ic->op == '^') &&
+           isBitwiseOptimizable (ic))) &&
+         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))->regType = REG_CND;
+         continue;
        }
 
 #if 0
-       /* reduce for support function calls */
-       if (ic->supportRtn || ic->op == '+' || ic->op == '-' )
-           packRegsForSupport(ic,ebp); 
+      /* reduce for support function calls */
+      if (ic->supportRtn || ic->op == '+' || ic->op == '-')
+       packRegsForSupport (ic, ebp);
 #endif
 
-#if 0
-       /* some cases the redundant moves can
-          can be eliminated for return statements */
-       if ((ic->op == RETURN || ic->op == SEND) &&
-           !isOperandInFarSpace(IC_LEFT(ic))    &&
-           !options.model)
-           packRegsForOneuse (ic,IC_LEFT(ic),ebp);     
-#endif
-       /* if pointer set & left has a size more than
-          one and right is not in far space */
-       if (POINTER_SET(ic)                    &&
-           /* MLH: no such thing.
-              !isOperandInFarSpace(IC_RIGHT(ic)) && */
-           !OP_SYMBOL(IC_RESULT(ic))->remat   &&
-           !IS_OP_RUONLY(IC_RIGHT(ic))        &&
-           getSize(aggrToPtr(operandType(IC_RESULT(ic)),FALSE)) > 1 )
-           
-           packRegsForOneuse (ic,IC_RESULT(ic),ebp);
-       
-       /* if pointer get */
-       if (POINTER_GET(ic)                    &&
-           /* MLH: dont have far space
-              !isOperandInFarSpace(IC_RESULT(ic))&& */
-           !OP_SYMBOL(IC_LEFT(ic))->remat     &&
-           !IS_OP_RUONLY(IC_RESULT(ic))         &&
-           getSize(aggrToPtr(operandType(IC_LEFT(ic)),FALSE)) > 1 )
-           packRegsForOneuse (ic,IC_LEFT(ic),ebp);
-       /* pack registers for accumulator use, when the result of an
-          arithmetic or bit wise operation has only one use, that use is
-          immediately following the defintion and the using iCode has
-          only one operand or has two operands but one is literal & the
-          result of that operation is not on stack then we can leave the
-          result of this operation in acc:b combination */
-#if 0
-       if ((IS_ARITHMETIC_OP(ic) 
-            || IS_BITWISE_OP(ic)
-            || ic->op == LEFT_OP || ic->op == RIGHT_OP
-            ) &&
-           IS_ITEMP(IC_RESULT(ic)) &&
-           getSize(operandType(IC_RESULT(ic))) <= 2)
-           packRegsForAccUse (ic);
-#else
-       if (!DISABLE_PACK_ACC && IS_ITEMP(IC_RESULT(ic)) &&
-           getSize(operandType(IC_RESULT(ic))) == 1)
-           packRegsForAccUse2(ic);
-#endif
+      /* some cases the redundant moves can
+         can be eliminated for return statements */
+      if (ic->op == RETURN || ic->op == SEND)
+        {
+         packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+       }
+
+      /* if pointer set & left has a size more than
+         one and right is not in far space */
+      if (!DISABLE_PACK_ONE_USE &&
+          POINTER_SET (ic) &&
+          /* MLH: no such thing.
+             !isOperandInFarSpace(IC_RIGHT(ic)) && */
+         !OP_SYMBOL (IC_RESULT (ic))->remat &&
+         !IS_OP_RUONLY (IC_RIGHT (ic)) &&
+         getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
+       {
+
+         packRegsForOneuse (ic, IC_RESULT (ic), ebp);
+       }
+
+      /* if pointer get */
+      if (!DISABLE_PACK_ONE_USE &&
+         POINTER_GET (ic) &&
+         IS_SYMOP (IC_LEFT (ic)) &&
+      /* MLH: dont have far space
+         !isOperandInFarSpace(IC_RESULT(ic))&& */
+         !OP_SYMBOL (IC_LEFT (ic))->remat &&
+         !IS_OP_RUONLY (IC_RESULT (ic)) &&
+         getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
+       {
+
+         packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+       }
+
+      /* pack registers for accumulator use, when the result of an
+         arithmetic or bit wise operation has only one use, that use is
+         immediately following the defintion and the using iCode has
+         only one operand or has two operands but one is literal & the
+         result of that operation is not on stack then we can leave the
+         result of this operation in acc:b combination */
+
+      if (!DISABLE_PACK_HL && IS_ITEMP (IC_RESULT (ic)))
+       {
+         /* PENDING */
+          if (IS_GB)
+           {
+             if (0)
+               packRegsForHLUse (ic);
+           }
+          else
+           {
+             packRegsForHLUse3 (ic, IC_RESULT (ic), ebp);
+           }
+       }
+
+      if (!DISABLE_PACK_IY && IS_ITEMP (IC_RESULT (ic)) && IS_Z80)
+       {
+          packRegsForIYUse (ic, IC_RESULT (ic), ebp);
+       }
+
+      if (!DISABLE_PACK_ACC && IS_ITEMP (IC_RESULT (ic)) &&
+         getSize (operandType (IC_RESULT (ic))) == 1)
+       {
+         packRegsForAccUse2 (ic);
+       }
     }
 }
-  
+
+/** Joins together two byte constant pushes into one word push.
+ */
+static iCode *
+joinPushes (iCode *lic)
+{
+  iCode *ic, *uic;
+
+  for (ic = lic; ic; ic = ic->next)
+    {
+      int first, second;
+      value *val;
+
+      uic = ic->next;
+
+      /* Anything past this? */
+      if (uic == NULL)
+        {
+          continue;
+        }
+      /* This and the next pushes? */
+      if (ic->op != IPUSH || uic->op != IPUSH)
+        {
+          continue;
+        }
+      /* Both literals? */
+      if ( !IS_OP_LITERAL (IC_LEFT (ic)) || !IS_OP_LITERAL (IC_LEFT (uic)))
+        {
+          continue;
+        }
+      /* Both characters? */
+      if ( getSize (operandType (IC_LEFT (ic))) != 1 || getSize (operandType (IC_LEFT (uic))) != 1)
+        {
+          continue;
+        }
+      /* Pull out the values, make a new type, and create the new iCode for it.
+       */
+      first = (int)operandLitValue ( IC_LEFT (ic));
+      second = (int)operandLitValue ( IC_LEFT (uic));
+
+      sprintf (buffer, "%uu", ((first << 8) | (second & 0xFF)) & 0xFFFFU);
+      val = constVal (buffer);
+      SPEC_NOUN (val->type) = V_INT;
+      IC_LEFT (ic) = operandFromOperand (IC_LEFT (ic));
+      IC_LEFT (ic)->operand.valOperand = val;
+      
+      /* Now remove the second one from the list. */
+      ic->next = uic->next;
+      if (uic->next)
+        {
+          /* Patch up the reverse link */
+          uic->next->prev = ic;
+        }
+    }
+
+  return lic;
+}
+
 /*-----------------------------------------------------------------*/
 /* assignRegisters - assigns registers to each live range as need  */
 /*-----------------------------------------------------------------*/
-void z80_assignRegisters (eBBlock **ebbs, int count)
+void 
+z80_assignRegisters (ebbIndex * ebbi)
 {
-    iCode *ic;
-    int i ;
+  eBBlock ** ebbs = ebbi->bbOrder;
+  int count = ebbi->count;
+  iCode *ic;
+  int i;
 
-    D(D_ALLOC, ("\n-> z80_assignRegisters: entered.\n"));
+  (D_ALLOC, ("\n-> z80_assignRegisters: entered.\n"));
 
-    setToNull((void *)&funcrUsed);
-    stackExtend = dataExtend = 0;
+  setToNull ((void *) &_G.funcrUsed);
+  setToNull ((void *) &_G.totRegAssigned);  
+  _G.stackExtend = _G.dataExtend = 0;
 
-    if (IS_GB) {
-       /* DE is required for the code gen. */
-       _nRegs = GBZ80_MAX_REGS;
-       regsZ80 = _gbz80_regs;
+  if (IS_GB)
+    {
+      /* DE is required for the code gen. */
+      _G.nRegs = GBZ80_MAX_REGS;
+      regsZ80 = _gbz80_regs;
     }
-    else {
-       _nRegs = Z80_MAX_REGS;
-       regsZ80 = _z80_regs;
+  else
+    {
+      _G.nRegs = Z80_MAX_REGS;
+      regsZ80 = _z80_regs;
     }
 
-    /* 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]);
 
-    if (options.dump_pack)
-       dumpEbbsToFileExt(".dumppack",ebbs,count);
+  /* liveranges probably changed by register packing
+     so we compute them again */
+  recomputeLiveRanges (ebbs, count);
 
-    /* first determine for each live range the number of 
-       registers & the type of registers required for each */
-    regTypeNum ();
-    
-    /* and serially allocate registers */ 
-    serialRegAssign(ebbs,count);
+  if (options.dump_pack)
+    dumpEbbsToFileExt (DUMP_PACK, ebbi);
+
+  /* first determine for each live range the number of 
+     registers & the type of registers required for each */
+  regTypeNum ();
+
+  /* and serially allocate registers */
+  serialRegAssign (ebbs, count);
+
+  freeAllRegs ();
+  fillGaps();
 
-    /* if stack was extended then tell the user */
-    if (stackExtend) {
-/*     werror(W_TOOMANY_SPILS,"stack", */
-/*            stackExtend,currFunc->name,""); */
-       stackExtend = 0 ;
+  /* if stack was extended then tell the user */
+  if (_G.stackExtend)
+    {
+/*      werror(W_TOOMANY_SPILS,"stack", */
+/*             _G.stackExtend,currFunc->name,""); */
+      _G.stackExtend = 0;
     }
 
-    if (dataExtend) {
-/*     werror(W_TOOMANY_SPILS,"data space", */
-/*            dataExtend,currFunc->name,""); */
-       dataExtend = 0 ;
+  if (_G.dataExtend)
+    {
+/*      werror(W_TOOMANY_SPILS,"data space", */
+/*             _G.dataExtend,currFunc->name,""); */
+      _G.dataExtend = 0;
     }
 
-    if (options.dump_rassgn)
-       dumpEbbsToFileExt(".dumprassgn",ebbs,count);
+  if (options.dump_rassgn) {
+    dumpEbbsToFileExt (DUMP_RASSGN, ebbi);
+    dumpLiveRanges (DUMP_LRANGE, liveRanges);
+  }
+
+  /* after that create the register mask
+     for each of the instruction */
+  createRegMask (ebbs, count);
 
-    /* after that create the register mask
-       for each of the instruction */
-    createRegMask (ebbs,count);
+  /* now get back the chain */
+  ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
 
-    /* now get back the chain */
-    ic = iCodeLabelOptimize(iCodeFromeBBlock (ebbs,count));
+  ic = joinPushes (ic);
 
-    /* redo that offsets for stacked automatic variables */
-    redoStackOffsets ();
+  /* redo that offsets for stacked automatic variables */
+  redoStackOffsets ();
 
-    genZ80Code(ic);
+  genZ80Code (ic);
 
-    /* free up any stackSpil locations allocated */   
-    applyToSet(stackSpil,deallocStackSpil);
-    slocNum = 0;
-    setToNull((void **)&stackSpil);
-    setToNull((void **)&spiltSet);
-    /* mark all registers as free */
-    freeAllRegs();
+  /* free up any stackSpil locations allocated */
+  applyToSet (_G.stackSpil, deallocStackSpil);
+  _G.slocNum = 0;
+  setToNull ((void *) &_G.stackSpil);
+  setToNull ((void *) &_G.spiltSet);
+  /* mark all registers as free */
+  freeAllRegs ();
 
-    return ;
+  return;
 }