X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fcodeopt.c;h=0a5eacc141a8f077b6fdc9d4b7d1bd9cd9e1fc16;hb=49905d74bd10e7fa469fed9dbe172d691853229f;hp=51dbfcec2d485457cfd762e7aa72fdf0729f3819;hpb=8dc74f33daa8b3d24bb90fbc4fab36d501c328e0;p=cc65 diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index 51dbfcec2..0a5eacc14 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -57,6 +57,7 @@ #include "coptptrload.h" #include "coptptrstore.h" #include "coptpush.h" +#include "coptshift.h" #include "coptsize.h" #include "coptstop.h" #include "coptstore.h" @@ -68,537 +69,6 @@ -/*****************************************************************************/ -/* Data */ -/*****************************************************************************/ - - - -/* Shift types */ -enum { - SHIFT_NONE, - SHIFT_ASR_1, - SHIFT_ASL_1, - SHIFT_LSR_1, - SHIFT_LSL_1 -}; - - - -/*****************************************************************************/ -/* Optimize shifts */ -/*****************************************************************************/ - - - -static unsigned OptShift1 (CodeSeg* S) -/* A call to the shlaxN routine may get replaced by one or more asl insns - * if the value of X is not used later. If X is used later, but it is zero - * on entry and it's a shift by one, it may get replaced by: - * - * asl a - * bcc L1 - * inx - * L1: - * - */ -{ - unsigned Changes = 0; - unsigned I; - - /* Generate register info */ - CS_GenRegInfo (S); - - /* Walk over the entries */ - I = 0; - while (I < CS_GetEntryCount (S)) { - - CodeEntry* N; - CodeEntry* X; - CodeLabel* L; - - /* Get next entry */ - CodeEntry* E = CS_GetEntry (S, I); - - /* Check for the sequence */ - if (E->OPC == OP65_JSR && - (strncmp (E->Arg, "shlax", 5) == 0 || - strncmp (E->Arg, "aslax", 5) == 0) && - strlen (E->Arg) == 6 && - IsDigit (E->Arg[5])) { - - if (!RegXUsed (S, I+1)) { - - /* Insert shift insns */ - unsigned Count = E->Arg[5] - '0'; - while (Count--) { - X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, E->LI); - CS_InsertEntry (S, X, I+1); - } - - /* Delete the call to shlax */ - CS_DelEntry (S, I); - - /* Remember, we had changes */ - ++Changes; - - } else if (E->RI->In.RegX == 0 && - E->Arg[5] == '1' && - (N = CS_GetNextEntry (S, I)) != 0) { - - /* asl a */ - X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, E->LI); - CS_InsertEntry (S, X, I+1); - - /* bcc L1 */ - L = CS_GenLabel (S, N); - X = NewCodeEntry (OP65_BCC, AM65_BRA, L->Name, L, E->LI); - CS_InsertEntry (S, X, I+2); - - /* inx */ - X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, E->LI); - CS_InsertEntry (S, X, I+3); - - /* Delete the call to shlax */ - CS_DelEntry (S, I); - - /* Remember, we had changes */ - ++Changes; - } - - } - - /* Next entry */ - ++I; - - } - - /* Free the register info */ - CS_FreeRegInfo (S); - - /* Return the number of changes made */ - return Changes; -} - - - -static unsigned OptShift2(CodeSeg* S) -/* A call to the asrax1 routines may get replaced by something simpler, if - * X is not used later: - * - * cmp #$80 - * ror a - * - */ -{ - unsigned Changes = 0; - unsigned I; - - /* Generate register info */ - CS_GenRegInfo (S); - - /* Walk over the entries */ - I = 0; - while (I < CS_GetEntryCount (S)) { - - unsigned Count; - - /* Get next entry */ - CodeEntry* E = CS_GetEntry (S, I); - - /* Check for the sequence */ - if (E->OPC == OP65_JSR && - strncmp (E->Arg, "asrax", 5) == 0 && - strlen (E->Arg) == 6 && - IsDigit (E->Arg[5]) && - (Count = (E->Arg[5] - '0')) >= 1 && - Count * 100 <= S->CodeSizeFactor && - !RegXUsed (S, I+1)) { - - CodeEntry* X; - unsigned J = I+1; - - /* Generate the replacement sequence */ - while (Count--) { - /* cmp #$80 */ - X = NewCodeEntry (OP65_CMP, AM65_IMM, "$80", 0, E->LI); - CS_InsertEntry (S, X, J++); - - /* ror a */ - X = NewCodeEntry (OP65_ROR, AM65_ACC, "a", 0, E->LI); - CS_InsertEntry (S, X, J++); - } - - /* Delete the call to asrax */ - CS_DelEntry (S, I); - - /* Remember, we had changes */ - ++Changes; - } - - /* Next entry */ - ++I; - - } - - /* Free the register info */ - CS_FreeRegInfo (S); - - /* Return the number of changes made */ - return Changes; -} - - - -static unsigned OptShift3 (CodeSeg* S) -/* The sequence - * - * bcc L - * inx - * L: jsr shrax1 - * - * may get replaced by - * - * ror a - * - * if X is zero on entry and unused later. - */ -{ - unsigned Changes = 0; - unsigned I; - - /* Generate register info */ - 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_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) && - CE_IsCallTo (L[2], "shrax1") && - !RegXUsed (S, I+3)) { - - /* Add the replacement insn instead */ - CodeEntry* X = NewCodeEntry (OP65_ROR, AM65_ACC, "a", 0, L[2]->LI); - CS_InsertEntry (S, X, I+3); - - /* Remove the bcs/dex/jsr */ - CS_DelEntries (S, I, 3); - - /* Remember, we had changes */ - ++Changes; - - } - - /* Next entry */ - ++I; - - } - - /* Free the register info */ - CS_FreeRegInfo (S); - - /* Return the number of changes made */ - return Changes; -} - - - -static unsigned OptShift4 (CodeSeg* S) -/* A call to the shraxN routine may get replaced by one or more lsr insns - * if the value of X is zero. - */ -{ - unsigned Changes = 0; - unsigned I; - - /* Generate register info */ - CS_GenRegInfo (S); - - /* Walk over the entries */ - I = 0; - while (I < CS_GetEntryCount (S)) { - - /* Get next entry */ - CodeEntry* E = CS_GetEntry (S, I); - - /* Check for the sequence */ - if (E->OPC == OP65_JSR && - strncmp (E->Arg, "shrax", 5) == 0 && - strlen (E->Arg) == 6 && - IsDigit (E->Arg[5]) && - E->RI->In.RegX == 0) { - - /* Insert shift insns */ - unsigned Count = E->Arg[5] - '0'; - while (Count--) { - CodeEntry* X = NewCodeEntry (OP65_LSR, AM65_ACC, "a", 0, E->LI); - CS_InsertEntry (S, X, I+1); - } - - /* Delete the call to shrax */ - CS_DelEntry (S, I); - - /* Remember, we had changes */ - ++Changes; - - } - - /* Next entry */ - ++I; - - } - - /* Free the register info */ - CS_FreeRegInfo (S); - - /* Return the number of changes made */ - return Changes; -} - - - -static unsigned GetShiftType (const char* Sub) -/* Helper function for OptShift5 */ -{ - if (*Sub == 'a') { - if (strcmp (Sub+1, "slax1") == 0) { - return SHIFT_ASL_1; - } else if (strcmp (Sub+1, "srax1") == 0) { - return SHIFT_ASR_1; - } - } else if (*Sub == 's') { - if (strcmp (Sub+1, "hlax1") == 0) { - return SHIFT_LSL_1; - } else if (strcmp (Sub+1, "hrax1") == 0) { - return SHIFT_LSR_1; - } - } - return SHIFT_NONE; -} - - - -static 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 = GetShiftType (L[2]->Arg)) != SHIFT_NONE&& - 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; -} - - - -static unsigned OptShift6 (CodeSeg* S) -/* Inline the shift subroutines. */ -{ - unsigned Changes = 0; - - /* Walk over the entries */ - unsigned I = 0; - while (I < CS_GetEntryCount (S)) { - - CodeEntry* X; - unsigned IP; - - /* Get next entry */ - CodeEntry* E = CS_GetEntry (S, I); - - /* Check for a call to one of the shift routine */ - if (E->OPC == OP65_JSR && - (strncmp (E->Arg, "shlax", 5) == 0 || - strncmp (E->Arg, "aslax", 5) == 0) && - strlen (E->Arg) == 6 && - IsDigit (E->Arg[5])) { - - /* Get number of shifts */ - unsigned ShiftCount = (E->Arg[5] - '0'); - - /* Code is: - * - * stx tmp1 - * asl a - * rol tmp1 - * (repeat ShiftCount-1 times) - * ldx tmp1 - * - * which makes 4 + 3 * ShiftCount bytes, compared to the original - * 3 bytes for the subroutine call. However, in most cases, the - * final load of the X register gets merged with some other insn - * and replaces a txa, so for a shift count of 1, we get a factor - * of 200, which matches nicely the CodeSizeFactor enabled with -Oi - */ - if (ShiftCount > 1 || S->CodeSizeFactor > 200) { - unsigned Size = 4 + 3 * ShiftCount; - if ((Size * 100 / 3) > S->CodeSizeFactor) { - /* Not acceptable */ - goto NextEntry; - } - } - - /* Inline the code. Insertion point is behind the subroutine call */ - IP = (I + 1); - - /* stx tmp1 */ - X = NewCodeEntry (OP65_STX, AM65_ZP, "tmp1", 0, E->LI); - CS_InsertEntry (S, X, IP++); - - while (ShiftCount--) { - /* asl a */ - X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, E->LI); - CS_InsertEntry (S, X, IP++); - - /* rol tmp1 */ - X = NewCodeEntry (OP65_ROL, AM65_ZP, "tmp1", 0, E->LI); - CS_InsertEntry (S, X, IP++); - } - - /* ldx tmp1 */ - X = NewCodeEntry (OP65_LDX, AM65_ZP, "tmp1", 0, E->LI); - CS_InsertEntry (S, X, IP++); - - /* Remove the subroutine call */ - CS_DelEntry (S, I); - - /* Remember, we had changes */ - ++Changes; - } - -NextEntry: - /* Next entry */ - ++I; - - } - - /* Return the number of changes made */ - return Changes; -} - - - /*****************************************************************************/ /* Optimize loads */ /*****************************************************************************/ @@ -613,9 +83,6 @@ static unsigned OptLoad1 (CodeSeg* S) unsigned I; unsigned Changes = 0; - /* Generate register info */ - CS_GenRegInfo (S); - /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { @@ -654,9 +121,6 @@ static unsigned OptLoad1 (CodeSeg* S) } - /* Free the register info */ - CS_FreeRegInfo (S); - /* Return the number of changes made */ return Changes; } @@ -669,9 +133,6 @@ static unsigned OptLoad2 (CodeSeg* S) unsigned I; unsigned Changes = 0; - /* Generate register info */ - CS_GenRegInfo (S); - /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { @@ -757,9 +218,6 @@ static unsigned OptLoad2 (CodeSeg* S) ++I; } - /* Free the register info */ - CS_FreeRegInfo (S); - /* Return the number of changes made */ return Changes; } @@ -793,9 +251,6 @@ static unsigned OptDecouple (CodeSeg* S) unsigned Changes = 0; unsigned I; - /* Generate register info for the following step */ - CS_GenRegInfo (S); - /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { @@ -993,9 +448,6 @@ static unsigned OptDecouple (CodeSeg* S) } - /* Free register info */ - CS_FreeRegInfo (S); - /* Return the number of changes made */ return Changes; } @@ -1036,9 +488,6 @@ static unsigned OptStackPtrOps (CodeSeg* S) unsigned Changes = 0; unsigned I; - /* Generate register info for the following step */ - CS_GenRegInfo (S); - /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { @@ -1093,9 +542,6 @@ static unsigned OptStackPtrOps (CodeSeg* S) } - /* Free register info */ - CS_FreeRegInfo (S); - /* Return the number of changes made */ return Changes; } @@ -1138,6 +584,12 @@ static OptFunc DOptAdd3 = { OptAdd3, "OptAdd3", 65, 0, static OptFunc DOptAdd4 = { OptAdd4, "OptAdd4", 90, 0, 0, 0, 0, 0 }; static OptFunc DOptAdd5 = { OptAdd5, "OptAdd5", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptAdd6 = { OptAdd6, "OptAdd6", 40, 0, 0, 0, 0, 0 }; +static OptFunc DOptBNegA1 = { OptBNegA1, "OptBNegA1", 100, 0, 0, 0, 0, 0 }; +static OptFunc DOptBNegA2 = { OptBNegA2, "OptBNegA2", 100, 0, 0, 0, 0, 0 }; +static OptFunc DOptBNegAX1 = { OptBNegAX1, "OptBNegAX1", 100, 0, 0, 0, 0, 0 }; +static OptFunc DOptBNegAX2 = { OptBNegAX2, "OptBNegAX2", 100, 0, 0, 0, 0, 0 }; +static OptFunc DOptBNegAX3 = { OptBNegAX3, "OptBNegAX3", 100, 0, 0, 0, 0, 0 }; +static OptFunc DOptBNegAX4 = { OptBNegAX4, "OptBNegAX4", 100, 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", 42, 0, 0, 0, 0, 0 }; @@ -1163,15 +615,11 @@ static OptFunc DOptJumpTarget2 = { OptJumpTarget2, "OptJumpTarget2", 100, 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 DOptNegAX1 = { OptNegAX1, "OptNegAX1", 165, 0, 0, 0, 0, 0 }; +static OptFunc DOptNegAX2 = { OptNegAX2, "OptNegAX2", 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 }; -static OptFunc DOptNegA1 = { OptNegA1, "OptNegA1", 100, 0, 0, 0, 0, 0 }; -static OptFunc DOptNegA2 = { OptNegA2, "OptNegA2", 100, 0, 0, 0, 0, 0 }; -static OptFunc DOptNegAX1 = { OptNegAX1, "OptNegAX1", 100, 0, 0, 0, 0, 0 }; -static OptFunc DOptNegAX2 = { OptNegAX2, "OptNegAX2", 100, 0, 0, 0, 0, 0 }; -static OptFunc DOptNegAX3 = { OptNegAX3, "OptNegAX3", 100, 0, 0, 0, 0, 0 }; -static OptFunc DOptNegAX4 = { OptNegAX4, "OptNegAX4", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPrecalc = { OptPrecalc, "OptPrecalc", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad1 = { OptPtrLoad1, "OptPtrLoad1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad2 = { OptPtrLoad2, "OptPtrLoad2", 100, 0, 0, 0, 0, 0 }; @@ -1187,11 +635,9 @@ 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 DOptPtrStore1 = { OptPtrStore1, "OptPtrStore1", 40, 0, 0, 0, 0, 0 }; -static OptFunc DOptPtrStore2 = { OptPtrStore2, "OptPtrStore2", 50, 0, 0, 0, 0, 0 }; -static OptFunc DOptPtrStore3 = { OptPtrStore3, "OptPtrStore3", 50, 0, 0, 0, 0, 0 }; -static OptFunc DOptPtrStore4 = { OptPtrStore4, "OptPtrStore4", 65, 0, 0, 0, 0, 0 }; -static OptFunc DOptPtrStore5 = { OptPtrStore5, "OptPtrStore5", 100, 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 }; 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 }; @@ -1235,6 +681,12 @@ static OptFunc* OptFuncs[] = { &DOptAdd4, &DOptAdd5, &DOptAdd6, + &DOptBNegA1, + &DOptBNegA2, + &DOptBNegAX1, + &DOptBNegAX2, + &DOptBNegAX3, + &DOptBNegAX4, &DOptBoolTrans, &DOptBranchDist, &DOptCmp1, @@ -1260,12 +712,8 @@ static OptFunc* OptFuncs[] = { &DOptJumpTarget3, &DOptLoad1, &DOptLoad2, - &DOptNegA1, - &DOptNegA2, &DOptNegAX1, &DOptNegAX2, - &DOptNegAX3, - &DOptNegAX4, &DOptPrecalc, &DOptPtrLoad1, &DOptPtrLoad11, @@ -1284,8 +732,6 @@ static OptFunc* OptFuncs[] = { &DOptPtrStore1, &DOptPtrStore2, &DOptPtrStore3, - &DOptPtrStore4, - &DOptPtrStore5, &DOptPush1, &DOptPush2, &DOptPushPop, @@ -1497,10 +943,10 @@ static void WriteOptStats (const char* Name) fprintf (F, "%-20s %10lu %10lu %10lu %10lu\n", O->Name, - O->TotalRuns, + O->TotalRuns, O->LastRuns, - O->TotalChanges, - O->LastChanges); + O->TotalChanges, + O->LastChanges); } /* Close the file, ignore errors here. */ @@ -1525,7 +971,7 @@ static unsigned RunOptFunc (CodeSeg* S, OptFunc* F, unsigned Max) Changes = 0; do { - /* Run the function */ + /* Run the function */ C = F->Func (S); if (Debug && C > 0) { printf ("Applied %s: %u changes\n", F->Name, C); @@ -1538,6 +984,11 @@ static unsigned RunOptFunc (CodeSeg* S, OptFunc* F, unsigned Max) F->TotalChanges += C; F->LastChanges += C; + /* If we had changes, regenerate register info */ + if (C) { + CS_GenRegInfo (S); + } + } while (--Max && C > 0); /* Return the number of changes */ @@ -1559,8 +1010,6 @@ static unsigned RunOptGroup1 (CodeSeg* S) Changes += RunOptFunc (S, &DOptPtrStore1, 1); Changes += RunOptFunc (S, &DOptPtrStore2, 1); Changes += RunOptFunc (S, &DOptPtrStore3, 1); - Changes += RunOptFunc (S, &DOptPtrStore4, 1); - Changes += RunOptFunc (S, &DOptPtrStore5, 1); Changes += RunOptFunc (S, &DOptAdd3, 1); /* Before OptPtrLoad5! */ Changes += RunOptFunc (S, &DOptPtrLoad1, 1); Changes += RunOptFunc (S, &DOptPtrLoad2, 1); @@ -1576,10 +1025,10 @@ static unsigned RunOptGroup1 (CodeSeg* S) Changes += RunOptFunc (S, &DOptPtrLoad15, 1); Changes += RunOptFunc (S, &DOptPtrLoad16, 1); Changes += RunOptFunc (S, &DOptPtrLoad17, 1); - Changes += RunOptFunc (S, &DOptNegAX1, 1); - Changes += RunOptFunc (S, &DOptNegAX2, 1); - Changes += RunOptFunc (S, &DOptNegAX3, 1); - Changes += RunOptFunc (S, &DOptNegAX4, 1); + Changes += RunOptFunc (S, &DOptBNegAX1, 1); + Changes += RunOptFunc (S, &DOptBNegAX2, 1); + Changes += RunOptFunc (S, &DOptBNegAX3, 1); + Changes += RunOptFunc (S, &DOptBNegAX4, 1); Changes += RunOptFunc (S, &DOptAdd1, 1); Changes += RunOptFunc (S, &DOptAdd2, 1); Changes += RunOptFunc (S, &DOptAdd4, 1); @@ -1591,7 +1040,6 @@ static unsigned RunOptGroup1 (CodeSeg* S) Changes += RunOptFunc (S, &DOptStore5, 1); Changes += RunOptFunc (S, &DOptShift1, 1); Changes += RunOptFunc (S, &DOptShift2, 1); - Changes += RunOptFunc (S, &DOptShift4, 1); Changes += RunOptFunc (S, &DOptShift5, 1); Changes += RunOptFunc (S, &DOptShift6, 1); Changes += RunOptFunc (S, &DOptStore1, 1); @@ -1633,9 +1081,13 @@ static unsigned RunOptGroup3 (CodeSeg* S) do { C = 0; - C += RunOptFunc (S, &DOptNegA1, 1); - C += RunOptFunc (S, &DOptNegA2, 1); - C += RunOptFunc (S, &DOptStackOps, 1); + C += RunOptFunc (S, &DOptBNegA1, 1); + C += RunOptFunc (S, &DOptBNegA2, 1); + C += RunOptFunc (S, &DOptNegAX1, 1); + C += RunOptFunc (S, &DOptNegAX2, 1); + C += RunOptFunc (S, &DOptStackOps, 3); + C += RunOptFunc (S, &DOptShift1, 1); + C += RunOptFunc (S, &DOptShift4, 1); C += RunOptFunc (S, &DOptSub1, 1); C += RunOptFunc (S, &DOptSub2, 1); C += RunOptFunc (S, &DOptSub3, 1); @@ -1789,6 +1241,7 @@ static unsigned RunOptGroup7 (CodeSeg* S) Changes += RunOptFunc (S, &DOptUnusedLoads, 1); Changes += RunOptFunc (S, &DOptJumpTarget1, 5); Changes += RunOptFunc (S, &DOptStore5, 1); + Changes += RunOptFunc (S, &DOptTransfers1, 1); Changes += RunOptFunc (S, &DOptTransfers3, 1); } @@ -1833,6 +1286,9 @@ void RunOpt (CodeSeg* S) Print (stdout, 1, "Running optimizer for global code segment\n"); } + /* Generate register info for all instructions */ + CS_GenRegInfo (S); + /* Run groups of optimizations */ RunOptGroup1 (S); RunOptGroup2 (S); @@ -1842,6 +1298,9 @@ void RunOpt (CodeSeg* S) RunOptGroup6 (S); RunOptGroup7 (S); + /* Free register info */ + CS_FreeRegInfo (S); + /* Write statistics */ if (StatFileName) { WriteOptStats (StatFileName);