]> git.sur5r.net Git - cc65/blob - src/cc65/coptptrload.c
Fixed a problem with OptPtrLoad6 (must correct stack pointer).
[cc65] / src / cc65 / coptptrload.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                               coptptrload.c                               */
4 /*                                                                           */
5 /*                      Optimize loads through pointers                      */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2001-2009 Ullrich von Bassewitz                                       */
10 /*               Roemerstrasse 52                                            */
11 /*               D-70794 Filderstadt                                         */
12 /* EMail:        uz@cc65.org                                                 */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <string.h>
37
38 /* common */
39 #include "xmalloc.h"
40
41 /* cc65 */
42 #include "codeent.h"
43 #include "codeinfo.h"
44 #include "coptptrload.h"
45
46
47
48 /*****************************************************************************/
49 /*                                   Code                                    */
50 /*****************************************************************************/
51
52
53
54 unsigned OptPtrLoad1 (CodeSeg* S)
55 /* Search for the sequence:
56  *
57  *      clc
58  *      adc     xxx
59  *      tay
60  *      txa
61  *      adc     yyy
62  *      tax
63  *      tya
64  *      ldy     #$00
65  *      jsr     ldauidx
66  *
67  * and replace it by:
68  *
69  *      sta     ptr1
70  *      txa
71  *      clc
72  *      adc     yyy
73  *      sta     ptr1+1
74  *      ldy     xxx
75  *      ldx     #$00
76  *      lda     (ptr1),y
77  */
78 {
79     unsigned Changes = 0;
80
81     /* Walk over the entries */
82     unsigned I = 0;
83     while (I < CS_GetEntryCount (S)) {
84
85         CodeEntry* L[9];
86
87         /* Get next entry */
88         L[0] = CS_GetEntry (S, I);
89
90         /* Check for the sequence */
91         if (L[0]->OPC == OP65_CLC               &&
92             CS_GetEntries (S, L+1, I+1, 8)      &&
93             L[1]->OPC == OP65_ADC               &&
94             (L[1]->AM == AM65_ABS          ||
95              L[1]->AM == AM65_ZP           ||
96              L[1]->AM == AM65_IMM)              &&
97             L[2]->OPC == OP65_TAY               &&
98             L[3]->OPC == OP65_TXA               &&
99             L[4]->OPC == OP65_ADC               &&
100             L[5]->OPC == OP65_TAX               &&
101             L[6]->OPC == OP65_TYA               &&
102             L[7]->OPC == OP65_LDY               &&
103             CE_IsKnownImm (L[7], 0)             &&
104             CE_IsCallTo (L[8], "ldauidx")       &&
105             !CS_RangeHasLabel (S, I+1, 8)) {
106
107             CodeEntry* X;
108             CodeEntry* P;
109
110             /* Track the insertion point */
111             unsigned IP = I;
112
113             /* sta ptr1 */
114             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[2]->LI);
115             CS_InsertEntry (S, X, IP++);
116
117             /* If the instruction before the clc is a ldx, replace the
118              * txa by an lda with the same location of the ldx. Otherwise
119              * transfer the value in X to A.
120              */
121             if ((P = CS_GetPrevEntry (S, I)) != 0 &&
122                 P->OPC == OP65_LDX                &&
123                 !CE_HasLabel (P)) {
124                 X = NewCodeEntry (OP65_LDA, P->AM, P->Arg, 0, P->LI);
125             } else {
126                 X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, L[3]->LI);
127             }
128             CS_InsertEntry (S, X, IP++);
129
130             /* clc is now in the right place */
131             ++IP;
132
133             /* adc yyy */
134             X = NewCodeEntry (OP65_ADC, L[4]->AM, L[4]->Arg, 0, L[4]->LI);
135             CS_InsertEntry (S, X, IP++);
136
137             /* sta ptr1+1 */
138             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1+1", 0, L[5]->LI);
139             CS_InsertEntry (S, X, IP++);
140
141             /* ldy xxx */
142             X = NewCodeEntry (OP65_LDY, L[1]->AM, L[1]->Arg, 0, L[1]->LI);
143             CS_InsertEntry (S, X, IP++);
144
145             /* ldx #$00 */
146             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[8]->LI);
147             CS_InsertEntry (S, X, IP++);
148
149             /* lda (ptr1),y */
150             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[8]->LI);
151             CS_InsertEntry (S, X, IP++);
152
153             /* Remove the old instructions */
154             CS_DelEntries (S, IP, 8);
155
156             /* Remember, we had changes */
157             ++Changes;
158
159         }
160
161         /* Next entry */
162         ++I;
163
164     }
165
166     /* Return the number of changes made */
167     return Changes;
168 }
169
170
171
172 unsigned OptPtrLoad2 (CodeSeg* S)
173 /* Search for the sequence:
174  *
175  *      adc     xxx
176  *      pha
177  *      txa
178  *      iny
179  *      adc     yyy
180  *      tax
181  *      pla
182  *      ldy
183  *      jsr     ldauidx
184  *
185  * and replace it by:
186  *
187  *      adc     xxx
188  *      sta     ptr1
189  *      txa
190  *      iny
191  *      adc     yyy
192  *      sta     ptr1+1
193  *      ldy
194  *      ldx     #$00
195  *      lda     (ptr1),y
196  */
197 {
198     unsigned Changes = 0;
199
200     /* Walk over the entries */
201     unsigned I = 0;
202     while (I < CS_GetEntryCount (S)) {
203
204         CodeEntry* L[9];
205
206         /* Get next entry */
207         L[0] = CS_GetEntry (S, I);
208
209         /* Check for the sequence */
210         if (L[0]->OPC == OP65_ADC               &&
211             CS_GetEntries (S, L+1, I+1, 8)      &&
212             L[1]->OPC == OP65_PHA               &&
213             L[2]->OPC == OP65_TXA               &&
214             L[3]->OPC == OP65_INY               &&
215             L[4]->OPC == OP65_ADC               &&
216             L[5]->OPC == OP65_TAX               &&
217             L[6]->OPC == OP65_PLA               &&
218             L[7]->OPC == OP65_LDY               &&
219             CE_IsCallTo (L[8], "ldauidx")       &&
220             !CS_RangeHasLabel (S, I+1, 8)) {
221
222             CodeEntry* X;
223
224             /* Store the low byte and remove the PHA instead */
225             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI);
226             CS_InsertEntry (S, X, I+1);
227
228             /* Store the high byte */
229             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1+1", 0, L[4]->LI);
230             CS_InsertEntry (S, X, I+6);
231
232             /* Load high and low byte */
233             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[6]->LI);
234             CS_InsertEntry (S, X, I+10);
235             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[6]->LI);
236             CS_InsertEntry (S, X, I+11);
237
238             /* Delete the old code */
239             CS_DelEntry (S, I+12);      /* jsr ldauidx */
240             CS_DelEntry (S, I+8);       /* pla */
241             CS_DelEntry (S, I+7);       /* tax */
242             CS_DelEntry (S, I+2);       /* pha */
243
244             /* Remember, we had changes */
245             ++Changes;
246
247         }
248
249         /* Next entry */
250         ++I;
251
252     }
253
254     /* Return the number of changes made */
255     return Changes;
256 }
257
258
259
260 unsigned OptPtrLoad3 (CodeSeg* S)
261 /* Search for the sequence:
262  *
263  *      lda     #<(label+0)
264  *      ldx     #>(label+0)
265  *      clc
266  *      adc     xxx
267  *      bcc     L
268  *      inx
269  * L:   ldy     #$00
270  *      jsr     ldauidx
271  *
272  * and replace it by:
273  *
274  *      ldy     xxx
275  *      ldx     #$00
276  *      lda     label,y
277  */
278 {
279     unsigned Changes = 0;
280
281     /* Walk over the entries */
282     unsigned I = 0;
283     while (I < CS_GetEntryCount (S)) {
284
285         CodeEntry* L[8];
286         unsigned Len;
287
288         /* Get next entry */
289         L[0] = CS_GetEntry (S, I);
290
291         /* Check for the sequence */
292         if (L[0]->OPC == OP65_LDA                            &&
293             L[0]->AM == AM65_IMM                             &&
294             CS_GetEntries (S, L+1, I+1, 7)                   &&
295             L[1]->OPC == OP65_LDX                            &&
296             L[1]->AM == AM65_IMM                             &&
297             L[2]->OPC == OP65_CLC                            &&
298             L[3]->OPC == OP65_ADC                            &&
299             (L[3]->AM == AM65_ABS || L[3]->AM == AM65_ZP)    &&
300             (L[4]->OPC == OP65_BCC || L[4]->OPC == OP65_JCC) &&
301             L[4]->JumpTo != 0                                &&
302             L[4]->JumpTo->Owner == L[6]                      &&
303             L[5]->OPC == OP65_INX                            &&
304             L[6]->OPC == OP65_LDY                            &&
305             CE_IsKnownImm (L[6], 0)                          &&
306             CE_IsCallTo (L[7], "ldauidx")                    &&
307             !CS_RangeHasLabel (S, I+1, 5)                    &&
308             !CE_HasLabel (L[7])                              &&
309             /* Check the label last because this is quite costly */
310             (Len = strlen (L[0]->Arg)) > 3                   &&
311             L[0]->Arg[0] == '<'                              &&
312             L[0]->Arg[1] == '('                              &&
313             strlen (L[1]->Arg) == Len                        &&
314             L[1]->Arg[0] == '>'                              &&
315             memcmp (L[0]->Arg+1, L[1]->Arg+1, Len-1) == 0) {
316
317             CodeEntry* X;
318             char* Label;
319
320             /* We will create all the new stuff behind the current one so
321              * we keep the line references.
322              */
323             X = NewCodeEntry (OP65_LDY, L[3]->AM, L[3]->Arg, 0, L[0]->LI);
324             CS_InsertEntry (S, X, I+8);
325
326             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[0]->LI);
327             CS_InsertEntry (S, X, I+9);
328
329             Label = memcpy (xmalloc (Len-2), L[0]->Arg+2, Len-3);
330             Label[Len-3] = '\0';
331             X = NewCodeEntry (OP65_LDA, AM65_ABSY, Label, 0, L[0]->LI);
332             CS_InsertEntry (S, X, I+10);
333             xfree (Label);
334
335             /* Remove the old code */
336             CS_DelEntries (S, I, 8);
337
338             /* Remember, we had changes */
339             ++Changes;
340
341         }
342
343         /* Next entry */
344         ++I;
345
346     }
347
348     /* Return the number of changes made */
349     return Changes;
350 }
351
352
353
354 unsigned OptPtrLoad4 (CodeSeg* S)
355 /* Search for the sequence:
356  *
357  *      lda     #<(label+0)
358  *      ldx     #>(label+0)
359  *      ldy     #$xx
360  *      clc
361  *      adc     (sp),y
362  *      bcc     L
363  *      inx
364  * L:   ldy     #$00
365  *      jsr     ldauidx
366  *
367  * and replace it by:
368  *
369  *      ldy     #$xx
370  *      lda     (sp),y
371  *      tay
372  *      ldx     #$00
373  *      lda     label,y
374  */
375 {
376     unsigned Changes = 0;
377
378     /* Walk over the entries */
379     unsigned I = 0;
380     while (I < CS_GetEntryCount (S)) {
381
382         CodeEntry* L[9];
383         unsigned Len;
384
385         /* Get next entry */
386         L[0] = CS_GetEntry (S, I);
387
388         /* Check for the sequence */
389         if (L[0]->OPC == OP65_LDA                            &&
390             L[0]->AM == AM65_IMM                             &&
391             CS_GetEntries (S, L+1, I+1, 8)                   &&
392             L[1]->OPC == OP65_LDX                            &&
393             L[1]->AM == AM65_IMM                             &&
394             !CE_HasLabel (L[1])                              &&
395             L[2]->OPC == OP65_LDY                            &&
396             CE_IsConstImm (L[2])                             &&
397             !CE_HasLabel (L[2])                              &&
398             L[3]->OPC == OP65_CLC                            &&
399             !CE_HasLabel (L[3])                              &&
400             L[4]->OPC == OP65_ADC                            &&
401             L[4]->AM == AM65_ZP_INDY                         &&
402             !CE_HasLabel (L[4])                              &&
403             (L[5]->OPC == OP65_BCC || L[5]->OPC == OP65_JCC) &&
404             L[5]->JumpTo != 0                                &&
405             L[5]->JumpTo->Owner == L[7]                      &&
406             !CE_HasLabel (L[5])                              &&
407             L[6]->OPC == OP65_INX                            &&
408             !CE_HasLabel (L[6])                              &&
409             L[7]->OPC == OP65_LDY                            &&
410             CE_IsKnownImm (L[7], 0)                          &&
411             CE_IsCallTo (L[8], "ldauidx")                    &&
412             !CE_HasLabel (L[8])                              &&
413             /* Check the label last because this is quite costly */
414             (Len = strlen (L[0]->Arg)) > 3                   &&
415             L[0]->Arg[0] == '<'                              &&
416             L[0]->Arg[1] == '('                              &&
417             strlen (L[1]->Arg) == Len                        &&
418             L[1]->Arg[0] == '>'                              &&
419             memcmp (L[0]->Arg+1, L[1]->Arg+1, Len-1) == 0) {
420
421             CodeEntry* X;
422             char* Label;
423
424             /* Add the lda */
425             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[4]->Arg, 0, L[0]->LI);
426             CS_InsertEntry (S, X, I+3);
427
428             /* Add the tay */
429             X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[0]->LI);
430             CS_InsertEntry (S, X, I+4);
431
432             /* Add the ldx */
433             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[0]->LI);
434             CS_InsertEntry (S, X, I+5);
435
436             /* Add the lda */
437             Label = memcpy (xmalloc (Len-2), L[0]->Arg+2, Len-3);
438             Label[Len-3] = '\0';
439             X = NewCodeEntry (OP65_LDA, AM65_ABSY, Label, 0, L[0]->LI);
440             CS_InsertEntry (S, X, I+6);
441             xfree (Label);
442
443             /* Remove the old code */
444             CS_DelEntries (S, I, 2);
445             CS_DelEntries (S, I+5, 6);
446
447             /* Remember, we had changes */
448             ++Changes;
449
450         }
451
452         /* Next entry */
453         ++I;
454
455     }
456
457     /* Return the number of changes made */
458     return Changes;
459 }
460
461
462
463 unsigned OptPtrLoad5 (CodeSeg* S)
464 /* Search for the sequence:
465  *
466  *      jsr     pushax
467  *      ldx     #$00
468  *      lda     yyy
469  *      jsr     tosaddax
470  *      ldy     #$00
471  *      jsr     ldauidx
472  *
473  * and replace it by:
474  *
475  *      sta     ptr1
476  *      stx     ptr1+1
477  *      ldy     yyy
478  *      ldx     #$00
479  *      lda     (ptr1),y
480  */
481 {
482     unsigned Changes = 0;
483
484     /* Walk over the entries */
485     unsigned I = 0;
486     while (I < CS_GetEntryCount (S)) {
487
488         CodeEntry* L[6];
489
490         /* Get next entry */
491         L[0] = CS_GetEntry (S, I);
492
493         /* Check for the sequence */
494         if (CE_IsCallTo (L[0], "pushax")                &&
495             CS_GetEntries (S, L+1, I+1, 5)              &&
496             L[1]->OPC == OP65_LDX                       &&
497             CE_IsKnownImm (L[1], 0)                     &&
498             L[2]->OPC == OP65_LDA                       &&
499             (L[2]->AM == AM65_ABS       ||
500              L[2]->AM == AM65_ZP        ||
501              L[2]->AM == AM65_IMM)                      &&
502             CE_IsCallTo (L[3], "tosaddax")              &&
503             L[4]->OPC == OP65_LDY                       &&
504             CE_IsKnownImm (L[4], 0)                     &&
505             CE_IsCallTo (L[5], "ldauidx")               &&
506             !CS_RangeHasLabel (S, I+1, 5)) {
507
508             CodeEntry* X;
509
510             /* sta ptr1 */
511             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI);
512             CS_InsertEntry (S, X, I+6);
513
514             /* stx ptr1+1 */
515             X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI);
516             CS_InsertEntry (S, X, I+7);
517
518             /* ldy yyy */
519             X = NewCodeEntry (OP65_LDY, L[2]->AM, L[2]->Arg, 0, L[2]->LI);
520             CS_InsertEntry (S, X, I+8);
521
522             /* ldx #$00 */
523             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[5]->LI);
524             CS_InsertEntry (S, X, I+9);
525
526             /* lda (ptr1),y */
527             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[5]->LI);
528             CS_InsertEntry (S, X, I+10);
529
530             /* Remove the old code */
531             CS_DelEntries (S, I, 6);
532
533             /* Remember, we had changes */
534             ++Changes;
535
536         }
537
538         /* Next entry */
539         ++I;
540
541     }
542
543     /* Return the number of changes made */
544     return Changes;
545 }
546
547
548
549 unsigned OptPtrLoad6 (CodeSeg* S)
550 /* Search for the sequence:
551  *
552  *      jsr     pushax
553  *      ldy     #xxx
554  *      ldx     #$00
555  *      lda     (sp),y
556  *      jsr     tosaddax
557  *      ldy     #$00
558  *      jsr     ldauidx
559  *
560  * and replace it by:
561  *
562  *      sta     ptr1
563  *      stx     ptr1+1
564  *      ldy     #xxx-2
565  *      lda     (sp),y
566  *      tay
567  *      ldx     #$00
568  *      lda     (ptr1),y
569  *      ldy     #$00
570  */
571 {
572     unsigned Changes = 0;
573
574     /* Walk over the entries */
575     unsigned I = 0;
576     while (I < CS_GetEntryCount (S)) {
577
578         CodeEntry* L[7];
579
580         /* Get next entry */
581         L[0] = CS_GetEntry (S, I);
582
583         /* Check for the sequence */
584         if (CE_IsCallTo (L[0], "pushax")                &&
585             CS_GetEntries (S, L+1, I+1, 6)              &&
586             L[1]->OPC == OP65_LDY                       &&
587             CE_IsConstImm (L[1])                        &&
588             L[1]->Num >= 2                              &&
589             L[2]->OPC == OP65_LDX                       &&
590             CE_IsKnownImm (L[2], 0)                     &&
591             L[3]->OPC == OP65_LDA                       &&
592             L[3]->AM == AM65_ZP_INDY                    &&
593             CE_IsCallTo (L[4], "tosaddax")              &&
594             L[5]->OPC == OP65_LDY                       &&
595             CE_IsKnownImm (L[5], 0)                     &&
596             CE_IsCallTo (L[6], "ldauidx")               &&
597             !CS_RangeHasLabel (S, I+1, 6)) {
598
599             CodeEntry*  X;
600             const char* Arg;
601
602             /* sta ptr1 */
603             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI);
604             CS_InsertEntry (S, X, I+7);
605
606             /* stx ptr1+1 */
607             X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI);
608             CS_InsertEntry (S, X, I+8);
609
610             /* ldy #xxx-2 */
611             Arg = MakeHexArg (L[1]->Num - 2);
612             X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI);
613             CS_InsertEntry (S, X, I+9);
614
615             /* lda (sp),y */
616             X = NewCodeEntry (OP65_LDA, L[3]->AM, L[3]->Arg, 0, L[3]->LI);
617             CS_InsertEntry (S, X, I+10);
618
619             /* tay */
620             X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[3]->LI);
621             CS_InsertEntry (S, X, I+11);
622
623             /* ldx #$00 */
624             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[5]->LI);
625             CS_InsertEntry (S, X, I+12);
626
627             /* lda (ptr1),y */
628             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[6]->LI);
629             CS_InsertEntry (S, X, I+13);
630
631             /* ldy #$00 (will eventually get removed later) */
632             X = NewCodeEntry (OP65_LDY, AM65_IMM, "$00", 0, L[5]->LI);
633             CS_InsertEntry (S, X, I+14);
634
635             /* Remove the old code */
636             CS_DelEntries (S, I, 7);
637
638             /* Remember, we had changes */
639             ++Changes;
640
641         }
642
643         /* Next entry */
644         ++I;
645
646     }
647
648     /* Return the number of changes made */
649     return Changes;
650 }
651
652
653
654 unsigned OptPtrLoad7 (CodeSeg* S)
655 /* Search for the sequence:
656  *
657  *      jsr     aslax1/shlax1
658  *      clc
659  *      adc     xxx
660  *      tay
661  *      txa
662  *      adc     yyy
663  *      tax
664  *      tya
665  *      ldy     zzz
666  *      jsr     ldaxidx
667  *
668  * and replace it by:
669  *
670  *      stx     tmp1
671  *      asl     a
672  *      rol     tmp1
673  *      clc
674  *      adc     xxx
675  *      sta     ptr1
676  *      lda     tmp1
677  *      adc     yyy
678  *      sta     ptr1+1
679  *      ldy     zzz
680  *      lda     (ptr1),y
681  *      tax
682  *      dey
683  *      lda     (ptr1),y
684  */
685 {
686     unsigned Changes = 0;
687     unsigned I;
688
689     /* Generate register info */
690     CS_GenRegInfo (S);
691
692     /* Walk over the entries */
693     I = 0;
694     while (I < CS_GetEntryCount (S)) {
695
696         CodeEntry* L[10];
697
698         /* Get next entry */
699         L[0] = CS_GetEntry (S, I);
700
701         /* Check for the sequence */
702         if (L[0]->OPC == OP65_JSR                               &&
703             (strcmp (L[0]->Arg, "aslax1") == 0          ||
704              strcmp (L[0]->Arg, "shlax1") == 0)                 &&
705             CS_GetEntries (S, L+1, I+1, 9)                      &&
706             L[1]->OPC == OP65_CLC                               &&
707             L[2]->OPC == OP65_ADC                               &&
708             L[3]->OPC == OP65_TAY                               &&
709             L[4]->OPC == OP65_TXA                               &&
710             L[5]->OPC == OP65_ADC                               &&
711             L[6]->OPC == OP65_TAX                               &&
712             L[7]->OPC == OP65_TYA                               &&
713             L[8]->OPC == OP65_LDY                               &&
714             CE_IsCallTo (L[9], "ldaxidx")                       &&
715             !CS_RangeHasLabel (S, I+1, 9)) {
716
717             CodeEntry* X;
718
719             /* Track the insertion point */
720             unsigned IP = I + 10;
721
722
723             /* If X is zero on entry to aslax1, we can generate:
724              *
725              *      asl     a
726              *      bcc     L1
727              *      inx
728              * L1:  clc
729              *
730              * instead of the code above. "lda tmp1" needs to be changed
731              * to "txa" in this case.
732              */
733             int ShortCode = (L[0]->RI->In.RegX == 0);
734
735             if (ShortCode) {
736
737                 CodeLabel* Lab;
738
739                 /* asl a */
740                 X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, L[0]->LI);
741                 CS_InsertEntry (S, X, IP++);
742
743                 /* Generate clc first, since we need the label */
744                 X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[1]->LI);
745                 CS_InsertEntry (S, X, IP);
746
747                 /* Get the label */
748                 Lab = CS_GenLabel (S, X);
749
750                 /* bcc Lab */
751                 X = NewCodeEntry (OP65_BCC, AM65_BRA, Lab->Name, Lab, L[0]->LI);
752                 CS_InsertEntry (S, X, IP++);
753
754                 /* inx */
755                 X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, L[0]->LI);
756                 CS_InsertEntry (S, X, IP++);
757
758                 /* Skip the clc insn */
759                 ++IP;
760
761             } else {
762
763                 /* stx tmp1 */
764                 X = NewCodeEntry (OP65_STX, AM65_ZP, "tmp1", 0, L[0]->LI);
765                 CS_InsertEntry (S, X, IP++);
766
767                 /* asl a */
768                 X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, L[0]->LI);
769                 CS_InsertEntry (S, X, IP++);
770
771                 /* rol tmp1 */
772                 X = NewCodeEntry (OP65_ROL, AM65_ZP, "tmp1", 0, L[0]->LI);
773                 CS_InsertEntry (S, X, IP++);
774
775                 /* clc */
776                 X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[1]->LI);
777                 CS_InsertEntry (S, X, IP++);
778
779             }
780
781             /* adc xxx */
782             X = NewCodeEntry (L[2]->OPC, L[2]->AM, L[2]->Arg, 0, L[2]->LI);
783             CS_InsertEntry (S, X, IP++);
784
785             /* sta ptr1 */
786             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[9]->LI);
787             CS_InsertEntry (S, X, IP++);
788
789             if (ShortCode) {
790                 /* txa */
791                 X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, L[4]->LI);
792             } else {
793                 /* lda tmp1 */
794                 X = NewCodeEntry (OP65_LDA, AM65_ZP, "tmp1", 0, L[4]->LI);
795             }
796             CS_InsertEntry (S, X, IP++);
797
798             /* adc xxx */
799             X = NewCodeEntry (L[5]->OPC, L[5]->AM, L[5]->Arg, 0, L[5]->LI);
800             CS_InsertEntry (S, X, IP++);
801
802             /* sta ptr1+1 */
803             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1+1", 0, L[9]->LI);
804             CS_InsertEntry (S, X, IP++);
805
806             /* ldy zzz */
807             X = NewCodeEntry (L[8]->OPC, L[8]->AM, L[8]->Arg, 0, L[8]->LI);
808             CS_InsertEntry (S, X, IP++);
809
810             /* lda (ptr1),y */
811             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[9]->LI);
812             CS_InsertEntry (S, X, IP++);
813
814             /* tax */
815             X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[9]->LI);
816             CS_InsertEntry (S, X, IP++);
817
818             /* dey */
819             X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[9]->LI);
820             CS_InsertEntry (S, X, IP++);
821
822             /* lda (ptr1),y */
823             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[9]->LI);
824             CS_InsertEntry (S, X, IP++);
825
826             /* Remove the old code */
827             CS_DelEntries (S, I, 10);
828
829             /* Remember, we had changes */
830             ++Changes;
831
832         }
833
834         /* Next entry */
835         ++I;
836
837     }
838
839     /* Free the register info */
840     CS_FreeRegInfo (S);
841
842     /* Return the number of changes made */
843     return Changes;
844 }
845
846
847
848 unsigned OptPtrLoad11 (CodeSeg* S)
849 /* Search for the sequence:
850  *
851  *      clc
852  *      adc     xxx
853  *      bcc     L
854  *      inx
855  * L:   ldy     #$00
856  *      jsr     ldauidx
857  *
858  * and replace it by:
859  *
860  *      ldy     xxx
861  *      sta     ptr1
862  *      stx     ptr1+1
863  *      ldx     #$00
864  *      lda     (ptr1),y
865  */
866 {
867     unsigned Changes = 0;
868
869     /* Walk over the entries */
870     unsigned I = 0;
871     while (I < CS_GetEntryCount (S)) {
872
873         CodeEntry* L[6];
874
875         /* Get next entry */
876         L[0] = CS_GetEntry (S, I);
877
878         /* Check for the sequence */
879         if (L[0]->OPC == OP65_CLC                            &&
880             CS_GetEntries (S, L+1, I+1, 5)                   &&
881             L[1]->OPC == OP65_ADC                            &&
882             (L[1]->AM == AM65_ABS || L[1]->AM == AM65_ZP || L[1]->AM == AM65_IMM)    &&
883             (L[2]->OPC == OP65_BCC || L[2]->OPC == OP65_JCC) &&
884             L[2]->JumpTo != 0                                &&
885             L[2]->JumpTo->Owner == L[4]                      &&
886             L[3]->OPC == OP65_INX                            &&
887             L[4]->OPC == OP65_LDY                            &&
888             CE_IsKnownImm (L[4], 0)                          &&
889             CE_IsCallTo (L[5], "ldauidx")                    &&
890             !CS_RangeHasLabel (S, I+1, 3)                    &&
891             !CE_HasLabel (L[5])) {
892
893             CodeEntry* X;
894
895             /* We will create all the new stuff behind the current one so
896              * we keep the line references.
897              */
898             X = NewCodeEntry (OP65_LDY, L[1]->AM, L[1]->Arg, 0, L[0]->LI);
899             CS_InsertEntry (S, X, I+6);
900
901             /* sta ptr1 */
902             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI);
903             CS_InsertEntry (S, X, I+7);
904
905             /* stx ptr1+1 */
906             X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI);
907             CS_InsertEntry (S, X, I+8);
908
909             /* ldx #$00 */
910             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[0]->LI);
911             CS_InsertEntry (S, X, I+9);
912
913             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[0]->LI);
914             CS_InsertEntry (S, X, I+10);
915
916             /* Remove the old code */
917             CS_DelEntries (S, I, 6);
918
919             /* Remember, we had changes */
920             ++Changes;
921
922         }
923
924         /* Next entry */
925         ++I;
926
927     }
928
929     /* Return the number of changes made */
930     return Changes;
931 }
932
933
934
935 unsigned OptPtrLoad12 (CodeSeg* S)
936 /* Search for the sequence:
937  *
938  *      lda     regbank+n
939  *      ldx     regbank+n+1
940  *      sta     regsave
941  *      stx     regsave+1
942  *      clc
943  *      adc     #$01
944  *      bcc     L0005
945  *      inx
946  * L:   sta     regbank+n
947  *      stx     regbank+n+1
948  *      lda     regsave
949  *      ldx     regsave+1
950  *      ldy     #$00
951  *      jsr     ldauidx
952  *
953  * and replace it by:
954  *
955  *      ldy     #$00
956  *      ldx     #$00
957  *      lda     (regbank+n),y
958  *      inc     regbank+n
959  *      bne     L1
960  *      inc     regbank+n+1
961  * L1:  tay                     <- only if flags are used
962  *
963  * This function must execute before OptPtrLoad7!
964  *
965  */
966 {
967     unsigned Changes = 0;
968
969     /* Walk over the entries */
970     unsigned I = 0;
971     while (I < CS_GetEntryCount (S)) {
972
973         CodeEntry* L[15];
974         unsigned Len;
975
976         /* Get next entry */
977         L[0] = CS_GetEntry (S, I);
978
979         /* Check for the sequence */
980         if (L[0]->OPC == OP65_LDA                               &&
981             L[0]->AM == AM65_ZP                                 &&
982             strncmp (L[0]->Arg, "regbank+", 8) == 0             &&
983             (Len = strlen (L[0]->Arg)) > 0                      &&
984             CS_GetEntries (S, L+1, I+1, 14)                     &&
985             !CS_RangeHasLabel (S, I+1, 7)                       &&
986             !CS_RangeHasLabel (S, I+9, 5)                       &&
987             L[1]->OPC == OP65_LDX                               &&
988             L[1]->AM == AM65_ZP                                 &&
989             strncmp (L[1]->Arg, L[0]->Arg, Len) == 0            &&
990             strcmp (L[1]->Arg+Len, "+1") == 0                   &&
991             L[2]->OPC == OP65_STA                               &&
992             L[2]->AM == AM65_ZP                                 &&
993             strcmp (L[2]->Arg, "regsave") == 0                  &&
994             L[3]->OPC == OP65_STX                               &&
995             L[3]->AM == AM65_ZP                                 &&
996             strcmp (L[3]->Arg, "regsave+1") == 0                &&
997             L[4]->OPC == OP65_CLC                               &&
998             L[5]->OPC == OP65_ADC                               &&
999             CE_IsKnownImm (L[5], 1)                             &&
1000             L[6]->OPC == OP65_BCC                               &&
1001             L[6]->JumpTo != 0                                   &&
1002             L[6]->JumpTo->Owner == L[8]                         &&
1003             L[7]->OPC == OP65_INX                               &&
1004             L[8]->OPC == OP65_STA                               &&
1005             L[8]->AM == AM65_ZP                                 &&
1006             strcmp (L[8]->Arg, L[0]->Arg) == 0                  &&
1007             L[9]->OPC == OP65_STX                               &&
1008             L[9]->AM == AM65_ZP                                 &&
1009             strcmp (L[9]->Arg, L[1]->Arg) == 0                  &&
1010             L[10]->OPC == OP65_LDA                              &&
1011             L[10]->AM == AM65_ZP                                &&
1012             strcmp (L[10]->Arg, "regsave") == 0                 &&
1013             L[11]->OPC == OP65_LDX                              &&
1014             L[11]->AM == AM65_ZP                                &&
1015             strcmp (L[11]->Arg, "regsave+1") == 0               &&
1016             L[12]->OPC == OP65_LDY                              &&
1017             CE_IsConstImm (L[12])                               &&
1018             CE_IsCallTo (L[13], "ldauidx")) {
1019
1020             CodeEntry* X;
1021             CodeLabel* Label;
1022
1023             /* Check if the instruction following the sequence uses the flags
1024              * set by the load. If so, insert a test of the value in the
1025              * accumulator.
1026              */
1027             if (CE_UseLoadFlags (L[14])) {
1028                 X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[13]->LI);
1029                 CS_InsertEntry (S, X, I+14);
1030             }
1031
1032             /* Attach a label to L[14]. This may be either the just inserted
1033              * instruction, or the one following the sequence.
1034              */
1035             Label = CS_GenLabel (S, L[14]);
1036
1037             /* ldy #$xx */
1038             X = NewCodeEntry (OP65_LDY, AM65_IMM, L[12]->Arg, 0, L[12]->LI);
1039             CS_InsertEntry (S, X, I+14);
1040
1041             /* ldx #$xx */
1042             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[13]->LI);
1043             CS_InsertEntry (S, X, I+15);
1044
1045             /* lda (regbank+n),y */
1046             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[13]->LI);
1047             CS_InsertEntry (S, X, I+16);
1048
1049             /* inc regbank+n */
1050             X = NewCodeEntry (OP65_INC, AM65_ZP, L[0]->Arg, 0, L[5]->LI);
1051             CS_InsertEntry (S, X, I+17);
1052
1053             /* bne ... */
1054             X = NewCodeEntry (OP65_BNE, AM65_BRA, Label->Name, Label, L[6]->LI);
1055             CS_InsertEntry (S, X, I+18);
1056
1057             /* inc regbank+n+1 */
1058             X = NewCodeEntry (OP65_INC, AM65_ZP, L[1]->Arg, 0, L[7]->LI);
1059             CS_InsertEntry (S, X, I+19);
1060
1061             /* Delete the old code */
1062             CS_DelEntries (S, I, 14);
1063
1064             /* Remember, we had changes */
1065             ++Changes;
1066
1067         }
1068
1069         /* Next entry */
1070         ++I;
1071
1072     }
1073
1074     /* Return the number of changes made */
1075     return Changes;
1076 }
1077
1078
1079
1080 unsigned OptPtrLoad13 (CodeSeg* S)
1081 /* Search for the sequence:
1082  *
1083  *      lda     zp
1084  *      ldx     zp+1
1085  *      ldy     xx
1086  *      jsr     ldauidx
1087  *
1088  * and replace it by:
1089  *
1090  *      ldy     xx
1091  *      ldx     #$00
1092  *      lda     (zp),y
1093  */
1094 {
1095     unsigned Changes = 0;
1096
1097     /* Walk over the entries */
1098     unsigned I = 0;
1099     while (I < CS_GetEntryCount (S)) {
1100
1101         CodeEntry* L[4];
1102         unsigned Len;
1103
1104         /* Get next entry */
1105         L[0] = CS_GetEntry (S, I);
1106
1107         /* Check for the sequence */
1108         if (L[0]->OPC == OP65_LDA && L[0]->AM == AM65_ZP        &&
1109             CS_GetEntries (S, L+1, I+1, 3)                      &&
1110             !CS_RangeHasLabel (S, I+1, 3)                       &&
1111             L[1]->OPC == OP65_LDX && L[1]->AM == AM65_ZP        &&
1112             (Len = strlen (L[0]->Arg)) > 0                      &&
1113             strncmp (L[0]->Arg, L[1]->Arg, Len) == 0            &&
1114             strcmp (L[1]->Arg + Len, "+1") == 0                 &&
1115             L[2]->OPC == OP65_LDY                               &&
1116             CE_IsCallTo (L[3], "ldauidx")) {
1117
1118             CodeEntry* X;
1119
1120             /* ldx #$00 */
1121             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[3]->LI);
1122             CS_InsertEntry (S, X, I+3);
1123
1124             /* lda (zp),y */
1125             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[3]->LI);
1126             CS_InsertEntry (S, X, I+4);
1127
1128             /* Remove the old code */
1129             CS_DelEntry (S, I+5);
1130             CS_DelEntries (S, I, 2);
1131
1132             /* Remember, we had changes */
1133             ++Changes;
1134
1135         }
1136
1137         /* Next entry */
1138         ++I;
1139
1140     }
1141
1142     /* Return the number of changes made */
1143     return Changes;
1144 }
1145
1146
1147
1148 unsigned OptPtrLoad14 (CodeSeg* S)
1149 /* Search for the sequence:
1150  *
1151  *      lda     zp
1152  *      ldx     zp+1
1153  *      (anything that doesn't change a/x)
1154  *      ldy     xx
1155  *      jsr     ldauidx
1156  *
1157  * and replace it by:
1158  *
1159  *      lda     zp
1160  *      ldx     zp+1
1161  *      (anything that doesn't change a/x)
1162  *      ldy     xx
1163  *      ldx     #$00
1164  *      lda     (zp),y
1165  *
1166  */
1167 {
1168     unsigned Changes = 0;
1169     unsigned I;
1170
1171     /* Generate register info */
1172     CS_GenRegInfo (S);
1173
1174     /* Walk over the entries */
1175     I = 0;
1176     while (I < CS_GetEntryCount (S)) {
1177
1178         CodeEntry* L[5];
1179         unsigned Len;
1180
1181         /* Get next entry */
1182         L[0] = CS_GetEntry (S, I);
1183
1184         /* Check for the sequence */
1185         if (L[0]->OPC == OP65_LDA && L[0]->AM == AM65_ZP        &&
1186             CS_GetEntries (S, L+1, I+1, 4)                      &&
1187             !CS_RangeHasLabel (S, I+1, 4)                       &&
1188             L[1]->OPC == OP65_LDX && L[1]->AM == AM65_ZP        &&
1189             (Len = strlen (L[0]->Arg)) > 0                      &&
1190             strncmp (L[0]->Arg, L[1]->Arg, Len) == 0            &&
1191             strcmp (L[1]->Arg + Len, "+1") == 0                 &&
1192             (L[2]->Chg & REG_AX) == 0                           &&
1193             L[3]->OPC == OP65_LDY                               &&
1194             CE_IsCallTo (L[4], "ldauidx")) {
1195
1196             CodeEntry* X;
1197
1198             /* ldx #$00 */
1199             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[3]->LI);
1200             CS_InsertEntry (S, X, I+5);
1201
1202             /* lda (zp),y */
1203             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[3]->LI);
1204             CS_InsertEntry (S, X, I+6);
1205
1206             /* Remove the old code */
1207             CS_DelEntry (S, I+4);
1208
1209             /* Remember, we had changes */
1210             ++Changes;
1211
1212         }
1213
1214         /* Next entry */
1215         ++I;
1216
1217     }
1218
1219     /* Free the register info */
1220     CS_FreeRegInfo (S);
1221
1222     /* Return the number of changes made */
1223     return Changes;
1224 }
1225
1226
1227
1228 unsigned OptPtrLoad15 (CodeSeg* S)
1229 /* Search for the sequence:
1230  *
1231  *      lda     zp
1232  *      ldx     zp+1
1233  *      ldy     xx
1234  *      jsr     ldaxidx
1235  *
1236  * and replace it by:
1237  *
1238  *      ldy     xx
1239  *      lda     (zp),y
1240  *      tax
1241  *      dey
1242  *      lda     (zp),y
1243  */
1244 {
1245     unsigned Changes = 0;
1246
1247     /* Walk over the entries */
1248     unsigned I = 0;
1249     while (I < CS_GetEntryCount (S)) {
1250
1251         CodeEntry* L[4];
1252         unsigned Len;
1253
1254         /* Get next entry */
1255         L[0] = CS_GetEntry (S, I);
1256
1257         /* Check for the sequence */
1258         if (L[0]->OPC == OP65_LDA && L[0]->AM == AM65_ZP        &&
1259             CS_GetEntries (S, L+1, I+1, 3)                      &&
1260             !CS_RangeHasLabel (S, I+1, 3)                       &&
1261             L[1]->OPC == OP65_LDX && L[1]->AM == AM65_ZP        &&
1262             (Len = strlen (L[0]->Arg)) > 0                      &&
1263             strncmp (L[0]->Arg, L[1]->Arg, Len) == 0            &&
1264             strcmp (L[1]->Arg + Len, "+1") == 0                 &&
1265             L[2]->OPC == OP65_LDY                               &&
1266             CE_IsCallTo (L[3], "ldaxidx")) {
1267
1268             CodeEntry* X;
1269
1270             /* lda (zp),y */
1271             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[3]->LI);
1272             CS_InsertEntry (S, X, I+4);
1273
1274             /* tax */
1275             X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[3]->LI);
1276             CS_InsertEntry (S, X, I+5);
1277
1278             /* dey */
1279             X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[3]->LI);
1280             CS_InsertEntry (S, X, I+6);
1281
1282             /* lda (zp),y */
1283             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[3]->LI);
1284             CS_InsertEntry (S, X, I+7);
1285
1286             /* Remove the old code */
1287             CS_DelEntry (S, I+3);
1288             CS_DelEntries (S, I, 2);
1289
1290             /* Remember, we had changes */
1291             ++Changes;
1292
1293         }
1294
1295         /* Next entry */
1296         ++I;
1297
1298     }
1299
1300     /* Return the number of changes made */
1301     return Changes;
1302 }
1303
1304
1305
1306 unsigned OptPtrLoad16 (CodeSeg* S)
1307 /* Search for the sequence
1308  *
1309  *      ldy     ...
1310  *      jsr     ldauidx
1311  *
1312  * and replace it by:
1313  *
1314  *      stx     ptr1+1
1315  *      sta     ptr1
1316  *      ldy     ...
1317  *      ldx     #$00
1318  *      lda     (ptr1),y
1319  *
1320  * This step must be executed *after* OptPtrLoad1!
1321  */
1322 {
1323     unsigned Changes = 0;
1324
1325     /* Walk over the entries */
1326     unsigned I = 0;
1327     while (I < CS_GetEntryCount (S)) {
1328
1329         CodeEntry* L[2];
1330
1331         /* Get next entry */
1332         L[0] = CS_GetEntry (S, I);
1333
1334         /* Check for the sequence */
1335         if (L[0]->OPC == OP65_LDY               &&
1336             CS_GetEntries (S, L+1, I+1, 1)      &&
1337             CE_IsCallTo (L[1], "ldauidx")       &&
1338             !CE_HasLabel (L[1])) {
1339
1340             CodeEntry* X;
1341
1342             /* Store the high byte */
1343             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI);
1344             CS_InsertEntry (S, X, I);
1345
1346             /* Store the low byte */
1347             X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI);
1348             CS_InsertEntry (S, X, I+1);
1349
1350             /* Delete the call to ldauidx */
1351             CS_DelEntry (S, I+3);
1352
1353             /* Load the high and low byte */
1354             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[0]->LI);
1355             CS_InsertEntry (S, X, I+3);
1356             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[0]->LI);
1357             CS_InsertEntry (S, X, I+4);
1358
1359             /* Remember, we had changes */
1360             ++Changes;
1361
1362         }
1363
1364         /* Next entry */
1365         ++I;
1366
1367     }
1368
1369     /* Return the number of changes made */
1370     return Changes;
1371 }
1372
1373
1374
1375 unsigned OptPtrLoad17 (CodeSeg* S)
1376 /* Search for the sequence
1377  *
1378  *      ldy     ...
1379  *      jsr     ldaxidx
1380  *
1381  * and replace it by:
1382  *
1383  *      sta     ptr1
1384  *      stx     ptr1+1
1385  *      ldy     ...
1386  *      lda     (ptr1),y
1387  *      tax
1388  *      dey
1389  *      lda     (ptr1),y
1390  *
1391  * This step must be executed *after* OptPtrLoad9! While code size increases
1392  * by more than 200%, inlining will greatly improve visibility for the
1393  * optimizer, so often part of the code gets improved later. So we will mark
1394  * the step with less than 200% so it gets executed when -Oi is in effect.
1395  */
1396 {
1397     unsigned Changes = 0;
1398
1399     /* Walk over the entries */
1400     unsigned I = 0;
1401     while (I < CS_GetEntryCount (S)) {
1402
1403         CodeEntry* L[2];
1404
1405         /* Get next entry */
1406         L[0] = CS_GetEntry (S, I);
1407
1408         /* Check for the sequence */
1409         if (L[0]->OPC == OP65_LDY               &&
1410             CS_GetEntries (S, L+1, I+1, 1)      &&
1411             CE_IsCallTo (L[1], "ldaxidx")       &&
1412             !CE_HasLabel (L[1])) {
1413
1414             CodeEntry* X;
1415
1416             /* Store the high byte */
1417             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI);
1418             CS_InsertEntry (S, X, I+2);
1419
1420             /* Store the low byte */
1421             X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI);
1422             CS_InsertEntry (S, X, I+3);
1423
1424             /* ldy ... */
1425             X = NewCodeEntry (L[0]->OPC, L[0]->AM, L[0]->Arg, 0, L[0]->LI);
1426             CS_InsertEntry (S, X, I+4);
1427
1428             /* lda (ptr1),y */
1429             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[1]->LI);
1430             CS_InsertEntry (S, X, I+5);
1431
1432             /* tax */
1433             X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[1]->LI);
1434             CS_InsertEntry (S, X, I+6);
1435
1436             /* dey */
1437             X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[1]->LI);
1438             CS_InsertEntry (S, X, I+7);
1439
1440             /* lda (ptr1),y */
1441             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[1]->LI);
1442             CS_InsertEntry (S, X, I+8);
1443
1444             /* Delete original sequence */
1445             CS_DelEntries (S, I, 2);
1446
1447             /* Remember, we had changes */
1448             ++Changes;
1449
1450         }
1451
1452         /* Next entry */
1453         ++I;
1454
1455     }
1456
1457     /* Return the number of changes made */
1458     return Changes;
1459 }
1460
1461
1462