void CS_DelEntry (CodeSeg* S, unsigned Index) /* Delete an entry from the code segment. This includes moving any associated * labels, removing references to labels and even removing the referenced labels * if the reference count drops to zero. * Note: Labels are moved forward if possible, that is, they are moved to the * next insn (not the preceeding one). */ { /* Get the code entry for the given index */ CodeEntry* E = CS_GetEntry (S, Index); /* If the entry has a labels, we have to move this label to the next insn. * If there is no next insn, move the label into the code segement label * pool. The operation is further complicated by the fact that the next * insn may already have a label. In that case change all reference to * this label and delete the label instead of moving it. */ unsigned Count = CE_GetLabelCount (E); if (Count > 0) { /* The instruction has labels attached. Check if there is a next * instruction. */ if (Index == CS_GetEntryCount (S)-1) { /* No next instruction, move to the codeseg label pool */ CS_MoveLabelsToPool (S, E); } else { /* There is a next insn, get it */ CodeEntry* N = CS_GetEntry (S, Index+1); /* Move labels to the next entry */ CS_MoveLabels (S, E, N); } } /* If this insn references a label, remove the reference. And, if the * the reference count for this label drops to zero, remove this label. */ if (E->JumpTo) { /* Remove the reference */ CS_RemoveLabelRef (S, E); } /* Delete the pointer to the insn */ CollDelete (&S->Entries, Index); /* Delete the instruction itself */ FreeCodeEntry (E); }
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; }
void CS_DelCodeRange (CodeSeg* S, unsigned First, unsigned Last) /* Delete all entries between first and last, both inclusive. The function * can only handle basic blocks (First is the only entry, Last the only exit) * and no open labels. It will call FAIL if any of these preconditions are * violated. */ { unsigned I; CodeEntry* FirstEntry; /* Do some sanity checks */ CHECK (First <= Last && Last < CS_GetEntryCount (S)); /* If Last is actually the last insn, call CS_DelCodeAfter instead, which * is more flexible in this case. */ if (Last == CS_GetEntryCount (S) - 1) { CS_DelCodeAfter (S, First); return; } /* Get the first entry and check if it has any labels. If it has, move * them to the insn following Last. If Last is the last insn of the code * segment, make them ownerless and move them to the label pool. */ FirstEntry = CS_GetEntry (S, First); if (CE_HasLabel (FirstEntry)) { /* Get the entry following last */ CodeEntry* FollowingEntry = CS_GetNextEntry (S, Last); if (FollowingEntry) { /* There is an entry after Last - move the labels */ CS_MoveLabels (S, FirstEntry, FollowingEntry); } else { /* Move the labels to the pool and clear the owner pointer */ CS_MoveLabelsToPool (S, FirstEntry); } } /* First pass: Delete all references to labels. If the reference count * for a label drops to zero, delete it. */ for (I = Last; I >= First; --I) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if this entry has a label reference */ if (E->JumpTo) { /* If the label is a label in the label pool, this is an error */ CodeLabel* L = E->JumpTo; CHECK (CollIndex (&S->Labels, L) < 0); /* Remove the reference to the label */ CS_RemoveLabelRef (S, E); } } /* Second pass: Delete the instructions. If a label attached to an * instruction still has references, it must be references from outside * the deleted area, which is an error. */ for (I = Last; I >= First; --I) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if this entry has a label attached */ CHECK (!CE_HasLabel (E)); /* Delete the pointer to the entry */ CollDelete (&S->Entries, I); /* Delete the entry itself */ FreeCodeEntry (E); } }