unsigned OptSub2 (CodeSeg* S) /* Search for the sequence ** ** lda xx ** sec ** sta tmp1 ** lda yy ** sbc tmp1 ** sta yy ** ** and replace it by ** ** sec ** lda yy ** sbc xx ** sta yy */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[5]; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ if (E->OPC == OP65_LDA && !CS_RangeHasLabel (S, I+1, 5) && CS_GetEntries (S, L, I+1, 5) && L[0]->OPC == OP65_SEC && L[1]->OPC == OP65_STA && strcmp (L[1]->Arg, "tmp1") == 0 && L[2]->OPC == OP65_LDA && L[3]->OPC == OP65_SBC && strcmp (L[3]->Arg, "tmp1") == 0 && L[4]->OPC == OP65_STA && strcmp (L[4]->Arg, L[2]->Arg) == 0) { /* Remove the store to tmp1 */ CS_DelEntry (S, I+2); /* Remove the subtraction */ CS_DelEntry (S, I+3); /* Move the lda to the position of the subtraction and change the ** op to SBC. */ CS_MoveEntry (S, I, I+3); CE_ReplaceOPC (E, OP65_SBC); /* If the sequence head had a label, move this label back to the ** head. */ if (CE_HasLabel (E)) { CS_MoveLabels (S, E, L[0]); } /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; }
unsigned OptCmp4 (CodeSeg* S) /* Search for * * lda x * ldx y * cpx #a * bne L1 * cmp #b * L1: jne/jeq L2 * * If a is zero, we may remove the compare. If a and b are both zero, we may * replace it by the sequence * * lda x * ora x+1 * jne/jeq ... * * L1 may be either the label at the branch instruction, or the target label * of this instruction. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[5]; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ if (E->OPC == OP65_LDA && CS_GetEntries (S, L, I+1, 5) && L[0]->OPC == OP65_LDX && !CE_HasLabel (L[0]) && IsImmCmp16 (L+1) && !RegAXUsed (S, I+6)) { if ((L[4]->Info & OF_FBRA) != 0 && L[1]->Num == 0 && L[3]->Num == 0) { /* The value is zero, we may use the simple code version. */ CE_ReplaceOPC (L[0], OP65_ORA); CS_DelEntries (S, I+2, 3); } else { /* Move the lda instruction after the first branch. This will * improve speed, since the load is delayed after the first * test. */ CS_MoveEntry (S, I, I+4); /* We will replace the ldx/cpx by lda/cmp */ CE_ReplaceOPC (L[0], OP65_LDA); CE_ReplaceOPC (L[1], OP65_CMP); /* Beware: If the first LDA instruction had a label, we have * to move this label to the top of the sequence again. */ if (CE_HasLabel (E)) { CS_MoveLabels (S, E, L[0]); } } ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; }