LI_DIRECT = 0x01, /* Direct op may be used */
LI_RELOAD_Y = 0x02, /* Reload index register Y */
LI_REMOVE = 0x04, /* Load may be removed */
+ LI_DUP_LOAD = 0x08, /* Duplicate load */
} LI_FLAGS;
/* Structure that tells us how to load the lhs values */
RI = &LI->X;
} else if (E->Chg & REG_Y) {
RI = &LI->Y;
- }
+ }
CHECK (RI != 0);
+ /* If we had a load or xfer op before, this is a duplicate load which
+ * can cause problems if it encountered between the pushax and the op,
+ * so remember it.
+ */
+ if (RI->LoadIndex >= 0 || RI->XferIndex >= 0) {
+ RI->Flags |= LI_DUP_LOAD;
+ }
+
/* Remember the load */
RI->LoadIndex = I;
RI->XferIndex = -1;
default: Internal ("Unknown XFR insn in TrackLoads");
}
+ /* If we had a load or xfer op before, this is a duplicate load which
+ * can cause problems if it encountered between the pushax and the op,
+ * so remember it.
+ */
+ if (Tgt->LoadIndex >= 0 || Tgt->XferIndex >= 0) {
+ Tgt->Flags |= LI_DUP_LOAD;
+ }
+
/* Transfer the data */
Tgt->LoadIndex = Src->LoadIndex;
Tgt->XferIndex = I;
} else if (CE_IsCallTo (E, "ldaxysp") && RegValIsKnown (E->RI->In.RegY)) {
+ /* If we had a load or xfer op before, this is a duplicate load which
+ * can cause problems if it encountered between the pushax and the op,
+ * so remember it for both registers involved.
+ */
+ if (LI->A.LoadIndex >= 0 || LI->A.XferIndex >= 0) {
+ LI->A.Flags |= LI_DUP_LOAD;
+ }
+ if (LI->X.LoadIndex >= 0 || LI->X.XferIndex >= 0) {
+ LI->X.Flags |= LI_DUP_LOAD;
+ }
+
/* Both registers set, Y changed */
LI->A.LoadIndex = I;
LI->A.XferIndex = -1;
"asrax3",
"asrax4",
"bnegax",
+ "decax1",
+ "decax2",
+ "decax3",
+ "decax4",
+ "decax5",
+ "decax6",
+ "decax7",
+ "decax8",
+ "decaxy",
+ "incax1",
+ "incax2",
+ "incax3",
+ "incax4",
+ "incax5",
+ "incax6",
+ "incax7",
+ "incax8",
+ "incaxy",
"ldaxidx",
"ldaxysp",
"negax",
}
}
}
+ if ((D->Rhs.A.Flags | D->Rhs.X.Flags) & LI_DUP_LOAD) {
+ /* Cannot optimize */
+ return 0;
+ }
/* Determine the zero page locations to use */
if ((D->UsedRegs & REG_PTR1) == REG_NONE) {
{
unsigned Changes = 0; /* Number of changes in one run */
StackOpData Data;
- unsigned I;
+ int I;
+ int OldEntryCount; /* Old number of entries */
enum {
Initialize,
} State = Initialize;
- /* Generate register info */
- CS_GenRegInfo (S);
-
/* Remember the code segment in the info struct */
Data.Code = S;
* intermediate code for zero page use.
*/
I = 0;
- while (I < CS_GetEntryCount (S)) {
+ while (I < (int)CS_GetEntryCount (S)) {
/* Get the next entry */
CodeEntry* E = CS_GetEntry (S, I);
Data.OpEntry = CS_GetEntry (S, Data.OpIndex);
Data.NextEntry = CS_GetNextEntry (S, Data.OpIndex);
+ /* Remember the current number of code lines */
+ OldEntryCount = CS_GetEntryCount (S);
+
/* Adjust stack offsets to account for the upcoming removal */
AdjustStackOffset (&Data, 2);
/* Call the optimizer function */
Changes += Data.OptFunc->Func (&Data);
+ /* Since the function may have added or deleted entries,
+ * correct the index.
+ */
+ I += CS_GetEntryCount (S) - OldEntryCount;
+
/* Regenerate register info */
CS_GenRegInfo (S);
/* Done */
State = Initialize;
- break;
+ continue;
}
}
- /* Free the register info */
- CS_FreeRegInfo (S);
-
/* Return the number of changes made */
return Changes;
}