+/*-----------------------------------------------------------------*/
+/* reassignLR - reassign this to registers */
+/*-----------------------------------------------------------------*/
+static void
+reassignLR (operand * op)
+{
+ symbol *sym = OP_SYMBOL (op);
+ int i;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* not spilt any more */
+ sym->isspilt = sym->blockSpil = sym->remainSpil = 0;
+ bitVectUnSetBit (_G.spiltSet, sym->key);
+
+ _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+
+ _G.blockSpil--;
+
+ for (i = 0; i < sym->nRegs; i++)
+ sym->regs[i]->isFree = 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* willCauseSpill - determines if allocating will cause a spill */
+/*-----------------------------------------------------------------*/
+static int
+willCauseSpill (int nr, int rt)
+{
+ debugLog ("%s\n", __FUNCTION__);
+ /* first check if there are any avlb registers
+ of te type required */
+ if (rt == REG_PTR)
+ {
+ /* special case for pointer type
+ if pointer type not avlb then
+ check for type gpr */
+ if (nFreeRegs (rt) >= nr)
+ return 0;
+ if (nFreeRegs (REG_GPR) >= nr)
+ return 0;
+ }
+ else
+ {
+ if (pic14_ptrRegReq)
+ {
+ if (nFreeRegs (rt) >= nr)
+ return 0;
+ }
+ else
+ {
+ if (nFreeRegs (REG_PTR) +
+ nFreeRegs (REG_GPR) >= nr)
+ return 0;
+ }
+ }
+
+ debugLog (" ... yep it will (cause a spill)\n");
+ /* it will cause a spil */
+ return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* positionRegs - the allocator can allocate same registers to res- */
+/* ult and operand, if this happens make sure they are in the same */
+/* position as the operand otherwise chaos results */
+/*-----------------------------------------------------------------*/
+static void
+positionRegs (symbol * result, symbol * opsym, int lineno)
+{
+ int count = min (result->nRegs, opsym->nRegs);
+ int i, j = 0, shared = 0;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* if the result has been spilt then cannot share */
+ if (opsym->isspilt)
+ return;
+again:
+ shared = 0;
+ /* first make sure that they actually share */
+ for (i = 0; i < count; i++)
+ {
+ for (j = 0; j < count; j++)
+ {
+ if (result->regs[i] == opsym->regs[j] && i != j)
+ {
+ shared = 1;
+ goto xchgPositions;
+ }
+ }
+ }
+xchgPositions:
+ if (shared)
+ {
+ regs *tmp = result->regs[i];
+ result->regs[i] = result->regs[j];
+ result->regs[j] = tmp;
+ goto again;
+ }
+}
+
+/*------------------------------------------------------------------*/
+/* verifyRegsAssigned - make sure an iTemp is properly initialized; */
+/* it should either have registers or have beed spilled. Otherwise, */
+/* there was an uninitialized variable, so just spill this to get */
+/* the operand in a valid state. */
+/*------------------------------------------------------------------*/
+static void
+verifyRegsAssigned (operand *op, iCode * ic)
+{
+ symbol * sym;
+
+ if (!op) return;
+ if (!IS_ITEMP (op)) return;
+
+ sym = OP_SYMBOL (op);
+ if (sym->isspilt) return;
+ if (!sym->nRegs) return;
+ if (sym->regs[0]) return;
+
+ werrorfl (ic->filename, ic->lineno, W_LOCAL_NOINIT,
+ sym->prereqv ? sym->prereqv->name : sym->name);
+ spillThis (sym);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* serialRegAssign - serially allocate registers to the variables */
+/*-----------------------------------------------------------------*/
+static void
+serialRegAssign (eBBlock ** ebbs, int count)
+{
+ int i;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* for all blocks */
+ for (i = 0; i < count; i++)
+ {
+
+ iCode *ic;
+
+ if (ebbs[i]->noPath &&
+ (ebbs[i]->entryLabel != entryLabel &&
+ ebbs[i]->entryLabel != returnLabel))
+ continue;
+
+ /* 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
+ range will have to be assigned again */
+ if (ic->op == IPOP)
+ reassignLR (IC_LEFT (ic));
+
+ /* if result is present && is a true symbol */
+ if (IC_RESULT (ic) && ic->op != IFX &&
+ IS_TRUE_SYMOP (IC_RESULT (ic)))
+ OP_SYMBOL (IC_RESULT (ic))->allocreq = 1;
+
+ /* take away registers from live
+ ranges that end at this instruction */
+ deassignLRs (ic, ebbs[i]);
+
+ /* some don't need registers */
+ if (SKIP_IC2 (ic) ||
+ ic->op == JUMPTABLE ||
+ ic->op == IFX ||
+ ic->op == IPUSH ||
+ ic->op == IPOP ||
+ (IC_RESULT (ic) && POINTER_SET (ic)))
+ continue;
+
+ /* now we need to allocate registers
+ only for the result */
+ 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 */
+ if (!sym->nRegs ||
+ sym->isspilt ||
+ bitVectBitValue (_G.regAssigned, sym->key) ||
+ 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
+ to be safe */
+ if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
+ {
+ 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);
+ 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 */
+ if (willCS) {
+ if (sym->usl.spillLoc) {
+ symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
+ allLRs, ebbs[i], ic));
+ if (leastUsed && leastUsed->used > sym->used) {
+ spillThis (sym);
+ continue;
+ }
+ } else {
+ /* 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 (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
+ spillThis (sym);
+ continue;
+ }
+ }
+ }
+ }
+
+ 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
+ then mark it */
+ if (POINTER_GET (ic)
+ && IS_SYMOP(IC_LEFT(ic))
+ && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
+ <= (unsigned) PTRSIZE)
+ {
+ pic14_ptrRegReq++;
+ ptrRegSet = 1;
+ }
+ /* else we assign registers to it */
+ _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+
+ debugLog (" %d - \n", __LINE__);
+ if(debugF)
+ bitVectDebugOn(_G.regAssigned, debugF);
+ for (j = 0; j < sym->nRegs; j++)
+ {
+ if (sym->regType == REG_PTR)
+ sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
+ else
+ sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
+
+ /* if the allocation failed which means
+ this was spilt then break */
+ if (!sym->regs[j])
+ break;
+ }
+ debugLog (" %d - \n", __LINE__);
+
+ /* 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);
+
+ debugLog (" %d - \n", __LINE__);
+ if (ptrRegSet)
+ {
+ debugLog (" %d - \n", __LINE__);
+ pic14_ptrRegReq--;
+ ptrRegSet = 0;
+ }
+
+ }
+ }
+ }
+
+ /* Check for and fix any problems with uninitialized operands */
+ for (i = 0; i < count; i++)
+ {
+ 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 (ic->op == JUMPTABLE)
+ {
+ verifyRegsAssigned (IC_JTCOND (ic), ic);
+ continue;
+ }
+
+ verifyRegsAssigned (IC_RESULT (ic), ic);
+ verifyRegsAssigned (IC_LEFT (ic), ic);
+ verifyRegsAssigned (IC_RIGHT (ic), ic);
+ }
+ }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* rUmaskForOp :- returns register mask for an operand */
+/*-----------------------------------------------------------------*/
+static bitVect *
+rUmaskForOp (operand * op)
+{
+ bitVect *rumask;
+ symbol *sym;
+ int j;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* only temporaries are assigned registers */
+ if (!IS_ITEMP (op))
+ return NULL;
+
+ sym = OP_SYMBOL (op);
+
+ /* if spilt or no registers assigned to it
+ then nothing */
+ if (sym->isspilt || !sym->nRegs)
+ return NULL;
+
+ rumask = newBitVect (pic14_nRegs);
+
+ for (j = 0; j < sym->nRegs; j++)
+ {
+ rumask = bitVectSetBit (rumask,
+ sym->regs[j]->rIdx);
+ }
+
+ return rumask;
+}
+
+/*-----------------------------------------------------------------*/
+/* regsUsedIniCode :- returns bit vector of registers used in iCode */
+/*-----------------------------------------------------------------*/
+static bitVect *
+regsUsedIniCode (iCode * ic)
+{
+ bitVect *rmask = newBitVect (pic14_nRegs);
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* do the special cases first */
+ if (ic->op == IFX)
+ {
+ rmask = bitVectUnion (rmask,
+ rUmaskForOp (IC_COND (ic)));
+ goto ret;
+ }
+
+ /* for the jumptable */
+ if (ic->op == JUMPTABLE)
+ {
+ rmask = bitVectUnion (rmask,
+ rUmaskForOp (IC_JTCOND (ic)));
+
+ goto ret;
+ }
+
+ /* of all other cases */
+ if (IC_LEFT (ic))
+ rmask = bitVectUnion (rmask,
+ rUmaskForOp (IC_LEFT (ic)));
+
+
+ if (IC_RIGHT (ic))
+ rmask = bitVectUnion (rmask,
+ rUmaskForOp (IC_RIGHT (ic)));
+
+ if (IC_RESULT (ic))
+ rmask = bitVectUnion (rmask,
+ rUmaskForOp (IC_RESULT (ic)));
+
+ret:
+ return rmask;
+}
+
+/*-----------------------------------------------------------------*/
+/* createRegMask - for each instruction will determine the regsUsed */
+/*-----------------------------------------------------------------*/
+static void
+createRegMask (eBBlock ** ebbs, int count)
+{
+ int i;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* for all blocks */
+ for (i = 0; i < count; i++)
+ {
+ iCode *ic;
+
+ if (ebbs[i]->noPath &&
+ (ebbs[i]->entryLabel != entryLabel &&
+ ebbs[i]->entryLabel != returnLabel))
+ continue;
+
+ /* for all instructions */
+ for (ic = ebbs[i]->sch; ic; ic = ic->next)
+ {
+
+ int j;
+
+ if (SKIP_IC2 (ic) || !ic->rlive)
+ continue;
+
+ /* first mark the registers used in this
+ instruction */
+ ic->rUsed = regsUsedIniCode (ic);
+ _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
+
+ /* now create the register mask for those
+ registers that are in use : this is a
+ super set of ic->rUsed */
+ ic->rMask = newBitVect (pic14_nRegs + 1);
+
+ /* for all live Ranges alive at this point */
+ for (j = 1; j < ic->rlive->size; j++)
+ {
+ symbol *sym;
+ int k;
+
+ /* if not alive then continue */
+ if (!bitVectBitValue (ic->rlive, j))
+ continue;
+
+ /* find the live range we are interested in */
+ if (!(sym = hTabItemWithKey (liveRanges, j)))
+ {
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "createRegMask cannot find live range");
+ exit (0);
+ }
+
+ /* if no register assigned to it */
+ if (!sym->nRegs || sym->isspilt)
+ continue;
+
+ /* for all the registers allocated to it */
+ for (k = 0; k < sym->nRegs; k++)
+ if (sym->regs[k])
+ ic->rMask =
+ bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
+ }
+ }
+ }
+}
+#if 0
+/* This was the active version */
+/*-----------------------------------------------------------------*/
+/* rematStr - returns the rematerialized string for a remat var */
+/*-----------------------------------------------------------------*/
+static symbol *
+rematStr (symbol * sym)
+{
+ char *s = buffer;
+ iCode *ic = sym->rematiCode;
+ symbol *psym = NULL;
+
+ debugLog ("%s\n", __FUNCTION__);
+
+ //printf ("%s\n", s);
+
+ /* if plus or minus print the right hand side */
+
+ if (ic->op == '+' || ic->op == '-') {
+
+ iCode *ric = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+
+ sprintf (s, "(%s %c 0x%04x)",
+ OP_SYMBOL (IC_LEFT (ric))->rname,
+ ic->op,
+ (int) operandLitValue (IC_RIGHT (ic)));
+
+
+ //fprintf(stderr, "ralloc.c:%d OOPS %s\n",__LINE__,s);
+
+ psym = newSymbol (OP_SYMBOL (IC_LEFT (ric))->rname, 1);
+ psym->offset = (int) operandLitValue (IC_RIGHT (ic));
+
+ return psym;
+ }
+
+ sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
+ psym = newSymbol (OP_SYMBOL (IC_LEFT (ic))->rname, 1);
+
+ //printf ("ralloc.c:%d %s\n", __LINE__,buffer);
+ return psym;
+}
+#endif
+
+#if 0
+/* deprecated version */
+/*-----------------------------------------------------------------*/
+/* rematStr - returns the rematerialized string for a remat var */
+/*-----------------------------------------------------------------*/
+static char *
+rematStr (symbol * sym)
+{
+ char *s = buffer;
+ iCode *ic = sym->rematiCode;
+
+ debugLog ("%s\n", __FUNCTION__);
+ while (1)
+ {
+
+ printf ("%s\n", s);
+ /* if plus or minus print the right hand side */
+ /*
+ if (ic->op == '+' || ic->op == '-') {
+ sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
+ ic->op );
+ s += strlen(s);
+ ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
+ continue ;
+ }
+ */
+ if (ic->op == '+' || ic->op == '-')
+ {
+ iCode *ric = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+ sprintf (s, "(%s %c 0x%04x)",
+ OP_SYMBOL (IC_LEFT (ric))->rname,
+ ic->op,
+ (int) operandLitValue (IC_RIGHT (ic)));
+
+ //s += strlen(s);
+ //ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
+ //continue ;
+ //fprintf(stderr, "ralloc.c:%d OOPS %s\n",__LINE__,s);
+ return buffer;
+ }
+
+ /* we reached the end */
+ sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
+ break;
+ }
+
+ printf ("%s\n", buffer);
+ return buffer;
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* regTypeNum - computes the type & number of registers required */
+/*-----------------------------------------------------------------*/
+static void
+regTypeNum ()
+{
+ symbol *sym;
+ int k;
+ //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) {
+
+ debugLog (" %d - itemp register\n", __LINE__);
+
+ /* if the type is marked as a conditional */
+ if (sym->regType == REG_CND)
+ continue;
+
+ /* if used in return only then we don't
+ need registers */
+ if (sym->accuse) {
+ if (IS_AGGREGATE (sym->type) || sym->isptr)
+ sym->type = aggrToPtr (sym->type, FALSE);
+ debugLog (" %d - no reg needed - accumulator used\n", __LINE__);
+
+ continue;
+ }
+
+ if (sym->ruonly) {
+ //if (IS_AGGREGATE (sym->type) || sym->isptr)
+ // sym->type = aggrToPtr (sym->type, FALSE);
+ debugLog (" %d - used as a return\n", __LINE__);
+
+ //continue;
+ }
+
+ /* if the symbol has only one definition &
+ that definition is a get_pointer and the
+ 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) &&
+ !IS_BITVAR (sym->etype) &&
+ (aggrToPtrDclType (operandType (IC_LEFT (ic)), FALSE) == POINTER)) {
+
+ if (ptrPseudoSymSafe (sym, ic)) {
+
+ symbol *psym;
+
+ debugLog (" %d - \n", __LINE__);
+
+ /* 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;
+ psym->etype = sym->etype;
+ psym->psbase = ptrBaseRematSym (OP_SYMBOL (IC_LEFT (ic)));
+ strcpy (psym->rname, psym->name);
+ sym->isspilt = 1;
+ sym->usl.spillLoc = psym;
+ continue;
+ }
+
+ /* if in data space or idata space then try to
+ allocate pointer register */
+
+ }
+#endif
+
+ /* if not then we require registers */
+ sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
+ getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
+ getSize (sym->type));
+
+
+ if(IS_PTR_CONST (sym->type)) {
+ debugLog (" %d const pointer type requires %d registers, changing to 2\n",__LINE__,sym->nRegs);
+ sym->nRegs = 2;
+ }
+
+ if (sym->nRegs > 4) {
+ fprintf (stderr, "allocated more than 4 or 0 registers for type ");
+ printTypeChain (sym->type, stderr);
+ fprintf (stderr, "\n");
+ }
+
+ /* determine the type of register required */
+ if (sym->nRegs == 1 &&
+ IS_PTR (sym->type) &&
+ sym->uptr)
+ sym->regType = REG_PTR;
+ else
+ sym->regType = REG_GPR;
+
+
+ debugLog (" reg name %s, reg type %s\n", sym->rname, debugLogRegType (sym->regType));
+
+ }
+ else
+ /* for the first run we don't provide */
+ /* registers for true symbols we will */
+ /* see how things go */
+ sym->nRegs = 0;
+ }
+
+}
+DEFSETFUNC (markRegFree)
+{
+ ((regs *)item)->isFree = 1;
+
+ return 0;
+}
+
+DEFSETFUNC (deallocReg)
+{
+ fprintf(stderr,"deallocting register %s\n",((regs *)item)->name);
+ ((regs *)item)->isFree = 1;
+ ((regs *)item)->wasUsed = 0;
+
+ return 0;
+}
+/*-----------------------------------------------------------------*/
+/* freeAllRegs - mark all registers as free */
+/*-----------------------------------------------------------------*/
+void
+pic14_freeAllRegs ()
+{
+ // int i;
+
+ debugLog ("%s\n", __FUNCTION__);
+
+ applyToSet(dynAllocRegs,markRegFree);
+ applyToSet(dynStackRegs,markRegFree);
+
+ /*
+ for (i = 0; i < pic14_nRegs; i++)
+ regspic14[i].isFree = 1;
+ */
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void
+pic14_deallocateAllRegs ()
+{
+ // int i;
+
+ debugLog ("%s\n", __FUNCTION__);
+
+ applyToSet(dynAllocRegs,deallocReg);
+
+ /*
+ for (i = 0; i < pic14_nRegs; i++) {
+ if(regspic14[i].pc_type == PO_GPR_TEMP) {
+ regspic14[i].isFree = 1;
+ regspic14[i].wasUsed = 0;
+ }
+ }
+ */
+}
+
+
+/*-----------------------------------------------------------------*/
+/* deallocStackSpil - this will set the stack pointer back */
+/*-----------------------------------------------------------------*/
+static
+DEFSETFUNC (deallocStackSpil)
+{
+ symbol *sym = item;
+
+ debugLog ("%s\n", __FUNCTION__);
+ deallocLocal (sym);
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* farSpacePackable - returns the packable icode for far variables */
+/*-----------------------------------------------------------------*/
+static iCode *
+farSpacePackable (iCode * ic)
+{
+ iCode *dic;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* go thru till we find a definition for the
+ symbol on the right */
+ for (dic = ic->prev; dic; dic = dic->prev)
+ {
+
+ /* if the definition is a call then no */
+ if ((dic->op == CALL || dic->op == PCALL) &&
+ IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+ {
+ return NULL;
+ }
+
+ /* if shift by unknown amount then not */
+ if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) &&
+ IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+ return NULL;
+
+ /* if pointer get and size > 1 */
+ if (POINTER_GET (dic) &&
+ getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > 1)
+ return NULL;
+
+ if (POINTER_SET (dic) &&
+ getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1)
+ return NULL;
+
+ /* if any three is a true symbol in far space */
+ if (IC_RESULT (dic) &&
+ IS_TRUE_SYMOP (IC_RESULT (dic)) &&
+ isOperandInFarSpace (IC_RESULT (dic)))
+ return NULL;
+
+ if (IC_RIGHT (dic) &&
+ IS_TRUE_SYMOP (IC_RIGHT (dic)) &&
+ isOperandInFarSpace (IC_RIGHT (dic)) &&
+ !isOperandEqual (IC_RIGHT (dic), IC_RESULT (ic)))
+ return NULL;
+
+ if (IC_LEFT (dic) &&
+ IS_TRUE_SYMOP (IC_LEFT (dic)) &&
+ isOperandInFarSpace (IC_LEFT (dic)) &&
+ !isOperandEqual (IC_LEFT (dic), IC_RESULT (ic)))
+ return NULL;
+
+ if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (dic)))
+ {
+ if ((dic->op == LEFT_OP ||
+ dic->op == RIGHT_OP ||
+ dic->op == '-') &&
+ IS_OP_LITERAL (IC_RIGHT (dic)))
+ return NULL;
+ else
+ return dic;
+ }
+ }
+
+ return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegsForAssign - register reduction for assignment */
+/*-----------------------------------------------------------------*/
+static int
+packRegsForAssign (iCode * ic, eBBlock * ebp)
+{
+
+ iCode *dic, *sic;
+
+ debugLog ("%s\n", __FUNCTION__);
+
+ debugAopGet (" result:", IC_RESULT (ic));
+ debugAopGet (" left:", IC_LEFT (ic));
+ debugAopGet (" right:", IC_RIGHT (ic));
+
+ /* if this is at an absolute address, then get the address. */
+ if (SPEC_ABSA ( OP_SYM_ETYPE(IC_RESULT(ic))) ) {
+ if(IS_CONFIG_ADDRESS( SPEC_ADDR ( OP_SYM_ETYPE(IC_RESULT(ic))))) {
+ debugLog (" %d - found config word declaration\n", __LINE__);
+ if(IS_VALOP(IC_RIGHT(ic))) {
+ debugLog (" setting config word to %x\n",
+ (int) floatFromVal (IC_RIGHT(ic)->operand.valOperand));
+ pic14_assignConfigWordValue( SPEC_ADDR ( OP_SYM_ETYPE(IC_RESULT(ic))),
+ (int) floatFromVal (IC_RIGHT(ic)->operand.valOperand));
+ }
+
+ /* remove the assignment from the iCode chain. */
+
+ remiCodeFromeBBlock (ebp, ic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+ hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+
+ return 1;
+
+ }
+ }
+
+ if (!IS_ITEMP (IC_RESULT (ic))) {
+ allocDirReg(IC_RESULT (ic));
+ debugLog (" %d - result is not temp\n", __LINE__);
+ }
+ /*
+ if (IC_LEFT (ic) && !IS_ITEMP (IC_LEFT (ic))) {
+ debugLog (" %d - left is not temp, allocating\n", __LINE__);
+ allocDirReg(IC_LEFT (ic));
+ }
+ */
+
+ if (!IS_ITEMP (IC_RIGHT (ic))) {
+ debugLog (" %d - not packing - right is not temp\n", __LINE__);
+
+ /* only pack if this is not a function pointer */
+ if (!IS_REF (IC_RIGHT (ic)))
+ allocDirReg(IC_RIGHT (ic));
+ return 0;
+ }
+
+ if (OP_SYMBOL (IC_RIGHT (ic))->isind ||
+ OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
+ {
+ debugLog (" %d - not packing - right side fails \n", __LINE__);
+ return 0;
+ }
+
+ /* if the true symbol is defined in far space or on stack
+ then we should not since this will increase register pressure */
+ if (isOperandInFarSpace (IC_RESULT (ic)))
+ {
+ if ((dic = farSpacePackable (ic)))
+ goto pack;
+ else
+ return 0;
+
+ }
+ /* find the definition of iTempNN scanning backwards if we find a
+ a use of the true symbol before we find the definition then
+ we cannot pack */
+ for (dic = ic->prev; dic; dic = dic->prev)
+ {
+
+ /* 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 &&
+ !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
+ {
+ debugLog (" %d - \n", __LINE__);
+ dic = NULL;
+ break;
+ }
+
+ if (SKIP_IC2 (dic))
+ continue;
+
+ if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
+ IS_OP_VOLATILE (IC_RESULT (dic)))
+ {
+ debugLog (" %d - dic is VOLATILE \n", __LINE__);
+ dic = NULL;
+ break;
+ }
+
+ if (IS_SYMOP (IC_RESULT (dic)) &&
+ IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+ {
+ /* A previous result was assigned to the same register - we'll our definition */
+ debugLog (" %d - dic result key == ic right key -- pointer set=%c\n",
+ __LINE__, ((POINTER_SET (dic)) ? 'Y' : 'N'));
+ if (POINTER_SET (dic))
+ dic = NULL;
+
+ break;
+ }
+
+ if (IS_SYMOP (IC_RIGHT (dic)) &&
+ (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
+ IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
+ {
+ debugLog (" %d - dic right key == ic rightor result key\n", __LINE__);
+ dic = NULL;
+ break;
+ }
+
+ if (IS_SYMOP (IC_LEFT (dic)) &&
+ (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
+ IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
+ {
+ debugLog (" %d - dic left key == ic rightor result key\n", __LINE__);
+ dic = NULL;
+ break;
+ }
+
+ if (POINTER_SET (dic) &&
+ IC_RESULT (dic)->key == IC_RESULT (ic)->key)
+ {
+ debugLog (" %d - dic result key == ic result key -- pointer set=Y\n",
+ __LINE__);
+ dic = NULL;
+ break;
+ }
+ }
+
+ 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 ||
+ OP_SYMBOL (IC_RESULT (ic))->iaccess)
+ {
+
+ /* the operation has only one symbol
+ operator then we can pack */
+ if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) ||
+ (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic))))
+ goto pack;
+
+ if (!((IC_LEFT (dic) &&
+ IC_RESULT (ic)->key == IC_LEFT (dic)->key) ||
+ (IC_RIGHT (dic) &&
+ IC_RESULT (ic)->key == IC_RIGHT (dic)->key)))
+ return 0;
+ }
+pack:
+ debugLog (" packing. removing %s\n", OP_SYMBOL (IC_RIGHT (ic))->rname);
+ debugLog (" replacing with %s\n", OP_SYMBOL (IC_RESULT (dic))->rname);
+ /* found the definition */
+ /* replace the result with the result of */
+ /* this assignment and remove this assignment */
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+ IC_RESULT (dic) = IC_RESULT (ic);
+
+ if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
+ {
+ OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
+ }
+ /* delete from liverange table also
+ delete from all the points inbetween and the new
+ one */
+ for (sic = dic; sic != ic; sic = sic->next)
+ {
+ bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
+ if (IS_ITEMP (IC_RESULT (dic)))
+ bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
+ }
+
+ remiCodeFromeBBlock (ebp, ic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+ hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+ OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+ return 1;
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/* findAssignToSym : scanning backwards looks for first assig found */
+/*-----------------------------------------------------------------*/
+static iCode *
+findAssignToSym (operand * op, iCode * ic)
+{
+ iCode *dic;
+
+ debugLog ("%s\n", __FUNCTION__);
+ for (dic = ic->prev; dic; dic = dic->prev)
+ {
+
+ /* if definition by assignment */
+ if (dic->op == '=' &&
+ !POINTER_SET (dic) &&
+ IC_RESULT (dic)->key == op->key
+ /* && IS_TRUE_SYMOP(IC_RIGHT(dic)) */
+ )
+ {
+
+ /* we are interested only if defined in far space */
+ /* or in stack space in case of + & - */
+
+ /* if assigned to a non-symbol then return
+ true */
+ if (!IS_SYMOP (IC_RIGHT (dic)))
+ break;
+
+ /* if the symbol is in far space then
+ we should not */
+ if (isOperandInFarSpace (IC_RIGHT (dic)))
+ return NULL;
+
+ /* for + & - operations make sure that
+ if it is on the stack it is the same
+ as one of the three operands */
+ if ((ic->op == '+' || ic->op == '-') &&
+ OP_SYMBOL (IC_RIGHT (dic))->onStack)
+ {
+
+ if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
+ IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
+ IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
+ return NULL;
+ }
+
+ break;
+
+ }
+
+ /* if we find an usage then we cannot delete it */
+ if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
+ return NULL;
+
+ if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
+ return NULL;
+
+ if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
+ return NULL;
+ }
+
+ /* now make sure that the right side of dic
+ is not defined between ic & dic */
+ if (dic)
+ {
+ iCode *sic = dic->next;
+
+ for (; sic != ic; sic = sic->next)
+ if (IC_RESULT (sic) &&
+ IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
+ return NULL;
+ }
+
+ return dic;
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegsForSupport :- reduce some registers for support calls */
+/*-----------------------------------------------------------------*/
+static int
+packRegsForSupport (iCode * ic, eBBlock * ebp)
+{
+ int change = 0;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* for the left & right operand :- look to see if the
+ left was assigned a true symbol in far space in that
+ case replace them */
+ if (IS_ITEMP (IC_LEFT (ic)) &&
+ OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
+ {
+ iCode *dic = findAssignToSym (IC_LEFT (ic), ic);
+ iCode *sic;
+
+ if (!dic)
+ goto right;
+
+ debugAopGet ("removing left:", IC_LEFT (ic));
+
+ /* found it we need to remove it from the
+ block */
+ for (sic = dic; sic != ic; sic = sic->next)
+ bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
+
+ IC_LEFT (ic)->operand.symOperand =
+ IC_RIGHT (dic)->operand.symOperand;
+ IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
+ remiCodeFromeBBlock (ebp, dic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+ hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+ change++;
+ }
+
+ /* do the same for the right operand */
+right:
+ if (!change &&
+ IS_ITEMP (IC_RIGHT (ic)) &&
+ OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
+ {
+ iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
+ iCode *sic;
+
+ if (!dic)
+ return change;
+
+ /* if this is a subtraction & the result
+ is a true symbol in far space then don't pack */
+ if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
+ {
+ sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
+ if (IN_FARSPACE (SPEC_OCLS (etype)))
+ return change;
+ }
+
+ debugAopGet ("removing right:", IC_RIGHT (ic));
+
+ /* found it we need to remove it from the
+ block */
+ for (sic = dic; sic != ic; sic = sic->next)
+ bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
+
+ IC_RIGHT (ic)->operand.symOperand =
+ IC_RIGHT (dic)->operand.symOperand;
+ IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
+
+ remiCodeFromeBBlock (ebp, dic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+ hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+ change++;
+ }
+
+ return change;
+}
+
+#define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
+
+
+/*-----------------------------------------------------------------*/
+/* packRegsForOneuse : - will reduce some registers for single Use */
+/*-----------------------------------------------------------------*/
+static iCode *
+packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
+{
+ bitVect *uses;
+ iCode *dic, *sic;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* if returning a literal then do nothing */
+ if (!IS_SYMOP (op))
+ return NULL;
+
+ /* 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
+ far space */
+ uses = bitVectCopy (OP_USES (op));
+ bitVectUnSetBit (uses, ic->key); /* take away this iCode */
+ if (!bitVectIsZero (uses)) /* has other uses */
+ return NULL;
+
+ /* if it has only one defintion */
+ if (bitVectnBitsOn (OP_DEFS (op)) > 1)
+ return NULL; /* has more than one definition */
+
+ /* get that definition */
+ if (!(dic =
+ hTabItemWithKey (iCodehTab,
+ bitVectFirstBit (OP_DEFS (op)))))
+ return NULL;
+
+ /* found the definition now check if it is local */
+ if (dic->seq < ebp->fSeq ||
+ dic->seq > ebp->lSeq)
+ return NULL; /* non-local */
+
+ /* now check if it is the return from
+ a function call */
+ if (dic->op == CALL || dic->op == PCALL)
+ {
+ if (ic->op != SEND && ic->op != RETURN &&
+ !POINTER_SET(ic) && !POINTER_GET(ic))
+ {
+ OP_SYMBOL (op)->ruonly = 1;
+ return dic;
+ }
+ dic = dic->next;
+ }
+
+
+ /* otherwise check that the definition does
+ not contain any symbols in far space */
+ if (isOperandInFarSpace (IC_LEFT (dic)) ||
+ isOperandInFarSpace (IC_RIGHT (dic)) ||
+ IS_OP_RUONLY (IC_LEFT (ic)) ||
+ IS_OP_RUONLY (IC_RIGHT (ic)))
+ {
+ return NULL;
+ }
+
+ /* if pointer set then make sure the pointer
+ is one byte */
+ if (POINTER_SET (dic) &&
+ !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
+ return NULL;
+
+ if (POINTER_GET (dic) &&
+ !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
+ return NULL;
+
+ sic = dic;
+
+ /* also make sure the intervenening instructions
+ don't have any thing in far space */
+ for (dic = dic->next; dic && dic != ic; dic = dic->next)
+ {
+
+ /* if there is an intervening function call then no */
+ if (dic->op == CALL || dic->op == PCALL)
+ return NULL;
+ /* if pointer set then make sure the pointer
+ is one byte */
+ if (POINTER_SET (dic) &&
+ !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
+ return NULL;
+
+ if (POINTER_GET (dic) &&
+ !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
+ return NULL;
+
+ /* if address of & the result is remat then okay */
+ if (dic->op == ADDRESS_OF &&
+ OP_SYMBOL (IC_RESULT (dic))->remat)
+ continue;
+
+ /* if operand has size of three or more & this
+ operation is a '*','/' or '%' then 'b' may
+ cause a problem */
+ if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
+ getSize (operandType (op)) >= 3)
+ return NULL;
+
+ /* if left or right or result is in far space */
+ if (isOperandInFarSpace (IC_LEFT (dic)) ||
+ isOperandInFarSpace (IC_RIGHT (dic)) ||
+ isOperandInFarSpace (IC_RESULT (dic)) ||
+ IS_OP_RUONLY (IC_LEFT (dic)) ||
+ IS_OP_RUONLY (IC_RIGHT (dic)) ||
+ IS_OP_RUONLY (IC_RESULT (dic)))
+ {
+ return NULL;
+ }
+ }
+
+ OP_SYMBOL (op)->ruonly = 1;
+ return sic;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* isBitwiseOptimizable - requirements of JEAN LOUIS VERN */
+/*-----------------------------------------------------------------*/
+static bool
+isBitwiseOptimizable (iCode * ic)
+{
+ sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
+ sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* bitwise operations are considered optimizable
+ under the following conditions (Jean-Louis VERN)
+
+ x & lit
+ bit & bit
+ bit & x
+ bit ^ bit
+ bit ^ x
+ x ^ lit
+ x | lit
+ bit | bit
+ bit | x
+ */
+ if (IS_LITERAL (rtype) ||
+ (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegsForAccUse - pack registers for acc use */
+/*-----------------------------------------------------------------*/
+static void
+packRegsForAccUse (iCode * ic)
+{
+ //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;
+ }
+ debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
+
+ /* if + or - then it has to be one byte result */
+ if ((ic->op == '+' || ic->op == '-')
+ && getSize (operandType (IC_RESULT (ic))) > 1)
+ return;
+
+ debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
+ /* if shift operation make sure right side is not a literal */
+ if (ic->op == RIGHT_OP &&
+ (isOperandLiteral (IC_RIGHT (ic)) ||
+ getSize (operandType (IC_RESULT (ic))) > 1))
+ return;
+
+ if (ic->op == LEFT_OP &&
+ (isOperandLiteral (IC_RIGHT (ic)) ||
+ getSize (operandType (IC_RESULT (ic))) > 1))
+ return;
+
+ if (IS_BITWISE_OP (ic) &&
+ getSize (operandType (IC_RESULT (ic))) > 1)
+ return;
+
+
+ /* has only one definition */
+ if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
+ return;
+
+ /* has only one use */
+ if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
+ return;
+
+ /* and the usage immediately follows this iCode */
+ if (!(uic = hTabItemWithKey (iCodehTab,
+ bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
+ return;
+
+ debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
+ if (ic->next != uic)
+ return;
+
+ /* if it is a conditional branch then we definitely can */
+ if (uic->op == IFX)
+ goto accuse;
+
+ if (uic->op == JUMPTABLE)
+ return;
+
+ /* if the usage is not is an assignment
+ or an arithmetic / bitwise / shift operation then not */
+ if (POINTER_SET (uic) &&
+ getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1)
+ return;
+
+ debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
+ if (uic->op != '=' &&
+ !IS_ARITHMETIC_OP (uic) &&
+ !IS_BITWISE_OP (uic) &&
+ uic->op != LEFT_OP &&
+ uic->op != RIGHT_OP)
+ return;
+
+ debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
+ /* if used in ^ operation then make sure right is not a
+ literl */
+ if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
+ return;
+
+ /* if shift operation make sure right side is not a literal */
+ if (uic->op == RIGHT_OP &&
+ (isOperandLiteral (IC_RIGHT (uic)) ||
+ getSize (operandType (IC_RESULT (uic))) > 1))
+ return;
+
+ if (uic->op == LEFT_OP &&
+ (isOperandLiteral (IC_RIGHT (uic)) ||
+ getSize (operandType (IC_RESULT (uic))) > 1))
+ return;
+
+ /* make sure that the result of this icode is not on the
+ stack, since acc is used to compute stack offset */
+ if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
+ OP_SYMBOL (IC_RESULT (uic))->onStack)
+ return;
+
+ /* if either one of them in far space then we cannot */
+ if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
+ isOperandInFarSpace (IC_LEFT (uic))) ||
+ (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
+ isOperandInFarSpace (IC_RIGHT (uic))))
+ return;
+
+ /* if the usage has only one operand then we can */
+ if (IC_LEFT (uic) == NULL ||
+ IC_RIGHT (uic) == NULL)
+ goto accuse;
+
+ /* make sure this is on the left side if not
+ a '+' since '+' is commutative */
+ if (ic->op != '+' &&
+ IC_LEFT (uic)->key != IC_RESULT (ic)->key)
+ return;
+
+ debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
+ /* if one of them is a literal then we can */
+ if ( ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) ||
+ (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic)))) &&
+ (getSize (operandType (IC_RESULT (uic))) <= 1))
+ {
+ OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
+ return;
+ }
+
+ debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
+ /* if the other one is not on stack then we can */
+ if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
+ (IS_ITEMP (IC_RIGHT (uic)) ||
+ (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
+ !OP_SYMBOL (IC_RIGHT (uic))->onStack)))
+ goto accuse;
+
+ if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key &&
+ (IS_ITEMP (IC_LEFT (uic)) ||
+ (IS_TRUE_SYMOP (IC_LEFT (uic)) &&
+ !OP_SYMBOL (IC_LEFT (uic))->onStack)))
+ goto accuse;
+
+ return;
+
+accuse:
+ debugLog ("%s - Yes we are using the accumulator\n", __FUNCTION__);
+ OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
+#endif
+}
+
+/*-----------------------------------------------------------------*/
+/* packForPush - hueristics to reduce iCode for pushing */
+/*-----------------------------------------------------------------*/
+static void
+packForReceive (iCode * ic, eBBlock * ebp)
+{
+ iCode *dic;
+
+ debugLog ("%s\n", __FUNCTION__);
+ debugAopGet (" result:", IC_RESULT (ic));
+ debugAopGet (" left:", IC_LEFT (ic));
+ debugAopGet (" right:", IC_RIGHT (ic));
+
+ if (!ic->next)
+ return;
+
+ for (dic = ic->next; dic; dic = dic->next)
+ {
+
+
+
+ if (IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key))
+ debugLog (" used on left\n");
+ if (IC_RIGHT (dic) && IC_RESULT (ic)->key == IC_RIGHT (dic)->key)
+ debugLog (" used on right\n");
+ if (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key)
+ debugLog (" used on result\n");
+
+ if ((IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key)) ||
+ (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key))
+ return;
+
+ }
+
+ debugLog (" hey we can remove this unnecessary assign\n");
+}
+/*-----------------------------------------------------------------*/
+/* packForPush - hueristics to reduce iCode for pushing */
+/*-----------------------------------------------------------------*/
+static void
+packForPush (iCode * ic, eBBlock * ebp)
+{
+ iCode *dic;
+
+ debugLog ("%s\n", __FUNCTION__);
+ if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
+ return;
+
+ /* must have only definition & one usage */
+ if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
+ bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
+ return;
+
+ /* find the definition */
+ if (!(dic = hTabItemWithKey (iCodehTab,
+ bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
+ return;
+
+ if (dic->op != '=' || POINTER_SET (dic))
+ return;
+
+ /* we now we know that it has one & only one def & use
+ and the that the definition is an assignment */
+ IC_LEFT (ic) = IC_RIGHT (dic);
+
+ remiCodeFromeBBlock (ebp, dic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+ hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+}
+
+void printSymType(char * str, sym_link *sl)
+{
+ debugLog (" %s Symbol type: ",str);
+ printTypeChain( sl, debugF);
+ debugLog ("\n");
+
+}
+
+/*-----------------------------------------------------------------*/
+/* some debug code to print the symbol S_TYPE. Note that
+* the function checkSClass in src/SDCCsymt.c dinks with
+* the S_TYPE in ways the PIC port doesn't fully like...*/
+/*-----------------------------------------------------------------*/
+void isData(sym_link *sl)
+{
+ FILE *of = stderr;
+
+ if(!sl)
+ return;
+
+ if(debugF)
+ of = debugF;
+
+ for ( ; sl; sl=sl->next) {
+ if(!IS_DECL(sl) ) {
+ switch (SPEC_SCLS(sl)) {
+
+ case S_DATA: fprintf (of, "data "); break;
+ case S_XDATA: fprintf (of, "xdata "); break;
+ case S_SFR: fprintf (of, "sfr "); break;
+ case S_SBIT: fprintf (of, "sbit "); break;
+ case S_CODE: fprintf (of, "code "); break;
+ case S_IDATA: fprintf (of, "idata "); break;
+ case S_PDATA: fprintf (of, "pdata "); break;
+ case S_LITERAL: fprintf (of, "literal "); break;
+ case S_STACK: fprintf (of, "stack "); break;
+ case S_XSTACK: fprintf (of, "xstack "); break;
+ case S_BIT: fprintf (of, "bit "); break;
+ case S_EEPROM: fprintf (of, "eeprom "); break;
+ default: break;
+ }
+
+ }
+
+ }
+
+}