* as/hc08/lkaomf51.c (OutputName),
[fw/sdcc] / src / ds390 / ralloc.c
index 55b2e22282412b9c398c52e94b8f1a4604e673a4..f69b12c2f29f1385bc897c1d74ed0f9ce0e7e009 100644 (file)
@@ -1,6 +1,6 @@
 /*------------------------------------------------------------------------
 
-  SDCCralloc.c - source file for register allocation. (8051) specific
+  SDCCralloc.c - source file for register allocation. (DS80C390) specific
 
                 Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
 
@@ -8,19 +8,19 @@
    under the terms of the GNU General Public License as published by the
    Free Software Foundation; either version 2, or (at your option) any
    later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-   
+
    In other words, you are welcome to use, share and improve this program.
    You are forbidden to forbid anyone else to use, share and improve
-   what you give them.   Help stamp out software-hoarding!  
+   what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 
 #include "common.h"
 /* since the pack the registers depending strictly on the MCU      */
 /*-----------------------------------------------------------------*/
 
+#define D(x)
+
 /* Global data */
 static struct
   {
     bitVect *spiltSet;
     set *stackSpil;
     bitVect *regAssigned;
+    bitVect *totRegAssigned;    /* final set of LRs that got into registers */
     short blockSpil;
     int slocNum;
-    bitVect *funcrUsed;                /* registers used in a function */
+    bitVect *funcrUsed;         /* registers used in a function */
     int stackExtend;
     int dataExtend;
+    bitVect *allBitregs;        /* all bit registers */
   }
 _G;
 
 /* Shared with gen.c */
-int ds390_ptrRegReq;           /* one byte pointer register required */
+int ds390_ptrRegReq;            /* one byte pointer register required */
 
 /* 8051 registers */
 regs regs390[] =
 {
 
-  {REG_GPR, R2_IDX, REG_GPR, "r2", "ar2", "0", 2, 1},
-  {REG_GPR, R3_IDX, REG_GPR, "r3", "ar3", "0", 3, 1},
-  {REG_GPR, R4_IDX, REG_GPR, "r4", "ar4", "0", 4, 1},
-  {REG_GPR, R5_IDX, REG_GPR, "r5", "ar5", "0", 5, 1},
-  {REG_GPR, R6_IDX, REG_GPR, "r6", "ar6", "0", 6, 1},
-  {REG_GPR, R7_IDX, REG_GPR, "r7", "ar7", "0", 7, 1},
-  {REG_PTR, R0_IDX, REG_PTR, "r0", "ar0", "0", 0, 1},
-  {REG_PTR, R1_IDX, REG_PTR, "r1", "ar1", "0", 1, 1},
-  {REG_GPR, X8_IDX, REG_GPR, "x8", "x8", "xreg", 0, 1},
-  {REG_GPR, X9_IDX, REG_GPR, "x9", "x9", "xreg", 1, 1},
-  {REG_GPR, X10_IDX, REG_GPR, "x10", "x10", "xreg", 2, 1},
-  {REG_GPR, X11_IDX, REG_GPR, "x11", "x11", "xreg", 3, 1},
-  {REG_GPR, X12_IDX, REG_GPR, "x12", "x12", "xreg", 4, 1},
-  {REG_CND, CND_IDX, REG_CND, "C", "C", "xreg", 0, 1},
+  {REG_GPR, R2_IDX, REG_GPR, "r2", "ar2", "0", 2, 1, 1},
+  {REG_GPR, R3_IDX, REG_GPR, "r3", "ar3", "0", 3, 1, 1},
+  {REG_GPR, R4_IDX, REG_GPR, "r4", "ar4", "0", 4, 1, 1},
+  {REG_GPR, R5_IDX, REG_GPR, "r5", "ar5", "0", 5, 1, 1},
+  {REG_GPR, R6_IDX, REG_GPR, "r6", "ar6", "0", 6, 1, 1},
+  {REG_GPR, R7_IDX, REG_GPR, "r7", "ar7", "0", 7, 1, 1},
+  {REG_PTR, R0_IDX, REG_PTR, "r0", "ar0", "0", 0, 1, 1},
+  {REG_PTR, R1_IDX, REG_PTR, "r1", "ar1", "0", 1, 1, 1},
+  {REG_GPR, DPL_IDX, REG_GPR, "dpl", "dpl", "dpl", 0, 0, 0},
+  {REG_GPR, DPH_IDX, REG_GPR, "dph", "dph", "dph", 0, 0, 0},
+  {REG_GPR, DPX_IDX, REG_GPR, "dpx", "dpx", "dpx", 0, 0, 0},
+  {REG_GPR, B_IDX, REG_GPR, "b", "b", "b", 0, 0, 0},
+  {REG_BIT, B0_IDX,  REG_BIT, "b0",   "b0",   "bits", 0, 1, 0},
+  {REG_BIT, B1_IDX,  REG_BIT, "b1",   "b1",   "bits", 1, 1, 0},
+  {REG_BIT, B2_IDX,  REG_BIT, "b2",   "b2",   "bits", 2, 1, 0},
+  {REG_BIT, B3_IDX,  REG_BIT, "b3",   "b3",   "bits", 3, 1, 0},
+  {REG_BIT, B4_IDX,  REG_BIT, "b4",   "b4",   "bits", 4, 1, 0},
+  {REG_BIT, B5_IDX,  REG_BIT, "b5",   "b5",   "bits", 5, 1, 0},
+  {REG_BIT, B6_IDX,  REG_BIT, "b6",   "b6",   "bits", 6, 1, 0},
+  {REG_BIT, B7_IDX,  REG_BIT, "b7",   "b7",   "bits", 7, 1, 0},
+  {REG_GPR, X8_IDX, REG_GPR, "x8", "x8", "xreg", 0, 0, 0},
+  {REG_GPR, X9_IDX, REG_GPR, "x9", "x9", "xreg", 1, 0, 0},
+  {REG_GPR, X10_IDX, REG_GPR, "x10", "x10", "xreg", 2, 0, 0},
+  {REG_GPR, X11_IDX, REG_GPR, "x11", "x11", "xreg", 3, 0, 0},
+  {REG_GPR, X12_IDX, REG_GPR, "x12", "x12", "xreg", 4, 0, 0},
+  {REG_CND, CND_IDX, REG_GPR, "C", "psw", "xreg", 0, 0, 0},
+  {0, DPL1_IDX, 0, "dpl1", "dpl1", "dpl1", 0, 0, 0},
+  {0, DPH1_IDX, 0, "dph1", "dph1", "dph1", 0, 0, 0},
+  {0, DPX1_IDX, 0, "dpx1", "dpx1", "dpx1", 0, 0, 0},
+  {0, DPS_IDX, 0, "dps", "dps", "dps", 0, 0, 0},
+  {0, A_IDX, 0, "a", "acc", "acc", 0, 0, 0},
+  {0, AP_IDX, 0, "ap", "ap", "ap", 0, 0, 0},
 };
+
 int ds390_nRegs = 13;
+int ds390_nBitRegs = 0;
+
 static void spillThis (symbol *);
+static void freeAllRegs ();
+static iCode * packRegsDPTRuse (operand *);
+static int packRegsDPTRnuse (operand *,unsigned);
 
 /*-----------------------------------------------------------------*/
 /* allocReg - allocates register of given type                     */
@@ -89,43 +117,41 @@ allocReg (short type)
       /* if type is given as 0 then any
          free register will do */
       if (!type &&
-         regs390[i].isFree)
-       {
-         regs390[i].isFree = 0;
-         if (currFunc)
-           currFunc->regsUsed =
-             bitVectSetBit (currFunc->regsUsed, i);
-         return &regs390[i];
-       }
-      /* other wise look for specific type
+          regs390[i].isFree)
+        {
+          regs390[i].isFree = 0;
+          if (currFunc)
+            currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, i);
+          return &regs390[i];
+        }
+      /* otherwise look for specific type
          of register */
       if (regs390[i].isFree &&
-         regs390[i].type == type)
-       {
-         regs390[i].isFree = 0;
-         if (currFunc)
-           currFunc->regsUsed =
-             bitVectSetBit (currFunc->regsUsed, i);
-         return &regs390[i];
-       }
+          regs390[i].type == type)
+        {
+          regs390[i].isFree = 0;
+          if (currFunc)
+            currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, i);
+          return &regs390[i];
+        }
     }
   return NULL;
 }
 
 /*-----------------------------------------------------------------*/
-/* ds390_regWithIdx - returns pointer to register wit index number       */
+/* ds390_regWithIdx - returns pointer to register with index number*/
 /*-----------------------------------------------------------------*/
 regs *
 ds390_regWithIdx (int idx)
 {
   int i;
 
-  for (i = 0; i < ds390_nRegs; i++)
+  for (i = 0; i < sizeof(regs390)/sizeof(regs); i++)
     if (regs390[i].rIdx == idx)
       return &regs390[i];
 
   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-         "regWithIdx not found");
+          "regWithIdx not found");
   exit (1);
 }
 
@@ -135,9 +161,24 @@ ds390_regWithIdx (int idx)
 static void
 freeReg (regs * reg)
 {
+  if (!reg)
+    {
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+              "freeReg - Freeing NULL register");
+      exit (1);
+    }
+
   reg->isFree = 1;
 }
 
+/*-----------------------------------------------------------------*/
+/* useReg - marks a register  as used                              */
+/*-----------------------------------------------------------------*/
+static void
+useReg (regs * reg)
+{
+  reg->isFree = 0;
+}
 
 /*-----------------------------------------------------------------*/
 /* nFreeRegs - returns number of free registers                    */
@@ -164,37 +205,22 @@ nfreeRegsType (int type)
   if (type == REG_PTR)
     {
       if ((nfr = nFreeRegs (type)) == 0)
-       return nFreeRegs (REG_GPR);
+        return nFreeRegs (REG_GPR);
     }
 
   return nFreeRegs (type);
 }
 
-
 /*-----------------------------------------------------------------*/
-/* allDefsOutOfRange - all definitions are out of a range          */
+/* isOperandInReg - returns true if operand is currently in regs   */
 /*-----------------------------------------------------------------*/
-static bool
-allDefsOutOfRange (bitVect * defs, int fseq, int toseq)
+static int isOperandInReg(operand *op)
 {
-  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;
+    if (!IS_SYMOP(op)) return 0;
+    if (OP_SYMBOL(op)->ruonly) return 1;
+    if (OP_SYMBOL(op)->accuse) return 1;
+    if (OP_SYMBOL(op)->dptr) return 1;
+    return bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(op)->key);
 }
 
 /*-----------------------------------------------------------------*/
@@ -205,24 +231,33 @@ computeSpillable (iCode * ic)
 {
   bitVect *spillable;
 
-  /* spillable live ranges are those that are live at this 
+  /* spillable live ranges are those that are live at this
      point . the following categories need to be subtracted
-     from this set. 
+     from this set.
      a) - those that are already spilt
      b) - if being used by this one
      c) - defined by this one */
 
   spillable = bitVectCopy (ic->rlive);
   spillable =
-    bitVectCplAnd (spillable, _G.spiltSet);    /* those already spilt */
+    bitVectCplAnd (spillable, _G.spiltSet);     /* those already spilt */
   spillable =
-    bitVectCplAnd (spillable, ic->uses);       /* used in this one */
+    bitVectCplAnd (spillable, ic->uses);        /* used in this one */
   bitVectUnSetBit (spillable, ic->defKey);
   spillable = bitVectIntersect (spillable, _G.regAssigned);
   return spillable;
 
 }
 
+/*-----------------------------------------------------------------*/
+/* bitType - will return 1 if the symbol has type REG_BIT          */
+/*-----------------------------------------------------------------*/
+static int
+bitType (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return (sym->regType == REG_BIT ? 1 : 0);
+}
+
 /*-----------------------------------------------------------------*/
 /* noSpilLoc - return true if a variable has no spil location      */
 /*-----------------------------------------------------------------*/
@@ -242,7 +277,7 @@ hasSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
 }
 
 /*-----------------------------------------------------------------*/
-/* directSpilLoc - will return 1 if the splilocation is in direct  */
+/* directSpilLoc - will return 1 if the spillocation is in direct  */
 /*-----------------------------------------------------------------*/
 static int
 directSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
@@ -273,17 +308,6 @@ rematable (symbol * sym, eBBlock * ebp, iCode * ic)
   return sym->remat;
 }
 
-/*-----------------------------------------------------------------*/
-/* 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 */
 /*-----------------------------------------------------------------*/
@@ -291,7 +315,7 @@ static int
 notUsedInRemaining (symbol * sym, eBBlock * ebp, iCode * ic)
 {
   return ((usedInRemaining (operandFromSymbol (sym), ic) ? 0 : 1) &&
-         allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
+          allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
 }
 
 /*-----------------------------------------------------------------*/
@@ -308,7 +332,7 @@ allLRs (symbol * sym, eBBlock * ebp, iCode * ic)
 /*-----------------------------------------------------------------*/
 static set *
 liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
-               eBBlock * ebp, iCode * ic)
+                eBBlock * ebp, iCode * ic)
 {
   set *rset = NULL;
   int i;
@@ -320,19 +344,19 @@ liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
     {
       symbol *sym;
       if (!bitVectBitValue (lrs, i))
-       continue;
+        continue;
 
-      /* if we don't find it in the live range 
+      /* if we don't find it in the live range
          hash table we are in serious trouble */
       if (!(sym = hTabItemWithKey (liveRanges, i)))
-       {
-         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-                 "liveRangesWith could not find liveRange");
-         exit (1);
-       }
+        {
+          werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                  "liveRangesWith could not find liveRange");
+          exit (1);
+        }
 
       if (func (sym, ebp, ic) && bitVectBitValue (_G.regAssigned, sym->key))
-       addSetHead (&rset, sym);
+        addSetHead (&rset, sym);
     }
 
   return rset;
@@ -356,18 +380,18 @@ leastUsedLR (set * sset)
     {
 
       /* if usage is the same then prefer
-         the spill the smaller of the two */
+         to spill the smaller of the two */
       if (lsym->used == sym->used)
-       if (getSize (lsym->type) < getSize (sym->type))
-         sym = lsym;
+        if (getSize (lsym->type) < getSize (sym->type))
+          sym = lsym;
 
       /* if less usage */
       if (lsym->used < sym->used)
-       sym = lsym;
+        sym = lsym;
 
     }
 
-  setToNull ((void **) &sset);
+  setToNull ((void *) &sset);
   sym->blockSpil = 0;
   return sym;
 }
@@ -380,15 +404,11 @@ noOverLap (set * itmpStack, symbol * fsym)
 {
   symbol *sym;
 
-
   for (sym = setFirstItem (itmpStack); sym;
        sym = setNextItem (itmpStack))
     {
-      if (sym->liveTo > fsym->liveFrom)
-       return 0;
-
+        if (bitVectBitValue(sym->clashes,fsym->key)) return 0;
     }
-
   return 1;
 }
 
@@ -444,24 +464,23 @@ spillLRWithPtrReg (symbol * forSym)
     {
       int j;
 
-      /* if no registers assigned to it or
-         spilt */
-      /* if it does not overlap with this then 
-         not need to spill it */
+      /* if no registers assigned to it or spilt */
+      /* if it does not overlap this then
+         no need to spill it */
 
       if (lrsym->isspilt || !lrsym->nRegs ||
-         (lrsym->liveTo < forSym->liveFrom))
-       continue;
+          (lrsym->liveTo < forSym->liveFrom))
+        continue;
 
       /* go thru the registers : if it is either
-         r0 or r1 then spil it */
+         r0 or r1 then spill it */
       for (j = 0; j < lrsym->nRegs; j++)
-       if (lrsym->regs[j] == r0 ||
-           lrsym->regs[j] == r1)
-         {
-           spillThis (lrsym);
-           break;
-         }
+        if (lrsym->regs[j] == r0 ||
+            lrsym->regs[j] == r1)
+          {
+            spillThis (lrsym);
+            break;
+          }
     }
 
 }
@@ -477,7 +496,7 @@ createStackSpil (symbol * sym)
 
   char slocBuffer[30];
 
-  /* first go try and find a free one that is already 
+  /* first go try and find a free one that is already
      existing on the stack */
   if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
     {
@@ -493,10 +512,11 @@ 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 */
 
-  if (sprintf (slocBuffer, "sloc%d", _G.slocNum++) >= sizeof (slocBuffer))
+  if (SNPRINTF (slocBuffer, sizeof(slocBuffer),
+                "sloc%d", _G.slocNum++) >= sizeof (slocBuffer))
     {
       fprintf (stderr, "***Internal error: slocBuffer overflowed: %s:%d\n",
-              __FILE__, __LINE__);
+               __FILE__, __LINE__);
       exit (1);
     }
 
@@ -505,15 +525,28 @@ createStackSpil (symbol * sym)
   /* set the type to the spilling symbol */
   sloc->type = copyLinkChain (sym->type);
   sloc->etype = getSpec (sloc->type);
-  SPEC_SCLS (sloc->etype) = options.model ? S_XDATA : S_DATA;
+  if (!IS_BIT (sloc->etype))
+    {
+      if (options.model == MODEL_SMALL)
+        {
+          SPEC_SCLS (sloc->etype) = S_DATA;
+        }
+      else
+        {
+          SPEC_SCLS (sloc->etype) = S_XDATA;
+        }
+    }
   SPEC_EXTR (sloc->etype) = 0;
+  SPEC_STAT (sloc->etype) = 0;
+  SPEC_VOLATILE(sloc->etype) = 0;
+  SPEC_ABSA(sloc->etype) = 0;
 
-  /* we don't allow it to be allocated`
+  /* 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 
+     and turn off overlaying
    */
 
   useXstack = options.useXstack;
@@ -528,7 +561,7 @@ createStackSpil (symbol * sym)
   options.useXstack = useXstack;
   options.model = model;
   options.noOverlay = noOverlay;
-  sloc->isref = 1;             /* to prevent compiler warning */
+  sloc->isref = 1;              /* to prevent compiler warning */
 
   /* if it is on the stack then update the stack */
   if (IN_STACK (sloc->etype))
@@ -544,7 +577,7 @@ createStackSpil (symbol * sym)
   sym->usl.spillLoc = sloc;
   sym->stackSpil = 1;
 
-  /* add it to the set of itempStack set 
+  /* add it to the set of itempStack set
      of the spill location */
   addSetHead (&sloc->usl.itmpStack, sym);
   return sym;
@@ -590,32 +623,32 @@ spillThis (symbol * sym)
   if (!(sym->remat || sym->usl.spillLoc))
     createStackSpil (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++)
 
     if (sym->regs[i])
       {
-       freeReg (sym->regs[i]);
-       sym->regs[i] = NULL;
+        freeReg (sym->regs[i]);
+        sym->regs[i] = NULL;
       }
 
-  /* if spilt on stack then free up r0 & r1 
+  /* if spilt on stack then free up r0 & r1
      if they could have been assigned to some
      LIVE ranges */
-  if (!ds390_ptrRegReq && isSpiltOnStack (sym))
+  if (!ds390_ptrRegReq && isSpiltOnStack (sym) && !options.stack10bit)
     {
-      ds390_ptrRegReq++;
+      ds390_ptrRegReq ++;
       spillLRWithPtrReg (sym);
     }
 
   if (sym->usl.spillLoc && !sym->remat)
-    sym->usl.spillLoc->allocreq = 1;
+    sym->usl.spillLoc->allocreq++;
   return;
 }
 
@@ -632,10 +665,20 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
   /* get the spillable live ranges */
   lrcs = computeSpillable (ic);
 
-  /* get all live ranges that are rematerizable */
-  if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
+  /* remove incompatible registers */
+  if ((forSym->regType == REG_PTR) || (forSym->regType == REG_GPR))
     {
+      selectS = liveRangesWith (lrcs, bitType, ebp, ic);
 
+      for (sym = setFirstItem (selectS); sym; sym = setNextItem (selectS))
+        {
+          bitVectUnSetBit (lrcs, sym->key);
+        }
+    }
+
+  /* get all live ranges that are rematerializable */
+  if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
+    {
       /* return the least used of these */
       return leastUsedLR (selectS);
     }
@@ -644,66 +687,66 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
   if ((selectS = liveRangesWith (lrcs, directSpilLoc, ebp, ic)))
     {
       sym = leastUsedLR (selectS);
-      strcpy (sym->rname, (sym->usl.spillLoc->rname[0] ?
-                          sym->usl.spillLoc->rname :
-                          sym->usl.spillLoc->name));
+      strncpyz (sym->rname,
+                sym->usl.spillLoc->rname[0] ?
+                   sym->usl.spillLoc->rname : sym->usl.spillLoc->name,
+                sizeof(sym->rname));
       sym->spildir = 1;
       /* mark it as allocation required */
-      sym->usl.spillLoc->allocreq = 1;
+      sym->usl.spillLoc->allocreq++;
       return sym;
     }
 
   /* if the symbol is local to the block then */
   if (forSym->liveTo < ebp->lSeq)
     {
-
       /* check if there are any live ranges allocated
          to registers that are not used in this block */
       if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
-       {
-         sym = leastUsedLR (selectS);
-         /* if this is not rematerializable */
-         if (!sym->remat)
-           {
-             _G.blockSpil++;
-             sym->blockSpil = 1;
-           }
-         return sym;
-       }
+        {
+          sym = leastUsedLR (selectS);
+          /* if this is not rematerializable */
+          if (!sym->remat)
+            {
+              _G.blockSpil++;
+              sym->blockSpil = 1;
+            }
+          return sym;
+        }
 
       /* check if there are any live ranges that not
          used in the remainder of the block */
-      if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
-       {
-         sym = leastUsedLR (selectS);
-         if (sym != forSym)
-           {
-             if (!sym->remat)
-               {
-                 sym->remainSpil = 1;
-                 _G.blockSpil++;
-               }
-             return sym;
-           }
-       }
+      if (!_G.blockSpil &&
+          !isiCodeInFunctionCall (ic) &&       
+          (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
+        {
+          sym = leastUsedLR (selectS);
+          if (sym != forSym)
+            {
+              if (!sym->remat)
+                {
+                  sym->remainSpil = 1;
+                  _G.blockSpil++;
+                }
+              return sym;
+            }
+        }
     }
 
   /* find live ranges with spillocation && not used as pointers */
   if ((selectS = liveRangesWith (lrcs, hasSpilLocnoUptr, ebp, ic)))
     {
-
       sym = leastUsedLR (selectS);
       /* mark this as allocation required */
-      sym->usl.spillLoc->allocreq = 1;
+      sym->usl.spillLoc->allocreq++;
       return sym;
     }
 
   /* find live ranges with spillocation */
   if ((selectS = liveRangesWith (lrcs, hasSpilLoc, ebp, ic)))
     {
-
       sym = leastUsedLR (selectS);
-      sym->usl.spillLoc->allocreq = 1;
+      sym->usl.spillLoc->allocreq++;
       return sym;
     }
 
@@ -712,10 +755,9 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
      used ofcourse */
   if ((selectS = liveRangesWith (lrcs, noSpilLoc, ebp, ic)))
     {
-
       /* return a created spil location */
       sym = createStackSpil (leastUsedLR (selectS));
-      sym->usl.spillLoc->allocreq = 1;
+      sym->usl.spillLoc->allocreq++;
       return sym;
     }
 
@@ -739,34 +781,35 @@ 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++)
     if (ssym->regs[i])
       freeReg (ssym->regs[i]);
 
-  /* if spilt on stack then free up r0 & r1 
+  /* if spilt on stack then free up r0 & r1
      if they could have been assigned to as gprs */
-  if (!ds390_ptrRegReq && isSpiltOnStack (ssym))
+  if (!ds390_ptrRegReq && isSpiltOnStack (ssym) && !options.stack10bit)
     {
-      ds390_ptrRegReq++;
+            ds390_ptrRegReq++;
       spillLRWithPtrReg (ssym);
     }
 
-  /* if this was a block level spil then insert push & pop 
+  /* if this was a block level spil then insert push & pop
      at the start & end of block respectively */
   if (ssym->blockSpil)
     {
       iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
       /* add push to the start of the block */
       addiCodeToeBBlock (ebp, nic, (ebp->sch->op == LABEL ?
-                                   ebp->sch->next : ebp->sch));
+                                    ebp->sch->next : ebp->sch));
       nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
       /* add pop to the end of the block */
       addiCodeToeBBlock (ebp, nic, NULL);
@@ -800,6 +843,7 @@ static regs *
 getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym)
 {
   regs *reg;
+  int j;
 
 tryAgain:
   /* try for a ptr type */
@@ -814,7 +858,12 @@ tryAgain:
   if (!spilSomething (ic, ebp, sym))
     return NULL;
 
-  /* this looks like an infinite loop but 
+  /* 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;
 }
@@ -826,6 +875,7 @@ static regs *
 getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
 {
   regs *reg;
+  int j;
 
 tryAgain:
   /* try for gpr type */
@@ -840,11 +890,95 @@ tryAgain:
   if (!spilSomething (ic, ebp, sym))
     return NULL;
 
-  /* this looks like an infinite loop but 
+  /* 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;
 }
 
+/*-----------------------------------------------------------------*/
+/* getRegBit - will try for Bit if not spill this                  */
+/*-----------------------------------------------------------------*/
+static regs *getRegBit (symbol * sym)
+{
+  regs *reg;
+
+  /* try for a bit type */
+  if ((reg = allocReg (REG_BIT)))
+    return reg;
+
+  spillThis (sym);
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegPtrNoSpil - get it cannot be spilt                        */
+/*-----------------------------------------------------------------*/
+static regs *getRegPtrNoSpil()
+{
+  regs *reg;
+
+  /* try for a ptr type */
+  if ((reg = allocReg (REG_PTR)))
+    return reg;
+
+  /* try for gpr type */
+  if ((reg = allocReg (REG_GPR)))
+    return reg;
+
+  assert(0);
+
+  /* just to make the compiler happy */
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegGprNoSpil - get it cannot be spilt                        */
+/*-----------------------------------------------------------------*/
+static regs *getRegGprNoSpil()
+{
+
+  regs *reg;
+  if ((reg = allocReg (REG_GPR)))
+    return reg;
+
+  if (!ds390_ptrRegReq)
+    if ((reg = allocReg (REG_PTR)))
+      return reg;
+
+  assert(0);
+
+  /* just to make the compiler happy */
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegBitNoSpil - get it cannot be spilt                        */
+/*-----------------------------------------------------------------*/
+#if 0
+static regs *getRegBitNoSpil()
+{
+  regs *reg;
+
+  /* try for a bit type */
+  if ((reg = allocReg (REG_BIT)))
+    return reg;
+
+  /* try for gpr type */
+  if ((reg = allocReg (REG_GPR)))
+    return reg;
+
+  assert(0);
+
+  /* just to make the compiler happy */
+  return 0;
+}
+#endif
+
 /*-----------------------------------------------------------------*/
 /* symHasReg - symbol has a given register                         */
 /*-----------------------------------------------------------------*/
@@ -860,6 +994,29 @@ symHasReg (symbol * sym, regs * reg)
   return FALSE;
 }
 
+/*-----------------------------------------------------------------*/
+/* updateRegUsage -  update the registers in use at the start of   */
+/*                   this icode                                    */
+/*-----------------------------------------------------------------*/
+static void
+updateRegUsage (iCode * ic)
+{
+  int reg;
+
+  for (reg=0; reg<ds390_nRegs; reg++)
+    {
+      if (regs390[reg].isFree)
+        {
+          ic->riu &= ~(1<<regs390[reg].offset);
+        }
+      else
+        {
+          ic->riu |= (1<<regs390[reg].offset);
+          BitBankUsed |= (reg >= B0_IDX);
+        }
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* deassignLRs - check the live to and if they have registers & are */
 /*               not spilt then free up the registers              */
@@ -878,87 +1035,89 @@ deassignLRs (iCode * ic, eBBlock * ebp)
       symbol *psym = NULL;
       /* if it does not end here */
       if (sym->liveTo > ic->seq)
-       continue;
+        continue;
 
-      /* if it was spilt on stack then we can 
+      /* if it was spilt on stack then we can
          mark the stack spil location as free */
       if (sym->isspilt)
-       {
-         if (sym->stackSpil)
-           {
-             sym->usl.spillLoc->isFree = 1;
-             sym->stackSpil = 0;
-           }
-         continue;
-       }
+        {
+          if (sym->stackSpil)
+            {
+              sym->usl.spillLoc->isFree = 1;
+              sym->stackSpil = 0;
+            }
+          continue;
+        }
 
       if (!bitVectBitValue (_G.regAssigned, sym->key))
-       continue;
+        continue;
 
       /* special case check if this is an IFX &
-         the privious one was a pop and the 
+         the privious one was a pop and the
          previous one was not spilt then keep track
          of the symbol */
       if (ic->op == IFX && ic->prev &&
-         ic->prev->op == IPOP &&
-         !ic->prev->parmPush &&
-         !OP_SYMBOL (IC_LEFT (ic->prev))->isspilt)
-       psym = OP_SYMBOL (IC_LEFT (ic->prev));
+          ic->prev->op == IPOP &&
+          !ic->prev->parmPush &&
+          !OP_SYMBOL (IC_LEFT (ic->prev))->isspilt)
+        psym = OP_SYMBOL (IC_LEFT (ic->prev));
 
       if (sym->nRegs)
-       {
-         int i = 0;
-
-         bitVectUnSetBit (_G.regAssigned, sym->key);
-
-         /* if the result of this one needs registers
-            and does not have it then assign it right
-            away */
-         if (IC_RESULT (ic) &&
-             !(SKIP_IC2 (ic) ||        /* not a special icode */
-               ic->op == JUMPTABLE ||
-               ic->op == IFX ||
-               ic->op == IPUSH ||
-               ic->op == IPOP ||
-               ic->op == RETURN ||
-               POINTER_SET (ic)) &&
-             (result = OP_SYMBOL (IC_RESULT (ic))) &&  /* has a result */
-             result->liveTo > ic->seq &&       /* and will live beyond this */
-             result->liveTo <= ebp->lSeq &&    /* does not go beyond this block */
-             result->regType == sym->regType &&        /* same register types */
-             result->nRegs &&  /* which needs registers */
-             !result->isspilt &&       /* and does not already have them */
-             !result->remat &&
-             !bitVectBitValue (_G.regAssigned, result->key) &&
-         /* the number of free regs + number of regs in this LR
-            can accomodate the what result Needs */
-             ((nfreeRegsType (result->regType) +
-               sym->nRegs) >= result->nRegs)
-           )
-           {
-
-             for (i = 0; i < result->nRegs; i++)
-               if (i < sym->nRegs)
-                 result->regs[i] = sym->regs[i];
-               else
-                 result->regs[i] = getRegGpr (ic, ebp, result);
-
-             _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
-
-           }
-
-         /* free the remaining */
-         for (; i < sym->nRegs; i++)
-           {
-             if (psym)
-               {
-                 if (!symHasReg (psym, sym->regs[i]))
-                   freeReg (sym->regs[i]);
-               }
-             else
-               freeReg (sym->regs[i]);
-           }
-       }
+        {
+          int i = 0;
+
+          bitVectUnSetBit (_G.regAssigned, sym->key);
+
+          /* if the result of this one needs registers
+             and does not have it then assign it right
+             away */
+          if (IC_RESULT (ic) &&
+              !(SKIP_IC2 (ic) ||        /* not a special icode */
+                ic->op == JUMPTABLE ||
+                ic->op == IFX ||
+                ic->op == IPUSH ||
+                ic->op == IPOP ||
+                ic->op == RETURN ||
+                POINTER_SET (ic)) &&
+              (result = OP_SYMBOL (IC_RESULT (ic))) &&  /* has a result */
+              result->liveTo > ic->seq &&       /* and will live beyond this */
+              result->liveTo <= ebp->lSeq &&    /* does not go beyond this block */
+              result->liveFrom == ic->seq &&    /* does not start before here */
+              result->regType == sym->regType &&        /* same register types */
+              result->nRegs &&  /* which needs registers */
+              !result->isspilt &&       /* and does not already have them */
+              !result->remat &&
+              !bitVectBitValue (_G.regAssigned, result->key) &&
+          /* the number of free regs + number of regs in this LR
+             can accomodate the what result Needs */
+              ((nfreeRegsType (result->regType) +
+                sym->nRegs) >= result->nRegs)
+            )
+            {
+
+              for (i = 0; i < result->nRegs; i++)
+                if (i < sym->nRegs)
+                  result->regs[i] = sym->regs[i];
+                else
+                  result->regs[i] = getRegGpr (ic, ebp, result);
+
+              _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
+              _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, result->key);
+
+            }
+
+          /* free the remaining */
+          for (; i < sym->nRegs; i++)
+            {
+              if (psym)
+                {
+                  if (!symHasReg (psym, sym->regs[i]))
+                    freeReg (sym->regs[i]);
+                }
+              else
+                freeReg (sym->regs[i]);
+            }
+        }
     }
 }
 
@@ -973,10 +1132,11 @@ reassignLR (operand * op)
   int i;
 
   /* 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--;
 
@@ -990,31 +1150,36 @@ reassignLR (operand * op)
 static int
 willCauseSpill (int nr, int rt)
 {
-  /* first check if there are any avlb registers
-     of te type required */
+  /* first check if there are any available registers
+     of the type required */
   if (rt == REG_PTR)
     {
-      /* special case for pointer type 
-         if pointer type not avlb then 
+      /* special case for pointer type
+         if pointer type not avlb then
          check for type gpr */
       if (nFreeRegs (rt) >= nr)
-       return 0;
+        return 0;
       if (nFreeRegs (REG_GPR) >= nr)
-       return 0;
+        return 0;
+    }
+  else if (rt == REG_BIT)
+    {
+      if (nFreeRegs (rt) >= nr)
+        return 0;
     }
   else
     {
       if (ds390_ptrRegReq)
-       {
-         if (nFreeRegs (rt) >= nr)
-           return 0;
-       }
+        {
+          if (nFreeRegs (rt) >= nr)
+            return 0;
+        }
       else
-       {
-         if (nFreeRegs (REG_PTR) +
-             nFreeRegs (REG_GPR) >= nr)
-           return 0;
-       }
+        {
+          if (nFreeRegs (REG_PTR) +
+              nFreeRegs (REG_GPR) >= nr)
+            return 0;
+        }
     }
 
   /* it will cause a spil */
@@ -1026,28 +1191,29 @@ willCauseSpill (int nr, int rt)
 /* ult and operand, if this happens make sure they are in the same */
 /* position as the operand otherwise chaos results                 */
 /*-----------------------------------------------------------------*/
-static void
-positionRegs (symbol * result, symbol * opsym, int lineno)
+static int
+positionRegs (symbol * result, symbol * opsym)
 {
   int count = min (result->nRegs, opsym->nRegs);
   int i, j = 0, shared = 0;
+  int change = 0;
 
   /* 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 */
   for (i = 0; i < count; i++)
     {
       for (j = 0; j < count; j++)
-       {
-         if (result->regs[i] == opsym->regs[j] && i != j)
-           {
-             shared = 1;
-             goto xchgPositions;
-           }
-       }
+        {
+          if (result->regs[i] == opsym->regs[j] && i != j)
+            {
+              shared = 1;
+              goto xchgPositions;
+            }
+        }
     }
 xchgPositions:
   if (shared)
@@ -1055,10 +1221,128 @@ xchgPositions:
       regs *tmp = result->regs[i];
       result->regs[i] = result->regs[j];
       result->regs[j] = tmp;
+      change ++;
       goto again;
     }
+  return change;
+}
+
+/*-----------------------------------------------------------------*/
+/* unusedLRS - returns a bitVector of liveranges not used in 'ebp' */
+/*-----------------------------------------------------------------*/
+bitVect *unusedLRs (eBBlock *ebp)
+{
+    bitVect *ret = NULL;
+    symbol *sym;
+    int key;
+
+    if (!ebp) return NULL;
+    for (sym = hTabFirstItem(liveRanges,&key); sym ;
+         sym = hTabNextItem(liveRanges,&key)) {
+
+        if (notUsedInBlock(sym,ebp,NULL)) {
+            ret = bitVectSetBit(ret,sym->key);
+        }
+    }
+
+    return ret;
 }
 
+/*-----------------------------------------------------------------*/
+/* deassignUnsedLRs - if this baisc block ends in a return then    */
+/*                    deassign symbols not used in this block      */
+/*-----------------------------------------------------------------*/
+bitVect *deassignUnsedLRs(eBBlock *ebp)
+{
+    bitVect *unused = NULL;
+    int i;
+
+    switch (returnAtEnd(ebp)) {
+    case 2: /* successor block ends in a return */
+        unused = unusedLRs((eBBlock *) setFirstItem(ebp->succList));
+        /* fall thru */
+    case 1: /* this block ends in a return */
+        unused = bitVectIntersect(unused,unusedLRs(ebp));
+        break;
+    }
+
+    if (unused) {
+        for (i = 0 ; i < unused->size ; i++ ) {
+
+            /* if unused  */
+            if (bitVectBitValue(unused,i)) {
+
+                /* if assigned to registers */
+                if (bitVectBitValue(_G.regAssigned,i)) {
+                    symbol *sym;
+                    int j;
+
+                    sym = hTabItemWithKey(liveRanges,i);
+                    /* remove it from regassigned & mark the
+                       register free */
+                    bitVectUnSetBit(_G.regAssigned,i);
+                    for (j = 0 ; j < sym->nRegs; j++)
+                        freeReg(sym->regs[j]);
+                } else {
+                    /* not assigned to registers : remove from set*/
+                    bitVectUnSetBit(unused,i);
+                }
+            }
+        }
+    }
+    return unused;
+}
+
+/*-----------------------------------------------------------------*/
+/* reassignUnusedLRs - put registers to unused Live ranges         */
+/*-----------------------------------------------------------------*/
+void reassignUnusedLRs (bitVect *unused)
+{
+    int i;
+    if (!unused) return ;
+
+    for (i = 0 ; i < unused->size ; i++ ) {
+        /* if unused : means it was assigned to registers before */
+        if (bitVectBitValue(unused,i)) {
+            symbol *sym;
+            int j;
+
+            /* put it back into reg set*/
+            bitVectSetBit(_G.regAssigned,i) ;
+
+            sym = hTabItemWithKey(liveRanges,i);
+            /* make registers busy */
+            for (j = 0 ; j < sym->nRegs; j++)
+                sym->regs[j]->isFree = 0;
+        }
+    }
+}
+
+/*------------------------------------------------------------------*/
+/* verifyRegsAssigned - make sure an iTemp is properly initialized; */
+/* it should either have registers or have beed spilled. Otherwise, */
+/* there was an uninitialized variable, so just spill this to get   */
+/* the operand in a valid state.                                    */
+/*------------------------------------------------------------------*/
+static void
+verifyRegsAssigned (operand *op, iCode * ic)
+{
+  symbol * sym;
+
+  if (!op) return;
+  if (!IS_ITEMP (op)) return;
+
+  sym = OP_SYMBOL (op);
+  if (sym->isspilt) return;
+  if (!sym->nRegs) return;
+  if (sym->regs[0]) return;
+
+  werrorfl (ic->filename, ic->lineno, W_LOCAL_NOINIT,
+            sym->prereqv ? sym->prereqv->name : sym->name);
+  spillThis (sym);
+}
+
+
 /*-----------------------------------------------------------------*/
 /* serialRegAssign - serially allocate registers to the variables  */
 /*-----------------------------------------------------------------*/
@@ -1069,156 +1353,433 @@ serialRegAssign (eBBlock ** ebbs, int count)
 
   /* for all blocks */
   for (i = 0; i < count; i++)
-    {
+      { /* ebbs */
 
       iCode *ic;
+      bitVect *unusedLRs = NULL;
 
       if (ebbs[i]->noPath &&
-         (ebbs[i]->entryLabel != entryLabel &&
-          ebbs[i]->entryLabel != returnLabel))
-       continue;
+          (ebbs[i]->entryLabel != entryLabel &&
+           ebbs[i]->entryLabel != returnLabel))
+        continue;
+
+      unusedLRs = deassignUnsedLRs(ebbs[i]);
 
-      /* of all instructions do */
+      /* for all instructions do */
       for (ic = ebbs[i]->sch; ic; ic = ic->next)
-       {
-
-         /* if this is an ipop that means some live
-            range will have to be assigned again */
-         if (ic->op == IPOP)
-           reassignLR (IC_LEFT (ic));
-
-         /* if result is present && is a true symbol */
-         if (IC_RESULT (ic) && ic->op != IFX &&
-             IS_TRUE_SYMOP (IC_RESULT (ic)))
-           OP_SYMBOL (IC_RESULT (ic))->allocreq = 1;
-
-         /* take away registers from live
-            ranges that end at this instruction */
-         deassignLRs (ic, ebbs[i]);
-
-         /* some don't need registers */
-         if (SKIP_IC2 (ic) ||
-             ic->op == JUMPTABLE ||
-             ic->op == IFX ||
-             ic->op == IPUSH ||
-             ic->op == IPOP ||
-             (IC_RESULT (ic) && POINTER_SET (ic)))
-           continue;
-
-         /* now we need to allocate registers
-            only for the result */
-         if (IC_RESULT (ic))
-           {
-             symbol *sym = OP_SYMBOL (IC_RESULT (ic));
-             bitVect *spillable;
-             int willCS;
-             int j;
-             int ptrRegSet = 0;
-
-             /* if it does not need or is spilt 
-                or is already assigned to registers
-                or will not live beyond this instructions */
-             if (!sym->nRegs ||
-                 sym->isspilt ||
-                 bitVectBitValue (_G.regAssigned, sym->key) ||
-                 sym->liveTo <= ic->seq)
-               continue;
-
-             /* if some liverange has been spilt at the block level
-                and this one live beyond this block then spil this
-                to be safe */
-             if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
-               {
-                 spillThis (sym);
-                 continue;
-               }
-             /* if trying to allocate this will cause
-                a spill and there is nothing to spill 
-                or this one is rematerializable then
-                spill this one */
-             willCS = willCauseSpill (sym->nRegs, sym->regType);
-             spillable = computeSpillable (ic);
-             if (sym->remat ||
-                 (willCS && bitVectIsZero (spillable)))
-               {
-
-                 spillThis (sym);
-                 continue;
-
-               }
-
-             /* if it has a spillocation & is used less than
-                all other live ranges then spill this */
-               if (willCS) {
-                   if (sym->usl.spillLoc) {
-                       symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
-                                                                        allLRs, ebbs[i], ic));
-                       if (leastUsed && leastUsed->used > sym->used) {
-                           spillThis (sym);
-                           continue;
-                       }
-                   } else {
-                       /* if none of the liveRanges have a spillLocation then better
-                          to spill this one than anything else already assigned to registers */
-                       if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
-                           spillThis (sym);
-                           continue;
-                       }
-                   }
-               }
-
-             /* if we need ptr regs for the right side
-                then mark it */
-             if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic))
-                 && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
-                 <= (unsigned) PTRSIZE)
-               {
-                 ds390_ptrRegReq++;
-                 ptrRegSet = 1;
-               }
-             /* else we assign registers to it */
-             _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
-
-             for (j = 0; j < sym->nRegs; j++)
-               {
-                 if (sym->regType == REG_PTR)
-                   sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
-                 else
-                   sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
-
-                 /* if the allocation falied which means
-                    this was spilt then break */
-                 if (!sym->regs[j])
-                   break;
-               }
-             /* if it shares registers with operands make sure
-                that they are in the same position */
-             if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
-                 OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=')
-               positionRegs (OP_SYMBOL (IC_RESULT (ic)),
-                             OP_SYMBOL (IC_LEFT (ic)), ic->lineno);
-             /* do the same for the right operand */
-             if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
-                 OP_SYMBOL (IC_RIGHT (ic))->nRegs)
-               positionRegs (OP_SYMBOL (IC_RESULT (ic)),
-                             OP_SYMBOL (IC_RIGHT (ic)), ic->lineno);
-
-             if (ptrRegSet)
-               {
-                 ds390_ptrRegReq--;
-                 ptrRegSet = 0;
-               }
-
-           }
-       }
+        {
+          updateRegUsage(ic);
+
+          /* if this is an ipop that means some live
+             range will have to be assigned again */
+          if (ic->op == IPOP)
+            reassignLR (IC_LEFT (ic));
+
+          /* if result is present && is a true symbol */
+          if (IC_RESULT (ic) && ic->op != IFX &&
+              IS_TRUE_SYMOP (IC_RESULT (ic)))
+            OP_SYMBOL (IC_RESULT (ic))->allocreq++;
+
+          /* take away registers from live
+             ranges that end at this instruction */
+          deassignLRs (ic, ebbs[i]);
+
+          /* some don't need registers */
+          if (SKIP_IC2 (ic) ||
+              ic->op == JUMPTABLE ||
+              ic->op == IFX ||
+              ic->op == IPUSH ||
+              ic->op == IPOP ||
+              (IC_RESULT (ic) && POINTER_SET (ic)))
+            continue;
+
+          /* now we need to allocate registers
+             only for the result */
+          if (IC_RESULT (ic))
+            {
+              symbol *sym = OP_SYMBOL (IC_RESULT (ic));
+              bitVect *spillable;
+              int willCS;
+              int j;
+              int ptrRegSet = 0;
+                
+              /* Make sure any spill location is definitely allocated */
+              if (sym->isspilt && !sym->remat && sym->usl.spillLoc &&
+                  !sym->usl.spillLoc->allocreq)
+                {
+                  sym->usl.spillLoc->allocreq++;
+                }
+
+              /* if it does not need or is spilt
+                 or is already assigned to registers
+                 or will not live beyond this instructions */
+              if (!sym->nRegs ||
+                  sym->isspilt ||
+                  bitVectBitValue (_G.regAssigned, sym->key) ||
+                  sym->liveTo <= ic->seq)
+                continue;
+
+              /* if some liverange has been spilt at the block level
+                 and this one live beyond this block then spil this
+                 to be safe */
+              if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
+                {
+                  spillThis (sym);
+                  continue;
+                }
+
+              willCS = willCauseSpill (sym->nRegs, sym->regType);
+              /* if this is a bit variable then don't use precious registers
+                 along with expensive bit-to-char conversions but just spill
+                 it */
+              if (willCS && SPEC_NOUN(sym->etype) == V_BIT)
+                {
+                  spillThis (sym);
+                  continue;
+                }
+
+              /* if trying to allocate this will cause
+                 a spill and there is nothing to spill
+                 or this one is rematerializable then
+                 spill this one */
+              spillable = computeSpillable (ic);
+              if (sym->remat || (willCS && bitVectIsZero (spillable)))
+                {
+                  spillThis (sym);
+                  continue;
+                }
+
+              /* If the live range preceeds the point of definition
+                 then ideally we must take into account registers that
+                 have been allocated after sym->liveFrom but freed
+                 before ic->seq. This is complicated, so spill this
+                 symbol instead and let fillGaps handle the allocation. */
+              if (sym->liveFrom < ic->seq)
+                {
+                    spillThis (sym);
+                    continue;
+                }
+
+              /* if it has a spillocation & is used less than
+                 all other live ranges then spill this */
+                if (willCS) {
+                    if (sym->usl.spillLoc) {
+                        symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
+                                                                         allLRs, ebbs[i], ic));
+                        if (leastUsed && leastUsed->used > sym->used) {
+                            spillThis (sym);
+                            continue;
+                        }
+                    } else {
+                        /* if none of the liveRanges have a spillLocation then better
+                           to spill this one than anything else already assigned to registers */
+                        if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
+                            /* if this is local to this block then we might find a block spil */
+                            if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
+                                spillThis (sym);
+                                continue;
+                            }
+                        }
+                    }
+                }
+
+              /* if we need ptr regs for the right side
+                 then mark it */
+              if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic))
+                  && getSize (OP_SYMBOL (IC_LEFT (ic))->type) <= (unsigned) PTRSIZE)
+                {
+                  ds390_ptrRegReq++;
+                  ptrRegSet = 1;
+                }
+              /* else we assign registers to it */
+              _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+              _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key);
+
+              for (j = 0; j < sym->nRegs; j++)
+                {
+                  sym->regs[j] = NULL;
+                  if (sym->regType == REG_PTR)
+                    sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
+                  else if (sym->regType == REG_BIT)
+                    sym->regs[j] = getRegBit (sym);
+                  else
+                    sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
+
+                  /* if the allocation failed which means
+                     this was spilt then break */
+                  if (!sym->regs[j])
+                    break;
+                }
+
+              /* if it shares registers with operands make sure
+                 that they are in the same position */
+              if (!POINTER_SET(ic) && !POINTER_GET(ic))
+                {
+                  if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
+                      OP_SYMBOL (IC_LEFT (ic))->nRegs)
+                    {
+                      positionRegs (OP_SYMBOL (IC_RESULT (ic)),
+                                    OP_SYMBOL (IC_LEFT (ic)));
+                    }
+                  /* do the same for the right operand */
+                  if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
+                      OP_SYMBOL (IC_RIGHT (ic))->nRegs)
+                    {
+                      positionRegs (OP_SYMBOL (IC_RESULT (ic)),
+                                    OP_SYMBOL (IC_RIGHT (ic)));
+                    }
+                }
+
+              if (ptrRegSet)
+                {
+                  ds390_ptrRegReq--;
+                  ptrRegSet = 0;
+                }
+
+            }
+        }
+      reassignUnusedLRs(unusedLRs);
     }
+
+    /* 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);
+          }
+      }
 }
 
 /*-----------------------------------------------------------------*/
-/* rUmaskForOp :- returns register mask for an operand             */
+/* fillGaps - Try to fill in the Gaps left by Pass1                */
+/*-----------------------------------------------------------------*/
+static void fillGaps()
+{
+    symbol *sym =NULL;
+    int key =0;
+    int loop = 0, change;
+    int pass;
+
+    if (getenv("DISABLE_FILL_GAPS")) return;
+
+    /* First try to do DPTRuse once more since now we know what got into
+       registers */
+
+    while (loop++ < 10) {
+        change = 0;
+
+        for (sym = hTabFirstItem(liveRanges,&key) ; sym ;
+             sym = hTabNextItem(liveRanges,&key)) {
+            int size = getSize(sym->type);
+
+            if (sym->liveFrom == sym->liveTo) continue;
+
+            if (sym->uptr && sym->dptr==0 && !sym->ruonly &&
+                size < 4 && size > 1) {
+
+                if (packRegsDPTRuse(operandFromSymbol(sym))) {
+
+                    /* if this was assigned to registers then */
+                    if (bitVectBitValue(_G.totRegAssigned,sym->key)) {
+                        /* take it out of the register assigned set */
+                        bitVectUnSetBit(_G.totRegAssigned,sym->key);
+                    } else if (sym->usl.spillLoc) {
+                        sym->usl.spillLoc->allocreq--;
+                        sym->usl.spillLoc = NULL;
+                    }
+
+                    sym->nRegs = 0;
+                    sym->isspilt = sym->spillA = 0;
+                    continue ;
+                }
+
+                /* try assigning other dptrs */
+                if (sym->dptr == 0 && packRegsDPTRnuse(operandFromSymbol(sym),1) && !getenv("DPTRnDISABLE")) {
+                    /* if this was ssigned to registers then */
+                    if (bitVectBitValue(_G.totRegAssigned,sym->key)) {
+                        /* take it out of the register assigned set */
+                        bitVectUnSetBit(_G.totRegAssigned,sym->key);
+                    } else if (sym->usl.spillLoc) {
+                        sym->usl.spillLoc->allocreq--;
+                        sym->usl.spillLoc = NULL;
+                    }
+                    sym->nRegs = 0;
+                    sym->isspilt = sym->spillA = 0;
+                }
+            }
+        }
+
+        /* look for liveranges that were 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 ;
+            if (!sym->uses || !sym->defs) 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++ ) {
+                if (sym->regType == REG_PTR)
+                    sym->regs[i] = getRegPtrNoSpil ();
+                else
+                    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.
+               We may need to perform the checks twice; once to
+               position the registers as needed, the second to
+               verify any register repositioning is still
+               compatible.
+              */
+            sym->isspilt = 0;
+            for (pass=0; pass<2; pass++) {
+                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)))>0);
+                        }
+                        if (IS_SYMOP(IC_RIGHT(ic)) &&
+                          bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) {
+                            pdone += (positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic)))>0);
+                        }
+                        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 (POINTER_SET(ic) || POINTER_GET(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)))>0);
+                        }
+                        if (pdone > 1) break;
+                    }
+                }
+                if (pdone == 0) break; /* second pass only if regs repositioned */
+                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 (fprintf (stderr, "Fill Gap gave up due to positioning for "
+                            "%s in function %s\n",
+                            sym->name, currFunc ? currFunc->name : "UNKNOWN"));
+                continue ;
+            }
+            D (fprintf (stderr, "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--;
+            sym->usl.spillLoc = NULL;
+            freeAllRegs();
+            change ++;
+        }
+        if (!change) break;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* findAllBitregs :- returns bit vector of all bit registers       */
 /*-----------------------------------------------------------------*/
 static bitVect *
-rUmaskForOp (operand * op)
+findAllBitregs (void)
+{
+  bitVect *rmask = newBitVect (ds390_nRegs);
+  int j;
+
+  for (j = 0; j < ds390_nRegs; j++)
+    {
+      if (regs390[j].type == REG_BIT)
+        rmask = bitVectSetBit (rmask, regs390[j].rIdx);
+    }
+
+  return rmask;
+}
+
+/*-----------------------------------------------------------------*/
+/* ds390_allBitregs :- returns bit vector of all bit registers     */
+/*-----------------------------------------------------------------*/
+bitVect *
+ds390_allBitregs (void)
+{
+  return _G.allBitregs;
+}
+
+/*-----------------------------------------------------------------*/
+/* rUmaskForOp :- returns register mask for an operand             */
+/*-----------------------------------------------------------------*/
+bitVect *
+ds390_rUmaskForOp (operand * op)
 {
   bitVect *rumask;
   symbol *sym;
@@ -1240,7 +1801,7 @@ rUmaskForOp (operand * op)
   for (j = 0; j < sym->nRegs; j++)
     {
       rumask = bitVectSetBit (rumask,
-                             sym->regs[j]->rIdx);
+                              sym->regs[j]->rIdx);
     }
 
   return rumask;
@@ -1258,7 +1819,7 @@ regsUsedIniCode (iCode * ic)
   if (ic->op == IFX)
     {
       rmask = bitVectUnion (rmask,
-                           rUmaskForOp (IC_COND (ic)));
+                            ds390_rUmaskForOp (IC_COND (ic)));
       goto ret;
     }
 
@@ -1266,7 +1827,7 @@ regsUsedIniCode (iCode * ic)
   if (ic->op == JUMPTABLE)
     {
       rmask = bitVectUnion (rmask,
-                           rUmaskForOp (IC_JTCOND (ic)));
+                            ds390_rUmaskForOp (IC_JTCOND (ic)));
 
       goto ret;
     }
@@ -1274,16 +1835,16 @@ regsUsedIniCode (iCode * ic)
   /* of all other cases */
   if (IC_LEFT (ic))
     rmask = bitVectUnion (rmask,
-                         rUmaskForOp (IC_LEFT (ic)));
+                          ds390_rUmaskForOp (IC_LEFT (ic)));
 
 
   if (IC_RIGHT (ic))
     rmask = bitVectUnion (rmask,
-                         rUmaskForOp (IC_RIGHT (ic)));
+                          ds390_rUmaskForOp (IC_RIGHT (ic)));
 
   if (IC_RESULT (ic))
     rmask = bitVectUnion (rmask,
-                         rUmaskForOp (IC_RESULT (ic)));
+                          ds390_rUmaskForOp (IC_RESULT (ic)));
 
 ret:
   return rmask;
@@ -1303,58 +1864,68 @@ createRegMask (eBBlock ** ebbs, int count)
       iCode *ic;
 
       if (ebbs[i]->noPath &&
-         (ebbs[i]->entryLabel != entryLabel &&
-          ebbs[i]->entryLabel != returnLabel))
-       continue;
+          (ebbs[i]->entryLabel != entryLabel &&
+           ebbs[i]->entryLabel != returnLabel))
+        continue;
 
       /* for all instructions */
       for (ic = ebbs[i]->sch; ic; ic = ic->next)
-       {
-
-         int j;
-
-         if (SKIP_IC2 (ic) || !ic->rlive)
-           continue;
-
-         /* first mark the registers used in this
-            instruction */
-         ic->rUsed = regsUsedIniCode (ic);
-         _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
-
-         /* now create the register mask for those 
-            registers that are in use : this is a
-            super set of ic->rUsed */
-         ic->rMask = newBitVect (ds390_nRegs + 1);
-
-         /* for all live Ranges alive at this point */
-         for (j = 1; j < ic->rlive->size; j++)
-           {
-             symbol *sym;
-             int k;
-
-             /* if not alive then continue */
-             if (!bitVectBitValue (ic->rlive, j))
-               continue;
-
-             /* find the live range we are interested in */
-             if (!(sym = hTabItemWithKey (liveRanges, j)))
-               {
-                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-                         "createRegMask cannot find live range");
-                 exit (0);
-               }
-
-             /* if no register assigned to it */
-             if (!sym->nRegs || sym->isspilt)
-               continue;
-
-             /* for all the registers allocated to it */
-             for (k = 0; k < sym->nRegs; k++)
-               if (sym->regs[k])
-                 ic->rMask =
-                   bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
-           }
-       }
+        {
+
+          int j;
+
+          if (SKIP_IC2 (ic) || !ic->rlive)
+            continue;
+
+          /* first mark the registers used in this
+             instruction */
+          ic->rUsed = regsUsedIniCode (ic);
+          _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
+
+          /* now create the register mask for those
+             registers that are in use : this is a
+             super set of ic->rUsed */
+          ic->rMask = newBitVect (ds390_nRegs + 1);
+
+          /* for all live Ranges alive at this point */
+          for (j = 1; j < ic->rlive->size; j++)
+            {
+              symbol *sym;
+              int k;
+
+              /* if not alive then continue */
+              if (!bitVectBitValue (ic->rlive, j))
+                continue;
+
+              /* find the live range we are interested in */
+              if (!(sym = hTabItemWithKey (liveRanges, j)))
+                {
+                  werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                          "createRegMask cannot find live range");
+                  fprintf(stderr, "\tmissing live range: key=%d\n", j);
+                  exit (0);
+                }
+#if 0
+              /* special case for ruonly */
+              if (sym->ruonly && sym->liveFrom != sym->liveTo) {
+                  int size = getSize(sym->type);
+                  int j = DPL_IDX;
+                  for (k = 0 ; k < size; k++ )
+                      ic->rMask = bitVectSetBit (ic->rMask, j++);
+                  continue ;
+              }
+#endif
+              /* if no register assigned to it */
+              if (!sym->nRegs || sym->isspilt)
+                continue;
+
+              /* for all the registers allocated to it */
+              for (k = 0; k < sym->nRegs; k++)
+                if (sym->regs[k])
+                  ic->rMask =
+                    bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
+            }
+        }
     }
 }
 
@@ -1367,21 +1938,30 @@ rematStr (symbol * sym)
   char *s = buffer;
   iCode *ic = sym->rematiCode;
 
+  *s = 0;
+
   while (1)
     {
 
       /* if plus or minus print the right hand side */
       if (ic->op == '+' || ic->op == '-')
-       {
-         sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
-                  ic->op);
-         s += strlen (s);
-         ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
-         continue;
-       }
-
+        {
+          SNPRINTF (s, sizeof(buffer) - strlen(buffer),
+                    "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
+                    ic->op);
+          s += strlen (s);
+          ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+          continue;
+        }
+
+      /* cast then continue */
+      if (IS_CAST_ICODE(ic)) {
+          ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
+          continue;
+      }
       /* we reached the end */
-      sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
+      SNPRINTF (s, sizeof(buffer) - strlen(buffer),
+                "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
       break;
     }
 
@@ -1405,86 +1985,72 @@ regTypeNum ()
 
       /* if used zero times then no registers needed */
       if ((sym->liveTo - sym->liveFrom) == 0)
-       continue;
+        continue;
 
 
       /* if the live range is a temporary */
       if (sym->isitmp)
-       {
-
-         /* if the type is marked as a conditional */
-         if (sym->regType == REG_CND)
-           continue;
-
-         /* if used in return only then we don't 
-            need registers */
-         if (sym->ruonly || sym->accuse)
-           {
-             if (IS_AGGREGATE (sym->type) || sym->isptr)
-               sym->type = aggrToPtr (sym->type, FALSE);
-             continue;
-           }
-
-         /* if the symbol has only one definition &
-            that definition is a get_pointer and the
-            pointer we are getting is rematerializable and
-            in "data" space */
-
-         if (bitVectnBitsOn (sym->defs) == 1 &&
-             (ic = hTabItemWithKey (iCodehTab,
-                                    bitVectFirstBit (sym->defs))) &&
-             POINTER_GET (ic) &&
-             !IS_BITVAR (sym->etype))
-           {
-
-
-             /* if remat in data space */
-             if (OP_SYMBOL (IC_LEFT (ic))->remat &&
-             // sym->type &&
-                 DCL_TYPE (aggrToPtr (sym->type, FALSE)) == POINTER)
-               {
-
-                 /* create a psuedo symbol & force a spil */
-                 symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
-                 psym->type = sym->type;
-                 psym->etype = sym->etype;
-                 strcpy (psym->rname, psym->name);
-                 sym->isspilt = 1;
-                 sym->usl.spillLoc = psym;
-                 continue;
-               }
-
-             /* if in data space or idata space then try to
-                allocate pointer register */
-
-           }
-
-         /* if not then we require registers */
-         sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
-                       getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
-                       getSize (sym->type));
-
-         if (sym->nRegs > 4)
-           {
-             fprintf (stderr, "allocated more than 4 or 0 registers for type ");
-             printTypeChain (sym->type, stderr);
-             fprintf (stderr, "\n");
-           }
-
-         /* determine the type of register required */
-         if (sym->nRegs == 1 &&
-             IS_PTR (sym->type) &&
-             sym->uptr)
-           sym->regType = REG_PTR;
-         else
-           sym->regType = REG_GPR;
-
-       }
+        {
+
+          /* if the type is marked as a conditional */
+          if (sym->regType == REG_CND)
+            continue;
+
+          /* if used in return only then we don't
+             need registers */
+          if (sym->ruonly || sym->accuse)
+            {
+              if (IS_AGGREGATE (sym->type) || sym->isptr)
+                sym->type = aggrToPtr (sym->type, FALSE);
+              continue;
+            }
+
+          /* if the symbol has only one definition &
+             that definition is a get_pointer */
+          if (bitVectnBitsOn (sym->defs) == 1 &&
+              (ic = hTabItemWithKey (iCodehTab,
+                                     bitVectFirstBit (sym->defs))) &&
+              POINTER_GET (ic) &&
+              !IS_BITVAR (sym->etype) &&
+              (aggrToPtrDclType (operandType (IC_LEFT (ic)), FALSE) == POINTER))
+            {
+
+              if (ptrPseudoSymSafe (sym, ic))
+                {
+                  ptrPseudoSymConvert (sym, ic, rematStr (OP_SYMBOL (IC_LEFT (ic))));
+                  continue;
+                }
+
+              /* if in data space or idata space then try to
+                 allocate pointer register */
+
+            }
+
+          /* if not then we require registers */
+          sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
+                        getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
+                        getSize (sym->type));
+
+          if (sym->nRegs > 4)
+            {
+              fprintf (stderr, "allocated more than 4 or 0 registers for type ");
+              printTypeChain (sym->type, stderr);
+              fprintf (stderr, "\n");
+            }
+
+          /* determine the type of register required */
+          if (sym->nRegs == 1 && IS_PTR (sym->type) && sym->uptr)
+            sym->regType = REG_PTR;
+          else if (IS_BIT(sym->type))
+            sym->regType = REG_BIT;
+          else
+            sym->regType = REG_GPR;
+        }
       else
-       /* for the first run we don't provide */
-       /* registers for true symbols we will */
-       /* see how things go                  */
-       sym->nRegs = 0;
+        /* for the first run we don't provide */
+        /* registers for true symbols we will */
+        /* see how things go                  */
+        sym->nRegs = 0;
     }
 
 }
@@ -1499,6 +2065,9 @@ freeAllRegs ()
 
   for (i = 0; i < ds390_nRegs; i++)
     regs390[i].isFree = 1;
+
+  for (i = B0_IDX; i < ds390_nBitRegs; i++)
+    regs390[i].isFree = 1;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1525,56 +2094,55 @@ farSpacePackable (iCode * ic)
      symbol on the right */
   for (dic = ic->prev; dic; dic = dic->prev)
     {
-
       /* if the definition is a call then no */
       if ((dic->op == CALL || dic->op == PCALL) &&
-         IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
-       {
-         return NULL;
-       }
+          IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+        {
+          return NULL;
+        }
 
       /* if shift by unknown amount then not */
       if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) &&
-         IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
-       return NULL;
+          IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+        return NULL;
 
       /* if pointer get and size > 1 */
       if (POINTER_GET (dic) &&
-         getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > 1)
-       return NULL;
+          getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > 1)
+        return NULL;
 
       if (POINTER_SET (dic) &&
-         getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1)
-       return NULL;
+          getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1)
+        return NULL;
 
-      /* if any three is a true symbol in far space */
+      /* if any tree is a true symbol in far space */
       if (IC_RESULT (dic) &&
-         IS_TRUE_SYMOP (IC_RESULT (dic)) &&
-         isOperandInFarSpace (IC_RESULT (dic)))
-       return NULL;
+          IS_TRUE_SYMOP (IC_RESULT (dic)) &&
+          isOperandInFarSpace (IC_RESULT (dic)))
+        return NULL;
 
       if (IC_RIGHT (dic) &&
-         IS_TRUE_SYMOP (IC_RIGHT (dic)) &&
-         isOperandInFarSpace (IC_RIGHT (dic)) &&
-         !isOperandEqual (IC_RIGHT (dic), IC_RESULT (ic)))
-       return NULL;
+          IS_TRUE_SYMOP (IC_RIGHT (dic)) &&
+          isOperandInFarSpace (IC_RIGHT (dic)) &&
+          !isOperandEqual (IC_RIGHT (dic), IC_RESULT (ic)))
+        return NULL;
 
       if (IC_LEFT (dic) &&
-         IS_TRUE_SYMOP (IC_LEFT (dic)) &&
-         isOperandInFarSpace (IC_LEFT (dic)) &&
-         !isOperandEqual (IC_LEFT (dic), IC_RESULT (ic)))
-       return NULL;
+          IS_TRUE_SYMOP (IC_LEFT (dic)) &&
+          isOperandInFarSpace (IC_LEFT (dic)) &&
+          !isOperandEqual (IC_LEFT (dic), IC_RESULT (ic)))
+        return NULL;
 
       if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (dic)))
-       {
-         if ((dic->op == LEFT_OP ||
-              dic->op == RIGHT_OP ||
-              dic->op == '-') &&
-             IS_OP_LITERAL (IC_RIGHT (dic)))
-           return NULL;
-         else
-           return dic;
-       }
+        {
+          if ((dic->op == LEFT_OP ||
+               dic->op == RIGHT_OP ||
+               dic->op == '-') &&
+              IS_OP_LITERAL (IC_RIGHT (dic)))
+            return NULL;
+          else
+            return dic;
+        }
     }
 
   return NULL;
@@ -1601,9 +2169,9 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
   if (isOperandInFarSpace (IC_RESULT (ic)))
     {
       if ((dic = farSpacePackable (ic)))
-       goto pack;
+        goto pack;
       else
-       return 0;
+        return 0;
     }
 #else
   if (isOperandInFarSpace(IC_RESULT(ic)) && !farSpacePackable(ic)) {
@@ -1611,76 +2179,78 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
   }
 #endif
 
-  /* find the definition of iTempNN scanning backwards if we find a 
-     a use of the true symbol in before we find the definition then 
+  /* find the definition of iTempNN scanning backwards if we find a
+     a use of the true symbol in before we find the definition then
      we cannot */
   for (dic = ic->prev; dic; dic = dic->prev)
     {
-#if 0 // jwk 20010410, the JanVanBelle case
-      /* if there is a function call and this is
-         a parameter & not my parameter then don't pack it */
-      if ((dic->op == CALL || dic->op == PCALL) &&
-         (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
-          !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
-       {
-         dic = NULL;
-         break;
-       }
-#else
       /* if there is a function call then don't pack it */
       if ((dic->op == CALL || dic->op == PCALL))
-       {
-         dic = NULL;
-         break;
-       }
-#endif
+        {
+          dic = NULL;
+          break;
+        }
 
       if (SKIP_IC2 (dic))
-       continue;
+        continue;
 
       if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
-         IS_OP_VOLATILE (IC_RESULT (dic)))
-       {
-         dic = NULL;
-         break;
-       }
+          IS_OP_VOLATILE (IC_RESULT (dic)))
+        {
+          dic = NULL;
+          break;
+        }
 
       if (IS_SYMOP (IC_RESULT (dic)) &&
-         IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
-       {
-         if (POINTER_SET (dic))
-           dic = NULL;
+          IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+        {
+          if (POINTER_SET (dic))
+            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;
-       }
+          (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;
-       }
+          (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
+           IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
+        {
+          dic = NULL;
+          break;
+        }
 
       if (POINTER_SET (dic) &&
-         IC_RESULT (dic)->key == IC_RESULT (ic)->key)
-       {
-         dic = NULL;
-         break;
-       }
+          IC_RESULT (dic)->key == IC_RESULT (ic)->key)
+        {
+          dic = NULL;
+          break;
+        }
     }
 
   if (!dic)
-    return 0;                  /* did not find */
+    return 0;                   /* did not find */
 
+  /* if assignment then check that right is not a bit */
+  if (ASSIGNMENT (ic) && !POINTER_SET (ic))
+    {
+      sym_link *etype = operandType (IC_RESULT (dic));
+      if (IS_BITFIELD (etype))
+        {
+          /* if result is a bit too then it's ok */
+          etype = operandType (IC_RESULT (ic));
+          if (!IS_BITFIELD (etype))
+            {
+              return 0;
+            }
+       }
+    }
   /* if the result is on stack or iaccess then it must be
      the same atleast one of the operands */
   if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
@@ -1690,100 +2260,110 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
       /* the operation has only one symbol
          operator then we can pack */
       if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) ||
-         (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic))))
-       goto pack;
+          (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic))))
+        goto pack;
 
       if (!((IC_LEFT (dic) &&
-            IC_RESULT (ic)->key == IC_LEFT (dic)->key) ||
-           (IC_RIGHT (dic) &&
-            IC_RESULT (ic)->key == IC_RIGHT (dic)->key)))
-       return 0;
+             IC_RESULT (ic)->key == IC_LEFT (dic)->key) ||
+            (IC_RIGHT (dic) &&
+             IC_RESULT (ic)->key == IC_RIGHT (dic)->key)))
+        return 0;
     }
 pack:
   /* found the definition */
   /* replace the result with the result of */
   /* this assignment and remove this assignment */
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+
   IC_RESULT (dic) = IC_RESULT (ic);
 
   if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
     {
       OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
     }
-  /* delete from liverange table also 
+  /* delete from liverange table also
      delete from all the points inbetween and the new
      one */
   for (sic = dic; sic != ic; sic = sic->next)
     {
       bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
       if (IS_ITEMP (IC_RESULT (dic)))
-       bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
+        bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
     }
 
   remiCodeFromeBBlock (ebp, ic);
+  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;
-
 }
 
-/*-----------------------------------------------------------------*/
+/*------------------------------------------------------------------*/
 /* findAssignToSym : scanning backwards looks for first assig found */
-/*-----------------------------------------------------------------*/
+/*------------------------------------------------------------------*/
 static iCode *
 findAssignToSym (operand * op, iCode * ic)
 {
   iCode *dic;
 
+  /* This routine is used to find sequences like
+     iTempAA = FOO;
+     ...;  (intervening ops don't use iTempAA or modify FOO)
+     blah = blah + iTempAA;
+
+     and eliminate the use of iTempAA, freeing up its register for
+     other uses.
+  */
+
   for (dic = ic->prev; dic; dic = dic->prev)
     {
 
       /* if definition by assignment */
       if (dic->op == '=' &&
-         !POINTER_SET (dic) &&
-         IC_RESULT (dic)->key == op->key
+          !POINTER_SET (dic) &&
+          IC_RESULT (dic)->key == op->key
 /*          &&  IS_TRUE_SYMOP(IC_RIGHT(dic)) */
-       )
-       {
+        )
+        {
 
-         /* we are interested only if defined in far space */
-         /* or in stack space in case of + & - */
+          /* we are interested only if defined in far space */
+          /* or in stack space in case of + & - */
 
-         /* if assigned to a non-symbol then return
-            true */
-         if (!IS_SYMOP (IC_RIGHT (dic)))
-           break;
+          /* if assigned to a non-symbol then return
+             FALSE */
+          if (!IS_SYMOP (IC_RIGHT (dic)))
+            return NULL;
 
-         /* if the symbol is in far space then
-            we should not */
-         if (isOperandInFarSpace (IC_RIGHT (dic)))
-           return NULL;
+          /* if the symbol is in far space then we should not */
+          if (isOperandInFarSpace (IC_RIGHT (dic)))
+            return NULL;
 
-         /* for + & - operations make sure that
-            if it is on the stack it is the same
-            as one of the three operands */
-         if ((ic->op == '+' || ic->op == '-') &&
-             OP_SYMBOL (IC_RIGHT (dic))->onStack)
-           {
+          /* for + & - operations make sure that
+             if it is on the stack it is the same
+             as one of the three operands */
+          if ((ic->op == '+' || ic->op == '-') &&
+              OP_SYMBOL (IC_RIGHT (dic))->onStack)
+            {
 
-             if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
-                 IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
-                 IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
-               return NULL;
-           }
+              if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
+                  IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
+                  IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
+                return NULL;
+            }
 
-         break;
+          break;
 
-       }
+        }
 
       /* if we find an usage then we cannot delete it */
       if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
-       return NULL;
+        return NULL;
 
       if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
-       return NULL;
+        return NULL;
 
       if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
-       return NULL;
+        return NULL;
     }
 
   /* now make sure that the right side of dic
@@ -1793,9 +2373,9 @@ findAssignToSym (operand * op, iCode * ic)
       iCode *sic = dic->next;
 
       for (; sic != ic; sic = sic->next)
-       if (IC_RESULT (sic) &&
-           IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
-         return NULL;
+        if (IC_RESULT (sic) &&
+            IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
+          return NULL;
     }
 
   return dic;
@@ -1810,6 +2390,7 @@ static int
 packRegsForSupport (iCode * ic, eBBlock * ebp)
 {
   int change = 0;
+
   /* for the left & right operand :- look to see if the
      left was assigned a true symbol in far space in that
      case replace them */
@@ -1820,16 +2401,22 @@ packRegsForSupport (iCode * ic, eBBlock * ebp)
       iCode *sic;
 
       if (!dic)
-       goto right;
+        goto right;
 
       /* found it we need to remove it from the
          block */
-      for (sic = dic; sic != ic; sic = sic->next)
-       bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
+      for (sic = dic; sic != ic; sic = sic->next) {
+        bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
+        sic->rlive = bitVectSetBit (sic->rlive, IC_RIGHT (dic)->key);
+      }
 
+      wassert(IS_SYMOP(IC_LEFT (ic)));
+      wassert(IS_SYMOP(IC_RIGHT (dic)));
       IC_LEFT (ic)->operand.symOperand =
-       IC_RIGHT (dic)->operand.symOperand;
+        IC_RIGHT (dic)->operand.symOperand;
+      OP_SYMBOL(IC_LEFT(ic))->liveTo = ic->seq;
       IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
+      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
       remiCodeFromeBBlock (ebp, dic);
       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
       change++;
@@ -1845,26 +2432,31 @@ right:
       iCode *sic;
 
       if (!dic)
-       return change;
+        return change;
 
       /* if this is a subtraction & the result
          is a true symbol in far space then don't pack */
       if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
-       {
-         sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
-         if (IN_FARSPACE (SPEC_OCLS (etype)))
-           return change;
-       }
+        {
+          sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
+          if (IN_FARSPACE (SPEC_OCLS (etype)))
+            return change;
+        }
       /* found it we need to remove it from the
          block */
-      for (sic = dic; sic != ic; sic = sic->next)
-       bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
+      for (sic = dic; sic != ic; sic = sic->next) {
+        bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
+        sic->rlive = bitVectSetBit (sic->rlive, IC_RIGHT (dic)->key);
+      }
 
+      wassert(IS_SYMOP(IC_RIGHT (ic)));
+      wassert(IS_SYMOP(IC_RIGHT (dic)));
       IC_RIGHT (ic)->operand.symOperand =
-       IC_RIGHT (dic)->operand.symOperand;
+        IC_RIGHT (dic)->operand.symOperand;
       IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
-
+      OP_SYMBOL(IC_RIGHT(ic))->liveTo = ic->seq;
       remiCodeFromeBBlock (ebp, dic);
+      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
       change++;
     }
@@ -1876,144 +2468,250 @@ right:
 
 
 /*-----------------------------------------------------------------*/
-/* packRegsForOneuse : - will reduce some registers for single Use */
+/* packRegsDPTRnuse - color live ranges that can go into extra DPTRS */
 /*-----------------------------------------------------------------*/
-static iCode *
-packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
+static int packRegsDPTRnuse( operand *op , unsigned dptr)
 {
-#if 1
-
-  /* I can't figure out how to make this safe yet. */
-  if ((int)ic+(int)op+(int)ebp) {
-    return 0;
-  } else {
-    return 0;
-  }
-  return NULL;
-
-#else
-  bitVect *uses;
-  iCode *dic, *sic;
-
-  /* if returning a literal then do nothing */
-  if (!IS_SYMOP (op))
-    return NULL;
-
-  /* only upto 2 bytes since we cannot predict
-     the usage of b, & acc */
-  if (getSize (operandType (op)) > (fReturnSizeDS390 - 2) &&
-      ic->op != RETURN &&
-      ic->op != SEND &&
-      !POINTER_SET (ic) &&
-      !POINTER_GET (ic))
-    return NULL;
-
-  /* this routine will mark the a symbol as used in one 
-     instruction use only && if the defintion is local 
-     (ie. within the basic block) && has only one definition &&
-     that definiion is either a return value from a 
-     function or does not contain any variables in
-     far space */
-  uses = bitVectCopy (OP_USES (op));
-  bitVectUnSetBit (uses, ic->key);     /* take away this iCode */
-  if (!bitVectIsZero (uses))   /* has other uses */
-    return NULL;
-
-  /* if it has only one defintion */
-  if (bitVectnBitsOn (OP_DEFS (op)) > 1)
-    return NULL;               /* has more than one definition */
-
-  /* get the that definition */
-  if (!(dic =
-       hTabItemWithKey (iCodehTab,
-                        bitVectFirstBit (OP_DEFS (op)))))
-    return NULL;
-
-  /* found the definition now check if it is local */
-  if (dic->seq < ebp->fSeq ||
-      dic->seq > ebp->lSeq)
-    return NULL;               /* non-local */
-
-  /* now check if it is the return from
-     a function call */
-  if (dic->op == CALL || dic->op == PCALL)
-    {
-      if (ic->op != SEND && ic->op != RETURN)
-       {
-         OP_SYMBOL (op)->ruonly = 1;
-         return dic;
-       }
-      dic = dic->next;
+    int i,key;
+    iCode *ic;
+
+    if (!IS_SYMOP(op) || !IS_ITEMP(op)) return 0;
+    if (OP_SYMBOL(op)->remat || OP_SYMBOL(op)->ruonly || OP_SYMBOL(op)->dptr)
+        return 0;
+
+    /* first check if any overlapping liverange has already been
+       assigned to this DPTR */
+    if (OP_SYMBOL(op)->clashes) {
+        for (i = 0 ; i < OP_SYMBOL(op)->clashes->size ; i++ ) {
+            symbol *sym;
+            if (bitVectBitValue(OP_SYMBOL(op)->clashes,i)) {
+                sym = hTabItemWithKey(liveRanges,i);
+                if (sym->dptr == dptr) return 0;
+            }
+        }
     }
 
-
-  /* otherwise check that the definition does
-     not contain any symbols in far space */
-  if (isOperandInFarSpace (IC_LEFT (dic)) ||
-      isOperandInFarSpace (IC_RIGHT (dic)) ||
-      IS_OP_RUONLY (IC_LEFT (ic)) ||
-      IS_OP_RUONLY (IC_RIGHT (ic)))
-    {
-      return NULL;
+    /* future for more dptrs */
+    if (dptr > 1) {
+        OP_SYMBOL(op)->dptr = dptr;
+        return 1;
     }
 
-  /* if pointer set then make sure the pointer
-     is one byte */
-  if (POINTER_SET (dic) &&
-      !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
-    return NULL;
-
-  if (POINTER_GET (dic) &&
-      !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
-    return NULL;
-
-  sic = dic;
-
-  /* also make sure the intervenening instructions
-     don't have any thing in far space */
-  for (dic = dic->next; dic && dic != ic; dic = dic->next)
-    {
+    /* DPTR1 is special since it is also used as a scratch by the backend .
+       so we walk thru the entire live range of this operand and make sure
+       DPTR1 will not be used by the backed . The logic here is to find out if
+       more than one operand in an icode is in far space then we give up : we
+       don't keep it live across functions for now
+    */
+
+    ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom);
+    for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
+         ic = hTabNextItem(iCodeSeqhTab,&key)) {
+        int nfs =0;
+
+        if (ic->op == CALL || ic->op == PCALL) return 0;
+
+        /* single operand icode are ok */
+        if (ic->op == IFX || ic->op == IPUSH)
+            continue ;
+
+        if (ic->op == SEND ) {
+            if (ic->argreg != 1 ) return 0;
+            else continue ;
+        }
+        /* two special cases first */
+        if (POINTER_GET(ic) && !isOperandEqual(IC_LEFT(ic),op)  && /* pointer get */
+            !OP_SYMBOL(IC_LEFT(ic))->ruonly                     && /* with result in far space */
+            (isOperandInFarSpace(IC_RESULT(ic)) &&
+             !isOperandInReg(IC_RESULT(ic)))) {
+            return 0;
+        }
+
+        if (POINTER_SET(ic) && !isOperandEqual(IC_RESULT(ic),op)        && /* pointer set */
+            !OP_SYMBOL(IC_RESULT(ic))->ruonly                           && /* with right in far space */
+            (isOperandInFarSpace(IC_RIGHT(ic)) &&
+             !isOperandInReg(IC_RIGHT(ic)))) {
+            return 0;
+        }
+
+        if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic))    && /* if symbol operand */
+            !isOperandEqual(IC_RESULT(ic),op)           && /* not the same as this */
+            ((isOperandInFarSpace(IC_RESULT(ic)) ||        /* in farspace or */
+              OP_SYMBOL(IC_RESULT(ic))->onStack)        && /* on the stack   */
+             !isOperandInReg(IC_RESULT(ic)))) {            /* and not in register */
+            nfs++;
+        }
+        /* same for left */
+        if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic))        && /* if symbol operand */
+            !isOperandEqual(IC_LEFT(ic),op)             && /* not the same as this */
+            ((isOperandInFarSpace(IC_LEFT(ic)) ||          /* in farspace or */
+              OP_SYMBOL(IC_LEFT(ic))->onStack)          && /* on the stack   */
+             !isOperandInReg(IC_LEFT(ic)))) {              /* and not in register */
+            nfs++;
+        }
+        /* same for right */
+        if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic))      && /* if symbol operand */
+            !isOperandEqual(IC_RIGHT(ic),op)            && /* not the same as this */
+            ((isOperandInFarSpace(IC_RIGHT(ic)) ||         /* in farspace or */
+              OP_SYMBOL(IC_RIGHT(ic))->onStack)         && /* on the stack   */
+             !isOperandInReg(IC_RIGHT(ic)))) {             /* and not in register */
+            nfs++;
+        }
+
+        // Check that no other ops in this range have been assigned to dptr1.
+        // I don't understand why this is not caught by the first check, above.
+        // But it isn't always, see bug 769624.
+        if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
+            (OP_SYMBOL(IC_RESULT(ic))->dptr == 1))
+        {
+            //fprintf(stderr, "dptr1 already in use in live range #1\n");
+            return 0;
+        }
+
+        if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) &&
+            (OP_SYMBOL(IC_LEFT(ic))->dptr == 1))
+        {
+            //fprintf(stderr, "dptr1 already in use in live range # 2\n");
+            return 0;
+        }
+
+        if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) &&
+            (OP_SYMBOL(IC_RIGHT(ic))->dptr == 1))
+        {
+            //fprintf(stderr, "dptr1 already in use in live range # 3\n");
+            return 0;
+        }
+
+        if (nfs && IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
+            OP_SYMBOL(IC_RESULT(ic))->ruonly) return 0;
+
+        if (nfs > 1) return 0;
+    }
+    OP_SYMBOL(op)->dptr = dptr;
+    return 1;
+}
 
-      /* if there is an intervening function call then no */
-      if (dic->op == CALL || dic->op == PCALL)
-       return NULL;
-      /* if pointer set then make sure the pointer
-         is one byte */
-      if (POINTER_SET (dic) &&
-         !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
-       return NULL;
+/*-----------------------------------------------------------------*/
+/* packRegsDPTRuse : - will reduce some registers for single Use */
+/*-----------------------------------------------------------------*/
+static iCode *
+packRegsDPTRuse (operand * op)
+{
+    /* go thru entire liveRange of this variable & check for
+       other possible usage of DPTR , if we don't find it the
+       assign this to DPTR (ruonly)
+    */
+    int i, key;
+    symbol *sym;
+    iCode *ic, *dic;
+    sym_link *type, *etype;
+
+    if (!IS_SYMOP(op) || !IS_ITEMP(op)) return NULL;
+    if (OP_SYMBOL(op)->remat || OP_SYMBOL(op)->ruonly) 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->ruonly) return NULL ;
+            }
+        }
+    }
 
-      if (POINTER_GET (dic) &&
-         !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
-       return NULL;
-
-      /* if address of & the result is remat the okay */
-      if (dic->op == ADDRESS_OF &&
-         OP_SYMBOL (IC_RESULT (dic))->remat)
-       continue;
-
-      /* if operand has size of three or more & this
-         operation is a '*','/' or '%' then 'b' may
-         cause a problem */
-      if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
-         getSize (operandType (op)) >= 3)
-       return NULL;
-
-      /* if left or right or result is in far space */
-      if (isOperandInFarSpace (IC_LEFT (dic)) ||
-         isOperandInFarSpace (IC_RIGHT (dic)) ||
-         isOperandInFarSpace (IC_RESULT (dic)) ||
-         IS_OP_RUONLY (IC_LEFT (dic)) ||
-         IS_OP_RUONLY (IC_RIGHT (dic)) ||
-         IS_OP_RUONLY (IC_RESULT (dic)))
-       {
-         return NULL;
-       }
-    }
-
-  OP_SYMBOL (op)->ruonly = 1;
-  return sic;
-#endif
+    /* no then go thru this guys live range */
+    dic = ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom);
+    for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
+         ic = hTabNextItem(iCodeSeqhTab,&key)) {
+
+        if (SKIP_IC3(ic)) continue;
+
+        /* if PCALL cannot be sure give up */
+        if (ic->op == PCALL) return NULL;
+
+        /* if SEND & not the first parameter then giveup */
+        if (ic->op == SEND && ic->argreg != 1 &&
+            ((isOperandInFarSpace(IC_LEFT(ic))  && !isOperandInReg(IC_LEFT(ic))) ||
+             isOperandEqual(op,IC_LEFT(ic)))) return NULL;
+
+        /* if CALL then make sure it is VOID || return value not used
+           or the return value is assigned to this one */
+        if (ic->op == CALL) {
+            if (OP_SYMBOL(IC_RESULT(ic))->liveTo ==
+                OP_SYMBOL(IC_RESULT(ic))->liveFrom) continue ;
+            etype = getSpec(type = operandType(IC_RESULT(ic)));
+            if (getSize(type) == 0 || isOperandEqual(op,IC_RESULT(ic)))
+                continue ;
+            return NULL ;
+        }
+
+        /* special case of add with a [remat] */
+        if (ic->op == '+' &&
+            OP_SYMBOL(IC_LEFT(ic))->remat &&
+            (isOperandInFarSpace(IC_RIGHT(ic)) &&
+             !isOperandInReg(IC_RIGHT(ic)))) return NULL ;
+
+        /* special cases  */
+        /* pointerGet */
+        if (POINTER_GET(ic) && !isOperandEqual(IC_LEFT(ic),op) &&
+            getSize(operandType(IC_LEFT(ic))) > 1 ) return NULL ;
+
+        /* pointerSet */
+        if (POINTER_SET(ic) && !isOperandEqual(IC_RESULT(ic),op) &&
+            getSize(operandType(IC_RESULT(ic))) > 1 ) return NULL;
+
+        /* conditionals can destroy 'b' - make sure B wont
+           be used in this one*/
+        if ((IS_CONDITIONAL(ic) || ic->op == '*' || ic->op == '/'  ||
+             ic->op == LEFT_OP || ic->op == RIGHT_OP ) &&
+            getSize(operandType(op)) > 3) return NULL;
+
+        /* if this is a cast to a bigger type */
+        if (ic->op==CAST) {
+          if (!IS_PTR(OP_SYM_TYPE(IC_RESULT(ic))) &&
+              getSize(OP_SYM_TYPE(IC_RESULT(ic))) >
+              getSize(OP_SYM_TYPE(IC_RIGHT(ic)))) {
+            return 0;
+          }
+        }
+
+        /* general case */
+        if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
+            !isOperandEqual(IC_RESULT(ic),op) &&
+            ( ( ( isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->onStack) &&
+                !isOperandInReg(IC_RESULT(ic))) ||
+             OP_SYMBOL(IC_RESULT(ic))->ruonly)) return NULL;
+
+        if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) &&
+            !isOperandEqual(IC_RIGHT(ic),op) &&
+            (OP_SYMBOL(IC_RIGHT(ic))->liveTo >= ic->seq ||
+             IS_TRUE_SYMOP(IC_RIGHT(ic))               ||
+             OP_SYMBOL(IC_RIGHT(ic))->ruonly) &&
+            ( ( isOperandInFarSpace(IC_RIGHT(ic)) || OP_SYMBOL(IC_RIGHT(ic))->onStack) &&
+                !isOperandInReg(IC_RIGHT(ic))) ) return NULL;
+
+        if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) &&
+            !isOperandEqual(IC_LEFT(ic),op) &&
+            (OP_SYMBOL(IC_LEFT(ic))->liveTo >= ic->seq ||
+             IS_TRUE_SYMOP(IC_LEFT(ic))               ||
+             OP_SYMBOL(IC_LEFT(ic))->ruonly) &&
+            ( ( isOperandInFarSpace(IC_LEFT(ic)) || OP_SYMBOL(IC_LEFT(ic))->onStack) &&
+                !isOperandInReg(IC_LEFT(ic))) ) return NULL;
+
+        if (IC_LEFT(ic) && IC_RIGHT(ic) &&
+            IS_ITEMP(IC_LEFT(ic)) && IS_ITEMP(IC_RIGHT(ic)) &&
+            (isOperandInFarSpace(IC_LEFT(ic)) && !isOperandInReg(IC_LEFT(ic))) &&
+            (isOperandInFarSpace(IC_RIGHT(ic)) && !isOperandInReg(IC_RIGHT(ic))))
+            return NULL;
+    }
+    OP_SYMBOL(op)->ruonly = 1;
+    if (OP_SYMBOL(op)->usl.spillLoc) {
+        if (OP_SYMBOL(op)->spillA)
+            OP_SYMBOL(op)->usl.spillLoc->allocreq--;
+        OP_SYMBOL(op)->usl.spillLoc = NULL;
+    }
+    return dic;
 }
 
 /*-----------------------------------------------------------------*/
@@ -2026,7 +2724,7 @@ isBitwiseOptimizable (iCode * ic)
   sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
 
   /* bitwise operations are considered optimizable
-     under the following conditions (Jean-Louis VERN) 
+     under the following conditions (Jean-Louis VERN)
 
      x & lit
      bit & bit
@@ -2038,7 +2736,7 @@ isBitwiseOptimizable (iCode * ic)
      bit | bit
      bit | x
    */
-  if ( IS_LITERAL (rtype) ||
+  if (IS_LITERAL (rtype) ||
       (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
     return TRUE;
   else
@@ -2053,6 +2751,22 @@ 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 we are calling a reentrant function that has stack parameters */
+  if (ic->op == CALL &&
+       IFFUNC_ISREENT(operandType(IC_LEFT(ic))) &&
+       FUNC_HASSTACKPARM(operandType(IC_LEFT(ic))))
+      return;
+
+  if (ic->op == PCALL &&
+       IFFUNC_ISREENT(operandType(IC_LEFT(ic))->next) &&
+       FUNC_HASSTACKPARM(operandType(IC_LEFT(ic))->next))
+      return;
+
   /* if + or - then it has to be one byte result */
   if ((ic->op == '+' || ic->op == '-')
       && getSize (operandType (IC_RESULT (ic))) > 1)
@@ -2084,7 +2798,7 @@ packRegsForAccUse (iCode * ic)
 
   /* and the usage immediately follows this iCode */
   if (!(uic = hTabItemWithKey (iCodehTab,
-                              bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
+                               bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
     return;
 
   if (ic->next != uic)
@@ -2110,8 +2824,8 @@ packRegsForAccUse (iCode * ic)
       uic->op != RIGHT_OP)
     return;
 
-  /* if used in ^ operation then make sure right is not a 
-     literl */
+  /* if used in ^ operation then make sure right is not a
+     literal */
   if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
     return;
 
@@ -2128,8 +2842,7 @@ packRegsForAccUse (iCode * ic)
 
   /* 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)
+  if (isOperandOnStack(IC_RESULT(uic)))
     return;
 
   /* if either one of them in far space then we cannot */
@@ -2150,25 +2863,17 @@ packRegsForAccUse (iCode * ic)
       IC_LEFT (uic)->key != IC_RESULT (ic)->key)
     return;
 
-  /* if one of them is a literal then we can */
-  if ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) ||
-      (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic))))
-    {
-      OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
-      return;
-    }
-
   /* if the other one is not on stack then we can */
   if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
       (IS_ITEMP (IC_RIGHT (uic)) ||
        (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
-       !OP_SYMBOL (IC_RIGHT (uic))->onStack)))
+        !OP_SYMBOL (IC_RIGHT (uic))->onStack)))
     goto accuse;
 
   if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key &&
       (IS_ITEMP (IC_LEFT (uic)) ||
        (IS_TRUE_SYMOP (IC_LEFT (uic)) &&
-       !OP_SYMBOL (IC_LEFT (uic))->onStack)))
+        !OP_SYMBOL (IC_LEFT (uic))->onStack)))
     goto accuse;
 
   return;
@@ -2176,19 +2881,19 @@ packRegsForAccUse (iCode * ic)
 accuse:
   OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
 
-
 }
 
 /*-----------------------------------------------------------------*/
-/* packForPush - hueristics to reduce iCode for pushing            */
+/* packForPush - heuristics to reduce iCode for pushing            */
 /*-----------------------------------------------------------------*/
 static void
-packForPush (iCode * ic, eBBlock * ebp)
+packForPush (iCode * ic, eBBlock ** ebpp, int blockno)
 {
   iCode *dic, *lic;
   bitVect *dbv;
+  struct eBBlock * ebp = ebpp[blockno];
 
-  if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
+  if ((ic->op != IPUSH && ic->op != SEND) || !IS_ITEMP (IC_LEFT (ic)))
     return;
 
   /* must have only definition & one usage */
@@ -2198,24 +2903,50 @@ packForPush (iCode * ic, eBBlock * ebp)
 
   /* find the definition */
   if (!(dic = hTabItemWithKey (iCodehTab,
-                              bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
+                               bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
     return;
 
   if (dic->op != '=' || POINTER_SET (dic))
     return;
 
+  if (dic->eBBlockNum != ic->eBBlockNum) return ;
+
   /* make sure the right side does not have any definitions
      inbetween */
   dbv = OP_DEFS(IC_RIGHT(dic));
-  for (lic = ic; lic != dic ; lic = lic->prev) {
-         if (bitVectBitValue(dbv,lic->key)) return ;
+  for (lic = ic; lic && lic != dic ; lic = lic->prev) {
+          if (bitVectBitValue (dbv, lic->key))
+            return;
   }
+  /* make sure they have the same type */
+  if (IS_SPEC(operandType(IC_LEFT(ic))))
+  {
+    sym_link *itype=operandType(IC_LEFT(ic));
+    sym_link *ditype=operandType(IC_RIGHT(dic));
 
+    if (SPEC_USIGN(itype)!=SPEC_USIGN(ditype) ||
+        SPEC_LONG(itype)!=SPEC_LONG(ditype))
+      return;
+  }
+  /* extend the live range of replaced operand if needed */
+  if (OP_SYMBOL(IC_RIGHT(dic))->liveTo < OP_SYMBOL(IC_LEFT(ic))->liveTo) {
+          OP_SYMBOL(IC_RIGHT(dic))->liveTo = OP_SYMBOL(IC_LEFT(ic))->liveTo;
+          OP_SYMBOL(IC_RIGHT(dic))->clashes =
+              bitVectUnion(OP_SYMBOL(IC_RIGHT(dic))->clashes,
+                           OP_SYMBOL(IC_LEFT(ic))->clashes);
+  }
+  for (lic = ic; lic && lic != dic; lic = lic->prev)
+    {
+      bitVectUnSetBit (lic->rlive, IC_LEFT (ic)->key);
+      if (IS_ITEMP (IC_RIGHT (dic)))
+        bitVectSetBit (lic->rlive, IC_RIGHT (dic)->key);
+    }
   /* we now we know that it has one & only one def & use
      and the that the definition is an assignment */
   IC_LEFT (ic) = IC_RIGHT (dic);
 
   remiCodeFromeBBlock (ebp, dic);
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
   hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
 }
 
@@ -2224,14 +2955,14 @@ packForPush (iCode * ic, eBBlock * ebp)
 /*                   pressure                                      */
 /*-----------------------------------------------------------------*/
 static void
-packRegisters (eBBlock * ebp)
+packRegisters (eBBlock ** ebpp, int blockno)
 {
   iCode *ic;
   int change = 0;
+  eBBlock *ebp = ebpp[blockno];
 
   while (1)
     {
-
       change = 0;
 
       /* look for assignments of the form */
@@ -2239,221 +2970,313 @@ packRegisters (eBBlock * ebp)
       /*       ....                       */
       /* TrueSym := iTempNN:1             */
       for (ic = ebp->sch; ic; ic = ic->next)
-       {
-
-
-         /* find assignment of the form TrueSym := iTempNN:1 */
-         if (ic->op == '=' && !POINTER_SET (ic))
-           change += packRegsForAssign (ic, ebp);
-       }
+        {
+          /* find assignment of the form TrueSym := iTempNN:1 */
+          if (ic->op == '=' && !POINTER_SET (ic))
+            change += packRegsForAssign (ic, ebp);
+        }
 
       if (!change)
-       break;
+        break;
     }
 
   for (ic = ebp->sch; ic; ic = ic->next)
     {
-
-      /* if this is an itemp & result of a address of a true sym 
+      /* Fix for bug #979599:   */
+      /* P0 &= ~1;              */
+
+      /* Look for two subsequent iCodes with */
+      /*   iTemp := _c;         */
+      /*   _c = iTemp & op;     */
+      /* and replace them by    */
+      /*   iTemp := _c;         */
+      /*   _c = _c & op;        */
+      if ((ic->op == BITWISEAND || ic->op == '|' || ic->op == '^') &&
+          ic->prev &&
+          ic->prev->op == '=' &&
+          IS_ITEMP (IC_LEFT (ic)) &&
+          IC_LEFT (ic) == IC_RESULT (ic->prev) &&
+          isOperandEqual (IC_RESULT(ic), IC_RIGHT(ic->prev)))
+        {
+          iCode* ic_prev = ic->prev;
+          symbol* prev_result_sym = OP_SYMBOL (IC_RESULT (ic_prev));
+
+          ReplaceOpWithCheaperOp (&IC_LEFT (ic), IC_RESULT (ic));
+          if (IC_RESULT (ic_prev) != IC_RIGHT (ic))
+            {
+              bitVectUnSetBit (OP_USES (IC_RESULT (ic_prev)), ic->key);
+              if (/*IS_ITEMP (IC_RESULT (ic_prev)) && */
+                  prev_result_sym->liveTo == ic->seq)
+                {
+                  prev_result_sym->liveTo = ic_prev->seq;
+                }
+            }
+          bitVectSetBit (OP_USES (IC_RESULT (ic)), ic->key);
+
+          bitVectSetBit (ic->rlive, IC_RESULT (ic)->key);
+
+          if (bitVectIsZero (OP_USES (IC_RESULT (ic_prev))))
+            {
+              bitVectUnSetBit (ic->rlive, IC_RESULT (ic)->key);
+              bitVectUnSetBit (OP_DEFS (IC_RESULT (ic_prev)), ic_prev->key);
+              remiCodeFromeBBlock (ebp, ic_prev);
+              hTabDeleteItem (&iCodehTab, ic_prev->key, ic_prev, DELETE_ITEM, NULL);
+            }
+        }
+
+      /* if this is an itemp & result of an address of a true sym
          then mark this as rematerialisable   */
       if (ic->op == ADDRESS_OF &&
-         IS_ITEMP (IC_RESULT (ic)) &&
-         IS_TRUE_SYMOP (IC_LEFT (ic)) &&
-         bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
-         !OP_SYMBOL (IC_LEFT (ic))->onStack)
-       {
-
-         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
-         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
-         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
-
-       }
+          IS_ITEMP (IC_RESULT (ic)) &&
+          IS_TRUE_SYMOP (IC_LEFT (ic)) &&
+          bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
+          !OP_SYMBOL (IC_LEFT (ic))->onStack)
+        {
+
+          OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+          OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+          OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+
+        }
+
+        /* if this is an itemp & used as a pointer
+           & assigned to a literal then remat */
+        if (IS_ASSIGN_ICODE(ic) &&
+            IS_ITEMP(IC_RESULT(ic)) &&
+            bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
+            isOperandLiteral(IC_RIGHT(ic)))
+        {
+          OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+          OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+          OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+        }
 
       /* if straight assignment then carry remat flag if
          this is the only definition */
       if (ic->op == '=' &&
-         !POINTER_SET (ic) &&
-         IS_SYMOP (IC_RIGHT (ic)) &&
-         OP_SYMBOL (IC_RIGHT (ic))->remat &&
-         bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
-       {
-
-         OP_SYMBOL (IC_RESULT (ic))->remat =
-           OP_SYMBOL (IC_RIGHT (ic))->remat;
-         OP_SYMBOL (IC_RESULT (ic))->rematiCode =
-           OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
-       }
-
-      /* if this is a +/- operation with a rematerizable 
+          !POINTER_SET (ic) &&
+          IS_SYMOP (IC_RIGHT (ic)) &&
+          OP_SYMBOL (IC_RIGHT (ic))->remat &&
+          !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode) &&
+          bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
+        {
+          OP_SYMBOL (IC_RESULT (ic))->remat =
+            OP_SYMBOL (IC_RIGHT (ic))->remat;
+          OP_SYMBOL (IC_RESULT (ic))->rematiCode =
+            OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
+        }
+
+      /* if cast to a generic pointer & the pointer being
+         cast is remat, then we can remat this cast as well */
+      if (ic->op == CAST &&
+          IS_SYMOP(IC_RIGHT(ic)) &&
+          !OP_SYMBOL(IC_RESULT(ic))->isreqv &&
+          OP_SYMBOL(IC_RIGHT(ic))->remat )
+        {
+          sym_link *to_type = operandType(IC_LEFT(ic));
+          sym_link *from_type = operandType(IC_RIGHT(ic));
+          if (IS_GENPTR(to_type) && IS_PTR(from_type))
+            {
+                      OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+                      OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+                      OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+              }
+      }
+
+      /* if this is a +/- operation with a rematerizable
          then mark this as rematerializable as well */
       if ((ic->op == '+' || ic->op == '-') &&
-         (IS_SYMOP (IC_LEFT (ic)) &&
-          IS_ITEMP (IC_RESULT (ic)) &&
-          OP_SYMBOL (IC_LEFT (ic))->remat &&
-          bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
-          IS_OP_LITERAL (IC_RIGHT (ic))))
-       {
-
-         //int i = operandLitValue(IC_RIGHT(ic));
-         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
-         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
-         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
-       }
+          (IS_SYMOP (IC_LEFT (ic)) &&
+           IS_ITEMP (IC_RESULT (ic)) &&
+           OP_SYMBOL (IC_LEFT (ic))->remat &&
+           (!IS_SYMOP (IC_RIGHT (ic)) || !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode)) &&
+           bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
+           IS_OP_LITERAL (IC_RIGHT (ic))))
+        {
+
+          //int i = operandLitValue(IC_RIGHT(ic));
+          OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+          OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+          OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+        }
 
       /* mark the pointer usages */
-      if (POINTER_SET (ic))
-       OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
+      if (POINTER_SET (ic) && IS_SYMOP (IC_RESULT (ic)))
+        OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
+
+      if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic)))
+        OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
+
+      if (ic->op == RETURN && IS_SYMOP (IC_LEFT(ic)))
+          OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
+
+      if (ic->op == RECEIVE && ic->argreg == 1 &&
+          IS_SYMOP (IC_RESULT (ic)) &&
+          getSize (operandType(IC_RESULT(ic))) <= 3)
+          OP_SYMBOL (IC_RESULT(ic))->uptr = 1;
 
-      if (POINTER_GET (ic))
-       OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
+      if (ic->op == SEND && ic->argreg == 1 &&
+          IS_SYMOP(IC_LEFT(ic)) &&
+          getSize (aggrToPtr(operandType(IC_LEFT(ic)),FALSE)) <= 3)
+          OP_SYMBOL (IC_LEFT(ic))->uptr = 1;
 
       if (!SKIP_IC2 (ic))
-       {
-         /* if we are using a symbol on the stack
-            then we should say ds390_ptrRegReq */
-         if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
-           ds390_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ||
-                                OP_SYMBOL (IC_COND (ic))->iaccess) ? 1 : 0);
-         else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic)))
-           ds390_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ||
-                             OP_SYMBOL (IC_JTCOND (ic))->iaccess) ? 1 : 0);
-         else
-           {
-             if (IS_SYMOP (IC_LEFT (ic)))
-               ds390_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ||
-                               OP_SYMBOL (IC_LEFT (ic))->iaccess) ? 1 : 0);
-             if (IS_SYMOP (IC_RIGHT (ic)))
-               ds390_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ||
-                              OP_SYMBOL (IC_RIGHT (ic))->iaccess) ? 1 : 0);
-             if (IS_SYMOP (IC_RESULT (ic)))
-               ds390_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ||
-                             OP_SYMBOL (IC_RESULT (ic))->iaccess) ? 1 : 0);
-           }
-       }
+        {
+          /* if we are using a symbol on the stack
+             then we should say ds390_ptrRegReq */
+          if (options.useXstack && ic->parmPush
+              && (ic->op == IPUSH || ic->op == IPOP))
+            ds390_ptrRegReq++;
+          if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
+                  ds390_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ? !options.stack10bit : 0) +
+                                      OP_SYMBOL (IC_COND (ic))->iaccess +
+                                      (SPEC_OCLS(OP_SYMBOL (IC_COND (ic))->etype) == idata));
+          else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic)))
+                  ds390_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ? !options.stack10bit : 0) +
+                                      OP_SYMBOL (IC_JTCOND (ic))->iaccess +
+                                      (SPEC_OCLS(OP_SYMBOL (IC_JTCOND (ic))->etype) == idata));
+          else
+            {
+              if (IS_SYMOP (IC_LEFT (ic)))
+                      ds390_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ? !options.stack10bit : 0) +
+                                          OP_SYMBOL (IC_LEFT (ic))->iaccess +
+                                          (SPEC_OCLS(OP_SYMBOL (IC_LEFT (ic))->etype) == idata));
+              if (IS_SYMOP (IC_RIGHT (ic)))
+                      ds390_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ? !options.stack10bit : 0) +
+                                          OP_SYMBOL (IC_RIGHT (ic))->iaccess +
+                                          (SPEC_OCLS(OP_SYMBOL (IC_RIGHT (ic))->etype) == idata));
+              if (IS_SYMOP (IC_RESULT (ic)))
+                      ds390_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ? !options.stack10bit : 0) +
+                                          OP_SYMBOL (IC_RESULT (ic))->iaccess +
+                                          (SPEC_OCLS(OP_SYMBOL (IC_RESULT (ic))->etype) == idata));
+            }
+        }
 
-#if 0
-      /* if the condition of an if instruction
-         is defined in the previous instruction then
-         mark the itemp as a conditional */
-      if ((IS_CONDITIONAL (ic) ||
-          (IS_BITWISE_OP(ic) && isBitwiseOptimizable(ic))) &&
-         ic->next && ic->next->op == IFX &&
-         isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
-         OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
-       {
-
-         OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
-         continue;
-       }
-#else
       /* if the condition of an if instruction
          is defined in the previous instruction and
-        this is the only usage then
+         this is the only usage then
          mark the itemp as a conditional */
       if ((IS_CONDITIONAL (ic) ||
-          (IS_BITWISE_OP(ic) && isBitwiseOptimizable (ic))) &&
-         ic->next && ic->next->op == IFX &&
-         bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 &&
-         isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
-         OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
-       {
-         OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
-         continue;
-       }
-#endif
-
+           (IS_BITWISE_OP(ic) && isBitwiseOptimizable (ic))) &&
+          ic->next && ic->next->op == IFX &&
+          bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 &&
+          isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
+          OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
+        {
+          OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
+          continue;
+        }
+#if 1
       /* reduce for support function calls */
       if (ic->supportRtn || ic->op == '+' || ic->op == '-')
-       packRegsForSupport (ic, ebp);
-
+        packRegsForSupport (ic, ebp);
+#endif
       /* 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);
+         can be eliminated for return statements . Can be elminated for the first SEND */
+      if ((ic->op == RETURN ||
+           ((ic->op == SEND || ic->op == RECEIVE)&& ic->argreg == 1)) &&
+          !isOperandInFarSpace (IC_LEFT (ic)) &&
+          !options.model) {
+
+          packRegsDPTRuse (IC_LEFT (ic));
+      }
+
+      if (ic->op == CALL) {
+          sym_link *ftype = operandType(IC_LEFT(ic));
+          if (getSize(operandType(IC_RESULT(ic))) <= 4 &&
+              !IFFUNC_ISBUILTIN(ftype)) {
+              packRegsDPTRuse (IC_RESULT (ic));
+          }
+      }
 
       /* if pointer set & left has a size more than
          one and right is not in far space */
       if (POINTER_SET (ic) &&
-         !isOperandInFarSpace (IC_RIGHT (ic)) &&
-         !OP_SYMBOL (IC_RESULT (ic))->remat &&
-         !IS_OP_RUONLY (IC_RIGHT (ic)) &&
-         getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
+          !isOperandInFarSpace (IC_RIGHT (ic)) &&
+          IS_SYMOP (IC_RESULT (ic)) &&
+          !OP_SYMBOL (IC_RESULT (ic))->remat &&
+          !IS_OP_RUONLY (IC_RIGHT (ic)) &&
+          getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1) {
 
-       packRegsForOneuse (ic, IC_RESULT (ic), ebp);
+          packRegsDPTRuse (IC_RESULT (ic));
+      }
 
       /* if pointer get */
       if (POINTER_GET (ic) &&
-         !isOperandInFarSpace (IC_RESULT (ic)) &&
-         !OP_SYMBOL (IC_LEFT (ic))->remat &&
-         !IS_OP_RUONLY (IC_RESULT (ic)) &&
-         getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
-
-       packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+          !isOperandInFarSpace (IC_RESULT (ic)) &&
+          IS_SYMOP (IC_LEFT (ic)) &&
+          !OP_SYMBOL (IC_LEFT (ic))->remat &&
+          !IS_OP_RUONLY (IC_RESULT (ic)) &&
+          getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1) {
 
+          packRegsDPTRuse (IC_LEFT (ic));
+      }
 
-      /* if this is cast for intergral promotion then
-         check if only use of  the definition of the 
+      /* if this is cast for intergral promotion then
+         check if it's the only use of  the definition of the
          operand being casted/ if yes then replace
-         the result of that arithmetic operation with 
+         the result of that arithmetic operation with
          this result and get rid of the cast */
       if (ic->op == CAST)
-       {
-         sym_link *fromType = operandType (IC_RIGHT (ic));
-         sym_link *toType = operandType (IC_LEFT (ic));
-
-         if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
-             getSize (fromType) != getSize (toType) &&
-             SPEC_USIGN (fromType) == SPEC_USIGN (toType))
-           {
-
-             iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
-             if (dic)
-               {
-                 if (IS_ARITHMETIC_OP (dic))
-                   {
-                     IC_RESULT (dic) = IC_RESULT (ic);
-                     remiCodeFromeBBlock (ebp, ic);
-                     hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
-                     OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
-                     ic = ic->prev;
-                   }
-                 else
-                   OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
-               }
-           }
-         else
-           {
-
-             /* if the type from and type to are the same
-                then if this is the only use then packit */
-             if (checkType (operandType (IC_RIGHT (ic)),
-                            operandType (IC_LEFT (ic))) == 1)
-               {
-                 iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
-                 if (dic)
-                   {
-                     IC_RESULT (dic) = IC_RESULT (ic);
-                     remiCodeFromeBBlock (ebp, ic);
-                     hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
-                     OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
-                     ic = ic->prev;
-                   }
-               }
-           }
-       }
-
-      /* pack for PUSH 
+        {
+          sym_link *fromType = operandType (IC_RIGHT (ic));
+          sym_link *toType = operandType (IC_LEFT (ic));
+
+          if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
+              getSize (fromType) != getSize (toType) &&
+              SPEC_USIGN (fromType) == SPEC_USIGN (toType))
+            {
+
+              iCode *dic = packRegsDPTRuse (IC_RIGHT (ic));
+              if (dic)
+                {
+                  if (IS_ARITHMETIC_OP (dic))
+                    {
+                      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+                      IC_RESULT (dic) = IC_RESULT (ic);
+                      remiCodeFromeBBlock (ebp, ic);
+                      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);
+                      ic = ic->prev;
+                    }
+                  else
+                    OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
+                }
+            }
+          else
+            {
+
+              /* if the type from and type to are the same
+                 then if this is the only use then packit */
+              if (compareType (operandType (IC_RIGHT (ic)),
+                             operandType (IC_LEFT (ic))) == 1)
+                {
+                  iCode *dic = packRegsDPTRuse (IC_RIGHT (ic));
+                  if (dic)
+                    {
+                      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+                      IC_RESULT (dic) = IC_RESULT (ic);
+                      remiCodeFromeBBlock (ebp, ic);
+                      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);
+                      ic = ic->prev;
+                    }
+                }
+            }
+        }
+
+      /* pack for PUSH
          iTempNN := (some variable in farspace) V1
          push iTempNN ;
          -------------
          push V1
        */
-      if (ic->op == IPUSH)
-       {
-         packForPush (ic, ebp);
-       }
+      if (ic->op == IPUSH || ic->op == SEND)
+        {
+          packForPush (ic, ebpp, blockno);
+        }
 
 
       /* pack registers for accumulator use, when the
@@ -2465,17 +3288,15 @@ packRegisters (eBBlock * ebp)
          we can leave the result of this operation in acc:b
          combination */
       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);
-
+           || IS_CONDITIONAL(ic)
+           || IS_BITWISE_OP (ic)
+           || ic->op == LEFT_OP || ic->op == RIGHT_OP
+           || (ic->op == ADDRESS_OF && isOperandOnStack (IC_LEFT (ic)))
+          ) &&
+          IS_ITEMP (IC_RESULT (ic)) &&
+          getSize (operandType (IC_RESULT (ic))) <= 2)
+
+        packRegsForAccUse (ic);
     }
 }
 
@@ -2483,35 +3304,55 @@ packRegisters (eBBlock * ebp)
 /* assignRegisters - assigns registers to each live range as need  */
 /*-----------------------------------------------------------------*/
 void
-ds390_assignRegisters (eBBlock ** ebbs, int count)
+ds390_assignRegisters (ebbIndex * ebbi)
 {
+  eBBlock ** ebbs = ebbi->bbOrder;
+  int count = ebbi->count;
   iCode *ic;
   int i;
 
+  setToNull ((void *) &_G.funcrUsed);
+  setToNull ((void *) &_G.regAssigned);
+  setToNull ((void *) &_G.totRegAssigned);
   setToNull ((void *) &_G.funcrUsed);
   ds390_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
-  /* if not register extentions then reduce number
-     of registers */
-  if (options.regExtend)
-    ds390_nRegs = 13;
+  if ((currFunc && IFFUNC_ISREENT (currFunc->type)) || options.stackAuto)
+    {
+      ds390_nBitRegs = 8;
+    }
   else
-    ds390_nRegs = 8;
+    {
+      ds390_nBitRegs = 0;
+    }
+  ds390_nRegs = 12 + ds390_nBitRegs;
+  _G.allBitregs = findAllBitregs ();
 
+  if (options.model != MODEL_FLAT24)
+    options.stack10bit = 0;
   /* change assignments this will remove some
      live ranges reducing some register pressure */
   for (i = 0; i < count; i++)
-    packRegisters (ebbs[i]);
+    packRegisters (ebbs, i);
+
+  /* liveranges probably changed by register packing
+     so we compute them again */
+  recomputeLiveRanges (ebbs, count);
 
   if (options.dump_pack)
-    dumpEbbsToFileExt (".dumppack", ebbs, count);
+    dumpEbbsToFileExt (DUMP_PACK, ebbi);
 
-  /* first determine for each live range the number of 
+  /* first determine for each live range the number of
      registers & the type of registers required for each */
   regTypeNum ();
 
   /* and serially allocate registers */
   serialRegAssign (ebbs, count);
 
+  ds390_nRegs = 8;
+  freeAllRegs ();
+  fillGaps();
+  ds390_nRegs = 12 + ds390_nBitRegs;
+
   /* if stack was extended then tell the user */
   if (_G.stackExtend)
     {
@@ -2532,10 +3373,22 @@ ds390_assignRegisters (eBBlock ** ebbs, int count)
   createRegMask (ebbs, count);
 
   /* redo that offsets for stacked automatic variables */
-  redoStackOffsets ();
+  if (currFunc)
+    redoStackOffsets ();
+
+  /* make sure r0 & r1 are flagged as used if they might be used */
+  /* as pointers */
+  if (currFunc && ds390_ptrRegReq)
+    {
+      currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, R0_IDX);
+      currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, R1_IDX);
+    }
 
   if (options.dump_rassgn)
-    dumpEbbsToFileExt (".dumprassgn", ebbs, count);
+    {
+    dumpEbbsToFileExt (DUMP_RASSGN, ebbi);
+    dumpLiveRanges (DUMP_LRANGE, liveRanges);
+  }
 
   /* do the overlaysegment stuff SDCCmem.c */
   doOverlays (ebbs, count);
@@ -2543,15 +3396,15 @@ ds390_assignRegisters (eBBlock ** ebbs, int count)
   /* now get back the chain */
   ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
 
-
   gen390Code (ic);
 
   /* free up any _G.stackSpil locations allocated */
   applyToSet (_G.stackSpil, deallocStackSpil);
   _G.slocNum = 0;
-  setToNull ((void **) &_G.stackSpil);
-  setToNull ((void **) &_G.spiltSet);
+  setToNull ((void *) &_G.stackSpil);
+  setToNull ((void *) &_G.spiltSet);
   /* mark all registers as free */
+  ds390_nRegs = 8;
   freeAllRegs ();
 
   return;