unsigned OptPtrLoad1 (CodeSeg* S)
/* Search for the sequence:
- *
- * clc
- * adc xxx
- * tay
- * txa
- * adc yyy
- * tax
- * tya
- * ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * sta ptr1
- * txa
- * clc
- * adc yyy
- * sta ptr1+1
- * ldy xxx
- * ldx #$00
- * lda (ptr1),y
- */
+**
+** clc
+** adc xxx
+** tay
+** txa
+** adc yyy
+** tax
+** tya
+** ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** sta ptr1
+** txa
+** clc
+** adc yyy
+** sta ptr1+1
+** ldy xxx
+** ldx #$00
+** lda (ptr1),y
+*/
{
unsigned Changes = 0;
CS_InsertEntry (S, X, IP++);
/* If the instruction before the clc is a ldx, replace the
- * txa by an lda with the same location of the ldx. Otherwise
- * transfer the value in X to A.
- */
+ ** txa by an lda with the same location of the ldx. Otherwise
+ ** transfer the value in X to A.
+ */
if ((P = CS_GetPrevEntry (S, I)) != 0 &&
P->OPC == OP65_LDX &&
!CE_HasLabel (P)) {
unsigned OptPtrLoad2 (CodeSeg* S)
/* Search for the sequence:
- *
- * adc xxx
- * pha
- * txa
- * iny
- * adc yyy
- * tax
- * pla
- * ldy
- * jsr ldauidx
- *
- * and replace it by:
- *
- * adc xxx
- * sta ptr1
- * txa
- * iny
- * adc yyy
- * sta ptr1+1
- * ldy
- * ldx #$00
- * lda (ptr1),y
- */
+**
+** adc xxx
+** pha
+** txa
+** iny
+** adc yyy
+** tax
+** pla
+** ldy
+** jsr ldauidx
+**
+** and replace it by:
+**
+** adc xxx
+** sta ptr1
+** txa
+** iny
+** adc yyy
+** sta ptr1+1
+** ldy
+** ldx #$00
+** lda (ptr1),y
+*/
{
unsigned Changes = 0;
unsigned OptPtrLoad3 (CodeSeg* S)
/* Search for the sequence:
- *
- * lda #<(label+0)
- * ldx #>(label+0)
- * clc
- * adc xxx
- * bcc L
- * inx
- * L: ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * ldy xxx
- * ldx #$00
- * lda label,y
- */
+**
+** lda #<(label+0)
+** ldx #>(label+0)
+** clc
+** adc xxx
+** bcc L
+** inx
+** L: ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy xxx
+** ldx #$00
+** lda label,y
+*/
{
unsigned Changes = 0;
char* Label;
/* We will create all the new stuff behind the current one so
- * we keep the line references.
- */
+ ** we keep the line references.
+ */
X = NewCodeEntry (OP65_LDY, L[3]->AM, L[3]->Arg, 0, L[0]->LI);
CS_InsertEntry (S, X, I+8);
unsigned OptPtrLoad4 (CodeSeg* S)
/* Search for the sequence:
- *
- * lda #<(label+0)
- * ldx #>(label+0)
- * ldy #$xx
- * clc
- * adc (sp),y
- * bcc L
- * inx
- * L: ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * ldy #$xx
- * lda (sp),y
- * tay
- * ldx #$00
- * lda label,y
- */
+**
+** lda #<(label+0)
+** ldx #>(label+0)
+** ldy #$xx
+** clc
+** adc (sp),y
+** bcc L
+** inx
+** L: ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy #$xx
+** lda (sp),y
+** tay
+** ldx #$00
+** lda label,y
+*/
{
unsigned Changes = 0;
unsigned OptPtrLoad5 (CodeSeg* S)
/* Search for the sequence:
- *
- * jsr pushax
- * ldx #$00
- * lda yyy
- * jsr tosaddax
- * ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * sta ptr1
- * stx ptr1+1
- * ldy yyy
- * ldx #$00
- * lda (ptr1),y
- */
+**
+** jsr pushax
+** ldx #$00
+** lda yyy
+** jsr tosaddax
+** ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** sta ptr1
+** stx ptr1+1
+** ldy yyy
+** ldx #$00
+** lda (ptr1),y
+*/
{
unsigned Changes = 0;
unsigned OptPtrLoad6 (CodeSeg* S)
/* Search for the sequence:
- *
- * jsr pushax
- * ldy #xxx
- * ldx #$00
- * lda (sp),y
- * jsr tosaddax
- * ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * sta ptr1
- * stx ptr1+1
- * ldy #xxx-2
- * lda (sp),y
- * tay
- * ldx #$00
- * lda (ptr1),y
- */
+**
+** jsr pushax
+** ldy #xxx
+** ldx #$00
+** lda (sp),y
+** jsr tosaddax
+** ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** sta ptr1
+** stx ptr1+1
+** ldy #xxx-2
+** lda (sp),y
+** tay
+** ldx #$00
+** lda (ptr1),y
+*/
{
unsigned Changes = 0;
unsigned OptPtrLoad7 (CodeSeg* S)
/* Search for the sequence:
- *
- * jsr aslax1/shlax1
- * clc
- * adc xxx
- * tay
- * txa
- * adc yyy
- * tax
- * tya
- * ldy zzz
- * jsr ldaxidx
- *
- * and replace it by:
- *
- * stx tmp1
- * asl a
- * rol tmp1
- * clc
- * adc xxx
- * sta ptr1
- * lda tmp1
- * adc yyy
- * sta ptr1+1
- * ldy zzz
- * lda (ptr1),y
- * tax
- * dey
- * lda (ptr1),y
- */
+**
+** jsr aslax1/shlax1
+** clc
+** adc xxx
+** tay
+** txa
+** adc yyy
+** tax
+** tya
+** ldy zzz
+** jsr ldaxidx
+**
+** and replace it by:
+**
+** stx tmp1
+** asl a
+** rol tmp1
+** clc
+** adc xxx
+** sta ptr1
+** lda tmp1
+** adc yyy
+** sta ptr1+1
+** ldy zzz
+** lda (ptr1),y
+** tax
+** dey
+** lda (ptr1),y
+*/
{
unsigned Changes = 0;
unsigned I;
/* If X is zero on entry to aslax1, we can generate:
- *
- * asl a
- * bcc L1
- * inx
- * L1: clc
- *
- * instead of the code above. "lda tmp1" needs to be changed
- * to "txa" in this case.
- */
+ **
+ ** asl a
+ ** bcc L1
+ ** inx
+ ** L1: clc
+ **
+ ** instead of the code above. "lda tmp1" needs to be changed
+ ** to "txa" in this case.
+ */
int ShortCode = (L[0]->RI->In.RegX == 0);
if (ShortCode) {
unsigned OptPtrLoad11 (CodeSeg* S)
/* Search for the sequence:
- *
- * clc
- * adc xxx
- * bcc L
- * inx
- * L: ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * ldy xxx
- * sta ptr1
- * stx ptr1+1
- * ldx #$00
- * lda (ptr1),y
- */
+**
+** clc
+** adc xxx
+** bcc L
+** inx
+** L: ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy xxx
+** sta ptr1
+** stx ptr1+1
+** ldx #$00
+** lda (ptr1),y
+*/
{
unsigned Changes = 0;
CodeEntry* X;
/* We will create all the new stuff behind the current one so
- * we keep the line references.
- */
+ ** we keep the line references.
+ */
X = NewCodeEntry (OP65_LDY, L[1]->AM, L[1]->Arg, 0, L[0]->LI);
CS_InsertEntry (S, X, I+6);
unsigned OptPtrLoad12 (CodeSeg* S)
/* Search for the sequence:
- *
- * lda regbank+n
- * ldx regbank+n+1
- * sta regsave
- * stx regsave+1
- * clc
- * adc #$01
- * bcc L0005
- * inx
- * L: sta regbank+n
- * stx regbank+n+1
- * lda regsave
- * ldx regsave+1
- * ldy #$00
- * jsr ldauidx
- *
- * and replace it by:
- *
- * ldy #$00
- * ldx #$00
- * lda (regbank+n),y
- * inc regbank+n
- * bne L1
- * inc regbank+n+1
- * L1: tay <- only if flags are used
- *
- * This function must execute before OptPtrLoad7!
- *
- */
+**
+** lda regbank+n
+** ldx regbank+n+1
+** sta regsave
+** stx regsave+1
+** clc
+** adc #$01
+** bcc L0005
+** inx
+** L: sta regbank+n
+** stx regbank+n+1
+** lda regsave
+** ldx regsave+1
+** ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy #$00
+** ldx #$00
+** lda (regbank+n),y
+** inc regbank+n
+** bne L1
+** inc regbank+n+1
+** L1: tay <- only if flags are used
+**
+** This function must execute before OptPtrLoad7!
+**
+*/
{
unsigned Changes = 0;
CodeLabel* Label;
/* Check if the instruction following the sequence uses the flags
- * set by the load. If so, insert a test of the value in the
- * accumulator.
- */
+ ** set by the load. If so, insert a test of the value in the
+ ** accumulator.
+ */
if (CE_UseLoadFlags (L[14])) {
X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[13]->LI);
CS_InsertEntry (S, X, I+14);
}
/* Attach a label to L[14]. This may be either the just inserted
- * instruction, or the one following the sequence.
- */
+ ** instruction, or the one following the sequence.
+ */
Label = CS_GenLabel (S, L[14]);
/* ldy #$xx */
unsigned OptPtrLoad13 (CodeSeg* S)
/* Search for the sequence:
- *
- * lda zp
- * ldx zp+1
- * ldy xx
- * jsr ldauidx
- *
- * and replace it by:
- *
- * ldy xx
- * ldx #$00
- * lda (zp),y
- */
+**
+** lda zp
+** ldx zp+1
+** ldy xx
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy xx
+** ldx #$00
+** lda (zp),y
+*/
{
unsigned Changes = 0;
unsigned OptPtrLoad14 (CodeSeg* S)
/* Search for the sequence:
- *
- * lda zp
- * ldx zp+1
- * (anything that doesn't change a/x)
- * ldy xx
- * jsr ldauidx
- *
- * and replace it by:
- *
- * lda zp
- * ldx zp+1
- * (anything that doesn't change a/x)
- * ldy xx
- * ldx #$00
- * lda (zp),y
- *
- */
+**
+** lda zp
+** ldx zp+1
+** (anything that doesn't change a/x)
+** ldy xx
+** jsr ldauidx
+**
+** and replace it by:
+**
+** lda zp
+** ldx zp+1
+** (anything that doesn't change a/x)
+** ldy xx
+** ldx #$00
+** lda (zp),y
+*/
{
unsigned Changes = 0;
unsigned I;
unsigned OptPtrLoad15 (CodeSeg* S)
/* Search for the sequence:
- *
- * lda zp
- * ldx zp+1
- * jsr pushax <- optional
- * ldy xx
- * jsr ldaxidx
- *
- * and replace it by:
- *
- * lda zp <- only if
- * ldx zp+1 <- call to
- * jsr pushax <- pushax present
- * ldy xx
- * lda (zp),y
- * tax
- * dey
- * lda (zp),y
- */
+**
+** lda zp
+** ldx zp+1
+** jsr pushax <- optional
+** ldy xx
+** jsr ldaxidx
+**
+** and replace it by:
+**
+** lda zp <- only if
+** ldx zp+1 <- call to
+** jsr pushax <- pushax present
+** ldy xx
+** lda (zp),y
+** tax
+** dey
+** lda (zp),y
+*/
{
unsigned Changes = 0;
unsigned OptPtrLoad16 (CodeSeg* S)
/* Search for the sequence
- *
- * ldy ...
- * jsr ldauidx
- *
- * and replace it by:
- *
- * stx ptr1+1
- * sta ptr1
- * ldy ...
- * ldx #$00
- * lda (ptr1),y
- *
- * This step must be executed *after* OptPtrLoad1!
- */
+**
+** ldy ...
+** jsr ldauidx
+**
+** and replace it by:
+**
+** stx ptr1+1
+** sta ptr1
+** ldy ...
+** ldx #$00
+** lda (ptr1),y
+**
+** This step must be executed *after* OptPtrLoad1!
+*/
{
unsigned Changes = 0;
unsigned OptPtrLoad17 (CodeSeg* S)
/* Search for the sequence
- *
- * ldy ...
- * jsr ldaxidx
- *
- * and replace it by:
- *
- * sta ptr1
- * stx ptr1+1
- * ldy ...
- * lda (ptr1),y
- * tax
- * dey
- * lda (ptr1),y
- *
- * This step must be executed *after* OptPtrLoad9! While code size increases
- * by more than 200%, inlining will greatly improve visibility for the
- * optimizer, so often part of the code gets improved later. So we will mark
- * the step with less than 200% so it gets executed when -Oi is in effect.
- */
+**
+** ldy ...
+** jsr ldaxidx
+**
+** and replace it by:
+**
+** sta ptr1
+** stx ptr1+1
+** ldy ...
+** lda (ptr1),y
+** tax
+** dey
+** lda (ptr1),y
+**
+** This step must be executed *after* OptPtrLoad9! While code size increases
+** by more than 200%, inlining will greatly improve visibility for the
+** optimizer, so often part of the code gets improved later. So we will mark
+** the step with less than 200% so it gets executed when -Oi is in effect.
+*/
{
unsigned Changes = 0;
+unsigned OptPtrLoad18 (CodeSeg* S)
+/* Search for the sequence:
+**
+** ldx #$xx
+** lda #$yy
+** clc
+** adc xxx
+** bcc L
+** inx
+** L: ldy #$00
+** jsr ldauidx
+**
+** and replace it by:
+**
+** ldy xxx
+** ldx #$00
+** lda $xxyy,y
+**
+** This is similar to OptPtrLoad3 but works on a constant address
+** instead of a label. Also, the initial X and A loads are reversed.
+** Must be run before OptPtrLoad11.
+*/
+{
+ unsigned Changes = 0;
+
+ /* Walk over the entries */
+ unsigned I = 0;
+ while (I < CS_GetEntryCount (S)) {
+
+ CodeEntry* L[8];
+
+ /* Get next entry */
+ L[0] = CS_GetEntry (S, I);
+
+ /* Check for the sequence */
+ if (L[0]->OPC == OP65_LDX &&
+ L[0]->AM == AM65_IMM &&
+ CS_GetEntries (S, L+1, I+1, 7) &&
+ L[1]->OPC == OP65_LDA &&
+ L[1]->AM == AM65_IMM &&
+ L[2]->OPC == OP65_CLC &&
+ L[3]->OPC == OP65_ADC &&
+ (L[3]->AM == AM65_ABS || L[3]->AM == AM65_ZP) &&
+ (L[4]->OPC == OP65_BCC || L[4]->OPC == OP65_JCC) &&
+ L[4]->JumpTo != 0 &&
+ L[4]->JumpTo->Owner == L[6] &&
+ L[5]->OPC == OP65_INX &&
+ L[6]->OPC == OP65_LDY &&
+ CE_IsKnownImm (L[6], 0) &&
+ CE_IsCallTo (L[7], "ldauidx") &&
+ !CS_RangeHasLabel (S, I+1, 5) &&
+ !CE_HasLabel (L[7]) &&
+ strlen (L[0]->Arg) == 3 &&
+ L[0]->Arg[0] == '$' &&
+ strlen (L[1]->Arg) == 3 &&
+ L[1]->Arg[0] == '$' ) {
+
+ CodeEntry* X;
+ char* Label;
+
+ /* We will create all the new stuff behind the current one so
+ ** we keep the line references.
+ */
+ X = NewCodeEntry (OP65_LDY, L[3]->AM, L[3]->Arg, 0, L[0]->LI);
+ CS_InsertEntry (S, X, I+8);
+
+ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[0]->LI);
+ CS_InsertEntry (S, X, I+9);
+
+ Label = xmalloc(6);
+ sprintf(Label, "$%s%s", L[0]->Arg+1, L[1]->Arg+1);
+ X = NewCodeEntry (OP65_LDA, AM65_ABSY, Label, 0, L[0]->LI);
+ CS_InsertEntry (S, X, I+10);
+ xfree (Label);
+
+ /* Remove the old code */
+ CS_DelEntries (S, I, 8);
+
+ /* Remember, we had changes */
+ ++Changes;
+
+ }
+
+ /* Next entry */
+ ++I;
+
+ }
+
+ /* Return the number of changes made */
+ return Changes;
+}
+
+
+
+unsigned OptPtrLoad19 (CodeSeg* S)
+/* Search for the sequence:
+**
+** ldx #0
+** and #mask (any value < 128)
+** jsr aslax1/shlax1
+** clc
+** adc #<(label+0)
+** tay
+** txa
+** adc #>(label+0)
+** tax
+** tya
+** ldy #$01
+** jsr ldaxidx
+**
+** and replace it by:
+**
+** ldx #0
+** and #mask (remove if == 127)
+** asl
+** tay
+** lda label,y
+** ldx label+1,y
+*/
+{
+ unsigned Changes = 0;
+ unsigned I;
+
+ /* Walk over the entries */
+ I = 0;
+ while (I < CS_GetEntryCount (S)) {
+
+ CodeEntry* L[12];
+
+ /* Get next entry */
+ L[0] = CS_GetEntry (S, I);
+
+ /* Check for the sequence */
+ if (L[0]->OPC == OP65_LDX &&
+ CE_IsKnownImm(L[0], 0) &&
+ CS_GetEntries (S, L+1, I+1, 11) &&
+ L[1]->OPC == OP65_AND &&
+ L[1]->AM == AM65_IMM &&
+ CE_HasNumArg (L[1]) && L[1]->Num <= 127 &&
+ L[2]->OPC == OP65_JSR &&
+ (strcmp (L[2]->Arg, "aslax1") == 0 ||
+ strcmp (L[2]->Arg, "shlax1") == 0) &&
+ L[3]->OPC == OP65_CLC &&
+ L[4]->OPC == OP65_ADC &&
+ L[5]->OPC == OP65_TAY &&
+ L[6]->OPC == OP65_TXA &&
+ L[7]->OPC == OP65_ADC &&
+ L[8]->OPC == OP65_TAX &&
+ L[9]->OPC == OP65_TYA &&
+ L[10]->OPC == OP65_LDY &&
+ CE_IsKnownImm(L[10], 1) &&
+ strlen(L[4]->Arg) >= 3 &&
+ L[4]->Arg[0] == '<' &&
+ strlen(L[7]->Arg) >= 3 &&
+ L[7]->Arg[0] == '>' &&
+ !strcmp(L[4]->Arg+1, L[7]->Arg+1) &&
+ CE_IsCallTo (L[11], "ldaxidx") &&
+ !CS_RangeHasLabel (S, I+1, 11)) {
+
+ CodeEntry* X;
+ char* Label;
+ int Len = strlen(L[4]->Arg);
+
+ /* Track the insertion point */
+ unsigned IP = I + 12;
+
+ /* asl a */
+ X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, L[2]->LI);
+ CS_InsertEntry (S, X, IP++);
+
+ /* tay */
+ X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[2]->LI);
+ CS_InsertEntry (S, X, IP++);
+
+ /* lda label,y */
+ Label = memcpy (xmalloc (Len-2), L[4]->Arg+2, Len-3);
+ Label[Len-3] = '\0';
+ X = NewCodeEntry (OP65_LDA, AM65_ABSY, Label, 0, L[10]->LI);
+ CS_InsertEntry (S, X, IP++);
+ xfree (Label);
+
+ /* lda label+1,y */
+ Label = memcpy (xmalloc (Len), L[4]->Arg+2, Len-3);
+ strcpy(&Label[Len-3], "+1");
+ X = NewCodeEntry (OP65_LDX, AM65_ABSY, Label, 0, L[10]->LI);
+ CS_InsertEntry (S, X, IP++);
+ xfree (Label);
+
+ /* Remove the old code */
+ /* Remove the AND only if it's == 127, since ASL erases high bit */
+ if (L[1]->Num == 127)
+ CS_DelEntries (S, I+1, 11);
+ else
+ CS_DelEntries (S, I+2, 10);
+ /* Remove the ldx #0 */
+ CS_DelEntry(S, I);
+
+ /* Remember, we had changes */
+ ++Changes;
+
+ }
+
+ /* Next entry */
+ ++I;
+
+ }
+
+ /* Return the number of changes made */
+ return Changes;
+}
+
+
+