// peeph-r2k.def - Rabbit 2000 (derived from Z80 peephole rules)
//
// Some of these peepholes could be potentially moved to peeph.def, but a
// GBZ80 expert should have a look at them before.
//
// (c) Philipp Klaus Krause (pkk@spth.de, philipp@colecovision.eu) 2006 - 2010
// *** modified by Leland Morrison for rabbit 2000 processor 2011
//
// 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 0 removed redundant load.
} if notVolatile(%1)

replace restart {
	ld	%1, %2
} by {
	; peephole 1 removed dead load from %2 into %1.
} if notVolatile(%1), notUsed(%1)
// Should probably check for notVolatile(%2), too, but gives many false positives and no regression tests fail.

replace restart {
	add	ix,sp
} by {
	; peephole 1a removed dead frame pointer setup.
} if notUsed('ix')

replace restart {
	ld	%1, %2 + %3
} by {
	; peephole 2 removed dead load from %2 + %3 into %1.
} if notVolatile(%1), notUsed(%1)
// Should probably check for notVolatile(%2), too, but gives many false positives and no regression tests fail.

replace restart {
	ld	%1, (iy)
} by {
	ld	%1, 0 (iy)
	; peephole 3 made 0 offset explicit.
}

replace restart {
	ld	(iy), %1
} by {
	ld	0 (iy), %1
	; peephole 4 made 0 offset explicit.
}

replace restart {
	inc	hl
} by {
	; peephole 5 removed dead increment of hl.
} if notUsed('hl')

replace restart {
	dec	hl
} by {
	; peephole 6 removed dead decrement of hl.
} if notUsed('hl')

replace restart {
	ld	%1, %2 (iy)
} by {
	; peephole 7 removed dead load from %2 (iy) into %1.
} if notUsed(%1)
// Should probably check for notVolatile(), but gives many false positives and no regression tests fail.

replace restart {
	ld	%1, %2 (ix)
} by {
	; peephole 8 removed dead load from %2 (ix) into %1.
} if notUsed(%1)

replace restart {
	ld	%1, %2
	ld	%3, %1
} by {
	; peephole 9 loaded %3 from %2 directly instead of going through %1.
	ld	%3, %2
} if canAssign(%3 %2), notVolatile(%1), notUsed(%1)

replace restart {
	ld	%1, %2
	ld	%3, %4
	ld	%5, %1
} by {
	ld	%5, %2
	; peephole 10 loaded %5 from %2 directly instead of going through %1.
	ld	%3, %4
} if canAssign(%5 %2), notVolatile(%1), operandsNotRelated(%1 %4), operandsNotRelated(%1 %3), operandsNotRelated(%4 %5), notUsed(%1), notSame(%3 %4 '(hl)' '(de)' '(bc)'), notVolatile(%5)
// Rule OK unless both %5 and %4 are volatile, but we can't express that directly.

replace restart {
	ld	%1, %2 (%3)
	ld	%4, %1
} by {
	; peephole 11 loaded %2 (%3) into %4 directly instead of going through %1.
	ld	%4, %2 (%3)
} if canAssign(%4 %2 %3), notVolatile(%1), notUsed(%1)

replace restart {
	ld	%1, %2
	ld	%3 (%4), %1
} by {
	; peephole 12 loaded %2 into %3 (%4) directly instead of going through %1.
	ld	%3 (%4), %2
} if canAssign(%3 %4 %2), notVolatile(%1), notUsed(%1)

replace restart {
	ld	%1, %2 (%3)
	ld	%4, %5 (%6)
	ld	%7, %1
} by {
	ld	%7, %2 (%3)
	; peephole 13 loaded %2 (%3) into %7 directly instead of going through %1.
	ld	%4, %5 (%6)
} if canAssign(%7 %2 %3), notVolatile(%1), notUsed(%1), notSame(%1 %4), notSame(%7 %4)

replace restart {
	ld	%1, %7
	ld	%5 (%6), %4
	ld	%2 (%3), %1
} by {
	ld	%5 (%6), %4
	; peephole 14 loaded %7 into %2 (%3) directly instead of going through %1.
	ld	%2 (%3), %7
} if canAssign(%2 %3 %7), notVolatile(%1), notUsed(%1), notSame(%1 %4)

replace restart {
	ld	%1, %2 (%3)
	ld	%4, %5
	ld	%7, %1
} by {
	ld	%7, %2 (%3)
	; peephole 15 loaded %2 (%3) into %7 directly instead of going through %1.
	ld	%4, %5
} if canAssign(%7 %2 %3), notVolatile(%1), notUsed(%1), notSame(%1 %5), notSame(%7 %4), notSame(%7 %5), notSame(%4 '(hl)' '(de)' '(bc)'), notSame(%5 '(hl)' '(de)' '(bc)' '(iy)')

replace restart {
	ld	%1,#%2
	ld	a,%3 (%1)
} by {
	; peephole 16 loaded %2 into a directly instead of going through %1.
	ld	a,(#%2 + %3)
} if notUsed(%1)

replace restart {
	ld	hl,#%1
	ld	a,(hl)
} by {
	ld	a,(#%1)
	; peephole 17 loaded a from (#%1) directly instead of using hl.
} if notUsed('hl')

replace restart {
	ld	hl,#%1 + %2
	ld	a,(hl)
} by {
	; peephole 18 loaded %2 into a directly instead of using hl.
	ld	a,(#%1 + %2)
} if notUsed('hl')

replace restart {
	ld	hl,#%1
	ld	(hl),a
} by {
	ld	(#%1),a
	; peephole 19 loaded (#%1) from a directly instead of using hl.
} if notUsed('hl')

replace restart {
	ld	hl,#%1 + %2
	ld	(hl),a
} by {
	ld	(#%1 + %2),a
	; peephole 20 loaded (#%1) from a directly instead of using hl.
} if notUsed('hl')

replace restart {
	srl	%1
	ld	a,%1
} by {
	ld	a,%1
	; peephole 21 shifted in a instead of %1.
	srl	a
} if notVolatile(%1), notUsed(%1)

replace restart {
	ld	e, l
	ld	d, h
	ld	a, (de)
	srl	a
	ld	(de), a
} by {
	ld	e, l
	ld	d, h
	srl	(hl)
	; peephole 21a shifted in (hl) instead of a.
} if notUsed('a')

replace restart {
	ld	iy, #%1
	ld	%2, %3 (iy)
	srl	%2
	bit %4, %3 (iy)
} by {
	ld	hl, #%1 + %3
	; peephole 21c used hl instead of iy.
	ld	%2, (hl)
	srl %2
	bit %4, (hl)
} if notUsed('iy'), notUsed('hl')

replace restart {
	ld	%1,(hl)
	ld	a,%2 (%3)
	sub	a,%1
} by {
	ld	a,%2 (%3)
	; peephole 22 used (hl) in sub directly instead of going through %1.
	sub	a,(hl)
} if notVolatile(%1), notUsed(%1)

replace restart {
	inc	bc
	ld	l,c
	ld	h,b
} by {
	ld	l,c
	ld	h,b
	; peephole 23 incremented in hl instead of bc.
	inc	hl
} if notUsed('bc')

replace restart {
	inc	de
	ld	l,e
	ld	h,d
} by {
	ld	l,e
	ld	h,d
	; peephole 24 incremented in hl instead of de.
	inc	hl
} if notUsed('de')

replace restart {
	ld	c,l
	ld	b,h
	ld	a,#%1
	ld	(bc),a
} by {
	ld	c,l
	ld	b,h
	ld	(hl),#%1
	; peephole 25 loaded #%1 into (hl) instead of (bc).
}

replace restart {
	ex	de, hl
	push	de
} by {
	; peephole 26 pushed hl directly instead of going through de.
	push	hl
} if notUsed('de'), notUsed('hl')

replace restart {
	ld	l,%1
	ld	h,d
	push	hl
} by {
	; peephole 27 pushed de instead of hl removing a load.
	ld	e,%1
	push	de
} if notUsed('hl'), notUsed('e')

replace restart {
	ex	de, hl
	push	bc
	push	de
} by {
	; peephole 28 pushed hl directly instead of going through de.
	push	bc
	push	hl
} if notUsed('de'), notUsed('hl')

replace restart {
	ld	l,c
	ld	h,b
	push	hl
} by {
	; peephole 29 pushed bc directly instead of going through hl.
	push	bc
} if notUsed('hl')

replace restart {
	ld	l,%1
	ld	h,b
	push	hl
} by {
	; peephole 30 pushed bc instead of hl removing a load.
	ld	c,%1
	push	bc
} if notUsed('hl'), notUsed('c')

replace restart {
	ld	c,l
	ld	b,h
	push	%1
	push	bc
} by {
	; peephole 31 pushed hl directly instead of going through bc.
	push	%1
	push	hl
} if notUsed('bc'), notSame(%1 'bc')

replace restart {
	pop	de
	ld	l, e
	ld	h, d
} by {
	; peephole 32 popped hl directly instead of going through de.
	pop	hl
} if notUsed('de')

replace restart {
	pop	bc
	ld	l, c
	ld	h, b
} by {
	; peephole 33 popped hl directly instead of going through bc.
	pop	hl
} if notUsed('bc')

replace restart {
	ld	%1 (ix), %2
	ld	%3, %1 (ix)
} by {
	; peephole 34 loaded %3 from %2 instead of going through %1 (ix).
	ld	%1 (ix), %2
	ld	%3, %2
}
// Don't need to check for volatile, since ix is used for the stack.

replace restart {
	ld	%1 (ix), a
	push	de
	ld	%2, %1 (ix)
} by {
	ld	%1 (ix), a
	push	de
	; peephole 34a loaded %2 from a instead of %1 (ix)
	ld	%2, a
}	

replace restart {
	push	af
	inc	sp
	ld	a,e
	push	af
	inc	sp
} by {
	; peephole 35 pushed de instead of pushing a twice.
	ld	d,a
	push	de
} if notUsed('d'), notUsed('a')

replace restart {
	push	af
	inc	sp
	ld	a,#%1
	push	af
	inc	sp
} by {
	; peephole 36 pushed de instead of pushing a twice.
	ld	d,a
	ld	e,#%1
	push	de
} if notUsed('de')

replace restart {
	push	af
	inc	sp
	ld	a,#%1
	push	af
	inc	sp
} by {
	; peephole 37 pushed bc instead of pushing a twice.
	ld	b,a
	ld	c,#%1
	push	bc
} if notUsed('bc')

replace restart {
	push	bc
	inc	sp
	push	de
	inc	sp
} by {
	ld	c, d
	; peephole 37a combined pushing of b and d.
	push	bc
} if notUsed('c')

replace restart {
	push	bc
	inc	sp
	ld	a, c
	push	af
	inc	sp
} by {
	push	bc
	ld	a, c
	; peephole 38 simplified pushing bc.
}

replace restart {
	push	de
	inc	sp
	ld	a, #%1
	push	af
	inc	sp
} by {
	ld	e, #%1
	push	de
	; peephole 39 simplified pushing de.
} if notUsed('e')

replace restart {
	ld	a,#%1
	ld	d,a
} by {
	; peephole 40 loaded #%1 into d directly instead of going through a.
	ld	d,#%1
} if notUsed('a')

replace restart {
	ld	%1,a
	ld	%2,%1
} by {
	; peephole 41 loaded %2 from a directly instead of going through %1.
	ld	%2,a
} if notUsed(%1)

replace restart {
	ld	a,%1 (ix)
	push	af
	inc	sp
	ld	a,%2 (ix)
	push	af
	inc	sp
} by {
	; peephole 42 pushed %1 (ix), %2(ix) through hl instead of af.
	ld	h,%1 (ix)
	ld	l,%2 (ix)
	push	hl
} if notUsed('a'), notUsed('hl')

replace restart {
	ld	c, l
	ld	b, h
	push	bc
} by {
	; peephole 43 pushed hl instead of bc.
	push	hl
} if notUsed('bc')

replace restart {
	pop	%1
	push	%1
} by {
	; peephole 44 eleminated dead pop/push pair.
} if notUsed(%1)

replace restart {
	ld	iy,#%1
	or	a,%2 (iy)
} by {
	; peephole 45 used hl instead of iy.
	ld	hl,#%1 + %2
	or	a,(hl)
} if notUsed('iy'), notUsed('hl')

replace restart {
	ld	iy,#%1
	ld	%2,%3 (iy)
} by {
	; peephole 46 used hl instead of iy.
	ld	hl,#%1 + %3
	ld	%2, (hl)
} if notUsed('iy'), notUsed('hl')

replace restart {
	ld	iy,#%1
	ld	h,%3 (iy)
} by {
	; peephole 46a used hl instead of iy.
	ld	hl,#%1 + %3
	ld	h, (hl)
} if notUsed('iy'), notUsed('l')

replace restart {
	ld	iy,#%1
	ld	%2 (iy), %3
} by {
	; peephole 46b used hl instead of iy.
	ld	hl,#%1 + %2
	ld	(hl), %3
} if notUsed('iy'), notUsed('hl'), notSame(%3 'h' 'l')

replace restart {
	ld	iy,#%1
	ld	%2,0 (iy)
	ld	%3,1 (iy)
} by {
	; peephole 47 used hl instead of iy.
	ld	hl,#%1
	ld	%2, (hl)
	inc	hl
	ld	%3, (hl)
} if notUsed('iy'), notUsed('hl'), operandsNotRelated(%2 'hl')

replace restart {
	ld	iy,#%1
	ld	%2 (iy),%3
	ld	l,%2 (iy)
} by {
	; peephole 48 used hl instead of iy.
	ld	hl,#%1 + %2
	ld	(hl),%3
	ld	l,(hl)
} if notUsed('iy'), notUsed('h')

replace restart {
	ld	iy,#%1
	ld	%2 (%3), %4
} by {
	; peephole 49 used hl instead of iy.
	ld	hl,#%1 + %2
	ld	(hl), %4
} if notUsed('iy'), notUsed('hl'), operandsNotRelated(%4 'hl')

replace restart {
	ld	iy,#%1
	bit	%2,%3 (iy)
} by {
	; peephole 49a used hl instead of iy.
	ld	hl,#%1+%3
	bit	%2, (hl)
} if notUsed('iy'), notUsed('hl')

replace restart {
	ld	iy, #%1
	add	iy, sp
	ld	%2, %3 (iy)
} by {
	; peephole 49b used hl instead of iy.
	ld	hl, #%1+%3
	add	hl, sp
	ld	%2, (hl)
} if notUsed('iy'), notUsed('hl')

replace restart {
	ld	iy, #%1
	add	iy, sp
	ld	%2, 0 (iy)
	ld	%3, 1 (iy)
} by {
	; peephole 49c used hl instead of iy.
	ld	hl, #%1
	add	hl, sp
	ld	%2, (hl)
	inc	hl
	ld	%3, (hl)
} if notUsed('iy'), notUsed('hl')

replace restart {
	ld	iy, #%1
	add	iy, sp
	ld	l, 0 (iy)
	ld	h, 1 (iy)
} by {
	; peephole 49d used hl instead of iy.
	ld	hl, #%1
	add	hl, sp
	ld	a, (hl)
	inc	hl
	ld	h, (hl)
	ld	l, a
} if notUsed('iy'), notUsed('a')

replace restart {
	ld	iy, #%1
	add	iy, sp
	ld	0 (iy), #%2
	ld	1 (iy), #%3
} by {
	; peephole 49e used hl instead of iy.
	ld	hl, #%1
	add	hl, sp
	ld	(hl), #%2
	inc	hl
	ld	(hl), #%3
} if notUsed('iy'), notUsed('hl')

replace restart {
	ld	%1,(hl)
	or	a,%1
} by {
	or	a,(hl)
	; peephole 50 used (hl) directly instead of going through %1.
} if notUsed(%1), notSame(%1 'a')

replace restart {
	ld	c,l
	ld	b,h
	inc	bc
} by {
	; peephole 51 incremented in hl instead of bc.
	inc	hl
	ld	c,l
	ld	b,h
} if notUsed('hl')

replace restart {
	ld	a,%1 (%2)
	bit	%3,a
} by {
	; peephole 52 tested bit of %1 (%2) directly instead of going through a.
	bit	%3,%1 (%2)
} if notUsed('a')

replace restart {
	ld	a,%1
	bit	%2,a
} by {
	; peephole 53 tested bit %2 of %1 directly instead of going through a.
	bit	%2,%1
} if notUsed('a'), canAssign(%1 'b')

replace restart {
	ld	a, %1
	set	%2, a
	ld	%1, a
} by {
	; peephole 54 set bit %2 of %1 directly instead of going through a.
	set	%2, %1
	ld	a, %1
} if canAssign(%1 'b')
// canAssign(%1 'b') is true, iff set b, %1 is possible.

replace restart {
	ld	a, %1 (%2)
	set	%3, a
	ld	%1 (%2), a
} by {
	; peephole 55 set bit %3 of %1 (%2) directly instead of going through a.
	set	%3, %1 (%2)
	ld	a, %1 (%2)
}

replace restart {
	ld	a, %1
	res	%2, a
	ld	%1, a
} by {
	; peephole 56 reset bit %2 of %1 directly instead of going through a.
	res	%2, %1
	ld	a, %1
} if canAssign(%1 'b')
// canAssign(%1 'b') is true, iff set b, %1 is possible.

replace restart {
	ld	a, %1 (%2)
	res	%3, a
	ld	%1 (%2), a
} by {
	; peephole 57 reset bit %3 of %1 (%2) directly instead of going through a.
	res	%3, %1 (%2)
	ld	a, %1 (%2)
}

replace restart {
	ld	c, %1 (%2)
	ld	b, %3 (%4)
	ld	l,c
	ld	h,b
} by {
	; peephole 58 stored %1 (%2) %3 (%4) into hl directly instead of going through bc.
	ld	l, %1 (%2)
	ld	h, %3 (%4)
} if notUsed('bc')

replace restart {
	ld	c, %1
	ld	b, %2
	ld	l,c
	ld	h,b
} by {
	; peephole 59 stored %2%1 into hl directly instead of going through bc.
	ld	l, %1
	ld	h, %2
} if notUsed('bc'), operandsNotRelated(%2 'l')

replace restart {
	jp	NC,%1
	jp	%2
%1:
} by {
	jp	C,%2
	; peephole 60 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 61 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 62 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 63 removed jp by using inverse jump logic
%1:
} if labelRefCountChange(%1 -1)

replace restart {
	jp	%5
} by {
	jp	%6
	; peephole 64 jumped to %6 directly instead of via %5.
} if labelIsUncondJump(), notSame(%5 %6), labelRefCountChange(%5 -1), labelRefCountChange(%6 +1)

replace restart {
	jp	%1,%5
} by {
	jp	%1,%6
	; peephole 65 jumped to %6 directly instead of via %5.
} if labelIsUncondJump(), notSame(%5 %6), labelRefCountChange(%5 -1), labelRefCountChange(%6 +1)

replace restart {
	jp	%1
%2:
%1:
} by {
   ; peephole 65a eliminated jump.
%2:
%1:
} if labelRefCountChange(%1 -1)

// A peephole that makes the code longer. Let's hope it's worth it in speed gain and further optimization potential.
replace restart {
	ld	a,#0x00
%1:
	bit	%2,a
	jp	Z,%3
} by {
	ld	a,#0x00
	jp	%3
	; peephole 65a jumped directly to %3 instead of testing a first.
%1:
	bit	%2,a
	jp	Z,%3
} if labelRefCountChange(%3 +1)

replace restart {
	ld	%1, %2
	jp	%3
	jp	%4
} by {
	ld	%1, %2
	jp	%3
	; peephole 65b removed unreachable jump to %3.
}

replace restart {
	ld	%1, %2
	jp	%3
%3:
} by {
	ld	%1, %2
%3:
	; peephole 65c removed redundant jump to %3.
} if labelRefCountChange(%3 -1)

replace restart {
	ld	%1, #0x01
	bit	0, %1
	jp	Z, %2
} by {
	ld	%1, #0x01
	; peephole 65d removed impossible jump to %2.
} if labelRefCountChange(%2 -1)
	
replace restart {
	xor	a,a
	ld	a,#0x00
} by {
	xor	a,a
	; peephole 66 removed redundant load of 0 into a.
}

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

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

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

replace restart {
	ld	%1,a
	ld	a,%1
} by {
	ld	%1,a
	; peephole 70 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 71 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	%1,a
	ld	a,%2
	or	a,%1
} by {
	ld	%1,a
	or	a,%2
	; peephole 72 removed load by reordering or arguments.
} if notVolatile(%1), canAssign('b' %2)
// canAssign('b' %2) is true, iff or a,%2 is possible.

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

replace restart {
	or	a,%1 (%2)
	or	a,a
} by {
	or	a,%1 (%2)
	; peephole 74 removed redundant or after or.
}

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

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

replace restart {
	xor	a,%1 (%2)
	or	a,a
} by {
	xor	a,%1 (%2)
	; peephole 77 removed redundant or after xor.
}

replace {
	ld	%1,%2
	ld	a,%2
} by {
	ld	a,%2
	ld	%1,a
	; peephole 78 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 79 removed redundant load from %3%1 into %4%2
} if notVolatile(%1 %2 %3 %4)

replace restart {
	push	de
	inc	sp
	ld	a,e
	push	af
	inc	sp
} by {
	push	de
	; peephole 80 pushed de
} if notUsed('a')

replace restart {
	ld	iy,%1
	add	iy,sp
	ld	sp,iy
} by {
	ld	hl,%1
	add	hl,sp
	ld	sp,hl
	; peephole 81 fixed stack using hl instead of iy.
} if notUsed('hl'), notUsed('iy')

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 82 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 83 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 84 replaced sub a,#0xFF by inc a.
	jp	Z,%1
}

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

replace restart {
	rlca
	ld	a,#0x00
	rla
} by {
	rlca
	and	a,#0x01
	; peephole 86 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 87 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 88 removed lower part of multibyte addition.
	ld	%2,a
	ld	a,%3
	add	a,%4
}

replace restart {
	ld	a, l
	add	a, #0x%1
	ld	e, a
	ld	a, h
	adc	a, #0x%2
	ld	d, a
} by {
	ld	de, #0x%2%1
	add	hl, de
	; peephole 89 used 16-bit addition.
	ld	e, l
	ld	d, h
	ld	a, h
} if notUsed('hl')

replace restart {
	ld	a, l
	add	a, #0x%1
	ld	c, a
	ld	a, h
	adc	a, #0x%2
	ld	b, a
} by {
	ld	bc, #0x%2%1
	add	hl,bc
	; peephole 90 used 16-bit addition.
	ld	c, l
	ld	b, h
	ld	a, h
} if notUsed('hl')

replace restart {
	ld	%1,a
	ld	a,%2
	add	a,%1
} by {
	; peephole 91 removed loads by exploiting commutativity of addition.
	add	a,%2
} if notVolatile(%1), notUsed(%1), canAssign('b' %2)
// canAssign('b' %2) is true, iff add a,%2 is possible.

replace restart {
	ld	%1 (ix),a
	ld	a,#%2
	add	a,%1 (ix)
} by {
	ld	%1 (ix),a
	; peephole 92 removed loads by exploiting commutativity of addition.
	add	a,#%2
}
// Don't need to check for volatile, since ix is used to access the stack.

replace restart {
	ld	l,%1 (ix)
	ld	h,%2 (ix)
	ld	a,(hl)
	inc	a
	ld	l,%1 (ix)
	ld	h,%2 (ix)
	ld	(hl),a
} by {
	ld	l,%1 (ix)
	ld	h,%2 (ix)
	inc	(hl)
	; peephole 93 incremented in (hl) instead of going through a.
} if notUsed('a')

replace restart {
	ld	%1, %2 (%3)
	inc	%1
	ld	%2 (%3), %1
} by {
	inc	%2 (%3)
	ld	%1, %2 (%3)
	; peephole 93a incremented in %2 (%3) instead of going through %1.
} if notSame(%3 'sp')

replace restart {
	ld	%1,a
	ld	a,%2
	add	a,%1
} by {
	ld	%1, a
	; peephole 94 removed load by exploiting commutativity of addition.
	add	a,%2
} if notSame(%2 '(bc)' '(de)'), canAssign('b' %2)
// canAssign('b' %2) is true, iff add a,%2 is possible.

replace restart {
	ld	c,l
	ld	b,h
	ld	hl,#%1
	add	hl,bc
} by {
	; peephole 95 removed loads by exploiting commutativity of addition.
	ld	bc,#%1
	add	hl,bc
} if notUsed('bc')

replace restart {
	ld	hl,#%1
	add	hl,%2
	ld	bc,#%4
	add	hl,bc
} by {
	; peephole 96 removed loads by exploiting commutativity of addition.
	ld	hl,#%1 + %4
	add	hl,%2
} if notUsed('bc')

replace restart {
	ld	c,e
	ld	b,d
	ld	hl,#%1
	add	hl,bc
} by {
	; peephole 97 removed loads by exploiting commutativity of addition.
	ld	hl,#%1
	add	hl,de
} if notUsed('bc')

replace restart {
	or	a,%1
	jp	NZ,%2
	ld	%3,#0x00
} by {
	or	a,%1
	jp	NZ,%2
	ld	%3,a
	; peephole 98 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 99 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 100 replaced constant #0x00 by a (which has just been tested to be #0x00).
}

replace restart {
	inc	a
	jp	NZ,%1
	ld	%2,#0x00
} by {
	inc	a
	jp	NZ,%1
	ld	%2,a
	; peephole 101 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 102 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 103 shortened or using a (which has just been tested to be #0x00).
} if canAssign('b' %3)
// canAssign('b' %2) is true, iff or a,%2 is possible.

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 104 shortened or using a (which has just been tested to be #0x00).
} if canAssign('b' %3)
// canAssign('b' %2) is true, iff or a,%2 is possible.

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 105 replaced constant #0x00 by a (which has just been tested to be #0x00).
}

replace restart {
	ld	(hl),#0x00
	inc	hl
	ld	(hl),#0x00
} by {
	xor	a, a
	; peephole 106 cached zero in a.
	ld	(hl), a
	inc	hl
	ld	(hl), a
} if notUsed('a')

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

replace restart {
	inc	hl
	ld	%1,#%2
	add	hl,%1
} by {
	ld	%1,#%2+1
	add	hl,%1
	; peephole 108 moved increment of hl to constant.
} if notUsed(%1)

replace restart {
	dec	hl
	ld	%1,#%2
	add	hl,%1
} by {
	ld	%1,#%2-1
	add	hl,%1
	; peephole 109 moved decrement of hl to constant.
} if notUsed(%1)

replace restart {
	inc	hl
	inc	hl
	inc	hl
	ld	hl, (hl)
} by {
	; peephole 109a moved increment of hl to offset.
	ld	hl, 3 (hl)
}

replace restart {
	inc	hl
	inc	hl
	ld	hl, (hl)
} by {
	; peephole 109b moved increment of hl to offset.
	ld	hl, 2 (hl)
}

replace restart {
	inc	hl
	ld	hl, (hl)
} by {
	; peephole 109c moved increment of hl to offset.
	ld	hl, 1 (hl)
}

replace restart {
	inc	iy
	ld	%1, %2 (iy)
} by {
	ld	%1, %2+1 (iy)
	; peephole 110 moved increment of iy to offset.
} if notUsed('iy')

replace restart {
	push	hl
	pop	iy
	pop	hl
	inc	iy
} by {
	inc	hl
	push	hl
	pop	iy
	pop	hl
	; peephole 111 incremented in hl instead of iy.
}

replace restart {
	push	hl
	pop	iy
	inc	iy
} by {
	inc	hl
	push	hl
	pop	iy
	; peephole 111a incremented in hl instead of iy.
} if notUsed('hl')

replace restart {
	ld	hl,%1
	add	hl,%2
	push	hl
	pop	iy
} by {
	ld	iy,%1
	add	iy,%2
	; peephole 111b added in iy instead of hl.
} if notUsed('hl'), notSame(%2 'hl')

replace restart {
	pop	af
	ld	sp,%1
} by {
	; peephole 112 removed redundant pop af.
	ld	sp,%1
} if notUsed('a')

replace restart {
	inc	sp
	ld	sp,%1
} by {
	; peephole 113 removed redundant inc sp.
	ld	sp,%1
} if notUsed('a')

replace restart {
	call	%1
	ret
} by {
	jp	%1
	; peephole 114 replaced call at end of function by jump (tail call optimization).
}

// Callee saves ix.
replace restart {
	call	%1
	pop	ix
	ret
} by {
	pop	ix
	jp	%1
	; peephole115 replaced call at end of function by jump moving call beyond pop ix (tail call optimization).
}

replace restart {
	ld	%1,#%2
	ld	%3,%4
	ld	%1,#%2
} by {
	ld	%1,#%2
	ld	%3,%4
	; peephole 116 removed load of #%2 into %1 since it's still there.
} if notVolatile(%1), operandsNotRelated(%3 %1)

replace restart {
	ld	hl,#%1
	ld	de,#%1
} by {
	; peephole 117 used #%1 from hl for load into de.
	ld	hl,#%1
	ld	e,l
	ld	d,h
}

replace restart {
	ld	%1 (ix),l
	ld	%2 (ix),h
	ld	%3,%1 (ix)
	ld	%4,%2 (ix)
} by {	
	ld	%1 (ix),l
	ld	%2 (ix),h
	; peephole 118 used hl instead of %2 (ix), %1 (ix) to load %4%3.
	ld	%3,l
	ld	%4,h
} if operandsNotRelated('h' %3)
// Don't check for volatile since ix points to the stack.

replace restart {
	ld	%1, a
	ld	a, %2 (%3)
	adc	a, #%4
	ld	%6, %1
} by {
	ld	%6, a
	ld	a, %2 (%3)
	adc	a, #%4
	; peephole 119 loaded %6 from a directly instead of going through %1.
} if notUsed(%1)

replace restart {
	ld	%1, a
	ld	a, %2 (%3)
	adc	a, #%4
	ld	%5, a
	ld	%6, %1
} by {
	ld	%6, a
	ld	a, %2 (%3)
	adc	a, #%4
	ld	%5, a
	; peephole 120 loaded %6 from a directly instead of going through %1.
} if notUsed(%1), notSame(%5 %1), notSame(%5 '(hl)' '(de)' '(bc)'), notSame(%5 %6), notSame(%6 '(hl)' '(de)' '(bc)'), notSame(%5 'a'), notSame(%6 'a')

replace restart {
	ld	%1, a
	ld	a, #%2
	adc	a, #%3
	ld	%5, a
	ld	%6, %1
} by {
	ld	%6, a
	ld	a, #%2
	adc	a, #%3
	ld	%5, a
	; peephole 121 loaded %6 from a directly instead of going through %1.
} if notUsed(%1), notSame(%5 %1), notSame(%5 %6 '(hl)' '(de)' '(bc)'), notSame(%6 'a')

replace restart {
	ld	hl, #%1
	add	hl, %2
	ex	de, hl
	ld	hl, #%3
	add	hl, de
} by {
	ld	hl, #%1+%3
	add	hl, %2
	; peephole 122 removed addition and loads exploiting commutativity of addition.
} if notUsed('de')

replace restart {
	ld	%1,l
	ld	%2,h
	ex	de,hl
	ld	(hl),%1
	inc	hl
	ld	(hl),%2
} by {
	ld	%1,l
	ex	de,hl
	; peephole 122a used de instead of going through %1%2.
	ld	(hl),e
	inc	hl
	ld	(hl),d
} if notUsed(%2), notSame(%1 'l' 'h' 'e' 'd'), notSame(%2 'l' 'h' 'e' 'd')
	
replace restart {
	ld	e, l
	ld	d, h
	ld	hl, #0x0001
	add	hl, de
} by {
	ld	e, l
	ld	d, h
	inc	hl
	; peephole 123 replaced addition by increment.
}

replace restart {	
	ld      sp,hl
	ld      hl,#0x0002
	add     hl,sp
} by {
	ld	sp, hl
	inc	hl
	inc	hl
	; peephole 124 replaced addition by increment.
}

replace restart {
	ex	de, hl
	ld	hl, #%1
	add	hl, de
} by {
	; peephole 125 removed ex exploiting commutativity of addition.
	ld	de, #%1
	add	hl, de
} if notUsed('de')

replace restart {
	ex	de, hl
	push	bc
	ex	de, hl
} by {
	push	bc
	; peephole 126 canceled subsequent ex de, hl.
}

replace restart {
	ld	hl, #%1
	add	hl, %2
	ex	de, hl
	inc	de
} by {
	ld	hl, #%1+1
	; peephole 127 moved increment to constant.
	add	hl, %2
	ex	de, hl
} if notUsed('hl')

replace restart {
	ld	a,#0x01
	jp	%1
%2:
	xor	a,a
%1:
	sub	a,#0x01
	ld	a,#0x00
	rla
} by {
	xor	a,a
	jp	%1
%2:
	ld	a,#0x01
%1:
	; peephole 128 removed negation.
} if labelRefCount(%1 1)

replace restart {
	and	a,#0x01
	sub	a,#0x01
	ld	a,#0x00
	rla
} by {
	and	a,#0x01
	xor	a,#0x01
	; peephole 129 used xor for negation.
}

replace restart {
	or	a,a
	sub	a,#%1
} by {
	; peephole 130 removed redundant or.
	sub	a,#%1
}

replace restart {
	ld	a,#0x00
	rla
	sub	a,#0x01
	ld	a,#0x00
	rla
} by {
	ld	a,#0x00
	ccf
	; peephole 131 moved negation from bit 0 to carry flag.
	rla
}

replace restart {
	ld	a, #<(%1)
	add	a, l
	ld	l, a
	ld	a, #>(%1)
	adc	a, h
	ld	h, a
	push	bc
} by {
	push	bc
	ld	bc, #%1
	add	hl, bc
	; peephole 132 used 16 bit addition by moving push bc
	ld	a, h
}

replace restart {
	pop	af
	push	hl
} by {
	; peephole 133 used ex to move hl onto the stack.
	ld	0(sp),hl
} if notUsed('a'), notUsed('hl')

replace restart {
	pop	af
	ld	hl, #%1
	push	hl
} by {
	ld	hl, #%1
	; peephole 134 used 0(sp) to move hl onto the stack.
	ld	0(sp),hl
} if notUsed('a'), notUsed('hl')

replace restart {
	pop	af
	inc	sp
	ld	hl,#%1
	push	hl
} by {
	inc	sp
	ld	hl,#%1
	; peephole 135 used 0(sp) to move #%1 onto the stack.
	ld	0(sp),hl
} if notUsed('a'), notUsed('hl')

replace restart {
	pop	af
	ld	a,#%1
	push	af
	inc	sp
} by {
	ld	h,#%1
	ld	0(sp),hl
	; peephole 136 used 0(sp) to move #%1 onto the stack.
	inc	sp
} if notUsed('a'), notUsed('hl')

replace restart {
	ld	%1,#%2
	ld	%3 (%1),a
%4:
	ld	%1,%5
} by {
	ld	(#%2 + %3),a
	; peephole 137 directly used #%2 instead of going through %1 using indirect addressing.
%4:
	ld	%1,%5
}

replace restart {
	pop	af
	ld	%1,#%2
	ld	%3 (%1),%4
	ld	%1,#%5
} by {
	ld	a,%4
	ld	(#%2 + %3),a
	; peephole 138 used #%2 directly instead of going through %1 using indirect addressing.
	pop	af
	ld	%1,#%5
} if notSame(%3 'a')

replace restart {
	ld	%1,a
	bit	%2,%1
} by {
	bit	%2,a
	; peephole 139 tested bit %2 of a directly instead of going through %1.
} if notUsed(%1)

replace restart {
	sbc	a,%1
	bit	7,a
	jp	Z,%2
} by {
	sbc	a,%1
	jp	P,%2
	; peephole 140 used sign flag instead of testing bit 7.
}

replace restart {
	sbc	a,%1
	bit	7,a
	jp	NZ,%2
} by {
	sbc	a,%1
	jp	M,%2
	; peephole 141 used sign flag instead of testing bit 7.
}

replace restart {
	ld	%1,a
	or	a,a
	jp	%3,%4
	ld	a,%1
} by {
	ld	%1,a
	or	a,a
	jp	%3,%4
	; peephole 142 used value still in a instead of reloading from %1.
}

replace {
	jp	%5
	ret
} by {
	jp	%5
	; peephole 143 removed unused ret.
}

replace {
	jp	%5
	ld	sp,ix
	pop	ix
	ret
} by {
	jp	%5
	; peephole 144 removed unused ret.
}

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

// These ex-generating rules should be among the last ones since ex counts as a read from both hl and de for notUsed().
barrier

replace restart {
	ld	d,h
	ld	e,l
} by {
	; peephole 146 used ex to load hl into de.
	ex	de,hl
} if notUsed('hl')

replace restart {
	ld	e,l
	ld	d,h
} by {
	; peephole 147 used ex to load hl into de.
	ex	de,hl
} if notUsed('hl')

replace restart {
	ld	l,e
	ld	h,d
} by {
	; peephole 148 used ex to load de into hl.
	ex	de,hl
} if notUsed('de')

barrier

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

// Ensure that all rules above see only jp, not jr.
barrier

replace {
	add	hl,de
	pop	de
	jp	(hl)
%1:
	jp	%5
	jp	%6
	jp	%7
%2:
} by {
	; peephole 150-3 removed addition using short jumps in jump-table.
	pop	de
	jp	(hl)
%1:
	jr	%5
	jr	%6
	jr	%7
%2:
} if labelJTInRange

replace {
	add	hl,de
	jp	(hl)
%1:
	jp	%5
	jp	%6
	jp	%7
%2:
} by {
	; peephole 150-3' removed addition using short jumps in jump-table.
	jp	(hl)
%1:
	jr	%5
	jr	%6
	jr	%7
%2:
} if labelJTInRange

replace {
	add	hl,de
	pop	de
	jp	(hl)
%1:
	jp	%5
	jp	%6
	jp	%7
	jp	%8
%2:
} by {
	; peephole 150-4 removed addition using short jumps in jump-table.
	pop	de
	jp	(hl)
%1:
	jr	%5
	jr	%6
	jr	%7
	jr	%8
%2:
} if labelJTInRange

replace {
	add	hl,de
	jp	(hl)
%1:
	jp	%5
	jp	%6
	jp	%7
	jp	%8
%2:
} by {
	; peephole 150-4' removed addition using short jumps in jump-table.
	jp	(hl)
%1:
	jr	%5
	jr	%6
	jr	%7
	jr	%8
%2:
} if labelJTInRange

replace {
	add	hl,de
	pop	de
	jp	(hl)
%1:
	jp	%5
	jp	%6
	jp	%7
	jp	%8
	jp	%9
%2:
} by {
	; peephole 150-5 removed addition using short jumps in jump-table.
	pop	de
	jp	(hl)
%1:
	jr	%5
	jr	%6
	jr	%7
	jr	%8
	jr	%9
%2:
} if labelJTInRange

replace {
	add	hl,de
	jp	(hl)
%1:
	jp	%5
	jp	%6
	jp	%7
	jp	%8
	jp	%9
%2:
} by {
	; peephole 150-5' removed addition using short jumps in jump-table.
	jp	(hl)
%1:
	jr	%5
	jr	%6
	jr	%7
	jr	%8
	jr	%9
%2:
} if labelJTInRange

replace {
	add	hl,de
	pop	de
	jp	(hl)
%1:
	jp	%5
	jp	%6
	jp	%7
	jp	%8
	jp	%9
	jp	%10
%2:
} by {
	; peephole 150-6 removed addition using short jumps in jump-table.
	pop	de
	jp	(hl)
%1:
	jr	%5
	jr	%6
	jr	%7
	jr	%8
	jr	%9
	jr	%10
%2:
} if labelJTInRange

replace {
	add	hl,de
	jp	(hl)
%1:
	jp	%5
	jp	%6
	jp	%7
	jp	%8
	jp	%9
	jp	%10
%2:
} by {
	; peephole 150-6' removed addition using short jumps in jump-table.
	jp	(hl)
%1:
	jr	%5
	jr	%6
	jr	%7
	jr	%8
	jr	%9
	jr	%10
%2:
} if labelJTInRange

replace {
	add	hl,de
	pop	de
	jp	(hl)
%1:
	jp	%5
	jp	%6
	jp	%7
	jp	%8
	jp	%9
	jp	%10
	jp	%11
%2:
} by {
	; peephole 150-7 removed addition using short jumps in jump-table.
	pop	de
	jp	(hl)
%1:
	jr	%5
	jr	%6
	jr	%7
	jr	%8
	jr	%9
	jr	%10
	jr	%11
%2:
} if labelJTInRange

replace {
	add	hl,de
	jp	(hl)
%1:
	jp	%5
	jp	%6
	jp	%7
	jp	%8
	jp	%9
	jp	%10
	jp	%11
%2:
} by {
	; peephole 150-7' removed addition using short jumps in jump-table.
	jp	(hl)
%1:
	jr	%5
	jr	%6
	jr	%7
	jr	%8
	jr	%9
	jr	%10
	jr	%11
%2:
} if labelJTInRange

barrier

// Do all jump optimizations before replacing by ret.

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

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

replace {
	jp	%5
} by {
	jr	%5
	; peephole 153 changed absolute to relative unconditional jump.
} if labelInRange()

replace {
	jp	Z,%5
} by {
	jr	Z,%5
	; peephole 154 changed absolute to relative conditional jump.
} if labelInRange()

replace {
	jp	NZ,%5
} by {
	jr	NZ,%5
	; peephole 155 changed absolute to relative conditional jump.
} if labelInRange()

replace {
	jp	C,%5
} by {
	jr	C,%5
	; peephole 156 changed absolute to relative conditional jump.
} if labelInRange()

replace {
	jp	NC,%5
} by {
	jr	NC,%5
	; peephole 157 changed absolute to relative conditional jump.
} if labelInRange()

