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