Minor peephole 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      %1,a
804         ld      a,%2
805         add     a,%1
806 } by {
807         ld      %1, a
808         ; peephole 43 removed load by exploiting commutativity of addition.
809         add     a,%2
810 } if operandsNotRelated(%2 '(bc)' '(de)')
811
812 replace restart {
813         ld      c,l
814         ld      b,h
815         ld      hl,#%1
816         add     hl,bc
817 } by {
818         ; peephole 43a removed loads by exploiting commutativity of addition.
819         ld      bc,#%1
820         add     hl,bc
821 } if notUsed('bc')
822
823 replace restart {
824         ld      hl,#%1
825         add     hl,%2
826         ld      bc,#%4
827         add     hl,bc
828 } by {
829         ; peephole 43b removed loads by exploiting commutativity of addition.
830         ld      hl,#%1 + %4
831         add     hl,%2
832 } if notUsed('bc')
833
834 replace restart {
835         ld      c,e
836         ld      b,d
837         ld      hl,#%1
838         add     hl,bc
839 } by {
840         ; peephole 43c removed loads by exploiting commutativity of addition.
841         ld      hl,#%1
842         add     hl,de
843 } if notUsed('bc')
844
845 replace restart {
846         or      a,%1
847         jp      NZ,%2
848         xor     a,a
849         or      a,%3
850 } by {
851         or      a,%1
852         jp      NZ,%2
853         ; peephole 44 removed redundant zeroing of a (which has just been tested to be #0x00).
854         or      a,%3
855 }
856
857 replace restart {
858         or      a,%1
859         jp      NZ,%2
860         ld      %3,#0x00
861 } by {
862         or      a,%1
863         jp      NZ,%2
864         ld      %3,a
865         ; peephole 45 replaced constant #0x00 by a (which has just been tested to be #0x00).
866 }
867
868 replace restart {
869         and     a,%1
870         jp      NZ,%2
871         ld      %3,#0x00
872 } by {
873         and     a,%1
874         jp      NZ,%2
875         ld      %3,a
876         ; peephole 46 replaced constant #0x00 by a (which has just been tested to be #0x00).
877 }
878
879 replace restart {
880         sub     a,%1
881         jp      NZ,%2
882         ld      %3,#0x00
883 } by {
884         sub     a,%1
885         jp      NZ,%2
886         ld      %3,a
887         ; peephole 47 replaced constant #0x00 by a (which has just been tested to be #0x00).
888 }
889
890 replace restart {
891         dec     a
892         jp      NZ,%1
893         ld      %2,#0x00
894 } by {
895         dec     a
896         jp      NZ,%1
897         ld      %2,a
898         ; peephole 48 replaced constant #0x00 by a (which has just been tested to be #0x00).
899 }
900
901 //replace restart {
902 //      or      a,%1
903 //      jp      NZ,%2
904 //      ld      a,%3
905 //      or      a,a
906 //} by {
907 //      or      a,%1
908 //      jp      NZ,%2
909 //      or      a,%3
910 //      ; peephole 49 shortened or using a (which has just been tested to be #0x00).
911 //} if operandsNotSame3(%3 '(bc)' '(de)')
912
913 //replace restart {
914 //      and     a,%1
915 //      jp      NZ,%2
916 //      ld      a,%3
917 //      or      a,a
918 //} by {
919 //      and     a,%1
920 //      jp      NZ,%2
921 //      or      a,%3
922 //      ; peephole 50 shortened or using a (which has just been tested to be #0x00).
923 //} if operandsNotSame3(%3 '(bc)' '(de)')
924
925 replace restart {
926         sub     a,%1
927         jp      NZ,%2
928         ld      a,%3
929         or      a,a
930 } by {
931         sub     a,%1
932         jp      NZ,%2
933         or      a,%3
934         ; peephole 51 shortened or using a (which has just been tested to be #0x00).
935 }
936 //if operandsNotSame3(%3 '(bc)' '(de)')
937
938 replace restart {
939         dec     a
940         jp      NZ,%1
941         ld      a,%2
942         or      a,a
943 } by {
944         dec     a
945         jp      NZ,%1
946         or      a,%2
947         ; peephole 52 shortened or using a (which has just been tested to be #0x00).
948 }
949 //if operandsNotSame3(%2 '(bc)' '(de)')
950
951 replace restart {
952         or      a,%1
953         jp      NZ,%2
954         push    %3
955         ld      %4,#0x00
956 } by {
957         or      a,%1
958         jp      NZ,%2
959         push    %3
960         ld      %4,a
961         ; peephole 53 replaced constant #0x00 by a (which has just been tested to be #0x00).
962 }
963
964 replace restart {
965         and     a,%1
966         jp      NZ,%2
967         push    %3
968         ld      %4,#0x00
969 } by {
970         sub     a,%1
971         jp      NZ,%2
972         push    %3
973         ld      %4,a
974         ; peephole 54 replaced constant #0x00 by a (which has just been tested to be #0x00).
975 }
976
977 replace restart {
978         sub     a,%1
979         jp      NZ,%2
980         push    %3
981         ld      %4,#0x00
982 } by {
983         sub     a,%1
984         jp      NZ,%2
985         push    %3
986         ld      %4,a
987         ; peephole 55 replaced constant #0x00 by a (which has just been tested to be #0x00).
988 }
989
990 replace restart {
991         dec     a
992         jp      NZ,%1
993         push    %2
994         ld      %3,#0x00
995 } by {
996         dec     a
997         jp      NZ,%1
998         push    %2
999         ld      %3,a
1000         ; peephole 56 replaced constant #0x00 by a (which has just been tested to be #0x00).
1001 }
1002
1003 replace restart {
1004         ld      de,#%1 + %2
1005         inc     de
1006 } by {
1007         ld      de,#%1 + %2+1
1008         ; peephole 59 moved increment of de to constant.
1009 }
1010
1011 replace restart {
1012         ld      bc,#%1 + %2
1013         inc     bc
1014 } by {
1015         ld      bc,#%1 + %2+1
1016         ; peephole 62 moved increment of bc to constant.
1017 }
1018
1019 replace restart {
1020         ld      bc,#%1
1021         ld      a,c
1022         add     a,#0x%2
1023         ld      c,a
1024         ld      a,b
1025         adc     a,#0x%3
1026         ld      b,a
1027 } by {
1028         ld      bc,#%1 + 0x%3%2
1029         ; peephole 63 moved addition of constant 0x%3%2 to bc to constant.
1030 }
1031
1032 replace restart {
1033         call    %1
1034         ret
1035 } by {
1036         jp      %1
1037         ; peephole 65 replaced call at end of function by jump.
1038 }
1039
1040 // Callee saves ix.
1041 replace restart {
1042         call    %1
1043         pop     ix
1044         ret
1045 } by {
1046         pop     ix
1047         jp      %1
1048         ; peephole 66 replaced call at end of function by jump moving call beyond pop ix.
1049 }
1050
1051 replace restart {
1052         ld      %1,a
1053         ld      %2,%1
1054         ld      %3,%1
1055 } by {
1056         ; peephole 67 loaded %2, %3 from a instead of %1.
1057         ld      %1,a
1058         ld      %2,a
1059         ld      %3,a
1060 } if notVolatile(%1)
1061
1062 replace restart {
1063         ld      %1,a
1064         ld      %2,a
1065         ld      %3,%1
1066 } by {
1067         ld      %1,a
1068         ld      %2,a
1069         ; peephole 68 loaded %3 from a instead of %1.
1070         ld      %3,a
1071 } if notVolatile(%1)
1072
1073 replace restart {
1074         ld      %1,l
1075         xor     a,a
1076         or      a,%1
1077 } by {  
1078         ld      %1,l
1079         xor     a,a
1080         ; peephole 69 used l in or instead of %1.
1081         or      a,l
1082 } if notVolatile(%1)
1083
1084 replace restart {
1085         ld      %1,#%2
1086         ld      %3,%4
1087         ld      %1,#%2
1088 } by {
1089         ld      %1,#%2
1090         ld      %3,%4
1091         ; peephole 70 removed load of #%2 into %1 since it's still there.
1092 } if notVolatile(%1), operandsNotRelated(%3 %1)
1093
1094 replace restart {
1095         ld      hl,#%1
1096         ld      de,#%1
1097 } by {
1098         ; peephole 70a used #%1 from hl for load into de.
1099         ld      hl,#%1
1100         ld      e,l
1101         ld      d,h
1102 }
1103
1104 replace restart {
1105         ld      hl,#%1
1106         push    hl
1107         ld      l,e
1108         ld      h,d
1109         jp      (hl)
1110 %1:
1111 } by {
1112         ; peephole 71 used ex to get de into hl.
1113         ex      de,hl
1114         ld      de,#%1
1115         push    de
1116         jp      (hl)
1117 %1:
1118 }
1119 // Lets' hope this is never applied to a jump table. It's fine for calls.
1120
1121 // Should be after 0z.
1122 replace restart {
1123         ld      %1 (ix),l
1124         ld      %2 (ix),h
1125         ld      %3,%1 (ix)
1126         ld      %4,%2 (ix)
1127 } by {  
1128         ld      %1 (ix),l
1129         ld      %2 (ix),h
1130         ; peephole 72 used hl instead of %2 (ix), %1 (ix) to load %4%3.
1131         ld      %3,l
1132         ld      %4,h
1133 } if operandsNotRelated('h' %3)
1134 // Don't check for volatile since ix points to the stack.
1135
1136 replace restart {
1137         ld      %1, a
1138         ld      a, %2 (%3)
1139         adc     a, #%4
1140         ld      l, %1
1141 } by {
1142         ld      l, a
1143         ld      a, %2 (%3)
1144         adc     a, #%4
1145         ; peephole 76 loaded l from a directly instead of going through %1.
1146 } if notUsed(%1)
1147
1148 replace restart {
1149         ld      %1, a
1150         ld      a, #%2
1151         adc     a, #%3
1152         ld      l, %1
1153 } by {
1154         ld      l, a
1155         ld      a, #%2
1156         adc     a, #%3
1157         ; peephole 77 loaded l from a directly instead of going through %1.
1158 } if notUsed(%1)
1159
1160 replace restart {
1161         ld      hl, #%1
1162         add     hl, %2
1163         ex      de, hl
1164         ld      hl, #%3
1165         add     hl, de
1166 } by {
1167         ld      hl, #%1+%3
1168         add     hl, %2
1169         ; peephole 78 removed addition and loads exploiting commutativity of addition.
1170 } if notUsed('de')
1171
1172 // These ex-generating rules should be among the last ones since ex counts as a read from both hl and de for notUsed().
1173 replace restart {
1174         ld      d,h
1175         ld      e,l
1176 } by {
1177         ; peephole 80 used ex to load hl into de.
1178         ex      de,hl
1179 } if notUsed('hl')
1180
1181 replace restart {
1182         ld      e,l
1183         ld      d,h
1184 } by {
1185         ; peephole 81 used ex to load hl into de.
1186         ex      de,hl
1187 } if notUsed('hl')
1188
1189 replace restart {
1190         ld      l,e
1191         ld      h,d
1192 } by {
1193         ; peephole 82 used ex to load de into hl.
1194         ex      de,hl
1195 } if notUsed('de')
1196
1197 // peeph-z80.def - Z80 peephole rules
1198 //
1199 //
1200 // (c) Philipp Klaus Krause (pkk@spth.de, philipp@colecovision.eu) 2006 - 2007
1201 //
1202 // This program is free software; you can redistribute it and/or modify it
1203 // under the terms of the GNU General Public License as published by the
1204 // Free Software Foundation; either version 2, or (at your option) any
1205 // later version.
1206 //
1207 // This program is distributed in the hope that it will be useful,
1208 // but WITHOUT ANY WARRANTY; without even the implied warranty of
1209 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1210 // GNU General Public License for more details.
1211 //
1212 // You should have received a copy of the GNU General Public License
1213 // along with this program; if not, write to the Free Software
1214 // Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1215
1216 replace restart {
1217         ld      %1,#%2
1218         ld      a,%3 (%1)
1219         ld      %4,a
1220         ld      %1,#%5
1221 } by {
1222         ld      a,(#%2 + %3)
1223         ; peephole z1 used #%2 directly instead of going through %1 using indirect addressing.
1224         ld      %4,a
1225         ld      %1,#%5
1226 }
1227
1228 replace restart {
1229         ld      %1,#%2
1230         ld      %3 (%1),a
1231 %4:
1232         ld      %1,%5
1233 } by {
1234         ld      (#%2 + %3),a
1235         ; peephole z2 directly used #%2 instead of going through %1 using indirect addressing.
1236 %4:
1237         ld      %1,%5
1238 }
1239
1240 replace restart {
1241         pop     af
1242         ld      %1,#%2
1243         ld      %3 (%1),%4
1244         ld      %1,#%5
1245 } by {
1246         ld      a,%4
1247         ld      (#%2 + %3),a
1248         ; peephole z3 used #%2 directly instead of going through %1 using indirect addressing.
1249         pop     af
1250         ld      %1,#%5
1251 } if operandsNotRelated(%3 'a')
1252
1253 replace restart {
1254         ld      bc,#%1 + %2
1255         ld      a,%3
1256         ld      (bc),a
1257 } by {
1258         ld      a,%3
1259         ld      (#%1 + %2),a
1260         ; peephole z4 directly used address #%1 + %2 instead of placing it in bc first.
1261 } if notUsed('bc')
1262
1263 replace restart {
1264         ld      bc,#%1 + %2 + %6
1265         ld      a,%3
1266         ld      (bc),a
1267 } by {
1268         ld      a,%3
1269         ld      (#%1 + %2 + %6),a
1270         ; peephole z5 directly used address #%1 + %2 + %6 instead of placing it in bc first.
1271 } if notUsed('bc')
1272
1273 replace restart {
1274         ld      c,%1
1275         ld      l,c
1276         ret
1277 } by {
1278         ld      l,%1
1279         ; peephole z8 moved %1 directly into l instead of going through c.
1280         ret
1281 }
1282
1283 replace restart {
1284         ld      b,h
1285         ld      c,l
1286         pop     af
1287         push    bc
1288         call    %1
1289 } by {
1290         ex      (sp),hl
1291         ; peephole z9 moved hl directly to the stack instead of going through bc.
1292         call    %1
1293 }
1294
1295 replace restart {
1296         ld      d,h
1297         ld      e,l
1298         pop     af
1299         push    de
1300         call    %1
1301 } by {
1302         ex      (sp),hl
1303         ; peephole z10 moved hl directly to the stack instead of going through de.
1304         call    %1
1305 }
1306
1307 replace restart {
1308         jp      %5
1309 } by {
1310         ret
1311         ; peephole z11 replaced jump by return.
1312 } if labelIsReturnOnly(), labelRefCountChange(%5 -1)
1313
1314 replace restart {
1315         jp      %1,%5
1316 } by {
1317         ret     %1
1318         ; peephole z11a replaced jump by return.
1319 } if labelIsReturnOnly(), labelRefCountChange(%5 -1)
1320
1321 // Should be one of the last ones. Opens the code to further peephole optimization.
1322 replace restart {
1323 %1:
1324 } by {
1325         ; peephole z12 removed unused label %1.
1326 } if labelRefCount(%1 0)
1327
1328 // Applying z11 or z11a followed by z12 will often leave a dead ret at the end of the function. Remove it.
1329 replace {
1330         jp      %5
1331         ret
1332 } by {
1333         jp      %5
1334         ; peephole z13 removed unused ret.
1335 }
1336
1337 // These four need two be here since the peephole optimizer continues to apply rules further down the file even for replace restart rules.
1338 replace restart {
1339         jp      NC,%1
1340         jp      %2
1341 %1:
1342 } by {
1343         jp      C,%2
1344         ; peephole 5' removed jp by using inverse jump logic
1345 %1:
1346 } if labelRefCountChange(%1 -1)
1347
1348 replace restart {
1349         jp      C,%1
1350         jp      %2
1351 %1:
1352 } by {
1353         jp      NC,%2
1354         ; peephole 5' removed jp by using inverse jump logic
1355 %1:
1356 } if labelRefCountChange(%1 -1)
1357
1358 replace restart {
1359         jp      NZ,%1
1360         jp      %2
1361 %1:
1362 } by {
1363         jp      Z,%2
1364         ; peephole 5' removed jp by using inverse jump logic
1365 %1:
1366 } if labelRefCountChange(%1 -1)
1367
1368 replace restart {
1369         jp      Z,%1
1370         jp      %2
1371 %1:
1372 } by {
1373         jp      NZ,%2
1374         ; peephole 6' removed jp by using inverse jump logic
1375 %1:
1376 } if labelRefCountChange(%1 -1)
1377
1378 // These should be the last rules, so that the peepholes above need to look at jp only.
1379 replace {
1380         jp      %5
1381 } by {
1382         jr      %5
1383         ; peephole z14 changed absolute to relative unconditional jump.
1384 } if labelInRange()
1385
1386 replace {
1387         jp      Z,%5
1388 } by {
1389         jr      Z,%5
1390         ; peephole z15 changed absolute to relative conditional jump.
1391 } if labelInRange()
1392
1393 replace {
1394         jp      NZ,%5
1395 } by {
1396         jr      NZ,%5
1397         ; peephole z16 changed absolute to relative conditional jump.
1398 } if labelInRange()
1399
1400 replace {
1401         jp      C,%5
1402 } by {
1403         jr      C,%5
1404         ; peephole z17 changed absolute to relative conditional jump.
1405 } if labelInRange()
1406
1407 replace {
1408         jp      NC,%5
1409 } by {
1410         jr      NC,%5
1411         ; peephole z18 changed absolute to relative conditional jump.
1412 } if labelInRange()