Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
Added Pic Port T.scott Dattalo scott@dattalo.com (2000)
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- In other words, you are welcome to use, share and improve this program.
- You are forbidden to forbid anyone else to use, share and improve
- what you give them. Help stamp out software-hoarding!
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding!
-------------------------------------------------------------------------*/
#include "common.h"
#include "pcode.h"
#include "gen.h"
+
#if defined(__BORLANDC__) || defined(_MSC_VER)
#define STRCASECMP stricmp
+#define FENTRY2 1 ? (void)0 : printf
#else
#define STRCASECMP strcasecmp
+//#define FENTRY2(fmt,...) do { fprintf (stderr, "%s:%d: called.\n", __FUNCTION__, __LINE__); fprintf (stderr, fmt, ## __VA_ARGS__); } while (0)
+#define FENTRY2 1 ? (void)0 : printf
#endif
/* this should go in SDCCicode.h, but it doesn't. */
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;
fprintf (debugF, "%s", buffer);
/*
- while (isspace(*bufferP)) bufferP++;
+ while (isspace((unsigned char)*bufferP)) bufferP++;
if (bufferP && *bufferP)
lineCurr = (lineCurr ?
switch (op)
{
- case IDENTIFIER:
- return "IDENTIFIER";
- case TYPE_NAME:
- return "TYPE_NAME";
- case CONSTANT:
- return "CONSTANT";
- case STRING_LITERAL:
- return "STRING_LITERAL";
- case SIZEOF:
- return "SIZEOF";
- case PTR_OP:
- return "PTR_OP";
- case INC_OP:
- return "INC_OP";
- case DEC_OP:
- return "DEC_OP";
- case LEFT_OP:
- return "LEFT_OP";
- case RIGHT_OP:
- return "RIGHT_OP";
- case LE_OP:
- return "LE_OP";
- case GE_OP:
- return "GE_OP";
- case EQ_OP:
- return "EQ_OP";
- case NE_OP:
- return "NE_OP";
- case AND_OP:
- return "AND_OP";
- case OR_OP:
- return "OR_OP";
- case MUL_ASSIGN:
- return "MUL_ASSIGN";
- case DIV_ASSIGN:
- return "DIV_ASSIGN";
- case MOD_ASSIGN:
- return "MOD_ASSIGN";
- case ADD_ASSIGN:
- return "ADD_ASSIGN";
- case SUB_ASSIGN:
- return "SUB_ASSIGN";
- case LEFT_ASSIGN:
- return "LEFT_ASSIGN";
- case RIGHT_ASSIGN:
- return "RIGHT_ASSIGN";
- case AND_ASSIGN:
- return "AND_ASSIGN";
- case XOR_ASSIGN:
- return "XOR_ASSIGN";
- case OR_ASSIGN:
- return "OR_ASSIGN";
- case TYPEDEF:
- return "TYPEDEF";
- case EXTERN:
- return "EXTERN";
- case STATIC:
- return "STATIC";
- case AUTO:
- return "AUTO";
- case REGISTER:
- return "REGISTER";
- case CODE:
- return "CODE";
- case EEPROM:
- return "EEPROM";
- case INTERRUPT:
- return "INTERRUPT";
- case SFR:
- return "SFR";
- case AT:
- return "AT";
- case SBIT:
- return "SBIT";
- case REENTRANT:
- return "REENTRANT";
- case USING:
- return "USING";
- case XDATA:
- return "XDATA";
- case DATA:
- return "DATA";
- case IDATA:
- return "IDATA";
- case PDATA:
- return "PDATA";
- case VAR_ARGS:
- return "VAR_ARGS";
- case CRITICAL:
- return "CRITICAL";
- case NONBANKED:
- return "NONBANKED";
- case BANKED:
- return "BANKED";
- case CHAR:
- return "CHAR";
- case SHORT:
- return "SHORT";
- case INT:
- return "INT";
- case LONG:
- return "LONG";
- case SIGNED:
- return "SIGNED";
- case UNSIGNED:
- return "UNSIGNED";
- case FLOAT:
- return "FLOAT";
- case DOUBLE:
- return "DOUBLE";
- case CONST:
- return "CONST";
- case VOLATILE:
- return "VOLATILE";
- case VOID:
- return "VOID";
- case BIT:
- return "BIT";
- case STRUCT:
- return "STRUCT";
- case UNION:
- return "UNION";
- case ENUM:
- return "ENUM";
- case ELIPSIS:
- return "ELIPSIS";
- case RANGE:
- return "RANGE";
- case FAR:
- return "FAR";
- case CASE:
- return "CASE";
- case DEFAULT:
- return "DEFAULT";
- case IF:
- return "IF";
- case ELSE:
- return "ELSE";
- case SWITCH:
- return "SWITCH";
- case WHILE:
- return "WHILE";
- case DO:
- return "DO";
- case FOR:
- return "FOR";
- case GOTO:
- return "GOTO";
- case CONTINUE:
- return "CONTINUE";
- case BREAK:
- return "BREAK";
- case RETURN:
- return "RETURN";
- case INLINEASM:
- return "INLINEASM";
- case IFX:
- return "IFX";
- case ADDRESS_OF:
- return "ADDRESS_OF";
- case GET_VALUE_AT_ADDRESS:
- return "GET_VALUE_AT_ADDRESS";
- case SPIL:
- return "SPIL";
- case UNSPIL:
- return "UNSPIL";
- case GETHBIT:
- return "GETHBIT";
- case BITWISEAND:
- return "BITWISEAND";
- case UNARYMINUS:
- return "UNARYMINUS";
- case IPUSH:
- return "IPUSH";
- case IPOP:
- return "IPOP";
- case PCALL:
- return "PCALL";
- case ENDFUNCTION:
- return "ENDFUNCTION";
- case JUMPTABLE:
- return "JUMPTABLE";
- case RRC:
- return "RRC";
- case RLC:
- return "RLC";
- case CAST:
- return "CAST";
- case CALL:
- return "CALL";
- case PARAM:
- return "PARAM ";
- case NULLOP:
- return "NULLOP";
- case BLOCK:
- return "BLOCK";
- case LABEL:
- return "LABEL";
- case RECEIVE:
- return "RECEIVE";
- case SEND:
- return "SEND";
+ case IDENTIFIER: return "IDENTIFIER";
+ case TYPE_NAME: return "TYPE_NAME";
+ case CONSTANT: return "CONSTANT";
+ case STRING_LITERAL: return "STRING_LITERAL";
+ case SIZEOF: return "SIZEOF";
+ case PTR_OP: return "PTR_OP";
+ case INC_OP: return "INC_OP";
+ case DEC_OP: return "DEC_OP";
+ case LEFT_OP: return "LEFT_OP";
+ case RIGHT_OP: return "RIGHT_OP";
+ case LE_OP: return "LE_OP";
+ case GE_OP: return "GE_OP";
+ case EQ_OP: return "EQ_OP";
+ case NE_OP: return "NE_OP";
+ case AND_OP: return "AND_OP";
+ case OR_OP: return "OR_OP";
+ case MUL_ASSIGN: return "MUL_ASSIGN";
+ case DIV_ASSIGN: return "DIV_ASSIGN";
+ case MOD_ASSIGN: return "MOD_ASSIGN";
+ case ADD_ASSIGN: return "ADD_ASSIGN";
+ case SUB_ASSIGN: return "SUB_ASSIGN";
+ case LEFT_ASSIGN: return "LEFT_ASSIGN";
+ case RIGHT_ASSIGN: return "RIGHT_ASSIGN";
+ case AND_ASSIGN: return "AND_ASSIGN";
+ case XOR_ASSIGN: return "XOR_ASSIGN";
+ case OR_ASSIGN: return "OR_ASSIGN";
+ case TYPEDEF: return "TYPEDEF";
+ case EXTERN: return "EXTERN";
+ case STATIC: return "STATIC";
+ case AUTO: return "AUTO";
+ case REGISTER: return "REGISTER";
+ case CODE: return "CODE";
+ case EEPROM: return "EEPROM";
+ case INTERRUPT: return "INTERRUPT";
+ case SFR: return "SFR";
+ case AT: return "AT";
+ case SBIT: return "SBIT";
+ case REENTRANT: return "REENTRANT";
+ case USING: return "USING";
+ case XDATA: return "XDATA";
+ case DATA: return "DATA";
+ case IDATA: return "IDATA";
+ case PDATA: return "PDATA";
+ case VAR_ARGS: return "VAR_ARGS";
+ case CRITICAL: return "CRITICAL";
+ case NONBANKED: return "NONBANKED";
+ case BANKED: return "BANKED";
+ case CHAR: return "CHAR";
+ case SHORT: return "SHORT";
+ case INT: return "INT";
+ case LONG: return "LONG";
+ case SIGNED: return "SIGNED";
+ case UNSIGNED: return "UNSIGNED";
+ case FLOAT: return "FLOAT";
+ case DOUBLE: return "DOUBLE";
+ case CONST: return "CONST";
+ case VOLATILE: return "VOLATILE";
+ case VOID: return "VOID";
+ case BIT: return "BIT";
+ case STRUCT: return "STRUCT";
+ case UNION: return "UNION";
+ case ENUM: return "ENUM";
+ case ELIPSIS: return "ELIPSIS";
+ case RANGE: return "RANGE";
+ case FAR: return "FAR";
+ case CASE: return "CASE";
+ case DEFAULT: return "DEFAULT";
+ case IF: return "IF";
+ case ELSE: return "ELSE";
+ case SWITCH: return "SWITCH";
+ case WHILE: return "WHILE";
+ case DO: return "DO";
+ case FOR: return "FOR";
+ case GOTO: return "GOTO";
+ case CONTINUE: return "CONTINUE";
+ case BREAK: return "BREAK";
+ case RETURN: return "RETURN";
+ case INLINEASM: return "INLINEASM";
+ case IFX: return "IFX";
+ case ADDRESS_OF: return "ADDRESS_OF";
+ case GET_VALUE_AT_ADDRESS: return "GET_VALUE_AT_ADDRESS";
+ case SPIL: return "SPIL";
+ case UNSPIL: return "UNSPIL";
+ case GETHBIT: return "GETHBIT";
+ case BITWISEAND: return "BITWISEAND";
+ case UNARYMINUS: return "UNARYMINUS";
+ case IPUSH: return "IPUSH";
+ case IPOP: return "IPOP";
+ case PCALL: return "PCALL";
+ case ENDFUNCTION: return "ENDFUNCTION";
+ case JUMPTABLE: return "JUMPTABLE";
+ case RRC: return "RRC";
+ case RLC: return "RLC";
+ case CAST: return "CAST";
+ case CALL: return "CALL";
+ case PARAM: return "PARAM ";
+ case NULLOP: return "NULLOP";
+ case BLOCK: return "BLOCK";
+ case LABEL: return "LABEL";
+ case RECEIVE: return "RECEIVE";
+ case SEND: return "SEND";
}
sprintf (buffer, "unknown op %d %c", op, op & 0xff);
return buffer;
switch (type)
{
- case REG_GPR:
- return "REG_GPR";
- case REG_PTR:
- return "REG_PTR";
- case REG_CND:
- return "REG_CND";
+ case REG_GPR: return "REG_GPR";
+ case REG_PTR: return "REG_PTR";
+ case REG_CND: return "REG_CND";
}
sprintf (buffer, "unknown reg type %d", type);
sprintf(buffer,"r0x%02X", dReg->rIdx);
dReg->name = Safe_strdup(buffer);
}
- //fprintf(stderr,"newReg: %s, rIdx = 0x%02x\n",dReg->name,rIdx);
dReg->isFree = 0;
dReg->wasUsed = 1;
if (type == REG_SFR)
dReg->reglives.assignedpFlows = newSet();
hTabAddItem(&dynDirectRegNames, regname2key(name), dReg);
-
+
return dReg;
}
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];
+ SNPRINTF(&buffer[0], 16, "STK%02d", i);
+ regs *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--;
static regs *
allocReg (short type)
{
+ regs *reg;
debugLog ("%s of type %s\n", __FUNCTION__, debugLogRegType (type));
//fprintf(stderr,"allocReg\n");
+ reg = pic14_findFreeReg (type);
+
+ reg->isFree = 0;
+ reg->wasUsed = 1;
+
+ return reg;
- return addSet(&dynAllocRegs,newReg(REG_GPR, PO_GPR_TEMP,dynrIdx++,NULL,1,0));
+
+ //return addSet(&dynAllocRegs,newReg(REG_GPR, PO_GPR_TEMP,dynrIdx++,NULL,1,0));
}
{
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);
}
} else {
int idx;
if (address) {
- if (IS_BITVAR (symlnk))
+ if (IS_BITVAR (spec))
idx = address >> 3;
else
idx = address;
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;
}
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;
/* 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) {
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);
+ }
break;
case REG_SFR:
if( (dReg = regWithIdx ( dynProcessorRegs, idx, fixed)) != NULL ) {
assignRelocatableRegisters(dynAllocRegs,0);
assignRelocatableRegisters(dynStackRegs,0);
+ assignRelocatableRegisters(dynDirectRegs,0);
/*
assignRelocatableRegisters(dynDirectRegs,0);
printf("assignRelocatableRegisters(dynDirectRegs,0);\n");
if (!bitVectBitValue (lrs, i))
continue;
- /* if we don't find it in the live range
+ /* if we don't find it in the live range
hash table we are in serious trouble */
if (!(sym = hTabItemWithKey (liveRanges, i)))
{
char slocBuffer[30];
debugLog ("%s\n", __FUNCTION__);
+
+ FENTRY2("called.");
/* first go try and find a free one that is already
existing on the stack */
sym_link *etype;
debugLog ("%s\n", __FUNCTION__);
+ FENTRY2("called.");
+
if (!sym)
return FALSE;
{
int i;
debugLog ("%s : %s\n", __FUNCTION__, sym->rname);
+ FENTRY2("sym: %s, spillLoc:%p (%s)\n", sym->rname, sym->usl.spillLoc, sym->usl.spillLoc ? sym->usl.spillLoc->rname : "<unknown>");
/* if this is rematerializable or has a spillLocation
we are okay, else we need to create a spillLocation
bitVectUnSetBit (_G.regAssigned, sym->key);
for (i = 0; i < sym->nRegs; i++)
-
+ {
if (sym->regs[i])
{
freeReg (sym->regs[i]);
sym->regs[i] = NULL;
}
+ }
- /* if spilt on stack then free up r0 & r1
- if they could have been assigned to some
- LIVE ranges */
- if (!pic14_ptrRegReq && isSpiltOnStack (sym))
- {
- pic14_ptrRegReq++;
- spillLRWithPtrReg (sym);
- }
+ /* if spilt on stack then free up r0 & r1
+ if they could have been assigned to some
+ LIVE ranges */
+ if (!pic14_ptrRegReq && isSpiltOnStack (sym))
+ {
+ pic14_ptrRegReq++;
+ spillLRWithPtrReg (sym);
+ }
- if (sym->usl.spillLoc && !sym->remat)
- sym->usl.spillLoc->allocreq = 1;
- return;
+ if (sym->usl.spillLoc && !sym->remat)
+ sym->usl.spillLoc->allocreq = 1;
+
+ return;
}
/*-----------------------------------------------------------------*/
symbol *sym;
debugLog ("%s\n", __FUNCTION__);
+ FENTRY2("called.");
/* get the spillable live ranges */
lrcs = computeSpillable (ic);
-
+
+
/* get all live ranges that are rematerizable */
if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
{
-
/* return the least used of these */
return leastUsedLR (selectS);
}
/* check if there are any live ranges that not
used in the remainder of the block */
- if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
+ if (!_G.blockSpil &&
+ !isiCodeInFunctionCall (ic) &&
+ (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
{
sym = leastUsedLR (selectS);
if (!sym->remat)
sym->usl.spillLoc->allocreq = 1;
return sym;
}
-
+
/* couldn't find then we need to create a spil
location on the stack , for which one? the least
used ofcourse */
if (sym->regs[j])
sym->regs[j]->isFree = 0;
- /* this looks like an infinite loop but
+ /* this looks like an infinite loop but
in really selectSpil will abort */
goto tryAgain;
}
/* if it does not end here */
if (sym->liveTo > ic->seq)
continue;
-
- /* if it was spilt on stack then we can
+
+ /* 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))
+ {
+ 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)
{
if (!bitVectBitValue (_G.regAssigned, sym->key))
continue;
-
- /* special case check if this is an IFX &
- the privious one was a pop and the
- previous one was not spilt then keep track
+ /* special case check if this is an IFX &
+ the privious one was a pop and the
+ previous one was not spilt then keep track
of the symbol */
if (ic->op == IFX && ic->prev &&
ic->prev->op == IPOP &&
!ic->prev->parmPush &&
+ IS_SYMOP(IC_LEFT (ic->prev)) &&
!OP_SYMBOL (IC_LEFT (ic->prev))->isspilt)
psym = OP_SYMBOL (IC_LEFT (ic->prev));
ic->op == IPOP ||
ic->op == RETURN ||
POINTER_SET (ic)) &&
+ IS_SYMOP (IC_RESULT (ic)) &&
(result = OP_SYMBOL (IC_RESULT (ic))) && /* has a result */
result->liveTo > ic->seq && /* and will live beyond this */
result->liveTo <= ebp->lSeq && /* does not go beyond this block */
+ result->liveFrom == ic->seq && /* does not start before here */
+ result->regType == sym->regType && /* same register types */
result->regType == sym->regType && /* same register types */
result->nRegs && /* which needs registers */
!result->isspilt && /* and does not already have them */
_G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
}
-
+
/* free the remaining */
for (; i < sym->nRegs; i++)
{
/* of all instructions do */
for (ic = ebbs[i]->sch; ic; ic = ic->next)
{
-
debugLog (" op: %s\n", decodeOp (ic->op));
/* if this is an ipop that means some live
IS_TRUE_SYMOP (IC_RESULT (ic)))
OP_SYMBOL (IC_RESULT (ic))->allocreq = 1;
- /* take away registers from live
+ /* take away registers from live
ranges that end at this instruction */
deassignLRs (ic, ebbs[i]);
(IC_RESULT (ic) && POINTER_SET (ic)))
continue;
- /* now we need to allocate registers
+ /* now we need to allocate registers
only for the result */
- if (IC_RESULT (ic))
+ if (IC_RESULT (ic) && IS_SYMOP (IC_RESULT (ic)))
{
symbol *sym = OP_SYMBOL (IC_RESULT (ic));
bitVect *spillable;
int willCS;
int j;
int ptrRegSet = 0;
-
+
+ /* Make sure any spill location is definately 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 */
sym->liveTo <= ic->seq)
continue;
- /* if some liverange has been spilt at the block level
- and this one live beyond this block then spil this
+ /* if some liverange has been spilt at the block level
+ and this one live beyond this block then spil this
to be safe */
if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
{
continue;
}
+
+ /* If the live range preceeds the point of definition
+ then ideally we must take into account registers that
+ have been allocated after sym->liveFrom but freed
+ before ic->seq. This is complicated, so spill this
+ symbol instead and let fillGaps handle the allocation. */
+ if (sym->liveFrom < ic->seq)
+ {
+ spillThis (sym);
+ continue;
+ }
/* if it has a spillocation & is used less than
all other live ranges then spill this */
continue;
}
} else {
- /* if none of the liveRanges have a spillLocation then better
+ /* if none of the liveRanges have a spillLocation then better
to spill this one than anything else already assigned to registers */
if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
/* if this is local to this block then we might find a block spil */
if (ic->op == RECEIVE)
debugLog ("When I get clever, I'll optimize the receive logic\n");
- /* if we need ptr regs for the right side
+ /* if we need ptr regs for the right side
then mark it */
- if (POINTER_GET (ic) && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
- <= (unsigned) PTRSIZE)
+ if (POINTER_GET (ic)
+ && IS_SYMOP(IC_LEFT(ic))
+ && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
+ <= (unsigned) PTRSIZE)
{
pic14_ptrRegReq++;
ptrRegSet = 1;
else
sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
- /* if the allocation failed which means
+ /* if the allocation failed which means
this was spilt then break */
if (!sym->regs[j])
break;
/* if it shares registers with operands make sure
that they are in the same position */
if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
+ IS_SYMOP(IC_RESULT(ic)) &&
OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=')
positionRegs (OP_SYMBOL (IC_RESULT (ic)),
OP_SYMBOL (IC_LEFT (ic)), ic->lineno);
/* do the same for the right operand */
if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
+ IS_SYMOP(IC_RESULT(ic)) &&
OP_SYMBOL (IC_RIGHT (ic))->nRegs && ic->op != '=')
positionRegs (OP_SYMBOL (IC_RESULT (ic)),
OP_SYMBOL (IC_RIGHT (ic)), ic->lineno);
ptrRegSet = 0;
}
+ }
}
}
- }
/* Check for and fix any problems with uninitialized operands */
for (i = 0; i < count; i++)
- {
- iCode *ic;
+ {
+ 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 (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);
- }
- }
+ 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);
+ }
+ }
}
}
}
}
-
+#if 0
+/* This was the active version */
/*-----------------------------------------------------------------*/
/* rematStr - returns the rematerialized string for a remat var */
/*-----------------------------------------------------------------*/
//printf ("ralloc.c:%d %s\n", __LINE__,buffer);
return psym;
}
+#endif
#if 0
+/* deprecated version */
/*-----------------------------------------------------------------*/
/* rematStr - returns the rematerialized string for a remat var */
/*-----------------------------------------------------------------*/
{
symbol *sym;
int k;
- iCode *ic;
+ //iCode *ic;
debugLog ("%s\n", __FUNCTION__);
/* for each live range do */
for (sym = hTabFirstItem (liveRanges, &k); sym;
sym = hTabNextItem (liveRanges, &k)) {
-
+
debugLog (" %d - %s\n", __LINE__, sym->rname);
/* if used zero times then no registers needed */
if ((sym->liveTo - sym->liveFrom) == 0)
continue;
-
-
+
+
/* if the live range is a temporary */
if (sym->isitmp) {
if (sym->regType == REG_CND)
continue;
- /* if used in return only then we don't
+ /* if used in return only then we don't
need registers */
if (sym->accuse) {
if (IS_AGGREGATE (sym->type) || sym->isptr)
pointer we are getting is rematerializable and
in "data" space */
+#if 0
if (bitVectnBitsOn (sym->defs) == 1 &&
- (ic = hTabItemWithKey (iCodehTab,
- bitVectFirstBit (sym->defs))) &&
- POINTER_GET (ic) &&
- !sym->noSpilLoc &&
- !IS_BITVAR (sym->etype)) {
-
-
- debugLog (" %d - \n", __LINE__);
-
- /* if remat in data space */
- if (OP_SYMBOL (IC_LEFT (ic))->remat &&
- DCL_TYPE (aggrToPtr (sym->type, FALSE)) == POINTER) {
+ (ic = hTabItemWithKey (iCodehTab,
+ bitVectFirstBit (sym->defs))) &&
+ POINTER_GET (ic) &&
+ !IS_BITVAR (sym->etype) &&
+ (aggrToPtrDclType (operandType (IC_LEFT (ic)), FALSE) == POINTER)) {
+
+ if (ptrPseudoSymSafe (sym, ic)) {
+
+ symbol *psym;
+ debugLog (" %d - \n", __LINE__);
+
/* create a psuedo symbol & force a spil */
//X symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
- symbol *psym = rematStr (OP_SYMBOL (IC_LEFT (ic)));
+ psym = rematStr (OP_SYMBOL (IC_LEFT (ic)));
psym->type = sym->type;
psym->etype = sym->etype;
+ psym->psbase = ptrBaseRematSym (OP_SYMBOL (IC_LEFT (ic)));
strcpy (psym->rname, psym->name);
sym->isspilt = 1;
sym->usl.spillLoc = psym;
allocate pointer register */
}
+#endif
/* if not then we require registers */
sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
/* registers for true symbols we will */
/* see how things go */
sym->nRegs = 0;
- }
+ }
}
DEFSETFUNC (markRegFree)
for (dic = ic->prev; dic; dic = dic->prev)
{
- /* if there is a function call and this is
+ /* if there is a function call and this is
a parameter & not my parameter then don't pack it */
if ((dic->op == CALL || dic->op == PCALL) &&
(OP_SYMBOL (IC_RESULT (ic))->_isparm &&
if (!dic)
return 0; /* did not find */
- /* if the result is on stack or iaccess then it must be
- the same atleast one of the operands */
+ /* 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 ||
OP_SYMBOL (IC_RESULT (ic))->iaccess)
{
if (!IS_SYMOP (op))
return NULL;
- /* only upto 2 bytes since we cannot predict
+ /* only upto 2 bytes since we cannot predict
the usage of b, & acc */
if (getSize (operandType (op)) > (fReturnSizePic - 2) &&
ic->op != RETURN &&
ic->op != SEND)
return NULL;
- /* this routine will mark the a symbol as used in one
- instruction use only && if the definition is local
- (ie. within the basic block) && has only one definition &&
- that definition is either a return value from a
- function or does not contain any variables in
+ /* this routine will mark the a symbol as used in one
+ instruction use only && if the definition is local
+ (ie. within the basic block) && has only one definition &&
+ that definition is either a return value from a
+ function or does not contain any variables in
far space */
uses = bitVectCopy (OP_USES (op));
bitVectUnSetBit (uses, ic->key); /* take away this iCode */
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;
accuse:
debugLog ("%s - Yes we are using the accumulator\n", __FUNCTION__);
OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
-
-
+#endif
}
/*-----------------------------------------------------------------*/
}
}
+
/*-----------------------------------------------------------------*/
/* packRegisters - does some transformations to reduce register */
/* pressure */
debugLog (" %d - Pointer set\n", __LINE__);
- /* if this is an itemp & result of a address of a true sym
+ /* Look for two subsequent iCodes with */
+ /* iTemp := _c; */
+ /* _c = iTemp & op; */
+ /* and replace them by */
+ /* iTemp := _c; */
+ /* _c = _c & op; */
+ if ((ic->op == BITWISEAND || ic->op == '|' || ic->op == '^') &&
+ ic->prev &&
+ ic->prev->op == '=' &&
+ IS_ITEMP (IC_LEFT (ic)) &&
+ IC_LEFT (ic) == IC_RESULT (ic->prev) &&
+ isOperandEqual (IC_RESULT(ic), IC_RIGHT(ic->prev)))
+ {
+ iCode* ic_prev = ic->prev;
+ symbol* prev_result_sym = OP_SYMBOL (IC_RESULT (ic_prev));
+
+ ReplaceOpWithCheaperOp (&IC_LEFT (ic), IC_RESULT (ic));
+ if (IC_RESULT (ic_prev) != IC_RIGHT (ic))
+ {
+ bitVectUnSetBit (OP_USES (IC_RESULT (ic_prev)), ic->key);
+ if (/*IS_ITEMP (IC_RESULT (ic_prev)) && */
+ prev_result_sym->liveTo == ic->seq)
+ {
+ prev_result_sym->liveTo = ic_prev->seq;
+ }
+ }
+ bitVectSetBit (OP_USES (IC_RESULT (ic)), ic->key);
+
+ bitVectSetBit (ic->rlive, IC_RESULT (ic)->key);
+
+ if (bitVectIsZero (OP_USES (IC_RESULT (ic_prev))))
+ {
+ bitVectUnSetBit (ic->rlive, IC_RESULT (ic)->key);
+ bitVectUnSetBit (OP_DEFS (IC_RESULT (ic_prev)), ic_prev->key);
+ remiCodeFromeBBlock (ebp, ic_prev);
+ hTabDeleteItem (&iCodehTab, ic_prev->key, ic_prev, DELETE_ITEM, NULL);
+ }
+ }
+
+ /* if this is an itemp & result of a address of a true sym
then mark this as rematerialisable */
if (ic->op == ADDRESS_OF &&
IS_ITEMP (IC_RESULT (ic)) &&
}
/* mark the pointer usages */
- if (POINTER_SET (ic))
+ if (POINTER_SET (ic) && IS_SYMOP(IC_RESULT(ic)))
{
OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
debugLog (" marking as a pointer (set) =>");
debugAopGet (" result:", IC_RESULT (ic));
}
- if (POINTER_GET (ic))
+ if (POINTER_GET (ic) && IS_SYMOP(IC_LEFT(ic)))
{
OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
debugLog (" marking as a pointer (get) =>");
if (!SKIP_IC2 (ic))
{
- /* if we are using a symbol on the stack
+ /* if we are using a symbol on the stack
then we should say pic14_ptrRegReq */
if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
pic14_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ||
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)
/* 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)
packRegsForOneuse (ic, IC_LEFT (ic), ebp);
- /* if this is cast for intergral promotion then
- check if only use of the definition of the
- operand being casted/ if yes then replace
- the result of that arithmetic operation with
+ /* if this is cast for intergral promotion then
+ check if only use of the definition of the
+ operand being casted/ if yes then replace
+ the result of that arithmetic operation with
this result and get rid of the cast */
if (ic->op == CAST) {
}
} else {
- /* if the type from and type to are the same
+ /* if the type from and type to are the same
then if this is the only use then packit */
if (compareType (operandType (IC_RIGHT (ic)),
operandType (IC_LEFT (ic))) == 1) {
packRegsForAccUse (ic);
- }
+ }
}
static void
/* assignRegisters - assigns registers to each live range as need */
/*-----------------------------------------------------------------*/
void
-pic14_assignRegisters (eBBlock ** ebbs, int count)
+pic14_assignRegisters (ebbIndex * ebbi)
{
+ eBBlock ** ebbs = ebbi->bbOrder;
+ int count = ebbi->count;
iCode *ic;
int i;
}
if (options.dump_pack)
- dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
+ dumpEbbsToFileExt (DUMP_PACK, ebbi);
- /* first determine for each live range the number of
+ /* first determine for each live range the number of
registers & the type of registers required for each */
regTypeNum ();
redoStackOffsets ();
if (options.dump_rassgn)
- dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
+ dumpEbbsToFileExt (DUMP_RASSGN, ebbi);
/* now get back the chain */
ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));