]> git.sur5r.net Git - cc65/blob - src/cc65/coptptrload.c
Normalized code.
[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+9;
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 */
131             X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[0]->LI);
132             CS_InsertEntry (S, X, IP++);
133
134             /* adc yyy */
135             X = NewCodeEntry (OP65_ADC, L[4]->AM, L[4]->Arg, 0, L[4]->LI);
136             CS_InsertEntry (S, X, IP++);
137
138             /* sta ptr1+1 */
139             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1+1", 0, L[5]->LI);
140             CS_InsertEntry (S, X, IP++);
141
142             /* ldy xxx */
143             X = NewCodeEntry (OP65_LDY, L[1]->AM, L[1]->Arg, 0, L[1]->LI);
144             CS_InsertEntry (S, X, IP++);
145
146             /* ldx #$00 */
147             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[8]->LI);
148             CS_InsertEntry (S, X, IP++);
149
150             /* lda (ptr1),y */
151             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[8]->LI);
152             CS_InsertEntry (S, X, IP++);
153
154             /* Remove the old instructions */
155             CS_DelEntries (S, I, 9);
156
157             /* Remember, we had changes */
158             ++Changes;
159
160         }
161
162         /* Next entry */
163         ++I;
164
165     }
166
167     /* Return the number of changes made */
168     return Changes;
169 }
170
171
172
173 unsigned OptPtrLoad2 (CodeSeg* S)
174 /* Search for the sequence:
175  *
176  *      adc     xxx
177  *      pha
178  *      txa
179  *      iny
180  *      adc     yyy
181  *      tax
182  *      pla
183  *      ldy
184  *      jsr     ldauidx
185  *
186  * and replace it by:
187  *
188  *      adc     xxx
189  *      sta     ptr1
190  *      txa
191  *      iny
192  *      adc     yyy
193  *      sta     ptr1+1
194  *      ldy
195  *      ldx     #$00
196  *      lda     (ptr1),y
197  */
198 {
199     unsigned Changes = 0;
200
201     /* Walk over the entries */
202     unsigned I = 0;
203     while (I < CS_GetEntryCount (S)) {
204
205         CodeEntry* L[9];
206
207         /* Get next entry */
208         L[0] = CS_GetEntry (S, I);
209
210         /* Check for the sequence */
211         if (L[0]->OPC == OP65_ADC               &&
212             CS_GetEntries (S, L+1, I+1, 8)      &&
213             L[1]->OPC == OP65_PHA               &&
214             L[2]->OPC == OP65_TXA               &&
215             L[3]->OPC == OP65_INY               &&
216             L[4]->OPC == OP65_ADC               &&
217             L[5]->OPC == OP65_TAX               &&
218             L[6]->OPC == OP65_PLA               &&
219             L[7]->OPC == OP65_LDY               &&
220             CE_IsCallTo (L[8], "ldauidx")       &&
221             !CS_RangeHasLabel (S, I+1, 8)) {
222
223             CodeEntry* X;
224
225             /* Store the low byte and remove the PHA instead */
226             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI);
227             CS_InsertEntry (S, X, I+1);
228
229             /* Store the high byte */
230             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1+1", 0, L[4]->LI);
231             CS_InsertEntry (S, X, I+6);
232
233             /* Load high and low byte */
234             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[6]->LI);
235             CS_InsertEntry (S, X, I+10);
236             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[6]->LI);
237             CS_InsertEntry (S, X, I+11);
238
239             /* Delete the old code */
240             CS_DelEntry (S, I+12);      /* jsr ldauidx */
241             CS_DelEntry (S, I+8);       /* pla */
242             CS_DelEntry (S, I+7);       /* tax */
243             CS_DelEntry (S, I+2);       /* pha */
244
245             /* Remember, we had changes */
246             ++Changes;
247
248         }
249
250         /* Next entry */
251         ++I;
252
253     }
254
255     /* Return the number of changes made */
256     return Changes;
257 }
258
259
260
261 unsigned OptPtrLoad3 (CodeSeg* S)
262 /* Search for the sequence:
263  *
264  *      lda     #<(label+0)
265  *      ldx     #>(label+0)
266  *      clc
267  *      adc     xxx
268  *      bcc     L
269  *      inx
270  * L:   ldy     #$00
271  *      jsr     ldauidx
272  *
273  * and replace it by:
274  *
275  *      ldy     xxx
276  *      ldx     #$00
277  *      lda     label,y
278  */
279 {
280     unsigned Changes = 0;
281
282     /* Walk over the entries */
283     unsigned I = 0;
284     while (I < CS_GetEntryCount (S)) {
285
286         CodeEntry* L[8];
287         unsigned Len;
288
289         /* Get next entry */
290         L[0] = CS_GetEntry (S, I);
291
292         /* Check for the sequence */
293         if (L[0]->OPC == OP65_LDA                            &&
294             L[0]->AM == AM65_IMM                             &&
295             CS_GetEntries (S, L+1, I+1, 7)                   &&
296             L[1]->OPC == OP65_LDX                            &&
297             L[1]->AM == AM65_IMM                             &&
298             L[2]->OPC == OP65_CLC                            &&
299             L[3]->OPC == OP65_ADC                            &&
300             (L[3]->AM == AM65_ABS || L[3]->AM == AM65_ZP)    &&
301             (L[4]->OPC == OP65_BCC || L[4]->OPC == OP65_JCC) &&
302             L[4]->JumpTo != 0                                &&
303             L[4]->JumpTo->Owner == L[6]                      &&
304             L[5]->OPC == OP65_INX                            &&
305             L[6]->OPC == OP65_LDY                            &&
306             CE_IsKnownImm (L[6], 0)                          &&
307             CE_IsCallTo (L[7], "ldauidx")                    &&
308             !CS_RangeHasLabel (S, I+1, 5)                    &&
309             !CE_HasLabel (L[7])                              &&
310             /* Check the label last because this is quite costly */
311             (Len = strlen (L[0]->Arg)) > 3                   &&
312             L[0]->Arg[0] == '<'                              &&
313             L[0]->Arg[1] == '('                              &&
314             strlen (L[1]->Arg) == Len                        &&
315             L[1]->Arg[0] == '>'                              &&
316             memcmp (L[0]->Arg+1, L[1]->Arg+1, Len-1) == 0) {
317
318             CodeEntry* X;
319             char* Label;
320
321             /* We will create all the new stuff behind the current one so
322              * we keep the line references.
323              */
324             X = NewCodeEntry (OP65_LDY, L[3]->AM, L[3]->Arg, 0, L[0]->LI);
325             CS_InsertEntry (S, X, I+8);
326
327             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[0]->LI);
328             CS_InsertEntry (S, X, I+9);
329
330             Label = memcpy (xmalloc (Len-2), L[0]->Arg+2, Len-3);
331             Label[Len-3] = '\0';
332             X = NewCodeEntry (OP65_LDA, AM65_ABSY, Label, 0, L[0]->LI);
333             CS_InsertEntry (S, X, I+10);
334             xfree (Label);
335
336             /* Remove the old code */
337             CS_DelEntries (S, I, 8);
338
339             /* Remember, we had changes */
340             ++Changes;
341
342         }
343
344         /* Next entry */
345         ++I;
346
347     }
348
349     /* Return the number of changes made */
350     return Changes;
351 }
352
353
354
355 unsigned OptPtrLoad4 (CodeSeg* S)
356 /* Search for the sequence:
357  *
358  *      lda     #<(label+0)
359  *      ldx     #>(label+0)
360  *      ldy     #$xx
361  *      clc
362  *      adc     (sp),y
363  *      bcc     L
364  *      inx
365  * L:   ldy     #$00
366  *      jsr     ldauidx
367  *
368  * and replace it by:
369  *
370  *      ldy     #$xx
371  *      lda     (sp),y
372  *      tay
373  *      ldx     #$00
374  *      lda     label,y
375  */
376 {
377     unsigned Changes = 0;
378
379     /* Walk over the entries */
380     unsigned I = 0;
381     while (I < CS_GetEntryCount (S)) {
382
383         CodeEntry* L[9];
384         unsigned Len;
385
386         /* Get next entry */
387         L[0] = CS_GetEntry (S, I);
388
389         /* Check for the sequence */
390         if (L[0]->OPC == OP65_LDA                            &&
391             L[0]->AM == AM65_IMM                             &&
392             CS_GetEntries (S, L+1, I+1, 8)                   &&
393             L[1]->OPC == OP65_LDX                            &&
394             L[1]->AM == AM65_IMM                             &&
395             !CE_HasLabel (L[1])                              &&
396             L[2]->OPC == OP65_LDY                            &&
397             CE_IsConstImm (L[2])                             &&
398             !CE_HasLabel (L[2])                              &&
399             L[3]->OPC == OP65_CLC                            &&
400             !CE_HasLabel (L[3])                              &&
401             L[4]->OPC == OP65_ADC                            &&
402             L[4]->AM == AM65_ZP_INDY                         &&
403             !CE_HasLabel (L[4])                              &&
404             (L[5]->OPC == OP65_BCC || L[5]->OPC == OP65_JCC) &&
405             L[5]->JumpTo != 0                                &&
406             L[5]->JumpTo->Owner == L[7]                      &&
407             !CE_HasLabel (L[5])                              &&
408             L[6]->OPC == OP65_INX                            &&
409             !CE_HasLabel (L[6])                              &&
410             L[7]->OPC == OP65_LDY                            &&
411             CE_IsKnownImm (L[7], 0)                          &&
412             CE_IsCallTo (L[8], "ldauidx")                    &&
413             !CE_HasLabel (L[8])                              &&
414             /* Check the label last because this is quite costly */
415             (Len = strlen (L[0]->Arg)) > 3                   &&
416             L[0]->Arg[0] == '<'                              &&
417             L[0]->Arg[1] == '('                              &&
418             strlen (L[1]->Arg) == Len                        &&
419             L[1]->Arg[0] == '>'                              &&
420             memcmp (L[0]->Arg+1, L[1]->Arg+1, Len-1) == 0) {
421
422             CodeEntry* X;
423             char* Label;
424
425             /* Add the lda */
426             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[4]->Arg, 0, L[0]->LI);
427             CS_InsertEntry (S, X, I+3);
428
429             /* Add the tay */
430             X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[0]->LI);
431             CS_InsertEntry (S, X, I+4);
432
433             /* Add the ldx */
434             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[0]->LI);
435             CS_InsertEntry (S, X, I+5);
436
437             /* Add the lda */
438             Label = memcpy (xmalloc (Len-2), L[0]->Arg+2, Len-3);
439             Label[Len-3] = '\0';
440             X = NewCodeEntry (OP65_LDA, AM65_ABSY, Label, 0, L[0]->LI);
441             CS_InsertEntry (S, X, I+6);
442             xfree (Label);
443
444             /* Remove the old code */
445             CS_DelEntries (S, I, 2);
446             CS_DelEntries (S, I+5, 6);
447
448             /* Remember, we had changes */
449             ++Changes;
450
451         }
452
453         /* Next entry */
454         ++I;
455
456     }
457
458     /* Return the number of changes made */
459     return Changes;
460 }
461
462
463
464 unsigned OptPtrLoad5 (CodeSeg* S)
465 /* Search for the sequence:
466  *
467  *      jsr     pushax
468  *      ldx     #$00
469  *      lda     yyy
470  *      jsr     tosaddax
471  *      ldy     #$00
472  *      jsr     ldauidx
473  *
474  * and replace it by:
475  *
476  *      sta     ptr1
477  *      stx     ptr1+1
478  *      ldy     yyy
479  *      ldx     #$00
480  *      lda     (ptr1),y
481  */
482 {
483     unsigned Changes = 0;
484
485     /* Walk over the entries */
486     unsigned I = 0;
487     while (I < CS_GetEntryCount (S)) {
488
489         CodeEntry* L[6];
490
491         /* Get next entry */
492         L[0] = CS_GetEntry (S, I);
493
494         /* Check for the sequence */
495         if (CE_IsCallTo (L[0], "pushax")                &&
496             CS_GetEntries (S, L+1, I+1, 5)              &&
497             L[1]->OPC == OP65_LDX                       &&
498             CE_IsKnownImm (L[1], 0)                     &&
499             L[2]->OPC == OP65_LDA                       &&
500             (L[2]->AM == AM65_ABS       ||
501              L[2]->AM == AM65_ZP        ||
502              L[2]->AM == AM65_IMM)                      &&
503             CE_IsCallTo (L[3], "tosaddax")              &&
504             L[4]->OPC == OP65_LDY                       &&
505             CE_IsKnownImm (L[4], 0)                     &&
506             CE_IsCallTo (L[5], "ldauidx")               &&
507             !CS_RangeHasLabel (S, I+1, 5)) {
508
509             CodeEntry* X;
510
511             /* sta ptr1 */
512             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI);
513             CS_InsertEntry (S, X, I+6);
514
515             /* stx ptr1+1 */
516             X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI);
517             CS_InsertEntry (S, X, I+7);
518
519             /* ldy yyy */
520             X = NewCodeEntry (OP65_LDY, L[2]->AM, L[2]->Arg, 0, L[2]->LI);
521             CS_InsertEntry (S, X, I+8);
522
523             /* ldx #$00 */
524             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[5]->LI);
525             CS_InsertEntry (S, X, I+9);
526
527             /* lda (ptr1),y */
528             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[5]->LI);
529             CS_InsertEntry (S, X, I+10);
530
531             /* Remove the old code */
532             CS_DelEntries (S, I, 6);
533
534             /* Remember, we had changes */
535             ++Changes;
536
537         }
538
539         /* Next entry */
540         ++I;
541
542     }
543
544     /* Return the number of changes made */
545     return Changes;
546 }
547
548
549
550 unsigned OptPtrLoad6 (CodeSeg* S)
551 /* Search for the sequence:
552  *
553  *      jsr     pushax
554  *      ldy     #xxx
555  *      ldx     #$00
556  *      lda     (sp),y
557  *      jsr     tosaddax
558  *      ldy     #$00
559  *      jsr     ldauidx
560  *
561  * and replace it by:
562  *
563  *      sta     ptr1
564  *      stx     ptr1+1
565  *      ldy     #xxx-2
566  *      lda     (sp),y
567  *      tay
568  *      ldx     #$00
569  *      lda     (ptr1),y
570  */
571 {
572     unsigned Changes = 0;
573
574     /* Walk over the entries */
575     unsigned I = 0;
576     while (I < CS_GetEntryCount (S)) {
577
578         CodeEntry* L[7];
579
580         /* Get next entry */
581         L[0] = CS_GetEntry (S, I);
582
583         /* Check for the sequence */
584         if (CE_IsCallTo (L[0], "pushax")                &&
585             CS_GetEntries (S, L+1, I+1, 6)              &&
586             L[1]->OPC == OP65_LDY                       &&
587             CE_IsConstImm (L[1])                        &&
588             L[1]->Num >= 2                              &&
589             L[2]->OPC == OP65_LDX                       &&
590             CE_IsKnownImm (L[2], 0)                     &&
591             L[3]->OPC == OP65_LDA                       &&
592             L[3]->AM == AM65_ZP_INDY                    &&
593             CE_IsCallTo (L[4], "tosaddax")              &&
594             L[5]->OPC == OP65_LDY                       &&
595             CE_IsKnownImm (L[5], 0)                     &&
596             CE_IsCallTo (L[6], "ldauidx")               &&
597             !CS_RangeHasLabel (S, I+1, 6)               &&
598             !RegYUsed (S, I+7)) {
599
600             CodeEntry*  X;
601             const char* Arg;
602
603             /* sta ptr1 */
604             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI);
605             CS_InsertEntry (S, X, I+7);
606
607             /* stx ptr1+1 */
608             X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI);
609             CS_InsertEntry (S, X, I+8);
610
611             /* ldy #xxx-2 */
612             Arg = MakeHexArg (L[1]->Num - 2);
613             X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI);
614             CS_InsertEntry (S, X, I+9);
615
616             /* lda (sp),y */
617             X = NewCodeEntry (OP65_LDA, L[3]->AM, L[3]->Arg, 0, L[3]->LI);
618             CS_InsertEntry (S, X, I+10);
619
620             /* tay */
621             X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[3]->LI);
622             CS_InsertEntry (S, X, I+11);
623
624             /* ldx #$00 */
625             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[5]->LI);
626             CS_InsertEntry (S, X, I+12);
627
628             /* lda (ptr1),y */
629             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[6]->LI);
630             CS_InsertEntry (S, X, I+13);
631
632             /* Remove the old code */
633             CS_DelEntries (S, I, 7);
634
635             /* Remember, we had changes */
636             ++Changes;
637
638         }
639
640         /* Next entry */
641         ++I;
642
643     }
644
645     /* Return the number of changes made */
646     return Changes;
647 }
648
649
650
651 unsigned OptPtrLoad7 (CodeSeg* S)
652 /* Search for the sequence:
653  *
654  *      jsr     aslax1/shlax1
655  *      clc
656  *      adc     xxx
657  *      tay
658  *      txa
659  *      adc     yyy
660  *      tax
661  *      tya
662  *      ldy     zzz
663  *      jsr     ldaxidx
664  *
665  * and replace it by:
666  *
667  *      stx     tmp1
668  *      asl     a
669  *      rol     tmp1
670  *      clc
671  *      adc     xxx
672  *      sta     ptr1
673  *      lda     tmp1
674  *      adc     yyy
675  *      sta     ptr1+1
676  *      ldy     zzz
677  *      lda     (ptr1),y
678  *      tax
679  *      dey
680  *      lda     (ptr1),y
681  */
682 {
683     unsigned Changes = 0;
684     unsigned I;
685
686     /* Walk over the entries */
687     I = 0;
688     while (I < CS_GetEntryCount (S)) {
689
690         CodeEntry* L[10];
691
692         /* Get next entry */
693         L[0] = CS_GetEntry (S, I);
694
695         /* Check for the sequence */
696         if (L[0]->OPC == OP65_JSR                               &&
697             (strcmp (L[0]->Arg, "aslax1") == 0          ||
698              strcmp (L[0]->Arg, "shlax1") == 0)                 &&
699             CS_GetEntries (S, L+1, I+1, 9)                      &&
700             L[1]->OPC == OP65_CLC                               &&
701             L[2]->OPC == OP65_ADC                               &&
702             L[3]->OPC == OP65_TAY                               &&
703             L[4]->OPC == OP65_TXA                               &&
704             L[5]->OPC == OP65_ADC                               &&
705             L[6]->OPC == OP65_TAX                               &&
706             L[7]->OPC == OP65_TYA                               &&
707             L[8]->OPC == OP65_LDY                               &&
708             CE_IsCallTo (L[9], "ldaxidx")                       &&
709             !CS_RangeHasLabel (S, I+1, 9)) {
710
711             CodeEntry* X;
712
713             /* Track the insertion point */
714             unsigned IP = I + 10;
715
716
717             /* If X is zero on entry to aslax1, we can generate:
718              *
719              *      asl     a
720              *      bcc     L1
721              *      inx
722              * L1:  clc
723              *
724              * instead of the code above. "lda tmp1" needs to be changed
725              * to "txa" in this case.
726              */
727             int ShortCode = (L[0]->RI->In.RegX == 0);
728
729             if (ShortCode) {
730
731                 CodeLabel* Lab;
732
733                 /* asl a */
734                 X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, L[0]->LI);
735                 CS_InsertEntry (S, X, IP++);
736
737                 /* Generate clc first, since we need the label */
738                 X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[1]->LI);
739                 CS_InsertEntry (S, X, IP);
740
741                 /* Get the label */
742                 Lab = CS_GenLabel (S, X);
743
744                 /* bcc Lab */
745                 X = NewCodeEntry (OP65_BCC, AM65_BRA, Lab->Name, Lab, L[0]->LI);
746                 CS_InsertEntry (S, X, IP++);
747
748                 /* inx */
749                 X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, L[0]->LI);
750                 CS_InsertEntry (S, X, IP++);
751
752                 /* Skip the clc insn */
753                 ++IP;
754
755             } else {
756
757                 /* stx tmp1 */
758                 X = NewCodeEntry (OP65_STX, AM65_ZP, "tmp1", 0, L[0]->LI);
759                 CS_InsertEntry (S, X, IP++);
760
761                 /* asl a */
762                 X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, L[0]->LI);
763                 CS_InsertEntry (S, X, IP++);
764
765                 /* rol tmp1 */
766                 X = NewCodeEntry (OP65_ROL, AM65_ZP, "tmp1", 0, L[0]->LI);
767                 CS_InsertEntry (S, X, IP++);
768
769                 /* clc */
770                 X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[1]->LI);
771                 CS_InsertEntry (S, X, IP++);
772
773             }
774
775             /* adc xxx */
776             X = NewCodeEntry (L[2]->OPC, L[2]->AM, L[2]->Arg, 0, L[2]->LI);
777             CS_InsertEntry (S, X, IP++);
778
779             /* sta ptr1 */
780             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[9]->LI);
781             CS_InsertEntry (S, X, IP++);
782
783             if (ShortCode) {
784                 /* txa */
785                 X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, L[4]->LI);
786             } else {
787                 /* lda tmp1 */
788                 X = NewCodeEntry (OP65_LDA, AM65_ZP, "tmp1", 0, L[4]->LI);
789             }
790             CS_InsertEntry (S, X, IP++);
791
792             /* adc xxx */
793             X = NewCodeEntry (L[5]->OPC, L[5]->AM, L[5]->Arg, 0, L[5]->LI);
794             CS_InsertEntry (S, X, IP++);
795
796             /* sta ptr1+1 */
797             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1+1", 0, L[9]->LI);
798             CS_InsertEntry (S, X, IP++);
799
800             /* ldy zzz */
801             X = NewCodeEntry (L[8]->OPC, L[8]->AM, L[8]->Arg, 0, L[8]->LI);
802             CS_InsertEntry (S, X, IP++);
803
804             /* lda (ptr1),y */
805             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[9]->LI);
806             CS_InsertEntry (S, X, IP++);
807
808             /* tax */
809             X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[9]->LI);
810             CS_InsertEntry (S, X, IP++);
811
812             /* dey */
813             X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[9]->LI);
814             CS_InsertEntry (S, X, IP++);
815
816             /* lda (ptr1),y */
817             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[9]->LI);
818             CS_InsertEntry (S, X, IP++);
819
820             /* Remove the old code */
821             CS_DelEntries (S, I, 10);
822
823             /* Remember, we had changes */
824             ++Changes;
825
826         }
827
828         /* Next entry */
829         ++I;
830
831     }
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     /* Walk over the entries */
1163     I = 0;
1164     while (I < CS_GetEntryCount (S)) {
1165
1166         CodeEntry* L[5];
1167         unsigned Len;
1168
1169         /* Get next entry */
1170         L[0] = CS_GetEntry (S, I);
1171
1172         /* Check for the sequence */
1173         if (L[0]->OPC == OP65_LDA && L[0]->AM == AM65_ZP        &&
1174             CS_GetEntries (S, L+1, I+1, 4)                      &&
1175             !CS_RangeHasLabel (S, I+1, 4)                       &&
1176             L[1]->OPC == OP65_LDX && L[1]->AM == AM65_ZP        &&
1177             (Len = strlen (L[0]->Arg)) > 0                      &&
1178             strncmp (L[0]->Arg, L[1]->Arg, Len) == 0            &&
1179             strcmp (L[1]->Arg + Len, "+1") == 0                 &&
1180             (L[2]->Chg & REG_AX) == 0                           &&
1181             L[3]->OPC == OP65_LDY                               &&
1182             CE_IsCallTo (L[4], "ldauidx")) {
1183
1184             CodeEntry* X;
1185
1186             /* ldx #$00 */
1187             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[3]->LI);
1188             CS_InsertEntry (S, X, I+5);
1189
1190             /* lda (zp),y */
1191             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[3]->LI);
1192             CS_InsertEntry (S, X, I+6);
1193
1194             /* Remove the old code */
1195             CS_DelEntry (S, I+4);
1196
1197             /* Remember, we had changes */
1198             ++Changes;
1199
1200         }
1201
1202         /* Next entry */
1203         ++I;
1204
1205     }
1206
1207     /* Return the number of changes made */
1208     return Changes;
1209 }
1210
1211
1212
1213 unsigned OptPtrLoad15 (CodeSeg* S)
1214 /* Search for the sequence:
1215  *
1216  *      lda     zp
1217  *      ldx     zp+1
1218  *      jsr     pushax          <- optional
1219  *      ldy     xx
1220  *      jsr     ldaxidx
1221  *
1222  * and replace it by:
1223  *
1224  *      lda     zp              <- only if
1225  *      ldx     zp+1            <- call to
1226  *      jsr     pushax          <- pushax present
1227  *      ldy     xx
1228  *      lda     (zp),y
1229  *      tax
1230  *      dey
1231  *      lda     (zp),y
1232  */
1233 {
1234     unsigned Changes = 0;
1235
1236     /* Walk over the entries */
1237     unsigned I = 0;
1238     while (I < CS_GetEntryCount (S)) {
1239
1240         CodeEntry* L[5];
1241         unsigned Len;
1242
1243         /* Check for the start of the sequence */
1244         if (CS_GetEntries (S, L, I, 3)                          &&
1245             L[0]->OPC == OP65_LDA && L[0]->AM == AM65_ZP        &&
1246             L[1]->OPC == OP65_LDX && L[1]->AM == AM65_ZP        &&
1247             !CS_RangeHasLabel (S, I+1, 2)                       &&
1248             (Len = strlen (L[0]->Arg)) > 0                      &&
1249             strncmp (L[0]->Arg, L[1]->Arg, Len) == 0            &&
1250             strcmp (L[1]->Arg + Len, "+1") == 0) {
1251
1252             unsigned PushAX = CE_IsCallTo (L[2], "pushax");
1253
1254             /* Check for the remainder of the sequence */
1255             if (CS_GetEntries (S, L+3, I+3, 1 + PushAX)         &&
1256                 !CS_RangeHasLabel (S, I+3, 1 + PushAX)          &&
1257                 L[2+PushAX]->OPC == OP65_LDY                    &&
1258                 CE_IsCallTo (L[3+PushAX], "ldaxidx")) {
1259
1260                 CodeEntry* X;
1261
1262                 /* lda (zp),y */
1263                 X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[3]->LI);
1264                 CS_InsertEntry (S, X, I+PushAX+4);
1265
1266                 /* tax */
1267                 X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[3]->LI);
1268                 CS_InsertEntry (S, X, I+PushAX+5);
1269
1270                 /* dey */
1271                 X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[3]->LI);
1272                 CS_InsertEntry (S, X, I+PushAX+6);
1273
1274                 /* lda (zp),y */
1275                 X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[3]->LI);
1276                 CS_InsertEntry (S, X, I+PushAX+7);
1277
1278                 /* Remove the old code */
1279                 CS_DelEntry (S, I+PushAX+3);
1280                 if (!PushAX) {
1281                     CS_DelEntries (S, I, 2);
1282                 }
1283
1284                 /* Remember, we had changes */
1285                 ++Changes;
1286
1287             }
1288         }
1289
1290         /* Next entry */
1291         ++I;
1292
1293     }
1294
1295     /* Return the number of changes made */
1296     return Changes;
1297 }
1298
1299
1300
1301 unsigned OptPtrLoad16 (CodeSeg* S)
1302 /* Search for the sequence
1303  *
1304  *      ldy     ...
1305  *      jsr     ldauidx
1306  *
1307  * and replace it by:
1308  *
1309  *      stx     ptr1+1
1310  *      sta     ptr1
1311  *      ldy     ...
1312  *      ldx     #$00
1313  *      lda     (ptr1),y
1314  *
1315  * This step must be executed *after* OptPtrLoad1!
1316  */
1317 {
1318     unsigned Changes = 0;
1319
1320     /* Walk over the entries */
1321     unsigned I = 0;
1322     while (I < CS_GetEntryCount (S)) {
1323
1324         CodeEntry* L[2];
1325
1326         /* Get next entry */
1327         L[0] = CS_GetEntry (S, I);
1328
1329         /* Check for the sequence */
1330         if (L[0]->OPC == OP65_LDY               &&
1331             CS_GetEntries (S, L+1, I+1, 1)      &&
1332             CE_IsCallTo (L[1], "ldauidx")       &&
1333             !CE_HasLabel (L[1])) {
1334
1335             CodeEntry* X;
1336
1337             /* stx ptr1+1 */
1338             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[1]->LI);
1339             CS_InsertEntry (S, X, I+2);
1340
1341             /* sta ptr1 */
1342             X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[1]->LI);
1343             CS_InsertEntry (S, X, I+3);
1344
1345             /* ldy ... */
1346             X = NewCodeEntry (L[0]->OPC, L[0]->AM, L[0]->Arg, 0, L[0]->LI);
1347             CS_InsertEntry (S, X, I+4);
1348
1349             /* ldx #$00 */
1350             X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[1]->LI);
1351             CS_InsertEntry (S, X, I+5);
1352
1353             /* lda (ptr1),y */
1354             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[1]->LI);
1355             CS_InsertEntry (S, X, I+6);
1356
1357             /* Delete the old code */
1358             CS_DelEntries (S, I, 2);
1359
1360             /* Remember, we had changes */
1361             ++Changes;
1362
1363         }
1364
1365         /* Next entry */
1366         ++I;
1367
1368     }
1369
1370     /* Return the number of changes made */
1371     return Changes;
1372 }
1373
1374
1375
1376 unsigned OptPtrLoad17 (CodeSeg* S)
1377 /* Search for the sequence
1378  *
1379  *      ldy     ...
1380  *      jsr     ldaxidx
1381  *
1382  * and replace it by:
1383  *
1384  *      sta     ptr1
1385  *      stx     ptr1+1
1386  *      ldy     ...
1387  *      lda     (ptr1),y
1388  *      tax
1389  *      dey
1390  *      lda     (ptr1),y
1391  *
1392  * This step must be executed *after* OptPtrLoad9! While code size increases
1393  * by more than 200%, inlining will greatly improve visibility for the
1394  * optimizer, so often part of the code gets improved later. So we will mark
1395  * the step with less than 200% so it gets executed when -Oi is in effect.
1396  */
1397 {
1398     unsigned Changes = 0;
1399
1400     /* Walk over the entries */
1401     unsigned I = 0;
1402     while (I < CS_GetEntryCount (S)) {
1403
1404         CodeEntry* L[2];
1405
1406         /* Get next entry */
1407         L[0] = CS_GetEntry (S, I);
1408
1409         /* Check for the sequence */
1410         if (L[0]->OPC == OP65_LDY               &&
1411             CS_GetEntries (S, L+1, I+1, 1)      &&
1412             CE_IsCallTo (L[1], "ldaxidx")       &&
1413             !CE_HasLabel (L[1])) {
1414
1415             CodeEntry* X;
1416
1417             /* Store the high byte */
1418             X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI);
1419             CS_InsertEntry (S, X, I+2);
1420
1421             /* Store the low byte */
1422             X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI);
1423             CS_InsertEntry (S, X, I+3);
1424
1425             /* ldy ... */
1426             X = NewCodeEntry (L[0]->OPC, L[0]->AM, L[0]->Arg, 0, L[0]->LI);
1427             CS_InsertEntry (S, X, I+4);
1428
1429             /* lda (ptr1),y */
1430             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[1]->LI);
1431             CS_InsertEntry (S, X, I+5);
1432
1433             /* tax */
1434             X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[1]->LI);
1435             CS_InsertEntry (S, X, I+6);
1436
1437             /* dey */
1438             X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[1]->LI);
1439             CS_InsertEntry (S, X, I+7);
1440
1441             /* lda (ptr1),y */
1442             X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[1]->LI);
1443             CS_InsertEntry (S, X, I+8);
1444
1445             /* Delete original sequence */
1446             CS_DelEntries (S, I, 2);
1447
1448             /* Remember, we had changes */
1449             ++Changes;
1450
1451         }
1452
1453         /* Next entry */
1454         ++I;
1455
1456     }
1457
1458     /* Return the number of changes made */
1459     return Changes;
1460 }