]> git.sur5r.net Git - cc65/blob - src/cc65/coptptrload.c
Some more pattern replacements.
[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
565  *      lda     (sp),y
566  *      tay
567  *      ldx     #$00
568  *      lda     (ptr1),y
569  */
570 {
571     unsigned Changes = 0;
572
573     /* Walk over the entries */
574     unsigned I = 0;
575     while (I < CS_GetEntryCount (S)) {
576
577         CodeEntry* L[7];
578
579         /* Get next entry */
580         L[0] = CS_GetEntry (S, I);
581
582         /* Check for the sequence */
583         if (CE_IsCallTo (L[0], "pushax")                &&
584             CS_GetEntries (S, L+1, I+1, 6)              &&
585             L[1]->OPC == OP65_LDY                       &&
586             L[2]->OPC == OP65_LDX                       &&
587             CE_IsKnownImm (L[2], 0)                     &&
588             L[3]->OPC == OP65_LDA                       &&
589             L[3]->AM == AM65_ZP_INDY                    &&
590             CE_IsCallTo (L[4], "tosaddax")              &&
591             L[5]->OPC == OP65_LDY                       &&
592             CE_IsKnownImm (L[5], 0)                     &&
593             CE_IsCallTo (L[6], "ldauidx")               &&
594             !CS_RangeHasLabel (S, I+1, 6)) {
595
596             CodeEntry* X;
597
598             /* sta ptr1 */
599             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI);
600             CS_InsertEntry (S, X, I+7);
601
602             /* stx ptr1+1 */
603             X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI);
604             CS_InsertEntry (S, X, I+8);
605
606             /* ldy yyy */
607             X = NewCodeEntry (OP65_LDY, L[1]->AM, L[1]->Arg, 0, L[1]->LI);
608             CS_InsertEntry (S, X, I+9);
609
610             /* lda (sp),y */
611             X = NewCodeEntry (OP65_LDA, L[3]->AM, L[3]->Arg, 0, L[3]->LI);
612             CS_InsertEntry (S, X, I+10);
613
614             /* tay */
615             X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[3]->LI);
616             CS_InsertEntry (S, X, I+11);
617
618             /* ldx #$00 */
619             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[5]->LI);
620             CS_InsertEntry (S, X, I+12);
621
622             /* lda (ptr1),y */
623             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[6]->LI);
624             CS_InsertEntry (S, X, I+13);
625
626             /* Remove the old code */
627             CS_DelEntries (S, I, 7);
628
629             /* Remember, we had changes */
630             ++Changes;
631
632         }
633
634         /* Next entry */
635         ++I;
636
637     }
638
639     /* Return the number of changes made */
640     return Changes;
641 }
642
643
644
645 unsigned OptPtrLoad7 (CodeSeg* S)
646 /* Search for the sequence:
647  *
648  *      jsr     aslax1/shlax1
649  *      clc
650  *      adc     xxx
651  *      tay
652  *      txa
653  *      adc     yyy
654  *      tax
655  *      tya
656  *      ldy     zzz
657  *      jsr     ldaxidx
658  *
659  * and replace it by:
660  *
661  *      stx     tmp1
662  *      asl     a
663  *      rol     tmp1
664  *      clc
665  *      adc     xxx
666  *      sta     ptr1
667  *      lda     tmp1
668  *      adc     yyy
669  *      sta     ptr1+1
670  *      ldy     zzz
671  *      lda     (ptr1),y
672  *      tax
673  *      dey
674  *      lda     (ptr1),y
675  */
676 {
677     unsigned Changes = 0;
678     unsigned I;
679
680     /* Generate register info */
681     CS_GenRegInfo (S);
682
683     /* Walk over the entries */
684     I = 0;
685     while (I < CS_GetEntryCount (S)) {
686
687         CodeEntry* L[10];
688
689         /* Get next entry */
690         L[0] = CS_GetEntry (S, I);
691
692         /* Check for the sequence */
693         if (L[0]->OPC == OP65_JSR                               &&
694             (strcmp (L[0]->Arg, "aslax1") == 0          ||
695              strcmp (L[0]->Arg, "shlax1") == 0)                 &&
696             CS_GetEntries (S, L+1, I+1, 9)                      &&
697             L[1]->OPC == OP65_CLC                               &&
698             L[2]->OPC == OP65_ADC                               &&
699             L[3]->OPC == OP65_TAY                               &&
700             L[4]->OPC == OP65_TXA                               &&
701             L[5]->OPC == OP65_ADC                               &&
702             L[6]->OPC == OP65_TAX                               &&
703             L[7]->OPC == OP65_TYA                               &&
704             L[8]->OPC == OP65_LDY                               &&
705             CE_IsCallTo (L[9], "ldaxidx")                       &&
706             !CS_RangeHasLabel (S, I+1, 9)) {
707
708             CodeEntry* X;
709
710             /* Track the insertion point */
711             unsigned IP = I + 10;
712
713
714             /* If X is zero on entry to aslax1, we can generate:
715              *
716              *      asl     a
717              *      bcc     L1
718              *      inx
719              * L1:  clc
720              *
721              * instead of the code above. "lda tmp1" needs to be changed
722              * to "txa" in this case.
723              */
724             int ShortCode = (L[0]->RI->In.RegX == 0);
725
726             if (ShortCode) {
727
728                 CodeLabel* Lab;
729
730                 /* asl a */
731                 X = NewCodeEntry (OP65_ASL, AM65_IMP, "a", 0, L[0]->LI);
732                 CS_InsertEntry (S, X, IP++);
733
734                 /* Generate clc first, since we need the label */
735                 X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[1]->LI);
736                 CS_InsertEntry (S, X, IP);
737
738                 /* Get the label */
739                 Lab = CS_GenLabel (S, X);
740
741                 /* bcc Lab */
742                 X = NewCodeEntry (OP65_BCC, AM65_BRA, Lab->Name, Lab, L[0]->LI);
743                 CS_InsertEntry (S, X, IP++);
744
745                 /* inx */
746                 X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, L[0]->LI);
747                 CS_InsertEntry (S, X, IP++);
748
749                 /* Skip the clc insn */
750                 ++IP;
751
752             } else {
753
754                 /* stx tmp1 */
755                 X = NewCodeEntry (OP65_STX, AM65_ZP, "tmp1", 0, L[0]->LI);
756                 CS_InsertEntry (S, X, IP++);
757
758                 /* asl a */
759                 X = NewCodeEntry (OP65_ASL, AM65_IMP, "a", 0, L[0]->LI);
760                 CS_InsertEntry (S, X, IP++);
761
762                 /* rol tmp1 */
763                 X = NewCodeEntry (OP65_ROL, AM65_ZP, "tmp1", 0, L[0]->LI);
764                 CS_InsertEntry (S, X, IP++);
765
766                 /* clc */
767                 X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[1]->LI);
768                 CS_InsertEntry (S, X, IP++);
769
770             }
771
772             /* adc xxx */
773             X = NewCodeEntry (L[2]->OPC, L[2]->AM, L[2]->Arg, 0, L[2]->LI);
774             CS_InsertEntry (S, X, IP++);
775
776             /* sta ptr1 */
777             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[9]->LI);
778             CS_InsertEntry (S, X, IP++);
779
780             if (ShortCode) {
781                 /* txa */
782                 X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, L[4]->LI);
783             } else {
784                 /* lda tmp1 */
785                 X = NewCodeEntry (OP65_LDA, AM65_ZP, "tmp1", 0, L[4]->LI);
786             }
787             CS_InsertEntry (S, X, IP++);
788
789             /* adc xxx */
790             X = NewCodeEntry (L[5]->OPC, L[5]->AM, L[5]->Arg, 0, L[5]->LI);
791             CS_InsertEntry (S, X, IP++);
792
793             /* sta ptr1+1 */
794             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1+1", 0, L[9]->LI);
795             CS_InsertEntry (S, X, IP++);
796
797             /* ldy zzz */
798             X = NewCodeEntry (L[8]->OPC, L[8]->AM, L[8]->Arg, 0, L[8]->LI);
799             CS_InsertEntry (S, X, IP++);
800
801             /* lda (ptr1),y */
802             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[9]->LI);
803             CS_InsertEntry (S, X, IP++);
804
805             /* tax */
806             X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[9]->LI);
807             CS_InsertEntry (S, X, IP++);
808
809             /* dey */
810             X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[9]->LI);
811             CS_InsertEntry (S, X, IP++);
812
813             /* lda (ptr1),y */
814             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[9]->LI);
815             CS_InsertEntry (S, X, IP++);
816
817             /* Remove the old code */
818             CS_DelEntries (S, I, 10);
819
820             /* Remember, we had changes */
821             ++Changes;
822
823         }
824
825         /* Next entry */
826         ++I;
827
828     }
829
830     /* Free the register info */
831     CS_FreeRegInfo (S);
832
833     /* Return the number of changes made */
834     return Changes;
835 }
836
837
838
839 unsigned OptPtrLoad11 (CodeSeg* S)
840 /* Search for the sequence:
841  *
842  *      clc
843  *      adc     xxx
844  *      bcc     L
845  *      inx
846  * L:   ldy     #$00
847  *      jsr     ldauidx
848  *
849  * and replace it by:
850  *
851  *      ldy     xxx
852  *      sta     ptr1
853  *      stx     ptr1+1
854  *      ldx     #$00
855  *      lda     (ptr1),y
856  */
857 {
858     unsigned Changes = 0;
859
860     /* Walk over the entries */
861     unsigned I = 0;
862     while (I < CS_GetEntryCount (S)) {
863
864         CodeEntry* L[6];
865
866         /* Get next entry */
867         L[0] = CS_GetEntry (S, I);
868
869         /* Check for the sequence */
870         if (L[0]->OPC == OP65_CLC                            &&
871             CS_GetEntries (S, L+1, I+1, 5)                   &&
872             L[1]->OPC == OP65_ADC                            &&
873             (L[1]->AM == AM65_ABS || L[1]->AM == AM65_ZP || L[1]->AM == AM65_IMM)    &&
874             (L[2]->OPC == OP65_BCC || L[2]->OPC == OP65_JCC) &&
875             L[2]->JumpTo != 0                                &&
876             L[2]->JumpTo->Owner == L[4]                      &&
877             L[3]->OPC == OP65_INX                            &&
878             L[4]->OPC == OP65_LDY                            &&
879             CE_IsKnownImm (L[4], 0)                          &&
880             CE_IsCallTo (L[5], "ldauidx")                    &&
881             !CS_RangeHasLabel (S, I+1, 3)                    &&
882             !CE_HasLabel (L[5])) {
883
884             CodeEntry* X;
885
886             /* We will create all the new stuff behind the current one so
887              * we keep the line references.
888              */
889             X = NewCodeEntry (OP65_LDY, L[1]->AM, L[1]->Arg, 0, L[0]->LI);
890             CS_InsertEntry (S, X, I+6);
891
892             /* sta ptr1 */
893             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI);
894             CS_InsertEntry (S, X, I+7);
895
896             /* stx ptr1+1 */
897             X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI);
898             CS_InsertEntry (S, X, I+8);
899
900             /* ldx #$00 */
901             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[0]->LI);
902             CS_InsertEntry (S, X, I+9);
903
904             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[0]->LI);
905             CS_InsertEntry (S, X, I+10);
906
907             /* Remove the old code */
908             CS_DelEntries (S, I, 6);
909
910             /* Remember, we had changes */
911             ++Changes;
912
913         }
914
915         /* Next entry */
916         ++I;
917
918     }
919
920     /* Return the number of changes made */
921     return Changes;
922 }
923
924
925
926 unsigned OptPtrLoad12 (CodeSeg* S)
927 /* Search for the sequence:
928  *
929  *      lda     regbank+n
930  *      ldx     regbank+n+1
931  *      sta     regsave
932  *      stx     regsave+1
933  *      clc
934  *      adc     #$01
935  *      bcc     L0005
936  *      inx
937  * L:   sta     regbank+n
938  *      stx     regbank+n+1
939  *      lda     regsave
940  *      ldx     regsave+1
941  *      ldy     #$00
942  *      jsr     ldauidx
943  *
944  * and replace it by:
945  *
946  *      ldy     #$00
947  *      ldx     #$00
948  *      lda     (regbank+n),y
949  *      inc     regbank+n
950  *      bne     L1
951  *      inc     regbank+n+1
952  * L1:  tay                     <- only if flags are used
953  *
954  * This function must execute before OptPtrLoad7!
955  *
956  */
957 {
958     unsigned Changes = 0;
959
960     /* Walk over the entries */
961     unsigned I = 0;
962     while (I < CS_GetEntryCount (S)) {
963
964         CodeEntry* L[15];
965         unsigned Len;
966
967         /* Get next entry */
968         L[0] = CS_GetEntry (S, I);
969
970         /* Check for the sequence */
971         if (L[0]->OPC == OP65_LDA                               &&
972             L[0]->AM == AM65_ZP                                 &&
973             strncmp (L[0]->Arg, "regbank+", 8) == 0             &&
974             (Len = strlen (L[0]->Arg)) > 0                      &&
975             CS_GetEntries (S, L+1, I+1, 14)                     &&
976             !CS_RangeHasLabel (S, I+1, 7)                       &&
977             !CS_RangeHasLabel (S, I+9, 5)                       &&
978             L[1]->OPC == OP65_LDX                               &&
979             L[1]->AM == AM65_ZP                                 &&
980             strncmp (L[1]->Arg, L[0]->Arg, Len) == 0            &&
981             strcmp (L[1]->Arg+Len, "+1") == 0                   &&
982             L[2]->OPC == OP65_STA                               &&
983             L[2]->AM == AM65_ZP                                 &&
984             strcmp (L[2]->Arg, "regsave") == 0                  &&
985             L[3]->OPC == OP65_STX                               &&
986             L[3]->AM == AM65_ZP                                 &&
987             strcmp (L[3]->Arg, "regsave+1") == 0                &&
988             L[4]->OPC == OP65_CLC                               &&
989             L[5]->OPC == OP65_ADC                               &&
990             CE_IsKnownImm (L[5], 1)                             &&
991             L[6]->OPC == OP65_BCC                               &&
992             L[6]->JumpTo != 0                                   &&
993             L[6]->JumpTo->Owner == L[8]                         &&
994             L[7]->OPC == OP65_INX                               &&
995             L[8]->OPC == OP65_STA                               &&
996             L[8]->AM == AM65_ZP                                 &&
997             strcmp (L[8]->Arg, L[0]->Arg) == 0                  &&
998             L[9]->OPC == OP65_STX                               &&
999             L[9]->AM == AM65_ZP                                 &&
1000             strcmp (L[9]->Arg, L[1]->Arg) == 0                  &&
1001             L[10]->OPC == OP65_LDA                              &&
1002             L[10]->AM == AM65_ZP                                &&
1003             strcmp (L[10]->Arg, "regsave") == 0                 &&
1004             L[11]->OPC == OP65_LDX                              &&
1005             L[11]->AM == AM65_ZP                                &&
1006             strcmp (L[11]->Arg, "regsave+1") == 0               &&
1007             L[12]->OPC == OP65_LDY                              &&
1008             CE_IsConstImm (L[12])                               &&
1009             CE_IsCallTo (L[13], "ldauidx")) {
1010
1011             CodeEntry* X;
1012             CodeLabel* Label;
1013
1014             /* Check if the instruction following the sequence uses the flags
1015              * set by the load. If so, insert a test of the value in the
1016              * accumulator.
1017              */
1018             if (CE_UseLoadFlags (L[14])) {
1019                 X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[13]->LI);
1020                 CS_InsertEntry (S, X, I+14);
1021             }
1022
1023             /* Attach a label to L[14]. This may be either the just inserted
1024              * instruction, or the one following the sequence.
1025              */
1026             Label = CS_GenLabel (S, L[14]);
1027
1028             /* ldy #$xx */
1029             X = NewCodeEntry (OP65_LDY, AM65_IMM, L[12]->Arg, 0, L[12]->LI);
1030             CS_InsertEntry (S, X, I+14);
1031
1032             /* ldx #$xx */
1033             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[13]->LI);
1034             CS_InsertEntry (S, X, I+15);
1035
1036             /* lda (regbank+n),y */
1037             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[13]->LI);
1038             CS_InsertEntry (S, X, I+16);
1039
1040             /* inc regbank+n */
1041             X = NewCodeEntry (OP65_INC, AM65_ZP, L[0]->Arg, 0, L[5]->LI);
1042             CS_InsertEntry (S, X, I+17);
1043
1044             /* bne ... */
1045             X = NewCodeEntry (OP65_BNE, AM65_BRA, Label->Name, Label, L[6]->LI);
1046             CS_InsertEntry (S, X, I+18);
1047
1048             /* inc regbank+n+1 */
1049             X = NewCodeEntry (OP65_INC, AM65_ZP, L[1]->Arg, 0, L[7]->LI);
1050             CS_InsertEntry (S, X, I+19);
1051
1052             /* Delete the old code */
1053             CS_DelEntries (S, I, 14);
1054
1055             /* Remember, we had changes */
1056             ++Changes;
1057
1058         }
1059
1060         /* Next entry */
1061         ++I;
1062
1063     }
1064
1065     /* Return the number of changes made */
1066     return Changes;
1067 }
1068
1069
1070
1071 unsigned OptPtrLoad13 (CodeSeg* S)
1072 /* Search for the sequence:
1073  *
1074  *      lda     zp
1075  *      ldx     zp+1
1076  *      ldy     xx
1077  *      jsr     ldauidx
1078  *
1079  * and replace it by:
1080  *
1081  *      ldy     xx
1082  *      ldx     #$00
1083  *      lda     (zp),y
1084  */
1085 {
1086     unsigned Changes = 0;
1087
1088     /* Walk over the entries */
1089     unsigned I = 0;
1090     while (I < CS_GetEntryCount (S)) {
1091
1092         CodeEntry* L[4];
1093         unsigned Len;
1094
1095         /* Get next entry */
1096         L[0] = CS_GetEntry (S, I);
1097
1098         /* Check for the sequence */
1099         if (L[0]->OPC == OP65_LDA && L[0]->AM == AM65_ZP        &&
1100             CS_GetEntries (S, L+1, I+1, 3)                      &&
1101             !CS_RangeHasLabel (S, I+1, 3)                       &&
1102             L[1]->OPC == OP65_LDX && L[1]->AM == AM65_ZP        &&
1103             (Len = strlen (L[0]->Arg)) > 0                      &&
1104             strncmp (L[0]->Arg, L[1]->Arg, Len) == 0            &&
1105             strcmp (L[1]->Arg + Len, "+1") == 0                 &&
1106             L[2]->OPC == OP65_LDY                               &&
1107             CE_IsCallTo (L[3], "ldauidx")) {
1108
1109             CodeEntry* X;
1110
1111             /* ldx #$00 */
1112             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[3]->LI);
1113             CS_InsertEntry (S, X, I+3);
1114
1115             /* lda (zp),y */
1116             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[3]->LI);
1117             CS_InsertEntry (S, X, I+4);
1118
1119             /* Remove the old code */
1120             CS_DelEntry (S, I+5);
1121             CS_DelEntries (S, I, 2);
1122
1123             /* Remember, we had changes */
1124             ++Changes;
1125
1126         }
1127
1128         /* Next entry */
1129         ++I;
1130
1131     }
1132
1133     /* Return the number of changes made */
1134     return Changes;
1135 }
1136
1137
1138
1139 unsigned OptPtrLoad14 (CodeSeg* S)
1140 /* Search for the sequence:
1141  *
1142  *      lda     zp
1143  *      ldx     zp+1
1144  *      (anything that doesn't change a/x)
1145  *      ldy     xx
1146  *      jsr     ldauidx
1147  *
1148  * and replace it by:
1149  *
1150  *      lda     zp
1151  *      ldx     zp+1
1152  *      (anything that doesn't change a/x)
1153  *      ldy     xx
1154  *      ldx     #$00
1155  *      lda     (zp),y
1156  *
1157  */
1158 {
1159     unsigned Changes = 0;
1160     unsigned I;
1161
1162     /* Generate register info */
1163     CS_GenRegInfo (S);
1164
1165     /* Walk over the entries */
1166     I = 0;
1167     while (I < CS_GetEntryCount (S)) {
1168
1169         CodeEntry* L[5];
1170         unsigned Len;
1171
1172         /* Get next entry */
1173         L[0] = CS_GetEntry (S, I);
1174
1175         /* Check for the sequence */
1176         if (L[0]->OPC == OP65_LDA && L[0]->AM == AM65_ZP        &&
1177             CS_GetEntries (S, L+1, I+1, 4)                      &&
1178             !CS_RangeHasLabel (S, I+1, 4)                       &&
1179             L[1]->OPC == OP65_LDX && L[1]->AM == AM65_ZP        &&
1180             (Len = strlen (L[0]->Arg)) > 0                      &&
1181             strncmp (L[0]->Arg, L[1]->Arg, Len) == 0            &&
1182             strcmp (L[1]->Arg + Len, "+1") == 0                 &&
1183             (L[2]->Chg & REG_AX) == 0                           &&
1184             L[3]->OPC == OP65_LDY                               &&
1185             CE_IsCallTo (L[4], "ldauidx")) {
1186
1187             CodeEntry* X;
1188
1189             /* ldx #$00 */
1190             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[3]->LI);
1191             CS_InsertEntry (S, X, I+5);
1192
1193             /* lda (zp),y */
1194             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[3]->LI);
1195             CS_InsertEntry (S, X, I+6);
1196
1197             /* Remove the old code */
1198             CS_DelEntry (S, I+4);
1199
1200             /* Remember, we had changes */
1201             ++Changes;
1202
1203         }
1204
1205         /* Next entry */
1206         ++I;
1207
1208     }
1209
1210     /* Free the register info */
1211     CS_FreeRegInfo (S);
1212
1213     /* Return the number of changes made */
1214     return Changes;
1215 }
1216
1217
1218
1219 unsigned OptPtrLoad15 (CodeSeg* S)
1220 /* Search for the sequence:
1221  *
1222  *      lda     zp
1223  *      ldx     zp+1
1224  *      ldy     xx
1225  *      jsr     ldaxidx
1226  *
1227  * and replace it by:
1228  *
1229  *      ldy     xx
1230  *      lda     (zp),y
1231  *      tax
1232  *      dey
1233  *      lda     (zp),y
1234  */
1235 {
1236     unsigned Changes = 0;
1237
1238     /* Walk over the entries */
1239     unsigned I = 0;
1240     while (I < CS_GetEntryCount (S)) {
1241
1242         CodeEntry* L[4];
1243         unsigned Len;
1244
1245         /* Get next entry */
1246         L[0] = CS_GetEntry (S, I);
1247
1248         /* Check for the sequence */
1249         if (L[0]->OPC == OP65_LDA && L[0]->AM == AM65_ZP        &&
1250             CS_GetEntries (S, L+1, I+1, 3)                      &&
1251             !CS_RangeHasLabel (S, I+1, 3)                       &&
1252             L[1]->OPC == OP65_LDX && L[1]->AM == AM65_ZP        &&
1253             (Len = strlen (L[0]->Arg)) > 0                      &&
1254             strncmp (L[0]->Arg, L[1]->Arg, Len) == 0            &&
1255             strcmp (L[1]->Arg + Len, "+1") == 0                 &&
1256             L[2]->OPC == OP65_LDY                               &&
1257             CE_IsCallTo (L[3], "ldaxidx")) {
1258
1259             CodeEntry* X;
1260
1261             /* lda (zp),y */
1262             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[3]->LI);
1263             CS_InsertEntry (S, X, I+4);
1264
1265             /* tax */
1266             X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[3]->LI);
1267             CS_InsertEntry (S, X, I+5);
1268
1269             /* dey */
1270             X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[3]->LI);
1271             CS_InsertEntry (S, X, I+6);
1272
1273             /* lda (zp),y */
1274             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[3]->LI);
1275             CS_InsertEntry (S, X, I+7);
1276
1277             /* Remove the old code */
1278             CS_DelEntry (S, I+3);
1279             CS_DelEntries (S, I, 2);
1280
1281             /* Remember, we had changes */
1282             ++Changes;
1283
1284         }
1285
1286         /* Next entry */
1287         ++I;
1288
1289     }
1290
1291     /* Return the number of changes made */
1292     return Changes;
1293 }
1294
1295
1296
1297 unsigned OptPtrLoad16 (CodeSeg* S)
1298 /* Search for the sequence
1299  *
1300  *      ldy     ...
1301  *      jsr     ldauidx
1302  *
1303  * and replace it by:
1304  *
1305  *      stx     ptr1+1
1306  *      sta     ptr1
1307  *      ldy     ...
1308  *      ldx     #$00
1309  *      lda     (ptr1),y
1310  *
1311  * This step must be executed *after* OptPtrLoad1!
1312  */
1313 {
1314     unsigned Changes = 0;
1315
1316     /* Walk over the entries */
1317     unsigned I = 0;
1318     while (I < CS_GetEntryCount (S)) {
1319
1320         CodeEntry* L[2];
1321
1322         /* Get next entry */
1323         L[0] = CS_GetEntry (S, I);
1324
1325         /* Check for the sequence */
1326         if (L[0]->OPC == OP65_LDY               &&
1327             CS_GetEntries (S, L+1, I+1, 1)      &&
1328             CE_IsCallTo (L[1], "ldauidx")       &&
1329             !CE_HasLabel (L[1])) {
1330
1331             CodeEntry* X;
1332
1333             /* Store the high byte */
1334             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI);
1335             CS_InsertEntry (S, X, I);
1336
1337             /* Store the low byte */
1338             X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI);
1339             CS_InsertEntry (S, X, I+1);
1340
1341             /* Delete the call to ldauidx */
1342             CS_DelEntry (S, I+3);
1343
1344             /* Load the high and low byte */
1345             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[0]->LI);
1346             CS_InsertEntry (S, X, I+3);
1347             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[0]->LI);
1348             CS_InsertEntry (S, X, I+4);
1349
1350             /* Remember, we had changes */
1351             ++Changes;
1352
1353         }
1354
1355         /* Next entry */
1356         ++I;
1357
1358     }
1359
1360     /* Return the number of changes made */
1361     return Changes;
1362 }
1363
1364
1365
1366 unsigned OptPtrLoad17 (CodeSeg* S)
1367 /* Search for the sequence
1368  *
1369  *      ldy     ...
1370  *      jsr     ldaxidx
1371  *
1372  * and replace it by:
1373  *
1374  *      ldy     ...
1375  *      sta     ptr1
1376  *      stx     ptr1+1
1377  *      lda     (ptr1),y
1378  *      tax
1379  *      dey
1380  *      lda     (ptr1),y
1381  *
1382  * This step must be executed *after* OptPtrLoad9! While code size increases
1383  * by more than 200%, inlining will greatly improve visibility for the
1384  * optimizer, so often part of the code gets improved later. So we will mark
1385  * the step with less than 200% so it gets executed when -Oi is in effect.
1386  */
1387 {
1388     unsigned Changes = 0;
1389
1390     /* Walk over the entries */
1391     unsigned I = 0;
1392     while (I < CS_GetEntryCount (S)) {
1393
1394         CodeEntry* L[2];
1395
1396         /* Get next entry */
1397         L[0] = CS_GetEntry (S, I);
1398
1399         /* Check for the sequence */
1400         if (L[0]->OPC == OP65_LDY               &&
1401             CS_GetEntries (S, L+1, I+1, 1)      &&
1402             CE_IsCallTo (L[1], "ldaxidx")       &&
1403             !CE_HasLabel (L[1])) {
1404
1405             CodeEntry* X;
1406
1407             /* Store the high byte */
1408             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI);
1409             CS_InsertEntry (S, X, I+1);
1410
1411             /* Store the low byte */
1412             X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI);
1413             CS_InsertEntry (S, X, I+2);
1414
1415             /* lda (ptr1),y */
1416             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[1]->LI);
1417             CS_InsertEntry (S, X, I+3);
1418
1419             /* tax */
1420             X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[1]->LI);
1421             CS_InsertEntry (S, X, I+4);
1422
1423             /* dey */
1424             X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[1]->LI);
1425             CS_InsertEntry (S, X, I+5);
1426
1427             /* lda (ptr1),y */
1428             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[1]->LI);
1429             CS_InsertEntry (S, X, I+6);
1430
1431             /* Delete the call to ldaxidx */
1432             CS_DelEntry (S, I+7);
1433
1434             /* Remember, we had changes */
1435             ++Changes;
1436
1437         }
1438
1439         /* Next entry */
1440         ++I;
1441
1442     }
1443
1444     /* Return the number of changes made */
1445     return Changes;
1446 }
1447
1448
1449