X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fcodeopt.c;h=30ffd605428e25b36ad5fd080d8f01566cfd3ac4;hb=112ae0e3db511ddd92e769c11328646ebe2a6240;hp=cdf0c193ff955c3c3c9e107293745e8ca2900964;hpb=b208b7e3b15b8b69e9ad3c5fc1f422101a2e30ea;p=cc65 diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index cdf0c193f..30ffd6054 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2001-2009 Ullrich von Bassewitz */ -/* Roemerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2001-2010, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -527,6 +527,60 @@ static unsigned OptLoad1 (CodeSeg* S) +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* E; + + /* Get next entry */ + E = CS_GetEntry (S, I); + + /* Check for the sequence */ + if (CE_IsCallTo (E, "ldaxysp")) { + + CodeEntry* X; + + /* lda (sp),y */ + X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, E->LI); + CS_InsertEntry (S, X, I+1); + + /* tax */ + X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, E->LI); + CS_InsertEntry (S, X, I+2); + + /* dey */ + X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, E->LI); + CS_InsertEntry (S, X, I+3); + + /* lda (sp),y */ + X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, E->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; +} + + + /*****************************************************************************/ /* Optimize stores through pointers */ /*****************************************************************************/ @@ -817,6 +871,121 @@ static unsigned OptPtrStore2 (CodeSeg* S) +static unsigned OptPtrStore3 (CodeSeg* S) +/* Search for the sequence: + * + * lda #<(label+0) + * ldx #>(label+0) + * ldy aaa + * clc + * adc (sp),y + * bcc L + * inx + * L: jsr pushax + * ldx #$00 + * lda yyy + * ldy #$00 + * jsr staspidx + * + * and replace it by: + * + * ldy aaa + * ldx #$00 + * lda (sp),y + * tay + * lda yyy + * sta label,y + */ +{ + unsigned Changes = 0; + + /* Walk over the entries */ + unsigned I = 0; + while (I < CS_GetEntryCount (S)) { + + CodeEntry* L[12]; + 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_IMM && + CS_GetEntries (S, L+1, I+1, 11) && + L[1]->OPC == OP65_LDX && + L[1]->AM == AM65_IMM && + L[2]->OPC == OP65_LDY && + L[3]->OPC == OP65_CLC && + L[4]->OPC == OP65_ADC && + L[4]->AM == AM65_ZP_INDY && + strcmp (L[4]->Arg, "sp") == 0 && + (L[5]->OPC == OP65_BCC || L[5]->OPC == OP65_JCC) && + L[5]->JumpTo != 0 && + L[5]->JumpTo->Owner == L[7] && + L[6]->OPC == OP65_INX && + CE_IsCallTo (L[7], "pushax") && + L[8]->OPC == OP65_LDX && + L[9]->OPC == OP65_LDA && + L[10]->OPC == OP65_LDY && + CE_IsKnownImm (L[10], 0) && + CE_IsCallTo (L[11], "staspidx") && + !CS_RangeHasLabel (S, I+1, 6) && + !CS_RangeHasLabel (S, I+8, 4) && + /* Check the label last because this is quite costly */ + (Len = strlen (L[0]->Arg)) > 3 && + L[0]->Arg[0] == '<' && + L[0]->Arg[1] == '(' && + strlen (L[1]->Arg) == Len && + L[1]->Arg[0] == '>' && + memcmp (L[0]->Arg+1, L[1]->Arg+1, Len-1) == 0) { + + CodeEntry* X; + char* Label; + + /* We will create all the new stuff behind the current one so + * we keep the line references. + */ + X = NewCodeEntry (OP65_LDY, L[2]->AM, L[2]->Arg, 0, L[2]->LI); + CS_InsertEntry (S, X, I+12); + + X = NewCodeEntry (OP65_LDX, L[8]->AM, L[8]->Arg, 0, L[8]->LI); + CS_InsertEntry (S, X, I+13); + + X = NewCodeEntry (OP65_LDA, L[4]->AM, L[4]->Arg, 0, L[4]->LI); + CS_InsertEntry (S, X, I+14); + + X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[4]->LI); + CS_InsertEntry (S, X, I+15); + + X = NewCodeEntry (OP65_LDA, L[9]->AM, L[9]->Arg, 0, L[9]->LI); + CS_InsertEntry (S, X, I+16); + + Label = memcpy (xmalloc (Len-2), L[0]->Arg+2, Len-3); + Label[Len-3] = '\0'; + X = NewCodeEntry (OP65_STA, AM65_ABSY, Label, 0, L[11]->LI); + CS_InsertEntry (S, X, I+17); + xfree (Label); + + /* Remove the old code */ + CS_DelEntries (S, I, 12); + + /* Remember, we had changes */ + ++Changes; + + } + + /* Next entry */ + ++I; + + } + + /* Return the number of changes made */ + return Changes; +} + + + /*****************************************************************************/ /* Decouple operations */ /*****************************************************************************/ @@ -1213,6 +1382,7 @@ static OptFunc DOptJumpTarget1 = { OptJumpTarget1, "OptJumpTarget1", 100, 0, static OptFunc DOptJumpTarget2 = { OptJumpTarget2, "OptJumpTarget2", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptJumpTarget3 = { OptJumpTarget3, "OptJumpTarget3", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptLoad1 = { OptLoad1, "OptLoad1", 100, 0, 0, 0, 0, 0 }; +static OptFunc DOptLoad2 = { OptLoad2, "OptLoad2", 200, 0, 0, 0, 0, 0 }; static OptFunc DOptRTS = { OptRTS, "OptRTS", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptRTSJumps1 = { OptRTSJumps1, "OptRTSJumps1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptRTSJumps2 = { OptRTSJumps2, "OptRTSJumps2", 100, 0, 0, 0, 0, 0 }; @@ -1231,14 +1401,15 @@ static OptFunc DOptPtrLoad5 = { OptPtrLoad5, "OptPtrLoad5", 50, 0, static OptFunc DOptPtrLoad6 = { OptPtrLoad6, "OptPtrLoad6", 60, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad7 = { OptPtrLoad7, "OptPtrLoad7", 140, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad11 = { OptPtrLoad11, "OptPtrLoad11", 92, 0, 0, 0, 0, 0 }; -static OptFunc DOptPtrLoad12 = { OptPtrLoad12, "OptPtrLoad12", 50, 0, 0, 0, 0, 0 }; -static OptFunc DOptPtrLoad13 = { OptPtrLoad13, "OptPtrLoad13", 65, 0, 0, 0, 0, 0 }; +static OptFunc DOptPtrLoad12 = { OptPtrLoad12, "OptPtrLoad12", 50, 0, 0, 0, 0, 0 }; +static OptFunc DOptPtrLoad13 = { OptPtrLoad13, "OptPtrLoad13", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad14 = { OptPtrLoad14, "OptPtrLoad14", 108, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad15 = { OptPtrLoad15, "OptPtrLoad15", 86, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad16 = { OptPtrLoad16, "OptPtrLoad16", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad17 = { OptPtrLoad17, "OptPtrLoad17", 190, 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 DOptPtrStore3 = { OptPtrStore3, "OptPtrStore3", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptPush1 = { OptPush1, "OptPush1", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptPush2 = { OptPush2, "OptPush2", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptPushPop = { OptPushPop, "OptPushPop", 0, 0, 0, 0, 0, 0 }; @@ -1251,7 +1422,7 @@ static OptFunc DOptSize2 = { OptSize2, "OptSize2", 100, 0, static OptFunc DOptStackOps = { OptStackOps, "OptStackOps", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptStackPtrOps = { OptStackPtrOps, "OptStackPtrOps", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptStore1 = { OptStore1, "OptStore1", 70, 0, 0, 0, 0, 0 }; -static OptFunc DOptStore2 = { OptStore2, "OptStore2", 220, 0, 0, 0, 0, 0 }; +static OptFunc DOptStore2 = { OptStore2, "OptStore2", 115, 0, 0, 0, 0, 0 }; static OptFunc DOptStore3 = { OptStore3, "OptStore3", 120, 0, 0, 0, 0, 0 }; static OptFunc DOptStore4 = { OptStore4, "OptStore4", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptStore5 = { OptStore5, "OptStore5", 100, 0, 0, 0, 0, 0 }; @@ -1259,7 +1430,8 @@ static OptFunc DOptStoreLoad = { OptStoreLoad, "OptStoreLoad", 0, 0, static OptFunc DOptSub1 = { OptSub1, "OptSub1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptSub2 = { OptSub2, "OptSub2", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptSub3 = { OptSub3, "OptSub3", 100, 0, 0, 0, 0, 0 }; -static OptFunc DOptTest1 = { OptTest1, "OptTest1", 100, 0, 0, 0, 0, 0 }; +static OptFunc DOptTest1 = { OptTest1, "OptTest1", 65, 0, 0, 0, 0, 0 }; +static OptFunc DOptTest2 = { OptTest2, "OptTest2", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptTransfers1 = { OptTransfers1, "OptTransfers1", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptTransfers2 = { OptTransfers2, "OptTransfers2", 60, 0, 0, 0, 0, 0 }; static OptFunc DOptTransfers3 = { OptTransfers3, "OptTransfers3", 65, 0, 0, 0, 0, 0 }; @@ -1303,6 +1475,7 @@ static OptFunc* OptFuncs[] = { &DOptJumpTarget2, &DOptJumpTarget3, &DOptLoad1, + &DOptLoad2, &DOptNegA1, &DOptNegA2, &DOptNegAX1, @@ -1326,6 +1499,7 @@ static OptFunc* OptFuncs[] = { &DOptPtrLoad7, &DOptPtrStore1, &DOptPtrStore2, + &DOptPtrStore3, &DOptPush1, &DOptPush2, &DOptPushPop, @@ -1350,6 +1524,7 @@ static OptFunc* OptFuncs[] = { &DOptSub2, &DOptSub3, &DOptTest1, + &DOptTest2, &DOptTransfers1, &DOptTransfers2, &DOptTransfers3, @@ -1592,6 +1767,7 @@ static unsigned RunOptGroup1 (CodeSeg* S) Changes += RunOptFunc (S, &DOptStackPtrOps, 5); Changes += RunOptFunc (S, &DOptPtrStore1, 1); Changes += RunOptFunc (S, &DOptPtrStore2, 1); + Changes += RunOptFunc (S, &DOptPtrStore3, 1); Changes += RunOptFunc (S, &DOptAdd3, 1); /* Before OptPtrLoad5! */ Changes += RunOptFunc (S, &DOptPtrLoad1, 1); Changes += RunOptFunc (S, &DOptPtrLoad2, 1); @@ -1614,6 +1790,11 @@ static unsigned RunOptGroup1 (CodeSeg* S) Changes += RunOptFunc (S, &DOptAdd1, 1); Changes += RunOptFunc (S, &DOptAdd2, 1); Changes += RunOptFunc (S, &DOptAdd4, 1); + Changes += RunOptFunc (S, &DOptAdd5, 1); + Changes += RunOptFunc (S, &DOptAdd6, 1); + Changes += RunOptFunc (S, &DOptAdd6, 1); + Changes += RunOptFunc (S, &DOptSub1, 1); + Changes += RunOptFunc (S, &DOptSub3, 1); Changes += RunOptFunc (S, &DOptStore4, 1); Changes += RunOptFunc (S, &DOptStore5, 1); Changes += RunOptFunc (S, &DOptShift1, 1); @@ -1661,12 +1842,12 @@ static unsigned RunOptGroup3 (CodeSeg* S) C += RunOptFunc (S, &DOptNegA1, 1); C += RunOptFunc (S, &DOptNegA2, 1); + C += RunOptFunc (S, &DOptStackOps, 1); C += RunOptFunc (S, &DOptSub1, 1); C += RunOptFunc (S, &DOptSub2, 1); C += RunOptFunc (S, &DOptSub3, 1); C += RunOptFunc (S, &DOptAdd5, 1); C += RunOptFunc (S, &DOptAdd6, 1); - C += RunOptFunc (S, &DOptStackOps, 1); C += RunOptFunc (S, &DOptJumpCascades, 1); C += RunOptFunc (S, &DOptDeadJumps, 1); C += RunOptFunc (S, &DOptRTS, 1); @@ -1674,7 +1855,6 @@ static unsigned RunOptGroup3 (CodeSeg* S) C += RunOptFunc (S, &DOptBoolTrans, 1); C += RunOptFunc (S, &DOptJumpTarget1, 1); C += RunOptFunc (S, &DOptJumpTarget2, 1); - C += RunOptFunc (S, &DOptJumpTarget3, 1); C += RunOptFunc (S, &DOptCondBranches1, 1); C += RunOptFunc (S, &DOptCondBranches2, 1); C += RunOptFunc (S, &DOptRTSJumps1, 1); @@ -1689,6 +1869,7 @@ static unsigned RunOptGroup3 (CodeSeg* S) C += RunOptFunc (S, &DOptCmp9, 1); C += RunOptFunc (S, &DOptTest1, 1); C += RunOptFunc (S, &DOptLoad1, 1); + C += RunOptFunc (S, &DOptJumpTarget3, 1); /* After OptCondBranches2 */ C += RunOptFunc (S, &DOptUnusedLoads, 1); C += RunOptFunc (S, &DOptUnusedStores, 1); C += RunOptFunc (S, &DOptDupLoads, 1); @@ -1712,6 +1893,27 @@ static unsigned RunOptGroup3 (CodeSeg* S) static unsigned RunOptGroup4 (CodeSeg* S) +/* Run another round of pattern replacements. These are done late, since there + * may be better replacements before. + */ +{ + unsigned Changes = 0; + + /* Repeat some of the steps here */ + Changes += RunOptFunc (S, &DOptPush1, 1); + Changes += RunOptFunc (S, &DOptPush2, 1); + Changes += RunOptFunc (S, &DOptUnusedLoads, 1); + Changes += RunOptFunc (S, &DOptTest2, 1); + Changes += RunOptFunc (S, &DOptTransfers2, 1); + Changes += RunOptFunc (S, &DOptLoad2, 1); + + /* Return the number of changes */ + return Changes; +} + + + +static unsigned RunOptGroup5 (CodeSeg* S) /* 65C02 specific optimizations. */ { unsigned Changes = 0; @@ -1735,25 +1937,6 @@ static unsigned RunOptGroup4 (CodeSeg* S) -static unsigned RunOptGroup5 (CodeSeg* S) -/* Run another round of pattern replacements. These are done late, since there - * may be better replacements before. - */ -{ - unsigned Changes = 0; - - Changes += RunOptFunc (S, &DOptPush1, 1); - Changes += RunOptFunc (S, &DOptPush2, 1); - /* Repeat some of the other optimizations now */ - Changes += RunOptFunc (S, &DOptUnusedLoads, 1); - Changes += RunOptFunc (S, &DOptTransfers2, 1); - - /* Return the number of changes */ - return Changes; -} - - - static unsigned RunOptGroup6 (CodeSeg* S) /* This one is quite special. It tries to replace "lda (sp),y" by "lda (sp,x)". * The latter is ony cycle slower, but if we're able to remove the necessary