示例#1
0
文件: coptcmp.c 项目: eakmeister/cc65
unsigned OptCmp1 (CodeSeg* S)
/* Search for the sequence
 *
 *  	ldx	xx
 *  	stx	tmp1
 *  	ora	tmp1
 *
 * and replace it by
 *
 *  	ora	xx
 */
{
    unsigned Changes = 0;

    /* Walk over the entries */
    unsigned 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_LDX               &&
	    !CS_RangeHasLabel (S, I+1, 2)       &&
	    CS_GetEntries (S, L+1, I+1, 2)	&&
       	    L[1]->OPC == OP65_STX	  	&&
	    strcmp (L[1]->Arg, "tmp1") == 0     &&
	    L[2]->OPC == OP65_ORA	    	&&
	    strcmp (L[2]->Arg, "tmp1") == 0) {

            CodeEntry* X;

	    /* Insert the ora instead */
            X = NewCodeEntry (OP65_ORA, L[0]->AM, L[0]->Arg, 0, L[0]->LI);
	    CS_InsertEntry (S, X, I);

	    /* Remove all other instructions */
	    CS_DelEntries (S, I+1, 3);

	    /* Remember, we had changes */
	    ++Changes;

	}

	/* Next entry */
	++I;

    }

    /* Return the number of changes made */
    return Changes;
}
示例#2
0
unsigned OptStore4 (CodeSeg* S)
/* Search for the sequence
**
**      sta     xx
**      stx     yy
**      lda     xx
**      ldx     yy
**
** and remove the useless load, provided that the next insn doesn't use flags
** from the load.
*/
{
    unsigned Changes = 0;

    /* Walk over the entries */
    unsigned 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_STA                           &&
            (L[0]->AM == AM65_ABS || L[0]->AM == AM65_ZP)   &&
            !CS_RangeHasLabel (S, I+1, 3)                   &&
            CS_GetEntries (S, L+1, I+1, 4)                  &&
            L[1]->OPC == OP65_STX                           &&
            L[1]->AM == L[0]->AM                            &&
            L[2]->OPC == OP65_LDA                           &&
            L[2]->AM == L[0]->AM                            &&
            L[3]->OPC == OP65_LDX                           &&
            L[3]->AM == L[1]->AM                            &&
            strcmp (L[0]->Arg, L[2]->Arg) == 0              &&
            strcmp (L[1]->Arg, L[3]->Arg) == 0              &&
            !CE_UseLoadFlags (L[4])) {

            /* Register has already the correct value, remove the loads */
            CS_DelEntries (S, I+2, 2);

            /* Remember, we had changes */
            ++Changes;

        }

        /* Next entry */
        ++I;

    }

    /* Return the number of changes made */
    return Changes;
}
示例#3
0
unsigned OptStore1 (CodeSeg* S)
/* Search for the sequence
**
**      ldy     #n
**      jsr     staxysp
**      ldy     #n+1
**      jsr     ldaxysp
**
** and remove the useless load.
*/
{
    unsigned Changes = 0;

    /* Walk over the entries */
    unsigned I = 0;
    while (I < CS_GetEntryCount (S)) {

        CodeEntry* L[4];

        /* Get next entry */
        L[0] = CS_GetEntry (S, I);

        /* Check for the sequence */
        if (L[0]->OPC == OP65_LDY                           &&
            CE_IsConstImm (L[0])                            &&
            L[0]->Num < 0xFF                                &&
            !CS_RangeHasLabel (S, I+1, 3)                   &&
            CS_GetEntries (S, L+1, I+1, 3)                  &&
            CE_IsCallTo (L[1], "staxysp")                   &&
            L[2]->OPC == OP65_LDY                           &&
            CE_IsKnownImm (L[2], L[0]->Num + 1)             &&
            CE_IsCallTo (L[3], "ldaxysp")) {

            /* Register has already the correct value, remove the loads */
            CS_DelEntries (S, I+2, 2);

            /* Remember, we had changes */
            ++Changes;

        }

        /* Next entry */
        ++I;

    }

    /* Return the number of changes made */
    return Changes;
}
示例#4
0
unsigned OptStore5 (CodeSeg* S)
/* Search for the sequence
**
**      lda     foo
**      ldx     bar
**      sta     something
**      stx     something-else
**
** and replace it by
**
**      lda     foo
**      sta     something
**      lda     bar
**      sta     something-else
**
** if X is not used later. This replacement doesn't save any cycles or bytes,
** but it keeps the value of X, which may be reused later.
*/
{
    unsigned Changes = 0;

    /* Walk over the entries */
    unsigned I = 0;
    while (I < CS_GetEntryCount (S)) {

        CodeEntry* L[4];

        /* Get next entry */
        L[0] = CS_GetEntry (S, I);

        /* Check for the sequence */
        if (L[0]->OPC == OP65_LDA                           &&
            !CS_RangeHasLabel (S, I+1, 3)                   &&
            CS_GetEntries (S, L+1, I+1, 3)                  &&
            L[1]->OPC == OP65_LDX                           &&
            L[2]->OPC == OP65_STA                           &&
            L[3]->OPC == OP65_STX                           &&
            !RegXUsed (S, I+4)) {

            CodeEntry* X;

            /* Insert the code after the sequence */
            X = NewCodeEntry (OP65_LDA, L[1]->AM, L[1]->Arg, 0, L[1]->LI);
            CS_InsertEntry (S, X, I+4);
            X = NewCodeEntry (OP65_STA, L[3]->AM, L[3]->Arg, 0, L[3]->LI);
            CS_InsertEntry (S, X, I+5);

            /* Delete the old code */
            CS_DelEntry (S, I+3);
            CS_DelEntry (S, I+1);

            /* Remember, we had changes */
            ++Changes;
        }

        /* Next entry */
        ++I;

    }

    /* Return the number of changes made */
    return Changes;
}
示例#5
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;
}
示例#6
0
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;
}
示例#7
0
文件: codeopt.c 项目: coyxc/cc65
static unsigned OptLoad2 (CodeSeg* S)
/* Replace calls to ldaxysp by inline code */
{
    unsigned I;
    unsigned Changes = 0;

    /* 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 (CE_IsCallTo (L[0], "ldaxysp")) {

            CodeEntry* X;

            /* Followed by sta abs/stx abs? */
            if (CS_GetEntries (S, L+1, I+1, 2)                  &&
                L[1]->OPC == OP65_STA                           &&
                L[2]->OPC == OP65_STX                           &&
                (L[1]->Arg == 0                         ||
                 L[2]->Arg == 0                         ||
                 strcmp (L[1]->Arg, L[2]->Arg) != 0)            &&
                !CS_RangeHasLabel (S, I+1, 2)                   &&
                !RegXUsed (S, I+3)) {

                /* A/X are stored into memory somewhere and X is not used
                ** later
                */

                /* lda (sp),y */
                X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[0]->LI);
                CS_InsertEntry (S, X, I+3);

                /* sta abs */
                X = NewCodeEntry (OP65_STA, L[2]->AM, L[2]->Arg, 0, L[2]->LI);
                CS_InsertEntry (S, X, I+4);

                /* dey */
                X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[0]->LI);
                CS_InsertEntry (S, X, I+5);

                /* lda (sp),y */
                X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[0]->LI);
                CS_InsertEntry (S, X, I+6);

                /* sta abs */
                X = NewCodeEntry (OP65_STA, L[1]->AM, L[1]->Arg, 0, L[1]->LI);
                CS_InsertEntry (S, X, I+7);

                /* Now remove the call to the subroutine and the sta/stx */
                CS_DelEntries (S, I, 3);

            } else {

                /* Standard replacement */

                /* lda (sp),y */
                X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[0]->LI);
                CS_InsertEntry (S, X, I+1);

                /* tax */
                X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[0]->LI);
                CS_InsertEntry (S, X, I+2);

                /* dey */
                X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[0]->LI);
                CS_InsertEntry (S, X, I+3);

                /* lda (sp),y */
                X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[0]->LI);
                CS_InsertEntry (S, X, I+4);

                /* Now remove the call to the subroutine */
                CS_DelEntry (S, I);

            }

            /* Remember, we had changes */
            ++Changes;

        }

        /* Next entry */
        ++I;
    }

    /* Return the number of changes made */
    return Changes;
}
示例#8
0
文件: coptcmp.c 项目: eakmeister/cc65
unsigned OptCmp3 (CodeSeg* S)
/* Search for
 *
 *     	lda/and/ora/eor	...
 *  	cmp #$00
 *  	jeq/jne
 * or
 *     	lda/and/ora/eor	...
 *  	cmp #$00
 *  	jsr boolxx
 *
 * and remove the cmp.
 */
{
    unsigned Changes = 0;

    /* Walk over the entries */
    unsigned 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_ADC ||
       	     L[0]->OPC == OP65_AND ||
             L[0]->OPC == OP65_ASL ||
       	     L[0]->OPC == OP65_DEA ||
       	     L[0]->OPC == OP65_EOR ||
       	     L[0]->OPC == OP65_INA ||
       	     L[0]->OPC == OP65_LDA ||
             L[0]->OPC == OP65_LSR ||
       	     L[0]->OPC == OP65_ORA ||
       	     L[0]->OPC == OP65_PLA ||
       	     L[0]->OPC == OP65_SBC ||
       	     L[0]->OPC == OP65_TXA ||
       	     L[0]->OPC == OP65_TYA)         &&
	    !CS_RangeHasLabel (S, I+1, 2)   &&
	    CS_GetEntries (S, L+1, I+1, 2)  &&
	    L[1]->OPC == OP65_CMP           &&
	    CE_IsKnownImm (L[1], 0)) {

            int Delete = 0;

	    /* Check for the call to boolxx. We only remove the compare if
       	     * the carry flag is not evaluated later, because the load will
             * not set the carry flag.
	     */
	    if (L[2]->OPC == OP65_JSR) {
	    	switch (FindBoolCmpCond (L[2]->Arg)) {

	    	    case CMP_EQ:
	    	    case CMP_NE:
	    	    case CMP_GT:
	    	    case CMP_GE:
	    	    case CMP_LT:
	    	    case CMP_LE:
	    	        /* Remove the compare */
                        Delete = 1;
	    	        break;

	    	    case CMP_UGT:
	     	    case CMP_UGE:
	    	    case CMP_ULT:
	    	    case CMP_ULE:
	    	    case CMP_INV:
	    	        /* Leave it alone */
	    	        break;
	    	}

	    } else if ((L[2]->Info & OF_FBRA) != 0) {
                /* The following insn branches on the condition of the load,
                 * so the compare instruction might be removed. For safety,
                 * do some more checks if the carry isn't used later, since
                 * the compare does set the carry, but the load does not.
                 */
                CodeEntry* E;
                CodeEntry* N;
                if ((E = CS_GetNextEntry (S, I+2)) != 0         &&
                    L[2]->JumpTo != 0                           &&
                    (N = L[2]->JumpTo->Owner) != 0              &&
                    N->OPC != OP65_BCC                          &&
                    N->OPC != OP65_BCS                          &&
                    N->OPC != OP65_JCC                          &&
                    N->OPC != OP65_JCS                          &&
                    (N->OPC != OP65_JSR                 ||
                    FindBoolCmpCond (N->Arg) == CMP_INV)) {

                    /* The following insn branches on the condition of a load,
                     * and there's no use of the carry flag in sight, so the
                     * compare instruction can be removed.
                     */
                    Delete = 1;
                }
            }

            /* Delete the compare if we can */
            if (Delete) {
                CS_DelEntry (S, I+1);
                ++Changes;
            }
	}

	/* Next entry */
	++I;

    }

    /* Return the number of changes made */
    return Changes;
}
示例#9
0
unsigned OptShift5 (CodeSeg* S)
/* Search for the sequence
 *
 *      lda     xxx
 *      ldx     yyy
 *      jsr     aslax1/asrax1/shlax1/shrax1
 *      sta     aaa
 *      stx     bbb
 *
 * and replace it by
 *
 *      lda     xxx
 *      asl     a
 *      sta     aaa
 *      lda     yyy
 *      rol     a
 *      sta     bbb
 *
 * or similar, provided that a/x is not used later
 */
{
    unsigned Changes = 0;

    /* Walk over the entries */
    unsigned I = 0;
    while (I < CS_GetEntryCount (S)) {

        unsigned ShiftType;
     	CodeEntry* L[5];

      	/* Get next entry */
       	L[0] = CS_GetEntry (S, I);

     	/* Check for the sequence */
       	if (L[0]->OPC == OP65_LDA                               &&
            (L[0]->AM == AM65_ABS || L[0]->AM == AM65_ZP)       &&
       	    CS_GetEntries (S, L+1, I+1, 4)     	                &&
            !CS_RangeHasLabel (S, I+1, 4)                       &&
            L[1]->OPC == OP65_LDX                               &&
            (L[1]->AM == AM65_ABS || L[1]->AM == AM65_ZP)       &&
            L[2]->OPC == OP65_JSR                               &&
            (ShiftType = GetShift (L[2]->Arg)) != SHIFT_NONE    &&
            SHIFT_COUNT(ShiftType) == 1                         &&
       	    L[3]->OPC == OP65_STA                               &&
            (L[3]->AM == AM65_ABS || L[3]->AM == AM65_ZP)       &&
            L[4]->OPC == OP65_STX                               &&
            (L[4]->AM == AM65_ABS || L[4]->AM == AM65_ZP)       &&
            !RegAXUsed (S, I+5)) {

            CodeEntry* X;

            /* Handle the four shift types differently */
            switch (ShiftType) {

                case SHIFT_ASR_1:
                    X = NewCodeEntry (OP65_LDA, L[1]->AM, L[1]->Arg, 0, L[1]->LI);
                    CS_InsertEntry (S, X, I+5);
                    X = NewCodeEntry (OP65_CMP, AM65_IMM, "$80", 0, L[2]->LI);
                    CS_InsertEntry (S, X, I+6);
                    X = NewCodeEntry (OP65_ROR, AM65_ACC, "a", 0, L[2]->LI);
                    CS_InsertEntry (S, X, I+7);
                    X = NewCodeEntry (OP65_STA, L[4]->AM, L[4]->Arg, 0, L[4]->LI);
                    CS_InsertEntry (S, X, I+8);
                    X = NewCodeEntry (OP65_LDA, L[0]->AM, L[0]->Arg, 0, L[0]->LI);
                    CS_InsertEntry (S, X, I+9);
                    X = NewCodeEntry (OP65_ROR, AM65_ACC, "a", 0, L[2]->LI);
                    CS_InsertEntry (S, X, I+10);
                    X = NewCodeEntry (OP65_STA, L[3]->AM, L[3]->Arg, 0, L[3]->LI);
                    CS_InsertEntry (S, X, I+11);
                    CS_DelEntries (S, I, 5);
                    break;

                case SHIFT_LSR_1:
                    X = NewCodeEntry (OP65_LDA, L[1]->AM, L[1]->Arg, 0, L[1]->LI);
                    CS_InsertEntry (S, X, I+5);
                    X = NewCodeEntry (OP65_LSR, AM65_ACC, "a", 0, L[2]->LI);
                    CS_InsertEntry (S, X, I+6);
                    X = NewCodeEntry (OP65_STA, L[4]->AM, L[4]->Arg, 0, L[4]->LI);
                    CS_InsertEntry (S, X, I+7);
                    X = NewCodeEntry (OP65_LDA, L[0]->AM, L[0]->Arg, 0, L[0]->LI);
                    CS_InsertEntry (S, X, I+8);
                    X = NewCodeEntry (OP65_ROR, AM65_ACC, "a", 0, L[2]->LI);
                    CS_InsertEntry (S, X, I+9);
                    X = NewCodeEntry (OP65_STA, L[3]->AM, L[3]->Arg, 0, L[3]->LI);
                    CS_InsertEntry (S, X, I+10);
                    CS_DelEntries (S, I, 5);
                    break;

                case SHIFT_LSL_1:
                case SHIFT_ASL_1:
                    /* These two are identical */
                    X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, L[2]->LI);
                    CS_InsertEntry (S, X, I+1);
                    X = NewCodeEntry (OP65_STA, L[3]->AM, L[3]->Arg, 0, L[3]->LI);
                    CS_InsertEntry (S, X, I+2);
                    X = NewCodeEntry (OP65_LDA, L[1]->AM, L[1]->Arg, 0, L[1]->LI);
                    CS_InsertEntry (S, X, I+3);
                    X = NewCodeEntry (OP65_ROL, AM65_ACC, "a", 0, L[2]->LI);
                    CS_InsertEntry (S, X, I+4);
                    X = NewCodeEntry (OP65_STA, L[4]->AM, L[4]->Arg, 0, L[4]->LI);
                    CS_InsertEntry (S, X, I+5);
                    CS_DelEntries (S, I+6, 4);
                    break;

            }

	    /* Remember, we had changes */
            ++Changes;

	}

	/* Next entry */
	++I;

    }

    /* Return the number of changes made */
    return Changes;
}
示例#10
0
unsigned OptBNegAX2 (CodeSeg* S)
/* Search for the sequence:
 *
 *      ldy     #xx
 *      jsr     ldaxysp
 *      jsr     bnegax
 *      jne/jeq ...
 *
 * and replace it by
 *
 *      ldy     #xx
 *      lda     (sp),y
 *      dey
 *      ora     (sp),y
 *      jeq/jne ...
 */
{
    unsigned Changes = 0;

    /* Walk over the entries */
    unsigned I = 0;
    while (I < CS_GetEntryCount (S)) {

        CodeEntry* L[4];

        /* Get next entry */
        L[0] = CS_GetEntry (S, I);

        /* Check for the sequence */
        if (L[0]->OPC == OP65_LDY               &&
            CE_IsConstImm (L[0])                &&
            !CS_RangeHasLabel (S, I+1, 3)       &&
            CS_GetEntries (S, L+1, I+1, 3)      &&
            CE_IsCallTo (L[1], "ldaxysp")       &&
            CE_IsCallTo (L[2], "bnegax")        &&
            (L[3]->Info & OF_ZBRA) != 0) {

            CodeEntry* X;

            /* lda (sp),y */
            X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI);
            CS_InsertEntry (S, X, I+1);

            /* dey */
            X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[1]->LI);
            CS_InsertEntry (S, X, I+2);

            /* ora (sp),y */
            X = NewCodeEntry (OP65_ORA, AM65_ZP_INDY, "sp", 0, L[1]->LI);
            CS_InsertEntry (S, X, I+3);

            /* Invert the branch */
            CE_ReplaceOPC (L[3], GetInverseBranch (L[3]->OPC));

            /* Delete the entries no longer needed. */
            CS_DelEntries (S, I+4, 2);

            /* Remember, we had changes */
            ++Changes;

        }

        /* Next entry */
        ++I;

    }

    /* Return the number of changes made */
    return Changes;
}
示例#11
0
unsigned OptShift3 (CodeSeg* S)
/* The sequence
 *
 *      bcc     L
 *  	inx
 * L:   jsr     shrax1
 *
 * may get replaced by
 *
 *      ror     a
 *
 * if X is zero on entry. For shift counts > 1, more
 *
 *      shr     a
 *
 * must be added.
 */
{
    unsigned Changes = 0;
    unsigned I;

    /* Walk over the entries */
    I = 0;
    while (I < CS_GetEntryCount (S)) {

        unsigned   Shift;
        unsigned   Count;
	CodeEntry* L[3];

      	/* Get next entry */
       	L[0] = CS_GetEntry (S, I);

     	/* Check for the sequence */
       	if ((L[0]->OPC == OP65_BCC || L[0]->OPC == OP65_JCC)    &&
	    L[0]->JumpTo != 0                                   &&
            L[0]->RI->In.RegX == 0                              &&
       	    CS_GetEntries (S, L+1, I+1, 2)                      &&
	    L[1]->OPC == OP65_INX            	       	        &&
	    L[0]->JumpTo->Owner == L[2]                         &&
	    !CS_RangeHasLabel (S, I, 2)                         &&
            L[2]->OPC == OP65_JSR                               &&
            (Shift = GetShift (L[2]->Arg)) != SHIFT_NONE        &&
            SHIFT_DIR (Shift) == SHIFT_DIR_RIGHT                &&
            (Count = SHIFT_COUNT (Shift)) > 0) {
                                                
            /* Add the replacement insn instead */
            CodeEntry* X = NewCodeEntry (OP65_ROR, AM65_ACC, "a", 0, L[2]->LI);
            CS_InsertEntry (S, X, I+3);
            while (--Count) {
                X = NewCodeEntry (OP65_LSR, AM65_ACC, "a", 0, L[2]->LI);
                CS_InsertEntry (S, X, I+4);
            }

	    /* Remove the bcs/dex/jsr */
	    CS_DelEntries (S, I, 3);

	    /* Remember, we had changes */
	    ++Changes;

	}

	/* Next entry */
	++I;

    }

    /* Return the number of changes made */
    return Changes;
}
示例#12
0
unsigned OptAdd1 (CodeSeg* S)
/* Search for the sequence
 *
 *      ldy     #xx
 *      jsr     ldaxysp
 *      jsr     pushax
 *      ldy     #yy
 *      jsr     ldaxysp
 *      jsr     tosaddax
 *
 * and replace it by:
 *
 *      ldy     #xx-1
 *      lda     (sp),y
 *      ldy     #yy-3
 *      clc
 *      adc     (sp),y
 *      pha
 *      ldy     #xx
 *      lda     (sp),y
 *      ldy     #yy-2
 *      adc     (sp),y
 *      tax
 *      pla
 */
{
    unsigned Changes = 0;

    /* Walk over the entries */
    unsigned I = 0;
    while (I < CS_GetEntryCount (S)) {

     	CodeEntry* L[6];

      	/* Get next entry */
       	L[0] = CS_GetEntry (S, I);

     	/* Check for the sequence */
       	if (L[0]->OPC == OP65_LDY            &&
	    CE_IsConstImm (L[0])             &&
	    !CS_RangeHasLabel (S, I+1, 5)    &&
       	    CS_GetEntries (S, L+1, I+1, 5)   &&
       	    CE_IsCallTo (L[1], "ldaxysp")    &&
       	    CE_IsCallTo (L[2], "pushax")     &&
       	    L[3]->OPC == OP65_LDY            &&
	    CE_IsConstImm (L[3])             &&
       	    CE_IsCallTo (L[4], "ldaxysp")    &&
       	    CE_IsCallTo (L[5], "tosaddax")) {

	    CodeEntry* X;
            const char* Arg;

       	    /* Correct the stack of the first Y register load */
	    CE_SetNumArg (L[0], L[0]->Num - 1);

            /* lda (sp),y */
            X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI);
            CS_InsertEntry (S, X, I+1);

            /* ldy #yy-3 */
	    Arg = MakeHexArg (L[3]->Num - 3);
            X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[4]->LI);
	    CS_InsertEntry (S, X, I+2);

       	    /* clc */
	    X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[5]->LI);
	    CS_InsertEntry (S, X, I+3);

	    /* adc (sp),y */
	    X = NewCodeEntry (OP65_ADC, AM65_ZP_INDY, "sp", 0, L[5]->LI);
	    CS_InsertEntry (S, X, I+4);

            /* pha */
            X = NewCodeEntry (OP65_PHA, AM65_IMP, 0, 0, L[5]->LI);
            CS_InsertEntry (S, X, I+5);

            /* ldy #xx (beware: L[0] has changed) */
	    Arg = MakeHexArg (L[0]->Num + 1);
            X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI);
	    CS_InsertEntry (S, X, I+6);

            /* lda (sp),y */
            X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI);
            CS_InsertEntry (S, X, I+7);

            /* ldy #yy-2 */
	    Arg = MakeHexArg (L[3]->Num - 2);
            X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[4]->LI);
	    CS_InsertEntry (S, X, I+8);

	    /* adc (sp),y */
	    X = NewCodeEntry (OP65_ADC, AM65_ZP_INDY, "sp", 0, L[5]->LI);
	    CS_InsertEntry (S, X, I+9);

            /* tax */
            X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[5]->LI);
            CS_InsertEntry (S, X, I+10);

            /* pla */
            X = NewCodeEntry (OP65_PLA, AM65_IMP, 0, 0, L[5]->LI);
            CS_InsertEntry (S, X, I+11);

	    /* Delete the old code */
	    CS_DelEntries (S, I+12, 5);

	    /* Remember, we had changes */
	    ++Changes;

	}

	/* Next entry */
	++I;

    }

    /* Return the number of changes made */
    return Changes;
}
示例#13
0
unsigned OptAdd4 (CodeSeg* S)
/* Search for the sequence
 *
 *  	jsr     pushax
 *      lda     xxx
 *     	ldx     yyy
 *      jsr     tosaddax
 *
 * and replace it by
 *
 *      clc
 *      adc     xxx
 *      pha
 *      txa
 *      adc     yyy
 *      tax
 *      pla
 */
{
    unsigned Changes = 0;

    /* Walk over the entries */
    unsigned I = 0;
    while (I < CS_GetEntryCount (S)) {

	CodeEntry* L[4];

      	/* Get next entry */
       	L[0] = CS_GetEntry (S, I);

     	/* Check for the sequence */
        if (CE_IsCallTo (L[0], "pushax")                        &&
       	    CS_GetEntries (S, L+1, I+1, 3)                      &&
            !CS_RangeHasLabel (S, I+1, 3)                       &&
            L[1]->OPC == OP65_LDA                               &&
            (L[1]->AM == AM65_ABS || L[1]->AM == AM65_ZP)       &&
            L[2]->OPC == OP65_LDX                               &&
            (L[2]->AM == AM65_ABS || L[2]->AM == AM65_ZP)       &&
            CE_IsCallTo (L[3], "tosaddax")) {

            CodeEntry* X;

            /* Insert new code behind the sequence */
	    X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[3]->LI);
	    CS_InsertEntry (S, X, I+4);

            /* adc xxx */
	    X = NewCodeEntry (OP65_ADC, L[1]->AM, L[1]->Arg, 0, L[3]->LI);
	    CS_InsertEntry (S, X, I+5);

            /* pha */
	    X = NewCodeEntry (OP65_PHA, AM65_IMP, 0, 0, L[3]->LI);
	    CS_InsertEntry (S, X, I+6);

            /* txa */
	    X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, L[3]->LI);
	    CS_InsertEntry (S, X, I+7);

            /* adc yyy */
	    X = NewCodeEntry (OP65_ADC, L[2]->AM, L[2]->Arg, 0, L[3]->LI);
	    CS_InsertEntry (S, X, I+8);

            /* tax */
	    X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[3]->LI);
	    CS_InsertEntry (S, X, I+9);

            /* pla */
	    X = NewCodeEntry (OP65_PLA, AM65_IMP, 0, 0, L[3]->LI);
	    CS_InsertEntry (S, X, I+10);

	    /* Delete the old code */
	    CS_DelEntries (S, I, 4);

	    /* Remember, we had changes */
	    ++Changes;

	}

	/* Next entry */
	++I;

    }

    /* Return the number of changes made */
    return Changes;
}
示例#14
0
unsigned OptAdd3 (CodeSeg* S)
/* Search for the sequence
 *
 *  	jsr     pushax
 *     	ldx     #$00
 *      lda     xxx
 *      jsr     tosaddax
 *
 * and replace it by
 *
 *      clc
 *      adc     xxx
 *      bcc     L1
 *      inx
 * L1:
 */
{
    unsigned Changes = 0;

    /* Walk over the entries */
    unsigned I = 0;
    while (I < CS_GetEntryCount (S)) {

	CodeEntry* L[5];

      	/* Get next entry */
       	L[0] = CS_GetEntry (S, I);

     	/* Check for the sequence */
        if (CE_IsCallTo (L[0], "pushax")                        &&
       	    CS_GetEntries (S, L+1, I+1, 4)                      &&
            !CS_RangeHasLabel (S, I+1, 3)                       &&
            L[1]->OPC == OP65_LDX                               &&
            CE_IsKnownImm (L[1], 0)                             &&
            L[2]->OPC == OP65_LDA                               &&
            CE_IsCallTo (L[3], "tosaddax")) {

            CodeEntry* X;
            CodeLabel* Label;

            /* Insert new code behind the sequence */
     	    X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[3]->LI);
     	    CS_InsertEntry (S, X, I+4);

            /* adc xxx */
     	    X = NewCodeEntry (OP65_ADC, L[2]->AM, L[2]->Arg, 0, L[3]->LI);
     	    CS_InsertEntry (S, X, I+5);

            /* bcc L1 */
            Label = CS_GenLabel (S, L[4]);
            X = NewCodeEntry (OP65_BCC, AM65_BRA, Label->Name, Label, L[3]->LI);
     	    CS_InsertEntry (S, X, I+6);

            /* inx */
            X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, L[3]->LI);
     	    CS_InsertEntry (S, X, I+7);

	    /* Delete the old code */
	    CS_DelEntries (S, I, 4);

	    /* Remember, we had changes */
	    ++Changes;

	}

	/* Next entry */
	++I;

    }

    /* Return the number of changes made */
    return Changes;
}
示例#15
0
unsigned OptAdd2 (CodeSeg* S)
/* Search for the sequence
 *
 *     	ldy     #xx
 *      jsr     ldaxysp
 *      ldy     #yy
 *      jsr     addeqysp
 *
 * and replace it by:
 *
 *      ldy     #xx-1
 *      lda     (sp),y
 *      ldy     #yy
 *      clc
 *      adc     (sp),y
 *      sta     (sp),y
 *      ldy     #xx
 *      lda     (sp),y
 *      ldy     #yy+1
 *      adc     (sp),y
 *      sta     (sp),y
 *
 * provided that a/x is not used later.
 */
{
    unsigned Changes = 0;

    /* Walk over the entries */
    unsigned I = 0;
    while (I < CS_GetEntryCount (S)) {

     	CodeEntry* L[4];

      	/* Get next entry */
       	L[0] = CS_GetEntry (S, I);

     	/* Check for the sequence */
	if (L[0]->OPC == OP65_LDY               &&
	    CE_IsConstImm (L[0])                &&
	    !CS_RangeHasLabel (S, I+1, 3)       &&
       	    CS_GetEntries (S, L+1, I+1, 3)   	&&
	    CE_IsCallTo (L[1], "ldaxysp")       &&
       	    L[2]->OPC == OP65_LDY               &&
	    CE_IsConstImm (L[2])                &&
       	    CE_IsCallTo (L[3], "addeqysp")      &&
       	    (GetRegInfo (S, I+4, REG_AX) & REG_AX) == 0) {

	    /* Insert new code behind the addeqysp */
	    const char* Arg;
	    CodeEntry* X;

	    /* ldy     #xx-1 */
	    Arg = MakeHexArg (L[0]->Num-1);
	    X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[0]->LI);
	    CS_InsertEntry (S, X, I+4);

	    /* lda     (sp),y */
	    X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI);
	    CS_InsertEntry (S, X, I+5);

	    /* ldy     #yy */
	    X = NewCodeEntry (OP65_LDY, AM65_IMM, L[2]->Arg, 0, L[2]->LI);
	    CS_InsertEntry (S, X, I+6);

	    /* clc */
	    X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[3]->LI);
	    CS_InsertEntry (S, X, I+7);

	    /* adc     (sp),y */
       	    X = NewCodeEntry (OP65_ADC, AM65_ZP_INDY, "sp", 0, L[3]->LI);
	    CS_InsertEntry (S, X, I+8);

	    /* sta     (sp),y */
	    X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, "sp", 0, L[3]->LI);
	    CS_InsertEntry (S, X, I+9);

	    /* ldy     #xx */
	    X = NewCodeEntry (OP65_LDY, AM65_IMM, L[0]->Arg, 0, L[0]->LI);
	    CS_InsertEntry (S, X, I+10);

	    /* lda     (sp),y */
	    X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI);
	    CS_InsertEntry (S, X, I+11);

	    /* ldy     #yy+1 */
	    Arg = MakeHexArg (L[2]->Num+1);
	    X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[2]->LI);
	    CS_InsertEntry (S, X, I+12);

	    /* adc     (sp),y */
	    X = NewCodeEntry (OP65_ADC, AM65_ZP_INDY, "sp", 0, L[3]->LI);
	    CS_InsertEntry (S, X, I+13);

	    /* sta     (sp),y */
	    X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, "sp", 0, L[3]->LI);
	    CS_InsertEntry (S, X, I+14);

	    /* Delete the old code */
	    CS_DelEntries (S, I, 4);

	    /* Remember, we had changes */
	    ++Changes;

	}

	/* Next entry */
	++I;

    }

    /* Return the number of changes made */
    return Changes;
}