CS_DelEntry (S, I+1);
/* Remember, we had changes */
- ++Changes;
+ ++Changes;
} else if ((BC == BC_EQ && E->Num == 0) ||
(BC == BC_NE && E->Num != 0) ||
/* Check which sort of load or transfer it is */
unsigned R;
switch (E->OPC) {
- case OP65_DEA:
- case OP65_INA:
- case OP65_LDA:
+ case OP65_DEA:
+ case OP65_INA:
+ case OP65_LDA:
case OP65_TXA:
case OP65_TYA: R = REG_A; break;
- case OP65_DEX:
- case OP65_INX:
- case OP65_LDX:
+ case OP65_DEX:
+ case OP65_INX:
+ case OP65_LDX:
case OP65_TAX: R = REG_X; break;
- case OP65_DEY:
- case OP65_INY:
+ case OP65_DEY:
+ case OP65_INY:
case OP65_LDY:
case OP65_TAY: R = REG_Y; break;
default: goto NextEntry; /* OOPS */
if ((GetRegInfo (S, I+1, R) & R) == 0) {
/* Register value is not used, remove the load */
- CS_DelEntry (S, I);
+ CS_DelEntry (S, I);
- /* Remember, we had changes. Account the deleted entry in I. */
- ++Changes;
- --I;
+ /* Remember, we had changes. Account the deleted entry in I. */
+ ++Changes;
+ --I;
}
}
}
break;
- case OP65_ADC:
case OP65_ASL:
case OP65_EOR:
case OP65_LSR:
- case OP65_SBC:
if (RegValIsKnown (Out->RegA)) {
/* Accu op zp with known contents */
Arg = MakeHexArg (Out->RegA);
}
break;
+ case OP65_ADC:
+ case OP65_SBC:
+ /* If this is an operation with an immediate operand of zero,
+ * and the register is zero, the operation won't give us any
+ * results we don't already have (including the flags), so
+ * remove it. Something like this is generated as a result of
+ * a compare where parts of the values are known to be zero.
+ */
+ if (In->RegA == 0 && CE_IsKnownImm (E, 0x00)) {
+ /* 0-0 or 0+0 -> remove */
+ CS_DelEntry (S, I);
+ ++Changes;
+ } else if (RegValIsKnown (Out->RegA)) {
+ /* Accu op zp with known contents */
+ Arg = MakeHexArg (Out->RegA);
+ }
+ break;
+
case OP65_AND:
if (CE_IsKnownImm (E, 0xFF)) {
/* AND with 0xFF, remove */
+/*****************************************************************************/
+/* Optimize indirect loads */
+/*****************************************************************************/
+
+
+
+unsigned OptIndLoads1 (CodeSeg* S)
+/* Change
+ *
+ * lda (zp),y
+ *
+ * into
+ *
+ * lda (zp,x)
+ *
+ * provided that x and y are both zero.
+ */
+{
+ unsigned Changes = 0;
+ unsigned I;
+
+ /* Generate register info for this step */
+ CS_GenRegInfo (S);
+
+ /* Walk over the entries */
+ I = 0;
+ while (I < CS_GetEntryCount (S)) {
+
+ /* Get next entry */
+ CodeEntry* E = CS_GetEntry (S, I);
+
+ /* Check if it's what we're looking for */
+ if (E->OPC == OP65_LDA &&
+ E->AM == AM65_ZP_INDY &&
+ E->RI->In.RegY == 0 &&
+ E->RI->In.RegX == 0) {
+
+ /* Replace by the same insn with other addressing mode */
+ CodeEntry* X = NewCodeEntry (E->OPC, AM65_ZPX_IND, E->Arg, 0, E->LI);
+ CS_InsertEntry (S, X, I+1);
+
+ /* Remove the old insn */
+ CS_DelEntry (S, I);
+ ++Changes;
+ }
+
+ /* Next entry */
+ ++I;
+
+ }
+
+ /* Free register info */
+ CS_FreeRegInfo (S);
+
+ /* Return the number of changes made */
+ return Changes;
+}
+
+
+
+unsigned OptIndLoads2 (CodeSeg* S)
+/* Change
+ *
+ * lda (zp,x)
+ *
+ * into
+ *
+ * lda (zp),y
+ *
+ * provided that x and y are both zero.
+ */
+{
+ unsigned Changes = 0;
+ unsigned I;
+
+ /* Generate register info for this step */
+ CS_GenRegInfo (S);
+
+ /* Walk over the entries */
+ I = 0;
+ while (I < CS_GetEntryCount (S)) {
+
+ /* Get next entry */
+ CodeEntry* E = CS_GetEntry (S, I);
+
+ /* Check if it's what we're looking for */
+ if (E->OPC == OP65_LDA &&
+ E->AM == AM65_ZPX_IND &&
+ E->RI->In.RegY == 0 &&
+ E->RI->In.RegX == 0) {
+
+ /* Replace by the same insn with other addressing mode */
+ CodeEntry* X = NewCodeEntry (E->OPC, AM65_ZP_INDY, E->Arg, 0, E->LI);
+ CS_InsertEntry (S, X, I+1);
+
+ /* Remove the old insn */
+ CS_DelEntry (S, I);
+ ++Changes;
+ }
+
+ /* Next entry */
+ ++I;
+
+ }
+
+ /* Free register info */
+ CS_FreeRegInfo (S);
+
+ /* Return the number of changes made */
+ return Changes;
+}
+
+
+