// Due to major changes in the Z80 peepholes the old peepholes from peeph.def have been moved here.
// All new peepholes went into peeph-z80.def. A GBZ80 expert should look into this files and peeph-z80.def
// And move peepholes that are useful and correct for both Z80 and GBZ80 into peeph.def.

// peeph.def - Common Z80 and gbz80 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,%1
} by {
	; peephole 1 removed redundant load.
} if notVolatile(%1)

replace restart {
	jp	NC,%1
	jp	%2
%1:
} by {
	jp	C,%2
	; peephole 3 removed jp by using inverse jump logic
%1:
} if labelRefCountChange(%1 -1)

replace restart {
	jp	C,%1
	jp	%2
%1:
} by {
	jp	NC,%2
	; peephole 4 removed jp by using inverse jump logic
%1:
} if labelRefCountChange(%1 -1)

replace restart {
	jp	NZ,%1
	jp	%2
%1:
} by {
	jp	Z,%2
	; peephole 5 removed jp by using inverse jump logic
%1:
} if labelRefCountChange(%1 -1)

replace restart {
	jp	Z,%1
	jp	%2
%1:
} by {
	jp	NZ,%2
	; peephole 6 removed jp by using inverse jump logic
%1:
} if labelRefCountChange(%1 -1)

replace restart {
	jp	%5
} by {
	jp	%6
	; peephole 7 redirected jump-to-jump at %5 by jump to %6
} if labelIsUncondJump(), labelRefCountChange(%5 -1), labelRefCountChange(%6 +1)

replace restart {
	jp	%1,%5
} by {
	jp	%1,%6
	; peephole 8 redirected jump-to-jump at %5 by jump to %6
} if labelIsUncondJump(), labelRefCountChange(%5 -1), labelRefCountChange(%6 +1)

replace restart {
	ld	%2,%3
	jp	%4
%5:
	ld	%2,%3
%4:
} by {
	; peephole 9 removed jump and redundant load.
%5:
	ld	%2,%3
%4:
} if labelRefCountChange(%4 -1)

replace restart {
	xor	a,a
	ld	a,#0x00
} by {
	xor	a,a
	; peephole 10 removed redundant load of 0 into a.
}

replace {
	ld	e,#0x%1
	ld	d,#0x%2
} by {
	ld	de,#0x%2%1
	; peephole 11 combined constant loads into register pair.
}

replace {
	ld	l,#0x%1
	ld	h,#0x%2
} by {
	ld	hl,#0x%2%1
	; peephole 12 combined constant loads into register pair.
}

replace {
	ld	c,#0x%1
	ld	b,#0x%2
} by {
	ld	bc,#0x%2%1
	; peephole 13 combined constant loads into register pair.
}

replace restart {
	ld	%1,a
	ld	a,%1
} by {
	ld	%1,a
	; peephole 14 removed redundant load from %1 into a.
} if notVolatile(%1)
// This gives many false negatives and without the test no problems are encountered in the regression tests
// Maybe we can try this after 2.7.0 release

replace restart {
	ld	a,%1
	ld	%1,a
} by {
	ld	a,%1
	; peephole 15 removed redundant load from a into %1.
} if notVolatile(%1)
// This gives many false negatives and without the test no problems are encountered in the regression tests
// Maybe we can try this after 2.7.0 release

replace restart {
	ld	%2,%3
	ld	a,%2
	and	a,%1
	ld	%2,%4
} by {
	ld	a,%3
	; peephole 16 moved %3 directly into a instead of going through %2.
	and	a,%1
	ld	%2,%4
} if notVolatile(%2), operandsNotSame

replace restart {
	ld	%1,a
	ld	a,%2
	or	a,%1
} by {
	ld	%1,a
	or	a,%2
	; peephole 17 removed load by reordering or arguments.
} if notVolatile(%1)

replace restart {
	ld	%1,a
	xor	a,a
	or	a,%1
} by {
	ld	%1,a
	or	a,a
	; peephole 18 used value still in a instead of loading it from %1.
}

replace restart {
	or	a,%1
	or	a,a
} by {
	or	a,%1
	; peephole 19 removed redundant or after or.
}

replace restart {
	and	a,%1
	or	a,a
} by {
	and	a,%1
	; peephole 20 removed redundant or after and.
}

replace restart {
	xor	a,%1
	or	a,a
} by {
	xor	a,%1
	; peephole 21 removed redundant or after xor.
}

replace restart {
	ld	%1,a
	and	a,%2
	ld	%1,a
} by {
	; peephole 22 removed redundant load into %1.
	and	a,%2
	ld	%1,a
} if notVolatile(%1)

replace {
	ld	%1,%2
	ld	a,%2
} by {
	ld	a,%2
	ld	%1,a
	; peephole 23 load value in a first and use it next
} if notVolatile(%1 %2)

replace restart {
	ld	%1,%2
	ld	%3,%4
	ld	%2,%1
	ld	%4,%3
} by {
	ld	%1,%2
	ld	%3,%4
	; peephole 24 removed redundant load from %3%1 into %4%2
} if notVolatile(%1 %2 %3 %4)

replace restart {
	ld	b,%1
	ld	a,b
	pop	bc
} by {
	ld	a,%1
	; peephole 25 removed load into b
	pop	bc
}

replace restart {
	ld	c,%1
	ld	a,c
	pop	bc
} by {
	ld	a,%1
	; peephole 26 removed load into c
	pop	bc
}

replace restart {
	ld	d,%1
	ld	a,d
	pop	de
} by {
	ld	a,%1
	; peephole 27 removed load into d
	pop	de
}

replace restart {
	ld	e,%1
	ld	a,e
	pop	de
} by {
	ld	a,%1
	; peephole 28 removed load into e
	pop	de
}

replace restart {
	ld	h,%1
	ld	a,h
	pop	hl
} by {
	ld	a,%1
	; peephole 29 removed load into h
	pop	hl
}

replace restart {
	ld	l,%1
	ld	a,l
	pop	hl
} by {
	ld	a,%1
	; peephole 30 removed load into l
	pop	hl
}

replace restart {
	ld	a,c
	push	af
	inc	sp
	ld	a,#%2
	push	af
	inc	sp
	call	%3
} by {
	ld	b,c
	ld	c,#%2
	push	bc
	; peephole 31 moved and pushed arguments c and #%2 through bc instead of pushing them individually.
	call	%3
}

replace restart {
	ld	a,e
	push	af
	inc	sp
	ld	a,#%2
	push	af
	inc	sp
	call	%3
} by {
	ld	d,e
	ld	e,#%2
	push	de
	; peephole 32 moved and pushed arguments e and #%2 through de instead of pushing them individually.
	call	%3
}

replace restart {
	ld	a,%1
	sub	a,%2
	jp	%3,%4
	ld	a,%1
} by {
	ld	a,%1
	cp	a,%2
	jp	%3,%4
	; peephole 33 removed load by replacing sub with cp
	assert	a=%1
} if notVolatile(%1)

replace restart {
	assert	a=%1
	sub	a,%2
	jp	%3,%4
	ld	a,%1
} by {
	cp	a,#%2
	jp	%3,%4
	; peephole 34 removed load by replacing sub with cp
	assert	a=%1
}

replace restart {
	assert	a=%1
} by {
}

replace restart {
	sub	a,#0xFF
	jp	Z,%1
} by {
	inc	a
	; peephole 35 replaced sub a,#0xFF by inc a.
	jp	Z,%1
}

replace restart {
	sub	a,#0xFF
	jp	NZ,%1
} by {
	inc	a
	; peephole 36 replaced sub a,#0xFF by inc a.
	jp	NZ,%1
}

replace restart {
	ld	bc,#%1 + %2
	ld	a,c
	add	a,%3
	ld	c,a
	ld	a,b
	adc	a,%4
	ld	b,a
} by {
	ld	a,#<(%1 + %2)
	add	a,%3
	ld	c,a
	ld	a,#>(%1 + %2)
	; peephole 37 directly used (%1 + %2) in calculation instead of placing it in bc first.
	adc	a,%4
	ld	b,a
}

replace restart {
	ld	de,#%1 + %2
	ld	a,e
	add	a,%3
	ld	e,a
	ld	a,d
	adc	a,%4
	ld	d,a
} by {
	ld	a,#<(%1 + %2)
	add	a,%3
	ld	e,a
	ld	a,#>(%1 + %2)
	; peephole 38 directly used (%1 + %2) in calculation instead of placing it in de first.
	adc	a,%4
	ld	d,a
}

replace restart {
	rlca
	ld	a,#0x00
	rla
} by {
	rlca
	and	a,#0x01
	; peephole 39 replaced zero load, rla by and since rlca writes the same value to carry bit and least significant bit.
}

replace restart {
	ld	%1,%2
	push	%1
	pop	%4
	ld	%1,%3
} by {
	ld	%4,%2
	; peephole 40 moved %2 directly into de instead of going through %1.
	ld	%1,%3
}

replace restart {
	add	a,#0x00
	ld	%2,a
	ld	a,%3
	adc	a,%4
} by {
	; peephole 41 removed lower part of multibyte addition.
	ld	%2,a
	ld	a,%3
	add	a,%4
}

replace restart {
	ld	%1,a
	ld	a,%2
	add	a,%1
	ld	%1,a
} by {
	; peephole 42 removed loads by exploiting commutativity of addition.
	add	a,%2
	ld	%1,a
} if notVolatile(%1)

// sdcc does not use the H flag. sla resets it, while add sets it.
// To ensure that the state of the H flag is not changed by this
// peephole uncomment the add %3, %4 at the end (since it overwrite the H flag).
replace restart {
	ld	%1, a
	sla	%1
	ld	a, %2
	//add	%3, %4
} by {
	add	a, a
	; peephole 42a shifts in accumulator insted of %1
	ld	%1, a
	ld	a, %2
	//add	%3, %4
}

replace restart {
	ld	%1,a
	ld	a,%2
	add	a,%1
} by {
	ld	%1, a
	; peephole 43 removed load by exploiting commutativity of addition.
	add	a,%2
}

replace restart {
	or	a,%1
	jp	NZ,%2
	xor	a,a
	or	a,%3
} by {
	or	a,%1
	jp	NZ,%2
	; peephole 44 removed redundant zeroing of a (which has just been tested to be #0x00).
	or	a,%3
}

replace restart {
	or	a,%1
	jp	NZ,%2
	ld	%3,#0x00
} by {
	or	a,%1
	jp	NZ,%2
	ld	%3,a
	; peephole 45 replaced constant #0x00 by a (which has just been tested to be #0x00).
}

replace restart {
	and	a,%1
	jp	NZ,%2
	ld	%3,#0x00
} by {
	and	a,%1
	jp	NZ,%2
	ld	%3,a
	; peephole 46 replaced constant #0x00 by a (which has just been tested to be #0x00).
}

replace restart {
	sub	a,%1
	jp	NZ,%2
	ld	%3,#0x00
} by {
	sub	a,%1
	jp	NZ,%2
	ld	%3,a
	; peephole 47 replaced constant #0x00 by a (which has just been tested to be #0x00).
}

replace restart {
	dec	a
	jp	NZ,%1
	ld	%2,#0x00
} by {
	dec	a
	jp	NZ,%1
	ld	%2,a
	; peephole 48 replaced constant #0x00 by a (which has just been tested to be #0x00).
}

replace restart {
	or	a,%1
	jp	NZ,%2
	ld	a,%3
	or	a,a
} by {
	or	a,%1
	jp	NZ,%2
	or	a,%3
	; peephole 49 shortened or using a (which has just been tested to be #0x00).
}

replace restart {
	and	a,%1
	jp	NZ,%2
	ld	a,%3
	or	a,a
} by {
	and	a,%1
	jp	NZ,%2
	or	a,%3
	; peephole 50 shortened or using a (which has just been tested to be #0x00).
}

replace restart {
	sub	a,%1
	jp	NZ,%2
	ld	a,%3
	or	a,a
} by {
	sub	a,%1
	jp	NZ,%2
	or	a,%3
	; peephole 51 shortened or using a (which has just been tested to be #0x00).
}

replace restart {
	dec	a
	jp	NZ,%1
	ld	a,%2
	or	a,a
} by {
	dec	a
	jp	NZ,%1
	or	a,%2
	; peephole 52 shortened or using a (which has just been tested to be #0x00).
}

replace restart {
	or	a,%1
	jp	NZ,%2
	push	%3
	ld	%4,#0x00
} by {
	or	a,%1
	jp	NZ,%2
	push	%3
	ld	%4,a
	; peephole 53 replaced constant #0x00 by a (which has just been tested to be #0x00).
}

replace restart {
	and	a,%1
	jp	NZ,%2
	push	%3
	ld	%4,#0x00
} by {
	sub	a,%1
	jp	NZ,%2
	push	%3
	ld	%4,a
	; peephole 54 replaced constant #0x00 by a (which has just been tested to be #0x00).
}

replace restart {
	sub	a,%1
	jp	NZ,%2
	push	%3
	ld	%4,#0x00
} by {
	sub	a,%1
	jp	NZ,%2
	push	%3
	ld	%4,a
	; peephole 55 replaced constant #0x00 by a (which has just been tested to be #0x00).
}

replace restart {
	dec	a
	jp	NZ,%1
	push	%2
	ld	%3,#0x00
} by {
	dec	a
	jp	NZ,%1
	push	%2
	ld	%3,a
	; peephole 56 replaced constant #0x00 by a (which has just been tested to be #0x00).
}

replace restart {
	ld	de,#%1 + %2
	inc	de
	inc	de
	inc	de
} by {
	ld	de,#%1 + %2 + 3
	; peephole 57 moved triple increment of de to constant.
}

replace restart {
	ld	de,#%1 + %2
	inc	de
	inc	de
} by {
	ld	de,#%1 + %2 + 2
	; peephole 58 moved double increment of de to constant.
}

replace restart {
	ld	de,#%1 + %2
	inc	de
} by {
	ld	de,#%1 + %2 + 1
	; peephole 59 moved increment of de to constant.
}

replace restart {
	ld	bc,#%1 + %2
	inc	bc
	inc	bc
	inc	bc
} by {
	ld	bc,#%1 + %2 + 3
	; peephole 60 moved triple increment of bc to constant.
}

replace restart {
	ld	bc,#%1 + %2
	inc	bc
	inc	bc
} by {
	ld	bc,#%1 + %2 + 2
	; peephole 61 moved double increment of bc to constant.
}

replace restart {
	ld	bc,#%1 + %2
	inc	bc
} by {
	ld	bc,#%1 + %2 + 1
	; peephole 62 moved increment of bc to constant.
}

replace restart {
	ld	bc,#%1
	ld	a,c
	add	a,#0x%2
	ld	c,a
	ld	a,b
	adc	a,#0x%3
	ld	b,a
} by {
	ld	bc,#%1 + 0x%3%2
	; peephole 63 moved addition of constant 0x%3%2 to bc to constant.
}

replace restart {
	ld	bc,#%1 + %4
	ld	a,c
	add	a,#0x%2
	ld	c,a
	ld	a,b
	adc	a,#0x%3
	ld	b,a
} by {
	ld	bc,#%1 + %4 + 0x%3%2
	; peephole 64 moved addition of constant 0x%3%2 to bc to constant.
}

replace restart {
	call	%1
	ret
} by {
	jp	%1
	; peephole 65 replaced call at end of function by jump.
}

// Callee saves ix.
replace restart {
	call	%1
	pop	ix
	ret
} by {
	pop	ix
	jp	%1
	; peephole 66 replaced call at end of function by jump moving call beyond pop ix.
}

// Old gbz80 rules from here onward

replace {
	ld	(hl),a
	dec	hl
} by {
	ld	(hl-),a
}
replace {
	ld	(hl),a
	inc	hl
} by {
	ld	(hl+),a
}
replace {
	ld	a,(hl)
	inc	hl
} by {
	ld	a,(hl+)
}
replace {
	ld	a,[hl]
	inc	hl
} by {
	ld	a,[hl+]
}
replace {
	ld	a,[hl]
	inc	hl
} by {
	ld	a,[hl+]
}
replace {
	ld	[hl],a
	inc	hl
} by {
	ld	[hl+],a
}
replace {
	ld	[hl],a
	dec	hl
} by {
	ld	[hl-],a
}
replace {
	ld	(hl+),a
	ld	(hl),d
	dec	hl
	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	ld	a,(de)
} by {
	ld	(hl+),a
	ld	(hl),d
	ld	e,a
	ld	a,(de)
}
replace {
	ld	(hl),a
	ld	%1,(hl)
} by {
	ld	(hl),a
	ld	%1,a
}
replace {
	ld	(hl),a
	inc	de
	ld	a,(de)
	inc	hl
} by {
	ld	(hl+),a
	inc	de
	ld	a,(de)
}
