#include "z80.h"
+/* Flags to turn off optimisations.
+ */
enum
{
DISABLE_PACK_ACC = 0,
DISABLE_PACK_ASSIGN = 0,
DISABLE_PACK_ONE_USE = 0,
DISABLE_PACK_HL = 0,
- LIMITED_PACK_ACC = 1,
};
+/* Flags to turn on debugging code.
+ */
enum
{
D_ALLOC = 0,
- D_ALLOC2 = 0
+ D_ALLOC2 = 0,
+ D_ACCUSE2 = 0,
+ D_ACCUSE2_VERBOSE = 0
};
#if 1
#define DISABLE_PACKREGSFORSUPPORT 1
#define DISABLE_PACKREGSFORACCUSE 1
-/*-----------------------------------------------------------------*/
-/* At this point we start getting processor specific although */
-/* some routines are non-processor specific & can be reused when */
-/* targetting other processors. The decision for this will have */
-/* to be made on a routine by routine basis */
-/* routines used to pack registers are most definitely not reusable */
-/* since the pack the registers depending strictly on the MCU */
-/*-----------------------------------------------------------------*/
-
-bitVect *spiltSet = NULL;
-set *stackSpil = NULL;
-bitVect *regAssigned = NULL;
-short blockSpil = 0;
-int slocNum = 0;
extern void genZ80Code (iCode *);
-bitVect *funcrUsed = NULL; /* registers used in a function */
-int stackExtend = 0;
-int dataExtend = 0;
-int _nRegs;
-/** Set to help debug register pressure related problems */
-#define DEBUG_FAKE_EXTRA_REGS 0
+/** Local static variables */
+static struct
+{
+ bitVect *spiltSet;
+ set *stackSpil;
+ bitVect *regAssigned;
+ short blockSpil;
+ int slocNum;
+ /* registers used in a function */
+ bitVect *funcrUsed;
+ int stackExtend;
+ int dataExtend;
+ int nRegs;
+} _G;
static regs _gbz80_regs[] =
{
{REG_GPR, B_IDX, "b", 1},
{REG_GPR, E_IDX, "e", 1},
{REG_GPR, D_IDX, "d", 1},
- /* { REG_GPR, L_IDX , "l", 1 },
- { REG_GPR, H_IDX , "h", 1 }, */
-#if DEBUG_FAKE_EXTRA_REGS
- {REG_GPR, M_IDX, "m", 1},
- {REG_GPR, N_IDX, "n", 1},
- {REG_GPR, O_IDX, "o", 1},
- {REG_GPR, P_IDX, "p", 1},
- {REG_GPR, Q_IDX, "q", 1},
- {REG_GPR, R_IDX, "r", 1},
- {REG_GPR, S_IDX, "s", 1},
- {REG_GPR, T_IDX, "t", 1},
-#endif
{REG_CND, CND_IDX, "c", 1}
};
{
int i;
- for (i = 0; i < _nRegs; i++)
+ for (i = 0; i < _G.nRegs; i++)
{
/* For now we allocate from any free */
if (regsZ80[i].isFree)
{
regsZ80[i].isFree = 0;
if (currFunc)
- currFunc->regsUsed =
- bitVectSetBit (currFunc->regsUsed, i);
+ {
+ currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, i);
+ }
D (D_ALLOC, ("allocReg: alloced %p\n", ®sZ80[i]));
return ®sZ80[i];
}
{
int i;
- for (i = 0; i < _nRegs; i++)
- if (regsZ80[i].rIdx == idx)
- return ®sZ80[i];
+ for (i = 0; i < _G.nRegs; i++)
+ {
+ if (regsZ80[i].rIdx == idx)
+ {
+ return ®sZ80[i];
+ }
+ }
- werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- "regWithIdx not found");
+ wassertl (0, "regWithIdx not found");
exit (1);
}
int i;
int nfr = 0;
- for (i = 0; i < _nRegs; i++)
+ for (i = 0; i < _G.nRegs; i++)
{
/* For now only one reg type */
if (regsZ80[i].isFree)
- nfr++;
+ {
+ nfr++;
+ }
}
return nfr;
}
if (type == REG_PTR)
{
if ((nfr = nFreeRegs (type)) == 0)
- return nFreeRegs (REG_GPR);
+ {
+ return nFreeRegs (REG_GPR);
+ }
}
return nFreeRegs (type);
spillable = bitVectCopy (ic->rlive);
spillable =
- bitVectCplAnd (spillable, spiltSet); /* those already spilt */
+ bitVectCplAnd (spillable, _G.spiltSet); /* those already spilt */
spillable =
bitVectCplAnd (spillable, ic->uses); /* used in this one */
bitVectUnSetBit (spillable, ic->defKey);
- spillable = bitVectIntersect (spillable, regAssigned);
- return spillable;
+ spillable = bitVectIntersect (spillable, _G.regAssigned);
+ return spillable;
}
/*-----------------------------------------------------------------*/
return 1;
}
-/*-----------------------------------------------------------------*/
-/* liveRangesWith - applies function to a given set of live range */
-/*-----------------------------------------------------------------*/
-set *
+/** liveRangesWith - applies function to a given set of live range
+ */
+static set *
liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
eBBlock * ebp, iCode * ic)
{
hash table we are in serious trouble */
if (!(sym = hTabItemWithKey (liveRanges, i)))
{
- werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- "liveRangesWith could not find liveRange");
+ wassertl (0, "liveRangesWith could not find liveRange");
exit (1);
}
- if (func (sym, ebp, ic) && bitVectBitValue (regAssigned, sym->key))
- addSetHead (&rset, sym);
+ if (func (sym, ebp, ic) && bitVectBitValue (_G.regAssigned, sym->key))
+ {
+ addSetHead (&rset, sym);
+ }
}
return rset;
}
-/*-----------------------------------------------------------------*/
-/* leastUsedLR - given a set determines which is the least used */
-/*-----------------------------------------------------------------*/
-symbol *
+/** leastUsedLR - given a set determines which is the least used
+ */
+static symbol *
leastUsedLR (set * sset)
{
symbol *sym = NULL, *lsym = NULL;
return sym;
}
-/*-----------------------------------------------------------------*/
-/* noOverLap - will iterate through the list looking for over lap */
-/*-----------------------------------------------------------------*/
+/** noOverLap - will iterate through the list looking for over lap
+ */
static int
noOverLap (set * itmpStack, symbol * fsym)
{
for (sym = setFirstItem (itmpStack); sym;
sym = setNextItem (itmpStack))
{
- if (sym->liveTo > fsym->liveFrom)
- return 0;
-
+ // if sym starts before (or on) our end point
+ // and ends after (or on) our start point,
+ // it is an overlap.
+ if (sym->liveFrom <= fsym->liveTo &&
+ sym->liveTo >= fsym->liveFrom)
+ {
+ return 0;
+ }
}
return 1;
}
/*-----------------------------------------------------------------*/
/* createStackSpil - create a location on the stack to spil */
/*-----------------------------------------------------------------*/
-symbol *
+static symbol *
createStackSpil (symbol * sym)
{
symbol *sloc = NULL;
/* first go try and find a free one that is already
existing on the stack */
- if (applyToSet (stackSpil, isFree, &sloc, sym))
+ if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
{
/* found a free one : just update & return */
sym->usl.spillLoc = sloc;
we need to allocate this on the stack : this is really a
hack!! but cannot think of anything better at this time */
- sprintf (buffer, "sloc%d", slocNum++);
+ sprintf (buffer, "sloc%d", _G.slocNum++);
sloc = newiTemp (buffer);
/* set the type to the spilling symbol */
sloc->etype = getSpec (sloc->type);
SPEC_SCLS (sloc->etype) = S_AUTO;
- /* we don't allow it to be allocated`
- onto the external stack since : so we
- temporarily turn it off ; we also
- turn off memory model to prevent
- the spil from going to the external storage
- and turn off overlaying
- */
allocLocal (sloc);
sloc->isref = 1; /* to prevent compiler warning */
if (IN_STACK (sloc->etype))
{
currFunc->stack += getSize (sloc->type);
- stackExtend += getSize (sloc->type);
+ _G.stackExtend += getSize (sloc->type);
}
else
- dataExtend += getSize (sloc->type);
+ {
+ _G.dataExtend += getSize (sloc->type);
+ }
/* add it to the stackSpil set */
- addSetHead (&stackSpil, sloc);
+ addSetHead (&_G.stackSpil, sloc);
sym->usl.spillLoc = sloc;
sym->stackSpil = 1;
return sym;
}
-/*-----------------------------------------------------------------*/
-/* isSpiltOnStack - returns true if the spil location is on stack */
-/*-----------------------------------------------------------------*/
-bool
-isSpiltOnStack (symbol * sym)
-{
- sym_link *etype;
-
- if (!sym)
- return FALSE;
-
- if (!sym->isspilt)
- return FALSE;
-
-/* if (sym->stackSpil) */
-/* return TRUE; */
-
- if (!sym->usl.spillLoc)
- return FALSE;
-
- etype = getSpec (sym->usl.spillLoc->type);
- if (IN_STACK (etype))
- return TRUE;
-
- return FALSE;
-}
-
/*-----------------------------------------------------------------*/
/* spillThis - spils a specific operand */
/*-----------------------------------------------------------------*/
we are okay, else we need to create a spillLocation
for it */
if (!(sym->remat || sym->usl.spillLoc))
- createStackSpil (sym);
+ {
+ createStackSpil (sym);
+ }
/* mark it has spilt & put it in the spilt set */
sym->isspilt = 1;
- spiltSet = bitVectSetBit (spiltSet, sym->key);
+ _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
- bitVectUnSetBit (regAssigned, sym->key);
+ bitVectUnSetBit (_G.regAssigned, sym->key);
for (i = 0; i < sym->nRegs; i++)
{
}
}
- /* if spilt on stack then free up r0 & r1
- if they could have been assigned to some
- LIVE ranges */
if (sym->usl.spillLoc && !sym->remat)
- sym->usl.spillLoc->allocreq = 1;
+ {
+ sym->usl.spillLoc->allocreq = 1;
+ }
return;
}
+#if DISABLED
+/*-----------------------------------------------------------------*/
+/* allDefsOutOfRange - all definitions are out of a range */
+/*-----------------------------------------------------------------*/
+static bool
+allDefsOutOfRange (bitVect * defs, int fseq, int toseq)
+{
+ int i;
+
+ if (!defs)
+ return TRUE;
+
+ for (i = 0; i < defs->size; i++)
+ {
+ iCode *ic;
+
+ if (bitVectBitValue (defs, i) &&
+ (ic = hTabItemWithKey (iCodehTab, i)) &&
+ (ic->seq >= fseq && ic->seq <= toseq))
+
+ return FALSE;
+
+ }
+
+ return TRUE;
+}
+
+/*-----------------------------------------------------------------*/
+/* hasSpilLocnoUptr - will return 1 if the symbol has spil location */
+/* but is not used as a pointer */
+/*-----------------------------------------------------------------*/
+static int
+hasSpilLocnoUptr (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+ return ((sym->usl.spillLoc && !sym->uptr) ? 1 : 0);
+}
+
+/*-----------------------------------------------------------------*/
+/* notUsedInBlock - not used in this block */
+/*-----------------------------------------------------------------*/
+static int
+notUsedInBlock (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+ return (!bitVectBitsInCommon (sym->defs, ebp->usesDefs) &&
+ allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
+/* return (!bitVectBitsInCommon(sym->defs,ebp->usesDefs)); */
+}
+
+/*-----------------------------------------------------------------*/
+/* notUsedInRemaining - not used or defined in remain of the block */
+/*-----------------------------------------------------------------*/
+static int
+notUsedInRemaining (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+ return ((usedInRemaining (operandFromSymbol (sym), ic) ? 0 : 1) &&
+ allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
+}
+#endif
+
/** Select a iTemp to spil : rather a simple procedure.
*/
symbol *
/* check if there are any live ranges allocated
to registers that are not used in this block */
- if (!blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
+ if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
{
sym = leastUsedLR (selectS);
/* if this is not rematerializable */
if (!sym->remat)
{
- blockSpil++;
+ _G.blockSpil++;
+ wassertl (0, "Attempted to do an unsupported block spill");
sym->blockSpil = 1;
}
return sym;
/* check if there are any live ranges that not
used in the remainder of the block */
- if (!blockSpil && (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
+ if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
{
sym = leastUsedLR (selectS);
- if (sym != ForSym)
+ if (sym != forSym)
{
if (!sym->remat)
{
+ wassertl (0, "Attempted to do an unsupported remain spill");
sym->remainSpil = 1;
- blockSpil++;
+ _G.blockSpil++;
}
return sym;
}
/* mark it as spilt */
ssym->isspilt = 1;
- spiltSet = bitVectSetBit (spiltSet, ssym->key);
+ _G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key);
/* mark it as not register assigned &
take it away from the set */
- bitVectUnSetBit (regAssigned, ssym->key);
+ bitVectUnSetBit (_G.regAssigned, ssym->key);
/* mark the registers as free */
for (i = 0; i < ssym->nRegs; i++)
if (ssym->regs[i])
freeReg (ssym->regs[i]);
+
+ wassertl (ssym->blockSpil == 0, "Encountered a sym with a block spill");
+ wassertl (ssym->remainSpil == 0, "Encountered a sym with a remain spill");
#if 0
/* if spilt on stack then free up r0 & r1
if they could have been assigned to as gprs */
continue;
}
- if (!bitVectBitValue (regAssigned, sym->key))
+ if (!bitVectBitValue (_G.regAssigned, sym->key))
continue;
/* special case check if this is an IFX &
{
int i = 0;
- bitVectUnSetBit (regAssigned, sym->key);
+ bitVectUnSetBit (_G.regAssigned, sym->key);
/* if the result of this one needs registers
and does not have it then assign it right
result->nRegs && /* which needs registers */
!result->isspilt && /* and does not already have them */
!result->remat &&
- !bitVectBitValue (regAssigned, result->key) &&
+ !bitVectBitValue (_G.regAssigned, result->key) &&
/* the number of free regs + number of regs in this LR
can accomodate the what result Needs */
((nfreeRegsType (result->regType) +
}
}
- regAssigned = bitVectSetBit (regAssigned, result->key);
+ _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
}
/* free the remaining */
/* not spilt any more */
sym->isspilt = sym->blockSpil = sym->remainSpil = 0;
- bitVectUnSetBit (spiltSet, sym->key);
+ bitVectUnSetBit (_G.spiltSet, sym->key);
- regAssigned = bitVectSetBit (regAssigned, sym->key);
+ _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
- blockSpil--;
+ _G.blockSpil--;
for (i = 0; i < sym->nRegs; i++)
sym->regs[i]->isFree = 0;
{
int i;
wassert (sym->nRegs == 2);
- for (i = 0; i < _nRegs; i += 2)
+ for (i = 0; i < _G.nRegs; i += 2)
{
if ((regsZ80[i].isFree) && (regsZ80[i + 1].isFree))
{
or will not live beyond this instructions */
if (!sym->nRegs ||
sym->isspilt ||
- bitVectBitValue (regAssigned, sym->key) ||
+ bitVectBitValue (_G.regAssigned, sym->key) ||
sym->liveTo <= ic->seq)
{
D (D_ALLOC, ("serialRegAssign: wont live long enough.\n"));
/* if some liverange has been spilt at the block level
and this one live beyond this block then spil this
to be safe */
- if (blockSpil && sym->liveTo > ebbs[i]->lSeq)
+ if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
{
D (D_ALLOC, ("serialRegAssign: \"spilling to be safe.\"\n"));
spillThis (sym);
}
/* else we assign registers to it */
- regAssigned = bitVectSetBit (regAssigned, sym->key);
+ _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
/* Special case: Try to fit into a reg pair if
available */
if (sym->isspilt || !sym->nRegs)
return NULL;
- rumask = newBitVect (_nRegs);
+ rumask = newBitVect (_G.nRegs);
for (j = 0; j < sym->nRegs; j++)
{
return rumask;
}
+bitVect *
+z80_rUmaskForOp (operand * op)
+{
+ return rUmaskForOp (op);
+}
+
/** Returns bit vector of registers used in iCode.
*/
bitVect *
regsUsedIniCode (iCode * ic)
{
- bitVect *rmask = newBitVect (_nRegs);
+ bitVect *rmask = newBitVect (_G.nRegs);
/* do the special cases first */
if (ic->op == IFX)
/* first mark the registers used in this
instruction */
ic->rUsed = regsUsedIniCode (ic);
- funcrUsed = bitVectUnion (funcrUsed, ic->rUsed);
+ _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 (_nRegs + 1);
+ ic->rMask = newBitVect (_G.nRegs + 1);
/* for all live Ranges alive at this point */
for (j = 1; j < ic->rlive->size; j++)
D (D_ALLOC, ("freeAllRegs: running.\n"));
- for (i = 0; i < _nRegs; i++)
+ for (i = 0; i < _G.nRegs; i++)
regsZ80[i].isFree = 1;
}
{
iCode *dic, *sic;
- D (D_ALLOC, ("packRegsForAssing: running on ic %p\n", ic));
+ D (D_ALLOC, ("packRegsForAssign: running on ic %p\n", ic));
- if (
- /* !IS_TRUE_SYMOP(IC_RESULT(ic)) || */
- !IS_ITEMP (IC_RIGHT (ic)) ||
- OP_LIVETO (IC_RIGHT (ic)) > ic->seq ||
- OP_SYMBOL (IC_RIGHT (ic))->isind)
- return 0;
+ if (!IS_ITEMP (IC_RIGHT (ic)) ||
+ OP_SYMBOL (IC_RIGHT (ic))->isind ||
+ OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
+ {
+ return 0;
+ }
#if 0
/* if the true symbol is defined in far space or on stack
}
remiCodeFromeBBlock (ebp, ic);
+ // PENDING: Check vs mcs51
return 1;
}
IC_RIGHT (dic)->operand.symOperand;
IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
remiCodeFromeBBlock (ebp, dic);
+ // PENDING: Check vs mcs51
change++;
}
IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
remiCodeFromeBBlock (ebp, dic);
+ // PENDING: vs mcs51
change++;
}
bitVect *uses;
iCode *dic, *sic;
+ // PENDING: Disable
D (D_ALLOC, ("packRegsForOneUse: running on ic %p\n", ic));
/* if returning a literal then do nothing */
IC_LEFT (uic)->key != IC_RESULT (ic)->key)
return;
+ // See mcs51 ralloc for reasoning
+#if 0
/* 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))))
goto accuse;
return;
}
+#endif
/** This is confusing :) Guess for now */
if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_HL;
}
-bool
+static bool
opPreservesA (iCode * ic, iCode * uic)
{
- /* if it is a conditional branch then we definitely can */
if (uic->op == IFX)
- return FALSE;
+ {
+ /* If we've gotten this far then the thing to compare must be
+ small enough and must be in A.
+ */
+ return TRUE;
+ }
if (uic->op == JUMPTABLE)
- return FALSE;
+ {
+ D (D_ACCUSE2, (" + Dropping as operation is a Jumptable\n"));
+ return FALSE;
+ }
+
+ /* A pointer assign preserves A if A is the left value. */
+ if (uic->op == '=' && POINTER_SET (uic))
+ {
+ return TRUE;
+ }
/* if the usage has only one operand then we can */
/* PENDING: check */
if (IC_LEFT (uic) == NULL ||
IC_RIGHT (uic) == NULL)
- return FALSE;
-
- /* PENDING: check this rule */
- if (getSize (operandType (IC_RESULT (uic))) > 1)
{
+ D (D_ACCUSE2, (" + Dropping as operation has only one operand\n"));
return FALSE;
}
- /*
- Bad:
- !IS_ARITHMETIC_OP(uic) (sub requires A)
- */
- if (
- uic->op != '+' &&
- !IS_BITWISE_OP (uic) &&
- uic->op != '=' &&
- uic->op != EQ_OP &&
- !POINTER_GET (uic) &&
- /*
- uic->op != LEFT_OP &&
- uic->op != RIGHT_OP && */
- 1
- )
+ /* PENDING: check this rule */
+ if (getSize (operandType (IC_RESULT (uic))) > 1)
{
+ D (D_ACCUSE2, (" + Dropping as operation has size is too big\n"));
return FALSE;
}
- /* PENDING */
- if (!IC_LEFT (uic) || !IC_RESULT (ic))
- return FALSE;
-
-/** This is confusing :) Guess for now */
- if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
- (IS_ITEMP (IC_RIGHT (uic)) ||
- (IS_TRUE_SYMOP (IC_RIGHT (uic)))))
- return TRUE;
-
- if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key &&
- (IS_ITEMP (IC_LEFT (uic)) ||
- (IS_TRUE_SYMOP (IC_LEFT (uic)))))
- return TRUE;
+ /* Disabled all of the old rules as they weren't verified and have
+ caused at least one problem.
+ */
return FALSE;
}
-static void
-joinPushes (iCode * ic)
+static bool
+opIgnoresA (iCode * ic, iCode * uic)
{
-#if 0
- if (ic->op == IPUSH &&
- isOperandLiteral (IC_LEFT (ic)) &&
- getSize (operandType (IC_LEFT (ic))) == 1 &&
- ic->next->op == IPUSH &&
- isOperandLiteral (IC_LEFT (ic->next)) &&
- getSize (operandType (IC_LEFT (ic->next))) == 1)
- {
- /* This is a bit tricky as michaelh doesnt know what he's doing.
- */
- /* First upgrade the size of (first) to int */
- SPEC_NOUN (operandType (IC_LEFT (ic))) = V_INT;
-
- floatFromVal (AOP /* need some sleep ... */ );
- /* Now get and join the values */
- value *val = aop->aopu.aop_lit;
- /* if it is a float then it gets tricky */
- /* otherwise it is fairly simple */
- if (!IS_FLOAT (val->type))
- {
- unsigned long v = floatFromVal (val);
-
- floatFrom ( /* need some sleep ... */ );
- printf ("Size %u\n", getSize (operandType (IC_LEFT (ic))));
- ic->next = ic->next->next;
- }
+ /* A increment of an iTemp by a constant is OK. */
+ if ( uic->op == '+' &&
+ IS_ITEMP (IC_LEFT (uic)) &&
+ IS_ITEMP (IC_RESULT (uic)) &&
+ IS_OP_LITERAL (IC_RIGHT (uic)))
+ {
+ unsigned int icount = (unsigned int) floatFromVal (IC_RIGHT (uic)->operand.valOperand);
+
+ /* Being an ITEMP means that we're already a symbol. */
+ if (icount == 1 &&
+ IC_RESULT (uic)->operand.symOperand->key == IC_LEFT (uic)->operand.symOperand->key
+ )
+ {
+ return TRUE;
+ }
}
-#endif
+
+ return FALSE;
}
+
+/* Some optimisation cases:
+
+ 1. Part of memcpy
+; genPointerGet
+ ld l,-4(ix)
+ ld h,-3(ix)
+ ld c,(hl)
+; genPlus
+ inc -4(ix)
+ jp nz,00108$
+ inc -3(ix)
+00108$:
+; genAssign (pointer)
+ ld a,c
+ ld (de),a
+
+ want to optimise down to:
+ ld hl,-4(ix) ...
+ ld a,(hl)
+ inc -4(ix).w ...
+ ld (de),a
+
+ So genPointer get is OK
+ genPlus where the right is constant, left is iTemp, and result is same as left
+ genAssign (pointer) is OK
+
+ 2. Part of _strcpy
+; genPointerGet
+ ld a,(de)
+ ld c,a
+; genIfx
+ xor a,a
+ or a,c
+ jp z,00103$
+; _strcpy.c 40
+; genAssign (pointer)
+; AOP_STK for _strcpy_to_1_1
+ ld l,-2(ix)
+ ld h,-1(ix)
+ ld (hl),c
+
+ want to optimise down to:
+ ld a,(de)
+ or a,a
+ jp z,00103$
+ ld (bc),a
+
+ So genIfx where IC_COND has size of 1 and is a constant.
+*/
+
/** Pack registers for acc use.
When the result of this operation is small and short lived it may
be able to be stored in the accumulator.
- Note that the 'A preserving' list is currently emperical :)e
+ Note that the 'A preserving' list is currently emperical :)
*/
static void
packRegsForAccUse2 (iCode * ic)
ic->op != EQ_OP &&
ic->op != CAST &&
1)
- return;
+ {
+ D (D_ACCUSE2, (" + Dropping as not a 'good' source command\n"));
+ return;
+ }
/* if + or - then it has to be one byte result.
MLH: Ok.
*/
if ((ic->op == '+' || ic->op == '-')
&& getSize (operandType (IC_RESULT (ic))) > 1)
- return;
-
- /* if shift operation make sure right side is not a literal.
- MLH: depends.
- */
-#if 0
- 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;
-#endif
+ {
+ D (D_ACCUSE2, (" + Dropping as it's a big + or -\n"));
+ return;
+ }
/* has only one definition */
if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
{
+ D (D_ACCUSE2, (" + Dropping as it has more than one definition\n"));
return;
}
if (!(uic = hTabItemWithKey (iCodehTab,
bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
{
+ D (D_ACCUSE2, (" + Dropping as usage does not follow first\n"));
return;
}
next = hTabItemWithKey (iCodehTab, setBit);
if (scan->next == next)
{
+ D (D_ACCUSE2_VERBOSE, (" ! Is next in line\n"));
+
bitVectUnSetBit (uses, setBit);
/* Still contigous. */
if (!opPreservesA (ic, next))
{
+ D (D_ACCUSE2, (" + Dropping as operation doesn't preserve A\n"));
return;
}
+ D (D_ACCUSE2_VERBOSE, (" ! Preserves A, so continue scanning\n"));
scan = next;
}
+ else if (scan->next == NULL && bitVectnBitsOn (uses) == 1 && next != NULL)
+ {
+ if (next->prev == NULL)
+ {
+ if (!opPreservesA (ic, next))
+ {
+ D (D_ACCUSE2, (" + Dropping as operation doesn't preserve A #2\n"));
+ return;
+ }
+ bitVectUnSetBit (uses, setBit);
+ scan = next;
+ }
+ else
+ {
+ D (D_ACCUSE2, (" + Dropping as last in list and next doesn't start a block\n"));
+ return;
+ }
+ }
+ else if (scan->next == NULL)
+ {
+ D (D_ACCUSE2, (" + Dropping as hit the end of the list\n"));
+ D (D_ACCUSE2, (" + Next in htab: %p\n", next));
+ return;
+ }
else
{
- return;
+ if (opIgnoresA (ic, scan->next))
+ {
+ /* Safe for now. */
+ scan = scan->next;
+ D (D_ACCUSE2_VERBOSE, (" ! Op ignores A, so continue scanning\n"));
+ }
+ else
+ {
+ D (D_ACCUSE2, (" + Dropping as parts are not consecuitive and intermediate might use A\n"));
+ return;
+ }
}
}
while (!bitVectIsZero (uses));
+
OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_A;
return;
}
ic->op == '^') &&
isBitwiseOptimizable (ic))) &&
ic->next && ic->next->op == IFX &&
+ bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 &&
isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
{
#endif
/* if pointer set & left has a size more than
one and right is not in far space */
- if (POINTER_SET (ic) &&
- /* MLH: no such thing.
- !isOperandInFarSpace(IC_RIGHT(ic)) && */
+ if (!DISABLE_PACK_ONE_USE &&
+ POINTER_SET (ic) &&
+ /* MLH: no such thing.
+ !isOperandInFarSpace(IC_RIGHT(ic)) && */
!OP_SYMBOL (IC_RESULT (ic))->remat &&
!IS_OP_RUONLY (IC_RIGHT (ic)) &&
getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
packRegsForAccUse2 (ic);
}
#endif
- joinPushes (ic);
}
}
D (D_ALLOC, ("\n-> z80_assignRegisters: entered.\n"));
- setToNull ((void *) &funcrUsed);
- stackExtend = dataExtend = 0;
+ setToNull ((void *) &_G.funcrUsed);
+ _G.stackExtend = _G.dataExtend = 0;
if (IS_GB)
{
/* DE is required for the code gen. */
- _nRegs = GBZ80_MAX_REGS;
+ _G.nRegs = GBZ80_MAX_REGS;
regsZ80 = _gbz80_regs;
}
else
{
- _nRegs = Z80_MAX_REGS;
+ _G.nRegs = Z80_MAX_REGS;
regsZ80 = _z80_regs;
}
serialRegAssign (ebbs, count);
/* if stack was extended then tell the user */
- if (stackExtend)
+ if (_G.stackExtend)
{
/* werror(W_TOOMANY_SPILS,"stack", */
-/* stackExtend,currFunc->name,""); */
- stackExtend = 0;
+/* _G.stackExtend,currFunc->name,""); */
+ _G.stackExtend = 0;
}
- if (dataExtend)
+ if (_G.dataExtend)
{
/* werror(W_TOOMANY_SPILS,"data space", */
-/* dataExtend,currFunc->name,""); */
- dataExtend = 0;
+/* _G.dataExtend,currFunc->name,""); */
+ _G.dataExtend = 0;
}
if (options.dump_rassgn)
genZ80Code (ic);
/* free up any stackSpil locations allocated */
- applyToSet (stackSpil, deallocStackSpil);
- slocNum = 0;
- setToNull ((void **) &stackSpil);
- setToNull ((void **) &spiltSet);
+ applyToSet (_G.stackSpil, deallocStackSpil);
+ _G.slocNum = 0;
+ setToNull ((void **) &_G.stackSpil);
+ setToNull ((void **) &_G.spiltSet);
/* mark all registers as free */
freeAllRegs ();