minor addition improvement
[fw/sdcc] / src / z80 / peeph-z80.def
1 // peeph.def - Common Z80 and gbz80 peephole rules
2 //
3 // These peepholes could be potentially moved to peeph.def, but a GBZ80 expert
4 // Should have a look at them before.
5 //
6 // (c) Philipp Klaus Krause (pkk@spth.de, philipp@colecovision.eu) 2006 - 2008
7 //
8 // This program is free software; you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by the
10 // Free Software Foundation; either version 2, or (at your option) any
11 // later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22 replace restart {
23         ld      %1,%1
24 } by {
25         ; peephole -1 removed redundant load.
26 } if notVolatile(%1)
27
28 // This one doesn't work currently since the peephole optimizer can't match lines generated by multiline macros: Bug #1570701
29 //replace restart {
30 //      pop     af
31 //      ld      sp,%1
32 //} by {
33 //      ; peephole -1a eleminated dead pop.
34 //      ld      sp,%1
35 //} if notUsed('a')
36
37 replace restart {
38         ld      %1,%2
39 } by {
40         ; peephole 0a removed dead load from %2 into %1.
41 } if notVolatile(%1), notUsed(%1)
42 // Should probably check for notVolatile(%2), too, but gives many false positives and no regression tests fail.
43
44 replace restart {
45         ld      %1,%2
46         ld      a,%1
47 } by {
48         ; peephole 0b loaded %2 into a directly instead of going through %1.
49         ld      a,%2
50 } if notVolatile(%1), notUsed(%1)
51
52 replace restart {
53         ld      %1,%2 (%3)
54         ld      a,%1
55 } by {
56         ; peephole 0c loaded %2 (%3) into a directly instead of going through %1.
57         ld      a,%2 (%3)
58 } if notVolatile(%1), notUsed(%1)
59
60 replace restart {
61         ld      %1,#%2
62         ld      a,%3 (%1)
63 } by {
64         ; peephole 0d loaded %2 into a directly instead of going through %1.
65         ld      a,(#%2+%3)
66 } if notUsed(%1)
67
68 replace restart {
69         srl     %1
70         ld      a,%1
71 } by {
72         ld      a,%1
73         ; peephole 0e shifted in a instead of %1.
74         srl     a
75 } if notVolatile(%1), notUsed(%1)
76
77 replace restart {
78         ld      %1,(hl)
79         ld      a,%2 (%3)
80         sub     a,%1
81 } by {
82         ld      a,%2 (%3)
83         ; peephole 0f used (hl) in sub directly instead of going through %1.
84         sub     a,(hl)
85 } if notVolatile(%1), notUsed(%1)
86
87 replace restart {
88         inc     bc
89         ld      l,c
90         ld      h,b
91 } by {
92         ld      l,c
93         ld      h,b
94         ; peephole 0g incremented in hl instead of bc.
95         inc     hl
96 } if notUsed('bc')
97
98 // Catch double and triple incs before later peepholes introduce an ex de,hl in here.
99 replace restart {
100         inc     de
101         inc     de
102         ld      l,e
103         ld      h,d
104 } by {
105         ld      l,e
106         ld      h,d
107         ; peephole 0h' incremented in hl instead of de.
108         inc     hl
109         inc     hl
110 } if notUsed('de')
111
112 replace restart {
113         inc     de
114         ld      l,e
115         ld      h,d
116 } by {
117         ld      l,e
118         ld      h,d
119         ; peephole 0h incremented in hl instead of de.
120         inc     hl
121 } if notUsed('de')
122
123 replace restart {
124         ld      e,%1
125         ld      d,%2
126         ld      l,e
127         ld      h,d
128 } by {
129         ; peephole 0i loaded %2%1 into hl directly instead of going through de.
130         ld      l,%1
131         ld      h,%2
132 } if notUsed('de')
133
134 replace restart {
135         ld      bc,#%2 + %3
136         ld      a,(bc)
137         ld      c,a
138 } by {
139         ; peephole 0j used hl for #%2 + %3 instead of bc, not going through a.
140         ld      hl,#%2 + %3
141         ld      c,(hl)
142 } if notUsed('a'), notUsed('hl')
143
144 replace restart {
145         ex      de,hl
146         push    hl
147 } by {
148         ; peephole 0k pushed de directly instead of going through hl.
149         push    de
150 } if notUsed('de'), notUsed('hl')
151
152 replace restart {
153         ex      de,hl
154         push    de
155 } by {
156         ; peephole 0k' pushed de directly instead of going through hl.
157         push    hl
158 } if notUsed('de'), notUsed('hl')
159
160 replace restart {
161         ex      de,hl
162         push    bc
163         push    de
164 } by {
165         ; peephole 0l pushed hl directly instead of going through de.
166         push    bc
167         push    hl
168 } if notUsed('de'), notUsed('hl')
169
170 replace restart {
171         ld      l,c
172         ld      h,b
173         push    hl
174 } by {
175         ; peephole 0m pushed bc directly instead of going through hl.
176         push    bc
177 } if notUsed('hl')
178
179 replace restart {
180         ld      c,a
181         push    de
182         ld      a,c
183 } by {
184         ; peephole 0n removed redundant load of a through c.
185         push    de
186 } if notUsed('c')
187
188 replace restart {
189         ld      c,e
190         ld      b,d
191         ld      a,(bc)
192 } by {
193         ; peephole 0o used de directly instead of going through bc.
194         ld      a,(de)
195 } if notUsed('bc')
196
197 replace restart {
198         pop     de
199         ld      l,e
200         ld      h,d
201 } by {
202         ; peephole 0p popped hl directly instead of going through de.
203         pop     hl
204 } if notUsed('de')
205
206 replace restart {
207         ld      %1,a
208         ld      %2 (%3),%1
209 } by {
210         ; peephole 0q loaded a into %2 (%3) directly instead of going through %1.
211         ld      %2 (%3),a
212 } if notVolatile(%1), notUsed(%1)
213
214 replace restart {
215         ld      %1 (ix),%2
216         ld      %3, %1 (ix)
217 } by {
218         ; peephole 0r loaded %3 from %2 instead of going through %1 (ix).
219         ld      %1 (ix),%2
220         ld      %3, %2
221 }
222 // Don't need to check for volatile, since ix is used for the stack.
223
224 replace restart {
225         ld      %1, %2 (%3)
226         ld      b, %1
227 } by {
228         ; peephole 0s loaded b from %2 (%3) instead of going through %1.
229         ld      b, %2 (%3)
230 } if notVolatile(%1), notUsed(%1)
231
232 replace restart {
233         ld      %1,a
234         ld      %2,%3
235         ld      %4,%1
236 } by {
237         ; peephole 0t loaded %4 from a instead of going through %1.
238         ld      %1,a
239         ld      %2,%3
240         ld      %4,a
241 } if notVolatile(%1), operandsNotRelated(%1 %3), operandsNotRelated(%1 %2)
242
243 replace restart {
244         ld      %1,(hl)
245         ld      e,%1
246 } by {
247         ; peephole 0u loaded e from (hl) instead of going through %1.
248         ld      e,(hl)
249 } if notUsed(%1)
250
251 replace restart {
252         ld      %1,l
253         ld      %2 (%3),%1
254 } by {  
255         ; peephole 0v loaded %2 (%3) from l instead of going through %1.
256         ld      %2 (%3),l
257 } if notUsed(%1)
258
259 replace restart {
260         ld      l,%1 (ix)
261         ld      h,%2 (ix)
262         ld      %3,(hl)
263         srl     %3
264         ld      l,%1 (ix)
265         ld      h,%2 (ix)
266         ld      (hl),%3
267 } by {  
268         ld      l,%1 (ix)
269         ld      h,%2 (ix)
270         ; peephole 0w shifted (hl) in place.
271         srl     (hl)
272         ld      %3,(hl)
273 } if notVolatile(%3)
274 // Don't check for volatile since ix points to the stack.
275
276 replace restart {
277         push    af
278         inc     sp
279         ld      a,e
280         push    af
281         inc     sp
282 } by {
283         ; peephole 0x pushed de instead of pushing a twice.
284         ld      d,a
285         push    de
286 } if notUsed('d'), notUsed('a')
287
288 replace restart {
289         push    af
290         inc     sp
291         ld      a,c
292         push    af
293         inc     sp
294 } by {
295         ; peephole 0y pushed bc instead of pushing a twice.
296         ld      b,a
297         push    bc
298 } if notUsed('b'), notUsed('a')
299
300 replace restart {
301         ld      a,#%1
302         ld      d,a
303 } by {
304         ; peephole 0z loaded #%1 into d directly instead of going through a.
305         ld      d,#%1
306 } if notUsed('a')
307
308 replace restart {
309         ld      a,%1 (ix)
310         push    af
311         inc     sp
312         ld      a,%2 (ix)
313         push    af
314         inc     sp
315 } by {
316         ; peephole 0za pushed %1 (ix), %2(ix) through hl instead of af.
317         ld      h,%1 (ix)
318         ld      l,%2 (ix)
319         push    hl
320 } if notUsed('a'), notUsed('hl')
321
322 replace restart {
323         ld      c,l
324         ld      b,h
325         push    bc
326 } by {
327         ; peephole 0zb pushed hl instead of bc.
328         push    hl
329 } if notUsed('bc')
330
331 // Doesn'T work due to bug #1947081
332 //replace restart {
333 //      pop     %1
334 //      push    %1
335 //} by {
336 //      ; peephole 0zc eleminated dead pop/push pair.
337 //} if notUsed(%1)
338
339 replace restart {
340         ld      iy,#%1
341         or      a,%2 (iy)
342 } by {
343         ; peephole 0zd used hl instead of iy.
344         ld      hl,#%1 + %2
345         or      a,(hl)
346 } if notUsed('iy'), notUsed('hl')
347
348 replace restart {
349         ld      iy,#%1
350         ld      %2,%3 (%4)
351 } by {
352         ; peephole 0ze used hl instead of iy.
353         ld      hl,#%1 + %3
354         ld      %2,(hl)
355 } if notUsed('iy'), notUsed('hl')
356
357 replace restart {
358         ld      iy,#%1
359         ld      %2 (%3), %4
360 } by {
361         ; peephole 0zf used hl instead of iy.
362         ld      hl,#%1 + %2
363         ld      (hl), %4
364 } if notUsed('iy'), notUsed('hl'), operandsNotRelated(%4 'h'), operandsNotRelated(%4 'l')
365
366 replace restart {
367         ld      e,l
368         ld      d,h
369         ld      %1,(de)
370 } by {
371         ; peephole 0zg loaded %1 from (hl) directly instead of going through (de).
372         ld      %1,(hl)
373 } if notUsed('de')
374
375 replace restart {
376         ld      c,l
377         ld      b,h
378         ld      %1,(bc)
379 } by {
380         ; peephole 0zh loaded %1 from (hl) directly instead of going through (bc).
381         ld      %1,(hl)
382 } if notUsed('bc')
383
384 replace restart {
385         ld      c,l
386         ld      b,h
387         inc     bc
388 } by {
389         ; peephole 0zi incremented in hl instead of bc.
390         inc     hl
391         ld      c,l
392         ld      b,h
393 } if notUsed('hl')
394
395 replace restart {
396         ld      a,%1 (%2)
397         bit     %3,a
398 } by {
399         ; peephole 0zj tested bit of %1 (%2) directly instead of going through a.
400         bit     %3,%1 (%2)
401 } if notUsed('a')
402
403 replace restart {
404         ld      bc, #%1 + %2
405         ld      l,c
406         ld      h,b
407 } by {
408         ; peephole 0zk stored constant #%1 + %2 into hl directly instead of going through bc.
409         ld      hl, #%1 + %2
410 } if notUsed('bc')
411
412 replace restart {
413         ld      c, %1 (%2)
414         ld      b, %3 (%4)
415         ld      l,c
416         ld      h,b
417 } by {
418         ; peephole 0zk' stored %1 (%2) %3 (%4) into hl directly instead of going through bc.
419         ld      l, %1 (%2)
420         ld      h, %3 (%4)
421 } if notUsed('bc')
422
423 replace restart {
424         jp      NC,%1
425         jp      %2
426 %1:
427 } by {
428         jp      C,%2
429         ; peephole 3 removed jp by using inverse jump logic
430 %1:
431 } if labelRefCountChange(%1 -1)
432
433 replace restart {
434         jp      C,%1
435         jp      %2
436 %1:
437 } by {
438         jp      NC,%2
439         ; peephole 4 removed jp by using inverse jump logic
440 %1:
441 } if labelRefCountChange(%1 -1)
442
443 replace restart {
444         jp      NZ,%1
445         jp      %2
446 %1:
447 } by {
448         jp      Z,%2
449         ; peephole 5 removed jp by using inverse jump logic
450 %1:
451 } if labelRefCountChange(%1 -1)
452
453 replace restart {
454         jp      Z,%1
455         jp      %2
456 %1:
457 } by {
458         jp      NZ,%2
459         ; peephole 6 removed jp by using inverse jump logic
460 %1:
461 } if labelRefCountChange(%1 -1)
462
463 replace restart {
464         jp      %5
465 } by {
466         jp      %6
467         ; peephole 7 redirected jump-to-jump at %5 by jump to %6
468 } if labelIsUncondJump(), labelRefCountChange(%5 -1), labelRefCountChange(%6 +1)
469
470 replace restart {
471         jp      %1,%5
472 } by {
473         jp      %1,%6
474         ; peephole 8 redirected jump-to-jump at %5 by jump to %6
475 } if labelIsUncondJump(), labelRefCountChange(%5 -1), labelRefCountChange(%6 +1)
476
477 replace restart {
478         xor     a,a
479         ld      a,#0x00
480 } by {
481         xor     a,a
482         ; peephole 10 removed redundant load of 0 into a.
483 }
484
485 replace {
486         ld      e,#0x%1
487         ld      d,#0x%2
488 } by {
489         ld      de,#0x%2%1
490         ; peephole 11 combined constant loads into register pair.
491 }
492
493 replace {
494         ld      l,#0x%1
495         ld      h,#0x%2
496 } by {
497         ld      hl,#0x%2%1
498         ; peephole 12 combined constant loads into register pair.
499 }
500
501 replace {
502         ld      c,#0x%1
503         ld      b,#0x%2
504 } by {
505         ld      bc,#0x%2%1
506         ; peephole 13 combined constant loads into register pair.
507 }
508
509 replace restart {
510         ld      %1,a
511         ld      a,%1
512 } by {
513         ld      %1,a
514         ; peephole 14 removed redundant load from %1 into a.
515 } if notVolatile(%1)
516 // This gives many false negatives and without the test no problems are encountered in the regression tests
517 // Maybe we can try this after 2.7.0 release
518
519 replace restart {
520         ld      a,%1
521         ld      %1,a
522 } by {
523         ld      a,%1
524         ; peephole 15 removed redundant load from a into %1.
525 } if notVolatile(%1)
526 // This gives many false negatives and without the test no problems are encountered in the regression tests
527 // Maybe we can try this after 2.7.0 release
528
529 replace restart {
530         ld      %1,a
531         ld      a,%2
532         or      a,%1
533 } by {
534         ld      %1,a
535         or      a,%2
536         ; peephole 17 removed load by reordering or arguments.
537 } if notVolatile(%1)
538
539 replace restart {
540         ld      %1,a
541         xor     a,a
542         or      a,%1
543 } by {
544         ld      %1,a
545         or      a,a
546         ; peephole 18 used value still in a instead of loading it from %1.
547 }
548
549 replace restart {
550         or      a,%1
551         or      a,a
552 } by {
553         or      a,%1
554         ; peephole 19 removed redundant or after or.
555 }
556
557 replace restart {
558         or      a,%1 (%2)
559         or      a,a
560 } by {
561         or      a,%1 (%2)
562         ; peephole 19a removed redundant or after or.
563 }
564
565 replace restart {
566         and     a,%1
567         or      a,a
568 } by {
569         and     a,%1
570         ; peephole 20 removed redundant or after and.
571 }
572
573 replace restart {
574         and     a,%1 (%2)
575         or      a,a
576 } by {
577         and     a,%1 (%2)
578         ; peephole 20a removed redundant or after and.
579 }
580
581 replace restart {
582         xor     a,%1
583         or      a,a
584 } by {
585         xor     a,%1
586         ; peephole 21 removed redundant or after xor.
587 }
588
589 replace restart {
590         xor     a,%1 (%2)
591         or      a,a
592 } by {
593         xor     a,%1 (%2)
594         ; peephole 21a removed redundant or after xor.
595 }
596
597 replace {
598         ld      %1,%2
599         ld      a,%2
600 } by {
601         ld      a,%2
602         ld      %1,a
603         ; peephole 23 load value in a first and use it next
604 } if notVolatile(%1 %2)
605
606 replace restart {
607         ld      %1,%2
608         ld      %3,%4
609         ld      %2,%1
610         ld      %4,%3
611 } by {
612         ld      %1,%2
613         ld      %3,%4
614         ; peephole 24 removed redundant load from %3%1 into %4%2
615 } if notVolatile(%1 %2 %3 %4)
616
617 replace restart {
618         ld      a,c
619         push    af
620         inc     sp
621         ld      a,#%2
622         push    af
623         inc     sp
624         call    %3
625 } by {
626         ld      b,c
627         ld      c,#%2
628         push    bc
629         ; peephole 31 moved and pushed arguments c and #%2 through bc instead of pushing them individually.
630         call    %3
631 }
632
633 replace restart {
634         ld      a,e
635         push    af
636         inc     sp
637         ld      a,#%2
638         push    af
639         inc     sp
640         call    %3
641 } by {
642         ld      d,e
643         ld      e,#%2
644         push    de
645         ; peephole 32 moved and pushed arguments e and #%2 through de instead of pushing them individually.
646         call    %3
647 }
648
649 replace restart {
650         ld      a,%1
651         sub     a,%2
652         jp      %3,%4
653         ld      a,%1
654 } by {
655         ld      a,%1
656         cp      a,%2
657         jp      %3,%4
658         ; peephole 33 removed load by replacing sub with cp
659         assert  a=%1
660 } if notVolatile(%1)
661
662 replace restart {
663         assert  a=%1
664         sub     a,%2
665         jp      %3,%4
666         ld      a,%1
667 } by {
668         cp      a,#%2
669         jp      %3,%4
670         ; peephole 34 removed load by replacing sub with cp
671         assert  a=%1
672 }
673
674 replace restart {
675         assert  a=%1
676 } by {
677 }
678
679 replace restart {
680         sub     a,#0xFF
681         jp      Z,%1
682 } by {
683         inc     a
684         ; peephole 35 replaced sub a,#0xFF by inc a.
685         jp      Z,%1
686 }
687
688 replace restart {
689         sub     a,#0xFF
690         jp      NZ,%1
691 } by {
692         inc     a
693         ; peephole 36 replaced sub a,#0xFF by inc a.
694         jp      NZ,%1
695 }
696
697 replace restart {
698         ld      bc,#%1 + %2
699         ld      a,c
700         add     a,%3
701         ld      c,a
702         ld      a,b
703         adc     a,%4
704         ld      b,a
705 } by {
706         ld      a,#<(%1 + %2)
707         add     a,%3
708         ld      c,a
709         ld      a,#>(%1 + %2)
710         ; peephole 37 directly used (%1 + %2) in calculation instead of placing it in bc first.
711         adc     a,%4
712         ld      b,a
713 }
714
715 replace restart {
716         ld      de,#%1 + %2
717         ld      a,e
718         add     a,%3
719         ld      e,a
720         ld      a,d
721         adc     a,%4
722         ld      d,a
723 } by {
724         ld      a,#<(%1 + %2)
725         add     a,%3
726         ld      e,a
727         ld      a,#>(%1 + %2)
728         ; peephole 38 directly used (%1 + %2) in calculation instead of placing it in de first.
729         adc     a,%4
730         ld      d,a
731 }
732
733 replace restart {
734         rlca
735         ld      a,#0x00
736         rla
737 } by {
738         rlca
739         and     a,#0x01
740         ; peephole 39 replaced zero load, rla by and since rlca writes the same value to carry bit and least significant bit.
741 }
742
743 replace restart {
744         ld      %1,%2
745         push    %1
746         pop     %4
747         ld      %1,%3
748 } by {
749         ld      %4,%2
750         ; peephole 40 moved %2 directly into de instead of going through %1.
751         ld      %1,%3
752 }
753
754 replace restart {
755         add     a,#0x00
756         ld      %2,a
757         ld      a,%3
758         adc     a,%4
759 } by {
760         ; peephole 41 removed lower part of multibyte addition.
761         ld      %2,a
762         ld      a,%3
763         add     a,%4
764 }
765
766 replace restart {
767         ld      %1,a
768         ld      a,%2
769         add     a,%1
770 } by {
771         ; peephole 42 removed loads by exploiting commutativity of addition.
772         add     a,%2
773 } if notVolatile(%1), notUsed(%1), operandsNotRelated(%2 '(bc)' '(de)')
774
775 replace restart {
776         ld      %1 (ix),a
777         ld      a,#%2
778         add     a,%1 (ix)
779 } by {
780         ld      %1 (ix),a
781         ; peephole 42a removed loads by exploiting commutativity of addition.
782         add     a,#%2
783 }
784 // Don't need to check for volatile, since ix is used to access the stack.
785
786 // sdcc does not use the H flag. sla resets it, while add sets it.
787 // To ensure that the state of the H flag is not changed by this
788 // peephole uncomment the add %3, %4 at the end (since it overwrite the H flag).
789 replace restart {
790         ld      %1, a
791         sla     %1
792         ld      a, %2
793         //add   %3, %4
794 } by {
795         add     a, a
796         ; peephole 42b shifts in accumulator insted of %1
797         ld      %1, a
798         ld      a, %2
799         //add   %3, %4
800 }
801
802 replace restart {
803         ld      l,%1 (ix)
804         ld      h,%2 (ix)
805         ld      a,(hl)
806         inc     a
807         ld      l,%1 (ix)
808         ld      h,%2 (ix)
809         ld      (hl),a
810 } by {
811         ld      l,%1 (ix)
812         ld      h,%2 (ix)
813         inc     (hl)
814         ; peephole 42c incremented in (hl) instead of going through a.
815 } if notUsed('a')
816
817 replace restart {
818         ld      l,%1 (ix)
819         ld      h,%2 (ix)
820         ld      a,(hl)
821         dec     a
822         ld      l,%1 (ix)
823         ld      h,%2 (ix)
824         ld      (hl),a
825 } by {
826         ld      l,%1 (ix)
827         ld      h,%2 (ix)
828         dec     (hl)
829         ; peephole 42d decremented in (hl) instead of going through a.
830 } if notUsed('a')
831
832 replace restart {
833         ld      %1,a
834         ld      a,%2
835         add     a,%1
836 } by {
837         ld      %1, a
838         ; peephole 43 removed load by exploiting commutativity of addition.
839         add     a,%2
840 } if operandsNotRelated(%2 '(bc)' '(de)')
841
842 replace restart {
843         ld      c,l
844         ld      b,h
845         ld      hl,#%1
846         add     hl,bc
847 } by {
848         ; peephole 43a removed loads by exploiting commutativity of addition.
849         ld      bc,#%1
850         add     hl,bc
851 } if notUsed('bc')
852
853 replace restart {
854         ld      hl,#%1
855         add     hl,%2
856         ld      bc,#%4
857         add     hl,bc
858 } by {
859         ; peephole 43b removed loads by exploiting commutativity of addition.
860         ld      hl,#%1 + %4
861         add     hl,%2
862 } if notUsed('bc')
863
864 replace restart {
865         ld      c,e
866         ld      b,d
867         ld      hl,#%1
868         add     hl,bc
869 } by {
870         ; peephole 43c removed loads by exploiting commutativity of addition.
871         ld      hl,#%1
872         add     hl,de
873 } if notUsed('bc')
874
875 replace restart {
876         or      a,%1
877         jp      NZ,%2
878         xor     a,a
879         or      a,%3
880 } by {
881         or      a,%1
882         jp      NZ,%2
883         ; peephole 44 removed redundant zeroing of a (which has just been tested to be #0x00).
884         or      a,%3
885 }
886
887 replace restart {
888         or      a,%1
889         jp      NZ,%2
890         ld      %3,#0x00
891 } by {
892         or      a,%1
893         jp      NZ,%2
894         ld      %3,a
895         ; peephole 45 replaced constant #0x00 by a (which has just been tested to be #0x00).
896 }
897
898 replace restart {
899         and     a,%1
900         jp      NZ,%2
901         ld      %3,#0x00
902 } by {
903         and     a,%1
904         jp      NZ,%2
905         ld      %3,a
906         ; peephole 46 replaced constant #0x00 by a (which has just been tested to be #0x00).
907 }
908
909 replace restart {
910         sub     a,%1
911         jp      NZ,%2
912         ld      %3,#0x00
913 } by {
914         sub     a,%1
915         jp      NZ,%2
916         ld      %3,a
917         ; peephole 47 replaced constant #0x00 by a (which has just been tested to be #0x00).
918 }
919
920 replace restart {
921         dec     a
922         jp      NZ,%1
923         ld      %2,#0x00
924 } by {
925         dec     a
926         jp      NZ,%1
927         ld      %2,a
928         ; peephole 48 replaced constant #0x00 by a (which has just been tested to be #0x00).
929 }
930
931 //replace restart {
932 //      or      a,%1
933 //      jp      NZ,%2
934 //      ld      a,%3
935 //      or      a,a
936 //} by {
937 //      or      a,%1
938 //      jp      NZ,%2
939 //      or      a,%3
940 //      ; peephole 49 shortened or using a (which has just been tested to be #0x00).
941 //} if operandsNotSame3(%3 '(bc)' '(de)')
942
943 //replace restart {
944 //      and     a,%1
945 //      jp      NZ,%2
946 //      ld      a,%3
947 //      or      a,a
948 //} by {
949 //      and     a,%1
950 //      jp      NZ,%2
951 //      or      a,%3
952 //      ; peephole 50 shortened or using a (which has just been tested to be #0x00).
953 //} if operandsNotSame3(%3 '(bc)' '(de)')
954
955 replace restart {
956         sub     a,%1
957         jp      NZ,%2
958         ld      a,%3
959         or      a,a
960 } by {
961         sub     a,%1
962         jp      NZ,%2
963         or      a,%3
964         ; peephole 51 shortened or using a (which has just been tested to be #0x00).
965 }
966 //if operandsNotSame3(%3 '(bc)' '(de)')
967
968 replace restart {
969         dec     a
970         jp      NZ,%1
971         ld      a,%2
972         or      a,a
973 } by {
974         dec     a
975         jp      NZ,%1
976         or      a,%2
977         ; peephole 52 shortened or using a (which has just been tested to be #0x00).
978 }
979 //if operandsNotSame3(%2 '(bc)' '(de)')
980
981 replace restart {
982         or      a,%1
983         jp      NZ,%2
984         push    %3
985         ld      %4,#0x00
986 } by {
987         or      a,%1
988         jp      NZ,%2
989         push    %3
990         ld      %4,a
991         ; peephole 53 replaced constant #0x00 by a (which has just been tested to be #0x00).
992 }
993
994 replace restart {
995         and     a,%1
996         jp      NZ,%2
997         push    %3
998         ld      %4,#0x00
999 } by {
1000         sub     a,%1
1001         jp      NZ,%2
1002         push    %3
1003         ld      %4,a
1004         ; peephole 54 replaced constant #0x00 by a (which has just been tested to be #0x00).
1005 }
1006
1007 replace restart {
1008         sub     a,%1
1009         jp      NZ,%2
1010         push    %3
1011         ld      %4,#0x00
1012 } by {
1013         sub     a,%1
1014         jp      NZ,%2
1015         push    %3
1016         ld      %4,a
1017         ; peephole 55 replaced constant #0x00 by a (which has just been tested to be #0x00).
1018 }
1019
1020 replace restart {
1021         dec     a
1022         jp      NZ,%1
1023         push    %2
1024         ld      %3,#0x00
1025 } by {
1026         dec     a
1027         jp      NZ,%1
1028         push    %2
1029         ld      %3,a
1030         ; peephole 56 replaced constant #0x00 by a (which has just been tested to be #0x00).
1031 }
1032
1033 replace restart {
1034         ld      de,#%1 + %2
1035         inc     de
1036 } by {
1037         ld      de,#%1 + %2+1
1038         ; peephole 59 moved increment of de to constant.
1039 }
1040
1041 replace restart {
1042         ld      bc,#%1 + %2
1043         inc     bc
1044 } by {
1045         ld      bc,#%1 + %2+1
1046         ; peephole 62 moved increment of bc to constant.
1047 }
1048
1049 replace restart {
1050         ld      bc,#%1
1051         ld      a,c
1052         add     a,#0x%2
1053         ld      c,a
1054         ld      a,b
1055         adc     a,#0x%3
1056         ld      b,a
1057 } by {
1058         ld      bc,#%1 + 0x%3%2
1059         ; peephole 63 moved addition of constant 0x%3%2 to bc to constant.
1060 }
1061
1062 replace restart {
1063         call    %1
1064         ret
1065 } by {
1066         jp      %1
1067         ; peephole 65 replaced call at end of function by jump.
1068 }
1069
1070 // Callee saves ix.
1071 replace restart {
1072         call    %1
1073         pop     ix
1074         ret
1075 } by {
1076         pop     ix
1077         jp      %1
1078         ; peephole 66 replaced call at end of function by jump moving call beyond pop ix.
1079 }
1080
1081 replace restart {
1082         ld      %1,a
1083         ld      %2,%1
1084         ld      %3,%1
1085 } by {
1086         ; peephole 67 loaded %2, %3 from a instead of %1.
1087         ld      %1,a
1088         ld      %2,a
1089         ld      %3,a
1090 } if notVolatile(%1)
1091
1092 replace restart {
1093         ld      %1,a
1094         ld      %2,a
1095         ld      %3,%1
1096 } by {
1097         ld      %1,a
1098         ld      %2,a
1099         ; peephole 68 loaded %3 from a instead of %1.
1100         ld      %3,a
1101 } if notVolatile(%1)
1102
1103 replace restart {
1104         ld      %1,l
1105         xor     a,a
1106         or      a,%1
1107 } by {  
1108         ld      %1,l
1109         xor     a,a
1110         ; peephole 69 used l in or instead of %1.
1111         or      a,l
1112 } if notVolatile(%1)
1113
1114 replace restart {
1115         ld      %1,#%2
1116         ld      %3,%4
1117         ld      %1,#%2
1118 } by {
1119         ld      %1,#%2
1120         ld      %3,%4
1121         ; peephole 70 removed load of #%2 into %1 since it's still there.
1122 } if notVolatile(%1), operandsNotRelated(%3 %1)
1123
1124 replace restart {
1125         ld      hl,#%1
1126         ld      de,#%1
1127 } by {
1128         ; peephole 70a used #%1 from hl for load into de.
1129         ld      hl,#%1
1130         ld      e,l
1131         ld      d,h
1132 }
1133
1134 replace restart {
1135         ld      hl,#%1
1136         push    hl
1137         ld      l,e
1138         ld      h,d
1139         jp      (hl)
1140 %1:
1141 } by {
1142         ; peephole 71 used ex to get de into hl.
1143         ex      de,hl
1144         ld      de,#%1
1145         push    de
1146         jp      (hl)
1147 %1:
1148 }
1149 // Lets' hope this is never applied to a jump table. It's fine for calls.
1150
1151 // Should be after 0z.
1152 replace restart {
1153         ld      %1 (ix),l
1154         ld      %2 (ix),h
1155         ld      %3,%1 (ix)
1156         ld      %4,%2 (ix)
1157 } by {  
1158         ld      %1 (ix),l
1159         ld      %2 (ix),h
1160         ; peephole 72 used hl instead of %2 (ix), %1 (ix) to load %4%3.
1161         ld      %3,l
1162         ld      %4,h
1163 } if operandsNotRelated('h' %3)
1164 // Don't check for volatile since ix points to the stack.
1165
1166 replace restart {
1167         ld      %1, a
1168         ld      a, %2 (%3)
1169         adc     a, #%4
1170         ld      l, %1
1171 } by {
1172         ld      l, a
1173         ld      a, %2 (%3)
1174         adc     a, #%4
1175         ; peephole 76 loaded l from a directly instead of going through %1.
1176 } if notUsed(%1)
1177
1178 replace restart {
1179         ld      %1, a
1180         ld      a, #%2
1181         adc     a, #%3
1182         ld      l, %1
1183 } by {
1184         ld      l, a
1185         ld      a, #%2
1186         adc     a, #%3
1187         ; peephole 77 loaded l from a directly instead of going through %1.
1188 } if notUsed(%1)
1189
1190 replace restart {
1191         ld      hl, #%1
1192         add     hl, %2
1193         ex      de, hl
1194         ld      hl, #%3
1195         add     hl, de
1196 } by {
1197         ld      hl, #%1+%3
1198         add     hl, %2
1199         ; peephole 78 removed addition and loads exploiting commutativity of addition.
1200 } if notUsed('de')
1201
1202 // These ex-generating rules should be among the last ones since ex counts as a read from both hl and de for notUsed().
1203 replace restart {
1204         ld      d,h
1205         ld      e,l
1206 } by {
1207         ; peephole 80 used ex to load hl into de.
1208         ex      de,hl
1209 } if notUsed('hl')
1210
1211 replace restart {
1212         ld      e,l
1213         ld      d,h
1214 } by {
1215         ; peephole 81 used ex to load hl into de.
1216         ex      de,hl
1217 } if notUsed('hl')
1218
1219 replace restart {
1220         ld      l,e
1221         ld      h,d
1222 } by {
1223         ; peephole 82 used ex to load de into hl.
1224         ex      de,hl
1225 } if notUsed('de')
1226
1227 // peeph-z80.def - Z80 peephole rules
1228 //
1229 //
1230 // (c) Philipp Klaus Krause (pkk@spth.de, philipp@colecovision.eu) 2006 - 2007
1231 //
1232 // This program is free software; you can redistribute it and/or modify it
1233 // under the terms of the GNU General Public License as published by the
1234 // Free Software Foundation; either version 2, or (at your option) any
1235 // later version.
1236 //
1237 // This program is distributed in the hope that it will be useful,
1238 // but WITHOUT ANY WARRANTY; without even the implied warranty of
1239 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1240 // GNU General Public License for more details.
1241 //
1242 // You should have received a copy of the GNU General Public License
1243 // along with this program; if not, write to the Free Software
1244 // Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1245
1246 replace restart {
1247         ld      %1,#%2
1248         ld      a,%3 (%1)
1249         ld      %4,a
1250         ld      %1,#%5
1251 } by {
1252         ld      a,(#%2 + %3)
1253         ; peephole z1 used #%2 directly instead of going through %1 using indirect addressing.
1254         ld      %4,a
1255         ld      %1,#%5
1256 }
1257
1258 replace restart {
1259         ld      %1,#%2
1260         ld      %3 (%1),a
1261 %4:
1262         ld      %1,%5
1263 } by {
1264         ld      (#%2 + %3),a
1265         ; peephole z2 directly used #%2 instead of going through %1 using indirect addressing.
1266 %4:
1267         ld      %1,%5
1268 }
1269
1270 replace restart {
1271         pop     af
1272         ld      %1,#%2
1273         ld      %3 (%1),%4
1274         ld      %1,#%5
1275 } by {
1276         ld      a,%4
1277         ld      (#%2 + %3),a
1278         ; peephole z3 used #%2 directly instead of going through %1 using indirect addressing.
1279         pop     af
1280         ld      %1,#%5
1281 } if operandsNotRelated(%3 'a')
1282
1283 replace restart {
1284         ld      bc,#%1 + %2
1285         ld      a,%3
1286         ld      (bc),a
1287 } by {
1288         ld      a,%3
1289         ld      (#%1 + %2),a
1290         ; peephole z4 directly used address #%1 + %2 instead of placing it in bc first.
1291 } if notUsed('bc')
1292
1293 replace restart {
1294         ld      bc,#%1 + %2 + %6
1295         ld      a,%3
1296         ld      (bc),a
1297 } by {
1298         ld      a,%3
1299         ld      (#%1 + %2 + %6),a
1300         ; peephole z5 directly used address #%1 + %2 + %6 instead of placing it in bc first.
1301 } if notUsed('bc')
1302
1303 replace restart {
1304         ld      c,%1
1305         ld      l,c
1306         ret
1307 } by {
1308         ld      l,%1
1309         ; peephole z8 moved %1 directly into l instead of going through c.
1310         ret
1311 }
1312
1313 replace restart {
1314         ld      b,h
1315         ld      c,l
1316         pop     af
1317         push    bc
1318         call    %1
1319 } by {
1320         ex      (sp),hl
1321         ; peephole z9 moved hl directly to the stack instead of going through bc.
1322         call    %1
1323 }
1324
1325 replace restart {
1326         ld      d,h
1327         ld      e,l
1328         pop     af
1329         push    de
1330         call    %1
1331 } by {
1332         ex      (sp),hl
1333         ; peephole z10 moved hl directly to the stack instead of going through de.
1334         call    %1
1335 }
1336
1337 replace restart {
1338         jp      %5
1339 } by {
1340         ret
1341         ; peephole z11 replaced jump by return.
1342 } if labelIsReturnOnly(), labelRefCountChange(%5 -1)
1343
1344 replace restart {
1345         jp      %1,%5
1346 } by {
1347         ret     %1
1348         ; peephole z11a replaced jump by return.
1349 } if labelIsReturnOnly(), labelRefCountChange(%5 -1)
1350
1351 // Should be one of the last ones. Opens the code to further peephole optimization.
1352 replace restart {
1353 %1:
1354 } by {
1355         ; peephole z12 removed unused label %1.
1356 } if labelRefCount(%1 0)
1357
1358 // Applying z11 or z11a followed by z12 will often leave a dead ret at the end of the function. Remove it.
1359 replace {
1360         jp      %5
1361         ret
1362 } by {
1363         jp      %5
1364         ; peephole z13 removed unused ret.
1365 }
1366
1367 // These four need two be here since the peephole optimizer continues to apply rules further down the file even for replace restart rules.
1368 replace restart {
1369         jp      NC,%1
1370         jp      %2
1371 %1:
1372 } by {
1373         jp      C,%2
1374         ; peephole 5' removed jp by using inverse jump logic
1375 %1:
1376 } if labelRefCountChange(%1 -1)
1377
1378 replace restart {
1379         jp      C,%1
1380         jp      %2
1381 %1:
1382 } by {
1383         jp      NC,%2
1384         ; peephole 5' removed jp by using inverse jump logic
1385 %1:
1386 } if labelRefCountChange(%1 -1)
1387
1388 replace restart {
1389         jp      NZ,%1
1390         jp      %2
1391 %1:
1392 } by {
1393         jp      Z,%2
1394         ; peephole 5' removed jp by using inverse jump logic
1395 %1:
1396 } if labelRefCountChange(%1 -1)
1397
1398 replace restart {
1399         jp      Z,%1
1400         jp      %2
1401 %1:
1402 } by {
1403         jp      NZ,%2
1404         ; peephole 6' removed jp by using inverse jump logic
1405 %1:
1406 } if labelRefCountChange(%1 -1)
1407
1408 // These should be the last rules, so that the peepholes above need to look at jp only.
1409 replace {
1410         jp      %5
1411 } by {
1412         jr      %5
1413         ; peephole z14 changed absolute to relative unconditional jump.
1414 } if labelInRange()
1415
1416 replace {
1417         jp      Z,%5
1418 } by {
1419         jr      Z,%5
1420         ; peephole z15 changed absolute to relative conditional jump.
1421 } if labelInRange()
1422
1423 replace {
1424         jp      NZ,%5
1425 } by {
1426         jr      NZ,%5
1427         ; peephole z16 changed absolute to relative conditional jump.
1428 } if labelInRange()
1429
1430 replace {
1431         jp      C,%5
1432 } by {
1433         jr      C,%5
1434         ; peephole z17 changed absolute to relative conditional jump.
1435 } if labelInRange()
1436
1437 replace {
1438         jp      NC,%5
1439 } by {
1440         jr      NC,%5
1441         ; peephole z18 changed absolute to relative conditional jump.
1442 } if labelInRange()