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