* src/z80/ralloc.c (packRegsForAssign): ported some bug fixes from the
[fw/sdcc] / src / z80 / ralloc.c
index f6265e4639ef60838e72201dcd4a296b4400151b..076277902ed9216c408ae3adb6653b85e6b26e5a 100644 (file)
@@ -53,7 +53,8 @@ enum
     DISABLE_PACK_ACC = 0,
     DISABLE_PACK_ASSIGN = 0,
     DISABLE_PACK_ONE_USE = 0,
-    DISABLE_PACK_HL = 0,
+    DISABLE_PACK_HL = 1,
+    DISABLE_PACK_IY = 0
   };
 
 /* Flags to turn on debugging code.
@@ -66,7 +67,10 @@ enum
     D_ACCUSE2_VERBOSE = 0,
     D_HLUSE = 0,
     D_HLUSE2 = 0,
-    D_HLUSE2_VERBOSE = 0
+    D_HLUSE2_VERBOSE = 0,
+    D_FILL_GAPS = 0,
+    D_PACK_IY = 0,
+    D_PACK_HLUSE3 = 0
   };
 
 #if 1
@@ -86,6 +90,7 @@ 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 */
@@ -118,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
@@ -214,34 +220,14 @@ nfreeRegsType (int type)
   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 */
@@ -370,7 +356,7 @@ leastUsedLR (set * sset)
 
     }
 
-  setToNull ((void **) &sset);
+  setToNull ((void *) &sset);
   sym->blockSpil = 0;
   return sym;
 }
@@ -463,7 +449,9 @@ createStackSpil (symbol * sym)
   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);
 
@@ -512,10 +500,11 @@ spillThis (symbol * sym)
     }
 
   /* mark it has spilt & put it in the spilt set */
-  sym->isspilt = 1;
+  sym->isspilt = sym->spillA = 1;
   _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
 
   bitVectUnSetBit (_G.regAssigned, sym->key);
+  bitVectUnSetBit (_G.totRegAssigned, sym->key);
 
   for (i = 0; i < sym->nRegs; i++)
     {
@@ -528,7 +517,7 @@ spillThis (symbol * sym)
 
   if (sym->usl.spillLoc && !sym->remat)
     {
-      sym->usl.spillLoc->allocreq = 1;
+      sym->usl.spillLoc->allocreq++;
     }
   return;
 }
@@ -570,17 +559,6 @@ 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 */
 /*-----------------------------------------------------------------*/
@@ -623,7 +601,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;
     }
 
@@ -669,7 +647,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
@@ -679,7 +657,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;
     }
 
@@ -691,7 +669,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;
     }
 
@@ -718,12 +696,13 @@ spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
   ssym = selectSpil (ic, ebp, forSym);
 
   /* mark it as spilt */
-  ssym->isspilt = 1;
+  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++)
@@ -784,6 +763,7 @@ regs *
 getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
 {
   regs *reg;
+  int j;
 
   D (D_ALLOC, ("getRegGpr: on ic %p\n", ic));
 tryAgain:
@@ -800,12 +780,33 @@ tryAgain:
       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;
+
+  /* try for gpr type */
+  if ((reg = allocReg (REG_GPR)))
+    {
+      D (D_ALLOC, ("getRegGprNoSpil: got a reg.\n"));
+      return reg;
+    }
+  assert(0);
+
+  /* just to make the compiler happy */
+  return 0;
+}
+
 /** Symbol has a given register.
  */
 static bool 
@@ -885,6 +886,7 @@ deassignLRs (iCode * ic, eBBlock * ebp)
              (result = OP_SYMBOL (IC_RESULT (ic))) &&  /* has a result */
              result->liveTo > ic->seq &&       /* and will live beyond this */
              result->liveTo <= ebp->lSeq &&    /* does not go beyond this block */
+             result->liveFrom == ic->seq &&    /* does not start before here */
              result->regType == sym->regType &&        /* same register types */
              result->nRegs &&  /* which needs registers */
              !result->isspilt &&       /* and does not already have them */
@@ -914,6 +916,7 @@ deassignLRs (iCode * ic, eBBlock * ebp)
                }
 
              _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
+             _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, result->key);
            }
 
          /* free the remaining */
@@ -944,10 +947,11 @@ reassignLR (operand * op)
   D (D_ALLOC, ("reassingLR: on sym %p\n", sym));
 
   /* not spilt any more */
-  sym->isspilt = sym->blockSpil = sym->remainSpil = 0;
+  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);
 
   _G.blockSpil--;
 
@@ -973,17 +977,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 */
@@ -1004,8 +1009,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.
@@ -1040,6 +1047,31 @@ tryAllocatingRegPair (symbol * 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.
@@ -1075,7 +1107,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 */
@@ -1137,6 +1169,17 @@ serialRegAssign (eBBlock ** ebbs, int count)
 
                }
 
+             /* If the live range preceeds the point of definition 
+                then ideally we must take into account registers that 
+                have been allocated after sym->liveFrom but freed
+                before ic->seq. This is complicated, so spill this
+                symbol instead and let fillGaps handle the allocation. */
+             if (sym->liveFrom < ic->seq)
+               {
+                   spillThis (sym);
+                   continue;                 
+               }
+
              /* if it has a spillocation & is used less than
                 all other live ranges then spill this */
              if (willCS) {
@@ -1162,6 +1205,7 @@ serialRegAssign (eBBlock ** ebbs, int count)
 
              /* 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 */
@@ -1189,15 +1233,154 @@ 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)));
+
+           }
+       }
+    }
+
+    /* 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()
+{
+    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 ;
+
+           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();
     }
 }
 
@@ -1501,26 +1684,57 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
       if (SKIP_IC2 (dic))
        continue;
 
-      if (IS_SYMOP (IC_RESULT (dic)) &&
-         IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
-       {
-         break;
-       }
+      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_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_RESULT (dic)) &&
+             IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+           {
+             if (POINTER_SET (dic))
+               dic = NULL;
 
-      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;
+             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;
+           }
+           
        }
     }
 
@@ -1569,7 +1783,7 @@ pack:
   // 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);
+  OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
   return 1;
 }
 
@@ -1773,7 +1987,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;
@@ -2109,10 +2324,9 @@ packRegsForHLUse3 (iCode * lic, operand * op, eBBlock * ebp)
   iCode *ic, *dic;
   bool isFirst = TRUE;
 
-#if 0
-  printf("Checking:\n");
-  piCode(lic, NULL);
-#endif
+  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)
     {
@@ -2159,12 +2373,12 @@ packRegsForHLUse3 (iCode * lic, operand * op, eBBlock * ebp)
   dic = ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom);
 
   for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
-       ic = hTabNextItem(iCodeSeqhTab,&key)) 
+       ic = hTabNextItem(iCodeSeqhTab, &key)) 
     {
-#if 0
-      piCode(ic, NULL);
-      printf("(op: %u)\n", ic->op);
-#endif
+      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;
@@ -2172,6 +2386,8 @@ packRegsForHLUse3 (iCode * lic, operand * op, eBBlock * ebp)
             continue;
           if (POINTER_GET (ic))
             continue;
+          if (ic->op == '=' && !POINTER_SET(ic))
+            continue;
         }
 
       if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic))
@@ -2207,13 +2423,25 @@ packRegsForHLUse3 (iCode * lic, operand * op, eBBlock * ebp)
       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;
 
@@ -2228,11 +2456,9 @@ packRegsForHLUse3 (iCode * lic, operand * op, eBBlock * ebp)
       return NULL;
     }
 
-#if 0
-  printf("Succeeded!\n");
-#endif
-  OP_SYMBOL (op)->accuse = ACCUSE_SCRATCH;
+  D (D_PACK_HLUSE3, ("Succeeded!\n"))
 
+  OP_SYMBOL (op)->accuse = ACCUSE_SCRATCH;
   return dic;
 }
 
@@ -2244,10 +2470,9 @@ packRegsForIYUse (iCode * lic, operand * op, eBBlock * ebp)
   iCode *ic, *dic;
   bitVect *uses;
 
-#if 0
-  printf("Checking IY on %p lic key %u first def %u:\n", OP_SYMBOL(op), lic->key, bitVectFirstBit(OP_DEFS(op)));
-  piCode(lic, NULL);
-#endif
+  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)
     {
@@ -2290,6 +2515,12 @@ packRegsForIYUse (iCode * lic, operand * op, eBBlock * ebp)
       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.
@@ -2300,10 +2531,8 @@ packRegsForIYUse (iCode * lic, operand * op, eBBlock * ebp)
   for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
        ic = hTabNextItem(iCodeSeqhTab,&key)) 
     {
-#if 0
-      piCode(ic, NULL);
-      printf("(op: %u uses %u)\n", ic->op, bitVectBitValue(uses, ic->key));
-#endif
+      if (D_PACK_IY)
+        piCode(ic, NULL);
 
       if (ic->op == PCALL || 
           ic->op == CALL ||
@@ -2314,13 +2543,32 @@ packRegsForIYUse (iCode * lic, operand * op, eBBlock * ebp)
       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 == IFX)
-            return NULL;
-
           if (ic->op == '=' &&
               isOperandEqual(IC_RESULT(ic), op))
             continue;
@@ -2347,23 +2595,8 @@ packRegsForIYUse (iCode * lic, operand * op, eBBlock * ebp)
         }
       else
         {
-          if (ic->op == IFX)
-            continue;
-
           /* This iCode doesn't use the sym.  See if this iCode preserves IY.
            */
-          if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) && 
-              isOperandInDirSpace(IC_RESULT(ic)))
-            return NULL;
-          
-          if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) && 
-              isOperandInFarSpace(IC_RIGHT(ic)))
-            return NULL;
-
-          if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) && 
-              isOperandInFarSpace(IC_LEFT(ic)))
-            return NULL;
-          
           continue;
         }
 
@@ -2371,11 +2604,9 @@ packRegsForIYUse (iCode * lic, operand * op, eBBlock * ebp)
       return NULL;
     }
 
-#if 0
-  printf("Succeeded IY!\n");
-#endif
-  OP_SYMBOL (op)->accuse = ACCUSE_IY;
+  D (D_PACK_IY, ("Succeeded IY!\n"));
 
+  OP_SYMBOL (op)->accuse = ACCUSE_IY;
   return dic;
 }
 
@@ -2524,11 +2755,14 @@ packRegsForAccUse2 (iCode * ic)
   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 &&
@@ -2754,6 +2988,7 @@ packRegisters (eBBlock * 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 &&
@@ -2773,13 +3008,19 @@ packRegisters (eBBlock * ebp)
 
       if (!DISABLE_PACK_HL && IS_ITEMP (IC_RESULT (ic)))
        {
+         /* PENDING */
           if (IS_GB)
-            packRegsForHLUse (ic);
+           {
+             if (0)
+               packRegsForHLUse (ic);
+           }
           else
-            packRegsForHLUse3 (ic, IC_RESULT (ic), ebp);
+           {
+             packRegsForHLUse3 (ic, IC_RESULT (ic), ebp);
+           }
        }
 
-      if (!DISABLE_PACK_HL && IS_ITEMP (IC_RESULT (ic)) && IS_Z80)
+      if (!DISABLE_PACK_IY && IS_ITEMP (IC_RESULT (ic)) && IS_Z80)
        {
           packRegsForIYUse (ic, IC_RESULT (ic), ebp);
        }
@@ -2831,9 +3072,10 @@ joinPushes (iCode *lic)
       first = (int)operandLitValue ( IC_LEFT (ic));
       second = (int)operandLitValue ( IC_LEFT (uic));
 
-      sprintf (buffer, "%u", ((first << 8) | (second & 0xFF)) & 0xFFFFU);
+      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. */
@@ -2860,6 +3102,7 @@ z80_assignRegisters (eBBlock ** ebbs, int count)
   D (D_ALLOC, ("\n-> z80_assignRegisters: entered.\n"));
 
   setToNull ((void *) &_G.funcrUsed);
+  setToNull ((void *) &_G.totRegAssigned);  
   _G.stackExtend = _G.dataExtend = 0;
 
   if (IS_GB)
@@ -2879,6 +3122,10 @@ z80_assignRegisters (eBBlock ** ebbs, int count)
   for (i = 0; i < count; i++)
     packRegisters (ebbs[i]);
 
+  /* liveranges probably changed by register packing
+     so we compute them again */
+  recomputeLiveRanges (ebbs, count);
+
   if (options.dump_pack)
     dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
 
@@ -2889,6 +3136,9 @@ z80_assignRegisters (eBBlock ** ebbs, int count)
   /* and serially allocate registers */
   serialRegAssign (ebbs, count);
 
+  freeAllRegs ();
+  fillGaps();
+
   /* if stack was extended then tell the user */
   if (_G.stackExtend)
     {
@@ -2926,8 +3176,8 @@ z80_assignRegisters (eBBlock ** ebbs, int count)
   /* free up any stackSpil locations allocated */
   applyToSet (_G.stackSpil, deallocStackSpil);
   _G.slocNum = 0;
-  setToNull ((void **) &_G.stackSpil);
-  setToNull ((void **) &_G.spiltSet);
+  setToNull ((void *) &_G.stackSpil);
+  setToNull ((void *) &_G.spiltSet);
   /* mark all registers as free */
   freeAllRegs ();