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