* src/mcs51/ralloc.c (deassignLR),
[fw/sdcc] / src / mcs51 / ralloc.c
index 4185bfd86d276465b8de8dbf3c3fe98b98470026..ec01a64642e23b935a55a847a41fa9527828b4a5 100644 (file)
@@ -74,9 +74,13 @@ regs regs8051[] =
   {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_CND, CND_IDX, REG_CND, "C", "psw", "0xd0", 0, 1},
+  {0, DPL_IDX, 0, "dpl", "dpl", "0x82", 0, 0},
+  {0, DPH_IDX, 0, "dph", "dph", "0x83", 0, 0},
+  {0, B_IDX, 0, "b", "b", "0xf0", 0, 0},
+  {0, A_IDX, 0, "a", "acc", "0xe0", 0, 0},
 };
-int mcs51_nRegs = 13;
+int mcs51_nRegs = 17;
 static void spillThis (symbol *);
 static void freeAllRegs ();
 
@@ -117,6 +121,23 @@ allocReg (short type)
   return NULL;
 }
 
+/*-----------------------------------------------------------------*/
+/* allocThisReg - allocates a particular register (if free)        */
+/*-----------------------------------------------------------------*/
+static regs *
+allocThisReg (regs * reg)
+{
+  if (!reg->isFree)
+    return NULL;
+
+  reg->isFree = 0;
+  if (currFunc)
+    currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, reg->rIdx);
+  
+  return reg;
+}
+
+
 /*-----------------------------------------------------------------*/
 /* mcs51_regWithIdx - returns pointer to register wit index number       */
 /*-----------------------------------------------------------------*/
@@ -125,7 +146,7 @@ mcs51_regWithIdx (int idx)
 {
   int i;
 
-  for (i = 0; i < mcs51_nRegs; i++)
+  for (i = 0; i < sizeof(regs8051)/sizeof(regs); i++)
     if (regs8051[i].rIdx == idx)
       return &regs8051[i];
 
@@ -350,7 +371,7 @@ leastUsedLR (set * sset)
 
     }
 
-  setToNull ((void **) &sset);
+  setToNull ((void *) &sset);
   sym->blockSpil = 0;
   return sym;
 }
@@ -571,7 +592,6 @@ spillThis (symbol * sym)
   if (!(sym->remat || sym->usl.spillLoc))
     createStackSpil (sym);
 
-
   /* mark it has spilt & put it in the spilt set */
   sym->isspilt = sym->spillA = 1;
   _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
@@ -783,6 +803,7 @@ static regs *
 getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym)
 {
   regs *reg;
+  int j;
 
 tryAgain:
   /* try for a ptr type */
@@ -797,6 +818,11 @@ tryAgain:
   if (!spilSomething (ic, ebp, sym))
     return NULL;
 
+  /* make sure partially assigned registers aren't reused */
+  for (j=0; j<=sym->nRegs; j++)
+    if (sym->regs[j])
+      sym->regs[j]->isFree = 0;
+      
   /* this looks like an infinite loop but 
      in really selectSpil will abort  */
   goto tryAgain;
@@ -809,7 +835,8 @@ static regs *
 getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
 {
   regs *reg;
-
+  int j;
+  
 tryAgain:
   /* try for gpr type */
   if ((reg = allocReg (REG_GPR)))
@@ -823,6 +850,11 @@ tryAgain:
   if (!spilSomething (ic, ebp, sym))
     return NULL;
 
+  /* make sure partially assigned registers aren't reused */
+  for (j=0; j<=sym->nRegs; j++)
+    if (sym->regs[j])
+      sym->regs[j]->isFree = 0;
+      
   /* this looks like an infinite loop but 
      in really selectSpil will abort  */
   goto tryAgain;
@@ -949,6 +981,7 @@ deassignLRs (iCode * ic, eBBlock * ebp)
              (result = OP_SYMBOL (IC_RESULT (ic))) &&  /* has a result */
              result->liveTo > ic->seq &&       /* and will live beyond this */
              result->liveTo <= ebp->lSeq &&    /* does not go beyond this block */
+             result->liveFrom == ic->seq &&    /* does not start before here */
              result->regType == sym->regType &&        /* same register types */
              result->nRegs &&  /* which needs registers */
              !result->isspilt &&       /* and does not already have them */
@@ -1088,6 +1121,33 @@ xchgPositions:
   return change;
 }
 
+
+/*------------------------------------------------------------------*/
+/* 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  */
 /*-----------------------------------------------------------------*/
@@ -1108,7 +1168,18 @@ serialRegAssign (eBBlock ** ebbs, int count)
 
        /* of all instructions do */
        for (ic = ebbs[i]->sch; ic; ic = ic->next) {
-
+#if 1
+           int reg;
+
+           // update the registers in use at the start of this icode
+           for (reg=0; reg<mcs51_nRegs; reg++) {
+             if (regs8051[reg].isFree) {
+               ic->riu &= ~(1<<regs8051[reg].offset);
+             } else {
+               ic->riu |= (1<<regs8051[reg].offset);
+             }
+           }
+#endif
            /* if this is an ipop that means some live
               range will have to be assigned again */
            if (ic->op == IPOP)
@@ -1167,6 +1238,16 @@ serialRegAssign (eBBlock ** ebbs, int count)
                    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 */
@@ -1197,36 +1278,63 @@ serialRegAssign (eBBlock ** ebbs, int count)
                    mcs51_ptrRegReq++;
                    ptrRegSet = 1;
                }
+               if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic))
+                   && SPEC_OCLS(OP_SYMBOL (IC_LEFT (ic))->etype) == idata) {
+                   mcs51_ptrRegReq++;
+                   ptrRegSet = 1;
+               }
+               if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic))
+                   && SPEC_OCLS(OP_SYMBOL (IC_RIGHT (ic))->etype) == idata) {
+                   mcs51_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
-                       sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
+                     {
+                       if (ic->op == CAST && IS_SYMOP (IC_RIGHT (ic)))
+                         {
+                           symbol * right = OP_SYMBOL (IC_RIGHT (ic));
+                           
+                           if (right->regs[j])
+                             sym->regs[j] = allocThisReg (right->regs[j]);
+                         }
+                       if (!sym->regs[j])
+                         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 (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
-                   OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=') {
-                   positionRegs (OP_SYMBOL (IC_RESULT (ic)),
-                                 OP_SYMBOL (IC_LEFT (ic)));
-               }
-               /* do the same for the right operand */
-               if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
-                   OP_SYMBOL (IC_RIGHT (ic))->nRegs) {
-                   positionRegs (OP_SYMBOL (IC_RESULT (ic)),
-                                 OP_SYMBOL (IC_RIGHT (ic)));
+                   if (!sym->regs[j])
+                     {
+                       for (i=0; i < sym->nRegs ; i++ )
+                         sym->regs[i] = NULL;
+                       break;
+                     }
                }
+               
+               if (!POINTER_SET(ic) && !POINTER_GET(ic)) {
+                    /* 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) {
+                       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) {
                    mcs51_ptrRegReq--;
@@ -1236,6 +1344,39 @@ serialRegAssign (eBBlock ** ebbs, int count)
            }
        }
     }
+
+    /* 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);
+          }
+      }    
 }
 
 /*-----------------------------------------------------------------*/
@@ -1244,7 +1385,9 @@ serialRegAssign (eBBlock ** ebbs, int count)
 static void fillGaps()
 {
     symbol *sym =NULL;
-    int key =0;    
+    int key =0;
+    int pass;
+    iCode *ic = NULL;
     
     if (getenv("DISABLE_FILL_GAPS")) return;
     
@@ -1267,9 +1410,9 @@ static void fillGaps()
                bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */
                continue ;
 
-               clr = hTabItemWithKey(liveRanges,i);
+           clr = hTabItemWithKey(liveRanges,i);
            assert(clr);
-        
+
            /* mark these registers as used */
            for (k = 0 ; k < clr->nRegs ; k++ ) 
                useReg(clr->regs[k]);
@@ -1281,52 +1424,111 @@ static void fillGaps()
            continue ;
        }
 
+       ic = NULL;          
+       for (i = 0 ; i < sym->defs->size ; i++ )
+          {
+           if (bitVectBitValue(sym->defs,i))
+             {
+               if (!(ic = hTabItemWithKey(iCodehTab,i)))
+                 continue;
+               if (ic->op == CAST)
+                 break;
+             }
+         }
+
+        D(printf("Atemping fillGaps on %s: [",sym->name));
        /* THERE IS HOPE !!!! */
        for (i=0; i < sym->nRegs ; i++ ) {
            if (sym->regType == REG_PTR)
                sym->regs[i] = getRegPtrNoSpil ();
            else
-               sym->regs[i] = getRegGprNoSpil ();                
+             {
+               sym->regs[i] = NULL;
+               if (ic && ic->op == CAST && IS_SYMOP (IC_RIGHT (ic)))
+                 {
+                   symbol * right = OP_SYMBOL (IC_RIGHT (ic));
+                   
+                   if (right->regs[i])
+                     sym->regs[i] = allocThisReg (right->regs[i]);
+                 }
+               if (!sym->regs[i])
+                 sym->regs[i] = getRegGprNoSpil ();
+             }
+            D(printf("%s ", sym->regs[i]->name));
        }
+        D(printf("]\n"));
 
-       /* for all its definitions check if the registers
+       /* 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 */
+          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 (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)));
+        for (pass=0; pass<2; pass++) {
+            D(printf(" checking definitions\n"));
+           for (i = 0 ; i < sym->defs->size ; i++ ) {
+               if (bitVectBitValue(sym->defs,i)) {
+                   if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ;
+                    D(printf("  ic->seq = %d\n", ic->seq));
+                   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)))
+                      {
+                        D(printf("   left = "));
+                        D(printOperand(IC_LEFT(ic),NULL));
+                      }
+                    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)))
+                      {
+                        D(printf("   right = "));
+                        D(printOperand(IC_RIGHT(ic),NULL));
+                      }
+                   if (IS_SYMOP(IC_RIGHT(ic)) && 
+                     bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) {
+                       pdone += (positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic)))>0);
+                   }
+                    D(printf("   pdone = %d\n", pdone));
+                   if (pdone > 1) break;
                }
-               if (pdone > 1) break;
            }
-       }
-       for (i = 0 ; i < sym->uses->size ; i++ ) {
-           if (bitVectBitValue(sym->uses,i)) {
-               iCode *ic;
-               if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ;
-               if (SKIP_IC(ic)) continue;
-               if (!IS_ASSIGN_ICODE(ic)) continue ;
-
-               /* if result is assigned to registers */
-               if (IS_SYMOP(IC_RESULT(ic)) && 
-                   bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) {
-                   pdone += positionRegs(sym,OP_SYMBOL(IC_RESULT(ic)));
+            D(printf(" checking uses\n"));
+           for (i = 0 ; i < sym->uses->size ; i++ ) {
+               if (bitVectBitValue(sym->uses,i)) {
+                   iCode *ic;
+                   if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ;
+                    D(printf("  ic->seq = %d\n", ic->seq));
+                   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)))
+                      {
+                        D(printf("   result = "));
+                        D(printOperand(IC_RESULT(ic),NULL));
+                      }
+                   if (IS_SYMOP(IC_RESULT(ic)) && 
+                       bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) {
+                       pdone += (positionRegs(sym,OP_SYMBOL(IC_RESULT(ic)))>0);
+                   }
+                    D(printf("   pdone = %d\n", pdone));
+                   if (pdone > 1) break;
                }
-               if (pdone > 1) break;
            }
-       }
+            if (pdone == 0) break; /* second pass only if regs repositioned */
+           if (pdone > 1) break;
+        }
+        D(printf(" sym->regs = ["));
+       for (i=0; i < sym->nRegs ; i++ )
+          D(printf("%s ", sym->regs[i]->name));
+        D(printf("]\n"));
        /* had to position more than once GIVE UP */
        if (pdone > 1) {
            /* UNDO all the changes we made to try this */
@@ -1339,6 +1541,7 @@ static void fillGaps()
            continue ;      
        }
        D(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--;
@@ -1371,6 +1574,7 @@ mcs51_rUmaskForOp (operand * op)
 
   for (j = 0; j < sym->nRegs; j++)
     {
+      if (sym->regs[j]) /* EEP - debug */
       rumask = bitVectSetBit (rumask,
                              sym->regs[j]->rIdx);
     }
@@ -1559,7 +1763,7 @@ regTypeNum (eBBlock *ebbs)
          if (sym->ruonly || sym->accuse)
            {
              if (IS_AGGREGATE (sym->type) || sym->isptr)
-               sym->type = aggrToPtr (sym->type, FALSE);
+               sym->type = aggrToPtr (sym->type, FALSE);
              continue;
            }
 
@@ -1569,33 +1773,13 @@ regTypeNum (eBBlock *ebbs)
              (ic = hTabItemWithKey (iCodehTab,
                                     bitVectFirstBit (sym->defs))) &&
              POINTER_GET (ic) &&
-             !sym->noSpilLoc &&
-             !IS_BITVAR (sym->etype))
+             !IS_BITVAR (sym->etype) &&
+             (aggrToPtrDclType (operandType (IC_LEFT (ic)), FALSE) == POINTER))
            {
 
-
-             /* and that pointer is remat in data space */
-             if (OP_SYMBOL (IC_LEFT (ic))->remat &&
-                 !IS_CAST_ICODE(OP_SYMBOL (IC_LEFT (ic))->rematiCode) &&
-                 DCL_TYPE (aggrToPtr (operandType(IC_LEFT(ic)), FALSE)) == POINTER)
+             if (ptrPseudoSymSafe (sym, ic))
                {
-                 /* 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;
-#if 0 // an alternative fix for bug #480076
-                 /* now this is a useless assignment to itself */
-                 remiCodeFromeBBlock (ebbs, ic);
-#else
-                 /* now this really is an assignment to itself, make it so;
-                    it will be optimized out later */
-                 ic->op='=';
-                 IC_RIGHT(ic)=IC_RESULT(ic);
-                 IC_LEFT(ic)=NULL;
-#endif
+                 ptrPseudoSymConvert (sym, ic, rematStr (OP_SYMBOL (IC_LEFT (ic))));
                  continue;
                }
 
@@ -1630,7 +1814,7 @@ regTypeNum (eBBlock *ebbs)
        /* registers for true symbols we will */
        /* see how things go                  */
        sym->nRegs = 0;
-    }
+         }
 
 }
 
@@ -1691,23 +1875,40 @@ farSpacePackable (iCode * ic)
          getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1)
        return NULL;
 
-      /* if any three is a true symbol in far space */
-      if (IC_RESULT (dic) &&
-         IS_TRUE_SYMOP (IC_RESULT (dic)) &&
-         isOperandInFarSpace (IC_RESULT (dic)))
-       return NULL;
+      if (dic->op == IFX)
+        {
+          if (IC_COND (dic) &&
+             IS_TRUE_SYMOP (IC_COND (dic)) &&
+             isOperandInFarSpace (IC_COND (dic)))
+           return NULL;
+        }
+      else if (dic->op == JUMPTABLE)
+        {
+          if (IC_JTCOND (dic) &&
+             IS_TRUE_SYMOP (IC_JTCOND (dic)) &&
+             isOperandInFarSpace (IC_JTCOND (dic)))
+           return NULL;
+        }
+      else
+        {
+          /* if any three is a true symbol in far space */
+          if (IC_RESULT (dic) &&
+             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;
+          if (IC_RIGHT (dic) &&
+             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;
+          if (IC_LEFT (dic) &&
+             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)))
        {
@@ -1731,12 +1932,10 @@ static int
 packRegsForAssign (iCode * ic, eBBlock * ebp)
 {
   iCode *dic, *sic;
-  //sym_link *etype = operandType (IC_RIGHT (ic));
 
   if (!IS_ITEMP (IC_RIGHT (ic)) ||
       OP_SYMBOL (IC_RIGHT (ic))->isind ||
-      OP_LIVETO (IC_RIGHT (ic)) > ic->seq
-      /* why? || IS_BITFIELD (etype) */ )
+      OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
     {
       return 0;
     }
@@ -1752,66 +1951,114 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
      we cannot */
   for (dic = ic->prev; dic; dic = dic->prev)
     {
-      /* if there is a function call then don't pack it */
+      int crossedCall = 0;
+      
+      /* We can pack across a function call only if it's a local */
+      /* variable or our parameter. Never pack global variables */
+      /* or parameters to a function we call. */
       if ((dic->op == CALL || dic->op == PCALL))
        {
-         dic = NULL;
-         break;
+         if (!OP_SYMBOL (IC_RESULT (ic))->ismyparm
+             && !OP_SYMBOL (IC_RESULT (ic))->islocal)
+           {
+             crossedCall = 1;
+           }
        }
 
       if (SKIP_IC2 (dic))
        continue;
 
-      if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
-         IS_OP_VOLATILE (IC_RESULT (dic)))
-       {
-         dic = NULL;
-         break;
-       }
+      if (dic->op == IFX)
+        {
+          if (IS_SYMOP (IC_COND (dic)) &&
+             (IC_COND (dic)->key == IC_RESULT (ic)->key ||
+              IC_COND (dic)->key == IC_RIGHT (ic)->key))
+           {
+             dic = NULL;
+             break;
+           }
+        }
+      else
+        {
+          if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
+             IS_OP_VOLATILE (IC_RESULT (dic)))
+           {
+             dic = NULL;
+             break;
+           }
 
-      if (IS_SYMOP (IC_RESULT (dic)) &&
-         IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
-       {
-         if (POINTER_SET (dic))
-           dic = NULL;
+          if (IS_SYMOP (IC_RESULT (dic)) &&
+             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;
-       }
+          if (IS_SYMOP (IC_RIGHT (dic)) &&
+             (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
+              IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
+           {
+             dic = NULL;
+             break;
+           }
 
-      if (IS_SYMOP (IC_LEFT (dic)) &&
-         (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
-          IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
-       {
-         dic = NULL;
-         break;
-       }
+          if (IS_SYMOP (IC_LEFT (dic)) &&
+             (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;
+          if (IS_SYMOP (IC_RESULT (dic)) &&
+             IC_RESULT (dic)->key == IC_RESULT (ic)->key)
+           {
+             dic = NULL;
+             break;
+           }
+           
+         if (crossedCall)
+           {
+             dic = NULL;
+             break;
+           }
+         
        }
     }
 
   if (!dic)
     return 0;                  /* did not find */
 
+  /* if assignment then check that right is not a bit */
+  if (ASSIGNMENT (ic) && !POINTER_SET (ic))
+    {
+      sym_link *etype = operandType (IC_RESULT (dic));
+      if (IS_BITFIELD (etype))
+        {
+          /* if result is a bit too then it's ok */
+          etype = operandType (IC_RESULT (ic));
+          if (!IS_BITFIELD (etype))
+            {
+              return 0;
+            }
+       }
+    }
+#if 0
   /* if assignment then check that right is not a bit */
   if (ASSIGNMENT (dic) && !POINTER_SET (dic))
     {
       sym_link *etype = operandType (IC_RIGHT (dic));
       if (IS_BITFIELD (etype))
-       return 0;
+        {
+          /* if result is a bit too then it's ok */
+          etype = operandType (IC_RESULT (dic));
+          if (!IS_BITFIELD (etype))
+            return 0;
+        }
     }
+#endif
   /* 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 ||
@@ -1835,12 +2082,14 @@ pack:
   /* 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);
+  ReplaceOpWithCheaperOp(&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;
     }
+  // TODO: and the otherway around?
+
   /* delete from liverange table also 
      delete from all the points inbetween and the new
      one */
@@ -1854,9 +2103,8 @@ pack:
   remiCodeFromeBBlock (ebp, ic);
   bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
   hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
-  OP_DEFS_SET ((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;
-
 }
 
 /*------------------------------------------------------------------*/
@@ -1876,7 +2124,6 @@ findAssignToSym (operand * op, iCode * ic)
      other uses.
   */
      
-
   for (dic = ic->prev; dic; dic = dic->prev)
     {
 
@@ -1889,14 +2136,28 @@ findAssignToSym (operand * op, iCode * ic)
        break;  /* found where this temp was defined */
 
       /* if we find an usage then we cannot delete it */
-      if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
-       return NULL;
+      
+      if (dic->op == IFX)
+        {
+          if (IC_COND (dic) && IC_COND (dic)->key == op->key)
+            return NULL;
+        }
+      else if (dic->op == JUMPTABLE)
+        {
+          if (IC_JTCOND (dic) && IC_JTCOND (dic)->key == op->key)
+            return NULL;
+        }
+      else
+        {
+          if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
+           return NULL;
 
-      if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
-       return NULL;
+          if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
+           return NULL;
 
-      if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
-       return NULL;
+          if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
+           return NULL;
+       }
     }
 
   if (!dic)
@@ -1975,7 +2236,8 @@ reassignAliasedSym (eBBlock *ebp, iCode *assignment, iCode *use, operand *op)
   /* update the sym of the used operand */
   OP_SYMBOL(op) = OP_SYMBOL(IC_RIGHT(assignment));
   op->key = OP_SYMBOL(op)->key;
-
+  OP_SYMBOL(op)->accuse = 0;
+  
   /* update the sym's liverange */
   if ( OP_LIVETO(op) < ic->seq )
     setToRange(op, ic->seq, FALSE);
@@ -2190,7 +2452,6 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
 
   OP_SYMBOL (op)->ruonly = 1;
   return sic;
-
 }
 
 /*-----------------------------------------------------------------*/
@@ -2428,10 +2689,11 @@ accuse:
 /* packForPush - hueristics 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)))
     return;
@@ -2449,32 +2711,46 @@ packForPush (iCode * ic, eBBlock * ebp)
   if (dic->op != '=' || POINTER_SET (dic))
     return;
 
-  /* make sure the right side does not have any definitions
-     inbetween */
-  dbv = OP_DEFS(IC_RIGHT(dic));
-  for (lic = ic; lic && lic != dic ; lic = lic->prev) {
-    if (bitVectBitValue(dbv,lic->key)) 
-      return ;
+  if (dic->seq < ebp->fSeq) { // Evelyn did this
+    int i;
+    for (i=0; i<blockno; i++) {
+      if (dic->seq >= ebpp[i]->fSeq && dic->seq <= ebpp[i]->lSeq) {
+       ebp=ebpp[i];
+       break;
+      }
+    }
+    wassert (i!=blockno); // no way to recover from here
   }
-  /* make sure they have the same type */
-  {
-    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 < ic->seq) {
-         OP_SYMBOL(IC_RIGHT(dic))->liveTo = ic->seq;
-  }
+  if (IS_SYMOP(IC_RIGHT(dic))) {
+    /* make sure the right side does not have any definitions
+       inbetween */
+    dbv = OP_DEFS(IC_RIGHT(dic));
+    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 < ic->seq) {
+      OP_SYMBOL(IC_RIGHT(dic))->liveTo = ic->seq;
+    }
+    bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,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);
-   
+  ReplaceOpWithCheaperOp(&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);
 }
 
@@ -2483,10 +2759,11 @@ 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)
     {
@@ -2545,7 +2822,8 @@ packRegisters (eBBlock * ebp)
         cast is remat, then we can remat this cast as well */
       if (ic->op == CAST && 
          IS_SYMOP(IC_RIGHT(ic)) &&
-         OP_SYMBOL(IC_RIGHT(ic))->remat ) {
+         OP_SYMBOL(IC_RIGHT(ic))->remat &&
+         bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1) {
              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)) {                  
@@ -2574,30 +2852,45 @@ packRegisters (eBBlock * ebp)
       if (POINTER_SET (ic))
        OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
 
-      if (POINTER_GET (ic))
+      if (POINTER_GET (ic) &&
+         IS_SYMOP(IC_LEFT (ic)))
        OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
 
       if (!SKIP_IC2 (ic))
        {
          /* if we are using a symbol on the stack
             then we should say mcs51_ptrRegReq */
+         if (options.useXstack && ic->parmPush
+             && (ic->op == IPUSH || ic->op == IPOP))
+           mcs51_ptrRegReq++;
          if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
            mcs51_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ||
-                                OP_SYMBOL (IC_COND (ic))->iaccess) ? 1 : 0);
+                                OP_SYMBOL (IC_COND (ic))->iaccess ||
+                                SPEC_OCLS(OP_SYMBOL (IC_COND (ic))->etype) == idata) ? 1 : 0);
          else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic)))
            mcs51_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ||
-                             OP_SYMBOL (IC_JTCOND (ic))->iaccess) ? 1 : 0);
+                             OP_SYMBOL (IC_JTCOND (ic))->iaccess ||
+                             SPEC_OCLS(OP_SYMBOL (IC_JTCOND (ic))->etype) == idata) ? 1 : 0);
          else
            {
              if (IS_SYMOP (IC_LEFT (ic)))
                mcs51_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ||
-                               OP_SYMBOL (IC_LEFT (ic))->iaccess) ? 1 : 0);
+                               OP_SYMBOL (IC_LEFT (ic))->iaccess ||
+                               SPEC_OCLS(OP_SYMBOL (IC_LEFT (ic))->etype) == idata) ? 1 : 0);
              if (IS_SYMOP (IC_RIGHT (ic)))
                mcs51_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ||
-                              OP_SYMBOL (IC_RIGHT (ic))->iaccess) ? 1 : 0);
+                              OP_SYMBOL (IC_RIGHT (ic))->iaccess ||
+                              SPEC_OCLS(OP_SYMBOL (IC_RIGHT (ic))->etype) == idata) ? 1 : 0);
              if (IS_SYMOP (IC_RESULT (ic)))
                mcs51_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ||
-                             OP_SYMBOL (IC_RESULT (ic))->iaccess) ? 1 : 0);
+                             OP_SYMBOL (IC_RESULT (ic))->iaccess ||
+                             SPEC_OCLS(OP_SYMBOL (IC_RESULT (ic))->etype) == idata) ? 1 : 0);
+             if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic))
+                 && getSize (OP_SYMBOL (IC_LEFT (ic))->type) <= (unsigned int) PTRSIZE)
+               mcs51_ptrRegReq ++;
+             if (POINTER_SET (ic) && IS_SYMOP (IC_RESULT (ic))
+                 && getSize (OP_SYMBOL (IC_RESULT (ic))->type) <= (unsigned int) PTRSIZE)
+               mcs51_ptrRegReq ++;
            }
        }
 
@@ -2625,12 +2918,7 @@ packRegisters (eBBlock * ebp)
       if ((ic->op == RETURN || (ic->op == SEND && ic->argreg == 1)) &&
          !isOperandInFarSpace (IC_LEFT (ic)) &&
          options.model == MODEL_SMALL) {
-       if (0 && options.stackAuto) {
-         /* we should check here if acc will be clobbered for stack
-            offset calculations */
-       } else {
-         packRegsForOneuse (ic, IC_LEFT (ic), ebp);
-       }
+       packRegsForOneuse (ic, IC_LEFT (ic), ebp);
       }
 
       /* if pointer set & left has a size more than
@@ -2640,16 +2928,15 @@ packRegisters (eBBlock * ebp)
          !OP_SYMBOL (IC_RESULT (ic))->remat &&
          !IS_OP_RUONLY (IC_RIGHT (ic)) &&
          getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
-
        packRegsForOneuse (ic, IC_RESULT (ic), ebp);
 
       /* if pointer get */
       if (POINTER_GET (ic) &&
+         IS_SYMOP (IC_LEFT (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);
 
 
@@ -2674,11 +2961,11 @@ packRegisters (eBBlock * ebp)
                  if (IS_ARITHMETIC_OP (dic))
                    {                  
                      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
-                     IC_RESULT (dic) = IC_RESULT (ic);
+                     ReplaceOpWithCheaperOp(&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_SET ((IC_RESULT (dic)), bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key));
+                     OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
                      ic = ic->prev;
                    }
                  else
@@ -2697,11 +2984,11 @@ packRegisters (eBBlock * ebp)
                  if (dic)
                    {
                      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
-                     IC_RESULT (dic) = IC_RESULT (ic);
+                     ReplaceOpWithCheaperOp(&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_SET ((IC_RESULT (dic)), bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key));
+                     OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
                      ic = ic->prev;
                    }
                }
@@ -2716,7 +3003,7 @@ packRegisters (eBBlock * ebp)
        */
       if (ic->op == IPUSH)
        {
-         packForPush (ic, ebp);
+         packForPush (ic, ebpp, blockno);
        }
 
 
@@ -2751,14 +3038,20 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count)
   int i;
 
   setToNull ((void *) &_G.funcrUsed);
+  setToNull ((void *) &_G.regAssigned);
   setToNull ((void *) &_G.totRegAssigned);
   mcs51_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
   mcs51_nRegs = 8;
 
   /* 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 (DUMP_PACK, ebbs, count);
@@ -2771,6 +3064,8 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count)
   serialRegAssign (ebbs, count);
 
   freeAllRegs ();
+  //setToNull ((void *) &_G.regAssigned);
+  //setToNull ((void *) &_G.totRegAssigned);
   fillGaps();
 
   /* if stack was extended then tell the user */
@@ -2793,7 +3088,17 @@ mcs51_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 && mcs51_ptrRegReq)
+    {
+      currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, R0_IDX);
+      currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, R1_IDX);
+    }
 
   if (options.dump_rassgn)
     {
@@ -2812,8 +3117,8 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count)
   /* 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 */
   freeAllRegs ();