* device/lib/printf_large.c (output_digit, calculate_digit): optimized,
[fw/sdcc] / src / mcs51 / ralloc.c
index 63479c48c54d6ad0c9077552919237e3dbb45d18..82ff7c8dc70c3ae045f188f36262a9e536ddd417 100644 (file)
@@ -51,6 +51,7 @@ static struct
     bitVect *funcrUsed;         /* registers used in a function */
     int stackExtend;
     int dataExtend;
+    bitVect *allBitregs;        /* all bit registers */
   }
 _G;
 
@@ -61,26 +62,34 @@ int mcs51_ptrRegReq;            /* one byte pointer register required */
 regs regs8051[] =
 {
 
-  {REG_GPR, R2_IDX, REG_GPR, "r2", "ar2", "0", 2, 1},
-  {REG_GPR, R3_IDX, REG_GPR, "r3", "ar3", "0", 3, 1},
-  {REG_GPR, R4_IDX, REG_GPR, "r4", "ar4", "0", 4, 1},
-  {REG_GPR, R5_IDX, REG_GPR, "r5", "ar5", "0", 5, 1},
-  {REG_GPR, R6_IDX, REG_GPR, "r6", "ar6", "0", 6, 1},
-  {REG_GPR, R7_IDX, REG_GPR, "r7", "ar7", "0", 7, 1},
-  {REG_PTR, R0_IDX, REG_PTR, "r0", "ar0", "0", 0, 1},
-  {REG_PTR, R1_IDX, REG_PTR, "r1", "ar1", "0", 1, 1},
-  {REG_GPR, X8_IDX, REG_GPR, "x8", "x8", "xreg", 0, 1},
-  {REG_GPR, X9_IDX, REG_GPR, "x9", "x9", "xreg", 1, 1},
+  {REG_GPR, R2_IDX,  REG_GPR, "r2",  "ar2", "0",    2, 1},
+  {REG_GPR, R3_IDX,  REG_GPR, "r3",  "ar3", "0",    3, 1},
+  {REG_GPR, R4_IDX,  REG_GPR, "r4",  "ar4", "0",    4, 1},
+  {REG_GPR, R5_IDX,  REG_GPR, "r5",  "ar5", "0",    5, 1},
+  {REG_GPR, R6_IDX,  REG_GPR, "r6",  "ar6", "0",    6, 1},
+  {REG_GPR, R7_IDX,  REG_GPR, "r7",  "ar7", "0",    7, 1},
+  {REG_PTR, R0_IDX,  REG_PTR, "r0",  "ar0", "0",    0, 1},
+  {REG_PTR, R1_IDX,  REG_PTR, "r1",  "ar1", "0",    1, 1},
+  {REG_BIT, B0_IDX,  REG_BIT, "b0",  "b0",  "bits", 0, 1},
+  {REG_BIT, B1_IDX,  REG_BIT, "b1",  "b1",  "bits", 1, 1},
+  {REG_BIT, B2_IDX,  REG_BIT, "b2",  "b2",  "bits", 2, 1},
+  {REG_BIT, B3_IDX,  REG_BIT, "b3",  "b3",  "bits", 3, 1},
+  {REG_BIT, B4_IDX,  REG_BIT, "b4",  "b4",  "bits", 4, 1},
+  {REG_BIT, B5_IDX,  REG_BIT, "b5",  "b5",  "bits", 5, 1},
+  {REG_BIT, B6_IDX,  REG_BIT, "b6",  "b6",  "bits", 6, 1},
+  {REG_BIT, B7_IDX,  REG_BIT, "b7",  "b7",  "bits", 7, 1},
+  {REG_GPR, X8_IDX,  REG_GPR, "x8",  "x8",  "xreg", 0, 1},
+  {REG_GPR, X9_IDX,  REG_GPR, "x9",  "x9",  "xreg", 1, 1},
   {REG_GPR, X10_IDX, REG_GPR, "x10", "x10", "xreg", 2, 1},
   {REG_GPR, X11_IDX, REG_GPR, "x11", "x11", "xreg", 3, 1},
   {REG_GPR, X12_IDX, REG_GPR, "x12", "x12", "xreg", 4, 1},
-  {REG_CND, CND_IDX, REG_CND, "C", "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},
+  {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 = 17;
+int mcs51_nRegs = 16;
 static void spillThis (symbol *);
 static void freeAllRegs ();
 
@@ -238,6 +247,15 @@ computeSpillable (iCode * ic)
 
 }
 
+/*-----------------------------------------------------------------*/
+/* bitType - will return 1 if the symbol has type REG_BIT          */
+/*-----------------------------------------------------------------*/
+static int
+bitType (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return (sym->regType == REG_BIT ? 1 : 0);
+}
+
 /*-----------------------------------------------------------------*/
 /* noSpilLoc - return true if a variable has no spil location      */
 /*-----------------------------------------------------------------*/
@@ -257,7 +275,7 @@ hasSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
 }
 
 /*-----------------------------------------------------------------*/
-/* directSpilLoc - will return 1 if the splilocation is in direct  */
+/* directSpilLoc - will return 1 if the spillocation is in direct  */
 /*-----------------------------------------------------------------*/
 static int
 directSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
@@ -360,7 +378,7 @@ leastUsedLR (set * sset)
     {
 
       /* if usage is the same then prefer
-         the spill the smaller of the two */
+         to spill the smaller of the two */
       if (lsym->used == sym->used)
         if (getSize (lsym->type) < getSize (sym->type))
           sym = lsym;
@@ -505,7 +523,10 @@ createStackSpil (symbol * sym)
   /* set the type to the spilling symbol */
   sloc->type = copyLinkChain (sym->type);
   sloc->etype = getSpec (sloc->type);
-  SPEC_SCLS (sloc->etype) = S_DATA;
+  if (!IS_BIT (sloc->etype))
+    {
+      SPEC_SCLS (sloc->etype) = S_DATA;
+    }
   SPEC_EXTR (sloc->etype) = 0;
   SPEC_STAT (sloc->etype) = 0;
   SPEC_VOLATILE(sloc->etype) = 0;
@@ -633,10 +654,20 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
   /* get the spillable live ranges */
   lrcs = computeSpillable (ic);
 
-  /* get all live ranges that are rematerizable */
-  if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
+  /* remove incompatible registers */
+  if ((forSym->regType == REG_PTR) || (forSym->regType == REG_GPR))
+    {
+      selectS = liveRangesWith (lrcs, bitType, ebp, ic);
+      
+      for (sym = setFirstItem (selectS); sym; sym = setNextItem (selectS))
     {
+          bitVectUnSetBit (lrcs, sym->key);
+        }
+    }
 
+  /* get all live ranges that are rematerializable */
+  if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
+    {
       /* return the least used of these */
       return leastUsedLR (selectS);
     }
@@ -658,7 +689,6 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
   /* if the symbol is local to the block then */
   if (forSym->liveTo < ebp->lSeq)
     {
-
       /* check if there are any live ranges allocated
          to registers that are not used in this block */
       if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
@@ -695,7 +725,6 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
   /* find live ranges with spillocation && not used as pointers */
   if ((selectS = liveRangesWith (lrcs, hasSpilLocnoUptr, ebp, ic)))
     {
-
       sym = leastUsedLR (selectS);
       /* mark this as allocation required */
       sym->usl.spillLoc->allocreq++;
@@ -705,7 +734,6 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
   /* find live ranges with spillocation */
   if ((selectS = liveRangesWith (lrcs, hasSpilLoc, ebp, ic)))
     {
-
       sym = leastUsedLR (selectS);
       sym->usl.spillLoc->allocreq++;
       return sym;
@@ -716,7 +744,6 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
      used ofcourse */
   if ((selectS = liveRangesWith (lrcs, noSpilLoc, ebp, ic)))
     {
-
       /* return a created spil location */
       sym = createStackSpil (leastUsedLR (selectS));
       sym->usl.spillLoc->allocreq++;
@@ -863,7 +890,22 @@ tryAgain:
 }
 
 /*-----------------------------------------------------------------*/
-/* getRegPtrNoSpil - get it cannot split                           */
+/* getRegBit - will try for Bit if not spill this                  */
+/*-----------------------------------------------------------------*/
+static regs *getRegBit (symbol * sym)
+{
+  regs *reg;
+
+  /* try for a bit type */
+  if ((reg = allocReg (REG_BIT)))
+    return reg;
+
+  spillThis (sym);
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegPtrNoSpil - get it cannot be spilt                        */
 /*-----------------------------------------------------------------*/
 static regs *getRegPtrNoSpil()
 {
@@ -884,7 +926,7 @@ static regs *getRegPtrNoSpil()
 }
 
 /*-----------------------------------------------------------------*/
-/* getRegGprNoSpil - get it cannot split                           */
+/* getRegGprNoSpil - get it cannot be spilt                           */
 /*-----------------------------------------------------------------*/
 static regs *getRegGprNoSpil()
 {
@@ -903,6 +945,27 @@ static regs *getRegGprNoSpil()
   return 0;
 }
 
+/*-----------------------------------------------------------------*/
+/* getRegBitNoSpil - get it cannot be spilt                        */
+/*-----------------------------------------------------------------*/
+static regs *getRegBitNoSpil()
+{
+  regs *reg;
+
+  /* try for a ptr type */
+  if ((reg = allocReg (REG_BIT)))
+    return reg;
+
+  /* try for gpr type */
+  if ((reg = allocReg (REG_GPR)))
+    return reg;
+
+  assert(0);
+
+  /* just to make the compiler happy */
+  return 0;
+}
+
 /*-----------------------------------------------------------------*/
 /* symHasReg - symbol has a given register                         */
 /*-----------------------------------------------------------------*/
@@ -918,6 +981,29 @@ symHasReg (symbol * sym, regs * reg)
   return FALSE;
 }
 
+/*-----------------------------------------------------------------*/
+/* updateRegUsage -  update the registers in use at the start of   */
+/*                   this icode                                    */
+/*-----------------------------------------------------------------*/
+static void
+updateRegUsage (iCode * ic)
+{
+  int reg;
+
+  for (reg=0; reg<mcs51_nRegs; reg++)
+    {
+      if (regs8051[reg].isFree)
+        {
+          ic->riu &= ~(1<<regs8051[reg].offset);
+        }
+      else
+        {
+          ic->riu |= (1<<regs8051[reg].offset);
+          BitBankUsed |= (reg >= 8);
+        }
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* deassignLRs - check the live to and if they have registers & are */
 /*               not spilt then free up the registers              */
@@ -1051,8 +1137,8 @@ reassignLR (operand * op)
 static int
 willCauseSpill (int nr, int rt)
 {
-  /* first check if there are any avlb registers
-     of te type required */
+  /* first check if there are any available registers
+     of the type required */
   if (rt == REG_PTR)
     {
       /* special case for pointer type
@@ -1063,6 +1149,11 @@ willCauseSpill (int nr, int rt)
       if (nFreeRegs (REG_GPR) >= nr)
         return 0;
     }
+  else if (rt == REG_BIT)
+    {
+      if (nFreeRegs (rt) >= nr)
+        return 0;
+    }
   else
     {
       if (mcs51_ptrRegReq)
@@ -1167,21 +1258,11 @@ serialRegAssign (eBBlock ** ebbs, int count)
            ebbs[i]->entryLabel != returnLabel))
         continue;
 
-      /* of all instructions do */
+      /* for 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
+            updateRegUsage(ic);
+
             /* if this is an ipop that means some live
                range will have to be assigned again */
             if (ic->op == IPOP)
@@ -1214,6 +1295,13 @@ serialRegAssign (eBBlock ** ebbs, int count)
                 int j;
                 int ptrRegSet = 0;
 
+                /* Make sure any spill location is definitely allocated */
+                if (sym->isspilt && !sym->remat && sym->usl.spillLoc &&
+                    !sym->usl.spillLoc->allocreq)
+                  {
+                    sym->usl.spillLoc->allocreq++;
+                  }
+                  
                 /* if it does not need or is spilt
                    or is already assigned to registers
                    or will not live beyond this instructions */
@@ -1230,11 +1318,20 @@ serialRegAssign (eBBlock ** ebbs, int count)
                     spillThis (sym);
                     continue;
                 }
+
+                willCS = willCauseSpill (sym->nRegs, sym->regType);
+                /* if this is a bit variable then don't use precious registers
+                   along with expensive bit-to-char conversions but just spill
+                   it */
+                if (willCS && SPEC_NOUN(sym->etype) == V_BIT) {
+                    spillThis (sym);
+                    continue;
+                }
+
                 /* if trying to allocate this will cause
                    a spill and there is nothing to spill
                    or this one is rematerializable then
                    spill this one */
-                willCS = willCauseSpill (sym->nRegs, sym->regType);
                 spillable = computeSpillable (ic);
                 if (sym->remat || (willCS && bitVectIsZero (spillable))) {
                     spillThis (sym);
@@ -1299,13 +1396,15 @@ serialRegAssign (eBBlock ** ebbs, int count)
                     sym->regs[j] = NULL;
                     if (sym->regType == REG_PTR)
                         sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
+                    else if (sym->regType == REG_BIT)
+                        sym->regs[j] = getRegBit (sym);
                     else
                       {
                         if (ic->op == CAST && IS_SYMOP (IC_RIGHT (ic)))
                           {
                             symbol * right = OP_SYMBOL (IC_RIGHT (ic));
 
-                            if (right->regs[j])
+                            if (right->regs[j] && (right->regType != REG_BIT))
                               sym->regs[j] = allocThisReg (right->regs[j]);
                           }
                         if (!sym->regs[j])
@@ -1316,6 +1415,7 @@ serialRegAssign (eBBlock ** ebbs, int count)
                        this was spilt then break */
                     if (!sym->regs[j])
                       {
+                        int i;
                         for (i=0; i < sym->nRegs ; i++ )
                           sym->regs[i] = NULL;
                         break;
@@ -1438,11 +1538,13 @@ static void fillGaps()
               }
           }
 
-        D(printf("Atemping fillGaps on %s: [",sym->name));
+        D(printf("Attempting 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 if (sym->regType == REG_BIT)
+                sym->regs[i] = getRegBitNoSpil ();
             else
               {
                 sym->regs[i] = NULL;
@@ -1551,6 +1653,33 @@ static void fillGaps()
     }
 }
 
+/*-----------------------------------------------------------------*/
+/* findAllBitregs :- returns bit vector of all bit registers       */
+/*-----------------------------------------------------------------*/
+static bitVect *
+findAllBitregs (void)
+{
+  bitVect *rmask = newBitVect (mcs51_nRegs);
+  int j;
+
+  for (j = 0; j < mcs51_nRegs; j++)
+    {
+      if (regs8051[j].type == REG_BIT)
+        rmask = bitVectSetBit (rmask, regs8051[j].rIdx);
+    }
+
+  return rmask;
+}
+
+/*-----------------------------------------------------------------*/
+/* mcs51_allBitregs :- returns bit vector of all bit registers     */
+/*-----------------------------------------------------------------*/
+bitVect *
+mcs51_allBitregs (void)
+{
+  return _G.allBitregs;
+}
+
 /*-----------------------------------------------------------------*/
 /* rUmaskForOp :- returns register mask for an operand             */
 /*-----------------------------------------------------------------*/
@@ -1577,8 +1706,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);
+        rumask = bitVectSetBit (rumask, sym->regs[j]->rIdx);
     }
 
   return rumask;
@@ -1807,13 +1935,12 @@ regTypeNum (eBBlock *ebbs)
             }
 
           /* determine the type of register required */
-          if (sym->nRegs == 1 &&
-              IS_PTR (sym->type) &&
-              sym->uptr)
+          if (sym->nRegs == 1 && IS_PTR (sym->type) && sym->uptr)
             sym->regType = REG_PTR;
+          else if (IS_BIT(sym->type))
+            sym->regType = REG_BIT;
           else
             sym->regType = REG_GPR;
-
         }
       else
         /* for the first run we don't provide */
@@ -2342,7 +2469,7 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
   /* this routine will mark the a symbol as used in one
      instruction use only && if the defintion is local
      (ie. within the basic block) && has only one definition &&
-     that definiion is either a return value from a
+     that definition is either a return value from a
      function or does not contain any variables in
      far space */
   if (bitVectnBitsOn (OP_USES (op)) > 1)
@@ -2710,7 +2837,7 @@ accuse:
 }
 
 /*-----------------------------------------------------------------*/
-/* packForPush - hueristics to reduce iCode for pushing            */
+/* packForPush - heuristics to reduce iCode for pushing            */
 /*-----------------------------------------------------------------*/
 static void
 packForPush (iCode * ic, eBBlock ** ebpp, int blockno)
@@ -3110,8 +3237,10 @@ packRegisters (eBBlock ** ebpp, int blockno)
 /* assignRegisters - assigns registers to each live range as need  */
 /*-----------------------------------------------------------------*/
 void
-mcs51_assignRegisters (eBBlock ** ebbs, int count)
+mcs51_assignRegisters (ebbIndex * ebbi)
 {
+  eBBlock ** ebbs = ebbi->bbOrder;
+  int count = ebbi->count;
   iCode *ic;
   int i;
 
@@ -3119,7 +3248,16 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count)
   setToNull ((void *) &_G.regAssigned);
   setToNull ((void *) &_G.totRegAssigned);
   mcs51_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
+  if ((currFunc && IFFUNC_ISREENT (currFunc->type)) || options.stackAuto)
+    {
+      mcs51_nRegs = 16;
+    }
+  else
+    {
   mcs51_nRegs = 8;
+    }
+  _G.allBitregs = findAllBitregs ();
+
 
   /* change assignments this will remove some
      live ranges reducing some register pressure */
@@ -3132,7 +3270,7 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count)
   recomputeLiveRanges (ebbs, count);
 
   if (options.dump_pack)
-    dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
+    dumpEbbsToFileExt (DUMP_PACK, ebbi);
 
   /* first determine for each live range the number of
      registers & the type of registers required for each */
@@ -3180,7 +3318,7 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count)
 
   if (options.dump_rassgn)
     {
-      dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
+      dumpEbbsToFileExt (DUMP_RASSGN, ebbi);
       dumpLiveRanges (DUMP_LRANGE, liveRanges);
     }