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