* src/SDCCsymt.c (initCSupport): Removed managling of support function
[fw/sdcc] / src / z80 / ralloc.c
index a46ae56f197c034a89bbe03e6860fde654b3961d..6e97b1da76c1f751639d006f6ba5fd1a057b4007 100644 (file)
 */
 
 #include "z80.h"
+#include "SDCCicode.h"
 
+/* Flags to turn off optimisations.
+ */
 enum
   {
     DISABLE_PACK_ACC = 0,
     DISABLE_PACK_ASSIGN = 0,
     DISABLE_PACK_ONE_USE = 0,
     DISABLE_PACK_HL = 0,
-    LIMITED_PACK_ACC = 1,
+    DISABLE_PACK_IY = 0
   };
 
+/* Flags to turn on debugging code.
+ */
 enum
   {
     D_ALLOC = 0,
-    D_ALLOC2 = 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
@@ -66,28 +79,26 @@ enum
 #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
+/** 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[] =
 {
@@ -102,18 +113,6 @@ static regs _z80_regs[] =
   {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}
 };
 
@@ -124,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
@@ -136,15 +136,16 @@ allocReg (short type)
 {
   int i;
 
-  for (i = 0; i < _nRegs; 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);
+            {
+              currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, i);
+            }
          D (D_ALLOC, ("allocReg: alloced %p\n", &regsZ80[i]));
          return &regsZ80[i];
        }
@@ -160,12 +161,15 @@ regWithIdx (int idx)
 {
   int i;
 
-  for (i = 0; i < _nRegs; i++)
-    if (regsZ80[i].rIdx == idx)
-      return &regsZ80[i];
+  for (i = 0; i < _G.nRegs; i++)
+    {
+      if (regsZ80[i].rIdx == idx)
+        {
+          return &regsZ80[i];
+        }
+    }
 
-  werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-         "regWithIdx not found");
+  wassertl (0, "regWithIdx not found");
   exit (1);
 }
 
@@ -188,11 +192,13 @@ nFreeRegs (int type)
   int i;
   int nfr = 0;
 
-  for (i = 0; i < _nRegs; i++)
+  for (i = 0; i < _G.nRegs; i++)
     {
       /* For now only one reg type */
       if (regsZ80[i].isFree)
-       nfr++;
+        {
+          nfr++;
+        }
     }
   return nfr;
 }
@@ -206,12 +212,22 @@ nfreeRegsType (int type)
   if (type == REG_PTR)
     {
       if ((nfr = nFreeRegs (type)) == 0)
-       return nFreeRegs (REG_GPR);
+        {
+          return nFreeRegs (REG_GPR);
+        }
     }
 
   return nFreeRegs (type);
 }
 
+/*-----------------------------------------------------------------*/
+/* useReg - marks a register  as used                              */
+/*-----------------------------------------------------------------*/
+static void
+useReg (regs * reg)
+{
+  reg->isFree = 0;
+}
 
 #if 0
 /*-----------------------------------------------------------------*/
@@ -258,13 +274,13 @@ computeSpillable (iCode * ic)
 
   spillable = bitVectCopy (ic->rlive);
   spillable =
-    bitVectCplAnd (spillable, spiltSet);       /* those already spilt */
+    bitVectCplAnd (spillable, _G.spiltSet);    /* those already spilt */
   spillable =
     bitVectCplAnd (spillable, ic->uses);       /* used in this one */
   bitVectUnSetBit (spillable, ic->defKey);
-  spillable = bitVectIntersect (spillable, regAssigned);
-  return spillable;
+  spillable = bitVectIntersect (spillable, _G.regAssigned);
 
+  return spillable;
 }
 
 /*-----------------------------------------------------------------*/
@@ -305,10 +321,9 @@ allLRs (symbol * sym, eBBlock * ebp, iCode * ic)
   return 1;
 }
 
-/*-----------------------------------------------------------------*/
-/* liveRangesWith - applies function to a given set of live range  */
-/*-----------------------------------------------------------------*/
-set *
+/** liveRangesWith - applies function to a given set of live range 
+ */
+static set *
 liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
                eBBlock * ebp, iCode * ic)
 {
@@ -328,23 +343,23 @@ liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
          hash table we are in serious trouble */
       if (!(sym = hTabItemWithKey (liveRanges, i)))
        {
-         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-                 "liveRangesWith could not find liveRange");
+          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;
 }
 
 
-/*-----------------------------------------------------------------*/
-/* leastUsedLR - given a set determines which is the least used    */
-/*-----------------------------------------------------------------*/
-symbol *
+/** leastUsedLR - given a set determines which is the least used 
+ */
+static symbol *
 leastUsedLR (set * sset)
 {
   symbol *sym = NULL, *lsym = NULL;
@@ -374,9 +389,8 @@ leastUsedLR (set * sset)
   return sym;
 }
 
-/*-----------------------------------------------------------------*/
-/* noOverLap - will iterate through the list looking for over lap  */
-/*-----------------------------------------------------------------*/
+/** noOverLap - will iterate through the list looking for over lap
+ */
 static int 
 noOverLap (set * itmpStack, symbol * fsym)
 {
@@ -385,9 +399,18 @@ noOverLap (set * itmpStack, symbol * fsym)
   for (sym = setFirstItem (itmpStack); sym;
        sym = setNextItem (itmpStack))
     {
-      if (sym->liveTo > fsym->liveFrom)
-       return 0;
-
+      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;
 }
@@ -423,7 +446,7 @@ DEFSETFUNC (isFree)
 /*-----------------------------------------------------------------*/
 /* createStackSpil - create a location on the stack to spil        */
 /*-----------------------------------------------------------------*/
-symbol *
+static symbol *
 createStackSpil (symbol * sym)
 {
   symbol *sloc = NULL;
@@ -432,7 +455,7 @@ createStackSpil (symbol * sym)
 
   /* first go try and find a free one that is already 
      existing on the stack */
-  if (applyToSet (stackSpil, isFree, &sloc, sym))
+  if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
     {
       /* found a free one : just update & return */
       sym->usl.spillLoc = sloc;
@@ -447,21 +470,17 @@ createStackSpil (symbol * sym)
      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++);
+  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;
 
-  /* 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 */
@@ -470,13 +489,15 @@ createStackSpil (symbol * sym)
   if (IN_STACK (sloc->etype))
     {
       currFunc->stack += getSize (sloc->type);
-      stackExtend += getSize (sloc->type);
+      _G.stackExtend += getSize (sloc->type);
     }
   else
-    dataExtend += getSize (sloc->type);
+    {
+      _G.dataExtend += getSize (sloc->type);
+    }
 
   /* add it to the stackSpil set */
-  addSetHead (&stackSpil, sloc);
+  addSetHead (&_G.stackSpil, sloc);
   sym->usl.spillLoc = sloc;
   sym->stackSpil = 1;
 
@@ -488,33 +509,6 @@ createStackSpil (symbol * sym)
   return sym;
 }
 
-/*-----------------------------------------------------------------*/
-/* isSpiltOnStack - returns true if the spil location is on stack  */
-/*-----------------------------------------------------------------*/
-bool 
-isSpiltOnStack (symbol * sym)
-{
-  sym_link *etype;
-
-  if (!sym)
-    return FALSE;
-
-  if (!sym->isspilt)
-    return FALSE;
-
-/*     if (sym->stackSpil) */
-/*      return TRUE; */
-
-  if (!sym->usl.spillLoc)
-    return FALSE;
-
-  etype = getSpec (sym->usl.spillLoc->type);
-  if (IN_STACK (etype))
-    return TRUE;
-
-  return FALSE;
-}
-
 /*-----------------------------------------------------------------*/
 /* spillThis - spils a specific operand                            */
 /*-----------------------------------------------------------------*/
@@ -529,13 +523,16 @@ spillThis (symbol * sym)
      we are okay, else we need to create a spillLocation
      for it */
   if (!(sym->remat || sym->usl.spillLoc))
-    createStackSpil (sym);
+    {
+      createStackSpil (sym);
+    }
 
   /* mark it has spilt & put it in the spilt set */
-  sym->isspilt = 1;
-  spiltSet = bitVectSetBit (spiltSet, sym->key);
+  sym->isspilt = sym->spillA = 1;
+  _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
 
-  bitVectUnSetBit (regAssigned, sym->key);
+  bitVectUnSetBit (_G.regAssigned, sym->key);
+  bitVectUnSetBit (_G.totRegAssigned, sym->key);
 
   for (i = 0; i < sym->nRegs; i++)
     {
@@ -546,14 +543,72 @@ spillThis (symbol * sym)
        }
     }
 
-  /* 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;
+    {
+      sym->usl.spillLoc->allocreq++;
+    }
   return;
 }
 
+#if DISABLED
+/*-----------------------------------------------------------------*/
+/* allDefsOutOfRange - all definitions are out of a range          */
+/*-----------------------------------------------------------------*/
+static bool
+allDefsOutOfRange (bitVect * defs, int fseq, int toseq)
+{
+  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;
+}
+
+/*-----------------------------------------------------------------*/
+/* 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);
+}
+
+/*-----------------------------------------------------------------*/
+/* notUsedInBlock - not used in this block                         */
+/*-----------------------------------------------------------------*/
+static int
+notUsedInBlock (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return (!bitVectBitsInCommon (sym->defs, ebp->usesDefs) &&
+         allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
+/*     return (!bitVectBitsInCommon(sym->defs,ebp->usesDefs)); */
+}
+
+/*-----------------------------------------------------------------*/
+/* 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 *
@@ -585,7 +640,7 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
                           sym->usl.spillLoc->name));
       sym->spildir = 1;
       /* mark it as allocation required */
-      sym->usl.spillLoc->allocreq = 1;
+      sym->usl.spillLoc->allocreq++;
       return sym;
     }
 
@@ -595,13 +650,14 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
 
       /* 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)))
+      if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
        {
          sym = leastUsedLR (selectS);
          /* if this is not rematerializable */
          if (!sym->remat)
            {
-             blockSpil++;
+             _G.blockSpil++;
+              wassertl (0, "Attempted to do an unsupported block spill");
              sym->blockSpil = 1;
            }
          return sym;
@@ -609,15 +665,16 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
 
       /* check if there are any live ranges that not
          used in the remainder of the block */
-      if (!blockSpil && (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
+      if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
        {
          sym = leastUsedLR (selectS);
-         if (sym != ForSym)
+         if (sym != forSym)
            {
              if (!sym->remat)
                {
+                  wassertl (0, "Attempted to do an unsupported remain spill");
                  sym->remainSpil = 1;
-                 blockSpil++;
+                 _G.blockSpil++;
                }
              return sym;
            }
@@ -629,7 +686,7 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
 
       sym = leastUsedLR (selectS);
       /* mark this as allocation required */
-      sym->usl.spillLoc->allocreq = 1;
+      sym->usl.spillLoc->allocreq++;
       return sym;
     }
 #endif
@@ -639,7 +696,7 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
     {
       D (D_ALLOC, ("selectSpil: using with spill.\n"));
       sym = leastUsedLR (selectS);
-      sym->usl.spillLoc->allocreq = 1;
+      sym->usl.spillLoc->allocreq++;
       return sym;
     }
 
@@ -651,7 +708,7 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
       D (D_ALLOC, ("selectSpil: creating new spill.\n"));
       /* return a created spil location */
       sym = createStackSpil (leastUsedLR (selectS));
-      sym->usl.spillLoc->allocreq = 1;
+      sym->usl.spillLoc->allocreq++;
       return sym;
     }
 
@@ -678,17 +735,21 @@ spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
   ssym = selectSpil (ic, ebp, forSym);
 
   /* mark it as spilt */
-  ssym->isspilt = 1;
-  spiltSet = bitVectSetBit (spiltSet, ssym->key);
+  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 (regAssigned, ssym->key);
+  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 */
@@ -763,6 +824,19 @@ tryAgain:
   goto tryAgain;
 }
 
+static regs *getRegGprNoSpil()
+{
+  regs *reg;
+
+  /* try for gpr type */
+  if ((reg = allocReg (REG_GPR)))
+    {
+      D (D_ALLOC, ("getRegGprNoSpil: got a reg.\n"));
+      return reg;
+    }
+  assert(0);
+}
+
 /** Symbol has a given register.
  */
 static bool 
@@ -808,7 +882,7 @@ deassignLRs (iCode * ic, eBBlock * ebp)
          continue;
        }
 
-      if (!bitVectBitValue (regAssigned, sym->key))
+      if (!bitVectBitValue (_G.regAssigned, sym->key))
        continue;
 
       /* special case check if this is an IFX &
@@ -827,7 +901,7 @@ deassignLRs (iCode * ic, eBBlock * ebp)
        {
          int i = 0;
 
-         bitVectUnSetBit (regAssigned, sym->key);
+         bitVectUnSetBit (_G.regAssigned, sym->key);
 
          /* if the result of this one needs registers
             and does not have it then assign it right
@@ -846,7 +920,7 @@ deassignLRs (iCode * ic, eBBlock * ebp)
              result->nRegs &&  /* which needs registers */
              !result->isspilt &&       /* and does not already have them */
              !result->remat &&
-             !bitVectBitValue (regAssigned, result->key) &&
+             !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) +
@@ -870,7 +944,8 @@ deassignLRs (iCode * ic, eBBlock * ebp)
                    }
                }
 
-             regAssigned = bitVectSetBit (regAssigned, result->key);
+             _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
+             _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, result->key);
            }
 
          /* free the remaining */
@@ -901,12 +976,13 @@ reassignLR (operand * op)
   D (D_ALLOC, ("reassingLR: on sym %p\n", sym));
 
   /* not spilt any more */
-  sym->isspilt = sym->blockSpil = sym->remainSpil = 0;
-  bitVectUnSetBit (spiltSet, sym->key);
+  sym->isspilt = sym->spillA = sym->blockSpil = sym->remainSpil = 0;
+  bitVectUnSetBit (_G.spiltSet, sym->key);
 
-  regAssigned = bitVectSetBit (regAssigned, 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;
@@ -930,17 +1006,18 @@ willCauseSpill (int nr, int rt)
     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;
+  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;
+    return 0;
 again:
   shared = 0;
   /* first make sure that they actually share */
@@ -961,8 +1038,10 @@ xchgPositions:
       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.
@@ -972,7 +1051,7 @@ tryAllocatingRegPair (symbol * sym)
 {
   int i;
   wassert (sym->nRegs == 2);
-  for (i = 0; i < _nRegs; i += 2)
+  for (i = 0; i < _G.nRegs; i += 2)
     {
       if ((regsZ80[i].isFree) && (regsZ80[i + 1].isFree))
        {
@@ -980,6 +1059,8 @@ tryAllocatingRegPair (symbol * sym)
          sym->regs[0] = &regsZ80[i];
          regsZ80[i + 1].isFree = 0;
          sym->regs[1] = &regsZ80[i + 1];
+          sym->regType = REG_PAIR;
+
          if (currFunc)
            {
              currFunc->regsUsed =
@@ -1030,7 +1111,7 @@ serialRegAssign (eBBlock ** ebbs, int count)
          /* 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;
+           OP_SYMBOL (IC_RESULT (ic))->allocreq++;
 
          /* take away registers from live
             ranges that end at this instruction */
@@ -1060,7 +1141,7 @@ serialRegAssign (eBBlock ** ebbs, int count)
                 or will not live beyond this instructions */
              if (!sym->nRegs ||
                  sym->isspilt ||
-                 bitVectBitValue (regAssigned, sym->key) ||
+                 bitVectBitValue (_G.regAssigned, sym->key) ||
                  sym->liveTo <= ic->seq)
                {
                  D (D_ALLOC, ("serialRegAssign: wont live long enough.\n"));
@@ -1070,7 +1151,7 @@ serialRegAssign (eBBlock ** ebbs, int count)
              /* 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)
+             if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
                {
                  D (D_ALLOC, ("serialRegAssign: \"spilling to be safe.\"\n"));
                  spillThis (sym);
@@ -1106,14 +1187,18 @@ serialRegAssign (eBBlock ** ebbs, int count)
                              /* 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 */
-             regAssigned = bitVectSetBit (regAssigned, sym->key);
+             _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 */
@@ -1141,15 +1226,119 @@ serialRegAssign (eBBlock ** ebbs, int count)
              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);
+                             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)), ic->lineno);
+                             OP_SYMBOL (IC_RIGHT (ic)));
+
+           }
+       }
+    }
+}
 
+/*-----------------------------------------------------------------*/
+/* fillGaps - Try to fill in the Gaps left by Pass1                */
+/*-----------------------------------------------------------------*/
+static void fillGaps()
+{
+    symbol *sym =NULL;
+    int key =0;    
+    
+    if (getenv("DISABLE_FILL_GAPS")) return;
+    
+    /* 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 ;
+
+       /* 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;
+
+           if (bitVectBitValue(sym->clashes,i) == 0 ||    /* those that clash with this */
+               bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */
+               continue ;
+
+           assert (clr = hTabItemWithKey(liveRanges,i));
+        
+           /* 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();
     }
 }
 
@@ -1174,7 +1363,7 @@ rUmaskForOp (operand * op)
   if (sym->isspilt || !sym->nRegs)
     return NULL;
 
-  rumask = newBitVect (_nRegs);
+  rumask = newBitVect (_G.nRegs);
 
   for (j = 0; j < sym->nRegs; j++)
     {
@@ -1184,12 +1373,18 @@ rUmaskForOp (operand * op)
   return rumask;
 }
 
+bitVect *
+z80_rUmaskForOp (operand * op)
+{
+  return rUmaskForOp (op);
+}
+
 /** Returns bit vector of registers used in iCode.
  */
 bitVect *
 regsUsedIniCode (iCode * ic)
 {
-  bitVect *rmask = newBitVect (_nRegs);
+  bitVect *rmask = newBitVect (_G.nRegs);
 
   /* do the special cases first */
   if (ic->op == IFX)
@@ -1255,12 +1450,12 @@ createRegMask (eBBlock ** ebbs, int count)
          /* first mark the registers used in this
             instruction */
          ic->rUsed = regsUsedIniCode (ic);
-         funcrUsed = bitVectUnion (funcrUsed, ic->rUsed);
+         _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 (_nRegs + 1);
+         ic->rMask = newBitVect (_G.nRegs + 1);
 
          /* for all live Ranges alive at this point */
          for (j = 1; j < ic->rlive->size; j++)
@@ -1401,7 +1596,7 @@ freeAllRegs ()
 
   D (D_ALLOC, ("freeAllRegs: running.\n"));
 
-  for (i = 0; i < _nRegs; i++)
+  for (i = 0; i < _G.nRegs; i++)
     regsZ80[i].isFree = 1;
 }
 
@@ -1423,37 +1618,22 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
 {
   iCode *dic, *sic;
 
-  D (D_ALLOC, ("packRegsForAssing: running on ic %p\n", ic));
+  D (D_ALLOC, ("packRegsForAssign: running on ic %p\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;
-
-#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 (!IS_ITEMP (IC_RIGHT (ic)) ||
+      OP_SYMBOL (IC_RIGHT (ic))->isind ||
+      OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
     {
-      if ((dic = farSpacePackable (ic)))
-       goto pack;
-      else
-       return 0;
+      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))
+      /* PENDING: Don't pack across function calls. */
+      if (dic->op == CALL || dic->op == PCALL)
        {
          dic = NULL;
          break;
@@ -1483,14 +1663,6 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
          dic = NULL;
          break;
        }
-#if 0
-      if (POINTER_SET (dic) &&
-         IC_RESULT (dic)->key == IC_RESULT (ic)->key)
-       {
-         dic = NULL;
-         break;
-       }
-#endif
     }
 
   if (!dic)
@@ -1501,7 +1673,6 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
   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))) ||
@@ -1518,6 +1689,7 @@ pack:
   /* 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)
@@ -1535,6 +1707,10 @@ pack:
     }
 
   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;
 }
 
@@ -1613,6 +1789,9 @@ findAssignToSym (operand * op, iCode * ic)
 
 }
 
+#if !DISABLE_PACKREGSFORSUPPORT
+// PENDING
+
 /*-----------------------------------------------------------------*/
 /* packRegsForSupport :- reduce some registers for support calls   */
 /*-----------------------------------------------------------------*/
@@ -1643,6 +1822,9 @@ packRegsForSupport (iCode * ic, eBBlock * ebp)
        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++;
     }
 
@@ -1667,11 +1849,15 @@ right:
       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)
 
@@ -1683,6 +1869,7 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
   bitVect *uses;
   iCode *dic, *sic;
 
+  // PENDING: Disable
   D (D_ALLOC, ("packRegsForOneUse: running on ic %p\n", ic));
 
   /* if returning a literal then do nothing */
@@ -1691,8 +1878,10 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
 
   /* only upto 2 bytes since we cannot predict
      the usage of b, & acc */
-  if (getSize (operandType (op)) > 2 &&
-      ic->op != RETURN &&
+  if (getSize (operandType (op)) > 2)
+    return NULL;
+
+  if (ic->op != RETURN &&
       ic->op != SEND)
     return NULL;
 
@@ -1725,7 +1914,8 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
   /* 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)
+      if (ic->op != SEND && ic->op != RETURN &&
+         !POINTER_SET(ic) && !POINTER_GET(ic))
        {
          OP_SYMBOL (op)->ruonly = 1;
          return dic;
@@ -1826,6 +2016,9 @@ 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.
@@ -1835,6 +2028,11 @@ packRegsForAccUse (iCode * ic)
 {
   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)
@@ -1933,6 +2131,8 @@ packRegsForAccUse (iCode * ic)
       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))))
@@ -1940,6 +2140,7 @@ packRegsForAccUse (iCode * ic)
       goto accuse;
       return;
     }
+#endif
 
 /** This is confusing :)  Guess for now */
   if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
@@ -1955,182 +2156,567 @@ packRegsForAccUse (iCode * ic)
 accuse:
   OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_A;
 }
+#endif
 
 static void 
 packRegsForHLUse (iCode * ic)
 {
   iCode *uic;
 
-  if (IS_GB)
-    return;
+  /* PENDING: Could do IFX */
+  if (ic->op == IFX)
+    {
+      return;
+    }
 
   /* has only one definition */
   if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
-    return;
+    {
+      D (D_HLUSE, ("  + Dropping as has more than one def\n"));
+      return;
+    }
 
   /* has only one use */
   if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
-    return;
+    {
+      D (D_HLUSE, ("  + Dropping as has more than one use\n"));
+      return;
+    }
 
   /* and the usage immediately follows this iCode */
   if (!(uic = hTabItemWithKey (iCodehTab,
                               bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
-    return;
+    {
+      D (D_HLUSE, ("  + Dropping as usage isn't in this block\n"));
+      return;
+    }
 
   if (ic->next != uic)
-    return;
+    {
+      D (D_HLUSE, ("  + Dropping as usage doesn't follow this\n"));
+      return;
+    }
+
+  if (uic->op ==IFX)
+    {
+      return;
+    }
+
+  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 (ic->op == ADDRESS_OF && uic->op == IPUSH)
-    goto hluse;
-  if (ic->op == CALL && ic->parmBytes == 0 && (uic->op == '-' || uic->op == '+'))
-    goto hluse;
+  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_HL;
+  OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_SCRATCH;
 }
 
-bool 
-opPreservesA (iCode * ic, iCode * uic)
+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 it is a conditional branch then we definitely can */
   if (uic->op == IFX)
-    return FALSE;
+    {
+      /* 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)
-    return FALSE;
+    {
+      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)
-    return FALSE;
-
-  /* PENDING: check this rule */
-  if (getSize (operandType (IC_RESULT (uic))) > 1)
     {
+      D (D_ACCUSE2, ("  + Dropping as operation has only one operand\n"));
       return FALSE;
     }
 
-  /*
-     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
-    )
+  /* 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;
     }
 
-  /* PENDING */
-  if (!IC_LEFT (uic) || !IC_RESULT (ic))
-    return FALSE;
-
-/** 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;
 
+  /* Disabled all of the old rules as they weren't verified and have
+     caused at least one problem.
+   */
   return FALSE;
 }
 
-static void 
-joinPushes (iCode * ic)
+/** Returns true if this operand preserves the value of A.
+ */
+static bool
+opIgnoresA (iCode * ic, iCode * uic)
 {
-#if 0
-  if (ic->op == IPUSH &&
-      isOperandLiteral (IC_LEFT (ic)) &&
-      getSize (operandType (IC_LEFT (ic))) == 1 &&
-      ic->next->op == IPUSH &&
-      isOperandLiteral (IC_LEFT (ic->next)) &&
-      getSize (operandType (IC_LEFT (ic->next))) == 1)
-    {
-      /* This is a bit tricky as michaelh doesnt know what he's doing.
-       */
-      /* First upgrade the size of (first) to int */
-      SPEC_NOUN (operandType (IC_LEFT (ic))) = V_INT;
-      SPEC_SHORT (operandType (IC_LEFT (ic))) = 0;
-
-      floatFromVal (AOP /* need some sleep ... */ );
-      /* Now get and join the values */
-      value *val = aop->aopu.aop_lit;
-      /* if it is a float then it gets tricky */
-      /* otherwise it is fairly simple */
-      if (!IS_FLOAT (val->type))
-       {
-         unsigned long v = floatFromVal (val);
-
-         floatFrom ( /* need some sleep ... */ );
-         printf ("Size %u\n", getSize (operandType (IC_LEFT (ic))));
-         ic->next = ic->next->next;
-       }
+  /* 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;
+        }
     }
-#endif
+  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 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)
 {
   iCode *uic;
 
-  D (D_ALLOC, ("packRegsForAccUse2: running on ic %p\n", ic));
+  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)
-    return;
+    {
+      D (D_ACCUSE2, ("  + Dropping as not a 'good' source command\n"));
+      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
+    {
+      D (D_ACCUSE2, ("  + Dropping as it's a big + or -\n"));
+      return;
+    }
 
   /* 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;
     }
 
@@ -2146,6 +2732,7 @@ packRegsForAccUse2 (iCode * ic)
   if (!(uic = hTabItemWithKey (iCodehTab,
                               bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
     {
+      D (D_ACCUSE2, ("  + Dropping as usage does not follow first\n"));
       return;
     }
 
@@ -2161,127 +2748,62 @@ packRegsForAccUse2 (iCode * ic)
        next = hTabItemWithKey (iCodehTab, setBit);
        if (scan->next == next)
          {
+            D (D_ACCUSE2_VERBOSE, ("  ! Is next in line\n"));
+
            bitVectUnSetBit (uses, setBit);
            /* Still contigous. */
-           if (!opPreservesA (ic, next))
+           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
          {
-           return;
+            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;
   }
-
-  /* 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
-
-  /* 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;
-    }
-#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
-
-#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
-
-  /* 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))))
-    {
-      goto accuse;
-      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 = ACCUSE_A;
 }
 
 /** Does some transformations to reduce register pressure.
@@ -2354,6 +2876,7 @@ packRegisters (eBBlock * ebp)
             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)
        {
@@ -2368,19 +2891,19 @@ packRegisters (eBBlock * ebp)
        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 (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 (POINTER_SET (ic) &&
-      /* MLH: no such thing.
-         !isOperandInFarSpace(IC_RIGHT(ic)) && */
+      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)
@@ -2401,6 +2924,7 @@ packRegisters (eBBlock * ebp)
 
          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
@@ -2410,27 +2934,81 @@ packRegisters (eBBlock * ebp)
 
       if (!DISABLE_PACK_HL && IS_ITEMP (IC_RESULT (ic)))
        {
-         packRegsForHLUse (ic);
+          if (IS_GB)
+            packRegsForHLUse (ic);
+          else
+            packRegsForHLUse3 (ic, IC_RESULT (ic), ebp);
        }
-#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_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);
        }
-#endif
-      joinPushes (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, "%u", ((first << 8) | (second & 0xFF)) & 0xFFFFU);
+      val = constVal (buffer);
+      SPEC_NOUN (val->type) = V_INT;
+      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  */
 /*-----------------------------------------------------------------*/
@@ -2442,18 +3020,19 @@ z80_assignRegisters (eBBlock ** ebbs, int count)
 
   D (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;
+      _G.nRegs = GBZ80_MAX_REGS;
       regsZ80 = _gbz80_regs;
     }
   else
     {
-      _nRegs = Z80_MAX_REGS;
+      _G.nRegs = Z80_MAX_REGS;
       regsZ80 = _z80_regs;
     }
 
@@ -2463,7 +3042,7 @@ z80_assignRegisters (eBBlock ** ebbs, int count)
     packRegisters (ebbs[i]);
 
   if (options.dump_pack)
-    dumpEbbsToFileExt (".dumppack", ebbs, count);
+    dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
 
   /* first determine for each live range the number of 
      registers & the type of registers required for each */
@@ -2472,23 +3051,28 @@ z80_assignRegisters (eBBlock ** ebbs, int count)
   /* and serially allocate registers */
   serialRegAssign (ebbs, count);
 
+  freeAllRegs ();
+  fillGaps();
+
   /* if stack was extended then tell the user */
-  if (stackExtend)
+  if (_G.stackExtend)
     {
 /*      werror(W_TOOMANY_SPILS,"stack", */
-/*             stackExtend,currFunc->name,""); */
-      stackExtend = 0;
+/*             _G.stackExtend,currFunc->name,""); */
+      _G.stackExtend = 0;
     }
 
-  if (dataExtend)
+  if (_G.dataExtend)
     {
 /*      werror(W_TOOMANY_SPILS,"data space", */
-/*             dataExtend,currFunc->name,""); */
-      dataExtend = 0;
+/*             _G.dataExtend,currFunc->name,""); */
+      _G.dataExtend = 0;
     }
 
-  if (options.dump_rassgn)
-    dumpEbbsToFileExt (".dumprassgn", ebbs, count);
+  if (options.dump_rassgn) {
+    dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
+    dumpLiveRanges (DUMP_LRANGE, liveRanges);
+  }
 
   /* after that create the register mask
      for each of the instruction */
@@ -2497,16 +3081,18 @@ z80_assignRegisters (eBBlock ** ebbs, int count)
   /* now get back the chain */
   ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
 
+  ic = joinPushes (ic);
+
   /* redo that offsets for stacked automatic variables */
   redoStackOffsets ();
 
   genZ80Code (ic);
 
   /* free up any stackSpil locations allocated */
-  applyToSet (stackSpil, deallocStackSpil);
-  slocNum = 0;
-  setToNull ((void **) &stackSpil);
-  setToNull ((void **) &spiltSet);
+  applyToSet (_G.stackSpil, deallocStackSpil);
+  _G.slocNum = 0;
+  setToNull ((void **) &_G.stackSpil);
+  setToNull ((void **) &_G.spiltSet);
   /* mark all registers as free */
   freeAllRegs ();