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