コード例 #1
0
ファイル: reginfo.c プロジェクト: AntiheroSoftware/cc65
static void RC_Dump1 (FILE* F, const char* Desc, short Val)
/* Dump one register value */
{
    if (RegValIsKnown (Val)) {
        fprintf (F, "%s=$%02X ", Desc, Val);
    } else {
        fprintf (F, "%s=$XX ", Desc);
    }
}
コード例 #2
0
ファイル: codeopt.c プロジェクト: coyxc/cc65
static unsigned OptLoad1 (CodeSeg* S)
/* Search for a call to ldaxysp where X is not used later and replace it by
** a load of just the A register.
*/
{
    unsigned I;
    unsigned Changes = 0;

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

        CodeEntry* E;

        /* Get next entry */
        E = CS_GetEntry (S, I);

        /* Check for the sequence */
        if (CE_IsCallTo (E, "ldaxysp")          &&
            RegValIsKnown (E->RI->In.RegY)      &&
            !RegXUsed (S, I+1)) {

            CodeEntry* X;

            /* Reload the Y register */
            const char* Arg = MakeHexArg (E->RI->In.RegY - 1);
            X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
            CS_InsertEntry (S, X, I+1);

            /* Load from stack */
            X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, E->LI);
            CS_InsertEntry (S, X, I+2);

            /* 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;
}
コード例 #3
0
ファイル: codeopt.c プロジェクト: coyxc/cc65
static unsigned IsDecSP (const CodeEntry* E)
/* Check if this is an insn that decrements the stack pointer. If so, return
** the decrement. If not, return zero.
** The function expects E to be a subroutine call.
*/
{
    if (strncmp (E->Arg, "decsp", 5) == 0) {
        if (E->Arg[5] >= '1' && E->Arg[5] <= '8') {
            return (E->Arg[5] - '0');
        }
    } else if (strcmp (E->Arg, "subysp") == 0 && RegValIsKnown (E->RI->In.RegY)) {
        return E->RI->In.RegY;
    }

    /* If we come here, it's not a decsp op */
    return 0;
}
コード例 #4
0
ファイル: coptstore.c プロジェクト: Aliandrana/cc65
unsigned OptStore3 (CodeSeg* S)
/* Search for a call to steaxysp. If the eax register is not used later, and
** the value is constant, just use the A register and store directly into the
** stack.
*/
{
    unsigned I;
    unsigned Changes = 0;

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

        /* Get next entry */
        CodeEntry* E = CS_GetEntry (S, I);

        /* Get the input registers */
        const RegInfo* RI = E->RI;

        /* Check for the call */
        if (CE_IsCallTo (E, "steaxysp")         &&
            RegValIsKnown (RI->In.RegA)         &&
            RegValIsKnown (RI->In.RegX)         &&
            RegValIsKnown (RI->In.RegY)         &&
            RegValIsKnown (RI->In.SRegLo)       &&
            RegValIsKnown (RI->In.SRegHi)       &&
            !RegEAXUsed (S, I+1)) {

            /* Get the register values */
            unsigned char A = (unsigned char) RI->In.RegA;
            unsigned char X = (unsigned char) RI->In.RegX;
            unsigned char Y = (unsigned char) RI->In.RegY;
            unsigned char L = (unsigned char) RI->In.SRegLo;
            unsigned char H = (unsigned char) RI->In.SRegHi;

            /* Setup other variables */
            unsigned    Done = 0;
            CodeEntry*  N;
            unsigned    IP = I + 1;     /* Insertion point */

            /* Replace the store. We will not remove the loads, since this is
            ** too complex and will be done by other optimizer steps.
            */
            N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (A), 0, E->LI);
            CS_InsertEntry (S, N, IP++);
            InsertStore (S, &IP, E->LI);
            Done |= 0x01;

            /* Check if we can store one of the other bytes */
            if (A == X && (Done & 0x02) == 0) {
                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+1), 0, E->LI);
                CS_InsertEntry (S, N, IP++);
                InsertStore (S, &IP, E->LI);
                Done |= 0x02;
            }
            if (A == L && (Done & 0x04) == 0) {
                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+2), 0, E->LI);
                CS_InsertEntry (S, N, IP++);
                InsertStore (S, &IP, E->LI);
                Done |= 0x04;
            }
            if (A == H && (Done & 0x08) == 0) {
                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+3), 0, E->LI);
                CS_InsertEntry (S, N, IP++);
                InsertStore (S, &IP, E->LI);
                Done |= 0x08;
            }

            /* Store the second byte */
            if ((Done & 0x02) == 0) {
                N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (X), 0, E->LI);
                CS_InsertEntry (S, N, IP++);
                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+1), 0, E->LI);
                CS_InsertEntry (S, N, IP++);
                InsertStore (S, &IP, E->LI);
                Done |= 0x02;
            }

            /* Check if we can store one of the other bytes */
            if (X == L && (Done & 0x04) == 0) {
                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+2), 0, E->LI);
                CS_InsertEntry (S, N, IP++);
                InsertStore (S, &IP, E->LI);
                Done |= 0x04;
            }
            if (X == H && (Done & 0x08) == 0) {
                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+3), 0, E->LI);
                CS_InsertEntry (S, N, IP++);
                InsertStore (S, &IP, E->LI);
                Done |= 0x08;
            }

            /* Store the third byte */
            if ((Done & 0x04) == 0) {
                N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (L), 0, E->LI);
                CS_InsertEntry (S, N, IP++);
                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+2), 0, E->LI);
                CS_InsertEntry (S, N, IP++);
                InsertStore (S, &IP, E->LI);
                Done |= 0x04;
            }

            /* Check if we can store one of the other bytes */
            if (L == H && (Done & 0x08) == 0) {
                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+3), 0, E->LI);
                CS_InsertEntry (S, N, IP++);
                InsertStore (S, &IP, E->LI);
                Done |= 0x08;
            }

            /* Store the fourth byte */
            if ((Done & 0x08) == 0) {
                N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (H), 0, E->LI);
                CS_InsertEntry (S, N, IP++);
                N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+3), 0, E->LI);
                CS_InsertEntry (S, N, IP++);
                InsertStore (S, &IP, E->LI);
                Done |= 0x08;
            }

            /* Remove the call */
            CS_DelEntry (S, I);

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

        }

        /* Next entry */
        ++I;

    }

    /* Return the number of changes made */
    return Changes;
}
コード例 #5
0
ファイル: codeopt.c プロジェクト: coyxc/cc65
static unsigned OptDecouple (CodeSeg* S)
/* Decouple operations, that is, do the following replacements:
**
**   dex        -> ldx #imm
**   inx        -> ldx #imm
**   dey        -> ldy #imm
**   iny        -> ldy #imm
**   tax        -> ldx #imm
**   txa        -> lda #imm
**   tay        -> ldy #imm
**   tya        -> lda #imm
**   lda zp     -> lda #imm
**   ldx zp     -> ldx #imm
**   ldy zp     -> ldy #imm
**
** Provided that the register values are known of course.
*/
{
    unsigned Changes = 0;
    unsigned I;

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

        const char* Arg;

        /* Get next entry and it's input register values */
        CodeEntry* E = CS_GetEntry (S, I);
        const RegContents* In = &E->RI->In;

        /* Assume we have no replacement */
        CodeEntry* X = 0;

        /* Check the instruction */
        switch (E->OPC) {

            case OP65_DEA:
                if (RegValIsKnown (In->RegA)) {
                    Arg = MakeHexArg ((In->RegA - 1) & 0xFF);
                    X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI);
                }
                break;

            case OP65_DEX:
                if (RegValIsKnown (In->RegX)) {
                    Arg = MakeHexArg ((In->RegX - 1) & 0xFF);
                    X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI);
                }
                break;

            case OP65_DEY:
                if (RegValIsKnown (In->RegY)) {
                    Arg = MakeHexArg ((In->RegY - 1) & 0xFF);
                    X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
                }
                break;

            case OP65_INA:
                if (RegValIsKnown (In->RegA)) {
                    Arg = MakeHexArg ((In->RegA + 1) & 0xFF);
                    X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI);
                }
                break;

            case OP65_INX:
                if (RegValIsKnown (In->RegX)) {
                    Arg = MakeHexArg ((In->RegX + 1) & 0xFF);
                    X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI);
                }
                break;

            case OP65_INY:
                if (RegValIsKnown (In->RegY)) {
                    Arg = MakeHexArg ((In->RegY + 1) & 0xFF);
                    X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
                }
                break;

            case OP65_LDA:
                if (E->AM == AM65_ZP) {
                    switch (GetKnownReg (E->Use & REG_ZP, In)) {
                        case REG_TMP1:
                            Arg = MakeHexArg (In->Tmp1);
                            X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI);
                            break;

                        case REG_PTR1_LO:
                            Arg = MakeHexArg (In->Ptr1Lo);
                            X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI);
                            break;

                        case REG_PTR1_HI:
                            Arg = MakeHexArg (In->Ptr1Hi);
                            X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI);
                            break;

                        case REG_SREG_LO:
                            Arg = MakeHexArg (In->SRegLo);
                            X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI);
                            break;

                        case REG_SREG_HI:
                            Arg = MakeHexArg (In->SRegHi);
                            X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI);
                            break;
                    }
                }
                break;

            case OP65_LDX:
                if (E->AM == AM65_ZP) {
                    switch (GetKnownReg (E->Use & REG_ZP, In)) {
                        case REG_TMP1:
                            Arg = MakeHexArg (In->Tmp1);
                            X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI);
                            break;

                        case REG_PTR1_LO:
                            Arg = MakeHexArg (In->Ptr1Lo);
                            X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI);
                            break;

                        case REG_PTR1_HI:
                            Arg = MakeHexArg (In->Ptr1Hi);
                            X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI);
                            break;

                        case REG_SREG_LO:
                            Arg = MakeHexArg (In->SRegLo);
                            X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI);
                            break;

                        case REG_SREG_HI:
                            Arg = MakeHexArg (In->SRegHi);
                            X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI);
                            break;
                    }
                }
                break;

            case OP65_LDY:
                if (E->AM == AM65_ZP) {
                    switch (GetKnownReg (E->Use, In)) {
                        case REG_TMP1:
                            Arg = MakeHexArg (In->Tmp1);
                            X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
                            break;

                        case REG_PTR1_LO:
                            Arg = MakeHexArg (In->Ptr1Lo);
                            X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
                            break;

                        case REG_PTR1_HI:
                            Arg = MakeHexArg (In->Ptr1Hi);
                            X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
                            break;

                        case REG_SREG_LO:
                            Arg = MakeHexArg (In->SRegLo);
                            X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
                            break;

                        case REG_SREG_HI:
                            Arg = MakeHexArg (In->SRegHi);
                            X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
                            break;
                    }
                }
                break;

            case OP65_TAX:
                if (E->RI->In.RegA >= 0) {
                    Arg = MakeHexArg (In->RegA);
                    X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI);
                }
                break;

            case OP65_TAY:
                if (E->RI->In.RegA >= 0) {
                    Arg = MakeHexArg (In->RegA);
                    X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI);
                }
                break;

            case OP65_TXA:
                if (E->RI->In.RegX >= 0) {
                    Arg = MakeHexArg (In->RegX);
                    X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI);
                }
                break;

            case OP65_TYA:
                if (E->RI->In.RegY >= 0) {
                    Arg = MakeHexArg (In->RegY);
                    X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI);
                }
                break;

            default:
                /* Avoid gcc warnings */
                break;

        }

        /* Insert the replacement if we have one */
        if (X) {
            CS_InsertEntry (S, X, I+1);
            CS_DelEntry (S, I);
            ++Changes;
        }

        /* Next entry */
        ++I;

    }

    /* Return the number of changes made */
    return Changes;
}
コード例 #6
0
ファイル: coptpush.c プロジェクト: eakmeister/cc65
unsigned OptPush1 (CodeSeg* S)
/* Given a sequence
 *
 *     jsr     ldaxysp
 *     jsr     pushax
 *
 * If a/x are not used later, and Y is known, replace that by
 *
 *     ldy     #xx+2
 *     jsr     pushwysp
 *
 * saving 3 bytes and several cycles.
 */
{
    unsigned I;
    unsigned Changes = 0;

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

     	CodeEntry* L[2];

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

     	/* Check for the sequence */
       	if (CE_IsCallTo (L[0], "ldaxysp")               &&
            RegValIsKnown (L[0]->RI->In.RegY)           &&
            L[0]->RI->In.RegY < 0xFE                    &&
            (L[1] = CS_GetNextEntry (S, I)) != 0        &&
            !CE_HasLabel (L[1])                         &&
       	    CE_IsCallTo (L[1], "pushax")                &&
       	    !RegAXUsed (S, I+2)) {

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

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

	    /* jsr pushwysp */
	    X = NewCodeEntry (OP65_JSR, AM65_ABS, "pushwysp", 0, L[1]->LI);
	    CS_InsertEntry (S, X, I+3);

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

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

	}

	/* Next entry */
	++I;

    }

    /* Return the number of changes made */
    return Changes;
}
コード例 #7
0
ファイル: codeent.c プロジェクト: Aliandrana/cc65
void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
/* Generate register info for this instruction. If an old info exists, it is
** overwritten.
*/
{
    /* Pointers to the register contents */
    RegContents* In;
    RegContents* Out;

    /* Function register usage */
    unsigned short Use, Chg;

    /* If we don't have a register info struct, allocate one. */
    if (E->RI == 0) {
        E->RI = NewRegInfo (InputRegs);
    } else {
        if (InputRegs) {
            E->RI->In  = *InputRegs;
        } else {
            RC_Invalidate (&E->RI->In);
        }
        E->RI->Out2 = E->RI->Out = E->RI->In;
    }

    /* Get pointers to the register contents */
    In  = &E->RI->In;
    Out = &E->RI->Out;

    /* Handle the different instructions */
    switch (E->OPC) {

        case OP65_ADC:
            /* We don't know the value of the carry, so the result is
            ** always unknown.
            */
            Out->RegA = UNKNOWN_REGVAL;
            break;

        case OP65_AND:
            if (RegValIsKnown (In->RegA)) {
                if (CE_IsConstImm (E)) {
                    Out->RegA = In->RegA & (short) E->Num;
                } else if (E->AM == AM65_ZP) {
                    switch (GetKnownReg (E->Use & REG_ZP, In)) {
                        case REG_TMP1:
                            Out->RegA = In->RegA & In->Tmp1;
                            break;
                        case REG_PTR1_LO:
                            Out->RegA = In->RegA & In->Ptr1Lo;
                            break;
                        case REG_PTR1_HI:
                            Out->RegA = In->RegA & In->Ptr1Hi;
                            break;
                        case REG_SREG_LO:
                            Out->RegA = In->RegA & In->SRegLo;
                            break;
                        case REG_SREG_HI:
                            Out->RegA = In->RegA & In->SRegHi;
                            break;
                        default:
                            Out->RegA = UNKNOWN_REGVAL;
                            break;
                    }
                } else {
                    Out->RegA = UNKNOWN_REGVAL;
                }
            } else if (CE_IsKnownImm (E, 0)) {
                /* A and $00 does always give zero */
                Out->RegA = 0;
            }
            break;

        case OP65_ASL:
            if (E->AM == AM65_ACC && RegValIsKnown (In->RegA)) {
                Out->RegA = (In->RegA << 1) & 0xFF;
            } else if (E->AM == AM65_ZP) {
                switch (GetKnownReg (E->Chg & REG_ZP, In)) {
                    case REG_TMP1:
                        Out->Tmp1 = (In->Tmp1 << 1) & 0xFF;
                        break;
                    case REG_PTR1_LO:
                        Out->Ptr1Lo = (In->Ptr1Lo << 1) & 0xFF;
                        break;
                    case REG_PTR1_HI:
                        Out->Ptr1Hi = (In->Ptr1Hi << 1) & 0xFF;
                        break;
                    case REG_SREG_LO:
                        Out->SRegLo = (In->SRegLo << 1) & 0xFF;
                        break;
                    case REG_SREG_HI:
                        Out->SRegHi = (In->SRegHi << 1) & 0xFF;
                        break;
                }
            } else if (E->AM == AM65_ZPX) {
                /* Invalidates all ZP registers */
                RC_InvalidateZP (Out);
            }
            break;

        case OP65_BCC:
            break;

        case OP65_BCS:
            break;

        case OP65_BEQ:
            break;

        case OP65_BIT:
            break;

        case OP65_BMI:
            break;

        case OP65_BNE:
            break;

        case OP65_BPL:
            break;

        case OP65_BRA:
            break;

        case OP65_BRK:
            break;

        case OP65_BVC:
            break;

        case OP65_BVS:
            break;

        case OP65_CLC:
            break;

        case OP65_CLD:
            break;

        case OP65_CLI:
            break;

        case OP65_CLV:
            break;

        case OP65_CMP:
            break;

        case OP65_CPX:
            break;

        case OP65_CPY:
            break;

        case OP65_DEA:
            if (RegValIsKnown (In->RegA)) {
                Out->RegA = (In->RegA - 1) & 0xFF;
            }
            break;

        case OP65_DEC:
            if (E->AM == AM65_ACC && RegValIsKnown (In->RegA)) {
                Out->RegA = (In->RegA - 1) & 0xFF;
            } else if (E->AM == AM65_ZP) {
                switch (GetKnownReg (E->Chg & REG_ZP, In)) {
                    case REG_TMP1:
                        Out->Tmp1 = (In->Tmp1 - 1) & 0xFF;
                        break;
                    case REG_PTR1_LO:
                        Out->Ptr1Lo = (In->Ptr1Lo - 1) & 0xFF;
                        break;
                    case REG_PTR1_HI:
                        Out->Ptr1Hi = (In->Ptr1Hi - 1) & 0xFF;
                        break;
                    case REG_SREG_LO:
                        Out->SRegLo = (In->SRegLo - 1) & 0xFF;
                        break;
                    case REG_SREG_HI:
                        Out->SRegHi = (In->SRegHi - 1) & 0xFF;
                        break;
                }
            } else if (E->AM == AM65_ZPX) {
                /* Invalidates all ZP registers */
                RC_InvalidateZP (Out);
            }
            break;

        case OP65_DEX:
            if (RegValIsKnown (In->RegX)) {
                Out->RegX = (In->RegX - 1) & 0xFF;
            }
            break;

        case OP65_DEY:
            if (RegValIsKnown (In->RegY)) {
                Out->RegY = (In->RegY - 1) & 0xFF;
            }
            break;

        case OP65_EOR:
            if (RegValIsKnown (In->RegA)) {
                if (CE_IsConstImm (E)) {
                    Out->RegA = In->RegA ^ (short) E->Num;
                } else if (E->AM == AM65_ZP) {
                    switch (GetKnownReg (E->Use & REG_ZP, In)) {
                        case REG_TMP1:
                            Out->RegA = In->RegA ^ In->Tmp1;
                            break;
                        case REG_PTR1_LO:
                            Out->RegA = In->RegA ^ In->Ptr1Lo;
                            break;
                        case REG_PTR1_HI:
                            Out->RegA = In->RegA ^ In->Ptr1Hi;
                            break;
                        case REG_SREG_LO:
                            Out->RegA = In->RegA ^ In->SRegLo;
                            break;
                        case REG_SREG_HI:
                            Out->RegA = In->RegA ^ In->SRegHi;
                            break;
                        default:
                            Out->RegA = UNKNOWN_REGVAL;
                            break;
                    }
                } else {
                    Out->RegA = UNKNOWN_REGVAL;
                }
            }
            break;

        case OP65_INA:
            if (RegValIsKnown (In->RegA)) {
                Out->RegA = (In->RegA + 1) & 0xFF;
            }
            break;

        case OP65_INC:
            if (E->AM == AM65_ACC && RegValIsKnown (In->RegA)) {
                Out->RegA = (In->RegA + 1) & 0xFF;
            } else if (E->AM == AM65_ZP) {
                switch (GetKnownReg (E->Chg & REG_ZP, In)) {
                    case REG_TMP1:
                        Out->Tmp1 = (In->Tmp1 + 1) & 0xFF;
                        break;
                    case REG_PTR1_LO:
                        Out->Ptr1Lo = (In->Ptr1Lo + 1) & 0xFF;
                        break;
                    case REG_PTR1_HI:
                        Out->Ptr1Hi = (In->Ptr1Hi + 1) & 0xFF;
                        break;
                    case REG_SREG_LO:
                        Out->SRegLo = (In->SRegLo + 1) & 0xFF;
                        break;
                    case REG_SREG_HI:
                        Out->SRegHi = (In->SRegHi + 1) & 0xFF;
                        break;
                }
            } else if (E->AM == AM65_ZPX) {
                /* Invalidates all ZP registers */
                RC_InvalidateZP (Out);
            }
            break;

        case OP65_INX:
            if (RegValIsKnown (In->RegX)) {
                Out->RegX = (In->RegX + 1) & 0xFF;
            }
            break;

        case OP65_INY:
            if (RegValIsKnown (In->RegY)) {
                Out->RegY = (In->RegY + 1) & 0xFF;
            }
            break;

        case OP65_JCC:
            break;

        case OP65_JCS:
            break;

        case OP65_JEQ:
            break;

        case OP65_JMI:
            break;

        case OP65_JMP:
            break;

        case OP65_JNE:
            break;

        case OP65_JPL:
            break;

        case OP65_JSR:
            /* Get the code info for the function */
            GetFuncInfo (E->Arg, &Use, &Chg);
            if (Chg & REG_A) {
                Out->RegA = UNKNOWN_REGVAL;
            }
            if (Chg & REG_X) {
                Out->RegX = UNKNOWN_REGVAL;
            }
            if (Chg & REG_Y) {
                Out->RegY = UNKNOWN_REGVAL;
            }
            if (Chg & REG_TMP1) {
                Out->Tmp1 = UNKNOWN_REGVAL;
            }
            if (Chg & REG_PTR1_LO) {
                Out->Ptr1Lo = UNKNOWN_REGVAL;
            }
            if (Chg & REG_PTR1_HI) {
                Out->Ptr1Hi = UNKNOWN_REGVAL;
            }
            if (Chg & REG_SREG_LO) {
                Out->SRegLo = UNKNOWN_REGVAL;
            }
            if (Chg & REG_SREG_HI) {
                Out->SRegHi = UNKNOWN_REGVAL;
            }
            /* ## FIXME: Quick hack for some known functions: */
            if (strcmp (E->Arg, "complax") == 0) {
                if (RegValIsKnown (In->RegA)) {
                    Out->RegA = (In->RegA ^ 0xFF);
                }
                if (RegValIsKnown (In->RegX)) {
                    Out->RegX = (In->RegX ^ 0xFF);
                }
            } else if (strcmp (E->Arg, "tosandax") == 0) {
                if (In->RegA == 0) {
                    Out->RegA = 0;
                }
                if (In->RegX == 0) {
                    Out->RegX = 0;
                }
            } else if (strcmp (E->Arg, "tosaslax") == 0) {
                if (RegValIsKnown (In->RegA) && (In->RegA & 0x0F) >= 8) {
                    printf ("Hey!\n");
                    Out->RegA = 0;
                }
            } else if (strcmp (E->Arg, "tosorax") == 0) {
                if (In->RegA == 0xFF) {
                    Out->RegA = 0xFF;
                }
                if (In->RegX == 0xFF) {
                    Out->RegX = 0xFF;
                }
            } else if (strcmp (E->Arg, "tosshlax") == 0) {
                if ((In->RegA & 0x0F) >= 8) {
                    Out->RegA = 0;
                }
            } else if (FindBoolCmpCond (E->Arg) != CMP_INV ||
                       FindTosCmpCond (E->Arg) != CMP_INV) {
                /* Result is boolean value, so X is zero on output */
                Out->RegX = 0;
            }
            break;

        case OP65_JVC:
            break;

        case OP65_JVS:
            break;

        case OP65_LDA:
            if (CE_IsConstImm (E)) {
                Out->RegA = (unsigned char) E->Num;
            } else if (E->AM == AM65_ZP) {
                switch (GetKnownReg (E->Use & REG_ZP, In)) {
                    case REG_TMP1:
                        Out->RegA = In->Tmp1;
                        break;
                    case REG_PTR1_LO:
                        Out->RegA = In->Ptr1Lo;
                        break;
                    case REG_PTR1_HI:
                        Out->RegA = In->Ptr1Hi;
                        break;
                    case REG_SREG_LO:
                        Out->RegA = In->SRegLo;
                        break;
                    case REG_SREG_HI:
                        Out->RegA = In->SRegHi;
                        break;
                    default:
                        Out->RegA = UNKNOWN_REGVAL;
                        break;
                }
            } else {
                /* A is now unknown */
                Out->RegA = UNKNOWN_REGVAL;
            }
            break;

        case OP65_LDX:
            if (CE_IsConstImm (E)) {
                Out->RegX = (unsigned char) E->Num;
            } else if (E->AM == AM65_ZP) {
                switch (GetKnownReg (E->Use & REG_ZP, In)) {
                    case REG_TMP1:
                        Out->RegX = In->Tmp1;
                        break;
                    case REG_PTR1_LO:
                        Out->RegX = In->Ptr1Lo;
                        break;
                    case REG_PTR1_HI:
                        Out->RegX = In->Ptr1Hi;
                        break;
                    case REG_SREG_LO:
                        Out->RegX = In->SRegLo;
                        break;
                    case REG_SREG_HI:
                        Out->RegX = In->SRegHi;
                        break;
                    default:
                        Out->RegX = UNKNOWN_REGVAL;
                        break;
                }
            } else {
                /* X is now unknown */
                Out->RegX = UNKNOWN_REGVAL;
            }
            break;

        case OP65_LDY:
            if (CE_IsConstImm (E)) {
                Out->RegY = (unsigned char) E->Num;
            } else if (E->AM == AM65_ZP) {
                switch (GetKnownReg (E->Use & REG_ZP, In)) {
                    case REG_TMP1:
                        Out->RegY = In->Tmp1;
                        break;
                    case REG_PTR1_LO:
                        Out->RegY = In->Ptr1Lo;
                        break;
                    case REG_PTR1_HI:
                        Out->RegY = In->Ptr1Hi;
                        break;
                    case REG_SREG_LO:
                        Out->RegY = In->SRegLo;
                        break;
                    case REG_SREG_HI:
                        Out->RegY = In->SRegHi;
                        break;
                    default:
                        Out->RegY = UNKNOWN_REGVAL;
                        break;
                }
            } else {
                /* Y is now unknown */
                Out->RegY = UNKNOWN_REGVAL;
            }
            break;

        case OP65_LSR:
            if (E->AM == AM65_ACC && RegValIsKnown (In->RegA)) {
                Out->RegA = (In->RegA >> 1) & 0xFF;
            } else if (E->AM == AM65_ZP) {
コード例 #8
0
ファイル: coptsize.c プロジェクト: eakmeister/cc65
unsigned OptSize2 (CodeSeg* S)
/* Do size optimization by using shorter code sequences, even if this
 * introduces relations between instructions. This step must be one of the
 * last steps, because it makes further work much more difficult.
 */
{
    unsigned Changes = 0;
    unsigned I;

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

      	/* Get next entry */
       	CodeEntry* E = CS_GetEntry (S, I);

        /* Get the input registers */
        const RegContents* In = &E->RI->In;

	/* Assume we have no replacement */
	CodeEntry* X = 0;

	/* Check the instruction */
	switch (E->OPC) {

	    case OP65_LDA:
	        if (CE_IsConstImm (E)) {
		    short Val = (short) E->Num;
		    if (Val == In->RegX) {
		    	X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, E->LI);
		    } else if (Val == In->RegY) {
		    	X = NewCodeEntry (OP65_TYA, AM65_IMP, 0, 0, E->LI);
		    } else if (RegValIsKnown (In->RegA) && (CPUIsets[CPU] & CPU_ISET_65SC02) != 0) {
		    	if (Val == ((In->RegA - 1) & 0xFF)) {
		     	    X = NewCodeEntry (OP65_DEA, AM65_IMP, 0, 0, E->LI);
		    	} else if (Val == ((In->RegA + 1) & 0xFF)) {
		    	    X = NewCodeEntry (OP65_INA, AM65_IMP, 0, 0, E->LI);
	      	    	}
		    }
	      	}
	        break;

	    case OP65_LDX:
	        if (CE_IsConstImm (E)) {
		    short Val = (short) E->Num;
		    if (RegValIsKnown (In->RegX) && Val == ((In->RegX - 1) & 0xFF)) {
			X = NewCodeEntry (OP65_DEX, AM65_IMP, 0, 0, E->LI);
       	       	    } else if (RegValIsKnown (In->RegX) && Val == ((In->RegX + 1) & 0xFF)) {
			X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, E->LI);
		    } else if (Val == In->RegA) {
			X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, E->LI);
                    }
		}
	        break;

       	    case OP65_LDY:
	        if (CE_IsConstImm (E)) {
		    short Val = (short) E->Num;
		    if (RegValIsKnown (In->RegY) && Val == ((In->RegY - 1) & 0xFF)) {
			X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, E->LI);
		    } else if (RegValIsKnown (In->RegY) && Val == ((In->RegY + 1) & 0xFF)) {
			X = NewCodeEntry (OP65_INY, AM65_IMP, 0, 0, E->LI);
		    } else if (Val == In->RegA) {
			X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, E->LI);
		    }
		}
	        break;

	    default:
	        /* Avoid gcc warnings */
	        break;

	}

	/* Insert the replacement if we have one */
	if (X) {
	    CS_InsertEntry (S, X, I+1);
	    CS_DelEntry (S, I);
	    ++Changes;
	}

	/* Next entry */
	++I;

    }

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