// 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.

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 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 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 {
	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 restart {
	ld	bc,#%1 + %2 + %6
	ld	a,%3
	ld	(bc),a
	ld	bc,#%4 + %5
} by {
	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 {
	ld	bc,#%1 + %2
	ld	a,%3
	ld	(bc),a
%7:
	ld	bc,#%4 + %5
} by {
	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	bc,#%1 + %2 + %6
	ld	a,%3
	ld	(bc),a
%7:
	ld	bc,#%4 + %5
} by {
	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
	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	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 {
	jp	%5
} by {
	ret
	; peephole z11 replaced jump by return.
} if labelIsReturnOnly(), labelRefCountChange(%5 -1)

replace restart {
	jp	%1,%5
} by {
	ret	%1
	; peephole z12 replaced jump by return.
} if labelIsReturnOnly(), labelRefCountChange(%5 -1)

// Should be one of the last ones. Opens the code to further peephole optimization.
replace restart {
%1:
} by {
	; peephole z13 removed unused label %1.
} if labelRefCount(%1 0)

// 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 conditional 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()
