X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcc65%2Fcodeopt.c;h=e26e747f42c2d8451d847e85015fbed322fac581;hb=d6c50c18267881ae4ad4117edeb81e6c36d33f44;hp=a7b46ca1b8258f9d2b11bc8f62fa8036cd96a5cf;hpb=eea99d2a1d1cfefb8eabbc5aea6438c8dad9d8ac;p=cc65 diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index a7b46ca1b..e26e747f4 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -7,7 +7,7 @@ /* */ /* */ /* (C) 2001-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -42,7 +42,6 @@ #include "cpu.h" #include "print.h" #include "xmalloc.h" -#include "xsprintf.h" /* cc65 */ #include "asmlabel.h" @@ -138,8 +137,7 @@ static unsigned OptShift1 (CodeSeg* S) static unsigned OptShift2 (CodeSeg* S) /* A call to the shraxN routine may get replaced by one or more lsr insns - * if the value of X is not used later, or if the value of X is known and - * zero. + * if the value of X is zero. */ { unsigned Changes = 0; @@ -160,7 +158,7 @@ static unsigned OptShift2 (CodeSeg* S) strncmp (E->Arg, "shrax", 5) == 0 && strlen (E->Arg) == 6 && IsDigit (E->Arg[5]) && - (E->RI->In.RegX == 0 || !RegXUsed (S, I+1))) { + E->RI->In.RegX == 0) { /* Insert shift insns */ unsigned Count = E->Arg[5] - '0'; @@ -461,6 +459,20 @@ static unsigned OptPtrStore1 (CodeSeg* S) * subop * ldy yyy * sta (ptr1),y + * + * In case a/x is loaded from the register bank before the pushax, we can even + * use the register bank instead of ptr1. + */ +/* + * jsr pushax + * ldy xxx + * jsr ldauidx + * ldx #$00 + * lda (zp),y + * subop + * ldy yyy + * sta (zp),y + * jsr staspidx */ { unsigned Changes = 0; @@ -491,28 +503,66 @@ static unsigned OptPtrStore1 (CodeSeg* S) CE_IsCallTo (L[4+K], "staspidx") && !CE_HasLabel (L[4+K])) { + + const char* RegBank = 0; + const char* ZPLoc = "ptr1"; CodeEntry* X; - /* Create and insert the stores */ - X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI); - CS_InsertEntry (S, X, I+1); - X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI); - CS_InsertEntry (S, X, I+2); + /* Get the preceeding two instructions and check them. We check + * for: + * lda regbank+n + * ldx regbank+n+1 + */ + if (I > 1) { + CodeEntry* P[2]; + P[0] = CS_GetEntry (S, I-2); + P[1] = CS_GetEntry (S, I-1); + if (P[0]->OPC == OP65_LDA && + P[0]->AM == AM65_ZP && + P[1]->OPC == OP65_LDX && + P[1]->AM == AM65_ZP && + !CE_HasLabel (P[1]) && + strncmp (P[0]->Arg, "regbank+", 8) == 0) { + + unsigned Len = strlen (P[0]->Arg); + + if (strncmp (P[0]->Arg, P[1]->Arg, Len) == 0 && + P[1]->Arg[Len+0] == '+' && + P[1]->Arg[Len+1] == '1' && + P[1]->Arg[Len+2] == '\0') { + + /* Ok, found. Use the name of the register bank */ + RegBank = ZPLoc = P[0]->Arg; + } + } + } - /* Insert the load from ptr1 */ + /* Insert the load via the zp pointer */ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[3]->LI); - CS_InsertEntry (S, X, I+5); - X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[2]->LI); - CS_InsertEntry (S, X, I+6); + CS_InsertEntry (S, X, I+3); + X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, ZPLoc, 0, L[2]->LI); + CS_InsertEntry (S, X, I+4); - /* Insert the store through ptr1 */ - X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, "ptr1", 0, L[3]->LI); - CS_InsertEntry (S, X, I+8+K); + /* Insert the store through the zp pointer */ + X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, ZPLoc, 0, L[3]->LI); + CS_InsertEntry (S, X, I+6+K); /* Delete the old code */ - CS_DelEntry (S, I+9+K); /* jsr spaspidx */ - CS_DelEntry (S, I+4); /* jsr ldauidx */ + CS_DelEntry (S, I+7+K); /* jsr spaspidx */ + CS_DelEntry (S, I+2); /* jsr ldauidx */ + + /* Create and insert the stores into the zp pointer if needed */ + if (RegBank == 0) { + X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI); + CS_InsertEntry (S, X, I+1); + X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI); + CS_InsertEntry (S, X, I+2); + } + + /* Delete more old code. Do it here to keep a label attached to + * entry I in place. + */ CS_DelEntry (S, I); /* jsr pushax */ /* Remember, we had changes */ @@ -978,7 +1028,7 @@ static unsigned OptPtrLoad4 (CodeSeg* S) L[1]->OPC == OP65_LDX && L[1]->AM == AM65_IMM && !CE_HasLabel (L[1]) && - L[2]->OPC == OP65_LDY && + L[2]->OPC == OP65_LDY && CE_KnownImm (L[2]) && !CE_HasLabel (L[2]) && L[3]->OPC == OP65_CLC && @@ -1008,7 +1058,7 @@ static unsigned OptPtrLoad4 (CodeSeg* S) CodeEntry* X; char* Label; - /* Add the lda */ + /* Add the lda */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[4]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+3); @@ -1028,7 +1078,7 @@ static unsigned OptPtrLoad4 (CodeSeg* S) xfree (Label); /* Remove the old code */ - CS_DelEntries (S, I, 2); + CS_DelEntries (S, I, 2); CS_DelEntries (S, I+5, 6); /* Remember, we had changes */ @@ -1048,6 +1098,152 @@ static unsigned OptPtrLoad4 (CodeSeg* S) static unsigned OptPtrLoad5 (CodeSeg* S) +/* Search for the sequence: + * + * lda regbank+n + * ldx regbank+n+1 + * sta regsave + * stx regsave+1 + * clc + * adc #$01 + * bcc L0005 + * inx + * L: sta regbank+n + * stx regbank+n+1 + * lda regsave + * ldx regsave+1 + * ldy #$00 + * jsr ldauidx + * + * and replace it by: + * + * ldy #$00 + * ldx #$00 + * lda (regbank+n),y + * inc regbank+n + * bne L1 + * inc regbank+n+1 + * L1: tay <- only if flags are used + * + * This function must execute before OptPtrLoad5! + * + */ +{ + unsigned Changes = 0; + + /* Walk over the entries */ + unsigned I = 0; + while (I < CS_GetEntryCount (S)) { + + CodeEntry* L[15]; + unsigned Len; + + /* Get next entry */ + L[0] = CS_GetEntry (S, I); + + /* Check for the sequence */ + if (L[0]->OPC == OP65_LDA && + L[0]->AM == AM65_ZP && + strncmp (L[0]->Arg, "regbank+", 8) == 0 && + (Len = strlen (L[0]->Arg)) > 0 && + CS_GetEntries (S, L+1, I+1, 14) && + !CS_RangeHasLabel (S, I+1, 7) && + !CS_RangeHasLabel (S, I+9, 5) && + L[1]->OPC == OP65_LDX && + L[1]->AM == AM65_ZP && + strncmp (L[1]->Arg, L[0]->Arg, Len) == 0 && + strcmp (L[1]->Arg+Len, "+1") == 0 && + L[2]->OPC == OP65_STA && + L[2]->AM == AM65_ZP && + strcmp (L[2]->Arg, "regsave") == 0 && + L[3]->OPC == OP65_STX && + L[3]->AM == AM65_ZP && + strcmp (L[3]->Arg, "regsave+1") == 0 && + L[4]->OPC == OP65_CLC && + L[5]->OPC == OP65_ADC && + CE_KnownImm (L[5]) && + L[5]->Num == 1 && + L[6]->OPC == OP65_BCC && + L[6]->JumpTo != 0 && + L[6]->JumpTo->Owner == L[8] && + L[7]->OPC == OP65_INX && + L[8]->OPC == OP65_STA && + L[8]->AM == AM65_ZP && + strcmp (L[8]->Arg, L[0]->Arg) == 0 && + L[9]->OPC == OP65_STX && + L[9]->AM == AM65_ZP && + strcmp (L[9]->Arg, L[1]->Arg) == 0 && + L[10]->OPC == OP65_LDA && + L[10]->AM == AM65_ZP && + strcmp (L[10]->Arg, "regsave") == 0 && + L[11]->OPC == OP65_LDX && + L[11]->AM == AM65_ZP && + strcmp (L[11]->Arg, "regsave+1") == 0 && + L[12]->OPC == OP65_LDY && + CE_KnownImm (L[12]) && + CE_IsCallTo (L[13], "ldauidx")) { + + CodeEntry* X; + CodeLabel* Label; + + /* Check if the instruction following the sequence uses the flags + * set by the load. If so, insert a test of the value in the + * accumulator. + */ + if (CE_UseLoadFlags (L[14])) { + X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[13]->LI); + CS_InsertEntry (S, X, I+14); + } + + /* Attach a label to L[14]. This may be either the just inserted + * instruction, or the one following the sequence. + */ + Label = CS_GenLabel (S, L[14]); + + /* ldy #$xx */ + X = NewCodeEntry (OP65_LDY, AM65_IMM, L[12]->Arg, 0, L[12]->LI); + CS_InsertEntry (S, X, I+14); + + /* ldx #$xx */ + X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[13]->LI); + CS_InsertEntry (S, X, I+15); + + /* lda (regbank+n),y */ + X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[13]->LI); + CS_InsertEntry (S, X, I+16); + + /* inc regbank+n */ + X = NewCodeEntry (OP65_INC, AM65_ZP, L[0]->Arg, 0, L[5]->LI); + CS_InsertEntry (S, X, I+17); + + /* bne ... */ + X = NewCodeEntry (OP65_BNE, AM65_BRA, Label->Name, Label, L[6]->LI); + CS_InsertEntry (S, X, I+18); + + /* inc regbank+n+1 */ + X = NewCodeEntry (OP65_INC, AM65_ZP, L[1]->Arg, 0, L[7]->LI); + CS_InsertEntry (S, X, I+19); + + /* Delete the old code */ + CS_DelEntries (S, I, 14); + + /* Remember, we had changes */ + ++Changes; + + } + + /* Next entry */ + ++I; + + } + + /* Return the number of changes made */ + return Changes; +} + + + +static unsigned OptPtrLoad6 (CodeSeg* S) /* Search for the sequence: * * lda zp @@ -1115,7 +1311,7 @@ static unsigned OptPtrLoad5 (CodeSeg* S) -static unsigned OptPtrLoad6 (CodeSeg* S) +static unsigned OptPtrLoad7 (CodeSeg* S) /* Search for the sequence: * * lda zp @@ -1193,7 +1389,7 @@ static unsigned OptPtrLoad6 (CodeSeg* S) -static unsigned OptPtrLoad7 (CodeSeg* S) +static unsigned OptPtrLoad8 (CodeSeg* S) /* Search for the sequence * * ldy ... @@ -1207,7 +1403,7 @@ static unsigned OptPtrLoad7 (CodeSeg* S) * ldx #$00 * lda (ptr1),y * - * This step must be execute *after* OptPtrLoad1! + * This step must be executed *after* OptPtrLoad1! */ { unsigned Changes = 0; @@ -1535,13 +1731,14 @@ static OptFunc DOptAdd4 = { OptAdd4, "OptAdd4", 100, 0, static OptFunc DOptAdd5 = { OptAdd5, "OptAdd5", 40, 0, 0, 0, 0, 0 }; static OptFunc DOptBoolTrans = { OptBoolTrans, "OptBoolTrans", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptBranchDist = { OptBranchDist, "OptBranchDist", 0, 0, 0, 0, 0, 0 }; -static OptFunc DOptCmp1 = { OptCmp1, "OptCmp1", 85, 0, 0, 0, 0, 0 }; -static OptFunc DOptCmp2 = { OptCmp2, "OptCmp2", 75, 0, 0, 0, 0, 0 }; +static OptFunc DOptCmp1 = { OptCmp1, "OptCmp1", 42, 0, 0, 0, 0, 0 }; +static OptFunc DOptCmp2 = { OptCmp2, "OptCmp2", 85, 0, 0, 0, 0, 0 }; static OptFunc DOptCmp3 = { OptCmp3, "OptCmp3", 75, 0, 0, 0, 0, 0 }; -static OptFunc DOptCmp4 = { OptCmp4, "OptCmp4", 100, 0, 0, 0, 0, 0 }; +static OptFunc DOptCmp4 = { OptCmp4, "OptCmp4", 75, 0, 0, 0, 0, 0 }; static OptFunc DOptCmp5 = { OptCmp5, "OptCmp5", 100, 0, 0, 0, 0, 0 }; -static OptFunc DOptCmp6 = { OptCmp6, "OptCmp6", 85, 0, 0, 0, 0, 0 }; -static OptFunc DOptCmp7 = { OptCmp7, "OptCmp7", 50, 0, 0, 0, 0, 0 }; +static OptFunc DOptCmp6 = { OptCmp6, "OptCmp6", 100, 0, 0, 0, 0, 0 }; +static OptFunc DOptCmp7 = { OptCmp7, "OptCmp7", 85, 0, 0, 0, 0, 0 }; +static OptFunc DOptCmp8 = { OptCmp8, "OptCmp8", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptCondBranches = { OptCondBranches, "OptCondBranches", 80, 0, 0, 0, 0, 0 }; static OptFunc DOptDeadCode = { OptDeadCode, "OptDeadCode", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptDeadJumps = { OptDeadJumps, "OptDeadJumps", 100, 0, 0, 0, 0, 0 }; @@ -1564,9 +1761,10 @@ static OptFunc DOptPtrLoad1 = { OptPtrLoad1, "OptPtrLoad1", 100, 0, static OptFunc DOptPtrLoad2 = { OptPtrLoad2, "OptPtrLoad2", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad3 = { OptPtrLoad3, "OptPtrLoad3", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad4 = { OptPtrLoad4, "OptPtrLoad4", 100, 0, 0, 0, 0, 0 }; -static OptFunc DOptPtrLoad5 = { OptPtrLoad5, "OptPtrLoad5", 65, 0, 0, 0, 0, 0 }; -static OptFunc DOptPtrLoad6 = { OptPtrLoad6, "OptPtrLoad6", 86, 0, 0, 0, 0, 0 }; -static OptFunc DOptPtrLoad7 = { OptPtrLoad7, "OptPtrLoad7", 100, 0, 0, 0, 0, 0 }; +static OptFunc DOptPtrLoad5 = { OptPtrLoad5, "OptPtrLoad5", 50, 0, 0, 0, 0, 0 }; +static OptFunc DOptPtrLoad6 = { OptPtrLoad6, "OptPtrLoad6", 65, 0, 0, 0, 0, 0 }; +static OptFunc DOptPtrLoad7 = { OptPtrLoad7, "OptPtrLoad7", 86, 0, 0, 0, 0, 0 }; +static OptFunc DOptPtrLoad8 = { OptPtrLoad8, "OptPtrLoad8", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrStore1 = { OptPtrStore1, "OptPtrStore1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrStore2 = { OptPtrStore2, "OptPtrStore2", 40, 0, 0, 0, 0, 0 }; static OptFunc DOptPush1 = { OptPush1, "OptPush1", 65, 0, 0, 0, 0, 0 }; @@ -1611,6 +1809,7 @@ static OptFunc* OptFuncs[] = { &DOptCmp5, &DOptCmp6, &DOptCmp7, + &DOptCmp8, &DOptCondBranches, &DOptDeadCode, &DOptDeadJumps, @@ -1633,6 +1832,7 @@ static OptFunc* OptFuncs[] = { &DOptPtrLoad5, &DOptPtrLoad6, &DOptPtrLoad7, + &DOptPtrLoad8, &DOptPtrStore1, &DOptPtrStore2, &DOptPush1, @@ -1857,7 +2057,7 @@ static unsigned RunOptFunc (CodeSeg* S, OptFunc* F, unsigned Max) /* Don't run the function if it is disabled or if it is prohibited by the * code size factor */ - if (F->Disabled || F->CodeSizeFactor > CodeSizeFactor) { + if (F->Disabled || F->CodeSizeFactor > S->CodeSizeFactor) { return 0; } @@ -1900,6 +2100,7 @@ static unsigned RunOptGroup1 (CodeSeg* S) Changes += RunOptFunc (S, &DOptPtrLoad4, 1); Changes += RunOptFunc (S, &DOptPtrLoad5, 1); Changes += RunOptFunc (S, &DOptPtrLoad6, 1); + Changes += RunOptFunc (S, &DOptPtrLoad7, 1); Changes += RunOptFunc (S, &DOptNegAX1, 1); Changes += RunOptFunc (S, &DOptNegAX2, 1); Changes += RunOptFunc (S, &DOptNegAX3, 1); @@ -1907,13 +2108,13 @@ static unsigned RunOptGroup1 (CodeSeg* S) Changes += RunOptFunc (S, &DOptAdd1, 1); Changes += RunOptFunc (S, &DOptAdd2, 1); Changes += RunOptFunc (S, &DOptAdd3, 1); + Changes += RunOptFunc (S, &DOptStore4, 1); Changes += RunOptFunc (S, &DOptShift1, 1); Changes += RunOptFunc (S, &DOptShift2, 1); Changes += RunOptFunc (S, &DOptShift3, 1); Changes += RunOptFunc (S, &DOptStore1, 1); Changes += RunOptFunc (S, &DOptStore2, 5); Changes += RunOptFunc (S, &DOptStore3, 5); - Changes += RunOptFunc (S, &DOptStore4, 1); /* Return the number of changes */ return Changes; @@ -1950,7 +2151,7 @@ static unsigned RunOptGroup3 (CodeSeg* S) do { C = 0; - C += RunOptFunc (S, &DOptPtrLoad7, 1); + C += RunOptFunc (S, &DOptPtrLoad8, 1); C += RunOptFunc (S, &DOptNegA1, 1); C += RunOptFunc (S, &DOptNegA2, 1); C += RunOptFunc (S, &DOptSub1, 1); @@ -1973,6 +2174,7 @@ static unsigned RunOptGroup3 (CodeSeg* S) C += RunOptFunc (S, &DOptCmp5, 1); C += RunOptFunc (S, &DOptCmp6, 1); C += RunOptFunc (S, &DOptCmp7, 1); + C += RunOptFunc (S, &DOptCmp8, 1); C += RunOptFunc (S, &DOptTest1, 1); C += RunOptFunc (S, &DOptLoad1, 1); C += RunOptFunc (S, &DOptUnusedLoads, 1); @@ -1998,7 +2200,7 @@ static unsigned RunOptGroup4 (CodeSeg* S) { unsigned Changes = 0; - if (CPU >= CPU_65C02) { + if (CPUIsets[CPU] & CPU_ISET_65SC02) { Changes += RunOptFunc (S, &DOpt65C02BitOps, 1); Changes += RunOptFunc (S, &DOpt65C02Ind, 1); Changes += RunOptFunc (S, &DOpt65C02Stores, 1); @@ -2042,7 +2244,7 @@ static unsigned RunOptGroup6 (CodeSeg* S) unsigned Changes = 0; unsigned C; - if (CodeSizeFactor <= 100) { + if (S->CodeSizeFactor <= 100) { /* Optimize for size, that is replace operations by shorter ones, even * if this does hinder further optimizations (no problem since we're * done soon). @@ -2091,7 +2293,7 @@ void RunOpt (CodeSeg* S) const char* StatFileName; /* If we shouldn't run the optimizer, bail out */ - if (!Optimize) { + if (!S->Optimize) { return; }