* .version: bumped version to 2.5.6 (pic14 ABI changed)
[fw/sdcc] / src / pic / ralloc.c
index 4d4bd48fab901389da4869db29ecd62ec6a15064..c6f7f3cf5785d5188961f84dc43a70bd85330619 100644 (file)
@@ -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,6 +336,7 @@ static int regname2key(char const *name)
        
 }
 
+static regs *regWithIdx (set *dRegs, int idx, int fixed);
 /*-----------------------------------------------------------------*/
 /* newReg - allocate and init memory for a new register            */
 /*-----------------------------------------------------------------*/
@@ -341,6 +344,20 @@ static regs* newReg(short type, short pc_type, int rIdx, char *name, int size, i
 {
        
        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,10 @@ 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);
+       debugLog( "%s: Created register %s (%p).\n",
+               __FUNCTION__, dReg->name, __builtin_return_address(0) );
+
        return dReg;
 }
 
@@ -470,7 +489,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 +497,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--;
@@ -575,7 +599,7 @@ dirregWithName (char *name)
 int IS_CONFIG_ADDRESS(int address)
 {
        
-       return address == 0x2007;
+       return address == 0x2007 || address == 0x2008;
 }
 
 /*-----------------------------------------------------------------*/
@@ -586,10 +610,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 +627,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 +637,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 +790,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 +821,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 +1209,7 @@ void writeUsedRegs(FILE *of)
        assignRelocatableRegisters(dynAllocRegs,0);
        assignRelocatableRegisters(dynStackRegs,0);
        
+       assignRelocatableRegisters(dynDirectRegs,0);
        /*
        assignRelocatableRegisters(dynDirectRegs,0);
        printf("assignRelocatableRegisters(dynDirectRegs,0);\n");
@@ -1942,14 +1968,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 +2743,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;
@@ -3407,10 +3455,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 +3607,7 @@ packRegsForAccUse (iCode * ic)
 accuse:
        debugLog ("%s - Yes we are using the accumulator\n", __FUNCTION__);
        OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
-       
-       
+#endif 
 }
 
 /*-----------------------------------------------------------------*/