#define OptFuncEntry(func) static OptFuncDesc D##func = { func, #func, 0 }
/* 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 DOptAdd1 = { OptAdd1, "OptAdd1", 60, 0, 0, 0, 0, 0 };
static OptFunc DOptAdd2 = { OptAdd2, "OptAdd2", 200, 0, 0, 0, 0, 0 };
/* Table containing all the steps in alphabetical order */
static OptFunc* OptFuncs[] = {
+ &DOpt65C02BitOps,
&DOpt65C02Ind,
&DOptAdd1,
&DOptAdd2,
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.
*/
- unsigned C = RunOptFunc (S, &DOpt65C02Ind, 1);
+ C = RunOptFunc (S, &DOpt65C02Ind, 1);
Changes += C;
if (C) {
Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
/* */
/* */
/* */
-/* (C) 2001 Ullrich von Bassewitz */
+/* (C) 2001-2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@cc65.org */
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
- /* Check for addressing mode indirect indexed Y where Y is zero.
+ /* Check for addressing mode indirect indexed Y where Y is zero.
* Note: All opcodes that are available as (zp),y are also available
* as (zp), so we can ignore the actual opcode here.
*/
+unsigned Opt65C02BitOps (CodeSeg* S)
+/* Use special bit op instructions of the C02 */
+{
+ 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)) {
+
+ CodeEntry* L[3];
+
+ /* Get next entry */
+ L[0] = CS_GetEntry (S, I);
+
+ /* Check for the sequence */
+ if (L[0]->OPC == OP65_LDA &&
+ (L[0]->AM == AM65_ZP || L[0]->AM == AM65_ABS) &&
+ !CS_RangeHasLabel (S, I+1, 2) &&
+ CS_GetEntries (S, L+1, I+1, 2) &&
+ (L[1]->OPC == OP65_AND || L[1]->OPC == OP65_ORA) &&
+ CE_KnownImm (L[1]) &&
+ L[2]->OPC == OP65_STA &&
+ L[2]->AM == L[0]->AM &&
+ strcmp (L[2]->Arg, L[0]->Arg) == 0 &&
+ !RegAUsed (S, I+3)) {
+
+ char Buf[32];
+ CodeEntry* X;
+
+ /* Use TRB for AND and TSB for ORA */
+ if (L[1]->OPC == OP65_AND) {
+
+ /* 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);
+
+ /* TRB */
+ X = NewCodeEntry (OP65_TRB, L[0]->AM, L[0]->Arg, 0, L[0]->LI);
+ CS_InsertEntry (S, X, I+1);
+
+ } 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);
+
+ /* TRB */
+ X = NewCodeEntry (OP65_TSB, L[0]->AM, L[0]->Arg, 0, L[0]->LI);
+ CS_InsertEntry (S, X, I+1);
+ }
+
+ /* Delete the old stuff */
+ CS_DelEntries (S, I+2, 3);
+
+ /* We had changes */
+ ++Changes;
+ }
+
+ /* Next entry */
+ ++I;
+
+ }
+
+ /* Free register info */
+ CS_FreeRegInfo (S);
+
+ /* Return the number of changes made */
+ return Changes;
+}
+
+