+static iCode *
+packRegsForIYUse (iCode * lic, operand * op, eBBlock * ebp)
+{
+ int i, key;
+ symbol *sym;
+ iCode *ic, *dic;
+ bitVect *uses;
+
+ D (D_PACK_IY, ("Checking IY on %p lic key %u first def %u line %u:\n", OP_SYMBOL(op), lic->key, bitVectFirstBit(OP_DEFS(op)), lic->lineno));
+ if (D_PACK_IY)
+ piCode(lic, NULL);
+
+ 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;
+ }
+
+ if (getSize (operandType (op)) != 2)
+ {
+ D (D_ACCUSE2, (" + Dropping as operation has size is too big\n"));
+ return FALSE;
+ }
+
+ /* 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 (D_PACK_IY)
+ piCode(ic, NULL);
+
+ if (ic->op == PCALL ||
+ ic->op == CALL ||
+ ic->op == JUMPTABLE
+ )
+ return NULL;
+
+ if (SKIP_IC2(ic))
+ continue;
+
+ /* Be pessamistic. */
+ if (ic->op == IFX)
+ return NULL;
+
+ D (D_PACK_IY, (" op: %u uses %u result: %d left: %d right: %d\n", ic->op, bitVectBitValue(uses, ic->key),
+ IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) ? isOperandInDirSpace(IC_RESULT(ic)) : -1,
+ IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) ? isOperandInDirSpace(IC_LEFT(ic)) : -1,
+ IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) ? isOperandInDirSpace(IC_RIGHT(ic)) : -1
+ ));
+
+ if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
+ isOperandInDirSpace(IC_RESULT(ic)))
+ return NULL;
+
+ if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) &&
+ isOperandInDirSpace(IC_RIGHT(ic)))
+ return NULL;
+
+ if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) &&
+ isOperandInDirSpace(IC_LEFT(ic)))
+ return NULL;
+
+ /* Only certain rules will work against IY. Check if this iCode uses
+ this symbol. */
+ if (bitVectBitValue(uses, ic->key) != 0)
+ {
+ 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
+ {
+ /* This iCode doesn't use the sym. See if this iCode preserves IY.
+ */
+ continue;
+ }
+
+ /* By default give up */
+ return NULL;
+ }
+
+ D (D_PACK_IY, ("Succeeded IY!\n"));
+
+ 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 * uic)
+{
+ if (uic->op == IFX)
+ {
+ /* 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)
+ {
+ 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)
+ {
+ D (D_ACCUSE2, (" + Dropping as operation has only one operand\n"));
+ return FALSE;
+ }
+
+ /* 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;
+ }
+
+
+ /* Disabled all of the old rules as they weren't verified and have
+ caused at least one problem.
+ */
+ return FALSE;
+}
+
+/** Returns true if this operand preserves the value of A.
+ */
+static bool
+opIgnoresA (iCode * ic, iCode * uic)
+{
+ /* 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) ulFromVal (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;
+ }
+ }
+ 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;
+}
+
+
+/* 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.
+*/
+