示例#1
0
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);
}
示例#2
0
文件: coptsub.c 项目: Aliandrana/cc65
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;
}
示例#3
0
文件: coptcmp.c 项目: eakmeister/cc65
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;
}
示例#4
0
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);
    }
}