* src/SDCCval.c (checkConstantRange): added
[fw/sdcc] / src / pic / ralloc.c
index 4d4bd48fab901389da4869db29ecd62ec6a15064..d8b5d8df9a6a0f979f3301a8f847e06f1f39f690 100644 (file)
@@ -52,7 +52,7 @@
 /*-----------------------------------------------------------------*/
 
 extern void genpic14Code (iCode *);
-extern void assignConfigWordValue(int address, int value);
+extern void pic14_assignConfigWordValue(int address, int value);
 
 /* Global data */
 static struct
@@ -88,7 +88,8 @@ static int rDirectIdx=0;
 int pic14_nRegs = 128;   // = sizeof (regspic14) / sizeof (regs);
 
 int Gstack_base_addr=0; /* The starting address of registers that
-* are used to pass and return parameters */
+                        * are used to pass and return parameters */
+int Gstack_size = 0;
 
 
 
@@ -133,8 +134,9 @@ static void
        vsprintf (buffer, fmt, ap);
 
        fprintf (debugF, "%s", buffer);
+       //if (options.verbose) fprintf (stderr, "%s: %s", __FUNCTION__, buffer);
        /*
-       while (isspace(*bufferP)) bufferP++;
+       while (isspace((unsigned char)*bufferP)) bufferP++;
 
        if (bufferP && *bufferP) 
                lineCurr = (lineCurr ?
@@ -334,13 +336,28 @@ static int regname2key(char const *name)
        
 }
 
+static regs *regWithIdx (set *dRegs, int idx, int fixed);
 /*-----------------------------------------------------------------*/
 /* newReg - allocate and init memory for a new register            */
 /*-----------------------------------------------------------------*/
-static regs* newReg(short type, short pc_type, int rIdx, char *name, int size, int alias)
+static regs* newReg(short type, PIC_OPTYPE pc_type, int rIdx, char *name, int size, int alias)
 {
        
        regs *dReg;
+
+       /* check whether a matching register already exists */
+       dReg = dirregWithName( name );
+       if (dReg) {
+         //printf( "%s: already present: %s\n", __FUNCTION__, name );
+         return (dReg);
+       }
+       dReg = regWithIdx( dynDirectRegs, rIdx, 0 );
+       if (!dReg) dReg = regWithIdx( dynDirectRegs, rIdx, 1 );
+       if (dReg)
+       {
+         //printf(  "%s: already present %s (idx:%d/%x)", __FUNCTION__, name, rIdx, rIdx );
+         return (dReg);
+       }
        
        dReg = Safe_calloc(1,sizeof(regs));
        dReg->type = type;
@@ -353,7 +370,7 @@ static regs* newReg(short type, short pc_type, int rIdx, char *name, int size, i
                dReg->name = Safe_strdup(buffer);
        }
        dReg->isFree = 0;
-       dReg->wasUsed = 1;
+       dReg->wasUsed = 0;
        if (type == REG_SFR)
                dReg->isFixed = 1;
        else
@@ -370,8 +387,14 @@ static regs* newReg(short type, short pc_type, int rIdx, char *name, int size, i
        dReg->reglives.usedpFlows = newSet();
        dReg->reglives.assignedpFlows = newSet();
        
-       hTabAddItem(&dynDirectRegNames, regname2key(name), dReg);
-       
+       hTabAddItem(&dynDirectRegNames, regname2key(dReg->name), dReg);
+#ifdef __GNUC__
+       debugLog( "%s: Created register %s (%p).\n",
+               __FUNCTION__, dReg->name, __builtin_return_address(0) );
+#else
+       debugLog( "%s: Created register %s.\n",
+               __FUNCTION__, dReg->name);
+#endif
        return dReg;
 }
 
@@ -470,7 +493,7 @@ regFindFree (set *dRegs)
        return NULL;
 }
 /*-----------------------------------------------------------------*/
-/* initStack - allocate registers for a psuedo stack               */
+/* initStack - allocate registers for a pseudo stack               */
 /*-----------------------------------------------------------------*/
 void initStack(int base_address, int size)
 {
@@ -478,13 +501,18 @@ void initStack(int base_address, int size)
        int i;
        
        Gstack_base_addr = base_address;
-       //fprintf(stderr,"initStack");
+       Gstack_size = size;
+       //fprintf(stderr,"initStack [base:0x%02x, size:%d]\n", base_address, size);
        
        for(i = 0; i<size; i++) {
-               regs *r = newReg(REG_STK, PO_GPR_TEMP,base_address,NULL,1,0);
+               char buffer[16];
+               regs *r;
+               SNPRINTF(&buffer[0], 16, "STK%02d", i);
+               r = newReg(REG_STK, PO_GPR_TEMP,base_address,buffer,1,0);
                r->address = base_address; // Pseudo stack needs a fixed location that can be known by all modules
                r->isFixed = 1;
-               r->name[0] = 's';
+               r->isPublic = 1;
+               //r->name[0] = 's';
                r->alias = 0x180; // Using shared memory for pseudo stack
                addSet(&dynStackRegs,r);
                base_address--;
@@ -505,7 +533,7 @@ allocProcessorRegister(int rIdx, char * name, short po_type, int alias)
 *-----------------------------------------------------------------*/
 
 regs *
-allocInternalRegister(int rIdx, char * name, short po_type, int alias)
+allocInternalRegister(int rIdx, char * name, PIC_OPTYPE po_type, int alias)
 {
        regs * reg = newReg(REG_GPR, po_type, rIdx, name,1,alias);
        
@@ -575,7 +603,7 @@ dirregWithName (char *name)
 int IS_CONFIG_ADDRESS(int address)
 {
        
-       return address == 0x2007;
+       return ((address == 0x2007) || (address == 0x2008));
 }
 
 /*-----------------------------------------------------------------*/
@@ -586,10 +614,11 @@ allocNewDirReg (sym_link *symlnk,const char *name)
 {
        regs *reg;
        int address = 0;
+       sym_link *spec = getSpec (symlnk);
        
        /* if this is at an absolute address, then get the address. */
-       if (SPEC_ABSA (symlnk) ) {
-               address = SPEC_ADDR (symlnk);
+       if (SPEC_ABSA (spec) ) {
+               address = SPEC_ADDR (spec);
                //fprintf(stderr,"reg %s is at an absolute address: 0x%03x\n",name,address);
        }
        
@@ -602,7 +631,7 @@ allocNewDirReg (sym_link *symlnk,const char *name)
        } else {
                int idx;
                if (address) {
-                       if (IS_BITVAR (symlnk))
+                       if (IS_BITVAR (spec))
                                idx = address >> 3;
                        else
                                idx = address;
@@ -612,20 +641,20 @@ allocNewDirReg (sym_link *symlnk,const char *name)
                reg = newReg(REG_GPR, PO_DIR, idx, (char*)name,getSize (symlnk),0 );
                debugLog ("  -- added %s to hash, size = %d\n", (char*)name,reg->size);
                
-               if (SPEC_ABSA (symlnk) ) {
+               if (SPEC_ABSA (spec) ) {
                        reg->type = REG_SFR;
                }
                
-               if (IS_BITVAR (symlnk)) {
+               if (IS_BITVAR (spec)) {
                        addSet(&dynDirectBitRegs, reg);
                        reg->isBitField = 1;
                } else
                        addSet(&dynDirectRegs, reg);
                
-               if (!IS_STATIC (symlnk)) {
+               if (!IS_STATIC (spec)) {
                        reg->isPublic = 1;
                }
-               if (IS_EXTERN (symlnk)) {
+               if (IS_EXTERN (spec)) {
                        reg->isExtern = 1;
                }
                
@@ -765,7 +794,7 @@ allocDirReg (operand *op )
                        debugLog ("  -- and it is at a fixed address 0x%02x\n",reg->address);
                }
        } else {
-               allocNewDirReg (OP_SYM_ETYPE(op),name);
+               allocNewDirReg (OP_SYM_TYPE(op),name);
        }
        
        return reg;
@@ -796,7 +825,7 @@ allocRegByName (char *name, int size)
                /* Register wasn't found in hash, so let's create
                * a new one and put it in the hash table AND in the 
                * dynDirectRegNames set */
-               //fprintf (stderr,"%s symbol name %s\n", __FUNCTION__,name);
+               //fprintf (stderr,"%s symbol name %s, size:%d\n", __FUNCTION__,name,size);
                reg = newReg(REG_GPR, PO_DIR, rDirectIdx++, name,size,0 );
                for (sym = setFirstItem(sfr->syms); sym; sym = setNextItem(sfr->syms)) {
                        if (strcmp(reg->name+1,sym->name)==0) {
@@ -1184,6 +1213,7 @@ void writeUsedRegs(FILE *of)
        assignRelocatableRegisters(dynAllocRegs,0);
        assignRelocatableRegisters(dynStackRegs,0);
        
+       assignRelocatableRegisters(dynDirectRegs,0);
        /*
        assignRelocatableRegisters(dynDirectRegs,0);
        printf("assignRelocatableRegisters(dynDirectRegs,0);\n");
@@ -1942,14 +1972,36 @@ deassignLRs (iCode * ic, eBBlock * ebp)
                /* if it does not end here */
                if (sym->liveTo > ic->seq)
                        continue;
-       
-               /* HACK: result and addr must be disjoint for POINTER_GET */
-               if (sym->liveTo == ic->seq && POINTER_GET(ic))
+
+               /* Prevent the result from being assigned the same registers as (one)
+                * operand as many genXXX-functions fail otherwise.
+                * POINTER_GET(ic) || ic->op == LEFT_OP || ic->op == RIGHT_OP || ic->op == NOT
+                * are known to fail. */
+               if (sym->liveTo == ic->seq && IC_RESULT(ic))
                {
-                       //piCode (ic, stderr); fprintf (stderr, " -- registers NOT deallocated\n");
-                       continue;
+                       switch (ic->op)
+                       {
+                       case '=':       /* assignment */
+                       case BITWISEAND: /* bitwise AND */
+                       case '|':       /* bitwise OR */
+                       case '^':       /* bitwise XOR */
+                       case '~':       /* bitwise negate */
+                       case RLC:       /* rotate through carry */
+                       case RRC:
+                       case UNARYMINUS:
+                       case '+':       /* addition */
+                       case '-':       /* subtraction */
+                         /* go ahead, these are safe to use with
+                          * non-disjoint register sets */
+                         break;
+
+                       default:
+                               /* do not release operand registers */
+                               //fprintf (stderr, "%s:%u: operand not freed: ", __FILE__, __LINE__); piCode (ic, stderr); fprintf (stderr, "\n");
+                               continue;
+                       } // switch
                }
-               
+       
                /* if it was spilt on stack then we can 
                mark the stack spil location as free */
                if (sym->isspilt)
@@ -2695,7 +2747,7 @@ regTypeNum ()
                                        
                                        debugLog ("  %d - \n", __LINE__);
                                
-                                       /* create a psuedo symbol & force a spil */
+                                       /* create a pseudo symbol & force a spil */
                                        //X symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
                                        psym = rematStr (OP_SYMBOL (IC_LEFT (ic)));
                                        psym->type = sym->type;
@@ -2909,7 +2961,7 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
                        if(IS_VALOP(IC_RIGHT(ic))) {
                                debugLog ("  setting config word to %x\n", 
                                        (int) floatFromVal (IC_RIGHT(ic)->operand.valOperand));
-                               assignConfigWordValue(  SPEC_ADDR ( OP_SYM_ETYPE(IC_RESULT(ic))),
+                               pic14_assignConfigWordValue(  SPEC_ADDR ( OP_SYM_ETYPE(IC_RESULT(ic))),
                                        (int) floatFromVal (IC_RIGHT(ic)->operand.valOperand));
                        }
                        
@@ -3032,6 +3084,19 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
        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 the result is on stack or iaccess then it must be
        the same at least one of the operands */
        if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
@@ -3407,10 +3472,22 @@ isBitwiseOptimizable (iCode * ic)
 static void
 packRegsForAccUse (iCode * ic)
 {
-       iCode *uic;
+       //iCode *uic;
        
        debugLog ("%s\n", __FUNCTION__);
+
+       /* result too large for WREG? */
+       if (getSize (operandType (IC_RESULT (ic))) > 1)
+         return;
        
+       /* We have to make sure that OP_SYMBOL(IC_RESULT(ic))
+        * is never used as an operand to an instruction that
+        * cannot have WREG as an operand (e.g. BTFSx cannot
+        * operate on WREG...
+        * For now, store all results into proper registers. */
+       return;
+
+#if 0
        /* if this is an aggregate, e.g. a one byte char array */
        if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
                return;
@@ -3547,8 +3624,7 @@ packRegsForAccUse (iCode * ic)
 accuse:
        debugLog ("%s - Yes we are using the accumulator\n", __FUNCTION__);
        OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
-       
-       
+#endif 
 }
 
 /*-----------------------------------------------------------------*/
@@ -3691,7 +3767,7 @@ packRegisters (eBBlock * ebp)
                /* TrueSym := iTempNN:1             */
                for (ic = ebp->sch; ic; ic = ic->next)
                {
-                       
+
                        /* find assignment of the form TrueSym := iTempNN:1 */
                        if (ic->op == '=' && !POINTER_SET (ic))
                                change += packRegsForAssign (ic, ebp);
@@ -4071,8 +4147,8 @@ pic14_assignRegisters (ebbIndex * ebbi)
        iCode *ic;
        int i;
        
-       debugLog ("<><><><><><><><><><><><><><><><><>\nstarting\t%s:%s", __FILE__, __FUNCTION__);
-       debugLog ("\nebbs before optimizing:\n");
+       debugLog ("<><><><><><><><><><><><><><><><><>\nstarting\t%s:%s\n", __FILE__, __FUNCTION__);
+       debugLog ("ebbs before optimizing:\n");
        dumpEbbsToDebug (ebbs, count);
        
        setToNull ((void *) &_G.funcrUsed);