* src/mcs51/gen.c (genFunction): optimize RECEIVE in reentrant
[fw/sdcc] / src / ds390 / ralloc.c
index dd1a2ab60b3ada130c9f11b60018296c565bfa50..3743e964dcf776f0369cdb7aa3971d007aa844e4 100644 (file)
@@ -77,7 +77,13 @@ regs regs390[] =
   {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", "C", "xreg", 0, 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;
 static void spillThis (symbol *);
@@ -130,7 +136,7 @@ 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];
 
@@ -190,31 +196,6 @@ nfreeRegsType (int type)
 }
 
 
-/*-----------------------------------------------------------------*/
-/* allDefsOutOfRange - all definitions are out of a range          */
-/*-----------------------------------------------------------------*/
-static bool
-allDefsOutOfRange (bitVect * defs, int fseq, int toseq)
-{
-  int i;
-
-  if (!defs)
-    return TRUE;
-
-  for (i = 0; i < defs->size; i++)
-    {
-      iCode *ic;
-
-      if (bitVectBitValue (defs, i) &&
-         (ic = hTabItemWithKey (iCodehTab, i)) &&
-         (ic->seq >= fseq && ic->seq <= toseq))
-
-       return FALSE;
-
-    }
-
-  return TRUE;
-}
 
 /*-----------------------------------------------------------------*/
 /* isOperandInReg - returns true if operand is currently in regs   */
@@ -304,18 +285,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) &&
-         allDefsOutOfRange (sym->uses, ebp->fSeq, ebp->lSeq));
-/*     return (!bitVectBitsInCommon(sym->defs,ebp->usesDefs)); */
-}
-
 /*-----------------------------------------------------------------*/
 /* notUsedInRemaining - not used or defined in remain of the block */
 /*-----------------------------------------------------------------*/
@@ -399,7 +368,7 @@ leastUsedLR (set * sset)
 
     }
 
-  setToNull ((void **) &sset);
+  setToNull ((void *) &sset);
   sym->blockSpil = 0;
   return sym;
 }
@@ -521,7 +490,8 @@ 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__);
@@ -641,12 +611,12 @@ spillThis (symbol * sym)
        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 += !options.stack10bit;
+      ds390_ptrRegReq ++;
       spillLRWithPtrReg (sym);
     }
 
@@ -680,9 +650,10 @@ 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++;
@@ -837,6 +808,7 @@ static regs *
 getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym)
 {
   regs *reg;
+  int j;
 
 tryAgain:
   /* try for a ptr type */
@@ -851,6 +823,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;
@@ -863,6 +840,7 @@ static regs *
 getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
 {
   regs *reg;
+  int j;
 
 tryAgain:
   /* try for gpr type */
@@ -877,6 +855,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;
@@ -898,6 +881,9 @@ static regs *getRegPtrNoSpil()
     return reg;
 
   assert(0);
+
+  /* just to make the compiler happy */
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
@@ -915,6 +901,9 @@ static regs *getRegGprNoSpil()
       return reg;
 
   assert(0);
+
+  /* just to make the compiler happy */
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1136,6 +1125,122 @@ xchgPositions:
   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);
+           /* makr 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  */
 /*-----------------------------------------------------------------*/
@@ -1146,16 +1251,17 @@ 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;
       
-/*       if (returnsAtEnd(ebbs[i])) */
+      unusedLRs = deassignUnsedLRs(ebbs[i]);
       
       /* of all instructions do */
       for (ic = ebbs[i]->sch; ic; ic = ic->next)
@@ -1274,17 +1380,25 @@ serialRegAssign (eBBlock ** ebbs, int count)
                  if (!sym->regs[j])
                    break;
                }
-             /* if it shares registers with operands make sure
+             
+              /* 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 (!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)
                {
@@ -1294,7 +1408,42 @@ serialRegAssign (eBBlock ** ebbs, int count)
 
            }
        }
+      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);
+          }
+      }    
+    
 }
 
 /*-----------------------------------------------------------------*/
@@ -1305,6 +1454,7 @@ static void fillGaps()
     symbol *sym =NULL;
     int key =0;    
     int loop = 0, change;
+    int pass;
 
     if (getenv("DISABLE_FILL_GAPS")) return;
     
@@ -1349,7 +1499,6 @@ static void fillGaps()
                        sym->usl.spillLoc->allocreq--;
                        sym->usl.spillLoc = NULL;
                    }
-/*                 printf("Allocated %s in function %s to DPTR1\n",sym->name,currFunc->name); */
                    sym->nRegs = 0;                 
                    sym->isspilt = sym->spillA = 0;                 
                }
@@ -1375,7 +1524,8 @@ static void fillGaps()
                    bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */
                    continue ;
                
-               assert (clr = hTabItemWithKey(liveRanges,i));
+               clr = hTabItemWithKey(liveRanges,i);
+               assert(clr);
                
                /* mark these registers as used */
                for (k = 0 ; k < clr->nRegs ; k++ ) 
@@ -1396,44 +1546,53 @@ static void fillGaps()
                    sym->regs[i] = getRegGprNoSpil ();            
            }
            
-           /* for all its definitions & uses 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++) {
+               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;
                    }
-                   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)));
+               }
+               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 > 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 */
@@ -1589,7 +1748,7 @@ createRegMask (eBBlock ** ebbs, int count)
                          "createRegMask cannot find live range");
                  exit (0);
                }
-             
+#if 0
              /* special case for ruonly */
              if (sym->ruonly && sym->liveFrom != sym->liveTo) {
                  int size = getSize(sym->type);
@@ -1598,6 +1757,7 @@ createRegMask (eBBlock ** ebbs, int count)
                      ic->rMask = bitVectSetBit (ic->rMask, j++);
                  continue ;
              }
+#endif
              /* if no register assigned to it */
              if (!sym->nRegs || sym->isspilt)
                continue;
@@ -1621,14 +1781,17 @@ 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);
+         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;
@@ -1639,7 +1802,8 @@ rematStr (symbol * sym)
          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;
     }
 
@@ -1684,10 +1848,7 @@ regTypeNum ()
            }
 
          /* 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 */
-
+            that definition is a get_pointer */
          if (bitVectnBitsOn (sym->defs) == 1 &&
              (ic = hTabItemWithKey (iCodehTab,
                                     bitVectFirstBit (sym->defs))) &&
@@ -1695,19 +1856,18 @@ regTypeNum ()
              !sym->noSpilLoc &&
              !IS_BITVAR (sym->etype))
            {
-
-
-             /* if remat in data space */
-             if (OP_SYMBOL (IC_LEFT (ic))->remat &&
+             /* and that pointer is remat in data space */
+             if (IS_SYMOP (IC_LEFT (ic)) &&
+                 OP_SYMBOL (IC_LEFT (ic))->remat &&
                  !IS_CAST_ICODE(OP_SYMBOL (IC_LEFT (ic))->rematiCode) &&
-                 DCL_TYPE (aggrToPtr (sym->type, FALSE)) == POINTER)
+                 DCL_TYPE (aggrToPtr (operandType(IC_LEFT(ic)), 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);
+                 strncpyz (psym->rname, psym->name, sizeof(psym->rname));
                  sym->isspilt = 1;
                  sym->usl.spillLoc = psym;
                  continue;
@@ -1971,7 +2131,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);
+  OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
   return 1;
 
 }
@@ -2080,6 +2240,8 @@ packRegsForSupport (iCode * ic, eBBlock * ebp)
        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;
       OP_SYMBOL(IC_LEFT(ic))->liveTo = ic->seq;
@@ -2117,6 +2279,8 @@ right:
        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 (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
@@ -2182,7 +2346,7 @@ static int packRegsDPTRnuse( operand *op , int dptr)
            continue ;
 
        if (ic->op == SEND ) {
-           if (ic->argreg != 1) return 0;
+           if (ic->argreg != 1 ) return 0;
            else continue ;
        }
        /* two special cases first */
@@ -2224,6 +2388,33 @@ static int packRegsDPTRnuse( operand *op , int dptr)
            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;
@@ -2270,7 +2461,9 @@ packRegsDPTRuse (operand * op)
        if (ic->op == PCALL) return NULL;
 
        /* if SEND & not the first parameter then giveup */
-       if (ic->op == SEND && ic->argreg != 1) return NULL;
+       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 */
@@ -2330,7 +2523,7 @@ packRegsDPTRuse (operand * op)
 
        if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) && 
            !isOperandEqual(IC_LEFT(ic),op) &&
-           (OP_SYMBOL(IC_LEFT(ic))->liveTo > ic->seq || 
+           (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) && 
@@ -2343,6 +2536,11 @@ packRegsDPTRuse (operand * op)
            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;
 }
 
@@ -2540,6 +2738,8 @@ packForPush (iCode * ic, eBBlock * ebp)
 
   if (dic->op != '=' || POINTER_SET (dic))
     return;
+  
+  if (dic->eBBlockNum != ic->eBBlockNum) return ;
 
   /* make sure the right side does not have any definitions
      inbetween */
@@ -2548,6 +2748,7 @@ packForPush (iCode * ic, eBBlock * ebp)
          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));
@@ -2557,8 +2758,11 @@ packForPush (iCode * ic, eBBlock * ebp)
       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 (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)
     {
@@ -2686,40 +2890,54 @@ packRegisters (eBBlock * ebp)
        }
 
       /* mark the pointer usages */
-      if (POINTER_SET (ic))
+      if (POINTER_SET (ic) && IS_SYMOP (IC_RESULT (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 (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 (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 (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);
+                                     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);
+                                     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);
+                                         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);
+                                         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);
+                                         OP_SYMBOL (IC_RESULT (ic))->iaccess +
+                                         (SPEC_OCLS(OP_SYMBOL (IC_RESULT (ic))->etype) == idata));
            }
        }
 
@@ -2764,6 +2982,7 @@ packRegisters (eBBlock * ebp)
          one and right is not in far space */
       if (POINTER_SET (ic) &&
          !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) {
@@ -2774,6 +2993,7 @@ packRegisters (eBBlock * ebp)
       /* if pointer get */
       if (POINTER_GET (ic) &&
          !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) {
@@ -2806,7 +3026,7 @@ packRegisters (eBBlock * ebp)
                      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);
                      ic = ic->prev;
                    }
                  else
@@ -2829,7 +3049,7 @@ packRegisters (eBBlock * ebp)
                      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);
                      ic = ic->prev;
                    }
                }
@@ -2891,6 +3111,10 @@ ds390_assignRegisters (eBBlock ** ebbs, int count)
   for (i = 0; i < count; i++)
     packRegisters (ebbs[i]);
 
+  /* liveranges probably changed by register packing
+     so we compute them again */
+  recomputeLiveRanges (ebbs, count);
+
   if (options.dump_pack)
     dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
 
@@ -2926,8 +3150,17 @@ 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 (DUMP_RASSGN, ebbs, count);
     dumpLiveRanges (DUMP_LRANGE, liveRanges);
@@ -2945,8 +3178,8 @@ ds390_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 */
   ds390_nRegs = 8;
   freeAllRegs ();