A few size optimizations
git-svn-id: svn://svn.cc65.org/cc65/trunk@1606 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -161,7 +161,9 @@ static const FuncInfo FuncInfoTable[] = {
|
|||||||
{ "pushc1", REG_NONE, REG_A | REG_Y },
|
{ "pushc1", REG_NONE, REG_A | REG_Y },
|
||||||
{ "pushc2", REG_NONE, REG_A | REG_Y },
|
{ "pushc2", REG_NONE, REG_A | REG_Y },
|
||||||
{ "pusheax", REG_EAX, REG_Y },
|
{ "pusheax", REG_EAX, REG_Y },
|
||||||
|
{ "pushw", REG_AX, REG_AXY | REG_PTR1 },
|
||||||
{ "pushw0sp", REG_NONE, REG_AXY },
|
{ "pushw0sp", REG_NONE, REG_AXY },
|
||||||
|
{ "pushwidx", REG_AXY, REG_AXY | REG_PTR1 },
|
||||||
{ "pushwysp", REG_Y, REG_AXY },
|
{ "pushwysp", REG_Y, REG_AXY },
|
||||||
{ "shlax1", REG_AX, REG_AX | REG_TMP1 },
|
{ "shlax1", REG_AX, REG_AX | REG_TMP1 },
|
||||||
{ "shlax2", REG_AX, REG_AX | REG_TMP1 },
|
{ "shlax2", REG_AX, REG_AX | REG_TMP1 },
|
||||||
|
|||||||
@@ -1438,6 +1438,7 @@ static OptFunc DOptPtrLoad6 = { OptPtrLoad6, "OptPtrLoad6", 100, 0,
|
|||||||
static OptFunc DOptPtrStore1 = { OptPtrStore1, "OptPtrStore1", 100, 0, 0, 0, 0, 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 DOptPtrStore2 = { OptPtrStore2, "OptPtrStore2", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptPush1 = { OptPush1, "OptPush1", 65, 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 DOptPushPop = { OptPushPop, "OptPushPop", 0, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptShift1 = { OptShift1, "OptShift1", 100, 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 };
|
static OptFunc DOptShift2 = { OptShift2, "OptShift2", 100, 0, 0, 0, 0, 0 };
|
||||||
@@ -1496,6 +1497,7 @@ static OptFunc* OptFuncs[] = {
|
|||||||
&DOptPtrStore1,
|
&DOptPtrStore1,
|
||||||
&DOptPtrStore2,
|
&DOptPtrStore2,
|
||||||
&DOptPush1,
|
&DOptPush1,
|
||||||
|
&DOptPush2,
|
||||||
&DOptPushPop,
|
&DOptPushPop,
|
||||||
&DOptRTS,
|
&DOptRTS,
|
||||||
&DOptRTSJumps1,
|
&DOptRTSJumps1,
|
||||||
@@ -1875,6 +1877,8 @@ static unsigned RunOptGroup5 (CodeSeg* S)
|
|||||||
unsigned Changes = 0;
|
unsigned Changes = 0;
|
||||||
|
|
||||||
Changes += RunOptFunc (S, &DOptPush1, 1);
|
Changes += RunOptFunc (S, &DOptPush1, 1);
|
||||||
|
Changes += RunOptFunc (S, &DOptPush2, 1);
|
||||||
|
Changes += RunOptFunc (S, &DOptUnusedLoads, 1);
|
||||||
|
|
||||||
/* Return the number of changes */
|
/* Return the number of changes */
|
||||||
return Changes;
|
return Changes;
|
||||||
|
|||||||
@@ -49,11 +49,10 @@
|
|||||||
unsigned OptPush1 (CodeSeg* S)
|
unsigned OptPush1 (CodeSeg* S)
|
||||||
/* Given a sequence
|
/* Given a sequence
|
||||||
*
|
*
|
||||||
* ldy #xx
|
|
||||||
* jsr ldaxysp
|
* jsr ldaxysp
|
||||||
* jsr pushax
|
* 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
|
* ldy #xx+2
|
||||||
* jsr pushwysp
|
* jsr pushwysp
|
||||||
@@ -61,42 +60,45 @@ unsigned OptPush1 (CodeSeg* S)
|
|||||||
* saving 3 bytes and several cycles.
|
* saving 3 bytes and several cycles.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
|
unsigned I;
|
||||||
unsigned Changes = 0;
|
unsigned Changes = 0;
|
||||||
|
|
||||||
|
/* Generate register info */
|
||||||
|
CS_GenRegInfo (S);
|
||||||
|
|
||||||
/* Walk over the entries */
|
/* Walk over the entries */
|
||||||
unsigned I = 0;
|
I = 0;
|
||||||
while (I < CS_GetEntryCount (S)) {
|
while (I < CS_GetEntryCount (S)) {
|
||||||
|
|
||||||
CodeEntry* L[3];
|
CodeEntry* L[2];
|
||||||
|
|
||||||
/* Get next entry */
|
/* Get next entry */
|
||||||
L[0] = CS_GetEntry (S, I);
|
L[0] = CS_GetEntry (S, I);
|
||||||
|
|
||||||
/* Check for the sequence */
|
/* Check for the sequence */
|
||||||
if (L[0]->OPC == OP65_LDY &&
|
if (CE_IsCallTo (L[0], "ldaxysp") &&
|
||||||
CE_KnownImm (L[0]) &&
|
RegValIsKnown (L[0]->RI->In.RegY) &&
|
||||||
L[0]->Num < 0xFE &&
|
L[0]->RI->In.RegY < 0xFE &&
|
||||||
!CS_RangeHasLabel (S, I+1, 2) &&
|
(L[1] = CS_GetNextEntry (S, I)) != 0 &&
|
||||||
CS_GetEntries (S, L+1, I+1, 2) &&
|
!CE_HasLabel (L[1]) &&
|
||||||
CE_IsCallTo (L[1], "ldaxysp") &&
|
CE_IsCallTo (L[1], "pushax") &&
|
||||||
CE_IsCallTo (L[2], "pushax") &&
|
!RegAXUsed (S, I+2)) {
|
||||||
!RegAXUsed (S, I+3)) {
|
|
||||||
|
|
||||||
/* Insert new code behind the pushax */
|
/* Insert new code behind the pushax */
|
||||||
const char* Arg;
|
const char* Arg;
|
||||||
CodeEntry* X;
|
CodeEntry* X;
|
||||||
|
|
||||||
/* ldy #xx+1 */
|
/* 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);
|
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 */
|
/* jsr pushwysp */
|
||||||
X = NewCodeEntry (OP65_JSR, AM65_ABS, "pushwysp", 0, L[2]->LI);
|
X = NewCodeEntry (OP65_JSR, AM65_ABS, "pushwysp", 0, L[1]->LI);
|
||||||
CS_InsertEntry (S, X, I+4);
|
CS_InsertEntry (S, X, I+3);
|
||||||
|
|
||||||
/* Delete the old code */
|
/* Delete the old code */
|
||||||
CS_DelEntries (S, I, 3);
|
CS_DelEntries (S, I, 2);
|
||||||
|
|
||||||
/* Remember, we had changes */
|
/* Remember, we had changes */
|
||||||
++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 the number of changes made */
|
||||||
return Changes;
|
return Changes;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2001 Ullrich von Bassewitz */
|
/* (C) 2001-2002 Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Wacholderweg 14 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70597 Stuttgart */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
@@ -64,6 +64,18 @@ unsigned OptPush1 (CodeSeg* S);
|
|||||||
* saving 3 bytes and several cycles.
|
* 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 */
|
/* End of coptpush.h */
|
||||||
|
|||||||
@@ -82,6 +82,8 @@ static const CallDesc CallTable [] = {
|
|||||||
{ "pushax", -1, 0, -1, "pusha0" },
|
{ "pushax", -1, 0, -1, "pusha0" },
|
||||||
{ "pushax", -1, 0xFF, -1, "pushaFF" },
|
{ "pushax", -1, 0xFF, -1, "pushaFF" },
|
||||||
{ "pushaysp", -1, -1, 0, "pusha0sp" },
|
{ "pushaysp", -1, -1, 0, "pusha0sp" },
|
||||||
|
{ "pushwidx", -1, -1, 1, "pushw" },
|
||||||
|
{ "pushwysp", -1, -1, 3, "pushw0sp" },
|
||||||
{ "staxysp", -1, -1, 0, "stax0sp" },
|
{ "staxysp", -1, -1, 0, "stax0sp" },
|
||||||
{ "tosaddax", -1, 0, -1, "tosadda0" },
|
{ "tosaddax", -1, 0, -1, "tosadda0" },
|
||||||
{ "tosandax", -1, 0, -1, "tosanda0" },
|
{ "tosandax", -1, 0, -1, "tosanda0" },
|
||||||
|
|||||||
@@ -607,7 +607,7 @@ static int HarmlessCall (const char* Name)
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
static const char* Tab[] = {
|
static const char* Tab[] = {
|
||||||
"ldaxidx",
|
"ldaxidx",
|
||||||
"ldaxysp",
|
"ldaxysp",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -699,7 +699,7 @@ unsigned OptStackOps (CodeSeg* S)
|
|||||||
Data.ZPLo = "ptr1";
|
Data.ZPLo = "ptr1";
|
||||||
Data.ZPHi = "ptr1+1";
|
Data.ZPHi = "ptr1+1";
|
||||||
} else if ((UsedRegs & REG_PTR2) == REG_NONE) {
|
} else if ((UsedRegs & REG_PTR2) == REG_NONE) {
|
||||||
Data.ZPLo = "ptr2";
|
Data.ZPLo = "ptr2";
|
||||||
Data.ZPHi = "ptr2+1";
|
Data.ZPHi = "ptr2+1";
|
||||||
} else {
|
} else {
|
||||||
/* No registers available */
|
/* No registers available */
|
||||||
@@ -741,16 +741,17 @@ unsigned OptStackOps (CodeSeg* S)
|
|||||||
/* Restart the sequence */
|
/* Restart the sequence */
|
||||||
Push = I;
|
Push = I;
|
||||||
UsedRegs = REG_NONE;
|
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 */
|
/* A call to an unkown subroutine ends the sequence */
|
||||||
InSeq = 0;
|
InSeq = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* Other stuff: Track zeropage register usage */
|
/* Other stuff: Track zeropage register usage */
|
||||||
UsedRegs |= (E->Use | E->Chg);
|
UsedRegs |= (E->Use | E->Chg);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (CE_IsCallTo (E, "pushax")) {
|
} else if (CE_IsCallTo (E, "pushax")) {
|
||||||
|
|||||||
Reference in New Issue
Block a user