Be more flexible when detecting a special sequence that can be optimized.

git-svn-id: svn://svn.cc65.org/cc65/trunk@5718 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz
2012-06-15 20:51:14 +00:00
parent b014bd8196
commit 7c9b27c048
5 changed files with 251 additions and 218 deletions

View File

@@ -397,7 +397,7 @@ void CE_SetNumArg (CodeEntry* E, long Num)
int CE_IsConstImm (const CodeEntry* E) int CE_IsConstImm (const CodeEntry* E)
/* Return true if the argument of E is a constant immediate value */ /* Return true if the argument of E is a constant immediate value */
{ {
return (E->AM == AM65_IMM && (E->Flags & CEF_NUMARG) != 0); return (E->AM == AM65_IMM && CE_HasNumArg (E));
} }
@@ -407,9 +407,7 @@ int CE_IsKnownImm (const CodeEntry* E, unsigned long Num)
* equal to Num. * equal to Num.
*/ */
{ {
return E->AM == AM65_IMM && return (E->AM == AM65_IMM && CE_HasNumArg (E) && E->Num == Num);
(E->Flags & CEF_NUMARG) != 0 &&
E->Num == Num;
} }
@@ -1388,7 +1386,7 @@ void CE_Output (const CodeEntry* E)
/* Print the mnemonic */ /* Print the mnemonic */
Chars = WriteOutput ("\t%s", D->Mnemo); Chars = WriteOutput ("\t%s", D->Mnemo);
/* Space to leave before the operand */ /* Space to leave before the operand */
Space = 9 - Chars; Space = 9 - Chars;
@@ -1453,7 +1451,7 @@ void CE_Output (const CodeEntry* E)
} }
/* Print usage info if requested by the debugging flag */ /* Print usage info if requested by the debugging flag */
if (Debug) { if (Debug) {
char Use [128]; char Use [128];
char Chg [128]; char Chg [128];
WriteOutput ("%*s; USE: %-12s CHG: %-12s SIZE: %u", WriteOutput ("%*s; USE: %-12s CHG: %-12s SIZE: %u",

View File

@@ -183,6 +183,16 @@ INLINE void CE_ResetMark (CodeEntry* E)
# define CE_ResetMark(E) ((E)->Flags &= ~CEF_USERMARK) # define CE_ResetMark(E) ((E)->Flags &= ~CEF_USERMARK)
#endif #endif
#if defined(HAVE_INLINE)
INLINE int CE_HasNumArg (const CodeEntry* E)
/* Return true if the instruction has a numeric argument */
{
return (E->Flags & CEF_NUMARG) != 0;
}
#else
# define CE_HasNumArg(E) (((E)->Flags & CEF_NUMARG) != 0)
#endif
void CE_SetArg (CodeEntry* E, const char* Arg); void CE_SetArg (CodeEntry* E, const char* Arg);
/* Replace the argument by the new one. */ /* Replace the argument by the new one. */

View File

@@ -1200,12 +1200,11 @@ static OptFunc DOptPtrLoad14 = { OptPtrLoad14, "OptPtrLoad14", 108, 0,
static OptFunc DOptPtrLoad15 = { OptPtrLoad15, "OptPtrLoad15", 86, 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 DOptPtrLoad16 = { OptPtrLoad16, "OptPtrLoad16", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptPtrLoad17 = { OptPtrLoad17, "OptPtrLoad17", 190, 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 DOptPtrStore1 = { OptPtrStore1, "OptPtrStore1", 65, 0, 0, 0, 0, 0 };
static OptFunc DOptPtrStore2 = { OptPtrStore2, "OptPtrStore2", 50, 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 DOptPtrStore3 = { OptPtrStore3, "OptPtrStore3", 50, 0, 0, 0, 0, 0 };
static OptFunc DOptPtrStore4 = { OptPtrStore4, "OptPtrStore4", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrStore4 = { OptPtrStore4, "OptPtrStore4", 65, 0, 0, 0, 0, 0 };
static OptFunc DOptPtrStore5 = { OptPtrStore5, "OptPtrStore5", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrStore5 = { OptPtrStore5, "OptPtrStore5", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptPtrStore6 = { OptPtrStore6, "OptPtrStore6", 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 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 };
@@ -1300,7 +1299,6 @@ static OptFunc* OptFuncs[] = {
&DOptPtrStore3, &DOptPtrStore3,
&DOptPtrStore4, &DOptPtrStore4,
&DOptPtrStore5, &DOptPtrStore5,
&DOptPtrStore6,
&DOptPush1, &DOptPush1,
&DOptPush2, &DOptPush2,
&DOptPushPop, &DOptPushPop,
@@ -1576,7 +1574,6 @@ static unsigned RunOptGroup1 (CodeSeg* S)
Changes += RunOptFunc (S, &DOptPtrStore3, 1); Changes += RunOptFunc (S, &DOptPtrStore3, 1);
Changes += RunOptFunc (S, &DOptPtrStore4, 1); Changes += RunOptFunc (S, &DOptPtrStore4, 1);
Changes += RunOptFunc (S, &DOptPtrStore5, 1); Changes += RunOptFunc (S, &DOptPtrStore5, 1);
Changes += RunOptFunc (S, &DOptPtrStore6, 1);
Changes += RunOptFunc (S, &DOptAdd3, 1); /* Before OptPtrLoad5! */ Changes += RunOptFunc (S, &DOptAdd3, 1); /* Before OptPtrLoad5! */
Changes += RunOptFunc (S, &DOptPtrLoad1, 1); Changes += RunOptFunc (S, &DOptPtrLoad1, 1);
Changes += RunOptFunc (S, &DOptPtrLoad2, 1); Changes += RunOptFunc (S, &DOptPtrLoad2, 1);

View File

@@ -36,7 +36,9 @@
#include <string.h> #include <string.h>
/* common */ /* common */
#include "strbuf.h"
#include "xmalloc.h" #include "xmalloc.h"
#include "xsprintf.h"
/* cc65 */ /* cc65 */
#include "codeent.h" #include "codeent.h"
@@ -89,7 +91,7 @@ static unsigned OptPtrStore1Sub (CodeSeg* S, unsigned I, CodeEntry** const L)
static const char* ZPLoadAX (CodeSeg* S, unsigned I) static const char* LoadAXZP (CodeSeg* S, unsigned I)
/* If the two instructions at S/I are a load of A/X from a two byte zero byte /* If the two instructions at S/I are a load of A/X from a two byte zero byte
* location, return the name of the zero page location. Otherwise return NULL. * location, return the name of the zero page location. Otherwise return NULL.
*/ */
@@ -121,8 +123,74 @@ static const char* ZPLoadAX (CodeSeg* S, unsigned I)
static const char* LoadAXImm (CodeSeg* S, unsigned I)
/* If the two instructions at S/I are a load of A/X of a constant value or a
* wqord sized address label, return the address of the location as a string.
* Beware: In case of a numeric value, the result is returned in static
* storage which is overwritten with each call.
*/
{
static StrBuf Buf = STATIC_STRBUF_INITIALIZER;
CodeEntry* L[2];
unsigned Len;
if (CS_GetEntries (S, L, I, 2) &&
((L[0]->OPC == OP65_LDA && L[1]->OPC == OP65_LDX) ||
(L[0]->OPC == OP65_LDX && L[1]->OPC == OP65_LDA)) &&
L[0]->AM == AM65_IMM &&
L[1]->AM == AM65_IMM &&
!CE_HasLabel (L[1])) {
/* Immediate load of A/X */
if (CE_HasNumArg (L[0]) && CE_HasNumArg (L[1])) {
/* Numeric argument - get low and high byte */
unsigned Hi, Lo;
if (L[0]->OPC == OP65_LDA) {
Lo = (L[0]->Num & 0xFF);
Hi = (L[1]->Num & 0xFF);
} else {
Lo = (L[1]->Num & 0xFF);
Hi = (L[0]->Num & 0xFF);
}
/* Format into buffer */
SB_Printf (&Buf, "$%04X", Lo | (Hi << 8));
/* Return the address as a string */
return SB_GetConstBuf (&Buf);
} else if ((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) {
/* Load of an address label */
SB_CopyBuf (&Buf, L[0]->Arg + 2, Len - 3);
SB_Terminate (&Buf);
return SB_GetConstBuf (&Buf);
} else {
/* Not found */
return 0;
}
} else {
/* Not found */
return 0;
}
}
/*****************************************************************************/ /*****************************************************************************/
/* Code */ /* Code */
/*****************************************************************************/ /*****************************************************************************/
@@ -130,8 +198,6 @@ static const char* ZPLoadAX (CodeSeg* S, unsigned I)
unsigned OptPtrStore1 (CodeSeg* S) unsigned OptPtrStore1 (CodeSeg* S)
/* Search for the sequence: /* Search for the sequence:
* *
* lda #<(label+0)
* ldx #>(label+0)
* clc * clc
* adc xxx * adc xxx
* bcc L * bcc L
@@ -144,10 +210,35 @@ unsigned OptPtrStore1 (CodeSeg* S)
* *
* and replace it by: * and replace it by:
* *
* sta ptr1
* stx ptr1+1
* ldy xxx * ldy xxx
* ldx #$00 * ldx #$00
* lda yyy * lda yyy
* sta label,y * sta (ptr1),y
*
* or by
*
* ldy xxx
* ldx #$00
* lda yyy
* sta label,y
*
* or by
*
* ldy xxx
* ldx #$00
* lda yyy
* sta $xxxx,y
*
* or by
*
* ldy xxx
* ldx #$00
* lda yyy
* sta (zp),y
*
* depending on the two instructions preceeding the sequence above.
*/ */
{ {
unsigned Changes = 0; unsigned Changes = 0;
@@ -156,64 +247,95 @@ unsigned OptPtrStore1 (CodeSeg* S)
unsigned I = 0; unsigned I = 0;
while (I < CS_GetEntryCount (S)) { while (I < CS_GetEntryCount (S)) {
CodeEntry* L[11]; CodeEntry* L[9];
unsigned Len;
/* 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_LDA && if (L[0]->OPC == OP65_CLC &&
L[0]->AM == AM65_IMM && CS_GetEntries (S, L+1, I+1, 8) &&
CS_GetEntries (S, L+1, I+1, 10) && L[1]->OPC == OP65_ADC &&
L[1]->OPC == OP65_LDX && (L[1]->AM == AM65_ABS ||
L[1]->AM == AM65_IMM && L[1]->AM == AM65_ZP ||
L[2]->OPC == OP65_CLC && L[1]->AM == AM65_IMM) &&
L[3]->OPC == OP65_ADC && (L[2]->OPC == OP65_BCC || L[2]->OPC == OP65_JCC) &&
(L[3]->AM == AM65_ABS || L[3]->AM == AM65_ZP) && L[2]->JumpTo != 0 &&
(L[4]->OPC == OP65_BCC || L[4]->OPC == OP65_JCC) && L[2]->JumpTo->Owner == L[4] &&
L[4]->JumpTo != 0 && L[3]->OPC == OP65_INX &&
L[4]->JumpTo->Owner == L[6] && CE_IsCallTo (L[4], "pushax") &&
L[5]->OPC == OP65_INX && L[5]->OPC == OP65_LDX &&
CE_IsCallTo (L[6], "pushax") && L[6]->OPC == OP65_LDA &&
L[7]->OPC == OP65_LDX && L[7]->OPC == OP65_LDY &&
L[8]->OPC == OP65_LDA && CE_IsKnownImm (L[7], 0) &&
L[9]->OPC == OP65_LDY && CE_IsCallTo (L[8], "staspidx") &&
CE_IsKnownImm (L[9], 0) && !CS_RangeHasLabel (S, I+1, 3) &&
CE_IsCallTo (L[10], "staspidx") && !CS_RangeHasLabel (S, I+5, 4)) {
!CS_RangeHasLabel (S, I+1, 5) &&
!CS_RangeHasLabel (S, I+7, 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; CodeEntry* X;
char* Label; const char* Loc;
am_t AM;
/* We will create all the new stuff behind the current one so /* Track the insertion point */
* we keep the line references. unsigned IP = I + 9;
*/
X = NewCodeEntry (OP65_LDY, L[3]->AM, L[3]->Arg, 0, L[0]->LI);
CS_InsertEntry (S, X, I+11);
X = NewCodeEntry (OP65_LDX, L[7]->AM, L[7]->Arg, 0, L[7]->LI); unsigned DeleteStart = I;
CS_InsertEntry (S, X, I+12); unsigned DeleteCount = 9;
if (I >= 2) {
if ((Loc = LoadAXZP (S, I-2)) != 0) {
/* If the sequence is preceeded by a load of a ZP value,
* we can use this ZP value as a pointer using ZP
* indirect Y addressing.
*/
AM = AM65_ZP_INDY;
DeleteStart -= 2;
DeleteCount += 2;
} else if ((Loc = LoadAXImm (S, I-2)) != 0) {
/* If the sequence is preceeded by a load of an immediate
* value, we can use this absolute value as an address
* using absolute indexed Y addressing.
*/
AM = AM65_ABSY;
DeleteStart -= 2;
DeleteCount += 2;
}
}
X = NewCodeEntry (OP65_LDA, L[8]->AM, L[8]->Arg, 0, L[8]->LI); /* If we don't have a zero page location, we use ptr1 with zp
CS_InsertEntry (S, X, I+13); * indirect Y addressing. We must store the value in A/X into
* ptr1 in this case.
*/
if (Loc == 0) {
Label = memcpy (xmalloc (Len-2), L[0]->Arg+2, Len-3); /* Must use ptr1 */
Label[Len-3] = '\0'; Loc = "ptr1";
X = NewCodeEntry (OP65_STA, AM65_ABSY, Label, 0, L[10]->LI); AM = AM65_ZP_INDY;
CS_InsertEntry (S, X, I+14);
xfree (Label); X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[8]->LI);
CS_InsertEntry (S, X, IP++);
X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[8]->LI);
CS_InsertEntry (S, X, IP++);
}
X = NewCodeEntry (OP65_LDY, L[1]->AM, L[1]->Arg, 0, L[1]->LI);
CS_InsertEntry (S, X, IP++);
X = NewCodeEntry (OP65_LDX, L[5]->AM, L[5]->Arg, 0, L[5]->LI);
CS_InsertEntry (S, X, IP++);
X = NewCodeEntry (OP65_LDA, L[6]->AM, L[6]->Arg, 0, L[6]->LI);
CS_InsertEntry (S, X, IP++);
X = NewCodeEntry (OP65_STA, AM, Loc, 0, L[8]->LI);
CS_InsertEntry (S, X, IP++);
/* Remove the old code */ /* Remove the old code */
CS_DelEntries (S, I, 11); CS_DelEntries (S, DeleteStart, DeleteCount);
/* Skip most of the generated replacement */
I += 3;
/* Remember, we had changes */ /* Remember, we had changes */
++Changes; ++Changes;
@@ -221,7 +343,7 @@ unsigned OptPtrStore1 (CodeSeg* S)
} }
/* Next entry */ /* Next entry */
++I; ++I;
} }
@@ -471,116 +593,6 @@ unsigned OptPtrStore3 (CodeSeg* S)
unsigned OptPtrStore4 (CodeSeg* S) unsigned OptPtrStore4 (CodeSeg* S)
/* Search for the sequence:
*
* clc
* adc xxx
* bcc L
* inx
* L: jsr pushax
* ldx #$00
* lda yyy
* ldy #$00
* jsr staspidx
*
* and replace it by:
*
* sta ptr1
* stx ptr1+1
* ldy xxx
* ldx #$00
* lda yyy
* sta (ptr1),y
*
* In case a/x is loaded from the register bank before the clc, we can even
* use the register bank instead of ptr1.
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < CS_GetEntryCount (S)) {
CodeEntry* L[9];
/* Get next entry */
L[0] = CS_GetEntry (S, I);
/* Check for the sequence */
if (L[0]->OPC == OP65_CLC &&
CS_GetEntries (S, L+1, I+1, 8) &&
L[1]->OPC == OP65_ADC &&
(L[1]->AM == AM65_ABS ||
L[1]->AM == AM65_ZP ||
L[1]->AM == AM65_IMM) &&
(L[2]->OPC == OP65_BCC || L[2]->OPC == OP65_JCC) &&
L[2]->JumpTo != 0 &&
L[2]->JumpTo->Owner == L[4] &&
L[3]->OPC == OP65_INX &&
CE_IsCallTo (L[4], "pushax") &&
L[5]->OPC == OP65_LDX &&
L[6]->OPC == OP65_LDA &&
L[7]->OPC == OP65_LDY &&
CE_IsKnownImm (L[7], 0) &&
CE_IsCallTo (L[8], "staspidx") &&
!CS_RangeHasLabel (S, I+1, 3) &&
!CS_RangeHasLabel (S, I+5, 4)) {
CodeEntry* X;
const char* ZPLoc;
/* Track the insertion point */
unsigned IP = I + 9;
/* If the sequence is preceeded by a load of a ZP value, we can
* use this ZP value as a pointer.
*/
if (I < 2 || (ZPLoc = ZPLoadAX (S, I-2)) == 0) {
ZPLoc = "ptr1";
/* Must use ptr1 */
X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[8]->LI);
CS_InsertEntry (S, X, IP++);
X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[8]->LI);
CS_InsertEntry (S, X, IP++);
}
X = NewCodeEntry (OP65_LDY, L[1]->AM, L[1]->Arg, 0, L[1]->LI);
CS_InsertEntry (S, X, IP++);
X = NewCodeEntry (OP65_LDX, L[5]->AM, L[5]->Arg, 0, L[5]->LI);
CS_InsertEntry (S, X, IP++);
X = NewCodeEntry (OP65_LDA, L[6]->AM, L[6]->Arg, 0, L[6]->LI);
CS_InsertEntry (S, X, IP++);
X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, ZPLoc, 0, L[8]->LI);
CS_InsertEntry (S, X, IP++);
/* Remove the old code */
CS_DelEntries (S, I, 9);
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
unsigned OptPtrStore5 (CodeSeg* S)
/* Search for the sequence: /* Search for the sequence:
* *
* clc * clc
@@ -647,23 +659,42 @@ unsigned OptPtrStore5 (CodeSeg* S)
CodeEntry* X; CodeEntry* X;
const char* Arg; const char* Arg;
const char* ZPLoc; const char* Loc;
am_t AM;
/* Track the insertion point */ /* Track the insertion point */
unsigned IP = I + 10; unsigned IP = I + 10;
/* If the sequence is preceeded by a load of a ZP value, we can if (I >= 2) {
* use this ZP value as a pointer. if ((Loc = LoadAXZP (S, I-2)) != 0) {
*/ /* If the sequence is preceeded by a load of a ZP value,
if (I < 2 || (ZPLoc = ZPLoadAX (S, I-2)) == 0) { * we can use this ZP value as a pointer using ZP
* indirect Y addressing.
*/
AM = AM65_ZP_INDY;
} else if ((Loc = LoadAXImm (S, I-2)) != 0) {
/* If the sequence is preceeded by a load of an immediate
* value, we can use this absolute value as an address
* using absolute indexed Y addressing.
*/
AM = AM65_ABSY;
}
}
ZPLoc = "ptr1"; /* If we don't have a zero page location, we use ptr1 with zp
* indirect Y addressing. We must store the value in A/X into
* ptr1 in this case.
*/
if (Loc == 0) {
/* Must use ptr1 */ /* Must use ptr1 */
X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[9]->LI); Loc = "ptr1";
AM = AM65_ZP_INDY;
X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[8]->LI);
CS_InsertEntry (S, X, IP++); CS_InsertEntry (S, X, IP++);
X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[9]->LI); X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[8]->LI);
CS_InsertEntry (S, X, IP++); CS_InsertEntry (S, X, IP++);
} }
@@ -681,7 +712,7 @@ unsigned OptPtrStore5 (CodeSeg* S)
X = NewCodeEntry (OP65_LDY, L[1]->AM, L[1]->Arg, 0, L[1]->LI); X = NewCodeEntry (OP65_LDY, L[1]->AM, L[1]->Arg, 0, L[1]->LI);
CS_InsertEntry (S, X, IP++); CS_InsertEntry (S, X, IP++);
X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, ZPLoc, 0, L[9]->LI); X = NewCodeEntry (OP65_STA, AM, Loc, 0, L[9]->LI);
CS_InsertEntry (S, X, IP++); CS_InsertEntry (S, X, IP++);
/* Remove the old code */ /* Remove the old code */
@@ -703,7 +734,7 @@ unsigned OptPtrStore5 (CodeSeg* S)
unsigned OptPtrStore6 (CodeSeg* S) unsigned OptPtrStore5 (CodeSeg* S)
/* Search for the sequence: /* Search for the sequence:
* *
* jsr pushax * jsr pushax

View File

@@ -52,8 +52,6 @@
unsigned OptPtrStore1 (CodeSeg* S); unsigned OptPtrStore1 (CodeSeg* S);
/* Search for the sequence: /* Search for the sequence:
* *
* lda #<(label+0)
* ldx #>(label+0)
* clc * clc
* adc xxx * adc xxx
* bcc L * bcc L
@@ -66,11 +64,36 @@ unsigned OptPtrStore1 (CodeSeg* S);
* *
* and replace it by: * and replace it by:
* *
* sta ptr1
* stx ptr1+1
* ldy xxx * ldy xxx
* ldx #$00 * ldx #$00
* lda yyy * lda yyy
* sta label,y * sta (ptr1),y
*/ *
* or by
*
* ldy xxx
* ldx #$00
* lda yyy
* sta label,y
*
* or by
*
* ldy xxx
* ldx #$00
* lda yyy
* sta $xxxx,y
*
* or by
*
* ldy xxx
* ldx #$00
* lda yyy
* sta (zp),y
*
* depending on the two instructions preceeding the sequence above.
*/
unsigned OptPtrStore2 (CodeSeg* S); unsigned OptPtrStore2 (CodeSeg* S);
/* Search for the sequence: /* Search for the sequence:
@@ -127,32 +150,6 @@ unsigned OptPtrStore3 (CodeSeg* S);
*/ */
unsigned OptPtrStore4 (CodeSeg* S); unsigned OptPtrStore4 (CodeSeg* S);
/* Search for the sequence:
*
* ldy #offs1
* clc
* adc (sp),y
* bcc L
* inx
* L: jsr pushax
* ldy #offs2
* ldx #$00
* lda (sp),y
* ldy #$00
* jsr staspidx
*
* and replace it by:
*
* sta ptr1
* stx ptr1+1
* ldx #$00
* ldy #offs2-2
* lda (sp),y
* ldy #offs1
* sta (ptr1),y
*/
unsigned OptPtrStore5 (CodeSeg* S);
/* Search for the sequence: /* Search for the sequence:
* *
* clc * clc
@@ -179,8 +176,8 @@ unsigned OptPtrStore5 (CodeSeg* S);
* In case a/x is loaded from the register bank before the clc, we can even * In case a/x is loaded from the register bank before the clc, we can even
* use the register bank instead of ptr1. * use the register bank instead of ptr1.
*/ */
unsigned OptPtrStore6 (CodeSeg* S); unsigned OptPtrStore5 (CodeSeg* S);
/* Search for the sequence: /* Search for the sequence:
* *
* jsr pushax * jsr pushax