More fixes for DPTR use
[fw/sdcc] / src / ds390 / ralloc.c
index 06f1be1c6ed3cb043e6739e27ae6ea98e8f0628d..27b8c1e4b5940dc8a429a7911c91585e5a77797f 100644 (file)
@@ -42,6 +42,7 @@ 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 */
@@ -78,6 +79,8 @@ regs regs390[] =
 };
 int ds390_nRegs = 13;
 static void spillThis (symbol *);
+static void freeAllRegs ();
+static iCode * packRegsDPTRuse (operand *);
 
 /*-----------------------------------------------------------------*/
 /* allocReg - allocates register of given type                     */
@@ -142,6 +145,15 @@ freeReg (regs * reg)
   reg->isFree = 1;
 }
 
+/*-----------------------------------------------------------------*/
+/* useReg - marks a register  as used                              */
+/*-----------------------------------------------------------------*/
+static void
+useReg (regs * reg)
+{
+  reg->isFree = 0;
+}
+
 
 /*-----------------------------------------------------------------*/
 /* nFreeRegs - returns number of free registers                    */
@@ -201,6 +213,16 @@ allDefsOutOfRange (bitVect * defs, int fseq, int toseq)
   return TRUE;
 }
 
+/*-----------------------------------------------------------------*/
+/* isOperandInReg - returns true if operand is currently in regs   */
+/*-----------------------------------------------------------------*/
+static int isOperandInReg(operand *op)
+{
+    if (!IS_SYMOP(op)) return 0;
+
+    return bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(op)->key);
+}
+
 /*-----------------------------------------------------------------*/
 /* computeSpillable - given a point find the spillable live ranges */
 /*-----------------------------------------------------------------*/
@@ -482,7 +504,7 @@ createStackSpil (symbol * sym)
   if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
     {
       /* found a free one : just update & return */
-      sym->usl.spillLoc = sloc;
+      sym->usl.spillLoc = sloc;      
       sym->stackSpil = 1;
       sloc->isFree = 0;
       addSetHead (&sloc->usl.itmpStack, sym);
@@ -511,6 +533,8 @@ createStackSpil (symbol * sym)
     SPEC_SCLS (sloc->etype) = S_XDATA;
   }
   SPEC_EXTR (sloc->etype) = 0;
+  SPEC_STAT (sloc->etype) = 0;
+  SPEC_VOLATILE(sloc->etype) = 0;
 
   /* we don't allow it to be allocated`
      onto the external stack since : so we
@@ -596,10 +620,11 @@ spillThis (symbol * sym)
 
 
   /* mark it has spilt & put it in the spilt set */
-  sym->isspilt = 1;
+  sym->isspilt = sym->spillA = 1;
   _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
 
   bitVectUnSetBit (_G.regAssigned, sym->key);
+  bitVectUnSetBit (_G.totRegAssigned, sym->key);
 
   for (i = 0; i < sym->nRegs; i++)
 
@@ -619,7 +644,7 @@ spillThis (symbol * sym)
     }
 
   if (sym->usl.spillLoc && !sym->remat)
-    sym->usl.spillLoc->allocreq = 1;
+    sym->usl.spillLoc->allocreq++;
   return;
 }
 
@@ -653,7 +678,7 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
                           sym->usl.spillLoc->name));
       sym->spildir = 1;
       /* mark it as allocation required */
-      sym->usl.spillLoc->allocreq = 1;
+      sym->usl.spillLoc->allocreq++;
       return sym;
     }
 
@@ -698,7 +723,7 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
 
       sym = leastUsedLR (selectS);
       /* mark this as allocation required */
-      sym->usl.spillLoc->allocreq = 1;
+      sym->usl.spillLoc->allocreq++;
       return sym;
     }
 
@@ -707,7 +732,7 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
     {
 
       sym = leastUsedLR (selectS);
-      sym->usl.spillLoc->allocreq = 1;
+      sym->usl.spillLoc->allocreq++;
       return sym;
     }
 
@@ -719,7 +744,7 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
 
       /* return a created spil location */
       sym = createStackSpil (leastUsedLR (selectS));
-      sym->usl.spillLoc->allocreq = 1;
+      sym->usl.spillLoc->allocreq++;
       return sym;
     }
 
@@ -743,12 +768,13 @@ spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
   ssym = selectSpil (ic, ebp, forSym);
 
   /* mark it as spilt */
-  ssym->isspilt = 1;
+  ssym->isspilt = ssym->spillA = 1;
   _G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key);
 
   /* mark it as not register assigned &
      take it away from the set */
   bitVectUnSetBit (_G.regAssigned, ssym->key);
+  bitVectUnSetBit (_G.totRegAssigned, ssym->key);
 
   /* mark the registers as free */
   for (i = 0; i < ssym->nRegs; i++)
@@ -849,6 +875,41 @@ tryAgain:
   goto tryAgain;
 }
 
+/*-----------------------------------------------------------------*/
+/* getRegPtrNoSpil - get it cannot split                           */
+/*-----------------------------------------------------------------*/
+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);
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegGprNoSpil - get it cannot split                           */
+/*-----------------------------------------------------------------*/
+static regs *getRegGprNoSpil()
+{
+
+  regs *reg;
+  if ((reg = allocReg (REG_GPR)))
+    return reg;
+
+  if (!ds390_ptrRegReq)
+    if ((reg = allocReg (REG_PTR)))
+      return reg;
+
+  assert(0);
+}
+
 /*-----------------------------------------------------------------*/
 /* symHasReg - symbol has a given register                         */
 /*-----------------------------------------------------------------*/
@@ -948,6 +1009,7 @@ deassignLRs (iCode * ic, eBBlock * ebp)
                  result->regs[i] = getRegGpr (ic, ebp, result);
 
              _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
+             _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, result->key);
 
            }
 
@@ -977,10 +1039,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--;
 
@@ -1030,15 +1093,16 @@ 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 */
@@ -1059,8 +1123,10 @@ xchgPositions:
       regs *tmp = result->regs[i];
       result->regs[i] = result->regs[j];
       result->regs[j] = tmp;
+      change ++;
       goto again;
     }
+  return change ;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1094,7 +1160,7 @@ serialRegAssign (eBBlock ** ebbs, int count)
          /* if result is present && is a true symbol */
          if (IC_RESULT (ic) && ic->op != IFX &&
              IS_TRUE_SYMOP (IC_RESULT (ic)))
-           OP_SYMBOL (IC_RESULT (ic))->allocreq = 1;
+           OP_SYMBOL (IC_RESULT (ic))->allocreq++;
 
          /* take away registers from live
             ranges that end at this instruction */
@@ -1165,8 +1231,11 @@ serialRegAssign (eBBlock ** ebbs, int count)
                        /* if none of the liveRanges have a spillLocation then better
                           to spill this one than anything else already assigned to registers */
                        if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
-                           spillThis (sym);
-                           continue;
+                           /* 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;
+                           }
                        }
                    }
                }
@@ -1182,6 +1251,7 @@ serialRegAssign (eBBlock ** ebbs, int count)
                }
              /* else we assign registers to it */
              _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+             _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key);
 
              for (j = 0; j < sym->nRegs; j++)
                {
@@ -1200,12 +1270,12 @@ serialRegAssign (eBBlock ** ebbs, int count)
              if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
                  OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=')
                positionRegs (OP_SYMBOL (IC_RESULT (ic)),
-                             OP_SYMBOL (IC_LEFT (ic)), ic->lineno);
+                             OP_SYMBOL (IC_LEFT (ic)));
              /* do the same for the right operand */
              if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
                  OP_SYMBOL (IC_RIGHT (ic))->nRegs)
                positionRegs (OP_SYMBOL (IC_RESULT (ic)),
-                             OP_SYMBOL (IC_RIGHT (ic)), ic->lineno);
+                             OP_SYMBOL (IC_RIGHT (ic)));
 
              if (ptrRegSet)
                {
@@ -1218,6 +1288,121 @@ serialRegAssign (eBBlock ** ebbs, int count)
     }
 }
 
+/*-----------------------------------------------------------------*/
+/* fillGaps - Try to fill in the Gaps left by Pass1                */
+/*-----------------------------------------------------------------*/
+static void fillGaps()
+{
+    symbol *sym =NULL;
+    int key =0;    
+    
+    if (getenv("DISABLE_FILL_GAPS")) return;
+    
+    /* First try to do DPTRuse once more since now we know what got into
+       registers */
+#if 1
+    for (sym = hTabFirstItem(liveRanges,&key) ; sym ; 
+        sym = hTabNextItem(liveRanges,&key)) {
+
+       if (sym->uptr && !sym->ruonly && getSize(sym->type) < 4) {
+           if (packRegsDPTRuse(operandFromSymbol(sym))) {
+
+               printf("FILL GAPS: found more DPTR use for %s in func %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN");
+               /* 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);
+                   sym->nRegs = 0;                 
+               } else if (sym->usl.spillLoc) sym->usl.spillLoc->allocreq--;
+
+               sym->isspilt = sym->spillA = 0;
+           }
+       }
+    }
+#endif    
+    /* look for livernages that was spilt by the allocator */
+    for (sym = hTabFirstItem(liveRanges,&key) ; sym ; 
+        sym = hTabNextItem(liveRanges,&key)) {
+
+       int i;
+       int pdone = 0;
+
+       if (!sym->spillA || !sym->clashes || sym->remat) continue ;
+
+       /* find the liveRanges this one clashes with, that are
+          still assigned to registers & mark the registers as used*/
+       for ( i = 0 ; i < sym->clashes->size ; i ++) {
+           int k;
+           symbol *clr;
+
+           if (bitVectBitValue(sym->clashes,i) == 0 ||    /* those that clash with this */
+               bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */
+               continue ;
+
+           assert (clr = hTabItemWithKey(liveRanges,i));
+        
+           /* mark these registers as used */
+           for (k = 0 ; k < clr->nRegs ; k++ ) 
+               useReg(clr->regs[k]);
+       }
+
+       if (willCauseSpill(sym->nRegs,sym->regType)) {
+           /* NOPE :( clear all registers & and continue */
+           freeAllRegs();
+           continue ;
+       }
+
+       /* THERE IS HOPE !!!! */
+       for (i=0; i < sym->nRegs ; i++ ) {
+           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 */
+       sym->isspilt = 0;
+       for (i = 0 ; i < sym->defs->size ; i++ ) {
+           if (bitVectBitValue(sym->defs,i)) {
+               iCode *ic;
+               if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ;
+               if (SKIP_IC(ic)) continue;
+               assert(isSymbolEqual(sym,OP_SYMBOL(IC_RESULT(ic)))); /* just making sure */
+               /* if left is assigned to registers */
+               if (IS_SYMOP(IC_LEFT(ic)) && 
+                   bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_LEFT(ic))->key)) {
+                   pdone += positionRegs(sym,OP_SYMBOL(IC_LEFT(ic)));
+               }
+               if (IS_SYMOP(IC_RIGHT(ic)) && 
+                   bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) {
+                   pdone += positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic)));
+               }
+               if (pdone > 1) break;
+           }
+       }
+       /* had to position more than once GIVE UP */
+       if (pdone > 1) {
+           /* UNDO all the changes we made to try this */
+           sym->isspilt = 0;
+           for (i=0; i < sym->nRegs ; i++ ) {
+               sym->regs[i] = NULL;
+           }
+           freeAllRegs();
+           printf("Fill Gap gave up due to positioning for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN");
+           continue ;      
+       }
+       printf("FILLED GAP for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN");
+       _G.totRegAssigned = bitVectSetBit(_G.totRegAssigned,sym->key);
+       sym->isspilt = sym->spillA = 0 ;
+       sym->usl.spillLoc->allocreq--;
+       freeAllRegs();
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* rUmaskForOp :- returns register mask for an operand             */
 /*-----------------------------------------------------------------*/
@@ -1349,7 +1534,7 @@ createRegMask (eBBlock ** ebbs, int count)
                }
              
              /* special case for ruonly */
-             if (sym->ruonly) {
+             if (sym->ruonly && sym->liveFrom != sym->liveTo) {
                  int size = getSize(sym->type);
                  int j = DPL_IDX;
                  for (k = 0 ; k < size; k++ )
@@ -1708,6 +1893,7 @@ pack:
   /* found the definition */
   /* replace the result with the result of */
   /* this assignment and remove this assignment */
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
   IC_RESULT (dic) = IC_RESULT (ic);
 
   if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
@@ -1725,6 +1911,7 @@ pack:
     }
 
   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);
   return 1;
@@ -1835,6 +2022,7 @@ packRegsForSupport (iCode * ic, eBBlock * ebp)
       IC_LEFT (ic)->operand.symOperand =
        IC_RIGHT (dic)->operand.symOperand;
       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++;
@@ -1870,6 +2058,7 @@ right:
       IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
 
       remiCodeFromeBBlock (ebp, dic);
+      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
       hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
       change++;
     }
@@ -1884,7 +2073,7 @@ right:
 /* packRegsDPTRuse : - will reduce some registers for single Use */
 /*-----------------------------------------------------------------*/
 static iCode *
-packRegsDPTRuse (iCode * lic, operand * op, eBBlock * ebp)
+packRegsDPTRuse (operand * op)
 {
     /* go thru entire liveRange of this variable & check for
        other possible usage of DPTR , if we don't find it the
@@ -1895,8 +2084,8 @@ packRegsDPTRuse (iCode * lic, operand * op, eBBlock * ebp)
     iCode *ic, *dic;
     sym_link *type, *etype;
     
-    if (!IS_SYMOP(op)) return NULL;
-    if (OP_SYMBOL(op)->remat) return NULL; 
+    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 */
@@ -1914,6 +2103,8 @@ packRegsDPTRuse (iCode * lic, operand * op, eBBlock * ebp)
     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;
 
@@ -1928,28 +2119,51 @@ packRegsDPTRuse (iCode * lic, operand * op, eBBlock * ebp)
 
        /* special case of add with a [remat] */
        if (ic->op == '+' && 
-           OP_SYMBOL(IC_LEFT(ic))->remat ) continue ;
+           OP_SYMBOL(IC_LEFT(ic))->remat &&
+           (!isOperandInFarSpace(IC_RIGHT(ic)) || 
+            isOperandInReg(IC_RIGHT(ic)))) continue ;
+
+       /* 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 == '/' ) && 
+           getSize(operandType(op)) > 3) return NULL;
 
        /* general case */
        if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) && 
            !isOperandEqual(IC_RESULT(ic),op) &&
-           (isOperandInFarSpace(IC_RESULT(ic)) || 
+           ((isOperandInFarSpace(IC_RESULT(ic)) && !isOperandInReg(IC_RESULT(ic))) || 
+            OP_SYMBOL(IC_RESULT(ic))->ruonly   ||
             OP_SYMBOL(IC_RESULT(ic))->onStack)) 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))) &&
-           (isOperandInFarSpace(IC_RIGHT(ic)) || 
+            IS_TRUE_SYMOP(IC_RIGHT(ic))               ||
+            OP_SYMBOL(IC_RIGHT(ic))->ruonly) &&
+           ((isOperandInFarSpace(IC_RIGHT(ic)) && !isOperandInReg(IC_RIGHT(ic)))|| 
             OP_SYMBOL(IC_RIGHT(ic))->onStack)) 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)))&&
-           (isOperandInFarSpace(IC_LEFT(ic)) || 
+            IS_TRUE_SYMOP(IC_LEFT(ic))               ||
+            OP_SYMBOL(IC_LEFT(ic))->ruonly) &&
+           ((isOperandInFarSpace(IC_LEFT(ic)) && !isOperandInReg(IC_LEFT(ic)))|| 
             OP_SYMBOL(IC_LEFT(ic))->onStack)) 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;
     return dic;
@@ -1992,6 +2206,11 @@ packRegsForAccUse (iCode * ic)
 {
   iCode *uic;
 
+  /* if this is an aggregate, e.g. a one byte char array */
+  if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
+    return;
+  }
+
   /* if + or - then it has to be one byte result */
   if ((ic->op == '+' || ic->op == '-')
       && getSize (operandType (IC_RESULT (ic))) > 1)
@@ -2067,9 +2286,14 @@ 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 0
   if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
       OP_SYMBOL (IC_RESULT (uic))->onStack)
     return;
+#else
+  if (isOperandOnStack(IC_RESULT(uic)))
+    return;
+#endif
 
   /* if either one of them in far space then we cannot */
   if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
@@ -2172,6 +2396,7 @@ packForPush (iCode * ic, eBBlock * ebp)
   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);
 }
 
@@ -2344,7 +2569,11 @@ packRegisters (eBBlock * ebp)
          !isOperandInFarSpace (IC_LEFT (ic)) &&
          !options.model) {
         
-         packRegsDPTRuse (ic, IC_LEFT (ic), ebp);
+         packRegsDPTRuse (IC_LEFT (ic));
+      }
+
+      if ((ic->op == CALL && getSize(operandType(IC_RESULT(ic))) <= 4)) {
+         packRegsDPTRuse (IC_RESULT (ic));       
       }
 
       /* if pointer set & left has a size more than
@@ -2355,7 +2584,7 @@ packRegisters (eBBlock * ebp)
          !IS_OP_RUONLY (IC_RIGHT (ic)) &&
          getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1) {
          
-         packRegsDPTRuse (ic, IC_RESULT (ic), ebp);
+         packRegsDPTRuse (IC_RESULT (ic));
       }
 
       /* if pointer get */
@@ -2365,7 +2594,7 @@ packRegisters (eBBlock * ebp)
          !IS_OP_RUONLY (IC_RESULT (ic)) &&
          getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1) {
 
-         packRegsDPTRuse (ic, IC_LEFT (ic), ebp);
+         packRegsDPTRuse (IC_LEFT (ic));
       }
 
       /* if this is cast for intergral promotion then
@@ -2383,13 +2612,15 @@ packRegisters (eBBlock * ebp)
              SPEC_USIGN (fromType) == SPEC_USIGN (toType))
            {
 
-             iCode *dic = packRegsDPTRuse (ic, IC_RIGHT (ic), ebp);
+             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;
@@ -2406,11 +2637,13 @@ packRegisters (eBBlock * ebp)
              if (compareType (operandType (IC_RIGHT (ic)),
                             operandType (IC_LEFT (ic))) == 1)
                {
-                 iCode *dic = packRegsDPTRuse (ic, IC_RIGHT (ic), ebp);
+                 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;
@@ -2462,7 +2695,10 @@ ds390_assignRegisters (eBBlock ** ebbs, int count)
   iCode *ic;
   int i;
 
-  setToNull ((void *) &_G.funcrUsed);
+  setToNull ((void *) &_G.funcrUsed);  
+  setToNull ((void *) &_G.regAssigned);  
+  setToNull ((void *) &_G.totRegAssigned);  
+  setToNull ((void *) &_G.funcrUsed);  
   ds390_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
   ds390_nRegs = 18;
   if (options.model != MODEL_FLAT24) options.stack10bit = 0;
@@ -2481,6 +2717,11 @@ ds390_assignRegisters (eBBlock ** ebbs, int count)
   /* and serially allocate registers */
   serialRegAssign (ebbs, count);
 
+  ds390_nRegs = 8;
+  freeAllRegs ();
+  fillGaps();
+  ds390_nRegs = 18;
+
   /* if stack was extended then tell the user */
   if (_G.stackExtend)
     {