#include "common.h"
#include "ralloc.h"
+#include "device.h"
#include "pcode.h"
#include "gen.h"
/*-----------------------------------------------------------------*/
extern void genpic14Code (iCode *);
-extern void assignConfigWordValue(int address, int value);
+extern void pic14_assignConfigWordValue(int address, int value);
/* Global data */
static struct
static hTab *dynDirectRegNames= NULL;
// static hTab *regHash = NULL; /* a hash table containing ALL registers */
-static int dynrIdx=0x20;
-static int rDirectIdx=0;
+static int dynrIdx = 0x1000;
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;
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 ?
}
+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;
+ regs *dReg, *reg_alias;
+
+ /* check whether a matching register already exists */
+ dReg = dirregWithName( name );
+ if (dReg) {
+ //printf( "%s: already present: %s\n", __FUNCTION__, name );
+ return (dReg);
+ }
+
+ // check whether a register at that location exists
+ reg_alias = regWithIdx( dynDirectRegs, rIdx, 0 );
+ if (!reg_alias) reg_alias = regWithIdx( dynDirectRegs, rIdx, 1 );
+ // create a new register
dReg = Safe_calloc(1,sizeof(regs));
dReg->type = type;
dReg->pc_type = pc_type;
dReg->name = Safe_strdup(buffer);
}
dReg->isFree = 0;
- dReg->wasUsed = 1;
+ dReg->wasUsed = 0;
if (type == REG_SFR)
dReg->isFixed = 1;
else
dReg->address = 0;
dReg->size = size;
dReg->alias = alias;
- dReg->reg_alias = NULL;
+ dReg->reg_alias = reg_alias;
dReg->reglives.usedpFlows = newSet();
dReg->reglives.assignedpFlows = newSet();
+ if (type != REG_STK) hTabAddItem(&dynDirectRegNames, regname2key(dReg->name), dReg);
+ debugLog( "%s: Created register %s.\n", __FUNCTION__, dReg->name);
- hTabAddItem(&dynDirectRegNames, regname2key(name), dReg);
-
return dReg;
}
dReg = setNextItem(dRegs)) {
if(idx == dReg->rIdx && (fixed == (int)dReg->isFixed)) {
+ while (dReg->reg_alias) dReg = dReg->reg_alias;
return dReg;
}
}
return NULL;
}
/*-----------------------------------------------------------------*/
-/* initStack - allocate registers for a psuedo stack */
+/* initStack - allocate registers for a pseudo stack */
/*-----------------------------------------------------------------*/
-void initStack(int base_address, int size)
+void initStack(int base_address, int size, int shared)
{
int i;
-
+ PIC_device *pic;
+
+ pic = pic14_getPIC();
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);
- r->address = base_address; // Pseudo stack needs a fixed location that can be known by all modules
+ char buffer[16];
+ regs *r;
+ SNPRINTF(&buffer[0], 16, "STK%02d", i);
+ // multi-bank device, sharebank prohibited by user
+ r = newReg(REG_STK, PO_GPR_TEMP, base_address--, buffer, 1, shared ? (pic ? pic->bankMask : 0x180) : 0x0);
r->isFixed = 1;
- r->name[0] = 's';
- r->alias = 0x180; // Using shared memory for pseudo stack
+ r->isPublic = 1;
+ r->isEmitted = 1;
+ //r->name[0] = 's';
addSet(&dynStackRegs,r);
- base_address--;
}
}
*-----------------------------------------------------------------*/
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);
while(reg) {
if(STRCASECMP(reg->name, name) == 0) {
+ // handle registers with multiple names
+ while (reg->reg_alias) reg = reg->reg_alias;
return(reg);
}
int IS_CONFIG_ADDRESS(int address)
{
- return address == 0x2007;
+ return ((address == 0x2007) || (address == 0x2008));
}
/*-----------------------------------------------------------------*/
else
idx = address;
} else {
- idx = rDirectIdx++;
+ idx = dynrIdx++;
}
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(!IS_CONFIG_ADDRESS(address)) {
//fprintf(stderr,"allocating new reg %s\n",name);
- reg = newReg(REG_GPR, PO_DIR, rDirectIdx++, name,getSize (OP_SYMBOL (op)->type),0 );
+ reg = newReg(REG_GPR, PO_DIR, dynrIdx++, name,getSize (OP_SYMBOL (op)->type),0 );
debugLog (" -- added %s to hash, size = %d\n", name,reg->size);
//hTabAddItem(&dynDirectRegNames, regname2key(name), reg);
* a new one and put it in the hash table AND in the
* dynDirectRegNames set */
//fprintf (stderr,"%s symbol name %s, size:%d\n", __FUNCTION__,name,size);
- reg = newReg(REG_GPR, PO_DIR, rDirectIdx++, name,size,0 );
+ reg = newReg(REG_GPR, PO_DIR, dynrIdx++, name,size,0 );
for (sym = setFirstItem(sfr->syms); sym; sym = setNextItem(sfr->syms)) {
if (strcmp(reg->name+1,sym->name)==0) {
unsigned a = SPEC_ADDR(sym->etype);
break;
case REG_STK:
- if( (dReg = regWithIdx ( dynStackRegs, idx, fixed)) != NULL ) {
+ if( (dReg = regWithIdx ( dynStackRegs, idx, 0)) != NULL ) {
+ debugLog ("Found a Stack Register!\n");
+ return dReg;
+ } else
+ if( (dReg = regWithIdx ( dynStackRegs, idx, 1)) != NULL ) {
debugLog ("Found a Stack Register!\n");
return dReg;
}
else {
werror (E_STACK_OUT, "Register");
/* return an existing register just to avoid the SDCC crash */
- return regWithIdx ( dynStackRegs, 0x7f, fixed);
+ return regWithIdx ( dynStackRegs, 0x7f, 0);
}
break;
case REG_SFR:
bit_no=0;
sprintf (buffer, "bitfield%d", byte_no);
//fprintf(stderr,"new relocatable bit field\n");
- relocbitfield = newReg(REG_GPR, PO_GPR_BIT,rDirectIdx++,buffer,1,0);
+ relocbitfield = newReg(REG_GPR, PO_GPR_BIT,dynrIdx++,buffer,1,0);
relocbitfield->isBitField = 1;
//addSet(&dynDirectRegs,relocbitfield);
addSet(&dynInternalRegs,relocbitfield);
}
breg->reg_alias = relocbitfield;
- breg->address = rDirectIdx; /* byte_no; */
+ breg->address = dynrIdx; /* byte_no; */
breg->rIdx = bit_no++;
}
}
/* if it does not end here */
if (sym->liveTo > ic->seq)
continue;
-
- /* HACK: result and operand must be disjoint for POINTER_GET/LEFT_OP/RIGHT_OP */
- if (sym->liveTo == ic->seq && (POINTER_GET(ic) || ic->op == LEFT_OP || ic->op == RIGHT_OP))
+
+ /* 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)
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;
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));
}
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 ||
/* 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);
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);