{ "bc", "c", "b" },
{ "de", "e", "d" },
{ "hl", "l", "h" },
- { "iy", "iy.l?", "iy.h?" },
- { "ix", "ix.l?", "ix.h?" }
+ { "iy", "iyl", "iyh" },
+ { "ix", "ixl", "ixh" }
};
// PENDING
return _pairs[_getTempPairId()].name;
}
+static PAIR_ID
+getFreePairId (iCode *ic)
+{
+ if (!(bitVectBitValue (ic->rMask, B_IDX) || bitVectBitValue(ic->rMask, C_IDX)))
+ {
+ return PAIR_BC;
+ }
+ else if (IS_Z80 && !(bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX)))
+ {
+ return PAIR_DE;
+ }
+ else
+ {
+ return PAIR_INVALID;
+ }
+}
+
static void
_tidyUp (char *buf)
{
}
else if (aop->type == AOP_STR || aop->type == AOP_HLREG)
{
- switch (*aop->aopu.aop_str[0])
- {
- case 'c':
- return "bc";
- break;
- case 'e':
- return "de";
- break;
- case 'l':
- return "hl";
- break;
- }
+ int i;
+ for (i = 0; i < NUM_PAIRS; i++)
+ {
+ if (strcmp(aop->aopu.aop_str[0], _pairs[i].l) == 0)
+ {
+ return _pairs[i].name;
+ }
+ }
}
wassertl (0, "Tried to get the pair name of something that isn't a pair");
return NULL;
return PAIR_HL;
}
}
- if (aop->type == AOP_STR || aop->type == AOP_HLREG)
+ else if (aop->type == AOP_STR || aop->type == AOP_HLREG)
{
- if (!strcmp (aop->aopu.aop_str[0], "c") && !strcmp (aop->aopu.aop_str[1], "b"))
- {
- return PAIR_BC;
- }
- if (!strcmp (aop->aopu.aop_str[0], "e") && !strcmp (aop->aopu.aop_str[1], "d"))
- {
- return PAIR_DE;
- }
- if (!strcmp (aop->aopu.aop_str[0], "l") && !strcmp (aop->aopu.aop_str[1], "h"))
- {
- return PAIR_HL;
- }
- }
+ int i;
+ for (i = 0; i < NUM_PAIRS; i++)
+ {
+ if (!strcmp (aop->aopu.aop_str[0], _pairs[i].l) && !strcmp (aop->aopu.aop_str[1], _pairs[i].h))
+ {
+ return i;
+ }
+ }
+ }
}
return PAIR_INVALID;
}
return;
}
+ if (sym->ruonly)
+ {
+ int i;
+ aop = op->aop = sym->aop = newAsmop (AOP_STR);
+ aop->size = getSize (sym->type);
+ for (i = 0; i < 4; i++)
+ aop->aopu.aop_str[i] = _fReturn[i];
+ return;
+ }
+
if (sym->accuse)
{
if (sym->accuse == ACCUSE_A)
aop->aopu.aop_str[0] = _pairs[PAIR_HL].l;
aop->aopu.aop_str[1] = _pairs[PAIR_HL].h;
}
+ else if (sym->accuse == ACCUSE_IY)
+ {
+ aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
+ aop->size = getSize (sym->type);
+ wassertl(aop->size <= 2, "Internal error: Caching in IY, but too big to fit in IY");
+ aop->aopu.aop_str[0] = _pairs[PAIR_IY].l;
+ aop->aopu.aop_str[1] = _pairs[PAIR_IY].h;
+ }
else
{
wassertl (0, "Marked as being allocated into A or HL but is actually in neither");
return;
}
- if (sym->ruonly)
- {
- int i;
- aop = op->aop = sym->aop = newAsmop (AOP_STR);
- aop->size = getSize (sym->type);
- for (i = 0; i < 4; i++)
- aop->aopu.aop_str[i] = _fReturn[i];
- return;
- }
-
/* else spill location */
sym->aop = op->aop = aop =
aopForSym (ic, sym->usl.spillLoc, result, requires_a);
if (isLitWord (aop)) {
fetchLitPair (pairId, aop, offset);
}
- else {
+ else
+ {
+ if (getPairId (aop) == pairId)
+ {
+ /* Do nothing */
+ }
/* we need to get it byte by byte */
- if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
+ else if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
aopGet (aop, offset, FALSE);
switch (aop->size - offset) {
case 1:
emit2("ld %s,!zero", _pairs[pairId].h);
}
}
+ else if (pairId == PAIR_IY)
+ {
+ if (isPair (aop))
+ {
+ emit2 ("push %s", _pairs[getPairId(aop)].name);
+ emit2 ("pop iy");
+ }
+ else
+ {
+ _push (PAIR_HL);
+ /* Can't load into parts, so load into HL then exchange. */
+ emit2 ("ld %s,%s", _pairs[PAIR_HL].l, aopGet (aop, offset, FALSE));
+ emit2 ("ld %s,%s", _pairs[PAIR_HL].h, aopGet (aop, offset + 1, FALSE));
+ emit2 ("push hl");
+ emit2 ("pop iy");
+ _pop (PAIR_HL);
+ }
+ }
else {
emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
}
else
- emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
+ {
+ emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
+ }
}
break;
emit2 ("ld h,%s", aopGet (AOP (left), MSB16, FALSE));
emit2 ("ld l,a");
}
+ else if ( getPairId ( AOP (result)) == PAIR_IY)
+ {
+ PAIR_ID id = getPairId (AOP (left));
+ if (id != PAIR_INVALID)
+ {
+ emit2("push %s", _pairs[id].name);
+ emit2("pop iy");
+ }
+ else
+ {
+ /* PENDING */
+ emitDebug("Error");
+ }
+ }
else
{
movLeft2Result (left, offl, result, offr, sign);
}
if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
{
- fetchPair (resultId, AOP (IC_RIGHT (ic)));
- emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
- return TRUE;
+ if (getPairId (AOP (IC_LEFT (ic))) == PAIR_HL)
+ {
+ PAIR_ID freep = getFreePairId (ic);
+ if (freep != PAIR_INVALID)
+ {
+ fetchPair (freep, AOP (IC_RIGHT (ic)));
+ emit2 ("add hl,%s", _pairs[freep].name);
+ return TRUE;
+ }
+ }
+ else
+ {
+ fetchPair (resultId, AOP (IC_RIGHT (ic)));
+ emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
+ return TRUE;
+ }
}
if (icount > 5)
return FALSE;
return TRUE;
}
+ if (IS_Z80 && isLitWord (AOP (IC_LEFT (ic))) && size == 2)
+ {
+ fetchLitPair (PAIR_HL, AOP (IC_LEFT (ic)), icount);
+ commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
+ return TRUE;
+ }
+
/* if the literal value of the right hand side
is greater than 4 then it is not worth it */
if (icount > 4)
}
}
- if (isPair (AOP (IC_RIGHT (ic))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
+ if ((isPair (AOP (IC_RIGHT (ic))) || isPair (AOP (IC_LEFT (ic)))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
{
/* Fetch into HL then do the add */
+ PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
+ PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
+
spillPair (PAIR_HL);
- fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
- emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
- goto release;
+
+ if (left == PAIR_HL && right != PAIR_INVALID)
+ {
+ emit2 ("add hl,%s", _pairs[right].name);
+ goto release;
+ }
+ else if (right == PAIR_HL && left != PAIR_INVALID)
+ {
+ emit2 ("add hl,%s", _pairs[left].name);
+ goto release;
+ }
+ else if (right != PAIR_INVALID)
+ {
+ fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
+ emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
+ goto release;
+ }
+ else if (left != PAIR_INVALID)
+ {
+ fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
+ emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
+ goto release;
+ }
+ else
+ {
+ /* Can't do it */
+ }
}
if (isPair (AOP (IC_RIGHT (ic))) && AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
{
inst = "nc";
}
+ else if (!strcmp (jval, "m"))
+ {
+ inst = "m";
+ }
+ else if (!strcmp (jval, "p"))
+ {
+ inst = "p";
+ }
else
{
/* The buffer contains the bit on A that we should test */
{
inst = "c";
}
+ else if (!strcmp (jval, "m"))
+ {
+ inst = "p";
+ }
+ else if (!strcmp (jval, "p"))
+ {
+ inst = "m";
+ }
else
{
/* The buffer contains the bit on A that we should test */
else if (!strcmp (jval, "nc"))
{
}
+ else if (!strcmp (jval, "m"))
+ {
+ }
+ else if (!strcmp (jval, "p"))
+ {
+ }
else
{
emit2 ("bit %s,a", jval);
}
#endif
-/** Generic compare for > or <
- */
-static void
-genCmp (operand * left, operand * right,
- operand * result, iCode * ifx, int sign)
-{
- int size, offset = 0;
- unsigned long lit = 0L;
- bool swap_sense = FALSE;
-
- /* if left & right are bit variables */
- if (AOP_TYPE (left) == AOP_CRY &&
- AOP_TYPE (right) == AOP_CRY)
- {
- /* Cant happen on the Z80 */
- wassertl (0, "Tried to compare two bits");
- }
- else
- {
- /* subtract right from left if at the
- end the carry flag is set then we know that
- left is greater than right */
- size = max (AOP_SIZE (left), AOP_SIZE (right));
-
+#if OLD
/* if unsigned char cmp with lit, just compare */
if ((size == 1) &&
(AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
}
}
}
+#endif
+
+/** Generic compare for > or <
+ */
+static void
+genCmp (operand * left, operand * right,
+ operand * result, iCode * ifx, int sign)
+{
+ int size, offset = 0;
+ unsigned long lit = 0L;
+ bool swap_sense = FALSE;
+
+ /* if left & right are bit variables */
+ if (AOP_TYPE (left) == AOP_CRY &&
+ AOP_TYPE (right) == AOP_CRY)
+ {
+ /* Cant happen on the Z80 */
+ wassertl (0, "Tried to compare two bits");
+ }
+ else
+ {
+ /* Do a long subtract of right from left. */
+ size = max (AOP_SIZE (left), AOP_SIZE (right));
+
+ if (size > 1 && IS_GB && requiresHL(AOP(right)) && requiresHL(AOP(left)))
+ {
+ // On the Gameboy we can't afford to adjust HL as it may trash the carry.
+ // Pull left into DE and right into HL
+ aopGet (AOP(left), LSB, FALSE);
+ emit2 ("ld d,h");
+ emit2 ("ld e,l");
+ aopGet (AOP(right), LSB, FALSE);
+
+ while (size--)
+ {
+ emit2 ("ld a,(de)");
+ emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc");
+
+ if (size != 0)
+ {
+ emit2 ("inc hl");
+ emit2 ("inc de");
+ }
+ offset++;
+ }
+ spillPair (PAIR_HL);
+ goto release;
+ }
+
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+ /* optimize if(x < 0) or if(x >= 0) */
+ if (lit == 0)
+ {
+ if (!sign)
+ {
+ /* No sign so it's always false */
+ _clearCarry();
+ }
+ else
+ {
+ /* Just load in the top most bit */
+ _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
+ if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
+ {
+ genIfxJump (ifx, "7");
+ return;
+ }
+ else
+ {
+ if (!sign)
+ {
+ emit2 ("rlc a");
+ }
+ if (ifx)
+ {
+ genIfxJump (ifx, swap_sense ? "c" : "nc");
+ return;
+ }
+ }
+ }
+ goto release;
+ }
+ }
+
+ while (size--)
+ {
+ _moveA (aopGet (AOP (left), offset, FALSE));
+ /* Subtract through, propagating the carry */
+ emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE));
+ offset++;
+ }
+ }
release:
if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
{
+ if (sign)
+ {
+ /* Shift the sign bit up into carry */
+ emit2 ("rlca");
+ }
outBitCLong (result, swap_sense);
}
else
ifx conditional branch then generate
code a little differently */
if (ifx)
- genIfxJump (ifx, swap_sense ? "nc" : "c");
+ {
+ if (IS_GB)
+ {
+ emit2 ("rlca");
+ genIfxJump (ifx, swap_sense ? "nc" : "c");
+ }
+ else
+ {
+ genIfxJump (ifx, swap_sense ? "p" : "m");
+ }
+ }
else
- outBitCLong (result, swap_sense);
+ {
+ if (sign)
+ {
+ /* Shift the sign bit up into carry */
+ emit2 ("rlca");
+ }
+ outBitCLong (result, swap_sense);
+ }
/* leave the result in acc */
}
}
else
{
tlbl = newiTempLabel (NULL);
+ emitDebug(";1");
gencjneshort (left, right, tlbl);
if (IC_TRUE (ifx))
{
+ emitDebug(";2");
emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
emitLabel (tlbl->key + 100);
}
{
/* PENDING: do this better */
symbol *lbl = newiTempLabel (NULL);
+ emitDebug(";3");
emit2 ("!shortjp !tlabel", lbl->key + 100);
emitLabel (tlbl->key + 100);
emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
}
else
{
+ emitDebug(";4");
+
gencjne (left, right, newiTempLabel (NULL));
if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
{
}
if (ifx)
{
+ emitDebug(";5");
genIfxJump (ifx, "a");
goto release;
}
then put the result in place */
if (AOP_TYPE (result) != AOP_CRY)
{
+ emitDebug(";6");
outAcc (result);
}
/* leave the result in acc */
aopOp (left, ic, FALSE, FALSE);
aopOp (result, ic, FALSE, FALSE);
- if (isPair (AOP (left)) && AOP_SIZE (result) == 1)
+ size = AOP_SIZE (result);
+
+ if (isPair (AOP (left)) && size == 1)
{
/* Just do it */
if (isPtrPair (AOP (left)))
goto release;
}
+ if ( getPairId( AOP (left)) == PAIR_IY)
+ {
+ /* Just do it */
+ offset = 0;
+ while (size--)
+ {
+ char at[20];
+ tsprintf (at, "!*iyx", offset);
+ aopPut (AOP (result), at, offset);
+ offset++;
+ }
+ goto release;
+ }
+
/* For now we always load into IY */
/* if this is remateriazable */
fetchPair (pair, AOP (left));
- /* so iy now contains the address */
freeAsmop (left, NULL, ic);
/* if bit then unpack */
{
wassert (0);
}
+ else if ( getPairId( AOP (result)) == PAIR_HL)
+ {
+ wassertl (size == 2, "HL must be of size 2");
+ emit2 ("ld a,!*hl");
+ emit2 ("inc hl");
+ emit2 ("ld h,!*hl");
+ emit2 ("ld l,a");
+ }
else
{
size = AOP_SIZE (result);
bool
isRegOrLit (asmop * aop)
{
- if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
+ if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD || aop->type == AOP_HLREG)
return TRUE;
return FALSE;
}
int size, offset;
sym_link *retype = getSpec (operandType (right));
PAIR_ID pairId = PAIR_HL;
-
+
aopOp (result, ic, FALSE, FALSE);
aopOp (right, ic, FALSE, FALSE);
if (IS_GB)
pairId = PAIR_DE;
+ size = AOP_SIZE (right);
+
/* Handle the exceptions first */
- if (isPair (AOP (result)) && (AOP_SIZE (right) == 1))
+ if (isPair (AOP (result)) && size == 1)
{
/* Just do it */
const char *l = aopGet (AOP (right), 0, FALSE);
}
goto release;
}
+
+ if ( getPairId( AOP (result)) == PAIR_IY)
+ {
+ /* Just do it */
+ const char *l = aopGet (AOP (right), 0, FALSE);
+
+ offset = 0;
+ while (size--)
+ {
+ if (canAssignToPtr (l))
+ {
+ emit2 ("ld !*iyx,%s", offset, aopGet( AOP(right), offset, FALSE));
+ }
+ else
+ {
+ _moveA (aopGet (AOP (right), offset, FALSE));
+ emit2 ("ld !*iyx,a", offset);
+ }
+ offset++;
+ }
+ goto release;
+ }
/* if the operand is already in dptr
then we do nothing else we move the value to dptr */
}
else
{
- size = AOP_SIZE (right);
offset = 0;
while (size--)
offset = 0;
if (AOP_TYPE (right) == AOP_LIT)
+ {
lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+ }
+
if (isPair (AOP (result)))
{
fetchPair (getPairId (AOP (result)), AOP (right));
offset++;
}
}
+ else if (size == 2 && AOP_TYPE (right) == AOP_IY)
+ {
+ emit2 ("ld hl,(%s)", AOP (right)->aopu.aop_dir);
+ aopPut (AOP (result), "l", LSB);
+ aopPut (AOP (result), "h", MSB16);
+ }
else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
{
/* Special case. Load into a and d, then load out. */
while (size--)
{
/* PENDING: do this check better */
- if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
+ if (IS_GB && requiresHL (AOP (right)) && requiresHL (AOP (result)))
{
_moveA (aopGet (AOP (right), offset, FALSE));
aopPut (AOP (result), "a", offset);
*/
#include "z80.h"
+#include "SDCCicode.h"
/* Flags to turn off optimisations.
*/
{
DISABLE_PACK_ACC = 0,
DISABLE_PACK_ASSIGN = 0,
- /* Pack for one use is quite broken. */
- DISABLE_PACK_ONE_USE = 1,
+ DISABLE_PACK_ONE_USE = 0,
DISABLE_PACK_HL = 0,
};
D_ALLOC2 = 0,
D_ACCUSE2 = 0,
D_ACCUSE2_VERBOSE = 0,
- D_HLUSE = 0
+ D_HLUSE = 0,
+ D_HLUSE2 = 0,
+ D_HLUSE2_VERBOSE = 0
};
#if 1
for (sym = setFirstItem (itmpStack); sym;
sym = setNextItem (itmpStack))
{
+ if (bitVectBitValue(sym->clashes,fsym->key))
+ return 0;
+#if 0
// if sym starts before (or on) our end point
// and ends after (or on) our start point,
// it is an overlap.
{
return 0;
}
+#endif
}
return 1;
}
sym->regs[0] = ®sZ80[i];
regsZ80[i + 1].isFree = 0;
sym->regs[1] = ®sZ80[i + 1];
+ sym->regType = REG_PAIR;
+
if (currFunc)
{
currFunc->regsUsed =
return 0;
}
-#if 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;
- }
-#endif
-
/* find the definition of iTempNN scanning backwards if we find a
a use of the true symbol in before we find the definition then
we cannot */
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))
+ /* PENDING: Don't pack across function calls. */
+ if (dic->op == CALL || dic->op == PCALL)
{
dic = NULL;
break;
dic = NULL;
break;
}
-#if 0
- if (POINTER_SET (dic) &&
- IC_RESULT (dic)->key == IC_RESULT (ic)->key)
- {
- dic = NULL;
- break;
- }
-#endif
}
if (!dic)
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))) ||
/* only upto 2 bytes since we cannot predict
the usage of b, & acc */
- if (getSize (operandType (op)) > 2 &&
- ic->op != RETURN &&
+ if (getSize (operandType (op)) > 2)
+ return NULL;
+
+ if (ic->op != RETURN &&
ic->op != SEND)
return NULL;
OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_SCRATCH;
}
+static iCode *
+packRegsForHLUse3 (iCode * lic, operand * op, eBBlock * ebp)
+{
+ int i, key;
+ symbol *sym;
+ iCode *ic, *dic;
+ bool isFirst = TRUE;
+
+#if 0
+ printf("Checking:\n");
+ piCode(lic, NULL);
+#endif
+
+ if ( OP_SYMBOL(op)->accuse)
+ {
+ return NULL;
+ }
+
+ if (OP_SYMBOL(op)->remat)
+ {
+ return NULL;
+ }
+
+ /* Only defined once */
+ if (bitVectnBitsOn (OP_DEFS (op)) > 1)
+ return NULL;
+
+ if (getSize (operandType (op)) != 2)
+ return NULL;
+
+ /* And this is the definition */
+ if (bitVectFirstBit (OP_DEFS (op)) != lic->key)
+ return NULL;
+
+ /* first check if any overlapping liverange has already been
+ assigned to DPTR */
+ if (OP_SYMBOL(op)->clashes)
+ {
+ for (i = 0 ; i < OP_SYMBOL(op)->clashes->size ; i++ )
+ {
+ if (bitVectBitValue(OP_SYMBOL(op)->clashes,i))
+ {
+ sym = hTabItemWithKey(liveRanges,i);
+ if (sym->accuse == ACCUSE_SCRATCH)
+ {
+ return NULL;
+ }
+ }
+ }
+ }
+
+ /* Nothing else that clashes with this is using the scratch
+ register. Scan through all of the intermediate instructions and
+ see if any of them could nuke HL.
+ */
+ dic = ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom);
+
+ for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
+ ic = hTabNextItem(iCodeSeqhTab,&key))
+ {
+#if 0
+ piCode(ic, NULL);
+ printf("(op: %u)\n", ic->op);
+#endif
+ if (isFirst)
+ {
+ isFirst = FALSE;
+ if (ic->op == ADDRESS_OF)
+ continue;
+ if (POINTER_GET (ic))
+ continue;
+ }
+
+ /* Handle the non left/right/result ones first */
+ if (ic->op == IFX)
+ continue;
+ if (ic->op == JUMPTABLE)
+ return NULL;
+
+ if (SKIP_IC2(ic))
+ continue;
+
+ if (ic->op == IPUSH && isOperandEqual (op, IC_LEFT (ic)))
+ continue;
+
+ if ((ic->op == '=' && !POINTER_SET(ic)) ||
+ ic->op == UNARYMINUS ||
+ ic->op == '+' ||
+ ic->op == '-' ||
+ 0)
+ continue;
+
+ if (POINTER_GET (ic) && isOperandEqual (op, IC_LEFT (ic)))
+ continue;
+
+ if (IS_VALOP (IC_RIGHT (ic)) &&
+ (ic->op == EQ_OP ||
+ 0))
+ {
+ continue;
+ }
+
+ /* By default give up */
+ return NULL;
+ }
+
+#if 0
+ printf("Succeeded!\n");
+#endif
+ OP_SYMBOL (op)->accuse = ACCUSE_SCRATCH;
+
+ return dic;
+}
+
+static iCode *
+packRegsForIYUse (iCode * lic, operand * op, eBBlock * ebp)
+{
+ int i, key;
+ symbol *sym;
+ iCode *ic, *dic;
+ bitVect *uses;
+
+#if 0
+ printf("Checking IY on %p lic key %u first def %u:\n", OP_SYMBOL(op), lic->key, bitVectFirstBit(OP_DEFS(op)));
+ piCode(lic, NULL);
+#endif
+
+ if ( OP_SYMBOL(op)->accuse)
+ {
+ return NULL;
+ }
+
+ if (OP_SYMBOL(op)->remat)
+ {
+ return NULL;
+ }
+
+ /* Only defined once */
+ if (bitVectnBitsOn (OP_DEFS (op)) > 1)
+ return NULL;
+
+ /* And this is the definition */
+ if (bitVectFirstBit (OP_DEFS (op)) != lic->key)
+ return NULL;
+
+ /* first check if any overlapping liverange has already been
+ assigned to DPTR */
+ if (OP_SYMBOL(op)->clashes)
+ {
+ for (i = 0 ; i < OP_SYMBOL(op)->clashes->size ; i++ )
+ {
+ if (bitVectBitValue(OP_SYMBOL(op)->clashes,i))
+ {
+ sym = hTabItemWithKey(liveRanges,i);
+ if (sym->accuse == ACCUSE_IY)
+ {
+ return NULL;
+ }
+ }
+ }
+ }
+
+ /* Only a few instructions can load into IY */
+ if (lic->op != '=')
+ {
+ return NULL;
+ }
+
+ /* Nothing else that clashes with this is using the scratch
+ register. Scan through all of the intermediate instructions and
+ see if any of them could nuke HL.
+ */
+ dic = ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom);
+ uses = OP_USES(op);
+
+ for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
+ ic = hTabNextItem(iCodeSeqhTab,&key))
+ {
+#if 0
+ piCode(ic, NULL);
+ printf("(op: %u uses %u)\n", ic->op, bitVectBitValue(uses, ic->key));
+#endif
+
+ if (ic->op == PCALL ||
+ ic->op == CALL ||
+ ic->op == JUMPTABLE
+ )
+ return NULL;
+
+ if (SKIP_IC2(ic))
+ continue;
+
+ /* Only certain rules will work against IY. Check if this iCode uses
+ this symbol. */
+ if (bitVectBitValue(uses, ic->key) != 0)
+ {
+ if (ic->op == IFX)
+ return NULL;
+
+ if (ic->op == '=' &&
+ isOperandEqual(IC_RESULT(ic), op))
+ continue;
+
+ if (ic->op == GET_VALUE_AT_ADDRESS &&
+ isOperandEqual(IC_LEFT(ic), op))
+ continue;
+
+ if (isOperandEqual(IC_RESULT(ic), IC_LEFT(ic)) == FALSE)
+ return NULL;
+
+ if (IC_RIGHT (ic) && IS_VALOP (IC_RIGHT (ic)))
+ {
+ if (ic->op == '+' ||
+ ic->op == '-')
+ {
+ /* Only works if the constant is small */
+ if (operandLitValue (IC_RIGHT (ic)) < 4)
+ continue;
+ }
+ }
+
+ return NULL;
+ }
+ else
+ {
+ if (ic->op == IFX)
+ continue;
+
+ /* This iCode doesn't use the sym. See if this iCode preserves IY.
+ */
+ if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
+ isOperandInDirSpace(IC_RESULT(ic)))
+ return NULL;
+
+ if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) &&
+ isOperandInFarSpace(IC_RIGHT(ic)))
+ return NULL;
+
+ if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) &&
+ isOperandInFarSpace(IC_LEFT(ic)))
+ return NULL;
+
+ continue;
+ }
+
+ /* By default give up */
+ return NULL;
+ }
+
+#if 0
+ printf("Succeeded IY!\n");
+#endif
+ OP_SYMBOL (op)->accuse = ACCUSE_IY;
+
+ return dic;
+}
+
+/** Returns TRUE if this operation can use acc and if it preserves the value.
+ */
static bool
-opPreservesA (iCode * ic, iCode * uic)
+opPreservesA (iCode * uic)
{
if (uic->op == IFX)
{
return FALSE;
}
+/** Returns true if this operand preserves the value of A.
+ */
static bool
opIgnoresA (iCode * ic, iCode * uic)
{
return TRUE;
}
}
+ else if (uic->op == '=' && !POINTER_SET (uic))
+ {
+ /* If they are equal and get optimised out then things are OK. */
+ if (isOperandEqual (IC_RESULT (uic), IC_RIGHT (uic)))
+ {
+ /* Straight assign is OK. */
+ return TRUE;
+ }
+ }
return FALSE;
}
{
iCode *uic;
- D (D_ALLOC, ("packRegsForAccUse2: running on ic %p\n", ic));
+ D (D_ACCUSE2, ("packRegsForAccUse2: running on ic %p line %u\n", ic, ic->lineno));
/* Filter out all but those 'good' commands */
if (
!IS_BITWISE_OP (ic) &&
ic->op != '=' &&
ic->op != EQ_OP &&
+ ic->op != '<' &&
+ ic->op != '>' &&
ic->op != CAST &&
ic->op != GETHBIT &&
1)
bitVectUnSetBit (uses, setBit);
/* Still contigous. */
- if (!opPreservesA (ic, next))
+ if (!opPreservesA (next))
{
D (D_ACCUSE2, (" + Dropping as operation doesn't preserve A\n"));
return;
{
if (next->prev == NULL)
{
- if (!opPreservesA (ic, next))
+ if (!opPreservesA (next))
{
D (D_ACCUSE2, (" + Dropping as operation doesn't preserve A #2\n"));
return;
OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_A;
return;
}
-
- /* OLD CODE FOLLOWS */
- /* if it is a conditional branch then we definitely can
- MLH: Depends.
- */
-#if 0
- if (uic->op == IFX)
- goto accuse;
-
- /* MLH: Depends. */
- if (uic->op == JUMPTABLE)
- return;
-#endif
-
- /* if the usage is not is an assignment or an
- arithmetic / bitwise / shift operation then not.
- MLH: Pending: Invalid. Our pointer sets are always peechy.
- */
-#if 0
- if (POINTER_SET (uic) &&
- getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1)
- {
- printf ("e5 %u\n", getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)));
- return;
- }
-#endif
-
- printf ("1\n");
- if (uic->op != '=' &&
- !IS_ARITHMETIC_OP (uic) &&
- !IS_BITWISE_OP (uic) &&
- uic->op != LEFT_OP &&
- uic->op != RIGHT_OP)
- {
- printf ("e6\n");
- return;
- }
-
- /* 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;
-
-#if 0
- /* 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;
-#endif
-
-#if 0
- /* 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;
-#endif
-
- /* 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;
-
- /* 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;
- }
-
-/** 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)))))
- goto accuse;
-
- if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key &&
- (IS_ITEMP (IC_LEFT (uic)) ||
- (IS_TRUE_SYMOP (IC_LEFT (uic)))))
- goto accuse;
- return;
-accuse:
- printf ("acc ok!\n");
- OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_A;
}
/** Does some transformations to reduce register pressure.
packRegsForSupport (ic, ebp);
#endif
+ /* some cases the redundant moves can
+ can be eliminated for return statements */
+ if (ic->op == RETURN || ic->op == SEND)
+ {
+ packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+ }
+
/* if pointer set & left has a size more than
one and right is not in far space */
if (!DISABLE_PACK_ONE_USE &&
if (!DISABLE_PACK_HL && IS_ITEMP (IC_RESULT (ic)))
{
- packRegsForHLUse (ic);
+ if (IS_GB)
+ packRegsForHLUse (ic);
+ else
+ packRegsForHLUse3 (ic, IC_RESULT (ic), ebp);
+ }
+
+ if (!DISABLE_PACK_HL && IS_ITEMP (IC_RESULT (ic)) && IS_Z80)
+ {
+ packRegsForIYUse (ic, IC_RESULT (ic), ebp);
}
if (!DISABLE_PACK_ACC && IS_ITEMP (IC_RESULT (ic)) &&