/* */
/* */
/* */
-/* (C) 2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 2001-2002 Ullrich von Bassewitz */
+/* Wacholderweg 14 */
+/* D-70597 Stuttgart */
+/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
} else if ((E->Chg & REG_SREG_HI) != 0 && In->SRegHi >= 0) {
Out->SRegHi = (In->SRegHi << 1) & 0xFF;
}
+ } else if (E->AM == AM65_ZPX) {
+ /* Invalidates all ZP registers */
+ RC_InvalidateZP (Out);
}
break;
} else if ((E->Chg & REG_SREG_HI) != 0 && In->SRegHi >= 0) {
Out->SRegHi = (In->SRegHi - 1) & 0xFF;
}
+ } else if (E->AM == AM65_ZPX) {
+ /* Invalidates all ZP registers */
+ RC_InvalidateZP (Out);
}
break;
} else if ((E->Chg & REG_SREG_HI) != 0 && In->SRegHi >= 0) {
Out->SRegHi = (In->SRegHi + 1) & 0xFF;
}
+ } else if (E->AM == AM65_ZPX) {
+ /* Invalidates all ZP registers */
+ RC_InvalidateZP (Out);
}
break;
} else if (E->Chg & REG_SREG_HI) {
Out->SRegHi = (In->SRegHi >> 1) & 0xFF;
}
+ } else if (E->AM == AM65_ZPX) {
+ /* Invalidates all ZP registers */
+ RC_InvalidateZP (Out);
}
break;
} else if (E->Chg & REG_SREG_HI) {
Out->SRegHi = -1;
}
+ } else if (E->AM == AM65_ZPX) {
+ /* Invalidates all ZP registers */
+ RC_InvalidateZP (Out);
}
break;
} else if (E->Chg & REG_SREG_HI) {
Out->SRegHi = -1;
}
+ } else if (E->AM == AM65_ZPX) {
+ /* Invalidates all ZP registers */
+ RC_InvalidateZP (Out);
}
break;
} else if (E->Chg & REG_SREG_HI) {
Out->SRegHi = In->RegA;
}
+ } else if (E->AM == AM65_ZPX) {
+ /* Invalidates all ZP registers */
+ RC_InvalidateZP (Out);
}
break;
case OP65_STX:
if (E->AM == AM65_ZP) {
- if (E->Chg & REG_SREG_LO) {
- Out->SRegLo = In->RegX;
- } else if (E->Chg & REG_SREG_HI) {
- Out->SRegHi = In->RegX;
- }
+ if (E->Chg & REG_SREG_LO) {
+ Out->SRegLo = In->RegX;
+ } else if (E->Chg & REG_SREG_HI) {
+ Out->SRegHi = In->RegX;
+ }
+ } else if (E->AM == AM65_ZPX) {
+ /* Invalidates all ZP registers */
+ RC_InvalidateZP (Out);
}
break;
case OP65_STY:
if (E->AM == AM65_ZP) {
- if (E->Chg & REG_SREG_LO) {
- Out->SRegLo = In->RegY;
- } else if (E->Chg & REG_SREG_HI) {
- Out->SRegHi = In->RegY;
- }
- }
+ if (E->Chg & REG_SREG_LO) {
+ Out->SRegLo = In->RegY;
+ } else if (E->Chg & REG_SREG_HI) {
+ Out->SRegHi = In->RegY;
+ }
+ } else if (E->AM == AM65_ZPX) {
+ /* Invalidates all ZP registers */
+ RC_InvalidateZP (Out);
+ }
+ break;
+
+ case OP65_STZ:
+ if (E->AM == AM65_ZP) {
+ if (E->Chg & REG_SREG_LO) {
+ Out->SRegLo = 0;
+ } else if (E->Chg & REG_SREG_HI) {
+ Out->SRegHi = 0;
+ }
+ } else if (E->AM == AM65_ZPX) {
+ /* Invalidates all ZP registers */
+ RC_InvalidateZP (Out);
+ }
break;
case OP65_TAX:
X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, E->LI);
} else if (Val == E->RI->In.RegA) {
X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, E->LI);
- }
+ }
}
break;
/* A list of all the function descriptions */
static OptFunc DOpt65C02BitOps = { Opt65C02BitOps, "Opt65C02BitOps", 66, 0, 0, 0, 0, 0 };
static OptFunc DOpt65C02Ind = { Opt65C02Ind, "Opt65C02Ind", 100, 0, 0, 0, 0, 0 };
+static OptFunc DOpt65C02Stores = { Opt65C02Stores, "Opt65C02Stores", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd1 = { OptAdd1, "OptAdd1", 60, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd2 = { OptAdd2, "OptAdd2", 200, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd3 = { OptAdd3, "OptAdd3", 40, 0, 0, 0, 0, 0 };
static OptFunc* OptFuncs[] = {
&DOpt65C02BitOps,
&DOpt65C02Ind,
+ &DOpt65C02Stores,
&DOptAdd1,
&DOptAdd2,
&DOptAdd3,
static unsigned RunOptGroup4 (CodeSeg* S)
/* 65C02 specific optimizations. */
{
- unsigned C;
unsigned Changes = 0;
if (CPU >= CPU_65C02) {
Changes += RunOptFunc (S, &DOpt65C02BitOps, 1);
- /* Replace (zp),y by (zp) if Y is zero. If we have changes, run register
- * load optimization again, since loads of Y may have become unnecessary.
- */
- C = RunOptFunc (S, &DOpt65C02Ind, 1);
- Changes += C;
- if (C) {
+ Changes += RunOptFunc (S, &DOpt65C02Ind, 1);
+ Changes += RunOptFunc (S, &DOpt65C02Stores, 1);
+ if (Changes) {
+ /* The 65C02 replacement codes do often make the use of a register
+ * value unnecessary, so if we have changes, run another load
+ * removal pass.
+ */
Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
}
}
/* LDA #XX */
sprintf (Buf, "$%02X", (int) ((~L[1]->Num) & 0xFF));
X = NewCodeEntry (OP65_LDA, AM65_IMM, Buf, 0, L[1]->LI);
- CS_InsertEntry (S, X, I);
+ CS_InsertEntry (S, X, I+3);
/* TRB */
X = NewCodeEntry (OP65_TRB, L[0]->AM, L[0]->Arg, 0, L[0]->LI);
- CS_InsertEntry (S, X, I+1);
+ CS_InsertEntry (S, X, I+4);
} else {
/* LDA #XX */
sprintf (Buf, "$%02X", (int) L[1]->Num);
X = NewCodeEntry (OP65_LDA, AM65_IMM, Buf, 0, L[1]->LI);
- CS_InsertEntry (S, X, I);
+ CS_InsertEntry (S, X, I+3);
- /* TRB */
+ /* TSB */
X = NewCodeEntry (OP65_TSB, L[0]->AM, L[0]->Arg, 0, L[0]->LI);
- CS_InsertEntry (S, X, I+1);
+ CS_InsertEntry (S, X, I+4);
}
/* Delete the old stuff */
- CS_DelEntries (S, I+2, 3);
+ CS_DelEntries (S, I, 3);
+
+ /* We had changes */
+ ++Changes;
+ }
+
+ /* Next entry */
+ ++I;
+
+ }
+
+ /* Free register info */
+ CS_FreeRegInfo (S);
+
+ /* Return the number of changes made */
+ return Changes;
+}
+
+
+
+unsigned Opt65C02Stores (CodeSeg* S)
+/* Use STZ where possible */
+{
+ 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 for the sequence */
+ if (E->OPC == OP65_STA &&
+ (E->AM == AM65_ZP || E->AM == AM65_ABS ||
+ E->AM == AM65_ZPX || E->AM == AM65_ABSX ) &&
+ E->RI->In.RegA == 0) {
+
+ /* Replace by STZ */
+ CodeEntry* X = NewCodeEntry (OP65_STZ, E->AM, E->Arg, 0, E->LI);
+ CS_InsertEntry (S, X, I+1);
+
+ /* Delete the old stuff */
+ CS_DelEntry (S, I);
/* We had changes */
++Changes;
unsigned Opt65C02BitOps (CodeSeg* S);
/* Use special bit op instructions of the C02 */
+unsigned Opt65C02Stores (CodeSeg* S);
+/* Use STZ where possible */
+
/* End of coptc02.h */
/* */
/* */
/* */
-/* (C) 2001 Ullrich von Bassewitz */
+/* (C) 2001-2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@cc65.org */
* location does already contain the value to be stored,
* remove the store.
*/
- if (In->RegX >= 0 && /* Value of A is known */
+ if (In->RegY >= 0 && /* Value of Y is known */
E->AM == AM65_ZP && /* Store into zp */
(((E->Chg & REG_SREG_LO) != 0 && /* Store into sreg */
- In->RegX == In->SRegLo) || /* Value identical */
+ In->RegY == In->SRegLo) || /* Value identical */
((E->Chg & REG_SREG_HI) != 0 && /* Store into sreg+1 */
- In->RegX == In->SRegHi))) { /* Value identical */
+ In->RegY == In->SRegHi))) { /* Value identical */
Delete = 1;
/* If the value in the Y register is known and the same as
* that in the A register, replace the store by a STA. The
*/
} else if (In->RegY >= 0) {
if (In->RegY == In->RegA) {
- CE_ReplaceOPC (E, OP65_STA);
+ CE_ReplaceOPC (E, OP65_STA);
} else if (In->RegY == In->RegX &&
- E->AM != AM65_ABSX &&
- E->AM != AM65_ZPX) {
+ E->AM != AM65_ABSX &&
+ E->AM != AM65_ZPX) {
CE_ReplaceOPC (E, OP65_STX);
}
}
break;
+ case OP65_STZ:
+ /* If we store into a known zero page location, and this
+ * location does already contain the value to be stored,
+ * remove the store.
+ */
+ if (CPU >= CPU_65C02 && E->AM == AM65_ZP) {
+ if (((E->Chg & REG_SREG_LO) != 0 && In->SRegLo == 0) ||
+ ((E->Chg & REG_SREG_HI) != 0 && In->SRegHi == 0)) {
+ Delete = 1;
+ }
+ }
+ break;
+
case OP65_TAX:
if (In->RegA >= 0 &&
In->RegA == In->RegX &&
/* */
/* */
/* */
-/* (C) 2001 Ullrich von Bassewitz */
+/* (C) 2001-2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@cc65.org */
REG_NONE, /* chg */
OF_STORE /* flags */
},
+ { OP65_STZ, /* opcode */
+ "stz", /* mnemonic */
+ 0, /* size */
+ REG_NONE, /* use */
+ REG_NONE, /* chg */
+ OF_STORE /* flags */
+ },
{ OP65_TAX, /* opcode */
"tax", /* mnemonic */
1, /* size */
case OP65_JPL: return BC_PL;
case OP65_JVC: return BC_VC;
case OP65_JVS: return BC_VS;
- default:
+ default:
Internal ("GetBranchCond: Invalid opcode: %d", OPC);
return 0;
}
-
+
/* */
/* */
/* */
-/* (C) 2001 Ullrich von Bassewitz */
+/* (C) 2001-2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@cc65.org */
OP65_STA,
OP65_STX,
OP65_STY,
+ OP65_STZ,
OP65_TAX,
OP65_TAY,
OP65_TRB,
/* */
/* */
/* */
-/* (C) 2001 Ullrich von Bassewitz */
+/* (C) 2001-2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@cc65.org */
+void RC_InvalidateZP (RegContents* C)
+/* Invalidate all ZP registers */
+{
+ C->SRegLo = -1;
+ C->SRegHi = -1;
+}
+
+
+
RegInfo* NewRegInfo (const RegContents* RC)
/* Allocate a new register info, initialize and return it. If RC is not
* a NULL pointer, it is used to initialize both, the input and output
/* */
/* */
/* */
-/* (C) 2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@cc65.org */
+/* (C) 2001-2002 Ullrich von Bassewitz */
+/* Wacholderweg 14 */
+/* D-70597 Stuttgart */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
void RC_Invalidate (RegContents* C);
/* Invalidate all registers */
+void RC_InvalidateZP (RegContents* C);
+/* Invalidate all ZP registers */
+
RegInfo* NewRegInfo (const RegContents* RC);
/* Allocate a new register info, initialize and return it. If RC is not
* a NULL pointer, it is used to initialize both, the input and output