* src/SDCCcse.c (algebraicOpts): fixed bug 1579949
[fw/sdcc] / src / z80 / peeph-z80.def
index 948531d9b19fbd006dddd7359bd306a08ccedf71..bb740d2a5a4e0db04d5bb2db8d18f6204097b352 100644 (file)
+// peeph-z80.def - Z80 peephole rules
+//
+//
+// (c) Philipp Klaus Krause (pkk@spth.de, philipp@colecovision.eu) 2006 - 2007
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option) any
+// later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+// This can't go into peeph.def since %1 could be (hl+) on gbz80.
 replace restart {
-       ld      a,%1(%2)
-       bit     %3,a
-       jp      %4,%5
-} by {
-       bit     %3,%1(%2)
-       jp      %4,%5
-}
-replace {
+       ld      %1,%3
        ld      %1,%2
-       ld      a,%2
 } by {
+       ; peephole z0 removed dead load into %1
        ld      %1,%2
-       ld      a,%1
+} if notVolatile(%1 %3), operandsNotSame
+
+replace restart {
+       ld      %1,#%2
+       ld      a,0(%1)
+       ld      %3,a
+       ld      %1,#%5
+} by {
+       ld      a,(#%2)
+       ; peephole z1 used #%2 directly instead of going through %1 using indirect addressing.
+       ld      %3,a
+       ld      %1,#%5
 }
-replace {
-       ld      %1,a
-       xor     a,a
-       or      a,%1
-       jp      z,%2
-} by {
-       ld      %1,a
-       or      a,a
-       jp      z,%2
+
+replace restart {
+       ld      %1,#%2
+       ld      0(%1),a
+%4:
+       ld      %1,%5
+} by {
+       ld      (#%2),a
+       ; peephole z2 directly used #%2 instead of going through %1 using indirect addressing.
+%4:
+       ld      %1,%5
 }
-replace {
-       rlca
-       ld      a,#0x00
-       rla
+
+replace restart {
+       pop     af
+       ld      %1,#%2
+       ld      0(%1),%3
+       ld      %1,#%4
+} by {
+       ld      a,%3
+       ld      (#%2),a
+       ; peephole z3 used #%2 directly instead of going through %1 using indirect addressing.
+       pop     af
+       ld      %1,#%4
+} if operandsNotRelated(%3 'a')
+
+replace restart {
+       ld      bc,#%1 + %2
+       ld      a,%3
+       ld      (bc),a
+       ld      bc,#%4 + %5
 } by {
-       rlca
-       and     a,#0x01
+       ld      a,%3
+       ld      (#%1 + %2),a
+       ; peephole z4 directly used address #%1 + %2 instead of placing it in bc first.
+       ld      bc,#%4 + %5
 }
-replace {
-       ld      %3,a
-       ld      l,%1
-       ld      h,%2
-       ld      l,(hl)
+
+replace restart {
+       ld      bc,#%1 + %2 + %6
        ld      a,%3
+       ld      (bc),a
+       ld      bc,#%4 + %5
 } by {
-       ld      %3,a
-       ld      l,%1
-       ld      h,%2
-       ld      l,(hl)
-} if notVolatile %3
+       ld      a,%3
+       ld      (#%1 + %2 + %6),a
+       ; peephole z5 directly used address #%1 + %2 + %6 instead of placing it in bc first.
+       ld      bc,#%4 + %5
+}
 
-;
-;--------------------------
-;
 replace restart {
-       pop     %1
-       push    %1
-       ld      %1,%2
+       ld      bc,#%1 + %2
+       ld      a,%3
+       ld      (bc),a
+%7:
+       ld      bc,#%4 + %5
 } by {
-       ;       z80 removed redundant pop/push
-       ld      %1,%2
+       ld      a,%3
+       ld      (#%1 + %2),a
+       ; peephole z6 directly used address #%1 + %2 instead of placing it in bc first.
+%7:
+       ld      bc,#%4 + %5
 }
 
 replace restart {
-       ld      l,a
-       ld      c,%1
-       ld      a,l
+       ld      bc,#%1 + %2 + %6
+       ld      a,%3
+       ld      (bc),a
+%7:
+       ld      bc,#%4 + %5
 } by {
-       ld      l,a
+       ld      a,%3
+       ld      (#%1 + %2 + %6),a
+       ; peephole z7 directly used address #%1 + %2 + %6 instead of placing it in bc first.
+%7:
+       ld      bc,#%4 + %5
+}
+
+replace restart {
        ld      c,%1
+       ld      l,c
+       ret
+} by {
+       ld      l,%1
+       ; peephole z8 moved %1 directly into l instead of going through c.
+       ret
 }
 
 replace restart {
+       ld      b,h
        ld      c,l
-       ld      a,c
-       and     a,#%1
-       ld      c,a
-       or      a,a
-} by {
-       ;       z80 stream lining 'and' logic
-       ld      a,#%1
-       and     a,l
-       ld      c,a
+       pop     af
+       push    bc
+       call    %1
+} by {
+       ex      (sp),hl
+       ; peephole z9 moved hl directly to the stack instead of going through bc.
+       call    %1
 }
 
 replace restart {
-       ld      a,c
-       and     a,#%1
-       ld      c,a
-       or      a,a
-} by {
-       ;       z80 stream lining 'and' logic
-       ld      a,#%1
-       and     a,c
-       ld      c,a
+       ld      d,h
+       ld      e,l
+       pop     af
+       push    de
+       call    %1
+} by {
+       ex      (sp),hl
+       ; peephole z10 moved hl directly to the stack instead of going through de.
+       call    %1
 }
 
 replace restart {
-       ld      a,c
-       or      a,#%1
-       ld      c,a
-} by {
-       ;       z80 stream lining 'or' logic
-       ld      a,#%1
-       or      a,c
-       ld      c,a
-}
+       jp      %5
+} by {
+       ret
+       ; peephole z11 replaced jump by return.
+} if labelIsReturnOnly(), labelRefCountChange(%5 -1)
 
+replace restart {
+       jp      %1,%5
+} by {
+       ret     %1
+       ; peephole z11a replaced jump by return.
+} if labelIsReturnOnly(), labelRefCountChange(%5 -1)
 
-replace {
+// Should be one of the last ones. Opens the code to further peephole optimization.
+replace restart {
 %1:
-       in0     a,(%2)
-       and     a,#%3
-       jp      z,%4
-%5:
-       jp      %6
-%4:
-       call    %7
-       jp      %1
-%6:
-       ret
 } by {
-%1:
-       in0     a,(%2)
-       and     a,#%3
-       jp      nz,%5
-%4:
-       call    %7
-       jp      %1
-%5:
-%6:
+       ; peephole z12 removed unused label %1.
+} if labelRefCount(%1 0)
+
+// Applying z11 or z11a followed by z12 will often leave a dead ret at the end of the function. Remove it.
+replace {
+       jp      %5
        ret
+} by {
+       jp      %5
+       ; peephole z13 removed unused ret.
 }
 
+// These should be the last rules, so that the peepholes above need to look at jp only.
+replace {
+       jp      %5
+} by {
+       jr      %5
+       ; peephole z14 changed absolute to relative unconditional jump.
+} if labelInRange()
 
+replace {
+       jp      Z,%5
+} by {
+       jr      Z,%5
+       ; peephole z15 changed absolute to relative conditional jump.
+} if labelInRange()
+
+replace {
+       jp      NZ,%5
+} by {
+       jr      NZ,%5
+       ; peephole z16 changed absolute to relative conditional jump.
+} if labelInRange()
+
+replace {
+       jp      C,%5
+} by {
+       jr      C,%5
+       ; peephole z17 changed absolute to relative conditional jump.
+} if labelInRange()
+
+replace {
+       jp      NC,%5
+} by {
+       jr      NC,%5
+       ; peephole z18 changed absolute to relative conditional jump.
+} if labelInRange()