From c61729a15ad1da563addc233dbafb2b30dda9b22 Mon Sep 17 00:00:00 2001 From: cuz Date: Sat, 23 Nov 2002 16:33:35 +0000 Subject: [PATCH] A few size optimizations git-svn-id: svn://svn.cc65.org/cc65/trunk@1606 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codeinfo.c | 2 + src/cc65/codeopt.c | 4 ++ src/cc65/coptpush.c | 101 ++++++++++++++++++++++++++++++++++++-------- src/cc65/coptpush.h | 14 +++++- src/cc65/coptsize.c | 2 + src/cc65/coptstop.c | 11 ++--- 6 files changed, 111 insertions(+), 23 deletions(-) diff --git a/src/cc65/codeinfo.c b/src/cc65/codeinfo.c index 47d038abc..f968b12d2 100644 --- a/src/cc65/codeinfo.c +++ b/src/cc65/codeinfo.c @@ -161,7 +161,9 @@ static const FuncInfo FuncInfoTable[] = { { "pushc1", REG_NONE, REG_A | REG_Y }, { "pushc2", REG_NONE, REG_A | REG_Y }, { "pusheax", REG_EAX, REG_Y }, + { "pushw", REG_AX, REG_AXY | REG_PTR1 }, { "pushw0sp", REG_NONE, REG_AXY }, + { "pushwidx", REG_AXY, REG_AXY | REG_PTR1 }, { "pushwysp", REG_Y, REG_AXY }, { "shlax1", REG_AX, REG_AX | REG_TMP1 }, { "shlax2", REG_AX, REG_AX | REG_TMP1 }, diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index f9fcd9428..51e7b9556 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -1438,6 +1438,7 @@ static OptFunc DOptPtrLoad6 = { OptPtrLoad6, "OptPtrLoad6", 100, 0, static OptFunc DOptPtrStore1 = { OptPtrStore1, "OptPtrStore1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrStore2 = { OptPtrStore2, "OptPtrStore2", 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 }; static OptFunc DOptShift1 = { OptShift1, "OptShift1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptShift2 = { OptShift2, "OptShift2", 100, 0, 0, 0, 0, 0 }; @@ -1496,6 +1497,7 @@ static OptFunc* OptFuncs[] = { &DOptPtrStore1, &DOptPtrStore2, &DOptPush1, + &DOptPush2, &DOptPushPop, &DOptRTS, &DOptRTSJumps1, @@ -1875,6 +1877,8 @@ static unsigned RunOptGroup5 (CodeSeg* S) unsigned Changes = 0; Changes += RunOptFunc (S, &DOptPush1, 1); + Changes += RunOptFunc (S, &DOptPush2, 1); + Changes += RunOptFunc (S, &DOptUnusedLoads, 1); /* Return the number of changes */ return Changes; diff --git a/src/cc65/coptpush.c b/src/cc65/coptpush.c index 887bbf9be..2a26d7cca 100644 --- a/src/cc65/coptpush.c +++ b/src/cc65/coptpush.c @@ -49,11 +49,10 @@ unsigned OptPush1 (CodeSeg* S) /* Given a sequence * - * ldy #xx * jsr ldaxysp * jsr pushax * - * If a/x are not used later, replace that by + * If a/x are not used later, and Y is known, replace that by * * ldy #xx+2 * jsr pushwysp @@ -61,42 +60,45 @@ unsigned OptPush1 (CodeSeg* S) * saving 3 bytes and several cycles. */ { + unsigned I; unsigned Changes = 0; + /* Generate register info */ + CS_GenRegInfo (S); + /* Walk over the entries */ - unsigned I = 0; + I = 0; while (I < CS_GetEntryCount (S)) { - CodeEntry* L[3]; + CodeEntry* L[2]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ - if (L[0]->OPC == OP65_LDY && - CE_KnownImm (L[0]) && - L[0]->Num < 0xFE && - !CS_RangeHasLabel (S, I+1, 2) && - CS_GetEntries (S, L+1, I+1, 2) && - CE_IsCallTo (L[1], "ldaxysp") && - CE_IsCallTo (L[2], "pushax") && - !RegAXUsed (S, I+3)) { + 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]->Num+2); + Arg = MakeHexArg (L[0]->RI->In.RegY+2); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[0]->LI); - CS_InsertEntry (S, X, I+3); + CS_InsertEntry (S, X, I+2); /* jsr pushwysp */ - X = NewCodeEntry (OP65_JSR, AM65_ABS, "pushwysp", 0, L[2]->LI); - CS_InsertEntry (S, X, I+4); + 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, 3); + CS_DelEntries (S, I, 2); /* Remember, we had changes */ ++Changes; @@ -108,6 +110,71 @@ unsigned OptPush1 (CodeSeg* S) } + /* Free the register info */ + CS_FreeRegInfo (S); + + /* Return the number of changes made */ + return Changes; +} + + + +unsigned OptPush2 (CodeSeg* S) +/* A sequence + * + * jsr ldaxidx + * jsr pushax + * + * may get replaced by + * + * jsr pushwidx + * + */ +{ + unsigned I; + unsigned Changes = 0; + + /* Generate register info */ + CS_GenRegInfo (S); + + /* 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], "ldaxidx") && + (L[1] = CS_GetNextEntry (S, I)) != 0 && + !CE_HasLabel (L[1]) && + CE_IsCallTo (L[1], "pushax")) { + + /* Insert new code behind the pushax */ + CodeEntry* X; + + /* jsr pushwidx */ + X = NewCodeEntry (OP65_JSR, AM65_ABS, "pushwidx", 0, L[1]->LI); + CS_InsertEntry (S, X, I+2); + + /* Delete the old code */ + CS_DelEntries (S, I, 2); + + /* Remember, we had changes */ + ++Changes; + + } + + /* Next entry */ + ++I; + + } + + /* Free the register info */ + CS_FreeRegInfo (S); + /* Return the number of changes made */ return Changes; } diff --git a/src/cc65/coptpush.h b/src/cc65/coptpush.h index 399051376..02b15d7ee 100644 --- a/src/cc65/coptpush.h +++ b/src/cc65/coptpush.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2001 Ullrich von Bassewitz */ +/* (C) 2001-2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ @@ -64,6 +64,18 @@ unsigned OptPush1 (CodeSeg* S); * saving 3 bytes and several cycles. */ +unsigned OptPush2 (CodeSeg* S); +/* A sequence + * + * jsr ldaxidx + * jsr pushax + * + * may get replaced by + * + * jsr pushwidx + * + */ + /* End of coptpush.h */ diff --git a/src/cc65/coptsize.c b/src/cc65/coptsize.c index b458540c5..c39838da7 100644 --- a/src/cc65/coptsize.c +++ b/src/cc65/coptsize.c @@ -82,6 +82,8 @@ static const CallDesc CallTable [] = { { "pushax", -1, 0, -1, "pusha0" }, { "pushax", -1, 0xFF, -1, "pushaFF" }, { "pushaysp", -1, -1, 0, "pusha0sp" }, + { "pushwidx", -1, -1, 1, "pushw" }, + { "pushwysp", -1, -1, 3, "pushw0sp" }, { "staxysp", -1, -1, 0, "stax0sp" }, { "tosaddax", -1, 0, -1, "tosadda0" }, { "tosandax", -1, 0, -1, "tosanda0" }, diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index c202b60e9..ed51fe130 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -607,7 +607,7 @@ static int HarmlessCall (const char* Name) */ { static const char* Tab[] = { - "ldaxidx", + "ldaxidx", "ldaxysp", }; @@ -699,7 +699,7 @@ unsigned OptStackOps (CodeSeg* S) Data.ZPLo = "ptr1"; Data.ZPHi = "ptr1+1"; } else if ((UsedRegs & REG_PTR2) == REG_NONE) { - Data.ZPLo = "ptr2"; + Data.ZPLo = "ptr2"; Data.ZPHi = "ptr2+1"; } else { /* No registers available */ @@ -741,16 +741,17 @@ unsigned OptStackOps (CodeSeg* S) /* Restart the sequence */ Push = I; UsedRegs = REG_NONE; - } else if (!HarmlessCall (E->Arg)) { + } else if (HarmlessCall (E->Arg)) { + /* Track zeropage register usage */ + UsedRegs |= (E->Use | E->Chg); + } else { /* A call to an unkown subroutine ends the sequence */ InSeq = 0; } } else { - /* Other stuff: Track zeropage register usage */ UsedRegs |= (E->Use | E->Chg); - } } else if (CE_IsCallTo (E, "pushax")) {