unsigned OptCmp7 (CodeSeg* S) /* Search for a sequence ldx/txa/branch and remove the txa if A is not * used later. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[2]; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ if ((E->OPC == OP65_LDX) && CS_GetEntries (S, L, I+1, 2) && L[0]->OPC == OP65_TXA && !CE_HasLabel (L[0]) && (L[1]->Info & OF_FBRA) != 0 && !CE_HasLabel (L[1]) && !RegAUsed (S, I+3)) { /* Remove the txa */ CS_DelEntry (S, I+1); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; }
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_IsConstImm (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+3); /* TRB */ X = NewCodeEntry (OP65_TRB, L[0]->AM, L[0]->Arg, 0, L[0]->LI); 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+3); /* TSB */ X = NewCodeEntry (OP65_TSB, L[0]->AM, L[0]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+4); } /* Delete the old stuff */ 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 OptCmp9 (CodeSeg* S) /* Search for the sequence * * sbc xx * bvs/bvc L * eor #$80 * L: asl a * bcc/bcs somewhere * * If A is not used later (which should be the case), we can branch on the N * flag instead of the carry flag and remove the asl. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[5]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_SBC && CS_GetEntries (S, L+1, I+1, 4) && (L[1]->OPC == OP65_BVC || L[1]->OPC == OP65_BVS) && L[1]->JumpTo != 0 && L[1]->JumpTo->Owner == L[3] && L[2]->OPC == OP65_EOR && CE_IsKnownImm (L[2], 0x80) && L[3]->OPC == OP65_ASL && L[3]->AM == AM65_ACC && (L[4]->OPC == OP65_BCC || L[4]->OPC == OP65_BCS || L[4]->OPC == OP65_JCC || L[4]->OPC == OP65_JCS) && !CE_HasLabel (L[4]) && !RegAUsed (S, I+4)) { /* Replace the branch condition */ switch (GetBranchCond (L[4]->OPC)) { case BC_CC: CE_ReplaceOPC (L[4], OP65_JPL); break; case BC_CS: CE_ReplaceOPC (L[4], OP65_JMI); break; default: Internal ("Unknown branch condition in OptCmp9"); } /* Delete the asl insn */ CS_DelEntry (S, I+3); /* Next sequence is somewhat ahead (if any) */ I += 3; /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; }