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