X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fcodeopt.c;h=498aa0ff2b889c6fc0a14b2e2da58db40663dc6c;hb=dca99d59e51515dbf511271afa093247dbd6869a;hp=e44bf2bf5590976edc1afe29ed3c09e4ed3f4ccc;hpb=5dcebbccb65924197ac9078fb90b6d08bd3f6823;p=cc65 diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index e44bf2bf5..498aa0ff2 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -69,7 +69,7 @@ #include "error.h" #include "global.h" #include "output.h" - +#include "symtab.h" /*****************************************************************************/ @@ -613,7 +613,116 @@ static unsigned OptStackPtrOps (CodeSeg* S) return Changes; } +static unsigned OptGotoSPAdj (CodeSeg* S) +/* Optimize SP adjustment for forward 'goto' */ +{ + unsigned Changes = 0; + unsigned I; + + /* Walk over the entries */ + I = 0; + while (I < CS_GetEntryCount (S)) { + + CodeEntry* L[10], *X; + unsigned short adjustment; + const char* Arg; + + /* Get next entry */ + L[0] = CS_GetEntry (S, I); + + /* Check for the sequence generated by g_lateadjustSP */ + if (L[0]->OPC == OP65_PHA && + CS_GetEntries (S, L+1, I+1, 9) && + L[1]->OPC == OP65_LDA && + L[1]->AM == AM65_ABS && + L[2]->OPC == OP65_CLC && + L[3]->OPC == OP65_ADC && + strcmp (L[3]->Arg, "sp") == 0 && + L[6]->OPC == OP65_ADC && + strcmp (L[6]->Arg, "sp+1") == 0 && + L[9]->OPC == OP65_JMP) { + adjustment = FindSPAdjustment (L[1]->Arg); + + if (adjustment == 0) { + /* No SP adjustment needed, remove the whole sequence */ + CS_DelEntries (S, I, 9); + } + else if (adjustment >= 65536 - 8) { + /* If adjustment is in range [-8, 0) we use decsp* calls */ + char Buf[20]; + adjustment = 65536 - adjustment; + xsprintf (Buf, sizeof (Buf), "decsp%u", adjustment); + X = NewCodeEntry (OP65_JSR, AM65_ABS, Buf, 0, L[1]->LI); + CS_InsertEntry (S, X, I + 9); + + /* Delete the old code */ + CS_DelEntries (S, I, 9); + } + else if (adjustment >= 65536 - 255) { + /* For range [-255, -8) we have ldy #, jsr subysp */ + adjustment = 65536 - adjustment; + Arg = MakeHexArg (adjustment); + X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI); + CS_InsertEntry (S, X, I + 9); + X = NewCodeEntry (OP65_JSR, AM65_ABS, "subysp", 0, L[1]->LI); + CS_InsertEntry (S, X, I + 10); + + /* Delete the old code */ + CS_DelEntries (S, I, 9); + } + else if (adjustment > 255) { + /* For ranges [-32768, 255) and (255, 32767) the only modification + ** is to replace the absolute with immediate addressing + */ + Arg = MakeHexArg (adjustment & 0xff); + X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, L[1]->LI); + CS_InsertEntry (S, X, I + 1); + Arg = MakeHexArg (adjustment >> 8); + X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, L[5]->LI); + CS_InsertEntry (S, X, I + 6); + + /* Delete the old code */ + CS_DelEntry (S, I + 2); + CS_DelEntry (S, I + 6); + } + else if (adjustment > 8) { + /* For range (8, 255] we have ldy #, jsr addysp */ + Arg = MakeHexArg (adjustment & 0xff); + X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI); + CS_InsertEntry (S, X, I + 9); + X = NewCodeEntry (OP65_JSR, AM65_ABS, "addysp", 0, L[1]->LI); + CS_InsertEntry (S, X, I + 10); + + /* Delete the old code */ + CS_DelEntries (S, I, 9); + } + else { + /* If adjustment is in range (0, 8] we use incsp* calls */ + char Buf[20]; + xsprintf (Buf, sizeof (Buf), "incsp%u", adjustment); + X = NewCodeEntry (OP65_JSR, AM65_ABS, Buf, 0, L[1]->LI); + CS_InsertEntry (S, X, I + 9); + + /* Delete the old code */ + CS_DelEntries (S, I, 9); + } + /* Regenerate register info */ + CS_GenRegInfo (S); + + /* Remember we had changes */ + Changes++; + + } else { + + /* Next entry */ + ++I; + } + } + + /* Return the number of changes made */ + return Changes; +} /*****************************************************************************/ /* struct OptFunc */ @@ -675,6 +784,7 @@ static OptFunc DOptDeadCode = { OptDeadCode, "OptDeadCode", 100, 0, static OptFunc DOptDeadJumps = { OptDeadJumps, "OptDeadJumps", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptDecouple = { OptDecouple, "OptDecouple", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptDupLoads = { OptDupLoads, "OptDupLoads", 0, 0, 0, 0, 0, 0 }; +static OptFunc DOptGotoSPAdj = { OptGotoSPAdj, "OptGotoSPAdj", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptIndLoads1 = { OptIndLoads1, "OptIndLoads1", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptIndLoads2 = { OptIndLoads2, "OptIndLoads2", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptJumpCascades = { OptJumpCascades, "OptJumpCascades", 100, 0, 0, 0, 0, 0 }; @@ -704,6 +814,8 @@ static OptFunc DOptPtrLoad14 = { OptPtrLoad14, "OptPtrLoad14", 108, 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 DOptPtrLoad18 = { OptPtrLoad18, "OptPtrLoad18", 100, 0, 0, 0, 0, 0 }; +static OptFunc DOptPtrLoad19 = { OptPtrLoad19, "OptPtrLoad19", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrStore1 = { OptPtrStore1, "OptPtrStore1", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrStore2 = { OptPtrStore2, "OptPtrStore2", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrStore3 = { OptPtrStore3, "OptPtrStore3", 100, 0, 0, 0, 0, 0 }; @@ -774,6 +886,7 @@ static OptFunc* OptFuncs[] = { &DOptDeadJumps, &DOptDecouple, &DOptDupLoads, + &DOptGotoSPAdj, &DOptIndLoads1, &DOptIndLoads2, &DOptJumpCascades, @@ -794,6 +907,8 @@ static OptFunc* OptFuncs[] = { &DOptPtrLoad15, &DOptPtrLoad16, &DOptPtrLoad17, + &DOptPtrLoad18, + &DOptPtrLoad19, &DOptPtrLoad2, &DOptPtrLoad3, &DOptPtrLoad4, @@ -870,7 +985,7 @@ static OptFunc* GetOptFunc (const char* Name) OptFunc* F = FindOptFunc (Name); if (F == 0) { /* Not found */ - AbEnd ("Optimization step `%s' not found", Name); + AbEnd ("Optimization step '%s' not found", Name); } return F; } @@ -1057,10 +1172,10 @@ static void WriteDebugOutput (CodeSeg* S, const char* Step) /* Output a header line */ if (Step == 0) { /* Initial output */ - WriteOutput ("Initial code for function `%s':\n", + WriteOutput ("Initial code for function '%s':\n", S->Func? S->Func->Name : ""); } else { - WriteOutput ("Code after applying `%s':\n", Step); + WriteOutput ("Code after applying '%s':\n", Step); } /* Output the code segment */ @@ -1122,6 +1237,7 @@ static unsigned RunOptGroup1 (CodeSeg* S) { unsigned Changes = 0; + Changes += RunOptFunc (S, &DOptGotoSPAdj, 1); Changes += RunOptFunc (S, &DOptStackPtrOps, 5); Changes += RunOptFunc (S, &DOptPtrStore1, 1); Changes += RunOptFunc (S, &DOptPtrStore2, 1); @@ -1133,6 +1249,8 @@ static unsigned RunOptGroup1 (CodeSeg* S) Changes += RunOptFunc (S, &DOptPtrLoad4, 1); Changes += RunOptFunc (S, &DOptPtrLoad5, 1); Changes += RunOptFunc (S, &DOptPtrLoad6, 1); + Changes += RunOptFunc (S, &DOptPtrLoad18, 1); /* Before OptPtrLoad7 */ + Changes += RunOptFunc (S, &DOptPtrLoad19, 1); /* Before OptPtrLoad7 */ Changes += RunOptFunc (S, &DOptPtrLoad7, 1); Changes += RunOptFunc (S, &DOptPtrLoad11, 1); Changes += RunOptFunc (S, &DOptPtrLoad12, 1); @@ -1400,7 +1518,7 @@ void RunOpt (CodeSeg* S) /* Print the name of the function we are working on */ if (S->Func) { - Print (stdout, 1, "Running optimizer for function `%s'\n", S->Func->Name); + Print (stdout, 1, "Running optimizer for function '%s'\n", S->Func->Name); } else { Print (stdout, 1, "Running optimizer for global code segment\n"); }